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 CHANGED
@@ -294,9 +294,12 @@ function hydrateSignalFromAsyncIterable(coreFn, compute, options) {
294
294
  return it;
295
295
  }
296
296
  };
297
- return coreFn(() => iterable, options);
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
- if (Array.isArray(res.value)) {
317
- for (let i = 0; i < res.value.length; i++) draft[i] = res.value[i];
318
- draft.length = res.value.length;
319
- } else {
320
- Object.assign(draft, res.value);
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
- together: () => !!props.together,
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(() => iterable, options);
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
- if (Array.isArray(res.value)) {
316
- for (let i = 0; i < res.value.length; i++) draft[i] = res.value[i];
317
- draft.length = res.value.length;
318
- } else {
319
- Object.assign(draft, res.value);
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
- together: () => !!props.together,
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 === "initial" || ssrSource === "client") {
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" || ssrSource === "initial") {
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 === "initial" || options?.ssrSource === "client") {
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) throw new InvalidTopLevelAsyncReadError();
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 collapseFallback = revealGroup ? revealGroup.register(id) : false;
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 together = !!props.together;
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
- collapsedByParent = parentGroup.register(id);
1037
- if (collapsed || together) console.warn("Nested <Reveal> with collapsed/together won't coordinate correctly with renderToString. Use renderToStream for full support.");
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
- if (collapsedByParent) return true;
1046
- return !together && collapsed && count > 1;
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
- collapsedByParent = parentGroup.register(id, {
1077
+ const reg = parentGroup.register(id, {
1063
1078
  onActivate: () => {
1064
- collapsedByParent = false;
1065
- advanceFrontier();
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
- if (!composites.has(keys[frontier])) ctx.revealFragments?.([keys[frontier]]);
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 activate = composites.get(keys[frontier]);
1081
- if (activate) activate();else if (!together && collapsed) ctx.revealFallbacks?.(keys.slice(frontier));
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
- if (options?.onActivate) composites.set(key, options.onActivate);
1091
- if (collapsedByParent) return true;
1092
- return !together && collapsed && keys.length > 1;
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
- if (collapsedByParent) {
1097
- notifyParentIfDone();
1098
- return;
1099
- }
1100
- if (together) {
1101
- if (resolved.size === keys.length) {
1102
- ctx.revealFragments?.(id);
1103
- notifyParentIfDone();
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
- advanceFrontier();
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;