framer-motion 12.24.10 → 12.24.12

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.
@@ -1 +1 @@
1
- {"version":3,"file":"VisualElementDragControls.mjs","sources":["../../../../src/gestures/drag/VisualElementDragControls.ts"],"sourcesContent":["import {\n isElementKeyboardAccessible,\n PanInfo,\n ResolvedConstraints,\n Transition,\n frame,\n mixNumber,\n percent,\n setDragLock,\n} from \"motion-dom\"\nimport { Axis, Point, invariant } from \"motion-utils\"\nimport { animateMotionValue } from \"../../animation/interfaces/motion-value\"\nimport { addDomEvent } from \"../../events/add-dom-event\"\nimport { addPointerEvent } from \"../../events/add-pointer-event\"\nimport { extractEventInfo } from \"../../events/event-info\"\nimport { MotionProps } from \"../../motion/types\"\nimport {\n convertBoundingBoxToBox,\n convertBoxToBoundingBox,\n} from \"../../projection/geometry/conversion\"\nimport { calcLength } from \"../../projection/geometry/delta-calc\"\nimport { createBox } from \"../../projection/geometry/models\"\nimport { LayoutUpdateData } from \"../../projection/node/types\"\nimport { eachAxis } from \"../../projection/utils/each-axis\"\nimport { measurePageBox } from \"../../projection/utils/measure\"\nimport type { VisualElement } from \"../../render/VisualElement\"\nimport { getContextWindow } from \"../../utils/get-context-window\"\nimport { isRefObject } from \"../../utils/is-ref-object\"\nimport { addValueToWillChange } from \"../../value/use-will-change/add-will-change\"\nimport { PanSession } from \"../pan/PanSession\"\nimport {\n applyConstraints,\n calcOrigin,\n calcRelativeConstraints,\n calcViewportConstraints,\n defaultElastic,\n rebaseAxisConstraints,\n resolveDragElastic,\n} from \"./utils/constraints\"\n\nexport const elementDragControls = new WeakMap<\n VisualElement,\n VisualElementDragControls\n>()\n\nexport interface DragControlOptions {\n /**\n * This distance after which dragging starts and a direction is locked in.\n *\n * @public\n */\n distanceThreshold?: number\n\n /**\n * Whether to immediately snap to the cursor when dragging starts.\n *\n * @public\n */\n snapToCursor?: boolean\n}\n\ntype DragDirection = \"x\" | \"y\"\n\nexport class VisualElementDragControls {\n private visualElement: VisualElement<HTMLElement>\n\n private panSession?: PanSession\n\n private openDragLock: VoidFunction | null = null\n\n isDragging = false\n private currentDirection: DragDirection | null = null\n\n private originPoint: Point = { x: 0, y: 0 }\n\n /**\n * The permitted boundaries of travel, in pixels.\n */\n private constraints: ResolvedConstraints | false = false\n\n private hasMutatedConstraints = false\n\n /**\n * The per-axis resolved elastic values.\n */\n private elastic = createBox()\n\n /**\n * The latest pointer event. Used as fallback when the `cancel` and `stop` functions are called without arguments.\n */\n private latestPointerEvent: PointerEvent | null = null\n\n /**\n * The latest pan info. Used as fallback when the `cancel` and `stop` functions are called without arguments.\n */\n private latestPanInfo: PanInfo | null = null\n\n constructor(visualElement: VisualElement<HTMLElement>) {\n this.visualElement = visualElement\n }\n\n start(\n originEvent: PointerEvent,\n { snapToCursor = false, distanceThreshold }: DragControlOptions = {}\n ) {\n /**\n * Don't start dragging if this component is exiting\n */\n const { presenceContext } = this.visualElement\n if (presenceContext && presenceContext.isPresent === false) return\n\n const onSessionStart = (event: PointerEvent) => {\n // Stop or pause animations based on context:\n // - snapToCursor: stop because we'll set new position values\n // - otherwise: pause to allow resume if no drag starts (for constraint animations)\n if (snapToCursor) {\n this.stopAnimation()\n this.snapToCursor(extractEventInfo(event).point)\n } else {\n this.pauseAnimation()\n }\n }\n\n const onStart = (event: PointerEvent, info: PanInfo) => {\n // Stop any paused animation so motion values reflect true current position\n // (pauseAnimation was called in onSessionStart to allow resume if no drag started)\n this.stopAnimation()\n\n // Attempt to grab the global drag gesture lock - maybe make this part of PanSession\n const { drag, dragPropagation, onDragStart } = this.getProps()\n\n if (drag && !dragPropagation) {\n if (this.openDragLock) this.openDragLock()\n\n this.openDragLock = setDragLock(drag)\n\n // If we don 't have the lock, don't start dragging\n if (!this.openDragLock) return\n }\n\n this.latestPointerEvent = event\n this.latestPanInfo = info\n this.isDragging = true\n\n this.currentDirection = null\n\n this.resolveConstraints()\n\n if (this.visualElement.projection) {\n this.visualElement.projection.isAnimationBlocked = true\n this.visualElement.projection.target = undefined\n }\n\n /**\n * Record gesture origin\n */\n eachAxis((axis) => {\n let current = this.getAxisMotionValue(axis).get() || 0\n\n /**\n * If the MotionValue is a percentage value convert to px\n */\n if (percent.test(current)) {\n const { projection } = this.visualElement\n\n if (projection && projection.layout) {\n const measuredAxis = projection.layout.layoutBox[axis]\n\n if (measuredAxis) {\n const length = calcLength(measuredAxis)\n current = length * (parseFloat(current) / 100)\n }\n }\n }\n\n this.originPoint[axis] = current\n })\n\n // Fire onDragStart event\n if (onDragStart) {\n frame.postRender(() => onDragStart(event, info))\n }\n\n addValueToWillChange(this.visualElement, \"transform\")\n\n const { animationState } = this.visualElement\n animationState && animationState.setActive(\"whileDrag\", true)\n }\n\n const onMove = (event: PointerEvent, info: PanInfo) => {\n this.latestPointerEvent = event\n this.latestPanInfo = info\n\n const {\n dragPropagation,\n dragDirectionLock,\n onDirectionLock,\n onDrag,\n } = this.getProps()\n\n // If we didn't successfully receive the gesture lock, early return.\n if (!dragPropagation && !this.openDragLock) return\n\n const { offset } = info\n // Attempt to detect drag direction if directionLock is true\n if (dragDirectionLock && this.currentDirection === null) {\n this.currentDirection = getCurrentDirection(offset)\n\n // If we've successfully set a direction, notify listener\n if (this.currentDirection !== null) {\n onDirectionLock && onDirectionLock(this.currentDirection)\n }\n\n return\n }\n\n // Update each point with the latest position\n this.updateAxis(\"x\", info.point, offset)\n this.updateAxis(\"y\", info.point, offset)\n\n /**\n * Ideally we would leave the renderer to fire naturally at the end of\n * this frame but if the element is about to change layout as the result\n * of a re-render we want to ensure the browser can read the latest\n * bounding box to ensure the pointer and element don't fall out of sync.\n */\n this.visualElement.render()\n\n /**\n * This must fire after the render call as it might trigger a state\n * change which itself might trigger a layout update.\n */\n onDrag && onDrag(event, info)\n }\n\n const onSessionEnd = (event: PointerEvent, info: PanInfo) => {\n this.latestPointerEvent = event\n this.latestPanInfo = info\n\n this.stop(event, info)\n\n this.latestPointerEvent = null\n this.latestPanInfo = null\n }\n\n const resumeAnimation = () =>\n eachAxis(\n (axis) =>\n this.getAnimationState(axis) === \"paused\" &&\n this.getAxisMotionValue(axis).animation?.play()\n )\n\n const { dragSnapToOrigin } = this.getProps()\n this.panSession = new PanSession(\n originEvent,\n {\n onSessionStart,\n onStart,\n onMove,\n onSessionEnd,\n resumeAnimation,\n },\n {\n transformPagePoint: this.visualElement.getTransformPagePoint(),\n dragSnapToOrigin,\n distanceThreshold,\n contextWindow: getContextWindow(this.visualElement),\n }\n )\n }\n\n /**\n * @internal\n */\n stop(event?: PointerEvent, panInfo?: PanInfo) {\n const finalEvent = event || this.latestPointerEvent\n const finalPanInfo = panInfo || this.latestPanInfo\n\n const isDragging = this.isDragging\n this.cancel()\n if (!isDragging || !finalPanInfo || !finalEvent) return\n\n const { velocity } = finalPanInfo\n this.startAnimation(velocity)\n\n const { onDragEnd } = this.getProps()\n if (onDragEnd) {\n frame.postRender(() => onDragEnd(finalEvent, finalPanInfo))\n }\n }\n\n /**\n * @internal\n */\n cancel() {\n this.isDragging = false\n\n const { projection, animationState } = this.visualElement\n\n if (projection) {\n projection.isAnimationBlocked = false\n }\n\n this.panSession && this.panSession.end()\n this.panSession = undefined\n\n const { dragPropagation } = this.getProps()\n\n if (!dragPropagation && this.openDragLock) {\n this.openDragLock()\n this.openDragLock = null\n }\n\n animationState && animationState.setActive(\"whileDrag\", false)\n }\n\n private updateAxis(axis: DragDirection, _point: Point, offset?: Point) {\n const { drag } = this.getProps()\n\n // If we're not dragging this axis, do an early return.\n if (!offset || !shouldDrag(axis, drag, this.currentDirection)) return\n\n const axisValue = this.getAxisMotionValue(axis)\n let next = this.originPoint[axis] + offset[axis]\n\n // Apply constraints\n if (this.constraints && this.constraints[axis]) {\n next = applyConstraints(\n next,\n this.constraints[axis],\n this.elastic[axis]\n )\n }\n\n axisValue.set(next)\n }\n\n private resolveConstraints() {\n const { dragConstraints, dragElastic } = this.getProps()\n\n const layout =\n this.visualElement.projection &&\n !this.visualElement.projection.layout\n ? this.visualElement.projection.measure(false)\n : this.visualElement.projection?.layout\n\n const prevConstraints = this.constraints\n\n if (dragConstraints && isRefObject(dragConstraints)) {\n if (!this.constraints) {\n this.constraints = this.resolveRefConstraints()\n }\n } else {\n if (dragConstraints && layout) {\n this.constraints = calcRelativeConstraints(\n layout.layoutBox,\n dragConstraints\n )\n } else {\n this.constraints = false\n }\n }\n\n this.elastic = resolveDragElastic(dragElastic)\n\n /**\n * If we're outputting to external MotionValues, we want to rebase the measured constraints\n * from viewport-relative to component-relative.\n */\n if (\n prevConstraints !== this.constraints &&\n layout &&\n this.constraints &&\n !this.hasMutatedConstraints\n ) {\n eachAxis((axis) => {\n if (\n this.constraints !== false &&\n this.getAxisMotionValue(axis)\n ) {\n this.constraints[axis] = rebaseAxisConstraints(\n layout.layoutBox[axis],\n this.constraints[axis]\n )\n }\n })\n }\n }\n\n private resolveRefConstraints() {\n const { dragConstraints: constraints, onMeasureDragConstraints } =\n this.getProps()\n if (!constraints || !isRefObject(constraints)) return false\n\n const constraintsElement = constraints.current as HTMLElement\n\n invariant(\n constraintsElement !== null,\n \"If `dragConstraints` is set as a React ref, that ref must be passed to another component's `ref` prop.\",\n \"drag-constraints-ref\"\n )\n\n const { projection } = this.visualElement\n\n // TODO\n if (!projection || !projection.layout) return false\n\n const constraintsBox = measurePageBox(\n constraintsElement,\n projection.root!,\n this.visualElement.getTransformPagePoint()\n )\n\n let measuredConstraints = calcViewportConstraints(\n projection.layout.layoutBox,\n constraintsBox\n )\n\n /**\n * If there's an onMeasureDragConstraints listener we call it and\n * if different constraints are returned, set constraints to that\n */\n if (onMeasureDragConstraints) {\n const userConstraints = onMeasureDragConstraints(\n convertBoxToBoundingBox(measuredConstraints)\n )\n\n this.hasMutatedConstraints = !!userConstraints\n\n if (userConstraints) {\n measuredConstraints = convertBoundingBoxToBox(userConstraints)\n }\n }\n\n return measuredConstraints\n }\n\n private startAnimation(velocity: Point) {\n const {\n drag,\n dragMomentum,\n dragElastic,\n dragTransition,\n dragSnapToOrigin,\n onDragTransitionEnd,\n } = this.getProps()\n\n const constraints: Partial<ResolvedConstraints> = this.constraints || {}\n\n const momentumAnimations = eachAxis((axis) => {\n if (!shouldDrag(axis, drag, this.currentDirection)) {\n return\n }\n\n let transition = (constraints && constraints[axis]) || {}\n\n if (dragSnapToOrigin) transition = { min: 0, max: 0 }\n\n /**\n * Overdamp the boundary spring if `dragElastic` is disabled. There's still a frame\n * of spring animations so we should look into adding a disable spring option to `inertia`.\n * We could do something here where we affect the `bounceStiffness` and `bounceDamping`\n * using the value of `dragElastic`.\n */\n const bounceStiffness = dragElastic ? 200 : 1000000\n const bounceDamping = dragElastic ? 40 : 10000000\n\n const inertia: Transition = {\n type: \"inertia\",\n velocity: dragMomentum ? velocity[axis] : 0,\n bounceStiffness,\n bounceDamping,\n timeConstant: 750,\n restDelta: 1,\n restSpeed: 10,\n ...dragTransition,\n ...transition,\n }\n\n // If we're not animating on an externally-provided `MotionValue` we can use the\n // component's animation controls which will handle interactions with whileHover (etc),\n // otherwise we just have to animate the `MotionValue` itself.\n return this.startAxisValueAnimation(axis, inertia)\n })\n\n // Run all animations and then resolve the new drag constraints.\n return Promise.all(momentumAnimations).then(onDragTransitionEnd)\n }\n\n private startAxisValueAnimation(\n axis: DragDirection,\n transition: Transition\n ) {\n const axisValue = this.getAxisMotionValue(axis)\n\n addValueToWillChange(this.visualElement, axis)\n\n return axisValue.start(\n animateMotionValue(\n axis,\n axisValue,\n 0,\n transition,\n this.visualElement,\n false\n )\n )\n }\n\n private stopAnimation() {\n eachAxis((axis) => this.getAxisMotionValue(axis).stop())\n }\n\n private pauseAnimation() {\n eachAxis((axis) => this.getAxisMotionValue(axis).animation?.pause())\n }\n\n private getAnimationState(axis: DragDirection) {\n return this.getAxisMotionValue(axis).animation?.state\n }\n\n /**\n * Drag works differently depending on which props are provided.\n *\n * - If _dragX and _dragY are provided, we output the gesture delta directly to those motion values.\n * - Otherwise, we apply the delta to the x/y motion values.\n */\n private getAxisMotionValue(axis: DragDirection) {\n const dragKey =\n `_drag${axis.toUpperCase()}` as `_drag${Uppercase<DragDirection>}`\n const props = this.visualElement.getProps()\n const externalMotionValue = props[dragKey]\n\n return externalMotionValue\n ? externalMotionValue\n : this.visualElement.getValue(\n axis,\n (props.initial\n ? props.initial[axis as keyof typeof props.initial]\n : undefined) || 0\n )\n }\n\n private snapToCursor(point: Point) {\n eachAxis((axis) => {\n const { drag } = this.getProps()\n\n // If we're not dragging this axis, do an early return.\n if (!shouldDrag(axis, drag, this.currentDirection)) return\n\n const { projection } = this.visualElement\n const axisValue = this.getAxisMotionValue(axis)\n\n if (projection && projection.layout) {\n const { min, max } = projection.layout.layoutBox[axis]\n\n /**\n * The layout measurement includes the current transform value,\n * so we need to add it back to get the correct snap position.\n * This fixes an issue where elements with initial coordinates\n * would snap to the wrong position on the first drag.\n */\n const current = axisValue.get() || 0\n\n axisValue.set(point[axis] - mixNumber(min, max, 0.5) + current)\n }\n })\n }\n\n /**\n * When the viewport resizes we want to check if the measured constraints\n * have changed and, if so, reposition the element within those new constraints\n * relative to where it was before the resize.\n */\n scalePositionWithinConstraints() {\n if (!this.visualElement.current) return\n\n const { drag, dragConstraints } = this.getProps()\n const { projection } = this.visualElement\n if (!isRefObject(dragConstraints) || !projection || !this.constraints)\n return\n\n /**\n * Stop current animations as there can be visual glitching if we try to do\n * this mid-animation\n */\n this.stopAnimation()\n\n /**\n * Record the relative position of the dragged element relative to the\n * constraints box and save as a progress value.\n */\n const boxProgress = { x: 0, y: 0 }\n eachAxis((axis) => {\n const axisValue = this.getAxisMotionValue(axis)\n if (axisValue && this.constraints !== false) {\n const latest = axisValue.get()\n boxProgress[axis] = calcOrigin(\n { min: latest, max: latest },\n this.constraints[axis] as Axis\n )\n }\n })\n\n /**\n * Update the layout of this element and resolve the latest drag constraints\n */\n const { transformTemplate } = this.visualElement.getProps()\n this.visualElement.current.style.transform = transformTemplate\n ? transformTemplate({}, \"\")\n : \"none\"\n projection.root && projection.root.updateScroll()\n projection.updateLayout()\n this.resolveConstraints()\n\n /**\n * For each axis, calculate the current progress of the layout axis\n * within the new constraints.\n */\n eachAxis((axis) => {\n if (!shouldDrag(axis, drag, null)) return\n\n /**\n * Calculate a new transform based on the previous box progress\n */\n const axisValue = this.getAxisMotionValue(axis)\n const { min, max } = (this.constraints as ResolvedConstraints)[\n axis\n ] as Axis\n axisValue.set(mixNumber(min, max, boxProgress[axis]))\n })\n }\n\n addListeners() {\n if (!this.visualElement.current) return\n elementDragControls.set(this.visualElement, this)\n const element = this.visualElement.current\n\n /**\n * Attach a pointerdown event listener on this DOM element to initiate drag tracking.\n */\n const stopPointerListener = addPointerEvent(\n element,\n \"pointerdown\",\n (event) => {\n const { drag, dragListener = true } = this.getProps()\n if (\n drag &&\n dragListener &&\n !isElementKeyboardAccessible(event.target as Element)\n ) {\n this.start(event)\n }\n }\n )\n\n const measureDragConstraints = () => {\n const { dragConstraints } = this.getProps()\n if (isRefObject(dragConstraints) && dragConstraints.current) {\n this.constraints = this.resolveRefConstraints()\n }\n }\n\n const { projection } = this.visualElement\n\n const stopMeasureLayoutListener = projection!.addEventListener(\n \"measure\",\n measureDragConstraints\n )\n\n if (projection && !projection!.layout) {\n projection.root && projection.root.updateScroll()\n projection.updateLayout()\n }\n\n frame.read(measureDragConstraints)\n\n /**\n * Attach a window resize listener to scale the draggable target within its defined\n * constraints as the window resizes.\n */\n const stopResizeListener = addDomEvent(window, \"resize\", () =>\n this.scalePositionWithinConstraints()\n )\n\n /**\n * If the element's layout changes, calculate the delta and apply that to\n * the drag gesture's origin point.\n */\n const stopLayoutUpdateListener = projection!.addEventListener(\n \"didUpdate\",\n (({ delta, hasLayoutChanged }: LayoutUpdateData) => {\n if (this.isDragging && hasLayoutChanged) {\n eachAxis((axis) => {\n const motionValue = this.getAxisMotionValue(axis)\n if (!motionValue) return\n\n this.originPoint[axis] += delta[axis].translate\n motionValue.set(\n motionValue.get() + delta[axis].translate\n )\n })\n\n this.visualElement.render()\n }\n }) as any\n )\n\n return () => {\n stopResizeListener()\n stopPointerListener()\n stopMeasureLayoutListener()\n stopLayoutUpdateListener && stopLayoutUpdateListener()\n }\n }\n\n getProps(): MotionProps {\n const props = this.visualElement.getProps()\n const {\n drag = false,\n dragDirectionLock = false,\n dragPropagation = false,\n dragConstraints = false,\n dragElastic = defaultElastic,\n dragMomentum = true,\n } = props\n return {\n ...props,\n drag,\n dragDirectionLock,\n dragPropagation,\n dragConstraints,\n dragElastic,\n dragMomentum,\n }\n }\n}\n\nfunction shouldDrag(\n direction: DragDirection,\n drag: boolean | DragDirection | undefined,\n currentDirection: null | DragDirection\n) {\n return (\n (drag === true || drag === direction) &&\n (currentDirection === null || currentDirection === direction)\n )\n}\n\n/**\n * Based on an x/y offset determine the current drag direction. If both axis' offsets are lower\n * than the provided threshold, return `null`.\n *\n * @param offset - The x/y offset from origin.\n * @param lockThreshold - (Optional) - the minimum absolute offset before we can determine a drag direction.\n */\nfunction getCurrentDirection(\n offset: Point,\n lockThreshold = 10\n): DragDirection | null {\n let direction: DragDirection | null = null\n\n if (Math.abs(offset.y) > lockThreshold) {\n direction = \"y\"\n } else if (Math.abs(offset.x) > lockThreshold) {\n direction = \"x\"\n }\n\n return direction\n}\n\nexport function expectsResolvedDragConstraints({\n dragConstraints,\n onMeasureDragConstraints,\n}: MotionProps) {\n return isRefObject(dragConstraints) && !!onMeasureDragConstraints\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"VisualElementDragControls.mjs","sources":["../../../../src/gestures/drag/VisualElementDragControls.ts"],"sourcesContent":["import {\n isElementKeyboardAccessible,\n PanInfo,\n ResolvedConstraints,\n Transition,\n frame,\n mixNumber,\n percent,\n setDragLock,\n} from \"motion-dom\"\nimport { Axis, Point, invariant } from \"motion-utils\"\nimport { animateMotionValue } from \"../../animation/interfaces/motion-value\"\nimport { addDomEvent } from \"../../events/add-dom-event\"\nimport { addPointerEvent } from \"../../events/add-pointer-event\"\nimport { extractEventInfo } from \"../../events/event-info\"\nimport { MotionProps } from \"../../motion/types\"\nimport {\n convertBoundingBoxToBox,\n convertBoxToBoundingBox,\n} from \"../../projection/geometry/conversion\"\nimport { calcLength } from \"../../projection/geometry/delta-calc\"\nimport { createBox } from \"../../projection/geometry/models\"\nimport type { LayoutUpdateData } from \"../../projection/node/types\"\nimport { eachAxis } from \"../../projection/utils/each-axis\"\nimport { measurePageBox } from \"../../projection/utils/measure\"\nimport type { VisualElement } from \"../../render/VisualElement\"\nimport { getContextWindow } from \"../../utils/get-context-window\"\nimport { isRefObject } from \"../../utils/is-ref-object\"\nimport { addValueToWillChange } from \"../../value/use-will-change/add-will-change\"\nimport { PanSession } from \"../pan/PanSession\"\nimport {\n applyConstraints,\n calcOrigin,\n calcRelativeConstraints,\n calcViewportConstraints,\n defaultElastic,\n rebaseAxisConstraints,\n resolveDragElastic,\n} from \"./utils/constraints\"\n\nexport const elementDragControls = new WeakMap<\n VisualElement,\n VisualElementDragControls\n>()\n\nexport interface DragControlOptions {\n /**\n * This distance after which dragging starts and a direction is locked in.\n *\n * @public\n */\n distanceThreshold?: number\n\n /**\n * Whether to immediately snap to the cursor when dragging starts.\n *\n * @public\n */\n snapToCursor?: boolean\n}\n\ntype DragDirection = \"x\" | \"y\"\n\nexport class VisualElementDragControls {\n private visualElement: VisualElement<HTMLElement>\n\n private panSession?: PanSession\n\n private openDragLock: VoidFunction | null = null\n\n isDragging = false\n private currentDirection: DragDirection | null = null\n\n private originPoint: Point = { x: 0, y: 0 }\n\n /**\n * The permitted boundaries of travel, in pixels.\n */\n private constraints: ResolvedConstraints | false = false\n\n private hasMutatedConstraints = false\n\n /**\n * The per-axis resolved elastic values.\n */\n private elastic = createBox()\n\n /**\n * The latest pointer event. Used as fallback when the `cancel` and `stop` functions are called without arguments.\n */\n private latestPointerEvent: PointerEvent | null = null\n\n /**\n * The latest pan info. Used as fallback when the `cancel` and `stop` functions are called without arguments.\n */\n private latestPanInfo: PanInfo | null = null\n\n constructor(visualElement: VisualElement<HTMLElement>) {\n this.visualElement = visualElement\n }\n\n start(\n originEvent: PointerEvent,\n { snapToCursor = false, distanceThreshold }: DragControlOptions = {}\n ) {\n /**\n * Don't start dragging if this component is exiting\n */\n const { presenceContext } = this.visualElement\n if (presenceContext && presenceContext.isPresent === false) return\n\n const onSessionStart = (event: PointerEvent) => {\n // Stop or pause animations based on context:\n // - snapToCursor: stop because we'll set new position values\n // - otherwise: pause to allow resume if no drag starts (for constraint animations)\n if (snapToCursor) {\n this.stopAnimation()\n this.snapToCursor(extractEventInfo(event).point)\n } else {\n this.pauseAnimation()\n }\n }\n\n const onStart = (event: PointerEvent, info: PanInfo) => {\n // Stop any paused animation so motion values reflect true current position\n // (pauseAnimation was called in onSessionStart to allow resume if no drag started)\n this.stopAnimation()\n\n // Attempt to grab the global drag gesture lock - maybe make this part of PanSession\n const { drag, dragPropagation, onDragStart } = this.getProps()\n\n if (drag && !dragPropagation) {\n if (this.openDragLock) this.openDragLock()\n\n this.openDragLock = setDragLock(drag)\n\n // If we don 't have the lock, don't start dragging\n if (!this.openDragLock) return\n }\n\n this.latestPointerEvent = event\n this.latestPanInfo = info\n this.isDragging = true\n\n this.currentDirection = null\n\n this.resolveConstraints()\n\n if (this.visualElement.projection) {\n this.visualElement.projection.isAnimationBlocked = true\n this.visualElement.projection.target = undefined\n }\n\n /**\n * Record gesture origin\n */\n eachAxis((axis) => {\n let current = this.getAxisMotionValue(axis).get() || 0\n\n /**\n * If the MotionValue is a percentage value convert to px\n */\n if (percent.test(current)) {\n const { projection } = this.visualElement\n\n if (projection && projection.layout) {\n const measuredAxis = projection.layout.layoutBox[axis]\n\n if (measuredAxis) {\n const length = calcLength(measuredAxis)\n current = length * (parseFloat(current) / 100)\n }\n }\n }\n\n this.originPoint[axis] = current\n })\n\n // Fire onDragStart event\n if (onDragStart) {\n frame.postRender(() => onDragStart(event, info))\n }\n\n addValueToWillChange(this.visualElement, \"transform\")\n\n const { animationState } = this.visualElement\n animationState && animationState.setActive(\"whileDrag\", true)\n }\n\n const onMove = (event: PointerEvent, info: PanInfo) => {\n this.latestPointerEvent = event\n this.latestPanInfo = info\n\n const {\n dragPropagation,\n dragDirectionLock,\n onDirectionLock,\n onDrag,\n } = this.getProps()\n\n // If we didn't successfully receive the gesture lock, early return.\n if (!dragPropagation && !this.openDragLock) return\n\n const { offset } = info\n // Attempt to detect drag direction if directionLock is true\n if (dragDirectionLock && this.currentDirection === null) {\n this.currentDirection = getCurrentDirection(offset)\n\n // If we've successfully set a direction, notify listener\n if (this.currentDirection !== null) {\n onDirectionLock && onDirectionLock(this.currentDirection)\n }\n\n return\n }\n\n // Update each point with the latest position\n this.updateAxis(\"x\", info.point, offset)\n this.updateAxis(\"y\", info.point, offset)\n\n /**\n * Ideally we would leave the renderer to fire naturally at the end of\n * this frame but if the element is about to change layout as the result\n * of a re-render we want to ensure the browser can read the latest\n * bounding box to ensure the pointer and element don't fall out of sync.\n */\n this.visualElement.render()\n\n /**\n * This must fire after the render call as it might trigger a state\n * change which itself might trigger a layout update.\n */\n onDrag && onDrag(event, info)\n }\n\n const onSessionEnd = (event: PointerEvent, info: PanInfo) => {\n this.latestPointerEvent = event\n this.latestPanInfo = info\n\n this.stop(event, info)\n\n this.latestPointerEvent = null\n this.latestPanInfo = null\n }\n\n const resumeAnimation = () =>\n eachAxis(\n (axis) =>\n this.getAnimationState(axis) === \"paused\" &&\n this.getAxisMotionValue(axis).animation?.play()\n )\n\n const { dragSnapToOrigin } = this.getProps()\n this.panSession = new PanSession(\n originEvent,\n {\n onSessionStart,\n onStart,\n onMove,\n onSessionEnd,\n resumeAnimation,\n },\n {\n transformPagePoint: this.visualElement.getTransformPagePoint(),\n dragSnapToOrigin,\n distanceThreshold,\n contextWindow: getContextWindow(this.visualElement),\n element: this.visualElement.current,\n }\n )\n }\n\n /**\n * @internal\n */\n stop(event?: PointerEvent, panInfo?: PanInfo) {\n const finalEvent = event || this.latestPointerEvent\n const finalPanInfo = panInfo || this.latestPanInfo\n\n const isDragging = this.isDragging\n this.cancel()\n if (!isDragging || !finalPanInfo || !finalEvent) return\n\n const { velocity } = finalPanInfo\n this.startAnimation(velocity)\n\n const { onDragEnd } = this.getProps()\n if (onDragEnd) {\n frame.postRender(() => onDragEnd(finalEvent, finalPanInfo))\n }\n }\n\n /**\n * @internal\n */\n cancel() {\n this.isDragging = false\n\n const { projection, animationState } = this.visualElement\n\n if (projection) {\n projection.isAnimationBlocked = false\n }\n\n this.panSession && this.panSession.end()\n this.panSession = undefined\n\n const { dragPropagation } = this.getProps()\n\n if (!dragPropagation && this.openDragLock) {\n this.openDragLock()\n this.openDragLock = null\n }\n\n animationState && animationState.setActive(\"whileDrag\", false)\n }\n\n private updateAxis(axis: DragDirection, _point: Point, offset?: Point) {\n const { drag } = this.getProps()\n\n // If we're not dragging this axis, do an early return.\n if (!offset || !shouldDrag(axis, drag, this.currentDirection)) return\n\n const axisValue = this.getAxisMotionValue(axis)\n let next = this.originPoint[axis] + offset[axis]\n\n // Apply constraints\n if (this.constraints && this.constraints[axis]) {\n next = applyConstraints(\n next,\n this.constraints[axis],\n this.elastic[axis]\n )\n }\n\n axisValue.set(next)\n }\n\n private resolveConstraints() {\n const { dragConstraints, dragElastic } = this.getProps()\n\n const layout =\n this.visualElement.projection &&\n !this.visualElement.projection.layout\n ? this.visualElement.projection.measure(false)\n : this.visualElement.projection?.layout\n\n const prevConstraints = this.constraints\n\n if (dragConstraints && isRefObject(dragConstraints)) {\n if (!this.constraints) {\n this.constraints = this.resolveRefConstraints()\n }\n } else {\n if (dragConstraints && layout) {\n this.constraints = calcRelativeConstraints(\n layout.layoutBox,\n dragConstraints\n )\n } else {\n this.constraints = false\n }\n }\n\n this.elastic = resolveDragElastic(dragElastic)\n\n /**\n * If we're outputting to external MotionValues, we want to rebase the measured constraints\n * from viewport-relative to component-relative.\n */\n if (\n prevConstraints !== this.constraints &&\n layout &&\n this.constraints &&\n !this.hasMutatedConstraints\n ) {\n eachAxis((axis) => {\n if (\n this.constraints !== false &&\n this.getAxisMotionValue(axis)\n ) {\n this.constraints[axis] = rebaseAxisConstraints(\n layout.layoutBox[axis],\n this.constraints[axis]\n )\n }\n })\n }\n }\n\n private resolveRefConstraints() {\n const { dragConstraints: constraints, onMeasureDragConstraints } =\n this.getProps()\n if (!constraints || !isRefObject(constraints)) return false\n\n const constraintsElement = constraints.current as HTMLElement\n\n invariant(\n constraintsElement !== null,\n \"If `dragConstraints` is set as a React ref, that ref must be passed to another component's `ref` prop.\",\n \"drag-constraints-ref\"\n )\n\n const { projection } = this.visualElement\n\n // TODO\n if (!projection || !projection.layout) return false\n\n const constraintsBox = measurePageBox(\n constraintsElement,\n projection.root!,\n this.visualElement.getTransformPagePoint()\n )\n\n let measuredConstraints = calcViewportConstraints(\n projection.layout.layoutBox,\n constraintsBox\n )\n\n /**\n * If there's an onMeasureDragConstraints listener we call it and\n * if different constraints are returned, set constraints to that\n */\n if (onMeasureDragConstraints) {\n const userConstraints = onMeasureDragConstraints(\n convertBoxToBoundingBox(measuredConstraints)\n )\n\n this.hasMutatedConstraints = !!userConstraints\n\n if (userConstraints) {\n measuredConstraints = convertBoundingBoxToBox(userConstraints)\n }\n }\n\n return measuredConstraints\n }\n\n private startAnimation(velocity: Point) {\n const {\n drag,\n dragMomentum,\n dragElastic,\n dragTransition,\n dragSnapToOrigin,\n onDragTransitionEnd,\n } = this.getProps()\n\n const constraints: Partial<ResolvedConstraints> = this.constraints || {}\n\n const momentumAnimations = eachAxis((axis) => {\n if (!shouldDrag(axis, drag, this.currentDirection)) {\n return\n }\n\n let transition = (constraints && constraints[axis]) || {}\n\n if (dragSnapToOrigin) transition = { min: 0, max: 0 }\n\n /**\n * Overdamp the boundary spring if `dragElastic` is disabled. There's still a frame\n * of spring animations so we should look into adding a disable spring option to `inertia`.\n * We could do something here where we affect the `bounceStiffness` and `bounceDamping`\n * using the value of `dragElastic`.\n */\n const bounceStiffness = dragElastic ? 200 : 1000000\n const bounceDamping = dragElastic ? 40 : 10000000\n\n const inertia: Transition = {\n type: \"inertia\",\n velocity: dragMomentum ? velocity[axis] : 0,\n bounceStiffness,\n bounceDamping,\n timeConstant: 750,\n restDelta: 1,\n restSpeed: 10,\n ...dragTransition,\n ...transition,\n }\n\n // If we're not animating on an externally-provided `MotionValue` we can use the\n // component's animation controls which will handle interactions with whileHover (etc),\n // otherwise we just have to animate the `MotionValue` itself.\n return this.startAxisValueAnimation(axis, inertia)\n })\n\n // Run all animations and then resolve the new drag constraints.\n return Promise.all(momentumAnimations).then(onDragTransitionEnd)\n }\n\n private startAxisValueAnimation(\n axis: DragDirection,\n transition: Transition\n ) {\n const axisValue = this.getAxisMotionValue(axis)\n\n addValueToWillChange(this.visualElement, axis)\n\n return axisValue.start(\n animateMotionValue(\n axis,\n axisValue,\n 0,\n transition,\n this.visualElement,\n false\n )\n )\n }\n\n private stopAnimation() {\n eachAxis((axis) => this.getAxisMotionValue(axis).stop())\n }\n\n private pauseAnimation() {\n eachAxis((axis) => this.getAxisMotionValue(axis).animation?.pause())\n }\n\n private getAnimationState(axis: DragDirection) {\n return this.getAxisMotionValue(axis).animation?.state\n }\n\n /**\n * Drag works differently depending on which props are provided.\n *\n * - If _dragX and _dragY are provided, we output the gesture delta directly to those motion values.\n * - Otherwise, we apply the delta to the x/y motion values.\n */\n private getAxisMotionValue(axis: DragDirection) {\n const dragKey =\n `_drag${axis.toUpperCase()}` as `_drag${Uppercase<DragDirection>}`\n const props = this.visualElement.getProps()\n const externalMotionValue = props[dragKey]\n\n return externalMotionValue\n ? externalMotionValue\n : this.visualElement.getValue(\n axis,\n (props.initial\n ? props.initial[axis as keyof typeof props.initial]\n : undefined) || 0\n )\n }\n\n private snapToCursor(point: Point) {\n eachAxis((axis) => {\n const { drag } = this.getProps()\n\n // If we're not dragging this axis, do an early return.\n if (!shouldDrag(axis, drag, this.currentDirection)) return\n\n const { projection } = this.visualElement\n const axisValue = this.getAxisMotionValue(axis)\n\n if (projection && projection.layout) {\n const { min, max } = projection.layout.layoutBox[axis]\n\n /**\n * The layout measurement includes the current transform value,\n * so we need to add it back to get the correct snap position.\n * This fixes an issue where elements with initial coordinates\n * would snap to the wrong position on the first drag.\n */\n const current = axisValue.get() || 0\n\n axisValue.set(point[axis] - mixNumber(min, max, 0.5) + current)\n }\n })\n }\n\n /**\n * When the viewport resizes we want to check if the measured constraints\n * have changed and, if so, reposition the element within those new constraints\n * relative to where it was before the resize.\n */\n scalePositionWithinConstraints() {\n if (!this.visualElement.current) return\n\n const { drag, dragConstraints } = this.getProps()\n const { projection } = this.visualElement\n if (!isRefObject(dragConstraints) || !projection || !this.constraints)\n return\n\n /**\n * Stop current animations as there can be visual glitching if we try to do\n * this mid-animation\n */\n this.stopAnimation()\n\n /**\n * Record the relative position of the dragged element relative to the\n * constraints box and save as a progress value.\n */\n const boxProgress = { x: 0, y: 0 }\n eachAxis((axis) => {\n const axisValue = this.getAxisMotionValue(axis)\n if (axisValue && this.constraints !== false) {\n const latest = axisValue.get()\n boxProgress[axis] = calcOrigin(\n { min: latest, max: latest },\n this.constraints[axis] as Axis\n )\n }\n })\n\n /**\n * Update the layout of this element and resolve the latest drag constraints\n */\n const { transformTemplate } = this.visualElement.getProps()\n this.visualElement.current.style.transform = transformTemplate\n ? transformTemplate({}, \"\")\n : \"none\"\n projection.root && projection.root.updateScroll()\n projection.updateLayout()\n this.resolveConstraints()\n\n /**\n * For each axis, calculate the current progress of the layout axis\n * within the new constraints.\n */\n eachAxis((axis) => {\n if (!shouldDrag(axis, drag, null)) return\n\n /**\n * Calculate a new transform based on the previous box progress\n */\n const axisValue = this.getAxisMotionValue(axis)\n const { min, max } = (this.constraints as ResolvedConstraints)[\n axis\n ] as Axis\n axisValue.set(mixNumber(min, max, boxProgress[axis]))\n })\n }\n\n addListeners() {\n if (!this.visualElement.current) return\n elementDragControls.set(this.visualElement, this)\n const element = this.visualElement.current\n\n /**\n * Attach a pointerdown event listener on this DOM element to initiate drag tracking.\n */\n const stopPointerListener = addPointerEvent(\n element,\n \"pointerdown\",\n (event) => {\n const { drag, dragListener = true } = this.getProps()\n if (\n drag &&\n dragListener &&\n !isElementKeyboardAccessible(event.target as Element)\n ) {\n this.start(event)\n }\n }\n )\n\n const measureDragConstraints = () => {\n const { dragConstraints } = this.getProps()\n if (isRefObject(dragConstraints) && dragConstraints.current) {\n this.constraints = this.resolveRefConstraints()\n }\n }\n\n const { projection } = this.visualElement\n\n const stopMeasureLayoutListener = projection!.addEventListener(\n \"measure\",\n measureDragConstraints\n )\n\n if (projection && !projection!.layout) {\n projection.root && projection.root.updateScroll()\n projection.updateLayout()\n }\n\n frame.read(measureDragConstraints)\n\n /**\n * Attach a window resize listener to scale the draggable target within its defined\n * constraints as the window resizes.\n */\n const stopResizeListener = addDomEvent(window, \"resize\", () =>\n this.scalePositionWithinConstraints()\n )\n\n /**\n * If the element's layout changes, calculate the delta and apply that to\n * the drag gesture's origin point.\n */\n const stopLayoutUpdateListener = projection!.addEventListener(\n \"didUpdate\",\n (({ delta, hasLayoutChanged }: LayoutUpdateData) => {\n if (this.isDragging && hasLayoutChanged) {\n eachAxis((axis) => {\n const motionValue = this.getAxisMotionValue(axis)\n if (!motionValue) return\n\n this.originPoint[axis] += delta[axis].translate\n motionValue.set(\n motionValue.get() + delta[axis].translate\n )\n })\n\n this.visualElement.render()\n }\n }) as any\n )\n\n return () => {\n stopResizeListener()\n stopPointerListener()\n stopMeasureLayoutListener()\n stopLayoutUpdateListener && stopLayoutUpdateListener()\n }\n }\n\n getProps(): MotionProps {\n const props = this.visualElement.getProps()\n const {\n drag = false,\n dragDirectionLock = false,\n dragPropagation = false,\n dragConstraints = false,\n dragElastic = defaultElastic,\n dragMomentum = true,\n } = props\n return {\n ...props,\n drag,\n dragDirectionLock,\n dragPropagation,\n dragConstraints,\n dragElastic,\n dragMomentum,\n }\n }\n}\n\nfunction shouldDrag(\n direction: DragDirection,\n drag: boolean | DragDirection | undefined,\n currentDirection: null | DragDirection\n) {\n return (\n (drag === true || drag === direction) &&\n (currentDirection === null || currentDirection === direction)\n )\n}\n\n/**\n * Based on an x/y offset determine the current drag direction. If both axis' offsets are lower\n * than the provided threshold, return `null`.\n *\n * @param offset - The x/y offset from origin.\n * @param lockThreshold - (Optional) - the minimum absolute offset before we can determine a drag direction.\n */\nfunction getCurrentDirection(\n offset: Point,\n lockThreshold = 10\n): DragDirection | null {\n let direction: DragDirection | null = null\n\n if (Math.abs(offset.y) > lockThreshold) {\n direction = \"y\"\n } else if (Math.abs(offset.x) > lockThreshold) {\n direction = \"x\"\n }\n\n return direction\n}\n\nexport function expectsResolvedDragConstraints({\n dragConstraints,\n onMeasureDragConstraints,\n}: MotionProps) {\n return isRefObject(dragConstraints) && !!onMeasureDragConstraints\n}\n"],"names":[],"mappings":"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"}
@@ -4,11 +4,12 @@ import { addPointerEvent } from '../../events/add-pointer-event.mjs';
4
4
  import { extractEventInfo } from '../../events/event-info.mjs';
