import { useState, useCallback, useMemo, useEffect, ReactNode } from 'react'; import { useOnboarding } from '@/hooks'; import { disableScroll, enableScroll } from '@/shared/helpers'; import { MODALS } from './consts'; import { ModalName, ModalProperties } from './types'; import { ModalContext } from './Context'; const { Provider } = ModalContext; type Props = { children: ReactNode; }; const ModalProvider = ({ children }: Props) => { const [modalName, setModalName] = useState(null); const [modalProps, setModalProps] = useState(null); const { isOnboardingActive } = useOnboarding(); const handleKeyDown = (event: KeyboardEvent) => { if (event.key === 'Escape') { modalProps.onClose(); // only exists in transaction modal and actually should extend onClose prop // however, cuz of Object.assign(defaultProps, props) it would be overrided // maybe it's worth to do a deep merge to handle such cases? if (modalProps.onAbort) modalProps.onAbort(); } }; const closeModal = useCallback(() => { setModalName(null); setModalProps(null); }, []); const showModal = useCallback( (name: K, props?: ModalProperties) => { const defaultProps = { onClose: closeModal }; setModalName(name); setModalProps(Object.assign(defaultProps, props)); }, [closeModal], ); const value = useMemo(() => ({ showModal, closeModal }), [showModal, closeModal]); useEffect(() => { if (!modalName || !modalProps || isOnboardingActive) return; disableScroll(); return () => { enableScroll(); }; }, [modalName, modalProps, isOnboardingActive]); useEffect(() => { if (!modalName || !modalProps) return; document.addEventListener('keydown', handleKeyDown, false); return () => { document.removeEventListener('keydown', handleKeyDown, false); }; // eslint-disable-next-line react-hooks/exhaustive-deps }, [modalName, modalProps]); const currentModal = useMemo(() => { if (modalName && modalProps) { const ModalComponent = MODALS[modalName]; // eslint-disable-next-line react/jsx-props-no-spreading return ; } }, [modalName, modalProps]); return ( {children} {currentModal} ); }; export { ModalProvider };