sibujs 4.4.0 → 4.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/README.md +11 -0
  2. package/dist/browser.cjs +31 -2
  3. package/dist/browser.d.cts +15 -2
  4. package/dist/browser.d.ts +15 -2
  5. package/dist/browser.js +4 -4
  6. package/dist/build.cjs +92 -13
  7. package/dist/build.js +10 -10
  8. package/dist/cdn.dev.global.js +9 -9
  9. package/dist/cdn.full.dev.global.js +10 -10
  10. package/dist/cdn.full.global.js +9 -9
  11. package/dist/cdn.global.js +9 -9
  12. package/dist/{chunk-XLO7SLIX.js → chunk-2DCGACUU.js} +16 -9
  13. package/dist/{chunk-6GSIXTWX.js → chunk-3JZ4L5TJ.js} +10 -4
  14. package/dist/{chunk-UCALUKB5.js → chunk-4PMLNECI.js} +4 -4
  15. package/dist/{chunk-RR7M3FHM.js → chunk-7LN645I6.js} +1 -1
  16. package/dist/{chunk-SKPTERHP.js → chunk-B3WHI2QA.js} +1 -1
  17. package/dist/{chunk-4Z3SPQ67.js → chunk-FTIR4QW2.js} +13 -3
  18. package/dist/{chunk-HFCOH2GN.js → chunk-GW3SCCZG.js} +4 -4
  19. package/dist/{chunk-PNIRUQ4C.js → chunk-KEISJXBU.js} +2 -2
  20. package/dist/{chunk-LYVUX7NT.js → chunk-OMJJM3KM.js} +2 -2
  21. package/dist/{chunk-VCTAEPSB.js → chunk-ONOHFDLG.js} +9 -1
  22. package/dist/{chunk-36S2YPP4.js → chunk-PCT43HW3.js} +1 -1
  23. package/dist/{chunk-W2EQ7X2L.js → chunk-RBTPLM32.js} +46 -8
  24. package/dist/{chunk-7GIHSAWB.js → chunk-RIXRAYIU.js} +1 -1
  25. package/dist/{chunk-HQSEH5F6.js → chunk-RJE2BNI4.js} +3 -3
  26. package/dist/{chunk-ADM46X22.js → chunk-S373NSMK.js} +18 -13
  27. package/dist/{chunk-M2F7TZHH.js → chunk-TBYTO6BS.js} +2 -2
  28. package/dist/{chunk-3BTTCZ5J.js → chunk-UGRX3S57.js} +31 -2
  29. package/dist/{chunk-7NBDXVHS.js → chunk-VUF4ALSW.js} +1 -1
  30. package/dist/{chunk-LQFGQNMV.js → chunk-VZKNK2V7.js} +9 -4
  31. package/dist/{chunk-NVNJH22U.js → chunk-XZZOBQAY.js} +1 -1
  32. package/dist/{customElement-CNZxEB9G.d.ts → customElement-OB9CIsc5.d.cts} +38 -10
  33. package/dist/{customElement-CNZxEB9G.d.cts → customElement-OB9CIsc5.d.ts} +38 -10
  34. package/dist/data.cjs +81 -9
  35. package/dist/data.js +6 -6
  36. package/dist/devtools.cjs +41 -2
  37. package/dist/devtools.js +4 -4
  38. package/dist/ecosystem.cjs +83 -9
  39. package/dist/ecosystem.d.cts +13 -5
  40. package/dist/ecosystem.d.ts +13 -5
  41. package/dist/ecosystem.js +7 -7
  42. package/dist/extras.cjs +115 -14
  43. package/dist/extras.d.cts +2 -2
  44. package/dist/extras.d.ts +2 -2
  45. package/dist/extras.js +19 -19
  46. package/dist/index.cjs +92 -13
  47. package/dist/index.d.cts +24 -151
  48. package/dist/index.d.ts +24 -151
  49. package/dist/index.js +10 -10
  50. package/dist/motion.cjs +31 -2
  51. package/dist/motion.js +3 -3
  52. package/dist/patterns.cjs +81 -10
  53. package/dist/patterns.d.cts +5 -0
  54. package/dist/patterns.d.ts +5 -0
  55. package/dist/patterns.js +5 -5
  56. package/dist/performance.cjs +31 -2
  57. package/dist/performance.js +4 -4
  58. package/dist/plugins.cjs +39 -2
  59. package/dist/plugins.js +6 -6
  60. package/dist/ssr.cjs +39 -2
  61. package/dist/ssr.js +7 -7
  62. package/dist/tagFactory-DVoDpHye.d.cts +215 -0
  63. package/dist/tagFactory-DVoDpHye.d.ts +215 -0
  64. package/dist/testing.cjs +31 -2
  65. package/dist/testing.js +2 -2
  66. package/dist/ui.cjs +93 -13
  67. package/dist/ui.d.cts +1 -1
  68. package/dist/ui.d.ts +1 -1
  69. package/dist/ui.js +6 -6
  70. package/dist/widgets.cjs +75 -9
  71. package/dist/widgets.js +6 -6
  72. package/package.json +2 -2
  73. package/dist/tagFactory-Bzupt4Pj.d.cts +0 -55
  74. package/dist/tagFactory-Bzupt4Pj.d.ts +0 -55
