sibujs 4.4.0 → 4.5.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 (74) hide show
  1. package/README.md +11 -0
  2. package/dist/browser.cjs +31 -2
  3. package/dist/browser.d.cts +15 -2
  4. package/dist/browser.d.ts +15 -2
  5. package/dist/browser.js +4 -4
  6. package/dist/build.cjs +92 -13
  7. package/dist/build.js +10 -10
  8. package/dist/cdn.dev.global.js +9 -9
  9. package/dist/cdn.full.dev.global.js +10 -10
  10. package/dist/cdn.full.global.js +9 -9
  11. package/dist/cdn.global.js +9 -9
  12. package/dist/{chunk-XLO7SLIX.js → chunk-2DCGACUU.js} +16 -9
  13. package/dist/{chunk-6GSIXTWX.js → chunk-3JZ4L5TJ.js} +10 -4
  14. package/dist/{chunk-UCALUKB5.js → chunk-4PMLNECI.js} +4 -4
  15. package/dist/{chunk-RR7M3FHM.js → chunk-7LN645I6.js} +1 -1
  16. package/dist/{chunk-SKPTERHP.js → chunk-B3WHI2QA.js} +1 -1
  17. package/dist/{chunk-4Z3SPQ67.js → chunk-FTIR4QW2.js} +13 -3
  18. package/dist/{chunk-HFCOH2GN.js → chunk-GW3SCCZG.js} +4 -4
  19. package/dist/{chunk-PNIRUQ4C.js → chunk-KEISJXBU.js} +2 -2
  20. package/dist/{chunk-LYVUX7NT.js → chunk-OMJJM3KM.js} +2 -2
  21. package/dist/{chunk-VCTAEPSB.js → chunk-ONOHFDLG.js} +9 -1
  22. package/dist/{chunk-36S2YPP4.js → chunk-PCT43HW3.js} +1 -1
  23. package/dist/{chunk-W2EQ7X2L.js → chunk-RBTPLM32.js} +46 -8
  24. package/dist/{chunk-7GIHSAWB.js → chunk-RIXRAYIU.js} +1 -1
  25. package/dist/{chunk-HQSEH5F6.js → chunk-RJE2BNI4.js} +3 -3
  26. package/dist/{chunk-ADM46X22.js → chunk-S373NSMK.js} +18 -13
  27. package/dist/{chunk-M2F7TZHH.js → chunk-TBYTO6BS.js} +2 -2
  28. package/dist/{chunk-3BTTCZ5J.js → chunk-UGRX3S57.js} +31 -2
  29. package/dist/{chunk-7NBDXVHS.js → chunk-VUF4ALSW.js} +1 -1
  30. package/dist/{chunk-LQFGQNMV.js → chunk-VZKNK2V7.js} +9 -4
  31. package/dist/{chunk-NVNJH22U.js → chunk-XZZOBQAY.js} +1 -1
  32. package/dist/{customElement-CNZxEB9G.d.ts → customElement-OB9CIsc5.d.cts} +38 -10
  33. package/dist/{customElement-CNZxEB9G.d.cts → customElement-OB9CIsc5.d.ts} +38 -10
  34. package/dist/data.cjs +81 -9
  35. package/dist/data.js +6 -6
  36. package/dist/devtools.cjs +41 -2
  37. package/dist/devtools.js +4 -4
  38. package/dist/ecosystem.cjs +83 -9
  39. package/dist/ecosystem.d.cts +13 -5
  40. package/dist/ecosystem.d.ts +13 -5
  41. package/dist/ecosystem.js +7 -7
  42. package/dist/extras.cjs +115 -14
  43. package/dist/extras.d.cts +2 -2
  44. package/dist/extras.d.ts +2 -2
  45. package/dist/extras.js +19 -19
  46. package/dist/index.cjs +92 -13
  47. package/dist/index.d.cts +24 -151
  48. package/dist/index.d.ts +24 -151
  49. package/dist/index.js +10 -10
  50. package/dist/motion.cjs +31 -2
  51. package/dist/motion.js +3 -3
  52. package/dist/patterns.cjs +81 -10
  53. package/dist/patterns.d.cts +5 -0
  54. package/dist/patterns.d.ts +5 -0
  55. package/dist/patterns.js +5 -5
  56. package/dist/performance.cjs +31 -2
  57. package/dist/performance.js +4 -4
  58. package/dist/plugins.cjs +39 -2
  59. package/dist/plugins.js +6 -6
  60. package/dist/ssr.cjs +39 -2
  61. package/dist/ssr.js +7 -7
  62. package/dist/tagFactory-DVoDpHye.d.cts +215 -0
  63. package/dist/tagFactory-DVoDpHye.d.ts +215 -0
  64. package/dist/testing.cjs +31 -2
  65. package/dist/testing.js +2 -2
  66. package/dist/ui.cjs +93 -13
  67. package/dist/ui.d.cts +1 -1
  68. package/dist/ui.d.ts +1 -1
  69. package/dist/ui.js +6 -6
  70. package/dist/widgets.cjs +75 -9
  71. package/dist/widgets.js +6 -6
  72. package/package.json +2 -2
  73. package/dist/tagFactory-Bzupt4Pj.d.cts +0 -55
  74. package/dist/tagFactory-Bzupt4Pj.d.ts +0 -55
