1+ import { useState , useEffect } from "react" ;
12import { MermaidDiagram } from "./MermaidDiagram.tsx" ;
23import type { ActiveTestCaseIndex , MermaidData } from "./index.tsx" ;
4+ import { usePersistedSectionState } from "./usePersistedSectionState.ts" ;
35
46interface CustomTestProps {
57 onChange : (
@@ -10,57 +12,112 @@ interface CustomTestProps {
1012 activeTestCaseIndex : ActiveTestCaseIndex ;
1113}
1214
15+ const STORAGE_KEY = "mermaid-to-excalidraw-definition" ;
16+
1317const CustomTest = ( {
1418 onChange,
1519 mermaidData,
1620 activeTestCaseIndex,
1721} : CustomTestProps ) => {
1822 const isActive = activeTestCaseIndex === "custom" ;
23+ const {
24+ isExpanded : isParsedDataExpanded ,
25+ handleToggle : handleParsedDataToggle ,
26+ } = usePersistedSectionState ( "custom:parsed-data" ) ;
27+ const [ textareaValue , setTextareaValue ] = useState ( ( ) => {
28+ // Load from localStorage on initial mount
29+ try {
30+ return localStorage . getItem ( STORAGE_KEY ) || "" ;
31+ } catch {
32+ return "" ;
33+ }
34+ } ) ;
35+
36+ // Update textarea when mermaidData changes from external source
37+ useEffect ( ( ) => {
38+ if ( mermaidData . definition && activeTestCaseIndex !== "custom" ) {
39+ setTextareaValue ( mermaidData . definition ) ;
40+ }
41+ } , [ mermaidData . definition , activeTestCaseIndex ] ) ;
42+
1943 return (
2044 < >
2145 < form
46+ className = "custom-test-form"
2247 onSubmit = { ( e ) => {
2348 e . preventDefault ( ) ;
2449
2550 const formData = new FormData ( e . target as HTMLFormElement ) ;
51+ const definition = formData . get ( "mermaid-input" ) ?. toString ( ) || "" ;
2652
27- onChange ( formData . get ( "mermaid-input" ) ?. toString ( ) || "" , "custom" ) ;
53+ // Save to localStorage
54+ try {
55+ localStorage . setItem ( STORAGE_KEY , definition ) ;
56+ } catch ( error ) {
57+ console . error ( "Failed to save to localStorage:" , error ) ;
58+ }
59+
60+ onChange ( definition , "custom" ) ;
2861 } }
2962 >
63+ < label className = "field-label" htmlFor = "mermaid-input" >
64+ { "Mermaid definition" }
65+ </ label >
3066 < textarea
3167 id = "mermaid-input"
3268 rows = { 10 }
3369 cols = { 50 }
3470 name = "mermaid-input"
71+ value = { textareaValue }
3572 onChange = { ( e ) => {
73+ const value = e . target . value ;
74+ setTextareaValue ( value ) ;
75+
3676 if ( ! isActive ) {
3777 return ;
3878 }
3979
40- onChange ( e . target . value , "custom" ) ;
80+ onChange ( value , "custom" ) ;
4181 } }
42- style = { { marginTop : "1rem" } }
43- placeholder = "Input Mermaid Syntax"
82+ placeholder = "Paste or type Mermaid syntax here"
4483 />
45- < br />
46- < button type = "submit" id = "render-excalidraw-btn" >
47- { "Render to Excalidraw" }
48- </ button >
84+ < div className = "custom-test-actions" >
85+ < button
86+ className = "playground-button"
87+ type = "submit"
88+ id = "render-excalidraw-btn"
89+ >
90+ { "Render to Excalidraw" }
91+ </ button >
92+ < p className = "custom-test-hint" >
93+ { "The live Excalidraw canvas updates on the right." }
94+ </ p >
95+ </ div >
4996 </ form >
5097
5198 { isActive && (
5299 < >
53- < MermaidDiagram
54- definition = { mermaidData . definition }
55- id = "custom-diagram"
56- />
100+ < section className = "custom-preview-card" >
101+ < div className = "preview-badge" > { "Live Mermaid SVG" } </ div >
102+ < div className = "diagram-preview-surface custom-diagram-surface" >
103+ < MermaidDiagram definition = { textareaValue } id = "custom-diagram" />
104+ </ div >
105+ </ section >
57106
58- < details id = "parsed-data-details" >
107+ < details
108+ id = "parsed-data-details"
109+ open = { isParsedDataExpanded }
110+ onToggle = { handleParsedDataToggle }
111+ >
59112 < summary > { "Parsed data from parseMermaid" } </ summary >
60- < pre id = "custom-parsed-data" >
61- { JSON . stringify ( mermaidData . output , null , 2 ) }
62- </ pre >
63- { mermaidData . error && < div id = "error" > { mermaidData . error } </ div > }
113+ { isParsedDataExpanded ? (
114+ < >
115+ < pre id = "custom-parsed-data" >
116+ { JSON . stringify ( mermaidData . output , null , 2 ) }
117+ </ pre >
118+ { mermaidData . error && < div id = "error" > { mermaidData . error } </ div > }
119+ </ >
120+ ) : null }
64121 </ details >
65122 </ >
66123 ) }
0 commit comments