@lobehub/ui
Version:
Lobe UI is an open-source UI component library for building AIGC web apps
1 lines • 5.29 kB
Source Map (JSON)
{"version":3,"file":"useMermaid.mjs","names":[],"sources":["../../src/hooks/useMermaid.ts"],"sourcesContent":["'use client';\n\nimport { useThemeMode } from 'antd-style';\nimport { renderMermaidSVG, type RenderOptions, type ThemeName, THEMES } from 'beautiful-mermaid';\nimport { useEffect, useId, useMemo, useState } from 'react';\n\nimport { prepareInlineMermaidSvg } from '@/Mermaid/SyntaxMermaid/prepareInlineSvg';\n\nimport { createCdnMermaidConfig, renderWithCdnMermaid } from './useMermaidCdn';\n\nexport type MermaidThemeName = 'lobe-theme' | ThemeName;\n\nexport interface MermaidRenderResult {\n error?: string;\n loading?: boolean;\n svg: string;\n}\n\n/**\n * beautiful-mermaid emits these as CSS custom properties on the SVG root and\n * derives the rest with color-mix(), so pointing them at antd's variables lets\n * the diagram follow the theme through CSS alone — no token subscription, and\n * no re-render (or re-layout) when the appearance changes.\n */\nconst LOBE_THEME_OPTIONS: RenderOptions = {\n accent: 'var(--ant-color-primary)',\n bg: 'var(--ant-color-bg-container)',\n border: 'var(--ant-color-border)',\n fg: 'var(--ant-color-text)',\n line: 'var(--ant-color-text-secondary)',\n muted: 'var(--ant-color-text-description)',\n surface: 'var(--ant-color-fill-tertiary)',\n transparent: true,\n};\n\nconst isNamedTheme = (theme?: MermaidThemeName): theme is ThemeName =>\n !!theme && theme !== 'lobe-theme' && theme in THEMES;\n\nexport const createMermaidOptions = (customTheme?: MermaidThemeName): RenderOptions =>\n isNamedTheme(customTheme) ? THEMES[customTheme]! : LOBE_THEME_OPTIONS;\n\n/**\n * beautiful-mermaid covers six diagram types; anything else throws here and is\n * handed to the CDN-loaded upstream mermaid instead.\n */\nexport const renderMermaid = (\n content: string,\n scopeId: string,\n customTheme?: MermaidThemeName,\n): MermaidRenderResult => {\n if (!content) return { svg: '' };\n try {\n const svg = renderMermaidSVG(content, createMermaidOptions(customTheme));\n return { svg: prepareInlineMermaidSvg(svg, scopeId) };\n } catch {\n return { error: 'unsupported', svg: '' };\n }\n};\n\nexport const useCdnMermaidFallback = (\n content: string,\n { enabled, theme: customTheme }: { enabled: boolean; theme?: MermaidThemeName },\n): MermaidRenderResult => {\n const { isDarkMode } = useThemeMode();\n const reactId = useId();\n const [result, setResult] = useState<MermaidRenderResult>({ svg: '' });\n\n useEffect(() => {\n if (!enabled || !content) {\n setResult({ svg: '' });\n return;\n }\n\n let active = true;\n setResult({ loading: true, svg: '' });\n\n const config = createCdnMermaidConfig(\n isDarkMode,\n isNamedTheme(customTheme) ? customTheme : undefined,\n );\n\n renderWithCdnMermaid(content, `mermaid-cdn-${reactId.replaceAll(':', '')}`, config)\n .then((svg) => {\n if (!active) return;\n setResult(svg ? { svg } : { error: 'Failed to render diagram', svg: '' });\n })\n .catch(() => {\n if (active) setResult({ error: 'Failed to render diagram', svg: '' });\n });\n\n return () => {\n active = false;\n };\n }, [enabled, content, isDarkMode, customTheme, reactId]);\n\n return result;\n};\n\nexport const useMermaid = (\n content: string,\n { theme: customTheme }: { theme?: MermaidThemeName } = {},\n): MermaidRenderResult => {\n const reactId = useId();\n const scopeId = useMemo(() => `mermaid-${reactId.replaceAll(':', '')}`, [reactId]);\n\n const primary = useMemo(\n () => renderMermaid(content, scopeId, customTheme),\n [content, scopeId, customTheme],\n );\n\n const fallback = useCdnMermaidFallback(content, {\n enabled: Boolean(primary.error),\n theme: customTheme,\n });\n\n return primary.error ? fallback : primary;\n};\n"],"mappings":";;;;;;;;;;;;;AAwBA,MAAM,qBAAoC;CACxC,QAAQ;CACR,IAAI;CACJ,QAAQ;CACR,IAAI;CACJ,MAAM;CACN,OAAO;CACP,SAAS;CACT,aAAa;AACf;AAEA,MAAM,gBAAgB,UACpB,CAAC,CAAC,SAAS,UAAU,gBAAgB,SAAS;AAEhD,MAAa,wBAAwB,gBACnC,aAAa,WAAW,IAAI,OAAO,eAAgB;;;;;AAMrD,MAAa,iBACX,SACA,SACA,gBACwB;CACxB,IAAI,CAAC,SAAS,OAAO,EAAE,KAAK,GAAG;CAC/B,IAAI;EAEF,OAAO,EAAE,KAAK,wBADF,iBAAiB,SAAS,qBAAqB,WAAW,CAC9B,GAAG,OAAO,EAAE;CACtD,QAAQ;EACN,OAAO;GAAE,OAAO;GAAe,KAAK;EAAG;CACzC;AACF;AAEA,MAAa,yBACX,SACA,EAAE,SAAS,OAAO,kBACM;CACxB,MAAM,EAAE,eAAe,aAAa;CACpC,MAAM,UAAU,MAAM;CACtB,MAAM,CAAC,QAAQ,aAAa,SAA8B,EAAE,KAAK,GAAG,CAAC;CAErE,gBAAgB;EACd,IAAI,CAAC,WAAW,CAAC,SAAS;GACxB,UAAU,EAAE,KAAK,GAAG,CAAC;GACrB;EACF;EAEA,IAAI,SAAS;EACb,UAAU;GAAE,SAAS;GAAM,KAAK;EAAG,CAAC;EAEpC,MAAM,SAAS,uBACb,YACA,aAAa,WAAW,IAAI,cAAc,KAAA,CAC5C;EAEA,qBAAqB,SAAS,eAAe,QAAQ,WAAW,KAAK,EAAE,KAAK,MAAM,CAAC,CAChF,MAAM,QAAQ;GACb,IAAI,CAAC,QAAQ;GACb,UAAU,MAAM,EAAE,IAAI,IAAI;IAAE,OAAO;IAA4B,KAAK;GAAG,CAAC;EAC1E,CAAC,CAAC,CACD,YAAY;GACX,IAAI,QAAQ,UAAU;IAAE,OAAO;IAA4B,KAAK;GAAG,CAAC;EACtE,CAAC;EAEH,aAAa;GACX,SAAS;EACX;CACF,GAAG;EAAC;EAAS;EAAS;EAAY;EAAa;CAAO,CAAC;CAEvD,OAAO;AACT;AAEA,MAAa,cACX,SACA,EAAE,OAAO,gBAA8C,CAAC,MAChC;CACxB,MAAM,UAAU,MAAM;CACtB,MAAM,UAAU,cAAc,WAAW,QAAQ,WAAW,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC;CAEjF,MAAM,UAAU,cACR,cAAc,SAAS,SAAS,WAAW,GACjD;EAAC;EAAS;EAAS;CAAW,CAChC;CAEA,MAAM,WAAW,sBAAsB,SAAS;EAC9C,SAAS,QAAQ,QAAQ,KAAK;EAC9B,OAAO;CACT,CAAC;CAED,OAAO,QAAQ,QAAQ,WAAW;AACpC"}