@llui/dom 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/dist/binding-registry.d.ts +10 -0
  2. package/dist/binding-registry.d.ts.map +1 -0
  3. package/dist/binding-registry.js +96 -0
  4. package/dist/binding-registry.js.map +1 -0
  5. package/dist/binding.d.ts +22 -0
  6. package/dist/binding.d.ts.map +1 -1
  7. package/dist/binding.js +56 -5
  8. package/dist/binding.js.map +1 -1
  9. package/dist/build-flags.d.ts +25 -0
  10. package/dist/build-flags.d.ts.map +1 -0
  11. package/dist/build-flags.js +18 -0
  12. package/dist/build-flags.js.map +1 -0
  13. package/dist/el-split.d.ts.map +1 -1
  14. package/dist/el-split.js +8 -4
  15. package/dist/el-split.js.map +1 -1
  16. package/dist/el-template.d.ts.map +1 -1
  17. package/dist/el-template.js +15 -18
  18. package/dist/el-template.js.map +1 -1
  19. package/dist/elements.d.ts.map +1 -1
  20. package/dist/elements.js +12 -4
  21. package/dist/elements.js.map +1 -1
  22. package/dist/hmr.js +9 -4
  23. package/dist/hmr.js.map +1 -1
  24. package/dist/index.d.ts +2 -0
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/index.js +2 -0
  27. package/dist/index.js.map +1 -1
  28. package/dist/internal/test-component-builder.d.ts +21 -0
  29. package/dist/internal/test-component-builder.d.ts.map +1 -0
  30. package/dist/internal/test-component-builder.js +65 -0
  31. package/dist/internal/test-component-builder.js.map +1 -0
  32. package/dist/internal.d.ts +1 -0
  33. package/dist/internal.d.ts.map +1 -1
  34. package/dist/internal.js +1 -0
  35. package/dist/internal.js.map +1 -1
  36. package/dist/lifetime.d.ts.map +1 -1
  37. package/dist/lifetime.js +16 -3
  38. package/dist/lifetime.js.map +1 -1
  39. package/dist/mount.d.ts +1 -0
  40. package/dist/mount.d.ts.map +1 -1
  41. package/dist/mount.js +32 -22
  42. package/dist/mount.js.map +1 -1
  43. package/dist/primitives/branch.d.ts.map +1 -1
  44. package/dist/primitives/branch.js +29 -16
  45. package/dist/primitives/branch.js.map +1 -1
  46. package/dist/primitives/client-only.d.ts +1 -1
  47. package/dist/primitives/client-only.d.ts.map +1 -1
  48. package/dist/primitives/client-only.js +3 -3
  49. package/dist/primitives/client-only.js.map +1 -1
  50. package/dist/primitives/context.d.ts.map +1 -1
  51. package/dist/primitives/context.js +6 -3
  52. package/dist/primitives/context.js.map +1 -1
  53. package/dist/primitives/each.d.ts.map +1 -1
  54. package/dist/primitives/each.js +121 -74
  55. package/dist/primitives/each.js.map +1 -1
  56. package/dist/primitives/foreign.js +2 -1
  57. package/dist/primitives/foreign.js.map +1 -1
  58. package/dist/primitives/lazy.d.ts +1 -1
  59. package/dist/primitives/lazy.d.ts.map +1 -1
  60. package/dist/primitives/lazy.js +11 -5
  61. package/dist/primitives/lazy.js.map +1 -1
  62. package/dist/primitives/portal.js +2 -1
  63. package/dist/primitives/portal.js.map +1 -1
  64. package/dist/primitives/sample.d.ts.map +1 -1
  65. package/dist/primitives/sample.js +22 -16
  66. package/dist/primitives/sample.js.map +1 -1
  67. package/dist/primitives/track.d.ts +54 -0
  68. package/dist/primitives/track.d.ts.map +1 -0
  69. package/dist/primitives/track.js +54 -0
  70. package/dist/primitives/track.js.map +1 -0
  71. package/dist/primitives/virtual-each.js +4 -2
  72. package/dist/primitives/virtual-each.js.map +1 -1
  73. package/dist/render-context.d.ts +27 -1
  74. package/dist/render-context.d.ts.map +1 -1
  75. package/dist/render-context.js +82 -33
  76. package/dist/render-context.js.map +1 -1
  77. package/dist/ssr.d.ts.map +1 -1
  78. package/dist/ssr.js +5 -3
  79. package/dist/ssr.js.map +1 -1
  80. package/dist/types.d.ts +2 -2
  81. package/dist/types.d.ts.map +1 -1
  82. package/dist/types.js.map +1 -1
  83. package/dist/update-loop.d.ts +1 -0
  84. package/dist/update-loop.d.ts.map +1 -1
  85. package/dist/update-loop.js +115 -50
  86. package/dist/update-loop.js.map +1 -1
  87. package/package.json +1 -1
@@ -1,7 +1,15 @@
1
1
  import { getRenderContext, setRenderContext, clearRenderContext, enterAccessor, exitAccessor, } from '../render-context.js';
2
2
  import { createLifetime, disposeLifetime, addDisposer } from '../lifetime.js';
3
3
  import { setFlatBindings } from '../binding.js';
4
- import { createView } from '../view-helpers.js';
4
+ import { getInstanceViewBag } from '../render-context.js';
5
+ // v0.4 Tier 1.2 + cache follow-up: pulls a cached View bag from the
6
+ // owning instance (constructed once via `def.__view(send)`). The
7
+ // createView fallback below is dead-code-eliminated in production
8
+ // builds — Vite folds `import.meta.env.MODE` to a constant inside
9
+ // getInstanceViewBag.
10
+ function getOwnerBag(ctx, send) {
11
+ return getInstanceViewBag(ctx.instance, send);
12
+ }
5
13
  import { FULL_MASK } from '../update-loop.js';
6
14
  import { pushMountQueue, popMountQueue, flushMountQueue } from './on-mount.js';
