blob: 066c1c2fdd9157ea2b6ad65b5dce9cd855d304c0 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
import { RefObject, useCallback, useEffect } from 'react';
/**
* Listen for click/focus outside an element and execute the given callback.
*
* @param el - A React reference to an element.
* @param callback - A callback function to execute on click outside.
*/
const useClickOutside = (el: RefObject<HTMLElement>, callback: () => void) => {
/**
* Check if an event target is outside an element.
*
* @param {RefObject<HTMLElement>} ref - A React reference object.
* @param {EventTarget} target - An event target.
* @returns {boolean} True if the event target is outside the ref object.
*/
const isTargetOutside = (
ref: RefObject<HTMLElement>,
target: EventTarget
): boolean => {
if (!ref.current) return false;
return !ref.current.contains(target as Node);
};
const handleEvent = useCallback(
(e: MouseEvent | FocusEvent) => {
if (e.target && isTargetOutside(el, e.target)) callback();
},
[el, callback]
);
useEffect(() => {
document.addEventListener('mousedown', handleEvent);
document.addEventListener('focusin', handleEvent);
return () => {
document.removeEventListener('mousedown', handleEvent);
document.removeEventListener('focusin', handleEvent);
};
}, [handleEvent]);
};
export default useClickOutside;
|