export default function Modal(title: string, on_close: () => void, children: () => JSXElement) {
let close = () => { };
const pop = popup((
) => {
let bg: HTMLDivElement;
let modal: HTMLDivElement;
const animate_opt: KeyframeAnimationOptions = {
duration: 200,
fill: "forwards"
};
close = () => {
if (!bg || !modal) {
pop.close();
on_close();
return;
}
modal.animate([{ top: "50%", transform: "translate(-50%,-50%)" }, { top: "100vh", transform: "translate(-50%, 0)" }], { ...animate_opt, easing: "ease-in" })
on_close();
bg.animate([{ opacity: 1 }, { opacity: 0 }], { ...animate_opt, easing: "ease-in" }).finished.then(() => {
pop.close();
})
}
createEffect(() => {
if (!bg || !modal) {
return;
}
bg.animate([{ opacity: 0 }, { opacity: 1 }], { ...animate_opt, easing: "ease-out" });
modal.animate([{ top: "100vh", transform: "translate(-50%, 0)" }, { top: "50%", transform: "translate(-50%,-50%)" }], { ...animate_opt, easing: "ease-out" })
})
return (
<div class="absolute z-50 inset-0 overflow-hidden">
<div ref={bg} class="inset-0 absolute bg-[rgba(0,0,0,.3)]" onclick={
close
}>
</div>
<div ref={modal} class="border absolute left-1/2 rounded-md bg-white p-3 ">
<div class="flex justify-between items-center gap-4">
<span>{title}</span> <AiOutlineClose onclick={close} size="1.25em" class="cursor-pointer" />
</div>
<div class="mt-2">{children()}</div>
</div>
</div>
)
})
return { close };
}