@datenlotse/jsonjoy-builder 0.4.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.
- package/LICENSE +21 -0
- package/README.md +203 -0
- package/dist/components/SchemaEditor/AddFieldButton.js +312 -0
- package/dist/components/SchemaEditor/JsonSchemaEditor.js +166 -0
- package/dist/components/SchemaEditor/JsonSchemaVisualizer.js +96 -0
- package/dist/components/SchemaEditor/SchemaField.js +104 -0
- package/dist/components/SchemaEditor/SchemaFieldList.js +84 -0
- package/dist/components/SchemaEditor/SchemaPropertyEditor.js +249 -0
- package/dist/components/SchemaEditor/SchemaTypeSelector.js +55 -0
- package/dist/components/SchemaEditor/SchemaVisualEditor.js +77 -0
- package/dist/components/SchemaEditor/TypeDropdown.js +72 -0
- package/dist/components/SchemaEditor/TypeEditor.js +71 -0
- package/dist/components/SchemaEditor/types/ArrayEditor.js +173 -0
- package/dist/components/SchemaEditor/types/BooleanEditor.js +107 -0
- package/dist/components/SchemaEditor/types/NumberEditor.js +583 -0
- package/dist/components/SchemaEditor/types/ObjectEditor.js +90 -0
- package/dist/components/SchemaEditor/types/StringEditor.js +542 -0
- package/dist/components/features/JsonValidator.js +239 -0
- package/dist/components/features/SchemaInferencer.js +107 -0
- package/dist/components/ui/badge.js +25 -0
- package/dist/components/ui/button.js +41 -0
- package/dist/components/ui/dialog.js +73 -0
- package/dist/components/ui/input.js +11 -0
- package/dist/components/ui/label.js +13 -0
- package/dist/components/ui/select.js +90 -0
- package/dist/components/ui/switch.js +14 -0
- package/dist/components/ui/tabs.js +24 -0
- package/dist/components/ui/tooltip.js +15 -0
- package/dist/hooks/use-monaco-theme.js +197 -0
- package/dist/hooks/use-translation.js +14 -0
- package/dist/i18n/locales/de.js +143 -0
- package/dist/i18n/locales/en.js +143 -0
- package/dist/i18n/locales/es.js +143 -0
- package/dist/i18n/locales/fr.js +143 -0
- package/dist/i18n/locales/ru.js +143 -0
- package/dist/i18n/locales/uk.js +143 -0
- package/dist/i18n/locales/zh.js +143 -0
- package/dist/i18n/translation-context.js +4 -0
- package/dist/i18n/translation-keys.js +0 -0
- package/dist/index.css +3830 -0
- package/dist/index.d.ts +995 -0
- package/dist/index.js +10 -0
- package/dist/lib/schema-inference.js +266 -0
- package/dist/lib/schemaCompile.js +113 -0
- package/dist/lib/schemaEditor.js +167 -0
- package/dist/lib/utils.js +40 -0
- package/dist/types/jsonSchema.js +98 -0
- package/dist/types/validation.js +215 -0
- package/dist/utils/jsonValidator.js +162 -0
- package/package.json +112 -0
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Maximize2 } from "lucide-react";
|
|
3
|
+
import { useRef, useState } from "react";
|
|
4
|
+
import { Tabs, TabsContent, TabsList, TabsTrigger } from "../ui/tabs.js";
|
|
5
|
+
import { useTranslation } from "../../hooks/use-translation.js";
|
|
6
|
+
import { cn } from "../../lib/utils.js";
|
|
7
|
+
import JsonSchemaVisualizer from "./JsonSchemaVisualizer.js";
|
|
8
|
+
import SchemaVisualEditor from "./SchemaVisualEditor.js";
|
|
9
|
+
const JsonSchemaEditor = ({ schema = {
|
|
10
|
+
type: "object"
|
|
11
|
+
}, readOnly = false, setSchema, className })=>{
|
|
12
|
+
const handleSchemaChange = (newSchema)=>{
|
|
13
|
+
setSchema(newSchema);
|
|
14
|
+
};
|
|
15
|
+
const t = useTranslation();
|
|
16
|
+
const [isFullscreen, setIsFullscreen] = useState(false);
|
|
17
|
+
const [leftPanelWidth, setLeftPanelWidth] = useState(50);
|
|
18
|
+
const resizeRef = useRef(null);
|
|
19
|
+
const containerRef = useRef(null);
|
|
20
|
+
const isDraggingRef = useRef(false);
|
|
21
|
+
const toggleFullscreen = ()=>{
|
|
22
|
+
setIsFullscreen(!isFullscreen);
|
|
23
|
+
};
|
|
24
|
+
const fullscreenClass = isFullscreen ? "fixed inset-0 z-50 bg-background" : "";
|
|
25
|
+
const handleMouseDown = (e)=>{
|
|
26
|
+
e.preventDefault();
|
|
27
|
+
isDraggingRef.current = true;
|
|
28
|
+
document.addEventListener("mousemove", handleMouseMove);
|
|
29
|
+
document.addEventListener("mouseup", handleMouseUp);
|
|
30
|
+
};
|
|
31
|
+
const handleMouseMove = (e)=>{
|
|
32
|
+
if (!isDraggingRef.current || !containerRef.current) return;
|
|
33
|
+
const containerRect = containerRef.current.getBoundingClientRect();
|
|
34
|
+
const newWidth = (e.clientX - containerRect.left) / containerRect.width * 100;
|
|
35
|
+
if (newWidth >= 20 && newWidth <= 80) setLeftPanelWidth(newWidth);
|
|
36
|
+
};
|
|
37
|
+
const handleMouseUp = ()=>{
|
|
38
|
+
isDraggingRef.current = false;
|
|
39
|
+
document.removeEventListener("mousemove", handleMouseMove);
|
|
40
|
+
document.removeEventListener("mouseup", handleMouseUp);
|
|
41
|
+
};
|
|
42
|
+
return /*#__PURE__*/ jsxs("div", {
|
|
43
|
+
className: cn("json-editor-container w-full", fullscreenClass, className, "jsonjoy"),
|
|
44
|
+
children: [
|
|
45
|
+
/*#__PURE__*/ jsx("div", {
|
|
46
|
+
className: "block lg:hidden w-full",
|
|
47
|
+
children: /*#__PURE__*/ jsxs(Tabs, {
|
|
48
|
+
defaultValue: "visual",
|
|
49
|
+
className: "w-full",
|
|
50
|
+
children: [
|
|
51
|
+
/*#__PURE__*/ jsxs("div", {
|
|
52
|
+
className: "flex items-center justify-between px-4 py-3 border-b w-full",
|
|
53
|
+
children: [
|
|
54
|
+
/*#__PURE__*/ jsx("h3", {
|
|
55
|
+
className: "font-medium",
|
|
56
|
+
children: t.schemaEditorTitle
|
|
57
|
+
}),
|
|
58
|
+
/*#__PURE__*/ jsxs("div", {
|
|
59
|
+
className: "flex items-center gap-2",
|
|
60
|
+
children: [
|
|
61
|
+
/*#__PURE__*/ jsx("button", {
|
|
62
|
+
type: "button",
|
|
63
|
+
onClick: toggleFullscreen,
|
|
64
|
+
className: "p-1.5 rounded-md hover:bg-secondary transition-colors",
|
|
65
|
+
"aria-label": t.schemaEditorToggleFullscreen,
|
|
66
|
+
children: /*#__PURE__*/ jsx(Maximize2, {
|
|
67
|
+
size: 16
|
|
68
|
+
})
|
|
69
|
+
}),
|
|
70
|
+
/*#__PURE__*/ jsxs(TabsList, {
|
|
71
|
+
className: "grid grid-cols-2 w-[200px]",
|
|
72
|
+
children: [
|
|
73
|
+
/*#__PURE__*/ jsx(TabsTrigger, {
|
|
74
|
+
value: "visual",
|
|
75
|
+
children: t.schemaEditorEditModeVisual
|
|
76
|
+
}),
|
|
77
|
+
/*#__PURE__*/ jsx(TabsTrigger, {
|
|
78
|
+
value: "json",
|
|
79
|
+
children: t.schemaEditorEditModeJson
|
|
80
|
+
})
|
|
81
|
+
]
|
|
82
|
+
})
|
|
83
|
+
]
|
|
84
|
+
})
|
|
85
|
+
]
|
|
86
|
+
}),
|
|
87
|
+
/*#__PURE__*/ jsx(TabsContent, {
|
|
88
|
+
value: "visual",
|
|
89
|
+
className: cn("focus:outline-hidden w-full", isFullscreen ? "h-screen" : "h-[500px]"),
|
|
90
|
+
children: /*#__PURE__*/ jsx(SchemaVisualEditor, {
|
|
91
|
+
readOnly: readOnly,
|
|
92
|
+
schema: schema,
|
|
93
|
+
onChange: handleSchemaChange
|
|
94
|
+
})
|
|
95
|
+
}),
|
|
96
|
+
/*#__PURE__*/ jsx(TabsContent, {
|
|
97
|
+
value: "json",
|
|
98
|
+
className: cn("focus:outline-hidden w-full", isFullscreen ? "h-screen" : "h-[500px]"),
|
|
99
|
+
children: /*#__PURE__*/ jsx(JsonSchemaVisualizer, {
|
|
100
|
+
schema: schema,
|
|
101
|
+
onChange: handleSchemaChange
|
|
102
|
+
})
|
|
103
|
+
})
|
|
104
|
+
]
|
|
105
|
+
})
|
|
106
|
+
}),
|
|
107
|
+
/*#__PURE__*/ jsxs("div", {
|
|
108
|
+
ref: containerRef,
|
|
109
|
+
className: cn("hidden lg:flex lg:flex-col w-full", isFullscreen ? "h-screen" : "h-[600px]"),
|
|
110
|
+
children: [
|
|
111
|
+
/*#__PURE__*/ jsxs("div", {
|
|
112
|
+
className: "flex items-center justify-between px-4 py-3 border-b w-full shrink-0",
|
|
113
|
+
children: [
|
|
114
|
+
/*#__PURE__*/ jsx("h3", {
|
|
115
|
+
className: "font-medium",
|
|
116
|
+
children: t.schemaEditorTitle
|
|
117
|
+
}),
|
|
118
|
+
/*#__PURE__*/ jsx("button", {
|
|
119
|
+
type: "button",
|
|
120
|
+
onClick: toggleFullscreen,
|
|
121
|
+
className: "p-1.5 rounded-md hover:bg-secondary transition-colors",
|
|
122
|
+
"aria-label": t.schemaEditorToggleFullscreen,
|
|
123
|
+
children: /*#__PURE__*/ jsx(Maximize2, {
|
|
124
|
+
size: 16
|
|
125
|
+
})
|
|
126
|
+
})
|
|
127
|
+
]
|
|
128
|
+
}),
|
|
129
|
+
/*#__PURE__*/ jsxs("div", {
|
|
130
|
+
className: "flex flex-row w-full grow min-h-0",
|
|
131
|
+
children: [
|
|
132
|
+
/*#__PURE__*/ jsx("div", {
|
|
133
|
+
className: "h-full min-h-0",
|
|
134
|
+
style: {
|
|
135
|
+
width: `${leftPanelWidth}%`
|
|
136
|
+
},
|
|
137
|
+
children: /*#__PURE__*/ jsx(SchemaVisualEditor, {
|
|
138
|
+
readOnly: readOnly,
|
|
139
|
+
schema: schema,
|
|
140
|
+
onChange: handleSchemaChange
|
|
141
|
+
})
|
|
142
|
+
}),
|
|
143
|
+
/*#__PURE__*/ jsx("div", {
|
|
144
|
+
ref: resizeRef,
|
|
145
|
+
className: "w-1 bg-border hover:bg-primary cursor-col-resize shrink-0",
|
|
146
|
+
onMouseDown: handleMouseDown
|
|
147
|
+
}),
|
|
148
|
+
/*#__PURE__*/ jsx("div", {
|
|
149
|
+
className: "h-full min-h-0",
|
|
150
|
+
style: {
|
|
151
|
+
width: `${100 - leftPanelWidth}%`
|
|
152
|
+
},
|
|
153
|
+
children: /*#__PURE__*/ jsx(JsonSchemaVisualizer, {
|
|
154
|
+
schema: schema,
|
|
155
|
+
onChange: handleSchemaChange
|
|
156
|
+
})
|
|
157
|
+
})
|
|
158
|
+
]
|
|
159
|
+
})
|
|
160
|
+
]
|
|
161
|
+
})
|
|
162
|
+
]
|
|
163
|
+
});
|
|
164
|
+
};
|
|
165
|
+
const SchemaEditor_JsonSchemaEditor = JsonSchemaEditor;
|
|
166
|
+
export { SchemaEditor_JsonSchemaEditor as default };
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import react from "@monaco-editor/react";
|
|
3
|
+
import { Download, FileJson, Loader2 } from "lucide-react";
|
|
4
|
+
import { useRef } from "react";
|
|
5
|
+
import { useMonacoTheme } from "../../hooks/use-monaco-theme.js";
|
|
6
|
+
import { useTranslation } from "../../hooks/use-translation.js";
|
|
7
|
+
import { cn } from "../../lib/utils.js";
|
|
8
|
+
const JsonSchemaVisualizer = ({ schema, className, onChange })=>{
|
|
9
|
+
const editorRef = useRef(null);
|
|
10
|
+
const { currentTheme, defineMonacoThemes, configureJsonDefaults, defaultEditorOptions } = useMonacoTheme();
|
|
11
|
+
const t = useTranslation();
|
|
12
|
+
const handleBeforeMount = (monaco)=>{
|
|
13
|
+
defineMonacoThemes(monaco);
|
|
14
|
+
configureJsonDefaults(monaco);
|
|
15
|
+
};
|
|
16
|
+
const handleEditorDidMount = (editor)=>{
|
|
17
|
+
editorRef.current = editor;
|
|
18
|
+
editor.focus();
|
|
19
|
+
};
|
|
20
|
+
const handleEditorChange = (value)=>{
|
|
21
|
+
if (!value) return;
|
|
22
|
+
try {
|
|
23
|
+
const parsedJson = JSON.parse(value);
|
|
24
|
+
if (onChange) onChange(parsedJson);
|
|
25
|
+
} catch (_error) {}
|
|
26
|
+
};
|
|
27
|
+
const handleDownload = ()=>{
|
|
28
|
+
const content = JSON.stringify(schema, null, 2);
|
|
29
|
+
const blob = new Blob([
|
|
30
|
+
content
|
|
31
|
+
], {
|
|
32
|
+
type: "application/json"
|
|
33
|
+
});
|
|
34
|
+
const url = URL.createObjectURL(blob);
|
|
35
|
+
const a = document.createElement("a");
|
|
36
|
+
a.href = url;
|
|
37
|
+
a.download = t.visualizerDownloadFileName;
|
|
38
|
+
document.body.appendChild(a);
|
|
39
|
+
a.click();
|
|
40
|
+
document.body.removeChild(a);
|
|
41
|
+
URL.revokeObjectURL(url);
|
|
42
|
+
};
|
|
43
|
+
return /*#__PURE__*/ jsxs("div", {
|
|
44
|
+
className: cn("relative overflow-hidden h-full flex flex-col", className, "jsonjoy"),
|
|
45
|
+
children: [
|
|
46
|
+
/*#__PURE__*/ jsxs("div", {
|
|
47
|
+
className: "flex items-center justify-between bg-secondary/80 backdrop-blur-xs px-4 py-2 border-b shrink-0",
|
|
48
|
+
children: [
|
|
49
|
+
/*#__PURE__*/ jsxs("div", {
|
|
50
|
+
className: "flex items-center gap-2",
|
|
51
|
+
children: [
|
|
52
|
+
/*#__PURE__*/ jsx(FileJson, {
|
|
53
|
+
size: 18
|
|
54
|
+
}),
|
|
55
|
+
/*#__PURE__*/ jsx("span", {
|
|
56
|
+
className: "font-medium text-sm",
|
|
57
|
+
children: t.visualizerSource
|
|
58
|
+
})
|
|
59
|
+
]
|
|
60
|
+
}),
|
|
61
|
+
/*#__PURE__*/ jsx("button", {
|
|
62
|
+
type: "button",
|
|
63
|
+
onClick: handleDownload,
|
|
64
|
+
className: "p-1.5 hover:bg-secondary rounded-md transition-colors",
|
|
65
|
+
title: t.visualizerDownloadTitle,
|
|
66
|
+
children: /*#__PURE__*/ jsx(Download, {
|
|
67
|
+
size: 16
|
|
68
|
+
})
|
|
69
|
+
})
|
|
70
|
+
]
|
|
71
|
+
}),
|
|
72
|
+
/*#__PURE__*/ jsx("div", {
|
|
73
|
+
className: "grow flex min-h-0",
|
|
74
|
+
children: /*#__PURE__*/ jsx(react, {
|
|
75
|
+
height: "100%",
|
|
76
|
+
defaultLanguage: "json",
|
|
77
|
+
value: JSON.stringify(schema, null, 2),
|
|
78
|
+
onChange: handleEditorChange,
|
|
79
|
+
beforeMount: handleBeforeMount,
|
|
80
|
+
onMount: handleEditorDidMount,
|
|
81
|
+
className: "monaco-editor-container w-full h-full",
|
|
82
|
+
loading: /*#__PURE__*/ jsx("div", {
|
|
83
|
+
className: "flex items-center justify-center h-full w-full bg-secondary/30",
|
|
84
|
+
children: /*#__PURE__*/ jsx(Loader2, {
|
|
85
|
+
className: "h-6 w-6 animate-spin"
|
|
86
|
+
})
|
|
87
|
+
}),
|
|
88
|
+
options: defaultEditorOptions,
|
|
89
|
+
theme: currentTheme
|
|
90
|
+
})
|
|
91
|
+
})
|
|
92
|
+
]
|
|
93
|
+
});
|
|
94
|
+
};
|
|
95
|
+
const SchemaEditor_JsonSchemaVisualizer = JsonSchemaVisualizer;
|
|
96
|
+
export { SchemaEditor_JsonSchemaVisualizer as default };
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import react, { Suspense } from "react";
|
|
3
|
+
import { useTranslation } from "../../hooks/use-translation.js";
|
|
4
|
+
import { asObjectSchema, getSchemaDescription, withObjectSchema } from "../../types/jsonSchema.js";
|
|
5
|
+
import SchemaPropertyEditor from "./SchemaPropertyEditor.js";
|
|
6
|
+
const SchemaField = (props)=>{
|
|
7
|
+
const { name, schema, required = false, onDelete, onEdit, depth = 0, readOnly = false } = props;
|
|
8
|
+
const handleNameChange = (newName)=>{
|
|
9
|
+
if (newName === name) return;
|
|
10
|
+
const type = withObjectSchema(schema, (s)=>s.type || "object", "object");
|
|
11
|
+
const description = getSchemaDescription(schema);
|
|
12
|
+
onEdit({
|
|
13
|
+
name: newName,
|
|
14
|
+
type: Array.isArray(type) ? type[0] : type,
|
|
15
|
+
description,
|
|
16
|
+
required,
|
|
17
|
+
validation: asObjectSchema(schema)
|
|
18
|
+
});
|
|
19
|
+
};
|
|
20
|
+
const handleRequiredChange = (isRequired)=>{
|
|
21
|
+
if (isRequired === required) return;
|
|
22
|
+
const type = withObjectSchema(schema, (s)=>s.type || "object", "object");
|
|
23
|
+
const description = getSchemaDescription(schema);
|
|
24
|
+
onEdit({
|
|
25
|
+
name,
|
|
26
|
+
type: Array.isArray(type) ? type[0] : type,
|
|
27
|
+
description,
|
|
28
|
+
required: isRequired,
|
|
29
|
+
validation: asObjectSchema(schema)
|
|
30
|
+
});
|
|
31
|
+
};
|
|
32
|
+
const handleSchemaChange = (newSchema)=>{
|
|
33
|
+
const type = newSchema.type || "object";
|
|
34
|
+
const description = newSchema.description || "";
|
|
35
|
+
onEdit({
|
|
36
|
+
name,
|
|
37
|
+
type: Array.isArray(type) ? type[0] : type,
|
|
38
|
+
description,
|
|
39
|
+
required,
|
|
40
|
+
validation: newSchema
|
|
41
|
+
});
|
|
42
|
+
};
|
|
43
|
+
return /*#__PURE__*/ jsx(SchemaPropertyEditor, {
|
|
44
|
+
name: name,
|
|
45
|
+
readOnly: readOnly,
|
|
46
|
+
schema: schema,
|
|
47
|
+
required: required,
|
|
48
|
+
onDelete: onDelete,
|
|
49
|
+
onNameChange: handleNameChange,
|
|
50
|
+
onRequiredChange: handleRequiredChange,
|
|
51
|
+
onSchemaChange: handleSchemaChange,
|
|
52
|
+
depth: depth
|
|
53
|
+
});
|
|
54
|
+
};
|
|
55
|
+
const SchemaEditor_SchemaField = SchemaField;
|
|
56
|
+
const ExpandButton = ({ expanded, onClick })=>{
|
|
57
|
+
const t = useTranslation();
|
|
58
|
+
const ChevronDown = /*#__PURE__*/ react.lazy(()=>import("lucide-react").then((mod)=>({
|
|
59
|
+
default: mod.ChevronDown
|
|
60
|
+
})));
|
|
61
|
+
const ChevronRight = /*#__PURE__*/ react.lazy(()=>import("lucide-react").then((mod)=>({
|
|
62
|
+
default: mod.ChevronRight
|
|
63
|
+
})));
|
|
64
|
+
return /*#__PURE__*/ jsx("button", {
|
|
65
|
+
type: "button",
|
|
66
|
+
className: "text-muted-foreground hover:text-foreground transition-colors",
|
|
67
|
+
onClick: onClick,
|
|
68
|
+
"aria-label": expanded ? t.collapse : t.expand,
|
|
69
|
+
children: /*#__PURE__*/ jsx(Suspense, {
|
|
70
|
+
fallback: /*#__PURE__*/ jsx("div", {
|
|
71
|
+
className: "w-[18px] h-[18px]"
|
|
72
|
+
}),
|
|
73
|
+
children: expanded ? /*#__PURE__*/ jsx(ChevronDown, {
|
|
74
|
+
size: 18
|
|
75
|
+
}) : /*#__PURE__*/ jsx(ChevronRight, {
|
|
76
|
+
size: 18
|
|
77
|
+
})
|
|
78
|
+
})
|
|
79
|
+
});
|
|
80
|
+
};
|
|
81
|
+
const FieldActions = ({ onDelete })=>{
|
|
82
|
+
const t = useTranslation();
|
|
83
|
+
const X = /*#__PURE__*/ react.lazy(()=>import("lucide-react").then((mod)=>({
|
|
84
|
+
default: mod.X
|
|
85
|
+
})));
|
|
86
|
+
return /*#__PURE__*/ jsx("div", {
|
|
87
|
+
className: "flex items-center gap-1 text-muted-foreground",
|
|
88
|
+
children: /*#__PURE__*/ jsx("button", {
|
|
89
|
+
type: "button",
|
|
90
|
+
onClick: onDelete,
|
|
91
|
+
className: "p-1 rounded-md hover:bg-secondary hover:text-destructive transition-colors opacity-0 group-hover:opacity-100",
|
|
92
|
+
"aria-label": t.fieldDelete,
|
|
93
|
+
children: /*#__PURE__*/ jsx(Suspense, {
|
|
94
|
+
fallback: /*#__PURE__*/ jsx("div", {
|
|
95
|
+
className: "w-[16px] h-[16px]"
|
|
96
|
+
}),
|
|
97
|
+
children: /*#__PURE__*/ jsx(X, {
|
|
98
|
+
size: 16
|
|
99
|
+
})
|
|
100
|
+
})
|
|
101
|
+
})
|
|
102
|
+
});
|
|
103
|
+
};
|
|
104
|
+
export { ExpandButton, FieldActions, SchemaEditor_SchemaField as default };
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useMemo } from "react";
|
|
3
|
+
import { useTranslation } from "../../hooks/use-translation.js";
|
|
4
|
+
import { getSchemaProperties } from "../../lib/schemaEditor.js";
|
|
5
|
+
import { buildValidationTree } from "../../types/validation.js";
|
|
6
|
+
import SchemaPropertyEditor from "./SchemaPropertyEditor.js";
|
|
7
|
+
const SchemaFieldList = ({ schema, onEditField, onDeleteField, onReorderField, readOnly = false })=>{
|
|
8
|
+
const t = useTranslation();
|
|
9
|
+
const properties = getSchemaProperties(schema);
|
|
10
|
+
const getValidSchemaType = (propSchema)=>{
|
|
11
|
+
if ("boolean" == typeof propSchema) return "object";
|
|
12
|
+
const type = propSchema.type;
|
|
13
|
+
if (Array.isArray(type)) return type[0] || "object";
|
|
14
|
+
return type || "object";
|
|
15
|
+
};
|
|
16
|
+
const handleNameChange = (oldName, newName)=>{
|
|
17
|
+
const property = properties.find((prop)=>prop.name === oldName);
|
|
18
|
+
if (!property) return;
|
|
19
|
+
const propSchemaObj = "boolean" == typeof property.schema ? {
|
|
20
|
+
type: "object"
|
|
21
|
+
} : property.schema;
|
|
22
|
+
onEditField(oldName, {
|
|
23
|
+
name: newName,
|
|
24
|
+
type: getValidSchemaType(property.schema),
|
|
25
|
+
description: propSchemaObj.description || "",
|
|
26
|
+
required: property.required,
|
|
27
|
+
default: propSchemaObj.default,
|
|
28
|
+
validation: propSchemaObj
|
|
29
|
+
});
|
|
30
|
+
};
|
|
31
|
+
const handleRequiredChange = (name, required)=>{
|
|
32
|
+
const property = properties.find((prop)=>prop.name === name);
|
|
33
|
+
if (!property) return;
|
|
34
|
+
const propSchemaObj = "boolean" == typeof property.schema ? {
|
|
35
|
+
type: "object"
|
|
36
|
+
} : property.schema;
|
|
37
|
+
onEditField(name, {
|
|
38
|
+
name,
|
|
39
|
+
type: getValidSchemaType(property.schema),
|
|
40
|
+
description: propSchemaObj.description || "",
|
|
41
|
+
required,
|
|
42
|
+
default: propSchemaObj.default,
|
|
43
|
+
validation: propSchemaObj
|
|
44
|
+
});
|
|
45
|
+
};
|
|
46
|
+
const handleSchemaChange = (name, updatedSchema)=>{
|
|
47
|
+
const property = properties.find((prop)=>prop.name === name);
|
|
48
|
+
if (!property) return;
|
|
49
|
+
const type = updatedSchema.type || "object";
|
|
50
|
+
const validType = Array.isArray(type) ? type[0] || "object" : type;
|
|
51
|
+
onEditField(name, {
|
|
52
|
+
name,
|
|
53
|
+
type: validType,
|
|
54
|
+
description: updatedSchema.description || "",
|
|
55
|
+
required: property.required,
|
|
56
|
+
default: updatedSchema.default,
|
|
57
|
+
validation: updatedSchema
|
|
58
|
+
});
|
|
59
|
+
};
|
|
60
|
+
const validationTree = useMemo(()=>buildValidationTree(schema, t), [
|
|
61
|
+
schema,
|
|
62
|
+
t
|
|
63
|
+
]);
|
|
64
|
+
const parentSchema = "boolean" == typeof schema ? void 0 : schema;
|
|
65
|
+
return /*#__PURE__*/ jsx("div", {
|
|
66
|
+
className: "space-y-2 animate-in",
|
|
67
|
+
children: properties.map((property, index)=>/*#__PURE__*/ jsx(SchemaPropertyEditor, {
|
|
68
|
+
name: property.name,
|
|
69
|
+
schema: property.schema,
|
|
70
|
+
required: property.required,
|
|
71
|
+
parentSchema: parentSchema,
|
|
72
|
+
validationNode: validationTree.children[property.name] ?? void 0,
|
|
73
|
+
onDelete: ()=>onDeleteField(property.name),
|
|
74
|
+
onNameChange: (newName)=>handleNameChange(property.name, newName),
|
|
75
|
+
onRequiredChange: (required)=>handleRequiredChange(property.name, required),
|
|
76
|
+
onSchemaChange: (schema)=>handleSchemaChange(property.name, schema),
|
|
77
|
+
onMoveUp: onReorderField && index > 0 ? ()=>onReorderField(property.name, "up") : void 0,
|
|
78
|
+
onMoveDown: onReorderField && index < properties.length - 1 ? ()=>onReorderField(property.name, "down") : void 0,
|
|
79
|
+
readOnly: readOnly
|
|
80
|
+
}, property.name))
|
|
81
|
+
});
|
|
82
|
+
};
|
|
83
|
+
const SchemaEditor_SchemaFieldList = SchemaFieldList;
|
|
84
|
+
export { SchemaEditor_SchemaFieldList as default };
|