{"version":3,"file":"use-long-press.cjs","names":[],"sources":["../../src/hooks/use-long-press.ts"],"sourcesContent":["import { useEffect } from \"react\";\nimport { useLatestRef } from \"./use-latest-ref\";\nimport type { RefObject } from \"react\";\n\nexport interface UseLongPressOptions {\n    /** Press duration in ms. Default `500`. */\n    delay?: number;\n    /** Pixel threshold — finger/mouse movement beyond this cancels the press. Default `10`. */\n    moveThreshold?: number;\n}\n\n/**\n * Detect long-press / long-tap gestures. Fires `fn` after `delay` ms\n * while the element is held. Cancels on move beyond `moveThreshold` or\n * pointer up before `delay`.\n *\n * @example\n * const ref = useRef<HTMLDivElement>(null);\n * useLongPress(ref, () => openContextMenu(), { delay: 600 });\n */\nexport function useLongPress<T extends HTMLElement>(\n    ref: RefObject<T | null>,\n    fn: () => void,\n    options: UseLongPressOptions = {},\n): void {\n    const { delay = 500, moveThreshold = 10 } = options;\n    const fnRef = useLatestRef(fn);\n\n    useEffect(() => {\n        const node = ref.current;\n        if (!node) return;\n        let timer: ReturnType<typeof setTimeout> | null = null;\n        let startX = 0;\n        let startY = 0;\n\n        const cancel = (): void => {\n            if (timer) {\n                clearTimeout(timer);\n                timer = null;\n            }\n        };\n\n        const onDown = (event: PointerEvent): void => {\n            startX = event.clientX;\n            startY = event.clientY;\n            cancel();\n            timer = setTimeout(() => {\n                timer = null;\n                fnRef.current();\n            }, delay);\n        };\n\n        const onMove = (event: PointerEvent): void => {\n            if (timer === null) return;\n            const dx = event.clientX - startX;\n            const dy = event.clientY - startY;\n            if (Math.hypot(dx, dy) > moveThreshold) cancel();\n        };\n\n        node.addEventListener(\"pointerdown\", onDown);\n        node.addEventListener(\"pointermove\", onMove);\n        node.addEventListener(\"pointerup\", cancel);\n        node.addEventListener(\"pointercancel\", cancel);\n        node.addEventListener(\"pointerleave\", cancel);\n        return () => {\n            cancel();\n            node.removeEventListener(\"pointerdown\", onDown);\n            node.removeEventListener(\"pointermove\", onMove);\n            node.removeEventListener(\"pointerup\", cancel);\n            node.removeEventListener(\"pointercancel\", cancel);\n            node.removeEventListener(\"pointerleave\", cancel);\n        };\n    }, [ref, delay, moveThreshold, fnRef]);\n}\n"],"mappings":"+DAoBA,SAAgB,EACZ,EACA,EACA,EAA+B,CAAC,EAC5B,CACJ,GAAM,CAAE,QAAQ,IAAK,gBAAgB,IAAO,EACtC,EAAQ,EAAA,aAAa,CAAE,GAE7B,EAAA,EAAA,UAAA,KAAgB,CACZ,IAAM,EAAO,EAAI,QACjB,GAAI,CAAC,EAAM,OACX,IAAI,EAA8C,KAC9C,EAAS,EACT,EAAS,EAEP,MAAqB,CACvB,AAEI,KADA,aAAa,CAAK,EACV,KAEhB,EAEM,EAAU,GAA8B,CAC1C,EAAS,EAAM,QACf,EAAS,EAAM,QACf,EAAO,EACP,EAAQ,eAAiB,CACrB,EAAQ,KACR,EAAM,QAAQ,CAClB,EAAG,CAAK,CACZ,EAEM,EAAU,GAA8B,CAC1C,GAAI,IAAU,KAAM,OACpB,IAAM,EAAK,EAAM,QAAU,EACrB,EAAK,EAAM,QAAU,EACvB,KAAK,MAAM,EAAI,CAAE,EAAI,GAAe,EAAO,CACnD,EAOA,OALA,EAAK,iBAAiB,cAAe,CAAM,EAC3C,EAAK,iBAAiB,cAAe,CAAM,EAC3C,EAAK,iBAAiB,YAAa,CAAM,EACzC,EAAK,iBAAiB,gBAAiB,CAAM,EAC7C,EAAK,iBAAiB,eAAgB,CAAM,MAC/B,CACT,EAAO,EACP,EAAK,oBAAoB,cAAe,CAAM,EAC9C,EAAK,oBAAoB,cAAe,CAAM,EAC9C,EAAK,oBAAoB,YAAa,CAAM,EAC5C,EAAK,oBAAoB,gBAAiB,CAAM,EAChD,EAAK,oBAAoB,eAAgB,CAAM,CACnD,CACJ,EAAG,CAAC,EAAK,EAAO,EAAe,CAAK,CAAC,CACzC"}