@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.
Files changed (137) hide show
  1. package/dist/es/Canvas.js +42 -46
  2. package/dist/es/Canvas.js.map +1 -1
  3. package/dist/es/Designer.js +121 -98
  4. package/dist/es/Designer.js.map +1 -1
  5. package/dist/es/DesignerContext.js +86 -73
  6. package/dist/es/DesignerContext.js.map +1 -1
  7. package/dist/es/Palette.js +3 -3
  8. package/dist/es/Palette.js.map +1 -1
  9. package/dist/es/PropertyPanel.js +97 -97
  10. package/dist/es/PropertyPanel.js.map +1 -1
  11. package/dist/es/catalog.js +19 -11
  12. package/dist/es/catalog.js.map +1 -1
  13. package/dist/es/designer-context.js +110 -0
  14. package/dist/es/designer-context.js.map +1 -0
  15. package/dist/es/history.js +73 -0
  16. package/dist/es/history.js.map +1 -0
  17. package/dist/es/index.js +3 -3
  18. package/dist/es/property/basic-property.js +6 -0
  19. package/dist/es/property/basic-property.js.map +1 -1
  20. package/dist/es/property-panel.js +294 -0
  21. package/dist/es/property-panel.js.map +1 -0
  22. package/dist/es/resizable-panel.js +103 -0
  23. package/dist/es/resizable-panel.js.map +1 -0
  24. package/dist/es/schema-utils.js +286 -0
  25. package/dist/es/schema-utils.js.map +1 -0
  26. package/dist/es/widgets/BindEditor.js +60 -49
  27. package/dist/es/widgets/BindEditor.js.map +1 -1
  28. package/dist/es/widgets/CodeEditor.js +41 -49
  29. package/dist/es/widgets/CodeEditor.js.map +1 -1
  30. package/dist/es/widgets/DefaultEditor.js +25 -30
  31. package/dist/es/widgets/DefaultEditor.js.map +1 -1
  32. package/dist/es/widgets/DependenciesEditor.js +21 -21
  33. package/dist/es/widgets/DependenciesEditor.js.map +1 -1
  34. package/dist/es/widgets/EnumEditor.js +25 -31
  35. package/dist/es/widgets/EnumEditor.js.map +1 -1
  36. package/dist/es/widgets/ExpressionSwitch.js +32 -30
  37. package/dist/es/widgets/ExpressionSwitch.js.map +1 -1
  38. package/dist/es/widgets/ReactionsEditor.js +103 -103
  39. package/dist/es/widgets/ReactionsEditor.js.map +1 -1
  40. package/dist/es/widgets/RemoteDataEditor.js +63 -63
  41. package/dist/es/widgets/RemoteDataEditor.js.map +1 -1
  42. package/dist/es/widgets/ValidateEditor.js +49 -49
  43. package/dist/es/widgets/ValidateEditor.js.map +1 -1
  44. package/dist/es/widgets/bind-editor.js +78 -0
  45. package/dist/es/widgets/bind-editor.js.map +1 -0
  46. package/dist/es/widgets/code-editor.js +76 -0
  47. package/dist/es/widgets/code-editor.js.map +1 -0
  48. package/dist/es/widgets/default-editor.js +50 -0
  49. package/dist/es/widgets/default-editor.js.map +1 -0
  50. package/dist/es/widgets/dependencies-editor.js +36 -0
  51. package/dist/es/widgets/dependencies-editor.js.map +1 -0
  52. package/dist/es/widgets/enum-editor.js +43 -0
  53. package/dist/es/widgets/enum-editor.js.map +1 -0
  54. package/dist/es/widgets/expression-builder.js +367 -0
  55. package/dist/es/widgets/expression-builder.js.map +1 -0
  56. package/dist/es/widgets/expression-model.js +340 -0
  57. package/dist/es/widgets/expression-model.js.map +1 -0
  58. package/dist/es/widgets/expression-switch.js +49 -0
  59. package/dist/es/widgets/expression-switch.js.map +1 -0
  60. package/dist/es/widgets/index.js +13 -13
  61. package/dist/es/widgets/index.js.map +1 -1
  62. package/dist/es/widgets/options-editor.js +102 -0
  63. package/dist/es/widgets/options-editor.js.map +1 -0
  64. package/dist/es/widgets/reactions-editor.js +401 -0
  65. package/dist/es/widgets/reactions-editor.js.map +1 -0
  66. package/dist/es/widgets/reactions-model.js +107 -0
  67. package/dist/es/widgets/reactions-model.js.map +1 -0
  68. package/dist/es/widgets/remote-data-editor.js +314 -0
  69. package/dist/es/widgets/remote-data-editor.js.map +1 -0
  70. package/dist/es/widgets/use-form-data-fields.js +16 -0
  71. package/dist/es/widgets/use-form-data-fields.js.map +1 -0
  72. package/dist/es/widgets/validate-editor.js +118 -0
  73. package/dist/es/widgets/validate-editor.js.map +1 -0
  74. package/package.json +4 -5
  75. package/dist/es/react/src/components/FormController.js +0 -154
  76. package/dist/es/react/src/components/FormController.js.map +0 -1
  77. package/dist/es/react/src/components/NexusField.js +0 -99
  78. package/dist/es/react/src/components/NexusField.js.map +0 -1
  79. package/dist/es/react/src/components/NexusForm.js +0 -121
  80. package/dist/es/react/src/components/NexusForm.js.map +0 -1
  81. package/dist/es/react/src/components/NexusFormProvider.js +0 -19
  82. package/dist/es/react/src/components/NexusFormProvider.js.map +0 -1
  83. package/dist/es/react/src/components/NexusLayout.js +0 -49
  84. package/dist/es/react/src/components/NexusLayout.js.map +0 -1
  85. package/dist/es/react/src/components/NexusObject.js +0 -65
  86. package/dist/es/react/src/components/NexusObject.js.map +0 -1
  87. package/dist/es/react/src/contexts/FieldInheritContext.js +0 -6
  88. package/dist/es/react/src/contexts/FieldInheritContext.js.map +0 -1
  89. package/dist/es/react/src/contexts/GridContext.js +0 -6
  90. package/dist/es/react/src/contexts/GridContext.js.map +0 -1
  91. package/dist/es/react/src/contexts/LayoutConfigContext.js +0 -6
  92. package/dist/es/react/src/contexts/LayoutConfigContext.js.map +0 -1
  93. package/dist/es/react/src/contexts/NexusContext.js +0 -13
  94. package/dist/es/react/src/contexts/NexusContext.js.map +0 -1
  95. package/dist/es/react/src/hooks/useForm.js +0 -10
  96. package/dist/es/react/src/hooks/useForm.js.map +0 -1
  97. package/dist/es/react/src/utils/renderTreeNode.js +0 -18
  98. package/dist/es/react/src/utils/renderTreeNode.js.map +0 -1
  99. package/dist/es/react/src/utils/resolveColSpan.js +0 -10
  100. package/dist/es/react/src/utils/resolveColSpan.js.map +0 -1
  101. package/dist/es/schemaUtils.test.js +0 -188
  102. package/dist/es/schemaUtils.test.js.map +0 -1
  103. package/dist/es/vite-env.d.js +0 -2
  104. package/dist/es/vite-env.d.js.map +0 -1
  105. package/dist/es/widgets/expressionModel.test.js +0 -193
  106. package/dist/es/widgets/expressionModel.test.js.map +0 -1
  107. package/src/Canvas.tsx +0 -1111
  108. package/src/Designer.css +0 -206
  109. package/src/Designer.tsx +0 -254
  110. package/src/DesignerContext.tsx +0 -192
  111. package/src/Palette.tsx +0 -261
  112. package/src/PropertyPanel.tsx +0 -486
  113. package/src/ResizablePanel.tsx +0 -210
  114. package/src/catalog.ts +0 -526
  115. package/src/index.ts +0 -25
  116. package/src/property/basic-property.ts +0 -126
  117. package/src/schemaUtils.test.ts +0 -261
  118. package/src/schemaUtils.ts +0 -627
  119. package/src/types.ts +0 -38
  120. package/src/vite-env.d.ts +0 -1
  121. package/src/widgets/BindEditor.tsx +0 -105
  122. package/src/widgets/CodeEditor.tsx +0 -114
  123. package/src/widgets/DefaultEditor.tsx +0 -73
  124. package/src/widgets/DependenciesEditor.tsx +0 -56
  125. package/src/widgets/EnumEditor.tsx +0 -66
  126. package/src/widgets/ExpressionBuilder.tsx +0 -509
  127. package/src/widgets/ExpressionSwitch.tsx +0 -62
  128. package/src/widgets/OptionsEditor.tsx +0 -141
  129. package/src/widgets/ReactionsEditor.tsx +0 -532
  130. package/src/widgets/RemoteDataEditor.tsx +0 -382
  131. package/src/widgets/ValidateEditor.tsx +0 -162
  132. package/src/widgets/expressionModel.test.ts +0 -262
  133. package/src/widgets/expressionModel.ts +0 -573
  134. package/src/widgets/index.ts +0 -45
  135. package/src/widgets/reactionsModel.ts +0 -190
  136. package/src/widgets/useFormDataFields.ts +0 -21
  137. /package/dist/es/{form-engine-designer.css → index.css} +0 -0