@@ -1,22 +1,22 @@
1
1
  import {
2
2
  watch
3
- } from "./chunk-RR7M3FHM.js";
3
+ } from "./chunk-7LN645I6.js";
4
4
  import {
5
5
  createId
6
6
  } from "./chunk-CCSJMTRN.js";
7
7
  import {
8
8
  derived
9
- } from "./chunk-W2EQ7X2L.js";
9
+ } from "./chunk-RBTPLM32.js";
10
10
  import {
11
11
  stripHtml
12
12
  } from "./chunk-IXKSNWV5.js";
13
13
  import {
14
14
  effect
15
- } from "./chunk-7GIHSAWB.js";
15
+ } from "./chunk-RIXRAYIU.js";
16
16
  import {
17
17
  batch,
18
18
  signal
19
- } from "./chunk-NVNJH22U.js";
19
+ } from "./chunk-XZZOBQAY.js";
20
20
 
21
21
  // src/widgets/Combobox.ts
22
22
  var boundComboboxes = /* @__PURE__ */ new WeakMap();
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  bindAttribute,
3
3
  setSafeAttribute
4
- } from "./chunk-VCTAEPSB.js";
4
+ } from "./chunk-ONOHFDLG.js";
5
5
  import {
6
6
  isEventHandlerAttr,
7
7
  sanitizeCSSValue,
@@ -13,7 +13,7 @@ import {
13
13
  } from "./chunk-QKRPLZ2V.js";
14
14
  import {
15
15
  reactiveBinding
16
- } from "./chunk-3BTTCZ5J.js";
16
+ } from "./chunk-UGRX3S57.js";
17
17
  import {
18
18
  DEV,
19
19
  devWarn,
@@ -6,11 +6,11 @@ import {
6
6
  } from "./chunk-52XFPGSN.js";
7
7
  import {
8
8
  effect
9
- } from "./chunk-7GIHSAWB.js";
9
+ } from "./chunk-RIXRAYIU.js";
10
10
  import {
11
11
  batch,
12
12
  signal
13
- } from "./chunk-NVNJH22U.js";
13
+ } from "./chunk-XZZOBQAY.js";
14
14
  import {
15
15
  reportError
16
16
  } from "./chunk-2WLZ6757.js";
@@ -5,7 +5,7 @@ import {
5
5
  } from "./chunk-IXKSNWV5.js";
6
6
  import {
7
7
  reactiveBinding
8
- } from "./chunk-3BTTCZ5J.js";
8
+ } from "./chunk-UGRX3S57.js";
9
9
  import {
10
10
  DEV,
11
11
  devWarn,
@@ -62,6 +62,14 @@ function setSafeAttribute(el, name, value, options = {}) {
62
62
  const html = isHtmlElement(el);
63
63
  const idlName = html ? name.toLowerCase() : name;
64
64
  if (typeof value === "boolean") {
65
+ if (name.length > 5 && name.slice(0, 5).toLowerCase() === "aria-") {
66
+ const token = value ? "true" : "false";
67
+ if ((ns ? el.getAttributeNS(ns, localName) : el.getAttribute(name)) !== token) {
68
+ if (ns) el.setAttributeNS(ns, name, token);
69
+ else el.setAttribute(name, token);
70
+ }
71
+ return true;
72
+ }
65
73
  if (html && BOOLEAN_IDL_ATTRS.has(idlName) && idlName in el) {
66
74
  setProp(el, idlName, value);
67
75
  } else if (value) {
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  SVG_NS,
3
3
  tagFactory
4
- } from "./chunk-PNIRUQ4C.js";
4
+ } from "./chunk-KEISJXBU.js";
5
5
 
6
6
  // src/core/rendering/html.ts
7
7
  var html = tagFactory("html");
@@ -1,9 +1,10 @@
1
1
  import {
2
+ cleanup,
2
3
  isTrackingSuspended,
3
4
  recordDependency,
4
5
  retrack,
5
6
  track
6
- } from "./chunk-3BTTCZ5J.js";
7
+ } from "./chunk-UGRX3S57.js";
7
8
  import {
8
9
  devAssert
9
10
  } from "./chunk-2WLZ6757.js";
@@ -16,10 +17,14 @@ function derived(getter, options) {
16
17
  const cs = {};
17
18
  cs._d = false;
18
19
  cs._init = false;
20
+ cs._f = false;
19
21
  cs._g = getter;
20
22
  cs.__v = 0;
23
+ let evaluating = false;
24
+ let disposed = false;
25
+ let pendingError;
21
26
  const markDirty = () => {
22
- if (cs._d) return;
27
+ if (cs._d || disposed) return;
23
28
  cs._d = true;
24
29
  };
25
30
  markDirty._c = 1;
@@ -42,33 +47,53 @@ function derived(getter, options) {
42
47
  }
43
48
  }, markDirty);
