@jsenv/dom 0.17.20 → 0.17.21
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_dom.js +157 -40
- package/package.json +1 -1
package/dist/jsenv_dom.js
CHANGED
|
@@ -14363,6 +14363,90 @@ const stickyAsRelativeCoords = (
|
|
|
14363
14363
|
return [leftPosition, topPosition];
|
|
14364
14364
|
};
|
|
14365
14365
|
|
|
14366
|
+
/**
|
|
14367
|
+
* The on-screen keyboard, when the app takes it over.
|
|
14368
|
+
*
|
|
14369
|
+
* By default a mobile browser answers the keyboard by shrinking the VISUAL
|
|
14370
|
+
* viewport, and everything sized against that viewport follows for free —
|
|
14371
|
+
* which is what the whole positioning layer here already relies on (see
|
|
14372
|
+
* pickPositionRelativeTo's own visualViewport reads). The VirtualKeyboard API
|
|
14373
|
+
* (Chromium only — no Firefox, no Safari) offers the other deal:
|
|
14374
|
+
* `overlaysContent = true` and the keyboard stops resizing anything, painting
|
|
14375
|
+
* over the page instead, while its geometry becomes readable — `boundingRect`
|
|
14376
|
+
* and a `geometrychange` event here, `env(keyboard-inset-*)` in CSS.
|
|
14377
|
+
*
|
|
14378
|
+
* That deal has to be taken whole: the instant the viewport stops shrinking,
|
|
14379
|
+
* whoever was sizing against it is sizing against a rectangle the keyboard now
|
|
14380
|
+
* covers. So this module answers ONE question — how many pixels at the bottom
|
|
14381
|
+
* of the visual viewport the keyboard covers — and the positioning layer
|
|
14382
|
+
* subtracts it. The answer is 0 in every other case (unsupported, never opted
|
|
14383
|
+
* in, keyboard closed), which is exactly what makes the two paths one path:
|
|
14384
|
+
* where the browser shrinks the viewport itself, there is nothing left to
|
|
14385
|
+
* subtract.
|
|
14386
|
+
*
|
|
14387
|
+
* Why take the deal at all, then, if the outcome is meant to match? Because a
|
|
14388
|
+
* resizing viewport is a resize of EVERYTHING, whether or not it had anything
|
|
14389
|
+
* to do with the field being typed into — the page reflows, fixed bars move,
|
|
14390
|
+
* and a mobile browser fires that resize transiently as focus goes from one
|
|
14391
|
+
* input to the next. Overlaying leaves the layout alone and hands over a
|
|
14392
|
+
* number instead. So navi takes it by default (see its own index.js) and only
|
|
14393
|
+
* offers a way back out, for an app whose own layout was built around the
|
|
14394
|
+
* viewport shrinking.
|
|
14395
|
+
*/
|
|
14396
|
+
|
|
14397
|
+
const virtualKeyboard = window.navigator.virtualKeyboard;
|
|
14398
|
+
|
|
14399
|
+
/**
|
|
14400
|
+
* Whether the keyboard overlays the content instead of resizing the viewport.
|
|
14401
|
+
* Returns whether it applies at all — false means the browser has no
|
|
14402
|
+
* VirtualKeyboard API and keeps shrinking the visual viewport, which is the
|
|
14403
|
+
* behavior everything here already follows, so there is nothing to report to
|
|
14404
|
+
* the caller beyond "not this way".
|
|
14405
|
+
*/
|
|
14406
|
+
const setVirtualKeyboardOverlaysContent = (value) => {
|
|
14407
|
+
if (!virtualKeyboard) {
|
|
14408
|
+
return false;
|
|
14409
|
+
}
|
|
14410
|
+
virtualKeyboard.overlaysContent = value;
|
|
14411
|
+
return true;
|
|
14412
|
+
};
|
|
14413
|
+
|
|
14414
|
+
/**
|
|
14415
|
+
* How many pixels at the bottom of the visual viewport the keyboard currently
|
|
14416
|
+
* covers — 0 unless the app opted in above AND the keyboard is up.
|
|
14417
|
+
*
|
|
14418
|
+
* `boundingRect` is all-zero when the keyboard is hidden, and also while
|
|
14419
|
+
* `overlaysContent` is false: a keyboard that resized the viewport covers
|
|
14420
|
+
* nothing that is left of it, so the zero is the right answer rather than a
|
|
14421
|
+
* missing one.
|
|
14422
|
+
*/
|
|
14423
|
+
const getVirtualKeyboardOverlayHeight = () => {
|
|
14424
|
+
if (!virtualKeyboard) {
|
|
14425
|
+
return 0;
|
|
14426
|
+
}
|
|
14427
|
+
const { height } = virtualKeyboard.boundingRect;
|
|
14428
|
+
return height > 0 ? height : 0;
|
|
14429
|
+
};
|
|
14430
|
+
|
|
14431
|
+
/**
|
|
14432
|
+
* Calls `callback` whenever the keyboard shows, hides or resizes. Returns an
|
|
14433
|
+
* unsubscribe function; a no-op (never calls back) without support.
|
|
14434
|
+
*
|
|
14435
|
+
* Undebounced on purpose, unlike window/visualViewport resize
|
|
14436
|
+
* (window_size.js): "geometrychange" is not the transient storm those are —
|
|
14437
|
+
* it fires on the keyboard itself changing, not on the layout reacting to it,
|
|
14438
|
+
* which is the whole point of overlaying.
|
|
14439
|
+
*/
|
|
14440
|
+
const subscribeVirtualKeyboardGeometryChange = (callback) => {
|
|
14441
|
+
if (!virtualKeyboard) {
|
|
14442
|
+
return () => {};
|
|
14443
|
+
}
|
|
14444
|
+
virtualKeyboard.addEventListener("geometrychange", callback);
|
|
14445
|
+
return () => {
|
|
14446
|
+
virtualKeyboard.removeEventListener("geometrychange", callback);
|
|
14447
|
+
};
|
|
14448
|
+
};
|
|
14449
|
+
|
|
14366
14450
|
// Both "resize" sources fire transiently on mobile (keyboard/UI chrome
|
|
14367
14451
|
// briefly shifting when focus moves between inputs) — debounced so
|
|
14368
14452
|
// consumers skip that in-between state. One shared timer per source (not
|
|
@@ -14377,17 +14461,29 @@ const [publishVisualViewportResize, subscribeVisualViewportResizeSettled] =
|
|
|
14377
14461
|
createPubSub();
|
|
14378
14462
|
const [publishWindowResize, subscribeWindowResizeSettled] = createPubSub();
|
|
14379
14463
|
|
|
14464
|
+
let visualViewportResizeTimeoutId;
|
|
14465
|
+
const scheduleVisualViewportResize = (event) => {
|
|
14466
|
+
visualViewportResizePending = true;
|
|
14467
|
+
clearTimeout(visualViewportResizeTimeoutId);
|
|
14468
|
+
visualViewportResizeTimeoutId = setTimeout(() => {
|
|
14469
|
+
visualViewportResizePending = false;
|
|
14470
|
+
publishVisualViewportResize(event);
|
|
14471
|
+
}, RESIZE_SETTLE_MS);
|
|
14472
|
+
};
|
|
14380
14473
|
if (window.visualViewport) {
|
|
14381
|
-
|
|
14382
|
-
|
|
14383
|
-
|
|
14384
|
-
|
|
14385
|
-
timeoutId = setTimeout(() => {
|
|
14386
|
-
visualViewportResizePending = false;
|
|
14387
|
-
publishVisualViewportResize(event);
|
|
14388
|
-
}, RESIZE_SETTLE_MS);
|
|
14389
|
-
});
|
|
14474
|
+
window.visualViewport.addEventListener(
|
|
14475
|
+
"resize",
|
|
14476
|
+
scheduleVisualViewportResize,
|
|
14477
|
+
);
|
|
14390
14478
|
}
|
|
14479
|
+
// The same event, said differently: where the keyboard overlays the content
|
|
14480
|
+
// (virtual_keyboard.js) there is no visualViewport resize at all when it
|
|
14481
|
+
// opens — the room left to place anything in changed
|
|
14482
|
+
// all the same, and every consumer here asks the same question either way
|
|
14483
|
+
// (getVisibleViewportRect in visible_rect.js already subtracts it). Through
|
|
14484
|
+
// the same debounce, and for the same reason: going straight from one input
|
|
14485
|
+
// to the next hides and re-shows the keyboard.
|
|
14486
|
+
subscribeVirtualKeyboardGeometryChange(scheduleVisualViewportResize);
|
|
14391
14487
|
|
|
14392
14488
|
let windowResizeTimeoutId;
|
|
14393
14489
|
window.addEventListener("resize", (event) => {
|
|
@@ -14406,6 +14502,39 @@ window.addEventListener("resize", (event) => {
|
|
|
14406
14502
|
}, RESIZE_SETTLE_MS);
|
|
14407
14503
|
});
|
|
14408
14504
|
|
|
14505
|
+
/**
|
|
14506
|
+
* The part of the viewport something can actually be placed in.
|
|
14507
|
+
*
|
|
14508
|
+
* visualViewport, not the layout viewport: only the visual one shrinks when
|
|
14509
|
+
* the on-screen keyboard opens (where the browser is the one shrinking it —
|
|
14510
|
+
* see below). Its offsetLeft/Top matter too, for pinch-zoom/pan.
|
|
14511
|
+
*
|
|
14512
|
+
* document.documentElement.clientWidth/Height is the fallback without
|
|
14513
|
+
* visualViewport support — the layout viewport net of any classic scrollbar,
|
|
14514
|
+
* which is what visualViewport itself reports, unlike window.innerWidth/Height
|
|
14515
|
+
* which counts the scrollbar in. Both readings existed here, one per call
|
|
14516
|
+
* site, for no reason anyone stated; they only ever differed by that scrollbar
|
|
14517
|
+
* and only on browsers with no visualViewport at all.
|
|
14518
|
+
*
|
|
14519
|
+
* The keyboard is then subtracted rather than assumed to have already shrunk
|
|
14520
|
+
* the viewport: with `overlaysContent` (virtual_keyboard.js, navi turns it on)
|
|
14521
|
+
* the viewport stays full height and the keyboard is painted over its bottom.
|
|
14522
|
+
* Zero everywhere else, the browser having done the subtraction itself.
|
|
14523
|
+
*/
|
|
14524
|
+
const getVisibleViewportRect = () => {
|
|
14525
|
+
const visualViewport = window.visualViewport;
|
|
14526
|
+
const documentElement = document.documentElement;
|
|
14527
|
+
const height = visualViewport
|
|
14528
|
+
? visualViewport.height
|
|
14529
|
+
: documentElement.clientHeight;
|
|
14530
|
+
return {
|
|
14531
|
+
left: visualViewport ? visualViewport.offsetLeft : 0,
|
|
14532
|
+
top: visualViewport ? visualViewport.offsetTop : 0,
|
|
14533
|
+
width: visualViewport ? visualViewport.width : documentElement.clientWidth,
|
|
14534
|
+
height: Math.max(0, height - getVirtualKeyboardOverlayHeight()),
|
|
14535
|
+
};
|
|
14536
|
+
};
|
|
14537
|
+
|
|
14409
14538
|
// Minimum fraction of element width/height that must be visible on the preferred side
|
|
14410
14539
|
// before flipping to the opposite side. Prevents flickering near the flip threshold.
|
|
14411
14540
|
const MIN_CONTENT_VISIBILITY_RATIO = 0.6;
|
|
@@ -14528,23 +14657,17 @@ const visibleRectEffect = (
|
|
|
14528
14657
|
const UNSET_EVENT = { type: "unset" };
|
|
14529
14658
|
const check = (event = UNSET_EVENT) => {
|
|
14530
14659
|
|
|
14531
|
-
//
|
|
14532
|
-
//
|
|
14533
|
-
// pickPositionRelativeTo's
|
|
14534
|
-
//
|
|
14535
|
-
//
|
|
14536
|
-
|
|
14537
|
-
|
|
14538
|
-
|
|
14539
|
-
|
|
14540
|
-
|
|
14541
|
-
|
|
14542
|
-
: window.innerWidth;
|
|
14543
|
-
const viewportHeight = visualViewport
|
|
14544
|
-
? visualViewport.height
|
|
14545
|
-
: window.innerHeight;
|
|
14546
|
-
const viewportOffsetLeft = visualViewport ? visualViewport.offsetLeft : 0;
|
|
14547
|
-
const viewportOffsetTop = visualViewport ? visualViewport.offsetTop : 0;
|
|
14660
|
+
// Computed here regardless of scroll container (not just where the
|
|
14661
|
+
// non-document branch below needs it) because a keyboard opening can
|
|
14662
|
+
// change pickPositionRelativeTo's available space without moving this
|
|
14663
|
+
// element's own visibleRect at all — see viewportRectChanged further
|
|
14664
|
+
// down.
|
|
14665
|
+
const {
|
|
14666
|
+
left: viewportOffsetLeft,
|
|
14667
|
+
top: viewportOffsetTop,
|
|
14668
|
+
width: viewportWidth,
|
|
14669
|
+
height: viewportHeight,
|
|
14670
|
+
} = getVisibleViewportRect();
|
|
14548
14671
|
|
|
14549
14672
|
// 1. Calculate element position relative to scrollable parent
|
|
14550
14673
|
const { scrollLeft, scrollTop } = scrollContainer;
|
|
@@ -15401,19 +15524,13 @@ const pickPositionRelativeTo = (
|
|
|
15401
15524
|
container,
|
|
15402
15525
|
} = {},
|
|
15403
15526
|
) => {
|
|
15404
|
-
// Needed before hasValidAnchor below.
|
|
15405
|
-
|
|
15406
|
-
|
|
15407
|
-
|
|
15408
|
-
|
|
15409
|
-
|
|
15410
|
-
|
|
15411
|
-
: document.documentElement.clientWidth;
|
|
15412
|
-
const viewportHeight = visualViewport
|
|
15413
|
-
? visualViewport.height
|
|
15414
|
-
: document.documentElement.clientHeight;
|
|
15415
|
-
const viewportLeft = visualViewport ? visualViewport.offsetLeft : 0;
|
|
15416
|
-
const viewportTop = visualViewport ? visualViewport.offsetTop : 0;
|
|
15527
|
+
// Needed before hasValidAnchor below.
|
|
15528
|
+
const {
|
|
15529
|
+
left: viewportLeft,
|
|
15530
|
+
top: viewportTop,
|
|
15531
|
+
width: viewportWidth,
|
|
15532
|
+
height: viewportHeight,
|
|
15533
|
+
} = getVisibleViewportRect();
|
|
15417
15534
|
|
|
15418
15535
|
// Resolved early: everything below that would otherwise reach for
|
|
15419
15536
|
// viewportLeft/Top/Width/Height instead uses these, so a "local" popover
|
|
@@ -19406,4 +19523,4 @@ const useResizeStatus = (elementRef, { as = "number" } = {}) => {
|
|
|
19406
19523
|
};
|
|
19407
19524
|
};
|
|
19408
19525
|
|
|
19409
|
-
export { EASING, ELEMENT_SIZE_CHANGE, activeElementSignal, addActiveElementEffect, addAttributeEffect, allowWheelThrough, appendStyles, applyNewPosition, canScroll, captureScrollState, chainEvent, claimWheelGesture, closestOpenableAncestor, contrastColor, createBackgroundColorTransition, createBackgroundTransition, createBorderRadiusTransition, createBorderTransition, createDragGestureController, createDragToMoveGestureController, createEventGroupLogger, createGroupTransitionController, createHeightTransition, createIterableWeakSet, createOpacityTransition, createPubSub, createStyleController, createTimelineTransition, createTransition, createTranslateXTransition, createValueEffect, createWidthTransition, cubicBezier, dispatchCustomEvent, dispatchInternalCustomEvent, dispatchPublicCustomEvent, dragAfterIntent, elementIsFocusable, elementIsVisibleForFocus, elementIsVisuallyVisible, findAfter, findAncestor, findBefore, findDescendant, findEvent, findFocusDelegateTarget, findFocusable, findSelfOrAncestorFixedPosition, formatEventSideEffect, getAncestorOpenType, getAvailableHeight, getAvailableWidth, getBackground, getBackgroundColor, getBorder, getBorderRadius, getBorderSizes, getContrastRatio, getDefaultStyles, getDragCoordinates, getDropTargetInfo, getElementSignature, getFirstVisuallyVisibleAncestor, getFocusVisibilityInfo, getHeight, getHeightWithoutTransition, getInnerHeight, getInnerWidth, getKeyboardEventDefaultAction, getLuminance, getMarginSizes, getMaxHeight, getMaxWidth, getMinHeight, getMinWidth, getOpacity, getOpacityWithoutTransition, getPaddingSizes, getPositionedParent, getPositioningScrollOffset, getPreferedColorScheme, getScrollBox, getScrollContainer, getScrollContainerSet, getScrollRelativeRect, getSelfAndAncestorScrolls, getStyle, getTranslateX, getTranslateXWithoutTransition, getTranslateY, getVisuallyVisibleInfo, getWidth, getWidthWithoutTransition, hasCSSSizeUnit, initFlexDetailsSet, initFocusGroup, initPositionSticky, isAncestorOpen, isPrimaryButtonEvent, isSameColor, isScrollable, markDragSource, measureLongestVisualLineWidth, measureScrollbar, measureWidestChildRow, mergeOneStyle, mergeTwoStyles, normalizeKeyboardKey, normalizeStyle, normalizeStyles, observeAncestorOpenState, onAncestorReopen, parsePositionArea, parseStyle, performTabNavigation, pickPositionRelativeTo, prefersDarkColors, prefersLightColors, preventFocusNav, preventFocusNavViaKeyboard, preventIntermediateScrollbar, releaseWheelGesture, resolveCSSColor, resolveCSSSize, resolveColorLuminance, resolveOklchLightness, scrollIntoViewScoped, scrollIntoViewWithStickyAwareness, scrollRoomTowards, setAttribute, setAttributes, setStyles, snapToPixel, startDragTo, startDragToResizeGesture, startDragToTravel, stickyAsRelativeCoords, stringifyStyle, subscribeVisualViewportResizeSettled, subscribeWindowResizeSettled, suppressClickAfterGesture, trapFocusInside, trapScrollInside, useActiveElement, useAvailableHeight, useAvailableWidth, useMaxHeight, useMaxWidth, useResizeStatus, visibleRectEffect, waitForPressHeld, watchWheelTravel, wheelGestureIsTakenFrom };
|
|
19526
|
+
export { EASING, ELEMENT_SIZE_CHANGE, activeElementSignal, addActiveElementEffect, addAttributeEffect, allowWheelThrough, appendStyles, applyNewPosition, canScroll, captureScrollState, chainEvent, claimWheelGesture, closestOpenableAncestor, contrastColor, createBackgroundColorTransition, createBackgroundTransition, createBorderRadiusTransition, createBorderTransition, createDragGestureController, createDragToMoveGestureController, createEventGroupLogger, createGroupTransitionController, createHeightTransition, createIterableWeakSet, createOpacityTransition, createPubSub, createStyleController, createTimelineTransition, createTransition, createTranslateXTransition, createValueEffect, createWidthTransition, cubicBezier, dispatchCustomEvent, dispatchInternalCustomEvent, dispatchPublicCustomEvent, dragAfterIntent, elementIsFocusable, elementIsVisibleForFocus, elementIsVisuallyVisible, findAfter, findAncestor, findBefore, findDescendant, findEvent, findFocusDelegateTarget, findFocusable, findSelfOrAncestorFixedPosition, formatEventSideEffect, getAncestorOpenType, getAvailableHeight, getAvailableWidth, getBackground, getBackgroundColor, getBorder, getBorderRadius, getBorderSizes, getContrastRatio, getDefaultStyles, getDragCoordinates, getDropTargetInfo, getElementSignature, getFirstVisuallyVisibleAncestor, getFocusVisibilityInfo, getHeight, getHeightWithoutTransition, getInnerHeight, getInnerWidth, getKeyboardEventDefaultAction, getLuminance, getMarginSizes, getMaxHeight, getMaxWidth, getMinHeight, getMinWidth, getOpacity, getOpacityWithoutTransition, getPaddingSizes, getPositionedParent, getPositioningScrollOffset, getPreferedColorScheme, getScrollBox, getScrollContainer, getScrollContainerSet, getScrollRelativeRect, getSelfAndAncestorScrolls, getStyle, getTranslateX, getTranslateXWithoutTransition, getTranslateY, getVirtualKeyboardOverlayHeight, getVisuallyVisibleInfo, getWidth, getWidthWithoutTransition, hasCSSSizeUnit, initFlexDetailsSet, initFocusGroup, initPositionSticky, isAncestorOpen, isPrimaryButtonEvent, isSameColor, isScrollable, markDragSource, measureLongestVisualLineWidth, measureScrollbar, measureWidestChildRow, mergeOneStyle, mergeTwoStyles, normalizeKeyboardKey, normalizeStyle, normalizeStyles, observeAncestorOpenState, onAncestorReopen, parsePositionArea, parseStyle, performTabNavigation, pickPositionRelativeTo, prefersDarkColors, prefersLightColors, preventFocusNav, preventFocusNavViaKeyboard, preventIntermediateScrollbar, releaseWheelGesture, resolveCSSColor, resolveCSSSize, resolveColorLuminance, resolveOklchLightness, scrollIntoViewScoped, scrollIntoViewWithStickyAwareness, scrollRoomTowards, setAttribute, setAttributes, setStyles, setVirtualKeyboardOverlaysContent, snapToPixel, startDragTo, startDragToResizeGesture, startDragToTravel, stickyAsRelativeCoords, stringifyStyle, subscribeVirtualKeyboardGeometryChange, subscribeVisualViewportResizeSettled, subscribeWindowResizeSettled, suppressClickAfterGesture, trapFocusInside, trapScrollInside, useActiveElement, useAvailableHeight, useAvailableWidth, useMaxHeight, useMaxWidth, useResizeStatus, visibleRectEffect, waitForPressHeld, watchWheelTravel, wheelGestureIsTakenFrom };
|