@jsenv/navi 0.29.166 → 0.29.167
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/jsenv_navi.js +30 -10
- package/dist/jsenv_navi.js.map +3 -3
- package/docs/AI_INSTRUCTIONS.md +11 -0
- package/docs/actions.md +6 -4
- package/docs/data_states.md +147 -0
- package/docs/error_handling.md +9 -0
- package/docs/list_refresh.md +16 -1
- package/package.json +1 -1
package/dist/jsenv_navi.js
CHANGED
|
@@ -17635,7 +17635,9 @@ const useActionAsyncData = (action, {
|
|
|
17635
17635
|
onLoad
|
|
17636
17636
|
}) => {
|
|
17637
17637
|
const loadingRef = useContext(LoadingContext);
|
|
17638
|
-
|
|
17638
|
+
// The boundary is where a suspension lands, so only the delegating path needs
|
|
17639
|
+
// one: `loading: true` draws the wait itself and never suspends.
|
|
17640
|
+
if (!loadingRef && loadingEffect !== "use") {
|
|
17639
17641
|
throw new Error(`Missing <Loading>: useAsyncData delegates the wait, so it needs a <Loading> boundary above it — or "loading: true" to draw that wait here.`);
|
|
17640
17642
|
}
|
|
17641
17643
|
useOnLoad(action, onLoad);
|
|
@@ -17719,15 +17721,19 @@ const useActionAsyncData = (action, {
|
|
|
17719
17721
|
}
|
|
17720
17722
|
if (runningState === FAILED) {
|
|
17721
17723
|
if (dismissedActionWeakSet.has(action)) {
|
|
17724
|
+
// Dismissing removes the error and nothing else: what is handed back is
|
|
17725
|
+
// the action's state without it — the data it holds, and no run in
|
|
17726
|
+
// progress. Holding nothing is one of those states, not a wait, so a
|
|
17727
|
+
// component drawing its own states gets it rather than being suspended
|
|
17728
|
+
// away from the retry it is offering.
|
|
17722
17729
|
const staleData = action.dataSignal.peek();
|
|
17723
|
-
if (staleData !== undefined) {
|
|
17724
|
-
// Dismissed with stale data — return it so children render normally
|
|
17730
|
+
if (staleData !== undefined || loadingEffect === "use") {
|
|
17725
17731
|
return [staleData, false, undefined];
|
|
17726
17732
|
}
|
|
17727
|
-
//
|
|
17728
|
-
//
|
|
17729
|
-
// so
|
|
17730
|
-
//
|
|
17733
|
+
// Nothing to hand over and the waits are delegated: there is no state
|
|
17734
|
+
// this component can draw, so it waits. The promise resolves on RUNNING
|
|
17735
|
+
// rather than never, so a run started from anywhere brings it back
|
|
17736
|
+
// through the ordinary loading path instead of leaving it stuck.
|
|
17731
17737
|
let dismissedPromise = dismissedActionPendingPromiseWeakMap.get(action);
|
|
17732
17738
|
if (!dismissedPromise) {
|
|
17733
17739
|
dismissedPromise = new Promise(resolve => {
|
|
@@ -17756,7 +17762,10 @@ const useActionAsyncData = (action, {
|
|
|
17756
17762
|
dismissedActionWeakSet.add(action);
|
|
17757
17763
|
setTick(n => n + 1);
|
|
17758
17764
|
};
|
|
17759
|
-
|
|
17765
|
+
// The previous answer is still there and a failed refresh does not unmake
|
|
17766
|
+
// it, so both are handed over: the component can say the failure over the
|
|
17767
|
+
// content it already has instead of choosing between the two.
|
|
17768
|
+
return [action.dataSignal.peek(), false, actionError, dismissError];
|
|
17760
17769
|
}
|
|
17761
17770
|
// Not marked: nothing is displayed yet — the boundary that catches this is
|
|
17762
17771
|
// what says so, and only if it has something to show.
|
|
@@ -39522,8 +39531,19 @@ const TextAnchor = ({
|
|
|
39522
39531
|
// which reads as the child "jumping" even though nothing about its own
|
|
39523
39532
|
// geometry changed. useDisplayedLayoutEffect skips the initial run in
|
|
39524
39533
|
// that case and reruns once the ancestor actually opens instead.
|
|
39525
|
-
|
|
39526
|
-
|
|
39534
|
+
//
|
|
39535
|
+
// It is asked about the CHILD, not about the anchor: the anchor is this
|
|
39536
|
+
// effect's own measuring device, displayed or not according to what the
|
|
39537
|
+
// effect last decided (see the hidden attribute below), so asking whether
|
|
39538
|
+
// it is on screen answers with that decision rather than with a fact about
|
|
39539
|
+
// the screen. On the façade of something closed — an icon in a picker's
|
|
39540
|
+
// trigger, where the openable ancestor is the picker itself — that answer
|
|
39541
|
+
// is "hidden", the correction waits for the popup to open, and the icon
|
|
39542
|
+
// jumps half a pixel on the first click. The child is what is being
|
|
39543
|
+
// positioned, and it is on screen exactly when the correction means
|
|
39544
|
+
// something.
|
|
39545
|
+
useDisplayedLayoutEffect(childRef, childEl => {
|
|
39546
|
+
const anchorEl = anchorRef.current;
|
|
39527
39547
|
if (!anchorEl || !childEl) {
|
|
39528
39548
|
return;
|
|
39529
39549
|
}
|