"use client"; import clsx from "clsx"; import { type FC, type PropsWithChildren, useCallback, useLayoutEffect, useRef, useState, } from "react"; import styles from "./dialog.module.css"; interface DialogProps { active?: boolean; className?: string; onAnimationDone?: () => void; onClickOutside?: () => void; width?: string; height?: string; allowOverflow?: boolean; drawer?: boolean; overlayClassname?: string; drawerClassname?: string; verticalScroll?: boolean; style?: React.CSSProperties; enableSkip?: boolean; } export const Dialog: FC> = ({ active, children, className, onAnimationDone, onClickOutside, width, height = "auto", allowOverflow, drawer = true, overlayClassname = "", drawerClassname = "", verticalScroll = true, style, enableSkip, ...rest }) => { const ref = useRef(null); const innerContainerRef = useRef(null); const [shouldClose, setShouldClose] = useState(false); // open/close dialog in response to active prop useLayoutEffect(() => { if (ref.current) { if (active) { if (ref.current.open) return; // cannot open twice ref.current.showModal(); } else { setShouldClose(true); setTimeout(() => { ref.current?.close(); setShouldClose(false); }, 400 /* animation duration */); } } }, [active]); let handleClickOutside = useCallback(() => { innerContainerRef.current && (innerContainerRef.current.style.marginBottom = "0px"); onClickOutside?.(); onAnimationDone?.(); }, [onAnimationDone, onClickOutside]); // click handler for closing the dialog useLayoutEffect(() => { // https://stackoverflow.com/questions/25864259/how-to-close-the-new-html-dialog-tag-by-clicking-on-its-backdrop const _handleClickOutside = (event) => { if (ref.current?.open) { const rect = ref.current.getBoundingClientRect(); const isInDialog = rect.top <= event.clientY && event.clientY <= rect.top + rect.height && rect.left <= event.clientX && event.clientX <= rect.left + rect.width; if (!isInDialog) { // ref.current.close(); handleClickOutside(); } } }; ref.current.addEventListener("click", _handleClickOutside); return () => { ref.current.removeEventListener("click", _handleClickOutside); }; }, [handleClickOutside]); return (
{active ? children : null}
); };