@jsenv/navi 0.29.488 → 0.29.489
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 +644 -153
- package/dist/dev/jsenv_navi.js.map +37 -33
- package/dist/jsenv_navi.js +644 -153
- package/dist/jsenv_navi.js.map +37 -33
- package/docs/navigation.md +5 -0
- package/docs/popup_open.md +7 -3
- package/docs/resource.md +1 -1
- package/package.json +2 -2
package/dist/jsenv_navi.js
CHANGED
|
@@ -966,6 +966,10 @@ const buttonI18n = /*#__PURE__*/ defineNaviMessages({
|
|
|
966
966
|
en: "Copied!",
|
|
967
967
|
fr: "Copié !",
|
|
968
968
|
},
|
|
969
|
+
"button.copy_refused": {
|
|
970
|
+
en: "Could not copy.",
|
|
971
|
+
fr: "Impossible de copier.",
|
|
972
|
+
},
|
|
969
973
|
});
|
|
970
974
|
|
|
971
975
|
// Spin messages — the ends of what one steps through when the control holding
|
|
@@ -2723,18 +2727,18 @@ const debounceSignal = (
|
|
|
2723
2727
|
signalToDebounce,
|
|
2724
2728
|
{ delay = 300, deepCompare = true } = {},
|
|
2725
2729
|
) => {
|
|
2730
|
+
const isSameValue = (a, b) =>
|
|
2731
|
+
deepCompare ? compareTwoJsValues(a, b) : a === b;
|
|
2726
2732
|
let timeoutId;
|
|
2727
2733
|
let latestValue = signalToDebounce.peek();
|
|
2728
|
-
|
|
2729
|
-
|
|
2730
|
-
|
|
2734
|
+
// Following the source subscribes to it, and through it to whatever it reads:
|
|
2735
|
+
// an app-level signal it reads would keep it — and its timer — alive for
|
|
2736
|
+
// good. So it is followed only while something reads the debounced value.
|
|
2737
|
+
let stopFollowing = null;
|
|
2738
|
+
const follow = () => {
|
|
2731
2739
|
const value = signalToDebounce.value;
|
|
2732
2740
|
const debouncedValue = debouncedSignal.peek();
|
|
2733
|
-
if (
|
|
2734
|
-
deepCompare
|
|
2735
|
-
? compareTwoJsValues(value, debouncedValue)
|
|
2736
|
-
: value === debouncedValue
|
|
2737
|
-
) {
|
|
2741
|
+
if (isSameValue(value, debouncedValue)) {
|
|
2738
2742
|
// The signal came back to where the debounced one already is: whatever it
|
|
2739
2743
|
// passed through on the way is not on its way any more. Leaving the timer
|
|
2740
2744
|
// armed would publish that in-between value once the delay elapses, and
|
|
@@ -2749,11 +2753,37 @@ const debounceSignal = (
|
|
|
2749
2753
|
timeoutId = setTimeout(() => {
|
|
2750
2754
|
debouncedSignal.value = latestValue;
|
|
2751
2755
|
}, delay);
|
|
2756
|
+
};
|
|
2757
|
+
const catchUp = () => {
|
|
2758
|
+
const value = signalToDebounce.peek();
|
|
2759
|
+
if (!isSameValue(value, debouncedSignal.peek())) {
|
|
2760
|
+
debouncedSignal.value = value;
|
|
2761
|
+
}
|
|
2762
|
+
latestValue = debouncedSignal.peek();
|
|
2763
|
+
};
|
|
2764
|
+
const debouncedSignal = signal(latestValue, {
|
|
2765
|
+
watched: () => {
|
|
2766
|
+
// Nobody was waiting on what the source said while nothing read it:
|
|
2767
|
+
// that is taken at once, not after a delay.
|
|
2768
|
+
catchUp();
|
|
2769
|
+
stopFollowing = effect(follow);
|
|
2770
|
+
},
|
|
2771
|
+
unwatched: () => {
|
|
2772
|
+
stopFollowing();
|
|
2773
|
+
stopFollowing = null;
|
|
2774
|
+
clearTimeout(timeoutId);
|
|
2775
|
+
timeoutId = undefined;
|
|
2776
|
+
},
|
|
2752
2777
|
});
|
|
2753
2778
|
|
|
2754
2779
|
debouncedSignal.flush = () => {
|
|
2755
2780
|
clearTimeout(timeoutId);
|
|
2756
|
-
|
|
2781
|
+
timeoutId = undefined;
|
|
2782
|
+
if (stopFollowing) {
|
|
2783
|
+
debouncedSignal.value = latestValue;
|
|
2784
|
+
return;
|
|
2785
|
+
}
|
|
2786
|
+
catchUp();
|
|
2757
2787
|
};
|
|
2758
2788
|
// Whoever reads the debounced value gets the previous one during the delay,
|
|
2759
2789
|
// with nothing saying a newer one is on its way. This says it.
|
|
@@ -4667,10 +4697,46 @@ const createActionProxyFromSignal = (
|
|
|
4667
4697
|
});
|
|
4668
4698
|
actionWeakMap.set(actionProxy, actionProxy);
|
|
4669
4699
|
|
|
4700
|
+
// Following the params subscribes to them, and through them to whatever
|
|
4701
|
+
// they read: a component's computed params reading an app-level signal stay
|
|
4702
|
+
// reachable from that signal for as long as anything listens to them. So a
|
|
4703
|
+
// binding follows its params only while something reads what it says (a
|
|
4704
|
+
// mounted component, a run's subscriber), and catches up when read again;
|
|
4705
|
+
// unread, every method retargets first (see proxyMethod). A binding asked to
|
|
4706
|
+
// act on their changes (runOnce, rerunOnChange, onChange: a route action,
|
|
4707
|
+
// actionRunEffect) follows them for as long as it exists.
|
|
4708
|
+
const followsParamsAlways = runOnce || rerunOnChange || Boolean(onChange);
|
|
4709
|
+
let readerCount = 0;
|
|
4710
|
+
let stopFollowingParams = null;
|
|
4711
|
+
const readerWatchOptions = followsParamsAlways
|
|
4712
|
+
? undefined
|
|
4713
|
+
: {
|
|
4714
|
+
watched: () => {
|
|
4715
|
+
readerCount++;
|
|
4716
|
+
if (readerCount === 1) {
|
|
4717
|
+
const stopMirroringParams = effect(() => {
|
|
4718
|
+
proxyParamsSignal.value = paramsSignal.value;
|
|
4719
|
+
});
|
|
4720
|
+
const stopRetargeting = effect(retargetOnParamsChange);
|
|
4721
|
+
stopFollowingParams = () => {
|
|
4722
|
+
stopMirroringParams();
|
|
4723
|
+
stopRetargeting();
|
|
4724
|
+
};
|
|
4725
|
+
}
|
|
4726
|
+
},
|
|
4727
|
+
unwatched: () => {
|
|
4728
|
+
readerCount--;
|
|
4729
|
+
if (readerCount === 0) {
|
|
4730
|
+
stopFollowingParams();
|
|
4731
|
+
stopFollowingParams = null;
|
|
4732
|
+
}
|
|
4733
|
+
},
|
|
4734
|
+
};
|
|
4735
|
+
|
|
4670
4736
|
// Create our own signal for params that we control completely
|
|
4671
4737
|
const proxyParamsSignal = signal(paramsSignal.value);
|
|
4672
4738
|
const proxySignal = (signalPropertyName, propertyName) => {
|
|
4673
|
-
const signalProxy = signal();
|
|
4739
|
+
const signalProxy = signal(undefined, readerWatchOptions);
|
|
4674
4740
|
let dispose;
|
|
4675
4741
|
onActionTargetChange(() => {
|
|
4676
4742
|
if (dispose) {
|
|
@@ -4797,20 +4863,34 @@ const createActionProxyFromSignal = (
|
|
|
4797
4863
|
}
|
|
4798
4864
|
// Watch for changes in the original paramsSignal and update ours
|
|
4799
4865
|
// (original signal wins over any replaceParams calls)
|
|
4800
|
-
|
|
4801
|
-
[paramsSignal, proxyParamsSignal],
|
|
4802
|
-
(paramsSignalRef, proxyParamsSignalRef) => {
|
|
4803
|
-
const newParams = paramsSignalRef.value;
|
|
4804
|
-
proxyParamsSignalRef.value = newParams;
|
|
4805
|
-
},
|
|
4806
|
-
);
|
|
4807
|
-
weakEffect([action], () => {
|
|
4866
|
+
const retargetOnParamsChange = () => {
|
|
4808
4867
|
// eslint-disable-next-line no-unused-expressions
|
|
4809
4868
|
proxyParamsSignal.value;
|
|
4810
4869
|
_updateTarget({
|
|
4811
4870
|
changeCause: "params_signal_change",
|
|
4812
4871
|
});
|
|
4813
|
-
}
|
|
4872
|
+
};
|
|
4873
|
+
if (followsParamsAlways) {
|
|
4874
|
+
weakEffect(
|
|
4875
|
+
[paramsSignal, proxyParamsSignal],
|
|
4876
|
+
(paramsSignalRef, proxyParamsSignalRef) => {
|
|
4877
|
+
const newParams = paramsSignalRef.value;
|
|
4878
|
+
proxyParamsSignalRef.value = newParams;
|
|
4879
|
+
},
|
|
4880
|
+
);
|
|
4881
|
+
weakEffect([action], retargetOnParamsChange);
|
|
4882
|
+
} else {
|
|
4883
|
+
// The first target is resolved now, as following would resolve it: the
|
|
4884
|
+
// subscribers wired above read what it says from the start (see
|
|
4885
|
+
// onActionTargetChange above). Untracked, as inside the effect that
|
|
4886
|
+
// resolves it otherwise: a binding is made during a render, which must
|
|
4887
|
+
// not subscribe to what retargeting reads.
|
|
4888
|
+
untracked(() => {
|
|
4889
|
+
_updateTarget({
|
|
4890
|
+
changeCause: "params_signal_change",
|
|
4891
|
+
});
|
|
4892
|
+
});
|
|
4893
|
+
}
|
|
4814
4894
|
actionProxy.replaceParams = (newParams) => {
|
|
4815
4895
|
if (currentAction === action) {
|
|
4816
4896
|
const currentParams = proxyParamsSignal.value;
|
|
@@ -5775,6 +5855,10 @@ const isPickerBoundaryFor = (candidate, el) => {
|
|
|
5775
5855
|
*/
|
|
5776
5856
|
const getParentControl = (el) => {
|
|
5777
5857
|
const ownControlRoot = el.closest("[navi-control]");
|
|
5858
|
+
if (!ownControlRoot) {
|
|
5859
|
+
// In no control at all (a list's root, a plain element): none around it.
|
|
5860
|
+
return null;
|
|
5861
|
+
}
|
|
5778
5862
|
const parentControlRoot = ownControlRoot.parentNode.closest("[navi-control]");
|
|
5779
5863
|
return parentControlRoot;
|
|
5780
5864
|
};
|
|
@@ -6250,10 +6334,14 @@ const resolveInputProps = (props, { controlType = "input" } = {}) => {
|
|
|
6250
6334
|
// signal wants a date field — but a boolean one maps to a checkbox, and
|
|
6251
6335
|
// a picker made into a checkbox is not a picker with a different look:
|
|
6252
6336
|
// it is another control, with no popup to open. A picker asked to hold
|
|
6253
|
-
// a yes/no keeps its two rows and stays itself.
|
|
6337
|
+
// a yes/no keeps its two rows and stays itself. Nor does a picker with
|
|
6338
|
+
// a popup of its own become the field for that type: it is what its
|
|
6339
|
+
// popup is — a frise one slides in is no number one types.
|
|
6254
6340
|
const wouldChangeWhatTheControlIs =
|
|
6255
6341
|
controlType === "picker" &&
|
|
6256
|
-
(
|
|
6342
|
+
(props.children !== undefined ||
|
|
6343
|
+
typeFromSignal === "checkbox" ||
|
|
6344
|
+
typeFromSignal === "radio");
|
|
6257
6345
|
if (typeFromSignal !== undefined && !wouldChangeWhatTheControlIs) {
|
|
6258
6346
|
props.type = typeFromSignal;
|
|
6259
6347
|
}
|
|
@@ -7331,7 +7419,8 @@ const generateSignalId = () => {
|
|
|
7331
7419
|
* deploys holds one copy, not ten. Only the storage key changes, the id the url reads stays `id`.
|
|
7332
7420
|
* @param {string} [options.type] - Type the value is coerced to, and read back as from localStorage and the url:
|
|
7333
7421
|
* any @jsenv/validity type (`"string"`, `"number"`, `"boolean"`, `"array"`, `"object"`, `"integer"`, `"date"`,
|
|
7334
|
-
* `"time"`…). Without it the value is not coerced.
|
|
7422
|
+
* `"time"`…). Without it the value is not coerced. On a type that is not text (`"string"`, `"email"`,
|
|
7423
|
+
* `"url"`), `""` — what a cleared control writes — is absence.
|
|
7335
7424
|
* @param {"string" | "number" | "boolean"} [options.itemType] - For array type: type of the array items.
|
|
7336
7425
|
* Used when reading the value back from a url search param, where everything is a string:
|
|
7337
7426
|
* `?level=3,4` becomes `[3, 4]` instead of `["3", "4"]`. Without it items stay strings.
|
|
@@ -7426,6 +7515,8 @@ const generateSignalId = () => {
|
|
|
7426
7515
|
* const childTab = stateSignal(parentTab);
|
|
7427
7516
|
* // childTab follows parentTab changes unless explicitly set
|
|
7428
7517
|
*/
|
|
7518
|
+
// The types "" is a value of: an empty text is still a text.
|
|
7519
|
+
const TEXT_TYPE_SET = new Set(["string", "email", "url"]);
|
|
7429
7520
|
const stateSignal = (defaultValue, options = {}) => {
|
|
7430
7521
|
const {
|
|
7431
7522
|
id,
|
|
@@ -7595,8 +7686,13 @@ const stateSignal = (defaultValue, options = {}) => {
|
|
|
7595
7686
|
};
|
|
7596
7687
|
|
|
7597
7688
|
// Create signal with initial value: use stored value, or undefined to indicate no explicit value
|
|
7689
|
+
// Whether "" says nothing at all: on a type that is not text, it is what a
|
|
7690
|
+
// cleared control writes (an empty field, a picker's cross) — no number, no
|
|
7691
|
+
// date — and kept, it would be an invalid value the address carries.
|
|
7692
|
+
const emptyStringIsAbsence =
|
|
7693
|
+
type !== undefined && !TEXT_TYPE_SET.has(type);
|
|
7598
7694
|
const processValue = (value) => {
|
|
7599
|
-
if (value === undefined) {
|
|
7695
|
+
if (value === undefined || (value === "" && emptyStringIsAbsence)) {
|
|
7600
7696
|
// Absence is never validated, and the verdict on the previous value
|
|
7601
7697
|
// (validSignal, validity.valid) must not outlive it.
|
|
7602
7698
|
clearValidity();
|
|
@@ -14911,6 +15007,14 @@ PSEUDO_CLASSES[":active"] = {
|
|
|
14911
15007
|
// focus_classes block below. At module scope so isMatchingFocusVisible (used
|
|
14912
15008
|
// here and in control_hooks.jsx) can read it.
|
|
14913
15009
|
let keyboardNavigationUsed = false;
|
|
15010
|
+
// The element a caller focused saying the ring must show (`focusVisible: true`
|
|
15011
|
+
// to moveFocusTo or autoFocus): it knows better than the modality — a screen
|
|
15012
|
+
// showing where Enter goes before any key was pressed. Until a pointer goes
|
|
15013
|
+
// down, which says the hand is elsewhere.
|
|
15014
|
+
let focusVisibleAskedElement = null;
|
|
15015
|
+
const askFocusVisible = (element) => {
|
|
15016
|
+
focusVisibleAskedElement = element;
|
|
15017
|
+
};
|
|
14914
15018
|
|
|
14915
15019
|
// HOW FOCUS-VISIBLE IS DECIDED (the details behind isMatchingFocusVisible)
|
|
14916
15020
|
//
|
|
@@ -14940,7 +15044,10 @@ let keyboardNavigationUsed = false;
|
|
|
14940
15044
|
//
|
|
14941
15045
|
// `keyboardNavigationUsed` has no such blind spot — it is set by navigation
|
|
14942
15046
|
// keydowns and cleared by pointerdown, whatever anyone prevents afterwards
|
|
14943
|
-
// — so it is the authority for everything rule 1 does not cover.
|
|
15047
|
+
// — so it is the authority for everything rule 1 does not cover. Save for
|
|
15048
|
+
// the element a caller explicitly focused with a ring (askFocusVisible):
|
|
15049
|
+
// that is somebody knowing better than the last interaction, not a state
|
|
15050
|
+
// left behind.
|
|
14944
15051
|
//
|
|
14945
15052
|
// Ring INHERITANCE (a controlled element ringing because its aria-controls
|
|
14946
15053
|
// controller is focused) stays gated on the keyboard modality even for an
|
|
@@ -14963,7 +15070,7 @@ const isMatchingFocusVisible = (el) => {
|
|
|
14963
15070
|
return false;
|
|
14964
15071
|
}
|
|
14965
15072
|
if (!keyboardNavigationUsed) {
|
|
14966
|
-
return
|
|
15073
|
+
return el === focusVisibleAskedElement;
|
|
14967
15074
|
}
|
|
14968
15075
|
return true;
|
|
14969
15076
|
};
|
|
@@ -15084,6 +15191,7 @@ const isKeyboardModality = () => keyboardNavigationUsed;
|
|
|
15084
15191
|
"pointerdown",
|
|
15085
15192
|
() => {
|
|
15086
15193
|
keyboardNavigationUsed = false;
|
|
15194
|
+
focusVisibleAskedElement = null;
|
|
15087
15195
|
},
|
|
15088
15196
|
{ capture: true },
|
|
15089
15197
|
);
|
|
@@ -16232,7 +16340,8 @@ const retryWhenPlaceable = (
|
|
|
16232
16340
|
* @param {object} [options]
|
|
16233
16341
|
* @param {boolean} [options.focusVisible] Decides the ring instead of the
|
|
16234
16342
|
* modality — for a caller that knows better than the last interaction does
|
|
16235
|
-
* (a transfer speaking for the gesture that opened a container, say).
|
|
16343
|
+
* (a transfer speaking for the gesture that opened a container, say). `true`
|
|
16344
|
+
* draws the ring even before any key was pressed, until a pointer goes down.
|
|
16236
16345
|
* @param {boolean} [options.preventScroll=true] Pass false to let the browser
|
|
16237
16346
|
* scroll the element into view.
|
|
16238
16347
|
*/
|
|
@@ -16240,6 +16349,9 @@ const moveFocusTo = (
|
|
|
16240
16349
|
element,
|
|
16241
16350
|
{ focusVisible, preventScroll = true } = {},
|
|
16242
16351
|
) => {
|
|
16352
|
+
if (focusVisible === true) {
|
|
16353
|
+
askFocusVisible(element);
|
|
16354
|
+
}
|
|
16243
16355
|
element.focus({
|
|
16244
16356
|
preventScroll,
|
|
16245
16357
|
focusVisible:
|
|
@@ -16417,6 +16529,14 @@ document.addEventListener(
|
|
|
16417
16529
|
const openedDuringThisPress = (openController) =>
|
|
16418
16530
|
openController.pressCountAtOpen === pressCount;
|
|
16419
16531
|
|
|
16532
|
+
/**
|
|
16533
|
+
* Which press the events landing now belong to: the pointerdown, mousedown and
|
|
16534
|
+
* click of one press read the same count, a tap's compatibility events
|
|
16535
|
+
* included (see above). A click the keyboard makes brings no pointerdown, so it
|
|
16536
|
+
* reads the count of the last press: tell it apart by `event.detail === 0`.
|
|
16537
|
+
*/
|
|
16538
|
+
const readPressCount = () => pressCount;
|
|
16539
|
+
|
|
16420
16540
|
// How long a popup waits before handing the focus to a field, when giving it
|
|
16421
16541
|
// is what raises the on-screen keyboard.
|
|
16422
16542
|
//
|
|
@@ -16809,6 +16929,14 @@ const createOpenController = (
|
|
|
16809
16929
|
// whole point: learning it afterwards means the content mounted on the
|
|
16810
16930
|
// previous subject first.
|
|
16811
16931
|
onOpen: null,
|
|
16932
|
+
// What the popup is open ON, as its content reads it (usePopupValue in
|
|
16933
|
+
// popup_value.js): written at the opening, right after `onOpen`, and left
|
|
16934
|
+
// alone by the close, so the content keeps drawing it while it leaves.
|
|
16935
|
+
popupValueSignal: signal(undefined),
|
|
16936
|
+
// How the opening reads that value, set by whoever holds the open state
|
|
16937
|
+
// (see useOpenPropsEffectOnOpenController); left unset, the value the
|
|
16938
|
+
// opening carries (a --navi-open source's).
|
|
16939
|
+
readPopupValue: null,
|
|
16812
16940
|
// What an Escape means for this popup, whoever heard the key — its own
|
|
16813
16941
|
// shortcut, its trigger's, the group it stands in, a bubble's: a cancel
|
|
16814
16942
|
// (what it holds reverts), unless its owner says otherwise (a Picker's
|
|
@@ -16943,6 +17071,9 @@ const createOpenController = (
|
|
|
16943
17071
|
// openEffect, which shows it: what the popup opens ON has to be
|
|
16944
17072
|
// known before either (see `onOpen` above).
|
|
16945
17073
|
controller.onOpen?.(requestOpenEvent);
|
|
17074
|
+
controller.popupValueSignal.value = controller.readPopupValue
|
|
17075
|
+
? controller.readPopupValue(requestOpenEvent)
|
|
17076
|
+
: requestOpenEvent.detail.value;
|
|
16946
17077
|
// After prepareFocusTransfer, which has to record what held the
|
|
16947
17078
|
// focus before anything inside the popup can claim it, and before
|
|
16948
17079
|
// openEffect, which measures the popup to place it.
|
|
@@ -17304,6 +17435,39 @@ const useOpenPropsEffectOnOpenController = (
|
|
|
17304
17435
|
if (signal && open) {
|
|
17305
17436
|
openSignalValueRef.current = signal.value;
|
|
17306
17437
|
}
|
|
17438
|
+
// What the popup is open ON (see usePopupValue): the id the signal names
|
|
17439
|
+
// when it holds more than "open", else the popup's own `value`, else what the
|
|
17440
|
+
// opening carries. Read once `onOpen` has run, which may write the signal.
|
|
17441
|
+
openController.readPopupValue = (requestOpenEvent) => {
|
|
17442
|
+
if (signal) {
|
|
17443
|
+
const signalValue = signal.peek();
|
|
17444
|
+
if (signalValue !== true && readOpened(signalValue, value)) {
|
|
17445
|
+
return signalValue;
|
|
17446
|
+
}
|
|
17447
|
+
}
|
|
17448
|
+
if (value !== undefined) {
|
|
17449
|
+
return value;
|
|
17450
|
+
}
|
|
17451
|
+
return requestOpenEvent.detail.value;
|
|
17452
|
+
};
|
|
17453
|
+
// The signal walked to another id while open (a sheet's "next"): the
|
|
17454
|
+
// content follows it. Written closed, it is left alone — that is the close
|
|
17455
|
+
// starting, and the content still has its exit to draw.
|
|
17456
|
+
useLayoutEffect(() => {
|
|
17457
|
+
if (!signal) {
|
|
17458
|
+
return undefined;
|
|
17459
|
+
}
|
|
17460
|
+
return effect(() => {
|
|
17461
|
+
const signalValue = signal.value;
|
|
17462
|
+
if (
|
|
17463
|
+
openController.opened &&
|
|
17464
|
+
signalValue !== true &&
|
|
17465
|
+
readOpened(signalValue, value)
|
|
17466
|
+
) {
|
|
17467
|
+
openController.popupValueSignal.value = signalValue;
|
|
17468
|
+
}
|
|
17469
|
+
});
|
|
17470
|
+
}, [signal, value]);
|
|
17307
17471
|
// Assigned on every render, like openEffect, so it always closes over the
|
|
17308
17472
|
// latest prop: a popup that opens or closes on its own (Escape, backdrop, a
|
|
17309
17473
|
// --navi-close command) writes what happened where the caller keeps it, so
|
|
@@ -25013,6 +25177,14 @@ const arraySignalStore = (
|
|
|
25013
25177
|
if (props === null || typeof props !== "object") {
|
|
25014
25178
|
return props;
|
|
25015
25179
|
}
|
|
25180
|
+
if (props[idKey] === undefined) {
|
|
25181
|
+
// Kept under `undefined`, every such item would be one and the same: a
|
|
25182
|
+
// list drawing its last row as many times as it has rows, a creation
|
|
25183
|
+
// rewriting all of them — and nothing saying why.
|
|
25184
|
+
throw new Error(
|
|
25185
|
+
`${name || "store"}: an item arrived without "${idKey}" (it has ${Object.keys(props).join(", ")}) — declare its key with idKey, or give a single item an id of its own ({ id: "me", … })`,
|
|
25186
|
+
);
|
|
25187
|
+
}
|
|
25016
25188
|
const item = createItem(props);
|
|
25017
25189
|
return item;
|
|
25018
25190
|
};
|
|
@@ -26198,13 +26370,12 @@ const createResourceLifecycleManager = () => {
|
|
|
26198
26370
|
if (!isSameResource && !isDependent) {
|
|
26199
26371
|
continue;
|
|
26200
26372
|
}
|
|
26373
|
+
// A write of a resource this one depends on reaches its lists as it
|
|
26374
|
+
// reruns its GET and GET_MANY: being heard is the whole condition (see
|
|
26375
|
+
// findEffectOnActions). rerunOn is about this resource's own writes.
|
|
26201
26376
|
if (
|
|
26202
|
-
|
|
26203
|
-
|
|
26204
|
-
config,
|
|
26205
|
-
triggeringAction,
|
|
26206
|
-
isSameResource,
|
|
26207
|
-
)
|
|
26377
|
+
isSameResource &&
|
|
26378
|
+
!shouldReadRerunAfter("GET_RANGE", config, triggeringAction, true)
|
|
26208
26379
|
) {
|
|
26209
26380
|
continue;
|
|
26210
26381
|
}
|
|
@@ -29378,6 +29549,17 @@ const useActionAsyncData = (action, {
|
|
|
29378
29549
|
useOnLoad(action, onLoad);
|
|
29379
29550
|
usePoll(action, poll);
|
|
29380
29551
|
|
|
29552
|
+
// The instance the binding points at, remembered from one render to the
|
|
29553
|
+
// next: a binding that comes back to params whose instance failed — a search
|
|
29554
|
+
// typed again after a network blip — asks again, as typing them the first
|
|
29555
|
+
// time did. Staying on the instance that just failed asks nothing (see
|
|
29556
|
+
// runIsOwed), and neither does a mount, which never switched to anything.
|
|
29557
|
+
// Read as it stands: getCurrentAction() would flush a debounced binding,
|
|
29558
|
+
// publishing every keystroke the moment it renders.
|
|
29559
|
+
const instance = action.isProxy ? getActionPrivateProperties(action).currentAction : action;
|
|
29560
|
+
const instanceRef = useRef(instance);
|
|
29561
|
+
const backOnFailure = instanceRef.current !== instance && action.runningStateSignal.peek() === FAILED;
|
|
29562
|
+
instanceRef.current = instance;
|
|
29381
29563
|
// `run: true` — this component owns the request, so it is what starts it, and
|
|
29382
29564
|
// it starts it from the render rather than from an effect: a component that
|
|
29383
29565
|
// suspends has no effects, so a run written in one would be waiting for
|
|
@@ -29385,7 +29567,7 @@ const useActionAsyncData = (action, {
|
|
|
29385
29567
|
// no-op — which is what makes starting it while rendering sound. From there
|
|
29386
29568
|
// the wait is the ordinary one: suspended into <Loading>, or drawn by the
|
|
29387
29569
|
// component under `loading: true`, exactly as for data someone else ran.
|
|
29388
|
-
if (run && action.paramsSignal.peek() !== undefined && runIsOwed(action)) {
|
|
29570
|
+
if (run && action.paramsSignal.peek() !== undefined && (runIsOwed(action) || backOnFailure)) {
|
|
29389
29571
|
// Nothing waits on this run: the failure is held by the action, and this
|
|
29390
29572
|
// hook is what reads it back.
|
|
29391
29573
|
runUnwatched(() => action.run({
|
|
@@ -31006,6 +31188,38 @@ const resolveContainerLength = (size, element) => {
|
|
|
31006
31188
|
return (parseFloat(amount) / 100) * containerSize;
|
|
31007
31189
|
};
|
|
31008
31190
|
|
|
31191
|
+
// "s", "-m" — the spacing scale, whose tokens are ems of the font where they
|
|
31192
|
+
// apply: a length only CSS knows, handed back as the var() it maps to, which
|
|
31193
|
+
// nothing can place with. Read off the given element (the root when none is),
|
|
31194
|
+
// for a caller asking for a number.
|
|
31195
|
+
const SCALE_WORD_REGEX = /^(-?)(xxs|xs|xl|xxl|[lms])$/;
|
|
31196
|
+
const TOKEN_LENGTH_REGEX = /^(-?[\d.]+)(px|r?em)$/;
|
|
31197
|
+
const resolveScaleLength = (size, element = document.documentElement) => {
|
|
31198
|
+
if (typeof size !== "string") {
|
|
31199
|
+
return null;
|
|
31200
|
+
}
|
|
31201
|
+
const match = SCALE_WORD_REGEX.exec(size);
|
|
31202
|
+
if (!match) {
|
|
31203
|
+
return null;
|
|
31204
|
+
}
|
|
31205
|
+
const [, sign, word] = match;
|
|
31206
|
+
const computedStyle = getComputedStyle(element);
|
|
31207
|
+
const token = computedStyle.getPropertyValue(`--navi-${word}`).trim();
|
|
31208
|
+
const tokenMatch = TOKEN_LENGTH_REGEX.exec(token);
|
|
31209
|
+
if (!tokenMatch) {
|
|
31210
|
+
return null;
|
|
31211
|
+
}
|
|
31212
|
+
const [, amount, unit] = tokenMatch;
|
|
31213
|
+
let unitInPx = 1;
|
|
31214
|
+
if (unit === "em") {
|
|
31215
|
+
unitInPx = parseFloat(computedStyle.fontSize);
|
|
31216
|
+
} else if (unit === "rem") {
|
|
31217
|
+
unitInPx = parseFloat(getComputedStyle(document.documentElement).fontSize);
|
|
31218
|
+
}
|
|
31219
|
+
const length = parseFloat(amount) * unitInPx;
|
|
31220
|
+
return sign ? -length : length;
|
|
31221
|
+
};
|
|
31222
|
+
|
|
31009
31223
|
const resolveSpacingSize = (size, element, property = "padding") => {
|
|
31010
31224
|
const viewportLength = resolveViewportLength(size);
|
|
31011
31225
|
if (viewportLength !== null) {
|
|
@@ -31015,6 +31229,10 @@ const resolveSpacingSize = (size, element, property = "padding") => {
|
|
|
31015
31229
|
if (containerLength !== null) {
|
|
31016
31230
|
return containerLength;
|
|
31017
31231
|
}
|
|
31232
|
+
const scaleLength = resolveScaleLength(size, element);
|
|
31233
|
+
if (scaleLength !== null) {
|
|
31234
|
+
return scaleLength;
|
|
31235
|
+
}
|
|
31018
31236
|
return normalizeStyle(SIZE_MAP[size] || size, property, "js", element);
|
|
31019
31237
|
};
|
|
31020
31238
|
// Whether a spacing is nothing at all, answered without resolving it. A
|
|
@@ -33536,20 +33754,32 @@ const useUrlSearchParam = (paramName, defaultValue) => {
|
|
|
33536
33754
|
* the one it would have picked, painted over.
|
|
33537
33755
|
*/
|
|
33538
33756
|
|
|
33539
|
-
const headEntries = [];
|
|
33757
|
+
const headEntries$1 = [];
|
|
33540
33758
|
const popupLayers = [];
|
|
33541
33759
|
const ownMetas = [];
|
|
33542
33760
|
|
|
33543
33761
|
/**
|
|
33544
|
-
*
|
|
33545
|
-
*
|
|
33762
|
+
* A Head's place in the stack, taken as it arrives and kept while what it asks
|
|
33763
|
+
* for changes (see head.jsx).
|
|
33764
|
+
*
|
|
33765
|
+
* @returns {{
|
|
33766
|
+
* set: (themeColors: Array<{ content: string, media: string|null }>) => void,
|
|
33767
|
+
* remove: () => void,
|
|
33768
|
+
* }}
|
|
33546
33769
|
*/
|
|
33547
|
-
const pushHeadThemeColors = (
|
|
33548
|
-
|
|
33549
|
-
|
|
33550
|
-
return
|
|
33551
|
-
|
|
33552
|
-
|
|
33770
|
+
const pushHeadThemeColors = () => {
|
|
33771
|
+
const themeColors = [];
|
|
33772
|
+
headEntries$1.push(themeColors);
|
|
33773
|
+
return {
|
|
33774
|
+
set: (themeColorsNext) => {
|
|
33775
|
+
themeColors.length = 0;
|
|
33776
|
+
themeColors.push(...themeColorsNext);
|
|
33777
|
+
queueRender();
|
|
33778
|
+
},
|
|
33779
|
+
remove: () => {
|
|
33780
|
+
headEntries$1.splice(headEntries$1.indexOf(themeColors), 1);
|
|
33781
|
+
queueRender();
|
|
33782
|
+
},
|
|
33553
33783
|
};
|
|
33554
33784
|
};
|
|
33555
33785
|
|
|
@@ -33647,8 +33877,8 @@ const readBackdropColor = (element) => {
|
|
|
33647
33877
|
};
|
|
33648
33878
|
|
|
33649
33879
|
let renderQueued = false;
|
|
33650
|
-
// Once per commit: a
|
|
33651
|
-
//
|
|
33880
|
+
// Once per commit: a page leaving as another arrives, or several Heads
|
|
33881
|
+
// changing together, hand the browser one colour, never the one in between.
|
|
33652
33882
|
const queueRender = () => {
|
|
33653
33883
|
if (renderQueued) {
|
|
33654
33884
|
return;
|
|
@@ -33667,8 +33897,8 @@ const render = () => {
|
|
|
33667
33897
|
media: meta.getAttribute("media"),
|
|
33668
33898
|
}));
|
|
33669
33899
|
let colors = [];
|
|
33670
|
-
for (let i = headEntries.length - 1; i >= 0; i--) {
|
|
33671
|
-
colors.push(...headEntries[i]);
|
|
33900
|
+
for (let i = headEntries$1.length - 1; i >= 0; i--) {
|
|
33901
|
+
colors.push(...headEntries$1[i]);
|
|
33672
33902
|
}
|
|
33673
33903
|
colors.push(...htmlColors);
|
|
33674
33904
|
for (const layer of popupLayers) {
|
|
@@ -33794,67 +34024,119 @@ const drawColor = (color) => {
|
|
|
33794
34024
|
// title it found would put its own page's title over the new one. A
|
|
33795
34025
|
// theme-color meta follows the same rule, kept by theme_color.js, where the
|
|
33796
34026
|
// popups of the top layer paint over it.
|
|
33797
|
-
|
|
34027
|
+
// Arriving is mounting: a Head that renders again — a layout's head whose
|
|
34028
|
+
// count moved, children built anew at every render — is updated where it
|
|
34029
|
+
// stands, under the Heads that arrived after it. Taken off and pushed back, a
|
|
34030
|
+
// layout's head would take the title from every page below it.
|
|
34031
|
+
const headEntries = [];
|
|
33798
34032
|
let titleWithoutHead = null;
|
|
33799
34033
|
const Head = ({
|
|
33800
34034
|
children
|
|
33801
34035
|
}) => {
|
|
34036
|
+
const entryRef = useRef(null);
|
|
33802
34037
|
useLayoutEffect(() => {
|
|
33803
|
-
|
|
33804
|
-
|
|
34038
|
+
const entry = {
|
|
34039
|
+
title: null,
|
|
34040
|
+
themeColors: pushHeadThemeColors()
|
|
34041
|
+
};
|
|
34042
|
+
headEntries.push(entry);
|
|
34043
|
+
entryRef.current = entry;
|
|
34044
|
+
return () => {
|
|
34045
|
+
entry.themeColors.remove();
|
|
34046
|
+
headEntries.splice(headEntries.indexOf(entry), 1);
|
|
34047
|
+
writeDocumentTitle();
|
|
34048
|
+
};
|
|
34049
|
+
}, []);
|
|
34050
|
+
const {
|
|
34051
|
+
title,
|
|
34052
|
+
themeColors,
|
|
34053
|
+
elements
|
|
34054
|
+
} = readHeadChildren(children);
|
|
34055
|
+
// What the children say, rather than the children: the elements are built
|
|
34056
|
+
// anew at every render, and saying the same thing again changes nothing.
|
|
34057
|
+
const contentKey = JSON.stringify([title, themeColors, elements]);
|
|
34058
|
+
useLayoutEffect(() => {
|
|
34059
|
+
const entry = entryRef.current;
|
|
34060
|
+
if (title !== null && !headEntries.some(other => other.title !== null)) {
|
|
34061
|
+
titleWithoutHead = document.title;
|
|
33805
34062
|
}
|
|
33806
|
-
|
|
34063
|
+
entry.title = title;
|
|
34064
|
+
writeDocumentTitle();
|
|
34065
|
+
entry.themeColors.set(themeColors);
|
|
33807
34066
|
const appendedElements = [];
|
|
33808
|
-
const
|
|
33809
|
-
|
|
33810
|
-
|
|
33811
|
-
|
|
33812
|
-
|
|
33813
|
-
}
|
|
33814
|
-
if (child.type === "title") {
|
|
33815
|
-
const titleChildren = child.props.children;
|
|
33816
|
-
titleEntry = {
|
|
33817
|
-
title: Array.isArray(titleChildren) ? titleChildren.join("") : titleChildren ?? ""
|
|
33818
|
-
};
|
|
33819
|
-
continue;
|
|
33820
|
-
}
|
|
33821
|
-
if (child.type === "meta" && child.props.name === "theme-color") {
|
|
33822
|
-
themeColors.push({
|
|
33823
|
-
content: child.props.content,
|
|
33824
|
-
media: child.props.media ?? null
|
|
33825
|
-
});
|
|
33826
|
-
continue;
|
|
33827
|
-
}
|
|
33828
|
-
const el = document.createElement(child.type);
|
|
33829
|
-
const props = child.props || {};
|
|
34067
|
+
for (const {
|
|
34068
|
+
type,
|
|
34069
|
+
props
|
|
34070
|
+
} of elements) {
|
|
34071
|
+
const el = document.createElement(type);
|
|
33830
34072
|
for (const [key, value] of Object.entries(props)) {
|
|
33831
34073
|
el.setAttribute(key, value);
|
|
33832
34074
|
}
|
|
33833
34075
|
document.head.appendChild(el);
|
|
33834
34076
|
appendedElements.push(el);
|
|
33835
34077
|
}
|
|
33836
|
-
if (titleEntry) {
|
|
33837
|
-
if (titleEntries.length === 0) {
|
|
33838
|
-
titleWithoutHead = document.title;
|
|
33839
|
-
}
|
|
33840
|
-
titleEntries.push(titleEntry);
|
|
33841
|
-
document.title = titleEntry.title;
|
|
33842
|
-
}
|
|
33843
|
-
const removeThemeColors = themeColors.length > 0 ? pushHeadThemeColors(themeColors) : null;
|
|
33844
34078
|
return () => {
|
|
33845
|
-
removeThemeColors?.();
|
|
33846
|
-
if (titleEntry) {
|
|
33847
|
-
titleEntries.splice(titleEntries.indexOf(titleEntry), 1);
|
|
33848
|
-
const lastEntry = titleEntries[titleEntries.length - 1];
|
|
33849
|
-
document.title = lastEntry ? lastEntry.title : titleWithoutHead;
|
|
33850
|
-
}
|
|
33851
34079
|
for (const el of appendedElements) {
|
|
33852
34080
|
el.remove();
|
|
33853
34081
|
}
|
|
33854
34082
|
};
|
|
33855
|
-
}, [
|
|
34083
|
+
}, [contentKey]);
|
|
33856
34084
|
return null;
|
|
33857
34085
|
};
|
|
34086
|
+
const writeDocumentTitle = () => {
|
|
34087
|
+
for (let i = headEntries.length - 1; i >= 0; i--) {
|
|
34088
|
+
const {
|
|
34089
|
+
title
|
|
34090
|
+
} = headEntries[i];
|
|
34091
|
+
if (title !== null) {
|
|
34092
|
+
document.title = title;
|
|
34093
|
+
return;
|
|
34094
|
+
}
|
|
34095
|
+
}
|
|
34096
|
+
if (titleWithoutHead !== null) {
|
|
34097
|
+
document.title = titleWithoutHead;
|
|
34098
|
+
titleWithoutHead = null;
|
|
34099
|
+
}
|
|
34100
|
+
};
|
|
34101
|
+
const readHeadChildren = children => {
|
|
34102
|
+
let title = null;
|
|
34103
|
+
const themeColors = [];
|
|
34104
|
+
const elements = [];
|
|
34105
|
+
if (!children) {
|
|
34106
|
+
return {
|
|
34107
|
+
title,
|
|
34108
|
+
themeColors,
|
|
34109
|
+
elements
|
|
34110
|
+
};
|
|
34111
|
+
}
|
|
34112
|
+
const childArray = Array.isArray(children) ? children : [children];
|
|
34113
|
+
for (const child of childArray) {
|
|
34114
|
+
if (!child) {
|
|
34115
|
+
continue;
|
|
34116
|
+
}
|
|
34117
|
+
if (child.type === "title") {
|
|
34118
|
+
const titleChildren = child.props.children;
|
|
34119
|
+
title = Array.isArray(titleChildren) ? titleChildren.join("") : titleChildren ?? "";
|
|
34120
|
+
continue;
|
|
34121
|
+
}
|
|
34122
|
+
if (child.type === "meta" && child.props.name === "theme-color") {
|
|
34123
|
+
themeColors.push({
|
|
34124
|
+
content: child.props.content,
|
|
34125
|
+
media: child.props.media ?? null
|
|
34126
|
+
});
|
|
34127
|
+
continue;
|
|
34128
|
+
}
|
|
34129
|
+
elements.push({
|
|
34130
|
+
type: child.type,
|
|
34131
|
+
props: child.props || {}
|
|
34132
|
+
});
|
|
34133
|
+
}
|
|
34134
|
+
return {
|
|
34135
|
+
title,
|
|
34136
|
+
themeColors,
|
|
34137
|
+
elements
|
|
34138
|
+
};
|
|
34139
|
+
};
|
|
33858
34140
|
|
|
33859
34141
|
/**
|
|
33860
34142
|
* A page is `{ route, params }`, never the route alone: a section of a page is
|
|
@@ -40510,7 +40792,7 @@ const resolveCommandValue = (source, event) => {
|
|
|
40510
40792
|
return event.detail.value;
|
|
40511
40793
|
}
|
|
40512
40794
|
if (source.hasAttribute("command-value")) {
|
|
40513
|
-
return source
|
|
40795
|
+
return readCommandValue(source);
|
|
40514
40796
|
}
|
|
40515
40797
|
if (source.type === "radio" || source.type === "checkbox") {
|
|
40516
40798
|
// Use readControlValue so that radio/checkbox sources return their `value`
|
|
@@ -40526,6 +40808,20 @@ const resolveCommandValue = (source, event) => {
|
|
|
40526
40808
|
// selected, and the screen it opens would prefill a new entry with it.
|
|
40527
40809
|
return getUIStateFromElement(source, { own: true });
|
|
40528
40810
|
};
|
|
40811
|
+
// The value as it was given: a <Button command-value={12}> holds the number, an
|
|
40812
|
+
// object, whatever the prop said, where its attribute can only say a string. A
|
|
40813
|
+
// plain element carrying the attribute says that string.
|
|
40814
|
+
const readCommandValue = (source) => {
|
|
40815
|
+
let responded = false;
|
|
40816
|
+
let value;
|
|
40817
|
+
dispatchCustomEvent(source, "navi_get_command_value", {
|
|
40818
|
+
respondWith: (jsValue) => {
|
|
40819
|
+
responded = true;
|
|
40820
|
+
value = jsValue;
|
|
40821
|
+
},
|
|
40822
|
+
});
|
|
40823
|
+
return responded ? value : source.getAttribute("command-value");
|
|
40824
|
+
};
|
|
40529
40825
|
|
|
40530
40826
|
const onNaviCommand = (e, { debugCommand = () => {} } = {}) => {
|
|
40531
40827
|
const { command, event, source, implementation } = e.detail;
|
|
@@ -41292,7 +41588,11 @@ const executeNaviDefine = (source, event, target) => {
|
|
|
41292
41588
|
// reads it (see List). "--navi-scroll:smooth" asks for the glide.
|
|
41293
41589
|
const scrollCommand = (source, event, { argument, value }) => {
|
|
41294
41590
|
const target =
|
|
41295
|
-
resolveExplicitTarget(source) ||
|
|
41591
|
+
resolveExplicitTarget(source) ||
|
|
41592
|
+
// The list sending it about itself, as List's JSDoc writes a scroll asked
|
|
41593
|
+
// by code: triggerNaviCommand(listEl, "--navi-scroll", event, { value }).
|
|
41594
|
+
(source.matches(".navi_list_container") ? source : null) ||
|
|
41595
|
+
resolveFirstParentControl(source);
|
|
41296
41596
|
if (!target) {
|
|
41297
41597
|
return undefined;
|
|
41298
41598
|
}
|
|
@@ -42786,6 +43086,9 @@ const useAutoFocus = (
|
|
|
42786
43086
|
`[autofocus] "${ancestorType}" opened ${getElementSignature(ancestor)} -> ${focusDebugCall}`,
|
|
42787
43087
|
);
|
|
42788
43088
|
}
|
|
43089
|
+
if (focusVisible === true) {
|
|
43090
|
+
askFocusVisible(focusableElement);
|
|
43091
|
+
}
|
|
42789
43092
|
focusableElement.focus({ preventScroll, focusVisible });
|
|
42790
43093
|
if (autoSelect) {
|
|
42791
43094
|
focusableElement.select();
|
|
@@ -47711,12 +48014,17 @@ const useControlProps = (props, {
|
|
|
47711
48014
|
}
|
|
47712
48015
|
};
|
|
47713
48016
|
}
|
|
48017
|
+
|
|
48018
|
+
// A field with an action of its own has Enter answered already: the
|
|
48019
|
+
// input effect (input_effect.js) commits it — through the change Enter
|
|
48020
|
+
// fires, or on the keydown itself under actionDebounce — and an action
|
|
48021
|
+
// run on every keystroke has nothing left to commit. --navi-send would
|
|
48022
|
+
// run that same action a second time. Nothing answers it under
|
|
48023
|
+
// actionEvent="custom", where the field's caller does.
|
|
48024
|
+
const enterAnsweredByInputEffect = Boolean(actionDebounce) || props.action !== undefined && actionEvent !== "custom";
|
|
47714
48025
|
const keyDownDefaultOnInput = e => {
|
|
47715
48026
|
if (e.key === "Enter") {
|
|
47716
|
-
if (
|
|
47717
|
-
// The input has its own debounced action; Enter fires it directly
|
|
47718
|
-
// (input_effect.js cancels the debounce and triggers the action via the change event).
|
|
47719
|
-
// Don't propagate to --navi-send, which would cause a double action call.
|
|
48027
|
+
if (enterAnsweredByInputEffect) {
|
|
47720
48028
|
return null;
|
|
47721
48029
|
}
|
|
47722
48030
|
return enterToSend(e);
|
|
@@ -52376,12 +52684,15 @@ const TextOverflow = ({
|
|
|
52376
52684
|
}) => {
|
|
52377
52685
|
return jsx(Text, {
|
|
52378
52686
|
block: true,
|
|
52379
|
-
as: "div"
|
|
52380
|
-
|
|
52687
|
+
as: "div"
|
|
52688
|
+
// One line does not wrap, at a typed newline either: white-space: pre
|
|
52689
|
+
// would keep every newline, and the text would be one line only while it
|
|
52690
|
+
// has none. A white-space the caller says wins.
|
|
52691
|
+
,
|
|
52692
|
+
noWrap: noWrap ?? (rest.as === "p" || saysWhiteSpace(rest) ? undefined : true)
|
|
52381
52693
|
// For paragraph we prefer to keep lines and only hide unbreakable long sections
|
|
52382
52694
|
,
|
|
52383
52695
|
preLine: rest.as === "p" ? true : undefined,
|
|
52384
|
-
noWrap: noWrap,
|
|
52385
52696
|
...rest,
|
|
52386
52697
|
maxLines: undefined,
|
|
52387
52698
|
"data-text-overflow": "",
|
|
@@ -57955,7 +58266,7 @@ const css$S = /* css */`@layer navi {
|
|
|
57955
58266
|
transparent);
|
|
57956
58267
|
}
|
|
57957
58268
|
|
|
57958
|
-
.navi_button
|
|
58269
|
+
.navi_button {
|
|
57959
58270
|
background: none;
|
|
57960
58271
|
border: none;
|
|
57961
58272
|
padding: 0;
|
|
@@ -57987,10 +58298,8 @@ a.navi_button {
|
|
|
57987
58298
|
outline: none;
|
|
57988
58299
|
position: relative;
|
|
57989
58300
|
|
|
57990
|
-
|
|
57991
|
-
|
|
57992
|
-
border: none;
|
|
57993
|
-
padding: 0;
|
|
58301
|
+
& .navi_button_content > [data-navi-space] {
|
|
58302
|
+
display: contents;
|
|
57994
58303
|
}
|
|
57995
58304
|
|
|
57996
58305
|
& .navi_button_content {
|
|
@@ -58265,6 +58574,12 @@ const ButtonUI = props => {
|
|
|
58265
58574
|
,
|
|
58266
58575
|
onnavi_get_value: e => {
|
|
58267
58576
|
e.detail.respondWith(props.value);
|
|
58577
|
+
}
|
|
58578
|
+
// Same for what a command is about, when it is not the button's value
|
|
58579
|
+
// (see resolveCommandValue).
|
|
58580
|
+
,
|
|
58581
|
+
onnavi_get_command_value: e => {
|
|
58582
|
+
e.detail.respondWith(props["command-value"]);
|
|
58268
58583
|
},
|
|
58269
58584
|
onContextMenu: e => {
|
|
58270
58585
|
if (as === "a") {
|
|
@@ -58305,7 +58620,12 @@ const ButtonUI = props => {
|
|
|
58305
58620
|
...controlChildrenWrapperProps,
|
|
58306
58621
|
children: jsx(ButtonContent, {
|
|
58307
58622
|
spacing: spacing,
|
|
58308
|
-
contentDisplay: contentDisplay
|
|
58623
|
+
contentDisplay: contentDisplay
|
|
58624
|
+
// The frame lays the children out in the button's flow: told so, a
|
|
58625
|
+
// `spacing` is its gap rather than a space one line tall. Not without
|
|
58626
|
+
// a frame: the button's box lays them out then.
|
|
58627
|
+
,
|
|
58628
|
+
flex: contentDisplay === "contents" ? undefined : props.flex ?? (icon ? "x" : undefined),
|
|
58309
58629
|
children: children
|
|
58310
58630
|
})
|
|
58311
58631
|
})]
|
|
@@ -58318,12 +58638,14 @@ const ButtonUI = props => {
|
|
|
58318
58638
|
const ButtonContent = ({
|
|
58319
58639
|
spacing,
|
|
58320
58640
|
contentDisplay = "inherit",
|
|
58641
|
+
flex,
|
|
58321
58642
|
children
|
|
58322
58643
|
}) => {
|
|
58323
58644
|
const boxForwardedProps = useContext(BoxForwardedPropsContext);
|
|
58324
58645
|
return jsxs(Text, {
|
|
58325
58646
|
...boxForwardedProps,
|
|
58326
58647
|
display: contentDisplay,
|
|
58648
|
+
flex: flex,
|
|
58327
58649
|
spacing: spacing,
|
|
58328
58650
|
className: "navi_button_content",
|
|
58329
58651
|
children: [children, jsx(ButtonShadow, {})]
|
|
@@ -68496,7 +68818,10 @@ const engageGroup = (groupEl, group, {
|
|
|
68496
68818
|
const focusWasInGroup = Boolean(focusedBefore) && focusedBefore !== groupEl && groupEl.contains(focusedBefore);
|
|
68497
68819
|
// What the focus goes back to, when nothing holds it any more at the close.
|
|
68498
68820
|
const focusOrigin = !focusWasInGroup && focusedBefore && focusedBefore !== document.body && focusedBefore !== groupEl ? focusedBefore : null;
|
|
68499
|
-
|
|
68821
|
+
// The ring navi drew, not the browser's flag: the flag outlives a press
|
|
68822
|
+
// whose mousedown was prevented, and given back as `focusVisible: true` it
|
|
68823
|
+
// would draw a ring nobody saw before (see isMatchingFocusVisible).
|
|
68824
|
+
const ringBefore = Boolean(focusedBefore?.matches && isMatchingFocusVisible(focusedBefore));
|
|
68500
68825
|
const {
|
|
68501
68826
|
scrollTop,
|
|
68502
68827
|
scrollLeft
|
|
@@ -68672,7 +68997,7 @@ const engageGroup = (groupEl, group, {
|
|
|
68672
68997
|
// or the user, put it since. Unless nothing moved it, that element is
|
|
68673
68998
|
// made no focus target for the call: inert — or, holding the focus
|
|
68674
68999
|
// inside it, without its tabindex, inert taking the focus with it.
|
|
68675
|
-
const ringBeforeClose = Boolean(focusedBeforeClose?.matches
|
|
69000
|
+
const ringBeforeClose = Boolean(focusedBeforeClose?.matches && isMatchingFocusVisible(focusedBeforeClose));
|
|
68676
69001
|
const focusMovedInGroup = focusWasInGroup && focusedBeforeClose && focusedBeforeClose !== document.body && focusedBeforeClose !== groupEl && focusedBeforeClose !== focusedBefore && focusedBeforeClose.isConnected && focusedBefore.isConnected;
|
|
68677
69002
|
const holdsFocusInside = focusMovedInGroup && focusedBefore.contains(focusedBeforeClose);
|
|
68678
69003
|
const madeInert = focusMovedInGroup && !holdsFocusInside && !focusedBefore.inert;
|
|
@@ -70655,6 +70980,29 @@ const usePopupName = ({
|
|
|
70655
70980
|
};
|
|
70656
70981
|
const NO_TITLE = [];
|
|
70657
70982
|
|
|
70983
|
+
// The open controller's popupValueSignal (see open_controller.js), handed to
|
|
70984
|
+
// the content by whatever renders it: Dialog, Popover, a picker's callout.
|
|
70985
|
+
const PopupValueContext = createContext(null);
|
|
70986
|
+
|
|
70987
|
+
/**
|
|
70988
|
+
* What the popup this is rendered inside is open ON: the value its `signal`
|
|
70989
|
+
* held while it read open (the id a single sheet bound to `?open=<id>` shows),
|
|
70990
|
+
* else its `value`, else the value of whatever opened it
|
|
70991
|
+
* (`<Button value={id} command="--navi-open">`).
|
|
70992
|
+
*
|
|
70993
|
+
* Held from the opening to the end of the exit, whoever asks the close: the
|
|
70994
|
+
* signal and the address read closed as soon as the close starts, while an
|
|
70995
|
+
* animated exit — and a lift flying back to the card it came from — still
|
|
70996
|
+
* draws what the content renders. A refused close keeps it; a reopening on
|
|
70997
|
+
* another value switches it at the reopening.
|
|
70998
|
+
*
|
|
70999
|
+
* @returns {any} `undefined` outside a popup.
|
|
71000
|
+
*/
|
|
71001
|
+
const usePopupValue = () => {
|
|
71002
|
+
const popupValueSignal = useContext(PopupValueContext);
|
|
71003
|
+
return popupValueSignal ? popupValueSignal.value : undefined;
|
|
71004
|
+
};
|
|
71005
|
+
|
|
70658
71006
|
installImportMetaCssBuild(import.meta);
|
|
70659
71007
|
// Same need popover.jsx has for its own local renderer (see its
|
|
70660
71008
|
// openLocalPopoverCount): a layer="local" dialog is a plain positioned element
|
|
@@ -71599,7 +71947,7 @@ const css$C = /* css */`
|
|
|
71599
71947
|
* whatever triggered the open (`e.detail.source`). A string is resolved via
|
|
71600
71948
|
* `document.getElementById` when the dialog opens — see popover.jsx's own
|
|
71601
71949
|
* `anchor` doc for why (mainly `defaultOpen`).
|
|
71602
|
-
* @param {Element|{current: Element}|string} [props.liftAnchor] - Under
|
|
71950
|
+
* @param {Element|{current: Element}|string|((popupValue: any) => Element|{current: Element}|string)} [props.liftAnchor] - Under
|
|
71603
71951
|
* `animation="lifting"` or `animation={{ open, close: "lifting" }}`, where the closing
|
|
71604
71952
|
* brings the box back to, when that is not where it came from: a popup one
|
|
71605
71953
|
* walks through (a row of cards shown one at a time) has something else in
|
|
@@ -71607,8 +71955,10 @@ const css$C = /* css */`
|
|
|
71607
71955
|
* card the press opened on. Same grammar as `anchor` (element, ref or id),
|
|
71608
71956
|
* resolved once the close is made — after `onClose` — so whatever names the
|
|
71609
71957
|
* card currently in front, or the box the close itself renders, is read
|
|
71610
|
-
* then and not at the opening.
|
|
71611
|
-
*
|
|
71958
|
+
* then and not at the opening. A function is called then with what the
|
|
71959
|
+
* dialog was open on (see `usePopupValue`): a close the holder asks for
|
|
71960
|
+
* (Back taking the id out of the address) has emptied its signal by then.
|
|
71961
|
+
* Left out, the box comes back to the anchor it came out of.
|
|
71612
71962
|
* @param {boolean} [props.sizeFromAnchor=false] - Whether the dialog takes the
|
|
71613
71963
|
* anchor's width/height as a min-width/min-height floor
|
|
71614
71964
|
* (`--anchor-width`/`--anchor-height`). Off by default: unlike a popover,
|
|
@@ -72139,9 +72489,12 @@ const useDialogProps = props => {
|
|
|
72139
72489
|
openerAriaLabel,
|
|
72140
72490
|
openerAriaLabelledBy
|
|
72141
72491
|
});
|
|
72142
|
-
const children = contentMounted ? jsx(
|
|
72143
|
-
value:
|
|
72144
|
-
children:
|
|
72492
|
+
const children = contentMounted ? jsx(PopupValueContext.Provider, {
|
|
72493
|
+
value: openController.popupValueSignal,
|
|
72494
|
+
children: jsx(PopupTitleContext.Provider, {
|
|
72495
|
+
value: registerTitle,
|
|
72496
|
+
children: childrenProp
|
|
72497
|
+
})
|
|
72145
72498
|
}) : null;
|
|
72146
72499
|
// Where it is placed, and whether there is a wall — the two questions that
|
|
72147
72500
|
// pick the show call (see this file's top comment).
|
|
@@ -72336,12 +72689,18 @@ const useDialogProps = props => {
|
|
|
72336
72689
|
// Silent when it names nothing: the close may be what renders it, and
|
|
72337
72690
|
// popup_lift.js asks again until it is there (and warns past that).
|
|
72338
72691
|
const resolveLiftAnchorElement = () => {
|
|
72339
|
-
|
|
72340
|
-
|
|
72692
|
+
// Asked with what the dialog was open on, which the signal holding it no
|
|
72693
|
+
// longer says once the close has started (see usePopupValue).
|
|
72694
|
+
const named = typeof liftAnchor === "function" ? liftAnchor(openController.popupValueSignal.peek()) : liftAnchor;
|
|
72695
|
+
if (!named) {
|
|
72696
|
+
return null;
|
|
72697
|
+
}
|
|
72698
|
+
if (typeof named === "string") {
|
|
72699
|
+
return document.getElementById(named);
|
|
72341
72700
|
}
|
|
72342
72701
|
// A ref is unwrapped even when it holds nothing, the same way `anchor` is:
|
|
72343
72702
|
// the ref object itself has no box to come back to.
|
|
72344
|
-
return "current" in
|
|
72703
|
+
return "current" in named ? named.current : named;
|
|
72345
72704
|
};
|
|
72346
72705
|
|
|
72347
72706
|
// The dialog and the anchor are the same box at two sizes, so the opening
|
|
@@ -72564,10 +72923,10 @@ const useDialogProps = props => {
|
|
|
72564
72923
|
// resolveSpacingSize walks up from there to find that container.
|
|
72565
72924
|
let marginWithContainerInPixels = resolveSpacingSize(marginWithContainer, dialogEl.parentElement);
|
|
72566
72925
|
if (typeof marginWithContainerInPixels !== "number") {
|
|
72567
|
-
// A value only CSS could evaluate (a
|
|
72568
|
-
//
|
|
72569
|
-
//
|
|
72570
|
-
console.warn(`Dialog: marginWithContainer="${marginWithContainer}" cannot be resolved to pixels. Use a number, a viewport length ("3appw", "3vvw", "2vvh") or a container length ("3cqw", "2cqh").`);
|
|
72926
|
+
// A value only CSS could evaluate (a percentage, a calc()…) — the
|
|
72927
|
+
// placement below needs a real number, and letting it through would
|
|
72928
|
+
// put the dialog at NaN.
|
|
72929
|
+
console.warn(`Dialog: marginWithContainer="${marginWithContainer}" cannot be resolved to pixels. Use a number, a spacing word ("s", "m"…), a viewport length ("3appw", "3vvw", "2vvh") or a container length ("3cqw", "2cqh").`);
|
|
72571
72930
|
marginWithContainerInPixels = 0;
|
|
72572
72931
|
}
|
|
72573
72932
|
// The size caps read the same gap in CSS as the placement below applies
|
|
@@ -73542,9 +73901,11 @@ const css$B = /* css */`
|
|
|
73542
73901
|
* big to bother anchoring to (`isAnchorTooBig`, always checked — see
|
|
73543
73902
|
* `pickPositionRelativeTo`'s own doc in visible_rect.js).
|
|
73544
73903
|
* @param {string|number} [props.marginWithContainer=0] - Extra spacing kept
|
|
73545
|
-
* between the popover and the edges of its container
|
|
73904
|
+
* between the popover and the edges of its container: a number of px, a
|
|
73905
|
+
* spacing word (`"s"`, read at the page's font size), a viewport length
|
|
73906
|
+
* (`"3appw"`) or a container length (`"3cqw"`).
|
|
73546
73907
|
* @param {string|number} [props.marginWithAnchor=0] - Extra spacing kept
|
|
73547
|
-
* between the popover and the edges of its anchor.
|
|
73908
|
+
* between the popover and the edges of its anchor, written the same way.
|
|
73548
73909
|
* @param {boolean} [props.backdrop=true] - Whether anything is laid between
|
|
73549
73910
|
* the popover and the page at all — asked before what an outside press does
|
|
73550
73911
|
* and before how the backdrop is painted. `false` leaves the page
|
|
@@ -74006,9 +74367,12 @@ const usePopoverProps = props => {
|
|
|
74006
74367
|
openerAriaLabel,
|
|
74007
74368
|
openerAriaLabelledBy
|
|
74008
74369
|
});
|
|
74009
|
-
const children = contentMounted ? jsx(
|
|
74010
|
-
value:
|
|
74011
|
-
children:
|
|
74370
|
+
const children = contentMounted ? jsx(PopupValueContext.Provider, {
|
|
74371
|
+
value: openController.popupValueSignal,
|
|
74372
|
+
children: jsx(PopupTitleContext.Provider, {
|
|
74373
|
+
value: registerTitle,
|
|
74374
|
+
children: childrenProp
|
|
74375
|
+
})
|
|
74012
74376
|
}) : null;
|
|
74013
74377
|
const isTopLayer = layer === "top";
|
|
74014
74378
|
const ref = props.ref;
|
|
@@ -74314,8 +74678,8 @@ const usePopoverProps = props => {
|
|
|
74314
74678
|
positionArea,
|
|
74315
74679
|
positionAreaFixed,
|
|
74316
74680
|
positionAreaWhenAnchorIsInvalid,
|
|
74317
|
-
marginWithAnchor:
|
|
74318
|
-
marginWithContainer:
|
|
74681
|
+
marginWithAnchor: resolveMarginInPixels(marginWithAnchor, "marginWithAnchor"),
|
|
74682
|
+
marginWithContainer: resolveMarginInPixels(marginWithContainer, "marginWithContainer"),
|
|
74319
74683
|
// Only meaningful for the custom renderer: popoverEl is always
|
|
74320
74684
|
// position: absolute relative to its own positioned ancestor,
|
|
74321
74685
|
// real anchor or not — this tells pickPositionRelativeTo to
|
|
@@ -74372,7 +74736,7 @@ const usePopoverProps = props => {
|
|
|
74372
74736
|
const pickOptions = {
|
|
74373
74737
|
positionArea,
|
|
74374
74738
|
container: positionedAncestor,
|
|
74375
|
-
marginWithContainer:
|
|
74739
|
+
marginWithContainer: resolveMarginInPixels(marginWithContainer, "marginWithContainer"),
|
|
74376
74740
|
event: positionEvent
|
|
74377
74741
|
};
|
|
74378
74742
|
position = pickPositionRelativeTo(popoverEl, null, pickOptions);
|
|
@@ -74947,6 +75311,17 @@ const resolvePositionAreaAndAnimationKind = ({
|
|
|
74947
75311
|
Popover.Close = PopupClose;
|
|
74948
75312
|
Popover.Title = PopupTitle;
|
|
74949
75313
|
|
|
75314
|
+
// The placement needs pixels: a value only CSS could evaluate (a percentage, a
|
|
75315
|
+
// calc()…) would put the popover at NaN, which is the top of the page.
|
|
75316
|
+
const resolveMarginInPixels = (margin, name) => {
|
|
75317
|
+
const pixels = resolveSpacingSize(margin);
|
|
75318
|
+
if (typeof pixels === "number") {
|
|
75319
|
+
return pixels;
|
|
75320
|
+
}
|
|
75321
|
+
console.warn(`Popover: ${name}="${margin}" cannot be resolved to pixels. Use a number, a spacing word ("xs", "s", "m"…), a viewport length ("3appw", "3vvw") or a container length ("3cqw", "2cqh").`);
|
|
75322
|
+
return 0;
|
|
75323
|
+
};
|
|
75324
|
+
|
|
74950
75325
|
installImportMetaCssBuild(import.meta);
|
|
74951
75326
|
const css$A = /* css */`@layer navi {
|
|
74952
75327
|
.navi_popup {
|
|
@@ -75006,7 +75381,7 @@ const css$A = /* css */`@layer navi {
|
|
|
75006
75381
|
* `maxWidth` below.
|
|
75007
75382
|
* @param {boolean} [props.sizeFromAnchor] - **Dialog-only**, same guard.
|
|
75008
75383
|
* @param {"box"|"scene"} [props.lift] - **Dialog-only**, same guard.
|
|
75009
|
-
* @param {Element|{current: Element}|string} [props.liftAnchor] -
|
|
75384
|
+
* @param {Element|{current: Element}|string|((popupValue: any) => Element|{current: Element}|string)} [props.liftAnchor] -
|
|
75010
75385
|
* **Dialog-only**, same guard.
|
|
75011
75386
|
* @param {string} [props.positionArea] - Forwarded as-is — `Dialog` and
|
|
75012
75387
|
* `Popover` have different own defaults (`"center"` vs. `"bottom"`),
|
|
@@ -75295,9 +75670,12 @@ const getPickerHostLabelId = (id, props) => {
|
|
|
75295
75670
|
* right now: in the popup, what is being picked, before anything is sent; on
|
|
75296
75671
|
* the façade, the answer the popup just closed on, before the server has said
|
|
75297
75672
|
* anything, and put back if the action fails. `loading` is the run in flight;
|
|
75298
|
-
* `interactive` is false while the picker is disabled, read-only or busy
|
|
75673
|
+
* `interactive` is false while the picker is disabled, read-only or busy;
|
|
75674
|
+
* `readOnly` says the picker is read-only or held by the network policy — a
|
|
75675
|
+
* hold the controls a caller draws on the façade are not held by, so a face
|
|
75676
|
+
* that wants to look held reads it here.
|
|
75299
75677
|
*
|
|
75300
|
-
* @returns {{ value: any, loading: boolean, interactive: boolean } | null}
|
|
75678
|
+
* @returns {{ value: any, loading: boolean, interactive: boolean, readOnly: boolean } | null}
|
|
75301
75679
|
* null outside a picker.
|
|
75302
75680
|
*/
|
|
75303
75681
|
const usePickerState = () => {
|
|
@@ -75308,12 +75686,14 @@ const usePickerState = () => {
|
|
|
75308
75686
|
const {
|
|
75309
75687
|
value,
|
|
75310
75688
|
loading,
|
|
75311
|
-
interactive
|
|
75689
|
+
interactive,
|
|
75690
|
+
readOnly
|
|
75312
75691
|
} = context;
|
|
75313
75692
|
return {
|
|
75314
75693
|
value,
|
|
75315
75694
|
loading,
|
|
75316
|
-
interactive
|
|
75695
|
+
interactive,
|
|
75696
|
+
readOnly
|
|
75317
75697
|
};
|
|
75318
75698
|
};
|
|
75319
75699
|
|
|
@@ -75651,6 +76031,9 @@ const PickerCustom = props => {
|
|
|
75651
76031
|
onConfirm,
|
|
75652
76032
|
onClose
|
|
75653
76033
|
};
|
|
76034
|
+
// The press the trigger's mousedown answered (see its reactions below): the
|
|
76035
|
+
// click it ends with is that press, not a second question.
|
|
76036
|
+
const pressAnsweredAtMouseDownRef = useRef(null);
|
|
75654
76037
|
// aria-controls + id
|
|
75655
76038
|
const popupId = `${props.id}_picker_popup`;
|
|
75656
76039
|
{
|
|
@@ -76142,6 +76525,7 @@ const PickerCustom = props => {
|
|
|
76142
76525
|
// Closing stays on the press even then: a gesture starting on an
|
|
76143
76526
|
// open picker wants the popup out of the way, and there is no
|
|
76144
76527
|
// choice being taken from anyone.
|
|
76528
|
+
pressAnsweredAtMouseDownRef.current = readPressCount();
|
|
76145
76529
|
return {
|
|
76146
76530
|
name: "mousedown to close picker",
|
|
76147
76531
|
intent: "read",
|
|
@@ -76160,6 +76544,7 @@ const PickerCustom = props => {
|
|
|
76160
76544
|
if (!opensOnPress || interactionsDispute || isPressDisputedByDrag(e.target) || isPressDisputedByHold(ref.current)) {
|
|
76161
76545
|
return null;
|
|
76162
76546
|
}
|
|
76547
|
+
pressAnsweredAtMouseDownRef.current = readPressCount();
|
|
76163
76548
|
return {
|
|
76164
76549
|
name: "mousedown to open picker",
|
|
76165
76550
|
intent: "read",
|
|
@@ -76173,6 +76558,15 @@ const PickerCustom = props => {
|
|
|
76173
76558
|
if (isWithinPickerContent(e.target)) {
|
|
76174
76559
|
return null;
|
|
76175
76560
|
}
|
|
76561
|
+
// One press, one answer: the press its mousedown answered is only
|
|
76562
|
+
// ending. Asked again, a refusal still on screen would read this
|
|
76563
|
+
// click as "got it" and take its explanation down before a frame
|
|
76564
|
+
// is drawn — under a finger the mousedown and the click arrive
|
|
76565
|
+
// together, after touchend (see reportInteractivity).
|
|
76566
|
+
if (e.detail !== 0 && pressAnsweredAtMouseDownRef.current === readPressCount()) {
|
|
76567
|
+
e.preventDefault();
|
|
76568
|
+
return null;
|
|
76569
|
+
}
|
|
76176
76570
|
// Still open at the click of a later press: that press brought no
|
|
76177
76571
|
// mousedown to close on (a drag source cancelled its pointerdown),
|
|
76178
76572
|
// so it closes here, as it opens here in that case. A mousedown
|
|
@@ -76278,17 +76672,35 @@ const getTriggerLabelIds = pickerEl => {
|
|
|
76278
76672
|
return ids.length === 0 ? undefined : ids.join(" ");
|
|
76279
76673
|
};
|
|
76280
76674
|
// What the picker holds without the person having changed it: its `value` (or
|
|
76281
|
-
// signal) moving, a default moving under it
|
|
76282
|
-
//
|
|
76283
|
-
//
|
|
76675
|
+
// signal) moving, a default moving under it, and what its popup's controls are
|
|
76676
|
+
// placed on as they mount. Read along the chain, never off the event alone: a
|
|
76677
|
+
// control in the popup carries its change up to the picker as an event of its
|
|
76678
|
+
// own (see the facade in ui_state_controller.js), chained to what caused it —
|
|
76679
|
+
// an app writing that control's bound signal included.
|
|
76680
|
+
const OUTSIDE_WRITE_TYPE_SET = new Set(["state_prop_change", "initial_state_push", "facade_child_mount_sync", "outside_value_follow"]);
|
|
76284
76681
|
const isWrittenByTheOutside = e => {
|
|
76285
76682
|
if (!e) {
|
|
76286
76683
|
return false;
|
|
76287
76684
|
}
|
|
76288
|
-
|
|
76685
|
+
return Boolean(findEvent(e, event => OUTSIDE_WRITE_TYPE_SET.has(event.type)));
|
|
76686
|
+
};
|
|
76687
|
+
// The popup echoes the trigger's corners (see the CSS above), right for a
|
|
76688
|
+
// length and wrong for a shape: a round trigger's 50% read on a sheet of
|
|
76689
|
+
// another size is an ellipse, and a pill's 999px a stadium. A shape leaves the
|
|
76690
|
+
// popup on the corners every popup has.
|
|
76691
|
+
const PILL_RADIUS_MIN_PX = 100;
|
|
76692
|
+
const isBorderRadiusAShape = borderRadius => {
|
|
76693
|
+
if (typeof borderRadius === "number") {
|
|
76694
|
+
return borderRadius >= PILL_RADIUS_MIN_PX;
|
|
76695
|
+
}
|
|
76696
|
+
if (typeof borderRadius !== "string") {
|
|
76697
|
+
return false;
|
|
76698
|
+
}
|
|
76699
|
+
const radius = borderRadius.trim();
|
|
76700
|
+
if (radius.endsWith("%")) {
|
|
76289
76701
|
return true;
|
|
76290
76702
|
}
|
|
76291
|
-
return
|
|
76703
|
+
return radius.endsWith("px") && parseFloat(radius) >= PILL_RADIUS_MIN_PX;
|
|
76292
76704
|
};
|
|
76293
76705
|
const getPickerInputUIState = pickerEl => {
|
|
76294
76706
|
const pickerInput = getPickerInput(pickerEl);
|
|
@@ -76463,7 +76875,7 @@ const PickerContentInsidePopup = props => {
|
|
|
76463
76875
|
,
|
|
76464
76876
|
"data-picker-popup": "",
|
|
76465
76877
|
backgroundColor: popupBackgroundColor,
|
|
76466
|
-
borderRadius: popupBorderRadius,
|
|
76878
|
+
borderRadius: popupBorderRadius === undefined && isBorderRadiusAShape(props.borderRadius) ? "var(--navi-popup-border-radius)" : popupBorderRadius,
|
|
76467
76879
|
boxShadow: popupBoxShadow,
|
|
76468
76880
|
borderWidth: isPopover ? undefined : dialogBorderWidth,
|
|
76469
76881
|
minWidth: isPopover ? popupWidthFitContent ? undefined : "var(--anchor-width, 0px)" : dialogMinWidth,
|
|
@@ -76563,7 +76975,10 @@ const PickerCalloutPopup = ({
|
|
|
76563
76975
|
mount,
|
|
76564
76976
|
anchor
|
|
76565
76977
|
});
|
|
76566
|
-
const children = contentMounted ?
|
|
76978
|
+
const children = contentMounted ? jsx(PopupValueContext.Provider, {
|
|
76979
|
+
value: openController.popupValueSignal,
|
|
76980
|
+
children: childrenProp
|
|
76981
|
+
}) : null;
|
|
76567
76982
|
// Inside a <PopupGroup> the wall is the group's (see popup_group.jsx): it
|
|
76568
76983
|
// decides what a press outside the callout does, and the callout spends and
|
|
76569
76984
|
// closes on none of its own.
|
|
@@ -76722,6 +77137,13 @@ const findFileChooser = pickerEl => {
|
|
|
76722
77137
|
return pickerEl.querySelector(".navi_picker_file_chooser");
|
|
76723
77138
|
};
|
|
76724
77139
|
const showNativePicker = (pickerInput, event) => {
|
|
77140
|
+
if (pickerInput.type === "file") {
|
|
77141
|
+
// WebKit presents nothing for a file input's showPicker() and throws
|
|
77142
|
+
// nothing, so the catch below never learns of it; a click, within the
|
|
77143
|
+
// press, opens the chooser in every engine.
|
|
77144
|
+
pickerInput.click();
|
|
77145
|
+
return;
|
|
77146
|
+
}
|
|
76725
77147
|
if (findEvent(event, isTouchDrivenEvent)) {
|
|
76726
77148
|
moveFocusTo(pickerInput, {
|
|
76727
77149
|
focusVisible: false
|
|
@@ -77353,7 +77775,8 @@ const css$x = /* css */`@layer navi {
|
|
|
77353
77775
|
* vertical one matches the line of text it sits on.
|
|
77354
77776
|
* @param {string} [props.color] - The line's own colour — `--color`.
|
|
77355
77777
|
* @param {string|number} [props.margin="0.5em"] - Room kept on both sides of
|
|
77356
|
-
* the line — `--margin`.
|
|
77778
|
+
* the line — `--margin`. A spacing word (`"xs"`, `"s"`, `"m"`…), a length or
|
|
77779
|
+
* a number of px, like any margin prop.
|
|
77357
77780
|
* @param {string|number} [props.marginStart] - Room on one side only —
|
|
77358
77781
|
* `--margin-start`, above a horizontal rule and left of a vertical one.
|
|
77359
77782
|
* @param {string|number} [props.marginEnd] - …and the other, `--margin-end`.
|
|
@@ -77384,9 +77807,9 @@ const Separator = ({
|
|
|
77384
77807
|
...cssVars({
|
|
77385
77808
|
"--size": lengthValue(size),
|
|
77386
77809
|
"--color": color,
|
|
77387
|
-
"--margin":
|
|
77388
|
-
"--margin-start":
|
|
77389
|
-
"--margin-end":
|
|
77810
|
+
"--margin": spacingValue(margin),
|
|
77811
|
+
"--margin-start": spacingValue(marginStart),
|
|
77812
|
+
"--margin-end": spacingValue(marginEnd)
|
|
77390
77813
|
}),
|
|
77391
77814
|
...style
|
|
77392
77815
|
}
|
|
@@ -77407,6 +77830,10 @@ const cssVars = vars => {
|
|
|
77407
77830
|
return declared;
|
|
77408
77831
|
};
|
|
77409
77832
|
const lengthValue = value => typeof value === "number" ? `${value}px` : value;
|
|
77833
|
+
// A margin reads the spacing scale like every other margin prop ("s" →
|
|
77834
|
+
// var(--navi-s)): written raw, a word is a valid custom property and an invalid
|
|
77835
|
+
// margin, which computes to 0 without falling back to anything.
|
|
77836
|
+
const spacingValue = value => value === undefined ? undefined : stringifySpacingStyle(value, "margin");
|
|
77410
77837
|
|
|
77411
77838
|
const ListItemHeaderOrFooterResolver = props => {
|
|
77412
77839
|
const Next = useNextResolver();
|
|
@@ -77907,7 +78334,9 @@ const createListItems = () => {
|
|
|
77907
78334
|
dropItemLocator: (ownerId) => {
|
|
77908
78335
|
locatorByOwner.delete(ownerId);
|
|
77909
78336
|
},
|
|
77910
|
-
// Where the item named by that id sits, asked of whoever holds it
|
|
78337
|
+
// Where the item named by that id sits, asked of whoever holds it: a run
|
|
78338
|
+
// knows its items, drawn or not; an item declared one by one is its own
|
|
78339
|
+
// holder, and says its place when it draws.
|
|
77911
78340
|
locateItem: (id) => {
|
|
77912
78341
|
for (const locator of locatorByOwner.values()) {
|
|
77913
78342
|
const index = locator.indexOf(id);
|
|
@@ -77915,6 +78344,16 @@ const createListItems = () => {
|
|
|
77915
78344
|
return index;
|
|
77916
78345
|
}
|
|
77917
78346
|
}
|
|
78347
|
+
for (const [entryId, entry] of entryById) {
|
|
78348
|
+
if (
|
|
78349
|
+
entry.ownerId === entryId &&
|
|
78350
|
+
entry.item &&
|
|
78351
|
+
entry.place !== undefined &&
|
|
78352
|
+
entry.data.itemId === id
|
|
78353
|
+
) {
|
|
78354
|
+
return entry.place;
|
|
78355
|
+
}
|
|
78356
|
+
}
|
|
77918
78357
|
return null;
|
|
77919
78358
|
},
|
|
77920
78359
|
// The room the item at that index takes: the room it took when it was
|
|
@@ -79305,6 +79744,11 @@ const css$v = /* css */`@property --list-group-label-height {
|
|
|
79305
79744
|
overflow: clip;
|
|
79306
79745
|
}
|
|
79307
79746
|
|
|
79747
|
+
.navi_list_container[data-horizontal]:not([data-scroller], [data-overflow-visible]) > .navi_list_scroll_container > .navi_list:not([navi-box-flow="grid"]) {
|
|
79748
|
+
width: min-content;
|
|
79749
|
+
min-width: 100%;
|
|
79750
|
+
}
|
|
79751
|
+
|
|
79308
79752
|
.navi_list_container[data-horizontal] {
|
|
79309
79753
|
--list-max-height: none;
|
|
79310
79754
|
|
|
@@ -79452,6 +79896,7 @@ const css$v = /* css */`@property --list-group-label-height {
|
|
|
79452
79896
|
|
|
79453
79897
|
& .navi_list_item_group_list {
|
|
79454
79898
|
--list-group-label-height: inherit;
|
|
79899
|
+
gap: var(--x-list-gap, 0px);
|
|
79455
79900
|
flex-direction: column;
|
|
79456
79901
|
width: 100%;
|
|
79457
79902
|
margin: 0;
|
|
@@ -86876,6 +87321,16 @@ const PickerChip = ({
|
|
|
86876
87321
|
children,
|
|
86877
87322
|
...rest
|
|
86878
87323
|
}) => {
|
|
87324
|
+
// Its picker's own state, not the zone's: on the façade the network policy's
|
|
87325
|
+
// hold is not handed down (see faceReadOnly in picker.jsx), and the cross is
|
|
87326
|
+
// what changes the picker.
|
|
87327
|
+
const pickerContext = usePickerContext();
|
|
87328
|
+
if (commandFor === undefined && pickerContext?.readOnly) {
|
|
87329
|
+
return jsx(Badge, {
|
|
87330
|
+
...rest,
|
|
87331
|
+
children: children
|
|
87332
|
+
});
|
|
87333
|
+
}
|
|
86879
87334
|
return jsxs(Badge, {
|
|
86880
87335
|
...rest,
|
|
86881
87336
|
children: [children, jsx(Badge.Button, {
|
|
@@ -87480,7 +87935,7 @@ const css$r = /* css */`@property --navi-picker-container-font-size {
|
|
|
87480
87935
|
flex-grow: 1;
|
|
87481
87936
|
display: inline-block;
|
|
87482
87937
|
|
|
87483
|
-
&[data-picker-facade] {
|
|
87938
|
+
&[data-picker-facade="drawing"] {
|
|
87484
87939
|
line-height: var(--navi-line-height);
|
|
87485
87940
|
}
|
|
87486
87941
|
|
|
@@ -87647,6 +88102,10 @@ const css$r = /* css */`@property --navi-picker-container-font-size {
|
|
|
87647
88102
|
--x-picker-cursor: pointer;
|
|
87648
88103
|
}
|
|
87649
88104
|
|
|
88105
|
+
&[data-readonly]:has( > .navi_picker_box > .navi_picker_input[data-readonly-reason="network-policy"]) > .navi_picker_box > .navi_picker_value[data-picker-facade="drawing"] {
|
|
88106
|
+
color: var(--picker-color);
|
|
88107
|
+
}
|
|
88108
|
+
|
|
87650
88109
|
&[data-focus-within]:has( > .navi_picker_box > .navi_picker_input[data-focus-visible]), &[data-focus-visible] {
|
|
87651
88110
|
--x-picker-border-color: transparent;
|
|
87652
88111
|
|
|
@@ -87867,6 +88326,12 @@ const PickerButton = props => {
|
|
|
87867
88326
|
// with it: what the popup changes is what the picker would send.
|
|
87868
88327
|
const readOnlyFromAbove = useContext(ReadOnlyContext);
|
|
87869
88328
|
const [readOnlyResolved, readOnlyMessageResolved] = readOnlyHandedDown(uiStateController, readOnly || readOnlyFromAbove);
|
|
88329
|
+
// What a caller draws on the face (its `ui`, its right slot) is read-only
|
|
88330
|
+
// with the picker, and not held with it: the network policy holds what the
|
|
88331
|
+
// picker would send, which its popup changes. A card used as the trigger
|
|
88332
|
+
// keeps its links and buttons, each held for what it sends itself.
|
|
88333
|
+
const faceReadOnly = readOnly || readOnlyFromAbove;
|
|
88334
|
+
const faceReadOnlyMessage = faceReadOnly ? props.readOnlyMessage ?? uiStateController.readOnlyMessageFromAbove : undefined;
|
|
87870
88335
|
// Read off the controller rather than worked out again: what makes a
|
|
87871
88336
|
// read-only picker open is settled once, where the gate reads it (see
|
|
87872
88337
|
// createControlInfo's readOnlyOpens). Needed here for the cursor.
|
|
@@ -87888,6 +88353,9 @@ const PickerButton = props => {
|
|
|
87888
88353
|
maxLines,
|
|
87889
88354
|
id: inputProps.id,
|
|
87890
88355
|
interactive,
|
|
88356
|
+
// Read-only, or held by the network policy — never busy: an action in
|
|
88357
|
+
// flight is not a value nobody may change (see the ReadOnlyProvider below).
|
|
88358
|
+
readOnly: Boolean(readOnlyResolved),
|
|
87891
88359
|
loading,
|
|
87892
88360
|
clearConfirm,
|
|
87893
88361
|
requestValue
|
|
@@ -88098,7 +88566,7 @@ const PickerButton = props => {
|
|
|
88098
88566
|
// the picker draws itself, so each is written on its own line
|
|
88099
88567
|
// (see .navi_picker_value in the CSS above).
|
|
88100
88568
|
,
|
|
88101
|
-
"data-picker-facade": ui === undefined ? undefined : ""
|
|
88569
|
+
"data-picker-facade": ui === undefined ? undefined : typeof ui === "string" || typeof ui === "number" ? "text" : "drawing"
|
|
88102
88570
|
// A placeholder is the picker saying "nothing here yet" about
|
|
88103
88571
|
// the value navi draws — the default rendering, or the one a
|
|
88104
88572
|
// typed picker installs for itself. A button's label is not
|
|
@@ -88110,6 +88578,8 @@ const PickerButton = props => {
|
|
|
88110
88578
|
"navi-placeholder": (ui === undefined || pickerUIIsNaviOwn(ui)) && !drawnAsButton && variant !== "text" && uiStateHoldsNothing(value) ? "" : undefined,
|
|
88111
88579
|
maxLines: maxLines,
|
|
88112
88580
|
children: jsx(PickerOwnContent, {
|
|
88581
|
+
readOnly: faceReadOnly,
|
|
88582
|
+
readOnlyMessage: faceReadOnlyMessage,
|
|
88113
88583
|
children: jsx(MaxLinesContext.Provider, {
|
|
88114
88584
|
value: maxLines,
|
|
88115
88585
|
children: ui === undefined ? isIcon ?
|
|
@@ -88137,6 +88607,8 @@ const PickerButton = props => {
|
|
|
88137
88607
|
}), hasRightSlot ? jsx("span", {
|
|
88138
88608
|
className: "navi_picker_right_slot",
|
|
88139
88609
|
children: jsx(PickerOwnContent, {
|
|
88610
|
+
readOnly: faceReadOnly,
|
|
88611
|
+
readOnlyMessage: faceReadOnlyMessage,
|
|
88140
88612
|
children: clearable && pickerHasSomethingToClear(pickerContext) ? jsx(PickerClear, {
|
|
88141
88613
|
size: rightSlotIconSize
|
|
88142
88614
|
}) : rightSlot === undefined ?
|
|
@@ -88288,12 +88760,18 @@ const pickerHasSomethingToClear = ({
|
|
|
88288
88760
|
// is empty, a chip the moment its value is taken out — takes the picker's own
|
|
88289
88761
|
// entry with it, leaving the picker looking for a controller that is gone.
|
|
88290
88762
|
const PickerOwnContent = ({
|
|
88763
|
+
readOnly,
|
|
88764
|
+
readOnlyMessage,
|
|
88291
88765
|
children
|
|
88292
88766
|
}) => jsx(ControlIdContext.Provider, {
|
|
88293
88767
|
value: undefined,
|
|
88294
88768
|
children: jsx(ControlNameContext.Provider, {
|
|
88295
88769
|
value: undefined,
|
|
88296
|
-
children:
|
|
88770
|
+
children: jsx(ReadOnlyProvider, {
|
|
88771
|
+
readOnly: readOnly,
|
|
88772
|
+
readOnlyMessage: readOnlyMessage,
|
|
88773
|
+
children: children
|
|
88774
|
+
})
|
|
88297
88775
|
})
|
|
88298
88776
|
});
|
|
88299
88777
|
|
|
@@ -88558,7 +89036,7 @@ const PickerUI = /*#__PURE__*/Object.assign(PickerDefaultUI, {
|
|
|
88558
89036
|
* openOn?: "press" | "longpress" | "contextmenu" | string | string[],
|
|
88559
89037
|
* animation?: boolean | "auto" | "fading" | "scaling" | "sliding" | "lifting" | `slide-from-${string}` | { open: boolean | "auto" | "fading" | "scaling" | "sliding" | `slide-from-${string}`, close: "lifting" },
|
|
88560
89038
|
* lift?: "box" | "scene",
|
|
88561
|
-
* liftAnchor?: Element | { current: Element } | string,
|
|
89039
|
+
* liftAnchor?: Element | { current: Element } | string | ((popupValue: any) => Element | { current: Element } | string),
|
|
88562
89040
|
* animationDuration?: string,
|
|
88563
89041
|
* calloutStatus?: "info" | "warning" | "error" | "success" | "none",
|
|
88564
89042
|
* calloutIcon?: boolean,
|
|
@@ -88633,7 +89111,9 @@ const PickerUI = /*#__PURE__*/Object.assign(PickerDefaultUI, {
|
|
|
88633
89111
|
* follows the theme) — the trigger's own `backgroundColor` is not it, so a
|
|
88634
89112
|
* variant that paints the trigger transparent leaves the popup a real sheet.
|
|
88635
89113
|
* @param {number|string} [popupBorderRadius] The popup's corners. Left out they
|
|
88636
|
-
* echo the trigger's `borderRadius
|
|
89114
|
+
* echo the trigger's `borderRadius` when it is a length of corners; a shape
|
|
89115
|
+
* (a percentage, a pill's 999px) leaves the popup on the corners every popup
|
|
89116
|
+
* has.
|
|
88637
89117
|
* @param {string} [popupBoxShadow] The popup's shadow, popover or dialog. Left
|
|
88638
89118
|
* out it is the one every navi popup casts. `"none"` for a popup that is
|
|
88639
89119
|
* not a sheet — a card lifted out of a page draws its own edges, and the
|
|
@@ -89005,11 +89485,12 @@ const PickerUI = /*#__PURE__*/Object.assign(PickerDefaultUI, {
|
|
|
89005
89485
|
* that opens precisely to get bigger. It brings an opaque, blurred backdrop
|
|
89006
89486
|
* with it (`--navi-backdrop-lift-*`); `backdropVariant="discrete"` asks for
|
|
89007
89487
|
* the light wash back.
|
|
89008
|
-
* @param {Element|{current: Element}|string} [liftAnchor] Dialog mode,
|
|
89488
|
+
* @param {Element|{current: Element}|string|((popupValue: any) => Element|{current: Element}|string)} [liftAnchor] Dialog mode,
|
|
89009
89489
|
* Dialog's own: where a lifting close lands when that is not the trigger
|
|
89010
89490
|
* (`animation="lifting"`, or `animation={{ open, close: "lifting" }}` for a
|
|
89011
89491
|
* popup that opens the plain way and only lands on close),
|
|
89012
|
-
* read once the close is made (after `onClose`).
|
|
89492
|
+
* read once the close is made (after `onClose`). A function is called with
|
|
89493
|
+
* what the popup was open on (see `usePopupValue`).
|
|
89013
89494
|
* @param {"box"|"scene"} [lift="box"] Dialog's own, under `animation="lifting"`:
|
|
89014
89495
|
* `"box"` for a card that extends (its top stays, the box uncovers the rest),
|
|
89015
89496
|
* `"scene"` for a thumbnail that is a band cut from the middle of the bigger
|
|
@@ -99038,9 +99519,11 @@ const KeyboardShortcutAriaElement = ({
|
|
|
99038
99519
|
* <Button action={copy}>{copied ? i18n("Copied") : i18n("Copy link")}</Button>
|
|
99039
99520
|
* ```
|
|
99040
99521
|
*
|
|
99041
|
-
* `copy` rejects when the browser refuses the write
|
|
99042
|
-
*
|
|
99043
|
-
*
|
|
99522
|
+
* `copy` rejects when the browser refuses the write (permission blocked, page
|
|
99523
|
+
* not in front, no clipboard outside a secure context), with navi's
|
|
99524
|
+
* `"button.copy_refused"` sentence — the browser's own error as its `cause` —
|
|
99525
|
+
* so an `action` running it says why on the control in the page's language. A
|
|
99526
|
+
* press while `copied` holds starts the moment again.
|
|
99044
99527
|
*
|
|
99045
99528
|
* @param {string | (() => string | Promise<string>)} text What is copied. A
|
|
99046
99529
|
* function is called at the press: for a text only built then (a report, a
|
|
@@ -99080,6 +99563,14 @@ const useCopyToClipboard = (text, { duration = 1500 } = {}) => {
|
|
|
99080
99563
|
|
|
99081
99564
|
const writeToClipboard = async (text) => {
|
|
99082
99565
|
const value = typeof text === "function" ? text() : text;
|
|
99566
|
+
try {
|
|
99567
|
+
await writeValueToClipboard(value);
|
|
99568
|
+
} catch (error) {
|
|
99569
|
+
// The browser's words are in its own language, and name its API.
|
|
99570
|
+
throw new Error(buttonI18n("button.copy_refused"), { cause: error });
|
|
99571
|
+
}
|
|
99572
|
+
};
|
|
99573
|
+
const writeValueToClipboard = async (value) => {
|
|
99083
99574
|
if (typeof value === "string") {
|
|
99084
99575
|
await window.navigator.clipboard.writeText(value);
|
|
99085
99576
|
return;
|
|
@@ -102084,5 +102575,5 @@ const UserSvg = () => jsx("svg", {
|
|
|
102084
102575
|
})
|
|
102085
102576
|
});
|
|
102086
102577
|
|
|
102087
|
-
export { ActionRenderer, ActiveKeyboardShortcuts, Address, Badge, BadgeCount, BadgeList, Binder, Box, Button, ButtonCopyToClipboard, CalloutStatusIcon, Caption, CardLayout, CheckSvg, CheckboxGroup, CloseSvg, Code, Col, Colgroup, Color, ConstructionSvg, ControlGroup, ControlSwap, DaySpin, Details, Dialog, Editable, ErrorBoundary, ErrorBoundaryContext, ExclamationSvg, Expandable, EyeClosedSvg, EyeSvg, Field, FixedBar, Form, Group, Head, HeartSvg, HomeSvg, Icon, Image, InfoSvg, Input, InputDuration, Interpolate, Label, Link, LinkAnchorSvg, LinkBlankTargetSvg, LinkCurrentSvg, List, ListItem, ListItemGroup, ListItems, Loading, LoadingDotsSvg, LoadingIndicator, LoadingIndicatorFluid, LoadingOutline, MessageBox, Meter, Nav, NaviDebug, NetworkPolicyError, NumberSpin, Paragraph, Picker, Popover, Popup, PopupGroup, Quantity, RadioGroup, Route, RouteTransitionArea, RouteTravel, RowNumberCol, RowNumberTableCell, SVGMaskOverlay, SearchSvg, Select, SelectableInput, SelectionContext, Separator, SettingsSvg, SidePanel, Slide, SlideContainer, Spin, SpinGroup, SplitButton, StarSvg, Step, StepList, SummaryMarker, Svg, Table, TableCell, Tbody, Text, TextBox, Textarea, TextareaCharCount, Thead, Time, TimeRange, TimeRangeSpin, TimeRangeWheel, TimeSpin, TimeWheel, Title, Tr, UITransition, Unit, UserSvg, ViewportLayout, Wheel, WheelGroup, WheelItem, actionRunEffect, activeRouteActionsSignal, activeRouteReadsSignal, anyMatchingRouteSignal, applySearch, arraySignalMembership, canNavBackSignal, canNavForwardSignal, coarsePointerSignal, compareTwoJsValues, constraintFromValidityRule, createAction, createAvailableConstraint, createRequestCanceller, createSearch, createSelectionKeyboardShortcuts, createSlot, defineInteractionDetector, defineRouteDefaultTransition, defineRouteTransition, detectHorizontalOverflow, dispatchRequestSetUIState, enableDebugActions, enableDebugOnDocumentLoading, enableVirtualKeyboardOverlay, ensureDocumentStartViewTransition, errorIsDisplayed, filterTableSelection, getNowHours, getNowHoursRoundedToStep, isCellSelected, isColumnSelected, isNetworkPolicyError, isPressOnControl, isRowSelected, isScrolling, isToday, keepPageOnScreen, languagesSignal, localStorageSignal, markAsOutsideTextFlow, markErrorAsDisplayedBy, moveArrayItemByIndex, moveFocusTo, navBack, navForward, navIntegratedVia, navTo, naviI18n, openCallout, preloadUrl, rawUrlPart, registerGlobalConstraint, reload, rerunActions, resource, route, routeAction, routeFallback, scrollActivitySignal, setBaseUrl, setNetworkPolicy, setPreferredLanguage, setSupportedLanguages, setUrlTargetOptions, setupRoutes, smallTouchScreenSignal, stateSignal, stopLoad, stringifyTableSelectionValue, swapArrayItemByIndex, syncOwnedResourceToSignals, syncResourceToSignals, todaySignal, triggerNaviCommand, updateActions, useActionStatus, useArraySignalMembership, useAsyncData, useCalloutElement, useCalloutRequestClose, useCanNavBack, useCanNavForward, useCancelPrevious, useCellGridFromRows, useConstraintValidityState, useCopyToClipboard, useDependenciesDiff, useDisplayedLayoutEffect, useDocumentResource, useDocumentState, useDocumentUrl, useEditionController, useFocusGroup, useHoldScrollRestoration, useInputGroup, useKeyboardShortcuts, useListItemState, useNavState, useNetworkPolicyReason, useOrderedColumns, usePickerState, usePopupMode, useRouteStatus, useSearchText, useSelectableElement, useSelectionController, useSignalSync, useSlideContainer, useSlideValue, useStateArray, useTitleLevel, useTransitionCover, useUrlSearchParam, useUrlTargetId, valueInLocalStorage, windowWidthSignal };
|
|
102578
|
+
export { ActionRenderer, ActiveKeyboardShortcuts, Address, Badge, BadgeCount, BadgeList, Binder, Box, Button, ButtonCopyToClipboard, CalloutStatusIcon, Caption, CardLayout, CheckSvg, CheckboxGroup, CloseSvg, Code, Col, Colgroup, Color, ConstructionSvg, ControlGroup, ControlSwap, DaySpin, Details, Dialog, Editable, ErrorBoundary, ErrorBoundaryContext, ExclamationSvg, Expandable, EyeClosedSvg, EyeSvg, Field, FixedBar, Form, Group, Head, HeartSvg, HomeSvg, Icon, Image, InfoSvg, Input, InputDuration, Interpolate, Label, Link, LinkAnchorSvg, LinkBlankTargetSvg, LinkCurrentSvg, List, ListItem, ListItemGroup, ListItems, Loading, LoadingDotsSvg, LoadingIndicator, LoadingIndicatorFluid, LoadingOutline, MessageBox, Meter, Nav, NaviDebug, NetworkPolicyError, NumberSpin, Paragraph, Picker, Popover, Popup, PopupGroup, Quantity, RadioGroup, Route, RouteTransitionArea, RouteTravel, RowNumberCol, RowNumberTableCell, SVGMaskOverlay, SearchSvg, Select, SelectableInput, SelectionContext, Separator, SettingsSvg, SidePanel, Slide, SlideContainer, Spin, SpinGroup, SplitButton, StarSvg, Step, StepList, SummaryMarker, Svg, Table, TableCell, Tbody, Text, TextBox, Textarea, TextareaCharCount, Thead, Time, TimeRange, TimeRangeSpin, TimeRangeWheel, TimeSpin, TimeWheel, Title, Tr, UITransition, Unit, UserSvg, ViewportLayout, Wheel, WheelGroup, WheelItem, actionRunEffect, activeRouteActionsSignal, activeRouteReadsSignal, anyMatchingRouteSignal, applySearch, arraySignalMembership, canNavBackSignal, canNavForwardSignal, coarsePointerSignal, compareTwoJsValues, constraintFromValidityRule, createAction, createAvailableConstraint, createRequestCanceller, createSearch, createSelectionKeyboardShortcuts, createSlot, defineInteractionDetector, defineRouteDefaultTransition, defineRouteTransition, detectHorizontalOverflow, dispatchRequestSetUIState, enableDebugActions, enableDebugOnDocumentLoading, enableVirtualKeyboardOverlay, ensureDocumentStartViewTransition, errorIsDisplayed, filterTableSelection, getNowHours, getNowHoursRoundedToStep, isCellSelected, isColumnSelected, isNetworkPolicyError, isPressOnControl, isRowSelected, isScrolling, isToday, keepPageOnScreen, languagesSignal, localStorageSignal, markAsOutsideTextFlow, markErrorAsDisplayedBy, moveArrayItemByIndex, moveFocusTo, navBack, navForward, navIntegratedVia, navTo, naviI18n, openCallout, preloadUrl, rawUrlPart, registerGlobalConstraint, reload, rerunActions, resource, route, routeAction, routeFallback, scrollActivitySignal, setBaseUrl, setNetworkPolicy, setPreferredLanguage, setSupportedLanguages, setUrlTargetOptions, setupRoutes, smallTouchScreenSignal, stateSignal, stopLoad, stringifyTableSelectionValue, swapArrayItemByIndex, syncOwnedResourceToSignals, syncResourceToSignals, todaySignal, triggerNaviCommand, updateActions, useActionStatus, useArraySignalMembership, useAsyncData, useCalloutElement, useCalloutRequestClose, useCanNavBack, useCanNavForward, useCancelPrevious, useCellGridFromRows, useConstraintValidityState, useCopyToClipboard, useDependenciesDiff, useDisplayedLayoutEffect, useDocumentResource, useDocumentState, useDocumentUrl, useEditionController, useFocusGroup, useHoldScrollRestoration, useInputGroup, useKeyboardShortcuts, useListItemState, useNavState, useNetworkPolicyReason, useOrderedColumns, usePickerState, usePopupMode, usePopupValue, useRouteStatus, useSearchText, useSelectableElement, useSelectionController, useSignalSync, useSlideContainer, useSlideValue, useStateArray, useTitleLevel, useTransitionCover, useUrlSearchParam, useUrlTargetId, valueInLocalStorage, windowWidthSignal };
|
|
102088
102579
|
//# sourceMappingURL=jsenv_navi.js.map
|