@tmagic/form 1.8.0-beta.28 → 1.8.0-beta.29

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.
@@ -120,14 +120,17 @@ var Text_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineCompo
120
120
  const ctrl = navigator.platform.match("Mac") ? $event.metaKey : $event.ctrlKey;
121
121
  const shift = $event.shiftKey;
122
122
  const alt = $event.altKey;
123
- if (arrowUp) if (ctrl) num += 100;
124
- else if (alt) num = (num * 1e4 + 1e3) / 1e4;
125
- else if (shift) num = num + 10;
126
- else num += 1;
127
- else if (arrowDown) if (ctrl) num -= 100;
128
- else if (alt) num = (num * 1e4 - 1e3) / 1e4;
129
- else if (shift) num -= 10;
130
- else num -= 1;
123
+ if (arrowUp) {
124
+ if (ctrl) num += 100;
125
+ else if (alt) num = (num * 1e4 + 1e3) / 1e4;
126
+ else if (shift) num = num + 10;
127
+ else num += 1;
128
+ } else if (arrowDown) {
129
+ if (ctrl) num -= 100;
130
+ else if (alt) num = (num * 1e4 - 1e3) / 1e4;
131
+ else if (shift) num -= 10;
132
+ else num -= 1;
133
+ }
131
134
  props.model[props.name] = `${num}${unit || ""}`;
132
135
  emit("change", props.model[props.name]);
133
136
  };
@@ -192,16 +192,20 @@ var resolveItemType = (mForm, config, props) => {
192
192
  return type?.replace(/([A-Z])/g, "-$1").toLowerCase() || (config?.items ? "" : "text");
193
193
  };
194
194
  var filterFunction = (mForm, config, props) => {
195
- if (typeof config === "function") return config(mForm, {
196
- values: readonly(mForm?.initValues || {}),
197
- model: readonly(props.model),
198
- parent: readonly(mForm?.parentValues || {}),
199
- formValue: readonly(mForm?.values || props.model),
200
- prop: props.prop,
201
- config: props.config,
202
- index: props.index,
203
- getFormValue: (prop) => getValueByKeyPath(prop, mForm?.values || props.model)
204
- });
195
+ if (typeof config === "function") {
196
+ const formValue = readonly(mForm?.values || props.model);
197
+ return config(mForm, {
198
+ values: readonly(mForm?.initValues || {}),
199
+ model: readonly(props.model),
200
+ parent: readonly(mForm?.parentValues || {}),
201
+ formValue,
202
+ formValues: formValue,
203
+ prop: props.prop,
204
+ config: props.config,
205
+ index: props.index,
206
+ getFormValue: (prop) => getValueByKeyPath(prop, mForm?.values || props.model)
207
+ });
208
+ }
205
209
  return config;
206
210
  };
