import { useEffect, useId, useMemo, useState, useRef, type ReactNode } from 'react' import { CollapsibleCard } from '../basic/collapsible-card' import { Button } from '../basic/button' import { FileList2Line } from '../basic/icons-inline' import { Scrollbar } from '../basic/scrollbar' import { useMermaidRender } from '../lib/use-mermaid-render' const ICON_CLASS = 'w-[var(--font-size-sm)] h-[var(--font-size-sm)] shrink-0 text-text-secondary' export interface MermaidPartProps { content?: string className?: string headerIcon?: ReactNode /** 布局风格,与 data-style 一致(如 soft/neutral/sharp),用于图表节点圆角等;不传则从 document 读取 */ dataStyle?: string } const defaultHeaderIcon = export function MermaidPart({ content = '', className, headerIcon, dataStyle }: MermaidPartProps) { const id = useId() const normalized = useMemo(() => (content ?? '').trim(), [content]) const { svg, error } = useMermaidRender(normalized, id, dataStyle) const [scale, setScale] = useState(1) const containerRef = useRef(null) useEffect(() => { if (!svg || error || !containerRef.current) return const el = containerRef.current const handleWheel = (e: WheelEvent) => { if (e.ctrlKey || e.metaKey) { e.preventDefault() const delta = e.deltaY > 0 ? -0.1 : 0.1 setScale((prev) => Math.max(0.5, Math.min(3, Math.round((prev + delta) * 10) / 10))) } } el.addEventListener('wheel', handleWheel, { passive: false }) return () => el.removeEventListener('wheel', handleWheel) }, [svg, error]) const zoomIn = () => setScale((s) => Math.min(3, Math.round((s + 0.1) * 10) / 10)) const zoomOut = () => setScale((s) => Math.max(0.5, Math.round((s - 0.1) * 10) / 10)) const reset = () => setScale(1) return ( Mermaid} headerRight={ svg && !error ? (
e.stopPropagation()}> {Math.round(scale * 100)}%
) : undefined } contentPadding="var(--spacing-1\.5) var(--spacing-2)" className={className} > {!normalized ? (
Mermaid content is empty.
) : error ? (
Mermaid render unavailable.
{error}
{normalized}
) : (
1 ? '100%' : 'auto' }} >
)} ) } MermaidPart.displayName = 'MermaidPart' export const MermaidDiagramCard = MermaidPart export type MermaidDiagramCardProps = MermaidPartProps