"use client"; import { cn } from "@/lib/utils"; import { AnimatePresence, motion } from "framer-motion"; import React, { ReactNode, createContext, useContext, useEffect, useRef, useState, } from "react"; interface ModalContextType { open: boolean; setOpen: (open: boolean) => void; } const ModalContext = createContext(undefined); export const ModalProvider = ({ children }: { children: ReactNode }) => { const [open, setOpen] = useState(false); return ( {children} ); }; export const useModal = () => { const context = useContext(ModalContext); if (!context) { throw new Error("useModal must be used within a ModalProvider"); } return context; }; export function Modal({ children }: { children: ReactNode }) { return {children}; } export const ModalTrigger = ({ children, className, }: { children: ReactNode; className?: string; }) => { const { setOpen } = useModal(); return ( ); }; export const ModalBody = ({ children, className, }: { children: ReactNode; className?: string; }) => { const { open } = useModal(); useEffect(() => { if (open) { document.body.style.overflow = "hidden"; } else { document.body.style.overflow = "auto"; } }, [open]); const modalRef = useRef(null); const { setOpen } = useModal(); useOutsideClick(modalRef, () => setOpen(false)); return ( {open && ( {children} )} ); }; export const ModalContent = ({ children, className, }: { children: ReactNode; className?: string; }) => { return (
{children}
); }; export const ModalFooter = ({ children, className, }: { children: ReactNode; className?: string; }) => { return (
{children}
); }; const Overlay = ({ className }: { className?: string }) => { return ( ); }; const CloseIcon = () => { const { setOpen } = useModal(); return ( ); }; // Hook to detect clicks outside of a component. // Add it in a separate file, I've added here for simplicity export const useOutsideClick = ( ref: React.RefObject, callback: Function ) => { useEffect(() => { const listener = (event: any) => { // DO NOTHING if the element being clicked is the target element or their children if (!ref.current || ref.current.contains(event.target)) { return; } callback(event); }; document.addEventListener("mousedown", listener); document.addEventListener("touchstart", listener); return () => { document.removeEventListener("mousedown", listener); document.removeEventListener("touchstart", listener); }; }, [ref, callback]); };