92 lines
2.8 KiB
TypeScript
92 lines
2.8 KiB
TypeScript
/* eslint-disable react-hooks/exhaustive-deps */
|
|
import { useEffect, useRef } from "react";
|
|
import useModalStore from "../stores/useModalStore";
|
|
import { AnimatePresence, motion } from "motion/react";
|
|
import CloseIcon from "./icons/CloseIcon";
|
|
import Button from "./ui/Button";
|
|
|
|
function ModalContainer() {
|
|
const { modal, setModal } = useModalStore();
|
|
const divRef = useRef<HTMLDivElement>(null);
|
|
const backdropRef = useRef<HTMLDivElement>(null);
|
|
const popoverRef = useRef<HTMLDivElement>(null);
|
|
const containerRef = useRef<HTMLDivElement>(null);
|
|
|
|
function handleResize() {
|
|
if (!popoverRef.current) return;
|
|
|
|
if (divRef.current!.clientHeight > popoverRef.current!.clientHeight) {
|
|
backdropRef.current!.style.height = `${divRef.current!.clientHeight}px`;
|
|
} else {
|
|
backdropRef.current!.style.height = `100%`;
|
|
}
|
|
}
|
|
|
|
function handleKeydown(e: KeyboardEvent) {
|
|
if (e.key !== "Escape") return;
|
|
setModal(null);
|
|
}
|
|
|
|
const rootRef = useRef<HTMLDivElement>(null);
|
|
|
|
useEffect(() => {
|
|
window.addEventListener("resize", handleResize);
|
|
window.addEventListener("keydown", handleKeydown);
|
|
|
|
return () => {
|
|
window.removeEventListener("resize", handleResize);
|
|
window.removeEventListener("keydown", handleKeydown);
|
|
};
|
|
}, []);
|
|
|
|
return (
|
|
<AnimatePresence>
|
|
{modal && (
|
|
<motion.div
|
|
ref={rootRef}
|
|
initial={{ opacity: 0 }}
|
|
animate={{ opacity: 1 }}
|
|
exit={{ opacity: 0 }}
|
|
className="h-full"
|
|
>
|
|
<div
|
|
ref={popoverRef}
|
|
className="fixed inset-0 flex flex-col items-center justify-center overflow-y-auto bg-black/70"
|
|
>
|
|
<div className="max-h-full">
|
|
<div ref={divRef} className="p-[1.08vw]">
|
|
<div
|
|
ref={backdropRef}
|
|
className="absolute inset-0 cursor-pointer"
|
|
onClick={() => setModal(null)}
|
|
/>
|
|
<div
|
|
ref={containerRef}
|
|
className="relative w-full"
|
|
// style={{
|
|
// height: `calc(${backdropRef.current?.clientHeight}px - 1.08vw * 2)`,
|
|
// }}
|
|
>
|
|
{modal}
|
|
<Button
|
|
onlyIcon
|
|
variant="secondary"
|
|
className="absolute top-[1.111vw] right-[1.111vw]"
|
|
onClick={() => setModal(null)}
|
|
>
|
|
<span className="2xl:w-[1.389vw] 2xl:h-[1.389vw] w-5 h-5">
|
|
<CloseIcon />
|
|
</span>
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</motion.div>
|
|
)}
|
|
</AnimatePresence>
|
|
);
|
|
}
|
|
|
|
export default ModalContainer;
|