(options: {
onClick?: (event: React.MouseEvent) => void
onMultipleClick: (event: React.MouseEvent, count: number) => boolean | void
})
| 3 | import { cancellablePromise, useCancellablePromises } from './use-cancellable-promises' |
| 4 | |
| 5 | const useMultipleClick = (options: { |
| 6 | onClick?: (event: React.MouseEvent) => void |
| 7 | onMultipleClick: (event: React.MouseEvent, count: number) => boolean | void |
| 8 | }) => { |
| 9 | const { onClick, onMultipleClick } = options |
| 10 | const api = useCancellablePromises() |
| 11 | const pointRef = React.useRef<{ x: number; y: number }>() |
| 12 | const countRef = React.useRef(0) |
| 13 | |
| 14 | const isSamePoint = (event: React.MouseEvent | MouseEvent | Touch) => { |
| 15 | const point = pointRef.current |
| 16 | return point |
| 17 | ? Math.abs(event.clientY - point.y) < 10 && Math.abs(event.clientX - point.x) < 10 |
| 18 | : false |
| 19 | } |
| 20 | |
| 21 | const clear = () => { |
| 22 | api.clearPendingPromises() |
| 23 | pointRef.current = undefined |
| 24 | } |
| 25 | |
| 26 | const handleMultipleClick = (event: React.MouseEvent) => { |
| 27 | if (event.button === 2) return |
| 28 | const point = pointRef.current |
| 29 | if (point) { |
| 30 | if (isSamePoint(event)) { |
| 31 | api.clearPendingPromises() |
| 32 | countRef.current += 1 |
| 33 | if (onMultipleClick(event, countRef.current) === false) { |
| 34 | clear() |
| 35 | return |
| 36 | } |
| 37 | } else { |
| 38 | clear() |
| 39 | } |
| 40 | } else { |
| 41 | countRef.current = 1 |
| 42 | pointRef.current = { |
| 43 | x: event.clientX, |
| 44 | y: event.clientY, |
| 45 | } |
| 46 | } |
| 47 | if (countRef.current === 1 && onMultipleClick(event, 1) === false) { |
| 48 | clear() |
| 49 | } else { |
| 50 | const waitForClick = cancellablePromise(api.delay(500)) |
| 51 | api.appendPendingPromise(waitForClick) |
| 52 | return waitForClick.promise |
| 53 | .then(() => { |
| 54 | api.removePendingPromise(waitForClick) |
| 55 | if (onClick) onClick(event) |
| 56 | pointRef.current = undefined |
| 57 | }) |
| 58 | .catch(errorInfo => { |
| 59 | api.removePendingPromise(waitForClick) |
| 60 | if (!errorInfo.isCanceled) { |
| 61 | throw errorInfo.error |
| 62 | } |
no test coverage detected
searching dependent graphs…