diff options
| author | Armand Philippot <git@armandphilippot.com> | 2022-06-08 12:07:08 +0200 |
|---|---|---|
| committer | Armand Philippot <git@armandphilippot.com> | 2022-06-08 12:19:28 +0200 |
| commit | 58cb40f031f395ca9efccff674ba0f2dae723f50 (patch) | |
| tree | d69539a66a83da85689b8f7e835492eedc068e1f /src/utils | |
| parent | 43bddd9506d790ad6707fe71f28a4ecfa635c8f1 (diff) | |
fix(settings): close tooltip when modal is closing
The event was not captured so the tooltip remained open when the
settings was closed. It prevented to click on the toolbar buttons.
Diffstat (limited to 'src/utils')
| -rw-r--r-- | src/utils/hooks/use-click-outside.tsx | 46 | ||||
| -rw-r--r-- | src/utils/hooks/use-on-click-outside.tsx | 52 |
2 files changed, 52 insertions, 46 deletions
diff --git a/src/utils/hooks/use-click-outside.tsx b/src/utils/hooks/use-click-outside.tsx deleted file mode 100644 index cead98b..0000000 --- a/src/utils/hooks/use-click-outside.tsx +++ /dev/null @@ -1,46 +0,0 @@ -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: (target: EventTarget) => 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(e.target); - }, - [el, callback] - ); - - useEffect(() => { - document.addEventListener('mousedown', handleEvent); - document.addEventListener('focusin', handleEvent); - - return () => { - document.removeEventListener('mousedown', handleEvent); - document.removeEventListener('focusin', handleEvent); - }; - }, [handleEvent]); -}; - -export default useClickOutside; diff --git a/src/utils/hooks/use-on-click-outside.tsx b/src/utils/hooks/use-on-click-outside.tsx new file mode 100644 index 0000000..04827b8 --- /dev/null +++ b/src/utils/hooks/use-on-click-outside.tsx @@ -0,0 +1,52 @@ +import { RefObject, useCallback, useEffect, useRef } from 'react'; + +export type UseOnClickOutsideCallback = (target: Node) => void; + +/** + * Detect click/focus outside an element and fire a callback function. + * + * @param {UseOnClickOutsideCallback} callback - A callback function to fire. + * @param {boolean} useCapture - Define event propagation method. Default: true. + * @returns {RefObject} A React reference object. + */ +const useOnClickOutside = <T extends HTMLElement>( + callback: UseOnClickOutsideCallback, + useCapture: boolean = true +): RefObject<T> => { + const ref = useRef<T | null>(null); + + /** + * Check if the target is outside the ref. + * + * @param {Node} target - The event target. + * @returns {boolean | null} True if the target is outside the ref. + */ + const isTargetOutside = (target: Node): boolean | null => { + return ref.current && !ref.current.contains(target); + }; + + /** + * Fire the callback if the event target is outside. + */ + const handler = useCallback( + (e: MouseEvent | FocusEvent) => { + if (e.target && isTargetOutside(e.target as Node)) + callback(e.target as Node); + }, + [callback] + ); + + useEffect(() => { + document.addEventListener('click', handler, useCapture); + document.addEventListener('focusin', handler, useCapture); + + return () => { + document.removeEventListener('click', handler); + document.removeEventListener('focusin', handler); + }; + }, [handler, useCapture]); + + return ref; +}; + +export default useOnClickOutside; |
