@streetui/renderer 1.6.0 → 1.7.0
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/dist/index.cjs +162 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +38 -2
- package/dist/index.d.ts +38 -2
- package/dist/index.js +165 -5
- package/dist/index.js.map +1 -1
- package/package.json +10 -10
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/render-context.ts","../src/node-instance.ts","../src/attributes.ts","../src/events.ts","../src/tag-map.ts","../src/patch.ts","../src/reconciliation.ts","../src/mount.ts","../src/renderer.ts","../src/hydration-diagnostics.ts","../src/hydrate.ts","../src/render-handle.ts","../src/dehydrate.ts","../src/ssr.ts"],"sourcesContent":["export * from './render-context.js';\nexport * from './node-instance.js';\nexport * from './attributes.js';\nexport * from './events.js';\nexport * from './mount.js';\nexport * from './patch.js';\nexport * from './reconciliation.js';\nexport * from './renderer.js';\nexport * from './render-handle.js';\nexport * from './hydrate.js';\nexport * from './hydration-diagnostics.js';\nexport * from './dehydrate.js';\nexport * from './ssr.js';\nexport * from './tag-map.js';\n","/**\n * RenderContext — shared state for a single mount operation.\n *\n * Passed through the render pipeline so every sub-function has access\n * to the DOM adapter, graph, and instance map without prop-drilling.\n */\n\nimport type { DOMAdapter } from '@streetui/dom';\nimport type { ApplicationGraph, GraphNode } from '@streetui/graph';\nimport type { NodeInstance } from './node-instance.js';\nimport type { HydrationDiagnosticSink } from './hydration-diagnostics.js';\n\nexport interface RenderContext {\n readonly dom: DOMAdapter;\n readonly graph: ApplicationGraph;\n /** Maps GraphNode.id → its live NodeInstance */\n readonly instances: Map<string, NodeInstance>;\n /** The root container element. */\n readonly container: Element;\n /**\n * Optional dev-only sink that observes hydration mismatch repairs. When\n * absent (the default) the hydration path does no extra work — this is how\n * DevTools/diagnostics stay off the production runtime path.\n */\n readonly hydrationDiagnostics?: HydrationDiagnosticSink;\n}\n\nexport function createRenderContext(\n dom: DOMAdapter,\n graph: ApplicationGraph,\n container: Element,\n hydrationDiagnostics?: HydrationDiagnosticSink,\n): RenderContext {\n return {\n dom,\n graph,\n instances: new Map(),\n container,\n ...(hydrationDiagnostics !== undefined ? { hydrationDiagnostics } : {}),\n };\n}\n","/**\n * NodeInstance — the renderer's live counterpart to a GraphNode.\n *\n * Tracks the actual DOM node(s), all signal subscriptions that drive\n * targeted DOM updates, and DOM event listener teardowns.\n */\n\nimport { CleanupRegistry } from '@streetui/core';\nimport type { GraphNode } from '@streetui/graph';\nimport type { ReadonlySignal } from '@streetui/state';\n\nexport class NodeInstance {\n readonly graphNode: GraphNode;\n /** The primary DOM node for this instance (element or text node). */\n domNode: Node;\n readonly children: NodeInstance[] = [];\n readonly cleanup: CleanupRegistry = new CleanupRegistry();\n\n constructor(graphNode: GraphNode, domNode: Node) {\n this.graphNode = graphNode;\n this.domNode = domNode;\n }\n\n addChild(child: NodeInstance): void {\n this.children.push(child);\n }\n\n /** Subscribe to a signal; auto-cleanup on unmount. */\n trackSignal<T>(sig: ReadonlySignal<T>, handler: (v: T) => void): void {\n const unsub = sig.subscribe(handler);\n this.cleanup.add(unsub);\n }\n\n /** Register a raw cleanup fn (DOM event removal, etc.). */\n trackCleanup(fn: () => void): void {\n this.cleanup.add(fn);\n }\n\n dispose(): void {\n for (const child of this.children) {\n child.dispose();\n }\n this.cleanup.run();\n }\n}\n","/**\n * Attribute and property application helpers.\n *\n * Decides whether a prop should be set as a DOM attribute or a JS property,\n * handling special cases (boolean attrs, event-like props, style, class).\n */\n\nimport type { DOMAdapter } from '@streetui/dom';\n\n// Properties that must be set as JS object properties, not HTML attributes\nconst DOM_PROPERTIES = new Set([\n 'value', 'checked', 'selected', 'indeterminate',\n 'innerHTML', 'textContent', 'innerText',\n 'scrollTop', 'scrollLeft',\n]);\n\n// Boolean attributes — present means true, absent means false\nconst BOOLEAN_ATTRS = new Set([\n 'disabled', 'readonly', 'required', 'checked', 'selected',\n 'multiple', 'autofocus', 'autoplay', 'controls', 'default',\n 'defer', 'formnovalidate', 'hidden', 'ismap', 'loop',\n 'novalidate', 'open', 'reversed', 'scoped', 'seamless',\n]);\n\nexport function applyProp(\n dom: DOMAdapter,\n element: Element,\n name: string,\n value: unknown,\n): void {\n // Skip internal renderer metadata\n if (name.startsWith('_')) return;\n // Skip event handlers (handled separately)\n if (name.startsWith('on')) return;\n\n if (DOM_PROPERTIES.has(name)) {\n dom.setProperty(element, name, value);\n return;\n }\n\n if (BOOLEAN_ATTRS.has(name)) {\n if (value === true || value === '' || value === name) {\n dom.setAttribute(element, name, '');\n } else {\n dom.removeAttribute(element, name);\n }\n return;\n }\n\n if (name === 'class' || name === 'className') {\n dom.setAttribute(element, 'class', String(value ?? ''));\n return;\n }\n\n if (name === 'style' && typeof value === 'object' && value !== null) {\n const el = element as HTMLElement;\n const styles = value as Record<string, string>;\n for (const [k, v] of Object.entries(styles)) {\n el.style.setProperty(k, v);\n }\n return;\n }\n\n if (value === null || value === undefined || value === false) {\n dom.removeAttribute(element, name);\n return;\n }\n\n dom.setAttribute(element, name, String(value));\n}\n\nexport function patchProp(\n dom: DOMAdapter,\n element: Element,\n name: string,\n oldValue: unknown,\n newValue: unknown,\n): void {\n if (Object.is(oldValue, newValue)) return;\n applyProp(dom, element, name, newValue);\n}\n","/**\n * Event wiring for the renderer.\n *\n * Given a GraphNode with event descriptors, this wires DOM listeners\n * that call the handlers stored in the graph's handler registry.\n */\n\nimport type { DOMAdapter } from '@streetui/dom';\nimport type { ApplicationGraph, GraphNode } from '@streetui/graph';\nimport type { NodeInstance } from './node-instance.js';\n\nexport function wireEvents(\n dom: DOMAdapter,\n graph: ApplicationGraph,\n node: GraphNode,\n element: Element,\n instance: NodeInstance,\n): void {\n // Fast exit for event-free nodes — avoids allocating a for-of iterator over\n // an empty array on every node during a large mount/hydrate.\n if (node.events.length === 0) return;\n for (const eventDesc of node.events) {\n const handler = graph.getHandler(eventDesc.handlerKey);\n if (handler === undefined) continue;\n\n const domListener: EventListener = (domEvent: Event) => {\n // For input events, pass the current value as first arg\n if (eventDesc.type === 'input' || eventDesc.type === 'change') {\n const input = domEvent.target as HTMLInputElement;\n (handler as (v: string) => void)(input.value);\n } else if (eventDesc.type === 'submit') {\n domEvent.preventDefault();\n (handler as (e: Event) => void)(domEvent);\n } else {\n (handler as () => void)();\n }\n };\n\n dom.addEventListener(element, eventDesc.type, domListener);\n instance.trackCleanup(() => {\n dom.removeEventListener(element, eventDesc.type, domListener);\n });\n }\n}\n","/**\n * Maps semantic node types to HTML tag names.\n */\n\nimport type { SemanticNodeType } from '@streetui/core';\n\nconst TAG_MAP: Partial<Record<SemanticNodeType, string>> = {\n application: 'div',\n page: 'div',\n section: 'section',\n container: 'div',\n heading: 'h1',\n text: 'span',\n button: 'button',\n input: 'input',\n form: 'form',\n list: 'ul',\n 'list-item': 'li',\n image: 'img',\n link: 'a',\n component: 'div',\n slot: 'div',\n fragment: 'div',\n 'reactive-list': 'ul',\n};\n\nexport function resolveTag(type: SemanticNodeType): string {\n return TAG_MAP[type] ?? 'div';\n}\n","/**\n * Patch — targeted DOM updates driven by signal changes.\n *\n * When a signal fires, we look up the NodeInstance and apply\n * only the changed prop — no full re-render, no tree diffing.\n */\n\nimport type { RenderContext } from './render-context.js';\nimport type { GraphNode } from '@streetui/graph';\nimport { applyProp, patchProp } from './attributes.js';\n\nexport function patchNode(\n ctx: RenderContext,\n graphNode: GraphNode,\n propKey: string,\n newValue: unknown,\n): void {\n const instance = ctx.instances.get(graphNode.id);\n if (instance === undefined) return;\n\n const domNode = instance.domNode;\n if (!ctx.dom.isElement(domNode)) return;\n\n const oldValue = graphNode.getProp(propKey);\n\n switch (propKey) {\n case 'text':\n if (!Object.is(oldValue, newValue)) {\n ctx.dom.setTextContent(domNode, String(newValue ?? ''));\n graphNode.setProp('text', String(newValue ?? ''));\n }\n break;\n case 'label':\n if (!Object.is(oldValue, newValue)) {\n ctx.dom.setTextContent(domNode, String(newValue ?? ''));\n graphNode.setProp('label', String(newValue ?? ''));\n }\n break;\n case 'disabled':\n if (newValue === true) {\n ctx.dom.setAttribute(domNode, 'disabled', '');\n } else {\n ctx.dom.removeAttribute(domNode, 'disabled');\n }\n graphNode.setProp('disabled', Boolean(newValue));\n break;\n case 'value':\n if (!Object.is(oldValue, newValue)) {\n ctx.dom.setProperty(domNode, 'value', String(newValue ?? ''));\n graphNode.setProp('value', String(newValue ?? ''));\n }\n break;\n default:\n patchProp(ctx.dom, domNode, propKey, oldValue, newValue);\n graphNode.setProp(propKey, newValue as string);\n break;\n }\n}\n","/**\n * Reconciliation — diff-based child list updates.\n *\n * When the children of a node change (e.g. a list driven by state),\n * this reconciler:\n * 1. Matches old instances to new graph nodes by key\n * 2. Reuses matched instances (updates their props)\n * 3. Applies a targeted content update to a reused item whose data changed\n * 4. Creates new instances for additions\n * 5. Removes stale instances (and prunes their handler registrations)\n * 6. Moves DOM nodes to match new order\n *\n * This is keyed reconciliation over the semantic graph — there is no virtual\n * DOM. A reused item keeps its own DOM element; only its changed content is\n * updated in place (falling back to remounting a subtree only where its shape\n * actually changed).\n */\n\nimport type { RenderContext } from './render-context.js';\nimport type { GraphNode } from '@streetui/graph';\nimport type { NodeInstance } from './node-instance.js';\nimport { patchNode } from './patch.js';\n\nexport type MountFn = (node: GraphNode, parent: Element) => NodeInstance;\n\nexport interface ReconcileResult {\n /** Instances in the new order. */\n instances: NodeInstance[];\n /** Instances that were removed and must be disposed. */\n removed: NodeInstance[];\n /**\n * GraphNodes freshly materialised during this reconcile (new rows + rebuilt\n * changed rows). The caller detaches any of these that were not adopted as a\n * live instance's graph node, so no orphan subtree lingers in the graph index.\n */\n built?: GraphNode[];\n}\n\n/**\n * A lazy reconciliation descriptor for one reactive-list row (mirrors the DSL's\n * `ListPlanEntry`). `sig()` and `build()` are only invoked for rows that are\n * genuinely new or whose source reference changed — the whole point of the\n * plan path (spec §15).\n */\nexport interface PlanEntry {\n readonly key: string;\n readonly item: unknown;\n readonly sig: () => string;\n readonly build: () => GraphNode;\n}\n\n/**\n * Reconcile children of a container element against a new list of graph nodes.\n *\n * @param ctx Render context\n * @param parentDom The DOM parent element\n * @param oldInstances Current child instances (in order)\n * @param newNodes New graph children (in desired order)\n * @param mountFn Factory to create a new NodeInstance for a graph node\n */\nexport function reconcileChildren(\n ctx: RenderContext,\n parentDom: Element,\n oldInstances: NodeInstance[],\n newNodes: readonly GraphNode[],\n mountFn: MountFn,\n): ReconcileResult {\n // Build key → old instance map\n const oldByKey = new Map<string, NodeInstance>();\n for (const inst of oldInstances) {\n const key = inst.graphNode.key ?? inst.graphNode.id;\n oldByKey.set(key, inst);\n }\n\n const newInstances: NodeInstance[] = [];\n const usedKeys = new Set<string>();\n\n for (const newNode of newNodes) {\n const key = newNode.key ?? newNode.id;\n const existing = oldByKey.get(key);\n\n if (existing !== undefined) {\n // Reuse — identity is stable, so the DOM element is preserved.\n usedKeys.add(key);\n const oldSig = existing.graphNode.getProp('_sig');\n const newSig = newNode.getProp('_sig');\n patchExistingInstance(ctx, existing, newNode);\n // Data changed but identity did not → targeted content update in place.\n if (!Object.is(oldSig, newSig)) {\n reconcileItemChildren(ctx, existing, newNode, mountFn);\n }\n newInstances.push(existing);\n } else {\n // New — create and mount\n const inst = mountFn(newNode, parentDom);\n newInstances.push(inst);\n }\n }\n\n // Determine removed instances\n const removed: NodeInstance[] = [];\n for (const inst of oldInstances) {\n const key = inst.graphNode.key ?? inst.graphNode.id;\n if (!usedKeys.has(key)) {\n removed.push(inst);\n }\n }\n\n // Remove stale DOM nodes\n for (const inst of removed) {\n const parent = ctx.dom.parentNode(inst.domNode);\n if (parent !== null) {\n ctx.dom.removeChild(parent, inst.domNode);\n }\n inst.dispose();\n }\n\n // Reorder DOM nodes to match new order\n reorderDom(ctx, parentDom, newInstances);\n\n return { instances: newInstances, removed };\n}\n\n/**\n * Plan-based keyed reconciliation (spec §15 — the optimised reactive-list path).\n *\n * Identical observable result to {@link reconcileChildren}, but driven by lazy\n * {@link PlanEntry} descriptors instead of a pre-built array of GraphNodes:\n *\n * - a reused row whose `item` reference is unchanged does **zero** work — no\n * signature hash, no subtree build, no prop patch (the common case for\n * append / prepend / remove / reorder / reverse, where existing item objects\n * keep their identity);\n * - a reused row whose reference changed hashes lazily and, only on a real\n * signature change, materialises a fresh subtree for a targeted in-place\n * content update;\n * - a genuinely new key builds + mounts exactly one subtree.\n *\n * DOM reordering uses a longest-increasing-subsequence pass so the number of\n * moves is minimal (e.g. a prepend into a 10k list moves 1 node, not 10k).\n */\nexport function reconcileChildrenByPlan(\n ctx: RenderContext,\n parentDom: Element,\n oldInstances: NodeInstance[],\n plan: readonly PlanEntry[],\n mountFn: MountFn,\n): ReconcileResult {\n const oldByKey = new Map<string, NodeInstance>();\n for (const inst of oldInstances) {\n oldByKey.set(inst.graphNode.key ?? inst.graphNode.id, inst);\n }\n\n const newInstances: NodeInstance[] = [];\n const usedKeys = new Set<string>();\n const built: GraphNode[] = [];\n\n for (const entry of plan) {\n const existing = oldByKey.get(entry.key);\n if (existing !== undefined) {\n usedKeys.add(entry.key);\n const oldItem = existing.graphNode.getProp('_item');\n // Identity short-circuit: same reference ⇒ data cannot have changed.\n if (!Object.is(oldItem, entry.item)) {\n const newSig = entry.sig();\n const oldSig = existing.graphNode.getProp('_sig');\n if (!Object.is(oldSig, newSig)) {\n const freshNode = entry.build();\n built.push(freshNode);\n patchExistingInstance(ctx, existing, freshNode);\n reconcileItemChildren(ctx, existing, freshNode, mountFn);\n existing.graphNode.setProp('_sig', newSig);\n }\n // Cache the new reference so the next pass can short-circuit again.\n existing.graphNode.setProp('_item', entry.item as never);\n }\n newInstances.push(existing);\n } else {\n const freshNode = entry.build();\n built.push(freshNode);\n const inst = mountFn(freshNode, parentDom);\n newInstances.push(inst);\n }\n }\n\n // Determine + remove stale instances.\n const removed: NodeInstance[] = [];\n for (const inst of oldInstances) {\n const key = inst.graphNode.key ?? inst.graphNode.id;\n if (!usedKeys.has(key)) removed.push(inst);\n }\n for (const inst of removed) {\n const parent = ctx.dom.parentNode(inst.domNode);\n if (parent !== null) ctx.dom.removeChild(parent, inst.domNode);\n inst.dispose();\n }\n\n // Minimal-move reorder to the desired order.\n reorderDomMinimal(ctx, parentDom, oldInstances, newInstances);\n\n return { instances: newInstances, removed, built };\n}\n\n/**\n * Minimal-move DOM reorder.\n *\n * Reused nodes retain their previous DOM slots and newly-mounted nodes sit at\n * the end. We compute the longest increasing subsequence of the reused nodes'\n * previous positions; those are already in correct relative order and stay put.\n * Every other node is inserted before its right-hand neighbour, walking\n * right-to-left. This yields exactly (n − |LIS|) `insertBefore` calls — the\n * minimum — instead of the O(n) sweep the naive reorder performs on a prepend.\n */\nfunction reorderDomMinimal(\n ctx: RenderContext,\n parentDom: Element,\n oldInstances: NodeInstance[],\n newInstances: NodeInstance[],\n): void {\n const n = newInstances.length;\n if (n === 0) return;\n\n const oldIndexOf = new Map<NodeInstance, number>();\n for (let i = 0; i < oldInstances.length; i++) oldIndexOf.set(oldInstances[i]!, i);\n\n const source = new Array<number>(n);\n let moved = false;\n let lastSeen = -1;\n for (let i = 0; i < n; i++) {\n const oi = oldIndexOf.get(newInstances[i]!);\n if (oi === undefined) {\n source[i] = -1; // freshly mounted row\n moved = true;\n } else {\n source[i] = oi;\n if (oi < lastSeen) moved = true; // an out-of-order reused row exists\n else lastSeen = oi;\n }\n }\n\n // Fast path: nothing is out of order and there are no new rows to reposition.\n if (!moved) return;\n\n const keep = longestIncreasingSubsequence(source);\n\n let refNode: Node | null = null;\n for (let i = n - 1; i >= 0; i--) {\n const domNode = newInstances[i]!.domNode;\n if (source[i] === -1 || !keep.has(i)) {\n if (ctx.dom.nextSibling(domNode) !== refNode) {\n ctx.dom.insertBefore(parentDom, domNode, refNode);\n }\n }\n refNode = domNode;\n }\n}\n\n/**\n * Indices (into `source`) forming a longest strictly-increasing subsequence,\n * ignoring `-1` entries (new rows, which always move). O(n log n) with\n * predecessor reconstruction.\n */\nfunction longestIncreasingSubsequence(source: readonly number[]): Set<number> {\n const keep = new Set<number>();\n const n = source.length;\n const tails: number[] = []; // tails[k] = source-index of smallest tail of an LIS of length k+1\n const prev = new Array<number>(n).fill(-1);\n\n for (let i = 0; i < n; i++) {\n const v = source[i]!;\n if (v < 0) continue;\n let lo = 0;\n let hi = tails.length;\n while (lo < hi) {\n const mid = (lo + hi) >> 1;\n if (source[tails[mid]!]! < v) lo = mid + 1;\n else hi = mid;\n }\n if (lo > 0) prev[i] = tails[lo - 1]!;\n tails[lo] = i;\n }\n\n let idx = tails.length > 0 ? tails[tails.length - 1]! : -1;\n while (idx >= 0) {\n keep.add(idx);\n idx = prev[idx]!;\n }\n return keep;\n}\n\n/**\n * Targeted in-place content update for a reused list item whose data changed.\n *\n * The item's DOM element is kept; only its contents are updated. Children are\n * matched positionally against the freshly-built subtree:\n * - same node type at a position → the existing child is reused and its props\n * are patched in place (e.g. a text node's text is rewritten), then we\n * recurse into its children;\n * - different type / new position → the fresh child node is reparented onto the\n * live item node and mounted;\n * - surplus old children → disposed, with DOM, subscriptions, listeners and\n * handler registrations all torn down.\n *\n * This deliberately reuses the same keyed/positional strategy rather than a\n * virtual DOM, and never destroys the item element itself.\n */\nfunction reconcileItemChildren(\n ctx: RenderContext,\n itemInstance: NodeInstance,\n newItemNode: GraphNode,\n mountFn: MountFn,\n): void {\n const el = itemInstance.domNode;\n if (!ctx.dom.isElement(el)) return;\n\n const oldChildren = [...itemInstance.children];\n const newChildNodes = [...newItemNode.children];\n const nextChildren: NodeInstance[] = [];\n const kept = new Set<NodeInstance>();\n\n for (let i = 0; i < newChildNodes.length; i++) {\n const newChild = newChildNodes[i]!;\n const oldChild = oldChildren[i];\n\n if (oldChild !== undefined && oldChild.graphNode.type === newChild.type) {\n // Reuse in place — patch this node's props and recurse into descendants.\n patchExistingInstance(ctx, oldChild, newChild);\n reconcileItemChildren(ctx, oldChild, newChild, mountFn);\n nextChildren.push(oldChild);\n kept.add(oldChild);\n } else {\n // Structural change at this position — mount the fresh child. Reparent it\n // out of the freshly-built subtree so the wholesale detach of the\n // unadopted item node (in mount.ts) does not remove this now-live node.\n itemInstance.graphNode.appendChild(newChild);\n const inst = mountFn(newChild, el);\n nextChildren.push(inst);\n }\n }\n\n // Dispose old children that were not reused (surplus or type-mismatched).\n for (const old of oldChildren) {\n if (kept.has(old)) continue;\n const parent = ctx.dom.parentNode(old.domNode);\n if (parent !== null) ctx.dom.removeChild(parent, old.domNode);\n old.dispose();\n forgetInstanceTree(ctx, old);\n ctx.graph.detachNode(old.graphNode);\n }\n\n // Restore correct DOM order within the item element.\n reorderDom(ctx, el, nextChildren);\n\n // Sync the live instance's children.\n itemInstance.children.length = 0;\n for (const c of nextChildren) itemInstance.children.push(c);\n\n // Keep the graph model's item children consistent with the reconciled order.\n for (const c of [...itemInstance.graphNode.children]) {\n itemInstance.graphNode.removeChild(c);\n }\n for (const c of nextChildren) itemInstance.graphNode.appendChild(c.graphNode);\n}\n\n/** Move a parent's DOM children to match the given instance order (minimal moves). */\nfunction reorderDom(\n ctx: RenderContext,\n parentDom: Element,\n instances: NodeInstance[],\n): void {\n let referenceNode: Node | null = null;\n for (let i = instances.length - 1; i >= 0; i--) {\n const inst = instances[i];\n if (inst === undefined) continue;\n const domNode = inst.domNode;\n const currentNext = ctx.dom.nextSibling(domNode);\n if (currentNext !== referenceNode) {\n ctx.dom.insertBefore(parentDom, domNode, referenceNode);\n }\n referenceNode = domNode;\n }\n}\n\n/** Recursively drop an instance subtree from the renderer's instance index. */\nfunction forgetInstanceTree(ctx: RenderContext, instance: NodeInstance): void {\n ctx.instances.delete(instance.graphNode.id);\n for (const child of instance.children) forgetInstanceTree(ctx, child);\n}\n\nfunction patchExistingInstance(\n ctx: RenderContext,\n instance: NodeInstance,\n newNode: GraphNode,\n): void {\n const oldNode = instance.graphNode;\n for (const [key, newVal] of Object.entries(newNode.props)) {\n const oldVal = oldNode.getProp(key);\n if (!Object.is(oldVal, newVal)) {\n patchNode(ctx, instance.graphNode, key, newVal);\n }\n }\n}\n","/**\n * Initial mount — creates DOM nodes for every GraphNode and\n * attaches them into the container.\n *\n * This is a recursive depth-first walk. For each GraphNode:\n * 1. Create the DOM element (or text node)\n * 2. Apply props/attributes\n * 3. Wire events\n * 4. Wire signal subscriptions for reactive props\n * 5. Recurse into children\n * 6. Insert into the DOM\n */\n\nimport type { GraphNode, ApplicationGraph } from '@streetui/graph';\nimport type { DOMAdapter } from '@streetui/dom';\nimport type { RenderContext } from './render-context.js';\nimport { NodeInstance } from './node-instance.js';\nimport { applyProp } from './attributes.js';\nimport { wireEvents } from './events.js';\nimport { resolveTag } from './tag-map.js';\nimport {\n reconcileChildren,\n reconcileChildrenByPlan,\n type PlanEntry,\n} from './reconciliation.js';\n\n/**\n * Prop keys handled by the per-type mount branches (or reserved internals), so\n * `applyNodeProps` must skip them to avoid double-applying. This set is\n * invariant across nodes, so it is hoisted to module scope: allocating it once\n * (rather than per node) removes N Set allocations per mount/SSR pass and the\n * GC pressure they create. Treat as read-only — never mutate.\n */\nconst SKIP_PROP_KEYS: ReadonlySet<string> = new Set([\n 'text', 'label', 'level', 'inputType', 'src', 'alt', 'href', 'external',\n 'value', 'placeholder', 'disabled', '_renderKey', 'key', 'name',\n]);\n\nexport function mountGraph(ctx: RenderContext): NodeInstance {\n return mountNode(ctx, ctx.graph.root, ctx.container);\n}\n\nexport function mountNode(\n ctx: RenderContext,\n graphNode: GraphNode,\n parentDom: Node,\n): NodeInstance {\n const { dom, graph } = ctx;\n\n // The application root node maps to the container itself — don't create a duplicate element\n if (graphNode.type === 'application') {\n const instance = new NodeInstance(graphNode, parentDom);\n ctx.instances.set(graphNode.id, instance);\n for (const child of graphNode.children) {\n const childInstance = mountNode(ctx, child, parentDom);\n instance.addChild(childInstance);\n }\n return instance;\n }\n\n // Text-only nodes render as a <span> containing a text node\n if (graphNode.type === 'text') {\n const text = String(graphNode.getProp('text') ?? '');\n const el = dom.createElement('span');\n const textNode = dom.createTextNode(text);\n dom.appendChild(el, textNode);\n applyNodeProps(ctx, graphNode, el);\n\n // Create the live instance up front and reuse it for event wiring. The\n // previous code allocated a throwaway NodeInstance solely to satisfy\n // wireEvents' signature, wasting one NodeInstance (+ its children array and\n // CleanupRegistry) per text node — pure GC pressure on the hottest mount\n // path. wireEvents/wireSignalBindings each early-return on empty arrays.\n const instance = new NodeInstance(graphNode, el);\n ctx.instances.set(graphNode.id, instance);\n wireEvents(dom, graph, graphNode, el, instance);\n\n // Reactive text binding — only build the update closure when the node has\n // bindings. wireSignalBindings early-returns on empty stateRefs, so for a\n // static text node (the common case in a large initial render) the\n // textUpdate closure would be allocated and thrown away: avoidable GC\n // pressure on the hottest mount path.\n if (graphNode.stateRefs.length !== 0) {\n wireSignalBindings(ctx, graphNode, instance, textUpdate(dom, el, textNode));\n }\n\n dom.appendChild(parentDom, el);\n return instance;\n }\n\n // Heading nodes\n if (graphNode.type === 'heading') {\n const level = (graphNode.getProp('level') as number | undefined) ?? 1;\n const tag = `h${level}` as string;\n const el = dom.createElement(tag);\n const text = String(graphNode.getProp('text') ?? '');\n dom.setTextContent(el, text);\n applyNodeProps(ctx, graphNode, el);\n\n const instance = new NodeInstance(graphNode, el);\n ctx.instances.set(graphNode.id, instance);\n wireEvents(dom, graph, graphNode, el, instance);\n\n if (graphNode.stateRefs.length !== 0) {\n wireSignalBindings(ctx, graphNode, instance, headingUpdate(dom, el));\n }\n\n dom.appendChild(parentDom, el);\n return instance;\n }\n\n // Input nodes\n if (graphNode.type === 'input') {\n const el = dom.createElement('input') as HTMLInputElement;\n const inputType = String(graphNode.getProp('inputType') ?? 'text');\n dom.setAttribute(el, 'type', inputType);\n const placeholder = graphNode.getProp('placeholder');\n if (placeholder !== undefined) dom.setAttribute(el, 'placeholder', String(placeholder));\n const value = graphNode.getProp('value');\n if (value !== undefined) dom.setProperty(el, 'value', String(value));\n applyNodeProps(ctx, graphNode, el);\n\n const instance = new NodeInstance(graphNode, el);\n ctx.instances.set(graphNode.id, instance);\n wireEvents(dom, graph, graphNode, el, instance);\n\n if (graphNode.stateRefs.length !== 0) {\n wireSignalBindings(ctx, graphNode, instance, inputUpdate(dom, el));\n }\n\n dom.appendChild(parentDom, el);\n return instance;\n }\n\n // Image nodes\n if (graphNode.type === 'image') {\n const el = dom.createElement('img') as HTMLImageElement;\n const src = graphNode.getProp('src');\n const alt = graphNode.getProp('alt');\n if (src !== undefined) dom.setAttribute(el, 'src', String(src));\n if (alt !== undefined) dom.setAttribute(el, 'alt', String(alt));\n const width = graphNode.getProp('width');\n const height = graphNode.getProp('height');\n if (width !== undefined) dom.setAttribute(el, 'width', String(width));\n if (height !== undefined) dom.setAttribute(el, 'height', String(height));\n applyNodeProps(ctx, graphNode, el);\n\n const instance = new NodeInstance(graphNode, el);\n ctx.instances.set(graphNode.id, instance);\n dom.appendChild(parentDom, el);\n return instance;\n }\n\n // Link nodes\n if (graphNode.type === 'link') {\n const el = dom.createElement('a') as HTMLAnchorElement;\n const href = graphNode.getProp('href');\n const label = graphNode.getProp('label');\n const external = graphNode.getProp('external');\n if (href !== undefined) dom.setAttribute(el, 'href', String(href));\n if (label !== undefined) dom.setTextContent(el, String(label));\n if (external === true) {\n dom.setAttribute(el, 'target', '_blank');\n dom.setAttribute(el, 'rel', 'noopener noreferrer');\n }\n applyNodeProps(ctx, graphNode, el);\n\n const instance = new NodeInstance(graphNode, el);\n ctx.instances.set(graphNode.id, instance);\n wireEvents(dom, graph, graphNode, el, instance);\n dom.appendChild(parentDom, el);\n return instance;\n }\n\n // Button nodes\n if (graphNode.type === 'button') {\n const el = dom.createElement('button') as HTMLButtonElement;\n const label = graphNode.getProp('label');\n if (label !== undefined) dom.setTextContent(el, String(label));\n const disabled = graphNode.getProp('disabled');\n if (disabled === true) dom.setAttribute(el, 'disabled', '');\n applyNodeProps(ctx, graphNode, el);\n\n const instance = new NodeInstance(graphNode, el);\n ctx.instances.set(graphNode.id, instance);\n wireEvents(dom, graph, graphNode, el, instance);\n\n if (graphNode.stateRefs.length !== 0) {\n wireSignalBindings(ctx, graphNode, instance, buttonUpdate(dom, el));\n }\n\n dom.appendChild(parentDom, el);\n return instance;\n }\n\n // Reactive list / conditional — a container whose children are driven by a\n // Signal. Initial child subtrees are already built into the graph by the DSL;\n // on signal change we reconcile the freshly-built desired children against the\n // live DOM using the keyed reconciler (no virtual DOM). A `conditional` uses\n // the identical machinery but renders as a neutral <div> holding 0..1 branch.\n if (graphNode.type === 'reactive-list' || graphNode.type === 'conditional') {\n const tag = resolveTag(graphNode.type);\n const el = dom.createElement(tag);\n applyNodeProps(ctx, graphNode, el);\n\n const instance = new NodeInstance(graphNode, el);\n ctx.instances.set(graphNode.id, instance);\n\n for (const child of graphNode.children) {\n const childInstance = mountNode(ctx, child, el);\n instance.addChild(childInstance);\n }\n\n dom.appendChild(parentDom, el);\n wireReactiveList(ctx, graphNode, instance, el);\n return instance;\n }\n\n // Container / section / page / form / list / list-item — structural nodes\n const tag = resolveTag(graphNode.type);\n const el = dom.createElement(tag);\n applyNodeProps(ctx, graphNode, el);\n\n // Surface a reactive-list item's stable, identity-only reconciliation key as a\n // public `data-streetui-key` attribute (e.g. \"id:1\"). This exposes only the\n // identity part — never the internal `_sig` value signature, signal ids or\n // graph node ids — so a row is directly selectable and its identity is\n // inspectable across reorders and in-place data updates.\n if (graphNode.type === 'list-item') {\n const itemKey = graphNode.getProp('key');\n if (itemKey !== undefined) {\n dom.setAttribute(el, 'data-streetui-key', String(itemKey));\n }\n }\n\n const instance = new NodeInstance(graphNode, el);\n ctx.instances.set(graphNode.id, instance);\n\n // wire form submit (reuse the live instance rather than a throwaway)\n if (graphNode.type === 'form') {\n wireEvents(dom, graph, graphNode, el, instance);\n }\n\n // Recurse into children\n for (const child of graphNode.children) {\n const childInstance = mountNode(ctx, child, el);\n instance.addChild(childInstance);\n }\n\n dom.appendChild(parentDom, el);\n return instance;\n}\n\n// ── Helpers ───────────────────────────────────────────────────────────────────\n\n/**\n * Per-node-type reactive-binding factories. Each returns the `onUpdate`\n * callback that `wireSignalBindings` invokes when a bound signal changes.\n * Extracted so both the browser mount path and the hydration path apply the\n * exact same DOM mutation semantics for each prop — no duplicated rendering\n * logic.\n */\nexport function textUpdate(\n dom: DOMAdapter,\n el: Element,\n textNode: Text,\n): (propKey: string, value: unknown) => void {\n return (propKey, value) => {\n if (propKey === 'text') {\n dom.setTextContent(textNode, String(value ?? ''));\n } else {\n applyProp(dom, el, propKey, value);\n }\n };\n}\n\nexport function headingUpdate(\n dom: DOMAdapter,\n el: Element,\n): (propKey: string, value: unknown) => void {\n return (propKey, value) => {\n if (propKey === 'text') {\n dom.setTextContent(el, String(value ?? ''));\n } else {\n applyProp(dom, el, propKey, value);\n }\n };\n}\n\nexport function inputUpdate(\n dom: DOMAdapter,\n el: Element,\n): (propKey: string, value: unknown) => void {\n return (propKey, value) => {\n if (propKey === 'value') {\n dom.setProperty(el, 'value', String(value ?? ''));\n } else {\n applyProp(dom, el, propKey, value);\n }\n };\n}\n\nexport function buttonUpdate(\n dom: DOMAdapter,\n el: Element,\n): (propKey: string, value: unknown) => void {\n return (propKey, value) => {\n if (propKey === 'label') {\n dom.setTextContent(el, String(value ?? ''));\n } else if (propKey === 'disabled') {\n if (value === true) {\n dom.setAttribute(el, 'disabled', '');\n } else {\n dom.removeAttribute(el, 'disabled');\n }\n } else {\n applyProp(dom, el, propKey, value);\n }\n };\n}\n\nexport function applyNodeProps(ctx: RenderContext, graphNode: GraphNode, el: Element): void {\n // Iterate own enumerable keys directly rather than via Object.entries, which\n // allocates a wrapper array plus one [key,value] tuple per prop — measurable\n // GC pressure when multiplied across every node in a large initial render.\n const props = graphNode.props;\n for (const key in props) {\n if (!Object.hasOwn(props, key)) continue;\n if (SKIP_PROP_KEYS.has(key)) continue;\n applyProp(ctx.dom, el, key, props[key]);\n }\n}\n\nexport function wireSignalBindings(\n ctx: RenderContext,\n graphNode: GraphNode,\n instance: NodeInstance,\n onUpdate: (propKey: string, value: unknown) => void,\n): void {\n // Fast exit for the common non-reactive node — avoids allocating a for-of\n // iterator over an empty stateRefs array on every static node.\n if (graphNode.stateRefs.length === 0) return;\n for (const stateRef of graphNode.stateRefs) {\n const signalKey = `__signal__${stateRef.signalId}`;\n const maybeSig = ctx.graph.getHandler(signalKey) as\n | { subscribe: (fn: (v: unknown) => void) => () => void; peek: () => unknown }\n | undefined;\n if (maybeSig === undefined || typeof maybeSig.subscribe !== 'function') continue;\n\n // Subscribe directly — avoids the ReadonlySignal<T> generic variance issue\n const unsub = maybeSig.subscribe((value) => {\n onUpdate(stateRef.propKey, value);\n });\n instance.trackCleanup(unsub);\n }\n}\n\n// ── Reactive list wiring ────────────────────────────────────────────────────────\n\ntype ListBuildFn = (items: unknown) => GraphNode[];\ntype ListPlanFn = (items: unknown) => PlanEntry[];\n\n/**\n * Subscribe a reactive-list instance to its driving signal. On each change the\n * DSL-registered plan factory produces lightweight per-row descriptors, which\n * are reconciled against the live DOM with the keyed, minimal-move reconciler\n * (spec §15). A `conditional` node has no plan handler and falls back to the\n * eager build factory (it only ever renders 0..1 branch, so eager is fine).\n */\nexport function wireReactiveList(\n ctx: RenderContext,\n graphNode: GraphNode,\n instance: NodeInstance,\n el: Element,\n): void {\n const plan = ctx.graph.getHandler(`__listplan__${graphNode.id}`) as\n | ListPlanFn\n | undefined;\n const build = ctx.graph.getHandler(`__listbuild__${graphNode.id}`) as\n | ListBuildFn\n | undefined;\n if (plan === undefined && build === undefined) return;\n\n for (const stateRef of graphNode.stateRefs) {\n if (stateRef.propKey !== 'items') continue;\n const sig = ctx.graph.getHandler(`__signal__${stateRef.signalId}`) as\n | { subscribe: (fn: (v: unknown) => void) => () => void }\n | undefined;\n if (sig === undefined || typeof sig.subscribe !== 'function') continue;\n\n const unsub = sig.subscribe((value) => {\n if (plan !== undefined) {\n reconcileReactiveListByPlan(ctx, graphNode, instance, el, plan(value));\n } else {\n reconcileReactiveList(ctx, graphNode, instance, el, build!(value));\n }\n });\n instance.trackCleanup(unsub);\n }\n}\n\nfunction reconcileReactiveListByPlan(\n ctx: RenderContext,\n listNode: GraphNode,\n listInstance: NodeInstance,\n listEl: Element,\n plan: PlanEntry[],\n): void {\n const oldInstances = [...listInstance.children];\n const result = reconcileChildrenByPlan(\n ctx,\n listEl,\n oldInstances,\n plan,\n (node, parent) => mountNode(ctx, node, parent),\n );\n\n // Sync the live instance's children to the reconciled order.\n listInstance.children.length = 0;\n for (const inst of result.instances) listInstance.children.push(inst);\n\n // Forget removed instances, and drop their graph nodes.\n for (const removed of result.removed) {\n forgetInstance(ctx, removed);\n ctx.graph.detachNode(removed.graphNode);\n }\n // Detach any freshly-built subtree that was not adopted as a live instance\n // (e.g. the top node of a rebuilt changed row, whose live instance keeps its\n // original graph node).\n const adopted = new Set(result.instances.map((i) => i.graphNode));\n for (const node of result.built ?? []) {\n if (!adopted.has(node)) ctx.graph.detachNode(node);\n }\n\n // Keep the graph model consistent: list node children match the new order.\n for (const child of [...listNode.children]) listNode.removeChild(child);\n for (const inst of result.instances) listNode.appendChild(inst.graphNode);\n}\n\nfunction reconcileReactiveList(\n ctx: RenderContext,\n listNode: GraphNode,\n listInstance: NodeInstance,\n listEl: Element,\n newNodes: GraphNode[],\n): void {\n const oldInstances = [...listInstance.children];\n const result = reconcileChildren(\n ctx,\n listEl,\n oldInstances,\n newNodes,\n (node, parent) => mountNode(ctx, node, parent),\n );\n\n // Sync the live instance's children to the reconciled order.\n listInstance.children.length = 0;\n for (const inst of result.instances) listInstance.children.push(inst);\n\n // Forget removed instances from the renderer index, and drop their graph\n // nodes (and any un-adopted freshly-built duplicates) from the graph index.\n for (const removed of result.removed) {\n forgetInstance(ctx, removed);\n ctx.graph.detachNode(removed.graphNode);\n }\n const adopted = new Set(result.instances.map((i) => i.graphNode));\n for (const built of newNodes) {\n if (!adopted.has(built)) ctx.graph.detachNode(built);\n }\n\n // Keep the graph model consistent: list node children match the new order.\n for (const child of [...listNode.children]) listNode.removeChild(child);\n for (const inst of result.instances) listNode.appendChild(inst.graphNode);\n}\n\n/** Recursively remove an instance subtree from the renderer's instance index. */\nfunction forgetInstance(ctx: RenderContext, instance: NodeInstance): void {\n ctx.instances.delete(instance.graphNode.id);\n for (const child of instance.children) forgetInstance(ctx, child);\n}\n","/**\n * StreetUI Renderer — framework-owned DOM renderer.\n *\n * No React. No Vue. No virtual-dom. No external rendering library.\n *\n * Pipeline:\n * CompiledApplication\n * → mountGraph (creates all DOM nodes)\n * → signal subscriptions drive patchNode (targeted updates)\n * → flush() propagates any pending scheduler jobs\n * → unmount() disposes everything\n */\n\nimport type { DOMAdapter } from '@streetui/dom';\nimport { BrowserDOMAdapter } from '@streetui/dom';\nimport type { CompiledApplication } from '@streetui/compiler';\nimport type { StreetRenderer, RenderHandle } from '@streetui/runtime';\nimport { createRenderContext } from './render-context.js';\nimport { mountGraph } from './mount.js';\nimport { hydrateGraph } from './hydrate.js';\nimport { StreetRenderHandle } from './render-handle.js';\nimport type { NodeInstance } from './node-instance.js';\nimport type { HydrationDiagnosticSink } from './hydration-diagnostics.js';\n\nexport interface StreetRendererOptions {\n /** Override the DOM adapter (e.g. for testing). Defaults to BrowserDOMAdapter. */\n readonly domAdapter?: DOMAdapter;\n /**\n * Optional dev-only sink that observes hydration mismatch repairs. Attach one\n * to surface server/client divergences during development; leave it unset in\n * production so hydration does no extra work.\n */\n readonly hydrationDiagnostics?: HydrationDiagnosticSink;\n}\n\nexport class StreetRendererImpl implements StreetRenderer {\n private readonly _dom: DOMAdapter;\n private readonly _hydrationDiagnostics?: HydrationDiagnosticSink;\n\n constructor(options: StreetRendererOptions = {}) {\n this._dom = options.domAdapter ?? new BrowserDOMAdapter();\n if (options.hydrationDiagnostics !== undefined) {\n this._hydrationDiagnostics = options.hydrationDiagnostics;\n }\n }\n\n mount(compiled: CompiledApplication, container: Element): RenderHandle {\n const ctx = createRenderContext(this._dom, compiled.graph, container);\n\n // Initial mount — creates the full DOM tree\n const rootInstance = mountGraph(ctx);\n\n // Wire all signal subscriptions so that signal → DOM patches happen automatically\n this._wireSignals(ctx, rootInstance);\n\n return new StreetRenderHandle(ctx, rootInstance);\n }\n\n /**\n * Hydrate a container that already holds server-rendered HTML for this\n * application. Instead of recreating the DOM, it walks the semantic graph\n * against the existing nodes, adopting matching elements and attaching\n * behavior (events + signal subscriptions). Mismatched subtrees are locally\n * replaced. Returns the same handle type as `mount`.\n */\n hydrate(compiled: CompiledApplication, container: Element): RenderHandle {\n const ctx = createRenderContext(\n this._dom,\n compiled.graph,\n container,\n this._hydrationDiagnostics,\n );\n const rootInstance = hydrateGraph(ctx);\n this._wireSignals(ctx, rootInstance);\n return new StreetRenderHandle(ctx, rootInstance);\n }\n\n private _wireSignals(\n ctx: ReturnType<typeof createRenderContext>,\n rootInstance: NodeInstance,\n ): void {\n // Each NodeInstance already wired its own signals in mountNode via wireSignalBindings.\n // This method is a hook for any cross-cutting signal concerns at the renderer level.\n // Currently no-op — individual mount calls handle their own subscriptions.\n void ctx;\n void rootInstance;\n }\n}\n\n/**\n * Create the default StreetUI renderer using the browser's DOM APIs.\n */\nexport function createRenderer(options?: StreetRendererOptions): StreetRendererImpl {\n return new StreetRendererImpl(options);\n}\n","/**\n * Hydration diagnostics — dev-only, opt-in explanations of hydration mismatches.\n *\n * Hydration is self-repairing: when the server-rendered DOM does not match the\n * graph at a position, the renderer mounts a fresh subtree in place and drops\n * the offending element (see `hydrateChildren` in `hydrate.ts`). That recovery\n * is silent by design — a local mismatch must never tear down the whole app.\n *\n * During development, though, a silent repair hides a real problem (usually a\n * server/client divergence). A `HydrationDiagnosticSink` can be attached to the\n * renderer to *observe* those repairs without changing them: for every mismatch\n * the renderer reports what it expected, what it found, where, and what it did\n * to recover. Nothing is thrown, nothing is mutated differently, and when no\n * sink is attached there is zero additional work on the hydration path.\n */\n\n/** What kind of divergence the hydrator encountered at a position. */\nexport type HydrationMismatchType =\n | 'tag-mismatch' // an element existed but was the wrong tag\n | 'missing-element' // the graph expected a child the DOM did not provide\n | 'surplus-element'; // the DOM had a child the graph no longer expects\n\n/** A single, fully-described hydration divergence and the repair taken. */\nexport interface HydrationDiagnostic {\n /** The category of mismatch. */\n readonly type: HydrationMismatchType;\n /** The tag the graph expected at this position (null for a surplus element). */\n readonly expected: string | null;\n /** The tag actually found in the server DOM (null for a missing element). */\n readonly found: string | null;\n /** A human-readable path to the position, e.g. `app / page[0] / section[1]`. */\n readonly path: string;\n /** The graph node id involved, when one exists (null for surplus DOM). */\n readonly nodeId: string | null;\n /** The semantic node type involved, when one exists (null for surplus DOM). */\n readonly nodeType: string | null;\n /** The recovery action the renderer performed. */\n readonly action: string;\n /** A single-line, developer-facing summary of the whole diagnostic. */\n readonly message: string;\n}\n\n/**\n * Receives hydration diagnostics as they are discovered. Kept intentionally\n * tiny so any logger — `console`, a test collector, a `DiagnosticSink` — can\n * satisfy it. Implementations must not throw.\n */\nexport interface HydrationDiagnosticSink {\n report(diagnostic: HydrationDiagnostic): void;\n}\n\n/** Build the canonical one-line message for a diagnostic. */\nexport function formatHydrationDiagnostic(\n d: Omit<HydrationDiagnostic, 'message'>,\n): string {\n const at = ` at ${d.path}`;\n switch (d.type) {\n case 'tag-mismatch':\n return `Hydration mismatch${at} — Expected: ${d.expected} / Found: ${d.found} / Action: ${d.action}`;\n case 'missing-element':\n return `Hydration mismatch${at} — Expected: ${d.expected} / Found: (nothing) / Action: ${d.action}`;\n case 'surplus-element':\n return `Hydration mismatch${at} — Expected: (nothing) / Found: ${d.found} / Action: ${d.action}`;\n }\n}\n\n/**\n * A ready-made sink that accumulates diagnostics into an array — the shape most\n * useful for tests and for a DevTools panel. The returned `diagnostics` array is\n * appended to in-place as repairs happen.\n */\nexport function createHydrationDiagnosticCollector(): {\n readonly sink: HydrationDiagnosticSink;\n readonly diagnostics: HydrationDiagnostic[];\n} {\n const diagnostics: HydrationDiagnostic[] = [];\n return {\n diagnostics,\n sink: {\n report(d) {\n diagnostics.push(d);\n },\n },\n };\n}\n\n/**\n * A sink that forwards each diagnostic to a `console`-like logger as a single\n * warning line. Handy default when you just want the messages surfaced in dev.\n */\nexport function consoleHydrationDiagnosticSink(\n logger: { warn(message: string): void } = console,\n): HydrationDiagnosticSink {\n return {\n report(d) {\n logger.warn(d.message);\n },\n };\n}\n","/**\n * Hydration — attach a live StreetUI runtime to server-rendered HTML.\n *\n * `hydrate` walks the semantic application graph top-down against the DOM that\n * the server already produced. For every graph node it *adopts* the matching\n * existing element (creating a `NodeInstance` that points at it) and attaches\n * behavior — event listeners and signal subscriptions — using the exact same\n * helpers the browser mount path uses (`wireEvents`, `wireSignalBindings`,\n * `wireReactiveList`, and the per-type update factories). Nothing is recreated\n * when the DOM matches.\n *\n * Matching is positional and works because every non-application graph node\n * maps to exactly one element (see mount.ts). When the element at a position\n * does not match the expected tag (or is missing), only that subtree is\n * repaired: the fresh subtree is mounted and spliced into place, leaving the\n * rest of the hydrated tree untouched. A local mismatch never tears down the\n * whole app.\n */\n\nimport type { GraphNode } from '@streetui/graph';\nimport type { RenderContext } from './render-context.js';\nimport { NodeInstance } from './node-instance.js';\nimport { wireEvents } from './events.js';\nimport { resolveTag } from './tag-map.js';\nimport { formatHydrationDiagnostic } from './hydration-diagnostics.js';\nimport {\n mountNode,\n wireSignalBindings,\n wireReactiveList,\n textUpdate,\n headingUpdate,\n inputUpdate,\n buttonUpdate,\n} from './mount.js';\n\n/** Hydrate the whole application graph against `ctx.container`. */\nexport function hydrateGraph(ctx: RenderContext): NodeInstance {\n const root = ctx.graph.root;\n // The application root maps to the container itself (no element of its own),\n // exactly as in mountNode.\n const instance = new NodeInstance(root, ctx.container);\n ctx.instances.set(root.id, instance);\n hydrateChildren(ctx, root, instance, ctx.container, 'app');\n return instance;\n}\n\n/**\n * Adopt `domNode` as the live element for `graphNode` and attach behavior.\n * The caller has already verified `domNode` matches `graphNode` (right tag).\n * `path` is the human-readable position used only for dev diagnostics.\n */\nfunction hydrateNode(\n ctx: RenderContext,\n graphNode: GraphNode,\n domNode: Element,\n path: string,\n): NodeInstance {\n const { dom, graph } = ctx;\n\n switch (graphNode.type) {\n case 'text': {\n // <span> with an inner text node. Adopt the text node (or create one if\n // the server markup somehow lacks it).\n let textNode = dom.firstChild(domNode);\n if (textNode === null || !dom.isTextNode(textNode)) {\n const created = dom.createTextNode(String(graphNode.getProp('text') ?? ''));\n dom.appendChild(domNode, created);\n textNode = created;\n }\n const instance = new NodeInstance(graphNode, domNode);\n ctx.instances.set(graphNode.id, instance);\n wireEvents(dom, graph, graphNode, domNode, instance);\n // Only build the per-type update closure when the node actually has\n // reactive bindings. wireSignalBindings early-returns on an empty\n // stateRefs list, so for a static node the `textUpdate(...)` closure would\n // be allocated and immediately discarded — pure GC pressure on the hot\n // hydration path, where the vast majority of nodes are static.\n if (graphNode.stateRefs.length !== 0) {\n wireSignalBindings(ctx, graphNode, instance, textUpdate(dom, domNode, textNode as Text));\n }\n return instance;\n }\n\n case 'heading': {\n const instance = new NodeInstance(graphNode, domNode);\n ctx.instances.set(graphNode.id, instance);\n wireEvents(dom, graph, graphNode, domNode, instance);\n if (graphNode.stateRefs.length !== 0) {\n wireSignalBindings(ctx, graphNode, instance, headingUpdate(dom, domNode));\n }\n return instance;\n }\n\n case 'input': {\n const instance = new NodeInstance(graphNode, domNode);\n ctx.instances.set(graphNode.id, instance);\n // The controlled value is already present in the server HTML (reflected as\n // the `value` attribute). Re-assert it as a live property so the element's\n // current value matches the bound signal exactly.\n const value = graphNode.getProp('value');\n if (value !== undefined) dom.setProperty(domNode, 'value', String(value));\n wireEvents(dom, graph, graphNode, domNode, instance);\n if (graphNode.stateRefs.length !== 0) {\n wireSignalBindings(ctx, graphNode, instance, inputUpdate(dom, domNode));\n }\n return instance;\n }\n\n case 'button': {\n const instance = new NodeInstance(graphNode, domNode);\n ctx.instances.set(graphNode.id, instance);\n wireEvents(dom, graph, graphNode, domNode, instance);\n if (graphNode.stateRefs.length !== 0) {\n wireSignalBindings(ctx, graphNode, instance, buttonUpdate(dom, domNode));\n }\n return instance;\n }\n\n case 'image':\n case 'link': {\n // Leaf elements with no reactive bindings or events beyond what the markup\n // already encodes; links may still carry click handlers.\n const instance = new NodeInstance(graphNode, domNode);\n ctx.instances.set(graphNode.id, instance);\n if (graphNode.type === 'link') wireEvents(dom, graph, graphNode, domNode, instance);\n return instance;\n }\n\n case 'reactive-list':\n case 'conditional': {\n // The server rendered the initial children (built into the graph at\n // compile time from the initial signal state). Adopt them positionally,\n // then subscribe for future signal changes — the same keyed reconciler as\n // the browser drives subsequent updates against the adopted instances.\n const instance = new NodeInstance(graphNode, domNode);\n ctx.instances.set(graphNode.id, instance);\n hydrateChildren(ctx, graphNode, instance, domNode, path);\n wireReactiveList(ctx, graphNode, instance, domNode);\n return instance;\n }\n\n default: {\n // Structural nodes: container / section / page / form / list / list-item.\n const instance = new NodeInstance(graphNode, domNode);\n ctx.instances.set(graphNode.id, instance);\n if (graphNode.type === 'form') {\n wireEvents(dom, graph, graphNode, domNode, instance);\n }\n // Hydration boundary (a \"slot\" such as the router outlet): adopt the\n // element itself but leave its existing children untouched — neither\n // hydrated by this pass nor removed as surplus. Something else (e.g. the\n // router) owns and will hydrate the content already inside it. Without\n // this, an empty-in-the-graph slot would strip the server-rendered\n // content it is meant to preserve.\n if (graphNode.getProp('_hydrationBoundary') === true) {\n return instance;\n }\n hydrateChildren(ctx, graphNode, instance, domNode, path);\n return instance;\n }\n }\n}\n\n// ── Child matching + local mismatch recovery ───────────────────────────────────\n\n/**\n * Positionally match a parent's expected child graph nodes against the actual\n * child *elements* in the DOM. Matching children are hydrated in place; a\n * mismatch (wrong tag or a missing element) triggers a local repair — the fresh\n * subtree is mounted and spliced into the correct position — without disturbing\n * sibling subtrees. Surplus DOM elements are removed.\n */\nfunction hydrateChildren(\n ctx: RenderContext,\n parentGraphNode: GraphNode,\n parentInstance: NodeInstance,\n parentDom: Element,\n parentPath: string,\n): void {\n const expected = parentGraphNode.children;\n const actual = elementChildren(ctx, parentDom);\n let cursor = 0;\n\n // The human-readable `path` is only ever consumed by hydration diagnostics,\n // which are inert unless a sink is attached. Building the\n // `${parentPath} / ${type}[${i}]` string for every child would allocate one\n // throwaway string per node on the hot path (10k+ on a large tree) for output\n // that is discarded in production. Gate the construction on the sink being\n // present; when it is absent, thread the (meaningless-but-unused) parent path\n // through unchanged so nested calls stay allocation-free too.\n const diag = ctx.hydrationDiagnostics !== undefined;\n\n for (let i = 0; i < expected.length; i++) {\n const childNode = expected[i]!;\n const want = expectedTag(ctx, childNode);\n const childPath = diag ? `${parentPath} / ${childNode.type}[${i}]` : parentPath;\n const actualEl = actual[cursor];\n\n if (\n actualEl !== undefined &&\n ctx.dom.isElement(actualEl) &&\n ctx.dom.tagName(actualEl) === want\n ) {\n // Match — adopt the existing element.\n const inst = hydrateNode(ctx, childNode, actualEl, childPath);\n parentInstance.addChild(inst);\n cursor++;\n } else {\n // Mismatch or missing — repair only this subtree. Mount fresh, then move\n // it into the correct position ahead of the offending/absent node.\n const ref = actualEl ?? null;\n const inst = mountFreshAt(ctx, childNode, parentDom, ref);\n parentInstance.addChild(inst);\n if (actualEl !== undefined) {\n // Drop the mismatched element that the fresh node replaces.\n const found = ctx.dom.isElement(actualEl) ? ctx.dom.tagName(actualEl) : null;\n reportHydrationDiagnostic(ctx, {\n type: 'tag-mismatch',\n expected: want,\n found,\n path: childPath,\n nodeId: childNode.id,\n nodeType: childNode.type,\n action: 'mounted fresh subtree in place',\n });\n ctx.dom.removeChild(parentDom, actualEl);\n cursor++;\n } else {\n reportHydrationDiagnostic(ctx, {\n type: 'missing-element',\n expected: want,\n found: null,\n path: childPath,\n nodeId: childNode.id,\n nodeType: childNode.type,\n action: 'mounted fresh subtree',\n });\n }\n }\n }\n\n // Remove any surplus server elements the graph no longer expects.\n for (let i = cursor; i < actual.length; i++) {\n const surplus = actual[i]!;\n reportHydrationDiagnostic(ctx, {\n type: 'surplus-element',\n expected: null,\n found: ctx.dom.isElement(surplus) ? ctx.dom.tagName(surplus) : null,\n path: `${parentPath} / [surplus ${i}]`,\n nodeId: null,\n nodeType: null,\n action: 'removed surplus server element',\n });\n ctx.dom.removeChild(parentDom, surplus);\n }\n}\n\n/**\n * Emit a hydration diagnostic through the (optional) sink. When no sink is\n * attached this is a single cheap `undefined` check — the production default.\n */\nfunction reportHydrationDiagnostic(\n ctx: RenderContext,\n d: {\n type: 'tag-mismatch' | 'missing-element' | 'surplus-element';\n expected: string | null;\n found: string | null;\n path: string;\n nodeId: string | null;\n nodeType: string | null;\n action: string;\n },\n): void {\n const sink = ctx.hydrationDiagnostics;\n if (sink === undefined) return;\n sink.report({ ...d, message: formatHydrationDiagnostic(d) });\n}\n\n/** Mount a fresh subtree for `node` and splice it before `ref` (or append). */\nfunction mountFreshAt(\n ctx: RenderContext,\n node: GraphNode,\n parentDom: Element,\n ref: Node | null,\n): NodeInstance {\n // mountNode appends the new subtree at the end of parentDom.\n const inst = mountNode(ctx, node, parentDom);\n if (ref !== null) {\n ctx.dom.insertBefore(parentDom, inst.domNode, ref);\n }\n return inst;\n}\n\n/** The element (not text/comment) children of a node, in order. */\nfunction elementChildren(ctx: RenderContext, parent: Element): Element[] {\n const out: Element[] = [];\n for (const node of ctx.dom.childNodes(parent)) {\n if (ctx.dom.isElement(node)) out.push(node);\n }\n return out;\n}\n\n/** The HTML tag a graph node is expected to occupy in the DOM. */\nfunction expectedTag(ctx: RenderContext, graphNode: GraphNode): string {\n switch (graphNode.type) {\n case 'text':\n return 'span';\n case 'heading': {\n const level = (graphNode.getProp('level') as number | undefined) ?? 1;\n return `h${level}`;\n }\n case 'input':\n return 'input';\n case 'image':\n return 'img';\n case 'link':\n return 'a';\n case 'button':\n return 'button';\n default:\n // reactive-list → ul, conditional → div, structural → resolveTag.\n return resolveTag(graphNode.type);\n }\n}\n","/**\n * StreetRenderHandle — the live handle returned by both `mount` and `hydrate`.\n *\n * Owns teardown for a mounted/hydrated application: disposes every NodeInstance\n * (removing event listeners and signal subscriptions) and clears the container\n * through the DOM adapter (never raw browser globals), so the same handle works\n * for browser and — in principle — server-driven teardown.\n */\n\nimport type { RenderHandle } from '@streetui/runtime';\nimport type { RenderContext } from './render-context.js';\nimport type { NodeInstance } from './node-instance.js';\n\nexport class StreetRenderHandle implements RenderHandle {\n private _disposed = false;\n private readonly _ctx: RenderContext;\n private readonly _rootInstance: NodeInstance;\n\n constructor(ctx: RenderContext, rootInstance: NodeInstance) {\n this._ctx = ctx;\n this._rootInstance = rootInstance;\n }\n\n flush(): void {\n if (this._disposed) return;\n // Signal subscriptions fire synchronously in StreetUI's state system;\n // flush() is a no-op at the renderer level — the DOM is already up to date\n // unless the scheduler is batching, in which case the scheduler calls\n // flush() after draining its queue.\n }\n\n unmount(): void {\n if (this._disposed) return;\n this._disposed = true;\n\n // Dispose all node instances (removes event listeners, signal subscriptions).\n this._rootInstance.dispose();\n\n // Remove all children from the container. Routed through the DOM adapter\n // (never `container.firstChild`/`removeChild`) so the teardown path is\n // server-safe.\n const dom = this._ctx.dom;\n const container = this._ctx.container;\n for (const child of dom.childNodes(container)) {\n dom.removeChild(container, child);\n }\n\n this._ctx.instances.clear();\n }\n}\n","/**\n * SSR state transfer (dehydration) — move server-resolved data to the client.\n *\n * When the server resolves resources before rendering, their data must reach\n * the client so hydration can seed them (via `resource({ initialData })`)\n * instead of refetching. StreetUI does this with a single, framework-scoped\n * `<script>` payload rather than blindly interpolating `JSON.stringify` into\n * markup.\n *\n * Safety (v0.4 rule #16): the JSON is emitted into a\n * `<script type=\"application/json\">` block — an inert data island the browser\n * never executes — and every character that could terminate that block or be\n * reinterpreted by the HTML/JS parser is escaped to its `\\uXXXX` form. Because\n * `<` inside JSON parses back to `<`, the payload round-trips exactly\n * while being impossible to break out of. This is deterministic (stable key\n * order is the caller's responsibility) and typed at the boundary as\n * `Record<string, unknown>` — never `any`.\n */\n\nimport type { DOMAdapter } from '@streetui/dom';\n\n/** Attribute marking StreetUI's state island so the client can find it. */\nexport const STATE_MARKER_ATTR = 'data-streetui-state';\n\n/**\n * Escape a JSON string for safe embedding inside a `<script>` element:\n * < > & → HTML / `</script>` breakout and entity ambiguity\n * U+2028 / U+2029 → invalid raw in JS string literals\n * Uses code-point checks so no raw separator characters live in this source.\n */\nfunction escapeForScript(json: string): string {\n let out = '';\n for (const ch of json) {\n const code = ch.charCodeAt(0);\n if (ch === '<') out += '\\\\u003c';\n else if (ch === '>') out += '\\\\u003e';\n else if (ch === '&') out += '\\\\u0026';\n else if (code === 0x2028) out += '\\\\u2028';\n else if (code === 0x2029) out += '\\\\u2029';\n else out += ch;\n }\n return out;\n}\n\n/**\n * Serialize a state map to an HTML `<script>` island for inclusion in the\n * server-rendered document (typically just before the closing tag of the\n * mount container). Returns an empty string for an empty map.\n */\nexport function serializeState(state: Record<string, unknown>): string {\n if (Object.keys(state).length === 0) return '';\n const json = escapeForScript(JSON.stringify(state));\n return `<script type=\"application/json\" ${STATE_MARKER_ATTR}>${json}</script>`;\n}\n\n/**\n * Read the state island back on the client. Searches `root` for StreetUI's\n * state `<script>` and parses it. Returns an empty object when absent or\n * unparseable (hydration then proceeds as a cold client render). Routed through\n * the DOM adapter so it is testable and never assumes a global `document`.\n */\nexport function readState(\n dom: DOMAdapter,\n root: Element | Document,\n): Record<string, unknown> {\n const el = dom.querySelector(root, `script[${STATE_MARKER_ATTR}]`);\n if (el === null) return {};\n const text = dom.getTextContent(el);\n if (text === null || text.length === 0) return {};\n try {\n const parsed: unknown = JSON.parse(text);\n if (parsed !== null && typeof parsed === 'object') {\n return parsed as Record<string, unknown>;\n }\n return {};\n } catch {\n return {};\n }\n}\n","/**\n * Server-side rendering — `renderToString`.\n *\n * Runs the *exact same* mount pipeline used in the browser (`mountGraph`), but\n * against a `ServerDOMAdapter` that builds a lightweight in-memory node tree\n * instead of a real browser DOM. The tree is then serialized to a normal HTML\n * string. Because both browser and server share the DSL → Compiler → Graph →\n * Runtime → Renderer pipeline, there is no second, SSR-specific renderer and no\n * virtual DOM.\n *\n * Lifecycle (v0.4 rule #20): the initial synchronous mount may open signal\n * subscriptions (via `wireSignalBindings`/`wireReactiveList`). On the server\n * those would be live forever, so once the HTML is serialized we dispose the\n * root instance — tearing down every subscription and listener. SSR therefore\n * has a *render* lifecycle only; the live *runtime* lifecycle is established\n * later on the client by `hydrate`.\n */\n\nimport { ServerDOMAdapter } from '@streetui/dom';\nimport type { CompiledApplication } from '@streetui/compiler';\nimport { createRenderContext } from './render-context.js';\nimport { mountGraph } from './mount.js';\n\nexport interface RenderToStringOptions {\n /**\n * Override the server DOM adapter (rarely needed). Defaults to a fresh\n * `ServerDOMAdapter` per call so concurrent renders never share state.\n */\n readonly domAdapter?: ServerDOMAdapter;\n}\n\n/**\n * Render a compiled StreetUI application to an HTML string.\n *\n * The returned markup contains only the application's own elements (the\n * synthetic container is not emitted), so callers embed it wherever they mount\n * on the client — e.g. inside `<div id=\"app\">…</div>`.\n */\nexport function renderToString(\n compiled: CompiledApplication,\n options: RenderToStringOptions = {},\n): string {\n const dom = options.domAdapter ?? new ServerDOMAdapter();\n\n // Synthetic container — the application root maps onto it, and the app's\n // top-level nodes are appended directly into it (mirroring browser mount).\n const container = dom.createElement('div');\n\n const ctx = createRenderContext(dom, compiled.graph, container);\n const rootInstance = mountGraph(ctx);\n\n const html = dom.serializeInner(container);\n\n // Tear down any subscriptions/listeners opened during mount — the server has\n // no live runtime. (rule #20)\n rootInstance.dispose();\n ctx.instances.clear();\n\n return html;\n}\n"],"mappings":"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","names":["instance","el","tag","import_dom"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/render-context.ts","../src/node-instance.ts","../src/attributes.ts","../src/events.ts","../src/mount.ts","../src/tag-map.ts","../src/patch.ts","../src/reconciliation.ts","../src/renderer.ts","../src/hydration-diagnostics.ts","../src/hydrate.ts","../src/render-handle.ts","../src/dehydrate.ts","../src/ssr.ts","../src/static-ssr-plan.ts"],"sourcesContent":["export * from './render-context.js';\nexport * from './node-instance.js';\nexport * from './attributes.js';\nexport * from './events.js';\nexport * from './mount.js';\nexport * from './patch.js';\nexport * from './reconciliation.js';\nexport * from './renderer.js';\nexport * from './render-handle.js';\nexport * from './hydrate.js';\nexport * from './hydration-diagnostics.js';\nexport * from './dehydrate.js';\nexport * from './ssr.js';\nexport * from './tag-map.js';\n","/**\n * RenderContext — shared state for a single mount operation.\n *\n * Passed through the render pipeline so every sub-function has access\n * to the DOM adapter, graph, and instance map without prop-drilling.\n */\n\nimport type { DOMAdapter } from '@streetui/dom';\nimport type { ApplicationGraph, GraphNode } from '@streetui/graph';\nimport type { NodeInstance } from './node-instance.js';\nimport type { HydrationDiagnosticSink } from './hydration-diagnostics.js';\n\nexport interface RenderContext {\n readonly dom: DOMAdapter;\n readonly graph: ApplicationGraph;\n /** Maps GraphNode.id → its live NodeInstance */\n readonly instances: Map<string, NodeInstance>;\n /** The root container element. */\n readonly container: Element;\n /**\n * Optional dev-only sink that observes hydration mismatch repairs. When\n * absent (the default) the hydration path does no extra work — this is how\n * DevTools/diagnostics stay off the production runtime path.\n */\n readonly hydrationDiagnostics?: HydrationDiagnosticSink;\n /**\n * Optional SSR-only static-subtree plan (v1.7). Maps a maximal\n * static-subtree root GraphNode.id → its precomputed, verbatim HTML string.\n * Present only on the server render path when a plan has been built; on the\n * browser mount path it is always `undefined`, so the client hot path is\n * unaffected (a single `=== undefined` check short-circuits). When a mounted\n * node's id is in this map, the renderer emits the precomputed HTML via\n * `dom.createRawHTML` instead of recursively constructing the subtree.\n */\n readonly staticHTML?: ReadonlyMap<string, string>;\n}\n\nexport function createRenderContext(\n dom: DOMAdapter,\n graph: ApplicationGraph,\n container: Element,\n hydrationDiagnostics?: HydrationDiagnosticSink,\n staticHTML?: ReadonlyMap<string, string>,\n): RenderContext {\n return {\n dom,\n graph,\n instances: new Map(),\n container,\n ...(hydrationDiagnostics !== undefined ? { hydrationDiagnostics } : {}),\n ...(staticHTML !== undefined ? { staticHTML } : {}),\n };\n}\n","/**\n * NodeInstance — the renderer's live counterpart to a GraphNode.\n *\n * Tracks the actual DOM node(s), all signal subscriptions that drive\n * targeted DOM updates, and DOM event listener teardowns.\n */\n\nimport { CleanupRegistry } from '@streetui/core';\nimport type { GraphNode } from '@streetui/graph';\nimport type { ReadonlySignal } from '@streetui/state';\n\nexport class NodeInstance {\n readonly graphNode: GraphNode;\n /** The primary DOM node for this instance (element or text node). */\n domNode: Node;\n readonly children: NodeInstance[] = [];\n readonly cleanup: CleanupRegistry = new CleanupRegistry();\n\n constructor(graphNode: GraphNode, domNode: Node) {\n this.graphNode = graphNode;\n this.domNode = domNode;\n }\n\n addChild(child: NodeInstance): void {\n this.children.push(child);\n }\n\n /** Subscribe to a signal; auto-cleanup on unmount. */\n trackSignal<T>(sig: ReadonlySignal<T>, handler: (v: T) => void): void {\n const unsub = sig.subscribe(handler);\n this.cleanup.add(unsub);\n }\n\n /** Register a raw cleanup fn (DOM event removal, etc.). */\n trackCleanup(fn: () => void): void {\n this.cleanup.add(fn);\n }\n\n dispose(): void {\n for (const child of this.children) {\n child.dispose();\n }\n this.cleanup.run();\n }\n}\n","/**\n * Attribute and property application helpers.\n *\n * Decides whether a prop should be set as a DOM attribute or a JS property,\n * handling special cases (boolean attrs, event-like props, style, class).\n */\n\nimport type { DOMAdapter } from '@streetui/dom';\n\n// Properties that must be set as JS object properties, not HTML attributes\nconst DOM_PROPERTIES = new Set([\n 'value', 'checked', 'selected', 'indeterminate',\n 'innerHTML', 'textContent', 'innerText',\n 'scrollTop', 'scrollLeft',\n]);\n\n// Boolean attributes — present means true, absent means false\nconst BOOLEAN_ATTRS = new Set([\n 'disabled', 'readonly', 'required', 'checked', 'selected',\n 'multiple', 'autofocus', 'autoplay', 'controls', 'default',\n 'defer', 'formnovalidate', 'hidden', 'ismap', 'loop',\n 'novalidate', 'open', 'reversed', 'scoped', 'seamless',\n]);\n\nexport function applyProp(\n dom: DOMAdapter,\n element: Element,\n name: string,\n value: unknown,\n): void {\n // Skip internal renderer metadata\n if (name.startsWith('_')) return;\n // Skip event handlers (handled separately)\n if (name.startsWith('on')) return;\n\n if (DOM_PROPERTIES.has(name)) {\n dom.setProperty(element, name, value);\n return;\n }\n\n if (BOOLEAN_ATTRS.has(name)) {\n if (value === true || value === '' || value === name) {\n dom.setAttribute(element, name, '');\n } else {\n dom.removeAttribute(element, name);\n }\n return;\n }\n\n if (name === 'class' || name === 'className') {\n dom.setAttribute(element, 'class', String(value ?? ''));\n return;\n }\n\n if (name === 'style' && typeof value === 'object' && value !== null) {\n const el = element as HTMLElement;\n const styles = value as Record<string, string>;\n for (const [k, v] of Object.entries(styles)) {\n el.style.setProperty(k, v);\n }\n return;\n }\n\n if (value === null || value === undefined || value === false) {\n dom.removeAttribute(element, name);\n return;\n }\n\n dom.setAttribute(element, name, String(value));\n}\n\nexport function patchProp(\n dom: DOMAdapter,\n element: Element,\n name: string,\n oldValue: unknown,\n newValue: unknown,\n): void {\n if (Object.is(oldValue, newValue)) return;\n applyProp(dom, element, name, newValue);\n}\n","/**\n * Event wiring for the renderer.\n *\n * Given a GraphNode with event descriptors, this wires DOM listeners\n * that call the handlers stored in the graph's handler registry.\n */\n\nimport type { DOMAdapter } from '@streetui/dom';\nimport type { ApplicationGraph, GraphNode } from '@streetui/graph';\nimport type { NodeInstance } from './node-instance.js';\n\nexport function wireEvents(\n dom: DOMAdapter,\n graph: ApplicationGraph,\n node: GraphNode,\n element: Element,\n instance: NodeInstance,\n): void {\n // Fast exit for event-free nodes — avoids allocating a for-of iterator over\n // an empty array on every node during a large mount/hydrate.\n if (node.events.length === 0) return;\n for (const eventDesc of node.events) {\n const handler = graph.getHandler(eventDesc.handlerKey);\n if (handler === undefined) continue;\n\n const domListener: EventListener = (domEvent: Event) => {\n // For input events, pass the current value as first arg\n if (eventDesc.type === 'input' || eventDesc.type === 'change') {\n const input = domEvent.target as HTMLInputElement;\n (handler as (v: string) => void)(input.value);\n } else if (eventDesc.type === 'submit') {\n domEvent.preventDefault();\n (handler as (e: Event) => void)(domEvent);\n } else {\n (handler as () => void)();\n }\n };\n\n dom.addEventListener(element, eventDesc.type, domListener);\n instance.trackCleanup(() => {\n dom.removeEventListener(element, eventDesc.type, domListener);\n });\n }\n}\n","/**\n * Initial mount — creates DOM nodes for every GraphNode and\n * attaches them into the container.\n *\n * This is a recursive depth-first walk. For each GraphNode:\n * 1. Create the DOM element (or text node)\n * 2. Apply props/attributes\n * 3. Wire events\n * 4. Wire signal subscriptions for reactive props\n * 5. Recurse into children\n * 6. Insert into the DOM\n */\n\nimport type { GraphNode, ApplicationGraph } from '@streetui/graph';\nimport type { DOMAdapter } from '@streetui/dom';\nimport {\n focusInitial,\n trapFocus,\n containFocus,\n onEscape,\n saveFocus,\n restoreFocus,\n} from '@streetui/dom';\nimport type { RenderContext } from './render-context.js';\nimport { NodeInstance } from './node-instance.js';\nimport { applyProp } from './attributes.js';\nimport { wireEvents } from './events.js';\nimport { resolveTag } from './tag-map.js';\nimport {\n reconcileChildren,\n reconcileChildrenByPlan,\n type PlanEntry,\n} from './reconciliation.js';\n\n/**\n * Prop keys handled by the per-type mount branches (or reserved internals), so\n * `applyNodeProps` must skip them to avoid double-applying. This set is\n * invariant across nodes, so it is hoisted to module scope: allocating it once\n * (rather than per node) removes N Set allocations per mount/SSR pass and the\n * GC pressure they create. Treat as read-only — never mutate.\n */\nconst SKIP_PROP_KEYS: ReadonlySet<string> = new Set([\n 'text', 'label', 'level', 'inputType', 'src', 'alt', 'href', 'external',\n 'value', 'placeholder', 'disabled', '_renderKey', 'key', 'name',\n]);\n\nexport function mountGraph(ctx: RenderContext): NodeInstance {\n return mountNode(ctx, ctx.graph.root, ctx.container);\n}\n\nexport function mountNode(\n ctx: RenderContext,\n graphNode: GraphNode,\n parentDom: Node,\n): NodeInstance {\n const { dom, graph } = ctx;\n\n // ── v1.7 static SSR fast path (SSR-only) ──────────────────────────────────\n // When a compiler-derived static SSR plan is present (server render only)\n // and this node is a maximal static-subtree root, emit its precomputed HTML\n // verbatim instead of recursively constructing ServerElement/ServerText/\n // NodeInstance for the whole subtree. `ctx.staticHTML` is always undefined on\n // the browser path, so this is a single short-circuiting check there — the\n // client hot path and its semantics are untouched (§5/§6/§23). The stored\n // string is produced by this same mount+serialize pipeline, so output is\n // byte-identical (§8). We still register ONE NodeInstance for the root so the\n // parent's children bookkeeping and post-render dispose behave normally.\n const staticHTML = ctx.staticHTML;\n if (staticHTML !== undefined && dom.createRawHTML !== undefined) {\n const precomputed = staticHTML.get(graphNode.id);\n if (precomputed !== undefined) {\n const raw = dom.createRawHTML(precomputed);\n dom.appendChild(parentDom, raw);\n const instance = new NodeInstance(graphNode, raw);\n ctx.instances.set(graphNode.id, instance);\n return instance;\n }\n }\n\n // The application root node maps to the container itself — don't create a duplicate element\n if (graphNode.type === 'application') {\n const instance = new NodeInstance(graphNode, parentDom);\n ctx.instances.set(graphNode.id, instance);\n for (const child of graphNode.children) {\n const childInstance = mountNode(ctx, child, parentDom);\n instance.addChild(childInstance);\n }\n return instance;\n }\n\n // Text-only nodes render as a <span> containing a text node\n if (graphNode.type === 'text') {\n const text = String(graphNode.getProp('text') ?? '');\n const el = dom.createElement('span');\n const textNode = dom.createTextNode(text);\n dom.appendChild(el, textNode);\n applyNodeProps(ctx, graphNode, el);\n\n // Create the live instance up front and reuse it for event wiring. The\n // previous code allocated a throwaway NodeInstance solely to satisfy\n // wireEvents' signature, wasting one NodeInstance (+ its children array and\n // CleanupRegistry) per text node — pure GC pressure on the hottest mount\n // path. wireEvents/wireSignalBindings each early-return on empty arrays.\n const instance = new NodeInstance(graphNode, el);\n ctx.instances.set(graphNode.id, instance);\n wireEvents(dom, graph, graphNode, el, instance);\n\n // Reactive text binding — only build the update closure when the node has\n // bindings. wireSignalBindings early-returns on empty stateRefs, so for a\n // static text node (the common case in a large initial render) the\n // textUpdate closure would be allocated and thrown away: avoidable GC\n // pressure on the hottest mount path.\n if (graphNode.stateRefs.length !== 0) {\n wireSignalBindings(ctx, graphNode, instance, textUpdate(dom, el, textNode));\n }\n\n dom.appendChild(parentDom, el);\n return instance;\n }\n\n // Heading nodes\n if (graphNode.type === 'heading') {\n const level = (graphNode.getProp('level') as number | undefined) ?? 1;\n const tag = `h${level}` as string;\n const el = dom.createElement(tag);\n const text = String(graphNode.getProp('text') ?? '');\n dom.setTextContent(el, text);\n applyNodeProps(ctx, graphNode, el);\n\n const instance = new NodeInstance(graphNode, el);\n ctx.instances.set(graphNode.id, instance);\n wireEvents(dom, graph, graphNode, el, instance);\n\n if (graphNode.stateRefs.length !== 0) {\n wireSignalBindings(ctx, graphNode, instance, headingUpdate(dom, el));\n }\n\n dom.appendChild(parentDom, el);\n return instance;\n }\n\n // Input nodes\n if (graphNode.type === 'input') {\n const el = dom.createElement('input') as HTMLInputElement;\n const inputType = String(graphNode.getProp('inputType') ?? 'text');\n dom.setAttribute(el, 'type', inputType);\n const placeholder = graphNode.getProp('placeholder');\n if (placeholder !== undefined) dom.setAttribute(el, 'placeholder', String(placeholder));\n const value = graphNode.getProp('value');\n if (value !== undefined) dom.setProperty(el, 'value', String(value));\n applyNodeProps(ctx, graphNode, el);\n\n const instance = new NodeInstance(graphNode, el);\n ctx.instances.set(graphNode.id, instance);\n wireEvents(dom, graph, graphNode, el, instance);\n\n if (graphNode.stateRefs.length !== 0) {\n wireSignalBindings(ctx, graphNode, instance, inputUpdate(dom, el));\n }\n\n dom.appendChild(parentDom, el);\n return instance;\n }\n\n // Image nodes\n if (graphNode.type === 'image') {\n const el = dom.createElement('img') as HTMLImageElement;\n const src = graphNode.getProp('src');\n const alt = graphNode.getProp('alt');\n if (src !== undefined) dom.setAttribute(el, 'src', String(src));\n if (alt !== undefined) dom.setAttribute(el, 'alt', String(alt));\n const width = graphNode.getProp('width');\n const height = graphNode.getProp('height');\n if (width !== undefined) dom.setAttribute(el, 'width', String(width));\n if (height !== undefined) dom.setAttribute(el, 'height', String(height));\n applyNodeProps(ctx, graphNode, el);\n\n const instance = new NodeInstance(graphNode, el);\n ctx.instances.set(graphNode.id, instance);\n dom.appendChild(parentDom, el);\n return instance;\n }\n\n // Link nodes\n if (graphNode.type === 'link') {\n const el = dom.createElement('a') as HTMLAnchorElement;\n const href = graphNode.getProp('href');\n const label = graphNode.getProp('label');\n const external = graphNode.getProp('external');\n if (href !== undefined) dom.setAttribute(el, 'href', String(href));\n if (label !== undefined) dom.setTextContent(el, String(label));\n if (external === true) {\n dom.setAttribute(el, 'target', '_blank');\n dom.setAttribute(el, 'rel', 'noopener noreferrer');\n }\n applyNodeProps(ctx, graphNode, el);\n\n const instance = new NodeInstance(graphNode, el);\n ctx.instances.set(graphNode.id, instance);\n wireEvents(dom, graph, graphNode, el, instance);\n dom.appendChild(parentDom, el);\n return instance;\n }\n\n // Button nodes\n if (graphNode.type === 'button') {\n const el = dom.createElement('button') as HTMLButtonElement;\n const label = graphNode.getProp('label');\n if (label !== undefined) dom.setTextContent(el, String(label));\n const disabled = graphNode.getProp('disabled');\n if (disabled === true) dom.setAttribute(el, 'disabled', '');\n applyNodeProps(ctx, graphNode, el);\n\n const instance = new NodeInstance(graphNode, el);\n ctx.instances.set(graphNode.id, instance);\n wireEvents(dom, graph, graphNode, el, instance);\n\n if (graphNode.stateRefs.length !== 0) {\n wireSignalBindings(ctx, graphNode, instance, buttonUpdate(dom, el));\n }\n\n dom.appendChild(parentDom, el);\n return instance;\n }\n\n // Reactive list / conditional — a container whose children are driven by a\n // Signal. Initial child subtrees are already built into the graph by the DSL;\n // on signal change we reconcile the freshly-built desired children against the\n // live DOM using the keyed reconciler (no virtual DOM). A `conditional` uses\n // the identical machinery but renders as a neutral <div> holding 0..1 branch.\n if (graphNode.type === 'reactive-list' || graphNode.type === 'conditional') {\n const tag = resolveTag(graphNode.type);\n const el = dom.createElement(tag);\n applyNodeProps(ctx, graphNode, el);\n\n const instance = new NodeInstance(graphNode, el);\n ctx.instances.set(graphNode.id, instance);\n\n for (const child of graphNode.children) {\n const childInstance = mountNode(ctx, child, el);\n instance.addChild(childInstance);\n }\n\n dom.appendChild(parentDom, el);\n wireReactiveList(ctx, graphNode, instance, el);\n return instance;\n }\n\n // Portal — a container whose children are relocated to a different DOM\n // location (document.body) on the browser, while a neutral inline anchor\n // stays at the declaration site. On the server there is no body, so the\n // children render inline in the anchor (deterministic HTML; hydration then\n // relocates them). This is the substrate for overlays (dialog/popover/…):\n // `wireOverlayBehavior` reads an optional `__overlay__<id>` descriptor and,\n // when present, wires focus trap/restore/containment/escape to the open\n // signal. A plain portal has no descriptor, so overlay wiring is a no-op.\n if (graphNode.type === 'portal') {\n const anchor = dom.createElement(resolveTag('portal'));\n dom.setAttribute(anchor, 'data-streetui-portal', '');\n applyNodeProps(ctx, graphNode, anchor);\n const instance = new NodeInstance(graphNode, anchor);\n ctx.instances.set(graphNode.id, instance);\n\n const body = dom.body();\n let target: Element = anchor; // SSR / no body → render inline in the anchor\n if (body !== null) {\n const portalContainer = dom.createElement('div');\n dom.setAttribute(portalContainer, 'data-streetui-portal-container', '');\n dom.appendChild(body, portalContainer);\n instance.trackCleanup(() => dom.removeChild(body, portalContainer));\n target = portalContainer;\n }\n\n for (const child of graphNode.children) {\n instance.addChild(mountNode(ctx, child, target));\n }\n\n dom.appendChild(parentDom, anchor);\n wireOverlayBehavior(ctx, graphNode, instance, target);\n return instance;\n }\n\n // Container / section / page / form / list / list-item — structural nodes\n const tag = resolveTag(graphNode.type);\n const el = dom.createElement(tag);\n applyNodeProps(ctx, graphNode, el);\n\n // Surface a reactive-list item's stable, identity-only reconciliation key as a\n // public `data-streetui-key` attribute (e.g. \"id:1\"). This exposes only the\n // identity part — never the internal `_sig` value signature, signal ids or\n // graph node ids — so a row is directly selectable and its identity is\n // inspectable across reorders and in-place data updates.\n if (graphNode.type === 'list-item') {\n const itemKey = graphNode.getProp('key');\n if (itemKey !== undefined) {\n dom.setAttribute(el, 'data-streetui-key', String(itemKey));\n }\n }\n\n const instance = new NodeInstance(graphNode, el);\n ctx.instances.set(graphNode.id, instance);\n\n // wire form submit (reuse the live instance rather than a throwaway)\n if (graphNode.type === 'form') {\n wireEvents(dom, graph, graphNode, el, instance);\n }\n\n // Recurse into children\n for (const child of graphNode.children) {\n const childInstance = mountNode(ctx, child, el);\n instance.addChild(childInstance);\n }\n\n dom.appendChild(parentDom, el);\n return instance;\n}\n\n// ── Helpers ───────────────────────────────────────────────────────────────────\n\n/**\n * Per-node-type reactive-binding factories. Each returns the `onUpdate`\n * callback that `wireSignalBindings` invokes when a bound signal changes.\n * Extracted so both the browser mount path and the hydration path apply the\n * exact same DOM mutation semantics for each prop — no duplicated rendering\n * logic.\n */\nexport function textUpdate(\n dom: DOMAdapter,\n el: Element,\n textNode: Text,\n): (propKey: string, value: unknown) => void {\n return (propKey, value) => {\n if (propKey === 'text') {\n dom.setTextContent(textNode, String(value ?? ''));\n } else {\n applyProp(dom, el, propKey, value);\n }\n };\n}\n\nexport function headingUpdate(\n dom: DOMAdapter,\n el: Element,\n): (propKey: string, value: unknown) => void {\n return (propKey, value) => {\n if (propKey === 'text') {\n dom.setTextContent(el, String(value ?? ''));\n } else {\n applyProp(dom, el, propKey, value);\n }\n };\n}\n\nexport function inputUpdate(\n dom: DOMAdapter,\n el: Element,\n): (propKey: string, value: unknown) => void {\n return (propKey, value) => {\n if (propKey === 'value') {\n dom.setProperty(el, 'value', String(value ?? ''));\n } else {\n applyProp(dom, el, propKey, value);\n }\n };\n}\n\nexport function buttonUpdate(\n dom: DOMAdapter,\n el: Element,\n): (propKey: string, value: unknown) => void {\n return (propKey, value) => {\n if (propKey === 'label') {\n dom.setTextContent(el, String(value ?? ''));\n } else if (propKey === 'disabled') {\n if (value === true) {\n dom.setAttribute(el, 'disabled', '');\n } else {\n dom.removeAttribute(el, 'disabled');\n }\n } else {\n applyProp(dom, el, propKey, value);\n }\n };\n}\n\nexport function applyNodeProps(ctx: RenderContext, graphNode: GraphNode, el: Element): void {\n // Iterate own enumerable keys directly rather than via Object.entries, which\n // allocates a wrapper array plus one [key,value] tuple per prop — measurable\n // GC pressure when multiplied across every node in a large initial render.\n const props = graphNode.props;\n for (const key in props) {\n if (!Object.hasOwn(props, key)) continue;\n if (SKIP_PROP_KEYS.has(key)) continue;\n applyProp(ctx.dom, el, key, props[key]);\n }\n}\n\nexport function wireSignalBindings(\n ctx: RenderContext,\n graphNode: GraphNode,\n instance: NodeInstance,\n onUpdate: (propKey: string, value: unknown) => void,\n): void {\n // Fast exit for the common non-reactive node — avoids allocating a for-of\n // iterator over an empty stateRefs array on every static node.\n if (graphNode.stateRefs.length === 0) return;\n for (const stateRef of graphNode.stateRefs) {\n const signalKey = `__signal__${stateRef.signalId}`;\n const maybeSig = ctx.graph.getHandler(signalKey) as\n | { subscribe: (fn: (v: unknown) => void) => () => void; peek: () => unknown }\n | undefined;\n if (maybeSig === undefined || typeof maybeSig.subscribe !== 'function') continue;\n\n // Subscribe directly — avoids the ReadonlySignal<T> generic variance issue\n const unsub = maybeSig.subscribe((value) => {\n onUpdate(stateRef.propKey, value);\n });\n instance.trackCleanup(unsub);\n }\n}\n\n// ── Reactive list wiring ────────────────────────────────────────────────────────\n\ntype ListBuildFn = (items: unknown) => GraphNode[];\ntype ListPlanFn = (items: unknown) => PlanEntry[];\n\n/**\n * Subscribe a reactive-list instance to its driving signal. On each change the\n * DSL-registered plan factory produces lightweight per-row descriptors, which\n * are reconciled against the live DOM with the keyed, minimal-move reconciler\n * (spec §15). A `conditional` node has no plan handler and falls back to the\n * eager build factory (it only ever renders 0..1 branch, so eager is fine).\n */\nexport function wireReactiveList(\n ctx: RenderContext,\n graphNode: GraphNode,\n instance: NodeInstance,\n el: Element,\n): void {\n const plan = ctx.graph.getHandler(`__listplan__${graphNode.id}`) as\n | ListPlanFn\n | undefined;\n const build = ctx.graph.getHandler(`__listbuild__${graphNode.id}`) as\n | ListBuildFn\n | undefined;\n if (plan === undefined && build === undefined) return;\n\n for (const stateRef of graphNode.stateRefs) {\n if (stateRef.propKey !== 'items') continue;\n const sig = ctx.graph.getHandler(`__signal__${stateRef.signalId}`) as\n | { subscribe: (fn: (v: unknown) => void) => () => void }\n | undefined;\n if (sig === undefined || typeof sig.subscribe !== 'function') continue;\n\n const unsub = sig.subscribe((value) => {\n if (plan !== undefined) {\n reconcileReactiveListByPlan(ctx, graphNode, instance, el, plan(value));\n } else {\n reconcileReactiveList(ctx, graphNode, instance, el, build!(value));\n }\n });\n instance.trackCleanup(unsub);\n }\n}\n\nfunction reconcileReactiveListByPlan(\n ctx: RenderContext,\n listNode: GraphNode,\n listInstance: NodeInstance,\n listEl: Element,\n plan: PlanEntry[],\n): void {\n const oldInstances = [...listInstance.children];\n const result = reconcileChildrenByPlan(\n ctx,\n listEl,\n oldInstances,\n plan,\n (node, parent) => mountNode(ctx, node, parent),\n );\n\n // Sync the live instance's children to the reconciled order.\n listInstance.children.length = 0;\n for (const inst of result.instances) listInstance.children.push(inst);\n\n // Forget removed instances, and drop their graph nodes.\n for (const removed of result.removed) {\n forgetInstance(ctx, removed);\n ctx.graph.detachNode(removed.graphNode);\n }\n // Detach any freshly-built subtree that was not adopted as a live instance\n // (e.g. the top node of a rebuilt changed row, whose live instance keeps its\n // original graph node).\n const adopted = new Set(result.instances.map((i) => i.graphNode));\n for (const node of result.built ?? []) {\n if (!adopted.has(node)) ctx.graph.detachNode(node);\n }\n\n // Keep the graph model consistent: list node children match the new order.\n for (const child of [...listNode.children]) listNode.removeChild(child);\n for (const inst of result.instances) listNode.appendChild(inst.graphNode);\n}\n\nfunction reconcileReactiveList(\n ctx: RenderContext,\n listNode: GraphNode,\n listInstance: NodeInstance,\n listEl: Element,\n newNodes: GraphNode[],\n): void {\n const oldInstances = [...listInstance.children];\n const result = reconcileChildren(\n ctx,\n listEl,\n oldInstances,\n newNodes,\n (node, parent) => mountNode(ctx, node, parent),\n );\n\n // Sync the live instance's children to the reconciled order.\n listInstance.children.length = 0;\n for (const inst of result.instances) listInstance.children.push(inst);\n\n // Forget removed instances from the renderer index, and drop their graph\n // nodes (and any un-adopted freshly-built duplicates) from the graph index.\n for (const removed of result.removed) {\n forgetInstance(ctx, removed);\n ctx.graph.detachNode(removed.graphNode);\n }\n const adopted = new Set(result.instances.map((i) => i.graphNode));\n for (const built of newNodes) {\n if (!adopted.has(built)) ctx.graph.detachNode(built);\n }\n\n // Keep the graph model consistent: list node children match the new order.\n for (const child of [...listNode.children]) listNode.removeChild(child);\n for (const inst of result.instances) listNode.appendChild(inst.graphNode);\n}\n\n/** Recursively remove an instance subtree from the renderer's instance index. */\nfunction forgetInstance(ctx: RenderContext, instance: NodeInstance): void {\n ctx.instances.delete(instance.graphNode.id);\n for (const child of instance.children) forgetInstance(ctx, child);\n}\n\n// ── Overlay behavior wiring ─────────────────────────────────────────────────────\n\n/**\n * Opaque overlay descriptor, read from the `__overlay__<portalId>` handler that\n * the DSL registers for dialog/popover/tooltip/dropdown/toast. Declared here as\n * a local structural type (mirroring the list plan/build handler pattern) so the\n * renderer never takes a compile-time dependency on the DSL package.\n */\ninterface OverlayBehavior {\n /** Reactive open/visibility state — the same signal that drives the panel's `when()`. */\n readonly open: {\n subscribe: (fn: (v: boolean) => void) => () => void;\n peek: () => unknown;\n };\n /** Trap Tab focus within, and redirect escaped focus back inside (modal semantics). */\n readonly modal: boolean;\n /** Move focus into the panel when it opens. */\n readonly takesFocus: boolean;\n /** Escape key invokes `onClose`. */\n readonly closeOnEscape: boolean;\n /** Restore focus to the pre-open element on close. */\n readonly restoreFocus: boolean;\n /** id of the element to focus first when opening. */\n readonly initialFocusId?: string;\n /** Requested-close callback (Escape). The app flips its own open signal here. */\n readonly onClose?: () => void;\n}\n\n/**\n * Attach overlay focus/keyboard behavior to a mounted portal. Server-safe: on\n * the server `dom.body()` is null so this returns immediately (SSR emits inert\n * markup, no focus concept). A plain portal has no `__overlay__` descriptor, so\n * this also returns immediately — the behavior is purely additive.\n *\n * The panel is mounted/unmounted by the portal's inner `when(open, …)`, whose\n * signal subscription is registered *before* this one (the conditional child is\n * mounted earlier in the portal branch). Signal subscribers fire synchronously\n * in subscription order, so on open→true the panel DOM exists before we move\n * focus into it, and on open→false the panel is torn down before we restore\n * focus. All listeners are tracked on the instance and torn down on unmount.\n */\nexport function wireOverlayBehavior(\n ctx: RenderContext,\n graphNode: GraphNode,\n instance: NodeInstance,\n target: Element,\n): void {\n const { dom, graph } = ctx;\n if (dom.body() === null) return; // server / no DOM environment\n\n const descFn = graph.getHandler(`__overlay__${graphNode.id}`) as\n | (() => OverlayBehavior)\n | undefined;\n if (descFn === undefined) return; // plain portal — no overlay behavior\n\n const desc = descFn();\n const openSig = desc.open;\n if (openSig === undefined || typeof openSig.subscribe !== 'function') return;\n\n let active: Array<() => void> = [];\n let saved: Element | null = null;\n\n const teardown = (): void => {\n for (const fn of active) fn();\n active = [];\n };\n\n const onOpenChange = (isOpen: boolean): void => {\n if (isOpen) {\n if (desc.restoreFocus) saved = saveFocus(dom);\n if (desc.takesFocus) focusInitial(dom, target, desc.initialFocusId);\n if (desc.modal) {\n active.push(trapFocus(dom, target));\n active.push(containFocus(dom, target));\n }\n if (desc.closeOnEscape && desc.onClose !== undefined) {\n active.push(onEscape(dom, target, desc.onClose));\n }\n } else {\n teardown();\n if (desc.restoreFocus && saved !== null) {\n restoreFocus(dom, saved);\n saved = null;\n }\n }\n };\n\n const unsub = openSig.subscribe(onOpenChange);\n instance.trackCleanup(unsub);\n instance.trackCleanup(teardown);\n\n // `subscribe` fires only on change; an overlay that is open on initial mount\n // has its panel already built into the graph, so run the open path now.\n if (openSig.peek() === true) onOpenChange(true);\n}\n","/**\n * Maps semantic node types to HTML tag names.\n */\n\nimport type { SemanticNodeType } from '@streetui/core';\n\nconst TAG_MAP: Partial<Record<SemanticNodeType, string>> = {\n application: 'div',\n page: 'div',\n section: 'section',\n container: 'div',\n heading: 'h1',\n text: 'span',\n button: 'button',\n input: 'input',\n form: 'form',\n list: 'ul',\n 'list-item': 'li',\n image: 'img',\n link: 'a',\n component: 'div',\n slot: 'div',\n fragment: 'div',\n 'reactive-list': 'ul',\n // A portal renders as a neutral inline anchor <div> at its declaration site;\n // its children are relocated to a document.body container on the browser\n // (see the portal branch in mount.ts). On the server (no body) it renders\n // inline, so the anchor tag is what SSR/hydration positionally match on.\n portal: 'div',\n};\n\nexport function resolveTag(type: SemanticNodeType): string {\n return TAG_MAP[type] ?? 'div';\n}\n","/**\n * Patch — targeted DOM updates driven by signal changes.\n *\n * When a signal fires, we look up the NodeInstance and apply\n * only the changed prop — no full re-render, no tree diffing.\n */\n\nimport type { RenderContext } from './render-context.js';\nimport type { GraphNode } from '@streetui/graph';\nimport { applyProp, patchProp } from './attributes.js';\n\nexport function patchNode(\n ctx: RenderContext,\n graphNode: GraphNode,\n propKey: string,\n newValue: unknown,\n): void {\n const instance = ctx.instances.get(graphNode.id);\n if (instance === undefined) return;\n\n const domNode = instance.domNode;\n if (!ctx.dom.isElement(domNode)) return;\n\n const oldValue = graphNode.getProp(propKey);\n\n switch (propKey) {\n case 'text':\n if (!Object.is(oldValue, newValue)) {\n ctx.dom.setTextContent(domNode, String(newValue ?? ''));\n graphNode.setProp('text', String(newValue ?? ''));\n }\n break;\n case 'label':\n if (!Object.is(oldValue, newValue)) {\n ctx.dom.setTextContent(domNode, String(newValue ?? ''));\n graphNode.setProp('label', String(newValue ?? ''));\n }\n break;\n case 'disabled':\n if (newValue === true) {\n ctx.dom.setAttribute(domNode, 'disabled', '');\n } else {\n ctx.dom.removeAttribute(domNode, 'disabled');\n }\n graphNode.setProp('disabled', Boolean(newValue));\n break;\n case 'value':\n if (!Object.is(oldValue, newValue)) {\n ctx.dom.setProperty(domNode, 'value', String(newValue ?? ''));\n graphNode.setProp('value', String(newValue ?? ''));\n }\n break;\n default:\n patchProp(ctx.dom, domNode, propKey, oldValue, newValue);\n graphNode.setProp(propKey, newValue as string);\n break;\n }\n}\n","/**\n * Reconciliation — diff-based child list updates.\n *\n * When the children of a node change (e.g. a list driven by state),\n * this reconciler:\n * 1. Matches old instances to new graph nodes by key\n * 2. Reuses matched instances (updates their props)\n * 3. Applies a targeted content update to a reused item whose data changed\n * 4. Creates new instances for additions\n * 5. Removes stale instances (and prunes their handler registrations)\n * 6. Moves DOM nodes to match new order\n *\n * This is keyed reconciliation over the semantic graph — there is no virtual\n * DOM. A reused item keeps its own DOM element; only its changed content is\n * updated in place (falling back to remounting a subtree only where its shape\n * actually changed).\n */\n\nimport type { RenderContext } from './render-context.js';\nimport type { GraphNode } from '@streetui/graph';\nimport type { NodeInstance } from './node-instance.js';\nimport { patchNode } from './patch.js';\n\nexport type MountFn = (node: GraphNode, parent: Element) => NodeInstance;\n\nexport interface ReconcileResult {\n /** Instances in the new order. */\n instances: NodeInstance[];\n /** Instances that were removed and must be disposed. */\n removed: NodeInstance[];\n /**\n * GraphNodes freshly materialised during this reconcile (new rows + rebuilt\n * changed rows). The caller detaches any of these that were not adopted as a\n * live instance's graph node, so no orphan subtree lingers in the graph index.\n */\n built?: GraphNode[];\n}\n\n/**\n * A lazy reconciliation descriptor for one reactive-list row (mirrors the DSL's\n * `ListPlanEntry`). `sig()` and `build()` are only invoked for rows that are\n * genuinely new or whose source reference changed — the whole point of the\n * plan path (spec §15).\n */\nexport interface PlanEntry {\n readonly key: string;\n readonly item: unknown;\n readonly sig: () => string;\n readonly build: () => GraphNode;\n}\n\n/**\n * Reconcile children of a container element against a new list of graph nodes.\n *\n * @param ctx Render context\n * @param parentDom The DOM parent element\n * @param oldInstances Current child instances (in order)\n * @param newNodes New graph children (in desired order)\n * @param mountFn Factory to create a new NodeInstance for a graph node\n */\nexport function reconcileChildren(\n ctx: RenderContext,\n parentDom: Element,\n oldInstances: NodeInstance[],\n newNodes: readonly GraphNode[],\n mountFn: MountFn,\n): ReconcileResult {\n // Build key → old instance map\n const oldByKey = new Map<string, NodeInstance>();\n for (const inst of oldInstances) {\n const key = inst.graphNode.key ?? inst.graphNode.id;\n oldByKey.set(key, inst);\n }\n\n const newInstances: NodeInstance[] = [];\n const usedKeys = new Set<string>();\n\n for (const newNode of newNodes) {\n const key = newNode.key ?? newNode.id;\n const existing = oldByKey.get(key);\n\n if (existing !== undefined) {\n // Reuse — identity is stable, so the DOM element is preserved.\n usedKeys.add(key);\n const oldSig = existing.graphNode.getProp('_sig');\n const newSig = newNode.getProp('_sig');\n patchExistingInstance(ctx, existing, newNode);\n // Data changed but identity did not → targeted content update in place.\n if (!Object.is(oldSig, newSig)) {\n reconcileItemChildren(ctx, existing, newNode, mountFn);\n }\n newInstances.push(existing);\n } else {\n // New — create and mount\n const inst = mountFn(newNode, parentDom);\n newInstances.push(inst);\n }\n }\n\n // Determine removed instances\n const removed: NodeInstance[] = [];\n for (const inst of oldInstances) {\n const key = inst.graphNode.key ?? inst.graphNode.id;\n if (!usedKeys.has(key)) {\n removed.push(inst);\n }\n }\n\n // Remove stale DOM nodes\n for (const inst of removed) {\n const parent = ctx.dom.parentNode(inst.domNode);\n if (parent !== null) {\n ctx.dom.removeChild(parent, inst.domNode);\n }\n inst.dispose();\n }\n\n // Reorder DOM nodes to match new order\n reorderDom(ctx, parentDom, newInstances);\n\n return { instances: newInstances, removed };\n}\n\n/**\n * Plan-based keyed reconciliation (spec §15 — the optimised reactive-list path).\n *\n * Identical observable result to {@link reconcileChildren}, but driven by lazy\n * {@link PlanEntry} descriptors instead of a pre-built array of GraphNodes:\n *\n * - a reused row whose `item` reference is unchanged does **zero** work — no\n * signature hash, no subtree build, no prop patch (the common case for\n * append / prepend / remove / reorder / reverse, where existing item objects\n * keep their identity);\n * - a reused row whose reference changed hashes lazily and, only on a real\n * signature change, materialises a fresh subtree for a targeted in-place\n * content update;\n * - a genuinely new key builds + mounts exactly one subtree.\n *\n * DOM reordering uses a longest-increasing-subsequence pass so the number of\n * moves is minimal (e.g. a prepend into a 10k list moves 1 node, not 10k).\n */\nexport function reconcileChildrenByPlan(\n ctx: RenderContext,\n parentDom: Element,\n oldInstances: NodeInstance[],\n plan: readonly PlanEntry[],\n mountFn: MountFn,\n): ReconcileResult {\n const oldByKey = new Map<string, NodeInstance>();\n for (const inst of oldInstances) {\n oldByKey.set(inst.graphNode.key ?? inst.graphNode.id, inst);\n }\n\n const newInstances: NodeInstance[] = [];\n const usedKeys = new Set<string>();\n const built: GraphNode[] = [];\n\n for (const entry of plan) {\n const existing = oldByKey.get(entry.key);\n if (existing !== undefined) {\n usedKeys.add(entry.key);\n const oldItem = existing.graphNode.getProp('_item');\n // Identity short-circuit: same reference ⇒ data cannot have changed.\n if (!Object.is(oldItem, entry.item)) {\n const newSig = entry.sig();\n const oldSig = existing.graphNode.getProp('_sig');\n if (!Object.is(oldSig, newSig)) {\n const freshNode = entry.build();\n built.push(freshNode);\n patchExistingInstance(ctx, existing, freshNode);\n reconcileItemChildren(ctx, existing, freshNode, mountFn);\n existing.graphNode.setProp('_sig', newSig);\n }\n // Cache the new reference so the next pass can short-circuit again.\n existing.graphNode.setProp('_item', entry.item as never);\n }\n newInstances.push(existing);\n } else {\n const freshNode = entry.build();\n built.push(freshNode);\n const inst = mountFn(freshNode, parentDom);\n newInstances.push(inst);\n }\n }\n\n // Determine + remove stale instances.\n const removed: NodeInstance[] = [];\n for (const inst of oldInstances) {\n const key = inst.graphNode.key ?? inst.graphNode.id;\n if (!usedKeys.has(key)) removed.push(inst);\n }\n for (const inst of removed) {\n const parent = ctx.dom.parentNode(inst.domNode);\n if (parent !== null) ctx.dom.removeChild(parent, inst.domNode);\n inst.dispose();\n }\n\n // Minimal-move reorder to the desired order.\n reorderDomMinimal(ctx, parentDom, oldInstances, newInstances);\n\n return { instances: newInstances, removed, built };\n}\n\n/**\n * Minimal-move DOM reorder.\n *\n * Reused nodes retain their previous DOM slots and newly-mounted nodes sit at\n * the end. We compute the longest increasing subsequence of the reused nodes'\n * previous positions; those are already in correct relative order and stay put.\n * Every other node is inserted before its right-hand neighbour, walking\n * right-to-left. This yields exactly (n − |LIS|) `insertBefore` calls — the\n * minimum — instead of the O(n) sweep the naive reorder performs on a prepend.\n */\nfunction reorderDomMinimal(\n ctx: RenderContext,\n parentDom: Element,\n oldInstances: NodeInstance[],\n newInstances: NodeInstance[],\n): void {\n const n = newInstances.length;\n if (n === 0) return;\n\n const oldIndexOf = new Map<NodeInstance, number>();\n for (let i = 0; i < oldInstances.length; i++) oldIndexOf.set(oldInstances[i]!, i);\n\n const source = new Array<number>(n);\n let moved = false;\n let lastSeen = -1;\n for (let i = 0; i < n; i++) {\n const oi = oldIndexOf.get(newInstances[i]!);\n if (oi === undefined) {\n source[i] = -1; // freshly mounted row\n moved = true;\n } else {\n source[i] = oi;\n if (oi < lastSeen) moved = true; // an out-of-order reused row exists\n else lastSeen = oi;\n }\n }\n\n // Fast path: nothing is out of order and there are no new rows to reposition.\n if (!moved) return;\n\n const keep = longestIncreasingSubsequence(source);\n\n let refNode: Node | null = null;\n for (let i = n - 1; i >= 0; i--) {\n const domNode = newInstances[i]!.domNode;\n if (source[i] === -1 || !keep.has(i)) {\n if (ctx.dom.nextSibling(domNode) !== refNode) {\n ctx.dom.insertBefore(parentDom, domNode, refNode);\n }\n }\n refNode = domNode;\n }\n}\n\n/**\n * Indices (into `source`) forming a longest strictly-increasing subsequence,\n * ignoring `-1` entries (new rows, which always move). O(n log n) with\n * predecessor reconstruction.\n */\nfunction longestIncreasingSubsequence(source: readonly number[]): Set<number> {\n const keep = new Set<number>();\n const n = source.length;\n const tails: number[] = []; // tails[k] = source-index of smallest tail of an LIS of length k+1\n const prev = new Array<number>(n).fill(-1);\n\n for (let i = 0; i < n; i++) {\n const v = source[i]!;\n if (v < 0) continue;\n let lo = 0;\n let hi = tails.length;\n while (lo < hi) {\n const mid = (lo + hi) >> 1;\n if (source[tails[mid]!]! < v) lo = mid + 1;\n else hi = mid;\n }\n if (lo > 0) prev[i] = tails[lo - 1]!;\n tails[lo] = i;\n }\n\n let idx = tails.length > 0 ? tails[tails.length - 1]! : -1;\n while (idx >= 0) {\n keep.add(idx);\n idx = prev[idx]!;\n }\n return keep;\n}\n\n/**\n * Targeted in-place content update for a reused list item whose data changed.\n *\n * The item's DOM element is kept; only its contents are updated. Children are\n * matched positionally against the freshly-built subtree:\n * - same node type at a position → the existing child is reused and its props\n * are patched in place (e.g. a text node's text is rewritten), then we\n * recurse into its children;\n * - different type / new position → the fresh child node is reparented onto the\n * live item node and mounted;\n * - surplus old children → disposed, with DOM, subscriptions, listeners and\n * handler registrations all torn down.\n *\n * This deliberately reuses the same keyed/positional strategy rather than a\n * virtual DOM, and never destroys the item element itself.\n */\nfunction reconcileItemChildren(\n ctx: RenderContext,\n itemInstance: NodeInstance,\n newItemNode: GraphNode,\n mountFn: MountFn,\n): void {\n const el = itemInstance.domNode;\n if (!ctx.dom.isElement(el)) return;\n\n const oldChildren = [...itemInstance.children];\n const newChildNodes = [...newItemNode.children];\n const nextChildren: NodeInstance[] = [];\n const kept = new Set<NodeInstance>();\n\n for (let i = 0; i < newChildNodes.length; i++) {\n const newChild = newChildNodes[i]!;\n const oldChild = oldChildren[i];\n\n if (oldChild !== undefined && oldChild.graphNode.type === newChild.type) {\n // Reuse in place — patch this node's props and recurse into descendants.\n patchExistingInstance(ctx, oldChild, newChild);\n reconcileItemChildren(ctx, oldChild, newChild, mountFn);\n nextChildren.push(oldChild);\n kept.add(oldChild);\n } else {\n // Structural change at this position — mount the fresh child. Reparent it\n // out of the freshly-built subtree so the wholesale detach of the\n // unadopted item node (in mount.ts) does not remove this now-live node.\n itemInstance.graphNode.appendChild(newChild);\n const inst = mountFn(newChild, el);\n nextChildren.push(inst);\n }\n }\n\n // Dispose old children that were not reused (surplus or type-mismatched).\n for (const old of oldChildren) {\n if (kept.has(old)) continue;\n const parent = ctx.dom.parentNode(old.domNode);\n if (parent !== null) ctx.dom.removeChild(parent, old.domNode);\n old.dispose();\n forgetInstanceTree(ctx, old);\n ctx.graph.detachNode(old.graphNode);\n }\n\n // Restore correct DOM order within the item element.\n reorderDom(ctx, el, nextChildren);\n\n // Sync the live instance's children.\n itemInstance.children.length = 0;\n for (const c of nextChildren) itemInstance.children.push(c);\n\n // Keep the graph model's item children consistent with the reconciled order.\n for (const c of [...itemInstance.graphNode.children]) {\n itemInstance.graphNode.removeChild(c);\n }\n for (const c of nextChildren) itemInstance.graphNode.appendChild(c.graphNode);\n}\n\n/** Move a parent's DOM children to match the given instance order (minimal moves). */\nfunction reorderDom(\n ctx: RenderContext,\n parentDom: Element,\n instances: NodeInstance[],\n): void {\n let referenceNode: Node | null = null;\n for (let i = instances.length - 1; i >= 0; i--) {\n const inst = instances[i];\n if (inst === undefined) continue;\n const domNode = inst.domNode;\n const currentNext = ctx.dom.nextSibling(domNode);\n if (currentNext !== referenceNode) {\n ctx.dom.insertBefore(parentDom, domNode, referenceNode);\n }\n referenceNode = domNode;\n }\n}\n\n/** Recursively drop an instance subtree from the renderer's instance index. */\nfunction forgetInstanceTree(ctx: RenderContext, instance: NodeInstance): void {\n ctx.instances.delete(instance.graphNode.id);\n for (const child of instance.children) forgetInstanceTree(ctx, child);\n}\n\nfunction patchExistingInstance(\n ctx: RenderContext,\n instance: NodeInstance,\n newNode: GraphNode,\n): void {\n const oldNode = instance.graphNode;\n for (const [key, newVal] of Object.entries(newNode.props)) {\n const oldVal = oldNode.getProp(key);\n if (!Object.is(oldVal, newVal)) {\n patchNode(ctx, instance.graphNode, key, newVal);\n }\n }\n}\n","/**\n * StreetUI Renderer — framework-owned DOM renderer.\n *\n * No React. No Vue. No virtual-dom. No external rendering library.\n *\n * Pipeline:\n * CompiledApplication\n * → mountGraph (creates all DOM nodes)\n * → signal subscriptions drive patchNode (targeted updates)\n * → flush() propagates any pending scheduler jobs\n * → unmount() disposes everything\n */\n\nimport type { DOMAdapter } from '@streetui/dom';\nimport { BrowserDOMAdapter } from '@streetui/dom';\nimport type { CompiledApplication } from '@streetui/compiler';\nimport type { StreetRenderer, RenderHandle } from '@streetui/runtime';\nimport { createRenderContext } from './render-context.js';\nimport { mountGraph } from './mount.js';\nimport { hydrateGraph } from './hydrate.js';\nimport { StreetRenderHandle } from './render-handle.js';\nimport type { NodeInstance } from './node-instance.js';\nimport type { HydrationDiagnosticSink } from './hydration-diagnostics.js';\n\nexport interface StreetRendererOptions {\n /** Override the DOM adapter (e.g. for testing). Defaults to BrowserDOMAdapter. */\n readonly domAdapter?: DOMAdapter;\n /**\n * Optional dev-only sink that observes hydration mismatch repairs. Attach one\n * to surface server/client divergences during development; leave it unset in\n * production so hydration does no extra work.\n */\n readonly hydrationDiagnostics?: HydrationDiagnosticSink;\n}\n\nexport class StreetRendererImpl implements StreetRenderer {\n private readonly _dom: DOMAdapter;\n private readonly _hydrationDiagnostics?: HydrationDiagnosticSink;\n\n constructor(options: StreetRendererOptions = {}) {\n this._dom = options.domAdapter ?? new BrowserDOMAdapter();\n if (options.hydrationDiagnostics !== undefined) {\n this._hydrationDiagnostics = options.hydrationDiagnostics;\n }\n }\n\n mount(compiled: CompiledApplication, container: Element): RenderHandle {\n const ctx = createRenderContext(this._dom, compiled.graph, container);\n\n // Initial mount — creates the full DOM tree\n const rootInstance = mountGraph(ctx);\n\n // Wire all signal subscriptions so that signal → DOM patches happen automatically\n this._wireSignals(ctx, rootInstance);\n\n return new StreetRenderHandle(ctx, rootInstance);\n }\n\n /**\n * Hydrate a container that already holds server-rendered HTML for this\n * application. Instead of recreating the DOM, it walks the semantic graph\n * against the existing nodes, adopting matching elements and attaching\n * behavior (events + signal subscriptions). Mismatched subtrees are locally\n * replaced. Returns the same handle type as `mount`.\n */\n hydrate(compiled: CompiledApplication, container: Element): RenderHandle {\n const ctx = createRenderContext(\n this._dom,\n compiled.graph,\n container,\n this._hydrationDiagnostics,\n );\n const rootInstance = hydrateGraph(ctx);\n this._wireSignals(ctx, rootInstance);\n return new StreetRenderHandle(ctx, rootInstance);\n }\n\n private _wireSignals(\n ctx: ReturnType<typeof createRenderContext>,\n rootInstance: NodeInstance,\n ): void {\n // Each NodeInstance already wired its own signals in mountNode via wireSignalBindings.\n // This method is a hook for any cross-cutting signal concerns at the renderer level.\n // Currently no-op — individual mount calls handle their own subscriptions.\n void ctx;\n void rootInstance;\n }\n}\n\n/**\n * Create the default StreetUI renderer using the browser's DOM APIs.\n */\nexport function createRenderer(options?: StreetRendererOptions): StreetRendererImpl {\n return new StreetRendererImpl(options);\n}\n","/**\n * Hydration diagnostics — dev-only, opt-in explanations of hydration mismatches.\n *\n * Hydration is self-repairing: when the server-rendered DOM does not match the\n * graph at a position, the renderer mounts a fresh subtree in place and drops\n * the offending element (see `hydrateChildren` in `hydrate.ts`). That recovery\n * is silent by design — a local mismatch must never tear down the whole app.\n *\n * During development, though, a silent repair hides a real problem (usually a\n * server/client divergence). A `HydrationDiagnosticSink` can be attached to the\n * renderer to *observe* those repairs without changing them: for every mismatch\n * the renderer reports what it expected, what it found, where, and what it did\n * to recover. Nothing is thrown, nothing is mutated differently, and when no\n * sink is attached there is zero additional work on the hydration path.\n */\n\n/** What kind of divergence the hydrator encountered at a position. */\nexport type HydrationMismatchType =\n | 'tag-mismatch' // an element existed but was the wrong tag\n | 'missing-element' // the graph expected a child the DOM did not provide\n | 'surplus-element'; // the DOM had a child the graph no longer expects\n\n/** A single, fully-described hydration divergence and the repair taken. */\nexport interface HydrationDiagnostic {\n /** The category of mismatch. */\n readonly type: HydrationMismatchType;\n /** The tag the graph expected at this position (null for a surplus element). */\n readonly expected: string | null;\n /** The tag actually found in the server DOM (null for a missing element). */\n readonly found: string | null;\n /** A human-readable path to the position, e.g. `app / page[0] / section[1]`. */\n readonly path: string;\n /** The graph node id involved, when one exists (null for surplus DOM). */\n readonly nodeId: string | null;\n /** The semantic node type involved, when one exists (null for surplus DOM). */\n readonly nodeType: string | null;\n /** The recovery action the renderer performed. */\n readonly action: string;\n /** A single-line, developer-facing summary of the whole diagnostic. */\n readonly message: string;\n}\n\n/**\n * Receives hydration diagnostics as they are discovered. Kept intentionally\n * tiny so any logger — `console`, a test collector, a `DiagnosticSink` — can\n * satisfy it. Implementations must not throw.\n */\nexport interface HydrationDiagnosticSink {\n report(diagnostic: HydrationDiagnostic): void;\n}\n\n/** Build the canonical one-line message for a diagnostic. */\nexport function formatHydrationDiagnostic(\n d: Omit<HydrationDiagnostic, 'message'>,\n): string {\n const at = ` at ${d.path}`;\n switch (d.type) {\n case 'tag-mismatch':\n return `Hydration mismatch${at} — Expected: ${d.expected} / Found: ${d.found} / Action: ${d.action}`;\n case 'missing-element':\n return `Hydration mismatch${at} — Expected: ${d.expected} / Found: (nothing) / Action: ${d.action}`;\n case 'surplus-element':\n return `Hydration mismatch${at} — Expected: (nothing) / Found: ${d.found} / Action: ${d.action}`;\n }\n}\n\n/**\n * A ready-made sink that accumulates diagnostics into an array — the shape most\n * useful for tests and for a DevTools panel. The returned `diagnostics` array is\n * appended to in-place as repairs happen.\n */\nexport function createHydrationDiagnosticCollector(): {\n readonly sink: HydrationDiagnosticSink;\n readonly diagnostics: HydrationDiagnostic[];\n} {\n const diagnostics: HydrationDiagnostic[] = [];\n return {\n diagnostics,\n sink: {\n report(d) {\n diagnostics.push(d);\n },\n },\n };\n}\n\n/**\n * A sink that forwards each diagnostic to a `console`-like logger as a single\n * warning line. Handy default when you just want the messages surfaced in dev.\n */\nexport function consoleHydrationDiagnosticSink(\n logger: { warn(message: string): void } = console,\n): HydrationDiagnosticSink {\n return {\n report(d) {\n logger.warn(d.message);\n },\n };\n}\n","/**\n * Hydration — attach a live StreetUI runtime to server-rendered HTML.\n *\n * `hydrate` walks the semantic application graph top-down against the DOM that\n * the server already produced. For every graph node it *adopts* the matching\n * existing element (creating a `NodeInstance` that points at it) and attaches\n * behavior — event listeners and signal subscriptions — using the exact same\n * helpers the browser mount path uses (`wireEvents`, `wireSignalBindings`,\n * `wireReactiveList`, and the per-type update factories). Nothing is recreated\n * when the DOM matches.\n *\n * Matching is positional and works because every non-application graph node\n * maps to exactly one element (see mount.ts). When the element at a position\n * does not match the expected tag (or is missing), only that subtree is\n * repaired: the fresh subtree is mounted and spliced into place, leaving the\n * rest of the hydrated tree untouched. A local mismatch never tears down the\n * whole app.\n */\n\nimport type { GraphNode } from '@streetui/graph';\nimport type { RenderContext } from './render-context.js';\nimport { NodeInstance } from './node-instance.js';\nimport { wireEvents } from './events.js';\nimport { resolveTag } from './tag-map.js';\nimport { formatHydrationDiagnostic } from './hydration-diagnostics.js';\nimport {\n mountNode,\n wireSignalBindings,\n wireReactiveList,\n wireOverlayBehavior,\n textUpdate,\n headingUpdate,\n inputUpdate,\n buttonUpdate,\n} from './mount.js';\n\n/** Hydrate the whole application graph against `ctx.container`. */\nexport function hydrateGraph(ctx: RenderContext): NodeInstance {\n const root = ctx.graph.root;\n // The application root maps to the container itself (no element of its own),\n // exactly as in mountNode.\n const instance = new NodeInstance(root, ctx.container);\n ctx.instances.set(root.id, instance);\n hydrateChildren(ctx, root, instance, ctx.container, 'app');\n return instance;\n}\n\n/**\n * Adopt `domNode` as the live element for `graphNode` and attach behavior.\n * The caller has already verified `domNode` matches `graphNode` (right tag).\n * `path` is the human-readable position used only for dev diagnostics.\n */\nfunction hydrateNode(\n ctx: RenderContext,\n graphNode: GraphNode,\n domNode: Element,\n path: string,\n): NodeInstance {\n const { dom, graph } = ctx;\n\n switch (graphNode.type) {\n case 'text': {\n // <span> with an inner text node. Adopt the text node (or create one if\n // the server markup somehow lacks it).\n let textNode = dom.firstChild(domNode);\n if (textNode === null || !dom.isTextNode(textNode)) {\n const created = dom.createTextNode(String(graphNode.getProp('text') ?? ''));\n dom.appendChild(domNode, created);\n textNode = created;\n }\n const instance = new NodeInstance(graphNode, domNode);\n ctx.instances.set(graphNode.id, instance);\n wireEvents(dom, graph, graphNode, domNode, instance);\n // Only build the per-type update closure when the node actually has\n // reactive bindings. wireSignalBindings early-returns on an empty\n // stateRefs list, so for a static node the `textUpdate(...)` closure would\n // be allocated and immediately discarded — pure GC pressure on the hot\n // hydration path, where the vast majority of nodes are static.\n if (graphNode.stateRefs.length !== 0) {\n wireSignalBindings(ctx, graphNode, instance, textUpdate(dom, domNode, textNode as Text));\n }\n return instance;\n }\n\n case 'heading': {\n const instance = new NodeInstance(graphNode, domNode);\n ctx.instances.set(graphNode.id, instance);\n wireEvents(dom, graph, graphNode, domNode, instance);\n if (graphNode.stateRefs.length !== 0) {\n wireSignalBindings(ctx, graphNode, instance, headingUpdate(dom, domNode));\n }\n return instance;\n }\n\n case 'input': {\n const instance = new NodeInstance(graphNode, domNode);\n ctx.instances.set(graphNode.id, instance);\n // The controlled value is already present in the server HTML (reflected as\n // the `value` attribute). Re-assert it as a live property so the element's\n // current value matches the bound signal exactly.\n const value = graphNode.getProp('value');\n if (value !== undefined) dom.setProperty(domNode, 'value', String(value));\n wireEvents(dom, graph, graphNode, domNode, instance);\n if (graphNode.stateRefs.length !== 0) {\n wireSignalBindings(ctx, graphNode, instance, inputUpdate(dom, domNode));\n }\n return instance;\n }\n\n case 'button': {\n const instance = new NodeInstance(graphNode, domNode);\n ctx.instances.set(graphNode.id, instance);\n wireEvents(dom, graph, graphNode, domNode, instance);\n if (graphNode.stateRefs.length !== 0) {\n wireSignalBindings(ctx, graphNode, instance, buttonUpdate(dom, domNode));\n }\n return instance;\n }\n\n case 'image':\n case 'link': {\n // Leaf elements with no reactive bindings or events beyond what the markup\n // already encodes; links may still carry click handlers.\n const instance = new NodeInstance(graphNode, domNode);\n ctx.instances.set(graphNode.id, instance);\n if (graphNode.type === 'link') wireEvents(dom, graph, graphNode, domNode, instance);\n return instance;\n }\n\n case 'reactive-list':\n case 'conditional': {\n // The server rendered the initial children (built into the graph at\n // compile time from the initial signal state). Adopt them positionally,\n // then subscribe for future signal changes — the same keyed reconciler as\n // the browser drives subsequent updates against the adopted instances.\n const instance = new NodeInstance(graphNode, domNode);\n ctx.instances.set(graphNode.id, instance);\n hydrateChildren(ctx, graphNode, instance, domNode, path);\n wireReactiveList(ctx, graphNode, instance, domNode);\n return instance;\n }\n\n case 'portal': {\n // The server rendered the portal's children INLINE inside the anchor\n // (no body on the server). Adopt the anchor, then — before positional\n // child hydration — relocate those inline children into a fresh\n // document.body container so their live location matches the browser\n // mount path exactly (and there is no positional mismatch). Hydrate the\n // children against the body container, then wire any overlay behavior.\n const instance = new NodeInstance(graphNode, domNode);\n ctx.instances.set(graphNode.id, instance);\n const body = dom.body();\n let target: Element = domNode;\n if (body !== null) {\n const portalContainer = dom.createElement('div');\n dom.setAttribute(portalContainer, 'data-streetui-portal-container', '');\n // `childNodes` returns a snapshot array, so moving during iteration is\n // safe. appendChild re-parents each node out of the anchor.\n for (const child of dom.childNodes(domNode)) {\n dom.appendChild(portalContainer, child);\n }\n dom.appendChild(body, portalContainer);\n instance.trackCleanup(() => dom.removeChild(body, portalContainer));\n target = portalContainer;\n }\n hydrateChildren(ctx, graphNode, instance, target, path);\n wireOverlayBehavior(ctx, graphNode, instance, target);\n return instance;\n }\n\n default: {\n // Structural nodes: container / section / page / form / list / list-item.\n const instance = new NodeInstance(graphNode, domNode);\n ctx.instances.set(graphNode.id, instance);\n if (graphNode.type === 'form') {\n wireEvents(dom, graph, graphNode, domNode, instance);\n }\n // Hydration boundary (a \"slot\" such as the router outlet): adopt the\n // element itself but leave its existing children untouched — neither\n // hydrated by this pass nor removed as surplus. Something else (e.g. the\n // router) owns and will hydrate the content already inside it. Without\n // this, an empty-in-the-graph slot would strip the server-rendered\n // content it is meant to preserve.\n if (graphNode.getProp('_hydrationBoundary') === true) {\n return instance;\n }\n hydrateChildren(ctx, graphNode, instance, domNode, path);\n return instance;\n }\n }\n}\n\n// ── Child matching + local mismatch recovery ───────────────────────────────────\n\n/**\n * Positionally match a parent's expected child graph nodes against the actual\n * child *elements* in the DOM. Matching children are hydrated in place; a\n * mismatch (wrong tag or a missing element) triggers a local repair — the fresh\n * subtree is mounted and spliced into the correct position — without disturbing\n * sibling subtrees. Surplus DOM elements are removed.\n */\nfunction hydrateChildren(\n ctx: RenderContext,\n parentGraphNode: GraphNode,\n parentInstance: NodeInstance,\n parentDom: Element,\n parentPath: string,\n): void {\n const expected = parentGraphNode.children;\n const actual = elementChildren(ctx, parentDom);\n let cursor = 0;\n\n // The human-readable `path` is only ever consumed by hydration diagnostics,\n // which are inert unless a sink is attached. Building the\n // `${parentPath} / ${type}[${i}]` string for every child would allocate one\n // throwaway string per node on the hot path (10k+ on a large tree) for output\n // that is discarded in production. Gate the construction on the sink being\n // present; when it is absent, thread the (meaningless-but-unused) parent path\n // through unchanged so nested calls stay allocation-free too.\n const diag = ctx.hydrationDiagnostics !== undefined;\n\n for (let i = 0; i < expected.length; i++) {\n const childNode = expected[i]!;\n const want = expectedTag(ctx, childNode);\n const childPath = diag ? `${parentPath} / ${childNode.type}[${i}]` : parentPath;\n const actualEl = actual[cursor];\n\n if (\n actualEl !== undefined &&\n ctx.dom.isElement(actualEl) &&\n ctx.dom.tagName(actualEl) === want\n ) {\n // Match — adopt the existing element.\n const inst = hydrateNode(ctx, childNode, actualEl, childPath);\n parentInstance.addChild(inst);\n cursor++;\n } else {\n // Mismatch or missing — repair only this subtree. Mount fresh, then move\n // it into the correct position ahead of the offending/absent node.\n const ref = actualEl ?? null;\n const inst = mountFreshAt(ctx, childNode, parentDom, ref);\n parentInstance.addChild(inst);\n if (actualEl !== undefined) {\n // Drop the mismatched element that the fresh node replaces.\n const found = ctx.dom.isElement(actualEl) ? ctx.dom.tagName(actualEl) : null;\n reportHydrationDiagnostic(ctx, {\n type: 'tag-mismatch',\n expected: want,\n found,\n path: childPath,\n nodeId: childNode.id,\n nodeType: childNode.type,\n action: 'mounted fresh subtree in place',\n });\n ctx.dom.removeChild(parentDom, actualEl);\n cursor++;\n } else {\n reportHydrationDiagnostic(ctx, {\n type: 'missing-element',\n expected: want,\n found: null,\n path: childPath,\n nodeId: childNode.id,\n nodeType: childNode.type,\n action: 'mounted fresh subtree',\n });\n }\n }\n }\n\n // Remove any surplus server elements the graph no longer expects.\n for (let i = cursor; i < actual.length; i++) {\n const surplus = actual[i]!;\n reportHydrationDiagnostic(ctx, {\n type: 'surplus-element',\n expected: null,\n found: ctx.dom.isElement(surplus) ? ctx.dom.tagName(surplus) : null,\n path: `${parentPath} / [surplus ${i}]`,\n nodeId: null,\n nodeType: null,\n action: 'removed surplus server element',\n });\n ctx.dom.removeChild(parentDom, surplus);\n }\n}\n\n/**\n * Emit a hydration diagnostic through the (optional) sink. When no sink is\n * attached this is a single cheap `undefined` check — the production default.\n */\nfunction reportHydrationDiagnostic(\n ctx: RenderContext,\n d: {\n type: 'tag-mismatch' | 'missing-element' | 'surplus-element';\n expected: string | null;\n found: string | null;\n path: string;\n nodeId: string | null;\n nodeType: string | null;\n action: string;\n },\n): void {\n const sink = ctx.hydrationDiagnostics;\n if (sink === undefined) return;\n sink.report({ ...d, message: formatHydrationDiagnostic(d) });\n}\n\n/** Mount a fresh subtree for `node` and splice it before `ref` (or append). */\nfunction mountFreshAt(\n ctx: RenderContext,\n node: GraphNode,\n parentDom: Element,\n ref: Node | null,\n): NodeInstance {\n // mountNode appends the new subtree at the end of parentDom.\n const inst = mountNode(ctx, node, parentDom);\n if (ref !== null) {\n ctx.dom.insertBefore(parentDom, inst.domNode, ref);\n }\n return inst;\n}\n\n/** The element (not text/comment) children of a node, in order. */\nfunction elementChildren(ctx: RenderContext, parent: Element): Element[] {\n const out: Element[] = [];\n for (const node of ctx.dom.childNodes(parent)) {\n if (ctx.dom.isElement(node)) out.push(node);\n }\n return out;\n}\n\n/** The HTML tag a graph node is expected to occupy in the DOM. */\nfunction expectedTag(ctx: RenderContext, graphNode: GraphNode): string {\n switch (graphNode.type) {\n case 'text':\n return 'span';\n case 'heading': {\n const level = (graphNode.getProp('level') as number | undefined) ?? 1;\n return `h${level}`;\n }\n case 'input':\n return 'input';\n case 'image':\n return 'img';\n case 'link':\n return 'a';\n case 'button':\n return 'button';\n default:\n // reactive-list → ul, conditional → div, structural → resolveTag.\n return resolveTag(graphNode.type);\n }\n}\n","/**\n * StreetRenderHandle — the live handle returned by both `mount` and `hydrate`.\n *\n * Owns teardown for a mounted/hydrated application: disposes every NodeInstance\n * (removing event listeners and signal subscriptions) and clears the container\n * through the DOM adapter (never raw browser globals), so the same handle works\n * for browser and — in principle — server-driven teardown.\n */\n\nimport type { RenderHandle } from '@streetui/runtime';\nimport type { RenderContext } from './render-context.js';\nimport type { NodeInstance } from './node-instance.js';\n\nexport class StreetRenderHandle implements RenderHandle {\n private _disposed = false;\n private readonly _ctx: RenderContext;\n private readonly _rootInstance: NodeInstance;\n\n constructor(ctx: RenderContext, rootInstance: NodeInstance) {\n this._ctx = ctx;\n this._rootInstance = rootInstance;\n }\n\n flush(): void {\n if (this._disposed) return;\n // Signal subscriptions fire synchronously in StreetUI's state system;\n // flush() is a no-op at the renderer level — the DOM is already up to date\n // unless the scheduler is batching, in which case the scheduler calls\n // flush() after draining its queue.\n }\n\n unmount(): void {\n if (this._disposed) return;\n this._disposed = true;\n\n // Dispose all node instances (removes event listeners, signal subscriptions).\n this._rootInstance.dispose();\n\n // Remove all children from the container. Routed through the DOM adapter\n // (never `container.firstChild`/`removeChild`) so the teardown path is\n // server-safe.\n const dom = this._ctx.dom;\n const container = this._ctx.container;\n for (const child of dom.childNodes(container)) {\n dom.removeChild(container, child);\n }\n\n this._ctx.instances.clear();\n }\n}\n","/**\n * SSR state transfer (dehydration) — move server-resolved data to the client.\n *\n * When the server resolves resources before rendering, their data must reach\n * the client so hydration can seed them (via `resource({ initialData })`)\n * instead of refetching. StreetUI does this with a single, framework-scoped\n * `<script>` payload rather than blindly interpolating `JSON.stringify` into\n * markup.\n *\n * Safety (v0.4 rule #16): the JSON is emitted into a\n * `<script type=\"application/json\">` block — an inert data island the browser\n * never executes — and every character that could terminate that block or be\n * reinterpreted by the HTML/JS parser is escaped to its `\\uXXXX` form. Because\n * `<` inside JSON parses back to `<`, the payload round-trips exactly\n * while being impossible to break out of. This is deterministic (stable key\n * order is the caller's responsibility) and typed at the boundary as\n * `Record<string, unknown>` — never `any`.\n */\n\nimport type { DOMAdapter } from '@streetui/dom';\n\n/** Attribute marking StreetUI's state island so the client can find it. */\nexport const STATE_MARKER_ATTR = 'data-streetui-state';\n\n/**\n * Escape a JSON string for safe embedding inside a `<script>` element:\n * < > & → HTML / `</script>` breakout and entity ambiguity\n * U+2028 / U+2029 → invalid raw in JS string literals\n * Uses code-point checks so no raw separator characters live in this source.\n */\nfunction escapeForScript(json: string): string {\n let out = '';\n for (const ch of json) {\n const code = ch.charCodeAt(0);\n if (ch === '<') out += '\\\\u003c';\n else if (ch === '>') out += '\\\\u003e';\n else if (ch === '&') out += '\\\\u0026';\n else if (code === 0x2028) out += '\\\\u2028';\n else if (code === 0x2029) out += '\\\\u2029';\n else out += ch;\n }\n return out;\n}\n\n/**\n * Serialize a state map to an HTML `<script>` island for inclusion in the\n * server-rendered document (typically just before the closing tag of the\n * mount container). Returns an empty string for an empty map.\n */\nexport function serializeState(state: Record<string, unknown>): string {\n if (Object.keys(state).length === 0) return '';\n const json = escapeForScript(JSON.stringify(state));\n return `<script type=\"application/json\" ${STATE_MARKER_ATTR}>${json}</script>`;\n}\n\n/**\n * Read the state island back on the client. Searches `root` for StreetUI's\n * state `<script>` and parses it. Returns an empty object when absent or\n * unparseable (hydration then proceeds as a cold client render). Routed through\n * the DOM adapter so it is testable and never assumes a global `document`.\n */\nexport function readState(\n dom: DOMAdapter,\n root: Element | Document,\n): Record<string, unknown> {\n const el = dom.querySelector(root, `script[${STATE_MARKER_ATTR}]`);\n if (el === null) return {};\n const text = dom.getTextContent(el);\n if (text === null || text.length === 0) return {};\n try {\n const parsed: unknown = JSON.parse(text);\n if (parsed !== null && typeof parsed === 'object') {\n return parsed as Record<string, unknown>;\n }\n return {};\n } catch {\n return {};\n }\n}\n","/**\n * Server-side rendering — `renderToString`.\n *\n * Runs the *exact same* mount pipeline used in the browser (`mountGraph`), but\n * against a `ServerDOMAdapter` that builds a lightweight in-memory node tree\n * instead of a real browser DOM. The tree is then serialized to a normal HTML\n * string. Because both browser and server share the DSL → Compiler → Graph →\n * Runtime → Renderer pipeline, there is no second, SSR-specific renderer and no\n * virtual DOM.\n *\n * Lifecycle (v0.4 rule #20): the initial synchronous mount may open signal\n * subscriptions (via `wireSignalBindings`/`wireReactiveList`). On the server\n * those would be live forever, so once the HTML is serialized we dispose the\n * root instance — tearing down every subscription and listener. SSR therefore\n * has a *render* lifecycle only; the live *runtime* lifecycle is established\n * later on the client by `hydrate`.\n */\n\nimport { ServerDOMAdapter } from '@streetui/dom';\nimport type { CompiledApplication } from '@streetui/compiler';\nimport { createRenderContext } from './render-context.js';\nimport { mountGraph } from './mount.js';\nimport { getStaticSSRPlan } from './static-ssr-plan.js';\n\nexport interface RenderToStringOptions {\n /**\n * Override the server DOM adapter (rarely needed). Defaults to a fresh\n * `ServerDOMAdapter` per call so concurrent renders never share state.\n */\n readonly domAdapter?: ServerDOMAdapter;\n /**\n * @internal — testing/benchmark knob for the v1.7 static SSR plan.\n *\n * `undefined` (default): use the per-app cached plan (build once, reuse).\n * `null`: disable the plan entirely — the exact v1.6 runtime mount path, used\n * by the byte-identity gate and A/B benchmark as the \"legacy\" baseline.\n * a map: use this explicit plan.\n *\n * Not part of the supported public API; output is byte-identical regardless\n * of this value (§8).\n */\n readonly staticPlan?: ReadonlyMap<string, string> | null;\n}\n\n/**\n * Render a compiled StreetUI application to an HTML string.\n *\n * The returned markup contains only the application's own elements (the\n * synthetic container is not emitted), so callers embed it wherever they mount\n * on the client — e.g. inside `<div id=\"app\">…</div>`.\n */\nexport function renderToString(\n compiled: CompiledApplication,\n options: RenderToStringOptions = {},\n): string {\n const dom = options.domAdapter ?? new ServerDOMAdapter();\n\n // Resolve the v1.7 static SSR plan: cached-by-default, `null` forces the v1.6\n // path, an explicit map is used as-is. Only maximal static-subtree roots are\n // collapsed; dynamic regions still mount through the runtime path (§5).\n const plan =\n options.staticPlan === null\n ? undefined\n : (options.staticPlan ?? getStaticSSRPlan(compiled));\n const staticHTML = plan !== undefined && plan.size > 0 ? plan : undefined;\n\n // Synthetic container — the application root maps onto it, and the app's\n // top-level nodes are appended directly into it (mirroring browser mount).\n const container = dom.createElement('div');\n\n const ctx = createRenderContext(dom, compiled.graph, container, undefined, staticHTML);\n const rootInstance = mountGraph(ctx);\n\n const html = dom.serializeInner(container);\n\n // Tear down any subscriptions/listeners opened during mount — the server has\n // no live runtime. (rule #20)\n rootInstance.dispose();\n ctx.instances.clear();\n\n return html;\n}\n","/**\n * Static SSR Plan (v1.7, spec §4/§6) — internal.\n *\n * A compiler-derived plan that precomputes the verbatim HTML of every *maximal\n * static subtree* in an application graph. During SSR, the renderer emits that\n * precomputed string directly (via `ServerDOMAdapter.createRawHTML`) instead of\n * recursively constructing a `ServerElement`/`ServerText`/`NodeInstance` for\n * every node in the subtree. On the 10k-row `/users` corpus, ~100% of the node\n * mass lives in 10,000 static 8-node row subtrees, so collapsing each row into\n * one precomputed string removes the bulk of the mount-phase construction work.\n *\n * Design constraints honoured here:\n * - §3 REUSE the existing compiler analysis (`analyzeGraph`) to classify nodes;\n * no new/expensive analysis, and nothing runs during normal `compile()`.\n * - §5/§15 Only *maximal static-subtree roots* are collapsed. A dynamic region\n * (reactive-list container, conditional, dynamic-text/attr node) is never\n * treated as static — the list itself stays dynamic; only the provably-static\n * subtree *inside* each repeated item is precomputed.\n * - §8 The precomputed HTML is produced by the SAME mount + serialize pipeline\n * as the runtime path, so full-render output is byte-identical.\n * - §19 The plan retains ONLY strings keyed by GraphNode.id. No ServerDOM node,\n * NodeInstance or application object is retained (the throwaway build tree is\n * disposed + cleared). The per-app cache is a WeakMap, so a plan is released\n * when its CompiledApplication is collected.\n * - §24 Everything here is internal: not re-exported from the `streetui` or\n * `streetui/server` runtime barrels.\n *\n * This module is only ever imported by the SSR entry (`renderToString`), which\n * is itself reachable solely through the server path, so it tree-shakes out of\n * client bundles (§20, verified by bundle measurement).\n */\n\nimport type { NodeId } from '@streetui/core';\nimport type { ApplicationGraph, GraphNode } from '@streetui/graph';\nimport type { CompiledApplication } from '@streetui/compiler';\nimport { analyzeGraph } from '@streetui/compiler/diagnostics';\nimport { ServerDOMAdapter } from '@streetui/dom';\nimport { createRenderContext } from './render-context.js';\nimport { mountNode } from './mount.js';\n\n/**\n * Internal representation of the static SSR plan: maximal static-subtree root\n * GraphNode.id → its precomputed, verbatim outer HTML. A plain `Map<string,\n * string>` is deliberate — it holds no DOM/application references (§19).\n */\nexport type StaticSSRPlan = ReadonlyMap<NodeId, string>;\n\n/**\n * Collect the ids of every *maximal* static-subtree root under `graph`.\n *\n * Walk from the root; when a node is itself a whole static subtree, it is a\n * maximal root — record it and stop (its static descendants are subsumed).\n * Otherwise descend into its children, so a dynamic node's individually-static\n * children are still captured (the mixed-tree case, §5). The `application` root\n * is never recorded: it maps onto the render container rather than emitting its\n * own element, so we always descend past it into its real top-level children.\n */\nfunction collectMaximalStaticRoots(graph: ApplicationGraph): GraphNode[] {\n const analysis = analyzeGraph(graph);\n const roots: GraphNode[] = [];\n\n const walk = (node: GraphNode): void => {\n if (node.type !== 'application') {\n const a = analysis.nodes.get(node.id);\n if (a !== undefined && a.isStaticSubtree) {\n roots.push(node);\n return;\n }\n }\n for (const child of node.children) walk(child);\n };\n\n walk(graph.root);\n return roots;\n}\n\n/**\n * Serialize the outer HTML of a single static subtree using the exact runtime\n * mount + serialize pipeline (so the bytes match a full render). The throwaway\n * tree is disposed immediately, so nothing is retained.\n */\nfunction serializeStaticSubtree(\n dom: ServerDOMAdapter,\n graph: ApplicationGraph,\n root: GraphNode,\n): string {\n const container = dom.createElement('div');\n // No `staticHTML` on this ctx → mountNode builds the subtree fully.\n const ctx = createRenderContext(dom, graph, container);\n const instance = mountNode(ctx, root, container);\n const html = dom.serializeInner(container);\n // Tear down (static subtrees open no subscriptions, but keep symmetry with\n // renderToString's lifecycle) and drop all references.\n instance.dispose();\n ctx.instances.clear();\n return html;\n}\n\n/**\n * Build the static SSR plan for a compiled application. O(n) analysis + one\n * mount/serialize per maximal static subtree. Returns an empty map when the app\n * has no static subtrees (e.g. a highly-dynamic page) — the SSR path then\n * behaves exactly as v1.6.\n */\nexport function buildStaticSSRPlan(compiled: CompiledApplication): StaticSSRPlan {\n const graph = compiled.graph;\n const roots = collectMaximalStaticRoots(graph);\n const plan = new Map<NodeId, string>();\n if (roots.length === 0) return plan;\n\n const dom = new ServerDOMAdapter();\n for (const root of roots) {\n plan.set(root.id, serializeStaticSubtree(dom, graph, root));\n }\n return plan;\n}\n\n/**\n * Per-application plan cache. A WeakMap keyed by the CompiledApplication so a\n * plan is built once and reused across renders, and is released together with\n * the compiled app it belongs to — no long-lived retention of app state (§19).\n */\nconst PLAN_CACHE = new WeakMap<CompiledApplication, StaticSSRPlan>();\n\n/** Get the cached static SSR plan for a compiled app, building it on first use. */\nexport function getStaticSSRPlan(compiled: CompiledApplication): StaticSSRPlan {\n let plan = PLAN_CACHE.get(compiled);\n if (plan === undefined) {\n plan = buildStaticSSRPlan(compiled);\n PLAN_CACHE.set(compiled, plan);\n }\n return plan;\n}\n"],"mappings":"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","names":["instance","el","tag","import_dom","import_dom","import_dom"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -110,8 +110,18 @@ interface RenderContext {
|
|
|
110
110
|
* DevTools/diagnostics stay off the production runtime path.
|
|
111
111
|
*/
|
|
112
112
|
readonly hydrationDiagnostics?: HydrationDiagnosticSink;
|
|
113
|
+
/**
|
|
114
|
+
* Optional SSR-only static-subtree plan (v1.7). Maps a maximal
|
|
115
|
+
* static-subtree root GraphNode.id → its precomputed, verbatim HTML string.
|
|
116
|
+
* Present only on the server render path when a plan has been built; on the
|
|
117
|
+
* browser mount path it is always `undefined`, so the client hot path is
|
|
118
|
+
* unaffected (a single `=== undefined` check short-circuits). When a mounted
|
|
119
|
+
* node's id is in this map, the renderer emits the precomputed HTML via
|
|
120
|
+
* `dom.createRawHTML` instead of recursively constructing the subtree.
|
|
121
|
+
*/
|
|
122
|
+
readonly staticHTML?: ReadonlyMap<string, string>;
|
|
113
123
|
}
|
|
114
|
-
declare function createRenderContext(dom: DOMAdapter, graph: ApplicationGraph, container: Element, hydrationDiagnostics?: HydrationDiagnosticSink): RenderContext;
|
|
124
|
+
declare function createRenderContext(dom: DOMAdapter, graph: ApplicationGraph, container: Element, hydrationDiagnostics?: HydrationDiagnosticSink, staticHTML?: ReadonlyMap<string, string>): RenderContext;
|
|
115
125
|
|
|
116
126
|
/**
|
|
117
127
|
* Attribute and property application helpers.
|
|
@@ -168,6 +178,20 @@ declare function wireSignalBindings(ctx: RenderContext, graphNode: GraphNode, in
|
|
|
168
178
|
* eager build factory (it only ever renders 0..1 branch, so eager is fine).
|
|
169
179
|
*/
|
|
170
180
|
declare function wireReactiveList(ctx: RenderContext, graphNode: GraphNode, instance: NodeInstance, el: Element): void;
|
|
181
|
+
/**
|
|
182
|
+
* Attach overlay focus/keyboard behavior to a mounted portal. Server-safe: on
|
|
183
|
+
* the server `dom.body()` is null so this returns immediately (SSR emits inert
|
|
184
|
+
* markup, no focus concept). A plain portal has no `__overlay__` descriptor, so
|
|
185
|
+
* this also returns immediately — the behavior is purely additive.
|
|
186
|
+
*
|
|
187
|
+
* The panel is mounted/unmounted by the portal's inner `when(open, …)`, whose
|
|
188
|
+
* signal subscription is registered *before* this one (the conditional child is
|
|
189
|
+
* mounted earlier in the portal branch). Signal subscribers fire synchronously
|
|
190
|
+
* in subscription order, so on open→true the panel DOM exists before we move
|
|
191
|
+
* focus into it, and on open→false the panel is torn down before we restore
|
|
192
|
+
* focus. All listeners are tracked on the instance and torn down on unmount.
|
|
193
|
+
*/
|
|
194
|
+
declare function wireOverlayBehavior(ctx: RenderContext, graphNode: GraphNode, instance: NodeInstance, target: Element): void;
|
|
171
195
|
|
|
172
196
|
/**
|
|
173
197
|
* Patch — targeted DOM updates driven by signal changes.
|
|
@@ -393,6 +417,18 @@ interface RenderToStringOptions {
|
|
|
393
417
|
* `ServerDOMAdapter` per call so concurrent renders never share state.
|
|
394
418
|
*/
|
|
395
419
|
readonly domAdapter?: ServerDOMAdapter;
|
|
420
|
+
/**
|
|
421
|
+
* @internal — testing/benchmark knob for the v1.7 static SSR plan.
|
|
422
|
+
*
|
|
423
|
+
* `undefined` (default): use the per-app cached plan (build once, reuse).
|
|
424
|
+
* `null`: disable the plan entirely — the exact v1.6 runtime mount path, used
|
|
425
|
+
* by the byte-identity gate and A/B benchmark as the "legacy" baseline.
|
|
426
|
+
* a map: use this explicit plan.
|
|
427
|
+
*
|
|
428
|
+
* Not part of the supported public API; output is byte-identical regardless
|
|
429
|
+
* of this value (§8).
|
|
430
|
+
*/
|
|
431
|
+
readonly staticPlan?: ReadonlyMap<string, string> | null;
|
|
396
432
|
}
|
|
397
433
|
/**
|
|
398
434
|
* Render a compiled StreetUI application to an HTML string.
|
|
@@ -409,4 +445,4 @@ declare function renderToString(compiled: CompiledApplication, options?: RenderT
|
|
|
409
445
|
|
|
410
446
|
declare function resolveTag(type: SemanticNodeType): string;
|
|
411
447
|
|
|
412
|
-
export { type HydrationDiagnostic, type HydrationDiagnosticSink, type HydrationMismatchType, type MountFn, NodeInstance, type PlanEntry, type ReconcileResult, type RenderContext, type RenderToStringOptions, STATE_MARKER_ATTR, StreetRenderHandle, StreetRendererImpl, type StreetRendererOptions, applyNodeProps, applyProp, buttonUpdate, consoleHydrationDiagnosticSink, createHydrationDiagnosticCollector, createRenderContext, createRenderer, formatHydrationDiagnostic, headingUpdate, hydrateGraph, inputUpdate, mountGraph, mountNode, patchNode, patchProp, readState, reconcileChildren, reconcileChildrenByPlan, renderToString, resolveTag, serializeState, textUpdate, wireEvents, wireReactiveList, wireSignalBindings };
|
|
448
|
+
export { type HydrationDiagnostic, type HydrationDiagnosticSink, type HydrationMismatchType, type MountFn, NodeInstance, type PlanEntry, type ReconcileResult, type RenderContext, type RenderToStringOptions, STATE_MARKER_ATTR, StreetRenderHandle, StreetRendererImpl, type StreetRendererOptions, applyNodeProps, applyProp, buttonUpdate, consoleHydrationDiagnosticSink, createHydrationDiagnosticCollector, createRenderContext, createRenderer, formatHydrationDiagnostic, headingUpdate, hydrateGraph, inputUpdate, mountGraph, mountNode, patchNode, patchProp, readState, reconcileChildren, reconcileChildrenByPlan, renderToString, resolveTag, serializeState, textUpdate, wireEvents, wireOverlayBehavior, wireReactiveList, wireSignalBindings };
|