···
const usePriority = makePriorityHook();
-
export function useDialogDismiss<T extends HTMLElement>(
const hasPriority = usePriority(ref);
if (!ref.current || !hasPriority) return;
function onKey(event: KeyboardEvent) {
if (!event.isComposing && event.code === 'Escape') {
// The current dialog can be dismissed by pressing escape if it either has focus
···
document.addEventListener('mousedown', onClick);
document.addEventListener('touchstart', onClick);
document.addEventListener('keydown', onKey);
document.removeEventListener('mousedown', onClick);
document.removeEventListener('touchstart', onClick);
document.removeEventListener('keydown', onKey);
-
}, [ref, hasPriority, onDismiss]);
···
const usePriority = makePriorityHook();
+
export interface DismissableOptions {
+
export function useDismissable<T extends HTMLElement>(
+
options?: DismissableOptions
+
const focusLoss = !!(options && options.focusLoss);
const hasPriority = usePriority(ref);
if (!ref.current || !hasPriority) return;
+
function onFocusOut(event: FocusEvent) {
+
if (event.defaultPrevented) return;
+
const { target, relatedTarget } = event;
+
contains(ref.current, target) &&
+
!contains(ref.current, relatedTarget)
function onKey(event: KeyboardEvent) {
if (!event.isComposing && event.code === 'Escape') {
// The current dialog can be dismissed by pressing escape if it either has focus
···
+
if (focusLoss) document.body.addEventListener('focusout', onFocusOut);
document.addEventListener('mousedown', onClick);
document.addEventListener('touchstart', onClick);
document.addEventListener('keydown', onKey);
+
if (focusLoss) document.body.removeEventListener('focusout', onFocusOut);
document.removeEventListener('mousedown', onClick);
document.removeEventListener('touchstart', onClick);
document.removeEventListener('keydown', onKey);
+
}, [ref, hasPriority, focusLoss, onDismiss]);