@jsenv/navi 0.29.470 → 0.29.471
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 +576 -303
- package/dist/dev/jsenv_navi.js.map +19 -17
- package/dist/jsenv_navi.js +556 -303
- package/dist/jsenv_navi.js.map +19 -17
- package/docs/AI_INSTRUCTIONS.md +2 -2
- package/docs/popup_open.md +52 -0
- package/docs/testid.md +15 -2
- package/package.json +1 -1
package/dist/jsenv_navi.js
CHANGED
|
@@ -39055,8 +39055,29 @@ const resolveFirstChildControl = (el) => {
|
|
|
39055
39055
|
}
|
|
39056
39056
|
return startEl.querySelector("[navi-control-host]");
|
|
39057
39057
|
};
|
|
39058
|
+
// The element a popup command is about: the closest one keeping an open state.
|
|
39058
39059
|
const resolveClosestExpandable = (el) => {
|
|
39059
|
-
|
|
39060
|
+
const expandable = el.closest("[aria-expanded]");
|
|
39061
|
+
if (!expandable) {
|
|
39062
|
+
return null;
|
|
39063
|
+
}
|
|
39064
|
+
return expandableRepeatedBy(expandable) || expandable;
|
|
39065
|
+
};
|
|
39066
|
+
// A control's host repeats the aria-expanded of its root, beside its role, for
|
|
39067
|
+
// assistive tech to read (a picker's <input>, a combobox or a button). The root
|
|
39068
|
+
// is the expandable: the host is a leaf the walk lands on only when it is the
|
|
39069
|
+
// source itself, and it carries the control's own `command`/`commandfor`, which
|
|
39070
|
+
// a command resolved again from it (a close after a clear) would follow.
|
|
39071
|
+
const expandableRepeatedBy = (el) => {
|
|
39072
|
+
const controlRoot = findControlRoot(el);
|
|
39073
|
+
if (
|
|
39074
|
+
controlRoot &&
|
|
39075
|
+
controlRoot !== el &&
|
|
39076
|
+
controlRoot.hasAttribute("aria-expanded")
|
|
39077
|
+
) {
|
|
39078
|
+
return controlRoot;
|
|
39079
|
+
}
|
|
39080
|
+
return null;
|
|
39060
39081
|
};
|
|
39061
39082
|
// The surface a send is decided on: the expandable holding the CONTROL that
|
|
39062
39083
|
// sends, never one that control is itself. A picker's own root carries
|
|
@@ -39067,7 +39088,7 @@ const resolveClosestExpandable = (el) => {
|
|
|
39067
39088
|
const resolveExpandableAround = (source) => {
|
|
39068
39089
|
const sender = findControlRoot(source) || source;
|
|
39069
39090
|
const parent = sender.parentElement;
|
|
39070
|
-
return parent ? parent
|
|
39091
|
+
return parent ? resolveClosestExpandable(parent) : null;
|
|
39071
39092
|
};
|
|
39072
39093
|
// An element carrying navi-command-proxy-for="anchorId" stands in for that
|
|
39073
39094
|
// other element as the command's source when the source is forwarded to
|
|
@@ -39368,8 +39389,12 @@ const sendCommand = (source, event, { requester }) => {
|
|
|
39368
39389
|
// looking at, and a decision just taken there is a reason to leave it. The
|
|
39369
39390
|
// NEAREST surface answers, and only that one — a form inside a slide inside a
|
|
39370
39391
|
// dialog goes back a slide, it does not also close the dialog.
|
|
39371
|
-
// send inside expandable
|
|
39372
|
-
|
|
39392
|
+
// send inside expandable — the control itself when it sends from its host,
|
|
39393
|
+
// whose aria-expanded is its root's (see expandableRepeatedBy)
|
|
39394
|
+
if (
|
|
39395
|
+
target.getAttribute("aria-expanded") === "true" &&
|
|
39396
|
+
!expandableRepeatedBy(target)
|
|
39397
|
+
) {
|
|
39373
39398
|
return {
|
|
39374
39399
|
target,
|
|
39375
39400
|
implementation: () => {
|
|
@@ -39804,7 +39829,7 @@ const requestCloseUpward = (target, detail) => {
|
|
|
39804
39829
|
return false;
|
|
39805
39830
|
}
|
|
39806
39831
|
const parent = expandable.parentElement;
|
|
39807
|
-
expandable = parent ? parent
|
|
39832
|
+
expandable = parent ? resolveClosestExpandable(parent) : null;
|
|
39808
39833
|
}
|
|
39809
39834
|
return true;
|
|
39810
39835
|
};
|
|
@@ -58184,6 +58209,10 @@ const Label = props => {
|
|
|
58184
58209
|
requiredIndicator
|
|
58185
58210
|
} = props;
|
|
58186
58211
|
const controlId = useContext(ControlIdContext);
|
|
58212
|
+
// What a popup opened from the control is named by (see getTriggerLabelIds
|
|
58213
|
+
// in picker_custom.jsx): aria-labelledby can only point at an id.
|
|
58214
|
+
const idDefault = useId();
|
|
58215
|
+
props.id = props.id || `label_${idDefault}`;
|
|
58187
58216
|
const [disabled, setDisabled] = useState(false);
|
|
58188
58217
|
const [readOnly, setReadOnly] = useState(false);
|
|
58189
58218
|
const [required, setRequired] = useState(false);
|
|
@@ -67877,9 +67906,297 @@ const PopupClose = ({
|
|
|
67877
67906
|
});
|
|
67878
67907
|
};
|
|
67879
67908
|
|
|
67909
|
+
const SuccessSvg = () => {
|
|
67910
|
+
return jsx("svg", {
|
|
67911
|
+
viewBox: "0 0 16 16",
|
|
67912
|
+
fill: "currentColor",
|
|
67913
|
+
children: jsx("path", {
|
|
67914
|
+
d: "M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8Zm1.5 0a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Zm10.28-1.72-4.5 4.5a.75.75 0 0 1-1.06 0l-2-2a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l1.47 1.47 3.97-3.97a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042Z"
|
|
67915
|
+
})
|
|
67916
|
+
});
|
|
67917
|
+
};
|
|
67918
|
+
const ErrorSvg = () => {
|
|
67919
|
+
return jsx("svg", {
|
|
67920
|
+
viewBox: "0 0 16 16",
|
|
67921
|
+
fill: "currentColor",
|
|
67922
|
+
children: jsx("path", {
|
|
67923
|
+
d: "M4.47.22A.749.749 0 0 1 5 0h6c.199 0 .389.079.53.22l4.25 4.25c.141.14.22.331.22.53v6a.749.749 0 0 1-.22.53l-4.25 4.25A.749.749 0 0 1 11 16H5a.749.749 0 0 1-.53-.22L.22 11.53A.749.749 0 0 1 0 11V5c0-.199.079-.389.22-.53Zm.84 1.28L1.5 5.31v5.38l3.81 3.81h5.38l3.81-3.81V5.31L10.69 1.5ZM8 4a.75.75 0 0 1 .75.75v3.5a.75.75 0 0 1-1.5 0v-3.5A.75.75 0 0 1 8 4Zm0 8a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z"
|
|
67924
|
+
})
|
|
67925
|
+
});
|
|
67926
|
+
};
|
|
67927
|
+
const InfoSvg$1 = () => {
|
|
67928
|
+
return jsx("svg", {
|
|
67929
|
+
viewBox: "0 0 16 16",
|
|
67930
|
+
fill: "currentColor",
|
|
67931
|
+
children: jsx("path", {
|
|
67932
|
+
d: "M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8Zm8-6.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13ZM6.5 7.75A.75.75 0 0 1 7.25 7h1a.75.75 0 0 1 .75.75v2.75h.25a.75.75 0 0 1 0 1.5h-2a.75.75 0 0 1 0-1.5h.25v-2h-.25a.75.75 0 0 1-.75-.75ZM8 6a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z"
|
|
67933
|
+
})
|
|
67934
|
+
});
|
|
67935
|
+
};
|
|
67936
|
+
const WarningSvg = () => {
|
|
67937
|
+
return jsx("svg", {
|
|
67938
|
+
viewBox: "0 0 16 16",
|
|
67939
|
+
fill: "currentColor",
|
|
67940
|
+
children: jsx("path", {
|
|
67941
|
+
d: "M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"
|
|
67942
|
+
})
|
|
67943
|
+
});
|
|
67944
|
+
};
|
|
67945
|
+
|
|
67946
|
+
installImportMetaCssBuild(import.meta);
|
|
67947
|
+
const css$E = /* css */`@layer navi {
|
|
67948
|
+
.navi_message_box {
|
|
67949
|
+
--background-color-info: var(--navi-info-color-light);
|
|
67950
|
+
--color-info: var(--navi-info-color);
|
|
67951
|
+
--background-color-success: var(--navi-success-color-light);
|
|
67952
|
+
--color-success: var(--navi-success-color);
|
|
67953
|
+
--background-color-warning: var(--navi-warning-color-light);
|
|
67954
|
+
--color-warning: var(--navi-warning-color);
|
|
67955
|
+
--background-color-error: var(--navi-error-color-light);
|
|
67956
|
+
--color-error: var(--navi-error-color);
|
|
67957
|
+
}
|
|
67958
|
+
}
|
|
67959
|
+
|
|
67960
|
+
.navi_message_box {
|
|
67961
|
+
--x-message-background-color: var(--background-color-info);
|
|
67962
|
+
--x-message-color: var(--color-info);
|
|
67963
|
+
background-color: var(--x-message-background-color);
|
|
67964
|
+
|
|
67965
|
+
& > .navi_icon {
|
|
67966
|
+
flex-shrink: 0;
|
|
67967
|
+
}
|
|
67968
|
+
}
|
|
67969
|
+
|
|
67970
|
+
.navi_message_box[data-status-info] {
|
|
67971
|
+
--x-message-background-color: var(--background-color-info);
|
|
67972
|
+
--x-message-color: var(--color-info);
|
|
67973
|
+
}
|
|
67974
|
+
|
|
67975
|
+
.navi_message_box[data-status-success] {
|
|
67976
|
+
--x-message-background-color: var(--background-color-success);
|
|
67977
|
+
--x-message-color: var(--color-success);
|
|
67978
|
+
}
|
|
67979
|
+
|
|
67980
|
+
.navi_message_box[data-status-warning] {
|
|
67981
|
+
--x-message-background-color: var(--background-color-warning);
|
|
67982
|
+
--x-message-color: var(--color-warning);
|
|
67983
|
+
}
|
|
67984
|
+
|
|
67985
|
+
.navi_message_box[data-status-error] {
|
|
67986
|
+
--x-message-background-color: var(--background-color-error);
|
|
67987
|
+
--x-message-color: var(--color-error);
|
|
67988
|
+
}
|
|
67989
|
+
|
|
67990
|
+
.navi_message_box[data-left-stripe] {
|
|
67991
|
+
border-left: 6px solid var(--x-message-color);
|
|
67992
|
+
border-top-left-radius: 6px;
|
|
67993
|
+
border-bottom-left-radius: 6px;
|
|
67994
|
+
}
|
|
67995
|
+
`;
|
|
67996
|
+
const MessageBox = ({
|
|
67997
|
+
status = "info",
|
|
67998
|
+
padding = "sm",
|
|
67999
|
+
icon,
|
|
68000
|
+
leftStripe,
|
|
68001
|
+
children,
|
|
68002
|
+
onClose,
|
|
68003
|
+
...rest
|
|
68004
|
+
}) => {
|
|
68005
|
+
import.meta.css = [css$E, "@jsenv/navi/src/text/message_box.jsx"];
|
|
68006
|
+
const [hasTitleChild, setHasTitleChild] = useState(false);
|
|
68007
|
+
const innerLeftStripe = leftStripe === undefined ? hasTitleChild : leftStripe;
|
|
68008
|
+
if (icon === true) {
|
|
68009
|
+
icon = status === "info" ? jsx(InfoSvg$1, {}) : status === "success" ? jsx(SuccessSvg, {}) : status === "warning" ? jsx(WarningSvg, {}) : status === "error" ? jsx(ErrorSvg, {}) : null;
|
|
68010
|
+
} else if (typeof icon === "function") {
|
|
68011
|
+
const Comp = icon;
|
|
68012
|
+
icon = jsx(Comp, {});
|
|
68013
|
+
}
|
|
68014
|
+
return jsx(Box, {
|
|
68015
|
+
as: "div",
|
|
68016
|
+
role: status === "info" ? "status" : "alert",
|
|
68017
|
+
"data-left-stripe": innerLeftStripe ? "" : undefined,
|
|
68018
|
+
inline: true,
|
|
68019
|
+
column: true,
|
|
68020
|
+
alignY: "center",
|
|
68021
|
+
spacing: "s",
|
|
68022
|
+
...rest,
|
|
68023
|
+
className: withPropsClassName("navi_message_box", rest.className),
|
|
68024
|
+
padding: padding,
|
|
68025
|
+
pseudoClasses: MessageBoxPseudoClasses,
|
|
68026
|
+
basePseudoState: {
|
|
68027
|
+
":-navi-status-info": status === "info",
|
|
68028
|
+
":-navi-status-success": status === "success",
|
|
68029
|
+
":-navi-status-warning": status === "warning",
|
|
68030
|
+
":-navi-status-error": status === "error"
|
|
68031
|
+
},
|
|
68032
|
+
children: jsx(MessageBoxStatusContext.Provider, {
|
|
68033
|
+
value: status,
|
|
68034
|
+
children: jsxs(MessageBoxReportTitleChildContext.Provider, {
|
|
68035
|
+
value: setHasTitleChild,
|
|
68036
|
+
children: [icon && jsx(Icon, {
|
|
68037
|
+
color: "var(--x-message-color)",
|
|
68038
|
+
height: "1lh",
|
|
68039
|
+
maxHeight: "auto",
|
|
68040
|
+
selfAlignY: "start",
|
|
68041
|
+
aspectRatio: "auto",
|
|
68042
|
+
children: icon
|
|
68043
|
+
}), jsx(Text, {
|
|
68044
|
+
children: children
|
|
68045
|
+
}), onClose &&
|
|
68046
|
+
// A column as tall as the first line of the message, pinned to the
|
|
68047
|
+
// top, the button centered in it: the close button stays level
|
|
68048
|
+
// with the first line however many lines the message takes (same
|
|
68049
|
+
// layout as Callout).
|
|
68050
|
+
jsx(Box, {
|
|
68051
|
+
flex: true,
|
|
68052
|
+
alignY: "center",
|
|
68053
|
+
height: "1lh",
|
|
68054
|
+
selfAlignY: "start",
|
|
68055
|
+
shrink: false,
|
|
68056
|
+
children: jsx(Button, {
|
|
68057
|
+
action: onClose,
|
|
68058
|
+
icon: true,
|
|
68059
|
+
border: "none",
|
|
68060
|
+
style: {
|
|
68061
|
+
":hover": {
|
|
68062
|
+
backgroundColor: "rgba(0, 0, 0, 0.1)"
|
|
68063
|
+
}
|
|
68064
|
+
},
|
|
68065
|
+
children: jsx(Icon, {
|
|
68066
|
+
children: jsx(CloseSvg, {})
|
|
68067
|
+
})
|
|
68068
|
+
})
|
|
68069
|
+
})]
|
|
68070
|
+
})
|
|
68071
|
+
})
|
|
68072
|
+
});
|
|
68073
|
+
};
|
|
68074
|
+
const MessageBoxPseudoClasses = [":-navi-status-info", ":-navi-status-success", ":-navi-status-warning", ":-navi-status-error"];
|
|
68075
|
+
const MessageBoxStatusContext = createContext();
|
|
68076
|
+
const MessageBoxReportTitleChildContext = createContext();
|
|
68077
|
+
|
|
68078
|
+
installImportMetaCssBuild(import.meta);
|
|
68079
|
+
const css$D = /* css */`.navi_message_box {
|
|
68080
|
+
& .navi_title {
|
|
68081
|
+
margin-top: 0;
|
|
68082
|
+
margin-bottom: var(--navi-s);
|
|
68083
|
+
color: var(--x-message-color);
|
|
68084
|
+
}
|
|
68085
|
+
}
|
|
68086
|
+
`;
|
|
68087
|
+
const Title = props => {
|
|
68088
|
+
import.meta.css = [css$D, "@jsenv/navi/src/text/title.jsx"];
|
|
68089
|
+
const messageBoxStatus = useContext(MessageBoxStatusContext);
|
|
68090
|
+
const innerAs = props.as || (messageBoxStatus ? "h4" : "h1");
|
|
68091
|
+
const titleLevel = parseInt(innerAs.slice(1));
|
|
68092
|
+
const reportTitleToMessageBox = useContext(MessageBoxReportTitleChildContext);
|
|
68093
|
+
reportTitleToMessageBox?.(true);
|
|
68094
|
+
return jsx(TitleLevelContext.Provider, {
|
|
68095
|
+
value: titleLevel,
|
|
68096
|
+
children: jsx(Text, {
|
|
68097
|
+
bold: true,
|
|
68098
|
+
className: withPropsClassName("navi_title"),
|
|
68099
|
+
as: messageBoxStatus ? "h4" : "h1",
|
|
68100
|
+
...props,
|
|
68101
|
+
pseudoClasses: TitlePseudoClasses,
|
|
68102
|
+
children: props.children
|
|
68103
|
+
})
|
|
68104
|
+
});
|
|
68105
|
+
};
|
|
68106
|
+
const TitleLevelContext = createContext();
|
|
68107
|
+
const useTitleLevel = () => {
|
|
68108
|
+
return useContext(TitleLevelContext);
|
|
68109
|
+
};
|
|
68110
|
+
const TitlePseudoClasses = [":hover"];
|
|
68111
|
+
|
|
68112
|
+
/**
|
|
68113
|
+
* What a popup is called, decided by Dialog and Popover alike: the name the
|
|
68114
|
+
* caller writes on it (aria-label/aria-labelledby), else the title it holds
|
|
68115
|
+
* (`<Popup.Title>`), else the name of what opened it (`openerAriaLabelledBy` /
|
|
68116
|
+
* `openerAriaLabel`, which a Picker fills with its trigger's). A popup no one
|
|
68117
|
+
* names is announced as "dialog" and nothing else.
|
|
68118
|
+
*
|
|
68119
|
+
* The title tells the popup it exists rather than the popup looking for it:
|
|
68120
|
+
* the content is built after the popup and thrown away before it (see
|
|
68121
|
+
* popup_content_mount.js), and a title may sit anywhere in it — a header, a
|
|
68122
|
+
* step of a form — so only the title knows when it is there.
|
|
68123
|
+
*/
|
|
68124
|
+
|
|
68125
|
+
const PopupTitleContext = createContext(null);
|
|
68126
|
+
|
|
68127
|
+
/**
|
|
68128
|
+
* The title of the popup it sits in — reached as `<Popup.Title>`,
|
|
68129
|
+
* `<Dialog.Title>` or `<Popover.Title>`. A heading (`h2` unless `as` says
|
|
68130
|
+
* otherwise) that is also the popup's accessible name: a screen reader
|
|
68131
|
+
* announces the popup by it, and `getByRole("dialog", { name })` finds it.
|
|
68132
|
+
* An `aria-label`/`aria-labelledby` written on the popup itself wins over it.
|
|
68133
|
+
*
|
|
68134
|
+
* @type {import("ignore:preact").FunctionComponent<{
|
|
68135
|
+
* as?: "h1" | "h2" | "h3" | "h4" | "h5" | "h6",
|
|
68136
|
+
* id?: string,
|
|
68137
|
+
* children?: import("ignore:preact").ComponentChildren,
|
|
68138
|
+
* } & Record<string, any>>}
|
|
68139
|
+
*/
|
|
68140
|
+
const PopupTitle = props => {
|
|
68141
|
+
const registerTitle = useContext(PopupTitleContext);
|
|
68142
|
+
const idDefault = useId();
|
|
68143
|
+
const id = props.id || `popup_title_${idDefault}`;
|
|
68144
|
+
useLayoutEffect(() => {
|
|
68145
|
+
if (!registerTitle) {
|
|
68146
|
+
return undefined;
|
|
68147
|
+
}
|
|
68148
|
+
return registerTitle(id);
|
|
68149
|
+
}, [registerTitle, id]);
|
|
68150
|
+
return jsx(Title, {
|
|
68151
|
+
as: "h2",
|
|
68152
|
+
...props,
|
|
68153
|
+
id: id
|
|
68154
|
+
});
|
|
68155
|
+
};
|
|
68156
|
+
|
|
68157
|
+
/**
|
|
68158
|
+
* The name props of a popup element, and what its titles register with —
|
|
68159
|
+
* handed to its children through PopupTitleContext.
|
|
68160
|
+
*/
|
|
68161
|
+
const usePopupName = ({
|
|
68162
|
+
ariaLabel,
|
|
68163
|
+
ariaLabelledBy,
|
|
68164
|
+
openerAriaLabel,
|
|
68165
|
+
openerAriaLabelledBy
|
|
68166
|
+
}) => {
|
|
68167
|
+
// Several titles is a content of the caller's own making (two steps both
|
|
68168
|
+
// mounted): the first one registered names the popup.
|
|
68169
|
+
const [titleIds, setTitleIds] = useState(NO_TITLE);
|
|
68170
|
+
const registerTitle = useMemo(() => {
|
|
68171
|
+
return id => {
|
|
68172
|
+
setTitleIds(ids => [...ids, id]);
|
|
68173
|
+
return () => {
|
|
68174
|
+
setTitleIds(ids => ids.filter(each => each !== id));
|
|
68175
|
+
};
|
|
68176
|
+
};
|
|
68177
|
+
}, []);
|
|
68178
|
+
let labelledBy;
|
|
68179
|
+
let label;
|
|
68180
|
+
if (ariaLabelledBy !== undefined || ariaLabel !== undefined) {
|
|
68181
|
+
labelledBy = ariaLabelledBy;
|
|
68182
|
+
label = ariaLabel;
|
|
68183
|
+
} else if (titleIds.length > 0) {
|
|
68184
|
+
labelledBy = titleIds[0];
|
|
68185
|
+
} else if (openerAriaLabelledBy !== undefined) {
|
|
68186
|
+
labelledBy = openerAriaLabelledBy;
|
|
68187
|
+
} else {
|
|
68188
|
+
label = openerAriaLabel;
|
|
68189
|
+
}
|
|
68190
|
+
return [{
|
|
68191
|
+
"aria-labelledby": labelledBy,
|
|
68192
|
+
"aria-label": label
|
|
68193
|
+
}, registerTitle];
|
|
68194
|
+
};
|
|
68195
|
+
const NO_TITLE = [];
|
|
68196
|
+
|
|
67880
68197
|
installImportMetaCssBuild(import.meta);
|
|
67881
68198
|
let openLocalDialogCount = 0;
|
|
67882
|
-
const css$
|
|
68199
|
+
const css$C = /* css */`
|
|
67883
68200
|
/* jsenv-css-opaque: popupCss overlaps these rules, own sheet = cascade
|
|
67884
68201
|
order depending on which popup renders first. */
|
|
67885
68202
|
|
|
@@ -68948,10 +69265,14 @@ const css$E = /* css */`
|
|
|
68948
69265
|
* under `"while-opened"`, only a press on what opens the popup does (a
|
|
68949
69266
|
* `--navi-open` button, a picker's trigger), never with an `onOpen`, and a
|
|
68950
69267
|
* press that does not open the popup throws it away.
|
|
69268
|
+
* @param {string} [props.openerAriaLabelledBy] - The id(s) naming what opened
|
|
69269
|
+
* the dialog: its accessible name when neither `aria-label`/`aria-labelledby`
|
|
69270
|
+
* nor a `<Dialog.Title>` names it. A Picker passes its trigger's.
|
|
69271
|
+
* @param {string} [props.openerAriaLabel] - The same, as a string.
|
|
68951
69272
|
* @param {import("ignore:preact").ComponentChildren} props.children
|
|
68952
69273
|
*/
|
|
68953
69274
|
const Dialog = props => {
|
|
68954
|
-
import.meta.css = [css$
|
|
69275
|
+
import.meta.css = [css$C, "@jsenv/navi/src/layout/dialog.jsx"];
|
|
68955
69276
|
if (props.openController) {
|
|
68956
69277
|
return jsx(ControlledDialog, {
|
|
68957
69278
|
...props
|
|
@@ -69325,6 +69646,9 @@ const useDialogProps = props => {
|
|
|
69325
69646
|
onOpen,
|
|
69326
69647
|
children: childrenProp,
|
|
69327
69648
|
mount,
|
|
69649
|
+
// Read by usePopupName below, never written on the element.
|
|
69650
|
+
openerAriaLabel,
|
|
69651
|
+
openerAriaLabelledBy,
|
|
69328
69652
|
...rest
|
|
69329
69653
|
} = props;
|
|
69330
69654
|
// Assigned on every render, like openEffect below, so it always closes over
|
|
@@ -69335,7 +69659,16 @@ const useDialogProps = props => {
|
|
|
69335
69659
|
mount,
|
|
69336
69660
|
anchor
|
|
69337
69661
|
});
|
|
69338
|
-
const
|
|
69662
|
+
const [nameProps, registerTitle] = usePopupName({
|
|
69663
|
+
ariaLabel: rest["aria-label"],
|
|
69664
|
+
ariaLabelledBy: rest["aria-labelledby"],
|
|
69665
|
+
openerAriaLabel,
|
|
69666
|
+
openerAriaLabelledBy
|
|
69667
|
+
});
|
|
69668
|
+
const children = contentMounted ? jsx(PopupTitleContext.Provider, {
|
|
69669
|
+
value: registerTitle,
|
|
69670
|
+
children: childrenProp
|
|
69671
|
+
}) : null;
|
|
69339
69672
|
// Where it is placed, and whether there is a wall — the two questions that
|
|
69340
69673
|
// pick the show call (see this file's top comment).
|
|
69341
69674
|
const isTopLayer = layer === "top";
|
|
@@ -70125,6 +70458,7 @@ const useDialogProps = props => {
|
|
|
70125
70458
|
"backdropFilter": backdrop ? backdropFilter : undefined,
|
|
70126
70459
|
"styleCSSVars": DIALOG_STYLE_CSS_VARS,
|
|
70127
70460
|
...rest,
|
|
70461
|
+
...nameProps,
|
|
70128
70462
|
...autoFocusProps,
|
|
70129
70463
|
"as": "dialog",
|
|
70130
70464
|
ref,
|
|
@@ -70298,10 +70632,11 @@ const DIALOG_STYLE_CSS_VARS = {
|
|
|
70298
70632
|
maxHeight: "--dialog-max-height"
|
|
70299
70633
|
};
|
|
70300
70634
|
Dialog.Close = PopupClose;
|
|
70635
|
+
Dialog.Title = PopupTitle;
|
|
70301
70636
|
|
|
70302
70637
|
installImportMetaCssBuild(import.meta);
|
|
70303
70638
|
let openLocalPopoverCount = 0;
|
|
70304
|
-
const css$
|
|
70639
|
+
const css$B = /* css */`
|
|
70305
70640
|
/* jsenv-css-opaque: popupCss overlaps these rules, own sheet = cascade
|
|
70306
70641
|
order depending on which popup renders first. */
|
|
70307
70642
|
|
|
@@ -70900,10 +71235,17 @@ const css$D = /* css */`
|
|
|
70900
71235
|
* under `"while-opened"`, only a press on what opens the popup does (a
|
|
70901
71236
|
* `--navi-open` button, a picker's trigger), never with an `onOpen`, and a
|
|
70902
71237
|
* press that does not open the popup throws it away.
|
|
71238
|
+
* @param {string} [props.openerAriaLabelledBy] - The id(s) naming what opened
|
|
71239
|
+
* the popover: its accessible name when neither `aria-label`/`aria-labelledby`
|
|
71240
|
+
* nor a `<Popover.Title>` names it. A Picker passes its trigger's.
|
|
71241
|
+
* @param {string} [props.openerAriaLabel] - The same, as a string. A popover
|
|
71242
|
+
* something names — these, `aria-label`/`aria-labelledby`, a
|
|
71243
|
+
* `<Popover.Title>` — is a `dialog`, unless given another `role`: a name on
|
|
71244
|
+
* an element with no role is read by nobody.
|
|
70903
71245
|
* @param {import("ignore:preact").ComponentChildren} props.children
|
|
70904
71246
|
*/
|
|
70905
71247
|
const Popover = props => {
|
|
70906
|
-
import.meta.css = [css$
|
|
71248
|
+
import.meta.css = [css$B, "@jsenv/navi/src/layout/popover.jsx"];
|
|
70907
71249
|
if (props.openController) {
|
|
70908
71250
|
return jsx(ControlledPopover, {
|
|
70909
71251
|
...props
|
|
@@ -71140,6 +71482,9 @@ const usePopoverProps = props => {
|
|
|
71140
71482
|
onOpen,
|
|
71141
71483
|
children: childrenProp,
|
|
71142
71484
|
mount,
|
|
71485
|
+
// Read by usePopupName below, never written on the element.
|
|
71486
|
+
openerAriaLabel,
|
|
71487
|
+
openerAriaLabelledBy,
|
|
71143
71488
|
...rest
|
|
71144
71489
|
} = props;
|
|
71145
71490
|
// Assigned on every render, like openEffect below, so it always closes over
|
|
@@ -71150,7 +71495,16 @@ const usePopoverProps = props => {
|
|
|
71150
71495
|
mount,
|
|
71151
71496
|
anchor
|
|
71152
71497
|
});
|
|
71153
|
-
const
|
|
71498
|
+
const [nameProps, registerTitle] = usePopupName({
|
|
71499
|
+
ariaLabel: rest["aria-label"],
|
|
71500
|
+
ariaLabelledBy: rest["aria-labelledby"],
|
|
71501
|
+
openerAriaLabel,
|
|
71502
|
+
openerAriaLabelledBy
|
|
71503
|
+
});
|
|
71504
|
+
const children = contentMounted ? jsx(PopupTitleContext.Provider, {
|
|
71505
|
+
value: registerTitle,
|
|
71506
|
+
children: childrenProp
|
|
71507
|
+
}) : null;
|
|
71154
71508
|
const isTopLayer = layer === "top";
|
|
71155
71509
|
const ref = props.ref;
|
|
71156
71510
|
const backdropRef = useRef();
|
|
@@ -71955,6 +72309,10 @@ const usePopoverProps = props => {
|
|
|
71955
72309
|
"navi-hidden": openController.openedInDom ? undefined : "",
|
|
71956
72310
|
"styleCSSVars": POPUP_STYLE_CSS_VARS,
|
|
71957
72311
|
...rest,
|
|
72312
|
+
...nameProps,
|
|
72313
|
+
// A <div> has no role, and a name on an element without one is read by
|
|
72314
|
+
// nobody: a popover something names is a dialog, unless told what else.
|
|
72315
|
+
"role": rest.role ?? (nameProps["aria-labelledby"] === undefined && nameProps["aria-label"] === undefined ? undefined : "dialog"),
|
|
71958
72316
|
...autoFocusProps,
|
|
71959
72317
|
ref,
|
|
71960
72318
|
// Not a control, but still something the rest of navi has to be able to
|
|
@@ -72070,9 +72428,10 @@ const resolvePositionAreaAndAnimationKind = ({
|
|
|
72070
72428
|
};
|
|
72071
72429
|
};
|
|
72072
72430
|
Popover.Close = PopupClose;
|
|
72431
|
+
Popover.Title = PopupTitle;
|
|
72073
72432
|
|
|
72074
72433
|
installImportMetaCssBuild(import.meta);
|
|
72075
|
-
const css$
|
|
72434
|
+
const css$A = /* css */`@layer navi {
|
|
72076
72435
|
.navi_popup {
|
|
72077
72436
|
--popup-border-radius: var(--navi-popup-border-radius);
|
|
72078
72437
|
--popup-border-width: 1px;
|
|
@@ -72213,6 +72572,10 @@ const css$C = /* css */`@layer navi {
|
|
|
72213
72572
|
* @param {string} [props.className] - Merged with the shared
|
|
72214
72573
|
* `"navi_popup"` class (see this file's own CSS) rather than replacing
|
|
72215
72574
|
* it.
|
|
72575
|
+
* @param {string} [props.openerAriaLabelledBy] - Forwarded as-is: the name the
|
|
72576
|
+
* popup takes when neither `aria-label`/`aria-labelledby` nor a
|
|
72577
|
+
* `<Popup.Title>` in `children` names it (see `Dialog`/`Popover`).
|
|
72578
|
+
* @param {string} [props.openerAriaLabel] - Forwarded as-is, same.
|
|
72216
72579
|
* @param {"always"|"idle"|"from-first-open"|"while-opened"} [props.mount] - When
|
|
72217
72580
|
* `children` are built and thrown away (see popup_content_mount.js).
|
|
72218
72581
|
* `"from-first-open"` (the default) builds them on the first open and keeps
|
|
@@ -72228,7 +72591,7 @@ const css$C = /* css */`@layer navi {
|
|
|
72228
72591
|
* @param {import("ignore:preact").ComponentChildren} props.children
|
|
72229
72592
|
*/
|
|
72230
72593
|
const Popup = props => {
|
|
72231
|
-
import.meta.css = [css$
|
|
72594
|
+
import.meta.css = [css$A, "@jsenv/navi/src/layout/popup.jsx"];
|
|
72232
72595
|
const {
|
|
72233
72596
|
mode: modeProp,
|
|
72234
72597
|
maxWidth,
|
|
@@ -72311,6 +72674,7 @@ const Popup = props => {
|
|
|
72311
72674
|
});
|
|
72312
72675
|
};
|
|
72313
72676
|
Popup.Close = PopupClose;
|
|
72677
|
+
Popup.Title = PopupTitle;
|
|
72314
72678
|
|
|
72315
72679
|
// What Dialog's own animation values mean to a popover, which has no lift
|
|
72316
72680
|
// (see the `animation` doc above).
|
|
@@ -72359,6 +72723,54 @@ const pickerUIIsNaviOwn = ui => {
|
|
|
72359
72723
|
return Boolean(ui) && typeof ui === "object" && Boolean(ui.type?.isPickerOwnUI);
|
|
72360
72724
|
};
|
|
72361
72725
|
|
|
72726
|
+
/*
|
|
72727
|
+
* What the picker really is, said on the element that holds the name and takes
|
|
72728
|
+
* the focus (the host input in picker.jsx), which is both what a screen reader
|
|
72729
|
+
* announces and what getByRole(role, { name }) finds:
|
|
72730
|
+
* - a picker that picks nothing is a door — its popup is a question
|
|
72731
|
+
* (type="confirm") or something to read (mode="callout", which says it for
|
|
72732
|
+
* itself) — and a door is pressed: "button";
|
|
72733
|
+
* - a picker holding a value and opening a popup of navi's is a select-only
|
|
72734
|
+
* combobox: it shows a value the user does not type, and opens what changes
|
|
72735
|
+
* it. A textbox could not say the rest — aria-expanded is not allowed on one,
|
|
72736
|
+
* so "open" and "closed" would never be announced;
|
|
72737
|
+
* - a picker showing the browser's own picker (no popup of navi's) stays the
|
|
72738
|
+
* textbox its <input> is.
|
|
72739
|
+
*/
|
|
72740
|
+
const getPickerHostRole = props => {
|
|
72741
|
+
if (props.role !== undefined) {
|
|
72742
|
+
return props.role;
|
|
72743
|
+
}
|
|
72744
|
+
if (props.picksNothing) {
|
|
72745
|
+
return "button";
|
|
72746
|
+
}
|
|
72747
|
+
if (props["aria-haspopup"] !== undefined) {
|
|
72748
|
+
return "combobox";
|
|
72749
|
+
}
|
|
72750
|
+
return undefined;
|
|
72751
|
+
};
|
|
72752
|
+
|
|
72753
|
+
/*
|
|
72754
|
+
* And what that button is called, when the caller wrote it as a drawing rather
|
|
72755
|
+
* than as a word: a door draws no value, so what sits in its value slot IS its
|
|
72756
|
+
* label — the `ui` a caller gave it, or its placeholder. Undefined the moment
|
|
72757
|
+
* the caller names it themselves (aria-label/aria-labelledby), which is the
|
|
72758
|
+
* only way to name a door drawn as an icon. Read by the popup too: what the
|
|
72759
|
+
* user pressed is a fair name for what it opened.
|
|
72760
|
+
*/
|
|
72761
|
+
const getPickerHostLabelId = (id, props) => {
|
|
72762
|
+
if (getPickerHostRole(props) !== "button") {
|
|
72763
|
+
return undefined;
|
|
72764
|
+
}
|
|
72765
|
+
if (props["aria-label"] !== undefined || props["aria-labelledby"] !== undefined) {
|
|
72766
|
+
return undefined;
|
|
72767
|
+
}
|
|
72768
|
+
if (props.variant === "headless" || props.ui === "default") {
|
|
72769
|
+
return undefined;
|
|
72770
|
+
}
|
|
72771
|
+
return `${id}_picker_label`;
|
|
72772
|
+
};
|
|
72773
|
+
|
|
72362
72774
|
/**
|
|
72363
72775
|
* What the picker holds, read from inside its `ui` — for a drawing given as
|
|
72364
72776
|
* an element (`ui={<MyCard game={game} />}`), which the picker cannot hand
|
|
@@ -72388,7 +72800,7 @@ const usePickerState = () => {
|
|
|
72388
72800
|
};
|
|
72389
72801
|
|
|
72390
72802
|
installImportMetaCssBuild(import.meta);
|
|
72391
|
-
const css$
|
|
72803
|
+
const css$z = /* css */`.navi_picker_callout_dock > [data-picker-content] {
|
|
72392
72804
|
display: none;
|
|
72393
72805
|
}
|
|
72394
72806
|
|
|
@@ -72417,7 +72829,7 @@ const css$B = /* css */`.navi_picker_callout_dock > [data-picker-content] {
|
|
|
72417
72829
|
}
|
|
72418
72830
|
}
|
|
72419
72831
|
|
|
72420
|
-
.navi_picker[
|
|
72832
|
+
.navi_picker[navi-popover-mode="overlay"][aria-expanded="true"] {
|
|
72421
72833
|
border-color: #0000;
|
|
72422
72834
|
}
|
|
72423
72835
|
|
|
@@ -72445,7 +72857,7 @@ const css$B = /* css */`.navi_picker_callout_dock > [data-picker-content] {
|
|
|
72445
72857
|
}
|
|
72446
72858
|
`;
|
|
72447
72859
|
const PickerCustomResolver = props => {
|
|
72448
|
-
import.meta.css = [css$
|
|
72860
|
+
import.meta.css = [css$z, "@jsenv/navi/src/control/picker/picker_custom.jsx"];
|
|
72449
72861
|
if (props.children === undefined) {
|
|
72450
72862
|
return renderResolver(PickerNative, props);
|
|
72451
72863
|
}
|
|
@@ -73254,6 +73666,24 @@ const isPressDisputedByHold = pickerEl => Boolean(pickerEl?.parentElement?.close
|
|
|
73254
73666
|
const getPickerInput = pickerEl => {
|
|
73255
73667
|
return pickerEl.querySelector(".navi_picker_input");
|
|
73256
73668
|
};
|
|
73669
|
+
|
|
73670
|
+
// The <label>s naming a picker's trigger, by id. Read off the document: it is
|
|
73671
|
+
// the one place a label[for] and its control meet (navi's own Label carries an
|
|
73672
|
+
// id for this). A label wrapping the picker is left out — it holds the trigger
|
|
73673
|
+
// and the popup with it, and the popup would be named after its own content.
|
|
73674
|
+
const getTriggerLabelIds = pickerEl => {
|
|
73675
|
+
const labels = pickerEl && getPickerInput(pickerEl)?.labels;
|
|
73676
|
+
if (!labels) {
|
|
73677
|
+
return undefined;
|
|
73678
|
+
}
|
|
73679
|
+
const ids = [];
|
|
73680
|
+
for (const label of labels) {
|
|
73681
|
+
if (label.id && !label.contains(pickerEl)) {
|
|
73682
|
+
ids.push(label.id);
|
|
73683
|
+
}
|
|
73684
|
+
}
|
|
73685
|
+
return ids.length === 0 ? undefined : ids.join(" ");
|
|
73686
|
+
};
|
|
73257
73687
|
const getPickerInputUIState = pickerEl => {
|
|
73258
73688
|
const pickerInput = getPickerInput(pickerEl);
|
|
73259
73689
|
return getUIStateFromElement(pickerInput);
|
|
@@ -73276,6 +73706,11 @@ const PickerContentInsidePopup = props => {
|
|
|
73276
73706
|
// Same reason: a `data-testid` on the picker names the trigger (see
|
|
73277
73707
|
// docs/testid.md) — this one names the popup.
|
|
73278
73708
|
popupTestId,
|
|
73709
|
+
// Same again for the accessible name: aria-label/aria-labelledby on the
|
|
73710
|
+
// picker name the trigger (see control_context.js), these the popup.
|
|
73711
|
+
popupAriaLabel,
|
|
73712
|
+
popupAriaLabelledBy,
|
|
73713
|
+
popupAriaDescribedBy,
|
|
73279
73714
|
positionArea,
|
|
73280
73715
|
popoverMode = "nearby",
|
|
73281
73716
|
popoverSpacing = popoverMode === "nearby" ? 5 : 0,
|
|
@@ -73337,8 +73772,25 @@ const PickerContentInsidePopup = props => {
|
|
|
73337
73772
|
} = props;
|
|
73338
73773
|
const isPopover = mode === "popover";
|
|
73339
73774
|
const isCallout = mode === "callout";
|
|
73340
|
-
|
|
73341
|
-
|
|
73775
|
+
// The trigger's name, in the order the browser reads it, for the popup to
|
|
73776
|
+
// take when neither the caller nor a <Popup.Title> names it: "Report this
|
|
73777
|
+
// book" is a fair name for the sheet it opens, "Start date" for a calendar.
|
|
73778
|
+
let openerAriaLabelledBy = rest["aria-labelledby"] ?? getPickerHostLabelId(props.id, props);
|
|
73779
|
+
let openerAriaLabel;
|
|
73780
|
+
if (openerAriaLabelledBy === undefined) {
|
|
73781
|
+
openerAriaLabel = rest["aria-label"];
|
|
73782
|
+
// Read only while open: the labels are a question for the document, and
|
|
73783
|
+
// a closed popup has nobody to announce it.
|
|
73784
|
+
if (openerAriaLabel === undefined && rest["aria-expanded"]) {
|
|
73785
|
+
openerAriaLabelledBy = getTriggerLabelIds(props.ref.current);
|
|
73786
|
+
}
|
|
73787
|
+
}
|
|
73788
|
+
return jsx(Next
|
|
73789
|
+
// A dialog in either mode: what a picker opens is content of the
|
|
73790
|
+
// caller's, never a listbox (a selectable List is a group of radios or
|
|
73791
|
+
// checkboxes). The popover says so with its role, below.
|
|
73792
|
+
, {
|
|
73793
|
+
"aria-haspopup": "dialog",
|
|
73342
73794
|
"navi-popover-mode": isPopover ? popoverMode : undefined,
|
|
73343
73795
|
...rest,
|
|
73344
73796
|
// On popupProps already (see the picker's popup assembly); they mean
|
|
@@ -73383,11 +73835,23 @@ const PickerContentInsidePopup = props => {
|
|
|
73383
73835
|
pressOutside: pressOutside,
|
|
73384
73836
|
children: jsx(PopupModeContext.Provider, {
|
|
73385
73837
|
value: mode,
|
|
73386
|
-
children:
|
|
73838
|
+
children: jsx(PopupTitleContext.Provider, {
|
|
73839
|
+
value: null,
|
|
73840
|
+
children: children
|
|
73841
|
+
})
|
|
73387
73842
|
})
|
|
73388
73843
|
}) : jsx(Popup, {
|
|
73389
73844
|
...popupProps,
|
|
73390
73845
|
"data-testid": popupTestId
|
|
73846
|
+
// What the trigger's aria-haspopup announces; a <dialog> says it
|
|
73847
|
+
// for itself.
|
|
73848
|
+
,
|
|
73849
|
+
role: isPopover ? "dialog" : undefined,
|
|
73850
|
+
"aria-label": popupAriaLabel,
|
|
73851
|
+
"aria-labelledby": popupAriaLabelledBy,
|
|
73852
|
+
"aria-describedby": popupAriaDescribedBy,
|
|
73853
|
+
openerAriaLabel: openerAriaLabel,
|
|
73854
|
+
openerAriaLabelledBy: openerAriaLabelledBy
|
|
73391
73855
|
// What the CSS above keys on: this picker's own popup, and no other
|
|
73392
73856
|
// popup below the picker.
|
|
73393
73857
|
,
|
|
@@ -73657,7 +74121,7 @@ const showNativePicker = (pickerInput, event) => {
|
|
|
73657
74121
|
};
|
|
73658
74122
|
|
|
73659
74123
|
installImportMetaCssBuild(import.meta);
|
|
73660
|
-
const css$
|
|
74124
|
+
const css$y = /* css */`.navi_picker_confirm_body {
|
|
73661
74125
|
min-width: 180px;
|
|
73662
74126
|
max-width: 320px;
|
|
73663
74127
|
padding: var(--navi-m);
|
|
@@ -73673,7 +74137,7 @@ const css$A = /* css */`.navi_picker_confirm_body {
|
|
|
73673
74137
|
}
|
|
73674
74138
|
`;
|
|
73675
74139
|
const PickerConfirmResolver = props => {
|
|
73676
|
-
import.meta.css = [css$
|
|
74140
|
+
import.meta.css = [css$y, "@jsenv/navi/src/control/picker/picker_confirm.jsx"];
|
|
73677
74141
|
const Next = useNextResolver();
|
|
73678
74142
|
if (props.type !== "confirm") {
|
|
73679
74143
|
return jsx(Next, {
|
|
@@ -74199,7 +74663,7 @@ const LoadingIndicator = ({
|
|
|
74199
74663
|
};
|
|
74200
74664
|
|
|
74201
74665
|
installImportMetaCssBuild(import.meta);
|
|
74202
|
-
const css$
|
|
74666
|
+
const css$x = /* css */`@layer navi {
|
|
74203
74667
|
.navi_separator {
|
|
74204
74668
|
--size: 1px;
|
|
74205
74669
|
--color: var(--navi-separator-color-default);
|
|
@@ -74273,7 +74737,7 @@ const Separator = ({
|
|
|
74273
74737
|
style,
|
|
74274
74738
|
...props
|
|
74275
74739
|
}) => {
|
|
74276
|
-
import.meta.css = [css$
|
|
74740
|
+
import.meta.css = [css$x, "@jsenv/navi/src/layout/separator.jsx"];
|
|
74277
74741
|
return jsx(Box, {
|
|
74278
74742
|
as: vertical ? "span" : "hr",
|
|
74279
74743
|
...props,
|
|
@@ -75067,7 +75531,7 @@ const listItemBlockedMessage = (loading, props) => {
|
|
|
75067
75531
|
};
|
|
75068
75532
|
|
|
75069
75533
|
installImportMetaCssBuild(import.meta);
|
|
75070
|
-
const css$
|
|
75534
|
+
const css$w = /* css */`@layer navi {
|
|
75071
75535
|
.navi_list_container[navi-selectable] {
|
|
75072
75536
|
--list-item-outline-width: var(--navi-focus-outline-width);
|
|
75073
75537
|
--list-item-outline-offset: calc(-1 * var(--list-item-outline-width));
|
|
@@ -75240,7 +75704,7 @@ const ListSelectableResolver = props => {
|
|
|
75240
75704
|
};
|
|
75241
75705
|
const ListSelectable = props => {
|
|
75242
75706
|
const Next = useNextResolver();
|
|
75243
|
-
import.meta.css = [css$
|
|
75707
|
+
import.meta.css = [css$w, "@jsenv/navi/src/control/list/list_selectable.jsx"];
|
|
75244
75708
|
// we allow ourselves to auto-generate a name
|
|
75245
75709
|
const defaultName = useId();
|
|
75246
75710
|
props.name = props.name || `listbox_${defaultName}`;
|
|
@@ -75909,7 +76373,7 @@ const ListRunItemContext = createContext(null);
|
|
|
75909
76373
|
// item takes its place in the collection by slot: the place is then the list's
|
|
75910
76374
|
// to move, and the item's to follow — see list_items.js.
|
|
75911
76375
|
const ListSlotContext = createContext(null);
|
|
75912
|
-
const css$
|
|
76376
|
+
const css$v = /* css */`@property --list-group-label-height {
|
|
75913
76377
|
syntax: "<length>";
|
|
75914
76378
|
inherits: false;
|
|
75915
76379
|
initial-value: 0;
|
|
@@ -76437,7 +76901,7 @@ const resolveRenderBudget = renderBudget => {
|
|
|
76437
76901
|
};
|
|
76438
76902
|
};
|
|
76439
76903
|
const ListUI = props => {
|
|
76440
|
-
import.meta.css = [css$
|
|
76904
|
+
import.meta.css = [css$v, "@jsenv/navi/src/control/list/list.jsx"];
|
|
76441
76905
|
const {
|
|
76442
76906
|
ref,
|
|
76443
76907
|
renderBudget: renderBudgetProp,
|
|
@@ -82552,7 +83016,7 @@ const createBadgeRegistry = () => {
|
|
|
82552
83016
|
};
|
|
82553
83017
|
|
|
82554
83018
|
installImportMetaCssBuild(import.meta);
|
|
82555
|
-
const css$
|
|
83019
|
+
const css$u = /* css */`@layer navi;
|
|
82556
83020
|
|
|
82557
83021
|
.navi_badge {
|
|
82558
83022
|
--font-size: .7em;
|
|
@@ -82655,7 +83119,7 @@ const BadgeUI = ({
|
|
|
82655
83119
|
className,
|
|
82656
83120
|
...props
|
|
82657
83121
|
}) => {
|
|
82658
|
-
import.meta.css = [css$
|
|
83122
|
+
import.meta.css = [css$u, "@jsenv/navi/src/text/badge.jsx"];
|
|
82659
83123
|
const defaultRef = useRef();
|
|
82660
83124
|
props.ref = props.ref || defaultRef;
|
|
82661
83125
|
const {
|
|
@@ -82763,7 +83227,7 @@ const wrapLabels = childArray => {
|
|
|
82763
83227
|
};
|
|
82764
83228
|
|
|
82765
83229
|
installImportMetaCssBuild(import.meta);
|
|
82766
|
-
const css$
|
|
83230
|
+
const css$t = /* css */`@layer navi;
|
|
82767
83231
|
|
|
82768
83232
|
.navi_badge_list {
|
|
82769
83233
|
flex-wrap: wrap;
|
|
@@ -82898,7 +83362,7 @@ const useBadgeRegistry = (children, enabled) => {
|
|
|
82898
83362
|
* component grants (a <Picker>, see max_lines_context.js).
|
|
82899
83363
|
*/
|
|
82900
83364
|
const BadgeList = props => {
|
|
82901
|
-
import.meta.css = [css$
|
|
83365
|
+
import.meta.css = [css$t, "@jsenv/navi/src/text/badge_list.jsx"];
|
|
82902
83366
|
const {
|
|
82903
83367
|
maxLines,
|
|
82904
83368
|
max,
|
|
@@ -83242,7 +83706,7 @@ const BadgeListContent = ({
|
|
|
83242
83706
|
};
|
|
83243
83707
|
|
|
83244
83708
|
installImportMetaCssBuild(import.meta);
|
|
83245
|
-
const css$
|
|
83709
|
+
const css$s = /* css */`.navi_color {
|
|
83246
83710
|
aspect-ratio: 1;
|
|
83247
83711
|
background-color: currentColor;
|
|
83248
83712
|
border: 1px solid #0003;
|
|
@@ -83262,7 +83726,7 @@ const Color = ({
|
|
|
83262
83726
|
children,
|
|
83263
83727
|
...rest
|
|
83264
83728
|
}) => {
|
|
83265
|
-
import.meta.css = [css$
|
|
83729
|
+
import.meta.css = [css$s, "@jsenv/navi/src/text/color.jsx"];
|
|
83266
83730
|
const color = children || undefined;
|
|
83267
83731
|
return jsx(Box, {
|
|
83268
83732
|
as: "span",
|
|
@@ -83749,7 +84213,7 @@ const PickerFileUI = /*#__PURE__*/asPickerOwnUI(() => {
|
|
|
83749
84213
|
});
|
|
83750
84214
|
|
|
83751
84215
|
installImportMetaCssBuild(import.meta);
|
|
83752
|
-
const css$
|
|
84216
|
+
const css$r = /* css */`@layer navi {
|
|
83753
84217
|
.navi_picker {
|
|
83754
84218
|
--picker-border-radius: var(--navi-control-border-radius);
|
|
83755
84219
|
--picker-border-width: var(--navi-control-border-width);
|
|
@@ -84218,7 +84682,7 @@ const css$t = /* css */`@layer navi {
|
|
|
84218
84682
|
}
|
|
84219
84683
|
`;
|
|
84220
84684
|
const PickerButton = props => {
|
|
84221
|
-
import.meta.css = [css$
|
|
84685
|
+
import.meta.css = [css$r, "@jsenv/navi/src/control/picker/picker.jsx"];
|
|
84222
84686
|
if (typeof props.maxLines === "string") {
|
|
84223
84687
|
props.maxLines = parseInt(props.maxLines);
|
|
84224
84688
|
}
|
|
@@ -84259,11 +84723,6 @@ const PickerButton = props => {
|
|
|
84259
84723
|
// confirm resolver (see picker_confirm.jsx), which is the picker that is
|
|
84260
84724
|
// one — a caller whose popup is a menu of actions says it for themselves.
|
|
84261
84725
|
picksNothing,
|
|
84262
|
-
// Where the caller's own role goes: onto the host, beside the name (see
|
|
84263
|
-
// control_context.js) — a role and a name on two different elements name
|
|
84264
|
-
// nothing at all. Left unsaid, a picker that picks nothing takes "button"
|
|
84265
|
-
// (see PickerInput below).
|
|
84266
|
-
role,
|
|
84267
84726
|
readOnly,
|
|
84268
84727
|
error,
|
|
84269
84728
|
// Who draws the loading outline. Left unsaid, the picker does, around its
|
|
@@ -84344,21 +84803,8 @@ const PickerButton = props => {
|
|
|
84344
84803
|
// clearing being a modification like any other.
|
|
84345
84804
|
const interactive = !basePseudoState[":disabled"] && !basePseudoState[":read-only"] && !loading;
|
|
84346
84805
|
usePickerErrorCallout(uiStateController, error);
|
|
84347
|
-
|
|
84348
|
-
|
|
84349
|
-
// door — its popup is a question (type="confirm") or something to read
|
|
84350
|
-
// (mode="callout", which says it for itself) — and a door is pressed. So it
|
|
84351
|
-
// answers to "button" rather than to the "textbox" its <input> would
|
|
84352
|
-
// otherwise be, which is both what a screen reader announces and what
|
|
84353
|
-
// getByRole("button", { name }) finds. A picker holding a value stays a
|
|
84354
|
-
// textbox: it does hold text.
|
|
84355
|
-
const hostRole = role ?? (picksNothing ? "button" : undefined);
|
|
84356
|
-
// And what that button is called, when the caller wrote it as a drawing
|
|
84357
|
-
// rather than as a word: a door draws no value, so what sits in its value
|
|
84358
|
-
// slot IS its label — the `ui` a caller gave it, or its placeholder. Skipped
|
|
84359
|
-
// the moment the caller names it themselves (aria-label/aria-labelledby),
|
|
84360
|
-
// which is the only way to name a door drawn as an icon.
|
|
84361
|
-
const hostLabelId = hostRole === "button" && inputProps["aria-label"] === undefined && inputProps["aria-labelledby"] === undefined && variant !== "headless" && ui !== "default" ? `${inputProps.id}_picker_label` : undefined;
|
|
84806
|
+
const hostRole = getPickerHostRole(props);
|
|
84807
|
+
const hostLabelId = getPickerHostLabelId(inputProps.id, props);
|
|
84362
84808
|
// What the picker knows about itself, for the pieces it does not place: the
|
|
84363
84809
|
// drawings of its value (Picker.UI.*), and the affordances a caller may put
|
|
84364
84810
|
// in their own `ui` (Picker.Clear) as much as the ones it puts in its slot.
|
|
@@ -84427,8 +84873,16 @@ const PickerButton = props => {
|
|
|
84427
84873
|
basePseudoState: basePseudoState,
|
|
84428
84874
|
styleCSSVars: PickerStyleCSSVars,
|
|
84429
84875
|
variant: undefined,
|
|
84430
|
-
icon: undefined
|
|
84876
|
+
icon: undefined
|
|
84877
|
+
// The caller's own role goes onto the host, beside the name (see
|
|
84878
|
+
// control_context.js): a role and a name on two different elements
|
|
84879
|
+
// name nothing at all. What the trigger opens is said there too, and
|
|
84880
|
+
// aria-haspopup with it. aria-expanded stays here as well: commands.js
|
|
84881
|
+
// and the CSS read the open state off the root (see
|
|
84882
|
+
// expandableRepeatedBy in commands.js).
|
|
84883
|
+
,
|
|
84431
84884
|
role: undefined,
|
|
84885
|
+
"aria-haspopup": undefined,
|
|
84432
84886
|
rightSlotIcon: undefined,
|
|
84433
84887
|
rightSlotIconSize: undefined,
|
|
84434
84888
|
rightSlot: undefined,
|
|
@@ -84468,6 +84922,8 @@ const PickerButton = props => {
|
|
|
84468
84922
|
inset: loadingOutlineInset
|
|
84469
84923
|
}), jsx(PickerInput, {
|
|
84470
84924
|
role: hostRole,
|
|
84925
|
+
"aria-haspopup": props["aria-haspopup"],
|
|
84926
|
+
"aria-expanded": props["aria-expanded"],
|
|
84471
84927
|
"aria-labelledby": hostLabelId,
|
|
84472
84928
|
tabIndex: variant === "headless" ? -1 : undefined,
|
|
84473
84929
|
"aria-hidden": variant === "headless" ? "true" : undefined,
|
|
@@ -84993,7 +85449,7 @@ const Picker = /*#__PURE__*/Object.assign(PickerResolved, {
|
|
|
84993
85449
|
});
|
|
84994
85450
|
|
|
84995
85451
|
installImportMetaCssBuild(import.meta);
|
|
84996
|
-
const css$
|
|
85452
|
+
const css$q = /* css */`@layer navi {
|
|
84997
85453
|
.navi_picker_spin {
|
|
84998
85454
|
--picker-spin-padding-x-default: var(--navi-picker-padding-x-default);
|
|
84999
85455
|
--picker-spin-padding-y-default: var(--navi-picker-padding-y-default);
|
|
@@ -85343,7 +85799,7 @@ const Spin = ({
|
|
|
85343
85799
|
nextLabel,
|
|
85344
85800
|
...rest
|
|
85345
85801
|
}) => {
|
|
85346
|
-
import.meta.css = [css$
|
|
85802
|
+
import.meta.css = [css$q, "@jsenv/navi/src/control/picker/picker_spin.jsx"];
|
|
85347
85803
|
const id = useId();
|
|
85348
85804
|
// What the group around it says, when there is one: how big the whole thing
|
|
85349
85805
|
// is written is said once, on the group, and every spin in it follows.
|
|
@@ -86054,7 +86510,7 @@ const renderValueDefault = value => String(value ?? "");
|
|
|
86054
86510
|
* are passed on to the spins sitting in them.
|
|
86055
86511
|
*/
|
|
86056
86512
|
const SpinGroup = props => {
|
|
86057
|
-
import.meta.css = [css$
|
|
86513
|
+
import.meta.css = [css$q, "@jsenv/navi/src/control/picker/picker_spin.jsx"];
|
|
86058
86514
|
const {
|
|
86059
86515
|
size
|
|
86060
86516
|
} = props;
|
|
@@ -86563,7 +87019,7 @@ const TimeRangeSpin = ({
|
|
|
86563
87019
|
};
|
|
86564
87020
|
|
|
86565
87021
|
installImportMetaCssBuild(import.meta);
|
|
86566
|
-
const css$
|
|
87022
|
+
const css$p = /* css */`.navi_checkbox_group {
|
|
86567
87023
|
border-style: solid;
|
|
86568
87024
|
|
|
86569
87025
|
&[data-callout] {
|
|
@@ -86623,7 +87079,7 @@ const CheckboxGroup = props => {
|
|
|
86623
87079
|
return checkboxGroup;
|
|
86624
87080
|
};
|
|
86625
87081
|
const CheckboxGroupInterface = props => {
|
|
86626
|
-
import.meta.css = [css$
|
|
87082
|
+
import.meta.css = [css$p, "@jsenv/navi/src/control/input/checkbox_group.jsx"];
|
|
86627
87083
|
const {
|
|
86628
87084
|
ref
|
|
86629
87085
|
} = props;
|
|
@@ -86741,7 +87197,7 @@ const formatIntlUnit = (unit, {
|
|
|
86741
87197
|
};
|
|
86742
87198
|
|
|
86743
87199
|
installImportMetaCssBuild(import.meta);
|
|
86744
|
-
const css$
|
|
87200
|
+
const css$o = /* css */`.navi_input_duration {
|
|
86745
87201
|
--duration-separator-spacing: 4px;
|
|
86746
87202
|
--loader-color: var(--navi-loader-color);
|
|
86747
87203
|
position: relative;
|
|
@@ -86806,7 +87262,7 @@ const css$q = /* css */`.navi_input_duration {
|
|
|
86806
87262
|
* "auto" aligns each field toward its neighbouring separator (first→right, last→left, middle/solo→center).
|
|
86807
87263
|
*/
|
|
86808
87264
|
const InputDuration = props => {
|
|
86809
|
-
import.meta.css = [css$
|
|
87265
|
+
import.meta.css = [css$o, "@jsenv/navi/src/control/input/input_duration.jsx"];
|
|
86810
87266
|
const defaultRef = useRef();
|
|
86811
87267
|
props.ref = props.ref || defaultRef;
|
|
86812
87268
|
props.max = props.max || "23h59";
|
|
@@ -87307,7 +87763,7 @@ const InputDurationPart = ({
|
|
|
87307
87763
|
};
|
|
87308
87764
|
|
|
87309
87765
|
installImportMetaCssBuild(import.meta);
|
|
87310
|
-
const css$
|
|
87766
|
+
const css$n = /* css */`.navi_radio_group {
|
|
87311
87767
|
border-style: solid;
|
|
87312
87768
|
|
|
87313
87769
|
&[data-callout] {
|
|
@@ -87347,7 +87803,7 @@ const RadioGroup = props => {
|
|
|
87347
87803
|
return radioGroup;
|
|
87348
87804
|
};
|
|
87349
87805
|
const RadioGroupInterface = props => {
|
|
87350
|
-
import.meta.css = [css$
|
|
87806
|
+
import.meta.css = [css$n, "@jsenv/navi/src/control/input/radio_group.jsx"];
|
|
87351
87807
|
const {
|
|
87352
87808
|
ref
|
|
87353
87809
|
} = props;
|
|
@@ -87377,7 +87833,7 @@ const RadioGroupInterface = props => {
|
|
|
87377
87833
|
};
|
|
87378
87834
|
|
|
87379
87835
|
installImportMetaCssBuild(import.meta);
|
|
87380
|
-
const css$
|
|
87836
|
+
const css$m = /* css */`.navi_input.navi_select {
|
|
87381
87837
|
& .navi_control_input {
|
|
87382
87838
|
padding-right: calc(var(--x-padding-right) + 1em);
|
|
87383
87839
|
line-height: var(--navi-control-line-height);
|
|
@@ -87424,7 +87880,7 @@ const Select = ({
|
|
|
87424
87880
|
...props
|
|
87425
87881
|
}) => {
|
|
87426
87882
|
installInputCss();
|
|
87427
|
-
import.meta.css = [css$
|
|
87883
|
+
import.meta.css = [css$m, "@jsenv/navi/src/control/input/select.jsx"];
|
|
87428
87884
|
const defaultRef = useRef(null);
|
|
87429
87885
|
props.ref = props.ref || defaultRef;
|
|
87430
87886
|
seedDefaultValueFromSignal(props);
|
|
@@ -87474,7 +87930,7 @@ const Select = ({
|
|
|
87474
87930
|
};
|
|
87475
87931
|
|
|
87476
87932
|
installImportMetaCssBuild(import.meta);
|
|
87477
|
-
const css$
|
|
87933
|
+
const css$l = /* css */`.navi_split_button {
|
|
87478
87934
|
border-radius: var(--navi-control-border-radius);
|
|
87479
87935
|
display: inline-flex;
|
|
87480
87936
|
position: relative;
|
|
@@ -87596,7 +88052,7 @@ const css$n = /* css */`.navi_split_button {
|
|
|
87596
88052
|
* on the split button's own box.
|
|
87597
88053
|
*/
|
|
87598
88054
|
const SplitButton = props => {
|
|
87599
|
-
import.meta.css = [css$
|
|
88055
|
+
import.meta.css = [css$l, "@jsenv/navi/src/control/input/split_button.jsx"];
|
|
87600
88056
|
const {
|
|
87601
88057
|
options = [],
|
|
87602
88058
|
value,
|
|
@@ -88615,7 +89071,7 @@ const createItemTracker = (onChange) => {
|
|
|
88615
89071
|
};
|
|
88616
89072
|
|
|
88617
89073
|
installImportMetaCssBuild(import.meta);
|
|
88618
|
-
const css$
|
|
89074
|
+
const css$k = /* css */`.navi_wheel_container {
|
|
88619
89075
|
--wheel-item-height: round(1.8em, 1px);
|
|
88620
89076
|
--wheel-emphasis-size: round(1.5em, 1px);
|
|
88621
89077
|
--wheel-item-width: 3.5ch;
|
|
@@ -89563,7 +90019,7 @@ const useWheelKeyboard = ({
|
|
|
89563
90019
|
}, [isHorizontal, interactive, isLoop]);
|
|
89564
90020
|
};
|
|
89565
90021
|
function WheelUI(props) {
|
|
89566
|
-
import.meta.css = [css$
|
|
90022
|
+
import.meta.css = [css$k, "@jsenv/navi/src/control/wheel/wheel.jsx"];
|
|
89567
90023
|
const {
|
|
89568
90024
|
ref,
|
|
89569
90025
|
visibleCount = 3,
|
|
@@ -90553,7 +91009,7 @@ Wheel.Item = WheelItem;
|
|
|
90553
91009
|
* @param {boolean|number} [props.zoom] - Enlarge the centered value of every wheel (see Wheel's zoom prop) with one prop for the whole group.
|
|
90554
91010
|
*/
|
|
90555
91011
|
const WheelGroup = props => {
|
|
90556
|
-
import.meta.css = [css$
|
|
91012
|
+
import.meta.css = [css$k, "@jsenv/navi/src/control/wheel/wheel.jsx"];
|
|
90557
91013
|
// WheelGroup IS a control group: it aggregates its named wheels ("hours",
|
|
90558
91014
|
// "minutes"…) into one object value, so it can sit directly inside a Form or a
|
|
90559
91015
|
// Picker with no extra <ControlGroup> wrapper. The wheel-specific presentation
|
|
@@ -90726,7 +91182,7 @@ const WheelColon = props => {
|
|
|
90726
91182
|
Wheel.Colon = WheelColon;
|
|
90727
91183
|
|
|
90728
91184
|
installImportMetaCssBuild(import.meta);
|
|
90729
|
-
const css$
|
|
91185
|
+
const css$j = /* css */`.navi_time_range_label {
|
|
90730
91186
|
--wheel-item-height: round(1.8em, 1px);
|
|
90731
91187
|
color: var(--wheel-color, light-dark(#111, #eee));
|
|
90732
91188
|
line-height: var(--wheel-item-height);
|
|
@@ -90950,7 +91406,7 @@ const TimeRangeWheel = ({
|
|
|
90950
91406
|
endTimeProps,
|
|
90951
91407
|
...rest
|
|
90952
91408
|
}) => {
|
|
90953
|
-
import.meta.css = [css$
|
|
91409
|
+
import.meta.css = [css$j, "@jsenv/navi/src/control/wheel/wheel_time.jsx"];
|
|
90954
91410
|
const startId = useId();
|
|
90955
91411
|
const startRef = useRef(null);
|
|
90956
91412
|
const endRef = useRef(null);
|
|
@@ -91538,7 +91994,7 @@ const Z_INDEX_DROP_PREVIEW = Z_INDEX_STICKY_CORNER + 1;
|
|
|
91538
91994
|
const Z_INDEX_TABLE_UI = Z_INDEX_STICKY_CORNER + 1;
|
|
91539
91995
|
|
|
91540
91996
|
installImportMetaCssBuild(import.meta);
|
|
91541
|
-
const css$
|
|
91997
|
+
const css$i = /* css */`.navi_table_drag_clone_container {
|
|
91542
91998
|
top: var(--table-visual-top);
|
|
91543
91999
|
left: var(--table-visual-left);
|
|
91544
92000
|
width: var(--table-visual-width);
|
|
@@ -91693,7 +92149,7 @@ const useTableDragContextValue = ({
|
|
|
91693
92149
|
}, [grabTarget, canChangeColumnOrder]);
|
|
91694
92150
|
};
|
|
91695
92151
|
const TableDragCloneContainer = /*#__PURE__*/forwardRef((props, ref) => {
|
|
91696
|
-
import.meta.css = [css$
|
|
92152
|
+
import.meta.css = [css$i, "@jsenv/navi/src/control/table/drag/table_drag.jsx"];
|
|
91697
92153
|
const {
|
|
91698
92154
|
tableId
|
|
91699
92155
|
} = props;
|
|
@@ -91992,7 +92448,7 @@ const ROW_MIN_HEIGHT = 30;
|
|
|
91992
92448
|
const ROW_MAX_HEIGHT = 100;
|
|
91993
92449
|
const COLUMN_MIN_WIDTH = 50;
|
|
91994
92450
|
const COLUMN_MAX_WIDTH = 500;
|
|
91995
|
-
const css$
|
|
92451
|
+
const css$h = /* css */`@layer navi {
|
|
91996
92452
|
.navi_table {
|
|
91997
92453
|
--table-resizer-handle-color: #063b7c;
|
|
91998
92454
|
--table-resizer-color: #387ec9;
|
|
@@ -92161,7 +92617,7 @@ const css$j = /* css */`@layer navi {
|
|
|
92161
92617
|
|
|
92162
92618
|
// Column resize components
|
|
92163
92619
|
const TableColumnResizer = props => {
|
|
92164
|
-
import.meta.css = [css$
|
|
92620
|
+
import.meta.css = [css$h, "@jsenv/navi/src/control/table/resize/table_resize.jsx"];
|
|
92165
92621
|
const defaultRef = useRef();
|
|
92166
92622
|
const ref = props.ref || defaultRef;
|
|
92167
92623
|
return jsxs("div", {
|
|
@@ -92633,7 +93089,7 @@ const findPreviousTableRow = currentRow => {
|
|
|
92633
93089
|
};
|
|
92634
93090
|
|
|
92635
93091
|
installImportMetaCssBuild(import.meta);
|
|
92636
|
-
const css$
|
|
93092
|
+
const css$g = /* css */`@layer navi {
|
|
92637
93093
|
.navi_table {
|
|
92638
93094
|
--selection-border-color: var(--navi-selection-border-color, #0078d4);
|
|
92639
93095
|
--selection-background-color: var(--navi-selection-background-color, #eaf1fd);
|
|
@@ -92727,7 +93183,7 @@ const useTableSelectionController = ({
|
|
|
92727
93183
|
onSelectionChange,
|
|
92728
93184
|
selectionColor
|
|
92729
93185
|
}) => {
|
|
92730
|
-
import.meta.css = [css$
|
|
93186
|
+
import.meta.css = [css$g, "@jsenv/navi/src/control/table/selection/table_selection.jsx"];
|
|
92731
93187
|
const selectionController = useSelectionController({
|
|
92732
93188
|
elementRef: tableRef,
|
|
92733
93189
|
layout: "grid",
|
|
@@ -93198,7 +93654,7 @@ const useTableStickyContextValue = ({
|
|
|
93198
93654
|
};
|
|
93199
93655
|
|
|
93200
93656
|
installImportMetaCssBuild(import.meta);
|
|
93201
|
-
const css$
|
|
93657
|
+
const css$f = /* css */`@layer navi {
|
|
93202
93658
|
.navi_table {
|
|
93203
93659
|
--sticky-frontier-color: silver;
|
|
93204
93660
|
--sticky-frontier-size: 12px;
|
|
@@ -93371,7 +93827,7 @@ const css$h = /* css */`@layer navi {
|
|
|
93371
93827
|
const TableStickyFrontier = ({
|
|
93372
93828
|
tableRef
|
|
93373
93829
|
}) => {
|
|
93374
|
-
import.meta.css = [css$
|
|
93830
|
+
import.meta.css = [css$f, "@jsenv/navi/src/control/table/sticky/table_sticky.jsx"];
|
|
93375
93831
|
const stickyLeftFrontierGhostRef = useRef();
|
|
93376
93832
|
const stickyLeftFrontierPreviewRef = useRef();
|
|
93377
93833
|
const stickyTopFrontierGhostRef = useRef();
|
|
@@ -93602,7 +94058,7 @@ installImportMetaCssBuild(import.meta);
|
|
|
93602
94058
|
* inset 0 -1px 0 0 color; // Bottom border
|
|
93603
94059
|
*/
|
|
93604
94060
|
|
|
93605
|
-
const css$
|
|
94061
|
+
const css$e = /* css */ `.navi_table_root {
|
|
93606
94062
|
max-width: var(--table-max-width, none);
|
|
93607
94063
|
max-height: var(--table-max-height, none);
|
|
93608
94064
|
position: relative;
|
|
@@ -93787,11 +94243,11 @@ const css$g = /* css */ `.navi_table_root {
|
|
|
93787
94243
|
// table must not carry this sheet, and a build that sees no caller drops the
|
|
93788
94244
|
// css with the function.
|
|
93789
94245
|
const installTableCss = () => {
|
|
93790
|
-
import.meta.css = [css$
|
|
94246
|
+
import.meta.css = [css$e, "@jsenv/navi/src/control/table/table_css.js"];
|
|
93791
94247
|
};
|
|
93792
94248
|
|
|
93793
94249
|
installImportMetaCssBuild(import.meta);
|
|
93794
|
-
const css$
|
|
94250
|
+
const css$d = /* css */`.navi_table_ui {
|
|
93795
94251
|
z-index: ${Z_INDEX_TABLE_UI};
|
|
93796
94252
|
pointer-events: none;
|
|
93797
94253
|
position: fixed;
|
|
@@ -93800,7 +94256,7 @@ const css$f = /* css */`.navi_table_ui {
|
|
|
93800
94256
|
}
|
|
93801
94257
|
`;
|
|
93802
94258
|
const TableUI = /*#__PURE__*/forwardRef((props, ref) => {
|
|
93803
|
-
import.meta.css = [css$
|
|
94259
|
+
import.meta.css = [css$d, "@jsenv/navi/src/control/table/table_ui.jsx"];
|
|
93804
94260
|
const {
|
|
93805
94261
|
tableRef,
|
|
93806
94262
|
tableId,
|
|
@@ -94722,7 +95178,7 @@ const normalizeKey = (key) => {
|
|
|
94722
95178
|
};
|
|
94723
95179
|
|
|
94724
95180
|
installImportMetaCssBuild(import.meta);
|
|
94725
|
-
const css$
|
|
95181
|
+
const css$c = /* css */`.navi_shortcut_container[data-visually-hidden], .navi_shortcut_button[data-visually-hidden] {
|
|
94726
95182
|
clip: rect(0, 0, 0, 0);
|
|
94727
95183
|
white-space: nowrap;
|
|
94728
95184
|
opacity: 0;
|
|
@@ -94739,7 +95195,7 @@ const css$e = /* css */`.navi_shortcut_container[data-visually-hidden], .navi_sh
|
|
|
94739
95195
|
const ActiveKeyboardShortcuts = ({
|
|
94740
95196
|
visible
|
|
94741
95197
|
}) => {
|
|
94742
|
-
import.meta.css = [css$
|
|
95198
|
+
import.meta.css = [css$c, "@jsenv/navi/src/keyboard/active_keyboard_shortcuts.jsx"];
|
|
94743
95199
|
const activeShortcuts = activeShortcutsSignal.value;
|
|
94744
95200
|
return jsx("div", {
|
|
94745
95201
|
className: "navi_shortcut_container",
|
|
@@ -94779,7 +95235,7 @@ const KeyboardShortcutAriaElement = ({
|
|
|
94779
95235
|
};
|
|
94780
95236
|
|
|
94781
95237
|
installImportMetaCssBuild(import.meta);
|
|
94782
|
-
const css$
|
|
95238
|
+
const css$b = /* css */`@layer navi {
|
|
94783
95239
|
.navi_clipboard_container {
|
|
94784
95240
|
--height: 1.5em;
|
|
94785
95241
|
--notif-spacing: .5em;
|
|
@@ -94810,7 +95266,7 @@ const ButtonCopyToClipboard = ({
|
|
|
94810
95266
|
children,
|
|
94811
95267
|
...props
|
|
94812
95268
|
}) => {
|
|
94813
|
-
import.meta.css = [css$
|
|
95269
|
+
import.meta.css = [css$b, "@jsenv/navi/src/control/input/button_copy_to_clipboard.jsx"];
|
|
94814
95270
|
const [copied, setCopied] = useState(false);
|
|
94815
95271
|
const renderedRef = useRef();
|
|
94816
95272
|
useEffect(() => {
|
|
@@ -94890,7 +95346,7 @@ const Address = ({
|
|
|
94890
95346
|
};
|
|
94891
95347
|
|
|
94892
95348
|
installImportMetaCssBuild(import.meta);
|
|
94893
|
-
const css$
|
|
95349
|
+
const css$a = /* css */`@layer navi;
|
|
94894
95350
|
|
|
94895
95351
|
.navi_text.navi_badge_count {
|
|
94896
95352
|
white-space: nowrap;
|
|
@@ -95019,7 +95475,7 @@ const BadgeCount = ({
|
|
|
95019
95475
|
lineLayout,
|
|
95020
95476
|
...props
|
|
95021
95477
|
}) => {
|
|
95022
|
-
import.meta.css = [css$
|
|
95478
|
+
import.meta.css = [css$a, "@jsenv/navi/src/text/badge_count.jsx"];
|
|
95023
95479
|
const defaultRef = useRef();
|
|
95024
95480
|
props.ref = props.ref || defaultRef;
|
|
95025
95481
|
const {
|
|
@@ -95162,7 +95618,7 @@ const BadgeCountCircle = ({
|
|
|
95162
95618
|
};
|
|
95163
95619
|
|
|
95164
95620
|
installImportMetaCssBuild(import.meta);
|
|
95165
|
-
const css$
|
|
95621
|
+
const css$9 = /* css */`@layer navi {
|
|
95166
95622
|
.navi_caption {
|
|
95167
95623
|
--color: #6b7280;
|
|
95168
95624
|
}
|
|
@@ -95182,7 +95638,7 @@ const Caption = ({
|
|
|
95182
95638
|
className,
|
|
95183
95639
|
...rest
|
|
95184
95640
|
}) => {
|
|
95185
|
-
import.meta.css = [css$
|
|
95641
|
+
import.meta.css = [css$9, "@jsenv/navi/src/text/caption.jsx"];
|
|
95186
95642
|
return jsx(Text, {
|
|
95187
95643
|
as: "small",
|
|
95188
95644
|
size: "0.8em" // We use em to be relative to the parent (we want to be smaller than the surrounding text)
|
|
@@ -95578,177 +96034,8 @@ const Interpolate = ({
|
|
|
95578
96034
|
});
|
|
95579
96035
|
};
|
|
95580
96036
|
|
|
95581
|
-
const SuccessSvg = () => {
|
|
95582
|
-
return jsx("svg", {
|
|
95583
|
-
viewBox: "0 0 16 16",
|
|
95584
|
-
fill: "currentColor",
|
|
95585
|
-
children: jsx("path", {
|
|
95586
|
-
d: "M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8Zm1.5 0a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Zm10.28-1.72-4.5 4.5a.75.75 0 0 1-1.06 0l-2-2a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l1.47 1.47 3.97-3.97a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042Z"
|
|
95587
|
-
})
|
|
95588
|
-
});
|
|
95589
|
-
};
|
|
95590
|
-
const ErrorSvg = () => {
|
|
95591
|
-
return jsx("svg", {
|
|
95592
|
-
viewBox: "0 0 16 16",
|
|
95593
|
-
fill: "currentColor",
|
|
95594
|
-
children: jsx("path", {
|
|
95595
|
-
d: "M4.47.22A.749.749 0 0 1 5 0h6c.199 0 .389.079.53.22l4.25 4.25c.141.14.22.331.22.53v6a.749.749 0 0 1-.22.53l-4.25 4.25A.749.749 0 0 1 11 16H5a.749.749 0 0 1-.53-.22L.22 11.53A.749.749 0 0 1 0 11V5c0-.199.079-.389.22-.53Zm.84 1.28L1.5 5.31v5.38l3.81 3.81h5.38l3.81-3.81V5.31L10.69 1.5ZM8 4a.75.75 0 0 1 .75.75v3.5a.75.75 0 0 1-1.5 0v-3.5A.75.75 0 0 1 8 4Zm0 8a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z"
|
|
95596
|
-
})
|
|
95597
|
-
});
|
|
95598
|
-
};
|
|
95599
|
-
const InfoSvg$1 = () => {
|
|
95600
|
-
return jsx("svg", {
|
|
95601
|
-
viewBox: "0 0 16 16",
|
|
95602
|
-
fill: "currentColor",
|
|
95603
|
-
children: jsx("path", {
|
|
95604
|
-
d: "M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8Zm8-6.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13ZM6.5 7.75A.75.75 0 0 1 7.25 7h1a.75.75 0 0 1 .75.75v2.75h.25a.75.75 0 0 1 0 1.5h-2a.75.75 0 0 1 0-1.5h.25v-2h-.25a.75.75 0 0 1-.75-.75ZM8 6a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z"
|
|
95605
|
-
})
|
|
95606
|
-
});
|
|
95607
|
-
};
|
|
95608
|
-
const WarningSvg = () => {
|
|
95609
|
-
return jsx("svg", {
|
|
95610
|
-
viewBox: "0 0 16 16",
|
|
95611
|
-
fill: "currentColor",
|
|
95612
|
-
children: jsx("path", {
|
|
95613
|
-
d: "M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"
|
|
95614
|
-
})
|
|
95615
|
-
});
|
|
95616
|
-
};
|
|
95617
|
-
|
|
95618
96037
|
installImportMetaCssBuild(import.meta);
|
|
95619
|
-
const css$
|
|
95620
|
-
.navi_message_box {
|
|
95621
|
-
--background-color-info: var(--navi-info-color-light);
|
|
95622
|
-
--color-info: var(--navi-info-color);
|
|
95623
|
-
--background-color-success: var(--navi-success-color-light);
|
|
95624
|
-
--color-success: var(--navi-success-color);
|
|
95625
|
-
--background-color-warning: var(--navi-warning-color-light);
|
|
95626
|
-
--color-warning: var(--navi-warning-color);
|
|
95627
|
-
--background-color-error: var(--navi-error-color-light);
|
|
95628
|
-
--color-error: var(--navi-error-color);
|
|
95629
|
-
}
|
|
95630
|
-
}
|
|
95631
|
-
|
|
95632
|
-
.navi_message_box {
|
|
95633
|
-
--x-message-background-color: var(--background-color-info);
|
|
95634
|
-
--x-message-color: var(--color-info);
|
|
95635
|
-
background-color: var(--x-message-background-color);
|
|
95636
|
-
|
|
95637
|
-
& > .navi_icon {
|
|
95638
|
-
flex-shrink: 0;
|
|
95639
|
-
}
|
|
95640
|
-
}
|
|
95641
|
-
|
|
95642
|
-
.navi_message_box[data-status-info] {
|
|
95643
|
-
--x-message-background-color: var(--background-color-info);
|
|
95644
|
-
--x-message-color: var(--color-info);
|
|
95645
|
-
}
|
|
95646
|
-
|
|
95647
|
-
.navi_message_box[data-status-success] {
|
|
95648
|
-
--x-message-background-color: var(--background-color-success);
|
|
95649
|
-
--x-message-color: var(--color-success);
|
|
95650
|
-
}
|
|
95651
|
-
|
|
95652
|
-
.navi_message_box[data-status-warning] {
|
|
95653
|
-
--x-message-background-color: var(--background-color-warning);
|
|
95654
|
-
--x-message-color: var(--color-warning);
|
|
95655
|
-
}
|
|
95656
|
-
|
|
95657
|
-
.navi_message_box[data-status-error] {
|
|
95658
|
-
--x-message-background-color: var(--background-color-error);
|
|
95659
|
-
--x-message-color: var(--color-error);
|
|
95660
|
-
}
|
|
95661
|
-
|
|
95662
|
-
.navi_message_box[data-left-stripe] {
|
|
95663
|
-
border-left: 6px solid var(--x-message-color);
|
|
95664
|
-
border-top-left-radius: 6px;
|
|
95665
|
-
border-bottom-left-radius: 6px;
|
|
95666
|
-
}
|
|
95667
|
-
`;
|
|
95668
|
-
const MessageBox = ({
|
|
95669
|
-
status = "info",
|
|
95670
|
-
padding = "sm",
|
|
95671
|
-
icon,
|
|
95672
|
-
leftStripe,
|
|
95673
|
-
children,
|
|
95674
|
-
onClose,
|
|
95675
|
-
...rest
|
|
95676
|
-
}) => {
|
|
95677
|
-
import.meta.css = [css$a, "@jsenv/navi/src/text/message_box.jsx"];
|
|
95678
|
-
const [hasTitleChild, setHasTitleChild] = useState(false);
|
|
95679
|
-
const innerLeftStripe = leftStripe === undefined ? hasTitleChild : leftStripe;
|
|
95680
|
-
if (icon === true) {
|
|
95681
|
-
icon = status === "info" ? jsx(InfoSvg$1, {}) : status === "success" ? jsx(SuccessSvg, {}) : status === "warning" ? jsx(WarningSvg, {}) : status === "error" ? jsx(ErrorSvg, {}) : null;
|
|
95682
|
-
} else if (typeof icon === "function") {
|
|
95683
|
-
const Comp = icon;
|
|
95684
|
-
icon = jsx(Comp, {});
|
|
95685
|
-
}
|
|
95686
|
-
return jsx(Box, {
|
|
95687
|
-
as: "div",
|
|
95688
|
-
role: status === "info" ? "status" : "alert",
|
|
95689
|
-
"data-left-stripe": innerLeftStripe ? "" : undefined,
|
|
95690
|
-
inline: true,
|
|
95691
|
-
column: true,
|
|
95692
|
-
alignY: "center",
|
|
95693
|
-
spacing: "s",
|
|
95694
|
-
...rest,
|
|
95695
|
-
className: withPropsClassName("navi_message_box", rest.className),
|
|
95696
|
-
padding: padding,
|
|
95697
|
-
pseudoClasses: MessageBoxPseudoClasses,
|
|
95698
|
-
basePseudoState: {
|
|
95699
|
-
":-navi-status-info": status === "info",
|
|
95700
|
-
":-navi-status-success": status === "success",
|
|
95701
|
-
":-navi-status-warning": status === "warning",
|
|
95702
|
-
":-navi-status-error": status === "error"
|
|
95703
|
-
},
|
|
95704
|
-
children: jsx(MessageBoxStatusContext.Provider, {
|
|
95705
|
-
value: status,
|
|
95706
|
-
children: jsxs(MessageBoxReportTitleChildContext.Provider, {
|
|
95707
|
-
value: setHasTitleChild,
|
|
95708
|
-
children: [icon && jsx(Icon, {
|
|
95709
|
-
color: "var(--x-message-color)",
|
|
95710
|
-
height: "1lh",
|
|
95711
|
-
maxHeight: "auto",
|
|
95712
|
-
selfAlignY: "start",
|
|
95713
|
-
aspectRatio: "auto",
|
|
95714
|
-
children: icon
|
|
95715
|
-
}), jsx(Text, {
|
|
95716
|
-
children: children
|
|
95717
|
-
}), onClose &&
|
|
95718
|
-
// A column as tall as the first line of the message, pinned to the
|
|
95719
|
-
// top, the button centered in it: the close button stays level
|
|
95720
|
-
// with the first line however many lines the message takes (same
|
|
95721
|
-
// layout as Callout).
|
|
95722
|
-
jsx(Box, {
|
|
95723
|
-
flex: true,
|
|
95724
|
-
alignY: "center",
|
|
95725
|
-
height: "1lh",
|
|
95726
|
-
selfAlignY: "start",
|
|
95727
|
-
shrink: false,
|
|
95728
|
-
children: jsx(Button, {
|
|
95729
|
-
action: onClose,
|
|
95730
|
-
icon: true,
|
|
95731
|
-
border: "none",
|
|
95732
|
-
style: {
|
|
95733
|
-
":hover": {
|
|
95734
|
-
backgroundColor: "rgba(0, 0, 0, 0.1)"
|
|
95735
|
-
}
|
|
95736
|
-
},
|
|
95737
|
-
children: jsx(Icon, {
|
|
95738
|
-
children: jsx(CloseSvg, {})
|
|
95739
|
-
})
|
|
95740
|
-
})
|
|
95741
|
-
})]
|
|
95742
|
-
})
|
|
95743
|
-
})
|
|
95744
|
-
});
|
|
95745
|
-
};
|
|
95746
|
-
const MessageBoxPseudoClasses = [":-navi-status-info", ":-navi-status-success", ":-navi-status-warning", ":-navi-status-error"];
|
|
95747
|
-
const MessageBoxStatusContext = createContext();
|
|
95748
|
-
const MessageBoxReportTitleChildContext = createContext();
|
|
95749
|
-
|
|
95750
|
-
installImportMetaCssBuild(import.meta);
|
|
95751
|
-
const css$9 = /* css */`@layer navi;
|
|
96038
|
+
const css$8 = /* css */`@layer navi;
|
|
95752
96039
|
|
|
95753
96040
|
.navi_quantity {
|
|
95754
96041
|
flex-direction: column;
|
|
@@ -95849,7 +96136,7 @@ const Quantity = ({
|
|
|
95849
96136
|
bold = true,
|
|
95850
96137
|
...props
|
|
95851
96138
|
}) => {
|
|
95852
|
-
import.meta.css = [css$
|
|
96139
|
+
import.meta.css = [css$8, "@jsenv/navi/src/text/quantity.jsx"];
|
|
95853
96140
|
const value = parseQuantityValue(children);
|
|
95854
96141
|
const valueRounded = integer && typeof value === "number" ? Math.round(value) : value;
|
|
95855
96142
|
const valueFormatted = typeof valueRounded === "number" ? formatNumber(valueRounded, {
|
|
@@ -95908,7 +96195,7 @@ const parseQuantityValue = children => {
|
|
|
95908
96195
|
};
|
|
95909
96196
|
|
|
95910
96197
|
installImportMetaCssBuild(import.meta);
|
|
95911
|
-
const css$
|
|
96198
|
+
const css$7 = /* css */`@layer navi {
|
|
95912
96199
|
.navi_meter {
|
|
95913
96200
|
--loader-color: var(--navi-loader-color);
|
|
95914
96201
|
--track-color: #efefef;
|
|
@@ -96047,7 +96334,7 @@ const Meter = ({
|
|
|
96047
96334
|
style,
|
|
96048
96335
|
...rest
|
|
96049
96336
|
}) => {
|
|
96050
|
-
import.meta.css = [css$
|
|
96337
|
+
import.meta.css = [css$7, "@jsenv/navi/src/text/meter.jsx"];
|
|
96051
96338
|
const defaultRef = useRef();
|
|
96052
96339
|
const ref = rest.ref || defaultRef;
|
|
96053
96340
|
value = Number(value);
|
|
@@ -96162,7 +96449,7 @@ const Paragraph = props => {
|
|
|
96162
96449
|
};
|
|
96163
96450
|
|
|
96164
96451
|
installImportMetaCssBuild(import.meta);
|
|
96165
|
-
const css$
|
|
96452
|
+
const css$6 = /* css */`.navi_text_box {
|
|
96166
96453
|
align-items: flex-start;
|
|
96167
96454
|
min-width: 0;
|
|
96168
96455
|
}
|
|
@@ -96204,7 +96491,7 @@ const TextBox = ({
|
|
|
96204
96491
|
children,
|
|
96205
96492
|
...rest
|
|
96206
96493
|
}) => {
|
|
96207
|
-
import.meta.css = [css$
|
|
96494
|
+
import.meta.css = [css$6, "@jsenv/navi/src/text/text_box.jsx"];
|
|
96208
96495
|
const boxRef = useRef(null);
|
|
96209
96496
|
const contentRef = useRef(null);
|
|
96210
96497
|
useLayoutEffect(() => {
|
|
@@ -96250,40 +96537,6 @@ const adjustWidth = (boxEl, contentEl) => {
|
|
|
96250
96537
|
contentEl.style.width = `${Math.ceil(optimalWidth)}px`;
|
|
96251
96538
|
};
|
|
96252
96539
|
|
|
96253
|
-
installImportMetaCssBuild(import.meta);
|
|
96254
|
-
const css$6 = /* css */`.navi_message_box {
|
|
96255
|
-
& .navi_title {
|
|
96256
|
-
margin-top: 0;
|
|
96257
|
-
margin-bottom: var(--navi-s);
|
|
96258
|
-
color: var(--x-message-color);
|
|
96259
|
-
}
|
|
96260
|
-
}
|
|
96261
|
-
`;
|
|
96262
|
-
const Title = props => {
|
|
96263
|
-
import.meta.css = [css$6, "@jsenv/navi/src/text/title.jsx"];
|
|
96264
|
-
const messageBoxStatus = useContext(MessageBoxStatusContext);
|
|
96265
|
-
const innerAs = props.as || (messageBoxStatus ? "h4" : "h1");
|
|
96266
|
-
const titleLevel = parseInt(innerAs.slice(1));
|
|
96267
|
-
const reportTitleToMessageBox = useContext(MessageBoxReportTitleChildContext);
|
|
96268
|
-
reportTitleToMessageBox?.(true);
|
|
96269
|
-
return jsx(TitleLevelContext.Provider, {
|
|
96270
|
-
value: titleLevel,
|
|
96271
|
-
children: jsx(Text, {
|
|
96272
|
-
bold: true,
|
|
96273
|
-
className: withPropsClassName("navi_title"),
|
|
96274
|
-
as: messageBoxStatus ? "h4" : "h1",
|
|
96275
|
-
...props,
|
|
96276
|
-
pseudoClasses: TitlePseudoClasses,
|
|
96277
|
-
children: props.children
|
|
96278
|
-
})
|
|
96279
|
-
});
|
|
96280
|
-
};
|
|
96281
|
-
const TitleLevelContext = createContext();
|
|
96282
|
-
const useTitleLevel = () => {
|
|
96283
|
-
return useContext(TitleLevelContext);
|
|
96284
|
-
};
|
|
96285
|
-
const TitlePseudoClasses = [":hover"];
|
|
96286
|
-
|
|
96287
96540
|
installImportMetaCssBuild(import.meta);
|
|
96288
96541
|
const css$5 = /* css */`@keyframes navi_image_shimmer {
|
|
96289
96542
|
0% {
|