1- import { useEffect , useId , useRef , useState , useCallback , useMemo } from "react" ;
1+ import { useEffect , useId , useRef , useState , useCallback } from "react" ;
22import mermaid from "mermaid" ;
33import {
44 Dialog ,
@@ -108,24 +108,6 @@ export function MermaidWidget({ content }: MermaidWidgetProps) {
108108 ) ;
109109}
110110
111- function getSvgDimensions ( svgString : string ) : { width : number ; height : number } | null {
112- const parser = new DOMParser ( ) ;
113- const doc = parser . parseFromString ( svgString , "image/svg+xml" ) ;
114- const svgEl = doc . querySelector ( "svg" ) ;
115- if ( ! svgEl ) return null ;
116-
117- // Try width/height attributes first, then viewBox
118- const w = parseFloat ( svgEl . getAttribute ( "width" ) || "0" ) ;
119- const h = parseFloat ( svgEl . getAttribute ( "height" ) || "0" ) ;
120- if ( w > 0 && h > 0 ) return { width : w , height : h } ;
121-
122- const vb = svgEl . getAttribute ( "viewBox" ) ;
123- if ( vb ) {
124- const parts = vb . split ( / \s + / ) . map ( Number ) ;
125- if ( parts . length === 4 && parts [ 2 ] > 0 && parts [ 3 ] > 0 ) {
126- return { width : parts [ 2 ] , height : parts [ 3 ] } ;
127- }
128- }
129111 return null ;
130112}
131113
@@ -134,28 +116,9 @@ function MermaidPanZoom({ svg }: { svg: string }) {
134116
135117
136118 // Calculate initial zoom to fit SVG in the actual container once it renders
137- const [ scale , setScale ] = useState ( 1 ) ;
138- const initialScaleRef = useRef ( 1 ) ;
119+ const [ scale , setScale ] = useState ( 2.5 ) ;
139120
140- // Strip inline width/height from SVG so it can scale freely
141- const scalableSvg = useMemo ( ( ) => {
142- return svg . replace ( / < s v g ( [ ^ > ] * ) w i d t h = " [ ^ " ] * " / , '<svg$1' ) . replace ( / < s v g ( [ ^ > ] * ) h e i g h t = " [ ^ " ] * " / , '<svg$1' ) . replace ( / < s v g / , '<svg width="100%" height="100%"' ) ;
143- } , [ svg ] ) ;
144121
145- useEffect ( ( ) => {
146- const container = containerRef . current ;
147- if ( ! container ) return ;
148- // Find the actual SVG element and measure it
149- const svgEl = container . querySelector ( 'svg' ) ;
150- if ( ! svgEl ) return ;
151- const bbox = svgEl . getBBox ( ) ;
152- const rect = container . getBoundingClientRect ( ) ;
153- if ( bbox . width === 0 || bbox . height === 0 || rect . width === 0 || rect . height === 0 ) return ;
154- const fitScale = Math . min ( rect . width / ( bbox . width + 20 ) , rect . height / ( bbox . height + 20 ) ) ;
155- const clamped = Math . min ( Math . max ( fitScale , 0.3 ) , 5 ) ;
156- initialScaleRef . current = clamped ;
157- setScale ( clamped ) ;
158- } , [ svg ] ) ;
159122 const [ translate , setTranslate ] = useState ( { x : 0 , y : 0 } ) ;
160123 const dragRef = useRef < { startX : number ; startY : number ; startTx : number ; startTy : number } | null > ( null ) ;
161124
@@ -191,7 +154,7 @@ function MermaidPanZoom({ svg }: { svg: string }) {
191154 } , [ ] ) ;
192155
193156 const resetView = useCallback ( ( ) => {
194- setScale ( initialScaleRef . current ) ;
157+ setScale ( 2.5 ) ;
195158 setTranslate ( { x : 0 , y : 0 } ) ;
196159 } , [ ] ) ;
197160
@@ -239,8 +202,8 @@ function MermaidPanZoom({ svg }: { svg: string }) {
239202 } }
240203 >
241204 < div
242- className = "[&_svg]:max-w-none"
243- dangerouslySetInnerHTML = { { __html : scalableSvg } }
205+ className = "[&_svg]:max-w-none [&_svg]:h-auto "
206+ dangerouslySetInnerHTML = { { __html : svg } }
244207 />
245208 </ div >
246209 </ div >
0 commit comments