import { createContext, useContext, useEffect, useState, useCallback, useMemo, DependencyList } from "react"; import { HideModal, ModalContextType, ModalType, ShowModal } from "./types"; import { generateKey, isFunctionalComponent } from "../utility"; // Create a context for managing modals const ModalContext = createContext({} as ModalContextType); /** * Custom hook to manage modal context. * @param component The component to be displayed as a modal. * @param inputs The dependencies to track for useMemo and useEffect. * @returns A tuple containing functions to show and hide the modal. */ const useModalContext = (component: ModalType, inputs: DependencyList = []): [ShowModal, HideModal] => { // Ensure that only functional components are used as modals if (!isFunctionalComponent(component)) { throw new Error( "Only stateless components can be used as an argument to useModal. You have probably passed a class component where a function was expected." ); } // Generate a unique key for the modal const key = useMemo(generateKey, []); // Memoize the modal component const modal = useMemo(() => component, inputs); // Access the modal context const context = useContext(ModalContext); // State to track if modal is shown or hidden const [isShown, setShown] = useState(false); // Function to show the modal const showModal = useCallback(() => setShown(true), []); // Function to hide the modal const hideModal = useCallback(() => setShown(false), []); // Effect to manage modal visibility useEffect(() => { if (isShown) { context.showModal(key, modal); } else { context.hideModal(key); } // Hide modal when parent component unmounts return () => context.hideModal(key); }, [modal, isShown]); return [showModal, hideModal]; }; export { useModalContext, ModalContext };