@xbeeant/form-engine-designer 0.0.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.
Files changed (117) hide show
  1. package/README.md +69 -0
  2. package/dist/es/Canvas.js +636 -0
  3. package/dist/es/Canvas.js.map +1 -0
  4. package/dist/es/Designer.js +162 -0
  5. package/dist/es/Designer.js.map +1 -0
  6. package/dist/es/DesignerContext.js +97 -0
  7. package/dist/es/DesignerContext.js.map +1 -0
  8. package/dist/es/Palette.js +148 -0
  9. package/dist/es/Palette.js.map +1 -0
  10. package/dist/es/PropertyPanel.js +294 -0
  11. package/dist/es/PropertyPanel.js.map +1 -0
  12. package/dist/es/ResizablePanel.js +103 -0
  13. package/dist/es/ResizablePanel.js.map +1 -0
  14. package/dist/es/catalog.js +514 -0
  15. package/dist/es/catalog.js.map +1 -0
  16. package/dist/es/form-engine-designer.css +1 -0
  17. package/dist/es/index.js +20 -0
  18. package/dist/es/index.js.map +1 -0
  19. package/dist/es/property/basic-property.js +115 -0
  20. package/dist/es/property/basic-property.js.map +1 -0
  21. package/dist/es/react/src/components/FormController.js +154 -0
  22. package/dist/es/react/src/components/FormController.js.map +1 -0
  23. package/dist/es/react/src/components/NexusField.js +99 -0
  24. package/dist/es/react/src/components/NexusField.js.map +1 -0
  25. package/dist/es/react/src/components/NexusForm.js +121 -0
  26. package/dist/es/react/src/components/NexusForm.js.map +1 -0
  27. package/dist/es/react/src/components/NexusFormProvider.js +19 -0
  28. package/dist/es/react/src/components/NexusFormProvider.js.map +1 -0
  29. package/dist/es/react/src/components/NexusLayout.js +49 -0
  30. package/dist/es/react/src/components/NexusLayout.js.map +1 -0
  31. package/dist/es/react/src/components/NexusObject.js +65 -0
  32. package/dist/es/react/src/components/NexusObject.js.map +1 -0
  33. package/dist/es/react/src/contexts/FieldInheritContext.js +6 -0
  34. package/dist/es/react/src/contexts/FieldInheritContext.js.map +1 -0
  35. package/dist/es/react/src/contexts/GridContext.js +6 -0
  36. package/dist/es/react/src/contexts/GridContext.js.map +1 -0
  37. package/dist/es/react/src/contexts/LayoutConfigContext.js +6 -0
  38. package/dist/es/react/src/contexts/LayoutConfigContext.js.map +1 -0
  39. package/dist/es/react/src/contexts/NexusContext.js +13 -0
  40. package/dist/es/react/src/contexts/NexusContext.js.map +1 -0
  41. package/dist/es/react/src/hooks/useForm.js +10 -0
  42. package/dist/es/react/src/hooks/useForm.js.map +1 -0
  43. package/dist/es/react/src/utils/renderTreeNode.js +18 -0
  44. package/dist/es/react/src/utils/renderTreeNode.js.map +1 -0
  45. package/dist/es/react/src/utils/resolveColSpan.js +10 -0
  46. package/dist/es/react/src/utils/resolveColSpan.js.map +1 -0
  47. package/dist/es/schemaUtils.js +286 -0
  48. package/dist/es/schemaUtils.js.map +1 -0
  49. package/dist/es/schemaUtils.test.js +188 -0
  50. package/dist/es/schemaUtils.test.js.map +1 -0
  51. package/dist/es/types.js +2 -0
  52. package/dist/es/types.js.map +1 -0
  53. package/dist/es/vite-env.d.js +2 -0
  54. package/dist/es/vite-env.d.js.map +1 -0
  55. package/dist/es/widgets/BindEditor.js +67 -0
  56. package/dist/es/widgets/BindEditor.js.map +1 -0
  57. package/dist/es/widgets/CodeEditor.js +84 -0
  58. package/dist/es/widgets/CodeEditor.js.map +1 -0
  59. package/dist/es/widgets/DefaultEditor.js +55 -0
  60. package/dist/es/widgets/DefaultEditor.js.map +1 -0
  61. package/dist/es/widgets/DependenciesEditor.js +36 -0
  62. package/dist/es/widgets/DependenciesEditor.js.map +1 -0
  63. package/dist/es/widgets/EnumEditor.js +49 -0
  64. package/dist/es/widgets/EnumEditor.js.map +1 -0
  65. package/dist/es/widgets/ExpressionBuilder.js +367 -0
  66. package/dist/es/widgets/ExpressionBuilder.js.map +1 -0
  67. package/dist/es/widgets/ExpressionSwitch.js +47 -0
  68. package/dist/es/widgets/ExpressionSwitch.js.map +1 -0
  69. package/dist/es/widgets/OptionsEditor.js +102 -0
  70. package/dist/es/widgets/OptionsEditor.js.map +1 -0
  71. package/dist/es/widgets/ReactionsEditor.js +401 -0
  72. package/dist/es/widgets/ReactionsEditor.js.map +1 -0
  73. package/dist/es/widgets/RemoteDataEditor.js +314 -0
  74. package/dist/es/widgets/RemoteDataEditor.js.map +1 -0
  75. package/dist/es/widgets/ValidateEditor.js +118 -0
  76. package/dist/es/widgets/ValidateEditor.js.map +1 -0
  77. package/dist/es/widgets/expressionModel.js +340 -0
  78. package/dist/es/widgets/expressionModel.js.map +1 -0
  79. package/dist/es/widgets/expressionModel.test.js +193 -0
  80. package/dist/es/widgets/expressionModel.test.js.map +1 -0
  81. package/dist/es/widgets/index.js +57 -0
  82. package/dist/es/widgets/index.js.map +1 -0
  83. package/dist/es/widgets/reactionsModel.js +107 -0
  84. package/dist/es/widgets/reactionsModel.js.map +1 -0
  85. package/dist/es/widgets/useFormDataFields.js +16 -0
  86. package/dist/es/widgets/useFormDataFields.js.map +1 -0
  87. package/package.json +62 -0
  88. package/src/Canvas.tsx +1111 -0
  89. package/src/Designer.css +206 -0
  90. package/src/Designer.tsx +254 -0
  91. package/src/DesignerContext.tsx +192 -0
  92. package/src/Palette.tsx +261 -0
  93. package/src/PropertyPanel.tsx +486 -0
  94. package/src/ResizablePanel.tsx +210 -0
  95. package/src/catalog.ts +526 -0
  96. package/src/index.ts +25 -0
  97. package/src/property/basic-property.ts +126 -0
  98. package/src/schemaUtils.test.ts +261 -0
  99. package/src/schemaUtils.ts +627 -0
  100. package/src/types.ts +38 -0
  101. package/src/vite-env.d.ts +1 -0
  102. package/src/widgets/BindEditor.tsx +105 -0
  103. package/src/widgets/CodeEditor.tsx +114 -0
  104. package/src/widgets/DefaultEditor.tsx +73 -0
  105. package/src/widgets/DependenciesEditor.tsx +56 -0
  106. package/src/widgets/EnumEditor.tsx +66 -0
  107. package/src/widgets/ExpressionBuilder.tsx +509 -0
  108. package/src/widgets/ExpressionSwitch.tsx +62 -0
  109. package/src/widgets/OptionsEditor.tsx +141 -0
  110. package/src/widgets/ReactionsEditor.tsx +532 -0
  111. package/src/widgets/RemoteDataEditor.tsx +382 -0
  112. package/src/widgets/ValidateEditor.tsx +162 -0
  113. package/src/widgets/expressionModel.test.ts +262 -0
  114. package/src/widgets/expressionModel.ts +573 -0
  115. package/src/widgets/index.ts +45 -0
  116. package/src/widgets/reactionsModel.ts +190 -0
  117. package/src/widgets/useFormDataFields.ts +21 -0
