TelegramPWA/src/hooks/useVirtualBackdrop.ts
2025-03-21 14:02:25 +04:00

48 lines
1.4 KiB
TypeScript

import type { RefObject } from 'react';
import { useEffect } from '../lib/teact/teact';
import { hasActiveViewTransition } from './animations/useViewTransition';
const BACKDROP_CLASSNAME = 'backdrop';
// This effect implements closing menus by clicking outside of them
// without adding extra elements to the DOM
export default function useVirtualBackdrop(
isOpen: boolean,
containerRef: RefObject<HTMLElement>,
onClose?: () => void | undefined,
ignoreRightClick?: boolean,
excludedClosestSelector?: string,
) {
useEffect(() => {
if (!isOpen || !onClose) {
return undefined;
}
const handleEvent = (e: MouseEvent) => {
const container = containerRef.current;
const target = e.target as HTMLElement | null;
if (!container || !target || (ignoreRightClick && e.button === 2) || hasActiveViewTransition()) {
return;
}
if ((
!container.contains(e.target as Node | null)
|| target.classList.contains(BACKDROP_CLASSNAME)
) && !(excludedClosestSelector && (
target.matches(excludedClosestSelector) || target.closest(excludedClosestSelector)
))) {
e.preventDefault();
e.stopPropagation();
onClose?.();
}
};
document.addEventListener('mousedown', handleEvent);
return () => {
document.removeEventListener('mousedown', handleEvent);
};
}, [excludedClosestSelector, ignoreRightClick, isOpen, containerRef, onClose]);
}