From 58cb40f031f395ca9efccff674ba0f2dae723f50 Mon Sep 17 00:00:00 2001 From: Armand Philippot Date: Wed, 8 Jun 2022 12:07:08 +0200 Subject: 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. --- src/utils/hooks/use-on-click-outside.tsx | 52 ++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 src/utils/hooks/use-on-click-outside.tsx (limited to 'src/utils/hooks/use-on-click-outside.tsx') 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 = ( + callback: UseOnClickOutsideCallback, + useCapture: boolean = true +): RefObject => { + const ref = useRef(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; -- cgit v1.2.3