@solidjs/signals 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.js CHANGED
@@ -240,6 +240,23 @@ let inTrackedQueueCallback = false;
240
240
  let _enforceLoadingBoundary = false;
241
241
  let _hitUnhandledAsync = false;
242
242
  let stashedOptimisticReads = null;
243
+ const transientStoreNodes = new Set();
244
+ function registerTransientStoreNode(node) {
245
+ transientStoreNodes.add(node);
246
+ }
247
+ function sweepTransientStoreNodes() {
248
+ if (transientStoreNodes.size === 0) return;
249
+ for (const node of transientStoreNodes) {
250
+ if (node._subs !== null) {
251
+ transientStoreNodes.delete(node);
252
+ continue;
253
+ }
254
+ if (node._pendingValue !== NOT_PENDING) continue;
255
+ if (node._overrideValue !== undefined && node._overrideValue !== NOT_PENDING) continue;
256
+ transientStoreNodes.delete(node);
257
+ node._unobserved?.();
258
+ }
259
+ }
243
260
  function resetUnhandledAsync() {
244
261
  _hitUnhandledAsync = false;
245
262
  }
@@ -589,6 +606,7 @@ function finalizePureQueue(completingTransition = null, incomplete = false) {
589
606
  optimisticStores.clear();
590
607
  schedule();
591
608
  }
609
+ sweepTransientStoreNodes();
592
610
  cleanupCompletedLanes(completingTransition);
593
611
  }
594
612
  }
@@ -1383,7 +1401,9 @@ function recompute(el, create = false) {
1383
1401
  if (lane) currentOptimisticLane = lane;
1384
1402
  }