207
211
  var display = function(mForm, config, props) {
@@ -8,6 +8,14 @@ dayjs.extend(customParseFormat);
8
8
  var extraTypeMatchRules = /* @__PURE__ */ new Map();
9
9
  var builtInTypeMatchRules = /* @__PURE__ */ new Map();
10
10
  var isPromise = (value) => typeof value === "object" && value !== null && typeof value.then === "function";
11
+ /**
12
+ * 同步校验无法等待 Promise。调用方会丢掉返回值,这里挂上空 handler,避免变成未捕获 rejection。
13
+ */
14
+ var ignorePromise = (value) => {
15
+ if (!isPromise(value)) return false;
16
+ value.then(() => {}, () => {});
17
+ return true;
18
+ };
11
19
  /** 注册或覆盖某个字段 type 的 typeMatch 校验规则。`builtIn` 登记不受 `clearTypeMatchRules` / `deleteTypeMatchRule` 影响。 */
12
20
  var registerTypeMatchRule = (type, validator, builtIn = false) => {
13
21
  (builtIn ? builtInTypeMatchRules : extraTypeMatchRules).set(toLine(type), validator);
@@ -25,16 +33,20 @@ var clearTypeMatchRules = () => {
25
33
  };
26
34
  /** 本地解析配置函数,避免与 form.ts 循环依赖 */
27
35
  var resolveConfig = (mForm, config, props) => {
28
- if (typeof config === "function") return config(mForm, {
29
- values: readonly(mForm?.initValues || {}),
30
- model: readonly(props.model),
31
- parent: readonly(mForm?.parentValues || {}),
32
- formValue: readonly(mForm?.values || props.model),
33
- prop: props.prop,
34
- config: props.config,
35
- index: props.index,
36
- getFormValue: (prop) => getValueByKeyPath(prop, mForm?.values || props.model)
37
- });
36
+ if (typeof config === "function") {
37
+ const formValue = readonly(mForm?.values || props.model);
38
+ return config(mForm, {
39
+ values: readonly(mForm?.initValues || {}),
40
+ model: readonly(props.model),
41
+ parent: readonly(mForm?.parentValues || {}),
42
+ formValue,
43
+ formValues: formValue,
44
+ prop: props.prop,
45
+ config: props.config,
46
+ index: props.index,
47
+ getFormValue: (prop) => getValueByKeyPath(prop, mForm?.values || props.model)
48
+ });
49
+ }
38
50
  return config;
39
51
  };
40
52
  var SKIP_TYPES = /* @__PURE__ */ new Set([
@@ -126,7 +138,7 @@ var resolveFieldDefaultValue = (mForm, props) => {
126
138
  const { defaultValue } = props.config || {};
127
139
  if (typeof defaultValue === "undefined" || defaultValue === "undefined") return void 0;
128
140
  const resolvedDefaultValue = resolveConfig(mForm, defaultValue, props);
129
- if (isPromise(resolvedDefaultValue)) return;
141
+ if (ignorePromise(resolvedDefaultValue)) return;
130
142
  return resolvedDefaultValue;
131
143
  };
132
144
  var isNumberValue = (value) => typeof value === "number" && !Number.isNaN(value);
@@ -203,9 +215,21 @@ var flattenSelectOptions = (options) => {
203
215
  });
204
216
  return values;
205
217
  };
206
- var resolveOptions = (props) => {
207
- const { options } = props.config || {};
208
- return Array.isArray(options) ? options : [];
218
+ /**
219
+ * 解析字段 options:静态数组原样返回;函数型与 `display` / `type` 一样当场求值。
220
+ *
221
+ * 函数返回 Promise、非数组或抛错时当作「还没有可选项」,交由调用方按空 options 跳过枚举。
222
+ * `remote` / `allowCreate` 仍由 `validateSelectValue` 单独放行,不在这里区分。
223
+ */
224
+ var resolveOptions = (mForm, props) => {
225
+ let resolved;
226
+ try {
227
+ resolved = resolveConfig(mForm, props.config?.options, props);
228
+ } catch {
229
+ return [];
230
+ }
231
+ if (ignorePromise(resolved) || !Array.isArray(resolved)) return [];
232
+ return resolved;
209
233
  };
210
234
  var includesOptionValue = (optionValues, value) => optionValues.some((item) => Object.is(item, value));
211
235
  var collectCascaderLeafValues = (options, result = []) => {
@@ -267,19 +291,18 @@ var validateSelectValue = (value, config, optionValues, message) => {
267
291
  if (typeof value === "object") return defaultMessage(message, `${value} 类型不合法`, optionExampleSuggestion(optionValues, "\"文本内容\" 或 123", false));
268
292
  return;
269
293
  }
270
- const isStaticOptions = Array.isArray(config.options);
271
294
  if (config.multiple) {
272
295
  if (!Array.isArray(value)) return defaultMessage(message, `${value} 类型应为数组`, optionExampleSuggestion(optionValues, "[\"选项1\", \"选项2\"]", true));
273
- if (isStaticOptions && value.some((item) => !includesOptionValue(optionValues, item))) return defaultMessage(message, `${value} 不在可选项中`, optionSuggestion(optionValues));
296
+ if (value.some((item) => !includesOptionValue(optionValues, item))) return defaultMessage(message, `${value} 不在可选项中`, optionSuggestion(optionValues));
274
297
  return;
275
298
  }
276
- if (isStaticOptions && !includesOptionValue(optionValues, value)) return defaultMessage(message, `${value} 不在可选项中`, optionSuggestion(optionValues));
299
+ if (!includesOptionValue(optionValues, value)) return defaultMessage(message, `${value} 不在可选项中`, optionSuggestion(optionValues));
277
300
  };
278
301
  var validateCascaderValue = (value, config, props, mForm, message) => {
279
- const options = resolveOptions(props);
302
+ const options = resolveOptions(mForm, props);
280
303
  if (!options.length) return;
281
304
  const valueSeparator = resolveConfig(mForm, config.valueSeparator, props);
282
- if (isPromise(valueSeparator)) return;
305
+ if (ignorePromise(valueSeparator)) return;
283
306
  const emitPath = config.emitPath !== false;
284
307
  const multiple = Boolean(config.multiple);
285
308
  const cascaderExample = (fallbackExample) => cascaderExampleSuggestion(options, config, valueSeparator, fallbackExample);
@@ -336,15 +359,15 @@ var validateBuiltinTypeMatch = (value, fieldType, mForm, props, message) => {
336
359
  if (!Object.is(value, activeValue) && !Object.is(value, inactiveValue)) return defaultMessage(message, `${value} 不在合法开关值中`, toggleSuggestion(activeValue, inactiveValue));
337
360
  return;
338
361
  }
339
- if (fieldType === "select") return validateSelectValue(value, config, flattenSelectOptions(resolveOptions(props)), message);
362
+ if (fieldType === "select") return validateSelectValue(value, config, flattenSelectOptions(resolveOptions(mForm, props)), message);
340
363
  if (fieldType === "radio-group") {
341
- const optionValues = flattenSelectOptions(resolveOptions(props));
364
+ const optionValues = flattenSelectOptions(resolveOptions(mForm, props));
342
365
  if (optionValues.length === 0) return;
343
366
  if (!includesOptionValue(optionValues, value)) return defaultMessage(message, `${value} 不在可选项中`, optionSuggestion(optionValues));
344
367
  return;
345
368
  }
346
369
  if (fieldType === "checkbox-group") {
347
- const optionValues = flattenSelectOptions(resolveOptions(props));
370
+ const optionValues = flattenSelectOptions(resolveOptions(mForm, props));
348
371
  if (optionValues.length === 0) return;
349
372
  if (!Array.isArray(value)) return defaultMessage(message, `${value} 类型应为数组`, optionExampleSuggestion(optionValues, "[\"选项1\", \"选项2\"]", true));
350
373
  if (value.some((item) => !includesOptionValue(optionValues, item))) return defaultMessage(message, `${value} 不在可选项中`, optionSuggestion(optionValues));
@@ -371,8 +394,14 @@ var validateTypeMatch = (value, mForm, props, message) => {
371
394
  if (isEmptyValue(value) || isEmptyArray(value)) return;
372
395
  if (!props.config?.name) return;
373
396
  const rawFieldType = "type" in (props.config || {}) ? props.config.type : "";
374
- if (typeof rawFieldType !== "string" || !rawFieldType) return;
375
- const fieldType = toLine(rawFieldType);
397
+ let resolvedType;
398
+ try {
399
+ resolvedType = resolveConfig(mForm, rawFieldType, props);
400
+ } catch {
401
+ return;
402
+ }
403
+ if (ignorePromise(resolvedType) || typeof resolvedType !== "string" || !resolvedType) return;
404
+ const fieldType = toLine(resolvedType);
376
405
  const customValidator = getTypeMatchRule(fieldType);
377
406
  if (customValidator) return customValidator(value, {
378
407
  fieldType,
@@ -91,8 +91,10 @@
91
91
  var unmasked = true;
92
92
  } catch (e) {}
93
93
  var result = nativeObjectToString$1.call(value);
94
- if (unmasked) if (isOwn) value[symToStringTag$1] = tag;
95
- else delete value[symToStringTag$1];
94
+ if (unmasked) {
95
+ if (isOwn) value[symToStringTag$1] = tag;
96
+ else delete value[symToStringTag$1];
97
+ }
96
98
  return result;
97
99
  }
98
100
  //#endregion
@@ -2049,6 +2051,14 @@
2049
2051
  var extraTypeMatchRules = /* @__PURE__ */ new Map();
2050
2052
  var builtInTypeMatchRules = /* @__PURE__ */ new Map();
2051
2053
  var isPromise = (value) => typeof value === "object" && value !== null && typeof value.then === "function";
2054
+ /**
2055
+ * 同步校验无法等待 Promise。调用方会丢掉返回值,这里挂上空 handler,避免变成未捕获 rejection。
2056
+ */
2057
+ var ignorePromise = (value) => {
2058
+ if (!isPromise(value)) return false;
2059
+ value.then(() => {}, () => {});
2060
+ return true;
2061
+ };
2052
2062
  /** 注册或覆盖某个字段 type 的 typeMatch 校验规则。`builtIn` 登记不受 `clearTypeMatchRules` / `deleteTypeMatchRule` 影响。 */
2053
2063
  var registerTypeMatchRule = (type, validator, builtIn = false) => {
2054
2064
  (builtIn ? builtInTypeMatchRules : extraTypeMatchRules).set((0, _tmagic_utils.toLine)(type), validator);
@@ -2066,16 +2076,20 @@
2066
2076
  };
2067
2077
  /** 本地解析配置函数,避免与 form.ts 循环依赖 */
2068
2078
  var resolveConfig = (mForm, config, props) => {
2069
- if (typeof config === "function") return config(mForm, {
2070
- values: (0, vue.readonly)(mForm?.initValues || {}),
2071
- model: (0, vue.readonly)(props.model),
2072
- parent: (0, vue.readonly)(mForm?.parentValues || {}),
2073
- formValue: (0, vue.readonly)(mForm?.values || props.model),
2074
- prop: props.prop,
2075
- config: props.config,
2076
- index: props.index,
2077
- getFormValue: (prop) => (0, _tmagic_utils.getValueByKeyPath)(prop, mForm?.values || props.model)
2078
- });
2079
+ if (typeof config === "function") {
2080
+ const formValue = (0, vue.readonly)(mForm?.values || props.model);
2081
+ return config(mForm, {
2082
+ values: (0, vue.readonly)(mForm?.initValues || {}),
2083
+ model: (0, vue.readonly)(props.model),
2084
+ parent: (0, vue.readonly)(mForm?.parentValues || {}),
2085
+ formValue,
2086
+ formValues: formValue,
2087
+ prop: props.prop,
2088
+ config: props.config,
2089
+ index: props.index,
2090
+ getFormValue: (prop) => (0, _tmagic_utils.getValueByKeyPath)(prop, mForm?.values || props.model)
2091
+ });
2092
+ }
2079
2093
  return config;
2080
2094
  };
2081
2095
  var SKIP_TYPES = /* @__PURE__ */ new Set([
@@ -2167,7 +2181,7 @@
2167
2181
  const { defaultValue } = props.config || {};
2168
2182
  if (typeof defaultValue === "undefined" || defaultValue === "undefined") return void 0;
2169
2183
  const resolvedDefaultValue = resolveConfig(mForm, defaultValue, props);
2170
- if (isPromise(resolvedDefaultValue)) return;
2184
+ if (ignorePromise(resolvedDefaultValue)) return;
2171
2185
  return resolvedDefaultValue;
2172
2186
  };
2173
2187
  var isNumberValue = (value) => typeof value === "number" && !Number.isNaN(value);
@@ -2244,9 +2258,21 @@
2244
2258
  });
2245
2259
  return values;
2246
2260
  };
2247
- var resolveOptions = (props) => {
2248
- const { options } = props.config || {};
2249
- return Array.isArray(options) ? options : [];
2261
+ /**
2262
+ * 解析字段 options:静态数组原样返回;函数型与 `display` / `type` 一样当场求值。
2263
+ *
2264
+ * 函数返回 Promise、非数组或抛错时当作「还没有可选项」,交由调用方按空 options 跳过枚举。
2265
+ * `remote` / `allowCreate` 仍由 `validateSelectValue` 单独放行,不在这里区分。
2266
+ */
2267
+ var resolveOptions = (mForm, props) => {
2268
+ let resolved;
2269
+ try {
2270
+ resolved = resolveConfig(mForm, props.config?.options, props);
2271
+ } catch {
2272
+ return [];
2273
+ }
2274
+ if (ignorePromise(resolved) || !Array.isArray(resolved)) return [];
2275
+ return resolved;
2250
2276
  };
2251
2277
  var includesOptionValue = (optionValues, value) => optionValues.some((item) => Object.is(item, value));
2252
2278
  var collectCascaderLeafValues = (options, result = []) => {
@@ -2308,19 +2334,18 @@
2308
2334
  if (typeof value === "object") return defaultMessage(message, `${value} 类型不合法`, optionExampleSuggestion(optionValues, "\"文本内容\" 或 123", false));
2309
2335
  return;
2310
2336
  }
2311
- const isStaticOptions = Array.isArray(config.options);
2312
2337
  if (config.multiple) {
2313
2338
  if (!Array.isArray(value)) return defaultMessage(message, `${value} 类型应为数组`, optionExampleSuggestion(optionValues, "[\"选项1\", \"选项2\"]", true));
2314
- if (isStaticOptions && value.some((item) => !includesOptionValue(optionValues, item))) return defaultMessage(message, `${value} 不在可选项中`, optionSuggestion(optionValues));
2339
+ if (value.some((item) => !includesOptionValue(optionValues, item))) return defaultMessage(message, `${value} 不在可选项中`, optionSuggestion(optionValues));
2315
2340
  return;
2316
2341
  }
2317
- if (isStaticOptions && !includesOptionValue(optionValues, value)) return defaultMessage(message, `${value} 不在可选项中`, optionSuggestion(optionValues));
2342
+ if (!includesOptionValue(optionValues, value)) return defaultMessage(message, `${value} 不在可选项中`, optionSuggestion(optionValues));
2318
2343
  };
2319
2344
  var validateCascaderValue = (value, config, props, mForm, message) => {
2320
- const options = resolveOptions(props);
2345
+ const options = resolveOptions(mForm, props);
2321
2346
  if (!options.length) return;
2322
2347
  const valueSeparator = resolveConfig(mForm, config.valueSeparator, props);
2323
- if (isPromise(valueSeparator)) return;
2348
+ if (ignorePromise(valueSeparator)) return;
2324
2349
  const emitPath = config.emitPath !== false;
2325
2350
  const multiple = Boolean(config.multiple);
2326
2351
  const cascaderExample = (fallbackExample) => cascaderExampleSuggestion(options, config, valueSeparator, fallbackExample);
@@ -2377,15 +2402,15 @@
2377
2402
  if (!Object.is(value, activeValue) && !Object.is(value, inactiveValue)) return defaultMessage(message, `${value} 不在合法开关值中`, toggleSuggestion(activeValue, inactiveValue));
2378
2403
  return;
2379
2404
  }
2380
- if (fieldType === "select") return validateSelectValue(value, config, flattenSelectOptions(resolveOptions(props)), message);
2405
+ if (fieldType === "select") return validateSelectValue(value, config, flattenSelectOptions(resolveOptions(mForm, props)), message);
2381
2406
  if (fieldType === "radio-group") {
2382
- const optionValues = flattenSelectOptions(resolveOptions(props));
2407
+ const optionValues = flattenSelectOptions(resolveOptions(mForm, props));
2383
2408
  if (optionValues.length === 0) return;
2384
2409
  if (!includesOptionValue(optionValues, value)) return defaultMessage(message, `${value} 不在可选项中`, optionSuggestion(optionValues));
2385
2410
  return;
2386
2411
  }
2387
2412
  if (fieldType === "checkbox-group") {
2388
- const optionValues = flattenSelectOptions(resolveOptions(props));
2413
+ const optionValues = flattenSelectOptions(resolveOptions(mForm, props));
2389
2414
  if (optionValues.length === 0) return;
2390
2415
  if (!Array.isArray(value)) return defaultMessage(message, `${value} 类型应为数组`, optionExampleSuggestion(optionValues, "[\"选项1\", \"选项2\"]", true));
2391
2416
  if (value.some((item) => !includesOptionValue(optionValues, item))) return defaultMessage(message, `${value} 不在可选项中`, optionSuggestion(optionValues));
@@ -2412,8 +2437,14 @@
2412
2437
  if (isEmptyValue(value) || isEmptyArray(value)) return;
2413
2438
  if (!props.config?.name) return;
2414
2439
  const rawFieldType = "type" in (props.config || {}) ? props.config.type : "";
2415
- if (typeof rawFieldType !== "string" || !rawFieldType) return;
2416
- const fieldType = (0, _tmagic_utils.toLine)(rawFieldType);
2440
+ let resolvedType;
2441
+ try {
2442
+ resolvedType = resolveConfig(mForm, rawFieldType, props);
2443
+ } catch {
2444
+ return;
2445
+ }
2446
+ if (ignorePromise(resolvedType) || typeof resolvedType !== "string" || !resolvedType) return;
2447
+ const fieldType = (0, _tmagic_utils.toLine)(resolvedType);
2417
2448
  const customValidator = getTypeMatchRule(fieldType);
2418
2449
  if (customValidator) return customValidator(value, {
2419
2450
  fieldType,
@@ -2820,16 +2851,20 @@
2820
2851
  return type?.replace(/([A-Z])/g, "-$1").toLowerCase() || (config?.items ? "" : "text");
2821
2852
  };
2822
2853
  var filterFunction = (mForm, config, props) => {
2823
- if (typeof config === "function") return config(mForm, {
2824
- values: (0, vue.readonly)(mForm?.initValues || {}),
2825
- model: (0, vue.readonly)(props.model),
2826
- parent: (0, vue.readonly)(mForm?.parentValues || {}),
2827
- formValue: (0, vue.readonly)(mForm?.values || props.model),
2828
- prop: props.prop,
2829
- config: props.config,
2830
- index: props.index,
2831
- getFormValue: (prop) => (0, _tmagic_utils.getValueByKeyPath)(prop, mForm?.values || props.model)
2832
- });
2854
+ if (typeof config === "function") {
2855
+ const formValue = (0, vue.readonly)(mForm?.values || props.model);
2856
+ return config(mForm, {
2857
+ values: (0, vue.readonly)(mForm?.initValues || {}),
2858
+ model: (0, vue.readonly)(props.model),
2859
+ parent: (0, vue.readonly)(mForm?.parentValues || {}),
2860
+ formValue,
2861
+ formValues: formValue,
2862
+ prop: props.prop,
2863
+ config: props.config,
2864
+ index: props.index,
2865
+ getFormValue: (prop) => (0, _tmagic_utils.getValueByKeyPath)(prop, mForm?.values || props.model)
2866
+ });
2867
+ }
2833
2868
  return config;
2834
2869
  };
2835
2870
  var display = function(mForm, config, props) {
@@ -97,8 +97,10 @@
97
97
  var unmasked = true;
98
98
  } catch (e) {}
99
99
  var result = nativeObjectToString$1.call(value);
100
- if (unmasked) if (isOwn) value[symToStringTag$1] = tag;
101
- else delete value[symToStringTag$1];
100
+ if (unmasked) {
101
+ if (isOwn) value[symToStringTag$1] = tag;
102
+ else delete value[symToStringTag$1];
103
+ }
102
104
  return result;
103
105
  }
104
106
  //#endregion
@@ -2903,6 +2905,14 @@
2903
2905
  var extraTypeMatchRules = /* @__PURE__ */ new Map();
2904
2906
  var builtInTypeMatchRules = /* @__PURE__ */ new Map();
2905
2907
  var isPromise = (value) => typeof value === "object" && value !== null && typeof value.then === "function";
2908
+ /**
2909
+ * 同步校验无法等待 Promise。调用方会丢掉返回值,这里挂上空 handler,避免变成未捕获 rejection。
2910
+ */
2911
+ var ignorePromise = (value) => {
2912
+ if (!isPromise(value)) return false;
2913
+ value.then(() => {}, () => {});
2914
+ return true;
2915
+ };
2906
2916
  /** 注册或覆盖某个字段 type 的 typeMatch 校验规则。`builtIn` 登记不受 `clearTypeMatchRules` / `deleteTypeMatchRule` 影响。 */
2907
2917
  var registerTypeMatchRule = (type, validator, builtIn = false) => {
2908
2918
  (builtIn ? builtInTypeMatchRules : extraTypeMatchRules).set((0, _tmagic_utils.toLine)(type), validator);
@@ -2920,16 +2930,20 @@
2920
2930
  };
2921
2931
  /** 本地解析配置函数,避免与 form.ts 循环依赖 */
2922
2932
  var resolveConfig = (mForm, config, props) => {
2923
- if (typeof config === "function") return config(mForm, {
2924
- values: (0, vue.readonly)(mForm?.initValues || {}),
2925
- model: (0, vue.readonly)(props.model),
2926
- parent: (0, vue.readonly)(mForm?.parentValues || {}),
2927
- formValue: (0, vue.readonly)(mForm?.values || props.model),
2928
- prop: props.prop,
2929
- config: props.config,
2930
- index: props.index,
2931
- getFormValue: (prop) => (0, _tmagic_utils.getValueByKeyPath)(prop, mForm?.values || props.model)
2932
- });
2933
+ if (typeof config === "function") {
2934
+ const formValue = (0, vue.readonly)(mForm?.values || props.model);
2935
+ return config(mForm, {
2936
+ values: (0, vue.readonly)(mForm?.initValues || {}),
2937
+ model: (0, vue.readonly)(props.model),
2938
+ parent: (0, vue.readonly)(mForm?.parentValues || {}),
2939
+ formValue,
2940
+ formValues: formValue,
2941
+ prop: props.prop,
2942
+ config: props.config,
2943
+ index: props.index,
2944
+ getFormValue: (prop) => (0, _tmagic_utils.getValueByKeyPath)(prop, mForm?.values || props.model)
2945
+ });
2946
+ }
2933
2947
  return config;
2934
2948
  };
2935
2949
  var SKIP_TYPES = /* @__PURE__ */ new Set([
@@ -3021,7 +3035,7 @@
3021
3035
  const { defaultValue } = props.config || {};
3022
3036
  if (typeof defaultValue === "undefined" || defaultValue === "undefined") return void 0;
3023
3037
  const resolvedDefaultValue = resolveConfig(mForm, defaultValue, props);
3024
- if (isPromise(resolvedDefaultValue)) return;
3038
+ if (ignorePromise(resolvedDefaultValue)) return;
3025
3039
  return resolvedDefaultValue;
3026
3040
  };
3027
3041
  var isNumberValue = (value) => typeof value === "number" && !Number.isNaN(value);
@@ -3098,9 +3112,21 @@
3098
3112
  });
3099
3113
  return values;
3100
3114
  };
3101
- var resolveOptions = (props) => {
3102
- const { options } = props.config || {};
3103
- return Array.isArray(options) ? options : [];
3115
+ /**
3116
+ * 解析字段 options:静态数组原样返回;函数型与 `display` / `type` 一样当场求值。
3117
+ *
3118
+ * 函数返回 Promise、非数组或抛错时当作「还没有可选项」,交由调用方按空 options 跳过枚举。
3119
+ * `remote` / `allowCreate` 仍由 `validateSelectValue` 单独放行,不在这里区分。
3120
+ */
3121
+ var resolveOptions = (mForm, props) => {
3122
+ let resolved;
3123
+ try {
3124
+ resolved = resolveConfig(mForm, props.config?.options, props);
3125
+ } catch {
3126
+ return [];
3127
+ }
3128
+ if (ignorePromise(resolved) || !Array.isArray(resolved)) return [];
3129
+ return resolved;
3104
3130
  };
3105
3131
  var includesOptionValue = (optionValues, value) => optionValues.some((item) => Object.is(item, value));
3106
3132
  var collectCascaderLeafValues = (options, result = []) => {
@@ -3162,19 +3188,18 @@
3162
3188
  if (typeof value === "object") return defaultMessage(message, `${value} 类型不合法`, optionExampleSuggestion(optionValues, "\"文本内容\" 或 123", false));
3163
3189
  return;
3164
3190
  }
3165
- const isStaticOptions = Array.isArray(config.options);
3166
3191
  if (config.multiple) {
3167
3192
  if (!Array.isArray(value)) return defaultMessage(message, `${value} 类型应为数组`, optionExampleSuggestion(optionValues, "[\"选项1\", \"选项2\"]", true));
3168
- if (isStaticOptions && value.some((item) => !includesOptionValue(optionValues, item))) return defaultMessage(message, `${value} 不在可选项中`, optionSuggestion(optionValues));
3193
+ if (value.some((item) => !includesOptionValue(optionValues, item))) return defaultMessage(message, `${value} 不在可选项中`, optionSuggestion(optionValues));
3169
3194
  return;
3170
3195
  }
3171
- if (isStaticOptions && !includesOptionValue(optionValues, value)) return defaultMessage(message, `${value} 不在可选项中`, optionSuggestion(optionValues));
3196
+ if (!includesOptionValue(optionValues, value)) return defaultMessage(message, `${value} 不在可选项中`, optionSuggestion(optionValues));
3172
3197
  };
3173
3198
  var validateCascaderValue = (value, config, props, mForm, message) => {
3174
- const options = resolveOptions(props);
3199
+ const options = resolveOptions(mForm, props);
3175
3200
  if (!options.length) return;
3176
3201
  const valueSeparator = resolveConfig(mForm, config.valueSeparator, props);
3177
- if (isPromise(valueSeparator)) return;
3202
+ if (ignorePromise(valueSeparator)) return;
3178
3203
  const emitPath = config.emitPath !== false;
3179
3204
  const multiple = Boolean(config.multiple);
3180
3205
  const cascaderExample = (fallbackExample) => cascaderExampleSuggestion(options, config, valueSeparator, fallbackExample);
@@ -3231,15 +3256,15 @@
3231
3256
  if (!Object.is(value, activeValue) && !Object.is(value, inactiveValue)) return defaultMessage(message, `${value} 不在合法开关值中`, toggleSuggestion(activeValue, inactiveValue));
3232
3257
  return;
3233
3258
  }
3234
- if (fieldType === "select") return validateSelectValue(value, config, flattenSelectOptions(resolveOptions(props)), message);
3259
+ if (fieldType === "select") return validateSelectValue(value, config, flattenSelectOptions(resolveOptions(mForm, props)), message);
3235
3260
  if (fieldType === "radio-group") {
3236
- const optionValues = flattenSelectOptions(resolveOptions(props));
3261
+ const optionValues = flattenSelectOptions(resolveOptions(mForm, props));
3237
3262
  if (optionValues.length === 0) return;
3238
3263
  if (!includesOptionValue(optionValues, value)) return defaultMessage(message, `${value} 不在可选项中`, optionSuggestion(optionValues));
3239
3264
  return;
3240
3265
  }
3241
3266
  if (fieldType === "checkbox-group") {
3242
- const optionValues = flattenSelectOptions(resolveOptions(props));
3267
+ const optionValues = flattenSelectOptions(resolveOptions(mForm, props));
3243
3268
  if (optionValues.length === 0) return;
3244
3269
  if (!Array.isArray(value)) return defaultMessage(message, `${value} 类型应为数组`, optionExampleSuggestion(optionValues, "[\"选项1\", \"选项2\"]", true));
3245
3270
  if (value.some((item) => !includesOptionValue(optionValues, item))) return defaultMessage(message, `${value} 不在可选项中`, optionSuggestion(optionValues));
@@ -3266,8 +3291,14 @@
3266
3291
  if (isEmptyValue(value) || isEmptyArray(value)) return;
3267
3292
  if (!props.config?.name) return;
3268
3293
  const rawFieldType = "type" in (props.config || {}) ? props.config.type : "";
3269
- if (typeof rawFieldType !== "string" || !rawFieldType) return;
3270
- const fieldType = (0, _tmagic_utils.toLine)(rawFieldType);
3294
+ let resolvedType;
3295
+ try {
3296
+ resolvedType = resolveConfig(mForm, rawFieldType, props);
3297
+ } catch {
3298
+ return;
3299
+ }
3300
+ if (ignorePromise(resolvedType) || typeof resolvedType !== "string" || !resolvedType) return;
3301
+ const fieldType = (0, _tmagic_utils.toLine)(resolvedType);
3271
3302
  const customValidator = getTypeMatchRule(fieldType);
3272
3303
  if (customValidator) return customValidator(value, {
3273
3304
  fieldType,
@@ -3674,16 +3705,20 @@
3674
3705
  return type?.replace(/([A-Z])/g, "-$1").toLowerCase() || (config?.items ? "" : "text");
3675
3706
  };
3676
3707
  var filterFunction = (mForm, config, props) => {
3677
- if (typeof config === "function") return config(mForm, {
3678
- values: (0, vue.readonly)(mForm?.initValues || {}),
3679
- model: (0, vue.readonly)(props.model),
3680
- parent: (0, vue.readonly)(mForm?.parentValues || {}),
3681
- formValue: (0, vue.readonly)(mForm?.values || props.model),
3682
- prop: props.prop,
3683
- config: props.config,
3684
- index: props.index,
3685
- getFormValue: (prop) => (0, _tmagic_utils.getValueByKeyPath)(prop, mForm?.values || props.model)
3686
- });
3708
+ if (typeof config === "function") {
3709
+ const formValue = (0, vue.readonly)(mForm?.values || props.model);
3710
+ return config(mForm, {
3711
+ values: (0, vue.readonly)(mForm?.initValues || {}),
3712
+ model: (0, vue.readonly)(props.model),
3713
+ parent: (0, vue.readonly)(mForm?.parentValues || {}),
3714
+ formValue,
3715
+ formValues: formValue,
3716
+ prop: props.prop,
3717
+ config: props.config,
3718
+ index: props.index,
3719
+ getFormValue: (prop) => (0, _tmagic_utils.getValueByKeyPath)(prop, mForm?.values || props.model)
3720
+ });
3721
+ }
3687
3722
  return config;
3688
3723
  };
3689
3724
  var display = function(mForm, config, props) {
@@ -8621,14 +8656,17 @@
8621
8656
  const ctrl = navigator.platform.match("Mac") ? $event.metaKey : $event.ctrlKey;
8622
8657
  const shift = $event.shiftKey;
8623
8658
  const alt = $event.altKey;
8624
- if (arrowUp) if (ctrl) num += 100;
8625
- else if (alt) num = (num * 1e4 + 1e3) / 1e4;
8626
- else if (shift) num = num + 10;
8627
- else num += 1;
8628
- else if (arrowDown) if (ctrl) num -= 100;
8629
- else if (alt) num = (num * 1e4 - 1e3) / 1e4;
8630
- else if (shift) num -= 10;
8631
- else num -= 1;
8659
+ if (arrowUp) {
8660
+ if (ctrl) num += 100;
8661
+ else if (alt) num = (num * 1e4 + 1e3) / 1e4;
8662
+ else if (shift) num = num + 10;
8663
+ else num += 1;
8664
+ } else if (arrowDown) {
8665
+ if (ctrl) num -= 100;
8666
+ else if (alt) num = (num * 1e4 - 1e3) / 1e4;
8667
+ else if (shift) num -= 10;
8668
+ else num -= 1;
8669
+ }
8632
8670
  props.model[props.name] = `${num}${unit || ""}`;
8633
8671
  emit("change", props.model[props.name]);
8634
8672
  };
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.8.0-beta.28",
2
+ "version": "1.8.0-beta.29",
3
3
  "name": "@tmagic/form",
4
4
  "type": "module",
5
5
  "sideEffects": [
@@ -46,21 +46,21 @@
46
46
  "@element-plus/icons-vue": "^2.3.2",
47
47
  "@popperjs/core": "^2.11.8",
48
48
  "async-validator": "^4.2.5",
49
- "dayjs": "^1.11.21",
49
+ "dayjs": "^1.11.23",
50
50
  "lodash-es": "^4.18.1",
51
51
  "sortablejs": "^1.15.7"
52
52
  },
53
53
  "devDependencies": {
54
54
  "@types/lodash-es": "^4.17.12",
55
55
  "@types/sortablejs": "^1.15.9",
56
- "@vue/test-utils": "^2.4.11"
56
+ "@vue/test-utils": "^2.5.1"
57
57
  },
58
58
  "peerDependencies": {
59
59
  "typescript": "^6.0.3",
60
- "vue": "^3.5.41",
61
- "@tmagic/design": "1.8.0-beta.28",
62
- "@tmagic/utils": "1.8.0-beta.28",
63
- "@tmagic/form-schema": "1.8.0-beta.28"
60
+ "vue": "^3.5.43",
61
+ "@tmagic/design": "1.8.0-beta.29",
62
+ "@tmagic/utils": "1.8.0-beta.29",
63
+ "@tmagic/form-schema": "1.8.0-beta.29"
64
64
  },
65
65
  "peerDependenciesMeta": {
66
66
  "typescript": {
package/src/utils/form.ts CHANGED
@@ -368,11 +368,14 @@ export const filterFunction = <T = any>(
368
368
  props: any,
369
369
  ) => {
370
370
  if (typeof config === 'function') {
371
+ const formValue = readonly(mForm?.values || props.model);
371
372
  return (config as FilterFunction<T>)(mForm, {
372
373
  values: readonly(mForm?.initValues || {}),
373
374
  model: readonly(props.model),
374
375
  parent: readonly(mForm?.parentValues || {}),
375
- formValue: readonly(mForm?.values || props.model),
376
+ formValue,
377
+ // Select.vue / SelectOptionFunction 使用 formValues 别名
378
+ formValues: formValue,
376
379
  prop: props.prop,
377
380
  config: props.config,
378
381
  index: props.index,