Skip to content

Commit 83a1c54

Browse files
committed
refactor: reorganize imports and improve Playground component structure
1 parent 7d27e0c commit 83a1c54

File tree

1 file changed

+91
-109
lines changed

1 file changed

+91
-109
lines changed

src/pages/playgroud/Playground.tsx

Lines changed: 91 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,17 @@
1-
import 'split-pane-react/esm/themes/default.css'
1+
import 'split-pane-react/esm/themes/default.css';
22

3-
import { useEffect, useState, useRef } from 'react'
4-
import { useRecoilState } from 'recoil'
5-
import { Pane } from 'split-pane-react'
6-
import { Decimal } from 'internet-object'
3+
import { Decimal } from 'internet-object';
4+
import { useCallback, useEffect, useRef, useState } from 'react';
5+
import Toggle from 'react-toggle';
6+
import { useRecoilState } from 'recoil';
7+
import { Pane } from 'split-pane-react';
8+
import SplitPane from 'split-pane-react/esm/SplitPane';
79

8-
import Toggle from 'react-toggle'
9-
import SplitPane from 'split-pane-react/esm/SplitPane'
10-
11-
import parseIO from './compiler'
12-
import Bar from '../../components/bar/Bar'
13-
import Editor from '../../components/editor/Editor'
14-
import Output from '../../components/output/Output'
15-
import editorPosition from '../../states/editor-pos'
10+
import Bar from '../../components/bar/Bar';
11+
import Editor from '../../components/editor/Editor';
12+
import Output from '../../components/output/Output';
13+
import editorPosition from '../../states/editor-pos';
14+
import { useParseIO, Marker } from '../../hooks/useParseIO';
1615

1716
interface PlaygroundProps {
1817
showSchema: boolean;
@@ -22,143 +21,122 @@ interface PlaygroundProps {
2221
schemaPanelHeight?: number;
2322
}
2423

24+
const DEFAULT_SCHEMA_PANEL_HEIGHT = 200;
25+
const MIN_PANEL_SIZE = 100;
26+
const DEFAULT_VERTICAL_SIZE = '60%';
27+
2528
const Playground = ({
2629
showSchema, setShowSchema,
2730
document,
2831
schema,
2932
schemaPanelHeight,
3033
}: PlaygroundProps) => {
31-
const [_, setEditorPos] = useRecoilState(editorPosition)
3234

33-
const [sizesH, setHSizes] = useState<[number | string, string]>([0, "auto"])
34-
const sizesHRef = useRef(sizesH)
35-
// Keep the ref in sync with state
35+
const [, setEditorPos] = useRecoilState(editorPosition);
36+
37+
// State for horizontal and vertical split sizes
38+
const [sizesH, setHSizes] = useState<[number | string, string]>([0, 'auto']);
39+
const sizesHRef = useRef(sizesH);
3640
useEffect(() => {
37-
sizesHRef.current = sizesH
38-
}, [sizesH])
39-
40-
const [sizesV, setVSizes] = useState([0, "auto"])
41-
const [schemaText, setSchemaText] = useState(schema)
42-
const [documentText, setDocumentText] = useState(document)
43-
const [jsonText, setJsonText] = useState("")
44-
const [markers, setMarkers] = useState<any[]>([])
45-
const [defMarkers, setDefMarkers] = useState<any[]>([])
46-
const [error, setError] = useState<boolean>(false)
47-
const [minifiedOutput, setMinifiedOutput] = useState(
48-
localStorage.getItem("minifiedOutput") === "true" ? true : false)
41+
sizesHRef.current = sizesH;
42+
}, [sizesH]);
4943

44+
const [sizesV, setVSizes] = useState<[number | string, string]>([0, 'auto']);
45+
const [schemaText, setSchemaText] = useState<string>(schema);
46+
const [documentText, setDocumentText] = useState<string>(document);
47+
const [jsonText, setJsonText] = useState<string>('');
48+
const [minifiedOutput, setMinifiedOutput] = useState<boolean>(localStorage.getItem('minifiedOutput') === 'true');
49+
// Use custom hook for parsing logic and marker state
50+
const { markers, defMarkers, jsonText: parsedJsonText, error, parse } = useParseIO(documentText, schemaText, showSchema, minifiedOutput);
51+
52+
53+
// Set initial horizontal split size when schemaPanelHeight changes
5054
useEffect(() => {
51-
setHSizes([schemaPanelHeight || 200, "auto"])
52-
}, [schemaPanelHeight])
55+
setHSizes([schemaPanelHeight || DEFAULT_SCHEMA_PANEL_HEIGHT, 'auto']);
56+
}, [schemaPanelHeight]);
5357

58+
// Debounced parse effect
5459
useEffect(() => {
55-
setTimeout(parse, 500)
56-
}, [schemaText, documentText, showSchema, minifiedOutput])
60+
const timer = setTimeout(() => {
61+
parse();
62+
}, 500);
63+
return () => clearTimeout(timer);
64+
}, [schemaText, documentText, showSchema, minifiedOutput, parse]);
5765

66+
// Keep jsonText in sync with parsedJsonText
5867
useEffect(() => {
59-
setSchemaText(schema)
60-
setDocumentText(document)
61-
}, [schema, document])
68+
setJsonText(parsedJsonText);
69+
}, [parsedJsonText]);
6270