44
49
  const hook = globalThis.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
45
- let evaluating = false;
46
50
  const validate = () => {
47
- if (!cs._d) return;
51
+ if (!cs._d || disposed || pendingError !== void 0) return;
48
52
  const oldValue = cs._v;
49
53
  evaluating = true;
50
54
  try {
51
55
  retrack(recompute, markDirty);
52
56
  if (!Object.is(oldValue, cs._v)) cs.__v++;
57
+ } catch (err) {
58
+ pendingError = { error: err };
59
+ cs.__v++;
60
+ if (disposed) cs._d = true;
61
+ else cs._f = true;
53
62
  } finally {
54
63
  evaluating = false;
64
+ if (disposed) cleanup(markDirty);
55
65
  }
56
- if (hook && !Object.is(oldValue, cs._v)) {
66
+ if (hook && !disposed && !Object.is(oldValue, cs._v)) {
57
67
  hook.emit("computed:update", { signal: cs, oldValue, newValue: cs._v });
58
68
  }
59
69
  };
60
70
  cs._validate = validate;
71
+ const throwPending = () => {
72
+ const { error } = pendingError;
73
+ pendingError = void 0;
74
+ if (disposed) cs._d = false;
75
+ throw error;
76
+ };
61
77
  function computedGetter() {
62
78
  if (evaluating) {
63
79
  throw new Error(
64
80
  `[SibuJS] Circular dependency detected in derived${debugName ? ` "${debugName}"` : ""}. A derived signal cannot read itself (directly or through a chain).`
65
81
  );
66
82
  }
67
- if (isTrackingSuspended()) {
68
- if (cs._d) validate();
83
+ if (isTrackingSuspended() || disposed) {
84
+ if (cs._d) {
85
+ validate();
86
+ if (pendingError !== void 0) throwPending();
87
+ }
69
88
  return cs._v;
70
89
  }
71
- if (cs._d) validate();
90
+ if (cs._d) {
91
+ validate();
92
+ if (pendingError !== void 0) {
93
+ recordDependency(cs);
94
+ throwPending();
95
+ }
96
+ }
72
97
  recordDependency(cs);
73
98
  return cs._v;
74
99
  }
@@ -77,6 +102,19 @@ function derived(getter, options) {
77
102
  cs.__name = debugName;
78
103
  }
79
104
  computedGetter.__signal = cs;
105
+ computedGetter.dispose = () => {
106
+ if (disposed) return;
107
+ disposed = true;
108
+ cs._d = pendingError !== void 0;
109
+ cleanup(markDirty);
110
+ const h = globalThis.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
111
+ if (h) {
112
+ try {
113
+ h.emit("computed:destroy", { signal: cs, getter: computedGetter });
114
+ } catch {
115
+ }
116
+ }
117
+ };
80
118
  if (hook) hook.emit("computed:create", { signal: cs, name: debugName, getter: computedGetter });
81
119
  return computedGetter;
82
120
  }
@@ -5,7 +5,7 @@ import {
5
5
  cleanup,
6
6
  retrack,
7
7
  untracked
8
- } from "./chunk-3BTTCZ5J.js";
8
+ } from "./chunk-UGRX3S57.js";
9
9
  import {
10
10
  devAssert,
11
11
  reportError
@@ -6,7 +6,7 @@ import {
6
6
  import {
7
7
  div,
8
8
  span
9
- } from "./chunk-36S2YPP4.js";
9
+ } from "./chunk-PCT43HW3.js";
10
10
  import {
11
11
  STATIC_VALUE_RESOLVER,
12
12
  planHeadElementEntry,
@@ -20,7 +20,7 @@ import {
20
20
  } from "./chunk-7ZHH77QA.js";
21
21
  import {
22
22
  effect
23
- } from "./chunk-7GIHSAWB.js";
23
+ } from "./chunk-RIXRAYIU.js";
24
24
  import {
25
25
  registerDisposer,
26
26
  replaceChildrenSafely
@@ -28,7 +28,7 @@ import {
28
28
  import {
29
29
  batch,
30
30
  signal
31
- } from "./chunk-NVNJH22U.js";
31
+ } from "./chunk-XZZOBQAY.js";
32
32
 
33
33
  // src/platform/head.ts
34
34
  function escapeScriptJsonLocal(json) {
@@ -135,42 +135,42 @@ import {
135
135
  use,
136
136
  var_,
137
137
  video
138
- } from "./chunk-36S2YPP4.js";
138
+ } from "./chunk-PCT43HW3.js";
139
139
  import {
140
140
  trustHTML
141
141
  } from "./chunk-NIOYEGBQ.js";
142
142
  import {
143
143
  watch
144
- } from "./chunk-RR7M3FHM.js";
144
+ } from "./chunk-7LN645I6.js";
145
145
  import {
146
146
  __resetIdCounter,
147
147
  createId
148
148
  } from "./chunk-CCSJMTRN.js";
149
149
  import {
150
150
  context
151
- } from "./chunk-7NBDXVHS.js";
151
+ } from "./chunk-VUF4ALSW.js";
152
152
  import {
153
153
  SVG_NS,
154
154
  bindChildNode,
155
155
  captureFocusWithin,
156
156
  restoreFocusWithin,
157
157
  tagFactory
158
- } from "./chunk-PNIRUQ4C.js";
158
+ } from "./chunk-KEISJXBU.js";
159
159
  import {
160
160
  bindAttribute,
161
161
  bindDynamic,
162
162
  setSafeAttribute
163
- } from "./chunk-VCTAEPSB.js";
163
+ } from "./chunk-ONOHFDLG.js";
164
164
  import {
165
165
  derived
166
- } from "./chunk-W2EQ7X2L.js";
166
+ } from "./chunk-RBTPLM32.js";
167
167
  import {
168
168
  globalSingleton
169
169
  } from "./chunk-7ZHH77QA.js";
