sibujs 4.5.0 → 4.7.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 (116) hide show
  1. package/README.md +1 -1
  2. package/dist/browser.cjs +326 -133
  3. package/dist/browser.d.cts +46 -14
  4. package/dist/browser.d.ts +46 -14
  5. package/dist/browser.js +8 -6
  6. package/dist/build.cjs +2094 -1033
  7. package/dist/build.d.cts +133 -44
  8. package/dist/build.d.ts +133 -44
  9. package/dist/build.js +1372 -574
  10. package/dist/cdn.dev.global.js +10 -10
  11. package/dist/cdn.full.dev.global.js +11 -11
  12. package/dist/cdn.full.global.js +10 -10
  13. package/dist/cdn.global.js +10 -10
  14. package/dist/{chunk-2DCGACUU.js → chunk-2BPG2XDA.js} +251 -66
  15. package/dist/{chunk-IXKSNWV5.js → chunk-2INLLLMZ.js} +1 -1
  16. package/dist/{chunk-4PMLNECI.js → chunk-3QWBSL5R.js} +98 -29
  17. package/dist/{chunk-KKLW7YWL.js → chunk-4AWA2PVD.js} +275 -144
  18. package/dist/chunk-5HZXGZ6T.js +24 -0
  19. package/dist/{chunk-PCT43HW3.js → chunk-7LUJQAOJ.js} +1 -1
  20. package/dist/{chunk-5DXA2J44.js → chunk-7XHATCIH.js} +5 -2
  21. package/dist/chunk-BC2SECJD.js +44 -0
  22. package/dist/{chunk-TBYTO6BS.js → chunk-BSY63EM6.js} +136 -80
  23. package/dist/{chunk-FTIR4QW2.js → chunk-DKXRACVN.js} +6 -8
  24. package/dist/{chunk-ONOHFDLG.js → chunk-FNJXNGYZ.js} +3 -3
  25. package/dist/{chunk-XZZOBQAY.js → chunk-FQRUXCEE.js} +6 -5
  26. package/dist/{chunk-NIOYEGBQ.js → chunk-HURREPU2.js} +27 -13
  27. package/dist/chunk-J6FW5TV6.js +233 -0
  28. package/dist/{chunk-UGRX3S57.js → chunk-JWKYU5GV.js} +22 -4
  29. package/dist/chunk-NYNYSPK7.js +318 -0
  30. package/dist/{chunk-RBTPLM32.js → chunk-RUSSKG6G.js} +13 -12
  31. package/dist/{chunk-7LN645I6.js → chunk-SLM3IA34.js} +3 -3
  32. package/dist/{chunk-R25EFXXC.js → chunk-TUCPL2HB.js} +3 -3
  33. package/dist/{chunk-B3WHI2QA.js → chunk-UNWRJRKC.js} +55 -31
  34. package/dist/{chunk-KEISJXBU.js → chunk-UOL2ECCS.js} +44 -17
  35. package/dist/{chunk-RJE2BNI4.js → chunk-VZSG24LS.js} +108 -45
  36. package/dist/{chunk-RIXRAYIU.js → chunk-WEQ3DMVL.js} +10 -4
  37. package/dist/{chunk-3JZ4L5TJ.js → chunk-WOLJZUFQ.js} +354 -90
  38. package/dist/{chunk-S373NSMK.js → chunk-XYV3EDB7.js} +283 -123
  39. package/dist/{chunk-VZKNK2V7.js → chunk-XZR4PXRE.js} +296 -38
  40. package/dist/{chunk-GW3SCCZG.js → chunk-Z3OHK6QT.js} +153 -110
  41. package/dist/{chunk-OMJJM3KM.js → chunk-ZVL7TY4K.js} +287 -130
  42. package/dist/{contracts-DBdg9J_a.d.ts → contracts-CLqzJnOV.d.ts} +36 -17
  43. package/dist/{contracts-DBdg9J_a.d.cts → contracts-CTOJXu-x.d.cts} +36 -17
  44. package/dist/{customElement-OB9CIsc5.d.cts → customElement-MmInOW1U.d.cts} +21 -0
  45. package/dist/{customElement-OB9CIsc5.d.ts → customElement-MmInOW1U.d.ts} +21 -0
  46. package/dist/data.cjs +410 -155
  47. package/dist/data.d.cts +166 -12
  48. package/dist/data.d.ts +166 -12
  49. package/dist/data.js +12 -9
  50. package/dist/devtools.cjs +98 -61
  51. package/dist/devtools.js +7 -8
  52. package/dist/dispose-GEIG2KOF.js +28 -0
  53. package/dist/ecosystem.cjs +372 -126
  54. package/dist/ecosystem.d.cts +20 -3
  55. package/dist/ecosystem.d.ts +20 -3
  56. package/dist/ecosystem.js +12 -12
  57. package/dist/extras.cjs +2366 -909
  58. package/dist/extras.d.cts +11 -9
  59. package/dist/extras.d.ts +11 -9
  60. package/dist/extras.js +39 -28
  61. package/dist/index.cjs +421 -158
  62. package/dist/index.d.cts +213 -171
  63. package/dist/index.d.ts +213 -171
  64. package/dist/index.js +24 -27
  65. package/dist/motion.cjs +118 -44
  66. package/dist/motion.js +5 -5
  67. package/dist/patterns.cjs +344 -53
  68. package/dist/patterns.d.cts +28 -9
  69. package/dist/patterns.d.ts +28 -9
  70. package/dist/patterns.js +8 -8
  71. package/dist/performance.cjs +325 -220
  72. package/dist/performance.d.cts +2 -2
  73. package/dist/performance.d.ts +2 -2
  74. package/dist/performance.js +8 -9
  75. package/dist/plugin-DVgSnTfK.d.cts +112 -0
  76. package/dist/plugin-DVgSnTfK.d.ts +112 -0
  77. package/dist/plugins.cjs +664 -233
  78. package/dist/plugins.d.cts +127 -14
  79. package/dist/plugins.d.ts +127 -14
  80. package/dist/plugins.js +96 -42
  81. package/dist/signal-EotCj4hS.d.cts +110 -0
  82. package/dist/signal-EotCj4hS.d.ts +110 -0
  83. package/dist/{ssr-BiPRdZ6n.d.cts → ssr-Bli9XRW5.d.cts} +5 -0
  84. package/dist/{ssr-BiPRdZ6n.d.ts → ssr-Bli9XRW5.d.ts} +5 -0
  85. package/dist/{ssr-Y7XOEPEN.js → ssr-XOTUASDO.js} +4 -5
  86. package/dist/ssr.cjs +229 -84
  87. package/dist/ssr.d.cts +9 -3
  88. package/dist/ssr.d.ts +9 -3
  89. package/dist/ssr.js +11 -12
  90. package/dist/{startup-BMpaiMhP.d.ts → startup-BLfSeL15.d.cts} +73 -22
  91. package/dist/{startup-BMpaiMhP.d.cts → startup-BLfSeL15.d.ts} +73 -22
  92. package/dist/tagFactory-8qL9LCIx.d.cts +156 -0
  93. package/dist/tagFactory-BL2fymez.d.ts +156 -0
  94. package/dist/testing.cjs +2503 -2191
  95. package/dist/testing.d.cts +56 -5
  96. package/dist/testing.d.ts +56 -5
  97. package/dist/testing.js +580 -307
  98. package/dist/types-CJFViL6Q.d.cts +26 -0
  99. package/dist/types-CJFViL6Q.d.ts +26 -0
  100. package/dist/ui.cjs +732 -329
  101. package/dist/ui.d.cts +41 -7
  102. package/dist/ui.d.ts +41 -7
  103. package/dist/ui.js +151 -56
  104. package/dist/widgets.cjs +267 -291
  105. package/dist/widgets.js +9 -10
  106. package/package.json +4 -2
  107. package/dist/chunk-2WLZ6757.js +0 -149
  108. package/dist/chunk-CCSJMTRN.js +0 -15
  109. package/dist/chunk-QKRPLZ2V.js +0 -108
  110. package/dist/chunk-VUF4ALSW.js +0 -60
  111. package/dist/chunk-WWV3SJ3L.js +0 -131
  112. package/dist/dispose-46BOMMQJ.js +0 -19
  113. package/dist/plugin-D30wlGW5.d.cts +0 -71
  114. package/dist/plugin-D30wlGW5.d.ts +0 -71
  115. package/dist/tagFactory-DVoDpHye.d.cts +0 -215
  116. package/dist/tagFactory-DVoDpHye.d.ts +0 -215
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  DEV,
3
3
  devWarn
