@jsenv/navi 0.29.305 → 0.29.307
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 +298 -197
- package/dist/dev/jsenv_navi.js.map +13 -13
- package/dist/dev/jsenv_navi_side_effects.js +2 -0
- package/dist/dev/jsenv_navi_side_effects.js.map +2 -2
- package/dist/jsenv_navi.js +257 -188
- package/dist/jsenv_navi.js.map +13 -13
- package/dist/jsenv_navi_side_effects.js +2 -0
- package/dist/jsenv_navi_side_effects.js.map +2 -2
- package/docs/dialog_shape.md +2 -2
- package/docs/popup_backdrop.md +28 -5
- package/docs/popup_open.md +6 -2
- package/package.json +3 -3
package/dist/dev/jsenv_navi.js
CHANGED
|
@@ -12,7 +12,7 @@ import { useErrorBoundary, useLayoutEffect, useContext, useCallback, useRef, use
|
|
|
12
12
|
import { humanizeI18n, prefixFirstAndIndentRemainingLines, setRuntimeLangSource, formatDuration, formatMonth, formatDay, resolveTimeRangePrecision, formatDatePlaceholder, toDate, getRelativeDay, formatDayRelative, formatMonthPlaceholder, formatWeekPlaceholder, formatDatetimePlaceholder, formatDatetime, toTimeOfDay, formatTimeOfDay, formatTime, formatMinuteDuration, formatSecondDuration, formatHourDuration, formatTimeRelative, formatNumber, interpolateText, installInterpolateJsx } from "@jsenv/humanize";
|
|
13
13
|
export { createI18n, formatDatetime, formatDay, formatDayRelative, formatDuration, formatHourDuration, formatMinuteDuration, formatMonth, formatNumber, formatSecondDuration, formatTime, formatTimeOfDay, formatTimeRange, formatTimeRelative, interpolateText } from "@jsenv/humanize";
|
|
14
14
|
import { jsxs, jsx, Fragment } from "preact/jsx-runtime";
|
|
15
|
-
import { durationContainsNaN, compareTwoDurations, durationToSeconds, DISPLAYABLE_RULE, MAX_LINE_BREAKS_RULE, NO_EMOJI_RULE, SINGLE_SPACE_RULE, createValidity, resolveCharClass, getCharClassMessageKey, compileCharClassAnchored, compileCharClass, CHAR_CLASS_PRESETS, parseDuration, durationToISOString } from "@jsenv/validity";
|
|
15
|
+
import { TYPE_RULE, durationContainsNaN, compareTwoDurations, durationToSeconds, DISPLAYABLE_RULE, MAX_LINE_BREAKS_RULE, NO_EMOJI_RULE, SINGLE_SPACE_RULE, createValidity, resolveCharClass, getCharClassMessageKey, compileCharClassAnchored, compileCharClass, CHAR_CLASS_PRESETS, parseDuration, durationToISOString } from "@jsenv/validity";
|
|
16
16
|
export { compareTwoDurations, durationContainsNaN, durationToHours, durationToISOString, durationToMinutes, durationToNumber, durationToSeconds, durationToString, parseDuration } from "@jsenv/validity";
|
|
17
17
|
import { Suspense, createPortal, forwardRef } from "preact/compat";
|
|
18
18
|
|
|
@@ -4947,6 +4947,11 @@ const radioControllersByName = new Map();
|
|
|
4947
4947
|
// The controller id is used as key — if the controller has no id, the value is not registered.
|
|
4948
4948
|
const naviJsRegistry = new Map();
|
|
4949
4949
|
|
|
4950
|
+
// Controllers already reported for sharing their id with another one. An id is
|
|
4951
|
+
// stated on every render of its control, so without this the warning below
|
|
4952
|
+
// would repeat for as long as both controls are on screen.
|
|
4953
|
+
const controllersWarned = new WeakSet();
|
|
4954
|
+
|
|
4950
4955
|
const getUIStateControllerById = (id) => controllersById.get(id);
|
|
4951
4956
|
const getRadioSiblings = (radioUIStateController) => {
|
|
4952
4957
|
const siblings = radioControllersByName.get(radioUIStateController.name);
|
|
@@ -4984,10 +4989,15 @@ const onUIStateControllerCreated = (uiStateController) => {
|
|
|
4984
4989
|
if (id) {
|
|
4985
4990
|
{
|
|
4986
4991
|
const existing = controllersById.get(id);
|
|
4987
|
-
if (
|
|
4992
|
+
if (
|
|
4993
|
+
existing &&
|
|
4994
|
+
existing !== uiStateController &&
|
|
4995
|
+
!controllersWarned.has(uiStateController)
|
|
4996
|
+
) {
|
|
4997
|
+
controllersWarned.add(uiStateController);
|
|
4988
4998
|
console.warn(
|
|
4989
4999
|
`[navi] Two controls share the same id "${id}" ("${existing.controlType}" and "${controlType}"). ` +
|
|
4990
|
-
`
|
|
5000
|
+
`The id resolves to whichever of them rendered last, so the other one is unreachable through it (undefined uiState, dead picker buttons). ` +
|
|
4991
5001
|
`Common causes: several controls inside a single <Field> (the Field provides one id via context and every control consumes it — put each control in its own <Field>, or give one an explicit id), ` +
|
|
4992
5002
|
`or the same content mounted twice (e.g. two popups sharing an id prefix while both hold their content).`,
|
|
4993
5003
|
);
|
|
@@ -5020,8 +5030,15 @@ const onUIStateControllerCreated = (uiStateController) => {
|
|
|
5020
5030
|
const onUIStateControllerDestroyed = (uiStateController) => {
|
|
5021
5031
|
const { id, name, controlType } = uiStateController;
|
|
5022
5032
|
if (id) {
|
|
5023
|
-
|
|
5024
|
-
|
|
5033
|
+
// Only the controller the id currently points at may take the entry away:
|
|
5034
|
+
// when two controls share an id, the one leaving would otherwise unregister
|
|
5035
|
+
// the one staying (see the warning in onUIStateControllerCreated), and the
|
|
5036
|
+
// same holds while a control is being replaced by its successor, which
|
|
5037
|
+
// registers during its render, before this cleanup runs.
|
|
5038
|
+
if (controllersById.get(id) === uiStateController) {
|
|
5039
|
+
controllersById.delete(id);
|
|
5040
|
+
naviJsRegistry.delete(id);
|
|
5041
|
+
}
|
|
5025
5042
|
}
|
|
5026
5043
|
const proxyFor = uiStateController.props["navi-control-proxy-for"];
|
|
5027
5044
|
if (proxyFor) {
|
|
@@ -8427,6 +8444,75 @@ const languagesSignal = computed(() => {
|
|
|
8427
8444
|
// (nor the "languagechange" listener above).
|
|
8428
8445
|
setRuntimeLangSource(() => languagesSignal.value);
|
|
8429
8446
|
|
|
8447
|
+
/**
|
|
8448
|
+
* Where navi meets @jsenv/validity.
|
|
8449
|
+
*
|
|
8450
|
+
* validity names a refusal with a key and its parameters rather than a
|
|
8451
|
+
* sentence, so that a field and a server can refuse in the same words in the
|
|
8452
|
+
* language of the person reading. navi is one of those two callers: it says the
|
|
8453
|
+
* sentence, in the browser, through `naviI18n`. The keys line up on purpose —
|
|
8454
|
+
* validity's `"single_space.start"` is navi's `"constraint.single_space.start"`
|
|
8455
|
+
* — so overriding a message is looking up one key, not going through a
|
|
8456
|
+
* translation table.
|
|
8457
|
+
*
|
|
8458
|
+
* The other direction is `constraintFromValidityRule`: a rule an app wrote for
|
|
8459
|
+
* its server, worn by a control as a constraint.
|
|
8460
|
+
*/
|
|
8461
|
+
|
|
8462
|
+
|
|
8463
|
+
/**
|
|
8464
|
+
* Turns a @jsenv/validity rule into a constraint a control can wear, so an app
|
|
8465
|
+
* rule written once — in the package its server reads too — is checked on both
|
|
8466
|
+
* sides instead of being written twice.
|
|
8467
|
+
*
|
|
8468
|
+
* @param {object} rule
|
|
8469
|
+
* `{ name, applyOn(ruleValue, value, ruleConfig) }`, the same object passed
|
|
8470
|
+
* to `createValidity({ rules })`.
|
|
8471
|
+
* @param {object} [ruleConfig]
|
|
8472
|
+
* What parameterizes the rule, under its own name — `{ maxWords: 40 }` for a
|
|
8473
|
+
* rule named `maxWords`. Pass `formatMessage` here to say the refusal through
|
|
8474
|
+
* the app's own i18n; without it the key is looked up in `naviI18n` under
|
|
8475
|
+
* `constraint.<key>`, and a rule answering with a finished sentence is shown
|
|
8476
|
+
* as-is.
|
|
8477
|
+
*
|
|
8478
|
+
* Call it once, at module level: a constraint rebuilt on every render is a new
|
|
8479
|
+
* object on every check.
|
|
8480
|
+
*/
|
|
8481
|
+
const constraintFromValidityRule = (rule, ruleConfig = {}) => {
|
|
8482
|
+
const { formatMessage, ...ruleParams } = ruleConfig;
|
|
8483
|
+
return {
|
|
8484
|
+
name: rule.name,
|
|
8485
|
+
check: (field) => {
|
|
8486
|
+
const result = rule.applyOn(
|
|
8487
|
+
ruleParams[rule.name],
|
|
8488
|
+
field.uiState,
|
|
8489
|
+
ruleParams,
|
|
8490
|
+
);
|
|
8491
|
+
if (!result) {
|
|
8492
|
+
return null;
|
|
8493
|
+
}
|
|
8494
|
+
if (typeof result === "string") {
|
|
8495
|
+
return result;
|
|
8496
|
+
}
|
|
8497
|
+
if (formatMessage) {
|
|
8498
|
+
return formatMessage(result.key, result.params);
|
|
8499
|
+
}
|
|
8500
|
+
return naviI18nFromValidityMessage(result);
|
|
8501
|
+
},
|
|
8502
|
+
};
|
|
8503
|
+
};
|
|
8504
|
+
|
|
8505
|
+
const naviI18nFromValidityMessage = ({ key, params }) => {
|
|
8506
|
+
if (params && typeof params.max === "number") {
|
|
8507
|
+
// Lets a template pluralize on the bound it names: "[max] retour[s]".
|
|
8508
|
+
return naviI18n(`constraint.${key}`, {
|
|
8509
|
+
...params,
|
|
8510
|
+
s: params.max > 1 ? "s" : "",
|
|
8511
|
+
});
|
|
8512
|
+
}
|
|
8513
|
+
return naviI18n(`constraint.${key}`, params);
|
|
8514
|
+
};
|
|
8515
|
+
|
|
8430
8516
|
/**
|
|
8431
8517
|
* https://developer.mozilla.org/en-US/docs/Web/HTML/Guides/Constraint_validation
|
|
8432
8518
|
*/
|
|
@@ -8576,9 +8662,8 @@ const PATTERN_CONSTRAINT = {
|
|
|
8576
8662
|
};
|
|
8577
8663
|
CONSTRAINT_ATTRIBUTE_SET.add("pattern");
|
|
8578
8664
|
|
|
8579
|
-
//
|
|
8580
|
-
|
|
8581
|
-
/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
|
|
8665
|
+
// What an address is, is @jsenv/validity's `type: "email"`: a server checking
|
|
8666
|
+
// the value again refuses it for the same reason and in the same words.
|
|
8582
8667
|
const TYPE_EMAIL_CONSTRAINT = {
|
|
8583
8668
|
name: "type_email",
|
|
8584
8669
|
messageAttribute: "data-type-message",
|
|
@@ -8592,14 +8677,11 @@ const TYPE_EMAIL_CONSTRAINT = {
|
|
|
8592
8677
|
if (!valueAsString) {
|
|
8593
8678
|
return null;
|
|
8594
8679
|
}
|
|
8595
|
-
|
|
8680
|
+
const result = TYPE_RULE.applyOn("email", valueAsString);
|
|
8681
|
+
if (!result) {
|
|
8596
8682
|
return null;
|
|
8597
8683
|
}
|
|
8598
|
-
|
|
8599
|
-
if (!valueAsString.includes("@")) {
|
|
8600
|
-
return naviI18n("constraint.type.email.at", { value: valueAsString });
|
|
8601
|
-
}
|
|
8602
|
-
return naviI18n("constraint.type.email.invalid");
|
|
8684
|
+
return naviI18nFromValidityMessage(result);
|
|
8603
8685
|
},
|
|
8604
8686
|
};
|
|
8605
8687
|
|
|
@@ -11900,75 +11982,6 @@ const isFunctionButNotAnActionFunction = (action) => {
|
|
|
11900
11982
|
return typeof action === "function" && !action.isAction;
|
|
11901
11983
|
};
|
|
11902
11984
|
|
|
11903
|
-
/**
|
|
11904
|
-
* Where navi meets @jsenv/validity.
|
|
11905
|
-
*
|
|
11906
|
-
* validity names a refusal with a key and its parameters rather than a
|
|
11907
|
-
* sentence, so that a field and a server can refuse in the same words in the
|
|
11908
|
-
* language of the person reading. navi is one of those two callers: it says the
|
|
11909
|
-
* sentence, in the browser, through `naviI18n`. The keys line up on purpose —
|
|
11910
|
-
* validity's `"single_space.start"` is navi's `"constraint.single_space.start"`
|
|
11911
|
-
* — so overriding a message is looking up one key, not going through a
|
|
11912
|
-
* translation table.
|
|
11913
|
-
*
|
|
11914
|
-
* The other direction is `constraintFromValidityRule`: a rule an app wrote for
|
|
11915
|
-
* its server, worn by a control as a constraint.
|
|
11916
|
-
*/
|
|
11917
|
-
|
|
11918
|
-
|
|
11919
|
-
/**
|
|
11920
|
-
* Turns a @jsenv/validity rule into a constraint a control can wear, so an app
|
|
11921
|
-
* rule written once — in the package its server reads too — is checked on both
|
|
11922
|
-
* sides instead of being written twice.
|
|
11923
|
-
*
|
|
11924
|
-
* @param {object} rule
|
|
11925
|
-
* `{ name, applyOn(ruleValue, value, ruleConfig) }`, the same object passed
|
|
11926
|
-
* to `createValidity({ rules })`.
|
|
11927
|
-
* @param {object} [ruleConfig]
|
|
11928
|
-
* What parameterizes the rule, under its own name — `{ maxWords: 40 }` for a
|
|
11929
|
-
* rule named `maxWords`. Pass `formatMessage` here to say the refusal through
|
|
11930
|
-
* the app's own i18n; without it the key is looked up in `naviI18n` under
|
|
11931
|
-
* `constraint.<key>`, and a rule answering with a finished sentence is shown
|
|
11932
|
-
* as-is.
|
|
11933
|
-
*
|
|
11934
|
-
* Call it once, at module level: a constraint rebuilt on every render is a new
|
|
11935
|
-
* object on every check.
|
|
11936
|
-
*/
|
|
11937
|
-
const constraintFromValidityRule = (rule, ruleConfig = {}) => {
|
|
11938
|
-
const { formatMessage, ...ruleParams } = ruleConfig;
|
|
11939
|
-
return {
|
|
11940
|
-
name: rule.name,
|
|
11941
|
-
check: (field) => {
|
|
11942
|
-
const result = rule.applyOn(
|
|
11943
|
-
ruleParams[rule.name],
|
|
11944
|
-
field.uiState,
|
|
11945
|
-
ruleParams,
|
|
11946
|
-
);
|
|
11947
|
-
if (!result) {
|
|
11948
|
-
return null;
|
|
11949
|
-
}
|
|
11950
|
-
if (typeof result === "string") {
|
|
11951
|
-
return result;
|
|
11952
|
-
}
|
|
11953
|
-
if (formatMessage) {
|
|
11954
|
-
return formatMessage(result.key, result.params);
|
|
11955
|
-
}
|
|
11956
|
-
return naviI18nFromValidityMessage(result);
|
|
11957
|
-
},
|
|
11958
|
-
};
|
|
11959
|
-
};
|
|
11960
|
-
|
|
11961
|
-
const naviI18nFromValidityMessage = ({ key, params }) => {
|
|
11962
|
-
if (params && typeof params.max === "number") {
|
|
11963
|
-
// Lets a template pluralize on the bound it names: "[max] retour[s]".
|
|
11964
|
-
return naviI18n(`constraint.${key}`, {
|
|
11965
|
-
...params,
|
|
11966
|
-
s: params.max > 1 ? "s" : "",
|
|
11967
|
-
});
|
|
11968
|
-
}
|
|
11969
|
-
return naviI18n(`constraint.${key}`, params);
|
|
11970
|
-
};
|
|
11971
|
-
|
|
11972
11985
|
/**
|
|
11973
11986
|
* `data-displayable` — the value must be something the layout can actually
|
|
11974
11987
|
* draw. What it refuses and why lives in @jsenv/validity's DISPLAYABLE_RULE:
|
|
@@ -35277,17 +35290,21 @@ const useUIStateController = (
|
|
|
35277
35290
|
if (el) {
|
|
35278
35291
|
el.__uiStateController__ = controller;
|
|
35279
35292
|
}
|
|
35280
|
-
// Re-register so the radio registry stays in sync when props.ref changes
|
|
35281
|
-
// identity (e.g. across a Suspense boundary). The render-phase call in
|
|
35282
|
-
// control_hooks.jsx handles the initial mount; this call handles re-runs.
|
|
35283
|
-
onUIStateControllerCreated(controller);
|
|
35284
35293
|
return () => {
|
|
35285
35294
|
if (el && el.__uiStateController__ === controller) {
|
|
35286
35295
|
delete el.__uiStateController__;
|
|
35287
35296
|
}
|
|
35288
|
-
onUIStateControllerDestroyed(controller);
|
|
35289
35297
|
};
|
|
35290
35298
|
}, [controllerRef]);
|
|
35299
|
+
// The registry entry lives as long as the component does. Registration is
|
|
35300
|
+
// done by the render (see useInteractiveProps); this cleanup is the only
|
|
35301
|
+
// thing that takes the entry away, so it must not follow the ref: a ref
|
|
35302
|
+
// identity change would run it right after the render that registered.
|
|
35303
|
+
useLayoutEffect(() => {
|
|
35304
|
+
return () => {
|
|
35305
|
+
onUIStateControllerDestroyed(controller);
|
|
35306
|
+
};
|
|
35307
|
+
}, []);
|
|
35291
35308
|
|
|
35292
35309
|
const { parentUIStateController: parentController } = scope;
|
|
35293
35310
|
useLayoutEffect(() => {
|
|
@@ -38916,11 +38933,13 @@ const useInteractiveProps = (props, {
|
|
|
38916
38933
|
// an action's own completion side effect — has to read the signal to get an
|
|
38917
38934
|
// answer that is not one frame late (see BUSY_CONSTRAINT).
|
|
38918
38935
|
uiStateController.boundAction = boundAction;
|
|
38936
|
+
// "This id is that controller", stated on every render: a Suspense boundary
|
|
38937
|
+
// parking a subtree runs every hook cleanup below it — the unregistration
|
|
38938
|
+
// included — while the controllers themselves survive, and readers look a
|
|
38939
|
+
// controller up by id while rendering, before any effect can run again.
|
|
38940
|
+
// Placed after controlHostProps is set, which the constraints read.
|
|
38941
|
+
onUIStateControllerCreated(uiStateController);
|
|
38919
38942
|
if (firstRender) {
|
|
38920
|
-
// Deferred from the factory so these run after controlHostProps is set.
|
|
38921
|
-
// Constraints like READONLY_CONSTRAINT and findControlProxyTargetController
|
|
38922
|
-
// read controlHostProps — calling these earlier would throw or produce wrong results.
|
|
38923
|
-
onUIStateControllerCreated(uiStateController);
|
|
38924
38943
|
uiStateController.rules.validation.checkValidity();
|
|
38925
38944
|
}
|
|
38926
38945
|
return [controlRootProps, controlHostProps];
|
|
@@ -48839,10 +48858,11 @@ const ButtonUI = props => {
|
|
|
48839
48858
|
cta,
|
|
48840
48859
|
spacing,
|
|
48841
48860
|
contentDisplay,
|
|
48842
|
-
//
|
|
48843
|
-
//
|
|
48844
|
-
// the outline belongs around the whole
|
|
48845
|
-
|
|
48861
|
+
// Who draws the loading outline. Left unsaid, the button does; "custom"
|
|
48862
|
+
// says someone else does — a button that is one half of a bigger control:
|
|
48863
|
+
// what is busy is the control, and the outline belongs around the whole
|
|
48864
|
+
// of it (see split_button.jsx).
|
|
48865
|
+
loadingOutline
|
|
48846
48866
|
} = props;
|
|
48847
48867
|
const [buttonControlRootProps, buttonControlHostProps, controlChildrenWrapperProps] = useControlProps(props, {
|
|
48848
48868
|
controlType: "button"
|
|
@@ -48968,7 +48988,7 @@ const ButtonUI = props => {
|
|
|
48968
48988
|
visualSelector: visualSelector,
|
|
48969
48989
|
hasChildUsingForwardedProps: true,
|
|
48970
48990
|
children: [jsx(LoadingOutline, {
|
|
48971
|
-
loading: loadingOutline
|
|
48991
|
+
loading: loadingOutline === "custom" ? false : loading,
|
|
48972
48992
|
inset: -1,
|
|
48973
48993
|
color: "var(--button-loader-color)"
|
|
48974
48994
|
}), jsx(ControlChildrenWrapper, {
|
|
@@ -59548,6 +59568,15 @@ const css$E = /* css */`
|
|
|
59548
59568
|
to filter). An entrance animation moves the dialog through scale and
|
|
59549
59569
|
transform instead, which compose under it: see popup_css.js. */
|
|
59550
59570
|
|
|
59571
|
+
/* animation="growing" brings its own wall: the popup is the anchor
|
|
59572
|
+
continued, not a surface shown over a page that goes on being read (see
|
|
59573
|
+
navi_css_vars.js for the paint). Before the rules below, so everything
|
|
59574
|
+
said out loud — an outside press that captures, a backdropVariant, the
|
|
59575
|
+
two paint props — still wins over what the animation assumes. */
|
|
59576
|
+
&[data-growing] {
|
|
59577
|
+
--backdrop-background: var(--navi-backdrop-grow-background);
|
|
59578
|
+
--backdrop-filter: var(--navi-backdrop-grow-backdrop-filter);
|
|
59579
|
+
}
|
|
59551
59580
|
&[data-pointer-interaction-outside="capture"] {
|
|
59552
59581
|
--backdrop-background: var(--navi-backdrop-capture-background);
|
|
59553
59582
|
--backdrop-filter: var(--navi-backdrop-capture-backdrop-filter);
|
|
@@ -59718,6 +59747,15 @@ const css$E = /* css */`
|
|
|
59718
59747
|
--backdrop-background: var(--navi-backdrop-close-background);
|
|
59719
59748
|
--backdrop-filter: var(--navi-backdrop-close-backdrop-filter);
|
|
59720
59749
|
}
|
|
59750
|
+
/* animation="growing" brings its own wall: the popup is the anchor
|
|
59751
|
+
continued, not a surface shown over a page that goes on being read (see
|
|
59752
|
+
navi_css_vars.js for the paint). Before the rules below, so everything
|
|
59753
|
+
said out loud — an outside press that captures, a backdropVariant, the
|
|
59754
|
+
two paint props — still wins over what the animation assumes. */
|
|
59755
|
+
&[data-growing] {
|
|
59756
|
+
--backdrop-background: var(--navi-backdrop-grow-background);
|
|
59757
|
+
--backdrop-filter: var(--navi-backdrop-grow-backdrop-filter);
|
|
59758
|
+
}
|
|
59721
59759
|
&[data-pointer-interaction-outside="capture"] {
|
|
59722
59760
|
--backdrop-background: var(--navi-backdrop-capture-background);
|
|
59723
59761
|
--backdrop-filter: var(--navi-backdrop-capture-backdrop-filter);
|
|
@@ -59935,7 +59973,8 @@ const css$E = /* css */`
|
|
|
59935
59973
|
* @param {"auto"|"discrete"|"invisible"} [props.backdropVariant="auto"] - How
|
|
59936
59974
|
* visible the backdrop is, independently of what it does. `"auto"`: the
|
|
59937
59975
|
* paint `pointerInteractionOutsideEffect` implies (dimmed for
|
|
59938
|
-
* `"close"`/`"cancel"`, blurred glass for `"capture"`)
|
|
59976
|
+
* `"close"`/`"cancel"`, blurred glass for `"capture"`), or the opaque wall
|
|
59977
|
+
* `animation="growing"` asks for. `"discrete"`: a
|
|
59939
59978
|
* barely-there dim. `"invisible"`: fully transparent — a wall that is not
|
|
59940
59979
|
* seen, still catching every press. This only changes how much the dialog
|
|
59941
59980
|
* insists visually, never what an outside click does; whether there is a
|
|
@@ -59968,7 +60007,11 @@ const css$E = /* css */`
|
|
|
59968
60007
|
* over it. It needs an anchor (whatever opened the dialog, or the `anchor`
|
|
59969
60008
|
* prop) and grows into whatever inside the dialog carries `data-grow`, the
|
|
59970
60009
|
* dialog itself when nothing does. `"auto"` never picks it: only the caller
|
|
59971
|
-
* knows the two boxes are one object.
|
|
60010
|
+
* knows the two boxes are one object. It also brings its own backdrop —
|
|
60011
|
+
* opaque and blurred (`--navi-backdrop-grow-*`), the page it came out of
|
|
60012
|
+
* being what the movement leaves rather than a context to keep readable;
|
|
60013
|
+
* `backdropVariant="discrete"` asks for the light wash back. See
|
|
60014
|
+
* `popup_grow.js`.
|
|
59972
60015
|
* @param {"box"|"scene"} [props.grow="box"] - Under `animation="growing"`,
|
|
59973
60016
|
* what the anchor and what it grows into are to each other, which decides
|
|
59974
60017
|
* how their pictures sit in the box moving between them. `"box"`: one
|
|
@@ -60998,6 +61041,7 @@ const useDialogProps = props => {
|
|
|
60998
61041
|
"animationDuration": rest.animationDuration,
|
|
60999
61042
|
"data-pointer-interaction-outside": pointerInteractionOutsideEffect,
|
|
61000
61043
|
"data-backdrop-variant": backdropVariant,
|
|
61044
|
+
"data-growing": growing ? "" : undefined,
|
|
61001
61045
|
backdropColor,
|
|
61002
61046
|
backdropFilter
|
|
61003
61047
|
});
|
|
@@ -61033,6 +61077,11 @@ const useDialogProps = props => {
|
|
|
61033
61077
|
// (and harmless for a local dialog, whose real backdrop element gets it
|
|
61034
61078
|
// via backdropProps).
|
|
61035
61079
|
"data-backdrop-variant": backdropVariant,
|
|
61080
|
+
// That this popup is the anchor continued rather than a surface shown
|
|
61081
|
+
// over the page, which is what its backdrop is painted from (see this
|
|
61082
|
+
// file's CSS). It cannot be read off navi-animation: growing arms no CSS
|
|
61083
|
+
// animation of its own, so that attribute is deliberately absent here.
|
|
61084
|
+
"data-growing": growing ? "" : undefined,
|
|
61036
61085
|
// That this dialog has no wall, said in the DOM: the browser generates a
|
|
61037
61086
|
// ::backdrop for the popover a wall-less top-layer dialog is shown as,
|
|
61038
61087
|
// and the CSS above keys off this to leave it unpainted. Also the only
|
|
@@ -61186,6 +61235,9 @@ const DIALOG_STYLE_CSS_VARS = {
|
|
|
61186
61235
|
animationDuration: "--popup-animation-duration",
|
|
61187
61236
|
backdropColor: "--backdrop-background",
|
|
61188
61237
|
backdropFilter: "--backdrop-filter",
|
|
61238
|
+
backgroundColor: "--dialog-background-color",
|
|
61239
|
+
boxShadow: "--dialog-box-shadow",
|
|
61240
|
+
borderWidth: "--dialog-border-width",
|
|
61189
61241
|
borderRadius: "--dialog-border-radius",
|
|
61190
61242
|
minWidth: "--dialog-min-width",
|
|
61191
61243
|
maxWidth: "--dialog-max-width",
|
|
@@ -62779,10 +62831,17 @@ const POPOVER_PSEUDO_CLASSES = [":hover", ":active", ":focus", ":focus-visible",
|
|
|
62779
62831
|
// Lets consumers pass animationDuration="0.5s"/borderRadius="8px" as regular
|
|
62780
62832
|
// props; Box maps them to the CSS vars for us (see box.jsx's styleCSSVars
|
|
62781
62833
|
// handling).
|
|
62834
|
+
// The paint props go through the popover's own vars rather than the properties
|
|
62835
|
+
// themselves, so the stylesheet keeps the last word on them (the same reason
|
|
62836
|
+
// dialog.jsx gives for borderRadius).
|
|
62782
62837
|
const POPUP_STYLE_CSS_VARS = {
|
|
62783
62838
|
animationDuration: "--popup-animation-duration",
|
|
62784
62839
|
backdropColor: "--backdrop-background",
|
|
62785
62840
|
backdropFilter: "--backdrop-filter",
|
|
62841
|
+
backgroundColor: "--popover-background-color",
|
|
62842
|
+
boxShadow: "--popover-box-shadow",
|
|
62843
|
+
borderWidth: "--popover-border-width",
|
|
62844
|
+
borderRadius: "--popover-border-radius",
|
|
62786
62845
|
minWidth: "--popover-min-width",
|
|
62787
62846
|
maxWidth: "--popover-max-width",
|
|
62788
62847
|
minHeight: "--popover-min-height",
|
|
@@ -63045,83 +63104,56 @@ const Popup = props => {
|
|
|
63045
63104
|
Popup.Close = PopupClose;
|
|
63046
63105
|
|
|
63047
63106
|
installImportMetaCssBuild(import.meta);
|
|
63048
|
-
const css$B = /* css */`.
|
|
63049
|
-
|
|
63050
|
-
|
|
63051
|
-
|
|
63052
|
-
|
|
63053
|
-
|
|
63054
|
-
|
|
63055
|
-
--popover-outline-width: var(--picker-outline-width);
|
|
63056
|
-
--popover-outline-color: var(--picker-outline-color);
|
|
63057
|
-
--popover-box-shadow: var(--picker-popup-box-shadow, var(--navi-popup-box-shadow));
|
|
63058
|
-
--popover-max-height: var(--picker-popover-max-height);
|
|
63059
|
-
min-width: var(--picker-popover-min-width, var(--anchor-width, 0px));
|
|
63060
|
-
cursor: default;
|
|
63061
|
-
|
|
63062
|
-
& .navi_list_container {
|
|
63063
|
-
--list-border-radius: max(0px,
|
|
63064
|
-
var(--popover-border-radius) - var(--popover-border-width));
|
|
63065
|
-
overscroll-behavior: none;
|
|
63066
|
-
width: 100%;
|
|
63107
|
+
const css$B = /* css */`.navi_popover[data-picker-popup] {
|
|
63108
|
+
--popover-border-radius: var(--picker-border-radius);
|
|
63109
|
+
--popover-border-width: var(--picker-border-width);
|
|
63110
|
+
--popover-border-color: var(--x-picker-border-color);
|
|
63111
|
+
--popover-outline-width: var(--picker-outline-width);
|
|
63112
|
+
--popover-outline-color: var(--picker-outline-color);
|
|
63113
|
+
cursor: default;
|
|
63067
63114
|
|
|
63068
|
-
|
|
63069
|
-
|
|
63070
|
-
|
|
63071
|
-
|
|
63072
|
-
}
|
|
63115
|
+
&:not([navi-hidden]) {
|
|
63116
|
+
flex-direction: column;
|
|
63117
|
+
display: flex;
|
|
63118
|
+
}
|
|
63073
63119
|
|
|
63074
|
-
|
|
63075
|
-
|
|
63076
|
-
border-
|
|
63077
|
-
|
|
63120
|
+
& .navi_list_container {
|
|
63121
|
+
--list-border-radius: max(0px,
|
|
63122
|
+
var(--popover-border-radius) - var(--popover-border-width));
|
|
63123
|
+
overscroll-behavior: none;
|
|
63124
|
+
width: 100%;
|
|
63078
63125
|
|
|
63079
|
-
|
|
63080
|
-
|
|
63081
|
-
display: flex;
|
|
63082
|
-
}
|
|
63126
|
+
&:not([data-overflow-visible]) {
|
|
63127
|
+
overflow: auto;
|
|
63083
63128
|
}
|
|
63084
63129
|
}
|
|
63130
|
+
}
|
|
63085
63131
|
|
|
63086
|
-
|
|
63087
|
-
|
|
63088
|
-
|
|
63089
|
-
--dialog-border-width: var(--picker-dialog-border-width, 0px);
|
|
63090
|
-
--dialog-border-color: var(--x-picker-border-color);
|
|
63091
|
-
--dialog-background-color: var(--picker-popup-background-color, var(--navi-popup-background-color));
|
|
63092
|
-
--dialog-outline-width: var(--picker-outline-width);
|
|
63093
|
-
--dialog-outline-color: var(--picker-outline-color);
|
|
63094
|
-
--dialog-box-shadow: var(--picker-popup-box-shadow, var(--navi-popup-box-shadow));
|
|
63095
|
-
--dialog-min-width: var(--picker-dialog-min-width);
|
|
63096
|
-
--dialog-min-height: var(--picker-dialog-min-height);
|
|
63097
|
-
--dialog-max-width: var(--picker-dialog-max-width);
|
|
63098
|
-
--dialog-max-height: var(--picker-dialog-max-height);
|
|
63099
|
-
cursor: default;
|
|
63132
|
+
.navi_picker[aria-haspopup="listbox"][aria-expanded="true"][navi-popover-mode="overlay"] {
|
|
63133
|
+
border-color: #0000;
|
|
63134
|
+
}
|
|
63100
63135
|
|
|
63101
|
-
|
|
63102
|
-
|
|
63103
|
-
|
|
63136
|
+
.navi_dialog[data-picker-popup] {
|
|
63137
|
+
--dialog-border-radius: var(--picker-border-radius);
|
|
63138
|
+
--dialog-border-color: var(--x-picker-border-color);
|
|
63139
|
+
--dialog-outline-width: var(--picker-outline-width);
|
|
63140
|
+
--dialog-outline-color: var(--picker-outline-color);
|
|
63141
|
+
cursor: default;
|
|
63104
63142
|
|
|
63105
|
-
|
|
63106
|
-
|
|
63107
|
-
|
|
63108
|
-
overscroll-behavior: none;
|
|
63109
|
-
width: 100%;
|
|
63143
|
+
&[open] {
|
|
63144
|
+
flex-direction: column;
|
|
63145
|
+
}
|
|
63110
63146
|
|
|
63111
|
-
|
|
63112
|
-
|
|
63113
|
-
|
|
63114
|
-
|
|
63115
|
-
|
|
63147
|
+
& .navi_list_container {
|
|
63148
|
+
--list-border-radius: max(0px,
|
|
63149
|
+
var(--dialog-border-radius) - var(--dialog-border-width));
|
|
63150
|
+
overscroll-behavior: none;
|
|
63151
|
+
width: 100%;
|
|
63116
63152
|
|
|
63117
|
-
|
|
63118
|
-
|
|
63153
|
+
&:not([data-overflow-visible]) {
|
|
63154
|
+
overflow: auto;
|
|
63119
63155
|
}
|
|
63120
63156
|
}
|
|
63121
|
-
|
|
63122
|
-
&[data-popup-width-fit-content] {
|
|
63123
|
-
--picker-popover-min-width: 0px;
|
|
63124
|
-
}
|
|
63125
63157
|
}
|
|
63126
63158
|
`;
|
|
63127
63159
|
const PickerCustomResolver = props => {
|
|
@@ -63885,6 +63917,22 @@ const PickerContentInsidePopup = props => {
|
|
|
63885
63917
|
// dialogMaxWidth="var(--anchor-width)", as a ceiling) — what keeps a card
|
|
63886
63918
|
// its own width once lifted. Dialog's own `sizeFromAnchor`.
|
|
63887
63919
|
dialogSizeFromAnchor,
|
|
63920
|
+
// The caller's word on the popup's own box. Written on the popup element,
|
|
63921
|
+
// where Popover/Dialog map them to their own vars, rather than as vars on
|
|
63922
|
+
// the picker: a var on the picker inherits into everything the popup
|
|
63923
|
+
// holds, and the pickers in there would read it as their own.
|
|
63924
|
+
popupBackgroundColor,
|
|
63925
|
+
popupBorderRadius,
|
|
63926
|
+
popupBoxShadow,
|
|
63927
|
+
popoverMaxHeight,
|
|
63928
|
+
dialogBorderWidth,
|
|
63929
|
+
dialogMinWidth,
|
|
63930
|
+
dialogMinHeight,
|
|
63931
|
+
dialogMaxWidth,
|
|
63932
|
+
dialogMaxHeight,
|
|
63933
|
+
// The popover is at least as wide as the trigger. True when the CONTENT
|
|
63934
|
+
// should size it (a Wheel) instead of being stretched to the trigger.
|
|
63935
|
+
popupWidthFitContent,
|
|
63888
63936
|
animation,
|
|
63889
63937
|
grow,
|
|
63890
63938
|
animationDuration,
|
|
@@ -63903,7 +63951,6 @@ const PickerContentInsidePopup = props => {
|
|
|
63903
63951
|
return jsx(Next, {
|
|
63904
63952
|
"aria-haspopup": isPopover ? "listbox" : "dialog",
|
|
63905
63953
|
"navi-popover-mode": isPopover ? popoverMode : undefined,
|
|
63906
|
-
"data-dialog-size-from-anchor": !isPopover && dialogSizeFromAnchor ? "" : undefined,
|
|
63907
63954
|
...rest,
|
|
63908
63955
|
// On popupProps already (see the picker's popup assembly); they mean
|
|
63909
63956
|
// nothing to the picker element.
|
|
@@ -63945,7 +63992,23 @@ const PickerContentInsidePopup = props => {
|
|
|
63945
63992
|
})
|
|
63946
63993
|
}) : jsx(Popup, {
|
|
63947
63994
|
...popupProps,
|
|
63948
|
-
"data-testid": popupTestId
|
|
63995
|
+
"data-testid": popupTestId
|
|
63996
|
+
// What the CSS above keys on: this picker's own popup, and no other
|
|
63997
|
+
// popup below the picker.
|
|
63998
|
+
,
|
|
63999
|
+
"data-picker-popup": "",
|
|
64000
|
+
backgroundColor: popupBackgroundColor,
|
|
64001
|
+
borderRadius: popupBorderRadius,
|
|
64002
|
+
boxShadow: popupBoxShadow,
|
|
64003
|
+
borderWidth: isPopover ? undefined : dialogBorderWidth,
|
|
64004
|
+
minWidth: isPopover ? popupWidthFitContent ? undefined : "var(--anchor-width, 0px)" : dialogMinWidth,
|
|
64005
|
+
minHeight: isPopover ? undefined : dialogMinHeight
|
|
64006
|
+
// As wide as the trigger under dialogSizeFromAnchor: Dialog's own
|
|
64007
|
+
// sizeFromAnchor is a floor, this is the ceiling. A dialogMaxWidth of
|
|
64008
|
+
// the caller's still wins.
|
|
64009
|
+
,
|
|
64010
|
+
maxWidth: isPopover ? undefined : dialogMaxWidth === undefined && dialogSizeFromAnchor ? "var(--anchor-width)" : dialogMaxWidth,
|
|
64011
|
+
maxHeight: isPopover ? popoverMaxHeight : dialogMaxHeight,
|
|
63949
64012
|
mode: mode,
|
|
63950
64013
|
layer: popupLayer,
|
|
63951
64014
|
animation: animation,
|
|
@@ -72043,6 +72106,26 @@ const css$t = /* css */`@layer navi {
|
|
|
72043
72106
|
}
|
|
72044
72107
|
}
|
|
72045
72108
|
|
|
72109
|
+
& [data-picker-content] {
|
|
72110
|
+
--picker-padding: initial;
|
|
72111
|
+
--picker-padding-x: initial;
|
|
72112
|
+
--picker-padding-y: initial;
|
|
72113
|
+
--picker-padding-top: initial;
|
|
72114
|
+
--picker-padding-right: initial;
|
|
72115
|
+
--picker-padding-bottom: initial;
|
|
72116
|
+
--picker-padding-left: initial;
|
|
72117
|
+
--picker-press-padding: initial;
|
|
72118
|
+
--picker-press-padding-x: initial;
|
|
72119
|
+
--picker-press-padding-y: initial;
|
|
72120
|
+
--picker-press-padding-top: initial;
|
|
72121
|
+
--picker-press-padding-right: initial;
|
|
72122
|
+
--picker-press-padding-bottom: initial;
|
|
72123
|
+
--picker-press-padding-left: initial;
|
|
72124
|
+
--picker-slot-spacing: initial;
|
|
72125
|
+
--picker-align-x: initial;
|
|
72126
|
+
--picker-align-y: initial;
|
|
72127
|
+
}
|
|
72128
|
+
|
|
72046
72129
|
& .navi_picker_content {
|
|
72047
72130
|
--x-corner-top-left-radius: initial;
|
|
72048
72131
|
--x-corner-top-right-radius: initial;
|
|
@@ -72246,11 +72329,6 @@ const PickerButton = props => {
|
|
|
72246
72329
|
placeholder,
|
|
72247
72330
|
ui,
|
|
72248
72331
|
maxLines: maxLinesProp = 1,
|
|
72249
|
-
// By default the popover is at least as wide as the trigger (min-width:
|
|
72250
|
-
// --anchor-width). Set true when the CONTENT should dictate the popover width
|
|
72251
|
-
// (e.g. a Wheel) instead of being stretched to the trigger — see
|
|
72252
|
-
// picker_custom.jsx.
|
|
72253
|
-
popupWidthFitContent,
|
|
72254
72332
|
// Adds a clear button to the right slot, the same one type="search" puts at
|
|
72255
72333
|
// the end of an input: a picker holds a value the user chose, and unsetting
|
|
72256
72334
|
// it should not require reopening the popup to hunt for a "none" entry.
|
|
@@ -72275,7 +72353,13 @@ const PickerButton = props => {
|
|
|
72275
72353
|
// (see PickerInput below).
|
|
72276
72354
|
role,
|
|
72277
72355
|
readOnly,
|
|
72278
|
-
error
|
|
72356
|
+
error,
|
|
72357
|
+
// Who draws the loading outline. Left unsaid, the picker does, around its
|
|
72358
|
+
// own box; "custom" says someone else does — a bigger surface this box is
|
|
72359
|
+
// a piece of, waiting as a whole (see the `loadingOutline` doc).
|
|
72360
|
+
loadingOutline,
|
|
72361
|
+
// Where the outline runs, in px from the picker's box: negative is outside.
|
|
72362
|
+
loadingOutlineInset = -2
|
|
72279
72363
|
} = props;
|
|
72280
72364
|
// A word in a sentence is never truncated — and the clamp's overflow: hidden
|
|
72281
72365
|
// would cut its dotted underline, which sits on the edge of the line box
|
|
@@ -72395,7 +72479,6 @@ const PickerButton = props => {
|
|
|
72395
72479
|
"navi-single-line": isSingleLine ? "" : undefined,
|
|
72396
72480
|
"navi-ui-custom": ui === "default" ? undefined : "",
|
|
72397
72481
|
"data-readonly-opens": readOnlyOpens ? "" : undefined,
|
|
72398
|
-
"data-popup-width-fit-content": popupWidthFitContent ? "" : undefined,
|
|
72399
72482
|
...pickerRemainingProps,
|
|
72400
72483
|
basePseudoState: basePseudoState,
|
|
72401
72484
|
styleCSSVars: PickerStyleCSSVars,
|
|
@@ -72410,9 +72493,10 @@ const PickerButton = props => {
|
|
|
72410
72493
|
openWhileReadOnly: undefined,
|
|
72411
72494
|
ui: undefined,
|
|
72412
72495
|
maxLines: undefined,
|
|
72413
|
-
popupWidthFitContent: undefined,
|
|
72414
72496
|
error: undefined,
|
|
72415
|
-
dayLabel: undefined
|
|
72497
|
+
dayLabel: undefined,
|
|
72498
|
+
loadingOutline: undefined,
|
|
72499
|
+
loadingOutlineInset: undefined
|
|
72416
72500
|
// This wrapper will receive keyboard event bubbling from the picker popup content
|
|
72417
72501
|
// we re-dispatch on the input (to get escape to close for instance)
|
|
72418
72502
|
,
|
|
@@ -72443,9 +72527,9 @@ const PickerButton = props => {
|
|
|
72443
72527
|
children: jsxs(PickerContext.Provider, {
|
|
72444
72528
|
value: pickerContext,
|
|
72445
72529
|
children: [variant === "headless" ? null : jsx(LoadingOutline, {
|
|
72446
|
-
loading: loading,
|
|
72530
|
+
loading: loadingOutline === "custom" ? false : loading,
|
|
72447
72531
|
color: "var(--picker-loader-color)",
|
|
72448
|
-
inset:
|
|
72532
|
+
inset: loadingOutlineInset
|
|
72449
72533
|
}), jsx(PickerInput, {
|
|
72450
72534
|
role: hostRole,
|
|
72451
72535
|
"aria-labelledby": hostLabelId,
|
|
@@ -72680,7 +72764,7 @@ const PickerClear = ({
|
|
|
72680
72764
|
// removed is the whole field's, and the picker already draws the wait
|
|
72681
72765
|
// around all of it. Two outlines for one wait is one too many.
|
|
72682
72766
|
,
|
|
72683
|
-
loadingOutline:
|
|
72767
|
+
loadingOutline: "custom"
|
|
72684
72768
|
// preventDefault, not just tabIndex="-1": a mousedown focuses its target
|
|
72685
72769
|
// before any click happens, and this button should never hold focus at
|
|
72686
72770
|
// all — the field keeps it.
|
|
@@ -72854,21 +72938,16 @@ const PICKER_BUTTON_PSEUDO_CLASSES = [":hover", ":focus", ":focus-visible", ":fo
|
|
|
72854
72938
|
const PickerInputPseudoClasses = [":focus", ":focus-visible", ":read-only", ":disabled", ":-navi-loading", ":-navi-has-value", ":-navi-expanded"];
|
|
72855
72939
|
|
|
72856
72940
|
// A pair is [the css variable, the style whose values the prop is written in]:
|
|
72857
|
-
//
|
|
72858
|
-
//
|
|
72941
|
+
// slotSpacing takes what margin takes, pressPadding what padding takes — see
|
|
72942
|
+
// box.jsx's readCSSVarEntry.
|
|
72943
|
+
// What the props say about the picker's own box only. The popup props
|
|
72944
|
+
// (popupBackgroundColor, dialogMaxWidth…) are handed to the popup element by
|
|
72945
|
+
// picker_custom.jsx: a variable on the root inherits into everything the popup
|
|
72946
|
+
// holds, and the pickers in there would read it as their own.
|
|
72859
72947
|
const PickerStyleCSSVars = {
|
|
72860
72948
|
"outlineWidth": "--picker-outline-width",
|
|
72861
72949
|
"borderWidth": "--picker-border-width",
|
|
72862
72950
|
"borderRadius": "--picker-border-radius",
|
|
72863
|
-
"popoverMaxHeight": ["--picker-popover-max-height", "maxHeight"],
|
|
72864
|
-
"dialogMinWidth": ["--picker-dialog-min-width", "minWidth"],
|
|
72865
|
-
"dialogMinHeight": ["--picker-dialog-min-height", "minHeight"],
|
|
72866
|
-
"dialogMaxWidth": ["--picker-dialog-max-width", "maxWidth"],
|
|
72867
|
-
"dialogMaxHeight": ["--picker-dialog-max-height", "maxHeight"],
|
|
72868
|
-
"popupBackgroundColor": "--picker-popup-background-color",
|
|
72869
|
-
"popupBorderRadius": ["--picker-popup-border-radius", "borderRadius"],
|
|
72870
|
-
"popupBoxShadow": ["--picker-popup-box-shadow", "boxShadow"],
|
|
72871
|
-
"dialogBorderWidth": ["--picker-dialog-border-width", "borderWidth"],
|
|
72872
72951
|
"slotSpacing": ["--picker-slot-spacing", "margin"],
|
|
72873
72952
|
"pressPadding": ["--picker-press-padding", "padding"],
|
|
72874
72953
|
"pressPaddingX": ["--picker-press-padding-x", "padding"],
|
|
@@ -72975,6 +73054,8 @@ const PickerFirstResolver = props => {
|
|
|
72975
73054
|
* popoverMode?: "nearby" | "overlay",
|
|
72976
73055
|
* positionArea?: string,
|
|
72977
73056
|
* popupWidthFitContent?: boolean,
|
|
73057
|
+
* loadingOutline?: "custom",
|
|
73058
|
+
* loadingOutlineInset?: number,
|
|
72978
73059
|
* variant?: "icon" | "circle" | "headless" | "discrete" | "button" | "text" | "bare" | "picker",
|
|
72979
73060
|
* icon?: boolean,
|
|
72980
73061
|
* alignX?: "start" | "center" | "end",
|
|
@@ -73092,9 +73173,12 @@ const PickerFirstResolver = props => {
|
|
|
73092
73173
|
* its own as well. Either way a card shows the score the moment the sheet
|
|
73093
73174
|
* leaves and takes it back on a refusal, with nothing held by the caller.
|
|
73094
73175
|
* `loading` is the wait it wears meanwhile: navi draws its loading outline
|
|
73095
|
-
* on every trigger,
|
|
73096
|
-
*
|
|
73097
|
-
*
|
|
73176
|
+
* on every trigger, two pixels out of the box. On a card-sized
|
|
73177
|
+
* `variant="bare"` that run sits on the card's own border and reads as a
|
|
73178
|
+
* border blinking; `loadingOutlineInset` moves it clear of it. And when the
|
|
73179
|
+
* picker's box is not the shape of what waits, `loadingOutline="custom"`
|
|
73180
|
+
* lets the drawing draw the wait itself, from that flag or from
|
|
73181
|
+
* `[data-loading]` on the picker root in css.
|
|
73098
73182
|
* @param {boolean} [readOnly] Nothing in this picker can be changed — and it
|
|
73099
73183
|
* still opens, so what is in the popup can be read: everything in there is
|
|
73100
73184
|
* held read-only in turn, each control greying out and saying why on its own.
|
|
@@ -73221,6 +73305,21 @@ const PickerFirstResolver = props => {
|
|
|
73221
73305
|
* nearest positioned ancestor it happens to find. `"picker"` (or an explicit
|
|
73222
73306
|
* `variant={undefined}`) asks a confirm or callout picker for the field-like
|
|
73223
73307
|
* drawing every other picker has.
|
|
73308
|
+
* @param {"custom"} [loadingOutline] Who draws the loading outline while the
|
|
73309
|
+
* action runs. Left unsaid, the picker does, around its own box. `"custom"`
|
|
73310
|
+
* says someone else does — what it means on a `Button` too — for a picker
|
|
73311
|
+
* that carries a wait drawn elsewhere: two nested pickers sharing one run
|
|
73312
|
+
* (a score picker drawn inside the card an edit picker wraps, see
|
|
73313
|
+
* `12_picker_card_demo.html`) are one wait, and one outline; and a
|
|
73314
|
+
* `variant="bare"` whose box is not
|
|
73315
|
+
* the shape of what waits (a card with a note pinned under it) leaves the
|
|
73316
|
+
* outline to the card, which knows its own box. The wait itself is still
|
|
73317
|
+
* worn: `aria-busy`, the busy refusal, the error callout, `[data-loading]`.
|
|
73318
|
+
* @param {number} [loadingOutlineInset=-2] Where the loading outline runs, in
|
|
73319
|
+
* px from the picker's box — negative is outside. A field wants it right on
|
|
73320
|
+
* its border; a card-sized trigger wants it a few pixels out, clear of the
|
|
73321
|
+
* card's own frame, so it reads as a run around the card rather than as its
|
|
73322
|
+
* border blinking.
|
|
73224
73323
|
* @param {boolean} [icon] The trigger is one icon — the `ui`, or the chevron
|
|
73225
73324
|
* when there is none. Its box is that icon's box plus the padding asked for
|
|
73226
73325
|
* and nothing else: no right slot, and no control line to be as tall as, so
|
|
@@ -73306,7 +73405,9 @@ const PickerFirstResolver = props => {
|
|
|
73306
73405
|
* (the popup itself when nothing does), and back on close. The trigger IS
|
|
73307
73406
|
* the anchor, so nothing has to be named for it — `dialogSizeFromAnchor`
|
|
73308
73407
|
* for a card that must keep its width on the way, left out for a drawing
|
|
73309
|
-
* that opens precisely to get bigger.
|
|
73408
|
+
* that opens precisely to get bigger. It brings an opaque, blurred backdrop
|
|
73409
|
+
* with it (`--navi-backdrop-grow-*`); `backdropVariant="discrete"` asks for
|
|
73410
|
+
* the light wash back.
|
|
73310
73411
|
* @param {"box"|"scene"} [grow="box"] Dialog's own, under `animation="growing"`:
|
|
73311
73412
|
* `"box"` for a card that extends (its top stays, the box uncovers the rest),
|
|
73312
73413
|
* `"scene"` for a thumbnail and the bigger view it is cut from (each picture
|
|
@@ -73317,9 +73418,9 @@ const PickerFirstResolver = props => {
|
|
|
73317
73418
|
* as a ceiling, unless a `dialogMaxWidth` says otherwise. What keeps a card
|
|
73318
73419
|
* its own width once lifted out of the page (`animation="growing"`, with
|
|
73319
73420
|
* `data-grow` on the card inside the popup): it moves, and nothing else
|
|
73320
|
-
* about it changes.
|
|
73321
|
-
*
|
|
73322
|
-
*
|
|
73421
|
+
* about it changes. `dialogMaxWidth="var(--anchor-width)"` says the same
|
|
73422
|
+
* ceiling by hand: the popup props are written on the dialog element, where
|
|
73423
|
+
* that variable lives.
|
|
73323
73424
|
* @param {"cancel"|"close"} [escapeEffect="cancel"] What Escape does to an open
|
|
73324
73425
|
* picker. "cancel" puts back the value the picker had at open, and a dialog
|
|
73325
73426
|
* picker also goes back in history — so anything written to the url while it
|
|
@@ -75965,7 +76066,7 @@ const SplitButton = props => {
|
|
|
75965
76066
|
readOnly,
|
|
75966
76067
|
disabled,
|
|
75967
76068
|
// The outline belongs around the pair, drawn below.
|
|
75968
|
-
loadingOutline:
|
|
76069
|
+
loadingOutline: "custom"
|
|
75969
76070
|
};
|
|
75970
76071
|
return jsxs(Box, {
|
|
75971
76072
|
ref: rootRef,
|