File size: 1,153 Bytes
63522a5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import React from "react";

/**
 * Hook to call a callback function when an element is clicked outside
 * @param callback The callback function to call when the element is clicked outside
 */
export const useClickOutsideElement = <T extends HTMLElement>(
  callback: () => void,
  ignoreOutsideClickRef?: React.RefObject<HTMLElement | null>,
) => {
  const ref = React.useRef<T>(null);
  // Hold the latest callback in a ref so the listener effect doesn't
  // re-register every render when callers pass an inline arrow function.
  const callbackRef = React.useRef(callback);
  React.useEffect(() => {
    callbackRef.current = callback;
  }, [callback]);

  React.useEffect(() => {
    const handleClickOutside = (event: MouseEvent) => {
      const target = event.target as Node;
      if (!ref.current) return;
      if (ref.current.contains(target)) return;
      if (ignoreOutsideClickRef?.current?.contains(target)) return;
      callbackRef.current();
    };

    document.addEventListener("click", handleClickOutside);

    return () => document.removeEventListener("click", handleClickOutside);
  }, [ignoreOutsideClickRef]);

  return ref;
};