@llui/dom 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (151) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +15 -0
  3. package/dist/addressed.d.ts +16 -0
  4. package/dist/addressed.d.ts.map +1 -0
  5. package/dist/addressed.js +40 -0
  6. package/dist/addressed.js.map +1 -0
  7. package/dist/binding.d.ts +18 -0
  8. package/dist/binding.d.ts.map +1 -0
  9. package/dist/binding.js +62 -0
  10. package/dist/binding.js.map +1 -0
  11. package/dist/chain-update.d.ts +7 -0
  12. package/dist/chain-update.d.ts.map +1 -0
  13. package/dist/chain-update.js +16 -0
  14. package/dist/chain-update.js.map +1 -0
  15. package/dist/component.d.ts +3 -0
  16. package/dist/component.d.ts.map +1 -0
  17. package/dist/component.js +4 -0
  18. package/dist/component.js.map +1 -0
  19. package/dist/devtools.d.ts +113 -0
  20. package/dist/devtools.d.ts.map +1 -0
  21. package/dist/devtools.js +390 -0
  22. package/dist/devtools.js.map +1 -0
  23. package/dist/el-split.d.ts +3 -0
  24. package/dist/el-split.d.ts.map +1 -0
  25. package/dist/el-split.js +54 -0
  26. package/dist/el-split.js.map +1 -0
  27. package/dist/el-template.d.ts +17 -0
  28. package/dist/el-template.d.ts.map +1 -0
  29. package/dist/el-template.js +64 -0
  30. package/dist/el-template.js.map +1 -0
  31. package/dist/elements.d.ts +80 -0
  32. package/dist/elements.d.ts.map +1 -0
  33. package/dist/elements.js +234 -0
  34. package/dist/elements.js.map +1 -0
  35. package/dist/form.d.ts +30 -0
  36. package/dist/form.d.ts.map +1 -0
  37. package/dist/form.js +12 -0
  38. package/dist/form.js.map +1 -0
  39. package/dist/hmr.d.ts +20 -0
  40. package/dist/hmr.d.ts.map +1 -0
  41. package/dist/hmr.js +98 -0
  42. package/dist/hmr.js.map +1 -0
  43. package/dist/hydrate.d.ts +29 -0
  44. package/dist/hydrate.d.ts.map +1 -0
  45. package/dist/hydrate.js +96 -0
  46. package/dist/hydrate.js.map +1 -0
  47. package/dist/index.d.ts +28 -0
  48. package/dist/index.d.ts.map +1 -0
  49. package/dist/index.js +34 -0
  50. package/dist/index.js.map +1 -0
  51. package/dist/merge-handlers.d.ts +7 -0
  52. package/dist/merge-handlers.d.ts.map +1 -0
  53. package/dist/merge-handlers.js +16 -0
  54. package/dist/merge-handlers.js.map +1 -0
  55. package/dist/mount.d.ts +14 -0
  56. package/dist/mount.d.ts.map +1 -0
  57. package/dist/mount.js +182 -0
  58. package/dist/mount.js.map +1 -0
  59. package/dist/primitives/branch.d.ts +3 -0
  60. package/dist/primitives/branch.d.ts.map +1 -0
  61. package/dist/primitives/branch.js +94 -0
  62. package/dist/primitives/branch.js.map +1 -0
  63. package/dist/primitives/child.d.ts +3 -0
  64. package/dist/primitives/child.d.ts.map +1 -0
  65. package/dist/primitives/child.js +77 -0
  66. package/dist/primitives/child.js.map +1 -0
  67. package/dist/primitives/context.d.ts +45 -0
  68. package/dist/primitives/context.d.ts.map +1 -0
  69. package/dist/primitives/context.js +87 -0
  70. package/dist/primitives/context.js.map +1 -0
  71. package/dist/primitives/each.d.ts +3 -0
  72. package/dist/primitives/each.d.ts.map +1 -0
  73. package/dist/primitives/each.js +515 -0
  74. package/dist/primitives/each.js.map +1 -0
  75. package/dist/primitives/error-boundary.d.ts +6 -0
  76. package/dist/primitives/error-boundary.d.ts.map +1 -0
  77. package/dist/primitives/error-boundary.js +32 -0
  78. package/dist/primitives/error-boundary.js.map +1 -0
  79. package/dist/primitives/foreign.d.ts +3 -0
  80. package/dist/primitives/foreign.d.ts.map +1 -0
  81. package/dist/primitives/foreign.js +80 -0
  82. package/dist/primitives/foreign.js.map +1 -0
  83. package/dist/primitives/memo.d.ts +3 -0
  84. package/dist/primitives/memo.d.ts.map +1 -0
  85. package/dist/primitives/memo.js +30 -0
  86. package/dist/primitives/memo.js.map +1 -0
  87. package/dist/primitives/on-mount.d.ts +2 -0
  88. package/dist/primitives/on-mount.d.ts.map +1 -0
  89. package/dist/primitives/on-mount.js +23 -0
  90. package/dist/primitives/on-mount.js.map +1 -0
  91. package/dist/primitives/portal.d.ts +3 -0
  92. package/dist/primitives/portal.d.ts.map +1 -0
  93. package/dist/primitives/portal.js +31 -0
  94. package/dist/primitives/portal.js.map +1 -0
  95. package/dist/primitives/selector.d.ts +22 -0
  96. package/dist/primitives/selector.d.ts.map +1 -0
  97. package/dist/primitives/selector.js +104 -0
  98. package/dist/primitives/selector.js.map +1 -0
  99. package/dist/primitives/show.d.ts +3 -0
  100. package/dist/primitives/show.d.ts.map +1 -0
  101. package/dist/primitives/show.js +12 -0
  102. package/dist/primitives/show.js.map +1 -0
  103. package/dist/primitives/slice.d.ts +23 -0
  104. package/dist/primitives/slice.d.ts.map +1 -0
  105. package/dist/primitives/slice.js +57 -0
  106. package/dist/primitives/slice.js.map +1 -0
  107. package/dist/primitives/text.d.ts +2 -0
  108. package/dist/primitives/text.d.ts.map +1 -0
  109. package/dist/primitives/text.js +35 -0
  110. package/dist/primitives/text.js.map +1 -0
  111. package/dist/render-context.d.ts +14 -0
  112. package/dist/render-context.d.ts.map +1 -0
  113. package/dist/render-context.js +14 -0
  114. package/dist/render-context.js.map +1 -0
  115. package/dist/runtime.d.ts +4 -0
  116. package/dist/runtime.d.ts.map +1 -0
  117. package/dist/runtime.js +14 -0
  118. package/dist/runtime.js.map +1 -0
  119. package/dist/scope.d.ts +24 -0
  120. package/dist/scope.d.ts.map +1 -0
  121. package/dist/scope.js +102 -0
  122. package/dist/scope.js.map +1 -0
  123. package/dist/slice-handler.d.ts +31 -0
  124. package/dist/slice-handler.d.ts.map +1 -0
  125. package/dist/slice-handler.js +34 -0
  126. package/dist/slice-handler.js.map +1 -0
  127. package/dist/ssr-dom.d.ts +12 -0
  128. package/dist/ssr-dom.d.ts.map +1 -0
  129. package/dist/ssr-dom.js +36 -0
  130. package/dist/ssr-dom.js.map +1 -0
  131. package/dist/ssr.d.ts +11 -0
  132. package/dist/ssr.d.ts.map +1 -0
  133. package/dist/ssr.js +127 -0
  134. package/dist/ssr.js.map +1 -0
  135. package/dist/structural.d.ts +4 -0
  136. package/dist/structural.d.ts.map +1 -0
  137. package/dist/structural.js +2 -0
  138. package/dist/structural.js.map +1 -0
  139. package/dist/types.d.ts +145 -0
  140. package/dist/types.d.ts.map +1 -0
  141. package/dist/types.js +3 -0
  142. package/dist/types.js.map +1 -0
  143. package/dist/update-loop.d.ts +31 -0
  144. package/dist/update-loop.d.ts.map +1 -0
  145. package/dist/update-loop.js +236 -0
  146. package/dist/update-loop.js.map +1 -0
  147. package/dist/view-helpers.d.ts +44 -0
  148. package/dist/view-helpers.d.ts.map +1 -0
  149. package/dist/view-helpers.js +24 -0
  150. package/dist/view-helpers.js.map +1 -0
  151. package/package.json +56 -0
