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
@@ -0,0 +1,79 @@
1
+ // src/utils/sanitize.ts
2
+ var SAFE_URL_PROTOCOLS = ["http:", "https:", "mailto:", "tel:", "ftp:"];
3
+ function sanitizeUrl(url) {
4
+ const trimmed = url.replace(/[\x00-\x20\x7f-\x9f]+/g, "").trim();
5
+ if (!trimmed) return "";
6
+ const lower = trimmed.toLowerCase();
7
+ let schemeEnd = -1;
8
+ for (let i = 0; i < lower.length; i++) {
9
+ const ch = lower.charCodeAt(i);
10
+ if (ch === 58) {
11
+ schemeEnd = i;
12
+ break;
13
+ }
14
+ if (ch === 47 || ch === 63 || ch === 35) break;
15
+ }
16
+ if (schemeEnd === -1) return trimmed;
17
+ const scheme = lower.slice(0, schemeEnd + 1);
18
+ if (!/^[a-z][a-z0-9+.-]*:$/.test(scheme)) return trimmed;
19
+ if (SAFE_URL_PROTOCOLS.indexOf(scheme) === -1) return "";
20
+ return trimmed;
21
+ }
22
+ function sanitizeSrcset(value) {
23
+ const parts = value.split(",");
24
+ const out = [];
25
+ for (let i = 0; i < parts.length; i++) {
26
+ const part = parts[i].trim();
27
+ if (!part) continue;
28
+ const m = part.match(/^(\S+)(\s+.+)?$/);
29
+ if (!m) continue;
30
+ const safe = sanitizeUrl(m[1]);
31
+ if (!safe) continue;
32
+ out.push(m[2] ? `${safe}${m[2]}` : safe);
33
+ }
34
+ return out.join(", ");
35
+ }
36
+ function sanitizeCSSValue(value) {
37
+ const decoded = value.replace(/\\([0-9a-fA-F]{1,6})\s?/g, (_m, hex) => {
38
+ const code = Number.parseInt(hex, 16);
39
+ if (!Number.isFinite(code) || code < 0 || code > 1114111) return "";
40
+ try {
41
+ return String.fromCodePoint(code);
42
+ } catch {
43
+ return "";
44
+ }
45
+ });
46
+ const lower = decoded.toLowerCase().replace(/\s+/g, "");
47
+ if (lower.includes("url(") || lower.includes("expression(") || lower.includes("javascript:") || lower.includes("vbscript:") || lower.includes("-moz-binding") || lower.includes("behavior:") || lower.includes("@import") || lower.includes("image-set(") || lower.includes("filter:progid")) {
48
+ return "";
49
+ }
50
+ return value;
51
+ }
52
+ function stripHtml(html) {
53
+ return String(html).replace(/<[^>]*>/g, "");
54
+ }
55
+ var URL_ATTRIBUTES = /* @__PURE__ */ new Set([
56
+ "href",
57
+ "xlink:href",
58
+ "src",
59
+ "action",
60
+ "formaction",
61
+ "formtarget",
62
+ "cite",
63
+ "poster",
64
+ "background",
65
+ "srcset",
66
+ "ping",
67
+ "data"
68
+ ]);
69
+ function isUrlAttribute(attr) {
70
+ return URL_ATTRIBUTES.has(attr);
71
+ }
72
+
73
+ export {
74
+ sanitizeUrl,
75
+ sanitizeSrcset,
76
+ sanitizeCSSValue,
77
+ stripHtml,
78
+ isUrlAttribute
79
+ };
@@ -1,12 +1,13 @@
1
1
  import {
2
2
  derived
3
- } from "./chunk-XHK6BDAJ.js";
3
+ } from "./chunk-DRUZZAK4.js";
4
4
  import {
5
5
  effect
6
- } from "./chunk-VQNQZCWJ.js";
6
+ } from "./chunk-WZA53FXU.js";
7
7
  import {
8
+ batch,
8
9
  signal
9
- } from "./chunk-NZIIMDWI.js";
10
+ } from "./chunk-RDTDJCAB.js";
10
11
 
