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
package/dist/patterns.cjs CHANGED
@@ -147,6 +147,25 @@ function reportError(error, context) {
147
147
  });
148
148
  }
149
149
 
150
+ // src/core/rendering/dispose.ts
151
+ function resolveCapture(capture) {
152
+ let frame = capture;
153
+ while (frame?.closed) frame = frame.forwardTo;
154
+ return frame ?? null;
155
+ }
156
+ var registrationCaptures = [];
157
+ function currentDisposerCapture() {
158
+ return resolveCapture(registrationCaptures[registrationCaptures.length - 1]);
159
+ }
160
+ function beginDisposerCapture(capture) {
161
+ if (capture === null && registrationCaptures.length === 0) return false;
162
+ registrationCaptures.push(resolveCapture(capture));
163
+ return true;
164
+ }
165
+ function endDisposerCapture() {
166
+ registrationCaptures.pop();
167
+ }
168
+
150
169
  // src/reactivity/track-core.ts
151
170
  var POOL_MAX = 4096;
152
171
  var nodePool = [];
@@ -305,6 +324,7 @@ function retrack(effectFn, subscriber) {
305
324
  }
306
325
  currentSubscriber = subscriber;
307
326
  const sub = subscriber;
327
+ if (sub._cap === void 0) sub._cap = currentDisposerCapture();
308
328
  const epoch = ++subscriberEpochCounter;
309
329
  sub._epoch = epoch;
310
330
  sub._structDirty = false;
@@ -496,7 +516,12 @@ function drainQueue() {
496
516
  quarantined.add(sub);
497
517
  continue;
498
518
  }
499
- safeInvoke(sub);
519
+ const pushed = beginDisposerCapture(sub._cap ?? null);
520
+ try {
521
+ safeInvoke(sub);
522
+ } finally {
523
+ if (pushed) endDisposerCapture();
524
+ }
500
525
  }
501
526
  }
