From 58cb40f031f395ca9efccff674ba0f2dae723f50 Mon Sep 17 00:00:00 2001
From: Armand Philippot <git@armandphilippot.com>
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 = <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;
-- 
cgit v1.2.3

