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>( 9 ref: Ref<T>, 10 onDismiss: () => void 11) { 12 const hasPriority = usePriority(ref); 13 14 useLayoutEffect(() => { 15 if (!hasPriority) return; 16 17 function onKey(event: KeyboardEvent) { 18 if ( 19 event.isComposing || 20 event.defaultPrevented || 21 event.code !== 'Escape' 22 ) 23 return; 24 event.preventDefault(); 25 onDismiss(); 26 } 27 28 function onClick(event: MouseEvent | TouchEvent) { 29 if ( 30 !ref.current || 31 contains(ref.current, event.target) || 32 event.defaultPrevented 33 ) 34 return; 35 event.preventDefault(); 36 onDismiss(); 37 } 38 39 document.addEventListener('mousedown', onClick); 40 document.addEventListener('touchstart', onClick); 41 document.addEventListener('keydown', onKey); 42 43 return () => { 44 document.removeEventListener('mousedown', onClick); 45 document.removeEventListener('touchstart', onClick); 46 document.removeEventListener('keydown', onKey); 47 }; 48 }, [ref, hasPriority, onDismiss]); 49}