4
- } from "./chunk-2WLZ6757.js";
4
+ } from "./chunk-NYNYSPK7.js";
5
5
 
6
6
  // src/patterns/hoc.ts
7
7
  function withWrapper(WrappedComponent, wrapper) {
@@ -122,7 +122,7 @@ function validateProps(props, schema) {
122
122
  const errors = [];
123
123
  for (const [key, def] of Object.entries(schema)) {
124
124
  const propDef = typeof def === "function" ? { type: def } : def;
125
- if (result[key] == null && propDef.default !== void 0) {
125
+ if (result[key] === void 0 && propDef.default !== void 0) {
126
126
  result[key] = typeof propDef.default === "function" ? propDef.default() : propDef.default;
127
127
  }
128
128
  if (propDef.required && result[key] == null) {
@@ -148,7 +148,7 @@ ${errors.map((e) => ` - ${e}`).join("\n")}`);
148
148
  for (const [key, def] of Object.entries(schema)) {
149
149
  if (typeof def === "function") continue;
150
150
  const fallback = def.default;
151
- if (result[key] == null && fallback !== void 0) {
151
+ if (result[key] === void 0 && fallback !== void 0) {
152
152
  result[key] = typeof fallback === "function" ? fallback() : fallback;
153
153
  }
154
154
  }
@@ -1,9 +1,13 @@
1
1
  import {
2
- registerDisposer
3
- } from "./chunk-QKRPLZ2V.js";
2
+ adoptThenable
3
+ } from "./chunk-5HZXGZ6T.js";
4
4
  import {
5
5
  signal
6
- } from "./chunk-XZZOBQAY.js";
6
+ } from "./chunk-FQRUXCEE.js";
7
+ import {
8
+ registerDisposer,
9
+ reportError
10
+ } from "./chunk-NYNYSPK7.js";
7
11
 
8
12
  // src/ui/transition.ts
9
13
  function transition(element, options = {}) {
@@ -32,6 +36,15 @@ function transition(element, options = {}) {
32
36
  resolvePrev();
33
37
  }
34
38
  }
39
+ function complete(callback, name, resolve) {
40
+ try {
41
+ callback?.();
42
+ } catch (error) {
43
+ reportError(error, { phase: "async", name, node: element });
44
+ } finally {
45
+ resolve();
46
+ }
47
+ }
35
48
  function enter() {
36
49
  return new Promise((resolve) => {
37
50
  cancelPending();
@@ -44,8 +57,7 @@ function transition(element, options = {}) {
44
57
  activeTimer = null;
45
58
  pendingResolve = null;
46
59
  if (enterClass) element.classList.remove(enterClass);
47
- onEnterDone?.();
48
- resolve();
60
+ complete(onEnterDone, "transition(onEnterDone)", resolve);
49
61
  };
50
62
  if (duration > 0) {
51
63
  pendingResolve = resolve;
@@ -66,8 +78,7 @@ function transition(element, options = {}) {
66
78
  activeTimer = null;
67
79
  pendingResolve = null;
68
80
  if (leaveClass) element.classList.remove(leaveClass);
69
- onLeaveDone?.();
70
- resolve();
81
+ complete(onLeaveDone, "transition(onLeaveDone)", resolve);
71
82
  };
72
83
  if (duration > 0) {
73
84
  pendingResolve = resolve;
@@ -274,18 +285,29 @@ async function sequence(steps) {
274
285
  function TransitionGroup(options) {
275
286
  const [elements, setElements] = signal([]);
276
287
  const positions = /* @__PURE__ */ new Map();
288
+ function runCallback(name, callback, el) {
289
+ const report = (error) => reportError(error, { phase: "async", name: `TransitionGroup.${name}`, node: el });
290
+ try {
291
+ adoptThenable(callback(el))?.then(void 0, report);
292
+ } catch (error) {
293
+ report(error);
294
+ }
295
+ }
277
296
  function add(el) {
278
297
  setElements((prev) => [...prev, el]);
279
- if (options.enter) {
280
- options.enter(el);
281
- }
298
+ if (options.enter) runCallback("enter", options.enter, el);
282
299
  }
283
300
  async function remove(el) {
284
- if (options.leave) {
285
- await options.leave(el);
301
+ try {
302
+ if (options.leave) {
303
+ await adoptThenable(options.leave(el));
304
+ }
305
+ } catch (error) {
306
+ reportError(error, { phase: "async", name: "TransitionGroup.leave", node: el });
307
+ } finally {
308
+ positions.delete(el);
309
+ setElements((prev) => prev.filter((e) => e !== el));
286
310
  }
287
- positions.delete(el);
288
- setElements((prev) => prev.filter((e) => e !== el));
289
311
  }
290
312
  function track(newElements) {
291
313
  const oldPositions = /* @__PURE__ */ new Map();
@@ -297,17 +319,13 @@ function TransitionGroup(options) {
297
319
  const currentSet = new Set(elements());
298
320
  for (const el of newElements) {
299
321
  if (!currentSet.has(el)) {
300
- if (options.enter) {
301
- options.enter(el);
302
- }
322
+ if (options.enter) runCallback("enter", options.enter, el);
303
323
  }
304
324
  }
305
325
  const newSet = new Set(newElements);
306
326
  for (const el of elements()) {
307
327
  if (!newSet.has(el)) {
308
- if (options.leave) {
309
- options.leave(el);
310
- }
328
+ if (options.leave) runCallback("leave", options.leave, el);
311
329
  }
312
330
  }
313
331
  setElements(newElements);
@@ -317,7 +335,7 @@ function TransitionGroup(options) {
317
335
  if (oldRect && typeof el.getBoundingClientRect === "function") {
318
336
  const newRect = el.getBoundingClientRect();
319
337
  if (oldRect.left !== newRect.left || oldRect.top !== newRect.top) {
320
- options.move(el);
338
+ runCallback("move", options.move, el);
321
339
  }
322
340
  }
323
341
  }
@@ -368,9 +386,13 @@ function springSignal(initial, options) {
368
386
  let target = initial;
369
387
  let rafId = null;
370
388
  let lastTime = 0;
389
+ let disposed = false;
390
+ const canAnimate = () => typeof requestAnimationFrame === "function";
371
391
  const REF_DT_MS = 1e3 / 60;
372
392
  const MAX_STEP_RATIO = 4;
373
393
  function tick(now) {
394
+ rafId = null;
395
+ if (disposed) return;
374
396
  if (lastTime === 0) lastTime = now;
375
397
  const rawDt = now - lastTime;
376
398
  lastTime = now;
@@ -383,23 +405,27 @@ function springSignal(initial, options) {
383
405
  if (Math.abs(current - target) < precision && Math.abs(velocity) < precision) {
384
406
  current = target;
385
407
  velocity = 0;
386
- rafId = null;
387
408
  lastTime = 0;
388
409
  setValue(current);
389
410
  return;
390
411
  }
391
412
  setValue(current);
413
+ if (disposed || rafId !== null) return;
392
414
  rafId = requestAnimationFrame(tick);
393
415
  }
416
+ function cancelFrame() {
417
+ if (rafId !== null) {
418
+ if (typeof cancelAnimationFrame === "function") cancelAnimationFrame(rafId);
419
+ rafId = null;
420
+ }
421
+ }
394
422
  function set(newTarget) {
423
+ if (disposed) return;
395
424
  target = newTarget;
396
- if (prefersReducedMotion()) {
425
+ if (!canAnimate() || prefersReducedMotion()) {
397
426
  current = newTarget;
398
427
  velocity = 0;
399
- if (rafId !== null) {
400
- cancelAnimationFrame(rafId);
401
- rafId = null;
402
- }
428
+ cancelFrame();
403
429
  lastTime = 0;
404
430
  setValue(current);
405
431
  return;
@@ -410,10 +436,8 @@ function springSignal(initial, options) {
410
436
  }
411
437
  }
412
438
  function dispose() {
413
- if (rafId !== null) {
414
- cancelAnimationFrame(rafId);
415
- rafId = null;
416
- }
439
+ disposed = true;
440
+ cancelFrame();
417
441
  lastTime = 0;
418
442
  }
419
443
  return [value, set, dispose];
@@ -1,25 +1,23 @@
1
1
  import {
2
2
  bindAttribute,
3
3
  setSafeAttribute
4
- } from "./chunk-ONOHFDLG.js";
4
+ } from "./chunk-FNJXNGYZ.js";
5
5
  import {
6
6
  isEventHandlerAttr,
7
7
  sanitizeCSSValue,
8
8
  sanitizeStyleAttribute
9
- } from "./chunk-IXKSNWV5.js";
10
- import {
11
- dispose,
12
- registerDisposer
13
- } from "./chunk-QKRPLZ2V.js";
9
+ } from "./chunk-2INLLLMZ.js";
14
10
  import {
15
11
  reactiveBinding
16
- } from "./chunk-UGRX3S57.js";
12
+ } from "./chunk-JWKYU5GV.js";
17
13
  import {
18
14
  DEV,
19
15
  devWarn,
20
16
  devWarnLazy,
17
+ dispose,
18
+ registerDisposer,
21
19
  reportError
22
- } from "./chunk-2WLZ6757.js";
20
+ } from "./chunk-NYNYSPK7.js";
23
21
 
24
22
  // src/core/rendering/focusPreservation.ts
25
23
  var IDENTITY_ATTRS = ["data-focus-key", "id", "name"];
@@ -221,8 +219,34 @@ function toKebab(prop) {
221
219
  }
222
220
  function applyStyle(el, style) {
223
221
  if (typeof style === "function") {
222
+ const getter = style;
223
+ let written = [];
224
+ let wroteString = false;
224
225
  const teardown = reactiveBinding(() => {
225
- el.setAttribute("style", sanitizeStyleAttribute(String(style()), { element: el }));
226
+ const value = getter();
227
+ if (value === null || typeof value !== "object") {
228
+ written = [];
229
+ wroteString = true;
230
+ el.setAttribute("style", sanitizeStyleAttribute(String(value), { element: el }));
231
+ return;
232
+ }
233
+ const decl = el.style;
234
+ if (wroteString) {
235
+ el.removeAttribute("style");
236
+ wroteString = false;
237
+ }
238
+ const next = [];
239
+ for (const prop in value) {
240
+ const val = value[prop];
241
+ if (val == null) continue;
242
+ const name = toKebab(prop);
243
+ next.push(name);
244
+ decl.setProperty(name, sanitizeCSSValue(String(val), { property: name, element: el }));
245
+ }
246
+ for (let i = 0; i < written.length; i++) {
247
+ if (next.indexOf(written[i]) === -1) decl.removeProperty(written[i]);
248
+ }
249
+ written = next;
226
250
  }, el);
227
251
  registerDisposer(el, teardown);
228
252
  return;
@@ -248,7 +272,7 @@ function applyStyle(el, style) {
248
272
  }
249
273
  function resolveClassValue(cls) {
250
274
  if (typeof cls === "string") return cls;
251
- if (typeof cls === "function") return cls();
275
+ if (typeof cls === "function") return cls() || "";
252
276
  if (!cls) return "";
253
277
  let out = "";
254
278
  for (const name in cls) {
@@ -265,7 +289,9 @@ function applyClass(el, cls) {
265
289
  }
266
290
  if (typeof cls === "function") {
267
291
  const teardown = reactiveBinding(() => {
268
- el.setAttribute("class", cls());
292
+ const value = cls();
293
+ if (value == null || value === false) el.removeAttribute("class");
294
+ else el.setAttribute("class", value);
269
295
  }, el);
270
296
  registerDisposer(el, teardown);
271
297
  return;
@@ -347,7 +373,7 @@ function appendChildren(el, nodes) {
347
373
  }
348
374
  }
349
375
  }
350
- var tagFactory = (tag, ns) => {
376
+ function tagFactory(tag, ns) {
351
377
  const blocked = isBlockedTag(tag);
352
378
  return (first, second) => {
353
379
  if (blocked) {
@@ -396,7 +422,9 @@ var tagFactory = (tag, ns) => {
396
422
  const pClass = props.class;
397
423
  if (pClass != null) applyClass(el, pClass);
398
424
  const pId = props.id;
399
- if (pId != null) {
425
+ if (typeof pId === "function") {
426
+ registerDisposer(el, bindAttribute(el, "id", pId));
427
+ } else if (pId != null) {
400
428
  if (DEV && typeof pId === "string" && CLOBBER_RISKY_IDS.has(pId.toLowerCase())) {
401
429
  devWarn(
402
430
  `tagFactory: element id="${pId}" matches a common global and may cause DOM clobbering. Avoid setting ids from untrusted input.`
@@ -446,12 +474,10 @@ var tagFactory = (tag, ns) => {
446
474
  }
447
475
  }
448
476
  }
449
- if (props.onElement && typeof props.onElement === "function") {
450
- props.onElement(el);
451
- }
477
+ if (typeof props.onElement === "function") props.onElement(el);
452
478
  return el;
453
479
  };
454
- };
480
+ }
455
481
 
456
482
  export {
457
483
  captureFocusWithin,
@@ -459,5 +485,6 @@ export {
459
485
  bindChildNode,
460
486
  SVG_NS,
461
487
  resolveClassValue,
488
+ appendChildren,
462
489
  tagFactory
463
490
  };
@@ -6,29 +6,30 @@ import {
6
6
  import {
7
7
  div,
8
8
  span
9
- } from "./chunk-PCT43HW3.js";
9
+ } from "./chunk-7LUJQAOJ.js";
10
10
  import {
11
11
  STATIC_VALUE_RESOLVER,
12
12
  planHeadElementEntry,
13
13
  planMetaEntry
14
- } from "./chunk-NIOYEGBQ.js";
14
+ } from "./chunk-HURREPU2.js";
15
15
  import {
16
16
  sanitizeUrl
17
- } from "./chunk-IXKSNWV5.js";
17
+ } from "./chunk-2INLLLMZ.js";
18
18
  import {
19
19
  globalSingleton
20
20
  } from "./chunk-7ZHH77QA.js";
21
21
  import {
22
22
  effect
23
- } from "./chunk-RIXRAYIU.js";
24
- import {
25
- registerDisposer,
26
- replaceChildrenSafely
27
- } from "./chunk-QKRPLZ2V.js";
23
+ } from "./chunk-WEQ3DMVL.js";
28
24
  import {
29
25
  batch,
30
26
  signal
31
- } from "./chunk-XZZOBQAY.js";
27
+ } from "./chunk-FQRUXCEE.js";
28
+ import {
29
+ registerDisposer,
30
+ replaceChildrenSafely,
31
+ reportError
32
+ } from "./chunk-NYNYSPK7.js";
32
33
 
33
34
  // src/platform/head.ts
34
35
  function escapeScriptJsonLocal(json) {
@@ -96,7 +97,7 @@ function Head(props) {
96
97
  };
97
98
  const apply = () => {
98
99
  cleanup();
99
- if (props.title) {
100
+ if (props.title != null) {
100
101
  if (typeof props.title === "function") {
101
102
  const getter = props.title;
102
103
  let lease = null;
@@ -151,13 +152,14 @@ function Head(props) {
151
152
  return anchor;
152
153
  }
153
154
  function setStructuredData(data) {
154
- const existing = document.head.querySelector('script[type="application/ld+json"][data-sibu]');
155
- if (existing) existing.remove();
155
+ const json = escapeScriptJsonLocal(JSON.stringify(data));
156
156
  const script = document.createElement("script");
157
157
  script.type = "application/ld+json";
158
158
  script.setAttribute("data-sibu", "true");
159
- script.textContent = escapeScriptJsonLocal(JSON.stringify(data));
160
- document.head.appendChild(script);
159
+ script.textContent = json;
160
+ const existing = document.head.querySelector('script[type="application/ld+json"][data-sibu]');
161
+ if (existing) existing.replaceWith(script);
162
+ else document.head.appendChild(script);
161
163
  }
162
164
  function setCanonical(url) {
163
165
  let link = document.head.querySelector('link[rel="canonical"]');
@@ -172,6 +174,11 @@ function setCanonical(url) {
172
174
  }
173
175
 
174
176
  // src/platform/worker.ts
177
+ function toError(err) {
178
+ if (err instanceof Error) return err;
179
+ if (err !== null && typeof err === "object" && "name" in err && "message" in err) return err;
180
+ return new Error(String(err));
181
+ }
175
182
  function worker(workerFn2) {
176
183
  const [result, setResult] = signal(null);
177
184
  const [error, setError] = signal(null);
@@ -194,8 +201,11 @@ function worker(workerFn2) {
194
201
  worker2 = new Worker(blobUrl);
195
202
  worker2.addEventListener("message", (e) => {
196
203
  revokeBlobUrl();
197
- setResult(e.data);
198
- setLoading(false);
204
+ batch(() => {
205
+ setResult(e.data);
206
+ setError(null);
207
+ setLoading(false);
208
+ });
199
209
  });
200
210
  worker2.addEventListener("error", (e) => {
201
211
  revokeBlobUrl();
@@ -212,10 +222,17 @@ function worker(workerFn2) {
212
222
  }
213
223
  function post(data) {
214
224
  if (!worker2) return;
215
- setLoading(true);
216
- setError(null);
217
- setResult(null);
218
- worker2.postMessage(data);
225
+ try {
226
+ worker2.postMessage(data);
227
+ } catch (err) {
228
+ setError(toError(err));
229
+ return;
230
+ }
231
+ batch(() => {
232
+ setLoading(true);
233
+ setError(null);
234
+ setResult(null);
235
+ });
219
236
  }
220
237
  function terminate() {
221
238
  if (!worker2) return;
@@ -279,9 +296,14 @@ function workerFn(fn) {
279
296
  reject(new Error("Worker is not available"));
280
297
  return;
281
298
  }
282
- setLoading(true);
299
+ try {
300
+ worker2.postMessage(args);
301
+ } catch (err) {
302
+ reject(toError(err));
303
+ return;
304
+ }
283
305
  queue.push({ resolve, reject });
284
- worker2.postMessage(args);
306
+ setLoading(true);
285
307
  });
286
308
  }
287
309
  function terminate() {
@@ -311,7 +333,11 @@ function createWorkerPool(workerFn2, poolSize) {
311
333
  }
312
334
  };
313
335
  function dispatchNext(idx) {
314
- if (!alive || inflight[idx] || queues[idx].length === 0) return;
336
+ while (alive && !inflight[idx] && queues[idx].length > 0) {
337
+ dispatchOne(idx);
338
+ }
339
+ }
340
+ function dispatchOne(idx) {
315
341
  const w = workers[idx];
316
342
  const slot = queues[idx].shift();
317
343
  const onMsg = (e) => {
@@ -336,10 +362,15 @@ function createWorkerPool(workerFn2, poolSize) {
336
362
  slot.reject(new Error(e.message || "Worker error"));
337
363
  dispatchNext(idx);
338
364
  };
365
+ try {
366
+ w.postMessage(slot.data);
367
+ } catch (err) {
368
+ slot.reject(toError(err));
369
+ return;
370
+ }
339
371
  inflight[idx] = { ...slot, onMsg, onErr };
340
372
  w.addEventListener("message", onMsg);
341
373
  w.addEventListener("error", onErr);
342
- w.postMessage(slot.data);
343
374
  }
344
375
  try {
345
376
  if (typeof Worker === "undefined") {
@@ -668,13 +699,13 @@ function createSharedScope(initialState) {
668
699
  for (const key of Object.keys(initialState)) {
669
700
  const [get2, set2] = signal(initialState[key]);
670
701
  signals.set(key, { get: get2, set: set2 });
671
- subscribers.set(key, /* @__PURE__ */ new Set());
702
+ subscribers.set(key, /* @__PURE__ */ new Map());
672
703
  }
673
704
  function ensureSignal(key) {
674
705
  if (!signals.has(key)) {
675
706
  const [get2, set2] = signal(void 0);
676
707
  signals.set(key, { get: get2, set: set2 });
677
- subscribers.set(key, /* @__PURE__ */ new Set());
708
+ subscribers.set(key, /* @__PURE__ */ new Map());
678
709
  }
679
710
  }
680
711
  function get(key) {
@@ -685,9 +716,14 @@ function createSharedScope(initialState) {
685
716
  ensureSignal(key);
686
717
  signals.get(key)?.set(value);
687
718
  const subs = subscribers.get(key);
688
- if (subs) {
689
- for (const cb of subs) {
690
- cb(value);
719
+ if (subs && subs.size > 0) {
720
+ for (const subscription of Array.from(subs.values())) {
721
+ if (!subscription.active) continue;
722
+ try {
723
+ subscription.callback(value);
724
+ } catch (err) {
725
+ reportError(err, { phase: "event", name: `sharedScope(${String(key)})` });
726
+ }
691
727
  }
692
728
  }
693
729
  }
@@ -698,9 +734,17 @@ function createSharedScope(initialState) {
698
734
  return () => {
699
735
  };
700
736
  }
701
- subs.add(callback);
737
+ const cb = callback;
738
+ let subscription = subs.get(cb);
739
+ if (!subscription) {
740
+ subscription = { callback: cb, active: true };
741
+ subs.set(cb, subscription);
742
+ }
743
+ const own = subscription;
702
744
  return () => {
703
- subs.delete(callback);
745
+ if (subs.get(cb) !== own) return;
746
+ own.active = false;
747
+ subs.delete(cb);
704
748
  };
705
749
  }
706
750
  return { get, set, subscribe };
@@ -852,15 +896,31 @@ async function generateStaticSite(options) {
852
896
  // src/platform/incrementalRegeneration.ts
853
897
  function createISR(options) {
854
898
  const { revalidateAfter, fetcher, initialData } = options;
899
+ if (!Number.isFinite(revalidateAfter) || revalidateAfter <= 0) {
900
+ throw new RangeError(`[SibuJS ISR] revalidateAfter must be a positive finite number, got ${revalidateAfter}`);
901
+ }
855
902
  const [data, setData] = signal(initialData);
856
- const [timestamp, setTimestamp] = signal(initialData !== void 0 ? Date.now() : 0);
903
+ const [stale, setStale] = signal(initialData === void 0);
857
904
  const controller = new AbortController();
858
905
  let inFlight = false;
859
906
  let disposed = false;
860
- const isStale = () => {
861
- const ts = timestamp();
862
- if (ts === 0) return true;
863
- return Date.now() - ts >= revalidateAfter;
907
+ let deadline;
908
+ const clearDeadline = () => {
909
+ if (deadline !== void 0) {
910
+ clearTimeout(deadline);
911
+ deadline = void 0;
912
+ }
913
+ };
914
+ const armDeadline = () => {
915
+ clearDeadline();
916
+ deadline = setTimeout(() => {
917
+ deadline = void 0;
918
+ if (disposed) return;
919
+ setStale(true);
920
+ revalidate().catch((err) => {
921
+ if (typeof console !== "undefined") console.warn("[SibuJS ISR] revalidate failed", err);
922
+ });
923
+ }, revalidateAfter);
864
924
  };
865
925
  const revalidate = async () => {
866
926
  if (disposed || inFlight) return;
@@ -869,8 +929,14 @@ function createISR(options) {
869
929
  try {
870
930
  const result = await fetcher({ signal: controller.signal });
871
931
  if (disposed || controller.signal.aborted) return;
872
- setData(result);
873
- setTimestamp(Date.now());
932
+ batch(() => {
933
+ setData(result);
934
+ setStale(false);
935
+ });
936
+ armDeadline();
937
+ } catch (err) {
938
+ if (!disposed && !controller.signal.aborted) armDeadline();
939
+ throw err;
874
940
  } finally {
875
941
  inFlight = false;
876
942
  }
@@ -879,19 +945,16 @@ function createISR(options) {
879
945
  revalidate().catch((err) => {
880
946
  if (typeof console !== "undefined") console.warn("[SibuJS ISR] initial fetch failed", err);
881
947
  });
948
+ } else {
949
+ armDeadline();
882
950
  }
883
- const intervalId = setInterval(() => {
884
- revalidate().catch((err) => {
885
- if (typeof console !== "undefined") console.warn("[SibuJS ISR] revalidate failed", err);
886
- });
887
- }, revalidateAfter);
888
951
  const dispose = () => {
889
952
  if (disposed) return;
890
953
  disposed = true;
891
- clearInterval(intervalId);
954
+ clearDeadline();
892
955
  controller.abort();
893
956
  };
894
- return { data, isStale, revalidate, dispose };
957
+ return { data, isStale: stale, revalidate, dispose };
895
958
  }
896
959
 
897
960
  // src/platform/routeActions.ts
@@ -1,15 +1,16 @@
1
1
  import {
2
2
  isSSR
3
- } from "./chunk-5DXA2J44.js";
3
+ } from "./chunk-7XHATCIH.js";
4
4
  import {
5
5
  cleanup,
6
+ emitDevtools,
6
7
  retrack,
7
8
  untracked
8
- } from "./chunk-UGRX3S57.js";
9
+ } from "./chunk-JWKYU5GV.js";
9
10
  import {
10
11
  devAssert,
11
12
  reportError
12
- } from "./chunk-2WLZ6757.js";
13
+ } from "./chunk-NYNYSPK7.js";
13
14
 
14
15
  // src/core/signals/effect.ts
15
16
  var _g = globalThis;
@@ -142,12 +143,17 @@ function effect(effectFn, options) {
142
143
  try {
143
144
  retrack(ctx.bodyFn, ctx.subscriber);
144
145
  if (ctx.rerunPending) drainReruns(ctx);
146
+ } catch (err) {
147
+ ctx.disposed = true;
148
+ if (ctx.userCleanups.length > 0) flushUserCleanups(ctx);
149
+ cleanup(ctx.subscriber);
150
+ throw err;
145
151
  } finally {
146
152
  ctx.running = false;
147
153
  ctx.rerunPending = false;
148
154
  }
149
155
  const hook = _g.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
150
- if (hook) hook.emit("effect:create", { effectFn });
156
+ if (hook) emitDevtools(hook, "effect:create", { effectFn });
151
157
  return () => disposeEffect(ctx);
152
158
  }
153
159