Skip to content

Commit 45d66d5

Browse files
author
Bender Rodriguez
committed
simplify: mermaid modal opens at fixed 250% zoom
Removed auto-fit logic (unreliable across SVG sizes). Fixed 250% zoom is readable and consistent. Cleaned up unused getSvgDimensions, useMemo.
1 parent d565cab commit 45d66d5

1 file changed

Lines changed: 5 additions & 42 deletions

File tree

web_src/src/components/AgentSidebar/widgets/MermaidWidget.tsx

Lines changed: 5 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useEffect, useId, useRef, useState, useCallback, useMemo } from "react";
1+
import { useEffect, useId, useRef, useState, useCallback } from "react";
22
import mermaid from "mermaid";
33
import {
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(/<svg([^>]*)width="[^"]*"/, '<svg$1').replace(/<svg([^>]*)height="[^"]*"/, '<svg$1').replace(/<svg/, '<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

Comments
 (0)