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
@@ -139,60 +139,70 @@ import {
139
139
  use,
140
140
  var_,
141
141
  video
142
- } from "./chunk-P3XWXJZU.js";
142
+ } from "./chunk-CWBVQML6.js";
143
143
  import {
144
144
  watch
145
- } from "./chunk-GJPXRJ45.js";
145
+ } from "./chunk-45YP72ZQ.js";
146
+ import {
147
+ trustHTML
148
+ } from "./chunk-JYD2PWXH.js";
146
149
  import {
147
150
  context
148
- } from "./chunk-6BMPXPUW.js";
151
+ } from "./chunk-OJ3P4ECI.js";
149
152
  import {
150
153
  SVG_NS,
151
154
  bindChildNode,
152
155
  tagFactory
153
- } from "./chunk-SFKNRVCU.js";
156
+ } from "./chunk-P2HSJDDN.js";
154
157
  import {
155
158
  bindAttribute,
156
- bindDynamic,
159
+ bindDynamic
160
+ } from "./chunk-WIPZPFBQ.js";
161
+ import {
162
+ derived
163
+ } from "./chunk-DRUZZAK4.js";
164
+ import {
157
165
  checkLeaks,
158
166
  dispose,
159
167
  registerDisposer
160
- } from "./chunk-5ZYQ6KDD.js";
161
- import {
162
- derived
163
- } from "./chunk-XHK6BDAJ.js";
168
+ } from "./chunk-2UPRY23K.js";
164
169
  import {
165
170
  isUrlAttribute,
171
+ sanitizeSrcset,
166
172
  sanitizeUrl
167
- } from "./chunk-CMBFNA7L.js";
173
+ } from "./chunk-UCS6AMJ7.js";
168
174
  import {
169
175
  effect,
170
176
  on
171
- } from "./chunk-VQNQZCWJ.js";
177
+ } from "./chunk-WZA53FXU.js";
172
178
  import {
173
179
  disableSSR,
174
180
  enableSSR,
181
+ getSSRStore,
175
182
  isSSR,
183
+ runInSSRContext,
176
184
  withSSR
177
- } from "./chunk-EUZND3CB.js";
185
+ } from "./chunk-2RA7SHDA.js";
178
186
  import {
179
187
  batch,
180
188
  enqueueBatchedSignal,
181
189
  isBatching,
182
190
  signal
183
- } from "./chunk-NZIIMDWI.js";
191
+ } from "./chunk-RDTDJCAB.js";
184
192
  import {
185
193
  notifySubscribers,
186
194
  recordDependency,
195
+ retrack,
196
+ setMaxDrainIterations,
187
197
  track,
188
198
  untracked
189
- } from "./chunk-K4G4ZQNR.js";
199
+ } from "./chunk-QO3WC6FS.js";
190
200
  import {
191
201
  __export,
192
202
  devAssert,
193
203
  devWarn,
194
204
  isDev
195
- } from "./chunk-5X6PP2UK.js";
205
+ } from "./chunk-LMLD24FC.js";
196
206
 
197
207
  // index.ts
198
208
  var index_exports = {};
