solid-js 2.0.0-beta.7 → 2.0.0-beta.8
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/dist/dev.cjs +21 -41
- package/dist/dev.js +21 -41
- package/dist/server.cjs +122 -37
- package/dist/server.js +122 -37
- package/dist/solid.cjs +21 -41
- package/dist/solid.js +21 -41
- package/package.json +2 -2
- package/types/client/flow.d.ts +34 -13
- package/types/client/hydration.d.ts +31 -6
- package/types/jsx-properties.d.ts +2 -5
- package/types/jsx.d.ts +108 -77
- package/types/server/flow.d.ts +40 -7
- package/types/server/hydration.d.ts +18 -1
- package/types/server/signals.d.ts +29 -9
- package/types-cjs/client/flow.d.cts +34 -13
- package/types-cjs/client/hydration.d.cts +31 -6
- package/types-cjs/jsx-properties.d.cts +2 -5
- package/types-cjs/jsx.d.cts +108 -77
- package/types-cjs/server/flow.d.cts +40 -7
- package/types-cjs/server/hydration.d.cts +18 -1
- package/types-cjs/server/signals.d.cts +29 -9
package/dist/dev.cjs
CHANGED
|
@@ -294,9 +294,12 @@ function hydrateSignalFromAsyncIterable(coreFn, compute, options) {
|
|
|
294
294
|
return it;
|
|
295
295
|
}
|
|
296
296
|
};
|
|
297
|
-
return coreFn(
|
|
297
|
+
return coreFn(prev => {
|
|
298
|
+
subFetch(compute, prev);
|
|
299
|
+
return iterable;
|
|
300
|
+
}, options);
|
|
298
301
|
}
|
|
299
|
-
function hydrateStoreFromAsyncIterable(coreFn, initialValue, options) {
|
|
302
|
+
function hydrateStoreFromAsyncIterable(coreFn, fn, initialValue, options) {
|
|
300
303
|
const parent = signals.getOwner();
|
|
301
304
|
const expectedId = signals.peekNextChildId(parent);
|
|
302
305
|
if (!sharedConfig.has(expectedId)) return null;
|
|
@@ -306,6 +309,10 @@ function hydrateStoreFromAsyncIterable(coreFn, initialValue, options) {
|
|
|
306
309
|
let isFirst = true;
|
|
307
310
|
let buffered = null;
|
|
308
311
|
return coreFn(draft => {
|
|
312
|
+
const {
|
|
313
|
+
proxy
|
|
314
|
+
} = createShadowDraft(draft);
|
|
315
|
+
subFetch(fn, proxy);
|
|
309
316
|
const process = res => {
|
|
310
317
|
if (res.done) return {
|
|
311
318
|
done: true,
|
|
@@ -313,11 +320,16 @@ function hydrateStoreFromAsyncIterable(coreFn, initialValue, options) {
|
|
|
313
320
|
};
|
|
314
321
|
if (isFirst) {
|
|
315
322
|
isFirst = false;
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
323
|
+
signals.setSnapshotCapture(false);
|
|
324
|
+
try {
|
|
325
|
+
if (Array.isArray(res.value)) {
|
|
326
|
+
for (let i = 0; i < res.value.length; i++) draft[i] = res.value[i];
|
|
327
|
+
draft.length = res.value.length;
|
|
328
|
+
} else {
|
|
329
|
+
Object.assign(draft, res.value);
|
|
330
|
+
}
|
|
331
|
+
} finally {
|
|
332
|
+
signals.setSnapshotCapture(true);
|
|
321
333
|
}
|
|
322
334
|
} else {
|
|
323
335
|
applyPatches(draft, res.value);
|
|
@@ -386,13 +398,6 @@ function hydratedCreateMemo(compute, options) {
|
|
|
386
398
|
setHydrated(true);
|
|
387
399
|
return memo;
|
|
388
400
|
}
|
|
389
|
-
if (ssrSource === "initial") {
|
|
390
|
-
return signals.createMemo(prev => {
|
|
391
|
-
if (!sharedConfig.hydrating) return compute(prev);
|
|
392
|
-
subFetch(compute, prev);
|
|
393
|
-
return prev;
|
|
394
|
-
}, options);
|
|
395
|
-
}
|
|
396
401
|
const aiResult = hydrateSignalFromAsyncIterable(signals.createMemo, compute, options);
|
|
397
402
|
if (aiResult !== null) return aiResult;
|
|
398
403
|
return signals.createMemo(prev => readSerializedOrCompute(compute, prev), options);
|
|
@@ -412,13 +417,6 @@ function hydratedCreateSignal(fn, second) {
|
|
|
412
417
|
setHydrated(true);
|
|
413
418
|
return sig;
|
|
414
419
|
}
|
|
415
|
-
if (ssrSource === "initial") {
|
|
416
|
-
return signals.createSignal(prev => {
|
|
417
|
-
if (!sharedConfig.hydrating) return fn(prev);
|
|
418
|
-
subFetch(fn, prev);
|
|
419
|
-
return prev;
|
|
420
|
-
}, second);
|
|
421
|
-
}
|
|
422
420
|
const aiResult = hydrateSignalFromAsyncIterable(signals.createSignal, fn, second);
|
|
423
421
|
if (aiResult !== null) return aiResult;
|
|
424
422
|
return signals.createSignal(prev => readSerializedOrCompute(fn, prev), second);
|
|
@@ -458,13 +456,6 @@ function hydratedCreateOptimistic(fn, second) {
|
|
|
458
456
|
setHydrated(true);
|
|
459
457
|
return sig;
|
|
460
458
|
}
|
|
461
|
-
if (ssrSource === "initial") {
|
|
462
|
-
return signals.createOptimistic(prev => {
|
|
463
|
-
if (!sharedConfig.hydrating) return fn(prev);
|
|
464
|
-
subFetch(fn, prev);
|
|
465
|
-
return prev;
|
|
466
|
-
}, second);
|
|
467
|
-
}
|
|
468
459
|
const aiResult = hydrateSignalFromAsyncIterable(signals.createOptimistic, fn, second);
|
|
469
460
|
if (aiResult !== null) return aiResult;
|
|
470
461
|
return signals.createOptimistic(prev => readSerializedOrCompute(fn, prev), second);
|
|
@@ -508,7 +499,7 @@ function hydrateStoreLikeFn(coreFn, fn, initialValue, options, ssrSource) {
|
|
|
508
499
|
setHydrated(true);
|
|
509
500
|
return result;
|
|
510
501
|
}
|
|
511
|
-
const aiResult = hydrateStoreFromAsyncIterable(coreFn, initialValue, options);
|
|
502
|
+
const aiResult = hydrateStoreFromAsyncIterable(coreFn, fn, initialValue, options);
|
|
512
503
|
if (aiResult !== null) return aiResult;
|
|
513
504
|
return coreFn(wrapStoreFn(fn), initialValue, options);
|
|
514
505
|
}
|
|
@@ -516,21 +507,18 @@ function hydratedCreateStore(first, second, third) {
|
|
|
516
507
|
if (typeof first !== "function" || !sharedConfig.hydrating) return signals.createStore(first, second, third);
|
|
517
508
|
markTopLevelSnapshotScope();
|
|
518
509
|
const ssrSource = third?.ssrSource;
|
|
519
|
-
if (ssrSource === "initial") return signals.createStore(second ?? {});
|
|
520
510
|
return hydrateStoreLikeFn(signals.createStore, first, second ?? {}, third, ssrSource);
|
|
521
511
|
}
|
|
522
512
|
function hydratedCreateOptimisticStore(first, second, third) {
|
|
523
513
|
if (typeof first !== "function" || !sharedConfig.hydrating) return signals.createOptimisticStore(first, second, third);
|
|
524
514
|
markTopLevelSnapshotScope();
|
|
525
515
|
const ssrSource = third?.ssrSource;
|
|
526
|
-
if (ssrSource === "initial") return signals.createOptimisticStore(second ?? {});
|
|
527
516
|
return hydrateStoreLikeFn(signals.createOptimisticStore, first, second ?? {}, third, ssrSource);
|
|
528
517
|
}
|
|
529
518
|
function hydratedCreateProjection(fn, initialValue, options) {
|
|
530
519
|
if (!sharedConfig.hydrating) return signals.createProjection(fn, initialValue, options);
|
|
531
520
|
markTopLevelSnapshotScope();
|
|
532
521
|
const ssrSource = options?.ssrSource;
|
|
533
|
-
if (ssrSource === "initial") return signals.createProjection(draft => draft, initialValue, options);
|
|
534
522
|
return hydrateStoreLikeFn(signals.createProjection, fn, initialValue, options, ssrSource);
|
|
535
523
|
}
|
|
536
524
|
function hydratedEffect(coreFn, compute, effectFn, options) {
|
|
@@ -552,14 +540,6 @@ function hydratedEffect(coreFn, compute, effectFn, options) {
|
|
|
552
540
|
setHydrated(true);
|
|
553
541
|
return;
|
|
554
542
|
}
|
|
555
|
-
if (ssrSource === "initial") {
|
|
556
|
-
coreFn(prev => {
|
|
557
|
-
if (!sharedConfig.hydrating) return compute(prev);
|
|
558
|
-
subFetch(compute, prev);
|
|
559
|
-
return prev;
|
|
560
|
-
}, effectFn, options);
|
|
561
|
-
return;
|
|
562
|
-
}
|
|
563
543
|
markTopLevelSnapshotScope();
|
|
564
544
|
coreFn(prev => readSerializedOrCompute(compute, prev), effectFn, options);
|
|
565
545
|
}
|
|
@@ -887,7 +867,7 @@ function Loading(props) {
|
|
|
887
867
|
}
|
|
888
868
|
function Reveal(props) {
|
|
889
869
|
return signals.createRevealOrder(() => props.children, {
|
|
890
|
-
|
|
870
|
+
order: () => props.order ?? "sequential",
|
|
891
871
|
collapsed: () => !!props.collapsed
|
|
892
872
|
});
|
|
893
873
|
}
|
package/dist/dev.js
CHANGED
|
@@ -293,9 +293,12 @@ function hydrateSignalFromAsyncIterable(coreFn, compute, options) {
|
|
|
293
293
|
return it;
|
|
294
294
|
}
|
|
295
295
|
};
|
|
296
|
-
return coreFn(
|
|
296
|
+
return coreFn(prev => {
|
|
297
|
+
subFetch(compute, prev);
|
|
298
|
+
return iterable;
|
|
299
|
+
}, options);
|
|
297
300
|
}
|
|
298
|
-
function hydrateStoreFromAsyncIterable(coreFn, initialValue, options) {
|
|
301
|
+
function hydrateStoreFromAsyncIterable(coreFn, fn, initialValue, options) {
|
|
299
302
|
const parent = getOwner();
|
|
300
303
|
const expectedId = peekNextChildId(parent);
|
|
301
304
|
if (!sharedConfig.has(expectedId)) return null;
|
|
@@ -305,6 +308,10 @@ function hydrateStoreFromAsyncIterable(coreFn, initialValue, options) {
|
|
|
305
308
|
let isFirst = true;
|
|
306
309
|
let buffered = null;
|
|
307
310
|
return coreFn(draft => {
|
|
311
|
+
const {
|
|
312
|
+
proxy
|
|
313
|
+
} = createShadowDraft(draft);
|
|
314
|
+
subFetch(fn, proxy);
|
|
308
315
|
const process = res => {
|
|
309
316
|
if (res.done) return {
|
|
310
317
|
done: true,
|
|
@@ -312,11 +319,16 @@ function hydrateStoreFromAsyncIterable(coreFn, initialValue, options) {
|
|
|
312
319
|
};
|
|
313
320
|
if (isFirst) {
|
|
314
321
|
isFirst = false;
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
322
|
+
setSnapshotCapture(false);
|
|
323
|
+
try {
|
|
324
|
+
if (Array.isArray(res.value)) {
|
|
325
|
+
for (let i = 0; i < res.value.length; i++) draft[i] = res.value[i];
|
|
326
|
+
draft.length = res.value.length;
|
|
327
|
+
} else {
|
|
328
|
+
Object.assign(draft, res.value);
|
|
329
|
+
}
|
|
330
|
+
} finally {
|
|
331
|
+
setSnapshotCapture(true);
|
|
320
332
|
}
|
|
321
333
|
} else {
|
|
322
334
|
applyPatches(draft, res.value);
|
|
@@ -385,13 +397,6 @@ function hydratedCreateMemo(compute, options) {
|
|
|
385
397
|
setHydrated(true);
|
|
386
398
|
return memo;
|
|
387
399
|
}
|
|
388
|
-
if (ssrSource === "initial") {
|
|
389
|
-
return createMemo$1(prev => {
|
|
390
|
-
if (!sharedConfig.hydrating) return compute(prev);
|
|
391
|
-
subFetch(compute, prev);
|
|
392
|
-
return prev;
|
|
393
|
-
}, options);
|
|
394
|
-
}
|
|
395
400
|
const aiResult = hydrateSignalFromAsyncIterable(createMemo$1, compute, options);
|
|
396
401
|
if (aiResult !== null) return aiResult;
|
|
397
402
|
return createMemo$1(prev => readSerializedOrCompute(compute, prev), options);
|
|
@@ -411,13 +416,6 @@ function hydratedCreateSignal(fn, second) {
|
|
|
411
416
|
setHydrated(true);
|
|
412
417
|
return sig;
|
|
413
418
|
}
|
|
414
|
-
if (ssrSource === "initial") {
|
|
415
|
-
return createSignal$1(prev => {
|
|
416
|
-
if (!sharedConfig.hydrating) return fn(prev);
|
|
417
|
-
subFetch(fn, prev);
|
|
418
|
-
return prev;
|
|
419
|
-
}, second);
|
|
420
|
-
}
|
|
421
419
|
const aiResult = hydrateSignalFromAsyncIterable(createSignal$1, fn, second);
|
|
422
420
|
if (aiResult !== null) return aiResult;
|
|
423
421
|
return createSignal$1(prev => readSerializedOrCompute(fn, prev), second);
|
|
@@ -457,13 +455,6 @@ function hydratedCreateOptimistic(fn, second) {
|
|
|
457
455
|
setHydrated(true);
|
|
458
456
|
return sig;
|
|
459
457
|
}
|
|
460
|
-
if (ssrSource === "initial") {
|
|
461
|
-
return createOptimistic$1(prev => {
|
|
462
|
-
if (!sharedConfig.hydrating) return fn(prev);
|
|
463
|
-
subFetch(fn, prev);
|
|
464
|
-
return prev;
|
|
465
|
-
}, second);
|
|
466
|
-
}
|
|
467
458
|
const aiResult = hydrateSignalFromAsyncIterable(createOptimistic$1, fn, second);
|
|
468
459
|
if (aiResult !== null) return aiResult;
|
|
469
460
|
return createOptimistic$1(prev => readSerializedOrCompute(fn, prev), second);
|
|
@@ -507,7 +498,7 @@ function hydrateStoreLikeFn(coreFn, fn, initialValue, options, ssrSource) {
|
|
|
507
498
|
setHydrated(true);
|
|
508
499
|
return result;
|
|
509
500
|
}
|
|
510
|
-
const aiResult = hydrateStoreFromAsyncIterable(coreFn, initialValue, options);
|
|
501
|
+
const aiResult = hydrateStoreFromAsyncIterable(coreFn, fn, initialValue, options);
|
|
511
502
|
if (aiResult !== null) return aiResult;
|
|
512
503
|
return coreFn(wrapStoreFn(fn), initialValue, options);
|
|
513
504
|
}
|
|
@@ -515,21 +506,18 @@ function hydratedCreateStore(first, second, third) {
|
|
|
515
506
|
if (typeof first !== "function" || !sharedConfig.hydrating) return createStore$1(first, second, third);
|
|
516
507
|
markTopLevelSnapshotScope();
|
|
517
508
|
const ssrSource = third?.ssrSource;
|
|
518
|
-
if (ssrSource === "initial") return createStore$1(second ?? {});
|
|
519
509
|
return hydrateStoreLikeFn(createStore$1, first, second ?? {}, third, ssrSource);
|
|
520
510
|
}
|
|
521
511
|
function hydratedCreateOptimisticStore(first, second, third) {
|
|
522
512
|
if (typeof first !== "function" || !sharedConfig.hydrating) return createOptimisticStore$1(first, second, third);
|
|
523
513
|
markTopLevelSnapshotScope();
|
|
524
514
|
const ssrSource = third?.ssrSource;
|
|
525
|
-
if (ssrSource === "initial") return createOptimisticStore$1(second ?? {});
|
|
526
515
|
return hydrateStoreLikeFn(createOptimisticStore$1, first, second ?? {}, third, ssrSource);
|
|
527
516
|
}
|
|
528
517
|
function hydratedCreateProjection(fn, initialValue, options) {
|
|
529
518
|
if (!sharedConfig.hydrating) return createProjection$1(fn, initialValue, options);
|
|
530
519
|
markTopLevelSnapshotScope();
|
|
531
520
|
const ssrSource = options?.ssrSource;
|
|
532
|
-
if (ssrSource === "initial") return createProjection$1(draft => draft, initialValue, options);
|
|
533
521
|
return hydrateStoreLikeFn(createProjection$1, fn, initialValue, options, ssrSource);
|
|
534
522
|
}
|
|
535
523
|
function hydratedEffect(coreFn, compute, effectFn, options) {
|
|
@@ -551,14 +539,6 @@ function hydratedEffect(coreFn, compute, effectFn, options) {
|
|
|
551
539
|
setHydrated(true);
|
|
552
540
|
return;
|
|
553
541
|
}
|
|
554
|
-
if (ssrSource === "initial") {
|
|
555
|
-
coreFn(prev => {
|
|
556
|
-
if (!sharedConfig.hydrating) return compute(prev);
|
|
557
|
-
subFetch(compute, prev);
|
|
558
|
-
return prev;
|
|
559
|
-
}, effectFn, options);
|
|
560
|
-
return;
|
|
561
|
-
}
|
|
562
542
|
markTopLevelSnapshotScope();
|
|
563
543
|
coreFn(prev => readSerializedOrCompute(compute, prev), effectFn, options);
|
|
564
544
|
}
|
|
@@ -886,7 +866,7 @@ function Loading(props) {
|
|
|
886
866
|
}
|
|
887
867
|
function Reveal(props) {
|
|
888
868
|
return createRevealOrder(() => props.children, {
|
|
889
|
-
|
|
869
|
+
order: () => props.order ?? "sequential",
|
|
890
870
|
collapsed: () => !!props.collapsed
|
|
891
871
|
});
|
|
892
872
|
}
|
package/dist/server.cjs
CHANGED
|
@@ -129,7 +129,7 @@ function createMemo(compute, options) {
|
|
|
129
129
|
}
|
|
130
130
|
}
|
|
131
131
|
const ssrSource = options?.ssrSource;
|
|
132
|
-
if (ssrSource === "
|
|
132
|
+
if (ssrSource === "client") {
|
|
133
133
|
comp.computed = true;
|
|
134
134
|
} else if (!options?.lazy) {
|
|
135
135
|
update();
|
|
@@ -325,7 +325,7 @@ function closeAsyncIterator(iter, value) {
|
|
|
325
325
|
}
|
|
326
326
|
function serverEffect(compute, effectFn, options) {
|
|
327
327
|
const ssrSource = options?.ssrSource;
|
|
328
|
-
if (ssrSource === "client"
|
|
328
|
+
if (ssrSource === "client") {
|
|
329
329
|
signals.createOwner();
|
|
330
330
|
return;
|
|
331
331
|
}
|
|
@@ -406,7 +406,7 @@ function createProjection(fn, initialValue, options) {
|
|
|
406
406
|
const ctx = sharedConfig.context;
|
|
407
407
|
const owner = signals.createOwner();
|
|
408
408
|
const [state] = createStore(initialValue);
|
|
409
|
-
if (options?.ssrSource === "
|
|
409
|
+
if (options?.ssrSource === "client") {
|
|
410
410
|
return state;
|
|
411
411
|
}
|
|
412
412
|
let disposed = false;
|
|
@@ -826,12 +826,6 @@ function ssrHandleError(err) {
|
|
|
826
826
|
}
|
|
827
827
|
throw err;
|
|
828
828
|
}
|
|
829
|
-
class InvalidTopLevelAsyncReadError extends Error {
|
|
830
|
-
constructor() {
|
|
831
|
-
super("Async values must be read within a tracking scope (JSX, a memo, or an effect's compute function).");
|
|
832
|
-
this.name = "InvalidTopLevelAsyncReadError";
|
|
833
|
-
}
|
|
834
|
-
}
|
|
835
829
|
function createLoadingBoundary(fn, fallback, options) {
|
|
836
830
|
const currentCtx = sharedConfig.context;
|
|
837
831
|
if (!currentCtx) {
|
|
@@ -846,6 +840,7 @@ function createLoadingBoundary(fn, fallback, options) {
|
|
|
846
840
|
o.id = id + "00";
|
|
847
841
|
let done;
|
|
848
842
|
let handledRenderError;
|
|
843
|
+
let retryPromise;
|
|
849
844
|
let serializeBuffer = [];
|
|
850
845
|
const bufferedCtx = Object.create(ctx);
|
|
851
846
|
bufferedCtx.serialize = (id, value, deferStream) => {
|
|
@@ -889,21 +884,26 @@ function createLoadingBoundary(fn, fallback, options) {
|
|
|
889
884
|
function runDiscovery() {
|
|
890
885
|
o.dispose(false);
|
|
891
886
|
serializeBuffer = [];
|
|
887
|
+
retryPromise = undefined;
|
|
892
888
|
return runLoadingPhase(() => {
|
|
893
889
|
try {
|
|
894
890
|
return ctx.resolve(fn());
|
|
895
891
|
} catch (err) {
|
|
896
|
-
if (err instanceof signals.NotReadyError)
|
|
892
|
+
if (err instanceof signals.NotReadyError) {
|
|
893
|
+
retryPromise = err.source;
|
|
894
|
+
return undefined;
|
|
895
|
+
}
|
|
897
896
|
throw err;
|
|
898
897
|
}
|
|
899
898
|
});
|
|
900
899
|
}
|
|
901
900
|
let ret = runDiscovery();
|
|
902
|
-
if (!ret?.p?.length) {
|
|
901
|
+
if (!retryPromise && !ret?.p?.length) {
|
|
903
902
|
commitBoundaryState();
|
|
904
903
|
return () => ret;
|
|
905
904
|
}
|
|
906
|
-
const
|
|
905
|
+
const regResult = revealGroup ? revealGroup.register(id) : null;
|
|
906
|
+
const collapseFallback = regResult?.collapseFallback ?? false;
|
|
907
907
|
if (collapseFallback && !ctx.async) {
|
|
908
908
|
commitBoundaryState();
|
|
909
909
|
ctx.serialize(id, "$$f");
|
|
@@ -924,6 +924,10 @@ function createLoadingBoundary(fn, fallback, options) {
|
|
|
924
924
|
done = ctx.registerFragment(id, regOpts);
|
|
925
925
|
(async () => {
|
|
926
926
|
try {
|
|
927
|
+
while (retryPromise) {
|
|
928
|
+
await retryPromise.catch(() => {});
|
|
929
|
+
ret = runDiscovery();
|
|
930
|
+
}
|
|
927
931
|
commitBoundaryState();
|
|
928
932
|
while (ret.p.length) {
|
|
929
933
|
await Promise.all(ret.p).catch(() => {});
|
|
@@ -1026,15 +1030,16 @@ function Loading(props) {
|
|
|
1026
1030
|
function Reveal(props) {
|
|
1027
1031
|
const o = signals.createOwner();
|
|
1028
1032
|
const id = o.id;
|
|
1029
|
-
const
|
|
1030
|
-
const collapsed = !!props.collapsed;
|
|
1033
|
+
const order = props.order ?? "sequential";
|
|
1034
|
+
const collapsed = order === "sequential" && !!props.collapsed;
|
|
1031
1035
|
if (!sharedConfig.context?.async) {
|
|
1032
1036
|
const parent = signals.getOwner();
|
|
1033
1037
|
const parentGroup = parent ? signals.runWithOwner(parent, () => signals.getContext(RevealGroupContext)) : null;
|
|
1034
1038
|
let collapsedByParent = false;
|
|
1035
1039
|
if (parentGroup) {
|
|
1036
|
-
|
|
1037
|
-
|
|
1040
|
+
const reg = parentGroup.register(id);
|
|
1041
|
+
collapsedByParent = reg.collapseFallback;
|
|
1042
|
+
if (order === "together" || collapsed) console.warn("Nested <Reveal> with collapsed/together won't coordinate correctly with renderToString. Use renderToStream for full support.");
|
|
1038
1043
|
}
|
|
1039
1044
|
let count = 0;
|
|
1040
1045
|
return signals.runWithOwner(o, () => {
|
|
@@ -1042,8 +1047,11 @@ function Reveal(props) {
|
|
|
1042
1047
|
id,
|
|
1043
1048
|
register(_key) {
|
|
1044
1049
|
count++;
|
|
1045
|
-
|
|
1046
|
-
return
|
|
1050
|
+
const collapseFallback = collapsedByParent || order === "sequential" && collapsed && count > 1;
|
|
1051
|
+
return {
|
|
1052
|
+
collapseFallback,
|
|
1053
|
+
held: false
|
|
1054
|
+
};
|
|
1047
1055
|
},
|
|
1048
1056
|
onResolved() {}
|
|
1049
1057
|
});
|
|
@@ -1053,58 +1061,129 @@ function Reveal(props) {
|
|
|
1053
1061
|
const ctx = sharedConfig.context;
|
|
1054
1062
|
const keys = [];
|
|
1055
1063
|
const resolved = new Set();
|
|
1064
|
+
const minimallyResolved = new Set();
|
|
1056
1065
|
const composites = new Map();
|
|
1066
|
+
const activated = new Set();
|
|
1067
|
+
const stash = [];
|
|
1068
|
+
const collapsedLeafKeys = [];
|
|
1057
1069
|
let frontier = 0;
|
|
1070
|
+
let heldByParent = false;
|
|
1071
|
+
let collapsedByParent = false;
|
|
1072
|
+
let selfMinimallyResolved = false;
|
|
1073
|
+
let notifiedParentDone = false;
|
|
1058
1074
|
const parent = signals.getOwner();
|
|
1059
1075
|
const parentGroup = parent ? signals.runWithOwner(parent, () => signals.getContext(RevealGroupContext)) : null;
|
|
1060
|
-
let collapsedByParent = false;
|
|
1061
1076
|
if (parentGroup) {
|
|
1062
|
-
|
|
1077
|
+
const reg = parentGroup.register(id, {
|
|
1063
1078
|
onActivate: () => {
|
|
1064
|
-
|
|
1065
|
-
|
|
1079
|
+
if (!heldByParent) return;
|
|
1080
|
+
heldByParent = false;
|
|
1081
|
+
if (collapsedByParent) {
|
|
1082
|
+
collapsedByParent = false;
|
|
1083
|
+
if (collapsedLeafKeys.length) {
|
|
1084
|
+
ctx.revealFallbacks?.([...collapsedLeafKeys]);
|
|
1085
|
+
collapsedLeafKeys.length = 0;
|
|
1086
|
+
}
|
|
1087
|
+
}
|
|
1088
|
+
if (order === "sequential") advanceFrontier();else if (order === "together") checkTogetherRelease();else naturalRelease();
|
|
1066
1089
|
}
|
|
1067
1090
|
});
|
|
1091
|
+
collapsedByParent = reg.collapseFallback;
|
|
1092
|
+
heldByParent = reg.held;
|
|
1068
1093
|
}
|
|
1069
1094
|
function notifyParentIfDone() {
|
|
1095
|
+
if (notifiedParentDone) return;
|
|
1070
1096
|
if (parentGroup && resolved.size === keys.length) {
|
|
1097
|
+
notifiedParentDone = true;
|
|
1071
1098
|
parentGroup.onResolved(id);
|
|
1072
1099
|
}
|
|
1073
1100
|
}
|
|
1101
|
+
function activateComposite(key) {
|
|
1102
|
+
if (activated.has(key)) return;
|
|
1103
|
+
activated.add(key);
|
|
1104
|
+
composites.get(key)();
|
|
1105
|
+
}
|
|
1106
|
+
function updateSelfMinimallyResolved() {
|
|
1107
|
+
if (selfMinimallyResolved) return;
|
|
1108
|
+
if (keys.length === 0) selfMinimallyResolved = true;else if (order === "together") selfMinimallyResolved = minimallyResolved.size === keys.length;else if (order === "sequential") selfMinimallyResolved = minimallyResolved.has(keys[0]);
|
|
1109
|
+
else selfMinimallyResolved = resolved.size > 0;
|
|
1110
|
+
if (selfMinimallyResolved) parentGroup?.onMinimallyResolved?.(id);
|
|
1111
|
+
}
|
|
1074
1112
|
function advanceFrontier() {
|
|
1113
|
+
if (heldByParent) return;
|
|
1075
1114
|
while (frontier < keys.length && resolved.has(keys[frontier])) {
|
|
1076
|
-
|
|
1115
|
+
const k = keys[frontier];
|
|
1116
|
+
if (composites.has(k)) activateComposite(k);else ctx.revealFragments?.([k]);
|
|
1077
1117
|
frontier++;
|
|
1078
1118
|
}
|
|
1079
1119
|
if (frontier < keys.length) {
|
|
1080
|
-
const
|
|
1081
|
-
if (
|
|
1120
|
+
const k = keys[frontier];
|
|
1121
|
+
if (composites.has(k)) activateComposite(k);else if (order === "sequential" && collapsed) ctx.revealFallbacks?.([k]);
|
|
1082
1122
|
}
|
|
1083
1123
|
notifyParentIfDone();
|
|
1084
1124
|
}
|
|
1125
|
+
function checkTogetherRelease() {
|
|
1126
|
+
if (order !== "together" || heldByParent) return;
|
|
1127
|
+
if (minimallyResolved.size < keys.length) return;
|
|
1128
|
+
if (stash.length) {
|
|
1129
|
+
ctx.revealFragments?.([...stash]);
|
|
1130
|
+
stash.length = 0;
|
|
1131
|
+
}
|
|
1132
|
+
composites.forEach((_, key) => activateComposite(key));
|
|
1133
|
+
notifyParentIfDone();
|
|
1134
|
+
}
|
|
1135
|
+
function naturalRelease() {
|
|
1136
|
+
if (stash.length) {
|
|
1137
|
+
ctx.revealFragments?.([...stash]);
|
|
1138
|
+
stash.length = 0;
|
|
1139
|
+
}
|
|
1140
|
+
composites.forEach((_, key) => activateComposite(key));
|
|
1141
|
+
notifyParentIfDone();
|
|
1142
|
+
}
|
|
1085
1143
|
return signals.runWithOwner(o, () => {
|
|
1086
1144
|
signals.setContext(RevealGroupContext, {
|
|
1087
1145
|
id,
|
|
1088
1146
|
register(key, options) {
|
|
1089
1147
|
keys.push(key);
|
|
1090
|
-
|
|
1091
|
-
if (
|
|
1092
|
-
|
|
1148
|
+
const isComposite = !!options?.onActivate;
|
|
1149
|
+
if (isComposite) composites.set(key, options.onActivate);
|
|
1150
|
+
const selfCollapse = order === "sequential" && collapsed && keys.length > 1;
|
|
1151
|
+
const collapseFallback = collapsedByParent || selfCollapse;
|
|
1152
|
+
if (collapseFallback && !isComposite) collapsedLeafKeys.push(key);
|
|
1153
|
+
let held = heldByParent;
|
|
1154
|
+
if (!held) {
|
|
1155
|
+
if (order === "together") held = true;else if (order === "sequential" && keys.length > 1) held = true;
|
|
1156
|
+
}
|
|
1157
|
+
return {
|
|
1158
|
+
collapseFallback,
|
|
1159
|
+
held
|
|
1160
|
+
};
|
|
1093
1161
|
},
|
|
1094
1162
|
onResolved(key) {
|
|
1095
1163
|
resolved.add(key);
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1164
|
+
const isLeaf = !composites.has(key);
|
|
1165
|
+
if (isLeaf) {
|
|
1166
|
+
if (order === "together") {
|
|
1167
|
+
stash.push(key);
|
|
1168
|
+
} else if (order === "natural" && heldByParent) {
|
|
1169
|
+
stash.push(key);
|
|
1170
|
+
} else if (order === "natural") {
|
|
1171
|
+
ctx.revealFragments?.([key]);
|
|
1104
1172
|
}
|
|
1173
|
+
markMinimallyResolved(key);
|
|
1174
|
+
if (order === "sequential" && !heldByParent) advanceFrontier();
|
|
1175
|
+
if (order === "natural") updateSelfMinimallyResolved();
|
|
1105
1176
|
} else {
|
|
1106
|
-
|
|
1177
|
+
if (!heldByParent) {
|
|
1178
|
+
if (order === "sequential") advanceFrontier();else if (order === "natural") activateComposite(key);
|
|
1179
|
+
}
|
|
1180
|
+
if (order === "together") checkTogetherRelease();
|
|
1181
|
+
if (order === "natural") updateSelfMinimallyResolved();
|
|
1107
1182
|
}
|
|
1183
|
+
notifyParentIfDone();
|
|
1184
|
+
},
|
|
1185
|
+
onMinimallyResolved(key) {
|
|
1186
|
+
markMinimallyResolved(key);
|
|
1108
1187
|
}
|
|
1109
1188
|
});
|
|
1110
1189
|
const result = props.children;
|
|
@@ -1113,6 +1192,12 @@ function Reveal(props) {
|
|
|
1113
1192
|
}
|
|
1114
1193
|
return result;
|
|
1115
1194
|
});
|
|
1195
|
+
function markMinimallyResolved(key) {
|
|
1196
|
+
if (minimallyResolved.has(key)) return;
|
|
1197
|
+
minimallyResolved.add(key);
|
|
1198
|
+
updateSelfMinimallyResolved();
|
|
1199
|
+
if (order === "together") checkTogetherRelease();
|
|
1200
|
+
}
|
|
1116
1201
|
}
|
|
1117
1202
|
|
|
1118
1203
|
const DEV = undefined;
|