solid-js 2.0.0-beta.7 → 2.0.0-beta.9
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/CHEATSHEET.md +562 -0
- package/README.md +44 -188
- 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 +7 -5
- package/types/client/component.d.ts +50 -0
- package/types/client/core.d.ts +98 -21
- package/types/client/flow.d.ts +97 -24
- package/types/client/hydration.d.ts +409 -22
- package/types/index.d.ts +1 -1
- package/types/jsx-properties.d.ts +2 -5
- package/types/jsx.d.ts +108 -77
- package/types/server/core.d.ts +14 -9
- package/types/server/flow.d.ts +40 -7
- package/types/server/hydration.d.ts +18 -1
- package/types/server/index.d.ts +1 -1
- package/types/server/signals.d.ts +30 -10
- package/types-cjs/client/component.d.cts +50 -0
- package/types-cjs/client/core.d.cts +98 -21
- package/types-cjs/client/flow.d.cts +97 -24
- package/types-cjs/client/hydration.d.cts +409 -22
- package/types-cjs/index.d.cts +1 -1
- package/types-cjs/jsx-properties.d.cts +2 -5
- package/types-cjs/jsx.d.cts +108 -77
- package/types-cjs/server/core.d.cts +14 -9
- package/types-cjs/server/flow.d.cts +40 -7
- package/types-cjs/server/hydration.d.cts +18 -1
- package/types-cjs/server/index.d.cts +1 -1
- package/types-cjs/server/signals.d.cts +30 -10
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;
|
package/dist/server.js
CHANGED
|
@@ -128,7 +128,7 @@ function createMemo(compute, options) {
|
|
|
128
128
|
}
|
|
129
129
|
}
|
|
130
130
|
const ssrSource = options?.ssrSource;
|
|
131
|
-
if (ssrSource === "
|
|
131
|
+
if (ssrSource === "client") {
|
|
132
132
|
comp.computed = true;
|
|
133
133
|
} else if (!options?.lazy) {
|
|
134
134
|
update();
|
|
@@ -324,7 +324,7 @@ function closeAsyncIterator(iter, value) {
|
|
|
324
324
|
}
|
|
325
325
|
function serverEffect(compute, effectFn, options) {
|
|
326
326
|
const ssrSource = options?.ssrSource;
|
|
327
|
-
if (ssrSource === "client"
|
|
327
|
+
if (ssrSource === "client") {
|
|
328
328
|
createOwner();
|
|
329
329
|
return;
|
|
330
330
|
}
|
|
@@ -405,7 +405,7 @@ function createProjection(fn, initialValue, options) {
|
|
|
405
405
|
const ctx = sharedConfig.context;
|
|
406
406
|
const owner = createOwner();
|
|
407
407
|
const [state] = createStore(initialValue);
|
|
408
|
-
if (options?.ssrSource === "
|
|
408
|
+
if (options?.ssrSource === "client") {
|
|
409
409
|
return state;
|
|
410
410
|
}
|
|
411
411
|
let disposed = false;
|
|
@@ -825,12 +825,6 @@ function ssrHandleError(err) {
|
|
|
825
825
|
}
|
|
826
826
|
throw err;
|
|
827
827
|
}
|
|
828
|
-
class InvalidTopLevelAsyncReadError extends Error {
|
|
829
|
-
constructor() {
|
|
830
|
-
super("Async values must be read within a tracking scope (JSX, a memo, or an effect's compute function).");
|
|
831
|
-
this.name = "InvalidTopLevelAsyncReadError";
|
|
832
|
-
}
|
|
833
|
-
}
|
|
834
828
|
function createLoadingBoundary(fn, fallback, options) {
|
|
835
829
|
const currentCtx = sharedConfig.context;
|
|
836
830
|
if (!currentCtx) {
|
|
@@ -845,6 +839,7 @@ function createLoadingBoundary(fn, fallback, options) {
|
|
|
845
839
|
o.id = id + "00";
|
|
846
840
|
let done;
|
|
847
841
|
let handledRenderError;
|
|
842
|
+
let retryPromise;
|
|
848
843
|
let serializeBuffer = [];
|
|
849
844
|
const bufferedCtx = Object.create(ctx);
|
|
850
845
|
bufferedCtx.serialize = (id, value, deferStream) => {
|
|
@@ -888,21 +883,26 @@ function createLoadingBoundary(fn, fallback, options) {
|
|
|
888
883
|
function runDiscovery() {
|
|
889
884
|
o.dispose(false);
|
|
890
885
|
serializeBuffer = [];
|
|
886
|
+
retryPromise = undefined;
|
|
891
887
|
return runLoadingPhase(() => {
|
|
892
888
|
try {
|
|
893
889
|
return ctx.resolve(fn());
|
|
894
890
|
} catch (err) {
|
|
895
|
-
if (err instanceof NotReadyError)
|
|
891
|
+
if (err instanceof NotReadyError) {
|
|
892
|
+
retryPromise = err.source;
|
|
893
|
+
return undefined;
|
|
894
|
+
}
|
|
896
895
|
throw err;
|
|
897
896
|
}
|
|
898
897
|
});
|
|
899
898
|
}
|
|
900
899
|
let ret = runDiscovery();
|
|
901
|
-
if (!ret?.p?.length) {
|
|
900
|
+
if (!retryPromise && !ret?.p?.length) {
|
|
902
901
|
commitBoundaryState();
|
|
903
902
|
return () => ret;
|
|
904
903
|
}
|
|
905
|
-
const
|
|
904
|
+
const regResult = revealGroup ? revealGroup.register(id) : null;
|
|
905
|
+
const collapseFallback = regResult?.collapseFallback ?? false;
|
|
906
906
|
if (collapseFallback && !ctx.async) {
|
|
907
907
|
commitBoundaryState();
|
|
908
908
|
ctx.serialize(id, "$$f");
|
|
@@ -923,6 +923,10 @@ function createLoadingBoundary(fn, fallback, options) {
|
|
|
923
923
|
done = ctx.registerFragment(id, regOpts);
|
|
924
924
|
(async () => {
|
|
925
925
|
try {
|
|
926
|
+
while (retryPromise) {
|
|
927
|
+
await retryPromise.catch(() => {});
|
|
928
|
+
ret = runDiscovery();
|
|
929
|
+
}
|
|
926
930
|
commitBoundaryState();
|
|
927
931
|
while (ret.p.length) {
|
|
928
932
|
await Promise.all(ret.p).catch(() => {});
|
|
@@ -1025,15 +1029,16 @@ function Loading(props) {
|
|
|
1025
1029
|
function Reveal(props) {
|
|
1026
1030
|
const o = createOwner();
|
|
1027
1031
|
const id = o.id;
|
|
1028
|
-
const
|
|
1029
|
-
const collapsed = !!props.collapsed;
|
|
1032
|
+
const order = props.order ?? "sequential";
|
|
1033
|
+
const collapsed = order === "sequential" && !!props.collapsed;
|
|
1030
1034
|
if (!sharedConfig.context?.async) {
|
|
1031
1035
|
const parent = getOwner();
|
|
1032
1036
|
const parentGroup = parent ? runWithOwner(parent, () => getContext(RevealGroupContext)) : null;
|
|
1033
1037
|
let collapsedByParent = false;
|
|
1034
1038
|
if (parentGroup) {
|
|
1035
|
-
|
|
1036
|
-
|
|
1039
|
+
const reg = parentGroup.register(id);
|
|
1040
|
+
collapsedByParent = reg.collapseFallback;
|
|
1041
|
+
if (order === "together" || collapsed) console.warn("Nested <Reveal> with collapsed/together won't coordinate correctly with renderToString. Use renderToStream for full support.");
|
|
1037
1042
|
}
|
|
1038
1043
|
let count = 0;
|
|
1039
1044
|
return runWithOwner(o, () => {
|
|
@@ -1041,8 +1046,11 @@ function Reveal(props) {
|
|
|
1041
1046
|
id,
|
|
1042
1047
|
register(_key) {
|
|
1043
1048
|
count++;
|
|
1044
|
-
|
|
1045
|
-
return
|
|
1049
|
+
const collapseFallback = collapsedByParent || order === "sequential" && collapsed && count > 1;
|
|
1050
|
+
return {
|
|
1051
|
+
collapseFallback,
|
|
1052
|
+
held: false
|
|
1053
|
+
};
|
|
1046
1054
|
},
|
|
1047
1055
|
onResolved() {}
|
|
1048
1056
|
});
|
|
@@ -1052,58 +1060,129 @@ function Reveal(props) {
|
|
|
1052
1060
|
const ctx = sharedConfig.context;
|
|
1053
1061
|
const keys = [];
|
|
1054
1062
|
const resolved = new Set();
|
|
1063
|
+
const minimallyResolved = new Set();
|
|
1055
1064
|
const composites = new Map();
|
|
1065
|
+
const activated = new Set();
|
|
1066
|
+
const stash = [];
|
|
1067
|
+
const collapsedLeafKeys = [];
|
|
1056
1068
|
let frontier = 0;
|
|
1069
|
+
let heldByParent = false;
|
|
1070
|
+
let collapsedByParent = false;
|
|
1071
|
+
let selfMinimallyResolved = false;
|
|
1072
|
+
let notifiedParentDone = false;
|
|
1057
1073
|
const parent = getOwner();
|
|
1058
1074
|
const parentGroup = parent ? runWithOwner(parent, () => getContext(RevealGroupContext)) : null;
|
|
1059
|
-
let collapsedByParent = false;
|
|
1060
1075
|
if (parentGroup) {
|
|
1061
|
-
|
|
1076
|
+
const reg = parentGroup.register(id, {
|
|
1062
1077
|
onActivate: () => {
|
|
1063
|
-
|
|
1064
|
-
|
|
1078
|
+
if (!heldByParent) return;
|
|
1079
|
+
heldByParent = false;
|
|
1080
|
+
if (collapsedByParent) {
|
|
1081
|
+
collapsedByParent = false;
|
|
1082
|
+
if (collapsedLeafKeys.length) {
|
|
1083
|
+
ctx.revealFallbacks?.([...collapsedLeafKeys]);
|
|
1084
|
+
collapsedLeafKeys.length = 0;
|
|
1085
|
+
}
|
|
1086
|
+
}
|
|
1087
|
+
if (order === "sequential") advanceFrontier();else if (order === "together") checkTogetherRelease();else naturalRelease();
|
|
1065
1088
|
}
|
|
1066
1089
|
});
|
|
1090
|
+
collapsedByParent = reg.collapseFallback;
|
|
1091
|
+
heldByParent = reg.held;
|
|
1067
1092
|
}
|
|
1068
1093
|
function notifyParentIfDone() {
|
|
1094
|
+
if (notifiedParentDone) return;
|
|
1069
1095
|
if (parentGroup && resolved.size === keys.length) {
|
|
1096
|
+
notifiedParentDone = true;
|
|
1070
1097
|
parentGroup.onResolved(id);
|
|
1071
1098
|
}
|
|
1072
1099
|
}
|
|
1100
|
+
function activateComposite(key) {
|
|
1101
|
+
if (activated.has(key)) return;
|
|
1102
|
+
activated.add(key);
|
|
1103
|
+
composites.get(key)();
|
|
1104
|
+
}
|
|
1105
|
+
function updateSelfMinimallyResolved() {
|
|
1106
|
+
if (selfMinimallyResolved) return;
|
|
1107
|
+
if (keys.length === 0) selfMinimallyResolved = true;else if (order === "together") selfMinimallyResolved = minimallyResolved.size === keys.length;else if (order === "sequential") selfMinimallyResolved = minimallyResolved.has(keys[0]);
|
|
1108
|
+
else selfMinimallyResolved = resolved.size > 0;
|
|
1109
|
+
if (selfMinimallyResolved) parentGroup?.onMinimallyResolved?.(id);
|
|
1110
|
+
}
|
|
1073
1111
|
function advanceFrontier() {
|
|
1112
|
+
if (heldByParent) return;
|
|
1074
1113
|
while (frontier < keys.length && resolved.has(keys[frontier])) {
|
|
1075
|
-
|
|
1114
|
+
const k = keys[frontier];
|
|
1115
|
+
if (composites.has(k)) activateComposite(k);else ctx.revealFragments?.([k]);
|
|
1076
1116
|
frontier++;
|
|
1077
1117
|
}
|
|
1078
1118
|
if (frontier < keys.length) {
|
|
1079
|
-
const
|
|
1080
|
-
if (
|
|
1119
|
+
const k = keys[frontier];
|
|
1120
|
+
if (composites.has(k)) activateComposite(k);else if (order === "sequential" && collapsed) ctx.revealFallbacks?.([k]);
|
|
1081
1121
|
}
|
|
1082
1122
|
notifyParentIfDone();
|
|
1083
1123
|
}
|
|
1124
|
+
function checkTogetherRelease() {
|
|
1125
|
+
if (order !== "together" || heldByParent) return;
|
|
1126
|
+
if (minimallyResolved.size < keys.length) return;
|
|
1127
|
+
if (stash.length) {
|
|
1128
|
+
ctx.revealFragments?.([...stash]);
|
|
1129
|
+
stash.length = 0;
|
|
1130
|
+
}
|
|
1131
|
+
composites.forEach((_, key) => activateComposite(key));
|
|
1132
|
+
notifyParentIfDone();
|
|
1133
|
+
}
|
|
1134
|
+
function naturalRelease() {
|
|
1135
|
+
if (stash.length) {
|
|
1136
|
+
ctx.revealFragments?.([...stash]);
|
|
1137
|
+
stash.length = 0;
|
|
1138
|
+
}
|
|
1139
|
+
composites.forEach((_, key) => activateComposite(key));
|
|
1140
|
+
notifyParentIfDone();
|
|
1141
|
+
}
|
|
1084
1142
|
return runWithOwner(o, () => {
|
|
1085
1143
|
setContext(RevealGroupContext, {
|
|
1086
1144
|
id,
|
|
1087
1145
|
register(key, options) {
|
|
1088
1146
|
keys.push(key);
|
|
1089
|
-
|
|
1090
|
-
if (
|
|
1091
|
-
|
|
1147
|
+
const isComposite = !!options?.onActivate;
|
|
1148
|
+
if (isComposite) composites.set(key, options.onActivate);
|
|
1149
|
+
const selfCollapse = order === "sequential" && collapsed && keys.length > 1;
|
|
1150
|
+
const collapseFallback = collapsedByParent || selfCollapse;
|
|
1151
|
+
if (collapseFallback && !isComposite) collapsedLeafKeys.push(key);
|
|
1152
|
+
let held = heldByParent;
|
|
1153
|
+
if (!held) {
|
|
1154
|
+
if (order === "together") held = true;else if (order === "sequential" && keys.length > 1) held = true;
|
|
1155
|
+
}
|
|
1156
|
+
return {
|
|
1157
|
+
collapseFallback,
|
|
1158
|
+
held
|
|
1159
|
+
};
|
|
1092
1160
|
},
|
|
1093
1161
|
onResolved(key) {
|
|
1094
1162
|
resolved.add(key);
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1163
|
+
const isLeaf = !composites.has(key);
|
|
1164
|
+
if (isLeaf) {
|
|
1165
|
+
if (order === "together") {
|
|
1166
|
+
stash.push(key);
|
|
1167
|
+
} else if (order === "natural" && heldByParent) {
|
|
1168
|
+
stash.push(key);
|
|
1169
|
+
} else if (order === "natural") {
|
|
1170
|
+
ctx.revealFragments?.([key]);
|
|
1103
1171
|
}
|
|
1172
|
+
markMinimallyResolved(key);
|
|
1173
|
+
if (order === "sequential" && !heldByParent) advanceFrontier();
|
|
1174
|
+
if (order === "natural") updateSelfMinimallyResolved();
|
|
1104
1175
|
} else {
|
|
1105
|
-
|
|
1176
|
+
if (!heldByParent) {
|
|
1177
|
+
if (order === "sequential") advanceFrontier();else if (order === "natural") activateComposite(key);
|
|
1178
|
+
}
|
|
1179
|
+
if (order === "together") checkTogetherRelease();
|
|
1180
|
+
if (order === "natural") updateSelfMinimallyResolved();
|
|
1106
1181
|
}
|
|
1182
|
+
notifyParentIfDone();
|
|
1183
|
+
},
|
|
1184
|
+
onMinimallyResolved(key) {
|
|
1185
|
+
markMinimallyResolved(key);
|
|
1107
1186
|
}
|
|
1108
1187
|
});
|
|
1109
1188
|
const result = props.children;
|
|
@@ -1112,6 +1191,12 @@ function Reveal(props) {
|
|
|
1112
1191
|
}
|
|
1113
1192
|
return result;
|
|
1114
1193
|
});
|
|
1194
|
+
function markMinimallyResolved(key) {
|
|
1195
|
+
if (minimallyResolved.has(key)) return;
|
|
1196
|
+
minimallyResolved.add(key);
|
|
1197
|
+
updateSelfMinimallyResolved();
|
|
1198
|
+
if (order === "together") checkTogetherRelease();
|
|
1199
|
+
}
|
|
1115
1200
|
}
|
|
1116
1201
|
|
|
1117
1202
|
const DEV = undefined;
|