import React, { useEffect, useRef } from 'react'; import { createPortal } from 'react-dom'; const FOCUSABLE = 'button:not(:disabled), [href], input:not(:disabled), [tabindex]:not([tabindex="-1"])'; export function ConfirmationPopup({ open, id, kicker, title, description, cancelLabel, confirmLabel, busy = false, onCancel, onConfirm, }) { const overlayRef = useRef(null); const dialogRef = useRef(null); const cancelRef = useRef(null); const busyRef = useRef(busy); const onCancelRef = useRef(onCancel); busyRef.current = busy; onCancelRef.current = onCancel; useEffect(() => { if (!open) return undefined; const previousFocus = document.activeElement; const background = [...(overlayRef.current?.parentElement?.children || [])] .filter((element) => !element.classList.contains('client-confirmation-popup')) .map((element) => [element, element.inert]); background.forEach(([element]) => { element.inert = true; }); const previousOverflow = document.body.style.overflow; document.body.style.overflow = 'hidden'; const frame = requestAnimationFrame(() => cancelRef.current?.focus()); const onKeyDown = (event) => { if (event.key === 'Escape' && !busyRef.current) { event.preventDefault(); onCancelRef.current(); return; } if (event.key !== 'Tab') return; const controls = [...(dialogRef.current?.querySelectorAll(FOCUSABLE) || [])]; if (!controls.length) return; const first = controls[0]; const last = controls.at(-1); if (!dialogRef.current?.contains(document.activeElement)) { event.preventDefault(); first.focus(); } else if (event.shiftKey && document.activeElement === first) { event.preventDefault(); last.focus(); } else if (!event.shiftKey && document.activeElement === last) { event.preventDefault(); first.focus(); } }; document.addEventListener('keydown', onKeyDown); return () => { cancelAnimationFrame(frame); document.removeEventListener('keydown', onKeyDown); background.forEach(([element, inert]) => { element.inert = inert; }); document.body.style.overflow = previousOverflow; requestAnimationFrame(() => previousFocus?.focus?.()); }; }, [open]); return createPortal(
{ if (event.target === event.currentTarget && !busy) onCancel(); }} >
{kicker && {kicker}}

{title}

{description}

, document.querySelector('.app.client-app') || document.body, ); }