import { Box } from '@rocket.chat/fuselage'; import type { MouseEvent, ReactElement, ReactNode, RefObject } from 'react'; import React, { useCallback, useEffect, useRef } from 'react'; const useEscapeKey = (onDismiss: (() => void) | undefined): void => { useEffect(() => { const closeOnEsc = (e: KeyboardEvent): void => { if (e.key !== 'Escape') { return; } e.stopPropagation(); onDismiss?.(); }; window.addEventListener('keydown', closeOnEsc); return (): void => { window.removeEventListener('keydown', closeOnEsc); }; }, [onDismiss]); }; const isAtBackdropChildren = (e: MouseEvent, ref: RefObject): boolean => { const backdrop = ref.current; const { parentElement } = e.target as HTMLElement; return (Boolean(parentElement) && backdrop?.contains(parentElement)) ?? false; }; const useOutsideClick = ( ref: RefObject, onDismiss: (() => void) | undefined, ): { onMouseDown: (e: MouseEvent) => void; onMouseUp: (e: MouseEvent) => void; } => { const hasClicked = useRef(false); const onMouseDown = useCallback( (e) => { if (isAtBackdropChildren(e, ref)) { hasClicked.current = false; return; } hasClicked.current = true; }, [ref], ); const onMouseUp = useCallback( (e: MouseEvent) => { if (isAtBackdropChildren(e, ref)) { hasClicked.current = false; return; } if (!hasClicked.current) { return; } hasClicked.current = false; e.stopPropagation(); onDismiss?.(); }, [onDismiss, ref], ); return { onMouseDown, onMouseUp, }; }; type ModalBackdropProps = { children?: ReactNode; onDismiss?: () => void; }; const ModalBackdrop = ({ children, onDismiss }: ModalBackdropProps): ReactElement => { const ref = useRef(null); useEscapeKey(onDismiss); const { onMouseDown, onMouseUp } = useOutsideClick(ref, onDismiss); return ( ); }; export default ModalBackdrop;