@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/dev/jsenv_navi.js
CHANGED
|
@@ -3209,6 +3209,12 @@ const actionWeakMap = new WeakMap();
|
|
|
3209
3209
|
*
|
|
3210
3210
|
* @param {Function} callback
|
|
3211
3211
|
* @param {object} [rootOptions]
|
|
3212
|
+
* @param {(params: any, action: object) => any} [rootOptions.provisionalValue] -
|
|
3213
|
+
* a value the action holds while a run is in flight and it has none of its
|
|
3214
|
+
* own, so a screen already knowing the answer draws it as a refresh rather
|
|
3215
|
+
* than a first load (data_states.md). Called at the start of every run whose
|
|
3216
|
+
* value is undefined; the answer replaces it as usual, and `undefined` means
|
|
3217
|
+
* "nothing known". A resource `GET` uses it to draw the row its store holds.
|
|
3212
3218
|
* @param {{ ms?: number, max?: number }} [rootOptions.keep] - how long an
|
|
3213
3219
|
* answer stays good once it has landed. Without it an answer lives exactly as
|
|
3214
3220
|
* long as something references it: the screen that asked goes away, and
|
|
@@ -3248,6 +3254,7 @@ const createAction = (callback, rootOptions = {}) => {
|
|
|
3248
3254
|
value,
|
|
3249
3255
|
resultToValue,
|
|
3250
3256
|
valueToData,
|
|
3257
|
+
provisionalValue,
|
|
3251
3258
|
dataDefault,
|
|
3252
3259
|
data = dataDefault,
|
|
3253
3260
|
|
|
@@ -3706,6 +3713,12 @@ const createAction = (callback, rootOptions = {}) => {
|
|
|
3706
3713
|
actionAbortMap.set(action, abort);
|
|
3707
3714
|
|
|
3708
3715
|
batch(() => {
|
|
3716
|
+
if (provisionalValue && valueSignal.peek() === undefined) {
|
|
3717
|
+
const provisional = provisionalValue(params, action);
|
|
3718
|
+
if (provisional !== undefined) {
|
|
3719
|
+
valueSignal.value = provisional;
|
|
3720
|
+
}
|
|
3721
|
+
}
|
|
3709
3722
|
runningStateSignal.value = RUNNING;
|
|
3710
3723
|
if (!isPrerun) {
|
|
3711
3724
|
isPrerunSignal.value = false;
|
|
@@ -5249,6 +5262,9 @@ const CONTROL_PROP_SET = new Set([
|
|
|
5249
5262
|
// The wait this control's action creates is its own: it renders busy and
|
|
5250
5263
|
// refuses a second press, and nothing above it is told (see BUSY_CONSTRAINT).
|
|
5251
5264
|
"actionStandalone",
|
|
5265
|
+
// The wait this control's action creates may be called off by the person
|
|
5266
|
+
// waiting: closing the popup it holds gives up on the run (see popup_busy.js).
|
|
5267
|
+
"actionAbortable",
|
|
5252
5268
|
|
|
5253
5269
|
"charGuard",
|
|
5254
5270
|
"maxLengthGuard",
|
|
@@ -8013,11 +8029,10 @@ const BUSY_CONSTRAINT = {
|
|
|
8013
8029
|
// Unless it says the wait is its own (`actionStandalone`): then the refusal
|
|
8014
8030
|
// stays on the element and every ancestor reads it as free — the group above
|
|
8015
8031
|
// (see getInteractionBlockingControls) and the popup around it (see
|
|
8016
|
-
//
|
|
8017
|
-
// `ignoredByParents`).
|
|
8032
|
+
// popup_busy.js, which filters on `ignoredByParents`).
|
|
8018
8033
|
check: (field, { intent } = {}) => {
|
|
8019
|
-
const
|
|
8020
|
-
if (!
|
|
8034
|
+
const busySource = findBusySource(field);
|
|
8035
|
+
if (!busySource) {
|
|
8021
8036
|
return null;
|
|
8022
8037
|
}
|
|
8023
8038
|
|
|
@@ -8038,11 +8053,31 @@ const BUSY_CONSTRAINT = {
|
|
|
8038
8053
|
message,
|
|
8039
8054
|
status: "info",
|
|
8040
8055
|
ignoredByParents: Boolean(field.actionStandalone),
|
|
8056
|
+
// Read off the control the run belongs to, not off this one: a field or a
|
|
8057
|
+
// submit button inherits its form's wait, so it inherits with it whether
|
|
8058
|
+
// the person waiting is allowed to call that wait off (see
|
|
8059
|
+
// abortControlRun, and `actionAbortable` in control_hooks.jsx).
|
|
8060
|
+
abortable: Boolean(busySource.action && busySource.field.actionAbortable),
|
|
8041
8061
|
};
|
|
8042
8062
|
},
|
|
8043
8063
|
};
|
|
8044
8064
|
CONSTRAINT_ATTRIBUTE_SET.add("data-busy");
|
|
8045
8065
|
|
|
8066
|
+
/**
|
|
8067
|
+
* Give up on the run that makes `field` busy — the person waiting deciding the
|
|
8068
|
+
* answer is not coming. The work is not undone: aborting frees the client and
|
|
8069
|
+
* nothing more, the server may already have done it (see docs/actions.md,
|
|
8070
|
+
* "Aborting saves resources, it does not undo"). What ends is the wait, and
|
|
8071
|
+
* with it every refusal held by it.
|
|
8072
|
+
*/
|
|
8073
|
+
const abortControlRun = (field, reason) => {
|
|
8074
|
+
const busySource = findBusySource(field);
|
|
8075
|
+
if (!busySource || !busySource.action) {
|
|
8076
|
+
return false;
|
|
8077
|
+
}
|
|
8078
|
+
return busySource.action.abort(reason);
|
|
8079
|
+
};
|
|
8080
|
+
|
|
8046
8081
|
// Asked source by source rather than off the rendered `aria-busy`, which
|
|
8047
8082
|
// conflates them and is a frame behind: that attribute is written during
|
|
8048
8083
|
// render, so it still says "true" for the whole tick in which an action
|
|
@@ -8054,9 +8089,15 @@ CONSTRAINT_ATTRIBUTE_SET.add("data-busy");
|
|
|
8054
8089
|
// control busy only because the group above is waiting has no state of its own
|
|
8055
8090
|
// to read — the group's answer IS its answer, so it asks upward and inherits
|
|
8056
8091
|
// the same live reading.
|
|
8057
|
-
|
|
8092
|
+
//
|
|
8093
|
+
// What comes back is the control the wait BELONGS to, and the running action
|
|
8094
|
+
// when there is one, because two questions are asked of it: whether this
|
|
8095
|
+
// control is busy at all, and what giving up on that wait would mean.
|
|
8096
|
+
const findBusySource = (field) => {
|
|
8058
8097
|
if (field.loadingFromOwnProp) {
|
|
8059
|
-
|
|
8098
|
+
// A `loading` prop is a wait the app draws itself; there is no run behind
|
|
8099
|
+
// it to call off.
|
|
8100
|
+
return { field, action: null };
|
|
8060
8101
|
}
|
|
8061
8102
|
const { boundAction } = field;
|
|
8062
8103
|
// An optimistic control stays interactive while its bound action runs:
|
|
@@ -8074,14 +8115,14 @@ const isControlBusy = (field) => {
|
|
|
8074
8115
|
// cannot move mid-run, this very gate blocks it.
|
|
8075
8116
|
const liveAction = boundAction.getCurrentAction?.() ?? boundAction;
|
|
8076
8117
|
if (liveAction.runningStateSignal.value === RUNNING) {
|
|
8077
|
-
return
|
|
8118
|
+
return { field, action: liveAction };
|
|
8078
8119
|
}
|
|
8079
8120
|
}
|
|
8080
8121
|
if (field.loadingFromAbove) {
|
|
8081
8122
|
const parent = field.parentUIStateController;
|
|
8082
|
-
return parent ?
|
|
8123
|
+
return parent ? findBusySource(parent) : null;
|
|
8083
8124
|
}
|
|
8084
|
-
return
|
|
8125
|
+
return null;
|
|
8085
8126
|
};
|
|
8086
8127
|
|
|
8087
8128
|
const DISABLED_CONSTRAINT = {
|
|
@@ -15101,17 +15142,15 @@ const resource = (
|
|
|
15101
15142
|
return item;
|
|
15102
15143
|
},
|
|
15103
15144
|
});
|
|
15104
|
-
const createRestActionForRoot = createRestActionFactoryForRoot(name, {
|
|
15105
|
-
idKey,
|
|
15106
|
-
store,
|
|
15107
|
-
declarationSite,
|
|
15108
|
-
});
|
|
15109
15145
|
// The row a GET designates, when the store already holds it — by its params:
|
|
15110
15146
|
// the value under idKey may be the id or any unique key (a route opening a
|
|
15111
15147
|
// user by id or by slug names both `id`), and a unique key may be given under
|
|
15112
|
-
// its own name
|
|
15113
|
-
//
|
|
15114
|
-
//
|
|
15148
|
+
// its own name. findItemByParams is what a GET draws while its request is in
|
|
15149
|
+
// flight (the action's provisionalValue). findItemInStore adds, when the
|
|
15150
|
+
// params name no row (a GET without params, or whose params carry no key),
|
|
15151
|
+
// the row the action last completed with: that fallback answers a GET under
|
|
15152
|
+
// a network policy (see applyNetworkPolicy) and only there — a GET of a row
|
|
15153
|
+
// the store lacks must draw its skeleton, never the row read just before.
|
|
15115
15154
|
const selectByAnyKey = (value) => {
|
|
15116
15155
|
const item = store.select(value);
|
|
15117
15156
|
if (item) {
|
|
@@ -15163,6 +15202,12 @@ const resource = (
|
|
|
15163
15202
|
return store.select(lastItemId) || null;
|
|
15164
15203
|
});
|
|
15165
15204
|
};
|
|
15205
|
+
const createRestActionForRoot = createRestActionFactoryForRoot(name, {
|
|
15206
|
+
idKey,
|
|
15207
|
+
store,
|
|
15208
|
+
findItemByParams,
|
|
15209
|
+
declarationSite,
|
|
15210
|
+
});
|
|
15166
15211
|
return createResource(name, {
|
|
15167
15212
|
idKey,
|
|
15168
15213
|
uniqueKeys,
|
|
@@ -16154,6 +16199,7 @@ const createRestActionFactoryForRoot = (
|
|
|
16154
16199
|
{
|
|
16155
16200
|
idKey,
|
|
16156
16201
|
store, // see array_signal_store.js
|
|
16202
|
+
findItemByParams,
|
|
16157
16203
|
declarationSite,
|
|
16158
16204
|
},
|
|
16159
16205
|
) => {
|
|
@@ -16225,6 +16271,16 @@ const createRestActionFactoryForRoot = (
|
|
|
16225
16271
|
return applyResultToValue(result);
|
|
16226
16272
|
},
|
|
16227
16273
|
valueToData: (itemId) => store.select(itemId),
|
|
16274
|
+
// While the request is out, the row the store already holds for these
|
|
16275
|
+
// params is drawn: the action starts on the "refresh over a known
|
|
16276
|
+
// answer" line of data_states.md rather than the first-load one.
|
|
16277
|
+
provisionalValue:
|
|
16278
|
+
verb === "GET"
|
|
16279
|
+
? (params) => {
|
|
16280
|
+
const item = untracked(() => findItemByParams(params));
|
|
16281
|
+
return item ? item[idKey] : undefined;
|
|
16282
|
+
}
|
|
16283
|
+
: undefined,
|
|
16228
16284
|
completeSideEffect: onActionComplete,
|
|
16229
16285
|
});
|
|
16230
16286
|
};
|
|
@@ -23944,50 +24000,30 @@ const parsePattern = (
|
|
|
23944
24000
|
};
|
|
23945
24001
|
|
|
23946
24002
|
/**
|
|
23947
|
-
*
|
|
24003
|
+
* A literal segment the url stops short of is optional when an ancestor
|
|
24004
|
+
* pattern has a path param AT THAT SAME POSITION whose default is this word:
|
|
24005
|
+
* "/admin/settings/:tab" is the page "/admin" opens on when "/admin/:section"
|
|
24006
|
+
* defaults to "settings". Only the connection occupying the segment's index
|
|
24007
|
+
* may excuse it — a query param, or a param sitting elsewhere, says nothing
|
|
24008
|
+
* about this position, so a state defaulting to "games" must not turn
|
|
24009
|
+
* "/places/:slug/games" into a match for "/places/:slug".
|
|
23948
24010
|
*/
|
|
23949
24011
|
const checkIfLiteralCanBeOptionalWithPatternObj = (
|
|
23950
|
-
|
|
24012
|
+
literalSegment,
|
|
23951
24013
|
patternObj,
|
|
23952
24014
|
) => {
|
|
23953
|
-
|
|
23954
|
-
|
|
23955
|
-
|
|
23956
|
-
|
|
23957
|
-
|
|
23958
|
-
|
|
23959
|
-
if (connection.isDefaultValue(literalValue)) {
|
|
23960
|
-
return true;
|
|
23961
|
-
}
|
|
23962
|
-
}
|
|
23963
|
-
|
|
23964
|
-
// Check parent pattern's connections
|
|
23965
|
-
let currentParent = patternObj.parent;
|
|
23966
|
-
while (currentParent) {
|
|
23967
|
-
for (const connection of currentParent.connections) {
|
|
23968
|
-
if (connection.isDefaultValue(literalValue)) {
|
|
24015
|
+
let ancestor = patternObj ? patternObj.parent : null;
|
|
24016
|
+
while (ancestor) {
|
|
24017
|
+
const ancestorSegment = ancestor.pattern.segments[literalSegment.index];
|
|
24018
|
+
if (ancestorSegment && ancestorSegment.type === "param") {
|
|
24019
|
+
const connection = ancestor.pathConnectionMap.get(ancestorSegment.name);
|
|
24020
|
+
if (connection && connection.isDefaultValue(literalSegment.value)) {
|
|
23969
24021
|
return true;
|
|
23970
24022
|
}
|
|
23971
24023
|
}
|
|
23972
|
-
|
|
24024
|
+
ancestor = ancestor.parent;
|
|
23973
24025
|
}
|
|
23974
|
-
|
|
23975
|
-
// Check children pattern's connections
|
|
23976
|
-
const checkChildrenRecursively = (pattern) => {
|
|
23977
|
-
for (const child of pattern.children || []) {
|
|
23978
|
-
for (const connection of child.connections) {
|
|
23979
|
-
if (connection.isDefaultValue(literalValue)) {
|
|
23980
|
-
return true;
|
|
23981
|
-
}
|
|
23982
|
-
}
|
|
23983
|
-
if (checkChildrenRecursively(child)) {
|
|
23984
|
-
return true;
|
|
23985
|
-
}
|
|
23986
|
-
}
|
|
23987
|
-
return false;
|
|
23988
|
-
};
|
|
23989
|
-
|
|
23990
|
-
return checkChildrenRecursively(patternObj);
|
|
24026
|
+
return false;
|
|
23991
24027
|
};
|
|
23992
24028
|
|
|
23993
24029
|
/**
|
|
@@ -24132,9 +24168,8 @@ const matchUrl = (
|
|
|
24132
24168
|
// Check if URL has this segment
|
|
24133
24169
|
if (urlSegmentIndex >= urlSegments.length) {
|
|
24134
24170
|
// URL is too short for this literal segment
|
|
24135
|
-
// Check if this literal segment can be treated as optional based on pattern hierarchy
|
|
24136
24171
|
const canBeOptional = checkIfLiteralCanBeOptionalWithPatternObj(
|
|
24137
|
-
patternSeg
|
|
24172
|
+
patternSeg,
|
|
24138
24173
|
patternObj,
|
|
24139
24174
|
);
|
|
24140
24175
|
if (canBeOptional) {
|
|
@@ -37628,7 +37663,8 @@ const useInteractiveProps = (props, {
|
|
|
37628
37663
|
readOnly,
|
|
37629
37664
|
loading,
|
|
37630
37665
|
optimistic,
|
|
37631
|
-
actionStandalone
|
|
37666
|
+
actionStandalone,
|
|
37667
|
+
actionAbortable
|
|
37632
37668
|
} = props;
|
|
37633
37669
|
|
|
37634
37670
|
// `whenSelfInteractionsBlocked="ignore"`: an affordance that writes nothing
|
|
@@ -37692,6 +37728,12 @@ const useInteractiveProps = (props, {
|
|
|
37692
37728
|
// above it is told, so a form still submits and a popup still closes over a
|
|
37693
37729
|
// run that was meant to be left going.
|
|
37694
37730
|
uiStateController.actionStandalone = Boolean(actionStandalone);
|
|
37731
|
+
// Read by BUSY_CONSTRAINT: the wait holds what is around it as always, and
|
|
37732
|
+
// the person waiting may end it — closing the popup this control holds
|
|
37733
|
+
// calls the run off instead of being refused (see popup_busy.js). Read off
|
|
37734
|
+
// the control the run belongs to, so a field or a submit inheriting a
|
|
37735
|
+
// form's wait inherits this with it.
|
|
37736
|
+
uiStateController.actionAbortable = Boolean(actionAbortable);
|
|
37695
37737
|
// What the interaction rule last refused is only true while the control is
|
|
37696
37738
|
// held; the state it was read from moves here (see refreshReport).
|
|
37697
37739
|
useLayoutEffect(() => {
|
|
@@ -48352,6 +48394,7 @@ const COMMAND_DEFAULT_PROPS_FACTORIES = {
|
|
|
48352
48394
|
* whenSelfInteractionsBlocked?: "hide" | "refuse" | "ignore",
|
|
48353
48395
|
* replace?: boolean,
|
|
48354
48396
|
* actionStandalone?: boolean,
|
|
48397
|
+
* actionAbortable?: boolean,
|
|
48355
48398
|
* [key: string]: any,
|
|
48356
48399
|
* }>}
|
|
48357
48400
|
* @param {boolean} [replace] Go where the press leads — an `href`, a
|
|
@@ -48395,6 +48438,14 @@ const COMMAND_DEFAULT_PROPS_FACTORIES = {
|
|
|
48395
48438
|
* running, which the app watches from somewhere else; never for one holding
|
|
48396
48439
|
* an answer the screen is the only place to read (see
|
|
48397
48440
|
* docs/interactions.md#the-fourth-question-whose-wait-is-it).
|
|
48441
|
+
* @param {boolean} [actionAbortable] The person waiting may give up on this
|
|
48442
|
+
* button's action: closing the popup the run holds calls it off and goes
|
|
48443
|
+
* through, instead of being refused. For a run whose answer may never come —
|
|
48444
|
+
* a request over a network that stops answering — where a popup with no way
|
|
48445
|
+
* out is worse than an answer lost. Aborting frees the client and nothing
|
|
48446
|
+
* more: the work may already have happened on the other side (see
|
|
48447
|
+
* docs/actions.md#aborting-saves-resources-it-does-not-undo), so say it only
|
|
48448
|
+
* where the screen can be re-opened on what is actually there.
|
|
48398
48449
|
* @param {string} [contentDisplay] The display of the frame the button draws
|
|
48399
48450
|
* around its children. It follows the button's own by default — its display
|
|
48400
48451
|
* and, a display alone saying nothing about direction, the rest of its flow
|
|
@@ -57342,6 +57393,66 @@ const getAvailableWidth = (layer, element) => {
|
|
|
57342
57393
|
return visualViewportWidthSignal.peek();
|
|
57343
57394
|
};
|
|
57344
57395
|
|
|
57396
|
+
/**
|
|
57397
|
+
* What a popup asks before it closes: is anything inside it mid-action, and may
|
|
57398
|
+
* the person waiting call that wait off.
|
|
57399
|
+
*
|
|
57400
|
+
* A popup carries no state of its own — it is layout (see dialog.jsx's top
|
|
57401
|
+
* comment) — so it walks the controls it contains and asks each one. Asked
|
|
57402
|
+
* rather than read off `aria-busy`, which is a render snapshot: BUSY_CONSTRAINT
|
|
57403
|
+
* answers live.
|
|
57404
|
+
*
|
|
57405
|
+
* `Dialog` and `Popover` both read this way and read it identically, so it
|
|
57406
|
+
* lives here rather than in each of them: the answer decides whether a close
|
|
57407
|
+
* request goes through, and the two must not drift on that.
|
|
57408
|
+
*/
|
|
57409
|
+
|
|
57410
|
+
|
|
57411
|
+
/**
|
|
57412
|
+
* The controls keeping `popupEl` open: mid-action, and not saying the wait is
|
|
57413
|
+
* their own. `ignoredByParents` is that saying (`actionStandalone`) — a popup
|
|
57414
|
+
* is one more ancestor such a control does not hold, the same reading a group
|
|
57415
|
+
* makes of it (see control_interaction.js).
|
|
57416
|
+
*/
|
|
57417
|
+
const findControlsHoldingPopup = (popupEl) => {
|
|
57418
|
+
const controlsHolding = [];
|
|
57419
|
+
for (const element of popupEl.querySelectorAll("[navi-control-host]")) {
|
|
57420
|
+
const controller = element.__uiStateController__;
|
|
57421
|
+
if (!controller) {
|
|
57422
|
+
continue;
|
|
57423
|
+
}
|
|
57424
|
+
const busyInfo = BUSY_CONSTRAINT.check(controller);
|
|
57425
|
+
if (busyInfo && !busyInfo.ignoredByParents) {
|
|
57426
|
+
controlsHolding.push({
|
|
57427
|
+
element,
|
|
57428
|
+
controller,
|
|
57429
|
+
abortable: busyInfo.abortable,
|
|
57430
|
+
});
|
|
57431
|
+
}
|
|
57432
|
+
}
|
|
57433
|
+
return controlsHolding;
|
|
57434
|
+
};
|
|
57435
|
+
|
|
57436
|
+
/**
|
|
57437
|
+
* Give up on every run holding the popup, so that closing may go through.
|
|
57438
|
+
*
|
|
57439
|
+
* All or nothing: calling off one run while another still keeps the popup shut
|
|
57440
|
+
* would cost an answer and change nothing on screen. Several of these controls
|
|
57441
|
+
* usually share one run — a form and the fields and submit inside it — and the
|
|
57442
|
+
* ones asked after it has been called off simply find nothing to call off.
|
|
57443
|
+
*/
|
|
57444
|
+
const giveUpOnControlsHoldingPopup = (controlsHolding, reason) => {
|
|
57445
|
+
for (const controlHolding of controlsHolding) {
|
|
57446
|
+
if (!controlHolding.abortable) {
|
|
57447
|
+
return false;
|
|
57448
|
+
}
|
|
57449
|
+
}
|
|
57450
|
+
for (const controlHolding of controlsHolding) {
|
|
57451
|
+
abortControlRun(controlHolding.controller, reason);
|
|
57452
|
+
}
|
|
57453
|
+
return true;
|
|
57454
|
+
};
|
|
57455
|
+
|
|
57345
57456
|
/**
|
|
57346
57457
|
* Entry/exit animation CSS shared by Popover and Dialog.
|
|
57347
57458
|
*
|
|
@@ -58131,7 +58242,7 @@ const PopupClose = ({
|
|
|
58131
58242
|
// and what is opened has to be closable. Whether closing is allowed at
|
|
58132
58243
|
// this instant is the popup's own question, answered by the popup — a
|
|
58133
58244
|
// dialog holds the close while an action inside it runs (see
|
|
58134
|
-
//
|
|
58245
|
+
// popup_busy.js).
|
|
58135
58246
|
,
|
|
58136
58247
|
whenSelfInteractionsBlocked: "ignore"
|
|
58137
58248
|
// The cross is drawn at the control size, which is a few millimetres
|
|
@@ -58880,14 +58991,21 @@ const UncontrolledDialog = props => {
|
|
|
58880
58991
|
// dialog has no such state of its own to consult (it is layout — see
|
|
58881
58992
|
// this file's top comment), so it asks what it contains, and lets that
|
|
58882
58993
|
// control report why the way it would to anyone else.
|
|
58883
|
-
const
|
|
58884
|
-
if (
|
|
58885
|
-
|
|
58886
|
-
event: requestCloseEvent,
|
|
58887
|
-
name: "dialog request close"
|
|
58888
|
-
});
|
|
58889
|
-
requestCloseEvent.preventDefault();
|
|
58994
|
+
const controlsHolding = findControlsHoldingPopup(dialogEl);
|
|
58995
|
+
if (controlsHolding.length === 0) {
|
|
58996
|
+
return;
|
|
58890
58997
|
}
|
|
58998
|
+
// Unless every one of those runs was declared givable-up
|
|
58999
|
+
// (`actionAbortable`): the answer is not coming, closing is how the
|
|
59000
|
+
// person waiting says so, and the runs are called off on the way out.
|
|
59001
|
+
if (giveUpOnControlsHoldingPopup(controlsHolding, "the dialog holding the run was closed")) {
|
|
59002
|
+
return;
|
|
59003
|
+
}
|
|
59004
|
+
dispatchRequestInteraction(controlsHolding[0].element, {
|
|
59005
|
+
event: requestCloseEvent,
|
|
59006
|
+
name: "dialog request close"
|
|
59007
|
+
});
|
|
59008
|
+
requestCloseEvent.preventDefault();
|
|
58891
59009
|
},
|
|
58892
59010
|
onClose: closeEvent => {
|
|
58893
59011
|
props.onClose?.(closeEvent);
|
|
@@ -59007,29 +59125,6 @@ const DOCKED = {
|
|
|
59007
59125
|
// no header and nothing marked is not pushed down at all; it is closed by its
|
|
59008
59126
|
// own controls, by the backdrop and by Escape.
|
|
59009
59127
|
const DOCKED_SWIPE_GRIP = "[data-header],[data-swipe-grip]";
|
|
59010
|
-
|
|
59011
|
-
// The first control inside `dialogEl` that is mid-action, if any. Walks the
|
|
59012
|
-
// controls rather than reading an attribute off the dialog: a dialog carries no
|
|
59013
|
-
// state of its own (see this file's top comment), and `aria-busy` on the
|
|
59014
|
-
// controls is a render snapshot — BUSY_CONSTRAINT reads the live answer.
|
|
59015
|
-
// Same as Popover's own; kept in both rather than shared, since each file reads
|
|
59016
|
-
// on its own — what changes here changes there too.
|
|
59017
|
-
const findBusyElementInside$1 = dialogEl => {
|
|
59018
|
-
for (const element of dialogEl.querySelectorAll("[navi-control-host]")) {
|
|
59019
|
-
const controller = element.__uiStateController__;
|
|
59020
|
-
if (!controller) {
|
|
59021
|
-
continue;
|
|
59022
|
-
}
|
|
59023
|
-
const busyInfo = BUSY_CONSTRAINT.check(controller);
|
|
59024
|
-
// `ignoredByParents`: the control says the wait is its own
|
|
59025
|
-
// (`actionStandalone`), so a popup is one more ancestor it does not hold —
|
|
59026
|
-
// the same reading a group makes of it (see control_interaction.js).
|
|
59027
|
-
if (busyInfo && !busyInfo.ignoredByParents) {
|
|
59028
|
-
return element;
|
|
59029
|
-
}
|
|
59030
|
-
}
|
|
59031
|
-
return null;
|
|
59032
|
-
};
|
|
59033
59128
|
const useDialogProps = props => {
|
|
59034
59129
|
const backdropProps = {};
|
|
59035
59130
|
const contentProps = {};
|
|
@@ -60491,14 +60586,21 @@ const UncontrolledPopover = props => {
|
|
|
60491
60586
|
debugPopup(openEvent, `popover opened`);
|
|
60492
60587
|
return {
|
|
60493
60588
|
onRequestClose: requestCloseEvent => {
|
|
60494
|
-
const
|
|
60495
|
-
if (
|
|
60496
|
-
|
|
60497
|
-
event: requestCloseEvent,
|
|
60498
|
-
name: "popover request close"
|
|
60499
|
-
});
|
|
60500
|
-
requestCloseEvent.preventDefault();
|
|
60589
|
+
const controlsHolding = findControlsHoldingPopup(popoverEl);
|
|
60590
|
+
if (controlsHolding.length === 0) {
|
|
60591
|
+
return;
|
|
60501
60592
|
}
|
|
60593
|
+
// Unless every one of those runs was declared givable-up
|
|
60594
|
+
// (`actionAbortable`): the answer is not coming, closing is how the
|
|
60595
|
+
// person waiting says so, and the runs are called off on the way out.
|
|
60596
|
+
if (giveUpOnControlsHoldingPopup(controlsHolding, "the popover holding the run was closed")) {
|
|
60597
|
+
return;
|
|
60598
|
+
}
|
|
60599
|
+
dispatchRequestInteraction(controlsHolding[0].element, {
|
|
60600
|
+
event: requestCloseEvent,
|
|
60601
|
+
name: "popover request close"
|
|
60602
|
+
});
|
|
60603
|
+
requestCloseEvent.preventDefault();
|
|
60502
60604
|
},
|
|
60503
60605
|
onClose: closeEvent => {
|
|
60504
60606
|
props.onClose?.(closeEvent);
|
|
@@ -60607,28 +60709,6 @@ const PopoverCustom = props => {
|
|
|
60607
60709
|
* contentProps]` — two plain prop objects ready to spread onto a
|
|
60608
60710
|
* backdrop/content element each.
|
|
60609
60711
|
*/
|
|
60610
|
-
// The first control inside `popupEl` that is mid-action, if any. Walks the
|
|
60611
|
-
// controls rather than reading an attribute off the popup: a popup carries no
|
|
60612
|
-
// state of its own (see this file's top comment), and `aria-busy` on the
|
|
60613
|
-
// controls is a render snapshot — BUSY_CONSTRAINT reads the live answer.
|
|
60614
|
-
// Same as Dialog's own; kept in both rather than shared, since each file reads
|
|
60615
|
-
// on its own — what changes here changes there too.
|
|
60616
|
-
const findBusyElementInside = popupEl => {
|
|
60617
|
-
for (const element of popupEl.querySelectorAll("[navi-control-host]")) {
|
|
60618
|
-
const controller = element.__uiStateController__;
|
|
60619
|
-
if (!controller) {
|
|
60620
|
-
continue;
|
|
60621
|
-
}
|
|
60622
|
-
const busyInfo = BUSY_CONSTRAINT.check(controller);
|
|
60623
|
-
// `ignoredByParents`: the control says the wait is its own
|
|
60624
|
-
// (`actionStandalone`), so a popup is one more ancestor it does not hold —
|
|
60625
|
-
// the same reading a group makes of it (see control_interaction.js).
|
|
60626
|
-
if (busyInfo && !busyInfo.ignoredByParents) {
|
|
60627
|
-
return element;
|
|
60628
|
-
}
|
|
60629
|
-
}
|
|
60630
|
-
return null;
|
|
60631
|
-
};
|
|
60632
60712
|
const usePopoverProps = props => {
|
|
60633
60713
|
const backdropProps = {};
|
|
60634
60714
|
const contentProps = {};
|