import { useState, useRef, useEffect, useDeferredValue } from "react"; import { BinaryFiles } from "../../types"; import { useApp } from "../App"; import { NonDeletedExcalidrawElement } from "../../element/types"; import { ArrowRightIcon } from "../icons"; import "./MermaidToExcalidraw.scss"; import { t } from "../../i18n"; import Trans from "../Trans"; import { LOCAL_STORAGE_KEY_MERMAID_TO_EXCALIDRAW, MermaidToExcalidrawLibProps, convertMermaidToExcalidraw, insertToEditor, saveMermaidDataToStorage, } from "./common"; import { TTDDialogPanels } from "./TTDDialogPanels"; import { TTDDialogPanel } from "./TTDDialogPanel"; import { TTDDialogInput } from "./TTDDialogInput"; import { TTDDialogOutput } from "./TTDDialogOutput"; const MERMAID_EXAMPLE = "flowchart TD\n A[Christmas] -->|Get money| B(Go shopping)\n B --> C{Let me think}\n C -->|One| D[Laptop]\n C -->|Two| E[iPhone]\n C -->|Three| F[Car]"; const importMermaidDataFromStorage = () => { try { const data = localStorage.getItem(LOCAL_STORAGE_KEY_MERMAID_TO_EXCALIDRAW); if (data) { return data; } } catch (error: any) { // Unable to access localStorage console.error(error); } return null; }; const MermaidToExcalidraw = ({ mermaidToExcalidrawLib, }: { mermaidToExcalidrawLib: MermaidToExcalidrawLibProps; }) => { const [text, setText] = useState(""); const deferredText = useDeferredValue(text.trim()); const [error, setError] = useState(null); const canvasRef = useRef(null); const data = useRef<{ elements: readonly NonDeletedExcalidrawElement[]; files: BinaryFiles | null; }>({ elements: [], files: null }); const app = useApp(); useEffect(() => { const data = importMermaidDataFromStorage() || MERMAID_EXAMPLE; setText(data); }, []); useEffect(() => { convertMermaidToExcalidraw({ canvasRef, data, mermaidToExcalidrawLib, setError, mermaidDefinition: deferredText, }).catch(() => {}); }, [deferredText, mermaidToExcalidrawLib]); const textRef = useRef(text); // slightly hacky but really quite simple // essentially, we want to save the text to LS when the component unmounts useEffect(() => { textRef.current = text; }, [text]); useEffect(() => { return () => { if (textRef.current) { saveMermaidDataToStorage(textRef.current); } }; }, []); return ( <>
( {el} )} sequenceLink={(el) => ( {el} )} />
setText(event.target.value)} /> { insertToEditor({ app, data, text, shouldSaveMermaidDataToStorage: true, }); }, label: t("mermaid.button"), icon: ArrowRightIcon, }} > ); }; export default MermaidToExcalidraw;