{"version":3,"file":"index.mjs","sources":["../../../../src/gestures/press/index.ts"],"sourcesContent":["import { secondsToMilliseconds } from \"motion-utils\"\nimport { cancelFrame, frame } from \"../../frameloop/frame\"\nimport { time } from \"../../frameloop/sync-time\"\nimport { bindToScope } from \"../../scope/active\"\nimport { isHTMLElement } from \"../../utils/is-html-element\"\nimport { ElementOrSelector } from \"../../utils/resolve-elements\"\nimport { isDragActive } from \"../drag/state/is-active\"\nimport { EventOptions } from \"../types\"\nimport { isNodeOrChild } from \"../utils/is-node-or-child\"\nimport { isPrimaryPointer } from \"../utils/is-primary-pointer\"\nimport { setupGesture } from \"../utils/setup\"\nimport { OnPressStartEvent, PressHandlers, PressOptions } from \"./types\"\nimport { isElementKeyboardAccessible } from \"./utils/is-keyboard-accessible\"\nimport { enableKeyboardPress } from \"./utils/keyboard\"\nimport { isPressing } from \"./utils/state\"\n\n/**\n * Filter out events that are not primary pointer events, or are triggering\n * while a Motion gesture is active.\n */\nfunction isValidPressEvent(event: PointerEvent) {\n    return isPrimaryPointer(event) && !isDragActive()\n}\n\nconst claimedPointerDownEvents = new WeakSet<Event>()\n\n/**\n * Max distance in px between consecutive presses of a `count` sequence.\n * Android's `ViewConfiguration` double tap slop is 100dp.\n */\nconst sequenceSlop = 100\n\n/**\n * Max distance in px a pointer can move during a held press (`hold`\n * pending, or `repeat`). Android's `ViewConfiguration` touch slop is 8dp.\n */\nconst holdSlop = 8\n\nconst exceeds = (a: PointerEvent, b: PointerEvent, max: number) =>\n    Math.hypot(a.clientX - b.clientX, a.clientY - b.clientY) > max\n\nconst preventDefault = (event: Event) => event.preventDefault()\n\n/**\n * A `count` sequence waiting for its next press.\n */\ninterface PressSequence {\n    count: number\n    event: PointerEvent\n    handlers: PressHandlers\n    expire: (force?: unknown) => true | void\n}\n\nexport interface PointerEventOptions extends EventOptions, PressOptions {\n    useGlobalTarget?: boolean\n    stopPropagation?: boolean\n}\n\n/**\n * Create a press gesture.\n *\n * Press is different to `\"pointerdown\"`, `\"pointerup\"` in that it\n * automatically filters out secondary pointer events like right\n * click and multitouch.\n *\n * It also adds accessibility support for keyboards, where\n * an element with a press gesture will receive focus and\n *  trigger on Enter `\"keydown\"` and `\"keyup\"` events.\n *\n * This is different to a browser's `\"click\"` event, which does\n * respond to keyboards but only for the `\"click\"` itself, rather\n * than the press start and end/cancel. The element also needs\n * to be focusable for this to work, whereas a press gesture will\n * make an element focusable by default.\n *\n * `onPressStart` fires on the first pointer or key down, and can return\n * a function to call when the press ends, or an object of handlers for\n * this press:\n *\n * ```js\n * press(button, () => ({\n *   onHold: (progress) => {},\n *   onComplete: (event, { success }) => {},\n * }), { hold: 0.5 })\n * ```\n *\n * @public\n */\nexport function press(\n    targetOrSelector: ElementOrSelector,\n    onPressStart: OnPressStartEvent,\n    options: PointerEventOptions = {}\n): VoidFunction {\n    onPressStart = bindToScope(onPressStart)\n\n    const [targets, eventOptions, cancelEvents] = setupGesture(\n        targetOrSelector,\n        options\n    )\n\n    const sequences = new WeakMap<Element, PressSequence>()\n\n    const startPress = (startEvent: PointerEvent) => {\n        const target = startEvent.currentTarget as Element\n\n        if (!isValidPressEvent(startEvent)) return\n        if (claimedPointerDownEvents.has(startEvent)) return\n\n        if (options.stopPropagation) {\n            claimedPointerDownEvents.add(startEvent)\n        }\n\n        /**\n         * Options are read per press so they can be updated between presses.\n         */\n        const {\n            count: presses = 1,\n            countTimeout = 0.3,\n            hold = 0,\n            repeat,\n        } = options\n        const downTime = time.now()\n        const holdTime = secondsToMilliseconds(hold)\n        const timeout = secondsToMilliseconds(countTimeout)\n        let previous = sequences.get(target)\n\n        /**\n         * A press during a `count` sequence continues it. If it's too late\n         * or too far away, the sequence is cancelled and this press starts\n         * a new one.\n         */\n        if (\n            previous?.expire(exceeds(previous.event, startEvent, sequenceSlop))\n        ) {\n            previous = undefined\n        } else if (previous) {\n            cancelFrame(previous.expire)\n            sequences.delete(target)\n        }\n\n        const count = previous ? previous.count + 1 : 1\n        const isFinal = count >= presses\n        const isHeld = isFinal && (hold || repeat)\n        let isActive = !hold\n        let repeats = 0\n        let handlers: PressHandlers\n\n        isPressing.add(target)\n\n        if (previous) {\n            handlers = previous.handlers\n        } else {\n            const result = onPressStart(target, startEvent)\n            handlers =\n                typeof result === \"function\"\n                    ? { onComplete: result }\n                    : result || {}\n        }\n\n        isFinal && isActive && handlers.onActive?.()\n\n        /**\n         * While held, `onHold` reports progress from 0 to 1 over `hold`,\n         * then over each `repeat`. Each cycle reports exactly 1 at its end,\n         * then 0 on the next frame.\n         */\n        const repeatTime = secondsToMilliseconds(repeat!)\n        let length = holdTime || repeatTime\n        let cycleEnd = downTime + length\n        let isCycleStart = true\n\n        const tick = () => {\n            if (eventOptions.signal!.aborted) return cancelFrame(tick)\n\n            let progress = Math.min(1 - (cycleEnd - time.now()) / length, 1)\n\n            /**\n             * The frame after a boundary reports 0, so each cycle visibly\n             * restarts. Boundaries are timed from `downTime`, so this\n             * doesn't delay the next one. If a long frame has already\n             * passed the next boundary, it reports 1 instead.\n             */\n            if (isCycleStart && progress < 1) progress = 0\n            isCycleStart = false\n            handlers.onHold?.(progress)\n\n            if (progress < 1) return\n\n            if (isActive) {\n                handlers.onRepeat?.(++repeats)\n            } else {\n                isActive = true\n                handlers.onActive?.()\n            }\n\n            if (repeat) {\n                isCycleStart = true\n                cycleEnd += length = repeatTime\n            } else {\n                cancelFrame(tick)\n            }\n        }\n\n        /**\n         * End listeners run in the capture phase so a descendant calling\n         * stopPropagation() in its own pointerup handler can't prevent the\n         * press gesture from ending. This also keeps the gesture-end\n         * ordering consistent with the drag gesture. See #2794.\n         */\n        const endEventOptions = { ...eventOptions, capture: true }\n\n        const onPointerEnd = (endEvent: PointerEvent, success: boolean) => {\n            /**\n             * Another touch lifting (for instance after a pinch) doesn't\n             * end the press.\n             */\n            if (!isPrimaryPointer(endEvent)) return\n\n            window.removeEventListener(\n                \"pointerup\",\n                onPointerUp,\n                endEventOptions\n            )\n            window.removeEventListener(\n                \"pointercancel\",\n                onPointerCancel,\n                endEventOptions\n            )\n            window.removeEventListener(\n                \"pointermove\",\n                onPointerMove,\n                endEventOptions\n            )\n            target.removeEventListener(\"contextmenu\", preventDefault)\n            cancelFrame(tick)\n            isPressing.delete(target)\n\n            /**\n             * A press that ends while a drag is active is a cancel.\n             */\n            if (isDragActive()) success = false\n\n            if (success && !isFinal) {\n                /**\n                 * Wait for the next press of the sequence, and cancel the\n                 * gesture if it doesn't arrive in time.\n                 */\n                const end = time.now()\n\n                /**\n                 * Cancels the sequence if it's `force`d, or the interval\n                 * has passed. Runs every frame, where `force` is frame\n                 * data, so it's checked with `=== true`.\n                 */\n                const expire = (force?: unknown) => {\n                    const isAborted = eventOptions.signal!.aborted\n                    if (\n                        isAborted ||\n                        force === true ||\n                        time.now() - end > timeout\n                    ) {\n                        cancelFrame(expire)\n                        sequences.delete(target)\n                        isAborted ||\n                            handlers.onComplete?.(endEvent, { success: false })\n                        return true\n                    }\n                }\n                sequences.set(target, {\n                    count,\n                    event: startEvent,\n                    handlers,\n                    expire,\n                })\n                frame.update(expire, true)\n            } else {\n                /**\n                 * Releasing before `hold` is reached is a cancel.\n                 */\n                handlers.onComplete?.(endEvent, {\n                    success: success && isActive,\n                })\n            }\n        }\n\n        const onPointerUp = (upEvent: PointerEvent) => {\n            onPointerEnd(\n                upEvent,\n                (target as any) === window ||\n                    (target as any) === document ||\n                    options.useGlobalTarget ||\n                    isNodeOrChild(target, upEvent.target as Element)\n            )\n        }\n\n        const onPointerCancel = (cancelEvent: PointerEvent) => {\n            onPointerEnd(cancelEvent, false)\n        }\n\n        /**\n         * Moving during a pending long press, or a repeating press, cancels\n         * it, so scrolling on touch devices doesn't trigger it. A drag\n         * starting during a `count` sequence cancels it.\n         */\n        const onPointerMove = (moveEvent: PointerEvent) => {\n            if (\n                isPrimaryPointer(moveEvent) &&\n                (((repeat || !isActive) &&\n                    exceeds(startEvent, moveEvent, holdSlop)) ||\n                    (presses > 1 && isDragActive()))\n            ) {\n                onPointerCancel(moveEvent)\n            }\n        }\n\n        window.addEventListener(\"pointerup\", onPointerUp, endEventOptions)\n        window.addEventListener(\n            \"pointercancel\",\n            onPointerCancel,\n            endEventOptions\n        )\n\n        if (isHeld || presses > 1) {\n            window.addEventListener(\n                \"pointermove\",\n                onPointerMove,\n                endEventOptions\n            )\n        }\n\n        if (isHeld) {\n            frame.update(tick, true)\n            /**\n             * Touch devices open a context menu or callout on long press,\n             * which would cancel the gesture.\n             */\n            target.addEventListener(\"contextmenu\", preventDefault, {\n                ...eventOptions,\n                passive: false,\n            })\n        }\n    }\n\n    targets.forEach((target: EventTarget) => {\n        const pointerDownTarget = options.useGlobalTarget ? window : target\n        pointerDownTarget.addEventListener(\n            \"pointerdown\",\n            startPress as EventListener,\n            eventOptions\n        )\n\n        if (isHTMLElement(target)) {\n            target.addEventListener(\n                \"focus\",\n                () => enableKeyboardPress(target, eventOptions),\n                eventOptions\n            )\n\n            if (\n                !isElementKeyboardAccessible(target) &&\n                !target.hasAttribute(\"tabindex\")\n            ) {\n                target.tabIndex = 0\n            }\n        }\n    })\n\n    return cancelEvents\n}\n"],"names":[],"mappings":"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"}