Skip to content

Commit 43f3150

Browse files
authored
feat(dev): add playground to render syntax (#235)
* feat(dev): add playground to render syntax * refactor: optimize code
1 parent 6b0c9b1 commit 43f3150

2 files changed

Lines changed: 98 additions & 0 deletions

File tree

dev/src/App.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { Flex, Radio } from 'antd';
22
import { useState } from 'react';
33
import { Composite } from './Composite';
44
import { ItemPreview } from './ItemPreview';
5+
import { Playground } from './Playground';
56
import { Preview } from './Preview';
67
import { StreamPreview } from './StreamPreview';
78

@@ -32,6 +33,7 @@ export const App = () => {
3233
{ label: '模版预览', value: 'preview' },
3334
{ label: '数据项预览', value: 'item' },
3435
{ label: '流式渲染', value: 'stream' },
36+
{ label: '语法渲染', value: 'playground' },
3537
]}
3638
value={tab}
3739
onChange={(e) => handleTabChange(e.target.value)}
@@ -46,6 +48,8 @@ export const App = () => {
4648
<Preview />
4749
) : tab === 'stream' ? (
4850
<StreamPreview />
51+
) : tab === 'playground' ? (
52+
<Playground />
4953
) : (
5054
<ItemPreview />
5155
)}

dev/src/Playground.tsx

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
import Editor from '@monaco-editor/react';
2+
import { Card } from 'antd';
3+
import { useEffect, useState } from 'react';
4+
import { Infographic } from './Infographic';
5+
import { getStoredValues, setStoredValues } from './utils/storage';
6+
7+
const STORAGE_KEY = 'playground-code';
8+
9+
const DEFAULT_CODE = `infographic list-row-horizontal-icon-arrow
10+
data
11+
title 信息图示例
12+
desc 粘贴或编辑左侧语法,右侧实时预览
13+
lists
14+
- label 项目一
15+
value 12.3
16+
desc 描述文字
17+
icon company-021_v1_lineal
18+
- label 项目二
19+
value 8.6
20+
desc 描述文字
21+
icon antenna-bars-5_v1_lineal
22+
- label 项目三
23+
value 15.1
24+
desc 描述文字
25+
icon achievment-050_v1_lineal
26+
`;
27+
28+
export const Playground = () => {
29+
const [code, setCode] = useState(() => {
30+
const saved = getStoredValues<{ code: string }>(STORAGE_KEY);
31+
return saved?.code || DEFAULT_CODE;
32+
});
33+
const [options, setOptions] = useState(code);
34+
35+
// Debounce: update preview 500ms after last edit, also persist
36+
useEffect(() => {
37+
const timer = setTimeout(() => {
38+
setOptions(code);
39+
setStoredValues(STORAGE_KEY, { code });
40+
}, 500);
41+
return () => clearTimeout(timer);
42+
}, [code]);
43+
44+
return (
45+
<div
46+
style={{
47+
display: 'flex',
48+
gap: 16,
49+
padding: 16,
50+
flex: 1,
51+
overflow: 'hidden',
52+
}}
53+
>
54+
<div style={{ width: 420, display: 'flex', flexDirection: 'column' }}>
55+
<Card
56+
title="语法输入"
57+
size="small"
58+
style={{ flex: 1, display: 'flex', flexDirection: 'column' }}
59+
styles={{
60+
body: {
61+
flex: 1,
62+
display: 'flex',
63+
flexDirection: 'column',
64+
overflow: 'hidden',
65+
},
66+
}}
67+
>
68+
<div style={{ flex: 1 }}>
69+
<Editor
70+
height="100%"
71+
defaultLanguage="plaintext"
72+
value={code}
73+
theme="vs-dark"
74+
options={{
75+
minimap: { enabled: false },
76+
fontSize: 13,
77+
lineNumbers: 'on',
78+
scrollBeyondLastLine: false,
79+
wordWrap: 'on',
80+
}}
81+
onChange={(value) => setCode(value || '')}
82+
/>
83+
</div>
84+
</Card>
85+
</div>
86+
87+
<div style={{ flex: 1, overflow: 'auto' }}>
88+
<Card title="预览" size="small" style={{ height: '100%' }}>
89+
<Infographic options={options} />
90+
</Card>
91+
</div>
92+
</div>
93+
);
94+
};

0 commit comments

Comments
 (0)