@pyreon/runtime-dom 0.11.1 → 0.11.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/analysis/index.js.html +1 -1
- package/lib/index.js +13 -12
- package/lib/index.js.map +1 -1
- package/lib/types/index.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/delegate.ts +2 -2
- package/src/hydrate.ts +8 -4
- package/src/mount.ts +6 -5
- package/src/props.ts +7 -5
- package/src/tests/show-context.test.ts +177 -0
|
@@ -5386,7 +5386,7 @@ var drawChart = (function (exports) {
|
|
|
5386
5386
|
</script>
|
|
5387
5387
|
<script>
|
|
5388
5388
|
/*<!--*/
|
|
5389
|
-
const data = {"version":2,"tree":{"name":"root","children":[{"name":"index.js","children":[{"name":"src","children":[{"uid":"
|
|
5389
|
+
const data = {"version":2,"tree":{"name":"root","children":[{"name":"index.js","children":[{"name":"src","children":[{"uid":"be9e8739-1","name":"delegate.ts"},{"uid":"be9e8739-3","name":"hydration-debug.ts"},{"uid":"be9e8739-5","name":"devtools.ts"},{"uid":"be9e8739-7","name":"nodes.ts"},{"uid":"be9e8739-9","name":"props.ts"},{"uid":"be9e8739-11","name":"mount.ts"},{"uid":"be9e8739-13","name":"hydrate.ts"},{"uid":"be9e8739-15","name":"keep-alive.ts"},{"uid":"be9e8739-17","name":"template.ts"},{"uid":"be9e8739-19","name":"transition.ts"},{"uid":"be9e8739-21","name":"transition-group.ts"},{"uid":"be9e8739-23","name":"index.ts"}]}]}],"isRoot":true},"nodeParts":{"be9e8739-1":{"renderedLength":1990,"gzipLength":976,"brotliLength":0,"metaUid":"be9e8739-0"},"be9e8739-3":{"renderedLength":704,"gzipLength":397,"brotliLength":0,"metaUid":"be9e8739-2"},"be9e8739-5":{"renderedLength":6803,"gzipLength":2095,"brotliLength":0,"metaUid":"be9e8739-4"},"be9e8739-7":{"renderedLength":16273,"gzipLength":4364,"brotliLength":0,"metaUid":"be9e8739-6"},"be9e8739-9":{"renderedLength":6157,"gzipLength":2362,"brotliLength":0,"metaUid":"be9e8739-8"},"be9e8739-11":{"renderedLength":9397,"gzipLength":2862,"brotliLength":0,"metaUid":"be9e8739-10"},"be9e8739-13":{"renderedLength":7694,"gzipLength":2333,"brotliLength":0,"metaUid":"be9e8739-12"},"be9e8739-15":{"renderedLength":1447,"gzipLength":692,"brotliLength":0,"metaUid":"be9e8739-14"},"be9e8739-17":{"renderedLength":4512,"gzipLength":1811,"brotliLength":0,"metaUid":"be9e8739-16"},"be9e8739-19":{"renderedLength":4007,"gzipLength":1316,"brotliLength":0,"metaUid":"be9e8739-18"},"be9e8739-21":{"renderedLength":6362,"gzipLength":1937,"brotliLength":0,"metaUid":"be9e8739-20"},"be9e8739-23":{"renderedLength":811,"gzipLength":491,"brotliLength":0,"metaUid":"be9e8739-22"}},"nodeMetas":{"be9e8739-0":{"id":"/src/delegate.ts","moduleParts":{"index.js":"be9e8739-1"},"imported":[{"uid":"be9e8739-24"}],"importedBy":[{"uid":"be9e8739-22"},{"uid":"be9e8739-12"},{"uid":"be9e8739-8"}]},"be9e8739-2":{"id":"/src/hydration-debug.ts","moduleParts":{"index.js":"be9e8739-3"},"imported":[],"importedBy":[{"uid":"be9e8739-22"},{"uid":"be9e8739-12"}]},"be9e8739-4":{"id":"/src/devtools.ts","moduleParts":{"index.js":"be9e8739-5"},"imported":[],"importedBy":[{"uid":"be9e8739-22"},{"uid":"be9e8739-10"}]},"be9e8739-6":{"id":"/src/nodes.ts","moduleParts":{"index.js":"be9e8739-7"},"imported":[{"uid":"be9e8739-24"}],"importedBy":[{"uid":"be9e8739-12"},{"uid":"be9e8739-10"}]},"be9e8739-8":{"id":"/src/props.ts","moduleParts":{"index.js":"be9e8739-9"},"imported":[{"uid":"be9e8739-25"},{"uid":"be9e8739-24"},{"uid":"be9e8739-0"}],"importedBy":[{"uid":"be9e8739-22"},{"uid":"be9e8739-12"},{"uid":"be9e8739-10"}]},"be9e8739-10":{"id":"/src/mount.ts","moduleParts":{"index.js":"be9e8739-11"},"imported":[{"uid":"be9e8739-25"},{"uid":"be9e8739-24"},{"uid":"be9e8739-4"},{"uid":"be9e8739-6"},{"uid":"be9e8739-8"}],"importedBy":[{"uid":"be9e8739-22"},{"uid":"be9e8739-12"},{"uid":"be9e8739-14"},{"uid":"be9e8739-20"}]},"be9e8739-12":{"id":"/src/hydrate.ts","moduleParts":{"index.js":"be9e8739-13"},"imported":[{"uid":"be9e8739-25"},{"uid":"be9e8739-24"},{"uid":"be9e8739-0"},{"uid":"be9e8739-2"},{"uid":"be9e8739-10"},{"uid":"be9e8739-6"},{"uid":"be9e8739-8"}],"importedBy":[{"uid":"be9e8739-22"}]},"be9e8739-14":{"id":"/src/keep-alive.ts","moduleParts":{"index.js":"be9e8739-15"},"imported":[{"uid":"be9e8739-25"},{"uid":"be9e8739-24"},{"uid":"be9e8739-10"}],"importedBy":[{"uid":"be9e8739-22"}]},"be9e8739-16":{"id":"/src/template.ts","moduleParts":{"index.js":"be9e8739-17"},"imported":[{"uid":"be9e8739-24"}],"importedBy":[{"uid":"be9e8739-22"}]},"be9e8739-18":{"id":"/src/transition.ts","moduleParts":{"index.js":"be9e8739-19"},"imported":[{"uid":"be9e8739-25"},{"uid":"be9e8739-24"}],"importedBy":[{"uid":"be9e8739-22"}]},"be9e8739-20":{"id":"/src/transition-group.ts","moduleParts":{"index.js":"be9e8739-21"},"imported":[{"uid":"be9e8739-25"},{"uid":"be9e8739-24"},{"uid":"be9e8739-10"}],"importedBy":[{"uid":"be9e8739-22"}]},"be9e8739-22":{"id":"/src/index.ts","moduleParts":{"index.js":"be9e8739-23"},"imported":[{"uid":"be9e8739-0"},{"uid":"be9e8739-12"},{"uid":"be9e8739-2"},{"uid":"be9e8739-14"},{"uid":"be9e8739-10"},{"uid":"be9e8739-8"},{"uid":"be9e8739-16"},{"uid":"be9e8739-18"},{"uid":"be9e8739-20"},{"uid":"be9e8739-4"}],"importedBy":[],"isEntry":true},"be9e8739-24":{"id":"@pyreon/reactivity","moduleParts":{},"imported":[],"importedBy":[{"uid":"be9e8739-0"},{"uid":"be9e8739-12"},{"uid":"be9e8739-14"},{"uid":"be9e8739-10"},{"uid":"be9e8739-8"},{"uid":"be9e8739-16"},{"uid":"be9e8739-18"},{"uid":"be9e8739-20"},{"uid":"be9e8739-6"}]},"be9e8739-25":{"id":"@pyreon/core","moduleParts":{},"imported":[],"importedBy":[{"uid":"be9e8739-12"},{"uid":"be9e8739-14"},{"uid":"be9e8739-10"},{"uid":"be9e8739-8"},{"uid":"be9e8739-18"},{"uid":"be9e8739-20"}]}},"env":{"rollup":"4.23.0"},"options":{"gzip":true,"brotli":false,"sourcemap":false}};
|
|
5390
5390
|
|
|
5391
5391
|
const run = () => {
|
|
5392
5392
|
const width = window.innerWidth;
|
package/lib/index.js
CHANGED
|
@@ -65,7 +65,7 @@ function setupDelegation(container) {
|
|
|
65
65
|
let el = e.target;
|
|
66
66
|
while (el && el !== container) {
|
|
67
67
|
const handler = el[prop];
|
|
68
|
-
if (handler) {
|
|
68
|
+
if (typeof handler === "function") {
|
|
69
69
|
batch(() => handler(e));
|
|
70
70
|
if (e.cancelBubble) break;
|
|
71
71
|
}
|
|
@@ -973,8 +973,8 @@ function applyProps(el, props) {
|
|
|
973
973
|
* Bind an event handler (onClick → "click") with batching + delegation support.
|
|
974
974
|
*/
|
|
975
975
|
function applyEventProp(el, key, value) {
|
|
976
|
-
if (
|
|
977
|
-
console.warn(`[Pyreon] Event handler "${key}" received a non-function value (${typeof value}). Expected a function. Did you mean ${key}={() => ...}?`);
|
|
976
|
+
if (typeof value !== "function") {
|
|
977
|
+
if (__DEV__$3) console.warn(`[Pyreon] Event handler "${key}" received a non-function value (${typeof value}). Expected a function. Did you mean ${key}={() => ...}?`);
|
|
978
978
|
return null;
|
|
979
979
|
}
|
|
980
980
|
const eventName = key[2]?.toLowerCase() + key.slice(3);
|
|
@@ -1127,7 +1127,7 @@ function mountChild(child, parent, anchor = null) {
|
|
|
1127
1127
|
};
|
|
1128
1128
|
}
|
|
1129
1129
|
const vnode = child;
|
|
1130
|
-
if (vnode.type === Fragment) return mountChildren(vnode.children, parent, anchor);
|
|
1130
|
+
if (vnode.type === Fragment) return mountChildren(vnode.children ?? [], parent, anchor);
|
|
1131
1131
|
if (vnode.type === ForSymbol) {
|
|
1132
1132
|
const { each, by, children } = vnode.props;
|
|
1133
1133
|
const prevDepth = _elementDepth;
|
|
@@ -1170,11 +1170,11 @@ const VOID_ELEMENTS = new Set([
|
|
|
1170
1170
|
]);
|
|
1171
1171
|
function mountElement(vnode, parent, anchor) {
|
|
1172
1172
|
const el = document.createElement(vnode.type);
|
|
1173
|
-
if (__DEV__$2 && vnode.children
|
|
1173
|
+
if (__DEV__$2 && (vnode.children?.length ?? 0) > 0 && VOID_ELEMENTS.has(vnode.type)) console.warn(`[Pyreon] <${vnode.type}> is a void element and cannot have children. Children passed to void elements will be ignored by the browser.`);
|
|
1174
1174
|
const props = vnode.props;
|
|
1175
1175
|
const propCleanup = props !== EMPTY_PROPS ? applyProps(el, props) : null;
|
|
1176
1176
|
_elementDepth++;
|
|
1177
|
-
const childCleanup = mountChildren(vnode.children, el, null);
|
|
1177
|
+
const childCleanup = mountChildren(vnode.children ?? [], el, null);
|
|
1178
1178
|
_elementDepth--;
|
|
1179
1179
|
parent.insertBefore(el, anchor);
|
|
1180
1180
|
const ref = props.ref;
|
|
@@ -1217,9 +1217,10 @@ function mountComponent(vnode, parent, anchor) {
|
|
|
1217
1217
|
const compId = `${componentName}-${Math.random().toString(36).slice(2, 9)}`;
|
|
1218
1218
|
const parentId = _mountingStack[_mountingStack.length - 1] ?? null;
|
|
1219
1219
|
_mountingStack.push(compId);
|
|
1220
|
-
const
|
|
1220
|
+
const children = vnode.children ?? [];
|
|
1221
|
+
const mergedProps = children.length > 0 && vnode.props.children === void 0 ? {
|
|
1221
1222
|
...vnode.props,
|
|
1222
|
-
children:
|
|
1223
|
+
children: children.length === 1 ? children[0] : children
|
|
1223
1224
|
} : vnode.props;
|
|
1224
1225
|
try {
|
|
1225
1226
|
const result = runWithHooks(vnode.type, mergedProps);
|
|
@@ -1401,7 +1402,7 @@ function hydrateReactiveText(child, domNode, parent, anchor, path) {
|
|
|
1401
1402
|
}
|
|
1402
1403
|
/** Hydrate a VNode (fragment, For, Portal, component, element). */
|
|
1403
1404
|
function hydrateVNode(vnode, domNode, parent, anchor, path) {
|
|
1404
|
-
if (vnode.type === Fragment) return hydrateChildren(vnode.children, domNode, parent, anchor, path);
|
|
1405
|
+
if (vnode.type === Fragment) return hydrateChildren(vnode.children ?? [], domNode, parent, anchor, path);
|
|
1405
1406
|
if (vnode.type === ForSymbol) return [mountChild(vnode, parent, insertMarker(parent, domNode, "pyreon-for")), null];
|
|
1406
1407
|
if (vnode.type === PortalSymbol) return [mountChild(vnode, parent, anchor), domNode];
|
|
1407
1408
|
if (typeof vnode.type === "function") return hydrateComponent(vnode, domNode, parent, anchor, path);
|
|
@@ -1438,7 +1439,7 @@ function hydrateElement(vnode, domNode, parent, anchor, path = "root") {
|
|
|
1438
1439
|
const propCleanup = applyProps(el, vnode.props);
|
|
1439
1440
|
if (propCleanup) cleanups.push(propCleanup);
|
|
1440
1441
|
const firstChild = firstReal(el.firstChild);
|
|
1441
|
-
const [childCleanup] = hydrateChildren(vnode.children, firstChild, el, null, elPath);
|
|
1442
|
+
const [childCleanup] = hydrateChildren(vnode.children ?? [], firstChild, el, null, elPath);
|
|
1442
1443
|
cleanups.push(childCleanup);
|
|
1443
1444
|
const ref = vnode.props.ref;
|
|
1444
1445
|
if (ref) if (typeof ref === "function") ref(el);
|
|
@@ -1475,9 +1476,9 @@ function hydrateComponent(vnode, domNode, parent, anchor, path = "root") {
|
|
|
1475
1476
|
const mountCleanups = [];
|
|
1476
1477
|
let nextDom = domNode;
|
|
1477
1478
|
const componentName = vnode.type.name || "Anonymous";
|
|
1478
|
-
const mergedProps = vnode.children.length > 0 && vnode.props.children === void 0 ? {
|
|
1479
|
+
const mergedProps = (vnode.children ?? []).length > 0 && vnode.props.children === void 0 ? {
|
|
1479
1480
|
...vnode.props,
|
|
1480
|
-
children: vnode.children.length === 1 ? vnode.children[0] : vnode.children
|
|
1481
|
+
children: (vnode.children ?? []).length === 1 ? (vnode.children ?? [])[0] : vnode.children ?? []
|
|
1481
1482
|
} : vnode.props;
|
|
1482
1483
|
let result;
|
|
1483
1484
|
try {
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["__DEV__","__DEV__","__DEV__","noop","__DEV__"],"sources":["../src/delegate.ts","../src/hydration-debug.ts","../src/devtools.ts","../src/nodes.ts","../src/props.ts","../src/mount.ts","../src/hydrate.ts","../src/keep-alive.ts","../src/template.ts","../src/transition.ts","../src/transition-group.ts","../src/index.ts"],"sourcesContent":["/**\n * Event delegation — single listener per event type on the mount container.\n *\n * Instead of calling addEventListener on every element, the compiler emits\n * `el.__click = handler` (expando property). A single delegated listener on the\n * container walks event.target up the DOM tree, checking for expandos.\n *\n * Benefits:\n * - Saves ~2000 addEventListener calls for 1000 rows with 2 handlers each\n * - Reduces memory per row (no per-element listener closure)\n * - Faster initial mount (~0.4-0.8ms savings on 1000-row benchmarks)\n */\n\nimport { batch } from \"@pyreon/reactivity\"\n\n/**\n * Events that are delegated (common bubbling events).\n * Non-bubbling events (focus, blur, mouseenter, mouseleave, load, error, scroll)\n * are NOT delegated — they must use addEventListener.\n */\nexport const DELEGATED_EVENTS = new Set([\n \"click\",\n \"dblclick\",\n \"contextmenu\",\n \"focusin\",\n \"focusout\",\n \"input\",\n \"change\",\n \"keydown\",\n \"keyup\",\n \"mousedown\",\n \"mouseup\",\n \"mousemove\",\n \"mouseover\",\n \"mouseout\",\n \"pointerdown\",\n \"pointerup\",\n \"pointermove\",\n \"pointerover\",\n \"pointerout\",\n \"touchstart\",\n \"touchend\",\n \"touchmove\",\n \"submit\",\n])\n\n/**\n * Property name used on DOM elements to store delegated event handlers.\n * Format: `__ev_{eventName}` e.g. `__ev_click`, `__ev_input`\n */\nexport function delegatedPropName(eventName: string): string {\n return `__ev_${eventName}`\n}\n\n// Track which containers already have delegation installed\nconst _delegated = new WeakSet<Element>()\n\n/**\n * Install delegation listeners on a container element.\n * Called once from mount(). Idempotent — safe to call multiple times.\n */\nexport function setupDelegation(container: Element): void {\n if (_delegated.has(container)) return\n _delegated.add(container)\n\n for (const eventName of DELEGATED_EVENTS) {\n const prop = delegatedPropName(eventName)\n container.addEventListener(eventName, (e: Event) => {\n let el = e.target as (HTMLElement & Record<string, unknown>) | null\n while (el && el !== container) {\n const handler = el[prop] as EventListener | undefined\n if (handler) {\n batch(() => handler(e))\n // Don't break — allow ancestor handlers too (consistent with addEventListener)\n // But if stopPropagation was called, stop walking\n if (e.cancelBubble) break\n }\n el = el.parentElement as (HTMLElement & Record<string, unknown>) | null\n }\n })\n }\n}\n","/**\n * Hydration mismatch warnings.\n *\n * Enabled automatically in development (NODE_ENV !== \"production\").\n * Can be toggled manually for testing or verbose production debugging.\n *\n * @example\n * import { enableHydrationWarnings } from \"@pyreon/runtime-dom\"\n * enableHydrationWarnings()\n */\n\nconst __DEV__ = typeof process !== \"undefined\" && process.env.NODE_ENV !== \"production\"\n\nlet _enabled = __DEV__\n\nexport function enableHydrationWarnings(): void {\n _enabled = true\n}\n\nexport function disableHydrationWarnings(): void {\n _enabled = false\n}\n\n/**\n * Emit a hydration mismatch warning.\n * @param type - Kind of mismatch\n * @param expected - What the VNode expected\n * @param actual - What the DOM had\n * @param path - Human-readable path in the tree, e.g. \"root > div > span\"\n */\nexport function warnHydrationMismatch(\n _type: \"tag\" | \"text\" | \"missing\",\n _expected: unknown,\n _actual: unknown,\n _path: string,\n): void {\n if (!_enabled) return\n console.warn(\n `[Pyreon] Hydration mismatch (${_type}): expected ${String(_expected)}, got ${String(_actual)} at ${_path}`,\n )\n}\n","/**\n * Pyreon DevTools — exposes a `__PYREON_DEVTOOLS__` global hook for browser devtools extensions\n * and in-app debugging utilities.\n *\n * Installed automatically on first `mount()` call in the browser.\n * No-op on the server (typeof window === \"undefined\").\n *\n * Usage:\n * window.__PYREON_DEVTOOLS__.getComponentTree() // root component entries\n * window.__PYREON_DEVTOOLS__.getAllComponents() // flat list of all live components\n * window.__PYREON_DEVTOOLS__.highlight(\"comp-id\") // outline a component's DOM node\n * window.__PYREON_DEVTOOLS__.onComponentMount(cb) // subscribe to mount events\n * window.__PYREON_DEVTOOLS__.onComponentUnmount(cb)// subscribe to unmount events\n * window.__PYREON_DEVTOOLS__.enableOverlay() // Ctrl+Shift+P: hover to inspect components\n */\n\nexport interface DevtoolsComponentEntry {\n id: string\n name: string\n /** First DOM element produced by this component, if any */\n el: Element | null\n parentId: string | null\n childIds: string[]\n}\n\nexport interface PyreonDevtools {\n readonly version: string\n getComponentTree(): DevtoolsComponentEntry[]\n getAllComponents(): DevtoolsComponentEntry[]\n highlight(id: string): void\n onComponentMount(cb: (entry: DevtoolsComponentEntry) => void): () => void\n onComponentUnmount(cb: (id: string) => void): () => void\n /** Toggle the component inspector overlay (also: Ctrl+Shift+P) */\n enableOverlay(): void\n disableOverlay(): void\n}\n\n// ─── Internal registry ────────────────────────────────────────────────────────\n\nconst _components = new Map<string, DevtoolsComponentEntry>()\nconst _mountListeners: ((entry: DevtoolsComponentEntry) => void)[] = []\nconst _unmountListeners: ((id: string) => void)[] = []\n\nexport function registerComponent(\n id: string,\n name: string,\n el: Element | null,\n parentId: string | null,\n): void {\n const entry: DevtoolsComponentEntry = { id, name, el, parentId, childIds: [] }\n _components.set(id, entry)\n if (parentId) {\n const parent = _components.get(parentId)\n if (parent) parent.childIds.push(id)\n }\n for (const cb of _mountListeners) cb(entry)\n}\n\nexport function unregisterComponent(id: string): void {\n const entry = _components.get(id)\n if (!entry) return\n if (entry.parentId) {\n const parent = _components.get(entry.parentId)\n if (parent) parent.childIds = parent.childIds.filter((c) => c !== id)\n }\n _components.delete(id)\n for (const cb of _unmountListeners) cb(id)\n}\n\n// ─── Component Inspector Overlay ─────────────────────────────────────────────\n\nlet _overlayActive = false\nlet _overlayEl: HTMLDivElement | null = null\nlet _tooltipEl: HTMLDivElement | null = null\nlet _currentHighlight: Element | null = null\n\nfunction findComponentForElement(el: Element): DevtoolsComponentEntry | null {\n // Walk up from the hovered element to find the nearest registered component\n let node: Element | null = el\n while (node) {\n for (const entry of _components.values()) {\n if (entry.el === node) return entry\n }\n node = node.parentElement\n }\n return null\n}\n\nfunction createOverlayElements(): void {\n if (_overlayEl) return\n\n _overlayEl = document.createElement(\"div\")\n _overlayEl.id = \"__pyreon-overlay\"\n _overlayEl.style.cssText =\n \"position:fixed;pointer-events:none;border:2px solid #00b4d8;border-radius:3px;z-index:999999;display:none;transition:all 0.08s ease-out;\"\n\n _tooltipEl = document.createElement(\"div\")\n _tooltipEl.style.cssText =\n \"position:fixed;pointer-events:none;background:#1a1a2e;color:#e0e0e0;font:12px/1.4 ui-monospace,monospace;padding:6px 10px;border-radius:4px;z-index:999999;display:none;box-shadow:0 2px 8px rgba(0,0,0,0.3);max-width:400px;white-space:pre-wrap;\"\n\n document.body.appendChild(_overlayEl)\n document.body.appendChild(_tooltipEl)\n}\n\nfunction positionOverlay(rect: DOMRect): void {\n if (!_overlayEl) return\n _overlayEl.style.display = \"block\"\n _overlayEl.style.top = `${rect.top}px`\n _overlayEl.style.left = `${rect.left}px`\n _overlayEl.style.width = `${rect.width}px`\n _overlayEl.style.height = `${rect.height}px`\n}\n\nfunction positionTooltip(entry: DevtoolsComponentEntry, rect: DOMRect): void {\n if (!_tooltipEl) return\n const childCount = entry.childIds.length\n let info = `<${entry.name}>`\n if (childCount > 0) info += `\\n ${childCount} child component${childCount === 1 ? \"\" : \"s\"}`\n _tooltipEl.textContent = info\n _tooltipEl.style.display = \"block\"\n _tooltipEl.style.top = `${rect.top - 30}px`\n _tooltipEl.style.left = `${rect.left}px`\n if (rect.top < 35) {\n _tooltipEl.style.top = `${rect.bottom + 4}px`\n }\n}\n\nfunction hideOverlayElements(): void {\n if (_overlayEl) _overlayEl.style.display = \"none\"\n if (_tooltipEl) _tooltipEl.style.display = \"none\"\n _currentHighlight = null\n}\n\n/** @internal — exported for testing only */\nexport function onOverlayMouseMove(e: MouseEvent): void {\n const target = document.elementFromPoint(e.clientX, e.clientY)\n if (!target || target === _overlayEl || target === _tooltipEl) return\n\n const entry = findComponentForElement(target)\n if (!entry?.el) {\n hideOverlayElements()\n return\n }\n\n if (entry.el === _currentHighlight) return\n _currentHighlight = entry.el\n\n const rect = entry.el.getBoundingClientRect()\n positionOverlay(rect)\n positionTooltip(entry, rect)\n}\n\n/** @internal — exported for testing only */\nexport function onOverlayClick(e: MouseEvent): void {\n e.preventDefault()\n e.stopPropagation()\n const target = document.elementFromPoint(e.clientX, e.clientY)\n if (!target) return\n const entry = findComponentForElement(target)\n if (entry) {\n console.group(`[Pyreon] <${entry.name}>`)\n console.log(\"element:\", entry.el)\n console.log(\"children:\", entry.childIds.length)\n if (entry.parentId) {\n const parent = _components.get(entry.parentId)\n if (parent) {\n console.log(\"parent:\", `<${parent.name}>`)\n }\n }\n console.groupEnd()\n }\n disableOverlay()\n}\n\nfunction onOverlayKeydown(e: KeyboardEvent): void {\n if (e.key === \"Escape\") {\n disableOverlay()\n }\n}\n\nfunction enableOverlay(): void {\n if (_overlayActive) return\n _overlayActive = true\n createOverlayElements()\n document.addEventListener(\"mousemove\", onOverlayMouseMove, true)\n document.addEventListener(\"click\", onOverlayClick, true)\n document.addEventListener(\"keydown\", onOverlayKeydown, true)\n document.body.style.cursor = \"crosshair\"\n}\n\nfunction disableOverlay(): void {\n if (!_overlayActive) return\n _overlayActive = false\n document.removeEventListener(\"mousemove\", onOverlayMouseMove, true)\n document.removeEventListener(\"click\", onOverlayClick, true)\n document.removeEventListener(\"keydown\", onOverlayKeydown, true)\n document.body.style.cursor = \"\"\n if (_overlayEl) _overlayEl.style.display = \"none\"\n if (_tooltipEl) _tooltipEl.style.display = \"none\"\n _currentHighlight = null\n}\n\n// ─── Installation ─────────────────────────────────────────────────────────────\n\nlet _installed = false\n// Resolved once at module load — avoids per-call typeof branch in coverage\nconst _hasWindow = typeof window !== \"undefined\"\n\nexport function installDevTools(): void {\n if (!_hasWindow || _installed) return\n _installed = true\n\n const devtools: PyreonDevtools = {\n version: \"0.1.0\",\n\n getComponentTree() {\n return Array.from(_components.values()).filter((e) => e.parentId === null)\n },\n\n getAllComponents() {\n return Array.from(_components.values())\n },\n\n highlight(id: string) {\n const entry = _components.get(id)\n if (!entry?.el) return\n const el = entry.el as HTMLElement\n const prev = el.style.outline\n el.style.outline = \"2px solid #00b4d8\"\n setTimeout(() => {\n el.style.outline = prev\n }, 1500)\n },\n\n onComponentMount(cb: (entry: DevtoolsComponentEntry) => void): () => void {\n _mountListeners.push(cb)\n return () => {\n const i = _mountListeners.indexOf(cb)\n if (i >= 0) _mountListeners.splice(i, 1)\n }\n },\n\n onComponentUnmount(cb: (id: string) => void): () => void {\n _unmountListeners.push(cb)\n return () => {\n const i = _unmountListeners.indexOf(cb)\n if (i >= 0) _unmountListeners.splice(i, 1)\n }\n },\n\n enableOverlay,\n disableOverlay,\n }\n\n // Attach to window — compatible with browser devtools extensions\n ;(window as unknown as Record<string, unknown>).__PYREON_DEVTOOLS__ = devtools\n\n // Ctrl+Shift+P toggles the component inspector overlay\n window.addEventListener(\"keydown\", (e) => {\n if (e.ctrlKey && e.shiftKey && e.key === \"P\") {\n e.preventDefault()\n if (_overlayActive) disableOverlay()\n else enableOverlay()\n }\n })\n\n // ── $p console helper ────────────────────────────────────────────────────\n // Type `$p` in the browser console for quick access to Pyreon debug tools.\n const win = window as unknown as Record<string, unknown>\n win.$p = {\n /** List all mounted components */\n components: () => devtools.getAllComponents(),\n /** Component tree (roots only) */\n tree: () => devtools.getComponentTree(),\n /** Highlight a component by id */\n highlight: (id: string) => devtools.highlight(id),\n /** Toggle component inspector overlay */\n inspect: () => {\n if (_overlayActive) disableOverlay()\n else enableOverlay()\n },\n /** Print component count */\n stats: () => {\n const all = devtools.getAllComponents()\n const roots = devtools.getComponentTree()\n console.log(\n `[Pyreon] ${all.length} component${all.length === 1 ? \"\" : \"s\"}, ${roots.length} root${roots.length === 1 ? \"\" : \"s\"}`,\n )\n return { total: all.length, roots: roots.length }\n },\n /** Quick help */\n help: () => {\n console.log(\n \"[Pyreon] $p commands:\\n\" +\n \" $p.components() — list all mounted components\\n\" +\n \" $p.tree() — component tree (roots only)\\n\" +\n \" $p.highlight(id)— outline a component\\n\" +\n \" $p.inspect() — toggle component inspector\\n\" +\n \" $p.stats() — print component count\\n\" +\n \" $p.help() — this message\",\n )\n },\n }\n}\n","import type { VNode, VNodeChild } from \"@pyreon/core\"\n\ntype MountFn = (child: VNodeChild, parent: Node, anchor: Node | null) => Cleanup\n\nimport { effect, runUntracked } from \"@pyreon/reactivity\"\n\nconst __DEV__ = typeof process !== \"undefined\" && process.env.NODE_ENV !== \"production\"\n\ntype Cleanup = () => void\n\n/**\n * Move all nodes strictly between `start` and `end` into a throwaway\n * DocumentFragment, detaching them from the live DOM in O(n) top-level moves.\n *\n * This is dramatically faster than Range.deleteContents() in JS-based DOMs\n * (happy-dom, jsdom) where deleting connected nodes with deep subtrees is O(n²).\n * In real browsers both approaches are similar, but the fragment approach is\n * never slower and avoids the pathological case.\n *\n * After this call every moved node has isConnected=false, so cleanup functions\n * that guard removeChild with `isConnected !== false` become no-ops.\n */\nfunction clearBetween(start: Node, end: Node): void {\n const frag = document.createDocumentFragment()\n let cur: Node | null = start.nextSibling\n while (cur && cur !== end) {\n const next: Node | null = cur.nextSibling\n frag.appendChild(cur)\n cur = next\n }\n // frag goes out of scope → nodes are GC-eligible\n}\n\n/**\n * Mount a reactive node whose content changes over time.\n *\n * A comment node is used as a stable anchor point in the DOM.\n * On each change: old nodes are removed, new ones inserted before the anchor.\n */\nexport function mountReactive(\n accessor: () => VNodeChild,\n parent: Node,\n anchor: Node | null,\n mount: (child: VNodeChild, p: Node, a: Node | null) => Cleanup,\n): Cleanup {\n const marker = document.createComment(\"pyreon\")\n parent.insertBefore(marker, anchor)\n\n let currentCleanup: Cleanup = () => {\n /* noop */\n }\n let generation = 0\n\n const e = effect(() => {\n const myGen = ++generation\n // Run cleanup outside tracking context — cleanup may write to signals\n // (e.g. onUnmount hooks), and those writes must not accidentally register\n // as dependencies of this effect, which would cause infinite recursion.\n runUntracked(() => currentCleanup())\n currentCleanup = () => {\n /* noop */\n }\n const value = accessor()\n if (__DEV__ && typeof value === \"function\") {\n console.warn(\n \"[Pyreon] Reactive accessor returned a function instead of a value. Did you forget to call the signal?\",\n )\n }\n if (value != null && value !== false) {\n const cleanup = mount(value, parent, marker)\n // Guard: a re-entrant signal update (e.g. ErrorBoundary catching a child\n // throw) may have already re-run this effect and updated currentCleanup.\n // In that case, discard our stale cleanup rather than overwriting the one\n // set by the re-entrant run.\n if (myGen === generation) {\n currentCleanup = cleanup\n } else {\n cleanup()\n }\n }\n })\n\n return () => {\n e.dispose()\n currentCleanup()\n marker.parentNode?.removeChild(marker)\n }\n}\n\n// ─── Keyed list reconciler ────────────────────────────────────────────────────\n\n/**\n * Efficient keyed list reconciler.\n *\n * When a reactive accessor returns VNode[] where every vnode carries a key,\n * this reconciler reuses, moves, and creates DOM nodes surgically instead of\n * tearing down and rebuilding the full list on every signal update.\n */\n\ninterface KeyedEntry {\n /** Comment node placed immediately before this entry's DOM content. */\n anchor: Comment\n cleanup: Cleanup\n}\n\n// WeakSets to identify anchor nodes belonging to list entries.\n// Entries use their first DOM node as anchor (element for simple vnodes, comment fallback for empty).\nconst _keyedAnchors = new WeakSet<Node>()\n\n/** LIS-based reorder state — shared across keyed list instances, grown as needed */\ninterface LisState {\n tails: Int32Array\n tailIdx: Int32Array\n pred: Int32Array\n stay: Uint8Array\n}\n\nfunction growLisArrays(lis: LisState, n: number): LisState {\n if (n <= lis.pred.length) return lis\n return {\n tails: new Int32Array(n + 16),\n tailIdx: new Int32Array(n + 16),\n pred: new Int32Array(n + 16),\n stay: new Uint8Array(n + 16),\n }\n}\n\nfunction computeKeyedLis(\n lis: LisState,\n n: number,\n newKeyOrder: (string | number)[],\n curPos: Map<string | number, number>,\n): number {\n const { tails, tailIdx, pred } = lis\n let lisLen = 0\n for (let i = 0; i < n; i++) {\n const key = newKeyOrder[i]\n if (key === undefined) continue\n const v = curPos.get(key) ?? -1\n if (v < 0) continue\n\n let lo = 0\n let hi = lisLen\n while (lo < hi) {\n const mid = (lo + hi) >> 1\n if ((tails[mid] as number) < v) lo = mid + 1\n else hi = mid\n }\n tails[lo] = v\n tailIdx[lo] = i\n if (lo > 0) pred[i] = tailIdx[lo - 1] as number\n if (lo === lisLen) lisLen++\n }\n return lisLen\n}\n\nfunction markStayingEntries(lis: LisState, lisLen: number): void {\n const { tailIdx, pred, stay } = lis\n let cur: number = lisLen > 0 ? (tailIdx[lisLen - 1] as number) : -1\n while (cur !== -1) {\n stay[cur] = 1\n cur = pred[cur] as number\n }\n}\n\nfunction applyKeyedMoves(\n n: number,\n newKeyOrder: (string | number)[],\n stay: Uint8Array,\n cache: Map<string | number, KeyedEntry>,\n parent: Node,\n tailMarker: Comment,\n): void {\n let cursor: Node = tailMarker\n for (let i = n - 1; i >= 0; i--) {\n const key = newKeyOrder[i]\n if (key === undefined) continue\n const entry = cache.get(key)\n if (!entry) continue\n if (!stay[i]) moveEntryBefore(parent, entry.anchor, cursor)\n cursor = entry.anchor\n }\n}\n\n/** Grow LIS typed arrays if needed, then compute and apply reorder. */\nfunction keyedListReorder(\n lis: LisState,\n n: number,\n newKeyOrder: (string | number)[],\n curPos: Map<string | number, number>,\n cache: Map<string | number, KeyedEntry>,\n parent: Node,\n tailMarker: Comment,\n): LisState {\n const grown = growLisArrays(lis, n)\n grown.pred.fill(-1, 0, n)\n grown.stay.fill(0, 0, n)\n\n const lisLen = computeKeyedLis(grown, n, newKeyOrder, curPos)\n markStayingEntries(grown, lisLen)\n applyKeyedMoves(n, newKeyOrder, grown.stay, cache, parent, tailMarker)\n\n return grown\n}\n\nexport function mountKeyedList(\n accessor: () => VNode[],\n parent: Node,\n listAnchor: Node | null,\n mountVNode: (vnode: VNode, p: Node, a: Node | null) => Cleanup,\n): Cleanup {\n const startMarker = document.createComment(\"\")\n const tailMarker = document.createComment(\"\")\n parent.insertBefore(startMarker, listAnchor)\n parent.insertBefore(tailMarker, listAnchor)\n\n const cache = new Map<string | number, KeyedEntry>()\n const curPos = new Map<string | number, number>()\n let currentKeyOrder: (string | number)[] = []\n\n let lis: LisState = {\n tails: new Int32Array(16),\n tailIdx: new Int32Array(16),\n pred: new Int32Array(16),\n stay: new Uint8Array(16),\n }\n\n const collectKeyOrder = (\n newList: VNode[],\n ): { newKeyOrder: (string | number)[]; newKeySet: Set<string | number> } => {\n const newKeyOrder: (string | number)[] = []\n const newKeySet = new Set<string | number>()\n for (const vnode of newList) {\n const key = vnode.key\n if (key !== null && key !== undefined) {\n newKeyOrder.push(key)\n newKeySet.add(key)\n }\n }\n return { newKeyOrder, newKeySet }\n }\n\n const removeStaleEntries = (newKeySet: Set<string | number>) => {\n for (const [key, entry] of cache) {\n if (newKeySet.has(key)) continue\n entry.cleanup()\n entry.anchor.parentNode?.removeChild(entry.anchor)\n cache.delete(key)\n curPos.delete(key)\n }\n }\n\n const mountNewEntries = (newList: VNode[]) => {\n for (const vnode of newList) {\n const key = vnode.key\n if (key === null || key === undefined) continue\n if (cache.has(key)) continue\n const anchor = document.createComment(\"\")\n _keyedAnchors.add(anchor)\n parent.insertBefore(anchor, tailMarker)\n const cleanup = mountVNode(vnode, parent, tailMarker)\n cache.set(key, { anchor, cleanup })\n }\n }\n\n const e = effect(() => {\n const newList = accessor()\n const n = newList.length\n\n if (n === 0 && cache.size > 0) {\n for (const entry of cache.values()) entry.cleanup()\n cache.clear()\n curPos.clear()\n currentKeyOrder = []\n clearBetween(startMarker, tailMarker)\n return\n }\n\n const { newKeyOrder, newKeySet } = collectKeyOrder(newList)\n removeStaleEntries(newKeySet)\n mountNewEntries(newList)\n\n if (currentKeyOrder.length > 0 && n > 0) {\n lis = keyedListReorder(lis, n, newKeyOrder, curPos, cache, parent, tailMarker)\n }\n\n curPos.clear()\n for (let i = 0; i < newKeyOrder.length; i++) {\n const k = newKeyOrder[i]\n if (k !== undefined) curPos.set(k, i)\n }\n currentKeyOrder = newKeyOrder\n })\n\n return () => {\n e.dispose()\n for (const entry of cache.values()) {\n entry.cleanup()\n entry.anchor.parentNode?.removeChild(entry.anchor)\n }\n cache.clear()\n startMarker.parentNode?.removeChild(startMarker)\n tailMarker.parentNode?.removeChild(tailMarker)\n }\n}\n\n// ─── For — source-aware keyed reconciler ─────────────────────────────────────\n\n/** Maximum number of displaced positions before falling back to full LIS. */\nconst SMALL_K = 8\n\n// WeakSet to identify anchor nodes belonging to mountFor entries.\nconst _forAnchors = new WeakSet<Node>()\n\n// anchor is the first DOM node of the entry (element for normal vnodes, comment fallback for empty).\n// Using the element itself saves 1 createComment + 1 DOM node per entry.\n// pos is merged here (instead of a separate Map) to halve Map operations.\n// cleanup is null when the entry has no teardown work (saves function call overhead on clear).\ninterface ForEntry {\n anchor: Node\n cleanup: Cleanup | null\n pos: number\n}\n\n/** Try small-k reorder; returns true if handled, false if LIS fallback needed. */\nfunction trySmallKReorder(\n n: number,\n newKeys: (string | number)[],\n currentKeys: (string | number)[],\n cache: Map<string | number, ForEntry>,\n liveParent: Node,\n tailMarker: Comment,\n): boolean {\n if (n !== currentKeys.length) return false\n const diffs: number[] = []\n for (let i = 0; i < n; i++) {\n if (newKeys[i] !== currentKeys[i]) {\n diffs.push(i)\n if (diffs.length > SMALL_K) return false\n }\n }\n if (diffs.length > 0) smallKPlace(liveParent, diffs, newKeys, cache, tailMarker)\n for (const i of diffs) {\n const cached = cache.get(newKeys[i] as string | number)\n if (cached) cached.pos = i\n }\n return true\n}\n\nfunction computeForLis(\n lis: LisState,\n n: number,\n newKeys: (string | number)[],\n cache: Map<string | number, ForEntry>,\n): number {\n const { tails, tailIdx, pred } = lis\n let lisLen = 0\n for (let i = 0; i < n; i++) {\n const key = newKeys[i] as string | number\n const v = cache.get(key)?.pos ?? 0\n let lo = 0\n let hi = lisLen\n while (lo < hi) {\n const mid = (lo + hi) >> 1\n if ((tails[mid] as number) < v) lo = mid + 1\n else hi = mid\n }\n tails[lo] = v\n tailIdx[lo] = i\n if (lo > 0) pred[i] = tailIdx[lo - 1] as number\n if (lo === lisLen) lisLen++\n }\n return lisLen\n}\n\nfunction applyForMoves(\n n: number,\n newKeys: (string | number)[],\n stay: Uint8Array,\n cache: Map<string | number, ForEntry>,\n liveParent: Node,\n tailMarker: Comment,\n): void {\n let cursor: Node = tailMarker\n for (let i = n - 1; i >= 0; i--) {\n const entry = cache.get(newKeys[i] as string | number)\n if (!entry) continue\n if (!stay[i]) moveEntryBefore(liveParent, entry.anchor, cursor)\n cursor = entry.anchor\n }\n}\n\n/** LIS-based reorder for mountFor. */\nfunction forLisReorder(\n lis: LisState,\n n: number,\n newKeys: (string | number)[],\n cache: Map<string | number, ForEntry>,\n liveParent: Node,\n tailMarker: Comment,\n): LisState {\n const grown = growLisArrays(lis, n)\n grown.pred.fill(-1, 0, n)\n grown.stay.fill(0, 0, n)\n\n const lisLen = computeForLis(grown, n, newKeys, cache)\n markStayingEntries(grown, lisLen)\n applyForMoves(n, newKeys, grown.stay, cache, liveParent, tailMarker)\n\n for (let i = 0; i < n; i++) {\n const cached = cache.get(newKeys[i] as string | number)\n if (cached) cached.pos = i\n }\n\n return grown\n}\n\n/**\n * Keyed reconciler that works directly on the source item array.\n *\n * Optimizations:\n * - Calls renderItem() only for NEW keys — 0 VNode allocations for reorders\n * - Small-k fast path: if <= SMALL_K positions changed, skips LIS\n * - Fast clear path: moves nodes to DocumentFragment for O(n) bulk detach\n * - Fresh render fast path: skips stale-check and reorder on first render\n */\nexport function mountFor<T>(\n source: () => T[],\n getKey: (item: T) => string | number,\n renderItem: (item: T) => import(\"@pyreon/core\").VNode | import(\"@pyreon/core\").NativeItem,\n parent: Node,\n anchor: Node | null,\n mountChild: MountFn,\n): Cleanup {\n const startMarker = document.createComment(\"\")\n const tailMarker = document.createComment(\"\")\n parent.insertBefore(startMarker, anchor)\n parent.insertBefore(tailMarker, anchor)\n\n let cache = new Map<string | number, ForEntry>()\n let currentKeys: (string | number)[] = []\n let cleanupCount = 0\n let anchorsRegistered = false\n\n let lis: LisState = {\n tails: new Int32Array(16),\n tailIdx: new Int32Array(16),\n pred: new Int32Array(16),\n stay: new Uint8Array(16),\n }\n\n const warnForKey = (seen: Set<string | number> | null, key: string | number) => {\n if (!__DEV__ || !seen) return\n if (key == null) {\n console.warn(\n \"[Pyreon] <For> `by` function returned null/undefined. \" +\n \"Keys must be strings or numbers. Check your `by` prop.\",\n )\n }\n if (seen.has(key)) {\n console.warn(`[Pyreon] Duplicate key \"${String(key)}\" in <For> list. Keys must be unique.`)\n }\n seen.add(key)\n }\n\n /** Render item into container, update cache+cleanupCount. No anchor registration. */\n const renderInto = (\n item: T,\n key: string | number,\n pos: number,\n container: Node,\n before: Node | null,\n ) => {\n const result = renderItem(item)\n if ((result as import(\"@pyreon/core\").NativeItem).__isNative) {\n const native = result as import(\"@pyreon/core\").NativeItem\n container.insertBefore(native.el, before)\n cache.set(key, { anchor: native.el, cleanup: native.cleanup, pos })\n if (native.cleanup) cleanupCount++\n return\n }\n const priorLast = before ? before.previousSibling : container.lastChild\n const cl = mountChild(result as import(\"@pyreon/core\").VNode, container, before)\n const firstMounted = priorLast ? priorLast.nextSibling : container.firstChild\n if (!firstMounted || firstMounted === before) {\n const ph = document.createComment(\"\")\n container.insertBefore(ph, before)\n cache.set(key, { anchor: ph, cleanup: cl, pos })\n } else {\n cache.set(key, { anchor: firstMounted, cleanup: cl, pos })\n }\n cleanupCount++\n }\n\n const handleFreshRender = (items: T[], n: number, liveParent: Node) => {\n const frag = document.createDocumentFragment()\n const keys = new Array<string | number>(n)\n const _seenKeys = __DEV__ ? new Set<string | number>() : null\n for (let i = 0; i < n; i++) {\n const item = items[i] as T\n const key = getKey(item)\n warnForKey(_seenKeys, key)\n keys[i] = key\n renderInto(item, key, i, frag, null)\n }\n liveParent.insertBefore(frag, tailMarker)\n anchorsRegistered = false\n currentKeys = keys\n }\n\n const collectNewKeys = (items: T[], n: number): (string | number)[] => {\n const newKeys = new Array<string | number>(n)\n const _seenUpdate = __DEV__ ? new Set<string | number>() : null\n for (let i = 0; i < n; i++) {\n newKeys[i] = getKey(items[i] as T)\n warnForKey(_seenUpdate, newKeys[i] as string | number)\n }\n return newKeys\n }\n\n const handleReplaceAll = (\n items: T[],\n n: number,\n newKeys: (string | number)[],\n liveParent: Node,\n ) => {\n if (cleanupCount > 0) {\n for (const entry of cache.values()) if (entry.cleanup) entry.cleanup()\n }\n cache = new Map()\n cleanupCount = 0\n\n const parentParent = liveParent.parentNode\n const canSwap =\n parentParent && liveParent.firstChild === startMarker && liveParent.lastChild === tailMarker\n\n const frag = document.createDocumentFragment()\n for (let i = 0; i < n; i++) {\n renderInto(items[i] as T, newKeys[i] as string | number, i, frag, null)\n }\n anchorsRegistered = false\n\n if (canSwap) {\n const fresh = liveParent.cloneNode(false)\n fresh.appendChild(startMarker)\n fresh.appendChild(frag)\n fresh.appendChild(tailMarker)\n parentParent.replaceChild(fresh, liveParent)\n } else {\n clearBetween(startMarker, tailMarker)\n liveParent.insertBefore(frag, tailMarker)\n }\n currentKeys = newKeys\n }\n\n const removeStaleForEntries = (newKeySet: Set<string | number>) => {\n for (const [key, entry] of cache) {\n if (newKeySet.has(key)) continue\n if (entry.cleanup) {\n entry.cleanup()\n cleanupCount--\n }\n entry.anchor.parentNode?.removeChild(entry.anchor)\n cache.delete(key)\n }\n }\n\n const mountNewForEntries = (\n items: T[],\n n: number,\n newKeys: (string | number)[],\n liveParent: Node,\n ) => {\n for (let i = 0; i < n; i++) {\n const key = newKeys[i] as string | number\n if (cache.has(key)) continue\n renderInto(items[i] as T, key, i, liveParent, tailMarker)\n const entry = cache.get(key)\n if (entry) _forAnchors.add(entry.anchor)\n }\n }\n\n const handleFastClear = (liveParent: Node) => {\n if (cache.size === 0) return\n if (cleanupCount > 0) {\n for (const entry of cache.values()) if (entry.cleanup) entry.cleanup()\n }\n const pp = liveParent.parentNode\n if (pp && liveParent.firstChild === startMarker && liveParent.lastChild === tailMarker) {\n const fresh = liveParent.cloneNode(false)\n fresh.appendChild(startMarker)\n fresh.appendChild(tailMarker)\n pp.replaceChild(fresh, liveParent)\n } else {\n clearBetween(startMarker, tailMarker)\n }\n cache = new Map()\n cleanupCount = 0\n currentKeys = []\n }\n\n const hasAnyKeptKey = (n: number, newKeys: (string | number)[]): boolean => {\n for (let i = 0; i < n; i++) {\n if (cache.has(newKeys[i] as string | number)) return true\n }\n return false\n }\n\n const handleIncrementalUpdate = (\n items: T[],\n n: number,\n newKeys: (string | number)[],\n liveParent: Node,\n ) => {\n removeStaleForEntries(new Set<string | number>(newKeys))\n mountNewForEntries(items, n, newKeys, liveParent)\n\n if (!anchorsRegistered) {\n for (const entry of cache.values()) _forAnchors.add(entry.anchor)\n anchorsRegistered = true\n }\n\n if (trySmallKReorder(n, newKeys, currentKeys, cache, liveParent, tailMarker)) {\n currentKeys = newKeys\n return\n }\n\n lis = forLisReorder(lis, n, newKeys, cache, liveParent, tailMarker)\n currentKeys = newKeys\n }\n\n const e = effect(() => {\n const liveParent = startMarker.parentNode\n if (!liveParent) return\n const items = source()\n const n = items.length\n\n if (n === 0) {\n handleFastClear(liveParent)\n return\n }\n\n if (currentKeys.length === 0) {\n handleFreshRender(items, n, liveParent)\n return\n }\n\n const newKeys = collectNewKeys(items, n)\n\n if (!hasAnyKeptKey(n, newKeys)) {\n handleReplaceAll(items, n, newKeys, liveParent)\n return\n }\n\n handleIncrementalUpdate(items, n, newKeys, liveParent)\n })\n\n return () => {\n e.dispose()\n for (const entry of cache.values()) {\n if (cleanupCount > 0 && entry.cleanup) entry.cleanup()\n entry.anchor.parentNode?.removeChild(entry.anchor)\n }\n cache = new Map()\n cleanupCount = 0\n startMarker.parentNode?.removeChild(startMarker)\n tailMarker.parentNode?.removeChild(tailMarker)\n }\n}\n\n/**\n * Small-k reorder: directly place the k displaced entries without LIS.\n */\nfunction smallKPlace(\n parent: Node,\n diffs: number[],\n newKeys: (string | number)[],\n cache: Map<string | number, { anchor: Node; cleanup: Cleanup | null }>,\n tailMarker: Comment,\n): void {\n const diffSet = new Set(diffs)\n let cursor: Node = tailMarker\n let prevDiffIdx = newKeys.length\n\n for (let d = diffs.length - 1; d >= 0; d--) {\n const i = diffs[d] as number\n\n let nextNonDiff = -1\n for (let j = i + 1; j < prevDiffIdx; j++) {\n if (!diffSet.has(j)) {\n nextNonDiff = j\n break\n }\n }\n\n if (nextNonDiff >= 0) {\n const nc = cache.get(newKeys[nextNonDiff] as string | number)?.anchor\n if (nc) cursor = nc\n }\n\n const entry = cache.get(newKeys[i] as string | number)\n if (!entry) {\n prevDiffIdx = i\n continue\n }\n moveEntryBefore(parent, entry.anchor, cursor)\n cursor = entry.anchor\n prevDiffIdx = i\n }\n}\n\n/**\n * Move startNode and all siblings belonging to this entry to just before `before`.\n * Stops at the next entry anchor (identified via WeakSet) or the tail marker.\n *\n * Fast path: if the next sibling is already a boundary (another entry or tail),\n * this entry is a single node — skip the toMove array entirely.\n */\nfunction moveEntryBefore(parent: Node, startNode: Node, before: Node): void {\n const next = startNode.nextSibling\n // Single-node fast path (covers all createTemplate rows — the common case)\n if (\n !next ||\n next === before ||\n (next.parentNode === parent && (_forAnchors.has(next) || _keyedAnchors.has(next)))\n ) {\n parent.insertBefore(startNode, before)\n return\n }\n // Multi-node slow path (fragments, components with multiple root nodes)\n const toMove: Node[] = [startNode]\n let cur: Node | null = next\n while (cur && cur !== before) {\n const nextNode: Node | null = cur.nextSibling\n toMove.push(cur)\n cur = nextNode\n if (\n cur &&\n cur.parentNode === parent &&\n (cur === before || _forAnchors.has(cur) || _keyedAnchors.has(cur))\n )\n break\n }\n for (const node of toMove) {\n parent.insertBefore(node, before)\n }\n}\n","import type { ClassValue, Props } from \"@pyreon/core\"\nimport { cx, normalizeStyleValue, toKebabCase } from \"@pyreon/core\"\n\nimport { batch, renderEffect } from \"@pyreon/reactivity\"\nimport { DELEGATED_EVENTS, delegatedPropName } from \"./delegate\"\n\ntype Cleanup = () => void\n\nconst __DEV__ = typeof process !== \"undefined\" && process.env.NODE_ENV !== \"production\"\n\n// ─── Configurable sanitizer ──────────────────────────────────────────────────\n\nexport type SanitizeFn = (html: string) => string\n\nlet _customSanitizer: SanitizeFn | null = null\n\n/**\n * Set a custom HTML sanitizer used by `innerHTML` and `sanitizeHtml()`.\n * Overrides both the Sanitizer API and the built-in fallback.\n *\n * @example\n * // With DOMPurify:\n * import DOMPurify from \"dompurify\"\n * setSanitizer((html) => DOMPurify.sanitize(html))\n *\n * // With sanitize-html:\n * import sanitize from \"sanitize-html\"\n * setSanitizer((html) => sanitize(html))\n *\n * // Reset to built-in:\n * setSanitizer(null)\n */\nexport function setSanitizer(fn: SanitizeFn | null): void {\n _customSanitizer = fn\n}\n\n// Safe HTML tags allowed by the fallback sanitizer (block + inline, no scripts/embeds/forms)\nconst SAFE_TAGS = new Set([\n \"a\",\n \"abbr\",\n \"address\",\n \"article\",\n \"aside\",\n \"b\",\n \"bdi\",\n \"bdo\",\n \"blockquote\",\n \"br\",\n \"caption\",\n \"cite\",\n \"code\",\n \"col\",\n \"colgroup\",\n \"dd\",\n \"del\",\n \"details\",\n \"dfn\",\n \"div\",\n \"dl\",\n \"dt\",\n \"em\",\n \"figcaption\",\n \"figure\",\n \"footer\",\n \"h1\",\n \"h2\",\n \"h3\",\n \"h4\",\n \"h5\",\n \"h6\",\n \"header\",\n \"hr\",\n \"i\",\n \"ins\",\n \"kbd\",\n \"li\",\n \"main\",\n \"mark\",\n \"nav\",\n \"ol\",\n \"p\",\n \"pre\",\n \"q\",\n \"rp\",\n \"rt\",\n \"ruby\",\n \"s\",\n \"samp\",\n \"section\",\n \"small\",\n \"span\",\n \"strong\",\n \"sub\",\n \"summary\",\n \"sup\",\n \"table\",\n \"tbody\",\n \"td\",\n \"tfoot\",\n \"th\",\n \"thead\",\n \"time\",\n \"tr\",\n \"u\",\n \"ul\",\n \"var\",\n \"wbr\",\n])\n\n// Attributes that can carry executable code\nconst UNSAFE_ATTR_RE = /^on/i\n\n/**\n * Fallback tag-stripping sanitizer for environments without the Sanitizer API.\n * Removes all tags not in SAFE_TAGS, strips event handler attributes,\n * and blocks javascript:/data: URLs in href/src/action attributes.\n */\nfunction fallbackSanitize(html: string): string {\n const doc = new DOMParser().parseFromString(html, \"text/html\")\n sanitizeNode(doc.body)\n return doc.body.innerHTML\n}\n\n/** Strip unsafe attributes from a single element. */\nfunction stripUnsafeAttrs(el: Element): void {\n const attrs = Array.from(el.attributes)\n for (const attr of attrs) {\n if (UNSAFE_ATTR_RE.test(attr.name)) {\n el.removeAttribute(attr.name)\n } else if (URL_ATTRS.has(attr.name) && UNSAFE_URL_RE.test(attr.value)) {\n el.removeAttribute(attr.name)\n }\n }\n}\n\nfunction sanitizeNode(node: Node): void {\n const children = Array.from(node.childNodes)\n for (const child of children) {\n if (child.nodeType !== 1) continue\n const el = child as Element\n const tag = el.tagName.toLowerCase()\n if (!SAFE_TAGS.has(tag)) {\n const text = document.createTextNode(el.textContent as string)\n node.replaceChild(text, el)\n continue\n }\n stripUnsafeAttrs(el)\n sanitizeNode(el)\n }\n}\n\n/**\n * Sanitize an HTML string using the browser Sanitizer API (Chrome 105+).\n * Falls back to a tag-allowlist sanitizer that strips unsafe elements and attributes.\n */\nexport function sanitizeHtml(html: string): string {\n // User-provided sanitizer takes priority (e.g. DOMPurify)\n if (_customSanitizer) return _customSanitizer(html)\n // DOM-based allowlist sanitizer — DOMParser is available in all browser targets.\n // sanitizeHtml is only called for innerHTML (DOM-only), so SSR fallback is not needed.\n return fallbackSanitize(html)\n}\n\n// Matches onClick, onInput, onMouseEnter, etc.\nconst EVENT_RE = /^on[A-Z]/\n\n/**\n * Apply all props to a DOM element.\n * Returns a single chained cleanup (or null if no props need teardown).\n * Uses for-in instead of Object.keys() to avoid allocating a keys array.\n */\nexport function applyProps(el: Element, props: Props): Cleanup | null {\n let first: Cleanup | null = null\n let cleanups: Cleanup[] | null = null\n for (const key in props) {\n if (key === \"key\" || key === \"ref\" || key === \"children\") continue\n const c = applyProp(el, key, props[key])\n if (c) {\n if (!first) {\n first = c\n } else if (!cleanups) {\n cleanups = [first, c]\n } else {\n cleanups.push(c)\n }\n }\n }\n if (cleanups)\n return () => {\n for (const c of cleanups) c()\n }\n return first\n}\n\n/**\n * Apply a single prop.\n *\n * - `onXxx` → addEventListener\n * - `() => value` (non-event function) → reactive via effect\n * - anything else → static attribute / DOM property\n */\n/**\n * Bind an event handler (onClick → \"click\") with batching + delegation support.\n */\nfunction applyEventProp(el: Element, key: string, value: unknown): Cleanup | null {\n if (__DEV__ && typeof value !== \"function\") {\n console.warn(\n `[Pyreon] Event handler \"${key}\" received a non-function value (${typeof value}). ` +\n `Expected a function. Did you mean ${key}={() => ...}?`,\n )\n return null\n }\n const eventName = key[2]?.toLowerCase() + key.slice(3)\n const handler = value as EventListener\n\n if (DELEGATED_EVENTS.has(eventName)) {\n const prop = delegatedPropName(eventName)\n ;(el as unknown as Record<string, unknown>)[prop] = (e: Event) => batch(() => handler(e))\n return () => {\n ;(el as unknown as Record<string, unknown>)[prop] = undefined\n }\n }\n\n const batched: EventListener = (e) => batch(() => handler(e))\n el.addEventListener(eventName, batched)\n return () => el.removeEventListener(eventName, batched)\n}\n\nexport function applyProp(el: Element, key: string, value: unknown): Cleanup | null {\n // Event listener: onClick → \"click\"\n if (EVENT_RE.test(key)) return applyEventProp(el, key, value)\n\n // innerHTML — sanitized via Sanitizer API or fallback allowlist sanitizer\n if (key === \"innerHTML\") {\n if (typeof (el as HTMLElement & { setHTML?: (h: string) => void }).setHTML === \"function\") {\n ;(el as HTMLElement & { setHTML: (h: string) => void }).setHTML(value as string)\n } else {\n ;(el as HTMLElement).innerHTML = sanitizeHtml(value as string)\n }\n return null\n }\n // dangerouslySetInnerHTML — intentionally raw, developer owns sanitization (same as React)\n if (key === \"dangerouslySetInnerHTML\") {\n if (__DEV__) {\n console.warn(\n \"[Pyreon] dangerouslySetInnerHTML bypasses sanitization. Ensure the HTML is trusted.\",\n )\n }\n ;(el as HTMLElement).innerHTML = (value as { __html: string }).__html\n return null\n }\n\n // Reactive prop — function that returns the actual value\n // Uses renderEffect (lighter than effect — no scope registration, no WeakMap)\n // since lifecycle is managed by mountElement's cleanup array.\n if (typeof value === \"function\") {\n const dispose = renderEffect(() => setStaticProp(el, key, (value as () => unknown)()))\n return dispose\n }\n\n setStaticProp(el, key, value)\n return null\n}\n\n// Attributes that carry URLs and must be guarded against javascript:/data: injection.\nconst URL_ATTRS = new Set([\"href\", \"src\", \"action\", \"formaction\", \"poster\", \"cite\", \"data\"])\nconst UNSAFE_URL_RE = /^\\s*(?:javascript|data):/i\n\n/** Apply a style prop (string or object). */\nfunction applyStyleProp(el: HTMLElement, value: unknown): void {\n if (typeof value === \"string\") {\n el.style.cssText = value\n } else if (value != null && typeof value === \"object\") {\n const obj = value as Record<string, unknown>\n for (const k in obj) {\n const css = normalizeStyleValue(k, obj[k])\n el.style.setProperty(k.startsWith(\"--\") ? k : toKebabCase(k), css)\n }\n }\n}\n\nfunction applyClassProp(el: Element, value: unknown): void {\n const resolved = typeof value === \"string\" ? value : cx(value as ClassValue)\n el.setAttribute(\"class\", resolved || \"\")\n}\n\nfunction setStaticProp(el: Element, key: string, value: unknown): void {\n // Block javascript:/data: URI injection in URL-bearing attributes.\n if (URL_ATTRS.has(key) && typeof value === \"string\" && UNSAFE_URL_RE.test(value)) {\n if (__DEV__) {\n console.warn(`[Pyreon] Blocked unsafe URL in \"${key}\" attribute: ${value}`)\n }\n return\n }\n\n if (key === \"class\" || key === \"className\") {\n applyClassProp(el, value)\n return\n }\n\n if (key === \"style\") {\n applyStyleProp(el as HTMLElement, value)\n return\n }\n\n if (value == null) {\n el.removeAttribute(key)\n return\n }\n\n if (typeof value === \"boolean\") {\n if (value) el.setAttribute(key, \"\")\n else el.removeAttribute(key)\n return\n }\n\n if (key in el) {\n ;(el as unknown as Record<string, unknown>)[key] = value\n return\n }\n\n el.setAttribute(key, String(value))\n}\n","import type {\n ComponentFn,\n ForProps,\n NativeItem,\n PortalProps,\n RefProp,\n VNode,\n VNodeChild,\n} from \"@pyreon/core\"\nimport {\n dispatchToErrorBoundary,\n EMPTY_PROPS,\n ForSymbol,\n Fragment,\n PortalSymbol,\n propagateError,\n reportError,\n runWithHooks,\n} from \"@pyreon/core\"\nimport { effectScope, renderEffect, runUntracked, setCurrentScope } from \"@pyreon/reactivity\"\nimport { registerComponent, unregisterComponent } from \"./devtools\"\nimport { mountFor, mountKeyedList, mountReactive } from \"./nodes\"\nimport { applyProps } from \"./props\"\n\nconst __DEV__ = typeof process !== \"undefined\" && process.env.NODE_ENV !== \"production\"\n\ntype Cleanup = () => void\nconst noop: Cleanup = () => {\n /* noop */\n}\n\n// When > 0, we're mounting children inside an element — child cleanups can skip\n// DOM removal (parent element removal handles it). This avoids allocating a\n// removeChild closure for every nested element that has no reactive work.\nlet _elementDepth = 0\n\n// Stack tracking which component is currently being mounted (depth-first order).\n// Used to infer parent/child relationships for DevTools.\nconst _mountingStack: string[] = []\n\n/**\n * Mount a single child into `parent`, inserting before `anchor` (null = append).\n * Returns a cleanup that removes the node(s) and disposes all reactive effects.\n *\n * This function is the hot path — all child types are handled inline to avoid\n * function call overhead in tight render loops (1000+ calls per list render).\n */\nexport function mountChild(\n child: VNodeChild | VNodeChild[] | (() => VNodeChild | VNodeChild[]),\n parent: Node,\n anchor: Node | null = null,\n): Cleanup {\n // Reactive accessor — function that reads signals\n if (typeof child === \"function\") {\n const sample = runUntracked(() => (child as () => VNodeChild | VNodeChild[])())\n if (isKeyedArray(sample)) {\n const prevDepth = _elementDepth\n _elementDepth = 0\n const cleanup = mountKeyedList(child as () => VNode[], parent, anchor, (v, p, a) =>\n mountChild(v, p, a),\n )\n _elementDepth = prevDepth\n return cleanup\n }\n // Text fast path: reactive string/number/boolean — update text.data in-place\n if (typeof sample === \"string\" || typeof sample === \"number\" || typeof sample === \"boolean\") {\n const text = document.createTextNode(sample == null || sample === false ? \"\" : String(sample))\n parent.insertBefore(text, anchor)\n const dispose = renderEffect(() => {\n const v = (child as () => unknown)()\n text.data = v == null || v === false ? \"\" : String(v as string | number)\n })\n if (_elementDepth > 0) return dispose\n return () => {\n dispose()\n const p = text.parentNode\n if (p && (p as Element).isConnected !== false) p.removeChild(text)\n }\n }\n const prevDepth = _elementDepth\n _elementDepth = 0\n const cleanup = mountReactive(child as () => VNodeChild, parent, anchor, mountChild)\n _elementDepth = prevDepth\n return cleanup\n }\n\n // Array of children (e.g. from .map())\n if (Array.isArray(child)) return mountChildren(child, parent, anchor)\n\n // Nothing to render\n if (child == null || child === false) return noop\n\n // Primitive — text node (static, no reactive effects to tear down).\n if (typeof child !== \"object\") {\n parent.insertBefore(document.createTextNode(String(child)), anchor)\n return noop\n }\n\n // NativeItem — pre-built DOM element from _tpl() or createTemplate().\n if ((child as unknown as NativeItem).__isNative) {\n const native = child as unknown as NativeItem\n parent.insertBefore(native.el, anchor)\n if (!native.cleanup) {\n if (_elementDepth > 0) return noop\n return () => {\n const p = native.el.parentNode\n if (p && (p as Element).isConnected !== false) p.removeChild(native.el)\n }\n }\n if (_elementDepth > 0) return native.cleanup\n return () => {\n native.cleanup?.()\n const p = native.el.parentNode\n if (p && (p as Element).isConnected !== false) p.removeChild(native.el)\n }\n }\n\n // VNode — element, component, fragment, For, Portal\n const vnode = child as VNode\n\n if (vnode.type === Fragment) return mountChildren(vnode.children, parent, anchor)\n\n if (vnode.type === (ForSymbol as unknown as string)) {\n const { each, by, children } = vnode.props as unknown as ForProps<unknown>\n const prevDepth = _elementDepth\n _elementDepth = 0\n const cleanup = mountFor(each, by, children, parent, anchor, mountChild)\n _elementDepth = prevDepth\n return cleanup\n }\n\n if (vnode.type === (PortalSymbol as unknown as string)) {\n const { target, children } = vnode.props as unknown as PortalProps\n if (__DEV__ && !target) {\n console.warn(\"[Pyreon] <Portal> received a falsy `target`. Provide a valid DOM element.\")\n return noop\n }\n if (__DEV__ && !(target instanceof Node)) {\n console.warn(\n `[Pyreon] <Portal> target must be a DOM node. Received ${typeof target}. ` +\n \"Use document.getElementById() or a ref to get the target element.\",\n )\n }\n return mountChild(children, target, null)\n }\n\n if (typeof vnode.type === \"function\") {\n return mountComponent(vnode as VNode & { type: ComponentFn }, parent, anchor)\n }\n\n if (__DEV__ && typeof vnode.type !== \"string\") {\n console.warn(\n `[Pyreon] Invalid VNode type: expected a string tag or component function, ` +\n `received ${typeof vnode.type} (${String(vnode.type)}). ` +\n `This usually means you passed an object or class instead of a component function.`,\n )\n return noop\n }\n\n return mountElement(vnode, parent, anchor)\n}\n\n// ─── Element ─────────────────────────────────────────────────────────────────\n\n// Void elements that cannot have children\nconst VOID_ELEMENTS = new Set([\n \"area\",\n \"base\",\n \"br\",\n \"col\",\n \"embed\",\n \"hr\",\n \"img\",\n \"input\",\n \"link\",\n \"meta\",\n \"param\",\n \"source\",\n \"track\",\n \"wbr\",\n])\n\nfunction mountElement(vnode: VNode, parent: Node, anchor: Node | null): Cleanup {\n const el = document.createElement(vnode.type as string)\n\n if (__DEV__ && vnode.children.length > 0 && VOID_ELEMENTS.has(vnode.type as string)) {\n console.warn(\n `[Pyreon] <${vnode.type as string}> is a void element and cannot have children. ` +\n \"Children passed to void elements will be ignored by the browser.\",\n )\n }\n\n // Skip applyProps entirely when props is the shared empty sentinel (identity check — no allocation)\n const props = vnode.props\n const propCleanup: Cleanup | null = props !== EMPTY_PROPS ? applyProps(el, props) : null\n\n // Mount children inside element context — nested elements can skip DOM removal closures\n _elementDepth++\n const childCleanup = mountChildren(vnode.children, el, null)\n _elementDepth--\n\n parent.insertBefore(el, anchor)\n\n // Populate ref after the element is in the DOM\n const ref = props.ref as RefProp<Element> | null | undefined\n if (ref) {\n if (typeof ref === \"function\") ref(el)\n else ref.current = el\n }\n\n if (!propCleanup && childCleanup === noop && !ref) {\n if (_elementDepth > 0) return noop\n return () => {\n const p = el.parentNode\n if (p && (p as Element).isConnected !== false) p.removeChild(el)\n }\n }\n\n if (_elementDepth > 0) {\n if (!ref && !propCleanup) return childCleanup\n if (!ref && propCleanup)\n return () => {\n propCleanup()\n childCleanup()\n }\n const refToClean = ref\n return () => {\n if (refToClean && typeof refToClean === \"object\") refToClean.current = null\n if (propCleanup) propCleanup()\n childCleanup()\n }\n }\n\n return () => {\n if (ref && typeof ref === \"object\") ref.current = null\n if (propCleanup) propCleanup()\n childCleanup()\n const p = el.parentNode\n if (p && (p as Element).isConnected !== false) p.removeChild(el)\n }\n}\n\n// ─── Component ───────────────────────────────────────────────────────────────\n\nfunction mountComponent(\n vnode: VNode & { type: ComponentFn },\n parent: Node,\n anchor: Node | null,\n): Cleanup {\n const scope = effectScope()\n setCurrentScope(scope)\n\n let hooks: ReturnType<typeof runWithHooks>[\"hooks\"]\n let output: VNodeChild\n\n const componentName = (vnode.type.name || \"Anonymous\") as string\n const compId = `${componentName}-${Math.random().toString(36).slice(2, 9)}`\n const parentId = _mountingStack[_mountingStack.length - 1] ?? null\n _mountingStack.push(compId)\n\n // Merge vnode.children into props.children if not already set\n const mergedProps =\n vnode.children.length > 0 && (vnode.props as Record<string, unknown>).children === undefined\n ? {\n ...vnode.props,\n children: vnode.children.length === 1 ? vnode.children[0] : vnode.children,\n }\n : vnode.props\n\n try {\n const result = runWithHooks(vnode.type, mergedProps)\n hooks = result.hooks\n output = result.vnode\n } catch (err) {\n _mountingStack.pop()\n setCurrentScope(null)\n scope.stop()\n reportError({\n component: componentName,\n phase: \"setup\",\n error: err,\n timestamp: Date.now(),\n props: vnode.props as Record<string, unknown>,\n })\n const handled = dispatchToErrorBoundary(err)\n if (!handled) {\n console.error(`[Pyreon] <${componentName}> threw during setup:`, err)\n }\n return noop\n } finally {\n setCurrentScope(null)\n }\n\n if (__DEV__ && output != null && typeof output === \"object\") {\n if (output instanceof Promise) {\n console.warn(\n `[Pyreon] Component <${componentName}> returned a Promise. ` +\n \"Components must be synchronous — use lazy() + Suspense for async loading, \" +\n \"or fetch data in onMount and store it in a signal.\",\n )\n } else if (!(\"type\" in output)) {\n console.warn(\n `[Pyreon] Component <${componentName}> returned an invalid value. Components must return a VNode, string, null, or function.`,\n )\n }\n }\n\n for (const fn of hooks.update) {\n scope.addUpdateHook(fn)\n }\n\n let subtreeCleanup: Cleanup = noop\n try {\n subtreeCleanup = output != null ? mountChild(output, parent, anchor) : noop\n } catch (err) {\n _mountingStack.pop()\n scope.stop()\n const handled = propagateError(err, hooks) || dispatchToErrorBoundary(err)\n if (!handled) {\n reportError({\n component: componentName,\n phase: \"render\",\n error: err,\n timestamp: Date.now(),\n props: vnode.props as Record<string, unknown>,\n })\n console.error(`[Pyreon] <${componentName}> threw during render:`, err)\n }\n return noop\n }\n\n _mountingStack.pop()\n\n const firstEl = parent instanceof Element ? parent.firstElementChild : null\n registerComponent(compId, componentName, firstEl, parentId)\n\n // Fire onMount hooks inline — effects created inside are tracked by the scope\n const mountCleanups: Cleanup[] = []\n for (const fn of hooks.mount) {\n try {\n let cleanup: (() => void) | undefined\n scope.runInScope(() => {\n cleanup = fn() as (() => void) | undefined\n })\n if (cleanup) mountCleanups.push(cleanup)\n } catch (err) {\n console.error(`[Pyreon] Error in onMount hook of <${componentName}>:`, err)\n reportError({ component: componentName, phase: \"mount\", error: err, timestamp: Date.now() })\n }\n }\n\n return () => {\n unregisterComponent(compId)\n scope.stop()\n subtreeCleanup()\n for (const fn of hooks.unmount) {\n try {\n fn()\n } catch (err) {\n console.error(`[Pyreon] Error in onUnmount hook of <${componentName}>:`, err)\n reportError({\n component: componentName,\n phase: \"unmount\",\n error: err,\n timestamp: Date.now(),\n })\n }\n }\n for (const fn of mountCleanups) fn()\n }\n}\n\n// ─── Children ────────────────────────────────────────────────────────────────\n\nfunction mountChildren(children: VNodeChild[], parent: Node, anchor: Node | null): Cleanup {\n if (children.length === 0) return noop\n\n // 1-child fast path\n if (children.length === 1) {\n const c = children[0] as VNodeChild\n if (c !== undefined) {\n if (anchor === null && (typeof c === \"string\" || typeof c === \"number\")) {\n ;(parent as HTMLElement).textContent = String(c)\n return noop\n }\n return mountChild(c, parent, anchor)\n }\n }\n\n // 2-child fast path — avoids .map() allocation (covers <tr><td/><td/></tr>)\n if (children.length === 2) {\n const c0 = children[0] as VNodeChild\n const c1 = children[1] as VNodeChild\n if (c0 !== undefined && c1 !== undefined) {\n const d0 = mountChild(c0, parent, anchor)\n const d1 = mountChild(c1, parent, anchor)\n if (d0 === noop && d1 === noop) return noop\n if (d0 === noop) return d1\n if (d1 === noop) return d0\n return () => {\n d0()\n d1()\n }\n }\n }\n\n const cleanups = children.map((c) => mountChild(c, parent, anchor))\n return () => {\n for (const fn of cleanups) fn()\n }\n}\n\n// ─── Keyed array detection ────────────────────────────────────────────────────\n\n/** Returns true if value is a non-empty array of VNodes that all carry keys. */\nfunction isKeyedArray(value: unknown): value is VNode[] {\n if (!Array.isArray(value) || value.length === 0) return false\n return value.every(\n (v) =>\n v !== null &&\n typeof v === \"object\" &&\n !Array.isArray(v) &&\n (v as VNode).key !== null &&\n (v as VNode).key !== undefined,\n )\n}\n","/**\n * SSR Hydration — \"walk-and-claim\" strategy.\n *\n * The server renders plain HTML (no special markers needed). On the client,\n * hydrateRoot walks the VNode tree in parallel with the live DOM tree and:\n *\n * - Static elements → matched by tag position, props attached (events + reactive effects)\n * - Static text → existing text node reused\n * - Reactive text → existing text node found, reactive effect attached to .data\n * - Reactive blocks → comment marker inserted, mountReactive takes over\n * - Components → component fn called, output VNode matched against DOM subtree\n * - For lists → full remount (can't map keys to DOM without SSR markers)\n * - Fragment → transparent, children matched directly\n * - Portal → always remounts into target\n *\n * Falls back to mountChild() whenever DOM structure doesn't match the VNode.\n */\n\nimport type { ComponentFn, Ref, VNode, VNodeChild } from \"@pyreon/core\"\nimport {\n dispatchToErrorBoundary,\n ForSymbol,\n Fragment,\n PortalSymbol,\n reportError,\n runWithHooks,\n} from \"@pyreon/core\"\nimport { effectScope, renderEffect, runUntracked, setCurrentScope } from \"@pyreon/reactivity\"\nimport { setupDelegation } from \"./delegate\"\nimport { warnHydrationMismatch } from \"./hydration-debug\"\nimport { mountChild } from \"./mount\"\nimport { mountReactive } from \"./nodes\"\nimport { applyProps } from \"./props\"\n\ntype Cleanup = () => void\nconst noop: Cleanup = () => {\n /* noop */\n}\n\n// ─── DOM cursor helpers ───────────────────────────────────────────────────────\n\n/** Skip comment and whitespace-only text nodes, return first \"real\" node */\nfunction firstReal(initialNode: ChildNode | null): ChildNode | null {\n let node = initialNode\n while (node) {\n if (node.nodeType === Node.COMMENT_NODE) {\n node = node.nextSibling\n continue\n }\n if (node.nodeType === Node.TEXT_NODE && isWhitespaceOnly((node as Text).data)) {\n node = node.nextSibling\n continue\n }\n return node\n }\n return null\n}\n\n/** Check if a string is whitespace-only without allocating a trimmed copy. */\nfunction isWhitespaceOnly(s: string): boolean {\n for (let i = 0; i < s.length; i++) {\n const c = s.charCodeAt(i)\n // space, tab, newline, carriage return, form feed\n if (c !== 32 && c !== 9 && c !== 10 && c !== 13 && c !== 12) return false\n }\n return true\n}\n\n/** Advance past a node, skipping whitespace-only text and comments */\nfunction nextReal(node: ChildNode): ChildNode | null {\n return firstReal(node.nextSibling)\n}\n\n// ─── Core recursive walker ────────────────────────────────────────────────────\n\n/**\n * Hydrate a single VNodeChild against the DOM subtree starting at `domNode`.\n * Returns [cleanup, nextDomSibling].\n */\n/** Insert a comment marker before domNode (or append if domNode is null). */\nfunction insertMarker(parent: Node, domNode: ChildNode | null, text: string): Comment {\n const marker = document.createComment(text)\n if (domNode) {\n parent.insertBefore(marker, domNode)\n } else {\n parent.appendChild(marker)\n }\n return marker\n}\n\n/** Hydrate a reactive accessor (function child). */\nfunction hydrateReactiveChild(\n child: () => VNodeChild,\n domNode: ChildNode | null,\n parent: Node,\n anchor: Node | null,\n path: string,\n): [Cleanup, ChildNode | null] {\n const initial = runUntracked(child)\n\n if (initial == null || initial === false) {\n const marker = insertMarker(parent, domNode, \"pyreon\")\n const cleanup = mountReactive(child, parent, marker, mountChild)\n return [cleanup, domNode]\n }\n\n if (typeof initial === \"string\" || typeof initial === \"number\" || typeof initial === \"boolean\") {\n return hydrateReactiveText(\n child as () => string | number | boolean | null | undefined,\n domNode,\n parent,\n anchor,\n path,\n )\n }\n\n const marker = insertMarker(parent, domNode, \"pyreon\")\n const cleanup = mountReactive(child, parent, marker, mountChild)\n const next = domNode ? nextReal(domNode) : null\n return [cleanup, next]\n}\n\n/** Hydrate a reactive text binding against an existing text node. */\nfunction hydrateReactiveText(\n child: () => string | number | boolean | null | undefined,\n domNode: ChildNode | null,\n parent: Node,\n anchor: Node | null,\n path: string,\n): [Cleanup, ChildNode | null] {\n if (domNode?.nodeType === Node.TEXT_NODE) {\n const textNode = domNode as Text\n const dispose = renderEffect(() => {\n const v = child()\n textNode.data = v == null ? \"\" : String(v)\n })\n return [dispose, nextReal(domNode)]\n }\n warnHydrationMismatch(\"text\", \"TextNode\", domNode?.nodeType ?? \"null\", `${path} > reactive`)\n const cleanup = mountChild(child, parent, anchor)\n return [cleanup, domNode]\n}\n\n/** Hydrate a VNode (fragment, For, Portal, component, element). */\nfunction hydrateVNode(\n vnode: VNode,\n domNode: ChildNode | null,\n parent: Node,\n anchor: Node | null,\n path: string,\n): [Cleanup, ChildNode | null] {\n if (vnode.type === Fragment) {\n return hydrateChildren(vnode.children, domNode, parent, anchor, path)\n }\n\n if (vnode.type === ForSymbol) {\n const marker = insertMarker(parent, domNode, \"pyreon-for\")\n const cleanup = mountChild(vnode, parent, marker)\n return [cleanup, null]\n }\n\n if (vnode.type === PortalSymbol) {\n const cleanup = mountChild(vnode, parent, anchor)\n return [cleanup, domNode]\n }\n\n if (typeof vnode.type === \"function\") {\n return hydrateComponent(vnode, domNode, parent, anchor, path)\n }\n\n if (typeof vnode.type === \"string\") {\n return hydrateElement(vnode, domNode, parent, anchor, path)\n }\n\n return [noop, domNode]\n}\n\nfunction hydrateChild(\n child: VNodeChild | VNodeChild[],\n domNode: ChildNode | null,\n parent: Node,\n anchor: Node | null,\n path = \"root\",\n): [Cleanup, ChildNode | null] {\n if (Array.isArray(child)) {\n const cleanups: Cleanup[] = []\n let cursor = domNode\n for (const c of child) {\n const [cleanup, next] = hydrateChild(c, cursor, parent, anchor, path)\n cleanups.push(cleanup)\n cursor = next\n }\n return [\n () => {\n for (const c of cleanups) c()\n },\n cursor,\n ]\n }\n\n if (child == null || child === false) return [noop, domNode]\n\n if (typeof child === \"function\") {\n return hydrateReactiveChild(child as () => VNodeChild, domNode, parent, anchor, path)\n }\n\n if (typeof child === \"string\" || typeof child === \"number\") {\n if (domNode?.nodeType === Node.TEXT_NODE) {\n return [() => (domNode as Text).remove(), nextReal(domNode)]\n }\n warnHydrationMismatch(\"text\", \"TextNode\", domNode?.nodeType ?? \"null\", `${path} > text`)\n const cleanup = mountChild(child, parent, anchor)\n return [cleanup, domNode]\n }\n\n return hydrateVNode(child as VNode, domNode, parent, anchor, path)\n}\n\n// ─── Element hydration ────────────────────────────────────────────────────────\n\nfunction hydrateElement(\n vnode: VNode,\n domNode: ChildNode | null,\n parent: Node,\n anchor: Node | null,\n path = \"root\",\n): [Cleanup, ChildNode | null] {\n const elPath = `${path} > ${vnode.type as string}`\n\n // Check if existing DOM node matches\n if (\n domNode?.nodeType === Node.ELEMENT_NODE &&\n (domNode as Element).tagName.toLowerCase() === vnode.type\n ) {\n const el = domNode as Element\n const cleanups: Cleanup[] = []\n\n // Attach props (events + reactive effects) — don't set static attrs (SSR already did)\n const propCleanup = applyProps(el, vnode.props)\n if (propCleanup) cleanups.push(propCleanup)\n\n // Hydrate children\n const firstChild = firstReal(el.firstChild as ChildNode | null)\n const [childCleanup] = hydrateChildren(vnode.children, firstChild, el, null, elPath)\n cleanups.push(childCleanup)\n\n // Set ref\n const ref = vnode.props.ref as Ref<Element> | ((el: Element) => void) | undefined\n if (ref) {\n if (typeof ref === \"function\") ref(el)\n else ref.current = el\n }\n\n const cleanup = () => {\n if (ref && typeof ref === \"object\") ref.current = null\n for (const c of cleanups) c()\n el.remove()\n }\n\n return [cleanup, nextReal(domNode)]\n }\n\n // Mismatch — fall back to fresh mount\n const actual =\n domNode?.nodeType === Node.ELEMENT_NODE\n ? (domNode as Element).tagName.toLowerCase()\n : (domNode?.nodeType ?? \"null\")\n warnHydrationMismatch(\"tag\", vnode.type, actual, elPath)\n const cleanup = mountChild(vnode, parent, anchor)\n return [cleanup, domNode]\n}\n\n// ─── Children hydration ───────────────────────────────────────────────────────\n\nfunction hydrateChildren(\n children: VNodeChild[],\n domNode: ChildNode | null,\n parent: Node,\n anchor: Node | null,\n path = \"root\",\n): [Cleanup, ChildNode | null] {\n if (children.length === 0) return [noop, domNode]\n\n // Single-child fast path — avoids cleanups array allocation\n if (children.length === 1) {\n return hydrateChild(children[0] as VNodeChild, domNode, parent, anchor, path)\n }\n\n const cleanups: Cleanup[] = []\n let cursor = domNode\n for (const child of children) {\n const [cleanup, next] = hydrateChild(child, cursor, parent, anchor, path)\n cleanups.push(cleanup)\n cursor = next\n }\n return [\n () => {\n for (const c of cleanups) c()\n },\n cursor,\n ]\n}\n\n// ─── Component hydration ──────────────────────────────────────────────────────\n\nfunction hydrateComponent(\n vnode: VNode,\n domNode: ChildNode | null,\n parent: Node,\n anchor: Node | null,\n path = \"root\",\n): [Cleanup, ChildNode | null] {\n const scope = effectScope()\n setCurrentScope(scope)\n\n let subtreeCleanup: Cleanup = noop\n const mountCleanups: Cleanup[] = []\n let nextDom: ChildNode | null = domNode\n\n // Function.name is always a string per spec; || handles empty string, avoids uncoverable ?? branch\n const componentName = ((vnode.type as ComponentFn).name || \"Anonymous\") as string\n const mergedProps =\n vnode.children.length > 0 && (vnode.props as Record<string, unknown>).children === undefined\n ? {\n ...vnode.props,\n children: vnode.children.length === 1 ? vnode.children[0] : vnode.children,\n }\n : vnode.props\n\n let result: ReturnType<typeof runWithHooks>\n try {\n result = runWithHooks(vnode.type as ComponentFn, mergedProps)\n } catch (err) {\n setCurrentScope(null)\n scope.stop()\n\n console.error(`[Pyreon] Error hydrating component <${componentName}>:`, err)\n reportError({\n component: componentName,\n phase: \"setup\",\n error: err,\n timestamp: Date.now(),\n props: vnode.props as Record<string, unknown>,\n })\n dispatchToErrorBoundary(err)\n return [noop, domNode]\n }\n setCurrentScope(null)\n\n const { vnode: output, hooks } = result\n\n // Register onUpdate hooks with the scope\n for (const fn of hooks.update) {\n scope.addUpdateHook(fn)\n }\n\n if (output != null) {\n const [childCleanup, next] = hydrateChild(output, domNode, parent, anchor, path)\n subtreeCleanup = childCleanup\n nextDom = next\n }\n\n // Fire onMount hooks; effects created inside are tracked by the scope via runInScope\n for (const fn of hooks.mount) {\n try {\n let c: (() => void) | undefined\n scope.runInScope(() => {\n c = fn() as (() => void) | undefined\n })\n if (c) mountCleanups.push(c)\n } catch (err) {\n reportError({ component: componentName, phase: \"mount\", error: err, timestamp: Date.now() })\n }\n }\n\n const cleanup: Cleanup = () => {\n scope.stop()\n subtreeCleanup()\n for (const fn of hooks.unmount) fn()\n for (const fn of mountCleanups) fn()\n }\n\n return [cleanup, nextDom]\n}\n\n// ─── Public API ───────────────────────────────────────────────────────────────\n\n/**\n * Hydrate a server-rendered container with a Pyreon VNode tree.\n *\n * Reuses existing DOM elements for static structure, attaches event listeners\n * and reactive effects without re-rendering. Falls back to fresh mount for\n * dynamic content (reactive conditionals, For lists).\n *\n * @example\n * // Server:\n * const html = await renderToString(h(App, null))\n *\n * // Client:\n * const unmount = hydrateRoot(document.getElementById(\"app\")!, h(App, null))\n */\nexport function hydrateRoot(container: Element, vnode: VNodeChild): () => void {\n setupDelegation(container)\n const firstChild = firstReal(container.firstChild as ChildNode | null)\n const [cleanup] = hydrateChild(vnode, firstChild, container, null)\n return cleanup\n}\n","import type { Props, VNodeChild } from \"@pyreon/core\"\nimport { createRef, h, onMount } from \"@pyreon/core\"\nimport { effect } from \"@pyreon/reactivity\"\nimport { mountChild } from \"./mount\"\n\nexport interface KeepAliveProps extends Props {\n /**\n * Accessor that returns true when this slot's children should be visible.\n * When false, children are CSS-hidden but remain mounted — effects and\n * signals stay alive.\n * Defaults to true (always visible / always mounted).\n */\n active?: () => boolean\n children?: VNodeChild\n}\n\n/**\n * KeepAlive — mounts its children once and keeps them alive even when hidden.\n *\n * Unlike conditional rendering (which destroys and recreates component state),\n * KeepAlive CSS-hides the children while preserving all reactive state,\n * scroll position, form values, and in-flight async operations.\n *\n * Children are mounted imperatively on first activation and are never unmounted\n * while the KeepAlive itself is mounted.\n *\n * Multi-slot pattern (one KeepAlive per route):\n * @example\n * h(Fragment, null, [\n * h(KeepAlive, { active: () => route() === \"/a\" }, h(RouteA, null)),\n * h(KeepAlive, { active: () => route() === \"/b\" }, h(RouteB, null)),\n * ])\n *\n * With JSX:\n * @example\n * <>\n * <KeepAlive active={() => route() === \"/a\"}><RouteA /></KeepAlive>\n * <KeepAlive active={() => route() === \"/b\"}><RouteB /></KeepAlive>\n * </>\n */\nexport function KeepAlive(props: KeepAliveProps): VNodeChild {\n const containerRef = createRef<HTMLElement>()\n let childCleanup: (() => void) | null = null\n let childMounted = false\n\n onMount(() => {\n const container = containerRef.current as HTMLElement\n\n const e = effect(() => {\n const isActive = props.active?.() ?? true\n\n if (!childMounted) {\n // Mount children into the container div exactly once\n childCleanup = mountChild(props.children ?? null, container, null)\n childMounted = true\n }\n\n // Show/hide without unmounting — state is fully preserved\n container.style.display = isActive ? \"\" : \"none\"\n })\n\n return () => {\n e.dispose()\n childCleanup?.()\n }\n })\n\n // `display: contents` makes the wrapper transparent to layout\n // (children appear as if directly in the parent flow)\n return h(\"div\", { ref: containerRef, style: \"display: contents\" })\n}\n","import type { NativeItem } from \"@pyreon/core\"\nimport { renderEffect } from \"@pyreon/reactivity\"\n\n/**\n * Creates a row/item factory backed by HTML template cloning.\n *\n * - The HTML string is parsed exactly once via <template>.innerHTML.\n * - Each call to the returned factory clones the root element via\n * cloneNode(true) — ~5-10x faster than createElement + setAttribute.\n * - `bind` receives the cloned element and the item; it should wire up\n * reactive effects and return a cleanup function.\n * - Returns a NativeItem directly (no VNode wrapper) — saves 2 allocations\n * per row vs the old VNode + props-object + children-array approach.\n *\n * @example\n * const rowTemplate = createTemplate<Row>(\n * \"<tr><td></td><td></td></tr>\",\n * (el, row) => {\n * const td1 = el.firstChild as HTMLElement\n * const td2 = td1.nextSibling as HTMLElement\n * td1.textContent = String(row.id)\n * const text = td2.firstChild as Text\n * text.data = row.label()\n * const unsub = row.label.subscribe(() => { text.data = row.label() })\n * return unsub\n * }\n * )\n */\nexport function createTemplate<T>(\n html: string,\n bind: (el: HTMLElement, item: T) => (() => void) | null,\n): (item: T) => NativeItem {\n const tmpl = document.createElement(\"template\")\n tmpl.innerHTML = html\n const proto = tmpl.content.firstElementChild as HTMLElement\n\n return (item: T): NativeItem => {\n const el = proto.cloneNode(true) as HTMLElement\n const cleanup = bind(el, item)\n return { __isNative: true, el, cleanup }\n }\n}\n\n// ─── Direct text binding (bypasses effect system) ────────────────────────────\n\n/**\n * Compiler-emitted direct text binding for single-signal text nodes.\n *\n * When the compiler detects `{signal()}` as the only reactive expression\n * in a text binding, it emits `_bindText(signal, textNode)` instead of\n * `_bind(() => { textNode.data = signal() })`.\n *\n * This bypasses the effect system entirely:\n * - No deps array allocation\n * - No withTracking / setDepsCollector overhead\n * - No `run` closure\n * - Signal.subscribe is used directly (O(1) subscribe + unsubscribe)\n *\n * @param source - A signal (anything with `._v` and `.direct`)\n * @param node - The Text node to update\n */\nexport function _bindText(\n source: { _v?: unknown; direct?: (fn: () => void) => () => void },\n node: Text,\n): () => void {\n // Fast path: source has .direct() (signal or computed)\n if (source.direct) {\n const textUpdate = () => {\n const v = source._v\n node.data = v == null || v === false ? \"\" : String(v as string | number)\n }\n textUpdate()\n return source.direct(textUpdate)\n }\n // Fallback: source is a plain callable (e.g. store getter, createMachine) — use renderEffect\n const fn = source as unknown as () => unknown\n return renderEffect(() => {\n const v = fn()\n node.data = v == null || v === false ? \"\" : String(v as string | number)\n })\n}\n\n// ─── Direct signal binding (bypasses effect system) ──────────────────────────\n\n/**\n * Compiler-emitted direct binding for single-signal reactive expressions.\n *\n * Like _bindText but for arbitrary DOM updates (attributes, className, style).\n * When the compiler detects that a reactive expression depends on exactly one\n * signal call, it emits `_bindDirect(signal, updater)` instead of\n * `_bind(() => { updater() })`.\n *\n * Uses signal.direct() for zero-overhead registration:\n * - Flat array instead of Set (no hashing)\n * - Index-based disposal (no Set.delete)\n * - No deps array, no withTracking, no run closure\n *\n * @param source - A signal (anything with `._v` and `.direct`)\n * @param updater - Function that reads `source._v` and applies the DOM update\n */\nexport function _bindDirect(\n source: { _v?: unknown; direct?: (fn: () => void) => () => void },\n updater: (value: unknown) => void,\n): () => void {\n // Fast path: source has .direct() (signal or computed)\n if (source.direct) {\n updater(source._v)\n return source.direct(() => updater(source._v))\n }\n // Fallback: plain callable — use renderEffect\n const fn = source as unknown as () => unknown\n return renderEffect(() => updater(fn()))\n}\n\n// ─── Compiler-facing template API ─────────────────────────────────────────────\n\n// Cache parsed <template> elements by HTML string — parse once, clone many.\nconst _tplCache = new Map<string, HTMLTemplateElement>()\n\n/**\n * Compiler-emitted template instantiation.\n *\n * Parses `html` into a <template> element once (cached), then cloneNode(true)\n * for each call. The `bind` function wires up dynamic attributes, text content,\n * and event listeners on the cloned element tree. Returns a NativeItem that\n * mountChild can insert directly — no VNode allocation.\n *\n * This is the runtime half of the compiler's template optimisation. The compiler\n * detects static JSX element trees and emits `_tpl(html, bindFn)` instead of\n * nested `h()` calls. Benefits:\n * - cloneNode(true) is ~5-10x faster than sequential createElement + setAttribute\n * - Zero VNode / props-object / children-array allocations per instance\n * - Static attributes are baked into the HTML string (no runtime prop application)\n *\n * @example\n * // Compiler output for: <div class=\"box\"><span>{text()}</span></div>\n * _tpl('<div class=\"box\"><span></span></div>', (__root) => {\n * const __e0 = __root.children[0];\n * const __d0 = _re(() => { __e0.textContent = text(); });\n * return () => { __d0(); };\n * })\n */\nexport function _tpl(html: string, bind: (el: HTMLElement) => (() => void) | null): NativeItem {\n let tpl = _tplCache.get(html)\n if (!tpl) {\n tpl = document.createElement(\"template\")\n tpl.innerHTML = html\n _tplCache.set(html, tpl)\n }\n const el = tpl.content.firstElementChild?.cloneNode(true) as HTMLElement\n const cleanup = bind(el)\n return { __isNative: true, el, cleanup }\n}\n","import type { Props, VNode, VNodeChild } from \"@pyreon/core\"\nimport { createRef, Fragment, h, onUnmount } from \"@pyreon/core\"\nimport { effect, runUntracked, signal } from \"@pyreon/reactivity\"\n\nconst __DEV__ = typeof process !== \"undefined\" && process.env.NODE_ENV !== \"production\"\n\nexport interface TransitionProps {\n /**\n * CSS class name prefix.\n * \"fade\" → fade-enter-from, fade-enter-active, fade-enter-to, fade-leave-from, …\n * Default: \"pyreon\"\n */\n name?: string\n /** Reactive boolean controlling whether the child is shown. */\n show: () => boolean\n /**\n * If true, runs the enter transition on the initial mount (instead of\n * appearing immediately). Default: false.\n */\n appear?: boolean\n // Individual class name overrides (override the prefix-based defaults)\n enterFrom?: string\n enterActive?: string\n enterTo?: string\n leaveFrom?: string\n leaveActive?: string\n leaveTo?: string\n // Lifecycle callbacks\n onBeforeEnter?: (el: HTMLElement) => void\n onAfterEnter?: (el: HTMLElement) => void\n onBeforeLeave?: (el: HTMLElement) => void\n onAfterLeave?: (el: HTMLElement) => void\n /**\n * The single child element to animate.\n * Must be a direct DOM element VNode (not a component) for class injection to work.\n */\n children?: VNodeChild\n}\n\n/**\n * Transition — adds CSS enter/leave animation classes to a single child element,\n * controlled by the reactive `show` prop.\n *\n * Class lifecycle:\n * Enter: {name}-enter-from → (next frame) → {name}-enter-active + {name}-enter-to → cleanup\n * Leave: {name}-leave-from → (next frame) → {name}-leave-active + {name}-leave-to → unmount\n *\n * The child element stays in the DOM during the leave animation and is removed only\n * after the CSS transition / animation completes.\n *\n * @example\n * const visible = signal(false)\n *\n * h(Transition, { name: \"fade\", show: () => visible() },\n * h(\"div\", { class: \"modal\" }, \"content\")\n * )\n *\n * // CSS:\n * // .fade-enter-from, .fade-leave-to { opacity: 0; }\n * // .fade-enter-active, .fade-leave-active { transition: opacity 300ms ease; }\n */\nexport function Transition(props: TransitionProps): VNodeChild {\n const n = props.name ?? \"pyreon\"\n const cls = {\n ef: props.enterFrom ?? `${n}-enter-from`,\n ea: props.enterActive ?? `${n}-enter-active`,\n et: props.enterTo ?? `${n}-enter-to`,\n lf: props.leaveFrom ?? `${n}-leave-from`,\n la: props.leaveActive ?? `${n}-leave-active`,\n lt: props.leaveTo ?? `${n}-leave-to`,\n }\n\n // Ref injected into the child element so we can apply/remove classes\n const ref = createRef<HTMLElement>()\n const isMounted = signal(runUntracked<boolean>(props.show))\n\n // Cancel an in-progress leave when re-entering before the animation ends\n let pendingLeaveCancel: (() => void) | null = null\n let initialized = false\n\n const applyEnter = (el: HTMLElement) => {\n pendingLeaveCancel?.()\n pendingLeaveCancel = null\n props.onBeforeEnter?.(el)\n el.classList.remove(cls.lf, cls.la, cls.lt)\n el.classList.add(cls.ef, cls.ea)\n requestAnimationFrame(() => {\n el.classList.remove(cls.ef)\n el.classList.add(cls.et)\n const done = () => {\n // Remove both listeners — only one fires, so clean up the other\n el.removeEventListener(\"transitionend\", done)\n el.removeEventListener(\"animationend\", done)\n el.classList.remove(cls.ea, cls.et)\n props.onAfterEnter?.(el)\n }\n el.addEventListener(\"transitionend\", done, { once: true })\n el.addEventListener(\"animationend\", done, { once: true })\n })\n }\n\n const applyLeave = (el: HTMLElement) => {\n props.onBeforeLeave?.(el)\n el.classList.remove(cls.ef, cls.ea, cls.et)\n el.classList.add(cls.lf, cls.la)\n requestAnimationFrame(() => {\n el.classList.remove(cls.lf)\n el.classList.add(cls.lt)\n const done = () => {\n // Remove both listeners — only one fires, so clean up the other\n el.removeEventListener(\"transitionend\", done)\n el.removeEventListener(\"animationend\", done)\n el.classList.remove(cls.la, cls.lt)\n pendingLeaveCancel = null\n isMounted.set(false)\n props.onAfterLeave?.(el)\n }\n pendingLeaveCancel = () => {\n el.removeEventListener(\"transitionend\", done)\n el.removeEventListener(\"animationend\", done)\n el.classList.remove(cls.lf, cls.la, cls.lt)\n }\n el.addEventListener(\"transitionend\", done, { once: true })\n el.addEventListener(\"animationend\", done, { once: true })\n })\n }\n\n const handleVisibilityChange = (visible: boolean) => {\n if (visible) {\n if (!isMounted.peek()) isMounted.set(true)\n queueMicrotask(() => applyEnter(ref.current as HTMLElement))\n return\n }\n if (!isMounted.peek()) return\n const el = ref.current\n if (!el) {\n isMounted.set(false)\n return\n }\n applyLeave(el)\n }\n\n effect(() => {\n const visible = props.show()\n if (!initialized) {\n initialized = true\n if (visible && props.appear) {\n queueMicrotask(() => applyEnter(ref.current as HTMLElement))\n }\n return\n }\n handleVisibilityChange(visible)\n })\n\n onUnmount(() => {\n pendingLeaveCancel?.()\n pendingLeaveCancel = null\n })\n\n // Return a reactive getter. Each call clones the child VNode with our injected ref\n // so we can read / write classes on the underlying DOM element.\n const rawChild = props.children\n // Return an empty Fragment (not null) when unmounted so mountChild uses\n // mountReactive instead of the null/primitive text-node fast-path, which\n // cannot later be swapped for a VNode when the element enters.\n const emptyFragment = h(Fragment, null)\n return (() => {\n if (!isMounted()) return emptyFragment\n if (!rawChild || typeof rawChild !== \"object\" || Array.isArray(rawChild)) {\n return rawChild ?? null\n }\n const vnode = rawChild as VNode\n // Only inject ref into DOM element children — component children need ref forwarding\n if (typeof vnode.type !== \"string\") {\n if (__DEV__) {\n console.warn(\n \"[Pyreon] Transition child is a component. Wrap it in a DOM element for enter/leave animations to work.\",\n )\n }\n return vnode\n }\n return { ...vnode, props: { ...vnode.props, ref } as Props }\n }) as unknown as VNode\n}\n","import type { Props, VNode, VNodeChild } from \"@pyreon/core\"\nimport { createRef, h, onMount, onUnmount } from \"@pyreon/core\"\nimport { effect, runUntracked, signal } from \"@pyreon/reactivity\"\nimport { mountChild } from \"./mount\"\n\nexport interface TransitionGroupProps<T = unknown> {\n /** Wrapper element tag. Default: \"div\" */\n tag?: string\n /** CSS class prefix. Default: \"pyreon\" */\n name?: string\n /** Animate items on initial mount. Default: false */\n appear?: boolean\n // CSS class overrides\n enterFrom?: string\n enterActive?: string\n enterTo?: string\n leaveFrom?: string\n leaveActive?: string\n leaveTo?: string\n /** Class applied during FLIP move animation. Default: \"{name}-move\" */\n moveClass?: string\n /** Reactive list source */\n items: () => T[]\n /** Stable key extractor */\n keyFn: (item: T, index: number) => string | number\n /**\n * Render a single DOM-element VNode for each item.\n * Must return a VNode whose `type` is a string (e.g. \"div\", \"li\") so\n * the component can inject a ref and read the underlying DOM node.\n */\n render: (item: T, index: number) => VNode\n // Lifecycle callbacks\n onBeforeEnter?: (el: HTMLElement) => void\n onAfterEnter?: (el: HTMLElement) => void\n onBeforeLeave?: (el: HTMLElement) => void\n onAfterLeave?: (el: HTMLElement) => void\n}\n\ntype ItemEntry = {\n key: string | number\n ref: ReturnType<typeof createRef<HTMLElement>>\n cleanup: () => void\n leaving: boolean\n}\n\n/**\n * TransitionGroup — animates a keyed reactive list with CSS enter/leave and\n * FLIP move animations.\n *\n * Class lifecycle:\n * Enter: {name}-enter-from → {name}-enter-active + {name}-enter-to → cleanup\n * Leave: {name}-leave-from → {name}-leave-active + {name}-leave-to → item removed\n * Move: {name}-move (applied when an item shifts position)\n *\n * @example\n * const items = signal([{ id: 1 }, { id: 2 }])\n *\n * h(TransitionGroup, {\n * tag: \"ul\",\n * name: \"list\",\n * items,\n * keyFn: (item) => item.id,\n * render: (item) => h(\"li\", { class: \"item\" }, item.id),\n * })\n *\n * // CSS:\n * // .list-enter-from, .list-leave-to { opacity: 0; transform: translateY(-10px); }\n * // .list-enter-active, .list-leave-active { transition: all 300ms ease; }\n * // .list-move { transition: transform 300ms ease; }\n */\nexport function TransitionGroup<T = unknown>(props: TransitionGroupProps<T>): VNodeChild {\n const tag = props.tag ?? \"div\"\n const n = props.name ?? \"pyreon\"\n const cls = {\n ef: props.enterFrom ?? `${n}-enter-from`,\n ea: props.enterActive ?? `${n}-enter-active`,\n et: props.enterTo ?? `${n}-enter-to`,\n lf: props.leaveFrom ?? `${n}-leave-from`,\n la: props.leaveActive ?? `${n}-leave-active`,\n lt: props.leaveTo ?? `${n}-leave-to`,\n mv: props.moveClass ?? `${n}-move`,\n }\n\n const containerRef = createRef<HTMLElement>()\n const entries = new Map<string | number, ItemEntry>()\n // Gates the effect until the container element is in the DOM\n const ready = signal(false)\n let firstRun = true\n\n const applyEnter = (el: HTMLElement) => {\n props.onBeforeEnter?.(el)\n el.classList.remove(cls.lf, cls.la, cls.lt)\n el.classList.add(cls.ef, cls.ea)\n requestAnimationFrame(() => {\n el.classList.remove(cls.ef)\n el.classList.add(cls.et)\n const done = () => {\n el.removeEventListener(\"transitionend\", done)\n el.removeEventListener(\"animationend\", done)\n el.classList.remove(cls.ea, cls.et)\n props.onAfterEnter?.(el)\n }\n el.addEventListener(\"transitionend\", done, { once: true })\n el.addEventListener(\"animationend\", done, { once: true })\n })\n }\n\n const applyLeave = (el: HTMLElement, onDone: () => void) => {\n props.onBeforeLeave?.(el)\n el.classList.remove(cls.ef, cls.ea, cls.et)\n el.classList.add(cls.lf, cls.la)\n requestAnimationFrame(() => {\n el.classList.remove(cls.lf)\n el.classList.add(cls.lt)\n const done = () => {\n el.removeEventListener(\"transitionend\", done)\n el.removeEventListener(\"animationend\", done)\n el.classList.remove(cls.la, cls.lt)\n props.onAfterLeave?.(el)\n onDone()\n }\n el.addEventListener(\"transitionend\", done, { once: true })\n el.addEventListener(\"animationend\", done, { once: true })\n })\n }\n\n /** Start leave animation for removed items. */\n const processLeaves = (newKeys: Set<string | number>) => {\n for (const [key, entry] of entries) {\n if (newKeys.has(key) || entry.leaving) continue\n entry.leaving = true\n const el = entry.ref.current\n if (el) {\n applyLeave(el, () => {\n entry.cleanup()\n entries.delete(key)\n })\n } else {\n entry.cleanup()\n entries.delete(key)\n }\n }\n }\n\n /** Mount new items and return the list of newly created entries. */\n const mountNewItems = (items: T[], container: HTMLElement): ItemEntry[] => {\n const newEntries: ItemEntry[] = []\n for (let i = 0; i < items.length; i++) {\n const item = items[i] as T\n const key = props.keyFn(item, i)\n if (entries.has(key)) continue\n const itemRef = createRef<HTMLElement>()\n const rawVNode = runUntracked(() => props.render(item, i))\n const vnode: VNode =\n typeof rawVNode.type === \"string\"\n ? { ...rawVNode, props: { ...rawVNode.props, ref: itemRef } as Props }\n : rawVNode\n const cleanup = mountChild(vnode, container, null)\n const entry: ItemEntry = { key, ref: itemRef, cleanup, leaving: false }\n entries.set(key, entry)\n newEntries.push(entry)\n }\n return newEntries\n }\n\n const startMoveAnimation = (el: HTMLElement) => {\n requestAnimationFrame(() => {\n el.classList.add(cls.mv)\n el.style.transform = \"\"\n el.style.transition = \"\"\n const done = () => {\n el.removeEventListener(\"transitionend\", done)\n el.removeEventListener(\"animationend\", done)\n el.classList.remove(cls.mv)\n }\n el.addEventListener(\"transitionend\", done, { once: true })\n el.addEventListener(\"animationend\", done, { once: true })\n })\n }\n\n const flipEntry = (entry: ItemEntry, oldPos: DOMRect) => {\n if (!entry.ref.current) return\n const newPos = entry.ref.current.getBoundingClientRect()\n const dx = oldPos.left - newPos.left\n const dy = oldPos.top - newPos.top\n if (Math.abs(dx) < 1 && Math.abs(dy) < 1) return\n const el = entry.ref.current\n el.style.transform = `translate(${dx}px, ${dy}px)`\n el.style.transition = \"none\"\n startMoveAnimation(el)\n }\n\n /** Apply FLIP move animations for items that shifted position. */\n const applyFlipMoves = (oldPositions: Map<string | number, DOMRect>) => {\n requestAnimationFrame(() => {\n for (const [key, entry] of entries) {\n if (entry.leaving) continue\n const oldPos = oldPositions.get(key)\n if (!oldPos) continue\n flipEntry(entry, oldPos)\n }\n })\n }\n\n const recordOldPositions = (): Map<string | number, DOMRect> => {\n const oldPositions = new Map<string | number, DOMRect>()\n for (const [key, entry] of entries) {\n if (!entry.leaving && entry.ref.current) {\n oldPositions.set(key, entry.ref.current.getBoundingClientRect())\n }\n }\n return oldPositions\n }\n\n const reorderEntries = (items: T[], container: HTMLElement) => {\n for (let i = 0; i < items.length; i++) {\n const key = props.keyFn(items[i] as T, i)\n const entry = entries.get(key)\n if (!entry || entry.leaving || !entry.ref.current) continue\n container.appendChild(entry.ref.current)\n }\n }\n\n const animateNewEntries = (newEntries: ItemEntry[]) => {\n for (const entry of newEntries) {\n queueMicrotask(() => {\n if (entry.ref.current) applyEnter(entry.ref.current)\n })\n }\n }\n\n const e = effect(() => {\n if (!ready()) return\n const container = containerRef.current\n if (!container) return\n\n const items = props.items()\n const newKeys = new Set(items.map((item, i) => props.keyFn(item, i)))\n const isFirst = firstRun\n firstRun = false\n\n const oldPositions = recordOldPositions()\n processLeaves(newKeys)\n const newEntries = mountNewItems(items, container)\n reorderEntries(items, container)\n\n if (!isFirst || props.appear) animateNewEntries(newEntries)\n if (!isFirst && oldPositions.size > 0) applyFlipMoves(oldPositions)\n })\n\n // Fire the effect once the container is in the DOM\n onMount(() => {\n ready.set(true)\n })\n\n onUnmount(() => {\n e.dispose()\n for (const entry of entries.values()) entry.cleanup()\n entries.clear()\n })\n\n return h(tag, { ref: containerRef })\n}\n","// @pyreon/runtime-dom — surgical signal-to-DOM renderer (no virtual DOM)\n\nexport { DELEGATED_EVENTS, delegatedPropName, setupDelegation } from \"./delegate\"\nexport type { DevtoolsComponentEntry, PyreonDevtools } from \"./devtools\"\nexport { hydrateRoot } from \"./hydrate\"\nexport { disableHydrationWarnings, enableHydrationWarnings } from \"./hydration-debug\"\nexport type { KeepAliveProps } from \"./keep-alive\"\nexport { KeepAlive } from \"./keep-alive\"\nexport { mountChild } from \"./mount\"\nexport type { SanitizeFn } from \"./props\"\nexport { applyProp, applyProps, sanitizeHtml, setSanitizer } from \"./props\"\nexport { _bindDirect, _bindText, _tpl, createTemplate } from \"./template\"\nexport type { TransitionProps } from \"./transition\"\nexport { Transition } from \"./transition\"\nexport type { TransitionGroupProps } from \"./transition-group\"\nexport { TransitionGroup } from \"./transition-group\"\n\nimport type { VNodeChild } from \"@pyreon/core\"\nimport { setupDelegation } from \"./delegate\"\nimport { installDevTools } from \"./devtools\"\nimport { mountChild } from \"./mount\"\n\nconst __DEV__ = typeof process !== \"undefined\" && process.env.NODE_ENV !== \"production\"\n\n/**\n * Mount a VNode tree into a container element.\n * Clears the container first, then mounts the given child.\n * Returns an `unmount` function that removes everything and disposes effects.\n *\n * @example\n * const unmount = mount(h(\"div\", null, \"Hello Pyreon\"), document.getElementById(\"app\")!)\n */\nexport function mount(root: VNodeChild, container: Element): () => void {\n if (__DEV__ && container == null) {\n throw new Error(\n '[pyreon] mount() called with a null/undefined container. Make sure the element exists in the DOM, e.g. document.getElementById(\"app\")',\n )\n }\n installDevTools()\n setupDelegation(container)\n container.innerHTML = \"\"\n return mountChild(root, container, null)\n}\n\n/** Alias for `mount` */\nexport const render = mount\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["__DEV__","__DEV__","__DEV__","noop","__DEV__"],"sources":["../src/delegate.ts","../src/hydration-debug.ts","../src/devtools.ts","../src/nodes.ts","../src/props.ts","../src/mount.ts","../src/hydrate.ts","../src/keep-alive.ts","../src/template.ts","../src/transition.ts","../src/transition-group.ts","../src/index.ts"],"sourcesContent":["/**\n * Event delegation — single listener per event type on the mount container.\n *\n * Instead of calling addEventListener on every element, the compiler emits\n * `el.__click = handler` (expando property). A single delegated listener on the\n * container walks event.target up the DOM tree, checking for expandos.\n *\n * Benefits:\n * - Saves ~2000 addEventListener calls for 1000 rows with 2 handlers each\n * - Reduces memory per row (no per-element listener closure)\n * - Faster initial mount (~0.4-0.8ms savings on 1000-row benchmarks)\n */\n\nimport { batch } from \"@pyreon/reactivity\"\n\n/**\n * Events that are delegated (common bubbling events).\n * Non-bubbling events (focus, blur, mouseenter, mouseleave, load, error, scroll)\n * are NOT delegated — they must use addEventListener.\n */\nexport const DELEGATED_EVENTS = new Set([\n \"click\",\n \"dblclick\",\n \"contextmenu\",\n \"focusin\",\n \"focusout\",\n \"input\",\n \"change\",\n \"keydown\",\n \"keyup\",\n \"mousedown\",\n \"mouseup\",\n \"mousemove\",\n \"mouseover\",\n \"mouseout\",\n \"pointerdown\",\n \"pointerup\",\n \"pointermove\",\n \"pointerover\",\n \"pointerout\",\n \"touchstart\",\n \"touchend\",\n \"touchmove\",\n \"submit\",\n])\n\n/**\n * Property name used on DOM elements to store delegated event handlers.\n * Format: `__ev_{eventName}` e.g. `__ev_click`, `__ev_input`\n */\nexport function delegatedPropName(eventName: string): string {\n return `__ev_${eventName}`\n}\n\n// Track which containers already have delegation installed\nconst _delegated = new WeakSet<Element>()\n\n/**\n * Install delegation listeners on a container element.\n * Called once from mount(). Idempotent — safe to call multiple times.\n */\nexport function setupDelegation(container: Element): void {\n if (_delegated.has(container)) return\n _delegated.add(container)\n\n for (const eventName of DELEGATED_EVENTS) {\n const prop = delegatedPropName(eventName)\n container.addEventListener(eventName, (e: Event) => {\n let el = e.target as (HTMLElement & Record<string, unknown>) | null\n while (el && el !== container) {\n const handler = el[prop]\n if (typeof handler === \"function\") {\n batch(() => handler(e))\n // Don't break — allow ancestor handlers too (consistent with addEventListener)\n // But if stopPropagation was called, stop walking\n if (e.cancelBubble) break\n }\n el = el.parentElement as (HTMLElement & Record<string, unknown>) | null\n }\n })\n }\n}\n","/**\n * Hydration mismatch warnings.\n *\n * Enabled automatically in development (NODE_ENV !== \"production\").\n * Can be toggled manually for testing or verbose production debugging.\n *\n * @example\n * import { enableHydrationWarnings } from \"@pyreon/runtime-dom\"\n * enableHydrationWarnings()\n */\n\nconst __DEV__ = typeof process !== \"undefined\" && process.env.NODE_ENV !== \"production\"\n\nlet _enabled = __DEV__\n\nexport function enableHydrationWarnings(): void {\n _enabled = true\n}\n\nexport function disableHydrationWarnings(): void {\n _enabled = false\n}\n\n/**\n * Emit a hydration mismatch warning.\n * @param type - Kind of mismatch\n * @param expected - What the VNode expected\n * @param actual - What the DOM had\n * @param path - Human-readable path in the tree, e.g. \"root > div > span\"\n */\nexport function warnHydrationMismatch(\n _type: \"tag\" | \"text\" | \"missing\",\n _expected: unknown,\n _actual: unknown,\n _path: string,\n): void {\n if (!_enabled) return\n console.warn(\n `[Pyreon] Hydration mismatch (${_type}): expected ${String(_expected)}, got ${String(_actual)} at ${_path}`,\n )\n}\n","/**\n * Pyreon DevTools — exposes a `__PYREON_DEVTOOLS__` global hook for browser devtools extensions\n * and in-app debugging utilities.\n *\n * Installed automatically on first `mount()` call in the browser.\n * No-op on the server (typeof window === \"undefined\").\n *\n * Usage:\n * window.__PYREON_DEVTOOLS__.getComponentTree() // root component entries\n * window.__PYREON_DEVTOOLS__.getAllComponents() // flat list of all live components\n * window.__PYREON_DEVTOOLS__.highlight(\"comp-id\") // outline a component's DOM node\n * window.__PYREON_DEVTOOLS__.onComponentMount(cb) // subscribe to mount events\n * window.__PYREON_DEVTOOLS__.onComponentUnmount(cb)// subscribe to unmount events\n * window.__PYREON_DEVTOOLS__.enableOverlay() // Ctrl+Shift+P: hover to inspect components\n */\n\nexport interface DevtoolsComponentEntry {\n id: string\n name: string\n /** First DOM element produced by this component, if any */\n el: Element | null\n parentId: string | null\n childIds: string[]\n}\n\nexport interface PyreonDevtools {\n readonly version: string\n getComponentTree(): DevtoolsComponentEntry[]\n getAllComponents(): DevtoolsComponentEntry[]\n highlight(id: string): void\n onComponentMount(cb: (entry: DevtoolsComponentEntry) => void): () => void\n onComponentUnmount(cb: (id: string) => void): () => void\n /** Toggle the component inspector overlay (also: Ctrl+Shift+P) */\n enableOverlay(): void\n disableOverlay(): void\n}\n\n// ─── Internal registry ────────────────────────────────────────────────────────\n\nconst _components = new Map<string, DevtoolsComponentEntry>()\nconst _mountListeners: ((entry: DevtoolsComponentEntry) => void)[] = []\nconst _unmountListeners: ((id: string) => void)[] = []\n\nexport function registerComponent(\n id: string,\n name: string,\n el: Element | null,\n parentId: string | null,\n): void {\n const entry: DevtoolsComponentEntry = { id, name, el, parentId, childIds: [] }\n _components.set(id, entry)\n if (parentId) {\n const parent = _components.get(parentId)\n if (parent) parent.childIds.push(id)\n }\n for (const cb of _mountListeners) cb(entry)\n}\n\nexport function unregisterComponent(id: string): void {\n const entry = _components.get(id)\n if (!entry) return\n if (entry.parentId) {\n const parent = _components.get(entry.parentId)\n if (parent) parent.childIds = parent.childIds.filter((c) => c !== id)\n }\n _components.delete(id)\n for (const cb of _unmountListeners) cb(id)\n}\n\n// ─── Component Inspector Overlay ─────────────────────────────────────────────\n\nlet _overlayActive = false\nlet _overlayEl: HTMLDivElement | null = null\nlet _tooltipEl: HTMLDivElement | null = null\nlet _currentHighlight: Element | null = null\n\nfunction findComponentForElement(el: Element): DevtoolsComponentEntry | null {\n // Walk up from the hovered element to find the nearest registered component\n let node: Element | null = el\n while (node) {\n for (const entry of _components.values()) {\n if (entry.el === node) return entry\n }\n node = node.parentElement\n }\n return null\n}\n\nfunction createOverlayElements(): void {\n if (_overlayEl) return\n\n _overlayEl = document.createElement(\"div\")\n _overlayEl.id = \"__pyreon-overlay\"\n _overlayEl.style.cssText =\n \"position:fixed;pointer-events:none;border:2px solid #00b4d8;border-radius:3px;z-index:999999;display:none;transition:all 0.08s ease-out;\"\n\n _tooltipEl = document.createElement(\"div\")\n _tooltipEl.style.cssText =\n \"position:fixed;pointer-events:none;background:#1a1a2e;color:#e0e0e0;font:12px/1.4 ui-monospace,monospace;padding:6px 10px;border-radius:4px;z-index:999999;display:none;box-shadow:0 2px 8px rgba(0,0,0,0.3);max-width:400px;white-space:pre-wrap;\"\n\n document.body.appendChild(_overlayEl)\n document.body.appendChild(_tooltipEl)\n}\n\nfunction positionOverlay(rect: DOMRect): void {\n if (!_overlayEl) return\n _overlayEl.style.display = \"block\"\n _overlayEl.style.top = `${rect.top}px`\n _overlayEl.style.left = `${rect.left}px`\n _overlayEl.style.width = `${rect.width}px`\n _overlayEl.style.height = `${rect.height}px`\n}\n\nfunction positionTooltip(entry: DevtoolsComponentEntry, rect: DOMRect): void {\n if (!_tooltipEl) return\n const childCount = entry.childIds.length\n let info = `<${entry.name}>`\n if (childCount > 0) info += `\\n ${childCount} child component${childCount === 1 ? \"\" : \"s\"}`\n _tooltipEl.textContent = info\n _tooltipEl.style.display = \"block\"\n _tooltipEl.style.top = `${rect.top - 30}px`\n _tooltipEl.style.left = `${rect.left}px`\n if (rect.top < 35) {\n _tooltipEl.style.top = `${rect.bottom + 4}px`\n }\n}\n\nfunction hideOverlayElements(): void {\n if (_overlayEl) _overlayEl.style.display = \"none\"\n if (_tooltipEl) _tooltipEl.style.display = \"none\"\n _currentHighlight = null\n}\n\n/** @internal — exported for testing only */\nexport function onOverlayMouseMove(e: MouseEvent): void {\n const target = document.elementFromPoint(e.clientX, e.clientY)\n if (!target || target === _overlayEl || target === _tooltipEl) return\n\n const entry = findComponentForElement(target)\n if (!entry?.el) {\n hideOverlayElements()\n return\n }\n\n if (entry.el === _currentHighlight) return\n _currentHighlight = entry.el\n\n const rect = entry.el.getBoundingClientRect()\n positionOverlay(rect)\n positionTooltip(entry, rect)\n}\n\n/** @internal — exported for testing only */\nexport function onOverlayClick(e: MouseEvent): void {\n e.preventDefault()\n e.stopPropagation()\n const target = document.elementFromPoint(e.clientX, e.clientY)\n if (!target) return\n const entry = findComponentForElement(target)\n if (entry) {\n console.group(`[Pyreon] <${entry.name}>`)\n console.log(\"element:\", entry.el)\n console.log(\"children:\", entry.childIds.length)\n if (entry.parentId) {\n const parent = _components.get(entry.parentId)\n if (parent) {\n console.log(\"parent:\", `<${parent.name}>`)\n }\n }\n console.groupEnd()\n }\n disableOverlay()\n}\n\nfunction onOverlayKeydown(e: KeyboardEvent): void {\n if (e.key === \"Escape\") {\n disableOverlay()\n }\n}\n\nfunction enableOverlay(): void {\n if (_overlayActive) return\n _overlayActive = true\n createOverlayElements()\n document.addEventListener(\"mousemove\", onOverlayMouseMove, true)\n document.addEventListener(\"click\", onOverlayClick, true)\n document.addEventListener(\"keydown\", onOverlayKeydown, true)\n document.body.style.cursor = \"crosshair\"\n}\n\nfunction disableOverlay(): void {\n if (!_overlayActive) return\n _overlayActive = false\n document.removeEventListener(\"mousemove\", onOverlayMouseMove, true)\n document.removeEventListener(\"click\", onOverlayClick, true)\n document.removeEventListener(\"keydown\", onOverlayKeydown, true)\n document.body.style.cursor = \"\"\n if (_overlayEl) _overlayEl.style.display = \"none\"\n if (_tooltipEl) _tooltipEl.style.display = \"none\"\n _currentHighlight = null\n}\n\n// ─── Installation ─────────────────────────────────────────────────────────────\n\nlet _installed = false\n// Resolved once at module load — avoids per-call typeof branch in coverage\nconst _hasWindow = typeof window !== \"undefined\"\n\nexport function installDevTools(): void {\n if (!_hasWindow || _installed) return\n _installed = true\n\n const devtools: PyreonDevtools = {\n version: \"0.1.0\",\n\n getComponentTree() {\n return Array.from(_components.values()).filter((e) => e.parentId === null)\n },\n\n getAllComponents() {\n return Array.from(_components.values())\n },\n\n highlight(id: string) {\n const entry = _components.get(id)\n if (!entry?.el) return\n const el = entry.el as HTMLElement\n const prev = el.style.outline\n el.style.outline = \"2px solid #00b4d8\"\n setTimeout(() => {\n el.style.outline = prev\n }, 1500)\n },\n\n onComponentMount(cb: (entry: DevtoolsComponentEntry) => void): () => void {\n _mountListeners.push(cb)\n return () => {\n const i = _mountListeners.indexOf(cb)\n if (i >= 0) _mountListeners.splice(i, 1)\n }\n },\n\n onComponentUnmount(cb: (id: string) => void): () => void {\n _unmountListeners.push(cb)\n return () => {\n const i = _unmountListeners.indexOf(cb)\n if (i >= 0) _unmountListeners.splice(i, 1)\n }\n },\n\n enableOverlay,\n disableOverlay,\n }\n\n // Attach to window — compatible with browser devtools extensions\n ;(window as unknown as Record<string, unknown>).__PYREON_DEVTOOLS__ = devtools\n\n // Ctrl+Shift+P toggles the component inspector overlay\n window.addEventListener(\"keydown\", (e) => {\n if (e.ctrlKey && e.shiftKey && e.key === \"P\") {\n e.preventDefault()\n if (_overlayActive) disableOverlay()\n else enableOverlay()\n }\n })\n\n // ── $p console helper ────────────────────────────────────────────────────\n // Type `$p` in the browser console for quick access to Pyreon debug tools.\n const win = window as unknown as Record<string, unknown>\n win.$p = {\n /** List all mounted components */\n components: () => devtools.getAllComponents(),\n /** Component tree (roots only) */\n tree: () => devtools.getComponentTree(),\n /** Highlight a component by id */\n highlight: (id: string) => devtools.highlight(id),\n /** Toggle component inspector overlay */\n inspect: () => {\n if (_overlayActive) disableOverlay()\n else enableOverlay()\n },\n /** Print component count */\n stats: () => {\n const all = devtools.getAllComponents()\n const roots = devtools.getComponentTree()\n console.log(\n `[Pyreon] ${all.length} component${all.length === 1 ? \"\" : \"s\"}, ${roots.length} root${roots.length === 1 ? \"\" : \"s\"}`,\n )\n return { total: all.length, roots: roots.length }\n },\n /** Quick help */\n help: () => {\n console.log(\n \"[Pyreon] $p commands:\\n\" +\n \" $p.components() — list all mounted components\\n\" +\n \" $p.tree() — component tree (roots only)\\n\" +\n \" $p.highlight(id)— outline a component\\n\" +\n \" $p.inspect() — toggle component inspector\\n\" +\n \" $p.stats() — print component count\\n\" +\n \" $p.help() — this message\",\n )\n },\n }\n}\n","import type { VNode, VNodeChild } from \"@pyreon/core\"\n\ntype MountFn = (child: VNodeChild, parent: Node, anchor: Node | null) => Cleanup\n\nimport { effect, runUntracked } from \"@pyreon/reactivity\"\n\nconst __DEV__ = typeof process !== \"undefined\" && process.env.NODE_ENV !== \"production\"\n\ntype Cleanup = () => void\n\n/**\n * Move all nodes strictly between `start` and `end` into a throwaway\n * DocumentFragment, detaching them from the live DOM in O(n) top-level moves.\n *\n * This is dramatically faster than Range.deleteContents() in JS-based DOMs\n * (happy-dom, jsdom) where deleting connected nodes with deep subtrees is O(n²).\n * In real browsers both approaches are similar, but the fragment approach is\n * never slower and avoids the pathological case.\n *\n * After this call every moved node has isConnected=false, so cleanup functions\n * that guard removeChild with `isConnected !== false` become no-ops.\n */\nfunction clearBetween(start: Node, end: Node): void {\n const frag = document.createDocumentFragment()\n let cur: Node | null = start.nextSibling\n while (cur && cur !== end) {\n const next: Node | null = cur.nextSibling\n frag.appendChild(cur)\n cur = next\n }\n // frag goes out of scope → nodes are GC-eligible\n}\n\n/**\n * Mount a reactive node whose content changes over time.\n *\n * A comment node is used as a stable anchor point in the DOM.\n * On each change: old nodes are removed, new ones inserted before the anchor.\n */\nexport function mountReactive(\n accessor: () => VNodeChild,\n parent: Node,\n anchor: Node | null,\n mount: (child: VNodeChild, p: Node, a: Node | null) => Cleanup,\n): Cleanup {\n const marker = document.createComment(\"pyreon\")\n parent.insertBefore(marker, anchor)\n\n let currentCleanup: Cleanup = () => {\n /* noop */\n }\n let generation = 0\n\n const e = effect(() => {\n const myGen = ++generation\n // Run cleanup outside tracking context — cleanup may write to signals\n // (e.g. onUnmount hooks), and those writes must not accidentally register\n // as dependencies of this effect, which would cause infinite recursion.\n runUntracked(() => currentCleanup())\n currentCleanup = () => {\n /* noop */\n }\n const value = accessor()\n if (__DEV__ && typeof value === \"function\") {\n console.warn(\n \"[Pyreon] Reactive accessor returned a function instead of a value. Did you forget to call the signal?\",\n )\n }\n if (value != null && value !== false) {\n const cleanup = mount(value, parent, marker)\n // Guard: a re-entrant signal update (e.g. ErrorBoundary catching a child\n // throw) may have already re-run this effect and updated currentCleanup.\n // In that case, discard our stale cleanup rather than overwriting the one\n // set by the re-entrant run.\n if (myGen === generation) {\n currentCleanup = cleanup\n } else {\n cleanup()\n }\n }\n })\n\n return () => {\n e.dispose()\n currentCleanup()\n marker.parentNode?.removeChild(marker)\n }\n}\n\n// ─── Keyed list reconciler ────────────────────────────────────────────────────\n\n/**\n * Efficient keyed list reconciler.\n *\n * When a reactive accessor returns VNode[] where every vnode carries a key,\n * this reconciler reuses, moves, and creates DOM nodes surgically instead of\n * tearing down and rebuilding the full list on every signal update.\n */\n\ninterface KeyedEntry {\n /** Comment node placed immediately before this entry's DOM content. */\n anchor: Comment\n cleanup: Cleanup\n}\n\n// WeakSets to identify anchor nodes belonging to list entries.\n// Entries use their first DOM node as anchor (element for simple vnodes, comment fallback for empty).\nconst _keyedAnchors = new WeakSet<Node>()\n\n/** LIS-based reorder state — shared across keyed list instances, grown as needed */\ninterface LisState {\n tails: Int32Array\n tailIdx: Int32Array\n pred: Int32Array\n stay: Uint8Array\n}\n\nfunction growLisArrays(lis: LisState, n: number): LisState {\n if (n <= lis.pred.length) return lis\n return {\n tails: new Int32Array(n + 16),\n tailIdx: new Int32Array(n + 16),\n pred: new Int32Array(n + 16),\n stay: new Uint8Array(n + 16),\n }\n}\n\nfunction computeKeyedLis(\n lis: LisState,\n n: number,\n newKeyOrder: (string | number)[],\n curPos: Map<string | number, number>,\n): number {\n const { tails, tailIdx, pred } = lis\n let lisLen = 0\n for (let i = 0; i < n; i++) {\n const key = newKeyOrder[i]\n if (key === undefined) continue\n const v = curPos.get(key) ?? -1\n if (v < 0) continue\n\n let lo = 0\n let hi = lisLen\n while (lo < hi) {\n const mid = (lo + hi) >> 1\n if ((tails[mid] as number) < v) lo = mid + 1\n else hi = mid\n }\n tails[lo] = v\n tailIdx[lo] = i\n if (lo > 0) pred[i] = tailIdx[lo - 1] as number\n if (lo === lisLen) lisLen++\n }\n return lisLen\n}\n\nfunction markStayingEntries(lis: LisState, lisLen: number): void {\n const { tailIdx, pred, stay } = lis\n let cur: number = lisLen > 0 ? (tailIdx[lisLen - 1] as number) : -1\n while (cur !== -1) {\n stay[cur] = 1\n cur = pred[cur] as number\n }\n}\n\nfunction applyKeyedMoves(\n n: number,\n newKeyOrder: (string | number)[],\n stay: Uint8Array,\n cache: Map<string | number, KeyedEntry>,\n parent: Node,\n tailMarker: Comment,\n): void {\n let cursor: Node = tailMarker\n for (let i = n - 1; i >= 0; i--) {\n const key = newKeyOrder[i]\n if (key === undefined) continue\n const entry = cache.get(key)\n if (!entry) continue\n if (!stay[i]) moveEntryBefore(parent, entry.anchor, cursor)\n cursor = entry.anchor\n }\n}\n\n/** Grow LIS typed arrays if needed, then compute and apply reorder. */\nfunction keyedListReorder(\n lis: LisState,\n n: number,\n newKeyOrder: (string | number)[],\n curPos: Map<string | number, number>,\n cache: Map<string | number, KeyedEntry>,\n parent: Node,\n tailMarker: Comment,\n): LisState {\n const grown = growLisArrays(lis, n)\n grown.pred.fill(-1, 0, n)\n grown.stay.fill(0, 0, n)\n\n const lisLen = computeKeyedLis(grown, n, newKeyOrder, curPos)\n markStayingEntries(grown, lisLen)\n applyKeyedMoves(n, newKeyOrder, grown.stay, cache, parent, tailMarker)\n\n return grown\n}\n\nexport function mountKeyedList(\n accessor: () => VNode[],\n parent: Node,\n listAnchor: Node | null,\n mountVNode: (vnode: VNode, p: Node, a: Node | null) => Cleanup,\n): Cleanup {\n const startMarker = document.createComment(\"\")\n const tailMarker = document.createComment(\"\")\n parent.insertBefore(startMarker, listAnchor)\n parent.insertBefore(tailMarker, listAnchor)\n\n const cache = new Map<string | number, KeyedEntry>()\n const curPos = new Map<string | number, number>()\n let currentKeyOrder: (string | number)[] = []\n\n let lis: LisState = {\n tails: new Int32Array(16),\n tailIdx: new Int32Array(16),\n pred: new Int32Array(16),\n stay: new Uint8Array(16),\n }\n\n const collectKeyOrder = (\n newList: VNode[],\n ): { newKeyOrder: (string | number)[]; newKeySet: Set<string | number> } => {\n const newKeyOrder: (string | number)[] = []\n const newKeySet = new Set<string | number>()\n for (const vnode of newList) {\n const key = vnode.key\n if (key !== null && key !== undefined) {\n newKeyOrder.push(key)\n newKeySet.add(key)\n }\n }\n return { newKeyOrder, newKeySet }\n }\n\n const removeStaleEntries = (newKeySet: Set<string | number>) => {\n for (const [key, entry] of cache) {\n if (newKeySet.has(key)) continue\n entry.cleanup()\n entry.anchor.parentNode?.removeChild(entry.anchor)\n cache.delete(key)\n curPos.delete(key)\n }\n }\n\n const mountNewEntries = (newList: VNode[]) => {\n for (const vnode of newList) {\n const key = vnode.key\n if (key === null || key === undefined) continue\n if (cache.has(key)) continue\n const anchor = document.createComment(\"\")\n _keyedAnchors.add(anchor)\n parent.insertBefore(anchor, tailMarker)\n const cleanup = mountVNode(vnode, parent, tailMarker)\n cache.set(key, { anchor, cleanup })\n }\n }\n\n const e = effect(() => {\n const newList = accessor()\n const n = newList.length\n\n if (n === 0 && cache.size > 0) {\n for (const entry of cache.values()) entry.cleanup()\n cache.clear()\n curPos.clear()\n currentKeyOrder = []\n clearBetween(startMarker, tailMarker)\n return\n }\n\n const { newKeyOrder, newKeySet } = collectKeyOrder(newList)\n removeStaleEntries(newKeySet)\n mountNewEntries(newList)\n\n if (currentKeyOrder.length > 0 && n > 0) {\n lis = keyedListReorder(lis, n, newKeyOrder, curPos, cache, parent, tailMarker)\n }\n\n curPos.clear()\n for (let i = 0; i < newKeyOrder.length; i++) {\n const k = newKeyOrder[i]\n if (k !== undefined) curPos.set(k, i)\n }\n currentKeyOrder = newKeyOrder\n })\n\n return () => {\n e.dispose()\n for (const entry of cache.values()) {\n entry.cleanup()\n entry.anchor.parentNode?.removeChild(entry.anchor)\n }\n cache.clear()\n startMarker.parentNode?.removeChild(startMarker)\n tailMarker.parentNode?.removeChild(tailMarker)\n }\n}\n\n// ─── For — source-aware keyed reconciler ─────────────────────────────────────\n\n/** Maximum number of displaced positions before falling back to full LIS. */\nconst SMALL_K = 8\n\n// WeakSet to identify anchor nodes belonging to mountFor entries.\nconst _forAnchors = new WeakSet<Node>()\n\n// anchor is the first DOM node of the entry (element for normal vnodes, comment fallback for empty).\n// Using the element itself saves 1 createComment + 1 DOM node per entry.\n// pos is merged here (instead of a separate Map) to halve Map operations.\n// cleanup is null when the entry has no teardown work (saves function call overhead on clear).\ninterface ForEntry {\n anchor: Node\n cleanup: Cleanup | null\n pos: number\n}\n\n/** Try small-k reorder; returns true if handled, false if LIS fallback needed. */\nfunction trySmallKReorder(\n n: number,\n newKeys: (string | number)[],\n currentKeys: (string | number)[],\n cache: Map<string | number, ForEntry>,\n liveParent: Node,\n tailMarker: Comment,\n): boolean {\n if (n !== currentKeys.length) return false\n const diffs: number[] = []\n for (let i = 0; i < n; i++) {\n if (newKeys[i] !== currentKeys[i]) {\n diffs.push(i)\n if (diffs.length > SMALL_K) return false\n }\n }\n if (diffs.length > 0) smallKPlace(liveParent, diffs, newKeys, cache, tailMarker)\n for (const i of diffs) {\n const cached = cache.get(newKeys[i] as string | number)\n if (cached) cached.pos = i\n }\n return true\n}\n\nfunction computeForLis(\n lis: LisState,\n n: number,\n newKeys: (string | number)[],\n cache: Map<string | number, ForEntry>,\n): number {\n const { tails, tailIdx, pred } = lis\n let lisLen = 0\n for (let i = 0; i < n; i++) {\n const key = newKeys[i] as string | number\n const v = cache.get(key)?.pos ?? 0\n let lo = 0\n let hi = lisLen\n while (lo < hi) {\n const mid = (lo + hi) >> 1\n if ((tails[mid] as number) < v) lo = mid + 1\n else hi = mid\n }\n tails[lo] = v\n tailIdx[lo] = i\n if (lo > 0) pred[i] = tailIdx[lo - 1] as number\n if (lo === lisLen) lisLen++\n }\n return lisLen\n}\n\nfunction applyForMoves(\n n: number,\n newKeys: (string | number)[],\n stay: Uint8Array,\n cache: Map<string | number, ForEntry>,\n liveParent: Node,\n tailMarker: Comment,\n): void {\n let cursor: Node = tailMarker\n for (let i = n - 1; i >= 0; i--) {\n const entry = cache.get(newKeys[i] as string | number)\n if (!entry) continue\n if (!stay[i]) moveEntryBefore(liveParent, entry.anchor, cursor)\n cursor = entry.anchor\n }\n}\n\n/** LIS-based reorder for mountFor. */\nfunction forLisReorder(\n lis: LisState,\n n: number,\n newKeys: (string | number)[],\n cache: Map<string | number, ForEntry>,\n liveParent: Node,\n tailMarker: Comment,\n): LisState {\n const grown = growLisArrays(lis, n)\n grown.pred.fill(-1, 0, n)\n grown.stay.fill(0, 0, n)\n\n const lisLen = computeForLis(grown, n, newKeys, cache)\n markStayingEntries(grown, lisLen)\n applyForMoves(n, newKeys, grown.stay, cache, liveParent, tailMarker)\n\n for (let i = 0; i < n; i++) {\n const cached = cache.get(newKeys[i] as string | number)\n if (cached) cached.pos = i\n }\n\n return grown\n}\n\n/**\n * Keyed reconciler that works directly on the source item array.\n *\n * Optimizations:\n * - Calls renderItem() only for NEW keys — 0 VNode allocations for reorders\n * - Small-k fast path: if <= SMALL_K positions changed, skips LIS\n * - Fast clear path: moves nodes to DocumentFragment for O(n) bulk detach\n * - Fresh render fast path: skips stale-check and reorder on first render\n */\nexport function mountFor<T>(\n source: () => T[],\n getKey: (item: T) => string | number,\n renderItem: (item: T) => import(\"@pyreon/core\").VNode | import(\"@pyreon/core\").NativeItem,\n parent: Node,\n anchor: Node | null,\n mountChild: MountFn,\n): Cleanup {\n const startMarker = document.createComment(\"\")\n const tailMarker = document.createComment(\"\")\n parent.insertBefore(startMarker, anchor)\n parent.insertBefore(tailMarker, anchor)\n\n let cache = new Map<string | number, ForEntry>()\n let currentKeys: (string | number)[] = []\n let cleanupCount = 0\n let anchorsRegistered = false\n\n let lis: LisState = {\n tails: new Int32Array(16),\n tailIdx: new Int32Array(16),\n pred: new Int32Array(16),\n stay: new Uint8Array(16),\n }\n\n const warnForKey = (seen: Set<string | number> | null, key: string | number) => {\n if (!__DEV__ || !seen) return\n if (key == null) {\n console.warn(\n \"[Pyreon] <For> `by` function returned null/undefined. \" +\n \"Keys must be strings or numbers. Check your `by` prop.\",\n )\n }\n if (seen.has(key)) {\n console.warn(`[Pyreon] Duplicate key \"${String(key)}\" in <For> list. Keys must be unique.`)\n }\n seen.add(key)\n }\n\n /** Render item into container, update cache+cleanupCount. No anchor registration. */\n const renderInto = (\n item: T,\n key: string | number,\n pos: number,\n container: Node,\n before: Node | null,\n ) => {\n const result = renderItem(item)\n if ((result as import(\"@pyreon/core\").NativeItem).__isNative) {\n const native = result as import(\"@pyreon/core\").NativeItem\n container.insertBefore(native.el, before)\n cache.set(key, { anchor: native.el, cleanup: native.cleanup, pos })\n if (native.cleanup) cleanupCount++\n return\n }\n const priorLast = before ? before.previousSibling : container.lastChild\n const cl = mountChild(result as import(\"@pyreon/core\").VNode, container, before)\n const firstMounted = priorLast ? priorLast.nextSibling : container.firstChild\n if (!firstMounted || firstMounted === before) {\n const ph = document.createComment(\"\")\n container.insertBefore(ph, before)\n cache.set(key, { anchor: ph, cleanup: cl, pos })\n } else {\n cache.set(key, { anchor: firstMounted, cleanup: cl, pos })\n }\n cleanupCount++\n }\n\n const handleFreshRender = (items: T[], n: number, liveParent: Node) => {\n const frag = document.createDocumentFragment()\n const keys = new Array<string | number>(n)\n const _seenKeys = __DEV__ ? new Set<string | number>() : null\n for (let i = 0; i < n; i++) {\n const item = items[i] as T\n const key = getKey(item)\n warnForKey(_seenKeys, key)\n keys[i] = key\n renderInto(item, key, i, frag, null)\n }\n liveParent.insertBefore(frag, tailMarker)\n anchorsRegistered = false\n currentKeys = keys\n }\n\n const collectNewKeys = (items: T[], n: number): (string | number)[] => {\n const newKeys = new Array<string | number>(n)\n const _seenUpdate = __DEV__ ? new Set<string | number>() : null\n for (let i = 0; i < n; i++) {\n newKeys[i] = getKey(items[i] as T)\n warnForKey(_seenUpdate, newKeys[i] as string | number)\n }\n return newKeys\n }\n\n const handleReplaceAll = (\n items: T[],\n n: number,\n newKeys: (string | number)[],\n liveParent: Node,\n ) => {\n if (cleanupCount > 0) {\n for (const entry of cache.values()) if (entry.cleanup) entry.cleanup()\n }\n cache = new Map()\n cleanupCount = 0\n\n const parentParent = liveParent.parentNode\n const canSwap =\n parentParent && liveParent.firstChild === startMarker && liveParent.lastChild === tailMarker\n\n const frag = document.createDocumentFragment()\n for (let i = 0; i < n; i++) {\n renderInto(items[i] as T, newKeys[i] as string | number, i, frag, null)\n }\n anchorsRegistered = false\n\n if (canSwap) {\n const fresh = liveParent.cloneNode(false)\n fresh.appendChild(startMarker)\n fresh.appendChild(frag)\n fresh.appendChild(tailMarker)\n parentParent.replaceChild(fresh, liveParent)\n } else {\n clearBetween(startMarker, tailMarker)\n liveParent.insertBefore(frag, tailMarker)\n }\n currentKeys = newKeys\n }\n\n const removeStaleForEntries = (newKeySet: Set<string | number>) => {\n for (const [key, entry] of cache) {\n if (newKeySet.has(key)) continue\n if (entry.cleanup) {\n entry.cleanup()\n cleanupCount--\n }\n entry.anchor.parentNode?.removeChild(entry.anchor)\n cache.delete(key)\n }\n }\n\n const mountNewForEntries = (\n items: T[],\n n: number,\n newKeys: (string | number)[],\n liveParent: Node,\n ) => {\n for (let i = 0; i < n; i++) {\n const key = newKeys[i] as string | number\n if (cache.has(key)) continue\n renderInto(items[i] as T, key, i, liveParent, tailMarker)\n const entry = cache.get(key)\n if (entry) _forAnchors.add(entry.anchor)\n }\n }\n\n const handleFastClear = (liveParent: Node) => {\n if (cache.size === 0) return\n if (cleanupCount > 0) {\n for (const entry of cache.values()) if (entry.cleanup) entry.cleanup()\n }\n const pp = liveParent.parentNode\n if (pp && liveParent.firstChild === startMarker && liveParent.lastChild === tailMarker) {\n const fresh = liveParent.cloneNode(false)\n fresh.appendChild(startMarker)\n fresh.appendChild(tailMarker)\n pp.replaceChild(fresh, liveParent)\n } else {\n clearBetween(startMarker, tailMarker)\n }\n cache = new Map()\n cleanupCount = 0\n currentKeys = []\n }\n\n const hasAnyKeptKey = (n: number, newKeys: (string | number)[]): boolean => {\n for (let i = 0; i < n; i++) {\n if (cache.has(newKeys[i] as string | number)) return true\n }\n return false\n }\n\n const handleIncrementalUpdate = (\n items: T[],\n n: number,\n newKeys: (string | number)[],\n liveParent: Node,\n ) => {\n removeStaleForEntries(new Set<string | number>(newKeys))\n mountNewForEntries(items, n, newKeys, liveParent)\n\n if (!anchorsRegistered) {\n for (const entry of cache.values()) _forAnchors.add(entry.anchor)\n anchorsRegistered = true\n }\n\n if (trySmallKReorder(n, newKeys, currentKeys, cache, liveParent, tailMarker)) {\n currentKeys = newKeys\n return\n }\n\n lis = forLisReorder(lis, n, newKeys, cache, liveParent, tailMarker)\n currentKeys = newKeys\n }\n\n const e = effect(() => {\n const liveParent = startMarker.parentNode\n if (!liveParent) return\n const items = source()\n const n = items.length\n\n if (n === 0) {\n handleFastClear(liveParent)\n return\n }\n\n if (currentKeys.length === 0) {\n handleFreshRender(items, n, liveParent)\n return\n }\n\n const newKeys = collectNewKeys(items, n)\n\n if (!hasAnyKeptKey(n, newKeys)) {\n handleReplaceAll(items, n, newKeys, liveParent)\n return\n }\n\n handleIncrementalUpdate(items, n, newKeys, liveParent)\n })\n\n return () => {\n e.dispose()\n for (const entry of cache.values()) {\n if (cleanupCount > 0 && entry.cleanup) entry.cleanup()\n entry.anchor.parentNode?.removeChild(entry.anchor)\n }\n cache = new Map()\n cleanupCount = 0\n startMarker.parentNode?.removeChild(startMarker)\n tailMarker.parentNode?.removeChild(tailMarker)\n }\n}\n\n/**\n * Small-k reorder: directly place the k displaced entries without LIS.\n */\nfunction smallKPlace(\n parent: Node,\n diffs: number[],\n newKeys: (string | number)[],\n cache: Map<string | number, { anchor: Node; cleanup: Cleanup | null }>,\n tailMarker: Comment,\n): void {\n const diffSet = new Set(diffs)\n let cursor: Node = tailMarker\n let prevDiffIdx = newKeys.length\n\n for (let d = diffs.length - 1; d >= 0; d--) {\n const i = diffs[d] as number\n\n let nextNonDiff = -1\n for (let j = i + 1; j < prevDiffIdx; j++) {\n if (!diffSet.has(j)) {\n nextNonDiff = j\n break\n }\n }\n\n if (nextNonDiff >= 0) {\n const nc = cache.get(newKeys[nextNonDiff] as string | number)?.anchor\n if (nc) cursor = nc\n }\n\n const entry = cache.get(newKeys[i] as string | number)\n if (!entry) {\n prevDiffIdx = i\n continue\n }\n moveEntryBefore(parent, entry.anchor, cursor)\n cursor = entry.anchor\n prevDiffIdx = i\n }\n}\n\n/**\n * Move startNode and all siblings belonging to this entry to just before `before`.\n * Stops at the next entry anchor (identified via WeakSet) or the tail marker.\n *\n * Fast path: if the next sibling is already a boundary (another entry or tail),\n * this entry is a single node — skip the toMove array entirely.\n */\nfunction moveEntryBefore(parent: Node, startNode: Node, before: Node): void {\n const next = startNode.nextSibling\n // Single-node fast path (covers all createTemplate rows — the common case)\n if (\n !next ||\n next === before ||\n (next.parentNode === parent && (_forAnchors.has(next) || _keyedAnchors.has(next)))\n ) {\n parent.insertBefore(startNode, before)\n return\n }\n // Multi-node slow path (fragments, components with multiple root nodes)\n const toMove: Node[] = [startNode]\n let cur: Node | null = next\n while (cur && cur !== before) {\n const nextNode: Node | null = cur.nextSibling\n toMove.push(cur)\n cur = nextNode\n if (\n cur &&\n cur.parentNode === parent &&\n (cur === before || _forAnchors.has(cur) || _keyedAnchors.has(cur))\n )\n break\n }\n for (const node of toMove) {\n parent.insertBefore(node, before)\n }\n}\n","import type { ClassValue, Props } from \"@pyreon/core\"\nimport { cx, normalizeStyleValue, toKebabCase } from \"@pyreon/core\"\n\nimport { batch, renderEffect } from \"@pyreon/reactivity\"\nimport { DELEGATED_EVENTS, delegatedPropName } from \"./delegate\"\n\ntype Cleanup = () => void\n\nconst __DEV__ = typeof process !== \"undefined\" && process.env.NODE_ENV !== \"production\"\n\n// ─── Configurable sanitizer ──────────────────────────────────────────────────\n\nexport type SanitizeFn = (html: string) => string\n\nlet _customSanitizer: SanitizeFn | null = null\n\n/**\n * Set a custom HTML sanitizer used by `innerHTML` and `sanitizeHtml()`.\n * Overrides both the Sanitizer API and the built-in fallback.\n *\n * @example\n * // With DOMPurify:\n * import DOMPurify from \"dompurify\"\n * setSanitizer((html) => DOMPurify.sanitize(html))\n *\n * // With sanitize-html:\n * import sanitize from \"sanitize-html\"\n * setSanitizer((html) => sanitize(html))\n *\n * // Reset to built-in:\n * setSanitizer(null)\n */\nexport function setSanitizer(fn: SanitizeFn | null): void {\n _customSanitizer = fn\n}\n\n// Safe HTML tags allowed by the fallback sanitizer (block + inline, no scripts/embeds/forms)\nconst SAFE_TAGS = new Set([\n \"a\",\n \"abbr\",\n \"address\",\n \"article\",\n \"aside\",\n \"b\",\n \"bdi\",\n \"bdo\",\n \"blockquote\",\n \"br\",\n \"caption\",\n \"cite\",\n \"code\",\n \"col\",\n \"colgroup\",\n \"dd\",\n \"del\",\n \"details\",\n \"dfn\",\n \"div\",\n \"dl\",\n \"dt\",\n \"em\",\n \"figcaption\",\n \"figure\",\n \"footer\",\n \"h1\",\n \"h2\",\n \"h3\",\n \"h4\",\n \"h5\",\n \"h6\",\n \"header\",\n \"hr\",\n \"i\",\n \"ins\",\n \"kbd\",\n \"li\",\n \"main\",\n \"mark\",\n \"nav\",\n \"ol\",\n \"p\",\n \"pre\",\n \"q\",\n \"rp\",\n \"rt\",\n \"ruby\",\n \"s\",\n \"samp\",\n \"section\",\n \"small\",\n \"span\",\n \"strong\",\n \"sub\",\n \"summary\",\n \"sup\",\n \"table\",\n \"tbody\",\n \"td\",\n \"tfoot\",\n \"th\",\n \"thead\",\n \"time\",\n \"tr\",\n \"u\",\n \"ul\",\n \"var\",\n \"wbr\",\n])\n\n// Attributes that can carry executable code\nconst UNSAFE_ATTR_RE = /^on/i\n\n/**\n * Fallback tag-stripping sanitizer for environments without the Sanitizer API.\n * Removes all tags not in SAFE_TAGS, strips event handler attributes,\n * and blocks javascript:/data: URLs in href/src/action attributes.\n */\nfunction fallbackSanitize(html: string): string {\n const doc = new DOMParser().parseFromString(html, \"text/html\")\n sanitizeNode(doc.body)\n return doc.body.innerHTML\n}\n\n/** Strip unsafe attributes from a single element. */\nfunction stripUnsafeAttrs(el: Element): void {\n const attrs = Array.from(el.attributes)\n for (const attr of attrs) {\n if (UNSAFE_ATTR_RE.test(attr.name)) {\n el.removeAttribute(attr.name)\n } else if (URL_ATTRS.has(attr.name) && UNSAFE_URL_RE.test(attr.value)) {\n el.removeAttribute(attr.name)\n }\n }\n}\n\nfunction sanitizeNode(node: Node): void {\n const children = Array.from(node.childNodes)\n for (const child of children) {\n if (child.nodeType !== 1) continue\n const el = child as Element\n const tag = el.tagName.toLowerCase()\n if (!SAFE_TAGS.has(tag)) {\n const text = document.createTextNode(el.textContent as string)\n node.replaceChild(text, el)\n continue\n }\n stripUnsafeAttrs(el)\n sanitizeNode(el)\n }\n}\n\n/**\n * Sanitize an HTML string using the browser Sanitizer API (Chrome 105+).\n * Falls back to a tag-allowlist sanitizer that strips unsafe elements and attributes.\n */\nexport function sanitizeHtml(html: string): string {\n // User-provided sanitizer takes priority (e.g. DOMPurify)\n if (_customSanitizer) return _customSanitizer(html)\n // DOM-based allowlist sanitizer — DOMParser is available in all browser targets.\n // sanitizeHtml is only called for innerHTML (DOM-only), so SSR fallback is not needed.\n return fallbackSanitize(html)\n}\n\n// Matches onClick, onInput, onMouseEnter, etc.\nconst EVENT_RE = /^on[A-Z]/\n\n/**\n * Apply all props to a DOM element.\n * Returns a single chained cleanup (or null if no props need teardown).\n * Uses for-in instead of Object.keys() to avoid allocating a keys array.\n */\nexport function applyProps(el: Element, props: Props): Cleanup | null {\n let first: Cleanup | null = null\n let cleanups: Cleanup[] | null = null\n for (const key in props) {\n if (key === \"key\" || key === \"ref\" || key === \"children\") continue\n const c = applyProp(el, key, props[key])\n if (c) {\n if (!first) {\n first = c\n } else if (!cleanups) {\n cleanups = [first, c]\n } else {\n cleanups.push(c)\n }\n }\n }\n if (cleanups)\n return () => {\n for (const c of cleanups) c()\n }\n return first\n}\n\n/**\n * Apply a single prop.\n *\n * - `onXxx` → addEventListener\n * - `() => value` (non-event function) → reactive via effect\n * - anything else → static attribute / DOM property\n */\n/**\n * Bind an event handler (onClick → \"click\") with batching + delegation support.\n */\nfunction applyEventProp(el: Element, key: string, value: unknown): Cleanup | null {\n if (typeof value !== \"function\") {\n if (__DEV__) {\n console.warn(\n `[Pyreon] Event handler \"${key}\" received a non-function value (${typeof value}). ` +\n `Expected a function. Did you mean ${key}={() => ...}?`,\n )\n }\n return null\n }\n const eventName = key[2]?.toLowerCase() + key.slice(3)\n const handler = value as EventListener\n\n if (DELEGATED_EVENTS.has(eventName)) {\n const prop = delegatedPropName(eventName)\n ;(el as unknown as Record<string, unknown>)[prop] = (e: Event) => batch(() => handler(e))\n return () => {\n ;(el as unknown as Record<string, unknown>)[prop] = undefined\n }\n }\n\n const batched: EventListener = (e) => batch(() => handler(e))\n el.addEventListener(eventName, batched)\n return () => el.removeEventListener(eventName, batched)\n}\n\nexport function applyProp(el: Element, key: string, value: unknown): Cleanup | null {\n // Event listener: onClick → \"click\"\n if (EVENT_RE.test(key)) return applyEventProp(el, key, value)\n\n // innerHTML — sanitized via Sanitizer API or fallback allowlist sanitizer\n if (key === \"innerHTML\") {\n if (typeof (el as HTMLElement & { setHTML?: (h: string) => void }).setHTML === \"function\") {\n ;(el as HTMLElement & { setHTML: (h: string) => void }).setHTML(value as string)\n } else {\n ;(el as HTMLElement).innerHTML = sanitizeHtml(value as string)\n }\n return null\n }\n // dangerouslySetInnerHTML — intentionally raw, developer owns sanitization (same as React)\n if (key === \"dangerouslySetInnerHTML\") {\n if (__DEV__) {\n console.warn(\n \"[Pyreon] dangerouslySetInnerHTML bypasses sanitization. Ensure the HTML is trusted.\",\n )\n }\n ;(el as HTMLElement).innerHTML = (value as { __html: string }).__html\n return null\n }\n\n // Reactive prop — function that returns the actual value\n // Uses renderEffect (lighter than effect — no scope registration, no WeakMap)\n // since lifecycle is managed by mountElement's cleanup array.\n if (typeof value === \"function\") {\n const dispose = renderEffect(() => setStaticProp(el, key, (value as () => unknown)()))\n return dispose\n }\n\n setStaticProp(el, key, value)\n return null\n}\n\n// Attributes that carry URLs and must be guarded against javascript:/data: injection.\nconst URL_ATTRS = new Set([\"href\", \"src\", \"action\", \"formaction\", \"poster\", \"cite\", \"data\"])\nconst UNSAFE_URL_RE = /^\\s*(?:javascript|data):/i\n\n/** Apply a style prop (string or object). */\nfunction applyStyleProp(el: HTMLElement, value: unknown): void {\n if (typeof value === \"string\") {\n el.style.cssText = value\n } else if (value != null && typeof value === \"object\") {\n const obj = value as Record<string, unknown>\n for (const k in obj) {\n const css = normalizeStyleValue(k, obj[k])\n el.style.setProperty(k.startsWith(\"--\") ? k : toKebabCase(k), css)\n }\n }\n}\n\nfunction applyClassProp(el: Element, value: unknown): void {\n const resolved = typeof value === \"string\" ? value : cx(value as ClassValue)\n el.setAttribute(\"class\", resolved || \"\")\n}\n\nfunction setStaticProp(el: Element, key: string, value: unknown): void {\n // Block javascript:/data: URI injection in URL-bearing attributes.\n if (URL_ATTRS.has(key) && typeof value === \"string\" && UNSAFE_URL_RE.test(value)) {\n if (__DEV__) {\n console.warn(`[Pyreon] Blocked unsafe URL in \"${key}\" attribute: ${value}`)\n }\n return\n }\n\n if (key === \"class\" || key === \"className\") {\n applyClassProp(el, value)\n return\n }\n\n if (key === \"style\") {\n applyStyleProp(el as HTMLElement, value)\n return\n }\n\n if (value == null) {\n el.removeAttribute(key)\n return\n }\n\n if (typeof value === \"boolean\") {\n if (value) el.setAttribute(key, \"\")\n else el.removeAttribute(key)\n return\n }\n\n if (key in el) {\n ;(el as unknown as Record<string, unknown>)[key] = value\n return\n }\n\n el.setAttribute(key, String(value))\n}\n","import type {\n ComponentFn,\n ForProps,\n NativeItem,\n PortalProps,\n RefProp,\n VNode,\n VNodeChild,\n} from \"@pyreon/core\"\nimport {\n dispatchToErrorBoundary,\n EMPTY_PROPS,\n ForSymbol,\n Fragment,\n PortalSymbol,\n propagateError,\n reportError,\n runWithHooks,\n} from \"@pyreon/core\"\nimport { effectScope, renderEffect, runUntracked, setCurrentScope } from \"@pyreon/reactivity\"\nimport { registerComponent, unregisterComponent } from \"./devtools\"\nimport { mountFor, mountKeyedList, mountReactive } from \"./nodes\"\nimport { applyProps } from \"./props\"\n\nconst __DEV__ = typeof process !== \"undefined\" && process.env.NODE_ENV !== \"production\"\n\ntype Cleanup = () => void\nconst noop: Cleanup = () => {\n /* noop */\n}\n\n// When > 0, we're mounting children inside an element — child cleanups can skip\n// DOM removal (parent element removal handles it). This avoids allocating a\n// removeChild closure for every nested element that has no reactive work.\nlet _elementDepth = 0\n\n// Stack tracking which component is currently being mounted (depth-first order).\n// Used to infer parent/child relationships for DevTools.\nconst _mountingStack: string[] = []\n\n/**\n * Mount a single child into `parent`, inserting before `anchor` (null = append).\n * Returns a cleanup that removes the node(s) and disposes all reactive effects.\n *\n * This function is the hot path — all child types are handled inline to avoid\n * function call overhead in tight render loops (1000+ calls per list render).\n */\nexport function mountChild(\n child: VNodeChild | VNodeChild[] | (() => VNodeChild | VNodeChild[]),\n parent: Node,\n anchor: Node | null = null,\n): Cleanup {\n // Reactive accessor — function that reads signals\n if (typeof child === \"function\") {\n const sample = runUntracked(() => (child as () => VNodeChild | VNodeChild[])())\n if (isKeyedArray(sample)) {\n const prevDepth = _elementDepth\n _elementDepth = 0\n const cleanup = mountKeyedList(child as () => VNode[], parent, anchor, (v, p, a) =>\n mountChild(v, p, a),\n )\n _elementDepth = prevDepth\n return cleanup\n }\n // Text fast path: reactive string/number/boolean — update text.data in-place\n if (typeof sample === \"string\" || typeof sample === \"number\" || typeof sample === \"boolean\") {\n const text = document.createTextNode(sample == null || sample === false ? \"\" : String(sample))\n parent.insertBefore(text, anchor)\n const dispose = renderEffect(() => {\n const v = (child as () => unknown)()\n text.data = v == null || v === false ? \"\" : String(v as string | number)\n })\n if (_elementDepth > 0) return dispose\n return () => {\n dispose()\n const p = text.parentNode\n if (p && (p as Element).isConnected !== false) p.removeChild(text)\n }\n }\n const prevDepth = _elementDepth\n _elementDepth = 0\n const cleanup = mountReactive(child as () => VNodeChild, parent, anchor, mountChild)\n _elementDepth = prevDepth\n return cleanup\n }\n\n // Array of children (e.g. from .map())\n if (Array.isArray(child)) return mountChildren(child, parent, anchor)\n\n // Nothing to render\n if (child == null || child === false) return noop\n\n // Primitive — text node (static, no reactive effects to tear down).\n if (typeof child !== \"object\") {\n parent.insertBefore(document.createTextNode(String(child)), anchor)\n return noop\n }\n\n // NativeItem — pre-built DOM element from _tpl() or createTemplate().\n if ((child as unknown as NativeItem).__isNative) {\n const native = child as unknown as NativeItem\n parent.insertBefore(native.el, anchor)\n if (!native.cleanup) {\n if (_elementDepth > 0) return noop\n return () => {\n const p = native.el.parentNode\n if (p && (p as Element).isConnected !== false) p.removeChild(native.el)\n }\n }\n if (_elementDepth > 0) return native.cleanup\n return () => {\n native.cleanup?.()\n const p = native.el.parentNode\n if (p && (p as Element).isConnected !== false) p.removeChild(native.el)\n }\n }\n\n // VNode — element, component, fragment, For, Portal\n const vnode = child as VNode\n\n if (vnode.type === Fragment) return mountChildren(vnode.children ?? [], parent, anchor)\n\n if (vnode.type === (ForSymbol as unknown as string)) {\n const { each, by, children } = vnode.props as unknown as ForProps<unknown>\n const prevDepth = _elementDepth\n _elementDepth = 0\n const cleanup = mountFor(each, by, children, parent, anchor, mountChild)\n _elementDepth = prevDepth\n return cleanup\n }\n\n if (vnode.type === (PortalSymbol as unknown as string)) {\n const { target, children } = vnode.props as unknown as PortalProps\n if (__DEV__ && !target) {\n console.warn(\"[Pyreon] <Portal> received a falsy `target`. Provide a valid DOM element.\")\n return noop\n }\n if (__DEV__ && !(target instanceof Node)) {\n console.warn(\n `[Pyreon] <Portal> target must be a DOM node. Received ${typeof target}. ` +\n \"Use document.getElementById() or a ref to get the target element.\",\n )\n }\n return mountChild(children, target, null)\n }\n\n if (typeof vnode.type === \"function\") {\n return mountComponent(vnode as VNode & { type: ComponentFn }, parent, anchor)\n }\n\n if (__DEV__ && typeof vnode.type !== \"string\") {\n console.warn(\n `[Pyreon] Invalid VNode type: expected a string tag or component function, ` +\n `received ${typeof vnode.type} (${String(vnode.type)}). ` +\n `This usually means you passed an object or class instead of a component function.`,\n )\n return noop\n }\n\n return mountElement(vnode, parent, anchor)\n}\n\n// ─── Element ─────────────────────────────────────────────────────────────────\n\n// Void elements that cannot have children\nconst VOID_ELEMENTS = new Set([\n \"area\",\n \"base\",\n \"br\",\n \"col\",\n \"embed\",\n \"hr\",\n \"img\",\n \"input\",\n \"link\",\n \"meta\",\n \"param\",\n \"source\",\n \"track\",\n \"wbr\",\n])\n\nfunction mountElement(vnode: VNode, parent: Node, anchor: Node | null): Cleanup {\n const el = document.createElement(vnode.type as string)\n\n if (__DEV__ && (vnode.children?.length ?? 0) > 0 && VOID_ELEMENTS.has(vnode.type as string)) {\n console.warn(\n `[Pyreon] <${vnode.type as string}> is a void element and cannot have children. ` +\n \"Children passed to void elements will be ignored by the browser.\",\n )\n }\n\n // Skip applyProps entirely when props is the shared empty sentinel (identity check — no allocation)\n const props = vnode.props\n const propCleanup: Cleanup | null = props !== EMPTY_PROPS ? applyProps(el, props) : null\n\n // Mount children inside element context — nested elements can skip DOM removal closures\n _elementDepth++\n const childCleanup = mountChildren(vnode.children ?? [], el, null)\n _elementDepth--\n\n parent.insertBefore(el, anchor)\n\n // Populate ref after the element is in the DOM\n const ref = props.ref as RefProp<Element> | null | undefined\n if (ref) {\n if (typeof ref === \"function\") ref(el)\n else ref.current = el\n }\n\n if (!propCleanup && childCleanup === noop && !ref) {\n if (_elementDepth > 0) return noop\n return () => {\n const p = el.parentNode\n if (p && (p as Element).isConnected !== false) p.removeChild(el)\n }\n }\n\n if (_elementDepth > 0) {\n if (!ref && !propCleanup) return childCleanup\n if (!ref && propCleanup)\n return () => {\n propCleanup()\n childCleanup()\n }\n const refToClean = ref\n return () => {\n if (refToClean && typeof refToClean === \"object\") refToClean.current = null\n if (propCleanup) propCleanup()\n childCleanup()\n }\n }\n\n return () => {\n if (ref && typeof ref === \"object\") ref.current = null\n if (propCleanup) propCleanup()\n childCleanup()\n const p = el.parentNode\n if (p && (p as Element).isConnected !== false) p.removeChild(el)\n }\n}\n\n// ─── Component ───────────────────────────────────────────────────────────────\n\nfunction mountComponent(\n vnode: VNode & { type: ComponentFn },\n parent: Node,\n anchor: Node | null,\n): Cleanup {\n const scope = effectScope()\n setCurrentScope(scope)\n\n let hooks: ReturnType<typeof runWithHooks>[\"hooks\"]\n let output: VNodeChild\n\n const componentName = (vnode.type.name || \"Anonymous\") as string\n const compId = `${componentName}-${Math.random().toString(36).slice(2, 9)}`\n const parentId = _mountingStack[_mountingStack.length - 1] ?? null\n _mountingStack.push(compId)\n\n // Merge vnode.children into props.children if not already set\n const children = vnode.children ?? []\n const mergedProps =\n children.length > 0 && (vnode.props as Record<string, unknown>).children === undefined\n ? {\n ...vnode.props,\n children: children.length === 1 ? children[0] : children,\n }\n : vnode.props\n\n try {\n const result = runWithHooks(vnode.type, mergedProps)\n hooks = result.hooks\n output = result.vnode\n } catch (err) {\n _mountingStack.pop()\n setCurrentScope(null)\n scope.stop()\n reportError({\n component: componentName,\n phase: \"setup\",\n error: err,\n timestamp: Date.now(),\n props: vnode.props as Record<string, unknown>,\n })\n const handled = dispatchToErrorBoundary(err)\n if (!handled) {\n console.error(`[Pyreon] <${componentName}> threw during setup:`, err)\n }\n return noop\n } finally {\n setCurrentScope(null)\n }\n\n if (__DEV__ && output != null && typeof output === \"object\") {\n if (output instanceof Promise) {\n console.warn(\n `[Pyreon] Component <${componentName}> returned a Promise. ` +\n \"Components must be synchronous — use lazy() + Suspense for async loading, \" +\n \"or fetch data in onMount and store it in a signal.\",\n )\n } else if (!(\"type\" in output)) {\n console.warn(\n `[Pyreon] Component <${componentName}> returned an invalid value. Components must return a VNode, string, null, or function.`,\n )\n }\n }\n\n for (const fn of hooks.update) {\n scope.addUpdateHook(fn)\n }\n\n let subtreeCleanup: Cleanup = noop\n try {\n subtreeCleanup = output != null ? mountChild(output, parent, anchor) : noop\n } catch (err) {\n _mountingStack.pop()\n scope.stop()\n const handled = propagateError(err, hooks) || dispatchToErrorBoundary(err)\n if (!handled) {\n reportError({\n component: componentName,\n phase: \"render\",\n error: err,\n timestamp: Date.now(),\n props: vnode.props as Record<string, unknown>,\n })\n console.error(`[Pyreon] <${componentName}> threw during render:`, err)\n }\n return noop\n }\n\n _mountingStack.pop()\n\n const firstEl = parent instanceof Element ? parent.firstElementChild : null\n registerComponent(compId, componentName, firstEl, parentId)\n\n // Fire onMount hooks inline — effects created inside are tracked by the scope\n const mountCleanups: Cleanup[] = []\n for (const fn of hooks.mount) {\n try {\n let cleanup: (() => void) | undefined\n scope.runInScope(() => {\n cleanup = fn() as (() => void) | undefined\n })\n if (cleanup) mountCleanups.push(cleanup)\n } catch (err) {\n console.error(`[Pyreon] Error in onMount hook of <${componentName}>:`, err)\n reportError({ component: componentName, phase: \"mount\", error: err, timestamp: Date.now() })\n }\n }\n\n return () => {\n unregisterComponent(compId)\n scope.stop()\n subtreeCleanup()\n for (const fn of hooks.unmount) {\n try {\n fn()\n } catch (err) {\n console.error(`[Pyreon] Error in onUnmount hook of <${componentName}>:`, err)\n reportError({\n component: componentName,\n phase: \"unmount\",\n error: err,\n timestamp: Date.now(),\n })\n }\n }\n for (const fn of mountCleanups) fn()\n }\n}\n\n// ─── Children ────────────────────────────────────────────────────────────────\n\nfunction mountChildren(children: VNodeChild[], parent: Node, anchor: Node | null): Cleanup {\n if (children.length === 0) return noop\n\n // 1-child fast path\n if (children.length === 1) {\n const c = children[0] as VNodeChild\n if (c !== undefined) {\n if (anchor === null && (typeof c === \"string\" || typeof c === \"number\")) {\n ;(parent as HTMLElement).textContent = String(c)\n return noop\n }\n return mountChild(c, parent, anchor)\n }\n }\n\n // 2-child fast path — avoids .map() allocation (covers <tr><td/><td/></tr>)\n if (children.length === 2) {\n const c0 = children[0] as VNodeChild\n const c1 = children[1] as VNodeChild\n if (c0 !== undefined && c1 !== undefined) {\n const d0 = mountChild(c0, parent, anchor)\n const d1 = mountChild(c1, parent, anchor)\n if (d0 === noop && d1 === noop) return noop\n if (d0 === noop) return d1\n if (d1 === noop) return d0\n return () => {\n d0()\n d1()\n }\n }\n }\n\n const cleanups = children.map((c) => mountChild(c, parent, anchor))\n return () => {\n for (const fn of cleanups) fn()\n }\n}\n\n// ─── Keyed array detection ────────────────────────────────────────────────────\n\n/** Returns true if value is a non-empty array of VNodes that all carry keys. */\nfunction isKeyedArray(value: unknown): value is VNode[] {\n if (!Array.isArray(value) || value.length === 0) return false\n return value.every(\n (v) =>\n v !== null &&\n typeof v === \"object\" &&\n !Array.isArray(v) &&\n (v as VNode).key !== null &&\n (v as VNode).key !== undefined,\n )\n}\n","/**\n * SSR Hydration — \"walk-and-claim\" strategy.\n *\n * The server renders plain HTML (no special markers needed). On the client,\n * hydrateRoot walks the VNode tree in parallel with the live DOM tree and:\n *\n * - Static elements → matched by tag position, props attached (events + reactive effects)\n * - Static text → existing text node reused\n * - Reactive text → existing text node found, reactive effect attached to .data\n * - Reactive blocks → comment marker inserted, mountReactive takes over\n * - Components → component fn called, output VNode matched against DOM subtree\n * - For lists → full remount (can't map keys to DOM without SSR markers)\n * - Fragment → transparent, children matched directly\n * - Portal → always remounts into target\n *\n * Falls back to mountChild() whenever DOM structure doesn't match the VNode.\n */\n\nimport type { ComponentFn, Ref, VNode, VNodeChild } from \"@pyreon/core\"\nimport {\n dispatchToErrorBoundary,\n ForSymbol,\n Fragment,\n PortalSymbol,\n reportError,\n runWithHooks,\n} from \"@pyreon/core\"\nimport { effectScope, renderEffect, runUntracked, setCurrentScope } from \"@pyreon/reactivity\"\nimport { setupDelegation } from \"./delegate\"\nimport { warnHydrationMismatch } from \"./hydration-debug\"\nimport { mountChild } from \"./mount\"\nimport { mountReactive } from \"./nodes\"\nimport { applyProps } from \"./props\"\n\ntype Cleanup = () => void\nconst noop: Cleanup = () => {\n /* noop */\n}\n\n// ─── DOM cursor helpers ───────────────────────────────────────────────────────\n\n/** Skip comment and whitespace-only text nodes, return first \"real\" node */\nfunction firstReal(initialNode: ChildNode | null): ChildNode | null {\n let node = initialNode\n while (node) {\n if (node.nodeType === Node.COMMENT_NODE) {\n node = node.nextSibling\n continue\n }\n if (node.nodeType === Node.TEXT_NODE && isWhitespaceOnly((node as Text).data)) {\n node = node.nextSibling\n continue\n }\n return node\n }\n return null\n}\n\n/** Check if a string is whitespace-only without allocating a trimmed copy. */\nfunction isWhitespaceOnly(s: string): boolean {\n for (let i = 0; i < s.length; i++) {\n const c = s.charCodeAt(i)\n // space, tab, newline, carriage return, form feed\n if (c !== 32 && c !== 9 && c !== 10 && c !== 13 && c !== 12) return false\n }\n return true\n}\n\n/** Advance past a node, skipping whitespace-only text and comments */\nfunction nextReal(node: ChildNode): ChildNode | null {\n return firstReal(node.nextSibling)\n}\n\n// ─── Core recursive walker ────────────────────────────────────────────────────\n\n/**\n * Hydrate a single VNodeChild against the DOM subtree starting at `domNode`.\n * Returns [cleanup, nextDomSibling].\n */\n/** Insert a comment marker before domNode (or append if domNode is null). */\nfunction insertMarker(parent: Node, domNode: ChildNode | null, text: string): Comment {\n const marker = document.createComment(text)\n if (domNode) {\n parent.insertBefore(marker, domNode)\n } else {\n parent.appendChild(marker)\n }\n return marker\n}\n\n/** Hydrate a reactive accessor (function child). */\nfunction hydrateReactiveChild(\n child: () => VNodeChild,\n domNode: ChildNode | null,\n parent: Node,\n anchor: Node | null,\n path: string,\n): [Cleanup, ChildNode | null] {\n const initial = runUntracked(child)\n\n if (initial == null || initial === false) {\n const marker = insertMarker(parent, domNode, \"pyreon\")\n const cleanup = mountReactive(child, parent, marker, mountChild)\n return [cleanup, domNode]\n }\n\n if (typeof initial === \"string\" || typeof initial === \"number\" || typeof initial === \"boolean\") {\n return hydrateReactiveText(\n child as () => string | number | boolean | null | undefined,\n domNode,\n parent,\n anchor,\n path,\n )\n }\n\n const marker = insertMarker(parent, domNode, \"pyreon\")\n const cleanup = mountReactive(child, parent, marker, mountChild)\n const next = domNode ? nextReal(domNode) : null\n return [cleanup, next]\n}\n\n/** Hydrate a reactive text binding against an existing text node. */\nfunction hydrateReactiveText(\n child: () => string | number | boolean | null | undefined,\n domNode: ChildNode | null,\n parent: Node,\n anchor: Node | null,\n path: string,\n): [Cleanup, ChildNode | null] {\n if (domNode?.nodeType === Node.TEXT_NODE) {\n const textNode = domNode as Text\n const dispose = renderEffect(() => {\n const v = child()\n textNode.data = v == null ? \"\" : String(v)\n })\n return [dispose, nextReal(domNode)]\n }\n warnHydrationMismatch(\"text\", \"TextNode\", domNode?.nodeType ?? \"null\", `${path} > reactive`)\n const cleanup = mountChild(child, parent, anchor)\n return [cleanup, domNode]\n}\n\n/** Hydrate a VNode (fragment, For, Portal, component, element). */\nfunction hydrateVNode(\n vnode: VNode,\n domNode: ChildNode | null,\n parent: Node,\n anchor: Node | null,\n path: string,\n): [Cleanup, ChildNode | null] {\n if (vnode.type === Fragment) {\n return hydrateChildren(vnode.children ?? [], domNode, parent, anchor, path)\n }\n\n if (vnode.type === ForSymbol) {\n const marker = insertMarker(parent, domNode, \"pyreon-for\")\n const cleanup = mountChild(vnode, parent, marker)\n return [cleanup, null]\n }\n\n if (vnode.type === PortalSymbol) {\n const cleanup = mountChild(vnode, parent, anchor)\n return [cleanup, domNode]\n }\n\n if (typeof vnode.type === \"function\") {\n return hydrateComponent(vnode, domNode, parent, anchor, path)\n }\n\n if (typeof vnode.type === \"string\") {\n return hydrateElement(vnode, domNode, parent, anchor, path)\n }\n\n return [noop, domNode]\n}\n\nfunction hydrateChild(\n child: VNodeChild | VNodeChild[],\n domNode: ChildNode | null,\n parent: Node,\n anchor: Node | null,\n path = \"root\",\n): [Cleanup, ChildNode | null] {\n if (Array.isArray(child)) {\n const cleanups: Cleanup[] = []\n let cursor = domNode\n for (const c of child) {\n const [cleanup, next] = hydrateChild(c, cursor, parent, anchor, path)\n cleanups.push(cleanup)\n cursor = next\n }\n return [\n () => {\n for (const c of cleanups) c()\n },\n cursor,\n ]\n }\n\n if (child == null || child === false) return [noop, domNode]\n\n if (typeof child === \"function\") {\n return hydrateReactiveChild(child as () => VNodeChild, domNode, parent, anchor, path)\n }\n\n if (typeof child === \"string\" || typeof child === \"number\") {\n if (domNode?.nodeType === Node.TEXT_NODE) {\n return [() => (domNode as Text).remove(), nextReal(domNode)]\n }\n warnHydrationMismatch(\"text\", \"TextNode\", domNode?.nodeType ?? \"null\", `${path} > text`)\n const cleanup = mountChild(child, parent, anchor)\n return [cleanup, domNode]\n }\n\n return hydrateVNode(child as VNode, domNode, parent, anchor, path)\n}\n\n// ─── Element hydration ────────────────────────────────────────────────────────\n\nfunction hydrateElement(\n vnode: VNode,\n domNode: ChildNode | null,\n parent: Node,\n anchor: Node | null,\n path = \"root\",\n): [Cleanup, ChildNode | null] {\n const elPath = `${path} > ${vnode.type as string}`\n\n // Check if existing DOM node matches\n if (\n domNode?.nodeType === Node.ELEMENT_NODE &&\n (domNode as Element).tagName.toLowerCase() === vnode.type\n ) {\n const el = domNode as Element\n const cleanups: Cleanup[] = []\n\n // Attach props (events + reactive effects) — don't set static attrs (SSR already did)\n const propCleanup = applyProps(el, vnode.props)\n if (propCleanup) cleanups.push(propCleanup)\n\n // Hydrate children\n const firstChild = firstReal(el.firstChild as ChildNode | null)\n const [childCleanup] = hydrateChildren(vnode.children ?? [], firstChild, el, null, elPath)\n cleanups.push(childCleanup)\n\n // Set ref\n const ref = vnode.props.ref as Ref<Element> | ((el: Element) => void) | undefined\n if (ref) {\n if (typeof ref === \"function\") ref(el)\n else ref.current = el\n }\n\n const cleanup = () => {\n if (ref && typeof ref === \"object\") ref.current = null\n for (const c of cleanups) c()\n el.remove()\n }\n\n return [cleanup, nextReal(domNode)]\n }\n\n // Mismatch — fall back to fresh mount\n const actual =\n domNode?.nodeType === Node.ELEMENT_NODE\n ? (domNode as Element).tagName.toLowerCase()\n : (domNode?.nodeType ?? \"null\")\n warnHydrationMismatch(\"tag\", vnode.type, actual, elPath)\n const cleanup = mountChild(vnode, parent, anchor)\n return [cleanup, domNode]\n}\n\n// ─── Children hydration ───────────────────────────────────────────────────────\n\nfunction hydrateChildren(\n children: VNodeChild[],\n domNode: ChildNode | null,\n parent: Node,\n anchor: Node | null,\n path = \"root\",\n): [Cleanup, ChildNode | null] {\n if (children.length === 0) return [noop, domNode]\n\n // Single-child fast path — avoids cleanups array allocation\n if (children.length === 1) {\n return hydrateChild(children[0] as VNodeChild, domNode, parent, anchor, path)\n }\n\n const cleanups: Cleanup[] = []\n let cursor = domNode\n for (const child of children) {\n const [cleanup, next] = hydrateChild(child, cursor, parent, anchor, path)\n cleanups.push(cleanup)\n cursor = next\n }\n return [\n () => {\n for (const c of cleanups) c()\n },\n cursor,\n ]\n}\n\n// ─── Component hydration ──────────────────────────────────────────────────────\n\nfunction hydrateComponent(\n vnode: VNode,\n domNode: ChildNode | null,\n parent: Node,\n anchor: Node | null,\n path = \"root\",\n): [Cleanup, ChildNode | null] {\n const scope = effectScope()\n setCurrentScope(scope)\n\n let subtreeCleanup: Cleanup = noop\n const mountCleanups: Cleanup[] = []\n let nextDom: ChildNode | null = domNode\n\n // Function.name is always a string per spec; || handles empty string, avoids uncoverable ?? branch\n const componentName = ((vnode.type as ComponentFn).name || \"Anonymous\") as string\n const mergedProps =\n (vnode.children ?? []).length > 0 &&\n (vnode.props as Record<string, unknown>).children === undefined\n ? {\n ...vnode.props,\n children:\n (vnode.children ?? []).length === 1\n ? (vnode.children ?? [])[0]\n : (vnode.children ?? []),\n }\n : vnode.props\n\n let result: ReturnType<typeof runWithHooks>\n try {\n result = runWithHooks(vnode.type as ComponentFn, mergedProps)\n } catch (err) {\n setCurrentScope(null)\n scope.stop()\n\n console.error(`[Pyreon] Error hydrating component <${componentName}>:`, err)\n reportError({\n component: componentName,\n phase: \"setup\",\n error: err,\n timestamp: Date.now(),\n props: vnode.props as Record<string, unknown>,\n })\n dispatchToErrorBoundary(err)\n return [noop, domNode]\n }\n setCurrentScope(null)\n\n const { vnode: output, hooks } = result\n\n // Register onUpdate hooks with the scope\n for (const fn of hooks.update) {\n scope.addUpdateHook(fn)\n }\n\n if (output != null) {\n const [childCleanup, next] = hydrateChild(output, domNode, parent, anchor, path)\n subtreeCleanup = childCleanup\n nextDom = next\n }\n\n // Fire onMount hooks; effects created inside are tracked by the scope via runInScope\n for (const fn of hooks.mount) {\n try {\n let c: (() => void) | undefined\n scope.runInScope(() => {\n c = fn() as (() => void) | undefined\n })\n if (c) mountCleanups.push(c)\n } catch (err) {\n reportError({ component: componentName, phase: \"mount\", error: err, timestamp: Date.now() })\n }\n }\n\n const cleanup: Cleanup = () => {\n scope.stop()\n subtreeCleanup()\n for (const fn of hooks.unmount) fn()\n for (const fn of mountCleanups) fn()\n }\n\n return [cleanup, nextDom]\n}\n\n// ─── Public API ───────────────────────────────────────────────────────────────\n\n/**\n * Hydrate a server-rendered container with a Pyreon VNode tree.\n *\n * Reuses existing DOM elements for static structure, attaches event listeners\n * and reactive effects without re-rendering. Falls back to fresh mount for\n * dynamic content (reactive conditionals, For lists).\n *\n * @example\n * // Server:\n * const html = await renderToString(h(App, null))\n *\n * // Client:\n * const unmount = hydrateRoot(document.getElementById(\"app\")!, h(App, null))\n */\nexport function hydrateRoot(container: Element, vnode: VNodeChild): () => void {\n setupDelegation(container)\n const firstChild = firstReal(container.firstChild as ChildNode | null)\n const [cleanup] = hydrateChild(vnode, firstChild, container, null)\n return cleanup\n}\n","import type { Props, VNodeChild } from \"@pyreon/core\"\nimport { createRef, h, onMount } from \"@pyreon/core\"\nimport { effect } from \"@pyreon/reactivity\"\nimport { mountChild } from \"./mount\"\n\nexport interface KeepAliveProps extends Props {\n /**\n * Accessor that returns true when this slot's children should be visible.\n * When false, children are CSS-hidden but remain mounted — effects and\n * signals stay alive.\n * Defaults to true (always visible / always mounted).\n */\n active?: () => boolean\n children?: VNodeChild\n}\n\n/**\n * KeepAlive — mounts its children once and keeps them alive even when hidden.\n *\n * Unlike conditional rendering (which destroys and recreates component state),\n * KeepAlive CSS-hides the children while preserving all reactive state,\n * scroll position, form values, and in-flight async operations.\n *\n * Children are mounted imperatively on first activation and are never unmounted\n * while the KeepAlive itself is mounted.\n *\n * Multi-slot pattern (one KeepAlive per route):\n * @example\n * h(Fragment, null, [\n * h(KeepAlive, { active: () => route() === \"/a\" }, h(RouteA, null)),\n * h(KeepAlive, { active: () => route() === \"/b\" }, h(RouteB, null)),\n * ])\n *\n * With JSX:\n * @example\n * <>\n * <KeepAlive active={() => route() === \"/a\"}><RouteA /></KeepAlive>\n * <KeepAlive active={() => route() === \"/b\"}><RouteB /></KeepAlive>\n * </>\n */\nexport function KeepAlive(props: KeepAliveProps): VNodeChild {\n const containerRef = createRef<HTMLElement>()\n let childCleanup: (() => void) | null = null\n let childMounted = false\n\n onMount(() => {\n const container = containerRef.current as HTMLElement\n\n const e = effect(() => {\n const isActive = props.active?.() ?? true\n\n if (!childMounted) {\n // Mount children into the container div exactly once\n childCleanup = mountChild(props.children ?? null, container, null)\n childMounted = true\n }\n\n // Show/hide without unmounting — state is fully preserved\n container.style.display = isActive ? \"\" : \"none\"\n })\n\n return () => {\n e.dispose()\n childCleanup?.()\n }\n })\n\n // `display: contents` makes the wrapper transparent to layout\n // (children appear as if directly in the parent flow)\n return h(\"div\", { ref: containerRef, style: \"display: contents\" })\n}\n","import type { NativeItem } from \"@pyreon/core\"\nimport { renderEffect } from \"@pyreon/reactivity\"\n\n/**\n * Creates a row/item factory backed by HTML template cloning.\n *\n * - The HTML string is parsed exactly once via <template>.innerHTML.\n * - Each call to the returned factory clones the root element via\n * cloneNode(true) — ~5-10x faster than createElement + setAttribute.\n * - `bind` receives the cloned element and the item; it should wire up\n * reactive effects and return a cleanup function.\n * - Returns a NativeItem directly (no VNode wrapper) — saves 2 allocations\n * per row vs the old VNode + props-object + children-array approach.\n *\n * @example\n * const rowTemplate = createTemplate<Row>(\n * \"<tr><td></td><td></td></tr>\",\n * (el, row) => {\n * const td1 = el.firstChild as HTMLElement\n * const td2 = td1.nextSibling as HTMLElement\n * td1.textContent = String(row.id)\n * const text = td2.firstChild as Text\n * text.data = row.label()\n * const unsub = row.label.subscribe(() => { text.data = row.label() })\n * return unsub\n * }\n * )\n */\nexport function createTemplate<T>(\n html: string,\n bind: (el: HTMLElement, item: T) => (() => void) | null,\n): (item: T) => NativeItem {\n const tmpl = document.createElement(\"template\")\n tmpl.innerHTML = html\n const proto = tmpl.content.firstElementChild as HTMLElement\n\n return (item: T): NativeItem => {\n const el = proto.cloneNode(true) as HTMLElement\n const cleanup = bind(el, item)\n return { __isNative: true, el, cleanup }\n }\n}\n\n// ─── Direct text binding (bypasses effect system) ────────────────────────────\n\n/**\n * Compiler-emitted direct text binding for single-signal text nodes.\n *\n * When the compiler detects `{signal()}` as the only reactive expression\n * in a text binding, it emits `_bindText(signal, textNode)` instead of\n * `_bind(() => { textNode.data = signal() })`.\n *\n * This bypasses the effect system entirely:\n * - No deps array allocation\n * - No withTracking / setDepsCollector overhead\n * - No `run` closure\n * - Signal.subscribe is used directly (O(1) subscribe + unsubscribe)\n *\n * @param source - A signal (anything with `._v` and `.direct`)\n * @param node - The Text node to update\n */\nexport function _bindText(\n source: { _v?: unknown; direct?: (fn: () => void) => () => void },\n node: Text,\n): () => void {\n // Fast path: source has .direct() (signal or computed)\n if (source.direct) {\n const textUpdate = () => {\n const v = source._v\n node.data = v == null || v === false ? \"\" : String(v as string | number)\n }\n textUpdate()\n return source.direct(textUpdate)\n }\n // Fallback: source is a plain callable (e.g. store getter, createMachine) — use renderEffect\n const fn = source as unknown as () => unknown\n return renderEffect(() => {\n const v = fn()\n node.data = v == null || v === false ? \"\" : String(v as string | number)\n })\n}\n\n// ─── Direct signal binding (bypasses effect system) ──────────────────────────\n\n/**\n * Compiler-emitted direct binding for single-signal reactive expressions.\n *\n * Like _bindText but for arbitrary DOM updates (attributes, className, style).\n * When the compiler detects that a reactive expression depends on exactly one\n * signal call, it emits `_bindDirect(signal, updater)` instead of\n * `_bind(() => { updater() })`.\n *\n * Uses signal.direct() for zero-overhead registration:\n * - Flat array instead of Set (no hashing)\n * - Index-based disposal (no Set.delete)\n * - No deps array, no withTracking, no run closure\n *\n * @param source - A signal (anything with `._v` and `.direct`)\n * @param updater - Function that reads `source._v` and applies the DOM update\n */\nexport function _bindDirect(\n source: { _v?: unknown; direct?: (fn: () => void) => () => void },\n updater: (value: unknown) => void,\n): () => void {\n // Fast path: source has .direct() (signal or computed)\n if (source.direct) {\n updater(source._v)\n return source.direct(() => updater(source._v))\n }\n // Fallback: plain callable — use renderEffect\n const fn = source as unknown as () => unknown\n return renderEffect(() => updater(fn()))\n}\n\n// ─── Compiler-facing template API ─────────────────────────────────────────────\n\n// Cache parsed <template> elements by HTML string — parse once, clone many.\nconst _tplCache = new Map<string, HTMLTemplateElement>()\n\n/**\n * Compiler-emitted template instantiation.\n *\n * Parses `html` into a <template> element once (cached), then cloneNode(true)\n * for each call. The `bind` function wires up dynamic attributes, text content,\n * and event listeners on the cloned element tree. Returns a NativeItem that\n * mountChild can insert directly — no VNode allocation.\n *\n * This is the runtime half of the compiler's template optimisation. The compiler\n * detects static JSX element trees and emits `_tpl(html, bindFn)` instead of\n * nested `h()` calls. Benefits:\n * - cloneNode(true) is ~5-10x faster than sequential createElement + setAttribute\n * - Zero VNode / props-object / children-array allocations per instance\n * - Static attributes are baked into the HTML string (no runtime prop application)\n *\n * @example\n * // Compiler output for: <div class=\"box\"><span>{text()}</span></div>\n * _tpl('<div class=\"box\"><span></span></div>', (__root) => {\n * const __e0 = __root.children[0];\n * const __d0 = _re(() => { __e0.textContent = text(); });\n * return () => { __d0(); };\n * })\n */\nexport function _tpl(html: string, bind: (el: HTMLElement) => (() => void) | null): NativeItem {\n let tpl = _tplCache.get(html)\n if (!tpl) {\n tpl = document.createElement(\"template\")\n tpl.innerHTML = html\n _tplCache.set(html, tpl)\n }\n const el = tpl.content.firstElementChild?.cloneNode(true) as HTMLElement\n const cleanup = bind(el)\n return { __isNative: true, el, cleanup }\n}\n","import type { Props, VNode, VNodeChild } from \"@pyreon/core\"\nimport { createRef, Fragment, h, onUnmount } from \"@pyreon/core\"\nimport { effect, runUntracked, signal } from \"@pyreon/reactivity\"\n\nconst __DEV__ = typeof process !== \"undefined\" && process.env.NODE_ENV !== \"production\"\n\nexport interface TransitionProps {\n /**\n * CSS class name prefix.\n * \"fade\" → fade-enter-from, fade-enter-active, fade-enter-to, fade-leave-from, …\n * Default: \"pyreon\"\n */\n name?: string\n /** Reactive boolean controlling whether the child is shown. */\n show: () => boolean\n /**\n * If true, runs the enter transition on the initial mount (instead of\n * appearing immediately). Default: false.\n */\n appear?: boolean\n // Individual class name overrides (override the prefix-based defaults)\n enterFrom?: string\n enterActive?: string\n enterTo?: string\n leaveFrom?: string\n leaveActive?: string\n leaveTo?: string\n // Lifecycle callbacks\n onBeforeEnter?: (el: HTMLElement) => void\n onAfterEnter?: (el: HTMLElement) => void\n onBeforeLeave?: (el: HTMLElement) => void\n onAfterLeave?: (el: HTMLElement) => void\n /**\n * The single child element to animate.\n * Must be a direct DOM element VNode (not a component) for class injection to work.\n */\n children?: VNodeChild\n}\n\n/**\n * Transition — adds CSS enter/leave animation classes to a single child element,\n * controlled by the reactive `show` prop.\n *\n * Class lifecycle:\n * Enter: {name}-enter-from → (next frame) → {name}-enter-active + {name}-enter-to → cleanup\n * Leave: {name}-leave-from → (next frame) → {name}-leave-active + {name}-leave-to → unmount\n *\n * The child element stays in the DOM during the leave animation and is removed only\n * after the CSS transition / animation completes.\n *\n * @example\n * const visible = signal(false)\n *\n * h(Transition, { name: \"fade\", show: () => visible() },\n * h(\"div\", { class: \"modal\" }, \"content\")\n * )\n *\n * // CSS:\n * // .fade-enter-from, .fade-leave-to { opacity: 0; }\n * // .fade-enter-active, .fade-leave-active { transition: opacity 300ms ease; }\n */\nexport function Transition(props: TransitionProps): VNodeChild {\n const n = props.name ?? \"pyreon\"\n const cls = {\n ef: props.enterFrom ?? `${n}-enter-from`,\n ea: props.enterActive ?? `${n}-enter-active`,\n et: props.enterTo ?? `${n}-enter-to`,\n lf: props.leaveFrom ?? `${n}-leave-from`,\n la: props.leaveActive ?? `${n}-leave-active`,\n lt: props.leaveTo ?? `${n}-leave-to`,\n }\n\n // Ref injected into the child element so we can apply/remove classes\n const ref = createRef<HTMLElement>()\n const isMounted = signal(runUntracked<boolean>(props.show))\n\n // Cancel an in-progress leave when re-entering before the animation ends\n let pendingLeaveCancel: (() => void) | null = null\n let initialized = false\n\n const applyEnter = (el: HTMLElement) => {\n pendingLeaveCancel?.()\n pendingLeaveCancel = null\n props.onBeforeEnter?.(el)\n el.classList.remove(cls.lf, cls.la, cls.lt)\n el.classList.add(cls.ef, cls.ea)\n requestAnimationFrame(() => {\n el.classList.remove(cls.ef)\n el.classList.add(cls.et)\n const done = () => {\n // Remove both listeners — only one fires, so clean up the other\n el.removeEventListener(\"transitionend\", done)\n el.removeEventListener(\"animationend\", done)\n el.classList.remove(cls.ea, cls.et)\n props.onAfterEnter?.(el)\n }\n el.addEventListener(\"transitionend\", done, { once: true })\n el.addEventListener(\"animationend\", done, { once: true })\n })\n }\n\n const applyLeave = (el: HTMLElement) => {\n props.onBeforeLeave?.(el)\n el.classList.remove(cls.ef, cls.ea, cls.et)\n el.classList.add(cls.lf, cls.la)\n requestAnimationFrame(() => {\n el.classList.remove(cls.lf)\n el.classList.add(cls.lt)\n const done = () => {\n // Remove both listeners — only one fires, so clean up the other\n el.removeEventListener(\"transitionend\", done)\n el.removeEventListener(\"animationend\", done)\n el.classList.remove(cls.la, cls.lt)\n pendingLeaveCancel = null\n isMounted.set(false)\n props.onAfterLeave?.(el)\n }\n pendingLeaveCancel = () => {\n el.removeEventListener(\"transitionend\", done)\n el.removeEventListener(\"animationend\", done)\n el.classList.remove(cls.lf, cls.la, cls.lt)\n }\n el.addEventListener(\"transitionend\", done, { once: true })\n el.addEventListener(\"animationend\", done, { once: true })\n })\n }\n\n const handleVisibilityChange = (visible: boolean) => {\n if (visible) {\n if (!isMounted.peek()) isMounted.set(true)\n queueMicrotask(() => applyEnter(ref.current as HTMLElement))\n return\n }\n if (!isMounted.peek()) return\n const el = ref.current\n if (!el) {\n isMounted.set(false)\n return\n }\n applyLeave(el)\n }\n\n effect(() => {\n const visible = props.show()\n if (!initialized) {\n initialized = true\n if (visible && props.appear) {\n queueMicrotask(() => applyEnter(ref.current as HTMLElement))\n }\n return\n }\n handleVisibilityChange(visible)\n })\n\n onUnmount(() => {\n pendingLeaveCancel?.()\n pendingLeaveCancel = null\n })\n\n // Return a reactive getter. Each call clones the child VNode with our injected ref\n // so we can read / write classes on the underlying DOM element.\n const rawChild = props.children\n // Return an empty Fragment (not null) when unmounted so mountChild uses\n // mountReactive instead of the null/primitive text-node fast-path, which\n // cannot later be swapped for a VNode when the element enters.\n const emptyFragment = h(Fragment, null)\n return (() => {\n if (!isMounted()) return emptyFragment\n if (!rawChild || typeof rawChild !== \"object\" || Array.isArray(rawChild)) {\n return rawChild ?? null\n }\n const vnode = rawChild as VNode\n // Only inject ref into DOM element children — component children need ref forwarding\n if (typeof vnode.type !== \"string\") {\n if (__DEV__) {\n console.warn(\n \"[Pyreon] Transition child is a component. Wrap it in a DOM element for enter/leave animations to work.\",\n )\n }\n return vnode\n }\n return { ...vnode, props: { ...vnode.props, ref } as Props }\n }) as unknown as VNode\n}\n","import type { Props, VNode, VNodeChild } from \"@pyreon/core\"\nimport { createRef, h, onMount, onUnmount } from \"@pyreon/core\"\nimport { effect, runUntracked, signal } from \"@pyreon/reactivity\"\nimport { mountChild } from \"./mount\"\n\nexport interface TransitionGroupProps<T = unknown> {\n /** Wrapper element tag. Default: \"div\" */\n tag?: string\n /** CSS class prefix. Default: \"pyreon\" */\n name?: string\n /** Animate items on initial mount. Default: false */\n appear?: boolean\n // CSS class overrides\n enterFrom?: string\n enterActive?: string\n enterTo?: string\n leaveFrom?: string\n leaveActive?: string\n leaveTo?: string\n /** Class applied during FLIP move animation. Default: \"{name}-move\" */\n moveClass?: string\n /** Reactive list source */\n items: () => T[]\n /** Stable key extractor */\n keyFn: (item: T, index: number) => string | number\n /**\n * Render a single DOM-element VNode for each item.\n * Must return a VNode whose `type` is a string (e.g. \"div\", \"li\") so\n * the component can inject a ref and read the underlying DOM node.\n */\n render: (item: T, index: number) => VNode\n // Lifecycle callbacks\n onBeforeEnter?: (el: HTMLElement) => void\n onAfterEnter?: (el: HTMLElement) => void\n onBeforeLeave?: (el: HTMLElement) => void\n onAfterLeave?: (el: HTMLElement) => void\n}\n\ntype ItemEntry = {\n key: string | number\n ref: ReturnType<typeof createRef<HTMLElement>>\n cleanup: () => void\n leaving: boolean\n}\n\n/**\n * TransitionGroup — animates a keyed reactive list with CSS enter/leave and\n * FLIP move animations.\n *\n * Class lifecycle:\n * Enter: {name}-enter-from → {name}-enter-active + {name}-enter-to → cleanup\n * Leave: {name}-leave-from → {name}-leave-active + {name}-leave-to → item removed\n * Move: {name}-move (applied when an item shifts position)\n *\n * @example\n * const items = signal([{ id: 1 }, { id: 2 }])\n *\n * h(TransitionGroup, {\n * tag: \"ul\",\n * name: \"list\",\n * items,\n * keyFn: (item) => item.id,\n * render: (item) => h(\"li\", { class: \"item\" }, item.id),\n * })\n *\n * // CSS:\n * // .list-enter-from, .list-leave-to { opacity: 0; transform: translateY(-10px); }\n * // .list-enter-active, .list-leave-active { transition: all 300ms ease; }\n * // .list-move { transition: transform 300ms ease; }\n */\nexport function TransitionGroup<T = unknown>(props: TransitionGroupProps<T>): VNodeChild {\n const tag = props.tag ?? \"div\"\n const n = props.name ?? \"pyreon\"\n const cls = {\n ef: props.enterFrom ?? `${n}-enter-from`,\n ea: props.enterActive ?? `${n}-enter-active`,\n et: props.enterTo ?? `${n}-enter-to`,\n lf: props.leaveFrom ?? `${n}-leave-from`,\n la: props.leaveActive ?? `${n}-leave-active`,\n lt: props.leaveTo ?? `${n}-leave-to`,\n mv: props.moveClass ?? `${n}-move`,\n }\n\n const containerRef = createRef<HTMLElement>()\n const entries = new Map<string | number, ItemEntry>()\n // Gates the effect until the container element is in the DOM\n const ready = signal(false)\n let firstRun = true\n\n const applyEnter = (el: HTMLElement) => {\n props.onBeforeEnter?.(el)\n el.classList.remove(cls.lf, cls.la, cls.lt)\n el.classList.add(cls.ef, cls.ea)\n requestAnimationFrame(() => {\n el.classList.remove(cls.ef)\n el.classList.add(cls.et)\n const done = () => {\n el.removeEventListener(\"transitionend\", done)\n el.removeEventListener(\"animationend\", done)\n el.classList.remove(cls.ea, cls.et)\n props.onAfterEnter?.(el)\n }\n el.addEventListener(\"transitionend\", done, { once: true })\n el.addEventListener(\"animationend\", done, { once: true })\n })\n }\n\n const applyLeave = (el: HTMLElement, onDone: () => void) => {\n props.onBeforeLeave?.(el)\n el.classList.remove(cls.ef, cls.ea, cls.et)\n el.classList.add(cls.lf, cls.la)\n requestAnimationFrame(() => {\n el.classList.remove(cls.lf)\n el.classList.add(cls.lt)\n const done = () => {\n el.removeEventListener(\"transitionend\", done)\n el.removeEventListener(\"animationend\", done)\n el.classList.remove(cls.la, cls.lt)\n props.onAfterLeave?.(el)\n onDone()\n }\n el.addEventListener(\"transitionend\", done, { once: true })\n el.addEventListener(\"animationend\", done, { once: true })\n })\n }\n\n /** Start leave animation for removed items. */\n const processLeaves = (newKeys: Set<string | number>) => {\n for (const [key, entry] of entries) {\n if (newKeys.has(key) || entry.leaving) continue\n entry.leaving = true\n const el = entry.ref.current\n if (el) {\n applyLeave(el, () => {\n entry.cleanup()\n entries.delete(key)\n })\n } else {\n entry.cleanup()\n entries.delete(key)\n }\n }\n }\n\n /** Mount new items and return the list of newly created entries. */\n const mountNewItems = (items: T[], container: HTMLElement): ItemEntry[] => {\n const newEntries: ItemEntry[] = []\n for (let i = 0; i < items.length; i++) {\n const item = items[i] as T\n const key = props.keyFn(item, i)\n if (entries.has(key)) continue\n const itemRef = createRef<HTMLElement>()\n const rawVNode = runUntracked(() => props.render(item, i))\n const vnode: VNode =\n typeof rawVNode.type === \"string\"\n ? { ...rawVNode, props: { ...rawVNode.props, ref: itemRef } as Props }\n : rawVNode\n const cleanup = mountChild(vnode, container, null)\n const entry: ItemEntry = { key, ref: itemRef, cleanup, leaving: false }\n entries.set(key, entry)\n newEntries.push(entry)\n }\n return newEntries\n }\n\n const startMoveAnimation = (el: HTMLElement) => {\n requestAnimationFrame(() => {\n el.classList.add(cls.mv)\n el.style.transform = \"\"\n el.style.transition = \"\"\n const done = () => {\n el.removeEventListener(\"transitionend\", done)\n el.removeEventListener(\"animationend\", done)\n el.classList.remove(cls.mv)\n }\n el.addEventListener(\"transitionend\", done, { once: true })\n el.addEventListener(\"animationend\", done, { once: true })\n })\n }\n\n const flipEntry = (entry: ItemEntry, oldPos: DOMRect) => {\n if (!entry.ref.current) return\n const newPos = entry.ref.current.getBoundingClientRect()\n const dx = oldPos.left - newPos.left\n const dy = oldPos.top - newPos.top\n if (Math.abs(dx) < 1 && Math.abs(dy) < 1) return\n const el = entry.ref.current\n el.style.transform = `translate(${dx}px, ${dy}px)`\n el.style.transition = \"none\"\n startMoveAnimation(el)\n }\n\n /** Apply FLIP move animations for items that shifted position. */\n const applyFlipMoves = (oldPositions: Map<string | number, DOMRect>) => {\n requestAnimationFrame(() => {\n for (const [key, entry] of entries) {\n if (entry.leaving) continue\n const oldPos = oldPositions.get(key)\n if (!oldPos) continue\n flipEntry(entry, oldPos)\n }\n })\n }\n\n const recordOldPositions = (): Map<string | number, DOMRect> => {\n const oldPositions = new Map<string | number, DOMRect>()\n for (const [key, entry] of entries) {\n if (!entry.leaving && entry.ref.current) {\n oldPositions.set(key, entry.ref.current.getBoundingClientRect())\n }\n }\n return oldPositions\n }\n\n const reorderEntries = (items: T[], container: HTMLElement) => {\n for (let i = 0; i < items.length; i++) {\n const key = props.keyFn(items[i] as T, i)\n const entry = entries.get(key)\n if (!entry || entry.leaving || !entry.ref.current) continue\n container.appendChild(entry.ref.current)\n }\n }\n\n const animateNewEntries = (newEntries: ItemEntry[]) => {\n for (const entry of newEntries) {\n queueMicrotask(() => {\n if (entry.ref.current) applyEnter(entry.ref.current)\n })\n }\n }\n\n const e = effect(() => {\n if (!ready()) return\n const container = containerRef.current\n if (!container) return\n\n const items = props.items()\n const newKeys = new Set(items.map((item, i) => props.keyFn(item, i)))\n const isFirst = firstRun\n firstRun = false\n\n const oldPositions = recordOldPositions()\n processLeaves(newKeys)\n const newEntries = mountNewItems(items, container)\n reorderEntries(items, container)\n\n if (!isFirst || props.appear) animateNewEntries(newEntries)\n if (!isFirst && oldPositions.size > 0) applyFlipMoves(oldPositions)\n })\n\n // Fire the effect once the container is in the DOM\n onMount(() => {\n ready.set(true)\n })\n\n onUnmount(() => {\n e.dispose()\n for (const entry of entries.values()) entry.cleanup()\n entries.clear()\n })\n\n return h(tag, { ref: containerRef })\n}\n","// @pyreon/runtime-dom — surgical signal-to-DOM renderer (no virtual DOM)\n\nexport { DELEGATED_EVENTS, delegatedPropName, setupDelegation } from \"./delegate\"\nexport type { DevtoolsComponentEntry, PyreonDevtools } from \"./devtools\"\nexport { hydrateRoot } from \"./hydrate\"\nexport { disableHydrationWarnings, enableHydrationWarnings } from \"./hydration-debug\"\nexport type { KeepAliveProps } from \"./keep-alive\"\nexport { KeepAlive } from \"./keep-alive\"\nexport { mountChild } from \"./mount\"\nexport type { SanitizeFn } from \"./props\"\nexport { applyProp, applyProps, sanitizeHtml, setSanitizer } from \"./props\"\nexport { _bindDirect, _bindText, _tpl, createTemplate } from \"./template\"\nexport type { TransitionProps } from \"./transition\"\nexport { Transition } from \"./transition\"\nexport type { TransitionGroupProps } from \"./transition-group\"\nexport { TransitionGroup } from \"./transition-group\"\n\nimport type { VNodeChild } from \"@pyreon/core\"\nimport { setupDelegation } from \"./delegate\"\nimport { installDevTools } from \"./devtools\"\nimport { mountChild } from \"./mount\"\n\nconst __DEV__ = typeof process !== \"undefined\" && process.env.NODE_ENV !== \"production\"\n\n/**\n * Mount a VNode tree into a container element.\n * Clears the container first, then mounts the given child.\n * Returns an `unmount` function that removes everything and disposes effects.\n *\n * @example\n * const unmount = mount(h(\"div\", null, \"Hello Pyreon\"), document.getElementById(\"app\")!)\n */\nexport function mount(root: VNodeChild, container: Element): () => void {\n if (__DEV__ && container == null) {\n throw new Error(\n '[pyreon] mount() called with a null/undefined container. Make sure the element exists in the DOM, e.g. document.getElementById(\"app\")',\n )\n }\n installDevTools()\n setupDelegation(container)\n container.innerHTML = \"\"\n return mountChild(root, container, null)\n}\n\n/** Alias for `mount` */\nexport const render = mount\n"],"mappings":"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"}
|
package/lib/types/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index2.d.ts","names":[],"sources":["../../../src/delegate.ts","../../../src/devtools.ts","../../../src/hydrate.ts","../../../src/hydration-debug.ts","../../../src/keep-alive.ts","../../../src/mount.ts","../../../src/props.ts","../../../src/template.ts","../../../src/transition.ts","../../../src/transition-group.ts","../../../src/index.ts"],"mappings":";;;;;;AAoBA;;;;;AA8BA;;;;;AAWA;;;;cAzCa,gBAAA,EAAgB,GAAA;;;;ACJ7B;iBDkCgB,iBAAA,CAAkB,SAAA;;;;;iBAWlB,eAAA,CAAgB,SAAA,EAAW,OAAA;;;;;;AAzC3C;;;;;AA8BA;;;;;AAWA;;UC7CiB,sBAAA;EACf,EAAA;EACA,IAAA;;EAEA,EAAA,EAAI,OAAA;EACJ,QAAA;EACA,QAAA;AAAA;AAAA,UAGe,cAAA;EAAA,SACN,OAAA;EACT,gBAAA,IAAoB,sBAAA;EACpB,gBAAA,IAAoB,sBAAA;EACpB,SAAA,CAAU,EAAA;EACV,gBAAA,CAAiB,EAAA,GAAK,KAAA,EAAO,sBAAA;EAC7B,kBAAA,CAAmB,EAAA,GAAK,EAAA;EATxB;EAWA,aAAA;EACA,cAAA;AAAA;;;;;;AAlBF;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"index2.d.ts","names":[],"sources":["../../../src/delegate.ts","../../../src/devtools.ts","../../../src/hydrate.ts","../../../src/hydration-debug.ts","../../../src/keep-alive.ts","../../../src/mount.ts","../../../src/props.ts","../../../src/template.ts","../../../src/transition.ts","../../../src/transition-group.ts","../../../src/index.ts"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pyreon/runtime-dom",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.3",
|
|
4
4
|
"description": "DOM renderer for Pyreon",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -39,8 +39,8 @@
|
|
|
39
39
|
"prepublishOnly": "bun run build"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@pyreon/core": "^0.11.
|
|
43
|
-
"@pyreon/reactivity": "^0.11.
|
|
42
|
+
"@pyreon/core": "^0.11.3",
|
|
43
|
+
"@pyreon/reactivity": "^0.11.3"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"@happy-dom/global-registrator": "^20.8.3",
|
package/src/delegate.ts
CHANGED
|
@@ -68,8 +68,8 @@ export function setupDelegation(container: Element): void {
|
|
|
68
68
|
container.addEventListener(eventName, (e: Event) => {
|
|
69
69
|
let el = e.target as (HTMLElement & Record<string, unknown>) | null
|
|
70
70
|
while (el && el !== container) {
|
|
71
|
-
const handler = el[prop]
|
|
72
|
-
if (handler) {
|
|
71
|
+
const handler = el[prop]
|
|
72
|
+
if (typeof handler === "function") {
|
|
73
73
|
batch(() => handler(e))
|
|
74
74
|
// Don't break — allow ancestor handlers too (consistent with addEventListener)
|
|
75
75
|
// But if stopPropagation was called, stop walking
|
package/src/hydrate.ts
CHANGED
|
@@ -150,7 +150,7 @@ function hydrateVNode(
|
|
|
150
150
|
path: string,
|
|
151
151
|
): [Cleanup, ChildNode | null] {
|
|
152
152
|
if (vnode.type === Fragment) {
|
|
153
|
-
return hydrateChildren(vnode.children, domNode, parent, anchor, path)
|
|
153
|
+
return hydrateChildren(vnode.children ?? [], domNode, parent, anchor, path)
|
|
154
154
|
}
|
|
155
155
|
|
|
156
156
|
if (vnode.type === ForSymbol) {
|
|
@@ -241,7 +241,7 @@ function hydrateElement(
|
|
|
241
241
|
|
|
242
242
|
// Hydrate children
|
|
243
243
|
const firstChild = firstReal(el.firstChild as ChildNode | null)
|
|
244
|
-
const [childCleanup] = hydrateChildren(vnode.children, firstChild, el, null, elPath)
|
|
244
|
+
const [childCleanup] = hydrateChildren(vnode.children ?? [], firstChild, el, null, elPath)
|
|
245
245
|
cleanups.push(childCleanup)
|
|
246
246
|
|
|
247
247
|
// Set ref
|
|
@@ -320,10 +320,14 @@ function hydrateComponent(
|
|
|
320
320
|
// Function.name is always a string per spec; || handles empty string, avoids uncoverable ?? branch
|
|
321
321
|
const componentName = ((vnode.type as ComponentFn).name || "Anonymous") as string
|
|
322
322
|
const mergedProps =
|
|
323
|
-
vnode.children.length > 0 &&
|
|
323
|
+
(vnode.children ?? []).length > 0 &&
|
|
324
|
+
(vnode.props as Record<string, unknown>).children === undefined
|
|
324
325
|
? {
|
|
325
326
|
...vnode.props,
|
|
326
|
-
children:
|
|
327
|
+
children:
|
|
328
|
+
(vnode.children ?? []).length === 1
|
|
329
|
+
? (vnode.children ?? [])[0]
|
|
330
|
+
: (vnode.children ?? []),
|
|
327
331
|
}
|
|
328
332
|
: vnode.props
|
|
329
333
|
|
package/src/mount.ts
CHANGED
|
@@ -118,7 +118,7 @@ export function mountChild(
|
|
|
118
118
|
// VNode — element, component, fragment, For, Portal
|
|
119
119
|
const vnode = child as VNode
|
|
120
120
|
|
|
121
|
-
if (vnode.type === Fragment) return mountChildren(vnode.children, parent, anchor)
|
|
121
|
+
if (vnode.type === Fragment) return mountChildren(vnode.children ?? [], parent, anchor)
|
|
122
122
|
|
|
123
123
|
if (vnode.type === (ForSymbol as unknown as string)) {
|
|
124
124
|
const { each, by, children } = vnode.props as unknown as ForProps<unknown>
|
|
@@ -183,7 +183,7 @@ const VOID_ELEMENTS = new Set([
|
|
|
183
183
|
function mountElement(vnode: VNode, parent: Node, anchor: Node | null): Cleanup {
|
|
184
184
|
const el = document.createElement(vnode.type as string)
|
|
185
185
|
|
|
186
|
-
if (__DEV__ && vnode.children
|
|
186
|
+
if (__DEV__ && (vnode.children?.length ?? 0) > 0 && VOID_ELEMENTS.has(vnode.type as string)) {
|
|
187
187
|
console.warn(
|
|
188
188
|
`[Pyreon] <${vnode.type as string}> is a void element and cannot have children. ` +
|
|
189
189
|
"Children passed to void elements will be ignored by the browser.",
|
|
@@ -196,7 +196,7 @@ function mountElement(vnode: VNode, parent: Node, anchor: Node | null): Cleanup
|
|
|
196
196
|
|
|
197
197
|
// Mount children inside element context — nested elements can skip DOM removal closures
|
|
198
198
|
_elementDepth++
|
|
199
|
-
const childCleanup = mountChildren(vnode.children, el, null)
|
|
199
|
+
const childCleanup = mountChildren(vnode.children ?? [], el, null)
|
|
200
200
|
_elementDepth--
|
|
201
201
|
|
|
202
202
|
parent.insertBefore(el, anchor)
|
|
@@ -259,11 +259,12 @@ function mountComponent(
|
|
|
259
259
|
_mountingStack.push(compId)
|
|
260
260
|
|
|
261
261
|
// Merge vnode.children into props.children if not already set
|
|
262
|
+
const children = vnode.children ?? []
|
|
262
263
|
const mergedProps =
|
|
263
|
-
|
|
264
|
+
children.length > 0 && (vnode.props as Record<string, unknown>).children === undefined
|
|
264
265
|
? {
|
|
265
266
|
...vnode.props,
|
|
266
|
-
children:
|
|
267
|
+
children: children.length === 1 ? children[0] : children,
|
|
267
268
|
}
|
|
268
269
|
: vnode.props
|
|
269
270
|
|
package/src/props.ts
CHANGED
|
@@ -203,11 +203,13 @@ export function applyProps(el: Element, props: Props): Cleanup | null {
|
|
|
203
203
|
* Bind an event handler (onClick → "click") with batching + delegation support.
|
|
204
204
|
*/
|
|
205
205
|
function applyEventProp(el: Element, key: string, value: unknown): Cleanup | null {
|
|
206
|
-
if (
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
`
|
|
210
|
-
|
|
206
|
+
if (typeof value !== "function") {
|
|
207
|
+
if (__DEV__) {
|
|
208
|
+
console.warn(
|
|
209
|
+
`[Pyreon] Event handler "${key}" received a non-function value (${typeof value}). ` +
|
|
210
|
+
`Expected a function. Did you mean ${key}={() => ...}?`,
|
|
211
|
+
)
|
|
212
|
+
}
|
|
211
213
|
return null
|
|
212
214
|
}
|
|
213
215
|
const eventName = key[2]?.toLowerCase() + key.slice(3)
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import { createContext, Fragment, h, provide, useContext } from "@pyreon/core"
|
|
2
|
+
import { signal } from "@pyreon/reactivity"
|
|
3
|
+
import { mount } from "@pyreon/runtime-dom"
|
|
4
|
+
import { describe, expect, it } from "vitest"
|
|
5
|
+
|
|
6
|
+
const TestCtx = createContext("default")
|
|
7
|
+
|
|
8
|
+
describe("context inheritance through reactive boundaries", () => {
|
|
9
|
+
it("child inside reactive accessor inherits parent context", async () => {
|
|
10
|
+
let childValue: string | undefined
|
|
11
|
+
|
|
12
|
+
function Child() {
|
|
13
|
+
childValue = useContext(TestCtx)
|
|
14
|
+
return h("span", null, childValue)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function Parent() {
|
|
18
|
+
provide(TestCtx, "from-parent")
|
|
19
|
+
const show = signal(false)
|
|
20
|
+
setTimeout(() => show.set(true), 10)
|
|
21
|
+
return () => (show() ? h(Child, null) : null)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const container = document.createElement("div")
|
|
25
|
+
mount(h(Parent, null), container)
|
|
26
|
+
await new Promise((r) => setTimeout(r, 50))
|
|
27
|
+
expect(childValue).toBe("from-parent")
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
it("deeply nested context survives through multiple reactive layers", async () => {
|
|
31
|
+
let innerValue: string | undefined
|
|
32
|
+
|
|
33
|
+
function Inner() {
|
|
34
|
+
innerValue = useContext(TestCtx)
|
|
35
|
+
return h("span", null, innerValue)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function Middle() {
|
|
39
|
+
const show = signal(false)
|
|
40
|
+
setTimeout(() => show.set(true), 10)
|
|
41
|
+
return () => (show() ? h(Inner, null) : null)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function Outer() {
|
|
45
|
+
provide(TestCtx, "outer-value")
|
|
46
|
+
const show = signal(false)
|
|
47
|
+
setTimeout(() => show.set(true), 5)
|
|
48
|
+
return () => (show() ? h(Middle, null) : null)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const container = document.createElement("div")
|
|
52
|
+
mount(h(Outer, null), container)
|
|
53
|
+
await new Promise((r) => setTimeout(r, 100))
|
|
54
|
+
expect(innerValue).toBe("outer-value")
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
it("sibling providers don't leak context to each other", async () => {
|
|
58
|
+
let childAValue: string | undefined
|
|
59
|
+
let childBValue: string | undefined
|
|
60
|
+
|
|
61
|
+
function ChildA() {
|
|
62
|
+
childAValue = useContext(TestCtx)
|
|
63
|
+
return h("span", null, childAValue)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function ChildB() {
|
|
67
|
+
childBValue = useContext(TestCtx)
|
|
68
|
+
return h("span", null, childBValue)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function ProviderA() {
|
|
72
|
+
provide(TestCtx, "A")
|
|
73
|
+
return h(ChildA, null)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function ProviderB() {
|
|
77
|
+
provide(TestCtx, "B")
|
|
78
|
+
return h(ChildB, null)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function App() {
|
|
82
|
+
return h(Fragment, null, h(ProviderA, null), h(ProviderB, null))
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const container = document.createElement("div")
|
|
86
|
+
mount(h(App, null), container)
|
|
87
|
+
await new Promise((r) => setTimeout(r, 50))
|
|
88
|
+
|
|
89
|
+
expect(childAValue).toBe("A")
|
|
90
|
+
expect(childBValue).toBe("B")
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
it("Show toggle preserves context across hide/show cycle", async () => {
|
|
94
|
+
let childValue: string | undefined
|
|
95
|
+
let mountCount = 0
|
|
96
|
+
|
|
97
|
+
function Child() {
|
|
98
|
+
mountCount++
|
|
99
|
+
childValue = useContext(TestCtx)
|
|
100
|
+
return h("span", null, childValue)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function Parent() {
|
|
104
|
+
provide(TestCtx, "persistent")
|
|
105
|
+
const show = signal(true)
|
|
106
|
+
|
|
107
|
+
// Hide then show again
|
|
108
|
+
setTimeout(() => show.set(false), 10)
|
|
109
|
+
setTimeout(() => show.set(true), 30)
|
|
110
|
+
|
|
111
|
+
return () => (show() ? h(Child, null) : null)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const container = document.createElement("div")
|
|
115
|
+
mount(h(Parent, null), container)
|
|
116
|
+
await new Promise((r) => setTimeout(r, 100))
|
|
117
|
+
|
|
118
|
+
expect(childValue).toBe("persistent")
|
|
119
|
+
expect(mountCount).toBe(2) // mounted twice (initial + re-show)
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
it("reactive context getter updates JSX without re-running component", async () => {
|
|
123
|
+
const ModeCtx = createContext<() => string>(() => "light")
|
|
124
|
+
let renderCount = 0
|
|
125
|
+
|
|
126
|
+
function Child() {
|
|
127
|
+
const getMode = useContext(ModeCtx)
|
|
128
|
+
renderCount++
|
|
129
|
+
// Reading the getter inside a reactive accessor — updates when mode changes
|
|
130
|
+
return h("span", null, () => getMode())
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function Parent() {
|
|
134
|
+
const mode = signal<string>("light")
|
|
135
|
+
provide(ModeCtx, () => mode())
|
|
136
|
+
setTimeout(() => mode.set("dark"), 10)
|
|
137
|
+
return h(Child, null)
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const container = document.createElement("div")
|
|
141
|
+
mount(h(Parent, null), container)
|
|
142
|
+
|
|
143
|
+
expect(container.textContent).toBe("light")
|
|
144
|
+
|
|
145
|
+
await new Promise((r) => setTimeout(r, 50))
|
|
146
|
+
expect(container.textContent).toBe("dark")
|
|
147
|
+
// Component setup ran once — JSX expression re-evaluated reactively
|
|
148
|
+
expect(renderCount).toBe(1)
|
|
149
|
+
})
|
|
150
|
+
|
|
151
|
+
it("nested Show inside For with context", async () => {
|
|
152
|
+
const ItemCtx = createContext("none")
|
|
153
|
+
const collected: string[] = []
|
|
154
|
+
|
|
155
|
+
function Item() {
|
|
156
|
+
const val = useContext(ItemCtx)
|
|
157
|
+
collected.push(val)
|
|
158
|
+
return h("li", null, val)
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function Parent() {
|
|
162
|
+
provide(ItemCtx, "parent-provided")
|
|
163
|
+
const items = signal([1, 2, 3])
|
|
164
|
+
const show = signal(false)
|
|
165
|
+
setTimeout(() => show.set(true), 10)
|
|
166
|
+
|
|
167
|
+
return () => (show() ? h("ul", null, ...items().map((i) => h(Item, { key: i }))) : null)
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const container = document.createElement("div")
|
|
171
|
+
mount(h(Parent, null), container)
|
|
172
|
+
await new Promise((r) => setTimeout(r, 50))
|
|
173
|
+
|
|
174
|
+
expect(collected.length).toBe(3)
|
|
175
|
+
expect(collected.every((v) => v === "parent-provided")).toBe(true)
|
|
176
|
+
})
|
|
177
|
+
})
|