@lobehub/ui
Version:
Lobe UI is an open-source UI component library for building AIGC web apps
1 lines • 5.5 kB
Source Map (JSON)
{"version":3,"file":"StreamMermaid.mjs","names":[],"sources":["../../../src/Mermaid/SyntaxMermaid/StreamMermaid.tsx"],"sourcesContent":["'use client';\n\nimport { kebabCase } from 'es-toolkit/compat';\nimport { type Ref } from 'react';\nimport { memo, useEffect, useId, useMemo, useState } from 'react';\n\nimport { useStreamMermaid } from '@/hooks/useStreamMermaid';\nimport Image from '@/Image';\n\nimport { mermaidThemes } from '../const';\nimport { type SyntaxMermaidProps } from '../type';\n\ninterface StreamMermaidProps {\n children: string;\n className?: string;\n fallbackClassName?: string;\n ref?: Ref<HTMLDivElement>;\n style?: SyntaxMermaidProps['style'];\n theme?: SyntaxMermaidProps['theme'];\n variant?: SyntaxMermaidProps['variant'];\n}\n\nconst StreamMermaid = memo<StreamMermaidProps>(\n ({ children, className, fallbackClassName, ref, style, theme: customTheme, variant }) => {\n const safeChildren = children ?? '';\n const isDefaultTheme = customTheme === 'lobe-theme' || !customTheme;\n\n const background = useMemo(() => {\n if (isDefaultTheme) return;\n return mermaidThemes.find((item) => item.id === customTheme)?.background;\n }, [isDefaultTheme, customTheme]);\n\n const id = useId();\n const mermaidId = kebabCase(`mermaid-${id}`);\n const data = useStreamMermaid(safeChildren, {\n enabled: true,\n id: mermaidId,\n theme: isDefaultTheme ? undefined : customTheme,\n });\n const isLoading = !data;\n const [blobUrl, setBlobUrl] = useState<string>();\n\n // 组件卸载时清理 Blob URL,避免内存泄漏\n useEffect(() => {\n return () => {\n if (blobUrl) URL.revokeObjectURL(blobUrl);\n };\n }, [blobUrl]);\n\n useEffect(() => {\n if (isLoading || !data) {\n // Clear blob URL when loading or no data\n setBlobUrl(undefined);\n return;\n }\n\n let finalSvgString = data;\n\n // 修复Firefox点击预览mermaid图时宽高为0导致不显示的异常\n if (\n typeof window !== 'undefined' &&\n typeof navigator !== 'undefined' &&\n navigator.userAgent.includes('Firefox')\n ) {\n const parser = new DOMParser();\n const svgDoc = parser.parseFromString(data, 'image/svg+xml');\n const svgElement = svgDoc.documentElement;\n if (svgElement && svgElement.hasAttribute('viewBox')) {\n const viewBox = svgElement.getAttribute('viewBox')!;\n const viewBoxParts = viewBox.split(' ');\n if (Array.isArray(viewBoxParts) && viewBoxParts.length === 4) {\n svgElement.setAttribute('width', viewBoxParts[2]);\n svgElement.setAttribute('height', viewBoxParts[3]);\n }\n finalSvgString = new XMLSerializer().serializeToString(svgDoc);\n }\n }\n\n // 创建Blob对象\n const svgBlob = new Blob([finalSvgString], { type: 'image/svg+xml' });\n // 创建并保存Blob URL\n const url = URL.createObjectURL(svgBlob);\n setBlobUrl(url);\n }, [isLoading, data]);\n\n const containerStyle = {\n background: variant === 'filled' ? background : undefined,\n margin: 0,\n minWidth: 300,\n padding: variant === 'borderless' ? 0 : 16,\n position: 'relative' as const,\n width: '100%',\n ...style,\n };\n\n if (!blobUrl) {\n return (\n <div className={fallbackClassName} style={style}>\n <div style={{ padding: 16 }}>Rendering...</div>\n </div>\n );\n }\n\n return (\n <Image\n alt={'mermaid'}\n className={className}\n maxHeight={480}\n minWidth={300}\n objectFit={'contain'}\n ref={ref}\n src={blobUrl}\n style={containerStyle}\n variant={'borderless'}\n width={'100%'}\n />\n );\n },\n);\n\nStreamMermaid.displayName = 'StreamMermaid';\n\nexport default StreamMermaid;\n"],"mappings":";;;;;;;;AAsBA,MAAM,gBAAgB,MACnB,EAAE,UAAU,WAAW,mBAAmB,KAAK,OAAO,OAAO,aAAa,cAAc;CACvF,MAAM,eAAe,YAAY;CACjC,MAAM,iBAAiB,gBAAgB,gBAAgB,CAAC;CAExD,MAAM,aAAa,cAAc;EAC/B,IAAI,gBAAgB;EACpB,OAAO,cAAc,MAAM,SAAS,KAAK,OAAO,WAAW,CAAC,EAAE;CAChE,GAAG,CAAC,gBAAgB,WAAW,CAAC;CAIhC,MAAM,OAAO,iBAAiB,cAAc;EAC1C,SAAS;EACT,IAHgB,UAAU,WADjB,MAC6B,GAG1B;EACZ,OAAO,iBAAiB,KAAA,IAAY;CACtC,CAAC;CACD,MAAM,YAAY,CAAC;CACnB,MAAM,CAAC,SAAS,cAAc,SAAiB;CAG/C,gBAAgB;EACd,aAAa;GACX,IAAI,SAAS,IAAI,gBAAgB,OAAO;EAC1C;CACF,GAAG,CAAC,OAAO,CAAC;CAEZ,gBAAgB;EACd,IAAI,aAAa,CAAC,MAAM;GAEtB,WAAW,KAAA,CAAS;GACpB;EACF;EAEA,IAAI,iBAAiB;EAGrB,IACE,OAAO,WAAW,eAClB,OAAO,cAAc,eACrB,UAAU,UAAU,SAAS,SAAS,GACtC;GAEA,MAAM,SAAS,IADI,UACC,CAAC,CAAC,gBAAgB,MAAM,eAAe;GAC3D,MAAM,aAAa,OAAO;GAC1B,IAAI,cAAc,WAAW,aAAa,SAAS,GAAG;IAEpD,MAAM,eADU,WAAW,aAAa,SACb,CAAC,CAAC,MAAM,GAAG;IACtC,IAAI,MAAM,QAAQ,YAAY,KAAK,aAAa,WAAW,GAAG;KAC5D,WAAW,aAAa,SAAS,aAAa,EAAE;KAChD,WAAW,aAAa,UAAU,aAAa,EAAE;IACnD;IACA,iBAAiB,IAAI,cAAc,CAAC,CAAC,kBAAkB,MAAM;GAC/D;EACF;EAGA,MAAM,UAAU,IAAI,KAAK,CAAC,cAAc,GAAG,EAAE,MAAM,gBAAgB,CAAC;EAEpE,MAAM,MAAM,IAAI,gBAAgB,OAAO;EACvC,WAAW,GAAG;CAChB,GAAG,CAAC,WAAW,IAAI,CAAC;CAEpB,MAAM,iBAAiB;EACrB,YAAY,YAAY,WAAW,aAAa,KAAA;EAChD,QAAQ;EACR,UAAU;EACV,SAAS,YAAY,eAAe,IAAI;EACxC,UAAU;EACV,OAAO;EACP,GAAG;CACL;CAEA,IAAI,CAAC,SACH,OACE,oBAAC,OAAD;EAAK,WAAW;EAA0B;YACxC,oBAAC,OAAD;GAAK,OAAO,EAAE,SAAS,GAAG;aAAG;EAAiB,CAAA;CAC3C,CAAA;CAIT,OACE,oBAAC,OAAD;EACE,KAAK;EACM;EACX,WAAW;EACX,UAAU;EACV,WAAW;EACN;EACL,KAAK;EACL,OAAO;EACP,SAAS;EACT,OAAO;CACR,CAAA;AAEL,CACF;AAEA,cAAc,cAAc"}