@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
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
import { jsx as i, jsxs as d } from "react/jsx-runtime";
|
|
2
|
+
import { Space as p, Input as h, Select as K, Tooltip as u, Collapse as k, InputNumber as S, Button as y } from "antd";
|
|
3
|
+
import { useState as C, useRef as f, useEffect as P } from "react";
|
|
4
|
+
import { genId as x } from "./reactions-model.js";
|
|
5
|
+
function v(e) {
|
|
6
|
+
return !e || typeof e != "object" ? [] : Object.entries(e).map(([l, t]) => ({
|
|
7
|
+
id: x(),
|
|
8
|
+
key: l,
|
|
9
|
+
value: typeof t == "string" ? t : JSON.stringify(t)
|
|
10
|
+
}));
|
|
11
|
+
}
|
|
12
|
+
function g(e) {
|
|
13
|
+
if (!e)
|
|
14
|
+
return;
|
|
15
|
+
const l = {};
|
|
16
|
+
for (const t of e) {
|
|
17
|
+
const n = t.key.trim();
|
|
18
|
+
if (!n)
|
|
19
|
+
continue;
|
|
20
|
+
const r = t.value.trim();
|
|
21
|
+
if (r)
|
|
22
|
+
try {
|
|
23
|
+
l[n] = JSON.parse(r);
|
|
24
|
+
} catch {
|
|
25
|
+
l[n] = r;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return Object.keys(l).length > 0 ? l : void 0;
|
|
29
|
+
}
|
|
30
|
+
function b(e) {
|
|
31
|
+
const l = e ?? {}, t = l.responseField ?? {}, n = l.params;
|
|
32
|
+
return {
|
|
33
|
+
url: l.url,
|
|
34
|
+
method: l.method,
|
|
35
|
+
dataPath: t.data,
|
|
36
|
+
valueKey: t.value,
|
|
37
|
+
labelKey: t.label,
|
|
38
|
+
params: n && typeof n == "object" ? v(n) : void 0,
|
|
39
|
+
headers: v(l.headers),
|
|
40
|
+
cacheKey: l.cacheKey,
|
|
41
|
+
timeout: l.timeout
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
function T(e) {
|
|
45
|
+
const l = e.url?.trim();
|
|
46
|
+
if (!l)
|
|
47
|
+
return;
|
|
48
|
+
const t = g(e.params), n = g(e.headers), r = {
|
|
49
|
+
url: l,
|
|
50
|
+
method: e.method || "GET",
|
|
51
|
+
responseField: {
|
|
52
|
+
data: e.dataPath?.trim() || "data",
|
|
53
|
+
value: e.valueKey?.trim() || "value",
|
|
54
|
+
label: e.labelKey?.trim() || "label"
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
return t && (r.params = t), n && (r.headers = n), e.cacheKey?.trim() && (r.cacheKey = e.cacheKey.trim()), e.timeout != null && (r.timeout = e.timeout), r;
|
|
58
|
+
}
|
|
59
|
+
function z({
|
|
60
|
+
rows: e,
|
|
61
|
+
onChange: l,
|
|
62
|
+
valuePlaceholder: t,
|
|
63
|
+
keyPlaceholder: n
|
|
64
|
+
}) {
|
|
65
|
+
return /* @__PURE__ */ d("div", { style: { width: "100%" }, children: [
|
|
66
|
+
e.map((r) => /* @__PURE__ */ d(
|
|
67
|
+
"div",
|
|
68
|
+
{
|
|
69
|
+
style: {
|
|
70
|
+
display: "flex",
|
|
71
|
+
gap: 6,
|
|
72
|
+
alignItems: "center",
|
|
73
|
+
marginBottom: 6
|
|
74
|
+
},
|
|
75
|
+
children: [
|
|
76
|
+
/* @__PURE__ */ i(
|
|
77
|
+
h,
|
|
78
|
+
{
|
|
79
|
+
size: "small",
|
|
80
|
+
value: r.key,
|
|
81
|
+
placeholder: n,
|
|
82
|
+
onChange: (c) => l(
|
|
83
|
+
e.map(
|
|
84
|
+
(o) => o.id === r.id ? { ...o, key: c.target.value } : o
|
|
85
|
+
)
|
|
86
|
+
)
|
|
87
|
+
}
|
|
88
|
+
),
|
|
89
|
+
/* @__PURE__ */ i(
|
|
90
|
+
h,
|
|
91
|
+
{
|
|
92
|
+
size: "small",
|
|
93
|
+
value: r.value,
|
|
94
|
+
placeholder: t,
|
|
95
|
+
onChange: (c) => l(
|
|
96
|
+
e.map(
|
|
97
|
+
(o) => o.id === r.id ? { ...o, value: c.target.value } : o
|
|
98
|
+
)
|
|
99
|
+
)
|
|
100
|
+
}
|
|
101
|
+
),
|
|
102
|
+
/* @__PURE__ */ i(
|
|
103
|
+
y,
|
|
104
|
+
{
|
|
105
|
+
size: "small",
|
|
106
|
+
type: "text",
|
|
107
|
+
danger: !0,
|
|
108
|
+
onClick: () => l(e.filter((c) => c.id !== r.id)),
|
|
109
|
+
children: "✕"
|
|
110
|
+
}
|
|
111
|
+
)
|
|
112
|
+
]
|
|
113
|
+
},
|
|
114
|
+
r.id
|
|
115
|
+
)),
|
|
116
|
+
/* @__PURE__ */ i(
|
|
117
|
+
y,
|
|
118
|
+
{
|
|
119
|
+
size: "small",
|
|
120
|
+
type: "dashed",
|
|
121
|
+
block: !0,
|
|
122
|
+
onClick: () => l([...e, { id: x(), key: "", value: "" }]),
|
|
123
|
+
children: "+ 添加"
|
|
124
|
+
}
|
|
125
|
+
)
|
|
126
|
+
] });
|
|
127
|
+
}
|
|
128
|
+
function w({ value: e, onChange: l }) {
|
|
129
|
+
const [t, n] = C(() => b(e)), r = f(e), c = f(e);
|
|
130
|
+
P(() => {
|
|
131
|
+
r.current !== e && (r.current = e, e !== c.current && n(b(e)));
|
|
132
|
+
}, [e]);
|
|
133
|
+
const o = (a) => {
|
|
134
|
+
n(a);
|
|
135
|
+
const m = T(a);
|
|
136
|
+
c.current = m, l(m);
|
|
137
|
+
}, s = (a) => {
|
|
138
|
+
o({ ...t, ...a });
|
|
139
|
+
};
|
|
140
|
+
return /* @__PURE__ */ i("div", { style: { width: "100%" }, children: /* @__PURE__ */ d(p, { orientation: "vertical", style: { width: "100%" }, size: 8, children: [
|
|
141
|
+
/* @__PURE__ */ d("div", { style: { display: "flex", gap: 6, alignItems: "center" }, children: [
|
|
142
|
+
/* @__PURE__ */ i(
|
|
143
|
+
h,
|
|
144
|
+
{
|
|
145
|
+
size: "small",
|
|
146
|
+
placeholder: "接口地址(必填),如 /api/options",
|
|
147
|
+
value: t.url,
|
|
148
|
+
onChange: (a) => s({ url: a.target.value }),
|
|
149
|
+
style: { flex: 1 }
|
|
150
|
+
}
|
|
151
|
+
),
|
|
152
|
+
/* @__PURE__ */ i(
|
|
153
|
+
K,
|
|
154
|
+
{
|
|
155
|
+
size: "small",
|
|
156
|
+
style: { width: 80 },
|
|
157
|
+
value: t.method,
|
|
158
|
+
onChange: (a) => s({ method: a }),
|
|
159
|
+
options: [
|
|
160
|
+
{ value: "GET", label: "GET" },
|
|
161
|
+
{ value: "POST", label: "POST" }
|
|
162
|
+
]
|
|
163
|
+
}
|
|
164
|
+
)
|
|
165
|
+
] }),
|
|
166
|
+
/* @__PURE__ */ i("div", { style: { fontSize: 11, color: "#999" }, children: "响应字段映射" }),
|
|
167
|
+
/* @__PURE__ */ d("div", { style: { display: "flex", gap: 6, alignItems: "center" }, children: [
|
|
168
|
+
/* @__PURE__ */ i(u, { title: "响应数据数组的路径,如 data.list / data.result.records", children: /* @__PURE__ */ i(
|
|
169
|
+
h,
|
|
170
|
+
{
|
|
171
|
+
size: "small",
|
|
172
|
+
placeholder: "数据路径(默认 data)",
|
|
173
|
+
value: t.dataPath,
|
|
174
|
+
onChange: (a) => s({ dataPath: a.target.value }),
|
|
175
|
+
style: { flex: 1 }
|
|
176
|
+
}
|
|
177
|
+
) }),
|
|
178
|
+
/* @__PURE__ */ i(u, { title: "作为选项值(value)的字段名", children: /* @__PURE__ */ i(
|
|
179
|
+
h,
|
|
180
|
+
{
|
|
181
|
+
size: "small",
|
|
182
|
+
placeholder: "值字段",
|
|
183
|
+
value: t.valueKey,
|
|
184
|
+
onChange: (a) => s({ valueKey: a.target.value }),
|
|
185
|
+
style: { flex: 1 }
|
|
186
|
+
}
|
|
187
|
+
) }),
|
|
188
|
+
/* @__PURE__ */ i(u, { title: "作为选项文案(label)的字段名", children: /* @__PURE__ */ i(
|
|
189
|
+
h,
|
|
190
|
+
{
|
|
191
|
+
size: "small",
|
|
192
|
+
placeholder: "文案字段",
|
|
193
|
+
value: t.labelKey,
|
|
194
|
+
onChange: (a) => s({ labelKey: a.target.value }),
|
|
195
|
+
style: { flex: 1 }
|
|
196
|
+
}
|
|
197
|
+
) })
|
|
198
|
+
] }),
|
|
199
|
+
/* @__PURE__ */ i(
|
|
200
|
+
k,
|
|
201
|
+
{
|
|
202
|
+
size: "small",
|
|
203
|
+
style: { width: "100%", background: "#fafafa" },
|
|
204
|
+
items: [
|
|
205
|
+
{
|
|
206
|
+
key: "params",
|
|
207
|
+
label: "请求参数(可选)",
|
|
208
|
+
children: /* @__PURE__ */ i(
|
|
209
|
+
z,
|
|
210
|
+
{
|
|
211
|
+
rows: t.params ?? [],
|
|
212
|
+
onChange: (a) => s({ params: a }),
|
|
213
|
+
keyPlaceholder: "参数名",
|
|
214
|
+
valuePlaceholder: "参数值(数字/布尔自动识别)"
|
|
215
|
+
}
|
|
216
|
+
)
|
|
217
|
+
},
|
|
218
|
+
{
|
|
219
|
+
key: "headers",
|
|
220
|
+
label: "请求头(可选)",
|
|
221
|
+
children: /* @__PURE__ */ i(
|
|
222
|
+
z,
|
|
223
|
+
{
|
|
224
|
+
rows: t.headers ?? [],
|
|
225
|
+
onChange: (a) => s({ headers: a }),
|
|
226
|
+
keyPlaceholder: "请求头名",
|
|
227
|
+
valuePlaceholder: "如 Bearer xxxx"
|
|
228
|
+
}
|
|
229
|
+
)
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
key: "advanced",
|
|
233
|
+
label: "高级",
|
|
234
|
+
children: /* @__PURE__ */ d(
|
|
235
|
+
p,
|
|
236
|
+
{
|
|
237
|
+
orientation: "vertical",
|
|
238
|
+
style: { width: "100%" },
|
|
239
|
+
size: 8,
|
|
240
|
+
children: [
|
|
241
|
+
/* @__PURE__ */ d(
|
|
242
|
+
"div",
|
|
243
|
+
{
|
|
244
|
+
style: { display: "flex", gap: 6, alignItems: "center" },
|
|
245
|
+
children: [
|
|
246
|
+
/* @__PURE__ */ i(
|
|
247
|
+
"span",
|
|
248
|
+
{
|
|
249
|
+
style: {
|
|
250
|
+
fontSize: 12,
|
|
251
|
+
color: "#666",
|
|
252
|
+
whiteSpace: "nowrap"
|
|
253
|
+
},
|
|
254
|
+
children: "缓存键"
|
|
255
|
+
}
|
|
256
|
+
),
|
|
257
|
+
/* @__PURE__ */ i(
|
|
258
|
+
h,
|
|
259
|
+
{
|
|
260
|
+
size: "small",
|
|
261
|
+
placeholder: "默认按字段路径缓存",
|
|
262
|
+
value: t.cacheKey,
|
|
263
|
+
onChange: (a) => s({ cacheKey: a.target.value })
|
|
264
|
+
}
|
|
265
|
+
)
|
|
266
|
+
]
|
|
267
|
+
}
|
|
268
|
+
),
|
|
269
|
+
/* @__PURE__ */ d(
|
|
270
|
+
"div",
|
|
271
|
+
{
|
|
272
|
+
style: { display: "flex", gap: 6, alignItems: "center" },
|
|
273
|
+
children: [
|
|
274
|
+
/* @__PURE__ */ i(
|
|
275
|
+
"span",
|
|
276
|
+
{
|
|
277
|
+
style: {
|
|
278
|
+
fontSize: 12,
|
|
279
|
+
color: "#666",
|
|
280
|
+
whiteSpace: "nowrap"
|
|
281
|
+
},
|
|
282
|
+
children: "超时(秒)"
|
|
283
|
+
}
|
|
284
|
+
),
|
|
285
|
+
/* @__PURE__ */ i(
|
|
286
|
+
S,
|
|
287
|
+
{
|
|
288
|
+
size: "small",
|
|
289
|
+
min: 1,
|
|
290
|
+
value: t.timeout,
|
|
291
|
+
onChange: (a) => s({ timeout: a ?? void 0 }),
|
|
292
|
+
placeholder: "默认 10",
|
|
293
|
+
style: { width: 120 }
|
|
294
|
+
}
|
|
295
|
+
)
|
|
296
|
+
]
|
|
297
|
+
}
|
|
298
|
+
)
|
|
299
|
+
]
|
|
300
|
+
}
|
|
301
|
+
)
|
|
302
|
+
}
|
|
303
|
+
]
|
|
304
|
+
}
|
|
305
|
+
),
|
|
306
|
+
/* @__PURE__ */ i("div", { style: { fontSize: 11, color: "#ccc" }, children: "提示:字段值变化后选项自动刷新;POST 时参数放入请求体" })
|
|
307
|
+
] }) });
|
|
308
|
+
}
|
|
309
|
+
const j = w;
|
|
310
|
+
export {
|
|
311
|
+
w as RemoteDataEditor,
|
|
312
|
+
j as remoteDataEditorWidget
|
|
313
|
+
};
|
|
314
|
+
//# sourceMappingURL=remote-data-editor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remote-data-editor.js","sources":["../../../src/widgets/remote-data-editor.tsx"],"sourcesContent":["// ============================================================================\n// RemoteDataEditor — 可视化编辑 remoteData 远程数据配置\n// 表单化配置代替手写 JSON:\n// - 接口地址 / 请求方式(GET | POST)\n// - 响应字段映射(数据数组路径 / 值字段 / 文案字段)\n// - 请求参数(key-value 行编辑)\n// - 请求头(key-value 行编辑,可选)\n// - 缓存键 / 超时(可选)\n// 值格式:RemoteDataConfig(见 @xbeeant/form-engine-ui 的 _shared.tsx)\n// ============================================================================\n\nimport type { WidgetProps } from '@xbeeant/form-engine-ui';\nimport {\n Button,\n Collapse,\n Input,\n InputNumber,\n Select,\n Space,\n Tooltip,\n} from 'antd';\nimport { useEffect, useRef, useState } from 'react';\nimport { genId } from './reactions-model';\n\ninterface KeyValueRow {\n id: string;\n key: string;\n value: string;\n}\n\ninterface RemoteDataForm {\n url?: string;\n method?: 'GET' | 'POST';\n dataPath?: string;\n valueKey?: string;\n labelKey?: string;\n params?: KeyValueRow[];\n headers?: KeyValueRow[];\n cacheKey?: string;\n timeout?: number;\n}\n\n/** Record → key-value 行 */\nfunction recordToRows(\n value: Record<string, unknown> | undefined,\n): KeyValueRow[] {\n if (!value || typeof value !== 'object') {\n return [];\n }\n return Object.entries(value).map(([key, v]) => ({\n id: genId(),\n key,\n value: typeof v === 'string' ? v : JSON.stringify(v),\n }));\n}\n\n/** key-value 行 → Record(空 key 或空 value 的行丢弃) */\nfunction rowsToRecord(\n rows: KeyValueRow[] | undefined,\n): Record<string, unknown> | undefined {\n if (!rows) {\n return undefined;\n }\n const result: Record<string, unknown> = {};\n for (const row of rows) {\n const key = row.key.trim();\n if (!key) {\n continue;\n }\n const raw = row.value.trim();\n if (!raw) {\n continue;\n }\n // 尝试解析 JSON(数字 / 布尔 / 对象),失败保留字符串\n try {\n result[key] = JSON.parse(raw);\n } catch {\n result[key] = raw;\n }\n }\n return Object.keys(result).length > 0 ? result : undefined;\n}\n\n/** RemoteDataConfig → 表单 */\nfunction configToForm(value: unknown): RemoteDataForm {\n const cfg = (value ?? {}) as Record<string, any>;\n const rf = (cfg.responseField ?? {}) as Record<string, any>;\n const params = cfg.params;\n return {\n url: cfg.url,\n method: cfg.method,\n dataPath: rf.data,\n valueKey: rf.value,\n labelKey: rf.label,\n params:\n params && typeof params === 'object' ? recordToRows(params) : undefined,\n headers: recordToRows(cfg.headers),\n cacheKey: cfg.cacheKey,\n timeout: cfg.timeout,\n };\n}\n\n/** 表单 → RemoteDataConfig */\nfunction formToConfig(\n form: RemoteDataForm,\n): Record<string, unknown> | undefined {\n const url = form.url?.trim();\n if (!url) {\n return undefined;\n }\n const params = rowsToRecord(form.params);\n const headers = rowsToRecord(form.headers);\n const config: Record<string, unknown> = {\n url,\n method: form.method || 'GET',\n responseField: {\n data: form.dataPath?.trim() || 'data',\n value: form.valueKey?.trim() || 'value',\n label: form.labelKey?.trim() || 'label',\n },\n };\n if (params) {\n config.params = params;\n }\n if (headers) {\n config.headers = headers;\n }\n if (form.cacheKey?.trim()) {\n config.cacheKey = form.cacheKey.trim();\n }\n if (form.timeout != null) {\n config.timeout = form.timeout;\n }\n return config;\n}\n\n/** key-value 行编辑器(参数 / 请求头共用) */\nfunction KeyValueRows({\n rows,\n onChange,\n valuePlaceholder,\n keyPlaceholder,\n}: {\n rows: KeyValueRow[];\n onChange: (rows: KeyValueRow[]) => void;\n valuePlaceholder: string;\n keyPlaceholder: string;\n}) {\n return (\n <div style={{ width: '100%' }}>\n {rows.map((row) => (\n <div\n key={row.id}\n style={{\n display: 'flex',\n gap: 6,\n alignItems: 'center',\n marginBottom: 6,\n }}\n >\n <Input\n size='small'\n value={row.key}\n placeholder={keyPlaceholder}\n onChange={(e) =>\n onChange(\n rows.map((r) =>\n r.id === row.id ? { ...r, key: e.target.value } : r,\n ),\n )\n }\n />\n <Input\n size='small'\n value={row.value}\n placeholder={valuePlaceholder}\n onChange={(e) =>\n onChange(\n rows.map((r) =>\n r.id === row.id ? { ...r, value: e.target.value } : r,\n ),\n )\n }\n />\n <Button\n size='small'\n type='text'\n danger\n onClick={() => onChange(rows.filter((r) => r.id !== row.id))}\n >\n ✕\n </Button>\n </div>\n ))}\n <Button\n size='small'\n type='dashed'\n block\n onClick={() => onChange([...rows, { id: genId(), key: '', value: '' }])}\n >\n + 添加\n </Button>\n </div>\n );\n}\n\nexport function RemoteDataEditor({ value, onChange }: WidgetProps) {\n const [form, setForm] = useState<RemoteDataForm>(() => configToForm(value));\n const prevValueRef = useRef(value);\n // 自身 onChange 引发的 value 回传不应触发重建(否则每次输入都被重置)\n const lastEmittedRef = useRef(value);\n\n useEffect(() => {\n if (prevValueRef.current !== value) {\n prevValueRef.current = value;\n if (value !== lastEmittedRef.current) {\n setForm(configToForm(value));\n }\n }\n }, [value]);\n\n const commit = (next: RemoteDataForm) => {\n setForm(next);\n const emitted = formToConfig(next);\n lastEmittedRef.current = emitted;\n onChange(emitted);\n };\n\n const patch = (partial: Partial<RemoteDataForm>) => {\n commit({ ...form, ...partial });\n };\n\n return (\n <div style={{ width: '100%' }}>\n <Space orientation='vertical' style={{ width: '100%' }} size={8}>\n {/* 请求地址 + 方式 */}\n <div style={{ display: 'flex', gap: 6, alignItems: 'center' }}>\n <Input\n size='small'\n placeholder='接口地址(必填),如 /api/options'\n value={form.url}\n onChange={(e) => patch({ url: e.target.value })}\n style={{ flex: 1 }}\n />\n <Select\n size='small'\n style={{ width: 80 }}\n value={form.method}\n onChange={(v) => patch({ method: v })}\n options={[\n { value: 'GET', label: 'GET' },\n { value: 'POST', label: 'POST' },\n ]}\n />\n </div>\n\n {/* 响应字段映射 */}\n <div style={{ fontSize: 11, color: '#999' }}>响应字段映射</div>\n <div style={{ display: 'flex', gap: 6, alignItems: 'center' }}>\n <Tooltip title='响应数据数组的路径,如 data.list / data.result.records'>\n <Input\n size='small'\n placeholder='数据路径(默认 data)'\n value={form.dataPath}\n onChange={(e) => patch({ dataPath: e.target.value })}\n style={{ flex: 1 }}\n />\n </Tooltip>\n <Tooltip title='作为选项值(value)的字段名'>\n <Input\n size='small'\n placeholder='值字段'\n value={form.valueKey}\n onChange={(e) => patch({ valueKey: e.target.value })}\n style={{ flex: 1 }}\n />\n </Tooltip>\n <Tooltip title='作为选项文案(label)的字段名'>\n <Input\n size='small'\n placeholder='文案字段'\n value={form.labelKey}\n onChange={(e) => patch({ labelKey: e.target.value })}\n style={{ flex: 1 }}\n />\n </Tooltip>\n </div>\n\n {/* 请求参数 / 请求头 / 高级 */}\n <Collapse\n size='small'\n style={{ width: '100%', background: '#fafafa' }}\n items={[\n {\n key: 'params',\n label: '请求参数(可选)',\n children: (\n <KeyValueRows\n rows={form.params ?? []}\n onChange={(rows) => patch({ params: rows })}\n keyPlaceholder='参数名'\n valuePlaceholder='参数值(数字/布尔自动识别)'\n />\n ),\n },\n {\n key: 'headers',\n label: '请求头(可选)',\n children: (\n <KeyValueRows\n rows={form.headers ?? []}\n onChange={(rows) => patch({ headers: rows })}\n keyPlaceholder='请求头名'\n valuePlaceholder='如 Bearer xxxx'\n />\n ),\n },\n {\n key: 'advanced',\n label: '高级',\n children: (\n <Space\n orientation='vertical'\n style={{ width: '100%' }}\n size={8}\n >\n <div\n style={{ display: 'flex', gap: 6, alignItems: 'center' }}\n >\n <span\n style={{\n fontSize: 12,\n color: '#666',\n whiteSpace: 'nowrap',\n }}\n >\n 缓存键\n </span>\n <Input\n size='small'\n placeholder='默认按字段路径缓存'\n value={form.cacheKey}\n onChange={(e) => patch({ cacheKey: e.target.value })}\n />\n </div>\n <div\n style={{ display: 'flex', gap: 6, alignItems: 'center' }}\n >\n <span\n style={{\n fontSize: 12,\n color: '#666',\n whiteSpace: 'nowrap',\n }}\n >\n 超时(秒)\n </span>\n <InputNumber\n size='small'\n min={1}\n value={form.timeout}\n onChange={(v) => patch({ timeout: v ?? undefined })}\n placeholder='默认 10'\n style={{ width: 120 }}\n />\n </div>\n </Space>\n ),\n },\n ]}\n />\n\n <div style={{ fontSize: 11, color: '#ccc' }}>\n 提示:字段值变化后选项自动刷新;POST 时参数放入请求体\n </div>\n </Space>\n </div>\n );\n}\n\nexport const remoteDataEditorWidget = RemoteDataEditor;\n"],"names":["recordToRows","value","key","v","genId","rowsToRecord","rows","result","row","raw","configToForm","cfg","rf","params","formToConfig","form","url","headers","config","KeyValueRows","onChange","valuePlaceholder","keyPlaceholder","jsxs","jsx","Input","e","r","Button","RemoteDataEditor","setForm","useState","prevValueRef","useRef","lastEmittedRef","useEffect","commit","next","emitted","patch","partial","Space","Select","Tooltip","Collapse","InputNumber","remoteDataEditorWidget"],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { useMemo as e } from "react";
|
|
2
|
+
import { useDesigner as o } from "../designer-context.js";
|
|
3
|
+
import { collectDataFieldPaths as r, collectDataFieldOptions as s } from "../schema-utils.js";
|
|
4
|
+
function n() {
|
|
5
|
+
const { schema: t } = o();
|
|
6
|
+
return e(() => r(t), [t]);
|
|
7
|
+
}
|
|
8
|
+
function c() {
|
|
9
|
+
const { schema: t } = o();
|
|
10
|
+
return e(() => s(t), [t]);
|
|
11
|
+
}
|
|
12
|
+
export {
|
|
13
|
+
c as useFormDataFieldOptions,
|
|
14
|
+
n as useFormDataFields
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=use-form-data-fields.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-form-data-fields.js","sources":["../../../src/widgets/use-form-data-fields.ts"],"sourcesContent":["// ============================================================================\n// useFormDataFields — 从当前设计器 schema 收集 formData 字段(供变量/依赖选择)\n// ============================================================================\n\nimport { useMemo } from 'react';\nimport { useDesigner } from '../designer-context';\nimport {\n collectDataFieldOptions,\n collectDataFieldPaths,\n} from '../schema-utils';\n\nexport function useFormDataFields(): string[] {\n const { schema } = useDesigner();\n return useMemo(() => collectDataFieldPaths(schema), [schema]);\n}\n\n/** 带字段标题的选项列表:显示 title,值为路径 key(供 dependencies 等选择器) */\nexport function useFormDataFieldOptions(): Array<{\n value: string;\n label: string;\n}> {\n const { schema } = useDesigner();\n return useMemo(() => collectDataFieldOptions(schema), [schema]);\n}\n"],"names":["useFormDataFields","schema","useDesigner","useMemo","collectDataFieldPaths","useFormDataFieldOptions","collectDataFieldOptions"],"mappings":";;;AAWO,SAASA,IAA8B;AAC5C,QAAM,EAAE,QAAAC,EAAA,IAAWC,EAAA;AACnB,SAAOC,EAAQ,MAAMC,EAAsBH,CAAM,GAAG,CAACA,CAAM,CAAC;AAC9D;AAGO,SAASI,IAGb;AACD,QAAM,EAAE,QAAAJ,EAAA,IAAWC,EAAA;AACnB,SAAOC,EAAQ,MAAMG,EAAwBL,CAAM,GAAG,CAACA,CAAM,CAAC;AAChE;"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { jsxs as c, jsx as r } from "react/jsx-runtime";
|
|
2
|
+
import { Button as u, Input as k } from "antd";
|
|
3
|
+
import { useState as v, useRef as h, useEffect as R } from "react";
|
|
4
|
+
import { ExpressionBuilder as z } from "./expression-builder.js";
|
|
5
|
+
import { genId as y } from "./reactions-model.js";
|
|
6
|
+
import { useFormDataFields as B } from "./use-form-data-fields.js";
|
|
7
|
+
function g(e) {
|
|
8
|
+
return !e || typeof e != "object" ? [] : Object.entries(e).map(
|
|
9
|
+
([n, s]) => ({ id: y(), key: n, expr: String(s ?? "") })
|
|
10
|
+
);
|
|
11
|
+
}
|
|
12
|
+
function S(e) {
|
|
13
|
+
const n = {};
|
|
14
|
+
for (const s of e) {
|
|
15
|
+
const o = s.key.trim(), l = s.expr.trim();
|
|
16
|
+
!o || !l || l === "{{ }}" || (n[o] = l);
|
|
17
|
+
}
|
|
18
|
+
return Object.keys(n).length > 0 ? n : void 0;
|
|
19
|
+
}
|
|
20
|
+
function j({ value: e, onChange: n }) {
|
|
21
|
+
const s = B(), [o, l] = v(() => g(e)), m = h(e), f = h(e);
|
|
22
|
+
R(() => {
|
|
23
|
+
m.current !== e && (m.current = e, e !== f.current && l(g(e)));
|
|
24
|
+
}, [e]);
|
|
25
|
+
const a = (t) => {
|
|
26
|
+
l(t);
|
|
27
|
+
const i = S(t);
|
|
28
|
+
f.current = i, n(i);
|
|
29
|
+
}, p = (t, i) => {
|
|
30
|
+
a(o.map((d) => d.id === t ? { ...d, ...i } : d));
|
|
31
|
+
}, x = (t) => {
|
|
32
|
+
a(o.filter((i) => i.id !== t));
|
|
33
|
+
}, b = () => {
|
|
34
|
+
a([...o, { id: y(), key: "", expr: "{{ }}" }]);
|
|
35
|
+
};
|
|
36
|
+
return /* @__PURE__ */ c("div", { style: { width: "100%" }, children: [
|
|
37
|
+
o.length === 0 ? /* @__PURE__ */ r(
|
|
38
|
+
"div",
|
|
39
|
+
{
|
|
40
|
+
style: {
|
|
41
|
+
fontSize: 11,
|
|
42
|
+
color: "#999",
|
|
43
|
+
background: "#fafafa",
|
|
44
|
+
border: "1px dashed #e0e0e0",
|
|
45
|
+
borderRadius: 6,
|
|
46
|
+
padding: "6px 8px",
|
|
47
|
+
marginBottom: 4
|
|
48
|
+
},
|
|
49
|
+
children: "点击下方「添加校验规则」,组合 校验名称 + 表达式(变量 / 操作符 / 值)。表达式需返回 boolean,可用变量:$self.value、formData。"
|
|
50
|
+
}
|
|
51
|
+
) : o.map((t, i) => /* @__PURE__ */ c(
|
|
52
|
+
"div",
|
|
53
|
+
{
|
|
54
|
+
style: {
|
|
55
|
+
border: "1px solid #e8e8e8",
|
|
56
|
+
borderRadius: 8,
|
|
57
|
+
padding: 8,
|
|
58
|
+
marginBottom: 8,
|
|
59
|
+
background: "#fff"
|
|
60
|
+
},
|
|
61
|
+
children: [
|
|
62
|
+
/* @__PURE__ */ c(
|
|
63
|
+
"div",
|
|
64
|
+
{
|
|
65
|
+
style: {
|
|
66
|
+
display: "flex",
|
|
67
|
+
alignItems: "center",
|
|
68
|
+
justifyContent: "space-between",
|
|
69
|
+
marginBottom: 6
|
|
70
|
+
},
|
|
71
|
+
children: [
|
|
72
|
+
/* @__PURE__ */ c("span", { style: { fontSize: 12, fontWeight: 600, color: "#333" }, children: [
|
|
73
|
+
"校验规则 ",
|
|
74
|
+
i + 1
|
|
75
|
+
] }),
|
|
76
|
+
/* @__PURE__ */ r(u, { size: "small", danger: !0, onClick: () => x(t.id), children: "删除" })
|
|
77
|
+
]
|
|
78
|
+
}
|
|
79
|
+
),
|
|
80
|
+
/* @__PURE__ */ c("div", { style: { marginBottom: 6 }, children: [
|
|
81
|
+
/* @__PURE__ */ r("div", { style: { fontSize: 11, color: "#666", marginBottom: 2 }, children: "规则名称(key)" }),
|
|
82
|
+
/* @__PURE__ */ r(
|
|
83
|
+
k,
|
|
84
|
+
{
|
|
85
|
+
size: "small",
|
|
86
|
+
placeholder: "如 match / len",
|
|
87
|
+
value: t.key,
|
|
88
|
+
onChange: (d) => p(t.id, { key: d.target.value })
|
|
89
|
+
}
|
|
90
|
+
)
|
|
91
|
+
] }),
|
|
92
|
+
/* @__PURE__ */ c("div", { children: [
|
|
93
|
+
/* @__PURE__ */ r("div", { style: { fontSize: 11, color: "#666", marginBottom: 2 }, children: "校验表达式(需返回 boolean)" }),
|
|
94
|
+
/* @__PURE__ */ r(
|
|
95
|
+
z,
|
|
96
|
+
{
|
|
97
|
+
value: t.expr,
|
|
98
|
+
onChange: (d) => p(t.id, { expr: d }),
|
|
99
|
+
fields: s,
|
|
100
|
+
showSelf: !0,
|
|
101
|
+
placeholder: "{{ $self.value.length >= 6 }}"
|
|
102
|
+
}
|
|
103
|
+
)
|
|
104
|
+
] })
|
|
105
|
+
]
|
|
106
|
+
},
|
|
107
|
+
t.id
|
|
108
|
+
)),
|
|
109
|
+
/* @__PURE__ */ r(u, { size: "small", type: "dashed", block: !0, onClick: b, children: "+ 添加校验规则" }),
|
|
110
|
+
/* @__PURE__ */ r("div", { style: { fontSize: 11, color: "#999", marginTop: 4 }, children: "提示:依赖字段(formData.xxx)变化时会自动联动重校验。" })
|
|
111
|
+
] });
|
|
112
|
+
}
|
|
113
|
+
const V = j;
|
|
114
|
+
export {
|
|
115
|
+
j as ValidateEditor,
|
|
116
|
+
V as validateEditorWidget
|
|
117
|
+
};
|
|
118
|
+
//# sourceMappingURL=validate-editor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-editor.js","sources":["../../../src/widgets/validate-editor.tsx"],"sourcesContent":["// ============================================================================\n// ValidateEditor — 可视化编辑 validate 校验规则\n// 每行一条规则:「规则名称 + 校验表达式」(表达式需返回 boolean)\n// 与 schema 的 ValidateSchema({ key: Expression })互相转换\n// ============================================================================\n\nimport type { WidgetProps } from '@xbeeant/form-engine-ui';\nimport { Button, Input } from 'antd';\nimport { useEffect, useRef, useState } from 'react';\nimport { ExpressionBuilder } from './expression-builder';\nimport { genId } from './reactions-model';\nimport { useFormDataFields } from './use-form-data-fields';\n\ninterface ValidateRow {\n id: string;\n key: string;\n expr: string;\n}\n\n/** ValidateSchema 对象 → 规则行 */\nfunction validateToRows(value: unknown): ValidateRow[] {\n if (!value || typeof value !== 'object') {\n return [];\n }\n return Object.entries(value as Record<string, unknown>).map(\n ([key, expr]) => ({ id: genId(), key, expr: String(expr ?? '') }),\n );\n}\n\n/** 规则行 → ValidateSchema 对象(空表达式 / 空 key 的行丢弃) */\nfunction rowsToValidate(\n rows: ValidateRow[],\n): Record<string, string> | undefined {\n const result: Record<string, string> = {};\n for (const row of rows) {\n const key = row.key.trim();\n const expr = row.expr.trim();\n if (!key || !expr || expr === '{{ }}') {\n continue;\n }\n result[key] = expr;\n }\n return Object.keys(result).length > 0 ? result : undefined;\n}\n\nexport function ValidateEditor({ value, onChange }: WidgetProps) {\n const fields = useFormDataFields();\n const [rows, setRows] = useState<ValidateRow[]>(() => validateToRows(value));\n const prevValueRef = useRef(value);\n // 自身 onChange 引发的 value 回传不应触发重建(否则每次输入都被重置)\n const lastEmittedRef = useRef(value);\n\n useEffect(() => {\n if (prevValueRef.current !== value) {\n prevValueRef.current = value;\n if (value !== lastEmittedRef.current) {\n setRows(validateToRows(value));\n }\n }\n }, [value]);\n\n const commit = (next: ValidateRow[]) => {\n setRows(next);\n const emitted = rowsToValidate(next);\n lastEmittedRef.current = emitted;\n onChange(emitted);\n };\n\n const updateRow = (id: string, patch: Partial<ValidateRow>) => {\n commit(rows.map((r) => (r.id === id ? { ...r, ...patch } : r)));\n };\n\n const removeRow = (id: string) => {\n commit(rows.filter((r) => r.id !== id));\n };\n\n const addRow = () => {\n commit([...rows, { id: genId(), key: '', expr: '{{ }}' }]);\n };\n\n return (\n <div style={{ width: '100%' }}>\n {rows.length === 0 ? (\n <div\n style={{\n fontSize: 11,\n color: '#999',\n background: '#fafafa',\n border: '1px dashed #e0e0e0',\n borderRadius: 6,\n padding: '6px 8px',\n marginBottom: 4,\n }}\n >\n 点击下方「添加校验规则」,组合 校验名称 + 表达式(变量 / 操作符 /\n 值)。表达式需返回 boolean,可用变量:$self.value、formData。\n </div>\n ) : (\n rows.map((row, i) => (\n <div\n key={row.id}\n style={{\n border: '1px solid #e8e8e8',\n borderRadius: 8,\n padding: 8,\n marginBottom: 8,\n background: '#fff',\n }}\n >\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n marginBottom: 6,\n }}\n >\n <span style={{ fontSize: 12, fontWeight: 600, color: '#333' }}>\n 校验规则 {i + 1}\n </span>\n <Button size='small' danger onClick={() => removeRow(row.id)}>\n 删除\n </Button>\n </div>\n <div style={{ marginBottom: 6 }}>\n <div style={{ fontSize: 11, color: '#666', marginBottom: 2 }}>\n 规则名称(key)\n </div>\n <Input\n size='small'\n placeholder='如 match / len'\n value={row.key}\n onChange={(e) => updateRow(row.id, { key: e.target.value })}\n />\n </div>\n <div>\n <div style={{ fontSize: 11, color: '#666', marginBottom: 2 }}>\n 校验表达式(需返回 boolean)\n </div>\n <ExpressionBuilder\n value={row.expr}\n onChange={(s) => updateRow(row.id, { expr: s })}\n fields={fields}\n showSelf\n placeholder='{{ $self.value.length >= 6 }}'\n />\n </div>\n </div>\n ))\n )}\n\n <Button size='small' type='dashed' block onClick={addRow}>\n + 添加校验规则\n </Button>\n <div style={{ fontSize: 11, color: '#999', marginTop: 4 }}>\n 提示:依赖字段(formData.xxx)变化时会自动联动重校验。\n </div>\n </div>\n );\n}\n\nexport const validateEditorWidget = ValidateEditor;\n"],"names":["validateToRows","value","key","expr","genId","rowsToValidate","rows","result","row","ValidateEditor","onChange","fields","useFormDataFields","setRows","useState","prevValueRef","useRef","lastEmittedRef","useEffect","commit","next","emitted","updateRow","id","patch","r","removeRow","addRow","jsx","jsxs","Button","Input","e","ExpressionBuilder","s","validateEditorWidget"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xbeeant/form-engine-designer",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public",
|
|
6
6
|
"registry": "https://registry.npmjs.org/"
|
|
@@ -19,7 +19,6 @@
|
|
|
19
19
|
},
|
|
20
20
|
"files": [
|
|
21
21
|
"dist",
|
|
22
|
-
"src",
|
|
23
22
|
"README.md"
|
|
24
23
|
],
|
|
25
24
|
"sideEffects": [
|
|
@@ -53,11 +52,11 @@
|
|
|
53
52
|
}
|
|
54
53
|
},
|
|
55
54
|
"dependencies": {
|
|
56
|
-
"@xbeeant/form-engine": "^0.0.
|
|
57
|
-
"@xbeeant/form-engine-ui": "^0.0.
|
|
55
|
+
"@xbeeant/form-engine": "^0.0.4",
|
|
56
|
+
"@xbeeant/form-engine-ui": "^0.0.4"
|
|
58
57
|
},
|
|
59
58
|
"devDependencies": {
|
|
60
59
|
"vitest": "^4.1.10"
|
|
61
60
|
},
|
|
62
|
-
"gitHead": "
|
|
61
|
+
"gitHead": "e21b7883779d4623ce1402a1af17b4d35addf4de"
|
|
63
62
|
}
|