File tree Expand file tree Collapse file tree 7 files changed +85
-10
lines changed
apps/website/content/docs Expand file tree Collapse file tree 7 files changed +85
-10
lines changed Original file line number Diff line number Diff line change 1+ ---
2+ " streamdown " : patch
3+ ---
4+
5+ Add PanZoom controls configurability for Mermaid diagrams.
6+
7+ - Support ` controls.mermaid.panZoom ` (boolean) to toggle zoom controls globally
8+ - Support ` mermaid.config.panZoom ` (boolean or ` { showControls?: boolean } ` ) per-instance
9+ - Keep defaults enabled; ` false ` explicitly hides the zoom controls
10+
11+ This is a non-breaking enhancement that aligns with existing control predicates.
Original file line number Diff line number Diff line change @@ -143,7 +143,8 @@ The `controls` prop can be configured granularly:
143143 mermaid: {
144144 download: true , // Show mermaid download button
145145 copy: true , // Show mermaid copy button
146- fullscreen: true // Show mermaid fullscreen button
146+ fullscreen: true , // Show mermaid fullscreen button
147+ panZoom: true // Show mermaid pan/zoom controls
147148 }
148149 }}
149150>
Original file line number Diff line number Diff line change @@ -192,6 +192,50 @@ ${markdownWithCode}
192192 expect ( codeButtons ?. length ) . toBeGreaterThan ( 0 ) ;
193193 } ) ;
194194 } ) ;
195+
196+ it ( "should hide mermaid pan-zoom controls when panZoom is false" , async ( ) => {
197+ const markdownWithMermaid = `
198+ \`\`\`mermaid
199+ graph TD
200+ A-->B
201+ \`\`\`
202+ ` ;
203+
204+ const { container } = render (
205+ < Streamdown controls = { { mermaid : { panZoom : false } } } >
206+ { markdownWithMermaid }
207+ </ Streamdown >
208+ ) ;
209+
210+ await waitFor ( ( ) => {
211+ const zoomInButton = container . querySelector ( 'button[title="Zoom in"]' ) ;
212+ expect ( zoomInButton ) . toBeFalsy ( ) ;
213+ } ) ;
214+ } ) ;
215+
216+ it ( "should show mermaid pan-zoom controls by default" , async ( ) => {
217+ const utils = await import ( "../lib/mermaid/utils" ) ;
218+ vi . spyOn ( utils , "initializeMermaid" ) . mockResolvedValue ( {
219+ render : vi . fn ( ) . mockResolvedValue ( { svg : "<svg></svg>" } ) ,
220+ } as any ) ;
221+ const markdownWithMermaid = `
222+ \`\`\`mermaid
223+ graph TD
224+ A-->B
225+ \`\`\`
226+ ` ;
227+
228+ const { container } = render (
229+ < Streamdown controls = { { mermaid : { } } } >
230+ { markdownWithMermaid }
231+ </ Streamdown >
232+ ) ;
233+
234+ await waitFor ( ( ) => {
235+ const zoomInButton = container . querySelector ( 'button[title="Zoom in"]' ) ;
236+ expect ( zoomInButton ) . toBeTruthy ( ) ;
237+ } ) ;
238+ } ) ;
195239 } ) ;
196240
197241 describe ( "with custom components" , ( ) => {
Original file line number Diff line number Diff line change @@ -41,6 +41,7 @@ export type ControlsConfig =
4141 download ?: boolean ;
4242 copy ?: boolean ;
4343 fullscreen ?: boolean ;
44+ panZoom ?: boolean ;
4445 } ;
4546 } ;
4647
Original file line number Diff line number Diff line change @@ -102,9 +102,9 @@ const shouldShowMermaidControl = (
102102 code ?: boolean ;
103103 mermaid ?:
104104 | boolean
105- | { download ?: boolean ; copy ?: boolean ; fullscreen ?: boolean } ;
105+ | { download ?: boolean ; copy ?: boolean ; fullscreen ?: boolean ; panZoom ?: boolean } ;
106106 } ,
107- controlType : "download" | "copy" | "fullscreen"
107+ controlType : "download" | "copy" | "fullscreen" | "panZoom"
108108) : boolean => {
109109 if ( typeof config === "boolean" ) {
110110 return config ;
@@ -640,10 +640,8 @@ const CodeComponent = ({
640640 const showMermaidControls = shouldShowControls ( controlsConfig , "mermaid" ) ;
641641 const showDownload = shouldShowMermaidControl ( controlsConfig , "download" ) ;
642642 const showCopy = shouldShowMermaidControl ( controlsConfig , "copy" ) ;
643- const showFullscreen = shouldShowMermaidControl (
644- controlsConfig ,
645- "fullscreen"
646- ) ;
643+ const showFullscreen = shouldShowMermaidControl ( controlsConfig , "fullscreen" ) ;
644+ const showPanZoomControls = shouldShowMermaidControl ( controlsConfig , "panZoom" ) ;
647645
648646 return (
649647 < Suspense fallback = { < CodeBlockSkeleton /> } >
@@ -672,7 +670,11 @@ const CodeComponent = ({
672670 ) }
673671 </ div >
674672 ) }
675- < Mermaid chart = { code } config = { mermaidContext ?. config } />
673+ < Mermaid
674+ chart = { code }
675+ config = { mermaidContext ?. config }
676+ showControls = { showPanZoomControls }
677+ />
676678 </ div >
677679 </ Suspense >
678680 ) ;
Original file line number Diff line number Diff line change @@ -38,7 +38,20 @@ export const MermaidFullscreenButton = ({
3838 ...props
3939} : MermaidFullscreenButtonProps ) => {
4040 const [ isFullscreen , setIsFullscreen ] = useState ( false ) ;
41- const { isAnimating } = useContext ( StreamdownContext ) ;
41+ const { isAnimating, controls : controlsConfig } = useContext ( StreamdownContext ) ;
42+ const showPanZoomControls = ( ( ) => {
43+ if ( typeof controlsConfig === "boolean" ) {
44+ return controlsConfig ;
45+ }
46+ const mermaidCtl = controlsConfig . mermaid ;
47+ if ( mermaidCtl === false ) {
48+ return false ;
49+ }
50+ if ( mermaidCtl === true || mermaidCtl === undefined ) {
51+ return true ;
52+ }
53+ return ( mermaidCtl as any ) . panZoom !== false ;
54+ } ) ( ) ;
4255
4356 const handleToggle = ( ) => {
4457 setIsFullscreen ( ! isFullscreen ) ;
@@ -121,6 +134,7 @@ export const MermaidFullscreenButton = ({
121134 className = "h-full w-full [&>div]:h-full [&>div]:overflow-hidden [&_svg]:h-auto [&_svg]:w-auto"
122135 config = { config }
123136 fullscreen = { true }
137+ showControls = { showPanZoomControls }
124138 />
125139 </ div >
126140 </ div >
Original file line number Diff line number Diff line change @@ -10,13 +10,15 @@ type MermaidProps = {
1010 className ?: string ;
1111 config ?: MermaidConfig ;
1212 fullscreen ?: boolean ;
13+ showControls ?: boolean ;
1314} ;
1415
1516export const Mermaid = ( {
1617 chart,
1718 className,
1819 config,
1920 fullscreen = false ,
21+ showControls = true ,
2022} : MermaidProps ) => {
2123 const [ error , setError ] = useState < string | null > ( null ) ;
2224 const [ isLoading , setIsLoading ] = useState ( true ) ;
@@ -122,7 +124,7 @@ export const Mermaid = ({
122124 fullscreen = { fullscreen }
123125 maxZoom = { 3 }
124126 minZoom = { 0.5 }
125- showControls = { true }
127+ showControls = { showControls }
126128 zoomStep = { 0.1 }
127129 >
128130 < div
You can’t perform that action at this time.
0 commit comments