@islands/hydration
Version:
Hydration utilities for îles
50 lines (49 loc) • 2.06 kB
JavaScript
//#region hydration.ts
const findById = (id) => document.getElementById(id) || console.error(`Missing #${id}, could not mount island.`);
function hydrateNow(framework, component, id, props, slots) {
const el = findById(id);
if (el) {
framework(component, id, el, props, slots);
el.setAttribute("hydrated", "");
}
}
async function resolveAndHydrate(frameworkFn, componentFn, id, props, slots) {
const [framework, component] = await Promise.all([frameworkFn(), componentFn()]);
hydrateNow(framework, component, id, props, slots);
}
function hydrateWhenIdle(framework, component, id, props, slots) {
const whenIdle = window.requestIdleCallback || setTimeout;
const cancelIdle = window.cancelIdleCallback || clearTimeout;
const idleId = whenIdle(() => resolveAndHydrate(framework, component, id, props, slots));
if (import.meta.env.DISPOSE_ISLANDS) onDispose(id, () => cancelIdle(idleId));
}
function hydrateOnMediaQuery(framework, component, id, props, slots) {
const mediaQuery = matchMedia(props._mediaQuery);
delete props._mediaQuery;
const onChange = (fn = null) => mediaQuery.onchange = fn;
const hydrate = () => {
onChange();
resolveAndHydrate(framework, component, id, props, slots);
};
mediaQuery.matches ? hydrate() : onChange(hydrate);
if (import.meta.env.DISPOSE_ISLANDS) onDispose(id, onChange);
}
function hydrateWhenVisible(framework, component, id, props, slots) {
const el = findById(id);
if (el) {
if (import.meta.env.DEV) el.style.display = "initial";
const observer = new IntersectionObserver(([{ isIntersecting }]) => {
if (isIntersecting) {
stopObserver();
if (import.meta.env.DEV) el.style.display = "";
resolveAndHydrate(framework, component, id, props, slots);
}
});
const stopObserver = () => observer.disconnect();
observer.observe(el);
if (import.meta.env.DISPOSE_ISLANDS) onDispose(id, stopObserver);
}
}
const onDispose = (id, fn) => window.__ILE_DISPOSE__?.set(id, fn);
//#endregion
export { hydrateNow, hydrateOnMediaQuery, hydrateWhenIdle, hydrateWhenVisible, onDispose };