@@ -276,6 +286,7 @@ __export(index_exports, {
276
286
  footer: () => footer,
277
287
  form: () => form,
278
288
  g: () => g,
289
+ getSSRStore: () => getSSRStore,
279
290
  getSlot: () => getSlot,
280
291
  h1: () => h1,
281
292
  h2: () => h2,
@@ -345,15 +356,18 @@ __export(index_exports, {
345
356
  registerComponent: () => registerComponent,
346
357
  registerDisposer: () => registerDisposer,
347
358
  resolveComponent: () => resolveComponent,
359
+ retrack: () => retrack,
348
360
  rp: () => rp,
349
361
  rt: () => rt,
350
362
  ruby: () => ruby,
363
+ runInSSRContext: () => runInSSRContext,
351
364
  s: () => s,
352
365
  samp: () => samp,
353
366
  script: () => script,
354
367
  section: () => section,
355
368
  select: () => select,
356
369
  setGlobalErrorHandler: () => setGlobalErrorHandler,
370
+ setMaxDrainIterations: () => setMaxDrainIterations,
357
371
  show: () => show,
358
372
  signal: () => signal,
359
373
  slot: () => slot,
@@ -373,6 +387,7 @@ __export(index_exports, {
373
387
  symbol: () => symbol,
374
388
  table: () => table,
375
389
  tagFactory: () => tagFactory,
390
+ takePendingError: () => takePendingError,
376
391
  tbody: () => tbody,
377
392
  td: () => td,
378
393
  template: () => template,
@@ -387,6 +402,7 @@ __export(index_exports, {
387
402
  track: () => track2,
388
403
  transition: () => transition,
389
404
  trapFocus: () => trapFocus,
405
+ trustHTML: () => trustHTML,
390
406
  tspan: () => tspan,
391
407
  u: () => u,
392
408
  ul: () => ul,
@@ -402,6 +418,8 @@ __export(index_exports, {
402
418
  });
403
419
 
404
420
  // src/core/rendering/htm.ts
421
+ var _isDev = isDev();
422
+ var RAW_TEXT_TAGS = /* @__PURE__ */ new Set(["script", "style"]);
405
423
  var VOID_ELEMENTS = /* @__PURE__ */ new Set([
406
424
  "area",
407
425
  "base",
@@ -586,6 +604,15 @@ function parseTemplate(strings) {
586
604
  children.push({ t: 0, el: { tag, svg: SVG_TAGS.has(tag), attrs, children: [] } });
587
605
  } else {
588
606
  const inner = parseChildren();
607
+ if (RAW_TEXT_TAGS.has(tag.toLowerCase())) {
608
+ for (let i2 = 0; i2 < inner.length; i2++) {
609
+ if (inner[i2].t === 2) {
610
+ throw new Error(
611
+ `html: dynamic \${...} expressions are not allowed inside <${tag}> (raw-text context). Build the content separately and append it as a Node.`
612
+ );
613
+ }
614
+ }
615
+ }
589
616
  if (template2[pos] === "<" && pos + 1 < len && template2[pos + 1] === "/") {
590
617
  pos += 2;
591
618
  readTagName();
@@ -612,27 +639,50 @@ function executeElement(tmpl, values) {
612
639
  break;
613
640
  case 1: {
614
641
  const name = attr.name;
615
- if (name[0] === "o" && name[1] === "n") break;
642
+ const lname = name.toLowerCase();
643
+ if (lname[0] === "o" && lname[1] === "n") break;
616
644
  const val = values[attr.idx];
617
645
  if (typeof val === "function") {
618
646
  registerDisposer(el, bindAttribute(el, name, val));
619
647
  } else if (val != null) {
620
648
  const str = String(val);
621
- el.setAttribute(name, isUrlAttribute(name) ? sanitizeUrl(str) : str);
649
+ if (lname === "srcset") {
650
+ el.setAttribute(name, sanitizeSrcset(str));
651
+ } else if (isUrlAttribute(lname)) {
652
+ el.setAttribute(name, sanitizeUrl(str));
653
+ } else {
654
+ el.setAttribute(name, str);
655
+ }
622
656
  }
623
657
  break;
624
658
  }
625
659
  case 2: {
626
660
  let val = attr.statics[0];
627
661
  for (let j = 0; j < attr.exprs.length; j++) {
628
- val += String(values[attr.exprs[j]]) + attr.statics[j + 1];
662
+ const ev = values[attr.exprs[j]];
663
+ val += (ev == null ? "" : String(ev)) + attr.statics[j + 1];
664
+ }
665
+ const lname2 = attr.name.toLowerCase();
666
+ if (lname2 === "srcset") {
667
+ el.setAttribute(attr.name, sanitizeSrcset(val));
668
+ } else if (isUrlAttribute(lname2)) {
669
+ el.setAttribute(attr.name, sanitizeUrl(val));
670
+ } else {
671
+ el.setAttribute(attr.name, val);
629
672
  }
630
- el.setAttribute(attr.name, val);
631
673
  break;
632
674
  }
633
- case 3:
634
- el.addEventListener(attr.name, values[attr.idx]);
675
+ case 3: {
676
+ const fn = values[attr.idx];
677
+ if (typeof fn === "function") {
678
+ el.addEventListener(attr.name, fn);
679
+ } else if (_isDev) {
680
+ devWarn(
681
+ `html: on:${attr.name} handler is not a function (got ${typeof fn}). Event listener was not attached.`
682
+ );
683
+ }
635
684
  break;
685
+ }
636
686
  case 4:
637
687
  el.setAttribute(attr.name, "");
638
688
  break;
@@ -726,7 +776,7 @@ function html(strings, ...values) {
726
776
  function mount(component, container) {
727
777
  if (!container) {
728
778
  throw new Error(
729
- "[Sibu] mount: container element not found. Make sure the DOM element exists before calling mount()."
779
+ "[SibuJS mount] container element not found. Make sure the DOM element exists before calling mount()."
730
780
  );
731
781
  }
732
782
  devAssert(
@@ -754,7 +804,7 @@ function mount(component, container) {
754
804
  }
755
805
 
756
806
  // src/core/rendering/each.ts
757
- var _isDev = isDev();
807
+ var _isDev2 = isDev();
758
808
  function resolveNodeChild(child) {
759
809
  if (typeof child === "function") {
760
810
  return resolveNodeChild(child());
@@ -849,17 +899,31 @@ function each(getArray, render, options) {
849
899
  node = existing;
850
900
  } else {
851
901
  const itemKey = key;
852
- const itemGetter = () => getArray()[keyIndexMap.get(itemKey)];
902
+ const itemGetter = () => untracked(() => getArray()[keyIndexMap.get(itemKey)]);
853
903
  const indexGetter = () => keyIndexMap.get(itemKey);
854
904
  try {
855
905
  node = resolveNodeChild(render(itemGetter, indexGetter));
856
906
  } catch (err) {
857
- if (_isDev) {
907
+ if (_isDev2) {
858
908
  devWarn(
859
909
  `each: render threw for item at index ${i2} (key="${newKeys[i2]}"): ${err instanceof Error ? err.message : String(err)}`
860
910
  );
861
911
  }
862
912
  node = document.createComment(`each:error:${i2}`);
913
+ const errorObj = err instanceof Error ? err : new Error(String(err));
914
+ queueMicrotask(() => {
915
+ try {
916
+ const target = anchor.parentNode;
917
+ if (target?.dispatchEvent) {
918
+ target.dispatchEvent(
919
+ new CustomEvent("sibu:error-propagate", { bubbles: true, detail: { error: errorObj } })
920
+ );
921
+ } else if (_isDev2) {
922
+ devWarn(`each: error not surfaced \u2014 anchor detached: ${errorObj.message}`);
923
+ }
924
+ } catch {
925
+ }
926
+ });
863
927
  }
864
928
  }
865
929
  workMap.set(key, node);
@@ -928,7 +992,8 @@ function each(getArray, render, options) {
928
992
  workMap = tmp;
929
993
  initialized = true;
930
994
  };
931
- track(update);
995
+ const untrack = track(update);
996
+ registerDisposer(anchor, untrack);
932
997
  if (!initialized) {
933
998
  queueMicrotask(() => {
934
999
  if (!initialized && anchor.parentNode) {
@@ -975,7 +1040,9 @@ function Portal(nodes, target) {
975
1040
  const anchor = document.createComment("portal");
976
1041
  const container = target || document.body;
977
1042
  let portalContent = null;
1043
+ let disposed = false;
978
1044
  queueMicrotask(() => {
1045
+ if (disposed) return;
979
1046
  try {
980
1047
  portalContent = nodes();
981
1048
  container.appendChild(portalContent);
@@ -983,9 +1050,22 @@ function Portal(nodes, target) {
983
1050
  if (typeof console !== "undefined") {
984
1051
  console.error("[Portal] Render error:", err);
985
1052
  }
1053
+ const errorObj = err instanceof Error ? err : new Error(String(err));
1054
+ queueMicrotask(() => {
1055
+ try {
1056
+ const target2 = anchor.parentNode;
1057
+ if (target2?.dispatchEvent) {
1058
+ target2.dispatchEvent(
1059
+ new CustomEvent("sibu:error-propagate", { bubbles: true, detail: { error: errorObj } })
1060
+ );
1061
+ }
1062
+ } catch {
1063
+ }
1064
+ });
986
1065
  }
987
1066
  });
988
1067
  registerDisposer(anchor, () => {
1068
+ disposed = true;
989
1069
  if (portalContent) {
990
1070
  dispose(portalContent);
991
1071
  portalContent.remove();
@@ -1025,7 +1105,8 @@ function DynamicComponent(is) {
1025
1105
  }
1026
1106
  container.replaceChildren(el);
1027
1107
  }
1028
- track(render);
1108
+ const untrack = track(render);
1109
+ registerDisposer(container, untrack);
1029
1110
  return container;
1030
1111
  }
1031
1112
 
@@ -1115,11 +1196,16 @@ function KeepAlive(activeKey, cases, options) {
1115
1196
  const anchor = document.createComment("keep-alive");
1116
1197
  const cache2 = /* @__PURE__ */ new Map();
1117
1198
  const lruOrder = [];
1118
- const max = options?.max ?? 0;
1199
+ const max = options?.max ?? 10;
1200
+ if (max === 0 && isDev()) {
1201
+ devWarn("KeepAlive: unbounded cache (max: 0). Cached subtrees will never be evicted \u2014 set `max` to bound memory.");
1202
+ }
1119
1203
  let currentKey;
1120
1204
  let currentNode = null;
1121
1205
  let initialized = false;
1206
+ let disposed = false;
1122
1207
  const update = () => {
1208
+ if (disposed) return;
1123
1209
  const key = activeKey();
1124
1210
  const parent = anchor.parentNode;
1125
1211
  if (!parent) return;
@@ -1159,12 +1245,23 @@ function KeepAlive(activeKey, cases, options) {
1159
1245
  currentNode = node;
1160
1246
  initialized = true;
1161
1247
  };
1162
- track(update);
1248
+ const untrack = track(update);
1163
1249
  if (!initialized) {
1164
1250
  queueMicrotask(() => {
1165
1251
  if (!initialized && anchor.parentNode) update();
1166
1252
  });
1167
1253
  }
1254
+ registerDisposer(anchor, () => {
1255
+ disposed = true;
1256
+ untrack();
1257
+ for (const node of cache2.values()) {
1258
+ dispose(node);
1259
+ if (node.parentNode) node.parentNode.removeChild(node);
1260
+ }
1261
+ cache2.clear();
1262
+ lruOrder.length = 0;
1263
+ currentNode = null;
1264
+ });
1168
1265
  return anchor;
1169
1266
  }
1170
1267
 
@@ -1314,7 +1411,7 @@ function store(initialState) {
1314
1411
  },
1315
1412
  set() {
1316
1413
  throw new Error(
1317
- "[Sibu] store: Direct mutation is not allowed. Use actions.setState() to update store properties."
1414
+ "[SibuJS store] Direct mutation is not allowed. Use actions.setState() to update store properties."
1318
1415
  );
1319
1416
  }
1320
1417
  });
@@ -1328,16 +1425,20 @@ function store(initialState) {
1328
1425
  const setState = (patch) => {
1329
1426
  const current = getSnapshot();
1330
1427
  const nextState = typeof patch === "function" ? patch(current) : patch;
1331
- Object.entries(nextState).forEach(([key, value]) => {
1332
- if (key in signals) {
1333
- signals[key][1](value);
1334
- }
1428
+ batch(() => {
1429
+ Object.entries(nextState).forEach(([key, value]) => {
1430
+ if (key in signals) {
1431
+ signals[key][1](value);
1432
+ }
1433
+ });
1335
1434
  });
1336
1435
  };
1337
1436
  const reset = () => {
1338
- Object.keys(initialState).forEach((key) => {
1339
- const setter = signals[key][1];
1340
- setter(initialState[key]);
1437
+ batch(() => {
1438
+ Object.keys(initialState).forEach((key) => {
1439
+ const setter = signals[key][1];
1440
+ setter(initialState[key]);
1441
+ });
1341
1442
  });
1342
1443
  };
1343
1444
  const subscribe = (callback) => {
@@ -1471,7 +1572,8 @@ function reactiveArray(initial = []) {
1471
1572
  function get() {
1472
1573
  recordDependency(signal2);
1473
1574
  if (snapshot === null) {
1474
- snapshot = Object.freeze([...data2]);
1575
+ const copy = data2.slice();
1576
+ snapshot = Object.freeze(copy);
1475
1577
  }
1476
1578
  return snapshot;
1477
1579
  }
@@ -1667,26 +1769,34 @@ function asyncDerived(factory, initial) {
1667
1769
  effect(() => {
1668
1770
  tick();
1669
1771
  const currentRun = ++runId;
1670
- setLoading(true);
1671
- setError(null);
1772
+ batch(() => {
1773
+ setLoading(true);
1774
+ setError(null);
1775
+ });
1672
1776
  let promise;
1673
1777
  try {
1674
1778
  promise = factory();
1675
1779
  } catch (err) {
1676
- setError(err);
1677
- setLoading(false);
1780
+ batch(() => {
1781
+ setError(err);
1782
+ setLoading(false);
1783
+ });
1678
1784
  return;
1679
1785
  }
1680
1786
  promise.then(
1681
1787
  (result) => {
1682
1788
  if (currentRun !== runId) return;
1683
- setValue(result);
1684
- setLoading(false);
1789
+ batch(() => {
1790
+ setValue(result);
1791
+ setLoading(false);
1792
+ });
1685
1793
  },
1686
1794
  (err) => {
1687
1795
  if (currentRun !== runId) return;
1688
- setError(err);
1689
- setLoading(false);
1796
+ batch(() => {
1797
+ setError(err);
1798
+ setLoading(false);
1799
+ });
1690
1800
  }
1691
1801
  );
1692
1802
  });
@@ -1713,26 +1823,186 @@ function runMountCallback(callback, hookName, element) {
1713
1823
  registerDisposer(element, cleanup);
1714
1824
  }
1715
1825
  }
1826
+ var mountWatchers = /* @__PURE__ */ new WeakMap();
1827
+ var unmountWatchers = /* @__PURE__ */ new WeakMap();
1828
+ var watchedMountElements = /* @__PURE__ */ new Set();
1829
+ var watchedUnmountElements = /* @__PURE__ */ new Set();
1830
+ var sharedObserver = null;
1831
+ var mutationCounter = 0;
1832
+ var FULL_SWEEP_INTERVAL = 256;
1833
+ function fireMount(el) {
1834
+ const cbs = mountWatchers.get(el);
1835
+ if (!cbs) return;
1836
+ mountWatchers.delete(el);
1837
+ watchedMountElements.delete(el);
1838
+ for (const cb of cbs) {
1839
+ try {
1840
+ cb();
1841
+ } catch {
1842
+ }
1843
+ }
1844
+ }
1845
+ function fireUnmount(el) {
1846
+ const cbs = unmountWatchers.get(el);
1847
+ if (!cbs) return;
1848
+ queueMicrotask(() => {
1849
+ if (el.isConnected) return;
1850
+ const stillCbs = unmountWatchers.get(el);
1851
+ if (!stillCbs) return;
1852
+ unmountWatchers.delete(el);
1853
+ watchedUnmountElements.delete(el);
1854
+ for (const cb of stillCbs) {
1855
+ try {
1856
+ cb();
1857
+ } catch {
1858
+ }
1859
+ }
1860
+ });
1861
+ }
1862
+ function visitAddedNode(node) {
1863
+ if (watchedMountElements.size === 0) return;
1864
+ if (node.nodeType !== 1) return;
1865
+ const el = node;
1866
+ if (watchedMountElements.has(el) && el.isConnected) {
1867
+ fireMount(el);
1868
+ }
1869
+ if (el.firstElementChild) {
1870
+ for (const watched of Array.from(watchedMountElements)) {
1871
+ if (watched !== el && watched.isConnected && el.contains(watched)) {
1872
+ fireMount(watched);
1873
+ }
1874
+ }
1875
+ }
1876
+ }
1877
+ function visitRemovedNode(node) {
1878
+ if (watchedUnmountElements.size === 0) return;
1879
+ if (node.nodeType !== 1) return;
1880
+ const el = node;
1881
+ if (watchedUnmountElements.has(el) && !el.isConnected) {
1882
+ fireUnmount(el);
1883
+ }
1884
+ if (el.firstElementChild) {
1885
+ for (const watched of Array.from(watchedUnmountElements)) {
1886
+ if (watched !== el && !watched.isConnected && el.contains(watched)) {
1887
+ fireUnmount(watched);
1888
+ }
1889
+ }
1890
+ }
1891
+ }
1892
+ function fullSweep() {
1893
+ if (watchedMountElements.size > 0) {
1894
+ for (const el of Array.from(watchedMountElements)) {
1895
+ if (el.isConnected) fireMount(el);
1896
+ }
1897
+ }
1898
+ if (watchedUnmountElements.size > 0) {
1899
+ for (const el of Array.from(watchedUnmountElements)) {
1900
+ if (!el.isConnected) fireUnmount(el);
1901
+ }
1902
+ }
1903
+ }
1904
+ function ensureObserver() {
1905
+ if (sharedObserver || typeof document === "undefined") return;
1906
+ sharedObserver = new MutationObserver((mutations) => {
1907
+ for (const m of mutations) {
1908
+ if (m.type !== "childList") continue;
1909
+ if (m.addedNodes.length > 0) {
1910
+ for (let i2 = 0; i2 < m.addedNodes.length; i2++) {
1911
+ visitAddedNode(m.addedNodes[i2]);
1912
+ }
1913
+ }
1914
+ if (m.removedNodes.length > 0) {
1915
+ for (let i2 = 0; i2 < m.removedNodes.length; i2++) {
1916
+ visitRemovedNode(m.removedNodes[i2]);
1917
+ }
1918
+ }
1919
+ }
1920
+ mutationCounter += mutations.length;
1921
+ if (mutationCounter >= FULL_SWEEP_INTERVAL) {
1922
+ mutationCounter = 0;
1923
+ fullSweep();
1924
+ }
1925
+ maybeDisconnectObserver();
1926
+ });
1927
+ sharedObserver.observe(document.body, { childList: true, subtree: true });
1928
+ }
1929
+ function maybeDisconnectObserver() {
1930
+ if (!sharedObserver) return;
1931
+ if (watchedMountElements.size === 0 && watchedUnmountElements.size === 0) {
1932
+ sharedObserver.disconnect();
1933
+ sharedObserver = null;
1934
+ mutationCounter = 0;
1935
+ }
1936
+ }
1937
+ function registerMountWatcher(element, cb) {
1938
+ let list = mountWatchers.get(element);
1939
+ if (!list) {
1940
+ list = [];
1941
+ mountWatchers.set(element, list);
1942
+ }
1943
+ list.push(cb);
1944
+ watchedMountElements.add(element);
1945
+ ensureObserver();
1946
+ return () => {
1947
+ const cbs = mountWatchers.get(element);
1948
+ if (cbs) {
1949
+ const idx = cbs.indexOf(cb);
1950
+ if (idx !== -1) cbs.splice(idx, 1);
1951
+ if (cbs.length === 0) {
1952
+ mountWatchers.delete(element);
1953
+ watchedMountElements.delete(element);
1954
+ }
1955
+ }
1956
+ maybeDisconnectObserver();
1957
+ };
1958
+ }
1959
+ function registerUnmountWatcher(element, cb) {
1960
+ let list = unmountWatchers.get(element);
1961
+ if (!list) {
1962
+ list = [];
1963
+ unmountWatchers.set(element, list);
1964
+ }
1965
+ list.push(cb);
1966
+ watchedUnmountElements.add(element);
1967
+ ensureObserver();
1968
+ return () => {
1969
+ const cbs = unmountWatchers.get(element);
1970
+ if (cbs) {
1971
+ const idx = cbs.indexOf(cb);
1972
+ if (idx !== -1) cbs.splice(idx, 1);
1973
+ if (cbs.length === 0) {
1974
+ unmountWatchers.delete(element);
1975
+ watchedUnmountElements.delete(element);
1976
+ }
1977
+ }
1978
+ maybeDisconnectObserver();
1979
+ };
1980
+ }
1716
1981
  function onMount(callback, element) {
1717
1982
  if (typeof document === "undefined") return;
1718
1983
  if (element) {
1984
+ let disposed = false;
1985
+ registerDisposer(element, () => {
1986
+ disposed = true;
1987
+ });
1719
1988
  if (element.isConnected) {
1720
- queueMicrotask(() => runMountCallback(callback, "onMount", element));
1989
+ queueMicrotask(() => {
1990
+ if (disposed) return;
1991
+ runMountCallback(callback, "onMount", element);
1992
+ });
1721
1993
  return;
1722
1994
  }
1723
- const observer = new MutationObserver(() => {
1724
- if (element.isConnected) {
1725
- observer.disconnect();
1726
- runMountCallback(callback, "onMount", element);
1727
- }
1728
- });
1729
- registerDisposer(element, () => observer.disconnect());
1730
1995
  queueMicrotask(() => {
1996
+ if (disposed) return;
1731
1997
  if (element.isConnected) {
1732
1998
  runMountCallback(callback, "onMount", element);
1733
- } else {
1734
- observer.observe(document.body, { childList: true, subtree: true });
1999
+ return;
1735
2000
  }
2001
+ const unregister = registerMountWatcher(element, () => {
2002
+ if (disposed) return;
2003
+ runMountCallback(callback, "onMount", element);
2004
+ });
2005
+ registerDisposer(element, unregister);
1736
2006
  });
1737
2007
  } else {
1738
2008
  queueMicrotask(() => {
@@ -1741,22 +2011,24 @@ function onMount(callback, element) {
1741
2011
  }
1742
2012
  }
1743
2013
  function onUnmount(callback, element) {
1744
- registerDisposer(element, () => safeCall(callback, "onUnmount"));
1745
- const startObserving = () => {
1746
- const observer = new MutationObserver(() => {
1747
- if (!element.isConnected) {
1748
- observer.disconnect();
1749
- safeCall(callback, "onUnmount");
1750
- }
1751
- });
1752
- observer.observe(document.body, { childList: true, subtree: true });
1753
- registerDisposer(element, () => observer.disconnect());
2014
+ if (typeof document === "undefined") return;
2015
+ let fired = false;
2016
+ const fireOnce = () => {
2017
+ if (fired) return;
2018
+ fired = true;
2019
+ safeCall(callback, "onUnmount");
2020
+ };
2021
+ registerDisposer(element, fireOnce);
2022
+ const startWatching = () => {
2023
+ if (fired) return;
2024
+ const unregister = registerUnmountWatcher(element, fireOnce);
2025
+ registerDisposer(element, unregister);
1754
2026
  };
1755
2027
  if (element.isConnected) {
1756
- startObserving();
2028
+ startWatching();
1757
2029
  } else {
1758
2030
  onMount(() => {
1759
- startObserving();
2031
+ startWatching();
1760
2032
  return void 0;
1761
2033
  }, element);
1762
2034
  }
@@ -1773,7 +2045,7 @@ function strict(fn) {
1773
2045
  try {
1774
2046
  fn();
1775
2047
  } catch (err) {
1776
- console.warn("[Sibu strict] second run threw:", err);
2048
+ console.warn("[SibuJS strict] second run threw:", err);
1777
2049
  }
1778
2050
  });
1779
2051
  }
@@ -1789,7 +2061,7 @@ function strictEffect(fn) {
1789
2061
  try {
1790
2062
  secondTeardown = effect(fn);
1791
2063
  } catch (err) {
1792
- console.warn("[Sibu strictEffect] second run threw:", err);
2064
+ console.warn("[SibuJS strictEffect] second run threw:", err);
1793
2065
  }
1794
2066
  });
1795
2067
  return () => {
@@ -1815,9 +2087,11 @@ function nextTick() {
1815
2087
  function defer(getter) {
1816
2088
  const [value, setValue] = signal(getter());
1817
2089
  let pending = false;
2090
+ let disposed = false;
1818
2091
  let latest = value();
1819
2092
  const flush = () => {
1820
2093
  pending = false;
2094
+ if (disposed) return;
1821
2095
  setValue(latest);
1822
2096
  };
1823
2097
  const schedule = () => {
@@ -1831,11 +2105,17 @@ function defer(getter) {
1831
2105
  }
1832
2106
  });
1833
2107
  };
1834
- track(() => {
2108
+ const teardown = track(() => {
1835
2109
  latest = getter();
1836
2110
  schedule();
1837
2111
  });
1838
- return value;
2112
+ const accessor = (() => value());
2113
+ accessor.dispose = () => {
2114
+ if (disposed) return;
2115
+ disposed = true;
2116
+ teardown();
2117
+ };
2118
+ return accessor;
1839
2119
  }
1840
2120
  var IDLE_FALLBACK_MS = 16;
1841
2121
  function scheduleIdle(fn) {
@@ -1876,6 +2156,32 @@ function transition() {
1876
2156
  }
1877
2157
 
1878
2158
  // src/core/rendering/lazy.ts
2159
+ var PENDING_ERROR = "__sibuPendingError";
2160
+ function dispatchPropagate(node, error) {
2161
+ const fire = () => {
2162
+ try {
2163
+ if (!node.parentNode) return false;
2164
+ node.dispatchEvent(new CustomEvent("sibu:error-propagate", { bubbles: true, detail: { error } }));
2165
+ return true;
2166
+ } catch {
2167
+ return false;
2168
+ }
2169
+ };
2170
+ if (node.parentNode && fire()) return;
2171
+ queueMicrotask(() => {
2172
+ if (fire()) return;
2173
+ node[PENDING_ERROR] = error;
2174
+ });
2175
+ }
2176
+ function takePendingError(node) {
2177
+ const rec = node;
2178
+ const err = rec[PENDING_ERROR];
2179
+ if (err instanceof Error) {
2180
+ delete rec[PENDING_ERROR];
2181
+ return err;
2182
+ }
2183
+ return void 0;
2184
+ }
1879
2185
  function lazy(importFn) {
1880
2186
  let cached = null;
1881
2187
  return function LazyComponent() {
@@ -1892,14 +2198,14 @@ function lazy(importFn) {
1892
2198
  }).catch((err) => {
1893
2199
  if (disposed) return;
1894
2200
  const errorObj = err instanceof Error ? err : new Error(String(err));
1895
- container.replaceChildren(div("sibu-lazy-error", `Failed to load component: ${errorObj.message}`));
2201
+ devWarn(`[SibuJS] lazy() failed to load component: ${errorObj.message}`);
2202
+ container.replaceChildren(div({ class: "sibu-lazy-error" }, `Failed to load component: ${errorObj.message}`));
2203
+ dispatchPropagate(container, errorObj);
1896
2204
  });
1897
2205
  container.appendChild(span("sibu-lazy-loading", "Loading..."));
1898
- const origRemove = container.remove.bind(container);
1899
- container.remove = () => {
2206
+ registerDisposer(container, () => {
1900
2207
  disposed = true;
1901
- origRemove();
1902
- };
2208
+ });
1903
2209
  return container;
1904
2210
  };
1905
2211
  }
@@ -1907,32 +2213,48 @@ function Suspense({ nodes, fallback }) {
1907
2213
  const container = div({ class: "sibu-suspense" });
1908
2214
  const fallbackEl = fallback();
1909
2215
  container.appendChild(fallbackEl);
2216
+ let suspenseDisposed = false;
2217
+ let observer = null;
2218
+ registerDisposer(container, () => {
2219
+ suspenseDisposed = true;
2220
+ if (observer) {
2221
+ observer.disconnect();
2222
+ observer = null;
2223
+ }
2224
+ });
1910
2225
  queueMicrotask(() => {
2226
+ if (suspenseDisposed) return;
1911
2227
  try {
1912
2228
  const childEl = nodes();
1913
2229
  if (childEl.classList.contains("sibu-lazy")) {
1914
- const observer = new MutationObserver(() => {
2230
+ if (!childEl.querySelector(".sibu-lazy-loading")) {
2231
+ container.replaceChildren(childEl);
2232
+ return;
2233
+ }
2234
+ observer = new MutationObserver(() => {
2235
+ if (suspenseDisposed) return;
1915
2236
  const loading = childEl.querySelector(".sibu-lazy-loading");
1916
2237
  if (!loading) {
1917
- observer.disconnect();
2238
+ observer?.disconnect();
2239
+ observer = null;
1918
2240
  container.replaceChildren(childEl);
1919
2241
  }
1920
2242
  });
1921
2243
  observer.observe(childEl, { childList: true, subtree: true });
1922
- if (!childEl.querySelector(".sibu-lazy-loading")) {
1923
- container.replaceChildren(childEl);
1924
- }
1925
2244
  } else {
1926
2245
  container.replaceChildren(childEl);
1927
2246
  }
1928
- } catch {
2247
+ } catch (err) {
2248
+ const errorObj = err instanceof Error ? err : new Error(String(err));
2249
+ devWarn(`[SibuJS] Suspense nodes() threw: ${errorObj.message}`);
2250
+ dispatchPropagate(container, errorObj);
1929
2251
  }
1930
2252
  });
1931
2253
  return container;
1932
2254
  }
1933
2255
 
1934
2256
  // src/components/ErrorDisplay.ts
1935
- var _isDev2 = isDev();
2257
+ var _isDev3 = isDev();
1936
2258
  var STYLES = `
1937
2259
  .sibu-error-display {
1938
2260
  border: 1px solid var(--sibu-err-border, #e5484d);
@@ -2018,20 +2340,21 @@ var STYLES = `
2018
2340
  font-weight: 600;
2019
2341
  }
2020
2342
  .sibu-error-display .sibu-err-copy-btn {
2021
- background: transparent;
2022
- border: 1px solid #3a3a4e;
2343
+ background: rgba(0, 0, 0, 0.22);
2344
+ border: 1px solid rgba(255, 255, 255, 0.15);
2023
2345
  border-radius: 4px;
2024
- color: #a0a3b8;
2346
+ color: rgba(255, 255, 255, 0.85);
2025
2347
  cursor: pointer;
2026
2348
  padding: 2px 10px;
2027
- font-size: 0.95em;
2349
+ font-size: 0.78em;
2028
2350
  font-family: inherit;
2029
2351
  transition: all 0.12s ease;
2352
+ flex-shrink: 0;
2030
2353
  }
2031
2354
  .sibu-error-display .sibu-err-copy-btn:hover {
2032
- background: #2a2a3e;
2033
- color: #e5e7eb;
2034
- border-color: #4a4a5e;
2355
+ background: rgba(0, 0, 0, 0.35);
2356
+ color: white;
2357
+ border-color: rgba(255, 255, 255, 0.3);
2035
2358
  }
2036
2359
 
2037
2360
  .sibu-error-display .sibu-err-stack {
@@ -2156,21 +2479,25 @@ function normalizeError(err) {
2156
2479
  cause: null
2157
2480
  };
2158
2481
  }
2159
- function buildCopyText(err, meta2) {
2482
+ function buildCopyText(err, meta2, headline) {
2160
2483
  const lines = [];
2484
+ lines.push(headline);
2161
2485
  lines.push(`[${err.code}] ${err.message}`);
2162
2486
  if (err.stack) {
2163
2487
  lines.push("");
2488
+ lines.push("Stack Trace:");
2164
2489
  lines.push(err.stack);
2165
2490
  }
2166
- if (err.cause) {
2491
+ let cause = err.cause;
2492
+ while (cause) {
2167
2493
  lines.push("");
2168
2494
  lines.push("Caused by:");
2169
- lines.push(` [${err.cause.code}] ${err.cause.message}`);
2170
- if (err.cause.stack) {
2171
- const indented = err.cause.stack.split("\n").map((l) => ` ${l}`).join("\n");
2495
+ lines.push(` [${cause.code}] ${cause.message}`);
2496
+ if (cause.stack) {
2497
+ const indented = cause.stack.split("\n").map((l) => ` ${l}`).join("\n");
2172
2498
  lines.push(indented);
2173
2499
  }
2500
+ cause = cause.cause;
2174
2501
  }
2175
2502
  if (meta2 && Object.keys(meta2).length > 0) {
2176
2503
  lines.push("");
@@ -2180,9 +2507,13 @@ function buildCopyText(err, meta2) {
2180
2507
  }
2181
2508
  }
2182
2509
  lines.push("");
2183
- lines.push(`At: ${(/* @__PURE__ */ new Date()).toISOString()}`);
2510
+ lines.push("Environment:");
2511
+ lines.push(` Timestamp: ${(/* @__PURE__ */ new Date()).toISOString()}`);
2512
+ if (typeof location !== "undefined") {
2513
+ lines.push(` URL: ${location.href}`);
2514
+ }
2184
2515
  if (typeof navigator !== "undefined" && navigator.userAgent) {
2185
- lines.push(`UA: ${navigator.userAgent}`);
2516
+ lines.push(` User Agent: ${navigator.userAgent}`);
2186
2517
  }
2187
2518
  return lines.join("\n");
2188
2519
  }
@@ -2234,7 +2565,7 @@ function ErrorDisplay(props) {
2234
2565
  injectStyles();
2235
2566
  const severity = props.severity ?? "error";
2236
2567
  const normalized = normalizeError(props.error);
2237
- const showDetails = props.alwaysShowDetails ?? _isDev2;
2568
+ const showDetails = props.alwaysShowDetails ?? _isDev3;
2238
2569
  const headline = props.title ?? normalized.message;
2239
2570
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").slice(0, 19);
2240
2571
  const [copyLabel, setCopyLabel] = signal("Copy");
@@ -2243,7 +2574,7 @@ function ErrorDisplay(props) {
2243
2574
  nodes: () => copyLabel(),
2244
2575
  on: {
2245
2576
  click: () => {
2246
- const text2 = buildCopyText(normalized, props.metadata);
2577
+ const text2 = buildCopyText(normalized, props.metadata, headline);
2247
2578
  if (typeof navigator !== "undefined" && navigator.clipboard) {
2248
2579
  navigator.clipboard.writeText(text2).then(
2249
2580
  () => {
@@ -2264,6 +2595,7 @@ function ErrorDisplay(props) {
2264
2595
  nodes: [
2265
2596
  code({ class: "sibu-err-icon", nodes: normalized.code }),
2266
2597
  h3({ class: "sibu-err-title", nodes: headline }),
2598
+ copyBtn,
2267
2599
  span({ class: "sibu-err-timestamp", nodes: timestamp })
2268
2600
  ]
2269
2601
  });
@@ -2275,25 +2607,12 @@ function ErrorDisplay(props) {
2275
2607
  nodes: [
2276
2608
  div({
2277
2609
  class: "sibu-err-section-head",
2278
- nodes: [span({ nodes: "Stack Trace" }), copyBtn]
2610
+ nodes: [span({ nodes: "Stack Trace" })]
2279
2611
  }),
2280
2612
  renderFrames(normalized.frames)
2281
2613
  ]
2282
2614
  })
2283
2615
  );
2284
- } else if (showDetails) {
2285
- bodyChildren.push(
2286
- div({
2287
- class: "sibu-err-section",
2288
- nodes: [
2289
- div({
2290
- class: "sibu-err-section-head",
2291
- nodes: [span({ nodes: "Details" }), copyBtn]
2292
- }),
2293
- div({ class: "sibu-err-stack", nodes: "(no stack available)" })
2294
- ]
2295
- })
2296
- );
2297
2616
  }
2298
2617
  if (showDetails) {
2299
2618
  bodyChildren.push(...renderCauseChain(normalized.cause));
@@ -2309,37 +2628,6 @@ function ErrorDisplay(props) {
2309
2628
  })
2310
2629
  );
2311
2630
  }
2312
- if (showDetails && typeof navigator !== "undefined" && navigator.userAgent) {
2313
- bodyChildren.push(
2314
- div({
2315
- class: "sibu-err-section",
2316
- nodes: [
2317
- div({ class: "sibu-err-section-head", nodes: [span({ nodes: "Environment" })] }),
2318
- div({
2319
- class: "sibu-err-meta",
2320
- nodes: (() => {
2321
- const dl2 = document.createElement("dl");
2322
- dl2.className = "sibu-err-meta";
2323
- const entries = [
2324
- ["User Agent", navigator.userAgent],
2325
- ["URL", typeof location !== "undefined" ? location.href : "(n/a)"],
2326
- ["Timestamp", (/* @__PURE__ */ new Date()).toISOString()]
2327
- ];
2328
- for (const [k, v] of entries) {
2329
- const dt2 = document.createElement("dt");
2330
- dt2.textContent = k;
2331
- const dd2 = document.createElement("dd");
2332
- dd2.textContent = v;
2333
- dl2.appendChild(dt2);
2334
- dl2.appendChild(dd2);
2335
- }
2336
- return dl2;
2337
- })()
2338
- })
2339
- ]
2340
- })
2341
- );
2342
- }
2343
2631
  const actionButtons = [];
2344
2632
  if (props.onRetry) {
2345
2633
  actionButtons.push(
@@ -2534,6 +2822,7 @@ function injectStyles2() {
2534
2822
  stylesInjected = true;
2535
2823
  }
2536
2824
  }
2825
+ var FALLBACK_CACHE_MAX = 50;
2537
2826
  var fallbackCache = /* @__PURE__ */ new WeakMap();
2538
2827
  function getMemoizedFallback(fallbackFn, error, retry) {
2539
2828
  let cache2 = fallbackCache.get(fallbackFn);
@@ -2542,27 +2831,42 @@ function getMemoizedFallback(fallbackFn, error, retry) {
2542
2831
  fallbackCache.set(fallbackFn, cache2);
2543
2832
  }
2544
2833
  const key = error.message;
2545
- if (!cache2.has(key)) {
2546
- cache2.set(key, fallbackFn(error, retry));
2834
+ let factory = cache2.get(key);
2835
+ if (factory) {
2836
+ cache2.delete(key);
2837
+ cache2.set(key, factory);
2838
+ } else {
2839
+ factory = () => fallbackFn(error, retry);
2840
+ cache2.set(key, factory);
2841
+ if (cache2.size > FALLBACK_CACHE_MAX) {
2842
+ const oldestKey = cache2.keys().next().value;
2843
+ if (oldestKey !== void 0) cache2.delete(oldestKey);
2844
+ }
2547
2845
  }
2548
- return cache2.get(key);
2846
+ return factory();
2549
2847
  }
2550
2848
  function ErrorBoundary({ nodes, fallback, onError, resetKeys }) {
2551
2849
  injectStyles2();
2552
2850
  const [error, setError] = signal(null);
2553
2851
  const retry = () => {
2554
2852
  if (fallback) {
2555
- fallbackCache.delete(fallback);
2853
+ const cur = error();
2854
+ const inner = fallbackCache.get(fallback);
2855
+ if (cur && inner) inner.delete(cur.message);
2556
2856
  }
2557
2857
  setError(null);
2558
2858
  };
2859
+ let resetKeysTeardown = null;
2559
2860
  if (resetKeys && resetKeys.length > 0) {
2560
2861
  let initialized = false;
2561
- effect(() => {
2862
+ resetKeysTeardown = effect(() => {
2562
2863
  for (const k of resetKeys) {
2563
2864
  try {
2564
2865
  k();
2565
- } catch {
2866
+ } catch (err) {
2867
+ if (typeof console !== "undefined") {
2868
+ console.warn("[SibuJS ErrorBoundary] resetKeys getter threw:", err);
2869
+ }
2566
2870
  }
2567
2871
  }
2568
2872
  if (!initialized) {
@@ -2575,7 +2879,15 @@ function ErrorBoundary({ nodes, fallback, onError, resetKeys }) {
2575
2879
  const handleError = (e) => {
2576
2880
  const errorObj = e instanceof Error ? e : new Error(String(e));
2577
2881
  setError(errorObj);
2578
- onError?.(errorObj);
2882
+ if (onError) {
2883
+ try {
2884
+ onError(errorObj);
2885
+ } catch (cbErr) {
2886
+ if (typeof console !== "undefined") {
2887
+ console.error("[SibuJS ErrorBoundary] onError callback threw:", cbErr);
2888
+ }
2889
+ }
2890
+ }
2579
2891
  return errorObj;
2580
2892
  };
2581
2893
  const defaultFallback = (err, retryFn) => {
@@ -2627,7 +2939,7 @@ function ErrorBoundary({ nodes, fallback, onError, resetKeys }) {
2627
2939
  }
2628
2940
  }
2629
2941
  });
2630
- container.addEventListener("sibu:error-propagate", (e) => {
2942
+ const propagateListener = (e) => {
2631
2943
  if (error()) return;
2632
2944
  e.stopPropagation();
2633
2945
  const customEvent = e;
@@ -2635,6 +2947,30 @@ function ErrorBoundary({ nodes, fallback, onError, resetKeys }) {
2635
2947
  if (propagatedError) {
2636
2948
  handleError(propagatedError);
2637
2949
  }
2950
+ };
2951
+ container.addEventListener("sibu:error-propagate", propagateListener);
2952
+ onMount(() => {
2953
+ const walker = document.createTreeWalker(container, NodeFilter.SHOW_ELEMENT);
2954
+ const collected = [];
2955
+ let node = walker.currentNode;
2956
+ while (node) {
2957
+ const pending = takePendingError(node);
2958
+ if (pending) collected.push(pending);
2959
+ node = walker.nextNode();
2960
+ }
2961
+ if (collected.length === 1) {
2962
+ handleError(collected[0]);
2963
+ } else if (collected.length > 1) {
2964
+ const Agg = globalThis.AggregateError;
2965
+ handleError(
2966
+ Agg ? new Agg(collected, `${collected.length} pre-mount errors caught by ErrorBoundary`) : new Error(collected.map((e) => e.message).join("; "))
2967
+ );
2968
+ }
2969
+ return void 0;
2970
+ }, container);
2971
+ registerDisposer(container, () => {
2972
+ if (resetKeysTeardown) resetKeysTeardown();
2973
+ container.removeEventListener("sibu:error-propagate", propagateListener);
2638
2974
  });
2639
2975
  return container;
2640
2976
  }
@@ -2770,6 +3106,7 @@ export {
2770
3106
  nextTick,
2771
3107
  defer,
2772
3108
  transition,
3109
+ takePendingError,
2773
3110
  lazy,
2774
3111
  Suspense,
2775
3112
  ErrorDisplay,