@getforma/core 1.0.0 → 1.0.1
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/README.md +4 -4
- package/dist/forma-runtime-csp.js +3400 -1
- package/dist/forma-runtime.js +3572 -1
- package/dist/formajs-runtime-hardened.global.js +3400 -1
- package/dist/formajs-runtime-hardened.global.js.map +1 -1
- package/dist/formajs-runtime.global.js +3572 -1
- package/dist/formajs-runtime.global.js.map +1 -1
- package/dist/formajs.global.js +3443 -1
- package/dist/formajs.global.js.map +1 -1
- package/dist/runtime-hardened.cjs.map +1 -1
- package/dist/runtime-hardened.js.map +1 -1
- package/dist/runtime.cjs.map +1 -1
- package/dist/runtime.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../node_modules/alien-signals/esm/system.mjs","../node_modules/alien-signals/esm/index.mjs","../src/reactive/signal.ts","../src/reactive/root.ts","../src/reactive/cleanup.ts","../src/reactive/dev.ts","../src/reactive/effect.ts","../src/reactive/computed.ts","../src/reactive/memo.ts","../src/reactive/batch.ts","../src/reactive/untrack.ts","../src/reactive/on.ts","../src/reactive/ref.ts","../src/reactive/reducer.ts","../src/reactive/suspense-context.ts","../src/reactive/resource.ts","../src/dom/list.ts","../src/dom/show.ts","../src/dom/hydrate.ts","../src/dom/element.ts","../src/dom/text.ts","../src/dom/mount.ts","../src/dom/switch.ts","../src/dom/portal.ts","../src/dom/error-boundary.ts","../src/dom/suspense.ts","../src/dom/activate.ts","../src/component/define.ts","../src/component/context.ts","../src/state/store.ts","../src/state/history.ts","../src/state/persist.ts","../src/events/bus.ts","../src/events/delegate.ts","../src/events/keyboard.ts","../src/dom-utils/query.ts","../src/dom-utils/mutate.ts","../src/dom-utils/traverse.ts","../src/dom-utils/observe.ts"],"sourcesContent":["/// <reference path=\"./jsx.d.ts\" />\n\n// Reactive core\nexport {\n createSignal, createEffect, createComputed, createMemo, batch,\n untrack, createRoot, onCleanup, on, onError,\n createRef, createReducer, createResource,\n // Reactive introspection (alien-signals 3.x)\n isSignal, isComputed, isEffect, isEffectScope,\n getBatchDepth, trigger,\n} from './reactive';\nexport type { SignalGetter, SignalSetter, SignalOptions, Ref, Dispatch, Resource, ResourceOptions, ErrorHandler } from './reactive';\n\n// DOM\nexport { h, Fragment, fragment, createText, mount, createList, cleanup, createShow, createSwitch, createPortal, createErrorBoundary, createSuspense, hydrateIsland, activateIslands, deactivateIsland, deactivateAllIslands, reconcileList } from './dom';\nexport type { IslandHydrateFn, ReconcileResult, ListTransitionHooks, CreateListOptions, SwitchCase } from './dom';\n\n// Component\nexport { defineComponent, disposeComponent, trackDisposer, onMount, onUnmount, createContext, provide, inject, unprovide } from './component';\nexport type { SetupFn, ComponentDef, CleanupFn, Context } from './component';\n\n// State\nexport { createStore, createHistory, persist } from './state';\nexport type { StoreSetter, PersistOptions, HistoryControls } from './state';\n\n// Events\nexport { createBus, delegate, onKey } from './events';\nexport type { EventBus, KeyOptions } from './events';\n\n// DOM Utils\nexport { $, $$, addClass, removeClass, toggleClass, setStyle, setAttr, setText, setHTML, setHTMLUnsafe,\n closest, children, siblings, parent, nextSibling, prevSibling,\n onResize, onIntersect, onMutation } from './dom-utils';\n\n// ─── Subpath imports (not in this bundle — zero network code here) ───\n// HTTP: import { createFetch, createSSE, createWebSocket } from '@getforma/core/http'\n// Storage: import { createLocalStorage, createIndexedDB } from '@getforma/core/storage'\n// Server: import { createAction, $$serverFunction } from '@getforma/core/server'\n","export const ReactiveFlags = {\n None: 0,\n Mutable: 1,\n Watching: 2,\n RecursedCheck: 4,\n Recursed: 8,\n Dirty: 16,\n Pending: 32,\n};\nexport function createReactiveSystem({ update, notify, unwatched, }) {\n return {\n link,\n unlink,\n propagate,\n checkDirty,\n shallowPropagate,\n };\n function link(dep, sub, version) {\n const prevDep = sub.depsTail;\n if (prevDep !== undefined && prevDep.dep === dep) {\n return;\n }\n const nextDep = prevDep !== undefined ? prevDep.nextDep : sub.deps;\n if (nextDep !== undefined && nextDep.dep === dep) {\n nextDep.version = version;\n sub.depsTail = nextDep;\n return;\n }\n const prevSub = dep.subsTail;\n if (prevSub !== undefined && prevSub.version === version && prevSub.sub === sub) {\n return;\n }\n const newLink = sub.depsTail\n = dep.subsTail\n = {\n version,\n dep,\n sub,\n prevDep,\n nextDep,\n prevSub,\n nextSub: undefined,\n };\n if (nextDep !== undefined) {\n nextDep.prevDep = newLink;\n }\n if (prevDep !== undefined) {\n prevDep.nextDep = newLink;\n }\n else {\n sub.deps = newLink;\n }\n if (prevSub !== undefined) {\n prevSub.nextSub = newLink;\n }\n else {\n dep.subs = newLink;\n }\n }\n function unlink(link, sub = link.sub) {\n const dep = link.dep;\n const prevDep = link.prevDep;\n const nextDep = link.nextDep;\n const nextSub = link.nextSub;\n const prevSub = link.prevSub;\n if (nextDep !== undefined) {\n nextDep.prevDep = prevDep;\n }\n else {\n sub.depsTail = prevDep;\n }\n if (prevDep !== undefined) {\n prevDep.nextDep = nextDep;\n }\n else {\n sub.deps = nextDep;\n }\n if (nextSub !== undefined) {\n nextSub.prevSub = prevSub;\n }\n else {\n dep.subsTail = prevSub;\n }\n if (prevSub !== undefined) {\n prevSub.nextSub = nextSub;\n }\n else if ((dep.subs = nextSub) === undefined) {\n unwatched(dep);\n }\n return nextDep;\n }\n function propagate(link) {\n let next = link.nextSub;\n let stack;\n top: do {\n const sub = link.sub;\n let flags = sub.flags;\n if (!(flags & (4 | 8 | 16 | 32))) {\n sub.flags = flags | 32;\n }\n else if (!(flags & (4 | 8))) {\n flags = 0;\n }\n else if (!(flags & 4)) {\n sub.flags = (flags & ~8) | 32;\n }\n else if (!(flags & (16 | 32)) && isValidLink(link, sub)) {\n sub.flags = flags | (8 | 32);\n flags &= 1;\n }\n else {\n flags = 0;\n }\n if (flags & 2) {\n notify(sub);\n }\n if (flags & 1) {\n const subSubs = sub.subs;\n if (subSubs !== undefined) {\n const nextSub = (link = subSubs).nextSub;\n if (nextSub !== undefined) {\n stack = { value: next, prev: stack };\n next = nextSub;\n }\n continue;\n }\n }\n if ((link = next) !== undefined) {\n next = link.nextSub;\n continue;\n }\n while (stack !== undefined) {\n link = stack.value;\n stack = stack.prev;\n if (link !== undefined) {\n next = link.nextSub;\n continue top;\n }\n }\n break;\n } while (true);\n }\n function checkDirty(link, sub) {\n let stack;\n let checkDepth = 0;\n let dirty = false;\n top: do {\n const dep = link.dep;\n const flags = dep.flags;\n if (sub.flags & 16) {\n dirty = true;\n }\n else if ((flags & (1 | 16)) === (1 | 16)) {\n if (update(dep)) {\n const subs = dep.subs;\n if (subs.nextSub !== undefined) {\n shallowPropagate(subs);\n }\n dirty = true;\n }\n }\n else if ((flags & (1 | 32)) === (1 | 32)) {\n if (link.nextSub !== undefined || link.prevSub !== undefined) {\n stack = { value: link, prev: stack };\n }\n link = dep.deps;\n sub = dep;\n ++checkDepth;\n continue;\n }\n if (!dirty) {\n const nextDep = link.nextDep;\n if (nextDep !== undefined) {\n link = nextDep;\n continue;\n }\n }\n while (checkDepth--) {\n const firstSub = sub.subs;\n const hasMultipleSubs = firstSub.nextSub !== undefined;\n if (hasMultipleSubs) {\n link = stack.value;\n stack = stack.prev;\n }\n else {\n link = firstSub;\n }\n if (dirty) {\n if (update(sub)) {\n if (hasMultipleSubs) {\n shallowPropagate(firstSub);\n }\n sub = link.sub;\n continue;\n }\n dirty = false;\n }\n else {\n sub.flags &= ~32;\n }\n sub = link.sub;\n const nextDep = link.nextDep;\n if (nextDep !== undefined) {\n link = nextDep;\n continue top;\n }\n }\n return dirty;\n } while (true);\n }\n function shallowPropagate(link) {\n do {\n const sub = link.sub;\n const flags = sub.flags;\n if ((flags & (32 | 16)) === 32) {\n sub.flags = flags | 16;\n if ((flags & (2 | 4)) === 2) {\n notify(sub);\n }\n }\n } while ((link = link.nextSub) !== undefined);\n }\n function isValidLink(checkLink, sub) {\n let link = sub.depsTail;\n while (link !== undefined) {\n if (link === checkLink) {\n return true;\n }\n link = link.prevDep;\n }\n return false;\n }\n}\n","import { createReactiveSystem } from './system.mjs';\nlet cycle = 0;\nlet batchDepth = 0;\nlet notifyIndex = 0;\nlet queuedLength = 0;\nlet activeSub;\nconst queued = [];\nconst { link, unlink, propagate, checkDirty, shallowPropagate, } = createReactiveSystem({\n update(node) {\n if (node.depsTail !== undefined) {\n return updateComputed(node);\n }\n else {\n return updateSignal(node);\n }\n },\n notify(effect) {\n let insertIndex = queuedLength;\n let firstInsertedIndex = insertIndex;\n do {\n queued[insertIndex++] = effect;\n effect.flags &= ~2;\n effect = effect.subs?.sub;\n if (effect === undefined || !(effect.flags & 2)) {\n break;\n }\n } while (true);\n queuedLength = insertIndex;\n while (firstInsertedIndex < --insertIndex) {\n const left = queued[firstInsertedIndex];\n queued[firstInsertedIndex++] = queued[insertIndex];\n queued[insertIndex] = left;\n }\n },\n unwatched(node) {\n if (!(node.flags & 1)) {\n effectScopeOper.call(node);\n }\n else if (node.depsTail !== undefined) {\n node.depsTail = undefined;\n node.flags = 1 | 16;\n purgeDeps(node);\n }\n },\n});\nexport function getActiveSub() {\n return activeSub;\n}\nexport function setActiveSub(sub) {\n const prevSub = activeSub;\n activeSub = sub;\n return prevSub;\n}\nexport function getBatchDepth() {\n return batchDepth;\n}\nexport function startBatch() {\n ++batchDepth;\n}\nexport function endBatch() {\n if (!--batchDepth) {\n flush();\n }\n}\nexport function isSignal(fn) {\n return fn.name === 'bound ' + signalOper.name;\n}\nexport function isComputed(fn) {\n return fn.name === 'bound ' + computedOper.name;\n}\nexport function isEffect(fn) {\n return fn.name === 'bound ' + effectOper.name;\n}\nexport function isEffectScope(fn) {\n return fn.name === 'bound ' + effectScopeOper.name;\n}\nexport function signal(initialValue) {\n return signalOper.bind({\n currentValue: initialValue,\n pendingValue: initialValue,\n subs: undefined,\n subsTail: undefined,\n flags: 1,\n });\n}\nexport function computed(getter) {\n return computedOper.bind({\n value: undefined,\n subs: undefined,\n subsTail: undefined,\n deps: undefined,\n depsTail: undefined,\n flags: 0,\n getter: getter,\n });\n}\nexport function effect(fn) {\n const e = {\n fn,\n subs: undefined,\n subsTail: undefined,\n deps: undefined,\n depsTail: undefined,\n flags: 2 | 4,\n };\n const prevSub = setActiveSub(e);\n if (prevSub !== undefined) {\n link(e, prevSub, 0);\n }\n try {\n e.fn();\n }\n finally {\n activeSub = prevSub;\n e.flags &= ~4;\n }\n return effectOper.bind(e);\n}\nexport function effectScope(fn) {\n const e = {\n deps: undefined,\n depsTail: undefined,\n subs: undefined,\n subsTail: undefined,\n flags: 0,\n };\n const prevSub = setActiveSub(e);\n if (prevSub !== undefined) {\n link(e, prevSub, 0);\n }\n try {\n fn();\n }\n finally {\n activeSub = prevSub;\n }\n return effectScopeOper.bind(e);\n}\nexport function trigger(fn) {\n const sub = {\n deps: undefined,\n depsTail: undefined,\n flags: 2,\n };\n const prevSub = setActiveSub(sub);\n try {\n fn();\n }\n finally {\n activeSub = prevSub;\n let link = sub.deps;\n while (link !== undefined) {\n const dep = link.dep;\n link = unlink(link, sub);\n const subs = dep.subs;\n if (subs !== undefined) {\n sub.flags = 0;\n propagate(subs);\n shallowPropagate(subs);\n }\n }\n if (!batchDepth) {\n flush();\n }\n }\n}\nfunction updateComputed(c) {\n ++cycle;\n c.depsTail = undefined;\n c.flags = 1 | 4;\n const prevSub = setActiveSub(c);\n try {\n const oldValue = c.value;\n return oldValue !== (c.value = c.getter(oldValue));\n }\n finally {\n activeSub = prevSub;\n c.flags &= ~4;\n purgeDeps(c);\n }\n}\nfunction updateSignal(s) {\n s.flags = 1;\n return s.currentValue !== (s.currentValue = s.pendingValue);\n}\nfunction run(e) {\n const flags = e.flags;\n if (flags & 16\n || (flags & 32\n && checkDirty(e.deps, e))) {\n ++cycle;\n e.depsTail = undefined;\n e.flags = 2 | 4;\n const prevSub = setActiveSub(e);\n try {\n e.fn();\n }\n finally {\n activeSub = prevSub;\n e.flags &= ~4;\n purgeDeps(e);\n }\n }\n else {\n e.flags = 2;\n }\n}\nfunction flush() {\n try {\n while (notifyIndex < queuedLength) {\n const effect = queued[notifyIndex];\n queued[notifyIndex++] = undefined;\n run(effect);\n }\n }\n finally {\n while (notifyIndex < queuedLength) {\n const effect = queued[notifyIndex];\n queued[notifyIndex++] = undefined;\n effect.flags |= 2 | 8;\n }\n notifyIndex = 0;\n queuedLength = 0;\n }\n}\nfunction computedOper() {\n const flags = this.flags;\n if (flags & 16\n || (flags & 32\n && (checkDirty(this.deps, this)\n || (this.flags = flags & ~32, false)))) {\n if (updateComputed(this)) {\n const subs = this.subs;\n if (subs !== undefined) {\n shallowPropagate(subs);\n }\n }\n }\n else if (!flags) {\n this.flags = 1 | 4;\n const prevSub = setActiveSub(this);\n try {\n this.value = this.getter();\n }\n finally {\n activeSub = prevSub;\n this.flags &= ~4;\n }\n }\n const sub = activeSub;\n if (sub !== undefined) {\n link(this, sub, cycle);\n }\n return this.value;\n}\nfunction signalOper(...value) {\n if (value.length) {\n if (this.pendingValue !== (this.pendingValue = value[0])) {\n this.flags = 1 | 16;\n const subs = this.subs;\n if (subs !== undefined) {\n propagate(subs);\n if (!batchDepth) {\n flush();\n }\n }\n }\n }\n else {\n if (this.flags & 16) {\n if (updateSignal(this)) {\n const subs = this.subs;\n if (subs !== undefined) {\n shallowPropagate(subs);\n }\n }\n }\n let sub = activeSub;\n while (sub !== undefined) {\n if (sub.flags & (1 | 2)) {\n link(this, sub, cycle);\n break;\n }\n sub = sub.subs?.sub;\n }\n return this.currentValue;\n }\n}\nfunction effectOper() {\n effectScopeOper.call(this);\n}\nfunction effectScopeOper() {\n this.depsTail = undefined;\n this.flags = 0;\n purgeDeps(this);\n const sub = this.subs;\n if (sub !== undefined) {\n unlink(sub);\n }\n}\nfunction purgeDeps(sub) {\n const depsTail = sub.depsTail;\n let dep = depsTail !== undefined ? depsTail.nextDep : sub.deps;\n while (dep !== undefined) {\n dep = unlink(dep, sub);\n }\n}\n","/**\n * Forma Reactive - Signal\n *\n * Fine-grained reactive primitive backed by alien-signals.\n * API: createSignal returns [getter, setter] tuple following SolidJS conventions.\n *\n * TC39 Signals equivalent: Signal.State\n */\n\nimport { signal as createRawSignal, setActiveSub } from 'alien-signals';\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\nexport type SignalGetter<T> = () => T;\nexport type SignalSetter<T> = (v: T | ((prev: T) => T)) => void;\n\nexport interface SignalOptions<T> {\n /** Debug name — attached to getter in dev mode for devtools inspection. */\n name?: string;\n /**\n * Custom equality check. When provided, the setter will read the current\n * value and only update the signal if `equals(prev, next)` returns `false`.\n *\n * Default: none (alien-signals uses strict inequality `!==` internally).\n *\n * ```ts\n * const [pos, setPos] = createSignal(\n * { x: 0, y: 0 },\n * { equals: (a, b) => a.x === b.x && a.y === b.y },\n * );\n *\n * setPos({ x: 0, y: 0 }); // skipped — equals returns true\n * setPos({ x: 1, y: 0 }); // applied — equals returns false\n * ```\n */\n equals?: (prev: T, next: T) => boolean;\n}\n\n/**\n * Wrap a value so the setter treats it as a literal value, not a functional updater.\n *\n * When `T` is itself a function type, passing a function to the setter is\n * ambiguous -- it looks like a functional update (`prev => next`). Use\n * `value()` to disambiguate:\n *\n * ```ts\n * const [getFn, setFn] = createSignal<() => void>(() => console.log('a'));\n *\n * // BUG: interpreted as a functional update -- calls the arrow with prev\n * // setFn(() => console.log('b'));\n *\n * // Correct: wraps in a thunk so the setter stores it as-is\n * setFn(value(() => console.log('b')));\n * ```\n */\nexport function value<T>(v: T): () => T {\n return () => v;\n}\n\ntype RawSignal<T> = {\n (): T;\n (value: T): void;\n};\n\nfunction applySignalSet<T>(\n s: RawSignal<T>,\n v: T | ((prev: T) => T),\n equals?: (prev: T, next: T) => boolean,\n): void {\n if (typeof v !== 'function') {\n if (equals) {\n // Read current value without tracking\n const prevSub = setActiveSub(undefined);\n const prev = s();\n setActiveSub(prevSub);\n if (equals(prev, v)) return; // skip — values are equal\n }\n s(v);\n return;\n }\n\n // Functional update: read prev without tracking\n const prevSub = setActiveSub(undefined);\n const prev = s();\n setActiveSub(prevSub);\n const next = (v as (prev: T) => T)(prev);\n if (equals && equals(prev, next)) return; // skip — values are equal\n s(next);\n}\n\n/**\n * Create a reactive signal.\n *\n * ```ts\n * const [count, setCount] = createSignal(0);\n * console.log(count()); // 0\n * setCount(1);\n * setCount(prev => prev + 1);\n * ```\n *\n * With custom equality:\n *\n * ```ts\n * const [pos, setPos] = createSignal(\n * { x: 0, y: 0 },\n * { equals: (a, b) => a.x === b.x && a.y === b.y },\n * );\n * ```\n */\nexport function createSignal<T>(initialValue: T, options?: SignalOptions<T>): [get: SignalGetter<T>, set: SignalSetter<T>] {\n const s = createRawSignal<T>(initialValue) as RawSignal<T>;\n const getter = s as unknown as SignalGetter<T>;\n const eq = options?.equals;\n const setter: SignalSetter<T> = (v: T | ((prev: T) => T)) => applySignalSet(s, v, eq);\n\n return [getter, setter];\n}\n","/**\n * Forma Reactive - Root\n *\n * Explicit reactive ownership scope. All effects created inside a root\n * are automatically disposed when the root is torn down.\n *\n * Uses alien-signals' `effectScope` under the hood for native graph-level\n * effect tracking, with a userland disposer list for non-effect cleanup\n * (e.g., event listeners, DOM references, timers).\n */\n\nimport { effectScope as rawEffectScope } from 'alien-signals';\n\n// ---------------------------------------------------------------------------\n// Root scope tracking\n// ---------------------------------------------------------------------------\n\nlet currentRoot: RootScope | null = null;\nconst rootStack: (RootScope | null)[] = [];\n\ninterface RootScope {\n /** Userland disposers (event listeners, DOM refs, timers, etc.) */\n disposers: (() => void)[];\n /** alien-signals effect scope dispose — tears down all reactive effects */\n scopeDispose: (() => void) | null;\n}\n\n/**\n * Create a reactive root scope.\n *\n * All effects created (via `createEffect`) inside the callback are tracked\n * at both the reactive graph level (via alien-signals effectScope) and the\n * userland level (via registerDisposer). The returned `dispose` function\n * tears down everything.\n *\n * ```ts\n * const dispose = createRoot(() => {\n * createEffect(() => console.log(count()));\n * createEffect(() => console.log(name()));\n * });\n * // later: dispose() stops both effects\n * ```\n */\nexport function createRoot<T>(fn: (dispose: () => void) => T): T {\n const scope: RootScope = { disposers: [], scopeDispose: null };\n\n rootStack.push(currentRoot);\n currentRoot = scope;\n\n const dispose = () => {\n // Dispose alien-signals effect scope first (reactive graph cleanup)\n if (scope.scopeDispose) {\n try { scope.scopeDispose(); } catch { /* ensure userland disposers still run */ }\n scope.scopeDispose = null;\n }\n // Then run userland disposers\n for (const d of scope.disposers) {\n try { d(); } catch { /* ensure all disposers run */ }\n }\n scope.disposers.length = 0;\n };\n\n let result: T;\n try {\n // Wrap in alien-signals effectScope for native effect tracking\n scope.scopeDispose = rawEffectScope(() => {\n result = fn(dispose);\n });\n } finally {\n currentRoot = rootStack.pop() ?? null;\n }\n\n return result!;\n}\n\n/**\n * @internal — called by createEffect to register disposers in the current root.\n */\nexport function registerDisposer(dispose: () => void): void {\n if (currentRoot) {\n currentRoot.disposers.push(dispose);\n }\n}\n\n/**\n * @internal — check if we're inside a root scope.\n */\nexport function hasActiveRoot(): boolean {\n return currentRoot !== null;\n}\n","/**\n * Forma Reactive - Cleanup\n *\n * Register cleanup functions within reactive scopes.\n * Inspired by SolidJS onCleanup().\n */\n\n// ---------------------------------------------------------------------------\n// Cleanup context tracking\n// ---------------------------------------------------------------------------\n\ntype CleanupCollector = ((fn: () => void) => void) | null;\n\nlet currentCleanupCollector: CleanupCollector = null;\n\n/**\n * Register a cleanup function in the current reactive scope.\n * The cleanup runs before the effect re-executes and on disposal.\n *\n * More composable than returning a cleanup from the effect function,\n * since it can be called from helper functions.\n *\n * ```ts\n * createEffect(() => {\n * const timer = setInterval(tick, 1000);\n * onCleanup(() => clearInterval(timer));\n * });\n * ```\n */\nexport function onCleanup(fn: () => void): void {\n currentCleanupCollector?.(fn);\n}\n\n/**\n * @internal — Set the cleanup collector for the current effect execution.\n */\nexport function setCleanupCollector(collector: CleanupCollector): CleanupCollector {\n const prev = currentCleanupCollector;\n currentCleanupCollector = collector;\n return prev;\n}\n","/**\n * Forma Reactive - Dev Mode\n *\n * Development utilities stripped from production builds via __DEV__ flag.\n * Bundlers replace __DEV__ with false → dead-code elimination removes all dev paths.\n */\n\n// __DEV__ is replaced by bundler (tsup define). Defaults to true for unbundled usage.\ndeclare const process: { env?: Record<string, string | undefined> } | undefined;\nexport const __DEV__: boolean = typeof process !== 'undefined'\n ? (process!.env?.NODE_ENV !== 'production')\n : true;\n\n// ---------------------------------------------------------------------------\n// Global error handler\n// ---------------------------------------------------------------------------\n\nexport type ErrorHandler = (error: unknown, info?: { source?: string }) => void;\n\nlet _errorHandler: ErrorHandler | null = null;\n\n/**\n * Install a global error handler for FormaJS reactive errors.\n * Called when effects, computeds, or event handlers throw.\n *\n * ```ts\n * onError((err, info) => {\n * console.error(`[${info?.source}]`, err);\n * Sentry.captureException(err);\n * });\n * ```\n */\nexport function onError(handler: ErrorHandler): void {\n _errorHandler = handler;\n}\n\n/** @internal */\nexport function reportError(error: unknown, source?: string): void {\n if (_errorHandler) {\n try { _errorHandler(error, source ? { source } : {}); } catch { /* prevent infinite loop */ }\n }\n if (__DEV__) {\n console.error(`[forma] ${source ?? 'Unknown'} error:`, error);\n }\n}\n","/**\n * Forma Reactive - Effect\n *\n * Side-effectful reactive computation that auto-tracks signal dependencies.\n * Backed by alien-signals for automatic dependency tracking.\n *\n * TC39 Signals equivalent: Signal.subtle.Watcher (effect is a userland concept)\n */\n\nimport { effect as rawEffect } from 'alien-signals';\nimport { hasActiveRoot, registerDisposer } from './root.js';\nimport { setCleanupCollector } from './cleanup.js';\nimport { reportError } from './dev.js';\n\n// ---------------------------------------------------------------------------\n// Cleanup array pool — avoids allocating a new array every effect re-run\n// ---------------------------------------------------------------------------\n\nconst POOL_SIZE = 32;\nconst MAX_REENTRANT_RUNS = 100;\nconst pool: (() => void)[][] = [];\nfor (let i = 0; i < POOL_SIZE; i++) pool.push([]);\nlet poolIdx = POOL_SIZE;\n\nfunction acquireArray(): (() => void)[] {\n if (poolIdx > 0) {\n const arr = pool[--poolIdx]!;\n arr.length = 0;\n return arr;\n }\n return [];\n}\n\nfunction releaseArray(arr: (() => void)[]): void {\n arr.length = 0;\n if (poolIdx < POOL_SIZE) {\n pool[poolIdx++] = arr;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Unified cleanup runner — single function for both re-run and dispose paths\n// ---------------------------------------------------------------------------\n\nfunction runCleanup(fn: (() => void) | undefined): void {\n if (fn === undefined) return;\n try {\n fn();\n } catch (e) {\n reportError(e, 'effect cleanup');\n }\n}\n\nfunction runCleanups(bag: (() => void)[] | undefined): void {\n if (bag === undefined) return;\n for (let i = 0; i < bag.length; i++) {\n try { bag[i]!(); } catch (e) { reportError(e, 'effect cleanup'); }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Create a reactive effect that auto-tracks signal dependencies.\n *\n * The provided function runs immediately and re-runs whenever any signal it\n * reads changes. If the function returns a cleanup function, that cleanup is\n * called before each re-run and on disposal.\n *\n * Additionally, `onCleanup()` can be called inside the effect to register\n * cleanup functions composably.\n *\n * Returns a dispose function that stops the effect.\n */\n/**\n * @internal — Lightweight effect for Forma's internal DOM bindings.\n *\n * Bypasses createEffect's cleanup infrastructure (pool, collector, error\n * reporting, engine compression) since internal effects never use\n * onCleanup() or return cleanup functions. This saves ~4 function calls\n * per effect creation and per re-run.\n *\n * ONLY use for effects that:\n * 1. Never call onCleanup()\n * 2. Never return a cleanup function\n * 3. Contain simple \"read signal → write DOM\" logic\n */\nexport function internalEffect(fn: () => void): () => void {\n const dispose = rawEffect(fn);\n if (hasActiveRoot()) {\n registerDisposer(dispose);\n }\n return dispose;\n}\n\nexport function createEffect(fn: () => void | (() => void)): () => void {\n const shouldRegister = hasActiveRoot();\n\n // Most effects have zero or one cleanup. Track the single-cleanup case\n // without array allocation; only promote to pooled array when needed.\n let cleanup: (() => void) | undefined;\n let cleanupBag: (() => void)[] | undefined;\n let nextCleanup: (() => void) | undefined;\n let nextCleanupBag: (() => void)[] | undefined;\n\n const addCleanup = (cb: () => void) => {\n if (nextCleanupBag !== undefined) {\n nextCleanupBag.push(cb);\n return;\n }\n if (nextCleanup !== undefined) {\n const bag = acquireArray();\n bag.push(nextCleanup, cb);\n nextCleanup = undefined;\n nextCleanupBag = bag;\n return;\n }\n nextCleanup = cb;\n };\n\n // \"Engine Compression\" exploit: most effects never use cleanup (onCleanup()\n // or return value). After the first clean run, we know this effect is\n // \"cleanup-free\" and can skip the entire cleanup infrastructure on re-runs.\n // This saves 4 function calls per re-run: acquireArray, setCleanupCollector,\n // releaseArray, and bag inspection. Like the engine compression ratio exploit —\n // the \"rules\" say we should always prepare for cleanup, but we measure at\n // \"room temperature\" (first run) and exploit the gap.\n let skipCleanupInfra = false;\n let firstRun = true;\n let running = false;\n let rerunRequested = false;\n\n const runOnce = () => {\n // Run and clear previous cleanups (only if any exist).\n if (cleanup !== undefined) {\n runCleanup(cleanup);\n cleanup = undefined;\n }\n if (cleanupBag !== undefined) {\n runCleanups(cleanupBag);\n releaseArray(cleanupBag);\n cleanupBag = undefined;\n }\n\n // Ultra-fast path: this effect has proven it doesn't use cleanup.\n // Skip acquireArray + setCleanupCollector + bag checks + releaseArray.\n if (skipCleanupInfra) {\n try { fn(); } catch (e) { reportError(e, 'effect'); }\n return;\n }\n\n nextCleanup = undefined;\n nextCleanupBag = undefined;\n\n // Full path: install collector for onCleanup() calls.\n const prevCollector = setCleanupCollector(addCleanup);\n\n try {\n const result = fn();\n\n if (typeof result === 'function') {\n addCleanup(result as () => void);\n }\n\n // Hot path: no cleanups registered or returned — enable ultra-fast path.\n if (nextCleanup === undefined && nextCleanupBag === undefined) {\n // First clean run → enable ultra-fast path for all subsequent runs\n if (firstRun) skipCleanupInfra = true;\n return;\n }\n\n if (nextCleanupBag !== undefined) {\n cleanupBag = nextCleanupBag;\n } else {\n cleanup = nextCleanup;\n }\n } catch (e) {\n reportError(e, 'effect');\n\n if (nextCleanupBag !== undefined) {\n cleanupBag = nextCleanupBag;\n } else {\n cleanup = nextCleanup;\n }\n } finally {\n setCleanupCollector(prevCollector);\n firstRun = false;\n }\n };\n\n const safeFn = () => {\n if (running) {\n rerunRequested = true;\n return;\n }\n\n running = true;\n try {\n let reentrantRuns = 0;\n do {\n rerunRequested = false;\n runOnce();\n if (rerunRequested) {\n reentrantRuns++;\n if (reentrantRuns >= MAX_REENTRANT_RUNS) {\n reportError(\n new Error(`createEffect exceeded ${MAX_REENTRANT_RUNS} re-entrant runs`),\n 'effect',\n );\n rerunRequested = false;\n }\n }\n } while (rerunRequested);\n } finally {\n running = false;\n }\n };\n\n const dispose = rawEffect(safeFn);\n\n // Wrap dispose to also run final cleanups\n let disposed = false;\n const wrappedDispose = () => {\n if (disposed) return;\n disposed = true;\n dispose();\n if (cleanup !== undefined) {\n runCleanup(cleanup);\n cleanup = undefined;\n }\n if (cleanupBag !== undefined) {\n runCleanups(cleanupBag);\n releaseArray(cleanupBag);\n cleanupBag = undefined;\n }\n };\n\n // Register in current root scope (if any)\n if (shouldRegister) {\n registerDisposer(wrappedDispose);\n }\n\n return wrappedDispose;\n}\n","/**\n * Forma Reactive - Computed\n *\n * Lazy, cached derived value that participates in the reactive graph.\n * Backed by alien-signals for automatic dependency tracking\n * and cache invalidation.\n *\n * TC39 Signals equivalent: Signal.Computed\n */\n\nimport { computed as rawComputed } from 'alien-signals';\n\n/**\n * Create a lazy, cached computed value.\n *\n * Note: Unlike SolidJS's createComputed (which is an eager synchronous\n * side effect), this is a lazy cached derivation — equivalent to\n * SolidJS's createMemo. Both createComputed and createMemo in FormaJS\n * are identical.\n *\n * The getter receives the previous value as an argument, enabling\n * efficient diffing patterns without a separate signal:\n *\n * ```ts\n * const [count, setCount] = createSignal(0);\n * const doubled = createComputed(() => count() * 2);\n * console.log(doubled()); // 0\n * setCount(5);\n * console.log(doubled()); // 10\n * ```\n *\n * With previous value (for diffing):\n *\n * ```ts\n * const changes = createComputed((prev) => {\n * const next = items();\n * if (prev) console.log(`changed from ${prev.length} to ${next.length} items`);\n * return next;\n * });\n * ```\n */\nexport function createComputed<T>(fn: (previousValue?: T) => T): () => T {\n return rawComputed(fn);\n}\n","/**\n * Forma Reactive - Memo\n *\n * Alias for createComputed with SolidJS/React-familiar naming.\n * A memoized derived value that only recomputes when its dependencies change.\n *\n * TC39 Signals equivalent: Signal.Computed\n */\n\nimport { createComputed } from './computed.js';\n\n/**\n * Create a memoized computed value.\n * Identical to `createComputed` — provided for React/SolidJS familiarity.\n *\n * Note: Unlike SolidJS's createComputed (which is an eager synchronous\n * side effect), both createComputed and createMemo in FormaJS are lazy\n * cached derivations — equivalent to SolidJS's createMemo. They are\n * identical.\n *\n * The computation runs lazily and caches the result. It only recomputes\n * when a signal it reads during computation changes.\n *\n * ```ts\n * const [count, setCount] = createSignal(0);\n * const doubled = createMemo(() => count() * 2);\n * console.log(doubled()); // 0\n * setCount(5);\n * console.log(doubled()); // 10\n * ```\n */\nexport const createMemo: typeof createComputed = createComputed;\n","/**\n * Forma Reactive - Batch\n *\n * Groups multiple signal updates and defers effect execution until the\n * outermost batch completes. Prevents intermediate re-renders.\n * Backed by alien-signals.\n *\n * TC39 Signals: no built-in batch — this is a userland optimization.\n */\n\nimport { startBatch, endBatch } from 'alien-signals';\n\n/**\n * Group multiple signal updates so that effects only run once after all\n * updates have been applied.\n *\n * ```ts\n * batch(() => {\n * setA(1);\n * setB(2);\n * // effects that depend on A and B won't run yet\n * });\n * // effects run here, once\n * ```\n *\n * Batches are nestable — only the outermost batch triggers the flush.\n */\nexport function batch(fn: () => void): void {\n startBatch();\n try {\n fn();\n } finally {\n endBatch();\n }\n}\n","/**\n * Forma Reactive - Untrack\n *\n * Read signals without subscribing to them in the reactive graph.\n * Essential for reading values inside effects without creating dependencies.\n *\n * TC39 Signals equivalent: Signal.subtle.untrack()\n */\n\nimport { setActiveSub } from 'alien-signals';\n\n/**\n * Execute a function without tracking signal reads.\n * Any signals read inside `fn` will NOT become dependencies of the\n * surrounding effect or computed.\n *\n * ```ts\n * createEffect(() => {\n * const a = count(); // tracked — effect re-runs when count changes\n * const b = untrack(() => other()); // NOT tracked — effect ignores other changes\n * });\n * ```\n */\nexport function untrack<T>(fn: () => T): T {\n const prev = setActiveSub(undefined);\n try {\n return fn();\n } finally {\n setActiveSub(prev);\n }\n}\n","/**\n * Forma Reactive - On\n *\n * Explicit dependency tracking for effects.\n * Only re-runs when the specified signals change, ignoring all other reads.\n *\n * SolidJS equivalent: on()\n * Vue equivalent: watch() with explicit deps\n * React equivalent: useEffect dependency array\n */\n\nimport { untrack } from './untrack.js';\n\n/**\n * Create a tracked effect body that only fires when specific dependencies change.\n *\n * Wraps a function so that only the `deps` signals are tracked.\n * All signal reads inside `fn` are untracked (won't cause re-runs).\n *\n * Use with `createEffect`:\n *\n * ```ts\n * const [a, setA] = createSignal(1);\n * const [b, setB] = createSignal(2);\n *\n * // Only re-runs when `a` changes, NOT when `b` changes:\n * createEffect(on(a, (value, prev) => {\n * console.log(`a changed: ${prev} → ${value}, b is ${b()}`);\n * }));\n *\n * setA(10); // fires: \"a changed: 1 → 10, b is 2\"\n * setB(20); // does NOT fire\n * ```\n *\n * Multiple dependencies:\n * ```ts\n * createEffect(on(\n * () => [a(), b()] as const,\n * ([aVal, bVal], prev) => { ... }\n * ));\n * ```\n */\nexport function on<T, U>(\n deps: () => T,\n fn: (value: T, prev: T | undefined) => U,\n options?: { defer?: boolean },\n): () => U | undefined {\n let prev: T | undefined;\n let isFirst = true;\n\n return () => {\n // Track only the deps\n const value = deps();\n\n if (options?.defer && isFirst) {\n isFirst = false;\n prev = value;\n return undefined;\n }\n\n // Run the body untracked so it doesn't add extra dependencies\n const result = untrack(() => fn(value, prev));\n prev = value;\n return result;\n };\n}\n","/**\n * Forma Reactive - Ref\n *\n * Mutable container that does NOT trigger reactivity.\n * Use for DOM references, previous values, instance variables —\n * anything that needs to persist across effect re-runs without\n * causing re-execution.\n *\n * React equivalent: useRef\n * SolidJS equivalent: (none — uses plain variables in setup)\n */\n\nexport interface Ref<T> {\n current: T;\n}\n\n/**\n * Create a mutable ref container.\n *\n * Unlike signals, writing to `.current` does NOT trigger effects.\n * Use when you need a stable reference across reactive scopes.\n *\n * ```ts\n * const timerRef = createRef<number | null>(null);\n *\n * createEffect(() => {\n * timerRef.current = setInterval(tick, 1000);\n * onCleanup(() => clearInterval(timerRef.current!));\n * });\n *\n * // DOM ref pattern:\n * const elRef = createRef<HTMLElement | null>(null);\n * h('div', { ref: (el) => { elRef.current = el; } });\n * ```\n */\nexport function createRef<T>(initialValue: T): Ref<T> {\n return { current: initialValue };\n}\n","/**\n * Forma Reactive - Reducer\n *\n * State machine pattern — dispatch actions to a pure reducer function.\n * Fine-grained: only the resulting state signal is reactive.\n *\n * React equivalent: useReducer\n * SolidJS equivalent: (none — uses createSignal + helpers)\n */\n\nimport { createSignal, type SignalGetter } from './signal.js';\n\nexport type Dispatch<A> = (action: A) => void;\n\n/**\n * Create a reducer — predictable state updates via dispatched actions.\n *\n * The reducer function must be pure: `(state, action) => newState`.\n * Returns a [state, dispatch] tuple.\n *\n * ```ts\n * type Action = { type: 'increment' } | { type: 'decrement' } | { type: 'reset' };\n *\n * const [count, dispatch] = createReducer(\n * (state: number, action: Action) => {\n * switch (action.type) {\n * case 'increment': return state + 1;\n * case 'decrement': return state - 1;\n * case 'reset': return 0;\n * }\n * },\n * 0,\n * );\n *\n * dispatch({ type: 'increment' }); // count() === 1\n * dispatch({ type: 'increment' }); // count() === 2\n * dispatch({ type: 'reset' }); // count() === 0\n * ```\n */\nexport function createReducer<S, A>(\n reducer: (state: S, action: A) => S,\n initialState: S,\n): [state: SignalGetter<S>, dispatch: Dispatch<A>] {\n const [state, setState] = createSignal(initialState);\n\n const dispatch: Dispatch<A> = (action) => {\n setState((prev) => reducer(prev, action));\n };\n\n return [state, dispatch];\n}\n","/**\n * Forma Reactive - Suspense Context\n *\n * Shared context stack for Suspense boundaries. Lives in the reactive layer\n * (not DOM) so that createResource can import it without circular dependencies.\n *\n * The pattern mirrors the lifecycle context stack in component/define.ts.\n */\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface SuspenseContext {\n /** Increment when a resource starts loading inside this boundary. */\n increment(): void;\n /** Decrement when a resource resolves/rejects inside this boundary. */\n decrement(): void;\n}\n\n// ---------------------------------------------------------------------------\n// Context stack\n// ---------------------------------------------------------------------------\n\nlet currentSuspenseContext: SuspenseContext | null = null;\nconst suspenseStack: (SuspenseContext | null)[] = [];\n\nexport function pushSuspenseContext(ctx: SuspenseContext): void {\n suspenseStack.push(currentSuspenseContext);\n currentSuspenseContext = ctx;\n}\n\nexport function popSuspenseContext(): void {\n currentSuspenseContext = suspenseStack.pop() ?? null;\n}\n\n/** Get the current Suspense context (if any). Called by createResource. */\nexport function getSuspenseContext(): SuspenseContext | null {\n return currentSuspenseContext;\n}\n","/**\n * Forma Reactive - Resource\n *\n * Async data fetching primitive with reactive loading/error state.\n * Tracks a source signal and refetches when it changes.\n *\n * SolidJS equivalent: createResource\n * React equivalent: use() + Suspense (React 19), or useSWR/react-query\n */\n\nimport { createSignal, type SignalGetter } from './signal.js';\nimport { internalEffect } from './effect.js';\nimport { untrack } from './untrack.js';\nimport { getSuspenseContext } from './suspense-context.js';\n\nexport interface Resource<T> {\n /** The resolved data (or undefined while loading). */\n (): T | undefined;\n /** True while the fetcher is running. */\n loading: SignalGetter<boolean>;\n /** The error if the fetcher rejected (or undefined). */\n error: SignalGetter<unknown>;\n /** Manually refetch with the current source value. */\n refetch: () => void;\n /** Manually set the data (overrides fetcher result). */\n mutate: (value: T | undefined) => void;\n}\n\nexport interface ResourceOptions<T> {\n /** Initial value before first fetch resolves. */\n initialValue?: T;\n}\n\n/**\n * Create an async resource that fetches data reactively.\n *\n * When `source` changes, the fetcher re-runs automatically.\n * Provides reactive `loading` and `error` signals.\n *\n * ```ts\n * const [userId, setUserId] = createSignal(1);\n *\n * const user = createResource(\n * userId, // source signal\n * (id) => fetch(`/api/users/${id}`).then(r => r.json()), // fetcher\n * );\n *\n * internalEffect(() => {\n * if (user.loading()) console.log('Loading...');\n * else if (user.error()) console.log('Error:', user.error());\n * else console.log('User:', user());\n * });\n *\n * setUserId(2); // automatically refetches\n * ```\n *\n * Without a source signal (static fetch):\n * ```ts\n * const posts = createResource(\n * () => true, // constant source — fetches once\n * () => fetch('/api/posts').then(r => r.json()),\n * );\n * ```\n */\nexport function createResource<T, S = true>(\n source: SignalGetter<S>,\n fetcher: (source: S) => Promise<T>,\n options?: ResourceOptions<T>,\n): Resource<T> {\n const [data, setData] = createSignal<T | undefined>(options?.initialValue);\n const [loading, setLoading] = createSignal(false);\n const [error, setError] = createSignal<unknown>(undefined);\n\n // Capture the Suspense context at creation time (not at fetch time).\n // This is critical because the Suspense boundary pushes/pops its context\n // synchronously during children() execution.\n const suspenseCtx = getSuspenseContext();\n\n let abortController: AbortController | null = null;\n let fetchVersion = 0;\n\n const doFetch = () => {\n // Read source outside tracking to get current value\n const sourceValue = untrack(source);\n\n // Abort previous in-flight request\n if (abortController) {\n abortController.abort();\n }\n const controller = new AbortController();\n abortController = controller;\n\n const version = ++fetchVersion;\n const isLatest = () => version === fetchVersion;\n let suspensePending = false;\n\n // Notify Suspense boundary that a fetch has started\n if (suspenseCtx) {\n suspenseCtx.increment();\n suspensePending = true;\n }\n\n setLoading(true);\n setError(undefined);\n\n Promise.resolve(fetcher(sourceValue))\n .then((result) => {\n // Only apply if this is still the latest fetch and wasn't aborted.\n if (isLatest() && !controller.signal.aborted) {\n setData(() => result);\n }\n })\n .catch((err) => {\n if (isLatest() && !controller.signal.aborted) {\n // Ignore abort errors\n if (err?.name !== 'AbortError') {\n setError(err);\n }\n }\n })\n .finally(() => {\n if (suspensePending) suspenseCtx?.decrement();\n if (isLatest()) {\n setLoading(false);\n if (abortController === controller) {\n abortController = null; // Release controller for GC\n }\n }\n });\n };\n\n // Auto-fetch when source changes\n internalEffect(() => {\n source(); // track the source signal\n doFetch();\n });\n\n // Build the resource object\n const resource = (() => data()) as Resource<T>;\n resource.loading = loading;\n resource.error = error;\n resource.refetch = doFetch;\n resource.mutate = (value) => setData(() => value);\n\n return resource;\n}\n","/**\n * Forma DOM - List\n *\n * Keyed list reconciliation with Longest Increasing Subsequence (LIS).\n * The LIS tells us the maximum set of DOM nodes that can stay in place;\n * only the remaining nodes need to be moved. This minimises DOM operations\n * to exactly `n - LIS_length` moves — provably optimal.\n *\n * Algorithm used by ivi, Inferno, and (with variations) Solid, Vue 3, Svelte.\n *\n * Uses comment-node markers instead of a wrapper <div>, so the list can be\n * placed inside <table>, <ul>, <select>, etc. without breaking semantics.\n *\n * Total module budget: <2KB minified.\n */\n\nimport { createSignal, internalEffect, untrack, __DEV__ } from '../reactive';\nimport { hydrating } from './hydrate.js';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface ReconcileResult<T> {\n nodes: Node[];\n items: T[];\n}\n\nexport interface ListTransitionHooks {\n onInsert?: (node: Node) => void;\n onBeforeRemove?: (node: Node, done: () => void) => void;\n}\n\ninterface CachedItem<T> {\n element: HTMLElement;\n item: T;\n getIndex: () => number;\n setIndex: (v: number) => void;\n}\n\nexport interface CreateListOptions {\n /**\n * How to handle same-key items whose object identity changed.\n * - 'none' (default): keep the existing row node for maximum throughput.\n * - 'rerender': re-render changed rows and patch static row DOM in place.\n */\n updateOnItemChange?: 'none' | 'rerender';\n}\n\n// ---------------------------------------------------------------------------\n// LIS — O(n log n) via patience sorting + binary search\n// ---------------------------------------------------------------------------\n\n/**\n * Find the longest increasing subsequence.\n * Returns indices into the input array.\n * O(n log n) time, O(n) space.\n */\nexport function longestIncreasingSubsequence(arr: number[]): number[] {\n const n = arr.length;\n if (n === 0) return [];\n\n // Pre-allocate typed arrays — avoids V8 array growth overhead on push\n const tails = new Int32Array(n);\n const tailIndices = new Int32Array(n);\n const predecessor = new Int32Array(n).fill(-1);\n let tailsLen = 0;\n\n for (let i = 0; i < n; i++) {\n const val = arr[i]!;\n\n // Binary search: leftmost tail >= val\n let lo = 0, hi = tailsLen;\n while (lo < hi) {\n const mid = (lo + hi) >> 1;\n if (tails[mid]! < val) lo = mid + 1;\n else hi = mid;\n }\n\n tails[lo] = val;\n tailIndices[lo] = i;\n if (lo > 0) predecessor[i] = tailIndices[lo - 1]!;\n if (lo >= tailsLen) tailsLen++;\n }\n\n // Reconstruct — return plain array since callers expect number[]\n const result = new Array<number>(tailsLen);\n let idx = tailIndices[tailsLen - 1]!;\n for (let i = tailsLen - 1; i >= 0; i--) {\n result[i] = idx;\n idx = predecessor[idx]!;\n }\n\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// reconcileList — low-level keyed reconciler\n// ---------------------------------------------------------------------------\n\n/** Below this threshold, use flat array scan instead of Map for better cache locality. */\nconst SMALL_LIST_THRESHOLD = 32;\nconst ABORT_SYM = Symbol.for('forma-abort');\nconst CACHE_SYM = Symbol.for('forma-attr-cache');\nconst DYNAMIC_CHILD_SYM = Symbol.for('forma-dynamic-child');\n\nfunction canPatchStaticElement(target: Node, source: Node): target is HTMLElement {\n return target instanceof HTMLElement\n && source instanceof HTMLElement\n && target.tagName === source.tagName\n && !(target as any)[ABORT_SYM]\n && !(target as any)[CACHE_SYM]\n && !(target as any)[DYNAMIC_CHILD_SYM]\n && !(source as any)[ABORT_SYM]\n && !(source as any)[CACHE_SYM]\n && !(source as any)[DYNAMIC_CHILD_SYM];\n}\n\nfunction patchStaticElement(target: HTMLElement, source: HTMLElement): void {\n // Sync attributes (events/reactive bindings are excluded by canPatchStaticElement).\n const sourceAttrNames = new Set<string>();\n for (const attr of Array.from(source.attributes)) {\n sourceAttrNames.add(attr.name);\n if (target.getAttribute(attr.name) !== attr.value) {\n target.setAttribute(attr.name, attr.value);\n }\n }\n for (const attr of Array.from(target.attributes)) {\n if (!sourceAttrNames.has(attr.name)) {\n target.removeAttribute(attr.name);\n }\n }\n\n // Move freshly rendered children into the existing keyed node.\n target.replaceChildren(...Array.from(source.childNodes));\n}\n\n/**\n * Small-list reconciler: uses flat arrays + indexOf instead of Map/Set.\n * For < 32 items, linear scan is faster than hash computation overhead.\n */\nfunction reconcileSmall<T>(\n parent: Node,\n oldItems: T[],\n newItems: T[],\n oldNodes: Node[],\n keyFn: (item: T) => string | number,\n createFn: (item: T) => Node,\n updateFn: (node: Node, item: T) => void,\n beforeNode?: Node | null,\n hooks?: ListTransitionHooks,\n): ReconcileResult<T> {\n const oldLen = oldItems.length;\n const newLen = newItems.length;\n\n // Build flat arrays for old keys/nodes — better cache locality than Map\n const oldKeys: (string | number)[] = new Array(oldLen);\n for (let i = 0; i < oldLen; i++) {\n oldKeys[i] = keyFn(oldItems[i]!);\n }\n\n // Classify each new item: find matching old index via linear scan\n const oldIndices = new Array<number>(newLen);\n const oldUsed = new Uint8Array(oldLen); // 0 = unused, 1 = used\n\n for (let i = 0; i < newLen; i++) {\n const key = keyFn(newItems[i]!);\n let found = -1;\n for (let j = 0; j < oldLen; j++) {\n if (!oldUsed[j] && oldKeys[j] === key) {\n found = j;\n oldUsed[j] = 1;\n break;\n }\n }\n oldIndices[i] = found;\n }\n\n // Remove old items not reused\n for (let i = 0; i < oldLen; i++) {\n if (!oldUsed[i]) {\n if (hooks?.onBeforeRemove) {\n const node = oldNodes[i]!;\n hooks.onBeforeRemove(node, () => {\n if (node.parentNode) node.parentNode.removeChild(node);\n });\n } else {\n parent.removeChild(oldNodes[i]!);\n }\n }\n }\n\n // Fast path: same keys, same order -> just update, 0 DOM moves\n if (oldLen === newLen) {\n let allSameOrder = true;\n for (let i = 0; i < newLen; i++) {\n if (oldIndices[i] !== i) {\n allSameOrder = false;\n break;\n }\n }\n if (allSameOrder) {\n const nodes = new Array<Node>(newLen);\n for (let i = 0; i < newLen; i++) {\n const node = oldNodes[i]!;\n updateFn(node, newItems[i]!);\n nodes[i] = node;\n }\n return { nodes, items: newItems };\n }\n }\n\n // LIS for minimum moves (still needed even for small lists)\n const reusedIndices: number[] = [];\n const reusedPositions: number[] = [];\n for (let i = 0; i < newLen; i++) {\n if (oldIndices[i] !== -1) {\n reusedIndices.push(oldIndices[i]!);\n reusedPositions.push(i);\n }\n }\n\n const lisOfReused = longestIncreasingSubsequence(reusedIndices);\n // Use Uint8Array as a bitmap instead of Set for small lists\n const lisFlags = new Uint8Array(newLen);\n for (const li of lisOfReused) {\n lisFlags[reusedPositions[li]!] = 1;\n }\n\n // Build result: walk right-to-left for stable insertBefore targets\n const newNodes = new Array<Node>(newLen);\n let nextSibling: Node | null = beforeNode ?? null;\n\n for (let i = newLen - 1; i >= 0; i--) {\n let node: Node;\n let isNew = false;\n\n if (oldIndices[i] === -1) {\n node = createFn(newItems[i]!);\n isNew = true;\n } else {\n node = oldNodes[oldIndices[i]!]!;\n updateFn(node, newItems[i]!);\n\n if (lisFlags[i]) {\n newNodes[i] = node;\n nextSibling = node;\n continue;\n }\n }\n\n if (nextSibling) {\n parent.insertBefore(node, nextSibling);\n } else {\n parent.appendChild(node);\n }\n\n if (isNew) hooks?.onInsert?.(node);\n\n newNodes[i] = node;\n nextSibling = node;\n }\n\n return { nodes: newNodes, items: newItems };\n}\n\n/**\n * Reconcile a DOM parent's children to match a new array of items.\n * Uses keyed reconciliation with LIS for minimum DOM operations.\n *\n * For small lists (< 32 items), uses a flat array scan path that avoids\n * Map/Set hash overhead and provides better cache locality.\n *\n * @param parent - The container DOM element\n * @param oldItems - Previous array (from last reconciliation)\n * @param newItems - New array to render\n * @param oldNodes - Previous DOM nodes array\n * @param keyFn - Extracts a unique key from each item\n * @param createFn - Creates a new DOM node for an item\n * @param updateFn - Updates an existing DOM node with new item data\n * @param beforeNode - Optional boundary marker. When provided, new nodes are\n * inserted before this node instead of appended to parent.\n * This allows the reconciler to operate within a range\n * delimited by comment markers.\n * @returns Object with new nodes array and items array for next call\n */\nexport function reconcileList<T>(\n parent: Node,\n oldItems: T[],\n newItems: T[],\n oldNodes: Node[],\n keyFn: (item: T) => string | number,\n createFn: (item: T) => Node,\n updateFn: (node: Node, item: T) => void,\n beforeNode?: Node | null,\n hooks?: ListTransitionHooks,\n): ReconcileResult<T> {\n const oldLen = oldItems.length;\n const newLen = newItems.length;\n\n // --- Trivial: new is empty -> remove all ---\n if (newLen === 0) {\n for (let i = 0; i < oldLen; i++) {\n if (hooks?.onBeforeRemove) {\n const node = oldNodes[i]!;\n hooks.onBeforeRemove(node, () => {\n if (node.parentNode) node.parentNode.removeChild(node);\n });\n } else {\n parent.removeChild(oldNodes[i]!);\n }\n }\n return { nodes: [], items: [] };\n }\n\n // --- Trivial: old is empty -> create all ---\n if (oldLen === 0) {\n const nodes = new Array<Node>(newLen);\n for (let i = 0; i < newLen; i++) {\n const node = createFn(newItems[i]!);\n if (beforeNode) {\n parent.insertBefore(node, beforeNode);\n } else {\n parent.appendChild(node);\n }\n hooks?.onInsert?.(node);\n nodes[i] = node;\n }\n return { nodes, items: newItems };\n }\n\n // --- Small list path: flat array scan, no Map/Set overhead ---\n if (oldLen < SMALL_LIST_THRESHOLD) {\n return reconcileSmall(parent, oldItems, newItems, oldNodes, keyFn, createFn, updateFn, beforeNode, hooks);\n }\n\n // --- Large list path: Map-based approach ---\n const oldKeyMap = new Map<string | number, number>();\n for (let i = 0; i < oldLen; i++) {\n oldKeyMap.set(keyFn(oldItems[i]!), i);\n }\n\n // --- Classify each new item: reuse or create ---\n // Use Uint8Array bitmap instead of Set for O(1) lookup without hash overhead\n const oldIndices = new Array<number>(newLen); // -1 means new item\n const oldUsed = new Uint8Array(oldLen);\n\n for (let i = 0; i < newLen; i++) {\n const key = keyFn(newItems[i]!);\n const oldIdx = oldKeyMap.get(key);\n if (oldIdx !== undefined) {\n oldIndices[i] = oldIdx;\n oldUsed[oldIdx] = 1;\n } else {\n oldIndices[i] = -1;\n }\n }\n\n // --- Remove old items not in new array ---\n for (let i = 0; i < oldLen; i++) {\n if (!oldUsed[i]) {\n if (hooks?.onBeforeRemove) {\n const node = oldNodes[i]!;\n hooks.onBeforeRemove(node, () => {\n if (node.parentNode) node.parentNode.removeChild(node);\n });\n } else {\n parent.removeChild(oldNodes[i]!);\n }\n }\n }\n\n // --- Fast path: same keys, same order -> just update, 0 DOM moves ---\n if (oldLen === newLen) {\n let allSameOrder = true;\n for (let i = 0; i < newLen; i++) {\n if (oldIndices[i] !== i) {\n allSameOrder = false;\n break;\n }\n }\n if (allSameOrder) {\n const nodes = new Array<Node>(newLen);\n for (let i = 0; i < newLen; i++) {\n const node = oldNodes[i]!;\n updateFn(node, newItems[i]!);\n nodes[i] = node;\n }\n return { nodes, items: newItems };\n }\n }\n\n // --- Find LIS of old indices (reused items only) ---\n const reusedIndices: number[] = [];\n const reusedPositions: number[] = []; // position in new array\n for (let i = 0; i < newLen; i++) {\n if (oldIndices[i] !== -1) {\n reusedIndices.push(oldIndices[i]!);\n reusedPositions.push(i);\n }\n }\n\n const lisOfReused = longestIncreasingSubsequence(reusedIndices);\n // Use Uint8Array bitmap instead of Set for O(1) lookup without hash overhead\n const lisFlags = new Uint8Array(newLen);\n for (const li of lisOfReused) {\n lisFlags[reusedPositions[li]!] = 1;\n }\n\n // --- Build result: walk right-to-left for stable insertBefore targets ---\n const newNodes = new Array<Node>(newLen);\n let nextSibling: Node | null = beforeNode ?? null;\n\n for (let i = newLen - 1; i >= 0; i--) {\n let node: Node;\n let isNew = false;\n\n if (oldIndices[i] === -1) {\n // NEW: create and insert\n node = createFn(newItems[i]!);\n isNew = true;\n } else {\n // REUSE: update content\n node = oldNodes[oldIndices[i]!]!;\n updateFn(node, newItems[i]!);\n\n if (lisFlags[i]) {\n // LIS item: already in correct relative position, don't move\n newNodes[i] = node;\n nextSibling = node;\n continue;\n }\n }\n\n // Insert/move into position\n if (nextSibling) {\n parent.insertBefore(node, nextSibling);\n } else {\n parent.appendChild(node);\n }\n\n if (isNew) hooks?.onInsert?.(node);\n\n newNodes[i] = node;\n nextSibling = node;\n }\n\n return { nodes: newNodes, items: newItems };\n}\n\n// ---------------------------------------------------------------------------\n// createList — high-level reactive API\n// ---------------------------------------------------------------------------\n\n/**\n * Create a reactively-bound list of DOM elements with keyed reconciliation.\n *\n * Returns a `DocumentFragment` containing two comment markers\n * (`<!--forma-list-start-->` and `<!--forma-list-end-->`) that delimit the\n * list's range in the DOM. All managed elements live between these markers.\n *\n * This avoids a wrapper `<div>` which would break `<table>`, `<ul>`,\n * `<select>` semantics and pollute the DOM.\n *\n * When the `items` signal changes, only the minimal set of DOM mutations is\n * performed using the LIS algorithm:\n * - New keys: create elements via `renderFn`\n * - Removed keys: remove elements from DOM\n * - Moved keys: reorder elements using minimum moves (n - LIS)\n * - Same keys: keep row nodes and update index signals\n * (or re-render row content when `updateOnItemChange: 'rerender'`)\n *\n * @param items Signal getter returning the current array of items.\n * @param keyFn Extracts a unique key from each item.\n * @param renderFn Renders a single item. Receives the item and a reactive index getter.\n * @returns A DocumentFragment to insert into the DOM. The fragment includes\n * start/end comment markers and any initial list items.\n *\n * ```ts\n * const frag = createList(\n * todos,\n * (t) => t.id,\n * (todo, index) => h('li', null, () => `${index() + 1}. ${todo.text}`),\n * );\n * container.appendChild(frag);\n * ```\n */\nexport function createList<T>(\n items: () => T[],\n keyFn: (item: T) => string | number,\n renderFn: (item: T, index: () => number) => HTMLElement,\n options?: CreateListOptions,\n): DocumentFragment {\n if (hydrating) {\n return { type: 'list', items, keyFn, renderFn, options } as unknown as DocumentFragment;\n }\n\n const startMarker = document.createComment('forma-list-start');\n const endMarker = document.createComment('forma-list-end');\n\n const fragment = document.createDocumentFragment();\n fragment.appendChild(startMarker);\n fragment.appendChild(endMarker);\n\n // Cache: key -> { element, item, setIndex }\n let cache = new Map<string | number, CachedItem<T>>();\n let currentNodes: Node[] = [];\n let currentItems: T[] = [];\n const updateOnItemChange = options?.updateOnItemChange ?? 'none';\n\n internalEffect(() => {\n const newItems = items();\n\n // The parent is discovered lazily: once the fragment has been inserted\n // into the live DOM the markers have a parentNode.\n const parent = startMarker.parentNode;\n if (!parent) {\n // Markers are not yet in the DOM — nothing to reconcile.\n // This can happen if the effect fires synchronously before mount.\n return;\n }\n\n // Edge case: non-array\n if (!Array.isArray(newItems)) {\n if (__DEV__) {\n console.warn('[forma] createList: value is not an array, treating as empty');\n }\n // Remove all nodes between the markers\n for (const node of currentNodes) {\n if (node.parentNode === parent) parent.removeChild(node);\n }\n cache = new Map();\n currentNodes = [];\n currentItems = [];\n return;\n }\n\n // Filter nullish items — avoid array allocation when no nulls found (common case)\n let cleanItems: T[] = newItems;\n for (let i = 0; i < newItems.length; i++) {\n if (newItems[i] == null) {\n cleanItems = newItems.filter(item => item != null);\n break;\n }\n }\n\n // Dev-mode duplicate key detection\n if (__DEV__) {\n const seen = new Set<string | number>();\n for (const item of cleanItems) {\n const key = keyFn(item);\n if (seen.has(key)) {\n console.warn('[forma] createList: duplicate key detected:', key);\n }\n seen.add(key);\n }\n }\n\n const updateRow = updateOnItemChange === 'rerender'\n ? (node: Node, item: T): void => {\n const key = keyFn(item);\n const cached = cache.get(key);\n if (!cached) return;\n if (cached.item === item) return;\n cached.item = item;\n\n if (!(node instanceof HTMLElement)) return;\n if ((node as any)[ABORT_SYM] || (node as any)[CACHE_SYM] || (node as any)[DYNAMIC_CHILD_SYM]) {\n return;\n }\n\n const next = untrack(() => renderFn(item, cached.getIndex));\n if (canPatchStaticElement(node, next)) {\n patchStaticElement(node, next);\n cached.element = node;\n }\n }\n : (_node: Node, item: T): void => {\n const key = keyFn(item);\n const cached = cache.get(key);\n if (cached) cached.item = item;\n };\n\n const result = reconcileList<T>(\n parent,\n currentItems,\n cleanItems,\n currentNodes,\n keyFn,\n // createFn: create element + cache entry\n (item) => {\n const key = keyFn(item);\n const [getIndex, setIndex] = createSignal(0);\n // Prevent child effects created during render from being nested under\n // the reconciler effect, which can stall their updates on reorders.\n const element = untrack(() => renderFn(item, getIndex));\n cache.set(key, { element, item, getIndex, setIndex });\n return element;\n },\n updateRow,\n // beforeNode: insert items before the end marker\n endMarker,\n );\n\n // Rebuild cache + update index signals in a single pass.\n // Avoids .map() array allocation + Set construction from the previous approach.\n const newCache = new Map<string | number, CachedItem<T>>();\n for (let i = 0; i < cleanItems.length; i++) {\n const key = keyFn(cleanItems[i]!);\n const cached = cache.get(key);\n if (cached) {\n cached.setIndex(i);\n newCache.set(key, cached);\n }\n }\n cache = newCache;\n\n currentNodes = result.nodes;\n currentItems = result.items;\n });\n\n return fragment;\n}\n","/**\n * Forma DOM - Show (Conditional Rendering)\n *\n * Surgically swaps a single DOM node based on a boolean signal.\n * Uses comment markers (like createList) for zero-wrapper rendering.\n * When condition changes, only ONE node is removed and ONE inserted.\n *\n * Each branch is rendered inside createRoot + untrack so that:\n * 1. Inner effects survive when the show effect re-runs (alien-signals\n * would otherwise dispose child effects linked to the parent).\n * 2. Inner effects are explicitly disposed when the branch changes.\n *\n * SolidJS equivalent: <Show when={} fallback={}>\n */\n\nimport { internalEffect, untrack, createRoot } from 'forma/reactive';\nimport { hydrating, type ShowDescriptor } from './hydrate.js';\n\n/**\n * Conditionally render content based on a reactive boolean.\n *\n * ```ts\n * const [show, setShow] = createSignal(true);\n * const fragment = createShow(\n * show,\n * () => h('div', null, 'Visible!'),\n * () => h('div', null, 'Hidden fallback'),\n * );\n * container.appendChild(fragment);\n * ```\n *\n * Returns a DocumentFragment with comment markers. The content between\n * markers is swapped reactively when `when()` changes.\n */\nexport function createShow(\n when: () => unknown,\n thenFn: () => Node,\n elseFn?: () => Node,\n): DocumentFragment {\n if (hydrating) {\n const branch = when() ? thenFn() : (elseFn?.() ?? null);\n return {\n type: 'show',\n condition: when,\n whenTrue: thenFn,\n whenFalse: elseFn,\n initialBranch: branch,\n } as unknown as DocumentFragment;\n }\n\n const startMarker = document.createComment('forma-show');\n const endMarker = document.createComment('/forma-show');\n const fragment = document.createDocumentFragment();\n fragment.appendChild(startMarker);\n fragment.appendChild(endMarker);\n\n let currentNode: Node | null = null;\n let lastTruthy: boolean | null = null;\n let currentDispose: (() => void) | null = null;\n\n const showDispose = internalEffect(() => {\n const truthy = !!when();\n const DEBUG = typeof (globalThis as any).__FORMA_DEBUG__ !== 'undefined';\n const DEBUG_LABEL = DEBUG ? thenFn.toString().slice(0, 60) : '';\n\n if (truthy === lastTruthy) {\n if (DEBUG) console.log('[forma:show] skip (same)', truthy, DEBUG_LABEL);\n return;\n }\n if (DEBUG) console.log('[forma:show]', lastTruthy, '→', truthy, DEBUG_LABEL);\n lastTruthy = truthy;\n\n const parent = startMarker.parentNode;\n if (!parent) {\n if (DEBUG) console.warn('[forma:show] parentNode is null! skipping.', DEBUG_LABEL);\n return;\n }\n if (DEBUG) console.log('[forma:show] parent:', parent.nodeName, 'inDoc:', document.contains(parent as any));\n\n // Dispose previous branch's inner effects\n if (currentDispose) {\n currentDispose();\n currentDispose = null;\n }\n\n // Remove current node. If it was a DocumentFragment, its children\n // transferred to the DOM on insertion and the fragment is now detached.\n // In that case, clear everything between the markers.\n if (currentNode) {\n if (currentNode.parentNode === parent) {\n parent.removeChild(currentNode);\n } else {\n while (startMarker.nextSibling && startMarker.nextSibling !== endMarker) {\n parent.removeChild(startMarker.nextSibling);\n }\n }\n }\n\n // Render inside createRoot so child effects are tracked for disposal,\n // and inside untrack so they are NOT linked to the show effect\n // (alien-signals disposes child effects on parent re-run, which would\n // kill reactivity in branches whose condition stays the same).\n const branchFn = truthy ? thenFn : elseFn;\n if (branchFn) {\n let branchDispose!: () => void;\n currentNode = createRoot((dispose) => {\n branchDispose = dispose;\n return untrack(() => branchFn());\n });\n currentDispose = branchDispose;\n } else {\n currentNode = null;\n }\n\n if (currentNode) {\n parent.insertBefore(currentNode, endMarker);\n }\n });\n\n // Attach cleanup so external disposal can clean up the branch and effect.\n (fragment as any).__showDispose = () => {\n showDispose();\n if (currentDispose) {\n currentDispose();\n currentDispose = null;\n }\n };\n\n return fragment;\n}\n","/**\n * FormaJS DOM - Hydrate\n *\n * Descriptor-based island hydration. During hydration, h() returns plain\n * descriptor objects instead of DOM elements. A top-down walk (adoptNode)\n * then matches these descriptors against SSR DOM to attach events and\n * reactive bindings. No DOM elements are created during hydration.\n */\n\nimport { internalEffect, createSignal, untrack, __DEV__ } from 'forma/reactive';\nimport { h } from './element.js';\nimport { reconcileList, createList } from './list.js';\nimport { createShow } from './show.js';\n\n// Same symbol identity as element.ts — Symbol.for() guarantees cross-module\n// sharing so cleanup(el) in element.ts aborts controllers created here.\nconst ABORT_SYM = Symbol.for('forma-abort');\n\n// ---------------------------------------------------------------------------\n// Hydration state — module-level boolean\n// ---------------------------------------------------------------------------\n\n/** True while hydration is in progress. Checked by h() to branch. */\nexport let hydrating = false;\n\n/**\n * Set the hydrating state. Used internally by hydration functions.\n * Required because `export let` cannot be reassigned from outside the module.\n */\nexport function setHydrating(value: boolean): void {\n hydrating = value;\n}\n\n// ---------------------------------------------------------------------------\n// Descriptor interfaces\n// ---------------------------------------------------------------------------\n\n/** Descriptor returned by h() during hydration instead of a real Element. */\nexport interface HydrationDescriptor {\n type: 'element';\n tag: string;\n props: Record<string, unknown> | null;\n children: unknown[];\n}\n\n/** Descriptor returned by createShow() during hydration. */\nexport interface ShowDescriptor {\n type: 'show';\n condition: () => unknown;\n whenTrue: () => unknown;\n whenFalse?: () => unknown;\n initialBranch: unknown;\n}\n\n/** Descriptor returned by createList() during hydration. */\nexport interface ListDescriptor {\n type: 'list';\n items: () => unknown[];\n keyFn: (item: unknown) => string | number;\n renderFn: (item: unknown, index: () => number) => HTMLElement;\n options?: Record<string, unknown>;\n}\n\n/** Maps built by collectMarkers() for O(1) marker lookup during adoption. */\nexport interface MarkerMap {\n text: Map<number, Text>;\n show: Map<number, { start: Comment; end: Comment; cachedContent: DocumentFragment | null }>;\n list: Map<number, { start: Comment; end: Comment }>;\n}\n\n// ---------------------------------------------------------------------------\n// Type guards\n// ---------------------------------------------------------------------------\n\n/** Check if a value is a HydrationDescriptor. */\nexport function isDescriptor(v: unknown): v is HydrationDescriptor {\n return v != null && typeof v === 'object' && 'type' in v && v.type === 'element';\n}\n\n/** Check if a value is a ShowDescriptor. */\nexport function isShowDescriptor(v: unknown): v is ShowDescriptor {\n return v != null && typeof v === 'object' && 'type' in v && v.type === 'show';\n}\n\n/** Check if a value is a ListDescriptor. */\nexport function isListDescriptor(v: unknown): v is ListDescriptor {\n return v != null && typeof v === 'object' && 'type' in v && v.type === 'list';\n}\n\n// ---------------------------------------------------------------------------\n// collectMarkers() — single-pass TreeWalker\n// ---------------------------------------------------------------------------\n\n/**\n * Walk the DOM under `root` once, collecting text and show markers into a\n * MarkerMap for O(1) lookup during adoptNode().\n *\n * Text markers: `<!--f:t0-->`, `<!--f:t1-->`, ... followed by a Text node\n * Show markers: `<!--f:s0-->` ... `<!--/f:s0-->` pairs\n */\nexport function collectMarkers(root: Element): MarkerMap {\n const text = new Map<number, Text>();\n const show = new Map<number, { start: Comment; end: Comment; cachedContent: DocumentFragment | null }>();\n const list = new Map<number, { start: Comment; end: Comment }>();\n\n // Pending show-start comments keyed by index, waiting for their closing marker\n const pendingShow = new Map<number, Comment>();\n // Pending list-start comments keyed by index, waiting for their closing marker\n const pendingList = new Map<number, Comment>();\n\n const walker = document.createTreeWalker(root, NodeFilter.SHOW_ALL, {\n acceptNode(node) {\n // Skip child island subtrees (REJECT = skip node AND all descendants)\n if (node !== root && node.nodeType === 1 &&\n (node as Element).hasAttribute('data-forma-island')) {\n return NodeFilter.FILTER_REJECT;\n }\n // Only process comments and text nodes\n if (node.nodeType === Node.COMMENT_NODE || node.nodeType === Node.TEXT_NODE) {\n return NodeFilter.FILTER_ACCEPT;\n }\n // Elements: skip the node itself but walk into children\n return NodeFilter.FILTER_SKIP;\n }\n });\n\n while (walker.nextNode()) {\n const node = walker.currentNode;\n\n if (node.nodeType === Node.COMMENT_NODE) {\n const data = (node as Comment).data;\n\n // Text marker: \"f:t<index>\"\n if (data.length >= 4 && data.charCodeAt(0) === 102 /* f */ && data.charCodeAt(1) === 58 /* : */ && data.charCodeAt(2) === 116 /* t */) {\n const idx = parseInt(data.slice(3), 10);\n if (!isNaN(idx)) {\n // The text node is the next sibling\n const next = node.nextSibling;\n if (next && next.nodeType === Node.TEXT_NODE) {\n text.set(idx, next as Text);\n }\n }\n continue;\n }\n\n // Show opening marker: \"f:s<index>\"\n if (data.length >= 4 && data.charCodeAt(0) === 102 /* f */ && data.charCodeAt(1) === 58 /* : */ && data.charCodeAt(2) === 115 /* s */) {\n const idx = parseInt(data.slice(3), 10);\n if (!isNaN(idx)) {\n pendingShow.set(idx, node as Comment);\n }\n continue;\n }\n\n // Show closing marker: \"/f:s<index>\"\n if (data.length >= 5 && data.charCodeAt(0) === 47 /* / */ && data.charCodeAt(1) === 102 /* f */ && data.charCodeAt(2) === 58 /* : */ && data.charCodeAt(3) === 115 /* s */) {\n const idx = parseInt(data.slice(4), 10);\n if (!isNaN(idx)) {\n const start = pendingShow.get(idx);\n if (start) {\n show.set(idx, { start, end: node as Comment, cachedContent: null });\n pendingShow.delete(idx);\n }\n }\n continue;\n }\n\n // List opening marker: \"f:l<index>\"\n if (data.length >= 4 && data.charCodeAt(0) === 102 /* f */ && data.charCodeAt(1) === 58 /* : */ && data.charCodeAt(2) === 108 /* l */) {\n const idx = parseInt(data.slice(3), 10);\n if (!isNaN(idx)) {\n pendingList.set(idx, node as Comment);\n }\n continue;\n }\n\n // List closing marker: \"/f:l<index>\"\n if (data.length >= 5 && data.charCodeAt(0) === 47 /* / */ && data.charCodeAt(1) === 102 /* f */ && data.charCodeAt(2) === 58 /* : */ && data.charCodeAt(3) === 108 /* l */) {\n const idx = parseInt(data.slice(4), 10);\n if (!isNaN(idx)) {\n const start = pendingList.get(idx);\n if (start) {\n list.set(idx, { start, end: node as Comment });\n pendingList.delete(idx);\n }\n }\n continue;\n }\n }\n }\n\n return { text, show, list };\n}\n\n// ---------------------------------------------------------------------------\n// applyDynamicProps()\n// ---------------------------------------------------------------------------\n\n/**\n * Attach event handlers and reactive attribute bindings to an existing\n * SSR element. Static (non-function) props are skipped because they are\n * already baked into the server HTML.\n */\nexport function applyDynamicProps(el: Element, props: Record<string, unknown> | null): void {\n if (!props) return;\n\n for (const key in props) {\n const value = props[key];\n\n // Skip non-function values — they are static and already in the SSR HTML\n if (typeof value !== 'function') continue;\n\n // Event handlers: onXxx — use AbortController so cleanup(el) removes them\n if (key.charCodeAt(0) === 111 /* o */ && key.charCodeAt(1) === 110 /* n */ && key.length > 2) {\n let ac = (el as any)[ABORT_SYM] as AbortController | undefined;\n if (!ac) {\n ac = new AbortController();\n (el as any)[ABORT_SYM] = ac;\n }\n el.addEventListener(key.slice(2).toLowerCase(), value as EventListener, { signal: ac.signal });\n continue;\n }\n\n // Reactive attribute binding (function, non-event)\n const fn = value as () => unknown;\n const attrKey = key; // capture for closure\n internalEffect(() => {\n const v = fn();\n if (v === false || v == null) {\n el.removeAttribute(attrKey);\n } else if (v === true) {\n el.setAttribute(attrKey, '');\n } else {\n el.setAttribute(attrKey, String(v));\n }\n });\n }\n}\n\n// ---------------------------------------------------------------------------\n// descriptorToElement()\n// ---------------------------------------------------------------------------\n\n/**\n * Convert any hydration-mode value (descriptor, show, list, or Node) back\n * into a real DOM Node. Used when SSR content mismatches client state and\n * the framework needs to create fresh DOM from captured descriptors.\n *\n * Temporarily exits hydration mode so h(), createShow(), createList()\n * create real elements with reactive bindings.\n */\nexport function ensureNode(value: unknown): Node | null {\n if (value instanceof Node) return value;\n if (value == null || value === false || value === true) return null;\n if (typeof value === 'string') return new Text(value);\n if (typeof value === 'number') return new Text(String(value));\n if (isDescriptor(value)) return descriptorToElement(value);\n if (isShowDescriptor(value)) {\n const prevH = hydrating;\n hydrating = false;\n try {\n return createShow(\n value.condition,\n () => ensureNode(value.whenTrue()) ?? document.createComment('empty'),\n value.whenFalse\n ? () => ensureNode(value.whenFalse!()) ?? document.createComment('empty')\n : undefined,\n );\n } finally {\n hydrating = prevH;\n }\n }\n if (isListDescriptor(value)) {\n const prevH = hydrating;\n hydrating = false;\n try {\n return createList(value.items, value.keyFn, value.renderFn, value.options);\n } finally {\n hydrating = prevH;\n }\n }\n return null;\n}\n\n/**\n * Convert a HydrationDescriptor back into a real DOM Element by calling h().\n * Used as a fallback when SSR DOM is missing or mismatched.\n *\n * Temporarily exits hydration mode so h() creates real elements.\n * Handles nested ShowDescriptor and ListDescriptor children by converting\n * them to real reactive primitives (createShow, createList).\n */\nexport function descriptorToElement(desc: HydrationDescriptor): Element {\n const prevHydrating = hydrating;\n hydrating = false;\n\n try {\n // Map children: recurse for nested descriptors, convert Show/List\n const children = desc.children.map((child) => {\n if (isDescriptor(child)) return descriptorToElement(child);\n if (isShowDescriptor(child)) return ensureNode(child);\n if (isListDescriptor(child)) return ensureNode(child);\n return child;\n });\n\n return h(desc.tag, desc.props, ...children);\n } finally {\n hydrating = prevHydrating;\n }\n}\n\n// ---------------------------------------------------------------------------\n// DOM cursor helpers for adoptNode\n// ---------------------------------------------------------------------------\n\n/** Check if comment data is an island start marker (f:iN). */\nfunction isIslandStart(data: string): boolean {\n return data.length >= 4 && data.charCodeAt(0) === 102 /* f */ && data.charCodeAt(1) === 58 /* : */ && data.charCodeAt(2) === 105 /* i */;\n}\n\n/** Check if comment data is a show start marker (f:sN). */\nfunction isShowStart(data: string): boolean {\n return data.length >= 4 && data.charCodeAt(0) === 102 /* f */ && data.charCodeAt(1) === 58 /* : */ && data.charCodeAt(2) === 115 /* s */;\n}\n\n/** Check if comment data is a text marker (f:tN). */\nfunction isTextStart(data: string): boolean {\n return data.length >= 4 && data.charCodeAt(0) === 102 /* f */ && data.charCodeAt(1) === 58 /* : */ && data.charCodeAt(2) === 116 /* t */;\n}\n\n/** Check if comment data is a list start marker (f:lN). */\nfunction isListStart(data: string): boolean {\n return data.length >= 4 && data.charCodeAt(0) === 102 /* f */ && data.charCodeAt(1) === 58 /* : */ && data.charCodeAt(2) === 108 /* l */;\n}\n\n/** Find the closing comment marker for a start marker (e.g., f:i0 → /f:i0). */\nfunction findClosingMarker(start: Comment): Comment | null {\n const closing = '/' + start.data;\n let node: Node | null = start.nextSibling;\n while (node) {\n if (node.nodeType === 8 && (node as Comment).data === closing) {\n return node as Comment;\n }\n node = node.nextSibling;\n }\n return null;\n}\n\n/** Find the first Text node between two comment markers (exclusive). */\nfunction findTextBetween(start: Comment, end: Comment): Text | null {\n let node: Node | null = start.nextSibling;\n while (node && node !== end) {\n if (node.nodeType === 3) return node as Text;\n node = node.nextSibling;\n }\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Show descriptor helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Find the first Element node between two comment markers (exclusive).\n */\nfunction nextElementBetweenMarkers(start: Comment, end: Comment): Element | undefined {\n let node: Node | null = start.nextSibling;\n while (node && node !== end) {\n if (node.nodeType === 1) return node as Element;\n node = node.nextSibling;\n }\n return undefined;\n}\n\n/**\n * Extract all nodes between two comment markers into a DocumentFragment.\n * The markers themselves are left in place.\n */\nfunction extractContentBetweenMarkers(start: Comment, end: Comment): DocumentFragment {\n const frag = document.createDocumentFragment();\n let node = start.nextSibling;\n while (node && node !== end) {\n const next = node.nextSibling;\n frag.appendChild(node);\n node = next;\n }\n return frag;\n}\n\n/**\n * Set up reactive show effect after hydration adoption.\n *\n * During initial hydration, content is adopted in place (no DOM movement).\n * On first toggle, current content is scooped into a cached fragment.\n * Subsequent toggles swap between cached fragments (pure DOM moves, no re-render).\n */\nfunction setupShowEffect(\n desc: ShowDescriptor,\n marker: { start: Comment; end: Comment; cachedContent: DocumentFragment | null },\n): void {\n let currentCondition = !!desc.condition();\n let thenFragment: DocumentFragment | null = null;\n let elseFragment: DocumentFragment | null = null;\n\n // Reverse mismatch: SSR is empty but client condition is true.\n // Insert truthy content immediately so the user sees correct content.\n const hasSSRContent = marker.start.nextSibling !== marker.end;\n if (!hasSSRContent && currentCondition) {\n if (__DEV__) console.warn('[forma] Hydration: show condition mismatch — SSR empty but client condition is true');\n const trueBranch = desc.whenTrue();\n if (trueBranch instanceof Node) {\n marker.start.parentNode!.insertBefore(trueBranch, marker.end);\n }\n }\n\n internalEffect(() => {\n const next = !!desc.condition();\n if (next === currentCondition) return;\n currentCondition = next;\n\n const parent = marker.start.parentNode;\n if (!parent) return;\n\n // Cache current content\n const current = extractContentBetweenMarkers(marker.start, marker.end);\n if (!next) {\n thenFragment = current;\n } else {\n elseFragment = current;\n }\n\n // Insert the appropriate branch: cached fragment if available, else factory\n let branch: unknown = next\n ? (thenFragment ?? desc.whenTrue())\n : (desc.whenFalse ? (elseFragment ?? desc.whenFalse()) : null);\n\n if (next && thenFragment) thenFragment = null; // consumed\n if (!next && elseFragment) elseFragment = null; // consumed\n\n // Convert hydration descriptors to real DOM (happens when SSR/client\n // branch mismatch causes the factory to return a pre-computed descriptor)\n if (branch != null && !(branch instanceof Node)) {\n branch = ensureNode(branch);\n }\n\n if (branch instanceof Node) {\n parent.insertBefore(branch, marker.end);\n }\n });\n}\n\n// ---------------------------------------------------------------------------\n// adoptBranchContent() — walk nested show/list descriptors in SSR content\n// ---------------------------------------------------------------------------\n\n/**\n * Recursively adopt the content between show markers against a descriptor\n * that may be a HydrationDescriptor, ShowDescriptor, or ListDescriptor.\n *\n * This handles the case where createShow nests: the outer show's\n * initialBranch is itself a ShowDescriptor (not a plain element), so we\n * need to find inner SSR markers and walk into them.\n */\nfunction adoptBranchContent(\n desc: unknown,\n regionStart: Comment,\n regionEnd: Comment,\n): void {\n if (isDescriptor(desc)) {\n // Plain element — find it between markers and adopt\n const el = nextElementBetweenMarkers(regionStart, regionEnd);\n if (el) adoptNode(desc, el);\n } else if (isShowDescriptor(desc)) {\n // Nested show — find inner show markers between region markers\n let node: ChildNode | null = regionStart.nextSibling;\n while (node && node !== regionEnd) {\n if (node.nodeType === 8 && isShowStart((node as Comment).data)) {\n const innerStart = node as Comment;\n const innerEnd = findClosingMarker(innerStart);\n if (innerEnd) {\n // Recursively adopt the inner show's content\n if (desc.initialBranch) {\n adoptBranchContent(desc.initialBranch, innerStart, innerEnd);\n }\n // Set up the inner show's toggle effect\n setupShowEffect(desc, { start: innerStart, end: innerEnd, cachedContent: null });\n }\n break;\n }\n node = node.nextSibling;\n }\n }\n // ListDescriptor adoption within show markers is handled by the existing\n // list adoption code in adoptNode when it encounters list markers.\n}\n\n// ---------------------------------------------------------------------------\n// adoptNode() — top-down descriptor walk with DOM cursor\n// ---------------------------------------------------------------------------\n\n/**\n * Walk a descriptor tree top-down, matching each descriptor against the\n * corresponding SSR DOM using a childNode cursor. Attaches event handlers\n * and reactive bindings without creating new DOM nodes.\n *\n * The cursor approach handles:\n * - Island markers (<!--f:iN-->): creates real DOM from descriptor\n * - Show markers (<!--f:sN-->): binds show effects or reactive text\n * - Text markers (<!--f:tN-->): binds reactive text effects\n * - Tag mismatches: falls back to descriptorToElement()\n */\nexport function adoptNode(\n desc: HydrationDescriptor,\n ssrEl: Element | undefined,\n): void {\n // Mismatch check\n if (!ssrEl || ssrEl.tagName !== desc.tag.toUpperCase()) {\n if (__DEV__) console.warn(`Hydration mismatch: expected <${desc.tag}>, got <${ssrEl?.tagName?.toLowerCase() ?? 'nothing'}>`);\n const fresh = descriptorToElement(desc);\n if (ssrEl) ssrEl.replaceWith(fresh);\n return;\n }\n\n // Attach dynamic props\n applyDynamicProps(ssrEl, desc.props);\n\n // Walk children via DOM cursor (instead of children[index])\n let cursor: ChildNode | null = ssrEl.firstChild;\n\n for (const child of desc.children) {\n // Skip falsy children\n if (child === false || child == null) continue;\n\n if (isDescriptor(child)) {\n // Skip whitespace-only text nodes\n while (cursor && cursor.nodeType === 3 && !(cursor as Text).data.trim()) {\n cursor = cursor.nextSibling;\n }\n\n // Skip child island elements — they are handled by their own activation\n while (cursor && cursor.nodeType === 1 &&\n (cursor as Element).hasAttribute('data-forma-island')) {\n cursor = cursor.nextSibling;\n }\n\n if (!cursor) {\n // No more DOM nodes — append fresh\n ssrEl.appendChild(descriptorToElement(child));\n continue;\n }\n\n if (cursor.nodeType === 1) {\n // Element node — adopt recursively\n const el = cursor as Element;\n cursor = cursor.nextSibling;\n adoptNode(child, el);\n } else if (cursor.nodeType === 8 && isIslandStart((cursor as Comment).data)) {\n // Island marker — create real DOM and insert before end marker\n const end = findClosingMarker(cursor as Comment);\n const fresh = descriptorToElement(child);\n if (end) {\n end.parentNode!.insertBefore(fresh, end);\n cursor = end.nextSibling;\n } else {\n ssrEl.appendChild(fresh);\n cursor = null;\n }\n } else {\n // Unexpected node — create fresh and append\n ssrEl.appendChild(descriptorToElement(child));\n }\n\n } else if (isShowDescriptor(child)) {\n // Advance cursor to next show marker\n while (cursor && !(cursor.nodeType === 8 && isShowStart((cursor as Comment).data))) {\n cursor = cursor.nextSibling;\n }\n\n if (cursor) {\n const start = cursor as Comment;\n const end = findClosingMarker(start);\n if (end) {\n if (child.initialBranch) {\n // Walk the initial branch against SSR content between markers.\n // initialBranch can be a HydrationDescriptor (element), ShowDescriptor\n // (nested show), or ListDescriptor — adoptBranchContent handles all.\n adoptBranchContent(child.initialBranch, start, end);\n }\n setupShowEffect(child, { start, end, cachedContent: null });\n cursor = end.nextSibling;\n }\n }\n\n } else if (isListDescriptor(child)) {\n // Advance cursor to next list marker\n while (cursor && !(cursor.nodeType === 8 && isListStart((cursor as Comment).data))) {\n cursor = cursor.nextSibling;\n }\n\n if (cursor) {\n const start = cursor as Comment;\n const end = findClosingMarker(start);\n if (end) {\n // Walk DOM between markers, collect SSR elements\n const ssrKeyMap = new Map<string | number, HTMLElement>();\n const ssrElements: HTMLElement[] = [];\n let node: Node | null = start.nextSibling;\n while (node && node !== end) {\n if (node.nodeType === 1) {\n const el = node as HTMLElement;\n ssrElements.push(el);\n const key = el.getAttribute('data-forma-key');\n if (key != null) {\n ssrKeyMap.set(key, el);\n }\n }\n node = node.nextSibling;\n }\n\n // Read current items without tracking (we set up our own effect below)\n const currentItems = untrack(() => child.items()) as any[];\n const listKeyFn = child.keyFn;\n const listRenderFn = child.renderFn;\n\n // Fallback: if no SSR elements have data-forma-key, match by index\n const useIndexFallback = ssrKeyMap.size === 0 && ssrElements.length > 0;\n\n // Match current items to SSR nodes by key (or index fallback)\n const adoptedNodes: Node[] = [];\n const adoptedItems: any[] = [];\n const usedIndices = new Set<number>();\n\n for (let i = 0; i < currentItems.length; i++) {\n const item = currentItems[i];\n const key = listKeyFn(item);\n\n let ssrNode: HTMLElement | undefined;\n if (useIndexFallback) {\n // Index-based matching: SSR elements lack keys, adopt by position\n if (i < ssrElements.length) {\n ssrNode = ssrElements[i];\n usedIndices.add(i);\n }\n } else {\n // Key-based matching: SSR keys from getAttribute() are always strings\n ssrNode = ssrKeyMap.get(String(key));\n if (ssrNode) ssrKeyMap.delete(String(key));\n }\n\n if (ssrNode) {\n // Reuse SSR element\n adoptedNodes.push(ssrNode);\n adoptedItems.push(item);\n } else {\n // Not found in SSR — render fresh, exit hydration mode temporarily\n if (__DEV__) console.warn(`[FormaJS] Hydration: list item key \"${key}\" not found in SSR — rendering fresh`);\n const prevHydrating = hydrating;\n hydrating = false;\n try {\n const [getIndex] = createSignal(i);\n const fresh = listRenderFn(item, getIndex);\n // Insert before end marker\n end.parentNode!.insertBefore(fresh, end);\n adoptedNodes.push(fresh);\n adoptedItems.push(item);\n } finally {\n hydrating = prevHydrating;\n }\n }\n }\n\n // Remove unused SSR nodes (keys that weren't matched, or excess index-based)\n if (useIndexFallback) {\n for (let i = 0; i < ssrElements.length; i++) {\n if (!usedIndices.has(i) && ssrElements[i]!.parentNode) {\n ssrElements[i]!.parentNode!.removeChild(ssrElements[i]!);\n }\n }\n } else {\n for (const [unusedKey, unusedNode] of ssrKeyMap) {\n if (__DEV__) console.warn(`[FormaJS] Hydration: removing extra SSR list item with key \"${unusedKey}\"`);\n if (unusedNode.parentNode) {\n unusedNode.parentNode.removeChild(unusedNode);\n }\n }\n }\n\n // Reorder adopted nodes to match item order (insert before end marker)\n const parent = start.parentNode!;\n for (const adoptedNode of adoptedNodes) {\n parent.insertBefore(adoptedNode, end);\n }\n\n // Set up state for reactive reconciliation.\n // Cache maps key → { element, item, getIndex, setIndex } so that\n // index signals can be updated after reconcileList reorders items\n // (same pattern as the non-hydration createList in list.ts).\n let cache = new Map<string | number, {\n element: HTMLElement;\n item: any;\n getIndex: () => number;\n setIndex: (v: number) => void;\n }>();\n\n // Seed cache with adopted items\n for (let i = 0; i < adoptedItems.length; i++) {\n const item = adoptedItems[i];\n const key = listKeyFn(item);\n const [getIndex, setIndex] = createSignal(i);\n cache.set(key, {\n element: adoptedNodes[i] as HTMLElement,\n item,\n getIndex,\n setIndex,\n });\n }\n\n let reconcileNodes = adoptedNodes.slice();\n let reconcileItems = adoptedItems.slice();\n\n // Attach reactive effect that calls reconcileList for subsequent updates\n internalEffect(() => {\n const newItems = child.items() as any[];\n\n // The parent is discovered lazily: once inserted into the live DOM\n const parent = start.parentNode;\n if (!parent) return;\n\n const result = reconcileList(\n parent,\n reconcileItems,\n newItems,\n reconcileNodes,\n listKeyFn,\n (item: any) => {\n const prevHydrating = hydrating;\n hydrating = false;\n try {\n const key = listKeyFn(item);\n const [getIndex, setIndex] = createSignal(0);\n const element = untrack(() => listRenderFn(item, getIndex));\n cache.set(key, { element, item, getIndex, setIndex });\n return element;\n } finally {\n hydrating = prevHydrating;\n }\n },\n (_node: Node, item: any) => {\n const key = listKeyFn(item);\n const cached = cache.get(key);\n if (cached) cached.item = item;\n },\n end,\n );\n\n // Rebuild cache + update index signals in a single pass\n const newCache = new Map<string | number, typeof cache extends Map<any, infer V> ? V : never>();\n for (let i = 0; i < newItems.length; i++) {\n const key = listKeyFn(newItems[i]!);\n const cached = cache.get(key);\n if (cached) {\n cached.setIndex(i);\n newCache.set(key, cached);\n }\n }\n cache = newCache;\n\n reconcileNodes = result.nodes;\n reconcileItems = result.items;\n });\n\n cursor = end.nextSibling;\n }\n }\n\n } else if (typeof child === 'function') {\n // Reactive binding — could be text (signal getter) or element (returns descriptor).\n // Peek at the return value to determine type before choosing the adoption path.\n while (cursor && cursor.nodeType === 3 && !(cursor as Text).data.trim()) {\n cursor = cursor.nextSibling;\n }\n\n // If cursor is at an element, check whether function returns a descriptor\n if (cursor && cursor.nodeType === 1) {\n const initial = (child as () => unknown)();\n if (isDescriptor(initial)) {\n // Function returned a descriptor — adopt the element at cursor\n const el = cursor as Element;\n cursor = cursor.nextSibling;\n adoptNode(initial, el);\n continue;\n }\n // Not a descriptor — fall through to text handling\n }\n\n if (cursor && cursor.nodeType === 8) {\n const data = (cursor as Comment).data;\n\n if (isTextStart(data)) {\n // Text marker: <!--f:tN-->text<!--/f:tN-->\n const endMarker = findClosingMarker(cursor as Comment);\n let textNode = cursor.nextSibling;\n if (!textNode || textNode.nodeType !== 3) {\n // Defensive fallback: SSR should have emitted a text node between\n // markers. If missing, create one — but warn in dev mode.\n if (__DEV__) console.warn(`[FormaJS] Hydration: created text node for marker ${data} — SSR walker should emit content between markers`);\n const created = document.createTextNode('');\n cursor.parentNode!.insertBefore(created, endMarker || cursor.nextSibling);\n textNode = created;\n }\n internalEffect(() => {\n (textNode as Text).data = String((child as () => unknown)());\n });\n cursor = endMarker ? endMarker.nextSibling : textNode.nextSibling;\n } else if (isShowStart(data)) {\n // Show marker used for reactive text (IR compiled inline ternary as ShowIf)\n const start = cursor as Comment;\n const end = findClosingMarker(start);\n if (end) {\n let textNode = findTextBetween(start, end);\n if (!textNode) {\n // Defensive fallback: SSR should have emitted content between\n // show markers for reactive text. Warn in dev mode.\n if (__DEV__) console.warn(`[FormaJS] Hydration: created text node for show marker ${start.data} — SSR walker should emit content between markers`);\n textNode = document.createTextNode('');\n start.parentNode!.insertBefore(textNode, end);\n }\n internalEffect(() => {\n (textNode as Text).data = String((child as () => unknown)());\n });\n cursor = end.nextSibling;\n } else {\n cursor = cursor.nextSibling;\n }\n } else {\n cursor = cursor.nextSibling;\n }\n } else if (cursor && cursor.nodeType === 3) {\n // Existing text node without markers — bind reactive effect directly\n const textNode = cursor as Text;\n cursor = cursor.nextSibling;\n internalEffect(() => {\n textNode.data = String((child as () => unknown)());\n });\n } else {\n // No cursor (empty parent) or unexpected node — SSR element has no\n // children where a reactive text binding is expected. This means the\n // IR didn't cover this part of the component tree. Warn and create.\n if (__DEV__) console.warn(`[FormaJS] Hydration: created text node in empty <${ssrEl.tagName.toLowerCase()}> — IR may not cover this component`);\n const textNode = document.createTextNode('');\n ssrEl.appendChild(textNode);\n internalEffect(() => {\n textNode.data = String((child as () => unknown)());\n });\n }\n } else if (typeof child === 'string' || typeof child === 'number') {\n // Static text — advance cursor past corresponding text node\n if (cursor && cursor.nodeType === 3) {\n cursor = cursor.nextSibling;\n }\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// hydrateIsland() — full orchestration\n// ---------------------------------------------------------------------------\n\n/**\n * Hydrate an SSR island in-place. Runs the component in hydration mode so\n * h() returns descriptors, then walks the descriptor tree against the SSR DOM\n * to attach event handlers and reactive bindings. No DOM elements are created.\n *\n * The component function MUST be called inside a reactive root (createRoot)\n * so that effects created during adoption are properly tracked.\n *\n * Returns the active root element — usually `target`, but may be a replacement\n * element when the CSR fallback fires (empty island shell replaced by the\n * component's own root element).\n *\n * @param component A function that builds the UI (calls h(), createShow, etc.)\n * @param target The container element with `data-forma-ssr` attribute\n */\nexport function hydrateIsland(component: () => unknown, target: Element): Element {\n // Check if the island has SSR content to hydrate against.\n // An empty island shell (tag + static attrs from compiler, no children)\n // has nothing to hydrate — fall through to CSR mode.\n const hasSSRContent = target.childElementCount > 0 ||\n (target.childNodes.length > 0 &&\n Array.from(target.childNodes).some(n =>\n n.nodeType === 1 || (n.nodeType === 3 && (n as Text).data.trim())));\n\n if (!hasSSRContent) {\n // CSR fallback: SSR emitted an empty shell element for this island.\n // Run the component in normal (non-hydration) mode and replace the\n // shell with the component's own root element.\n if (__DEV__) {\n const name = target.getAttribute('data-forma-component') || 'unknown';\n console.warn(\n `[forma] Island \"${name}\" has no SSR content — falling back to CSR. ` +\n `This means the IR walker did not render content between ISLAND_START and ISLAND_END.`,\n );\n }\n\n const result = component();\n if (result instanceof Element) {\n // Transfer data-forma-* attributes from the shell to the component's root\n for (const attr of Array.from(target.attributes)) {\n if (attr.name.startsWith('data-forma-')) {\n result.setAttribute(attr.name, attr.value);\n }\n }\n target.replaceWith(result);\n return result;\n } else if (result instanceof Node) {\n target.appendChild(result);\n }\n return target;\n }\n\n // 1. Enter hydration mode (h() returns descriptors)\n setHydrating(true);\n\n // 2. Run component — builds descriptor tree, zero DOM work\n let descriptor: unknown;\n try {\n descriptor = component();\n } finally {\n // 3. Exit hydration mode\n setHydrating(false);\n }\n\n // Guard: if component returned nothing (e.g. mock fn in tests, or simple\n // islands that only set up effects), skip adoption entirely.\n if (!descriptor || !isDescriptor(descriptor)) {\n target.removeAttribute('data-forma-ssr');\n return target;\n }\n\n // 4. Walk descriptor tree top-down against SSR DOM.\n // For island activation: the target IS the island root element (has\n // data-forma-island). Adopt directly on target.\n // For mount() container pattern: target is a wrapper, adopt on target.children[0].\n if (target.hasAttribute('data-forma-island')) {\n adoptNode(descriptor, target);\n } else {\n adoptNode(descriptor, target.children[0] as Element);\n }\n\n // 5. Remove SSR marker\n target.removeAttribute('data-forma-ssr');\n return target;\n}\n\n","/**\n * Forma DOM - Element\n *\n * Hyperscript-style element factory (`h`) and Fragment helper.\n * Backed by alien-signals via forma/reactive.\n *\n * Supports both HTML and SVG elements with automatic namespace detection.\n * Provides event listener cleanup via AbortController.\n */\n\nimport { internalEffect } from 'forma/reactive';\nimport { hydrating, type HydrationDescriptor } from './hydrate.js';\n\n/**\n * Symbol used as JSX Fragment factory. h(Fragment, null, ...children) returns DocumentFragment.\n *\n * Typed as a callable for TypeScript's JSX checker — at runtime it's a symbol\n * that h() detects via `tag === Fragment`. esbuild transforms `<>...</>` into\n * `h(Fragment, null, ...)` which never actually calls Fragment.\n */\nexport const Fragment: (props: { children?: unknown }) => DocumentFragment =\n Symbol.for('forma.fragment') as any;\n\n// ---------------------------------------------------------------------------\n// SVG namespace and tag detection\n// ---------------------------------------------------------------------------\n\nconst SVG_NS = 'http://www.w3.org/2000/svg';\nconst XLINK_NS = 'http://www.w3.org/1999/xlink';\n\n/** Known SVG tag names for O(1) lookup. */\nconst SVG_TAGS = new Set([\n 'svg',\n 'path',\n 'circle',\n 'rect',\n 'line',\n 'polyline',\n 'polygon',\n 'ellipse',\n 'g',\n 'text',\n 'tspan',\n 'textPath',\n 'defs',\n 'use',\n 'symbol',\n 'clipPath',\n 'mask',\n 'pattern',\n 'marker',\n 'linearGradient',\n 'radialGradient',\n 'stop',\n 'filter',\n 'feGaussianBlur',\n 'feColorMatrix',\n 'feOffset',\n 'feBlend',\n 'feMerge',\n 'feMergeNode',\n 'feComposite',\n 'feFlood',\n 'feMorphology',\n 'feTurbulence',\n 'feDisplacementMap',\n 'feImage',\n 'foreignObject',\n 'animate',\n 'animateTransform',\n 'animateMotion',\n 'set',\n 'image',\n 'switch',\n 'desc',\n 'title',\n 'metadata',\n]);\n\n// ---------------------------------------------------------------------------\n// Boolean HTML attributes (set/remove via setAttribute/removeAttribute)\n// ---------------------------------------------------------------------------\n\nconst BOOLEAN_ATTRS = new Set([\n 'disabled',\n 'checked',\n 'readonly',\n 'required',\n 'autofocus',\n 'autoplay',\n 'controls',\n 'default',\n 'defer',\n 'formnovalidate',\n 'hidden',\n 'ismap',\n 'loop',\n 'multiple',\n 'muted',\n 'nomodule',\n 'novalidate',\n 'open',\n 'playsinline',\n 'reversed',\n 'selected',\n 'async',\n]);\n\n// ---------------------------------------------------------------------------\n// Element prototype cache — cloneNode(false) is a C++ memcpy, faster than\n// createElement which must parse the tag string and validate.\n// \"Flexible Wings\" exploit: the prototypes pass static inspection (they're\n// standard elements) but flex at runtime to avoid parsing overhead.\n// ---------------------------------------------------------------------------\n\nlet ELEMENT_PROTOS: Record<string, HTMLElement> | null = null;\n\nfunction getProto(tag: string): HTMLElement {\n if (!ELEMENT_PROTOS) {\n ELEMENT_PROTOS = Object.create(null);\n // Pre-create prototypes for the 30 most common HTML tags\n for (const t of [\n 'div', 'span', 'p', 'a', 'li', 'ul', 'ol', 'button', 'input',\n 'label', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'section', 'header',\n 'footer', 'main', 'nav', 'table', 'tr', 'td', 'th', 'tbody',\n 'img', 'form', 'select', 'option', 'textarea', 'i', 'b', 'strong',\n 'em', 'small', 'article', 'aside', 'details', 'summary',\n ]) {\n ELEMENT_PROTOS![t] = document.createElement(t);\n }\n }\n return ELEMENT_PROTOS![tag] ?? (ELEMENT_PROTOS![tag] = document.createElement(tag));\n}\n\n// ---------------------------------------------------------------------------\n// Event name cache — avoids .slice(2).toLowerCase() string allocations\n// on every event binding. \"Super Clipping\" exploit.\n// ---------------------------------------------------------------------------\n\nconst EVENT_NAMES: Record<string, string> = Object.create(null);\n\nfunction eventName(key: string): string {\n return EVENT_NAMES[key] ?? (EVENT_NAMES[key] = key.slice(2).toLowerCase());\n}\n\n// ---------------------------------------------------------------------------\n// Symbol-based AbortController storage (avoids WeakMap overhead)\n// ---------------------------------------------------------------------------\n\nconst ABORT_SYM = Symbol.for('forma-abort');\n\n/** Get or lazily create an AbortController for an element. */\nfunction getAbortController(el: Element): AbortController {\n let controller = (el as any)[ABORT_SYM] as AbortController | undefined;\n if (!controller) {\n controller = new AbortController();\n (el as any)[ABORT_SYM] = controller;\n }\n return controller;\n}\n\n/**\n * Remove all event listeners previously attached via `h()` on the given element.\n *\n * Calls `AbortController.abort()` for the element, which automatically removes\n * every listener that was registered with its signal. The controller is then\n * deleted so a fresh one is created if the element is reused.\n */\nexport function cleanup(el: Element): void {\n const controller = (el as any)[ABORT_SYM] as AbortController | undefined;\n if (controller) {\n controller.abort();\n delete (el as any)[ABORT_SYM];\n }\n}\n\n// ---------------------------------------------------------------------------\n// Attribute diffing cache (avoids redundant DOM writes)\n// ---------------------------------------------------------------------------\n\nconst CACHE_SYM = Symbol.for('forma-attr-cache');\nconst DYNAMIC_CHILD_SYM = Symbol.for('forma-dynamic-child');\n\nfunction getCache(el: Element): Record<string, unknown> {\n return (el as any)[CACHE_SYM] ?? ((el as any)[CACHE_SYM] = Object.create(null));\n}\n\n// ---------------------------------------------------------------------------\n// Prop handler functions (extracted for dispatch table)\n// ---------------------------------------------------------------------------\n\ntype PropHandler = (el: Element, key: string, value: unknown) => void;\n\n/** Handle class / className prop. */\nfunction handleClass(el: Element, _key: string, value: unknown): void {\n if (typeof value === 'function') {\n internalEffect(() => {\n const v = (value as () => string)();\n const cache = getCache(el);\n if (cache['class'] === v) return;\n cache['class'] = v;\n if (el instanceof HTMLElement) {\n el.className = v;\n } else {\n el.setAttribute('class', v);\n }\n });\n } else {\n const cache = getCache(el);\n if (cache['class'] === value) return;\n cache['class'] = value;\n if (el instanceof HTMLElement) {\n el.className = value as string;\n } else {\n el.setAttribute('class', value as string);\n }\n }\n}\n\n/** Handle style prop. Reconciles object styles by removing stale keys. */\nfunction handleStyle(el: Element, _key: string, value: unknown): void {\n if (typeof value === 'function') {\n let prevKeys: string[] = [];\n internalEffect(() => {\n const v = (value as () => string | Record<string, string>)();\n if (typeof v === 'string') {\n const cache = getCache(el);\n if (cache['style'] === v) return;\n cache['style'] = v;\n prevKeys = [];\n (el as HTMLElement | SVGElement).style.cssText = v;\n } else if (v && typeof v === 'object') {\n const style = (el as HTMLElement | SVGElement).style;\n const nextKeys = Object.keys(v);\n // Remove keys that were present last time but are absent now\n for (const k of prevKeys) {\n if (!(k in (v as Record<string, string>))) {\n style.removeProperty(k.replace(/[A-Z]/g, (c) => '-' + c.toLowerCase()));\n }\n }\n Object.assign(style, v);\n prevKeys = nextKeys;\n }\n });\n } else if (typeof value === 'string') {\n const cache = getCache(el);\n if (cache['style'] === value) return;\n cache['style'] = value;\n (el as HTMLElement | SVGElement).style.cssText = value;\n } else if (value && typeof value === 'object') {\n Object.assign((el as HTMLElement | SVGElement).style, value);\n }\n}\n\n/** Handle event handler props (onClick, onInput, etc.). Cached eventName. */\nfunction handleEvent(el: Element, key: string, value: unknown): void {\n const controller = getAbortController(el);\n el.addEventListener(\n eventName(key),\n value as EventListener,\n { signal: controller.signal },\n );\n}\n\n/**\n * Handle dangerouslySetInnerHTML prop.\n *\n * **Security:** No sanitization is performed. Never pass user-controlled\n * strings through `__html` — this will create an XSS vulnerability.\n * Only use with trusted, server-generated markup.\n *\n * Supports both static `{ __html: string }` values and reactive functions\n * that return `{ __html: string }`.\n */\nfunction handleInnerHTML(el: Element, _key: string, value: unknown): void {\n if (typeof value === 'function') {\n internalEffect(() => {\n const resolved = (value as () => unknown)();\n if (resolved == null) {\n el.innerHTML = '';\n return;\n }\n if (typeof resolved !== 'object' || !('__html' in (resolved as any))) {\n throw new TypeError(\n 'dangerouslySetInnerHTML: expected { __html: string }, got ' + typeof resolved,\n );\n }\n const html = (resolved as { __html: string }).__html;\n if (typeof html !== 'string') {\n throw new TypeError(\n 'dangerouslySetInnerHTML: __html must be a string, got ' + typeof html,\n );\n }\n const cache = getCache(el);\n if (cache['innerHTML'] === html) return;\n cache['innerHTML'] = html;\n el.innerHTML = html;\n });\n } else {\n if (value == null) {\n el.innerHTML = '';\n return;\n }\n if (typeof value !== 'object' || !('__html' in (value as any))) {\n throw new TypeError(\n 'dangerouslySetInnerHTML: expected { __html: string }, got ' + typeof value,\n );\n }\n const html = (value as { __html: string }).__html;\n if (typeof html !== 'string') {\n throw new TypeError(\n 'dangerouslySetInnerHTML: __html must be a string, got ' + typeof html,\n );\n }\n el.innerHTML = html;\n }\n}\n\n/** Handle xlink: namespaced SVG attributes. */\nfunction handleXLink(el: Element, key: string, value: unknown): void {\n const localName = key.slice(6); // strip \"xlink:\" prefix\n if (typeof value === 'function') {\n internalEffect(() => {\n const v = (value as () => unknown)();\n if (v == null || v === false) {\n el.removeAttributeNS(XLINK_NS, localName);\n } else {\n el.setAttributeNS(XLINK_NS, key, String(v));\n }\n });\n } else {\n if (value == null || value === false) {\n el.removeAttributeNS(XLINK_NS, localName);\n } else {\n el.setAttributeNS(XLINK_NS, key, String(value));\n }\n }\n}\n\n/** Handle boolean attributes (disabled, checked, etc.). */\nfunction handleBooleanAttr(el: Element, key: string, value: unknown): void {\n if (typeof value === 'function') {\n internalEffect(() => {\n const v = (value as () => boolean)();\n const cache = getCache(el);\n if (cache[key] === v) return;\n cache[key] = v;\n if (v) {\n el.setAttribute(key, '');\n } else {\n el.removeAttribute(key);\n }\n });\n } else {\n const cache = getCache(el);\n if (cache[key] === value) return;\n cache[key] = value;\n if (value) {\n el.setAttribute(key, '');\n } else {\n el.removeAttribute(key);\n }\n }\n}\n\n/** Handle generic attributes with setAttribute/removeAttribute. */\nfunction handleGenericAttr(el: Element, key: string, value: unknown): void {\n if (typeof value === 'function') {\n internalEffect(() => {\n const v = (value as () => unknown)();\n if (v == null || v === false) {\n const cache = getCache(el);\n if (cache[key] === null) return;\n cache[key] = null;\n el.removeAttribute(key);\n } else {\n const strVal = String(v);\n const cache = getCache(el);\n if (cache[key] === strVal) return;\n cache[key] = strVal;\n el.setAttribute(key, strVal);\n }\n });\n } else {\n if (value == null || value === false) {\n const cache = getCache(el);\n if (cache[key] === null) return;\n cache[key] = null;\n el.removeAttribute(key);\n } else {\n const strVal = String(value);\n const cache = getCache(el);\n if (cache[key] === strVal) return;\n cache[key] = strVal;\n el.setAttribute(key, strVal);\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Prop dispatch table (O(1) Map lookup replaces sequential if/else chain)\n// ---------------------------------------------------------------------------\n\nconst PROP_HANDLERS = new Map<string, PropHandler>();\n\n// Register specific prop handlers\nPROP_HANDLERS.set('class', handleClass);\nPROP_HANDLERS.set('className', handleClass);\nPROP_HANDLERS.set('style', handleStyle);\nPROP_HANDLERS.set('ref', () => {}); // no-op, handled in h()\nPROP_HANDLERS.set('dangerouslySetInnerHTML', handleInnerHTML);\n\n// Register boolean attrs into the dispatch table\nfor (const attr of BOOLEAN_ATTRS) {\n PROP_HANDLERS.set(attr, handleBooleanAttr);\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\n/** Apply a single prop to an element (supports both HTML and SVG). */\nfunction applyProp(el: Element, key: string, value: unknown): void {\n // \"Twin Chassis\" exploit: inline check for the #1 most common prop\n // String === is ~2ns vs Map.get() ~8ns. Saves 75% dispatch time for 'class'.\n if (key === 'class') { handleClass(el, key, value); return; }\n\n // 2. Event handler detection (2-char check, faster than startsWith)\n // Events are the #2 most common prop type — check before Map.\n if (key.charCodeAt(0) === 111 /* 'o' */ && key.charCodeAt(1) === 110 /* 'n' */ && key.length > 2) {\n handleEvent(el, key, value); return;\n }\n\n // 3. Dispatch table for remaining known props (className, style, boolean attrs)\n const handler = PROP_HANDLERS.get(key);\n if (handler) { handler(el, key, value); return; }\n\n // 4. xlink: namespace (rare, check last)\n if (key.charCodeAt(0) === 120 /* 'x' */ && key.startsWith('xlink:')) {\n handleXLink(el, key, value); return;\n }\n\n // 5. Generic attribute fallback\n handleGenericAttr(el, key, value);\n}\n\n// ---------------------------------------------------------------------------\n// \"Blown Diffuser\" — static prop fast path (no cache, no effects)\n// Used only during h() initial element creation for non-function prop values.\n// Saves: getCache() lookup, cache diff check, cache write — per static prop.\n// ---------------------------------------------------------------------------\n\nfunction applyStaticProp(el: Element, key: string, value: unknown): void {\n if (value == null || value === false) return;\n\n if (key === 'class' || key === 'className') {\n (el as HTMLElement).className = value as string;\n return;\n }\n\n if (key === 'style') {\n if (typeof value === 'string') {\n (el as HTMLElement | SVGElement).style.cssText = value;\n } else if (value && typeof value === 'object') {\n Object.assign((el as HTMLElement | SVGElement).style, value);\n }\n return;\n }\n\n if (key === 'dangerouslySetInnerHTML') {\n if (typeof value !== 'object' || !('__html' in (value as any))) {\n throw new TypeError(\n 'dangerouslySetInnerHTML: expected { __html: string }, got ' + typeof value,\n );\n }\n const html = (value as { __html: string }).__html;\n if (typeof html !== 'string') {\n throw new TypeError(\n 'dangerouslySetInnerHTML: __html must be a string, got ' + typeof html,\n );\n }\n el.innerHTML = html;\n return;\n }\n\n // xlink: namespace\n if (key.charCodeAt(0) === 120 /* x */ && key.startsWith('xlink:')) {\n el.setAttributeNS(XLINK_NS, key, String(value));\n return;\n }\n\n // Boolean attrs\n if (BOOLEAN_ATTRS.has(key)) {\n if (value) el.setAttribute(key, '');\n return;\n }\n\n // Generic: true → empty string attribute, else stringified value\n if (value === true) {\n el.setAttribute(key, '');\n } else {\n el.setAttribute(key, String(value));\n }\n}\n\n/** Append a single child to a parent node. */\nfunction appendChild(parent: Node, child: unknown): void {\n // \"Active Suspension\" exploit: check the MOST COMMON type first.\n // In h('div', props, h('span'), h('button')), children are Nodes 70%+ of the time.\n // instanceof Node returns false in O(1) for primitives (null, string, number)\n // because V8 checks \"is this an object?\" first — no prototype chain walk.\n // This saves 3-5 wasted type comparisons vs the conventional null-first order.\n if (child instanceof Node) {\n parent.appendChild(child);\n return;\n }\n\n // \"Track Limits\": new Text() bypasses Document.createTextNode's validation.\n if (typeof child === 'string') {\n parent.appendChild(new Text(child));\n return;\n }\n\n // Null/false/true → skip (React-style conditional pattern)\n if (child == null || child === false || child === true) {\n return;\n }\n\n if (typeof child === 'number') {\n parent.appendChild(new Text(String(child)));\n return;\n }\n\n // Function child: reactive binding via signal getter.\n // The return value determines the binding type:\n // - Node (from h() call) → append/replace as element\n // - primitive (string/number/null) → bind as text\n if (typeof child === 'function') {\n if (parent instanceof Element) {\n (parent as any)[DYNAMIC_CHILD_SYM] = true;\n }\n let currentNode: Node | null = null;\n internalEffect(() => {\n const v = (child as () => unknown)();\n if (v instanceof Node) {\n // Function returned a DOM element — adopt or replace\n if (currentNode) {\n parent.replaceChild(v, currentNode);\n } else {\n parent.appendChild(v);\n }\n currentNode = v;\n } else {\n // Primitive value — bind as text\n const text = typeof v === 'symbol' ? String(v) : String(v ?? '');\n if (!currentNode) {\n currentNode = new Text(text);\n parent.appendChild(currentNode);\n } else if (currentNode.nodeType === 3) {\n (currentNode as Text).data = text;\n } else {\n const tn = new Text(text);\n parent.replaceChild(tn, currentNode);\n currentNode = tn;\n }\n }\n });\n return;\n }\n\n if (Array.isArray(child)) {\n for (const item of child) {\n appendChild(parent, item);\n }\n return;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Create a real DOM element with optional props and children.\n *\n * Supports both HTML and SVG elements. SVG tags are detected automatically\n * and created with the correct SVG namespace. Inside a `foreignObject`,\n * children switch back to the HTML namespace.\n *\n * Event listeners are attached with an AbortController signal so they can\n * be removed in bulk via `cleanup(el)`.\n *\n * Hyperscript-style API:\n * ```ts\n * h('div', { class: 'container', onClick: handleClick },\n * h('span', null, 'Hello'),\n * h('span', null, name), // name is a signal getter\n * )\n *\n * h('svg', { viewBox: '0 0 24 24', fill: 'none' },\n * h('path', { d: 'M12 2L2 22h20L12 2z', stroke: 'currentColor' }),\n * )\n * ```\n */\n// Overloads: function component, Fragment, string\nexport function h(tag: (props: Record<string, unknown>) => unknown, props?: Record<string, unknown> | null, ...children: unknown[]): Node;\nexport function h(tag: typeof Fragment, props?: null, ...children: unknown[]): DocumentFragment;\nexport function h(tag: string, props?: Record<string, unknown> | null, ...children: unknown[]): HTMLElement;\nexport function h(\n tag: string | typeof Fragment | ((props: Record<string, unknown>) => unknown),\n props?: Record<string, unknown> | null,\n ...children: unknown[]\n): HTMLElement | DocumentFragment {\n // Function component: call with merged props + children\n if (typeof tag === 'function' && tag !== Fragment) {\n const mergedProps = { ...(props ?? {}), children };\n return tag(mergedProps) as unknown as HTMLElement;\n }\n\n // Fragment: return DocumentFragment with children\n if (tag === Fragment) {\n const frag = document.createDocumentFragment();\n for (const child of children) {\n appendChild(frag, child);\n }\n return frag;\n }\n\n // After the Fragment guard above, tag is guaranteed to be a string\n const tagName = tag as string;\n\n if (hydrating) {\n return { type: 'element', tag: tagName, props: props ?? null, children } as unknown as HTMLElement;\n }\n\n // \"Flexible Wings\" exploit: for HTML elements, clone a pre-created prototype\n // instead of calling createElement. cloneNode(false) is a single C++ memcpy\n // that copies the element's internal state without parsing the tag string.\n // Skip the SVG Set lookup entirely when the tag is in the proto cache (hot path).\n let el: Element;\n if (ELEMENT_PROTOS && ELEMENT_PROTOS[tagName]) {\n el = ELEMENT_PROTOS[tagName]!.cloneNode(false) as HTMLElement;\n } else if (SVG_TAGS.has(tagName)) {\n el = document.createElementNS(SVG_NS, tagName);\n } else {\n el = getProto(tagName).cloneNode(false) as HTMLElement;\n }\n\n // \"Blown Diffuser\" exploit: split props into static and dynamic paths.\n // Static props (string/number/boolean literals) go through a zero-cache\n // fast path. Only dynamic props (function values) need the attribute cache\n // for diffing on re-runs. This avoids:\n // - Object.create(null) allocation for elements with only static props\n // - Cache read/write operations that always miss on first call\n // - getCache() indirection in every prop handler\n if (props) {\n let hasDynamic = false;\n for (const key in props) {\n if (key === 'ref') continue;\n const value = props[key];\n\n // Event handlers: no cache needed, direct binding\n if (key.charCodeAt(0) === 111 /* o */ && key.charCodeAt(1) === 110 /* n */ && key.length > 2) {\n handleEvent(el, key, value);\n continue;\n }\n\n // Dynamic prop (function value, not event): needs cache + effect\n if (typeof value === 'function') {\n if (!hasDynamic) {\n // Lazy-allocate cache only when first dynamic prop is found\n (el as any)[CACHE_SYM] = Object.create(null);\n hasDynamic = true;\n }\n applyProp(el, key, value);\n continue;\n }\n\n // Static prop: zero-cache fast path — direct DOM write\n applyStaticProp(el, key, value);\n }\n }\n\n // Append children — fast path for single string/number child avoids\n // Text node allocation + separate appendChild. el.textContent is a single\n // native C++ call that combines both operations.\n const childLen = children.length;\n if (childLen === 1) {\n const only = children[0];\n if (typeof only === 'string') {\n el.textContent = only;\n } else if (typeof only === 'number') {\n el.textContent = String(only);\n } else {\n appendChild(el, only);\n }\n } else if (childLen > 1) {\n for (const child of children) {\n appendChild(el, child);\n }\n }\n\n // Call ref after element is fully constructed\n if (props && typeof props['ref'] === 'function') {\n (props['ref'] as (el: Element) => void)(el);\n }\n\n return el as unknown as HTMLElement;\n}\n\n/**\n * Create a DocumentFragment from children.\n *\n * ```ts\n * fragment(\n * h('li', null, 'one'),\n * h('li', null, 'two'),\n * )\n * ```\n */\nexport function fragment(...children: unknown[]): DocumentFragment {\n const frag = document.createDocumentFragment();\n for (const child of children) {\n appendChild(frag, child);\n }\n return frag;\n}\n","/**\n * Forma DOM - Text\n *\n * Creates static or reactive Text nodes.\n * Zero dependencies -- native browser APIs only.\n */\n\nimport { internalEffect } from 'forma/reactive';\n\n/**\n * Create a Text node that is either static or reactively bound.\n *\n * - If `value` is a string, creates a plain Text node.\n * - If `value` is a function (signal getter), creates a Text node and sets up\n * an effect that auto-updates `textContent` whenever the signal changes.\n *\n * @returns The Text node.\n */\nexport function createText(value: string | (() => string)): Text {\n if (typeof value === 'function') {\n // \"Track Limits\": new Text() bypasses Document factory dispatch\n const node = new Text('');\n internalEffect(() => {\n // \"DAS\": CharacterData.data is the rawest text setter\n node.data = value();\n });\n return node;\n }\n return new Text(value);\n}\n","/**\n * Forma DOM - Mount\n *\n * Mounts a component function into a DOM container, returning an unmount handle.\n * Uses createRoot() for automatic effect disposal — no global state.\n *\n * When the container has `data-forma-ssr`, uses hydrateIsland() for zero-flash\n * descriptor-based hydration instead of tearing down and rebuilding the DOM.\n */\n\nimport { createRoot } from 'forma/reactive';\nimport { hydrateIsland } from './hydrate.js';\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Mount a component into a DOM container.\n *\n * All effects created during the component's render are tracked via\n * `createRoot()` and automatically disposed when unmount is called.\n *\n * When `data-forma-ssr` is present on the container, the component runs\n * inside `createRoot` in hydration mode — h() returns descriptors that are\n * walked against SSR DOM to attach handlers and reactive bindings.\n *\n * @param component A function returning an HTMLElement or DocumentFragment.\n * @param container An HTMLElement or a CSS selector string.\n * @returns An unmount function that removes the DOM and disposes all effects.\n *\n * ```ts\n * const unmount = mount(() => h('h1', null, 'Hello'), '#app');\n * // later…\n * unmount();\n * ```\n */\nexport function mount(\n component: () => HTMLElement | DocumentFragment,\n container: HTMLElement | string,\n): () => void {\n const target =\n typeof container === 'string'\n ? document.querySelector<HTMLElement>(container)\n : container;\n\n if (!target) {\n throw new Error(`mount: container not found — \"${container}\"`);\n }\n\n let disposeRoot!: () => void;\n\n if (target.hasAttribute('data-forma-ssr')) {\n // SSR content present — hydrate in-place using descriptor-based adoption.\n // The component MUST run inside createRoot so effects are tracked.\n createRoot((dispose) => {\n disposeRoot = dispose;\n hydrateIsland(component, target);\n });\n } else {\n // Normal mount — clear and append\n const dom = createRoot((dispose) => {\n disposeRoot = dispose;\n return component();\n });\n target.innerHTML = '';\n target.appendChild(dom);\n }\n\n // Return unmount function\n let unmounted = false;\n return () => {\n if (unmounted) return;\n unmounted = true;\n disposeRoot();\n target.innerHTML = '';\n };\n}\n","/**\n * Forma DOM - Switch (Multi-branch Conditional)\n *\n * Maps a reactive value to one of N render branches.\n * Caches previously rendered nodes for instant swap-back.\n *\n * Each cached branch gets its own reactive root (ownership scope) so that:\n * 1. Inner effects survive when the switch effect re-runs (alien-signals\n * would otherwise dispose child effects linked to the parent).\n * 2. Inner effects are explicitly disposed when the branch is evicted\n * from the cache or the switch itself is torn down.\n *\n * SolidJS equivalent: <Switch><Match when={}>\n */\n\nimport { internalEffect, untrack, createRoot } from 'forma/reactive';\n\nexport interface SwitchCase<T> {\n match: T;\n render: () => Node;\n}\n\n/** Cached branch: the rendered DOM node + a dispose function for its root. */\ninterface CachedBranch {\n node: Node;\n dispose: () => void;\n}\n\n/**\n * Multi-branch conditional rendering with node caching.\n *\n * ```ts\n * const [tab, setTab] = createSignal('home');\n * const fragment = createSwitch(tab, [\n * { match: 'home', render: () => h('div', null, 'Home page') },\n * { match: 'about', render: () => h('div', null, 'About page') },\n * { match: 'contact', render: () => h('div', null, 'Contact page') },\n * ], () => h('div', null, '404'));\n * ```\n *\n * Previously rendered branches are cached — switching back to a tab\n * re-inserts the cached node without re-rendering.\n */\nexport function createSwitch<T>(\n value: () => T,\n cases: SwitchCase<T>[],\n fallback?: () => Node,\n): DocumentFragment {\n const startMarker = document.createComment('forma-switch');\n const endMarker = document.createComment('/forma-switch');\n const fragment = document.createDocumentFragment();\n fragment.appendChild(startMarker);\n fragment.appendChild(endMarker);\n\n // Branch cache: value → { node, dispose }\n // Each branch has its own reactive root for explicit lifecycle management.\n const cache = new Map<T, CachedBranch>();\n let currentNode: Node | null = null;\n let currentMatch: T | typeof UNSET = UNSET;\n\n const switchDispose = internalEffect(() => {\n const val = value();\n if (val === currentMatch) return; // Same branch, skip\n\n const DEBUG = typeof (globalThis as any).__FORMA_DEBUG__ !== 'undefined';\n if (DEBUG) console.log('[forma:switch] transition', String(currentMatch), '→', String(val));\n\n currentMatch = val;\n\n const parent = startMarker.parentNode;\n if (!parent) {\n if (DEBUG) console.warn('[forma:switch] markers not in DOM yet, skipping');\n return;\n }\n\n // Remove current content between markers.\n // If currentNode was a DocumentFragment, its children transferred to the\n // DOM on insertion and the fragment is now detached (parentNode === null).\n // We must scoop the children BACK into the fragment so the cache stays\n // valid for re-insertion later.\n if (currentNode) {\n if (currentNode.parentNode === parent) {\n if (DEBUG) console.log('[forma:switch] removing single node');\n parent.removeChild(currentNode);\n } else if (currentNode.nodeType === 11 /* DOCUMENT_FRAGMENT_NODE */) {\n // Scoop DOM nodes back into the fragment for cache reuse\n if (DEBUG) console.log('[forma:switch] scooping nodes back into fragment');\n let scooped = 0;\n while (startMarker.nextSibling && startMarker.nextSibling !== endMarker) {\n currentNode.appendChild(startMarker.nextSibling);\n scooped++;\n }\n if (DEBUG) console.log('[forma:switch] scooped', scooped, 'nodes back into fragment');\n } else {\n // Other detached node — just clear between markers\n if (DEBUG) console.log('[forma:switch] clearing detached node between markers');\n while (startMarker.nextSibling && startMarker.nextSibling !== endMarker) {\n parent.removeChild(startMarker.nextSibling);\n }\n }\n }\n\n // Find matching case\n const matchedCase = cases.find(c => c.match === val);\n if (matchedCase) {\n let entry = cache.get(val);\n if (!entry) {\n // Render inside a createRoot so child effects are tracked for\n // disposal, and inside untrack so they are NOT linked to the\n // switch effect (alien-signals disposes child effects on parent\n // re-run, which would kill reactivity in cached branches).\n let branchDispose!: () => void;\n const node = createRoot((dispose) => {\n branchDispose = dispose;\n return untrack(() => matchedCase.render());\n });\n entry = { node, dispose: branchDispose };\n cache.set(val, entry);\n if (DEBUG) console.log('[forma:switch] rendered new branch for', String(val), '→', node.nodeName, 'type', node.nodeType);\n } else {\n if (DEBUG) console.log('[forma:switch] reusing cached branch for', String(val), '→', entry.node.nodeName, 'type', entry.node.nodeType, 'childNodes', entry.node.childNodes?.length);\n }\n currentNode = entry.node;\n } else {\n // Fallback — not cached, effects are owned by the switch effect\n // and correctly torn down on next re-run.\n currentNode = fallback?.() ?? null;\n if (DEBUG) console.log('[forma:switch] no match, using fallback');\n }\n\n if (currentNode) {\n parent.insertBefore(currentNode, endMarker);\n if (DEBUG) console.log('[forma:switch] inserted', currentNode.nodeName, 'before end marker');\n }\n });\n\n // Attach a cleanup marker so external disposal (via disposeComponent or\n // parent root teardown) can clean up all cached branches.\n (fragment as any).__switchDispose = () => {\n switchDispose();\n for (const entry of cache.values()) {\n entry.dispose();\n }\n cache.clear();\n };\n\n return fragment;\n}\n\n// Sentinel value for \"no match yet\"\nconst UNSET = Symbol('unset');\n","/**\n * Forma DOM - Portal\n *\n * Renders children into a different DOM container than the parent.\n * Useful for modals, tooltips, dropdowns that need to escape overflow.\n *\n * SolidJS equivalent: <Portal mount={}>\n */\n\nimport { createEffect } from 'forma/reactive';\n\n/**\n * Render content into an external DOM container.\n *\n * ```ts\n * const modal = createPortal(\n * () => h('div', { class: 'modal' }, 'Modal content'),\n * document.body,\n * );\n * ```\n *\n * Returns a comment node placeholder. The actual content is rendered\n * into the target container. Cleanup removes content from target.\n */\nexport function createPortal(\n children: () => Node,\n target?: Element | string,\n): Comment {\n const placeholder = document.createComment('forma-portal');\n\n const resolvedTarget = typeof target === 'string'\n ? document.querySelector(target)\n : (target ?? document.body);\n\n if (!resolvedTarget) {\n throw new Error(`createPortal: target not found: ${target}`);\n }\n\n let mountedNode: Node | null = null;\n const removeMountedNode = () => {\n if (mountedNode && mountedNode.parentNode === resolvedTarget) {\n resolvedTarget.removeChild(mountedNode);\n }\n mountedNode = null;\n };\n\n createEffect(() => {\n const node = children();\n\n // Remove previous\n removeMountedNode();\n\n mountedNode = node;\n resolvedTarget.appendChild(node);\n\n // Ensure portal content is removed when the owner root disposes.\n return () => {\n removeMountedNode();\n };\n });\n\n return placeholder;\n}\n","/**\n * Forma DOM - Error Boundary\n *\n * Catches errors during rendering and shows a fallback UI.\n * Provides a retry function to re-attempt the original render.\n *\n * SolidJS equivalent: <ErrorBoundary fallback={}>\n */\n\nimport { createSignal, internalEffect } from 'forma/reactive';\n\n/**\n * Wrap a render function with error recovery.\n *\n * ```ts\n * const fragment = createErrorBoundary(\n * () => h('div', null, riskyComponent()),\n * (error, retry) => h('div', { class: 'error' },\n * h('p', null, `Error: ${error.message}`),\n * h('button', { onClick: retry }, 'Retry'),\n * ),\n * );\n * ```\n *\n * If `tryFn` throws, `catchFn` is called with the error and a retry function.\n * Calling `retry()` re-runs `tryFn`.\n */\nexport function createErrorBoundary(\n tryFn: () => Node,\n catchFn: (error: Error, retry: () => void) => Node,\n): DocumentFragment {\n const startMarker = document.createComment('forma-error-boundary');\n const endMarker = document.createComment('/forma-error-boundary');\n const fragment = document.createDocumentFragment();\n fragment.appendChild(startMarker);\n fragment.appendChild(endMarker);\n\n const [retryCount, setRetryCount] = createSignal(0);\n let currentNode: Node | null = null;\n\n internalEffect(() => {\n // Subscribe to retryCount so retry() triggers re-run\n retryCount();\n\n const parent = startMarker.parentNode;\n if (!parent) return;\n\n // Remove current\n if (currentNode && currentNode.parentNode === parent) {\n parent.removeChild(currentNode);\n }\n\n try {\n currentNode = tryFn();\n } catch (e) {\n const error = e instanceof Error ? e : new Error(String(e));\n const retry = () => setRetryCount(c => c + 1);\n currentNode = catchFn(error, retry);\n }\n\n if (currentNode) {\n parent.insertBefore(currentNode, endMarker);\n }\n });\n\n return fragment;\n}\n","/**\n * Forma DOM - Suspense\n *\n * A Suspense boundary that shows fallback content while async resources\n * inside the children function are loading. Uses comment markers\n * (like createShow, createList) for zero-wrapper rendering.\n *\n * When all resources resolve, the fallback is swapped for the real content.\n * If a resource errors, the fallback remains (pair with createErrorBoundary\n * for error handling).\n *\n * SolidJS equivalent: <Suspense fallback={}>\n */\n\nimport { createSignal, internalEffect } from 'forma/reactive';\nimport {\n type SuspenseContext,\n pushSuspenseContext,\n popSuspenseContext,\n} from 'forma/reactive/suspense-context';\n\n// Re-export context utilities so consumers can import from dom/suspense\nexport { getSuspenseContext, pushSuspenseContext, popSuspenseContext } from 'forma/reactive/suspense-context';\nexport type { SuspenseContext } from 'forma/reactive/suspense-context';\n\n// ---------------------------------------------------------------------------\n// createSuspense\n// ---------------------------------------------------------------------------\n\n/**\n * Create a Suspense boundary that shows fallback content while async resources\n * inside the children function are loading.\n *\n * Uses comment markers: `<!--forma-suspense-->` / `<!--/forma-suspense-->`\n *\n * When all resources resolve, the fallback is swapped for the real content.\n * If a resource errors, the fallback remains (pair with createErrorBoundary\n * for errors).\n *\n * ```ts\n * const frag = createSuspense(\n * () => h('div', null, 'Loading...'),\n * () => {\n * const data = createResource(source, fetcher);\n * return h('div', null, () => data()?.name ?? '');\n * },\n * );\n * container.appendChild(frag);\n * ```\n */\nexport function createSuspense(\n fallback: () => Node,\n children: () => Node,\n): DocumentFragment {\n const startMarker = document.createComment('forma-suspense');\n const endMarker = document.createComment('/forma-suspense');\n const fragment = document.createDocumentFragment();\n fragment.appendChild(startMarker);\n fragment.appendChild(endMarker);\n\n const [pending, setPending] = createSignal(0);\n let currentNode: Node | null = null;\n let resolvedNode: Node | null = null;\n let fallbackNode: Node | null = null;\n\n const ctx: SuspenseContext = {\n increment() { setPending(p => p + 1); },\n decrement() { setPending(p => Math.max(0, p - 1)); },\n };\n\n // Render children within the Suspense context so that any createResource\n // calls inside will register with this boundary.\n pushSuspenseContext(ctx);\n try {\n resolvedNode = children();\n } finally {\n popSuspenseContext();\n }\n\n // Reactively swap between fallback and children based on pending count\n internalEffect(() => {\n const parent = startMarker.parentNode;\n if (!parent) return;\n\n const isPending = pending() > 0;\n const newNode = isPending ? (fallbackNode ??= fallback()) : resolvedNode;\n\n if (newNode === currentNode) return;\n\n // Remove current node\n if (currentNode && currentNode.parentNode === parent) {\n parent.removeChild(currentNode);\n }\n\n // Insert new node\n if (newNode) {\n parent.insertBefore(newNode, endMarker);\n }\n\n currentNode = newNode;\n });\n\n return fragment;\n}\n","/**\n * Forma DOM - Island Activation\n *\n * Discovers SSR-rendered islands via [data-forma-island] attributes,\n * loads props (inline or script_tag), and hydrates each island inside\n * an independent createRoot scope with try/catch error isolation.\n */\n\nimport { createRoot, __DEV__ } from 'forma/reactive';\nimport { hydrateIsland } from './hydrate.js';\n\n/**\n * Function that hydrates an island.\n *\n * @param el The root element of the island (`[data-forma-island]`).\n * Useful for layout measurement, focus management, CSS class\n * toggling, third-party library init, or reading extra `data-*`\n * attributes from the server-rendered shell.\n * @param props Parsed props from `data-forma-props` (inline or script block),\n * or `null` if no props were provided.\n * @returns A component tree (from `h()` calls) for descriptor-based\n * hydration, or `undefined` for imperative islands that set up\n * their own effects.\n */\nexport type IslandHydrateFn = (el: HTMLElement, props: Record<string, unknown> | null) => unknown;\n\nconst FORBIDDEN_PROP_KEYS = new Set(['__proto__', 'constructor', 'prototype']);\n\nfunction sanitizeProps(obj: Record<string, unknown>): Record<string, unknown> {\n for (const key of FORBIDDEN_PROP_KEYS) {\n if (key in obj) delete (obj as any)[key];\n }\n return obj;\n}\n\n/**\n * Load props for an island from either inline attribute or shared script block.\n */\nfunction loadIslandProps(\n root: HTMLElement,\n id: number,\n sharedProps: Record<string, unknown> | null,\n): Record<string, unknown> | null {\n // Mode 1: Inline (small props, < 1KB)\n const inline = root.getAttribute('data-forma-props');\n if (inline) {\n return sanitizeProps(JSON.parse(inline));\n }\n\n // Mode 2: Script tag (1KB–50KB, pre-parsed)\n if (sharedProps && String(id) in sharedProps) {\n return sanitizeProps((sharedProps as any)[String(id)] as Record<string, unknown>);\n }\n\n // No props — island creates its own state\n return null;\n}\n\n/**\n * Discover and activate all SSR-rendered islands on the page.\n *\n * Each island is activated inside its own createRoot scope with try/catch\n * isolation — a broken island never takes down its siblings.\n *\n * @param registry Map of component names to hydration functions.\n */\nexport function activateIslands(registry: Record<string, IslandHydrateFn>): void {\n // Parse shared props once before the loop\n const scriptBlock = document.getElementById('__forma_islands');\n const sharedProps: Record<string, unknown> | null =\n scriptBlock ? JSON.parse(scriptBlock.textContent!) : null;\n\n const islands = document.querySelectorAll<HTMLElement>('[data-forma-island]');\n\n for (const root of islands) {\n const id = parseInt(root.getAttribute('data-forma-island')!, 10);\n const componentName = root.getAttribute('data-forma-component')!;\n const hydrateFn = registry[componentName];\n\n if (!hydrateFn) {\n if (__DEV__) console.warn(`[forma] No hydrate function for island \"${componentName}\" (id=${id})`);\n root.setAttribute('data-forma-status', 'error');\n continue;\n }\n\n const trigger = root.getAttribute('data-forma-hydrate') || 'load';\n\n if (trigger === 'visible') {\n // Defer hydration until island enters the viewport\n const observer = new IntersectionObserver(\n (entries) => {\n for (const entry of entries) {\n if (!entry.isIntersecting) continue;\n observer.disconnect();\n hydrateIslandRoot(root, id, componentName, hydrateFn, sharedProps);\n }\n },\n { rootMargin: '200px' },\n );\n observer.observe(root);\n } else if (trigger === 'idle') {\n const hydrate = () => hydrateIslandRoot(root, id, componentName, hydrateFn, sharedProps);\n if (typeof requestIdleCallback === 'function') {\n requestIdleCallback(hydrate);\n } else {\n setTimeout(hydrate, 200);\n }\n } else if (trigger === 'interaction') {\n const hydrate = () => {\n root.removeEventListener('pointerdown', hydrate, true);\n root.removeEventListener('focusin', hydrate, true);\n hydrateIslandRoot(root, id, componentName, hydrateFn, sharedProps);\n };\n root.addEventListener('pointerdown', hydrate, { capture: true, once: true });\n root.addEventListener('focusin', hydrate, { capture: true, once: true });\n } else {\n // load (default) — hydrate immediately\n hydrateIslandRoot(root, id, componentName, hydrateFn, sharedProps);\n }\n }\n}\n\n/**\n * Dispose a single island, tearing down its reactive root and all effects.\n *\n * Safe to call multiple times (idempotent). Sets `data-forma-status` to\n * `\"disposed\"` so the island can be distinguished from active/error states.\n */\nexport function deactivateIsland(el: HTMLElement): void {\n const dispose = (el as any).__formaDispose;\n if (typeof dispose === 'function') {\n dispose();\n delete (el as any).__formaDispose;\n el.setAttribute('data-forma-status', 'disposed');\n }\n}\n\n/**\n * Dispose ALL active islands under a root element (or the whole document).\n *\n * Use this when swapping module content — e.g., replacing the contents of\n * a `<forma-stage>` Shadow DOM during AI generation. Prevents leaked effects\n * and event listeners from accumulating across swaps.\n */\nexport function deactivateAllIslands(root: Element | Document = document): void {\n const islands = root.querySelectorAll<HTMLElement>('[data-forma-status=\"active\"]');\n for (const island of islands) {\n deactivateIsland(island);\n }\n}\n\n/** Hydrate a single island root with error isolation. */\nfunction hydrateIslandRoot(\n root: HTMLElement,\n id: number,\n componentName: string,\n hydrateFn: IslandHydrateFn,\n sharedProps: Record<string, unknown> | null,\n): void {\n try {\n const props = loadIslandProps(root, id, sharedProps);\n root.setAttribute('data-forma-status', 'hydrating');\n\n // hydrateIsland may replace the shell element with the component's own\n // root element (CSR fallback for empty islands). Track the active root.\n let activeRoot: Element = root;\n createRoot((dispose) => {\n activeRoot = hydrateIsland(() => hydrateFn(root, props), root);\n (activeRoot as any).__formaDispose = dispose;\n });\n\n activeRoot.setAttribute('data-forma-status', 'active');\n } catch (err) {\n if (__DEV__) console.error(`[forma] Island \"${componentName}\" (id=${id}) failed:`, err);\n root.setAttribute('data-forma-status', 'error');\n }\n}\n","/**\n * Forma Component - Define\n *\n * Component definition system where the setup function runs ONCE.\n * Reactivity comes from signals, not re-rendering.\n * Backed by alien-signals via forma/reactive.\n */\n\nimport { reportError } from '../reactive/dev.js';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport type CleanupFn = () => void;\nexport type SetupFn = () => HTMLElement | DocumentFragment;\n\nexport interface ComponentDef {\n setup: SetupFn;\n name?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Lifecycle context stack\n// ---------------------------------------------------------------------------\n\ninterface LifecycleContext {\n /** Dispose functions for all effects created during setup. */\n disposers: (() => void)[];\n /** Callbacks registered via onMount(). */\n mountCallbacks: (() => void | CleanupFn)[];\n /** Callbacks registered via onUnmount(). */\n unmountCallbacks: (() => void)[];\n}\n\nlet currentLifecycleContext: LifecycleContext | null = null;\nconst lifecycleStack: (LifecycleContext | null)[] = [];\n\nfunction pushLifecycleContext(ctx: LifecycleContext): void {\n lifecycleStack.push(currentLifecycleContext);\n currentLifecycleContext = ctx;\n}\n\nfunction popLifecycleContext(): void {\n currentLifecycleContext = lifecycleStack.pop() ?? null;\n}\n\n// ---------------------------------------------------------------------------\n// Public API - Lifecycle hooks\n// ---------------------------------------------------------------------------\n\n/**\n * Register a callback that runs after the component's setup completes.\n * If the callback returns a function, that function is called on unmount.\n * Must be called inside a setup function.\n */\nexport function onMount(fn: () => void | CleanupFn): void {\n if (currentLifecycleContext === null) {\n throw new Error('onMount() must be called inside a component setup function');\n }\n currentLifecycleContext.mountCallbacks.push(fn);\n}\n\n/**\n * Register a callback that runs when the component is disposed.\n * Must be called inside a setup function.\n */\nexport function onUnmount(fn: () => void): void {\n if (currentLifecycleContext === null) {\n throw new Error('onUnmount() must be called inside a component setup function');\n }\n currentLifecycleContext.unmountCallbacks.push(fn);\n}\n\n// ---------------------------------------------------------------------------\n// Internal: symbol for attaching dispose to DOM nodes\n// ---------------------------------------------------------------------------\n\nconst DISPOSE_KEY = Symbol('forma:component:dispose');\n\ninterface DisposableNode {\n [DISPOSE_KEY]?: () => void;\n}\n\n// ---------------------------------------------------------------------------\n// Public API - defineComponent\n// ---------------------------------------------------------------------------\n\n/**\n * Define a component from a setup function or definition object.\n * Returns a factory function that, when called, produces a DOM element\n * with attached lifecycle and disposal logic.\n *\n * The setup function runs ONCE per factory call. Reactivity is driven\n * by signals, not by re-running setup.\n */\nexport function defineComponent(\n setupOrDef: SetupFn | ComponentDef,\n): () => HTMLElement | DocumentFragment {\n const setup: SetupFn =\n typeof setupOrDef === 'function' ? setupOrDef : setupOrDef.setup;\n const name: string | undefined =\n typeof setupOrDef === 'function' ? undefined : setupOrDef.name;\n\n return function componentFactory(): HTMLElement | DocumentFragment {\n // Create a fresh lifecycle context for this component instance\n const ctx: LifecycleContext = {\n disposers: [],\n mountCallbacks: [],\n unmountCallbacks: [],\n };\n\n // Push lifecycle context so onMount/onUnmount calls register here\n pushLifecycleContext(ctx);\n\n let dom: HTMLElement | DocumentFragment;\n try {\n dom = setup();\n } finally {\n popLifecycleContext();\n }\n\n // Build the dispose function that tears down the entire component\n const dispose = (): void => {\n // Run onUnmount callbacks\n for (const cb of ctx.unmountCallbacks) {\n try {\n cb();\n } catch (e) {\n reportError(e, 'onUnmount');\n }\n }\n\n // Dispose all effects\n for (const d of ctx.disposers) {\n try {\n d();\n } catch (e) {\n reportError(e, 'component disposer');\n }\n }\n\n // Clean up\n ctx.disposers.length = 0;\n ctx.mountCallbacks.length = 0;\n ctx.unmountCallbacks.length = 0;\n };\n\n // Attach dispose to the DOM node so callers can tear it down\n (dom as unknown as DisposableNode)[DISPOSE_KEY] = dispose;\n\n // Run mount callbacks (synchronously, after setup completes)\n // If a mount callback returns a cleanup, register it as an unmount callback\n for (const cb of ctx.mountCallbacks) {\n try {\n const cleanup = cb();\n if (typeof cleanup === 'function') {\n ctx.unmountCallbacks.push(cleanup);\n }\n } catch (e) {\n reportError(e, 'onMount');\n }\n }\n\n return dom;\n };\n}\n\n/**\n * Dispose a component that was created via defineComponent.\n * This runs all onUnmount callbacks and disposes all tracked effects.\n */\nexport function disposeComponent(dom: HTMLElement | DocumentFragment): void {\n const disposable = dom as unknown as DisposableNode;\n if (typeof disposable[DISPOSE_KEY] === 'function') {\n disposable[DISPOSE_KEY]();\n delete disposable[DISPOSE_KEY];\n }\n}\n\n/**\n * Track an effect disposal within the current component's lifecycle.\n * Call this inside a setup function to ensure effects are cleaned up\n * when the component is disposed.\n */\nexport function trackDisposer(dispose: () => void): void {\n if (currentLifecycleContext !== null) {\n currentLifecycleContext.disposers.push(dispose);\n }\n}\n","/**\n * Forma Component - Context\n *\n * Dependency injection via stack-based context.\n * Simpler than React's Provider component tree: provide() pushes a value,\n * inject() reads the top, component teardown pops automatically.\n * Zero dependencies -- native browser APIs only.\n */\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface Context<T> {\n /** Unique identifier for this context. */\n readonly id: symbol;\n /** Value returned when no provider is active. */\n readonly defaultValue: T;\n}\n\n// ---------------------------------------------------------------------------\n// Internal storage\n// ---------------------------------------------------------------------------\n\n/**\n * Per-context value stacks.\n * Each context id maps to a stack of provided values.\n * The top of the stack is the \"current\" value.\n */\nconst contextStacks = new Map<symbol, unknown[]>();\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Create a new context with a default value.\n *\n * ```ts\n * const ThemeCtx = createContext('light');\n * ```\n */\nexport function createContext<T>(defaultValue: T): Context<T> {\n return {\n id: Symbol('forma:context'),\n defaultValue,\n };\n}\n\n/**\n * Provide a value for a context.\n * The value is pushed onto the context's stack and will be returned by\n * inject() until it is removed via unprovide() or overridden by a nested provide().\n *\n * ```ts\n * provide(ThemeCtx, 'dark');\n * ```\n */\nexport function provide<T>(ctx: Context<T>, value: T): void {\n let stack = contextStacks.get(ctx.id);\n if (stack === undefined) {\n stack = [];\n contextStacks.set(ctx.id, stack);\n }\n stack.push(value);\n}\n\n/**\n * Read the current value of a context.\n * Returns the most recently provided value, or the default if none was provided.\n *\n * ```ts\n * const theme = inject(ThemeCtx); // 'dark' if provided, else 'light'\n * ```\n */\nexport function inject<T>(ctx: Context<T>): T {\n const stack = contextStacks.get(ctx.id);\n if (stack === undefined || stack.length === 0) {\n return ctx.defaultValue;\n }\n return stack[stack.length - 1] as T;\n}\n\n/**\n * Remove the most recent provided value for a context.\n * Used during component teardown to restore the previous scope.\n *\n * ```ts\n * unprovide(ThemeCtx);\n * ```\n */\nexport function unprovide<T>(ctx: Context<T>): void {\n const stack = contextStacks.get(ctx.id);\n if (stack !== undefined && stack.length > 0) {\n stack.pop();\n // Clean up empty stacks to avoid memory leaks\n if (stack.length === 0) {\n contextStacks.delete(ctx.id);\n }\n }\n}\n","/**\n * Forma State - Store\n *\n * Deep reactive store with path-based signal granularity.\n * Every property path (e.g. `user.name`, `items.0.done`) gets its own signal,\n * so only effects that read a specific path are notified when it changes.\n *\n * Inspired by SolidJS's createStore and Vue's reactive(), with:\n * - Lazy proxy wrapping (child objects proxied on first access)\n * - Structural sharing (replacing an object invalidates child signals)\n * - Array mutation batching (push/pop/splice/sort etc. batch their signals)\n *\n * Backed by alien-signals via forma/reactive.\n */\n\nimport { createSignal, batch, untrack } from 'forma/reactive';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ntype SignalPair = [get: () => unknown, set: (v: unknown) => void];\n\nexport type StoreSetter<T extends object> = (\n partial: Partial<T> | ((prev: T) => Partial<T>),\n) => void;\n\n// ---------------------------------------------------------------------------\n// Symbols\n// ---------------------------------------------------------------------------\n\n/** Access the underlying raw (unproxied) object from a store proxy. */\nconst RAW = Symbol('forma-raw');\n\n/** Marker: true on every store proxy so we can detect them. */\nconst PROXY = Symbol('forma-proxy');\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nconst ARRAY_MUTATORS = new Set([\n 'push',\n 'pop',\n 'shift',\n 'unshift',\n 'splice',\n 'sort',\n 'reverse',\n 'fill',\n 'copyWithin',\n]);\n\nfunction isPlainObject(v: unknown): v is Record<string, unknown> {\n if (v == null || typeof v !== 'object') return false;\n const proto = Object.getPrototypeOf(v);\n return proto === Object.prototype || proto === null || Array.isArray(v);\n}\n\nfunction shouldWrap(v: unknown): v is object {\n if (v == null || typeof v !== 'object') return false;\n // Don't wrap special built-ins (Date, RegExp, Map, Set, etc.)\n if (v instanceof Date || v instanceof RegExp || v instanceof Map ||\n v instanceof Set || v instanceof WeakMap || v instanceof WeakSet ||\n v instanceof Error || v instanceof Promise) {\n return false;\n }\n // Already a store proxy — no double wrapping\n if ((v as any)[PROXY]) return false;\n return true;\n}\n\n// ---------------------------------------------------------------------------\n// Deep-clone helper (used for functional setter snapshots)\n// ---------------------------------------------------------------------------\n\nfunction deepClone(obj: unknown, seen?: WeakSet<object>): unknown {\n if (obj === null || typeof obj !== 'object') return obj;\n if (!seen) seen = new WeakSet();\n if (seen.has(obj as object)) return obj; // circular — return ref as-is\n seen.add(obj as object);\n if (Array.isArray(obj)) return obj.map(item => deepClone(item, seen));\n const out: Record<string, unknown> = {};\n for (const key of Object.keys(obj as Record<string, unknown>)) {\n out[key] = deepClone((obj as any)[key], seen);\n }\n return out;\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Create a deep reactive store.\n *\n * Returns a tuple of `[getter proxy, setter function]`.\n * The getter proxy tracks reads at every property path via dedicated signals.\n * Setting a property (either via `setState()` or direct mutation like\n * `state.user.name = 'Bob'`) only notifies effects that actually read that\n * specific path.\n *\n * ```ts\n * const [state, setState] = createStore({\n * count: 0,\n * user: { name: 'Alice', age: 30 },\n * items: [{ text: 'Buy milk', done: false }],\n * });\n *\n * // Fine-grained reads\n * state.user.name; // tracked at path \"user.name\"\n * state.items[0].done; // tracked at path \"items.0.done\"\n *\n * // Setter API (batched)\n * setState({ count: 1 });\n * setState(prev => ({ count: prev.count + 1 }));\n *\n * // Direct mutation (via Proxy set trap)\n * state.user.name = 'Bob'; // only \"user.name\" subscribers notified\n * state.items[0].done = true;\n *\n * // Array mutations\n * state.items.push({ text: 'Walk dog', done: false });\n * ```\n *\n * **Limitation:** `Object.keys(state)`, `for...in`, and spread (`{...state}`)\n * are NOT reactive. Adding or removing a property will not trigger effects\n * that iterated over keys. Use signals or explicit arrays for collections\n * that need to react to membership changes.\n */\nexport function createStore<T extends object>(\n initial: T,\n): [get: T, set: StoreSetter<T>] {\n // -------------------------------------------------------------------------\n // Signal-per-path map\n // -------------------------------------------------------------------------\n\n /** Map of dot-separated paths -> signal pairs. */\n const signals = new Map<string, SignalPair>();\n\n /** Parent path -> set of direct child paths for O(1) child invalidation. */\n const children = new Map<string, Set<string>>();\n\n /**\n * Register a signal path with its parent in the adjacency map.\n * This allows walking the tree instead of scanning all signals.\n */\n function registerChild(path: string): void {\n const lastDot = path.lastIndexOf('.');\n if (lastDot === -1) return; // root-level, no parent\n const parentPath = path.substring(0, lastDot);\n let set = children.get(parentPath);\n if (!set) { set = new Set(); children.set(parentPath, set); }\n set.add(path);\n }\n\n /**\n * Get or create the signal for a given path.\n * When creating, seeds with `initialValue`.\n */\n function getSignal(path: string, initialValue?: unknown): SignalPair {\n let pair = signals.get(path);\n if (!pair) {\n pair = createSignal<unknown>(initialValue) as SignalPair;\n signals.set(path, pair);\n registerChild(path);\n }\n return pair;\n }\n\n // -------------------------------------------------------------------------\n // Proxy cache (raw object -> proxy)\n // -------------------------------------------------------------------------\n\n /**\n * WeakMap so proxies for child objects are reused as long as the raw object\n * is alive. When an object is replaced, the old entry is GC'd naturally.\n */\n const proxyCache = new WeakMap<object, object>();\n\n // -------------------------------------------------------------------------\n // Invalidation\n // -------------------------------------------------------------------------\n\n /**\n * Recursively delete all child signals using the adjacency map.\n * Called when an entire sub-tree is replaced so stale signals are not reused.\n * O(k) where k = number of descendant signals, instead of O(n) over all signals.\n */\n function invalidateChildren(parentPath: string): void {\n const childSet = children.get(parentPath);\n if (!childSet) return;\n for (const childPath of childSet) {\n // Recursively invalidate grandchildren first\n invalidateChildren(childPath);\n // Remove the signal itself\n signals.delete(childPath);\n // Clean up this child's entry in the adjacency map\n children.delete(childPath);\n }\n // Clear the parent's children set (all children have been removed)\n childSet.clear();\n }\n\n // -------------------------------------------------------------------------\n // Proxy factory (lazy, recursive)\n // -------------------------------------------------------------------------\n\n function wrap(raw: object, basePath: string): object {\n // Primitives / non-wrappable values pass through\n if (!shouldWrap(raw)) return raw;\n\n // Return cached proxy if we already have one for this raw object\n const cached = proxyCache.get(raw);\n if (cached) return cached;\n\n const isArr = Array.isArray(raw);\n // Pre-compute the path prefix to avoid repeated string concatenation in hot paths\n const basePrefix = basePath ? basePath + '.' : '';\n\n // Inline cache: skip Map lookup when the same key is accessed repeatedly\n // (very common in render loops and effects that read the same property)\n let lastKey: string = '';\n let lastSignal: SignalPair | undefined;\n\n const proxy: object = new Proxy(raw, {\n // -------------------------------------------------------------------\n // GET\n // -------------------------------------------------------------------\n get(target: any, prop: PropertyKey, receiver: unknown): unknown {\n // Escape hatches\n if (prop === RAW) return target;\n if (prop === PROXY) return true;\n\n // Symbols pass through (Symbol.iterator, Symbol.toPrimitive, etc.)\n if (typeof prop === 'symbol') {\n return Reflect.get(target, prop, receiver);\n }\n\n const key = String(prop);\n // Cache-friendly path construction: avoid template literals in hot path\n const childPath = basePrefix + key;\n\n // ------------------------------------------------------------------\n // Array mutator methods — wrap to batch signal updates\n // ------------------------------------------------------------------\n if (isArr && ARRAY_MUTATORS.has(key)) {\n return (...args: unknown[]) => {\n let result: unknown;\n batch(() => {\n // Unwrap proxy arguments (e.g. pushing a store proxy)\n const rawArgs = args.map((a) =>\n a != null && typeof a === 'object' && (a as any)[RAW]\n ? (a as any)[RAW]\n : a,\n );\n result = (target as any)[key].apply(target, rawArgs);\n\n // Invalidate all child paths so they recreate from the\n // mutated raw array on next access.\n invalidateChildren(basePath);\n\n // Notify the length signal\n const [, setLen] = getSignal(\n basePrefix + 'length',\n (target as unknown[]).length,\n );\n setLen((target as unknown[]).length);\n });\n return result;\n };\n }\n\n // ------------------------------------------------------------------\n // Array `length` — special-case so it's always tracked\n // ------------------------------------------------------------------\n if (isArr && key === 'length') {\n const [getter] = getSignal(childPath, target.length);\n getter(); // subscribe\n return target.length;\n }\n\n // ------------------------------------------------------------------\n // Regular property access\n // ------------------------------------------------------------------\n const value = Reflect.get(target, prop);\n\n // Inline cache: if same key as last access, skip Map lookup\n let pair: SignalPair;\n if (key === lastKey && lastSignal) {\n pair = lastSignal;\n } else {\n pair = getSignal(childPath, value);\n lastKey = key;\n lastSignal = pair;\n }\n\n pair[0](); // subscribe to this path\n\n // Lazily wrap child objects/arrays\n if (shouldWrap(value)) {\n return wrap(value, childPath);\n }\n\n return value;\n },\n\n // -------------------------------------------------------------------\n // SET\n // -------------------------------------------------------------------\n set(target: any, prop: PropertyKey, value: unknown): boolean {\n if (typeof prop === 'symbol') {\n return Reflect.set(target, prop, value);\n }\n\n const key = String(prop);\n const childPath = basePrefix + key;\n\n // Unwrap if the value being set is itself a proxy\n const rawValue =\n value != null && typeof value === 'object' && (value as any)[RAW]\n ? (value as any)[RAW]\n : value;\n\n // Write to the underlying object\n Reflect.set(target, prop, rawValue);\n\n // If we're replacing with an object, invalidate all child signals\n // and evict the old proxy so sub-paths are recreated on next access.\n if (rawValue != null && typeof rawValue === 'object') {\n invalidateChildren(childPath);\n // Remove cached proxy for the old value so a fresh one is created\n // on the next access.\n }\n\n // Update the length signal when setting indexed array elements\n if (isArr && key !== 'length') {\n const lengthPath = basePrefix + 'length';\n const lenPair = signals.get(lengthPath);\n if (lenPair) {\n lenPair[1](target.length);\n }\n }\n\n // Notify (or create) the signal for this path\n const [, setter] = getSignal(childPath, rawValue);\n setter(rawValue);\n\n return true;\n },\n\n // -------------------------------------------------------------------\n // HAS — track membership checks\n // -------------------------------------------------------------------\n has(target: any, prop: PropertyKey): boolean {\n if (typeof prop === 'symbol') {\n return Reflect.has(target, prop);\n }\n const key = String(prop);\n const childPath = basePrefix + key;\n // Subscribe so that `'x' in state` is tracked\n const [getter] = getSignal(childPath, Reflect.get(target, prop));\n getter();\n return Reflect.has(target, prop);\n },\n\n // -------------------------------------------------------------------\n // OWNKEYS — return keys from the raw target\n // -------------------------------------------------------------------\n ownKeys(target: any): (string | symbol)[] {\n return Reflect.ownKeys(target);\n },\n\n // -------------------------------------------------------------------\n // GETOWNPROPERTYDESCRIPTOR — needed for Object.keys / spread / ...\n // -------------------------------------------------------------------\n getOwnPropertyDescriptor(target: any, prop: PropertyKey) {\n return Object.getOwnPropertyDescriptor(target, prop);\n },\n\n // -------------------------------------------------------------------\n // DELETEPROPERTY — clean up signals when a key is removed\n // -------------------------------------------------------------------\n deleteProperty(target: any, prop: PropertyKey): boolean {\n if (typeof prop === 'symbol') {\n return Reflect.deleteProperty(target, prop);\n }\n\n const key = String(prop);\n const childPath = basePrefix + key;\n\n const result = Reflect.deleteProperty(target, prop);\n\n // Clean up the signal for this path and all children via adjacency map\n invalidateChildren(childPath);\n signals.delete(childPath);\n\n // Remove from parent's children set in the adjacency map\n const parentPath = basePath;\n if (parentPath !== undefined) {\n const parentSet = children.get(parentPath);\n if (parentSet) {\n parentSet.delete(childPath);\n if (parentSet.size === 0) children.delete(parentPath);\n }\n }\n // Clean up the deleted path's own children entry\n children.delete(childPath);\n\n return result;\n },\n });\n\n proxyCache.set(raw, proxy);\n return proxy;\n }\n\n // -------------------------------------------------------------------------\n // Root proxy\n // -------------------------------------------------------------------------\n\n const rootProxy = wrap(initial, '') as T;\n\n // -------------------------------------------------------------------------\n // Snapshot (for functional setter)\n // -------------------------------------------------------------------------\n\n /**\n * Produce a plain-object snapshot of the store's current state.\n * Reads are untracked so calling `setState(prev => ...)` inside an effect\n * does not create additional subscriptions.\n */\n function getCurrentSnapshot(): T {\n return untrack(() => deepClone(initial) as T);\n }\n\n // -------------------------------------------------------------------------\n // Setter\n // -------------------------------------------------------------------------\n\n const setter: StoreSetter<T> = (\n partial: Partial<T> | ((prev: T) => Partial<T>),\n ) => {\n // Resolve functional updates by snapshotting current state\n const updates: Partial<T> =\n typeof partial === 'function' ? partial(getCurrentSnapshot()) : partial;\n\n // Batch all top-level key writes so effects run only once\n batch(() => {\n for (const key of Object.keys(updates) as (keyof T & string)[]) {\n (rootProxy as Record<string, unknown>)[key] = (updates as Record<string, unknown>)[key];\n }\n });\n };\n\n return [rootProxy, setter];\n}\n","/**\n * Forma State - History\n *\n * Undo/redo for any signal. Tracks changes and maintains undo/redo stacks\n * with reactive canUndo/canRedo signals.\n * Zero dependencies -- native browser APIs only.\n */\n\nimport { createSignal, internalEffect, batch } from 'forma/reactive';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface HistoryControls<T> {\n /** Undo the last change, restoring the previous value. */\n undo: () => void;\n /** Redo the last undone change. */\n redo: () => void;\n /** Reactive getter: true if undo is available. */\n canUndo: () => boolean;\n /** Reactive getter: true if redo is available. */\n canRedo: () => boolean;\n /** Reactive getter: the full history stack (past + current + future). */\n history: () => T[];\n /** Reactive getter: current position in the history stack (0-based). */\n cursor: () => number;\n /** Clear all history, keeping only the current value. */\n clear: () => void;\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Create undo/redo history tracking for a signal.\n *\n * ```ts\n * const [count, setCount] = createSignal(0);\n * const h = createHistory([count, setCount], { maxLength: 50 });\n *\n * setCount(1);\n * setCount(2);\n * h.undo(); // count() === 1\n * h.redo(); // count() === 2\n * h.canUndo(); // true (reactive)\n * ```\n */\nexport function createHistory<T>(\n source: [get: () => T, set: (v: T) => void],\n options?: { maxLength?: number },\n): HistoryControls<T> {\n const [sourceGet, sourceSet] = source;\n const maxLength = options?.maxLength ?? 100;\n\n // ---------- Internal mutable state (not signals) ----------\n // We use plain arrays/numbers to avoid creating signal dependencies\n // inside the source-tracking effect, which would cause re-entrance issues.\n let _stack: T[] = [sourceGet()];\n let _cursor = 0;\n\n // ---------- Reactive output signals ----------\n // These are signals that external consumers can subscribe to.\n // We update them explicitly after every mutation.\n const [stackSignal, setStackSignal] = createSignal<T[]>([..._stack]);\n const [cursorSignal, setCursorSignal] = createSignal(_cursor);\n // Separate signal for stack length so canRedo only depends on numeric\n // signals and doesn't re-fire when array reference changes but length stays.\n const [stackLenSignal, setStackLenSignal] = createSignal(_stack.length);\n\n /** Sync the reactive output signals with internal mutable state. */\n function syncSignals(): void {\n batch(() => {\n setStackSignal([..._stack]);\n setCursorSignal(_cursor);\n setStackLenSignal(_stack.length);\n });\n }\n\n // Track whether the next source change should be ignored\n // (because it was caused by undo/redo, not an external set).\n let ignoreNext = false;\n let isFirstRun = true;\n\n // Watch the source signal for external changes\n internalEffect(() => {\n const value = sourceGet();\n\n // Skip the initial effect run -- the initial value is already in the stack\n if (isFirstRun) {\n isFirstRun = false;\n return;\n }\n\n if (ignoreNext) {\n ignoreNext = false;\n return;\n }\n\n // New value from an external set: push onto history\n // Discard any \"future\" entries after the current cursor (redo is cleared)\n _stack = _stack.slice(0, _cursor + 1);\n _stack.push(value);\n\n // Enforce maxLength\n if (_stack.length > maxLength) {\n _stack.splice(0, _stack.length - maxLength);\n }\n\n _cursor = _stack.length - 1;\n syncSignals();\n });\n\n // Reactive derived getters\n const canUndo = (): boolean => cursorSignal() > 0;\n const canRedo = (): boolean => cursorSignal() < stackLenSignal() - 1;\n\n const undo = (): void => {\n if (_cursor <= 0) return;\n\n _cursor--;\n ignoreNext = true;\n sourceSet(_stack[_cursor] as T);\n syncSignals();\n };\n\n const redo = (): void => {\n if (_cursor >= _stack.length - 1) return;\n\n _cursor++;\n ignoreNext = true;\n sourceSet(_stack[_cursor] as T);\n syncSignals();\n };\n\n const clear = (): void => {\n const currentValue = sourceGet();\n _stack = [currentValue];\n _cursor = 0;\n syncSignals();\n };\n\n return {\n undo,\n redo,\n canUndo,\n canRedo,\n history: () => stackSignal(),\n cursor: () => cursorSignal(),\n clear,\n };\n}\n","/**\n * Forma State - Persist\n *\n * Auto-persist a signal to localStorage (or any Storage-compatible backend).\n * Reads stored value on creation; writes on every signal change.\n * Zero dependencies -- native browser APIs only.\n */\n\nimport { internalEffect } from 'forma/reactive';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface PersistOptions<T> {\n /** Storage backend. Defaults to localStorage. */\n storage?: Storage;\n /** Custom serializer. Defaults to JSON.stringify. */\n serialize?: (v: T) => string;\n /** Custom deserializer. Defaults to JSON.parse. */\n deserialize?: (s: string) => T;\n /** Optional validator — return true if the deserialized value is valid. Rejects corrupt/tampered data. */\n validate?: (v: unknown) => v is T;\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Persist a signal's value to storage.\n *\n * On creation, reads the stored value (if any) and hydrates the signal.\n * Then sets up an effect to write to storage whenever the signal changes.\n *\n * ```ts\n * const [theme, setTheme] = createSignal('light');\n * persist([theme, setTheme], 'app:theme');\n *\n * setTheme('dark'); // auto-saved to localStorage under key 'app:theme'\n * ```\n */\nexport function persist<T>(\n source: [get: () => T, set: (v: T) => void],\n key: string,\n options?: PersistOptions<T>,\n): void {\n const [sourceGet, sourceSet] = source;\n const storage = options?.storage ?? globalThis.localStorage;\n const serialize = options?.serialize ?? JSON.stringify;\n const deserialize = options?.deserialize ?? JSON.parse;\n const validate = options?.validate;\n\n // Step 1: Hydrate from storage (if a value exists)\n try {\n const stored = storage.getItem(key);\n if (stored !== null) {\n const value = deserialize(stored);\n if (!validate || validate(value)) {\n sourceSet(value);\n }\n }\n } catch {\n // Stored data is invalid or storage is unavailable -- ignore and keep\n // the signal's current value.\n }\n\n // Step 2: Set up effect to persist on changes\n internalEffect(() => {\n const value = sourceGet();\n try {\n const serialized = serialize(value);\n storage.setItem(key, serialized);\n } catch {\n // Storage write failed (e.g., quota exceeded) -- silently ignore.\n }\n });\n}\n","// Typed event bus — pub/sub pattern\n\nexport interface EventBus<T extends Record<string, unknown>> {\n on<K extends keyof T>(event: K, handler: (payload: T[K]) => void): () => void;\n once<K extends keyof T>(event: K, handler: (payload: T[K]) => void): () => void;\n emit<K extends keyof T>(event: K, payload: T[K]): void;\n off<K extends keyof T>(event: K, handler: (payload: T[K]) => void): void;\n clear(): void;\n}\n\nexport function createBus<\n T extends Record<string, unknown> = Record<string, unknown>,\n>(): EventBus<T> {\n const listeners = new Map<keyof T, Set<(payload: any) => void>>();\n\n function getHandlers<K extends keyof T>(event: K): Set<(payload: any) => void> {\n let set = listeners.get(event);\n if (!set) {\n set = new Set();\n listeners.set(event, set);\n }\n return set;\n }\n\n function on<K extends keyof T>(\n event: K,\n handler: (payload: T[K]) => void,\n ): () => void {\n const set = getHandlers(event);\n set.add(handler);\n return () => {\n set.delete(handler);\n };\n }\n\n function once<K extends keyof T>(\n event: K,\n handler: (payload: T[K]) => void,\n ): () => void {\n const wrapper = (payload: T[K]) => {\n off(event, wrapper);\n handler(payload);\n };\n return on(event, wrapper);\n }\n\n function emit<K extends keyof T>(event: K, payload: T[K]): void {\n const set = listeners.get(event);\n if (set) {\n // Iterate over a snapshot so removals during emit are safe\n for (const handler of [...set]) {\n try {\n handler(payload);\n } catch (e) {\n console.error(`[forma] Bus handler error on \"${String(event)}\":`, e);\n }\n }\n }\n }\n\n function off<K extends keyof T>(\n event: K,\n handler: (payload: T[K]) => void,\n ): void {\n const set = listeners.get(event);\n if (set) {\n set.delete(handler);\n }\n }\n\n function clear(): void {\n listeners.clear();\n }\n\n return { on, once, emit, off, clear };\n}\n","// Event delegation — single listener on parent, matches children by selector\n\nexport function delegate<K extends keyof HTMLElementEventMap>(\n container: HTMLElement | Document,\n selector: string,\n event: K,\n handler: (e: HTMLElementEventMap[K], matchedEl: HTMLElement) => void,\n options?: AddEventListenerOptions,\n): () => void {\n const listener = (e: Event) => {\n const target = e.target;\n if (!(target instanceof HTMLElement)) return;\n\n const root =\n container instanceof Document ? container.documentElement : container;\n const matched = target.closest(selector);\n\n if (matched instanceof HTMLElement && root.contains(matched)) {\n handler(e as HTMLElementEventMap[K], matched);\n }\n };\n\n container.addEventListener(event, listener, options);\n\n return () => {\n container.removeEventListener(event, listener, options);\n };\n}\n","// Keyboard shortcut handler\n\ntype KeyCombo = string; // e.g., 'ctrl+s', 'shift+enter', 'escape', 'ctrl+shift+z'\n\nexport interface KeyOptions {\n target?: EventTarget;\n preventDefault?: boolean;\n}\n\ninterface ParsedCombo {\n ctrl: boolean;\n shift: boolean;\n alt: boolean;\n meta: boolean;\n key: string;\n}\n\nfunction parseCombo(combo: KeyCombo): ParsedCombo {\n const parts = combo.toLowerCase().split('+').map((p) => p.trim());\n const modifiers: ParsedCombo = {\n ctrl: false,\n shift: false,\n alt: false,\n meta: false,\n key: '',\n };\n\n for (const part of parts) {\n switch (part) {\n case 'ctrl':\n case 'control':\n modifiers.ctrl = true;\n break;\n case 'shift':\n modifiers.shift = true;\n break;\n case 'alt':\n modifiers.alt = true;\n break;\n case 'meta':\n case 'cmd':\n case 'command':\n modifiers.meta = true;\n break;\n default:\n modifiers.key = part;\n }\n }\n\n return modifiers;\n}\n\nfunction matchesCombo(e: KeyboardEvent, parsed: ParsedCombo): boolean {\n if (e.ctrlKey !== parsed.ctrl) return false;\n if (e.shiftKey !== parsed.shift) return false;\n if (e.altKey !== parsed.alt) return false;\n if (e.metaKey !== parsed.meta) return false;\n return e.key.toLowerCase() === parsed.key;\n}\n\nexport function onKey(\n combo: KeyCombo,\n handler: (e: KeyboardEvent) => void,\n options?: KeyOptions,\n): () => void {\n const target: EventTarget = options?.target ?? document;\n const shouldPreventDefault = options?.preventDefault ?? true;\n const parsed = parseCombo(combo);\n\n const listener = (e: Event) => {\n if (!(e instanceof KeyboardEvent)) return;\n if (matchesCombo(e, parsed)) {\n if (shouldPreventDefault) {\n e.preventDefault();\n }\n handler(e);\n }\n };\n\n target.addEventListener('keydown', listener);\n\n return () => {\n target.removeEventListener('keydown', listener);\n };\n}\n","// Typed query helpers\n\nexport function $<T extends HTMLElement = HTMLElement>(\n selector: string,\n parent?: ParentNode,\n): T | null {\n return (parent ?? document).querySelector<T>(selector);\n}\n\nexport function $$<T extends HTMLElement = HTMLElement>(\n selector: string,\n parent?: ParentNode,\n): T[] {\n return Array.from((parent ?? document).querySelectorAll<T>(selector));\n}\n","// DOM mutation helpers\n\nexport function addClass(el: HTMLElement, ...classes: string[]): void {\n el.classList.add(...classes);\n}\n\nexport function removeClass(el: HTMLElement, ...classes: string[]): void {\n el.classList.remove(...classes);\n}\n\nexport function toggleClass(\n el: HTMLElement,\n className: string,\n force?: boolean,\n): boolean {\n return el.classList.toggle(className, force);\n}\n\nexport function setStyle(\n el: HTMLElement,\n styles: Partial<CSSStyleDeclaration>,\n): void {\n for (const [key, value] of Object.entries(styles)) {\n if (value !== undefined) {\n (el.style as any)[key] = value;\n }\n }\n}\n\nexport function setAttr(\n el: HTMLElement,\n attrs: Record<string, string | boolean | null>,\n): void {\n for (const [name, value] of Object.entries(attrs)) {\n if (value === false || value === null) {\n el.removeAttribute(name);\n } else if (value === true) {\n el.setAttribute(name, '');\n } else {\n el.setAttribute(name, value);\n }\n }\n}\n\nexport function setText(el: HTMLElement, text: string): void {\n el.textContent = text;\n}\n\n/**\n * Set raw HTML on an element. **No sanitization is performed.**\n *\n * Prefer `setText()` for user-controlled content. Only use this when you\n * trust the HTML source (e.g., server-rendered markup you control).\n *\n * @deprecated Use `setHTMLUnsafe` instead — renamed to signal risk.\n */\nexport function setHTML(el: HTMLElement, html: string): void {\n el.innerHTML = html;\n}\n\n/**\n * Set raw HTML on an element. **No sanitization is performed.**\n *\n * Prefer `setText()` for user-controlled content. Only use this when you\n * trust the HTML source (e.g., server-rendered markup you control).\n */\nexport function setHTMLUnsafe(el: HTMLElement, html: string): void {\n el.innerHTML = html;\n}\n","// DOM traversal helpers\n\nexport function closest<T extends HTMLElement = HTMLElement>(\n el: HTMLElement,\n selector: string,\n): T | null {\n return el.closest<T>(selector);\n}\n\nexport function children<T extends HTMLElement = HTMLElement>(\n el: HTMLElement,\n selector?: string,\n): T[] {\n const all = Array.from(el.children) as HTMLElement[];\n if (!selector) return all as T[];\n return all.filter((child) => child.matches(selector)) as T[];\n}\n\nexport function siblings<T extends HTMLElement = HTMLElement>(\n el: HTMLElement,\n selector?: string,\n): T[] {\n const parentEl = el.parentElement;\n if (!parentEl) return [];\n const all = Array.from(parentEl.children) as HTMLElement[];\n const sibs = all.filter((child) => child !== el);\n if (!selector) return sibs as T[];\n return sibs.filter((child) => child.matches(selector)) as T[];\n}\n\nexport function parent<T extends HTMLElement = HTMLElement>(\n el: HTMLElement,\n): T | null {\n return el.parentElement as T | null;\n}\n\nexport function nextSibling<T extends HTMLElement = HTMLElement>(\n el: HTMLElement,\n selector?: string,\n): T | null {\n let sib = el.nextElementSibling;\n while (sib) {\n if (sib instanceof HTMLElement) {\n if (!selector || sib.matches(selector)) {\n return sib as T;\n }\n }\n sib = sib.nextElementSibling;\n }\n return null;\n}\n\nexport function prevSibling<T extends HTMLElement = HTMLElement>(\n el: HTMLElement,\n selector?: string,\n): T | null {\n let sib = el.previousElementSibling;\n while (sib) {\n if (sib instanceof HTMLElement) {\n if (!selector || sib.matches(selector)) {\n return sib as T;\n }\n }\n sib = sib.previousElementSibling;\n }\n return null;\n}\n","// Observer wrappers — clean API for ResizeObserver, IntersectionObserver, MutationObserver\n\nexport function onResize(\n el: HTMLElement,\n handler: (entry: ResizeObserverEntry) => void,\n): () => void {\n const observer = new ResizeObserver((entries) => {\n for (const entry of entries) {\n handler(entry);\n }\n });\n observer.observe(el);\n return () => {\n observer.disconnect();\n };\n}\n\nexport function onIntersect(\n el: HTMLElement,\n handler: (entry: IntersectionObserverEntry) => void,\n options?: IntersectionObserverInit,\n): () => void {\n const observer = new IntersectionObserver((entries) => {\n for (const entry of entries) {\n handler(entry);\n }\n }, options);\n observer.observe(el);\n return () => {\n observer.disconnect();\n };\n}\n\nexport function onMutation(\n el: HTMLElement,\n handler: (mutations: MutationRecord[]) => void,\n options?: MutationObserverInit,\n): () => void {\n const observer = new MutationObserver((mutations) => {\n handler(mutations);\n });\n observer.observe(el, options ?? { childList: true, subtree: true });\n return () => {\n observer.disconnect();\n };\n}\n"],"mappings":"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","names":["src_exports","__export","$","$$","Fragment","activateIslands","addClass","batch","children","cleanup","closest","createBus","createComputed","createContext","createEffect","createErrorBoundary","createHistory","createList","createMemo","createPortal","createReducer","createRef","createResource","createRoot","createShow","createSignal","createStore","createSuspense","createSwitch","createText","deactivateAllIslands","deactivateIsland","defineComponent","delegate","disposeComponent","fragment","getBatchDepth","h","hydrateIsland","inject","isComputed","isEffect","isEffectScope","isSignal","mount","nextSibling","on","onCleanup","onError","onIntersect","onKey","onMount","onMutation","onResize","onUnmount","parent","persist","prevSibling","provide","reconcileList","removeClass","setAttr","setHTML","setHTMLUnsafe","setStyle","setText","siblings","toggleClass","trackDisposer","trigger","unprovide","untrack","createReactiveSystem","update","notify","unwatched","link","unlink","propagate","checkDirty","shallowPropagate","dep","sub","version","prevDep","nextDep","prevSub","newLink","nextSub","next","stack","top","flags","isValidLink","subSubs","checkDepth","dirty","subs","firstSub","hasMultipleSubs","checkLink","cycle","batchDepth","notifyIndex","queuedLength","activeSub","queued","link","unlink","propagate","checkDirty","shallowPropagate","createReactiveSystem","node","updateComputed","updateSignal","effect","insertIndex","firstInsertedIndex","left","purgeDeps","effectScopeOper","setActiveSub","sub","prevSub","activeSub","getBatchDepth","batchDepth","startBatch","endBatch","flush","isSignal","fn","signalOper","isComputed","computedOper","isEffect","effectOper","isEffectScope","effectScopeOper","signal","initialValue","computed","getter","effect","e","link","effectScope","trigger","dep","unlink","subs","propagate","shallowPropagate","updateComputed","c","cycle","oldValue","purgeDeps","updateSignal","s","run","flags","checkDirty","notifyIndex","queuedLength","queued","value","depsTail","applySignalSet","s","v","equals","prevSub","setActiveSub","prev","next","createSignal","initialValue","options","signal","getter","eq","currentRoot","rootStack","createRoot","fn","scope","dispose","d","result","effectScope","registerDisposer","hasActiveRoot","currentCleanupCollector","onCleanup","fn","setCleanupCollector","collector","prev","__DEV__","_errorHandler","onError","handler","reportError","error","source","POOL_SIZE","MAX_REENTRANT_RUNS","pool","i","poolIdx","acquireArray","arr","releaseArray","runCleanup","fn","e","reportError","runCleanups","bag","internalEffect","dispose","effect","hasActiveRoot","registerDisposer","createEffect","shouldRegister","cleanup","cleanupBag","nextCleanup","nextCleanupBag","addCleanup","cb","skipCleanupInfra","firstRun","running","rerunRequested","runOnce","prevCollector","setCleanupCollector","result","reentrantRuns","disposed","wrappedDispose","createComputed","fn","computed","createMemo","createComputed","batch","fn","startBatch","endBatch","untrack","fn","prev","setActiveSub","on","deps","fn","options","prev","isFirst","value","result","untrack","createRef","initialValue","createReducer","reducer","initialState","state","setState","createSignal","action","prev","currentSuspenseContext","suspenseStack","pushSuspenseContext","ctx","popSuspenseContext","getSuspenseContext","createResource","source","fetcher","options","data","setData","createSignal","loading","setLoading","error","setError","suspenseCtx","getSuspenseContext","abortController","fetchVersion","doFetch","sourceValue","untrack","controller","version","isLatest","suspensePending","result","err","internalEffect","resource","value","longestIncreasingSubsequence","arr","n","tails","tailIndices","predecessor","tailsLen","i","val","lo","hi","mid","result","idx","SMALL_LIST_THRESHOLD","ABORT_SYM","CACHE_SYM","DYNAMIC_CHILD_SYM","canPatchStaticElement","target","source","patchStaticElement","sourceAttrNames","attr","reconcileSmall","parent","oldItems","newItems","oldNodes","keyFn","createFn","updateFn","beforeNode","hooks","oldLen","newLen","oldKeys","oldIndices","oldUsed","key","found","j","node","allSameOrder","nodes","reusedIndices","reusedPositions","lisOfReused","lisFlags","li","newNodes","nextSibling","isNew","reconcileList","oldKeyMap","oldIdx","createList","items","renderFn","options","hydrating","startMarker","endMarker","fragment","cache","currentNodes","currentItems","updateOnItemChange","internalEffect","__DEV__","cleanItems","item","seen","getIndex","setIndex","createSignal","element","untrack","cached","next","_node","newCache","createShow","when","thenFn","elseFn","hydrating","branch","startMarker","endMarker","fragment","currentNode","lastTruthy","currentDispose","showDispose","internalEffect","truthy","DEBUG","DEBUG_LABEL","parent","branchFn","branchDispose","createRoot","dispose","untrack","ABORT_SYM","hydrating","setHydrating","value","isDescriptor","v","isShowDescriptor","isListDescriptor","applyDynamicProps","el","props","key","value","ac","ABORT_SYM","fn","attrKey","internalEffect","v","ensureNode","isDescriptor","descriptorToElement","isShowDescriptor","prevH","hydrating","createShow","isListDescriptor","createList","desc","prevHydrating","children","child","h","isIslandStart","data","isShowStart","isTextStart","isListStart","findClosingMarker","start","closing","node","findTextBetween","end","nextElementBetweenMarkers","extractContentBetweenMarkers","frag","next","setupShowEffect","marker","currentCondition","thenFragment","elseFragment","__DEV__","trueBranch","parent","current","branch","adoptBranchContent","regionStart","regionEnd","adoptNode","innerStart","innerEnd","ssrEl","fresh","cursor","ssrKeyMap","ssrElements","currentItems","untrack","listKeyFn","listRenderFn","useIndexFallback","adoptedNodes","adoptedItems","usedIndices","i","item","ssrNode","getIndex","createSignal","unusedKey","unusedNode","adoptedNode","cache","setIndex","reconcileNodes","reconcileItems","newItems","result","reconcileList","element","_node","cached","newCache","initial","endMarker","textNode","created","hydrateIsland","component","target","n","name","attr","setHydrating","descriptor","Fragment","SVG_NS","XLINK_NS","SVG_TAGS","BOOLEAN_ATTRS","ELEMENT_PROTOS","getProto","tag","EVENT_NAMES","eventName","key","ABORT_SYM","getAbortController","el","controller","cleanup","CACHE_SYM","DYNAMIC_CHILD_SYM","getCache","handleClass","_key","value","internalEffect","v","cache","handleStyle","prevKeys","style","nextKeys","k","c","handleEvent","handleInnerHTML","resolved","html","handleXLink","localName","handleBooleanAttr","handleGenericAttr","strVal","PROP_HANDLERS","attr","applyProp","handler","applyStaticProp","appendChild","parent","child","currentNode","text","tn","item","h","props","children","mergedProps","frag","tagName","hydrating","hasDynamic","childLen","only","fragment","createText","value","node","internalEffect","mount","component","container","target","disposeRoot","createRoot","dispose","hydrateIsland","dom","unmounted","createSwitch","value","cases","fallback","startMarker","endMarker","fragment","cache","currentNode","currentMatch","UNSET","switchDispose","internalEffect","val","DEBUG","parent","scooped","matchedCase","c","entry","branchDispose","node","createRoot","dispose","untrack","createPortal","children","target","placeholder","resolvedTarget","mountedNode","removeMountedNode","createEffect","node","createErrorBoundary","tryFn","catchFn","startMarker","endMarker","fragment","retryCount","setRetryCount","createSignal","currentNode","internalEffect","parent","e","error","c","createSuspense","fallback","children","startMarker","endMarker","fragment","pending","setPending","createSignal","currentNode","resolvedNode","fallbackNode","pushSuspenseContext","p","popSuspenseContext","internalEffect","parent","newNode","FORBIDDEN_PROP_KEYS","sanitizeProps","obj","key","loadIslandProps","root","id","sharedProps","inline","activateIslands","registry","scriptBlock","islands","componentName","hydrateFn","__DEV__","trigger","observer","entries","entry","hydrateIslandRoot","hydrate","deactivateIsland","el","dispose","deactivateAllIslands","island","props","activeRoot","createRoot","hydrateIsland","err","currentLifecycleContext","lifecycleStack","pushLifecycleContext","ctx","popLifecycleContext","onMount","fn","onUnmount","DISPOSE_KEY","defineComponent","setupOrDef","setup","name","dom","dispose","cb","e","reportError","d","cleanup","disposeComponent","disposable","trackDisposer","contextStacks","createContext","defaultValue","provide","ctx","value","stack","inject","unprovide","RAW","PROXY","ARRAY_MUTATORS","shouldWrap","v","PROXY","deepClone","obj","seen","item","out","key","createStore","initial","signals","children","registerChild","path","lastDot","parentPath","set","getSignal","initialValue","pair","createSignal","proxyCache","invalidateChildren","childSet","childPath","wrap","raw","basePath","cached","isArr","basePrefix","lastKey","lastSignal","proxy","target","prop","receiver","RAW","ARRAY_MUTATORS","args","result","batch","rawArgs","a","setLen","getter","value","rawValue","lengthPath","lenPair","setter","parentSet","rootProxy","getCurrentSnapshot","untrack","partial","updates","createHistory","source","options","sourceGet","sourceSet","maxLength","_stack","_cursor","stackSignal","setStackSignal","createSignal","cursorSignal","setCursorSignal","stackLenSignal","setStackLenSignal","syncSignals","batch","ignoreNext","isFirstRun","internalEffect","value","persist","source","key","options","sourceGet","sourceSet","storage","serialize","deserialize","validate","stored","value","internalEffect","serialized","createBus","listeners","getHandlers","event","set","on","handler","once","wrapper","payload","off","emit","e","clear","delegate","container","selector","event","handler","options","listener","e","target","root","matched","parseCombo","combo","parts","p","modifiers","part","matchesCombo","parsed","onKey","handler","options","target","shouldPreventDefault","listener","e","$","selector","parent","$$","addClass","el","classes","removeClass","toggleClass","className","force","setStyle","styles","key","value","setAttr","attrs","name","setText","text","setHTML","html","setHTMLUnsafe","closest","el","selector","children","all","child","siblings","parentEl","sibs","parent","nextSibling","sib","prevSibling","onResize","el","handler","observer","entries","entry","onIntersect","options","onMutation","mutations"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../node_modules/alien-signals/esm/system.mjs","../node_modules/alien-signals/esm/index.mjs","../src/reactive/signal.ts","../src/reactive/root.ts","../src/reactive/cleanup.ts","../src/reactive/dev.ts","../src/reactive/effect.ts","../src/reactive/computed.ts","../src/reactive/memo.ts","../src/reactive/batch.ts","../src/reactive/untrack.ts","../src/reactive/on.ts","../src/reactive/ref.ts","../src/reactive/reducer.ts","../src/reactive/suspense-context.ts","../src/reactive/resource.ts","../src/dom/list.ts","../src/dom/show.ts","../src/dom/hydrate.ts","../src/dom/element.ts","../src/dom/text.ts","../src/dom/mount.ts","../src/dom/switch.ts","../src/dom/portal.ts","../src/dom/error-boundary.ts","../src/dom/suspense.ts","../src/dom/activate.ts","../src/component/define.ts","../src/component/context.ts","../src/state/store.ts","../src/state/history.ts","../src/state/persist.ts","../src/events/bus.ts","../src/events/delegate.ts","../src/events/keyboard.ts","../src/dom-utils/query.ts","../src/dom-utils/mutate.ts","../src/dom-utils/traverse.ts","../src/dom-utils/observe.ts"],"sourcesContent":["/// <reference path=\"./jsx.d.ts\" />\n\n// Reactive core\nexport {\n createSignal, createEffect, createComputed, createMemo, batch,\n untrack, createRoot, onCleanup, on, onError,\n createRef, createReducer, createResource,\n // Reactive introspection (alien-signals 3.x)\n isSignal, isComputed, isEffect, isEffectScope,\n getBatchDepth, trigger,\n} from './reactive';\nexport type { SignalGetter, SignalSetter, SignalOptions, Ref, Dispatch, Resource, ResourceOptions, ErrorHandler } from './reactive';\n\n// DOM\nexport { h, Fragment, fragment, createText, mount, createList, cleanup, createShow, createSwitch, createPortal, createErrorBoundary, createSuspense, hydrateIsland, activateIslands, deactivateIsland, deactivateAllIslands, reconcileList } from './dom';\nexport type { IslandHydrateFn, ReconcileResult, ListTransitionHooks, CreateListOptions, SwitchCase } from './dom';\n\n// Component\nexport { defineComponent, disposeComponent, trackDisposer, onMount, onUnmount, createContext, provide, inject, unprovide } from './component';\nexport type { SetupFn, ComponentDef, CleanupFn, Context } from './component';\n\n// State\nexport { createStore, createHistory, persist } from './state';\nexport type { StoreSetter, PersistOptions, HistoryControls } from './state';\n\n// Events\nexport { createBus, delegate, onKey } from './events';\nexport type { EventBus, KeyOptions } from './events';\n\n// DOM Utils\nexport { $, $$, addClass, removeClass, toggleClass, setStyle, setAttr, setText, setHTML, setHTMLUnsafe,\n closest, children, siblings, parent, nextSibling, prevSibling,\n onResize, onIntersect, onMutation } from './dom-utils';\n\n// ─── Subpath imports (not in this bundle — zero network code here) ───\n// HTTP: import { createFetch, createSSE, createWebSocket } from '@getforma/core/http'\n// Storage: import { createLocalStorage, createIndexedDB } from '@getforma/core/storage'\n// Server: import { createAction, $$serverFunction } from '@getforma/core/server'\n","export const ReactiveFlags = {\n None: 0,\n Mutable: 1,\n Watching: 2,\n RecursedCheck: 4,\n Recursed: 8,\n Dirty: 16,\n Pending: 32,\n};\nexport function createReactiveSystem({ update, notify, unwatched, }) {\n return {\n link,\n unlink,\n propagate,\n checkDirty,\n shallowPropagate,\n };\n function link(dep, sub, version) {\n const prevDep = sub.depsTail;\n if (prevDep !== undefined && prevDep.dep === dep) {\n return;\n }\n const nextDep = prevDep !== undefined ? prevDep.nextDep : sub.deps;\n if (nextDep !== undefined && nextDep.dep === dep) {\n nextDep.version = version;\n sub.depsTail = nextDep;\n return;\n }\n const prevSub = dep.subsTail;\n if (prevSub !== undefined && prevSub.version === version && prevSub.sub === sub) {\n return;\n }\n const newLink = sub.depsTail\n = dep.subsTail\n = {\n version,\n dep,\n sub,\n prevDep,\n nextDep,\n prevSub,\n nextSub: undefined,\n };\n if (nextDep !== undefined) {\n nextDep.prevDep = newLink;\n }\n if (prevDep !== undefined) {\n prevDep.nextDep = newLink;\n }\n else {\n sub.deps = newLink;\n }\n if (prevSub !== undefined) {\n prevSub.nextSub = newLink;\n }\n else {\n dep.subs = newLink;\n }\n }\n function unlink(link, sub = link.sub) {\n const dep = link.dep;\n const prevDep = link.prevDep;\n const nextDep = link.nextDep;\n const nextSub = link.nextSub;\n const prevSub = link.prevSub;\n if (nextDep !== undefined) {\n nextDep.prevDep = prevDep;\n }\n else {\n sub.depsTail = prevDep;\n }\n if (prevDep !== undefined) {\n prevDep.nextDep = nextDep;\n }\n else {\n sub.deps = nextDep;\n }\n if (nextSub !== undefined) {\n nextSub.prevSub = prevSub;\n }\n else {\n dep.subsTail = prevSub;\n }\n if (prevSub !== undefined) {\n prevSub.nextSub = nextSub;\n }\n else if ((dep.subs = nextSub) === undefined) {\n unwatched(dep);\n }\n return nextDep;\n }\n function propagate(link) {\n let next = link.nextSub;\n let stack;\n top: do {\n const sub = link.sub;\n let flags = sub.flags;\n if (!(flags & (4 | 8 | 16 | 32))) {\n sub.flags = flags | 32;\n }\n else if (!(flags & (4 | 8))) {\n flags = 0;\n }\n else if (!(flags & 4)) {\n sub.flags = (flags & ~8) | 32;\n }\n else if (!(flags & (16 | 32)) && isValidLink(link, sub)) {\n sub.flags = flags | (8 | 32);\n flags &= 1;\n }\n else {\n flags = 0;\n }\n if (flags & 2) {\n notify(sub);\n }\n if (flags & 1) {\n const subSubs = sub.subs;\n if (subSubs !== undefined) {\n const nextSub = (link = subSubs).nextSub;\n if (nextSub !== undefined) {\n stack = { value: next, prev: stack };\n next = nextSub;\n }\n continue;\n }\n }\n if ((link = next) !== undefined) {\n next = link.nextSub;\n continue;\n }\n while (stack !== undefined) {\n link = stack.value;\n stack = stack.prev;\n if (link !== undefined) {\n next = link.nextSub;\n continue top;\n }\n }\n break;\n } while (true);\n }\n function checkDirty(link, sub) {\n let stack;\n let checkDepth = 0;\n let dirty = false;\n top: do {\n const dep = link.dep;\n const flags = dep.flags;\n if (sub.flags & 16) {\n dirty = true;\n }\n else if ((flags & (1 | 16)) === (1 | 16)) {\n if (update(dep)) {\n const subs = dep.subs;\n if (subs.nextSub !== undefined) {\n shallowPropagate(subs);\n }\n dirty = true;\n }\n }\n else if ((flags & (1 | 32)) === (1 | 32)) {\n if (link.nextSub !== undefined || link.prevSub !== undefined) {\n stack = { value: link, prev: stack };\n }\n link = dep.deps;\n sub = dep;\n ++checkDepth;\n continue;\n }\n if (!dirty) {\n const nextDep = link.nextDep;\n if (nextDep !== undefined) {\n link = nextDep;\n continue;\n }\n }\n while (checkDepth--) {\n const firstSub = sub.subs;\n const hasMultipleSubs = firstSub.nextSub !== undefined;\n if (hasMultipleSubs) {\n link = stack.value;\n stack = stack.prev;\n }\n else {\n link = firstSub;\n }\n if (dirty) {\n if (update(sub)) {\n if (hasMultipleSubs) {\n shallowPropagate(firstSub);\n }\n sub = link.sub;\n continue;\n }\n dirty = false;\n }\n else {\n sub.flags &= ~32;\n }\n sub = link.sub;\n const nextDep = link.nextDep;\n if (nextDep !== undefined) {\n link = nextDep;\n continue top;\n }\n }\n return dirty;\n } while (true);\n }\n function shallowPropagate(link) {\n do {\n const sub = link.sub;\n const flags = sub.flags;\n if ((flags & (32 | 16)) === 32) {\n sub.flags = flags | 16;\n if ((flags & (2 | 4)) === 2) {\n notify(sub);\n }\n }\n } while ((link = link.nextSub) !== undefined);\n }\n function isValidLink(checkLink, sub) {\n let link = sub.depsTail;\n while (link !== undefined) {\n if (link === checkLink) {\n return true;\n }\n link = link.prevDep;\n }\n return false;\n }\n}\n","import { createReactiveSystem } from './system.mjs';\nlet cycle = 0;\nlet batchDepth = 0;\nlet notifyIndex = 0;\nlet queuedLength = 0;\nlet activeSub;\nconst queued = [];\nconst { link, unlink, propagate, checkDirty, shallowPropagate, } = createReactiveSystem({\n update(node) {\n if (node.depsTail !== undefined) {\n return updateComputed(node);\n }\n else {\n return updateSignal(node);\n }\n },\n notify(effect) {\n let insertIndex = queuedLength;\n let firstInsertedIndex = insertIndex;\n do {\n queued[insertIndex++] = effect;\n effect.flags &= ~2;\n effect = effect.subs?.sub;\n if (effect === undefined || !(effect.flags & 2)) {\n break;\n }\n } while (true);\n queuedLength = insertIndex;\n while (firstInsertedIndex < --insertIndex) {\n const left = queued[firstInsertedIndex];\n queued[firstInsertedIndex++] = queued[insertIndex];\n queued[insertIndex] = left;\n }\n },\n unwatched(node) {\n if (!(node.flags & 1)) {\n effectScopeOper.call(node);\n }\n else if (node.depsTail !== undefined) {\n node.depsTail = undefined;\n node.flags = 1 | 16;\n purgeDeps(node);\n }\n },\n});\nexport function getActiveSub() {\n return activeSub;\n}\nexport function setActiveSub(sub) {\n const prevSub = activeSub;\n activeSub = sub;\n return prevSub;\n}\nexport function getBatchDepth() {\n return batchDepth;\n}\nexport function startBatch() {\n ++batchDepth;\n}\nexport function endBatch() {\n if (!--batchDepth) {\n flush();\n }\n}\nexport function isSignal(fn) {\n return fn.name === 'bound ' + signalOper.name;\n}\nexport function isComputed(fn) {\n return fn.name === 'bound ' + computedOper.name;\n}\nexport function isEffect(fn) {\n return fn.name === 'bound ' + effectOper.name;\n}\nexport function isEffectScope(fn) {\n return fn.name === 'bound ' + effectScopeOper.name;\n}\nexport function signal(initialValue) {\n return signalOper.bind({\n currentValue: initialValue,\n pendingValue: initialValue,\n subs: undefined,\n subsTail: undefined,\n flags: 1,\n });\n}\nexport function computed(getter) {\n return computedOper.bind({\n value: undefined,\n subs: undefined,\n subsTail: undefined,\n deps: undefined,\n depsTail: undefined,\n flags: 0,\n getter: getter,\n });\n}\nexport function effect(fn) {\n const e = {\n fn,\n subs: undefined,\n subsTail: undefined,\n deps: undefined,\n depsTail: undefined,\n flags: 2 | 4,\n };\n const prevSub = setActiveSub(e);\n if (prevSub !== undefined) {\n link(e, prevSub, 0);\n }\n try {\n e.fn();\n }\n finally {\n activeSub = prevSub;\n e.flags &= ~4;\n }\n return effectOper.bind(e);\n}\nexport function effectScope(fn) {\n const e = {\n deps: undefined,\n depsTail: undefined,\n subs: undefined,\n subsTail: undefined,\n flags: 0,\n };\n const prevSub = setActiveSub(e);\n if (prevSub !== undefined) {\n link(e, prevSub, 0);\n }\n try {\n fn();\n }\n finally {\n activeSub = prevSub;\n }\n return effectScopeOper.bind(e);\n}\nexport function trigger(fn) {\n const sub = {\n deps: undefined,\n depsTail: undefined,\n flags: 2,\n };\n const prevSub = setActiveSub(sub);\n try {\n fn();\n }\n finally {\n activeSub = prevSub;\n let link = sub.deps;\n while (link !== undefined) {\n const dep = link.dep;\n link = unlink(link, sub);\n const subs = dep.subs;\n if (subs !== undefined) {\n sub.flags = 0;\n propagate(subs);\n shallowPropagate(subs);\n }\n }\n if (!batchDepth) {\n flush();\n }\n }\n}\nfunction updateComputed(c) {\n ++cycle;\n c.depsTail = undefined;\n c.flags = 1 | 4;\n const prevSub = setActiveSub(c);\n try {\n const oldValue = c.value;\n return oldValue !== (c.value = c.getter(oldValue));\n }\n finally {\n activeSub = prevSub;\n c.flags &= ~4;\n purgeDeps(c);\n }\n}\nfunction updateSignal(s) {\n s.flags = 1;\n return s.currentValue !== (s.currentValue = s.pendingValue);\n}\nfunction run(e) {\n const flags = e.flags;\n if (flags & 16\n || (flags & 32\n && checkDirty(e.deps, e))) {\n ++cycle;\n e.depsTail = undefined;\n e.flags = 2 | 4;\n const prevSub = setActiveSub(e);\n try {\n e.fn();\n }\n finally {\n activeSub = prevSub;\n e.flags &= ~4;\n purgeDeps(e);\n }\n }\n else {\n e.flags = 2;\n }\n}\nfunction flush() {\n try {\n while (notifyIndex < queuedLength) {\n const effect = queued[notifyIndex];\n queued[notifyIndex++] = undefined;\n run(effect);\n }\n }\n finally {\n while (notifyIndex < queuedLength) {\n const effect = queued[notifyIndex];\n queued[notifyIndex++] = undefined;\n effect.flags |= 2 | 8;\n }\n notifyIndex = 0;\n queuedLength = 0;\n }\n}\nfunction computedOper() {\n const flags = this.flags;\n if (flags & 16\n || (flags & 32\n && (checkDirty(this.deps, this)\n || (this.flags = flags & ~32, false)))) {\n if (updateComputed(this)) {\n const subs = this.subs;\n if (subs !== undefined) {\n shallowPropagate(subs);\n }\n }\n }\n else if (!flags) {\n this.flags = 1 | 4;\n const prevSub = setActiveSub(this);\n try {\n this.value = this.getter();\n }\n finally {\n activeSub = prevSub;\n this.flags &= ~4;\n }\n }\n const sub = activeSub;\n if (sub !== undefined) {\n link(this, sub, cycle);\n }\n return this.value;\n}\nfunction signalOper(...value) {\n if (value.length) {\n if (this.pendingValue !== (this.pendingValue = value[0])) {\n this.flags = 1 | 16;\n const subs = this.subs;\n if (subs !== undefined) {\n propagate(subs);\n if (!batchDepth) {\n flush();\n }\n }\n }\n }\n else {\n if (this.flags & 16) {\n if (updateSignal(this)) {\n const subs = this.subs;\n if (subs !== undefined) {\n shallowPropagate(subs);\n }\n }\n }\n let sub = activeSub;\n while (sub !== undefined) {\n if (sub.flags & (1 | 2)) {\n link(this, sub, cycle);\n break;\n }\n sub = sub.subs?.sub;\n }\n return this.currentValue;\n }\n}\nfunction effectOper() {\n effectScopeOper.call(this);\n}\nfunction effectScopeOper() {\n this.depsTail = undefined;\n this.flags = 0;\n purgeDeps(this);\n const sub = this.subs;\n if (sub !== undefined) {\n unlink(sub);\n }\n}\nfunction purgeDeps(sub) {\n const depsTail = sub.depsTail;\n let dep = depsTail !== undefined ? depsTail.nextDep : sub.deps;\n while (dep !== undefined) {\n dep = unlink(dep, sub);\n }\n}\n","/**\n * Forma Reactive - Signal\n *\n * Fine-grained reactive primitive backed by alien-signals.\n * API: createSignal returns [getter, setter] tuple following SolidJS conventions.\n *\n * TC39 Signals equivalent: Signal.State\n */\n\nimport { signal as createRawSignal, setActiveSub } from 'alien-signals';\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\nexport type SignalGetter<T> = () => T;\nexport type SignalSetter<T> = (v: T | ((prev: T) => T)) => void;\n\nexport interface SignalOptions<T> {\n /** Debug name — attached to getter in dev mode for devtools inspection. */\n name?: string;\n /**\n * Custom equality check. When provided, the setter will read the current\n * value and only update the signal if `equals(prev, next)` returns `false`.\n *\n * Default: none (alien-signals uses strict inequality `!==` internally).\n *\n * ```ts\n * const [pos, setPos] = createSignal(\n * { x: 0, y: 0 },\n * { equals: (a, b) => a.x === b.x && a.y === b.y },\n * );\n *\n * setPos({ x: 0, y: 0 }); // skipped — equals returns true\n * setPos({ x: 1, y: 0 }); // applied — equals returns false\n * ```\n */\n equals?: (prev: T, next: T) => boolean;\n}\n\n/**\n * Wrap a value so the setter treats it as a literal value, not a functional updater.\n *\n * When `T` is itself a function type, passing a function to the setter is\n * ambiguous -- it looks like a functional update (`prev => next`). Use\n * `value()` to disambiguate:\n *\n * ```ts\n * const [getFn, setFn] = createSignal<() => void>(() => console.log('a'));\n *\n * // BUG: interpreted as a functional update -- calls the arrow with prev\n * // setFn(() => console.log('b'));\n *\n * // Correct: wraps in a thunk so the setter stores it as-is\n * setFn(value(() => console.log('b')));\n * ```\n */\nexport function value<T>(v: T): () => T {\n return () => v;\n}\n\ntype RawSignal<T> = {\n (): T;\n (value: T): void;\n};\n\nfunction applySignalSet<T>(\n s: RawSignal<T>,\n v: T | ((prev: T) => T),\n equals?: (prev: T, next: T) => boolean,\n): void {\n if (typeof v !== 'function') {\n if (equals) {\n // Read current value without tracking\n const prevSub = setActiveSub(undefined);\n const prev = s();\n setActiveSub(prevSub);\n if (equals(prev, v)) return; // skip — values are equal\n }\n s(v);\n return;\n }\n\n // Functional update: read prev without tracking\n const prevSub = setActiveSub(undefined);\n const prev = s();\n setActiveSub(prevSub);\n const next = (v as (prev: T) => T)(prev);\n if (equals && equals(prev, next)) return; // skip — values are equal\n s(next);\n}\n\n/**\n * Create a reactive signal.\n *\n * ```ts\n * const [count, setCount] = createSignal(0);\n * console.log(count()); // 0\n * setCount(1);\n * setCount(prev => prev + 1);\n * ```\n *\n * With custom equality:\n *\n * ```ts\n * const [pos, setPos] = createSignal(\n * { x: 0, y: 0 },\n * { equals: (a, b) => a.x === b.x && a.y === b.y },\n * );\n * ```\n */\nexport function createSignal<T>(initialValue: T, options?: SignalOptions<T>): [get: SignalGetter<T>, set: SignalSetter<T>] {\n const s = createRawSignal<T>(initialValue) as RawSignal<T>;\n const getter = s as unknown as SignalGetter<T>;\n const eq = options?.equals;\n const setter: SignalSetter<T> = (v: T | ((prev: T) => T)) => applySignalSet(s, v, eq);\n\n return [getter, setter];\n}\n","/**\n * Forma Reactive - Root\n *\n * Explicit reactive ownership scope. All effects created inside a root\n * are automatically disposed when the root is torn down.\n *\n * Uses alien-signals' `effectScope` under the hood for native graph-level\n * effect tracking, with a userland disposer list for non-effect cleanup\n * (e.g., event listeners, DOM references, timers).\n */\n\nimport { effectScope as rawEffectScope } from 'alien-signals';\n\n// ---------------------------------------------------------------------------\n// Root scope tracking\n// ---------------------------------------------------------------------------\n\nlet currentRoot: RootScope | null = null;\nconst rootStack: (RootScope | null)[] = [];\n\ninterface RootScope {\n /** Userland disposers (event listeners, DOM refs, timers, etc.) */\n disposers: (() => void)[];\n /** alien-signals effect scope dispose — tears down all reactive effects */\n scopeDispose: (() => void) | null;\n}\n\n/**\n * Create a reactive root scope.\n *\n * All effects created (via `createEffect`) inside the callback are tracked\n * at both the reactive graph level (via alien-signals effectScope) and the\n * userland level (via registerDisposer). The returned `dispose` function\n * tears down everything.\n *\n * ```ts\n * const dispose = createRoot(() => {\n * createEffect(() => console.log(count()));\n * createEffect(() => console.log(name()));\n * });\n * // later: dispose() stops both effects\n * ```\n */\nexport function createRoot<T>(fn: (dispose: () => void) => T): T {\n const scope: RootScope = { disposers: [], scopeDispose: null };\n\n rootStack.push(currentRoot);\n currentRoot = scope;\n\n const dispose = () => {\n // Dispose alien-signals effect scope first (reactive graph cleanup)\n if (scope.scopeDispose) {\n try { scope.scopeDispose(); } catch { /* ensure userland disposers still run */ }\n scope.scopeDispose = null;\n }\n // Then run userland disposers\n for (const d of scope.disposers) {\n try { d(); } catch { /* ensure all disposers run */ }\n }\n scope.disposers.length = 0;\n };\n\n let result: T;\n try {\n // Wrap in alien-signals effectScope for native effect tracking\n scope.scopeDispose = rawEffectScope(() => {\n result = fn(dispose);\n });\n } finally {\n currentRoot = rootStack.pop() ?? null;\n }\n\n return result!;\n}\n\n/**\n * @internal — called by createEffect to register disposers in the current root.\n */\nexport function registerDisposer(dispose: () => void): void {\n if (currentRoot) {\n currentRoot.disposers.push(dispose);\n }\n}\n\n/**\n * @internal — check if we're inside a root scope.\n */\nexport function hasActiveRoot(): boolean {\n return currentRoot !== null;\n}\n","/**\n * Forma Reactive - Cleanup\n *\n * Register cleanup functions within reactive scopes.\n * Inspired by SolidJS onCleanup().\n */\n\n// ---------------------------------------------------------------------------\n// Cleanup context tracking\n// ---------------------------------------------------------------------------\n\ntype CleanupCollector = ((fn: () => void) => void) | null;\n\nlet currentCleanupCollector: CleanupCollector = null;\n\n/**\n * Register a cleanup function in the current reactive scope.\n * The cleanup runs before the effect re-executes and on disposal.\n *\n * More composable than returning a cleanup from the effect function,\n * since it can be called from helper functions.\n *\n * ```ts\n * createEffect(() => {\n * const timer = setInterval(tick, 1000);\n * onCleanup(() => clearInterval(timer));\n * });\n * ```\n */\nexport function onCleanup(fn: () => void): void {\n currentCleanupCollector?.(fn);\n}\n\n/**\n * @internal — Set the cleanup collector for the current effect execution.\n */\nexport function setCleanupCollector(collector: CleanupCollector): CleanupCollector {\n const prev = currentCleanupCollector;\n currentCleanupCollector = collector;\n return prev;\n}\n","/**\n * Forma Reactive - Dev Mode\n *\n * Development utilities stripped from production builds via __DEV__ flag.\n * Bundlers replace __DEV__ with false → dead-code elimination removes all dev paths.\n */\n\n// __DEV__ is replaced by bundler (tsup define). Defaults to true for unbundled usage.\ndeclare const process: { env?: Record<string, string | undefined> } | undefined;\nexport const __DEV__: boolean = typeof process !== 'undefined'\n ? (process!.env?.NODE_ENV !== 'production')\n : true;\n\n// ---------------------------------------------------------------------------\n// Global error handler\n// ---------------------------------------------------------------------------\n\nexport type ErrorHandler = (error: unknown, info?: { source?: string }) => void;\n\nlet _errorHandler: ErrorHandler | null = null;\n\n/**\n * Install a global error handler for FormaJS reactive errors.\n * Called when effects, computeds, or event handlers throw.\n *\n * ```ts\n * onError((err, info) => {\n * console.error(`[${info?.source}]`, err);\n * Sentry.captureException(err);\n * });\n * ```\n */\nexport function onError(handler: ErrorHandler): void {\n _errorHandler = handler;\n}\n\n/** @internal */\nexport function reportError(error: unknown, source?: string): void {\n if (_errorHandler) {\n try { _errorHandler(error, source ? { source } : {}); } catch { /* prevent infinite loop */ }\n }\n if (__DEV__) {\n console.error(`[forma] ${source ?? 'Unknown'} error:`, error);\n }\n}\n","/**\n * Forma Reactive - Effect\n *\n * Side-effectful reactive computation that auto-tracks signal dependencies.\n * Backed by alien-signals for automatic dependency tracking.\n *\n * TC39 Signals equivalent: Signal.subtle.Watcher (effect is a userland concept)\n */\n\nimport { effect as rawEffect } from 'alien-signals';\nimport { hasActiveRoot, registerDisposer } from './root.js';\nimport { setCleanupCollector } from './cleanup.js';\nimport { reportError } from './dev.js';\n\n// ---------------------------------------------------------------------------\n// Cleanup array pool — avoids allocating a new array every effect re-run\n// ---------------------------------------------------------------------------\n\nconst POOL_SIZE = 32;\nconst MAX_REENTRANT_RUNS = 100;\nconst pool: (() => void)[][] = [];\nfor (let i = 0; i < POOL_SIZE; i++) pool.push([]);\nlet poolIdx = POOL_SIZE;\n\nfunction acquireArray(): (() => void)[] {\n if (poolIdx > 0) {\n const arr = pool[--poolIdx]!;\n arr.length = 0;\n return arr;\n }\n return [];\n}\n\nfunction releaseArray(arr: (() => void)[]): void {\n arr.length = 0;\n if (poolIdx < POOL_SIZE) {\n pool[poolIdx++] = arr;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Unified cleanup runner — single function for both re-run and dispose paths\n// ---------------------------------------------------------------------------\n\nfunction runCleanup(fn: (() => void) | undefined): void {\n if (fn === undefined) return;\n try {\n fn();\n } catch (e) {\n reportError(e, 'effect cleanup');\n }\n}\n\nfunction runCleanups(bag: (() => void)[] | undefined): void {\n if (bag === undefined) return;\n for (let i = 0; i < bag.length; i++) {\n try { bag[i]!(); } catch (e) { reportError(e, 'effect cleanup'); }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Create a reactive effect that auto-tracks signal dependencies.\n *\n * The provided function runs immediately and re-runs whenever any signal it\n * reads changes. If the function returns a cleanup function, that cleanup is\n * called before each re-run and on disposal.\n *\n * Additionally, `onCleanup()` can be called inside the effect to register\n * cleanup functions composably.\n *\n * Returns a dispose function that stops the effect.\n */\n/**\n * @internal — Lightweight effect for Forma's internal DOM bindings.\n *\n * Bypasses createEffect's cleanup infrastructure (pool, collector, error\n * reporting, engine compression) since internal effects never use\n * onCleanup() or return cleanup functions. This saves ~4 function calls\n * per effect creation and per re-run.\n *\n * ONLY use for effects that:\n * 1. Never call onCleanup()\n * 2. Never return a cleanup function\n * 3. Contain simple \"read signal → write DOM\" logic\n */\nexport function internalEffect(fn: () => void): () => void {\n const dispose = rawEffect(fn);\n if (hasActiveRoot()) {\n registerDisposer(dispose);\n }\n return dispose;\n}\n\nexport function createEffect(fn: () => void | (() => void)): () => void {\n const shouldRegister = hasActiveRoot();\n\n // Most effects have zero or one cleanup. Track the single-cleanup case\n // without array allocation; only promote to pooled array when needed.\n let cleanup: (() => void) | undefined;\n let cleanupBag: (() => void)[] | undefined;\n let nextCleanup: (() => void) | undefined;\n let nextCleanupBag: (() => void)[] | undefined;\n\n const addCleanup = (cb: () => void) => {\n if (nextCleanupBag !== undefined) {\n nextCleanupBag.push(cb);\n return;\n }\n if (nextCleanup !== undefined) {\n const bag = acquireArray();\n bag.push(nextCleanup, cb);\n nextCleanup = undefined;\n nextCleanupBag = bag;\n return;\n }\n nextCleanup = cb;\n };\n\n // \"Engine Compression\" exploit: most effects never use cleanup (onCleanup()\n // or return value). After the first clean run, we know this effect is\n // \"cleanup-free\" and can skip the entire cleanup infrastructure on re-runs.\n // This saves 4 function calls per re-run: acquireArray, setCleanupCollector,\n // releaseArray, and bag inspection. Like the engine compression ratio exploit —\n // the \"rules\" say we should always prepare for cleanup, but we measure at\n // \"room temperature\" (first run) and exploit the gap.\n let skipCleanupInfra = false;\n let firstRun = true;\n let running = false;\n let rerunRequested = false;\n\n const runOnce = () => {\n // Run and clear previous cleanups (only if any exist).\n if (cleanup !== undefined) {\n runCleanup(cleanup);\n cleanup = undefined;\n }\n if (cleanupBag !== undefined) {\n runCleanups(cleanupBag);\n releaseArray(cleanupBag);\n cleanupBag = undefined;\n }\n\n // Ultra-fast path: this effect has proven it doesn't use cleanup.\n // Skip acquireArray + setCleanupCollector + bag checks + releaseArray.\n if (skipCleanupInfra) {\n try { fn(); } catch (e) { reportError(e, 'effect'); }\n return;\n }\n\n nextCleanup = undefined;\n nextCleanupBag = undefined;\n\n // Full path: install collector for onCleanup() calls.\n const prevCollector = setCleanupCollector(addCleanup);\n\n try {\n const result = fn();\n\n if (typeof result === 'function') {\n addCleanup(result as () => void);\n }\n\n // Hot path: no cleanups registered or returned — enable ultra-fast path.\n if (nextCleanup === undefined && nextCleanupBag === undefined) {\n // First clean run → enable ultra-fast path for all subsequent runs\n if (firstRun) skipCleanupInfra = true;\n return;\n }\n\n if (nextCleanupBag !== undefined) {\n cleanupBag = nextCleanupBag;\n } else {\n cleanup = nextCleanup;\n }\n } catch (e) {\n reportError(e, 'effect');\n\n if (nextCleanupBag !== undefined) {\n cleanupBag = nextCleanupBag;\n } else {\n cleanup = nextCleanup;\n }\n } finally {\n setCleanupCollector(prevCollector);\n firstRun = false;\n }\n };\n\n const safeFn = () => {\n if (running) {\n rerunRequested = true;\n return;\n }\n\n running = true;\n try {\n let reentrantRuns = 0;\n do {\n rerunRequested = false;\n runOnce();\n if (rerunRequested) {\n reentrantRuns++;\n if (reentrantRuns >= MAX_REENTRANT_RUNS) {\n reportError(\n new Error(`createEffect exceeded ${MAX_REENTRANT_RUNS} re-entrant runs`),\n 'effect',\n );\n rerunRequested = false;\n }\n }\n } while (rerunRequested);\n } finally {\n running = false;\n }\n };\n\n const dispose = rawEffect(safeFn);\n\n // Wrap dispose to also run final cleanups\n let disposed = false;\n const wrappedDispose = () => {\n if (disposed) return;\n disposed = true;\n dispose();\n if (cleanup !== undefined) {\n runCleanup(cleanup);\n cleanup = undefined;\n }\n if (cleanupBag !== undefined) {\n runCleanups(cleanupBag);\n releaseArray(cleanupBag);\n cleanupBag = undefined;\n }\n };\n\n // Register in current root scope (if any)\n if (shouldRegister) {\n registerDisposer(wrappedDispose);\n }\n\n return wrappedDispose;\n}\n","/**\n * Forma Reactive - Computed\n *\n * Lazy, cached derived value that participates in the reactive graph.\n * Backed by alien-signals for automatic dependency tracking\n * and cache invalidation.\n *\n * TC39 Signals equivalent: Signal.Computed\n */\n\nimport { computed as rawComputed } from 'alien-signals';\n\n/**\n * Create a lazy, cached computed value.\n *\n * Note: Unlike SolidJS's createComputed (which is an eager synchronous\n * side effect), this is a lazy cached derivation — equivalent to\n * SolidJS's createMemo. Both createComputed and createMemo in FormaJS\n * are identical.\n *\n * The getter receives the previous value as an argument, enabling\n * efficient diffing patterns without a separate signal:\n *\n * ```ts\n * const [count, setCount] = createSignal(0);\n * const doubled = createComputed(() => count() * 2);\n * console.log(doubled()); // 0\n * setCount(5);\n * console.log(doubled()); // 10\n * ```\n *\n * With previous value (for diffing):\n *\n * ```ts\n * const changes = createComputed((prev) => {\n * const next = items();\n * if (prev) console.log(`changed from ${prev.length} to ${next.length} items`);\n * return next;\n * });\n * ```\n */\nexport function createComputed<T>(fn: (previousValue?: T) => T): () => T {\n return rawComputed(fn);\n}\n","/**\n * Forma Reactive - Memo\n *\n * Alias for createComputed with SolidJS/React-familiar naming.\n * A memoized derived value that only recomputes when its dependencies change.\n *\n * TC39 Signals equivalent: Signal.Computed\n */\n\nimport { createComputed } from './computed.js';\n\n/**\n * Create a memoized computed value.\n * Identical to `createComputed` — provided for React/SolidJS familiarity.\n *\n * Note: Unlike SolidJS's createComputed (which is an eager synchronous\n * side effect), both createComputed and createMemo in FormaJS are lazy\n * cached derivations — equivalent to SolidJS's createMemo. They are\n * identical.\n *\n * The computation runs lazily and caches the result. It only recomputes\n * when a signal it reads during computation changes.\n *\n * ```ts\n * const [count, setCount] = createSignal(0);\n * const doubled = createMemo(() => count() * 2);\n * console.log(doubled()); // 0\n * setCount(5);\n * console.log(doubled()); // 10\n * ```\n */\nexport const createMemo: typeof createComputed = createComputed;\n","/**\n * Forma Reactive - Batch\n *\n * Groups multiple signal updates and defers effect execution until the\n * outermost batch completes. Prevents intermediate re-renders.\n * Backed by alien-signals.\n *\n * TC39 Signals: no built-in batch — this is a userland optimization.\n */\n\nimport { startBatch, endBatch } from 'alien-signals';\n\n/**\n * Group multiple signal updates so that effects only run once after all\n * updates have been applied.\n *\n * ```ts\n * batch(() => {\n * setA(1);\n * setB(2);\n * // effects that depend on A and B won't run yet\n * });\n * // effects run here, once\n * ```\n *\n * Batches are nestable — only the outermost batch triggers the flush.\n */\nexport function batch(fn: () => void): void {\n startBatch();\n try {\n fn();\n } finally {\n endBatch();\n }\n}\n","/**\n * Forma Reactive - Untrack\n *\n * Read signals without subscribing to them in the reactive graph.\n * Essential for reading values inside effects without creating dependencies.\n *\n * TC39 Signals equivalent: Signal.subtle.untrack()\n */\n\nimport { setActiveSub } from 'alien-signals';\n\n/**\n * Execute a function without tracking signal reads.\n * Any signals read inside `fn` will NOT become dependencies of the\n * surrounding effect or computed.\n *\n * ```ts\n * createEffect(() => {\n * const a = count(); // tracked — effect re-runs when count changes\n * const b = untrack(() => other()); // NOT tracked — effect ignores other changes\n * });\n * ```\n */\nexport function untrack<T>(fn: () => T): T {\n const prev = setActiveSub(undefined);\n try {\n return fn();\n } finally {\n setActiveSub(prev);\n }\n}\n","/**\n * Forma Reactive - On\n *\n * Explicit dependency tracking for effects.\n * Only re-runs when the specified signals change, ignoring all other reads.\n *\n * SolidJS equivalent: on()\n * Vue equivalent: watch() with explicit deps\n * React equivalent: useEffect dependency array\n */\n\nimport { untrack } from './untrack.js';\n\n/**\n * Create a tracked effect body that only fires when specific dependencies change.\n *\n * Wraps a function so that only the `deps` signals are tracked.\n * All signal reads inside `fn` are untracked (won't cause re-runs).\n *\n * Use with `createEffect`:\n *\n * ```ts\n * const [a, setA] = createSignal(1);\n * const [b, setB] = createSignal(2);\n *\n * // Only re-runs when `a` changes, NOT when `b` changes:\n * createEffect(on(a, (value, prev) => {\n * console.log(`a changed: ${prev} → ${value}, b is ${b()}`);\n * }));\n *\n * setA(10); // fires: \"a changed: 1 → 10, b is 2\"\n * setB(20); // does NOT fire\n * ```\n *\n * Multiple dependencies:\n * ```ts\n * createEffect(on(\n * () => [a(), b()] as const,\n * ([aVal, bVal], prev) => { ... }\n * ));\n * ```\n */\nexport function on<T, U>(\n deps: () => T,\n fn: (value: T, prev: T | undefined) => U,\n options?: { defer?: boolean },\n): () => U | undefined {\n let prev: T | undefined;\n let isFirst = true;\n\n return () => {\n // Track only the deps\n const value = deps();\n\n if (options?.defer && isFirst) {\n isFirst = false;\n prev = value;\n return undefined;\n }\n\n // Run the body untracked so it doesn't add extra dependencies\n const result = untrack(() => fn(value, prev));\n prev = value;\n return result;\n };\n}\n","/**\n * Forma Reactive - Ref\n *\n * Mutable container that does NOT trigger reactivity.\n * Use for DOM references, previous values, instance variables —\n * anything that needs to persist across effect re-runs without\n * causing re-execution.\n *\n * React equivalent: useRef\n * SolidJS equivalent: (none — uses plain variables in setup)\n */\n\nexport interface Ref<T> {\n current: T;\n}\n\n/**\n * Create a mutable ref container.\n *\n * Unlike signals, writing to `.current` does NOT trigger effects.\n * Use when you need a stable reference across reactive scopes.\n *\n * ```ts\n * const timerRef = createRef<number | null>(null);\n *\n * createEffect(() => {\n * timerRef.current = setInterval(tick, 1000);\n * onCleanup(() => clearInterval(timerRef.current!));\n * });\n *\n * // DOM ref pattern:\n * const elRef = createRef<HTMLElement | null>(null);\n * h('div', { ref: (el) => { elRef.current = el; } });\n * ```\n */\nexport function createRef<T>(initialValue: T): Ref<T> {\n return { current: initialValue };\n}\n","/**\n * Forma Reactive - Reducer\n *\n * State machine pattern — dispatch actions to a pure reducer function.\n * Fine-grained: only the resulting state signal is reactive.\n *\n * React equivalent: useReducer\n * SolidJS equivalent: (none — uses createSignal + helpers)\n */\n\nimport { createSignal, type SignalGetter } from './signal.js';\n\nexport type Dispatch<A> = (action: A) => void;\n\n/**\n * Create a reducer — predictable state updates via dispatched actions.\n *\n * The reducer function must be pure: `(state, action) => newState`.\n * Returns a [state, dispatch] tuple.\n *\n * ```ts\n * type Action = { type: 'increment' } | { type: 'decrement' } | { type: 'reset' };\n *\n * const [count, dispatch] = createReducer(\n * (state: number, action: Action) => {\n * switch (action.type) {\n * case 'increment': return state + 1;\n * case 'decrement': return state - 1;\n * case 'reset': return 0;\n * }\n * },\n * 0,\n * );\n *\n * dispatch({ type: 'increment' }); // count() === 1\n * dispatch({ type: 'increment' }); // count() === 2\n * dispatch({ type: 'reset' }); // count() === 0\n * ```\n */\nexport function createReducer<S, A>(\n reducer: (state: S, action: A) => S,\n initialState: S,\n): [state: SignalGetter<S>, dispatch: Dispatch<A>] {\n const [state, setState] = createSignal(initialState);\n\n const dispatch: Dispatch<A> = (action) => {\n setState((prev) => reducer(prev, action));\n };\n\n return [state, dispatch];\n}\n","/**\n * Forma Reactive - Suspense Context\n *\n * Shared context stack for Suspense boundaries. Lives in the reactive layer\n * (not DOM) so that createResource can import it without circular dependencies.\n *\n * The pattern mirrors the lifecycle context stack in component/define.ts.\n */\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface SuspenseContext {\n /** Increment when a resource starts loading inside this boundary. */\n increment(): void;\n /** Decrement when a resource resolves/rejects inside this boundary. */\n decrement(): void;\n}\n\n// ---------------------------------------------------------------------------\n// Context stack\n// ---------------------------------------------------------------------------\n\nlet currentSuspenseContext: SuspenseContext | null = null;\nconst suspenseStack: (SuspenseContext | null)[] = [];\n\nexport function pushSuspenseContext(ctx: SuspenseContext): void {\n suspenseStack.push(currentSuspenseContext);\n currentSuspenseContext = ctx;\n}\n\nexport function popSuspenseContext(): void {\n currentSuspenseContext = suspenseStack.pop() ?? null;\n}\n\n/** Get the current Suspense context (if any). Called by createResource. */\nexport function getSuspenseContext(): SuspenseContext | null {\n return currentSuspenseContext;\n}\n","/**\n * Forma Reactive - Resource\n *\n * Async data fetching primitive with reactive loading/error state.\n * Tracks a source signal and refetches when it changes.\n *\n * SolidJS equivalent: createResource\n * React equivalent: use() + Suspense (React 19), or useSWR/react-query\n */\n\nimport { createSignal, type SignalGetter } from './signal.js';\nimport { internalEffect } from './effect.js';\nimport { untrack } from './untrack.js';\nimport { getSuspenseContext } from './suspense-context.js';\n\nexport interface Resource<T> {\n /** The resolved data (or undefined while loading). */\n (): T | undefined;\n /** True while the fetcher is running. */\n loading: SignalGetter<boolean>;\n /** The error if the fetcher rejected (or undefined). */\n error: SignalGetter<unknown>;\n /** Manually refetch with the current source value. */\n refetch: () => void;\n /** Manually set the data (overrides fetcher result). */\n mutate: (value: T | undefined) => void;\n}\n\nexport interface ResourceOptions<T> {\n /** Initial value before first fetch resolves. */\n initialValue?: T;\n}\n\n/**\n * Create an async resource that fetches data reactively.\n *\n * When `source` changes, the fetcher re-runs automatically.\n * Provides reactive `loading` and `error` signals.\n *\n * ```ts\n * const [userId, setUserId] = createSignal(1);\n *\n * const user = createResource(\n * userId, // source signal\n * (id) => fetch(`/api/users/${id}`).then(r => r.json()), // fetcher\n * );\n *\n * internalEffect(() => {\n * if (user.loading()) console.log('Loading...');\n * else if (user.error()) console.log('Error:', user.error());\n * else console.log('User:', user());\n * });\n *\n * setUserId(2); // automatically refetches\n * ```\n *\n * Without a source signal (static fetch):\n * ```ts\n * const posts = createResource(\n * () => true, // constant source — fetches once\n * () => fetch('/api/posts').then(r => r.json()),\n * );\n * ```\n */\nexport function createResource<T, S = true>(\n source: SignalGetter<S>,\n fetcher: (source: S) => Promise<T>,\n options?: ResourceOptions<T>,\n): Resource<T> {\n const [data, setData] = createSignal<T | undefined>(options?.initialValue);\n const [loading, setLoading] = createSignal(false);\n const [error, setError] = createSignal<unknown>(undefined);\n\n // Capture the Suspense context at creation time (not at fetch time).\n // This is critical because the Suspense boundary pushes/pops its context\n // synchronously during children() execution.\n const suspenseCtx = getSuspenseContext();\n\n let abortController: AbortController | null = null;\n let fetchVersion = 0;\n\n const doFetch = () => {\n // Read source outside tracking to get current value\n const sourceValue = untrack(source);\n\n // Abort previous in-flight request\n if (abortController) {\n abortController.abort();\n }\n const controller = new AbortController();\n abortController = controller;\n\n const version = ++fetchVersion;\n const isLatest = () => version === fetchVersion;\n let suspensePending = false;\n\n // Notify Suspense boundary that a fetch has started\n if (suspenseCtx) {\n suspenseCtx.increment();\n suspensePending = true;\n }\n\n setLoading(true);\n setError(undefined);\n\n Promise.resolve(fetcher(sourceValue))\n .then((result) => {\n // Only apply if this is still the latest fetch and wasn't aborted.\n if (isLatest() && !controller.signal.aborted) {\n setData(() => result);\n }\n })\n .catch((err) => {\n if (isLatest() && !controller.signal.aborted) {\n // Ignore abort errors\n if (err?.name !== 'AbortError') {\n setError(err);\n }\n }\n })\n .finally(() => {\n if (suspensePending) suspenseCtx?.decrement();\n if (isLatest()) {\n setLoading(false);\n if (abortController === controller) {\n abortController = null; // Release controller for GC\n }\n }\n });\n };\n\n // Auto-fetch when source changes\n internalEffect(() => {\n source(); // track the source signal\n doFetch();\n });\n\n // Build the resource object\n const resource = (() => data()) as Resource<T>;\n resource.loading = loading;\n resource.error = error;\n resource.refetch = doFetch;\n resource.mutate = (value) => setData(() => value);\n\n return resource;\n}\n","/**\n * Forma DOM - List\n *\n * Keyed list reconciliation with Longest Increasing Subsequence (LIS).\n * The LIS tells us the maximum set of DOM nodes that can stay in place;\n * only the remaining nodes need to be moved. This minimises DOM operations\n * to exactly `n - LIS_length` moves — provably optimal.\n *\n * Algorithm used by ivi, Inferno, and (with variations) Solid, Vue 3, Svelte.\n *\n * Uses comment-node markers instead of a wrapper <div>, so the list can be\n * placed inside <table>, <ul>, <select>, etc. without breaking semantics.\n *\n * Total module budget: <2KB minified.\n */\n\nimport { createSignal, internalEffect, untrack, __DEV__ } from '../reactive';\nimport { hydrating } from './hydrate.js';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface ReconcileResult<T> {\n nodes: Node[];\n items: T[];\n}\n\nexport interface ListTransitionHooks {\n onInsert?: (node: Node) => void;\n onBeforeRemove?: (node: Node, done: () => void) => void;\n}\n\ninterface CachedItem<T> {\n element: HTMLElement;\n item: T;\n getIndex: () => number;\n setIndex: (v: number) => void;\n}\n\nexport interface CreateListOptions {\n /**\n * How to handle same-key items whose object identity changed.\n * - 'none' (default): keep the existing row node for maximum throughput.\n * - 'rerender': re-render changed rows and patch static row DOM in place.\n */\n updateOnItemChange?: 'none' | 'rerender';\n}\n\n// ---------------------------------------------------------------------------\n// LIS — O(n log n) via patience sorting + binary search\n// ---------------------------------------------------------------------------\n\n/**\n * Find the longest increasing subsequence.\n * Returns indices into the input array.\n * O(n log n) time, O(n) space.\n */\nexport function longestIncreasingSubsequence(arr: number[]): number[] {\n const n = arr.length;\n if (n === 0) return [];\n\n // Pre-allocate typed arrays — avoids V8 array growth overhead on push\n const tails = new Int32Array(n);\n const tailIndices = new Int32Array(n);\n const predecessor = new Int32Array(n).fill(-1);\n let tailsLen = 0;\n\n for (let i = 0; i < n; i++) {\n const val = arr[i]!;\n\n // Binary search: leftmost tail >= val\n let lo = 0, hi = tailsLen;\n while (lo < hi) {\n const mid = (lo + hi) >> 1;\n if (tails[mid]! < val) lo = mid + 1;\n else hi = mid;\n }\n\n tails[lo] = val;\n tailIndices[lo] = i;\n if (lo > 0) predecessor[i] = tailIndices[lo - 1]!;\n if (lo >= tailsLen) tailsLen++;\n }\n\n // Reconstruct — return plain array since callers expect number[]\n const result = new Array<number>(tailsLen);\n let idx = tailIndices[tailsLen - 1]!;\n for (let i = tailsLen - 1; i >= 0; i--) {\n result[i] = idx;\n idx = predecessor[idx]!;\n }\n\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// reconcileList — low-level keyed reconciler\n// ---------------------------------------------------------------------------\n\n/** Below this threshold, use flat array scan instead of Map for better cache locality. */\nconst SMALL_LIST_THRESHOLD = 32;\nconst ABORT_SYM = Symbol.for('forma-abort');\nconst CACHE_SYM = Symbol.for('forma-attr-cache');\nconst DYNAMIC_CHILD_SYM = Symbol.for('forma-dynamic-child');\n\nfunction canPatchStaticElement(target: Node, source: Node): target is HTMLElement {\n return target instanceof HTMLElement\n && source instanceof HTMLElement\n && target.tagName === source.tagName\n && !(target as any)[ABORT_SYM]\n && !(target as any)[CACHE_SYM]\n && !(target as any)[DYNAMIC_CHILD_SYM]\n && !(source as any)[ABORT_SYM]\n && !(source as any)[CACHE_SYM]\n && !(source as any)[DYNAMIC_CHILD_SYM];\n}\n\nfunction patchStaticElement(target: HTMLElement, source: HTMLElement): void {\n // Sync attributes (events/reactive bindings are excluded by canPatchStaticElement).\n const sourceAttrNames = new Set<string>();\n for (const attr of Array.from(source.attributes)) {\n sourceAttrNames.add(attr.name);\n if (target.getAttribute(attr.name) !== attr.value) {\n target.setAttribute(attr.name, attr.value);\n }\n }\n for (const attr of Array.from(target.attributes)) {\n if (!sourceAttrNames.has(attr.name)) {\n target.removeAttribute(attr.name);\n }\n }\n\n // Move freshly rendered children into the existing keyed node.\n target.replaceChildren(...Array.from(source.childNodes));\n}\n\n/**\n * Small-list reconciler: uses flat arrays + indexOf instead of Map/Set.\n * For < 32 items, linear scan is faster than hash computation overhead.\n */\nfunction reconcileSmall<T>(\n parent: Node,\n oldItems: T[],\n newItems: T[],\n oldNodes: Node[],\n keyFn: (item: T) => string | number,\n createFn: (item: T) => Node,\n updateFn: (node: Node, item: T) => void,\n beforeNode?: Node | null,\n hooks?: ListTransitionHooks,\n): ReconcileResult<T> {\n const oldLen = oldItems.length;\n const newLen = newItems.length;\n\n // Build flat arrays for old keys/nodes — better cache locality than Map\n const oldKeys: (string | number)[] = new Array(oldLen);\n for (let i = 0; i < oldLen; i++) {\n oldKeys[i] = keyFn(oldItems[i]!);\n }\n\n // Classify each new item: find matching old index via linear scan\n const oldIndices = new Array<number>(newLen);\n const oldUsed = new Uint8Array(oldLen); // 0 = unused, 1 = used\n\n for (let i = 0; i < newLen; i++) {\n const key = keyFn(newItems[i]!);\n let found = -1;\n for (let j = 0; j < oldLen; j++) {\n if (!oldUsed[j] && oldKeys[j] === key) {\n found = j;\n oldUsed[j] = 1;\n break;\n }\n }\n oldIndices[i] = found;\n }\n\n // Remove old items not reused\n for (let i = 0; i < oldLen; i++) {\n if (!oldUsed[i]) {\n if (hooks?.onBeforeRemove) {\n const node = oldNodes[i]!;\n hooks.onBeforeRemove(node, () => {\n if (node.parentNode) node.parentNode.removeChild(node);\n });\n } else {\n parent.removeChild(oldNodes[i]!);\n }\n }\n }\n\n // Fast path: same keys, same order -> just update, 0 DOM moves\n if (oldLen === newLen) {\n let allSameOrder = true;\n for (let i = 0; i < newLen; i++) {\n if (oldIndices[i] !== i) {\n allSameOrder = false;\n break;\n }\n }\n if (allSameOrder) {\n const nodes = new Array<Node>(newLen);\n for (let i = 0; i < newLen; i++) {\n const node = oldNodes[i]!;\n updateFn(node, newItems[i]!);\n nodes[i] = node;\n }\n return { nodes, items: newItems };\n }\n }\n\n // LIS for minimum moves (still needed even for small lists)\n const reusedIndices: number[] = [];\n const reusedPositions: number[] = [];\n for (let i = 0; i < newLen; i++) {\n if (oldIndices[i] !== -1) {\n reusedIndices.push(oldIndices[i]!);\n reusedPositions.push(i);\n }\n }\n\n const lisOfReused = longestIncreasingSubsequence(reusedIndices);\n // Use Uint8Array as a bitmap instead of Set for small lists\n const lisFlags = new Uint8Array(newLen);\n for (const li of lisOfReused) {\n lisFlags[reusedPositions[li]!] = 1;\n }\n\n // Build result: walk right-to-left for stable insertBefore targets\n const newNodes = new Array<Node>(newLen);\n let nextSibling: Node | null = beforeNode ?? null;\n\n for (let i = newLen - 1; i >= 0; i--) {\n let node: Node;\n let isNew = false;\n\n if (oldIndices[i] === -1) {\n node = createFn(newItems[i]!);\n isNew = true;\n } else {\n node = oldNodes[oldIndices[i]!]!;\n updateFn(node, newItems[i]!);\n\n if (lisFlags[i]) {\n newNodes[i] = node;\n nextSibling = node;\n continue;\n }\n }\n\n if (nextSibling) {\n parent.insertBefore(node, nextSibling);\n } else {\n parent.appendChild(node);\n }\n\n if (isNew) hooks?.onInsert?.(node);\n\n newNodes[i] = node;\n nextSibling = node;\n }\n\n return { nodes: newNodes, items: newItems };\n}\n\n/**\n * Reconcile a DOM parent's children to match a new array of items.\n * Uses keyed reconciliation with LIS for minimum DOM operations.\n *\n * For small lists (< 32 items), uses a flat array scan path that avoids\n * Map/Set hash overhead and provides better cache locality.\n *\n * @param parent - The container DOM element\n * @param oldItems - Previous array (from last reconciliation)\n * @param newItems - New array to render\n * @param oldNodes - Previous DOM nodes array\n * @param keyFn - Extracts a unique key from each item\n * @param createFn - Creates a new DOM node for an item\n * @param updateFn - Updates an existing DOM node with new item data\n * @param beforeNode - Optional boundary marker. When provided, new nodes are\n * inserted before this node instead of appended to parent.\n * This allows the reconciler to operate within a range\n * delimited by comment markers.\n * @returns Object with new nodes array and items array for next call\n */\nexport function reconcileList<T>(\n parent: Node,\n oldItems: T[],\n newItems: T[],\n oldNodes: Node[],\n keyFn: (item: T) => string | number,\n createFn: (item: T) => Node,\n updateFn: (node: Node, item: T) => void,\n beforeNode?: Node | null,\n hooks?: ListTransitionHooks,\n): ReconcileResult<T> {\n const oldLen = oldItems.length;\n const newLen = newItems.length;\n\n // --- Trivial: new is empty -> remove all ---\n if (newLen === 0) {\n for (let i = 0; i < oldLen; i++) {\n if (hooks?.onBeforeRemove) {\n const node = oldNodes[i]!;\n hooks.onBeforeRemove(node, () => {\n if (node.parentNode) node.parentNode.removeChild(node);\n });\n } else {\n parent.removeChild(oldNodes[i]!);\n }\n }\n return { nodes: [], items: [] };\n }\n\n // --- Trivial: old is empty -> create all ---\n if (oldLen === 0) {\n const nodes = new Array<Node>(newLen);\n for (let i = 0; i < newLen; i++) {\n const node = createFn(newItems[i]!);\n if (beforeNode) {\n parent.insertBefore(node, beforeNode);\n } else {\n parent.appendChild(node);\n }\n hooks?.onInsert?.(node);\n nodes[i] = node;\n }\n return { nodes, items: newItems };\n }\n\n // --- Small list path: flat array scan, no Map/Set overhead ---\n if (oldLen < SMALL_LIST_THRESHOLD) {\n return reconcileSmall(parent, oldItems, newItems, oldNodes, keyFn, createFn, updateFn, beforeNode, hooks);\n }\n\n // --- Large list path: Map-based approach ---\n const oldKeyMap = new Map<string | number, number>();\n for (let i = 0; i < oldLen; i++) {\n oldKeyMap.set(keyFn(oldItems[i]!), i);\n }\n\n // --- Classify each new item: reuse or create ---\n // Use Uint8Array bitmap instead of Set for O(1) lookup without hash overhead\n const oldIndices = new Array<number>(newLen); // -1 means new item\n const oldUsed = new Uint8Array(oldLen);\n\n for (let i = 0; i < newLen; i++) {\n const key = keyFn(newItems[i]!);\n const oldIdx = oldKeyMap.get(key);\n if (oldIdx !== undefined) {\n oldIndices[i] = oldIdx;\n oldUsed[oldIdx] = 1;\n } else {\n oldIndices[i] = -1;\n }\n }\n\n // --- Remove old items not in new array ---\n for (let i = 0; i < oldLen; i++) {\n if (!oldUsed[i]) {\n if (hooks?.onBeforeRemove) {\n const node = oldNodes[i]!;\n hooks.onBeforeRemove(node, () => {\n if (node.parentNode) node.parentNode.removeChild(node);\n });\n } else {\n parent.removeChild(oldNodes[i]!);\n }\n }\n }\n\n // --- Fast path: same keys, same order -> just update, 0 DOM moves ---\n if (oldLen === newLen) {\n let allSameOrder = true;\n for (let i = 0; i < newLen; i++) {\n if (oldIndices[i] !== i) {\n allSameOrder = false;\n break;\n }\n }\n if (allSameOrder) {\n const nodes = new Array<Node>(newLen);\n for (let i = 0; i < newLen; i++) {\n const node = oldNodes[i]!;\n updateFn(node, newItems[i]!);\n nodes[i] = node;\n }\n return { nodes, items: newItems };\n }\n }\n\n // --- Find LIS of old indices (reused items only) ---\n const reusedIndices: number[] = [];\n const reusedPositions: number[] = []; // position in new array\n for (let i = 0; i < newLen; i++) {\n if (oldIndices[i] !== -1) {\n reusedIndices.push(oldIndices[i]!);\n reusedPositions.push(i);\n }\n }\n\n const lisOfReused = longestIncreasingSubsequence(reusedIndices);\n // Use Uint8Array bitmap instead of Set for O(1) lookup without hash overhead\n const lisFlags = new Uint8Array(newLen);\n for (const li of lisOfReused) {\n lisFlags[reusedPositions[li]!] = 1;\n }\n\n // --- Build result: walk right-to-left for stable insertBefore targets ---\n const newNodes = new Array<Node>(newLen);\n let nextSibling: Node | null = beforeNode ?? null;\n\n for (let i = newLen - 1; i >= 0; i--) {\n let node: Node;\n let isNew = false;\n\n if (oldIndices[i] === -1) {\n // NEW: create and insert\n node = createFn(newItems[i]!);\n isNew = true;\n } else {\n // REUSE: update content\n node = oldNodes[oldIndices[i]!]!;\n updateFn(node, newItems[i]!);\n\n if (lisFlags[i]) {\n // LIS item: already in correct relative position, don't move\n newNodes[i] = node;\n nextSibling = node;\n continue;\n }\n }\n\n // Insert/move into position\n if (nextSibling) {\n parent.insertBefore(node, nextSibling);\n } else {\n parent.appendChild(node);\n }\n\n if (isNew) hooks?.onInsert?.(node);\n\n newNodes[i] = node;\n nextSibling = node;\n }\n\n return { nodes: newNodes, items: newItems };\n}\n\n// ---------------------------------------------------------------------------\n// createList — high-level reactive API\n// ---------------------------------------------------------------------------\n\n/**\n * Create a reactively-bound list of DOM elements with keyed reconciliation.\n *\n * Returns a `DocumentFragment` containing two comment markers\n * (`<!--forma-list-start-->` and `<!--forma-list-end-->`) that delimit the\n * list's range in the DOM. All managed elements live between these markers.\n *\n * This avoids a wrapper `<div>` which would break `<table>`, `<ul>`,\n * `<select>` semantics and pollute the DOM.\n *\n * When the `items` signal changes, only the minimal set of DOM mutations is\n * performed using the LIS algorithm:\n * - New keys: create elements via `renderFn`\n * - Removed keys: remove elements from DOM\n * - Moved keys: reorder elements using minimum moves (n - LIS)\n * - Same keys: keep row nodes and update index signals\n * (or re-render row content when `updateOnItemChange: 'rerender'`)\n *\n * @param items Signal getter returning the current array of items.\n * @param keyFn Extracts a unique key from each item.\n * @param renderFn Renders a single item. Receives the item and a reactive index getter.\n * @returns A DocumentFragment to insert into the DOM. The fragment includes\n * start/end comment markers and any initial list items.\n *\n * ```ts\n * const frag = createList(\n * todos,\n * (t) => t.id,\n * (todo, index) => h('li', null, () => `${index() + 1}. ${todo.text}`),\n * );\n * container.appendChild(frag);\n * ```\n */\nexport function createList<T>(\n items: () => T[],\n keyFn: (item: T) => string | number,\n renderFn: (item: T, index: () => number) => HTMLElement,\n options?: CreateListOptions,\n): DocumentFragment {\n if (hydrating) {\n return { type: 'list', items, keyFn, renderFn, options } as unknown as DocumentFragment;\n }\n\n const startMarker = document.createComment('forma-list-start');\n const endMarker = document.createComment('forma-list-end');\n\n const fragment = document.createDocumentFragment();\n fragment.appendChild(startMarker);\n fragment.appendChild(endMarker);\n\n // Cache: key -> { element, item, setIndex }\n let cache = new Map<string | number, CachedItem<T>>();\n let currentNodes: Node[] = [];\n let currentItems: T[] = [];\n const updateOnItemChange = options?.updateOnItemChange ?? 'none';\n\n internalEffect(() => {\n const newItems = items();\n\n // The parent is discovered lazily: once the fragment has been inserted\n // into the live DOM the markers have a parentNode.\n const parent = startMarker.parentNode;\n if (!parent) {\n // Markers are not yet in the DOM — nothing to reconcile.\n // This can happen if the effect fires synchronously before mount.\n return;\n }\n\n // Edge case: non-array\n if (!Array.isArray(newItems)) {\n if (__DEV__) {\n console.warn('[forma] createList: value is not an array, treating as empty');\n }\n // Remove all nodes between the markers\n for (const node of currentNodes) {\n if (node.parentNode === parent) parent.removeChild(node);\n }\n cache = new Map();\n currentNodes = [];\n currentItems = [];\n return;\n }\n\n // Filter nullish items — avoid array allocation when no nulls found (common case)\n let cleanItems: T[] = newItems;\n for (let i = 0; i < newItems.length; i++) {\n if (newItems[i] == null) {\n cleanItems = newItems.filter(item => item != null);\n break;\n }\n }\n\n // Dev-mode duplicate key detection\n if (__DEV__) {\n const seen = new Set<string | number>();\n for (const item of cleanItems) {\n const key = keyFn(item);\n if (seen.has(key)) {\n console.warn('[forma] createList: duplicate key detected:', key);\n }\n seen.add(key);\n }\n }\n\n const updateRow = updateOnItemChange === 'rerender'\n ? (node: Node, item: T): void => {\n const key = keyFn(item);\n const cached = cache.get(key);\n if (!cached) return;\n if (cached.item === item) return;\n cached.item = item;\n\n if (!(node instanceof HTMLElement)) return;\n if ((node as any)[ABORT_SYM] || (node as any)[CACHE_SYM] || (node as any)[DYNAMIC_CHILD_SYM]) {\n return;\n }\n\n const next = untrack(() => renderFn(item, cached.getIndex));\n if (canPatchStaticElement(node, next)) {\n patchStaticElement(node, next);\n cached.element = node;\n }\n }\n : (_node: Node, item: T): void => {\n const key = keyFn(item);\n const cached = cache.get(key);\n if (cached) cached.item = item;\n };\n\n const result = reconcileList<T>(\n parent,\n currentItems,\n cleanItems,\n currentNodes,\n keyFn,\n // createFn: create element + cache entry\n (item) => {\n const key = keyFn(item);\n const [getIndex, setIndex] = createSignal(0);\n // Prevent child effects created during render from being nested under\n // the reconciler effect, which can stall their updates on reorders.\n const element = untrack(() => renderFn(item, getIndex));\n cache.set(key, { element, item, getIndex, setIndex });\n return element;\n },\n updateRow,\n // beforeNode: insert items before the end marker\n endMarker,\n );\n\n // Rebuild cache + update index signals in a single pass.\n // Avoids .map() array allocation + Set construction from the previous approach.\n const newCache = new Map<string | number, CachedItem<T>>();\n for (let i = 0; i < cleanItems.length; i++) {\n const key = keyFn(cleanItems[i]!);\n const cached = cache.get(key);\n if (cached) {\n cached.setIndex(i);\n newCache.set(key, cached);\n }\n }\n cache = newCache;\n\n currentNodes = result.nodes;\n currentItems = result.items;\n });\n\n return fragment;\n}\n","/**\n * Forma DOM - Show (Conditional Rendering)\n *\n * Surgically swaps a single DOM node based on a boolean signal.\n * Uses comment markers (like createList) for zero-wrapper rendering.\n * When condition changes, only ONE node is removed and ONE inserted.\n *\n * Each branch is rendered inside createRoot + untrack so that:\n * 1. Inner effects survive when the show effect re-runs (alien-signals\n * would otherwise dispose child effects linked to the parent).\n * 2. Inner effects are explicitly disposed when the branch changes.\n *\n * SolidJS equivalent: <Show when={} fallback={}>\n */\n\nimport { internalEffect, untrack, createRoot } from 'forma/reactive';\nimport { hydrating, type ShowDescriptor } from './hydrate.js';\n\n/**\n * Conditionally render content based on a reactive boolean.\n *\n * ```ts\n * const [show, setShow] = createSignal(true);\n * const fragment = createShow(\n * show,\n * () => h('div', null, 'Visible!'),\n * () => h('div', null, 'Hidden fallback'),\n * );\n * container.appendChild(fragment);\n * ```\n *\n * Returns a DocumentFragment with comment markers. The content between\n * markers is swapped reactively when `when()` changes.\n */\nexport function createShow(\n when: () => unknown,\n thenFn: () => Node,\n elseFn?: () => Node,\n): DocumentFragment {\n if (hydrating) {\n const branch = when() ? thenFn() : (elseFn?.() ?? null);\n return {\n type: 'show',\n condition: when,\n whenTrue: thenFn,\n whenFalse: elseFn,\n initialBranch: branch,\n } as unknown as DocumentFragment;\n }\n\n const startMarker = document.createComment('forma-show');\n const endMarker = document.createComment('/forma-show');\n const fragment = document.createDocumentFragment();\n fragment.appendChild(startMarker);\n fragment.appendChild(endMarker);\n\n let currentNode: Node | null = null;\n let lastTruthy: boolean | null = null;\n let currentDispose: (() => void) | null = null;\n\n const showDispose = internalEffect(() => {\n const truthy = !!when();\n const DEBUG = typeof (globalThis as any).__FORMA_DEBUG__ !== 'undefined';\n const DEBUG_LABEL = DEBUG ? thenFn.toString().slice(0, 60) : '';\n\n if (truthy === lastTruthy) {\n if (DEBUG) console.log('[forma:show] skip (same)', truthy, DEBUG_LABEL);\n return;\n }\n if (DEBUG) console.log('[forma:show]', lastTruthy, '→', truthy, DEBUG_LABEL);\n lastTruthy = truthy;\n\n const parent = startMarker.parentNode;\n if (!parent) {\n if (DEBUG) console.warn('[forma:show] parentNode is null! skipping.', DEBUG_LABEL);\n return;\n }\n if (DEBUG) console.log('[forma:show] parent:', parent.nodeName, 'inDoc:', document.contains(parent as any));\n\n // Dispose previous branch's inner effects\n if (currentDispose) {\n currentDispose();\n currentDispose = null;\n }\n\n // Remove current node. If it was a DocumentFragment, its children\n // transferred to the DOM on insertion and the fragment is now detached.\n // In that case, clear everything between the markers.\n if (currentNode) {\n if (currentNode.parentNode === parent) {\n parent.removeChild(currentNode);\n } else {\n while (startMarker.nextSibling && startMarker.nextSibling !== endMarker) {\n parent.removeChild(startMarker.nextSibling);\n }\n }\n }\n\n // Render inside createRoot so child effects are tracked for disposal,\n // and inside untrack so they are NOT linked to the show effect\n // (alien-signals disposes child effects on parent re-run, which would\n // kill reactivity in branches whose condition stays the same).\n const branchFn = truthy ? thenFn : elseFn;\n if (branchFn) {\n let branchDispose!: () => void;\n currentNode = createRoot((dispose) => {\n branchDispose = dispose;\n return untrack(() => branchFn());\n });\n currentDispose = branchDispose;\n } else {\n currentNode = null;\n }\n\n if (currentNode) {\n parent.insertBefore(currentNode, endMarker);\n }\n });\n\n // Attach cleanup so external disposal can clean up the branch and effect.\n (fragment as any).__showDispose = () => {\n showDispose();\n if (currentDispose) {\n currentDispose();\n currentDispose = null;\n }\n };\n\n return fragment;\n}\n","/**\n * FormaJS DOM - Hydrate\n *\n * Descriptor-based island hydration. During hydration, h() returns plain\n * descriptor objects instead of DOM elements. A top-down walk (adoptNode)\n * then matches these descriptors against SSR DOM to attach events and\n * reactive bindings. No DOM elements are created during hydration.\n */\n\nimport { internalEffect, createSignal, untrack, __DEV__ } from 'forma/reactive';\nimport { h } from './element.js';\nimport { reconcileList, createList } from './list.js';\nimport { createShow } from './show.js';\n\n// Same symbol identity as element.ts — Symbol.for() guarantees cross-module\n// sharing so cleanup(el) in element.ts aborts controllers created here.\nconst ABORT_SYM = Symbol.for('forma-abort');\n\n// ---------------------------------------------------------------------------\n// Hydration state — module-level boolean\n// ---------------------------------------------------------------------------\n\n/** True while hydration is in progress. Checked by h() to branch. */\nexport let hydrating = false;\n\n/**\n * Set the hydrating state. Used internally by hydration functions.\n * Required because `export let` cannot be reassigned from outside the module.\n */\nexport function setHydrating(value: boolean): void {\n hydrating = value;\n}\n\n// ---------------------------------------------------------------------------\n// Descriptor interfaces\n// ---------------------------------------------------------------------------\n\n/** Descriptor returned by h() during hydration instead of a real Element. */\nexport interface HydrationDescriptor {\n type: 'element';\n tag: string;\n props: Record<string, unknown> | null;\n children: unknown[];\n}\n\n/** Descriptor returned by createShow() during hydration. */\nexport interface ShowDescriptor {\n type: 'show';\n condition: () => unknown;\n whenTrue: () => unknown;\n whenFalse?: () => unknown;\n initialBranch: unknown;\n}\n\n/** Descriptor returned by createList() during hydration. */\nexport interface ListDescriptor {\n type: 'list';\n items: () => unknown[];\n keyFn: (item: unknown) => string | number;\n renderFn: (item: unknown, index: () => number) => HTMLElement;\n options?: Record<string, unknown>;\n}\n\n/** Maps built by collectMarkers() for O(1) marker lookup during adoption. */\nexport interface MarkerMap {\n text: Map<number, Text>;\n show: Map<number, { start: Comment; end: Comment; cachedContent: DocumentFragment | null }>;\n list: Map<number, { start: Comment; end: Comment }>;\n}\n\n// ---------------------------------------------------------------------------\n// Type guards\n// ---------------------------------------------------------------------------\n\n/** Check if a value is a HydrationDescriptor. */\nexport function isDescriptor(v: unknown): v is HydrationDescriptor {\n return v != null && typeof v === 'object' && 'type' in v && v.type === 'element';\n}\n\n/** Check if a value is a ShowDescriptor. */\nexport function isShowDescriptor(v: unknown): v is ShowDescriptor {\n return v != null && typeof v === 'object' && 'type' in v && v.type === 'show';\n}\n\n/** Check if a value is a ListDescriptor. */\nexport function isListDescriptor(v: unknown): v is ListDescriptor {\n return v != null && typeof v === 'object' && 'type' in v && v.type === 'list';\n}\n\n// ---------------------------------------------------------------------------\n// collectMarkers() — single-pass TreeWalker\n// ---------------------------------------------------------------------------\n\n/**\n * Walk the DOM under `root` once, collecting text and show markers into a\n * MarkerMap for O(1) lookup during adoptNode().\n *\n * Text markers: `<!--f:t0-->`, `<!--f:t1-->`, ... followed by a Text node\n * Show markers: `<!--f:s0-->` ... `<!--/f:s0-->` pairs\n */\nexport function collectMarkers(root: Element): MarkerMap {\n const text = new Map<number, Text>();\n const show = new Map<number, { start: Comment; end: Comment; cachedContent: DocumentFragment | null }>();\n const list = new Map<number, { start: Comment; end: Comment }>();\n\n // Pending show-start comments keyed by index, waiting for their closing marker\n const pendingShow = new Map<number, Comment>();\n // Pending list-start comments keyed by index, waiting for their closing marker\n const pendingList = new Map<number, Comment>();\n\n const walker = document.createTreeWalker(root, NodeFilter.SHOW_ALL, {\n acceptNode(node) {\n // Skip child island subtrees (REJECT = skip node AND all descendants)\n if (node !== root && node.nodeType === 1 &&\n (node as Element).hasAttribute('data-forma-island')) {\n return NodeFilter.FILTER_REJECT;\n }\n // Only process comments and text nodes\n if (node.nodeType === Node.COMMENT_NODE || node.nodeType === Node.TEXT_NODE) {\n return NodeFilter.FILTER_ACCEPT;\n }\n // Elements: skip the node itself but walk into children\n return NodeFilter.FILTER_SKIP;\n }\n });\n\n while (walker.nextNode()) {\n const node = walker.currentNode;\n\n if (node.nodeType === Node.COMMENT_NODE) {\n const data = (node as Comment).data;\n\n // Text marker: \"f:t<index>\"\n if (data.length >= 4 && data.charCodeAt(0) === 102 /* f */ && data.charCodeAt(1) === 58 /* : */ && data.charCodeAt(2) === 116 /* t */) {\n const idx = parseInt(data.slice(3), 10);\n if (!isNaN(idx)) {\n // The text node is the next sibling\n const next = node.nextSibling;\n if (next && next.nodeType === Node.TEXT_NODE) {\n text.set(idx, next as Text);\n }\n }\n continue;\n }\n\n // Show opening marker: \"f:s<index>\"\n if (data.length >= 4 && data.charCodeAt(0) === 102 /* f */ && data.charCodeAt(1) === 58 /* : */ && data.charCodeAt(2) === 115 /* s */) {\n const idx = parseInt(data.slice(3), 10);\n if (!isNaN(idx)) {\n pendingShow.set(idx, node as Comment);\n }\n continue;\n }\n\n // Show closing marker: \"/f:s<index>\"\n if (data.length >= 5 && data.charCodeAt(0) === 47 /* / */ && data.charCodeAt(1) === 102 /* f */ && data.charCodeAt(2) === 58 /* : */ && data.charCodeAt(3) === 115 /* s */) {\n const idx = parseInt(data.slice(4), 10);\n if (!isNaN(idx)) {\n const start = pendingShow.get(idx);\n if (start) {\n show.set(idx, { start, end: node as Comment, cachedContent: null });\n pendingShow.delete(idx);\n }\n }\n continue;\n }\n\n // List opening marker: \"f:l<index>\"\n if (data.length >= 4 && data.charCodeAt(0) === 102 /* f */ && data.charCodeAt(1) === 58 /* : */ && data.charCodeAt(2) === 108 /* l */) {\n const idx = parseInt(data.slice(3), 10);\n if (!isNaN(idx)) {\n pendingList.set(idx, node as Comment);\n }\n continue;\n }\n\n // List closing marker: \"/f:l<index>\"\n if (data.length >= 5 && data.charCodeAt(0) === 47 /* / */ && data.charCodeAt(1) === 102 /* f */ && data.charCodeAt(2) === 58 /* : */ && data.charCodeAt(3) === 108 /* l */) {\n const idx = parseInt(data.slice(4), 10);\n if (!isNaN(idx)) {\n const start = pendingList.get(idx);\n if (start) {\n list.set(idx, { start, end: node as Comment });\n pendingList.delete(idx);\n }\n }\n continue;\n }\n }\n }\n\n return { text, show, list };\n}\n\n// ---------------------------------------------------------------------------\n// applyDynamicProps()\n// ---------------------------------------------------------------------------\n\n/**\n * Attach event handlers and reactive attribute bindings to an existing\n * SSR element. Static (non-function) props are skipped because they are\n * already baked into the server HTML.\n */\nexport function applyDynamicProps(el: Element, props: Record<string, unknown> | null): void {\n if (!props) return;\n\n for (const key in props) {\n const value = props[key];\n\n // Skip non-function values — they are static and already in the SSR HTML\n if (typeof value !== 'function') continue;\n\n // Event handlers: onXxx — use AbortController so cleanup(el) removes them\n if (key.charCodeAt(0) === 111 /* o */ && key.charCodeAt(1) === 110 /* n */ && key.length > 2) {\n let ac = (el as any)[ABORT_SYM] as AbortController | undefined;\n if (!ac) {\n ac = new AbortController();\n (el as any)[ABORT_SYM] = ac;\n }\n el.addEventListener(key.slice(2).toLowerCase(), value as EventListener, { signal: ac.signal });\n continue;\n }\n\n // Reactive attribute binding (function, non-event)\n const fn = value as () => unknown;\n const attrKey = key; // capture for closure\n internalEffect(() => {\n const v = fn();\n if (v === false || v == null) {\n el.removeAttribute(attrKey);\n } else if (v === true) {\n el.setAttribute(attrKey, '');\n } else {\n el.setAttribute(attrKey, String(v));\n }\n });\n }\n}\n\n// ---------------------------------------------------------------------------\n// descriptorToElement()\n// ---------------------------------------------------------------------------\n\n/**\n * Convert any hydration-mode value (descriptor, show, list, or Node) back\n * into a real DOM Node. Used when SSR content mismatches client state and\n * the framework needs to create fresh DOM from captured descriptors.\n *\n * Temporarily exits hydration mode so h(), createShow(), createList()\n * create real elements with reactive bindings.\n */\nexport function ensureNode(value: unknown): Node | null {\n if (value instanceof Node) return value;\n if (value == null || value === false || value === true) return null;\n if (typeof value === 'string') return new Text(value);\n if (typeof value === 'number') return new Text(String(value));\n if (isDescriptor(value)) return descriptorToElement(value);\n if (isShowDescriptor(value)) {\n const prevH = hydrating;\n hydrating = false;\n try {\n return createShow(\n value.condition,\n () => ensureNode(value.whenTrue()) ?? document.createComment('empty'),\n value.whenFalse\n ? () => ensureNode(value.whenFalse!()) ?? document.createComment('empty')\n : undefined,\n );\n } finally {\n hydrating = prevH;\n }\n }\n if (isListDescriptor(value)) {\n const prevH = hydrating;\n hydrating = false;\n try {\n return createList(value.items, value.keyFn, value.renderFn, value.options);\n } finally {\n hydrating = prevH;\n }\n }\n return null;\n}\n\n/**\n * Convert a HydrationDescriptor back into a real DOM Element by calling h().\n * Used as a fallback when SSR DOM is missing or mismatched.\n *\n * Temporarily exits hydration mode so h() creates real elements.\n * Handles nested ShowDescriptor and ListDescriptor children by converting\n * them to real reactive primitives (createShow, createList).\n */\nexport function descriptorToElement(desc: HydrationDescriptor): Element {\n const prevHydrating = hydrating;\n hydrating = false;\n\n try {\n // Map children: recurse for nested descriptors, convert Show/List\n const children = desc.children.map((child) => {\n if (isDescriptor(child)) return descriptorToElement(child);\n if (isShowDescriptor(child)) return ensureNode(child);\n if (isListDescriptor(child)) return ensureNode(child);\n return child;\n });\n\n return h(desc.tag, desc.props, ...children);\n } finally {\n hydrating = prevHydrating;\n }\n}\n\n// ---------------------------------------------------------------------------\n// DOM cursor helpers for adoptNode\n// ---------------------------------------------------------------------------\n\n/** Check if comment data is an island start marker (f:iN). */\nfunction isIslandStart(data: string): boolean {\n return data.length >= 4 && data.charCodeAt(0) === 102 /* f */ && data.charCodeAt(1) === 58 /* : */ && data.charCodeAt(2) === 105 /* i */;\n}\n\n/** Check if comment data is a show start marker (f:sN). */\nfunction isShowStart(data: string): boolean {\n return data.length >= 4 && data.charCodeAt(0) === 102 /* f */ && data.charCodeAt(1) === 58 /* : */ && data.charCodeAt(2) === 115 /* s */;\n}\n\n/** Check if comment data is a text marker (f:tN). */\nfunction isTextStart(data: string): boolean {\n return data.length >= 4 && data.charCodeAt(0) === 102 /* f */ && data.charCodeAt(1) === 58 /* : */ && data.charCodeAt(2) === 116 /* t */;\n}\n\n/** Check if comment data is a list start marker (f:lN). */\nfunction isListStart(data: string): boolean {\n return data.length >= 4 && data.charCodeAt(0) === 102 /* f */ && data.charCodeAt(1) === 58 /* : */ && data.charCodeAt(2) === 108 /* l */;\n}\n\n/** Find the closing comment marker for a start marker (e.g., f:i0 → /f:i0). */\nfunction findClosingMarker(start: Comment): Comment | null {\n const closing = '/' + start.data;\n let node: Node | null = start.nextSibling;\n while (node) {\n if (node.nodeType === 8 && (node as Comment).data === closing) {\n return node as Comment;\n }\n node = node.nextSibling;\n }\n return null;\n}\n\n/** Find the first Text node between two comment markers (exclusive). */\nfunction findTextBetween(start: Comment, end: Comment): Text | null {\n let node: Node | null = start.nextSibling;\n while (node && node !== end) {\n if (node.nodeType === 3) return node as Text;\n node = node.nextSibling;\n }\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Show descriptor helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Find the first Element node between two comment markers (exclusive).\n */\nfunction nextElementBetweenMarkers(start: Comment, end: Comment): Element | undefined {\n let node: Node | null = start.nextSibling;\n while (node && node !== end) {\n if (node.nodeType === 1) return node as Element;\n node = node.nextSibling;\n }\n return undefined;\n}\n\n/**\n * Extract all nodes between two comment markers into a DocumentFragment.\n * The markers themselves are left in place.\n */\nfunction extractContentBetweenMarkers(start: Comment, end: Comment): DocumentFragment {\n const frag = document.createDocumentFragment();\n let node = start.nextSibling;\n while (node && node !== end) {\n const next = node.nextSibling;\n frag.appendChild(node);\n node = next;\n }\n return frag;\n}\n\n/**\n * Set up reactive show effect after hydration adoption.\n *\n * During initial hydration, content is adopted in place (no DOM movement).\n * On first toggle, current content is scooped into a cached fragment.\n * Subsequent toggles swap between cached fragments (pure DOM moves, no re-render).\n */\nfunction setupShowEffect(\n desc: ShowDescriptor,\n marker: { start: Comment; end: Comment; cachedContent: DocumentFragment | null },\n): void {\n let currentCondition = !!desc.condition();\n let thenFragment: DocumentFragment | null = null;\n let elseFragment: DocumentFragment | null = null;\n\n // Reverse mismatch: SSR is empty but client condition is true.\n // Insert truthy content immediately so the user sees correct content.\n const hasSSRContent = marker.start.nextSibling !== marker.end;\n if (!hasSSRContent && currentCondition) {\n if (__DEV__) console.warn('[forma] Hydration: show condition mismatch — SSR empty but client condition is true');\n const trueBranch = desc.whenTrue();\n if (trueBranch instanceof Node) {\n marker.start.parentNode!.insertBefore(trueBranch, marker.end);\n }\n }\n\n internalEffect(() => {\n const next = !!desc.condition();\n if (next === currentCondition) return;\n currentCondition = next;\n\n const parent = marker.start.parentNode;\n if (!parent) return;\n\n // Cache current content\n const current = extractContentBetweenMarkers(marker.start, marker.end);\n if (!next) {\n thenFragment = current;\n } else {\n elseFragment = current;\n }\n\n // Insert the appropriate branch: cached fragment if available, else factory\n let branch: unknown = next\n ? (thenFragment ?? desc.whenTrue())\n : (desc.whenFalse ? (elseFragment ?? desc.whenFalse()) : null);\n\n if (next && thenFragment) thenFragment = null; // consumed\n if (!next && elseFragment) elseFragment = null; // consumed\n\n // Convert hydration descriptors to real DOM (happens when SSR/client\n // branch mismatch causes the factory to return a pre-computed descriptor)\n if (branch != null && !(branch instanceof Node)) {\n branch = ensureNode(branch);\n }\n\n if (branch instanceof Node) {\n parent.insertBefore(branch, marker.end);\n }\n });\n}\n\n// ---------------------------------------------------------------------------\n// adoptBranchContent() — walk nested show/list descriptors in SSR content\n// ---------------------------------------------------------------------------\n\n/**\n * Recursively adopt the content between show markers against a descriptor\n * that may be a HydrationDescriptor, ShowDescriptor, or ListDescriptor.\n *\n * This handles the case where createShow nests: the outer show's\n * initialBranch is itself a ShowDescriptor (not a plain element), so we\n * need to find inner SSR markers and walk into them.\n */\nfunction adoptBranchContent(\n desc: unknown,\n regionStart: Comment,\n regionEnd: Comment,\n): void {\n if (isDescriptor(desc)) {\n // Plain element — find it between markers and adopt\n const el = nextElementBetweenMarkers(regionStart, regionEnd);\n if (el) adoptNode(desc, el);\n } else if (isShowDescriptor(desc)) {\n // Nested show — find inner show markers between region markers\n let node: ChildNode | null = regionStart.nextSibling;\n while (node && node !== regionEnd) {\n if (node.nodeType === 8 && isShowStart((node as Comment).data)) {\n const innerStart = node as Comment;\n const innerEnd = findClosingMarker(innerStart);\n if (innerEnd) {\n // Recursively adopt the inner show's content\n if (desc.initialBranch) {\n adoptBranchContent(desc.initialBranch, innerStart, innerEnd);\n }\n // Set up the inner show's toggle effect\n setupShowEffect(desc, { start: innerStart, end: innerEnd, cachedContent: null });\n }\n break;\n }\n node = node.nextSibling;\n }\n }\n // ListDescriptor adoption within show markers is handled by the existing\n // list adoption code in adoptNode when it encounters list markers.\n}\n\n// ---------------------------------------------------------------------------\n// adoptNode() — top-down descriptor walk with DOM cursor\n// ---------------------------------------------------------------------------\n\n/**\n * Walk a descriptor tree top-down, matching each descriptor against the\n * corresponding SSR DOM using a childNode cursor. Attaches event handlers\n * and reactive bindings without creating new DOM nodes.\n *\n * The cursor approach handles:\n * - Island markers (<!--f:iN-->): creates real DOM from descriptor\n * - Show markers (<!--f:sN-->): binds show effects or reactive text\n * - Text markers (<!--f:tN-->): binds reactive text effects\n * - Tag mismatches: falls back to descriptorToElement()\n */\nexport function adoptNode(\n desc: HydrationDescriptor,\n ssrEl: Element | undefined,\n): void {\n // Mismatch check\n if (!ssrEl || ssrEl.tagName !== desc.tag.toUpperCase()) {\n if (__DEV__) console.warn(`Hydration mismatch: expected <${desc.tag}>, got <${ssrEl?.tagName?.toLowerCase() ?? 'nothing'}>`);\n const fresh = descriptorToElement(desc);\n if (ssrEl) ssrEl.replaceWith(fresh);\n return;\n }\n\n // Attach dynamic props\n applyDynamicProps(ssrEl, desc.props);\n\n // Walk children via DOM cursor (instead of children[index])\n let cursor: ChildNode | null = ssrEl.firstChild;\n\n for (const child of desc.children) {\n // Skip falsy children\n if (child === false || child == null) continue;\n\n if (isDescriptor(child)) {\n // Skip whitespace-only text nodes\n while (cursor && cursor.nodeType === 3 && !(cursor as Text).data.trim()) {\n cursor = cursor.nextSibling;\n }\n\n // Skip child island elements — they are handled by their own activation\n while (cursor && cursor.nodeType === 1 &&\n (cursor as Element).hasAttribute('data-forma-island')) {\n cursor = cursor.nextSibling;\n }\n\n if (!cursor) {\n // No more DOM nodes — append fresh\n ssrEl.appendChild(descriptorToElement(child));\n continue;\n }\n\n if (cursor.nodeType === 1) {\n // Element node — adopt recursively\n const el = cursor as Element;\n cursor = cursor.nextSibling;\n adoptNode(child, el);\n } else if (cursor.nodeType === 8 && isIslandStart((cursor as Comment).data)) {\n // Island marker — create real DOM and insert before end marker\n const end = findClosingMarker(cursor as Comment);\n const fresh = descriptorToElement(child);\n if (end) {\n end.parentNode!.insertBefore(fresh, end);\n cursor = end.nextSibling;\n } else {\n ssrEl.appendChild(fresh);\n cursor = null;\n }\n } else {\n // Unexpected node — create fresh and append\n ssrEl.appendChild(descriptorToElement(child));\n }\n\n } else if (isShowDescriptor(child)) {\n // Advance cursor to next show marker\n while (cursor && !(cursor.nodeType === 8 && isShowStart((cursor as Comment).data))) {\n cursor = cursor.nextSibling;\n }\n\n if (cursor) {\n const start = cursor as Comment;\n const end = findClosingMarker(start);\n if (end) {\n if (child.initialBranch) {\n // Walk the initial branch against SSR content between markers.\n // initialBranch can be a HydrationDescriptor (element), ShowDescriptor\n // (nested show), or ListDescriptor — adoptBranchContent handles all.\n adoptBranchContent(child.initialBranch, start, end);\n }\n setupShowEffect(child, { start, end, cachedContent: null });\n cursor = end.nextSibling;\n }\n }\n\n } else if (isListDescriptor(child)) {\n // Advance cursor to next list marker\n while (cursor && !(cursor.nodeType === 8 && isListStart((cursor as Comment).data))) {\n cursor = cursor.nextSibling;\n }\n\n if (cursor) {\n const start = cursor as Comment;\n const end = findClosingMarker(start);\n if (end) {\n // Walk DOM between markers, collect SSR elements\n const ssrKeyMap = new Map<string | number, HTMLElement>();\n const ssrElements: HTMLElement[] = [];\n let node: Node | null = start.nextSibling;\n while (node && node !== end) {\n if (node.nodeType === 1) {\n const el = node as HTMLElement;\n ssrElements.push(el);\n const key = el.getAttribute('data-forma-key');\n if (key != null) {\n ssrKeyMap.set(key, el);\n }\n }\n node = node.nextSibling;\n }\n\n // Read current items without tracking (we set up our own effect below)\n const currentItems = untrack(() => child.items()) as any[];\n const listKeyFn = child.keyFn;\n const listRenderFn = child.renderFn;\n\n // Fallback: if no SSR elements have data-forma-key, match by index\n const useIndexFallback = ssrKeyMap.size === 0 && ssrElements.length > 0;\n\n // Match current items to SSR nodes by key (or index fallback)\n const adoptedNodes: Node[] = [];\n const adoptedItems: any[] = [];\n const usedIndices = new Set<number>();\n\n for (let i = 0; i < currentItems.length; i++) {\n const item = currentItems[i];\n const key = listKeyFn(item);\n\n let ssrNode: HTMLElement | undefined;\n if (useIndexFallback) {\n // Index-based matching: SSR elements lack keys, adopt by position\n if (i < ssrElements.length) {\n ssrNode = ssrElements[i];\n usedIndices.add(i);\n }\n } else {\n // Key-based matching: SSR keys from getAttribute() are always strings\n ssrNode = ssrKeyMap.get(String(key));\n if (ssrNode) ssrKeyMap.delete(String(key));\n }\n\n if (ssrNode) {\n // Reuse SSR element\n adoptedNodes.push(ssrNode);\n adoptedItems.push(item);\n } else {\n // Not found in SSR — render fresh, exit hydration mode temporarily\n if (__DEV__) console.warn(`[FormaJS] Hydration: list item key \"${key}\" not found in SSR — rendering fresh`);\n const prevHydrating = hydrating;\n hydrating = false;\n try {\n const [getIndex] = createSignal(i);\n const fresh = listRenderFn(item, getIndex);\n // Insert before end marker\n end.parentNode!.insertBefore(fresh, end);\n adoptedNodes.push(fresh);\n adoptedItems.push(item);\n } finally {\n hydrating = prevHydrating;\n }\n }\n }\n\n // Remove unused SSR nodes (keys that weren't matched, or excess index-based)\n if (useIndexFallback) {\n for (let i = 0; i < ssrElements.length; i++) {\n if (!usedIndices.has(i) && ssrElements[i]!.parentNode) {\n ssrElements[i]!.parentNode!.removeChild(ssrElements[i]!);\n }\n }\n } else {\n for (const [unusedKey, unusedNode] of ssrKeyMap) {\n if (__DEV__) console.warn(`[FormaJS] Hydration: removing extra SSR list item with key \"${unusedKey}\"`);\n if (unusedNode.parentNode) {\n unusedNode.parentNode.removeChild(unusedNode);\n }\n }\n }\n\n // Reorder adopted nodes to match item order (insert before end marker)\n const parent = start.parentNode!;\n for (const adoptedNode of adoptedNodes) {\n parent.insertBefore(adoptedNode, end);\n }\n\n // Set up state for reactive reconciliation.\n // Cache maps key → { element, item, getIndex, setIndex } so that\n // index signals can be updated after reconcileList reorders items\n // (same pattern as the non-hydration createList in list.ts).\n let cache = new Map<string | number, {\n element: HTMLElement;\n item: any;\n getIndex: () => number;\n setIndex: (v: number) => void;\n }>();\n\n // Seed cache with adopted items\n for (let i = 0; i < adoptedItems.length; i++) {\n const item = adoptedItems[i];\n const key = listKeyFn(item);\n const [getIndex, setIndex] = createSignal(i);\n cache.set(key, {\n element: adoptedNodes[i] as HTMLElement,\n item,\n getIndex,\n setIndex,\n });\n }\n\n let reconcileNodes = adoptedNodes.slice();\n let reconcileItems = adoptedItems.slice();\n\n // Attach reactive effect that calls reconcileList for subsequent updates\n internalEffect(() => {\n const newItems = child.items() as any[];\n\n // The parent is discovered lazily: once inserted into the live DOM\n const parent = start.parentNode;\n if (!parent) return;\n\n const result = reconcileList(\n parent,\n reconcileItems,\n newItems,\n reconcileNodes,\n listKeyFn,\n (item: any) => {\n const prevHydrating = hydrating;\n hydrating = false;\n try {\n const key = listKeyFn(item);\n const [getIndex, setIndex] = createSignal(0);\n const element = untrack(() => listRenderFn(item, getIndex));\n cache.set(key, { element, item, getIndex, setIndex });\n return element;\n } finally {\n hydrating = prevHydrating;\n }\n },\n (_node: Node, item: any) => {\n const key = listKeyFn(item);\n const cached = cache.get(key);\n if (cached) cached.item = item;\n },\n end,\n );\n\n // Rebuild cache + update index signals in a single pass\n const newCache = new Map<string | number, typeof cache extends Map<any, infer V> ? V : never>();\n for (let i = 0; i < newItems.length; i++) {\n const key = listKeyFn(newItems[i]!);\n const cached = cache.get(key);\n if (cached) {\n cached.setIndex(i);\n newCache.set(key, cached);\n }\n }\n cache = newCache;\n\n reconcileNodes = result.nodes;\n reconcileItems = result.items;\n });\n\n cursor = end.nextSibling;\n }\n }\n\n } else if (typeof child === 'function') {\n // Reactive binding — could be text (signal getter) or element (returns descriptor).\n // Peek at the return value to determine type before choosing the adoption path.\n while (cursor && cursor.nodeType === 3 && !(cursor as Text).data.trim()) {\n cursor = cursor.nextSibling;\n }\n\n // If cursor is at an element, check whether function returns a descriptor\n if (cursor && cursor.nodeType === 1) {\n const initial = (child as () => unknown)();\n if (isDescriptor(initial)) {\n // Function returned a descriptor — adopt the element at cursor\n const el = cursor as Element;\n cursor = cursor.nextSibling;\n adoptNode(initial, el);\n continue;\n }\n // Not a descriptor — fall through to text handling\n }\n\n if (cursor && cursor.nodeType === 8) {\n const data = (cursor as Comment).data;\n\n if (isTextStart(data)) {\n // Text marker: <!--f:tN-->text<!--/f:tN-->\n const endMarker = findClosingMarker(cursor as Comment);\n let textNode = cursor.nextSibling;\n if (!textNode || textNode.nodeType !== 3) {\n // Defensive fallback: SSR should have emitted a text node between\n // markers. If missing, create one — but warn in dev mode.\n if (__DEV__) console.warn(`[FormaJS] Hydration: created text node for marker ${data} — SSR walker should emit content between markers`);\n const created = document.createTextNode('');\n cursor.parentNode!.insertBefore(created, endMarker || cursor.nextSibling);\n textNode = created;\n }\n internalEffect(() => {\n (textNode as Text).data = String((child as () => unknown)());\n });\n cursor = endMarker ? endMarker.nextSibling : textNode.nextSibling;\n } else if (isShowStart(data)) {\n // Show marker used for reactive text (IR compiled inline ternary as ShowIf)\n const start = cursor as Comment;\n const end = findClosingMarker(start);\n if (end) {\n let textNode = findTextBetween(start, end);\n if (!textNode) {\n // Defensive fallback: SSR should have emitted content between\n // show markers for reactive text. Warn in dev mode.\n if (__DEV__) console.warn(`[FormaJS] Hydration: created text node for show marker ${start.data} — SSR walker should emit content between markers`);\n textNode = document.createTextNode('');\n start.parentNode!.insertBefore(textNode, end);\n }\n internalEffect(() => {\n (textNode as Text).data = String((child as () => unknown)());\n });\n cursor = end.nextSibling;\n } else {\n cursor = cursor.nextSibling;\n }\n } else {\n cursor = cursor.nextSibling;\n }\n } else if (cursor && cursor.nodeType === 3) {\n // Existing text node without markers — bind reactive effect directly\n const textNode = cursor as Text;\n cursor = cursor.nextSibling;\n internalEffect(() => {\n textNode.data = String((child as () => unknown)());\n });\n } else {\n // No cursor (empty parent) or unexpected node — SSR element has no\n // children where a reactive text binding is expected. This means the\n // IR didn't cover this part of the component tree. Warn and create.\n if (__DEV__) console.warn(`[FormaJS] Hydration: created text node in empty <${ssrEl.tagName.toLowerCase()}> — IR may not cover this component`);\n const textNode = document.createTextNode('');\n ssrEl.appendChild(textNode);\n internalEffect(() => {\n textNode.data = String((child as () => unknown)());\n });\n }\n } else if (typeof child === 'string' || typeof child === 'number') {\n // Static text — advance cursor past corresponding text node\n if (cursor && cursor.nodeType === 3) {\n cursor = cursor.nextSibling;\n }\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// hydrateIsland() — full orchestration\n// ---------------------------------------------------------------------------\n\n/**\n * Hydrate an SSR island in-place. Runs the component in hydration mode so\n * h() returns descriptors, then walks the descriptor tree against the SSR DOM\n * to attach event handlers and reactive bindings. No DOM elements are created.\n *\n * The component function MUST be called inside a reactive root (createRoot)\n * so that effects created during adoption are properly tracked.\n *\n * Returns the active root element — usually `target`, but may be a replacement\n * element when the CSR fallback fires (empty island shell replaced by the\n * component's own root element).\n *\n * @param component A function that builds the UI (calls h(), createShow, etc.)\n * @param target The container element with `data-forma-ssr` attribute\n */\nexport function hydrateIsland(component: () => unknown, target: Element): Element {\n // Check if the island has SSR content to hydrate against.\n // An empty island shell (tag + static attrs from compiler, no children)\n // has nothing to hydrate — fall through to CSR mode.\n const hasSSRContent = target.childElementCount > 0 ||\n (target.childNodes.length > 0 &&\n Array.from(target.childNodes).some(n =>\n n.nodeType === 1 || (n.nodeType === 3 && (n as Text).data.trim())));\n\n if (!hasSSRContent) {\n // CSR fallback: SSR emitted an empty shell element for this island.\n // Run the component in normal (non-hydration) mode and replace the\n // shell with the component's own root element.\n if (__DEV__) {\n const name = target.getAttribute('data-forma-component') || 'unknown';\n console.warn(\n `[forma] Island \"${name}\" has no SSR content — falling back to CSR. ` +\n `This means the IR walker did not render content between ISLAND_START and ISLAND_END.`,\n );\n }\n\n const result = component();\n if (result instanceof Element) {\n // Transfer data-forma-* attributes from the shell to the component's root\n for (const attr of Array.from(target.attributes)) {\n if (attr.name.startsWith('data-forma-')) {\n result.setAttribute(attr.name, attr.value);\n }\n }\n target.replaceWith(result);\n return result;\n } else if (result instanceof Node) {\n target.appendChild(result);\n }\n return target;\n }\n\n // 1. Enter hydration mode (h() returns descriptors)\n setHydrating(true);\n\n // 2. Run component — builds descriptor tree, zero DOM work\n let descriptor: unknown;\n try {\n descriptor = component();\n } finally {\n // 3. Exit hydration mode\n setHydrating(false);\n }\n\n // Guard: if component returned nothing (e.g. mock fn in tests, or simple\n // islands that only set up effects), skip adoption entirely.\n if (!descriptor || !isDescriptor(descriptor)) {\n target.removeAttribute('data-forma-ssr');\n return target;\n }\n\n // 4. Walk descriptor tree top-down against SSR DOM.\n // For island activation: the target IS the island root element (has\n // data-forma-island). Adopt directly on target.\n // For mount() container pattern: target is a wrapper, adopt on target.children[0].\n if (target.hasAttribute('data-forma-island')) {\n adoptNode(descriptor, target);\n } else {\n adoptNode(descriptor, target.children[0] as Element);\n }\n\n // 5. Remove SSR marker\n target.removeAttribute('data-forma-ssr');\n return target;\n}\n\n","/**\n * Forma DOM - Element\n *\n * Hyperscript-style element factory (`h`) and Fragment helper.\n * Backed by alien-signals via forma/reactive.\n *\n * Supports both HTML and SVG elements with automatic namespace detection.\n * Provides event listener cleanup via AbortController.\n */\n\nimport { internalEffect } from 'forma/reactive';\nimport { hydrating, type HydrationDescriptor } from './hydrate.js';\n\n/**\n * Symbol used as JSX Fragment factory. h(Fragment, null, ...children) returns DocumentFragment.\n *\n * Typed as a callable for TypeScript's JSX checker — at runtime it's a symbol\n * that h() detects via `tag === Fragment`. esbuild transforms `<>...</>` into\n * `h(Fragment, null, ...)` which never actually calls Fragment.\n */\nexport const Fragment: (props: { children?: unknown }) => DocumentFragment =\n Symbol.for('forma.fragment') as any;\n\n// ---------------------------------------------------------------------------\n// SVG namespace and tag detection\n// ---------------------------------------------------------------------------\n\nconst SVG_NS = 'http://www.w3.org/2000/svg';\nconst XLINK_NS = 'http://www.w3.org/1999/xlink';\n\n/** Known SVG tag names for O(1) lookup. */\nconst SVG_TAGS = new Set([\n 'svg',\n 'path',\n 'circle',\n 'rect',\n 'line',\n 'polyline',\n 'polygon',\n 'ellipse',\n 'g',\n 'text',\n 'tspan',\n 'textPath',\n 'defs',\n 'use',\n 'symbol',\n 'clipPath',\n 'mask',\n 'pattern',\n 'marker',\n 'linearGradient',\n 'radialGradient',\n 'stop',\n 'filter',\n 'feGaussianBlur',\n 'feColorMatrix',\n 'feOffset',\n 'feBlend',\n 'feMerge',\n 'feMergeNode',\n 'feComposite',\n 'feFlood',\n 'feMorphology',\n 'feTurbulence',\n 'feDisplacementMap',\n 'feImage',\n 'foreignObject',\n 'animate',\n 'animateTransform',\n 'animateMotion',\n 'set',\n 'image',\n 'switch',\n 'desc',\n 'title',\n 'metadata',\n]);\n\n// ---------------------------------------------------------------------------\n// Boolean HTML attributes (set/remove via setAttribute/removeAttribute)\n// ---------------------------------------------------------------------------\n\nconst BOOLEAN_ATTRS = new Set([\n 'disabled',\n 'checked',\n 'readonly',\n 'required',\n 'autofocus',\n 'autoplay',\n 'controls',\n 'default',\n 'defer',\n 'formnovalidate',\n 'hidden',\n 'ismap',\n 'loop',\n 'multiple',\n 'muted',\n 'nomodule',\n 'novalidate',\n 'open',\n 'playsinline',\n 'reversed',\n 'selected',\n 'async',\n]);\n\n// ---------------------------------------------------------------------------\n// Element prototype cache — cloneNode(false) is a C++ memcpy, faster than\n// createElement which must parse the tag string and validate.\n// \"Flexible Wings\" exploit: the prototypes pass static inspection (they're\n// standard elements) but flex at runtime to avoid parsing overhead.\n// ---------------------------------------------------------------------------\n\nlet ELEMENT_PROTOS: Record<string, HTMLElement> | null = null;\n\nfunction getProto(tag: string): HTMLElement {\n if (!ELEMENT_PROTOS) {\n ELEMENT_PROTOS = Object.create(null);\n // Pre-create prototypes for the 30 most common HTML tags\n for (const t of [\n 'div', 'span', 'p', 'a', 'li', 'ul', 'ol', 'button', 'input',\n 'label', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'section', 'header',\n 'footer', 'main', 'nav', 'table', 'tr', 'td', 'th', 'tbody',\n 'img', 'form', 'select', 'option', 'textarea', 'i', 'b', 'strong',\n 'em', 'small', 'article', 'aside', 'details', 'summary',\n ]) {\n ELEMENT_PROTOS![t] = document.createElement(t);\n }\n }\n return ELEMENT_PROTOS![tag] ?? (ELEMENT_PROTOS![tag] = document.createElement(tag));\n}\n\n// ---------------------------------------------------------------------------\n// Event name cache — avoids .slice(2).toLowerCase() string allocations\n// on every event binding. \"Super Clipping\" exploit.\n// ---------------------------------------------------------------------------\n\nconst EVENT_NAMES: Record<string, string> = Object.create(null);\n\nfunction eventName(key: string): string {\n return EVENT_NAMES[key] ?? (EVENT_NAMES[key] = key.slice(2).toLowerCase());\n}\n\n// ---------------------------------------------------------------------------\n// Symbol-based AbortController storage (avoids WeakMap overhead)\n// ---------------------------------------------------------------------------\n\nconst ABORT_SYM = Symbol.for('forma-abort');\n\n/** Get or lazily create an AbortController for an element. */\nfunction getAbortController(el: Element): AbortController {\n let controller = (el as any)[ABORT_SYM] as AbortController | undefined;\n if (!controller) {\n controller = new AbortController();\n (el as any)[ABORT_SYM] = controller;\n }\n return controller;\n}\n\n/**\n * Remove all event listeners previously attached via `h()` on the given element.\n *\n * Calls `AbortController.abort()` for the element, which automatically removes\n * every listener that was registered with its signal. The controller is then\n * deleted so a fresh one is created if the element is reused.\n */\nexport function cleanup(el: Element): void {\n const controller = (el as any)[ABORT_SYM] as AbortController | undefined;\n if (controller) {\n controller.abort();\n delete (el as any)[ABORT_SYM];\n }\n}\n\n// ---------------------------------------------------------------------------\n// Attribute diffing cache (avoids redundant DOM writes)\n// ---------------------------------------------------------------------------\n\nconst CACHE_SYM = Symbol.for('forma-attr-cache');\nconst DYNAMIC_CHILD_SYM = Symbol.for('forma-dynamic-child');\n\nfunction getCache(el: Element): Record<string, unknown> {\n return (el as any)[CACHE_SYM] ?? ((el as any)[CACHE_SYM] = Object.create(null));\n}\n\n// ---------------------------------------------------------------------------\n// Prop handler functions (extracted for dispatch table)\n// ---------------------------------------------------------------------------\n\ntype PropHandler = (el: Element, key: string, value: unknown) => void;\n\n/** Handle class / className prop. */\nfunction handleClass(el: Element, _key: string, value: unknown): void {\n if (typeof value === 'function') {\n internalEffect(() => {\n const v = (value as () => string)();\n const cache = getCache(el);\n if (cache['class'] === v) return;\n cache['class'] = v;\n if (el instanceof HTMLElement) {\n el.className = v;\n } else {\n el.setAttribute('class', v);\n }\n });\n } else {\n const cache = getCache(el);\n if (cache['class'] === value) return;\n cache['class'] = value;\n if (el instanceof HTMLElement) {\n el.className = value as string;\n } else {\n el.setAttribute('class', value as string);\n }\n }\n}\n\n/** Handle style prop. Reconciles object styles by removing stale keys. */\nfunction handleStyle(el: Element, _key: string, value: unknown): void {\n if (typeof value === 'function') {\n let prevKeys: string[] = [];\n internalEffect(() => {\n const v = (value as () => string | Record<string, string>)();\n if (typeof v === 'string') {\n const cache = getCache(el);\n if (cache['style'] === v) return;\n cache['style'] = v;\n prevKeys = [];\n (el as HTMLElement | SVGElement).style.cssText = v;\n } else if (v && typeof v === 'object') {\n const style = (el as HTMLElement | SVGElement).style;\n const nextKeys = Object.keys(v);\n // Remove keys that were present last time but are absent now\n for (const k of prevKeys) {\n if (!(k in (v as Record<string, string>))) {\n style.removeProperty(k.replace(/[A-Z]/g, (c) => '-' + c.toLowerCase()));\n }\n }\n Object.assign(style, v);\n prevKeys = nextKeys;\n }\n });\n } else if (typeof value === 'string') {\n const cache = getCache(el);\n if (cache['style'] === value) return;\n cache['style'] = value;\n (el as HTMLElement | SVGElement).style.cssText = value;\n } else if (value && typeof value === 'object') {\n Object.assign((el as HTMLElement | SVGElement).style, value);\n }\n}\n\n/** Handle event handler props (onClick, onInput, etc.). Cached eventName. */\nfunction handleEvent(el: Element, key: string, value: unknown): void {\n const controller = getAbortController(el);\n el.addEventListener(\n eventName(key),\n value as EventListener,\n { signal: controller.signal },\n );\n}\n\n/**\n * Handle dangerouslySetInnerHTML prop.\n *\n * **Security:** No sanitization is performed. Never pass user-controlled\n * strings through `__html` — this will create an XSS vulnerability.\n * Only use with trusted, server-generated markup.\n *\n * Supports both static `{ __html: string }` values and reactive functions\n * that return `{ __html: string }`.\n */\nfunction handleInnerHTML(el: Element, _key: string, value: unknown): void {\n if (typeof value === 'function') {\n internalEffect(() => {\n const resolved = (value as () => unknown)();\n if (resolved == null) {\n el.innerHTML = '';\n return;\n }\n if (typeof resolved !== 'object' || !('__html' in (resolved as any))) {\n throw new TypeError(\n 'dangerouslySetInnerHTML: expected { __html: string }, got ' + typeof resolved,\n );\n }\n const html = (resolved as { __html: string }).__html;\n if (typeof html !== 'string') {\n throw new TypeError(\n 'dangerouslySetInnerHTML: __html must be a string, got ' + typeof html,\n );\n }\n const cache = getCache(el);\n if (cache['innerHTML'] === html) return;\n cache['innerHTML'] = html;\n el.innerHTML = html;\n });\n } else {\n if (value == null) {\n el.innerHTML = '';\n return;\n }\n if (typeof value !== 'object' || !('__html' in (value as any))) {\n throw new TypeError(\n 'dangerouslySetInnerHTML: expected { __html: string }, got ' + typeof value,\n );\n }\n const html = (value as { __html: string }).__html;\n if (typeof html !== 'string') {\n throw new TypeError(\n 'dangerouslySetInnerHTML: __html must be a string, got ' + typeof html,\n );\n }\n el.innerHTML = html;\n }\n}\n\n/** Handle xlink: namespaced SVG attributes. */\nfunction handleXLink(el: Element, key: string, value: unknown): void {\n const localName = key.slice(6); // strip \"xlink:\" prefix\n if (typeof value === 'function') {\n internalEffect(() => {\n const v = (value as () => unknown)();\n if (v == null || v === false) {\n el.removeAttributeNS(XLINK_NS, localName);\n } else {\n el.setAttributeNS(XLINK_NS, key, String(v));\n }\n });\n } else {\n if (value == null || value === false) {\n el.removeAttributeNS(XLINK_NS, localName);\n } else {\n el.setAttributeNS(XLINK_NS, key, String(value));\n }\n }\n}\n\n/** Handle boolean attributes (disabled, checked, etc.). */\nfunction handleBooleanAttr(el: Element, key: string, value: unknown): void {\n if (typeof value === 'function') {\n internalEffect(() => {\n const v = (value as () => boolean)();\n const cache = getCache(el);\n if (cache[key] === v) return;\n cache[key] = v;\n if (v) {\n el.setAttribute(key, '');\n } else {\n el.removeAttribute(key);\n }\n });\n } else {\n const cache = getCache(el);\n if (cache[key] === value) return;\n cache[key] = value;\n if (value) {\n el.setAttribute(key, '');\n } else {\n el.removeAttribute(key);\n }\n }\n}\n\n/** Handle generic attributes with setAttribute/removeAttribute. */\nfunction handleGenericAttr(el: Element, key: string, value: unknown): void {\n if (typeof value === 'function') {\n internalEffect(() => {\n const v = (value as () => unknown)();\n if (v == null || v === false) {\n const cache = getCache(el);\n if (cache[key] === null) return;\n cache[key] = null;\n el.removeAttribute(key);\n } else {\n const strVal = String(v);\n const cache = getCache(el);\n if (cache[key] === strVal) return;\n cache[key] = strVal;\n el.setAttribute(key, strVal);\n }\n });\n } else {\n if (value == null || value === false) {\n const cache = getCache(el);\n if (cache[key] === null) return;\n cache[key] = null;\n el.removeAttribute(key);\n } else {\n const strVal = String(value);\n const cache = getCache(el);\n if (cache[key] === strVal) return;\n cache[key] = strVal;\n el.setAttribute(key, strVal);\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Prop dispatch table (O(1) Map lookup replaces sequential if/else chain)\n// ---------------------------------------------------------------------------\n\nconst PROP_HANDLERS = new Map<string, PropHandler>();\n\n// Register specific prop handlers\nPROP_HANDLERS.set('class', handleClass);\nPROP_HANDLERS.set('className', handleClass);\nPROP_HANDLERS.set('style', handleStyle);\nPROP_HANDLERS.set('ref', () => {}); // no-op, handled in h()\nPROP_HANDLERS.set('dangerouslySetInnerHTML', handleInnerHTML);\n\n// Register boolean attrs into the dispatch table\nfor (const attr of BOOLEAN_ATTRS) {\n PROP_HANDLERS.set(attr, handleBooleanAttr);\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\n/** Apply a single prop to an element (supports both HTML and SVG). */\nfunction applyProp(el: Element, key: string, value: unknown): void {\n // \"Twin Chassis\" exploit: inline check for the #1 most common prop\n // String === is ~2ns vs Map.get() ~8ns. Saves 75% dispatch time for 'class'.\n if (key === 'class') { handleClass(el, key, value); return; }\n\n // 2. Event handler detection (2-char check, faster than startsWith)\n // Events are the #2 most common prop type — check before Map.\n if (key.charCodeAt(0) === 111 /* 'o' */ && key.charCodeAt(1) === 110 /* 'n' */ && key.length > 2) {\n handleEvent(el, key, value); return;\n }\n\n // 3. Dispatch table for remaining known props (className, style, boolean attrs)\n const handler = PROP_HANDLERS.get(key);\n if (handler) { handler(el, key, value); return; }\n\n // 4. xlink: namespace (rare, check last)\n if (key.charCodeAt(0) === 120 /* 'x' */ && key.startsWith('xlink:')) {\n handleXLink(el, key, value); return;\n }\n\n // 5. Generic attribute fallback\n handleGenericAttr(el, key, value);\n}\n\n// ---------------------------------------------------------------------------\n// \"Blown Diffuser\" — static prop fast path (no cache, no effects)\n// Used only during h() initial element creation for non-function prop values.\n// Saves: getCache() lookup, cache diff check, cache write — per static prop.\n// ---------------------------------------------------------------------------\n\nfunction applyStaticProp(el: Element, key: string, value: unknown): void {\n if (value == null || value === false) return;\n\n if (key === 'class' || key === 'className') {\n (el as HTMLElement).className = value as string;\n return;\n }\n\n if (key === 'style') {\n if (typeof value === 'string') {\n (el as HTMLElement | SVGElement).style.cssText = value;\n } else if (value && typeof value === 'object') {\n Object.assign((el as HTMLElement | SVGElement).style, value);\n }\n return;\n }\n\n if (key === 'dangerouslySetInnerHTML') {\n if (typeof value !== 'object' || !('__html' in (value as any))) {\n throw new TypeError(\n 'dangerouslySetInnerHTML: expected { __html: string }, got ' + typeof value,\n );\n }\n const html = (value as { __html: string }).__html;\n if (typeof html !== 'string') {\n throw new TypeError(\n 'dangerouslySetInnerHTML: __html must be a string, got ' + typeof html,\n );\n }\n el.innerHTML = html;\n return;\n }\n\n // xlink: namespace\n if (key.charCodeAt(0) === 120 /* x */ && key.startsWith('xlink:')) {\n el.setAttributeNS(XLINK_NS, key, String(value));\n return;\n }\n\n // Boolean attrs\n if (BOOLEAN_ATTRS.has(key)) {\n if (value) el.setAttribute(key, '');\n return;\n }\n\n // Generic: true → empty string attribute, else stringified value\n if (value === true) {\n el.setAttribute(key, '');\n } else {\n el.setAttribute(key, String(value));\n }\n}\n\n/** Append a single child to a parent node. */\nfunction appendChild(parent: Node, child: unknown): void {\n // \"Active Suspension\" exploit: check the MOST COMMON type first.\n // In h('div', props, h('span'), h('button')), children are Nodes 70%+ of the time.\n // instanceof Node returns false in O(1) for primitives (null, string, number)\n // because V8 checks \"is this an object?\" first — no prototype chain walk.\n // This saves 3-5 wasted type comparisons vs the conventional null-first order.\n if (child instanceof Node) {\n parent.appendChild(child);\n return;\n }\n\n // \"Track Limits\": new Text() bypasses Document.createTextNode's validation.\n if (typeof child === 'string') {\n parent.appendChild(new Text(child));\n return;\n }\n\n // Null/false/true → skip (React-style conditional pattern)\n if (child == null || child === false || child === true) {\n return;\n }\n\n if (typeof child === 'number') {\n parent.appendChild(new Text(String(child)));\n return;\n }\n\n // Function child: reactive binding via signal getter.\n // The return value determines the binding type:\n // - Node (from h() call) → append/replace as element\n // - primitive (string/number/null) → bind as text\n if (typeof child === 'function') {\n if (parent instanceof Element) {\n (parent as any)[DYNAMIC_CHILD_SYM] = true;\n }\n let currentNode: Node | null = null;\n internalEffect(() => {\n const v = (child as () => unknown)();\n if (v instanceof Node) {\n // Function returned a DOM element — adopt or replace\n if (currentNode) {\n parent.replaceChild(v, currentNode);\n } else {\n parent.appendChild(v);\n }\n currentNode = v;\n } else {\n // Primitive value — bind as text\n const text = typeof v === 'symbol' ? String(v) : String(v ?? '');\n if (!currentNode) {\n currentNode = new Text(text);\n parent.appendChild(currentNode);\n } else if (currentNode.nodeType === 3) {\n (currentNode as Text).data = text;\n } else {\n const tn = new Text(text);\n parent.replaceChild(tn, currentNode);\n currentNode = tn;\n }\n }\n });\n return;\n }\n\n if (Array.isArray(child)) {\n for (const item of child) {\n appendChild(parent, item);\n }\n return;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Create a real DOM element with optional props and children.\n *\n * Supports both HTML and SVG elements. SVG tags are detected automatically\n * and created with the correct SVG namespace. Inside a `foreignObject`,\n * children switch back to the HTML namespace.\n *\n * Event listeners are attached with an AbortController signal so they can\n * be removed in bulk via `cleanup(el)`.\n *\n * Hyperscript-style API:\n * ```ts\n * h('div', { class: 'container', onClick: handleClick },\n * h('span', null, 'Hello'),\n * h('span', null, name), // name is a signal getter\n * )\n *\n * h('svg', { viewBox: '0 0 24 24', fill: 'none' },\n * h('path', { d: 'M12 2L2 22h20L12 2z', stroke: 'currentColor' }),\n * )\n * ```\n */\n// Overloads: function component, Fragment, string\nexport function h(tag: (props: Record<string, unknown>) => unknown, props?: Record<string, unknown> | null, ...children: unknown[]): Node;\nexport function h(tag: typeof Fragment, props?: null, ...children: unknown[]): DocumentFragment;\nexport function h(tag: string, props?: Record<string, unknown> | null, ...children: unknown[]): HTMLElement;\nexport function h(\n tag: string | typeof Fragment | ((props: Record<string, unknown>) => unknown),\n props?: Record<string, unknown> | null,\n ...children: unknown[]\n): HTMLElement | DocumentFragment {\n // Function component: call with merged props + children\n if (typeof tag === 'function' && tag !== Fragment) {\n const mergedProps = { ...(props ?? {}), children };\n return tag(mergedProps) as unknown as HTMLElement;\n }\n\n // Fragment: return DocumentFragment with children\n if (tag === Fragment) {\n const frag = document.createDocumentFragment();\n for (const child of children) {\n appendChild(frag, child);\n }\n return frag;\n }\n\n // After the Fragment guard above, tag is guaranteed to be a string\n const tagName = tag as string;\n\n if (hydrating) {\n return { type: 'element', tag: tagName, props: props ?? null, children } as unknown as HTMLElement;\n }\n\n // \"Flexible Wings\" exploit: for HTML elements, clone a pre-created prototype\n // instead of calling createElement. cloneNode(false) is a single C++ memcpy\n // that copies the element's internal state without parsing the tag string.\n // Skip the SVG Set lookup entirely when the tag is in the proto cache (hot path).\n let el: Element;\n if (ELEMENT_PROTOS && ELEMENT_PROTOS[tagName]) {\n el = ELEMENT_PROTOS[tagName]!.cloneNode(false) as HTMLElement;\n } else if (SVG_TAGS.has(tagName)) {\n el = document.createElementNS(SVG_NS, tagName);\n } else {\n el = getProto(tagName).cloneNode(false) as HTMLElement;\n }\n\n // \"Blown Diffuser\" exploit: split props into static and dynamic paths.\n // Static props (string/number/boolean literals) go through a zero-cache\n // fast path. Only dynamic props (function values) need the attribute cache\n // for diffing on re-runs. This avoids:\n // - Object.create(null) allocation for elements with only static props\n // - Cache read/write operations that always miss on first call\n // - getCache() indirection in every prop handler\n if (props) {\n let hasDynamic = false;\n for (const key in props) {\n if (key === 'ref') continue;\n const value = props[key];\n\n // Event handlers: no cache needed, direct binding\n if (key.charCodeAt(0) === 111 /* o */ && key.charCodeAt(1) === 110 /* n */ && key.length > 2) {\n handleEvent(el, key, value);\n continue;\n }\n\n // Dynamic prop (function value, not event): needs cache + effect\n if (typeof value === 'function') {\n if (!hasDynamic) {\n // Lazy-allocate cache only when first dynamic prop is found\n (el as any)[CACHE_SYM] = Object.create(null);\n hasDynamic = true;\n }\n applyProp(el, key, value);\n continue;\n }\n\n // Static prop: zero-cache fast path — direct DOM write\n applyStaticProp(el, key, value);\n }\n }\n\n // Append children — fast path for single string/number child avoids\n // Text node allocation + separate appendChild. el.textContent is a single\n // native C++ call that combines both operations.\n const childLen = children.length;\n if (childLen === 1) {\n const only = children[0];\n if (typeof only === 'string') {\n el.textContent = only;\n } else if (typeof only === 'number') {\n el.textContent = String(only);\n } else {\n appendChild(el, only);\n }\n } else if (childLen > 1) {\n for (const child of children) {\n appendChild(el, child);\n }\n }\n\n // Call ref after element is fully constructed\n if (props && typeof props['ref'] === 'function') {\n (props['ref'] as (el: Element) => void)(el);\n }\n\n return el as unknown as HTMLElement;\n}\n\n/**\n * Create a DocumentFragment from children.\n *\n * ```ts\n * fragment(\n * h('li', null, 'one'),\n * h('li', null, 'two'),\n * )\n * ```\n */\nexport function fragment(...children: unknown[]): DocumentFragment {\n const frag = document.createDocumentFragment();\n for (const child of children) {\n appendChild(frag, child);\n }\n return frag;\n}\n","/**\n * Forma DOM - Text\n *\n * Creates static or reactive Text nodes.\n * Zero dependencies -- native browser APIs only.\n */\n\nimport { internalEffect } from 'forma/reactive';\n\n/**\n * Create a Text node that is either static or reactively bound.\n *\n * - If `value` is a string, creates a plain Text node.\n * - If `value` is a function (signal getter), creates a Text node and sets up\n * an effect that auto-updates `textContent` whenever the signal changes.\n *\n * @returns The Text node.\n */\nexport function createText(value: string | (() => string)): Text {\n if (typeof value === 'function') {\n // \"Track Limits\": new Text() bypasses Document factory dispatch\n const node = new Text('');\n internalEffect(() => {\n // \"DAS\": CharacterData.data is the rawest text setter\n node.data = value();\n });\n return node;\n }\n return new Text(value);\n}\n","/**\n * Forma DOM - Mount\n *\n * Mounts a component function into a DOM container, returning an unmount handle.\n * Uses createRoot() for automatic effect disposal — no global state.\n *\n * When the container has `data-forma-ssr`, uses hydrateIsland() for zero-flash\n * descriptor-based hydration instead of tearing down and rebuilding the DOM.\n */\n\nimport { createRoot } from 'forma/reactive';\nimport { hydrateIsland } from './hydrate.js';\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Mount a component into a DOM container.\n *\n * All effects created during the component's render are tracked via\n * `createRoot()` and automatically disposed when unmount is called.\n *\n * When `data-forma-ssr` is present on the container, the component runs\n * inside `createRoot` in hydration mode — h() returns descriptors that are\n * walked against SSR DOM to attach handlers and reactive bindings.\n *\n * @param component A function returning an HTMLElement or DocumentFragment.\n * @param container An HTMLElement or a CSS selector string.\n * @returns An unmount function that removes the DOM and disposes all effects.\n *\n * ```ts\n * const unmount = mount(() => h('h1', null, 'Hello'), '#app');\n * // later…\n * unmount();\n * ```\n */\nexport function mount(\n component: () => HTMLElement | DocumentFragment,\n container: HTMLElement | string,\n): () => void {\n const target =\n typeof container === 'string'\n ? document.querySelector<HTMLElement>(container)\n : container;\n\n if (!target) {\n throw new Error(`mount: container not found — \"${container}\"`);\n }\n\n let disposeRoot!: () => void;\n\n if (target.hasAttribute('data-forma-ssr')) {\n // SSR content present — hydrate in-place using descriptor-based adoption.\n // The component MUST run inside createRoot so effects are tracked.\n createRoot((dispose) => {\n disposeRoot = dispose;\n hydrateIsland(component, target);\n });\n } else {\n // Normal mount — clear and append\n const dom = createRoot((dispose) => {\n disposeRoot = dispose;\n return component();\n });\n target.innerHTML = '';\n target.appendChild(dom);\n }\n\n // Return unmount function\n let unmounted = false;\n return () => {\n if (unmounted) return;\n unmounted = true;\n disposeRoot();\n target.innerHTML = '';\n };\n}\n","/**\n * Forma DOM - Switch (Multi-branch Conditional)\n *\n * Maps a reactive value to one of N render branches.\n * Caches previously rendered nodes for instant swap-back.\n *\n * Each cached branch gets its own reactive root (ownership scope) so that:\n * 1. Inner effects survive when the switch effect re-runs (alien-signals\n * would otherwise dispose child effects linked to the parent).\n * 2. Inner effects are explicitly disposed when the branch is evicted\n * from the cache or the switch itself is torn down.\n *\n * SolidJS equivalent: <Switch><Match when={}>\n */\n\nimport { internalEffect, untrack, createRoot } from 'forma/reactive';\n\nexport interface SwitchCase<T> {\n match: T;\n render: () => Node;\n}\n\n/** Cached branch: the rendered DOM node + a dispose function for its root. */\ninterface CachedBranch {\n node: Node;\n dispose: () => void;\n}\n\n/**\n * Multi-branch conditional rendering with node caching.\n *\n * ```ts\n * const [tab, setTab] = createSignal('home');\n * const fragment = createSwitch(tab, [\n * { match: 'home', render: () => h('div', null, 'Home page') },\n * { match: 'about', render: () => h('div', null, 'About page') },\n * { match: 'contact', render: () => h('div', null, 'Contact page') },\n * ], () => h('div', null, '404'));\n * ```\n *\n * Previously rendered branches are cached — switching back to a tab\n * re-inserts the cached node without re-rendering.\n */\nexport function createSwitch<T>(\n value: () => T,\n cases: SwitchCase<T>[],\n fallback?: () => Node,\n): DocumentFragment {\n const startMarker = document.createComment('forma-switch');\n const endMarker = document.createComment('/forma-switch');\n const fragment = document.createDocumentFragment();\n fragment.appendChild(startMarker);\n fragment.appendChild(endMarker);\n\n // Branch cache: value → { node, dispose }\n // Each branch has its own reactive root for explicit lifecycle management.\n const cache = new Map<T, CachedBranch>();\n let currentNode: Node | null = null;\n let currentMatch: T | typeof UNSET = UNSET;\n\n const switchDispose = internalEffect(() => {\n const val = value();\n if (val === currentMatch) return; // Same branch, skip\n\n const DEBUG = typeof (globalThis as any).__FORMA_DEBUG__ !== 'undefined';\n if (DEBUG) console.log('[forma:switch] transition', String(currentMatch), '→', String(val));\n\n currentMatch = val;\n\n const parent = startMarker.parentNode;\n if (!parent) {\n if (DEBUG) console.warn('[forma:switch] markers not in DOM yet, skipping');\n return;\n }\n\n // Remove current content between markers.\n // If currentNode was a DocumentFragment, its children transferred to the\n // DOM on insertion and the fragment is now detached (parentNode === null).\n // We must scoop the children BACK into the fragment so the cache stays\n // valid for re-insertion later.\n if (currentNode) {\n if (currentNode.parentNode === parent) {\n if (DEBUG) console.log('[forma:switch] removing single node');\n parent.removeChild(currentNode);\n } else if (currentNode.nodeType === 11 /* DOCUMENT_FRAGMENT_NODE */) {\n // Scoop DOM nodes back into the fragment for cache reuse\n if (DEBUG) console.log('[forma:switch] scooping nodes back into fragment');\n let scooped = 0;\n while (startMarker.nextSibling && startMarker.nextSibling !== endMarker) {\n currentNode.appendChild(startMarker.nextSibling);\n scooped++;\n }\n if (DEBUG) console.log('[forma:switch] scooped', scooped, 'nodes back into fragment');\n } else {\n // Other detached node — just clear between markers\n if (DEBUG) console.log('[forma:switch] clearing detached node between markers');\n while (startMarker.nextSibling && startMarker.nextSibling !== endMarker) {\n parent.removeChild(startMarker.nextSibling);\n }\n }\n }\n\n // Find matching case\n const matchedCase = cases.find(c => c.match === val);\n if (matchedCase) {\n let entry = cache.get(val);\n if (!entry) {\n // Render inside a createRoot so child effects are tracked for\n // disposal, and inside untrack so they are NOT linked to the\n // switch effect (alien-signals disposes child effects on parent\n // re-run, which would kill reactivity in cached branches).\n let branchDispose!: () => void;\n const node = createRoot((dispose) => {\n branchDispose = dispose;\n return untrack(() => matchedCase.render());\n });\n entry = { node, dispose: branchDispose };\n cache.set(val, entry);\n if (DEBUG) console.log('[forma:switch] rendered new branch for', String(val), '→', node.nodeName, 'type', node.nodeType);\n } else {\n if (DEBUG) console.log('[forma:switch] reusing cached branch for', String(val), '→', entry.node.nodeName, 'type', entry.node.nodeType, 'childNodes', entry.node.childNodes?.length);\n }\n currentNode = entry.node;\n } else {\n // Fallback — not cached, effects are owned by the switch effect\n // and correctly torn down on next re-run.\n currentNode = fallback?.() ?? null;\n if (DEBUG) console.log('[forma:switch] no match, using fallback');\n }\n\n if (currentNode) {\n parent.insertBefore(currentNode, endMarker);\n if (DEBUG) console.log('[forma:switch] inserted', currentNode.nodeName, 'before end marker');\n }\n });\n\n // Attach a cleanup marker so external disposal (via disposeComponent or\n // parent root teardown) can clean up all cached branches.\n (fragment as any).__switchDispose = () => {\n switchDispose();\n for (const entry of cache.values()) {\n entry.dispose();\n }\n cache.clear();\n };\n\n return fragment;\n}\n\n// Sentinel value for \"no match yet\"\nconst UNSET = Symbol('unset');\n","/**\n * Forma DOM - Portal\n *\n * Renders children into a different DOM container than the parent.\n * Useful for modals, tooltips, dropdowns that need to escape overflow.\n *\n * SolidJS equivalent: <Portal mount={}>\n */\n\nimport { createEffect } from 'forma/reactive';\n\n/**\n * Render content into an external DOM container.\n *\n * ```ts\n * const modal = createPortal(\n * () => h('div', { class: 'modal' }, 'Modal content'),\n * document.body,\n * );\n * ```\n *\n * Returns a comment node placeholder. The actual content is rendered\n * into the target container. Cleanup removes content from target.\n */\nexport function createPortal(\n children: () => Node,\n target?: Element | string,\n): Comment {\n const placeholder = document.createComment('forma-portal');\n\n const resolvedTarget = typeof target === 'string'\n ? document.querySelector(target)\n : (target ?? document.body);\n\n if (!resolvedTarget) {\n throw new Error(`createPortal: target not found: ${target}`);\n }\n\n let mountedNode: Node | null = null;\n const removeMountedNode = () => {\n if (mountedNode && mountedNode.parentNode === resolvedTarget) {\n resolvedTarget.removeChild(mountedNode);\n }\n mountedNode = null;\n };\n\n createEffect(() => {\n const node = children();\n\n // Remove previous\n removeMountedNode();\n\n mountedNode = node;\n resolvedTarget.appendChild(node);\n\n // Ensure portal content is removed when the owner root disposes.\n return () => {\n removeMountedNode();\n };\n });\n\n return placeholder;\n}\n","/**\n * Forma DOM - Error Boundary\n *\n * Catches errors during rendering and shows a fallback UI.\n * Provides a retry function to re-attempt the original render.\n *\n * SolidJS equivalent: <ErrorBoundary fallback={}>\n */\n\nimport { createSignal, internalEffect } from 'forma/reactive';\n\n/**\n * Wrap a render function with error recovery.\n *\n * ```ts\n * const fragment = createErrorBoundary(\n * () => h('div', null, riskyComponent()),\n * (error, retry) => h('div', { class: 'error' },\n * h('p', null, `Error: ${error.message}`),\n * h('button', { onClick: retry }, 'Retry'),\n * ),\n * );\n * ```\n *\n * If `tryFn` throws, `catchFn` is called with the error and a retry function.\n * Calling `retry()` re-runs `tryFn`.\n */\nexport function createErrorBoundary(\n tryFn: () => Node,\n catchFn: (error: Error, retry: () => void) => Node,\n): DocumentFragment {\n const startMarker = document.createComment('forma-error-boundary');\n const endMarker = document.createComment('/forma-error-boundary');\n const fragment = document.createDocumentFragment();\n fragment.appendChild(startMarker);\n fragment.appendChild(endMarker);\n\n const [retryCount, setRetryCount] = createSignal(0);\n let currentNode: Node | null = null;\n\n internalEffect(() => {\n // Subscribe to retryCount so retry() triggers re-run\n retryCount();\n\n const parent = startMarker.parentNode;\n if (!parent) return;\n\n // Remove current\n if (currentNode && currentNode.parentNode === parent) {\n parent.removeChild(currentNode);\n }\n\n try {\n currentNode = tryFn();\n } catch (e) {\n const error = e instanceof Error ? e : new Error(String(e));\n const retry = () => setRetryCount(c => c + 1);\n currentNode = catchFn(error, retry);\n }\n\n if (currentNode) {\n parent.insertBefore(currentNode, endMarker);\n }\n });\n\n return fragment;\n}\n","/**\n * Forma DOM - Suspense\n *\n * A Suspense boundary that shows fallback content while async resources\n * inside the children function are loading. Uses comment markers\n * (like createShow, createList) for zero-wrapper rendering.\n *\n * When all resources resolve, the fallback is swapped for the real content.\n * If a resource errors, the fallback remains (pair with createErrorBoundary\n * for error handling).\n *\n * SolidJS equivalent: <Suspense fallback={}>\n */\n\nimport { createSignal, internalEffect } from 'forma/reactive';\nimport {\n type SuspenseContext,\n pushSuspenseContext,\n popSuspenseContext,\n} from 'forma/reactive/suspense-context';\n\n// Re-export context utilities so consumers can import from dom/suspense\nexport { getSuspenseContext, pushSuspenseContext, popSuspenseContext } from 'forma/reactive/suspense-context';\nexport type { SuspenseContext } from 'forma/reactive/suspense-context';\n\n// ---------------------------------------------------------------------------\n// createSuspense\n// ---------------------------------------------------------------------------\n\n/**\n * Create a Suspense boundary that shows fallback content while async resources\n * inside the children function are loading.\n *\n * Uses comment markers: `<!--forma-suspense-->` / `<!--/forma-suspense-->`\n *\n * When all resources resolve, the fallback is swapped for the real content.\n * If a resource errors, the fallback remains (pair with createErrorBoundary\n * for errors).\n *\n * ```ts\n * const frag = createSuspense(\n * () => h('div', null, 'Loading...'),\n * () => {\n * const data = createResource(source, fetcher);\n * return h('div', null, () => data()?.name ?? '');\n * },\n * );\n * container.appendChild(frag);\n * ```\n */\nexport function createSuspense(\n fallback: () => Node,\n children: () => Node,\n): DocumentFragment {\n const startMarker = document.createComment('forma-suspense');\n const endMarker = document.createComment('/forma-suspense');\n const fragment = document.createDocumentFragment();\n fragment.appendChild(startMarker);\n fragment.appendChild(endMarker);\n\n const [pending, setPending] = createSignal(0);\n let currentNode: Node | null = null;\n let resolvedNode: Node | null = null;\n let fallbackNode: Node | null = null;\n\n const ctx: SuspenseContext = {\n increment() { setPending(p => p + 1); },\n decrement() { setPending(p => Math.max(0, p - 1)); },\n };\n\n // Render children within the Suspense context so that any createResource\n // calls inside will register with this boundary.\n pushSuspenseContext(ctx);\n try {\n resolvedNode = children();\n } finally {\n popSuspenseContext();\n }\n\n // Reactively swap between fallback and children based on pending count\n internalEffect(() => {\n const parent = startMarker.parentNode;\n if (!parent) return;\n\n const isPending = pending() > 0;\n const newNode = isPending ? (fallbackNode ??= fallback()) : resolvedNode;\n\n if (newNode === currentNode) return;\n\n // Remove current node\n if (currentNode && currentNode.parentNode === parent) {\n parent.removeChild(currentNode);\n }\n\n // Insert new node\n if (newNode) {\n parent.insertBefore(newNode, endMarker);\n }\n\n currentNode = newNode;\n });\n\n return fragment;\n}\n","/**\n * Forma DOM - Island Activation\n *\n * Discovers SSR-rendered islands via [data-forma-island] attributes,\n * loads props (inline or script_tag), and hydrates each island inside\n * an independent createRoot scope with try/catch error isolation.\n */\n\nimport { createRoot, __DEV__ } from 'forma/reactive';\nimport { hydrateIsland } from './hydrate.js';\n\n/**\n * Function that hydrates an island.\n *\n * @param el The root element of the island (`[data-forma-island]`).\n * Useful for layout measurement, focus management, CSS class\n * toggling, third-party library init, or reading extra `data-*`\n * attributes from the server-rendered shell.\n * @param props Parsed props from `data-forma-props` (inline or script block),\n * or `null` if no props were provided.\n * @returns A component tree (from `h()` calls) for descriptor-based\n * hydration, or `undefined` for imperative islands that set up\n * their own effects.\n */\nexport type IslandHydrateFn = (el: HTMLElement, props: Record<string, unknown> | null) => unknown;\n\nconst FORBIDDEN_PROP_KEYS = new Set(['__proto__', 'constructor', 'prototype']);\n\nfunction sanitizeProps(obj: Record<string, unknown>): Record<string, unknown> {\n for (const key of FORBIDDEN_PROP_KEYS) {\n if (key in obj) delete (obj as any)[key];\n }\n return obj;\n}\n\n/**\n * Load props for an island from either inline attribute or shared script block.\n */\nfunction loadIslandProps(\n root: HTMLElement,\n id: number,\n sharedProps: Record<string, unknown> | null,\n): Record<string, unknown> | null {\n // Mode 1: Inline (small props, < 1KB)\n const inline = root.getAttribute('data-forma-props');\n if (inline) {\n return sanitizeProps(JSON.parse(inline));\n }\n\n // Mode 2: Script tag (1KB–50KB, pre-parsed)\n if (sharedProps && String(id) in sharedProps) {\n return sanitizeProps((sharedProps as any)[String(id)] as Record<string, unknown>);\n }\n\n // No props — island creates its own state\n return null;\n}\n\n/**\n * Discover and activate all SSR-rendered islands on the page.\n *\n * Each island is activated inside its own createRoot scope with try/catch\n * isolation — a broken island never takes down its siblings.\n *\n * @param registry Map of component names to hydration functions.\n */\nexport function activateIslands(registry: Record<string, IslandHydrateFn>): void {\n // Parse shared props once before the loop\n const scriptBlock = document.getElementById('__forma_islands');\n const sharedProps: Record<string, unknown> | null =\n scriptBlock ? JSON.parse(scriptBlock.textContent!) : null;\n\n const islands = document.querySelectorAll<HTMLElement>('[data-forma-island]');\n\n for (const root of islands) {\n const id = parseInt(root.getAttribute('data-forma-island')!, 10);\n const componentName = root.getAttribute('data-forma-component')!;\n const hydrateFn = registry[componentName];\n\n if (!hydrateFn) {\n if (__DEV__) console.warn(`[forma] No hydrate function for island \"${componentName}\" (id=${id})`);\n root.setAttribute('data-forma-status', 'error');\n continue;\n }\n\n const trigger = root.getAttribute('data-forma-hydrate') || 'load';\n\n if (trigger === 'visible') {\n // Defer hydration until island enters the viewport\n const observer = new IntersectionObserver(\n (entries) => {\n for (const entry of entries) {\n if (!entry.isIntersecting) continue;\n observer.disconnect();\n hydrateIslandRoot(root, id, componentName, hydrateFn, sharedProps);\n }\n },\n { rootMargin: '200px' },\n );\n observer.observe(root);\n } else if (trigger === 'idle') {\n const hydrate = () => hydrateIslandRoot(root, id, componentName, hydrateFn, sharedProps);\n if (typeof requestIdleCallback === 'function') {\n requestIdleCallback(hydrate);\n } else {\n setTimeout(hydrate, 200);\n }\n } else if (trigger === 'interaction') {\n const hydrate = () => {\n root.removeEventListener('pointerdown', hydrate, true);\n root.removeEventListener('focusin', hydrate, true);\n hydrateIslandRoot(root, id, componentName, hydrateFn, sharedProps);\n };\n root.addEventListener('pointerdown', hydrate, { capture: true, once: true });\n root.addEventListener('focusin', hydrate, { capture: true, once: true });\n } else {\n // load (default) — hydrate immediately\n hydrateIslandRoot(root, id, componentName, hydrateFn, sharedProps);\n }\n }\n}\n\n/**\n * Dispose a single island, tearing down its reactive root and all effects.\n *\n * Safe to call multiple times (idempotent). Sets `data-forma-status` to\n * `\"disposed\"` so the island can be distinguished from active/error states.\n */\nexport function deactivateIsland(el: HTMLElement): void {\n const dispose = (el as any).__formaDispose;\n if (typeof dispose === 'function') {\n dispose();\n delete (el as any).__formaDispose;\n el.setAttribute('data-forma-status', 'disposed');\n }\n}\n\n/**\n * Dispose ALL active islands under a root element (or the whole document).\n *\n * Use this when swapping module content — e.g., replacing the contents of\n * a `<forma-stage>` Shadow DOM during AI generation. Prevents leaked effects\n * and event listeners from accumulating across swaps.\n */\nexport function deactivateAllIslands(root: Element | Document = document): void {\n const islands = root.querySelectorAll<HTMLElement>('[data-forma-status=\"active\"]');\n for (const island of islands) {\n deactivateIsland(island);\n }\n}\n\n/** Hydrate a single island root with error isolation. */\nfunction hydrateIslandRoot(\n root: HTMLElement,\n id: number,\n componentName: string,\n hydrateFn: IslandHydrateFn,\n sharedProps: Record<string, unknown> | null,\n): void {\n try {\n const props = loadIslandProps(root, id, sharedProps);\n root.setAttribute('data-forma-status', 'hydrating');\n\n // hydrateIsland may replace the shell element with the component's own\n // root element (CSR fallback for empty islands). Track the active root.\n let activeRoot: Element = root;\n createRoot((dispose) => {\n activeRoot = hydrateIsland(() => hydrateFn(root, props), root);\n (activeRoot as any).__formaDispose = dispose;\n });\n\n activeRoot.setAttribute('data-forma-status', 'active');\n } catch (err) {\n if (__DEV__) console.error(`[forma] Island \"${componentName}\" (id=${id}) failed:`, err);\n root.setAttribute('data-forma-status', 'error');\n }\n}\n","/**\n * Forma Component - Define\n *\n * Component definition system where the setup function runs ONCE.\n * Reactivity comes from signals, not re-rendering.\n * Backed by alien-signals via forma/reactive.\n */\n\nimport { reportError } from '../reactive/dev.js';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport type CleanupFn = () => void;\nexport type SetupFn = () => HTMLElement | DocumentFragment;\n\nexport interface ComponentDef {\n setup: SetupFn;\n name?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Lifecycle context stack\n// ---------------------------------------------------------------------------\n\ninterface LifecycleContext {\n /** Dispose functions for all effects created during setup. */\n disposers: (() => void)[];\n /** Callbacks registered via onMount(). */\n mountCallbacks: (() => void | CleanupFn)[];\n /** Callbacks registered via onUnmount(). */\n unmountCallbacks: (() => void)[];\n}\n\nlet currentLifecycleContext: LifecycleContext | null = null;\nconst lifecycleStack: (LifecycleContext | null)[] = [];\n\nfunction pushLifecycleContext(ctx: LifecycleContext): void {\n lifecycleStack.push(currentLifecycleContext);\n currentLifecycleContext = ctx;\n}\n\nfunction popLifecycleContext(): void {\n currentLifecycleContext = lifecycleStack.pop() ?? null;\n}\n\n// ---------------------------------------------------------------------------\n// Public API - Lifecycle hooks\n// ---------------------------------------------------------------------------\n\n/**\n * Register a callback that runs after the component's setup completes.\n * If the callback returns a function, that function is called on unmount.\n * Must be called inside a setup function.\n */\nexport function onMount(fn: () => void | CleanupFn): void {\n if (currentLifecycleContext === null) {\n throw new Error('onMount() must be called inside a component setup function');\n }\n currentLifecycleContext.mountCallbacks.push(fn);\n}\n\n/**\n * Register a callback that runs when the component is disposed.\n * Must be called inside a setup function.\n */\nexport function onUnmount(fn: () => void): void {\n if (currentLifecycleContext === null) {\n throw new Error('onUnmount() must be called inside a component setup function');\n }\n currentLifecycleContext.unmountCallbacks.push(fn);\n}\n\n// ---------------------------------------------------------------------------\n// Internal: symbol for attaching dispose to DOM nodes\n// ---------------------------------------------------------------------------\n\nconst DISPOSE_KEY = Symbol('forma:component:dispose');\n\ninterface DisposableNode {\n [DISPOSE_KEY]?: () => void;\n}\n\n// ---------------------------------------------------------------------------\n// Public API - defineComponent\n// ---------------------------------------------------------------------------\n\n/**\n * Define a component from a setup function or definition object.\n * Returns a factory function that, when called, produces a DOM element\n * with attached lifecycle and disposal logic.\n *\n * The setup function runs ONCE per factory call. Reactivity is driven\n * by signals, not by re-running setup.\n */\nexport function defineComponent(\n setupOrDef: SetupFn | ComponentDef,\n): () => HTMLElement | DocumentFragment {\n const setup: SetupFn =\n typeof setupOrDef === 'function' ? setupOrDef : setupOrDef.setup;\n const name: string | undefined =\n typeof setupOrDef === 'function' ? undefined : setupOrDef.name;\n\n return function componentFactory(): HTMLElement | DocumentFragment {\n // Create a fresh lifecycle context for this component instance\n const ctx: LifecycleContext = {\n disposers: [],\n mountCallbacks: [],\n unmountCallbacks: [],\n };\n\n // Push lifecycle context so onMount/onUnmount calls register here\n pushLifecycleContext(ctx);\n\n let dom: HTMLElement | DocumentFragment;\n try {\n dom = setup();\n } finally {\n popLifecycleContext();\n }\n\n // Build the dispose function that tears down the entire component\n const dispose = (): void => {\n // Run onUnmount callbacks\n for (const cb of ctx.unmountCallbacks) {\n try {\n cb();\n } catch (e) {\n reportError(e, 'onUnmount');\n }\n }\n\n // Dispose all effects\n for (const d of ctx.disposers) {\n try {\n d();\n } catch (e) {\n reportError(e, 'component disposer');\n }\n }\n\n // Clean up\n ctx.disposers.length = 0;\n ctx.mountCallbacks.length = 0;\n ctx.unmountCallbacks.length = 0;\n };\n\n // Attach dispose to the DOM node so callers can tear it down\n (dom as unknown as DisposableNode)[DISPOSE_KEY] = dispose;\n\n // Run mount callbacks (synchronously, after setup completes)\n // If a mount callback returns a cleanup, register it as an unmount callback\n for (const cb of ctx.mountCallbacks) {\n try {\n const cleanup = cb();\n if (typeof cleanup === 'function') {\n ctx.unmountCallbacks.push(cleanup);\n }\n } catch (e) {\n reportError(e, 'onMount');\n }\n }\n\n return dom;\n };\n}\n\n/**\n * Dispose a component that was created via defineComponent.\n * This runs all onUnmount callbacks and disposes all tracked effects.\n */\nexport function disposeComponent(dom: HTMLElement | DocumentFragment): void {\n const disposable = dom as unknown as DisposableNode;\n if (typeof disposable[DISPOSE_KEY] === 'function') {\n disposable[DISPOSE_KEY]();\n delete disposable[DISPOSE_KEY];\n }\n}\n\n/**\n * Track an effect disposal within the current component's lifecycle.\n * Call this inside a setup function to ensure effects are cleaned up\n * when the component is disposed.\n */\nexport function trackDisposer(dispose: () => void): void {\n if (currentLifecycleContext !== null) {\n currentLifecycleContext.disposers.push(dispose);\n }\n}\n","/**\n * Forma Component - Context\n *\n * Dependency injection via stack-based context.\n * Simpler than React's Provider component tree: provide() pushes a value,\n * inject() reads the top, component teardown pops automatically.\n * Zero dependencies -- native browser APIs only.\n */\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface Context<T> {\n /** Unique identifier for this context. */\n readonly id: symbol;\n /** Value returned when no provider is active. */\n readonly defaultValue: T;\n}\n\n// ---------------------------------------------------------------------------\n// Internal storage\n// ---------------------------------------------------------------------------\n\n/**\n * Per-context value stacks.\n * Each context id maps to a stack of provided values.\n * The top of the stack is the \"current\" value.\n */\nconst contextStacks = new Map<symbol, unknown[]>();\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Create a new context with a default value.\n *\n * ```ts\n * const ThemeCtx = createContext('light');\n * ```\n */\nexport function createContext<T>(defaultValue: T): Context<T> {\n return {\n id: Symbol('forma:context'),\n defaultValue,\n };\n}\n\n/**\n * Provide a value for a context.\n * The value is pushed onto the context's stack and will be returned by\n * inject() until it is removed via unprovide() or overridden by a nested provide().\n *\n * ```ts\n * provide(ThemeCtx, 'dark');\n * ```\n */\nexport function provide<T>(ctx: Context<T>, value: T): void {\n let stack = contextStacks.get(ctx.id);\n if (stack === undefined) {\n stack = [];\n contextStacks.set(ctx.id, stack);\n }\n stack.push(value);\n}\n\n/**\n * Read the current value of a context.\n * Returns the most recently provided value, or the default if none was provided.\n *\n * ```ts\n * const theme = inject(ThemeCtx); // 'dark' if provided, else 'light'\n * ```\n */\nexport function inject<T>(ctx: Context<T>): T {\n const stack = contextStacks.get(ctx.id);\n if (stack === undefined || stack.length === 0) {\n return ctx.defaultValue;\n }\n return stack[stack.length - 1] as T;\n}\n\n/**\n * Remove the most recent provided value for a context.\n * Used during component teardown to restore the previous scope.\n *\n * ```ts\n * unprovide(ThemeCtx);\n * ```\n */\nexport function unprovide<T>(ctx: Context<T>): void {\n const stack = contextStacks.get(ctx.id);\n if (stack !== undefined && stack.length > 0) {\n stack.pop();\n // Clean up empty stacks to avoid memory leaks\n if (stack.length === 0) {\n contextStacks.delete(ctx.id);\n }\n }\n}\n","/**\n * Forma State - Store\n *\n * Deep reactive store with path-based signal granularity.\n * Every property path (e.g. `user.name`, `items.0.done`) gets its own signal,\n * so only effects that read a specific path are notified when it changes.\n *\n * Inspired by SolidJS's createStore and Vue's reactive(), with:\n * - Lazy proxy wrapping (child objects proxied on first access)\n * - Structural sharing (replacing an object invalidates child signals)\n * - Array mutation batching (push/pop/splice/sort etc. batch their signals)\n *\n * Backed by alien-signals via forma/reactive.\n */\n\nimport { createSignal, batch, untrack } from 'forma/reactive';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ntype SignalPair = [get: () => unknown, set: (v: unknown) => void];\n\nexport type StoreSetter<T extends object> = (\n partial: Partial<T> | ((prev: T) => Partial<T>),\n) => void;\n\n// ---------------------------------------------------------------------------\n// Symbols\n// ---------------------------------------------------------------------------\n\n/** Access the underlying raw (unproxied) object from a store proxy. */\nconst RAW = Symbol('forma-raw');\n\n/** Marker: true on every store proxy so we can detect them. */\nconst PROXY = Symbol('forma-proxy');\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nconst ARRAY_MUTATORS = new Set([\n 'push',\n 'pop',\n 'shift',\n 'unshift',\n 'splice',\n 'sort',\n 'reverse',\n 'fill',\n 'copyWithin',\n]);\n\nfunction isPlainObject(v: unknown): v is Record<string, unknown> {\n if (v == null || typeof v !== 'object') return false;\n const proto = Object.getPrototypeOf(v);\n return proto === Object.prototype || proto === null || Array.isArray(v);\n}\n\nfunction shouldWrap(v: unknown): v is object {\n if (v == null || typeof v !== 'object') return false;\n // Don't wrap special built-ins (Date, RegExp, Map, Set, etc.)\n if (v instanceof Date || v instanceof RegExp || v instanceof Map ||\n v instanceof Set || v instanceof WeakMap || v instanceof WeakSet ||\n v instanceof Error || v instanceof Promise) {\n return false;\n }\n // Already a store proxy — no double wrapping\n if ((v as any)[PROXY]) return false;\n return true;\n}\n\n// ---------------------------------------------------------------------------\n// Deep-clone helper (used for functional setter snapshots)\n// ---------------------------------------------------------------------------\n\nfunction deepClone(obj: unknown, seen?: WeakSet<object>): unknown {\n if (obj === null || typeof obj !== 'object') return obj;\n if (!seen) seen = new WeakSet();\n if (seen.has(obj as object)) return obj; // circular — return ref as-is\n seen.add(obj as object);\n if (Array.isArray(obj)) return obj.map(item => deepClone(item, seen));\n const out: Record<string, unknown> = {};\n for (const key of Object.keys(obj as Record<string, unknown>)) {\n out[key] = deepClone((obj as any)[key], seen);\n }\n return out;\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Create a deep reactive store.\n *\n * Returns a tuple of `[getter proxy, setter function]`.\n * The getter proxy tracks reads at every property path via dedicated signals.\n * Setting a property (either via `setState()` or direct mutation like\n * `state.user.name = 'Bob'`) only notifies effects that actually read that\n * specific path.\n *\n * ```ts\n * const [state, setState] = createStore({\n * count: 0,\n * user: { name: 'Alice', age: 30 },\n * items: [{ text: 'Buy milk', done: false }],\n * });\n *\n * // Fine-grained reads\n * state.user.name; // tracked at path \"user.name\"\n * state.items[0].done; // tracked at path \"items.0.done\"\n *\n * // Setter API (batched)\n * setState({ count: 1 });\n * setState(prev => ({ count: prev.count + 1 }));\n *\n * // Direct mutation (via Proxy set trap)\n * state.user.name = 'Bob'; // only \"user.name\" subscribers notified\n * state.items[0].done = true;\n *\n * // Array mutations\n * state.items.push({ text: 'Walk dog', done: false });\n * ```\n *\n * **Limitation:** `Object.keys(state)`, `for...in`, and spread (`{...state}`)\n * are NOT reactive. Adding or removing a property will not trigger effects\n * that iterated over keys. Use signals or explicit arrays for collections\n * that need to react to membership changes.\n */\nexport function createStore<T extends object>(\n initial: T,\n): [get: T, set: StoreSetter<T>] {\n // -------------------------------------------------------------------------\n // Signal-per-path map\n // -------------------------------------------------------------------------\n\n /** Map of dot-separated paths -> signal pairs. */\n const signals = new Map<string, SignalPair>();\n\n /** Parent path -> set of direct child paths for O(1) child invalidation. */\n const children = new Map<string, Set<string>>();\n\n /**\n * Register a signal path with its parent in the adjacency map.\n * This allows walking the tree instead of scanning all signals.\n */\n function registerChild(path: string): void {\n const lastDot = path.lastIndexOf('.');\n if (lastDot === -1) return; // root-level, no parent\n const parentPath = path.substring(0, lastDot);\n let set = children.get(parentPath);\n if (!set) { set = new Set(); children.set(parentPath, set); }\n set.add(path);\n }\n\n /**\n * Get or create the signal for a given path.\n * When creating, seeds with `initialValue`.\n */\n function getSignal(path: string, initialValue?: unknown): SignalPair {\n let pair = signals.get(path);\n if (!pair) {\n pair = createSignal<unknown>(initialValue) as SignalPair;\n signals.set(path, pair);\n registerChild(path);\n }\n return pair;\n }\n\n // -------------------------------------------------------------------------\n // Proxy cache (raw object -> proxy)\n // -------------------------------------------------------------------------\n\n /**\n * WeakMap so proxies for child objects are reused as long as the raw object\n * is alive. When an object is replaced, the old entry is GC'd naturally.\n */\n const proxyCache = new WeakMap<object, object>();\n\n // -------------------------------------------------------------------------\n // Invalidation\n // -------------------------------------------------------------------------\n\n /**\n * Recursively delete all child signals using the adjacency map.\n * Called when an entire sub-tree is replaced so stale signals are not reused.\n * O(k) where k = number of descendant signals, instead of O(n) over all signals.\n */\n function invalidateChildren(parentPath: string): void {\n const childSet = children.get(parentPath);\n if (!childSet) return;\n for (const childPath of childSet) {\n // Recursively invalidate grandchildren first\n invalidateChildren(childPath);\n // Remove the signal itself\n signals.delete(childPath);\n // Clean up this child's entry in the adjacency map\n children.delete(childPath);\n }\n // Clear the parent's children set (all children have been removed)\n childSet.clear();\n }\n\n // -------------------------------------------------------------------------\n // Proxy factory (lazy, recursive)\n // -------------------------------------------------------------------------\n\n function wrap(raw: object, basePath: string): object {\n // Primitives / non-wrappable values pass through\n if (!shouldWrap(raw)) return raw;\n\n // Return cached proxy if we already have one for this raw object\n const cached = proxyCache.get(raw);\n if (cached) return cached;\n\n const isArr = Array.isArray(raw);\n // Pre-compute the path prefix to avoid repeated string concatenation in hot paths\n const basePrefix = basePath ? basePath + '.' : '';\n\n // Inline cache: skip Map lookup when the same key is accessed repeatedly\n // (very common in render loops and effects that read the same property)\n let lastKey: string = '';\n let lastSignal: SignalPair | undefined;\n\n const proxy: object = new Proxy(raw, {\n // -------------------------------------------------------------------\n // GET\n // -------------------------------------------------------------------\n get(target: any, prop: PropertyKey, receiver: unknown): unknown {\n // Escape hatches\n if (prop === RAW) return target;\n if (prop === PROXY) return true;\n\n // Symbols pass through (Symbol.iterator, Symbol.toPrimitive, etc.)\n if (typeof prop === 'symbol') {\n return Reflect.get(target, prop, receiver);\n }\n\n const key = String(prop);\n // Cache-friendly path construction: avoid template literals in hot path\n const childPath = basePrefix + key;\n\n // ------------------------------------------------------------------\n // Array mutator methods — wrap to batch signal updates\n // ------------------------------------------------------------------\n if (isArr && ARRAY_MUTATORS.has(key)) {\n return (...args: unknown[]) => {\n let result: unknown;\n batch(() => {\n // Unwrap proxy arguments (e.g. pushing a store proxy)\n const rawArgs = args.map((a) =>\n a != null && typeof a === 'object' && (a as any)[RAW]\n ? (a as any)[RAW]\n : a,\n );\n result = (target as any)[key].apply(target, rawArgs);\n\n // Invalidate all child paths so they recreate from the\n // mutated raw array on next access.\n invalidateChildren(basePath);\n\n // Notify the length signal\n const [, setLen] = getSignal(\n basePrefix + 'length',\n (target as unknown[]).length,\n );\n setLen((target as unknown[]).length);\n });\n return result;\n };\n }\n\n // ------------------------------------------------------------------\n // Array `length` — special-case so it's always tracked\n // ------------------------------------------------------------------\n if (isArr && key === 'length') {\n const [getter] = getSignal(childPath, target.length);\n getter(); // subscribe\n return target.length;\n }\n\n // ------------------------------------------------------------------\n // Regular property access\n // ------------------------------------------------------------------\n const value = Reflect.get(target, prop);\n\n // Inline cache: if same key as last access, skip Map lookup\n let pair: SignalPair;\n if (key === lastKey && lastSignal) {\n pair = lastSignal;\n } else {\n pair = getSignal(childPath, value);\n lastKey = key;\n lastSignal = pair;\n }\n\n pair[0](); // subscribe to this path\n\n // Lazily wrap child objects/arrays\n if (shouldWrap(value)) {\n return wrap(value, childPath);\n }\n\n return value;\n },\n\n // -------------------------------------------------------------------\n // SET\n // -------------------------------------------------------------------\n set(target: any, prop: PropertyKey, value: unknown): boolean {\n if (typeof prop === 'symbol') {\n return Reflect.set(target, prop, value);\n }\n\n const key = String(prop);\n const childPath = basePrefix + key;\n\n // Unwrap if the value being set is itself a proxy\n const rawValue =\n value != null && typeof value === 'object' && (value as any)[RAW]\n ? (value as any)[RAW]\n : value;\n\n // Write to the underlying object\n Reflect.set(target, prop, rawValue);\n\n // If we're replacing with an object, invalidate all child signals\n // and evict the old proxy so sub-paths are recreated on next access.\n if (rawValue != null && typeof rawValue === 'object') {\n invalidateChildren(childPath);\n // Remove cached proxy for the old value so a fresh one is created\n // on the next access.\n }\n\n // Update the length signal when setting indexed array elements\n if (isArr && key !== 'length') {\n const lengthPath = basePrefix + 'length';\n const lenPair = signals.get(lengthPath);\n if (lenPair) {\n lenPair[1](target.length);\n }\n }\n\n // Notify (or create) the signal for this path\n const [, setter] = getSignal(childPath, rawValue);\n setter(rawValue);\n\n return true;\n },\n\n // -------------------------------------------------------------------\n // HAS — track membership checks\n // -------------------------------------------------------------------\n has(target: any, prop: PropertyKey): boolean {\n if (typeof prop === 'symbol') {\n return Reflect.has(target, prop);\n }\n const key = String(prop);\n const childPath = basePrefix + key;\n // Subscribe so that `'x' in state` is tracked\n const [getter] = getSignal(childPath, Reflect.get(target, prop));\n getter();\n return Reflect.has(target, prop);\n },\n\n // -------------------------------------------------------------------\n // OWNKEYS — return keys from the raw target\n // -------------------------------------------------------------------\n ownKeys(target: any): (string | symbol)[] {\n return Reflect.ownKeys(target);\n },\n\n // -------------------------------------------------------------------\n // GETOWNPROPERTYDESCRIPTOR — needed for Object.keys / spread / ...\n // -------------------------------------------------------------------\n getOwnPropertyDescriptor(target: any, prop: PropertyKey) {\n return Object.getOwnPropertyDescriptor(target, prop);\n },\n\n // -------------------------------------------------------------------\n // DELETEPROPERTY — clean up signals when a key is removed\n // -------------------------------------------------------------------\n deleteProperty(target: any, prop: PropertyKey): boolean {\n if (typeof prop === 'symbol') {\n return Reflect.deleteProperty(target, prop);\n }\n\n const key = String(prop);\n const childPath = basePrefix + key;\n\n const result = Reflect.deleteProperty(target, prop);\n\n // Clean up the signal for this path and all children via adjacency map\n invalidateChildren(childPath);\n signals.delete(childPath);\n\n // Remove from parent's children set in the adjacency map\n const parentPath = basePath;\n if (parentPath !== undefined) {\n const parentSet = children.get(parentPath);\n if (parentSet) {\n parentSet.delete(childPath);\n if (parentSet.size === 0) children.delete(parentPath);\n }\n }\n // Clean up the deleted path's own children entry\n children.delete(childPath);\n\n return result;\n },\n });\n\n proxyCache.set(raw, proxy);\n return proxy;\n }\n\n // -------------------------------------------------------------------------\n // Root proxy\n // -------------------------------------------------------------------------\n\n const rootProxy = wrap(initial, '') as T;\n\n // -------------------------------------------------------------------------\n // Snapshot (for functional setter)\n // -------------------------------------------------------------------------\n\n /**\n * Produce a plain-object snapshot of the store's current state.\n * Reads are untracked so calling `setState(prev => ...)` inside an effect\n * does not create additional subscriptions.\n */\n function getCurrentSnapshot(): T {\n return untrack(() => deepClone(initial) as T);\n }\n\n // -------------------------------------------------------------------------\n // Setter\n // -------------------------------------------------------------------------\n\n const setter: StoreSetter<T> = (\n partial: Partial<T> | ((prev: T) => Partial<T>),\n ) => {\n // Resolve functional updates by snapshotting current state\n const updates: Partial<T> =\n typeof partial === 'function' ? partial(getCurrentSnapshot()) : partial;\n\n // Batch all top-level key writes so effects run only once\n batch(() => {\n for (const key of Object.keys(updates) as (keyof T & string)[]) {\n (rootProxy as Record<string, unknown>)[key] = (updates as Record<string, unknown>)[key];\n }\n });\n };\n\n return [rootProxy, setter];\n}\n","/**\n * Forma State - History\n *\n * Undo/redo for any signal. Tracks changes and maintains undo/redo stacks\n * with reactive canUndo/canRedo signals.\n * Zero dependencies -- native browser APIs only.\n */\n\nimport { createSignal, internalEffect, batch } from 'forma/reactive';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface HistoryControls<T> {\n /** Undo the last change, restoring the previous value. */\n undo: () => void;\n /** Redo the last undone change. */\n redo: () => void;\n /** Reactive getter: true if undo is available. */\n canUndo: () => boolean;\n /** Reactive getter: true if redo is available. */\n canRedo: () => boolean;\n /** Reactive getter: the full history stack (past + current + future). */\n history: () => T[];\n /** Reactive getter: current position in the history stack (0-based). */\n cursor: () => number;\n /** Clear all history, keeping only the current value. */\n clear: () => void;\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Create undo/redo history tracking for a signal.\n *\n * ```ts\n * const [count, setCount] = createSignal(0);\n * const h = createHistory([count, setCount], { maxLength: 50 });\n *\n * setCount(1);\n * setCount(2);\n * h.undo(); // count() === 1\n * h.redo(); // count() === 2\n * h.canUndo(); // true (reactive)\n * ```\n */\nexport function createHistory<T>(\n source: [get: () => T, set: (v: T) => void],\n options?: { maxLength?: number },\n): HistoryControls<T> {\n const [sourceGet, sourceSet] = source;\n const maxLength = options?.maxLength ?? 100;\n\n // ---------- Internal mutable state (not signals) ----------\n // We use plain arrays/numbers to avoid creating signal dependencies\n // inside the source-tracking effect, which would cause re-entrance issues.\n let _stack: T[] = [sourceGet()];\n let _cursor = 0;\n\n // ---------- Reactive output signals ----------\n // These are signals that external consumers can subscribe to.\n // We update them explicitly after every mutation.\n const [stackSignal, setStackSignal] = createSignal<T[]>([..._stack]);\n const [cursorSignal, setCursorSignal] = createSignal(_cursor);\n // Separate signal for stack length so canRedo only depends on numeric\n // signals and doesn't re-fire when array reference changes but length stays.\n const [stackLenSignal, setStackLenSignal] = createSignal(_stack.length);\n\n /** Sync the reactive output signals with internal mutable state. */\n function syncSignals(): void {\n batch(() => {\n setStackSignal([..._stack]);\n setCursorSignal(_cursor);\n setStackLenSignal(_stack.length);\n });\n }\n\n // Track whether the next source change should be ignored\n // (because it was caused by undo/redo, not an external set).\n let ignoreNext = false;\n let isFirstRun = true;\n\n // Watch the source signal for external changes\n internalEffect(() => {\n const value = sourceGet();\n\n // Skip the initial effect run -- the initial value is already in the stack\n if (isFirstRun) {\n isFirstRun = false;\n return;\n }\n\n if (ignoreNext) {\n ignoreNext = false;\n return;\n }\n\n // New value from an external set: push onto history\n // Discard any \"future\" entries after the current cursor (redo is cleared)\n _stack = _stack.slice(0, _cursor + 1);\n _stack.push(value);\n\n // Enforce maxLength\n if (_stack.length > maxLength) {\n _stack.splice(0, _stack.length - maxLength);\n }\n\n _cursor = _stack.length - 1;\n syncSignals();\n });\n\n // Reactive derived getters\n const canUndo = (): boolean => cursorSignal() > 0;\n const canRedo = (): boolean => cursorSignal() < stackLenSignal() - 1;\n\n const undo = (): void => {\n if (_cursor <= 0) return;\n\n _cursor--;\n ignoreNext = true;\n sourceSet(_stack[_cursor] as T);\n syncSignals();\n };\n\n const redo = (): void => {\n if (_cursor >= _stack.length - 1) return;\n\n _cursor++;\n ignoreNext = true;\n sourceSet(_stack[_cursor] as T);\n syncSignals();\n };\n\n const clear = (): void => {\n const currentValue = sourceGet();\n _stack = [currentValue];\n _cursor = 0;\n syncSignals();\n };\n\n return {\n undo,\n redo,\n canUndo,\n canRedo,\n history: () => stackSignal(),\n cursor: () => cursorSignal(),\n clear,\n };\n}\n","/**\n * Forma State - Persist\n *\n * Auto-persist a signal to localStorage (or any Storage-compatible backend).\n * Reads stored value on creation; writes on every signal change.\n * Zero dependencies -- native browser APIs only.\n */\n\nimport { internalEffect } from 'forma/reactive';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface PersistOptions<T> {\n /** Storage backend. Defaults to localStorage. */\n storage?: Storage;\n /** Custom serializer. Defaults to JSON.stringify. */\n serialize?: (v: T) => string;\n /** Custom deserializer. Defaults to JSON.parse. */\n deserialize?: (s: string) => T;\n /** Optional validator — return true if the deserialized value is valid. Rejects corrupt/tampered data. */\n validate?: (v: unknown) => v is T;\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Persist a signal's value to storage.\n *\n * On creation, reads the stored value (if any) and hydrates the signal.\n * Then sets up an effect to write to storage whenever the signal changes.\n *\n * ```ts\n * const [theme, setTheme] = createSignal('light');\n * persist([theme, setTheme], 'app:theme');\n *\n * setTheme('dark'); // auto-saved to localStorage under key 'app:theme'\n * ```\n */\nexport function persist<T>(\n source: [get: () => T, set: (v: T) => void],\n key: string,\n options?: PersistOptions<T>,\n): void {\n const [sourceGet, sourceSet] = source;\n const storage = options?.storage ?? globalThis.localStorage;\n const serialize = options?.serialize ?? JSON.stringify;\n const deserialize = options?.deserialize ?? JSON.parse;\n const validate = options?.validate;\n\n // Step 1: Hydrate from storage (if a value exists)\n try {\n const stored = storage.getItem(key);\n if (stored !== null) {\n const value = deserialize(stored);\n if (!validate || validate(value)) {\n sourceSet(value);\n }\n }\n } catch {\n // Stored data is invalid or storage is unavailable -- ignore and keep\n // the signal's current value.\n }\n\n // Step 2: Set up effect to persist on changes\n internalEffect(() => {\n const value = sourceGet();\n try {\n const serialized = serialize(value);\n storage.setItem(key, serialized);\n } catch {\n // Storage write failed (e.g., quota exceeded) -- silently ignore.\n }\n });\n}\n","// Typed event bus — pub/sub pattern\n\nexport interface EventBus<T extends Record<string, unknown>> {\n on<K extends keyof T>(event: K, handler: (payload: T[K]) => void): () => void;\n once<K extends keyof T>(event: K, handler: (payload: T[K]) => void): () => void;\n emit<K extends keyof T>(event: K, payload: T[K]): void;\n off<K extends keyof T>(event: K, handler: (payload: T[K]) => void): void;\n clear(): void;\n}\n\nexport function createBus<\n T extends Record<string, unknown> = Record<string, unknown>,\n>(): EventBus<T> {\n const listeners = new Map<keyof T, Set<(payload: any) => void>>();\n\n function getHandlers<K extends keyof T>(event: K): Set<(payload: any) => void> {\n let set = listeners.get(event);\n if (!set) {\n set = new Set();\n listeners.set(event, set);\n }\n return set;\n }\n\n function on<K extends keyof T>(\n event: K,\n handler: (payload: T[K]) => void,\n ): () => void {\n const set = getHandlers(event);\n set.add(handler);\n return () => {\n set.delete(handler);\n };\n }\n\n function once<K extends keyof T>(\n event: K,\n handler: (payload: T[K]) => void,\n ): () => void {\n const wrapper = (payload: T[K]) => {\n off(event, wrapper);\n handler(payload);\n };\n return on(event, wrapper);\n }\n\n function emit<K extends keyof T>(event: K, payload: T[K]): void {\n const set = listeners.get(event);\n if (set) {\n // Iterate over a snapshot so removals during emit are safe\n for (const handler of [...set]) {\n try {\n handler(payload);\n } catch (e) {\n console.error(`[forma] Bus handler error on \"${String(event)}\":`, e);\n }\n }\n }\n }\n\n function off<K extends keyof T>(\n event: K,\n handler: (payload: T[K]) => void,\n ): void {\n const set = listeners.get(event);\n if (set) {\n set.delete(handler);\n }\n }\n\n function clear(): void {\n listeners.clear();\n }\n\n return { on, once, emit, off, clear };\n}\n","// Event delegation — single listener on parent, matches children by selector\n\nexport function delegate<K extends keyof HTMLElementEventMap>(\n container: HTMLElement | Document,\n selector: string,\n event: K,\n handler: (e: HTMLElementEventMap[K], matchedEl: HTMLElement) => void,\n options?: AddEventListenerOptions,\n): () => void {\n const listener = (e: Event) => {\n const target = e.target;\n if (!(target instanceof HTMLElement)) return;\n\n const root =\n container instanceof Document ? container.documentElement : container;\n const matched = target.closest(selector);\n\n if (matched instanceof HTMLElement && root.contains(matched)) {\n handler(e as HTMLElementEventMap[K], matched);\n }\n };\n\n container.addEventListener(event, listener, options);\n\n return () => {\n container.removeEventListener(event, listener, options);\n };\n}\n","// Keyboard shortcut handler\n\ntype KeyCombo = string; // e.g., 'ctrl+s', 'shift+enter', 'escape', 'ctrl+shift+z'\n\nexport interface KeyOptions {\n target?: EventTarget;\n preventDefault?: boolean;\n}\n\ninterface ParsedCombo {\n ctrl: boolean;\n shift: boolean;\n alt: boolean;\n meta: boolean;\n key: string;\n}\n\nfunction parseCombo(combo: KeyCombo): ParsedCombo {\n const parts = combo.toLowerCase().split('+').map((p) => p.trim());\n const modifiers: ParsedCombo = {\n ctrl: false,\n shift: false,\n alt: false,\n meta: false,\n key: '',\n };\n\n for (const part of parts) {\n switch (part) {\n case 'ctrl':\n case 'control':\n modifiers.ctrl = true;\n break;\n case 'shift':\n modifiers.shift = true;\n break;\n case 'alt':\n modifiers.alt = true;\n break;\n case 'meta':\n case 'cmd':\n case 'command':\n modifiers.meta = true;\n break;\n default:\n modifiers.key = part;\n }\n }\n\n return modifiers;\n}\n\nfunction matchesCombo(e: KeyboardEvent, parsed: ParsedCombo): boolean {\n if (e.ctrlKey !== parsed.ctrl) return false;\n if (e.shiftKey !== parsed.shift) return false;\n if (e.altKey !== parsed.alt) return false;\n if (e.metaKey !== parsed.meta) return false;\n return e.key.toLowerCase() === parsed.key;\n}\n\nexport function onKey(\n combo: KeyCombo,\n handler: (e: KeyboardEvent) => void,\n options?: KeyOptions,\n): () => void {\n const target: EventTarget = options?.target ?? document;\n const shouldPreventDefault = options?.preventDefault ?? true;\n const parsed = parseCombo(combo);\n\n const listener = (e: Event) => {\n if (!(e instanceof KeyboardEvent)) return;\n if (matchesCombo(e, parsed)) {\n if (shouldPreventDefault) {\n e.preventDefault();\n }\n handler(e);\n }\n };\n\n target.addEventListener('keydown', listener);\n\n return () => {\n target.removeEventListener('keydown', listener);\n };\n}\n","// Typed query helpers\n\nexport function $<T extends HTMLElement = HTMLElement>(\n selector: string,\n parent?: ParentNode,\n): T | null {\n return (parent ?? document).querySelector<T>(selector);\n}\n\nexport function $$<T extends HTMLElement = HTMLElement>(\n selector: string,\n parent?: ParentNode,\n): T[] {\n return Array.from((parent ?? document).querySelectorAll<T>(selector));\n}\n","// DOM mutation helpers\n\nexport function addClass(el: HTMLElement, ...classes: string[]): void {\n el.classList.add(...classes);\n}\n\nexport function removeClass(el: HTMLElement, ...classes: string[]): void {\n el.classList.remove(...classes);\n}\n\nexport function toggleClass(\n el: HTMLElement,\n className: string,\n force?: boolean,\n): boolean {\n return el.classList.toggle(className, force);\n}\n\nexport function setStyle(\n el: HTMLElement,\n styles: Partial<CSSStyleDeclaration>,\n): void {\n for (const [key, value] of Object.entries(styles)) {\n if (value !== undefined) {\n (el.style as any)[key] = value;\n }\n }\n}\n\nexport function setAttr(\n el: HTMLElement,\n attrs: Record<string, string | boolean | null>,\n): void {\n for (const [name, value] of Object.entries(attrs)) {\n if (value === false || value === null) {\n el.removeAttribute(name);\n } else if (value === true) {\n el.setAttribute(name, '');\n } else {\n el.setAttribute(name, value);\n }\n }\n}\n\nexport function setText(el: HTMLElement, text: string): void {\n el.textContent = text;\n}\n\n/**\n * Set raw HTML on an element. **No sanitization is performed.**\n *\n * Prefer `setText()` for user-controlled content. Only use this when you\n * trust the HTML source (e.g., server-rendered markup you control).\n *\n * @deprecated Use `setHTMLUnsafe` instead — renamed to signal risk.\n */\nexport function setHTML(el: HTMLElement, html: string): void {\n el.innerHTML = html;\n}\n\n/**\n * Set raw HTML on an element. **No sanitization is performed.**\n *\n * Prefer `setText()` for user-controlled content. Only use this when you\n * trust the HTML source (e.g., server-rendered markup you control).\n */\nexport function setHTMLUnsafe(el: HTMLElement, html: string): void {\n el.innerHTML = html;\n}\n","// DOM traversal helpers\n\nexport function closest<T extends HTMLElement = HTMLElement>(\n el: HTMLElement,\n selector: string,\n): T | null {\n return el.closest<T>(selector);\n}\n\nexport function children<T extends HTMLElement = HTMLElement>(\n el: HTMLElement,\n selector?: string,\n): T[] {\n const all = Array.from(el.children) as HTMLElement[];\n if (!selector) return all as T[];\n return all.filter((child) => child.matches(selector)) as T[];\n}\n\nexport function siblings<T extends HTMLElement = HTMLElement>(\n el: HTMLElement,\n selector?: string,\n): T[] {\n const parentEl = el.parentElement;\n if (!parentEl) return [];\n const all = Array.from(parentEl.children) as HTMLElement[];\n const sibs = all.filter((child) => child !== el);\n if (!selector) return sibs as T[];\n return sibs.filter((child) => child.matches(selector)) as T[];\n}\n\nexport function parent<T extends HTMLElement = HTMLElement>(\n el: HTMLElement,\n): T | null {\n return el.parentElement as T | null;\n}\n\nexport function nextSibling<T extends HTMLElement = HTMLElement>(\n el: HTMLElement,\n selector?: string,\n): T | null {\n let sib = el.nextElementSibling;\n while (sib) {\n if (sib instanceof HTMLElement) {\n if (!selector || sib.matches(selector)) {\n return sib as T;\n }\n }\n sib = sib.nextElementSibling;\n }\n return null;\n}\n\nexport function prevSibling<T extends HTMLElement = HTMLElement>(\n el: HTMLElement,\n selector?: string,\n): T | null {\n let sib = el.previousElementSibling;\n while (sib) {\n if (sib instanceof HTMLElement) {\n if (!selector || sib.matches(selector)) {\n return sib as T;\n }\n }\n sib = sib.previousElementSibling;\n }\n return null;\n}\n","// Observer wrappers — clean API for ResizeObserver, IntersectionObserver, MutationObserver\n\nexport function onResize(\n el: HTMLElement,\n handler: (entry: ResizeObserverEntry) => void,\n): () => void {\n const observer = new ResizeObserver((entries) => {\n for (const entry of entries) {\n handler(entry);\n }\n });\n observer.observe(el);\n return () => {\n observer.disconnect();\n };\n}\n\nexport function onIntersect(\n el: HTMLElement,\n handler: (entry: IntersectionObserverEntry) => void,\n options?: IntersectionObserverInit,\n): () => void {\n const observer = new IntersectionObserver((entries) => {\n for (const entry of entries) {\n handler(entry);\n }\n }, options);\n observer.observe(el);\n return () => {\n observer.disconnect();\n };\n}\n\nexport function onMutation(\n el: HTMLElement,\n handler: (mutations: MutationRecord[]) => void,\n options?: MutationObserverInit,\n): () => void {\n const observer = new MutationObserver((mutations) => {\n handler(mutations);\n });\n observer.observe(el, options ?? { childList: true, subtree: true });\n return () => {\n observer.disconnect();\n };\n}\n"],"mappings":"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","names":["link","unlink","propagate","checkDirty","shallowPropagate","effect","link","effect","value","prevSub","prev","cleanup","value","value","parent","nextSibling","fragment","fragment","parent","ABORT_SYM","value","value","ABORT_SYM","children","parent","ABORT_SYM","CACHE_SYM","DYNAMIC_CHILD_SYM","value","parent","children","value","value","fragment","parent","children","fragment","parent","children","fragment","parent","trigger","cleanup","value","children","value","setter","value","value","on","parent","value"]}
|