import "./Modal.scss"; import React, { useState, useLayoutEffect, useRef } from "react"; import { createPortal } from "react-dom"; import clsx from "clsx"; import { KEYS } from "../keys"; import { useExcalidrawContainer, useIsMobile } from "./App"; import { AppState } from "../types"; export const Modal = (props: { className?: string; children: React.ReactNode; maxWidth?: number; onCloseRequest(): void; labelledBy: string; theme?: AppState["theme"]; }) => { const { theme = "light" } = props; const modalRoot = useBodyRoot(theme); if (!modalRoot) { return null; } const handleKeydown = (event: React.KeyboardEvent) => { if (event.key === KEYS.ESCAPE) { event.nativeEvent.stopImmediatePropagation(); event.stopPropagation(); props.onCloseRequest(); } }; return createPortal(
{props.children}
, modalRoot, ); }; const useBodyRoot = (theme: AppState["theme"]) => { const [div, setDiv] = useState(null); const isMobile = useIsMobile(); const isMobileRef = useRef(isMobile); isMobileRef.current = isMobile; const excalidrawContainer = useExcalidrawContainer(); useLayoutEffect(() => { if (div) { div.classList.toggle("excalidraw--mobile", isMobile); } }, [div, isMobile]); useLayoutEffect(() => { const isDarkTheme = !!excalidrawContainer?.classList.contains("theme--dark") || theme === "dark"; const div = document.createElement("div"); div.classList.add("excalidraw", "excalidraw-modal-container"); div.classList.toggle("excalidraw--mobile", isMobileRef.current); if (isDarkTheme) { div.classList.add("theme--dark"); div.classList.add("theme--dark-background-none"); } document.body.appendChild(div); setDiv(div); return () => { document.body.removeChild(div); }; }, [excalidrawContainer, theme]); return div; };