@jsenv/navi 0.29.191 → 0.29.192
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 +346 -64
- package/dist/dev/jsenv_navi.js.map +11 -11
- package/dist/dev/jsenv_navi_side_effects.js +31 -4
- package/dist/dev/jsenv_navi_side_effects.js.map +3 -3
- package/dist/jsenv_navi.js +321 -64
- package/dist/jsenv_navi.js.map +11 -11
- package/dist/jsenv_navi_side_effects.js +31 -4
- package/dist/jsenv_navi_side_effects.js.map +3 -3
- package/docs/AI_INSTRUCTIONS.md +9 -0
- package/docs/interactions.md +104 -8
- package/docs/popup_backdrop.md +93 -0
- 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, coarsePointerSignal, smallTouchScreenSignal } from "./jsenv_navi_side_effects.js";
|
|
6
6
|
export { disableVirtualKeyboardOverlay } from "./jsenv_navi_side_effects.js";
|
|
7
|
-
import { elementIsFocusable, createIterableWeakSet, dispatchInternalCustomEvent, dispatchCustomEvent, getVisuallyVisibleInfo, getFirstVisuallyVisibleAncestor, getElementSignature, createPubSub, findEvent, createValueEffect, findFocusDelegateTarget, findFocusable, scrollIntoViewThroughScrollables, allowWheelThrough, dispatchPublicCustomEvent, resolveCSSColor, ELEMENT_SIZE_CHANGE, findSelfOrAncestorFixedPosition, visibleRectEffect, pickPositionRelativeTo, getBorderSizes, getPaddingSizes, applyNewPosition, measureLongestVisualLineWidth, chainEvent, keepTouchRefusable, waitForPressHeld, suppressClickAfterGesture, startDragToTravel, markDragSource, startDragTo, createEventGroupLogger, getKeyboardEventDefaultAction, activeElementSignal, normalizeStyle, mergeOneStyle, getPositionedParent, normalizeStyles, createGroupTransitionController, getBorderRadius, preventIntermediateScrollbar, createOpacityTransition, watchWheelTravel, scrollRoomTowards, getScrollContainer, closestOpenableAncestor, isAncestorOpen, isDisplayedDespiteClosedAncestor, observeAncestorOpenState, getAncestorOpenType, findBefore, findAfter, resolveCSSSize, hasCSSSizeUnit, releaseWheelGesture, getScrollIntoViewScopedOffsets, wheelGestureIsTakenFrom, claimWheelGesture, scrollIntoViewScoped, initFocusGroup, isTouchDrivenEvent, stringifyStyle as stringifyStyle$1, resolveOklchLightness, contrastColor, parsePositionArea, snapToPixel, trapFocusInside, trapScrollInside, onAncestorReopen, isPressDisputedByDrag, canScroll, measureWidestChildRow, performTabNavigation, dragAfterIntent, stickyAsRelativeCoords, createDragToMoveGestureController, getDropTargetInfo, setStyles, useActiveElement } from "@jsenv/dom";
|
|
7
|
+
import { elementIsFocusable, createIterableWeakSet, dispatchInternalCustomEvent, dispatchCustomEvent, getVisuallyVisibleInfo, getFirstVisuallyVisibleAncestor, getElementSignature, createPubSub, findEvent, createValueEffect, findFocusDelegateTarget, findFocusable, scrollIntoViewThroughScrollables, allowWheelThrough, dispatchPublicCustomEvent, resolveCSSColor, ELEMENT_SIZE_CHANGE, findSelfOrAncestorFixedPosition, visibleRectEffect, pickPositionRelativeTo, getBorderSizes, getPaddingSizes, applyNewPosition, measureLongestVisualLineWidth, chainEvent, keepTouchRefusable, waitForPressHeld, suppressClickAfterGesture, startDragToTravel, markDragSource, startDragTo, createEventGroupLogger, getKeyboardEventDefaultAction, activeElementSignal, normalizeStyle, mergeOneStyle, getPositionedParent, normalizeStyles, createGroupTransitionController, getBorderRadius, preventIntermediateScrollbar, createOpacityTransition, watchWheelTravel, scrollRoomTowards, getScrollContainer, closestOpenableAncestor, isAncestorOpen, isDisplayedDespiteClosedAncestor, observeAncestorOpenState, getAncestorOpenType, findBefore, findAfter, resolveCSSSize, hasCSSSizeUnit, releaseWheelGesture, getScrollIntoViewScopedOffsets, wheelGestureIsTakenFrom, claimWheelGesture, scrollIntoViewScoped, initFocusGroup, isTouchDrivenEvent, stringifyStyle as stringifyStyle$1, resolveOklchLightness, contrastColor, parsePositionArea, snapToPixel, trapFocusInside, trapScrollInside, getVirtualKeyboardOverlayHeight, onAncestorReopen, isPressDisputedByDrag, canScroll, measureWidestChildRow, performTabNavigation, dragAfterIntent, stickyAsRelativeCoords, createDragToMoveGestureController, getDropTargetInfo, setStyles, useActiveElement } from "@jsenv/dom";
|
|
8
8
|
export { chainEvent, clickIsSuppressed, contrastColor, createDragGestureController, dragAfterIntent, findEvent, markDragSource, startDragTo } from "@jsenv/dom";
|
|
9
9
|
import { signal, computed, effect, untracked, batch, useComputed, useSignal } from "@preact/signals";
|
|
10
10
|
import { isValidElement, createContext, render, h, toChildArray, options, cloneElement, Fragment as Fragment$1 } from "preact";
|
|
@@ -5904,7 +5904,13 @@ const css$12 = /* css */ `
|
|
|
5904
5904
|
To ensure ti goes above we put a z-index: 1, I hope it won't bite use in the future */
|
|
5905
5905
|
z-index: 1;
|
|
5906
5906
|
/* Callout styles */
|
|
5907
|
-
display:
|
|
5907
|
+
/* No display declared here on purpose: the UA rule hiding a closed popover
|
|
5908
|
+
is the only thing that takes a hidden callout off screen, and any author
|
|
5909
|
+
display beats it (author origin wins over the UA stylesheet whatever the
|
|
5910
|
+
specificity). Overridden, hidePopover() leaves the box painted — out of
|
|
5911
|
+
the top layer, so laid out against the nearest positioned ancestor while
|
|
5912
|
+
its placement is written in document coordinates: drawn at the wrong
|
|
5913
|
+
place instead of not at all. */
|
|
5908
5914
|
height: auto; /* User agent reset */
|
|
5909
5915
|
margin: 0;
|
|
5910
5916
|
padding: 0; /* User agent reset */
|
|
@@ -10358,17 +10364,27 @@ const swipeTypeOf = (axis, pulled) => {
|
|
|
10358
10364
|
* two, refuse.
|
|
10359
10365
|
*
|
|
10360
10366
|
* interactions={{ land: (event) => {
|
|
10361
|
-
* const { fromId, toId, syncCloneWithDropTarget } = event.detail;
|
|
10367
|
+
* const { fromId, toId, x, y, syncCloneWithDropTarget } = event.detail;
|
|
10362
10368
|
* …
|
|
10363
10369
|
* }}}
|
|
10364
10370
|
*
|
|
10365
10371
|
* `toId` is an element and never null: a copy over nothing is a release that meant
|
|
10366
|
-
* nothing, and the interaction does not happen at all
|
|
10372
|
+
* nothing, and the interaction does not happen at all — unless the element says
|
|
10373
|
+
* `data-toss-by="release-outside"` (see below), which gives that release a
|
|
10374
|
+
* meaning of its own.
|
|
10375
|
+
*
|
|
10376
|
+
* WHERE ON IT, in `x`, `y`, `width`, `height`: the box the copy came down in,
|
|
10377
|
+
* measured inside the place — its border and its scroll taken out. A place that is
|
|
10378
|
+
* a SURFACE — a plan, a map, a floor — has no element under the copy to name and
|
|
10379
|
+
* nothing to swap with: where it came down IS the answer, and `toId` says which
|
|
10380
|
+
* surface rather than which piece.
|
|
10367
10381
|
*
|
|
10368
10382
|
* `syncCloneWithDropTarget` takes an element here, which `reorder` has no use for:
|
|
10369
10383
|
* a place of a board can be larger than what stands on it (a quarter of a court, a
|
|
10370
10384
|
* square holding a smaller piece), and the copy has to come down where the piece
|
|
10371
|
-
* will be rather than filling the place. Left alone, it lands on the place itself
|
|
10385
|
+
* will be rather than filling the place. Left alone, it lands on the place itself —
|
|
10386
|
+
* so a surface either passes what the thing becomes or does not call it at all,
|
|
10387
|
+
* which leaves the copy where the hand put it, over the thing appearing there.
|
|
10372
10388
|
*
|
|
10373
10389
|
* WHICH ELEMENTS ARE PLACES: those marked `data-droppable`, and only those.
|
|
10374
10390
|
* Declaring `land` says an element can be CARRIED, which on a board is a different
|
|
@@ -10377,9 +10393,30 @@ const swipeTypeOf = (axis, pulled) => {
|
|
|
10377
10393
|
* case (dropped on a piece, the two swap). A list has no such distinction — every
|
|
10378
10394
|
* row is both, which is why `reorder` needs no marker in the markup.
|
|
10379
10395
|
*
|
|
10380
|
-
*
|
|
10381
|
-
* and a piece are siblings
|
|
10382
|
-
*
|
|
10396
|
+
* WHERE THE PLACES ARE LOOKED FOR: inside the carried element's PARENT, so a place
|
|
10397
|
+
* and a piece are siblings — and `data-drop-container` on an ancestor says
|
|
10398
|
+
* otherwise. Two arrangements need it, and both are the same one: what is carried
|
|
10399
|
+
* does not stand among the places. A palette is a strip BESIDE the surface it
|
|
10400
|
+
* fills, a marker already placed is drawn INSIDE the surface it can be put back
|
|
10401
|
+
* on, and in each case the search must cover what holds both. It holds the places
|
|
10402
|
+
* rather than being one — a surface carrying it would never be found from inside
|
|
10403
|
+
* itself. It is also what lets the copy travel there: named, the area it may cross
|
|
10404
|
+
* is the page rather than the source's own scroll area.
|
|
10405
|
+
*
|
|
10406
|
+
* <div data-drop-container>
|
|
10407
|
+
* <aside>{shapes.map((shape) => <Shape interactions={{ land: add }} />)}</aside>
|
|
10408
|
+
* <Plan id="plan" data-droppable>…</Plan>
|
|
10409
|
+
* </div>
|
|
10410
|
+
*
|
|
10411
|
+
* HOW A TOSS IS MADE: `data-toss-by`, beside `toss`. A THROW (`"throw"`, the
|
|
10412
|
+
* default) is far AND fast — the flick that gets rid of something, a list's
|
|
10413
|
+
* gesture, and it is judged before any landing. A RELEASE OUTSIDE
|
|
10414
|
+
* (`"release-outside"`) has no place under it — dragging a marker off a plan and
|
|
10415
|
+
* letting go, deliberate and never a flick, a surface's gesture. Each is named on
|
|
10416
|
+
* its own because each is wrong where the other is right: on a plan a fast drag
|
|
10417
|
+
* that ends ON it has not asked for the thing to go, and on a list a row let go of
|
|
10418
|
+
* beside it is a row put back. Both at once is
|
|
10419
|
+
* `data-toss-by="throw release-outside"`.
|
|
10383
10420
|
*
|
|
10384
10421
|
* Nothing of the gesture is decided here. `startDragTo` owns all of it — the
|
|
10385
10422
|
* copy carried above the page while the original keeps its place in the layout, the
|
|
@@ -10469,6 +10506,8 @@ const REORDERABLE_ATTRIBUTE = "data-reorderable";
|
|
|
10469
10506
|
// The same for `land`, except the markup is what writes it: a place of a board is
|
|
10470
10507
|
// not the same thing as a piece of it (see the top of this file).
|
|
10471
10508
|
const DROPPABLE_ATTRIBUTE = "data-droppable";
|
|
10509
|
+
// What holds the places, when the carried element does not stand among them.
|
|
10510
|
+
const DROP_CONTAINER_ATTRIBUTE = "data-drop-container";
|
|
10472
10511
|
// Which axes the drag walks: "x", "y" or "xy". Its default is not the same for
|
|
10473
10512
|
// every outcome — a list runs one way, and something being put somewhere goes
|
|
10474
10513
|
// wherever it is put.
|
|
@@ -10478,6 +10517,10 @@ const SLOP_ATTRIBUTE = "data-drag-slop";
|
|
|
10478
10517
|
const THRESHOLD_ATTRIBUTE = "data-drag-threshold";
|
|
10479
10518
|
const TOSS_DISTANCE_ATTRIBUTE = "data-toss-distance";
|
|
10480
10519
|
const TOSS_SPEED_ATTRIBUTE = "data-toss-speed";
|
|
10520
|
+
// How a toss is made here: "throw" (far and fast), "release-outside" (let go of
|
|
10521
|
+
// away from every place), or both.
|
|
10522
|
+
const TOSS_BY_ATTRIBUTE = "data-toss-by";
|
|
10523
|
+
const TOSS_BY_DEFAULT = "throw";
|
|
10481
10524
|
|
|
10482
10525
|
defineInteractionDetector({
|
|
10483
10526
|
name: "drag",
|
|
@@ -10508,6 +10551,16 @@ defineInteractionDetector({
|
|
|
10508
10551
|
// the hand takes it: a board has places all around, a thing put somewhere has
|
|
10509
10552
|
// two axes to be put along, and a throw goes where it was thrown.
|
|
10510
10553
|
(canReorder && !canLand && !canToss ? "y" : "xy");
|
|
10554
|
+
// Where the places are, and what a release away from all of them means —
|
|
10555
|
+
// both read at setup for the same reason as the axes: they are what the
|
|
10556
|
+
// gesture is about, and it is what holds the two sides of it that says them.
|
|
10557
|
+
const dropContainer = element.closest(`[${DROP_CONTAINER_ATTRIBUTE}]`);
|
|
10558
|
+
const tossByHolder = element.closest(`[${TOSS_BY_ATTRIBUTE}]`);
|
|
10559
|
+
const tossBy = (
|
|
10560
|
+
tossByHolder?.getAttribute(TOSS_BY_ATTRIBUTE) || TOSS_BY_DEFAULT
|
|
10561
|
+
)
|
|
10562
|
+
.trim()
|
|
10563
|
+
.split(/\s+/);
|
|
10511
10564
|
|
|
10512
10565
|
if (canReorder) {
|
|
10513
10566
|
element.setAttribute(REORDERABLE_ATTRIBUTE, "");
|
|
@@ -10534,23 +10587,29 @@ defineInteractionDetector({
|
|
|
10534
10587
|
: canReorder
|
|
10535
10588
|
? `[${REORDERABLE_ATTRIBUTE}]`
|
|
10536
10589
|
: undefined,
|
|
10590
|
+
containerElement: dropContainer || undefined,
|
|
10537
10591
|
getItemId: (itemElement) => itemElement.id,
|
|
10538
10592
|
direction: { x: axes.includes("x"), y: axes.includes("y") },
|
|
10539
10593
|
// Where it may go, said in the DOM. A thing that is put somewhere stays
|
|
10540
10594
|
// inside what one can SEE of its container ("scrollport", not "scroll":
|
|
10541
10595
|
// the scrollable area can be far larger than the box, and "inside the box"
|
|
10542
|
-
// is what a hand expects). `data-drag-free` lifts that
|
|
10543
|
-
//
|
|
10544
|
-
|
|
10545
|
-
|
|
10546
|
-
|
|
10547
|
-
|
|
10548
|
-
|
|
10596
|
+
// is what a hand expects). `data-drag-free` lifts that, and so does a
|
|
10597
|
+
// named container of places: they are somewhere else by construction, and
|
|
10598
|
+
// a copy kept in its own scroll area could never reach them. Left alone
|
|
10599
|
+
// for a throw, which frees the area on its own — it has to be able to
|
|
10600
|
+
// leave.
|
|
10601
|
+
areaConstraint:
|
|
10602
|
+
dropContainer || element.closest(`[data-drag-free]`)
|
|
10603
|
+
? "none"
|
|
10604
|
+
: canMove
|
|
10605
|
+
? "scrollport"
|
|
10606
|
+
: undefined,
|
|
10549
10607
|
threshold: readConfig(THRESHOLD_ATTRIBUTE, undefined),
|
|
10550
10608
|
longPressDelay: readConfig(DELAY_ATTRIBUTE, undefined),
|
|
10551
10609
|
longPressSlop: readConfig(SLOP_ATTRIBUTE, undefined),
|
|
10552
10610
|
tossDistance: readConfig(TOSS_DISTANCE_ATTRIBUTE, undefined),
|
|
10553
10611
|
tossSpeed: readConfig(TOSS_SPEED_ATTRIBUTE, undefined),
|
|
10612
|
+
tossBy,
|
|
10554
10613
|
// The one moment the gesture has that is not a release. Said here rather
|
|
10555
10614
|
// than from the press that led to it, because the press is only one of the
|
|
10556
10615
|
// two ways in: a finger holds still, a mouse travels a few pixels, and it
|
|
@@ -10573,12 +10632,7 @@ defineInteractionDetector({
|
|
|
10573
10632
|
toId,
|
|
10574
10633
|
syncCloneWithDropTarget,
|
|
10575
10634
|
}),
|
|
10576
|
-
onLand: (
|
|
10577
|
-
trigger(LAND, pointerDownEvent, {
|
|
10578
|
-
fromId,
|
|
10579
|
-
toId,
|
|
10580
|
-
syncCloneWithDropTarget,
|
|
10581
|
-
}),
|
|
10635
|
+
onLand: (detail) => trigger(LAND, pointerDownEvent, detail),
|
|
10582
10636
|
onToss: ({ gestureInfo }) =>
|
|
10583
10637
|
trigger(TOSS, pointerDownEvent, {
|
|
10584
10638
|
id: element.id,
|
|
@@ -19670,6 +19724,7 @@ import.meta.css = /* css */[`[data-scrollable] > .navi_loading_outline_wrapper,
|
|
|
19670
19724
|
|
|
19671
19725
|
[data-scrollable] {
|
|
19672
19726
|
overflow: var(--x-scrollable-overflow, auto);
|
|
19727
|
+
scroll-padding: var(--navi-scroll-padding, var(--navi-s));
|
|
19673
19728
|
--box-header-z-index: var(--navi-z-index-sticky);
|
|
19674
19729
|
--box-footer-z-index: var(--navi-z-index-sticky);
|
|
19675
19730
|
isolation: isolate;
|
|
@@ -19714,8 +19769,9 @@ import.meta.css = /* css */[`[data-scrollable] > .navi_loading_outline_wrapper,
|
|
|
19714
19769
|
border-bottom-left-radius: inherit;
|
|
19715
19770
|
outline-width: var(--navi-focus-outline-width);
|
|
19716
19771
|
outline-offset: calc(-1 * var(--navi-focus-outline-width));
|
|
19717
|
-
flex: 0 auto;
|
|
19718
19772
|
min-height: 0;
|
|
19773
|
+
scroll-padding: var(--navi-scroll-padding, var(--navi-s));
|
|
19774
|
+
flex: 0 auto;
|
|
19719
19775
|
overflow: auto;
|
|
19720
19776
|
|
|
19721
19777
|
&:focus-visible {
|
|
@@ -44401,6 +44457,7 @@ const mayHaveHiddenFocus = (event) => {
|
|
|
44401
44457
|
);
|
|
44402
44458
|
};
|
|
44403
44459
|
|
|
44460
|
+
const scrollportHeightMap = new WeakMap();
|
|
44404
44461
|
/**
|
|
44405
44462
|
* Scrolls whatever holds focus inside `popupEl` back into view, if the popup
|
|
44406
44463
|
* getting shorter has pushed it out.
|
|
@@ -44415,14 +44472,27 @@ const mayHaveHiddenFocus = (event) => {
|
|
|
44415
44472
|
* past its bottom edge — visually, swallowed by the footer. The browser does
|
|
44416
44473
|
* not redo a scroll-into-view it already answered, so this does.
|
|
44417
44474
|
*
|
|
44475
|
+
* Only what the shrink itself hid, though: with the keyboard up the user reads
|
|
44476
|
+
* the rest of the popup by scrolling the field away — to reach the submit under
|
|
44477
|
+
* it, typically — and the room keeps changing while they do (a keyboard settling
|
|
44478
|
+
* in two steps, a suggestion strip, a browser bar). Answering each of those by
|
|
44479
|
+
* scrolling the field back takes the popup away from wherever they had just
|
|
44480
|
+
* scrolled it, over and over: what they were reading cannot be reached at all
|
|
44481
|
+
* without blurring the field first, and the popup reads as unscrollable. So the
|
|
44482
|
+
* field is brought back only when it was in view before the room shrank, which
|
|
44483
|
+
* one remembered number answers: a resize moves neither scrollTop nor the
|
|
44484
|
+
* element's offset inside the scrolled content, so measuring against the height
|
|
44485
|
+
* the scrollport HAD is measuring the state before the change.
|
|
44486
|
+
*
|
|
44418
44487
|
* Scoped to the field's own scroll container (never the page): a popup traps
|
|
44419
44488
|
* scrolling precisely so the document underneath cannot move, and a plain
|
|
44420
44489
|
* scrollIntoView walks past a container whose scrollbar isn't visible — see
|
|
44421
44490
|
* scrollIntoViewScoped's own doc.
|
|
44422
44491
|
*
|
|
44423
|
-
* "nearest": the smallest scroll that makes it visible, and none at all when
|
|
44424
|
-
*
|
|
44425
|
-
*
|
|
44492
|
+
* "nearest": the smallest scroll that makes it visible, and none at all when it
|
|
44493
|
+
* already is. Where it lands is the container's own business — a navi scroller
|
|
44494
|
+
* keeps a band free at its edges so a field never comes back glued to one (see
|
|
44495
|
+
* scroll-padding in box.jsx).
|
|
44426
44496
|
*/
|
|
44427
44497
|
const keepFocusedElementVisible = (popupEl) => {
|
|
44428
44498
|
const { activeElement } = document;
|
|
@@ -44432,7 +44502,49 @@ const keepFocusedElementVisible = (popupEl) => {
|
|
|
44432
44502
|
if (!popupEl.contains(activeElement)) {
|
|
44433
44503
|
return;
|
|
44434
44504
|
}
|
|
44435
|
-
|
|
44505
|
+
const scrollContainer = getScrollContainer(activeElement);
|
|
44506
|
+
if (!scrollContainer || !popupEl.contains(scrollContainer)) {
|
|
44507
|
+
// What scrolls the field is outside the popup, which means the page: a
|
|
44508
|
+
// popup holds it still on purpose (trapScrollInside), so there is nothing
|
|
44509
|
+
// here to scroll back.
|
|
44510
|
+
return;
|
|
44511
|
+
}
|
|
44512
|
+
const scrollportHeight = scrollContainer.clientHeight;
|
|
44513
|
+
const scrollportHeightBefore = scrollportHeightMap.get(scrollContainer);
|
|
44514
|
+
scrollportHeightMap.set(scrollContainer, scrollportHeight);
|
|
44515
|
+
if (scrollportHeightBefore !== undefined) {
|
|
44516
|
+
if (scrollportHeight >= scrollportHeightBefore) {
|
|
44517
|
+
// Nothing was taken away, so nothing was hidden by this.
|
|
44518
|
+
return;
|
|
44519
|
+
}
|
|
44520
|
+
if (
|
|
44521
|
+
!isVisibleInScrollport(
|
|
44522
|
+
activeElement,
|
|
44523
|
+
scrollContainer,
|
|
44524
|
+
scrollportHeightBefore,
|
|
44525
|
+
)
|
|
44526
|
+
) {
|
|
44527
|
+
return;
|
|
44528
|
+
}
|
|
44529
|
+
}
|
|
44530
|
+
scrollIntoViewScoped(activeElement, {
|
|
44531
|
+
container: scrollContainer,
|
|
44532
|
+
block: "nearest",
|
|
44533
|
+
});
|
|
44534
|
+
};
|
|
44535
|
+
|
|
44536
|
+
// Whether any part of `el` was showing in `container` back when its scrollport
|
|
44537
|
+
// was `scrollportHeight` tall. Both boxes are read now: the container may have
|
|
44538
|
+
// moved as well as shrunk (a centered dialog re-centers itself), and the
|
|
44539
|
+
// difference between the two tops is what that move leaves alone.
|
|
44540
|
+
const isVisibleInScrollport = (el, container, scrollportHeight) => {
|
|
44541
|
+
const elRect = el.getBoundingClientRect();
|
|
44542
|
+
const containerRect = container.getBoundingClientRect();
|
|
44543
|
+
const elTop = elRect.top - containerRect.top + container.scrollTop;
|
|
44544
|
+
const elBottom = elTop + elRect.height;
|
|
44545
|
+
const scrollportTop = container.scrollTop;
|
|
44546
|
+
const scrollportBottom = scrollportTop + scrollportHeight;
|
|
44547
|
+
return elBottom > scrollportTop && elTop < scrollportBottom;
|
|
44436
44548
|
};
|
|
44437
44549
|
|
|
44438
44550
|
/**
|
|
@@ -44479,6 +44591,32 @@ const whenTransitionSettles = (el, onSettled) => {
|
|
|
44479
44591
|
};
|
|
44480
44592
|
};
|
|
44481
44593
|
|
|
44594
|
+
/**
|
|
44595
|
+
* Drops the document's text selection when it lives inside `el`, leaving a
|
|
44596
|
+
* selection made elsewhere on the page alone.
|
|
44597
|
+
*
|
|
44598
|
+
* A popup being closed takes its content with it, and a selection is a claim
|
|
44599
|
+
* on content the user can still act on: kept, it would outlive the surface it
|
|
44600
|
+
* was made on — painted on the box for the length of its exit transition, with
|
|
44601
|
+
* the handles and the copy toolbar a phone draws from the live selection
|
|
44602
|
+
* hanging over something that is going away — and reappear with the box on
|
|
44603
|
+
* the next opening. Dropping the selection is the only way to remove that
|
|
44604
|
+
* chrome: a `user-select: none` on the closing box hides the highlight in some
|
|
44605
|
+
* browsers only, and the handles are the browser's own, drawn from the
|
|
44606
|
+
* selection object rather than from any style.
|
|
44607
|
+
*/
|
|
44608
|
+
const clearTextSelectionInside = (el) => {
|
|
44609
|
+
const selection = window.getSelection();
|
|
44610
|
+
if (!selection || selection.rangeCount === 0) {
|
|
44611
|
+
return;
|
|
44612
|
+
}
|
|
44613
|
+
const range = selection.getRangeAt(0);
|
|
44614
|
+
if (!el.contains(range.commonAncestorContainer)) {
|
|
44615
|
+
return;
|
|
44616
|
+
}
|
|
44617
|
+
selection.removeAllRanges();
|
|
44618
|
+
};
|
|
44619
|
+
|
|
44482
44620
|
/**
|
|
44483
44621
|
* Disables pointer-events on `el` until its current CSS transition settles —
|
|
44484
44622
|
* avoids the cursor changing/something becoming clickable while the popup is
|
|
@@ -56135,6 +56273,15 @@ const css$E = /* css */`
|
|
|
56135
56273
|
scroll (a short body, an axis with nowhere to go) must not travel to
|
|
56136
56274
|
whatever is behind. */
|
|
56137
56275
|
overscroll-behavior: none;
|
|
56276
|
+
/* What the backdrop paints, resolved on the dialog rather than on the
|
|
56277
|
+
pseudo-element that paints it: ::backdrop takes no inline style and
|
|
56278
|
+
carries no attribute of its own, so the backdropColor/backdropFilter
|
|
56279
|
+
props land here — inline, beating every rule below — and the
|
|
56280
|
+
pseudo-element inherits whichever won. A colour and a filter travel
|
|
56281
|
+
together everywhere a backdrop is painted: see navi_css_vars.js for
|
|
56282
|
+
why a blur is not tied to what an outside click does. */
|
|
56283
|
+
--backdrop-background: var(--navi-backdrop-close-background);
|
|
56284
|
+
--backdrop-filter: var(--navi-backdrop-close-backdrop-filter);
|
|
56138
56285
|
|
|
56139
56286
|
/* Docking answers a different question than --dialog-max-width: a sheet
|
|
56140
56287
|
spans its container's full width, flush against the two side edges —
|
|
@@ -56185,6 +56332,7 @@ const css$E = /* css */`
|
|
|
56185
56332
|
&[data-flush-bottom][data-flush-left] {
|
|
56186
56333
|
border-bottom-left-radius: 0;
|
|
56187
56334
|
}
|
|
56335
|
+
|
|
56188
56336
|
/* The placement is a translate, so the translate property is spoken for
|
|
56189
56337
|
here (see applyNewPosition in visible_rect.js, which owns it and animates
|
|
56190
56338
|
it itself through the Web Animations API rather than through this file's
|
|
@@ -56192,26 +56340,26 @@ const css$E = /* css */`
|
|
|
56192
56340
|
to filter). An entrance animation moves the dialog through scale and
|
|
56193
56341
|
transform instead, which compose under it: see popup_css.js. */
|
|
56194
56342
|
|
|
56195
|
-
|
|
56196
|
-
background: var(--navi-backdrop-
|
|
56343
|
+
&[data-pointer-interaction-outside="capture"] {
|
|
56344
|
+
--backdrop-background: var(--navi-backdrop-capture-background);
|
|
56345
|
+
--backdrop-filter: var(--navi-backdrop-capture-backdrop-filter);
|
|
56197
56346
|
}
|
|
56198
|
-
|
|
56199
|
-
|
|
56200
|
-
|
|
56347
|
+
/* backdropVariant, after the rules it overrides: same specificity, so
|
|
56348
|
+
order is what decides. showModal() still makes the page inert either
|
|
56349
|
+
way — only the paint goes away. */
|
|
56350
|
+
&[data-backdrop-variant="discrete"] {
|
|
56351
|
+
--backdrop-background: var(--navi-backdrop-discrete-background);
|
|
56352
|
+
--backdrop-filter: var(--navi-backdrop-discrete-backdrop-filter);
|
|
56201
56353
|
}
|
|
56202
|
-
|
|
56203
|
-
|
|
56204
|
-
|
|
56205
|
-
|
|
56206
|
-
|
|
56207
|
-
page inert either way — only the paint goes away. */
|
|
56208
|
-
&[data-backdrop-variant="discrete"]::backdrop {
|
|
56209
|
-
background: var(--navi-backdrop-discrete-background);
|
|
56210
|
-
backdrop-filter: none;
|
|
56354
|
+
/* The one backdrop with nothing to blur through: "invisible" paints
|
|
56355
|
+
nothing at all, and a filter would still be seen. */
|
|
56356
|
+
&[data-backdrop-variant="invisible"] {
|
|
56357
|
+
--backdrop-background: transparent;
|
|
56358
|
+
--backdrop-filter: none;
|
|
56211
56359
|
}
|
|
56212
|
-
|
|
56213
|
-
background:
|
|
56214
|
-
backdrop-filter:
|
|
56360
|
+
&::backdrop {
|
|
56361
|
+
background: var(--backdrop-background);
|
|
56362
|
+
backdrop-filter: var(--backdrop-filter);
|
|
56215
56363
|
}
|
|
56216
56364
|
|
|
56217
56365
|
/* Nested under &[navi-animation] (not the other way around) so every
|
|
@@ -56321,6 +56469,17 @@ const css$E = /* css */`
|
|
|
56321
56469
|
in openEffect) gets pointer-events: none mid-transition. */
|
|
56322
56470
|
pointer-events: auto;
|
|
56323
56471
|
|
|
56472
|
+
/* Painted through the same two variables as the via-attribute renderer's
|
|
56473
|
+
::backdrop (see them for what each rule is for) — here they resolve on
|
|
56474
|
+
the element that paints, which is also the element the
|
|
56475
|
+
backdropColor/backdropFilter props are set on. Declared unconditionally
|
|
56476
|
+
first so a variable inherited from a dialog this popup was opened from
|
|
56477
|
+
can never reach the paint. */
|
|
56478
|
+
--backdrop-background: transparent;
|
|
56479
|
+
--backdrop-filter: none;
|
|
56480
|
+
background: var(--backdrop-background);
|
|
56481
|
+
backdrop-filter: var(--backdrop-filter);
|
|
56482
|
+
|
|
56324
56483
|
/* A plain div, unlike dialogEl itself (a real <dialog>, natively hidden
|
|
56325
56484
|
by default until .show()/.showModal() adds [open]) — needs its own
|
|
56326
56485
|
starting-hidden mechanism. [navi-hidden] is set from useDialogProps'
|
|
@@ -56337,23 +56496,20 @@ const css$E = /* css */`
|
|
|
56337
56496
|
/* Makes pointerInteractionOutsideEffect have a visible impact on backdrop */
|
|
56338
56497
|
&[data-pointer-interaction-outside="close"],
|
|
56339
56498
|
&[data-pointer-interaction-outside="cancel"] {
|
|
56340
|
-
background: var(--navi-backdrop-close-background);
|
|
56499
|
+
--backdrop-background: var(--navi-backdrop-close-background);
|
|
56500
|
+
--backdrop-filter: var(--navi-backdrop-close-backdrop-filter);
|
|
56341
56501
|
}
|
|
56342
56502
|
&[data-pointer-interaction-outside="capture"] {
|
|
56343
|
-
background: var(--navi-backdrop-capture-background);
|
|
56344
|
-
backdrop-filter: var(--navi-backdrop-capture-backdrop-filter);
|
|
56503
|
+
--backdrop-background: var(--navi-backdrop-capture-background);
|
|
56504
|
+
--backdrop-filter: var(--navi-backdrop-capture-backdrop-filter);
|
|
56345
56505
|
}
|
|
56346
|
-
|
|
56347
|
-
/* Same override as the via-attribute renderer's own ::backdrop rules
|
|
56348
|
-
above, on the real element this renderer uses instead — see them for
|
|
56349
|
-
the specificity/ordering reasoning. */
|
|
56350
56506
|
&[data-backdrop-variant="discrete"] {
|
|
56351
|
-
background: var(--navi-backdrop-discrete-background);
|
|
56352
|
-
backdrop-filter:
|
|
56507
|
+
--backdrop-background: var(--navi-backdrop-discrete-background);
|
|
56508
|
+
--backdrop-filter: var(--navi-backdrop-discrete-backdrop-filter);
|
|
56353
56509
|
}
|
|
56354
56510
|
&[data-backdrop-variant="invisible"] {
|
|
56355
|
-
background: transparent;
|
|
56356
|
-
backdrop-filter: none;
|
|
56511
|
+
--backdrop-background: transparent;
|
|
56512
|
+
--backdrop-filter: none;
|
|
56357
56513
|
}
|
|
56358
56514
|
|
|
56359
56515
|
/* overlay is a no-op here (this backdrop is a plain div, never a
|
|
@@ -56480,6 +56636,17 @@ const css$E = /* css */`
|
|
|
56480
56636
|
* barely-there dim. `"invisible"`: fully transparent. The dialog stays modal
|
|
56481
56637
|
* either way — this only changes how much it insists visually, never what
|
|
56482
56638
|
* an outside click does or whether the page behind stays reachable.
|
|
56639
|
+
* @param {string} [props.backdropColor] - The wash painted over what is
|
|
56640
|
+
* behind, for this popup alone: any CSS color (`"rgb(6 10 20 / 88%)"`).
|
|
56641
|
+
* Wins over `backdropVariant` and over the theme tokens
|
|
56642
|
+
* (`--navi-backdrop-*-background`), which is where the same choice goes
|
|
56643
|
+
* when it is the whole app's.
|
|
56644
|
+
* @param {string} [props.backdropFilter] - What that same wash does to the
|
|
56645
|
+
* picture underneath: `"blur(4px)"` to keep the page behind recognisable
|
|
56646
|
+
* while it stops being readable. A `backdrop-filter` value, so
|
|
56647
|
+
* `saturate()`/`grayscale()` work too. How far what is behind withdraws is
|
|
56648
|
+
* a question of paint, not of what an outside click does — a backdrop that
|
|
56649
|
+
* closes can blur.
|
|
56483
56650
|
* @param {boolean} [props.scrollCapture] - Traps scroll gestures inside the
|
|
56484
56651
|
* dialog so the page/container behind it can't scroll while it's open.
|
|
56485
56652
|
* A `layer="local"` dialog always locks its own positioned ancestor's
|
|
@@ -56816,6 +56983,13 @@ const useDialogProps = props => {
|
|
|
56816
56983
|
// always modal, so "none" here never makes the page behind reachable:
|
|
56817
56984
|
// it only stops the dim from being drawn.
|
|
56818
56985
|
backdropVariant = "auto",
|
|
56986
|
+
// The paint itself, when the tokens behind backdropVariant are not what
|
|
56987
|
+
// this one dialog wants. Named/forwarded rather than left in ...rest:
|
|
56988
|
+
// rest lands on the dialog element, and these belong to the backdrop —
|
|
56989
|
+
// which is the pseudo-element of one renderer and a sibling of the other,
|
|
56990
|
+
// so both objects below get them (see this file's CSS).
|
|
56991
|
+
backdropColor,
|
|
56992
|
+
backdropFilter,
|
|
56819
56993
|
scrollCapture: scrollCaptureProp,
|
|
56820
56994
|
// "auto" (default) → the dialog follows its content. "frozen" → measured
|
|
56821
56995
|
// once, held at that size while open. See this prop's own JSDoc above.
|
|
@@ -57244,6 +57418,33 @@ const useDialogProps = props => {
|
|
|
57244
57418
|
// recheck its own position whenever this dialog itself moves is
|
|
57245
57419
|
// handled generically by applyNewPosition itself (dispatches
|
|
57246
57420
|
// navi_position_change on every call) — nothing to do here.
|
|
57421
|
+
logPlacement(triggerEvent, position);
|
|
57422
|
+
};
|
|
57423
|
+
// The whole picture in one line: where the dialog ended up, and what it
|
|
57424
|
+
// believed about the room when it decided. Both are needed together — a box
|
|
57425
|
+
// that looks wrong on screen while these numbers are right means something
|
|
57426
|
+
// covers the screen that no API describes (a phone's autofill/suggestion
|
|
57427
|
+
// strip), and the absence of a line after the keyboard arrives means the
|
|
57428
|
+
// placement was never asked to run again.
|
|
57429
|
+
const logPlacement = (triggerEvent, position) => {
|
|
57430
|
+
// The decided target, never the current rect: the placement animates, so
|
|
57431
|
+
// a box read right after applying one is somewhere between the two and
|
|
57432
|
+
// reads like a decision nobody took.
|
|
57433
|
+
const {
|
|
57434
|
+
visualViewport
|
|
57435
|
+
} = window;
|
|
57436
|
+
// Reads nothing that brings the layout up to date — no getComputedStyle,
|
|
57437
|
+
// no window.innerWidth/innerHeight. That is the very thing this line is
|
|
57438
|
+
// here to observe (see getVisibleViewportRect in @jsenv/dom): a log that
|
|
57439
|
+
// forced it would hand the NEXT placement a fresh viewport and hide the
|
|
57440
|
+
// bug it was printed to show. Everything below is either already computed
|
|
57441
|
+
// (the pick's own numbers, "room" being the room it had) or free to read.
|
|
57442
|
+
const message = `placed on "${triggerEvent ? triggerEvent.type : "open"}": ${Math.round(position.width)}x${Math.round(position.height)} at ${Math.round(position.top)}->${Math.round(position.top + position.height)} | room ${Math.round(position.containerHeightAvailable)} | viewport ${Math.round(visualViewport.width)}x${Math.round(visualViewport.height)} +${Math.round(visualViewport.offsetLeft)},${Math.round(visualViewport.offsetTop)} | keyboard ${getVirtualKeyboardOverlayHeight()}`;
|
|
57443
|
+
if (triggerEvent) {
|
|
57444
|
+
debugPopup(triggerEvent, message);
|
|
57445
|
+
} else {
|
|
57446
|
+
debugPopup(message);
|
|
57447
|
+
}
|
|
57247
57448
|
};
|
|
57248
57449
|
// Cleared here rather than on close, where the box is deliberately left
|
|
57249
57450
|
// frozen at the size it was closing at (see the closing function's own
|
|
@@ -57391,6 +57592,7 @@ const useDialogProps = props => {
|
|
|
57391
57592
|
}
|
|
57392
57593
|
return closeEvent => {
|
|
57393
57594
|
debugPopup(`"${closeEvent.type}" on ${getElementSignature(closeEvent.target)} -> closeDialog`);
|
|
57595
|
+
clearTextSelectionInside(dialogEl);
|
|
57394
57596
|
dialogEl.setAttribute("aria-expanded", "false");
|
|
57395
57597
|
if (!isModal) {
|
|
57396
57598
|
openLocalDialogCount = Math.max(0, openLocalDialogCount - 1);
|
|
@@ -57478,7 +57680,9 @@ const useDialogProps = props => {
|
|
|
57478
57680
|
"styleCSSVars": DIALOG_STYLE_CSS_VARS,
|
|
57479
57681
|
"animationDuration": rest.animationDuration,
|
|
57480
57682
|
"data-pointer-interaction-outside": pointerInteractionOutsideEffect,
|
|
57481
|
-
"data-backdrop-variant": backdropVariant
|
|
57683
|
+
"data-backdrop-variant": backdropVariant,
|
|
57684
|
+
backdropColor,
|
|
57685
|
+
backdropFilter
|
|
57482
57686
|
});
|
|
57483
57687
|
Object.assign(contentProps, {
|
|
57484
57688
|
tabIndex,
|
|
@@ -57512,6 +57716,11 @@ const useDialogProps = props => {
|
|
|
57512
57716
|
// as the prop just above (and harmless for the custom renderer, whose
|
|
57513
57717
|
// real backdrop element gets it via backdropProps).
|
|
57514
57718
|
"data-backdrop-variant": backdropVariant,
|
|
57719
|
+
// Read by the native ::backdrop, which inherits them from here (see this
|
|
57720
|
+
// file's CSS) — the custom renderer's own backdrop element gets them via
|
|
57721
|
+
// backdropProps above.
|
|
57722
|
+
backdropColor,
|
|
57723
|
+
backdropFilter,
|
|
57515
57724
|
"styleCSSVars": DIALOG_STYLE_CSS_VARS,
|
|
57516
57725
|
...rest,
|
|
57517
57726
|
...autoFocusProps,
|
|
@@ -57628,6 +57837,8 @@ const DIALOG_PSEUDO_CLASSES = [":hover", ":active", ":focus", ":focus-visible",
|
|
|
57628
57837
|
// an inline border-radius would outrank them.
|
|
57629
57838
|
const DIALOG_STYLE_CSS_VARS = {
|
|
57630
57839
|
animationDuration: "--popup-animation-duration",
|
|
57840
|
+
backdropColor: "--backdrop-background",
|
|
57841
|
+
backdropFilter: "--backdrop-filter",
|
|
57631
57842
|
borderRadius: "--dialog-border-radius",
|
|
57632
57843
|
minWidth: "--dialog-min-width",
|
|
57633
57844
|
maxWidth: "--dialog-max-width",
|
|
@@ -57861,8 +58072,18 @@ const css$D = /* css */`
|
|
|
57861
58072
|
z-index: calc(var(--navi-z-index-popup) + var(--popover-stack-order, 0));
|
|
57862
58073
|
margin: 0;
|
|
57863
58074
|
padding: 0;
|
|
57864
|
-
|
|
58075
|
+
/* What this backdrop paints, in two variables the rules below write as
|
|
58076
|
+
defaults — so the backdropColor/backdropFilter props, inline on this
|
|
58077
|
+
very element, beat all of them. Declared unconditionally first so a
|
|
58078
|
+
variable inherited from a dialog this popover was opened from can never
|
|
58079
|
+
reach the paint. A colour and a filter travel together everywhere a
|
|
58080
|
+
backdrop is painted: see navi_css_vars.js for why a blur is not tied to
|
|
58081
|
+
what an outside click does. */
|
|
58082
|
+
--backdrop-background: transparent;
|
|
58083
|
+
--backdrop-filter: none;
|
|
58084
|
+
background: var(--backdrop-background);
|
|
57865
58085
|
border: none;
|
|
58086
|
+
backdrop-filter: var(--backdrop-filter);
|
|
57866
58087
|
/* Always clickable while actually rendered (display: none/hidePopover()
|
|
57867
58088
|
while genuinely closed already makes it non-interactive on its own)
|
|
57868
58089
|
— an outside click should close the popover even while it's still
|
|
@@ -57893,11 +58114,12 @@ const css$D = /* css */`
|
|
|
57893
58114
|
/* Makes pointerInteractionOutsideEffect have a visible impact on backdrop */
|
|
57894
58115
|
&[data-pointer-interaction-outside="close"],
|
|
57895
58116
|
&[data-pointer-interaction-outside="cancel"] {
|
|
57896
|
-
background: var(--navi-backdrop-close-background);
|
|
58117
|
+
--backdrop-background: var(--navi-backdrop-close-background);
|
|
58118
|
+
--backdrop-filter: var(--navi-backdrop-close-backdrop-filter);
|
|
57897
58119
|
}
|
|
57898
58120
|
&[data-pointer-interaction-outside="capture"] {
|
|
57899
|
-
background: var(--navi-backdrop-capture-background);
|
|
57900
|
-
backdrop-filter: var(--navi-backdrop-capture-backdrop-filter);
|
|
58121
|
+
--backdrop-background: var(--navi-backdrop-capture-background);
|
|
58122
|
+
--backdrop-filter: var(--navi-backdrop-capture-backdrop-filter);
|
|
57901
58123
|
}
|
|
57902
58124
|
|
|
57903
58125
|
/* backdropVariant overrides whatever the effect above picked — same
|
|
@@ -57906,12 +58128,14 @@ const css$D = /* css */`
|
|
|
57906
58128
|
and still pointer-events: auto, so an outside click keeps doing
|
|
57907
58129
|
exactly what pointerInteractionOutsideEffect says. */
|
|
57908
58130
|
&[data-backdrop-variant="discrete"] {
|
|
57909
|
-
background: var(--navi-backdrop-discrete-background);
|
|
57910
|
-
backdrop-filter:
|
|
58131
|
+
--backdrop-background: var(--navi-backdrop-discrete-background);
|
|
58132
|
+
--backdrop-filter: var(--navi-backdrop-discrete-backdrop-filter);
|
|
57911
58133
|
}
|
|
58134
|
+
/* The one backdrop with nothing to blur through: "invisible" paints
|
|
58135
|
+
nothing at all, and a filter would still be seen. */
|
|
57912
58136
|
&[data-backdrop-variant="invisible"] {
|
|
57913
|
-
background: transparent;
|
|
57914
|
-
backdrop-filter: none;
|
|
58137
|
+
--backdrop-background: transparent;
|
|
58138
|
+
--backdrop-filter: none;
|
|
57915
58139
|
}
|
|
57916
58140
|
|
|
57917
58141
|
/* navi-animation mirrors the content popover's own resolved value (set
|
|
@@ -57991,6 +58215,17 @@ const css$D = /* css */`
|
|
|
57991
58215
|
* changes how much the popover insists on being the thing you deal with.
|
|
57992
58216
|
* Ignored when `pointerInteractionOutsideEffect="none"` (there is no
|
|
57993
58217
|
* backdrop at all then, and outside clicks pass through).
|
|
58218
|
+
* @param {string} [props.backdropColor] - The wash painted over what is
|
|
58219
|
+
* behind, for this popup alone: any CSS color (`"rgb(6 10 20 / 88%)"`).
|
|
58220
|
+
* Wins over `backdropVariant` and over the theme tokens
|
|
58221
|
+
* (`--navi-backdrop-*-background`), which is where the same choice goes
|
|
58222
|
+
* when it is the whole app's.
|
|
58223
|
+
* @param {string} [props.backdropFilter] - What that same wash does to the
|
|
58224
|
+
* picture underneath: `"blur(4px)"` to keep the page behind recognisable
|
|
58225
|
+
* while it stops being readable. A `backdrop-filter` value, so
|
|
58226
|
+
* `saturate()`/`grayscale()` work too. How far what is behind withdraws is
|
|
58227
|
+
* a question of paint, not of what an outside click does — a backdrop that
|
|
58228
|
+
* closes can blur.
|
|
57994
58229
|
* @param {boolean} [props.scrollCapture] - Traps scroll gestures inside the
|
|
57995
58230
|
* popover so the page/container behind it can't scroll while it's open.
|
|
57996
58231
|
* @param {boolean} [props.focusCapture] - Traps Tab navigation inside the
|
|
@@ -58302,6 +58537,12 @@ const usePopoverProps = props => {
|
|
|
58302
58537
|
// the paint the effect implies; "discrete"/"none" tone it down or
|
|
58303
58538
|
// remove it entirely without giving up the outside click.
|
|
58304
58539
|
backdropVariant = "auto",
|
|
58540
|
+
// The paint itself, when the tokens behind backdropVariant are not what
|
|
58541
|
+
// this one popover wants. Named/forwarded rather than left in ...rest:
|
|
58542
|
+
// rest lands on the popover element, and these belong to its backdrop,
|
|
58543
|
+
// which is a sibling element (see this file's top comment).
|
|
58544
|
+
backdropColor,
|
|
58545
|
+
backdropFilter,
|
|
58305
58546
|
scrollCapture,
|
|
58306
58547
|
focusCapture,
|
|
58307
58548
|
// "auto" (default) → the popover follows its content. "frozen" → measured
|
|
@@ -58896,6 +59137,7 @@ const usePopoverProps = props => {
|
|
|
58896
59137
|
// reason: only ever built here.
|
|
58897
59138
|
return closeEvent => {
|
|
58898
59139
|
debugPopup(closeEvent, `closePopover()`);
|
|
59140
|
+
clearTextSelectionInside(popoverEl);
|
|
58899
59141
|
popoverEl.setAttribute("aria-expanded", "false");
|
|
58900
59142
|
// Set regardless of isTopLayer — see the open side's own identical
|
|
58901
59143
|
// comment (openEffect above) for why hidePopover() alone isn't
|
|
@@ -59011,6 +59253,8 @@ const usePopoverProps = props => {
|
|
|
59011
59253
|
"animationDuration": rest.animationDuration,
|
|
59012
59254
|
"data-pointer-interaction-outside": pointerInteractionOutsideEffect,
|
|
59013
59255
|
"data-backdrop-variant": backdropVariant,
|
|
59256
|
+
backdropColor,
|
|
59257
|
+
backdropFilter,
|
|
59014
59258
|
"onMouseDown": mouseDownEvent => {
|
|
59015
59259
|
if (mouseDownEvent.button !== 0) {
|
|
59016
59260
|
return;
|
|
@@ -59115,6 +59359,8 @@ const POPOVER_PSEUDO_CLASSES = [":hover", ":active", ":focus", ":focus-visible",
|
|
|
59115
59359
|
// handling).
|
|
59116
59360
|
const POPUP_STYLE_CSS_VARS = {
|
|
59117
59361
|
animationDuration: "--popup-animation-duration",
|
|
59362
|
+
backdropColor: "--backdrop-background",
|
|
59363
|
+
backdropFilter: "--backdrop-filter",
|
|
59118
59364
|
minWidth: "--popover-min-width",
|
|
59119
59365
|
maxWidth: "--popover-max-width",
|
|
59120
59366
|
minHeight: "--popover-min-height",
|
|
@@ -59233,6 +59479,10 @@ const css$C = /* css */`@layer navi {
|
|
|
59233
59479
|
* how visible the backdrop is, independently of what an outside click
|
|
59234
59480
|
* does. Unlike `pointerInteractionOutsideEffect` above, this one needs no
|
|
59235
59481
|
* default here — `"auto"` already means the same thing on both sides.
|
|
59482
|
+
* @param {string} [props.backdropColor] - Forwarded as-is (both understand it
|
|
59483
|
+
* identically): the wash the backdrop paints over what is behind.
|
|
59484
|
+
* @param {string} [props.backdropFilter] - Forwarded as-is: what that wash
|
|
59485
|
+
* does to the picture underneath, `"blur(4px)"` and the like.
|
|
59236
59486
|
* @param {boolean|"auto"|"fading"|"scaling"|"sliding"|"expanding"|`slide-from-${string}`|`expand-${string}`} [props.animation]
|
|
59237
59487
|
* - Forwarded as-is.
|
|
59238
59488
|
* @param {string} [props.animationDuration] - Forwarded as-is.
|
|
@@ -60101,6 +60351,8 @@ const PickerContentInsidePopup = props => {
|
|
|
60101
60351
|
// Named/forwarded rather than left in ...rest: rest goes to the picker
|
|
60102
60352
|
// element itself, not the popup, and this belongs to the popup.
|
|
60103
60353
|
backdropVariant,
|
|
60354
|
+
backdropColor,
|
|
60355
|
+
backdropFilter,
|
|
60104
60356
|
dialogExpand,
|
|
60105
60357
|
dialogExpandX,
|
|
60106
60358
|
dialogExpandY,
|
|
@@ -60176,6 +60428,8 @@ const PickerContentInsidePopup = props => {
|
|
|
60176
60428
|
scrollCapture: scrollCapture,
|
|
60177
60429
|
pointerInteractionOutsideEffect: pointerLock ? "capture" : pointerInteractionOutsideEffect,
|
|
60178
60430
|
backdropVariant: backdropVariant,
|
|
60431
|
+
backdropColor: backdropColor,
|
|
60432
|
+
backdropFilter: backdropFilter,
|
|
60179
60433
|
focusCapture: isPopover ? focusCapture : undefined,
|
|
60180
60434
|
expand: isPopover ? undefined : dialogExpand,
|
|
60181
60435
|
expandX: isPopover ? undefined : dialogExpandX,
|
|
@@ -71251,6 +71505,8 @@ const css$n = /* css */`.navi_split_button {
|
|
|
71251
71505
|
* dockedOnSmallTouchScreen?: boolean,
|
|
71252
71506
|
* marginWithContainer?: number | string,
|
|
71253
71507
|
* backdropVariant?: "auto" | "discrete" | "invisible",
|
|
71508
|
+
* backdropColor?: string,
|
|
71509
|
+
* backdropFilter?: string,
|
|
71254
71510
|
* pointerInteractionOutsideEffect?: "close" | "cancel" | "capture",
|
|
71255
71511
|
* escapeEffect?: "cancel" | "close",
|
|
71256
71512
|
* popupLayer?: "top" | "local",
|
|
@@ -71297,6 +71553,7 @@ const css$n = /* css */`.navi_split_button {
|
|
|
71297
71553
|
* `dialogMaxWidth`/`Height`,
|
|
71298
71554
|
* `marginWithContainer`, `popoverMode`, `popoverSpacing`, `popupLayer`,
|
|
71299
71555
|
* `popupTestId`, `popupWidthFitContent`, `popoverMaxHeight`, `backdropVariant`,
|
|
71556
|
+
* `backdropColor`, `backdropFilter`,
|
|
71300
71557
|
* `pointerInteractionOutsideEffect`, `escapeEffect`, `closeOnFocusOut`,
|
|
71301
71558
|
* `scrollCapture`, `focusCapture`, `popupBackgroundColor`,
|
|
71302
71559
|
* `popupBorderRadius`, `animation`. See picker.jsx for what each one says.
|
|
@@ -71497,7 +71754,7 @@ const SplitButton = props => {
|
|
|
71497
71754
|
// What the Picker's popup answers to — Picker's own popup props, named here so
|
|
71498
71755
|
// a caller reaches all of them through the split button (see picker.jsx's JSDoc
|
|
71499
71756
|
// for what each one says).
|
|
71500
|
-
const POPUP_PROP_SET = new Set(["mode", "popupLayer", "popupTestId", "positionArea", "popoverMode", "popoverSpacing", "popupWidthFitContent", "popoverMaxHeight", "dialogMinWidth", "dialogMinHeight", "dialogMaxWidth", "dialogMaxHeight", "dialogExpand", "dialogExpandX", "dialogExpandY", "dockedOnSmallTouchScreen", "marginWithContainer", "backdropVariant", "pointerInteractionOutsideEffect", "escapeEffect", "closeOnFocusOut", "scrollCapture", "focusCapture", "popupBackgroundColor", "popupBorderRadius", "animation"]);
|
|
71757
|
+
const POPUP_PROP_SET = new Set(["mode", "popupLayer", "popupTestId", "positionArea", "popoverMode", "popoverSpacing", "popupWidthFitContent", "popoverMaxHeight", "dialogMinWidth", "dialogMinHeight", "dialogMaxWidth", "dialogMaxHeight", "dialogExpand", "dialogExpandX", "dialogExpandY", "dockedOnSmallTouchScreen", "marginWithContainer", "backdropVariant", "backdropColor", "backdropFilter", "pointerInteractionOutsideEffect", "escapeEffect", "closeOnFocusOut", "scrollCapture", "focusCapture", "popupBackgroundColor", "popupBorderRadius", "animation"]);
|
|
71501
71758
|
const splitPopupProps = props => {
|
|
71502
71759
|
const popupProps = {};
|
|
71503
71760
|
const boxProps = {};
|