@xbeeant/form-engine-designer 0.0.2 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (137) hide show
  1. package/dist/es/Canvas.js +42 -46
  2. package/dist/es/Canvas.js.map +1 -1
  3. package/dist/es/Designer.js +121 -98
  4. package/dist/es/Designer.js.map +1 -1
  5. package/dist/es/DesignerContext.js +86 -73
  6. package/dist/es/DesignerContext.js.map +1 -1
  7. package/dist/es/Palette.js +3 -3
  8. package/dist/es/Palette.js.map +1 -1
  9. package/dist/es/PropertyPanel.js +97 -97
  10. package/dist/es/PropertyPanel.js.map +1 -1
  11. package/dist/es/catalog.js +19 -11
  12. package/dist/es/catalog.js.map +1 -1
  13. package/dist/es/designer-context.js +110 -0
  14. package/dist/es/designer-context.js.map +1 -0
  15. package/dist/es/history.js +73 -0
  16. package/dist/es/history.js.map +1 -0
  17. package/dist/es/index.js +3 -3
  18. package/dist/es/property/basic-property.js +6 -0
  19. package/dist/es/property/basic-property.js.map +1 -1
  20. package/dist/es/property-panel.js +294 -0
  21. package/dist/es/property-panel.js.map +1 -0
  22. package/dist/es/resizable-panel.js +103 -0
  23. package/dist/es/resizable-panel.js.map +1 -0
  24. package/dist/es/schema-utils.js +286 -0
  25. package/dist/es/schema-utils.js.map +1 -0
  26. package/dist/es/widgets/BindEditor.js +60 -49
  27. package/dist/es/widgets/BindEditor.js.map +1 -1
  28. package/dist/es/widgets/CodeEditor.js +41 -49
  29. package/dist/es/widgets/CodeEditor.js.map +1 -1
  30. package/dist/es/widgets/DefaultEditor.js +25 -30
  31. package/dist/es/widgets/DefaultEditor.js.map +1 -1
  32. package/dist/es/widgets/DependenciesEditor.js +21 -21
  33. package/dist/es/widgets/DependenciesEditor.js.map +1 -1
  34. package/dist/es/widgets/EnumEditor.js +25 -31
  35. package/dist/es/widgets/EnumEditor.js.map +1 -1
  36. package/dist/es/widgets/ExpressionSwitch.js +32 -30
  37. package/dist/es/widgets/ExpressionSwitch.js.map +1 -1
  38. package/dist/es/widgets/ReactionsEditor.js +103 -103
  39. package/dist/es/widgets/ReactionsEditor.js.map +1 -1
  40. package/dist/es/widgets/RemoteDataEditor.js +63 -63
  41. package/dist/es/widgets/RemoteDataEditor.js.map +1 -1
  42. package/dist/es/widgets/ValidateEditor.js +49 -49
  43. package/dist/es/widgets/ValidateEditor.js.map +1 -1
  44. package/dist/es/widgets/bind-editor.js +78 -0
  45. package/dist/es/widgets/bind-editor.js.map +1 -0
  46. package/dist/es/widgets/code-editor.js +76 -0
  47. package/dist/es/widgets/code-editor.js.map +1 -0
  48. package/dist/es/widgets/default-editor.js +50 -0
  49. package/dist/es/widgets/default-editor.js.map +1 -0
  50. package/dist/es/widgets/dependencies-editor.js +36 -0
  51. package/dist/es/widgets/dependencies-editor.js.map +1 -0
  52. package/dist/es/widgets/enum-editor.js +43 -0
  53. package/dist/es/widgets/enum-editor.js.map +1 -0
  54. package/dist/es/widgets/expression-builder.js +367 -0
  55. package/dist/es/widgets/expression-builder.js.map +1 -0
  56. package/dist/es/widgets/expression-model.js +340 -0
  57. package/dist/es/widgets/expression-model.js.map +1 -0
  58. package/dist/es/widgets/expression-switch.js +49 -0
  59. package/dist/es/widgets/expression-switch.js.map +1 -0
  60. package/dist/es/widgets/index.js +13 -13
  61. package/dist/es/widgets/index.js.map +1 -1
  62. package/dist/es/widgets/options-editor.js +102 -0
  63. package/dist/es/widgets/options-editor.js.map +1 -0
  64. package/dist/es/widgets/reactions-editor.js +401 -0
  65. package/dist/es/widgets/reactions-editor.js.map +1 -0
  66. package/dist/es/widgets/reactions-model.js +107 -0
  67. package/dist/es/widgets/reactions-model.js.map +1 -0
  68. package/dist/es/widgets/remote-data-editor.js +314 -0
  69. package/dist/es/widgets/remote-data-editor.js.map +1 -0
  70. package/dist/es/widgets/use-form-data-fields.js +16 -0
  71. package/dist/es/widgets/use-form-data-fields.js.map +1 -0
  72. package/dist/es/widgets/validate-editor.js +118 -0
  73. package/dist/es/widgets/validate-editor.js.map +1 -0
  74. package/package.json +4 -5
  75. package/dist/es/react/src/components/FormController.js +0 -154
  76. package/dist/es/react/src/components/FormController.js.map +0 -1
  77. package/dist/es/react/src/components/NexusField.js +0 -99
  78. package/dist/es/react/src/components/NexusField.js.map +0 -1
  79. package/dist/es/react/src/components/NexusForm.js +0 -121
  80. package/dist/es/react/src/components/NexusForm.js.map +0 -1
  81. package/dist/es/react/src/components/NexusFormProvider.js +0 -19
  82. package/dist/es/react/src/components/NexusFormProvider.js.map +0 -1
  83. package/dist/es/react/src/components/NexusLayout.js +0 -49
  84. package/dist/es/react/src/components/NexusLayout.js.map +0 -1
  85. package/dist/es/react/src/components/NexusObject.js +0 -65
  86. package/dist/es/react/src/components/NexusObject.js.map +0 -1
  87. package/dist/es/react/src/contexts/FieldInheritContext.js +0 -6
  88. package/dist/es/react/src/contexts/FieldInheritContext.js.map +0 -1
  89. package/dist/es/react/src/contexts/GridContext.js +0 -6
  90. package/dist/es/react/src/contexts/GridContext.js.map +0 -1
  91. package/dist/es/react/src/contexts/LayoutConfigContext.js +0 -6
  92. package/dist/es/react/src/contexts/LayoutConfigContext.js.map +0 -1
  93. package/dist/es/react/src/contexts/NexusContext.js +0 -13
  94. package/dist/es/react/src/contexts/NexusContext.js.map +0 -1
  95. package/dist/es/react/src/hooks/useForm.js +0 -10
  96. package/dist/es/react/src/hooks/useForm.js.map +0 -1
  97. package/dist/es/react/src/utils/renderTreeNode.js +0 -18
  98. package/dist/es/react/src/utils/renderTreeNode.js.map +0 -1
  99. package/dist/es/react/src/utils/resolveColSpan.js +0 -10
  100. package/dist/es/react/src/utils/resolveColSpan.js.map +0 -1
  101. package/dist/es/schemaUtils.test.js +0 -188
  102. package/dist/es/schemaUtils.test.js.map +0 -1
  103. package/dist/es/vite-env.d.js +0 -2
  104. package/dist/es/vite-env.d.js.map +0 -1
  105. package/dist/es/widgets/expressionModel.test.js +0 -193
  106. package/dist/es/widgets/expressionModel.test.js.map +0 -1
  107. package/src/Canvas.tsx +0 -1111
  108. package/src/Designer.css +0 -206
  109. package/src/Designer.tsx +0 -254
  110. package/src/DesignerContext.tsx +0 -192
  111. package/src/Palette.tsx +0 -261
  112. package/src/PropertyPanel.tsx +0 -486
  113. package/src/ResizablePanel.tsx +0 -210
  114. package/src/catalog.ts +0 -526
  115. package/src/index.ts +0 -25
  116. package/src/property/basic-property.ts +0 -126
  117. package/src/schemaUtils.test.ts +0 -261
  118. package/src/schemaUtils.ts +0 -627
  119. package/src/types.ts +0 -38
  120. package/src/vite-env.d.ts +0 -1
  121. package/src/widgets/BindEditor.tsx +0 -105
  122. package/src/widgets/CodeEditor.tsx +0 -114
  123. package/src/widgets/DefaultEditor.tsx +0 -73
  124. package/src/widgets/DependenciesEditor.tsx +0 -56
  125. package/src/widgets/EnumEditor.tsx +0 -66
  126. package/src/widgets/ExpressionBuilder.tsx +0 -509
  127. package/src/widgets/ExpressionSwitch.tsx +0 -62
  128. package/src/widgets/OptionsEditor.tsx +0 -141
  129. package/src/widgets/ReactionsEditor.tsx +0 -532
  130. package/src/widgets/RemoteDataEditor.tsx +0 -382
  131. package/src/widgets/ValidateEditor.tsx +0 -162
  132. package/src/widgets/expressionModel.test.ts +0 -262
  133. package/src/widgets/expressionModel.ts +0 -573
  134. package/src/widgets/index.ts +0 -45
  135. package/src/widgets/reactionsModel.ts +0 -190
  136. package/src/widgets/useFormDataFields.ts +0 -21
  137. /package/dist/es/{form-engine-designer.css → index.css} +0 -0
