import classNames from "classnames"; import { ReactNode, FC, useEffect, useRef, useState } from "react"; import { useTranslation } from "react-i18next"; import ViewState from "../../ReactViewModels/ViewState"; import Styles from "./explorer-window.scss"; const SLIDE_DURATION = 300; interface IProps { isVisible?: boolean; onClose: () => void; viewState: ViewState; onStartAnimatingIn?: () => void; onDoneAnimatingIn?: () => void; children: ReactNode; isTopElement?: boolean; } const ModalPopup: FC = (props) => { const { t } = useTranslation(); const [inTransition, setInTransition] = useState(false); const animationTimeout = useRef | null>(null); function slideIn() { props.onStartAnimatingIn?.(); setInTransition(true); animationTimeout.current = setTimeout(() => { setInTransition(false); setTimeout(() => { props.onDoneAnimatingIn?.(); }, SLIDE_DURATION); }); } function slideOut() { setInTransition(true); animationTimeout.current = setTimeout(() => { setInTransition(false); }, SLIDE_DURATION); } useEffect(() => { // Clear previous timeout if (animationTimeout.current !== null) { clearTimeout(animationTimeout.current); animationTimeout.current = null; } if (props.isVisible) { slideIn(); } else { slideOut(); } /* eslint-disable-next-line react-hooks/exhaustive-deps */ }, [props.isVisible]); useEffect(() => { const escKeyListener = (e: KeyboardEvent) => { // Only explicitly check share modal state, move to levels/"layers of modals" logic if we need to go any deeper if (e.key === "Escape" && !props.viewState.shareModalIsVisible) { props.onClose(); } }; window.addEventListener("keydown", escKeyListener, true); }); // Render explorer panel when explorer panel should be visible // or when sliding out (animation) const renderUi = props.isVisible || inTransition; return renderUi ? (
) : null; }; export default ModalPopup;