@jsenv/navi 0.29.299 → 0.29.300
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 +94 -4
- package/dist/dev/jsenv_navi.js.map +3 -3
- package/dist/jsenv_navi.js +49 -3
- package/dist/jsenv_navi.js.map +3 -3
- package/docs/AI_INSTRUCTIONS.md +2 -1
- package/docs/popup_open.md +83 -2
- package/package.json +1 -1
package/dist/dev/jsenv_navi.js
CHANGED
|
@@ -62349,6 +62349,7 @@ const css$B = /* css */`.navi_picker {
|
|
|
62349
62349
|
--popover-background-color: var(--picker-popup-background-color, var(--navi-popup-background-color));
|
|
62350
62350
|
--popover-outline-width: var(--picker-outline-width);
|
|
62351
62351
|
--popover-outline-color: var(--picker-outline-color);
|
|
62352
|
+
--popover-box-shadow: var(--picker-popup-box-shadow, var(--navi-popup-box-shadow));
|
|
62352
62353
|
--popover-max-height: var(--picker-popover-max-height);
|
|
62353
62354
|
min-width: var(--picker-popover-min-width, var(--anchor-width, 0px));
|
|
62354
62355
|
cursor: default;
|
|
@@ -62385,6 +62386,7 @@ const css$B = /* css */`.navi_picker {
|
|
|
62385
62386
|
--dialog-background-color: var(--picker-popup-background-color, var(--navi-popup-background-color));
|
|
62386
62387
|
--dialog-outline-width: var(--picker-outline-width);
|
|
62387
62388
|
--dialog-outline-color: var(--picker-outline-color);
|
|
62389
|
+
--dialog-box-shadow: var(--picker-popup-box-shadow, var(--navi-popup-box-shadow));
|
|
62388
62390
|
--dialog-min-width: var(--picker-dialog-min-width);
|
|
62389
62391
|
--dialog-min-height: var(--picker-dialog-min-height);
|
|
62390
62392
|
--dialog-max-width: var(--picker-dialog-max-width);
|
|
@@ -62569,7 +62571,10 @@ const PickerCustom = props => {
|
|
|
62569
62571
|
// hands the popup that controller, and a controlled Dialog/Popover reads
|
|
62570
62572
|
// no onOpen/onClose of its own.
|
|
62571
62573
|
onOpen,
|
|
62572
|
-
onClose
|
|
62574
|
+
onClose,
|
|
62575
|
+
// What opens the popup — the press, or an interaction navi detects
|
|
62576
|
+
// ("longpress", "contextmenu"…, or a list of them). See the JSDoc.
|
|
62577
|
+
openOn = "press"
|
|
62573
62578
|
} = props;
|
|
62574
62579
|
// Resolve the id the same way useControlProps does (own id > Field's id > generated id)
|
|
62575
62580
|
// before computing popupId below, so two Pickers without an explicit id never collide.
|
|
@@ -62605,6 +62610,7 @@ const PickerCustom = props => {
|
|
|
62605
62610
|
delete pickerProps.onConfirm;
|
|
62606
62611
|
delete pickerProps.onOpen;
|
|
62607
62612
|
delete pickerProps.onClose;
|
|
62613
|
+
delete pickerProps.openOn;
|
|
62608
62614
|
// Read below for the popup alone; on the trigger it would land on the DOM as
|
|
62609
62615
|
// an unknown attribute holding a ref object.
|
|
62610
62616
|
delete pickerProps.anchor;
|
|
@@ -63002,7 +63008,29 @@ const PickerCustom = props => {
|
|
|
63002
63008
|
// could then never form. So the picker steps back and opens on the click,
|
|
63003
63009
|
// which the browser only delivers if the press stayed a press (a gesture
|
|
63004
63010
|
// swallows the click it leaves behind).
|
|
63005
|
-
|
|
63011
|
+
// Opening on something else than the press: the hold, the right click.
|
|
63012
|
+
// Declared on the picker itself, as the caller would declare their own,
|
|
63013
|
+
// so it is read and arbitrated like any other gesture — a swipe on the
|
|
63014
|
+
// same card takes the press a hold would have taken — and gated like one:
|
|
63015
|
+
// a read-only picker refuses it where the finger is. The press is then
|
|
63016
|
+
// nobody's: a tap on the card opens nothing (see the two reactions
|
|
63017
|
+
// below), and the keyboard keeps its own ways in (the shortcuts above).
|
|
63018
|
+
const openOnList = Array.isArray(openOn) ? openOn : [openOn];
|
|
63019
|
+
const opensOnPress = openOnList.includes("press");
|
|
63020
|
+
let interactions = props.interactions;
|
|
63021
|
+
if (!opensOnPress) {
|
|
63022
|
+
interactions = {
|
|
63023
|
+
...interactions
|
|
63024
|
+
};
|
|
63025
|
+
for (const type of openOnList) {
|
|
63026
|
+
interactions[type] = e => {
|
|
63027
|
+
requestOpen(e);
|
|
63028
|
+
};
|
|
63029
|
+
}
|
|
63030
|
+
pickerProps.interactions = interactions;
|
|
63031
|
+
pickerProps["data-open-on"] = openOnList.join(" ");
|
|
63032
|
+
}
|
|
63033
|
+
const interactionsDispute = interactionsDisputeThePress(interactions);
|
|
63006
63034
|
Object.assign(pickerProps, {
|
|
63007
63035
|
eventReactionDefinitions: {
|
|
63008
63036
|
mouseDown: e => {
|
|
@@ -63028,7 +63056,7 @@ const PickerCustom = props => {
|
|
|
63028
63056
|
// because that is where such a box says what it travels by — and
|
|
63029
63057
|
// asked at every press, since what the picker sits in is not the
|
|
63030
63058
|
// picker's to know at mount.
|
|
63031
|
-
if (interactionsDispute || isPressDisputedByDrag(e.target)) {
|
|
63059
|
+
if (!opensOnPress || interactionsDispute || isPressDisputedByDrag(e.target)) {
|
|
63032
63060
|
return null;
|
|
63033
63061
|
}
|
|
63034
63062
|
return {
|
|
@@ -63045,6 +63073,11 @@ const PickerCustom = props => {
|
|
|
63045
63073
|
if (isWithinPickerContent(e.target)) {
|
|
63046
63074
|
return null;
|
|
63047
63075
|
}
|
|
63076
|
+
if (!opensOnPress) {
|
|
63077
|
+
// Neither the tap, nor the click a hold leaves behind: the press
|
|
63078
|
+
// is not what opens this picker.
|
|
63079
|
+
return null;
|
|
63080
|
+
}
|
|
63048
63081
|
// When a label is clicked it transfers focus to the select
|
|
63049
63082
|
// in that case we want to open it (otherwise we have already opened on mousedown interaction)
|
|
63050
63083
|
// And when a gesture disputes the press (see the two disputes
|
|
@@ -63125,7 +63158,12 @@ const PickerContentInsidePopup = props => {
|
|
|
63125
63158
|
// itself, and this one does not. Popover ignores it, same as Dialog ignores
|
|
63126
63159
|
// marginWithAnchor.
|
|
63127
63160
|
dockedOnSmallTouchScreen,
|
|
63161
|
+
// Same again: the dialog takes the trigger's box as a floor (and, with
|
|
63162
|
+
// dialogMaxWidth="var(--anchor-width)", as a ceiling) — what keeps a card
|
|
63163
|
+
// its own width once lifted. Dialog's own `sizeFromAnchor`.
|
|
63164
|
+
dialogSizeFromAnchor,
|
|
63128
63165
|
animation,
|
|
63166
|
+
animationDuration,
|
|
63129
63167
|
// mode="callout": what the callout says about what it holds, and paints
|
|
63130
63168
|
// in its border and icon — "none" for a plain tooltip (see the callout
|
|
63131
63169
|
// defaults in PickerCustomResolver). And whether it wears a cross: without
|
|
@@ -63186,6 +63224,7 @@ const PickerContentInsidePopup = props => {
|
|
|
63186
63224
|
mode: mode,
|
|
63187
63225
|
layer: popupLayer,
|
|
63188
63226
|
animation: animation,
|
|
63227
|
+
animationDuration: animationDuration,
|
|
63189
63228
|
positionArea: isPopover ? positionArea ?? (popoverMode === "nearby" ? "bottom-start" : "inset(top-left)") : positionArea,
|
|
63190
63229
|
marginWithAnchor: isPopover ? popoverSpacing : undefined,
|
|
63191
63230
|
marginWithContainer: marginWithContainer === undefined && isPopover ? popoverSpacing : marginWithContainer,
|
|
@@ -63200,6 +63239,7 @@ const PickerContentInsidePopup = props => {
|
|
|
63200
63239
|
expandX: isPopover ? undefined : dialogExpandX,
|
|
63201
63240
|
expandY: isPopover ? undefined : dialogExpandY,
|
|
63202
63241
|
dockedOnSmallTouchScreen: isPopover ? undefined : dockedOnSmallTouchScreen,
|
|
63242
|
+
sizeFromAnchor: isPopover ? undefined : dialogSizeFromAnchor,
|
|
63203
63243
|
children: jsx(PopupModeContext.Provider, {
|
|
63204
63244
|
value: mode,
|
|
63205
63245
|
children: children
|
|
@@ -71217,6 +71257,11 @@ const css$t = /* css */`@layer navi {
|
|
|
71217
71257
|
}
|
|
71218
71258
|
}
|
|
71219
71259
|
|
|
71260
|
+
&[data-open-on~="longpress"] {
|
|
71261
|
+
-webkit-touch-callout: none;
|
|
71262
|
+
user-select: none;
|
|
71263
|
+
}
|
|
71264
|
+
|
|
71220
71265
|
&[navi-ui-custom] {
|
|
71221
71266
|
& .navi_picker_input {
|
|
71222
71267
|
top: calc(-1 * (var(--picker-border-width) + var(--x-picker-press-padding-top)));
|
|
@@ -72045,6 +72090,7 @@ const PickerStyleCSSVars = {
|
|
|
72045
72090
|
"dialogMaxHeight": ["--picker-dialog-max-height", "maxHeight"],
|
|
72046
72091
|
"popupBackgroundColor": "--picker-popup-background-color",
|
|
72047
72092
|
"popupBorderRadius": ["--picker-popup-border-radius", "borderRadius"],
|
|
72093
|
+
"popupBoxShadow": ["--picker-popup-box-shadow", "boxShadow"],
|
|
72048
72094
|
"dialogBorderWidth": ["--picker-dialog-border-width", "borderWidth"],
|
|
72049
72095
|
"slotSpacing": ["--picker-slot-spacing", "margin"],
|
|
72050
72096
|
"pressPadding": ["--picker-press-padding", "padding"],
|
|
@@ -72142,6 +72188,9 @@ const PickerFirstResolver = props => {
|
|
|
72142
72188
|
* action?: (value: any, event: Event) => void,
|
|
72143
72189
|
* children?: import("ignore:preact").ComponentChildren,
|
|
72144
72190
|
* mode?: "popover" | "dialog" | "callout",
|
|
72191
|
+
* openOn?: "press" | "longpress" | "contextmenu" | string | string[],
|
|
72192
|
+
* animation?: boolean | "auto" | "fading" | "scaling" | "sliding" | "growing" | `slide-from-${string}`,
|
|
72193
|
+
* animationDuration?: string,
|
|
72145
72194
|
* calloutStatus?: "info" | "warning" | "error" | "success" | "none",
|
|
72146
72195
|
* calloutIcon?: boolean,
|
|
72147
72196
|
* calloutCloseButton?: boolean,
|
|
@@ -72172,6 +72221,7 @@ const PickerFirstResolver = props => {
|
|
|
72172
72221
|
* dialogMaxHeight?: number | string,
|
|
72173
72222
|
* popupBackgroundColor?: string,
|
|
72174
72223
|
* popupBorderRadius?: number | string,
|
|
72224
|
+
* popupBoxShadow?: string,
|
|
72175
72225
|
* dialogBorderWidth?: number | string,
|
|
72176
72226
|
* clearable?: boolean,
|
|
72177
72227
|
* picksNothing?: boolean,
|
|
@@ -72184,6 +72234,7 @@ const PickerFirstResolver = props => {
|
|
|
72184
72234
|
* dialogExpand?: boolean,
|
|
72185
72235
|
* dialogExpandX?: boolean,
|
|
72186
72236
|
* dialogExpandY?: boolean,
|
|
72237
|
+
* dialogSizeFromAnchor?: boolean,
|
|
72187
72238
|
* marginWithContainer?: number | string,
|
|
72188
72239
|
* anchor?: import("ignore:preact").RefObject<HTMLElement> | HTMLElement,
|
|
72189
72240
|
* escapeEffect?: "cancel" | "close",
|
|
@@ -72201,6 +72252,23 @@ const PickerFirstResolver = props => {
|
|
|
72201
72252
|
* variant that paints the trigger transparent leaves the popup a real sheet.
|
|
72202
72253
|
* @param {number|string} [popupBorderRadius] The popup's corners. Left out they
|
|
72203
72254
|
* echo the trigger's `borderRadius`.
|
|
72255
|
+
* @param {string} [popupBoxShadow] The popup's shadow, popover or dialog. Left
|
|
72256
|
+
* out it is the one every navi popup casts. `"none"` for a popup that is
|
|
72257
|
+
* not a sheet — a card lifted out of a page draws its own edges, and the
|
|
72258
|
+
* popup only carries it (see `dialogSizeFromAnchor`).
|
|
72259
|
+
* @param {"press"|"longpress"|"contextmenu"|string|string[]} [openOn="press"]
|
|
72260
|
+
* What opens the popup. The press, by default — the way a native select
|
|
72261
|
+
* opens. Any other name is an interaction navi detects (see
|
|
72262
|
+
* docs/interactions.md: `"longpress"`, `"contextmenu"`, `"dblclick"`…), or
|
|
72263
|
+
* a list of them — `["longpress", "contextmenu"]` is the hold on a phone and
|
|
72264
|
+
* the right click at a desk. The picker declares it on itself, so it is
|
|
72265
|
+
* arbitrated like any other gesture: a swipe on the same card takes the
|
|
72266
|
+
* press a hold would have taken. A tap then opens nothing — the press stays
|
|
72267
|
+
* free for what the `ui` holds, which is what lets a whole card be a picker
|
|
72268
|
+
* without every touch on it opening the sheet — and the keyboard keeps its
|
|
72269
|
+
* ways in (Enter, Space, the arrows). Being a gesture, the open goes through
|
|
72270
|
+
* the interaction gate as one: a `readOnly` picker refuses it and says so
|
|
72271
|
+
* where the finger is, whatever `openWhileReadOnly` says.
|
|
72204
72272
|
* @param {import("ignore:preact").ComponentChildren | "default"} [ui] What the
|
|
72205
72273
|
* trigger draws in place of the value's default rendering (a date, a list
|
|
72206
72274
|
* joined by commas…) — and then all it draws: `placeholder` is not shown
|
|
@@ -72312,7 +72380,14 @@ const PickerFirstResolver = props => {
|
|
|
72312
72380
|
* @param {boolean} [picksNothing] The popup asks something rather than holding
|
|
72313
72381
|
* an answer, so the trigger draws a label and never a value: no chevron, no
|
|
72314
72382
|
* clear cross, in any variant. `type="confirm"` says it for itself; say it
|
|
72315
|
-
* for a popup of your own that is a menu of actions rather than a choice
|
|
72383
|
+
* for a popup of your own that is a menu of actions rather than a choice —
|
|
72384
|
+
* or a DOOR: a drawing that grows to be looked at (a weather scene, a plan),
|
|
72385
|
+
* with no `action` at all. The picker is then a trigger and a popup, and
|
|
72386
|
+
* nothing more: its close does nothing, and what it keeps from being a
|
|
72387
|
+
* control is what a door still needs — the role of a button, the keyboard
|
|
72388
|
+
* opening it, the anchor being itself, and one popup per instance without
|
|
72389
|
+
* an id to wire. See "The trigger wears the wait" in docs/popup_open.md for
|
|
72390
|
+
* when that beats a `Button` opening a shared `Dialog`.
|
|
72316
72391
|
* @param {string|import("ignore:preact").ComponentChildren} [clearConfirm] The
|
|
72317
72392
|
* question asked before the clear cross clears anything — the `message` of
|
|
72318
72393
|
* the `<Picker type="confirm">` the cross then is, plain text or JSX. Asked
|
|
@@ -72419,6 +72494,21 @@ const PickerFirstResolver = props => {
|
|
|
72419
72494
|
* a dialog docked by `dockedOnSmallTouchScreen` withdraws it and stays
|
|
72420
72495
|
* container-wide, so both can be stated at once.
|
|
72421
72496
|
* @param {number|string} [dialogMaxHeight] Same, on the height.
|
|
72497
|
+
* @param {boolean|"auto"|"fading"|"scaling"|"sliding"|"growing"|`slide-from-${string}`} [animation]
|
|
72498
|
+
* The popup's own (see Popover/Dialog). `"growing"` is the one a picker
|
|
72499
|
+
* whose `ui` is a whole piece of the page wants: the popup is the browser
|
|
72500
|
+
* morphing the trigger's box into what carries `data-grow` inside the popup
|
|
72501
|
+
* (the popup itself when nothing does), and back on close. The trigger IS
|
|
72502
|
+
* the anchor, so nothing has to be named for it — see `dialogSizeFromAnchor`
|
|
72503
|
+
* for a card that must keep its width on the way, and leave it out for a
|
|
72504
|
+
* drawing that opens precisely to get bigger.
|
|
72505
|
+
* @param {string} [animationDuration] The popup's own (`--popup-animation-duration`).
|
|
72506
|
+
* @param {boolean} [dialogSizeFromAnchor] Dialog mode: the dialog takes the
|
|
72507
|
+
* trigger's box as a floor (`--anchor-width`/`--anchor-height`, Dialog's
|
|
72508
|
+
* own `sizeFromAnchor`) — and, with `dialogMaxWidth="var(--anchor-width)"`,
|
|
72509
|
+
* as a ceiling too. That pair is what keeps a card its own width once
|
|
72510
|
+
* lifted out of the page (`animation="growing"`, with `data-grow` on the
|
|
72511
|
+
* card inside the popup): it moves, and nothing else about it changes.
|
|
72422
72512
|
* @param {"cancel"|"close"} [escapeEffect="cancel"] What Escape does to an open
|
|
72423
72513
|
* picker. "cancel" puts back the value the picker had at open, and a dialog
|
|
72424
72514
|
* picker also goes back in history — so anything written to the url while it
|