UNPKG

woby

Version:

A high-performance framework with fine-grained observable/signal-based reactivity for building rich applications.

81 lines (80 loc) 2.85 kB
import { m as setChild, F as FragmentUtils, E as get, t as createHTMLNode, G as useRenderEffect, h as assign, H as context, I as SYMBOL_SUSPENSE_COLLECTOR, J as effect } from "./setters-Ddu0s6oK.js"; import { r as root } from "./root-B8Ruf358.js"; import { b as boolean, r as resolve, o as observable, m as memo } from "./merge_style-CyMhMoCQ.js"; const render = (child, parent) => { if (!parent || !(parent instanceof HTMLElement)) throw new Error("Invalid parent node"); parent.textContent = ""; return root((stack, dispose) => { setChild(parent, child, FragmentUtils.make(), stack); return () => { dispose(stack); parent.textContent = ""; }; }); }; const Portal = ({ when = true, mount, wrapper, children }) => { const portal = get(wrapper) || createHTMLNode("div"); if (!(portal instanceof HTMLElement)) throw new Error("Invalid wrapper node"); const condition = boolean(when); const stack = new Error(); useRenderEffect(() => { if (!get(condition)) return; const parent = get(mount) || document.body; if (!(parent instanceof Element)) throw new Error("Invalid mount node"); parent.insertBefore(portal, null); return () => { parent.removeChild(portal); }; }, stack); useRenderEffect(() => { if (!get(condition)) return; return render(children, portal); }, stack); return assign(() => get(condition) || children, { metadata: { portal } }); }; const SuspenseCollector = { create: () => { const parent = SuspenseCollector.get(); const suspenses = observable([]); const active = memo(() => suspenses().some((suspense) => suspense.active())); const register = (suspense) => { parent == null ? void 0 : parent.register(suspense); suspenses((prev) => [...prev, suspense]); }; const unregister = (suspense) => { parent == null ? void 0 : parent.unregister(suspense); suspenses((prev) => prev.filter((other) => other !== suspense)); }; const data = { suspenses, active, register, unregister }; return data; }, get: () => { return context(SYMBOL_SUSPENSE_COLLECTOR); }, wrap: (fn) => { const data = SuspenseCollector.create(); return context({ [SYMBOL_SUSPENSE_COLLECTOR]: data }, () => { return resolve(() => fn(data)); }); } }; const renderToString = (child) => { return new Promise((resolve2) => { root((stack, dispose) => { get(SuspenseCollector.wrap((suspenses) => { const { portal } = Portal({ children: child }).metadata; effect((stack2) => { if (suspenses.active()) return; resolve2(portal.innerHTML); dispose(stack2); }, { suspense: false, stack }); })); }); }); }; export { Portal as P, renderToString as a, render as r }; //# sourceMappingURL=render_to_string-DPtjoKMd.js.map