sibujs 1.5.0 → 2.1.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 (208) hide show
  1. package/dist/browser.cjs +332 -121
  2. package/dist/browser.d.cts +5 -0
  3. package/dist/browser.d.ts +5 -0
  4. package/dist/browser.js +6 -6
  5. package/dist/build.cjs +1049 -344
  6. package/dist/build.js +15 -13
  7. package/dist/cdn.global.js +17 -16
  8. package/dist/chunk-2RA7SHDA.js +65 -0
  9. package/dist/chunk-2UPRY23K.js +80 -0
  10. package/dist/{chunk-BMPL52BF.js → chunk-3DZP6OIT.js} +118 -66
  11. package/dist/chunk-3JHCYHWN.js +125 -0
  12. package/dist/{chunk-CZUGLNJS.js → chunk-45YP72ZQ.js} +3 -3
  13. package/dist/{chunk-JCDUJN2F.js → chunk-AMK2TYNW.js} +490 -153
  14. package/dist/{chunk-NHUC2QWH.js → chunk-CWBVQML6.js} +1 -1
  15. package/dist/{chunk-XHK6BDAJ.js → chunk-DRUZZAK4.js} +25 -8
  16. package/dist/{chunk-RJ46C3CS.js → chunk-GWWURC5M.js} +71 -20
  17. package/dist/{chunk-3X2YG6YM.js → chunk-JYD2PWXH.js} +59 -28
  18. package/dist/{chunk-2BYQDGN3.js → chunk-KGYT6UO6.js} +234 -63
  19. package/dist/{chunk-5X6PP2UK.js → chunk-LMLD24FC.js} +2 -2
  20. package/dist/{chunk-M4NLBH4I.js → chunk-LYTCUZ7H.js} +3 -2
  21. package/dist/{chunk-XUEEGU5O.js → chunk-NASX6ST2.js} +16 -4
  22. package/dist/{chunk-VQDZK23A.js → chunk-O6EFQ3KT.js} +181 -66
  23. package/dist/{chunk-BGN5ZMP4.js → chunk-OJ3P4ECI.js} +14 -2
  24. package/dist/chunk-ON5MMR2J.js +1327 -0
  25. package/dist/{chunk-SFKNRVCU.js → chunk-P2HSJDDN.js} +135 -79
  26. package/dist/chunk-QO3WC6FS.js +384 -0
  27. package/dist/{chunk-WZSPOOER.js → chunk-RDTDJCAB.js} +8 -5
  28. package/dist/{chunk-7GRNSCFT.js → chunk-TH2ILCYW.js} +312 -185
  29. package/dist/chunk-UCS6AMJ7.js +79 -0
  30. package/dist/{chunk-VAPYJN4X.js → chunk-V6C4FADE.js} +93 -23
  31. package/dist/{chunk-OUZZEE4S.js → chunk-WANSMF2L.js} +17 -11
  32. package/dist/{chunk-23VV7YD3.js → chunk-WIPZPFBQ.js} +25 -30
  33. package/dist/chunk-WZA53FXU.js +149 -0
  34. package/dist/{chunk-BGTHZHJ5.js → chunk-ZAQSMOED.js} +188 -44
  35. package/dist/{customElement-BL3Uo8dL.d.cts → customElement-CPfIrbvg.d.cts} +14 -10
  36. package/dist/{customElement-BL3Uo8dL.d.ts → customElement-CPfIrbvg.d.ts} +14 -10
  37. package/dist/data.cjs +536 -151
  38. package/dist/data.d.cts +20 -2
  39. package/dist/data.d.ts +20 -2
  40. package/dist/data.js +11 -9
  41. package/dist/devtools.cjs +613 -266
  42. package/dist/devtools.d.cts +1 -1
  43. package/dist/devtools.d.ts +1 -1
  44. package/dist/devtools.js +12 -6
  45. package/dist/ecosystem.cjs +602 -197
  46. package/dist/ecosystem.d.cts +9 -7
  47. package/dist/ecosystem.d.ts +9 -7
  48. package/dist/ecosystem.js +12 -11
  49. package/dist/extras.cjs +3500 -1608
  50. package/dist/extras.d.cts +9 -9
  51. package/dist/extras.d.ts +9 -9
  52. package/dist/extras.js +58 -45
  53. package/dist/index.cjs +1055 -344
  54. package/dist/index.d.cts +85 -8
  55. package/dist/index.d.ts +85 -8
  56. package/dist/index.js +32 -16
  57. package/dist/{introspect-BumjnBKr.d.cts → introspect-2TOlQ7oa.d.cts} +25 -3
  58. package/dist/{introspect-CZrlcaYy.d.ts → introspect-DnIpHQQz.d.ts} +25 -3
  59. package/dist/motion.cjs +122 -63
  60. package/dist/motion.js +4 -4
  61. package/dist/patterns.cjs +450 -110
  62. package/dist/patterns.d.cts +11 -12
  63. package/dist/patterns.d.ts +11 -12
  64. package/dist/patterns.js +7 -7
  65. package/dist/performance.cjs +373 -149
  66. package/dist/performance.d.cts +23 -16
  67. package/dist/performance.d.ts +23 -16
  68. package/dist/performance.js +13 -8
  69. package/dist/plugin-D30wlGW5.d.cts +71 -0
  70. package/dist/plugin-D30wlGW5.d.ts +71 -0
  71. package/dist/plugins.cjs +729 -301
  72. package/dist/plugins.d.cts +10 -3
  73. package/dist/plugins.d.ts +10 -3
  74. package/dist/plugins.js +106 -38
  75. package/dist/{ssr-Do_SiVoL.d.cts → ssr-CrVNy6Pa.d.cts} +9 -15
  76. package/dist/{ssr-Do_SiVoL.d.ts → ssr-CrVNy6Pa.d.ts} +9 -15
  77. package/dist/{ssr-4PBXAOO3.js → ssr-FXD2PPMC.js} +4 -3
  78. package/dist/ssr.cjs +736 -274
  79. package/dist/ssr.d.cts +26 -6
  80. package/dist/ssr.d.ts +26 -6
  81. package/dist/ssr.js +12 -11
  82. package/dist/{tagFactory-DaJ0YWX6.d.cts → tagFactory-S17H2qxu.d.cts} +9 -1
  83. package/dist/{tagFactory-DaJ0YWX6.d.ts → tagFactory-S17H2qxu.d.ts} +9 -1
  84. package/dist/testing.cjs +303 -76
  85. package/dist/testing.d.cts +17 -4
  86. package/dist/testing.d.ts +17 -4
  87. package/dist/testing.js +100 -44
  88. package/dist/ui.cjs +589 -178
  89. package/dist/ui.d.cts +1 -1
  90. package/dist/ui.d.ts +1 -1
  91. package/dist/ui.js +20 -17
  92. package/dist/widgets.cjs +1103 -146
  93. package/dist/widgets.d.cts +104 -2
  94. package/dist/widgets.d.ts +104 -2
  95. package/dist/widgets.js +9 -7
  96. package/package.json +8 -2
  97. package/dist/chunk-32DY64NT.js +0 -282
  98. package/dist/chunk-3AIRKM3B.js +0 -1263
  99. package/dist/chunk-3ARAQO7B.js +0 -398
  100. package/dist/chunk-3CRQALYP.js +0 -877
  101. package/dist/chunk-4EI4AG32.js +0 -482
  102. package/dist/chunk-4MYMUBRS.js +0 -21
  103. package/dist/chunk-5ZYQ6KDD.js +0 -154
  104. package/dist/chunk-6BMPXPUW.js +0 -26
  105. package/dist/chunk-6HLLIF3K.js +0 -398
  106. package/dist/chunk-6LSNVCS2.js +0 -937
  107. package/dist/chunk-6SA3QQES.js +0 -61
  108. package/dist/chunk-77L6NL3X.js +0 -1097
  109. package/dist/chunk-7BF6TK55.js +0 -1097
  110. package/dist/chunk-7TQKR4PP.js +0 -294
  111. package/dist/chunk-7V26P53V.js +0 -712
  112. package/dist/chunk-AZ3ISID5.js +0 -298
  113. package/dist/chunk-B7SWRFUT.js +0 -332
  114. package/dist/chunk-BTU3TJDS.js +0 -365
  115. package/dist/chunk-BW3WT46K.js +0 -937
  116. package/dist/chunk-C6KFWOFV.js +0 -616
  117. package/dist/chunk-CHF5OHIA.js +0 -61
  118. package/dist/chunk-CHJ27IGK.js +0 -26
  119. package/dist/chunk-CMBFNA7L.js +0 -27
  120. package/dist/chunk-DAHRH4ON.js +0 -331
  121. package/dist/chunk-DKOHBI74.js +0 -924
  122. package/dist/chunk-DTCOOBMX.js +0 -725
  123. package/dist/chunk-EBGIRKQY.js +0 -616
  124. package/dist/chunk-EUZND3CB.js +0 -27
  125. package/dist/chunk-EVCZO745.js +0 -365
  126. package/dist/chunk-EWFVA3TJ.js +0 -282
  127. package/dist/chunk-F3FA4F32.js +0 -292
  128. package/dist/chunk-FGOEVHY3.js +0 -60
  129. package/dist/chunk-G3BOQPVO.js +0 -365
  130. package/dist/chunk-GCOK2LC3.js +0 -282
  131. package/dist/chunk-GJPXRJ45.js +0 -37
  132. package/dist/chunk-HGMJFBC7.js +0 -654
  133. package/dist/chunk-JAKHTMQU.js +0 -1000
  134. package/dist/chunk-JCI5M6U6.js +0 -956
  135. package/dist/chunk-K4G4ZQNR.js +0 -286
  136. package/dist/chunk-K5ZUMYVS.js +0 -89
  137. package/dist/chunk-KQPDEVVS.js +0 -398
  138. package/dist/chunk-L6JRBDNS.js +0 -60
  139. package/dist/chunk-LA6KQEDU.js +0 -712
  140. package/dist/chunk-MB6QFH3I.js +0 -2776
  141. package/dist/chunk-MDVXJWFN.js +0 -304
  142. package/dist/chunk-MEZVEBPN.js +0 -2008
  143. package/dist/chunk-MK4ERFYL.js +0 -2249
  144. package/dist/chunk-MLKGABMK.js +0 -9
  145. package/dist/chunk-MQ5GOYPH.js +0 -2249
  146. package/dist/chunk-MYRV7VDM.js +0 -742
  147. package/dist/chunk-N6IZB6KJ.js +0 -567
  148. package/dist/chunk-NEKUBFPT.js +0 -60
  149. package/dist/chunk-NMRUZALC.js +0 -1097
  150. package/dist/chunk-NYVAC6P5.js +0 -37
  151. package/dist/chunk-NZIIMDWI.js +0 -84
  152. package/dist/chunk-OF7UZIVB.js +0 -725
  153. package/dist/chunk-P3XWXJZU.js +0 -282
  154. package/dist/chunk-P6W3STU4.js +0 -2249
  155. package/dist/chunk-PBHF5WKN.js +0 -616
  156. package/dist/chunk-PDZQY43A.js +0 -616
  157. package/dist/chunk-PTQJDMRT.js +0 -146
  158. package/dist/chunk-PZEGYCF5.js +0 -61
  159. package/dist/chunk-QBMDLBU2.js +0 -975
  160. package/dist/chunk-QWZG56ET.js +0 -2744
  161. package/dist/chunk-RQGQSLQK.js +0 -725
  162. package/dist/chunk-SDLZDHKP.js +0 -107
  163. package/dist/chunk-TDGZL5CU.js +0 -365
  164. package/dist/chunk-TNQWPPE6.js +0 -37
  165. package/dist/chunk-TSOKIX5Z.js +0 -654
  166. package/dist/chunk-UHNL42EF.js +0 -2730
  167. package/dist/chunk-UNXCEF6S.js +0 -21
  168. package/dist/chunk-V2XTI523.js +0 -347
  169. package/dist/chunk-VAU366PN.js +0 -2241
  170. package/dist/chunk-VMVDTCXB.js +0 -712
  171. package/dist/chunk-VQNQZCWJ.js +0 -61
  172. package/dist/chunk-VRW3FULF.js +0 -725
  173. package/dist/chunk-WADYRCO2.js +0 -304
  174. package/dist/chunk-WILQZRO4.js +0 -282
  175. package/dist/chunk-WR5D4EGH.js +0 -26
  176. package/dist/chunk-WUHJISPP.js +0 -298
  177. package/dist/chunk-XYU6TZOW.js +0 -182
  178. package/dist/chunk-Y6GP4QGG.js +0 -276
  179. package/dist/chunk-YECR7UIA.js +0 -347
  180. package/dist/chunk-YUTWTI4B.js +0 -654
  181. package/dist/chunk-Z65KYU7I.js +0 -26
  182. package/dist/chunk-Z6POF5YC.js +0 -975
  183. package/dist/chunk-ZBJP6WFL.js +0 -482
  184. package/dist/chunk-ZD6OAMTH.js +0 -277
  185. package/dist/chunk-ZWKZCBO6.js +0 -317
  186. package/dist/contracts-DDrwxvJ-.d.cts +0 -245
  187. package/dist/contracts-DDrwxvJ-.d.ts +0 -245
  188. package/dist/contracts-DOrhwbke.d.cts +0 -245
  189. package/dist/contracts-DOrhwbke.d.ts +0 -245
  190. package/dist/contracts-xo5ckdRP.d.cts +0 -240
  191. package/dist/contracts-xo5ckdRP.d.ts +0 -240
  192. package/dist/customElement-BKQfbSZQ.d.cts +0 -262
  193. package/dist/customElement-BKQfbSZQ.d.ts +0 -262
  194. package/dist/customElement-D2DJp_xn.d.cts +0 -313
  195. package/dist/customElement-D2DJp_xn.d.ts +0 -313
  196. package/dist/customElement-yz8uyk-0.d.cts +0 -308
  197. package/dist/customElement-yz8uyk-0.d.ts +0 -308
  198. package/dist/introspect-Cb0zgpi2.d.cts +0 -477
  199. package/dist/introspect-Y2xNXGSf.d.ts +0 -477
  200. package/dist/plugin-Bek4RhJY.d.cts +0 -43
  201. package/dist/plugin-Bek4RhJY.d.ts +0 -43
  202. package/dist/ssr-3RXHP5ES.js +0 -38
  203. package/dist/ssr-6GIMY5MX.js +0 -38
  204. package/dist/ssr-BA6sxxUd.d.cts +0 -135
  205. package/dist/ssr-BA6sxxUd.d.ts +0 -135
  206. package/dist/ssr-WKUPVSSK.js +0 -36
  207. package/dist/tagFactory-Dl8QCLga.d.cts +0 -23
  208. package/dist/tagFactory-Dl8QCLga.d.ts +0 -23
