2023-09-11 12:53:31 +02:00
|
|
|
import { useEffect } from 'react';
|
|
|
|
|
|
|
|
export const useOnBlur = (
|
|
|
|
containerRef: React.RefObject<HTMLElement>,
|
2023-10-02 14:25:46 +02:00
|
|
|
callback: () => void,
|
2023-09-11 12:53:31 +02:00
|
|
|
): void => {
|
|
|
|
useEffect(() => {
|
2023-09-18 14:42:41 +02:00
|
|
|
let mouseDownInside = false;
|
|
|
|
|
|
|
|
const handleMouseDown = (event: MouseEvent) => {
|
|
|
|
mouseDownInside =
|
|
|
|
containerRef.current?.contains(event.target as Node) || false;
|
|
|
|
};
|
|
|
|
|
2023-09-11 12:53:31 +02:00
|
|
|
const handleBlur = (event: FocusEvent) => {
|
|
|
|
setTimeout(() => {
|
|
|
|
if (
|
2023-09-18 14:42:41 +02:00
|
|
|
!mouseDownInside &&
|
2023-09-11 12:53:31 +02:00
|
|
|
containerRef.current &&
|
|
|
|
!containerRef.current.contains(document.activeElement)
|
|
|
|
) {
|
|
|
|
callback();
|
|
|
|
}
|
2023-09-18 14:42:41 +02:00
|
|
|
// Reset the flag for the next sequence of events.
|
|
|
|
mouseDownInside = false;
|
2023-09-11 12:53:31 +02:00
|
|
|
}, 0);
|
|
|
|
};
|
|
|
|
|
2023-09-18 14:42:41 +02:00
|
|
|
document.addEventListener('mousedown', handleMouseDown);
|
|
|
|
|
2023-09-11 12:53:31 +02:00
|
|
|
const containerElement = containerRef.current;
|
|
|
|
if (containerElement) {
|
|
|
|
containerElement.addEventListener('blur', handleBlur, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
return () => {
|
2023-09-18 14:42:41 +02:00
|
|
|
document.removeEventListener('mousedown', handleMouseDown);
|
2023-09-11 12:53:31 +02:00
|
|
|
if (containerElement) {
|
|
|
|
containerElement.removeEventListener('blur', handleBlur, true);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}, [containerRef, callback]);
|
|
|
|
};
|