@shopgate/engage
Version:
Shopgate's ENGAGE library.
56 lines (53 loc) • 1.71 kB
JavaScript
// @ts-check
import { useRef, useCallback } from 'react';
/** @typedef {import('./useLongPress').LongPressHandlers} LongPressHandlers */
/** @typedef {import('./useLongPress').UseLongPressOptions} UseLongPressOptions */
/**
* Prevents the default context menu from appearing on long press.
* @param {MouseEvent} e The event object.
*/
const preventContextMenu = e => {
e.preventDefault();
};
// eslint-disable-next-line valid-jsdoc
/**
* Custom hook to handle long press interactions.
*
* @param {(e: Event) => void} callback - Function to call on long press.
* @param {UseLongPressOptions} [options={}] - Configuration and lifecycle callbacks.
* @returns {LongPressHandlers} An object containing event handlers for mouse and touch events.
*/
export default function useLongPress(callback, {
threshold = 1000,
onStart,
onFinish,
onCancel
} = {}) {
/** @type {import('react').MutableRefObject<number | undefined>} */
const timerRef = useRef(undefined);
const triggeredRef = useRef(false);
const start = useCallback(e => {
if (onStart) onStart(e);
triggeredRef.current = false;
timerRef.current = window.setTimeout(() => {
callback(e);
triggeredRef.current = true;
if (onFinish) onFinish(e);
}, threshold);
}, [onStart, threshold, callback, onFinish]);
const cancel = useCallback(e => {
window.clearTimeout(timerRef.current);
if (!triggeredRef.current && onCancel) {
onCancel(e);
}
}, [onCancel]);
return {
onMouseDown: start,
onTouchStart: start,
onMouseUp: cancel,
onMouseLeave: cancel,
onTouchEnd: cancel,
// prevents right-click or long-press menu
onContextMenu: preventContextMenu
};
}