package/dist/ui.cjs CHANGED
@@ -417,6 +417,15 @@ function untracked(fn) {
417
417
  var subscriberEpochCounter = 0;
418
418
  function retrack(effectFn, subscriber) {
419
419
  const prev = currentSubscriber;
420
+ let savedDepth = 0;
421
+ let savedSuspendSub = null;
422
+ if (trackingSuspended) {
423
+ savedDepth = suspendDepth;
424
+ savedSuspendSub = suspendSavedSub;
425
+ suspendDepth = 0;
426
+ suspendSavedSub = null;
427
+ trackingSuspended = false;
428
+ }
420
429
  currentSubscriber = subscriber;
421
430
  const sub = subscriber;
422
431
  const epoch = ++subscriberEpochCounter;
@@ -431,6 +440,11 @@ function retrack(effectFn, subscriber) {
431
440
  effectFn();
432
441
  } finally {
433
442
  currentSubscriber = prev;
443
+ if (savedDepth !== 0) {
444
+ suspendDepth = savedDepth;
445
+ suspendSavedSub = savedSuspendSub;
446
+ trackingSuspended = true;
447
+ }
434
448
  let node = sub.depsHead ?? null;
435
449
  while (node !== null) {
436
450
  const next = node.subNext;
@@ -450,11 +464,25 @@ function track(effectFn, subscriber) {
450
464
  if (!subscriber) return reactiveBinding(effectFn);
451
465
  cleanup(subscriber);
452
466
  const prev = currentSubscriber;
467
+ let savedDepth = 0;
468
+ let savedSuspendSub = null;
469
+ if (trackingSuspended) {
470
+ savedDepth = suspendDepth;
471
+ savedSuspendSub = suspendSavedSub;
472
+ suspendDepth = 0;
473
+ suspendSavedSub = null;
474
+ trackingSuspended = false;
475
+ }
453
476
  currentSubscriber = subscriber;
454
477
  try {
455
478
  effectFn();
456
479
  } finally {
457
480
  currentSubscriber = prev;
481
+ if (savedDepth !== 0) {
482
+ suspendDepth = savedDepth;
483
+ suspendSavedSub = savedSuspendSub;
484
+ trackingSuspended = true;
485
+ }
458
486
  const sub2 = subscriber;
459
487
  for (let n = sub2.depsHead ?? null; n !== null; n = n.subNext) {
460
488
  const sig = n.sig;
@@ -625,8 +653,9 @@ function propagateDirty(sub) {
625
653
  if (s._c) {
626
654
  const nSig = s._sig;
627
655
  if (nSig) {
628
- if (!nSig._d) {
656
+ if (!nSig._d || nSig._f === true) {
629
657
  nSig._d = true;
658
+ nSig._f = false;
630
659
  stack.push(nSig);
631
660
  }
632
661
  } else {
@@ -726,7 +755,7 @@ function forEachSubscriber(signal2, visit) {
726
755
  }
727
756
 
728
757
  // src/reactivity/track.ts
729
- var _runtimeVersion = true ? "4.4.0" : "dev";
758
+ var _runtimeVersion = true ? "4.5.0" : "dev";
730
759
  var REGISTRY_KEY = /* @__PURE__ */ Symbol.for("sibujs.reactive.v1");
731
760
  function resolveReactiveApi() {
732
761
  const g = globalThis;
@@ -790,10 +819,14 @@ function derived(getter, options) {
790
819
  const cs = {};
791
820
  cs._d = false;
792
821
  cs._init = false;
822
+ cs._f = false;
793
823
  cs._g = getter;
794
824
  cs.__v = 0;
825
+ let evaluating = false;
826
+ let disposed = false;
827
+ let pendingError;
795
828
  const markDirty = () => {
796
- if (cs._d) return;
829
+ if (cs._d || disposed) return;
797
830
  cs._d = true;
798
831
  };
799
832
  markDirty._c = 1;
@@ -816,33 +849,53 @@ function derived(getter, options) {
816
849
  }
817
850
  }, markDirty);
818
851
  const hook = globalThis.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
819
- let evaluating = false;
820
852
  const validate = () => {
821
- if (!cs._d) return;
853
+ if (!cs._d || disposed || pendingError !== void 0) return;
822
854
  const oldValue = cs._v;
823
855
  evaluating = true;
824
856
  try {
825
857
  retrack2(recompute, markDirty);
826
858
  if (!Object.is(oldValue, cs._v)) cs.__v++;
859
+ } catch (err) {
860
+ pendingError = { error: err };
861
+ cs.__v++;
862
+ if (disposed) cs._d = true;
863
+ else cs._f = true;
827
864
  } finally {
828
865
  evaluating = false;
866
+ if (disposed) cleanup2(markDirty);
829
867
  }
830
- if (hook && !Object.is(oldValue, cs._v)) {
868
+ if (hook && !disposed && !Object.is(oldValue, cs._v)) {
831
869
  hook.emit("computed:update", { signal: cs, oldValue, newValue: cs._v });
832
870
  }
833
871
  };
834
872
  cs._validate = validate;
873
+ const throwPending = () => {
874
+ const { error } = pendingError;
875
+ pendingError = void 0;
876
+ if (disposed) cs._d = false;
877
+ throw error;
878
+ };
835
879
  function computedGetter() {
836
880
  if (evaluating) {
837
881
  throw new Error(
838
882
  `[SibuJS] Circular dependency detected in derived${debugName ? ` "${debugName}"` : ""}. A derived signal cannot read itself (directly or through a chain).`
839
883
  );
840
884
  }
841
- if (isTrackingSuspended2()) {
842
- if (cs._d) validate();
885
+ if (isTrackingSuspended2() || disposed) {
886
+ if (cs._d) {
887
+ validate();
888
+ if (pendingError !== void 0) throwPending();
889
+ }
843
890
  return cs._v;
844
891
  }
845
- if (cs._d) validate();
892
+ if (cs._d) {
893
+ validate();
894
+ if (pendingError !== void 0) {
895
+ recordDependency2(cs);
896
+ throwPending();
897
+ }
898
+ }
846
899
  recordDependency2(cs);
847
900
  return cs._v;
848
901
  }
@@ -851,6 +904,19 @@ function derived(getter, options) {
851
904
  cs.__name = debugName;
852
905
  }
853
906
  computedGetter.__signal = cs;
907
+ computedGetter.dispose = () => {
908
+ if (disposed) return;
909
+ disposed = true;
910
+ cs._d = pendingError !== void 0;
911
+ cleanup2(markDirty);
912
+ const h = globalThis.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
913
+ if (h) {
914
+ try {
915
+ h.emit("computed:destroy", { signal: cs, getter: computedGetter });
916
+ } catch {
917
+ }
918
+ }
919
+ };
854
920
  if (hook) hook.emit("computed:create", { signal: cs, name: debugName, getter: computedGetter });
855
921
  return computedGetter;
856
922
  }
@@ -2488,6 +2554,14 @@ function setSafeAttribute(el, name, value, options = {}) {
2488
2554
  const html = isHtmlElement(el);
2489
2555
  const idlName = html ? name.toLowerCase() : name;
2490
2556
  if (typeof value === "boolean") {
2557
+ if (name.length > 5 && name.slice(0, 5).toLowerCase() === "aria-") {
2558
+ const token = value ? "true" : "false";
2559
+ if ((ns ? el.getAttributeNS(ns, localName) : el.getAttribute(name)) !== token) {
2560
+ if (ns) el.setAttributeNS(ns, name, token);
2561
+ else el.setAttribute(name, token);
2562
+ }
2563
+ return true;
2564
+ }
2491
2565
  if (html && BOOLEAN_IDL_ATTRS.has(idlName) && idlName in el) {
2492
2566
  setProp(el, idlName, value);
2493
2567
  } else if (value) {
@@ -2561,13 +2635,13 @@ function bindBoolAttr(el, attr, getter) {
2561
2635
  let value;
2562
2636
  try {
2563
2637
  value = reactiveGetter();
2564
- } catch {
2638
+ } catch (err) {
2639
+ reportError(err, { phase: "binding", name: "bindBoolAttr", node: el });
2565
2640
  return;
2566
2641
  }
2567
2642
  setSafeAttribute(el, attr, Boolean(value), { label: "bindBoolAttr" });
2568
2643
  }
2569
- const teardown = track2(commit);
2570
- return teardown;
2644
+ return reactiveBinding2(commit, el);
2571
2645
  }
2572
2646
  function bindData(el, key, getter) {
2573
2647
  const dataAttr = `data-${key}`;
@@ -2831,7 +2905,13 @@ function pagination(options) {
2831
2905
  const clamped = Math.max(1, Math.min(target, totalPages()));
2832
2906
  setPage(clamped);
2833
2907
  }
2834
- return { page: currentPage, pageSize, totalPages, next, prev, goTo, startIndex, endIndex };
2908
+ function dispose2() {
2909
+ startIndex.dispose();
2910
+ endIndex.dispose();
2911
+ currentPage.dispose();
2912
+ totalPages.dispose();
2913
+ }
2914
+ return { page: currentPage, pageSize, totalPages, next, prev, goTo, startIndex, endIndex, dispose: dispose2 };
2835
2915
  }
2836
2916
 
2837
2917
  // src/ui/eventBus.ts
package/dist/ui.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- export { A as AttributeSource, a as AttributeValue, B as BoundFieldProps, C as CustomElementOptions, F as FieldConfig, b as FocusTrap, c as FormConfig, d as FormField, e as FormReturn, I as IntersectionResult, M as MaskOptions, T as Toast, f as ToastInstance, V as ValidatorFn, g as VirtualList, h as VirtualListProps, _ as __resetDialogStack, i as announce, j as aria, k as bindAttrs, l as bindBoolAttr, m as bindData, n as bindField, o as creditCardMask, p as custom, q as dateMask, r as defineElement, s as dialog, t as email, u as eventBus, v as focus, w as form, x as hotkey, y as infiniteScroll, z as inputMask, D as intersection, E as lazyLoad, G as matchesPattern, H as max, J as maxLength, K as min, L as minLength, N as pagination, O as phoneMask, P as removeScopedStyle, Q as required, R as scopedStyle, S as ssnMask, U as svgElement, W as timeMask, X as toast, Y as withScopedStyle, Z as zipMask } from './customElement-CNZxEB9G.cjs';
1
+ export { A as AttributeSource, a as AttributeValue, B as BoundFieldProps, C as CustomElementOptions, F as FieldConfig, b as FocusTrap, c as FormConfig, d as FormField, e as FormReturn, I as IntersectionResult, M as MaskOptions, P as PaginationResult, T as Toast, f as ToastInstance, V as ValidatorFn, g as VirtualList, h as VirtualListProps, _ as __resetDialogStack, i as announce, j as aria, k as bindAttrs, l as bindBoolAttr, m as bindData, n as bindField, o as creditCardMask, p as custom, q as dateMask, r as defineElement, s as dialog, t as email, u as eventBus, v as focus, w as form, x as hotkey, y as infiniteScroll, z as inputMask, D as intersection, E as lazyLoad, G as matchesPattern, H as max, J as maxLength, K as min, L as minLength, N as pagination, O as phoneMask, Q as removeScopedStyle, R as required, S as scopedStyle, U as ssnMask, W as svgElement, X as timeMask, Y as toast, Z as withScopedStyle, $ as zipMask } from './customElement-OB9CIsc5.cjs';
2
2
  export { C as ComponentProps, P as PropDef, a as PropSchema, R as RenderProp, V as Validator, b as assertType, c as compose, d as createGuard, e as createSlots, f as defineComponent, g as defineSlottedComponent, h as defineStrictComponent, v as validateProps, i as validators, w as withBoundary, j as withDefaults, k as withProps, l as withWrapper } from './contracts-DBdg9J_a.cjs';
3
3
 
4
4
  interface FormActionHandle<TArgs extends unknown[], TResult> {
package/dist/ui.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { A as AttributeSource, a as AttributeValue, B as BoundFieldProps, C as CustomElementOptions, F as FieldConfig, b as FocusTrap, c as FormConfig, d as FormField, e as FormReturn, I as IntersectionResult, M as MaskOptions, T as Toast, f as ToastInstance, V as ValidatorFn, g as VirtualList, h as VirtualListProps, _ as __resetDialogStack, i as announce, j as aria, k as bindAttrs, l as bindBoolAttr, m as bindData, n as bindField, o as creditCardMask, p as custom, q as dateMask, r as defineElement, s as dialog, t as email, u as eventBus, v as focus, w as form, x as hotkey, y as infiniteScroll, z as inputMask, D as intersection, E as lazyLoad, G as matchesPattern, H as max, J as maxLength, K as min, L as minLength, N as pagination, O as phoneMask, P as removeScopedStyle, Q as required, R as scopedStyle, S as ssnMask, U as svgElement, W as timeMask, X as toast, Y as withScopedStyle, Z as zipMask } from './customElement-CNZxEB9G.js';
1
+ export { A as AttributeSource, a as AttributeValue, B as BoundFieldProps, C as CustomElementOptions, F as FieldConfig, b as FocusTrap, c as FormConfig, d as FormField, e as FormReturn, I as IntersectionResult, M as MaskOptions, P as PaginationResult, T as Toast, f as ToastInstance, V as ValidatorFn, g as VirtualList, h as VirtualListProps, _ as __resetDialogStack, i as announce, j as aria, k as bindAttrs, l as bindBoolAttr, m as bindData, n as bindField, o as creditCardMask, p as custom, q as dateMask, r as defineElement, s as dialog, t as email, u as eventBus, v as focus, w as form, x as hotkey, y as infiniteScroll, z as inputMask, D as intersection, E as lazyLoad, G as matchesPattern, H as max, J as maxLength, K as min, L as minLength, N as pagination, O as phoneMask, Q as removeScopedStyle, R as required, S as scopedStyle, U as ssnMask, W as svgElement, X as timeMask, Y as toast, Z as withScopedStyle, $ as zipMask } from './customElement-OB9CIsc5.js';
2
2
  export { C as ComponentProps, P as PropDef, a as PropSchema, R as RenderProp, V as Validator, b as assertType, c as compose, d as createGuard, e as createSlots, f as defineComponent, g as defineSlottedComponent, h as defineStrictComponent, v as validateProps, i as validators, w as withBoundary, j as withDefaults, k as withProps, l as withWrapper } from './contracts-DBdg9J_a.js';
3
3
 
4
4
  interface FormActionHandle<TArgs extends unknown[], TResult> {
package/dist/ui.js CHANGED
@@ -38,7 +38,7 @@ import {
38
38
  toast,
39
39
  withScopedStyle,
40
40
  zipMask
41
- } from "./chunk-XLO7SLIX.js";
41
+ } from "./chunk-2DCGACUU.js";
42
42
  import {
43
43
  RenderProp,
44
44
  assertType,
@@ -58,23 +58,23 @@ import {
58
58
  import {
59
59
  createId
60
60
  } from "./chunk-CCSJMTRN.js";
61
- import "./chunk-VCTAEPSB.js";
62
- import "./chunk-W2EQ7X2L.js";
61
+ import "./chunk-ONOHFDLG.js";
62
+ import "./chunk-RBTPLM32.js";
63
63
  import "./chunk-IXKSNWV5.js";
64
64
  import {
65
65
  globalSingleton
66
66
  } from "./chunk-7ZHH77QA.js";
67
67
  import {
68
68
  effect
69
- } from "./chunk-7GIHSAWB.js";
69
+ } from "./chunk-RIXRAYIU.js";
70
70
  import "./chunk-5DXA2J44.js";
71
71
  import {
72
72
  registerDisposer
73
73
  } from "./chunk-QKRPLZ2V.js";
74
74
  import {
75
75
  signal
76
- } from "./chunk-NVNJH22U.js";
77
- import "./chunk-3BTTCZ5J.js";
76
+ } from "./chunk-XZZOBQAY.js";
77
+ import "./chunk-UGRX3S57.js";
78
78
  import "./chunk-2WLZ6757.js";
79
79
 
80
80
  // src/ui/formAction.ts
package/dist/widgets.cjs CHANGED
@@ -291,6 +291,15 @@ function untracked(fn) {
291
291
  var subscriberEpochCounter = 0;
292
292
  function retrack(effectFn, subscriber) {
293
293
  const prev = currentSubscriber;
294
+ let savedDepth = 0;
295
+ let savedSuspendSub = null;
296
+ if (trackingSuspended) {
297
+ savedDepth = suspendDepth;
298
+ savedSuspendSub = suspendSavedSub;
299
+ suspendDepth = 0;
300
+ suspendSavedSub = null;
301
+ trackingSuspended = false;
302
+ }
294
303
  currentSubscriber = subscriber;
295
304
  const sub = subscriber;
296
305
  const epoch = ++subscriberEpochCounter;
@@ -305,6 +314,11 @@ function retrack(effectFn, subscriber) {
305
314
  effectFn();
306
315
  } finally {
307
316
  currentSubscriber = prev;
317
+ if (savedDepth !== 0) {
318
+ suspendDepth = savedDepth;
319
+ suspendSavedSub = savedSuspendSub;
320
+ trackingSuspended = true;
321
+ }
308
322
  let node = sub.depsHead ?? null;
309
323
  while (node !== null) {
310
324
  const next = node.subNext;
@@ -324,11 +338,25 @@ function track(effectFn, subscriber) {
324
338
  if (!subscriber) return reactiveBinding(effectFn);
325
339
  cleanup(subscriber);
326
340
  const prev = currentSubscriber;
341
+ let savedDepth = 0;
342
+ let savedSuspendSub = null;
343
+ if (trackingSuspended) {
344
+ savedDepth = suspendDepth;
345
+ savedSuspendSub = suspendSavedSub;
346
+ suspendDepth = 0;
347
+ suspendSavedSub = null;
348
+ trackingSuspended = false;
349
+ }
327
350
  currentSubscriber = subscriber;
328
351
  try {
329
352
  effectFn();
330
353
  } finally {
331
354
  currentSubscriber = prev;
355
+ if (savedDepth !== 0) {
356
+ suspendDepth = savedDepth;
357
+ suspendSavedSub = savedSuspendSub;
358
+ trackingSuspended = true;
359
+ }
332
360
  const sub2 = subscriber;
333
361
  for (let n = sub2.depsHead ?? null; n !== null; n = n.subNext) {
334
362
  const sig = n.sig;
@@ -499,8 +527,9 @@ function propagateDirty(sub) {
499
527
  if (s._c) {
500
528
  const nSig = s._sig;
501
529
  if (nSig) {
502
- if (!nSig._d) {
530
+ if (!nSig._d || nSig._f === true) {
503
531
  nSig._d = true;
532
+ nSig._f = false;
504
533
  stack.push(nSig);
505
534
  }
506
535
  } else {
@@ -600,7 +629,7 @@ function forEachSubscriber(signal2, visit) {
600
629
  }
601
630
 
602
631
  // src/reactivity/track.ts
603
- var _runtimeVersion = true ? "4.4.0" : "dev";
632
+ var _runtimeVersion = true ? "4.5.0" : "dev";
604
633
  var REGISTRY_KEY = /* @__PURE__ */ Symbol.for("sibujs.reactive.v1");
605
634
  function resolveReactiveApi() {
606
635
  const g = globalThis;
@@ -664,10 +693,14 @@ function derived(getter, options) {
664
693
  const cs = {};
665
694
  cs._d = false;
666
695
  cs._init = false;
696
+ cs._f = false;
667
697
  cs._g = getter;
668
698
  cs.__v = 0;
699
+ let evaluating = false;
700
+ let disposed = false;
701
+ let pendingError;
669
702
  const markDirty = () => {
670
- if (cs._d) return;
703
+ if (cs._d || disposed) return;
671
704
  cs._d = true;
672
705
  };
673
706
  markDirty._c = 1;
@@ -690,33 +723,53 @@ function derived(getter, options) {
690
723
  }
691
724
  }, markDirty);
692
725
  const hook = globalThis.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
693
- let evaluating = false;
694
726
  const validate = () => {
695
- if (!cs._d) return;
727
+ if (!cs._d || disposed || pendingError !== void 0) return;
696
728
  const oldValue = cs._v;
697
729
  evaluating = true;
698
730
  try {
699
731
  retrack2(recompute, markDirty);
700
732
  if (!Object.is(oldValue, cs._v)) cs.__v++;
733
+ } catch (err) {
734
+ pendingError = { error: err };
735
+ cs.__v++;
736
+ if (disposed) cs._d = true;
737
+ else cs._f = true;
701
738
  } finally {
702
739
  evaluating = false;
740
+ if (disposed) cleanup2(markDirty);
703
741
  }
704
- if (hook && !Object.is(oldValue, cs._v)) {
742
+ if (hook && !disposed && !Object.is(oldValue, cs._v)) {
705
743
  hook.emit("computed:update", { signal: cs, oldValue, newValue: cs._v });
706
744
  }
707
745
  };
708
746
  cs._validate = validate;
747
+ const throwPending = () => {
748
+ const { error } = pendingError;
749
+ pendingError = void 0;
750
+ if (disposed) cs._d = false;
751
+ throw error;
752
+ };
709
753
  function computedGetter() {
710
754
  if (evaluating) {
711
755
  throw new Error(
712
756
  `[SibuJS] Circular dependency detected in derived${debugName ? ` "${debugName}"` : ""}. A derived signal cannot read itself (directly or through a chain).`
713
757
  );
714
758
  }
715
- if (isTrackingSuspended2()) {
716
- if (cs._d) validate();
759
+ if (isTrackingSuspended2() || disposed) {
760
+ if (cs._d) {
761
+ validate();
762
+ if (pendingError !== void 0) throwPending();
763
+ }
717
764
  return cs._v;
718
765
  }
719
- if (cs._d) validate();
766
+ if (cs._d) {
767
+ validate();
768
+ if (pendingError !== void 0) {
769
+ recordDependency2(cs);
770
+ throwPending();
771
+ }
772
+ }
720
773
  recordDependency2(cs);
721
774
  return cs._v;
722
775
  }
@@ -725,6 +778,19 @@ function derived(getter, options) {
725
778
  cs.__name = debugName;
726
779
  }
727
780
  computedGetter.__signal = cs;
781
+ computedGetter.dispose = () => {
782
+ if (disposed) return;
783
+ disposed = true;
784
+ cs._d = pendingError !== void 0;
785
+ cleanup2(markDirty);
786
+ const h = globalThis.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
787
+ if (h) {
788
+ try {
789
+ h.emit("computed:destroy", { signal: cs, getter: computedGetter });
790
+ } catch {
791
+ }
792
+ }
793
+ };
728
794
  if (hook) hook.emit("computed:create", { signal: cs, name: debugName, getter: computedGetter });
729
795
  return computedGetter;
730
796
  }
package/dist/widgets.js CHANGED
@@ -8,15 +8,15 @@ import {
8
8
  select,
9
9
  tabs,
10
10
  tooltip
11
- } from "./chunk-HFCOH2GN.js";
12
- import "./chunk-RR7M3FHM.js";
11
+ } from "./chunk-GW3SCCZG.js";
12
+ import "./chunk-7LN645I6.js";
13
13
  import "./chunk-CCSJMTRN.js";
14
- import "./chunk-W2EQ7X2L.js";
14
+ import "./chunk-RBTPLM32.js";
15
15
  import "./chunk-IXKSNWV5.js";
16
- import "./chunk-7GIHSAWB.js";
16
+ import "./chunk-RIXRAYIU.js";
17
17
  import "./chunk-5DXA2J44.js";
18
- import "./chunk-NVNJH22U.js";
19
- import "./chunk-3BTTCZ5J.js";
18
+ import "./chunk-XZZOBQAY.js";
19
+ import "./chunk-UGRX3S57.js";
20
20
  import "./chunk-2WLZ6757.js";
21
21
  export {
22
22
  accordion,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "sibujs",
3
- "version": "4.4.0",
4
- "description": "A lightweight, function-based frontend framework that combines the best of React, Svelte, and Vue — with zero VDOM and maximum simplicity. Designed for developers who want fine-grained reactivity and full control without compilation or magic.",
3
+ "version": "4.5.0",
4
+ "description": "A function-based frontend framework with fine-grained reactivity and no virtual DOM. Tag factories return live DOM nodes you can hold and mutate, signals update only what changed, and nothing needs a compiler — it runs from a script tag or a bundler.",
5
5
  "keywords": [
6
6
  "frontend",
7
7
  "framework",
@@ -1,55 +0,0 @@
1
- /**
2
- * Canonical disposer/teardown signature used across the framework.
3
- *
4
- * Returned by `effect()`, `track()`, widget `bind()` methods, and other
5
- * subscription/lifecycle helpers. All disposers MUST be idempotent — calling
6
- * twice should be a no-op rather than an error.
7
- */
8
- type Dispose = () => void;
9
- type NodeChild = Node | Element | Text | Comment | string | number | boolean | (() => NodeChild) | null | undefined;
10
- type NodeChildren = NodeChild | NodeChild[] | NodeChild[][] | (() => NodeChild | NodeChild[]);
11
-
12
- declare const SVG_NS = "http://www.w3.org/2000/svg";
13
- interface TagProps {
14
- id?: string;
15
- class?: string | (() => string) | Record<string, boolean | (() => boolean)>;
16
- style?: Record<string, string | number | (() => string | number)> | string | (() => string);
17
- ref?: {
18
- current: Element | null;
19
- };
20
- nodes?: NodeChildren;
21
- on?: Record<string, (ev: Event) => void>;
22
- /** Called with the element after creation — useful for imperative bindings */
23
- onElement?: (el: HTMLElement) => void;
24
- [attr: string]: unknown;
25
- }
26
- /**
27
- * Factory for creating HTML or SVG elements with reactive props and nodes.
28
- *
29
- * Calling conventions:
30
- *
31
- * tag() empty element
32
- * tag("text") element with text content
33
- * tag(42) element with numeric text content
34
- * tag([childA, childB]) element with children (array)
35
- * tag(node) element wrapping a single existing node
36
- * tag(getter) element with a reactive child
37
- * tag("className", children) positional: class + children
38
- * tag({ ...props }) full props object (children via props.nodes)
39
- * tag({ ...props }, children) props + children (no need for `nodes:` key!)
40
- *
41
- * The last form is the "deeply-nested shorthand" the codebase favours:
42
- *
43
- * div({ class: "card" }, [
44
- * h1({ class: "title" }, "Hello"),
45
- * p({ class: "body" }, "World"),
46
- * div({ class: "row" }, [
47
- * span({ id: "x" }, "child"),
48
- * ]),
49
- * ])
50
- *
51
- * `children` overrides `props.nodes` when both are present.
52
- */
53
- declare const tagFactory: (tag: string, ns?: string) => (first?: TagProps | NodeChildren, second?: NodeChildren) => Element;
54
-
55
- export { type Dispose as D, type NodeChild as N, SVG_NS as S, type TagProps as T, type NodeChildren as a, tagFactory as t };
@@ -1,55 +0,0 @@
1
- /**
2
- * Canonical disposer/teardown signature used across the framework.
3
- *
4
- * Returned by `effect()`, `track()`, widget `bind()` methods, and other
5
- * subscription/lifecycle helpers. All disposers MUST be idempotent — calling
6
- * twice should be a no-op rather than an error.
7
- */
8
- type Dispose = () => void;
9
- type NodeChild = Node | Element | Text | Comment | string | number | boolean | (() => NodeChild) | null | undefined;
10
- type NodeChildren = NodeChild | NodeChild[] | NodeChild[][] | (() => NodeChild | NodeChild[]);
11
-
12
- declare const SVG_NS = "http://www.w3.org/2000/svg";
13
- interface TagProps {
14
- id?: string;
15
- class?: string | (() => string) | Record<string, boolean | (() => boolean)>;
16
- style?: Record<string, string | number | (() => string | number)> | string | (() => string);
17
- ref?: {
18
- current: Element | null;
19
- };
20
- nodes?: NodeChildren;
21
- on?: Record<string, (ev: Event) => void>;
22
- /** Called with the element after creation — useful for imperative bindings */
23
- onElement?: (el: HTMLElement) => void;
24
- [attr: string]: unknown;
25
- }
26
- /**
27
- * Factory for creating HTML or SVG elements with reactive props and nodes.
28
- *
29
- * Calling conventions:
30
- *
31
- * tag() empty element
32
- * tag("text") element with text content
33
- * tag(42) element with numeric text content
34
- * tag([childA, childB]) element with children (array)
35
- * tag(node) element wrapping a single existing node
36
- * tag(getter) element with a reactive child
37
- * tag("className", children) positional: class + children
38
- * tag({ ...props }) full props object (children via props.nodes)
39
- * tag({ ...props }, children) props + children (no need for `nodes:` key!)
40
- *
41
- * The last form is the "deeply-nested shorthand" the codebase favours:
42
- *
43
- * div({ class: "card" }, [
44
- * h1({ class: "title" }, "Hello"),
45
- * p({ class: "body" }, "World"),
46
- * div({ class: "row" }, [
47
- * span({ id: "x" }, "child"),
48
- * ]),
49
- * ])
50
- *
51
- * `children` overrides `props.nodes` when both are present.
52
- */
53
- declare const tagFactory: (tag: string, ns?: string) => (first?: TagProps | NodeChildren, second?: NodeChildren) => Element;
54
-
55
- export { type Dispose as D, type NodeChild as N, SVG_NS as S, type TagProps as T, type NodeChildren as a, tagFactory as t };