package/src/catalog.ts ADDED
@@ -0,0 +1,526 @@
1
+ // ============================================================================
2
+ // @xbeeant/form-engine-designer — 组件目录
3
+ // ============================================================================
4
+
5
+ import type { CatalogItem } from './types';
6
+
7
+ /**
8
+ * 表单组件目录
9
+ * 每个项创建一个 DataFieldSchema 节点
10
+ * widget 名对齐 @xbeeant/form-engine-ui 中 antdWidgets 实际注册的 key
11
+ */
12
+ export const widgetCatalog: CatalogItem[] = [
13
+ {
14
+ label: '输入框',
15
+ icon: '📝',
16
+ category: 'widget',
17
+ widget: 'input',
18
+ createNode: () => ({ type: 'string', widget: 'input', title: '输入框' }),
19
+ },
20
+ {
21
+ label: '密码框',
22
+ icon: '🔑',
23
+ category: 'widget',
24
+ widget: 'password',
25
+ createNode: () => ({ type: 'string', widget: 'password', title: '密码框' }),
26
+ },
27
+ {
28
+ label: '数字输入',
29
+ icon: '🔢',
30
+ category: 'widget',
31
+ widget: 'number',
32
+ createNode: () => ({ type: 'number', widget: 'number', title: '数字输入' }),
33
+ },
34
+ {
35
+ label: '文本域',
36
+ icon: '📄',
37
+ category: 'widget',
38
+ widget: 'textarea',
39
+ createNode: () => ({ type: 'string', widget: 'textarea', title: '文本域' }),
40
+ },
41
+ {
42
+ label: '下拉选择',
43
+ icon: '📋',
44
+ category: 'widget',
45
+ widget: 'select',
46
+ createNode: () => ({
47
+ type: 'string',
48
+ widget: 'select',
49
+ title: '下拉选择',
50
+ enum: ['option1', 'option2'],
51
+ enumNames: ['选项1', '选项2'],
52
+ }),
53
+ },
54
+ {
55
+ label: '下拉选择(远程)',
56
+ icon: '📡',
57
+ category: 'widget',
58
+ widget: 'selectWithRemote',
59
+ createNode: () => ({
60
+ type: 'string',
61
+ widget: 'selectWithRemote',
62
+ title: '下拉选择(远程)',
63
+ remoteData: {
64
+ url: '/api/options',
65
+ method: 'GET',
66
+ responseField: { data: 'data.list', value: 'id', label: 'name' },
67
+ params: { page: 1, pageSize: 50 },
68
+ },
69
+ }),
70
+ },
71
+ {
72
+ label: '单选',
73
+ icon: '🔘',
74
+ category: 'widget',
75
+ widget: 'radio',
76
+ createNode: () => ({
77
+ type: 'string',
78
+ widget: 'radio',
79
+ title: '单选',
80
+ enum: ['a', 'b'],
81
+ enumNames: ['选项A', '选项B'],
82
+ }),
83
+ },
84
+ {
85
+ label: '复选框',
86
+ icon: '☑️',
87
+ category: 'widget',
88
+ widget: 'checkbox',
89
+ createNode: () => ({
90
+ type: 'boolean',
91
+ widget: 'checkbox',
92
+ title: '复选框',
93
+ }),
94
+ },
95
+ {
96
+ label: '多选',
97
+ icon: '☒',
98
+ category: 'widget',
99
+ widget: 'checkboxes',
100
+ createNode: () => ({
101
+ type: 'array',
102
+ widget: 'checkboxes',
103
+ title: '多选',
104
+ enum: ['a', 'b'],
105
+ enumNames: ['选项A', '选项B'],
106
+ }),
107
+ },
108
+ {
109
+ label: '多选下拉',
110
+ icon: '📊',
111
+ category: 'widget',
112
+ widget: 'multiSelect',
113
+ createNode: () => ({
114
+ type: 'array',
115
+ widget: 'multiSelect',
116
+ title: '多选下拉',
117
+ enum: ['a', 'b'],
118
+ enumNames: ['选项A', '选项B'],
119
+ }),
120
+ },
121
+ {
122
+ label: '多选下拉(远程)',
123
+ icon: '📡',
124
+ category: 'widget',
125
+ widget: 'multiSelectWithRemote',
126
+ createNode: () => ({
127
+ type: 'array',
128
+ widget: 'multiSelectWithRemote',
129
+ title: '多选下拉(远程)',
130
+ remoteData: {
131
+ url: '/api/multi-options',
132
+ method: 'GET',
133
+ responseField: { data: 'data.list', value: 'id', label: 'name' },
134
+ params: { page: 1, pageSize: 50 },
135
+ },
136
+ }),
137
+ },
138
+ {
139
+ label: '开关',
140
+ icon: '🔀',
141
+ category: 'widget',
142
+ widget: 'switch',
143
+ createNode: () => ({ type: 'boolean', widget: 'switch', title: '开关' }),
144
+ },
145
+ {
146
+ label: '日期选择',
147
+ icon: '📅',
148
+ category: 'widget',
149
+ widget: 'date',
150
+ createNode: () => ({ type: 'string', widget: 'date', title: '日期选择' }),
151
+ },
152
+ {
153
+ label: '日期范围',
154
+ icon: '📅',
155
+ category: 'widget',
156
+ widget: 'dateRange',
157
+ createNode: () => ({
158
+ type: 'string',
159
+ widget: 'dateRange',
160
+ title: '日期范围',
161
+ }),
162
+ },
163
+ {
164
+ label: '时间选择',
165
+ icon: '⏰',
166
+ category: 'widget',
167
+ widget: 'time',
168
+ createNode: () => ({ type: 'string', widget: 'time', title: '时间选择' }),
169
+ },
170
+ {
171
+ label: '时间范围',
172
+ icon: '⏰',
173
+ category: 'widget',
174
+ widget: 'timeRange',
175
+ createNode: () => ({
176
+ type: 'string',
177
+ widget: 'timeRange',
178
+ title: '时间范围',
179
+ }),
180
+ },
181
+ {
182
+ label: '滑块',
183
+ icon: '🎚️',
184
+ category: 'widget',
185
+ widget: 'slider',
186
+ createNode: () => ({ type: 'number', widget: 'slider', title: '滑块' }),
187
+ },
188
+ {
189
+ label: '颜色选择',
190
+ icon: '🎨',
191
+ category: 'widget',
192
+ widget: 'color',
193
+ createNode: () => ({ type: 'string', widget: 'color', title: '颜色选择' }),
194
+ },
195
+ {
196
+ label: 'URL输入',
197
+ icon: '🔗',
198
+ category: 'widget',
199
+ widget: 'urlInput',
200
+ createNode: () => ({
201
+ type: 'string',
202
+ widget: 'urlInput',
203
+ title: 'URL输入',
204
+ }),
205
+ },
206
+ {
207
+ label: '图片上传',
208
+ icon: '🖼️',
209
+ category: 'widget',
210
+ widget: 'image',
211
+ createNode: () => ({ type: 'string', widget: 'image', title: '图片上传' }),
212
+ },
213
+ {
214
+ label: 'HTML展示',
215
+ icon: '📄',
216
+ category: 'widget',
217
+ widget: 'html',
218
+ createNode: () => ({ type: 'string', widget: 'html', title: 'HTML展示' }),
219
+ },
220
+ {
221
+ label: '标题文字',
222
+ icon: '🏷️',
223
+ category: 'widget',
224
+ widget: 'voidTitle',
225
+ createNode: () => ({
226
+ type: 'string',
227
+ widget: 'voidTitle',
228
+ title: '标题文字',
229
+ }),
230
+ },
231
+ {
232
+ label: '树选择',
233
+ icon: '🌲',
234
+ category: 'widget',
235
+ widget: 'treeSelect',
236
+ createNode: () => ({
237
+ type: 'string',
238
+ widget: 'treeSelect',
239
+ title: '树选择',
240
+ }),
241
+ },
242
+ {
243
+ label: '自动完成',
244
+ icon: '🔎',
245
+ category: 'widget',
246
+ widget: 'autoComplete',
247
+ createNode: () => ({
248
+ type: 'string',
249
+ widget: 'autoComplete',
250
+ title: '自动完成',
251
+ enum: ['option1', 'option2'],
252
+ enumNames: ['选项1', '选项2'],
253
+ }),
254
+ },
255
+ {
256
+ label: '自动完成(远程)',
257
+ icon: '📡',
258
+ category: 'widget',
259
+ widget: 'autoCompleteWithRemote',
260
+ createNode: () => ({
261
+ type: 'string',
262
+ widget: 'autoCompleteWithRemote',
263
+ title: '自动完成(远程)',
264
+ remoteData: {
265
+ url: '/api/suggestions',
266
+ method: 'GET',
267
+ responseField: { data: 'data.suggestions', value: 'id', label: 'name' },
268
+ params: { keyword: '' },
269
+ },
270
+ }),
271
+ },
272
+ {
273
+ label: '级联选择',
274
+ icon: '🌳',
275
+ category: 'widget',
276
+ widget: 'cascader',
277
+ createNode: () => ({
278
+ type: 'array',
279
+ widget: 'cascader',
280
+ title: '级联选择',
281
+ enum: ['a', 'b'],
282
+ enumNames: ['选项A', '选项B'],
283
+ }),
284
+ },
285
+ {
286
+ label: '级联选择(远程)',
287
+ icon: '📡',
288
+ category: 'widget',
289
+ widget: 'cascaderWithRemote',
290
+ createNode: () => ({
291
+ type: 'array',
292
+ widget: 'cascaderWithRemote',
293
+ title: '级联选择(远程)',
294
+ remoteData: {
295
+ url: '/api/cascader/nodes',
296
+ method: 'GET',
297
+ responseField: {
298
+ data: 'data.children',
299
+ value: 'id',
300
+ label: 'name',
301
+ parentIdKey: 'parentId',
302
+ },
303
+ params: { parentId: null },
304
+ },
305
+ }),
306
+ },
307
+ {
308
+ label: '提及',
309
+ icon: '💬',
310
+ category: 'widget',
311
+ widget: 'mentions',
312
+ createNode: () => ({
313
+ type: 'string',
314
+ widget: 'mentions',
315
+ title: '提及',
316
+ enum: ['alice', 'bob'],
317
+ enumNames: ['Alice', 'Bob'],
318
+ }),
319
+ },
320
+ {
321
+ label: '提及(远程)',
322
+ icon: '📡',
323
+ category: 'widget',
324
+ widget: 'mentionsWithRemote',
325
+ createNode: () => ({
326
+ type: 'string',
327
+ widget: 'mentionsWithRemote',
328
+ title: '提及(远程)',
329
+ remoteData: {
330
+ url: '/api/users/suggestions',
331
+ method: 'GET',
332
+ responseField: { data: 'data.users', value: 'id', label: 'name' },
333
+ params: { keyword: '' },
334
+ },
335
+ }),
336
+ },
337
+ {
338
+ label: '分段控制器',
339
+ icon: '🎚️',
340
+ category: 'widget',
341
+ widget: 'segmented',
342
+ createNode: () => ({
343
+ type: 'string',
344
+ widget: 'segmented',
345
+ title: '分段控制器',
346
+ enum: ['a', 'b'],
347
+ enumNames: ['选项A', '选项B'],
348
+ }),
349
+ },
350
+ {
351
+ label: '穿梭框',
352
+ icon: '⇄',
353
+ category: 'widget',
354
+ widget: 'transfer',
355
+ createNode: () => ({
356
+ type: 'array',
357
+ widget: 'transfer',
358
+ title: '穿梭框',
359
+ }),
360
+ },
361
+ {
362
+ label: '文件上传',
363
+ icon: '📎',
364
+ category: 'widget',
365
+ widget: 'file',
366
+ createNode: () => ({ type: 'array', widget: 'file', title: '文件上传' }),
367
+ },
368
+ {
369
+ label: '数据对象',
370
+ icon: '🗂️',
371
+ category: 'widget',
372
+ widget: 'object',
373
+ createNode: () => ({ type: 'object', title: '数据对象', properties: {} }),
374
+ },
375
+ {
376
+ label: '常规列表',
377
+ icon: '📋',
378
+ category: 'widget',
379
+ widget: 'list',
380
+ createNode: () => ({
381
+ type: 'array',
382
+ widget: 'list',
383
+ title: '常规列表',
384
+ items: {
385
+ type: 'object',
386
+ properties: {},
387
+ },
388
+ }),
389
+ },
390
+ {
391
+ label: '简单列表',
392
+ icon: '📃',
393
+ category: 'widget',
394
+ widget: 'simpleList',
395
+ createNode: () => ({
396
+ type: 'array',
397
+ widget: 'simpleList',
398
+ title: '简单列表',
399
+ items: {
400
+ type: 'object',
401
+ properties: {},
402
+ },
403
+ }),
404
+ },
405
+ {
406
+ label: '表格列表',
407
+ icon: '📊',
408
+ category: 'widget',
409
+ widget: 'tableList',
410
+ createNode: () => ({
411
+ type: 'array',
412
+ widget: 'tableList',
413
+ title: '表格列表',
414
+ items: {
415
+ type: 'object',
416
+ properties: {},
417
+ },
418
+ }),
419
+ },
420
+ ];
421
+
422
+ /**
423
+ * 布局组件目录
424
+ * 每个项创建一个 LayoutContainerSchema 节点
425
+ */
426
+ export const layoutCatalog: CatalogItem[] = [
427
+ {
428
+ label: '卡片',
429
+ icon: '📦',
430
+ category: 'layout',
431
+ layoutType: 'card',
432
+ createNode: () => ({ type: 'card', title: '卡片', properties: {} }),
433
+ },
434
+ {
435
+ label: '栅格',
436
+ icon: '🔲',
437
+ category: 'layout',
438
+ layoutType: 'grid',
439
+ createNode: () => ({ type: 'grid', column: 2, properties: {} }),
440
+ },
441
+ {
442
+ label: '标签页',
443
+ icon: '📑',
444
+ category: 'layout',
445
+ layoutType: 'tabs',
446
+ createNode: () => ({
447
+ type: 'tabs',
448
+ title: '标签页',
449
+ properties: {
450
+ pane1: { type: 'tabPane', title: '标签页签 1', properties: {} },
451
+ },
452
+ }),
453
+ },
454
+ {
455
+ label: '标签页签',
456
+ icon: '📑',
457
+ category: 'layout',
458
+ layoutType: 'tabPane',
459
+ createNode: () => ({ type: 'tabPane', title: '标签页签', properties: {} }),
460
+ },
461
+ {
462
+ label: '折叠面板',
463
+ icon: '📂',
464
+ category: 'layout',
465
+ layoutType: 'collapse',
466
+ createNode: () => ({
467
+ type: 'collapse',
468
+ title: '折叠面板',
469
+ properties: {
470
+ panel1: { type: 'collapsePanel', title: '折叠面板 1', properties: {} },
471
+ },
472
+ }),
473
+ },
474
+ {
475
+ label: '折叠面板项',
476
+ icon: '📂',
477
+ category: 'layout',
478
+ layoutType: 'collapsePanel',
479
+ createNode: () => ({
480
+ type: 'collapsePanel',
481
+ title: '折叠面板项',
482
+ properties: {},
483
+ }),
484
+ },
485
+ {
486
+ label: '步骤条',
487
+ icon: '📝',
488
+ category: 'layout',
489
+ layoutType: 'steps',
490
+ createNode: () => ({
491
+ type: 'steps',
492
+ title: '步骤条',
493
+ properties: {
494
+ step1: { type: 'step', title: '步骤 1', properties: {} },
495
+ },
496
+ }),
497
+ },
498
+ {
499
+ label: '步骤项',
500
+ icon: '📝',
501
+ category: 'layout',
502
+ layoutType: 'step',
503
+ createNode: () => ({ type: 'step', title: '步骤项', properties: {} }),
504
+ },
505
+ {
506
+ label: '分割线',
507
+ icon: '➖',
508
+ category: 'layout',
509
+ layoutType: 'divider',
510
+ createNode: () => ({ type: 'divider', properties: {} }),
511
+ },
512
+ {
513
+ label: '弹性布局',
514
+ icon: '📐',
515
+ category: 'layout',
516
+ layoutType: 'flex',
517
+ createNode: () => ({ type: 'flex', properties: {} }),
518
+ },
519
+ {
520
+ label: '间距布局',
521
+ icon: '↔️',
522
+ category: 'layout',
523
+ layoutType: 'space',
524
+ createNode: () => ({ type: 'space', properties: {} }),
525
+ },
526
+ ];
package/src/index.ts ADDED
@@ -0,0 +1,25 @@
1
+ // ============================================================================
2
+ // @xbeeant/form-engine-designer — 公共 API
3
+ // ============================================================================
4
+
5
+ export { layoutCatalog, widgetCatalog } from './catalog';
6
+ export type { DesignerProps } from './Designer';
7
+ export { Designer } from './Designer';
8
+ export type { DesignerContextValue } from './DesignerContext';
9
+ export { DesignerProvider, useDesigner } from './DesignerContext';
10
+ export {
11
+ addChildToSchema,
12
+ collectDataFieldOptions,
13
+ collectDataFieldPaths,
14
+ flattenNodeForPropertyEditor,
15
+ getNodeAtProperties,
16
+ removeNodeFromSchema,
17
+ updateNodeInSchema,
18
+ updateNodeWithNesting,
19
+ } from './schemaUtils';
20
+ export type {
21
+ CatalogItem,
22
+ DesignerMode,
23
+ FieldDef,
24
+ SchemaPath,
25
+ } from './types';
@@ -0,0 +1,126 @@
1
+ import type { SchemaNode } from '@xbeeant/form-engine';
2
+
3
+ // ============================================================================
4
+ // 属性面板各分组的字段定义(扁平结构,由 PropertyPanel 包裹进 collapse 分组)
5
+ // ============================================================================
6
+
7
+ // ── 通用属性 ──────────────────────────────────────────────────────────────
8
+ export const commonPropertyFields: Record<string, SchemaNode> = {
9
+ title: {
10
+ widget: 'input',
11
+ type: 'string',
12
+ title: '标题(title)',
13
+ },
14
+ description: {
15
+ widget: 'textarea',
16
+ type: 'string',
17
+ title: '描述(description)',
18
+ },
19
+ placeholder: {
20
+ widget: 'input',
21
+ type: 'string',
22
+ title: '占位提示(placeholder)',
23
+ },
24
+ default: {
25
+ widget: 'input',
26
+ type: 'string',
27
+ title: '默认值(default)',
28
+ },
29
+ extra: {
30
+ widget: 'input',
31
+ type: 'string',
32
+ title: '额外说明(extra)',
33
+ },
34
+ // ── 状态控制 ────────────────────────────────────────────────────────────
35
+ disabled: {
36
+ widget: 'propertyExpr',
37
+ type: 'string',
38
+ title: '禁用(disabled)',
39
+ },
40
+ readOnly: {
41
+ widget: 'propertyExpr',
42
+ type: 'string',
43
+ title: '只读(readOnly)',
44
+ },
45
+ readOnlyWidget: {
46
+ widget: 'input',
47
+ type: 'string',
48
+ title: '只读渲染组件(readOnlyWidget)',
49
+ placeholder: '如 html,未配置时沿用只读文本渲染',
50
+ },
51
+ hidden: {
52
+ widget: 'propertyExpr',
53
+ type: 'string',
54
+ title: '隐藏(hidden)',
55
+ },
56
+ // ── 布局尺寸(x-render 对齐)──────────────────────────────────────────
57
+ width: {
58
+ widget: 'input',
59
+ type: 'string',
60
+ title: '单元素宽度(width)',
61
+ placeholder: '如 20%',
62
+ },
63
+ colSpan: {
64
+ widget: 'number',
65
+ type: 'number',
66
+ title: '栅格跨度(colSpan)',
67
+ placeholder: 'grid 列数的整数倍',
68
+ },
69
+ };
70
+
71
+ // ── 校验配置 ──────────────────────────────────────────────────────────────
72
+ // 字段级约束(pattern/min/max)由 SchemaParser 自动转换为 ValidationRule;
73
+ // 完整的 rules 数组可通过「Schema」标签页直接编辑 JSON。
74
+ export const validationPropertyFields: Record<string, SchemaNode> = {
75
+ required: {
76
+ widget: 'propertyExpr',
77
+ type: 'string',
78
+ title: '必填(required)',
79
+ },
80
+ pattern: {
81
+ widget: 'input',
82
+ type: 'string',
83
+ title: '正则校验(pattern)',
84
+ placeholder: '如 ^1[3-9]\\d{9}$',
85
+ },
86
+ min: {
87
+ widget: 'number',
88
+ type: 'number',
89
+ title: '最小值/最小长度(min)',
90
+ placeholder: 'number→数值 / string→长度 / array→项数',
91
+ },
92
+ max: {
93
+ widget: 'number',
94
+ type: 'number',
95
+ title: '最大值/最大长度(max)',
96
+ placeholder: 'number→数值 / string→长度 / array→项数',
97
+ },
98
+ validate: {
99
+ widget: 'propertyValidate',
100
+ type: 'string',
101
+ title: '跨字段校验(validate)',
102
+ },
103
+ };
104
+
105
+ // ── 依赖配置 ──────────────────────────────────────────────────────────────
106
+ export const dependencyPropertyFields: Record<string, SchemaNode> = {
107
+ bind: {
108
+ widget: 'propertyBind',
109
+ type: 'string',
110
+ title: '数据绑定(bind)',
111
+ },
112
+ dependencies: {
113
+ widget: 'propertyDependencies',
114
+ type: 'string',
115
+ title: '依赖字段(dependencies)',
116
+ },
117
+ };
118
+
119
+ // ── 联动配置 ──────────────────────────────────────────────────────────────
120
+ export const reactionPropertyFields: Record<string, SchemaNode> = {
121
+ reactions: {
122
+ widget: 'propertyReactions',
123
+ type: 'string',
124
+ title: '联动规则(reactions)',
125
+ },
126
+ };