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}