{"version":3,"file":"index.mjs","sources":["../../../../src/gestures/drag/index.ts"],"sourcesContent":["import type { BoundingBox } from \"motion-utils\"\nimport type { InertiaOptions } from \"../../animation/types\"\nimport { acquireProjectionNode } from \"../../layout/LayoutAnimationBuilder\"\nimport type { MotionNodeOptions } from \"../../node/types\"\nimport type { VisualElement } from \"../../render/VisualElement\"\nimport { activeScope, addToScope } from \"../../scope/active\"\nimport {\n    resolveElements,\n    type ElementOrSelector,\n} from \"../../utils/resolve-elements\"\nimport type { DragElastic, DragHandler } from \"./types\"\nimport { VisualElementDragControls } from \"./VisualElementDragControls\"\n\n/**\n * @public\n */\nexport interface DragOptions {\n    /**\n     * Restrict dragging to a single axis. By default an element can be\n     * dragged on both axes.\n     */\n    axis?: \"x\" | \"y\"\n\n    /**\n     * The permitted draggable area. Either `top`/`left`/`right`/`bottom`\n     * distances in pixels, relative to the element's origin, or an element\n     * the draggable element must stay within.\n     */\n    constraints?: Partial<BoundingBox> | Element\n\n    /**\n     * How far, from `0` to `1`, the element can move outside its\n     * constraints. Can be set per edge. Defaults to `0.35`.\n     */\n    elastic?: DragElastic\n\n    /**\n     * Whether to carry the gesture's velocity into an inertia animation\n     * on release. Defaults to `true`.\n     */\n    momentum?: boolean\n\n    /**\n     * Options for the inertia animation that runs on release.\n     */\n    transition?: InertiaOptions\n\n    /**\n     * Animate back to the origin on release.\n     */\n    snapToOrigin?: boolean | \"x\" | \"y\"\n\n    /**\n     * Lock dragging to the first axis the pointer moves along.\n     */\n    directionLock?: boolean\n\n    /**\n     * Allow drag gestures to start on parent elements that are also\n     * draggable. By default, only the innermost draggable element moves.\n     */\n    propagation?: boolean\n\n    onStart?: DragHandler\n    onMove?: DragHandler\n    onEnd?: DragHandler\n    onDirectionLock?: (axis: \"x\" | \"y\") => void\n    onTransitionEnd?: () => void\n\n    /**\n     * Called when element constraints are measured. Return a new\n     * `BoundingBox` to override them.\n     */\n    onMeasureConstraints?: (constraints: BoundingBox) => BoundingBox | void\n}\n\nconst toProps = ({\n    axis,\n    constraints,\n    elastic,\n    momentum,\n    transition,\n    snapToOrigin,\n    directionLock,\n    propagation,\n    onStart,\n    onMove,\n    onEnd,\n    onDirectionLock,\n    onTransitionEnd,\n    onMeasureConstraints,\n}: DragOptions): MotionNodeOptions => ({\n    drag: axis || true,\n    dragConstraints: constraints,\n    dragElastic: elastic,\n    dragMomentum: momentum,\n    dragTransition: transition,\n    dragSnapToOrigin: snapToOrigin,\n    dragDirectionLock: directionLock,\n    dragPropagation: propagation,\n    onDragStart: onStart,\n    onDrag: onMove,\n    onDragEnd: onEnd,\n    onDirectionLock,\n    onDragTransitionEnd: onTransitionEnd,\n    onMeasureDragConstraints: onMeasureConstraints,\n})\n\nconst dragStyles = [\n    \"user-select\",\n    \"-webkit-user-select\",\n    \"-webkit-touch-callout\",\n    \"touch-action\",\n]\n\n/**\n * Apply the styles React's drag prop applies, so touch input drags\n * instead of panning the page, and text selection and native drag (ghost\n * image) don't interrupt the gesture. Returns a function that restores\n * the element's previous values.\n */\nfunction applyDragStyles(element: HTMLElement, axis?: \"x\" | \"y\") {\n    const { style } = element\n    const draggable = element.getAttribute(\"draggable\")\n    const prev = dragStyles.map((key) => style.getPropertyValue(key))\n    const touchAction = axis ? \"pan-\" + (axis === \"x\" ? \"y\" : \"x\") : \"none\"\n\n    dragStyles.forEach((key, i) =>\n        style.setProperty(key, i < 3 ? \"none\" : touchAction)\n    )\n    element.setAttribute(\"draggable\", \"false\")\n\n    return () => {\n        dragStyles.forEach((key, i) => style.setProperty(key, prev[i]))\n        draggable === null\n            ? element.removeAttribute(\"draggable\")\n            : element.setAttribute(\"draggable\", draggable)\n    }\n}\n\n/**\n * Make elements draggable. Returns a function that removes the gesture.\n *\n * ```javascript\n * const stop = drag(\"#box\", { axis: \"x\", constraints: { left: 0, right: 300 } })\n * ```\n *\n * The element's `x` and `y` are motion values shared with `animate()`\n * and `animateLayout()`, so these can animate the element after a drag.\n *\n * @public\n */\nexport function drag(\n    elementOrSelector: ElementOrSelector,\n    options: DragOptions = {}\n): VoidFunction {\n    const props = toProps(options)\n    const scope = activeScope.current\n\n    /**\n     * Run callbacks in the active scope, so work they start is collected.\n     */\n    if (scope) {\n        for (const key in props) {\n            const value = props[key as keyof MotionNodeOptions]\n            if (typeof value === \"function\") {\n                ;(props as any)[key] = scope.bind(value)\n            }\n        }\n    }\n\n    const cleanups = resolveElements(elementOrSelector).map((element) => {\n        scope?.track(element)\n        const [node, release] = acquireProjectionNode(element as HTMLElement)\n\n        /**\n         * Measure layout even when not animating it, as constraints and\n         * layout-shift correction are computed from it.\n         */\n        node.setOptions({ alwaysMeasureLayout: true })\n\n        const controls = new VisualElementDragControls(\n            node.options.visualElement as VisualElement<HTMLElement>,\n            () => props\n        )\n        const removeListeners = controls.addListeners()\n        const removeStyles = applyDragStyles(\n            element as HTMLElement,\n            options.axis\n        )\n\n        return () => {\n            removeStyles()\n            removeListeners?.()\n            controls.cancel()\n            controls.stopAnimation()\n            release()\n        }\n    })\n\n    return addToScope(() => cleanups.forEach((cleanup) => cleanup()))\n}\n"],"names":[],"mappings":"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"}