1385
1403
  try {
1386
- value = handleAsync(el, el._fn(value));
1404
+ const prevInFlight = el._inFlight;
1405
+ const fnResult = el._fn(value);
1406
+ value = el._inFlight !== prevInFlight ? fnResult : handleAsync(el, fnResult);
1387
1407
  clearStatus(el, create);
1388
1408
  const resolvedLane = resolveLane(el);
1389
1409
  if (resolvedLane) {
@@ -1482,7 +1502,7 @@ function updateIfNecessary(el) {
1482
1502
  }
1483
1503
  el._flags = el._flags & (REACTIVE_SNAPSHOT_STALE | REACTIVE_IN_HEAP | REACTIVE_IN_HEAP_HEIGHT);
1484
1504
  }
1485
- function computed(fn, initialValue, options) {
1505
+ function computed(fn, options) {
1486
1506
  const transparent = options?.transparent ?? false;
1487
1507
  const self = {
1488
1508
  id:
@@ -1497,7 +1517,7 @@ function computed(fn, initialValue, options) {
1497
1517
  _context: context?._context ?? defaultContext,
1498
1518
  _childCount: 0,
1499
1519
  _fn: fn,
1500
- _value: initialValue,
1520
+ _value: undefined,
1501
1521
  _height: 0,
1502
1522
  _child: null,
1503
1523
  _nextHeap: undefined,
@@ -1592,8 +1612,8 @@ function optimisticSignal(v, options) {
1592
1612
  s._overrideValue = NOT_PENDING;
1593
1613
  return s;
1594
1614
  }
1595
- function optimisticComputed(fn, initialValue, options) {
1596
- const c = computed(fn, initialValue, options);
1615
+ function optimisticComputed(fn, options) {
1616
+ const c = computed(fn, options);
1597
1617
  c._overrideValue = NOT_PENDING;
1598
1618
  return c;
1599
1619
  }
@@ -2041,26 +2061,23 @@ function hasContext(context, owner) {
2041
2061
  function isUndefined(value) {
2042
2062
  return typeof value === "undefined";
2043
2063
  }
2044
- function effect(compute, effect, error, initialValue, options) {
2064
+ function effect(compute, effect, error, options) {
2045
2065
  let initialized = false;
2046
- const node = computed(
2047
- options?.render ? p => staleValues(() => compute(p)) : compute,
2048
- initialValue,
2049
- {
2050
- ...options,
2051
- equals: () => {
2052
- node._modified = !node._error;
2053
- if (initialized) node._queue.enqueue(node._type, runEffect.bind(node));
2054
- return false;
2055
- },
2056
- lazy: true
2057
- }
2058
- );
2059
- node._prevValue = initialValue;
2066
+ const isUser = !!options?.user;
2067
+ const node = computed(isUser ? compute : p => staleValues(() => compute(p)), {
2068
+ ...options,
2069
+ equals: () => {
2070
+ node._modified = !node._error;
2071
+ if (initialized) node._queue.enqueue(node._type, runEffect.bind(node));
2072
+ return false;
2073
+ },
2074
+ lazy: true
2075
+ });
2076
+ node._prevValue = undefined;
2060
2077
  node._effectFn = effect;
2061
2078
  node._errorFn = error;
2062
2079
  node._cleanup = undefined;
2063
- node._type = options?.render ? EFFECT_RENDER : EFFECT_USER;
2080
+ node._type = isUser ? EFFECT_USER : EFFECT_RENDER;
2064
2081
  node._notifyStatus = (status, error) => {
2065
2082
  const actualStatus = status !== undefined ? status : node._statusFlags;
2066
2083
  const actualError = error !== undefined ? error : node._error;
@@ -2085,23 +2102,24 @@ function effect(compute, effect, error, initialValue, options) {
2085
2102
  if (_hitUnhandledAsync) {
2086
2103
  resetUnhandledAsync();
2087
2104
  if (!node._queue.notify(node, STATUS_ERROR, STATUS_ERROR)) {
2088
- const message = "An async value must be rendered inside a Loading boundary.";
2105
+ const message =
2106
+ "An async value was read outside a Loading boundary. The root mount will be deferred until all pending async settles.";
2089
2107
  emitDiagnostic({
2090
2108
  code: "ASYNC_OUTSIDE_LOADING_BOUNDARY",
2091
2109
  kind: "async",
2092
- severity: "error",
2110
+ severity: "warn",
2093
2111
  message: message,
2094
2112
  ownerId: node.id,
2095
2113
  ownerName: node._name
2096
2114
  });
2097
- throw new Error(message);
2115
+ console.warn(message);
2098
2116
  }
2099
2117
  }
2100
2118
  }
2101
2119
  };
2102
2120
  recompute(node, true);
2103
2121
  !options?.defer &&
2104
- (node._type === EFFECT_USER
2122
+ (node._type === EFFECT_USER || options?.schedule
2105
2123
  ? node._queue.enqueue(node._type, runEffect.bind(node))
2106
2124
  : runEffect.call(node));
2107
2125
  initialized = true;
@@ -2169,7 +2187,6 @@ function trackedEffect(fn, options) {
2169
2187
  }
2170
2188
  node._cleanup = cleanup;
2171
2189
  },
2172
- undefined,
2173
2190
  { ...options, lazy: true }
2174
2191
  );
2175
2192
  node._cleanup = undefined;
@@ -2280,7 +2297,7 @@ function accessor(node) {
2280
2297
  }
2281
2298
  function createSignal(first, second) {
2282
2299
  if (typeof first === "function") {
2283
- const node = computed(first, undefined, second);
2300
+ const node = computed(first, second);
2284
2301
  node._preventAutoDisposal = true;
2285
2302
  return [accessor(node), setSignal.bind(null, node)];
2286
2303
  }
@@ -2289,20 +2306,17 @@ function createSignal(first, second) {
2289
2306
  return [accessor(node), setSignal.bind(null, node)];
2290
2307
  }
2291
2308
  function createMemo(compute, options) {
2292
- let node = computed(compute, undefined, options);
2309
+ let node = computed(compute, options);
2293
2310
  return accessor(node);
2294
2311
  }
2295
2312
  function createEffect(compute, effectFn, options) {
2296
- effect(compute, effectFn.effect || effectFn, effectFn.error, undefined, {
2297
- ...options,
2298
- name: options?.name ?? "effect"
2313
+ effect(compute, effectFn.effect || effectFn, effectFn.error, {
2314
+ user: true,
2315
+ ...{ ...options, name: options?.name ?? "effect" }
2299
2316
  });
2300
2317
  }
2301
2318
  function createRenderEffect(compute, effectFn, options) {
2302
- effect(compute, effectFn, undefined, undefined, {
2303
- render: true,
2304
- ...{ ...options, name: options?.name ?? "effect" }
2305
- });
2319
+ effect(compute, effectFn, undefined, { ...options, name: options?.name ?? "effect" });
2306
2320
  }
2307
2321
  function createTrackedEffect(compute, options) {
2308
2322
  trackedEffect(compute, { ...options, name: options?.name ?? "trackedEffect" });
@@ -2327,8 +2341,11 @@ function createReaction(effectFn, options) {
2327
2341
  dispose(node);
2328
2342
  },
2329
2343
  effectFn.error,
2330
- undefined,
2331
- { defer: true, ...(true ? { ...options, name: options?.name ?? "effect" } : options) }
2344
+ {
2345
+ ...(true ? { ...options, name: options?.name ?? "effect" } : options),
2346
+ user: true,
2347
+ defer: true
2348
+ }
2332
2349
  );
2333
2350
  });
2334
2351
  };
@@ -2355,7 +2372,7 @@ function resolve(fn) {
2355
2372
  }
2356
2373
  function createOptimistic(first, second) {
2357
2374
  if (typeof first === "function") {
2358
- const node = optimisticComputed(first, undefined, second);
2375
+ const node = optimisticComputed(first, second);
2359
2376
  node._preventAutoDisposal = true;
2360
2377
  return [accessor(node), setSignal.bind(null, node)];
2361
2378
  }
@@ -2543,31 +2560,39 @@ function createProjectionInternal(fn, seed, options) {
2543
2560
  return wrapped;
2544
2561
  };
2545
2562
  const wrappedStore = wrapProjection(seed);
2546
- node = computed(() => {
2547
- const owner = getOwner();
2548
- let settled = false;
2549
- let result;
2550
- const draft = new Proxy(
2551
- wrappedStore,
2552
- createWriteTraps(() => !settled || owner._inFlight === result)
2553
- );
2554
- storeSetter(draft, s => {
2555
- result = fn(s);
2556
- settled = true;
2557
- const value = handleAsync(owner, result, value => {
2558
- value !== s &&
2559
- value !== undefined &&
2560
- storeSetter(wrappedStore, reconcile(value, options?.key || "id"));
2561
- });
2562
- value !== s && value !== undefined && reconcile(value, options?.key || "id")(wrappedStore);
2563
- });
2564
- });
2563
+ node = computed(
2564
+ () => {
2565
+ if (!node) node = getOwner();
2566
+ runProjectionComputed(wrappedStore, fn, options?.key || "id");
2567
+ },
2568
+ options?.name ? { name: options.name } : undefined
2569
+ );
2565
2570
  node._preventAutoDisposal = true;
2566
2571
  return { store: wrappedStore, node: node };
2567
2572
  }
2568
2573
  function createProjection(fn, seed, options) {
2569
2574
  return createProjectionInternal(fn, seed, options).store;
2570
2575
  }
2576
+ function runProjectionComputed(wrappedStore, fn, key, wrapCommit) {
2577
+ const owner = getOwner();
2578
+ let settled = false;
2579
+ let result;
2580
+ const draft = new Proxy(
2581
+ wrappedStore,
2582
+ createWriteTraps(() => !settled || owner._inFlight === result)
2583
+ );
2584
+ storeSetter(draft, s => {
2585
+ result = fn(s);
2586
+ settled = true;
2587
+ const commit = v => {
2588
+ if (v === s || v === undefined) return;
2589
+ const write = () => storeSetter(wrappedStore, reconcile(v, key));
2590
+ wrapCommit ? wrapCommit(write) : write();
2591
+ };
2592
+ commit(handleAsync(owner, result, commit));
2593
+ });
2594
+ return owner;
2595
+ }
2571
2596
  function createWriteTraps(isActive) {
2572
2597
  const traps = {
2573
2598
  get(_, prop) {
@@ -2677,7 +2702,7 @@ function getNode(nodes, property, value, firewall, equals = isEqual, optimistic,
2677
2702
  {
2678
2703
  equals: equals,
2679
2704
  unobserved() {
2680
- delete nodes[property];
2705
+ if (nodes[property] === s) delete nodes[property];
2681
2706
  }
2682
2707
  },
2683
2708
  firewall
@@ -2751,19 +2776,51 @@ function prepareStoreWrite(target, store, property) {
2751
2776
  if (useOptimistic) trackOptimisticStore(store);
2752
2777
  return { base: base, overrideKey: overrideKey, state: state };
2753
2778
  }
2754
- function notifyStoreProperty(target, property, mode, value) {
2755
- if (target[STORE_HAS]?.[property]) setSignal(target[STORE_HAS][property], mode !== "delete");
2779
+ function upsertStoreNode(target, nodes, property, prev, snapshotProps) {
2780
+ if (nodes[property]) return nodes[property];
2781
+ const initial = isWrappable(prev) ? wrap(prev, target) : prev;
2782
+ const node = getNode(
2783
+ nodes,
2784
+ property,
2785
+ initial,
2786
+ target[STORE_FIREWALL],
2787
+ isEqual,
2788
+ target[STORE_OPTIMISTIC],
2789
+ snapshotProps
2790
+ );
2791
+ registerTransientStoreNode(node);
2792
+ return node;
2793
+ }
2794
+ function notifyStoreProperty(target, property, mode, value, prev, prevHas) {
2795
+ const skipUpsert = projectionWriteActive || target[STORE_OPTIMISTIC];
2796
+ const newHas = mode !== "delete";
2797
+ const existingHas = target[STORE_HAS]?.[property];
2798
+ if (existingHas) {
2799
+ setSignal(existingHas, newHas);
2800
+ } else if (!skipUpsert && mode !== "invalidate" && prevHas !== newHas) {
2801
+ const hasNode = upsertStoreNode(target, getNodes(target, STORE_HAS), property, prevHas);
2802
+ setSignal(hasNode, newHas);
2803
+ }
2756
2804
  const nodes = getNodes(target, STORE_NODE);
2757
2805
  if (mode === "set") {
2758
- nodes[property] &&
2806
+ if (nodes[property]) {
2759
2807
  setSignal(nodes[property], () => (isWrappable(value) ? wrap(value, target) : value));
2808
+ } else if (!skipUpsert) {
2809
+ const node = upsertStoreNode(target, nodes, property, prev, target[STORE_SNAPSHOT_PROPS]);
2810
+ setSignal(node, () => (isWrappable(value) ? wrap(value, target) : value));
2811
+ }
2760
2812
  } else if (mode === "invalidate") {
2761
2813
  if (nodes[property]) {
2762
2814
  setSignal(nodes[property], {});
2763
2815
  delete nodes[property];
2764
2816
  }
2765
2817
  } else {
2766
- nodes[property] && setSignal(nodes[property], undefined);
2818
+ if (nodes[property]) {
2819
+ setSignal(nodes[property], undefined);
2820
+ } else if (!skipUpsert) {
2821
+ const node = upsertStoreNode(target, nodes, property, prev, target[STORE_SNAPSHOT_PROPS]);
2822
+ setSignal(node, undefined);
2823
+ }
2767
2824
  }
2768
2825
  nodes[$TRACK] && setSignal(nodes[$TRACK], undefined);
2769
2826
  }
@@ -2860,18 +2917,13 @@ const storeTraps = {
2860
2917
  : target[STORE_OVERRIDE] && property in target[STORE_OVERRIDE]
2861
2918
  ? target[STORE_OVERRIDE][property] !== $DELETED
2862
2919
  : property in target[STORE_VALUE];
2863
- if (!writeOnly(target[$PROXY])) {
2864
- getObserver() &&
2865
- read(
2866
- getNode(
2867
- getNodes(target, STORE_HAS),
2868
- property,
2869
- has,
2870
- target[STORE_FIREWALL],
2871
- isEqual,
2872
- target[STORE_OPTIMISTIC]
2873
- )
2874
- );
2920
+ if (writeOnly(target[$PROXY])) return has;
2921
+ const nodes = getNodes(target, STORE_HAS);
2922
+ if (nodes[property]) return read(nodes[property]);
2923
+ if (getObserver()) {
2924
+ return read(
2925
+ getNode(nodes, property, has, target[STORE_FIREWALL], isEqual, target[STORE_OPTIMISTIC])
2926
+ );
2875
2927
  }
2876
2928
  return has;
2877
2929
  },
@@ -2890,6 +2942,12 @@ const storeTraps = {
2890
2942
  : target[STORE_OVERRIDE] && property in target[STORE_OVERRIDE]
2891
2943
  ? target[STORE_OVERRIDE][property]
2892
2944
  : base;
2945
+ const prevHas =
2946
+ target[STORE_OPTIMISTIC_OVERRIDE] && property in target[STORE_OPTIMISTIC_OVERRIDE]
2947
+ ? target[STORE_OPTIMISTIC_OVERRIDE][property] !== $DELETED
2948
+ : target[STORE_OVERRIDE] && property in target[STORE_OVERRIDE]
2949
+ ? target[STORE_OVERRIDE][property] !== $DELETED
2950
+ : property in target[STORE_VALUE];
2893
2951
  const value = rawValue?.[$TARGET]?.[STORE_VALUE] ?? rawValue;
2894
2952
  const isArrayIndexWrite = Array.isArray(state) && property !== "length";
2895
2953
  const nextIndex = isArrayIndexWrite ? parseInt(property) + 1 : 0;
@@ -2909,11 +2967,21 @@ const storeTraps = {
2909
2967
  override[property] = value;
2910
2968
  if (nextLength !== undefined) override.length = nextLength;
2911
2969
  }
2912
- notifyStoreProperty(target, property, "set", value);
2913
- if (Array.isArray(state)) {
2970
+ notifyStoreProperty(target, property, "set", value, prev, prevHas);
2971
+ if (Array.isArray(state) && property !== "length" && nextLength !== undefined) {
2914
2972
  const nodes = getNodes(target, STORE_NODE);
2915
- const lengthValue = property === "length" ? value : nextLength;
2916
- lengthValue !== undefined && nodes.length && setSignal(nodes.length, lengthValue);
2973
+ if (nodes.length) {
2974
+ setSignal(nodes.length, nextLength);
2975
+ } else if (!projectionWriteActive && !target[STORE_OPTIMISTIC]) {
2976
+ const node = upsertStoreNode(
2977
+ target,
2978
+ nodes,
2979
+ "length",
2980
+ len,
2981
+ target[STORE_SNAPSHOT_PROPS]
2982
+ );
2983
+ setSignal(node, nextLength);
2984
+ }
2917
2985
  }
2918
2986
  if (true) DEV$1.hooks.onStoreNodeUpdate?.(target[$PROXY], property, value, prev);
2919
2987
  });
@@ -2971,7 +3039,7 @@ const storeTraps = {
2971
3039
  } else if (target[overrideKey] && property in target[overrideKey]) {
2972
3040
  delete target[overrideKey][property];
2973
3041
  } else return true;
2974
- notifyStoreProperty(target, property, "delete");
3042
+ notifyStoreProperty(target, property, "delete", undefined, prev, true);
2975
3043
  });
2976
3044
  }
2977
3045
  return true;
@@ -3101,37 +3169,25 @@ function createOptimisticProjectionInternal(fn, initialValue, options) {
3101
3169
  };
3102
3170
  const wrappedStore = wrapProjection(initialValue);
3103
3171
  if (fn) {
3104
- node = computed(() => {
3105
- const owner = getOwner();
3106
- let settled = false;
3107
- let result;
3108
- const draft = new Proxy(
3109
- wrappedStore,
3110
- createWriteTraps(() => !settled || owner._inFlight === result)
3111
- );
3172
+ const wrapCommit = write => {
3112
3173
  setProjectionWriteActive(true);
3113
3174
  try {
3114
- storeSetter(draft, s => {
3115
- result = fn(s);
3116
- settled = true;
3117
- const value = handleAsync(owner, result, value => {
3118
- setProjectionWriteActive(true);
3119
- try {
3120
- value !== s &&
3121
- value !== undefined &&
3122
- storeSetter(wrappedStore, reconcile(value, options?.key || "id"));
3123
- } finally {
3124
- setProjectionWriteActive(false);
3125
- }
3126
- });
3127
- value !== s &&
3128
- value !== undefined &&
3129
- reconcile(value, options?.key || "id")(wrappedStore);
3130
- });
3175
+ write();
3131
3176
  } finally {
3132
3177
  setProjectionWriteActive(false);
3133
3178
  }
3134
- });
3179
+ };
3180
+ node = computed(
3181
+ () => {
3182
+ setProjectionWriteActive(true);
3183
+ try {
3184
+ runProjectionComputed(wrappedStore, fn, options?.key || "id", wrapCommit);
3185
+ } finally {
3186
+ setProjectionWriteActive(false);
3187
+ }
3188
+ },
3189
+ options?.name ? { name: options.name } : undefined
3190
+ );
3135
3191
  node._preventAutoDisposal = true;
3136
3192
  }
3137
3193
  return { store: wrappedStore, node: node };
@@ -3635,7 +3691,7 @@ function compare(key, a, b) {
3635
3691
  return key ? key(a) === key(b) : true;
3636
3692
  }
3637
3693
  function boundaryComputed(fn, propagationMask) {
3638
- const node = computed(fn, undefined, { lazy: true });
3694
+ const node = computed(fn, { lazy: true });
3639
3695
  node._notifyStatus = (status, error) => {
3640
3696
  const flags = status !== undefined ? status : node._statusFlags;
3641
3697
  const actualError = error !== undefined ? error : node._error;
@@ -3660,12 +3716,16 @@ const ON_INIT = Symbol();
3660
3716
  const RevealControllerContext = createContext(null);
3661
3717
  let _revealUsed = false;
3662
3718
  const FALSE_ACCESSOR = () => false;
3719
+ const SEQUENTIAL_ACCESSOR = () => "sequential";
3663
3720
  function isRevealController(slot) {
3664
3721
  return slot instanceof RevealController;
3665
3722
  }
3666
3723
  function isSlotReady(slot) {
3667
3724
  return isRevealController(slot) ? slot.isReady() : slot._sources.size === 0 && !slot._pending;
3668
3725
  }
3726
+ function isSlotMinimallyReady(slot) {
3727
+ return isRevealController(slot) ? slot.isMinimallyReady() : isSlotReady(slot);
3728
+ }
3669
3729
  function setSlotState(slot, controller, disabled, collapsed) {
3670
3730
  setSignal(slot._disabled, disabled);
3671
3731
  setSignal(slot._collapsed, collapsed);
@@ -3677,16 +3737,17 @@ function setSlotState(slot, controller, disabled, collapsed) {
3677
3737
  slot._revealController = undefined;
3678
3738
  }
3679
3739
  class RevealController {
3680
- _togetherAccessor;
3740
+ _orderAccessor;
3681
3741
  _collapsedAccessor;
3682
3742
  _slots = [];
3683
3743
  _parentController;
3684
3744
  _disabled = signal(false, { ownedWrite: true, _noSnapshot: true });
3685
3745
  _collapsed = signal(false, { ownedWrite: true, _noSnapshot: true });
3686
3746
  _ready = true;
3747
+ _minimallyReady = true;
3687
3748
  _evaluating = false;
3688
- constructor(together, collapsed) {
3689
- this._togetherAccessor = together;
3749
+ constructor(order, collapsed) {
3750
+ this._orderAccessor = order;
3690
3751
  this._collapsedAccessor = collapsed;
3691
3752
  }
3692
3753
  _forEachOwnedSlot(fn) {
@@ -3701,12 +3762,37 @@ class RevealController {
3701
3762
  isReady() {
3702
3763
  return this._forEachOwnedSlot(isSlotReady);
3703
3764
  }
3765
+ isMinimallyReady() {
3766
+ const order = untrack(this._orderAccessor);
3767
+ if (order === "together") return this.isReady();
3768
+ if (order === "natural") {
3769
+ let hasSlot = false;
3770
+ let anyReady = false;
3771
+ this._forEachOwnedSlot(slot => {
3772
+ hasSlot = true;
3773
+ if (isSlotMinimallyReady(slot)) {
3774
+ anyReady = true;
3775
+ return false;
3776
+ }
3777
+ });
3778
+ return !hasSlot || anyReady;
3779
+ }
3780
+ let firstReady = true;
3781
+ this._forEachOwnedSlot(slot => {
3782
+ firstReady = isSlotMinimallyReady(slot);
3783
+ return false;
3784
+ });
3785
+ return firstReady;
3786
+ }
3704
3787
  register(slot) {
3705
3788
  if (this._slots.includes(slot)) return;
3706
3789
  this._slots.push(slot);
3707
- const together = !!untrack(this._togetherAccessor);
3790
+ const order = untrack(this._orderAccessor);
3708
3791
  (setSignal(slot._disabled, true),
3709
- setSignal(slot._collapsed, together ? false : !!untrack(this._collapsedAccessor)));
3792
+ setSignal(
3793
+ slot._collapsed,
3794
+ order === "sequential" ? !!untrack(this._collapsedAccessor) : false
3795
+ ));
3710
3796
  untrack(() => this.evaluate());
3711
3797
  }
3712
3798
  unregister(slot) {
@@ -3718,29 +3804,52 @@ class RevealController {
3718
3804
  if (this._evaluating) return;
3719
3805
  this._evaluating = true;
3720
3806
  const wasReady = this._ready;
3807
+ const wasMinReady = this._minimallyReady;
3721
3808
  try {
3722
3809
  const disabled = disabledOverride ?? read(this._disabled),
3723
- collapseTail = !!untrack(this._collapsedAccessor),
3810
+ order = untrack(this._orderAccessor),
3811
+ collapseTail = order === "sequential" && !!untrack(this._collapsedAccessor),
3724
3812
  collapsed = collapsedOverride ?? collapseTail;
3725
- if (disabled && collapsed)
3726
- this._forEachOwnedSlot(slot => setSlotState(slot, this, true, true));
3727
- else if (!!untrack(this._togetherAccessor)) {
3728
- const ready = this.isReady();
3729
- this._forEachOwnedSlot(slot => setSlotState(slot, this, !ready, false));
3813
+ if (disabled) {
3814
+ this._forEachOwnedSlot(slot => setSlotState(slot, this, true, collapsed));
3815
+ } else if (order === "natural") {
3816
+ this._forEachOwnedSlot(slot => {
3817
+ if (isRevealController(slot)) {
3818
+ setSignal(slot._collapsed, false);
3819
+ setSignal(slot._disabled, false);
3820
+ slot.evaluate(false, false);
3821
+ } else {
3822
+ setSlotState(slot, this, !isSlotReady(slot), false);
3823
+ }
3824
+ });
3825
+ } else if (order === "together") {
3826
+ const minReady = this._forEachOwnedSlot(isSlotMinimallyReady);
3827
+ this._forEachOwnedSlot(slot => setSlotState(slot, this, !minReady, false));
3730
3828
  } else {
3731
3829
  let pendingSeen = false;
3732
3830
  this._forEachOwnedSlot(slot => {
3733
3831
  if (pendingSeen) return setSlotState(slot, this, true, collapseTail);
3734
3832
  if (isSlotReady(slot)) return setSlotState(slot, this, false, false);
3735
3833
  pendingSeen = true;
3736
- setSlotState(slot, this, true, false);
3834
+ if (isRevealController(slot)) {
3835
+ setSignal(slot._collapsed, false);
3836
+ setSignal(slot._disabled, false);
3837
+ slot.evaluate(false, false);
3838
+ } else {
3839
+ setSlotState(slot, this, true, false);
3840
+ }
3737
3841
  });
3738
3842
  }
3739
3843
  } finally {
3740
3844
  this._ready = this.isReady();
3845
+ this._minimallyReady = this.isMinimallyReady();
3741
3846
  this._evaluating = false;
3742
3847
  }
3743
- if (this._parentController && wasReady !== this._ready) this._parentController.evaluate();
3848
+ if (
3849
+ this._parentController &&
3850
+ (wasReady !== this._ready || wasMinReady !== this._minimallyReady)
3851
+ )
3852
+ this._parentController.evaluate();
3744
3853
  }
3745
3854
  }
3746
3855
  class CollectionQueue extends Queue {
@@ -3889,14 +3998,14 @@ function createRevealOrder(fn, options) {
3889
3998
  _revealUsed = true;
3890
3999
  const owner = createOwner();
3891
4000
  const parentController = getContext(RevealControllerContext);
3892
- const together = options?.together || FALSE_ACCESSOR,
4001
+ const order = options?.order || SEQUENTIAL_ACCESSOR,
3893
4002
  collapsed = options?.collapsed || FALSE_ACCESSOR;
3894
- const controller = new RevealController(together, collapsed);
4003
+ const controller = new RevealController(order, collapsed);
3895
4004
  setContext(RevealControllerContext, controller, owner);
3896
4005
  return runWithOwner(owner, () => {
3897
4006
  const value = fn();
3898
4007
  computed(() => {
3899
- together();
4008
+ order();
3900
4009
  collapsed();
3901
4010
  controller.evaluate();
3902
4011
  });