mirror of
https://github.com/excalidraw/excalidraw.git
synced 2025-05-03 10:00:07 -04:00
feat: text-to-diagram (#7325)
Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
This commit is contained in:
parent
dd8a7d41e2
commit
14845a343b
37 changed files with 1381 additions and 510 deletions
153
src/components/TTDDialog/common.ts
Normal file
153
src/components/TTDDialog/common.ts
Normal file
|
@ -0,0 +1,153 @@
|
|||
import { MermaidOptions } from "@excalidraw/mermaid-to-excalidraw";
|
||||
import { MermaidToExcalidrawResult } from "@excalidraw/mermaid-to-excalidraw/dist/interfaces";
|
||||
import { DEFAULT_EXPORT_PADDING, DEFAULT_FONT_SIZE } from "../../constants";
|
||||
import {
|
||||
convertToExcalidrawElements,
|
||||
exportToCanvas,
|
||||
} from "../../packages/excalidraw/index";
|
||||
import { NonDeletedExcalidrawElement } from "../../element/types";
|
||||
import { AppClassProperties, BinaryFiles } from "../../types";
|
||||
import { canvasToBlob } from "../../data/blob";
|
||||
|
||||
const resetPreview = ({
|
||||
canvasRef,
|
||||
setError,
|
||||
}: {
|
||||
canvasRef: React.RefObject<HTMLDivElement>;
|
||||
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,
|
||||
options: MermaidOptions,
|
||||
) => Promise<MermaidToExcalidrawResult>;
|
||||
}>;
|
||||
}
|
||||
|
||||
interface ConvertMermaidToExcalidrawFormatProps {
|
||||
canvasRef: React.RefObject<HTMLDivElement>;
|
||||
mermaidToExcalidrawLib: MermaidToExcalidrawLibProps;
|
||||
text: string;
|
||||
setError: (error: Error | null) => void;
|
||||
data: React.MutableRefObject<{
|
||||
elements: readonly NonDeletedExcalidrawElement[];
|
||||
files: BinaryFiles | null;
|
||||
}>;
|
||||
}
|
||||
|
||||
export const convertMermaidToExcalidraw = async ({
|
||||
canvasRef,
|
||||
mermaidToExcalidrawLib,
|
||||
text,
|
||||
setError,
|
||||
data,
|
||||
}: ConvertMermaidToExcalidrawFormatProps) => {
|
||||
const canvasNode = canvasRef.current;
|
||||
const parent = canvasNode?.parentElement;
|
||||
|
||||
if (!canvasNode || !parent) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!text) {
|
||||
resetPreview({ canvasRef, setError });
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const api = await mermaidToExcalidrawLib.api;
|
||||
|
||||
const { elements, files } = await api.parseMermaidToExcalidraw(text, {
|
||||
fontSize: DEFAULT_FONT_SIZE,
|
||||
});
|
||||
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)
|
||||
await canvasToBlob(canvas);
|
||||
parent.style.background = "var(--default-bg-color)";
|
||||
canvasNode.replaceChildren(canvas);
|
||||
} catch (err: any) {
|
||||
console.error(err);
|
||||
parent.style.background = "var(--default-bg-color)";
|
||||
if (text) {
|
||||
setError(err);
|
||||
}
|
||||
|
||||
throw err;
|
||||
}
|
||||
};
|
||||
|
||||
export const LOCAL_STORAGE_KEY_MERMAID_TO_EXCALIDRAW = "mermaid-to-excalidraw";
|
||||
export const saveMermaidDataToStorage = (data: string) => {
|
||||
try {
|
||||
localStorage.setItem(LOCAL_STORAGE_KEY_MERMAID_TO_EXCALIDRAW, data);
|
||||
} catch (error: any) {
|
||||
// Unable to access window.localStorage
|
||||
console.error(error);
|
||||
}
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
};
|
Loading…
Add table
Add a link
Reference in a new issue