@@ -0,0 +1,80 @@
1
+ import { getRenderContext } from '../render-context';
2
+ import { createBinding } from '../binding';
3
+ import { createScope, addDisposer } from '../scope';
4
+ const FULL_MASK = 0xffffffff;
5
+ export function foreign(opts) {
6
+ const ctx = getRenderContext();
7
+ const parentScope = ctx.rootScope;
8
+ const foreignScope = createScope(parentScope);
9
+ // Create container element
10
+ const tag = opts.container?.tag ?? 'div';
11
+ const container = document.createElement(tag);
12
+ if (opts.container?.attrs) {
13
+ for (const [key, value] of Object.entries(opts.container.attrs)) {
14
+ container.setAttribute(key, value);
15
+ }
16
+ }
17
+ // Mount the foreign instance
18
+ const instance = opts.mount({ container, send: ctx.send });
19
+ // Evaluate initial props and call sync
20
+ let prevProps = undefined;
21
+ const initialProps = opts.props(ctx.state);
22
+ if (typeof opts.sync === 'function') {
23
+ opts.sync({ instance, props: initialProps, prev: undefined });
24
+ }
25
+ else {
26
+ for (const key of Object.keys(initialProps)) {
27
+ const handler = opts.sync[key];
28
+ if (handler) {
29
+ handler({ instance, value: initialProps[key], prev: undefined });
30
+ }
31
+ }
32
+ }
33
+ prevProps = initialProps;
34
+ // Register a binding for the props accessor — fires when state changes
35
+ createBinding(foreignScope, {
36
+ mask: FULL_MASK,
37
+ accessor: ((state) => {
38
+ const newProps = opts.props(state);
39
+ // Shallow-diff props
40
+ let changed = false;
41
+ if (!prevProps) {
42
+ changed = true;
43
+ }
44
+ else {
45
+ for (const key of Object.keys(newProps)) {
46
+ if (!Object.is(newProps[key], prevProps[key])) {
47
+ changed = true;
48
+ break;
49
+ }
50
+ }
51
+ }
52
+ if (changed) {
53
+ if (typeof opts.sync === 'function') {
54
+ opts.sync({ instance, props: newProps, prev: prevProps });
55
+ }
56
+ else {
57
+ for (const key of Object.keys(newProps)) {
58
+ if (!prevProps || !Object.is(newProps[key], prevProps[key])) {
59
+ const handler = opts.sync[key];
60
+ if (handler) {
61
+ handler({ instance, value: newProps[key], prev: prevProps?.[key] });
62
+ }
63
+ }
64
+ }
65
+ }
66
+ prevProps = newProps;
67
+ }
68
+ return newProps;
69
+ }),
70
+ kind: 'text', // kind doesn't matter — applyBinding won't be called
71
+ node: container,
72
+ perItem: false,
73
+ });
74
+ // Destroy on scope disposal
75
+ addDisposer(foreignScope, () => {
76
+ opts.destroy(instance);
77
+ });
78
+ return [container];
79
+ }
80
+ //# sourceMappingURL=foreign.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"foreign.js","sourceRoot":"","sources":["../../src/primitives/foreign.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export declare function setCurrentDirtyMask(mask: number): void;
2
+ export declare function memo<S, T>(accessor: (s: S) => T, mask?: number): (s: S) => T;
3
+ //# sourceMappingURL=memo.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memo.d.ts","sourceRoot":"","sources":["../../src/primitives/memo.ts"],"names":[],"mappings":"AAGA,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAEtD;AAID,wBAAgB,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CA0B5E"}
@@ -0,0 +1,30 @@
1
+ // Current dirty mask — set by the update loop during Phase 2
2
+ let currentDirtyMask = 0;
3
+ export function setCurrentDirtyMask(mask) {
4
+ currentDirtyMask = mask;
5
+ }
6
+ const UNSET = Symbol('unset');
7
+ export function memo(accessor, mask) {
8
+ let lastInput = UNSET;
9
+ let lastOutput;
10
+ return (s) => {
11
+ // Level 1: bitmask fast path — skip if dirty mask doesn't overlap
12
+ if (lastInput !== UNSET && mask !== undefined && (mask & currentDirtyMask) === 0) {
13
+ return lastOutput;
14
+ }
15
+ // Same state reference — skip
16
+ if (lastInput !== UNSET && Object.is(s, lastInput)) {
17
+ return lastOutput;
18
+ }
19
+ // Level 2: output stability — re-evaluate but return cached if same result
20
+ const result = accessor(s);
21
+ if (lastInput !== UNSET && Object.is(result, lastOutput)) {
22
+ lastInput = s;
23
+ return lastOutput;
24
+ }
25
+ lastInput = s;
26
+ lastOutput = result;
27
+ return result;
28
+ };
29
+ }
30
+ //# sourceMappingURL=memo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memo.js","sourceRoot":"","sources":["../../src/primitives/memo.ts"],"names":[],"mappings":"AAAA,6DAA6D;AAC7D,IAAI,gBAAgB,GAAG,CAAC,CAAA;AAExB,MAAM,UAAU,mBAAmB,CAAC,IAAY;IAC9C,gBAAgB,GAAG,IAAI,CAAA;AACzB,CAAC;AAED,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,CAAA;AAE7B,MAAM,UAAU,IAAI,CAAO,QAAqB,EAAE,IAAa;IAC7D,IAAI,SAAS,GAAqB,KAAK,CAAA;IACvC,IAAI,UAAa,CAAA;IAEjB,OAAO,CAAC,CAAI,EAAE,EAAE;QACd,kEAAkE;QAClE,IAAI,SAAS,KAAK,KAAK,IAAI,IAAI,KAAK,SAAS,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC,KAAK,CAAC,EAAE,CAAC;YACjF,OAAO,UAAU,CAAA;QACnB,CAAC;QAED,8BAA8B;QAC9B,IAAI,SAAS,KAAK,KAAK,IAAI,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,SAAS,CAAC,EAAE,CAAC;YACnD,OAAO,UAAU,CAAA;QACnB,CAAC;QAED,2EAA2E;QAC3E,MAAM,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAA;QAC1B,IAAI,SAAS,KAAK,KAAK,IAAI,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,CAAC,EAAE,CAAC;YACzD,SAAS,GAAG,CAAC,CAAA;YACb,OAAO,UAAU,CAAA;QACnB,CAAC;QAED,SAAS,GAAG,CAAC,CAAA;QACb,UAAU,GAAG,MAAM,CAAA;QACnB,OAAO,MAAM,CAAA;IACf,CAAC,CAAA;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function onMount(callback: (el: Element) => (() => void) | void): void;
2
+ //# sourceMappingURL=on-mount.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"on-mount.d.ts","sourceRoot":"","sources":["../../src/primitives/on-mount.ts"],"names":[],"mappings":"AAGA,wBAAgB,OAAO,CAAC,QAAQ,EAAE,CAAC,EAAE,EAAE,OAAO,KAAK,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,GAAG,IAAI,CAoB5E"}
@@ -0,0 +1,23 @@
1
+ import { getRenderContext } from '../render-context';
2
+ import { addDisposer } from '../scope';
3
+ export function onMount(callback) {
4
+ // No-op on the server — event listeners and DOM callbacks are client-only
5
+ if (typeof window === 'undefined')
6
+ return;
7
+ const ctx = getRenderContext();
8
+ const scope = ctx.rootScope;
9
+ const container = ctx.container ?? document.body;
10
+ let cancelled = false;
11
+ addDisposer(scope, () => {
12
+ cancelled = true;
13
+ });
14
+ queueMicrotask(() => {
15
+ if (cancelled)
16
+ return;
17
+ const cleanup = callback(container);
18
+ if (typeof cleanup === 'function') {
19
+ addDisposer(scope, cleanup);
20
+ }
21
+ });
22
+ }
23
+ //# sourceMappingURL=on-mount.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"on-mount.js","sourceRoot":"","sources":["../../src/primitives/on-mount.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AAEtC,MAAM,UAAU,OAAO,CAAC,QAA8C;IACpE,0EAA0E;IAC1E,IAAI,OAAO,MAAM,KAAK,WAAW;QAAE,OAAM;IAEzC,MAAM,GAAG,GAAG,gBAAgB,EAAE,CAAA;IAC9B,MAAM,KAAK,GAAG,GAAG,CAAC,SAAS,CAAA;IAC3B,MAAM,SAAS,GAAG,GAAG,CAAC,SAAS,IAAI,QAAQ,CAAC,IAAI,CAAA;IAChD,IAAI,SAAS,GAAG,KAAK,CAAA;IAErB,WAAW,CAAC,KAAK,EAAE,GAAG,EAAE;QACtB,SAAS,GAAG,IAAI,CAAA;IAClB,CAAC,CAAC,CAAA;IAEF,cAAc,CAAC,GAAG,EAAE;QAClB,IAAI,SAAS;YAAE,OAAM;QACrB,MAAM,OAAO,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAA;QACnC,IAAI,OAAO,OAAO,KAAK,UAAU,EAAE,CAAC;YAClC,WAAW,CAAC,KAAK,EAAE,OAAO,CAAC,CAAA;QAC7B,CAAC;IACH,CAAC,CAAC,CAAA;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { PortalOptions } from '../types';
2
+ export declare function portal(opts: PortalOptions): Node[];
3
+ //# sourceMappingURL=portal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"portal.d.ts","sourceRoot":"","sources":["../../src/primitives/portal.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAI7C,wBAAgB,MAAM,CAAC,IAAI,EAAE,aAAa,GAAG,IAAI,EAAE,CAiClD"}
@@ -0,0 +1,31 @@
1
+ import { getRenderContext, setRenderContext, clearRenderContext } from '../render-context';
2
+ import { createScope, addDisposer } from '../scope';
3
+ export function portal(opts) {
4
+ const ctx = getRenderContext();
5
+ const parentScope = ctx.rootScope;
6
+ const target = typeof opts.target === 'string' ? document.querySelector(opts.target) : opts.target;
7
+ if (!target) {
8
+ return [];
9
+ }
10
+ const portalScope = createScope(parentScope);
11
+ const buildCtx = { ...ctx, rootScope: portalScope, container: target };
12
+ setRenderContext(buildCtx);
13
+ const nodes = opts.render();
14
+ clearRenderContext();
15
+ // Restore parent context
16
+ setRenderContext(ctx);
17
+ for (const node of nodes) {
18
+ target.appendChild(node);
19
+ }
20
+ // On scope disposal, remove portal nodes from target
21
+ addDisposer(portalScope, () => {
22
+ for (const node of nodes) {
23
+ if (node.parentNode === target) {
24
+ target.removeChild(node);
25
+ }
26
+ }
27
+ });
28
+ // Portal returns nothing to the parent DOM — nodes live in the target
29
+ return [];
30
+ }
31
+ //# sourceMappingURL=portal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"portal.js","sourceRoot":"","sources":["../../src/primitives/portal.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AAC1F,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AAEnD,MAAM,UAAU,MAAM,CAAC,IAAmB;IACxC,MAAM,GAAG,GAAG,gBAAgB,EAAE,CAAA;IAC9B,MAAM,WAAW,GAAG,GAAG,CAAC,SAAS,CAAA;IAEjC,MAAM,MAAM,GAAG,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAA;IAElG,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,EAAE,CAAA;IACX,CAAC;IAED,MAAM,WAAW,GAAG,WAAW,CAAC,WAAW,CAAC,CAAA;IAC5C,MAAM,QAAQ,GAAG,EAAE,GAAG,GAAG,EAAE,SAAS,EAAE,WAAW,EAAE,SAAS,EAAE,MAAiB,EAAE,CAAA;IACjF,gBAAgB,CAAC,QAAQ,CAAC,CAAA;IAC1B,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,CAAA;IAC3B,kBAAkB,EAAE,CAAA;IACpB,yBAAyB;IACzB,gBAAgB,CAAC,GAAG,CAAC,CAAA;IAErB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAA;IAC1B,CAAC;IAED,qDAAqD;IACrD,WAAW,CAAC,WAAW,EAAE,GAAG,EAAE;QAC5B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,IAAI,CAAC,UAAU,KAAK,MAAM,EAAE,CAAC;gBAC/B,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAA;YAC1B,CAAC;QACH,CAAC;IACH,CAAC,CAAC,CAAA;IAEF,sEAAsE;IACtE,OAAO,EAAE,CAAA;AACX,CAAC"}
@@ -0,0 +1,22 @@
1
+ import type { BindingKind } from '../types';
2
+ /**
3
+ * Optimized "one-of-N" reactive binding — O(1) updates instead of O(n).
4
+ *
5
+ * Watches a state field and compares it against per-item keys. When the
6
+ * field changes, only the old and new matching rows update their DOM.
7
+ *
8
+ * Usage:
9
+ * // In view, before each():
10
+ * const sel = selector<State, number>(s => s.selected)
11
+ *
12
+ * // Inside each() render:
13
+ * tr({ class: sel.bind(item(r => r.id), 'class', match => match ? 'danger' : '') })
14
+ *
15
+ * sel.bind() creates and manages the DOM binding directly.
16
+ * Returns Node[] to spread into the element's children (empty — no visible output).
17
+ */
18
+ export declare function selector<S, V>(field: (s: S) => V): SelectorInstance<V>;
19
+ export interface SelectorInstance<V> {
20
+ bind(node: Node, key: V | (() => V), kind: BindingKind, propKey: string | undefined, transform: (match: boolean) => unknown): void;
21
+ }
22
+ //# sourceMappingURL=selector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"selector.d.ts","sourceRoot":"","sources":["../../src/primitives/selector.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AAU3C;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,gBAAgB,CAAC,CAAC,CAAC,CAgGtE;AAED,MAAM,WAAW,gBAAgB,CAAC,CAAC;IACjC,IAAI,CACF,IAAI,EAAE,IAAI,EACV,GAAG,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,EAClB,IAAI,EAAE,WAAW,EACjB,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,SAAS,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,GACrC,IAAI,CAAA;CACR"}
@@ -0,0 +1,104 @@
1
+ import { getRenderContext } from '../render-context';
2
+ import { createBinding, applyBinding } from '../binding';
3
+ import { addDisposer } from '../scope';
4
+ import { FULL_MASK } from '../update-loop';
5
+ /**
6
+ * Optimized "one-of-N" reactive binding — O(1) updates instead of O(n).
7
+ *
8
+ * Watches a state field and compares it against per-item keys. When the
9
+ * field changes, only the old and new matching rows update their DOM.
10
+ *
11
+ * Usage:
12
+ * // In view, before each():
13
+ * const sel = selector<State, number>(s => s.selected)
14
+ *
15
+ * // Inside each() render:
16
+ * tr({ class: sel.bind(item(r => r.id), 'class', match => match ? 'danger' : '') })
17
+ *
18
+ * sel.bind() creates and manages the DOM binding directly.
19
+ * Returns Node[] to spread into the element's children (empty — no visible output).
20
+ */
21
+ export function selector(field) {
22
+ const ctx = getRenderContext();
23
+ const scope = ctx.rootScope;
24
+ const registry = new Map();
25
+ let lastValue = field(ctx.state);
26
+ // Single watcher binding — evaluates the state field per update cycle.
27
+ // When the value changes, directly updates only affected entries.
28
+ createBinding(scope, {
29
+ mask: FULL_MASK,
30
+ accessor: ((state) => {
31
+ const newValue = field(state);
32
+ if (Object.is(newValue, lastValue))
33
+ return lastValue;
34
+ // Deselect old
35
+ const oldEntries = registry.get(lastValue);
36
+ if (oldEntries) {
37
+ for (const entry of oldEntries) {
38
+ const v = entry.transform(false);
39
+ if (!Object.is(v, entry.lastValue)) {
40
+ entry.lastValue = v;
41
+ applyBinding({ kind: entry.kind, node: entry.node, key: entry.key }, v);
42
+ }
43
+ }
44
+ }
45
+ // Select new
46
+ const newEntries = registry.get(newValue);
47
+ if (newEntries) {
48
+ for (const entry of newEntries) {
49
+ const v = entry.transform(true);
50
+ if (!Object.is(v, entry.lastValue)) {
51
+ entry.lastValue = v;
52
+ applyBinding({ kind: entry.kind, node: entry.node, key: entry.key }, v);
53
+ }
54
+ }
55
+ }
56
+ lastValue = newValue;
57
+ return newValue;
58
+ }),
59
+ kind: 'text',
60
+ node: document.createComment('selector'),
61
+ perItem: false,
62
+ });
63
+ return {
64
+ /**
65
+ * Bind a DOM node to this selector. Called per row inside each().
66
+ * Applies the initial value and registers for O(1) future updates.
67
+ *
68
+ * @param node - The DOM element to bind
69
+ * @param key - The per-item value to compare against the state field
70
+ * @param kind - Binding kind ('class', 'attr', 'prop', etc.)
71
+ * @param propKey - Property/attribute name (e.g., 'class')
72
+ * @param transform - Maps match boolean to the DOM value
73
+ */
74
+ bind(node, key, kind, propKey, transform) {
75
+ const currentKey = typeof key === 'function' ? key() : key;
76
+ const initialMatch = Object.is(lastValue, currentKey);
77
+ const initialValue = transform(initialMatch);
78
+ // Apply initial value
79
+ applyBinding({ kind, node, key: propKey }, initialValue);
80
+ // Register in selector registry
81
+ const entry = {
82
+ node,
83
+ kind,
84
+ key: propKey,
85
+ lastValue: initialValue,
86
+ transform,
87
+ };
88
+ let bucket = registry.get(currentKey);
89
+ if (!bucket) {
90
+ bucket = new Set();
91
+ registry.set(currentKey, bucket);
92
+ }
93
+ bucket.add(entry);
94
+ // Cleanup when row scope is disposed
95
+ const itemScope = getRenderContext().rootScope;
96
+ addDisposer(itemScope, () => {
97
+ bucket.delete(entry);
98
+ if (bucket.size === 0)
99
+ registry.delete(currentKey);
100
+ });
101
+ },
102
+ };
103
+ }
104
+ //# sourceMappingURL=selector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"selector.js","sourceRoot":"","sources":["../../src/primitives/selector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { ShowOptions } from '../types';
2
+ export declare function show<S, M = unknown>(opts: ShowOptions<S, M>): Node[];
3
+ //# sourceMappingURL=show.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"show.d.ts","sourceRoot":"","sources":["../../src/primitives/show.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AAK3C,wBAAgB,IAAI,CAAC,CAAC,EAAE,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,CAQpE"}
@@ -0,0 +1,12 @@
1
+ import { branch } from './branch';
2
+ const EMPTY = () => [];
3
+ export function show(opts) {
4
+ return branch({
5
+ on: opts.when,
6
+ cases: { true: opts.render, false: opts.fallback ?? EMPTY },
7
+ enter: opts.enter,
8
+ leave: opts.leave,
9
+ onTransition: opts.onTransition,
10
+ });
11
+ }
12
+ //# sourceMappingURL=show.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"show.js","sourceRoot":"","sources":["../../src/primitives/show.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AAEjC,MAAM,KAAK,GAAG,GAAG,EAAE,CAAC,EAAY,CAAA;AAEhC,MAAM,UAAU,IAAI,CAAiB,IAAuB;IAC1D,OAAO,MAAM,CAAO;QAClB,EAAE,EAAE,IAAI,CAAC,IAAI;QACb,KAAK,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,QAAQ,IAAI,KAAK,EAAE;QAC3D,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,YAAY,EAAE,IAAI,CAAC,YAAY;KAChC,CAAC,CAAA;AACJ,CAAC"}
@@ -0,0 +1,23 @@
1
+ import type { Send } from '../types';
2
+ import type { View } from '../view-helpers';
3
+ /**
4
+ * Build a `View<Sub, M>` that composes a selector into every state-bound
5
+ * accessor. Used to write view-functions over a sub-slice of parent state:
6
+ *
7
+ * ```ts
8
+ * import { slice } from '@llui/dom'
9
+ *
10
+ * view: (h) => {
11
+ * const formView = slice(h, (s) => s.form)
12
+ * return [...formView.show({ when: f => f.valid, render: () => [...] })]
13
+ * }
14
+ * ```
15
+ *
16
+ * Kept as a standalone function rather than a method on the View bundle so
17
+ * apps that don't use it don't pay for its bundle cost — tree-shaken when
18
+ * unused.
19
+ */
20
+ export declare function slice<Root, Sub, M>(h: View<Root, M> | {
21
+ send: Send<M>;
22
+ }, lift: (r: Root) => Sub): View<Sub, M>;
23
+ //# sourceMappingURL=slice.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slice.d.ts","sourceRoot":"","sources":["../../src/primitives/slice.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAe,MAAM,UAAU,CAAA;AACjD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAA;AAS3C;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,KAAK,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,EAChC,CAAC,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,GAAG;IAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAA;CAAE,EACpC,IAAI,EAAE,CAAC,CAAC,EAAE,IAAI,KAAK,GAAG,GACrB,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAiCd"}
@@ -0,0 +1,57 @@
1
+ import { show as _show } from './show';
2
+ import { branch as _branch } from './branch';
3
+ import { each as _each } from './each';
4
+ import { text as _text } from './text';
5
+ import { memo as _memo } from './memo';
6
+ import { selector as _selector } from './selector';
7
+ import { useContext } from './context';
8
+ /**
9
+ * Build a `View<Sub, M>` that composes a selector into every state-bound
10
+ * accessor. Used to write view-functions over a sub-slice of parent state:
11
+ *
12
+ * ```ts
13
+ * import { slice } from '@llui/dom'
14
+ *
15
+ * view: (h) => {
16
+ * const formView = slice(h, (s) => s.form)
17
+ * return [...formView.show({ when: f => f.valid, render: () => [...] })]
18
+ * }
19
+ * ```
20
+ *
21
+ * Kept as a standalone function rather than a method on the View bundle so
22
+ * apps that don't use it don't pay for its bundle cost — tree-shaken when
23
+ * unused.
24
+ */
25
+ export function slice(h, lift) {
26
+ const send = h.send;
27
+ return {
28
+ send,
29
+ show: (opts) => _show({
30
+ ...opts,
31
+ when: (r) => opts.when(lift(r)),
32
+ }),
33
+ branch: (opts) => _branch({
34
+ ...opts,
35
+ on: (r) => opts.on(lift(r)),
36
+ }),
37
+ each: (opts) => _each({
38
+ ...opts,
39
+ items: (r) => opts.items(lift(r)),
40
+ }),
41
+ text: (accessor, mask) => {
42
+ if (typeof accessor === 'string')
43
+ return _text(accessor);
44
+ return _text((r) => accessor(lift(r)), mask);
45
+ },
46
+ memo: (accessor) => {
47
+ const m = _memo((r) => accessor(lift(r)));
48
+ return (s) => m(s);
49
+ },
50
+ selector: (field) => _selector((r) => field(lift(r))),
51
+ ctx: (c) => {
52
+ const root = useContext(c);
53
+ return (s) => root(s);
54
+ },
55
+ };
56
+ }
57
+ //# sourceMappingURL=slice.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slice.js","sourceRoot":"","sources":["../../src/primitives/slice.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,IAAI,IAAI,KAAK,EAAE,MAAM,QAAQ,CAAA;AACtC,OAAO,EAAE,MAAM,IAAI,OAAO,EAAE,MAAM,UAAU,CAAA;AAC5C,OAAO,EAAE,IAAI,IAAI,KAAK,EAAE,MAAM,QAAQ,CAAA;AACtC,OAAO,EAAE,IAAI,IAAI,KAAK,EAAE,MAAM,QAAQ,CAAA;AACtC,OAAO,EAAE,IAAI,IAAI,KAAK,EAAE,MAAM,QAAQ,CAAA;AACtC,OAAO,EAAE,QAAQ,IAAI,SAAS,EAAE,MAAM,YAAY,CAAA;AAClD,OAAO,EAAE,UAAU,EAAgB,MAAM,WAAW,CAAA;AAEpD;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,KAAK,CACnB,CAAoC,EACpC,IAAsB;IAEtB,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,CAAA;IACnB,OAAO;QACL,IAAI;QACJ,IAAI,EAAE,CAAC,IAAI,EAAE,EAAE,CACb,KAAK,CAAU;YACb,GAAG,IAAI;YACP,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;SAChC,CAAC;QACJ,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CACf,OAAO,CAAU;YACf,GAAG,IAAI;YACP,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;SAC5B,CAAC;QACJ,IAAI,EAAE,CAAI,IAA4B,EAAE,EAAE,CACxC,KAAK,CAAa;YAChB,GAAG,IAAI;YACP,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;SAClC,CAAC;QACJ,IAAI,EAAE,CAAC,QAAQ,EAAE,IAAI,EAAE,EAAE;YACvB,IAAI,OAAO,QAAQ,KAAK,QAAQ;gBAAE,OAAO,KAAK,CAAC,QAAQ,CAAC,CAAA;YACxD,OAAO,KAAK,CAAO,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAA;QACpD,CAAC;QACD,IAAI,EAAE,CAAI,QAAuB,EAAE,EAAE;YACnC,MAAM,CAAC,GAAG,KAAK,CAAU,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;YAClD,OAAO,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,CAAoB,CAAC,CAAA;QAC5C,CAAC;QACD,QAAQ,EAAE,CAAI,KAAoB,EAAE,EAAE,CAAC,SAAS,CAAU,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QAChF,GAAG,EAAE,CAAI,CAAa,EAAE,EAAE;YACxB,MAAM,IAAI,GAAG,UAAU,CAAU,CAAC,CAAC,CAAA;YACnC,OAAO,CAAC,CAAM,EAAE,EAAE,CAAC,IAAI,CAAC,CAAoB,CAAC,CAAA;QAC/C,CAAC;KACF,CAAA;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function text<S>(accessor: ((s: S) => string) | (() => string) | string, mask?: number): Text;
2
+ //# sourceMappingURL=text.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../../src/primitives/text.ts"],"names":[],"mappings":"AAKA,wBAAgB,IAAI,CAAC,CAAC,EACpB,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,CAAC,GAAG,CAAC,MAAM,MAAM,CAAC,GAAG,MAAM,EACtD,IAAI,CAAC,EAAE,MAAM,GACZ,IAAI,CAiCN"}
@@ -0,0 +1,35 @@
1
+ import { getRenderContext } from '../render-context';
2
+ import { createBinding } from '../binding';
3
+ import { addItemUpdater } from '../scope';
4
+ import { FULL_MASK } from '../update-loop';
5
+ export function text(accessor, mask) {
6
+ if (typeof accessor === 'string') {
7
+ return document.createTextNode(accessor);
8
+ }
9
+ const ctx = getRenderContext();
10
+ const node = document.createTextNode('');
11
+ // Per-item accessor from each() — zero-arg function (length === 0)
12
+ // Register as direct updater, bypassing Phase 2 binding scan
13
+ if (accessor.length === 0) {
14
+ const get = accessor;
15
+ node.nodeValue = String(get());
16
+ addItemUpdater(ctx.rootScope, () => {
17
+ node.nodeValue = String(get());
18
+ });
19
+ return node;
20
+ }
21
+ // Component-level state accessor
22
+ const bindingMask = mask ?? FULL_MASK;
23
+ const binding = createBinding(ctx.rootScope, {
24
+ mask: bindingMask,
25
+ accessor: accessor,
26
+ kind: 'text',
27
+ node,
28
+ perItem: false,
29
+ });
30
+ const initialValue = accessor(ctx.state);
31
+ node.nodeValue = String(initialValue);
32
+ binding.lastValue = initialValue;
33
+ return node;
34
+ }
35
+ //# sourceMappingURL=text.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text.js","sourceRoot":"","sources":["../../src/primitives/text.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAC1C,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAE1C,MAAM,UAAU,IAAI,CAClB,QAAsD,EACtD,IAAa;IAEb,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE,CAAC;QACjC,OAAO,QAAQ,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAA;IAC1C,CAAC;IAED,MAAM,GAAG,GAAG,gBAAgB,EAAE,CAAA;IAC9B,MAAM,IAAI,GAAG,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC,CAAA;IAExC,mEAAmE;IACnE,6DAA6D;IAC7D,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,MAAM,GAAG,GAAG,QAAwB,CAAA;QACpC,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,GAAG,EAAE,CAAC,CAAA;QAC9B,cAAc,CAAC,GAAG,CAAC,SAAS,EAAE,GAAG,EAAE;YACjC,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,GAAG,EAAE,CAAC,CAAA;QAChC,CAAC,CAAC,CAAA;QACF,OAAO,IAAI,CAAA;IACb,CAAC;IAED,iCAAiC;IACjC,MAAM,WAAW,GAAG,IAAI,IAAI,SAAS,CAAA;IACrC,MAAM,OAAO,GAAG,aAAa,CAAC,GAAG,CAAC,SAAS,EAAE;QAC3C,IAAI,EAAE,WAAW;QACjB,QAAQ,EAAE,QAAqC;QAC/C,IAAI,EAAE,MAAM;QACZ,IAAI;QACJ,OAAO,EAAE,KAAK;KACf,CAAC,CAAA;IACF,MAAM,YAAY,GAAI,QAA6B,CAAC,GAAG,CAAC,KAAU,CAAC,CAAA;IACnE,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,YAAY,CAAC,CAAA;IACrC,OAAO,CAAC,SAAS,GAAG,YAAY,CAAA;IAEhC,OAAO,IAAI,CAAA;AACb,CAAC"}
@@ -0,0 +1,14 @@
1
+ import type { Scope, Binding } from './types';
2
+ import type { StructuralBlock } from './structural';
3
+ export interface RenderContext {
4
+ rootScope: Scope;
5
+ state: unknown;
6
+ allBindings: Binding[];
7
+ structuralBlocks: StructuralBlock[];
8
+ container?: Element;
9
+ send?: (msg: unknown) => void;
10
+ }
11
+ export declare function setRenderContext(ctx: RenderContext): void;
12
+ export declare function clearRenderContext(): void;
13
+ export declare function getRenderContext(): RenderContext;
14
+ //# sourceMappingURL=render-context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render-context.d.ts","sourceRoot":"","sources":["../src/render-context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AAC7C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAEnD,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,KAAK,CAAA;IAChB,KAAK,EAAE,OAAO,CAAA;IACd,WAAW,EAAE,OAAO,EAAE,CAAA;IACtB,gBAAgB,EAAE,eAAe,EAAE,CAAA;IACnC,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,CAAA;CAC9B;AAID,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,aAAa,GAAG,IAAI,CAEzD;AAED,wBAAgB,kBAAkB,IAAI,IAAI,CAEzC;AAED,wBAAgB,gBAAgB,IAAI,aAAa,CAKhD"}
@@ -0,0 +1,14 @@
1
+ let currentContext = null;
2
+ export function setRenderContext(ctx) {
3
+ currentContext = ctx;
4
+ }
5
+ export function clearRenderContext() {
6
+ currentContext = null;
7
+ }
8
+ export function getRenderContext() {
9
+ if (!currentContext) {
10
+ throw new Error('LLUI: primitives can only be called inside view()');
11
+ }
12
+ return currentContext;
13
+ }
14
+ //# sourceMappingURL=render-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render-context.js","sourceRoot":"","sources":["../src/render-context.ts"],"names":[],"mappings":"AAYA,IAAI,cAAc,GAAyB,IAAI,CAAA;AAE/C,MAAM,UAAU,gBAAgB,CAAC,GAAkB;IACjD,cAAc,GAAG,GAAG,CAAA;AACtB,CAAC;AAED,MAAM,UAAU,kBAAkB;IAChC,cAAc,GAAG,IAAI,CAAA;AACvB,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAA;IACtE,CAAC;IACD,OAAO,cAAc,CAAA;AACvB,CAAC"}
@@ -0,0 +1,4 @@
1
+ export declare function registerInstance(inst: object): void;
2
+ export declare function unregisterInstance(inst: object): void;
3
+ export declare function flush(): void;
4
+ //# sourceMappingURL=runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAKA,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAEnD;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAErD;AAED,wBAAgB,KAAK,IAAI,IAAI,CAI5B"}
@@ -0,0 +1,14 @@
1
+ import { flushInstance } from './update-loop';
2
+ const activeInstances = new Set();
3
+ export function registerInstance(inst) {
4
+ activeInstances.add(inst);
5
+ }
6
+ export function unregisterInstance(inst) {
7
+ activeInstances.delete(inst);
8
+ }
9
+ export function flush() {
10
+ for (const inst of activeInstances) {
11
+ flushInstance(inst);
12
+ }
13
+ }
14
+ //# sourceMappingURL=runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.js","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAG7C,MAAM,eAAe,GAAG,IAAI,GAAG,EAAU,CAAA;AAEzC,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;AAC3B,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,IAAY;IAC7C,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;AAC9B,CAAC;AAED,MAAM,UAAU,KAAK;IACnB,KAAK,MAAM,IAAI,IAAI,eAAe,EAAE,CAAC;QACnC,aAAa,CAAC,IAAyB,CAAC,CAAA;IAC1C,CAAC;AACH,CAAC"}
@@ -0,0 +1,24 @@
1
+ import type { Scope, Binding } from './types';
2
+ export declare function createScope(parent: Scope | null): Scope;
3
+ /**
4
+ * Dispose a scope and all its children. By default, detaches the scope
5
+ * from its parent's `children` array via `indexOf + splice` — O(N) per
6
+ * call, which becomes O(N²) when disposing many sibling scopes in bulk
7
+ * (e.g. `each` clearing 1000 rows).
8
+ *
9
+ * Pass `skipParentRemoval = true` when the caller will batch-remove
10
+ * children afterwards (see `removeOrphanedFromParent`). The scope's
11
+ * `parent` pointer is still set to `null` so the caller can identify
12
+ * orphaned entries.
13
+ */
14
+ export declare function disposeScope(scope: Scope, skipParentRemoval?: boolean): void;
15
+ /**
16
+ * Batch-remove children with `parent === null` from `parent.children`.
17
+ * Called after a bulk `disposeScope(child, true)` pass to collapse the
18
+ * individual O(N) splice operations into one O(N) scan.
19
+ */
20
+ export declare function removeOrphanedChildren(parent: Scope): void;
21
+ export declare function addBinding(scope: Scope, binding: Binding): void;
22
+ export declare function addItemUpdater(scope: Scope, updater: () => void): void;
23
+ export declare function addDisposer(scope: Scope, disposer: () => void): void;
24
+ //# sourceMappingURL=scope.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scope.d.ts","sourceRoot":"","sources":["../src/scope.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AAU7C,wBAAgB,WAAW,CAAC,MAAM,EAAE,KAAK,GAAG,IAAI,GAAG,KAAK,CAiBvD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,KAAK,EAAE,iBAAiB,UAAQ,GAAG,IAAI,CA+B1E;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,KAAK,GAAG,IAAI,CAO1D;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAI/D;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,IAAI,GAAG,IAAI,CAGtE;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI,CAGpE"}