@jsenv/navi 0.29.154 → 0.29.156
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/jsenv_navi.js +72 -8
- package/dist/jsenv_navi.js.map +10 -6
- package/docs/testid.md +47 -1
- package/package.json +1 -1
package/dist/jsenv_navi.js
CHANGED
|
@@ -5432,6 +5432,11 @@ const CONTROL_ATTRIBUTE_SET = new Set([
|
|
|
5432
5432
|
"spellcheck",
|
|
5433
5433
|
"autoCorrect",
|
|
5434
5434
|
"aria-controls",
|
|
5435
|
+
// The name goes where the role is: the root box has none, so an aria-label
|
|
5436
|
+
// left on it names nothing at all, while the host is what the user focuses
|
|
5437
|
+
// and what a screen reader announces (and what getByRole({ name }) reads).
|
|
5438
|
+
"aria-label",
|
|
5439
|
+
"aria-labelledby",
|
|
5435
5440
|
"tabIndex",
|
|
5436
5441
|
"command",
|
|
5437
5442
|
"commandFor",
|
|
@@ -6419,6 +6424,11 @@ const css$12 = /* css */`
|
|
|
6419
6424
|
* @param {Object} options - Configuration options
|
|
6420
6425
|
* @param {HTMLElement} [options.anchorElement] - Element the callout should follow. If not provided or too big, callout will be centered in viewport
|
|
6421
6426
|
* @param {string} [options.status=""] - Callout status: "info" | "warning" | "error" | "success"
|
|
6427
|
+
* @param {string} [options.testId] - `data-testid` on the callout element. The callout is
|
|
6428
|
+
* drawn by navi, so nothing the caller renders can carry the name a test needs — same
|
|
6429
|
+
* situation as a picker's `popupTestId` (see docs/testid.md). A role is already there
|
|
6430
|
+
* for free (`status`/`alert`); reach for this when the role is not enough to tell two
|
|
6431
|
+
* callouts apart.
|
|
6422
6432
|
* @param {Function} [options.onClose] - Callback when callout is closed
|
|
6423
6433
|
* @param {boolean} [options.closeOnClickOutside] - Whether to close on outside clicks (defaults to true for "info" status)
|
|
6424
6434
|
* @param {boolean} [options.icon=true] - Whether the status icon is shown beside the message.
|
|
@@ -6465,6 +6475,7 @@ const openCallout = (message, {
|
|
|
6465
6475
|
// "success" - positive feedback (e.g., "Changes saved successfully")
|
|
6466
6476
|
// "" - neutral information
|
|
6467
6477
|
status = "",
|
|
6478
|
+
testId,
|
|
6468
6479
|
onClose,
|
|
6469
6480
|
closeOnClickOutside = status === "info",
|
|
6470
6481
|
closeOnFocusLeave = closeOnClickOutside,
|
|
@@ -6642,6 +6653,15 @@ const openCallout = (message, {
|
|
|
6642
6653
|
calloutElement.removeAttribute("data-icon");
|
|
6643
6654
|
}
|
|
6644
6655
|
}
|
|
6656
|
+
if (Object.hasOwn(options, "testId")) {
|
|
6657
|
+
// Per message, like the cross below: a callout is a slot several things
|
|
6658
|
+
// speak through, and the one speaking is what a test is looking at.
|
|
6659
|
+
if (options.testId) {
|
|
6660
|
+
calloutElement.setAttribute("data-testid", options.testId);
|
|
6661
|
+
} else {
|
|
6662
|
+
calloutElement.removeAttribute("data-testid");
|
|
6663
|
+
}
|
|
6664
|
+
}
|
|
6645
6665
|
if (Object.hasOwn(options, "closeButton")) {
|
|
6646
6666
|
// Per message rather than per callout: what replaces a message (a
|
|
6647
6667
|
// constraint taking over a tooltip's callout) brings its own cross back.
|
|
@@ -7042,6 +7062,7 @@ const openCallout = (message, {
|
|
|
7042
7062
|
}
|
|
7043
7063
|
update(message, {
|
|
7044
7064
|
status,
|
|
7065
|
+
testId,
|
|
7045
7066
|
icon,
|
|
7046
7067
|
closeButton
|
|
7047
7068
|
});
|
|
@@ -7073,12 +7094,19 @@ const ARROW_SPACING = 8;
|
|
|
7073
7094
|
// (closest "[aria-expanded]", see commands.js): a button inside the callout
|
|
7074
7095
|
// closes the callout, not the picker or dialog around it. Never "false" — a
|
|
7075
7096
|
// closed callout is removed, not kept.
|
|
7097
|
+
//
|
|
7098
|
+
// role="status" is the floor, not the final value: a message appearing without
|
|
7099
|
+
// the user asking for it is a live region, and a callout carrying no status at
|
|
7100
|
+
// all still owes one. A status raises it (the addStatusEffect swapping in
|
|
7101
|
+
// "alert" for warning/error), and it is also the name a test reaches the
|
|
7102
|
+
// callout by — navi's classes and ids are not a contract (docs/testid.md).
|
|
7076
7103
|
const calloutTemplate = /* html */`
|
|
7077
7104
|
<div
|
|
7078
7105
|
class="navi_callout"
|
|
7079
7106
|
popover="manual"
|
|
7080
7107
|
navi-out-of-flow=""
|
|
7081
7108
|
aria-expanded="true"
|
|
7109
|
+
role="status"
|
|
7082
7110
|
>
|
|
7083
7111
|
<div class="navi_callout_box">
|
|
7084
7112
|
<div class="navi_callout_frame"></div>
|
|
@@ -7691,7 +7719,7 @@ const generateSvgWithoutArrow = (width, height) => {
|
|
|
7691
7719
|
*
|
|
7692
7720
|
* Usage:
|
|
7693
7721
|
* const myToken = createOpenToken();
|
|
7694
|
-
* calloutManager.addOpenToken(myToken, { message, status, anchorElement, event, skipFocus, onClose });
|
|
7722
|
+
* calloutManager.addOpenToken(myToken, { message, status, testId, anchorElement, event, skipFocus, onClose });
|
|
7695
7723
|
* calloutManager.removeOpenToken(myToken, event);
|
|
7696
7724
|
* calloutManager.requestCloseCallout(event, debugReason); // force-close all
|
|
7697
7725
|
* calloutManager.callout // current open callout or null
|
|
@@ -7737,6 +7765,7 @@ const createCalloutManager = (
|
|
|
7737
7765
|
const [, remainingTokenData] = tokens.entries().next().value;
|
|
7738
7766
|
callout.update(remainingTokenData.message, {
|
|
7739
7767
|
status: remainingTokenData.status,
|
|
7768
|
+
testId: remainingTokenData.testId,
|
|
7740
7769
|
icon: remainingTokenData.icon,
|
|
7741
7770
|
closeButton: remainingTokenData.closeButton,
|
|
7742
7771
|
});
|
|
@@ -7763,6 +7792,7 @@ const createCalloutManager = (
|
|
|
7763
7792
|
{
|
|
7764
7793
|
message,
|
|
7765
7794
|
status,
|
|
7795
|
+
testId,
|
|
7766
7796
|
icon,
|
|
7767
7797
|
closeButton,
|
|
7768
7798
|
anchorElement,
|
|
@@ -7777,12 +7807,13 @@ const createCalloutManager = (
|
|
|
7777
7807
|
}
|
|
7778
7808
|
const calloutOptions = {
|
|
7779
7809
|
status,
|
|
7810
|
+
testId,
|
|
7780
7811
|
icon,
|
|
7781
7812
|
closeButton,
|
|
7782
7813
|
closeOnClickOutside: status !== "error",
|
|
7783
7814
|
};
|
|
7784
7815
|
|
|
7785
|
-
tokens.set(token, { message, status, icon, closeButton, onClose });
|
|
7816
|
+
tokens.set(token, { message, status, testId, icon, closeButton, onClose });
|
|
7786
7817
|
if (callout) {
|
|
7787
7818
|
callout.update(message, calloutOptions);
|
|
7788
7819
|
return;
|
|
@@ -59308,6 +59339,7 @@ const PickerContentInsidePopup = props => {
|
|
|
59308
59339
|
children: isCallout ? jsx(PickerCalloutPopup, {
|
|
59309
59340
|
...popupProps,
|
|
59310
59341
|
pickerRef: props.ref,
|
|
59342
|
+
testId: popupTestId,
|
|
59311
59343
|
status: calloutStatus,
|
|
59312
59344
|
icon: calloutIcon,
|
|
59313
59345
|
closeButton: calloutCloseButton,
|
|
@@ -59372,6 +59404,7 @@ const PickerCalloutPopup = ({
|
|
|
59372
59404
|
anchor,
|
|
59373
59405
|
openController,
|
|
59374
59406
|
pickerRef,
|
|
59407
|
+
testId,
|
|
59375
59408
|
status,
|
|
59376
59409
|
icon,
|
|
59377
59410
|
closeButton,
|
|
@@ -59397,6 +59430,10 @@ const PickerCalloutPopup = ({
|
|
|
59397
59430
|
const anchorElement = anchor === pickerRef ? undefined : anchor && "current" in anchor ? anchor.current : anchor;
|
|
59398
59431
|
calloutManager.addOpenToken(PICKER_CALLOUT_CONTENT_TOKEN, {
|
|
59399
59432
|
message: hostRef.current,
|
|
59433
|
+
// The popup a `popupTestId` names is this callout: it is the surface the
|
|
59434
|
+
// picker opens, drawn by navi, so it is the one thing the caller cannot
|
|
59435
|
+
// name from its own children.
|
|
59436
|
+
testId,
|
|
59400
59437
|
// "none" is the picker's word for it; the callout's is no status at all.
|
|
59401
59438
|
status: status === "none" ? undefined : status,
|
|
59402
59439
|
icon,
|
|
@@ -66945,6 +66982,10 @@ installImportMetaCssBuild(import.meta);const css$t = /* css */`@layer navi {
|
|
|
66945
66982
|
--x-picker-padding-right: var(--picker-padding-right, var(--picker-padding-x, var(--picker-padding, var(--picker-padding-x-default))));
|
|
66946
66983
|
--x-picker-padding-left: var(--picker-padding-left, var(--picker-padding-x, var(--picker-padding, var(--picker-padding-x-default))));
|
|
66947
66984
|
--x-picker-padding-bottom: var(--picker-padding-bottom, var(--picker-padding-y, var(--picker-padding, var(--picker-padding-y-default))));
|
|
66985
|
+
--x-picker-press-padding-top: var(--picker-press-padding-top, var(--picker-press-padding-y, var(--picker-press-padding, 0px)));
|
|
66986
|
+
--x-picker-press-padding-right: var(--picker-press-padding-right, var(--picker-press-padding-x, var(--picker-press-padding, 0px)));
|
|
66987
|
+
--x-picker-press-padding-bottom: var(--picker-press-padding-bottom, var(--picker-press-padding-y, var(--picker-press-padding, 0px)));
|
|
66988
|
+
--x-picker-press-padding-left: var(--picker-press-padding-left, var(--picker-press-padding-x, var(--picker-press-padding, 0px)));
|
|
66948
66989
|
--x-picker-color: var(--picker-color);
|
|
66949
66990
|
--x-picker-icon-color: var(--picker-icon-color);
|
|
66950
66991
|
--x-picker-align-x: var(--picker-align-x, var(--picker-align-x-default));
|
|
@@ -67091,14 +67132,17 @@ installImportMetaCssBuild(import.meta);const css$t = /* css */`@layer navi {
|
|
|
67091
67132
|
|
|
67092
67133
|
&[navi-ui-custom] {
|
|
67093
67134
|
& .navi_picker_input {
|
|
67094
|
-
top: calc(-1 * var(--picker-border-width));
|
|
67095
|
-
right: calc(-1 *
|
|
67096
|
-
|
|
67097
|
-
|
|
67098
|
-
|
|
67099
|
-
|
|
67135
|
+
top: calc(-1 * (var(--picker-border-width) + var(--x-picker-press-padding-top)));
|
|
67136
|
+
right: calc(-1 *
|
|
67137
|
+
(var(--picker-border-width) + var(--x-picker-press-padding-right)));
|
|
67138
|
+
bottom: calc(-1 *
|
|
67139
|
+
(var(--picker-border-width) + var(--x-picker-press-padding-bottom)));
|
|
67140
|
+
left: calc(-1 * (var(--picker-border-width) + var(--x-picker-press-padding-left)));
|
|
67100
67141
|
width: auto;
|
|
67101
67142
|
height: auto;
|
|
67143
|
+
font: inherit;
|
|
67144
|
+
opacity: 0;
|
|
67145
|
+
appearance: none;
|
|
67102
67146
|
position: absolute;
|
|
67103
67147
|
}
|
|
67104
67148
|
}
|
|
@@ -67278,6 +67322,12 @@ const PickerButton = props => {
|
|
|
67278
67322
|
// keywords have to become lengths here — "s" reaching CSS untouched makes
|
|
67279
67323
|
// the declaration invalid, silently, and the gap just goes away.
|
|
67280
67324
|
props.slotSpacing = resolveSpacingSize(props.slotSpacing);
|
|
67325
|
+
for (const pressPaddingPropName of PRESS_PADDING_PROP_NAMES) {
|
|
67326
|
+
const pressPadding = props[pressPaddingPropName];
|
|
67327
|
+
if (pressPadding !== undefined) {
|
|
67328
|
+
props[pressPaddingPropName] = stringifySpacingStyle(pressPadding);
|
|
67329
|
+
}
|
|
67330
|
+
}
|
|
67281
67331
|
const {
|
|
67282
67332
|
ref,
|
|
67283
67333
|
variant,
|
|
@@ -67836,6 +67886,13 @@ const isOpeningKeyboardOnMobile = type => {
|
|
|
67836
67886
|
const NON_MOBILE_KEYBOARD_TYPES = new Set(["date", "month", "week", "time", "datetime-local", "color"]);
|
|
67837
67887
|
const PICKER_BUTTON_PSEUDO_CLASSES = [":hover", ":focus", ":focus-visible", ":focus-within", ":read-only", ":disabled", ":-navi-loading", ":-navi-expanded", ":-navi-has-value"];
|
|
67838
67888
|
const PickerInputPseudoClasses = [":focus", ":focus-visible", ":read-only", ":disabled", ":-navi-loading", ":-navi-has-value", ":-navi-expanded"];
|
|
67889
|
+
|
|
67890
|
+
// Spacing props that are not the names of real CSS styles, so Box hands them to
|
|
67891
|
+
// the custom property untouched: a size keyword would reach CSS as the word "s"
|
|
67892
|
+
// and a number as a unitless one, either of which makes the calc() using it
|
|
67893
|
+
// invalid and drops the press area back to the box. Hence the pass in
|
|
67894
|
+
// PickerButton, which turns them into lengths.
|
|
67895
|
+
const PRESS_PADDING_PROP_NAMES = ["pressPadding", "pressPaddingX", "pressPaddingY", "pressPaddingTop", "pressPaddingRight", "pressPaddingBottom", "pressPaddingLeft"];
|
|
67839
67896
|
const PickerStyleCSSVars = {
|
|
67840
67897
|
"outlineWidth": "--picker-outline-width",
|
|
67841
67898
|
"borderWidth": "--picker-border-width",
|
|
@@ -67849,6 +67906,13 @@ const PickerStyleCSSVars = {
|
|
|
67849
67906
|
"popupBorderRadius": "--picker-popup-border-radius",
|
|
67850
67907
|
"dialogBorderWidth": "--picker-dialog-border-width",
|
|
67851
67908
|
"slotSpacing": "--picker-slot-spacing",
|
|
67909
|
+
"pressPadding": "--picker-press-padding",
|
|
67910
|
+
"pressPaddingX": "--picker-press-padding-x",
|
|
67911
|
+
"pressPaddingY": "--picker-press-padding-y",
|
|
67912
|
+
"pressPaddingTop": "--picker-press-padding-top",
|
|
67913
|
+
"pressPaddingRight": "--picker-press-padding-right",
|
|
67914
|
+
"pressPaddingBottom": "--picker-press-padding-bottom",
|
|
67915
|
+
"pressPaddingLeft": "--picker-press-padding-left",
|
|
67852
67916
|
// alignX/alignY resolve to these two on a flex-x box; naming the CSS style
|
|
67853
67917
|
// (not the prop) is what styleCSSVars matches, so justifyContent/alignItems
|
|
67854
67918
|
// passed directly land in the same variables.
|