502
527
  function drainNotificationQueue() {
@@ -632,7 +657,7 @@ function forEachSubscriber(signal2, visit) {
632
657
  }
633
658
 
634
659
  // src/reactivity/track.ts
635
- var _runtimeVersion = true ? "4.5.0" : "dev";
660
+ var _runtimeVersion = true ? "4.7.0" : "dev";
636
661
  var REGISTRY_KEY = /* @__PURE__ */ Symbol.for("sibujs.reactive.v1");
637
662
  function resolveReactiveApi() {
638
663
  const g = globalThis;
@@ -738,6 +763,14 @@ var batch = API2.batch;
738
763
  var enqueueBatchedSignal = API2.enqueueBatchedSignal;
739
764
  var isBatching = API2.isBatching;
740
765
 
766
+ // src/core/devtoolsHook.ts
767
+ function emitDevtools(hook, event, payload) {
768
+ try {
769
+ hook.emit(event, payload);
770
+ } catch {
771
+ }
772
+ }
773
+
741
774
  // src/core/signals/signal.ts
742
775
  var _g = globalThis;
743
776
  function signal(initial, options) {
@@ -771,7 +804,7 @@ function signal(initial, options) {
771
804
  state2.__v++;
772
805
  if (DEV) {
773
806
  const hook = _g.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
774
- if (hook) hook.emit("signal:update", { signal: state2, name: debugName, oldValue: prev, newValue });
807
+ if (hook) emitDevtools(hook, "signal:update", { signal: state2, name: debugName, oldValue: prev, newValue });
775
808
  }
776
809
  if (!enqueueBatchedSignal(state2)) {
777
810
  notifySubscribers2(state2);
@@ -785,7 +818,7 @@ function signal(initial, options) {
785
818
  state2.value = newValue;
786
819
  state2.__v++;
787
820
  const hook = _g.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
788
- if (hook) hook.emit("signal:update", { signal: state2, name: debugName, oldValue: prev, newValue });
821
+ if (hook) emitDevtools(hook, "signal:update", { signal: state2, name: debugName, oldValue: prev, newValue });
789
822
  if (!enqueueBatchedSignal(state2)) {
790
823
  notifySubscribers2(state2);
791
824
  }
@@ -804,7 +837,7 @@ function signal(initial, options) {
804
837
  }
805
838
  if (DEV) {
806
839
  const hook = _g.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
807
- if (hook) hook.emit("signal:create", { signal: state2, name: debugName, getter: get, initial });
840
+ if (hook) emitDevtools(hook, "signal:create", { signal: state2, name: debugName, getter: get, initial });
808
841
  }
809
842
  return [get, set];
810
843
  }
@@ -826,12 +859,24 @@ function stripUnsafeKeys(obj) {
826
859
  function machine(config) {
827
860
  const [state2, setState] = signal(config.initial);
828
861
  const [context, setContext] = signal(config.context || {});
829
- const initialDef = config.states[config.initial];
830
- if (initialDef?.entry) {
831
- initialDef.entry(context());
862
+ let currentState = config.initial;
863
+ let currentContext = context();
864
+ const queue = [];
865
+ let processing = false;
866
+ function drain() {
867
+ processing = true;
868
+ try {
869
+ while (queue.length > 0) {
870
+ step(queue.shift());
871
+ }
872
+ } catch (err) {
873
+ queue.length = 0;
874
+ throw err;
875
+ } finally {
876
+ processing = false;
877
+ }
832
878
  }
833
- function send(event) {
834
- const currentState = state2();
879
+ function step(event) {
835
880
  const stateDef = config.states[currentState];
836
881
  if (!stateDef?.on) return;
837
882
  const transition = stateDef.on[event];
@@ -846,28 +891,51 @@ function machine(config) {
846
891
  guard = transition.guard;
847
892
  action = transition.action;
848
893
  }
849
- const ctx = context();
894
+ const ctx = currentContext;
850
895
  if (guard && !guard(ctx)) return;
851
896
  if (stateDef.exit) {
852
897
  stateDef.exit(ctx);
853
898
  }
899
+ let nextContext = ctx;
854
900
  if (action) {
855
901
  const rawPatch = action(ctx);
856
- const next = { ...ctx, ...stripUnsafeKeys(rawPatch) };
857
- setContext(next);
902
+ nextContext = { ...ctx, ...stripUnsafeKeys(rawPatch) };
858
903
  }
859
- setState(target);
904
+ currentState = target;
905
+ currentContext = nextContext;
906
+ batch(() => {
907
+ if (action) setContext(nextContext);
908
+ setState(target);
909
+ });
860
910
  const targetDef = config.states[target];
861
911
  if (targetDef?.entry) {
862
- targetDef.entry(context());
912
+ targetDef.entry(currentContext);
913
+ }
914
+ }
915
+ function send(event) {
916
+ queue.push(event);
917
+ if (processing) return;
918
+ drain();
919
+ }
920
+ const initialDef = config.states[config.initial];
921
+ if (initialDef?.entry) {
922
+ processing = true;
923
+ try {
924
+ initialDef.entry(currentContext);
925
+ } catch (err) {
926
+ queue.length = 0;
927
+ throw err;
928
+ } finally {
929
+ processing = false;
863
930
  }
931
+ if (queue.length > 0) drain();
864
932
  }
865
933
  function matches(s) {
866
934
  return state2() === s;
867
935
  }
868
936
  function can(event) {
869
- const currentState = state2();
870
- const stateDef = config.states[currentState];
937
+ const currentState2 = state2();
938
+ const stateDef = config.states[currentState2];
871
939
  if (!stateDef?.on) return false;
872
940
  const transition = stateDef.on[event];
873
941
  if (!transition) return false;
@@ -1034,12 +1102,17 @@ function effect(effectFn, options) {
1034
1102
  try {
1035
1103
  retrack2(ctx.bodyFn, ctx.subscriber);
1036
1104
  if (ctx.rerunPending) drainReruns(ctx);
1105
+ } catch (err) {
1106
+ ctx.disposed = true;
1107
+ if (ctx.userCleanups.length > 0) flushUserCleanups(ctx);
1108
+ cleanup2(ctx.subscriber);
1109
+ throw err;
1037
1110
  } finally {
1038
1111
  ctx.running = false;
1039
1112
  ctx.rerunPending = false;
1040
1113
  }
1041
1114
  const hook = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
1042
- if (hook) hook.emit("effect:create", { effectFn });
1115
+ if (hook) emitDevtools(hook, "effect:create", { effectFn });
1043
1116
  return () => disposeEffect(ctx);
1044
1117
  }
1045
1118
 
@@ -1437,17 +1510,17 @@ function derived(getter, options) {
1437
1510
  cs._d = false;
1438
1511
  cs._init = true;
1439
1512
  };
1440
- track2(() => {
1441
- let threw = true;
1442
- try {
1513
+ try {
1514
+ track2(() => {
1443
1515
  cs._v = getter();
1444
1516
  cs._d = false;
1445
1517
  cs._init = true;
1446
- threw = false;
1447
- } finally {
1448
- if (threw) cs._d = true;
1449
- }
1450
- }, markDirty);
1518
+ }, markDirty);
1519
+ } catch (err) {
1520
+ disposed = true;
1521
+ cleanup2(markDirty);
1522
+ throw err;
1523
+ }
1451
1524
  const hook = globalThis.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
1452
1525
  const validate = () => {
1453
1526
  if (!cs._d || disposed || pendingError !== void 0) return;
@@ -1466,7 +1539,7 @@ function derived(getter, options) {
1466
1539
  if (disposed) cleanup2(markDirty);
1467
1540
  }
1468
1541
  if (hook && !disposed && !Object.is(oldValue, cs._v)) {
1469
- hook.emit("computed:update", { signal: cs, oldValue, newValue: cs._v });
1542
+ emitDevtools(hook, "computed:update", { signal: cs, oldValue, newValue: cs._v });
1470
1543
  }
1471
1544
  };
1472
1545
  cs._validate = validate;
@@ -1517,12 +1590,15 @@ function derived(getter, options) {
1517
1590
  }
1518
1591
  }
1519
1592
  };
1520
- if (hook) hook.emit("computed:create", { signal: cs, name: debugName, getter: computedGetter });
1593
+ if (hook) emitDevtools(hook, "computed:create", { signal: cs, name: debugName, getter: computedGetter });
1521
1594
  return computedGetter;
1522
1595
  }
1523
1596
 
1524
1597
  // src/patterns/timeTravel.ts
1525
1598
  function timeline(initial, maxHistory = 100) {
1599
+ if (!Number.isSafeInteger(maxHistory) || maxHistory < 1) {
1600
+ throw new RangeError(`[timeline] maxHistory must be a positive safe integer, got ${maxHistory}`);
1601
+ }
1526
1602
  const [history, setHistory] = signal([initial]);
1527
1603
  const [index, setIndex] = signal(0);
1528
1604
  const value = derived(() => history()[index()]);
@@ -1577,6 +1653,120 @@ function timeline(initial, maxHistory = 100) {
1577
1653
  return { value, set, undo, redo, canUndo, canRedo, history, index, reset, jumpTo, dispose };
1578
1654
  }
1579
1655
 
1656
+ // src/utils/adoption.ts
1657
+ var nativeThen = Promise.prototype.then;
1658
+ function probeNative(target, onRejected, onOpen) {
1659
+ let decided = false;
1660
+ const decide = (rejected) => {
1661
+ if (decided) return;
1662
+ decided = true;
1663
+ (rejected ? onRejected : onOpen)();
1664
+ };
1665
+ try {
1666
+ Reflect.apply(nativeThen, target, [void 0, () => decide(true)]);
1667
+ } catch {
1668
+ queueMicrotask(() => decide(true));
1669
+ return;
1670
+ }
1671
+ queueMicrotask(() => decide(false));
1672
+ }
1673
+ function adopt(value) {
1674
+ if (value === null || typeof value !== "object" && typeof value !== "function") return null;
1675
+ let then;
1676
+ try {
1677
+ then = value.then;
1678
+ } catch (error) {
1679
+ return {
1680
+ promise: Promise.reject(error),
1681
+ failedEarly: true,
1682
+ probe: (onRejected) => queueMicrotask(onRejected)
1683
+ };
1684
+ }
1685
+ if (typeof then !== "function") return null;
1686
+ let resolvePromise;
1687
+ let rejectPromise;
1688
+ const promise = new Promise((resolve, reject) => {
1689
+ resolvePromise = resolve;
1690
+ rejectPromise = reject;
1691
+ });
1692
+ let state2 = "invoking";
1693
+ let nativeTarget;
1694
+ const waiters = [];
1695
+ const transition = (next) => {
1696
+ state2 = next;
1697
+ if (next === "invoking") return;
1698
+ for (const waiter of waiters.splice(0)) waiter();
1699
+ };
1700
+ const fulfil = (result) => {
1701
+ resolvePromise(result);
1702
+ transition("fulfilled");
1703
+ };
1704
+ const fail = (error) => {
1705
+ rejectPromise(error);
1706
+ transition("rejected");
1707
+ };
1708
+ const follow = (result) => {
1709
+ if (result === promise) {
1710
+ fail(new TypeError("adopt: a thenable resolved to its own adoption"));
1711
+ return;
1712
+ }
1713
+ if (result === null || typeof result !== "object" && typeof result !== "function") {
1714
+ fulfil(result);
1715
+ return;
1716
+ }
1717
+ let nextThen;
1718
+ try {
1719
+ nextThen = result.then;
1720
+ } catch (error) {
1721
+ fail(error);
1722
+ return;
1723
+ }
1724
+ if (typeof nextThen !== "function") {
1725
+ fulfil(result);
1726
+ return;
1727
+ }
1728
+ invokeLater(result, nextThen);
1729
+ };
1730
+ const invokeLater = (target, targetThen) => {
1731
+ if (targetThen === nativeThen) {
1732
+ nativeTarget = target;
1733
+ transition("native");
1734
+ } else {
1735
+ transition("invoking");
1736
+ }
1737
+ queueMicrotask(() => {
1738
+ let done = false;
1739
+ const onResolve = (result) => {
1740
+ if (done) return;
1741
+ done = true;
1742
+ follow(result);
1743
+ };
1744
+ const onReject = (error) => {
1745
+ if (done) return;
1746
+ done = true;
1747
+ fail(error);
1748
+ };
1749
+ try {
1750
+ Reflect.apply(targetThen, target, [onResolve, onReject]);
1751
+ } catch (error) {
1752
+ onReject(error);
1753
+ }
1754
+ if (!done && state2 === "invoking") transition("pending");
1755
+ });
1756
+ };
1757
+ invokeLater(value, then);
1758
+ const probe = (onRejected, onOpen) => {
1759
+ const decide = () => {
1760
+ if (state2 === "native") probeNative(nativeTarget, onRejected, onOpen);
1761
+ else (state2 === "rejected" ? onRejected : onOpen)();
1762
+ };
1763
+ if (state2 === "native") probeNative(nativeTarget, onRejected, onOpen);
1764
+ else if (state2 === "invoking") waiters.push(decide);
1765
+ else queueMicrotask(state2 === "rejected" ? onRejected : onOpen);
1766
+ };
1767
+ return { promise, failedEarly: false, probe };
1768
+ }
1769
+
1580
1770
  // src/patterns/globalStore.ts
1581
1771
  function deepClone(value) {
1582
1772
  if (typeof structuredClone === "function") {
@@ -1611,8 +1801,51 @@ function deepClone(value) {
1611
1801
  function globalStore(config) {
1612
1802
  const initialState = deepClone(config.state);
1613
1803
  const [getState, setState] = signal({ ...initialState });
1614
- const listeners = /* @__PURE__ */ new Set();
1804
+ const subscriptions = /* @__PURE__ */ new Map();
1615
1805
  const middlewares = config.middleware || [];
1806
+ function notifyListeners(state2) {
1807
+ if (subscriptions.size === 0) return;
1808
+ for (const subscription of Array.from(subscriptions.values())) {
1809
+ if (!subscription.active) continue;
1810
+ try {
1811
+ subscription.callback(state2);
1812
+ } catch (err) {
1813
+ reportError(err, { phase: "event", name: "globalStore(subscribe)" });
1814
+ }
1815
+ }
1816
+ }
1817
+ const operations = [];
1818
+ let running = false;
1819
+ function perform(operation, rethrowOwn = true) {
1820
+ operations.push(operation);
1821
+ if (running) return;
1822
+ running = true;
1823
+ let callerError;
1824
+ let callerFailed = false;
1825
+ try {
1826
+ let first = true;
1827
+ let cursor = 0;
1828
+ while (cursor < operations.length) {
1829
+ const next = operations[cursor];
1830
+ operations[cursor++] = void 0;
1831
+ try {
1832
+ next();
1833
+ } catch (err) {
1834
+ if (first && rethrowOwn) {
1835
+ callerFailed = true;
1836
+ callerError = err;
1837
+ } else {
1838
+ reportError(err, { phase: "event", name: "globalStore(dispatch)" });
1839
+ }
1840
+ }
1841
+ first = false;
1842
+ }
1843
+ } finally {
1844
+ operations.length = 0;
1845
+ running = false;
1846
+ }
1847
+ if (callerFailed) throw callerError;
1848
+ }
1616
1849
  function dispatch(action, payload) {
1617
1850
  const actionFn = config.actions[action];
1618
1851
  if (!actionFn) throw new Error(`Unknown action: ${String(action)}`);
@@ -1621,38 +1854,96 @@ function globalStore(config) {
1621
1854
  const rawPatch = actionFn(current, payload);
1622
1855
  const patch = stripUnsafeKeys(rawPatch);
1623
1856
  setState({ ...current, ...patch });
1624
- const newState = getState();
1625
- for (const listener of listeners) {
1626
- listener(newState);
1627
- }
1857
+ notifyListeners(getState());
1628
1858
  };
1629
- if (middlewares.length === 0) {
1630
- execute();
1631
- return;
1632
- }
1633
- let index = 0;
1634
- const next = () => {
1635
- if (index < middlewares.length) {
1636
- const mw = middlewares[index++];
1637
- mw(getState(), String(action), payload, next);
1638
- } else {
1859
+ perform(() => {
1860
+ if (middlewares.length === 0) {
1639
1861
  execute();
1862
+ return;
1640
1863
  }
1641
- };
1642
- next();
1864
+ const runFrom = (index) => {
1865
+ if (index >= middlewares.length) {
1866
+ execute();
1867
+ return;
1868
+ }
1869
+ let called = false;
1870
+ let failed = false;
1871
+ let synchronous = true;
1872
+ const next = () => {
1873
+ if (failed && !called) {
1874
+ if (DEV)
1875
+ devWarn(
1876
+ `globalStore: middleware ${index} next() called after it failed for "${String(action)}"; ignored.`
1877
+ );
1878
+ called = true;
1879
+ return;
1880
+ }
1881
+ if (called) {
1882
+ if (DEV)
1883
+ devWarn(
1884
+ `globalStore: middleware ${index} next() called more than once for "${String(action)}"; ignored.`
1885
+ );
1886
+ return;
1887
+ }
1888
+ called = true;
1889
+ if (synchronous) {
1890
+ runFrom(index + 1);
1891
+ return;
1892
+ }
1893
+ const proceed = () => perform(() => runFrom(index + 1), false);
1894
+ if (!adoption) {
1895
+ proceed();
1896
+ return;
1897
+ }
1898
+ adoption.probe(() => {
1899
+ failed = true;
1900
+ if (DEV)
1901
+ devWarn(
1902
+ `globalStore: middleware ${index} next() called after it failed for "${String(action)}"; ignored.`
1903
+ );
1904
+ }, proceed);
1905
+ };
1906
+ let adoption = null;
1907
+ try {
1908
+ adoption = adopt(middlewares[index](getState(), String(action), payload, next));
1909
+ } catch (err) {
1910
+ failed = true;
1911
+ throw err;
1912
+ } finally {
1913
+ synchronous = false;
1914
+ }
1915
+ if (adoption) {
1916
+ if (adoption.failedEarly) failed = true;
1917
+ adoption.promise.then(void 0, (err) => {
1918
+ failed = true;
1919
+ reportError(err, { phase: "async", name: "globalStore(middleware)" });
1920
+ });
1921
+ }
1922
+ };
1923
+ runFrom(0);
1924
+ });
1643
1925
  }
1644
1926
  function select(selector) {
1645
1927
  return () => selector(getState());
1646
1928
  }
1647
1929
  function subscribe(callback) {
1648
- listeners.add(callback);
1649
- return () => listeners.delete(callback);
1930
+ let subscription = subscriptions.get(callback);
1931
+ if (!subscription) {
1932
+ subscription = { callback, active: true };
1933
+ subscriptions.set(callback, subscription);
1934
+ }
1935
+ const own = subscription;
1936
+ return () => {
1937
+ if (subscriptions.get(callback) !== own) return;
1938
+ own.active = false;
1939
+ subscriptions.delete(callback);
1940
+ };
1650
1941
  }
1651
1942
  function reset() {
1652
- setState({ ...initialState });
1653
- for (const listener of listeners) {
1654
- listener(getState());
1655
- }
1943
+ perform(() => {
1944
+ setState({ ...initialState });
1945
+ notifyListeners(getState());
1946
+ });
1656
1947
  }
1657
1948
  return { getState, select, dispatch, subscribe, reset };
1658
1949
  }
@@ -1776,7 +2067,7 @@ function validateProps(props, schema) {
1776
2067
  const errors = [];
1777
2068
  for (const [key, def] of Object.entries(schema)) {
1778
2069
  const propDef = typeof def === "function" ? { type: def } : def;
1779
- if (result[key] == null && propDef.default !== void 0) {
2070
+ if (result[key] === void 0 && propDef.default !== void 0) {
1780
2071
  result[key] = typeof propDef.default === "function" ? propDef.default() : propDef.default;
1781
2072
  }
1782
2073
  if (propDef.required && result[key] == null) {
@@ -1802,7 +2093,7 @@ ${errors.map((e) => ` - ${e}`).join("\n")}`);
1802
2093
  for (const [key, def] of Object.entries(schema)) {
1803
2094
  if (typeof def === "function") continue;
1804
2095
  const fallback = def.default;
1805
- if (result[key] == null && fallback !== void 0) {
2096
+ if (result[key] === void 0 && fallback !== void 0) {
1806
2097
  result[key] = typeof fallback === "function" ? fallback() : fallback;
1807
2098
  }
1808
2099
  }
@@ -1,4 +1,5 @@
1
- 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';
1
+ export { C as ComponentProps, P as PropDef, a as PropSchema, R as RenderProp, V as Validator, W as WithDefaultsProps, 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-CTOJXu-x.cjs';
2
+ import './types-CJFViL6Q.cjs';
2
3
 
3
4
  interface MachineConfig<S extends string, E extends string, C extends object = Record<string, unknown>> {
4
5
  initial: S;
@@ -36,10 +37,10 @@ declare function machine<S extends string, E extends string, C extends object =
36
37
  * @param key Storage key
37
38
  * @param initial Default value when no persisted value exists
38
39
  * @param options Storage options
39
- * @returns The same `[getter, setter]` tuple as `signal()`. For localStorage
40
- * (cross-tab sync on), the setter additionally carries a non-enumerable
41
- * `dispose()` method — call `setter.dispose()` on unmount to remove the
42
- * `storage` event listener; otherwise it lives for the page's lifetime.
40
+ * @returns The same `[getter, setter]` tuple as `signal()`. The setter also
41
+ * carries a non-enumerable `dispose()` method — call `setter.dispose()` on
42
+ * unmount to stop persisting and remove the cross-tab `storage` listener;
43
+ * otherwise both live for the page's lifetime.
43
44
  *
44
45
  * @example
45
46
  * ```ts
@@ -94,15 +95,21 @@ interface PersistOptions<T = unknown> {
94
95
  * Must be synchronous — see `encrypt` docs. */
95
96
  decrypt?: (value: string) => string;
96
97
  }
98
+ /** Setter returned by {@link persisted}: writes like a `signal()` setter, released with `dispose()`. */
99
+ type PersistedSetter<T> = ((next: T | ((prev: T) => T)) => void) & {
100
+ /** Stop persisting changes and remove the cross-tab `storage` listener. */
101
+ dispose(): void;
102
+ };
97
103
  /**
98
104
  * A signal mirrored into persistent storage, rehydrated on creation.
99
105
  *
100
106
  * @param key Storage key.
101
107
  * @param initial Value used when storage holds nothing (or holds junk).
102
108
  * @param options Storage backend, serializer and version/migration settings.
103
- * @returns A `[accessor, setter]` pair with the same shape as `signal`.
109
+ * @returns A `[accessor, setter]` pair with the same shape as `signal`; the
110
+ * setter carries `dispose()`.
104
111
  */
105
- declare function persisted<T>(key: string, initial: T, options?: PersistOptions<T>): [() => T, (next: T | ((prev: T) => T)) => void];
112
+ declare function persisted<T>(key: string, initial: T, options?: PersistOptions<T>): [() => T, PersistedSetter<T>];
106
113
 
107
114
  /**
108
115
  * optimistic provides optimistic UI updates that can be reverted on failure.
@@ -210,10 +217,22 @@ interface TimeTravelReturn<T> {
210
217
  }
211
218
  /**
212
219
  * timeline wraps a state value with undo/redo history.
220
+ *
221
+ * @param maxHistory How many entries (including the current one) to keep. Must
222
+ * be a positive safe integer — `0`, negative, fractional, `NaN` or infinite
223
+ * capacities throw a `RangeError`, since they would evict the current value
224
+ * and break the index invariant.
213
225
  */
214
226
  declare function timeline<T>(initial: T, maxHistory?: number): TimeTravelReturn<T>;
215
227
 
216
- type Middleware<S> = (state: S, action: string, payload: unknown, next: () => void) => void;
228
+ /**
229
+ * Store middleware. Call `next()` once to continue the chain — synchronously or
230
+ * later (after an `await`, from a timer). A middleware may be `async`: a
231
+ * rejection is reported through the runtime error handler, and a middleware
232
+ * that fails (throws, or rejects) before calling `next()` never continues —
233
+ * a later `next()` from it is ignored.
234
+ */
235
+ type Middleware<S> = (state: S, action: string, payload: unknown, next: () => void) => void | PromiseLike<void>;
217
236
  type Selector<S, R> = (state: S) => R;
218
237
  /**
219
238
  * Action-map constraint.
@@ -247,4 +266,4 @@ declare function globalStore<S extends object, A extends StoreActionMap<S>>(conf
247
266
  middleware?: Middleware<S>[];
248
267
  }): GlobalStore<S, A>;
249
268
 
250
- export { type GlobalStore, type MachineConfig, type MachineReturn, type Middleware, type PersistOptions, type Selector, type StoreActionMap, type TimeTravelReturn, globalStore, machine, optimistic, optimisticList, persisted, timeline };
269
+ export { type GlobalStore, type MachineConfig, type MachineReturn, type Middleware, type PersistOptions, type PersistedSetter, type Selector, type StoreActionMap, type TimeTravelReturn, globalStore, machine, optimistic, optimisticList, persisted, timeline };