@jsenv/navi 0.29.485 → 0.29.487
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 +334 -65
- package/dist/dev/jsenv_navi.js.map +20 -20
- package/dist/dev/jsenv_navi_side_effects.js.map +2 -2
- package/dist/jsenv_navi.js +334 -65
- package/dist/jsenv_navi.js.map +20 -20
- package/dist/jsenv_navi_side_effects.js.map +2 -2
- package/docs/popup_open.md +5 -0
- package/docs/typography.md +5 -3
- package/package.json +1 -1
package/dist/jsenv_navi.js
CHANGED
|
@@ -5420,7 +5420,13 @@ const MessagePropsRefContext = createContext();
|
|
|
5420
5420
|
const ControlIdContext = createContext();
|
|
5421
5421
|
const ControlNameContext = createContext();
|
|
5422
5422
|
const DisabledContext = createContext();
|
|
5423
|
+
// Truthy when what is above is read-only, and "network-policy" when that is a
|
|
5424
|
+
// write held by the network policy: what it holds is held in turn, and says
|
|
5425
|
+
// so in the policy's words (see readOnlyHandedDown in control_hooks.jsx).
|
|
5423
5426
|
const ReadOnlyContext = createContext();
|
|
5427
|
+
// The words that go with it, when what handed read-only down gave some (its
|
|
5428
|
+
// readOnlyMessage, or the ones it was handed in turn).
|
|
5429
|
+
const ReadOnlyMessageContext = createContext();
|
|
5424
5430
|
const RequiredContext = createContext();
|
|
5425
5431
|
const LoadingContext$1 = createContext();
|
|
5426
5432
|
createContext();
|
|
@@ -11489,6 +11495,31 @@ const resolveEffectiveDocumentState = (
|
|
|
11489
11495
|
return { ...state, ...sharedState };
|
|
11490
11496
|
};
|
|
11491
11497
|
|
|
11498
|
+
/**
|
|
11499
|
+
* What a press on a link handed to the navigation it starts (see the
|
|
11500
|
+
* integrations' `carryByLinkNavigation`): each write is an `editState` applied
|
|
11501
|
+
* to the entry that navigation writes, and an `otherwise` that makes the write
|
|
11502
|
+
* where it would have been made, for a press that starts no navigation here.
|
|
11503
|
+
*/
|
|
11504
|
+
const applyPressWrites = (state, pressWrites) => {
|
|
11505
|
+
if (!pressWrites) {
|
|
11506
|
+
return state;
|
|
11507
|
+
}
|
|
11508
|
+
let stateWritten = state;
|
|
11509
|
+
for (const { editState } of pressWrites) {
|
|
11510
|
+
stateWritten = editState(stateWritten);
|
|
11511
|
+
}
|
|
11512
|
+
return stateWritten;
|
|
11513
|
+
};
|
|
11514
|
+
const writePressWritesHere = (pressWrites) => {
|
|
11515
|
+
if (!pressWrites) {
|
|
11516
|
+
return;
|
|
11517
|
+
}
|
|
11518
|
+
for (const { otherwise } of pressWrites) {
|
|
11519
|
+
otherwise();
|
|
11520
|
+
}
|
|
11521
|
+
};
|
|
11522
|
+
|
|
11492
11523
|
// Preact's own useId() (see preact/hooks) returns "P<mask0>-<mask1>", where the
|
|
11493
11524
|
// mask is derived from render order within the nearest root/async boundary:
|
|
11494
11525
|
// stable across re-renders of the same mount, but not across two mounts on the
|
|
@@ -13133,6 +13164,7 @@ const setupBrowserIntegrationViaHistory = ({
|
|
|
13133
13164
|
// Asked to go where we already are: an address that redirects is never
|
|
13134
13165
|
// the one being displayed, so there is nothing to go to and nothing to
|
|
13135
13166
|
// stack on the history.
|
|
13167
|
+
writePressWritesHere(options.pressWrites);
|
|
13136
13168
|
return undefined;
|
|
13137
13169
|
}
|
|
13138
13170
|
return handleRoutingTask(redirectionUrl, {
|
|
@@ -13144,10 +13176,13 @@ const setupBrowserIntegrationViaHistory = ({
|
|
|
13144
13176
|
// Decided before anything is announced: an elided push IS the traversal it
|
|
13145
13177
|
// becomes, and the traversal will make its own announcements when the
|
|
13146
13178
|
// browser answers — a before/after cycle here would be about a navigation
|
|
13147
|
-
// that never happens.
|
|
13179
|
+
// that never happens. A push with something of its own for its entry — a
|
|
13180
|
+
// state, what the press handed over (see carryByLinkNavigation) — is a
|
|
13181
|
+
// new entry, never one standing there already.
|
|
13148
13182
|
if (
|
|
13149
13183
|
options.navigationType === "push" &&
|
|
13150
13184
|
options.state === undefined &&
|
|
13185
|
+
!options.pressWrites &&
|
|
13151
13186
|
url !== readAddress()
|
|
13152
13187
|
) {
|
|
13153
13188
|
const delta = adjacentEntryDelta(url);
|
|
@@ -13197,6 +13232,7 @@ const setupBrowserIntegrationViaHistory = ({
|
|
|
13197
13232
|
redirected,
|
|
13198
13233
|
landOn,
|
|
13199
13234
|
debounce,
|
|
13235
|
+
pressWrites,
|
|
13200
13236
|
} = options;
|
|
13201
13237
|
let { state } = options;
|
|
13202
13238
|
|
|
@@ -13207,15 +13243,18 @@ const setupBrowserIntegrationViaHistory = ({
|
|
|
13207
13243
|
|
|
13208
13244
|
if (navigationType === "push" || navigationType === "replace") {
|
|
13209
13245
|
markUrlAsVisited(url);
|
|
13210
|
-
const effectiveState =
|
|
13211
|
-
|
|
13212
|
-
|
|
13213
|
-
|
|
13214
|
-
|
|
13215
|
-
|
|
13216
|
-
|
|
13217
|
-
|
|
13218
|
-
|
|
13246
|
+
const effectiveState = applyPressWrites(
|
|
13247
|
+
resolveEffectiveDocumentState(state, {
|
|
13248
|
+
navigationType,
|
|
13249
|
+
isArrival: isArrival(url, { from: urlLeft }),
|
|
13250
|
+
currentState: getDocumentState(),
|
|
13251
|
+
sharedState: {
|
|
13252
|
+
jsenv_visited_urls: Array.from(visitedUrlSet),
|
|
13253
|
+
[NAV_DEPTH_STATE_KEY]: getNavDepth(),
|
|
13254
|
+
},
|
|
13255
|
+
}),
|
|
13256
|
+
pressWrites,
|
|
13257
|
+
);
|
|
13219
13258
|
if (navigationType === "replace" && debounce && state === undefined) {
|
|
13220
13259
|
// Nothing of its own for the entry: the address moves, the state is
|
|
13221
13260
|
// carried over. The one kind of write allowed to lag, and only when
|
|
@@ -13315,6 +13354,36 @@ const setupBrowserIntegrationViaHistory = ({
|
|
|
13315
13354
|
return requestedResult;
|
|
13316
13355
|
};
|
|
13317
13356
|
|
|
13357
|
+
// A press on a link is one navigation, and what the press asks of the
|
|
13358
|
+
// history entry is part of it: a popup the link's own command closes is
|
|
13359
|
+
// closed on the entry the link leads to, while the one it leaves keeps what
|
|
13360
|
+
// the reader was looking at — a back finds the popup open. The link's
|
|
13361
|
+
// listeners run before the routing is asked (below), so a write they make
|
|
13362
|
+
// is handed over, keyed by the click, rather than written onto the entry
|
|
13363
|
+
// being left. Once the link has been answered there is nothing to hand
|
|
13364
|
+
// over to: the navigation, when there was one, has already written its
|
|
13365
|
+
// entry, and a write lands there by itself.
|
|
13366
|
+
const linkPressWritesMap = new WeakMap();
|
|
13367
|
+
const answeredLinkClickSet = new WeakSet();
|
|
13368
|
+
const carryByLinkNavigation = (event, pressWrite) => {
|
|
13369
|
+
const clickEvent = findEvent(event, "click");
|
|
13370
|
+
if (
|
|
13371
|
+
!clickEvent ||
|
|
13372
|
+
clickEvent.eventPhase === Event.NONE ||
|
|
13373
|
+
answeredLinkClickSet.has(clickEvent) ||
|
|
13374
|
+
!clickEvent.target.closest("a")
|
|
13375
|
+
) {
|
|
13376
|
+
return false;
|
|
13377
|
+
}
|
|
13378
|
+
const pressWrites = linkPressWritesMap.get(clickEvent);
|
|
13379
|
+
if (pressWrites) {
|
|
13380
|
+
pressWrites.push(pressWrite);
|
|
13381
|
+
} else {
|
|
13382
|
+
linkPressWritesMap.set(clickEvent, [pressWrite]);
|
|
13383
|
+
}
|
|
13384
|
+
return true;
|
|
13385
|
+
};
|
|
13386
|
+
|
|
13318
13387
|
// A click on a link is answered on the link itself, after the link's own
|
|
13319
13388
|
// listeners: a navi control decides there whether the press is allowed — it
|
|
13320
13389
|
// refuses with preventDefault from its click reaction — and runs its command
|
|
@@ -13322,34 +13391,42 @@ const setupBrowserIntegrationViaHistory = ({
|
|
|
13322
13391
|
// is the order the Navigation API integration gets for free, where the
|
|
13323
13392
|
// navigation starts once the click has been dispatched.
|
|
13324
13393
|
const onLinkClick = (e) => {
|
|
13394
|
+
answeredLinkClickSet.add(e);
|
|
13395
|
+
const pressWrites = linkPressWritesMap.get(e);
|
|
13396
|
+
linkPressWritesMap.delete(e);
|
|
13397
|
+
if (!routeLinkClick(e, pressWrites)) {
|
|
13398
|
+
writePressWritesHere(pressWrites);
|
|
13399
|
+
}
|
|
13400
|
+
};
|
|
13401
|
+
const routeLinkClick = (e, pressWrites) => {
|
|
13325
13402
|
if (e.button !== 0) {
|
|
13326
13403
|
// Ignore non-left clicks
|
|
13327
|
-
return;
|
|
13404
|
+
return false;
|
|
13328
13405
|
}
|
|
13329
13406
|
if (e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) {
|
|
13330
13407
|
// A modifier asks the browser for something other than this tab: a new
|
|
13331
13408
|
// tab (meta on macOS, ctrl elsewhere), a new window (shift), a download
|
|
13332
13409
|
// (alt).
|
|
13333
|
-
return;
|
|
13410
|
+
return false;
|
|
13334
13411
|
}
|
|
13335
13412
|
if (e.defaultPrevented) {
|
|
13336
13413
|
// Refused — by the link itself, or by whoever came before it.
|
|
13337
|
-
return;
|
|
13414
|
+
return false;
|
|
13338
13415
|
}
|
|
13339
13416
|
const linkElement = e.currentTarget;
|
|
13340
13417
|
if (linkElement.hasAttribute("data-readonly")) {
|
|
13341
|
-
return;
|
|
13418
|
+
return false;
|
|
13342
13419
|
}
|
|
13343
13420
|
if (linkOpensElsewhere(linkElement)) {
|
|
13344
13421
|
// Another tab or window, or a download (see link_elsewhere.js).
|
|
13345
|
-
return;
|
|
13422
|
+
return false;
|
|
13346
13423
|
}
|
|
13347
13424
|
const href = linkElement.href;
|
|
13348
13425
|
const { isEmpty, isCurrent, isSameOrigin, isAnchor } =
|
|
13349
13426
|
getHrefTargetInfo(href);
|
|
13350
13427
|
if (isEmpty || !isSameOrigin) {
|
|
13351
13428
|
// Let link to other origins be handled by the browser
|
|
13352
|
-
return;
|
|
13429
|
+
return false;
|
|
13353
13430
|
}
|
|
13354
13431
|
if (isAnchor) {
|
|
13355
13432
|
// Fragment navigation belongs to the browser: it owns the indicated
|
|
@@ -13361,13 +13438,13 @@ const setupBrowserIntegrationViaHistory = ({
|
|
|
13361
13438
|
// change reaches whoever is waiting on the designated element.
|
|
13362
13439
|
rearmUrlTarget();
|
|
13363
13440
|
}
|
|
13364
|
-
return;
|
|
13441
|
+
return false;
|
|
13365
13442
|
}
|
|
13366
13443
|
if (linkAsksForDocument(linkElement)) {
|
|
13367
13444
|
// The link says its address is another document of this origin (see
|
|
13368
13445
|
// link_document.js). Routing to it would land on the fallback route
|
|
13369
13446
|
// instead of loading the page.
|
|
13370
|
-
return;
|
|
13447
|
+
return false;
|
|
13371
13448
|
}
|
|
13372
13449
|
// Nothing here declared a route, so there is nothing to route to: the
|
|
13373
13450
|
// page is a plain document and a link in it is a plain link. Taking it
|
|
@@ -13375,7 +13452,7 @@ const setupBrowserIntegrationViaHistory = ({
|
|
|
13375
13452
|
// the address bar moves and the page does not (see applyRouting's own
|
|
13376
13453
|
// "not called yet" branch, which is where that used to end up).
|
|
13377
13454
|
if (!isRouting()) {
|
|
13378
|
-
return;
|
|
13455
|
+
return false;
|
|
13379
13456
|
}
|
|
13380
13457
|
e.preventDefault();
|
|
13381
13458
|
handleRoutingTask(href, {
|
|
@@ -13389,7 +13466,9 @@ const setupBrowserIntegrationViaHistory = ({
|
|
|
13389
13466
|
// whoever knows what to do with it, and it is the anchor itself —
|
|
13390
13467
|
// resolved here, where it already is.
|
|
13391
13468
|
element: linkElement,
|
|
13469
|
+
pressWrites,
|
|
13392
13470
|
});
|
|
13471
|
+
return true;
|
|
13393
13472
|
};
|
|
13394
13473
|
// Wired from the capture phase on window, the first place a click is seen,
|
|
13395
13474
|
// so that a link is answered whatever handler stops the click on its way up
|
|
@@ -13569,6 +13648,7 @@ const setupBrowserIntegrationViaHistory = ({
|
|
|
13569
13648
|
navBack,
|
|
13570
13649
|
navForward,
|
|
13571
13650
|
getDocumentState,
|
|
13651
|
+
carryByLinkNavigation,
|
|
13572
13652
|
isVisited,
|
|
13573
13653
|
visitedUrlsSignal,
|
|
13574
13654
|
};
|
|
@@ -13968,8 +14048,32 @@ const useNavStateBasic = (
|
|
|
13968
14048
|
// that param for gone. Only with nothing of this document behind (the state
|
|
13969
14049
|
// was entered on a cold-loaded url, navBack has nowhere to go) does it
|
|
13970
14050
|
// rewrite in place.
|
|
13971
|
-
|
|
14051
|
+
//
|
|
14052
|
+
// event: what asked for it. A leave the press of a link asks for (its
|
|
14053
|
+
// --navi-close) is made by the navigation that link starts: the entry the
|
|
14054
|
+
// link leads to does not hold the key, and every entry behind is left as
|
|
14055
|
+
// the reader saw it — a back finds the state still entered.
|
|
14056
|
+
const leave = ({ isBack, event } = {}) => {
|
|
13972
14057
|
enteredRef.current = false;
|
|
14058
|
+
if (!Object.hasOwn(browserIntegration.getDocumentState() || {}, id)) {
|
|
14059
|
+
return;
|
|
14060
|
+
}
|
|
14061
|
+
if (
|
|
14062
|
+
event &&
|
|
14063
|
+
browserIntegration.carryByLinkNavigation(event, {
|
|
14064
|
+
editState: (state) => {
|
|
14065
|
+
const stateWithoutKey = { ...state };
|
|
14066
|
+
delete stateWithoutKey[id];
|
|
14067
|
+
return stateWithoutKey;
|
|
14068
|
+
},
|
|
14069
|
+
otherwise: () => leaveEntry({ isBack }),
|
|
14070
|
+
})
|
|
14071
|
+
) {
|
|
14072
|
+
return;
|
|
14073
|
+
}
|
|
14074
|
+
leaveEntry({ isBack });
|
|
14075
|
+
};
|
|
14076
|
+
const leaveEntry = ({ isBack }) => {
|
|
13973
14077
|
const currentStateCopy = browserIntegration.getDocumentState() || {};
|
|
13974
14078
|
if (!Object.hasOwn(currentStateCopy, id)) {
|
|
13975
14079
|
return;
|
|
@@ -14027,6 +14131,9 @@ const useNavStateBasic = (
|
|
|
14027
14131
|
* the value allows associating extra data when needed.
|
|
14028
14132
|
* - `leave()`: navigate AWAY FROM this state (removes `id` from document state,
|
|
14029
14133
|
* or goes back in history when `type` is "push").
|
|
14134
|
+
* `leave({ event })` with the event that asked for it: asked by the press
|
|
14135
|
+
* of a link that navigates, the key is left out of the entry the link
|
|
14136
|
+
* leads to, and the entry it leaves keeps it.
|
|
14030
14137
|
*/
|
|
14031
14138
|
const useNavState = useNavStateBasic;
|
|
14032
14139
|
|
|
@@ -17210,8 +17317,13 @@ const useOpenPropsEffectOnOpenController = (
|
|
|
17210
17317
|
} else {
|
|
17211
17318
|
// Under type "push" a cancel discards everything written while
|
|
17212
17319
|
// the popup was open — it goes back with the entry; a confirmed
|
|
17213
|
-
// close keeps those writes (see useNavState's own leave()).
|
|
17214
|
-
|
|
17320
|
+
// close keeps those writes (see useNavState's own leave()). A
|
|
17321
|
+
// close a link's press asked for is written by the navigation
|
|
17322
|
+
// the link starts.
|
|
17323
|
+
leaveNavState({
|
|
17324
|
+
isBack: Boolean(event?.detail?.isCancel),
|
|
17325
|
+
event,
|
|
17326
|
+
});
|
|
17215
17327
|
}
|
|
17216
17328
|
}
|
|
17217
17329
|
if (signal) {
|
|
@@ -17432,8 +17544,9 @@ const useOpenControllerByProps = (props, name) => {
|
|
|
17432
17544
|
* opened it, so a section written in a display font gets its tooltips in that
|
|
17433
17545
|
* font. `color`, `font-size` and `font-weight` are absent too — each surface
|
|
17434
17546
|
* answers those its own way (a popup and a callout write in
|
|
17435
|
-
* --navi-popup-color; a popup follows the size of what opened it
|
|
17436
|
-
*
|
|
17547
|
+
* --navi-popup-color; a popup follows the size of what opened it — for a
|
|
17548
|
+
* picker's popup, what is around the picker, see .navi_picker_content — a
|
|
17549
|
+
* callout resets to the document's size).
|
|
17437
17550
|
*
|
|
17438
17551
|
* In `@layer navi` so an app that wants one of these back says so on the
|
|
17439
17552
|
* surface and wins, without having to out-specify anything.
|
|
@@ -21034,6 +21147,13 @@ CONSTRAINT_ATTRIBUTE_SET.add("data-readonly");
|
|
|
21034
21147
|
CONSTRAINT_ATTRIBUTE_SET.add("data-readonly-reason");
|
|
21035
21148
|
|
|
21036
21149
|
const readOnlyMessage = (field) => {
|
|
21150
|
+
// Read-only from above, in the words of what made it so (a picker's or a
|
|
21151
|
+
// group's readOnlyMessage): what it holds says what it says — over the
|
|
21152
|
+
// network policy's words too, as that control's own words win over them on
|
|
21153
|
+
// itself.
|
|
21154
|
+
if (field.readOnlyMessageFromAbove) {
|
|
21155
|
+
return field.readOnlyMessageFromAbove;
|
|
21156
|
+
}
|
|
21037
21157
|
// Read-only for a reason the control named itself, read off the reason
|
|
21038
21158
|
// rather than off the surrounding state: a button read-only for its own
|
|
21039
21159
|
// reasons, inside a form that happens to be unchanged, is not waiting for
|
|
@@ -46692,6 +46812,8 @@ const useUIFacadeStateController = (props, realUIStateController) => {
|
|
|
46692
46812
|
s.controller.controlHostProps = realUIStateController.controlHostProps;
|
|
46693
46813
|
s.controller.readOnlyWithoutRun =
|
|
46694
46814
|
realUIStateController.readOnlyWithoutRun;
|
|
46815
|
+
s.controller.readOnlyMessageFromAbove =
|
|
46816
|
+
realUIStateController.readOnlyMessageFromAbove;
|
|
46695
46817
|
realUIStateController.pushStateDownToFacadeChild =
|
|
46696
46818
|
s.controller.pushStateDownToChild;
|
|
46697
46819
|
|
|
@@ -47037,6 +47159,7 @@ const ControlgroupChildrenWrapper = ({
|
|
|
47037
47159
|
required,
|
|
47038
47160
|
disabled,
|
|
47039
47161
|
readOnly,
|
|
47162
|
+
readOnlyMessage,
|
|
47040
47163
|
loading,
|
|
47041
47164
|
boundAction,
|
|
47042
47165
|
actionRequesterSignal
|
|
@@ -47050,8 +47173,9 @@ const ControlgroupChildrenWrapper = ({
|
|
|
47050
47173
|
value: name,
|
|
47051
47174
|
children: jsx(DisabledContext.Provider, {
|
|
47052
47175
|
value: disabled,
|
|
47053
|
-
children: jsx(
|
|
47054
|
-
|
|
47176
|
+
children: jsx(ReadOnlyProvider, {
|
|
47177
|
+
readOnly: readOnly,
|
|
47178
|
+
readOnlyMessage: readOnlyMessage,
|
|
47055
47179
|
children: jsx(RequiredContext.Provider, {
|
|
47056
47180
|
value: required,
|
|
47057
47181
|
children: jsx(LoadingContext$1.Provider, {
|
|
@@ -47071,6 +47195,34 @@ const ControlgroupChildrenWrapper = ({
|
|
|
47071
47195
|
})
|
|
47072
47196
|
})
|
|
47073
47197
|
});
|
|
47198
|
+
// What a control hands to what it holds about being read-only: the state, and
|
|
47199
|
+
// the words it is said in. What it holds writes into it, so it is held for the
|
|
47200
|
+
// same reason and says what the control says. Held by the network policy, it
|
|
47201
|
+
// hands down the hold itself — read-only alone, what it holds would refuse in
|
|
47202
|
+
// navi's generic words. Read-only, it hands down its readOnlyMessage, or the
|
|
47203
|
+
// one it was handed.
|
|
47204
|
+
const readOnlyHandedDown = (uiStateController, readOnly) => {
|
|
47205
|
+
const {
|
|
47206
|
+
controlHostProps,
|
|
47207
|
+
props
|
|
47208
|
+
} = uiStateController;
|
|
47209
|
+
const readOnlyResolved = controlHostProps["data-readonly-reason"] === "network-policy" ? "network-policy" : readOnly;
|
|
47210
|
+
if (!readOnlyResolved) {
|
|
47211
|
+
return [readOnlyResolved, undefined];
|
|
47212
|
+
}
|
|
47213
|
+
return [readOnlyResolved, props.readOnlyMessage ?? uiStateController.readOnlyMessageFromAbove];
|
|
47214
|
+
};
|
|
47215
|
+
const ReadOnlyProvider = ({
|
|
47216
|
+
readOnly,
|
|
47217
|
+
readOnlyMessage,
|
|
47218
|
+
children
|
|
47219
|
+
}) => jsx(ReadOnlyContext.Provider, {
|
|
47220
|
+
value: readOnly,
|
|
47221
|
+
children: jsx(ReadOnlyMessageContext.Provider, {
|
|
47222
|
+
value: readOnlyMessage,
|
|
47223
|
+
children: children
|
|
47224
|
+
})
|
|
47225
|
+
});
|
|
47074
47226
|
|
|
47075
47227
|
// What the caller writes for these is called from the control's own reactions
|
|
47076
47228
|
// (see `reactions` below), so the split leaves them out of both sides.
|
|
@@ -48297,7 +48449,7 @@ const useControlgroupProps = (props, {
|
|
|
48297
48449
|
basePseudoState
|
|
48298
48450
|
} = controlgroupProps;
|
|
48299
48451
|
const disabled = basePseudoState[":disabled"];
|
|
48300
|
-
const readOnly = basePseudoState[":read-only"];
|
|
48452
|
+
const [readOnly, readOnlyMessage] = readOnlyHandedDown(uiGroupStateController, basePseudoState[":read-only"]);
|
|
48301
48453
|
const loading = basePseudoState[":-navi-loading"];
|
|
48302
48454
|
const controlgroupChildrenWrapperProps = useMemo(() => ({
|
|
48303
48455
|
uiGroupStateController,
|
|
@@ -48305,10 +48457,11 @@ const useControlgroupProps = (props, {
|
|
|
48305
48457
|
required: controlgroupProps.required,
|
|
48306
48458
|
disabled,
|
|
48307
48459
|
readOnly,
|
|
48460
|
+
readOnlyMessage,
|
|
48308
48461
|
loading,
|
|
48309
48462
|
boundAction,
|
|
48310
48463
|
actionRequesterSignal
|
|
48311
|
-
}), [uiGroupStateController, controlgroupProps.name, controlgroupProps.required, disabled, readOnly, loading, boundAction, actionRequesterSignal]);
|
|
48464
|
+
}), [uiGroupStateController, controlgroupProps.name, controlgroupProps.required, disabled, readOnly, readOnlyMessage, loading, boundAction, actionRequesterSignal]);
|
|
48312
48465
|
return [controlRootProps, {
|
|
48313
48466
|
...controlgroupProps,
|
|
48314
48467
|
"name": undefined,
|
|
@@ -48504,6 +48657,7 @@ const useInteractiveProps = (props, {
|
|
|
48504
48657
|
{
|
|
48505
48658
|
const controlDisabledFromAbove = useContext(DisabledContext);
|
|
48506
48659
|
const controlReadOnlyFromAbove = useContext(ReadOnlyContext);
|
|
48660
|
+
const controlReadOnlyMessageFromAbove = useContext(ReadOnlyMessageContext);
|
|
48507
48661
|
const controlRequired = useContext(RequiredContext);
|
|
48508
48662
|
const controlLoadingFromAbove = useContext(LoadingContext$1);
|
|
48509
48663
|
// A SIGNAL holding the element whose press the group's action is wearing
|
|
@@ -48543,8 +48697,15 @@ const useInteractiveProps = (props, {
|
|
|
48543
48697
|
// pressable on a game nobody may edit. Its own props still hold; only what
|
|
48544
48698
|
// came from above is dropped (see self_interactions.js for the three modes).
|
|
48545
48699
|
const zoneStateApplies = !selfInteractionsIgnoreBlock(props);
|
|
48700
|
+
// A press that only leaves the popup it sits in writes nothing to the zone
|
|
48701
|
+
// around it either, so that zone being read-only — or holding a write the
|
|
48702
|
+
// network policy keeps — does not hold it: the popup answers the close
|
|
48703
|
+
// itself. A read-only picker's popup then closes from its own button as
|
|
48704
|
+
// it does from a press outside, and refuses both alike when it holds a
|
|
48705
|
+
// change it cannot send.
|
|
48706
|
+
const zoneReadOnlyApplies = zoneStateApplies && !pressOnlyLeaves(props);
|
|
48546
48707
|
const controlDisabled = zoneStateApplies && controlDisabledFromAbove;
|
|
48547
|
-
const controlReadOnly =
|
|
48708
|
+
const controlReadOnly = zoneReadOnlyApplies && controlReadOnlyFromAbove;
|
|
48548
48709
|
const controlLoading = zoneStateApplies && controlLoadingFromAbove;
|
|
48549
48710
|
const disabledResolved = disabled || controlDisabled;
|
|
48550
48711
|
const requiredResolved = required || controlRequired;
|
|
@@ -48559,10 +48720,11 @@ const useInteractiveProps = (props, {
|
|
|
48559
48720
|
// but cannot be taken.
|
|
48560
48721
|
const readOnlyFromParentMaxLengthGuard = Boolean(zoneStateApplies && uiStateController.parentUIStateController?.isChildBlockedByMaxLengthGuard?.(uiStateController));
|
|
48561
48722
|
// A write cannot leave under a network policy, so the control asking for
|
|
48562
|
-
// one —
|
|
48563
|
-
//
|
|
48564
|
-
//
|
|
48565
|
-
|
|
48723
|
+
// one — sitting in a form that does, or in what a held control holds (a
|
|
48724
|
+
// picker's popup) — refuses before the press and says why (see
|
|
48725
|
+
// network_policy.js): a press that looks accepted and fails after is what
|
|
48726
|
+
// the policy exists to avoid.
|
|
48727
|
+
const heldByNetworkPolicy = networkPolicyReason !== null && (isWriteAction(boundAction) || Boolean(zoneReadOnlyApplies && parentAction && isWriteAction(parentAction)) || controlReadOnly === "network-policy");
|
|
48566
48728
|
// Held back because the surface above already has as many runs in flight as
|
|
48567
48729
|
// it allows (see parallel_guard.js). Only a control that would START one:
|
|
48568
48730
|
// anything without an action of its own runs nothing and has nothing to
|
|
@@ -48581,6 +48743,10 @@ const useInteractiveProps = (props, {
|
|
|
48581
48743
|
// still read-only in the tick the run settles — the tick a form's
|
|
48582
48744
|
// after-send `--navi-reset` asks the form to empty itself.
|
|
48583
48745
|
uiStateController.readOnlyWithoutRun = Boolean(readOnlyBase);
|
|
48746
|
+
// The words of what made this control read-only from above, when it gave
|
|
48747
|
+
// some: read by READONLY_CONSTRAINT, and handed further down with the
|
|
48748
|
+
// read-only state (see readOnlyHandedDown).
|
|
48749
|
+
uiStateController.readOnlyMessageFromAbove = controlReadOnly ? controlReadOnlyMessageFromAbove : undefined;
|
|
48584
48750
|
// Read-only, and what this control opens still opens: reading what is in
|
|
48585
48751
|
// there changes nothing. Read by READONLY_CONSTRAINT, which lets an
|
|
48586
48752
|
// interaction that only reads through on it.
|
|
@@ -49113,6 +49279,12 @@ const splitControlProps = (props, {
|
|
|
49113
49279
|
}
|
|
49114
49280
|
return [controlRootProps, controlHostProps];
|
|
49115
49281
|
};
|
|
49282
|
+
// What a press leaving a popup asks for: closing it, or cancelling it. Only on
|
|
49283
|
+
// a control running nothing of its own — one with an action writes, wherever
|
|
49284
|
+
// it then leads.
|
|
49285
|
+
const LEAVING_COMMAND_SET = new Set(["--navi-close", "--navi-cancel"]);
|
|
49286
|
+
const pressOnlyLeaves = props => LEAVING_COMMAND_SET.has(props.command) && !props.action;
|
|
49287
|
+
|
|
49116
49288
|
// `onPointerDown`, `onFocusOut`… but not navi's own events (`onnavi_command`),
|
|
49117
49289
|
// which keep the element they are dispatched on.
|
|
49118
49290
|
const isDomListenerProp = key => /^on[A-Z]/.test(key);
|
|
@@ -53123,7 +53295,9 @@ const LinkPseudoElements = ["::-navi-loader", "::-navi-indicator"];
|
|
|
53123
53295
|
* fetching on a hover.
|
|
53124
53296
|
* @param {string} [props.command] - What the press asks of a control around
|
|
53125
53297
|
* the link — `"--navi-close"` on a link that leaves the sheet it is in.
|
|
53126
|
-
* Triggered on the press, before the navigation.
|
|
53298
|
+
* Triggered on the press, before the navigation. A popup it closes that
|
|
53299
|
+
* keeps its open state in the history entry (`navState`) is closed on the
|
|
53300
|
+
* entry the navigation leads to: Back finds it open.
|
|
53127
53301
|
* @param {Function} [props.action] - Work the press runs, before the
|
|
53128
53302
|
* navigation. Nothing waits for it — not the navigation, not `command`: what
|
|
53129
53303
|
* the next page must find has to be written synchronously (a draft in a
|
|
@@ -57671,7 +57845,7 @@ const css$S = /* css */`@layer navi {
|
|
|
57671
57845
|
--button-color: currentColor;
|
|
57672
57846
|
--button-cursor: pointer;
|
|
57673
57847
|
--button-font-size: var(--navi-control-font-size);
|
|
57674
|
-
--button-font-family: var(--navi-control-font-family, inherit);
|
|
57848
|
+
--button-font-family: var(--navi-button-font-family, var(--navi-control-font-family, inherit));
|
|
57675
57849
|
--button-border-color-hover: color-mix(in srgb,
|
|
57676
57850
|
var(--button-border-color) 70%,
|
|
57677
57851
|
black);
|
|
@@ -59399,14 +59573,16 @@ const css$O = /* css */`@layer navi {
|
|
|
59399
59573
|
--checkmark-color-disabled: #eee;
|
|
59400
59574
|
--border-color-disabled-checked: #d3d3d3;
|
|
59401
59575
|
--background-color-disabled-checked: #d3d3d3;
|
|
59402
|
-
--button-border-color:
|
|
59403
|
-
--button-background-color:
|
|
59576
|
+
--button-border-color: var(--navi-control-border-color);
|
|
59577
|
+
--button-background-color: var(--navi-button-background-color);
|
|
59404
59578
|
--button-border-color-hover: color-mix(in srgb,
|
|
59405
59579
|
var(--button-border-color) 70%,
|
|
59406
59580
|
black);
|
|
59407
59581
|
--button-background-color-hover: color-mix(in srgb,
|
|
59408
59582
|
var(--button-background-color) 95%,
|
|
59409
59583
|
black);
|
|
59584
|
+
--button-background-color-readonly: var(--button-background-color);
|
|
59585
|
+
--button-background-color-disabled: var(--button-background-color-readonly);
|
|
59410
59586
|
}
|
|
59411
59587
|
|
|
59412
59588
|
.navi_checkbox[data-variant="switch"] {
|
|
@@ -59434,19 +59610,40 @@ const css$O = /* css */`@layer navi {
|
|
|
59434
59610
|
--margin: 0;
|
|
59435
59611
|
--width: auto;
|
|
59436
59612
|
--height: auto;
|
|
59613
|
+
--font-family: var(--navi-button-font-family, var(--navi-control-font-family, inherit));
|
|
59437
59614
|
--border-color: var(--button-border-color);
|
|
59438
59615
|
--border-color-hover: var(--button-border-color-hover);
|
|
59439
59616
|
--background-color: var(--button-background-color);
|
|
59440
59617
|
--background-color-hover: var(--button-background-color-hover);
|
|
59441
59618
|
--background-color-readonly: var(--button-background-color-readonly);
|
|
59442
59619
|
--background-color-disabled: var(--button-background-color-disabled);
|
|
59620
|
+
}
|
|
59621
|
+
|
|
59622
|
+
.navi_checkbox[data-variant="button"]:not([data-label]) {
|
|
59623
|
+
--button-padding-x-default: 0;
|
|
59624
|
+
--button-padding-y-default: 0;
|
|
59443
59625
|
--border-color-checked: var(--button-border-color);
|
|
59626
|
+
--border-color-hover-checked: var(--button-border-color-hover);
|
|
59444
59627
|
--background-color-checked: var(--button-background-color);
|
|
59628
|
+
--background-color-hover-checked: var(--button-background-color-hover);
|
|
59629
|
+
--checkmark-color: currentColor;
|
|
59445
59630
|
}
|
|
59446
59631
|
|
|
59447
59632
|
.navi_checkbox[data-variant="button"][data-label] {
|
|
59448
|
-
--border-
|
|
59449
|
-
--
|
|
59633
|
+
--border-radius: var(--navi-control-border-radius);
|
|
59634
|
+
--button-padding-x-default: var(--navi-button-padding-x-default);
|
|
59635
|
+
--button-padding-y-default: var(--navi-button-padding-y-default);
|
|
59636
|
+
line-height: var(--navi-control-line-height);
|
|
59637
|
+
}
|
|
59638
|
+
|
|
59639
|
+
.navi_checkbox[data-variant="button"][data-button-variant="discrete"] {
|
|
59640
|
+
--border-width: 0;
|
|
59641
|
+
--button-border-color: transparent;
|
|
59642
|
+
--button-border-color-hover: var(--button-border-color);
|
|
59643
|
+
--button-background-color: transparent;
|
|
59644
|
+
--button-background-color-hover: color-mix(in srgb,
|
|
59645
|
+
currentColor 8%,
|
|
59646
|
+
var(--button-background-color));
|
|
59450
59647
|
}
|
|
59451
59648
|
}
|
|
59452
59649
|
|
|
@@ -59554,23 +59751,24 @@ const css$O = /* css */`@layer navi {
|
|
|
59554
59751
|
--color-mix: var(--color-mix-light);
|
|
59555
59752
|
}
|
|
59556
59753
|
|
|
59754
|
+
& .navi_checkbox_marker {
|
|
59755
|
+
opacity: 0;
|
|
59756
|
+
stroke: var(--x-checkmark-color);
|
|
59757
|
+
transform: scale(.5);
|
|
59758
|
+
}
|
|
59759
|
+
|
|
59760
|
+
&[data-checked] .navi_checkbox_marker {
|
|
59761
|
+
opacity: 1;
|
|
59762
|
+
transition-property: opacity, transform;
|
|
59763
|
+
transition-duration: .15s;
|
|
59764
|
+
transition-timing-function: ease;
|
|
59765
|
+
transform: scale(1);
|
|
59766
|
+
}
|
|
59767
|
+
|
|
59557
59768
|
&[data-variant="checkbox"] {
|
|
59558
59769
|
& .navi_checkbox_marker {
|
|
59559
|
-
opacity: 0;
|
|
59560
59770
|
width: 100%;
|
|
59561
59771
|
height: 100%;
|
|
59562
|
-
stroke: var(--x-checkmark-color);
|
|
59563
|
-
transform: scale(.5);
|
|
59564
|
-
}
|
|
59565
|
-
|
|
59566
|
-
&[data-checked] {
|
|
59567
|
-
& .navi_checkbox_marker {
|
|
59568
|
-
opacity: 1;
|
|
59569
|
-
transition-property: opacity, transform;
|
|
59570
|
-
transition-duration: .15s;
|
|
59571
|
-
transition-timing-function: ease;
|
|
59572
|
-
transform: scale(1);
|
|
59573
|
-
}
|
|
59574
59772
|
}
|
|
59575
59773
|
|
|
59576
59774
|
&[data-accent-very-light] {
|
|
@@ -59609,6 +59807,11 @@ const css$O = /* css */`@layer navi {
|
|
|
59609
59807
|
justify-content: center;
|
|
59610
59808
|
align-items: center;
|
|
59611
59809
|
|
|
59810
|
+
& .navi_checkbox_marker {
|
|
59811
|
+
width: 1em;
|
|
59812
|
+
height: 1em;
|
|
59813
|
+
}
|
|
59814
|
+
|
|
59612
59815
|
&[data-label] {
|
|
59613
59816
|
&[data-checked] .navi_checkbox_label {
|
|
59614
59817
|
color: var(--x-checkmark-color);
|
|
@@ -59657,7 +59860,8 @@ const InputCheckboxFieldInterface = props => {
|
|
|
59657
59860
|
const {
|
|
59658
59861
|
icon,
|
|
59659
59862
|
switch: switchProp,
|
|
59660
|
-
|
|
59863
|
+
buttonVariant,
|
|
59864
|
+
variant = buttonVariant ? "button" : icon ? "icon" : switchProp ? "switch" : "checkbox",
|
|
59661
59865
|
// "checkbox", "switch", "icon", "button"
|
|
59662
59866
|
accentColor
|
|
59663
59867
|
} = props;
|
|
@@ -59712,7 +59916,9 @@ const InputCheckboxFieldInterface = props => {
|
|
|
59712
59916
|
variant: undefined,
|
|
59713
59917
|
switch: undefined,
|
|
59714
59918
|
icon: undefined,
|
|
59919
|
+
buttonVariant: undefined,
|
|
59715
59920
|
"data-variant": variant,
|
|
59921
|
+
"data-button-variant": variant === "button" ? buttonVariant : undefined,
|
|
59716
59922
|
"data-label": hasLabel ? "" : undefined,
|
|
59717
59923
|
baseClassName: "navi_checkbox",
|
|
59718
59924
|
pseudoStateSelector: ".navi_control_input",
|
|
@@ -60186,6 +60392,9 @@ const css$M = /* css */`@layer navi {
|
|
|
60186
60392
|
--radiomark-color-disabled: #d3d3d3;
|
|
60187
60393
|
--border-color-checked-disabled: #d3d3d3;
|
|
60188
60394
|
--background-color-disabled-checked: var(--background-color);
|
|
60395
|
+
--button-padding-x-default: 0;
|
|
60396
|
+
--button-padding-y-default: 0;
|
|
60397
|
+
--button-border-radius: var(--navi-control-border-radius);
|
|
60189
60398
|
--button-border-width: 1px;
|
|
60190
60399
|
--button-border-color: transparent;
|
|
60191
60400
|
--button-background-color: transparent;
|
|
@@ -62410,6 +62619,7 @@ const InputPseudoElements = ["::-navi-loader"];
|
|
|
62410
62619
|
* boolean?: boolean,
|
|
62411
62620
|
* selectOnPress?: boolean,
|
|
62412
62621
|
* variant?: "checkbox" | "switch" | "icon" | "button",
|
|
62622
|
+
* buttonVariant?: "discrete",
|
|
62413
62623
|
* actionVerb?: "GET" | "POST" | "PUT" | "PATCH" | "DELETE",
|
|
62414
62624
|
* [key: string]: any,
|
|
62415
62625
|
* }>}
|
|
@@ -62425,6 +62635,10 @@ const InputPseudoElements = ["::-navi-loader"];
|
|
|
62425
62635
|
* is a square around its checkmark (or its `icon`, which takes an
|
|
62426
62636
|
* `[off, on]` pair). Bound with `signal`, it follows whatever else writes
|
|
62427
62637
|
* that signal.
|
|
62638
|
+
* @param {"discrete"} [buttonVariant] A checkbox drawn as a button, drawn as
|
|
62639
|
+
* that variant of `Button`: `"discrete"` has no box at rest and a wash on
|
|
62640
|
+
* hover (checked, its words still fill with the accent). Implies
|
|
62641
|
+
* `variant="button"`.
|
|
62428
62642
|
* @param {"GET"|"POST"|"PUT"|"PATCH"|"DELETE"} [actionVerb] What a plain
|
|
62429
62643
|
* function `action` does to the server. A write verb puts the field under
|
|
62430
62644
|
* the network policy: held read-only up front, with the policy's message,
|
|
@@ -71662,6 +71876,10 @@ const UncontrolledDialog = props => {
|
|
|
71662
71876
|
// needs the dialog element to look at what it contains.
|
|
71663
71877
|
const defaultRef = useRef();
|
|
71664
71878
|
props.ref = props.ref || defaultRef;
|
|
71879
|
+
// The close is built once per opening (see useOpenController below): read
|
|
71880
|
+
// through a ref, an onClose given by a render while open is the one called.
|
|
71881
|
+
const onCloseRef = useRef(null);
|
|
71882
|
+
onCloseRef.current = props.onClose;
|
|
71665
71883
|
const openController = useOpenController(openEvent => {
|
|
71666
71884
|
const dialogEl = props.ref.current;
|
|
71667
71885
|
return {
|
|
@@ -71688,7 +71906,7 @@ const UncontrolledDialog = props => {
|
|
|
71688
71906
|
requestCloseEvent.preventDefault();
|
|
71689
71907
|
},
|
|
71690
71908
|
onClose: closeEvent => {
|
|
71691
|
-
|
|
71909
|
+
onCloseRef.current?.(closeEvent);
|
|
71692
71910
|
}
|
|
71693
71911
|
};
|
|
71694
71912
|
});
|
|
@@ -73547,6 +73765,9 @@ const UncontrolledPopover = props => {
|
|
|
73547
73765
|
// the popover element to read what it holds.
|
|
73548
73766
|
const defaultRef = useRef();
|
|
73549
73767
|
props.ref = props.ref || defaultRef;
|
|
73768
|
+
// Read at the close, not captured at the opening: see UncontrolledDialog.
|
|
73769
|
+
const onCloseRef = useRef(null);
|
|
73770
|
+
onCloseRef.current = props.onClose;
|
|
73550
73771
|
// Same as Dialog's own UncontrolledDialog, for the same reasons — see it for
|
|
73551
73772
|
// the full story: a popover is a surface, so the only thing it has to say
|
|
73552
73773
|
// about closing is that what it contains must not be interrupted mid-action.
|
|
@@ -73571,7 +73792,7 @@ const UncontrolledPopover = props => {
|
|
|
73571
73792
|
requestCloseEvent.preventDefault();
|
|
73572
73793
|
},
|
|
73573
73794
|
onClose: closeEvent => {
|
|
73574
|
-
|
|
73795
|
+
onCloseRef.current?.(closeEvent);
|
|
73575
73796
|
}
|
|
73576
73797
|
};
|
|
73577
73798
|
});
|
|
@@ -75421,6 +75642,15 @@ const PickerCustom = props => {
|
|
|
75421
75642
|
// closed (see onClose below) — a press that ran before the close would make
|
|
75422
75643
|
// the picker busy, and a busy picker refuses the very close that follows.
|
|
75423
75644
|
const confirmEventRef = useRef(null);
|
|
75645
|
+
// The close is built once per opening (see useOpenController below), but
|
|
75646
|
+
// these props answer how it ends: read through a ref, a render while open
|
|
75647
|
+
// (a sheet turned into the next question) is heard by the close.
|
|
75648
|
+
const closePropsRef = useRef(null);
|
|
75649
|
+
closePropsRef.current = {
|
|
75650
|
+
canSendWhileUnchanged,
|
|
75651
|
+
onConfirm,
|
|
75652
|
+
onClose
|
|
75653
|
+
};
|
|
75424
75654
|
// aria-controls + id
|
|
75425
75655
|
const popupId = `${props.id}_picker_popup`;
|
|
75426
75656
|
{
|
|
@@ -75519,7 +75749,7 @@ const PickerCustom = props => {
|
|
|
75519
75749
|
// and for that picker the same value said again means something.
|
|
75520
75750
|
// A press outside, Escape, the cross say nothing and keep skipping.
|
|
75521
75751
|
const said = requestCloseEvent.detail.isSend || confirmEventRef.current;
|
|
75522
|
-
if (!(canSendWhileUnchanged && said)) {
|
|
75752
|
+
if (!(closePropsRef.current.canSendWhileUnchanged && said)) {
|
|
75523
75753
|
// No action to run, but still allow the close.
|
|
75524
75754
|
return;
|
|
75525
75755
|
}
|
|
@@ -75580,7 +75810,7 @@ const PickerCustom = props => {
|
|
|
75580
75810
|
const confirmEvent = confirmEventRef.current;
|
|
75581
75811
|
confirmEventRef.current = null;
|
|
75582
75812
|
if (confirmEvent && !closeEvent.detail.isCancel) {
|
|
75583
|
-
onConfirm?.(confirmEvent);
|
|
75813
|
+
closePropsRef.current.onConfirm?.(confirmEvent);
|
|
75584
75814
|
}
|
|
75585
75815
|
// After the value bookkeeping above — whoever listens reads the
|
|
75586
75816
|
// picker's value as it ends up, committed or restored on a cancel —
|
|
@@ -75591,7 +75821,7 @@ const PickerCustom = props => {
|
|
|
75591
75821
|
// spells into the address — a route param naming what was being
|
|
75592
75822
|
// edited, cleared now that nothing is — has to be written before,
|
|
75593
75823
|
// or the landing puts it back.
|
|
75594
|
-
onClose?.(closeEvent);
|
|
75824
|
+
closePropsRef.current.onClose?.(closeEvent);
|
|
75595
75825
|
leaveExpanded({
|
|
75596
75826
|
isBack: closeEvent.detail.isCancel
|
|
75597
75827
|
});
|
|
@@ -75681,6 +75911,11 @@ const PickerCustom = props => {
|
|
|
75681
75911
|
// button) hangs its popup off the whole control instead.
|
|
75682
75912
|
anchor: props.anchor || props.ref,
|
|
75683
75913
|
openController,
|
|
75914
|
+
// Before the content is built and shown, so it is laid out and placed
|
|
75915
|
+
// at the size it is read at (see .navi_picker_content in picker.jsx).
|
|
75916
|
+
onOpen: () => {
|
|
75917
|
+
writeContainerFont(ref.current, popupRef.current);
|
|
75918
|
+
},
|
|
75684
75919
|
// A picker whose value was never given to it reads it off the control in
|
|
75685
75920
|
// its popup (see useUIFacadeStateController), so that control is built as
|
|
75686
75921
|
// soon as something reads the value: at mount when the picker sees the
|
|
@@ -76504,6 +76739,30 @@ const showNativePicker = (pickerInput, event) => {
|
|
|
76504
76739
|
}
|
|
76505
76740
|
};
|
|
76506
76741
|
|
|
76742
|
+
// The popup of a picker is opened where the picker stands, so it writes at the
|
|
76743
|
+
// size and weight of what is around it — the ones a Dialog rendered there
|
|
76744
|
+
// inherits — and never at the ones the trigger is drawn at. CSS cannot reach
|
|
76745
|
+
// past the picker's own: its root holds the popup and sets both. Written on the
|
|
76746
|
+
// holder only when they differ, so an opening that changes nothing invalidates
|
|
76747
|
+
// no style.
|
|
76748
|
+
const writeContainerFont = (pickerEl, popupEl) => {
|
|
76749
|
+
const container = pickerEl?.parentElement;
|
|
76750
|
+
const holder = popupEl?.closest("[data-picker-content]");
|
|
76751
|
+
if (!container || !holder) {
|
|
76752
|
+
return;
|
|
76753
|
+
}
|
|
76754
|
+
const {
|
|
76755
|
+
fontSize,
|
|
76756
|
+
fontWeight
|
|
76757
|
+
} = getComputedStyle(container);
|
|
76758
|
+
if (holder.style.fontSize !== fontSize) {
|
|
76759
|
+
holder.style.fontSize = fontSize;
|
|
76760
|
+
}
|
|
76761
|
+
if (holder.style.fontWeight !== fontWeight) {
|
|
76762
|
+
holder.style.fontWeight = fontWeight;
|
|
76763
|
+
}
|
|
76764
|
+
};
|
|
76765
|
+
|
|
76507
76766
|
installImportMetaCssBuild(import.meta);
|
|
76508
76767
|
const css$y = /* css */`.navi_picker_confirm_body {
|
|
76509
76768
|
min-width: 180px;
|
|
@@ -78471,11 +78730,16 @@ const ListItemSelectable = props => {
|
|
|
78471
78730
|
// A list waiting on something is not unavailable, it is not answering yet —
|
|
78472
78731
|
// busy rather than read-only (see BUSY_CONSTRAINT, which is asked first),
|
|
78473
78732
|
// and the wait is about the same thing the read-only would be about.
|
|
78733
|
+
//
|
|
78734
|
+
// Unless what made the list read-only says it better: in words of its own (a
|
|
78735
|
+
// picker's or a list's readOnlyMessage), or because it is the network
|
|
78736
|
+
// policy holding the write the selection would make.
|
|
78474
78737
|
const readOnlyFromAbove = useContext(ReadOnlyContext);
|
|
78738
|
+
const readOnlyMessageFromAbove = useContext(ReadOnlyMessageContext);
|
|
78475
78739
|
const readOnlyMessageKey = readOnlyFromAbove ? multiple ? `constraint.readonly.selection` : `constraint.readonly.choice` : `constraint.readonly.option`;
|
|
78476
78740
|
// Handed to the row as well as to the control: whichever of the two catches
|
|
78477
78741
|
// the press answers it, and they must not answer it differently.
|
|
78478
|
-
const readOnlyMessageResolved = props.readOnlyMessage ?? constraintI18n(readOnlyMessageKey, props);
|
|
78742
|
+
const readOnlyMessageResolved = props.readOnlyMessage ?? (readOnlyFromAbove ? readOnlyMessageFromAbove : undefined) ?? (readOnlyFromAbove === "network-policy" ? getNetworkPolicyReadOnlyMessage() : constraintI18n(readOnlyMessageKey, props));
|
|
78479
78743
|
const busyMessageResolved = props.busyMessage ?? (loading ? listItemBusyMessage(loading, props) : constraintI18n(multiple ? `constraint.busy.selection` : `constraint.busy.choice`, props));
|
|
78480
78744
|
const inputRef = useRef();
|
|
78481
78745
|
const inputType = multiple ? "checkbox" : "radio";
|
|
@@ -87077,6 +87341,7 @@ const css$r = /* css */`@layer navi {
|
|
|
87077
87341
|
.navi_picker:is([data-variant="button"], [data-variant="border"], [data-variant="discrete-border"]) {
|
|
87078
87342
|
--picker-padding-x-default: var(--navi-button-padding-x-default);
|
|
87079
87343
|
--picker-padding-y-default: var(--navi-button-padding-y-default);
|
|
87344
|
+
--picker-font-family: var(--navi-button-font-family, var(--navi-control-font-family, inherit));
|
|
87080
87345
|
--picker-align-x-default: center;
|
|
87081
87346
|
--picker-background-color: var(--navi-button-background-color);
|
|
87082
87347
|
--picker-border-color-readonly: color-mix(in srgb,
|
|
@@ -87376,8 +87641,9 @@ const css$r = /* css */`@layer navi {
|
|
|
87376
87641
|
--x-corner-top-right-radius: initial;
|
|
87377
87642
|
--x-corner-bottom-right-radius: initial;
|
|
87378
87643
|
--x-corner-bottom-left-radius: initial;
|
|
87379
|
-
font-
|
|
87644
|
+
font-weight: initial;
|
|
87380
87645
|
text-align: initial;
|
|
87646
|
+
font-size: 1rem;
|
|
87381
87647
|
display: contents;
|
|
87382
87648
|
}
|
|
87383
87649
|
|
|
@@ -87615,9 +87881,10 @@ const PickerButton = props => {
|
|
|
87615
87881
|
// The same chain useControlProps resolves (own prop first, then what the
|
|
87616
87882
|
// group above says), for the two things it does not carry: the popup content,
|
|
87617
87883
|
// which is read-only along with the picker, and the cursor, which stays a
|
|
87618
|
-
// pointer on a picker that still opens.
|
|
87884
|
+
// pointer on a picker that still opens. A hold of the network policy goes
|
|
87885
|
+
// with it: what the popup changes is what the picker would send.
|
|
87619
87886
|
const readOnlyFromAbove = useContext(ReadOnlyContext);
|
|
87620
|
-
const readOnlyResolved = readOnly || readOnlyFromAbove;
|
|
87887
|
+
const [readOnlyResolved, readOnlyMessageResolved] = readOnlyHandedDown(uiStateController, readOnly || readOnlyFromAbove);
|
|
87621
87888
|
// Read off the controller rather than worked out again: what makes a
|
|
87622
87889
|
// read-only picker open is settled once, where the gate reads it (see
|
|
87623
87890
|
// createControlInfo's readOnlyOpens). Needed here for the cursor.
|
|
@@ -87665,11 +87932,13 @@ const PickerButton = props => {
|
|
|
87665
87932
|
/* Read-only crosses into everything the picker is made of: what it really
|
|
87666
87933
|
holds is drawn by controls of their own — in the popup, and on the façade
|
|
87667
87934
|
where an application puts its own affordances — and each of them refuses
|
|
87668
|
-
in
|
|
87935
|
+
once told, in the picker's words when it gave some (readOnlyMessage),
|
|
87936
|
+
in its own otherwise. Said from the read-only state alone, never
|
|
87669
87937
|
from the busy one — an action running for a moment is not the same thing
|
|
87670
87938
|
as a value nobody may change. */
|
|
87671
|
-
jsx(
|
|
87672
|
-
|
|
87939
|
+
jsx(ReadOnlyProvider, {
|
|
87940
|
+
readOnly: readOnlyResolved,
|
|
87941
|
+
readOnlyMessage: readOnlyMessageResolved,
|
|
87673
87942
|
children: jsxs(Box
|
|
87674
87943
|
// A word in a sentence (variant="text") sits in a <p>, where a <div> is
|
|
87675
87944
|
// not allowed: phrasing content there, block content elsewhere.
|