Files
formbricks-formbricks/apps/web/lib/utils/hooks/useClickOutside.ts
2025-04-21 15:57:54 +02:00

37 lines
1.3 KiB
TypeScript

import { RefObject, useEffect } from "react";
// Improved version of https://usehooks.com/useOnClickOutside/
export const useClickOutside = (
ref: RefObject<HTMLElement | HTMLDivElement | null>,
handler: (event: MouseEvent | TouchEvent) => void
): void => {
useEffect(() => {
let startedInside = false;
let startedWhenMounted = false;
const listener = (event: MouseEvent | TouchEvent) => {
// Do nothing if `mousedown` or `touchstart` started inside ref element
if (startedInside || !startedWhenMounted) return;
// Do nothing if clicking ref's element or descendent elements
if (!ref.current || ref.current.contains(event.target as Node)) return;
handler(event);
};
const validateEventStart = (event: MouseEvent | TouchEvent) => {
startedWhenMounted = ref.current !== null;
startedInside = ref.current !== null && ref.current.contains(event.target as Node);
};
document.addEventListener("mousedown", validateEventStart);
document.addEventListener("touchstart", validateEventStart);
document.addEventListener("click", listener);
return () => {
document.removeEventListener("mousedown", validateEventStart);
document.removeEventListener("touchstart", validateEventStart);
document.removeEventListener("click", listener);
};
}, [ref, handler]);
};