@tyx1703/json-schema-editor-visual 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,634 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import react, { useCallback, useMemo } from "react";
3
+ import { Button, Checkbox, Col, Dropdown, Input, Row, Select, Space, Tooltip, message } from "antd";
4
+ import { CaretDownOutlined, CaretRightOutlined, CloseOutlined, EditOutlined, PlusOutlined, SettingOutlined } from "@ant-design/icons";
5
+ import { JSONPATH_JOIN_CHAR, SCHEMA_TYPE, getData, isEqual, isNil } from "../../utils.js";
6
+ import FieldInput from "./FieldInput.js";
7
+ import { useLocalProvider } from "../LocalProvider/index.js";
8
+ import MockSelect from "../MockSelect/index.js";
9
+ import { useAppDispatch, useAppSelector } from "../../store/index.js";
10
+ import { addChildFieldAction, addFieldAction, changeNameAction, changeTypeAction, changeValueAction, deleteItemAction, enableRequireAction, setOpenValueAction } from "../../store/schemaSlice.js";
11
+ import "./schemaJson.css";
12
+ const { Option: Option } = Select;
13
+ const mapping = (name, data, showEdit, showAdv, mock)=>{
14
+ switch(data.type){
15
+ case 'array':
16
+ return /*#__PURE__*/ jsx(SchemaArray, {
17
+ prefix: name,
18
+ data: data,
19
+ showEdit: showEdit,
20
+ showAdv: showAdv,
21
+ mock: mock
22
+ });
23
+ case 'object':
24
+ {
25
+ const nameArray = [
26
+ ...name,
27
+ 'properties'
28
+ ];
29
+ return /*#__PURE__*/ jsx(SchemaObject, {
30
+ prefix: nameArray,
31
+ data: data,
32
+ showEdit: showEdit,
33
+ showAdv: showAdv,
34
+ mock: mock
35
+ });
36
+ }
37
+ default:
38
+ return null;
39
+ }
40
+ };
41
+ const SchemaArray = /*#__PURE__*/ react.memo(({ data, prefix, showEdit, showAdv, mock })=>{
42
+ const isMock = Boolean(mock);
43
+ const dispatch = useAppDispatch();
44
+ const open = useAppSelector((state)=>state.schema.open);
45
+ const LocaleProvider = useLocalProvider();
46
+ const tagPaddingLeftStyle = useMemo(()=>{
47
+ const length = prefix.filter((name)=>'properties' !== name).length;
48
+ return {
49
+ paddingLeft: `${20 * (length + 1)}px`
50
+ };
51
+ }, [
52
+ prefix
53
+ ]);
54
+ const getPrefix = useCallback(()=>[
55
+ ...prefix,
56
+ 'items'
57
+ ], [
58
+ prefix
59
+ ]);
60
+ const handleChangeType = (value)=>{
61
+ const key = [
62
+ ...getPrefix(),
63
+ 'type'
64
+ ];
65
+ dispatch(changeTypeAction({
66
+ key,
67
+ value
68
+ }));
69
+ };
70
+ const handleChangeDesc = (e)=>{
71
+ const key = [
72
+ ...getPrefix(),
73
+ "description"
74
+ ];
75
+ dispatch(changeValueAction({
76
+ key,
77
+ value: e.target.value
78
+ }));
79
+ };
80
+ const handleChangeMock = (e)=>{
81
+ const key = [
82
+ ...getPrefix(),
83
+ 'mock'
84
+ ];
85
+ const value = e ? {
86
+ mock: e
87
+ } : '';
88
+ dispatch(changeValueAction({
89
+ key,
90
+ value
91
+ }));
92
+ };
93
+ const handleChangeTitle = (e)=>{
94
+ const key = [
95
+ ...getPrefix(),
96
+ 'title'
97
+ ];
98
+ dispatch(changeValueAction({
99
+ key,
100
+ value: e.target.value
101
+ }));
102
+ };
103
+ const handleAddChildField = ()=>{
104
+ const keyArr = [
105
+ ...getPrefix(),
106
+ 'properties'
107
+ ];
108
+ dispatch(addChildFieldAction({
109
+ key: keyArr
110
+ }));
111
+ dispatch(setOpenValueAction({
112
+ key: keyArr,
113
+ value: true
114
+ }));
115
+ };
116
+ const handleClickIcon = ()=>{
117
+ const keyArr = [
118
+ ...getPrefix(),
119
+ 'properties'
120
+ ];
121
+ dispatch(setOpenValueAction({
122
+ key: keyArr
123
+ }));
124
+ };
125
+ const handleShowEdit = (name, type)=>{
126
+ showEdit(getPrefix(), name, data.items?.[name], type);
127
+ };
128
+ const handleShowAdv = ()=>{
129
+ showAdv(getPrefix(), data.items);
130
+ };
131
+ if (isNil(data.items)) return null;
132
+ const items = data.items;
133
+ const prefixArray = getPrefix();
134
+ const prefixArrayStr = [
135
+ ...prefixArray,
136
+ 'properties'
137
+ ].join(JSONPATH_JOIN_CHAR);
138
+ const showIcon = getData(open, [
139
+ prefixArrayStr
140
+ ]);
141
+ return /*#__PURE__*/ jsxs("div", {
142
+ className: "array-type",
143
+ children: [
144
+ /*#__PURE__*/ jsxs(Row, {
145
+ className: "array-item-type",
146
+ justify: "space-around",
147
+ align: "middle",
148
+ children: [
149
+ /*#__PURE__*/ jsx(Col, {
150
+ span: 8,
151
+ className: "col-item name-item col-item-name",
152
+ style: tagPaddingLeftStyle,
153
+ children: /*#__PURE__*/ jsxs(Row, {
154
+ justify: "space-around",
155
+ align: "middle",
156
+ children: [
157
+ /*#__PURE__*/ jsx(Col, {
158
+ span: 2,
159
+ className: "down-style-col",
160
+ children: 'object' === items.type && /*#__PURE__*/ jsx("span", {
161
+ className: "down-style",
162
+ onClick: handleClickIcon,
163
+ children: showIcon ? /*#__PURE__*/ jsx(CaretDownOutlined, {
164
+ className: "icon-object"
165
+ }) : /*#__PURE__*/ jsx(CaretRightOutlined, {
166
+ className: "icon-object"
167
+ })
168
+ })
169
+ }),
170
+ /*#__PURE__*/ jsx(Col, {
171
+ span: 22,
172
+ children: /*#__PURE__*/ jsxs(Space.Compact, {
173
+ children: [
174
+ /*#__PURE__*/ jsx(Input, {
175
+ disabled: true,
176
+ value: "Items"
177
+ }),
178
+ /*#__PURE__*/ jsx(Button, {
179
+ type: "text",
180
+ disabled: true,
181
+ icon: /*#__PURE__*/ jsx(Checkbox, {
182
+ disabled: true
183
+ })
184
+ })
185
+ ]
186
+ })
187
+ })
188
+ ]
189
+ })
190
+ }),
191
+ /*#__PURE__*/ jsx(Col, {
192
+ span: 3,
193
+ className: "col-item col-item-type",
194
+ children: /*#__PURE__*/ jsx(Select, {
195
+ className: "type-select-style",
196
+ onChange: handleChangeType,
197
+ value: items.type,
198
+ children: SCHEMA_TYPE.map((item, index)=>/*#__PURE__*/ jsx(Option, {
199
+ value: item,
200
+ children: item
201
+ }, index))
202
+ })
203
+ }),
204
+ isMock && /*#__PURE__*/ jsx(Col, {
205
+ span: 3,
206
+ className: "col-item col-item-mock",
207
+ children: /*#__PURE__*/ jsx(MockSelect, {
208
+ schema: items,
209
+ showEdit: ()=>handleShowEdit('mock', items.type),
210
+ onChange: handleChangeMock,
211
+ mock: mock
212
+ })
213
+ }),
214
+ /*#__PURE__*/ jsx(Col, {
215
+ span: isMock ? 4 : 5,
216
+ className: "col-item col-item-mock",
217
+ children: /*#__PURE__*/ jsxs(Space.Compact, {
218
+ children: [
219
+ /*#__PURE__*/ jsx(Input, {
220
+ placeholder: LocaleProvider('title'),
221
+ value: items.title,
222
+ onChange: handleChangeTitle
223
+ }),
224
+ /*#__PURE__*/ jsx(Button, {
225
+ icon: /*#__PURE__*/ jsx(EditOutlined, {}),
226
+ onClick: ()=>handleShowEdit('title')
227
+ })
228
+ ]
229
+ })
230
+ }),
231
+ /*#__PURE__*/ jsx(Col, {
232
+ span: isMock ? 4 : 5,
233
+ className: "col-item col-item-desc",
234
+ children: /*#__PURE__*/ jsxs(Space.Compact, {
235
+ children: [
236
+ /*#__PURE__*/ jsx(Input, {
237
+ placeholder: LocaleProvider("description"),
238
+ value: items.description,
239
+ onChange: handleChangeDesc
240
+ }),
241
+ /*#__PURE__*/ jsx(Button, {
242
+ icon: /*#__PURE__*/ jsx(EditOutlined, {}),
243
+ onClick: ()=>handleShowEdit("description")
244
+ })
245
+ ]
246
+ })
247
+ }),
248
+ /*#__PURE__*/ jsxs(Col, {
249
+ span: isMock ? 2 : 3,
250
+ className: "col-item col-item-setting",
251
+ children: [
252
+ /*#__PURE__*/ jsx("span", {
253
+ className: "adv-set",
254
+ onClick: handleShowAdv,
255
+ children: /*#__PURE__*/ jsx(Tooltip, {
256
+ placement: "top",
257
+ title: LocaleProvider('adv_setting'),
258
+ children: /*#__PURE__*/ jsx(SettingOutlined, {})
259
+ })
260
+ }),
261
+ 'object' === items.type && /*#__PURE__*/ jsx("span", {
262
+ onClick: handleAddChildField,
263
+ children: /*#__PURE__*/ jsx(Tooltip, {
264
+ placement: "top",
265
+ title: LocaleProvider('add_child_node'),
266
+ children: /*#__PURE__*/ jsx(PlusOutlined, {
267
+ className: "plus"
268
+ })
269
+ })
270
+ })
271
+ ]
272
+ })
273
+ ]
274
+ }),
275
+ /*#__PURE__*/ jsx("div", {
276
+ className: "option-formStyle",
277
+ children: mapping(prefixArray, items, showEdit, showAdv, mock)
278
+ })
279
+ ]
280
+ });
281
+ });
282
+ const SchemaItem = /*#__PURE__*/ react.memo(({ name, data, prefix, showEdit, showAdv, mock })=>{
283
+ const dispatch = useAppDispatch();
284
+ const open = useAppSelector((state)=>state.schema.open);
285
+ const LocaleProvider = useLocalProvider();
286
+ const tagPaddingLeftStyle = useMemo(()=>{
287
+ const length = prefix.filter((n)=>'properties' !== n).length;
288
+ return {
289
+ paddingLeft: `${20 * (length + 1)}px`
290
+ };
291
+ }, [
292
+ prefix
293
+ ]);
294
+ const getPrefix = useCallback(()=>[
295
+ ...prefix,
296
+ name
297
+ ], [
298
+ prefix,
299
+ name
300
+ ]);
301
+ const handleChangeName = (e)=>{
302
+ const value = e.target.value;
303
+ if (data.properties[value] && 'object' == typeof data.properties[value]) return message.error(`The field "${value}" already exists.`);
304
+ dispatch(changeNameAction({
305
+ value,
306
+ prefix,
307
+ name
308
+ }));
309
+ };
310
+ const handleChangeDesc = (e)=>{
311
+ const key = [
312
+ ...getPrefix(),
313
+ "description"
314
+ ];
315
+ dispatch(changeValueAction({
316
+ key,
317
+ value: e.target.value
318
+ }));
319
+ };
320
+ const handleChangeMock = (e)=>{
321
+ const key = [
322
+ ...getPrefix(),
323
+ 'mock'
324
+ ];
325
+ const value = e ? {
326
+ mock: e
327
+ } : '';
328
+ dispatch(changeValueAction({
329
+ key,
330
+ value
331
+ }));
332
+ };
333
+ const handleChangeTitle = (e)=>{
334
+ const key = [
335
+ ...getPrefix(),
336
+ 'title'
337
+ ];
338
+ dispatch(changeValueAction({
339
+ key,
340
+ value: e.target.value
341
+ }));
342
+ };
343
+ const handleChangeType = (value)=>{
344
+ const key = [
345
+ ...getPrefix(),
346
+ 'type'
347
+ ];
348
+ dispatch(changeTypeAction({
349
+ key,
350
+ value
351
+ }));
352
+ };
353
+ const handleDeleteItem = ()=>{
354
+ const keyArr = getPrefix();
355
+ dispatch(deleteItemAction({
356
+ key: keyArr
357
+ }));
358
+ dispatch(enableRequireAction({
359
+ prefix,
360
+ name,
361
+ required: false
362
+ }));
363
+ };
364
+ const handleShowEdit = (editorName, type)=>{
365
+ showEdit(getPrefix(), editorName, data.properties[name][editorName], type);
366
+ };
367
+ const handleShowAdv = ()=>{
368
+ showAdv(getPrefix(), data.properties[name]);
369
+ };
370
+ const handleAddField = ()=>{
371
+ dispatch(addFieldAction({
372
+ prefix,
373
+ name
374
+ }));
375
+ };
376
+ const handleClickIcon = ()=>{
377
+ const keyArr = [
378
+ ...getPrefix(),
379
+ 'properties'
380
+ ];
381
+ dispatch(setOpenValueAction({
382
+ key: keyArr
383
+ }));
384
+ };
385
+ const handleEnableRequire = (e)=>{
386
+ const required = e.target.checked;
387
+ dispatch(enableRequireAction({
388
+ prefix,
389
+ name,
390
+ required
391
+ }));
392
+ };
393
+ const value = data.properties[name];
394
+ const prefixArray = getPrefix();
395
+ const prefixStr = prefix.join(JSONPATH_JOIN_CHAR);
396
+ const prefixArrayStr = [
397
+ ...prefixArray,
398
+ 'properties'
399
+ ].join(JSONPATH_JOIN_CHAR);
400
+ const show = getData(open, [
401
+ prefixStr
402
+ ]);
403
+ const showIcon = getData(open, [
404
+ prefixArrayStr
405
+ ]);
406
+ if (!show) return null;
407
+ return /*#__PURE__*/ jsxs("div", {
408
+ "data-testid": null,
409
+ children: [
410
+ /*#__PURE__*/ jsxs(Row, {
411
+ justify: "space-around",
412
+ align: "middle",
413
+ children: [
414
+ /*#__PURE__*/ jsx(Col, {
415
+ span: 8,
416
+ className: "col-item name-item col-item-name",
417
+ style: tagPaddingLeftStyle,
418
+ children: /*#__PURE__*/ jsxs(Row, {
419
+ justify: "space-around",
420
+ align: "middle",
421
+ children: [
422
+ /*#__PURE__*/ jsx(Col, {
423
+ span: 2,
424
+ className: "down-style-col",
425
+ children: 'object' === value.type && /*#__PURE__*/ jsx("span", {
426
+ className: "down-style",
427
+ onClick: handleClickIcon,
428
+ children: showIcon ? /*#__PURE__*/ jsx(CaretDownOutlined, {
429
+ className: "icon-object"
430
+ }) : /*#__PURE__*/ jsx(CaretRightOutlined, {
431
+ className: "icon-object"
432
+ })
433
+ })
434
+ }),
435
+ /*#__PURE__*/ jsx(Col, {
436
+ span: 22,
437
+ children: /*#__PURE__*/ jsxs(Space.Compact, {
438
+ children: [
439
+ /*#__PURE__*/ jsx(FieldInput, {
440
+ onChange: handleChangeName,
441
+ value: name,
442
+ "data-testid": null
443
+ }),
444
+ /*#__PURE__*/ jsx(Tooltip, {
445
+ placement: "top",
446
+ title: LocaleProvider('required'),
447
+ children: /*#__PURE__*/ jsx(Button, {
448
+ type: "text",
449
+ children: /*#__PURE__*/ jsx(Checkbox, {
450
+ onChange: handleEnableRequire,
451
+ checked: isNil(data.required) ? false : data.required.includes(name)
452
+ })
453
+ })
454
+ })
455
+ ]
456
+ })
457
+ })
458
+ ]
459
+ })
460
+ }),
461
+ /*#__PURE__*/ jsx(Col, {
462
+ span: 3,
463
+ className: "col-item col-item-type",
464
+ children: /*#__PURE__*/ jsx(Select, {
465
+ className: "type-select-style",
466
+ onChange: handleChangeType,
467
+ value: value.type,
468
+ children: SCHEMA_TYPE.map((item, index)=>/*#__PURE__*/ jsx(Option, {
469
+ value: item,
470
+ children: item
471
+ }, index))
472
+ })
473
+ }),
474
+ mock && /*#__PURE__*/ jsx(Col, {
475
+ span: 3,
476
+ className: "col-item col-item-mock",
477
+ children: /*#__PURE__*/ jsx(MockSelect, {
478
+ schema: value,
479
+ showEdit: ()=>handleShowEdit('mock', value.type),
480
+ onChange: handleChangeMock,
481
+ mock: mock
482
+ })
483
+ }),
484
+ /*#__PURE__*/ jsx(Col, {
485
+ span: mock ? 4 : 5,
486
+ className: "col-item col-item-mock",
487
+ children: /*#__PURE__*/ jsxs(Space.Compact, {
488
+ children: [
489
+ /*#__PURE__*/ jsx(Input, {
490
+ placeholder: LocaleProvider('title'),
491
+ value: value.title,
492
+ onChange: handleChangeTitle,
493
+ "data-testid": null
494
+ }),
495
+ /*#__PURE__*/ jsx(Button, {
496
+ icon: /*#__PURE__*/ jsx(EditOutlined, {}),
497
+ onClick: ()=>handleShowEdit('title')
498
+ })
499
+ ]
500
+ })
501
+ }),
502
+ /*#__PURE__*/ jsx(Col, {
503
+ span: mock ? 4 : 5,
504
+ className: "col-item col-item-desc",
505
+ children: /*#__PURE__*/ jsxs(Space.Compact, {
506
+ children: [
507
+ /*#__PURE__*/ jsx(Input, {
508
+ placeholder: LocaleProvider("description"),
509
+ value: value.description,
510
+ onChange: handleChangeDesc,
511
+ "data-testid": null
512
+ }),
513
+ /*#__PURE__*/ jsx(Button, {
514
+ icon: /*#__PURE__*/ jsx(EditOutlined, {}),
515
+ onClick: ()=>handleShowEdit("description")
516
+ })
517
+ ]
518
+ })
519
+ }),
520
+ /*#__PURE__*/ jsxs(Col, {
521
+ span: mock ? 2 : 3,
522
+ className: "col-item col-item-setting",
523
+ children: [
524
+ /*#__PURE__*/ jsx("span", {
525
+ className: "adv-set",
526
+ onClick: handleShowAdv,
527
+ "data-testid": null,
528
+ children: /*#__PURE__*/ jsx(Tooltip, {
529
+ placement: "top",
530
+ title: LocaleProvider('adv_setting'),
531
+ children: /*#__PURE__*/ jsx(SettingOutlined, {})
532
+ })
533
+ }),
534
+ /*#__PURE__*/ jsx("span", {
535
+ className: "delete-item",
536
+ onClick: handleDeleteItem,
537
+ children: /*#__PURE__*/ jsx(CloseOutlined, {
538
+ className: "close"
539
+ })
540
+ }),
541
+ 'object' === value.type ? /*#__PURE__*/ jsx(DropPlus, {
542
+ prefix: prefix,
543
+ name: name
544
+ }) : /*#__PURE__*/ jsx("span", {
545
+ onClick: handleAddField,
546
+ children: /*#__PURE__*/ jsx(Tooltip, {
547
+ placement: "top",
548
+ title: LocaleProvider('add_sibling_node'),
549
+ children: /*#__PURE__*/ jsx(PlusOutlined, {
550
+ className: "plus"
551
+ })
552
+ })
553
+ })
554
+ ]
555
+ })
556
+ ]
557
+ }),
558
+ /*#__PURE__*/ jsx("div", {
559
+ className: "option-formStyle",
560
+ children: mapping(prefixArray, value, showEdit, showAdv, mock)
561
+ })
562
+ ]
563
+ });
564
+ });
565
+ const SchemaObjectComponent = ({ data, prefix, showEdit, showAdv, mock })=>{
566
+ useAppSelector((state)=>state.schema.open);
567
+ return /*#__PURE__*/ jsx("div", {
568
+ className: "object-style",
569
+ children: Object.keys(data.properties || {}).map((name)=>/*#__PURE__*/ jsx(SchemaItem, {
570
+ data: data,
571
+ name: name,
572
+ prefix: prefix,
573
+ showEdit: showEdit,
574
+ showAdv: showAdv,
575
+ mock: mock
576
+ }, name))
577
+ });
578
+ };
579
+ const SchemaObject = /*#__PURE__*/ react.memo(SchemaObjectComponent, (prevProps, nextProps)=>isEqual(prevProps.data, nextProps.data) && isEqual(prevProps.prefix, nextProps.prefix));
580
+ const DropPlus = ({ prefix, name })=>{
581
+ const dispatch = useAppDispatch();
582
+ const LocaleProvider = useLocalProvider();
583
+ const menuItems = [
584
+ {
585
+ key: 'sibling',
586
+ label: LocaleProvider('sibling_node'),
587
+ onClick: ()=>dispatch(addFieldAction({
588
+ prefix,
589
+ name
590
+ }))
591
+ },
592
+ {
593
+ key: 'child',
594
+ label: LocaleProvider('child_node'),
595
+ onClick: ()=>{
596
+ dispatch(setOpenValueAction({
597
+ key: [
598
+ ...prefix,
599
+ name,
600
+ 'properties'
601
+ ],
602
+ value: true
603
+ }));
604
+ dispatch(addChildFieldAction({
605
+ key: [
606
+ ...prefix,
607
+ name,
608
+ 'properties'
609
+ ]
610
+ }));
611
+ }
612
+ }
613
+ ];
614
+ return /*#__PURE__*/ jsx(Tooltip, {
615
+ placement: "top",
616
+ title: LocaleProvider('add_node'),
617
+ children: /*#__PURE__*/ jsx(Dropdown, {
618
+ menu: {
619
+ items: menuItems
620
+ },
621
+ children: /*#__PURE__*/ jsx(PlusOutlined, {
622
+ className: "plus"
623
+ })
624
+ })
625
+ });
626
+ };
627
+ function SchemaJson({ data, showEdit, showAdv, mock }) {
628
+ const item = mapping([], data, showEdit, showAdv, mock);
629
+ return /*#__PURE__*/ jsx("div", {
630
+ className: "schema-content",
631
+ children: item
632
+ });
633
+ }
634
+ export default SchemaJson;
@@ -0,0 +1,9 @@
1
+ import './schemaJson.css';
2
+ import { JsonSchema, Format } from '../../types';
3
+ interface CustomItemProps {
4
+ data: string;
5
+ changeCustomValue: (data: JsonSchema) => void;
6
+ format: Format;
7
+ }
8
+ export default function CustomItem({ data, changeCustomValue, format, }: CustomItemProps): import("react/jsx-runtime").JSX.Element;
9
+ export {};