UNPKG

@aircall/blocks

Version:

Aircall Blocks — higher-level UI compositions built on @aircall/ds

79 lines (78 loc) 2.68 kB
import { t as ChatbotLoadingBlock } from "./chatbot-loading-block-DCJoZhC2.js"; import { Alert, AlertDescription, AlertTitle, useDsTranslation, useTheme } from "@aircall/ds"; import { useEffect, useId, useRef, useState } from "react"; import { jsx, jsxs } from "react/jsx-runtime"; import { CircleX } from "@aircall/react-icons"; import mermaid from "mermaid"; //#region src/components/chatbot-mermaid-block.tsx const STREAM_DEBOUNCE_MS = 500; /** Renders a fenced ```mermaid code block inside a chatbot response as an SVG diagram. */ function ChatbotMermaidBlock({ code, streaming = false }) { const t = useDsTranslation("blocks"); const { resolvedTheme } = useTheme(); const diagramId = useId().replace(/:/g, "-"); const renderCountRef = useRef(0); const containerRef = useRef(null); const [svg, setSvg] = useState(null); const [bindFunctions, setBindFunctions] = useState(); const [error, setError] = useState(false); useEffect(() => { if (resolvedTheme === void 0) return; let cancelled = false; function attemptRender() { mermaid.initialize({ startOnLoad: false, theme: resolvedTheme === "dark" ? "dark" : "default", securityLevel: "strict", suppressErrorRendering: true }); setError(false); renderCountRef.current += 1; const renderId = `mermaid-${diagramId}-${renderCountRef.current}`; mermaid.render(renderId, code).then((result) => { if (cancelled) return; setSvg(result.svg); setBindFunctions(() => result.bindFunctions); }).catch(() => { if (cancelled) return; if (!streaming) setError(true); }); } if (!streaming) { attemptRender(); return () => { cancelled = true; }; } const timeout = setTimeout(attemptRender, STREAM_DEBOUNCE_MS); return () => { cancelled = true; clearTimeout(timeout); }; }, [ code, diagramId, resolvedTheme, streaming ]); useEffect(() => { if (svg && containerRef.current) bindFunctions === null || bindFunctions === void 0 || bindFunctions(containerRef.current); }, [svg, bindFunctions]); if (error) return /* @__PURE__ */ jsxs(Alert, { variant: "error", className: "mt-4 first:mt-0", children: [ /* @__PURE__ */ jsx(CircleX, { "aria-hidden": "true" }), /* @__PURE__ */ jsx(AlertTitle, { children: t("chatbotResponse.mermaidErrorTitle") }), /* @__PURE__ */ jsx(AlertDescription, { children: t("chatbotResponse.mermaidErrorDescription") }) ] }); if (!svg) return /* @__PURE__ */ jsx(ChatbotLoadingBlock, {}); return /* @__PURE__ */ jsx("div", { ref: containerRef, className: "mt-4 overflow-auto first:mt-0", dangerouslySetInnerHTML: { __html: svg } }); } //#endregion export { ChatbotMermaidBlock };