@jsenv/navi 0.29.304 → 0.29.305
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 +147 -18
- package/dist/dev/jsenv_navi.js.map +7 -7
- package/dist/jsenv_navi.js +139 -17
- package/dist/jsenv_navi.js.map +7 -7
- package/package.json +1 -1
package/dist/dev/jsenv_navi.js
CHANGED
|
@@ -38366,6 +38366,15 @@ const useInteractiveProps = (props, {
|
|
|
38366
38366
|
const debugAction = useDebugAction();
|
|
38367
38367
|
const debugInteraction = useDebugInteraction();
|
|
38368
38368
|
const debugFocus = useDebugFocus();
|
|
38369
|
+
|
|
38370
|
+
// The very instance a run of this control is using, held in a SIGNAL because
|
|
38371
|
+
// the busy state below follows it: it is captured at navi_action_start and
|
|
38372
|
+
// released when the run settles (see onnavi_action_start).
|
|
38373
|
+
const runningActionSignalRef = useRef(null);
|
|
38374
|
+
if (runningActionSignalRef.current === null) {
|
|
38375
|
+
runningActionSignalRef.current = signal(null);
|
|
38376
|
+
}
|
|
38377
|
+
uiStateController.runningActionSignal = runningActionSignalRef.current;
|
|
38369
38378
|
{
|
|
38370
38379
|
const {
|
|
38371
38380
|
autoFocus,
|
|
@@ -38404,7 +38413,15 @@ const useInteractiveProps = (props, {
|
|
|
38404
38413
|
const isActionRequesterComputed = useMemo(() => parentActionRequesterSignal ? computed(() => parentActionRequesterSignal.value === ref.current) : null, [parentActionRequesterSignal]);
|
|
38405
38414
|
const parallelGuard = useContext(ParallelGuardContext);
|
|
38406
38415
|
const parentAction = useContext(ActionContext);
|
|
38407
|
-
|
|
38416
|
+
// The instance the run in flight is using when there is one, and only
|
|
38417
|
+
// then boundAction: boundAction can be a proxy following the UI state
|
|
38418
|
+
// signal, and that state moves while a run is out — a popup content
|
|
38419
|
+
// unmounting takes the group's value with it. The proxy would resolve to
|
|
38420
|
+
// the instance for the new value, which is idle, and the control would
|
|
38421
|
+
// stop waiting on a run that is still going. What it waits on is the run
|
|
38422
|
+
// it started, from navi_action_start to its settlement.
|
|
38423
|
+
const runningAction = uiStateController.runningActionSignal.value;
|
|
38424
|
+
const actionStatus = useActionStatus(runningAction || boundAction);
|
|
38408
38425
|
const networkPolicyReason = useNetworkPolicyReason();
|
|
38409
38426
|
const {
|
|
38410
38427
|
disabled,
|
|
@@ -38765,7 +38782,7 @@ const useInteractiveProps = (props, {
|
|
|
38765
38782
|
// state has already moved to the new value by now — the proxy would
|
|
38766
38783
|
// resolve to the instance for that new value, which is not the one
|
|
38767
38784
|
// running.
|
|
38768
|
-
uiStateController.
|
|
38785
|
+
uiStateController.runningActionSignal.peek()?.abort(`superseded by a newer request on this control`);
|
|
38769
38786
|
return;
|
|
38770
38787
|
}
|
|
38771
38788
|
debugAction(e, `executing action ${e.detail.action.callSource}`);
|
|
@@ -38787,14 +38804,14 @@ const useInteractiveProps = (props, {
|
|
|
38787
38804
|
// this run (see the optimistic queue above), the state — and the
|
|
38788
38805
|
// proxy's resolution — will have moved on.
|
|
38789
38806
|
const runAction = e.detail.action;
|
|
38790
|
-
uiStateController.
|
|
38807
|
+
uiStateController.runningActionSignal.value = runAction.getCurrentAction?.() ?? runAction;
|
|
38791
38808
|
// Fires when the run's underlying work has settled — even for an
|
|
38792
38809
|
// aborted run, whose promise is awaited to completion (see
|
|
38793
38810
|
// performRun in actions.js) — which is exactly what "the server is
|
|
38794
38811
|
// done with it" means, and therefore when the queued request may go.
|
|
38795
38812
|
e.detail.addSideEffect(outcome => {
|
|
38796
38813
|
uiStateController.actionInFlight = false;
|
|
38797
|
-
uiStateController.
|
|
38814
|
+
uiStateController.runningActionSignal.value = null;
|
|
38798
38815
|
uiStateController.parallelGuard?.release(uiStateController);
|
|
38799
38816
|
const queuedEvent = uiStateController.queuedActionAllowedEvent;
|
|
38800
38817
|
if (!queuedEvent) {
|
|
@@ -59115,14 +59132,22 @@ const clipOf = (side, distance) => {
|
|
|
59115
59132
|
// before the next one takes it (see releaseGrowInProgress).
|
|
59116
59133
|
const NAME = "navi-popup-grow";
|
|
59117
59134
|
const NAME_PROPERTY = "view-transition-name";
|
|
59118
|
-
// Worn by the root for the length of the movement
|
|
59119
|
-
//
|
|
59135
|
+
// Worn by the root for the length of the movement, saying which way it goes
|
|
59136
|
+
// ("opening" | "closing") — what the CSS keys the page's own opt-out and the
|
|
59137
|
+
// clip near the anchor's end on, and the movement's only trace in the document.
|
|
59120
59138
|
const ROOT_ATTRIBUTE = "data-navi-popup-grow";
|
|
59139
|
+
// What the two boxes are to each other (Dialog's `grow`: "box" | "scene"),
|
|
59140
|
+
// worn by the root too — it decides how each picture sits in the moving box.
|
|
59141
|
+
const KIND_ATTRIBUTE = "data-navi-popup-grow-kind";
|
|
59121
59142
|
// Inside the popup, the one node that IS the anchor once it has grown.
|
|
59122
59143
|
const TARGET_SELECTOR = "[data-grow]";
|
|
59123
59144
|
// The popup's own animation duration, published on the root because the
|
|
59124
59145
|
// ::view-transition tree hangs off it and inherits from nowhere else.
|
|
59125
59146
|
const DURATION_PROPERTY = "--navi-popup-grow-duration";
|
|
59147
|
+
// The corners of the box being left, published the same way: the pictures are
|
|
59148
|
+
// clipped to the moving box (dialog.jsx), and a card with rounded corners must
|
|
59149
|
+
// not travel with square ones.
|
|
59150
|
+
const BORDER_RADIUS_PROPERTY = "--navi-popup-grow-border-radius";
|
|
59126
59151
|
|
|
59127
59152
|
let releaseGrowInProgress = null;
|
|
59128
59153
|
|
|
@@ -59133,13 +59158,13 @@ let releaseGrowInProgress = null;
|
|
|
59133
59158
|
* `opened` says which way: the box being left is the anchor when the popup is
|
|
59134
59159
|
* opening and the popup when it is closing, and the arriving one is only known
|
|
59135
59160
|
* once the change has been made (the content a popup grows into is built by
|
|
59136
|
-
* that very change).
|
|
59161
|
+
* that very change). `grow` is Dialog's own prop of that name.
|
|
59137
59162
|
*/
|
|
59138
59163
|
const growPopupFromAnchor = (
|
|
59139
59164
|
popupEl,
|
|
59140
59165
|
anchorElement,
|
|
59141
59166
|
applyChange,
|
|
59142
|
-
{ opened },
|
|
59167
|
+
{ opened, grow },
|
|
59143
59168
|
) => {
|
|
59144
59169
|
const startViewTransition = ensureDocumentStartViewTransition();
|
|
59145
59170
|
// A movement still wearing the name would make the name two elements wide,
|
|
@@ -59150,7 +59175,8 @@ const growPopupFromAnchor = (
|
|
|
59150
59175
|
const elementLeaving = opened ? anchorElement : resolveGrowTarget(popupEl);
|
|
59151
59176
|
const giveBackNameLeaving = wearGrowName(elementLeaving);
|
|
59152
59177
|
const root = document.documentElement;
|
|
59153
|
-
root.setAttribute(ROOT_ATTRIBUTE, "");
|
|
59178
|
+
root.setAttribute(ROOT_ATTRIBUTE, opened ? "opening" : "closing");
|
|
59179
|
+
root.setAttribute(KIND_ATTRIBUTE, grow);
|
|
59154
59180
|
const duration = getComputedStyle(popupEl)
|
|
59155
59181
|
.getPropertyValue("--popup-animation-duration")
|
|
59156
59182
|
.trim();
|
|
@@ -59160,6 +59186,10 @@ const growPopupFromAnchor = (
|
|
|
59160
59186
|
// browser's own pace.
|
|
59161
59187
|
root.style.setProperty(DURATION_PROPERTY, duration);
|
|
59162
59188
|
}
|
|
59189
|
+
const borderRadius = getComputedStyle(elementLeaving).borderRadius;
|
|
59190
|
+
if (borderRadius) {
|
|
59191
|
+
root.style.setProperty(BORDER_RADIUS_PROPERTY, borderRadius);
|
|
59192
|
+
}
|
|
59163
59193
|
|
|
59164
59194
|
let giveBackNameArriving = null;
|
|
59165
59195
|
const release = () => {
|
|
@@ -59170,7 +59200,9 @@ const growPopupFromAnchor = (
|
|
|
59170
59200
|
giveBackNameLeaving();
|
|
59171
59201
|
giveBackNameArriving?.();
|
|
59172
59202
|
root.removeAttribute(ROOT_ATTRIBUTE);
|
|
59203
|
+
root.removeAttribute(KIND_ATTRIBUTE);
|
|
59173
59204
|
root.style.removeProperty(DURATION_PROPERTY);
|
|
59205
|
+
root.style.removeProperty(BORDER_RADIUS_PROPERTY);
|
|
59174
59206
|
};
|
|
59175
59207
|
releaseGrowInProgress = release;
|
|
59176
59208
|
|
|
@@ -59734,6 +59766,73 @@ const css$E = /* css */`
|
|
|
59734
59766
|
&::view-transition-new(navi-popup-grow) {
|
|
59735
59767
|
animation-duration: var(--navi-popup-grow-duration, 0.25s);
|
|
59736
59768
|
}
|
|
59769
|
+
|
|
59770
|
+
/* Each picture is drawn as wide as the box and as tall as it is, so a box
|
|
59771
|
+
that grows in height alone (a card keeping its width) would show the
|
|
59772
|
+
whole taller picture from the first frame, and the movement would read
|
|
59773
|
+
as a fade. Clipped to the box, the picture is uncovered as the box
|
|
59774
|
+
grows and covered back as it shrinks — behind the corners the box
|
|
59775
|
+
has in the page, published by popup_grow.js. */
|
|
59776
|
+
&::view-transition-image-pair(navi-popup-grow) {
|
|
59777
|
+
border-radius: var(--navi-popup-grow-border-radius, 0);
|
|
59778
|
+
overflow: clip;
|
|
59779
|
+
}
|
|
59780
|
+
|
|
59781
|
+
/* One scene through two frames (Dialog's grow="scene"): each picture
|
|
59782
|
+
covers the box, cropped around its centre, so what both frames show
|
|
59783
|
+
lands on itself. */
|
|
59784
|
+
&[data-navi-popup-grow-kind="scene"] {
|
|
59785
|
+
&::view-transition-old(navi-popup-grow),
|
|
59786
|
+
&::view-transition-new(navi-popup-grow) {
|
|
59787
|
+
height: 100%;
|
|
59788
|
+
object-fit: cover;
|
|
59789
|
+
}
|
|
59790
|
+
}
|
|
59791
|
+
|
|
59792
|
+
/* The anchor lives in the page, under the fixed bars; the popup lives in
|
|
59793
|
+
the top layer, over them. The pictures are painted above everything,
|
|
59794
|
+
bars included, so near the anchor's end of the movement the whole tree
|
|
59795
|
+
is clipped to the room between the bars — a thumbnail half under the
|
|
59796
|
+
top bar leaves from under it and comes back under it — and freed near
|
|
59797
|
+
the popup's end, where a tall dialog may stand over them. Clipped for
|
|
59798
|
+
the 65% of the time nearest the anchor: with the group's own ease that
|
|
59799
|
+
leaves the last 35% of the time to cover more than half of the trip,
|
|
59800
|
+
so the picture is out of the bars before the clip closes on it. */
|
|
59801
|
+
&::view-transition {
|
|
59802
|
+
animation: navi-popup-grow-clip var(--navi-popup-grow-duration, 0.25s)
|
|
59803
|
+
ease both;
|
|
59804
|
+
}
|
|
59805
|
+
&[data-navi-popup-grow="closing"]::view-transition {
|
|
59806
|
+
animation-direction: reverse;
|
|
59807
|
+
}
|
|
59808
|
+
}
|
|
59809
|
+
/* The bars sit at the app's own inset (fixed_bar.jsx), so the room they
|
|
59810
|
+
take starts there; both tokens are 0px where nothing takes any. */
|
|
59811
|
+
@keyframes navi-popup-grow-clip {
|
|
59812
|
+
0%,
|
|
59813
|
+
65% {
|
|
59814
|
+
clip-path: inset(
|
|
59815
|
+
calc(
|
|
59816
|
+
var(--navi-app-inset-top, 0px) +
|
|
59817
|
+
var(--navi-fixed-bar-space-top, 0px)
|
|
59818
|
+
)
|
|
59819
|
+
calc(
|
|
59820
|
+
var(--navi-app-inset-right, 0px) +
|
|
59821
|
+
var(--navi-fixed-bar-space-right, 0px)
|
|
59822
|
+
)
|
|
59823
|
+
calc(
|
|
59824
|
+
var(--navi-app-inset-bottom, 0px) +
|
|
59825
|
+
var(--navi-fixed-bar-space-bottom, 0px)
|
|
59826
|
+
)
|
|
59827
|
+
calc(
|
|
59828
|
+
var(--navi-app-inset-left, 0px) +
|
|
59829
|
+
var(--navi-fixed-bar-space-left, 0px)
|
|
59830
|
+
)
|
|
59831
|
+
);
|
|
59832
|
+
}
|
|
59833
|
+
100% {
|
|
59834
|
+
clip-path: inset(0);
|
|
59835
|
+
}
|
|
59737
59836
|
}
|
|
59738
59837
|
|
|
59739
59838
|
${surfaceTextCss}
|
|
@@ -59870,6 +59969,15 @@ const css$E = /* css */`
|
|
|
59870
59969
|
* prop) and grows into whatever inside the dialog carries `data-grow`, the
|
|
59871
59970
|
* dialog itself when nothing does. `"auto"` never picks it: only the caller
|
|
59872
59971
|
* knows the two boxes are one object. See `popup_grow.js`.
|
|
59972
|
+
* @param {"box"|"scene"} [props.grow="box"] - Under `animation="growing"`,
|
|
59973
|
+
* what the anchor and what it grows into are to each other, which decides
|
|
59974
|
+
* how their pictures sit in the box moving between them. `"box"`: one
|
|
59975
|
+
* object at two sizes — a card gaining fields. Each picture is drawn at the
|
|
59976
|
+
* box's width from its top edge, and a box growing in height uncovers more
|
|
59977
|
+
* of it: the header stays where it is, the rest extends. `"scene"`: one
|
|
59978
|
+
* scene through two frames — a thumbnail and the map it is cut from. Each
|
|
59979
|
+
* picture covers the box, cropped around its centre and never distorted, so
|
|
59980
|
+
* what both frames show lands on itself.
|
|
59873
59981
|
* @param {string} [props.animationDuration] - Maps to
|
|
59874
59982
|
* `--popup-animation-duration`.
|
|
59875
59983
|
* @param {Element|{current: Element}|string} [props.anchor] - Never used for
|
|
@@ -60212,6 +60320,7 @@ const useDialogProps = props => {
|
|
|
60212
60320
|
// once, held at that size while open. See this prop's own JSDoc above.
|
|
60213
60321
|
sizing = "auto",
|
|
60214
60322
|
animation,
|
|
60323
|
+
grow = "box",
|
|
60215
60324
|
// Inert unless sizeFromAnchor below (see this file's top comment) —
|
|
60216
60325
|
// Dialog's own positioning is never relative to it.
|
|
60217
60326
|
anchor,
|
|
@@ -60438,7 +60547,8 @@ const useDialogProps = props => {
|
|
|
60438
60547
|
return;
|
|
60439
60548
|
}
|
|
60440
60549
|
growPopupFromAnchor(dialogEl, anchorElement, applyChange, {
|
|
60441
|
-
opened
|
|
60550
|
+
opened,
|
|
60551
|
+
grow
|
|
60442
60552
|
});
|
|
60443
60553
|
} : null;
|
|
60444
60554
|
|
|
@@ -62777,6 +62887,7 @@ const css$C = /* css */`@layer navi {
|
|
|
62777
62887
|
* popup meant to dock on a phone must not declare itself compact — see
|
|
62778
62888
|
* `maxWidth` below.
|
|
62779
62889
|
* @param {boolean} [props.sizeFromAnchor] - **Dialog-only**, same guard.
|
|
62890
|
+
* @param {"box"|"scene"} [props.grow] - **Dialog-only**, same guard.
|
|
62780
62891
|
* @param {string} [props.positionArea] - Forwarded as-is — `Dialog` and
|
|
62781
62892
|
* `Popover` have different own defaults (`"center"` vs. `"bottom"`),
|
|
62782
62893
|
* deliberately not homogenized here (each reads best for its own typical
|
|
@@ -62883,6 +62994,7 @@ const Popup = props => {
|
|
|
62883
62994
|
// in the dialog branch, so they never reach the popover element.
|
|
62884
62995
|
dockedOnSmallTouchScreen,
|
|
62885
62996
|
sizeFromAnchor,
|
|
62997
|
+
grow,
|
|
62886
62998
|
...rest
|
|
62887
62999
|
} = props;
|
|
62888
63000
|
const [mode] = useResolvedPopupMode(modeProp, maxWidth, {
|
|
@@ -62901,6 +63013,7 @@ const Popup = props => {
|
|
|
62901
63013
|
...rest,
|
|
62902
63014
|
dockedOnSmallTouchScreen: dockedOnSmallTouchScreen,
|
|
62903
63015
|
sizeFromAnchor: sizeFromAnchor,
|
|
63016
|
+
grow: grow,
|
|
62904
63017
|
maxWidth: maxWidth,
|
|
62905
63018
|
pointerInteractionOutsideEffect: pointerInteractionOutsideEffect,
|
|
62906
63019
|
backdrop: backdrop,
|
|
@@ -63360,19 +63473,26 @@ const PickerCustom = props => {
|
|
|
63360
63473
|
commitUIStateAsAnswer(controller, closeEvent);
|
|
63361
63474
|
}
|
|
63362
63475
|
}
|
|
63363
|
-
leaveExpanded({
|
|
63364
|
-
isBack: closeEvent.detail.isCancel
|
|
63365
|
-
});
|
|
63366
|
-
// Reset so the next opening re-evaluates screen size
|
|
63367
|
-
resetMode();
|
|
63368
63476
|
const confirmEvent = confirmEventRef.current;
|
|
63369
63477
|
confirmEventRef.current = null;
|
|
63370
63478
|
if (confirmEvent && !closeEvent.detail.isCancel) {
|
|
63371
63479
|
onConfirm?.(confirmEvent);
|
|
63372
63480
|
}
|
|
63373
|
-
//
|
|
63374
|
-
// picker's value as it ends up
|
|
63481
|
+
// After the value bookkeeping above — whoever listens reads the
|
|
63482
|
+
// picker's value as it ends up, committed or restored on a cancel —
|
|
63483
|
+
// and before leaveExpanded below, which is where the caller's
|
|
63484
|
+
// reaction runs for a Dialog too. A close that keeps goes back onto
|
|
63485
|
+
// the entry the popup was opened from while KEEPING the url as it
|
|
63486
|
+
// stands at that moment (see useNavState's leave()), so what onClose
|
|
63487
|
+
// spells into the address — a route param naming what was being
|
|
63488
|
+
// edited, cleared now that nothing is — has to be written before,
|
|
63489
|
+
// or the landing puts it back.
|
|
63375
63490
|
onClose?.(closeEvent);
|
|
63491
|
+
leaveExpanded({
|
|
63492
|
+
isBack: closeEvent.detail.isCancel
|
|
63493
|
+
});
|
|
63494
|
+
// Reset so the next opening re-evaluates screen size
|
|
63495
|
+
resetMode();
|
|
63376
63496
|
}
|
|
63377
63497
|
};
|
|
63378
63498
|
});
|
|
@@ -63766,6 +63886,7 @@ const PickerContentInsidePopup = props => {
|
|
|
63766
63886
|
// its own width once lifted. Dialog's own `sizeFromAnchor`.
|
|
63767
63887
|
dialogSizeFromAnchor,
|
|
63768
63888
|
animation,
|
|
63889
|
+
grow,
|
|
63769
63890
|
animationDuration,
|
|
63770
63891
|
// mode="callout": what the callout says about what it holds, and paints
|
|
63771
63892
|
// in its border and icon — "none" for a plain tooltip (see the callout
|
|
@@ -63844,6 +63965,7 @@ const PickerContentInsidePopup = props => {
|
|
|
63844
63965
|
expandY: isPopover ? undefined : dialogExpandY,
|
|
63845
63966
|
dockedOnSmallTouchScreen: isPopover ? undefined : dockedOnSmallTouchScreen,
|
|
63846
63967
|
sizeFromAnchor: isPopover ? undefined : dialogSizeFromAnchor,
|
|
63968
|
+
grow: isPopover ? undefined : grow,
|
|
63847
63969
|
children: jsx(PopupModeContext.Provider, {
|
|
63848
63970
|
value: mode,
|
|
63849
63971
|
children: children
|
|
@@ -72845,6 +72967,7 @@ const PickerFirstResolver = props => {
|
|
|
72845
72967
|
* mode?: "popover" | "dialog" | "callout",
|
|
72846
72968
|
* openOn?: "press" | "longpress" | "contextmenu" | string | string[],
|
|
72847
72969
|
* animation?: boolean | "auto" | "fading" | "scaling" | "sliding" | "growing" | `slide-from-${string}`,
|
|
72970
|
+
* grow?: "box" | "scene",
|
|
72848
72971
|
* animationDuration?: string,
|
|
72849
72972
|
* calloutStatus?: "info" | "warning" | "error" | "success" | "none",
|
|
72850
72973
|
* calloutIcon?: boolean,
|
|
@@ -73135,7 +73258,9 @@ const PickerFirstResolver = props => {
|
|
|
73135
73258
|
* the user validated: that is `action`. `closeEvent.detail.isCancel` tells a
|
|
73136
73259
|
* cancel (Escape, the back gesture) from a close that keeps. Fires after the
|
|
73137
73260
|
* picker's value has settled — committed, or restored on a cancel — so the
|
|
73138
|
-
* value read in here is the one the picker ends up holding
|
|
73261
|
+
* value read in here is the one the picker ends up holding, and before the
|
|
73262
|
+
* popup leaves the history entry it pushed, so a route param cleared in here
|
|
73263
|
+
* is part of the url a close that keeps carries back.
|
|
73139
73264
|
* @param {number|string} [rightSlotIconSize="inherit"] How big what sits in the
|
|
73140
73265
|
* right slot is drawn — the chevron, a `rightSlotIcon`, or the clear button's
|
|
73141
73266
|
* cross. "inherit" takes the picker's own font size.
|
|
@@ -73182,6 +73307,10 @@ const PickerFirstResolver = props => {
|
|
|
73182
73307
|
* the anchor, so nothing has to be named for it — `dialogSizeFromAnchor`
|
|
73183
73308
|
* for a card that must keep its width on the way, left out for a drawing
|
|
73184
73309
|
* that opens precisely to get bigger.
|
|
73310
|
+
* @param {"box"|"scene"} [grow="box"] Dialog's own, under `animation="growing"`:
|
|
73311
|
+
* `"box"` for a card that extends (its top stays, the box uncovers the rest),
|
|
73312
|
+
* `"scene"` for a thumbnail and the bigger view it is cut from (each picture
|
|
73313
|
+
* covers the box, cropped around its centre).
|
|
73185
73314
|
* @param {string} [animationDuration] The popup's own (`--popup-animation-duration`).
|
|
73186
73315
|
* @param {boolean} [dialogSizeFromAnchor] Dialog mode: the dialog is as wide
|
|
73187
73316
|
* as the trigger — its box as a floor (Dialog's own `sizeFromAnchor`) and
|