53 lines
1.2 KiB
TypeScript
53 lines
1.2 KiB
TypeScript
import { useCallback, useRef } from "react"
|
|
|
|
const DEFAULT_DELAY_MS = 500
|
|
|
|
export function useLongPress(
|
|
onLongPress: () => void,
|
|
options?: { delay?: number; disabled?: boolean }
|
|
) {
|
|
const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null)
|
|
const firedRef = useRef(false)
|
|
const delay = options?.delay ?? DEFAULT_DELAY_MS
|
|
const disabled = options?.disabled ?? false
|
|
|
|
const clear = useCallback(() => {
|
|
if (timerRef.current) {
|
|
clearTimeout(timerRef.current)
|
|
timerRef.current = null
|
|
}
|
|
}, [])
|
|
|
|
const onPointerDown = useCallback(
|
|
(e: React.PointerEvent) => {
|
|
if (disabled) return
|
|
if (e.pointerType === "mouse" && e.button !== 0) return
|
|
firedRef.current = false
|
|
clear()
|
|
timerRef.current = setTimeout(() => {
|
|
firedRef.current = true
|
|
onLongPress()
|
|
}, delay)
|
|
},
|
|
[clear, delay, disabled, onLongPress]
|
|
)
|
|
|
|
const onClickCapture = useCallback(
|
|
(e: React.MouseEvent) => {
|
|
if (!firedRef.current) return
|
|
e.preventDefault()
|
|
e.stopPropagation()
|
|
firedRef.current = false
|
|
},
|
|
[]
|
|
)
|
|
|
|
return {
|
|
onPointerDown,
|
|
onPointerUp: clear,
|
|
onPointerLeave: clear,
|
|
onPointerCancel: clear,
|
|
onClickCapture,
|
|
}
|
|
}
|