-
Notifications
You must be signed in to change notification settings - Fork 51
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
build: simple setup vite for playground #52
Changes from 27 commits
f920e96
48245fd
5b5c3a4
900014c
e8037fc
b3505c0
7b71547
88c08f0
ece4a0d
8f149ae
390f1d0
266a594
9d3d496
7cbec3a
8155f6d
9ad7db4
799c472
ef2a7fa
84fa718
006eb29
3511403
c87ee04
694fe96
29710e2
96f6505
192f306
2475856
d3716a2
e540933
c0752ad
2e09454
378eaf9
51f080c
b9cfd1c
e6ee857
55ac328
1fab572
cf65699
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
import { MermaidDiagram } from "./MermaidDiagram.tsx"; | ||
import type { MermaidData, UpdateMermaidDefinition } from "./index.tsx"; | ||
|
||
interface CustomTestProps { | ||
onChange: UpdateMermaidDefinition; | ||
mermaidData: MermaidData; | ||
isActive: boolean; | ||
} | ||
|
||
const CustomTest = ({ onChange, mermaidData, isActive }: CustomTestProps) => { | ||
return ( | ||
<> | ||
<form | ||
onSubmit={(e) => { | ||
e.preventDefault(); | ||
|
||
const formData = new FormData(e.target as HTMLFormElement); | ||
|
||
onChange(formData.get("mermaid-input")?.toString() || "", true); | ||
}} | ||
> | ||
<textarea | ||
id="mermaid-input" | ||
rows={10} | ||
cols={50} | ||
name="mermaid-input" | ||
onChange={(e) => { | ||
if (!isActive) { | ||
return; | ||
} | ||
|
||
onChange(e.target.value, true); | ||
}} | ||
style={{ marginTop: "1rem" }} | ||
placeholder="Input Mermaid Syntax" | ||
/> | ||
<br /> | ||
<button type="submit" id="render-excalidraw-btn"> | ||
{"Render to Excalidraw"} | ||
</button> | ||
</form> | ||
|
||
{isActive && ( | ||
<> | ||
<MermaidDiagram | ||
definition={mermaidData.definition} | ||
id="custom-diagram" | ||
/> | ||
|
||
<details id="parsed-data-details"> | ||
<summary>{"Parsed data from parseMermaid"}</summary> | ||
<pre id="custom-parsed-data"> | ||
{JSON.stringify(mermaidData.output, null, 2)} | ||
</pre> | ||
</details> | ||
|
||
{typeof mermaidData.error === "string" && ( | ||
<div id="error">{mermaidData.error}</div> | ||
)} | ||
</> | ||
)} | ||
</> | ||
); | ||
}; | ||
|
||
export default CustomTest; |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
import { useEffect, useState } from "react"; | ||
import { | ||
Excalidraw, | ||
convertToExcalidrawElements, | ||
} from "@excalidraw/excalidraw"; | ||
import type { ExcalidrawImperativeAPI } from "@excalidraw/excalidraw/types/types.js"; | ||
import { graphToExcalidraw } from "../src/graphToExcalidraw"; | ||
import { DEFAULT_FONT_SIZE } from "../src/constants"; | ||
import type { MermaidData } from "./"; | ||
|
||
interface ExcalidrawWrapperProps { | ||
mermaidDefinition: MermaidData["definition"]; | ||
mermaidOutput: MermaidData["output"]; | ||
} | ||
|
||
const ExcalidrawWrapper = ({ | ||
mermaidDefinition, | ||
mermaidOutput, | ||
}: ExcalidrawWrapperProps) => { | ||
const [excalidrawAPI, setExcalidrawAPI] = | ||
useState<ExcalidrawImperativeAPI | null>(null); | ||
|
||
useEffect(() => { | ||
if (!excalidrawAPI) { | ||
return; | ||
} | ||
|
||
if (mermaidDefinition === "" || mermaidOutput === null) { | ||
excalidrawAPI.resetScene(); | ||
return; | ||
} | ||
|
||
const { elements, files } = graphToExcalidraw(mermaidOutput, { | ||
fontSize: DEFAULT_FONT_SIZE, | ||
}); | ||
|
||
excalidrawAPI.updateScene({ | ||
elements: convertToExcalidrawElements(elements), | ||
}); | ||
excalidrawAPI.scrollToContent(excalidrawAPI.getSceneElements(), { | ||
fitToContent: true, | ||
}); | ||
|
||
if (files) { | ||
excalidrawAPI.addFiles(Object.values(files)); | ||
} | ||
}, [mermaidDefinition, mermaidOutput]); | ||
|
||
return ( | ||
<div className="excalidraw-wrapper"> | ||
<Excalidraw | ||
initialData={{ | ||
appState: { | ||
viewBackgroundColor: "#fafafa", | ||
currentItemFontFamily: 1, | ||
}, | ||
}} | ||
excalidrawAPI={(api) => setExcalidrawAPI(api)} | ||
/> | ||
</div> | ||
); | ||
}; | ||
|
||
export default ExcalidrawWrapper; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import { useState, useTransition, useEffect } from "react"; | ||
import mermaid from "mermaid"; | ||
|
||
interface MermaidProps { | ||
id: string; | ||
definition: string; | ||
} | ||
|
||
export const MermaidDiagram = ({ definition, id }: MermaidProps) => { | ||
const [svg, setSvg] = useState(""); | ||
const [, startTransition] = useTransition(); | ||
|
||
useEffect(() => { | ||
const render = async (id: string, definition: string) => { | ||
const { svg } = await mermaid.render(`mermaid-diagram-${id}`, definition); | ||
startTransition(() => { | ||
setSvg(svg); | ||
}); | ||
}; | ||
|
||
render(id, definition); | ||
}, [definition, id]); | ||
|
||
return ( | ||
<div | ||
style={{ width: "50%" }} | ||
className="mermaid" | ||
dangerouslySetInnerHTML={{ __html: svg }} | ||
/> | ||
); | ||
}; |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,114 @@ | ||||||
import { useRef, useEffect, Fragment } from "react"; | ||||||
|
||||||
import { FLOWCHART_DIAGRAM_TESTCASES } from "./testcases/flowchart"; | ||||||
import { SEQUENCE_DIAGRAM_TESTCASES } from "./testcases/sequence.ts"; | ||||||
import { CLASS_DIAGRAM_TESTCASES } from "./testcases/class.ts"; | ||||||
import { UNSUPPORTED_DIAGRAM_TESTCASES } from "./testcases/unsupported.ts"; | ||||||
|
||||||
import type { UpdateMermaidDefinition } from "./index.tsx"; | ||||||
import { MermaidDiagram } from "./MermaidDiagram.tsx"; | ||||||
|
||||||
interface TestCaseProps { | ||||||
name: string; | ||||||
testcases: { name: string; definition: string }[]; | ||||||
onChange: (definition: string, activeTestcaseIndex: number) => void; | ||||||
error: string | null; | ||||||
activeTestcase?: number; | ||||||
} | ||||||
|
||||||
const Testcase = ({ | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Lets move this component to a file There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done in c0752ad |
||||||
name, | ||||||
testcases, | ||||||
onChange, | ||||||
error, | ||||||
activeTestcase, | ||||||
}: TestCaseProps) => { | ||||||
const baseId = name.toLowerCase(); | ||||||
|
||||||
useEffect(() => { | ||||||
if (activeTestcase !== undefined) { | ||||||
const { definition } = testcases[activeTestcase]; | ||||||
|
||||||
onChange(definition, activeTestcase); | ||||||
} | ||||||
}, [testcases]); | ||||||
|
||||||
return ( | ||||||
<> | ||||||
<h2> | ||||||
{name} {"Diagrams"} | ||||||
</h2> | ||||||
<details> | ||||||
<summary> | ||||||
{name} {"Examples"} | ||||||
</summary> | ||||||
<div id={`${baseId}-container`} className="testcase-container"> | ||||||
{testcases.map(({ name, definition }, index) => { | ||||||
const id = `${baseId}-${index}`; | ||||||
return ( | ||||||
<Fragment key={id}> | ||||||
<h2 style={{ marginTop: "50px", color: "#f06595" }}>{name}</h2> | ||||||
<pre>{definition}</pre> | ||||||
<button | ||||||
onClick={() => { | ||||||
onChange(definition, index); | ||||||
}} | ||||||
> | ||||||
{"Render to Excalidraw"} | ||||||
</button> | ||||||
|
||||||
<MermaidDiagram definition={definition} id={id} /> | ||||||
|
||||||
{error && activeTestcase === index && ( | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This would mean it shows error only for active testcase lets make it render error irrespective of the condition ? Currently If I edit a testcase file such with errored syntax, the text gets updated however mermaid diagram doesn't rerender. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @ad1992 I was thinking about this, and the idea of just showing for the active test case was to not have to store the individual errors for each testcase. Today we don't have the reference so the last error would be overwritten, so that error structure in the App file would become a kind of multidimensional array: [
[
0 // index testcases files,
0 // index testcase inside testscases file
]
] There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nah let's not complicate it, we might add error field later in test case file itself if needed, that would simplify this. However for now instead of not rendering anything during error, how about saying "Error in Rendering Mermaid Diagram" ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @ad1992 I realized that it shouldn't be the responsibility of the testcase or the custom testcase to understand if there was an error in the rendering of the memraid. I've moved the responsibility over to MermaidDiagram. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yeah agreed 💯, I was considering that too. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It got a lot better hahaha There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I kept it in the custom test case so we could track the parseMermaid, not just the diagram error. |
||||||
<div id="error">{error}</div> | ||||||
)} | ||||||
</Fragment> | ||||||
); | ||||||
})} | ||||||
</div> | ||||||
</details> | ||||||
</> | ||||||
); | ||||||
}; | ||||||
|
||||||
interface TestcasesProps { | ||||||
onChange: UpdateMermaidDefinition; | ||||||
isCustomTest: boolean; | ||||||
error: TestCaseProps["error"]; | ||||||
} | ||||||
|
||||||
const Testcases = ({ onChange, error, isCustomTest }: TestcasesProps) => { | ||||||
const activeTestcase = useRef<[number, number]>(); | ||||||
|
||||||
const testCases = [ | ||||||
{ name: "Flowchart", testcases: FLOWCHART_DIAGRAM_TESTCASES }, | ||||||
{ name: "Sequence", testcases: SEQUENCE_DIAGRAM_TESTCASES }, | ||||||
{ name: "Class", testcases: CLASS_DIAGRAM_TESTCASES }, | ||||||
{ name: "Unsupported", testcases: UNSUPPORTED_DIAGRAM_TESTCASES }, | ||||||
]; | ||||||
|
||||||
return ( | ||||||
<> | ||||||
{testCases.map(({ name, testcases }, index) => ( | ||||||
<Testcase | ||||||
key={index} | ||||||
name={name} | ||||||
activeTestcase={ | ||||||
activeTestcase.current?.[0] === index | ||||||
? activeTestcase.current[1] | ||||||
: undefined | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is confusing, lets have rename to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @ad1992 now I'm a bit confused haha. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @igorwessel to fix that can we have a base index instead? It starts from There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @ad1992 I will try this approach it should work. if don't maybe we can just destructure and name these variables? const [activeTestCaseFileIndex, activeTestCaseIndex] = activeTestCase.current
activeTestCaseFileIndex === fileIndex ? activeTestCaseIndex : undefined There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||||||
} | ||||||
onChange={(definition, activeTestcaseIndex) => { | ||||||
activeTestcase.current = [index, activeTestcaseIndex]; | ||||||
|
||||||
onChange(definition, false); | ||||||
}} | ||||||
testcases={testcases} | ||||||
error={!isCustomTest ? error : null} | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
better readability There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done in e540933 |
||||||
/> | ||||||
))} | ||||||
</> | ||||||
); | ||||||
}; | ||||||
|
||||||
export default Testcases; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1 @@ | ||
declare const ExcalidrawLib: typeof import("@excalidraw/excalidraw"); | ||
declare const React: typeof import("react"); | ||
declare const ReactDOM: typeof import("react-dom/client"); | ||
/// <reference types="vite/client" /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rename to
activeTestCaseIndex
as its the index and not the testcaseThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done in d3716a2