11
12
  // src/patterns/machine.ts
12
13
  function machine(config) {
@@ -74,7 +75,11 @@ function machine(config) {
74
75
  function persisted(key, initial, options = {}) {
75
76
  const storage = options.session ? sessionStorage : localStorage;
76
77
  const serialize = options.serialize || JSON.stringify;
77
- const deserialize = options.deserialize || JSON.parse;
78
+ const safeReviver = (k, v) => {
79
+ if (k === "__proto__" || k === "constructor" || k === "prototype") return void 0;
80
+ return v;
81
+ };
82
+ const deserialize = options.deserialize || ((raw) => JSON.parse(raw, safeReviver));
78
83
  const encrypt = options.encrypt;
79
84
  const decrypt = options.decrypt;
80
85
  const syncTabs = options.session ? false : options.syncTabs ?? true;
@@ -178,6 +183,27 @@ function optimisticList(initialValue) {
178
183
  const [pending, setPending] = signal(false);
179
184
  let inflightCount = 0;
180
185
  let version = 0;
186
+ let tempIdCounter = 0;
187
+ const itemIds = /* @__PURE__ */ new WeakMap();
188
+ const idToItem = /* @__PURE__ */ new Map();
189
+ function tagItem(item) {
190
+ const id = ++tempIdCounter;
191
+ if (item !== null && typeof item === "object") {
192
+ itemIds.set(item, id);
193
+ }
194
+ idToItem.set(id, item);
195
+ return id;
196
+ }
197
+ function findIndexById(list, id) {
198
+ for (let i = 0; i < list.length; i++) {
199
+ const it = list[i];
200
+ if (it !== null && typeof it === "object" && itemIds.get(it) === id) {
201
+ return i;
202
+ }
203
+ if (Object.is(it, idToItem.get(id))) return i;
204
+ }
205
+ return -1;
206
+ }
181
207
  function begin() {
182
208
  const v = ++version;
183
209
  inflightCount++;
@@ -193,12 +219,13 @@ function optimisticList(initialValue) {
193
219
  }
194
220
  async function add(item, asyncAction) {
195
221
  const prev = items();
222
+ const id = tagItem(item);
196
223
  setItems([...prev, item]);
197
224
  const myVersion = begin();
198
225
  try {
199
226
  const result = await asyncAction();
200
227
  setItems((current) => {
201
- const idx = current.lastIndexOf(item);
228
+ const idx = findIndexById(current, id);
202
229
  if (idx >= 0) {
203
230
  const next = [...current];
204
231
  next[idx] = result;
@@ -206,8 +233,10 @@ function optimisticList(initialValue) {
206
233
  }
207
234
  return [...current, result];
208
235
  });
236
+ idToItem.delete(id);
209
237
  end(myVersion);
210
238
  } catch {
239
+ idToItem.delete(id);
211
240
  end(myVersion, () => setItems(prev));
212
241
  }
213
242
  }
@@ -224,12 +253,13 @@ function optimisticList(initialValue) {
224
253
  }
225
254
  async function updateItem(predicate, patch, asyncAction) {
226
255
  const prev = items();
227
- const patchedRefs = [];
256
+ const patchedIds = [];
228
257
  setItems(
229
258
  prev.map((item) => {
230
259
  if (predicate(item)) {
231
260
  const patched = { ...item, ...patch };
232
- patchedRefs.push(patched);
261
+ const id = tagItem(patched);
262
+ patchedIds.push(id);
233
263
  return patched;
234
264
  }
235
265
  return item;
@@ -238,9 +268,19 @@ function optimisticList(initialValue) {
238
268
  const myVersion = begin();
239
269
  try {
240
270
  const result = await asyncAction();
241
- setItems((current) => current.map((item) => patchedRefs.includes(item) ? result : item));
271
+ setItems(
272
+ (current) => current.map((item) => {
273
+ if (item !== null && typeof item === "object") {
274
+ const existingId = itemIds.get(item);
275
+ if (existingId !== void 0 && patchedIds.includes(existingId)) return result;
276
+ }
277
+ return item;
278
+ })
279
+ );
280
+ for (const id of patchedIds) idToItem.delete(id);
242
281
  end(myVersion);
243
282
  } catch {
283
+ for (const id of patchedIds) idToItem.delete(id);
244
284
  end(myVersion, () => setItems(prev));
245
285
  }
246
286
  }
@@ -249,10 +289,7 @@ function optimisticList(initialValue) {
249
289
  pending,
250
290
  add,
251
291
  remove,
252
- update: updateItem,
253
- addOptimistic: add,
254
- removeOptimistic: remove,
255
- updateOptimistic: updateItem
292
+ update: updateItem
256
293
  };
257
294
  }
258
295
 
@@ -271,14 +308,16 @@ function timeline(initial, maxHistory = 100) {
271
308
  const idx = index();
272
309
  const newHistory = hist.slice(0, idx + 1);
273
310
  newHistory.push(newValue);
274
- if (newHistory.length > maxHistory) {
275
- newHistory.shift();
276
- setHistory(newHistory);
277
- setIndex(newHistory.length - 1);
278
- } else {
279
- setHistory(newHistory);
280
- setIndex(idx + 1);
281
- }
311
+ batch(() => {
312
+ if (newHistory.length > maxHistory) {
313
+ newHistory.shift();
314
+ setHistory(newHistory);
315
+ setIndex(newHistory.length - 1);
316
+ } else {
317
+ setHistory(newHistory);
318
+ setIndex(idx + 1);
319
+ }
320
+ });
282
321
  }
283
322
  function undo() {
284
323
  if (canUndo()) {
@@ -291,8 +330,10 @@ function timeline(initial, maxHistory = 100) {
291
330
  }
292
331
  }
293
332
  function reset() {
294
- setHistory([initial]);
295
- setIndex(0);
333
+ batch(() => {
334
+ setHistory([initial]);
335
+ setIndex(0);
336
+ });
296
337
  }
297
338
  function jumpTo(targetIndex) {
298
339
  const hist = history();
@@ -304,8 +345,37 @@ function timeline(initial, maxHistory = 100) {
304
345
  }
305
346
 
306
347
  // src/patterns/globalStore.ts
348
+ function deepClone(value) {
349
+ if (typeof structuredClone === "function") {
350
+ return structuredClone(value);
351
+ }
352
+ const seen = /* @__PURE__ */ new WeakSet();
353
+ const clone = (v) => {
354
+ if (v === null || typeof v !== "object") return v;
355
+ if (seen.has(v)) throw new Error("deepClone: circular reference");
356
+ seen.add(v);
357
+ if (v instanceof Date) return new Date(v.getTime());
358
+ if (v instanceof Map) {
359
+ const out2 = /* @__PURE__ */ new Map();
360
+ for (const [k, val] of v) out2.set(clone(k), clone(val));
361
+ return out2;
362
+ }
363
+ if (v instanceof Set) {
364
+ const out2 = /* @__PURE__ */ new Set();
365
+ for (const val of v) out2.add(clone(val));
366
+ return out2;
367
+ }
368
+ if (Array.isArray(v)) return v.map(clone);
369
+ const out = {};
370
+ for (const k of Object.keys(v)) {
371
+ out[k] = clone(v[k]);
372
+ }
373
+ return out;
374
+ };
375
+ return clone(value);
376
+ }
307
377
  function globalStore(config) {
308
- const initialState = JSON.parse(JSON.stringify(config.state));
378
+ const initialState = deepClone(config.state);
309
379
  const [getState, setState] = signal({ ...initialState });
310
380
  const listeners = /* @__PURE__ */ new Set();
311
381
  const middlewares = config.middleware || [];
@@ -1,19 +1,19 @@
1
1
  import {
2
2
  createPlugin
3
- } from "./chunk-K5ZUMYVS.js";
3
+ } from "./chunk-3JHCYHWN.js";
4
4
  import {
5
5
  tagFactory
6
- } from "./chunk-B7SWRFUT.js";
6
+ } from "./chunk-P2HSJDDN.js";
7
7
  import {
8
8
  derived
9
- } from "./chunk-L6JRBDNS.js";
9
+ } from "./chunk-DRUZZAK4.js";
10
10
  import {
11
11
  effect
12
- } from "./chunk-6SA3QQES.js";
12
+ } from "./chunk-WZA53FXU.js";
13
13
  import {
14
14
  batch,
15
15
  signal
16
- } from "./chunk-V2XTI523.js";
16
+ } from "./chunk-RDTDJCAB.js";
17
17
 
18
18
  // src/ecosystem/adapters/mobx.ts
19
19
  function mobXAdapter(options) {
@@ -21,7 +21,7 @@ function mobXAdapter(options) {
21
21
  const { autorun } = options;
22
22
  const disposers = [];
23
23
  function fromMobX(expression) {
24
- const [getValue, setValue] = signal(expression());
24
+ const [getValue, setValue] = signal(void 0);
25
25
  const disposer = autorun(() => {
26
26
  const newValue = expression();
27
27
  batch(() => {
@@ -29,7 +29,13 @@ function mobXAdapter(options) {
29
29
  });
30
30
  });
31
31
  disposers.push(disposer);
32
- return getValue;
32
+ const getter = (() => getValue());
33
+ getter.dispose = () => {
34
+ const i = disposers.indexOf(disposer);
35
+ if (i >= 0) disposers.splice(i, 1);
36
+ disposer();
37
+ };
38
+ return getter;
33
39
  }
34
40
  function toMobX(sibuGetter, callback) {
35
41
  return effect(() => {
@@ -57,12 +63,12 @@ function reduxAdapter(options) {
57
63
  setState(store.getState());
58
64
  });
59
65
  });
60
- function useSelector(selector) {
66
+ function select(selector) {
61
67
  return derived(() => selector(getState()));
62
68
  }
63
69
  const api = {
64
70
  getState,
65
- useSelector,
71
+ select,
66
72
  dispatch: store.dispatch.bind(store),
67
73
  destroy: unsubscribe
68
74
  };
@@ -80,12 +86,12 @@ function zustandAdapter(options) {
80
86
  setSibuState(state);
81
87
  });
82
88
  });
83
- function useSelector(selector) {
89
+ function select(selector) {
84
90
  return derived(() => selector(getState()));
85
91
  }
86
92
  const api = {
87
93
  getState,
88
- useSelector,
94
+ select,
89
95
  setState: store.setState.bind(store),
90
96
  destroy() {
91
97
  unsubscribe();
@@ -1,36 +1,34 @@
1
+ import {
2
+ isUrlAttribute,
3
+ sanitizeUrl
4
+ } from "./chunk-UCS6AMJ7.js";
1
5
  import {
2
6
  track
3
- } from "./chunk-V2XTI523.js";
7
+ } from "./chunk-QO3WC6FS.js";
4
8
  import {
5
9
  devWarn,
6
10
  isDev
7
- } from "./chunk-UNXCEF6S.js";
8
-
9
- // src/utils/sanitize.ts
10
- function sanitizeUrl(url) {
11
- const trimmed = url.replace(/[\x00-\x20\x7f-\x9f]+/g, "").trim();
12
- if (!trimmed) return "";
13
- const lower = trimmed.toLowerCase();
14
- if (lower.startsWith("javascript:") || lower.startsWith("data:") || lower.startsWith("vbscript:") || lower.startsWith("blob:")) {
15
- return "";
16
- }
17
- return trimmed;
18
- }
19
- function sanitizeCSSValue(value) {
20
- const lower = value.toLowerCase().replace(/\s+/g, "");
21
- if (lower.includes("url(") || lower.includes("expression(") || lower.includes("javascript:") || lower.includes("-moz-binding")) {
22
- return "";
23
- }
24
- return value;
25
- }
26
- var URL_ATTRIBUTES = /* @__PURE__ */ new Set(["href", "src", "action", "formaction", "cite", "poster", "background", "srcset"]);
27
- function isUrlAttribute(attr) {
28
- return URL_ATTRIBUTES.has(attr);
29
- }
11
+ } from "./chunk-LMLD24FC.js";
30
12
 
31
13
  // src/reactivity/bindAttribute.ts
32
14
  var _isDev = isDev();
15
+ function setProp(el, key, val) {
16
+ el[key] = val;
17
+ }
18
+ function isEventHandlerAttr(name) {
19
+ if (name.length < 3) return false;
20
+ const lower = name.toLowerCase();
21
+ return lower[0] === "o" && lower[1] === "n" && lower.charCodeAt(2) >= 97 && lower.charCodeAt(2) <= 122;
22
+ }
33
23
  function bindAttribute(el, attr, getter) {
24
+ if (isEventHandlerAttr(attr)) {
25
+ if (_isDev)
26
+ devWarn(
27
+ `bindAttribute: refusing to bind event-handler attribute "${attr}". Use on:{ ${attr.slice(2)}: fn } instead.`
28
+ );
29
+ return () => {
30
+ };
31
+ }
34
32
  function commit() {
35
33
  let value;
36
34
  try {
@@ -42,7 +40,7 @@ function bindAttribute(el, attr, getter) {
42
40
  }
43
41
  if (typeof value === "boolean") {
44
42
  if (attr in el && (attr === "checked" || attr === "disabled" || attr === "selected")) {
45
- el[attr] = value;
43
+ setProp(el, attr, value);
46
44
  } else if (value) {
47
45
  el.setAttribute(attr, "");
48
46
  } else {
@@ -52,7 +50,7 @@ function bindAttribute(el, attr, getter) {
52
50
  }
53
51
  const str = String(value);
54
52
  if ((attr === "value" || attr === "checked") && attr in el) {
55
- el[attr] = attr === "checked" ? Boolean(value) : str;
53
+ setProp(el, attr, attr === "checked" ? Boolean(value) : str);
56
54
  } else {
57
55
  el.setAttribute(attr, isUrlAttribute(attr) ? sanitizeUrl(str) : str);
58
56
  }
@@ -83,7 +81,7 @@ function bindDynamic(el, nameGetter, valueGetter) {
83
81
  }
84
82
  const str = String(value);
85
83
  if ((name === "value" || name === "checked") && name in el) {
86
- el[name] = name === "checked" ? Boolean(value) : str;
84
+ setProp(el, name, name === "checked" ? Boolean(value) : str);
87
85
  } else {
88
86
  el.setAttribute(name, isUrlAttribute(name) ? sanitizeUrl(str) : str);
89
87
  }
@@ -99,9 +97,6 @@ function bindDynamic(el, nameGetter, valueGetter) {
99
97
  }
100
98
 
101
99
  export {
102
- sanitizeUrl,
103
- sanitizeCSSValue,
104
- isUrlAttribute,
105
100
  bindAttribute,
106
101
  bindDynamic
107
102
  };
@@ -0,0 +1,149 @@
1
+ import {
2
+ isSSR
3
+ } from "./chunk-2RA7SHDA.js";
4
+ import {
5
+ track,
6
+ untracked
7
+ } from "./chunk-QO3WC6FS.js";
8
+ import {
9
+ devAssert
10
+ } from "./chunk-LMLD24FC.js";
11
+
12
+ // src/core/signals/effect.ts
13
+ var _g = globalThis;
14
+ function on(deps, handler) {
15
+ let prev;
16
+ let first = true;
17
+ return () => {
18
+ const value = deps();
19
+ if (first) {
20
+ first = false;
21
+ prev = value;
22
+ untracked(() => handler(value, void 0));
23
+ } else {
24
+ const p = prev;
25
+ prev = value;
26
+ untracked(() => handler(value, p));
27
+ }
28
+ };
29
+ }
30
+ function effect(effectFn, options) {
31
+ devAssert(typeof effectFn === "function", "effect: argument must be a function.");
32
+ if (isSSR()) return () => {
33
+ };
34
+ const onError = options?.onError;
35
+ let userCleanups = [];
36
+ const onCleanup = (fn) => {
37
+ userCleanups.push(fn);
38
+ };
39
+ const runUserCleanups = () => {
40
+ if (userCleanups.length === 0) return;
41
+ const list = userCleanups;
42
+ userCleanups = [];
43
+ for (let i = list.length - 1; i >= 0; i--) {
44
+ try {
45
+ list[i]();
46
+ } catch (err) {
47
+ if (typeof console !== "undefined") {
48
+ console.warn("[SibuJS effect] onCleanup threw:", err);
49
+ }
50
+ }
51
+ }
52
+ };
53
+ const invokeBody = () => effectFn(onCleanup);
54
+ const wrappedFn = onError ? () => {
55
+ try {
56
+ invokeBody();
57
+ } catch (err) {
58
+ onError(err);
59
+ }
60
+ } : invokeBody;
61
+ let cleanupHandle = () => {
62
+ };
63
+ let running = false;
64
+ let rerunPending = false;
65
+ const MAX_RERUNS = 100;
66
+ const subscriber = () => {
67
+ if (running) {
68
+ rerunPending = true;
69
+ return;
70
+ }
71
+ running = true;
72
+ try {
73
+ let reruns = 0;
74
+ do {
75
+ rerunPending = false;
76
+ runUserCleanups();
77
+ cleanupHandle();
78
+ cleanupHandle = track(wrappedFn, subscriber);
79
+ if (++reruns > MAX_RERUNS) {
80
+ if (_g.__SIBU_DEV_WARN__ !== false && typeof console !== "undefined") {
81
+ console.error(
82
+ `[SibuJS] effect re-requested itself ${MAX_RERUNS}+ times \u2014 likely a write-reads-self cycle. Breaking to prevent infinite loop.`
83
+ );
84
+ }
85
+ rerunPending = false;
86
+ break;
87
+ }
88
+ } while (rerunPending);
89
+ } finally {
90
+ running = false;
91
+ rerunPending = false;
92
+ }
93
+ };
94
+ running = true;
95
+ try {
96
+ let reruns = 0;
97
+ do {
98
+ rerunPending = false;
99
+ runUserCleanups();
100
+ cleanupHandle();
101
+ cleanupHandle = track(wrappedFn, subscriber);
102
+ if (++reruns > MAX_RERUNS) {
103
+ if (_g.__SIBU_DEV_WARN__ !== false && typeof console !== "undefined") {
104
+ console.error(
105
+ `[SibuJS] effect re-requested itself ${MAX_RERUNS}+ times on initial run \u2014 likely a write-reads-self cycle. Breaking to prevent infinite loop.`
106
+ );
107
+ }
108
+ rerunPending = false;
109
+ break;
110
+ }
111
+ } while (rerunPending);
112
+ } finally {
113
+ running = false;
114
+ rerunPending = false;
115
+ }
116
+ const hook = _g.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
117
+ if (hook) hook.emit("effect:create", { effectFn });
118
+ let disposed = false;
119
+ return () => {
120
+ if (disposed) return;
121
+ disposed = true;
122
+ const h = _g.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
123
+ if (h) {
124
+ try {
125
+ h.emit("effect:destroy", { effectFn });
126
+ } catch {
127
+ }
128
+ }
129
+ try {
130
+ runUserCleanups();
131
+ } catch (err) {
132
+ if (typeof console !== "undefined") {
133
+ console.warn("[SibuJS effect] onCleanup threw during dispose:", err);
134
+ }
135
+ }
136
+ try {
137
+ cleanupHandle();
138
+ } catch (err) {
139
+ if (typeof console !== "undefined") {
140
+ console.warn("[SibuJS effect] dispose threw:", err);
141
+ }
142
+ }
143
+ };
144
+ }
145
+
146
+ export {
147
+ on,
148
+ effect
149
+ };