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,7 +1,7 @@
1
1
  import {
2
2
  SVG_NS,
3
3
  tagFactory
4
- } from "./chunk-WADYRCO2.js";
4
+ } from "./chunk-P2HSJDDN.js";
5
5
 
6
6
  // src/core/rendering/html.ts
7
7
  var html = tagFactory("html");
@@ -1,16 +1,18 @@
1
1
  import {
2
2
  recordDependency,
3
+ retrack,
3
4
  track,
4
5
  trackingSuspended
5
- } from "./chunk-K4G4ZQNR.js";
6
+ } from "./chunk-QO3WC6FS.js";
6
7
  import {
7
8
  devAssert
8
- } from "./chunk-5X6PP2UK.js";
9
+ } from "./chunk-LMLD24FC.js";
9
10
 
10
11
  // src/core/signals/derived.ts
11
12
  function derived(getter, options) {
12
13
  devAssert(typeof getter === "function", "derived: argument must be a getter function.");
13
14
  const debugName = options?.name;
15
+ const equals = options?.equals;
14
16
  const cs = {};
15
17
  cs._d = false;
16
18
  cs._g = getter;
@@ -21,8 +23,14 @@ function derived(getter, options) {
21
23
  markDirty._c = 1;
22
24
  markDirty._sig = cs;
23
25
  track(() => {
24
- cs._d = false;
25
- cs._v = getter();
26
+ let threw = true;
27
+ try {
28
+ cs._v = getter();
29
+ cs._d = false;
30
+ threw = false;
31
+ } finally {
32
+ if (threw) cs._d = true;
33
+ }
26
34
  }, markDirty);
27
35
  const hook = globalThis.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
28
36
  let evaluating = false;
@@ -35,11 +43,16 @@ function derived(getter, options) {
35
43
  if (trackingSuspended) {
36
44
  if (cs._d) {
37
45
  evaluating = true;
46
+ let threw = true;
38
47
  try {
39
- cs._d = false;
40
- cs._v = getter();
48
+ retrack(() => {
49
+ cs._v = getter();
50
+ cs._d = false;
51
+ threw = false;
52
+ }, markDirty);
41
53
  } finally {
42
54
  evaluating = false;
55
+ if (threw) cs._d = true;
43
56
  }
44
57
  }
45
58
  return cs._v;
@@ -48,13 +61,17 @@ function derived(getter, options) {
48
61
  if (cs._d) {
49
62
  const oldValue = cs._v;
50
63
  evaluating = true;
64
+ let threw = true;
51
65
  try {
52
- track(() => {
66
+ retrack(() => {
67
+ const next = getter();
68
+ cs._v = equals && cs._v !== void 0 ? equals(cs._v, next) ? cs._v : next : next;
53
69
  cs._d = false;
54
- cs._v = getter();
70
+ threw = false;
55
71
  }, markDirty);
56
72
  } finally {
57
73
  evaluating = false;
74
+ if (threw) cs._d = true;
58
75
  }
59
76
  if (hook && oldValue !== cs._v) {
60
77
  hook.emit("computed:update", { signal: cs, oldValue, newValue: cs._v });
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  effect
3
- } from "./chunk-VQNQZCWJ.js";
3
+ } from "./chunk-WZA53FXU.js";
4
4
  import {
5
5
  batch,
6
6
  signal
7
- } from "./chunk-NZIIMDWI.js";
7
+ } from "./chunk-RDTDJCAB.js";
8
8
 
9
9
  // src/browser/media.ts
10
10
  function media(query) {
@@ -399,7 +399,10 @@ function dropZone(element, options) {
399
399
  const raw = e.dataTransfer.getData("application/json");
400
400
  if (raw) {
401
401
  try {
402
- transferData = JSON.parse(raw);
402
+ transferData = JSON.parse(
403
+ raw,
404
+ (k, v) => k === "__proto__" || k === "constructor" || k === "prototype" ? void 0 : v
405
+ );
403
406
  } catch {
404
407
  transferData = raw;
405
408
  }
@@ -779,13 +782,21 @@ function wakeLock() {
779
782
  }
780
783
  const onVisibility = () => {
781
784
  if (sentinel?.released && !document.hidden) {
782
- void request();
785
+ request().catch((err) => {
786
+ if (typeof console !== "undefined") {
787
+ console.warn("[SibuJS wakeLock] re-acquire failed:", err);
788
+ }
789
+ });
783
790
  }
784
791
  };
785
792
  document.addEventListener("visibilitychange", onVisibility);
786
793
  function dispose() {
787
794
  document.removeEventListener("visibilitychange", onVisibility);
788
- void release();
795
+ release().catch((err) => {
796
+ if (typeof console !== "undefined") {
797
+ console.warn("[SibuJS wakeLock] release failed:", err);
798
+ }
799
+ });
789
800
  }
790
801
  return { active, request, release, dispose };
791
802
  }
@@ -981,11 +992,21 @@ function speech() {
981
992
  };
982
993
  }
983
994
  const synth = window.speechSynthesis;
984
- const interval = setInterval(() => {
985
- setSpeaking(synth.speaking);
986
- setPaused(synth.paused);
987
- }, 200);
995
+ let interval = null;
996
+ function startPolling() {
997
+ if (interval !== null) return;
998
+ interval = setInterval(() => {
999
+ setSpeaking(synth.speaking);
1000
+ setPaused(synth.paused);
1001
+ if (!synth.speaking && !synth.paused) {
1002
+ clearInterval(interval);
1003
+ interval = null;
1004
+ }
1005
+ }, 200);
1006
+ }
1007
+ let disposed = false;
988
1008
  function speak(text, options = {}) {
1009
+ if (disposed) return;
989
1010
  const u = new SpeechSynthesisUtterance(text);
990
1011
  if (options.lang) u.lang = options.lang;
991
1012
  if (options.rate != null) u.rate = options.rate;
@@ -996,19 +1017,41 @@ function speech() {
996
1017
  const match = voices.find((v) => v.name === options.voice);
997
1018
  if (match) u.voice = match;
998
1019
  }
999
- u.addEventListener("start", () => setSpeaking(true));
1000
- u.addEventListener("end", () => {
1001
- setSpeaking(false);
1002
- setPaused(false);
1003
- });
1004
- u.addEventListener("error", () => {
1005
- setSpeaking(false);
1006
- setPaused(false);
1007
- });
1020
+ u.addEventListener(
1021
+ "start",
1022
+ () => {
1023
+ if (!disposed) setSpeaking(true);
1024
+ },
1025
+ { once: true }
1026
+ );
1027
+ u.addEventListener(
1028
+ "end",
1029
+ () => {
1030
+ if (disposed) return;
1031
+ setSpeaking(false);
1032
+ setPaused(false);
1033
+ },
1034
+ { once: true }
1035
+ );
1036
+ u.addEventListener(
1037
+ "error",
1038
+ () => {
1039
+ if (disposed) return;
1040
+ setSpeaking(false);
1041
+ setPaused(false);
1042
+ },
1043
+ { once: true }
1044
+ );
1008
1045
  synth.speak(u);
1046
+ setSpeaking(true);
1047
+ startPolling();
1009
1048
  }
1010
1049
  function dispose() {
1011
- clearInterval(interval);
1050
+ disposed = true;
1051
+ if (interval !== null) {
1052
+ clearInterval(interval);
1053
+ interval = null;
1054
+ }
1012
1055
  synth.cancel();
1013
1056
  }
1014
1057
  return {
@@ -1237,13 +1280,21 @@ function imageLoader(src) {
1237
1280
  };
1238
1281
  img.src = url;
1239
1282
  }
1283
+ let srcEffectTeardown = null;
1240
1284
  if (typeof src === "function") {
1241
- start(src());
1285
+ srcEffectTeardown = effect(() => {
1286
+ const url = src();
1287
+ start(url);
1288
+ });
1242
1289
  } else {
1243
1290
  start(src);
1244
1291
  }
1245
1292
  function dispose() {
1246
1293
  disposed = true;
1294
+ if (srcEffectTeardown) {
1295
+ srcEffectTeardown();
1296
+ srcEffectTeardown = null;
1297
+ }
1247
1298
  if (current) {
1248
1299
  current.onload = null;
1249
1300
  current.onerror = null;
@@ -1,9 +1,12 @@
1
1
  import {
2
2
  sanitizeUrl
3
- } from "./chunk-CMBFNA7L.js";
3
+ } from "./chunk-UCS6AMJ7.js";
4
+ import {
5
+ getSSRStore
6
+ } from "./chunk-2RA7SHDA.js";
4
7
  import {
5
8
  isDev
6
- } from "./chunk-5X6PP2UK.js";
9
+ } from "./chunk-LMLD24FC.js";
7
10
 
8
11
  // src/platform/ssr.ts
9
12
  var _isDev = isDev();
@@ -123,7 +126,7 @@ function hydrate(component, container, options = {}) {
123
126
  options.onMismatch(first);
124
127
  } else if (_isDev) {
125
128
  console.warn(
126
- `[Sibu hydration] ${first.message}
129
+ `[SibuJS hydration] ${first.message}
127
130
  at ${first.path}
128
131
  server: ${first.serverValue}
129
132
  client: ${first.clientValue}`
@@ -131,17 +134,9 @@ function hydrate(component, container, options = {}) {
131
134
  }
132
135
  }
133
136
  }
134
- hydrateNode(container.firstElementChild, clientTree);
137
+ container.replaceChildren(clientTree);
135
138
  container.setAttribute("data-sibu-hydrated", "true");
136
139
  }
137
- function hydrateNode(serverNode, clientNode) {
138
- if (!serverNode) return;
139
- const serverChildren = Array.from(serverNode.children);
140
- const clientChildren = Array.from(clientNode.children);
141
- for (let i = 0; i < Math.min(serverChildren.length, clientChildren.length); i++) {
142
- hydrateNode(serverChildren[i], clientChildren[i]);
143
- }
144
- }
145
140
  function collectMismatches(serverNode, clientNode, path, out, max = 5) {
146
141
  if (out.length >= max) return;
147
142
  const nodePath = path || clientNode?.tagName?.toLowerCase() || "(root)";
@@ -371,12 +366,16 @@ function renderToReadableStream(element) {
371
366
  controller.enqueue(value);
372
367
  }
373
368
  },
374
- cancel() {
375
- generator.return(void 0);
369
+ async cancel() {
370
+ await generator.return(void 0);
376
371
  }
377
372
  });
378
373
  }
374
+ var SAFE_ID = /^[A-Za-z0-9_-]+$/;
379
375
  function island(id, component) {
376
+ if (!SAFE_ID.test(id)) {
377
+ throw new Error(`[SibuJS SSR] island: id must match [A-Za-z0-9_-]+ (got: ${JSON.stringify(id.slice(0, 32))})`);
378
+ }
380
379
  const el = component();
381
380
  el.setAttribute("data-sibu-island", id);
382
381
  return el;
@@ -389,8 +388,9 @@ function hydrateIslands(container, islands) {
389
388
  const factory = islands[id];
390
389
  if (typeof factory !== "function") continue;
391
390
  const clientTree = factory();
392
- hydrateNode(marker, clientTree);
393
- marker.setAttribute("data-sibu-hydrated", "true");
391
+ clientTree.setAttribute("data-sibu-island", id);
392
+ clientTree.setAttribute("data-sibu-hydrated", "true");
393
+ marker.replaceWith(clientTree);
394
394
  }
395
395
  container.setAttribute("data-sibu-hydrated", "partial");
396
396
  }
@@ -407,8 +407,9 @@ function hydrateProgressively(container, islands, options) {
407
407
  for (const entry of entries) {
408
408
  if (entry.isIntersecting) {
409
409
  const clientTree = factory();
410
- hydrateNode(marker, clientTree);
411
- marker.setAttribute("data-sibu-hydrated", "true");
410
+ clientTree.setAttribute("data-sibu-island", id);
411
+ clientTree.setAttribute("data-sibu-hydrated", "true");
412
+ marker.replaceWith(clientTree);
412
413
  observer.disconnect();
413
414
  break;
414
415
  }
@@ -424,20 +425,37 @@ function hydrateProgressively(container, islands, options) {
424
425
  for (const cleanup of cleanups) cleanup();
425
426
  };
426
427
  }
427
- var suspenseIdCounter = 0;
428
428
  function resetSSRState() {
429
- suspenseIdCounter = 0;
429
+ getSSRStore().suspenseIdCounter = 0;
430
+ }
431
+ function noop() {
430
432
  }
431
433
  function ssrSuspense(props) {
432
- const id = `sibu-sus-${suspenseIdCounter++}`;
434
+ const store = getSSRStore();
435
+ const id = `sibu-sus-${store.suspenseIdCounter++}`;
436
+ const timeoutMs = props.timeoutMs ?? 3e4;
433
437
  const fallbackEl = props.fallback();
434
438
  const wrapper = document.createElement("div");
435
439
  wrapper.setAttribute("data-sibu-suspense-id", id);
436
440
  wrapper.appendChild(fallbackEl);
437
- const promise = props.content().then((resolvedEl) => ({
438
- id,
439
- html: renderToString(resolvedEl)
440
- }));
441
+ const fallbackHtml = renderToString(fallbackEl);
442
+ let timer;
443
+ const timeoutPromise = new Promise((_, reject) => {
444
+ timer = setTimeout(() => reject(new Error(`[SibuJS SSR] ssrSuspense timed out after ${timeoutMs}ms`)), timeoutMs);
445
+ });
446
+ const raced = Promise.race([props.content(), timeoutPromise]);
447
+ const promise = raced.then(
448
+ (resolvedEl) => {
449
+ if (timer) clearTimeout(timer);
450
+ return { id, html: renderToString(resolvedEl) };
451
+ },
452
+ (err) => {
453
+ if (timer) clearTimeout(timer);
454
+ if (_isDev) console.warn("[SibuJS SSR] ssrSuspense rejected:", err);
455
+ return { id, html: fallbackHtml };
456
+ }
457
+ );
458
+ promise.catch(noop);
441
459
  return { element: wrapper, promise };
442
460
  }
443
461
  var SAFE_SUSPENSE_ID = /^[A-Za-z0-9_-]+$/;
@@ -465,14 +483,27 @@ var SSR_DATA_ATTR = "__SIBU_SSR_DATA__";
465
483
  function escapeScriptJson(json) {
466
484
  return json.replace(/</g, "\\u003c").replace(/>/g, "\\u003e").replace(/&/g, "\\u0026").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
467
485
  }
468
- function serializeState(state, nonce) {
469
- const json = escapeScriptJson(JSON.stringify(state));
486
+ var DEFAULT_MAX_SSR_BYTES = 1024 * 1024;
487
+ function serializeState(state, nonce, options) {
488
+ const rawJson = JSON.stringify(state);
489
+ const maxBytes = options?.maxBytes ?? DEFAULT_MAX_SSR_BYTES;
490
+ const byteLen = typeof TextEncoder !== "undefined" ? new TextEncoder().encode(rawJson).byteLength : Buffer.byteLength(rawJson, "utf8");
491
+ if (byteLen > maxBytes) {
492
+ throw new Error(`[SibuJS SSR] serializeState: payload (${byteLen} bytes) exceeds maxBytes (${maxBytes})`);
493
+ }
494
+ const json = escapeScriptJson(rawJson);
470
495
  const nonceAttr = nonce ? ` nonce="${escapeAttr(nonce)}"` : "";
471
496
  return `<script${nonceAttr}>window.${SSR_DATA_ATTR}=${json}</script>`;
472
497
  }
473
498
  function deserializeState(validate) {
474
499
  if (typeof window === "undefined") return void 0;
475
- const raw = window[SSR_DATA_ATTR];
500
+ if (_isDev && !validate) {
501
+ console.warn(
502
+ "[SibuJS SSR] deserializeState() called without a validate guard \u2014 tampered SSR payloads will not be detected."
503
+ );
504
+ }
505
+ const w = window;
506
+ const raw = w[SSR_DATA_ATTR];
476
507
  if (raw === void 0) return void 0;
477
508
  if (validate && !validate(raw)) return void 0;
478
509
  return raw;