@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
@@ -0,0 +1,10 @@
1
+ import type { Binding } from './types.js';
2
+ export interface BindingRegistry {
3
+ readonly byPrefix: Map<number, Set<Binding>>;
4
+ readonly subscriptions: WeakMap<Binding, readonly number[]>;
5
+ }
6
+ export declare function createBindingRegistry(): BindingRegistry;
7
+ export declare function registerBinding(reg: BindingRegistry, binding: Binding, prefixIds: readonly number[]): void;
8
+ export declare function unregisterBinding(reg: BindingRegistry, binding: Binding): void;
9
+ export declare function dispatchChanged(reg: BindingRegistry, changed: readonly number[], fire: (binding: Binding) => void): void;
10
+ //# sourceMappingURL=binding-registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"binding-registry.d.ts","sourceRoot":"","sources":["../src/binding-registry.ts"],"names":[],"mappings":"AA+BA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AAEzC,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC,CAAA;IAC5C,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC,CAAA;CAC5D;AAED,wBAAgB,qBAAqB,IAAI,eAAe,CAKvD;AAED,wBAAgB,eAAe,CAC7B,GAAG,EAAE,eAAe,EACpB,OAAO,EAAE,OAAO,EAChB,SAAS,EAAE,SAAS,MAAM,EAAE,GAC3B,IAAI,CAkBN;AAED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,eAAe,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAK9E;AAkBD,wBAAgB,eAAe,CAC7B,GAAG,EAAE,eAAe,EACpB,OAAO,EAAE,SAAS,MAAM,EAAE,EAC1B,IAAI,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,GAC/B,IAAI,CAgBN"}
@@ -0,0 +1,96 @@
1
+ // Binding registry — Option B Phase 1.
2
+ //
3
+ // Replacement model for the Phase 2 flat-binding-array scan in
4
+ // `update-loop.ts`. Bindings register under the compile-time prefix-IDs
5
+ // they read (a list of positions in the host component's `__prefixes`
6
+ // table). On state change, the runtime walks `__prefixes` to identify
7
+ // changed prefix-IDs, then calls `dispatchChanged` to fire the union of
8
+ // subscribers — O(changed-prefixes) instead of O(total-bindings).
9
+ //
10
+ // Phase 1 is a standalone module: data structures + register/unregister/
11
+ // dispatch + unit tests. The runtime still uses the flat-array model;
12
+ // Phase 2 wires this in behind a per-component flag, Phase 3 makes it the
13
+ // only model. See `docs/proposals/v0.5-rebuild/option-b-hybrid-signals.md`.
14
+ //
15
+ // Data model:
16
+ // - `byPrefix: Map<prefixId, Set<Binding>>` — primary lookup. `Set`
17
+ // preserves insertion order (ES2015 spec), so dispatch fires in
18
+ // mount order without an extra array allocation.
19
+ // - `subscriptions: WeakMap<Binding, readonly prefixId[]>` — reverse
20
+ // index. Used by `unregisterBinding` to find which prefix-sets a
21
+ // binding belongs to in O(prefixIds.length) instead of scanning
22
+ // every set. Weak keying so a binding that's eligible for GC
23
+ // doesn't leak via this map.
24
+ //
25
+ // Dispatch dedup: a binding registered under multiple changed prefixes
26
+ // must fire exactly once per dispatch. We collect-then-iterate via a
27
+ // transient `Set<Binding>` rather than firing inside the prefix walk —
28
+ // the allocation cost is bounded by the number of subscribers actually
29
+ // matched, which is the same upper bound as the flat-array model's
30
+ // per-update binding count.
31
+ export function createBindingRegistry() {
32
+ return {
33
+ byPrefix: new Map(),
34
+ subscriptions: new WeakMap(),
35
+ };
36
+ }
37
+ export function registerBinding(reg, binding, prefixIds) {
38
+ // If the binding was already registered, strip its existing entries
39
+ // first so the prefix-set membership reflects the new declaration.
40
+ // This supports re-registration after a binding's accessor changes
41
+ // (compile-time-uncommon but legal at runtime).
42
+ const existing = reg.subscriptions.get(binding);
43
+ if (existing)
44
+ removeFromPrefixSets(reg, binding, existing);
45
+ reg.subscriptions.set(binding, prefixIds);
46
+ for (let i = 0; i < prefixIds.length; i++) {
47
+ const id = prefixIds[i];
48
+ let set = reg.byPrefix.get(id);
49
+ if (!set) {
50
+ set = new Set();
51
+ reg.byPrefix.set(id, set);
52
+ }
53
+ set.add(binding);
54
+ }
55
+ }
56
+ export function unregisterBinding(reg, binding) {
57
+ const prefixIds = reg.subscriptions.get(binding);
58
+ if (!prefixIds)
59
+ return; // not registered — idempotent no-op
60
+ removeFromPrefixSets(reg, binding, prefixIds);
61
+ reg.subscriptions.delete(binding);
62
+ }
63
+ function removeFromPrefixSets(reg, binding, prefixIds) {
64
+ for (let i = 0; i < prefixIds.length; i++) {
65
+ const id = prefixIds[i];
66
+ const set = reg.byPrefix.get(id);
67
+ if (!set)
68
+ continue;
69
+ set.delete(binding);
70
+ // Drop empty sets so iteration in dispatch doesn't visit dead
71
+ // entries and the map stays tight as components churn.
72
+ if (set.size === 0)
73
+ reg.byPrefix.delete(id);
74
+ }
75
+ }
76
+ export function dispatchChanged(reg, changed, fire) {
77
+ if (changed.length === 0)
78
+ return;
79
+ // Collect-then-iterate so a binding registered under multiple changed
80
+ // prefixes fires exactly once. The set's insertion order is the
81
+ // order in which we encounter the binding via the FIRST changed
82
+ // prefix it matches — which preserves mount order when there's a
83
+ // single changed prefix (the common case), and is well-defined
84
+ // (V8/JSC) for the multi-prefix case.
85
+ const toFire = new Set();
86
+ for (let i = 0; i < changed.length; i++) {
87
+ const set = reg.byPrefix.get(changed[i]);
88
+ if (!set)
89
+ continue;
90
+ for (const binding of set)
91
+ toFire.add(binding);
92
+ }
93
+ for (const binding of toFire)
94
+ fire(binding);
95
+ }
96
+ //# sourceMappingURL=binding-registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"binding-registry.js","sourceRoot":"","sources":["../src/binding-registry.ts"],"names":[],"mappings":"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","sourcesContent":["// Binding registry — Option B Phase 1.\n//\n// Replacement model for the Phase 2 flat-binding-array scan in\n// `update-loop.ts`. Bindings register under the compile-time prefix-IDs\n// they read (a list of positions in the host component's `__prefixes`\n// table). On state change, the runtime walks `__prefixes` to identify\n// changed prefix-IDs, then calls `dispatchChanged` to fire the union of\n// subscribers — O(changed-prefixes) instead of O(total-bindings).\n//\n// Phase 1 is a standalone module: data structures + register/unregister/\n// dispatch + unit tests. The runtime still uses the flat-array model;\n// Phase 2 wires this in behind a per-component flag, Phase 3 makes it the\n// only model. See `docs/proposals/v0.5-rebuild/option-b-hybrid-signals.md`.\n//\n// Data model:\n// - `byPrefix: Map<prefixId, Set<Binding>>` — primary lookup. `Set`\n// preserves insertion order (ES2015 spec), so dispatch fires in\n// mount order without an extra array allocation.\n// - `subscriptions: WeakMap<Binding, readonly prefixId[]>` — reverse\n// index. Used by `unregisterBinding` to find which prefix-sets a\n// binding belongs to in O(prefixIds.length) instead of scanning\n// every set. Weak keying so a binding that's eligible for GC\n// doesn't leak via this map.\n//\n// Dispatch dedup: a binding registered under multiple changed prefixes\n// must fire exactly once per dispatch. We collect-then-iterate via a\n// transient `Set<Binding>` rather than firing inside the prefix walk —\n// the allocation cost is bounded by the number of subscribers actually\n// matched, which is the same upper bound as the flat-array model's\n// per-update binding count.\n\nimport type { Binding } from './types.js'\n\nexport interface BindingRegistry {\n readonly byPrefix: Map<number, Set<Binding>>\n readonly subscriptions: WeakMap<Binding, readonly number[]>\n}\n\nexport function createBindingRegistry(): BindingRegistry {\n return {\n byPrefix: new Map(),\n subscriptions: new WeakMap(),\n }\n}\n\nexport function registerBinding(\n reg: BindingRegistry,\n binding: Binding,\n prefixIds: readonly number[],\n): void {\n // If the binding was already registered, strip its existing entries\n // first so the prefix-set membership reflects the new declaration.\n // This supports re-registration after a binding's accessor changes\n // (compile-time-uncommon but legal at runtime).\n const existing = reg.subscriptions.get(binding)\n if (existing) removeFromPrefixSets(reg, binding, existing)\n\n reg.subscriptions.set(binding, prefixIds)\n for (let i = 0; i < prefixIds.length; i++) {\n const id = prefixIds[i]!\n let set = reg.byPrefix.get(id)\n if (!set) {\n set = new Set()\n reg.byPrefix.set(id, set)\n }\n set.add(binding)\n }\n}\n\nexport function unregisterBinding(reg: BindingRegistry, binding: Binding): void {\n const prefixIds = reg.subscriptions.get(binding)\n if (!prefixIds) return // not registered — idempotent no-op\n removeFromPrefixSets(reg, binding, prefixIds)\n reg.subscriptions.delete(binding)\n}\n\nfunction removeFromPrefixSets(\n reg: BindingRegistry,\n binding: Binding,\n prefixIds: readonly number[],\n): void {\n for (let i = 0; i < prefixIds.length; i++) {\n const id = prefixIds[i]!\n const set = reg.byPrefix.get(id)\n if (!set) continue\n set.delete(binding)\n // Drop empty sets so iteration in dispatch doesn't visit dead\n // entries and the map stays tight as components churn.\n if (set.size === 0) reg.byPrefix.delete(id)\n }\n}\n\nexport function dispatchChanged(\n reg: BindingRegistry,\n changed: readonly number[],\n fire: (binding: Binding) => void,\n): void {\n if (changed.length === 0) return\n\n // Collect-then-iterate so a binding registered under multiple changed\n // prefixes fires exactly once. The set's insertion order is the\n // order in which we encounter the binding via the FIRST changed\n // prefix it matches — which preserves mount order when there's a\n // single changed prefix (the common case), and is well-defined\n // (V8/JSC) for the multi-prefix case.\n const toFire = new Set<Binding>()\n for (let i = 0; i < changed.length; i++) {\n const set = reg.byPrefix.get(changed[i]!)\n if (!set) continue\n for (const binding of set) toFire.add(binding)\n }\n for (const binding of toFire) fire(binding)\n}\n"]}
package/dist/binding.d.ts CHANGED
@@ -15,6 +15,28 @@ export interface CreateBindingOpts {
15
15
  export declare function getFlatBindings(): Binding[] | null;
16
16
  export declare function setFlatBindings(arr: Binding[] | null): void;
17
17
  export declare function createBinding(scope: Lifetime, opts: CreateBindingOpts): Binding;
18
+ /**
19
+ * Bind a value of uncertain runtime type. Compiler-emitted call site
20
+ * when an element-helper prop value is an unresolvable identifier
21
+ * (function parameter, opaque import) — the compiler can't tell at
22
+ * build time whether the value will be a reactive accessor or a
23
+ * plain primitive, so it defers the dispatch here.
24
+ *
25
+ * If `value` is a function, register as a reactive binding with
26
+ * FULL_MASK gating (the compiler couldn't analyze accessor deps).
27
+ * Otherwise apply it directly as a one-shot prop/attr/class/style set.
28
+ *
29
+ * v0.4 size-cut: this exists to keep `createElement` (the heavyweight
30
+ * runtime fallback in `elements.ts`) from being pulled in by uncertain
31
+ * prop sites. ~1.8 kB minified saved per affected app.
32
+ *
33
+ * Compiler-emit target only — user code should not call this directly.
34
+ * (The runtime is re-exported through index.ts. We deliberately don't
35
+ * mark this as private/internal in the JSDoc because the corresponding
36
+ * stripping setting in tsconfig.build.json would then produce a
37
+ * dangling re-export pointing at a missing member.)
38
+ */
39
+ export declare function __bindUncertain(el: Node, kind: BindingKind, key: string | undefined, value: unknown): void;
18
40
  export declare function applyBinding(target: {
19
41
  kind: BindingKind;
20
42
  node: Node;
@@ -1 +1 @@
1
- {"version":3,"file":"binding.d.ts","sourceRoot":"","sources":["../src/binding.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAGhE,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAA;IACZ;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,OAAO,CAAA;IACnC,IAAI,EAAE,WAAW,CAAA;IACjB,IAAI,EAAE,IAAI,CAAA;IACV,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,OAAO,CAAA;CACjB;AAID,wBAAgB,eAAe,IAAI,OAAO,EAAE,GAAG,IAAI,CAElD;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,IAAI,GAAG,IAAI,CAE3D;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAkB/E;AAED,wBAAgB,YAAY,CAC1B,MAAM,EAAE;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,IAAI,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,EACvD,KAAK,EAAE,OAAO,GACb,IAAI,CA+DN"}
1
+ {"version":3,"file":"binding.d.ts","sourceRoot":"","sources":["../src/binding.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAKhE,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAA;IACZ;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,OAAO,CAAA;IACnC,IAAI,EAAE,WAAW,CAAA;IACjB,IAAI,EAAE,IAAI,CAAA;IACV,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,OAAO,CAAA;CACjB;AAID,wBAAgB,eAAe,IAAI,OAAO,EAAE,GAAG,IAAI,CAElD;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,IAAI,GAAG,IAAI,CAE3D;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAkB/E;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,eAAe,CAC7B,EAAE,EAAE,IAAI,EACR,IAAI,EAAE,WAAW,EACjB,GAAG,EAAE,MAAM,GAAG,SAAS,EACvB,KAAK,EAAE,OAAO,GACb,IAAI,CAmBN;AAED,wBAAgB,YAAY,CAC1B,MAAM,EAAE;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,IAAI,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,EACvD,KAAK,EAAE,OAAO,GACb,IAAI,CAsEN"}
package/dist/binding.js CHANGED
@@ -1,4 +1,6 @@
1
1
  import { addBinding } from './lifetime.js';
2
+ import { getRenderContext } from './render-context.js';
3
+ import { FULL_MASK } from './update-loop.js';
2
4
  let flatBindings = null;
3
5
  export function getFlatBindings() {
4
6
  return flatBindings;
@@ -24,6 +26,48 @@ export function createBinding(scope, opts) {
24
26
  flatBindings.push(binding);
25
27
  return binding;
26
28
  }
29
+ /**
30
+ * Bind a value of uncertain runtime type. Compiler-emitted call site
31
+ * when an element-helper prop value is an unresolvable identifier
32
+ * (function parameter, opaque import) — the compiler can't tell at
33
+ * build time whether the value will be a reactive accessor or a
34
+ * plain primitive, so it defers the dispatch here.
35
+ *
36
+ * If `value` is a function, register as a reactive binding with
37
+ * FULL_MASK gating (the compiler couldn't analyze accessor deps).
38
+ * Otherwise apply it directly as a one-shot prop/attr/class/style set.
39
+ *
40
+ * v0.4 size-cut: this exists to keep `createElement` (the heavyweight
41
+ * runtime fallback in `elements.ts`) from being pulled in by uncertain
42
+ * prop sites. ~1.8 kB minified saved per affected app.
43
+ *
44
+ * Compiler-emit target only — user code should not call this directly.
45
+ * (The runtime is re-exported through index.ts. We deliberately don't
46
+ * mark this as private/internal in the JSDoc because the corresponding
47
+ * stripping setting in tsconfig.build.json would then produce a
48
+ * dangling re-export pointing at a missing member.)
49
+ */
50
+ export function __bindUncertain(el, kind, key, value) {
51
+ if (typeof value === 'function') {
52
+ const ctx = getRenderContext();
53
+ const fn = value;
54
+ const perItem = fn.length === 0;
55
+ const binding = createBinding(ctx.rootLifetime, {
56
+ mask: FULL_MASK,
57
+ accessor: fn,
58
+ kind,
59
+ node: el,
60
+ key,
61
+ perItem,
62
+ });
63
+ const initial = perItem ? fn() : fn(ctx.state);
64
+ binding.lastValue = initial;
65
+ applyBinding({ kind, node: el, key }, initial);
66
+ }
67
+ else {
68
+ applyBinding({ kind, node: el, key }, value);
69
+ }
70
+ }
27
71
  export function applyBinding(target, value) {
28
72
  // Defensive guard: if a reactive accessor leaks through as a raw
29
73
  // function value, emitting its `.toString()` into the DOM (e.g. as
@@ -33,11 +77,18 @@ export function applyBinding(target, value) {
33
77
  // are registered via addEventListener in the element helpers, not
34
78
  // via applyBinding.
35
79
  if (typeof value === 'function') {
36
- throw new TypeError(`[LLui] applyBinding(${target.kind}${target.key ? `, '${target.key}'` : ''}) received ` +
37
- `a function as its value. This means an accessor wasn't invoked before ` +
38
- `reaching the binding layer — usually a bug in a compiled binding tuple or ` +
39
- `in a helper that forwards props without calling them. The arrow's source ` +
40
- `would have been serialized into the DOM otherwise. Offender: ${value.toString().slice(0, 120)}`);
80
+ // Dev-only: surface the offending accessor source + key + kind so
81
+ // the bug is obvious. Production builds throw a brief variant
82
+ // this guard is a defensive check against compiler bugs / corrupt
83
+ // tuples; app code that hits it has already crashed.
84
+ if (import.meta.env?.DEV) {
85
+ throw new TypeError(`[LLui] applyBinding(${target.kind}${target.key ? `, '${target.key}'` : ''}) received ` +
86
+ `a function as its value. This means an accessor wasn't invoked before ` +
87
+ `reaching the binding layer — usually a bug in a compiled binding tuple or ` +
88
+ `in a helper that forwards props without calling them. The arrow's source ` +
89
+ `would have been serialized into the DOM otherwise. Offender: ${value.toString().slice(0, 120)}`);
90
+ }
91
+ throw new TypeError(`[LLui] applyBinding(${target.kind}) received a function value`);
41
92
  }
42
93
  switch (target.kind) {
43
94
  case 'effect':
@@ -1 +1 @@
1
- {"version":3,"file":"binding.js","sourceRoot":"","sources":["../src/binding.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAgB1C,IAAI,YAAY,GAAqB,IAAI,CAAA;AAEzC,MAAM,UAAU,eAAe;IAC7B,OAAO,YAAY,CAAA;AACrB,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,GAAqB;IACnD,YAAY,GAAG,GAAG,CAAA;AACpB,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,KAAe,EAAE,IAAuB;IACpE,MAAM,OAAO,GAAY;QACvB,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,CAAC;QACxB,QAAQ,EAAE,IAAI,CAAC,QAAuC;QACtD,SAAS,EAAE,SAAS;QACpB,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,GAAG,EAAE,IAAI,CAAC,GAAG;QACb,aAAa,EAAE,KAAK;QACpB,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,IAAI,EAAE,KAAK;KACZ,CAAA;IAED,UAAU,CAAC,KAAK,EAAE,OAAO,CAAC,CAAA;IAC1B,IAAI,YAAY;QAAE,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IAE5C,OAAO,OAAO,CAAA;AAChB,CAAC;AAED,MAAM,UAAU,YAAY,CAC1B,MAAuD,EACvD,KAAc;IAEd,iEAAiE;IACjE,mEAAmE;IACnE,qEAAqE;IACrE,qEAAqE;IACrE,oEAAoE;IACpE,kEAAkE;IAClE,oBAAoB;IACpB,IAAI,OAAO,KAAK,KAAK,UAAU,EAAE,CAAC;QAChC,MAAM,IAAI,SAAS,CACjB,uBAAuB,MAAM,CAAC,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,EAAE,aAAa;YACrF,wEAAwE;YACxE,4EAA4E;YAC5E,2EAA2E;YAC3E,gEAAgE,KAAK,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CACnG,CAAA;IACH,CAAC;IAED,QAAQ,MAAM,CAAC,IAAI,EAAE,CAAC;QACpB,KAAK,QAAQ;YACX,8DAA8D;YAC9D,+DAA+D;YAC/D,iEAAiE;YACjE,MAAK;QAEP,KAAK,MAAM;YACT,MAAM,CAAC,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,CAAA;YACrC,MAAK;QAEP,KAAK,MAAM,CAAC,CAAC,CAAC;YACZ,MAAM,EAAE,GAAG,MAAM,CAAC,IAAmB,CAEpC;YAAC,EAAU,CAAC,MAAM,CAAC,GAAI,CAAC,GAAG,KAAK,CAAA;YACjC,MAAK;QACP,CAAC;QAED,KAAK,MAAM;YACT,IAAI,KAAK,IAAI,IAAI,EAAE,CAAC;gBAClB,CAAC;gBAAC,MAAM,CAAC,IAAgB,CAAC,eAAe,CAAC,MAAM,CAAC,GAAI,CAAC,CAAA;YACxD,CAAC;iBAAM,IAAI,KAAK,KAAK,KAAK,EAAE,CAAC;gBAC3B,4DAA4D;gBAC5D,IAAI,MAAM,CAAC,GAAI,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;oBACpC,CAAC;oBAAC,MAAM,CAAC,IAAgB,CAAC,YAAY,CAAC,MAAM,CAAC,GAAI,EAAE,OAAO,CAAC,CAAA;gBAC9D,CAAC;qBAAM,CAAC;oBACN,CAAC;oBAAC,MAAM,CAAC,IAAgB,CAAC,eAAe,CAAC,MAAM,CAAC,GAAI,CAAC,CAAA;gBACxD,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,CAAC;gBAAC,MAAM,CAAC,IAAgB,CAAC,YAAY,CAAC,MAAM,CAAC,GAAI,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAA;YACpE,CAAC;YACD,MAAK;QAEP,KAAK,OAAO;YACV,CAAC;YAAC,MAAM,CAAC,IAAgB,CAAC,YAAY,CAAC,OAAO,EAAE,KAAe,CAAC,CAAA;YAChE,MAAK;QAEP,KAAK,OAAO;YACV,IAAI,KAAK,IAAI,IAAI,EAAE,CAAC;gBAClB,CAAC;gBAAC,MAAM,CAAC,IAAoB,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,GAAI,CAAC,CAAA;YACjE,CAAC;iBAAM,CAAC;gBACN,CAAC;gBAAC,MAAM,CAAC,IAAoB,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,GAAI,EAAE,KAAe,CAAC,CAAA;YAC/E,CAAC;YACD,MAAK;IACT,CAAC;AACH,CAAC","sourcesContent":["import type { Lifetime, Binding, BindingKind } from './types.js'\nimport { addBinding } from './lifetime.js'\n\nexport interface CreateBindingOpts {\n mask: number\n /**\n * High-word bits 31..61. Optional; defaults to 0. Compiler-emitted\n * only when the accessor reads a prefix past bit 30.\n */\n maskHi?: number\n accessor: (state: never) => unknown\n kind: BindingKind\n node: Node\n key?: string\n perItem: boolean\n}\n\nlet flatBindings: Binding[] | null = null\n\nexport function getFlatBindings(): Binding[] | null {\n return flatBindings\n}\n\nexport function setFlatBindings(arr: Binding[] | null): void {\n flatBindings = arr\n}\n\nexport function createBinding(scope: Lifetime, opts: CreateBindingOpts): Binding {\n const binding: Binding = {\n mask: opts.mask,\n maskHi: opts.maskHi ?? 0,\n accessor: opts.accessor as (state: unknown) => unknown,\n lastValue: undefined,\n kind: opts.kind,\n node: opts.node,\n key: opts.key,\n ownerLifetime: scope,\n perItem: opts.perItem,\n dead: false,\n }\n\n addBinding(scope, binding)\n if (flatBindings) flatBindings.push(binding)\n\n return binding\n}\n\nexport function applyBinding(\n target: { kind: BindingKind; node: Node; key?: string },\n value: unknown,\n): void {\n // Defensive guard: if a reactive accessor leaks through as a raw\n // function value, emitting its `.toString()` into the DOM (e.g. as\n // an attribute) would be a silent correctness bug that only surfaces\n // on server-rendered pages. Throw loudly so the callsite is obvious.\n // Event handlers (onXxx → 'prop' kind) are NOT handled here; events\n // are registered via addEventListener in the element helpers, not\n // via applyBinding.\n if (typeof value === 'function') {\n throw new TypeError(\n `[LLui] applyBinding(${target.kind}${target.key ? `, '${target.key}'` : ''}) received ` +\n `a function as its value. This means an accessor wasn't invoked before ` +\n `reaching the binding layer — usually a bug in a compiled binding tuple or ` +\n `in a helper that forwards props without calling them. The arrow's source ` +\n `would have been serialized into the DOM otherwise. Offender: ${value.toString().slice(0, 120)}`,\n )\n }\n\n switch (target.kind) {\n case 'effect':\n // Side-effect-only binding — the accessor already ran for its\n // side effects in Phase 2. We keep `applyBinding` callable for\n // type-uniform call sites, but there is no DOM write to perform.\n break\n\n case 'text':\n target.node.nodeValue = String(value)\n break\n\n case 'prop': {\n const el = target.node as HTMLElement\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ;(el as any)[target.key!] = value\n break\n }\n\n case 'attr':\n if (value == null) {\n ;(target.node as Element).removeAttribute(target.key!)\n } else if (value === false) {\n // ARIA attributes need explicit \"false\"; others are removed\n if (target.key!.startsWith('aria-')) {\n ;(target.node as Element).setAttribute(target.key!, 'false')\n } else {\n ;(target.node as Element).removeAttribute(target.key!)\n }\n } else {\n ;(target.node as Element).setAttribute(target.key!, String(value))\n }\n break\n\n case 'class':\n ;(target.node as Element).setAttribute('class', value as string)\n break\n\n case 'style':\n if (value == null) {\n ;(target.node as HTMLElement).style.removeProperty(target.key!)\n } else {\n ;(target.node as HTMLElement).style.setProperty(target.key!, value as string)\n }\n break\n }\n}\n"]}
1
+ {"version":3,"file":"binding.js","sourceRoot":"","sources":["../src/binding.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Lifetime, Binding, BindingKind } from './types.js'\nimport { addBinding } from './lifetime.js'\nimport { getRenderContext } from './render-context.js'\nimport { FULL_MASK } from './update-loop.js'\n\nexport interface CreateBindingOpts {\n mask: number\n /**\n * High-word bits 31..61. Optional; defaults to 0. Compiler-emitted\n * only when the accessor reads a prefix past bit 30.\n */\n maskHi?: number\n accessor: (state: never) => unknown\n kind: BindingKind\n node: Node\n key?: string\n perItem: boolean\n}\n\nlet flatBindings: Binding[] | null = null\n\nexport function getFlatBindings(): Binding[] | null {\n return flatBindings\n}\n\nexport function setFlatBindings(arr: Binding[] | null): void {\n flatBindings = arr\n}\n\nexport function createBinding(scope: Lifetime, opts: CreateBindingOpts): Binding {\n const binding: Binding = {\n mask: opts.mask,\n maskHi: opts.maskHi ?? 0,\n accessor: opts.accessor as (state: unknown) => unknown,\n lastValue: undefined,\n kind: opts.kind,\n node: opts.node,\n key: opts.key,\n ownerLifetime: scope,\n perItem: opts.perItem,\n dead: false,\n }\n\n addBinding(scope, binding)\n if (flatBindings) flatBindings.push(binding)\n\n return binding\n}\n\n/**\n * Bind a value of uncertain runtime type. Compiler-emitted call site\n * when an element-helper prop value is an unresolvable identifier\n * (function parameter, opaque import) — the compiler can't tell at\n * build time whether the value will be a reactive accessor or a\n * plain primitive, so it defers the dispatch here.\n *\n * If `value` is a function, register as a reactive binding with\n * FULL_MASK gating (the compiler couldn't analyze accessor deps).\n * Otherwise apply it directly as a one-shot prop/attr/class/style set.\n *\n * v0.4 size-cut: this exists to keep `createElement` (the heavyweight\n * runtime fallback in `elements.ts`) from being pulled in by uncertain\n * prop sites. ~1.8 kB minified saved per affected app.\n *\n * Compiler-emit target only — user code should not call this directly.\n * (The runtime is re-exported through index.ts. We deliberately don't\n * mark this as private/internal in the JSDoc because the corresponding\n * stripping setting in tsconfig.build.json would then produce a\n * dangling re-export pointing at a missing member.)\n */\nexport function __bindUncertain(\n el: Node,\n kind: BindingKind,\n key: string | undefined,\n value: unknown,\n): void {\n if (typeof value === 'function') {\n const ctx = getRenderContext()\n const fn = value as (s: never) => unknown\n const perItem = fn.length === 0\n const binding = createBinding(ctx.rootLifetime, {\n mask: FULL_MASK,\n accessor: fn,\n kind,\n node: el,\n key,\n perItem,\n })\n const initial = perItem ? (fn as unknown as () => unknown)() : fn(ctx.state as never)\n binding.lastValue = initial\n applyBinding({ kind, node: el, key }, initial)\n } else {\n applyBinding({ kind, node: el, key }, value)\n }\n}\n\nexport function applyBinding(\n target: { kind: BindingKind; node: Node; key?: string },\n value: unknown,\n): void {\n // Defensive guard: if a reactive accessor leaks through as a raw\n // function value, emitting its `.toString()` into the DOM (e.g. as\n // an attribute) would be a silent correctness bug that only surfaces\n // on server-rendered pages. Throw loudly so the callsite is obvious.\n // Event handlers (onXxx → 'prop' kind) are NOT handled here; events\n // are registered via addEventListener in the element helpers, not\n // via applyBinding.\n if (typeof value === 'function') {\n // Dev-only: surface the offending accessor source + key + kind so\n // the bug is obvious. Production builds throw a brief variant —\n // this guard is a defensive check against compiler bugs / corrupt\n // tuples; app code that hits it has already crashed.\n if (import.meta.env?.DEV) {\n throw new TypeError(\n `[LLui] applyBinding(${target.kind}${target.key ? `, '${target.key}'` : ''}) received ` +\n `a function as its value. This means an accessor wasn't invoked before ` +\n `reaching the binding layer — usually a bug in a compiled binding tuple or ` +\n `in a helper that forwards props without calling them. The arrow's source ` +\n `would have been serialized into the DOM otherwise. Offender: ${value.toString().slice(0, 120)}`,\n )\n }\n throw new TypeError(`[LLui] applyBinding(${target.kind}) received a function value`)\n }\n\n switch (target.kind) {\n case 'effect':\n // Side-effect-only binding — the accessor already ran for its\n // side effects in Phase 2. We keep `applyBinding` callable for\n // type-uniform call sites, but there is no DOM write to perform.\n break\n\n case 'text':\n target.node.nodeValue = String(value)\n break\n\n case 'prop': {\n const el = target.node as HTMLElement\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ;(el as any)[target.key!] = value\n break\n }\n\n case 'attr':\n if (value == null) {\n ;(target.node as Element).removeAttribute(target.key!)\n } else if (value === false) {\n // ARIA attributes need explicit \"false\"; others are removed\n if (target.key!.startsWith('aria-')) {\n ;(target.node as Element).setAttribute(target.key!, 'false')\n } else {\n ;(target.node as Element).removeAttribute(target.key!)\n }\n } else {\n ;(target.node as Element).setAttribute(target.key!, String(value))\n }\n break\n\n case 'class':\n ;(target.node as Element).setAttribute('class', value as string)\n break\n\n case 'style':\n if (value == null) {\n ;(target.node as HTMLElement).style.removeProperty(target.key!)\n } else {\n ;(target.node as HTMLElement).style.setProperty(target.key!, value as string)\n }\n break\n }\n}\n"]}
@@ -0,0 +1,25 @@
1
+ declare global {
2
+ /**
3
+ * True when the host adapter (vite-plugin) enables the agent
4
+ * surface. Gates the binding-descriptors registry and related
5
+ * agent-only runtime so non-agent consumers don't ship the code.
6
+ *
7
+ * @see packages/vite-plugin/src/index.ts — sets this via Vite `define`.
8
+ * @see packages/dom/src/binding-descriptors.ts — agent-only module
9
+ * that becomes unreachable when this flag is false.
10
+ */
11
+ const __LLUI_AGENT__: boolean;
12
+ /**
13
+ * True when any component in the host app uses `each()`'s `enter` /
14
+ * `leave` / `onTransition` options. Gates the per-entry enter/leave
15
+ * helpers in `each.ts` (`removeEntry`, `fireEnter`) and the per-cycle
16
+ * `report` / `leaving` queue. Apps without animations drop ~0.3 kB
17
+ * gz; apps that need them pass `transitions: true` to the vite plugin.
18
+ *
19
+ * @see packages/vite-plugin/src/index.ts — sets this via Vite `define`.
20
+ * @see packages/dom/src/primitives/each.ts — gated branches.
21
+ */
22
+ const __LLUI_TRANSITIONS__: boolean;
23
+ }
24
+ export {};
25
+ //# sourceMappingURL=build-flags.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-flags.d.ts","sourceRoot":"","sources":["../src/build-flags.ts"],"names":[],"mappings":"AAaA,OAAO,CAAC,MAAM,CAAC;IACb;;;;;;;;OAQG;IACH,MAAM,cAAc,EAAE,OAAO,CAAA;IAC7B;;;;;;;;;OASG;IACH,MAAM,oBAAoB,EAAE,OAAO,CAAA;CACpC;AAMD,OAAO,EAAE,CAAA"}
@@ -0,0 +1,18 @@
1
+ // Build-time feature flags consumed by the runtime.
2
+ //
3
+ // `@llui/vite-plugin`'s `define` config substitutes these literals at
4
+ // build time. When a flag is set to `false`, the bundler's dead-code
5
+ // eliminator drops every `if (FLAG)` branch — and any module that's
6
+ // only reachable through those branches tree-shakes out entirely.
7
+ //
8
+ // Consumers that don't go through `@llui/vite-plugin` (raw tsc/vitest,
9
+ // other bundlers without a `define` for these) see the flags as
10
+ // undefined at runtime — JavaScript `if (undefined)` is falsy, so the
11
+ // gated agent path simply stays off. This matches the safe default
12
+ // (no agent runtime active).
13
+ // `globalThis` fallback for environments that don't process the
14
+ // `define` substitution (raw tsc test runs, third-party tooling).
15
+ // The runtime check is `typeof __LLUI_AGENT__ !== 'undefined' && __LLUI_AGENT__`.
16
+ // Exporting nothing — this is a declaration-only module.
17
+ export {};
18
+ //# sourceMappingURL=build-flags.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-flags.js","sourceRoot":"","sources":["../src/build-flags.ts"],"names":[],"mappings":"AAAA,oDAAoD;AACpD,EAAE;AACF,sEAAsE;AACtE,qEAAqE;AACrE,oEAAoE;AACpE,kEAAkE;AAClE,EAAE;AACF,uEAAuE;AACvE,gEAAgE;AAChE,sEAAsE;AACtE,mEAAmE;AACnE,6BAA6B;AA0B7B,gEAAgE;AAChE,kEAAkE;AAClE,kFAAkF;AAClF,yDAAyD;AACzD,OAAO,EAAE,CAAA","sourcesContent":["// Build-time feature flags consumed by the runtime.\n//\n// `@llui/vite-plugin`'s `define` config substitutes these literals at\n// build time. When a flag is set to `false`, the bundler's dead-code\n// eliminator drops every `if (FLAG)` branch — and any module that's\n// only reachable through those branches tree-shakes out entirely.\n//\n// Consumers that don't go through `@llui/vite-plugin` (raw tsc/vitest,\n// other bundlers without a `define` for these) see the flags as\n// undefined at runtime — JavaScript `if (undefined)` is falsy, so the\n// gated agent path simply stays off. This matches the safe default\n// (no agent runtime active).\n\ndeclare global {\n /**\n * True when the host adapter (vite-plugin) enables the agent\n * surface. Gates the binding-descriptors registry and related\n * agent-only runtime so non-agent consumers don't ship the code.\n *\n * @see packages/vite-plugin/src/index.ts — sets this via Vite `define`.\n * @see packages/dom/src/binding-descriptors.ts — agent-only module\n * that becomes unreachable when this flag is false.\n */\n const __LLUI_AGENT__: boolean\n /**\n * True when any component in the host app uses `each()`'s `enter` /\n * `leave` / `onTransition` options. Gates the per-entry enter/leave\n * helpers in `each.ts` (`removeEntry`, `fireEnter`) and the per-cycle\n * `report` / `leaving` queue. Apps without animations drop ~0.3 kB\n * gz; apps that need them pass `transitions: true` to the vite plugin.\n *\n * @see packages/vite-plugin/src/index.ts — sets this via Vite `define`.\n * @see packages/dom/src/primitives/each.ts — gated branches.\n */\n const __LLUI_TRANSITIONS__: boolean\n}\n\n// `globalThis` fallback for environments that don't process the\n// `define` substitution (raw tsc test runs, third-party tooling).\n// The runtime check is `typeof __LLUI_AGENT__ !== 'undefined' && __LLUI_AGENT__`.\n// Exporting nothing — this is a declaration-only module.\nexport {}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"el-split.d.ts","sourceRoot":"","sources":["../src/el-split.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAM7C,wBAAgB,OAAO,CACrB,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,WAAW,KAAK,IAAI,CAAC,GAAG,IAAI,EAC5C,MAAM,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC,GAAG,IAAI,EAO7C,QAAQ,EAAE,KAAK,CACX,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,OAAO,CAAC,GACxD,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,OAAO,EAAE,MAAM,CAAC,CACnE,GAAG,IAAI,EAMR,QAAQ,EAAE,KAAK,CAAC,IAAI,GAAG,MAAM,GAAG,KAAK,CAAC,IAAI,GAAG,MAAM,CAAC,CAAC,GAAG,IAAI,GAC3D,WAAW,CA2Fb"}
1
+ {"version":3,"file":"el-split.d.ts","sourceRoot":"","sources":["../src/el-split.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAM7C,wBAAgB,OAAO,CACrB,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,WAAW,KAAK,IAAI,CAAC,GAAG,IAAI,EAC5C,MAAM,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC,GAAG,IAAI,EAO7C,QAAQ,EAAE,KAAK,CACX,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,OAAO,CAAC,GACxD,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,OAAO,EAAE,MAAM,CAAC,CACnE,GAAG,IAAI,EAMR,QAAQ,EAAE,KAAK,CAAC,IAAI,GAAG,MAAM,GAAG,KAAK,CAAC,IAAI,GAAG,MAAM,CAAC,CAAC,GAAG,IAAI,GAC3D,WAAW,CA+Fb"}
package/dist/el-split.js CHANGED
@@ -29,10 +29,14 @@ children) {
29
29
  // `send({type:'X'})` calls with `Object.assign(arrow,
30
30
  // {__lluiVariants: ['X', …]})`. Register those so the agent
31
31
  // layer's `list_actions` reflects the live UI affordances.
32
- const variants = handler
33
- ?.__lluiVariants;
34
- if (variants && variants.length > 0 && ctx.instance) {
35
- registerBindingVariants(ctx.instance, ctx.rootLifetime, variants);
32
+ // Agent-only gated by `__LLUI_AGENT__`. See elements.ts for
33
+ // the same pattern + rationale.
34
+ if (typeof __LLUI_AGENT__ !== 'undefined' && __LLUI_AGENT__) {
35
+ const variants = handler
36
+ ?.__lluiVariants;
37
+ if (variants && variants.length > 0 && ctx.instance) {
38
+ registerBindingVariants(ctx.instance, ctx.rootLifetime, variants);
39
+ }
36
40
  }
37
41
  el.addEventListener(eventName, handler);
38
42
  }
@@ -1 +1 @@
1
- {"version":3,"file":"el-split.js","sourceRoot":"","sources":["../src/el-split.ts"],"names":[],"mappings":"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","sourcesContent":["import type { BindingKind } from './types.js'\nimport { getRenderContext } from './render-context.js'\nimport { createBinding, applyBinding } from './binding.js'\nimport { addCheckedItemUpdater } from './lifetime.js'\nimport { registerBindingVariants } from './binding-descriptors.js'\n\nexport function elSplit(\n tag: string,\n staticFn: ((el: HTMLElement) => void) | null,\n events: Array<[string, EventListener]> | null,\n // Bindings are 4-tuples for low-word-only access (the common case)\n // or 5-tuples when the binding's accessor reads a prefix at bit\n // position 31..61, in which case the 5th slot carries the high-word\n // mask. Stale compiled bundles emit only 4-tuples; new bundles emit\n // the 5th slot when (and only when) needed, so the on-the-wire\n // representation stays byte-identical for ≤31-prefix components.\n bindings: Array<\n | [number, BindingKind, string, (state: never) => unknown]\n | [number, BindingKind, string, (state: never) => unknown, number]\n > | null,\n // Accepts raw strings too (wrapped in Text nodes at append time so\n // user code like `button([], ['Sign in'])` works without an explicit\n // text() wrapper) and nested arrays (flattened one level to match the\n // raw createElement path — supports patterns like `main([pageSlot()])`\n // where pageSlot() returns Node[]).\n children: Array<Node | string | Array<Node | string>> | null,\n): HTMLElement {\n const ctx = getRenderContext()\n const el = ctx.dom.createElement(tag) as HTMLElement\n\n if (staticFn) {\n staticFn(el)\n }\n\n if (events) {\n for (const [eventName, handler] of events) {\n // Compiler-tagged variants — same protocol as the raw\n // `createElement` path in `elements.ts`. The vite-plugin's\n // tagger wraps event-handler arrows containing literal\n // `send({type:'X'})` calls with `Object.assign(arrow,\n // {__lluiVariants: ['X', …]})`. Register those so the agent\n // layer's `list_actions` reflects the live UI affordances.\n const variants = (handler as { __lluiVariants?: readonly string[] } | null | undefined)\n ?.__lluiVariants\n if (variants && variants.length > 0 && ctx.instance) {\n registerBindingVariants(ctx.instance, ctx.rootLifetime, variants)\n }\n el.addEventListener(eventName, handler)\n }\n }\n\n if (bindings) {\n for (const b of bindings) {\n const mask = b[0]\n const kind = b[1]\n const key = b[2]\n const accessor = b[3]\n // Tuple length 5 carries a high-word mask in slot 4 (when the\n // accessor reads a path at bit position 31..61). Length 4 stays\n // pure low-word — covers both ≤31-prefix components and\n // 32..61-prefix components whose individual bindings only touch\n // low-word paths.\n const maskHi = b.length === 5 ? (b[4] as number) : 0\n const perItem = accessor.length === 0\n if (perItem) {\n const get = accessor as unknown as () => unknown\n const target = { kind, node: el, key }\n const initial = addCheckedItemUpdater(ctx.rootLifetime, get, (v) => applyBinding(target, v))\n applyBinding(target, initial)\n } else {\n const binding = createBinding(ctx.rootLifetime, {\n mask,\n maskHi,\n accessor,\n kind,\n node: el,\n key,\n perItem: false,\n })\n const initialValue = accessor(ctx.state as never)\n binding.lastValue = initialValue\n applyBinding({ kind, node: el, key }, initialValue)\n }\n }\n }\n\n if (children) {\n for (const child of children) {\n // Strings get wrapped in Text nodes — matches createElement's\n // behavior in elements.ts. Without this, user code that passes\n // raw strings as children (e.g. `button([], ['Sign in'])`) crashes\n // in jsdom with \"parameter 1 is not of type 'Node'\" during SSR\n // and throws a TypeError in strict browsers.\n if (typeof child === 'string') {\n el.appendChild(ctx.dom.createTextNode(child))\n } else if (Array.isArray(child)) {\n // Arrays-in-children are flattened one level. This matches\n // the raw createElement path in elements.ts and makes patterns\n // like `main([pageSlot()])` (where pageSlot() returns Node[])\n // work consistently between raw and compiled call paths.\n // Without this flattening, tests run via vitest pass (raw path\n // flattens) but SSR via the compiler transform crashes with\n // \"appendChild parameter is not of type Node\".\n for (const node of child) {\n if (typeof node === 'string') {\n el.appendChild(ctx.dom.createTextNode(node))\n } else {\n el.appendChild(node)\n }\n }\n } else {\n el.appendChild(child)\n }\n }\n }\n\n return el\n}\n"]}
1
+ {"version":3,"file":"el-split.js","sourceRoot":"","sources":["../src/el-split.ts"],"names":[],"mappings":"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","sourcesContent":["import type { BindingKind } from './types.js'\nimport { getRenderContext } from './render-context.js'\nimport { createBinding, applyBinding } from './binding.js'\nimport { addCheckedItemUpdater } from './lifetime.js'\nimport { registerBindingVariants } from './binding-descriptors.js'\n\nexport function elSplit(\n tag: string,\n staticFn: ((el: HTMLElement) => void) | null,\n events: Array<[string, EventListener]> | null,\n // Bindings are 4-tuples for low-word-only access (the common case)\n // or 5-tuples when the binding's accessor reads a prefix at bit\n // position 31..61, in which case the 5th slot carries the high-word\n // mask. Stale compiled bundles emit only 4-tuples; new bundles emit\n // the 5th slot when (and only when) needed, so the on-the-wire\n // representation stays byte-identical for ≤31-prefix components.\n bindings: Array<\n | [number, BindingKind, string, (state: never) => unknown]\n | [number, BindingKind, string, (state: never) => unknown, number]\n > | null,\n // Accepts raw strings too (wrapped in Text nodes at append time so\n // user code like `button([], ['Sign in'])` works without an explicit\n // text() wrapper) and nested arrays (flattened one level to match the\n // raw createElement path — supports patterns like `main([pageSlot()])`\n // where pageSlot() returns Node[]).\n children: Array<Node | string | Array<Node | string>> | null,\n): HTMLElement {\n const ctx = getRenderContext()\n const el = ctx.dom.createElement(tag) as HTMLElement\n\n if (staticFn) {\n staticFn(el)\n }\n\n if (events) {\n for (const [eventName, handler] of events) {\n // Compiler-tagged variants — same protocol as the raw\n // `createElement` path in `elements.ts`. The vite-plugin's\n // tagger wraps event-handler arrows containing literal\n // `send({type:'X'})` calls with `Object.assign(arrow,\n // {__lluiVariants: ['X', …]})`. Register those so the agent\n // layer's `list_actions` reflects the live UI affordances.\n // Agent-only — gated by `__LLUI_AGENT__`. See elements.ts for\n // the same pattern + rationale.\n if (typeof __LLUI_AGENT__ !== 'undefined' && __LLUI_AGENT__) {\n const variants = (handler as { __lluiVariants?: readonly string[] } | null | undefined)\n ?.__lluiVariants\n if (variants && variants.length > 0 && ctx.instance) {\n registerBindingVariants(ctx.instance, ctx.rootLifetime, variants)\n }\n }\n el.addEventListener(eventName, handler)\n }\n }\n\n if (bindings) {\n for (const b of bindings) {\n const mask = b[0]\n const kind = b[1]\n const key = b[2]\n const accessor = b[3]\n // Tuple length 5 carries a high-word mask in slot 4 (when the\n // accessor reads a path at bit position 31..61). Length 4 stays\n // pure low-word — covers both ≤31-prefix components and\n // 32..61-prefix components whose individual bindings only touch\n // low-word paths.\n const maskHi = b.length === 5 ? (b[4] as number) : 0\n const perItem = accessor.length === 0\n if (perItem) {\n const get = accessor as unknown as () => unknown\n const target = { kind, node: el, key }\n const initial = addCheckedItemUpdater(ctx.rootLifetime, get, (v) => applyBinding(target, v))\n applyBinding(target, initial)\n } else {\n const binding = createBinding(ctx.rootLifetime, {\n mask,\n maskHi,\n accessor,\n kind,\n node: el,\n key,\n perItem: false,\n })\n const initialValue = accessor(ctx.state as never)\n binding.lastValue = initialValue\n applyBinding({ kind, node: el, key }, initialValue)\n }\n }\n }\n\n if (children) {\n for (const child of children) {\n // Strings get wrapped in Text nodes — matches createElement's\n // behavior in elements.ts. Without this, user code that passes\n // raw strings as children (e.g. `button([], ['Sign in'])`) crashes\n // in jsdom with \"parameter 1 is not of type 'Node'\" during SSR\n // and throws a TypeError in strict browsers.\n if (typeof child === 'string') {\n el.appendChild(ctx.dom.createTextNode(child))\n } else if (Array.isArray(child)) {\n // Arrays-in-children are flattened one level. This matches\n // the raw createElement path in elements.ts and makes patterns\n // like `main([pageSlot()])` (where pageSlot() returns Node[])\n // work consistently between raw and compiled call paths.\n // Without this flattening, tests run via vitest pass (raw path\n // flattens) but SSR via the compiler transform crashes with\n // \"appendChild parameter is not of type Node\".\n for (const node of child) {\n if (typeof node === 'string') {\n el.appendChild(ctx.dom.createTextNode(node))\n } else {\n el.appendChild(node)\n }\n }\n } else {\n el.appendChild(child)\n }\n }\n }\n\n return el\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"el-template.d.ts","sourceRoot":"","sources":["../src/el-template.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAC7C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAmB1C;;;;;;6BAM6B;AAC7B,MAAM,MAAM,YAAY,GAAG,CACzB,IAAI,EAAE,IAAI,EACV,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,WAAW,EACjB,GAAG,EAAE,MAAM,GAAG,SAAS,EACvB,QAAQ,EAAE,CAAC,CAAC,EAAE,KAAK,KAAK,OAAO,EAC/B,MAAM,CAAC,EAAE,MAAM,KACZ,IAAI,CAAA;AAET;;;;;;;;;;;GAWG;AACH,wBAAgB,UAAU,CACxB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,GAC9D,OAAO,CAsCT;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAUxD"}
1
+ {"version":3,"file":"el-template.d.ts","sourceRoot":"","sources":["../src/el-template.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAC7C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAmB1C;;;;;;6BAM6B;AAC7B,MAAM,MAAM,YAAY,GAAG,CACzB,IAAI,EAAE,IAAI,EACV,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,WAAW,EACjB,GAAG,EAAE,MAAM,GAAG,SAAS,EACvB,QAAQ,EAAE,CAAC,CAAC,EAAE,KAAK,KAAK,OAAO,EAC/B,MAAM,CAAC,EAAE,MAAM,KACZ,IAAI,CAAA;AAET;;;;;;;;;;;GAWG;AACH,wBAAgB,UAAU,CACxB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,GAC9D,OAAO,CAqCT;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CASxD"}
@@ -1,18 +1,17 @@
1
1
  import { getRenderContext } from './render-context.js';
2
2
  import { createBinding, applyBinding } from './binding.js';
3
3
  import { addCheckedItemUpdater } from './lifetime.js';
4
- // Per-env cache: each DomEnv owns its own HTMLTemplateElement cache so
5
- // concurrent SSR with different envs (jsdom + linkedom in one process)
6
- // never cross-polluates node instances. Keyed by env identity via
7
- // WeakMap so envs get GC'd with their caches.
8
- const templateCacheByEnv = new WeakMap();
9
- function getTemplateCache(env) {
10
- let cache = templateCacheByEnv.get(env);
11
- if (!cache) {
12
- cache = new Map();
13
- templateCacheByEnv.set(env, cache);
14
- }
15
- return cache;
4
+ // Template cache. Each HTML string maps to its parsed
5
+ // `HTMLTemplateElement`. Single shared `Map` keyed only on the HTML
6
+ // the WeakMap-by-env layer that wrapped this used to support
7
+ // concurrent SSR with mixed envs (jsdom + linkedom in one process)
8
+ // but in practice each runtime uses one env and the layer was
9
+ // zero-benefit overhead. SSR processes that need a fresh cache call
10
+ // `_resetTemplateCache()` at boundary points.
11
+ const templateCache = new Map();
12
+ /** @internal SSR-only — clear the cache between independent renders. */
13
+ export function _resetTemplateCache() {
14
+ templateCache.clear();
16
15
  }
17
16
  /**
18
17
  * Clone a cached HTML template and apply a patch function.
@@ -28,12 +27,11 @@ function getTemplateCache(env) {
28
27
  */
29
28
  export function elTemplate(html, patch) {
30
29
  const ctx = getRenderContext();
31
- const cache = getTemplateCache(ctx.dom);
32
- let tmpl = cache.get(html);
30
+ let tmpl = templateCache.get(html);
33
31
  if (!tmpl) {
34
32
  tmpl = ctx.dom.createElement('template');
35
33
  tmpl.innerHTML = html;
36
- cache.set(html, tmpl);
34
+ templateCache.set(html, tmpl);
37
35
  }
38
36
  const root = tmpl.content.firstElementChild.cloneNode(true);
39
37
  const bind = (node, mask, kind, key, accessor, maskHi = 0) => {
@@ -76,12 +74,11 @@ export function elTemplate(html, patch) {
76
74
  */
77
75
  export function __cloneStaticTemplate(html) {
78
76
  const ctx = getRenderContext('cloneStaticTemplate');
79
- const cache = getTemplateCache(ctx.dom);
80
- let tmpl = cache.get(html);
77
+ let tmpl = templateCache.get(html);
81
78
  if (!tmpl) {
82
79
  tmpl = ctx.dom.createElement('template');
83
80
  tmpl.innerHTML = html;
84
- cache.set(html, tmpl);
81
+ templateCache.set(html, tmpl);
85
82
  }
86
83
  return tmpl.content.cloneNode(true).firstChild;
87
84
  }
@@ -1 +1 @@
1
- {"version":3,"file":"el-template.js","sourceRoot":"","sources":["../src/el-template.ts"],"names":[],"mappings":"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","sourcesContent":["import type { BindingKind } from './types.js'\nimport type { DomEnv } from './dom-env.js'\nimport { getRenderContext } from './render-context.js'\nimport { createBinding, applyBinding } from './binding.js'\nimport { addCheckedItemUpdater } from './lifetime.js'\n\n// Per-env cache: each DomEnv owns its own HTMLTemplateElement cache so\n// concurrent SSR with different envs (jsdom + linkedom in one process)\n// never cross-polluates node instances. Keyed by env identity via\n// WeakMap so envs get GC'd with their caches.\nconst templateCacheByEnv = new WeakMap<DomEnv, Map<string, HTMLTemplateElement>>()\nfunction getTemplateCache(env: DomEnv): Map<string, HTMLTemplateElement> {\n let cache = templateCacheByEnv.get(env)\n if (!cache) {\n cache = new Map()\n templateCacheByEnv.set(env, cache)\n }\n return cache\n}\n\n/** Callback passed to patch functions — registers a reactive binding on a node.\n *\n * `maskHi` (optional, defaults to 0) carries the high-word mask for\n * accessors that read prefixes at bit positions 31..61. Stale\n * compiled bundles emitted before multi-word support omit the\n * parameter entirely; the defaulting keeps them correct under\n * ≤31-prefix components. */\nexport type TemplateBind = (\n node: Node,\n mask: number,\n kind: BindingKind,\n key: string | undefined,\n accessor: (s: never) => unknown,\n maskHi?: number,\n) => void\n\n/**\n * Clone a cached HTML template and apply a patch function.\n *\n * The patch function receives the cloned root element and a `bind` helper\n * that registers reactive bindings in the current render context.\n *\n * Per-item bindings (accessor.length === 0) are registered as direct\n * updaters on the scope — called by each() when item changes, bypassing\n * the Phase 2 binding scan entirely.\n *\n * Fast path for each() rows — 1 cloneNode instead of N createElement.\n */\nexport function elTemplate(\n html: string,\n patch: (root: Element, bind: TemplateBind, dom: DomEnv) => void,\n): Element {\n const ctx = getRenderContext()\n const cache = getTemplateCache(ctx.dom)\n let tmpl = cache.get(html)\n if (!tmpl) {\n tmpl = ctx.dom.createElement('template') as HTMLTemplateElement\n tmpl.innerHTML = html\n cache.set(html, tmpl)\n }\n\n const root = tmpl.content.firstElementChild!.cloneNode(true) as Element\n\n const bind: TemplateBind = (node, mask, kind, key, accessor, maskHi = 0) => {\n const perItem = accessor.length === 0\n if (perItem) {\n const get = accessor as unknown as () => unknown\n const target = { kind, node, key }\n const initial = addCheckedItemUpdater(ctx.rootLifetime, get, (v) => applyBinding(target, v))\n applyBinding(target, initial)\n } else {\n // State-level: use the binding system for Phase 2\n const binding = createBinding(ctx.rootLifetime, {\n mask,\n maskHi,\n accessor,\n kind,\n node,\n key,\n perItem: false,\n })\n const initialValue = accessor(ctx.state as never)\n binding.lastValue = initialValue\n applyBinding({ kind, node, key }, initialValue)\n }\n }\n\n patch(root, bind, ctx.dom)\n return root\n}\n\n/**\n * Emitted by `@llui/vite-plugin` for static-content template clones\n * (no bindings). Replaces the bare `document.createElement('template')`\n * IIFE the compiler used to emit, threading through `ctx.dom` so SSR\n * in non-browser envs (jsdom, linkedom) works without globalThis mutation.\n *\n * App authors should not call this directly — use `elTemplate` for\n * dynamic content and element helpers (`div`, `span`, …) for everything\n * else. The underscore prefix signals the compiler-only surface; the\n * export exists because the compiler emits import references to it.\n */\nexport function __cloneStaticTemplate(html: string): Node {\n const ctx = getRenderContext('cloneStaticTemplate')\n const cache = getTemplateCache(ctx.dom)\n let tmpl = cache.get(html)\n if (!tmpl) {\n tmpl = ctx.dom.createElement('template') as HTMLTemplateElement\n tmpl.innerHTML = html\n cache.set(html, tmpl)\n }\n return tmpl.content.cloneNode(true).firstChild!\n}\n"]}
1
+ {"version":3,"file":"el-template.js","sourceRoot":"","sources":["../src/el-template.ts"],"names":[],"mappings":"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","sourcesContent":["import type { BindingKind } from './types.js'\nimport type { DomEnv } from './dom-env.js'\nimport { getRenderContext } from './render-context.js'\nimport { createBinding, applyBinding } from './binding.js'\nimport { addCheckedItemUpdater } from './lifetime.js'\n\n// Template cache. Each HTML string maps to its parsed\n// `HTMLTemplateElement`. Single shared `Map` keyed only on the HTML —\n// the WeakMap-by-env layer that wrapped this used to support\n// concurrent SSR with mixed envs (jsdom + linkedom in one process)\n// but in practice each runtime uses one env and the layer was\n// zero-benefit overhead. SSR processes that need a fresh cache call\n// `_resetTemplateCache()` at boundary points.\nconst templateCache = new Map<string, HTMLTemplateElement>()\n\n/** @internal SSR-only clear the cache between independent renders. */\nexport function _resetTemplateCache(): void {\n templateCache.clear()\n}\n\n/** Callback passed to patch functions — registers a reactive binding on a node.\n *\n * `maskHi` (optional, defaults to 0) carries the high-word mask for\n * accessors that read prefixes at bit positions 31..61. Stale\n * compiled bundles emitted before multi-word support omit the\n * parameter entirely; the defaulting keeps them correct under\n * ≤31-prefix components. */\nexport type TemplateBind = (\n node: Node,\n mask: number,\n kind: BindingKind,\n key: string | undefined,\n accessor: (s: never) => unknown,\n maskHi?: number,\n) => void\n\n/**\n * Clone a cached HTML template and apply a patch function.\n *\n * The patch function receives the cloned root element and a `bind` helper\n * that registers reactive bindings in the current render context.\n *\n * Per-item bindings (accessor.length === 0) are registered as direct\n * updaters on the scope — called by each() when item changes, bypassing\n * the Phase 2 binding scan entirely.\n *\n * Fast path for each() rows — 1 cloneNode instead of N createElement.\n */\nexport function elTemplate(\n html: string,\n patch: (root: Element, bind: TemplateBind, dom: DomEnv) => void,\n): Element {\n const ctx = getRenderContext()\n let tmpl = templateCache.get(html)\n if (!tmpl) {\n tmpl = ctx.dom.createElement('template') as HTMLTemplateElement\n tmpl.innerHTML = html\n templateCache.set(html, tmpl)\n }\n\n const root = tmpl.content.firstElementChild!.cloneNode(true) as Element\n\n const bind: TemplateBind = (node, mask, kind, key, accessor, maskHi = 0) => {\n const perItem = accessor.length === 0\n if (perItem) {\n const get = accessor as unknown as () => unknown\n const target = { kind, node, key }\n const initial = addCheckedItemUpdater(ctx.rootLifetime, get, (v) => applyBinding(target, v))\n applyBinding(target, initial)\n } else {\n // State-level: use the binding system for Phase 2\n const binding = createBinding(ctx.rootLifetime, {\n mask,\n maskHi,\n accessor,\n kind,\n node,\n key,\n perItem: false,\n })\n const initialValue = accessor(ctx.state as never)\n binding.lastValue = initialValue\n applyBinding({ kind, node, key }, initialValue)\n }\n }\n\n patch(root, bind, ctx.dom)\n return root\n}\n\n/**\n * Emitted by `@llui/vite-plugin` for static-content template clones\n * (no bindings). Replaces the bare `document.createElement('template')`\n * IIFE the compiler used to emit, threading through `ctx.dom` so SSR\n * in non-browser envs (jsdom, linkedom) works without globalThis mutation.\n *\n * App authors should not call this directly — use `elTemplate` for\n * dynamic content and element helpers (`div`, `span`, …) for everything\n * else. The underscore prefix signals the compiler-only surface; the\n * export exists because the compiler emits import references to it.\n */\nexport function __cloneStaticTemplate(html: string): Node {\n const ctx = getRenderContext('cloneStaticTemplate')\n let tmpl = templateCache.get(html)\n if (!tmpl) {\n tmpl = ctx.dom.createElement('template') as HTMLTemplateElement\n tmpl.innerHTML = html\n templateCache.set(html, tmpl)\n }\n return tmpl.content.cloneNode(true).firstChild!\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"elements.d.ts","sourceRoot":"","sources":["../src/elements.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"elements.d.ts","sourceRoot":"","sources":["../src/elements.ts"],"names":[],"mappings":"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"}
package/dist/elements.js CHANGED
@@ -70,10 +70,18 @@ function createElement(tag, propsOrChildren, maybeChildren) {
70
70
  // through `list_actions`. The lifetime hook removes the
71
71
  // entries on scope dispose (item unmount, branch swap, etc.)
72
72
  // so the LLM sees only what's currently affordable.
73
- const tagged = value
74
- ?.__lluiVariants;
75
- if (tagged && tagged.length > 0 && ctx.instance) {
76
- registerBindingVariants(ctx.instance, ctx.rootLifetime, tagged);
73
+ // Agent-only gated by the build-time `__LLUI_AGENT__` flag.
74
+ // Vite-plugin sets the flag to `false` by default; consumers
75
+ // pass `llui({ agent: true })` to flip it. When false, the
76
+ // bundler dead-codes this branch and `registerBindingVariants`
77
+ // becomes unreachable, allowing the whole binding-descriptors
78
+ // module to tree-shake out of the bundle.
79
+ if (typeof __LLUI_AGENT__ !== 'undefined' && __LLUI_AGENT__) {
80
+ const tagged = value
81
+ ?.__lluiVariants;
82
+ if (tagged && tagged.length > 0 && ctx.instance) {
83
+ registerBindingVariants(ctx.instance, ctx.rootLifetime, tagged);
84
+ }
77
85
  }
78
86
  el.addEventListener(eventName, value);
79
87
  continue;