@@ -1,52 +1,52 @@
1
1
  import { jsx as i, jsxs as d } from "react/jsx-runtime";
2
- import { Form as k, Space as p, Input as h, Select as S, Tooltip as u, Collapse as C, InputNumber as P, Button as y } from "antd";
3
- import { useState as T, useRef as f, useEffect as I } from "react";
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
4
  import { genId as x } from "./reactionsModel.js";
5
5
  function v(e) {
6
- return !e || typeof e != "object" ? [] : Object.entries(e).map(([t, n]) => ({
6
+ return !e || typeof e != "object" ? [] : Object.entries(e).map(([l, t]) => ({
7
7
  id: x(),
8
- key: t,
9
- value: typeof n == "string" ? n : JSON.stringify(n)
8
+ key: l,
9
+ value: typeof t == "string" ? t : JSON.stringify(t)
10
10
  }));
11
11
  }
12
12
  function g(e) {
13
13
  if (!e)
14
14
  return;
15
- const t = {};
16
- for (const n of e) {
17
- const l = n.key.trim();
18
- if (!l)
15
+ const l = {};
16
+ for (const t of e) {
17
+ const n = t.key.trim();
18
+ if (!n)
19
19
  continue;
20
- const r = n.value.trim();
20
+ const r = t.value.trim();
21
21
  if (r)
22
22
  try {
23
- t[l] = JSON.parse(r);
23
+ l[n] = JSON.parse(r);
24
24
  } catch {
25
- t[l] = r;
25
+ l[n] = r;
26
26
  }
27
27
  }
28
- return Object.keys(t).length > 0 ? t : void 0;
28
+ return Object.keys(l).length > 0 ? l : void 0;
29
29
  }
30
30
  function b(e) {
31
- const t = e ?? {}, n = t.responseField ?? {}, l = t.params;
31
+ const l = e ?? {}, t = l.responseField ?? {}, n = l.params;
32
32
  return {
33
- url: t.url,
34
- method: t.method,
35
- dataPath: n.data,
36
- valueKey: n.value,
37
- labelKey: n.label,
38
- params: l && typeof l == "object" ? v(l) : void 0,
39
- headers: v(t.headers),
40
- cacheKey: t.cacheKey,
41
- timeout: t.timeout
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
42
  };
43
43
  }
44
- function w(e) {
45
- const t = e.url?.trim();
46
- if (!t)
44
+ function T(e) {
45
+ const l = e.url?.trim();
46
+ if (!l)
47
47
  return;
48
- const n = g(e.params), l = g(e.headers), r = {
49
- url: t,
48
+ const t = g(e.params), n = g(e.headers), r = {
49
+ url: l,
50
50
  method: e.method || "GET",
51
51
  responseField: {
52
52
  data: e.dataPath?.trim() || "data",
@@ -54,13 +54,13 @@ function w(e) {
54
54
  label: e.labelKey?.trim() || "label"
55
55
  }
56
56
  };
57
- return n && (r.params = n), l && (r.headers = l), e.cacheKey?.trim() && (r.cacheKey = e.cacheKey.trim()), e.timeout != null && (r.timeout = e.timeout), r;
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
58
  }
59
59
  function z({
60
60
  rows: e,
61
- onChange: t,
62
- valuePlaceholder: n,
63
- keyPlaceholder: l
61
+ onChange: l,
62
+ valuePlaceholder: t,
63
+ keyPlaceholder: n
64
64
  }) {
65
65
  return /* @__PURE__ */ d("div", { style: { width: "100%" }, children: [
66
66
  e.map((r) => /* @__PURE__ */ d(
@@ -78,8 +78,8 @@ function z({
78
78
  {
79
79
  size: "small",
80
80
  value: r.key,
81
- placeholder: l,
82
- onChange: (c) => t(
81
+ placeholder: n,
82
+ onChange: (c) => l(
83
83
  e.map(
84
84
  (o) => o.id === r.id ? { ...o, key: c.target.value } : o
85
85
  )
@@ -91,8 +91,8 @@ function z({
91
91
  {
92
92
  size: "small",
93
93
  value: r.value,
94
- placeholder: n,
95
- onChange: (c) => t(
94
+ placeholder: t,
95
+ onChange: (c) => l(
96
96
  e.map(
97
97
  (o) => o.id === r.id ? { ...o, value: c.target.value } : o
98
98
  )
@@ -105,7 +105,7 @@ function z({
105
105
  size: "small",
106
106
  type: "text",
107
107
  danger: !0,
108
- onClick: () => t(e.filter((c) => c.id !== r.id)),
108
+ onClick: () => l(e.filter((c) => c.id !== r.id)),
109
109
  children: "✕"
110
110
  }
111
111
  )
@@ -119,42 +119,42 @@ function z({
119
119
  size: "small",
120
120
  type: "dashed",
121
121
  block: !0,
122
- onClick: () => t([...e, { id: x(), key: "", value: "" }]),
122
+ onClick: () => l([...e, { id: x(), key: "", value: "" }]),
123
123
  children: "+ 添加"
124
124
  }
125
125
  )
126
126
  ] });
127
127
  }
128
- function E({ value: e, onChange: t, title: n }) {
129
- const [l, r] = T(() => b(e)), c = f(e), o = f(e);
130
- I(() => {
131
- c.current !== e && (c.current = e, e !== o.current && r(b(e)));
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
132
  }, [e]);
133
- const K = (a) => {
134
- r(a);
135
- const m = w(a);
136
- o.current = m, t(m);
133
+ const o = (a) => {
134
+ n(a);
135
+ const m = T(a);
136
+ c.current = m, l(m);
137
137
  }, s = (a) => {
138
- K({ ...l, ...a });
138
+ o({ ...t, ...a });
139
139
  };
140
- return /* @__PURE__ */ i(k.Item, { layout: "vertical", label: n, style: { width: "100%" }, children: /* @__PURE__ */ d(p, { orientation: "vertical", style: { width: "100%" }, size: 8, children: [
140
+ return /* @__PURE__ */ i("div", { style: { width: "100%" }, children: /* @__PURE__ */ d(p, { orientation: "vertical", style: { width: "100%" }, size: 8, children: [
141
141
  /* @__PURE__ */ d("div", { style: { display: "flex", gap: 6, alignItems: "center" }, children: [
142
142
  /* @__PURE__ */ i(
143
143
  h,
144
144
  {
145
145
  size: "small",
146
146
  placeholder: "接口地址(必填),如 /api/options",
147
- value: l.url,
147
+ value: t.url,
148
148
  onChange: (a) => s({ url: a.target.value }),
149
149
  style: { flex: 1 }
150
150
  }
151
151
  ),
152
152
  /* @__PURE__ */ i(
153
- S,
153
+ K,
154
154
  {
155
155
  size: "small",
156
156
  style: { width: 80 },
157
- value: l.method,
157
+ value: t.method,
158
158
  onChange: (a) => s({ method: a }),
159
159
  options: [
160
160
  { value: "GET", label: "GET" },
@@ -170,7 +170,7 @@ function E({ value: e, onChange: t, title: n }) {
170
170
  {
171
171
  size: "small",
172
172
  placeholder: "数据路径(默认 data)",
173
- value: l.dataPath,
173
+ value: t.dataPath,
174
174
  onChange: (a) => s({ dataPath: a.target.value }),
175
175
  style: { flex: 1 }
176
176
  }
@@ -180,7 +180,7 @@ function E({ value: e, onChange: t, title: n }) {
180
180
  {
181
181
  size: "small",
182
182
  placeholder: "值字段",
183
- value: l.valueKey,
183
+ value: t.valueKey,
184
184
  onChange: (a) => s({ valueKey: a.target.value }),
185
185
  style: { flex: 1 }
186
186
  }
@@ -190,14 +190,14 @@ function E({ value: e, onChange: t, title: n }) {
190
190
  {
191
191
  size: "small",
192
192
  placeholder: "文案字段",
193
- value: l.labelKey,
193
+ value: t.labelKey,
194
194
  onChange: (a) => s({ labelKey: a.target.value }),
195
195
  style: { flex: 1 }
196
196
  }
197
197
  ) })
198
198
  ] }),
199
199
  /* @__PURE__ */ i(
200
- C,
200
+ k,
201
201
  {
202
202
  size: "small",
203
203
  style: { width: "100%", background: "#fafafa" },
@@ -208,7 +208,7 @@ function E({ value: e, onChange: t, title: n }) {
208
208
  children: /* @__PURE__ */ i(
209
209
  z,
210
210
  {
211
- rows: l.params ?? [],
211
+ rows: t.params ?? [],
212
212
  onChange: (a) => s({ params: a }),
213
213
  keyPlaceholder: "参数名",
214
214
  valuePlaceholder: "参数值(数字/布尔自动识别)"
@@ -221,7 +221,7 @@ function E({ value: e, onChange: t, title: n }) {
221
221
  children: /* @__PURE__ */ i(
222
222
  z,
223
223
  {
224
- rows: l.headers ?? [],
224
+ rows: t.headers ?? [],
225
225
  onChange: (a) => s({ headers: a }),
226
226
  keyPlaceholder: "请求头名",
227
227
  valuePlaceholder: "如 Bearer xxxx"
@@ -259,7 +259,7 @@ function E({ value: e, onChange: t, title: n }) {
259
259
  {
260
260
  size: "small",
261
261
  placeholder: "默认按字段路径缓存",
262
- value: l.cacheKey,
262
+ value: t.cacheKey,
263
263
  onChange: (a) => s({ cacheKey: a.target.value })
264
264
  }
265
265
  )
@@ -283,11 +283,11 @@ function E({ value: e, onChange: t, title: n }) {
283
283
  }
284
284
  ),
285
285
  /* @__PURE__ */ i(
286
- P,
286
+ S,
287
287
  {
288
288
  size: "small",
289
289
  min: 1,
290
- value: l.timeout,
290
+ value: t.timeout,
291
291
  onChange: (a) => s({ timeout: a ?? void 0 }),
292
292
  placeholder: "默认 10",
293
293
  style: { width: 120 }
@@ -306,9 +306,9 @@ function E({ value: e, onChange: t, title: n }) {
306
306
  /* @__PURE__ */ i("div", { style: { fontSize: 11, color: "#ccc" }, children: "提示:字段值变化后选项自动刷新;POST 时参数放入请求体" })
307
307
  ] }) });
308
308
  }
309
- const B = E;
309
+ const j = w;
310
310
  export {
311
- E as RemoteDataEditor,
312
- B as remoteDataEditorWidget
311
+ w as RemoteDataEditor,
312
+ j as remoteDataEditorWidget
313
313
  };
314
314
  //# sourceMappingURL=RemoteDataEditor.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"RemoteDataEditor.js","sources":["../../../src/widgets/RemoteDataEditor.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 Form,\n Input,\n InputNumber,\n Select,\n Space,\n Tooltip,\n} from 'antd';\nimport { useEffect, useRef, useState } from 'react';\nimport { genId } from './reactionsModel';\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, title }: 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 <Form.Item layout={'vertical'} label={title} 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 </Form.Item>\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","title","setForm","useState","prevValueRef","useRef","lastEmittedRef","useEffect","commit","next","emitted","patch","partial","Form","Space","Select","Tooltip","Collapse","InputNumber","remoteDataEditorWidget"],"mappings":";;;;AA4CA,SAASA,EACPC,GACe;AACf,SAAI,CAACA,KAAS,OAAOA,KAAU,WACtB,CAAA,IAEF,OAAO,QAAQA,CAAK,EAAE,IAAI,CAAC,CAACC,GAAKC,CAAC,OAAO;AAAA,IAC9C,IAAIC,EAAA;AAAA,IACJ,KAAAF;AAAA,IACA,OAAO,OAAOC,KAAM,WAAWA,IAAI,KAAK,UAAUA,CAAC;AAAA,EAAA,EACnD;AACJ;AAGA,SAASE,EACPC,GACqC;AACrC,MAAI,CAACA;AACH;AAEF,QAAMC,IAAkC,CAAA;AACxC,aAAWC,KAAOF,GAAM;AACtB,UAAMJ,IAAMM,EAAI,IAAI,KAAA;AACpB,QAAI,CAACN;AACH;AAEF,UAAMO,IAAMD,EAAI,MAAM,KAAA;AACtB,QAAKC;AAIL,UAAI;AACF,QAAAF,EAAOL,CAAG,IAAI,KAAK,MAAMO,CAAG;AAAA,MAC9B,QAAQ;AACN,QAAAF,EAAOL,CAAG,IAAIO;AAAA,MAChB;AAAA,EACF;AACA,SAAO,OAAO,KAAKF,CAAM,EAAE,SAAS,IAAIA,IAAS;AACnD;AAGA,SAASG,EAAaT,GAAgC;AACpD,QAAMU,IAAOV,KAAS,CAAA,GAChBW,IAAMD,EAAI,iBAAiB,CAAA,GAC3BE,IAASF,EAAI;AACnB,SAAO;AAAA,IACL,KAAKA,EAAI;AAAA,IACT,QAAQA,EAAI;AAAA,IACZ,UAAUC,EAAG;AAAA,IACb,UAAUA,EAAG;AAAA,IACb,UAAUA,EAAG;AAAA,IACb,QACEC,KAAU,OAAOA,KAAW,WAAWb,EAAaa,CAAM,IAAI;AAAA,IAChE,SAASb,EAAaW,EAAI,OAAO;AAAA,IACjC,UAAUA,EAAI;AAAA,IACd,SAASA,EAAI;AAAA,EAAA;AAEjB;AAGA,SAASG,EACPC,GACqC;AACrC,QAAMC,IAAMD,EAAK,KAAK,KAAA;AACtB,MAAI,CAACC;AACH;AAEF,QAAMH,IAASR,EAAaU,EAAK,MAAM,GACjCE,IAAUZ,EAAaU,EAAK,OAAO,GACnCG,IAAkC;AAAA,IACtC,KAAAF;AAAA,IACA,QAAQD,EAAK,UAAU;AAAA,IACvB,eAAe;AAAA,MACb,MAAMA,EAAK,UAAU,KAAA,KAAU;AAAA,MAC/B,OAAOA,EAAK,UAAU,KAAA,KAAU;AAAA,MAChC,OAAOA,EAAK,UAAU,UAAU;AAAA,IAAA;AAAA,EAClC;AAEF,SAAIF,MACFK,EAAO,SAASL,IAEdI,MACFC,EAAO,UAAUD,IAEfF,EAAK,UAAU,WACjBG,EAAO,WAAWH,EAAK,SAAS,KAAA,IAE9BA,EAAK,WAAW,SAClBG,EAAO,UAAUH,EAAK,UAEjBG;AACT;AAGA,SAASC,EAAa;AAAA,EACpB,MAAAb;AAAA,EACA,UAAAc;AAAA,EACA,kBAAAC;AAAA,EACA,gBAAAC;AACF,GAKG;AACD,2BACG,OAAA,EAAI,OAAO,EAAE,OAAO,UAClB,UAAA;AAAA,IAAAhB,EAAK,IAAI,CAACE,MACT,gBAAAe;AAAA,MAAC;AAAA,MAAA;AAAA,QAEC,OAAO;AAAA,UACL,SAAS;AAAA,UACT,KAAK;AAAA,UACL,YAAY;AAAA,UACZ,cAAc;AAAA,QAAA;AAAA,QAGhB,UAAA;AAAA,UAAA,gBAAAC;AAAA,YAACC;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,OAAOjB,EAAI;AAAA,cACX,aAAac;AAAA,cACb,UAAU,CAACI,MACTN;AAAA,gBACEd,EAAK;AAAA,kBAAI,CAACqB,MACRA,EAAE,OAAOnB,EAAI,KAAK,EAAE,GAAGmB,GAAG,KAAKD,EAAE,OAAO,UAAUC;AAAA,gBAAA;AAAA,cACpD;AAAA,YACF;AAAA,UAAA;AAAA,UAGJ,gBAAAH;AAAA,YAACC;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,OAAOjB,EAAI;AAAA,cACX,aAAaa;AAAA,cACb,UAAU,CAACK,MACTN;AAAA,gBACEd,EAAK;AAAA,kBAAI,CAACqB,MACRA,EAAE,OAAOnB,EAAI,KAAK,EAAE,GAAGmB,GAAG,OAAOD,EAAE,OAAO,UAAUC;AAAA,gBAAA;AAAA,cACtD;AAAA,YACF;AAAA,UAAA;AAAA,UAGJ,gBAAAH;AAAA,YAACI;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,MAAK;AAAA,cACL,QAAM;AAAA,cACN,SAAS,MAAMR,EAASd,EAAK,OAAO,CAACqB,MAAMA,EAAE,OAAOnB,EAAI,EAAE,CAAC;AAAA,cAC5D,UAAA;AAAA,YAAA;AAAA,UAAA;AAAA,QAED;AAAA,MAAA;AAAA,MAvCKA,EAAI;AAAA,IAAA,CAyCZ;AAAA,IACD,gBAAAgB;AAAA,MAACI;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,MAAK;AAAA,QACL,OAAK;AAAA,QACL,SAAS,MAAMR,EAAS,CAAC,GAAGd,GAAM,EAAE,IAAIF,EAAA,GAAS,KAAK,IAAI,OAAO,GAAA,CAAI,CAAC;AAAA,QACvE,UAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAED,GACF;AAEJ;AAEO,SAASyB,EAAiB,EAAE,OAAA5B,GAAO,UAAAmB,GAAU,OAAAU,KAAsB;AACxE,QAAM,CAACf,GAAMgB,CAAO,IAAIC,EAAyB,MAAMtB,EAAaT,CAAK,CAAC,GACpEgC,IAAeC,EAAOjC,CAAK,GAE3BkC,IAAiBD,EAAOjC,CAAK;AAEnC,EAAAmC,EAAU,MAAM;AACd,IAAIH,EAAa,YAAYhC,MAC3BgC,EAAa,UAAUhC,GACnBA,MAAUkC,EAAe,WAC3BJ,EAAQrB,EAAaT,CAAK,CAAC;AAAA,EAGjC,GAAG,CAACA,CAAK,CAAC;AAEV,QAAMoC,IAAS,CAACC,MAAyB;AACvC,IAAAP,EAAQO,CAAI;AACZ,UAAMC,IAAUzB,EAAawB,CAAI;AACjC,IAAAH,EAAe,UAAUI,GACzBnB,EAASmB,CAAO;AAAA,EAClB,GAEMC,IAAQ,CAACC,MAAqC;AAClD,IAAAJ,EAAO,EAAE,GAAGtB,GAAM,GAAG0B,GAAS;AAAA,EAChC;AAEA,SACE,gBAAAjB,EAACkB,EAAK,MAAL,EAAU,QAAQ,YAAY,OAAOZ,GAAO,OAAO,EAAE,OAAO,UAC3D,UAAA,gBAAAP,EAACoB,GAAA,EAAM,aAAY,YAAW,OAAO,EAAE,OAAO,OAAA,GAAU,MAAM,GAE5D,UAAA;AAAA,IAAA,gBAAApB,EAAC,OAAA,EAAI,OAAO,EAAE,SAAS,QAAQ,KAAK,GAAG,YAAY,SAAA,GACjD,UAAA;AAAA,MAAA,gBAAAC;AAAA,QAACC;AAAA,QAAA;AAAA,UACC,MAAK;AAAA,UACL,aAAY;AAAA,UACZ,OAAOV,EAAK;AAAA,UACZ,UAAU,CAACW,MAAMc,EAAM,EAAE,KAAKd,EAAE,OAAO,OAAO;AAAA,UAC9C,OAAO,EAAE,MAAM,EAAA;AAAA,QAAE;AAAA,MAAA;AAAA,MAEnB,gBAAAF;AAAA,QAACoB;AAAA,QAAA;AAAA,UACC,MAAK;AAAA,UACL,OAAO,EAAE,OAAO,GAAA;AAAA,UAChB,OAAO7B,EAAK;AAAA,UACZ,UAAU,CAACZ,MAAMqC,EAAM,EAAE,QAAQrC,GAAG;AAAA,UACpC,SAAS;AAAA,YACP,EAAE,OAAO,OAAO,OAAO,MAAA;AAAA,YACvB,EAAE,OAAO,QAAQ,OAAO,OAAA;AAAA,UAAO;AAAA,QACjC;AAAA,MAAA;AAAA,IACF,GACF;AAAA,IAGA,gBAAAqB,EAAC,SAAI,OAAO,EAAE,UAAU,IAAI,OAAO,OAAA,GAAU,UAAA,SAAA,CAAM;AAAA,IACnD,gBAAAD,EAAC,OAAA,EAAI,OAAO,EAAE,SAAS,QAAQ,KAAK,GAAG,YAAY,SAAA,GACjD,UAAA;AAAA,MAAA,gBAAAC,EAACqB,GAAA,EAAQ,OAAM,+CACb,UAAA,gBAAArB;AAAA,QAACC;AAAA,QAAA;AAAA,UACC,MAAK;AAAA,UACL,aAAY;AAAA,UACZ,OAAOV,EAAK;AAAA,UACZ,UAAU,CAACW,MAAMc,EAAM,EAAE,UAAUd,EAAE,OAAO,OAAO;AAAA,UACnD,OAAO,EAAE,MAAM,EAAA;AAAA,QAAE;AAAA,MAAA,GAErB;AAAA,MACA,gBAAAF,EAACqB,GAAA,EAAQ,OAAM,oBACb,UAAA,gBAAArB;AAAA,QAACC;AAAA,QAAA;AAAA,UACC,MAAK;AAAA,UACL,aAAY;AAAA,UACZ,OAAOV,EAAK;AAAA,UACZ,UAAU,CAACW,MAAMc,EAAM,EAAE,UAAUd,EAAE,OAAO,OAAO;AAAA,UACnD,OAAO,EAAE,MAAM,EAAA;AAAA,QAAE;AAAA,MAAA,GAErB;AAAA,MACA,gBAAAF,EAACqB,GAAA,EAAQ,OAAM,qBACb,UAAA,gBAAArB;AAAA,QAACC;AAAA,QAAA;AAAA,UACC,MAAK;AAAA,UACL,aAAY;AAAA,UACZ,OAAOV,EAAK;AAAA,UACZ,UAAU,CAACW,MAAMc,EAAM,EAAE,UAAUd,EAAE,OAAO,OAAO;AAAA,UACnD,OAAO,EAAE,MAAM,EAAA;AAAA,QAAE;AAAA,MAAA,EACnB,CACF;AAAA,IAAA,GACF;AAAA,IAGA,gBAAAF;AAAA,MAACsB;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,OAAO,EAAE,OAAO,QAAQ,YAAY,UAAA;AAAA,QACpC,OAAO;AAAA,UACL;AAAA,YACE,KAAK;AAAA,YACL,OAAO;AAAA,YACP,UACE,gBAAAtB;AAAA,cAACL;AAAA,cAAA;AAAA,gBACC,MAAMJ,EAAK,UAAU,CAAA;AAAA,gBACrB,UAAU,CAACT,MAASkC,EAAM,EAAE,QAAQlC,GAAM;AAAA,gBAC1C,gBAAe;AAAA,gBACf,kBAAiB;AAAA,cAAA;AAAA,YAAA;AAAA,UACnB;AAAA,UAGJ;AAAA,YACE,KAAK;AAAA,YACL,OAAO;AAAA,YACP,UACE,gBAAAkB;AAAA,cAACL;AAAA,cAAA;AAAA,gBACC,MAAMJ,EAAK,WAAW,CAAA;AAAA,gBACtB,UAAU,CAACT,MAASkC,EAAM,EAAE,SAASlC,GAAM;AAAA,gBAC3C,gBAAe;AAAA,gBACf,kBAAiB;AAAA,cAAA;AAAA,YAAA;AAAA,UACnB;AAAA,UAGJ;AAAA,YACE,KAAK;AAAA,YACL,OAAO;AAAA,YACP,UACE,gBAAAiB;AAAA,cAACoB;AAAA,cAAA;AAAA,gBACC,aAAY;AAAA,gBACZ,OAAO,EAAE,OAAO,OAAA;AAAA,gBAChB,MAAM;AAAA,gBAEN,UAAA;AAAA,kBAAA,gBAAApB;AAAA,oBAAC;AAAA,oBAAA;AAAA,sBACC,OAAO,EAAE,SAAS,QAAQ,KAAK,GAAG,YAAY,SAAA;AAAA,sBAE9C,UAAA;AAAA,wBAAA,gBAAAC;AAAA,0BAAC;AAAA,0BAAA;AAAA,4BACC,OAAO;AAAA,8BACL,UAAU;AAAA,8BACV,OAAO;AAAA,8BACP,YAAY;AAAA,4BAAA;AAAA,4BAEf,UAAA;AAAA,0BAAA;AAAA,wBAAA;AAAA,wBAGD,gBAAAA;AAAA,0BAACC;AAAA,0BAAA;AAAA,4BACC,MAAK;AAAA,4BACL,aAAY;AAAA,4BACZ,OAAOV,EAAK;AAAA,4BACZ,UAAU,CAACW,MAAMc,EAAM,EAAE,UAAUd,EAAE,OAAO,MAAA,CAAO;AAAA,0BAAA;AAAA,wBAAA;AAAA,sBACrD;AAAA,oBAAA;AAAA,kBAAA;AAAA,kBAEF,gBAAAH;AAAA,oBAAC;AAAA,oBAAA;AAAA,sBACC,OAAO,EAAE,SAAS,QAAQ,KAAK,GAAG,YAAY,SAAA;AAAA,sBAE9C,UAAA;AAAA,wBAAA,gBAAAC;AAAA,0BAAC;AAAA,0BAAA;AAAA,4BACC,OAAO;AAAA,8BACL,UAAU;AAAA,8BACV,OAAO;AAAA,8BACP,YAAY;AAAA,4BAAA;AAAA,4BAEf,UAAA;AAAA,0BAAA;AAAA,wBAAA;AAAA,wBAGD,gBAAAA;AAAA,0BAACuB;AAAA,0BAAA;AAAA,4BACC,MAAK;AAAA,4BACL,KAAK;AAAA,4BACL,OAAOhC,EAAK;AAAA,4BACZ,UAAU,CAACZ,MAAMqC,EAAM,EAAE,SAASrC,KAAK,QAAW;AAAA,4BAClD,aAAY;AAAA,4BACZ,OAAO,EAAE,OAAO,IAAA;AAAA,0BAAI;AAAA,wBAAA;AAAA,sBACtB;AAAA,oBAAA;AAAA,kBAAA;AAAA,gBACF;AAAA,cAAA;AAAA,YAAA;AAAA,UACF;AAAA,QAEJ;AAAA,MACF;AAAA,IAAA;AAAA,IAGF,gBAAAqB,EAAC,SAAI,OAAO,EAAE,UAAU,IAAI,OAAO,OAAA,GAAU,UAAA,gCAAA,CAE7C;AAAA,EAAA,EAAA,CACF,EAAA,CACF;AAEJ;AAEO,MAAMwB,IAAyBnB;"}
1
+ {"version":3,"file":"RemoteDataEditor.js","sources":["../../../src/widgets/RemoteDataEditor.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 './reactionsModel';\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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"}
@@ -1,40 +1,40 @@
1
- import { jsxs as s, jsx as i } from "react/jsx-runtime";
2
- import { Form as v, Button as h, Input as R } from "antd";
3
- import { useState as z, useRef as g, useEffect as B } from "react";
4
- import { ExpressionBuilder as S } from "./ExpressionBuilder.js";
5
- import { genId as x } from "./reactionsModel.js";
6
- import { useFormDataFields as j } from "./useFormDataFields.js";
7
- function y(e) {
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 "./ExpressionBuilder.js";
5
+ import { genId as y } from "./reactionsModel.js";
6
+ import { useFormDataFields as B } from "./useFormDataFields.js";
7
+ function g(e) {
8
8
  return !e || typeof e != "object" ? [] : Object.entries(e).map(
9
- ([n, l]) => ({ id: x(), key: n, expr: String(l ?? "") })
9
+ ([n, s]) => ({ id: y(), key: n, expr: String(s ?? "") })
10
10
  );
11
11
  }
12
- function w(e) {
12
+ function S(e) {
13
13
  const n = {};
14
- for (const l of e) {
15
- const a = l.key.trim(), o = l.expr.trim();
16
- !a || !o || o === "{{ }}" || (n[a] = o);
14
+ for (const s of e) {
15
+ const o = s.key.trim(), l = s.expr.trim();
16
+ !o || !l || l === "{{ }}" || (n[o] = l);
17
17
  }
18
18
  return Object.keys(n).length > 0 ? n : void 0;
19
19
  }
20
- function C({ value: e, onChange: n, title: l }) {
21
- const a = j(), [o, m] = z(() => y(e)), f = g(e), p = g(e);
22
- B(() => {
23
- f.current !== e && (f.current = e, e !== p.current && m(y(e)));
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
24
  }, [e]);
25
- const c = (t) => {
26
- m(t);
27
- const r = w(t);
28
- p.current = r, n(r);
29
- }, u = (t, r) => {
30
- c(o.map((d) => d.id === t ? { ...d, ...r } : d));
31
- }, b = (t) => {
32
- c(o.filter((r) => r.id !== t));
33
- }, k = () => {
34
- c([...o, { id: x(), key: "", expr: "{{ }}" }]);
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
35
  };
36
- return /* @__PURE__ */ s(v.Item, { layout: "vertical", label: l, style: { width: "100%" }, children: [
37
- o.length === 0 ? /* @__PURE__ */ i(
36
+ return /* @__PURE__ */ c("div", { style: { width: "100%" }, children: [
37
+ o.length === 0 ? /* @__PURE__ */ r(
38
38
  "div",
39
39
  {
40
40
  style: {
@@ -48,7 +48,7 @@ function C({ value: e, onChange: n, title: l }) {
48
48
  },
49
49
  children: "点击下方「添加校验规则」,组合 校验名称 + 表达式(变量 / 操作符 / 值)。表达式需返回 boolean,可用变量:$self.value、formData。"
50
50
  }
51
- ) : o.map((t, r) => /* @__PURE__ */ s(
51
+ ) : o.map((t, i) => /* @__PURE__ */ c(
52
52
  "div",
53
53
  {
54
54
  style: {
@@ -59,7 +59,7 @@ function C({ value: e, onChange: n, title: l }) {
59
59
  background: "#fff"
60
60
  },
61
61
  children: [
62
- /* @__PURE__ */ s(
62
+ /* @__PURE__ */ c(
63
63
  "div",
64
64
  {
65
65
  style: {
@@ -69,34 +69,34 @@ function C({ value: e, onChange: n, title: l }) {
69
69
  marginBottom: 6
70
70
  },
71
71
  children: [
72
- /* @__PURE__ */ s("span", { style: { fontSize: 12, fontWeight: 600, color: "#333" }, children: [
72
+ /* @__PURE__ */ c("span", { style: { fontSize: 12, fontWeight: 600, color: "#333" }, children: [
73
73
  "校验规则 ",
74
- r + 1
74
+ i + 1
75
75
  ] }),
76
- /* @__PURE__ */ i(h, { size: "small", danger: !0, onClick: () => b(t.id), children: "删除" })
76
+ /* @__PURE__ */ r(u, { size: "small", danger: !0, onClick: () => x(t.id), children: "删除" })
77
77
  ]
78
78
  }
79
79
  ),
80
- /* @__PURE__ */ s("div", { style: { marginBottom: 6 }, children: [
81
- /* @__PURE__ */ i("div", { style: { fontSize: 11, color: "#666", marginBottom: 2 }, children: "规则名称(key)" }),
82
- /* @__PURE__ */ i(
83
- R,
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
84
  {
85
85
  size: "small",
86
86
  placeholder: "如 match / len",
87
87
  value: t.key,
88
- onChange: (d) => u(t.id, { key: d.target.value })
88
+ onChange: (d) => p(t.id, { key: d.target.value })
89
89
  }
90
90
  )
91
91
  ] }),
92
- /* @__PURE__ */ s("div", { children: [
93
- /* @__PURE__ */ i("div", { style: { fontSize: 11, color: "#666", marginBottom: 2 }, children: "校验表达式(需返回 boolean)" }),
94
- /* @__PURE__ */ i(
95
- S,
92
+ /* @__PURE__ */ c("div", { children: [
93
+ /* @__PURE__ */ r("div", { style: { fontSize: 11, color: "#666", marginBottom: 2 }, children: "校验表达式(需返回 boolean)" }),
94
+ /* @__PURE__ */ r(
95
+ z,
96
96
  {
97
97
  value: t.expr,
98
- onChange: (d) => u(t.id, { expr: d }),
99
- fields: a,
98
+ onChange: (d) => p(t.id, { expr: d }),
99
+ fields: s,
100
100
  showSelf: !0,
101
101
  placeholder: "{{ $self.value.length >= 6 }}"
102
102
  }
@@ -106,13 +106,13 @@ function C({ value: e, onChange: n, title: l }) {
106
106
  },
107
107
  t.id
108
108
  )),
109
- /* @__PURE__ */ i(h, { size: "small", type: "dashed", block: !0, onClick: k, children: "+ 添加校验规则" }),
110
- /* @__PURE__ */ i("div", { style: { fontSize: 11, color: "#999", marginTop: 4 }, children: "提示:依赖字段(formData.xxx)变化时会自动联动重校验。" })
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
111
  ] });
112
112
  }
113
- const O = C;
113
+ const V = j;
114
114
  export {
115
- C as ValidateEditor,
116
- O as validateEditorWidget
115
+ j as ValidateEditor,
116
+ V as validateEditorWidget
117
117
  };
118
118
  //# sourceMappingURL=ValidateEditor.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ValidateEditor.js","sources":["../../../src/widgets/ValidateEditor.tsx"],"sourcesContent":["// ============================================================================\n// ValidateEditor — 可视化编辑 validate 校验规则\n// 每行一条规则:「规则名称 + 校验表达式」(表达式需返回 boolean)\n// 与 schema 的 ValidateSchema({ key: Expression })互相转换\n// ============================================================================\n\nimport type { WidgetProps } from '@xbeeant/form-engine-ui';\nimport { Button, Form, Input } from 'antd';\nimport { useEffect, useRef, useState } from 'react';\nimport { ExpressionBuilder } from './ExpressionBuilder';\nimport { genId } from './reactionsModel';\nimport { useFormDataFields } from './useFormDataFields';\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, title }: 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 <Form.Item layout={'vertical'} label={title} 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 </Form.Item>\n );\n}\n\nexport const validateEditorWidget = ValidateEditor;\n"],"names":["validateToRows","value","key","expr","genId","rowsToValidate","rows","result","row","ValidateEditor","onChange","title","fields","useFormDataFields","setRows","useState","prevValueRef","useRef","lastEmittedRef","useEffect","commit","next","emitted","updateRow","id","patch","r","removeRow","addRow","jsxs","Form","jsx","i","Button","Input","e","ExpressionBuilder","s","validateEditorWidget"],"mappings":"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"}
1
+ {"version":3,"file":"ValidateEditor.js","sources":["../../../src/widgets/ValidateEditor.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 './ExpressionBuilder';\nimport { genId } from './reactionsModel';\nimport { useFormDataFields } from './useFormDataFields';\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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"}