diff options
Diffstat (limited to 'packages/excalidraw/components/TTDDialog/common.ts')
| -rw-r--r-- | packages/excalidraw/components/TTDDialog/common.ts | 161 |
1 files changed, 161 insertions, 0 deletions
diff --git a/packages/excalidraw/components/TTDDialog/common.ts b/packages/excalidraw/components/TTDDialog/common.ts new file mode 100644 index 0000000..4191126 --- /dev/null +++ b/packages/excalidraw/components/TTDDialog/common.ts @@ -0,0 +1,161 @@ +import type { MermaidConfig } from "@excalidraw/mermaid-to-excalidraw"; +import type { MermaidToExcalidrawResult } from "@excalidraw/mermaid-to-excalidraw/dist/interfaces"; +import { DEFAULT_EXPORT_PADDING, EDITOR_LS_KEYS } from "../../constants"; +import { convertToExcalidrawElements, exportToCanvas } from "../../index"; +import type { NonDeletedExcalidrawElement } from "../../element/types"; +import type { AppClassProperties, BinaryFiles } from "../../types"; +import { canvasToBlob } from "../../data/blob"; +import { EditorLocalStorage } from "../../data/EditorLocalStorage"; +import { t } from "../../i18n"; + +const resetPreview = ({ + canvasRef, + setError, +}: { + canvasRef: React.RefObject<HTMLDivElement | null>; + setError: (error: Error | null) => void; +}) => { + const canvasNode = canvasRef.current; + + if (!canvasNode) { + return; + } + const parent = canvasNode.parentElement; + if (!parent) { + return; + } + parent.style.background = ""; + setError(null); + canvasNode.replaceChildren(); +}; + +export interface MermaidToExcalidrawLibProps { + loaded: boolean; + api: Promise<{ + parseMermaidToExcalidraw: ( + definition: string, + config?: MermaidConfig, + ) => Promise<MermaidToExcalidrawResult>; + }>; +} + +interface ConvertMermaidToExcalidrawFormatProps { + canvasRef: React.RefObject<HTMLDivElement | null>; + mermaidToExcalidrawLib: MermaidToExcalidrawLibProps; + mermaidDefinition: string; + setError: (error: Error | null) => void; + data: React.MutableRefObject<{ + elements: readonly NonDeletedExcalidrawElement[]; + files: BinaryFiles | null; + }>; +} + +export const convertMermaidToExcalidraw = async ({ + canvasRef, + mermaidToExcalidrawLib, + mermaidDefinition, + setError, + data, +}: ConvertMermaidToExcalidrawFormatProps) => { + const canvasNode = canvasRef.current; + const parent = canvasNode?.parentElement; + + if (!canvasNode || !parent) { + return; + } + + if (!mermaidDefinition) { + resetPreview({ canvasRef, setError }); + return; + } + + try { + const api = await mermaidToExcalidrawLib.api; + + let ret; + try { + ret = await api.parseMermaidToExcalidraw(mermaidDefinition); + } catch (err: any) { + ret = await api.parseMermaidToExcalidraw( + mermaidDefinition.replace(/"/g, "'"), + ); + } + const { elements, files } = ret; + setError(null); + + data.current = { + elements: convertToExcalidrawElements(elements, { + regenerateIds: true, + }), + files, + }; + + const canvas = await exportToCanvas({ + elements: data.current.elements, + files: data.current.files, + exportPadding: DEFAULT_EXPORT_PADDING, + maxWidthOrHeight: + Math.max(parent.offsetWidth, parent.offsetHeight) * + window.devicePixelRatio, + }); + // if converting to blob fails, there's some problem that will + // likely prevent preview and export (e.g. canvas too big) + try { + await canvasToBlob(canvas); + } catch (e: any) { + if (e.name === "CANVAS_POSSIBLY_TOO_BIG") { + throw new Error(t("canvasError.canvasTooBig")); + } + throw e; + } + parent.style.background = "var(--default-bg-color)"; + canvasNode.replaceChildren(canvas); + } catch (err: any) { + parent.style.background = "var(--default-bg-color)"; + if (mermaidDefinition) { + setError(err); + } + + throw err; + } +}; + +export const saveMermaidDataToStorage = (mermaidDefinition: string) => { + EditorLocalStorage.set( + EDITOR_LS_KEYS.MERMAID_TO_EXCALIDRAW, + mermaidDefinition, + ); +}; + +export const insertToEditor = ({ + app, + data, + text, + shouldSaveMermaidDataToStorage, +}: { + app: AppClassProperties; + data: React.MutableRefObject<{ + elements: readonly NonDeletedExcalidrawElement[]; + files: BinaryFiles | null; + }>; + text?: string; + shouldSaveMermaidDataToStorage?: boolean; +}) => { + const { elements: newElements, files } = data.current; + + if (!newElements.length) { + return; + } + + app.addElementsFromPasteOrLibrary({ + elements: newElements, + files, + position: "center", + fitToContent: true, + }); + app.setOpenDialog(null); + + if (shouldSaveMermaidDataToStorage && text) { + saveMermaidDataToStorage(text); + } +}; |
