|
| 1 | +import { SyntheticEvent, useCallback, useRef } from "react"; |
| 2 | + |
| 3 | +/** |
| 4 | + * **`useDoubleClick`**: hook to handle double click event. Double clicking in react as well as with vanilla js, it is possible to manage it but it is not possible to have both managers on the same element. Thanks to this hook it is possible to do this, and it works with all events that can be associated with a user click (for example _mousedown_ but also _touchstart_). |
| 5 | + * @param {((evt: SyntheticEvent<T, E>) => Promise<void>|void)|Object} handler |
| 6 | + * @param {((evt: SyntheticEvent<T, E>) => Promise<void> | void)} handler.doubleClick - callback executed on double click. |
| 7 | + * @param {((evt: SyntheticEvent<T, E>) => Promise<void> | void)} [handler.singleClick] - callback executed on single click. |
| 8 | + * @param {number} [handler.tolerance=300] - delay to execute __singleClick__ callback. |
| 9 | + * @returns {((evt: SyntheticEvent<T, E>) => Promise<void> | void)} callback |
| 10 | + */ |
| 11 | +export const useDoubleClick = <T extends Element = Element, E extends Event = Event>(handler: ((evt: SyntheticEvent<T, E>) => Promise<void> | void) | { doubleClick: (evt: SyntheticEvent<T, E>) => Promise<void> | void, singleClick?: (evt: SyntheticEvent<T, E>) => Promise<void> | void, tolerance?: number }) => { |
| 12 | + const count = useRef(0); |
| 13 | + const tolerance = useRef("tolerance" in handler ? handler.tolerance : 300); |
| 14 | + const idTimeout = useRef<number>(); |
| 15 | + |
| 16 | + return useCallback((evt: SyntheticEvent<T, E>) => { |
| 17 | + "persist" in evt && evt.persist(); |
| 18 | + !!idTimeout.current && clearTimeout(idTimeout.current); |
| 19 | + count.current++; |
| 20 | + if (count.current === 1 && "singleClick" in handler && !!handler.singleClick) { |
| 21 | + idTimeout.current = setTimeout(() => { |
| 22 | + handler.singleClick!(evt); |
| 23 | + count.current = 0; |
| 24 | + }, tolerance.current) as unknown as number; |
| 25 | + } |
| 26 | + if (count.current === 2) { |
| 27 | + "doubleClick" in handler |
| 28 | + ? handler.doubleClick(evt) |
| 29 | + : handler(evt); |
| 30 | + count.current = 0; |
| 31 | + } |
| 32 | + }, [handler]); |
| 33 | +} |
0 commit comments