@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
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
// ============================================================================
|
|
2
|
-
// BindEditor — 编辑 bind 属性(路径映射)
|
|
3
|
-
// 支持四种模式:无/字符串/数组/false,不同模式显示不同的子控件
|
|
4
|
-
// ============================================================================
|
|
5
|
-
|
|
6
|
-
import type { WidgetProps } from '@xbeeant/form-engine-ui';
|
|
7
|
-
import { Form, Input, Select } from 'antd';
|
|
8
|
-
import { useState } from 'react';
|
|
9
|
-
|
|
10
|
-
function getBindMode(value: unknown): string {
|
|
11
|
-
if (value === false || value === 'false') {
|
|
12
|
-
return 'false';
|
|
13
|
-
}
|
|
14
|
-
if (Array.isArray(value)) {
|
|
15
|
-
return 'array';
|
|
16
|
-
}
|
|
17
|
-
if (typeof value === 'string' && value.length > 0) {
|
|
18
|
-
return 'string';
|
|
19
|
-
}
|
|
20
|
-
return 'none';
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const BIND_MODE_OPTIONS = [
|
|
24
|
-
{ value: 'none', label: '无(使用字段路径)' },
|
|
25
|
-
{ value: 'string', label: '字符串路径' },
|
|
26
|
-
{ value: 'array', label: '字符串数组(多路径拆分)' },
|
|
27
|
-
{ value: 'false', label: '不绑定(不提交)' },
|
|
28
|
-
];
|
|
29
|
-
|
|
30
|
-
export function BindEditor({ value, onChange, title }: WidgetProps) {
|
|
31
|
-
const mode = getBindMode(value);
|
|
32
|
-
// 本地状态缓存文本值,防止每次按键都触发 onChange
|
|
33
|
-
const [textValue, setTextValue] = useState<string>(
|
|
34
|
-
Array.isArray(value)
|
|
35
|
-
? (value as string[]).join('\n')
|
|
36
|
-
: typeof value === 'string'
|
|
37
|
-
? value
|
|
38
|
-
: '',
|
|
39
|
-
);
|
|
40
|
-
|
|
41
|
-
const handleModeChange = (newMode: string) => {
|
|
42
|
-
if (newMode === 'none') {
|
|
43
|
-
onChange(undefined);
|
|
44
|
-
setTextValue('');
|
|
45
|
-
} else if (newMode === 'string') {
|
|
46
|
-
onChange('');
|
|
47
|
-
setTextValue('');
|
|
48
|
-
} else if (newMode === 'array') {
|
|
49
|
-
onChange([]);
|
|
50
|
-
setTextValue('');
|
|
51
|
-
} else if (newMode === 'false') {
|
|
52
|
-
onChange(false);
|
|
53
|
-
setTextValue('');
|
|
54
|
-
}
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
const handleTextCommit = () => {
|
|
58
|
-
if (mode === 'string') {
|
|
59
|
-
onChange(textValue || undefined);
|
|
60
|
-
} else if (mode === 'array') {
|
|
61
|
-
const lines = textValue
|
|
62
|
-
.split('\n')
|
|
63
|
-
.map((s) => s.trim())
|
|
64
|
-
.filter((s) => s.length > 0);
|
|
65
|
-
onChange(lines.length > 0 ? lines : undefined);
|
|
66
|
-
}
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
return (
|
|
70
|
-
<Form.Item layout={'vertical'} label={title} style={{ width: '100%' }}>
|
|
71
|
-
<div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
|
|
72
|
-
<Select
|
|
73
|
-
value={mode}
|
|
74
|
-
options={BIND_MODE_OPTIONS}
|
|
75
|
-
onChange={handleModeChange}
|
|
76
|
-
style={{ width: '100%' }}
|
|
77
|
-
/>
|
|
78
|
-
{mode === 'string' && (
|
|
79
|
-
<Input
|
|
80
|
-
placeholder='如: user.name'
|
|
81
|
-
value={textValue}
|
|
82
|
-
onChange={(e) => setTextValue(e.target.value)}
|
|
83
|
-
onBlur={handleTextCommit}
|
|
84
|
-
onPressEnter={handleTextCommit}
|
|
85
|
-
/>
|
|
86
|
-
)}
|
|
87
|
-
{mode === 'array' && (
|
|
88
|
-
<Input.TextArea
|
|
89
|
-
rows={3}
|
|
90
|
-
placeholder={'如: a.b\nc.d'}
|
|
91
|
-
value={textValue}
|
|
92
|
-
onChange={(e) => setTextValue(e.target.value)}
|
|
93
|
-
onBlur={handleTextCommit}
|
|
94
|
-
/>
|
|
95
|
-
)}
|
|
96
|
-
<div style={{ fontSize: 11, color: '#999' }}>
|
|
97
|
-
提示:bind 将字段值映射到不同数据路径。string[]
|
|
98
|
-
表示字段值数组按顺序拆分到多个路径;false 表示字段不参与提交。
|
|
99
|
-
</div>
|
|
100
|
-
</div>
|
|
101
|
-
</Form.Item>
|
|
102
|
-
);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
export const bindEditorWidget = BindEditor;
|
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
// ============================================================================
|
|
2
|
-
// CodeEditor — 属性面板专用 JSON 编辑器
|
|
3
|
-
// 供 remoteData 等对象配置使用:支持语法校验、格式化与占位符示例
|
|
4
|
-
// 值格式:object | array(非法 JSON 不写回,光标处自动提示)
|
|
5
|
-
// ============================================================================
|
|
6
|
-
|
|
7
|
-
import type { WidgetProps } from '@xbeeant/form-engine-ui';
|
|
8
|
-
import { Button, Form, Input, Space, Typography } from 'antd';
|
|
9
|
-
import { useMemo, useState } from 'react';
|
|
10
|
-
|
|
11
|
-
export function CodeEditor({
|
|
12
|
-
value,
|
|
13
|
-
onChange,
|
|
14
|
-
title,
|
|
15
|
-
description,
|
|
16
|
-
placeholder,
|
|
17
|
-
...rest
|
|
18
|
-
}: WidgetProps) {
|
|
19
|
-
const fieldProps = rest as Record<string, unknown>;
|
|
20
|
-
const lines = (fieldProps?.lines as number) ?? 10;
|
|
21
|
-
|
|
22
|
-
const [error, setError] = useState<string | null>(null);
|
|
23
|
-
|
|
24
|
-
// 编辑态文案:初始为 JSON 字符串;解析失败时保留原文(不打断输入)
|
|
25
|
-
const [draft, setDraft] = useState<string | undefined>(undefined);
|
|
26
|
-
|
|
27
|
-
const text = useMemo(() => {
|
|
28
|
-
if (draft !== undefined) {
|
|
29
|
-
return draft;
|
|
30
|
-
}
|
|
31
|
-
if (value === undefined || value === null) {
|
|
32
|
-
return '';
|
|
33
|
-
}
|
|
34
|
-
try {
|
|
35
|
-
return JSON.stringify(value, null, 2);
|
|
36
|
-
} catch {
|
|
37
|
-
return String(value);
|
|
38
|
-
}
|
|
39
|
-
}, [draft, value]);
|
|
40
|
-
|
|
41
|
-
const handleChange = (raw: string) => {
|
|
42
|
-
setDraft(raw);
|
|
43
|
-
const trimmed = raw.trim();
|
|
44
|
-
if (!trimmed) {
|
|
45
|
-
setError(null);
|
|
46
|
-
onChange(undefined);
|
|
47
|
-
return;
|
|
48
|
-
}
|
|
49
|
-
try {
|
|
50
|
-
const parsed = JSON.parse(trimmed);
|
|
51
|
-
setError(null);
|
|
52
|
-
onChange(parsed);
|
|
53
|
-
} catch (e) {
|
|
54
|
-
setError(e instanceof Error ? e.message : 'JSON 解析失败');
|
|
55
|
-
}
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
const handleFormat = () => {
|
|
59
|
-
try {
|
|
60
|
-
const formatted = JSON.stringify(JSON.parse(text), null, 2);
|
|
61
|
-
setDraft(formatted);
|
|
62
|
-
setError(null);
|
|
63
|
-
} catch {
|
|
64
|
-
// 语法非法时静默,保留原文
|
|
65
|
-
}
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
return (
|
|
69
|
-
<Form.Item
|
|
70
|
-
label={title}
|
|
71
|
-
layout={'vertical'}
|
|
72
|
-
style={{ width: '100%' }}
|
|
73
|
-
help={
|
|
74
|
-
error ? (
|
|
75
|
-
<Typography.Text type='danger' style={{ fontSize: 11 }}>
|
|
76
|
-
{error}
|
|
77
|
-
</Typography.Text>
|
|
78
|
-
) : description ? (
|
|
79
|
-
<span style={{ fontSize: 11, color: '#999' }}>{description}</span>
|
|
80
|
-
) : undefined
|
|
81
|
-
}
|
|
82
|
-
validateStatus={error ? 'error' : undefined}
|
|
83
|
-
>
|
|
84
|
-
<Input.TextArea
|
|
85
|
-
value={text}
|
|
86
|
-
rows={lines}
|
|
87
|
-
onChange={(e) => handleChange(e.target.value)}
|
|
88
|
-
placeholder={
|
|
89
|
-
placeholder
|
|
90
|
-
? `示例:\n${typeof placeholder === 'string' ? placeholder : JSON.stringify(placeholder, null, 2)}`
|
|
91
|
-
: '{}'
|
|
92
|
-
}
|
|
93
|
-
style={{ fontFamily: 'monospace', fontSize: 12 }}
|
|
94
|
-
/>
|
|
95
|
-
<Space.Compact style={{ marginTop: 6, width: '100%' }}>
|
|
96
|
-
<Button size='small' onClick={handleFormat} disabled={!!error}>
|
|
97
|
-
格式化
|
|
98
|
-
</Button>
|
|
99
|
-
<Button
|
|
100
|
-
size='small'
|
|
101
|
-
onClick={() => {
|
|
102
|
-
setDraft('');
|
|
103
|
-
setError(null);
|
|
104
|
-
onChange(undefined);
|
|
105
|
-
}}
|
|
106
|
-
>
|
|
107
|
-
清空
|
|
108
|
-
</Button>
|
|
109
|
-
</Space.Compact>
|
|
110
|
-
</Form.Item>
|
|
111
|
-
);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
export const codeEditorWidget = CodeEditor;
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
// ============================================================================
|
|
2
|
-
// DefaultEditor — 按字段类型编辑默认值
|
|
3
|
-
// string → Input, number/integer → InputNumber, boolean → Switch, object/array → JSON TextArea
|
|
4
|
-
// ============================================================================
|
|
5
|
-
|
|
6
|
-
import type { WidgetProps } from '@xbeeant/form-engine-ui';
|
|
7
|
-
import { Form, Input, InputNumber, Switch } from 'antd';
|
|
8
|
-
|
|
9
|
-
export function DefaultEditor({
|
|
10
|
-
value,
|
|
11
|
-
onChange,
|
|
12
|
-
title,
|
|
13
|
-
...rest
|
|
14
|
-
}: WidgetProps) {
|
|
15
|
-
const fieldProps = rest as Record<string, unknown>;
|
|
16
|
-
const dataType = (fieldProps?.dataType as string) ?? 'string';
|
|
17
|
-
|
|
18
|
-
if (dataType === 'boolean') {
|
|
19
|
-
return (
|
|
20
|
-
<Form.Item label={title} style={{ width: '100%' }}>
|
|
21
|
-
<Switch checked={!!value} onChange={(v) => onChange(v)} />
|
|
22
|
-
</Form.Item>
|
|
23
|
-
);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
if (dataType === 'number' || dataType === 'integer') {
|
|
27
|
-
return (
|
|
28
|
-
<Form.Item label={title} style={{ width: '100%' }}>
|
|
29
|
-
<InputNumber
|
|
30
|
-
value={value as number}
|
|
31
|
-
onChange={(v) => onChange(v ?? undefined)}
|
|
32
|
-
style={{ width: '100%' }}
|
|
33
|
-
/>
|
|
34
|
-
</Form.Item>
|
|
35
|
-
);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
if (dataType === 'object' || dataType === 'array') {
|
|
39
|
-
const text = value !== undefined ? JSON.stringify(value, null, 2) : '';
|
|
40
|
-
return (
|
|
41
|
-
<Form.Item label={`${title}(JSON)`} style={{ width: '100%' }}>
|
|
42
|
-
<Input.TextArea
|
|
43
|
-
rows={3}
|
|
44
|
-
value={text}
|
|
45
|
-
onChange={(e) => {
|
|
46
|
-
const t = e.target.value.trim();
|
|
47
|
-
if (!t) {
|
|
48
|
-
onChange(undefined);
|
|
49
|
-
return;
|
|
50
|
-
}
|
|
51
|
-
try {
|
|
52
|
-
onChange(JSON.parse(t));
|
|
53
|
-
} catch {
|
|
54
|
-
// JSON 解析失败时不更新
|
|
55
|
-
}
|
|
56
|
-
}}
|
|
57
|
-
/>
|
|
58
|
-
</Form.Item>
|
|
59
|
-
);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// string
|
|
63
|
-
return (
|
|
64
|
-
<Form.Item label={title} style={{ width: '100%' }}>
|
|
65
|
-
<Input
|
|
66
|
-
value={(value as string) ?? ''}
|
|
67
|
-
onChange={(e) => onChange(e.target.value || undefined)}
|
|
68
|
-
/>
|
|
69
|
-
</Form.Item>
|
|
70
|
-
);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
export const defaultEditorWidget = DefaultEditor;
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
// ============================================================================
|
|
2
|
-
// DependenciesEditor — 编辑 dependencies 依赖字段路径(string[])
|
|
3
|
-
// 通过标签选择器从表单字段中选择依赖路径,也支持手动输入自定义路径
|
|
4
|
-
// ============================================================================
|
|
5
|
-
|
|
6
|
-
import type { WidgetProps } from '@xbeeant/form-engine-ui';
|
|
7
|
-
import { Form, Select } from 'antd';
|
|
8
|
-
import { useEffect, useRef, useState } from 'react';
|
|
9
|
-
import { useFormDataFieldOptions } from './useFormDataFields';
|
|
10
|
-
|
|
11
|
-
export function DependenciesEditor({ value, onChange, title }: WidgetProps) {
|
|
12
|
-
const fieldOptions = useFormDataFieldOptions();
|
|
13
|
-
const [tags, setTags] = useState<string[]>(() =>
|
|
14
|
-
Array.isArray(value) ? [...value] : [],
|
|
15
|
-
);
|
|
16
|
-
const prevValueRef = useRef(value);
|
|
17
|
-
const lastEmittedRef = useRef(value);
|
|
18
|
-
|
|
19
|
-
// 外部 value 变化(切换节点等)时重置,自身 onChange 回传不重置
|
|
20
|
-
useEffect(() => {
|
|
21
|
-
if (prevValueRef.current !== value) {
|
|
22
|
-
prevValueRef.current = value;
|
|
23
|
-
if (value !== lastEmittedRef.current) {
|
|
24
|
-
setTags(Array.isArray(value) ? [...value] : []);
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
}, [value]);
|
|
28
|
-
|
|
29
|
-
const commit = (next: string[]) => {
|
|
30
|
-
setTags(next);
|
|
31
|
-
lastEmittedRef.current = next;
|
|
32
|
-
onChange(next.length > 0 ? next : undefined);
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
return (
|
|
36
|
-
<Form.Item layout={'vertical'} label={title} style={{ width: '100%' }}>
|
|
37
|
-
<Select
|
|
38
|
-
size='small'
|
|
39
|
-
mode='tags'
|
|
40
|
-
value={tags}
|
|
41
|
-
onChange={(v) =>
|
|
42
|
-
commit((v as string[]).map((s) => s.trim()).filter(Boolean))
|
|
43
|
-
}
|
|
44
|
-
options={fieldOptions}
|
|
45
|
-
placeholder='选择或输入依赖字段路径'
|
|
46
|
-
style={{ width: '100%' }}
|
|
47
|
-
/>
|
|
48
|
-
<div style={{ fontSize: 11, color: '#999', marginTop: 4 }}>
|
|
49
|
-
提示:依赖字段值变化时,触发该字段重新求值与渲染。支持相对路径(如 处于
|
|
50
|
-
address.city 时填 province 表示 address.province)。
|
|
51
|
-
</div>
|
|
52
|
-
</Form.Item>
|
|
53
|
-
);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
export const dependenciesEditorWidget = DependenciesEditor;
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
// ============================================================================
|
|
2
|
-
// EnumEditor — 编辑 enum 枚举值及 enumNames 枚举文案
|
|
3
|
-
// 使用两个 TextArea,值按行分隔
|
|
4
|
-
// ============================================================================
|
|
5
|
-
|
|
6
|
-
import type { WidgetProps } from '@xbeeant/form-engine-ui';
|
|
7
|
-
import { Form, Input } from 'antd';
|
|
8
|
-
|
|
9
|
-
export function EnumEditor({ value, onChange }: WidgetProps) {
|
|
10
|
-
// value 是一个包含 _enum 和 _enumNames 的对象(由 engine 传入)
|
|
11
|
-
// 实际上 engine 传入的 value 是字段存储的原始值
|
|
12
|
-
// 这里我们使用单独的 _enum 和 _enumNames key
|
|
13
|
-
// 实际上这个 widget 对应 schema 中的 _enum 字段
|
|
14
|
-
// 但 engine 只传单个 value
|
|
15
|
-
|
|
16
|
-
// 这里简化处理:value 是 _enum 的序列化字符串
|
|
17
|
-
// _enumNames 通过 props 或 dependValues 传递
|
|
18
|
-
// 但更简洁的方式是让 schema 中有两个独立字段
|
|
19
|
-
|
|
20
|
-
// 这个 widget 实际上应该对应两个字段。让我们重新考虑...
|
|
21
|
-
// 在 schema 中,我们只定义了一个 _enum 字段,这个 widget 渲染时
|
|
22
|
-
// value 是 _enum 的值(序列化字符串)
|
|
23
|
-
|
|
24
|
-
return (
|
|
25
|
-
<>
|
|
26
|
-
<Form.Item label='枚举值(enum,每行一个)' style={{ width: '100%' }}>
|
|
27
|
-
<Input.TextArea
|
|
28
|
-
rows={3}
|
|
29
|
-
value={typeof value === 'string' ? value : ''}
|
|
30
|
-
onChange={(e) => onChange(e.target.value)}
|
|
31
|
-
placeholder='每行一个枚举值'
|
|
32
|
-
/>
|
|
33
|
-
</Form.Item>
|
|
34
|
-
{/* _enumNames 由调用方通过额外逻辑处理 */}
|
|
35
|
-
<div
|
|
36
|
-
style={{ fontSize: 11, color: '#999', marginTop: -12, marginBottom: 8 }}
|
|
37
|
-
>
|
|
38
|
-
提示:枚举值用于选项的值,枚举文案见下方字段
|
|
39
|
-
</div>
|
|
40
|
-
</>
|
|
41
|
-
);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export const enumEditorWidget = EnumEditor;
|
|
45
|
-
|
|
46
|
-
// ────────────────────────────────────────────────────────────────────────────
|
|
47
|
-
// EnumNamesEditor — 编辑 enumNames(与 _enum 配对使用)
|
|
48
|
-
// ────────────────────────────────────────────────────────────────────────────
|
|
49
|
-
|
|
50
|
-
export function EnumNamesEditor({ value, onChange }: WidgetProps) {
|
|
51
|
-
return (
|
|
52
|
-
<Form.Item
|
|
53
|
-
label='枚举文案(enumNames,每行一个)'
|
|
54
|
-
style={{ width: '100%' }}
|
|
55
|
-
>
|
|
56
|
-
<Input.TextArea
|
|
57
|
-
rows={3}
|
|
58
|
-
value={typeof value === 'string' ? value : ''}
|
|
59
|
-
onChange={(e) => onChange(e.target.value)}
|
|
60
|
-
placeholder='每行一个枚举文案,与枚举值一一对应'
|
|
61
|
-
/>
|
|
62
|
-
</Form.Item>
|
|
63
|
-
);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
export const enumNamesEditorWidget = EnumNamesEditor;
|