@webiny/app-admin 6.3.0-beta.2 → 6.3.0-beta.3
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/base/Base/DefaultFieldRenderers.js +69 -5
- package/base/Base/DefaultFieldRenderers.js.map +1 -1
- package/base/Base/DefaultLayoutRenderers.js +5 -1
- package/base/Base/DefaultLayoutRenderers.js.map +1 -1
- package/base/Base/FieldRenderers/CheckboxesRenderer.d.ts +13 -0
- package/base/Base/FieldRenderers/CheckboxesRenderer.js +28 -0
- package/base/Base/FieldRenderers/CheckboxesRenderer.js.map +1 -0
- package/base/Base/FieldRenderers/CodeEditorRenderer.d.ts +15 -0
- package/base/Base/FieldRenderers/CodeEditorRenderer.js +17 -0
- package/base/Base/FieldRenderers/CodeEditorRenderer.js.map +1 -0
- package/base/Base/FieldRenderers/DateTimeInputsRenderer.d.ts +17 -0
- package/base/Base/FieldRenderers/DateTimeInputsRenderer.js +66 -0
- package/base/Base/FieldRenderers/DateTimeInputsRenderer.js.map +1 -0
- package/base/Base/FieldRenderers/DateTimeRenderer.d.ts +21 -0
- package/base/Base/FieldRenderers/DateTimeRenderer.js +46 -0
- package/base/Base/FieldRenderers/DateTimeRenderer.js.map +1 -0
- package/base/Base/FieldRenderers/FilePickerRenderer.d.ts +12 -0
- package/base/Base/FieldRenderers/FilePickerRenderer.js +47 -0
- package/base/Base/FieldRenderers/FilePickerRenderer.js.map +1 -0
- package/base/Base/FieldRenderers/FileUrlPickerRenderer.d.ts +12 -0
- package/base/Base/FieldRenderers/FileUrlPickerRenderer.js +25 -0
- package/base/Base/FieldRenderers/FileUrlPickerRenderer.js.map +1 -0
- package/base/Base/FieldRenderers/HiddenRenderer.d.ts +12 -0
- package/base/Base/FieldRenderers/HiddenRenderer.js +5 -0
- package/base/Base/FieldRenderers/HiddenRenderer.js.map +1 -0
- package/base/Base/FieldRenderers/HorizontalTabsRenderer.d.ts +5 -0
- package/base/Base/FieldRenderers/HorizontalTabsRenderer.js +27 -0
- package/base/Base/FieldRenderers/HorizontalTabsRenderer.js.map +1 -0
- package/base/Base/FieldRenderers/InputRenderer.d.ts +4 -7
- package/base/Base/FieldRenderers/InputRenderer.js +2 -2
- package/base/Base/FieldRenderers/InputRenderer.js.map +1 -1
- package/base/Base/FieldRenderers/NumberInputRenderer.d.ts +12 -0
- package/base/Base/FieldRenderers/NumberInputRenderer.js +23 -0
- package/base/Base/FieldRenderers/NumberInputRenderer.js.map +1 -0
- package/base/Base/FieldRenderers/NumberInputsRenderer.d.ts +14 -0
- package/base/Base/FieldRenderers/NumberInputsRenderer.js +49 -0
- package/base/Base/FieldRenderers/NumberInputsRenderer.js.map +1 -0
- package/base/Base/FieldRenderers/ObjectRenderer/DynamicZoneRenderer.d.ts +14 -0
- package/base/Base/FieldRenderers/ObjectRenderer/DynamicZoneRenderer.js +20 -0
- package/base/Base/FieldRenderers/ObjectRenderer/DynamicZoneRenderer.js.map +1 -0
- package/base/Base/FieldRenderers/ObjectRenderer/KeyValueTagsRenderer.d.ts +14 -0
- package/base/Base/FieldRenderers/ObjectRenderer/KeyValueTagsRenderer.js +65 -0
- package/base/Base/FieldRenderers/ObjectRenderer/KeyValueTagsRenderer.js.map +1 -0
- package/base/Base/FieldRenderers/ObjectRenderer/MultiValueDynamicZone.d.ts +10 -0
- package/base/Base/FieldRenderers/ObjectRenderer/MultiValueDynamicZone.js +109 -0
- package/base/Base/FieldRenderers/ObjectRenderer/MultiValueDynamicZone.js.map +1 -0
- package/base/Base/FieldRenderers/ObjectRenderer/ObjectAccordionMultipleRenderer.d.ts +17 -0
- package/base/Base/FieldRenderers/ObjectRenderer/ObjectAccordionMultipleRenderer.js +55 -0
- package/base/Base/FieldRenderers/ObjectRenderer/ObjectAccordionMultipleRenderer.js.map +1 -0
- package/base/Base/FieldRenderers/ObjectRenderer/ObjectFieldComponents.d.ts +7 -3
- package/base/Base/FieldRenderers/ObjectRenderer/ObjectFieldComponents.js +15 -19
- package/base/Base/FieldRenderers/ObjectRenderer/ObjectFieldComponents.js.map +1 -1
- package/base/Base/FieldRenderers/ObjectRenderer/ObjectRenderer.d.ts +5 -8
- package/base/Base/FieldRenderers/ObjectRenderer/ObjectRenderer.js +7 -50
- package/base/Base/FieldRenderers/ObjectRenderer/ObjectRenderer.js.map +1 -1
- package/base/Base/FieldRenderers/ObjectRenderer/SingleValueDynamicZone.d.ts +10 -0
- package/base/Base/FieldRenderers/ObjectRenderer/SingleValueDynamicZone.js +64 -0
- package/base/Base/FieldRenderers/ObjectRenderer/SingleValueDynamicZone.js.map +1 -0
- package/base/Base/FieldRenderers/ObjectRenderer/TemplatePicker.d.ts +10 -0
- package/base/Base/FieldRenderers/ObjectRenderer/TemplatePicker.js +85 -0
- package/base/Base/FieldRenderers/ObjectRenderer/TemplatePicker.js.map +1 -0
- package/base/Base/FieldRenderers/PassthroughRenderer.d.ts +3 -6
- package/base/Base/FieldRenderers/PassthroughRenderer.js +9 -23
- package/base/Base/FieldRenderers/PassthroughRenderer.js.map +1 -1
- package/base/Base/FieldRenderers/RadioButtonsRenderer.d.ts +13 -0
- package/base/Base/FieldRenderers/RadioButtonsRenderer.js +27 -0
- package/base/Base/FieldRenderers/RadioButtonsRenderer.js.map +1 -0
- package/base/Base/FieldRenderers/SelectRenderer.d.ts +6 -8
- package/base/Base/FieldRenderers/SelectRenderer.js +8 -5
- package/base/Base/FieldRenderers/SelectRenderer.js.map +1 -1
- package/base/Base/FieldRenderers/SwitchRenderer.d.ts +12 -0
- package/base/Base/FieldRenderers/SwitchRenderer.js +19 -0
- package/base/Base/FieldRenderers/SwitchRenderer.js.map +1 -0
- package/base/Base/FieldRenderers/TagsRenderer.d.ts +12 -0
- package/base/Base/FieldRenderers/TagsRenderer.js +21 -0
- package/base/Base/FieldRenderers/TagsRenderer.js.map +1 -0
- package/base/Base/FieldRenderers/TextInputsRenderer.d.ts +14 -0
- package/base/Base/FieldRenderers/TextInputsRenderer.js +48 -0
- package/base/Base/FieldRenderers/TextInputsRenderer.js.map +1 -0
- package/base/Base/FieldRenderers/TextareaRenderer.d.ts +3 -6
- package/base/Base/FieldRenderers/TextareaRenderer.js +3 -4
- package/base/Base/FieldRenderers/TextareaRenderer.js.map +1 -1
- package/base/Base/FieldRenderers/TextareasRenderer.d.ts +14 -0
- package/base/Base/FieldRenderers/TextareasRenderer.js +51 -0
- package/base/Base/FieldRenderers/TextareasRenderer.js.map +1 -0
- package/base/Base/FieldRenderers/VerticalTabsRenderer.js +2 -2
- package/base/Base/FieldRenderers/VerticalTabsRenderer.js.map +1 -1
- package/base/Base/Menus.js +5 -64
- package/base/Base/Menus.js.map +1 -1
- package/base/Base/RoutesConfig.js +6 -0
- package/base/Base/RoutesConfig.js.map +1 -1
- package/exports/admin/build-params.d.ts +2 -0
- package/exports/admin/build-params.js +3 -0
- package/exports/admin/build-params.js.map +1 -1
- package/exports/admin/form.d.ts +5 -0
- package/exports/admin/form.js +8 -0
- package/exports/admin/form.js.map +1 -1
- package/exports/admin/ui.d.ts +1 -0
- package/exports/admin/ui.js +1 -0
- package/exports/admin/ui.js.map +1 -1
- package/exports/admin.d.ts +3 -1
- package/exports/admin.js +3 -1
- package/exports/admin.js.map +1 -1
- package/features/formModel/ConditionRuleEvaluator.d.ts +9 -0
- package/features/formModel/ConditionRuleEvaluator.js +56 -0
- package/features/formModel/ConditionRuleEvaluator.js.map +1 -0
- package/features/formModel/Field.d.ts +50 -4
- package/features/formModel/Field.js +254 -35
- package/features/formModel/Field.js.map +1 -1
- package/features/formModel/FieldBuilder.d.ts +17 -35
- package/features/formModel/FieldBuilder.js +63 -100
- package/features/formModel/FieldBuilder.js.map +1 -1
- package/features/formModel/FieldBuilder.test.js +127 -13
- package/features/formModel/FieldBuilder.test.js.map +1 -1
- package/features/formModel/FieldBuilderRegistry.d.ts +4 -0
- package/features/formModel/FieldBuilderRegistry.js +31 -0
- package/features/formModel/FieldBuilderRegistry.js.map +1 -0
- package/features/formModel/FocusManager.d.ts +14 -0
- package/features/formModel/FocusManager.js +109 -0
- package/features/formModel/FocusManager.js.map +1 -0
- package/features/formModel/FormModel.d.ts +27 -31
- package/features/formModel/FormModel.js +210 -403
- package/features/formModel/FormModel.js.map +1 -1
- package/features/formModel/FormModel.test.js +2044 -193
- package/features/formModel/FormModel.test.js.map +1 -1
- package/features/formModel/FormModelFactory.d.ts +4 -2
- package/features/formModel/FormModelFactory.js +13 -3
- package/features/formModel/FormModelFactory.js.map +1 -1
- package/features/formModel/FormView.d.ts +2 -0
- package/features/formModel/FormView.js +44 -37
- package/features/formModel/FormView.js.map +1 -1
- package/features/formModel/LayoutBuilderFactory.d.ts +61 -0
- package/features/formModel/LayoutBuilderFactory.js +386 -0
- package/features/formModel/LayoutBuilderFactory.js.map +1 -0
- package/features/formModel/LayoutMutator.d.ts +11 -0
- package/features/formModel/LayoutMutator.js +136 -0
- package/features/formModel/LayoutMutator.js.map +1 -0
- package/features/formModel/LayoutResolver.d.ts +26 -0
- package/features/formModel/LayoutResolver.js +239 -0
- package/features/formModel/LayoutResolver.js.map +1 -0
- package/features/formModel/ObjectField.d.ts +55 -4
- package/features/formModel/ObjectField.js +499 -82
- package/features/formModel/ObjectField.js.map +1 -1
- package/features/formModel/Rules.test.d.ts +1 -0
- package/features/formModel/Rules.test.js +289 -0
- package/features/formModel/Rules.test.js.map +1 -0
- package/features/formModel/abstractions.d.ts +402 -52
- package/features/formModel/abstractions.js +55 -0
- package/features/formModel/abstractions.js.map +1 -1
- package/features/formModel/createFieldRenderer.d.ts +20 -0
- package/features/formModel/createFieldRenderer.js +15 -0
- package/features/formModel/createFieldRenderer.js.map +1 -0
- package/features/formModel/demo/FieldRenderersDemoPresenter.d.ts +18 -0
- package/features/formModel/demo/FieldRenderersDemoPresenter.js +225 -0
- package/features/formModel/demo/FieldRenderersDemoPresenter.js.map +1 -0
- package/features/formModel/demo/FormModelDemo.d.ts +4 -0
- package/features/formModel/demo/FormModelDemo.js +230 -0
- package/features/formModel/demo/FormModelDemo.js.map +1 -0
- package/features/formModel/demo/FormModelDemoPresenter.d.ts +22 -0
- package/features/formModel/demo/FormModelDemoPresenter.js +121 -0
- package/features/formModel/demo/FormModelDemoPresenter.js.map +1 -0
- package/features/formModel/demo/FormModelPhase11Presenter.d.ts +25 -0
- package/features/formModel/demo/FormModelPhase11Presenter.js +104 -0
- package/features/formModel/demo/FormModelPhase11Presenter.js.map +1 -0
- package/features/formModel/demo/FormModelPhase8c1Presenter.d.ts +23 -0
- package/features/formModel/demo/FormModelPhase8c1Presenter.js +62 -0
- package/features/formModel/demo/FormModelPhase8c1Presenter.js.map +1 -0
- package/features/formModel/feature.js +12 -0
- package/features/formModel/feature.js.map +1 -1
- package/features/formModel/fieldTypes/BooleanFieldType.d.ts +19 -0
- package/features/formModel/fieldTypes/BooleanFieldType.js +23 -0
- package/features/formModel/fieldTypes/BooleanFieldType.js.map +1 -0
- package/features/formModel/fieldTypes/DateTimeFieldType.d.ts +173 -0
- package/features/formModel/fieldTypes/DateTimeFieldType.js +369 -0
- package/features/formModel/fieldTypes/DateTimeFieldType.js.map +1 -0
- package/features/formModel/fieldTypes/FileFieldType.d.ts +18 -0
- package/features/formModel/fieldTypes/FileFieldType.js +20 -0
- package/features/formModel/fieldTypes/FileFieldType.js.map +1 -0
- package/features/formModel/fieldTypes/FileUrlFieldType.d.ts +18 -0
- package/features/formModel/fieldTypes/FileUrlFieldType.js +20 -0
- package/features/formModel/fieldTypes/FileUrlFieldType.js.map +1 -0
- package/features/formModel/fieldTypes/NumberFieldType.d.ts +19 -0
- package/features/formModel/fieldTypes/NumberFieldType.js +27 -0
- package/features/formModel/fieldTypes/NumberFieldType.js.map +1 -0
- package/features/formModel/fieldTypes/ObjectFieldType.d.ts +34 -0
- package/features/formModel/fieldTypes/ObjectFieldType.js +109 -0
- package/features/formModel/fieldTypes/ObjectFieldType.js.map +1 -0
- package/features/formModel/fieldTypes/TextFieldType.d.ts +18 -0
- package/features/formModel/fieldTypes/TextFieldType.js +20 -0
- package/features/formModel/fieldTypes/TextFieldType.js.map +1 -0
- package/features/formModel/fieldTypes/index.d.ts +7 -0
- package/features/formModel/fieldTypes/index.js +9 -0
- package/features/formModel/fieldTypes/index.js.map +1 -0
- package/features/formModel/index.d.ts +13 -4
- package/features/formModel/index.js +21 -2
- package/features/formModel/index.js.map +1 -1
- package/features/formModel/renderers.d.ts +15 -1
- package/features/formModel/renderers.js +15 -1
- package/features/formModel/renderers.js.map +1 -1
- package/features/tools/LexicalContext/LexicalContext.d.ts +14 -0
- package/features/tools/LexicalContext/LexicalContext.js +22 -0
- package/features/tools/LexicalContext/LexicalContext.js.map +1 -0
- package/features/tools/LexicalContext/abstractions.d.ts +11 -0
- package/features/tools/LexicalContext/abstractions.js +4 -0
- package/features/tools/LexicalContext/abstractions.js.map +1 -0
- package/features/tools/LexicalContext/index.d.ts +2 -0
- package/features/tools/LexicalContext/index.js +3 -0
- package/features/tools/LexicalContext/index.js.map +1 -0
- package/features/tools/feature.js +2 -0
- package/features/tools/feature.js.map +1 -1
- package/features/tools/index.d.ts +1 -0
- package/features/tools/index.js +1 -0
- package/features/tools/index.js.map +1 -1
- package/index.d.ts +8 -1
- package/index.js +7 -0
- package/index.js.map +1 -1
- package/package.json +30 -24
- package/presentation/installation/components/SystemInstaller/steps/AdminUserStep/createPasswordValidator.js +1 -1
- package/presentation/installation/components/SystemInstaller/steps/AdminUserStep/createPasswordValidator.js.map +1 -1
- package/presentation/lexicalContext/useLexicalContext.d.ts +3 -0
- package/presentation/lexicalContext/useLexicalContext.js +14 -0
- package/presentation/lexicalContext/useLexicalContext.js.map +1 -0
- package/presentation/textToLexicalTool/TextToLexicalTool.d.ts +3 -0
- package/presentation/textToLexicalTool/TextToLexicalTool.js +6 -2
- package/presentation/textToLexicalTool/TextToLexicalTool.js.map +1 -1
- package/presentation/textToLexicalTool/textToLexicalState.d.ts +2 -1
- package/presentation/textToLexicalTool/textToLexicalState.js +15 -3
- package/presentation/textToLexicalTool/textToLexicalState.js.map +1 -1
- package/routes.d.ts +1 -0
- package/routes.js +4 -0
- package/routes.js.map +1 -1
- package/base/Base/FieldRenderers/ObjectRenderer/ObjectListFlatRenderer.d.ts +0 -21
- package/base/Base/FieldRenderers/ObjectRenderer/ObjectListFlatRenderer.js +0 -28
- package/base/Base/FieldRenderers/ObjectRenderer/ObjectListFlatRenderer.js.map +0 -1
|
@@ -1,35 +1,42 @@
|
|
|
1
1
|
import { makeAutoObservable, runInAction, toJS } from "mobx";
|
|
2
2
|
import { Field } from "./Field.js";
|
|
3
|
-
|
|
3
|
+
import { createTemplateBuilder } from "./fieldTypes/ObjectFieldType.js";
|
|
4
|
+
/** Reserved key used as the template discriminator in templated object data. */
|
|
5
|
+
export const TEMPLATE_DISCRIMINATOR = "_templateId";
|
|
6
|
+
function createChildFields(childBuilders, form, parentPath) {
|
|
4
7
|
const children = new Map();
|
|
5
8
|
for (const [name, builder] of Object.entries(childBuilders)) {
|
|
6
9
|
const config = builder.build(name);
|
|
7
|
-
const field = createFieldFromConfig(config, form);
|
|
10
|
+
const field = createFieldFromConfig(config, form, parentPath);
|
|
8
11
|
children.set(name, field);
|
|
9
12
|
}
|
|
10
13
|
return children;
|
|
11
14
|
}
|
|
12
|
-
function createFieldFromConfig(config, form) {
|
|
15
|
+
function createFieldFromConfig(config, form, parentPath) {
|
|
13
16
|
if (config.childBuilders) {
|
|
14
17
|
const objField = new ObjectField(config);
|
|
15
18
|
if (form) {
|
|
16
|
-
objField.setForm(form);
|
|
19
|
+
objField.setForm(form, parentPath);
|
|
17
20
|
}
|
|
18
21
|
return objField;
|
|
19
22
|
}
|
|
20
23
|
const field = new Field(config);
|
|
21
24
|
if (form) {
|
|
22
|
-
field.setForm(form);
|
|
25
|
+
field.setForm(form, parentPath);
|
|
23
26
|
}
|
|
24
27
|
return field;
|
|
25
28
|
}
|
|
26
|
-
function hydrateChildren(children, data) {
|
|
29
|
+
function hydrateChildren(children, data, options) {
|
|
27
30
|
if (!data) {
|
|
28
31
|
return;
|
|
29
32
|
}
|
|
30
33
|
for (const [name, field] of children) {
|
|
31
34
|
if (name in data) {
|
|
32
|
-
field.
|
|
35
|
+
if (options?.clone && field.config.cloneValue) {
|
|
36
|
+
field.setValueSilent(field.config.cloneValue(data[name]));
|
|
37
|
+
} else {
|
|
38
|
+
field.setValueSilent(data[name]);
|
|
39
|
+
}
|
|
33
40
|
}
|
|
34
41
|
}
|
|
35
42
|
}
|
|
@@ -44,10 +51,10 @@ function getChildrenData(children) {
|
|
|
44
51
|
}
|
|
45
52
|
return data;
|
|
46
53
|
}
|
|
47
|
-
async function validateChildren(children) {
|
|
54
|
+
async function validateChildren(children, options) {
|
|
48
55
|
let allValid = true;
|
|
49
56
|
for (const [, field] of children) {
|
|
50
|
-
const valid = await field.validate();
|
|
57
|
+
const valid = await field.validate(options);
|
|
51
58
|
if (!valid) {
|
|
52
59
|
allValid = false;
|
|
53
60
|
}
|
|
@@ -66,18 +73,48 @@ let itemKeyCounter = 0;
|
|
|
66
73
|
export class ObjectField {
|
|
67
74
|
_form = null;
|
|
68
75
|
_items = [];
|
|
76
|
+
_templates = [];
|
|
77
|
+
_activeTemplateId = null;
|
|
78
|
+
/** Inner layout for non-templated objects (single layout, applied per item too). */
|
|
79
|
+
_ownLayout = null;
|
|
80
|
+
/** Per-template inner layouts for templated objects. */
|
|
81
|
+
_templateLayouts = {};
|
|
82
|
+
_validating = false;
|
|
69
83
|
constructor(config) {
|
|
70
84
|
this.config = config;
|
|
71
85
|
this._base = new Field({
|
|
72
86
|
...config,
|
|
73
87
|
type: "object",
|
|
74
|
-
renderer: config.renderer ?? "
|
|
88
|
+
renderer: config.renderer ?? (config.isList ? "objectAccordionMultiple" : "objectAccordionSingle")
|
|
75
89
|
});
|
|
76
|
-
this.
|
|
90
|
+
this._templates = config.templates ?? [];
|
|
91
|
+
this._isTemplated = this._templates.length > 0;
|
|
92
|
+
if (this._isTemplated) {
|
|
93
|
+
// Templated mode: children populated per-item (list) or when a template is picked (single).
|
|
94
|
+
this._children = new Map();
|
|
95
|
+
} else {
|
|
96
|
+
this._children = createChildFields(config.childBuilders, null);
|
|
97
|
+
}
|
|
77
98
|
makeAutoObservable(this, {
|
|
78
99
|
config: false
|
|
79
100
|
});
|
|
80
101
|
}
|
|
102
|
+
_findTemplate(id) {
|
|
103
|
+
return this._templates.find(t => t.id === id);
|
|
104
|
+
}
|
|
105
|
+
_rebuildChildrenForTemplate(templateId) {
|
|
106
|
+
const template = this._findTemplate(templateId);
|
|
107
|
+
if (!template) {
|
|
108
|
+
throw new Error(`Template "${templateId}" not found on field "${this.config.name}". ` + `Available: ${this._templates.map(t => t.id).join(", ") || "(none)"}.`);
|
|
109
|
+
}
|
|
110
|
+
const children = createChildFields(template.childBuilders, this._form, this.qualifiedName);
|
|
111
|
+
this._children = children;
|
|
112
|
+
this._activeTemplateId = templateId;
|
|
113
|
+
const inner = this._innerLayoutFor(templateId);
|
|
114
|
+
if (inner) {
|
|
115
|
+
this._applyNestedObjectLayouts(inner, children);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
81
118
|
|
|
82
119
|
// --- Forwarded from _base ---
|
|
83
120
|
|
|
@@ -90,21 +127,28 @@ export class ObjectField {
|
|
|
90
127
|
get visible() {
|
|
91
128
|
return this._base.visible;
|
|
92
129
|
}
|
|
130
|
+
get disabled() {
|
|
131
|
+
return this._base.disabled;
|
|
132
|
+
}
|
|
93
133
|
setDisabled(value) {
|
|
94
134
|
this._base.setDisabled(value);
|
|
95
135
|
}
|
|
96
136
|
setVisible(value) {
|
|
97
137
|
this._base.setVisible(value);
|
|
98
138
|
}
|
|
99
|
-
|
|
139
|
+
setAncestorRules(rules) {
|
|
140
|
+
this._base.setAncestorRules(rules);
|
|
141
|
+
}
|
|
142
|
+
setForm(form, parentPath) {
|
|
100
143
|
this._form = form;
|
|
101
|
-
this._base.setForm(form);
|
|
144
|
+
this._base.setForm(form, parentPath);
|
|
145
|
+
const myPath = this._base.qualifiedName;
|
|
102
146
|
for (const [, field] of this._children) {
|
|
103
|
-
field.setForm(form);
|
|
147
|
+
field.setForm(form, myPath);
|
|
104
148
|
}
|
|
105
149
|
for (const item of this._items) {
|
|
106
150
|
for (const [, field] of item.children) {
|
|
107
|
-
field.setForm(form);
|
|
151
|
+
field.setForm(form, myPath);
|
|
108
152
|
}
|
|
109
153
|
}
|
|
110
154
|
}
|
|
@@ -123,18 +167,196 @@ export class ObjectField {
|
|
|
123
167
|
addOnBlur(cb) {
|
|
124
168
|
this._base.addOnBlur(cb);
|
|
125
169
|
}
|
|
170
|
+
addRequiredWhen(fn, message) {
|
|
171
|
+
this._base.addRequiredWhen(fn, message);
|
|
172
|
+
}
|
|
173
|
+
setComputed(fn) {
|
|
174
|
+
this._base.setComputed(fn);
|
|
175
|
+
}
|
|
176
|
+
setComputedUntilDirty(fn) {
|
|
177
|
+
this._base.setComputedUntilDirty(fn);
|
|
178
|
+
}
|
|
126
179
|
blur() {
|
|
127
180
|
this._base.blur();
|
|
128
181
|
}
|
|
129
182
|
remove() {
|
|
130
183
|
this._base.remove();
|
|
131
184
|
}
|
|
185
|
+
get qualifiedName() {
|
|
186
|
+
return this._base.qualifiedName;
|
|
187
|
+
}
|
|
188
|
+
focus() {
|
|
189
|
+
this._base.focus();
|
|
190
|
+
}
|
|
191
|
+
requestFocus() {
|
|
192
|
+
this._base.requestFocus();
|
|
193
|
+
}
|
|
194
|
+
clearFocusRequest() {
|
|
195
|
+
this._base.clearFocusRequest();
|
|
196
|
+
}
|
|
197
|
+
getInnerLayout() {
|
|
198
|
+
if (this.isTemplated) {
|
|
199
|
+
return this._activeTemplateId ? this._templateLayouts[this._activeTemplateId] ?? null : null;
|
|
200
|
+
}
|
|
201
|
+
return this._ownLayout;
|
|
202
|
+
}
|
|
132
203
|
|
|
133
204
|
// --- Object-specific ---
|
|
134
205
|
|
|
135
206
|
get isList() {
|
|
136
207
|
return this.config.isList;
|
|
137
208
|
}
|
|
209
|
+
get isTemplated() {
|
|
210
|
+
return this._isTemplated;
|
|
211
|
+
}
|
|
212
|
+
get activeTemplateId() {
|
|
213
|
+
return this._activeTemplateId;
|
|
214
|
+
}
|
|
215
|
+
get availableTemplates() {
|
|
216
|
+
const result = [];
|
|
217
|
+
for (const template of this._templates) {
|
|
218
|
+
if (template.visible && this._form) {
|
|
219
|
+
if (!template.visible(this._form)) {
|
|
220
|
+
continue;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
result.push({
|
|
224
|
+
id: template.id,
|
|
225
|
+
label: template.label,
|
|
226
|
+
icon: template.icon
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
return result;
|
|
230
|
+
}
|
|
231
|
+
setTemplate(templateId) {
|
|
232
|
+
if (this._activeTemplateId === templateId) {
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
this._rebuildChildrenForTemplate(templateId);
|
|
236
|
+
}
|
|
237
|
+
get templates() {
|
|
238
|
+
return {
|
|
239
|
+
add: (id, configure) => this._addTemplate(id, configure),
|
|
240
|
+
remove: templateId => this._removeTemplate(templateId)
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
_addTemplate(id, configure) {
|
|
244
|
+
if (!this.isTemplated) {
|
|
245
|
+
throw new Error(`Object field "${this.config.name}" is not templated; templates.add() requires the field to be defined with .template().`);
|
|
246
|
+
}
|
|
247
|
+
if (id === TEMPLATE_DISCRIMINATOR) {
|
|
248
|
+
throw new Error(`Template id "${TEMPLATE_DISCRIMINATOR}" is reserved. Choose a different id.`);
|
|
249
|
+
}
|
|
250
|
+
if (this._findTemplate(id)) {
|
|
251
|
+
throw new Error(`Duplicate template id "${id}".`);
|
|
252
|
+
}
|
|
253
|
+
const tb = createTemplateBuilder();
|
|
254
|
+
configure(tb);
|
|
255
|
+
this._templates.push(tb._build(id, this._form.registry));
|
|
256
|
+
}
|
|
257
|
+
_removeTemplate(templateId) {
|
|
258
|
+
if (!this.isTemplated) {
|
|
259
|
+
throw new Error(`Object field "${this.config.name}" is not templated; templates.remove() requires the field to be defined with .template().`);
|
|
260
|
+
}
|
|
261
|
+
const index = this._templates.findIndex(t => t.id === templateId);
|
|
262
|
+
if (index === -1) {
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
this._templates.splice(index, 1);
|
|
266
|
+
if (this.config.isList) {
|
|
267
|
+
this._items = this._items.filter(item => item.templateId !== templateId);
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
if (this._activeTemplateId === templateId) {
|
|
271
|
+
this._activeTemplateId = null;
|
|
272
|
+
this._children = new Map();
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
setInnerLayout(layout) {
|
|
276
|
+
if (Array.isArray(layout)) {
|
|
277
|
+
if (this.isTemplated) {
|
|
278
|
+
throw new Error(`Object field "${this.config.name}" is templated; layout.object() must pass a per-template map (Record<templateId, LayoutNode[]>), not a single LayoutNode[].`);
|
|
279
|
+
}
|
|
280
|
+
this._ownLayout = layout;
|
|
281
|
+
this._templateLayouts = {};
|
|
282
|
+
// Apply nested object layouts to children that already exist
|
|
283
|
+
// (non-templated single + non-templated list items).
|
|
284
|
+
this._applyNestedObjectLayouts(layout, this._children);
|
|
285
|
+
for (const item of this._items) {
|
|
286
|
+
this._applyNestedObjectLayouts(layout, item.children);
|
|
287
|
+
}
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
if (!this.isTemplated) {
|
|
291
|
+
throw new Error(`Object field "${this.config.name}" is not templated; layout.object() must pass a single LayoutNode[], not a per-template map.`);
|
|
292
|
+
}
|
|
293
|
+
this._templateLayouts = layout;
|
|
294
|
+
this._ownLayout = null;
|
|
295
|
+
// Apply nested object layouts to currently-active templated children
|
|
296
|
+
// (templated single with active template + templated list items).
|
|
297
|
+
if (this._activeTemplateId && layout[this._activeTemplateId]) {
|
|
298
|
+
this._applyNestedObjectLayouts(layout[this._activeTemplateId], this._children);
|
|
299
|
+
}
|
|
300
|
+
for (const item of this._items) {
|
|
301
|
+
if (item.templateId && layout[item.templateId]) {
|
|
302
|
+
this._applyNestedObjectLayouts(layout[item.templateId], item.children);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Walk an inner layout for nested `object` nodes and forward each one to
|
|
309
|
+
* the matching child field. The recursion bottoms out naturally: each
|
|
310
|
+
* matched child is itself an ObjectField and will run `_applyNestedObjectLayouts`
|
|
311
|
+
* against its own children whenever they materialise.
|
|
312
|
+
*/
|
|
313
|
+
_applyNestedObjectLayouts(layout, children) {
|
|
314
|
+
for (const node of layout) {
|
|
315
|
+
if (node.type === "object") {
|
|
316
|
+
const child = children.get(node.fieldName);
|
|
317
|
+
if (child && isObjectField(child)) {
|
|
318
|
+
child.setInnerLayout(node.inner);
|
|
319
|
+
}
|
|
320
|
+
} else if (node.type === "tabs") {
|
|
321
|
+
for (const tab of node.tabs) {
|
|
322
|
+
this._applyNestedObjectLayouts(tab.layout, children);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* Returns the inner layout that should apply to a freshly-built children
|
|
330
|
+
* Map for the given templateId (templated objects/lists) or for the
|
|
331
|
+
* non-templated case. Used to seed nested object layouts on newly-created
|
|
332
|
+
* children before they go live.
|
|
333
|
+
*/
|
|
334
|
+
_innerLayoutFor(templateId) {
|
|
335
|
+
if (this.isTemplated) {
|
|
336
|
+
if (templateId === undefined) {
|
|
337
|
+
return undefined;
|
|
338
|
+
}
|
|
339
|
+
return this._templateLayouts[templateId];
|
|
340
|
+
}
|
|
341
|
+
return this._ownLayout ?? undefined;
|
|
342
|
+
}
|
|
343
|
+
_resolveLayoutForChildren(children, templateId) {
|
|
344
|
+
const layoutNodes = this.isTemplated ? templateId !== null ? this._templateLayouts[templateId] : undefined : this._ownLayout ?? undefined;
|
|
345
|
+
if (layoutNodes && this._form?.resolveChildLayout) {
|
|
346
|
+
return this._form.resolveChildLayout(layoutNodes, children);
|
|
347
|
+
}
|
|
348
|
+
// Default: one row per visible child, in insertion order.
|
|
349
|
+
const fallback = [];
|
|
350
|
+
for (const [, field] of children) {
|
|
351
|
+
if (field.visible) {
|
|
352
|
+
fallback.push({
|
|
353
|
+
type: "row",
|
|
354
|
+
fields: [field.vm]
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
return fallback;
|
|
359
|
+
}
|
|
138
360
|
get children() {
|
|
139
361
|
return this._children;
|
|
140
362
|
}
|
|
@@ -142,19 +364,77 @@ export class ObjectField {
|
|
|
142
364
|
return this._items.map(item => ({
|
|
143
365
|
key: item.key,
|
|
144
366
|
children: item.children,
|
|
145
|
-
|
|
367
|
+
templateId: item.templateId,
|
|
368
|
+
getData: () => this._getItemData(item)
|
|
146
369
|
}));
|
|
147
370
|
}
|
|
371
|
+
_getItemData(item) {
|
|
372
|
+
const data = getChildrenData(item.children);
|
|
373
|
+
if (item.templateId !== undefined) {
|
|
374
|
+
return {
|
|
375
|
+
[TEMPLATE_DISCRIMINATOR]: item.templateId,
|
|
376
|
+
...data
|
|
377
|
+
};
|
|
378
|
+
}
|
|
379
|
+
return data;
|
|
380
|
+
}
|
|
148
381
|
getChild(name) {
|
|
149
382
|
return this._children.get(name);
|
|
150
383
|
}
|
|
384
|
+
fields(factory) {
|
|
385
|
+
if (this.isTemplated) {
|
|
386
|
+
throw new Error(`Object field "${this.config.name}" is templated; use templates.add()/remove() to manage children. Each template owns its own fields.`);
|
|
387
|
+
}
|
|
388
|
+
const builders = factory(this._form.registry);
|
|
389
|
+
for (const [name, builder] of Object.entries(builders)) {
|
|
390
|
+
if (builder === undefined) {
|
|
391
|
+
this._children.delete(name);
|
|
392
|
+
this.config.childBuilders[name] = undefined;
|
|
393
|
+
delete this.config.childBuilders[name];
|
|
394
|
+
if (this.config.isList) {
|
|
395
|
+
for (const item of this._items) {
|
|
396
|
+
item.children.delete(name);
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
continue;
|
|
400
|
+
}
|
|
401
|
+
this.config.childBuilders[name] = builder;
|
|
402
|
+
const built = builder.build(name);
|
|
403
|
+
const newField = createFieldFromConfig(built, this._form, this.qualifiedName);
|
|
404
|
+
this._children.set(name, newField);
|
|
405
|
+
if (this.config.isList) {
|
|
406
|
+
for (const item of this._items) {
|
|
407
|
+
const itemField = createFieldFromConfig(built, this._form, this.qualifiedName);
|
|
408
|
+
item.children.set(name, itemField);
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
// Re-apply nested object layouts so newly-added children pick up any
|
|
414
|
+
// layout.object() entries already registered on this field.
|
|
415
|
+
if (this._ownLayout) {
|
|
416
|
+
this._applyNestedObjectLayouts(this._ownLayout, this._children);
|
|
417
|
+
for (const item of this._items) {
|
|
418
|
+
this._applyNestedObjectLayouts(this._ownLayout, item.children);
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
}
|
|
151
422
|
getListItemChild(index, name) {
|
|
152
423
|
const item = this._items[index];
|
|
153
424
|
return item?.children.get(name);
|
|
154
425
|
}
|
|
155
426
|
getData() {
|
|
156
427
|
if (this.config.isList) {
|
|
157
|
-
return this._items.map(item =>
|
|
428
|
+
return this._items.map(item => this._getItemData(item));
|
|
429
|
+
}
|
|
430
|
+
if (this.isTemplated) {
|
|
431
|
+
if (this._activeTemplateId === null) {
|
|
432
|
+
return null;
|
|
433
|
+
}
|
|
434
|
+
return {
|
|
435
|
+
[TEMPLATE_DISCRIMINATOR]: this._activeTemplateId,
|
|
436
|
+
...getChildrenData(this._children)
|
|
437
|
+
};
|
|
158
438
|
}
|
|
159
439
|
return getChildrenData(this._children);
|
|
160
440
|
}
|
|
@@ -169,15 +449,69 @@ export class ObjectField {
|
|
|
169
449
|
this._items = [];
|
|
170
450
|
if (Array.isArray(value)) {
|
|
171
451
|
for (const itemData of value) {
|
|
172
|
-
this.
|
|
452
|
+
if (this.isTemplated) {
|
|
453
|
+
if (!itemData || typeof itemData !== "object") {
|
|
454
|
+
continue;
|
|
455
|
+
}
|
|
456
|
+
const data = itemData;
|
|
457
|
+
const templateId = data[TEMPLATE_DISCRIMINATOR];
|
|
458
|
+
if (typeof templateId !== "string") {
|
|
459
|
+
continue;
|
|
460
|
+
}
|
|
461
|
+
if (!this._findTemplate(templateId)) {
|
|
462
|
+
continue;
|
|
463
|
+
}
|
|
464
|
+
const {
|
|
465
|
+
[TEMPLATE_DISCRIMINATOR]: _discarded,
|
|
466
|
+
...rest
|
|
467
|
+
} = data;
|
|
468
|
+
this._addItemInternal(rest, templateId);
|
|
469
|
+
} else {
|
|
470
|
+
this._addItemInternal(itemData);
|
|
471
|
+
}
|
|
173
472
|
}
|
|
174
473
|
}
|
|
175
|
-
|
|
176
|
-
|
|
474
|
+
return;
|
|
475
|
+
}
|
|
476
|
+
if (this.isTemplated) {
|
|
477
|
+
if (value === null || value === undefined) {
|
|
478
|
+
this._activeTemplateId = null;
|
|
479
|
+
this._children = new Map();
|
|
480
|
+
return;
|
|
481
|
+
}
|
|
482
|
+
const data = value;
|
|
483
|
+
const templateId = data[TEMPLATE_DISCRIMINATOR];
|
|
484
|
+
if (typeof templateId !== "string") {
|
|
485
|
+
return;
|
|
486
|
+
}
|
|
487
|
+
if (!this._findTemplate(templateId)) {
|
|
488
|
+
return;
|
|
489
|
+
}
|
|
490
|
+
this._rebuildChildrenForTemplate(templateId);
|
|
491
|
+
const {
|
|
492
|
+
[TEMPLATE_DISCRIMINATOR]: _discarded,
|
|
493
|
+
...rest
|
|
494
|
+
} = data;
|
|
495
|
+
hydrateChildren(this._children, rest);
|
|
496
|
+
return;
|
|
177
497
|
}
|
|
498
|
+
hydrateChildren(this._children, value);
|
|
178
499
|
}
|
|
179
|
-
addItem(data) {
|
|
180
|
-
this.
|
|
500
|
+
addItem(templateIdOrData, data) {
|
|
501
|
+
if (this.isTemplated) {
|
|
502
|
+
if (typeof templateIdOrData !== "string") {
|
|
503
|
+
throw new Error(`Object field "${this.config.name}": templated list items require a template id. ` + `Call addItem(templateId) with one of: ${this._templates.map(t => t.id).join(", ")}.`);
|
|
504
|
+
}
|
|
505
|
+
if (!this._findTemplate(templateIdOrData)) {
|
|
506
|
+
throw new Error(`Template "${templateIdOrData}" not found on field "${this.config.name}". ` + `Available: ${this._templates.map(t => t.id).join(", ") || "(none)"}.`);
|
|
507
|
+
}
|
|
508
|
+
this._addItemInternal(data, templateIdOrData);
|
|
509
|
+
return;
|
|
510
|
+
}
|
|
511
|
+
if (typeof templateIdOrData === "string") {
|
|
512
|
+
throw new Error(`Object field "${this.config.name}" is not templated; addItem() does not accept a template id.`);
|
|
513
|
+
}
|
|
514
|
+
this._addItemInternal(templateIdOrData);
|
|
181
515
|
}
|
|
182
516
|
removeItem(index) {
|
|
183
517
|
this._items.splice(index, 1);
|
|
@@ -189,16 +523,52 @@ export class ObjectField {
|
|
|
189
523
|
const [item] = this._items.splice(fromIndex, 1);
|
|
190
524
|
this._items.splice(toIndex, 0, item);
|
|
191
525
|
}
|
|
192
|
-
|
|
193
|
-
const
|
|
526
|
+
duplicateItem(index) {
|
|
527
|
+
const source = this._items[index];
|
|
528
|
+
if (!source) {
|
|
529
|
+
return;
|
|
530
|
+
}
|
|
531
|
+
const data = getChildrenData(source.children);
|
|
532
|
+
const children = createChildFields(this._templateChildBuilders(source.templateId), this._form, this.qualifiedName);
|
|
533
|
+
hydrateChildren(children, data, {
|
|
534
|
+
clone: true
|
|
535
|
+
});
|
|
536
|
+
const key = `item_${++itemKeyCounter}`;
|
|
537
|
+
this._items.splice(index + 1, 0, {
|
|
538
|
+
key,
|
|
539
|
+
children,
|
|
540
|
+
templateId: source.templateId
|
|
541
|
+
});
|
|
542
|
+
const inner = this._innerLayoutFor(source.templateId);
|
|
543
|
+
if (inner) {
|
|
544
|
+
this._applyNestedObjectLayouts(inner, children);
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
_templateChildBuilders(templateId) {
|
|
548
|
+
if (templateId === undefined) {
|
|
549
|
+
return this.config.childBuilders;
|
|
550
|
+
}
|
|
551
|
+
const template = this._findTemplate(templateId);
|
|
552
|
+
if (!template) {
|
|
553
|
+
throw new Error(`Template "${templateId}" not found on field "${this.config.name}".`);
|
|
554
|
+
}
|
|
555
|
+
return template.childBuilders;
|
|
556
|
+
}
|
|
557
|
+
_addItemInternal(data, templateId) {
|
|
558
|
+
const children = createChildFields(this._templateChildBuilders(templateId), this._form, this.qualifiedName);
|
|
194
559
|
if (data) {
|
|
195
560
|
hydrateChildren(children, data);
|
|
196
561
|
}
|
|
197
562
|
const key = `item_${++itemKeyCounter}`;
|
|
198
563
|
this._items.push({
|
|
199
564
|
key,
|
|
200
|
-
children
|
|
565
|
+
children,
|
|
566
|
+
templateId
|
|
201
567
|
});
|
|
568
|
+
const inner = this._innerLayoutFor(templateId);
|
|
569
|
+
if (inner) {
|
|
570
|
+
this._applyNestedObjectLayouts(inner, children);
|
|
571
|
+
}
|
|
202
572
|
}
|
|
203
573
|
resetValidation() {
|
|
204
574
|
this._base.resetValidation();
|
|
@@ -229,24 +599,44 @@ export class ObjectField {
|
|
|
229
599
|
placeholder: baseVm.placeholder,
|
|
230
600
|
value: this.getValue(),
|
|
231
601
|
validation: baseVm.validation,
|
|
602
|
+
validating: this._validating,
|
|
232
603
|
required: baseVm.required,
|
|
604
|
+
visible: baseVm.visible,
|
|
233
605
|
disabled: baseVm.disabled,
|
|
234
606
|
renderer: baseVm.renderer,
|
|
235
607
|
rendererSettings: baseVm.rendererSettings,
|
|
236
608
|
onChange: value => this.setValue(value),
|
|
237
|
-
onBlur: () =>
|
|
609
|
+
onBlur: () => {
|
|
610
|
+
if (this._form?.submitted) {
|
|
611
|
+
void this.validate();
|
|
612
|
+
}
|
|
613
|
+
this.blur();
|
|
614
|
+
},
|
|
615
|
+
focusRequested: baseVm.focusRequested,
|
|
616
|
+
clearFocusRequest: baseVm.clearFocusRequest,
|
|
238
617
|
isList: this.config.isList,
|
|
239
618
|
fields: this.config.isList ? [] : Array.from(this._children.values()).filter(f => f.visible).map(f => f.vm),
|
|
619
|
+
layout: this.config.isList ? [] : this._resolveLayoutForChildren(this._children, this._activeTemplateId),
|
|
240
620
|
items: this.config.isList ? this._items.map((item, index) => ({
|
|
241
621
|
key: item.key,
|
|
242
622
|
fields: Array.from(item.children.values()).filter(f => f.visible).map(f => f.vm),
|
|
623
|
+
layout: this._resolveLayoutForChildren(item.children, item.templateId ?? null),
|
|
624
|
+
templateId: item.templateId,
|
|
243
625
|
remove: () => this.removeItem(index),
|
|
244
626
|
moveUp: () => this.moveItem(index, index - 1),
|
|
245
|
-
moveDown: () => this.moveItem(index, index + 1)
|
|
627
|
+
moveDown: () => this.moveItem(index, index + 1),
|
|
628
|
+
duplicate: () => this.duplicateItem(index)
|
|
246
629
|
})) : [],
|
|
247
|
-
addItem:
|
|
630
|
+
addItem: value => {
|
|
631
|
+
return value !== undefined ? this.addItem(value) : this.addItem();
|
|
632
|
+
},
|
|
248
633
|
removeItem: index => this.removeItem(index),
|
|
249
|
-
moveItem: (from, to) => this.moveItem(from, to)
|
|
634
|
+
moveItem: (from, to) => this.moveItem(from, to),
|
|
635
|
+
duplicateItem: index => this.duplicateItem(index),
|
|
636
|
+
isTemplated: this.isTemplated,
|
|
637
|
+
availableTemplates: this.availableTemplates,
|
|
638
|
+
activeTemplateId: this._activeTemplateId,
|
|
639
|
+
setTemplate: templateId => this.setTemplate(templateId)
|
|
250
640
|
};
|
|
251
641
|
}
|
|
252
642
|
get hasErrors() {
|
|
@@ -274,72 +664,99 @@ export class ObjectField {
|
|
|
274
664
|
}
|
|
275
665
|
return false;
|
|
276
666
|
}
|
|
277
|
-
async validate() {
|
|
278
|
-
if (this.
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
667
|
+
async validate(options) {
|
|
668
|
+
if (!this.visible) {
|
|
669
|
+
this.setValidation({
|
|
670
|
+
isValid: null
|
|
671
|
+
});
|
|
672
|
+
return true;
|
|
673
|
+
}
|
|
674
|
+
runInAction(() => {
|
|
675
|
+
this._validating = true;
|
|
676
|
+
});
|
|
677
|
+
try {
|
|
678
|
+
const requiredState = this._base.resolveRequired();
|
|
679
|
+
if (requiredState.required) {
|
|
680
|
+
const message = requiredState.message || "This field is required.";
|
|
681
|
+
if (this.config.isList && this._items.length === 0) {
|
|
290
682
|
this.setValidation({
|
|
291
683
|
isValid: false,
|
|
292
|
-
message
|
|
684
|
+
message
|
|
293
685
|
});
|
|
294
686
|
return false;
|
|
295
687
|
}
|
|
688
|
+
if (!this.config.isList) {
|
|
689
|
+
if (this.isTemplated) {
|
|
690
|
+
if (this._activeTemplateId === null) {
|
|
691
|
+
this.setValidation({
|
|
692
|
+
isValid: false,
|
|
693
|
+
message
|
|
694
|
+
});
|
|
695
|
+
return false;
|
|
696
|
+
}
|
|
697
|
+
} else {
|
|
698
|
+
const data = this.getData();
|
|
699
|
+
const hasAnyValue = Object.values(data).some(v => v !== null && v !== undefined && v !== "");
|
|
700
|
+
if (!hasAnyValue) {
|
|
701
|
+
this.setValidation({
|
|
702
|
+
isValid: false,
|
|
703
|
+
message
|
|
704
|
+
});
|
|
705
|
+
return false;
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
}
|
|
296
709
|
}
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
710
|
+
if (this.config.isList && this.config.listSchema) {
|
|
711
|
+
const listData = this.getData();
|
|
712
|
+
const result = await this.config.listSchema.safeParseAsync(listData);
|
|
713
|
+
if (!result.success) {
|
|
714
|
+
const firstIssue = result.error.issues[0];
|
|
715
|
+
runInAction(() => {
|
|
716
|
+
this.setValidation({
|
|
717
|
+
isValid: false,
|
|
718
|
+
message: firstIssue?.message || "Invalid value."
|
|
719
|
+
});
|
|
307
720
|
});
|
|
308
|
-
|
|
309
|
-
|
|
721
|
+
return false;
|
|
722
|
+
}
|
|
310
723
|
}
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
724
|
+
if (this.config.schema) {
|
|
725
|
+
const data = this.getData();
|
|
726
|
+
const result = await this.config.schema.safeParseAsync(data);
|
|
727
|
+
if (!result.success) {
|
|
728
|
+
const firstIssue = result.error.issues[0];
|
|
729
|
+
runInAction(() => {
|
|
730
|
+
this.setValidation({
|
|
731
|
+
isValid: false,
|
|
732
|
+
message: firstIssue?.message || "Invalid value."
|
|
733
|
+
});
|
|
321
734
|
});
|
|
322
|
-
|
|
323
|
-
|
|
735
|
+
return false;
|
|
736
|
+
}
|
|
324
737
|
}
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
738
|
+
let allValid = true;
|
|
739
|
+
if (this.config.isList) {
|
|
740
|
+
for (const item of this._items) {
|
|
741
|
+
const valid = await validateChildren(item.children, options);
|
|
742
|
+
if (!valid) {
|
|
743
|
+
allValid = false;
|
|
744
|
+
}
|
|
332
745
|
}
|
|
746
|
+
} else {
|
|
747
|
+
allValid = await validateChildren(this._children, options);
|
|
333
748
|
}
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
this.setValidation({
|
|
339
|
-
isValid: allValid
|
|
749
|
+
runInAction(() => {
|
|
750
|
+
this.setValidation({
|
|
751
|
+
isValid: allValid
|
|
752
|
+
});
|
|
340
753
|
});
|
|
341
|
-
|
|
342
|
-
|
|
754
|
+
return allValid;
|
|
755
|
+
} finally {
|
|
756
|
+
runInAction(() => {
|
|
757
|
+
this._validating = false;
|
|
758
|
+
});
|
|
759
|
+
}
|
|
343
760
|
}
|
|
344
761
|
}
|
|
345
762
|
|