@@ -1,262 +0,0 @@
1
- import type { NexusSchema } from '@xbeeant/form-engine';
2
- import { describe, expect, it } from 'vitest';
3
- import { collectDataFieldPaths } from '../schemaUtils';
4
- import {
5
- buildExpression,
6
- type ConditionOperator,
7
- parseExpression,
8
- parseVariable,
9
- stripBraces,
10
- variableToString,
11
- } from './expressionModel';
12
-
13
- describe('buildExpression', () => {
14
- it('构建基本比较表达式(文本 / 数字 / 布尔 / 变量右值)', () => {
15
- expect(
16
- buildExpression([
17
- {
18
- id: '1',
19
- logic: 'and',
20
- variable: { source: 'formData', path: 'usePromo' },
21
- operator: 'eq',
22
- rightMode: 'boolean',
23
- right: 'true',
24
- },
25
- ]),
26
- ).toBe('{{ formData.usePromo === true }}');
27
-
28
- expect(
29
- buildExpression([
30
- {
31
- id: '1',
32
- logic: 'and',
33
- variable: { source: 'formData', path: 'amount' },
34
- operator: 'gte',
35
- rightMode: 'number',
36
- right: '100',
37
- },
38
- ]),
39
- ).toBe('{{ formData.amount >= 100 }}');
40
-
41
- expect(
42
- buildExpression([
43
- {
44
- id: '1',
45
- logic: 'and',
46
- variable: { source: 'self', path: '' },
47
- operator: 'neq',
48
- rightMode: 'string',
49
- right: 'special',
50
- },
51
- ]),
52
- ).toBe("{{ $self.value !== 'special' }}");
53
-
54
- expect(
55
- buildExpression([
56
- {
57
- id: '1',
58
- logic: 'and',
59
- variable: { source: 'formData', path: 'amount' },
60
- operator: 'eq',
61
- rightMode: 'variable',
62
- right: 'formData.limit',
63
- },
64
- ]),
65
- ).toBe('{{ formData.amount === formData.limit }}');
66
- });
67
-
68
- it('空右值 / 未选变量视为不完整条件,返回空模板', () => {
69
- expect(
70
- buildExpression([
71
- {
72
- id: '1',
73
- logic: 'and',
74
- variable: { source: 'formData', path: '' },
75
- operator: 'eq',
76
- rightMode: 'string',
77
- right: 'x',
78
- },
79
- ]),
80
- ).toBe('{{ }}');
81
-
82
- expect(
83
- buildExpression([
84
- {
85
- id: '1',
86
- logic: 'and',
87
- variable: { source: 'formData', path: 'a' },
88
- operator: 'eq',
89
- rightMode: 'string',
90
- right: '',
91
- },
92
- ]),
93
- ).toBe('{{ }}');
94
- });
95
-
96
- it('无条件时返回空模板', () => {
97
- expect(buildExpression([])).toBe('{{ }}');
98
- });
99
-
100
- it('按 and/or 连接多条条件', () => {
101
- const cond = (op: 'eq' | 'neq', right: string) => ({
102
- id: Math.random().toString(),
103
- logic: 'and' as const,
104
- variable: { source: 'formData' as const, path: 'a' },
105
- operator: op,
106
- rightMode: 'string' as const,
107
- right,
108
- });
109
- const c1 = { ...cond('eq', 'x'), id: '1' };
110
- const c2 = { ...cond('neq', 'y'), id: '2', logic: 'or' as const };
111
- expect(buildExpression([c1, c2])).toBe(
112
- "{{ formData.a === 'x' || formData.a !== 'y' }}",
113
- );
114
- });
115
-
116
- it('contains / startsWith / empty / truthy 等操作符', () => {
117
- const base = (operator: ConditionOperator, right = '') => ({
118
- id: '1',
119
- logic: 'and' as const,
120
- variable: { source: 'formData' as const, path: 'code' },
121
- operator,
122
- rightMode: 'string' as const,
123
- right,
124
- });
125
- expect(buildExpression([base('contains', 'CN')])).toBe(
126
- "{{ String(formData.code).includes('CN') }}",
127
- );
128
- expect(buildExpression([base('notEmpty')])).toBe(
129
- "{{ (formData.code != null && String(formData.code).trim() !== '') }}",
130
- );
131
- expect(buildExpression([base('truthy')])).toBe('{{ !!(formData.code) }}');
132
- });
133
- });
134
-
135
- describe('parseExpression', () => {
136
- it('解析基本表达式为行模型', () => {
137
- const conds = parseExpression('{{ formData.usePromo === true }}');
138
- expect(conds).not.toBeNull();
139
- expect(conds![0]).toMatchObject({
140
- variable: { source: 'formData', path: 'usePromo' },
141
- operator: 'eq',
142
- rightMode: 'boolean',
143
- right: 'true',
144
- });
145
- });
146
-
147
- it('解析 $deps / $self / 文本字面量', () => {
148
- const conds = parseExpression('{{ $deps[0] === true }}');
149
- expect(conds![0].variable).toEqual({ source: 'deps', path: '0' });
150
-
151
- const self = parseExpression("{{ $self.value === 'x' }}");
152
- expect(self![0].variable).toEqual({ source: 'self', path: '' });
153
- expect(self![0].rightMode).toBe('string');
154
- expect(self![0].right).toBe('x');
155
- });
156
-
157
- it('解析 and/or 连接', () => {
158
- const conds = parseExpression(
159
- "{{ formData.a === 'x' && formData.b > 3 || formData.c == 'y' }}",
160
- );
161
- expect(conds!.length).toBe(3);
162
- expect(conds![0].logic).toBe('and');
163
- expect(conds![1].logic).toBe('and');
164
- expect(conds![2].logic).toBe('or');
165
- });
166
-
167
- it('解析空模板 / 空串为 []', () => {
168
- expect(parseExpression('{{ }}')).toEqual([]);
169
- expect(parseExpression('')).toEqual([]);
170
- expect(parseExpression(undefined)).toEqual([]);
171
- });
172
-
173
- it('无法解析的表达式返回 null(回退高级模式)', () => {
174
- expect(parseExpression('{{ formData.a.toUpperCase() }}')).toBeNull();
175
- expect(parseExpression('{{ $deps[0] + 1 > 2 }}')).toBeNull();
176
- });
177
-
178
- it('round-trip:build → parse → build 保持一致', () => {
179
- const src = "{{ formData.a === 'x' || formData.b >= 3 }}";
180
- const conds = parseExpression(src)!;
181
- expect(conds.length).toBe(2);
182
- const rebuilt = buildExpression(conds);
183
- expect(rebuilt).toBe(src);
184
- });
185
- });
186
-
187
- describe('变量工具', () => {
188
- it('stripBraces 去除包裹', () => {
189
- expect(stripBraces('{{ a === 1 }}')).toBe('a === 1');
190
- expect(stripBraces('a === 1')).toBe('a === 1');
191
- });
192
-
193
- it('variableToString 各来源', () => {
194
- expect(variableToString({ source: 'formData', path: 'user.name' })).toBe(
195
- 'formData.user.name',
196
- );
197
- expect(variableToString({ source: 'deps', path: '2' })).toBe('$deps[2]');
198
- expect(variableToString({ source: 'self', path: '' })).toBe('$self.value');
199
- expect(variableToString({ source: 'index', path: '' })).toBe('$index');
200
- expect(variableToString({ source: 'root', path: '' })).toBe('rootValue');
201
- });
202
-
203
- it('parseVariable 非标识符字段用括号访问', () => {
204
- expect(parseVariable("formData['a-b']")).toEqual({
205
- source: 'formData',
206
- path: 'a-b',
207
- });
208
- expect(variableToString(parseVariable("formData['a-b']"))).toBe(
209
- "formData['a-b']",
210
- );
211
- });
212
- });
213
-
214
- describe('collectDataFieldPaths', () => {
215
- it('布局节点 Key 不进路径,对象 / 数组透传', () => {
216
- const schema = {
217
- type: 'object',
218
- properties: {
219
- card: {
220
- type: 'card',
221
- title: '卡片',
222
- properties: {
223
- name: { type: 'string', widget: 'input', title: '姓名' },
224
- address: {
225
- type: 'object',
226
- properties: {
227
- city: { type: 'string', widget: 'input' },
228
- },
229
- },
230
- tags: {
231
- type: 'array',
232
- widget: 'list',
233
- items: {
234
- type: 'object',
235
- properties: {
236
- label: { type: 'string', widget: 'input' },
237
- },
238
- },
239
- },
240
- },
241
- },
242
- },
243
- } as unknown as NexusSchema;
244
-
245
- expect(collectDataFieldPaths(schema)).toEqual([
246
- 'name',
247
- 'address.city',
248
- 'tags',
249
- 'tags[0].label',
250
- ]);
251
- });
252
-
253
- it('子表单(带 widget 的 object)视为叶子字段', () => {
254
- const schema = {
255
- type: 'object',
256
- properties: {
257
- sub: { type: 'object', widget: 'subForm', properties: {} },
258
- },
259
- } as unknown as NexusSchema;
260
- expect(collectDataFieldPaths(schema)).toEqual(['sub']);
261
- });
262
- });