@datenlotse/jsonjoy-builder 0.4.0 → 0.5.1
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/dist/components/SchemaEditor/AddFieldButton.js +59 -4
- package/dist/components/SchemaEditor/SchemaPropertyEditor.js +77 -2
- package/dist/components/SchemaEditor/SchemaVisualEditor.js +1 -0
- package/dist/components/SchemaEditor/types/ObjectEditor.js +1 -0
- package/dist/i18n/locales/de.js +6 -3
- package/dist/i18n/locales/en.js +3 -0
- package/dist/i18n/locales/es.js +3 -0
- package/dist/i18n/locales/fr.js +3 -0
- package/dist/i18n/locales/ru.js +3 -0
- package/dist/i18n/locales/uk.js +3 -0
- package/dist/i18n/locales/zh.js +3 -0
- package/dist/index.css +19 -1
- package/dist/index.d.ts +18 -0
- package/dist/lib/schemaEditor.js +3 -1
- package/dist/types/validation.js +91 -10
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { CirclePlus, HelpCircle, Info } from "lucide-react";
|
|
3
|
-
import { useId, useState } from "react";
|
|
3
|
+
import { useEffect, useId, useState } from "react";
|
|
4
4
|
import { Badge } from "../ui/badge.js";
|
|
5
5
|
import { Button } from "../ui/button.js";
|
|
6
6
|
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "../ui/dialog.js";
|
|
@@ -8,30 +8,64 @@ import { Input } from "../ui/input.js";
|
|
|
8
8
|
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "../ui/tooltip.js";
|
|
9
9
|
import { useTranslation } from "../../hooks/use-translation.js";
|
|
10
10
|
import SchemaTypeSelector from "./SchemaTypeSelector.js";
|
|
11
|
-
|
|
11
|
+
import TypeEditor from "./TypeEditor.js";
|
|
12
|
+
const ENUM_TYPES = [
|
|
13
|
+
"string",
|
|
14
|
+
"number",
|
|
15
|
+
"integer"
|
|
16
|
+
];
|
|
17
|
+
function createEmptyDraftSchema(type) {
|
|
18
|
+
return {
|
|
19
|
+
type
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
const AddFieldButton = ({ parentSchema, onAddField, variant = "primary" })=>{
|
|
12
23
|
const [dialogOpen, setDialogOpen] = useState(false);
|
|
13
24
|
const [fieldName, setFieldName] = useState("");
|
|
14
25
|
const [fieldType, setFieldType] = useState("string");
|
|
15
26
|
const [fieldDesc, setFieldDesc] = useState("");
|
|
16
27
|
const [fieldRequired, setFieldRequired] = useState(false);
|
|
28
|
+
const [draftSchema, setDraftSchema] = useState(()=>createEmptyDraftSchema("string"));
|
|
17
29
|
const fieldNameId = useId();
|
|
18
30
|
const fieldDescId = useId();
|
|
19
31
|
const fieldRequiredId = useId();
|
|
20
32
|
const fieldTypeId = useId();
|
|
21
33
|
const t = useTranslation();
|
|
34
|
+
useEffect(()=>{
|
|
35
|
+
setDraftSchema((prev)=>{
|
|
36
|
+
const nextType = fieldType;
|
|
37
|
+
const prevType = prev.type;
|
|
38
|
+
if (prevType === nextType) return prev;
|
|
39
|
+
return createEmptyDraftSchema(nextType);
|
|
40
|
+
});
|
|
41
|
+
}, [
|
|
42
|
+
fieldType
|
|
43
|
+
]);
|
|
44
|
+
useEffect(()=>{
|
|
45
|
+
if (dialogOpen) setDraftSchema(createEmptyDraftSchema(fieldType));
|
|
46
|
+
}, [
|
|
47
|
+
dialogOpen
|
|
48
|
+
]);
|
|
22
49
|
const handleSubmit = (e)=>{
|
|
23
50
|
e.preventDefault();
|
|
24
51
|
if (!fieldName.trim()) return;
|
|
52
|
+
const validation = ENUM_TYPES.includes(fieldType) && Object.keys(draftSchema).length > 1 ? {
|
|
53
|
+
...draftSchema,
|
|
54
|
+
type: fieldType
|
|
55
|
+
} : void 0;
|
|
25
56
|
onAddField({
|
|
26
|
-
name: fieldName,
|
|
57
|
+
name: fieldName.trim(),
|
|
27
58
|
type: fieldType,
|
|
28
59
|
description: fieldDesc,
|
|
29
|
-
required: fieldRequired
|
|
60
|
+
required: fieldRequired,
|
|
61
|
+
default: draftSchema.default,
|
|
62
|
+
validation
|
|
30
63
|
});
|
|
31
64
|
setFieldName("");
|
|
32
65
|
setFieldType("string");
|
|
33
66
|
setFieldDesc("");
|
|
34
67
|
setFieldRequired(false);
|
|
68
|
+
setDraftSchema(createEmptyDraftSchema("string"));
|
|
35
69
|
setDialogOpen(false);
|
|
36
70
|
};
|
|
37
71
|
return /*#__PURE__*/ jsxs(Fragment, {
|
|
@@ -283,6 +317,27 @@ const AddFieldButton = ({ onAddField, variant = "primary" })=>{
|
|
|
283
317
|
})
|
|
284
318
|
]
|
|
285
319
|
}),
|
|
320
|
+
ENUM_TYPES.includes(fieldType) && /*#__PURE__*/ jsxs("details", {
|
|
321
|
+
className: "group rounded-lg border bg-muted/30",
|
|
322
|
+
children: [
|
|
323
|
+
/*#__PURE__*/ jsx("summary", {
|
|
324
|
+
className: "cursor-pointer list-none px-4 py-3 text-sm font-medium",
|
|
325
|
+
children: t.stringAllowedValuesEnumLabel
|
|
326
|
+
}),
|
|
327
|
+
/*#__PURE__*/ jsx("div", {
|
|
328
|
+
className: "border-t px-4 pb-4 pt-2",
|
|
329
|
+
children: /*#__PURE__*/ jsx(TypeEditor, {
|
|
330
|
+
schema: draftSchema,
|
|
331
|
+
readOnly: false,
|
|
332
|
+
parentSchema: parentSchema,
|
|
333
|
+
propertyName: fieldName.trim() || void 0,
|
|
334
|
+
validationNode: void 0,
|
|
335
|
+
onChange: setDraftSchema,
|
|
336
|
+
depth: 1
|
|
337
|
+
})
|
|
338
|
+
})
|
|
339
|
+
]
|
|
340
|
+
}),
|
|
286
341
|
/*#__PURE__*/ jsxs(DialogFooter, {
|
|
287
342
|
className: "mt-6 gap-2 flex-wrap",
|
|
288
343
|
children: [
|
|
@@ -2,9 +2,10 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { ChevronDown, ChevronRight, ChevronUp, X } from "lucide-react";
|
|
3
3
|
import { useEffect, useMemo, useState } from "react";
|
|
4
4
|
import { Input } from "../ui/input.js";
|
|
5
|
+
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "../ui/select.js";
|
|
5
6
|
import { useTranslation } from "../../hooks/use-translation.js";
|
|
6
7
|
import { cn } from "../../lib/utils.js";
|
|
7
|
-
import { asObjectSchema, getSchemaDescription, withObjectSchema } from "../../types/jsonSchema.js";
|
|
8
|
+
import { asObjectSchema, getSchemaDescription, isBooleanSchema, withObjectSchema } from "../../types/jsonSchema.js";
|
|
8
9
|
import { Badge } from "../ui/badge.js";
|
|
9
10
|
import TypeDropdown from "./TypeDropdown.js";
|
|
10
11
|
import TypeEditor from "./TypeEditor.js";
|
|
@@ -23,6 +24,33 @@ const SchemaPropertyEditor = ({ name, schema, required, readOnly = false, parent
|
|
|
23
24
|
schema
|
|
24
25
|
]);
|
|
25
26
|
const [tempDefault, setTempDefault] = useState(defaultValue);
|
|
27
|
+
const defaultValueOptions = useMemo(()=>{
|
|
28
|
+
if ("string" !== type && "number" !== type && "integer" !== type) return null;
|
|
29
|
+
const objSchema = asObjectSchema(schema);
|
|
30
|
+
const enumValues = objSchema.enum;
|
|
31
|
+
const dependentEnum = objSchema.$dependentEnum;
|
|
32
|
+
if (Array.isArray(enumValues) && enumValues.length > 0) return enumValues.map((v)=>String(v));
|
|
33
|
+
if (dependentEnum && parentSchema) {
|
|
34
|
+
const controllingPropertyName = dependentEnum.property;
|
|
35
|
+
const controllingPropertySchema = parentSchema.properties?.[controllingPropertyName];
|
|
36
|
+
if (controllingPropertySchema && "object" == typeof controllingPropertySchema && !isBooleanSchema(controllingPropertySchema)) {
|
|
37
|
+
const controllingDefault = controllingPropertySchema.default;
|
|
38
|
+
if (void 0 !== controllingDefault) {
|
|
39
|
+
const ctrlDefaultStr = String(controllingDefault);
|
|
40
|
+
const allowedValues = dependentEnum.values[ctrlDefaultStr];
|
|
41
|
+
if (Array.isArray(allowedValues) && allowedValues.length > 0) return allowedValues.map((v)=>String(v));
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return null;
|
|
46
|
+
}, [
|
|
47
|
+
schema,
|
|
48
|
+
type,
|
|
49
|
+
parentSchema
|
|
50
|
+
]);
|
|
51
|
+
const defaultError = useMemo(()=>validationNode?.validation.errors?.find((err)=>"default" === err.path[0])?.message, [
|
|
52
|
+
validationNode
|
|
53
|
+
]);
|
|
26
54
|
useEffect(()=>{
|
|
27
55
|
setTempName(name);
|
|
28
56
|
setTempDesc(getSchemaDescription(schema));
|
|
@@ -78,6 +106,26 @@ const SchemaPropertyEditor = ({ name, schema, required, readOnly = false, parent
|
|
|
78
106
|
});
|
|
79
107
|
}
|
|
80
108
|
};
|
|
109
|
+
const handleDefaultSelectChange = (value)=>{
|
|
110
|
+
const objSchema = asObjectSchema(schema);
|
|
111
|
+
const currentDefault = objSchema.default;
|
|
112
|
+
if ("__none__" === value || "" === value) {
|
|
113
|
+
if (void 0 !== currentDefault) {
|
|
114
|
+
const { default: _, ...rest } = objSchema;
|
|
115
|
+
onSchemaChange(rest);
|
|
116
|
+
}
|
|
117
|
+
} else {
|
|
118
|
+
let parsedValue = value;
|
|
119
|
+
if ("number" === type || "integer" === type) {
|
|
120
|
+
parsedValue = Number(value);
|
|
121
|
+
if (Number.isNaN(parsedValue)) parsedValue = value;
|
|
122
|
+
}
|
|
123
|
+
if (JSON.stringify(currentDefault) !== JSON.stringify(parsedValue)) onSchemaChange({
|
|
124
|
+
...objSchema,
|
|
125
|
+
default: parsedValue
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
};
|
|
81
129
|
return /*#__PURE__*/ jsxs("div", {
|
|
82
130
|
className: cn("mb-2 animate-in rounded-lg border transition-all duration-200", depth > 0 && "ml-0 sm:ml-4 border-l border-l-border/40"),
|
|
83
131
|
children: [
|
|
@@ -221,13 +269,40 @@ const SchemaPropertyEditor = ({ name, schema, required, readOnly = false, parent
|
|
|
221
269
|
className: "text-xs font-medium text-muted-foreground",
|
|
222
270
|
children: t.propertyDefaultLabel
|
|
223
271
|
}),
|
|
224
|
-
/*#__PURE__*/
|
|
272
|
+
defaultValueOptions && defaultValueOptions.length > 0 ? /*#__PURE__*/ jsxs(Select, {
|
|
273
|
+
value: "" !== defaultValue && defaultValueOptions.includes(defaultValue) ? defaultValue : "__none__",
|
|
274
|
+
onValueChange: handleDefaultSelectChange,
|
|
275
|
+
children: [
|
|
276
|
+
/*#__PURE__*/ jsx(SelectTrigger, {
|
|
277
|
+
className: "h-8 text-sm",
|
|
278
|
+
children: /*#__PURE__*/ jsx(SelectValue, {
|
|
279
|
+
placeholder: t.propertyDefaultPlaceholder
|
|
280
|
+
})
|
|
281
|
+
}),
|
|
282
|
+
/*#__PURE__*/ jsxs(SelectContent, {
|
|
283
|
+
children: [
|
|
284
|
+
/*#__PURE__*/ jsx(SelectItem, {
|
|
285
|
+
value: "__none__",
|
|
286
|
+
children: t.propertyDefaultNone
|
|
287
|
+
}),
|
|
288
|
+
defaultValueOptions.map((option)=>/*#__PURE__*/ jsx(SelectItem, {
|
|
289
|
+
value: option,
|
|
290
|
+
children: option
|
|
291
|
+
}, option))
|
|
292
|
+
]
|
|
293
|
+
})
|
|
294
|
+
]
|
|
295
|
+
}) : /*#__PURE__*/ jsx(Input, {
|
|
225
296
|
value: tempDefault,
|
|
226
297
|
onChange: (e)=>setTempDefault(e.target.value),
|
|
227
298
|
onBlur: handleDefaultSubmit,
|
|
228
299
|
onKeyDown: (e)=>"Enter" === e.key && handleDefaultSubmit(),
|
|
229
300
|
placeholder: t.propertyDefaultPlaceholder,
|
|
230
301
|
className: "h-8 text-sm"
|
|
302
|
+
}),
|
|
303
|
+
defaultError && /*#__PURE__*/ jsx("div", {
|
|
304
|
+
className: "text-xs text-destructive italic",
|
|
305
|
+
children: defaultError
|
|
231
306
|
})
|
|
232
307
|
]
|
|
233
308
|
}),
|
|
@@ -44,6 +44,7 @@ const SchemaVisualEditor = ({ schema, onChange, readOnly = false })=>{
|
|
|
44
44
|
!readOnly && /*#__PURE__*/ jsx("div", {
|
|
45
45
|
className: "mb-6 shrink-0",
|
|
46
46
|
children: /*#__PURE__*/ jsx(AddFieldButton, {
|
|
47
|
+
parentSchema: asObjectSchema(schema),
|
|
47
48
|
onAddField: handleAddField
|
|
48
49
|
})
|
|
49
50
|
}),
|
|
@@ -79,6 +79,7 @@ const ObjectEditor = ({ schema, validationNode, onChange, depth = 0, readOnly =
|
|
|
79
79
|
!readOnly && /*#__PURE__*/ jsx("div", {
|
|
80
80
|
className: "mt-4",
|
|
81
81
|
children: /*#__PURE__*/ jsx(AddFieldButton, {
|
|
82
|
+
parentSchema: normalizedSchema,
|
|
82
83
|
onAddField: handleAddProperty,
|
|
83
84
|
variant: "secondary"
|
|
84
85
|
})
|
package/dist/i18n/locales/de.js
CHANGED
|
@@ -30,7 +30,7 @@ const de = {
|
|
|
30
30
|
fieldTypeBooleanDescription: "Für Wahr/Falsch-Werte",
|
|
31
31
|
fieldTypeObjectLabel: "Gruppe",
|
|
32
32
|
fieldTypeObjectDescription: "Zum Gruppieren verwandter Felder",
|
|
33
|
-
fieldTypeArrayLabel: "
|
|
33
|
+
fieldTypeArrayLabel: "Mehrfach-Auswahl",
|
|
34
34
|
fieldTypeArrayDescription: "Für Sammlungen von Elementen",
|
|
35
35
|
propertyDescriptionPlaceholder: "Beschreibung hinzufügen...",
|
|
36
36
|
propertyDescriptionButton: "Beschreibung hinzufügen...",
|
|
@@ -41,6 +41,9 @@ const de = {
|
|
|
41
41
|
propertyMoveDown: "Feld nach unten verschieben",
|
|
42
42
|
propertyDefaultLabel: "Standardwert",
|
|
43
43
|
propertyDefaultPlaceholder: "Standardwert eingeben...",
|
|
44
|
+
propertyDefaultMustBeInEnum: "Der Standardwert muss einer der erlaubten Werte sein.",
|
|
45
|
+
propertyDefaultRequiresDependentDefault: "Ein Standardwert kann nur gesetzt werden, wenn die abhängige Eigenschaft einen Standardwert hat.",
|
|
46
|
+
propertyDefaultNone: "Kein Standardwert",
|
|
44
47
|
schemaEditorTitle: "JSON-Schema-Editor",
|
|
45
48
|
schemaEditorToggleFullscreen: "Vollbild umschalten",
|
|
46
49
|
schemaEditorEditModeVisual: "Visuell",
|
|
@@ -109,10 +112,10 @@ const de = {
|
|
|
109
112
|
whenPropertyEquals: "Wenn {property} = {value}",
|
|
110
113
|
stringFormatSelectPlaceholder: "Format auswählen",
|
|
111
114
|
stringValidationErrorLengthRange: "'Minimale Länge' darf nicht größer als 'Maximale Länge' sein.",
|
|
112
|
-
schemaTypeArray: "
|
|
115
|
+
schemaTypeArray: "Mehrfach-Auswahl",
|
|
113
116
|
schemaTypeBoolean: "Ja/Nein",
|
|
114
117
|
schemaTypeNumber: "Zahl",
|
|
115
|
-
schemaTypeObject: "
|
|
118
|
+
schemaTypeObject: "Gruppe",
|
|
116
119
|
schemaTypeString: "Text",
|
|
117
120
|
schemaTypeNull: "Leer",
|
|
118
121
|
inferrerTitle: "JSON-Schema ableiten",
|
package/dist/i18n/locales/en.js
CHANGED
|
@@ -41,6 +41,9 @@ const en = {
|
|
|
41
41
|
propertyMoveDown: "Move field down",
|
|
42
42
|
propertyDefaultLabel: "Default Value",
|
|
43
43
|
propertyDefaultPlaceholder: "Enter default value...",
|
|
44
|
+
propertyDefaultMustBeInEnum: "Default value must be one of the allowed values.",
|
|
45
|
+
propertyDefaultRequiresDependentDefault: "Default can only be set when the dependent property has a default.",
|
|
46
|
+
propertyDefaultNone: "No default",
|
|
44
47
|
schemaEditorTitle: "JSON Schema Editor",
|
|
45
48
|
schemaEditorToggleFullscreen: "Toggle fullscreen",
|
|
46
49
|
schemaEditorEditModeVisual: "Visual",
|
package/dist/i18n/locales/es.js
CHANGED
|
@@ -41,6 +41,9 @@ const es = {
|
|
|
41
41
|
propertyMoveDown: "Mover campo hacia abajo",
|
|
42
42
|
propertyDefaultLabel: "Valor por defecto",
|
|
43
43
|
propertyDefaultPlaceholder: "Ingresar valor por defecto...",
|
|
44
|
+
propertyDefaultMustBeInEnum: "El valor por defecto debe ser uno de los valores permitidos.",
|
|
45
|
+
propertyDefaultRequiresDependentDefault: "El valor por defecto solo puede establecerse cuando la propiedad dependiente tiene un valor por defecto.",
|
|
46
|
+
propertyDefaultNone: "Sin valor por defecto",
|
|
44
47
|
schemaEditorTitle: "Editor de JSON Schema",
|
|
45
48
|
schemaEditorToggleFullscreen: "Cambiar a pantalla completa",
|
|
46
49
|
schemaEditorEditModeVisual: "Visual",
|
package/dist/i18n/locales/fr.js
CHANGED
|
@@ -41,6 +41,9 @@ const fr = {
|
|
|
41
41
|
propertyMoveDown: "Déplacer le champ vers le bas",
|
|
42
42
|
propertyDefaultLabel: "Valeur par défaut",
|
|
43
43
|
propertyDefaultPlaceholder: "Entrer la valeur par défaut...",
|
|
44
|
+
propertyDefaultMustBeInEnum: "La valeur par défaut doit être l'une des valeurs autorisées.",
|
|
45
|
+
propertyDefaultRequiresDependentDefault: "La valeur par défaut ne peut être définie que lorsque la propriété dépendante a une valeur par défaut.",
|
|
46
|
+
propertyDefaultNone: "Aucune valeur par défaut",
|
|
44
47
|
schemaEditorTitle: "Éditeur de schéma JSON",
|
|
45
48
|
schemaEditorToggleFullscreen: "Basculer en plein écran",
|
|
46
49
|
schemaEditorEditModeVisual: "Visuel",
|
package/dist/i18n/locales/ru.js
CHANGED
|
@@ -41,6 +41,9 @@ const ru = {
|
|
|
41
41
|
propertyMoveDown: "Переместить поле вниз",
|
|
42
42
|
propertyDefaultLabel: "Значение по умолчанию",
|
|
43
43
|
propertyDefaultPlaceholder: "Введите значение по умолчанию...",
|
|
44
|
+
propertyDefaultMustBeInEnum: "Значение по умолчанию должно быть одним из разрешенных значений.",
|
|
45
|
+
propertyDefaultRequiresDependentDefault: "Значение по умолчанию может быть установлено только тогда, когда зависимое свойство имеет значение по умолчанию.",
|
|
46
|
+
propertyDefaultNone: "Нет значения по умолчанию",
|
|
44
47
|
schemaEditorTitle: "Редактор JSON схем",
|
|
45
48
|
schemaEditorToggleFullscreen: "Переключить полноэкранный режим",
|
|
46
49
|
schemaEditorEditModeVisual: "Визуальный",
|
package/dist/i18n/locales/uk.js
CHANGED
|
@@ -41,6 +41,9 @@ const uk = {
|
|
|
41
41
|
propertyMoveDown: "Перемістити поле вниз",
|
|
42
42
|
propertyDefaultLabel: "Значення за замовчуванням",
|
|
43
43
|
propertyDefaultPlaceholder: "Введіть значення за замовчуванням...",
|
|
44
|
+
propertyDefaultMustBeInEnum: "Значення за замовчуванням повинно бути одним з дозволених значень.",
|
|
45
|
+
propertyDefaultRequiresDependentDefault: "Значення за замовчуванням може бути встановлено лише тоді, коли залежна властивість має значення за замовчуванням.",
|
|
46
|
+
propertyDefaultNone: "Немає значення за замовчуванням",
|
|
44
47
|
schemaEditorTitle: "Редактор JSON-схем",
|
|
45
48
|
schemaEditorToggleFullscreen: "Перемкнути повноекранний режим",
|
|
46
49
|
schemaEditorEditModeVisual: "Візуальний",
|
package/dist/i18n/locales/zh.js
CHANGED
|
@@ -41,6 +41,9 @@ const zh = {
|
|
|
41
41
|
propertyMoveDown: "向下移动字段",
|
|
42
42
|
propertyDefaultLabel: "默认值",
|
|
43
43
|
propertyDefaultPlaceholder: "输入默认值...",
|
|
44
|
+
propertyDefaultMustBeInEnum: "默认值必须是允许的值之一。",
|
|
45
|
+
propertyDefaultRequiresDependentDefault: "只有在依赖属性具有默认值时才能设置默认值。",
|
|
46
|
+
propertyDefaultNone: "无默认值",
|
|
44
47
|
schemaEditorTitle: "JSON Schema 编辑器",
|
|
45
48
|
schemaEditorToggleFullscreen: "切换全屏",
|
|
46
49
|
schemaEditorEditModeVisual: "可视化",
|
package/dist/index.css
CHANGED
|
@@ -1356,6 +1356,10 @@
|
|
|
1356
1356
|
cursor: text;
|
|
1357
1357
|
}
|
|
1358
1358
|
|
|
1359
|
+
.jsonjoy .list-none, .jsonjoy.list-none {
|
|
1360
|
+
list-style-type: none;
|
|
1361
|
+
}
|
|
1362
|
+
|
|
1359
1363
|
.jsonjoy .grid-cols-1, .jsonjoy.grid-cols-1 {
|
|
1360
1364
|
grid-template-columns: repeat(1, minmax(0, 1fr));
|
|
1361
1365
|
}
|
|
@@ -1719,7 +1723,17 @@
|
|
|
1719
1723
|
background-color: var(--jsonjoy-color-green-50);
|
|
1720
1724
|
}
|
|
1721
1725
|
|
|
1722
|
-
.jsonjoy .bg-muted, .jsonjoy.bg-muted, .jsonjoy .bg-muted\/
|
|
1726
|
+
.jsonjoy .bg-muted, .jsonjoy.bg-muted, .jsonjoy .bg-muted\/30, .jsonjoy.bg-muted\/30 {
|
|
1727
|
+
background-color: var(--jsonjoy-color-muted);
|
|
1728
|
+
}
|
|
1729
|
+
|
|
1730
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
1731
|
+
.jsonjoy .bg-muted\/30, .jsonjoy.bg-muted\/30 {
|
|
1732
|
+
background-color: color-mix(in oklab, var(--jsonjoy-color-muted) 30%, transparent);
|
|
1733
|
+
}
|
|
1734
|
+
}
|
|
1735
|
+
|
|
1736
|
+
.jsonjoy .bg-muted\/40, .jsonjoy.bg-muted\/40 {
|
|
1723
1737
|
background-color: var(--jsonjoy-color-muted);
|
|
1724
1738
|
}
|
|
1725
1739
|
|
|
@@ -1968,6 +1982,10 @@
|
|
|
1968
1982
|
padding-bottom: calc(var(--jsonjoy-spacing) * 2);
|
|
1969
1983
|
}
|
|
1970
1984
|
|
|
1985
|
+
.jsonjoy .pb-4, .jsonjoy.pb-4 {
|
|
1986
|
+
padding-bottom: calc(var(--jsonjoy-spacing) * 4);
|
|
1987
|
+
}
|
|
1988
|
+
|
|
1971
1989
|
.jsonjoy .pb-24, .jsonjoy.pb-24 {
|
|
1972
1990
|
padding-bottom: calc(var(--jsonjoy-spacing) * 24);
|
|
1973
1991
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -400,6 +400,24 @@ export declare interface Translation {
|
|
|
400
400
|
* > Enter default value...
|
|
401
401
|
*/
|
|
402
402
|
readonly propertyDefaultPlaceholder: string;
|
|
403
|
+
/**
|
|
404
|
+
* The translation for the key `propertyDefaultMustBeInEnum`. English default is:
|
|
405
|
+
*
|
|
406
|
+
* > Default value must be one of the allowed values.
|
|
407
|
+
*/
|
|
408
|
+
readonly propertyDefaultMustBeInEnum: string;
|
|
409
|
+
/**
|
|
410
|
+
* The translation for the key `propertyDefaultRequiresDependentDefault`. English default is:
|
|
411
|
+
*
|
|
412
|
+
* > Default can only be set when the dependent property has a default.
|
|
413
|
+
*/
|
|
414
|
+
readonly propertyDefaultRequiresDependentDefault: string;
|
|
415
|
+
/**
|
|
416
|
+
* The translation for the key `propertyDefaultNone`. English default is:
|
|
417
|
+
*
|
|
418
|
+
* > No default
|
|
419
|
+
*/
|
|
420
|
+
readonly propertyDefaultNone: string;
|
|
403
421
|
/**
|
|
404
422
|
* The translation for the key `arrayNoConstraint`. English default is:
|
|
405
423
|
*
|
package/dist/lib/schemaEditor.js
CHANGED
|
@@ -129,7 +129,9 @@ function renameObjectProperty(schema, oldName, newName) {
|
|
|
129
129
|
const propertyOrder = newSchema.$propertyOrder || Object.keys(newSchema.properties);
|
|
130
130
|
for (const key of propertyOrder)if (key === oldName) newProperties[newName] = newSchema.properties[oldName];
|
|
131
131
|
else if (key in newSchema.properties) newProperties[key] = newSchema.properties[key];
|
|
132
|
-
for (const [key, value] of Object.entries(newSchema.properties))if (
|
|
132
|
+
for (const [key, value] of Object.entries(newSchema.properties))if (key !== oldName) {
|
|
133
|
+
if (!(key in newProperties)) newProperties[key] = value;
|
|
134
|
+
}
|
|
133
135
|
newSchema.properties = newProperties;
|
|
134
136
|
if (newSchema.required) newSchema.required = newSchema.required.map((field)=>field === oldName ? newName : field);
|
|
135
137
|
if (newSchema.$propertyOrder) newSchema.$propertyOrder = newSchema.$propertyOrder.map((name)=>name === oldName ? newName : name);
|
package/dist/types/validation.js
CHANGED
|
@@ -138,7 +138,75 @@ function validateSchemaByType(schema, type, t) {
|
|
|
138
138
|
errors: result.error.issues
|
|
139
139
|
};
|
|
140
140
|
}
|
|
141
|
-
function
|
|
141
|
+
function validateDefaultInEnum(schema, type, t, parentSchema) {
|
|
142
|
+
if ("string" !== type && "number" !== type && "integer" !== type) return null;
|
|
143
|
+
const defaultValue = schema.default;
|
|
144
|
+
if (void 0 === defaultValue) return null;
|
|
145
|
+
const enumValues = schema.enum;
|
|
146
|
+
if (Array.isArray(enumValues) && enumValues.length > 0) {
|
|
147
|
+
const isInEnum = enumValues.some((val)=>{
|
|
148
|
+
if ("number" === type || "integer" === type) return val === defaultValue || "number" == typeof val && "number" == typeof defaultValue && val === defaultValue;
|
|
149
|
+
return String(val) === String(defaultValue);
|
|
150
|
+
});
|
|
151
|
+
if (!isInEnum) return {
|
|
152
|
+
code: "custom",
|
|
153
|
+
message: t.propertyDefaultMustBeInEnum,
|
|
154
|
+
path: [
|
|
155
|
+
"default"
|
|
156
|
+
]
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
const dependentEnum = schema.$dependentEnum;
|
|
160
|
+
if (dependentEnum) {
|
|
161
|
+
const controllingPropertyName = dependentEnum.property;
|
|
162
|
+
const dependentValuesMap = dependentEnum.values;
|
|
163
|
+
if (!parentSchema) return {
|
|
164
|
+
code: "custom",
|
|
165
|
+
message: t.propertyDefaultRequiresDependentDefault,
|
|
166
|
+
path: [
|
|
167
|
+
"default"
|
|
168
|
+
]
|
|
169
|
+
};
|
|
170
|
+
const controllingPropertySchema = parentSchema.properties?.[controllingPropertyName];
|
|
171
|
+
if (!controllingPropertySchema || "object" != typeof controllingPropertySchema) return {
|
|
172
|
+
code: "custom",
|
|
173
|
+
message: t.propertyDefaultRequiresDependentDefault,
|
|
174
|
+
path: [
|
|
175
|
+
"default"
|
|
176
|
+
]
|
|
177
|
+
};
|
|
178
|
+
const controllingDefault = controllingPropertySchema.default;
|
|
179
|
+
if (void 0 === controllingDefault) return {
|
|
180
|
+
code: "custom",
|
|
181
|
+
message: t.propertyDefaultRequiresDependentDefault,
|
|
182
|
+
path: [
|
|
183
|
+
"default"
|
|
184
|
+
]
|
|
185
|
+
};
|
|
186
|
+
const ctrlDefaultStr = String(controllingDefault);
|
|
187
|
+
const allowedValues = dependentValuesMap[ctrlDefaultStr];
|
|
188
|
+
if (!Array.isArray(allowedValues) || 0 === allowedValues.length) return {
|
|
189
|
+
code: "custom",
|
|
190
|
+
message: t.propertyDefaultRequiresDependentDefault,
|
|
191
|
+
path: [
|
|
192
|
+
"default"
|
|
193
|
+
]
|
|
194
|
+
};
|
|
195
|
+
const isInAllowedValues = allowedValues.some((val)=>{
|
|
196
|
+
if ("number" === type || "integer" === type) return val === defaultValue || "number" == typeof val && "number" == typeof defaultValue && val === defaultValue;
|
|
197
|
+
return String(val) === String(defaultValue);
|
|
198
|
+
});
|
|
199
|
+
if (!isInAllowedValues) return {
|
|
200
|
+
code: "custom",
|
|
201
|
+
message: t.propertyDefaultMustBeInEnum,
|
|
202
|
+
path: [
|
|
203
|
+
"default"
|
|
204
|
+
]
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
return null;
|
|
208
|
+
}
|
|
209
|
+
function buildValidationTree(schema, t, parentSchema) {
|
|
142
210
|
const deriveType = (sch)=>{
|
|
143
211
|
if (!sch || "object" != typeof sch) return;
|
|
144
212
|
const declared = sch.type;
|
|
@@ -169,20 +237,33 @@ function buildValidationTree(schema, t) {
|
|
|
169
237
|
const sch = schema;
|
|
170
238
|
const currentType = deriveType(sch);
|
|
171
239
|
const validation = validateSchemaByType(schema, currentType, t);
|
|
240
|
+
if ("string" === currentType || "number" === currentType || "integer" === currentType) {
|
|
241
|
+
const defaultError = validateDefaultInEnum(schema, currentType, t, parentSchema);
|
|
242
|
+
if (defaultError) if (validation.success) {
|
|
243
|
+
validation.success = false;
|
|
244
|
+
validation.errors = [
|
|
245
|
+
defaultError
|
|
246
|
+
];
|
|
247
|
+
} else validation.errors = [
|
|
248
|
+
...validation.errors || [],
|
|
249
|
+
defaultError
|
|
250
|
+
];
|
|
251
|
+
}
|
|
172
252
|
const children = {};
|
|
173
253
|
if ("object" === currentType) {
|
|
254
|
+
const currentObjectSchema = schema;
|
|
174
255
|
const properties = sch.properties;
|
|
175
|
-
if (properties && "object" == typeof properties) for (const [propName, propSchema] of Object.entries(properties))children[propName] = buildValidationTree(propSchema, t);
|
|
176
|
-
if (sch.patternProperties && "object" == typeof sch.patternProperties) for (const [patternName, patternSchema] of Object.entries(sch.patternProperties))children[`pattern:${patternName}`] = buildValidationTree(patternSchema, t);
|
|
256
|
+
if (properties && "object" == typeof properties) for (const [propName, propSchema] of Object.entries(properties))children[propName] = buildValidationTree(propSchema, t, currentObjectSchema);
|
|
257
|
+
if (sch.patternProperties && "object" == typeof sch.patternProperties) for (const [patternName, patternSchema] of Object.entries(sch.patternProperties))children[`pattern:${patternName}`] = buildValidationTree(patternSchema, t, currentObjectSchema);
|
|
177
258
|
}
|
|
178
259
|
if ("array" === currentType) {
|
|
179
260
|
const items = sch.items;
|
|
180
261
|
if (Array.isArray(items)) items.forEach((it, idx)=>{
|
|
181
|
-
children[`items[${idx}]`] = buildValidationTree(it, t);
|
|
262
|
+
children[`items[${idx}]`] = buildValidationTree(it, t, parentSchema);
|
|
182
263
|
});
|
|
183
|
-
else if (items) children.items = buildValidationTree(items, t);
|
|
264
|
+
else if (items) children.items = buildValidationTree(items, t, parentSchema);
|
|
184
265
|
if (Array.isArray(sch.prefixItems)) sch.prefixItems.forEach((it, idx)=>{
|
|
185
|
-
children[`prefixItems[${idx}]`] = buildValidationTree(it, t);
|
|
266
|
+
children[`prefixItems[${idx}]`] = buildValidationTree(it, t, parentSchema);
|
|
186
267
|
});
|
|
187
268
|
}
|
|
188
269
|
const combinators = [
|
|
@@ -196,13 +277,13 @@ function buildValidationTree(schema, t) {
|
|
|
196
277
|
children[[
|
|
197
278
|
comb,
|
|
198
279
|
idx
|
|
199
|
-
].join(":")] = buildValidationTree(subSchema, t);
|
|
280
|
+
].join(":")] = buildValidationTree(subSchema, t, parentSchema);
|
|
200
281
|
});
|
|
201
282
|
}
|
|
202
|
-
if (sch.not) children.not = buildValidationTree(sch.not, t);
|
|
203
|
-
if (sch.$defs && "object" == typeof sch.$defs) for (const [defName, defSchema] of Object.entries(sch.$defs))children[`$defs:${defName}`] = buildValidationTree(defSchema, t);
|
|
283
|
+
if (sch.not) children.not = buildValidationTree(sch.not, t, parentSchema);
|
|
284
|
+
if (sch.$defs && "object" == typeof sch.$defs) for (const [defName, defSchema] of Object.entries(sch.$defs))children[`$defs:${defName}`] = buildValidationTree(defSchema, t, parentSchema);
|
|
204
285
|
const definitions = sch.definitions;
|
|
205
|
-
if (definitions && "object" == typeof definitions) for (const [defName, defSchema] of Object.entries(definitions))children[`definitions:${defName}`] = buildValidationTree(defSchema, t);
|
|
286
|
+
if (definitions && "object" == typeof definitions) for (const [defName, defSchema] of Object.entries(definitions))children[`definitions:${defName}`] = buildValidationTree(defSchema, t, parentSchema);
|
|
206
287
|
const ownErrors = validation.success ? 0 : validation.errors?.length ?? 0;
|
|
207
288
|
const childrenErrors = Object.values(children).reduce((sum, child)=>sum + child.cumulativeChildrenErrors, 0);
|
|
208
289
|
return {
|