7
15
  export function branch(opts) {
@@ -56,15 +64,17 @@ export function branch(opts) {
56
64
  const mq = pushMountQueue();
57
65
  onMountQueue = mq.queue;
58
66
  currentLifetime = createLifetime(parentLifetime);
59
- currentLifetime._kind =
60
- opts.__disposalCause === 'show-hide'
61
- ? 'show'
62
- : opts.__disposalCause === 'scope-rebuild'
63
- ? 'scope'
64
- : 'branch';
67
+ if (import.meta.env?.DEV) {
68
+ currentLifetime._kind =
69
+ opts.__disposalCause === 'show-hide'
70
+ ? 'show'
71
+ : opts.__disposalCause === 'scope-rebuild'
72
+ ? 'scope'
73
+ : 'branch';
74
+ }
65
75
  setFlatBindings(ctx.allBindings);
66
76
  setRenderContext({ ...ctx, rootLifetime: currentLifetime, state });
67
- currentNodes = newBuilder(createView(send));
77
+ currentNodes = newBuilder(getOwnerBag(ctx, send));
68
78
  clearRenderContext();
69
79
  setFlatBindings(null);
70
80
  popMountQueue(mq.prev);
@@ -91,7 +101,8 @@ export function branch(opts) {
91
101
  // defaults to `'branch-swap'`. Tag wins over any pre-existing
92
102
  // value set by an inner primitive so the outermost cause is
93
103
  // reported (matches how humans describe the event).
94
- leavingLifetime.disposalCause = opts.__disposalCause ?? 'branch-swap';
104
+ if (import.meta.env?.DEV)
105
+ leavingLifetime.disposalCause = opts.__disposalCause ?? 'branch-swap';
95
106
  disposeLifetime(leavingLifetime);
96
107
  }
97
108
  };
@@ -125,14 +136,16 @@ export function branch(opts) {
125
136
  // are returned to the parent), so we don't need to flush here.
126
137
  if (builder) {
127
138
  currentLifetime = createLifetime(parentLifetime);
128
- currentLifetime._kind =
129
- opts.__disposalCause === 'show-hide'
130
- ? 'show'
131
- : opts.__disposalCause === 'scope-rebuild'
132
- ? 'scope'
133
- : 'branch';
139
+ if (import.meta.env?.DEV) {
140
+ currentLifetime._kind =
141
+ opts.__disposalCause === 'show-hide'
142
+ ? 'show'
143
+ : opts.__disposalCause === 'scope-rebuild'
144
+ ? 'scope'
145
+ : 'branch';
146
+ }
134
147
  setRenderContext({ ...ctx, rootLifetime: currentLifetime });
135
- currentNodes = builder(createView(send));
148
+ currentNodes = builder(getOwnerBag(ctx, send));
136
149
  clearRenderContext();
137
150
  setRenderContext(ctx);
138
151
  // Fire enter on initial mount
@@ -1 +1 @@
1
- {"version":3,"file":"branch.js","sourceRoot":"","sources":["../../src/primitives/branch.ts"],"names":[],"mappings":"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","sourcesContent":["import type { BranchOptions, Lifetime } from '../types.js'\nimport {\n getRenderContext,\n setRenderContext,\n clearRenderContext,\n enterAccessor,\n exitAccessor,\n} from '../render-context.js'\nimport { createLifetime, disposeLifetime, addDisposer } from '../lifetime.js'\nimport { setFlatBindings } from '../binding.js'\nimport { createView } from '../view-helpers.js'\nimport { FULL_MASK } from '../update-loop.js'\nimport { pushMountQueue, popMountQueue, flushMountQueue } from './on-mount.js'\nimport type { StructuralBlock } from '../structural.js'\n\nexport function branch<S, M = unknown, K extends string = string>(\n opts: BranchOptions<S, M, K>,\n): Node[] {\n const ctx = getRenderContext('branch')\n const parentLifetime = ctx.rootLifetime\n const blocks = ctx.structuralBlocks\n const send = ctx.send as (msg: M) => void\n\n const anchor = ctx.dom.createComment('branch')\n\n // `on` accessor wrapped so sample()/h.sample() called from inside throws a\n // targeted error. Both initial and reconcile paths route through callOn.\n // `Discriminant<S, K>` is `((s: S) => K) | (() => K)` — passing `state`\n // works for either arm at runtime (zero-arg ignores the extra), but a\n // typed wrapper forces a union-call inference TypeScript can't unify.\n // The runtime cast keeps the wrapper transparent.\n const callOn = (state: S) => {\n enterAccessor('branch().on')\n try {\n return (opts.on as (s: S) => K)(state)\n } finally {\n exitAccessor()\n }\n }\n\n let currentKey = callOn(ctx.state as S)\n let currentLifetime: Lifetime | null = null\n let currentNodes: Node[] = []\n\n const block: StructuralBlock = {\n mask: (opts as { __mask?: number }).__mask ?? FULL_MASK,\n maskHi: (opts as { __maskHi?: number }).__maskHi ?? 0,\n reconcile(state: unknown) {\n const newKey = callOn(state as S)\n if (Object.is(newKey, currentKey)) return\n\n const parent = anchor.parentNode\n if (!parent) return\n\n const leavingNodes = currentNodes\n const leavingLifetime = currentLifetime\n\n // Build new arm first (before removing old — for FLIP animations)\n currentNodes = []\n currentLifetime = null\n currentKey = newKey\n\n const newCaseKey = String(newKey) as K\n const newBuilder = opts.cases?.[newCaseKey] ?? opts.default\n // Collect onMount callbacks from the new case into a local queue,\n // then flush them SYNCHRONOUSLY after the new nodes are inserted.\n // Without this, onMount inside a branch case would see stale DOM\n // (nodes not yet attached) OR fall back to queueMicrotask and\n // race with synchronous event dispatches after the reconcile.\n let onMountQueue: Array<() => void> | null = null\n if (newBuilder) {\n const mq = pushMountQueue()\n onMountQueue = mq.queue\n currentLifetime = createLifetime(parentLifetime)\n currentLifetime._kind =\n opts.__disposalCause === 'show-hide'\n ? 'show'\n : opts.__disposalCause === 'scope-rebuild'\n ? 'scope'\n : 'branch'\n setFlatBindings(ctx.allBindings)\n setRenderContext({ ...ctx, rootLifetime: currentLifetime, state })\n currentNodes = newBuilder(createView<S, M>(send))\n clearRenderContext()\n setFlatBindings(null)\n popMountQueue(mq.prev)\n\n const ref = anchor.nextSibling\n for (const node of currentNodes) {\n parent.insertBefore(node, ref)\n }\n }\n if (onMountQueue) flushMountQueue(onMountQueue)\n\n // Fire enter for new nodes\n if (opts.enter && currentNodes.length > 0) {\n opts.enter(currentNodes)\n }\n\n // Handle leave — may be deferred via Promise\n const removeOld = () => {\n for (const node of leavingNodes) {\n if (node.parentNode) node.parentNode.removeChild(node)\n }\n if (leavingLifetime) {\n // Tag BEFORE dispose so the disposer log records the cause.\n // `show()` passes `__disposalCause: 'show-hide'`; raw branch()\n // defaults to `'branch-swap'`. Tag wins over any pre-existing\n // value set by an inner primitive so the outermost cause is\n // reported (matches how humans describe the event).\n leavingLifetime.disposalCause = opts.__disposalCause ?? 'branch-swap'\n disposeLifetime(leavingLifetime)\n }\n }\n\n if (leavingNodes.length > 0 && opts.leave) {\n const result = opts.leave(leavingNodes)\n if (result && typeof (result as Promise<void>).then === 'function') {\n ;(result as Promise<void>).then(removeOld)\n } else {\n removeOld()\n }\n } else {\n removeOld()\n }\n },\n }\n\n // Register the block BEFORE running the initial builder so that parent\n // blocks always precede their nested children in the flat blocks array.\n // This guarantees correct Phase 1 iteration order: parents reconcile\n // first, so a parent that unmounts its old arm can dispose nested child\n // blocks (splicing them out of this array) without corrupting the loop\n // index — the splice only affects entries to the RIGHT of the parent.\n blocks.push(block)\n\n const caseKey = String(currentKey) as K\n const builder = opts.cases?.[caseKey] ?? opts.default\n // Initial-mount onMount callbacks are handled by the outer mountApp\n // queue — we're still inside the first view() call. branch doesn't\n // insert into the DOM at this point (the anchor + initial children\n // are returned to the parent), so we don't need to flush here.\n if (builder) {\n currentLifetime = createLifetime(parentLifetime)\n currentLifetime._kind =\n opts.__disposalCause === 'show-hide'\n ? 'show'\n : opts.__disposalCause === 'scope-rebuild'\n ? 'scope'\n : 'branch'\n setRenderContext({ ...ctx, rootLifetime: currentLifetime })\n currentNodes = builder(createView<S, M>(send))\n clearRenderContext()\n setRenderContext(ctx)\n\n // Fire enter on initial mount\n if (opts.enter && currentNodes.length > 0) {\n opts.enter(currentNodes)\n }\n }\n\n addDisposer(parentLifetime, () => {\n const idx = blocks.indexOf(block)\n if (idx !== -1) blocks.splice(idx, 1)\n // Remove arm DOM nodes + the anchor. The parent's own cleanup\n // (e.g. an outer branch's removeOld) only walks what its initial\n // render captured — nodes that THIS branch inserted into the\n // shared parent AFTER the outer's snapshot (including every\n // arm swap since initial mount) aren't in that list. Walking\n // `currentNodes` here and guarding with `parentNode` closes the\n // leak: if the parent DOM is already cascade-removed by an\n // ancestor, `node.parentNode` is null and the removeChild\n // no-ops. If the parent is still live (spread-into-arm case),\n // the removal is what cleans up the orphans.\n for (const node of currentNodes) {\n if (node.parentNode) node.parentNode.removeChild(node)\n }\n if (anchor.parentNode) anchor.parentNode.removeChild(anchor)\n if (currentLifetime) {\n disposeLifetime(currentLifetime)\n currentLifetime = null\n }\n })\n\n return [anchor, ...currentNodes]\n}\n"]}
1
+ {"version":3,"file":"branch.js","sourceRoot":"","sources":["../../src/primitives/branch.ts"],"names":[],"mappings":"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","sourcesContent":["import type { BranchOptions, Lifetime } from '../types.js'\nimport {\n getRenderContext,\n setRenderContext,\n clearRenderContext,\n enterAccessor,\n exitAccessor,\n} from '../render-context.js'\nimport { createLifetime, disposeLifetime, addDisposer } from '../lifetime.js'\nimport { setFlatBindings } from '../binding.js'\nimport type { View } from '../view-helpers.js'\nimport { getInstanceViewBag } from '../render-context.js'\nimport type { ComponentInstance } from '../update-loop.js'\n\n// v0.4 Tier 1.2 + cache follow-up: pulls a cached View bag from the\n// owning instance (constructed once via `def.__view(send)`). The\n// createView fallback below is dead-code-eliminated in production\n// builds — Vite folds `import.meta.env.MODE` to a constant inside\n// getInstanceViewBag.\nfunction getOwnerBag<S, M>(\n ctx: { instance?: ComponentInstance | undefined },\n send: import('../types.js').Send<M>,\n): View<S, M> {\n return getInstanceViewBag<S, M>(ctx.instance, send) as View<S, M>\n}\nimport { FULL_MASK } from '../update-loop.js'\nimport { pushMountQueue, popMountQueue, flushMountQueue } from './on-mount.js'\nimport type { StructuralBlock } from '../structural.js'\n\nexport function branch<S, M = unknown, K extends string = string>(\n opts: BranchOptions<S, M, K>,\n): Node[] {\n const ctx = getRenderContext('branch')\n const parentLifetime = ctx.rootLifetime\n const blocks = ctx.structuralBlocks\n const send = ctx.send as (msg: M) => void\n\n const anchor = ctx.dom.createComment('branch')\n\n // `on` accessor wrapped so sample()/h.sample() called from inside throws a\n // targeted error. Both initial and reconcile paths route through callOn.\n // `Discriminant<S, K>` is `((s: S) => K) | (() => K)` — passing `state`\n // works for either arm at runtime (zero-arg ignores the extra), but a\n // typed wrapper forces a union-call inference TypeScript can't unify.\n // The runtime cast keeps the wrapper transparent.\n const callOn = (state: S) => {\n enterAccessor('branch().on')\n try {\n return (opts.on as (s: S) => K)(state)\n } finally {\n exitAccessor()\n }\n }\n\n let currentKey = callOn(ctx.state as S)\n let currentLifetime: Lifetime | null = null\n let currentNodes: Node[] = []\n\n const block: StructuralBlock = {\n mask: (opts as { __mask?: number }).__mask ?? FULL_MASK,\n maskHi: (opts as { __maskHi?: number }).__maskHi ?? 0,\n reconcile(state: unknown) {\n const newKey = callOn(state as S)\n if (Object.is(newKey, currentKey)) return\n\n const parent = anchor.parentNode\n if (!parent) return\n\n const leavingNodes = currentNodes\n const leavingLifetime = currentLifetime\n\n // Build new arm first (before removing old — for FLIP animations)\n currentNodes = []\n currentLifetime = null\n currentKey = newKey\n\n const newCaseKey = String(newKey) as K\n const newBuilder = opts.cases?.[newCaseKey] ?? opts.default\n // Collect onMount callbacks from the new case into a local queue,\n // then flush them SYNCHRONOUSLY after the new nodes are inserted.\n // Without this, onMount inside a branch case would see stale DOM\n // (nodes not yet attached) OR fall back to queueMicrotask and\n // race with synchronous event dispatches after the reconcile.\n let onMountQueue: Array<() => void> | null = null\n if (newBuilder) {\n const mq = pushMountQueue()\n onMountQueue = mq.queue\n currentLifetime = createLifetime(parentLifetime)\n if (import.meta.env?.DEV) {\n currentLifetime._kind =\n opts.__disposalCause === 'show-hide'\n ? 'show'\n : opts.__disposalCause === 'scope-rebuild'\n ? 'scope'\n : 'branch'\n }\n setFlatBindings(ctx.allBindings)\n setRenderContext({ ...ctx, rootLifetime: currentLifetime, state })\n currentNodes = newBuilder(getOwnerBag<S, M>(ctx, send))\n clearRenderContext()\n setFlatBindings(null)\n popMountQueue(mq.prev)\n\n const ref = anchor.nextSibling\n for (const node of currentNodes) {\n parent.insertBefore(node, ref)\n }\n }\n if (onMountQueue) flushMountQueue(onMountQueue)\n\n // Fire enter for new nodes\n if (opts.enter && currentNodes.length > 0) {\n opts.enter(currentNodes)\n }\n\n // Handle leave — may be deferred via Promise\n const removeOld = () => {\n for (const node of leavingNodes) {\n if (node.parentNode) node.parentNode.removeChild(node)\n }\n if (leavingLifetime) {\n // Tag BEFORE dispose so the disposer log records the cause.\n // `show()` passes `__disposalCause: 'show-hide'`; raw branch()\n // defaults to `'branch-swap'`. Tag wins over any pre-existing\n // value set by an inner primitive so the outermost cause is\n // reported (matches how humans describe the event).\n if (import.meta.env?.DEV)\n leavingLifetime.disposalCause = opts.__disposalCause ?? 'branch-swap'\n disposeLifetime(leavingLifetime)\n }\n }\n\n if (leavingNodes.length > 0 && opts.leave) {\n const result = opts.leave(leavingNodes)\n if (result && typeof (result as Promise<void>).then === 'function') {\n ;(result as Promise<void>).then(removeOld)\n } else {\n removeOld()\n }\n } else {\n removeOld()\n }\n },\n }\n\n // Register the block BEFORE running the initial builder so that parent\n // blocks always precede their nested children in the flat blocks array.\n // This guarantees correct Phase 1 iteration order: parents reconcile\n // first, so a parent that unmounts its old arm can dispose nested child\n // blocks (splicing them out of this array) without corrupting the loop\n // index — the splice only affects entries to the RIGHT of the parent.\n blocks.push(block)\n\n const caseKey = String(currentKey) as K\n const builder = opts.cases?.[caseKey] ?? opts.default\n // Initial-mount onMount callbacks are handled by the outer mountApp\n // queue — we're still inside the first view() call. branch doesn't\n // insert into the DOM at this point (the anchor + initial children\n // are returned to the parent), so we don't need to flush here.\n if (builder) {\n currentLifetime = createLifetime(parentLifetime)\n if (import.meta.env?.DEV) {\n currentLifetime._kind =\n opts.__disposalCause === 'show-hide'\n ? 'show'\n : opts.__disposalCause === 'scope-rebuild'\n ? 'scope'\n : 'branch'\n }\n setRenderContext({ ...ctx, rootLifetime: currentLifetime })\n currentNodes = builder(getOwnerBag<S, M>(ctx, send))\n clearRenderContext()\n setRenderContext(ctx)\n\n // Fire enter on initial mount\n if (opts.enter && currentNodes.length > 0) {\n opts.enter(currentNodes)\n }\n }\n\n addDisposer(parentLifetime, () => {\n const idx = blocks.indexOf(block)\n if (idx !== -1) blocks.splice(idx, 1)\n // Remove arm DOM nodes + the anchor. The parent's own cleanup\n // (e.g. an outer branch's removeOld) only walks what its initial\n // render captured — nodes that THIS branch inserted into the\n // shared parent AFTER the outer's snapshot (including every\n // arm swap since initial mount) aren't in that list. Walking\n // `currentNodes` here and guarding with `parentNode` closes the\n // leak: if the parent DOM is already cascade-removed by an\n // ancestor, `node.parentNode` is null and the removeChild\n // no-ops. If the parent is still live (spread-into-arm case),\n // the removal is what cleans up the orphans.\n for (const node of currentNodes) {\n if (node.parentNode) node.parentNode.removeChild(node)\n }\n if (anchor.parentNode) anchor.parentNode.removeChild(anchor)\n if (currentLifetime) {\n disposeLifetime(currentLifetime)\n currentLifetime = null\n }\n })\n\n return [anchor, ...currentNodes]\n}\n"]}
@@ -43,7 +43,7 @@
43
43
  * code path; the SSR bundle elides it.
44
44
  */
45
45
  import type { ComponentDef } from '../types.js';
46
- import { type View } from '../view-helpers.js';
46
+ import type { View } from '../view-helpers.js';
47
47
  export interface ClientOnlyOptions<S, M> {
48
48
  /**
49
49
  * Browser-only render callback. Invoked on client mount and hydrate.
@@ -1 +1 @@
1
- {"version":3,"file":"client-only.d.ts","sourceRoot":"","sources":["../../src/primitives/client-only.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAE/C,OAAO,EAAc,KAAK,IAAI,EAAE,MAAM,oBAAoB,CAAA;AAE1D,MAAM,WAAW,iBAAiB,CAAC,CAAC,EAAE,CAAC;IACrC;;;;OAIG;IACH,MAAM,EAAE,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,IAAI,EAAE,CAAA;IAEnC;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,IAAI,EAAE,CAAA;CACvC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,iBAAiB,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,CAkBhF;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,CAOjF"}
1
+ {"version":3,"file":"client-only.d.ts","sourceRoot":"","sources":["../../src/primitives/client-only.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAE/C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAA;AAE9C,MAAM,WAAW,iBAAiB,CAAC,CAAC,EAAE,CAAC;IACrC;;;;OAIG;IACH,MAAM,EAAE,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,IAAI,EAAE,CAAA;IAEnC;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,IAAI,EAAE,CAAA;CACvC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,iBAAiB,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,CAmBhF;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,CAOjF"}
@@ -42,8 +42,7 @@
42
42
  * The bundler sees `import('leaflet')` only from the client-reachable
43
43
  * code path; the SSR bundle elides it.
44
44
  */
45
- import { getRenderContext } from '../render-context.js';
46
- import { createView } from '../view-helpers.js';
45
+ import { getRenderContext, getInstanceViewBag } from '../render-context.js';
47
46
  /**
48
47
  * Mark a view subtree as browser-only. See module doc comment for the
49
48
  * full semantics.
@@ -64,7 +63,8 @@ import { createView } from '../view-helpers.js';
64
63
  export function clientOnly(opts) {
65
64
  const ctx = getRenderContext('clientOnly');
66
65
  const send = ctx.send;
67
- const bag = createView(send);
66
+ // v0.4 Tier 1.2 + cache: bag is memoised per owning instance.
67
+ const bag = getInstanceViewBag(ctx.instance, send);
68
68
  // `ctx.dom.isBrowser` is the discriminator — it's true only when the
69
69
  // env wraps the live browser globals (see `browserEnv()`). SSR envs
70
70
  // (`jsdomEnv`, `linkedomEnv`, custom adapters) don't set it. This
@@ -1 +1 @@
1
- {"version":3,"file":"client-only.js","sourceRoot":"","sources":["../../src/primitives/client-only.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAGH,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AACvD,OAAO,EAAE,UAAU,EAAa,MAAM,oBAAoB,CAAA;AAyB1D;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,UAAU,CAAiB,IAA6B;IACtE,MAAM,GAAG,GAAG,gBAAgB,CAAC,YAAY,CAAC,CAAA;IAC1C,MAAM,IAAI,GAAG,GAAG,CAAC,IAAwB,CAAA;IACzC,MAAM,GAAG,GAAG,UAAU,CAAO,IAAI,CAAC,CAAA;IAElC,qEAAqE;IACrE,oEAAoE;IACpE,kEAAkE;IAClE,gEAAgE;IAChE,mEAAmE;IACnE,IAAI,GAAG,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC;QACtB,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;IACzB,CAAC;IAED,MAAM,KAAK,GAAG,GAAG,CAAC,GAAG,CAAC,aAAa,CAAC,wBAAwB,CAAC,CAAA;IAC7D,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,aAAa,CAAC,sBAAsB,CAAC,CAAA;IACzD,MAAM,aAAa,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;IAC7D,OAAO,CAAC,KAAK,EAAE,GAAG,aAAa,EAAE,GAAG,CAAC,CAAA;AACvC,CAAC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,OAAO;QACL,IAAI;QACJ,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC;QACpB,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QACtB,IAAI,EAAE,GAAG,EAAE,CAAC,UAAU,CAAgB,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;KAC5D,CAAA;AACH,CAAC","sourcesContent":["/**\n * `clientOnly()` — a view primitive that marks a subtree as browser-only.\n *\n * Problem it solves: some widgets can't render on the server. Leaflet,\n * Chart.js, Monaco, and most imperative browser libraries touch `window`\n * or `document` at construction time. Wrapping them in `clientOnly`\n * means SSR never invokes the render callback — the server emits a\n * placeholder (optionally backed by a user-supplied fallback subtree)\n * and the real render happens at client mount / hydrate time.\n *\n * How it works:\n *\n * - SSR (env without `isBrowser`): emits\n * `<!--llui-client-only-start-->` + fallback nodes (if any) +\n * `<!--llui-client-only-end-->`. The `render` callback is never\n * invoked.\n * - Client mount / hydrate (env with `isBrowser: true`): runs `render`\n * inline. Because LLui's hydration is an atomic swap — the client\n * builds fresh DOM and `container.replaceChildren` wipes the server\n * HTML — no anchor walking or fallback disposal is needed on the\n * client side. The client simply produces its DOM; the SSR output\n * is discarded by `replaceChildren`.\n *\n * State threading: `render` and `fallback` both receive a `View<S, M>`\n * bag keyed to the host component's state, so inner `text`, `branch`,\n * `each`, etc. behave the same as if the primitive weren't there.\n *\n * Gating heavy imports: if the library itself can't be imported on the\n * server, put the import INSIDE `render` via dynamic `import()`:\n *\n * ...clientOnly({\n * fallback: () => [div({ class: 'skeleton' })],\n * render: () => [foreign({\n * create: async (el) => {\n * const L = await import('leaflet')\n * return L.map(el).setView([0, 0], 13)\n * },\n * // ...\n * })],\n * })\n *\n * The bundler sees `import('leaflet')` only from the client-reachable\n * code path; the SSR bundle elides it.\n */\n\nimport type { ComponentDef } from '../types.js'\nimport { getRenderContext } from '../render-context.js'\nimport { createView, type View } from '../view-helpers.js'\n\nexport interface ClientOnlyOptions<S, M> {\n /**\n * Browser-only render callback. Invoked on client mount and hydrate.\n * NEVER invoked during SSR (`renderToString` / `renderNodes`). Free\n * to touch `window`, `document`, or import browser-only modules.\n */\n render: (bag: View<S, M>) => Node[]\n\n /**\n * Server-rendered stand-in. When present, SSR runs `fallback` and\n * serializes its output into the HTML between the anchor comments.\n * Useful for skeleton/shimmer loaders and to preserve layout width\n * before the client widget mounts.\n *\n * Omit to emit only the anchor pair — zero layout impact until the\n * client mounts, which may cause content shift.\n *\n * Both `render` and `fallback` receive the same `View<S, M>` bag;\n * state-dependent fallback bindings are evaluated once at SSR time.\n */\n fallback?: (bag: View<S, M>) => Node[]\n}\n\n/**\n * Mark a view subtree as browser-only. See module doc comment for the\n * full semantics.\n *\n * Returns `Node[]` — spread into a parent element's children array.\n *\n * ```ts\n * view: () => [\n * div({ class: 'dashboard' }, [\n * ...clientOnly({\n * fallback: () => [div({ class: 'chart-skeleton' })],\n * render: () => [foreign({ create: (el) => new Chart(el, cfg) })],\n * }),\n * ]),\n * ]\n * ```\n */\nexport function clientOnly<S, M = unknown>(opts: ClientOnlyOptions<S, M>): Node[] {\n const ctx = getRenderContext('clientOnly')\n const send = ctx.send as (msg: M) => void\n const bag = createView<S, M>(send)\n\n // `ctx.dom.isBrowser` is the discriminator — it's true only when the\n // env wraps the live browser globals (see `browserEnv()`). SSR envs\n // (`jsdomEnv`, `linkedomEnv`, custom adapters) don't set it. This\n // check lets `clientOnly` choose behavior without the primitive\n // needing to know about `renderToString` vs `mountApp` call sites.\n if (ctx.dom.isBrowser) {\n return opts.render(bag)\n }\n\n const start = ctx.dom.createComment('llui-client-only-start')\n const end = ctx.dom.createComment('llui-client-only-end')\n const fallbackNodes = opts.fallback ? opts.fallback(bag) : []\n return [start, ...fallbackNodes, end]\n}\n\n/**\n * Generated component stub used by `@llui/vite-plugin`'s `'use client'`\n * directive. For SSR builds, every `export const X = component({...})`\n * in a `'use client'` module is rewritten to\n * `export const X = __clientOnlyStub('X')` — the module's real imports\n * and top-level side effects never run under SSR.\n *\n * The stub is a minimal valid `ComponentDef` whose `view()` emits a\n * `clientOnly` placeholder. The client build imports the ORIGINAL\n * module (directive is a no-op on client), so the real component mounts\n * on hydrate; atomic-swap wipes the SSR stub's empty placeholder.\n *\n * State shape is `{}` and message type is `never` — the stub doesn't\n * participate in any real update cycle. Callers that tried to `send()`\n * messages against the stub during SSR would be dispatching into the\n * void, which is fine: SSR doesn't process messages.\n *\n * App authors should not call this directly — reach for `clientOnly`\n * or the `'use client'` directive depending on the granularity you\n * want.\n */\nexport function __clientOnlyStub(name: string): ComponentDef<object, never, never> {\n return {\n name,\n init: () => [{}, []],\n update: (s) => [s, []],\n view: () => clientOnly<object, never>({ render: () => [] }),\n }\n}\n"]}
1
+ {"version":3,"file":"client-only.js","sourceRoot":"","sources":["../../src/primitives/client-only.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAGH,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AA0B3E;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,UAAU,CAAiB,IAA6B;IACtE,MAAM,GAAG,GAAG,gBAAgB,CAAC,YAAY,CAAC,CAAA;IAC1C,MAAM,IAAI,GAAG,GAAG,CAAC,IAAwB,CAAA;IACzC,8DAA8D;IAC9D,MAAM,GAAG,GAAG,kBAAkB,CAAO,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAe,CAAA;IAEtE,qEAAqE;IACrE,oEAAoE;IACpE,kEAAkE;IAClE,gEAAgE;IAChE,mEAAmE;IACnE,IAAI,GAAG,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC;QACtB,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;IACzB,CAAC;IAED,MAAM,KAAK,GAAG,GAAG,CAAC,GAAG,CAAC,aAAa,CAAC,wBAAwB,CAAC,CAAA;IAC7D,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,aAAa,CAAC,sBAAsB,CAAC,CAAA;IACzD,MAAM,aAAa,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;IAC7D,OAAO,CAAC,KAAK,EAAE,GAAG,aAAa,EAAE,GAAG,CAAC,CAAA;AACvC,CAAC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,OAAO;QACL,IAAI;QACJ,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC;QACpB,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QACtB,IAAI,EAAE,GAAG,EAAE,CAAC,UAAU,CAAgB,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;KAC5D,CAAA;AACH,CAAC","sourcesContent":["/**\n * `clientOnly()` — a view primitive that marks a subtree as browser-only.\n *\n * Problem it solves: some widgets can't render on the server. Leaflet,\n * Chart.js, Monaco, and most imperative browser libraries touch `window`\n * or `document` at construction time. Wrapping them in `clientOnly`\n * means SSR never invokes the render callback — the server emits a\n * placeholder (optionally backed by a user-supplied fallback subtree)\n * and the real render happens at client mount / hydrate time.\n *\n * How it works:\n *\n * - SSR (env without `isBrowser`): emits\n * `<!--llui-client-only-start-->` + fallback nodes (if any) +\n * `<!--llui-client-only-end-->`. The `render` callback is never\n * invoked.\n * - Client mount / hydrate (env with `isBrowser: true`): runs `render`\n * inline. Because LLui's hydration is an atomic swap — the client\n * builds fresh DOM and `container.replaceChildren` wipes the server\n * HTML — no anchor walking or fallback disposal is needed on the\n * client side. The client simply produces its DOM; the SSR output\n * is discarded by `replaceChildren`.\n *\n * State threading: `render` and `fallback` both receive a `View<S, M>`\n * bag keyed to the host component's state, so inner `text`, `branch`,\n * `each`, etc. behave the same as if the primitive weren't there.\n *\n * Gating heavy imports: if the library itself can't be imported on the\n * server, put the import INSIDE `render` via dynamic `import()`:\n *\n * ...clientOnly({\n * fallback: () => [div({ class: 'skeleton' })],\n * render: () => [foreign({\n * create: async (el) => {\n * const L = await import('leaflet')\n * return L.map(el).setView([0, 0], 13)\n * },\n * // ...\n * })],\n * })\n *\n * The bundler sees `import('leaflet')` only from the client-reachable\n * code path; the SSR bundle elides it.\n */\n\nimport type { ComponentDef } from '../types.js'\nimport { getRenderContext, getInstanceViewBag } from '../render-context.js'\nimport type { View } from '../view-helpers.js'\n\nexport interface ClientOnlyOptions<S, M> {\n /**\n * Browser-only render callback. Invoked on client mount and hydrate.\n * NEVER invoked during SSR (`renderToString` / `renderNodes`). Free\n * to touch `window`, `document`, or import browser-only modules.\n */\n render: (bag: View<S, M>) => Node[]\n\n /**\n * Server-rendered stand-in. When present, SSR runs `fallback` and\n * serializes its output into the HTML between the anchor comments.\n * Useful for skeleton/shimmer loaders and to preserve layout width\n * before the client widget mounts.\n *\n * Omit to emit only the anchor pair — zero layout impact until the\n * client mounts, which may cause content shift.\n *\n * Both `render` and `fallback` receive the same `View<S, M>` bag;\n * state-dependent fallback bindings are evaluated once at SSR time.\n */\n fallback?: (bag: View<S, M>) => Node[]\n}\n\n/**\n * Mark a view subtree as browser-only. See module doc comment for the\n * full semantics.\n *\n * Returns `Node[]` — spread into a parent element's children array.\n *\n * ```ts\n * view: () => [\n * div({ class: 'dashboard' }, [\n * ...clientOnly({\n * fallback: () => [div({ class: 'chart-skeleton' })],\n * render: () => [foreign({ create: (el) => new Chart(el, cfg) })],\n * }),\n * ]),\n * ]\n * ```\n */\nexport function clientOnly<S, M = unknown>(opts: ClientOnlyOptions<S, M>): Node[] {\n const ctx = getRenderContext('clientOnly')\n const send = ctx.send as (msg: M) => void\n // v0.4 Tier 1.2 + cache: bag is memoised per owning instance.\n const bag = getInstanceViewBag<S, M>(ctx.instance, send) as View<S, M>\n\n // `ctx.dom.isBrowser` is the discriminator — it's true only when the\n // env wraps the live browser globals (see `browserEnv()`). SSR envs\n // (`jsdomEnv`, `linkedomEnv`, custom adapters) don't set it. This\n // check lets `clientOnly` choose behavior without the primitive\n // needing to know about `renderToString` vs `mountApp` call sites.\n if (ctx.dom.isBrowser) {\n return opts.render(bag)\n }\n\n const start = ctx.dom.createComment('llui-client-only-start')\n const end = ctx.dom.createComment('llui-client-only-end')\n const fallbackNodes = opts.fallback ? opts.fallback(bag) : []\n return [start, ...fallbackNodes, end]\n}\n\n/**\n * Generated component stub used by `@llui/vite-plugin`'s `'use client'`\n * directive. For SSR builds, every `export const X = component({...})`\n * in a `'use client'` module is rewritten to\n * `export const X = __clientOnlyStub('X')` — the module's real imports\n * and top-level side effects never run under SSR.\n *\n * The stub is a minimal valid `ComponentDef` whose `view()` emits a\n * `clientOnly` placeholder. The client build imports the ORIGINAL\n * module (directive is a no-op on client), so the real component mounts\n * on hydrate; atomic-swap wipes the SSR stub's empty placeholder.\n *\n * State shape is `{}` and message type is `never` — the stub doesn't\n * participate in any real update cycle. Callers that tried to `send()`\n * messages against the stub during SSR would be dispatching into the\n * void, which is fine: SSR doesn't process messages.\n *\n * App authors should not call this directly — reach for `clientOnly`\n * or the `'use client'` directive depending on the granularity you\n * want.\n */\nexport function __clientOnlyStub(name: string): ComponentDef<object, never, never> {\n return {\n name,\n init: () => [{}, []],\n update: (s) => [s, []],\n view: () => clientOnly<object, never>({ render: () => [] }),\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/primitives/context.ts"],"names":[],"mappings":"AAUA,MAAM,WAAW,OAAO,CAAC,CAAC;IACxB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,QAAQ,EAAE,CAAC,GAAG,SAAS,CAAA;IAChC,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAA;CACnC;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,YAAY,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAE5E;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,CAAC,EAC1B,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,EACf,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,EACrB,QAAQ,EAAE,MAAM,IAAI,EAAE,GACrB,IAAI,EAAE,CAoBR;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CA0B7D;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,MAAM,IAAI,EAAE,GAAG,IAAI,EAAE,CAEzF;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAKrD"}
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/primitives/context.ts"],"names":[],"mappings":"AAUA,MAAM,WAAW,OAAO,CAAC,CAAC;IACxB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,QAAQ,EAAE,CAAC,GAAG,SAAS,CAAA;IAChC,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAA;CACnC;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,YAAY,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAE5E;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,CAAC,EAC1B,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,EACf,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,EACrB,QAAQ,EAAE,MAAM,IAAI,EAAE,GACrB,IAAI,EAAE,CAoBR;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CA6B7D;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,MAAM,IAAI,EAAE,GAAG,IAAI,EAAE,CAEzF;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAKrD"}
@@ -89,9 +89,12 @@ export function useContext(ctx) {
89
89
  return () => d;
90
90
  }
91
91
  const label = ctx._name ?? ctx._id.description ?? 'unknown';
92
- throw new Error(`[LLui] useContext(${label}): no provider found and no default value. ` +
93
- `Wrap a parent element with provide(${label}, accessor, () => [...]) ` +
94
- `or pass a default to createContext().`);
92
+ if (import.meta.env?.DEV) {
93
+ throw new Error(`[LLui] useContext(${label}): no provider found and no default value. ` +
94
+ `Wrap a parent element with provide(${label}, accessor, () => [...]) ` +
95
+ `or pass a default to createContext().`);
96
+ }
97
+ throw new Error(`[LLui] useContext(${label}): no provider`);
95
98
  }
96
99
  /**
97
100
  * Provide a state-independent value to every descendant. Companion to
@@ -1 +1 @@
1
- {"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/primitives/context.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Lifetime } from '../types.js'\nimport { getRenderContext, setRenderContext, clearRenderContext } from '../render-context.js'\nimport { createLifetime } from '../lifetime.js'\n\n/**\n * Per-scope storage: scope → (context-id → accessor).\n * WeakMap so disposed scopes are GC'd.\n */\nconst contextMap = new WeakMap<Lifetime, Map<symbol, (s: unknown) => unknown>>()\n\nexport interface Context<T> {\n readonly _id: symbol\n readonly _default: T | undefined\n readonly _name: string | undefined\n}\n\n/**\n * Create a typed context key. Pass a default value to make consumers without a\n * provider resolve to it; omit to make unprovided consumption throw.\n *\n * ```ts\n * const ThemeContext = createContext<'light' | 'dark'>('light')\n * ```\n */\nexport function createContext<T>(defaultValue?: T, name?: string): Context<T> {\n return { _id: Symbol(name ?? 'llui-ctx'), _default: defaultValue, _name: name }\n}\n\n/**\n * Provide a reactive value for `ctx` to every descendant rendered inside `children`.\n * The accessor `(s: S) => T` is evaluated lazily at binding read time, so providers\n * can thread state slices down without prop drilling.\n *\n * ```ts\n * view: ({ send }) => [\n * provide(ThemeContext, (s: State) => s.theme, () => [\n * header(send),\n * main(send),\n * ]),\n * ]\n * ```\n *\n * Nested providers shadow outer ones within their subtree. The outer value is\n * restored after `children()` returns, so sibling subtrees aren't affected.\n */\nexport function provide<S, T>(\n ctx: Context<T>,\n accessor: (s: S) => T,\n children: () => Node[],\n): Node[] {\n const renderCtx = getRenderContext('provide')\n const parentLifetime = renderCtx.rootLifetime\n // Create a sub-scope so the context is attached to THIS provider alone.\n // Descendants (including those mounted later via show/branch/each) walk\n // up to this scope via their own parent chain and find the accessor.\n // Nested providers create their own sub-scope, shadowing outer values.\n const providerScope = createLifetime(parentLifetime)\n const map = new Map<symbol, (s: unknown) => unknown>()\n map.set(ctx._id, accessor as (s: unknown) => unknown)\n contextMap.set(providerScope, map)\n // Render children with the provider scope as the new rootLifetime so any\n // primitives (bindings, structural blocks, nested providers) attach here.\n setRenderContext({ ...renderCtx, rootLifetime: providerScope })\n try {\n return children()\n } finally {\n clearRenderContext()\n setRenderContext(renderCtx)\n }\n}\n\n/**\n * Read a context accessor within a view or view-function. Walks the scope chain\n * from the current render point to find the nearest provider. Returns an\n * `(s: S) => T` accessor that can be passed to bindings (text/class/etc.).\n *\n * ```ts\n * export function themedCard(): Node[] {\n * const theme = useContext(ThemeContext)\n * return div({ class: (s) => `card theme-${theme(s)}` }, [...])\n * }\n * ```\n */\nexport function useContext<S, T>(ctx: Context<T>): (s: S) => T {\n let scope: Lifetime | null = null\n try {\n scope = getRenderContext('useContext').rootLifetime\n } catch {\n // No render context (e.g. called from connect() in a unit test).\n // Fall through to default resolution below.\n }\n while (scope) {\n const map = contextMap.get(scope)\n if (map?.has(ctx._id)) {\n const accessor = map.get(ctx._id)!\n return accessor as (s: S) => T\n }\n scope = scope.parent\n }\n if (ctx._default !== undefined) {\n const d = ctx._default\n return () => d\n }\n const label = ctx._name ?? ctx._id.description ?? 'unknown'\n throw new Error(\n `[LLui] useContext(${label}): no provider found and no default value. ` +\n `Wrap a parent element with provide(${label}, accessor, () => [...]) ` +\n `or pass a default to createContext().`,\n )\n}\n\n/**\n * Provide a state-independent value to every descendant. Companion to\n * `provide()` for the common case of publishing a stable dispatcher\n * bag, callback record, or DI container — anything that doesn't depend\n * on the parent's state.\n *\n * ```ts\n * provideValue(ToastContext, { show: (m) => send({ type: 'toast', m }) }, () => [\n * main([pageSlot()]),\n * ])\n * ```\n *\n * Equivalent to `provide(ctx, () => value, children)`, but exists so\n * the call site reads as \"provide this value\" rather than \"provide an\n * accessor that ignores its state argument and returns a value.\" Pair\n * with `useContextValue` for symmetric ergonomics on the consumer side.\n *\n * Internally still uses the accessor mechanism: the value is wrapped\n * in a constant lambda. Consumers that read via the reactive\n * `useContext` form will get an `(s) => T` whose accessor ignores `s`.\n */\nexport function provideValue<T>(ctx: Context<T>, value: T, children: () => Node[]): Node[] {\n return provide(ctx, () => value, children)\n}\n\n/**\n * Read a state-independent value from the nearest provider. Companion\n * to `useContext()` for the common case of consuming a stable\n * dispatcher bag, callback record, or DI container.\n *\n * ```ts\n * const toast = useContextValue(ToastContext)\n * button({ onClick: () => toast.show('Saved') }, [text('Save')])\n * ```\n *\n * Equivalent to calling the accessor returned by `useContext` with\n * `undefined`, but reads as a single function call instead of a\n * three-step \"look up the accessor, ignore the state arg, get the\n * value\" dance.\n *\n * ## Value capture contract\n *\n * **The returned value is captured once, at view-construction time.**\n * Any reference you store from `useContextValue(ctx)` into a closure\n * — for example, by assigning it to a local `const` inside `view(...)`\n * and reading it from an event handler — sees the value as it was\n * when the view ran. The closure does NOT re-read the context on each\n * event dispatch.\n *\n * That's fine, and usually what you want, for stable dispatcher bags:\n * the bag's methods close over the layout's `send`, and `send` itself\n * is stable across the layout's lifetime, so the methods work\n * correctly regardless of when the handler fires. Pages can stash\n * `const toast = useContextValue(ToastContext)` at the top of their\n * `view()` and call `toast.show(...)` from any event handler below.\n *\n * **Do NOT use `useContextValue` when the consumer needs to see\n * updates to the context value.** If a parent re-`provideValue`s the\n * context with a different object later, existing consumers already\n * holding the captured value will still see the old one. For\n * reactive consumption, use `useContext(ctx)` — that returns an\n * accessor that re-reads the provider on each binding evaluation, so\n * reactive bindings (`class`, `text`, etc.) pick up updates\n * automatically.\n *\n * **Do NOT use `useContextValue` against a provider whose accessor\n * reads from state.** The accessor is invoked with `undefined` here,\n * so any `(s) => s.something` provider will throw or return garbage.\n * Match `provideValue` on the producer side with `useContextValue` on\n * the consumer side, and `provide` with `useContext`.\n */\nexport function useContextValue<T>(ctx: Context<T>): T {\n const accessor = useContext<unknown, T>(ctx)\n // The contract above: the producer side promised this accessor\n // doesn't read its state arg. Pass undefined.\n return accessor(undefined)\n}\n"]}
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/primitives/context.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Lifetime } from '../types.js'\nimport { getRenderContext, setRenderContext, clearRenderContext } from '../render-context.js'\nimport { createLifetime } from '../lifetime.js'\n\n/**\n * Per-scope storage: scope → (context-id → accessor).\n * WeakMap so disposed scopes are GC'd.\n */\nconst contextMap = new WeakMap<Lifetime, Map<symbol, (s: unknown) => unknown>>()\n\nexport interface Context<T> {\n readonly _id: symbol\n readonly _default: T | undefined\n readonly _name: string | undefined\n}\n\n/**\n * Create a typed context key. Pass a default value to make consumers without a\n * provider resolve to it; omit to make unprovided consumption throw.\n *\n * ```ts\n * const ThemeContext = createContext<'light' | 'dark'>('light')\n * ```\n */\nexport function createContext<T>(defaultValue?: T, name?: string): Context<T> {\n return { _id: Symbol(name ?? 'llui-ctx'), _default: defaultValue, _name: name }\n}\n\n/**\n * Provide a reactive value for `ctx` to every descendant rendered inside `children`.\n * The accessor `(s: S) => T` is evaluated lazily at binding read time, so providers\n * can thread state slices down without prop drilling.\n *\n * ```ts\n * view: ({ send }) => [\n * provide(ThemeContext, (s: State) => s.theme, () => [\n * header(send),\n * main(send),\n * ]),\n * ]\n * ```\n *\n * Nested providers shadow outer ones within their subtree. The outer value is\n * restored after `children()` returns, so sibling subtrees aren't affected.\n */\nexport function provide<S, T>(\n ctx: Context<T>,\n accessor: (s: S) => T,\n children: () => Node[],\n): Node[] {\n const renderCtx = getRenderContext('provide')\n const parentLifetime = renderCtx.rootLifetime\n // Create a sub-scope so the context is attached to THIS provider alone.\n // Descendants (including those mounted later via show/branch/each) walk\n // up to this scope via their own parent chain and find the accessor.\n // Nested providers create their own sub-scope, shadowing outer values.\n const providerScope = createLifetime(parentLifetime)\n const map = new Map<symbol, (s: unknown) => unknown>()\n map.set(ctx._id, accessor as (s: unknown) => unknown)\n contextMap.set(providerScope, map)\n // Render children with the provider scope as the new rootLifetime so any\n // primitives (bindings, structural blocks, nested providers) attach here.\n setRenderContext({ ...renderCtx, rootLifetime: providerScope })\n try {\n return children()\n } finally {\n clearRenderContext()\n setRenderContext(renderCtx)\n }\n}\n\n/**\n * Read a context accessor within a view or view-function. Walks the scope chain\n * from the current render point to find the nearest provider. Returns an\n * `(s: S) => T` accessor that can be passed to bindings (text/class/etc.).\n *\n * ```ts\n * export function themedCard(): Node[] {\n * const theme = useContext(ThemeContext)\n * return div({ class: (s) => `card theme-${theme(s)}` }, [...])\n * }\n * ```\n */\nexport function useContext<S, T>(ctx: Context<T>): (s: S) => T {\n let scope: Lifetime | null = null\n try {\n scope = getRenderContext('useContext').rootLifetime\n } catch {\n // No render context (e.g. called from connect() in a unit test).\n // Fall through to default resolution below.\n }\n while (scope) {\n const map = contextMap.get(scope)\n if (map?.has(ctx._id)) {\n const accessor = map.get(ctx._id)!\n return accessor as (s: S) => T\n }\n scope = scope.parent\n }\n if (ctx._default !== undefined) {\n const d = ctx._default\n return () => d\n }\n const label = ctx._name ?? ctx._id.description ?? 'unknown'\n if (import.meta.env?.DEV) {\n throw new Error(\n `[LLui] useContext(${label}): no provider found and no default value. ` +\n `Wrap a parent element with provide(${label}, accessor, () => [...]) ` +\n `or pass a default to createContext().`,\n )\n }\n throw new Error(`[LLui] useContext(${label}): no provider`)\n}\n\n/**\n * Provide a state-independent value to every descendant. Companion to\n * `provide()` for the common case of publishing a stable dispatcher\n * bag, callback record, or DI container — anything that doesn't depend\n * on the parent's state.\n *\n * ```ts\n * provideValue(ToastContext, { show: (m) => send({ type: 'toast', m }) }, () => [\n * main([pageSlot()]),\n * ])\n * ```\n *\n * Equivalent to `provide(ctx, () => value, children)`, but exists so\n * the call site reads as \"provide this value\" rather than \"provide an\n * accessor that ignores its state argument and returns a value.\" Pair\n * with `useContextValue` for symmetric ergonomics on the consumer side.\n *\n * Internally still uses the accessor mechanism: the value is wrapped\n * in a constant lambda. Consumers that read via the reactive\n * `useContext` form will get an `(s) => T` whose accessor ignores `s`.\n */\nexport function provideValue<T>(ctx: Context<T>, value: T, children: () => Node[]): Node[] {\n return provide(ctx, () => value, children)\n}\n\n/**\n * Read a state-independent value from the nearest provider. Companion\n * to `useContext()` for the common case of consuming a stable\n * dispatcher bag, callback record, or DI container.\n *\n * ```ts\n * const toast = useContextValue(ToastContext)\n * button({ onClick: () => toast.show('Saved') }, [text('Save')])\n * ```\n *\n * Equivalent to calling the accessor returned by `useContext` with\n * `undefined`, but reads as a single function call instead of a\n * three-step \"look up the accessor, ignore the state arg, get the\n * value\" dance.\n *\n * ## Value capture contract\n *\n * **The returned value is captured once, at view-construction time.**\n * Any reference you store from `useContextValue(ctx)` into a closure\n * — for example, by assigning it to a local `const` inside `view(...)`\n * and reading it from an event handler — sees the value as it was\n * when the view ran. The closure does NOT re-read the context on each\n * event dispatch.\n *\n * That's fine, and usually what you want, for stable dispatcher bags:\n * the bag's methods close over the layout's `send`, and `send` itself\n * is stable across the layout's lifetime, so the methods work\n * correctly regardless of when the handler fires. Pages can stash\n * `const toast = useContextValue(ToastContext)` at the top of their\n * `view()` and call `toast.show(...)` from any event handler below.\n *\n * **Do NOT use `useContextValue` when the consumer needs to see\n * updates to the context value.** If a parent re-`provideValue`s the\n * context with a different object later, existing consumers already\n * holding the captured value will still see the old one. For\n * reactive consumption, use `useContext(ctx)` — that returns an\n * accessor that re-reads the provider on each binding evaluation, so\n * reactive bindings (`class`, `text`, etc.) pick up updates\n * automatically.\n *\n * **Do NOT use `useContextValue` against a provider whose accessor\n * reads from state.** The accessor is invoked with `undefined` here,\n * so any `(s) => s.something` provider will throw or return garbage.\n * Match `provideValue` on the producer side with `useContextValue` on\n * the consumer side, and `provide` with `useContext`.\n */\nexport function useContextValue<T>(ctx: Context<T>): T {\n const accessor = useContext<unknown, T>(ctx)\n // The contract above: the producer side promised this accessor\n // doesn't read its state arg. Pass undefined.\n return accessor(undefined)\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"each.d.ts","sourceRoot":"","sources":["../../src/primitives/each.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAA0B,MAAM,aAAa,CAAA;AA0BtE,uEAAuE;AACvE,wBAAgB,eAAe,CAAC,EAAE,EAAE,MAAM,IAAI,GAAG,IAAI,CAEpD;AAED,sEAAsE;AACtE,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,KAAK,IAAI,GAAG,IAAI,CAEzE;AAwDD,wBAAgB,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,WAAW,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,CA6S1E"}
1
+ {"version":3,"file":"each.d.ts","sourceRoot":"","sources":["../../src/primitives/each.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAA0B,MAAM,aAAa,CAAA;AA8BtE,uEAAuE;AACvE,wBAAgB,eAAe,CAAC,EAAE,EAAE,MAAM,IAAI,GAAG,IAAI,CAEpD;AAED,sEAAsE;AACtE,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,KAAK,IAAI,GAAG,IAAI,CAEzE;AAwDD,wBAAgB,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,WAAW,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,CAgU1E"}