@@ -7522,17 +7522,50 @@ const getScrollbarState = (
75227522 * @param {Element} [options.container] - The scroll container to scroll. Defaults to getScrollContainer(el).
75237523 * @param {"start"|"center"|"end"|"nearest"} [options.block="nearest"] - Vertical alignment.
75247524 * @param {"start"|"center"|"end"|"nearest"} [options.inline="nearest"] - Horizontal alignment.
7525+ * @param {"auto"|"instant"|"smooth"} [options.behavior] - Left out, the container's CSS scroll-behavior decides; "instant" is for a caller that measures the result in the same tick.
75257526 */
75267527const scrollIntoViewScoped = (
75277528 el,
7528- { container = getScrollContainer(el), ...rest } = {},
7529+ { container = getScrollContainer(el), behavior, ...rest } = {},
75297530) => {
75307531 if (!container) {
75317532 return;
75327533 }
7533- container.scrollTo(
7534- getScrollIntoViewScopedOffsets(el, { container, ...rest }),
7535- );
7534+ container.scrollTo({
7535+ behavior,
7536+ ...getScrollIntoViewScopedOffsets(el, { container, ...rest }),
7537+ });
7538+ };
7539+
7540+ /**
7541+ * Scrolls `el` into view in every scroll container between it and the
7542+ * document, innermost first — the chain `Element.prototype.scrollIntoView`
7543+ * walks, minus the boxes nobody can scroll back.
7544+ *
7545+ * `overflow: hidden` is the one that matters: it IS a scroll container, so
7546+ * the native call spends scroll on it as readily as on any other, and there
7547+ * it is spent for good — no scrollbar, no wheel, no touch gives it back. A
7548+ * card clipping a drawing, holding something that overlaps its edge by 2px,
7549+ * ends up 2px off until it re-renders. Only the containers `isScrollable`
7550+ * recognizes on its own (without `includeHidden`) are moved; the ones that
7551+ * merely clip are left where they are.
7552+ *
7553+ * Each container measures `el` where the inner ones just put it, so the outer
7554+ * ones see the final position rather than the one they started from.
7555+ *
7556+ * @param {Element} el - The element to scroll into view.
7557+ * @param {object} options - the same as scrollIntoViewScoped's, minus container.
7558+ */
7559+ const scrollIntoViewThroughScrollables = (el, options) => {
7560+ for (const scrollContainer of getScrollContainerSet(el)) {
7561+ // getScrollContainerSet already skips what only clips, except at the end
7562+ // of the chain: with nothing scrollable left to find it hands back the
7563+ // document scroller, which a scroll lock may have turned into a clip too.
7564+ if (!isScrollable(scrollContainer)) {
7565+ continue;
7566+ }
7567+ scrollIntoViewScoped(el, { ...options, container: scrollContainer });
7568+ }
75367569};
75377570
75387571/**
@@ -7554,7 +7587,6 @@ const getScrollIntoViewScopedOffsets = (
75547587 inline = "nearest",
75557588 } = {},
75567589) => {
7557- const containerRect = container.getBoundingClientRect();
75587590 const elRect = el.getBoundingClientRect();
75597591 const style = getComputedStyle(el);
75607592
@@ -7565,15 +7597,35 @@ const getScrollIntoViewScopedOffsets = (
75657597
75667598 const currentScrollTop = container.scrollTop;
75677599 const currentScrollLeft = container.scrollLeft;
7568- const containerHeight = containerRect.height;
7569- const containerWidth = containerRect.width;
7600+
7601+ // Where the container shows its content, in the coordinates
7602+ // getBoundingClientRect speaks. The document scroller is a case apart: what
7603+ // it shows is the viewport, sitting at the origin of those coordinates,
7604+ // while its own box is the whole page and travels with the scroll — reading
7605+ // that box would count the scroll twice and compare the element to the
7606+ // height of the document rather than the height of the screen.
7607+ let containerTop;
7608+ let containerLeft;
7609+ let containerHeight;
7610+ let containerWidth;
7611+ if (container === container.ownerDocument.scrollingElement) {
7612+ containerTop = 0;
7613+ containerLeft = 0;
7614+ containerHeight = container.clientHeight;
7615+ containerWidth = container.clientWidth;
7616+ } else {
7617+ const containerRect = container.getBoundingClientRect();
7618+ containerTop = containerRect.top;
7619+ containerLeft = containerRect.left;
7620+ containerHeight = containerRect.height;
7621+ containerWidth = containerRect.width;
7622+ }
75707623
75717624 // Element position relative to the container's scroll origin.
7572- const elTop =
7573- elRect.top - containerRect.top + currentScrollTop - scrollMarginTop;
7625+ const elTop = elRect.top - containerTop + currentScrollTop - scrollMarginTop;
75747626 const elBottom = elTop + elRect.height + scrollMarginTop + scrollMarginBottom;
75757627 const elLeft =
7576- elRect.left - containerRect.left + currentScrollLeft - scrollMarginLeft;
7628+ elRect.left - containerLeft + currentScrollLeft - scrollMarginLeft;
75777629 const elRight = elLeft + elRect.width + scrollMarginLeft + scrollMarginRight;
75787630
75797631 let newScrollTop = currentScrollTop;
@@ -9455,6 +9507,14 @@ installImportMetaCssBuild(import.meta);/**
94559507 * A tap is left alone by that: a press that goes nowhere is still a press, which
94569508 * is what a piece that is also a link or a card needs.
94579509 *
9510+ * A HOLD is not, and nothing in such a place is text to select. Taking the wait
9511+ * away takes away the only thing that answered a finger held still, so the
9512+ * browser answers it alone: its own long press selects the word under the thumb,
9513+ * and the card the hand meant to carry is left blue and handled. Said to every
9514+ * pointer — a mouse there drags from the first few pixels, so a selection begun
9515+ * there is one that could never be finished either. What says its press is its
9516+ * own keeps its text (see the stylesheet below).
9517+ *
94589518 * It is opt-in and cannot be anything else. Nothing here can see whether the
94599519 * surroundings scroll — a page scrolls by default, an overflow is one CSS
94609520 * property away, and getting it wrong the wrong way means the list runs away
@@ -9499,6 +9559,11 @@ const css$4 = /* css */`[data-drag-handle], [data-drag-source] {
94999559
95009560[data-drag-on-contact] [data-drag-source], [data-drag-source][data-drag-on-contact] {
95019561 touch-action: pinch-zoom;
9562+ user-select: none;
9563+ }
9564+
9565+ [data-drag-on-contact] [data-drag-ignore], [data-drag-on-contact] [popover], [data-drag-on-contact] dialog, [data-drag-on-contact] :is(input:not([data-press-only]), textarea), [data-drag-on-contact] :is([contenteditable=""], [contenteditable="true"]) {
9566+ user-select: text;
95029567}
95039568
95049569[data-drag-ignore], [data-self-interactions~="drag"], [data-self-interactions~="*"], [data-drag-source] [popover], [data-drag-source] dialog {
@@ -20174,4 +20239,4 @@ const useResizeStatus = (elementRef, { as = "number" } = {}) => {
2017420239 };
2017520240};
2017620241
20177- export { EASING, ELEMENT_SIZE_CHANGE, activeElementSignal, addActiveElementEffect, addAttributeEffect, allowWheelThrough, appendStyles, applyNewPosition, canScroll, captureScrollState, chainEvent, claimWheelGesture, clickIsSuppressed, 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, getScrollIntoViewScopedOffsets, getScrollRelativeRect, getSelfAndAncestorScrolls, getStyle, getTranslateX, getTranslateXWithoutTransition, getTranslateY, getVirtualKeyboardOverlayHeight, getVisuallyVisibleInfo, getWidth, getWidthWithoutTransition, hasCSSSizeUnit, initFlexDetailsSet, initFocusGroup, initPositionSticky, isAncestorOpen, isDisplayedDespiteClosedAncestor, isPressDisputedByDrag, isPrimaryButtonEvent, isSameColor, isScrollable, isTouchDrivenEvent, 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 };
20242+ export { EASING, ELEMENT_SIZE_CHANGE, activeElementSignal, addActiveElementEffect, addAttributeEffect, allowWheelThrough, appendStyles, applyNewPosition, canScroll, captureScrollState, chainEvent, claimWheelGesture, clickIsSuppressed, 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, getScrollIntoViewScopedOffsets, getScrollRelativeRect, getSelfAndAncestorScrolls, getStyle, getTranslateX, getTranslateXWithoutTransition, getTranslateY, getVirtualKeyboardOverlayHeight, getVisuallyVisibleInfo, getWidth, getWidthWithoutTransition, hasCSSSizeUnit, initFlexDetailsSet, initFocusGroup, initPositionSticky, isAncestorOpen, isDisplayedDespiteClosedAncestor, isPressDisputedByDrag, isPrimaryButtonEvent, isSameColor, isScrollable, isTouchDrivenEvent, 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, scrollIntoViewThroughScrollables, 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 };
0 commit comments