| import React, { useEffect, useRef, useState } from "react"; |
|
|
| export default function Mermaid({ chart }) { |
| const ref = useRef(null); |
| const [svg, setSvg] = useState(""); |
| const [error, setError] = useState(false); |
|
|
| useEffect(() => { |
| let isMounted = true; |
| |
| async function renderMermaid() { |
| try { |
| setError(false); |
| const { default: mermaid } = await import("https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs"); |
| |
| mermaid.initialize({ |
| startOnLoad: false, |
| theme: "dark", |
| securityLevel: "loose", |
| fontFamily: "Inter, sans-serif", |
| }); |
|
|
| if (isMounted && ref.current) { |
| const id = `mermaid-${Math.random().toString(36).substr(2, 9)}`; |
| const { svg } = await mermaid.render(id, chart); |
| if (isMounted) { |
| setSvg(svg); |
| } |
| } |
| } catch (err) { |
| console.error("Mermaid rendering failed:", err); |
| if (isMounted) { |
| setError(true); |
| } |
| } |
| } |
|
|
| renderMermaid(); |
| return () => { |
| isMounted = false; |
| }; |
| }, [chart]); |
|
|
| const getLoadingContent = () => { |
| if (error) { |
| return `<div class="error" style="color: #ffb4a9; font-size: 0.9rem;">Failed to render diagram. Please check the syntax.</div>`; |
| } |
| return `<div class="loading">Rendering diagram...</div>`; |
| }; |
|
|
| return ( |
| <div |
| ref={ref} |
| className="mermaid-container" |
| style={{ |
| display: "flex", |
| justifyContent: "center", |
| padding: "1rem", |
| background: "rgba(0,0,0,0.2)", |
| borderRadius: "8px", |
| margin: "1rem 0", |
| overflowX: "auto" |
| }} |
| dangerouslySetInnerHTML={{ __html: svg || getLoadingContent() }} |
| /> |
| ); |
| } |
|
|