@jsenv/navi 0.29.225 → 0.29.227
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/README.md +2 -0
- package/dist/dev/jsenv_navi.js +168 -115
- package/dist/dev/jsenv_navi.js.map +13 -12
- package/dist/jsenv_navi.js +168 -115
- package/dist/jsenv_navi.js.map +13 -12
- package/docs/AI_INSTRUCTIONS.md +8 -6
- package/docs/dynamic_import.md +118 -69
- package/docs/interactions.md +7 -0
- package/docs/popup_open.md +31 -4
- package/package.json +1 -1
package/dist/jsenv_navi.js
CHANGED
|
@@ -5158,6 +5158,9 @@ const CONTROL_PROP_SET = new Set([
|
|
|
5158
5158
|
// The wait this control's action creates is its own: it renders busy and
|
|
5159
5159
|
// refuses a second press, and nothing above it is told (see BUSY_CONSTRAINT).
|
|
5160
5160
|
"actionStandalone",
|
|
5161
|
+
// The wait this control's action creates may be called off by the person
|
|
5162
|
+
// waiting: closing the popup it holds gives up on the run (see popup_busy.js).
|
|
5163
|
+
"actionAbortable",
|
|
5161
5164
|
|
|
5162
5165
|
"charGuard",
|
|
5163
5166
|
"maxLengthGuard",
|
|
@@ -7867,11 +7870,10 @@ const BUSY_CONSTRAINT = {
|
|
|
7867
7870
|
// Unless it says the wait is its own (`actionStandalone`): then the refusal
|
|
7868
7871
|
// stays on the element and every ancestor reads it as free — the group above
|
|
7869
7872
|
// (see getInteractionBlockingControls) and the popup around it (see
|
|
7870
|
-
//
|
|
7871
|
-
// `ignoredByParents`).
|
|
7873
|
+
// popup_busy.js, which filters on `ignoredByParents`).
|
|
7872
7874
|
check: (field, { intent } = {}) => {
|
|
7873
|
-
const
|
|
7874
|
-
if (!
|
|
7875
|
+
const busySource = findBusySource(field);
|
|
7876
|
+
if (!busySource) {
|
|
7875
7877
|
return null;
|
|
7876
7878
|
}
|
|
7877
7879
|
|
|
@@ -7892,11 +7894,31 @@ const BUSY_CONSTRAINT = {
|
|
|
7892
7894
|
message,
|
|
7893
7895
|
status: "info",
|
|
7894
7896
|
ignoredByParents: Boolean(field.actionStandalone),
|
|
7897
|
+
// Read off the control the run belongs to, not off this one: a field or a
|
|
7898
|
+
// submit button inherits its form's wait, so it inherits with it whether
|
|
7899
|
+
// the person waiting is allowed to call that wait off (see
|
|
7900
|
+
// abortControlRun, and `actionAbortable` in control_hooks.jsx).
|
|
7901
|
+
abortable: Boolean(busySource.action && busySource.field.actionAbortable),
|
|
7895
7902
|
};
|
|
7896
7903
|
},
|
|
7897
7904
|
};
|
|
7898
7905
|
CONSTRAINT_ATTRIBUTE_SET.add("data-busy");
|
|
7899
7906
|
|
|
7907
|
+
/**
|
|
7908
|
+
* Give up on the run that makes `field` busy — the person waiting deciding the
|
|
7909
|
+
* answer is not coming. The work is not undone: aborting frees the client and
|
|
7910
|
+
* nothing more, the server may already have done it (see docs/actions.md,
|
|
7911
|
+
* "Aborting saves resources, it does not undo"). What ends is the wait, and
|
|
7912
|
+
* with it every refusal held by it.
|
|
7913
|
+
*/
|
|
7914
|
+
const abortControlRun = (field, reason) => {
|
|
7915
|
+
const busySource = findBusySource(field);
|
|
7916
|
+
if (!busySource || !busySource.action) {
|
|
7917
|
+
return false;
|
|
7918
|
+
}
|
|
7919
|
+
return busySource.action.abort(reason);
|
|
7920
|
+
};
|
|
7921
|
+
|
|
7900
7922
|
// Asked source by source rather than off the rendered `aria-busy`, which
|
|
7901
7923
|
// conflates them and is a frame behind: that attribute is written during
|
|
7902
7924
|
// render, so it still says "true" for the whole tick in which an action
|
|
@@ -7908,9 +7930,15 @@ CONSTRAINT_ATTRIBUTE_SET.add("data-busy");
|
|
|
7908
7930
|
// control busy only because the group above is waiting has no state of its own
|
|
7909
7931
|
// to read — the group's answer IS its answer, so it asks upward and inherits
|
|
7910
7932
|
// the same live reading.
|
|
7911
|
-
|
|
7933
|
+
//
|
|
7934
|
+
// What comes back is the control the wait BELONGS to, and the running action
|
|
7935
|
+
// when there is one, because two questions are asked of it: whether this
|
|
7936
|
+
// control is busy at all, and what giving up on that wait would mean.
|
|
7937
|
+
const findBusySource = (field) => {
|
|
7912
7938
|
if (field.loadingFromOwnProp) {
|
|
7913
|
-
|
|
7939
|
+
// A `loading` prop is a wait the app draws itself; there is no run behind
|
|
7940
|
+
// it to call off.
|
|
7941
|
+
return { field, action: null };
|
|
7914
7942
|
}
|
|
7915
7943
|
const { boundAction } = field;
|
|
7916
7944
|
// An optimistic control stays interactive while its bound action runs:
|
|
@@ -7928,14 +7956,14 @@ const isControlBusy = (field) => {
|
|
|
7928
7956
|
// cannot move mid-run, this very gate blocks it.
|
|
7929
7957
|
const liveAction = boundAction.getCurrentAction?.() ?? boundAction;
|
|
7930
7958
|
if (liveAction.runningStateSignal.value === RUNNING) {
|
|
7931
|
-
return
|
|
7959
|
+
return { field, action: liveAction };
|
|
7932
7960
|
}
|
|
7933
7961
|
}
|
|
7934
7962
|
if (field.loadingFromAbove) {
|
|
7935
7963
|
const parent = field.parentUIStateController;
|
|
7936
|
-
return parent ?
|
|
7964
|
+
return parent ? findBusySource(parent) : null;
|
|
7937
7965
|
}
|
|
7938
|
-
return
|
|
7966
|
+
return null;
|
|
7939
7967
|
};
|
|
7940
7968
|
|
|
7941
7969
|
const DISABLED_CONSTRAINT = {
|
|
@@ -23611,50 +23639,30 @@ const parsePattern = (
|
|
|
23611
23639
|
};
|
|
23612
23640
|
|
|
23613
23641
|
/**
|
|
23614
|
-
*
|
|
23642
|
+
* A literal segment the url stops short of is optional when an ancestor
|
|
23643
|
+
* pattern has a path param AT THAT SAME POSITION whose default is this word:
|
|
23644
|
+
* "/admin/settings/:tab" is the page "/admin" opens on when "/admin/:section"
|
|
23645
|
+
* defaults to "settings". Only the connection occupying the segment's index
|
|
23646
|
+
* may excuse it — a query param, or a param sitting elsewhere, says nothing
|
|
23647
|
+
* about this position, so a state defaulting to "games" must not turn
|
|
23648
|
+
* "/places/:slug/games" into a match for "/places/:slug".
|
|
23615
23649
|
*/
|
|
23616
23650
|
const checkIfLiteralCanBeOptionalWithPatternObj = (
|
|
23617
|
-
|
|
23651
|
+
literalSegment,
|
|
23618
23652
|
patternObj,
|
|
23619
23653
|
) => {
|
|
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)) {
|
|
23654
|
+
let ancestor = patternObj ? patternObj.parent : null;
|
|
23655
|
+
while (ancestor) {
|
|
23656
|
+
const ancestorSegment = ancestor.pattern.segments[literalSegment.index];
|
|
23657
|
+
if (ancestorSegment && ancestorSegment.type === "param") {
|
|
23658
|
+
const connection = ancestor.pathConnectionMap.get(ancestorSegment.name);
|
|
23659
|
+
if (connection && connection.isDefaultValue(literalSegment.value)) {
|
|
23636
23660
|
return true;
|
|
23637
23661
|
}
|
|
23638
23662
|
}
|
|
23639
|
-
|
|
23663
|
+
ancestor = ancestor.parent;
|
|
23640
23664
|
}
|
|
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);
|
|
23665
|
+
return false;
|
|
23658
23666
|
};
|
|
23659
23667
|
|
|
23660
23668
|
/**
|
|
@@ -23799,9 +23807,8 @@ const matchUrl = (
|
|
|
23799
23807
|
// Check if URL has this segment
|
|
23800
23808
|
if (urlSegmentIndex >= urlSegments.length) {
|
|
23801
23809
|
// URL is too short for this literal segment
|
|
23802
|
-
// Check if this literal segment can be treated as optional based on pattern hierarchy
|
|
23803
23810
|
const canBeOptional = checkIfLiteralCanBeOptionalWithPatternObj(
|
|
23804
|
-
patternSeg
|
|
23811
|
+
patternSeg,
|
|
23805
23812
|
patternObj,
|
|
23806
23813
|
);
|
|
23807
23814
|
if (canBeOptional) {
|
|
@@ -30841,22 +30848,23 @@ const routeAction = (
|
|
|
30841
30848
|
|
|
30842
30849
|
// The instance the effect above runs on the match is the one bound to `true`
|
|
30843
30850
|
// (the default params), so a prerun here is what the arrival promotes to a
|
|
30844
|
-
// run. A prefetch that fails is
|
|
30845
|
-
//
|
|
30851
|
+
// run. A prefetch that fails is not reported: nothing on screen asked for it,
|
|
30852
|
+
// and the failure stays on the instance, where a run asks again — a FAILED
|
|
30853
|
+
// action is run, only RUNNING and COMPLETED are left alone — and the arrival
|
|
30854
|
+
// shows its own. It is left FAILED on purpose, not reset: the press that
|
|
30855
|
+
// brings the arrival also focuses the link, so a prerun can be in flight when
|
|
30856
|
+
// the arrival promotes it, and a reset landing after that would pull the
|
|
30857
|
+
// answer from under the page that is reading it.
|
|
30846
30858
|
const prefetchParamless = (action) => {
|
|
30847
30859
|
const instance = action.bindParams(true);
|
|
30848
|
-
const forget = () => {
|
|
30849
|
-
instance.reset({ reason: "prefetch failed" });
|
|
30850
|
-
};
|
|
30851
30860
|
let result;
|
|
30852
30861
|
try {
|
|
30853
30862
|
result = instance.prerun({ reason: "intent" });
|
|
30854
30863
|
} catch {
|
|
30855
|
-
forget();
|
|
30856
30864
|
return;
|
|
30857
30865
|
}
|
|
30858
30866
|
if (result && typeof result.catch === "function") {
|
|
30859
|
-
result.catch(
|
|
30867
|
+
result.catch(() => {});
|
|
30860
30868
|
}
|
|
30861
30869
|
};
|
|
30862
30870
|
|
|
@@ -37062,7 +37070,8 @@ const useInteractiveProps = (props, {
|
|
|
37062
37070
|
readOnly,
|
|
37063
37071
|
loading,
|
|
37064
37072
|
optimistic,
|
|
37065
|
-
actionStandalone
|
|
37073
|
+
actionStandalone,
|
|
37074
|
+
actionAbortable
|
|
37066
37075
|
} = props;
|
|
37067
37076
|
|
|
37068
37077
|
// `whenSelfInteractionsBlocked="ignore"`: an affordance that writes nothing
|
|
@@ -37126,6 +37135,12 @@ const useInteractiveProps = (props, {
|
|
|
37126
37135
|
// above it is told, so a form still submits and a popup still closes over a
|
|
37127
37136
|
// run that was meant to be left going.
|
|
37128
37137
|
uiStateController.actionStandalone = Boolean(actionStandalone);
|
|
37138
|
+
// Read by BUSY_CONSTRAINT: the wait holds what is around it as always, and
|
|
37139
|
+
// the person waiting may end it — closing the popup this control holds
|
|
37140
|
+
// calls the run off instead of being refused (see popup_busy.js). Read off
|
|
37141
|
+
// the control the run belongs to, so a field or a submit inheriting a
|
|
37142
|
+
// form's wait inherits this with it.
|
|
37143
|
+
uiStateController.actionAbortable = Boolean(actionAbortable);
|
|
37129
37144
|
// What the interaction rule last refused is only true while the control is
|
|
37130
37145
|
// held; the state it was read from moves here (see refreshReport).
|
|
37131
37146
|
useLayoutEffect(() => {
|
|
@@ -47719,6 +47734,7 @@ const COMMAND_DEFAULT_PROPS_FACTORIES = {
|
|
|
47719
47734
|
* whenSelfInteractionsBlocked?: "hide" | "refuse" | "ignore",
|
|
47720
47735
|
* replace?: boolean,
|
|
47721
47736
|
* actionStandalone?: boolean,
|
|
47737
|
+
* actionAbortable?: boolean,
|
|
47722
47738
|
* [key: string]: any,
|
|
47723
47739
|
* }>}
|
|
47724
47740
|
* @param {boolean} [replace] Go where the press leads — an `href`, a
|
|
@@ -47762,6 +47778,14 @@ const COMMAND_DEFAULT_PROPS_FACTORIES = {
|
|
|
47762
47778
|
* running, which the app watches from somewhere else; never for one holding
|
|
47763
47779
|
* an answer the screen is the only place to read (see
|
|
47764
47780
|
* docs/interactions.md#the-fourth-question-whose-wait-is-it).
|
|
47781
|
+
* @param {boolean} [actionAbortable] The person waiting may give up on this
|
|
47782
|
+
* button's action: closing the popup the run holds calls it off and goes
|
|
47783
|
+
* through, instead of being refused. For a run whose answer may never come —
|
|
47784
|
+
* a request over a network that stops answering — where a popup with no way
|
|
47785
|
+
* out is worse than an answer lost. Aborting frees the client and nothing
|
|
47786
|
+
* more: the work may already have happened on the other side (see
|
|
47787
|
+
* docs/actions.md#aborting-saves-resources-it-does-not-undo), so say it only
|
|
47788
|
+
* where the screen can be re-opened on what is actually there.
|
|
47765
47789
|
* @param {string} [contentDisplay] The display of the frame the button draws
|
|
47766
47790
|
* around its children. It follows the button's own by default — its display
|
|
47767
47791
|
* and, a display alone saying nothing about direction, the rest of its flow
|
|
@@ -56656,6 +56680,66 @@ const getAvailableWidth = (layer, element) => {
|
|
|
56656
56680
|
return visualViewportWidthSignal.peek();
|
|
56657
56681
|
};
|
|
56658
56682
|
|
|
56683
|
+
/**
|
|
56684
|
+
* What a popup asks before it closes: is anything inside it mid-action, and may
|
|
56685
|
+
* the person waiting call that wait off.
|
|
56686
|
+
*
|
|
56687
|
+
* A popup carries no state of its own — it is layout (see dialog.jsx's top
|
|
56688
|
+
* comment) — so it walks the controls it contains and asks each one. Asked
|
|
56689
|
+
* rather than read off `aria-busy`, which is a render snapshot: BUSY_CONSTRAINT
|
|
56690
|
+
* answers live.
|
|
56691
|
+
*
|
|
56692
|
+
* `Dialog` and `Popover` both read this way and read it identically, so it
|
|
56693
|
+
* lives here rather than in each of them: the answer decides whether a close
|
|
56694
|
+
* request goes through, and the two must not drift on that.
|
|
56695
|
+
*/
|
|
56696
|
+
|
|
56697
|
+
|
|
56698
|
+
/**
|
|
56699
|
+
* The controls keeping `popupEl` open: mid-action, and not saying the wait is
|
|
56700
|
+
* their own. `ignoredByParents` is that saying (`actionStandalone`) — a popup
|
|
56701
|
+
* is one more ancestor such a control does not hold, the same reading a group
|
|
56702
|
+
* makes of it (see control_interaction.js).
|
|
56703
|
+
*/
|
|
56704
|
+
const findControlsHoldingPopup = (popupEl) => {
|
|
56705
|
+
const controlsHolding = [];
|
|
56706
|
+
for (const element of popupEl.querySelectorAll("[navi-control-host]")) {
|
|
56707
|
+
const controller = element.__uiStateController__;
|
|
56708
|
+
if (!controller) {
|
|
56709
|
+
continue;
|
|
56710
|
+
}
|
|
56711
|
+
const busyInfo = BUSY_CONSTRAINT.check(controller);
|
|
56712
|
+
if (busyInfo && !busyInfo.ignoredByParents) {
|
|
56713
|
+
controlsHolding.push({
|
|
56714
|
+
element,
|
|
56715
|
+
controller,
|
|
56716
|
+
abortable: busyInfo.abortable,
|
|
56717
|
+
});
|
|
56718
|
+
}
|
|
56719
|
+
}
|
|
56720
|
+
return controlsHolding;
|
|
56721
|
+
};
|
|
56722
|
+
|
|
56723
|
+
/**
|
|
56724
|
+
* Give up on every run holding the popup, so that closing may go through.
|
|
56725
|
+
*
|
|
56726
|
+
* All or nothing: calling off one run while another still keeps the popup shut
|
|
56727
|
+
* would cost an answer and change nothing on screen. Several of these controls
|
|
56728
|
+
* usually share one run — a form and the fields and submit inside it — and the
|
|
56729
|
+
* ones asked after it has been called off simply find nothing to call off.
|
|
56730
|
+
*/
|
|
56731
|
+
const giveUpOnControlsHoldingPopup = (controlsHolding, reason) => {
|
|
56732
|
+
for (const controlHolding of controlsHolding) {
|
|
56733
|
+
if (!controlHolding.abortable) {
|
|
56734
|
+
return false;
|
|
56735
|
+
}
|
|
56736
|
+
}
|
|
56737
|
+
for (const controlHolding of controlsHolding) {
|
|
56738
|
+
abortControlRun(controlHolding.controller, reason);
|
|
56739
|
+
}
|
|
56740
|
+
return true;
|
|
56741
|
+
};
|
|
56742
|
+
|
|
56659
56743
|
/**
|
|
56660
56744
|
* Entry/exit animation CSS shared by Popover and Dialog.
|
|
56661
56745
|
*
|
|
@@ -57445,7 +57529,7 @@ const PopupClose = ({
|
|
|
57445
57529
|
// and what is opened has to be closable. Whether closing is allowed at
|
|
57446
57530
|
// this instant is the popup's own question, answered by the popup — a
|
|
57447
57531
|
// dialog holds the close while an action inside it runs (see
|
|
57448
|
-
//
|
|
57532
|
+
// popup_busy.js).
|
|
57449
57533
|
,
|
|
57450
57534
|
whenSelfInteractionsBlocked: "ignore"
|
|
57451
57535
|
// The cross is drawn at the control size, which is a few millimetres
|
|
@@ -58194,14 +58278,21 @@ const UncontrolledDialog = props => {
|
|
|
58194
58278
|
// dialog has no such state of its own to consult (it is layout — see
|
|
58195
58279
|
// this file's top comment), so it asks what it contains, and lets that
|
|
58196
58280
|
// control report why the way it would to anyone else.
|
|
58197
|
-
const
|
|
58198
|
-
if (
|
|
58199
|
-
|
|
58200
|
-
|
|
58201
|
-
|
|
58202
|
-
|
|
58203
|
-
|
|
58281
|
+
const controlsHolding = findControlsHoldingPopup(dialogEl);
|
|
58282
|
+
if (controlsHolding.length === 0) {
|
|
58283
|
+
return;
|
|
58284
|
+
}
|
|
58285
|
+
// Unless every one of those runs was declared givable-up
|
|
58286
|
+
// (`actionAbortable`): the answer is not coming, closing is how the
|
|
58287
|
+
// person waiting says so, and the runs are called off on the way out.
|
|
58288
|
+
if (giveUpOnControlsHoldingPopup(controlsHolding, "the dialog holding the run was closed")) {
|
|
58289
|
+
return;
|
|
58204
58290
|
}
|
|
58291
|
+
dispatchRequestInteraction(controlsHolding[0].element, {
|
|
58292
|
+
event: requestCloseEvent,
|
|
58293
|
+
name: "dialog request close"
|
|
58294
|
+
});
|
|
58295
|
+
requestCloseEvent.preventDefault();
|
|
58205
58296
|
},
|
|
58206
58297
|
onClose: closeEvent => {
|
|
58207
58298
|
props.onClose?.(closeEvent);
|
|
@@ -58321,29 +58412,6 @@ const DOCKED = {
|
|
|
58321
58412
|
// no header and nothing marked is not pushed down at all; it is closed by its
|
|
58322
58413
|
// own controls, by the backdrop and by Escape.
|
|
58323
58414
|
const DOCKED_SWIPE_GRIP = "[data-header],[data-swipe-grip]";
|
|
58324
|
-
|
|
58325
|
-
// The first control inside `dialogEl` that is mid-action, if any. Walks the
|
|
58326
|
-
// controls rather than reading an attribute off the dialog: a dialog carries no
|
|
58327
|
-
// state of its own (see this file's top comment), and `aria-busy` on the
|
|
58328
|
-
// controls is a render snapshot — BUSY_CONSTRAINT reads the live answer.
|
|
58329
|
-
// Same as Popover's own; kept in both rather than shared, since each file reads
|
|
58330
|
-
// on its own — what changes here changes there too.
|
|
58331
|
-
const findBusyElementInside$1 = dialogEl => {
|
|
58332
|
-
for (const element of dialogEl.querySelectorAll("[navi-control-host]")) {
|
|
58333
|
-
const controller = element.__uiStateController__;
|
|
58334
|
-
if (!controller) {
|
|
58335
|
-
continue;
|
|
58336
|
-
}
|
|
58337
|
-
const busyInfo = BUSY_CONSTRAINT.check(controller);
|
|
58338
|
-
// `ignoredByParents`: the control says the wait is its own
|
|
58339
|
-
// (`actionStandalone`), so a popup is one more ancestor it does not hold —
|
|
58340
|
-
// the same reading a group makes of it (see control_interaction.js).
|
|
58341
|
-
if (busyInfo && !busyInfo.ignoredByParents) {
|
|
58342
|
-
return element;
|
|
58343
|
-
}
|
|
58344
|
-
}
|
|
58345
|
-
return null;
|
|
58346
|
-
};
|
|
58347
58415
|
const useDialogProps = props => {
|
|
58348
58416
|
const backdropProps = {};
|
|
58349
58417
|
const contentProps = {};
|
|
@@ -59796,14 +59864,21 @@ const UncontrolledPopover = props => {
|
|
|
59796
59864
|
debugPopup(openEvent, `popover opened`);
|
|
59797
59865
|
return {
|
|
59798
59866
|
onRequestClose: requestCloseEvent => {
|
|
59799
|
-
const
|
|
59800
|
-
if (
|
|
59801
|
-
|
|
59802
|
-
|
|
59803
|
-
|
|
59804
|
-
|
|
59805
|
-
|
|
59867
|
+
const controlsHolding = findControlsHoldingPopup(popoverEl);
|
|
59868
|
+
if (controlsHolding.length === 0) {
|
|
59869
|
+
return;
|
|
59870
|
+
}
|
|
59871
|
+
// Unless every one of those runs was declared givable-up
|
|
59872
|
+
// (`actionAbortable`): the answer is not coming, closing is how the
|
|
59873
|
+
// person waiting says so, and the runs are called off on the way out.
|
|
59874
|
+
if (giveUpOnControlsHoldingPopup(controlsHolding, "the popover holding the run was closed")) {
|
|
59875
|
+
return;
|
|
59806
59876
|
}
|
|
59877
|
+
dispatchRequestInteraction(controlsHolding[0].element, {
|
|
59878
|
+
event: requestCloseEvent,
|
|
59879
|
+
name: "popover request close"
|
|
59880
|
+
});
|
|
59881
|
+
requestCloseEvent.preventDefault();
|
|
59807
59882
|
},
|
|
59808
59883
|
onClose: closeEvent => {
|
|
59809
59884
|
props.onClose?.(closeEvent);
|
|
@@ -59912,28 +59987,6 @@ const PopoverCustom = props => {
|
|
|
59912
59987
|
* contentProps]` — two plain prop objects ready to spread onto a
|
|
59913
59988
|
* backdrop/content element each.
|
|
59914
59989
|
*/
|
|
59915
|
-
// The first control inside `popupEl` that is mid-action, if any. Walks the
|
|
59916
|
-
// controls rather than reading an attribute off the popup: a popup carries no
|
|
59917
|
-
// state of its own (see this file's top comment), and `aria-busy` on the
|
|
59918
|
-
// controls is a render snapshot — BUSY_CONSTRAINT reads the live answer.
|
|
59919
|
-
// Same as Dialog's own; kept in both rather than shared, since each file reads
|
|
59920
|
-
// on its own — what changes here changes there too.
|
|
59921
|
-
const findBusyElementInside = popupEl => {
|
|
59922
|
-
for (const element of popupEl.querySelectorAll("[navi-control-host]")) {
|
|
59923
|
-
const controller = element.__uiStateController__;
|
|
59924
|
-
if (!controller) {
|
|
59925
|
-
continue;
|
|
59926
|
-
}
|
|
59927
|
-
const busyInfo = BUSY_CONSTRAINT.check(controller);
|
|
59928
|
-
// `ignoredByParents`: the control says the wait is its own
|
|
59929
|
-
// (`actionStandalone`), so a popup is one more ancestor it does not hold —
|
|
59930
|
-
// the same reading a group makes of it (see control_interaction.js).
|
|
59931
|
-
if (busyInfo && !busyInfo.ignoredByParents) {
|
|
59932
|
-
return element;
|
|
59933
|
-
}
|
|
59934
|
-
}
|
|
59935
|
-
return null;
|
|
59936
|
-
};
|
|
59937
59990
|
const usePopoverProps = props => {
|
|
59938
59991
|
const backdropProps = {};
|
|
59939
59992
|
const contentProps = {};
|