5
5
  import { distance2D } from '../../utils/distance.mjs';
6
6
 
7
+ const overflowStyles = /*#__PURE__*/ new Set(["auto", "scroll"]);
7
8
  /**
8
9
  * @internal
9
10
  */
10
11
  class PanSession {
11
- constructor(event, handlers, { transformPagePoint, contextWindow = window, dragSnapToOrigin = false, distanceThreshold = 3, } = {}) {
12
+ constructor(event, handlers, { transformPagePoint, contextWindow = window, dragSnapToOrigin = false, distanceThreshold = 3, element, } = {}) {
12
13
  /**
13
14
  * @internal
14
15
  */
@@ -29,6 +30,22 @@ class PanSession {
29
30
  * @internal
30
31
  */
31
32
  this.contextWindow = window;
33
+ /**
34
+ * Scroll positions of scrollable ancestors and window.
35
+ * @internal
36
+ */
37
+ this.scrollPositions = new Map();
38
+ /**
39
+ * Cleanup function for scroll listeners.
40
+ * @internal
41
+ */
42
+ this.removeScrollListeners = null;
43
+ this.onElementScroll = (event) => {
44
+ this.handleScroll(event.target);
45
+ };
46
+ this.onWindowScroll = () => {
47
+ this.handleScroll(window);
48
+ };
32
49
  this.updatePoint = () => {
33
50
  if (!(this.lastMoveEvent && this.lastMoveEventInfo))
34
51
  return;
@@ -91,12 +108,93 @@ class PanSession {
91
108
  onSessionStart &&
92
109
  onSessionStart(event, getPanInfo(initialInfo, this.history));
93
110
  this.removeListeners = pipe(addPointerEvent(this.contextWindow, "pointermove", this.handlePointerMove), addPointerEvent(this.contextWindow, "pointerup", this.handlePointerUp), addPointerEvent(this.contextWindow, "pointercancel", this.handlePointerUp));
111
+ // Start scroll tracking if element provided
112
+ if (element) {
113
+ this.startScrollTracking(element);
114
+ }
115
+ }
116
+ /**
117
+ * Start tracking scroll on ancestors and window.
118
+ */
119
+ startScrollTracking(element) {
120
+ // Store initial scroll positions for scrollable ancestors
121
+ let current = element.parentElement;
122
+ while (current) {
123
+ const style = getComputedStyle(current);
124
+ if (overflowStyles.has(style.overflowX) ||
125
+ overflowStyles.has(style.overflowY)) {
126
+ this.scrollPositions.set(current, {
127
+ x: current.scrollLeft,
128
+ y: current.scrollTop,
129
+ });
130
+ }
131
+ current = current.parentElement;
132
+ }
133
+ // Track window scroll
134
+ this.scrollPositions.set(window, {
135
+ x: window.scrollX,
136
+ y: window.scrollY,
137
+ });
138
+ // Capture listener catches element scroll events as they bubble
139
+ window.addEventListener("scroll", this.onElementScroll, {
140
+ capture: true,
141
+ passive: true,
142
+ });
143
+ // Direct window scroll listener (window scroll doesn't bubble)
144
+ window.addEventListener("scroll", this.onWindowScroll, {
145
+ passive: true,
146
+ });
147
+ this.removeScrollListeners = () => {
148
+ window.removeEventListener("scroll", this.onElementScroll, {
149
+ capture: true,
150
+ });
151
+ window.removeEventListener("scroll", this.onWindowScroll);
152
+ };
153
+ }
154
+ /**
155
+ * Handle scroll compensation during drag.
156
+ *
157
+ * For element scroll: adjusts history origin since pageX/pageY doesn't change.
158
+ * For window scroll: adjusts lastMoveEventInfo since pageX/pageY would change.
159
+ */
160
+ handleScroll(target) {
161
+ const initial = this.scrollPositions.get(target);
162
+ if (!initial)
163
+ return;
164
+ const isWindow = target === window;
165
+ const current = isWindow
166
+ ? { x: window.scrollX, y: window.scrollY }
167
+ : {
168
+ x: target.scrollLeft,
169
+ y: target.scrollTop,
170
+ };
171
+ const delta = { x: current.x - initial.x, y: current.y - initial.y };
172
+ if (delta.x === 0 && delta.y === 0)
173
+ return;
174
+ if (isWindow) {
175
+ // Window scroll: pageX/pageY changes, so update lastMoveEventInfo
176
+ if (this.lastMoveEventInfo) {
177
+ this.lastMoveEventInfo.point.x += delta.x;
178
+ this.lastMoveEventInfo.point.y += delta.y;
179
+ }
180
+ }
181
+ else {
182
+ // Element scroll: pageX/pageY unchanged, so adjust history origin
183
+ if (this.history.length > 0) {
184
+ this.history[0].x -= delta.x;
185
+ this.history[0].y -= delta.y;
186
+ }
187
+ }
188
+ this.scrollPositions.set(target, current);
189
+ frame.update(this.updatePoint, true);
94
190
  }
95
191
  updateHandlers(handlers) {
96
192
  this.handlers = handlers;
97
193
  }
98
194
  end() {
99
195
  this.removeListeners && this.removeListeners();
196
+ this.removeScrollListeners && this.removeScrollListeners();
197
+ this.scrollPositions.clear();
100
198
  cancelFrame(this.updatePoint);
101
199
  }
102
200
  }
@@ -1 +1 @@
1
- {"version":3,"file":"PanSession.mjs","sources":["../../../../src/gestures/pan/PanSession.ts"],"sourcesContent":["import type { EventInfo, PanHandler } from \"motion-dom\"\nimport { cancelFrame, frame, frameData, isPrimaryPointer } from \"motion-dom\"\nimport {\n millisecondsToSeconds,\n pipe,\n Point,\n secondsToMilliseconds,\n TransformPoint,\n} from \"motion-utils\"\nimport { addPointerEvent } from \"../../events/add-pointer-event\"\nimport { extractEventInfo } from \"../../events/event-info\"\nimport { distance2D } from \"../../utils/distance\"\n\ninterface PanSessionHandlers {\n onSessionStart: PanHandler\n onStart: PanHandler\n onMove: PanHandler\n onEnd: PanHandler\n onSessionEnd: PanHandler\n resumeAnimation: () => void\n}\n\ninterface PanSessionOptions {\n transformPagePoint?: TransformPoint\n dragSnapToOrigin?: boolean\n distanceThreshold?: number\n contextWindow?: (Window & typeof globalThis) | null\n}\n\ninterface TimestampedPoint extends Point {\n timestamp: number\n}\n\n/**\n * @internal\n */\nexport class PanSession {\n /**\n * @internal\n */\n private history: TimestampedPoint[]\n\n /**\n * @internal\n */\n private startEvent: PointerEvent | null = null\n\n /**\n * @internal\n */\n private lastMoveEvent: PointerEvent | null = null\n\n /**\n * @internal\n */\n private lastMoveEventInfo: EventInfo | null = null\n\n /**\n * @internal\n */\n private transformPagePoint?: TransformPoint\n\n /**\n * @internal\n */\n private handlers: Partial<PanSessionHandlers> = {}\n\n /**\n * @internal\n */\n private removeListeners: Function\n\n /**\n * For determining if an animation should resume after it is interupted\n *\n * @internal\n */\n private dragSnapToOrigin: boolean\n\n /**\n * The distance after which panning should start.\n *\n * @internal\n */\n private distanceThreshold: number\n\n /**\n * @internal\n */\n private contextWindow: PanSessionOptions[\"contextWindow\"] = window\n\n constructor(\n event: PointerEvent,\n handlers: Partial<PanSessionHandlers>,\n {\n transformPagePoint,\n contextWindow = window,\n dragSnapToOrigin = false,\n distanceThreshold = 3,\n }: PanSessionOptions = {}\n ) {\n // If we have more than one touch, don't start detecting this gesture\n if (!isPrimaryPointer(event)) return\n\n this.dragSnapToOrigin = dragSnapToOrigin\n this.handlers = handlers\n this.transformPagePoint = transformPagePoint\n this.distanceThreshold = distanceThreshold\n this.contextWindow = contextWindow || window\n\n const info = extractEventInfo(event)\n const initialInfo = transformPoint(info, this.transformPagePoint)\n const { point } = initialInfo\n\n const { timestamp } = frameData\n\n this.history = [{ ...point, timestamp }]\n\n const { onSessionStart } = handlers\n onSessionStart &&\n onSessionStart(event, getPanInfo(initialInfo, this.history))\n\n this.removeListeners = pipe(\n addPointerEvent(\n this.contextWindow,\n \"pointermove\",\n this.handlePointerMove\n ),\n addPointerEvent(\n this.contextWindow,\n \"pointerup\",\n this.handlePointerUp\n ),\n addPointerEvent(\n this.contextWindow,\n \"pointercancel\",\n this.handlePointerUp\n )\n )\n }\n\n private updatePoint = () => {\n if (!(this.lastMoveEvent && this.lastMoveEventInfo)) return\n\n const info = getPanInfo(this.lastMoveEventInfo, this.history)\n const isPanStarted = this.startEvent !== null\n\n // Only start panning if the offset is larger than 3 pixels. If we make it\n // any larger than this we'll want to reset the pointer history\n // on the first update to avoid visual snapping to the cursor.\n const isDistancePastThreshold =\n distance2D(info.offset, { x: 0, y: 0 }) >= this.distanceThreshold\n\n if (!isPanStarted && !isDistancePastThreshold) return\n\n const { point } = info\n const { timestamp } = frameData\n this.history.push({ ...point, timestamp })\n\n const { onStart, onMove } = this.handlers\n\n if (!isPanStarted) {\n onStart && onStart(this.lastMoveEvent, info)\n this.startEvent = this.lastMoveEvent\n }\n\n onMove && onMove(this.lastMoveEvent, info)\n }\n\n private handlePointerMove = (event: PointerEvent, info: EventInfo) => {\n this.lastMoveEvent = event\n this.lastMoveEventInfo = transformPoint(info, this.transformPagePoint)\n\n // Throttle mouse move event to once per frame\n frame.update(this.updatePoint, true)\n }\n\n private handlePointerUp = (event: PointerEvent, info: EventInfo) => {\n this.end()\n\n const { onEnd, onSessionEnd, resumeAnimation } = this.handlers\n\n // Resume animation if dragSnapToOrigin is set OR if no drag started (user just clicked)\n // This ensures constraint animations continue when interrupted by a click\n if (this.dragSnapToOrigin || !this.startEvent) {\n resumeAnimation && resumeAnimation()\n }\n if (!(this.lastMoveEvent && this.lastMoveEventInfo)) return\n\n const panInfo = getPanInfo(\n event.type === \"pointercancel\"\n ? this.lastMoveEventInfo\n : transformPoint(info, this.transformPagePoint),\n this.history\n )\n\n if (this.startEvent && onEnd) {\n onEnd(event, panInfo)\n }\n\n onSessionEnd && onSessionEnd(event, panInfo)\n }\n\n updateHandlers(handlers: Partial<PanSessionHandlers>) {\n this.handlers = handlers\n }\n\n end() {\n this.removeListeners && this.removeListeners()\n cancelFrame(this.updatePoint)\n }\n}\n\nfunction transformPoint(\n info: EventInfo,\n transformPagePoint?: (point: Point) => Point\n) {\n return transformPagePoint ? { point: transformPagePoint(info.point) } : info\n}\n\nfunction subtractPoint(a: Point, b: Point): Point {\n return { x: a.x - b.x, y: a.y - b.y }\n}\n\nfunction getPanInfo({ point }: EventInfo, history: TimestampedPoint[]) {\n return {\n point,\n delta: subtractPoint(point, lastDevicePoint(history)),\n offset: subtractPoint(point, startDevicePoint(history)),\n velocity: getVelocity(history, 0.1),\n }\n}\n\nfunction startDevicePoint(history: TimestampedPoint[]): TimestampedPoint {\n return history[0]\n}\n\nfunction lastDevicePoint(history: TimestampedPoint[]): TimestampedPoint {\n return history[history.length - 1]\n}\n\nfunction getVelocity(history: TimestampedPoint[], timeDelta: number): Point {\n if (history.length < 2) {\n return { x: 0, y: 0 }\n }\n\n let i = history.length - 1\n let timestampedPoint: TimestampedPoint | null = null\n const lastPoint = lastDevicePoint(history)\n while (i >= 0) {\n timestampedPoint = history[i]\n if (\n lastPoint.timestamp - timestampedPoint.timestamp >\n secondsToMilliseconds(timeDelta)\n ) {\n break\n }\n i--\n }\n\n if (!timestampedPoint) {\n return { x: 0, y: 0 }\n }\n\n const time = millisecondsToSeconds(\n lastPoint.timestamp - timestampedPoint.timestamp\n )\n if (time === 0) {\n return { x: 0, y: 0 }\n }\n\n const currentVelocity = {\n x: (lastPoint.x - timestampedPoint.x) / time,\n y: (lastPoint.y - timestampedPoint.y) / time,\n }\n\n if (currentVelocity.x === Infinity) {\n currentVelocity.x = 0\n }\n if (currentVelocity.y === Infinity) {\n currentVelocity.y = 0\n }\n\n return currentVelocity\n}\n"],"names":[],"mappings":";;;;;;AAiCA;;AAEG;MACU,UAAU,CAAA;AAuDnB,IAAA,WAAA,CACI,KAAmB,EACnB,QAAqC,EACrC,EACI,kBAAkB,EAClB,aAAa,GAAG,MAAM,EACtB,gBAAgB,GAAG,KAAK,EACxB,iBAAiB,GAAG,CAAC,MACF,EAAE,EAAA;AAzD7B;;AAEG;QACK,IAAU,CAAA,UAAA,GAAwB,IAAI,CAAA;AAE9C;;AAEG;QACK,IAAa,CAAA,aAAA,GAAwB,IAAI,CAAA;AAEjD;;AAEG;QACK,IAAiB,CAAA,iBAAA,GAAqB,IAAI,CAAA;AAOlD;;AAEG;QACK,IAAQ,CAAA,QAAA,GAAgC,EAAE,CAAA;AAqBlD;;AAEG;QACK,IAAa,CAAA,aAAA,GAAuC,MAAM,CAAA;QAoD1D,IAAW,CAAA,WAAA,GAAG,MAAK;YACvB,IAAI,EAAE,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC,iBAAiB,CAAC;gBAAE,OAAM;AAE3D,YAAA,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,iBAAiB,EAAE,IAAI,CAAC,OAAO,CAAC,CAAA;AAC7D,YAAA,MAAM,YAAY,GAAG,IAAI,CAAC,UAAU,KAAK,IAAI,CAAA;;;;YAK7C,MAAM,uBAAuB,GACzB,UAAU,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,iBAAiB,CAAA;AAErE,YAAA,IAAI,CAAC,YAAY,IAAI,CAAC,uBAAuB;gBAAE,OAAM;AAErD,YAAA,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI,CAAA;AACtB,YAAA,MAAM,EAAE,SAAS,EAAE,GAAG,SAAS,CAAA;AAC/B,YAAA,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,KAAK,EAAE,SAAS,EAAE,CAAC,CAAA;YAE1C,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAA;YAEzC,IAAI,CAAC,YAAY,EAAE;gBACf,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,CAAA;AAC5C,gBAAA,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,aAAa,CAAA;aACvC;YAED,MAAM,IAAI,MAAM,CAAC,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,CAAA;AAC9C,SAAC,CAAA;AAEO,QAAA,IAAA,CAAA,iBAAiB,GAAG,CAAC,KAAmB,EAAE,IAAe,KAAI;AACjE,YAAA,IAAI,CAAC,aAAa,GAAG,KAAK,CAAA;YAC1B,IAAI,CAAC,iBAAiB,GAAG,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,kBAAkB,CAAC,CAAA;;YAGtE,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,CAAA;AACxC,SAAC,CAAA;AAEO,QAAA,IAAA,CAAA,eAAe,GAAG,CAAC,KAAmB,EAAE,IAAe,KAAI;YAC/D,IAAI,CAAC,GAAG,EAAE,CAAA;YAEV,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAA;;;YAI9D,IAAI,IAAI,CAAC,gBAAgB,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE;gBAC3C,eAAe,IAAI,eAAe,EAAE,CAAA;aACvC;YACD,IAAI,EAAE,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC,iBAAiB,CAAC;gBAAE,OAAM;YAE3D,MAAM,OAAO,GAAG,UAAU,CACtB,KAAK,CAAC,IAAI,KAAK,eAAe;kBACxB,IAAI,CAAC,iBAAiB;AACxB,kBAAE,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,kBAAkB,CAAC,EACnD,IAAI,CAAC,OAAO,CACf,CAAA;AAED,YAAA,IAAI,IAAI,CAAC,UAAU,IAAI,KAAK,EAAE;AAC1B,gBAAA,KAAK,CAAC,KAAK,EAAE,OAAO,CAAC,CAAA;aACxB;AAED,YAAA,YAAY,IAAI,YAAY,CAAC,KAAK,EAAE,OAAO,CAAC,CAAA;AAChD,SAAC,CAAA;;AAnGG,QAAA,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC;YAAE,OAAM;AAEpC,QAAA,IAAI,CAAC,gBAAgB,GAAG,gBAAgB,CAAA;AACxC,QAAA,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAA;AACxB,QAAA,IAAI,CAAC,kBAAkB,GAAG,kBAAkB,CAAA;AAC5C,QAAA,IAAI,CAAC,iBAAiB,GAAG,iBAAiB,CAAA;AAC1C,QAAA,IAAI,CAAC,aAAa,GAAG,aAAa,IAAI,MAAM,CAAA;AAE5C,QAAA,MAAM,IAAI,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAA;QACpC,MAAM,WAAW,GAAG,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,kBAAkB,CAAC,CAAA;AACjE,QAAA,MAAM,EAAE,KAAK,EAAE,GAAG,WAAW,CAAA;AAE7B,QAAA,MAAM,EAAE,SAAS,EAAE,GAAG,SAAS,CAAA;QAE/B,IAAI,CAAC,OAAO,GAAG,CAAC,EAAE,GAAG,KAAK,EAAE,SAAS,EAAE,CAAC,CAAA;AAExC,QAAA,MAAM,EAAE,cAAc,EAAE,GAAG,QAAQ,CAAA;QACnC,cAAc;AACV,YAAA,cAAc,CAAC,KAAK,EAAE,UAAU,CAAC,WAAW,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,CAAA;QAEhE,IAAI,CAAC,eAAe,GAAG,IAAI,CACvB,eAAe,CACX,IAAI,CAAC,aAAa,EAClB,aAAa,EACb,IAAI,CAAC,iBAAiB,CACzB,EACD,eAAe,CACX,IAAI,CAAC,aAAa,EAClB,WAAW,EACX,IAAI,CAAC,eAAe,CACvB,EACD,eAAe,CACX,IAAI,CAAC,aAAa,EAClB,eAAe,EACf,IAAI,CAAC,eAAe,CACvB,CACJ,CAAA;KACJ;AAgED,IAAA,cAAc,CAAC,QAAqC,EAAA;AAChD,QAAA,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAA;KAC3B;IAED,GAAG,GAAA;AACC,QAAA,IAAI,CAAC,eAAe,IAAI,IAAI,CAAC,eAAe,EAAE,CAAA;AAC9C,QAAA,WAAW,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;KAChC;AACJ,CAAA;AAED,SAAS,cAAc,CACnB,IAAe,EACf,kBAA4C,EAAA;AAE5C,IAAA,OAAO,kBAAkB,GAAG,EAAE,KAAK,EAAE,kBAAkB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,IAAI,CAAA;AAChF,CAAC;AAED,SAAS,aAAa,CAAC,CAAQ,EAAE,CAAQ,EAAA;IACrC,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAA;AACzC,CAAC;AAED,SAAS,UAAU,CAAC,EAAE,KAAK,EAAa,EAAE,OAA2B,EAAA;IACjE,OAAO;QACH,KAAK;QACL,KAAK,EAAE,aAAa,CAAC,KAAK,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC;QACrD,MAAM,EAAE,aAAa,CAAC,KAAK,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAC;AACvD,QAAA,QAAQ,EAAE,WAAW,CAAC,OAAO,EAAE,GAAG,CAAC;KACtC,CAAA;AACL,CAAC;AAED,SAAS,gBAAgB,CAAC,OAA2B,EAAA;AACjD,IAAA,OAAO,OAAO,CAAC,CAAC,CAAC,CAAA;AACrB,CAAC;AAED,SAAS,eAAe,CAAC,OAA2B,EAAA;IAChD,OAAO,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;AACtC,CAAC;AAED,SAAS,WAAW,CAAC,OAA2B,EAAE,SAAiB,EAAA;AAC/D,IAAA,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE;QACpB,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAA;KACxB;AAED,IAAA,IAAI,CAAC,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,CAAA;IAC1B,IAAI,gBAAgB,GAA4B,IAAI,CAAA;AACpD,IAAA,MAAM,SAAS,GAAG,eAAe,CAAC,OAAO,CAAC,CAAA;AAC1C,IAAA,OAAO,CAAC,IAAI,CAAC,EAAE;AACX,QAAA,gBAAgB,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;AAC7B,QAAA,IACI,SAAS,CAAC,SAAS,GAAG,gBAAgB,CAAC,SAAS;AAChD,YAAA,qBAAqB,CAAC,SAAS,CAAC,EAClC;YACE,MAAK;SACR;AACD,QAAA,CAAC,EAAE,CAAA;KACN;IAED,IAAI,CAAC,gBAAgB,EAAE;QACnB,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAA;KACxB;AAED,IAAA,MAAM,IAAI,GAAG,qBAAqB,CAC9B,SAAS,CAAC,SAAS,GAAG,gBAAgB,CAAC,SAAS,CACnD,CAAA;AACD,IAAA,IAAI,IAAI,KAAK,CAAC,EAAE;QACZ,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAA;KACxB;AAED,IAAA,MAAM,eAAe,GAAG;QACpB,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC,GAAG,gBAAgB,CAAC,CAAC,IAAI,IAAI;QAC5C,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC,GAAG,gBAAgB,CAAC,CAAC,IAAI,IAAI;KAC/C,CAAA;AAED,IAAA,IAAI,eAAe,CAAC,CAAC,KAAK,QAAQ,EAAE;AAChC,QAAA,eAAe,CAAC,CAAC,GAAG,CAAC,CAAA;KACxB;AACD,IAAA,IAAI,eAAe,CAAC,CAAC,KAAK,QAAQ,EAAE;AAChC,QAAA,eAAe,CAAC,CAAC,GAAG,CAAC,CAAA;KACxB;AAED,IAAA,OAAO,eAAe,CAAA;AAC1B;;;;"}
1
+ {"version":3,"file":"PanSession.mjs","sources":["../../../../src/gestures/pan/PanSession.ts"],"sourcesContent":["import type { EventInfo, PanHandler } from \"motion-dom\"\nimport { cancelFrame, frame, frameData, isPrimaryPointer } from \"motion-dom\"\nimport {\n millisecondsToSeconds,\n pipe,\n Point,\n secondsToMilliseconds,\n TransformPoint,\n} from \"motion-utils\"\nimport { addPointerEvent } from \"../../events/add-pointer-event\"\nimport { extractEventInfo } from \"../../events/event-info\"\nimport { distance2D } from \"../../utils/distance\"\n\ninterface PanSessionHandlers {\n onSessionStart: PanHandler\n onStart: PanHandler\n onMove: PanHandler\n onEnd: PanHandler\n onSessionEnd: PanHandler\n resumeAnimation: () => void\n}\n\ninterface PanSessionOptions {\n transformPagePoint?: TransformPoint\n dragSnapToOrigin?: boolean\n distanceThreshold?: number\n contextWindow?: (Window & typeof globalThis) | null\n /**\n * Element being dragged. When provided, scroll events on its\n * ancestors and window are compensated so the gesture continues\n * smoothly during scroll.\n */\n element?: HTMLElement | null\n}\n\ninterface TimestampedPoint extends Point {\n timestamp: number\n}\n\nconst overflowStyles = /*#__PURE__*/ new Set([\"auto\", \"scroll\"])\n\n/**\n * @internal\n */\nexport class PanSession {\n /**\n * @internal\n */\n private history: TimestampedPoint[]\n\n /**\n * @internal\n */\n private startEvent: PointerEvent | null = null\n\n /**\n * @internal\n */\n private lastMoveEvent: PointerEvent | null = null\n\n /**\n * @internal\n */\n private lastMoveEventInfo: EventInfo | null = null\n\n /**\n * @internal\n */\n private transformPagePoint?: TransformPoint\n\n /**\n * @internal\n */\n private handlers: Partial<PanSessionHandlers> = {}\n\n /**\n * @internal\n */\n private removeListeners: Function\n\n /**\n * For determining if an animation should resume after it is interupted\n *\n * @internal\n */\n private dragSnapToOrigin: boolean\n\n /**\n * The distance after which panning should start.\n *\n * @internal\n */\n private distanceThreshold: number\n\n /**\n * @internal\n */\n private contextWindow: PanSessionOptions[\"contextWindow\"] = window\n\n /**\n * Scroll positions of scrollable ancestors and window.\n * @internal\n */\n private scrollPositions: Map<Element | Window, Point> = new Map()\n\n /**\n * Cleanup function for scroll listeners.\n * @internal\n */\n private removeScrollListeners: (() => void) | null = null\n\n constructor(\n event: PointerEvent,\n handlers: Partial<PanSessionHandlers>,\n {\n transformPagePoint,\n contextWindow = window,\n dragSnapToOrigin = false,\n distanceThreshold = 3,\n element,\n }: PanSessionOptions = {}\n ) {\n // If we have more than one touch, don't start detecting this gesture\n if (!isPrimaryPointer(event)) return\n\n this.dragSnapToOrigin = dragSnapToOrigin\n this.handlers = handlers\n this.transformPagePoint = transformPagePoint\n this.distanceThreshold = distanceThreshold\n this.contextWindow = contextWindow || window\n\n const info = extractEventInfo(event)\n const initialInfo = transformPoint(info, this.transformPagePoint)\n const { point } = initialInfo\n\n const { timestamp } = frameData\n\n this.history = [{ ...point, timestamp }]\n\n const { onSessionStart } = handlers\n onSessionStart &&\n onSessionStart(event, getPanInfo(initialInfo, this.history))\n\n this.removeListeners = pipe(\n addPointerEvent(\n this.contextWindow,\n \"pointermove\",\n this.handlePointerMove\n ),\n addPointerEvent(\n this.contextWindow,\n \"pointerup\",\n this.handlePointerUp\n ),\n addPointerEvent(\n this.contextWindow,\n \"pointercancel\",\n this.handlePointerUp\n )\n )\n\n // Start scroll tracking if element provided\n if (element) {\n this.startScrollTracking(element)\n }\n }\n\n /**\n * Start tracking scroll on ancestors and window.\n */\n private startScrollTracking(element: HTMLElement): void {\n // Store initial scroll positions for scrollable ancestors\n let current = element.parentElement\n while (current) {\n const style = getComputedStyle(current)\n if (\n overflowStyles.has(style.overflowX) ||\n overflowStyles.has(style.overflowY)\n ) {\n this.scrollPositions.set(current, {\n x: current.scrollLeft,\n y: current.scrollTop,\n })\n }\n current = current.parentElement\n }\n\n // Track window scroll\n this.scrollPositions.set(window, {\n x: window.scrollX,\n y: window.scrollY,\n })\n\n // Capture listener catches element scroll events as they bubble\n window.addEventListener(\"scroll\", this.onElementScroll, {\n capture: true,\n passive: true,\n })\n\n // Direct window scroll listener (window scroll doesn't bubble)\n window.addEventListener(\"scroll\", this.onWindowScroll, {\n passive: true,\n })\n\n this.removeScrollListeners = () => {\n window.removeEventListener(\"scroll\", this.onElementScroll, {\n capture: true,\n })\n window.removeEventListener(\"scroll\", this.onWindowScroll)\n }\n }\n\n private onElementScroll = (event: Event): void => {\n this.handleScroll(event.target as Element)\n }\n\n private onWindowScroll = (): void => {\n this.handleScroll(window)\n }\n\n /**\n * Handle scroll compensation during drag.\n *\n * For element scroll: adjusts history origin since pageX/pageY doesn't change.\n * For window scroll: adjusts lastMoveEventInfo since pageX/pageY would change.\n */\n private handleScroll(target: Element | Window): void {\n const initial = this.scrollPositions.get(target)\n if (!initial) return\n\n const isWindow = target === window\n const current = isWindow\n ? { x: window.scrollX, y: window.scrollY }\n : {\n x: (target as Element).scrollLeft,\n y: (target as Element).scrollTop,\n }\n\n const delta = { x: current.x - initial.x, y: current.y - initial.y }\n if (delta.x === 0 && delta.y === 0) return\n\n if (isWindow) {\n // Window scroll: pageX/pageY changes, so update lastMoveEventInfo\n if (this.lastMoveEventInfo) {\n this.lastMoveEventInfo.point.x += delta.x\n this.lastMoveEventInfo.point.y += delta.y\n }\n } else {\n // Element scroll: pageX/pageY unchanged, so adjust history origin\n if (this.history.length > 0) {\n this.history[0].x -= delta.x\n this.history[0].y -= delta.y\n }\n }\n\n this.scrollPositions.set(target, current)\n frame.update(this.updatePoint, true)\n }\n\n private updatePoint = () => {\n if (!(this.lastMoveEvent && this.lastMoveEventInfo)) return\n\n const info = getPanInfo(this.lastMoveEventInfo, this.history)\n const isPanStarted = this.startEvent !== null\n\n // Only start panning if the offset is larger than 3 pixels. If we make it\n // any larger than this we'll want to reset the pointer history\n // on the first update to avoid visual snapping to the cursor.\n const isDistancePastThreshold =\n distance2D(info.offset, { x: 0, y: 0 }) >= this.distanceThreshold\n\n if (!isPanStarted && !isDistancePastThreshold) return\n\n const { point } = info\n const { timestamp } = frameData\n this.history.push({ ...point, timestamp })\n\n const { onStart, onMove } = this.handlers\n\n if (!isPanStarted) {\n onStart && onStart(this.lastMoveEvent, info)\n this.startEvent = this.lastMoveEvent\n }\n\n onMove && onMove(this.lastMoveEvent, info)\n }\n\n private handlePointerMove = (event: PointerEvent, info: EventInfo) => {\n this.lastMoveEvent = event\n this.lastMoveEventInfo = transformPoint(info, this.transformPagePoint)\n\n // Throttle mouse move event to once per frame\n frame.update(this.updatePoint, true)\n }\n\n private handlePointerUp = (event: PointerEvent, info: EventInfo) => {\n this.end()\n\n const { onEnd, onSessionEnd, resumeAnimation } = this.handlers\n\n // Resume animation if dragSnapToOrigin is set OR if no drag started (user just clicked)\n // This ensures constraint animations continue when interrupted by a click\n if (this.dragSnapToOrigin || !this.startEvent) {\n resumeAnimation && resumeAnimation()\n }\n if (!(this.lastMoveEvent && this.lastMoveEventInfo)) return\n\n const panInfo = getPanInfo(\n event.type === \"pointercancel\"\n ? this.lastMoveEventInfo\n : transformPoint(info, this.transformPagePoint),\n this.history\n )\n\n if (this.startEvent && onEnd) {\n onEnd(event, panInfo)\n }\n\n onSessionEnd && onSessionEnd(event, panInfo)\n }\n\n updateHandlers(handlers: Partial<PanSessionHandlers>) {\n this.handlers = handlers\n }\n\n end() {\n this.removeListeners && this.removeListeners()\n this.removeScrollListeners && this.removeScrollListeners()\n this.scrollPositions.clear()\n cancelFrame(this.updatePoint)\n }\n}\n\nfunction transformPoint(\n info: EventInfo,\n transformPagePoint?: (point: Point) => Point\n) {\n return transformPagePoint ? { point: transformPagePoint(info.point) } : info\n}\n\nfunction subtractPoint(a: Point, b: Point): Point {\n return { x: a.x - b.x, y: a.y - b.y }\n}\n\nfunction getPanInfo({ point }: EventInfo, history: TimestampedPoint[]) {\n return {\n point,\n delta: subtractPoint(point, lastDevicePoint(history)),\n offset: subtractPoint(point, startDevicePoint(history)),\n velocity: getVelocity(history, 0.1),\n }\n}\n\nfunction startDevicePoint(history: TimestampedPoint[]): TimestampedPoint {\n return history[0]\n}\n\nfunction lastDevicePoint(history: TimestampedPoint[]): TimestampedPoint {\n return history[history.length - 1]\n}\n\nfunction getVelocity(history: TimestampedPoint[], timeDelta: number): Point {\n if (history.length < 2) {\n return { x: 0, y: 0 }\n }\n\n let i = history.length - 1\n let timestampedPoint: TimestampedPoint | null = null\n const lastPoint = lastDevicePoint(history)\n while (i >= 0) {\n timestampedPoint = history[i]\n if (\n lastPoint.timestamp - timestampedPoint.timestamp >\n secondsToMilliseconds(timeDelta)\n ) {\n break\n }\n i--\n }\n\n if (!timestampedPoint) {\n return { x: 0, y: 0 }\n }\n\n const time = millisecondsToSeconds(\n lastPoint.timestamp - timestampedPoint.timestamp\n )\n if (time === 0) {\n return { x: 0, y: 0 }\n }\n\n const currentVelocity = {\n x: (lastPoint.x - timestampedPoint.x) / time,\n y: (lastPoint.y - timestampedPoint.y) / time,\n }\n\n if (currentVelocity.x === Infinity) {\n currentVelocity.x = 0\n }\n if (currentVelocity.y === Infinity) {\n currentVelocity.y = 0\n }\n\n return currentVelocity\n}\n"],"names":[],"mappings":"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"}
@@ -2427,6 +2427,12 @@
2427
2427
  super();
2428
2428
  this.finishedTime = null;
2429
2429
  this.isStopped = false;
2430
+ /**
2431
+ * Tracks a manually-set start time that takes precedence over WAAPI's
2432
+ * dynamic startTime. This is cleared when play() or time setter is called,
2433
+ * allowing WAAPI to take over timing.
2434
+ */
2435
+ this.manualStartTime = null;
2430
2436
  if (!options)
2431
2437
  return;
2432
2438
  const { element, name, keyframes, pseudoElement, allowFlatten = false, finalKeyframe, onComplete, } = options;
@@ -2462,6 +2468,7 @@
2462
2468
  play() {
2463
2469
  if (this.isStopped)
2464
2470
  return;
2471
+ this.manualStartTime = null;
2465
2472
  this.animation.play();
2466
2473
  if (this.state === "finished") {
2467
2474
  this.updateFinished();
@@ -2525,6 +2532,7 @@
2525
2532
  return millisecondsToSeconds(Number(this.animation.currentTime) || 0);
2526
2533
  }
2527
2534
  set time(newTime) {
2535
+ this.manualStartTime = null;
2528
2536
  this.finishedTime = null;
2529
2537
  this.animation.currentTime = secondsToMilliseconds(newTime);
2530
2538
  }
@@ -2547,10 +2555,10 @@
2547
2555
  : this.animation.playState;
2548
2556
  }
2549
2557
  get startTime() {
2550
- return Number(this.animation.startTime);
2558
+ return this.manualStartTime ?? Number(this.animation.startTime);
2551
2559
  }
2552
2560
  set startTime(newStartTime) {
2553
- this.animation.startTime = newStartTime;
2561
+ this.manualStartTime = this.animation.startTime = newStartTime;
2554
2562
  }
2555
2563
  /**
2556
2564
  * Attaches a timeline to the animation, for instance the `ScrollTimeline`.
@@ -2612,7 +2620,7 @@
2612
2620
  */
2613
2621
  replaceTransitionType(options);
2614
2622
  super(options);
2615
- if (options.startTime) {
2623
+ if (options.startTime !== undefined) {
2616
2624
  this.startTime = options.startTime;
2617
2625
  }
2618
2626
  this.options = options;
@@ -2637,8 +2645,14 @@
2637
2645
  ...options,
2638
2646
  autoplay: false,
2639
2647
  });
2640
- const sampleTime = secondsToMilliseconds(this.finishedTime ?? this.time);
2641
- motionValue.setWithVelocity(sampleAnimation.sample(sampleTime - sampleDelta).value, sampleAnimation.sample(sampleTime).value, sampleDelta);
2648
+ /**
2649
+ * Use wall-clock elapsed time for sampling.
2650
+ * Under CPU load, WAAPI's currentTime may not reflect actual
2651
+ * elapsed time, causing incorrect sampling and visual jumps.
2652
+ */
2653
+ const sampleTime = Math.max(sampleDelta, time.now() - this.startTime);
2654
+ const delta = clamp(0, sampleDelta, sampleTime - sampleDelta);
2655
+ motionValue.setWithVelocity(sampleAnimation.sample(Math.max(0, sampleTime - delta)).value, sampleAnimation.sample(sampleTime).value, delta);
2642
2656
  sampleAnimation.stop();
2643
2657
  }
2644
2658
  }
@@ -10788,11 +10802,12 @@
10788
10802
  return Math.sqrt(xDelta ** 2 + yDelta ** 2);
10789
10803
  }