170
170
  import {
171
171
  effect,
172
172
  on
173
- } from "./chunk-7GIHSAWB.js";
173
+ } from "./chunk-RIXRAYIU.js";
174
174
  import {
175
175
  disableSSR,
176
176
  enableSSR,
@@ -195,7 +195,7 @@ import {
195
195
  external,
196
196
  isBatching,
197
197
  signal
198
- } from "./chunk-NVNJH22U.js";
198
+ } from "./chunk-XZZOBQAY.js";
199
199
  import {
200
200
  notifySubscribers,
201
201
  reactiveBinding,
@@ -206,7 +206,7 @@ import {
206
206
  suspendTracking,
207
207
  track,
208
208
  untracked
209
- } from "./chunk-3BTTCZ5J.js";
209
+ } from "./chunk-UGRX3S57.js";
210
210
  import {
211
211
  DEV,
212
212
  __export,
@@ -1757,7 +1757,7 @@ function show(condition, element) {
1757
1757
  const update = () => {
1758
1758
  resolved.style.display = condition() ? "" : "none";
1759
1759
  };
1760
- registerDisposer(resolved, track(update));
1760
+ registerDisposer(resolved, reactiveBinding(update, resolved));
1761
1761
  return resolved;
1762
1762
  }
1763
1763
  function attachBranch(parent, anchor, branch, attachedOnce, where) {
@@ -1802,7 +1802,7 @@ function when(condition, thenBranch, elseBranch) {
1802
1802
  restoreFocusWithin(focused, currentNode ? [currentNode] : [], "when");
1803
1803
  initialized = true;
1804
1804
  };
1805
- registerDisposer(anchor, track(update));
1805
+ registerDisposer(anchor, reactiveBinding(update, anchor));
1806
1806
  if (!initialized) {
1807
1807
  queueMicrotask(() => {
1808
1808
  if (!initialized && anchor.parentNode) update();
@@ -1836,7 +1836,7 @@ function match(value, cases, fallback) {
1836
1836
  restoreFocusWithin(focused, currentNode ? [currentNode] : [], "match");
1837
1837
  initialized = true;
1838
1838
  };
1839
- registerDisposer(anchor, track(update));
1839
+ registerDisposer(anchor, reactiveBinding(update, anchor));
1840
1840
  if (!initialized) {
1841
1841
  queueMicrotask(() => {
1842
1842
  if (!initialized && anchor.parentNode) update();
@@ -1991,7 +1991,12 @@ function each(getArray, render, options) {
1991
1991
  const [indexGetter, setIndex] = signal(i2);
1992
1992
  let node;
1993
1993
  try {
1994
- node = resolveNodeChild(render(itemGetter, indexGetter));
1994
+ suspendTracking();
1995
+ try {
1996
+ node = resolveNodeChild(render(itemGetter, indexGetter));
1997
+ } finally {
1998
+ resumeTracking();
1999
+ }
1995
2000
  } catch (err) {
1996
2001
  const key2 = newKeys[i2];
1997
2002
  node = document.createComment(`each:error:${i2}`);
@@ -6,14 +6,14 @@ import {
6
6
  } from "./chunk-7ZHH77QA.js";
7
7
  import {
8
8
  effect
9
- } from "./chunk-7GIHSAWB.js";
9
+ } from "./chunk-RIXRAYIU.js";
10
10
  import {
11
11
  dispose,
12
12
  replaceChildrenSafely
13
13
  } from "./chunk-QKRPLZ2V.js";
14
14
  import {
15
15
  signal
16
- } from "./chunk-NVNJH22U.js";
16
+ } from "./chunk-XZZOBQAY.js";
17
17
  import {
18
18
  DEV,
19
19
  devWarn,
@@ -151,6 +151,15 @@ function untracked(fn) {
151
151
  var subscriberEpochCounter = 0;
152
152
  function retrack(effectFn, subscriber) {
153
153
  const prev = currentSubscriber;
154
+ let savedDepth = 0;
155
+ let savedSuspendSub = null;
156
+ if (trackingSuspended) {
157
+ savedDepth = suspendDepth;
158
+ savedSuspendSub = suspendSavedSub;
159
+ suspendDepth = 0;
160
+ suspendSavedSub = null;
161
+ trackingSuspended = false;
162
+ }
154
163
  currentSubscriber = subscriber;
155
164
  const sub = subscriber;
156
165
  const epoch = ++subscriberEpochCounter;
@@ -165,6 +174,11 @@ function retrack(effectFn, subscriber) {
165
174
  effectFn();
166
175
  } finally {
167
176
  currentSubscriber = prev;
177
+ if (savedDepth !== 0) {
178
+ suspendDepth = savedDepth;
179
+ suspendSavedSub = savedSuspendSub;
180
+ trackingSuspended = true;
181
+ }
168
182
  let node = sub.depsHead ?? null;
169
183
  while (node !== null) {
170
184
  const next = node.subNext;
@@ -184,11 +198,25 @@ function track(effectFn, subscriber) {
184
198
  if (!subscriber) return reactiveBinding(effectFn);
185
199
  cleanup(subscriber);
186
200
  const prev = currentSubscriber;
201
+ let savedDepth = 0;
202
+ let savedSuspendSub = null;
203
+ if (trackingSuspended) {
204
+ savedDepth = suspendDepth;
205
+ savedSuspendSub = suspendSavedSub;
206
+ suspendDepth = 0;
207
+ suspendSavedSub = null;
208
+ trackingSuspended = false;
209
+ }
187
210
  currentSubscriber = subscriber;
188
211
  try {
189
212
  effectFn();
190
213
  } finally {
191
214
  currentSubscriber = prev;
215
+ if (savedDepth !== 0) {
216
+ suspendDepth = savedDepth;
217
+ suspendSavedSub = savedSuspendSub;
218
+ trackingSuspended = true;
219
+ }
192
220
  const sub2 = subscriber;
193
221
  for (let n = sub2.depsHead ?? null; n !== null; n = n.subNext) {
194
222
  const sig = n.sig;
@@ -359,8 +387,9 @@ function propagateDirty(sub) {
359
387
  if (s._c) {
360
388
  const nSig = s._sig;
361
389
  if (nSig) {
362
- if (!nSig._d) {
390
+ if (!nSig._d || nSig._f === true) {
363
391
  nSig._d = true;
392
+ nSig._f = false;
364
393
  stack.push(nSig);
365
394
  }
366
395
  } else {
@@ -460,7 +489,7 @@ function forEachSubscriber(signal, visit) {
460
489
  }
461
490
 
462
491
  // src/reactivity/track.ts
463
- var _runtimeVersion = true ? "4.4.0" : "dev";
492
+ var _runtimeVersion = true ? "4.5.0" : "dev";
464
493
  var REGISTRY_KEY = /* @__PURE__ */ Symbol.for("sibujs.reactive.v1");
465
494
  function resolveReactiveApi() {
466
495
  const g = globalThis;
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-5DXA2J44.js";
4
4
  import {
5
5
  signal
6
- } from "./chunk-NVNJH22U.js";
6
+ } from "./chunk-XZZOBQAY.js";
7
7
  import {
8
8
  DEV,
9
9
  devWarn
@@ -4,14 +4,14 @@ import {
4
4
  } from "./chunk-H3SRKIYX.js";
5
5
  import {
6
6
  derived
7
- } from "./chunk-W2EQ7X2L.js";
7
+ } from "./chunk-RBTPLM32.js";
8
8
  import {
9
9
  effect
10
- } from "./chunk-7GIHSAWB.js";
10
+ } from "./chunk-RIXRAYIU.js";
11
11
  import {
12
12
  batch,
13
13
  signal
14
- } from "./chunk-NVNJH22U.js";
14
+ } from "./chunk-XZZOBQAY.js";
15
15
 
16
16
  // src/patterns/machine.ts
17
17
  function machine(config) {
@@ -487,7 +487,12 @@ function timeline(initial, maxHistory = 100) {
487
487
  setIndex(targetIndex);
488
488
  }
489
489
  }
490
- return { value, set, undo, redo, canUndo, canRedo, history, index, reset, jumpTo };
490
+ function dispose() {
491
+ value.dispose();
492
+ canUndo.dispose();
493
+ canRedo.dispose();
494
+ }
495
+ return { value, set, undo, redo, canUndo, canRedo, history, index, reset, jumpTo, dispose };
491
496
  }
492
497
 
493
498
  // src/patterns/globalStore.ts
@@ -3,7 +3,7 @@ import {
3
3
  notifySubscribers,
4
4
  queueSignalNotification,
5
5
  recordDependency
6
- } from "./chunk-3BTTCZ5J.js";
6
+ } from "./chunk-UGRX3S57.js";
7
7
  import {
8
8
  DEV
9
9
  } from "./chunk-2WLZ6757.js";
@@ -148,6 +148,17 @@ interface VirtualListProps<T> {
148
148
  }
149
149
  /**
150
150
  * VirtualList renders only visible items for efficient large-list rendering.
151
+ *
152
+ * Scope — it virtualizes ONE axis:
153
+ * - vertical only, inside a container of fixed `containerHeight`;
154
+ * - every item has the same fixed `itemHeight`;
155
+ * - on each scroll or `items()` change the visible window is disposed and
156
+ * re-rendered through `renderItem` (no keyed reuse of item nodes);
157
+ * - no horizontal virtualization, frozen rows/columns or sticky headers.
158
+ *
159
+ * Two-axis content (spreadsheets, large grids with frozen headers) needs its
160
+ * own windowing, typically a keyed `each()` over the visible row indices with a
161
+ * nested keyed `each()` over the visible column indices.
151
162
  */
152
163
  declare function VirtualList<T>(props: VirtualListProps<T>): HTMLElement;
153
164
 
@@ -302,6 +313,12 @@ declare function bindAttrs(el: HTMLElement, attrs: Record<string, AttributeSourc
302
313
  * Reactively toggle a boolean attribute (like disabled, readonly, hidden).
303
314
  * When the value is truthy the attribute is present (set to ""),
304
315
  * when falsy the attribute is removed entirely.
316
+ *
317
+ * `aria-*` names are the exception, as in every attribute writer: ARIA states
318
+ * are "true"/"false" tokens, and a missing state means "not applicable" rather
319
+ * than `false`, so `bindBoolAttr(el, "aria-busy", false)` writes
320
+ * `aria-busy="false"`. This helper cannot remove an ARIA attribute; use
321
+ * `bindAttribute(el, "aria-busy", () => (busy() ? true : null))` for that.
305
322
  * Returns a teardown function to stop reactive tracking.
306
323
  *
307
324
  * The attribute NAME is policed too: `bindBoolAttr(el, "onclick", true)` would
@@ -403,14 +420,7 @@ declare function infiniteScroll(options: {
403
420
  dispose: () => void;
404
421
  };
405
422
 
406
- /**
407
- * pagination provides reactive pagination state and controls.
408
- */
409
- declare function pagination(options: {
410
- totalItems: () => number;
411
- pageSize?: number;
412
- initialPage?: number;
413
- }): {
423
+ interface PaginationResult {
414
424
  page: () => number;
415
425
  pageSize: () => number;
416
426
  totalPages: () => number;
@@ -419,7 +429,25 @@ declare function pagination(options: {
419
429
  goTo: (page: number) => void;
420
430
  startIndex: () => number;
421
431
  endIndex: () => number;
422
- };
432
+ /**
433
+ * Release the subscriptions to `totalItems`. Call it when the pagination is
434
+ * discarded before the state it reads. Afterwards the accessors return their
435
+ * last values and the controls no longer move the page. Idempotent.
436
+ */
437
+ dispose: () => void;
438
+ }
439
+ /**
440
+ * pagination provides reactive pagination state and controls.
441
+ *
442
+ * It subscribes to the caller's `totalItems` getter, which usually lives longer
443
+ * than the pagination itself (a store, a query result). Call `dispose()` when
444
+ * the pagination is no longer used, e.g. `onUnmount(pager.dispose, el)`.
445
+ */
446
+ declare function pagination(options: {
447
+ totalItems: () => number;
448
+ pageSize?: number;
449
+ initialPage?: number;
450
+ }): PaginationResult;
423
451
 
424
452
  /**
425
453
  * eventBus creates a typed publish/subscribe event system.
@@ -458,4 +486,4 @@ declare function defineElement(name: string, component: (props: Record<string, u
458
486
  */
459
487
  declare function svgElement(tag: string, props?: Record<string, unknown>, ...nodes: (SVGElement | string)[]): SVGElement;
460
488
 
461
- export { type AttributeSource as A, type BoundFieldProps as B, type CustomElementOptions as C, intersection as D, lazyLoad as E, type FieldConfig as F, matchesPattern as G, max as H, type IntersectionResult as I, maxLength as J, min as K, minLength as L, type MaskOptions as M, pagination as N, phoneMask as O, removeScopedStyle as P, required as Q, scopedStyle as R, ssnMask as S, type Toast as T, svgElement as U, type ValidatorFn as V, timeMask as W, toast as X, withScopedStyle as Y, zipMask as Z, __resetDialogStack as _, type AttributeValue as a, FocusTrap as b, type FormConfig as c, type FormField as d, type FormReturn as e, type ToastInstance as f, VirtualList as g, type VirtualListProps as h, announce as i, aria as j, bindAttrs as k, bindBoolAttr as l, bindData as m, bindField as n, creditCardMask as o, custom as p, dateMask as q, defineElement as r, dialog as s, email as t, eventBus as u, focus as v, form as w, hotkey as x, infiniteScroll as y, inputMask as z };
489
+ export { zipMask as $, type AttributeSource as A, type BoundFieldProps as B, type CustomElementOptions as C, intersection as D, lazyLoad as E, type FieldConfig as F, matchesPattern as G, max as H, type IntersectionResult as I, maxLength as J, min as K, minLength as L, type MaskOptions as M, pagination as N, phoneMask as O, type PaginationResult as P, removeScopedStyle as Q, required as R, scopedStyle as S, type Toast as T, ssnMask as U, type ValidatorFn as V, svgElement as W, timeMask as X, toast as Y, withScopedStyle as Z, __resetDialogStack as _, type AttributeValue as a, FocusTrap as b, type FormConfig as c, type FormField as d, type FormReturn as e, type ToastInstance as f, VirtualList as g, type VirtualListProps as h, announce as i, aria as j, bindAttrs as k, bindBoolAttr as l, bindData as m, bindField as n, creditCardMask as o, custom as p, dateMask as q, defineElement as r, dialog as s, email as t, eventBus as u, focus as v, form as w, hotkey as x, infiniteScroll as y, inputMask as z };
@@ -148,6 +148,17 @@ interface VirtualListProps<T> {
148
148
  }
149
149
  /**
150
150
  * VirtualList renders only visible items for efficient large-list rendering.
151
+ *
152
+ * Scope — it virtualizes ONE axis:
153
+ * - vertical only, inside a container of fixed `containerHeight`;
154
+ * - every item has the same fixed `itemHeight`;
155
+ * - on each scroll or `items()` change the visible window is disposed and
156
+ * re-rendered through `renderItem` (no keyed reuse of item nodes);
157
+ * - no horizontal virtualization, frozen rows/columns or sticky headers.
158
+ *
159
+ * Two-axis content (spreadsheets, large grids with frozen headers) needs its
160
+ * own windowing, typically a keyed `each()` over the visible row indices with a
161
+ * nested keyed `each()` over the visible column indices.
151
162
  */
152
163
  declare function VirtualList<T>(props: VirtualListProps<T>): HTMLElement;
153
164
 
@@ -302,6 +313,12 @@ declare function bindAttrs(el: HTMLElement, attrs: Record<string, AttributeSourc
302
313
  * Reactively toggle a boolean attribute (like disabled, readonly, hidden).
303
314
  * When the value is truthy the attribute is present (set to ""),
304
315
  * when falsy the attribute is removed entirely.
316
+ *
317
+ * `aria-*` names are the exception, as in every attribute writer: ARIA states
318
+ * are "true"/"false" tokens, and a missing state means "not applicable" rather
319
+ * than `false`, so `bindBoolAttr(el, "aria-busy", false)` writes
320
+ * `aria-busy="false"`. This helper cannot remove an ARIA attribute; use
321
+ * `bindAttribute(el, "aria-busy", () => (busy() ? true : null))` for that.
305
322
  * Returns a teardown function to stop reactive tracking.
306
323
  *
307
324
  * The attribute NAME is policed too: `bindBoolAttr(el, "onclick", true)` would
@@ -403,14 +420,7 @@ declare function infiniteScroll(options: {
403
420
  dispose: () => void;
404
421
  };
405
422
 
406
- /**
407
- * pagination provides reactive pagination state and controls.
408
- */
409
- declare function pagination(options: {
410
- totalItems: () => number;
411
- pageSize?: number;
412
- initialPage?: number;
413
- }): {
423
+ interface PaginationResult {
414
424
  page: () => number;
415
425
  pageSize: () => number;
416
426
  totalPages: () => number;
@@ -419,7 +429,25 @@ declare function pagination(options: {
419
429
  goTo: (page: number) => void;
420
430
  startIndex: () => number;
421
431
  endIndex: () => number;
422
- };
432
+ /**
433
+ * Release the subscriptions to `totalItems`. Call it when the pagination is
434
+ * discarded before the state it reads. Afterwards the accessors return their
435
+ * last values and the controls no longer move the page. Idempotent.
436
+ */
437
+ dispose: () => void;
438
+ }
439
+ /**
440
+ * pagination provides reactive pagination state and controls.
441
+ *
442
+ * It subscribes to the caller's `totalItems` getter, which usually lives longer
443
+ * than the pagination itself (a store, a query result). Call `dispose()` when
444
+ * the pagination is no longer used, e.g. `onUnmount(pager.dispose, el)`.
445
+ */
446
+ declare function pagination(options: {
447
+ totalItems: () => number;
448
+ pageSize?: number;
449
+ initialPage?: number;
450
+ }): PaginationResult;
423
451
 
424
452
  /**
425
453
  * eventBus creates a typed publish/subscribe event system.
@@ -458,4 +486,4 @@ declare function defineElement(name: string, component: (props: Record<string, u
458
486
  */
459
487
  declare function svgElement(tag: string, props?: Record<string, unknown>, ...nodes: (SVGElement | string)[]): SVGElement;
460
488
 
461
- export { type AttributeSource as A, type BoundFieldProps as B, type CustomElementOptions as C, intersection as D, lazyLoad as E, type FieldConfig as F, matchesPattern as G, max as H, type IntersectionResult as I, maxLength as J, min as K, minLength as L, type MaskOptions as M, pagination as N, phoneMask as O, removeScopedStyle as P, required as Q, scopedStyle as R, ssnMask as S, type Toast as T, svgElement as U, type ValidatorFn as V, timeMask as W, toast as X, withScopedStyle as Y, zipMask as Z, __resetDialogStack as _, type AttributeValue as a, FocusTrap as b, type FormConfig as c, type FormField as d, type FormReturn as e, type ToastInstance as f, VirtualList as g, type VirtualListProps as h, announce as i, aria as j, bindAttrs as k, bindBoolAttr as l, bindData as m, bindField as n, creditCardMask as o, custom as p, dateMask as q, defineElement as r, dialog as s, email as t, eventBus as u, focus as v, form as w, hotkey as x, infiniteScroll as y, inputMask as z };
489
+ export { zipMask as $, type AttributeSource as A, type BoundFieldProps as B, type CustomElementOptions as C, intersection as D, lazyLoad as E, type FieldConfig as F, matchesPattern as G, max as H, type IntersectionResult as I, maxLength as J, min as K, minLength as L, type MaskOptions as M, pagination as N, phoneMask as O, type PaginationResult as P, removeScopedStyle as Q, required as R, scopedStyle as S, type Toast as T, ssnMask as U, type ValidatorFn as V, svgElement as W, timeMask as X, toast as Y, withScopedStyle as Z, __resetDialogStack as _, type AttributeValue as a, FocusTrap as b, type FormConfig as c, type FormField as d, type FormReturn as e, type ToastInstance as f, VirtualList as g, type VirtualListProps as h, announce as i, aria as j, bindAttrs as k, bindBoolAttr as l, bindData as m, bindField as n, creditCardMask as o, custom as p, dateMask as q, defineElement as r, dialog as s, email as t, eventBus as u, focus as v, form as w, hotkey as x, infiniteScroll as y, inputMask as z };