@@ -1,19 +1,22 @@
1
1
  import {
2
- bindAttribute,
3
- registerDisposer
4
- } from "./chunk-5ZYQ6KDD.js";
2
+ bindAttribute
3
+ } from "./chunk-WIPZPFBQ.js";
5
4
  import {
6
5
  derived
7
- } from "./chunk-XHK6BDAJ.js";
6
+ } from "./chunk-DRUZZAK4.js";
7
+ import {
8
+ dispose,
9
+ registerDisposer
10
+ } from "./chunk-2UPRY23K.js";
8
11
  import {
9
12
  effect
10
- } from "./chunk-VQNQZCWJ.js";
13
+ } from "./chunk-WZA53FXU.js";
11
14
  import {
12
15
  signal
13
- } from "./chunk-NZIIMDWI.js";
16
+ } from "./chunk-RDTDJCAB.js";
14
17
  import {
15
18
  track
16
- } from "./chunk-K4G4ZQNR.js";
19
+ } from "./chunk-QO3WC6FS.js";
17
20
 
18
21
  // src/ui/form.ts
19
22
  function required(message = "This field is required") {
@@ -116,9 +119,18 @@ function form(config) {
116
119
  }
117
120
  return null;
118
121
  });
122
+ const wrappedSet = (next) => {
123
+ setValue(next);
124
+ setManualErrors((prev) => {
125
+ if (!(name in prev) || prev[name] == null) return prev;
126
+ const copy = { ...prev };
127
+ copy[name] = null;
128
+ return copy;
129
+ });
130
+ };
119
131
  fieldMap[name] = {
120
132
  value,
121
- set: setValue,
133
+ set: wrappedSet,
122
134
  error,
123
135
  touched: isTouched,
124
136
  touch: () => setTouched(true),
@@ -252,6 +264,7 @@ function intersection(options) {
252
264
  let observer = null;
253
265
  let currentElement = null;
254
266
  function observe(element) {
267
+ if (typeof IntersectionObserver === "undefined") return;
255
268
  unobserve();
256
269
  currentElement = element;
257
270
  observer = new IntersectionObserver((entries) => {
@@ -279,6 +292,11 @@ function intersection(options) {
279
292
  };
280
293
  }
281
294
  function lazyLoad(element, loader, options) {
295
+ if (typeof IntersectionObserver === "undefined") {
296
+ loader();
297
+ return () => {
298
+ };
299
+ }
282
300
  const observer = new IntersectionObserver((entries) => {
283
301
  for (const entry of entries) {
284
302
  if (entry.isIntersecting) {
@@ -353,7 +371,7 @@ function inputMask(options) {
353
371
  const stripRegex = buildStripRegex();
354
372
  const rawCharTest = options.pattern.includes("*") ? () => true : (c) => /[a-zA-Z0-9]/.test(c);
355
373
  function bind(input) {
356
- input.addEventListener("input", () => {
374
+ const onInput = () => {
357
375
  const cursorBefore = input.selectionStart ?? input.value.length;
358
376
  const oldValue = input.value;
359
377
  const raw = oldValue.replace(stripRegex, "");
@@ -377,13 +395,19 @@ function inputMask(options) {
377
395
  }
378
396
  }
379
397
  input.setSelectionRange(newCursor, newCursor);
380
- });
381
- input.addEventListener("focus", () => {
398
+ };
399
+ const onFocus = () => {
382
400
  if (!input.value) {
383
401
  const display = options.pattern.replace(/9/g, placeholder).replace(/A/g, placeholder).replace(/\*/g, placeholder);
384
402
  input.placeholder = display;
385
403
  }
386
- });
404
+ };
405
+ input.addEventListener("input", onInput);
406
+ input.addEventListener("focus", onFocus);
407
+ return () => {
408
+ input.removeEventListener("input", onInput);
409
+ input.removeEventListener("focus", onFocus);
410
+ };
387
411
  }
388
412
  return { value, rawValue, bind };
389
413
  }
@@ -425,8 +449,20 @@ function focus() {
425
449
  let currentElement = null;
426
450
  function bind(element) {
427
451
  currentElement = element;
428
- element.addEventListener("focus", () => setIsFocused(true));
429
- element.addEventListener("blur", () => setIsFocused(false));
452
+ const onFocus = () => setIsFocused(true);
453
+ const onBlur = () => setIsFocused(false);
454
+ element.addEventListener("focus", onFocus);
455
+ element.addEventListener("blur", onBlur);
456
+ let disposed = false;
457
+ const dispose2 = () => {
458
+ if (disposed) return;
459
+ disposed = true;
460
+ element.removeEventListener("focus", onFocus);
461
+ element.removeEventListener("blur", onBlur);
462
+ if (currentElement === element) currentElement = null;
463
+ };
464
+ registerDisposer(element, dispose2);
465
+ return dispose2;
430
466
  }
431
467
  function focus2() {
432
468
  currentElement?.focus();
@@ -441,11 +477,35 @@ function FocusTrap(nodes, options = {}) {
441
477
  container.setAttribute("data-sibu-focus-trap", "true");
442
478
  container.appendChild(nodes);
443
479
  const previouslyFocused = document.activeElement;
444
- container.addEventListener("keydown", (e) => {
480
+ const FOCUSABLE_SELECTOR = 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"]), [contenteditable]';
481
+ function isEffectivelyVisible(el) {
482
+ let node = el;
483
+ while (node) {
484
+ if (node.hasAttribute("inert")) return false;
485
+ if (node.getAttribute("aria-hidden") === "true") return false;
486
+ if (node.hidden) return false;
487
+ node = node.parentElement;
488
+ }
489
+ if (el.offsetParent === null && el.getClientRects().length === 0) return false;
490
+ return true;
491
+ }
492
+ function getFocusable() {
493
+ const raw = Array.from(container.querySelectorAll(FOCUSABLE_SELECTOR));
494
+ const out = [];
495
+ for (const el of raw) {
496
+ if (el.hasAttribute("disabled")) continue;
497
+ if (el.getAttribute("aria-hidden") === "true") continue;
498
+ if (el.hasAttribute("inert")) continue;
499
+ const ce = el.getAttribute("contenteditable");
500
+ if (ce !== null && ce === "false") continue;
501
+ if (!isEffectivelyVisible(el)) continue;
502
+ out.push(el);
503
+ }
504
+ return out;
505
+ }
506
+ const onTrapKeydown = (e) => {
445
507
  if (e.key !== "Tab") return;
446
- const focusable = container.querySelectorAll(
447
- 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
448
- );
508
+ const focusable = getFocusable();
449
509
  if (focusable.length === 0) {
450
510
  e.preventDefault();
451
511
  return;
@@ -463,18 +523,18 @@ function FocusTrap(nodes, options = {}) {
463
523
  first.focus();
464
524
  }
465
525
  }
466
- });
526
+ };
527
+ container.addEventListener("keydown", onTrapKeydown);
467
528
  if (options.autoFocus !== false) {
468
529
  queueMicrotask(() => {
469
- const first = container.querySelector(
470
- 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
471
- );
530
+ const first = getFocusable()[0];
472
531
  first?.focus();
473
532
  });
474
533
  }
475
534
  let trapObserver = null;
476
535
  function restoreFocusAndCleanup() {
477
536
  if (options.restoreFocus !== false) previouslyFocused?.focus();
537
+ container.removeEventListener("keydown", onTrapKeydown);
478
538
  if (trapObserver) {
479
539
  trapObserver.disconnect();
480
540
  trapObserver = null;
@@ -488,7 +548,7 @@ function FocusTrap(nodes, options = {}) {
488
548
  });
489
549
  queueMicrotask(() => {
490
550
  if (container.isConnected) {
491
- trapObserver.observe(document.body, { childList: true, subtree: true });
551
+ trapObserver.observe(container, { childList: true, subtree: true });
492
552
  }
493
553
  });
494
554
  }
@@ -525,7 +585,16 @@ function hotkey(combo, handler, options = {}) {
525
585
  document.addEventListener("keydown", listener);
526
586
  return () => document.removeEventListener("keydown", listener);
527
587
  }
528
- function announce(message, priority = "polite") {
588
+ var announceQueues = {
589
+ polite: [],
590
+ assertive: []
591
+ };
592
+ var announceDraining = {
593
+ polite: false,
594
+ assertive: false
595
+ };
596
+ var ANNOUNCE_INTERVAL_MS = 150;
597
+ function ensureLiveRegion(priority) {
529
598
  let region = document.getElementById(`sibu-announce-${priority}`);
530
599
  if (!region) {
531
600
  region = document.createElement("div");
@@ -536,11 +605,33 @@ function announce(message, priority = "polite") {
536
605
  region.style.cssText = "position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0;";
537
606
  document.body.appendChild(region);
538
607
  }
608
+ return region;
609
+ }
610
+ function drainAnnounceQueue(priority) {
611
+ if (announceDraining[priority]) return;
612
+ const queue = announceQueues[priority];
613
+ if (queue.length === 0) return;
614
+ announceDraining[priority] = true;
615
+ const region = ensureLiveRegion(priority);
616
+ const next = queue.shift();
539
617
  region.textContent = "";
540
618
  requestAnimationFrame(() => {
541
- if (region) region.textContent = message;
619
+ if (!region.isConnected) {
620
+ announceDraining[priority] = false;
621
+ return;
622
+ }
623
+ region.textContent = next;
624
+ setTimeout(() => {
625
+ announceDraining[priority] = false;
626
+ drainAnnounceQueue(priority);
627
+ }, ANNOUNCE_INTERVAL_MS);
542
628
  });
543
629
  }
630
+ function announce(message, priority = "polite") {
631
+ if (typeof document === "undefined") return;
632
+ announceQueues[priority].push(message);
633
+ drainAnnounceQueue(priority);
634
+ }
544
635
 
545
636
  // src/ui/scopedStyle.ts
546
637
  var scopeCounter = 0;
@@ -677,66 +768,91 @@ function bindData(el, key, getter) {
677
768
  }
678
769
 
679
770
  // src/ui/dialog.ts
771
+ var dialogStack = [];
772
+ var globalListenerAttached = false;
773
+ function __resetDialogStack() {
774
+ while (dialogStack.length > 0) dialogStack.pop();
775
+ if (typeof window !== "undefined" && globalListenerAttached) {
776
+ window.removeEventListener("keydown", handleGlobalKeydown);
777
+ globalListenerAttached = false;
778
+ }
779
+ }
780
+ function handleGlobalKeydown(event) {
781
+ if (event.key !== "Escape") return;
782
+ const top = dialogStack[dialogStack.length - 1];
783
+ if (top) top.close();
784
+ }
785
+ function ensureGlobalListener() {
786
+ if (typeof window === "undefined" || globalListenerAttached) return;
787
+ window.addEventListener("keydown", handleGlobalKeydown);
788
+ globalListenerAttached = true;
789
+ }
790
+ function removeGlobalListenerIfIdle() {
791
+ if (typeof window === "undefined") return;
792
+ if (!globalListenerAttached) return;
793
+ if (dialogStack.length > 0) return;
794
+ window.removeEventListener("keydown", handleGlobalKeydown);
795
+ globalListenerAttached = false;
796
+ }
680
797
  function dialog() {
681
798
  const [isOpen, setIsOpen] = signal(false);
682
- let listenerAttached = false;
683
- function handleKeydown(event) {
684
- if (event.key === "Escape") {
685
- close();
686
- }
799
+ const entry = { close: () => close() };
800
+ function pushOnStack() {
801
+ if (dialogStack.indexOf(entry) !== -1) return;
802
+ dialogStack.push(entry);
803
+ ensureGlobalListener();
687
804
  }
688
- function attachListener() {
689
- if (typeof window !== "undefined" && !listenerAttached) {
690
- window.addEventListener("keydown", handleKeydown);
691
- listenerAttached = true;
692
- }
693
- }
694
- function detachListener() {
695
- if (typeof window !== "undefined" && listenerAttached) {
696
- window.removeEventListener("keydown", handleKeydown);
697
- listenerAttached = false;
698
- }
805
+ function removeFromStack() {
806
+ const idx = dialogStack.indexOf(entry);
807
+ if (idx !== -1) dialogStack.splice(idx, 1);
808
+ removeGlobalListenerIfIdle();
699
809
  }
700
810
  function open() {
811
+ if (isOpen()) return;
701
812
  setIsOpen(true);
702
- attachListener();
813
+ pushOnStack();
703
814
  }
704
815
  function close() {
816
+ if (!isOpen()) {
817
+ removeFromStack();
818
+ return;
819
+ }
705
820
  setIsOpen(false);
706
- detachListener();
821
+ removeFromStack();
707
822
  }
708
823
  function toggle() {
709
824
  if (isOpen()) close();
710
825
  else open();
711
826
  }
712
- function dispose() {
713
- detachListener();
827
+ function dispose2() {
828
+ removeFromStack();
714
829
  setIsOpen(false);
715
830
  }
716
- return { open, close, isOpen, toggle, dispose };
831
+ return { open, close, isOpen, toggle, dispose: dispose2 };
717
832
  }
718
833
 
719
834
  // src/ui/toast.ts
720
- var toastCounter = 0;
721
835
  function toast(options) {
722
836
  const duration = options?.duration ?? 3e3;
723
837
  const maxToasts = options?.maxToasts ?? Infinity;
724
838
  const [toasts, setToasts] = signal([]);
725
839
  const timers = /* @__PURE__ */ new Map();
840
+ let toastCounter = 0;
726
841
  function show(message, type) {
727
842
  const id = `toast-${++toastCounter}`;
728
843
  const toast2 = { id, message, type };
844
+ const trimmedIds = [];
729
845
  setToasts((prev) => {
730
846
  const next = [...prev, toast2];
731
847
  if (next.length > maxToasts) {
732
848
  const removed = next.splice(0, next.length - maxToasts);
733
- for (const r of removed) {
734
- clearTimerForToast(r.id);
735
- }
849
+ for (const r of removed) trimmedIds.push(r.id);
736
850
  }
737
851
  return next;
738
852
  });
739
- if (duration > 0) {
853
+ for (const tid of trimmedIds) clearTimerForToast(tid);
854
+ const wasTrimmed = trimmedIds.indexOf(id) !== -1;
855
+ if (duration > 0 && !wasTrimmed) {
740
856
  const timer = setTimeout(() => {
741
857
  dismiss(id);
742
858
  }, duration);
@@ -822,14 +938,14 @@ function infiniteScroll(options) {
822
938
  },
823
939
  configurable: true
824
940
  });
825
- function dispose() {
941
+ function dispose2() {
826
942
  disposed = true;
827
943
  if (observer) {
828
944
  observer.disconnect();
829
945
  observer = null;
830
946
  }
831
947
  }
832
- return { sentinelRef: originalRef, loading, dispose };
948
+ return { sentinelRef: originalRef, loading, dispose: dispose2 };
833
949
  }
834
950
 
835
951
  // src/ui/pagination.ts
@@ -908,7 +1024,7 @@ function defineElement(name, component, options = {}) {
908
1024
  class SibuElement extends HTMLElement {
909
1025
  constructor() {
910
1026
  super();
911
- this._rendered = false;
1027
+ this._rendered = null;
912
1028
  if (options.shadow !== false) {
913
1029
  this._root = this.attachShadow({ mode: options.mode || "open" });
914
1030
  } else {
@@ -922,25 +1038,23 @@ function defineElement(name, component, options = {}) {
922
1038
  this._render();
923
1039
  }
924
1040
  disconnectedCallback() {
925
- if (this._root instanceof ShadowRoot) {
926
- this._root.innerHTML = "";
927
- }
928
- this._rendered = false;
1041
+ this._teardown();
929
1042
  }
930
1043
  attributeChangedCallback() {
931
1044
  if (this._rendered) {
932
1045
  this._render();
933
1046
  }
934
1047
  }
1048
+ _teardown() {
1049
+ if (this._rendered) {
1050
+ dispose(this._rendered);
1051
+ this._rendered = null;
1052
+ }
1053
+ this._root.replaceChildren();
1054
+ }
935
1055
  _render() {
1056
+ this._teardown();
936
1057
  const props = this._getProps();
937
- if (this._root instanceof ShadowRoot) {
938
- this._root.innerHTML = "";
939
- } else {
940
- while (this._root.firstChild) {
941
- this._root.removeChild(this._root.firstChild);
942
- }
943
- }
944
1058
  if (options.styles && this._root instanceof ShadowRoot) {
945
1059
  const styleEl = document.createElement("style");
946
1060
  styleEl.textContent = options.styles;
@@ -948,7 +1062,7 @@ function defineElement(name, component, options = {}) {
948
1062
  }
949
1063
  const el = component(props, this);
950
1064
  this._root.appendChild(el);
951
- this._rendered = true;
1065
+ this._rendered = el;
952
1066
  }
953
1067
  _getProps() {
954
1068
  const props = {};
@@ -1013,6 +1127,7 @@ export {
1013
1127
  bindAttrs,
1014
1128
  bindBoolAttr,
1015
1129
  bindData,
1130
+ __resetDialogStack,
1016
1131
  dialog,
1017
1132
  toast,
1018
1133
  infiniteScroll,
@@ -1,13 +1,15 @@
1
1
  import {
2
2
  signal
3
- } from "./chunk-WZSPOOER.js";
3
+ } from "./chunk-RDTDJCAB.js";
4
4
 
5
5
  // src/core/rendering/context.ts
6
6
  function context(defaultValue) {
7
7
  const [getValue, setValue] = signal(defaultValue);
8
- return {
8
+ const ctx = {
9
9
  provide(value) {
10
+ const previous = getValue();
10
11
  setValue(value);
12
+ return () => setValue(previous);
11
13
  },
12
14
  use() {
13
15
  return getValue;
@@ -17,8 +19,18 @@ function context(defaultValue) {
17
19
  },
18
20
  set(value) {
19
21
  setValue(value);
22
+ },
23
+ withContext(value, fn) {
24
+ const previous = getValue();
25
+ setValue(value);
26
+ try {
27
+ return fn();
28
+ } finally {
29
+ setValue(previous);
30
+ }
20
31
  }
21
32
  };
33
+ return ctx;
22
34
  }
23
35
 
24
36
  export {