|
1 | 1 | /** |
2 | | - * Copyright IBM Corp. 2016, 2023 |
| 2 | + * Copyright IBM Corp. 2016, 2025 |
3 | 3 | * |
4 | 4 | * This source code is licensed under the Apache-2.0 license found in the |
5 | 5 | * LICENSE file in the root directory of this source tree. |
6 | 6 | */ |
7 | 7 |
|
8 | | -import { useEffect, useRef } from 'react'; |
9 | | -import { useEvent } from './useEvent'; |
| 8 | +import { useEffect, useRef, type RefObject } from 'react'; |
10 | 9 | import { canUseDOM } from './environment'; |
| 10 | +import { useWindowEvent } from './useEvent'; |
11 | 11 |
|
12 | | -export function useOutsideClick(ref, callback) { |
| 12 | +export const useOutsideClick = <T extends HTMLElement>( |
| 13 | + ref: RefObject<T>, |
| 14 | + callback: (event: MouseEvent) => void |
| 15 | +) => { |
13 | 16 | const savedCallback = useRef(callback); |
14 | 17 |
|
15 | 18 | useEffect(() => { |
16 | 19 | savedCallback.current = callback; |
17 | | - }); |
| 20 | + }, [callback]); |
18 | 21 |
|
19 | 22 | // We conditionally guard the `useEvent` hook for SSR. `canUseDOM` can be |
20 | 23 | // treated as a constant as it will be false when executed in a Node.js |
21 | 24 | // environment and true when executed in the browser |
22 | 25 | if (canUseDOM) { |
23 | 26 | // eslint-disable-next-line react-hooks/rules-of-hooks |
24 | | - useEvent(window, 'click', (event) => { |
25 | | - if (ref.current && !ref.current.contains(event.target)) { |
| 27 | + useWindowEvent('click', (event) => { |
| 28 | + const { target } = event; |
| 29 | + |
| 30 | + if ( |
| 31 | + target instanceof Node && |
| 32 | + ref.current && |
| 33 | + !ref.current.contains(target) |
| 34 | + ) { |
26 | 35 | savedCallback.current(event); |
27 | 36 | } |
28 | 37 | }); |
29 | 38 | } |
30 | | -} |
| 39 | +}; |
0 commit comments