mirror of
https://github.com/utopia-os/utopia-ui.git
synced 2025-12-13 07:46:10 +00:00
67 lines
1.6 KiB
TypeScript
67 lines
1.6 KiB
TypeScript
import * as React from "react";
|
|
import { MouseEvent, useEffect, useRef } from "react";
|
|
|
|
|
|
const isClickInsideRectangle = (e: MouseEvent, element: HTMLElement) => {
|
|
const r = element.getBoundingClientRect();
|
|
|
|
return (
|
|
e.clientX > r.left &&
|
|
e.clientX < r.right &&
|
|
e.clientY > r.top &&
|
|
e.clientY < r.bottom
|
|
);
|
|
};
|
|
|
|
type Props = {
|
|
title: string;
|
|
isOpened: boolean;
|
|
onClose: () => void;
|
|
children: React.ReactNode;
|
|
};
|
|
|
|
const DialogModal = ({
|
|
title,
|
|
isOpened,
|
|
onClose,
|
|
children,
|
|
}: Props) => {
|
|
|
|
const ref = useRef<HTMLDialogElement>(null);
|
|
|
|
useEffect(() => {
|
|
if (isOpened) {
|
|
ref.current?.showModal();
|
|
ref.current?.classList.remove("tw-hidden");
|
|
document.body.classList.add("modal-open"); // prevent bg scroll
|
|
} else {
|
|
ref.current?.close();
|
|
ref.current?.classList.add("tw-hidden");
|
|
document.body.classList.remove("modal-open");
|
|
}
|
|
}, [isOpened]);
|
|
|
|
|
|
return (
|
|
<dialog className='tw-card tw-shadow-xl tw-absolute tw-right-0 tw-top-0 tw-bottom-0 tw-left-0 tw-m-auto tw-transition-opacity tw-duration-300'
|
|
|
|
ref={ref}
|
|
onCancel={onClose}
|
|
onClick={(e) =>
|
|
ref.current && !isClickInsideRectangle(e, ref.current) && onClose()
|
|
}
|
|
>
|
|
<div className="tw-card-body tw-p-2">
|
|
|
|
<h2 className='tw-text-2xl tw-font-semibold tw-mb-2 tw-text-center'>{title}</h2>
|
|
|
|
{children}
|
|
<button className="tw-btn tw-btn-sm tw-btn-circle tw-btn-ghost tw-absolute tw-right-2 tw-top-2" onClick={onClose}>✕</button>
|
|
|
|
</div>
|
|
</dialog>
|
|
);
|
|
};
|
|
|
|
export default DialogModal;
|