@xbeeant/form-engine-designer 0.0.3 → 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 -47
- 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 +99 -100
- package/dist/es/PropertyPanel.js.map +1 -1
- package/dist/es/catalog.js +17 -10
- 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.css +1 -1
- 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 -160
- package/dist/es/react/src/components/FormController.js.map +0 -1
- package/dist/es/react/src/components/NexusField.js +0 -98
- package/dist/es/react/src/components/NexusField.js.map +0 -1
- package/dist/es/react/src/components/NexusForm.js +0 -128
- 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 -13
- 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/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 -527
- 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/src/Palette.tsx
DELETED
|
@@ -1,261 +0,0 @@
|
|
|
1
|
-
// ============================================================================
|
|
2
|
-
// @xbeeant/form-engine-designer — 左侧组件目录面板
|
|
3
|
-
// ============================================================================
|
|
4
|
-
|
|
5
|
-
import type { SchemaNode } from '@xbeeant/form-engine';
|
|
6
|
-
import { Collapse, Input } from 'antd';
|
|
7
|
-
import type { DragEvent } from 'react';
|
|
8
|
-
import { useCallback, useMemo, useState } from 'react';
|
|
9
|
-
import { useDesigner } from './DesignerContext';
|
|
10
|
-
import {
|
|
11
|
-
generateKey,
|
|
12
|
-
getNodeAtProperties,
|
|
13
|
-
getPropertiesOf,
|
|
14
|
-
} from './schemaUtils';
|
|
15
|
-
import type { CatalogItem, FieldDef } from './types';
|
|
16
|
-
|
|
17
|
-
// 拖拽负载:palette 组件目录项 or 外部字段定义
|
|
18
|
-
export interface PaletteDragPayload {
|
|
19
|
-
source: 'palette';
|
|
20
|
-
catalogItem: CatalogItem;
|
|
21
|
-
}
|
|
22
|
-
export interface FieldDefDragPayload {
|
|
23
|
-
source: 'fieldDef';
|
|
24
|
-
fieldDef: FieldDef;
|
|
25
|
-
}
|
|
26
|
-
export type PaletteDragData = PaletteDragPayload | FieldDefDragPayload;
|
|
27
|
-
|
|
28
|
-
// 面板类型 → 允许的唯一父容器类型(面板不能直接添加到根或普通容器)
|
|
29
|
-
const PANE_PARENT_TYPE: Record<string, string> = {
|
|
30
|
-
tabPane: 'tabs',
|
|
31
|
-
collapsePanel: 'collapse',
|
|
32
|
-
step: 'steps',
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
const isPaneItem = (item: CatalogItem): boolean =>
|
|
36
|
-
item.category === 'layout' && !!PANE_PARENT_TYPE[item.layoutType ?? ''];
|
|
37
|
-
|
|
38
|
-
function PaletteItem({
|
|
39
|
-
item,
|
|
40
|
-
onAdd,
|
|
41
|
-
}: {
|
|
42
|
-
item: CatalogItem;
|
|
43
|
-
onAdd: (item: CatalogItem) => void;
|
|
44
|
-
}) {
|
|
45
|
-
const handleDragStart = (e: DragEvent<HTMLDivElement>) => {
|
|
46
|
-
const payload: PaletteDragPayload = {
|
|
47
|
-
source: 'palette',
|
|
48
|
-
catalogItem: item,
|
|
49
|
-
};
|
|
50
|
-
e.dataTransfer.setData('application/json', JSON.stringify(payload));
|
|
51
|
-
e.dataTransfer.effectAllowed = 'copy';
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
// 面板类组件只能放入对应容器,点击/拖拽提示差异化
|
|
55
|
-
const paneParent = isPaneItem(item)
|
|
56
|
-
? PANE_PARENT_TYPE[item.layoutType ?? '']
|
|
57
|
-
: undefined;
|
|
58
|
-
const title = paneParent
|
|
59
|
-
? `拖拽「${item.label}」到「${paneParent}」容器中,或选中容器后点击`
|
|
60
|
-
: `点击添加或拖拽「${item.label}」到画布`;
|
|
61
|
-
|
|
62
|
-
return (
|
|
63
|
-
<div
|
|
64
|
-
className='group flex flex-col items-center gap-1 rounded-lg border border-[#f0f0f0] bg-white px-1 py-2 cursor-grab select-none transition-all hover:-translate-y-px hover:border-[#1677ff] hover:shadow-[0_2px_8px_rgba(22,119,255,0.12)] active:cursor-grabbing'
|
|
65
|
-
draggable
|
|
66
|
-
onDragStart={handleDragStart}
|
|
67
|
-
onClick={() => onAdd(item)}
|
|
68
|
-
title={title}
|
|
69
|
-
>
|
|
70
|
-
<span className='flex h-7 w-7 items-center justify-center rounded-md bg-[#f5f7fa] text-[15px] transition-colors group-hover:bg-[#e8f1ff]'>
|
|
71
|
-
{item.icon}
|
|
72
|
-
</span>
|
|
73
|
-
<span className='w-full truncate text-center text-xs text-[#666] transition-colors group-hover:text-[#1677ff]'>
|
|
74
|
-
{item.label}
|
|
75
|
-
</span>
|
|
76
|
-
</div>
|
|
77
|
-
);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
function FieldDefItem({ field }: { field: FieldDef }) {
|
|
81
|
-
const handleDragStart = (e: DragEvent<HTMLDivElement>) => {
|
|
82
|
-
const payload: FieldDefDragPayload = {
|
|
83
|
-
source: 'fieldDef',
|
|
84
|
-
fieldDef: field,
|
|
85
|
-
};
|
|
86
|
-
e.dataTransfer.setData('application/json', JSON.stringify(payload));
|
|
87
|
-
e.dataTransfer.effectAllowed = 'copy';
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
return (
|
|
91
|
-
<div
|
|
92
|
-
className='flex items-center gap-2 rounded-lg border border-[#f0f0f0] bg-white px-2 py-1.5 cursor-grab select-none transition-all hover:-translate-y-px hover:border-[#1677ff] hover:shadow-[0_2px_8px_rgba(22,119,255,0.12)] active:cursor-grabbing'
|
|
93
|
-
draggable
|
|
94
|
-
onDragStart={handleDragStart}
|
|
95
|
-
title={`id: ${field.id} · widget: ${field.widget}`}
|
|
96
|
-
>
|
|
97
|
-
<span className='flex h-6 w-6 flex-shrink-0 items-center justify-center rounded-md bg-[#f5f7fa] text-[13px]'>
|
|
98
|
-
🔧
|
|
99
|
-
</span>
|
|
100
|
-
<span className='truncate text-xs text-[#666]'>{field.name}</span>
|
|
101
|
-
</div>
|
|
102
|
-
);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
export function Palette() {
|
|
106
|
-
const {
|
|
107
|
-
schema,
|
|
108
|
-
selectedPath,
|
|
109
|
-
addNode,
|
|
110
|
-
fields,
|
|
111
|
-
widgetCatalog,
|
|
112
|
-
layoutCatalog,
|
|
113
|
-
} = useDesigner();
|
|
114
|
-
const [keyword, setKeyword] = useState('');
|
|
115
|
-
|
|
116
|
-
const handleAdd = useCallback(
|
|
117
|
-
(item: CatalogItem) => {
|
|
118
|
-
const base = item.widget || item.layoutType || 'field';
|
|
119
|
-
// 面板类组件只能放入对应容器:点击时若已选中匹配容器则加入,否则忽略
|
|
120
|
-
const paneParentType = isPaneItem(item)
|
|
121
|
-
? PANE_PARENT_TYPE[item.layoutType ?? '']
|
|
122
|
-
: undefined;
|
|
123
|
-
if (paneParentType) {
|
|
124
|
-
if (!selectedPath || selectedPath.length === 0) {
|
|
125
|
-
return;
|
|
126
|
-
}
|
|
127
|
-
const parent = getNodeAtProperties(schema.properties, selectedPath);
|
|
128
|
-
if (!parent || parent.type !== paneParentType) {
|
|
129
|
-
return;
|
|
130
|
-
}
|
|
131
|
-
const parentProps = getPropertiesOf(parent);
|
|
132
|
-
if (!parentProps) {
|
|
133
|
-
return;
|
|
134
|
-
}
|
|
135
|
-
const key = generateKey(parentProps, base);
|
|
136
|
-
addNode(selectedPath, key, item.createNode() as unknown as SchemaNode);
|
|
137
|
-
return;
|
|
138
|
-
}
|
|
139
|
-
const key = generateKey(schema.properties, base);
|
|
140
|
-
const node = item.createNode() as unknown as SchemaNode;
|
|
141
|
-
addNode([], key, node);
|
|
142
|
-
},
|
|
143
|
-
[schema, addNode, selectedPath],
|
|
144
|
-
);
|
|
145
|
-
|
|
146
|
-
const kw = keyword.trim().toLowerCase();
|
|
147
|
-
|
|
148
|
-
const widgetItems = useMemo(
|
|
149
|
-
() =>
|
|
150
|
-
widgetCatalog
|
|
151
|
-
.filter((item) => item.label.toLowerCase().includes(kw))
|
|
152
|
-
.map((item) => (
|
|
153
|
-
<PaletteItem key={item.widget} item={item} onAdd={handleAdd} />
|
|
154
|
-
)),
|
|
155
|
-
[widgetCatalog, kw, handleAdd],
|
|
156
|
-
);
|
|
157
|
-
|
|
158
|
-
const layoutItems = useMemo(
|
|
159
|
-
() =>
|
|
160
|
-
layoutCatalog
|
|
161
|
-
.filter((item) => item.label.toLowerCase().includes(kw))
|
|
162
|
-
.map((item) => (
|
|
163
|
-
<PaletteItem key={item.layoutType} item={item} onAdd={handleAdd} />
|
|
164
|
-
)),
|
|
165
|
-
[layoutCatalog, kw, handleAdd],
|
|
166
|
-
);
|
|
167
|
-
|
|
168
|
-
const fieldItems = useMemo(
|
|
169
|
-
() =>
|
|
170
|
-
(fields ?? [])
|
|
171
|
-
.filter((field) => field.name.toLowerCase().includes(kw))
|
|
172
|
-
.map((field) => <FieldDefItem key={field.id} field={field} />),
|
|
173
|
-
[fields, kw],
|
|
174
|
-
);
|
|
175
|
-
|
|
176
|
-
const sectionGrid = (items: React.ReactNode[], hasMore: boolean) =>
|
|
177
|
-
items.length > 0 ? (
|
|
178
|
-
<div className='grid grid-cols-2 gap-1.5 px-1 pb-2'>{items}</div>
|
|
179
|
-
) : (
|
|
180
|
-
<div className='py-3 text-center text-xs text-[#c0c4cc]'>
|
|
181
|
-
{hasMore ? '无匹配组件' : '暂无组件'}
|
|
182
|
-
</div>
|
|
183
|
-
);
|
|
184
|
-
|
|
185
|
-
const collapseItems = [
|
|
186
|
-
{
|
|
187
|
-
key: 'widgets',
|
|
188
|
-
label: (
|
|
189
|
-
<span className='flex w-full items-center justify-between pr-1'>
|
|
190
|
-
<span>表单组件</span>
|
|
191
|
-
<span className='rounded-full bg-[#f0f0f0] px-1.5 py-px text-[11px] text-[#999]'>
|
|
192
|
-
{widgetItems.length}
|
|
193
|
-
</span>
|
|
194
|
-
</span>
|
|
195
|
-
),
|
|
196
|
-
children: sectionGrid(widgetItems, true),
|
|
197
|
-
},
|
|
198
|
-
{
|
|
199
|
-
key: 'layouts',
|
|
200
|
-
label: (
|
|
201
|
-
<span className='flex w-full items-center justify-between pr-1'>
|
|
202
|
-
<span>布局组件</span>
|
|
203
|
-
<span className='rounded-full bg-[#f0f0f0] px-1.5 py-px text-[11px] text-[#999]'>
|
|
204
|
-
{layoutItems.length}
|
|
205
|
-
</span>
|
|
206
|
-
</span>
|
|
207
|
-
),
|
|
208
|
-
children: sectionGrid(layoutItems, true),
|
|
209
|
-
},
|
|
210
|
-
];
|
|
211
|
-
|
|
212
|
-
// 仅当传入 fields 时显示「字段列表」分组
|
|
213
|
-
if (fields && fields.length > 0) {
|
|
214
|
-
collapseItems.push({
|
|
215
|
-
key: 'fieldList',
|
|
216
|
-
label: (
|
|
217
|
-
<span className='flex w-full items-center justify-between pr-1'>
|
|
218
|
-
<span>字段列表</span>
|
|
219
|
-
<span className='rounded-full bg-[#f0f0f0] px-1.5 py-px text-[11px] text-[#999]'>
|
|
220
|
-
{fieldItems.length}
|
|
221
|
-
</span>
|
|
222
|
-
</span>
|
|
223
|
-
),
|
|
224
|
-
children: (
|
|
225
|
-
<div className='flex flex-col gap-1.5 px-1 pb-2'>
|
|
226
|
-
{fieldItems.length > 0 ? (
|
|
227
|
-
fieldItems
|
|
228
|
-
) : (
|
|
229
|
-
<div className='py-3 text-center text-xs text-[#c0c4cc]'>
|
|
230
|
-
无匹配字段
|
|
231
|
-
</div>
|
|
232
|
-
)}
|
|
233
|
-
</div>
|
|
234
|
-
),
|
|
235
|
-
});
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
return (
|
|
239
|
-
<div className='flex h-full flex-col border-r border-[#f0f0f0] bg-[#f7f8fa]'>
|
|
240
|
-
<div className='px-3 pb-2 pt-3'>
|
|
241
|
-
<Input
|
|
242
|
-
size='small'
|
|
243
|
-
allowClear
|
|
244
|
-
prefix={<span className='text-xs text-[#bbb]'>🔍</span>}
|
|
245
|
-
placeholder='搜索组件…'
|
|
246
|
-
value={keyword}
|
|
247
|
-
onChange={(e) => setKeyword(e.target.value)}
|
|
248
|
-
className='nexus-palette-search'
|
|
249
|
-
/>
|
|
250
|
-
</div>
|
|
251
|
-
<div className='flex-1 overflow-y-auto px-2 pb-3'>
|
|
252
|
-
<Collapse
|
|
253
|
-
className='nexus-palette-collapse'
|
|
254
|
-
expandIconPlacement='end'
|
|
255
|
-
defaultActiveKey={['widgets', 'layouts']}
|
|
256
|
-
items={collapseItems}
|
|
257
|
-
/>
|
|
258
|
-
</div>
|
|
259
|
-
</div>
|
|
260
|
-
);
|
|
261
|
-
}
|