71+
// Sync schema and document text with props
72+
useEffect(() => {
73+
setSchemaText(schema);
74+
setDocumentText(document);
75+
}, [schema, document]);
76+
77+
// Set initial vertical split size
6378
useEffect(() => {
6479
if (sizesV[0] === 0) {
65-
setVSizes(["60%", "auto"])
80+
setVSizes([DEFAULT_VERTICAL_SIZE, 'auto']);
6681
}
67-
}, [sizesV])
82+
}, [sizesV]);
6883

84+
// Update horizontal split when showSchema changes
6985
useEffect(() => {
7086
if (!showSchema) {
71-
setHSizes([0, "auto"])
72-
} else {
73-
setHSizes([schemaPanelHeight || 200, "auto"])
74-
}
75-
}, [showSchema])
76-
77-
const parse = () => {
78-
const result = parseIO(documentText, showSchema ? schemaText : null)
79-
if (result.defsMarkers) {
80-
setDefMarkers(result.defsMarkers)
81-
} else {
82-
setDefMarkers([])
83-
}
84-
85-
if (result.docMarkers) {
86-
setMarkers(result.docMarkers)
87+
setHSizes([0, 'auto']);
8788
} else {
88-
setMarkers([])
89+
setHSizes([schemaPanelHeight || DEFAULT_SCHEMA_PANEL_HEIGHT, 'auto']);
8990
}
90-
91-
if (result.output) {
92-
const output = JSON.stringify(result.output, function (k, v:any) {
93-
// Convert BigInt to string
94-
if (typeof v === "bigint") return `io:big:${v.toString()}`
95-
if (typeof v === "number") {
96-
if (isNaN(v)) return "io:number:NaN"
97-
}
98-
99-
if (v instanceof Decimal) {
100-
return `io:decimal:${v.toString()}`
101-
}
102-
103-
if (v === Infinity) return "io:number:Inf"
104-
if (v === -Infinity) return "io:number:-Inf"
105-
if (typeof v === "undefined") return "io:undefined"
106-
107-
return v
108-
}, minifiedOutput ? 0 : 2)
109-
setJsonText(output)
110-
setError(false)
111-
} else {
112-
setJsonText(result.errorMessage || "")
113-
setError(true)
114-
}
115-
}
91+
}, [showSchema, schemaPanelHeight]);
11692

11793
const layoutCSS = { height: "100%" }
11894

119-
const handleHBarDragEnd = (): void => {
120-
const currentSizesH = sizesHRef.current
121-
if (typeof currentSizesH[0] === "number") {
122-
if (currentSizesH[0] <= 100) {
95+
96+
// Handlers with useCallback for stable references
97+
const handleHBarDragEnd = useCallback((): void => {
98+
const currentSizesH = sizesHRef.current;
99+
if (typeof currentSizesH[0] === 'number') {
100+
if (currentSizesH[0] <= MIN_PANEL_SIZE) {
123101
if (showSchema) {
124-
setHSizes([0, "auto"])
125-
setShowSchema(false)
102+
setHSizes([0, 'auto']);
103+
setShowSchema(false);
126104
} else {
127-
setHSizes([200, "auto"])
128-
setShowSchema(true)
105+
setHSizes([DEFAULT_SCHEMA_PANEL_HEIGHT, 'auto']);
106+
setShowSchema(true);
129107
}
130108
} else {
131-
setShowSchema(currentSizesH[0] > 0)
109+
setShowSchema(currentSizesH[0] > 0);
132110
}
133111
}
134-
}
112+
}, [showSchema, setShowSchema]);
135113

136-
const handleHBar = (s: any): void => {
137-
setHSizes(s)
114+
const handleHBar = useCallback((s: [number | string, string]): void => {
115+
setHSizes(s);
138116
// sizesHRef will be updated by the useEffect above
139-
}
117+
}, []);
140118

141-
const handleSchemaChange = (value: string): void => {
142-
setSchemaText(value)
143-
}
119+
const handleSchemaChange = useCallback((value: string): void => {
120+
setSchemaText(value);
121+
}, []);
144122

145-
const handleIOChange = (value: string): void => {
146-
setDocumentText(value)
147-
}
123+
const handleIOChange = useCallback((value: string): void => {
124+
setDocumentText(value);
125+
}, []);
148126

149-
const handleCaretPositionChange = (name: string, position: any): void => {
127+
const handleCaretPositionChange = useCallback((name: string, position: any): void => {
150128
setEditorPos({
151129
editorName: name,
152130
row: position.row,
153131
column: position.column,
154-
position: position.position
155-
})
156-
}
132+
position: position.position,
133+
});
134+
}, [setEditorPos]);
157135

158-
const handleOnCompressChange = (event: any): void => {
159-
localStorage.setItem("minifiedOutput", event.target.checked)
160-
setMinifiedOutput(event.target.checked)
161-
}
136+
const handleOnCompressChange = useCallback((event: React.ChangeEvent<HTMLInputElement>): void => {
137+
localStorage.setItem('minifiedOutput', event.target.checked.toString());
138+
setMinifiedOutput(event.target.checked);
139+
}, []);
162140

163141
return (
164142
<div className="editor-area">
@@ -210,7 +188,11 @@ const Playground = ({
210188
<Bar label="JSON Output" bytes={jsonText.length}>
211189
<label className="toggleSwtich" title="Compress">
212190
<span>Minify</span>
213-
<Toggle onChange={handleOnCompressChange} checked={minifiedOutput} />
191+
<Toggle
192+
onChange={handleOnCompressChange}
193+
checked={minifiedOutput}
194+
aria-label="Toggle minified JSON output"
195+
/>
214196
</label>
215197
</Bar>
216198
<Output value={jsonText} options={{

0 commit comments

Comments
 (0)