feat(files): zoom controls for inline mermaid and images in markdown (#4411)

- Add pan/zoom/fit controls to mermaid diagrams rendered inline in markdown — same experience as the standalone .mmd viewer
- Wrap inline markdown images in ZoomablePreview with fit-to-container scale
- Allow fit zoom to upscale small diagrams to fill the view (previously capped at 100%)
This commit is contained in:
Waleed
2026-05-06 20:24:40 -07:00
committed by GitHub
parent a251e45400
commit 28f1912e89
2 changed files with 18 additions and 8 deletions
@@ -495,7 +495,14 @@ const STATIC_MARKDOWN_COMPONENTS = {
),
'mermaid-diagram': ({ definition }: { definition?: string }) => {
const isStreaming = useContext(MermaidStreamingCtx)
return <MermaidDiagram definition={definition ?? ''} isStreaming={isStreaming} />
return (
<MermaidDiagram
definition={definition ?? ''}
isStreaming={isStreaming}
zoomable
zoomClassName='my-4 h-[420px] rounded-lg'
/>
)
},
p: ({ children }: { children?: React.ReactNode }) => (
<p className='mb-3 break-words text-[14px] text-[var(--text-primary)] leading-[1.6] last:mb-0'>
@@ -619,12 +626,15 @@ const STATIC_MARKDOWN_COMPONENTS = {
img: ({ src, alt }: React.ImgHTMLAttributes<HTMLImageElement>) => {
const resolvedSrc = resolveSimFileUrl(typeof src === 'string' ? src : undefined)
return (
<img
src={resolvedSrc}
alt={alt ?? ''}
className='my-3 max-w-full rounded-md'
loading='lazy'
/>
<ZoomablePreview className='my-3 h-[360px] rounded-md' initialScale='actual'>
<img
src={resolvedSrc}
alt={alt ?? ''}
className='max-h-full max-w-full select-none object-contain'
draggable={false}
loading='lazy'
/>
</ZoomablePreview>
)
},
table: ({ children }: { children?: React.ReactNode }) => (
@@ -47,7 +47,7 @@ function getFitZoom(container: Size, content: Size): number {
const availableWidth = Math.max(1, container.width - FIT_PADDING)
const availableHeight = Math.max(1, container.height - FIT_PADDING)
return clampZoom(Math.min(1, availableWidth / content.width, availableHeight / content.height))
return clampZoom(Math.min(availableWidth / content.width, availableHeight / content.height))
}
function clampOffset(container: Size, content: Size, offset: Offset, zoom: number): Offset {