sibujs 4.4.0 → 4.6.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.
- package/README.md +11 -0
- package/dist/browser.cjs +339 -130
- package/dist/browser.d.cts +61 -16
- package/dist/browser.d.ts +61 -16
- package/dist/browser.js +8 -6
- package/dist/build.cjs +273 -82
- package/dist/build.js +15 -16
- package/dist/cdn.dev.global.js +12 -12
- package/dist/cdn.full.dev.global.js +11 -11
- package/dist/cdn.full.global.js +10 -10
- package/dist/cdn.global.js +12 -12
- package/dist/{chunk-IXKSNWV5.js → chunk-2INLLLMZ.js} +1 -1
- package/dist/chunk-3ISI6ACU.js +44 -0
- package/dist/{chunk-VCTAEPSB.js → chunk-47M47FOM.js} +11 -3
- package/dist/chunk-5HZXGZ6T.js +24 -0
- package/dist/{chunk-KKLW7YWL.js → chunk-5MT6SJ3P.js} +275 -144
- package/dist/{chunk-3BTTCZ5J.js → chunk-5Q4R7HCL.js} +42 -4
- package/dist/{chunk-ADM46X22.js → chunk-7GQCWFOE.js} +157 -61
- package/dist/{chunk-4Z3SPQ67.js → chunk-7NCARGJW.js} +16 -8
- package/dist/{chunk-5DXA2J44.js → chunk-7XHATCIH.js} +5 -2
- package/dist/{chunk-LQFGQNMV.js → chunk-AIF3Z2T7.js} +302 -39
- package/dist/{chunk-UCALUKB5.js → chunk-BAAG6ZTI.js} +98 -29
- package/dist/{chunk-NVNJH22U.js → chunk-D33YTSX5.js} +2 -2
- package/dist/{chunk-M2F7TZHH.js → chunk-DKGBBKOF.js} +136 -80
- package/dist/{chunk-NIOYEGBQ.js → chunk-HURREPU2.js} +27 -13
- package/dist/{chunk-HFCOH2GN.js → chunk-HYXDKS4N.js} +153 -110
- package/dist/chunk-J6FW5TV6.js +233 -0
- package/dist/{chunk-36S2YPP4.js → chunk-JSXPZCET.js} +1 -1
- package/dist/chunk-NYNYSPK7.js +318 -0
- package/dist/{chunk-HQSEH5F6.js → chunk-ORMZXBKQ.js} +108 -45
- package/dist/{chunk-LYVUX7NT.js → chunk-OXUY2A6L.js} +287 -130
- package/dist/{chunk-6GSIXTWX.js → chunk-PK6FK2G2.js} +187 -66
- package/dist/{chunk-W2EQ7X2L.js → chunk-QE4TTDU3.js} +47 -9
- package/dist/{chunk-XLO7SLIX.js → chunk-SXXVZMKZ.js} +262 -70
- package/dist/{chunk-R25EFXXC.js → chunk-TUCPL2HB.js} +3 -3
- package/dist/{chunk-RR7M3FHM.js → chunk-UZQ6ALFS.js} +3 -3
- package/dist/{chunk-PNIRUQ4C.js → chunk-VVWPJ543.js} +6 -8
- package/dist/{chunk-7GIHSAWB.js → chunk-XC4MEKGA.js} +3 -3
- package/dist/{chunk-SKPTERHP.js → chunk-XRRZKZYX.js} +55 -31
- package/dist/{contracts-DBdg9J_a.d.cts → contracts-DRIuclVT.d.cts} +10 -2
- package/dist/{contracts-DBdg9J_a.d.ts → contracts-DRIuclVT.d.ts} +10 -2
- package/dist/{customElement-CNZxEB9G.d.ts → customElement-MmInOW1U.d.cts} +59 -10
- package/dist/{customElement-CNZxEB9G.d.cts → customElement-MmInOW1U.d.ts} +59 -10
- package/dist/data.cjs +293 -125
- package/dist/data.d.cts +47 -9
- package/dist/data.d.ts +47 -9
- package/dist/data.js +12 -9
- package/dist/devtools.cjs +121 -58
- package/dist/devtools.js +7 -8
- package/dist/dispose-GEIG2KOF.js +28 -0
- package/dist/ecosystem.cjs +391 -112
- package/dist/ecosystem.d.cts +31 -7
- package/dist/ecosystem.d.ts +31 -7
- package/dist/ecosystem.js +12 -12
- package/dist/extras.cjs +2250 -879
- package/dist/extras.d.cts +10 -9
- package/dist/extras.d.ts +10 -9
- package/dist/extras.js +39 -28
- package/dist/index.cjs +273 -82
- package/dist/index.d.cts +44 -154
- package/dist/index.d.ts +44 -154
- package/dist/index.js +24 -27
- package/dist/motion.cjs +137 -42
- package/dist/motion.js +5 -5
- package/dist/patterns.cjs +397 -48
- package/dist/patterns.d.cts +32 -9
- package/dist/patterns.d.ts +32 -9
- package/dist/patterns.js +8 -8
- package/dist/performance.cjs +338 -217
- package/dist/performance.d.cts +2 -2
- package/dist/performance.d.ts +2 -2
- package/dist/performance.js +8 -9
- package/dist/plugin-DVgSnTfK.d.cts +112 -0
- package/dist/plugin-DVgSnTfK.d.ts +112 -0
- package/dist/plugins.cjs +587 -203
- package/dist/plugins.d.cts +3 -3
- package/dist/plugins.d.ts +3 -3
- package/dist/plugins.js +35 -23
- package/dist/signal-EotCj4hS.d.cts +110 -0
- package/dist/signal-EotCj4hS.d.ts +110 -0
- package/dist/{ssr-BiPRdZ6n.d.cts → ssr-Bli9XRW5.d.cts} +5 -0
- package/dist/{ssr-BiPRdZ6n.d.ts → ssr-Bli9XRW5.d.ts} +5 -0
- package/dist/{ssr-Y7XOEPEN.js → ssr-XOTUASDO.js} +4 -5
- package/dist/ssr.cjs +214 -73
- package/dist/ssr.d.cts +9 -3
- package/dist/ssr.d.ts +9 -3
- package/dist/ssr.js +11 -12
- package/dist/{startup-BMpaiMhP.d.ts → startup-BLfSeL15.d.cts} +73 -22
- package/dist/{startup-BMpaiMhP.d.cts → startup-BLfSeL15.d.ts} +73 -22
- package/dist/tagFactory-DFstCLQV.d.cts +117 -0
- package/dist/tagFactory-DkaNVUNV.d.ts +117 -0
- package/dist/testing.cjs +2481 -2153
- package/dist/testing.d.cts +56 -5
- package/dist/testing.d.ts +56 -5
- package/dist/testing.js +580 -307
- package/dist/ui.cjs +798 -328
- package/dist/ui.d.cts +40 -7
- package/dist/ui.d.ts +40 -7
- package/dist/ui.js +151 -56
- package/dist/widgets.cjs +319 -285
- package/dist/widgets.js +9 -10
- package/package.json +2 -2
- package/dist/chunk-2WLZ6757.js +0 -149
- package/dist/chunk-7NBDXVHS.js +0 -60
- package/dist/chunk-CCSJMTRN.js +0 -15
- package/dist/chunk-QKRPLZ2V.js +0 -108
- package/dist/chunk-WWV3SJ3L.js +0 -131
- package/dist/dispose-46BOMMQJ.js +0 -19
- package/dist/plugin-D30wlGW5.d.cts +0 -71
- package/dist/plugin-D30wlGW5.d.ts +0 -71
- package/dist/tagFactory-Bzupt4Pj.d.cts +0 -55
- package/dist/tagFactory-Bzupt4Pj.d.ts +0 -55
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 = [];
|
|
@@ -294,8 +313,18 @@ function untracked(fn) {
|
|
|
294
313
|
var subscriberEpochCounter = 0;
|
|
295
314
|
function retrack(effectFn, subscriber) {
|
|
296
315
|
const prev = currentSubscriber;
|
|
316
|
+
let savedDepth = 0;
|
|
317
|
+
let savedSuspendSub = null;
|
|
318
|
+
if (trackingSuspended) {
|
|
319
|
+
savedDepth = suspendDepth;
|
|
320
|
+
savedSuspendSub = suspendSavedSub;
|
|
321
|
+
suspendDepth = 0;
|
|
322
|
+
suspendSavedSub = null;
|
|
323
|
+
trackingSuspended = false;
|
|
324
|
+
}
|
|
297
325
|
currentSubscriber = subscriber;
|
|
298
326
|
const sub = subscriber;
|
|
327
|
+
if (sub._cap === void 0) sub._cap = currentDisposerCapture();
|
|
299
328
|
const epoch = ++subscriberEpochCounter;
|
|
300
329
|
sub._epoch = epoch;
|
|
301
330
|
sub._structDirty = false;
|
|
@@ -308,6 +337,11 @@ function retrack(effectFn, subscriber) {
|
|
|
308
337
|
effectFn();
|
|
309
338
|
} finally {
|
|
310
339
|
currentSubscriber = prev;
|
|
340
|
+
if (savedDepth !== 0) {
|
|
341
|
+
suspendDepth = savedDepth;
|
|
342
|
+
suspendSavedSub = savedSuspendSub;
|
|
343
|
+
trackingSuspended = true;
|
|
344
|
+
}
|
|
311
345
|
let node = sub.depsHead ?? null;
|
|
312
346
|
while (node !== null) {
|
|
313
347
|
const next = node.subNext;
|
|
@@ -327,11 +361,25 @@ function track(effectFn, subscriber) {
|
|
|
327
361
|
if (!subscriber) return reactiveBinding(effectFn);
|
|
328
362
|
cleanup(subscriber);
|
|
329
363
|
const prev = currentSubscriber;
|
|
364
|
+
let savedDepth = 0;
|
|
365
|
+
let savedSuspendSub = null;
|
|
366
|
+
if (trackingSuspended) {
|
|
367
|
+
savedDepth = suspendDepth;
|
|
368
|
+
savedSuspendSub = suspendSavedSub;
|
|
369
|
+
suspendDepth = 0;
|
|
370
|
+
suspendSavedSub = null;
|
|
371
|
+
trackingSuspended = false;
|
|
372
|
+
}
|
|
330
373
|
currentSubscriber = subscriber;
|
|
331
374
|
try {
|
|
332
375
|
effectFn();
|
|
333
376
|
} finally {
|
|
334
377
|
currentSubscriber = prev;
|
|
378
|
+
if (savedDepth !== 0) {
|
|
379
|
+
suspendDepth = savedDepth;
|
|
380
|
+
suspendSavedSub = savedSuspendSub;
|
|
381
|
+
trackingSuspended = true;
|
|
382
|
+
}
|
|
335
383
|
const sub2 = subscriber;
|
|
336
384
|
for (let n = sub2.depsHead ?? null; n !== null; n = n.subNext) {
|
|
337
385
|
const sig = n.sig;
|
|
@@ -468,7 +516,12 @@ function drainQueue() {
|
|
|
468
516
|
quarantined.add(sub);
|
|
469
517
|
continue;
|
|
470
518
|
}
|
|
471
|
-
|
|
519
|
+
const pushed = beginDisposerCapture(sub._cap ?? null);
|
|
520
|
+
try {
|
|
521
|
+
safeInvoke(sub);
|
|
522
|
+
} finally {
|
|
523
|
+
if (pushed) endDisposerCapture();
|
|
524
|
+
}
|
|
472
525
|
}
|
|
473
526
|
}
|
|
474
527
|
function drainNotificationQueue() {
|
|
@@ -502,8 +555,9 @@ function propagateDirty(sub) {
|
|
|
502
555
|
if (s._c) {
|
|
503
556
|
const nSig = s._sig;
|
|
504
557
|
if (nSig) {
|
|
505
|
-
if (!nSig._d) {
|
|
558
|
+
if (!nSig._d || nSig._f === true) {
|
|
506
559
|
nSig._d = true;
|
|
560
|
+
nSig._f = false;
|
|
507
561
|
stack.push(nSig);
|
|
508
562
|
}
|
|
509
563
|
} else {
|
|
@@ -603,7 +657,7 @@ function forEachSubscriber(signal2, visit) {
|
|
|
603
657
|
}
|
|
604
658
|
|
|
605
659
|
// src/reactivity/track.ts
|
|
606
|
-
var _runtimeVersion = true ? "4.
|
|
660
|
+
var _runtimeVersion = true ? "4.6.0" : "dev";
|
|
607
661
|
var REGISTRY_KEY = /* @__PURE__ */ Symbol.for("sibujs.reactive.v1");
|
|
608
662
|
function resolveReactiveApi() {
|
|
609
663
|
const g = globalThis;
|
|
@@ -797,12 +851,24 @@ function stripUnsafeKeys(obj) {
|
|
|
797
851
|
function machine(config) {
|
|
798
852
|
const [state2, setState] = signal(config.initial);
|
|
799
853
|
const [context, setContext] = signal(config.context || {});
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
854
|
+
let currentState = config.initial;
|
|
855
|
+
let currentContext = context();
|
|
856
|
+
const queue = [];
|
|
857
|
+
let processing = false;
|
|
858
|
+
function drain() {
|
|
859
|
+
processing = true;
|
|
860
|
+
try {
|
|
861
|
+
while (queue.length > 0) {
|
|
862
|
+
step(queue.shift());
|
|
863
|
+
}
|
|
864
|
+
} catch (err) {
|
|
865
|
+
queue.length = 0;
|
|
866
|
+
throw err;
|
|
867
|
+
} finally {
|
|
868
|
+
processing = false;
|
|
869
|
+
}
|
|
803
870
|
}
|
|
804
|
-
function
|
|
805
|
-
const currentState = state2();
|
|
871
|
+
function step(event) {
|
|
806
872
|
const stateDef = config.states[currentState];
|
|
807
873
|
if (!stateDef?.on) return;
|
|
808
874
|
const transition = stateDef.on[event];
|
|
@@ -817,28 +883,51 @@ function machine(config) {
|
|
|
817
883
|
guard = transition.guard;
|
|
818
884
|
action = transition.action;
|
|
819
885
|
}
|
|
820
|
-
const ctx =
|
|
886
|
+
const ctx = currentContext;
|
|
821
887
|
if (guard && !guard(ctx)) return;
|
|
822
888
|
if (stateDef.exit) {
|
|
823
889
|
stateDef.exit(ctx);
|
|
824
890
|
}
|
|
891
|
+
let nextContext = ctx;
|
|
825
892
|
if (action) {
|
|
826
893
|
const rawPatch = action(ctx);
|
|
827
|
-
|
|
828
|
-
setContext(next);
|
|
894
|
+
nextContext = { ...ctx, ...stripUnsafeKeys(rawPatch) };
|
|
829
895
|
}
|
|
830
|
-
|
|
896
|
+
currentState = target;
|
|
897
|
+
currentContext = nextContext;
|
|
898
|
+
batch(() => {
|
|
899
|
+
if (action) setContext(nextContext);
|
|
900
|
+
setState(target);
|
|
901
|
+
});
|
|
831
902
|
const targetDef = config.states[target];
|
|
832
903
|
if (targetDef?.entry) {
|
|
833
|
-
targetDef.entry(
|
|
904
|
+
targetDef.entry(currentContext);
|
|
834
905
|
}
|
|
835
906
|
}
|
|
907
|
+
function send(event) {
|
|
908
|
+
queue.push(event);
|
|
909
|
+
if (processing) return;
|
|
910
|
+
drain();
|
|
911
|
+
}
|
|
912
|
+
const initialDef = config.states[config.initial];
|
|
913
|
+
if (initialDef?.entry) {
|
|
914
|
+
processing = true;
|
|
915
|
+
try {
|
|
916
|
+
initialDef.entry(currentContext);
|
|
917
|
+
} catch (err) {
|
|
918
|
+
queue.length = 0;
|
|
919
|
+
throw err;
|
|
920
|
+
} finally {
|
|
921
|
+
processing = false;
|
|
922
|
+
}
|
|
923
|
+
if (queue.length > 0) drain();
|
|
924
|
+
}
|
|
836
925
|
function matches(s) {
|
|
837
926
|
return state2() === s;
|
|
838
927
|
}
|
|
839
928
|
function can(event) {
|
|
840
|
-
const
|
|
841
|
-
const stateDef = config.states[
|
|
929
|
+
const currentState2 = state2();
|
|
930
|
+
const stateDef = config.states[currentState2];
|
|
842
931
|
if (!stateDef?.on) return false;
|
|
843
932
|
const transition = stateDef.on[event];
|
|
844
933
|
if (!transition) return false;
|
|
@@ -1390,10 +1479,14 @@ function derived(getter, options) {
|
|
|
1390
1479
|
const cs = {};
|
|
1391
1480
|
cs._d = false;
|
|
1392
1481
|
cs._init = false;
|
|
1482
|
+
cs._f = false;
|
|
1393
1483
|
cs._g = getter;
|
|
1394
1484
|
cs.__v = 0;
|
|
1485
|
+
let evaluating = false;
|
|
1486
|
+
let disposed = false;
|
|
1487
|
+
let pendingError;
|
|
1395
1488
|
const markDirty = () => {
|
|
1396
|
-
if (cs._d) return;
|
|
1489
|
+
if (cs._d || disposed) return;
|
|
1397
1490
|
cs._d = true;
|
|
1398
1491
|
};
|
|
1399
1492
|
markDirty._c = 1;
|
|
@@ -1416,33 +1509,53 @@ function derived(getter, options) {
|
|
|
1416
1509
|
}
|
|
1417
1510
|
}, markDirty);
|
|
1418
1511
|
const hook = globalThis.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
1419
|
-
let evaluating = false;
|
|
1420
1512
|
const validate = () => {
|
|
1421
|
-
if (!cs._d) return;
|
|
1513
|
+
if (!cs._d || disposed || pendingError !== void 0) return;
|
|
1422
1514
|
const oldValue = cs._v;
|
|
1423
1515
|
evaluating = true;
|
|
1424
1516
|
try {
|
|
1425
1517
|
retrack2(recompute, markDirty);
|
|
1426
1518
|
if (!Object.is(oldValue, cs._v)) cs.__v++;
|
|
1519
|
+
} catch (err) {
|
|
1520
|
+
pendingError = { error: err };
|
|
1521
|
+
cs.__v++;
|
|
1522
|
+
if (disposed) cs._d = true;
|
|
1523
|
+
else cs._f = true;
|
|
1427
1524
|
} finally {
|
|
1428
1525
|
evaluating = false;
|
|
1526
|
+
if (disposed) cleanup2(markDirty);
|
|
1429
1527
|
}
|
|
1430
|
-
if (hook && !Object.is(oldValue, cs._v)) {
|
|
1528
|
+
if (hook && !disposed && !Object.is(oldValue, cs._v)) {
|
|
1431
1529
|
hook.emit("computed:update", { signal: cs, oldValue, newValue: cs._v });
|
|
1432
1530
|
}
|
|
1433
1531
|
};
|
|
1434
1532
|
cs._validate = validate;
|
|
1533
|
+
const throwPending = () => {
|
|
1534
|
+
const { error } = pendingError;
|
|
1535
|
+
pendingError = void 0;
|
|
1536
|
+
if (disposed) cs._d = false;
|
|
1537
|
+
throw error;
|
|
1538
|
+
};
|
|
1435
1539
|
function computedGetter() {
|
|
1436
1540
|
if (evaluating) {
|
|
1437
1541
|
throw new Error(
|
|
1438
1542
|
`[SibuJS] Circular dependency detected in derived${debugName ? ` "${debugName}"` : ""}. A derived signal cannot read itself (directly or through a chain).`
|
|
1439
1543
|
);
|
|
1440
1544
|
}
|
|
1441
|
-
if (isTrackingSuspended2()) {
|
|
1442
|
-
if (cs._d)
|
|
1545
|
+
if (isTrackingSuspended2() || disposed) {
|
|
1546
|
+
if (cs._d) {
|
|
1547
|
+
validate();
|
|
1548
|
+
if (pendingError !== void 0) throwPending();
|
|
1549
|
+
}
|
|
1443
1550
|
return cs._v;
|
|
1444
1551
|
}
|
|
1445
|
-
if (cs._d)
|
|
1552
|
+
if (cs._d) {
|
|
1553
|
+
validate();
|
|
1554
|
+
if (pendingError !== void 0) {
|
|
1555
|
+
recordDependency2(cs);
|
|
1556
|
+
throwPending();
|
|
1557
|
+
}
|
|
1558
|
+
}
|
|
1446
1559
|
recordDependency2(cs);
|
|
1447
1560
|
return cs._v;
|
|
1448
1561
|
}
|
|
@@ -1451,12 +1564,28 @@ function derived(getter, options) {
|
|
|
1451
1564
|
cs.__name = debugName;
|
|
1452
1565
|
}
|
|
1453
1566
|
computedGetter.__signal = cs;
|
|
1567
|
+
computedGetter.dispose = () => {
|
|
1568
|
+
if (disposed) return;
|
|
1569
|
+
disposed = true;
|
|
1570
|
+
cs._d = pendingError !== void 0;
|
|
1571
|
+
cleanup2(markDirty);
|
|
1572
|
+
const h = globalThis.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
1573
|
+
if (h) {
|
|
1574
|
+
try {
|
|
1575
|
+
h.emit("computed:destroy", { signal: cs, getter: computedGetter });
|
|
1576
|
+
} catch {
|
|
1577
|
+
}
|
|
1578
|
+
}
|
|
1579
|
+
};
|
|
1454
1580
|
if (hook) hook.emit("computed:create", { signal: cs, name: debugName, getter: computedGetter });
|
|
1455
1581
|
return computedGetter;
|
|
1456
1582
|
}
|
|
1457
1583
|
|
|
1458
1584
|
// src/patterns/timeTravel.ts
|
|
1459
1585
|
function timeline(initial, maxHistory = 100) {
|
|
1586
|
+
if (!Number.isSafeInteger(maxHistory) || maxHistory < 1) {
|
|
1587
|
+
throw new RangeError(`[timeline] maxHistory must be a positive safe integer, got ${maxHistory}`);
|
|
1588
|
+
}
|
|
1460
1589
|
const [history, setHistory] = signal([initial]);
|
|
1461
1590
|
const [index, setIndex] = signal(0);
|
|
1462
1591
|
const value = derived(() => history()[index()]);
|
|
@@ -1503,7 +1632,126 @@ function timeline(initial, maxHistory = 100) {
|
|
|
1503
1632
|
setIndex(targetIndex);
|
|
1504
1633
|
}
|
|
1505
1634
|
}
|
|
1506
|
-
|
|
1635
|
+
function dispose() {
|
|
1636
|
+
value.dispose();
|
|
1637
|
+
canUndo.dispose();
|
|
1638
|
+
canRedo.dispose();
|
|
1639
|
+
}
|
|
1640
|
+
return { value, set, undo, redo, canUndo, canRedo, history, index, reset, jumpTo, dispose };
|
|
1641
|
+
}
|
|
1642
|
+
|
|
1643
|
+
// src/utils/adoption.ts
|
|
1644
|
+
var nativeThen = Promise.prototype.then;
|
|
1645
|
+
function probeNative(target, onRejected, onOpen) {
|
|
1646
|
+
let decided = false;
|
|
1647
|
+
const decide = (rejected) => {
|
|
1648
|
+
if (decided) return;
|
|
1649
|
+
decided = true;
|
|
1650
|
+
(rejected ? onRejected : onOpen)();
|
|
1651
|
+
};
|
|
1652
|
+
try {
|
|
1653
|
+
Reflect.apply(nativeThen, target, [void 0, () => decide(true)]);
|
|
1654
|
+
} catch {
|
|
1655
|
+
queueMicrotask(() => decide(true));
|
|
1656
|
+
return;
|
|
1657
|
+
}
|
|
1658
|
+
queueMicrotask(() => decide(false));
|
|
1659
|
+
}
|
|
1660
|
+
function adopt(value) {
|
|
1661
|
+
if (value === null || typeof value !== "object" && typeof value !== "function") return null;
|
|
1662
|
+
let then;
|
|
1663
|
+
try {
|
|
1664
|
+
then = value.then;
|
|
1665
|
+
} catch (error) {
|
|
1666
|
+
return {
|
|
1667
|
+
promise: Promise.reject(error),
|
|
1668
|
+
failedEarly: true,
|
|
1669
|
+
probe: (onRejected) => queueMicrotask(onRejected)
|
|
1670
|
+
};
|
|
1671
|
+
}
|
|
1672
|
+
if (typeof then !== "function") return null;
|
|
1673
|
+
let resolvePromise;
|
|
1674
|
+
let rejectPromise;
|
|
1675
|
+
const promise = new Promise((resolve, reject) => {
|
|
1676
|
+
resolvePromise = resolve;
|
|
1677
|
+
rejectPromise = reject;
|
|
1678
|
+
});
|
|
1679
|
+
let state2 = "invoking";
|
|
1680
|
+
let nativeTarget;
|
|
1681
|
+
const waiters = [];
|
|
1682
|
+
const transition = (next) => {
|
|
1683
|
+
state2 = next;
|
|
1684
|
+
if (next === "invoking") return;
|
|
1685
|
+
for (const waiter of waiters.splice(0)) waiter();
|
|
1686
|
+
};
|
|
1687
|
+
const fulfil = (result) => {
|
|
1688
|
+
resolvePromise(result);
|
|
1689
|
+
transition("fulfilled");
|
|
1690
|
+
};
|
|
1691
|
+
const fail = (error) => {
|
|
1692
|
+
rejectPromise(error);
|
|
1693
|
+
transition("rejected");
|
|
1694
|
+
};
|
|
1695
|
+
const follow = (result) => {
|
|
1696
|
+
if (result === promise) {
|
|
1697
|
+
fail(new TypeError("adopt: a thenable resolved to its own adoption"));
|
|
1698
|
+
return;
|
|
1699
|
+
}
|
|
1700
|
+
if (result === null || typeof result !== "object" && typeof result !== "function") {
|
|
1701
|
+
fulfil(result);
|
|
1702
|
+
return;
|
|
1703
|
+
}
|
|
1704
|
+
let nextThen;
|
|
1705
|
+
try {
|
|
1706
|
+
nextThen = result.then;
|
|
1707
|
+
} catch (error) {
|
|
1708
|
+
fail(error);
|
|
1709
|
+
return;
|
|
1710
|
+
}
|
|
1711
|
+
if (typeof nextThen !== "function") {
|
|
1712
|
+
fulfil(result);
|
|
1713
|
+
return;
|
|
1714
|
+
}
|
|
1715
|
+
invokeLater(result, nextThen);
|
|
1716
|
+
};
|
|
1717
|
+
const invokeLater = (target, targetThen) => {
|
|
1718
|
+
if (targetThen === nativeThen) {
|
|
1719
|
+
nativeTarget = target;
|
|
1720
|
+
transition("native");
|
|
1721
|
+
} else {
|
|
1722
|
+
transition("invoking");
|
|
1723
|
+
}
|
|
1724
|
+
queueMicrotask(() => {
|
|
1725
|
+
let done = false;
|
|
1726
|
+
const onResolve = (result) => {
|
|
1727
|
+
if (done) return;
|
|
1728
|
+
done = true;
|
|
1729
|
+
follow(result);
|
|
1730
|
+
};
|
|
1731
|
+
const onReject = (error) => {
|
|
1732
|
+
if (done) return;
|
|
1733
|
+
done = true;
|
|
1734
|
+
fail(error);
|
|
1735
|
+
};
|
|
1736
|
+
try {
|
|
1737
|
+
Reflect.apply(targetThen, target, [onResolve, onReject]);
|
|
1738
|
+
} catch (error) {
|
|
1739
|
+
onReject(error);
|
|
1740
|
+
}
|
|
1741
|
+
if (!done && state2 === "invoking") transition("pending");
|
|
1742
|
+
});
|
|
1743
|
+
};
|
|
1744
|
+
invokeLater(value, then);
|
|
1745
|
+
const probe = (onRejected, onOpen) => {
|
|
1746
|
+
const decide = () => {
|
|
1747
|
+
if (state2 === "native") probeNative(nativeTarget, onRejected, onOpen);
|
|
1748
|
+
else (state2 === "rejected" ? onRejected : onOpen)();
|
|
1749
|
+
};
|
|
1750
|
+
if (state2 === "native") probeNative(nativeTarget, onRejected, onOpen);
|
|
1751
|
+
else if (state2 === "invoking") waiters.push(decide);
|
|
1752
|
+
else queueMicrotask(state2 === "rejected" ? onRejected : onOpen);
|
|
1753
|
+
};
|
|
1754
|
+
return { promise, failedEarly: false, probe };
|
|
1507
1755
|
}
|
|
1508
1756
|
|
|
1509
1757
|
// src/patterns/globalStore.ts
|
|
@@ -1540,8 +1788,51 @@ function deepClone(value) {
|
|
|
1540
1788
|
function globalStore(config) {
|
|
1541
1789
|
const initialState = deepClone(config.state);
|
|
1542
1790
|
const [getState, setState] = signal({ ...initialState });
|
|
1543
|
-
const
|
|
1791
|
+
const subscriptions = /* @__PURE__ */ new Map();
|
|
1544
1792
|
const middlewares = config.middleware || [];
|
|
1793
|
+
function notifyListeners(state2) {
|
|
1794
|
+
if (subscriptions.size === 0) return;
|
|
1795
|
+
for (const subscription of Array.from(subscriptions.values())) {
|
|
1796
|
+
if (!subscription.active) continue;
|
|
1797
|
+
try {
|
|
1798
|
+
subscription.callback(state2);
|
|
1799
|
+
} catch (err) {
|
|
1800
|
+
reportError(err, { phase: "event", name: "globalStore(subscribe)" });
|
|
1801
|
+
}
|
|
1802
|
+
}
|
|
1803
|
+
}
|
|
1804
|
+
const operations = [];
|
|
1805
|
+
let running = false;
|
|
1806
|
+
function perform(operation, rethrowOwn = true) {
|
|
1807
|
+
operations.push(operation);
|
|
1808
|
+
if (running) return;
|
|
1809
|
+
running = true;
|
|
1810
|
+
let callerError;
|
|
1811
|
+
let callerFailed = false;
|
|
1812
|
+
try {
|
|
1813
|
+
let first = true;
|
|
1814
|
+
let cursor = 0;
|
|
1815
|
+
while (cursor < operations.length) {
|
|
1816
|
+
const next = operations[cursor];
|
|
1817
|
+
operations[cursor++] = void 0;
|
|
1818
|
+
try {
|
|
1819
|
+
next();
|
|
1820
|
+
} catch (err) {
|
|
1821
|
+
if (first && rethrowOwn) {
|
|
1822
|
+
callerFailed = true;
|
|
1823
|
+
callerError = err;
|
|
1824
|
+
} else {
|
|
1825
|
+
reportError(err, { phase: "event", name: "globalStore(dispatch)" });
|
|
1826
|
+
}
|
|
1827
|
+
}
|
|
1828
|
+
first = false;
|
|
1829
|
+
}
|
|
1830
|
+
} finally {
|
|
1831
|
+
operations.length = 0;
|
|
1832
|
+
running = false;
|
|
1833
|
+
}
|
|
1834
|
+
if (callerFailed) throw callerError;
|
|
1835
|
+
}
|
|
1545
1836
|
function dispatch(action, payload) {
|
|
1546
1837
|
const actionFn = config.actions[action];
|
|
1547
1838
|
if (!actionFn) throw new Error(`Unknown action: ${String(action)}`);
|
|
@@ -1550,38 +1841,96 @@ function globalStore(config) {
|
|
|
1550
1841
|
const rawPatch = actionFn(current, payload);
|
|
1551
1842
|
const patch = stripUnsafeKeys(rawPatch);
|
|
1552
1843
|
setState({ ...current, ...patch });
|
|
1553
|
-
|
|
1554
|
-
for (const listener of listeners) {
|
|
1555
|
-
listener(newState);
|
|
1556
|
-
}
|
|
1844
|
+
notifyListeners(getState());
|
|
1557
1845
|
};
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
return;
|
|
1561
|
-
}
|
|
1562
|
-
let index = 0;
|
|
1563
|
-
const next = () => {
|
|
1564
|
-
if (index < middlewares.length) {
|
|
1565
|
-
const mw = middlewares[index++];
|
|
1566
|
-
mw(getState(), String(action), payload, next);
|
|
1567
|
-
} else {
|
|
1846
|
+
perform(() => {
|
|
1847
|
+
if (middlewares.length === 0) {
|
|
1568
1848
|
execute();
|
|
1849
|
+
return;
|
|
1569
1850
|
}
|
|
1570
|
-
|
|
1571
|
-
|
|
1851
|
+
const runFrom = (index) => {
|
|
1852
|
+
if (index >= middlewares.length) {
|
|
1853
|
+
execute();
|
|
1854
|
+
return;
|
|
1855
|
+
}
|
|
1856
|
+
let called = false;
|
|
1857
|
+
let failed = false;
|
|
1858
|
+
let synchronous = true;
|
|
1859
|
+
const next = () => {
|
|
1860
|
+
if (failed && !called) {
|
|
1861
|
+
if (DEV)
|
|
1862
|
+
devWarn(
|
|
1863
|
+
`globalStore: middleware ${index} next() called after it failed for "${String(action)}"; ignored.`
|
|
1864
|
+
);
|
|
1865
|
+
called = true;
|
|
1866
|
+
return;
|
|
1867
|
+
}
|
|
1868
|
+
if (called) {
|
|
1869
|
+
if (DEV)
|
|
1870
|
+
devWarn(
|
|
1871
|
+
`globalStore: middleware ${index} next() called more than once for "${String(action)}"; ignored.`
|
|
1872
|
+
);
|
|
1873
|
+
return;
|
|
1874
|
+
}
|
|
1875
|
+
called = true;
|
|
1876
|
+
if (synchronous) {
|
|
1877
|
+
runFrom(index + 1);
|
|
1878
|
+
return;
|
|
1879
|
+
}
|
|
1880
|
+
const proceed = () => perform(() => runFrom(index + 1), false);
|
|
1881
|
+
if (!adoption) {
|
|
1882
|
+
proceed();
|
|
1883
|
+
return;
|
|
1884
|
+
}
|
|
1885
|
+
adoption.probe(() => {
|
|
1886
|
+
failed = true;
|
|
1887
|
+
if (DEV)
|
|
1888
|
+
devWarn(
|
|
1889
|
+
`globalStore: middleware ${index} next() called after it failed for "${String(action)}"; ignored.`
|
|
1890
|
+
);
|
|
1891
|
+
}, proceed);
|
|
1892
|
+
};
|
|
1893
|
+
let adoption = null;
|
|
1894
|
+
try {
|
|
1895
|
+
adoption = adopt(middlewares[index](getState(), String(action), payload, next));
|
|
1896
|
+
} catch (err) {
|
|
1897
|
+
failed = true;
|
|
1898
|
+
throw err;
|
|
1899
|
+
} finally {
|
|
1900
|
+
synchronous = false;
|
|
1901
|
+
}
|
|
1902
|
+
if (adoption) {
|
|
1903
|
+
if (adoption.failedEarly) failed = true;
|
|
1904
|
+
adoption.promise.then(void 0, (err) => {
|
|
1905
|
+
failed = true;
|
|
1906
|
+
reportError(err, { phase: "async", name: "globalStore(middleware)" });
|
|
1907
|
+
});
|
|
1908
|
+
}
|
|
1909
|
+
};
|
|
1910
|
+
runFrom(0);
|
|
1911
|
+
});
|
|
1572
1912
|
}
|
|
1573
1913
|
function select(selector) {
|
|
1574
1914
|
return () => selector(getState());
|
|
1575
1915
|
}
|
|
1576
1916
|
function subscribe(callback) {
|
|
1577
|
-
|
|
1578
|
-
|
|
1917
|
+
let subscription = subscriptions.get(callback);
|
|
1918
|
+
if (!subscription) {
|
|
1919
|
+
subscription = { callback, active: true };
|
|
1920
|
+
subscriptions.set(callback, subscription);
|
|
1921
|
+
}
|
|
1922
|
+
const own = subscription;
|
|
1923
|
+
return () => {
|
|
1924
|
+
if (subscriptions.get(callback) !== own) return;
|
|
1925
|
+
own.active = false;
|
|
1926
|
+
subscriptions.delete(callback);
|
|
1927
|
+
};
|
|
1579
1928
|
}
|
|
1580
1929
|
function reset() {
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
}
|
|
1930
|
+
perform(() => {
|
|
1931
|
+
setState({ ...initialState });
|
|
1932
|
+
notifyListeners(getState());
|
|
1933
|
+
});
|
|
1585
1934
|
}
|
|
1586
1935
|
return { getState, select, dispatch, subscribe, reset };
|
|
1587
1936
|
}
|
|
@@ -1705,7 +2054,7 @@ function validateProps(props, schema) {
|
|
|
1705
2054
|
const errors = [];
|
|
1706
2055
|
for (const [key, def] of Object.entries(schema)) {
|
|
1707
2056
|
const propDef = typeof def === "function" ? { type: def } : def;
|
|
1708
|
-
if (result[key]
|
|
2057
|
+
if (result[key] === void 0 && propDef.default !== void 0) {
|
|
1709
2058
|
result[key] = typeof propDef.default === "function" ? propDef.default() : propDef.default;
|
|
1710
2059
|
}
|
|
1711
2060
|
if (propDef.required && result[key] == null) {
|
|
@@ -1731,7 +2080,7 @@ ${errors.map((e) => ` - ${e}`).join("\n")}`);
|
|
|
1731
2080
|
for (const [key, def] of Object.entries(schema)) {
|
|
1732
2081
|
if (typeof def === "function") continue;
|
|
1733
2082
|
const fallback = def.default;
|
|
1734
|
-
if (result[key]
|
|
2083
|
+
if (result[key] === void 0 && fallback !== void 0) {
|
|
1735
2084
|
result[key] = typeof fallback === "function" ? fallback() : fallback;
|
|
1736
2085
|
}
|
|
1737
2086
|
}
|
package/dist/patterns.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
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-
|
|
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-DRIuclVT.cjs';
|
|
2
2
|
|
|
3
3
|
interface MachineConfig<S extends string, E extends string, C extends object = Record<string, unknown>> {
|
|
4
4
|
initial: S;
|
|
@@ -36,10 +36,10 @@ declare function machine<S extends string, E extends string, C extends object =
|
|
|
36
36
|
* @param key Storage key
|
|
37
37
|
* @param initial Default value when no persisted value exists
|
|
38
38
|
* @param options Storage options
|
|
39
|
-
* @returns The same `[getter, setter]` tuple as `signal()`.
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
39
|
+
* @returns The same `[getter, setter]` tuple as `signal()`. The setter also
|
|
40
|
+
* carries a non-enumerable `dispose()` method — call `setter.dispose()` on
|
|
41
|
+
* unmount to stop persisting and remove the cross-tab `storage` listener;
|
|
42
|
+
* otherwise both live for the page's lifetime.
|
|
43
43
|
*
|
|
44
44
|
* @example
|
|
45
45
|
* ```ts
|
|
@@ -94,15 +94,21 @@ interface PersistOptions<T = unknown> {
|
|
|
94
94
|
* Must be synchronous — see `encrypt` docs. */
|
|
95
95
|
decrypt?: (value: string) => string;
|
|
96
96
|
}
|
|
97
|
+
/** Setter returned by {@link persisted}: writes like a `signal()` setter, released with `dispose()`. */
|
|
98
|
+
type PersistedSetter<T> = ((next: T | ((prev: T) => T)) => void) & {
|
|
99
|
+
/** Stop persisting changes and remove the cross-tab `storage` listener. */
|
|
100
|
+
dispose(): void;
|
|
101
|
+
};
|
|
97
102
|
/**
|
|
98
103
|
* A signal mirrored into persistent storage, rehydrated on creation.
|
|
99
104
|
*
|
|
100
105
|
* @param key Storage key.
|
|
101
106
|
* @param initial Value used when storage holds nothing (or holds junk).
|
|
102
107
|
* @param options Storage backend, serializer and version/migration settings.
|
|
103
|
-
* @returns A `[accessor, setter]` pair with the same shape as `signal
|
|
108
|
+
* @returns A `[accessor, setter]` pair with the same shape as `signal`; the
|
|
109
|
+
* setter carries `dispose()`.
|
|
104
110
|
*/
|
|
105
|
-
declare function persisted<T>(key: string, initial: T, options?: PersistOptions<T>): [() => T,
|
|
111
|
+
declare function persisted<T>(key: string, initial: T, options?: PersistOptions<T>): [() => T, PersistedSetter<T>];
|
|
106
112
|
|
|
107
113
|
/**
|
|
108
114
|
* optimistic provides optimistic UI updates that can be reverted on failure.
|
|
@@ -202,13 +208,30 @@ interface TimeTravelReturn<T> {
|
|
|
202
208
|
index: () => number;
|
|
203
209
|
reset: () => void;
|
|
204
210
|
jumpTo: (index: number) => void;
|
|
211
|
+
/**
|
|
212
|
+
* Dispose the internal `value`, `canUndo` and `canRedo` deriveds and remove
|
|
213
|
+
* them from DevTools. Afterwards they return their last values. Idempotent.
|
|
214
|
+
*/
|
|
215
|
+
dispose: () => void;
|
|
205
216
|
}
|
|
206
217
|
/**
|
|
207
218
|
* timeline wraps a state value with undo/redo history.
|
|
219
|
+
*
|
|
220
|
+
* @param maxHistory How many entries (including the current one) to keep. Must
|
|
221
|
+
* be a positive safe integer — `0`, negative, fractional, `NaN` or infinite
|
|
222
|
+
* capacities throw a `RangeError`, since they would evict the current value
|
|
223
|
+
* and break the index invariant.
|
|
208
224
|
*/
|
|
209
225
|
declare function timeline<T>(initial: T, maxHistory?: number): TimeTravelReturn<T>;
|
|
210
226
|
|
|
211
|
-
|
|
227
|
+
/**
|
|
228
|
+
* Store middleware. Call `next()` once to continue the chain — synchronously or
|
|
229
|
+
* later (after an `await`, from a timer). A middleware may be `async`: a
|
|
230
|
+
* rejection is reported through the runtime error handler, and a middleware
|
|
231
|
+
* that fails (throws, or rejects) before calling `next()` never continues —
|
|
232
|
+
* a later `next()` from it is ignored.
|
|
233
|
+
*/
|
|
234
|
+
type Middleware<S> = (state: S, action: string, payload: unknown, next: () => void) => void | PromiseLike<void>;
|
|
212
235
|
type Selector<S, R> = (state: S) => R;
|
|
213
236
|
/**
|
|
214
237
|
* Action-map constraint.
|
|
@@ -242,4 +265,4 @@ declare function globalStore<S extends object, A extends StoreActionMap<S>>(conf
|
|
|
242
265
|
middleware?: Middleware<S>[];
|
|
243
266
|
}): GlobalStore<S, A>;
|
|
244
267
|
|
|
245
|
-
export { type GlobalStore, type MachineConfig, type MachineReturn, type Middleware, type PersistOptions, type Selector, type StoreActionMap, type TimeTravelReturn, globalStore, machine, optimistic, optimisticList, persisted, timeline };
|
|
268
|
+
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 };
|