10790
10804
 
10805
+ const overflowStyles = /*#__PURE__*/ new Set(["auto", "scroll"]);
10791
10806
  /**
10792
10807
  * @internal
10793
10808
  */
10794
10809
  class PanSession {
10795
- constructor(event, handlers, { transformPagePoint, contextWindow = window, dragSnapToOrigin = false, distanceThreshold = 3, } = {}) {
10810
+ constructor(event, handlers, { transformPagePoint, contextWindow = window, dragSnapToOrigin = false, distanceThreshold = 3, element, } = {}) {
10796
10811
  /**
10797
10812
  * @internal
10798
10813
  */
@@ -10813,6 +10828,22 @@
10813
10828
  * @internal
10814
10829
  */
10815
10830
  this.contextWindow = window;
10831
+ /**
10832
+ * Scroll positions of scrollable ancestors and window.
10833
+ * @internal
10834
+ */
10835
+ this.scrollPositions = new Map();
10836
+ /**
10837
+ * Cleanup function for scroll listeners.
10838
+ * @internal
10839
+ */
10840
+ this.removeScrollListeners = null;
10841
+ this.onElementScroll = (event) => {
10842
+ this.handleScroll(event.target);
10843
+ };
10844
+ this.onWindowScroll = () => {
10845
+ this.handleScroll(window);
10846
+ };
10816
10847
  this.updatePoint = () => {
10817
10848
  if (!(this.lastMoveEvent && this.lastMoveEventInfo))
10818
10849
  return;
@@ -10875,12 +10906,93 @@
10875
10906
  onSessionStart &&
10876
10907
  onSessionStart(event, getPanInfo(initialInfo, this.history));
10877
10908
  this.removeListeners = pipe(addPointerEvent(this.contextWindow, "pointermove", this.handlePointerMove), addPointerEvent(this.contextWindow, "pointerup", this.handlePointerUp), addPointerEvent(this.contextWindow, "pointercancel", this.handlePointerUp));
10909
+ // Start scroll tracking if element provided
10910
+ if (element) {
10911
+ this.startScrollTracking(element);
10912
+ }
10913
+ }
10914
+ /**
10915
+ * Start tracking scroll on ancestors and window.
10916
+ */
10917
+ startScrollTracking(element) {
10918
+ // Store initial scroll positions for scrollable ancestors
10919
+ let current = element.parentElement;
10920
+ while (current) {
10921
+ const style = getComputedStyle(current);
10922
+ if (overflowStyles.has(style.overflowX) ||
10923
+ overflowStyles.has(style.overflowY)) {
10924
+ this.scrollPositions.set(current, {
10925
+ x: current.scrollLeft,
10926
+ y: current.scrollTop,
10927
+ });
10928
+ }
10929
+ current = current.parentElement;
10930
+ }
10931
+ // Track window scroll
10932
+ this.scrollPositions.set(window, {
10933
+ x: window.scrollX,
10934
+ y: window.scrollY,
10935
+ });
10936
+ // Capture listener catches element scroll events as they bubble
10937
+ window.addEventListener("scroll", this.onElementScroll, {
10938
+ capture: true,
10939
+ passive: true,
10940
+ });
10941
+ // Direct window scroll listener (window scroll doesn't bubble)
10942
+ window.addEventListener("scroll", this.onWindowScroll, {
10943
+ passive: true,
10944
+ });
10945
+ this.removeScrollListeners = () => {
10946
+ window.removeEventListener("scroll", this.onElementScroll, {
10947
+ capture: true,
10948
+ });
10949
+ window.removeEventListener("scroll", this.onWindowScroll);
10950
+ };
10951
+ }
10952
+ /**
10953
+ * Handle scroll compensation during drag.
10954
+ *
10955
+ * For element scroll: adjusts history origin since pageX/pageY doesn't change.
10956
+ * For window scroll: adjusts lastMoveEventInfo since pageX/pageY would change.
10957
+ */
10958
+ handleScroll(target) {
10959
+ const initial = this.scrollPositions.get(target);
10960
+ if (!initial)
10961
+ return;
10962
+ const isWindow = target === window;
10963
+ const current = isWindow
10964
+ ? { x: window.scrollX, y: window.scrollY }
10965
+ : {
10966
+ x: target.scrollLeft,
10967
+ y: target.scrollTop,
10968
+ };
10969
+ const delta = { x: current.x - initial.x, y: current.y - initial.y };
10970
+ if (delta.x === 0 && delta.y === 0)
10971
+ return;
10972
+ if (isWindow) {
10973
+ // Window scroll: pageX/pageY changes, so update lastMoveEventInfo
10974
+ if (this.lastMoveEventInfo) {
10975
+ this.lastMoveEventInfo.point.x += delta.x;
10976
+ this.lastMoveEventInfo.point.y += delta.y;
10977
+ }
10978
+ }
10979
+ else {
10980
+ // Element scroll: pageX/pageY unchanged, so adjust history origin
10981
+ if (this.history.length > 0) {
10982
+ this.history[0].x -= delta.x;
10983
+ this.history[0].y -= delta.y;
10984
+ }
10985
+ }
10986
+ this.scrollPositions.set(target, current);
10987
+ frame.update(this.updatePoint, true);
10878
10988
  }
10879
10989
  updateHandlers(handlers) {
10880
10990
  this.handlers = handlers;
10881
10991
  }
10882
10992
  end() {
10883
10993
  this.removeListeners && this.removeListeners();
10994
+ this.removeScrollListeners && this.removeScrollListeners();
10995
+ this.scrollPositions.clear();
10884
10996
  cancelFrame(this.updatePoint);
10885
10997
  }
10886
10998
  }
@@ -11212,6 +11324,7 @@
11212
11324
  dragSnapToOrigin,
11213
11325
  distanceThreshold,
11214
11326
  contextWindow: getContextWindow(this.visualElement),
11327
+ element: this.visualElement.current,
11215
11328
  });
11216
11329
  }
11217
11330
  /**