UNPKG

@mantine/hooks

Version:

A collection of 50+ hooks for state and UI management

96 lines (95 loc) 3.08 kB
"use client"; import { useEffect, useMemo, useRef } from "react"; //#region packages/@mantine/hooks/src/use-long-press/use-long-press.ts const DEFAULT_EVENTS = ["mouse", "touch"]; const DEFAULT_MOVE_THRESHOLD = 10; function useLongPress(onLongPress, options = {}) { const { threshold = 400, events = DEFAULT_EVENTS, cancelOnMove = false, onStart, onFinish, onCancel } = options; const isLongPressActive = useRef(false); const isPressed = useRef(false); const timeout = useRef(-1); const startPosition = useRef(null); useEffect(() => () => window.clearTimeout(timeout.current), []); return useMemo(() => { if (typeof onLongPress !== "function") return {}; const moveEnabled = cancelOnMove !== false; const moveThreshold = cancelOnMove === true ? DEFAULT_MOVE_THRESHOLD : cancelOnMove === false ? 0 : cancelOnMove; const start = (event) => { if (!isMouseEvent(event) && !isTouchEvent(event)) return; if (onStart) onStart(event); startPosition.current = getEventPosition(event); isPressed.current = true; timeout.current = window.setTimeout(() => { onLongPress(event); isLongPressActive.current = true; }, threshold); }; const cancel = (event) => { if (!isMouseEvent(event) && !isTouchEvent(event)) return; if (isLongPressActive.current) { if (onFinish) onFinish(event); } else if (isPressed.current) { if (onCancel) onCancel(event); } isLongPressActive.current = false; isPressed.current = false; startPosition.current = null; if (timeout.current !== -1) { window.clearTimeout(timeout.current); timeout.current = -1; } }; const move = (event) => { if (!moveEnabled || !isPressed.current || isLongPressActive.current) return; const position = getEventPosition(event); if (!position || !startPosition.current) return; const dx = position.x - startPosition.current.x; const dy = position.y - startPosition.current.y; if (Math.sqrt(dx * dx + dy * dy) > moveThreshold) cancel(event); }; const handlers = {}; if (events.includes("mouse")) { handlers.onMouseDown = start; handlers.onMouseUp = cancel; handlers.onMouseLeave = cancel; if (moveEnabled) handlers.onMouseMove = move; } if (events.includes("touch")) { handlers.onTouchStart = start; handlers.onTouchEnd = cancel; handlers.onTouchCancel = cancel; if (moveEnabled) handlers.onTouchMove = move; } return handlers; }, [ onLongPress, threshold, onCancel, onFinish, onStart, cancelOnMove, events.join(",") ]); } function getEventPosition(event) { if (isTouchEvent(event)) { const touch = event.touches[0] ?? event.changedTouches[0]; return touch ? { x: touch.clientX, y: touch.clientY } : null; } return { x: event.clientX, y: event.clientY }; } function isTouchEvent(event) { return window.TouchEvent ? event.nativeEvent instanceof TouchEvent : "touches" in event.nativeEvent; } function isMouseEvent(event) { return event.nativeEvent instanceof MouseEvent; } //#endregion export { useLongPress }; //# sourceMappingURL=use-long-press.mjs.map