@jsenv/navi 0.29.226 → 0.29.228
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/jsenv_navi.js +196 -116
- package/dist/dev/jsenv_navi.js.map +14 -13
- package/dist/jsenv_navi.js +196 -116
- package/dist/jsenv_navi.js.map +14 -13
- package/docs/AI_INSTRUCTIONS.md +2 -1
- package/docs/data_states.md +7 -0
- package/docs/dynamic_import.md +62 -37
- package/docs/interactions.md +7 -0
- package/docs/popup_open.md +31 -4
- package/package.json +1 -1
package/dist/jsenv_navi.js
CHANGED
|
@@ -3149,6 +3149,12 @@ const actionWeakMap = new WeakMap();
|
|
|
3149
3149
|
*
|
|
3150
3150
|
* @param {Function} callback
|
|
3151
3151
|
* @param {object} [rootOptions]
|
|
3152
|
+
* @param {(params: any, action: object) => any} [rootOptions.provisionalValue] -
|
|
3153
|
+
* a value the action holds while a run is in flight and it has none of its
|
|
3154
|
+
* own, so a screen already knowing the answer draws it as a refresh rather
|
|
3155
|
+
* than a first load (data_states.md). Called at the start of every run whose
|
|
3156
|
+
* value is undefined; the answer replaces it as usual, and `undefined` means
|
|
3157
|
+
* "nothing known". A resource `GET` uses it to draw the row its store holds.
|
|
3152
3158
|
* @param {{ ms?: number, max?: number }} [rootOptions.keep] - how long an
|
|
3153
3159
|
* answer stays good once it has landed. Without it an answer lives exactly as
|
|
3154
3160
|
* long as something references it: the screen that asked goes away, and
|
|
@@ -3188,6 +3194,7 @@ const createAction = (callback, rootOptions = {}) => {
|
|
|
3188
3194
|
value,
|
|
3189
3195
|
resultToValue,
|
|
3190
3196
|
valueToData,
|
|
3197
|
+
provisionalValue,
|
|
3191
3198
|
dataDefault,
|
|
3192
3199
|
data = dataDefault,
|
|
3193
3200
|
|
|
@@ -3646,6 +3653,12 @@ const createAction = (callback, rootOptions = {}) => {
|
|
|
3646
3653
|
actionAbortMap.set(action, abort);
|
|
3647
3654
|
|
|
3648
3655
|
batch(() => {
|
|
3656
|
+
if (provisionalValue && valueSignal.peek() === undefined) {
|
|
3657
|
+
const provisional = provisionalValue(params, action);
|
|
3658
|
+
if (provisional !== undefined) {
|
|
3659
|
+
valueSignal.value = provisional;
|
|
3660
|
+
}
|
|
3661
|
+
}
|
|
3649
3662
|
runningStateSignal.value = RUNNING;
|
|
3650
3663
|
if (!isPrerun) {
|
|
3651
3664
|
isPrerunSignal.value = false;
|
|
@@ -5158,6 +5171,9 @@ const CONTROL_PROP_SET = new Set([
|
|
|
5158
5171
|
// The wait this control's action creates is its own: it renders busy and
|
|
5159
5172
|
// refuses a second press, and nothing above it is told (see BUSY_CONSTRAINT).
|
|
5160
5173
|
"actionStandalone",
|
|
5174
|
+
// The wait this control's action creates may be called off by the person
|
|
5175
|
+
// waiting: closing the popup it holds gives up on the run (see popup_busy.js).
|
|
5176
|
+
"actionAbortable",
|
|
5161
5177
|
|
|
5162
5178
|
"charGuard",
|
|
5163
5179
|
"maxLengthGuard",
|
|
@@ -7867,11 +7883,10 @@ const BUSY_CONSTRAINT = {
|
|
|
7867
7883
|
// Unless it says the wait is its own (`actionStandalone`): then the refusal
|
|
7868
7884
|
// stays on the element and every ancestor reads it as free — the group above
|
|
7869
7885
|
// (see getInteractionBlockingControls) and the popup around it (see
|
|
7870
|
-
//
|
|
7871
|
-
// `ignoredByParents`).
|
|
7886
|
+
// popup_busy.js, which filters on `ignoredByParents`).
|
|
7872
7887
|
check: (field, { intent } = {}) => {
|
|
7873
|
-
const
|
|
7874
|
-
if (!
|
|
7888
|
+
const busySource = findBusySource(field);
|
|
7889
|
+
if (!busySource) {
|
|
7875
7890
|
return null;
|
|
7876
7891
|
}
|
|
7877
7892
|
|
|
@@ -7892,11 +7907,31 @@ const BUSY_CONSTRAINT = {
|
|
|
7892
7907
|
message,
|
|
7893
7908
|
status: "info",
|
|
7894
7909
|
ignoredByParents: Boolean(field.actionStandalone),
|
|
7910
|
+
// Read off the control the run belongs to, not off this one: a field or a
|
|
7911
|
+
// submit button inherits its form's wait, so it inherits with it whether
|
|
7912
|
+
// the person waiting is allowed to call that wait off (see
|
|
7913
|
+
// abortControlRun, and `actionAbortable` in control_hooks.jsx).
|
|
7914
|
+
abortable: Boolean(busySource.action && busySource.field.actionAbortable),
|
|
7895
7915
|
};
|
|
7896
7916
|
},
|
|
7897
7917
|
};
|
|
7898
7918
|
CONSTRAINT_ATTRIBUTE_SET.add("data-busy");
|
|
7899
7919
|
|
|
7920
|
+
/**
|
|
7921
|
+
* Give up on the run that makes `field` busy — the person waiting deciding the
|
|
7922
|
+
* answer is not coming. The work is not undone: aborting frees the client and
|
|
7923
|
+
* nothing more, the server may already have done it (see docs/actions.md,
|
|
7924
|
+
* "Aborting saves resources, it does not undo"). What ends is the wait, and
|
|
7925
|
+
* with it every refusal held by it.
|
|
7926
|
+
*/
|
|
7927
|
+
const abortControlRun = (field, reason) => {
|
|
7928
|
+
const busySource = findBusySource(field);
|
|
7929
|
+
if (!busySource || !busySource.action) {
|
|
7930
|
+
return false;
|
|
7931
|
+
}
|
|
7932
|
+
return busySource.action.abort(reason);
|
|
7933
|
+
};
|
|
7934
|
+
|
|
7900
7935
|
// Asked source by source rather than off the rendered `aria-busy`, which
|
|
7901
7936
|
// conflates them and is a frame behind: that attribute is written during
|
|
7902
7937
|
// render, so it still says "true" for the whole tick in which an action
|
|
@@ -7908,9 +7943,15 @@ CONSTRAINT_ATTRIBUTE_SET.add("data-busy");
|
|
|
7908
7943
|
// control busy only because the group above is waiting has no state of its own
|
|
7909
7944
|
// to read — the group's answer IS its answer, so it asks upward and inherits
|
|
7910
7945
|
// the same live reading.
|
|
7911
|
-
|
|
7946
|
+
//
|
|
7947
|
+
// What comes back is the control the wait BELONGS to, and the running action
|
|
7948
|
+
// when there is one, because two questions are asked of it: whether this
|
|
7949
|
+
// control is busy at all, and what giving up on that wait would mean.
|
|
7950
|
+
const findBusySource = (field) => {
|
|
7912
7951
|
if (field.loadingFromOwnProp) {
|
|
7913
|
-
|
|
7952
|
+
// A `loading` prop is a wait the app draws itself; there is no run behind
|
|
7953
|
+
// it to call off.
|
|
7954
|
+
return { field, action: null };
|
|
7914
7955
|
}
|
|
7915
7956
|
const { boundAction } = field;
|
|
7916
7957
|
// An optimistic control stays interactive while its bound action runs:
|
|
@@ -7928,14 +7969,14 @@ const isControlBusy = (field) => {
|
|
|
7928
7969
|
// cannot move mid-run, this very gate blocks it.
|
|
7929
7970
|
const liveAction = boundAction.getCurrentAction?.() ?? boundAction;
|
|
7930
7971
|
if (liveAction.runningStateSignal.value === RUNNING) {
|
|
7931
|
-
return
|
|
7972
|
+
return { field, action: liveAction };
|
|
7932
7973
|
}
|
|
7933
7974
|
}
|
|
7934
7975
|
if (field.loadingFromAbove) {
|
|
7935
7976
|
const parent = field.parentUIStateController;
|
|
7936
|
-
return parent ?
|
|
7977
|
+
return parent ? findBusySource(parent) : null;
|
|
7937
7978
|
}
|
|
7938
|
-
return
|
|
7979
|
+
return null;
|
|
7939
7980
|
};
|
|
7940
7981
|
|
|
7941
7982
|
const DISABLED_CONSTRAINT = {
|
|
@@ -14831,17 +14872,15 @@ const resource = (
|
|
|
14831
14872
|
return item;
|
|
14832
14873
|
},
|
|
14833
14874
|
});
|
|
14834
|
-
const createRestActionForRoot = createRestActionFactoryForRoot(name, {
|
|
14835
|
-
idKey,
|
|
14836
|
-
store,
|
|
14837
|
-
declarationSite,
|
|
14838
|
-
});
|
|
14839
14875
|
// The row a GET designates, when the store already holds it — by its params:
|
|
14840
14876
|
// the value under idKey may be the id or any unique key (a route opening a
|
|
14841
14877
|
// user by id or by slug names both `id`), and a unique key may be given under
|
|
14842
|
-
// its own name
|
|
14843
|
-
//
|
|
14844
|
-
//
|
|
14878
|
+
// its own name. findItemByParams is what a GET draws while its request is in
|
|
14879
|
+
// flight (the action's provisionalValue). findItemInStore adds, when the
|
|
14880
|
+
// params name no row (a GET without params, or whose params carry no key),
|
|
14881
|
+
// the row the action last completed with: that fallback answers a GET under
|
|
14882
|
+
// a network policy (see applyNetworkPolicy) and only there — a GET of a row
|
|
14883
|
+
// the store lacks must draw its skeleton, never the row read just before.
|
|
14845
14884
|
const selectByAnyKey = (value) => {
|
|
14846
14885
|
const item = store.select(value);
|
|
14847
14886
|
if (item) {
|
|
@@ -14893,6 +14932,12 @@ const resource = (
|
|
|
14893
14932
|
return store.select(lastItemId) || null;
|
|
14894
14933
|
});
|
|
14895
14934
|
};
|
|
14935
|
+
const createRestActionForRoot = createRestActionFactoryForRoot(name, {
|
|
14936
|
+
idKey,
|
|
14937
|
+
store,
|
|
14938
|
+
findItemByParams,
|
|
14939
|
+
declarationSite,
|
|
14940
|
+
});
|
|
14896
14941
|
return createResource(name, {
|
|
14897
14942
|
idKey,
|
|
14898
14943
|
uniqueKeys,
|
|
@@ -15884,6 +15929,7 @@ const createRestActionFactoryForRoot = (
|
|
|
15884
15929
|
{
|
|
15885
15930
|
idKey,
|
|
15886
15931
|
store, // see array_signal_store.js
|
|
15932
|
+
findItemByParams,
|
|
15887
15933
|
declarationSite,
|
|
15888
15934
|
},
|
|
15889
15935
|
) => {
|
|
@@ -15955,6 +16001,16 @@ const createRestActionFactoryForRoot = (
|
|
|
15955
16001
|
return applyResultToValue(result);
|
|
15956
16002
|
},
|
|
15957
16003
|
valueToData: (itemId) => store.select(itemId),
|
|
16004
|
+
// While the request is out, the row the store already holds for these
|
|
16005
|
+
// params is drawn: the action starts on the "refresh over a known
|
|
16006
|
+
// answer" line of data_states.md rather than the first-load one.
|
|
16007
|
+
provisionalValue:
|
|
16008
|
+
verb === "GET"
|
|
16009
|
+
? (params) => {
|
|
16010
|
+
const item = untracked(() => findItemByParams(params));
|
|
16011
|
+
return item ? item[idKey] : undefined;
|
|
16012
|
+
}
|
|
16013
|
+
: undefined,
|
|
15958
16014
|
completeSideEffect: onActionComplete,
|
|
15959
16015
|
});
|
|
15960
16016
|
};
|
|
@@ -23611,50 +23667,30 @@ const parsePattern = (
|
|
|
23611
23667
|
};
|
|
23612
23668
|
|
|
23613
23669
|
/**
|
|
23614
|
-
*
|
|
23670
|
+
* A literal segment the url stops short of is optional when an ancestor
|
|
23671
|
+
* pattern has a path param AT THAT SAME POSITION whose default is this word:
|
|
23672
|
+
* "/admin/settings/:tab" is the page "/admin" opens on when "/admin/:section"
|
|
23673
|
+
* defaults to "settings". Only the connection occupying the segment's index
|
|
23674
|
+
* may excuse it — a query param, or a param sitting elsewhere, says nothing
|
|
23675
|
+
* about this position, so a state defaulting to "games" must not turn
|
|
23676
|
+
* "/places/:slug/games" into a match for "/places/:slug".
|
|
23615
23677
|
*/
|
|
23616
23678
|
const checkIfLiteralCanBeOptionalWithPatternObj = (
|
|
23617
|
-
|
|
23679
|
+
literalSegment,
|
|
23618
23680
|
patternObj,
|
|
23619
23681
|
) => {
|
|
23620
|
-
|
|
23621
|
-
|
|
23622
|
-
|
|
23623
|
-
|
|
23624
|
-
|
|
23625
|
-
|
|
23626
|
-
if (connection.isDefaultValue(literalValue)) {
|
|
23627
|
-
return true;
|
|
23628
|
-
}
|
|
23629
|
-
}
|
|
23630
|
-
|
|
23631
|
-
// Check parent pattern's connections
|
|
23632
|
-
let currentParent = patternObj.parent;
|
|
23633
|
-
while (currentParent) {
|
|
23634
|
-
for (const connection of currentParent.connections) {
|
|
23635
|
-
if (connection.isDefaultValue(literalValue)) {
|
|
23682
|
+
let ancestor = patternObj ? patternObj.parent : null;
|
|
23683
|
+
while (ancestor) {
|
|
23684
|
+
const ancestorSegment = ancestor.pattern.segments[literalSegment.index];
|
|
23685
|
+
if (ancestorSegment && ancestorSegment.type === "param") {
|
|
23686
|
+
const connection = ancestor.pathConnectionMap.get(ancestorSegment.name);
|
|
23687
|
+
if (connection && connection.isDefaultValue(literalSegment.value)) {
|
|
23636
23688
|
return true;
|
|
23637
23689
|
}
|
|
23638
23690
|
}
|
|
23639
|
-
|
|
23691
|
+
ancestor = ancestor.parent;
|
|
23640
23692
|
}
|
|
23641
|
-
|
|
23642
|
-
// Check children pattern's connections
|
|
23643
|
-
const checkChildrenRecursively = (pattern) => {
|
|
23644
|
-
for (const child of pattern.children || []) {
|
|
23645
|
-
for (const connection of child.connections) {
|
|
23646
|
-
if (connection.isDefaultValue(literalValue)) {
|
|
23647
|
-
return true;
|
|
23648
|
-
}
|
|
23649
|
-
}
|
|
23650
|
-
if (checkChildrenRecursively(child)) {
|
|
23651
|
-
return true;
|
|
23652
|
-
}
|
|
23653
|
-
}
|
|
23654
|
-
return false;
|
|
23655
|
-
};
|
|
23656
|
-
|
|
23657
|
-
return checkChildrenRecursively(patternObj);
|
|
23693
|
+
return false;
|
|
23658
23694
|
};
|
|
23659
23695
|
|
|
23660
23696
|
/**
|
|
@@ -23799,9 +23835,8 @@ const matchUrl = (
|
|
|
23799
23835
|
// Check if URL has this segment
|
|
23800
23836
|
if (urlSegmentIndex >= urlSegments.length) {
|
|
23801
23837
|
// URL is too short for this literal segment
|
|
23802
|
-
// Check if this literal segment can be treated as optional based on pattern hierarchy
|
|
23803
23838
|
const canBeOptional = checkIfLiteralCanBeOptionalWithPatternObj(
|
|
23804
|
-
patternSeg
|
|
23839
|
+
patternSeg,
|
|
23805
23840
|
patternObj,
|
|
23806
23841
|
);
|
|
23807
23842
|
if (canBeOptional) {
|
|
@@ -37063,7 +37098,8 @@ const useInteractiveProps = (props, {
|
|
|
37063
37098
|
readOnly,
|
|
37064
37099
|
loading,
|
|
37065
37100
|
optimistic,
|
|
37066
|
-
actionStandalone
|
|
37101
|
+
actionStandalone,
|
|
37102
|
+
actionAbortable
|
|
37067
37103
|
} = props;
|
|
37068
37104
|
|
|
37069
37105
|
// `whenSelfInteractionsBlocked="ignore"`: an affordance that writes nothing
|
|
@@ -37127,6 +37163,12 @@ const useInteractiveProps = (props, {
|
|
|
37127
37163
|
// above it is told, so a form still submits and a popup still closes over a
|
|
37128
37164
|
// run that was meant to be left going.
|
|
37129
37165
|
uiStateController.actionStandalone = Boolean(actionStandalone);
|
|
37166
|
+
// Read by BUSY_CONSTRAINT: the wait holds what is around it as always, and
|
|
37167
|
+
// the person waiting may end it — closing the popup this control holds
|
|
37168
|
+
// calls the run off instead of being refused (see popup_busy.js). Read off
|
|
37169
|
+
// the control the run belongs to, so a field or a submit inheriting a
|
|
37170
|
+
// form's wait inherits this with it.
|
|
37171
|
+
uiStateController.actionAbortable = Boolean(actionAbortable);
|
|
37130
37172
|
// What the interaction rule last refused is only true while the control is
|
|
37131
37173
|
// held; the state it was read from moves here (see refreshReport).
|
|
37132
37174
|
useLayoutEffect(() => {
|
|
@@ -47720,6 +47762,7 @@ const COMMAND_DEFAULT_PROPS_FACTORIES = {
|
|
|
47720
47762
|
* whenSelfInteractionsBlocked?: "hide" | "refuse" | "ignore",
|
|
47721
47763
|
* replace?: boolean,
|
|
47722
47764
|
* actionStandalone?: boolean,
|
|
47765
|
+
* actionAbortable?: boolean,
|
|
47723
47766
|
* [key: string]: any,
|
|
47724
47767
|
* }>}
|
|
47725
47768
|
* @param {boolean} [replace] Go where the press leads — an `href`, a
|
|
@@ -47763,6 +47806,14 @@ const COMMAND_DEFAULT_PROPS_FACTORIES = {
|
|
|
47763
47806
|
* running, which the app watches from somewhere else; never for one holding
|
|
47764
47807
|
* an answer the screen is the only place to read (see
|
|
47765
47808
|
* docs/interactions.md#the-fourth-question-whose-wait-is-it).
|
|
47809
|
+
* @param {boolean} [actionAbortable] The person waiting may give up on this
|
|
47810
|
+
* button's action: closing the popup the run holds calls it off and goes
|
|
47811
|
+
* through, instead of being refused. For a run whose answer may never come —
|
|
47812
|
+
* a request over a network that stops answering — where a popup with no way
|
|
47813
|
+
* out is worse than an answer lost. Aborting frees the client and nothing
|
|
47814
|
+
* more: the work may already have happened on the other side (see
|
|
47815
|
+
* docs/actions.md#aborting-saves-resources-it-does-not-undo), so say it only
|
|
47816
|
+
* where the screen can be re-opened on what is actually there.
|
|
47766
47817
|
* @param {string} [contentDisplay] The display of the frame the button draws
|
|
47767
47818
|
* around its children. It follows the button's own by default — its display
|
|
47768
47819
|
* and, a display alone saying nothing about direction, the rest of its flow
|
|
@@ -56657,6 +56708,66 @@ const getAvailableWidth = (layer, element) => {
|
|
|
56657
56708
|
return visualViewportWidthSignal.peek();
|
|
56658
56709
|
};
|
|
56659
56710
|
|
|
56711
|
+
/**
|
|
56712
|
+
* What a popup asks before it closes: is anything inside it mid-action, and may
|
|
56713
|
+
* the person waiting call that wait off.
|
|
56714
|
+
*
|
|
56715
|
+
* A popup carries no state of its own — it is layout (see dialog.jsx's top
|
|
56716
|
+
* comment) — so it walks the controls it contains and asks each one. Asked
|
|
56717
|
+
* rather than read off `aria-busy`, which is a render snapshot: BUSY_CONSTRAINT
|
|
56718
|
+
* answers live.
|
|
56719
|
+
*
|
|
56720
|
+
* `Dialog` and `Popover` both read this way and read it identically, so it
|
|
56721
|
+
* lives here rather than in each of them: the answer decides whether a close
|
|
56722
|
+
* request goes through, and the two must not drift on that.
|
|
56723
|
+
*/
|
|
56724
|
+
|
|
56725
|
+
|
|
56726
|
+
/**
|
|
56727
|
+
* The controls keeping `popupEl` open: mid-action, and not saying the wait is
|
|
56728
|
+
* their own. `ignoredByParents` is that saying (`actionStandalone`) — a popup
|
|
56729
|
+
* is one more ancestor such a control does not hold, the same reading a group
|
|
56730
|
+
* makes of it (see control_interaction.js).
|
|
56731
|
+
*/
|
|
56732
|
+
const findControlsHoldingPopup = (popupEl) => {
|
|
56733
|
+
const controlsHolding = [];
|
|
56734
|
+
for (const element of popupEl.querySelectorAll("[navi-control-host]")) {
|
|
56735
|
+
const controller = element.__uiStateController__;
|
|
56736
|
+
if (!controller) {
|
|
56737
|
+
continue;
|
|
56738
|
+
}
|
|
56739
|
+
const busyInfo = BUSY_CONSTRAINT.check(controller);
|
|
56740
|
+
if (busyInfo && !busyInfo.ignoredByParents) {
|
|
56741
|
+
controlsHolding.push({
|
|
56742
|
+
element,
|
|
56743
|
+
controller,
|
|
56744
|
+
abortable: busyInfo.abortable,
|
|
56745
|
+
});
|
|
56746
|
+
}
|
|
56747
|
+
}
|
|
56748
|
+
return controlsHolding;
|
|
56749
|
+
};
|
|
56750
|
+
|
|
56751
|
+
/**
|
|
56752
|
+
* Give up on every run holding the popup, so that closing may go through.
|
|
56753
|
+
*
|
|
56754
|
+
* All or nothing: calling off one run while another still keeps the popup shut
|
|
56755
|
+
* would cost an answer and change nothing on screen. Several of these controls
|
|
56756
|
+
* usually share one run — a form and the fields and submit inside it — and the
|
|
56757
|
+
* ones asked after it has been called off simply find nothing to call off.
|
|
56758
|
+
*/
|
|
56759
|
+
const giveUpOnControlsHoldingPopup = (controlsHolding, reason) => {
|
|
56760
|
+
for (const controlHolding of controlsHolding) {
|
|
56761
|
+
if (!controlHolding.abortable) {
|
|
56762
|
+
return false;
|
|
56763
|
+
}
|
|
56764
|
+
}
|
|
56765
|
+
for (const controlHolding of controlsHolding) {
|
|
56766
|
+
abortControlRun(controlHolding.controller, reason);
|
|
56767
|
+
}
|
|
56768
|
+
return true;
|
|
56769
|
+
};
|
|
56770
|
+
|
|
56660
56771
|
/**
|
|
56661
56772
|
* Entry/exit animation CSS shared by Popover and Dialog.
|
|
56662
56773
|
*
|
|
@@ -57446,7 +57557,7 @@ const PopupClose = ({
|
|
|
57446
57557
|
// and what is opened has to be closable. Whether closing is allowed at
|
|
57447
57558
|
// this instant is the popup's own question, answered by the popup — a
|
|
57448
57559
|
// dialog holds the close while an action inside it runs (see
|
|
57449
|
-
//
|
|
57560
|
+
// popup_busy.js).
|
|
57450
57561
|
,
|
|
57451
57562
|
whenSelfInteractionsBlocked: "ignore"
|
|
57452
57563
|
// The cross is drawn at the control size, which is a few millimetres
|
|
@@ -58195,14 +58306,21 @@ const UncontrolledDialog = props => {
|
|
|
58195
58306
|
// dialog has no such state of its own to consult (it is layout — see
|
|
58196
58307
|
// this file's top comment), so it asks what it contains, and lets that
|
|
58197
58308
|
// control report why the way it would to anyone else.
|
|
58198
|
-
const
|
|
58199
|
-
if (
|
|
58200
|
-
|
|
58201
|
-
event: requestCloseEvent,
|
|
58202
|
-
name: "dialog request close"
|
|
58203
|
-
});
|
|
58204
|
-
requestCloseEvent.preventDefault();
|
|
58309
|
+
const controlsHolding = findControlsHoldingPopup(dialogEl);
|
|
58310
|
+
if (controlsHolding.length === 0) {
|
|
58311
|
+
return;
|
|
58205
58312
|
}
|
|
58313
|
+
// Unless every one of those runs was declared givable-up
|
|
58314
|
+
// (`actionAbortable`): the answer is not coming, closing is how the
|
|
58315
|
+
// person waiting says so, and the runs are called off on the way out.
|
|
58316
|
+
if (giveUpOnControlsHoldingPopup(controlsHolding, "the dialog holding the run was closed")) {
|
|
58317
|
+
return;
|
|
58318
|
+
}
|
|
58319
|
+
dispatchRequestInteraction(controlsHolding[0].element, {
|
|
58320
|
+
event: requestCloseEvent,
|
|
58321
|
+
name: "dialog request close"
|
|
58322
|
+
});
|
|
58323
|
+
requestCloseEvent.preventDefault();
|
|
58206
58324
|
},
|
|
58207
58325
|
onClose: closeEvent => {
|
|
58208
58326
|
props.onClose?.(closeEvent);
|
|
@@ -58322,29 +58440,6 @@ const DOCKED = {
|
|
|
58322
58440
|
// no header and nothing marked is not pushed down at all; it is closed by its
|
|
58323
58441
|
// own controls, by the backdrop and by Escape.
|
|
58324
58442
|
const DOCKED_SWIPE_GRIP = "[data-header],[data-swipe-grip]";
|
|
58325
|
-
|
|
58326
|
-
// The first control inside `dialogEl` that is mid-action, if any. Walks the
|
|
58327
|
-
// controls rather than reading an attribute off the dialog: a dialog carries no
|
|
58328
|
-
// state of its own (see this file's top comment), and `aria-busy` on the
|
|
58329
|
-
// controls is a render snapshot — BUSY_CONSTRAINT reads the live answer.
|
|
58330
|
-
// Same as Popover's own; kept in both rather than shared, since each file reads
|
|
58331
|
-
// on its own — what changes here changes there too.
|
|
58332
|
-
const findBusyElementInside$1 = dialogEl => {
|
|
58333
|
-
for (const element of dialogEl.querySelectorAll("[navi-control-host]")) {
|
|
58334
|
-
const controller = element.__uiStateController__;
|
|
58335
|
-
if (!controller) {
|
|
58336
|
-
continue;
|
|
58337
|
-
}
|
|
58338
|
-
const busyInfo = BUSY_CONSTRAINT.check(controller);
|
|
58339
|
-
// `ignoredByParents`: the control says the wait is its own
|
|
58340
|
-
// (`actionStandalone`), so a popup is one more ancestor it does not hold —
|
|
58341
|
-
// the same reading a group makes of it (see control_interaction.js).
|
|
58342
|
-
if (busyInfo && !busyInfo.ignoredByParents) {
|
|
58343
|
-
return element;
|
|
58344
|
-
}
|
|
58345
|
-
}
|
|
58346
|
-
return null;
|
|
58347
|
-
};
|
|
58348
58443
|
const useDialogProps = props => {
|
|
58349
58444
|
const backdropProps = {};
|
|
58350
58445
|
const contentProps = {};
|
|
@@ -59797,14 +59892,21 @@ const UncontrolledPopover = props => {
|
|
|
59797
59892
|
debugPopup(openEvent, `popover opened`);
|
|
59798
59893
|
return {
|
|
59799
59894
|
onRequestClose: requestCloseEvent => {
|
|
59800
|
-
const
|
|
59801
|
-
if (
|
|
59802
|
-
|
|
59803
|
-
event: requestCloseEvent,
|
|
59804
|
-
name: "popover request close"
|
|
59805
|
-
});
|
|
59806
|
-
requestCloseEvent.preventDefault();
|
|
59895
|
+
const controlsHolding = findControlsHoldingPopup(popoverEl);
|
|
59896
|
+
if (controlsHolding.length === 0) {
|
|
59897
|
+
return;
|
|
59807
59898
|
}
|
|
59899
|
+
// Unless every one of those runs was declared givable-up
|
|
59900
|
+
// (`actionAbortable`): the answer is not coming, closing is how the
|
|
59901
|
+
// person waiting says so, and the runs are called off on the way out.
|
|
59902
|
+
if (giveUpOnControlsHoldingPopup(controlsHolding, "the popover holding the run was closed")) {
|
|
59903
|
+
return;
|
|
59904
|
+
}
|
|
59905
|
+
dispatchRequestInteraction(controlsHolding[0].element, {
|
|
59906
|
+
event: requestCloseEvent,
|
|
59907
|
+
name: "popover request close"
|
|
59908
|
+
});
|
|
59909
|
+
requestCloseEvent.preventDefault();
|
|
59808
59910
|
},
|
|
59809
59911
|
onClose: closeEvent => {
|
|
59810
59912
|
props.onClose?.(closeEvent);
|
|
@@ -59913,28 +60015,6 @@ const PopoverCustom = props => {
|
|
|
59913
60015
|
* contentProps]` — two plain prop objects ready to spread onto a
|
|
59914
60016
|
* backdrop/content element each.
|
|
59915
60017
|
*/
|
|
59916
|
-
// The first control inside `popupEl` that is mid-action, if any. Walks the
|
|
59917
|
-
// controls rather than reading an attribute off the popup: a popup carries no
|
|
59918
|
-
// state of its own (see this file's top comment), and `aria-busy` on the
|
|
59919
|
-
// controls is a render snapshot — BUSY_CONSTRAINT reads the live answer.
|
|
59920
|
-
// Same as Dialog's own; kept in both rather than shared, since each file reads
|
|
59921
|
-
// on its own — what changes here changes there too.
|
|
59922
|
-
const findBusyElementInside = popupEl => {
|
|
59923
|
-
for (const element of popupEl.querySelectorAll("[navi-control-host]")) {
|
|
59924
|
-
const controller = element.__uiStateController__;
|
|
59925
|
-
if (!controller) {
|
|
59926
|
-
continue;
|
|
59927
|
-
}
|
|
59928
|
-
const busyInfo = BUSY_CONSTRAINT.check(controller);
|
|
59929
|
-
// `ignoredByParents`: the control says the wait is its own
|
|
59930
|
-
// (`actionStandalone`), so a popup is one more ancestor it does not hold —
|
|
59931
|
-
// the same reading a group makes of it (see control_interaction.js).
|
|
59932
|
-
if (busyInfo && !busyInfo.ignoredByParents) {
|
|
59933
|
-
return element;
|
|
59934
|
-
}
|
|
59935
|
-
}
|
|
59936
|
-
return null;
|
|
59937
|
-
};
|
|
59938
60018
|
const usePopoverProps = props => {
|
|
59939
60019
|
const backdropProps = {};
|
|
59940
60020
|
const contentProps = {};
|