@lobehub/ui
Version:
Lobe UI is an open-source UI component library for building AIGC web apps
1 lines • 5.4 kB
Source Map (JSON)
{"version":3,"file":"StreamMermaid.mjs","names":["Image"],"sources":["../../../src/Mermaid/SyntaxMermaid/StreamMermaid.tsx"],"sourcesContent":["'use client';\n\nimport { kebabCase } from 'es-toolkit/compat';\nimport { memo, useEffect, useId, useMemo, useState } from 'react';\nimport type { Ref } from 'react';\n\nimport Image from '@/Image';\nimport { useStreamMermaid } from '@/hooks/useStreamMermaid';\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 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={{\n background: variant === 'filled' ? background : undefined,\n borderRadius: 0,\n margin: 0,\n minWidth: 300,\n padding: variant === 'borderless' ? 0 : 16,\n position: 'relative',\n width: '100%',\n ...style,\n }}\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;AAC/B,MAAI,eAAgB;AACpB,SAAO,cAAc,MAAM,SAAS,KAAK,OAAO,YAAY,EAAE;IAC7D,CAAC,gBAAgB,YAAY,CAAC;CAIjC,MAAM,OAAO,iBAAiB,cAAc;EAC1C,SAAS;EACT,IAHgB,UAAU,WADjB,OAAO,GAC0B;EAI1C,OAAO,iBAAiB,SAAY;EACrC,CAAC;CACF,MAAM,YAAY,CAAC;CACnB,MAAM,CAAC,SAAS,cAAc,UAAkB;AAGhD,iBAAgB;AACd,eAAa;AACX,OAAI,QAAS,KAAI,gBAAgB,QAAQ;;IAE1C,CAAC,QAAQ,CAAC;AAEb,iBAAgB;AACd,MAAI,aAAa,CAAC,MAAM;AAEtB,cAAW,OAAU;AACrB;;EAGF,IAAI,iBAAiB;AAGrB,MACE,OAAO,WAAW,eAClB,OAAO,cAAc,eACrB,UAAU,UAAU,SAAS,UAAU,EACvC;GAEA,MAAM,SADS,IAAI,WAAW,CACR,gBAAgB,MAAM,gBAAgB;GAC5D,MAAM,aAAa,OAAO;AAC1B,OAAI,cAAc,WAAW,aAAa,UAAU,EAAE;IAEpD,MAAM,eADU,WAAW,aAAa,UAAU,CACrB,MAAM,IAAI;AACvC,QAAI,MAAM,QAAQ,aAAa,IAAI,aAAa,WAAW,GAAG;AAC5D,gBAAW,aAAa,SAAS,aAAa,GAAG;AACjD,gBAAW,aAAa,UAAU,aAAa,GAAG;;AAEpD,qBAAiB,IAAI,eAAe,CAAC,kBAAkB,OAAO;;;EAKlE,MAAM,UAAU,IAAI,KAAK,CAAC,eAAe,EAAE,EAAE,MAAM,iBAAiB,CAAC;AAGrE,aADY,IAAI,gBAAgB,QAAQ,CACzB;IACd,CAAC,WAAW,KAAK,CAAC;AAErB,KAAI,CAAC,QACH,QACE,oBAAC;EAAI,WAAW;EAA0B;YACxC,oBAAC;GAAI,OAAO,EAAE,SAAS,IAAI;aAAE;IAAkB;GAC3C;AAIV,QACE,oBAACA;EACC,KAAK;EACM;EACX,WAAW;EACX,UAAU;EACV,WAAW;EACN;EACL,KAAK;EACL,OAAO;GACL,YAAY,YAAY,WAAW,aAAa;GAChD,cAAc;GACd,QAAQ;GACR,UAAU;GACV,SAAS,YAAY,eAAe,IAAI;GACxC,UAAU;GACV,OAAO;GACP,GAAG;GACJ;EACD,SAAS;EACT,OAAO;GACP;EAGP;AAED,cAAc,cAAc;AAE5B,4BAAe"}