UNPKG

@lobehub/ui

Version:

Lobe UI is an open-source UI component library for building AIGC web apps

1 lines 3.95 kB
{"version":3,"file":"MermaidSvg.mjs","names":[],"sources":["../../../src/Mermaid/SyntaxMermaid/MermaidSvg.tsx"],"sourcesContent":["'use client';\n\nimport { memo, type Ref, useCallback, useEffect, useRef, useState } from 'react';\n\nimport { DEFAULT_AUTO_ZOOM_THRESHOLD, DEFAULT_MAX_SCALE } from '@/Image/viewer/geometry';\nimport PreviewOutlet from '@/Image/viewer/PreviewOutlet';\nimport { openPreview } from '@/Image/viewer/registry';\n\nimport { toStandaloneSvgString } from './prepareInlineSvg';\nimport { prepareMermaidSvgString } from './prepareMermaidSvg';\n\ninterface MermaidSvgProps {\n className?: string;\n ref?: Ref<HTMLDivElement>;\n style?: React.CSSProperties;\n svg: string;\n}\n\n// The viewer flies the image out of the element it was opened from, so the\n// diagram needs a real <img> to measure — hence a hidden anchor tracking the\n// diagram box rather than a display:none preview image.\nconst anchorStyle: React.CSSProperties = {\n height: '100%',\n insetBlockStart: 0,\n insetInlineStart: 0,\n pointerEvents: 'none',\n position: 'absolute',\n visibility: 'hidden',\n width: '100%',\n};\n\nconst MermaidSvg = memo<MermaidSvgProps>(({ className, ref, style, svg }) => {\n const containerRef = useRef<HTMLDivElement>(null);\n const anchorRef = useRef<HTMLImageElement>(null);\n const [previewUrl, setPreviewUrl] = useState<string>();\n\n useEffect(() => {\n return () => {\n if (previewUrl) URL.revokeObjectURL(previewUrl);\n };\n }, [previewUrl]);\n\n // The preview copy is only built on demand: it has to bake in the resolved\n // CSS variables and be XML-well-formed, neither of which the inline copy needs.\n const handleOpen = useCallback(() => {\n const element = containerRef.current?.querySelector('svg');\n const anchor = anchorRef.current;\n if (!element || !anchor) return;\n\n const standalone = prepareMermaidSvgString(toStandaloneSvgString(element));\n const url = URL.createObjectURL(new Blob([standalone], { type: 'image/svg+xml' }));\n setPreviewUrl((previous) => {\n if (previous) URL.revokeObjectURL(previous);\n return url;\n });\n\n openPreview({\n element: anchor,\n options: {\n autoZoomThreshold: DEFAULT_AUTO_ZOOM_THRESHOLD,\n defaultZoom: 'auto',\n maxScale: DEFAULT_MAX_SCALE,\n },\n src: url,\n });\n }, []);\n\n return (\n <div className={className} ref={ref} style={{ position: 'relative', ...style }}>\n <div\n dangerouslySetInnerHTML={{ __html: svg }}\n ref={containerRef}\n style={{ cursor: 'zoom-in' }}\n onClick={handleOpen}\n />\n <img aria-hidden alt=\"\" ref={anchorRef} src={previewUrl} style={anchorStyle} />\n <PreviewOutlet elementRef={anchorRef} />\n </div>\n );\n});\n\nMermaidSvg.displayName = 'MermaidSvg';\n\nexport default MermaidSvg;\n"],"mappings":";;;;;;;;AAqBA,MAAM,cAAmC;CACvC,QAAQ;CACR,iBAAiB;CACjB,kBAAkB;CAClB,eAAe;CACf,UAAU;CACV,YAAY;CACZ,OAAO;AACT;AAEA,MAAM,aAAa,MAAuB,EAAE,WAAW,KAAK,OAAO,UAAU;CAC3E,MAAM,eAAe,OAAuB,IAAI;CAChD,MAAM,YAAY,OAAyB,IAAI;CAC/C,MAAM,CAAC,YAAY,iBAAiB,SAAiB;CAErD,gBAAgB;EACd,aAAa;GACX,IAAI,YAAY,IAAI,gBAAgB,UAAU;EAChD;CACF,GAAG,CAAC,UAAU,CAAC;CAIf,MAAM,aAAa,kBAAkB;EACnC,MAAM,UAAU,aAAa,SAAS,cAAc,KAAK;EACzD,MAAM,SAAS,UAAU;EACzB,IAAI,CAAC,WAAW,CAAC,QAAQ;EAEzB,MAAM,aAAa,wBAAwB,sBAAsB,OAAO,CAAC;EACzE,MAAM,MAAM,IAAI,gBAAgB,IAAI,KAAK,CAAC,UAAU,GAAG,EAAE,MAAM,gBAAgB,CAAC,CAAC;EACjF,eAAe,aAAa;GAC1B,IAAI,UAAU,IAAI,gBAAgB,QAAQ;GAC1C,OAAO;EACT,CAAC;EAED,YAAY;GACV,SAAS;GACT,SAAS;IACP,mBAAA;IACA,aAAa;IACb,UAAA;GACF;GACA,KAAK;EACP,CAAC;CACH,GAAG,CAAC,CAAC;CAEL,OACE,qBAAC,OAAD;EAAgB;EAAgB;EAAK,OAAO;GAAE,UAAU;GAAY,GAAG;EAAM;EAA7E,UAAA;GACE,oBAAC,OAAD;IACE,yBAAyB,EAAE,QAAQ,IAAI;IACvC,KAAK;IACL,OAAO,EAAE,QAAQ,UAAU;IAC3B,SAAS;GACV,CAAA;GACD,oBAAC,OAAD;IAAK,eAAA;IAAY,KAAI;IAAG,KAAK;IAAW,KAAK;IAAY,OAAO;GAAc,CAAA;GAC9E,oBAAC,eAAD,EAAe,YAAY,UAAY,CAAA;EACpC;;AAET,CAAC;AAED,WAAW,cAAc"}