@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/dev/jsenv_navi.js
CHANGED
|
@@ -5689,7 +5689,13 @@ const MessagePropsRefContext = createContext();
|
|
|
5689
5689
|
const ControlIdContext = createContext();
|
|
5690
5690
|
const ControlNameContext = createContext();
|
|
5691
5691
|
const DisabledContext = createContext();
|
|
5692
|
+
// Truthy when what is above is read-only, and "network-policy" when that is a
|
|
5693
|
+
// write held by the network policy: what it holds is held in turn, and says
|
|
5694
|
+
// so in the policy's words (see readOnlyHandedDown in control_hooks.jsx).
|
|
5692
5695
|
const ReadOnlyContext = createContext();
|
|
5696
|
+
// The words that go with it, when what handed read-only down gave some (its
|
|
5697
|
+
// readOnlyMessage, or the ones it was handed in turn).
|
|
5698
|
+
const ReadOnlyMessageContext = createContext();
|
|
5693
5699
|
const RequiredContext = createContext();
|
|
5694
5700
|
const LoadingContext$1 = createContext();
|
|
5695
5701
|
createContext();
|
|
@@ -12079,6 +12085,31 @@ const resolveEffectiveDocumentState = (
|
|
|
12079
12085
|
return { ...state, ...sharedState };
|
|
12080
12086
|
};
|
|
12081
12087
|
|
|
12088
|
+
/**
|
|
12089
|
+
* What a press on a link handed to the navigation it starts (see the
|
|
12090
|
+
* integrations' `carryByLinkNavigation`): each write is an `editState` applied
|
|
12091
|
+
* to the entry that navigation writes, and an `otherwise` that makes the write
|
|
12092
|
+
* where it would have been made, for a press that starts no navigation here.
|
|
12093
|
+
*/
|
|
12094
|
+
const applyPressWrites = (state, pressWrites) => {
|
|
12095
|
+
if (!pressWrites) {
|
|
12096
|
+
return state;
|
|
12097
|
+
}
|
|
12098
|
+
let stateWritten = state;
|
|
12099
|
+
for (const { editState } of pressWrites) {
|
|
12100
|
+
stateWritten = editState(stateWritten);
|
|
12101
|
+
}
|
|
12102
|
+
return stateWritten;
|
|
12103
|
+
};
|
|
12104
|
+
const writePressWritesHere = (pressWrites) => {
|
|
12105
|
+
if (!pressWrites) {
|
|
12106
|
+
return;
|
|
12107
|
+
}
|
|
12108
|
+
for (const { otherwise } of pressWrites) {
|
|
12109
|
+
otherwise();
|
|
12110
|
+
}
|
|
12111
|
+
};
|
|
12112
|
+
|
|
12082
12113
|
// Preact's own useId() (see preact/hooks) returns "P<mask0>-<mask1>", where the
|
|
12083
12114
|
// mask is derived from render order within the nearest root/async boundary:
|
|
12084
12115
|
// stable across re-renders of the same mount, but not across two mounts on the
|
|
@@ -13734,6 +13765,7 @@ const setupBrowserIntegrationViaHistory = ({
|
|
|
13734
13765
|
// Asked to go where we already are: an address that redirects is never
|
|
13735
13766
|
// the one being displayed, so there is nothing to go to and nothing to
|
|
13736
13767
|
// stack on the history.
|
|
13768
|
+
writePressWritesHere(options.pressWrites);
|
|
13737
13769
|
return undefined;
|
|
13738
13770
|
}
|
|
13739
13771
|
return handleRoutingTask(redirectionUrl, {
|
|
@@ -13745,10 +13777,13 @@ const setupBrowserIntegrationViaHistory = ({
|
|
|
13745
13777
|
// Decided before anything is announced: an elided push IS the traversal it
|
|
13746
13778
|
// becomes, and the traversal will make its own announcements when the
|
|
13747
13779
|
// browser answers — a before/after cycle here would be about a navigation
|
|
13748
|
-
// that never happens.
|
|
13780
|
+
// that never happens. A push with something of its own for its entry — a
|
|
13781
|
+
// state, what the press handed over (see carryByLinkNavigation) — is a
|
|
13782
|
+
// new entry, never one standing there already.
|
|
13749
13783
|
if (
|
|
13750
13784
|
options.navigationType === "push" &&
|
|
13751
13785
|
options.state === undefined &&
|
|
13786
|
+
!options.pressWrites &&
|
|
13752
13787
|
url !== readAddress()
|
|
13753
13788
|
) {
|
|
13754
13789
|
const delta = adjacentEntryDelta(url);
|
|
@@ -13798,6 +13833,7 @@ const setupBrowserIntegrationViaHistory = ({
|
|
|
13798
13833
|
redirected,
|
|
13799
13834
|
landOn,
|
|
13800
13835
|
debounce,
|
|
13836
|
+
pressWrites,
|
|
13801
13837
|
} = options;
|
|
13802
13838
|
let { state } = options;
|
|
13803
13839
|
|
|
@@ -13808,15 +13844,18 @@ const setupBrowserIntegrationViaHistory = ({
|
|
|
13808
13844
|
|
|
13809
13845
|
if (navigationType === "push" || navigationType === "replace") {
|
|
13810
13846
|
markUrlAsVisited(url);
|
|
13811
|
-
const effectiveState =
|
|
13812
|
-
|
|
13813
|
-
|
|
13814
|
-
|
|
13815
|
-
|
|
13816
|
-
|
|
13817
|
-
|
|
13818
|
-
|
|
13819
|
-
|
|
13847
|
+
const effectiveState = applyPressWrites(
|
|
13848
|
+
resolveEffectiveDocumentState(state, {
|
|
13849
|
+
navigationType,
|
|
13850
|
+
isArrival: isArrival(url, { from: urlLeft }),
|
|
13851
|
+
currentState: getDocumentState(),
|
|
13852
|
+
sharedState: {
|
|
13853
|
+
jsenv_visited_urls: Array.from(visitedUrlSet),
|
|
13854
|
+
[NAV_DEPTH_STATE_KEY]: getNavDepth(),
|
|
13855
|
+
},
|
|
13856
|
+
}),
|
|
13857
|
+
pressWrites,
|
|
13858
|
+
);
|
|
13820
13859
|
if (navigationType === "replace" && debounce && state === undefined) {
|
|
13821
13860
|
// Nothing of its own for the entry: the address moves, the state is
|
|
13822
13861
|
// carried over. The one kind of write allowed to lag, and only when
|
|
@@ -13916,6 +13955,36 @@ const setupBrowserIntegrationViaHistory = ({
|
|
|
13916
13955
|
return requestedResult;
|
|
13917
13956
|
};
|
|
13918
13957
|
|
|
13958
|
+
// A press on a link is one navigation, and what the press asks of the
|
|
13959
|
+
// history entry is part of it: a popup the link's own command closes is
|
|
13960
|
+
// closed on the entry the link leads to, while the one it leaves keeps what
|
|
13961
|
+
// the reader was looking at — a back finds the popup open. The link's
|
|
13962
|
+
// listeners run before the routing is asked (below), so a write they make
|
|
13963
|
+
// is handed over, keyed by the click, rather than written onto the entry
|
|
13964
|
+
// being left. Once the link has been answered there is nothing to hand
|
|
13965
|
+
// over to: the navigation, when there was one, has already written its
|
|
13966
|
+
// entry, and a write lands there by itself.
|
|
13967
|
+
const linkPressWritesMap = new WeakMap();
|
|
13968
|
+
const answeredLinkClickSet = new WeakSet();
|
|
13969
|
+
const carryByLinkNavigation = (event, pressWrite) => {
|
|
13970
|
+
const clickEvent = findEvent(event, "click");
|
|
13971
|
+
if (
|
|
13972
|
+
!clickEvent ||
|
|
13973
|
+
clickEvent.eventPhase === Event.NONE ||
|
|
13974
|
+
answeredLinkClickSet.has(clickEvent) ||
|
|
13975
|
+
!clickEvent.target.closest("a")
|
|
13976
|
+
) {
|
|
13977
|
+
return false;
|
|
13978
|
+
}
|
|
13979
|
+
const pressWrites = linkPressWritesMap.get(clickEvent);
|
|
13980
|
+
if (pressWrites) {
|
|
13981
|
+
pressWrites.push(pressWrite);
|
|
13982
|
+
} else {
|
|
13983
|
+
linkPressWritesMap.set(clickEvent, [pressWrite]);
|
|
13984
|
+
}
|
|
13985
|
+
return true;
|
|
13986
|
+
};
|
|
13987
|
+
|
|
13919
13988
|
// A click on a link is answered on the link itself, after the link's own
|
|
13920
13989
|
// listeners: a navi control decides there whether the press is allowed — it
|
|
13921
13990
|
// refuses with preventDefault from its click reaction — and runs its command
|
|
@@ -13923,34 +13992,42 @@ const setupBrowserIntegrationViaHistory = ({
|
|
|
13923
13992
|
// is the order the Navigation API integration gets for free, where the
|
|
13924
13993
|
// navigation starts once the click has been dispatched.
|
|
13925
13994
|
const onLinkClick = (e) => {
|
|
13995
|
+
answeredLinkClickSet.add(e);
|
|
13996
|
+
const pressWrites = linkPressWritesMap.get(e);
|
|
13997
|
+
linkPressWritesMap.delete(e);
|
|
13998
|
+
if (!routeLinkClick(e, pressWrites)) {
|
|
13999
|
+
writePressWritesHere(pressWrites);
|
|
14000
|
+
}
|
|
14001
|
+
};
|
|
14002
|
+
const routeLinkClick = (e, pressWrites) => {
|
|
13926
14003
|
if (e.button !== 0) {
|
|
13927
14004
|
// Ignore non-left clicks
|
|
13928
|
-
return;
|
|
14005
|
+
return false;
|
|
13929
14006
|
}
|
|
13930
14007
|
if (e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) {
|
|
13931
14008
|
// A modifier asks the browser for something other than this tab: a new
|
|
13932
14009
|
// tab (meta on macOS, ctrl elsewhere), a new window (shift), a download
|
|
13933
14010
|
// (alt).
|
|
13934
|
-
return;
|
|
14011
|
+
return false;
|
|
13935
14012
|
}
|
|
13936
14013
|
if (e.defaultPrevented) {
|
|
13937
14014
|
// Refused — by the link itself, or by whoever came before it.
|
|
13938
|
-
return;
|
|
14015
|
+
return false;
|
|
13939
14016
|
}
|
|
13940
14017
|
const linkElement = e.currentTarget;
|
|
13941
14018
|
if (linkElement.hasAttribute("data-readonly")) {
|
|
13942
|
-
return;
|
|
14019
|
+
return false;
|
|
13943
14020
|
}
|
|
13944
14021
|
if (linkOpensElsewhere(linkElement)) {
|
|
13945
14022
|
// Another tab or window, or a download (see link_elsewhere.js).
|
|
13946
|
-
return;
|
|
14023
|
+
return false;
|
|
13947
14024
|
}
|
|
13948
14025
|
const href = linkElement.href;
|
|
13949
14026
|
const { isEmpty, isCurrent, isSameOrigin, isAnchor } =
|
|
13950
14027
|
getHrefTargetInfo(href);
|
|
13951
14028
|
if (isEmpty || !isSameOrigin) {
|
|
13952
14029
|
// Let link to other origins be handled by the browser
|
|
13953
|
-
return;
|
|
14030
|
+
return false;
|
|
13954
14031
|
}
|
|
13955
14032
|
if (isAnchor) {
|
|
13956
14033
|
// Fragment navigation belongs to the browser: it owns the indicated
|
|
@@ -13962,13 +14039,13 @@ const setupBrowserIntegrationViaHistory = ({
|
|
|
13962
14039
|
// change reaches whoever is waiting on the designated element.
|
|
13963
14040
|
rearmUrlTarget();
|
|
13964
14041
|
}
|
|
13965
|
-
return;
|
|
14042
|
+
return false;
|
|
13966
14043
|
}
|
|
13967
14044
|
if (linkAsksForDocument(linkElement)) {
|
|
13968
14045
|
// The link says its address is another document of this origin (see
|
|
13969
14046
|
// link_document.js). Routing to it would land on the fallback route
|
|
13970
14047
|
// instead of loading the page.
|
|
13971
|
-
return;
|
|
14048
|
+
return false;
|
|
13972
14049
|
}
|
|
13973
14050
|
// Nothing here declared a route, so there is nothing to route to: the
|
|
13974
14051
|
// page is a plain document and a link in it is a plain link. Taking it
|
|
@@ -13976,7 +14053,7 @@ const setupBrowserIntegrationViaHistory = ({
|
|
|
13976
14053
|
// the address bar moves and the page does not (see applyRouting's own
|
|
13977
14054
|
// "not called yet" branch, which is where that used to end up).
|
|
13978
14055
|
if (!isRouting()) {
|
|
13979
|
-
return;
|
|
14056
|
+
return false;
|
|
13980
14057
|
}
|
|
13981
14058
|
e.preventDefault();
|
|
13982
14059
|
handleRoutingTask(href, {
|
|
@@ -13990,7 +14067,9 @@ const setupBrowserIntegrationViaHistory = ({
|
|
|
13990
14067
|
// whoever knows what to do with it, and it is the anchor itself —
|
|
13991
14068
|
// resolved here, where it already is.
|
|
13992
14069
|
element: linkElement,
|
|
14070
|
+
pressWrites,
|
|
13993
14071
|
});
|
|
14072
|
+
return true;
|
|
13994
14073
|
};
|
|
13995
14074
|
// Wired from the capture phase on window, the first place a click is seen,
|
|
13996
14075
|
// so that a link is answered whatever handler stops the click on its way up
|
|
@@ -14170,6 +14249,7 @@ const setupBrowserIntegrationViaHistory = ({
|
|
|
14170
14249
|
navBack,
|
|
14171
14250
|
navForward,
|
|
14172
14251
|
getDocumentState,
|
|
14252
|
+
carryByLinkNavigation,
|
|
14173
14253
|
isVisited,
|
|
14174
14254
|
visitedUrlsSignal,
|
|
14175
14255
|
};
|
|
@@ -14707,8 +14787,32 @@ const useNavStateBasic = (
|
|
|
14707
14787
|
// that param for gone. Only with nothing of this document behind (the state
|
|
14708
14788
|
// was entered on a cold-loaded url, navBack has nowhere to go) does it
|
|
14709
14789
|
// rewrite in place.
|
|
14710
|
-
|
|
14790
|
+
//
|
|
14791
|
+
// event: what asked for it. A leave the press of a link asks for (its
|
|
14792
|
+
// --navi-close) is made by the navigation that link starts: the entry the
|
|
14793
|
+
// link leads to does not hold the key, and every entry behind is left as
|
|
14794
|
+
// the reader saw it — a back finds the state still entered.
|
|
14795
|
+
const leave = ({ isBack, event } = {}) => {
|
|
14711
14796
|
enteredRef.current = false;
|
|
14797
|
+
if (!Object.hasOwn(browserIntegration.getDocumentState() || {}, id)) {
|
|
14798
|
+
return;
|
|
14799
|
+
}
|
|
14800
|
+
if (
|
|
14801
|
+
event &&
|
|
14802
|
+
browserIntegration.carryByLinkNavigation(event, {
|
|
14803
|
+
editState: (state) => {
|
|
14804
|
+
const stateWithoutKey = { ...state };
|
|
14805
|
+
delete stateWithoutKey[id];
|
|
14806
|
+
return stateWithoutKey;
|
|
14807
|
+
},
|
|
14808
|
+
otherwise: () => leaveEntry({ isBack }),
|
|
14809
|
+
})
|
|
14810
|
+
) {
|
|
14811
|
+
return;
|
|
14812
|
+
}
|
|
14813
|
+
leaveEntry({ isBack });
|
|
14814
|
+
};
|
|
14815
|
+
const leaveEntry = ({ isBack }) => {
|
|
14712
14816
|
const currentStateCopy = browserIntegration.getDocumentState() || {};
|
|
14713
14817
|
if (!Object.hasOwn(currentStateCopy, id)) {
|
|
14714
14818
|
return;
|
|
@@ -14766,6 +14870,9 @@ const useNavStateBasic = (
|
|
|
14766
14870
|
* the value allows associating extra data when needed.
|
|
14767
14871
|
* - `leave()`: navigate AWAY FROM this state (removes `id` from document state,
|
|
14768
14872
|
* or goes back in history when `type` is "push").
|
|
14873
|
+
* `leave({ event })` with the event that asked for it: asked by the press
|
|
14874
|
+
* of a link that navigates, the key is left out of the entry the link
|
|
14875
|
+
* leads to, and the entry it leaves keeps it.
|
|
14769
14876
|
*/
|
|
14770
14877
|
const useNavState = useNavStateWithWarnings
|
|
14771
14878
|
;
|
|
@@ -17996,8 +18103,13 @@ const useOpenPropsEffectOnOpenController = (
|
|
|
17996
18103
|
} else {
|
|
17997
18104
|
// Under type "push" a cancel discards everything written while
|
|
17998
18105
|
// the popup was open — it goes back with the entry; a confirmed
|
|
17999
|
-
// close keeps those writes (see useNavState's own leave()).
|
|
18000
|
-
|
|
18106
|
+
// close keeps those writes (see useNavState's own leave()). A
|
|
18107
|
+
// close a link's press asked for is written by the navigation
|
|
18108
|
+
// the link starts.
|
|
18109
|
+
leaveNavState({
|
|
18110
|
+
isBack: Boolean(event?.detail?.isCancel),
|
|
18111
|
+
event,
|
|
18112
|
+
});
|
|
18001
18113
|
}
|
|
18002
18114
|
}
|
|
18003
18115
|
if (signal) {
|
|
@@ -18218,8 +18330,9 @@ const useOpenControllerByProps = (props, name) => {
|
|
|
18218
18330
|
* opened it, so a section written in a display font gets its tooltips in that
|
|
18219
18331
|
* font. `color`, `font-size` and `font-weight` are absent too — each surface
|
|
18220
18332
|
* answers those its own way (a popup and a callout write in
|
|
18221
|
-
* --navi-popup-color; a popup follows the size of what opened it
|
|
18222
|
-
*
|
|
18333
|
+
* --navi-popup-color; a popup follows the size of what opened it — for a
|
|
18334
|
+
* picker's popup, what is around the picker, see .navi_picker_content — a
|
|
18335
|
+
* callout resets to the document's size).
|
|
18223
18336
|
*
|
|
18224
18337
|
* In `@layer navi` so an app that wants one of these back says so on the
|
|
18225
18338
|
* surface and wins, without having to out-specify anything.
|
|
@@ -21909,6 +22022,13 @@ CONSTRAINT_ATTRIBUTE_SET.add("data-readonly");
|
|
|
21909
22022
|
CONSTRAINT_ATTRIBUTE_SET.add("data-readonly-reason");
|
|
21910
22023
|
|
|
21911
22024
|
const readOnlyMessage = (field) => {
|
|
22025
|
+
// Read-only from above, in the words of what made it so (a picker's or a
|
|
22026
|
+
// group's readOnlyMessage): what it holds says what it says — over the
|
|
22027
|
+
// network policy's words too, as that control's own words win over them on
|
|
22028
|
+
// itself.
|
|
22029
|
+
if (field.readOnlyMessageFromAbove) {
|
|
22030
|
+
return field.readOnlyMessageFromAbove;
|
|
22031
|
+
}
|
|
21912
22032
|
// Read-only for a reason the control named itself, read off the reason
|
|
21913
22033
|
// rather than off the surrounding state: a button read-only for its own
|
|
21914
22034
|
// reasons, inside a form that happens to be unchanged, is not waiting for
|
|
@@ -48049,6 +48169,8 @@ const useUIFacadeStateController = (props, realUIStateController) => {
|
|
|
48049
48169
|
s.controller.controlHostProps = realUIStateController.controlHostProps;
|
|
48050
48170
|
s.controller.readOnlyWithoutRun =
|
|
48051
48171
|
realUIStateController.readOnlyWithoutRun;
|
|
48172
|
+
s.controller.readOnlyMessageFromAbove =
|
|
48173
|
+
realUIStateController.readOnlyMessageFromAbove;
|
|
48052
48174
|
realUIStateController.pushStateDownToFacadeChild =
|
|
48053
48175
|
s.controller.pushStateDownToChild;
|
|
48054
48176
|
|
|
@@ -48472,6 +48594,7 @@ const ControlgroupChildrenWrapper = ({
|
|
|
48472
48594
|
required,
|
|
48473
48595
|
disabled,
|
|
48474
48596
|
readOnly,
|
|
48597
|
+
readOnlyMessage,
|
|
48475
48598
|
loading,
|
|
48476
48599
|
boundAction,
|
|
48477
48600
|
actionRequesterSignal
|
|
@@ -48485,8 +48608,9 @@ const ControlgroupChildrenWrapper = ({
|
|
|
48485
48608
|
value: name,
|
|
48486
48609
|
children: jsx(DisabledContext.Provider, {
|
|
48487
48610
|
value: disabled,
|
|
48488
|
-
children: jsx(
|
|
48489
|
-
|
|
48611
|
+
children: jsx(ReadOnlyProvider, {
|
|
48612
|
+
readOnly: readOnly,
|
|
48613
|
+
readOnlyMessage: readOnlyMessage,
|
|
48490
48614
|
children: jsx(RequiredContext.Provider, {
|
|
48491
48615
|
value: required,
|
|
48492
48616
|
children: jsx(LoadingContext$1.Provider, {
|
|
@@ -48506,6 +48630,34 @@ const ControlgroupChildrenWrapper = ({
|
|
|
48506
48630
|
})
|
|
48507
48631
|
})
|
|
48508
48632
|
});
|
|
48633
|
+
// What a control hands to what it holds about being read-only: the state, and
|
|
48634
|
+
// the words it is said in. What it holds writes into it, so it is held for the
|
|
48635
|
+
// same reason and says what the control says. Held by the network policy, it
|
|
48636
|
+
// hands down the hold itself — read-only alone, what it holds would refuse in
|
|
48637
|
+
// navi's generic words. Read-only, it hands down its readOnlyMessage, or the
|
|
48638
|
+
// one it was handed.
|
|
48639
|
+
const readOnlyHandedDown = (uiStateController, readOnly) => {
|
|
48640
|
+
const {
|
|
48641
|
+
controlHostProps,
|
|
48642
|
+
props
|
|
48643
|
+
} = uiStateController;
|
|
48644
|
+
const readOnlyResolved = controlHostProps["data-readonly-reason"] === "network-policy" ? "network-policy" : readOnly;
|
|
48645
|
+
if (!readOnlyResolved) {
|
|
48646
|
+
return [readOnlyResolved, undefined];
|
|
48647
|
+
}
|
|
48648
|
+
return [readOnlyResolved, props.readOnlyMessage ?? uiStateController.readOnlyMessageFromAbove];
|
|
48649
|
+
};
|
|
48650
|
+
const ReadOnlyProvider = ({
|
|
48651
|
+
readOnly,
|
|
48652
|
+
readOnlyMessage,
|
|
48653
|
+
children
|
|
48654
|
+
}) => jsx(ReadOnlyContext.Provider, {
|
|
48655
|
+
value: readOnly,
|
|
48656
|
+
children: jsx(ReadOnlyMessageContext.Provider, {
|
|
48657
|
+
value: readOnlyMessage,
|
|
48658
|
+
children: children
|
|
48659
|
+
})
|
|
48660
|
+
});
|
|
48509
48661
|
|
|
48510
48662
|
// What the caller writes for these is called from the control's own reactions
|
|
48511
48663
|
// (see `reactions` below), so the split leaves them out of both sides.
|
|
@@ -49756,7 +49908,7 @@ const useControlgroupProps = (props, {
|
|
|
49756
49908
|
basePseudoState
|
|
49757
49909
|
} = controlgroupProps;
|
|
49758
49910
|
const disabled = basePseudoState[":disabled"];
|
|
49759
|
-
const readOnly = basePseudoState[":read-only"];
|
|
49911
|
+
const [readOnly, readOnlyMessage] = readOnlyHandedDown(uiGroupStateController, basePseudoState[":read-only"]);
|
|
49760
49912
|
const loading = basePseudoState[":-navi-loading"];
|
|
49761
49913
|
const controlgroupChildrenWrapperProps = useMemo(() => ({
|
|
49762
49914
|
uiGroupStateController,
|
|
@@ -49764,10 +49916,11 @@ const useControlgroupProps = (props, {
|
|
|
49764
49916
|
required: controlgroupProps.required,
|
|
49765
49917
|
disabled,
|
|
49766
49918
|
readOnly,
|
|
49919
|
+
readOnlyMessage,
|
|
49767
49920
|
loading,
|
|
49768
49921
|
boundAction,
|
|
49769
49922
|
actionRequesterSignal
|
|
49770
|
-
}), [uiGroupStateController, controlgroupProps.name, controlgroupProps.required, disabled, readOnly, loading, boundAction, actionRequesterSignal]);
|
|
49923
|
+
}), [uiGroupStateController, controlgroupProps.name, controlgroupProps.required, disabled, readOnly, readOnlyMessage, loading, boundAction, actionRequesterSignal]);
|
|
49771
49924
|
return [controlRootProps, {
|
|
49772
49925
|
...controlgroupProps,
|
|
49773
49926
|
"name": undefined,
|
|
@@ -49963,6 +50116,7 @@ const useInteractiveProps = (props, {
|
|
|
49963
50116
|
{
|
|
49964
50117
|
const controlDisabledFromAbove = useContext(DisabledContext);
|
|
49965
50118
|
const controlReadOnlyFromAbove = useContext(ReadOnlyContext);
|
|
50119
|
+
const controlReadOnlyMessageFromAbove = useContext(ReadOnlyMessageContext);
|
|
49966
50120
|
const controlRequired = useContext(RequiredContext);
|
|
49967
50121
|
const controlLoadingFromAbove = useContext(LoadingContext$1);
|
|
49968
50122
|
// A SIGNAL holding the element whose press the group's action is wearing
|
|
@@ -50002,8 +50156,15 @@ const useInteractiveProps = (props, {
|
|
|
50002
50156
|
// pressable on a game nobody may edit. Its own props still hold; only what
|
|
50003
50157
|
// came from above is dropped (see self_interactions.js for the three modes).
|
|
50004
50158
|
const zoneStateApplies = !selfInteractionsIgnoreBlock(props);
|
|
50159
|
+
// A press that only leaves the popup it sits in writes nothing to the zone
|
|
50160
|
+
// around it either, so that zone being read-only — or holding a write the
|
|
50161
|
+
// network policy keeps — does not hold it: the popup answers the close
|
|
50162
|
+
// itself. A read-only picker's popup then closes from its own button as
|
|
50163
|
+
// it does from a press outside, and refuses both alike when it holds a
|
|
50164
|
+
// change it cannot send.
|
|
50165
|
+
const zoneReadOnlyApplies = zoneStateApplies && !pressOnlyLeaves(props);
|
|
50005
50166
|
const controlDisabled = zoneStateApplies && controlDisabledFromAbove;
|
|
50006
|
-
const controlReadOnly =
|
|
50167
|
+
const controlReadOnly = zoneReadOnlyApplies && controlReadOnlyFromAbove;
|
|
50007
50168
|
const controlLoading = zoneStateApplies && controlLoadingFromAbove;
|
|
50008
50169
|
const disabledResolved = disabled || controlDisabled;
|
|
50009
50170
|
const requiredResolved = required || controlRequired;
|
|
@@ -50018,10 +50179,11 @@ const useInteractiveProps = (props, {
|
|
|
50018
50179
|
// but cannot be taken.
|
|
50019
50180
|
const readOnlyFromParentMaxLengthGuard = Boolean(zoneStateApplies && uiStateController.parentUIStateController?.isChildBlockedByMaxLengthGuard?.(uiStateController));
|
|
50020
50181
|
// A write cannot leave under a network policy, so the control asking for
|
|
50021
|
-
// one —
|
|
50022
|
-
//
|
|
50023
|
-
//
|
|
50024
|
-
|
|
50182
|
+
// one — sitting in a form that does, or in what a held control holds (a
|
|
50183
|
+
// picker's popup) — refuses before the press and says why (see
|
|
50184
|
+
// network_policy.js): a press that looks accepted and fails after is what
|
|
50185
|
+
// the policy exists to avoid.
|
|
50186
|
+
const heldByNetworkPolicy = networkPolicyReason !== null && (isWriteAction(boundAction) || Boolean(zoneReadOnlyApplies && parentAction && isWriteAction(parentAction)) || controlReadOnly === "network-policy");
|
|
50025
50187
|
// Held back because the surface above already has as many runs in flight as
|
|
50026
50188
|
// it allows (see parallel_guard.js). Only a control that would START one:
|
|
50027
50189
|
// anything without an action of its own runs nothing and has nothing to
|
|
@@ -50040,6 +50202,10 @@ const useInteractiveProps = (props, {
|
|
|
50040
50202
|
// still read-only in the tick the run settles — the tick a form's
|
|
50041
50203
|
// after-send `--navi-reset` asks the form to empty itself.
|
|
50042
50204
|
uiStateController.readOnlyWithoutRun = Boolean(readOnlyBase);
|
|
50205
|
+
// The words of what made this control read-only from above, when it gave
|
|
50206
|
+
// some: read by READONLY_CONSTRAINT, and handed further down with the
|
|
50207
|
+
// read-only state (see readOnlyHandedDown).
|
|
50208
|
+
uiStateController.readOnlyMessageFromAbove = controlReadOnly ? controlReadOnlyMessageFromAbove : undefined;
|
|
50043
50209
|
// Read-only, and what this control opens still opens: reading what is in
|
|
50044
50210
|
// there changes nothing. Read by READONLY_CONSTRAINT, which lets an
|
|
50045
50211
|
// interaction that only reads through on it.
|
|
@@ -50574,6 +50740,12 @@ const splitControlProps = (props, {
|
|
|
50574
50740
|
}
|
|
50575
50741
|
return [controlRootProps, controlHostProps];
|
|
50576
50742
|
};
|
|
50743
|
+
// What a press leaving a popup asks for: closing it, or cancelling it. Only on
|
|
50744
|
+
// a control running nothing of its own — one with an action writes, wherever
|
|
50745
|
+
// it then leads.
|
|
50746
|
+
const LEAVING_COMMAND_SET = new Set(["--navi-close", "--navi-cancel"]);
|
|
50747
|
+
const pressOnlyLeaves = props => LEAVING_COMMAND_SET.has(props.command) && !props.action;
|
|
50748
|
+
|
|
50577
50749
|
// `onPointerDown`, `onFocusOut`… but not navi's own events (`onnavi_command`),
|
|
50578
50750
|
// which keep the element they are dispatched on.
|
|
50579
50751
|
const isDomListenerProp = key => /^on[A-Z]/.test(key);
|
|
@@ -54584,7 +54756,9 @@ const LinkPseudoElements = ["::-navi-loader", "::-navi-indicator"];
|
|
|
54584
54756
|
* fetching on a hover.
|
|
54585
54757
|
* @param {string} [props.command] - What the press asks of a control around
|
|
54586
54758
|
* the link — `"--navi-close"` on a link that leaves the sheet it is in.
|
|
54587
|
-
* Triggered on the press, before the navigation.
|
|
54759
|
+
* Triggered on the press, before the navigation. A popup it closes that
|
|
54760
|
+
* keeps its open state in the history entry (`navState`) is closed on the
|
|
54761
|
+
* entry the navigation leads to: Back finds it open.
|
|
54588
54762
|
* @param {Function} [props.action] - Work the press runs, before the
|
|
54589
54763
|
* navigation. Nothing waits for it — not the navigation, not `command`: what
|
|
54590
54764
|
* the next page must find has to be written synchronously (a draft in a
|
|
@@ -59148,7 +59322,7 @@ const css$S = /* css */`@layer navi {
|
|
|
59148
59322
|
--button-color: currentColor;
|
|
59149
59323
|
--button-cursor: pointer;
|
|
59150
59324
|
--button-font-size: var(--navi-control-font-size);
|
|
59151
|
-
--button-font-family: var(--navi-control-font-family, inherit);
|
|
59325
|
+
--button-font-family: var(--navi-button-font-family, var(--navi-control-font-family, inherit));
|
|
59152
59326
|
--button-border-color-hover: color-mix(in srgb,
|
|
59153
59327
|
var(--button-border-color) 70%,
|
|
59154
59328
|
black);
|
|
@@ -60893,14 +61067,16 @@ const css$O = /* css */`@layer navi {
|
|
|
60893
61067
|
--checkmark-color-disabled: #eee;
|
|
60894
61068
|
--border-color-disabled-checked: #d3d3d3;
|
|
60895
61069
|
--background-color-disabled-checked: #d3d3d3;
|
|
60896
|
-
--button-border-color:
|
|
60897
|
-
--button-background-color:
|
|
61070
|
+
--button-border-color: var(--navi-control-border-color);
|
|
61071
|
+
--button-background-color: var(--navi-button-background-color);
|
|
60898
61072
|
--button-border-color-hover: color-mix(in srgb,
|
|
60899
61073
|
var(--button-border-color) 70%,
|
|
60900
61074
|
black);
|
|
60901
61075
|
--button-background-color-hover: color-mix(in srgb,
|
|
60902
61076
|
var(--button-background-color) 95%,
|
|
60903
61077
|
black);
|
|
61078
|
+
--button-background-color-readonly: var(--button-background-color);
|
|
61079
|
+
--button-background-color-disabled: var(--button-background-color-readonly);
|
|
60904
61080
|
}
|
|
60905
61081
|
|
|
60906
61082
|
.navi_checkbox[data-variant="switch"] {
|
|
@@ -60928,19 +61104,40 @@ const css$O = /* css */`@layer navi {
|
|
|
60928
61104
|
--margin: 0;
|
|
60929
61105
|
--width: auto;
|
|
60930
61106
|
--height: auto;
|
|
61107
|
+
--font-family: var(--navi-button-font-family, var(--navi-control-font-family, inherit));
|
|
60931
61108
|
--border-color: var(--button-border-color);
|
|
60932
61109
|
--border-color-hover: var(--button-border-color-hover);
|
|
60933
61110
|
--background-color: var(--button-background-color);
|
|
60934
61111
|
--background-color-hover: var(--button-background-color-hover);
|
|
60935
61112
|
--background-color-readonly: var(--button-background-color-readonly);
|
|
60936
61113
|
--background-color-disabled: var(--button-background-color-disabled);
|
|
61114
|
+
}
|
|
61115
|
+
|
|
61116
|
+
.navi_checkbox[data-variant="button"]:not([data-label]) {
|
|
61117
|
+
--button-padding-x-default: 0;
|
|
61118
|
+
--button-padding-y-default: 0;
|
|
60937
61119
|
--border-color-checked: var(--button-border-color);
|
|
61120
|
+
--border-color-hover-checked: var(--button-border-color-hover);
|
|
60938
61121
|
--background-color-checked: var(--button-background-color);
|
|
61122
|
+
--background-color-hover-checked: var(--button-background-color-hover);
|
|
61123
|
+
--checkmark-color: currentColor;
|
|
60939
61124
|
}
|
|
60940
61125
|
|
|
60941
61126
|
.navi_checkbox[data-variant="button"][data-label] {
|
|
60942
|
-
--border-
|
|
60943
|
-
--
|
|
61127
|
+
--border-radius: var(--navi-control-border-radius);
|
|
61128
|
+
--button-padding-x-default: var(--navi-button-padding-x-default);
|
|
61129
|
+
--button-padding-y-default: var(--navi-button-padding-y-default);
|
|
61130
|
+
line-height: var(--navi-control-line-height);
|
|
61131
|
+
}
|
|
61132
|
+
|
|
61133
|
+
.navi_checkbox[data-variant="button"][data-button-variant="discrete"] {
|
|
61134
|
+
--border-width: 0;
|
|
61135
|
+
--button-border-color: transparent;
|
|
61136
|
+
--button-border-color-hover: var(--button-border-color);
|
|
61137
|
+
--button-background-color: transparent;
|
|
61138
|
+
--button-background-color-hover: color-mix(in srgb,
|
|
61139
|
+
currentColor 8%,
|
|
61140
|
+
var(--button-background-color));
|
|
60944
61141
|
}
|
|
60945
61142
|
}
|
|
60946
61143
|
|
|
@@ -61048,23 +61245,24 @@ const css$O = /* css */`@layer navi {
|
|
|
61048
61245
|
--color-mix: var(--color-mix-light);
|
|
61049
61246
|
}
|
|
61050
61247
|
|
|
61248
|
+
& .navi_checkbox_marker {
|
|
61249
|
+
opacity: 0;
|
|
61250
|
+
stroke: var(--x-checkmark-color);
|
|
61251
|
+
transform: scale(.5);
|
|
61252
|
+
}
|
|
61253
|
+
|
|
61254
|
+
&[data-checked] .navi_checkbox_marker {
|
|
61255
|
+
opacity: 1;
|
|
61256
|
+
transition-property: opacity, transform;
|
|
61257
|
+
transition-duration: .15s;
|
|
61258
|
+
transition-timing-function: ease;
|
|
61259
|
+
transform: scale(1);
|
|
61260
|
+
}
|
|
61261
|
+
|
|
61051
61262
|
&[data-variant="checkbox"] {
|
|
61052
61263
|
& .navi_checkbox_marker {
|
|
61053
|
-
opacity: 0;
|
|
61054
61264
|
width: 100%;
|
|
61055
61265
|
height: 100%;
|
|
61056
|
-
stroke: var(--x-checkmark-color);
|
|
61057
|
-
transform: scale(.5);
|
|
61058
|
-
}
|
|
61059
|
-
|
|
61060
|
-
&[data-checked] {
|
|
61061
|
-
& .navi_checkbox_marker {
|
|
61062
|
-
opacity: 1;
|
|
61063
|
-
transition-property: opacity, transform;
|
|
61064
|
-
transition-duration: .15s;
|
|
61065
|
-
transition-timing-function: ease;
|
|
61066
|
-
transform: scale(1);
|
|
61067
|
-
}
|
|
61068
61266
|
}
|
|
61069
61267
|
|
|
61070
61268
|
&[data-accent-very-light] {
|
|
@@ -61103,6 +61301,11 @@ const css$O = /* css */`@layer navi {
|
|
|
61103
61301
|
justify-content: center;
|
|
61104
61302
|
align-items: center;
|
|
61105
61303
|
|
|
61304
|
+
& .navi_checkbox_marker {
|
|
61305
|
+
width: 1em;
|
|
61306
|
+
height: 1em;
|
|
61307
|
+
}
|
|
61308
|
+
|
|
61106
61309
|
&[data-label] {
|
|
61107
61310
|
&[data-checked] .navi_checkbox_label {
|
|
61108
61311
|
color: var(--x-checkmark-color);
|
|
@@ -61162,7 +61365,8 @@ const InputCheckboxFieldInterface = props => {
|
|
|
61162
61365
|
const {
|
|
61163
61366
|
icon,
|
|
61164
61367
|
switch: switchProp,
|
|
61165
|
-
|
|
61368
|
+
buttonVariant,
|
|
61369
|
+
variant = buttonVariant ? "button" : icon ? "icon" : switchProp ? "switch" : "checkbox",
|
|
61166
61370
|
// "checkbox", "switch", "icon", "button"
|
|
61167
61371
|
accentColor
|
|
61168
61372
|
} = props;
|
|
@@ -61217,7 +61421,9 @@ const InputCheckboxFieldInterface = props => {
|
|
|
61217
61421
|
variant: undefined,
|
|
61218
61422
|
switch: undefined,
|
|
61219
61423
|
icon: undefined,
|
|
61424
|
+
buttonVariant: undefined,
|
|
61220
61425
|
"data-variant": variant,
|
|
61426
|
+
"data-button-variant": variant === "button" ? buttonVariant : undefined,
|
|
61221
61427
|
"data-label": hasLabel ? "" : undefined,
|
|
61222
61428
|
baseClassName: "navi_checkbox",
|
|
61223
61429
|
pseudoStateSelector: ".navi_control_input",
|
|
@@ -61691,6 +61897,9 @@ const css$M = /* css */`@layer navi {
|
|
|
61691
61897
|
--radiomark-color-disabled: #d3d3d3;
|
|
61692
61898
|
--border-color-checked-disabled: #d3d3d3;
|
|
61693
61899
|
--background-color-disabled-checked: var(--background-color);
|
|
61900
|
+
--button-padding-x-default: 0;
|
|
61901
|
+
--button-padding-y-default: 0;
|
|
61902
|
+
--button-border-radius: var(--navi-control-border-radius);
|
|
61694
61903
|
--button-border-width: 1px;
|
|
61695
61904
|
--button-border-color: transparent;
|
|
61696
61905
|
--button-background-color: transparent;
|
|
@@ -63915,6 +64124,7 @@ const InputPseudoElements = ["::-navi-loader"];
|
|
|
63915
64124
|
* boolean?: boolean,
|
|
63916
64125
|
* selectOnPress?: boolean,
|
|
63917
64126
|
* variant?: "checkbox" | "switch" | "icon" | "button",
|
|
64127
|
+
* buttonVariant?: "discrete",
|
|
63918
64128
|
* actionVerb?: "GET" | "POST" | "PUT" | "PATCH" | "DELETE",
|
|
63919
64129
|
* [key: string]: any,
|
|
63920
64130
|
* }>}
|
|
@@ -63930,6 +64140,10 @@ const InputPseudoElements = ["::-navi-loader"];
|
|
|
63930
64140
|
* is a square around its checkmark (or its `icon`, which takes an
|
|
63931
64141
|
* `[off, on]` pair). Bound with `signal`, it follows whatever else writes
|
|
63932
64142
|
* that signal.
|
|
64143
|
+
* @param {"discrete"} [buttonVariant] A checkbox drawn as a button, drawn as
|
|
64144
|
+
* that variant of `Button`: `"discrete"` has no box at rest and a wash on
|
|
64145
|
+
* hover (checked, its words still fill with the accent). Implies
|
|
64146
|
+
* `variant="button"`.
|
|
63933
64147
|
* @param {"GET"|"POST"|"PUT"|"PATCH"|"DELETE"} [actionVerb] What a plain
|
|
63934
64148
|
* function `action` does to the server. A write verb puts the field under
|
|
63935
64149
|
* the network policy: held read-only up front, with the policy's message,
|
|
@@ -73258,6 +73472,10 @@ const UncontrolledDialog = props => {
|
|
|
73258
73472
|
// needs the dialog element to look at what it contains.
|
|
73259
73473
|
const defaultRef = useRef();
|
|
73260
73474
|
props.ref = props.ref || defaultRef;
|
|
73475
|
+
// The close is built once per opening (see useOpenController below): read
|
|
73476
|
+
// through a ref, an onClose given by a render while open is the one called.
|
|
73477
|
+
const onCloseRef = useRef(null);
|
|
73478
|
+
onCloseRef.current = props.onClose;
|
|
73261
73479
|
const openController = useOpenController(openEvent => {
|
|
73262
73480
|
const dialogEl = props.ref.current;
|
|
73263
73481
|
debugPopup(openEvent, `dialog opened`);
|
|
@@ -73285,7 +73503,7 @@ const UncontrolledDialog = props => {
|
|
|
73285
73503
|
requestCloseEvent.preventDefault();
|
|
73286
73504
|
},
|
|
73287
73505
|
onClose: closeEvent => {
|
|
73288
|
-
|
|
73506
|
+
onCloseRef.current?.(closeEvent);
|
|
73289
73507
|
}
|
|
73290
73508
|
};
|
|
73291
73509
|
});
|
|
@@ -75232,6 +75450,9 @@ const UncontrolledPopover = props => {
|
|
|
75232
75450
|
// the popover element to read what it holds.
|
|
75233
75451
|
const defaultRef = useRef();
|
|
75234
75452
|
props.ref = props.ref || defaultRef;
|
|
75453
|
+
// Read at the close, not captured at the opening: see UncontrolledDialog.
|
|
75454
|
+
const onCloseRef = useRef(null);
|
|
75455
|
+
onCloseRef.current = props.onClose;
|
|
75235
75456
|
// Same as Dialog's own UncontrolledDialog, for the same reasons — see it for
|
|
75236
75457
|
// the full story: a popover is a surface, so the only thing it has to say
|
|
75237
75458
|
// about closing is that what it contains must not be interrupted mid-action.
|
|
@@ -75257,7 +75478,7 @@ const UncontrolledPopover = props => {
|
|
|
75257
75478
|
requestCloseEvent.preventDefault();
|
|
75258
75479
|
},
|
|
75259
75480
|
onClose: closeEvent => {
|
|
75260
|
-
|
|
75481
|
+
onCloseRef.current?.(closeEvent);
|
|
75261
75482
|
}
|
|
75262
75483
|
};
|
|
75263
75484
|
});
|
|
@@ -77117,6 +77338,15 @@ const PickerCustom = props => {
|
|
|
77117
77338
|
// closed (see onClose below) — a press that ran before the close would make
|
|
77118
77339
|
// the picker busy, and a busy picker refuses the very close that follows.
|
|
77119
77340
|
const confirmEventRef = useRef(null);
|
|
77341
|
+
// The close is built once per opening (see useOpenController below), but
|
|
77342
|
+
// these props answer how it ends: read through a ref, a render while open
|
|
77343
|
+
// (a sheet turned into the next question) is heard by the close.
|
|
77344
|
+
const closePropsRef = useRef(null);
|
|
77345
|
+
closePropsRef.current = {
|
|
77346
|
+
canSendWhileUnchanged,
|
|
77347
|
+
onConfirm,
|
|
77348
|
+
onClose
|
|
77349
|
+
};
|
|
77120
77350
|
// aria-controls + id
|
|
77121
77351
|
const popupId = `${props.id}_picker_popup`;
|
|
77122
77352
|
{
|
|
@@ -77217,7 +77447,7 @@ const PickerCustom = props => {
|
|
|
77217
77447
|
// and for that picker the same value said again means something.
|
|
77218
77448
|
// A press outside, Escape, the cross say nothing and keep skipping.
|
|
77219
77449
|
const said = requestCloseEvent.detail.isSend || confirmEventRef.current;
|
|
77220
|
-
if (!(canSendWhileUnchanged && said)) {
|
|
77450
|
+
if (!(closePropsRef.current.canSendWhileUnchanged && said)) {
|
|
77221
77451
|
// No action to run, but still allow the close.
|
|
77222
77452
|
return;
|
|
77223
77453
|
}
|
|
@@ -77289,7 +77519,7 @@ const PickerCustom = props => {
|
|
|
77289
77519
|
const confirmEvent = confirmEventRef.current;
|
|
77290
77520
|
confirmEventRef.current = null;
|
|
77291
77521
|
if (confirmEvent && !closeEvent.detail.isCancel) {
|
|
77292
|
-
onConfirm?.(confirmEvent);
|
|
77522
|
+
closePropsRef.current.onConfirm?.(confirmEvent);
|
|
77293
77523
|
}
|
|
77294
77524
|
// After the value bookkeeping above — whoever listens reads the
|
|
77295
77525
|
// picker's value as it ends up, committed or restored on a cancel —
|
|
@@ -77300,7 +77530,7 @@ const PickerCustom = props => {
|
|
|
77300
77530
|
// spells into the address — a route param naming what was being
|
|
77301
77531
|
// edited, cleared now that nothing is — has to be written before,
|
|
77302
77532
|
// or the landing puts it back.
|
|
77303
|
-
onClose?.(closeEvent);
|
|
77533
|
+
closePropsRef.current.onClose?.(closeEvent);
|
|
77304
77534
|
leaveExpanded({
|
|
77305
77535
|
isBack: closeEvent.detail.isCancel
|
|
77306
77536
|
});
|
|
@@ -77390,6 +77620,11 @@ const PickerCustom = props => {
|
|
|
77390
77620
|
// button) hangs its popup off the whole control instead.
|
|
77391
77621
|
anchor: props.anchor || props.ref,
|
|
77392
77622
|
openController,
|
|
77623
|
+
// Before the content is built and shown, so it is laid out and placed
|
|
77624
|
+
// at the size it is read at (see .navi_picker_content in picker.jsx).
|
|
77625
|
+
onOpen: () => {
|
|
77626
|
+
writeContainerFont(ref.current, popupRef.current);
|
|
77627
|
+
},
|
|
77393
77628
|
// A picker whose value was never given to it reads it off the control in
|
|
77394
77629
|
// its popup (see useUIFacadeStateController), so that control is built as
|
|
77395
77630
|
// soon as something reads the value: at mount when the picker sees the
|
|
@@ -78214,6 +78449,30 @@ const showNativePicker = (pickerInput, event) => {
|
|
|
78214
78449
|
}
|
|
78215
78450
|
};
|
|
78216
78451
|
|
|
78452
|
+
// The popup of a picker is opened where the picker stands, so it writes at the
|
|
78453
|
+
// size and weight of what is around it — the ones a Dialog rendered there
|
|
78454
|
+
// inherits — and never at the ones the trigger is drawn at. CSS cannot reach
|
|
78455
|
+
// past the picker's own: its root holds the popup and sets both. Written on the
|
|
78456
|
+
// holder only when they differ, so an opening that changes nothing invalidates
|
|
78457
|
+
// no style.
|
|
78458
|
+
const writeContainerFont = (pickerEl, popupEl) => {
|
|
78459
|
+
const container = pickerEl?.parentElement;
|
|
78460
|
+
const holder = popupEl?.closest("[data-picker-content]");
|
|
78461
|
+
if (!container || !holder) {
|
|
78462
|
+
return;
|
|
78463
|
+
}
|
|
78464
|
+
const {
|
|
78465
|
+
fontSize,
|
|
78466
|
+
fontWeight
|
|
78467
|
+
} = getComputedStyle(container);
|
|
78468
|
+
if (holder.style.fontSize !== fontSize) {
|
|
78469
|
+
holder.style.fontSize = fontSize;
|
|
78470
|
+
}
|
|
78471
|
+
if (holder.style.fontWeight !== fontWeight) {
|
|
78472
|
+
holder.style.fontWeight = fontWeight;
|
|
78473
|
+
}
|
|
78474
|
+
};
|
|
78475
|
+
|
|
78217
78476
|
installImportMetaCssBuild(import.meta);
|
|
78218
78477
|
const css$y = /* css */`.navi_picker_confirm_body {
|
|
78219
78478
|
min-width: 180px;
|
|
@@ -80181,11 +80440,16 @@ const ListItemSelectable = props => {
|
|
|
80181
80440
|
// A list waiting on something is not unavailable, it is not answering yet —
|
|
80182
80441
|
// busy rather than read-only (see BUSY_CONSTRAINT, which is asked first),
|
|
80183
80442
|
// and the wait is about the same thing the read-only would be about.
|
|
80443
|
+
//
|
|
80444
|
+
// Unless what made the list read-only says it better: in words of its own (a
|
|
80445
|
+
// picker's or a list's readOnlyMessage), or because it is the network
|
|
80446
|
+
// policy holding the write the selection would make.
|
|
80184
80447
|
const readOnlyFromAbove = useContext(ReadOnlyContext);
|
|
80448
|
+
const readOnlyMessageFromAbove = useContext(ReadOnlyMessageContext);
|
|
80185
80449
|
const readOnlyMessageKey = readOnlyFromAbove ? multiple ? `constraint.readonly.selection` : `constraint.readonly.choice` : `constraint.readonly.option`;
|
|
80186
80450
|
// Handed to the row as well as to the control: whichever of the two catches
|
|
80187
80451
|
// the press answers it, and they must not answer it differently.
|
|
80188
|
-
const readOnlyMessageResolved = props.readOnlyMessage ?? constraintI18n(readOnlyMessageKey, props);
|
|
80452
|
+
const readOnlyMessageResolved = props.readOnlyMessage ?? (readOnlyFromAbove ? readOnlyMessageFromAbove : undefined) ?? (readOnlyFromAbove === "network-policy" ? getNetworkPolicyReadOnlyMessage() : constraintI18n(readOnlyMessageKey, props));
|
|
80189
80453
|
const busyMessageResolved = props.busyMessage ?? (loading ? listItemBusyMessage(loading, props) : constraintI18n(multiple ? `constraint.busy.selection` : `constraint.busy.choice`, props));
|
|
80190
80454
|
const inputRef = useRef();
|
|
80191
80455
|
const inputType = multiple ? "checkbox" : "radio";
|
|
@@ -88978,6 +89242,7 @@ const css$r = /* css */`@layer navi {
|
|
|
88978
89242
|
.navi_picker:is([data-variant="button"], [data-variant="border"], [data-variant="discrete-border"]) {
|
|
88979
89243
|
--picker-padding-x-default: var(--navi-button-padding-x-default);
|
|
88980
89244
|
--picker-padding-y-default: var(--navi-button-padding-y-default);
|
|
89245
|
+
--picker-font-family: var(--navi-button-font-family, var(--navi-control-font-family, inherit));
|
|
88981
89246
|
--picker-align-x-default: center;
|
|
88982
89247
|
--picker-background-color: var(--navi-button-background-color);
|
|
88983
89248
|
--picker-border-color-readonly: color-mix(in srgb,
|
|
@@ -89277,8 +89542,9 @@ const css$r = /* css */`@layer navi {
|
|
|
89277
89542
|
--x-corner-top-right-radius: initial;
|
|
89278
89543
|
--x-corner-bottom-right-radius: initial;
|
|
89279
89544
|
--x-corner-bottom-left-radius: initial;
|
|
89280
|
-
font-
|
|
89545
|
+
font-weight: initial;
|
|
89281
89546
|
text-align: initial;
|
|
89547
|
+
font-size: 1rem;
|
|
89282
89548
|
display: contents;
|
|
89283
89549
|
}
|
|
89284
89550
|
|
|
@@ -89521,9 +89787,10 @@ const PickerButton = props => {
|
|
|
89521
89787
|
// The same chain useControlProps resolves (own prop first, then what the
|
|
89522
89788
|
// group above says), for the two things it does not carry: the popup content,
|
|
89523
89789
|
// which is read-only along with the picker, and the cursor, which stays a
|
|
89524
|
-
// pointer on a picker that still opens.
|
|
89790
|
+
// pointer on a picker that still opens. A hold of the network policy goes
|
|
89791
|
+
// with it: what the popup changes is what the picker would send.
|
|
89525
89792
|
const readOnlyFromAbove = useContext(ReadOnlyContext);
|
|
89526
|
-
const readOnlyResolved = readOnly || readOnlyFromAbove;
|
|
89793
|
+
const [readOnlyResolved, readOnlyMessageResolved] = readOnlyHandedDown(uiStateController, readOnly || readOnlyFromAbove);
|
|
89527
89794
|
// Read off the controller rather than worked out again: what makes a
|
|
89528
89795
|
// read-only picker open is settled once, where the gate reads it (see
|
|
89529
89796
|
// createControlInfo's readOnlyOpens). Needed here for the cursor.
|
|
@@ -89571,11 +89838,13 @@ const PickerButton = props => {
|
|
|
89571
89838
|
/* Read-only crosses into everything the picker is made of: what it really
|
|
89572
89839
|
holds is drawn by controls of their own — in the popup, and on the façade
|
|
89573
89840
|
where an application puts its own affordances — and each of them refuses
|
|
89574
|
-
in
|
|
89841
|
+
once told, in the picker's words when it gave some (readOnlyMessage),
|
|
89842
|
+
in its own otherwise. Said from the read-only state alone, never
|
|
89575
89843
|
from the busy one — an action running for a moment is not the same thing
|
|
89576
89844
|
as a value nobody may change. */
|
|
89577
|
-
jsx(
|
|
89578
|
-
|
|
89845
|
+
jsx(ReadOnlyProvider, {
|
|
89846
|
+
readOnly: readOnlyResolved,
|
|
89847
|
+
readOnlyMessage: readOnlyMessageResolved,
|
|
89579
89848
|
children: jsxs(Box
|
|
89580
89849
|
// A word in a sentence (variant="text") sits in a <p>, where a <div> is
|
|
89581
89850
|
// not allowed: phrasing content there, block content elsewhere.
|