@jsenv/navi 0.29.74 → 0.29.76
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/jsenv_navi.js +406 -61
- package/dist/jsenv_navi.js.map +18 -14
- package/docs/AI_INSTRUCTIONS.md +11 -0
- package/docs/dialog_shape.md +223 -0
- package/docs/z_index.md +35 -9
- package/package.json +2 -2
package/dist/jsenv_navi.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { installImportMetaCssBuild, windowHeightSignal, windowWidthSignal, visualViewportHeightSignal, visualViewportWidthSignal, getAppHeight, getAppWidth, smallTouchScreenSignal } from "./jsenv_navi_side_effects.js";
|
|
6
6
|
export { coarsePointerSignal, disableVirtualKeyboardOverlay } from "./jsenv_navi_side_effects.js";
|
|
7
|
-
import { elementIsFocusable, createPubSub, dispatchInternalCustomEvent, dispatchCustomEvent, getVisuallyVisibleInfo, getFirstVisuallyVisibleAncestor, getElementSignature, findEvent, createValueEffect, findFocusDelegateTarget, findFocusable, allowWheelThrough, dispatchPublicCustomEvent, resolveCSSColor, ELEMENT_SIZE_CHANGE, findSelfOrAncestorFixedPosition, visibleRectEffect, pickPositionRelativeTo, getBorderSizes, getPaddingSizes, applyNewPosition, measureLongestVisualLineWidth, chainEvent, waitForPressHeld, suppressClickAfterGesture, startDragToTravel, markDragSource, startDragTo, createIterableWeakSet, createEventGroupLogger, getKeyboardEventDefaultAction, activeElementSignal, normalizeStyle, mergeOneStyle, getPositionedParent, mergeTwoStyles, normalizeStyles, resolveCSSSize, hasCSSSizeUnit, resolveOklchLightness, contrastColor, closestOpenableAncestor, isAncestorOpen, observeAncestorOpenState, getAncestorOpenType, clickIsSuppressed, scrollRoomTowards, parsePositionArea, snapToPixel, trapFocusInside, trapScrollInside, onAncestorReopen, createGroupTransitionController, getBorderRadius, preventIntermediateScrollbar, createOpacityTransition, watchWheelTravel, findBefore, findAfter, initFocusGroup,
|
|
7
|
+
import { elementIsFocusable, createPubSub, dispatchInternalCustomEvent, dispatchCustomEvent, getVisuallyVisibleInfo, getFirstVisuallyVisibleAncestor, getElementSignature, findEvent, createValueEffect, findFocusDelegateTarget, findFocusable, allowWheelThrough, dispatchPublicCustomEvent, resolveCSSColor, ELEMENT_SIZE_CHANGE, findSelfOrAncestorFixedPosition, visibleRectEffect, pickPositionRelativeTo, getBorderSizes, getPaddingSizes, applyNewPosition, measureLongestVisualLineWidth, chainEvent, waitForPressHeld, suppressClickAfterGesture, startDragToTravel, markDragSource, startDragTo, createIterableWeakSet, createEventGroupLogger, getKeyboardEventDefaultAction, activeElementSignal, normalizeStyle, mergeOneStyle, getPositionedParent, mergeTwoStyles, normalizeStyles, resolveCSSSize, hasCSSSizeUnit, resolveOklchLightness, contrastColor, closestOpenableAncestor, isAncestorOpen, observeAncestorOpenState, getAncestorOpenType, clickIsSuppressed, isTouchDrivenEvent, scrollIntoViewScoped, scrollRoomTowards, parsePositionArea, snapToPixel, trapFocusInside, trapScrollInside, onAncestorReopen, createGroupTransitionController, getBorderRadius, preventIntermediateScrollbar, createOpacityTransition, watchWheelTravel, findBefore, findAfter, initFocusGroup, getScrollContainer, canScroll, measureWidestChildRow, performTabNavigation, wheelGestureIsTakenFrom, releaseWheelGesture, claimWheelGesture, dragAfterIntent, stickyAsRelativeCoords, createDragToMoveGestureController, getDropTargetInfo, setStyles, useActiveElement, stringifyStyle as stringifyStyle$1 } from "@jsenv/dom";
|
|
8
8
|
export { clickIsSuppressed, contrastColor, findEvent, startDragTo } from "@jsenv/dom";
|
|
9
9
|
import { signal, computed, effect, batch, untracked, useSignal } from "@preact/signals";
|
|
10
10
|
import { createContext, isValidElement, h, Fragment, render, toChildArray, options, cloneElement } from "preact";
|
|
@@ -60,7 +60,9 @@ const css$12 = /* css */`
|
|
|
60
60
|
what the page positioned itself, which loses to DOM order otherwise
|
|
61
61
|
(a sticky part is written before what scrolls under it). Box applies
|
|
62
62
|
it by default, isolated, and lets a call site write auto back:
|
|
63
|
-
--box-header-z-index / --box-footer-z-index.
|
|
63
|
+
--box-header-z-index / --box-footer-z-index. <Box sticky> gets it from
|
|
64
|
+
the prop itself, for the same reason and with the same way out (an
|
|
65
|
+
explicit zIndex, "auto" included).
|
|
64
66
|
|
|
65
67
|
"While stuck" is the condition the name states, and it costs something
|
|
66
68
|
to ignore: a sticky part at rest is a block in the flow with nothing
|
|
@@ -16935,6 +16937,28 @@ const DIMENSION_PROPS = {
|
|
|
16935
16937
|
return { transform: `scaleZ(${value})` };
|
|
16936
16938
|
},
|
|
16937
16939
|
};
|
|
16940
|
+
const applyPositionSticky = applyToCssPropWhenTruthy(
|
|
16941
|
+
"position",
|
|
16942
|
+
"sticky",
|
|
16943
|
+
"static",
|
|
16944
|
+
);
|
|
16945
|
+
// A sticky box is one something scrolls under, which is what
|
|
16946
|
+
// --navi-z-index-sticky names; without it the box is a positioned element at
|
|
16947
|
+
// z-index: auto and loses to anything the page raised — a Group member holding
|
|
16948
|
+
// focus (2) is seen passing in front of a sticky submit bar. Like Box's own
|
|
16949
|
+
// header/footer, the band applies always and not only while stuck: a box
|
|
16950
|
+
// written by an app is the generic case, it cannot read its own stuck state
|
|
16951
|
+
// (see docs/z_index.md), and dropping to auto loses to a single
|
|
16952
|
+
// position: relative. An explicit zIndex (including zIndex="auto") wins.
|
|
16953
|
+
const stickyZIndex = (styleContext) => {
|
|
16954
|
+
if (
|
|
16955
|
+
styleContext.styles.zIndex !== undefined ||
|
|
16956
|
+
styleContext.remainingProps.zIndex !== undefined
|
|
16957
|
+
) {
|
|
16958
|
+
return null;
|
|
16959
|
+
}
|
|
16960
|
+
return { zIndex: "var(--navi-z-index-sticky)" };
|
|
16961
|
+
};
|
|
16938
16962
|
const POSITION_PROPS = {
|
|
16939
16963
|
// For row, selfAlignX uses auto margins for positioning
|
|
16940
16964
|
// NOTE: Auto margins only work effectively for positioning individual items.
|
|
@@ -17002,11 +17026,22 @@ const POSITION_PROPS = {
|
|
|
17002
17026
|
}
|
|
17003
17027
|
return undefined;
|
|
17004
17028
|
},
|
|
17005
|
-
position:
|
|
17029
|
+
position: (value, styleContext) => {
|
|
17030
|
+
if (value === "sticky") {
|
|
17031
|
+
return { position: "sticky", ...stickyZIndex(styleContext) };
|
|
17032
|
+
}
|
|
17033
|
+
return { position: value };
|
|
17034
|
+
},
|
|
17006
17035
|
absolute: applyToCssPropWhenTruthy("position", "absolute", "static"),
|
|
17007
17036
|
relative: applyToCssPropWhenTruthy("position", "relative", "static"),
|
|
17008
17037
|
fixed: applyToCssPropWhenTruthy("position", "fixed", "static"),
|
|
17009
|
-
sticky:
|
|
17038
|
+
sticky: (value, styleContext) => {
|
|
17039
|
+
const positionStyles = applyPositionSticky(value, styleContext);
|
|
17040
|
+
if (!value) {
|
|
17041
|
+
return positionStyles;
|
|
17042
|
+
}
|
|
17043
|
+
return { ...positionStyles, ...stickyZIndex(styleContext) };
|
|
17044
|
+
},
|
|
17010
17045
|
zIndex: PASS_THROUGH,
|
|
17011
17046
|
// Keeps the zIndex values used inside this box local to it — see
|
|
17012
17047
|
// docs/z_index.md: a z-index that opens no stacking context competes with
|
|
@@ -19345,10 +19380,48 @@ import.meta.css = [/* css */`
|
|
|
19345
19380
|
outline-offset: calc(-1 * var(--navi-focus-outline-width));
|
|
19346
19381
|
overflow: auto;
|
|
19347
19382
|
|
|
19383
|
+
/* The same reading as the header's corners above, on all four: a body
|
|
19384
|
+
follows the corners of the box it is drawn in — which is also what
|
|
19385
|
+
it clips its content to, the overflow just above. */
|
|
19386
|
+
border-top-left-radius: inherit;
|
|
19387
|
+
border-top-right-radius: inherit;
|
|
19388
|
+
border-bottom-right-radius: inherit;
|
|
19389
|
+
border-bottom-left-radius: inherit;
|
|
19390
|
+
|
|
19348
19391
|
&:focus-visible {
|
|
19349
19392
|
outline-style: solid;
|
|
19350
19393
|
}
|
|
19351
19394
|
}
|
|
19395
|
+
|
|
19396
|
+
/* A corner a header or a footer covers is not the body's to follow:
|
|
19397
|
+
what the body meets there is their flat separator line, not a curve,
|
|
19398
|
+
and a radius against it shows the box through the gap it opens. */
|
|
19399
|
+
> [data-header] ~ [data-body] {
|
|
19400
|
+
border-top-left-radius: 0;
|
|
19401
|
+
border-top-right-radius: 0;
|
|
19402
|
+
}
|
|
19403
|
+
> [data-body]:has(~ [data-footer]) {
|
|
19404
|
+
border-bottom-right-radius: 0;
|
|
19405
|
+
border-bottom-left-radius: 0;
|
|
19406
|
+
}
|
|
19407
|
+
|
|
19408
|
+
/* A body with no padding of its own holds content running edge to edge:
|
|
19409
|
+
whatever sits at one of its ends is drawn ON the corner the body just
|
|
19410
|
+
resolved, so a radius of its own there carves a notch out of it. The
|
|
19411
|
+
body already clips to that corner, which makes "none" the right radius
|
|
19412
|
+
for what lands on it — square, and the body draws the curve. The ask
|
|
19413
|
+
travels down as a corner claim (see group.jsx) so a navi control
|
|
19414
|
+
answers it wherever it sits inside. */
|
|
19415
|
+
> [data-body][data-body-flush] {
|
|
19416
|
+
> :first-child {
|
|
19417
|
+
--x-corner-top-left-radius: 0;
|
|
19418
|
+
--x-corner-top-right-radius: 0;
|
|
19419
|
+
}
|
|
19420
|
+
> :last-child {
|
|
19421
|
+
--x-corner-bottom-right-radius: 0;
|
|
19422
|
+
--x-corner-bottom-left-radius: 0;
|
|
19423
|
+
}
|
|
19424
|
+
}
|
|
19352
19425
|
}
|
|
19353
19426
|
}
|
|
19354
19427
|
|
|
@@ -19551,6 +19624,11 @@ const Box = props => {
|
|
|
19551
19624
|
}
|
|
19552
19625
|
if (body) {
|
|
19553
19626
|
rest["data-body"] = "";
|
|
19627
|
+
// Padding is what decides whether the content reaches the body's own
|
|
19628
|
+
// corners — see the corner claims in this file's CSS.
|
|
19629
|
+
if (!PADDING_PROP_NAMES.some(name => isNonZeroSpacing(rest[name]))) {
|
|
19630
|
+
rest["data-body-flush"] = "";
|
|
19631
|
+
}
|
|
19554
19632
|
}
|
|
19555
19633
|
const defaultDisplay = getDefaultDisplay(TagName);
|
|
19556
19634
|
// Read the parent flow early so we can use it when display="inherit" is requested.
|
|
@@ -20015,6 +20093,16 @@ const shouldInjectSeparatorBetween = (left, right) => {
|
|
|
20015
20093
|
}
|
|
20016
20094
|
return true;
|
|
20017
20095
|
};
|
|
20096
|
+
const PADDING_PROP_NAMES = ["padding", "paddingX", "paddingY", "paddingTop", "paddingRight", "paddingBottom", "paddingLeft"];
|
|
20097
|
+
const isNonZeroSpacing = value => {
|
|
20098
|
+
if (value === undefined || value === null || value === false) {
|
|
20099
|
+
return false;
|
|
20100
|
+
}
|
|
20101
|
+
if (value === 0 || value === "0" || value === "none") {
|
|
20102
|
+
return false;
|
|
20103
|
+
}
|
|
20104
|
+
return true;
|
|
20105
|
+
};
|
|
20018
20106
|
|
|
20019
20107
|
const useDebounceTrue = (value, delay = 300) => {
|
|
20020
20108
|
const [debouncedTrue, setDebouncedTrue] = useState(false);
|
|
@@ -28546,7 +28634,21 @@ const prepareFocusTransfer = (prepareEvent, debugFocus) => {
|
|
|
28546
28634
|
focusedElement,
|
|
28547
28635
|
focusVisible,
|
|
28548
28636
|
|
|
28549
|
-
|
|
28637
|
+
/**
|
|
28638
|
+
* Moves the focus into `containerEl`, on the element the ladder above
|
|
28639
|
+
* picks.
|
|
28640
|
+
*
|
|
28641
|
+
* `getDelay(target)` — asked once the target is known, answers how many
|
|
28642
|
+
* milliseconds to wait before actually focusing it. The ladder is what
|
|
28643
|
+
* decides WHO gets the focus and it may only run once (it consumes the
|
|
28644
|
+
* autofocus-restore mark), so a caller with a policy about WHEN cannot
|
|
28645
|
+
* resolve the target itself to make up its mind: it is handed the answer
|
|
28646
|
+
* instead. Returns a cancel function when it did delay, so a container
|
|
28647
|
+
* closing before the delay is up takes back a focus it never gave;
|
|
28648
|
+
* undefined when it focused straight away and there is nothing to take
|
|
28649
|
+
* back.
|
|
28650
|
+
*/
|
|
28651
|
+
transferFocus: (transferEvent, containerEl, { getDelay } = {}) => {
|
|
28550
28652
|
let target;
|
|
28551
28653
|
let reason;
|
|
28552
28654
|
const lastFocused = clearAutofocusRestore(containerEl);
|
|
@@ -28574,24 +28676,39 @@ const prepareFocusTransfer = (prepareEvent, debugFocus) => {
|
|
|
28574
28676
|
}
|
|
28575
28677
|
}
|
|
28576
28678
|
if (!target) {
|
|
28577
|
-
return;
|
|
28679
|
+
return undefined;
|
|
28578
28680
|
}
|
|
28579
28681
|
// The modality speaks for the transfer, but an editable target outranks
|
|
28580
28682
|
// it: it draws its ring on any focus (see isMatchingFocusVisible), so
|
|
28581
28683
|
// the native :focus-visible is told the same.
|
|
28582
28684
|
const targetFocusVisible = focusVisible || isEditableTarget(target);
|
|
28685
|
+
const giveFocus = () => {
|
|
28686
|
+
debugFocus(
|
|
28687
|
+
transferEvent,
|
|
28688
|
+
`Moving focus to ${getElementSignature(target)}.focus({ preventScroll: true, focusVisible: ${targetFocusVisible} }) (reason: ${reason})`,
|
|
28689
|
+
);
|
|
28690
|
+
target.focus({
|
|
28691
|
+
preventScroll: true,
|
|
28692
|
+
focusVisible: targetFocusVisible,
|
|
28693
|
+
});
|
|
28694
|
+
if (target.hasAttribute("navi-autofocus-select")) {
|
|
28695
|
+
target.select();
|
|
28696
|
+
target.scrollLeft = 0;
|
|
28697
|
+
}
|
|
28698
|
+
};
|
|
28699
|
+
const delay = getDelay?.(target) || 0;
|
|
28700
|
+
if (!delay) {
|
|
28701
|
+
giveFocus();
|
|
28702
|
+
return undefined;
|
|
28703
|
+
}
|
|
28583
28704
|
debugFocus(
|
|
28584
28705
|
transferEvent,
|
|
28585
|
-
`
|
|
28706
|
+
`Delaying focus to ${getElementSignature(target)} by ${delay}ms`,
|
|
28586
28707
|
);
|
|
28587
|
-
|
|
28588
|
-
|
|
28589
|
-
|
|
28590
|
-
}
|
|
28591
|
-
if (target.hasAttribute("navi-autofocus-select")) {
|
|
28592
|
-
target.select();
|
|
28593
|
-
target.scrollLeft = 0;
|
|
28594
|
-
}
|
|
28708
|
+
const timeout = setTimeout(giveFocus, delay);
|
|
28709
|
+
return () => {
|
|
28710
|
+
clearTimeout(timeout);
|
|
28711
|
+
};
|
|
28595
28712
|
},
|
|
28596
28713
|
|
|
28597
28714
|
restoreFocus: (restoreEvent) => {
|
|
@@ -28633,6 +28750,21 @@ const getFocusedBeforeTransfer = (e) => {
|
|
|
28633
28750
|
return document.activeElement;
|
|
28634
28751
|
};
|
|
28635
28752
|
|
|
28753
|
+
// How long a popup waits before handing the focus to a field, when giving it
|
|
28754
|
+
// is what raises the on-screen keyboard.
|
|
28755
|
+
//
|
|
28756
|
+
// The focus is normally given as early as possible. But a popup places itself
|
|
28757
|
+
// against the viewport, and on a phone the keyboard takes a third of that
|
|
28758
|
+
// viewport away the moment a field receives focus — so the two landing in the
|
|
28759
|
+
// same tick means the popup is still arriving when the room under it changes,
|
|
28760
|
+
// and it re-places itself mid-entrance. Waiting lets it settle first, and the
|
|
28761
|
+
// keyboard then shrinks a box that has stopped moving.
|
|
28762
|
+
//
|
|
28763
|
+
// Long enough to outlast an entrance transition rather than merely reaching
|
|
28764
|
+
// the next frame: what has to be over is the popup MOVING, not one paint of
|
|
28765
|
+
// it.
|
|
28766
|
+
const FOCUS_DELAY_ON_KEYBOARD_MS = 250;
|
|
28767
|
+
|
|
28636
28768
|
/**
|
|
28637
28769
|
* Owns open/close decision-making for a popup (Dialog or Popover): guards
|
|
28638
28770
|
* against duplicate requests and notifies the popup owner's own reactions.
|
|
@@ -28871,8 +29003,32 @@ const createOpenController = (
|
|
|
28871
29003
|
// once mousedown.preventDefault() has kept focus from landing
|
|
28872
29004
|
// anywhere yet.
|
|
28873
29005
|
|
|
28874
|
-
|
|
29006
|
+
// Two conditions, and both are about THIS opening rather than about
|
|
29007
|
+
// the device:
|
|
29008
|
+
// - the interaction: only a finger raises a virtual keyboard, and a
|
|
29009
|
+
// hybrid tablet answers "coarse" to every device-level signal
|
|
29010
|
+
// whichever of its two inputs was just used — the open event still
|
|
29011
|
+
// remembers which one it was. An opening with no pointer in it at
|
|
29012
|
+
// all (a keyboard shortcut, defaultOpen, an app calling open()) is
|
|
29013
|
+
// not one either.
|
|
29014
|
+
// - the target: focusing a button raises nothing, so there is nothing
|
|
29015
|
+
// to wait for and the focus stays immediate. Only a field the
|
|
29016
|
+
// keyboard comes up for is worth delaying — which is why the
|
|
29017
|
+
// decision is taken on the resolved target, inside transferFocus.
|
|
29018
|
+
const openedByTouch = Boolean(
|
|
29019
|
+
findEvent(requestOpenEvent, isTouchDrivenEvent),
|
|
29020
|
+
);
|
|
29021
|
+
const cancelPendingFocus = focusTransfer.transferFocus(e, el, {
|
|
29022
|
+
getDelay: (target) =>
|
|
29023
|
+
openedByTouch && isEditableTarget(target)
|
|
29024
|
+
? FOCUS_DELAY_ON_KEYBOARD_MS
|
|
29025
|
+
: 0,
|
|
29026
|
+
});
|
|
28875
29027
|
return (closeEvent) => {
|
|
29028
|
+
// Closed before the delay was up: the focus was never given, so it
|
|
29029
|
+
// must not be given now — to a field inside a popup on its way out,
|
|
29030
|
+
// raising the keyboard as it goes.
|
|
29031
|
+
cancelPendingFocus?.();
|
|
28876
29032
|
markAutofocusRestoreOnClose(el, closeEvent, focusedAtClose);
|
|
28877
29033
|
const focusoutEvent = findEvent(closeEvent, "focusout");
|
|
28878
29034
|
if (focusoutEvent) {
|
|
@@ -29141,6 +29297,60 @@ const flushSyncRendering = (fn) => {
|
|
|
29141
29297
|
*/
|
|
29142
29298
|
|
|
29143
29299
|
|
|
29300
|
+
/**
|
|
29301
|
+
* Whether a visibleRectEffect delivery is one that can have taken height away
|
|
29302
|
+
* from a popup, and so pushed whatever holds focus out of sight:
|
|
29303
|
+
* - "resize": the window/visual viewport settled — which is also how the
|
|
29304
|
+
* on-screen keyboard arrives, overlay or not (window_size.js);
|
|
29305
|
+
* - ELEMENT_SIZE_CHANGE: the popup's own box measured different;
|
|
29306
|
+
* - "focusin": the focus-settled re-measure, for the room that changes with
|
|
29307
|
+
* nothing announcing it (subscribeFocusSettled in window_size.js).
|
|
29308
|
+
*
|
|
29309
|
+
* Everything else is a scroll of one kind or another, where nothing got
|
|
29310
|
+
* smaller and scrolling the focused element back would fight the very gesture
|
|
29311
|
+
* that fired it.
|
|
29312
|
+
*/
|
|
29313
|
+
const mayHaveHiddenFocus = (event) => {
|
|
29314
|
+
const type = event?.type;
|
|
29315
|
+
return (
|
|
29316
|
+
type === "resize" || type === ELEMENT_SIZE_CHANGE || type === "focusin"
|
|
29317
|
+
);
|
|
29318
|
+
};
|
|
29319
|
+
|
|
29320
|
+
/**
|
|
29321
|
+
* Scrolls whatever holds focus inside `popupEl` back into view, if the popup
|
|
29322
|
+
* getting shorter has pushed it out.
|
|
29323
|
+
*
|
|
29324
|
+
* The case this exists for: a field low in the scrolling body of a popup that
|
|
29325
|
+
* also has a footer (box.jsx — with a body, the body is the only thing that
|
|
29326
|
+
* scrolls and the footer is a sibling sitting right under it). Focusing the
|
|
29327
|
+
* field makes the browser scroll it into view, which it does against the
|
|
29328
|
+
* popup's height AT THAT MOMENT; the on-screen keyboard then opens and takes
|
|
29329
|
+
* that height away. The body shrinks, its scrollTop does not move, so the
|
|
29330
|
+
* content slides down relative to the shorter scrollport and the field ends up
|
|
29331
|
+
* past its bottom edge — visually, swallowed by the footer. The browser does
|
|
29332
|
+
* not redo a scroll-into-view it already answered, so this does.
|
|
29333
|
+
*
|
|
29334
|
+
* Scoped to the field's own scroll container (never the page): a popup traps
|
|
29335
|
+
* scrolling precisely so the document underneath cannot move, and a plain
|
|
29336
|
+
* scrollIntoView walks past a container whose scrollbar isn't visible — see
|
|
29337
|
+
* scrollIntoViewScoped's own doc.
|
|
29338
|
+
*
|
|
29339
|
+
* "nearest": the smallest scroll that makes it visible, and none at all when
|
|
29340
|
+
* it already is — so this is free to call on every resize, and never fights
|
|
29341
|
+
* where the user had scrolled to.
|
|
29342
|
+
*/
|
|
29343
|
+
const keepFocusedElementVisible = (popupEl) => {
|
|
29344
|
+
const { activeElement } = document;
|
|
29345
|
+
if (!activeElement || activeElement === popupEl) {
|
|
29346
|
+
return;
|
|
29347
|
+
}
|
|
29348
|
+
if (!popupEl.contains(activeElement)) {
|
|
29349
|
+
return;
|
|
29350
|
+
}
|
|
29351
|
+
scrollIntoViewScoped(activeElement, { block: "nearest" });
|
|
29352
|
+
};
|
|
29353
|
+
|
|
29144
29354
|
/**
|
|
29145
29355
|
* Calls `onSettled` once `el`'s current CSS transition is over — via
|
|
29146
29356
|
* `transitionend`, with a safety `setTimeout` fallback matching the longest
|
|
@@ -30044,6 +30254,24 @@ const css$X = /* css */`
|
|
|
30044
30254
|
outline-color: var(--dialog-outline-color);
|
|
30045
30255
|
outline-offset: 0;
|
|
30046
30256
|
box-shadow: var(--dialog-box-shadow);
|
|
30257
|
+
|
|
30258
|
+
/* Docking answers a different question than --dialog-max-width: a sheet
|
|
30259
|
+
spans its container's full width, flush against the two side edges —
|
|
30260
|
+
that shape IS the mode — while the caller's ceiling was an answer about
|
|
30261
|
+
the *centered* box ("do not sprawl on a wide window"). Applying it here
|
|
30262
|
+
turns the sheet into a small floating box that no longer touches the
|
|
30263
|
+
edges it was docked to, so it is dropped out of the clamp entirely; the
|
|
30264
|
+
container ceiling still holds. --dialog-min-width needs no such rule:
|
|
30265
|
+
the floor is below the full width a docked dialog takes, so it stops
|
|
30266
|
+
mattering on its own. Height is untouched — a sheet is content-tall, not
|
|
30267
|
+
container-tall (expandY cancels docking outright), so --dialog-max-height
|
|
30268
|
+
still means what it meant. */
|
|
30269
|
+
&[data-docked] {
|
|
30270
|
+
--x-dialog-max-width: min(
|
|
30271
|
+
var(--container-position-remaining-width, var(--dialog-maxmax-width)),
|
|
30272
|
+
var(--dialog-maxmax-width)
|
|
30273
|
+
);
|
|
30274
|
+
}
|
|
30047
30275
|
/* The clamped max, not --dialog-maxmax-*: that one is the viewport minus
|
|
30048
30276
|
the spacing, which is only the real ceiling for layer="top". A local
|
|
30049
30277
|
dialog is confined to its positioned ancestor, whose size reaches here
|
|
@@ -30284,7 +30512,15 @@ const css$X = /* css */`
|
|
|
30284
30512
|
* from where the finger just tapped, and size alone would dock a narrow
|
|
30285
30513
|
* desktop window, which is still a mouse. It supplies defaults for
|
|
30286
30514
|
* `positionArea`, `marginWithContainer`, `expandX` and `scrollCapture`, so
|
|
30287
|
-
* any of them can still be pinned explicitly
|
|
30515
|
+
* any of them can still be pinned explicitly — including `expandX={false}`,
|
|
30516
|
+
* which opts the docked dialog out of the full-width stretch and leaves it a
|
|
30517
|
+
* floating box at the bottom. It also withdraws `maxWidth` while docked: a
|
|
30518
|
+
* sheet is container-wide by definition, and a `maxWidth` is an answer about
|
|
30519
|
+
* the *centered* shape, so the two can be stated together (`maxWidth="16rem"
|
|
30520
|
+
* dockedOnSmallTouchScreen`) and each applies where it means something.
|
|
30521
|
+
* `minWidth` needs no such rule — its floor is below the full width — and
|
|
30522
|
+
* `maxHeight`/`minHeight` keep applying, a sheet being content-tall.
|
|
30523
|
+
* Ignored entirely when `expandY`
|
|
30288
30524
|
* (or `expand`) is set: a dialog already filling the height is on the bottom
|
|
30289
30525
|
* edge docking would bring it to, so docking could only take away the shape
|
|
30290
30526
|
* the caller asked for. Re-resolves live as the pointer
|
|
@@ -30306,7 +30542,10 @@ const css$X = /* css */`
|
|
|
30306
30542
|
* @param {boolean} [props.expand] - Shorthand for both `expandX` and `expandY`.
|
|
30307
30543
|
* @param {boolean} [props.expandX] - Stretches the dialog to the full width its
|
|
30308
30544
|
* container allows (`--dialog-maxmax-width`). Set by
|
|
30309
|
-
* `dockedOnSmallTouchScreen` on a small touch screen
|
|
30545
|
+
* `dockedOnSmallTouchScreen` on a small touch screen — so passing `false`
|
|
30546
|
+
* here also opts out of *that* stretch, leaving a docked dialog a floating
|
|
30547
|
+
* box instead of a flush sheet. To keep the sheet flush and merely cap the
|
|
30548
|
+
* centered shape, use `maxWidth`: docking withdraws it on its own.
|
|
30310
30549
|
* @param {boolean} [props.expandY] - Same, vertically
|
|
30311
30550
|
* (`--dialog-maxmax-height`). Cancels `dockedOnSmallTouchScreen`.
|
|
30312
30551
|
* @param {string|number} [props.marginWithContainer="3appw"] - Minimum gap kept
|
|
@@ -30365,7 +30604,9 @@ const css$X = /* css */`
|
|
|
30365
30604
|
* so it can never push the dialog past `--dialog-maxmax-width` (the
|
|
30366
30605
|
* viewport/container-spacing ceiling) regardless of how large a value is
|
|
30367
30606
|
* passed.
|
|
30368
|
-
* @param {string} [props.maxWidth] - Maps to `--dialog-max-width`.
|
|
30607
|
+
* @param {string} [props.maxWidth] - Maps to `--dialog-max-width`. Describes
|
|
30608
|
+
* the centered shape only: a dialog docked by `dockedOnSmallTouchScreen`
|
|
30609
|
+
* ignores it and stays container-wide.
|
|
30369
30610
|
* @param {string} [props.minHeight] - Maps to `--dialog-min-height`, same
|
|
30370
30611
|
* clamping as `minWidth`.
|
|
30371
30612
|
* @param {string} [props.maxHeight] - Maps to `--dialog-max-height`.
|
|
@@ -30990,6 +31231,11 @@ const useDialogProps = props => {
|
|
|
30990
31231
|
// handled generically by applyNewPosition itself (dispatches
|
|
30991
31232
|
// navi_position_change on every call) — nothing to do here.
|
|
30992
31233
|
};
|
|
31234
|
+
// Cleared here rather than on close, where the box is deliberately left
|
|
31235
|
+
// frozen at the size it was closing at (see the closing function's own
|
|
31236
|
+
// comment): this opening has its own content to be measured against, and
|
|
31237
|
+
// measuring it inside last time's box would answer with last time's size.
|
|
31238
|
+
unfreezeSize(dialogEl);
|
|
30993
31239
|
positionDialog();
|
|
30994
31240
|
if (sizing === "frozen") {
|
|
30995
31241
|
// After positionDialog: the caps it writes
|
|
@@ -31012,6 +31258,12 @@ const useDialogProps = props => {
|
|
|
31012
31258
|
event
|
|
31013
31259
|
}) => {
|
|
31014
31260
|
positionDialog(event);
|
|
31261
|
+
// Only for what can have taken height away from the dialog — a
|
|
31262
|
+
// scroll never does, and re-scrolling on one would fight the finger
|
|
31263
|
+
// that caused it. See keepFocusedElementVisible's own doc.
|
|
31264
|
+
if (mayHaveHiddenFocus(event)) {
|
|
31265
|
+
keepFocusedElementVisible(dialogEl);
|
|
31266
|
+
}
|
|
31015
31267
|
}, {
|
|
31016
31268
|
event: e,
|
|
31017
31269
|
skipElementResize: true
|
|
@@ -31064,6 +31316,12 @@ const useDialogProps = props => {
|
|
|
31064
31316
|
}
|
|
31065
31317
|
const hasCssTransitionAnimation = Boolean(resolvedAnimation);
|
|
31066
31318
|
const cancelOpenInteractionSuppression = !silent && hasCssTransitionAnimation ? suppressPointerEventsDuringTransition(dialogEl) : null;
|
|
31319
|
+
// Handing the focus to a field is what raises the on-screen keyboard, and
|
|
31320
|
+
// the keyboard takes away the very room this dialog was just placed
|
|
31321
|
+
// against — so on a touch-driven opening the transfer waits for the
|
|
31322
|
+
// entrance to be over. Decided by transferFocusOnOpen, the only place that
|
|
31323
|
+
// knows WHICH element is about to be focused (open_controller.js and its
|
|
31324
|
+
// FOCUS_DELAY_ON_KEYBOARD_MS).
|
|
31067
31325
|
const restoreFocus = openController.transferFocusOnOpen(dialogEl);
|
|
31068
31326
|
|
|
31069
31327
|
// isModal outside-click detection (see this file's top comment for why
|
|
@@ -31129,9 +31387,16 @@ const useDialogProps = props => {
|
|
|
31129
31387
|
// property is actually present — harmless the rest of the time.
|
|
31130
31388
|
dialogEl.setAttribute("navi-hidden", "");
|
|
31131
31389
|
dialogEl.close();
|
|
31132
|
-
//
|
|
31133
|
-
//
|
|
31134
|
-
|
|
31390
|
+
// Held at the size it has right now, for the whole way out. cleanup()
|
|
31391
|
+
// below already stops the JS repositioning, but the size is CSS-driven
|
|
31392
|
+
// (--x-dialog-max-height, and `height` outright under expandY) and
|
|
31393
|
+
// keeps following the visual viewport on its own — so a dialog closed
|
|
31394
|
+
// while the keyboard is up grows back to fill the room the keyboard is
|
|
31395
|
+
// giving back, WHILE fading out. Coherent, and still wrong to watch: a
|
|
31396
|
+
// box being dismissed has nothing left to adapt to, and the growth
|
|
31397
|
+
// reads as something happening at the exact moment nothing should. The
|
|
31398
|
+
// next opening clears it (see openEffect's own unfreezeSize).
|
|
31399
|
+
freezeSize(dialogEl);
|
|
31135
31400
|
cancelOpenInteractionSuppression?.();
|
|
31136
31401
|
if (hasCssTransitionAnimation) {
|
|
31137
31402
|
suppressPointerEventsDuringTransition(dialogEl);
|
|
@@ -31259,6 +31524,10 @@ const useDialogProps = props => {
|
|
|
31259
31524
|
// scrolling area, so it says so once, here.
|
|
31260
31525
|
"overflow": "auto",
|
|
31261
31526
|
"data-layer": layer,
|
|
31527
|
+
// The sheet shape is live in CSS, not just a set of resolved defaults:
|
|
31528
|
+
// it is what withdraws the caller's --dialog-max-width (see the stylesheet
|
|
31529
|
+
// above), which is an answer about the centered box only.
|
|
31530
|
+
"data-docked": isDocked ? "" : undefined,
|
|
31262
31531
|
"data-expand-x": expandX ? "" : undefined,
|
|
31263
31532
|
"data-expand-y": expandY ? "" : undefined,
|
|
31264
31533
|
"data-flush-top": flushEdges.top ? "" : undefined,
|
|
@@ -32443,6 +32712,12 @@ const usePopoverProps = props => {
|
|
|
32443
32712
|
}
|
|
32444
32713
|
popoverEl.removeAttribute("data-anchor-out-of-view");
|
|
32445
32714
|
positionPopover(event);
|
|
32715
|
+
// Same as Dialog's own — a popup with a scrolling body and a footer
|
|
32716
|
+
// swallows the field it just got shorter around. See
|
|
32717
|
+
// keepFocusedElementVisible's own doc in popup_shared.js.
|
|
32718
|
+
if (mayHaveHiddenFocus(event)) {
|
|
32719
|
+
keepFocusedElementVisible(popoverEl);
|
|
32720
|
+
}
|
|
32446
32721
|
}, {
|
|
32447
32722
|
event: e,
|
|
32448
32723
|
// it's ok for the popover to become unsync with the anchor size
|
|
@@ -38830,24 +39105,34 @@ const ROUTE_TRAVEL_ATTRIBUTE = "data-navi-route-travel";
|
|
|
38830
39105
|
// included).
|
|
38831
39106
|
|
|
38832
39107
|
const css$T = /* css */`
|
|
38833
|
-
/* The marked region is a picture of its own
|
|
38834
|
-
|
|
38835
|
-
|
|
38836
|
-
|
|
39108
|
+
/* The marked region is a picture of its own for the length of a transition of
|
|
39109
|
+
OURS, and only then — the name is what makes the pages a picture the
|
|
39110
|
+
movement below can carry.
|
|
39111
|
+
|
|
39112
|
+
Named outside that, it would be a picture during every view transition the
|
|
39113
|
+
APPLICATION starts — two rows swapping, a list changing — and a page is
|
|
39114
|
+
several screens tall: its picture is the whole element, drawn in the top
|
|
39115
|
+
layer from wherever the element starts, so it paints over the fixed bars
|
|
39116
|
+
and past the bottom of the screen for the length of a movement that has
|
|
39117
|
+
nothing to do with the pages. Unnamed, it stays part of the document's own
|
|
39118
|
+
picture, where the browser cuts it at the viewport like everything else. */
|
|
39119
|
+
:root[data-navi-route-transition] [data-navi-route-transition-area] {
|
|
38837
39120
|
view-transition-name: navi-route-transition;
|
|
38838
39121
|
}
|
|
38839
39122
|
|
|
38840
|
-
/* A named descendant — a
|
|
38841
|
-
|
|
38842
|
-
|
|
38843
|
-
pages
|
|
38844
|
-
|
|
38845
|
-
|
|
38846
|
-
|
|
38847
|
-
|
|
39123
|
+
/* A named descendant — a thumbnail named for a morph, a row named for a
|
|
39124
|
+
reorder gesture — is a hole in the area's picture and a group of its own.
|
|
39125
|
+
Nested groups keep that group inside the area's, which is what cuts it at
|
|
39126
|
+
the pages' edge instead of letting it paint across the screen. What it does
|
|
39127
|
+
NOT do is make it travel: the movement is carried by the area's two
|
|
39128
|
+
pictures, and a group is not one of them, so a named descendant stands
|
|
39129
|
+
where it was captured while the pages slide under it. A morph wants exactly
|
|
39130
|
+
that; a component that names its parts for changes of its own does not, and
|
|
39131
|
+
drops its names for the length of the movement (see list.jsx). A browser
|
|
39132
|
+
without nested groups is warned instead (see
|
|
38848
39133
|
warnAboutNamesEscapingArea). */
|
|
38849
39134
|
@supports (view-transition-group: contain) {
|
|
38850
|
-
[data-navi-route-transition-area] {
|
|
39135
|
+
:root[data-navi-route-transition] [data-navi-route-transition-area] {
|
|
38851
39136
|
view-transition-group: contain;
|
|
38852
39137
|
}
|
|
38853
39138
|
}
|
|
@@ -45736,9 +46021,12 @@ installImportMetaCssBuild(import.meta);/**
|
|
|
45736
46021
|
* along the bar it adds to the padding asked for. Note that every
|
|
45737
46022
|
* `env(safe-area-inset-*)` is 0 unless the page asks for it:
|
|
45738
46023
|
* `<meta name="viewport" content="…, viewport-fit=cover">`.
|
|
45739
|
-
* 4. **Its hairline is
|
|
45740
|
-
*
|
|
45741
|
-
*
|
|
46024
|
+
* 4. **Its hairline is part of its box.** The line covers the content just as
|
|
46025
|
+
* the bar does, so the room given back has to include it — a line drawn
|
|
46026
|
+
* outside the box (a box-shadow, an outline) is a line the content scrolls
|
|
46027
|
+
* under, and a line a page transition paints over. It is a real border,
|
|
46028
|
+
* added to the size asked for exactly like the notch inset is, so the
|
|
46029
|
+
* content still gets the size the prop names.
|
|
45742
46030
|
*/
|
|
45743
46031
|
const css$M = /* css */`
|
|
45744
46032
|
@layer navi {
|
|
@@ -45798,39 +46086,50 @@ const css$M = /* css */`
|
|
|
45798
46086
|
}
|
|
45799
46087
|
|
|
45800
46088
|
/* Across the bar, the inset of the edge it is pinned to is padding AND is
|
|
45801
|
-
added to the size
|
|
45802
|
-
|
|
46089
|
+
added to the size, and the hairline on the content side is added the
|
|
46090
|
+
same way: the background then runs under the notch, the line stands
|
|
46091
|
+
clear of the content, and the content keeps the whole width/height asked
|
|
46092
|
+
for. */
|
|
45803
46093
|
&[data-area="top"] {
|
|
45804
46094
|
top: var(--navi-app-inset-top);
|
|
45805
|
-
height: calc(
|
|
46095
|
+
height: calc(
|
|
46096
|
+
var(--navi-fixed-bar-height) + env(safe-area-inset-top) +
|
|
46097
|
+
var(--navi-fixed-bar-border-width)
|
|
46098
|
+
);
|
|
45806
46099
|
padding-top: env(safe-area-inset-top);
|
|
45807
|
-
|
|
46100
|
+
border-bottom: var(--navi-fixed-bar-border-width) solid
|
|
45808
46101
|
var(--navi-fixed-bar-border-color);
|
|
45809
46102
|
}
|
|
45810
46103
|
&[data-area="bottom"] {
|
|
45811
46104
|
bottom: var(--navi-app-inset-bottom);
|
|
45812
|
-
height: calc(
|
|
46105
|
+
height: calc(
|
|
46106
|
+
var(--navi-fixed-bar-height) + env(safe-area-inset-bottom) +
|
|
46107
|
+
var(--navi-fixed-bar-border-width)
|
|
46108
|
+
);
|
|
45813
46109
|
padding-bottom: env(safe-area-inset-bottom);
|
|
45814
|
-
|
|
46110
|
+
border-top: var(--navi-fixed-bar-border-width) solid
|
|
45815
46111
|
var(--navi-fixed-bar-border-color);
|
|
45816
46112
|
}
|
|
45817
46113
|
&[data-area="left"] {
|
|
45818
46114
|
left: var(--navi-app-inset-left);
|
|
45819
|
-
width: calc(
|
|
46115
|
+
width: calc(
|
|
46116
|
+
var(--navi-fixed-bar-width) + env(safe-area-inset-left) +
|
|
46117
|
+
var(--navi-fixed-bar-border-width)
|
|
46118
|
+
);
|
|
45820
46119
|
padding-left: env(safe-area-inset-left);
|
|
45821
|
-
|
|
46120
|
+
border-right: var(--navi-fixed-bar-border-width) solid
|
|
45822
46121
|
var(--navi-fixed-bar-border-color);
|
|
45823
46122
|
}
|
|
45824
46123
|
&[data-area="right"] {
|
|
45825
46124
|
right: var(--navi-app-inset-right);
|
|
45826
|
-
width: calc(
|
|
46125
|
+
width: calc(
|
|
46126
|
+
var(--navi-fixed-bar-width) + env(safe-area-inset-right) +
|
|
46127
|
+
var(--navi-fixed-bar-border-width)
|
|
46128
|
+
);
|
|
45827
46129
|
padding-right: env(safe-area-inset-right);
|
|
45828
|
-
|
|
46130
|
+
border-left: var(--navi-fixed-bar-border-width) solid
|
|
45829
46131
|
var(--navi-fixed-bar-border-color);
|
|
45830
46132
|
}
|
|
45831
|
-
&[data-border="none"] {
|
|
45832
|
-
box-shadow: none;
|
|
45833
|
-
}
|
|
45834
46133
|
}
|
|
45835
46134
|
`;
|
|
45836
46135
|
const FixedBarStyleCSSVars = {
|
|
@@ -45864,9 +46163,10 @@ const FixedBarStyleCSSVars = {
|
|
|
45864
46163
|
* @param {string|number} [props.width] - …and for one on a side. The safe-area
|
|
45865
46164
|
* inset is NOT part of it: it is added on top, so the content keeps the size
|
|
45866
46165
|
* asked for.
|
|
45867
|
-
* @param {boolean} [props.border=true] - The hairline on the content side.
|
|
45868
|
-
*
|
|
45869
|
-
* `borderWidth`/`borderColor`, or
|
|
46166
|
+
* @param {boolean} [props.border=true] - The hairline on the content side. It
|
|
46167
|
+
* is added to the size rather than taken out of it, and counts in the room
|
|
46168
|
+
* the bar gives back; give it a `borderWidth`/`borderColor`, or
|
|
46169
|
+
* `border={false}` for none.
|
|
45870
46170
|
* @param {string|number} [props.maxWidth] - Keeps the bar lined up with a
|
|
45871
46171
|
* content column narrower than the window (it stays centered).
|
|
45872
46172
|
*/
|
|
@@ -45879,9 +46179,16 @@ const FixedBar = ({
|
|
|
45879
46179
|
import.meta.css = [css$M, "@jsenv/navi/src/layout/fixed_bar/fixed_bar.jsx"];
|
|
45880
46180
|
const defaultRef = useRef();
|
|
45881
46181
|
props.ref = props.ref || defaultRef;
|
|
46182
|
+
// Said with the width the border rule reads rather than with an attribute of
|
|
46183
|
+
// its own: the width is what the size calc adds, so a line asked away here
|
|
46184
|
+
// is a line that takes no room either.
|
|
46185
|
+
if (!border) {
|
|
46186
|
+
props.borderWidth = "0px";
|
|
46187
|
+
}
|
|
45882
46188
|
// Whichever of width/height crosses the edge the bar sits on is what the
|
|
45883
46189
|
// content has to be given back — and the bar's border box already IS that:
|
|
45884
|
-
// the size it was given
|
|
46190
|
+
// the size it was given, the inset of that edge, and the hairline standing
|
|
46191
|
+
// between it and the content. Measured rather than
|
|
45885
46192
|
// rebuilt as a calc() expression, so a size coming from anywhere — a prop, a
|
|
45886
46193
|
// theme variable, the content itself — is reserved just the same, and each
|
|
45887
46194
|
// `env()` inset stays the browser's business alone.
|
|
@@ -45928,7 +46235,6 @@ const FixedBar = ({
|
|
|
45928
46235
|
return jsx(Box, {
|
|
45929
46236
|
baseClassName: "navi_fixed_bar",
|
|
45930
46237
|
"data-area": area,
|
|
45931
|
-
"data-border": border ? undefined : "none",
|
|
45932
46238
|
...props,
|
|
45933
46239
|
styleCSSVars: FixedBarStyleCSSVars,
|
|
45934
46240
|
children: children
|
|
@@ -57051,7 +57357,26 @@ const css$w = /* css */`
|
|
|
57051
57357
|
flex-direction: column;
|
|
57052
57358
|
background-color: var(--x-list-background-color);
|
|
57053
57359
|
border: var(--x-list-border-width) solid var(--x-list-border-color);
|
|
57054
|
-
|
|
57360
|
+
/* Squared from the outside, corner by corner: whoever draws the surface
|
|
57361
|
+
the list is laid on says which corners are the list's to draw (a popup's
|
|
57362
|
+
body does, see box.jsx), and each corner falls back to the list's own
|
|
57363
|
+
radius when nothing asks for anything. */
|
|
57364
|
+
border-top-left-radius: var(
|
|
57365
|
+
--x-corner-top-left-radius,
|
|
57366
|
+
var(--x-list-border-radius)
|
|
57367
|
+
);
|
|
57368
|
+
border-top-right-radius: var(
|
|
57369
|
+
--x-corner-top-right-radius,
|
|
57370
|
+
var(--x-list-border-radius)
|
|
57371
|
+
);
|
|
57372
|
+
border-bottom-right-radius: var(
|
|
57373
|
+
--x-corner-bottom-right-radius,
|
|
57374
|
+
var(--x-list-border-radius)
|
|
57375
|
+
);
|
|
57376
|
+
border-bottom-left-radius: var(
|
|
57377
|
+
--x-corner-bottom-left-radius,
|
|
57378
|
+
var(--x-list-border-radius)
|
|
57379
|
+
);
|
|
57055
57380
|
|
|
57056
57381
|
transition: opacity 0.2s ease;
|
|
57057
57382
|
/* overflow:hidden is required on the container (not the inner scroll element)
|
|
@@ -57060,6 +57385,13 @@ const css$w = /* css */`
|
|
|
57060
57385
|
overflow: hidden;
|
|
57061
57386
|
|
|
57062
57387
|
.navi_list_scroll_container {
|
|
57388
|
+
/* The ask stops here: this element is inside the list's frame, so a row
|
|
57389
|
+
or a control it holds is not at the surface's corner. */
|
|
57390
|
+
--x-corner-top-left-radius: initial;
|
|
57391
|
+
--x-corner-top-right-radius: initial;
|
|
57392
|
+
--x-corner-bottom-right-radius: initial;
|
|
57393
|
+
--x-corner-bottom-left-radius: initial;
|
|
57394
|
+
|
|
57063
57395
|
width: inherit;
|
|
57064
57396
|
min-width: inherit;
|
|
57065
57397
|
max-width: var(--list-max-width, inherit);
|
|
@@ -57533,9 +57865,19 @@ const css$w = /* css */`
|
|
|
57533
57865
|
without being contained animate across the page (the pictures live in the
|
|
57534
57866
|
top layer, where no overflow of the document reaches them), which is worse
|
|
57535
57867
|
than not animating at all. So a browser with no nested groups gets no name
|
|
57536
|
-
either, and the change simply happens.
|
|
57868
|
+
either, and the change simply happens.
|
|
57869
|
+
|
|
57870
|
+
Named for a change of the list's own, and for that alone: while the PAGES
|
|
57871
|
+
are the ones moving — a route transition, a route travel — the list is part
|
|
57872
|
+
of what travels, and a picture of its own is precisely what does not
|
|
57873
|
+
travel. A page is carried by its own picture; anything named inside it is
|
|
57874
|
+
lifted out of that picture into a group of its own, which stays where it
|
|
57875
|
+
was captured while the page slides away under it. So the names are dropped
|
|
57876
|
+
for the length of such a movement and the list crosses the screen with the
|
|
57877
|
+
page, as a block. */
|
|
57537
57878
|
@supports (view-transition-group: contain) {
|
|
57538
|
-
|
|
57879
|
+
:root:not([data-navi-route-transition], [data-navi-route-travel])
|
|
57880
|
+
.navi_list_container[data-item-transition] {
|
|
57539
57881
|
/* The list needs a name to be a group at all; which name does not matter,
|
|
57540
57882
|
only that no other element in the document carries it. */
|
|
57541
57883
|
view-transition-name: match-element;
|
|
@@ -65595,6 +65937,8 @@ const css$l = /* css */`
|
|
|
65595
65937
|
* positionArea?: string,
|
|
65596
65938
|
* popupWidthFitContent?: boolean,
|
|
65597
65939
|
* popoverMaxHeight?: number | string,
|
|
65940
|
+
* dialogMinWidth?: number | string,
|
|
65941
|
+
* dialogMinHeight?: number | string,
|
|
65598
65942
|
* dialogMaxWidth?: number | string,
|
|
65599
65943
|
* dialogMaxHeight?: number | string,
|
|
65600
65944
|
* dialogExpand?: boolean,
|
|
@@ -65644,7 +65988,8 @@ const css$l = /* css */`
|
|
|
65644
65988
|
* popover; a dialog keeps Dialog's own "center".
|
|
65645
65989
|
*
|
|
65646
65990
|
* Every other prop the Picker's popup answers to is forwarded as-is —
|
|
65647
|
-
* `dockedOnSmallTouchScreen`, `dialogExpand*`, `
|
|
65991
|
+
* `dockedOnSmallTouchScreen`, `dialogExpand*`, `dialogMinWidth`/`Height`,
|
|
65992
|
+
* `dialogMaxWidth`/`Height`,
|
|
65648
65993
|
* `marginWithContainer`, `popoverMode`, `popoverSpacing`, `popupLayer`,
|
|
65649
65994
|
* `popupWidthFitContent`, `popoverMaxHeight`, `backdropVariant`,
|
|
65650
65995
|
* `pointerInteractionOutsideEffect`, `escapeEffect`, `closeOnFocusOut`,
|
|
@@ -65849,7 +66194,7 @@ const SplitButton = props => {
|
|
|
65849
66194
|
// What the Picker's popup answers to — Picker's own popup props, named here so
|
|
65850
66195
|
// a caller reaches all of them through the split button (see picker.jsx's JSDoc
|
|
65851
66196
|
// for what each one says).
|
|
65852
|
-
const POPUP_PROP_SET = new Set(["mode", "popupLayer", "positionArea", "popoverMode", "popoverSpacing", "popupWidthFitContent", "popoverMaxHeight", "dialogMaxWidth", "dialogMaxHeight", "dialogExpand", "dialogExpandX", "dialogExpandY", "dockedOnSmallTouchScreen", "marginWithContainer", "backdropVariant", "pointerInteractionOutsideEffect", "escapeEffect", "closeOnFocusOut", "scrollCapture", "focusCapture", "popupBackgroundColor", "popupBorderRadius", "animation"]);
|
|
66197
|
+
const POPUP_PROP_SET = new Set(["mode", "popupLayer", "positionArea", "popoverMode", "popoverSpacing", "popupWidthFitContent", "popoverMaxHeight", "dialogMinWidth", "dialogMinHeight", "dialogMaxWidth", "dialogMaxHeight", "dialogExpand", "dialogExpandX", "dialogExpandY", "dockedOnSmallTouchScreen", "marginWithContainer", "backdropVariant", "pointerInteractionOutsideEffect", "escapeEffect", "closeOnFocusOut", "scrollCapture", "focusCapture", "popupBackgroundColor", "popupBorderRadius", "animation"]);
|
|
65853
66198
|
const splitPopupProps = props => {
|
|
65854
66199
|
const popupProps = {};
|
|
65855
66200
|
const boxProps = {};
|