jq79 0.1.6 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/jq79.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/jq79.ts"],"sourcesContent":["\nexport const $ = (selectorOrEl: string | Element, selector?: string) => \n typeof selectorOrEl === \"string\"\n ? document.querySelector(selectorOrEl)\n : selectorOrEl.querySelector(selector || \"\")\n\nexport const $$ = (selectorOrEl: string | Element, selector?: string) => Array.from(\n typeof selectorOrEl === \"string\"\n ? document.querySelectorAll(selectorOrEl)\n : selectorOrEl.querySelectorAll(selector || \"\")\n)\n\n// $create(tag, attrs): attrs are set as attributes, except className, which\n// may be a string or an array of class names.\nexport const $create = (tag: string, attrs: Record<string, any> = {}): HTMLElement => {\n const el = document.createElement(tag);\n for (const [name, value] of Object.entries(attrs)) {\n if (name === 'className') {\n el.className = Array.isArray(value) ? value.join(' ') : value;\n } else if (name === 'textContent') {\n el.textContent = value;\n } else if (name === 'children') {\n for (const child of value) {\n el.appendChild(child);\n }\n } else {\n el.setAttribute(name, value);\n }\n }\n return el;\n};\n\ntype TemplateNode = {\n tag: string\n attrs: Record<string, string>\n children: (TemplateNode | string)[]\n}\n\ntype TagBlock = {\n attrs: Record<string, string>\n content: string\n}\n\nconst elementAttrs = (el: Element): Record<string, string> =>\n Object.fromEntries(Array.from(el.attributes).map(attr => [attr.name, attr.value]))\n\nconst elementToAST = (el: Element): TemplateNode => ({\n tag: el.tagName.toLowerCase(),\n attrs: elementAttrs(el),\n children: Array.from(el.childNodes).flatMap((node): (TemplateNode | string)[] => {\n if (node.nodeType === Node.TEXT_NODE) {\n const text = node.textContent?.trim() ?? \"\"\n return text ? [text] : []\n }\n if (node.nodeType === Node.ELEMENT_NODE) {\n return [elementToAST(node as Element)]\n }\n return []\n })\n})\n\n// evaluated with `with` (rather than passing scope keys as positional params)\n// so only the identifiers an expression actually references are read from\n// `scope` - which is what makes dependency tracking in $reactive\n// precise instead of \"read everything up front\". `extras` are passed as\n// function parameters (outside the `with`), so scope keys still win but names\n// like $event resolve when the scope doesn't shadow them\nconst evalExpr = (expr: string, scope: Record<string, any>, extras?: Record<string, any>): any => {\n try {\n return new Function(\"$scope\", ...Object.keys(extras ?? {}), `with ($scope) { return (${expr}); }`)(\n scope,\n ...Object.values(extras ?? {})\n )\n } catch {\n return undefined\n }\n}\n\nconst interpolate = (template: string, scope: Record<string, any>): string =>\n template.replace(/{{\\s*(.+?)\\s*}}/g, (_, expr) => evalExpr(expr, scope) ?? \"\")\n\ntype ChangeListener = (value: any, dotKey: string) => void\ntype AnyChangeListener = (dotKey: string, value: any) => void\ntype ListenerOptions = { immediate?: boolean }\ntype Unsubscribe = () => void\n\ntype ReactiveDeepData<T> = T & {\n $on: (dotKey: string, listener: ChangeListener, options?: ListenerOptions) => Unsubscribe\n $onAny: (listener: AnyChangeListener, options?: ListenerOptions) => Unsubscribe\n // runs `run` immediately, recording every dotKey it reads off this store, then\n // re-runs it whenever a changed dotKey overlaps one of those - see pathsOverlap\n $effect: (run: () => void) => Unsubscribe\n}\n\nconst getByPath = (obj: Record<string, any>, dotKey: string): any =>\n dotKey.split(\".\").reduce((acc, key) => (acc == null ? undefined : acc[key]), obj)\n\n// only plain objects and arrays get deep-wrapped by the reactive store;\n// class instances (Component79, Date, DOM nodes, ...) pass through untouched\n// so their identity, prototypes and internals stay intact\nconst isPlainData = (value: object): boolean => {\n if (Array.isArray(value)) return true\n const proto = Object.getPrototypeOf(value)\n return proto === Object.prototype || proto === null\n}\n\nconst walkLeaves = (obj: Record<string, any>, path: string, visit: (dotKey: string, value: any) => void) => {\n Object.entries(obj).forEach(([key, value]) => {\n const dotKey = path ? `${path}.${key}` : key\n if (value && typeof value === \"object\" && isPlainData(value)) walkLeaves(value, dotKey, visit)\n else visit(dotKey, value)\n })\n}\n\n// true when `a` and `b` sit on the same ancestor/descendant line, e.g.\n// \"user\" & \"user.address.city\" (a change to either affects the other) - false\n// for siblings like \"user.name\" & \"user.age\"\nconst pathsOverlap = (a: string, b: string): boolean =>\n a === b || a.startsWith(`${b}.`) || b.startsWith(`${a}.`)\n\n// active $effect() runs, innermost last - a module-level stack (rather than\n// one per store) so nested effects across stores still nest correctly; reads\n// during makeReactive's `get` trap are attributed to whichever run is on top\nconst trackerStack: Set<string>[] = []\n\n// runs fn with dependency tracking suspended - reads inside it are attributed\n// to a throwaway set instead of the currently running effect\nconst untracked = <T>(fn: () => T): T => {\n trackerStack.push(new Set())\n try {\n return fn()\n } finally {\n trackerStack.pop()\n }\n}\n\ntype Effect = { deps: Set<string>; run: () => void }\n\nexport const $reactive = <T extends Record<string, any>>(data: T): ReactiveDeepData<T> => {\n const exactListeners = new Map<string, Set<ChangeListener>>()\n const anyListeners = new Set<AnyChangeListener>()\n const effects = new Set<Effect>()\n // every proxy this store has ever handed out, so re-assigning an object\n // that's already reactive (e.g. `data.list = [data.list[1], data.list[0]]`)\n // doesn't wrap it a second time - which would hand out a *new* object\n // identity for the same logical item, breaking reference-equality checks\n // like :each's keyed diffing\n const reactiveProxies = new WeakSet<object>()\n\n const notify = (dotKey: string, value: any) => {\n exactListeners.get(dotKey)?.forEach(listener => listener(value, dotKey))\n anyListeners.forEach(listener => listener(dotKey, value))\n effects.forEach(effect => {\n if (Array.from(effect.deps).some(dep => pathsOverlap(dep, dotKey))) effect.run()\n })\n }\n\n const makeReactive = (obj: Record<string, any>, path: string): Record<string, any> => {\n if (reactiveProxies.has(obj)) return obj\n\n Object.entries(obj).forEach(([key, value]) => {\n if (value && typeof value === \"object\" && isPlainData(value)) {\n obj[key] = makeReactive(value, path ? `${path}.${key}` : key)\n }\n })\n\n const proxy = new Proxy(obj, {\n get(target, key, receiver) {\n if (typeof key === \"string\") {\n trackerStack[trackerStack.length - 1]?.add(path ? `${path}.${key}` : key)\n }\n return Reflect.get(target, key, receiver)\n },\n set(target, key: string, value, receiver) {\n // an assignment delegated up the prototype chain from a derived scope\n // (Object.create(store) child, or a wrapping proxy): if the key isn't\n // a real property of this store, honor the receiver so the new binding\n // lands on the derived scope - a scope-local variable, not a store\n // mutation, so no notify. If the key IS a store property, fall through\n // and mutate the store itself regardless of receiver, so assignments\n // like @click=\"count = count + 1\" work from any nested scope\n if (receiver !== proxy && !Object.prototype.hasOwnProperty.call(target, key)) {\n return Reflect.set(target, key, value, receiver)\n }\n\n const dotKey = path ? `${path}.${key}` : key\n if (value && typeof value === \"object\" && isPlainData(value)) {\n value = makeReactive(value, dotKey)\n }\n target[key] = value\n notify(dotKey, value)\n return true\n }\n })\n\n reactiveProxies.add(proxy)\n return proxy\n }\n\n const reactive = makeReactive(data, \"\") as ReactiveDeepData<T>\n\n const $on = (dotKey: string, listener: ChangeListener, { immediate = false }: ListenerOptions = {}): Unsubscribe => {\n if (!exactListeners.has(dotKey)) exactListeners.set(dotKey, new Set())\n exactListeners.get(dotKey)!.add(listener)\n if (immediate) listener(getByPath(reactive, dotKey), dotKey)\n return () => exactListeners.get(dotKey)?.delete(listener)\n }\n\n const $onAny = (listener: AnyChangeListener, { immediate = false }: ListenerOptions = {}): Unsubscribe => {\n anyListeners.add(listener)\n if (immediate) walkLeaves(reactive, \"\", (dotKey, value) => listener(dotKey, value))\n return () => anyListeners.delete(listener)\n }\n\n const $effect = (run: () => void): Unsubscribe => {\n const effect: Effect = {\n deps: new Set(),\n run: () => {\n const deps = new Set<string>()\n trackerStack.push(deps)\n try {\n run()\n } finally {\n trackerStack.pop()\n effect.deps = deps\n }\n },\n }\n effects.add(effect)\n effect.run()\n return () => { effects.delete(effect) }\n }\n\n Object.defineProperty(reactive, \"$on\", { value: $on, enumerable: false })\n Object.defineProperty(reactive, \"$onAny\", { value: $onAny, enumerable: false })\n Object.defineProperty(reactive, \"$effect\", { value: $effect, enumerable: false })\n\n return reactive\n}\n\nconst CONTROL_ATTRS = new Set([\":bind\", \":if\", \":elseif\", \":else\", \":each\", \":key\", \":with\"])\nconst EACH_PATTERN = /^\\s*(\\w+)\\s+in\\s+(.+)$/\n\ntype ConditionalBranch = { expr?: string; node: TemplateNode }\n\n// groups the disposers of every $effect created for one rendered subtree\n// (an :if branch, an :each item, ...) so the whole subtree's bindings can be\n// torn down in one call when that subtree is replaced/removed. `scope.$effect`\n// resolves through the prototype chain up to the root store no matter how\n// many nested :each scopes sit in between (see renderEach's itemScope)\ntype EffectScope = {\n effect: (run: () => void) => void\n // registers an arbitrary cleanup (e.g. destroying a nested component) to\n // run when this subtree is torn down\n onDispose: (fn: Unsubscribe) => void\n dispose: () => void\n}\n\nconst createEffectScope = (scope: Record<string, any>): EffectScope => {\n const disposers: Unsubscribe[] = []\n return {\n effect: run => { disposers.push(scope.$effect(run)) },\n onDispose: fn => { disposers.push(fn) },\n dispose: () => { disposers.splice(0).forEach(dispose => dispose()) },\n }\n}\n\n// @event attributes: @click=\"onClick\", @submit.prevent=\"$event => onSubmit($event)\",\n// or an inline statement like @click=\"count = count + 1\". The expression is\n// evaluated (with `$event` in scope) on every event; if it yields a function,\n// that function is then invoked with the event - so both a handler reference\n// and an inline arrow/statement work. Modifiers after dots: .prevent .stop\n// .self (runtime guards) and .once .capture (addEventListener options)\nconst bindEvent = (el: Element, attr: string, expr: string, scope: Record<string, any>) => {\n const [name, ...modifiers] = attr.slice(1).split(\".\")\n const mods = new Set(modifiers)\n\n el.addEventListener(name, event => {\n if (mods.has(\"self\") && event.target !== el) return\n if (mods.has(\"prevent\")) event.preventDefault()\n if (mods.has(\"stop\")) event.stopPropagation()\n\n const handler = evalExpr(expr, scope, { $event: event })\n if (typeof handler === \"function\") handler.call(el, event)\n }, { once: mods.has(\"once\"), capture: mods.has(\"capture\") })\n}\n\nconst kebabToCamel = (name: string) => name.replace(/-(\\w)/g, (_, c: string) => c.toUpperCase())\n\n// finds the scope variable a template tag refers to. HTML parsing lowercases\n// tag names, so <NestedComponent> arrives as \"nestedcomponent\" and matching is\n// case-insensitive with dashes stripped (<nested-component> works too). Only\n// PascalCase scope keys participate, so ordinary variables named like real\n// elements (title, code, ...) never hijack them\nconst findComponentKey = (scope: Record<string, any>, tag: string): string | null => {\n const normalized = tag.replace(/-/g, \"\").toLowerCase()\n for (let obj: any = scope; obj && obj !== Object.prototype; obj = Object.getPrototypeOf(obj)) {\n for (const key of Object.keys(obj)) {\n if (/^[A-Z]/.test(key) && key.replace(/-/g, \"\").toLowerCase() === normalized) return key\n }\n }\n return null\n}\n\n// <MyComponent :user :title=\"'str'\"></MyComponent> - renders a child\n// component instance at this position. Props: `:name=\"expr\"` evaluates expr\n// in the parent scope (`:name` alone is shorthand for `:name=\"name\"`), plain\n// attributes pass through as literal strings, and kebab-case prop names\n// become camelCase. Props stay live: a parent effect re-evaluates each\n// expression and writes it into the child's store. The component variable is\n// reactive too - while it's undefined (e.g. an `await import(...)` still in\n// flight) nothing renders, and the child appears when it resolves\nconst renderNestedComponent = (key: string, node: TemplateNode, scope: Record<string, any>, fx: EffectScope): Node => {\n const anchor = document.createComment(key)\n const wrapper = document.createDocumentFragment()\n wrapper.appendChild(anchor)\n\n const props: Record<string, string> = {} // prop name -> expression in parent scope\n Object.entries(node.attrs).forEach(([attr, value]) => {\n if (CONTROL_ATTRS.has(attr) || attr.startsWith(\"@\")) return\n if (attr.startsWith(\":\")) {\n const name = kebabToCamel(attr.slice(1))\n props[name] = value || name\n } else {\n props[kebabToCamel(attr)] = JSON.stringify(value)\n }\n })\n\n let current: Component79 | null = null\n let currentDef: Component79 | null = null\n let childFx: EffectScope | null = null\n\n fx.effect(() => {\n const value = evalExpr(key, scope)\n const nextDef = value instanceof Component79 ? value : null\n if (nextDef === currentDef) return\n\n childFx?.dispose()\n childFx = null\n current?.destroy() // unmounts its marker range, removing the child's DOM\n current = null\n currentDef = nextDef\n if (!nextDef) return\n\n // a fresh instance per usage site: the definition's parsed parts are\n // shared, but store/effects/DOM are per instance\n const instance = new Component79({ template: nextDef.template, scripts: nextDef.scripts, styles: nextDef.styles })\n const seed = untracked(() =>\n Object.fromEntries(Object.entries(props).map(([name, expr]) => [name, evalExpr(expr, scope)]))\n )\n const holder = document.createDocumentFragment()\n instance.render(seed).mount(holder)\n anchor.parentNode!.insertBefore(holder, anchor.nextSibling)\n\n const syncFx = createEffectScope(scope)\n Object.entries(props).forEach(([name, expr]) => {\n syncFx.effect(() => { (instance.data as Record<string, any>)[name] = evalExpr(expr, scope) })\n })\n\n childFx = syncFx\n current = instance\n })\n\n fx.onDispose(() => {\n childFx?.dispose()\n current?.destroy()\n })\n\n return wrapper\n}\n\n// :with=\"expr\" narrows the scope for an element and its subtree: names\n// resolve against the expression's value first, then fall back to the outer\n// scope. The value is re-evaluated lazily on every name lookup (never\n// snapshotted), so an effect reading through this proxy tracks both the\n// expression's own dependencies and the property it reads - replacing the\n// object or mutating one of its properties re-renders exactly the dependents,\n// without rebuilding the subtree. Assignments to names the object owns write\n// through to it (reactively, if it came from a store); everything else\n// behaves as if the :with weren't there\nconst createWithScope = (expr: string, scope: Record<string, any>): Record<string, any> => {\n const source = (): Record<string, any> | null => {\n const value = evalExpr(expr, scope)\n return value !== null && typeof value === \"object\" ? value : null\n }\n return new Proxy(scope, {\n has(target, key) {\n const obj = source()\n return (obj !== null && Reflect.has(obj, key)) || Reflect.has(target, key)\n },\n get(target, key) {\n const obj = source()\n if (obj !== null && Reflect.has(obj, key)) return obj[key as string]\n return Reflect.get(target, key)\n },\n set(target, key, value) {\n const obj = source()\n if (obj !== null && Reflect.has(obj, key)) {\n obj[key as string] = value\n return true\n }\n return Reflect.set(target, key, value)\n },\n })\n}\n\n// renders a single element node: static attrs, @event listeners, a reactive\n// :bind object, and its (reactive) children. :if/:elseif/:else/:each are\n// handled by renderNodes, which decides *whether*/*how many times* a node is\n// rendered before calling this. Tags matching a PascalCase scope variable\n// render as nested components instead\nconst renderNode = (node: TemplateNode, outerScope: Record<string, any>, fx: EffectScope): Node => {\n // :with applies to the element's own bindings (@events, :bind) and its\n // whole subtree. On a :each element the item scope is already in place, so\n // :with=\"item\" works\n const withExpr = node.attrs[\":with\"]\n const scope = withExpr !== undefined ? createWithScope(withExpr, outerScope) : outerScope\n\n const componentKey = findComponentKey(scope, node.tag)\n if (componentKey) return renderNestedComponent(componentKey, node, scope, fx)\n\n const el = document.createElement(node.tag)\n\n Object.entries(node.attrs).forEach(([key, value]) => {\n if (key.startsWith(\"@\")) bindEvent(el, key, value, scope)\n else if (!CONTROL_ATTRS.has(key)) el.setAttribute(key, value)\n })\n\n const bindExpr = node.attrs[\":bind\"]\n if (bindExpr !== undefined) {\n let boundKeys: string[] = []\n\n fx.effect(() => {\n boundKeys.forEach(key => el.removeAttribute(key))\n const bound = evalExpr(bindExpr, scope)\n boundKeys = bound && typeof bound === \"object\" ? Object.keys(bound) : []\n boundKeys.forEach(key => {\n const value = bound[key]\n if (value != null && value !== false) el.setAttribute(key, String(value))\n })\n })\n }\n\n el.appendChild(renderNodes(node.children, scope, fx))\n\n return el\n}\n\n// a :if/:elseif*/:else? chain sharing one anchor comment so the active branch\n// can be swapped in place without disturbing sibling positions. Only depends\n// on whatever the branch expressions read (e.g. \"score\"), and skips\n// rebuilding entirely when the active branch hasn't actually changed\nconst renderConditional = (branches: ConditionalBranch[], scope: Record<string, any>, fx: EffectScope): Node => {\n const anchor = document.createComment(\"if\")\n const wrapper = document.createDocumentFragment()\n wrapper.appendChild(anchor)\n\n let current: Node | null = null\n let activeBranch: ConditionalBranch | null = null\n let branchFx: EffectScope | null = null\n\n fx.effect(() => {\n const next = branches.find(branch => branch.expr === undefined || evalExpr(branch.expr, scope)) ?? null\n if (next === activeBranch) return\n\n branchFx?.dispose()\n if (current) current.parentNode?.removeChild(current)\n current = null\n activeBranch = next\n if (!next) return\n\n branchFx = createEffectScope(scope)\n current = renderNode(next.node, scope, branchFx)\n anchor.parentNode!.insertBefore(current, anchor.nextSibling)\n })\n\n return wrapper\n}\n\n// defines a loop-local binding directly as `scope`'s own property. Plain\n// assignment (scope[key] = value) would only do this if the key isn't\n// already own on `scope` *or anywhere up its prototype chain* - if it isn't,\n// JS delegates the [[Set]] to whatever's up there, which for us is another\n// reactive proxy's `set` trap: it would wrap `value` as if it were a genuine\n// store mutation and fire a bogus notify() under a name (e.g. \"item\") shared\n// by every unrelated item in every :each on the page. defineProperty always\n// writes to `scope` itself, never delegating, so this can't happen\nconst defineScopeVar = (scope: Record<string, any>, key: string, value: any) => {\n Object.defineProperty(scope, key, { value, writable: true, enumerable: true, configurable: true })\n}\n\ntype EachEntry = { key: any; item: any; scope: Record<string, any>; node: Node; fx: EffectScope }\n\n// :each=\"item in items\", optionally keyed with :key=\"expr\". Only depends on\n// the list expression itself (e.g. \"items\"), and on each run diffs by key:\n// unchanged items (same key, same item reference) keep their DOM/effects,\n// changed/added ones are (re)rendered, removed ones are disposed. Without\n// :key, position is used as the key, so reordering rebuilds every item after\n// the first change - add :key for anything that gets reordered or filtered.\n// Each item gets its own scope via Object.create(scope), so `item`/`$index`\n// shadow same-named outer bindings without copying the parent scope's keys\nconst renderEach = (node: TemplateNode, scope: Record<string, any>, fx: EffectScope): Node => {\n const match = node.attrs[\":each\"].match(EACH_PATTERN)\n if (!match) return document.createComment(`invalid :each expression \"${node.attrs[\":each\"]}\"`)\n\n const [, itemName, listExpr] = match\n const keyExpr = node.attrs[\":key\"]\n const { [\":each\"]: _each, [\":key\"]: _key, ...itemAttrs } = node.attrs\n const itemNode: TemplateNode = { ...node, attrs: itemAttrs }\n\n const anchor = document.createComment(\"each\")\n const wrapper = document.createDocumentFragment()\n wrapper.appendChild(anchor)\n\n let entries: EachEntry[] = []\n\n fx.effect(() => {\n const list = evalExpr(listExpr, scope)\n const items = Array.isArray(list) ? list : []\n const previous = new Map(entries.map(entry => [entry.key, entry]))\n\n const nextEntries = items.map((item, index): EachEntry => {\n const itemScope = Object.create(scope)\n defineScopeVar(itemScope, itemName, item)\n defineScopeVar(itemScope, \"$index\", index)\n const key = keyExpr !== undefined ? evalExpr(keyExpr, itemScope) : index\n const existing = previous.get(key)\n\n if (existing && Object.is(existing.item, item)) {\n defineScopeVar(existing.scope, \"$index\", index)\n return existing\n }\n\n existing?.fx.dispose()\n existing?.node.parentNode?.removeChild(existing.node)\n\n const itemFx = createEffectScope(scope)\n return { key, item, scope: itemScope, fx: itemFx, node: renderNode(itemNode, itemScope, itemFx) }\n })\n\n const nextKeys = new Set(nextEntries.map(entry => entry.key))\n entries.forEach(entry => {\n if (!nextKeys.has(entry.key)) {\n entry.fx.dispose()\n entry.node.parentNode?.removeChild(entry.node)\n }\n })\n\n let prevNode: Node = anchor\n nextEntries.forEach(entry => {\n if (prevNode.nextSibling !== entry.node) anchor.parentNode!.insertBefore(entry.node, prevNode.nextSibling)\n prevNode = entry.node\n })\n\n entries = nextEntries\n })\n\n return wrapper\n}\n\n// renders a list of sibling template nodes (text + elements), grouping\n// consecutive :if/:elseif/:else nodes into a single conditional block\nconst renderNodes = (nodes: (TemplateNode | string)[], scope: Record<string, any>, fx: EffectScope): DocumentFragment => {\n const fragment = document.createDocumentFragment()\n let i = 0\n\n while (i < nodes.length) {\n const node = nodes[i]\n\n if (typeof node === \"string\") {\n const textNode = document.createTextNode(\"\")\n fx.effect(() => { textNode.textContent = interpolate(node, scope) })\n fragment.appendChild(textNode)\n i++\n continue\n }\n\n if (\":each\" in node.attrs) {\n fragment.appendChild(renderEach(node, scope, fx))\n i++\n continue\n }\n\n if (\":if\" in node.attrs) {\n const branches: ConditionalBranch[] = [{ expr: node.attrs[\":if\"], node }]\n i++\n while (i < nodes.length && typeof nodes[i] !== \"string\" && \":elseif\" in (nodes[i] as TemplateNode).attrs) {\n const elseifNode = nodes[i] as TemplateNode\n branches.push({ expr: elseifNode.attrs[\":elseif\"], node: elseifNode })\n i++\n }\n if (i < nodes.length && typeof nodes[i] !== \"string\" && \":else\" in (nodes[i] as TemplateNode).attrs) {\n branches.push({ node: nodes[i] as TemplateNode })\n i++\n }\n\n fragment.appendChild(renderConditional(branches, scope, fx))\n continue\n }\n\n fragment.appendChild(renderNode(node, scope, fx))\n i++\n }\n\n return fragment\n}\n\nexport const renderComponent = (component: Component79, data: ReactiveDeepData<Record<string, any>>): Node =>\n renderNodes(component.template, data, createEffectScope(data))\n\ntype ComponentParts = {\n template: TemplateNode[]\n scripts: TagBlock[]\n styles: TagBlock[]\n}\n\nconst VOID_ELEMENTS = new Set([\n \"area\", \"base\", \"br\", \"col\", \"embed\", \"hr\", \"img\", \"input\",\n \"link\", \"meta\", \"param\", \"source\", \"track\", \"wbr\",\n])\n\n// a self-closing tag with its attributes; quoted attribute values are matched\n// as whole chunks so a \"/>\" inside one doesn't end the tag early\nconst SELF_CLOSING_RE = /<([A-Za-z][\\w-]*)((?:\"[^\"]*\"|'[^']*'|[^>\"'])*?)\\/>/g\nconst RAW_BLOCK_RE = /(<script[\\s\\S]*?<\\/script\\s*>|<style[\\s\\S]*?<\\/style\\s*>)/gi\n\n// expands self-closing tags (<MyComponent />, <div />) into explicit\n// open+close pairs BEFORE DOM parsing. The HTML parser ignores the slash and\n// would treat them as unclosed, swallowing the following siblings. Void\n// elements keep their native behavior, and <script>/<style> contents are\n// passed through untouched so code inside them is never rewritten\nconst expandSelfClosingTags = (src: string): string =>\n src\n .split(RAW_BLOCK_RE)\n .map((chunk, i) =>\n i % 2 === 1 // odd chunks are the captured script/style blocks\n ? chunk\n : chunk.replace(SELF_CLOSING_RE, (match, tag: string, attrs: string) =>\n VOID_ELEMENTS.has(tag.toLowerCase()) ? match : `<${tag}${attrs}></${tag}>`\n )\n )\n .join(\"\")\n\n// converts a string of HTML into an AST representation of the component:\n// - template: the non-script/style top-level elements, as TemplateNodes\n// - scripts/styles: { attrs, content } blocks in source order\nconst parseComponentString = (component: string): ComponentParts => {\n // example\n // <script :setup=\"{ fname, lname }\">\n // const fullName = `${fname} ${lname}`\n // </script>\n //\n // <div :bind=\"{ fullName }\"></div>\n // <div class=\"full-name\">\n // {{ fullName }}\n // </div>\n //\n // <style>\n // .full-name {\n // color: red;\n // }\n // </style>\n\n // parsed as the content of a <template> so leading <script>/<style> tags\n // aren't reparented into <head> by the HTML parser\n const parsedDOM = new DOMParser().parseFromString(`<template>${expandSelfClosingTags(component)}</template>`, \"text/html\")\n const root = parsedDOM.querySelector(\"template\") as HTMLTemplateElement\n\n const scripts: TagBlock[] = []\n const styles: TagBlock[] = []\n const template: TemplateNode[] = []\n\n Array.from(root.content.children).forEach(el => {\n const block = { attrs: elementAttrs(el), content: el.textContent ?? \"\" }\n\n if (el.tagName === \"SCRIPT\") scripts.push(block)\n else if (el.tagName === \"STYLE\") styles.push(block)\n else template.push(elementToAST(el))\n })\n\n return { template, scripts, styles }\n}\n\n// ---------------------------------------------------------------------------\n// :setup script transform\n//\n// setup scripts are written like Svelte components:\n//\n// let firstName = null\n// $: fullName = `${firstName} ${lastName}`\n// fetchUser().then(user => { firstName = user.firstName })\n//\n// and are executed inside `with ($scope)` against the component's reactive\n// store, so plain assignments (even from async callbacks) go through the\n// proxy's set trap and re-render whatever depends on them. To make that work\n// the source is lightly rewritten - no full JS parser, just a scanner that is\n// string/comment-aware and only touches code at brace/paren depth 0:\n// - `let/var/const x = ...` at the top level loses its keyword, becoming a\n// scope assignment (the name is pre-declared on the store so the `with`\n// lookup resolves it)\n// - `$: x = expr` becomes `$__effect(() => { x = expr })`, re-running when a\n// dependency read inside expr changes ($__effect is deliberately NOT a\n// property of the scope, so `with` falls through to the function parameter)\n// ---------------------------------------------------------------------------\n\ntype SetupTransform = { vars: string[]; code: string }\n\nconst DECLARATION_RE = /(?:let|var|const)\\s+([A-Za-z_$][\\w$]*)/y\nconst REACTIVE_LABEL_RE = /\\$:\\s*/y\nconst IMPORT_CALL_RE = /import(?=\\s*\\()/y\nconst REACTIVE_ASSIGN_RE = /\\$:\\s*([A-Za-z_$][\\w$]*)\\s*=(?!=)/y\n\nconst skipString = (src: string, start: number): number => {\n const quote = src[start]\n let i = start + 1\n while (i < src.length) {\n if (src[i] === \"\\\\\") { i += 2; continue }\n if (src[i] === quote) return i + 1\n i++\n }\n return src.length\n}\n\nconst skipLineComment = (src: string, start: number): number => {\n const end = src.indexOf(\"\\n\", start)\n return end === -1 ? src.length : end\n}\n\nconst skipBlockComment = (src: string, start: number): number => {\n const end = src.indexOf(\"*/\", start + 2)\n return end === -1 ? src.length : end + 2\n}\n\n// end of a statement starting at `start`: the first newline or `;` that isn't\n// inside a string/comment or unbalanced brackets, so multi-line RHS like a\n// wrapped function call or template literal stays in one piece\nconst findStatementEnd = (src: string, start: number): number => {\n let depth = 0\n let i = start\n while (i < src.length) {\n const ch = src[i]\n if (ch === \"'\" || ch === '\"' || ch === \"`\") { i = skipString(src, i); continue }\n if (ch === \"/\" && src[i + 1] === \"/\") { i = skipLineComment(src, i); continue }\n if (ch === \"/\" && src[i + 1] === \"*\") { i = skipBlockComment(src, i); continue }\n if (\"([{\".includes(ch)) depth++\n else if (\")]}\".includes(ch)) depth--\n else if (depth <= 0 && (ch === \"\\n\" || ch === \";\")) return i\n i++\n }\n return src.length\n}\n\nconst transformSetupScript = (src: string): SetupTransform => {\n const vars: string[] = []\n let out = \"\"\n let i = 0\n let depth = 0\n let atStatementStart = true\n\n while (i < src.length) {\n const ch = src[i]\n const next = src[i + 1]\n\n if (ch === \"'\" || ch === '\"' || ch === \"`\") {\n const end = skipString(src, i)\n out += src.slice(i, end)\n i = end\n atStatementStart = false\n continue\n }\n if (ch === \"/\" && (next === \"/\" || next === \"*\")) {\n const end = next === \"/\" ? skipLineComment(src, i) : skipBlockComment(src, i)\n out += src.slice(i, end)\n i = end\n continue\n }\n\n // `import(...)` is a keyword form, so it can't be intercepted through the\n // scope - rewrite the identifier to the injected $__import (which loads\n // .html URLs as components via Component79.fetch and delegates the rest to\n // native import). The `(` is left for the scanner so depth stays balanced\n if (ch === \"i\" && (i === 0 || !/[\\w$.]/.test(src[i - 1]))) {\n IMPORT_CALL_RE.lastIndex = i\n if (IMPORT_CALL_RE.test(src)) {\n out += \"$__import\"\n i += \"import\".length\n atStatementStart = false\n continue\n }\n }\n\n if (depth === 0 && atStatementStart) {\n DECLARATION_RE.lastIndex = i\n const decl = DECLARATION_RE.exec(src)\n if (decl) {\n vars.push(decl[1])\n out += decl[1]\n i += decl[0].length\n atStatementStart = false\n continue\n }\n\n REACTIVE_LABEL_RE.lastIndex = i\n const label = REACTIVE_LABEL_RE.exec(src)\n if (label) {\n REACTIVE_ASSIGN_RE.lastIndex = i\n const assign = REACTIVE_ASSIGN_RE.exec(src)\n if (assign) vars.push(assign[1])\n const start = i + label[0].length\n const end = findStatementEnd(src, start)\n out += `$__effect(() => { ${src.slice(start, end)} });`\n i = end\n continue\n }\n }\n\n if (\"([{\".includes(ch)) depth++\n else if (\")]}\".includes(ch)) depth = Math.max(0, depth - 1)\n\n if (ch === \"\\n\" || ch === \";\" || ch === \"}\") atStatementStart = true\n else if (!/\\s/.test(ch)) atStatementStart = false\n\n out += ch\n i++\n }\n\n return { vars, code: out }\n}\n\n// loads .html URLs as components, delegating anything else to native import()\nconst importResource = (url: string): Promise<any> =>\n /\\.html?([?#]|$)/.test(url) ? Component79.fetch(url) : import(url)\n\n// document.head styles are shared by content and refcounted, so N instances\n// of the same component (e.g. one per :each item) inject a single <style> tag\n// that goes away when the last instance is destroyed\nconst styleRegistry = new Map<string, { el: HTMLStyleElement; count: number }>()\n\nconst acquireStyle = (content: string) => {\n let entry = styleRegistry.get(content)\n if (!entry) {\n const el = document.createElement(\"style\")\n el.textContent = content\n document.head.appendChild(el)\n entry = { el, count: 0 }\n styleRegistry.set(content, entry)\n }\n entry.count++\n}\n\nconst releaseStyle = (content: string) => {\n const entry = styleRegistry.get(content)\n if (entry && --entry.count <= 0) {\n entry.el.remove()\n styleRegistry.delete(content)\n }\n}\n\n// library helpers injected into setup scripts. They behave like extra\n// globals: a same-named scope property (render data or a top-level\n// declaration) shadows them\nconst SETUP_HELPERS: Record<string, any> = { $, $$, $create, $reactive }\n\n// scripts run inside `with (scriptScope)`, where scriptScope's `has` trap\n// claims ownership of every name that is neither a real global, an injected\n// library helper, nor one of the internal helpers. This makes `with` route ALL\n// other reads/writes through the reactive store - even bare assignments to\n// names never declared with let/const, which would otherwise leak onto\n// globalThis - while `console`, `Promise`, `fetch`, etc. still resolve\n// normally. get/set are deliberately not trapped: they default-forward to\n// `scope` (the reactive proxy), preserving tracking and notify.\n// The body is wrapped in an async IIFE so top-level `await` works: everything\n// up to the first await runs synchronously (before the template renders), and\n// later assignments update the DOM reactively when they happen\nconst runSetupScript = (code: string, scope: Record<string, any>, effect: (run: () => void) => void, instanceHelpers: Record<string, any> = {}) => {\n // instanceHelpers are per-component-instance additions (e.g. $emit, which\n // is bound to this instance's DOM position)\n const helpers = { ...SETUP_HELPERS, ...instanceHelpers }\n const scriptScope = new Proxy(scope, {\n has: (target, key) =>\n key !== \"$__effect\" && key !== \"$__import\" &&\n (Reflect.has(target, key) || !(key in globalThis) && !(key in helpers)),\n })\n const result: Promise<void> = new Function(\n \"$scope\", \"$__effect\", \"$__import\", ...Object.keys(helpers),\n `return (async () => { with ($scope) { ${code} } })()`\n )(scriptScope, effect, importResource, ...Object.values(helpers))\n result.catch(error => console.error(\"jq79: error in :setup script\", error))\n}\n\n// a parsed single-file component. Typical lifecycle:\n//\n// const jq79 = new Component79(src) // or await Component79.fetch(url)\n// jq79.render({ user }) // build reactive DOM, run scripts, inject styles\n// .mount(\"#app\") // attach (renderShadow mounts into a shadow root)\n// ...\n// jq79.unmount() // detach, keeping state - mount() re-attaches\n// .destroy() // dispose effects and remove styles\nexport class Component79 {\n template: TemplateNode[]\n scripts: TagBlock[]\n styles: TagBlock[]\n\n data: ReactiveDeepData<Record<string, any>> | null = null\n\n private fx: EffectScope | null = null\n // holds the rendered nodes while unmounted; anchors keep this fragment as\n // their parentNode, so effects keep the (detached) DOM up to date and a\n // later mount() shows current state\n private content: DocumentFragment | null = null\n // markers bracketing the component's output so unmount() can collect nodes\n // that :if/:each inserted next to the anchors after mounting\n private startMarker: Comment | null = null\n private endMarker: Comment | null = null\n // shadow rendering keeps per-instance <style> elements; head rendering goes\n // through the shared refcounted styleRegistry instead\n private styleEls: HTMLStyleElement[] = []\n private ownsSharedStyles = false\n private useShadow = false\n private mountRoot: Element | ShadowRoot | DocumentFragment | null = null\n // settles the $mounted() promise handed to this render generation's scripts\n private resolveMounted: (() => void) | null = null\n\n constructor(src: string | ComponentParts) {\n const { template, scripts, styles } = typeof src === \"string\" ? parseComponentString(src) : src\n this.template = template\n this.scripts = scripts\n this.styles = styles\n }\n\n static async fetch(url: string): Promise<Component79> {\n const response = await fetch(url)\n if (!response.ok) throw new Error(`failed to fetch component from ${url}: ${response.status}`)\n return new Component79(await response.text())\n }\n\n render(data: Record<string, any> = {}): this {\n return this.renderWith(data, false)\n }\n\n // like render(), but styles are injected into a shadow root attached to the\n // mount target instead of document.head, so they don't leak globally\n renderShadow(data: Record<string, any> = {}): this {\n return this.renderWith(data, true)\n }\n\n private renderWith(data: Record<string, any>, shadow: boolean): this {\n this.destroy()\n\n const store = $reactive({ ...data })\n const fx = createEffectScope(store)\n this.data = store\n this.fx = fx\n this.useShadow = shadow\n\n this.startMarker = document.createComment(\"jq79\")\n this.endMarker = document.createComment(\"/jq79\")\n\n // $emit dispatches a bubbling CustomEvent from this instance's start\n // marker, so once mounted it travels up the real DOM and parents can\n // listen on any ancestor (or with @event-name on a wrapping element).\n // Captures the marker rather than `this` so a later re-render's scripts\n // can't dispatch from the wrong generation\n const marker = this.startMarker\n const $emit = (eventName: string, payload?: any): boolean =>\n marker.dispatchEvent(new CustomEvent(eventName, { detail: payload, bubbles: true, composed: true }))\n\n // `await $mounted()` suspends a setup script until mount() attaches the\n // component, so code below it can querySelector its own DOM. Resumption\n // is a microtask, so in the usual synchronous render().mount() flow the\n // whole tree (nested components included) is in the document before the\n // script continues. If this instance is never mounted, the promise stays\n // pending and the script's tail never runs\n let resolveMounted!: () => void\n const mounted = new Promise<void>(resolve => { resolveMounted = resolve })\n this.resolveMounted = resolveMounted\n const $mounted = () => mounted\n\n // $self / $$self mirror $ / $$ but only search this instance's own\n // output: the sibling nodes between its markers. They work detached too\n // (the holding fragment keeps markers and rendered nodes as siblings),\n // though the template renders after the scripts run, so they only find\n // something from post-await code or callbacks\n const endMarker = this.endMarker\n const $$self = (selector: string): Element[] => {\n const found: Element[] = []\n for (let node: Node | null = marker.nextSibling; node && node !== endMarker; node = node.nextSibling) {\n if (node instanceof Element) {\n if (node.matches(selector)) found.push(node)\n found.push(...Array.from(node.querySelectorAll(selector)))\n }\n }\n return found\n }\n const $self = (selector: string): Element | null => $$self(selector)[0] ?? null\n\n // scripts run before the template renders so `$:` values are initialized;\n // a `:mounted` script defers entirely until mount() instead\n this.scripts.forEach(script => {\n const { vars, code } = transformSetupScript(script.content)\n // pre-declare script vars on the store so `with` resolves assignments\n // to them (and reads of them) through the reactive proxy\n vars.forEach(name => { if (!(name in store)) (store as any)[name] = undefined })\n const body = \":mounted\" in script.attrs ? `await $mounted();\\n${code}` : code\n runSetupScript(body, store, fx.effect, { $emit, $mounted, $self, $$self })\n })\n\n const content = document.createDocumentFragment()\n content.append(this.startMarker, renderNodes(this.template, store, fx), this.endMarker)\n this.content = content\n\n if (shadow) {\n this.styleEls = this.styles.map(style => {\n const el = document.createElement(\"style\")\n el.textContent = style.content\n return el\n })\n } else {\n this.styles.forEach(style => acquireStyle(style.content))\n this.ownsSharedStyles = true\n }\n\n return this\n }\n\n mount(parent: Element | ShadowRoot | DocumentFragment | string): this {\n const target = typeof parent === \"string\" ? $(parent) : parent\n if (!target) throw new Error(`mount target not found: ${parent}`)\n if (!this.content) throw new Error(\"render() must be called before mount()\")\n if (this.mountRoot) this.unmount()\n\n const root = this.useShadow && target instanceof Element\n ? target.shadowRoot ?? target.attachShadow({ mode: \"open\" })\n : target\n if (this.useShadow) this.styleEls.forEach(el => root.appendChild(el))\n root.appendChild(this.content)\n this.mountRoot = root\n this.resolveMounted?.()\n return this\n }\n\n unmount(): this {\n if (!this.mountRoot || !this.content || !this.startMarker || !this.endMarker) return this\n\n // move everything between the markers (inclusive) back into the holding\n // fragment - including nodes :if/:each inserted after mounting\n let node: Node | null = this.startMarker\n while (node) {\n const nextNode: Node | null = node.nextSibling\n this.content.appendChild(node)\n if (node === this.endMarker) break\n node = nextNode\n }\n\n this.mountRoot = null\n return this\n }\n\n destroy(): this {\n this.unmount()\n this.fx?.dispose()\n this.fx = null\n this.styleEls.forEach(el => el.parentNode?.removeChild(el))\n this.styleEls = []\n if (this.ownsSharedStyles) {\n this.styles.forEach(style => releaseStyle(style.content))\n this.ownsSharedStyles = false\n }\n this.content = null\n this.startMarker = null\n this.endMarker = null\n this.data = null\n this.resolveMounted = null\n return this\n }\n}\n\nexport const parseComponent = (component: string): Component79 => new Component79(component)\n\n"],"mappings":"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","names":["$","selectorOrEl","selector","$$","$create","tag","attrs","el","name","value","child","elementAttrs","attr","elementToAST","node","text","evalExpr","expr","scope","extras","interpolate","template","_","getByPath","obj","dotKey","acc","key","isPlainData","proto","walkLeaves","path","visit","pathsOverlap","a","b","trackerStack","untracked","fn","$reactive","data","exactListeners","anyListeners","effects","reactiveProxies","notify","listener","effect","dep","makeReactive","proxy","target","receiver","reactive","$on","immediate","$onAny","$effect","run","deps","CONTROL_ATTRS","EACH_PATTERN","createEffectScope","disposers","dispose","bindEvent","modifiers","mods","event","handler","kebabToCamel","c","findComponentKey","normalized","renderNestedComponent","fx","anchor","wrapper","props","current","currentDef","childFx","nextDef","Component79","instance","seed","holder","syncFx","createWithScope","source","renderNode","outerScope","withExpr","componentKey","bindExpr","boundKeys","bound","renderNodes","renderConditional","branches","activeBranch","branchFx","next","branch","defineScopeVar","renderEach","match","itemName","listExpr","keyExpr","_each","_key","itemAttrs","itemNode","entries","list","items","previous","entry","nextEntries","item","index","itemScope","existing","itemFx","nextKeys","prevNode","nodes","fragment","i","textNode","elseifNode","renderComponent","component","VOID_ELEMENTS","SELF_CLOSING_RE","RAW_BLOCK_RE","expandSelfClosingTags","src","chunk","parseComponentString","root","scripts","styles","block","DECLARATION_RE","REACTIVE_LABEL_RE","IMPORT_CALL_RE","REACTIVE_ASSIGN_RE","skipString","start","quote","skipLineComment","end","skipBlockComment","findStatementEnd","depth","ch","transformSetupScript","vars","out","atStatementStart","decl","label","assign","importResource","url","styleRegistry","acquireStyle","content","releaseStyle","SETUP_HELPERS","runSetupScript","code","instanceHelpers","helpers","scriptScope","error","_Component79","__publicField","response","shadow","store","marker","$emit","eventName","payload","resolveMounted","mounted","resolve","$mounted","endMarker","$$self","found","$self","script","body","style","parent","nextNode","parseComponent"]}
1
+ {"version":3,"sources":["../src/jq79.ts"],"sourcesContent":["\nexport const $ = (selectorOrEl: string | Element, selector?: string) => \n typeof selectorOrEl === \"string\"\n ? document.querySelector(selectorOrEl)\n : selectorOrEl.querySelector(selector || \"\")\n\nexport const $$ = (selectorOrEl: string | Element, selector?: string) => Array.from(\n typeof selectorOrEl === \"string\"\n ? document.querySelectorAll(selectorOrEl)\n : selectorOrEl.querySelectorAll(selector || \"\")\n)\n\n// $create(tag, attrs): attrs are set as attributes, except className, which\n// may be a string or an array of class names.\nexport const $create = (tag: string, attrs: Record<string, any> = {}): HTMLElement => {\n const el = document.createElement(tag);\n for (const [name, value] of Object.entries(attrs)) {\n if (name === 'className') {\n el.className = Array.isArray(value) ? value.join(' ') : value;\n } else if (name === 'textContent') {\n el.textContent = value;\n } else if (name === 'children') {\n for (const child of value) {\n el.appendChild(child);\n }\n } else {\n el.setAttribute(name, value);\n }\n }\n return el;\n};\n\ntype TemplateNode = {\n tag: string\n attrs: Record<string, string>\n children: (TemplateNode | string)[]\n}\n\ntype TagBlock = {\n attrs: Record<string, string>\n content: string\n}\n\nconst elementAttrs = (el: Element): Record<string, string> =>\n Object.fromEntries(Array.from(el.attributes).map(attr => [attr.name, attr.value]))\n\nconst elementToAST = (el: Element): TemplateNode => ({\n tag: el.tagName.toLowerCase(),\n attrs: elementAttrs(el),\n children: Array.from(el.childNodes).flatMap((node): (TemplateNode | string)[] => {\n if (node.nodeType === Node.TEXT_NODE) {\n const text = node.textContent?.trim() ?? \"\"\n return text ? [text] : []\n }\n if (node.nodeType === Node.ELEMENT_NODE) {\n return [elementToAST(node as Element)]\n }\n return []\n })\n})\n\n// evaluated with `with` (rather than passing scope keys as positional params)\n// so only the identifiers an expression actually references are read from\n// `scope` - which is what makes dependency tracking in $reactive\n// precise instead of \"read everything up front\". `extras` are passed as\n// function parameters (outside the `with`), so scope keys still win but names\n// like $event resolve when the scope doesn't shadow them\nconst evalExpr = (expr: string, scope: Record<string, any>, extras?: Record<string, any>): any => {\n try {\n return new Function(\"$scope\", ...Object.keys(extras ?? {}), `with ($scope) { return (${expr}); }`)(\n scope,\n ...Object.values(extras ?? {})\n )\n } catch {\n return undefined\n }\n}\n\nconst interpolate = (template: string, scope: Record<string, any>): string =>\n template.replace(/{{\\s*(.+?)\\s*}}/g, (_, expr) => evalExpr(expr, scope) ?? \"\")\n\ntype ChangeListener = (value: any, dotKey: string) => void\ntype AnyChangeListener = (dotKey: string, value: any) => void\ntype ListenerOptions = { immediate?: boolean }\ntype Unsubscribe = () => void\n\ntype ReactiveDeepData<T> = T & {\n $on: (dotKey: string, listener: ChangeListener, options?: ListenerOptions) => Unsubscribe\n $onAny: (listener: AnyChangeListener, options?: ListenerOptions) => Unsubscribe\n // runs `run` immediately, recording every dotKey it reads off this store, then\n // re-runs it whenever a changed dotKey overlaps one of those - see pathsOverlap\n $effect: (run: () => void) => Unsubscribe\n}\n\nconst getByPath = (obj: Record<string, any>, dotKey: string): any =>\n dotKey.split(\".\").reduce((acc, key) => (acc == null ? undefined : acc[key]), obj)\n\n// only plain objects and arrays get deep-wrapped by the reactive store;\n// class instances (Component79, Date, DOM nodes, ...) pass through untouched\n// so their identity, prototypes and internals stay intact\nconst isPlainData = (value: object): boolean => {\n if (Array.isArray(value)) return true\n const proto = Object.getPrototypeOf(value)\n return proto === Object.prototype || proto === null\n}\n\nconst walkLeaves = (obj: Record<string, any>, path: string, visit: (dotKey: string, value: any) => void) => {\n Object.entries(obj).forEach(([key, value]) => {\n const dotKey = path ? `${path}.${key}` : key\n if (value && typeof value === \"object\" && isPlainData(value)) walkLeaves(value, dotKey, visit)\n else visit(dotKey, value)\n })\n}\n\n// true when `a` and `b` sit on the same ancestor/descendant line, e.g.\n// \"user\" & \"user.address.city\" (a change to either affects the other) - false\n// for siblings like \"user.name\" & \"user.age\"\nconst pathsOverlap = (a: string, b: string): boolean =>\n a === b || a.startsWith(`${b}.`) || b.startsWith(`${a}.`)\n\n// active $effect() runs, innermost last - a module-level stack (rather than\n// one per store) so nested effects across stores still nest correctly; reads\n// during makeReactive's `get` trap are attributed to whichever run is on top\nconst trackerStack: Set<string>[] = []\n\n// runs fn with dependency tracking suspended - reads inside it are attributed\n// to a throwaway set instead of the currently running effect\nconst untracked = <T>(fn: () => T): T => {\n trackerStack.push(new Set())\n try {\n return fn()\n } finally {\n trackerStack.pop()\n }\n}\n\ntype Effect = { deps: Set<string>; run: () => void }\n\nexport const $reactive = <T extends Record<string, any>>(data: T): ReactiveDeepData<T> => {\n const exactListeners = new Map<string, Set<ChangeListener>>()\n const anyListeners = new Set<AnyChangeListener>()\n const effects = new Set<Effect>()\n // every proxy this store has ever handed out, so re-assigning an object\n // that's already reactive (e.g. `data.list = [data.list[1], data.list[0]]`)\n // doesn't wrap it a second time - which would hand out a *new* object\n // identity for the same logical item, breaking reference-equality checks\n // like :each's keyed diffing\n const reactiveProxies = new WeakSet<object>()\n\n const notify = (dotKey: string, value: any) => {\n exactListeners.get(dotKey)?.forEach(listener => listener(value, dotKey))\n anyListeners.forEach(listener => listener(dotKey, value))\n effects.forEach(effect => {\n if (Array.from(effect.deps).some(dep => pathsOverlap(dep, dotKey))) effect.run()\n })\n }\n\n const makeReactive = (obj: Record<string, any>, path: string): Record<string, any> => {\n if (reactiveProxies.has(obj)) return obj\n\n Object.entries(obj).forEach(([key, value]) => {\n if (value && typeof value === \"object\" && isPlainData(value)) {\n obj[key] = makeReactive(value, path ? `${path}.${key}` : key)\n }\n })\n\n const proxy = new Proxy(obj, {\n get(target, key, receiver) {\n if (typeof key === \"string\") {\n trackerStack[trackerStack.length - 1]?.add(path ? `${path}.${key}` : key)\n }\n return Reflect.get(target, key, receiver)\n },\n set(target, key: string, value, receiver) {\n // an assignment delegated up the prototype chain from a derived scope\n // (Object.create(store) child, or a wrapping proxy): if the key isn't\n // a real property of this store, honor the receiver so the new binding\n // lands on the derived scope - a scope-local variable, not a store\n // mutation, so no notify. If the key IS a store property, fall through\n // and mutate the store itself regardless of receiver, so assignments\n // like @click=\"count = count + 1\" work from any nested scope\n if (receiver !== proxy && !Object.prototype.hasOwnProperty.call(target, key)) {\n return Reflect.set(target, key, value, receiver)\n }\n\n const dotKey = path ? `${path}.${key}` : key\n if (value && typeof value === \"object\" && isPlainData(value)) {\n value = makeReactive(value, dotKey)\n }\n target[key] = value\n notify(dotKey, value)\n return true\n }\n })\n\n reactiveProxies.add(proxy)\n return proxy\n }\n\n const reactive = makeReactive(data, \"\") as ReactiveDeepData<T>\n\n const $on = (dotKey: string, listener: ChangeListener, { immediate = false }: ListenerOptions = {}): Unsubscribe => {\n if (!exactListeners.has(dotKey)) exactListeners.set(dotKey, new Set())\n exactListeners.get(dotKey)!.add(listener)\n if (immediate) listener(getByPath(reactive, dotKey), dotKey)\n return () => exactListeners.get(dotKey)?.delete(listener)\n }\n\n const $onAny = (listener: AnyChangeListener, { immediate = false }: ListenerOptions = {}): Unsubscribe => {\n anyListeners.add(listener)\n if (immediate) walkLeaves(reactive, \"\", (dotKey, value) => listener(dotKey, value))\n return () => anyListeners.delete(listener)\n }\n\n const $effect = (run: () => void): Unsubscribe => {\n const effect: Effect = {\n deps: new Set(),\n run: () => {\n const deps = new Set<string>()\n trackerStack.push(deps)\n try {\n run()\n } finally {\n trackerStack.pop()\n effect.deps = deps\n }\n },\n }\n effects.add(effect)\n effect.run()\n return () => { effects.delete(effect) }\n }\n\n Object.defineProperty(reactive, \"$on\", { value: $on, enumerable: false })\n Object.defineProperty(reactive, \"$onAny\", { value: $onAny, enumerable: false })\n Object.defineProperty(reactive, \"$effect\", { value: $effect, enumerable: false })\n\n return reactive\n}\n\nconst CONTROL_ATTRS = new Set([\":bind\", \":if\", \":elseif\", \":else\", \":each\", \":key\", \":with\"])\nconst EACH_PATTERN = /^\\s*(\\w+)\\s+in\\s+(.+)$/\n\ntype ConditionalBranch = { expr?: string; node: TemplateNode }\n\n// groups the disposers of every $effect created for one rendered subtree\n// (an :if branch, an :each item, ...) so the whole subtree's bindings can be\n// torn down in one call when that subtree is replaced/removed. `scope.$effect`\n// resolves through the prototype chain up to the root store no matter how\n// many nested :each scopes sit in between (see renderEach's itemScope)\ntype EffectScope = {\n effect: (run: () => void) => void\n // registers an arbitrary cleanup (e.g. destroying a nested component) to\n // run when this subtree is torn down\n onDispose: (fn: Unsubscribe) => void\n dispose: () => void\n}\n\nconst createEffectScope = (scope: Record<string, any>): EffectScope => {\n const disposers: Unsubscribe[] = []\n return {\n effect: run => { disposers.push(scope.$effect(run)) },\n onDispose: fn => { disposers.push(fn) },\n dispose: () => { disposers.splice(0).forEach(dispose => dispose()) },\n }\n}\n\n// @event attributes: @click=\"onClick\", @submit.prevent=\"$event => onSubmit($event)\",\n// or an inline statement like @click=\"count = count + 1\". The expression is\n// evaluated (with `$event` in scope) on every event; if it yields a function,\n// that function is then invoked with the event - so both a handler reference\n// and an inline arrow/statement work. Modifiers after dots: .prevent .stop\n// .self (runtime guards) and .once .capture (addEventListener options)\nconst bindEvent = (el: Element, attr: string, expr: string, scope: Record<string, any>) => {\n const [name, ...modifiers] = attr.slice(1).split(\".\")\n const mods = new Set(modifiers)\n\n el.addEventListener(name, event => {\n if (mods.has(\"self\") && event.target !== el) return\n if (mods.has(\"prevent\")) event.preventDefault()\n if (mods.has(\"stop\")) event.stopPropagation()\n\n const handler = evalExpr(expr, scope, { $event: event })\n if (typeof handler === \"function\") handler.call(el, event)\n }, { once: mods.has(\"once\"), capture: mods.has(\"capture\") })\n}\n\nconst kebabToCamel = (name: string) => name.replace(/-(\\w)/g, (_, c: string) => c.toUpperCase())\n\n// finds the scope variable a template tag refers to. HTML parsing lowercases\n// tag names, so <NestedComponent> arrives as \"nestedcomponent\" and matching is\n// case-insensitive with dashes stripped (<nested-component> works too). Only\n// PascalCase scope keys participate, so ordinary variables named like real\n// elements (title, code, ...) never hijack them\nconst findComponentKey = (scope: Record<string, any>, tag: string): string | null => {\n const normalized = tag.replace(/-/g, \"\").toLowerCase()\n for (let obj: any = scope; obj && obj !== Object.prototype; obj = Object.getPrototypeOf(obj)) {\n for (const key of Object.keys(obj)) {\n if (/^[A-Z]/.test(key) && key.replace(/-/g, \"\").toLowerCase() === normalized) return key\n }\n }\n return null\n}\n\n// <MyComponent :user :title=\"'str'\"></MyComponent> - renders a child\n// component instance at this position. Props: `:name=\"expr\"` evaluates expr\n// in the parent scope (`:name` alone is shorthand for `:name=\"name\"`), plain\n// attributes pass through as literal strings, and kebab-case prop names\n// become camelCase. Props stay live: a parent effect re-evaluates each\n// expression and writes it into the child's store. The component variable is\n// reactive too - while it's undefined (e.g. an `await import(...)` still in\n// flight) nothing renders, and the child appears when it resolves\nconst renderNestedComponent = (key: string, node: TemplateNode, scope: Record<string, any>, fx: EffectScope): Node => {\n const anchor = document.createComment(key)\n const wrapper = document.createDocumentFragment()\n wrapper.appendChild(anchor)\n\n const props: Record<string, string> = {} // prop name -> expression in parent scope\n Object.entries(node.attrs).forEach(([attr, value]) => {\n if (CONTROL_ATTRS.has(attr) || attr.startsWith(\"@\")) return\n if (attr.startsWith(\":\")) {\n const name = kebabToCamel(attr.slice(1))\n props[name] = value || name\n } else {\n props[kebabToCamel(attr)] = JSON.stringify(value)\n }\n })\n\n let current: Component79 | null = null\n let currentDef: Component79 | null = null\n let childFx: EffectScope | null = null\n\n fx.effect(() => {\n const value = evalExpr(key, scope)\n const nextDef = value instanceof Component79 ? value : null\n if (nextDef === currentDef) return\n\n childFx?.dispose()\n childFx = null\n current?.destroy() // detaches its marker range, removing the child's DOM\n current = null\n currentDef = nextDef\n if (!nextDef) return\n\n // a fresh instance per usage site: the definition's parsed parts are\n // shared, but store/effects/DOM are per instance\n const instance = new Component79({ template: nextDef.template, scripts: nextDef.scripts, styles: nextDef.styles })\n const seed = untracked(() =>\n Object.fromEntries(Object.entries(props).map(([name, expr]) => [name, evalExpr(expr, scope)]))\n )\n const holder = document.createDocumentFragment()\n instance.render(seed).mount(holder)\n anchor.parentNode!.insertBefore(holder, anchor.nextSibling)\n\n const syncFx = createEffectScope(scope)\n Object.entries(props).forEach(([name, expr]) => {\n syncFx.effect(() => { (instance.data as Record<string, any>)[name] = evalExpr(expr, scope) })\n })\n\n childFx = syncFx\n current = instance\n })\n\n fx.onDispose(() => {\n childFx?.dispose()\n current?.destroy()\n })\n\n return wrapper\n}\n\n// :with=\"expr\" narrows the scope for an element and its subtree: names\n// resolve against the expression's value first, then fall back to the outer\n// scope. The value is re-evaluated lazily on every name lookup (never\n// snapshotted), so an effect reading through this proxy tracks both the\n// expression's own dependencies and the property it reads - replacing the\n// object or mutating one of its properties re-renders exactly the dependents,\n// without rebuilding the subtree. Assignments to names the object owns write\n// through to it (reactively, if it came from a store); everything else\n// behaves as if the :with weren't there\nconst createWithScope = (expr: string, scope: Record<string, any>): Record<string, any> => {\n const source = (): Record<string, any> | null => {\n const value = evalExpr(expr, scope)\n return value !== null && typeof value === \"object\" ? value : null\n }\n return new Proxy(scope, {\n has(target, key) {\n const obj = source()\n return (obj !== null && Reflect.has(obj, key)) || Reflect.has(target, key)\n },\n get(target, key) {\n const obj = source()\n if (obj !== null && Reflect.has(obj, key)) return obj[key as string]\n return Reflect.get(target, key)\n },\n set(target, key, value) {\n const obj = source()\n if (obj !== null && Reflect.has(obj, key)) {\n obj[key as string] = value\n return true\n }\n return Reflect.set(target, key, value)\n },\n })\n}\n\n// renders a single element node: static attrs, @event listeners, a reactive\n// :bind object, and its (reactive) children. :if/:elseif/:else/:each are\n// handled by renderNodes, which decides *whether*/*how many times* a node is\n// rendered before calling this. Tags matching a PascalCase scope variable\n// render as nested components instead\nconst renderNode = (node: TemplateNode, outerScope: Record<string, any>, fx: EffectScope): Node => {\n // :with applies to the element's own bindings (@events, :bind) and its\n // whole subtree. On a :each element the item scope is already in place, so\n // :with=\"item\" works\n const withExpr = node.attrs[\":with\"]\n const scope = withExpr !== undefined ? createWithScope(withExpr, outerScope) : outerScope\n\n const componentKey = findComponentKey(scope, node.tag)\n if (componentKey) return renderNestedComponent(componentKey, node, scope, fx)\n\n const el = document.createElement(node.tag)\n\n Object.entries(node.attrs).forEach(([key, value]) => {\n if (key.startsWith(\"@\")) bindEvent(el, key, value, scope)\n else if (!CONTROL_ATTRS.has(key)) el.setAttribute(key, value)\n })\n\n const bindExpr = node.attrs[\":bind\"]\n if (bindExpr !== undefined) {\n let boundKeys: string[] = []\n\n fx.effect(() => {\n boundKeys.forEach(key => el.removeAttribute(key))\n const bound = evalExpr(bindExpr, scope)\n boundKeys = bound && typeof bound === \"object\" ? Object.keys(bound) : []\n boundKeys.forEach(key => {\n const value = bound[key]\n if (value != null && value !== false) el.setAttribute(key, String(value))\n })\n })\n }\n\n el.appendChild(renderNodes(node.children, scope, fx))\n\n return el\n}\n\n// a :if/:elseif*/:else? chain sharing one anchor comment so the active branch\n// can be swapped in place without disturbing sibling positions. Only depends\n// on whatever the branch expressions read (e.g. \"score\"), and skips\n// rebuilding entirely when the active branch hasn't actually changed\nconst renderConditional = (branches: ConditionalBranch[], scope: Record<string, any>, fx: EffectScope): Node => {\n const anchor = document.createComment(\"if\")\n const wrapper = document.createDocumentFragment()\n wrapper.appendChild(anchor)\n\n let current: Node | null = null\n let activeBranch: ConditionalBranch | null = null\n let branchFx: EffectScope | null = null\n\n fx.effect(() => {\n const next = branches.find(branch => branch.expr === undefined || evalExpr(branch.expr, scope)) ?? null\n if (next === activeBranch) return\n\n branchFx?.dispose()\n if (current) current.parentNode?.removeChild(current)\n current = null\n activeBranch = next\n if (!next) return\n\n branchFx = createEffectScope(scope)\n current = renderNode(next.node, scope, branchFx)\n anchor.parentNode!.insertBefore(current, anchor.nextSibling)\n })\n\n return wrapper\n}\n\n// defines a loop-local binding directly as `scope`'s own property. Plain\n// assignment (scope[key] = value) would only do this if the key isn't\n// already own on `scope` *or anywhere up its prototype chain* - if it isn't,\n// JS delegates the [[Set]] to whatever's up there, which for us is another\n// reactive proxy's `set` trap: it would wrap `value` as if it were a genuine\n// store mutation and fire a bogus notify() under a name (e.g. \"item\") shared\n// by every unrelated item in every :each on the page. defineProperty always\n// writes to `scope` itself, never delegating, so this can't happen\nconst defineScopeVar = (scope: Record<string, any>, key: string, value: any) => {\n Object.defineProperty(scope, key, { value, writable: true, enumerable: true, configurable: true })\n}\n\ntype EachEntry = { key: any; item: any; scope: Record<string, any>; node: Node; fx: EffectScope }\n\n// :each=\"item in items\", optionally keyed with :key=\"expr\". Only depends on\n// the list expression itself (e.g. \"items\"), and on each run diffs by key:\n// unchanged items (same key, same item reference) keep their DOM/effects,\n// changed/added ones are (re)rendered, removed ones are disposed. Without\n// :key, position is used as the key, so reordering rebuilds every item after\n// the first change - add :key for anything that gets reordered or filtered.\n// Each item gets its own scope via Object.create(scope), so `item`/`$index`\n// shadow same-named outer bindings without copying the parent scope's keys\nconst renderEach = (node: TemplateNode, scope: Record<string, any>, fx: EffectScope): Node => {\n const match = node.attrs[\":each\"].match(EACH_PATTERN)\n if (!match) return document.createComment(`invalid :each expression \"${node.attrs[\":each\"]}\"`)\n\n const [, itemName, listExpr] = match\n const keyExpr = node.attrs[\":key\"]\n const { [\":each\"]: _each, [\":key\"]: _key, ...itemAttrs } = node.attrs\n const itemNode: TemplateNode = { ...node, attrs: itemAttrs }\n\n const anchor = document.createComment(\"each\")\n const wrapper = document.createDocumentFragment()\n wrapper.appendChild(anchor)\n\n let entries: EachEntry[] = []\n\n fx.effect(() => {\n const list = evalExpr(listExpr, scope)\n const items = Array.isArray(list) ? list : []\n const previous = new Map(entries.map(entry => [entry.key, entry]))\n\n const nextEntries = items.map((item, index): EachEntry => {\n const itemScope = Object.create(scope)\n defineScopeVar(itemScope, itemName, item)\n defineScopeVar(itemScope, \"$index\", index)\n const key = keyExpr !== undefined ? evalExpr(keyExpr, itemScope) : index\n const existing = previous.get(key)\n\n if (existing && Object.is(existing.item, item)) {\n defineScopeVar(existing.scope, \"$index\", index)\n return existing\n }\n\n existing?.fx.dispose()\n existing?.node.parentNode?.removeChild(existing.node)\n\n const itemFx = createEffectScope(scope)\n return { key, item, scope: itemScope, fx: itemFx, node: renderNode(itemNode, itemScope, itemFx) }\n })\n\n const nextKeys = new Set(nextEntries.map(entry => entry.key))\n entries.forEach(entry => {\n if (!nextKeys.has(entry.key)) {\n entry.fx.dispose()\n entry.node.parentNode?.removeChild(entry.node)\n }\n })\n\n let prevNode: Node = anchor\n nextEntries.forEach(entry => {\n if (prevNode.nextSibling !== entry.node) anchor.parentNode!.insertBefore(entry.node, prevNode.nextSibling)\n prevNode = entry.node\n })\n\n entries = nextEntries\n })\n\n return wrapper\n}\n\n// renders a list of sibling template nodes (text + elements), grouping\n// consecutive :if/:elseif/:else nodes into a single conditional block\nconst renderNodes = (nodes: (TemplateNode | string)[], scope: Record<string, any>, fx: EffectScope): DocumentFragment => {\n const fragment = document.createDocumentFragment()\n let i = 0\n\n while (i < nodes.length) {\n const node = nodes[i]\n\n if (typeof node === \"string\") {\n const textNode = document.createTextNode(\"\")\n fx.effect(() => { textNode.textContent = interpolate(node, scope) })\n fragment.appendChild(textNode)\n i++\n continue\n }\n\n if (\":each\" in node.attrs) {\n fragment.appendChild(renderEach(node, scope, fx))\n i++\n continue\n }\n\n if (\":if\" in node.attrs) {\n const branches: ConditionalBranch[] = [{ expr: node.attrs[\":if\"], node }]\n i++\n while (i < nodes.length && typeof nodes[i] !== \"string\" && \":elseif\" in (nodes[i] as TemplateNode).attrs) {\n const elseifNode = nodes[i] as TemplateNode\n branches.push({ expr: elseifNode.attrs[\":elseif\"], node: elseifNode })\n i++\n }\n if (i < nodes.length && typeof nodes[i] !== \"string\" && \":else\" in (nodes[i] as TemplateNode).attrs) {\n branches.push({ node: nodes[i] as TemplateNode })\n i++\n }\n\n fragment.appendChild(renderConditional(branches, scope, fx))\n continue\n }\n\n fragment.appendChild(renderNode(node, scope, fx))\n i++\n }\n\n return fragment\n}\n\nexport const renderComponent = (component: Component79, data: ReactiveDeepData<Record<string, any>>): Node =>\n renderNodes(component.template, data, createEffectScope(data))\n\ntype ComponentParts = {\n template: TemplateNode[]\n scripts: TagBlock[]\n styles: TagBlock[]\n}\n\nconst VOID_ELEMENTS = new Set([\n \"area\", \"base\", \"br\", \"col\", \"embed\", \"hr\", \"img\", \"input\",\n \"link\", \"meta\", \"param\", \"source\", \"track\", \"wbr\",\n])\n\n// a self-closing tag with its attributes; quoted attribute values are matched\n// as whole chunks so a \"/>\" inside one doesn't end the tag early\nconst SELF_CLOSING_RE = /<([A-Za-z][\\w-]*)((?:\"[^\"]*\"|'[^']*'|[^>\"'])*?)\\/>/g\nconst RAW_BLOCK_RE = /(<script[\\s\\S]*?<\\/script\\s*>|<style[\\s\\S]*?<\\/style\\s*>)/gi\n\n// expands self-closing tags (<MyComponent />, <div />) into explicit\n// open+close pairs BEFORE DOM parsing. The HTML parser ignores the slash and\n// would treat them as unclosed, swallowing the following siblings. Void\n// elements keep their native behavior, and <script>/<style> contents are\n// passed through untouched so code inside them is never rewritten\nconst expandSelfClosingTags = (src: string): string =>\n src\n .split(RAW_BLOCK_RE)\n .map((chunk, i) =>\n i % 2 === 1 // odd chunks are the captured script/style blocks\n ? chunk\n : chunk.replace(SELF_CLOSING_RE, (match, tag: string, attrs: string) =>\n VOID_ELEMENTS.has(tag.toLowerCase()) ? match : `<${tag}${attrs}></${tag}>`\n )\n )\n .join(\"\")\n\n// converts a string of HTML into an AST representation of the component:\n// - template: the non-script/style top-level elements, as TemplateNodes\n// - scripts/styles: { attrs, content } blocks in source order\nconst parseComponentString = (component: string): ComponentParts => {\n // example\n // <script :setup=\"{ fname, lname }\">\n // const fullName = `${fname} ${lname}`\n // </script>\n //\n // <div :bind=\"{ fullName }\"></div>\n // <div class=\"full-name\">\n // {{ fullName }}\n // </div>\n //\n // <style>\n // .full-name {\n // color: red;\n // }\n // </style>\n\n // parsed as the content of a <template> so leading <script>/<style> tags\n // aren't reparented into <head> by the HTML parser\n const parsedDOM = new DOMParser().parseFromString(`<template>${expandSelfClosingTags(component)}</template>`, \"text/html\")\n const root = parsedDOM.querySelector(\"template\") as HTMLTemplateElement\n\n const scripts: TagBlock[] = []\n const styles: TagBlock[] = []\n const template: TemplateNode[] = []\n\n Array.from(root.content.children).forEach(el => {\n const block = { attrs: elementAttrs(el), content: el.textContent ?? \"\" }\n\n if (el.tagName === \"SCRIPT\") scripts.push(block)\n else if (el.tagName === \"STYLE\") styles.push(block)\n else template.push(elementToAST(el))\n })\n\n return { template, scripts, styles }\n}\n\n// ---------------------------------------------------------------------------\n// :setup script transform\n//\n// setup scripts are written like Svelte components:\n//\n// let firstName = null\n// $: fullName = `${firstName} ${lastName}`\n// fetchUser().then(user => { firstName = user.firstName })\n//\n// and are executed inside `with ($scope)` against the component's reactive\n// store, so plain assignments (even from async callbacks) go through the\n// proxy's set trap and re-render whatever depends on them. To make that work\n// the source is lightly rewritten - no full JS parser, just a scanner that is\n// string/comment-aware and only touches code at brace/paren depth 0:\n// - `let/var/const x = ...` at the top level loses its keyword, becoming a\n// scope assignment (the name is pre-declared on the store so the `with`\n// lookup resolves it)\n// - `$: x = expr` becomes `$__effect(() => { x = expr })`, re-running when a\n// dependency read inside expr changes ($__effect is deliberately NOT a\n// property of the scope, so `with` falls through to the function parameter)\n// ---------------------------------------------------------------------------\n\ntype SetupTransform = { vars: string[]; code: string }\n\nconst DECLARATION_RE = /(?:let|var|const)\\s+([A-Za-z_$][\\w$]*)/y\nconst REACTIVE_LABEL_RE = /\\$:\\s*/y\nconst IMPORT_CALL_RE = /import(?=\\s*\\()/y\nconst REACTIVE_ASSIGN_RE = /\\$:\\s*([A-Za-z_$][\\w$]*)\\s*=(?!=)/y\n\nconst skipString = (src: string, start: number): number => {\n const quote = src[start]\n let i = start + 1\n while (i < src.length) {\n if (src[i] === \"\\\\\") { i += 2; continue }\n if (src[i] === quote) return i + 1\n i++\n }\n return src.length\n}\n\nconst skipLineComment = (src: string, start: number): number => {\n const end = src.indexOf(\"\\n\", start)\n return end === -1 ? src.length : end\n}\n\nconst skipBlockComment = (src: string, start: number): number => {\n const end = src.indexOf(\"*/\", start + 2)\n return end === -1 ? src.length : end + 2\n}\n\n// end of a statement starting at `start`: the first newline or `;` that isn't\n// inside a string/comment or unbalanced brackets, so multi-line RHS like a\n// wrapped function call or template literal stays in one piece\nconst findStatementEnd = (src: string, start: number): number => {\n let depth = 0\n let i = start\n while (i < src.length) {\n const ch = src[i]\n if (ch === \"'\" || ch === '\"' || ch === \"`\") { i = skipString(src, i); continue }\n if (ch === \"/\" && src[i + 1] === \"/\") { i = skipLineComment(src, i); continue }\n if (ch === \"/\" && src[i + 1] === \"*\") { i = skipBlockComment(src, i); continue }\n if (\"([{\".includes(ch)) depth++\n else if (\")]}\".includes(ch)) depth--\n else if (depth <= 0 && (ch === \"\\n\" || ch === \";\")) return i\n i++\n }\n return src.length\n}\n\nconst transformSetupScript = (src: string): SetupTransform => {\n const vars: string[] = []\n let out = \"\"\n let i = 0\n let depth = 0\n let atStatementStart = true\n\n while (i < src.length) {\n const ch = src[i]\n const next = src[i + 1]\n\n if (ch === \"'\" || ch === '\"' || ch === \"`\") {\n const end = skipString(src, i)\n out += src.slice(i, end)\n i = end\n atStatementStart = false\n continue\n }\n if (ch === \"/\" && (next === \"/\" || next === \"*\")) {\n const end = next === \"/\" ? skipLineComment(src, i) : skipBlockComment(src, i)\n out += src.slice(i, end)\n i = end\n continue\n }\n\n // `import(...)` is a keyword form, so it can't be intercepted through the\n // scope - rewrite the identifier to the injected $__import (which loads\n // .html URLs as components via Component79.fetch and delegates the rest to\n // native import). The `(` is left for the scanner so depth stays balanced\n if (ch === \"i\" && (i === 0 || !/[\\w$.]/.test(src[i - 1]))) {\n IMPORT_CALL_RE.lastIndex = i\n if (IMPORT_CALL_RE.test(src)) {\n out += \"$__import\"\n i += \"import\".length\n atStatementStart = false\n continue\n }\n }\n\n if (depth === 0 && atStatementStart) {\n DECLARATION_RE.lastIndex = i\n const decl = DECLARATION_RE.exec(src)\n if (decl) {\n vars.push(decl[1])\n out += decl[1]\n i += decl[0].length\n atStatementStart = false\n continue\n }\n\n REACTIVE_LABEL_RE.lastIndex = i\n const label = REACTIVE_LABEL_RE.exec(src)\n if (label) {\n REACTIVE_ASSIGN_RE.lastIndex = i\n const assign = REACTIVE_ASSIGN_RE.exec(src)\n if (assign) vars.push(assign[1])\n const start = i + label[0].length\n const end = findStatementEnd(src, start)\n out += `$__effect(() => { ${src.slice(start, end)} });`\n i = end\n continue\n }\n }\n\n if (\"([{\".includes(ch)) depth++\n else if (\")]}\".includes(ch)) depth = Math.max(0, depth - 1)\n\n if (ch === \"\\n\" || ch === \";\" || ch === \"}\") atStatementStart = true\n else if (!/\\s/.test(ch)) atStatementStart = false\n\n out += ch\n i++\n }\n\n return { vars, code: out }\n}\n\n// loads .html URLs as components, delegating anything else to native import()\nconst importResource = (url: string): Promise<any> =>\n /\\.html?([?#]|$)/.test(url) ? Component79.fetch(url) : import(url)\n\n// document.head styles are shared by content and refcounted, so N instances\n// of the same component (e.g. one per :each item) inject a single <style> tag\n// that goes away when the last instance is destroyed\nconst styleRegistry = new Map<string, { el: HTMLStyleElement; count: number }>()\n\nconst acquireStyle = (content: string) => {\n let entry = styleRegistry.get(content)\n if (!entry) {\n const el = document.createElement(\"style\")\n el.textContent = content\n document.head.appendChild(el)\n entry = { el, count: 0 }\n styleRegistry.set(content, entry)\n }\n entry.count++\n}\n\nconst releaseStyle = (content: string) => {\n const entry = styleRegistry.get(content)\n if (entry && --entry.count <= 0) {\n entry.el.remove()\n styleRegistry.delete(content)\n }\n}\n\n// library helpers injected into setup scripts. They behave like extra\n// globals: a same-named scope property (render data or a top-level\n// declaration) shadows them\nconst SETUP_HELPERS: Record<string, any> = { $, $$, $create, $reactive }\n\n// scripts run inside `with (scriptScope)`, where scriptScope's `has` trap\n// claims ownership of every name that is neither a real global, an injected\n// library helper, nor one of the internal helpers. This makes `with` route ALL\n// other reads/writes through the reactive store - even bare assignments to\n// names never declared with let/const, which would otherwise leak onto\n// globalThis - while `console`, `Promise`, `fetch`, etc. still resolve\n// normally. get/set are deliberately not trapped: they default-forward to\n// `scope` (the reactive proxy), preserving tracking and notify.\n// The body is wrapped in an async IIFE so top-level `await` works: everything\n// up to the first await runs synchronously (before the template renders), and\n// later assignments update the DOM reactively when they happen\nconst runSetupScript = (code: string, scope: Record<string, any>, effect: (run: () => void) => void, instanceHelpers: Record<string, any> = {}) => {\n // instanceHelpers are per-component-instance additions (e.g. $emit, which\n // is bound to this instance's DOM position)\n const helpers = { ...SETUP_HELPERS, ...instanceHelpers }\n const scriptScope = new Proxy(scope, {\n has: (target, key) =>\n key !== \"$__effect\" && key !== \"$__import\" &&\n (Reflect.has(target, key) || !(key in globalThis) && !(key in helpers)),\n })\n const result: Promise<void> = new Function(\n \"$scope\", \"$__effect\", \"$__import\", ...Object.keys(helpers),\n `return (async () => { with ($scope) { ${code} } })()`\n )(scriptScope, effect, importResource, ...Object.values(helpers))\n result.catch(error => console.error(\"jq79: error in :setup script\", error))\n}\n\ntype EmitListener = (event: CustomEvent, payload: any) => void\n\n// a parsed single-file component. Typical lifecycle:\n//\n// const jq79 = new Component79(src) // or await Component79.fetch(url)\n// jq79.on(\"submit\", (e, payload) => {}) // hear this instance's $emit events\n// jq79.mount(\"#app\", { user }) // render (reactive DOM, scripts, styles) + attach\n// ... // (mountShadow mounts into a shadow root)\n// jq79.detach() // detach, keeping state - mount() re-attaches\n// .destroy() // dispose effects and remove styles\nexport class Component79 {\n template: TemplateNode[]\n scripts: TagBlock[]\n styles: TagBlock[]\n\n data: ReactiveDeepData<Record<string, any>> | null = null\n\n private fx: EffectScope | null = null\n // holds the rendered nodes while detached; anchors keep this fragment as\n // their parentNode, so effects keep the (detached) DOM up to date and a\n // later mount() shows current state\n private content: DocumentFragment | null = null\n // markers bracketing the component's output so detach() can collect nodes\n // that :if/:each inserted next to the anchors after mounting\n private startMarker: Comment | null = null\n private endMarker: Comment | null = null\n // shadow rendering keeps per-instance <style> elements; head rendering goes\n // through the shared refcounted styleRegistry instead\n private styleEls: HTMLStyleElement[] = []\n private ownsSharedStyles = false\n private useShadow = false\n private mountRoot: Element | ShadowRoot | DocumentFragment | null = null\n // settles the $mounted() promise handed to this render generation's scripts\n private resolveMounted: (() => void) | null = null\n // instance-level listeners for $emit events, registered with on(). Kept\n // outside the render generation so they survive re-render and destroy()\n private emitListeners = new Map<string, Set<EmitListener>>()\n\n constructor(src: string | ComponentParts) {\n const { template, scripts, styles } = typeof src === \"string\" ? parseComponentString(src) : src\n this.template = template\n this.scripts = scripts\n this.styles = styles\n }\n\n static async fetch(url: string): Promise<Component79> {\n const response = await fetch(url)\n if (!response.ok) throw new Error(`failed to fetch component from ${url}: ${response.status}`)\n return new Component79(await response.text())\n }\n\n // subscribes to this instance's $emit events, on top of the DOM CustomEvent\n // dispatch - so it hears emits even while the component is detached (where\n // the event has no ancestors to bubble to). Chainable; can be called before\n // render()\n on(eventName: string, listener: EmitListener): this {\n if (!this.emitListeners.has(eventName)) this.emitListeners.set(eventName, new Set())\n this.emitListeners.get(eventName)!.add(listener)\n return this\n }\n\n off(eventName: string, listener: EmitListener): this {\n this.emitListeners.get(eventName)?.delete(listener)\n return this\n }\n\n render(data: Record<string, any> = {}): this {\n return this.renderWith(data, false)\n }\n\n // like render(), but styles are injected into a shadow root attached to the\n // mount target instead of document.head, so they don't leak globally\n renderShadow(data: Record<string, any> = {}): this {\n return this.renderWith(data, true)\n }\n\n private renderWith(data: Record<string, any>, shadow: boolean): this {\n this.destroy()\n\n const store = $reactive({ ...data })\n const fx = createEffectScope(store)\n this.data = store\n this.fx = fx\n this.useShadow = shadow\n\n this.startMarker = document.createComment(\"jq79\")\n this.endMarker = document.createComment(\"/jq79\")\n\n // $emit dispatches a bubbling CustomEvent from this instance's start\n // marker, so once mounted it travels up the real DOM and parents can\n // listen on any ancestor (or with @event-name on a wrapping element).\n // Captures the marker rather than `this` so a later re-render's scripts\n // can't dispatch from the wrong generation - the same guard keeps stale\n // generations from reaching the instance's on() listeners\n const marker = this.startMarker\n const $emit = (eventName: string, payload?: any): boolean => {\n const event = new CustomEvent(eventName, { detail: payload, bubbles: true, composed: true })\n const result = marker.dispatchEvent(event)\n if (marker === this.startMarker) {\n this.emitListeners.get(eventName)?.forEach(listener => listener(event, payload))\n }\n return result\n }\n\n // `await $mounted()` suspends a setup script until mount() attaches the\n // component, so code below it can querySelector its own DOM. Resumption\n // is a microtask, so in the usual synchronous render().mount() flow the\n // whole tree (nested components included) is in the document before the\n // script continues. If this instance is never mounted, the promise stays\n // pending and the script's tail never runs\n let resolveMounted!: () => void\n const mounted = new Promise<void>(resolve => { resolveMounted = resolve })\n this.resolveMounted = resolveMounted\n const $mounted = () => mounted\n\n // $self / $$self mirror $ / $$ but only search this instance's own\n // output: the sibling nodes between its markers. They work detached too\n // (the holding fragment keeps markers and rendered nodes as siblings),\n // though the template renders after the scripts run, so they only find\n // something from post-await code or callbacks\n const endMarker = this.endMarker\n const $$self = (selector: string): Element[] => {\n const found: Element[] = []\n for (let node: Node | null = marker.nextSibling; node && node !== endMarker; node = node.nextSibling) {\n if (node instanceof Element) {\n if (node.matches(selector)) found.push(node)\n found.push(...Array.from(node.querySelectorAll(selector)))\n }\n }\n return found\n }\n const $self = (selector: string): Element | null => $$self(selector)[0] ?? null\n\n // scripts run before the template renders so `$:` values are initialized;\n // a `:mounted` script defers entirely until mount() instead\n this.scripts.forEach(script => {\n const { vars, code } = transformSetupScript(script.content)\n // pre-declare script vars on the store so `with` resolves assignments\n // to them (and reads of them) through the reactive proxy\n vars.forEach(name => { if (!(name in store)) (store as any)[name] = undefined })\n const body = \":mounted\" in script.attrs ? `await $mounted();\\n${code}` : code\n runSetupScript(body, store, fx.effect, { $emit, $mounted, $self, $$self })\n })\n\n const content = document.createDocumentFragment()\n content.append(this.startMarker, renderNodes(this.template, store, fx), this.endMarker)\n this.content = content\n\n if (shadow) {\n this.styleEls = this.styles.map(style => {\n const el = document.createElement(\"style\")\n el.textContent = style.content\n return el\n })\n } else {\n this.styles.forEach(style => acquireStyle(style.content))\n this.ownsSharedStyles = true\n }\n\n return this\n }\n\n // renders (when needed) and attaches in one call: the component is rendered\n // on the first mount, and re-rendered fresh whenever `data` is passed.\n // mount(el) on an already-rendered component just re-attaches, keeping its\n // state - the detach()/mount() round trip. Rendering here keeps whichever\n // style mode was last used (document.head unless renderShadow/mountShadow\n // chose a shadow root)\n mount(parent: Element | ShadowRoot | DocumentFragment | string, data?: Record<string, any>): this {\n const target = typeof parent === \"string\" ? $(parent) : parent\n if (!target) throw new Error(`mount target not found: ${parent}`)\n if (!this.content || data !== undefined) this.renderWith(data ?? {}, this.useShadow)\n return this.attach(target)\n }\n\n // like mount(), but renders with styles scoped to a shadow root on the\n // target instead of document.head\n mountShadow(parent: Element | ShadowRoot | DocumentFragment | string, data?: Record<string, any>): this {\n const target = typeof parent === \"string\" ? $(parent) : parent\n if (!target) throw new Error(`mount target not found: ${parent}`)\n if (!this.content || data !== undefined || !this.useShadow) this.renderWith(data ?? {}, true)\n return this.attach(target)\n }\n\n private attach(target: Element | ShadowRoot | DocumentFragment): this {\n if (this.mountRoot) this.detach()\n\n const root = this.useShadow && target instanceof Element\n ? target.shadowRoot ?? target.attachShadow({ mode: \"open\" })\n : target\n if (this.useShadow) this.styleEls.forEach(el => root.appendChild(el))\n root.appendChild(this.content!)\n this.mountRoot = root\n this.resolveMounted?.()\n return this\n }\n\n // detaches from the DOM while keeping all state; a later mount() re-attaches\n // with any updates that happened while detached already applied\n detach(): this {\n if (!this.mountRoot || !this.content || !this.startMarker || !this.endMarker) return this\n\n // move everything between the markers (inclusive) back into the holding\n // fragment - including nodes :if/:each inserted after mounting\n let node: Node | null = this.startMarker\n while (node) {\n const nextNode: Node | null = node.nextSibling\n this.content.appendChild(node)\n if (node === this.endMarker) break\n node = nextNode\n }\n\n this.mountRoot = null\n return this\n }\n\n destroy(): this {\n this.detach()\n this.fx?.dispose()\n this.fx = null\n this.styleEls.forEach(el => el.parentNode?.removeChild(el))\n this.styleEls = []\n if (this.ownsSharedStyles) {\n this.styles.forEach(style => releaseStyle(style.content))\n this.ownsSharedStyles = false\n }\n this.content = null\n this.startMarker = null\n this.endMarker = null\n this.data = null\n this.resolveMounted = null\n return this\n }\n}\n\nexport const parseComponent = (component: string): Component79 => new Component79(component)\n\n"],"mappings":"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","names":["$","selectorOrEl","selector","$$","$create","tag","attrs","el","name","value","child","elementAttrs","attr","elementToAST","node","text","evalExpr","expr","scope","extras","interpolate","template","_","getByPath","obj","dotKey","acc","key","isPlainData","proto","walkLeaves","path","visit","pathsOverlap","a","b","trackerStack","untracked","fn","$reactive","data","exactListeners","anyListeners","effects","reactiveProxies","notify","listener","effect","dep","makeReactive","proxy","target","receiver","reactive","$on","immediate","$onAny","$effect","run","deps","CONTROL_ATTRS","EACH_PATTERN","createEffectScope","disposers","dispose","bindEvent","modifiers","mods","event","handler","kebabToCamel","c","findComponentKey","normalized","renderNestedComponent","fx","anchor","wrapper","props","current","currentDef","childFx","nextDef","Component79","instance","seed","holder","syncFx","createWithScope","source","renderNode","outerScope","withExpr","componentKey","bindExpr","boundKeys","bound","renderNodes","renderConditional","branches","activeBranch","branchFx","next","branch","defineScopeVar","renderEach","match","itemName","listExpr","keyExpr","_each","_key","itemAttrs","itemNode","entries","list","items","previous","entry","nextEntries","item","index","itemScope","existing","itemFx","nextKeys","prevNode","nodes","fragment","i","textNode","elseifNode","renderComponent","component","VOID_ELEMENTS","SELF_CLOSING_RE","RAW_BLOCK_RE","expandSelfClosingTags","src","chunk","parseComponentString","root","scripts","styles","block","DECLARATION_RE","REACTIVE_LABEL_RE","IMPORT_CALL_RE","REACTIVE_ASSIGN_RE","skipString","start","quote","skipLineComment","end","skipBlockComment","findStatementEnd","depth","ch","transformSetupScript","vars","out","atStatementStart","decl","label","assign","importResource","url","styleRegistry","acquireStyle","content","releaseStyle","SETUP_HELPERS","runSetupScript","code","instanceHelpers","helpers","scriptScope","error","_Component79","__publicField","response","eventName","shadow","store","marker","$emit","payload","result","resolveMounted","mounted","resolve","$mounted","endMarker","$$self","found","$self","script","body","style","parent","nextNode","parseComponent"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jq79",
3
- "version": "0.1.6",
3
+ "version": "0.2.0",
4
4
  "description": "Mini reactive component library: single-file components, Svelte-style setup scripts, fine-grained proxy reactivity. One file, zero dependencies.",
5
5
  "keywords": [
6
6
  "reactive",
package/src/jq79.ts CHANGED
@@ -337,7 +337,7 @@ const renderNestedComponent = (key: string, node: TemplateNode, scope: Record<st
337
337
 
338
338
  childFx?.dispose()
339
339
  childFx = null
340
- current?.destroy() // unmounts its marker range, removing the child's DOM
340
+ current?.destroy() // detaches its marker range, removing the child's DOM
341
341
  current = null
342
342
  currentDef = nextDef
343
343
  if (!nextDef) return
@@ -888,13 +888,15 @@ const runSetupScript = (code: string, scope: Record<string, any>, effect: (run:
888
888
  result.catch(error => console.error("jq79: error in :setup script", error))
889
889
  }
890
890
 
891
+ type EmitListener = (event: CustomEvent, payload: any) => void
892
+
891
893
  // a parsed single-file component. Typical lifecycle:
892
894
  //
893
895
  // const jq79 = new Component79(src) // or await Component79.fetch(url)
894
- // jq79.render({ user }) // build reactive DOM, run scripts, inject styles
895
- // .mount("#app") // attach (renderShadow mounts into a shadow root)
896
- // ...
897
- // jq79.unmount() // detach, keeping state - mount() re-attaches
896
+ // jq79.on("submit", (e, payload) => {}) // hear this instance's $emit events
897
+ // jq79.mount("#app", { user }) // render (reactive DOM, scripts, styles) + attach
898
+ // ... // (mountShadow mounts into a shadow root)
899
+ // jq79.detach() // detach, keeping state - mount() re-attaches
898
900
  // .destroy() // dispose effects and remove styles
899
901
  export class Component79 {
900
902
  template: TemplateNode[]
@@ -904,11 +906,11 @@ export class Component79 {
904
906
  data: ReactiveDeepData<Record<string, any>> | null = null
905
907
 
906
908
  private fx: EffectScope | null = null
907
- // holds the rendered nodes while unmounted; anchors keep this fragment as
909
+ // holds the rendered nodes while detached; anchors keep this fragment as
908
910
  // their parentNode, so effects keep the (detached) DOM up to date and a
909
911
  // later mount() shows current state
910
912
  private content: DocumentFragment | null = null
911
- // markers bracketing the component's output so unmount() can collect nodes
913
+ // markers bracketing the component's output so detach() can collect nodes
912
914
  // that :if/:each inserted next to the anchors after mounting
913
915
  private startMarker: Comment | null = null
914
916
  private endMarker: Comment | null = null
@@ -920,6 +922,9 @@ export class Component79 {
920
922
  private mountRoot: Element | ShadowRoot | DocumentFragment | null = null
921
923
  // settles the $mounted() promise handed to this render generation's scripts
922
924
  private resolveMounted: (() => void) | null = null
925
+ // instance-level listeners for $emit events, registered with on(). Kept
926
+ // outside the render generation so they survive re-render and destroy()
927
+ private emitListeners = new Map<string, Set<EmitListener>>()
923
928
 
924
929
  constructor(src: string | ComponentParts) {
925
930
  const { template, scripts, styles } = typeof src === "string" ? parseComponentString(src) : src
@@ -934,6 +939,21 @@ export class Component79 {
934
939
  return new Component79(await response.text())
935
940
  }
936
941
 
942
+ // subscribes to this instance's $emit events, on top of the DOM CustomEvent
943
+ // dispatch - so it hears emits even while the component is detached (where
944
+ // the event has no ancestors to bubble to). Chainable; can be called before
945
+ // render()
946
+ on(eventName: string, listener: EmitListener): this {
947
+ if (!this.emitListeners.has(eventName)) this.emitListeners.set(eventName, new Set())
948
+ this.emitListeners.get(eventName)!.add(listener)
949
+ return this
950
+ }
951
+
952
+ off(eventName: string, listener: EmitListener): this {
953
+ this.emitListeners.get(eventName)?.delete(listener)
954
+ return this
955
+ }
956
+
937
957
  render(data: Record<string, any> = {}): this {
938
958
  return this.renderWith(data, false)
939
959
  }
@@ -960,10 +980,17 @@ export class Component79 {
960
980
  // marker, so once mounted it travels up the real DOM and parents can
961
981
  // listen on any ancestor (or with @event-name on a wrapping element).
962
982
  // Captures the marker rather than `this` so a later re-render's scripts
963
- // can't dispatch from the wrong generation
983
+ // can't dispatch from the wrong generation - the same guard keeps stale
984
+ // generations from reaching the instance's on() listeners
964
985
  const marker = this.startMarker
965
- const $emit = (eventName: string, payload?: any): boolean =>
966
- marker.dispatchEvent(new CustomEvent(eventName, { detail: payload, bubbles: true, composed: true }))
986
+ const $emit = (eventName: string, payload?: any): boolean => {
987
+ const event = new CustomEvent(eventName, { detail: payload, bubbles: true, composed: true })
988
+ const result = marker.dispatchEvent(event)
989
+ if (marker === this.startMarker) {
990
+ this.emitListeners.get(eventName)?.forEach(listener => listener(event, payload))
991
+ }
992
+ return result
993
+ }
967
994
 
968
995
  // `await $mounted()` suspends a setup script until mount() attaches the
969
996
  // component, so code below it can querySelector its own DOM. Resumption
@@ -1023,23 +1050,44 @@ export class Component79 {
1023
1050
  return this
1024
1051
  }
1025
1052
 
1026
- mount(parent: Element | ShadowRoot | DocumentFragment | string): this {
1053
+ // renders (when needed) and attaches in one call: the component is rendered
1054
+ // on the first mount, and re-rendered fresh whenever `data` is passed.
1055
+ // mount(el) on an already-rendered component just re-attaches, keeping its
1056
+ // state - the detach()/mount() round trip. Rendering here keeps whichever
1057
+ // style mode was last used (document.head unless renderShadow/mountShadow
1058
+ // chose a shadow root)
1059
+ mount(parent: Element | ShadowRoot | DocumentFragment | string, data?: Record<string, any>): this {
1027
1060
  const target = typeof parent === "string" ? $(parent) : parent
1028
1061
  if (!target) throw new Error(`mount target not found: ${parent}`)
1029
- if (!this.content) throw new Error("render() must be called before mount()")
1030
- if (this.mountRoot) this.unmount()
1062
+ if (!this.content || data !== undefined) this.renderWith(data ?? {}, this.useShadow)
1063
+ return this.attach(target)
1064
+ }
1065
+
1066
+ // like mount(), but renders with styles scoped to a shadow root on the
1067
+ // target instead of document.head
1068
+ mountShadow(parent: Element | ShadowRoot | DocumentFragment | string, data?: Record<string, any>): this {
1069
+ const target = typeof parent === "string" ? $(parent) : parent
1070
+ if (!target) throw new Error(`mount target not found: ${parent}`)
1071
+ if (!this.content || data !== undefined || !this.useShadow) this.renderWith(data ?? {}, true)
1072
+ return this.attach(target)
1073
+ }
1074
+
1075
+ private attach(target: Element | ShadowRoot | DocumentFragment): this {
1076
+ if (this.mountRoot) this.detach()
1031
1077
 
1032
1078
  const root = this.useShadow && target instanceof Element
1033
1079
  ? target.shadowRoot ?? target.attachShadow({ mode: "open" })
1034
1080
  : target
1035
1081
  if (this.useShadow) this.styleEls.forEach(el => root.appendChild(el))
1036
- root.appendChild(this.content)
1082
+ root.appendChild(this.content!)
1037
1083
  this.mountRoot = root
1038
1084
  this.resolveMounted?.()
1039
1085
  return this
1040
1086
  }
1041
1087
 
1042
- unmount(): this {
1088
+ // detaches from the DOM while keeping all state; a later mount() re-attaches
1089
+ // with any updates that happened while detached already applied
1090
+ detach(): this {
1043
1091
  if (!this.mountRoot || !this.content || !this.startMarker || !this.endMarker) return this
1044
1092
 
1045
1093
  // move everything between the markers (inclusive) back into the holding
@@ -1057,7 +1105,7 @@ export class Component79 {
1057
1105
  }
1058
1106
 
1059
1107
  destroy(): this {
1060
- this.unmount()
1108
+ this.detach()
1061
1109
  this.fx?.dispose()
1062
1110
  this.fx = null
1063
1111
  this.styleEls.forEach(el => el.parentNode?.removeChild(el))