@jsenv/navi 0.29.454 → 0.29.456
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 +90 -96
- package/dist/dev/jsenv_navi.js.map +9 -9
- package/dist/dev/jsenv_navi_side_effects.js +1 -0
- package/dist/dev/jsenv_navi_side_effects.js.map +2 -2
- package/dist/jsenv_navi.js +87 -95
- package/dist/jsenv_navi.js.map +9 -9
- package/dist/jsenv_navi_side_effects.js +1 -0
- package/dist/jsenv_navi_side_effects.js.map +2 -2
- package/docs/control_value.md +18 -0
- package/docs/popup_backdrop.md +16 -0
- package/package.json +1 -1
package/dist/dev/jsenv_navi.js
CHANGED
|
@@ -33755,9 +33755,33 @@ const pushHeadThemeColors = (themeColors) => {
|
|
|
33755
33755
|
};
|
|
33756
33756
|
};
|
|
33757
33757
|
|
|
33758
|
+
/**
|
|
33759
|
+
* What a popup asks of the colour while it is open: its `themeColor` prop,
|
|
33760
|
+
* else the `--navi-popup-theme-color` it inherits — where the choice goes
|
|
33761
|
+
* when it is the app's, or a part of the app's, rather than one popup's.
|
|
33762
|
+
*
|
|
33763
|
+
* @param {Element} element - The popup element.
|
|
33764
|
+
* @param {string|false} [themeColor] - The popup's prop.
|
|
33765
|
+
* @returns {string} `"auto"` paints what the popup lays over the top edge,
|
|
33766
|
+
* `"none"` leaves the colour as it is, anything else is a colour forcing it.
|
|
33767
|
+
*/
|
|
33768
|
+
const readPopupThemeColor = (element, themeColor) => {
|
|
33769
|
+
if (themeColor === false) {
|
|
33770
|
+
return "none";
|
|
33771
|
+
}
|
|
33772
|
+
if (themeColor) {
|
|
33773
|
+
return themeColor;
|
|
33774
|
+
}
|
|
33775
|
+
const token = getComputedStyle(element)
|
|
33776
|
+
.getPropertyValue("--navi-popup-theme-color")
|
|
33777
|
+
.trim();
|
|
33778
|
+
return token || "auto";
|
|
33779
|
+
};
|
|
33780
|
+
|
|
33758
33781
|
/**
|
|
33759
33782
|
* @param {object} paint
|
|
33760
|
-
* @param {string}
|
|
33783
|
+
* @param {string} paint.themeColor - `"auto"` paints the two colours below,
|
|
33784
|
+
* a colour forces it and nothing is painted.
|
|
33761
33785
|
* @param {string|null} [paint.backdropColor] - Laid over the page's colour.
|
|
33762
33786
|
* @param {string|null} [paint.surfaceColor] - Laid over that, for a popup
|
|
33763
33787
|
* flush with the top edge.
|
|
@@ -33769,7 +33793,7 @@ const pushPopupThemeColor = ({
|
|
|
33769
33793
|
surfaceColor,
|
|
33770
33794
|
}) => {
|
|
33771
33795
|
let layer;
|
|
33772
|
-
if (themeColor) {
|
|
33796
|
+
if (themeColor !== "auto") {
|
|
33773
33797
|
layer = { color: themeColor };
|
|
33774
33798
|
} else {
|
|
33775
33799
|
const paints = [];
|
|
@@ -40613,18 +40637,20 @@ const callLiftOverCallbacks = () => {
|
|
|
40613
40637
|
*
|
|
40614
40638
|
* A picker's `action` waits for its popup to close: what is done in there is
|
|
40615
40639
|
* one answer, given when the person is done. A change made while the popup is
|
|
40616
|
-
* closed — a chip's cross, a paste, a cut, a value proposed
|
|
40617
|
-
* (`--navi-update`) — has no close coming, so nothing would ever
|
|
40618
|
-
* value moves on screen and the record behind it stays. Each of
|
|
40619
|
-
* calls this right after setting the value; a failing action
|
|
40620
|
-
* back (resetOnError), as it does after a close.
|
|
40640
|
+
* closed — the clear cross, a chip's cross, a paste, a cut, a value proposed
|
|
40641
|
+
* from beside it (`--navi-update`) — has no close coming, so nothing would ever
|
|
40642
|
+
* send it: the value moves on screen and the record behind it stays. Each of
|
|
40643
|
+
* those gestures calls this right after setting the value; a failing action
|
|
40644
|
+
* puts the value back (resetOnError), as it does after a close.
|
|
40621
40645
|
*
|
|
40622
40646
|
* Called by gestures only. A value set without one — a bound signal followed, a
|
|
40623
40647
|
* cancel or a failure rolled back — is the picker being told, not asked, which
|
|
40624
40648
|
* is why this is not a reaction to every value set on a closed picker.
|
|
40625
40649
|
*
|
|
40626
|
-
* The
|
|
40627
|
-
*
|
|
40650
|
+
* The action is requested the way the close requests it, not through
|
|
40651
|
+
* `--navi-send`: a send also answers the surface around the control (a slide
|
|
40652
|
+
* moves on, an open dialog closes — see resolveAfterSend in commands.js), and a
|
|
40653
|
+
* cross pressed on a picker in a dialog is not the dialog being answered.
|
|
40628
40654
|
*/
|
|
40629
40655
|
|
|
40630
40656
|
|
|
@@ -40647,6 +40673,13 @@ const sendClosedPickerChange = (element, { event, name, requester }) => {
|
|
|
40647
40673
|
if (props.picksNothing) {
|
|
40648
40674
|
return;
|
|
40649
40675
|
}
|
|
40676
|
+
// A source with an action of its own made the request already: `<Button
|
|
40677
|
+
// action={remove} command="--navi-clear">` runs the removal, and the command
|
|
40678
|
+
// that follows only brings the picker in line with it. Sending the picker's
|
|
40679
|
+
// action on top would ask twice.
|
|
40680
|
+
if (requester?.__uiStateController__?.props.action) {
|
|
40681
|
+
return;
|
|
40682
|
+
}
|
|
40650
40683
|
// `requester`: the source of a command may have claimed the press to send
|
|
40651
40684
|
// this very change (see isAimedAtSelfInteractionsBelow).
|
|
40652
40685
|
dispatchRequestAction(controlHost, { event, name, requester });
|
|
@@ -41060,20 +41093,6 @@ registerNaviCommand("--navi-clear", (source, event) => {
|
|
|
41060
41093
|
return undefined;
|
|
41061
41094
|
}
|
|
41062
41095
|
const fromInput = source.closest(`[navi-control="input"]`);
|
|
41063
|
-
// A control that commits on an explicit send — a picker, whose list sends the
|
|
41064
|
-
// moment a value is chosen — has nothing that would commit a clear: its
|
|
41065
|
-
// action never runs on a ui state change. Left alone, the field goes empty
|
|
41066
|
-
// while the caller still holds the value it gave, and renders it right back.
|
|
41067
|
-
//
|
|
41068
|
-
// Unless the source committed the clear itself: a clear button given its own
|
|
41069
|
-
// action (`<Button action={remove} command="--navi-clear">`) already made the
|
|
41070
|
-
// request — the ui state is being brought in line with what just happened, and
|
|
41071
|
-
// sending the picker's own action on top would ask twice.
|
|
41072
|
-
const sourceController = source.__uiStateController__;
|
|
41073
|
-
const fromSendOnlyControl = Boolean(
|
|
41074
|
-
source.closest?.(`[navi-control=picker]`) &&
|
|
41075
|
-
!sourceController?.props.action,
|
|
41076
|
-
);
|
|
41077
41096
|
|
|
41078
41097
|
const performClear = (clearEvent) => {
|
|
41079
41098
|
dispatchRequestInteraction(target, {
|
|
@@ -41084,46 +41103,11 @@ registerNaviCommand("--navi-clear", (source, event) => {
|
|
|
41084
41103
|
requester: source,
|
|
41085
41104
|
prevented: () => clearEvent.preventDefault(),
|
|
41086
41105
|
allowed: () => {
|
|
41087
|
-
// What the control holds, before it holds nothing: the clear is
|
|
41088
|
-
// optimistic — the field empties now and the send that commits it may
|
|
41089
|
-
// still fail — so what it emptied has to be kept to be put back.
|
|
41090
|
-
const uiStateBefore = getUIStateFromElement(target);
|
|
41091
41106
|
dispatchRequestClearUIState(target, clearEvent);
|
|
41092
|
-
|
|
41093
|
-
|
|
41094
|
-
|
|
41095
|
-
|
|
41096
|
-
// state signal, so this sends the value the control now holds.
|
|
41097
|
-
const actionHost = findControlHost(target) || target;
|
|
41098
|
-
const completion = watchActionCompletion(actionHost, () => {
|
|
41099
|
-
triggerNaviCommand(source, "--navi-send", clearEvent, {
|
|
41100
|
-
optional: true,
|
|
41101
|
-
});
|
|
41102
|
-
});
|
|
41103
|
-
completion.whenSettled(({ error, aborted }) => {
|
|
41104
|
-
if (!error && !aborted) {
|
|
41105
|
-
return;
|
|
41106
|
-
}
|
|
41107
|
-
// The removal did not happen, so the field must stop saying it did.
|
|
41108
|
-
// The error itself stays where the action put it — on the control,
|
|
41109
|
-
// which is still there, unlike the cross that has just gone with the
|
|
41110
|
-
// value it cleared (see addErrorMessage in use_execute_action.js).
|
|
41111
|
-
//
|
|
41112
|
-
// Put back from the inside ("clear_rollback" is an internal event
|
|
41113
|
-
// type, see ui_state_controller.js) rather than asked for the way a
|
|
41114
|
-
// user would: nobody acted, the control is being returned to the
|
|
41115
|
-
// state its caller still holds. Asked from the outside it would be
|
|
41116
|
-
// answered with "this element is busy" — the action is still
|
|
41117
|
-
// settling — over the very error that explains why the value is back.
|
|
41118
|
-
const controller = actionHost.__uiStateController__;
|
|
41119
|
-
if (!controller) {
|
|
41120
|
-
return;
|
|
41121
|
-
}
|
|
41122
|
-
const rollbackEvent = new CustomEvent("clear_rollback", {
|
|
41123
|
-
detail: {},
|
|
41124
|
-
});
|
|
41125
|
-
chainEvent(rollbackEvent, clearEvent);
|
|
41126
|
-
controller.setUIState(uiStateBefore, rollbackEvent);
|
|
41107
|
+
sendClosedPickerChange(target, {
|
|
41108
|
+
event: clearEvent,
|
|
41109
|
+
name: "--navi-clear",
|
|
41110
|
+
requester: source,
|
|
41127
41111
|
});
|
|
41128
41112
|
},
|
|
41129
41113
|
});
|
|
@@ -41863,6 +41847,7 @@ registerNaviCommand("--navi-select", (source, event) => {
|
|
|
41863
41847
|
return dispatchCustomEvent(target, "navi_request_select", {
|
|
41864
41848
|
event,
|
|
41865
41849
|
id: resolveCommandValue(source, event),
|
|
41850
|
+
requester: source,
|
|
41866
41851
|
});
|
|
41867
41852
|
},
|
|
41868
41853
|
};
|
|
@@ -41879,6 +41864,7 @@ registerNaviCommand("--navi-unselect", (source, event) => {
|
|
|
41879
41864
|
return dispatchCustomEvent(target, "navi_request_unselect", {
|
|
41880
41865
|
event,
|
|
41881
41866
|
id: resolveCommandValue(source, event),
|
|
41867
|
+
requester: source,
|
|
41882
41868
|
});
|
|
41883
41869
|
},
|
|
41884
41870
|
};
|
|
@@ -45782,12 +45768,6 @@ const INTERNAL_EVENT_SET = new Set([
|
|
|
45782
45768
|
// on registration, and group pushing value/defaultValue to children on registerChild.
|
|
45783
45769
|
// Equivalent to defaultValue initialization: no uiAction, no commands, no parent notification.
|
|
45784
45770
|
"initial_state_push",
|
|
45785
|
-
// navi undoing its own optimistic write: the clear cross emptied the control
|
|
45786
|
-
// before the send that commits it, the send failed, and the value it emptied
|
|
45787
|
-
// goes back where it was (see the --navi-clear command). Nothing acted — the
|
|
45788
|
-
// control is being put back on the state the caller still holds — so this
|
|
45789
|
-
// must not fire a uiAction, a command, or a report on the way.
|
|
45790
|
-
"clear_rollback",
|
|
45791
45771
|
// A picker's popup closed on a cancel (the no button, Escape, a click
|
|
45792
45772
|
// outside): what the picker held at open goes back. Nobody acted — no
|
|
45793
45773
|
// command — but the value really did move back, so uiAction and the parent
|
|
@@ -67952,16 +67932,17 @@ const css$E = /* css */`
|
|
|
67952
67932
|
* `saturate()`/`grayscale()` work too. How far what is behind withdraws is
|
|
67953
67933
|
* a question of paint, not of what an outside click does — a backdrop that
|
|
67954
67934
|
* closes can blur.
|
|
67955
|
-
* @param {string|false} [props.themeColor] - The colour the browser
|
|
67956
|
-
* above the page (`<meta name="theme-color">`: Chrome's address bar
|
|
67957
|
-
* Android, an installed app's status bar) while this dialog is open.
|
|
67958
|
-
*
|
|
67935
|
+
* @param {"auto"|string|false} [props.themeColor] - The colour the browser
|
|
67936
|
+
* paints above the page (`<meta name="theme-color">`: Chrome's address bar
|
|
67937
|
+
* on Android, an installed app's status bar) while this dialog is open.
|
|
67938
|
+
* `"auto"` is what the dialog lays over the top edge of the screen: its
|
|
67959
67939
|
* backdrop over the colour the page asked for (`<Head>`), and its own
|
|
67960
67940
|
* background over that when it is flush with the top edge
|
|
67961
67941
|
* (`marginWithContainer={0}` with `expand`/`expandY` or a top
|
|
67962
67942
|
* `positionArea`). A colour forces it, for a surface whose colour cannot be
|
|
67963
67943
|
* read (an image, a gradient); `false` leaves the page's colour alone.
|
|
67964
|
-
* `
|
|
67944
|
+
* Left out, the `--navi-popup-theme-color` token decides, `"auto"` unless
|
|
67945
|
+
* the app says otherwise. `layer="top"` only.
|
|
67965
67946
|
* @param {boolean} [props.scrollCapture] - Traps scroll gestures inside the
|
|
67966
67947
|
* dialog so the page/container behind it can't scroll while it's open.
|
|
67967
67948
|
* A `layer="local"` dialog always locks its own positioned ancestor's
|
|
@@ -69131,12 +69112,15 @@ const useDialogProps = props => {
|
|
|
69131
69112
|
// What the browser paints above the page goes with what is laid over its
|
|
69132
69113
|
// top edge, from the start of the opening to the start of the closing: a
|
|
69133
69114
|
// local dialog lays nothing there.
|
|
69134
|
-
if (isTopLayer
|
|
69135
|
-
|
|
69136
|
-
|
|
69137
|
-
|
|
69138
|
-
|
|
69139
|
-
|
|
69115
|
+
if (isTopLayer) {
|
|
69116
|
+
const popupThemeColor = readPopupThemeColor(dialogEl, themeColor);
|
|
69117
|
+
if (popupThemeColor !== "none") {
|
|
69118
|
+
addCleanup(pushPopupThemeColor({
|
|
69119
|
+
themeColor: popupThemeColor,
|
|
69120
|
+
backdropColor: backdrop ? readBackdropColor(dialogEl) : null,
|
|
69121
|
+
surfaceColor: flushEdges.top ? getComputedStyle(dialogEl).backgroundColor : null
|
|
69122
|
+
}));
|
|
69123
|
+
}
|
|
69140
69124
|
}
|
|
69141
69125
|
const cancelOpenInteractionSuppression = !silent && hasCssTransitionAnimation ? suppressPointerEventsDuringTransition(dialogEl) : null;
|
|
69142
69126
|
// Handing the focus to a field is what raises the on-screen keyboard, and
|
|
@@ -70002,12 +69986,14 @@ const css$D = /* css */`
|
|
|
70002
69986
|
* `saturate()`/`grayscale()` work too. How far what is behind withdraws is
|
|
70003
69987
|
* a question of paint, not of what an outside click does — a backdrop that
|
|
70004
69988
|
* closes can blur.
|
|
70005
|
-
* @param {string|false} [props.themeColor] - The colour the browser
|
|
70006
|
-
* above the page (`<meta name="theme-color">`: Chrome's address bar
|
|
70007
|
-
* Android, an installed app's status bar) while this popover is open.
|
|
70008
|
-
*
|
|
69989
|
+
* @param {"auto"|string|false} [props.themeColor] - The colour the browser
|
|
69990
|
+
* paints above the page (`<meta name="theme-color">`: Chrome's address bar
|
|
69991
|
+
* on Android, an installed app's status bar) while this popover is open.
|
|
69992
|
+
* `"auto"` is the backdrop laid over the colour the page asked for
|
|
70009
69993
|
* (`<Head>`), and the page's colour when there is no backdrop. A colour
|
|
70010
|
-
* forces it; `false` leaves the page's colour alone.
|
|
69994
|
+
* forces it; `false` leaves the page's colour alone. Left out, the
|
|
69995
|
+
* `--navi-popup-theme-color` token decides, `"auto"` unless the app says
|
|
69996
|
+
* otherwise. `layer="top"` only.
|
|
70011
69997
|
* @param {boolean} [props.scrollCapture] - Traps scroll gestures inside the
|
|
70012
69998
|
* popover so the page/container behind it can't scroll while it's open.
|
|
70013
69999
|
* @param {boolean} [props.focusCapture] - Traps Tab navigation inside the
|
|
@@ -70968,11 +70954,14 @@ const usePopoverProps = props => {
|
|
|
70968
70954
|
// What the browser paints above the page goes with what is laid over its
|
|
70969
70955
|
// top edge, from the start of the opening to the start of the closing: a
|
|
70970
70956
|
// local popover's backdrop stops at its container.
|
|
70971
|
-
if (isTopLayer
|
|
70972
|
-
|
|
70973
|
-
|
|
70974
|
-
|
|
70975
|
-
|
|
70957
|
+
if (isTopLayer) {
|
|
70958
|
+
const popupThemeColor = readPopupThemeColor(popoverEl, themeColor);
|
|
70959
|
+
if (popupThemeColor !== "none") {
|
|
70960
|
+
addCleanup(pushPopupThemeColor({
|
|
70961
|
+
themeColor: popupThemeColor,
|
|
70962
|
+
backdropColor: backdropEl ? readBackdropColor(backdropEl) : null
|
|
70963
|
+
}));
|
|
70964
|
+
}
|
|
70976
70965
|
}
|
|
70977
70966
|
const cancelOpenInteractionSuppression = !silent && hasCssTransitionAnimation ? suppressPointerEventsDuringTransition(popoverEl) : null;
|
|
70978
70967
|
// autoFocus={false}: opening moves no focus at all — whoever has the
|
|
@@ -71390,10 +71379,11 @@ const css$C = /* css */`@layer navi {
|
|
|
71390
71379
|
* identically): the wash the backdrop paints over what is behind.
|
|
71391
71380
|
* @param {string} [props.backdropFilter] - Forwarded as-is: what that wash
|
|
71392
71381
|
* does to the picture underneath, `"blur(4px)"` and the like.
|
|
71393
|
-
* @param {string|false} [props.themeColor] - Forwarded as-is: the
|
|
71394
|
-
* browser paints above the page while the popup is open
|
|
71395
|
-
*
|
|
71396
|
-
* leaves the page's colour alone.
|
|
71382
|
+
* @param {"auto"|string|false} [props.themeColor] - Forwarded as-is: the
|
|
71383
|
+
* colour the browser paints above the page while the popup is open.
|
|
71384
|
+
* `"auto"` works it out from what the popup lays over the top edge, a
|
|
71385
|
+
* colour forces it, `false` leaves the page's colour alone. Left out, the
|
|
71386
|
+
* `--navi-popup-theme-color` token decides.
|
|
71397
71387
|
* @param {boolean|"auto"|"fading"|"scaling"|"sliding"|`slide-from-${string}`|"expanding"|`expand-${string}`|"lifting"|{open: boolean|"auto"|"fading"|"scaling"|"sliding"|`slide-from-${string}`, close: "lifting"}} [props.animation]
|
|
71398
71388
|
* - Forwarded to whichever renders — see either component's own doc.
|
|
71399
71389
|
* `"expanding"`/`"expand-*"` are `Popover`'s own; `"lifting"` and
|
|
@@ -84127,7 +84117,8 @@ const requestPickerListEntry = (pickerEl, pickerInputEl, e, goal) => {
|
|
|
84127
84117
|
return;
|
|
84128
84118
|
}
|
|
84129
84119
|
const {
|
|
84130
|
-
id: entry
|
|
84120
|
+
id: entry,
|
|
84121
|
+
requester
|
|
84131
84122
|
} = e.detail;
|
|
84132
84123
|
const isThere = uiState.some(item => compareTwoJsValues(item, entry));
|
|
84133
84124
|
if (goal === "select" ? isThere : !isThere) {
|
|
@@ -84144,7 +84135,8 @@ const requestPickerListEntry = (pickerEl, pickerInputEl, e, goal) => {
|
|
|
84144
84135
|
});
|
|
84145
84136
|
sendClosedPickerChange(pickerInputEl, {
|
|
84146
84137
|
event: e,
|
|
84147
|
-
name: goal
|
|
84138
|
+
name: goal,
|
|
84139
|
+
requester
|
|
84148
84140
|
});
|
|
84149
84141
|
}
|
|
84150
84142
|
});
|
|
@@ -84618,7 +84610,9 @@ const PickerFirstResolver = props => {
|
|
|
84618
84610
|
* the `<Picker type="confirm">` the cross then is, plain text or JSX. Asked
|
|
84619
84611
|
* BEFORE the ui state is emptied, so answering no leaves the field exactly
|
|
84620
84612
|
* as it was; answering yes clears and sends, and the picker's own action
|
|
84621
|
-
* receives the cleared value like any other choice.
|
|
84613
|
+
* receives the cleared value like any other choice. A cut (Ctrl+X) on such a
|
|
84614
|
+
* picker copies the value and leaves it in place: no clear without the
|
|
84615
|
+
* question.
|
|
84622
84616
|
* @param {"icon"|"headless"|"discrete"|"button"|"text"|"bare"|"picker"} [variant]
|
|
84623
84617
|
* How the trigger is drawn. `"button"` is a Button's drawing — surface,
|
|
84624
84618
|
* padding, a centered label, no chevron — and what a `type="confirm"` picker
|