feat: publish Regex Tools 0.2.0
This commit is contained in:
71
src/components/ModalDialog.tsx
Normal file
71
src/components/ModalDialog.tsx
Normal file
@@ -0,0 +1,71 @@
|
||||
import { useEffect, useRef, type ReactNode } from "react";
|
||||
|
||||
export function ModalDialog({
|
||||
id,
|
||||
open,
|
||||
labelledBy,
|
||||
onClose,
|
||||
children,
|
||||
className = "",
|
||||
}: {
|
||||
readonly id: string;
|
||||
readonly open: boolean;
|
||||
readonly labelledBy: string;
|
||||
readonly onClose: () => void;
|
||||
readonly children: ReactNode;
|
||||
readonly className?: string;
|
||||
}) {
|
||||
const dialog = useRef<HTMLDialogElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const element = dialog.current;
|
||||
if (!element) return;
|
||||
|
||||
if (open && !element.open) {
|
||||
if (typeof element.showModal === "function") {
|
||||
element.showModal();
|
||||
} else {
|
||||
// jsdom and older browsers can still expose the content for a usable
|
||||
// non-modal fallback.
|
||||
element.setAttribute("open", "");
|
||||
}
|
||||
(
|
||||
element.querySelector<HTMLElement>("[data-dialog-initial-focus]") ??
|
||||
element
|
||||
).focus();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!open && element.open) {
|
||||
if (typeof element.close === "function") {
|
||||
element.close();
|
||||
} else {
|
||||
element.removeAttribute("open");
|
||||
}
|
||||
}
|
||||
}, [open]);
|
||||
|
||||
return (
|
||||
<dialog
|
||||
ref={dialog}
|
||||
id={id}
|
||||
className={`app-dialog auxiliary-dialog ${className}`.trim()}
|
||||
aria-labelledby={labelledBy}
|
||||
aria-modal="true"
|
||||
tabIndex={-1}
|
||||
onClose={onClose}
|
||||
onCancel={(event) => {
|
||||
event.preventDefault();
|
||||
onClose();
|
||||
}}
|
||||
onKeyDownCapture={(event) => {
|
||||
if (event.key !== "Escape") return;
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
onClose();
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</dialog>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user