@xbeeant/form-engine-designer 0.0.2 → 0.0.4
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/es/Canvas.js +42 -46
- package/dist/es/Canvas.js.map +1 -1
- package/dist/es/Designer.js +121 -98
- package/dist/es/Designer.js.map +1 -1
- package/dist/es/DesignerContext.js +86 -73
- package/dist/es/DesignerContext.js.map +1 -1
- package/dist/es/Palette.js +3 -3
- package/dist/es/Palette.js.map +1 -1
- package/dist/es/PropertyPanel.js +97 -97
- package/dist/es/PropertyPanel.js.map +1 -1
- package/dist/es/catalog.js +19 -11
- package/dist/es/catalog.js.map +1 -1
- package/dist/es/designer-context.js +110 -0
- package/dist/es/designer-context.js.map +1 -0
- package/dist/es/history.js +73 -0
- package/dist/es/history.js.map +1 -0
- package/dist/es/index.js +3 -3
- package/dist/es/property/basic-property.js +6 -0
- package/dist/es/property/basic-property.js.map +1 -1
- package/dist/es/property-panel.js +294 -0
- package/dist/es/property-panel.js.map +1 -0
- package/dist/es/resizable-panel.js +103 -0
- package/dist/es/resizable-panel.js.map +1 -0
- package/dist/es/schema-utils.js +286 -0
- package/dist/es/schema-utils.js.map +1 -0
- package/dist/es/widgets/BindEditor.js +60 -49
- package/dist/es/widgets/BindEditor.js.map +1 -1
- package/dist/es/widgets/CodeEditor.js +41 -49
- package/dist/es/widgets/CodeEditor.js.map +1 -1
- package/dist/es/widgets/DefaultEditor.js +25 -30
- package/dist/es/widgets/DefaultEditor.js.map +1 -1
- package/dist/es/widgets/DependenciesEditor.js +21 -21
- package/dist/es/widgets/DependenciesEditor.js.map +1 -1
- package/dist/es/widgets/EnumEditor.js +25 -31
- package/dist/es/widgets/EnumEditor.js.map +1 -1
- package/dist/es/widgets/ExpressionSwitch.js +32 -30
- package/dist/es/widgets/ExpressionSwitch.js.map +1 -1
- package/dist/es/widgets/ReactionsEditor.js +103 -103
- package/dist/es/widgets/ReactionsEditor.js.map +1 -1
- package/dist/es/widgets/RemoteDataEditor.js +63 -63
- package/dist/es/widgets/RemoteDataEditor.js.map +1 -1
- package/dist/es/widgets/ValidateEditor.js +49 -49
- package/dist/es/widgets/ValidateEditor.js.map +1 -1
- package/dist/es/widgets/bind-editor.js +78 -0
- package/dist/es/widgets/bind-editor.js.map +1 -0
- package/dist/es/widgets/code-editor.js +76 -0
- package/dist/es/widgets/code-editor.js.map +1 -0
- package/dist/es/widgets/default-editor.js +50 -0
- package/dist/es/widgets/default-editor.js.map +1 -0
- package/dist/es/widgets/dependencies-editor.js +36 -0
- package/dist/es/widgets/dependencies-editor.js.map +1 -0
- package/dist/es/widgets/enum-editor.js +43 -0
- package/dist/es/widgets/enum-editor.js.map +1 -0
- package/dist/es/widgets/expression-builder.js +367 -0
- package/dist/es/widgets/expression-builder.js.map +1 -0
- package/dist/es/widgets/expression-model.js +340 -0
- package/dist/es/widgets/expression-model.js.map +1 -0
- package/dist/es/widgets/expression-switch.js +49 -0
- package/dist/es/widgets/expression-switch.js.map +1 -0
- package/dist/es/widgets/index.js +13 -13
- package/dist/es/widgets/index.js.map +1 -1
- package/dist/es/widgets/options-editor.js +102 -0
- package/dist/es/widgets/options-editor.js.map +1 -0
- package/dist/es/widgets/reactions-editor.js +401 -0
- package/dist/es/widgets/reactions-editor.js.map +1 -0
- package/dist/es/widgets/reactions-model.js +107 -0
- package/dist/es/widgets/reactions-model.js.map +1 -0
- package/dist/es/widgets/remote-data-editor.js +314 -0
- package/dist/es/widgets/remote-data-editor.js.map +1 -0
- package/dist/es/widgets/use-form-data-fields.js +16 -0
- package/dist/es/widgets/use-form-data-fields.js.map +1 -0
- package/dist/es/widgets/validate-editor.js +118 -0
- package/dist/es/widgets/validate-editor.js.map +1 -0
- package/package.json +4 -5
- package/dist/es/react/src/components/FormController.js +0 -154
- package/dist/es/react/src/components/FormController.js.map +0 -1
- package/dist/es/react/src/components/NexusField.js +0 -99
- package/dist/es/react/src/components/NexusField.js.map +0 -1
- package/dist/es/react/src/components/NexusForm.js +0 -121
- package/dist/es/react/src/components/NexusForm.js.map +0 -1
- package/dist/es/react/src/components/NexusFormProvider.js +0 -19
- package/dist/es/react/src/components/NexusFormProvider.js.map +0 -1
- package/dist/es/react/src/components/NexusLayout.js +0 -49
- package/dist/es/react/src/components/NexusLayout.js.map +0 -1
- package/dist/es/react/src/components/NexusObject.js +0 -65
- package/dist/es/react/src/components/NexusObject.js.map +0 -1
- package/dist/es/react/src/contexts/FieldInheritContext.js +0 -6
- package/dist/es/react/src/contexts/FieldInheritContext.js.map +0 -1
- package/dist/es/react/src/contexts/GridContext.js +0 -6
- package/dist/es/react/src/contexts/GridContext.js.map +0 -1
- package/dist/es/react/src/contexts/LayoutConfigContext.js +0 -6
- package/dist/es/react/src/contexts/LayoutConfigContext.js.map +0 -1
- package/dist/es/react/src/contexts/NexusContext.js +0 -13
- package/dist/es/react/src/contexts/NexusContext.js.map +0 -1
- package/dist/es/react/src/hooks/useForm.js +0 -10
- package/dist/es/react/src/hooks/useForm.js.map +0 -1
- package/dist/es/react/src/utils/renderTreeNode.js +0 -18
- package/dist/es/react/src/utils/renderTreeNode.js.map +0 -1
- package/dist/es/react/src/utils/resolveColSpan.js +0 -10
- package/dist/es/react/src/utils/resolveColSpan.js.map +0 -1
- package/dist/es/schemaUtils.test.js +0 -188
- package/dist/es/schemaUtils.test.js.map +0 -1
- package/dist/es/vite-env.d.js +0 -2
- package/dist/es/vite-env.d.js.map +0 -1
- package/dist/es/widgets/expressionModel.test.js +0 -193
- package/dist/es/widgets/expressionModel.test.js.map +0 -1
- package/src/Canvas.tsx +0 -1111
- package/src/Designer.css +0 -206
- package/src/Designer.tsx +0 -254
- package/src/DesignerContext.tsx +0 -192
- package/src/Palette.tsx +0 -261
- package/src/PropertyPanel.tsx +0 -486
- package/src/ResizablePanel.tsx +0 -210
- package/src/catalog.ts +0 -526
- package/src/index.ts +0 -25
- package/src/property/basic-property.ts +0 -126
- package/src/schemaUtils.test.ts +0 -261
- package/src/schemaUtils.ts +0 -627
- package/src/types.ts +0 -38
- package/src/vite-env.d.ts +0 -1
- package/src/widgets/BindEditor.tsx +0 -105
- package/src/widgets/CodeEditor.tsx +0 -114
- package/src/widgets/DefaultEditor.tsx +0 -73
- package/src/widgets/DependenciesEditor.tsx +0 -56
- package/src/widgets/EnumEditor.tsx +0 -66
- package/src/widgets/ExpressionBuilder.tsx +0 -509
- package/src/widgets/ExpressionSwitch.tsx +0 -62
- package/src/widgets/OptionsEditor.tsx +0 -141
- package/src/widgets/ReactionsEditor.tsx +0 -532
- package/src/widgets/RemoteDataEditor.tsx +0 -382
- package/src/widgets/ValidateEditor.tsx +0 -162
- package/src/widgets/expressionModel.test.ts +0 -262
- package/src/widgets/expressionModel.ts +0 -573
- package/src/widgets/index.ts +0 -45
- package/src/widgets/reactionsModel.ts +0 -190
- package/src/widgets/useFormDataFields.ts +0 -21
- /package/dist/es/{form-engine-designer.css → index.css} +0 -0
package/src/schemaUtils.test.ts
DELETED
|
@@ -1,261 +0,0 @@
|
|
|
1
|
-
import type { NexusSchema, SchemaNode } from '@xbeeant/form-engine';
|
|
2
|
-
import { NexusEngine } from '@xbeeant/form-engine';
|
|
3
|
-
import { describe, expect, it } from 'vitest';
|
|
4
|
-
import {
|
|
5
|
-
addChildToSchema,
|
|
6
|
-
collectDataFieldOptions,
|
|
7
|
-
diffPropertyPatch,
|
|
8
|
-
extractFormLevelConfig,
|
|
9
|
-
flattenNodeForPropertyEditor,
|
|
10
|
-
updateNodeWithNesting,
|
|
11
|
-
} from './schemaUtils';
|
|
12
|
-
|
|
13
|
-
const radioNode: SchemaNode = {
|
|
14
|
-
type: 'string',
|
|
15
|
-
widget: 'radio',
|
|
16
|
-
title: '单选',
|
|
17
|
-
enum: ['a', 'b'],
|
|
18
|
-
enumNames: ['选项A', '选项B'],
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
describe('diffPropertyPatch', () => {
|
|
22
|
-
it('filters out empty-string defaults for untouched fields', () => {
|
|
23
|
-
const initial = {
|
|
24
|
-
title: '单选',
|
|
25
|
-
options: [
|
|
26
|
-
{ value: 'a', label: '选项A' },
|
|
27
|
-
{ value: 'b', label: '选项B' },
|
|
28
|
-
],
|
|
29
|
-
};
|
|
30
|
-
const allValues = {
|
|
31
|
-
title: '单选',
|
|
32
|
-
description: '',
|
|
33
|
-
placeholder: '',
|
|
34
|
-
default: '',
|
|
35
|
-
disabled: '',
|
|
36
|
-
readOnly: '',
|
|
37
|
-
hidden: '',
|
|
38
|
-
required: '',
|
|
39
|
-
pattern: '',
|
|
40
|
-
bind: '',
|
|
41
|
-
dependencies: '',
|
|
42
|
-
options: [
|
|
43
|
-
{ value: 'a', label: '选项A' },
|
|
44
|
-
{ value: 'b', label: '选项B' },
|
|
45
|
-
],
|
|
46
|
-
};
|
|
47
|
-
const patch = diffPropertyPatch(initial, allValues);
|
|
48
|
-
expect(patch).toEqual({});
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
it('keeps genuinely changed values', () => {
|
|
52
|
-
const initial = { title: '单选', options: [{ value: 'a', label: 'A' }] };
|
|
53
|
-
const allValues = {
|
|
54
|
-
title: '新标题',
|
|
55
|
-
options: [
|
|
56
|
-
{ value: 'a', label: 'A' },
|
|
57
|
-
{ value: 'b', label: 'B' },
|
|
58
|
-
],
|
|
59
|
-
};
|
|
60
|
-
const patch = diffPropertyPatch(initial, allValues);
|
|
61
|
-
expect(patch).toEqual(allValues);
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
it('empty string is treated as unassigned and never written to schema', () => {
|
|
65
|
-
const initial = { title: '单选', description: '说明', bind: 'user.name' };
|
|
66
|
-
const allValues = { title: '单选', description: '', bind: '' };
|
|
67
|
-
const patch = diffPropertyPatch(initial, allValues);
|
|
68
|
-
expect(patch).toEqual({});
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
it('user-cleared field is written back as undefined for deletion', () => {
|
|
72
|
-
const initial = { title: '单选', variant: 'outlined', description: '说明' };
|
|
73
|
-
const allValues = { title: '单选', variant: '', description: '' };
|
|
74
|
-
const changed = new Set(['variant']);
|
|
75
|
-
const patch = diffPropertyPatch(initial, allValues, changed);
|
|
76
|
-
expect(patch).toEqual({ variant: undefined });
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
it('untouched empty fields stay skipped even with changedFields set', () => {
|
|
80
|
-
const initial = { title: '单选' };
|
|
81
|
-
const allValues = { title: '单选', description: '', placeholder: '' };
|
|
82
|
-
const changed = new Set(['title']);
|
|
83
|
-
const patch = diffPropertyPatch(initial, allValues, changed);
|
|
84
|
-
expect(patch).toEqual({});
|
|
85
|
-
});
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
describe('updateNodeWithNesting deletion semantics', () => {
|
|
89
|
-
it('cleared UI prop is removed from node.props instead of written as undefined', () => {
|
|
90
|
-
const schema: NexusSchema = {
|
|
91
|
-
type: 'object',
|
|
92
|
-
properties: {
|
|
93
|
-
card: {
|
|
94
|
-
type: 'card',
|
|
95
|
-
title: '卡片',
|
|
96
|
-
props: { variant: 'outlined', hoverable: true },
|
|
97
|
-
properties: {},
|
|
98
|
-
},
|
|
99
|
-
},
|
|
100
|
-
};
|
|
101
|
-
const next = updateNodeWithNesting(schema, ['card'], {
|
|
102
|
-
variant: undefined,
|
|
103
|
-
});
|
|
104
|
-
const node = next.properties.card as Record<string, unknown>;
|
|
105
|
-
expect((node.props as Record<string, unknown>).variant).toBeUndefined();
|
|
106
|
-
expect('variant' in (node.props as Record<string, unknown>)).toBe(false);
|
|
107
|
-
expect((node.props as Record<string, unknown>).hoverable).toBe(true);
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
it('cleared schema-level key is removed from the node', () => {
|
|
111
|
-
const schema: NexusSchema = {
|
|
112
|
-
type: 'object',
|
|
113
|
-
properties: {
|
|
114
|
-
gender: { ...radioNode, bind: 'user.gender' },
|
|
115
|
-
},
|
|
116
|
-
};
|
|
117
|
-
const next = updateNodeWithNesting(schema, ['gender'], { bind: undefined });
|
|
118
|
-
const node = next.properties.gender as Record<string, unknown>;
|
|
119
|
-
expect(node.bind).toBeUndefined();
|
|
120
|
-
expect('bind' in node).toBe(false);
|
|
121
|
-
expect(node.title).toBe('单选');
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
it('widget display format is written into node.props (antd passthrough)', () => {
|
|
125
|
-
// date 等控件的 format 是显示格式,必须走 props 通道才能被 widget 消费;
|
|
126
|
-
// 顶层 node.format 保留给 JSON Schema 校验语义(email/url)
|
|
127
|
-
const schema: NexusSchema = {
|
|
128
|
-
type: 'object',
|
|
129
|
-
properties: {
|
|
130
|
-
birthday: { type: 'string', widget: 'date', title: '出生日期' },
|
|
131
|
-
},
|
|
132
|
-
};
|
|
133
|
-
const next = updateNodeWithNesting(schema, ['birthday'], {
|
|
134
|
-
format: 'YYYY/MM/DD',
|
|
135
|
-
});
|
|
136
|
-
const node = next.properties.birthday as Record<string, unknown>;
|
|
137
|
-
expect(node.format).toBeUndefined();
|
|
138
|
-
expect('format' in node).toBe(false);
|
|
139
|
-
expect((node.props as Record<string, unknown>).format).toBe('YYYY/MM/DD');
|
|
140
|
-
});
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
describe('designer full property-panel patch', () => {
|
|
144
|
-
it('empty defaults are not written, radio key preserved in formData', () => {
|
|
145
|
-
let schema: NexusSchema = { type: 'object', properties: {} };
|
|
146
|
-
schema = addChildToSchema(schema, [], 'gender', radioNode);
|
|
147
|
-
|
|
148
|
-
// simulate property form allValues (includes empty-string defaults) + diff filter
|
|
149
|
-
const initial = flattenNodeForPropertyEditor(
|
|
150
|
-
schema.properties.gender as never,
|
|
151
|
-
);
|
|
152
|
-
const allValues = {
|
|
153
|
-
title: '单选',
|
|
154
|
-
description: '',
|
|
155
|
-
placeholder: '',
|
|
156
|
-
default: '',
|
|
157
|
-
extra: '',
|
|
158
|
-
disabled: '',
|
|
159
|
-
readOnly: '',
|
|
160
|
-
readOnlyWidget: '',
|
|
161
|
-
hidden: '',
|
|
162
|
-
width: '',
|
|
163
|
-
options: [
|
|
164
|
-
{ value: 'a', label: '选项A' },
|
|
165
|
-
{ value: 'b', label: '选项B' },
|
|
166
|
-
],
|
|
167
|
-
optionType: '',
|
|
168
|
-
buttonStyle: '',
|
|
169
|
-
required: '',
|
|
170
|
-
pattern: '',
|
|
171
|
-
validate: '',
|
|
172
|
-
bind: '',
|
|
173
|
-
dependencies: '',
|
|
174
|
-
};
|
|
175
|
-
const patch = diffPropertyPatch(initial, allValues);
|
|
176
|
-
expect(patch.bind).toBeUndefined();
|
|
177
|
-
|
|
178
|
-
schema = updateNodeWithNesting(schema, ['gender'], patch);
|
|
179
|
-
|
|
180
|
-
const engine = new NexusEngine();
|
|
181
|
-
engine.init(schema);
|
|
182
|
-
engine.setFieldValue('gender', 'a');
|
|
183
|
-
expect(engine.getFormData()).toEqual({ gender: 'a' });
|
|
184
|
-
});
|
|
185
|
-
});
|
|
186
|
-
|
|
187
|
-
describe('extractFormLevelConfig', () => {
|
|
188
|
-
it('only extracts top-level form config keys, not the whole schema', () => {
|
|
189
|
-
const schema: NexusSchema = {
|
|
190
|
-
type: 'object',
|
|
191
|
-
displayType: 'row',
|
|
192
|
-
colon: true,
|
|
193
|
-
properties: { gender: radioNode },
|
|
194
|
-
};
|
|
195
|
-
const keys = [
|
|
196
|
-
'displayType',
|
|
197
|
-
'labelWidth',
|
|
198
|
-
'colon',
|
|
199
|
-
'label',
|
|
200
|
-
'readOnly',
|
|
201
|
-
'column',
|
|
202
|
-
];
|
|
203
|
-
const config = extractFormLevelConfig(
|
|
204
|
-
schema as unknown as Record<string, unknown>,
|
|
205
|
-
keys,
|
|
206
|
-
);
|
|
207
|
-
expect(config).toEqual({ displayType: 'row', colon: true });
|
|
208
|
-
expect('properties' in config).toBe(false);
|
|
209
|
-
expect('type' in config).toBe(false);
|
|
210
|
-
});
|
|
211
|
-
|
|
212
|
-
it('omits form-level keys that are not set on the schema', () => {
|
|
213
|
-
const schema: NexusSchema = { type: 'object', properties: {} };
|
|
214
|
-
const config = extractFormLevelConfig(
|
|
215
|
-
schema as unknown as Record<string, unknown>,
|
|
216
|
-
['labelWidth', 'column'],
|
|
217
|
-
);
|
|
218
|
-
expect(config).toEqual({});
|
|
219
|
-
});
|
|
220
|
-
});
|
|
221
|
-
|
|
222
|
-
describe('collectDataFieldOptions', () => {
|
|
223
|
-
it('labels options with field title, values with path key', () => {
|
|
224
|
-
const schema: NexusSchema = {
|
|
225
|
-
type: 'object',
|
|
226
|
-
properties: {
|
|
227
|
-
user: {
|
|
228
|
-
type: 'object',
|
|
229
|
-
properties: {
|
|
230
|
-
name: { type: 'string', title: '姓名' },
|
|
231
|
-
gender: { type: 'string', widget: 'radio', title: '性别' },
|
|
232
|
-
},
|
|
233
|
-
},
|
|
234
|
-
tags: {
|
|
235
|
-
type: 'array',
|
|
236
|
-
widget: 'list',
|
|
237
|
-
items: { type: 'string', widget: 'input', title: '标签项' },
|
|
238
|
-
},
|
|
239
|
-
},
|
|
240
|
-
};
|
|
241
|
-
const options = collectDataFieldOptions(schema);
|
|
242
|
-
expect(options).toEqual([
|
|
243
|
-
{ value: 'user.name', label: '姓名' },
|
|
244
|
-
{ value: 'user.gender', label: '性别' },
|
|
245
|
-
{ value: 'tags', label: 'tags' },
|
|
246
|
-
{ value: 'tags[0]', label: '标签项' },
|
|
247
|
-
]);
|
|
248
|
-
});
|
|
249
|
-
|
|
250
|
-
it('falls back to key when title is missing', () => {
|
|
251
|
-
const schema: NexusSchema = {
|
|
252
|
-
type: 'object',
|
|
253
|
-
properties: {
|
|
254
|
-
birthday: { type: 'string', widget: 'date' },
|
|
255
|
-
},
|
|
256
|
-
};
|
|
257
|
-
expect(collectDataFieldOptions(schema)).toEqual([
|
|
258
|
-
{ value: 'birthday', label: 'birthday' },
|
|
259
|
-
]);
|
|
260
|
-
});
|
|
261
|
-
});
|