Mirror: React hooks for accessible, common web interactions. UI super powers without the UI.
1import { useLayoutEffect } from './utils/react'; 2import { contains } from './utils/element'; 3import { makePriorityHook } from './usePriority'; 4import { Ref } from './types'; 5 6const usePriority = makePriorityHook(); 7 8export function useDialogDismiss<T extends HTMLElement>(ref: Ref<T>, onDismiss: () => void) { 9 const hasPriority = usePriority(ref); 10 11 useLayoutEffect(() => { 12 if (!hasPriority) return; 13 14 function onKey(event: KeyboardEvent) { 15 if (event.isComposing || event.defaultPrevented || event.code !== 'Escape') return; 16 event.preventDefault(); 17 onDismiss(); 18 }; 19 20 function onClick(event: MouseEvent | TouchEvent) { 21 if (!ref.current || contains(ref.current, event.target) || event.defaultPrevented) return; 22 event.preventDefault(); 23 onDismiss(); 24 } 25 26 document.addEventListener('mousedown', onClick); 27 document.addEventListener('touchstart', onClick); 28 document.addEventListener('keydown', onKey); 29 30 return () => { 31 document.removeEventListener('mousedown', onClick); 32 document.removeEventListener('touchstart', onClick); 33 document.removeEventListener('keydown', onKey); 34 }; 35 }, [ref, hasPriority, onDismiss]); 36}