@tmagic/form 1.8.0-beta.22 → 1.8.0-beta.24

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.
@@ -1,7 +1,8 @@
1
- import { FORM_DIFF_CONFIG_KEY, FORM_TYPE_MATCH_VALID_KEY } from "../schema.js";
1
+ import { FORM_DIFF_CONFIG_KEY, FORM_SILENT_MODE_KEY, FORM_TYPE_MATCH_VALID_KEY } from "../schema.js";
2
2
  import { createObjectProp, display, filterFunction, getRules } from "../utils/form.js";
3
3
  import Hidden_default from "../fields/Hidden.js";
4
4
  import { getField } from "../utils/config.js";
5
+ import { getSilentLeafFieldTypes } from "../utils/silentLeafFieldTypes.js";
5
6
  import FormLabel_default from "./FormLabel.js";
6
7
  import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createSlots, createTextVNode, createVNode, defineComponent, inject, mergeProps, normalizeClass, normalizeStyle, openBlock, provide, readonly, ref, renderList, renderSlot, resolveComponent, resolveDynamicComponent, toDisplayString, toRaw, unref, watch, watchEffect, withCtx } from "vue";
7
8
  import { isEqual } from "lodash-es";
@@ -117,6 +118,8 @@ var Container_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
117
118
  return new Set(DEFAULT_SELF_DIFF_FIELD_TYPES);
118
119
  });
119
120
  const isSelfDiffField = computed(() => effectiveSelfDiffFieldTypes.value.has(type.value));
121
+ const silentMode = inject(FORM_SILENT_MODE_KEY, false);
122
+ const shouldRenderLeafField = computed(() => !silentMode || !getSilentLeafFieldTypes().has(type.value));
120
123
  const disabled = computed(() => props.disabled || filterFunction(mForm, props.config.disabled, props));
121
124
  const text = computed(() => filterFunction(mForm, props.config.text, props));
122
125
  const tooltip = computed(() => {
@@ -292,7 +295,7 @@ var Container_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
292
295
  "label-width",
293
296
  "style"
294
297
  ])) : type.value && display$1.value && !showDiff.value ? (openBlock(), createElementBlock(Fragment, { key: 2 }, [createVNode(unref(TMagicFormItem), mergeProps(formItemProps.value, { class: { "tmagic-form-hidden": `${itemLabelWidth.value}` === "0" || !text.value } }), {
295
- label: withCtx(() => [renderSlot(_ctx.$slots, "label", {
298
+ label: withCtx(() => [shouldRenderLeafField.value ? renderSlot(_ctx.$slots, "label", {
296
299
  config: __props.config,
297
300
  type: type.value,
298
301
  text: text.value,
@@ -310,8 +313,8 @@ var Container_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
310
313
  "use-label",
311
314
  "label-title",
312
315
  "text"
313
- ]), __props.config.titleExtra && __props.config.labelPosition === "top" ? (openBlock(), createElementBlock("span", _hoisted_2, toDisplayString(__props.config.titleExtra), 1)) : createCommentVNode("v-if", true)])]),
314
- default: withCtx(() => [tooltip.value.text ? (openBlock(), createBlock(unref(TMagicTooltip), {
316
+ ]), __props.config.titleExtra && __props.config.labelPosition === "top" ? (openBlock(), createElementBlock("span", _hoisted_2, toDisplayString(__props.config.titleExtra), 1)) : createCommentVNode("v-if", true)], void 0, 0) : createCommentVNode("v-if", true)]),
317
+ default: withCtx(() => [shouldRenderLeafField.value ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [tooltip.value.text ? (openBlock(), createBlock(unref(TMagicTooltip), {
315
318
  key: 0,
316
319
  placement: tooltip.value.placement
317
320
  }, {
@@ -338,9 +341,9 @@ var Container_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
338
341
  "model",
339
342
  "last-values",
340
343
  "is-compare"
341
- ]))]),
344
+ ]))], 64)) : createCommentVNode("v-if", true)]),
342
345
  _: 3
343
- }, 16, ["class"]), __props.config.tip && type.value === "checkbox" && !__props.config.useLabel ? (openBlock(), createBlock(unref(TMagicTooltip), {
346
+ }, 16, ["class"]), shouldRenderLeafField.value && __props.config.tip && type.value === "checkbox" && !__props.config.useLabel ? (openBlock(), createBlock(unref(TMagicTooltip), {
344
347
  key: 0,
345
348
  placement: "top"
346
349
  }, {
@@ -360,7 +363,7 @@ var Container_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
360
363
  "tmagic-form-hidden": `${itemLabelWidth.value}` === "0" || !text.value,
361
364
  "self-diff": true
362
365
  } }), {
363
- label: withCtx(() => [renderSlot(_ctx.$slots, "label", {
366
+ label: withCtx(() => [shouldRenderLeafField.value ? renderSlot(_ctx.$slots, "label", {
364
367
  config: __props.config,
365
368
  type: type.value,
366
369
  text: text.value,
@@ -378,8 +381,8 @@ var Container_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
378
381
  "use-label",
379
382
  "label-title",
380
383
  "text"
381
- ])])]),
382
- default: withCtx(() => [tooltip.value.text ? (openBlock(), createBlock(unref(TMagicTooltip), {
384
+ ])], void 0, 0) : createCommentVNode("v-if", true)]),
385
+ default: withCtx(() => [shouldRenderLeafField.value ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [tooltip.value.text ? (openBlock(), createBlock(unref(TMagicTooltip), {
383
386
  key: 0,
384
387
  placement: tooltip.value.placement
385
388
  }, {
@@ -404,7 +407,7 @@ var Container_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
404
407
  "model",
405
408
  "last-values",
406
409
  "is-compare"
407
- ]))]),
410
+ ]))], 64)) : createCommentVNode("v-if", true)]),
408
411
  _: 3
409
412
  }, 16, ["class"])) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [
410
413
  createCommentVNode(" 普通字段:渲染前后两份独立的组件用于对比 "),
@@ -413,7 +416,7 @@ var Container_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
413
416
  "tmagic-form-hidden": `${itemLabelWidth.value}` === "0" || !text.value,
414
417
  "show-before-diff": true
415
418
  } }), {
416
- label: withCtx(() => [renderSlot(_ctx.$slots, "label", {
419
+ label: withCtx(() => [shouldRenderLeafField.value ? renderSlot(_ctx.$slots, "label", {
417
420
  config: __props.config,
418
421
  type: type.value,
419
422
  text: text.value,
@@ -431,8 +434,8 @@ var Container_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
431
434
  "use-label",
432
435
  "label-title",
433
436
  "text"
434
- ])])]),
435
- default: withCtx(() => [tooltip.value.text ? (openBlock(), createBlock(unref(TMagicTooltip), {
437
+ ])], void 0, 0) : createCommentVNode("v-if", true)]),
438
+ default: withCtx(() => [shouldRenderLeafField.value ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [tooltip.value.text ? (openBlock(), createBlock(unref(TMagicTooltip), {
436
439
  key: 0,
437
440
  placement: tooltip.value.placement
438
441
  }, {
@@ -445,10 +448,10 @@ var Container_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
445
448
  }, 8, ["placement"])) : (openBlock(), createBlock(resolveDynamicComponent(tagName.value), mergeProps({ key: 1 }, fieldsProps.value, {
446
449
  model: __props.lastValues,
447
450
  onChange: onChangeHandler
448
- }), null, 16, ["model"]))]),
451
+ }), null, 16, ["model"]))], 64)) : createCommentVNode("v-if", true)]),
449
452
  _: 3
450
453
  }, 16, ["class"]),
451
- __props.config.tip && type.value === "checkbox" && !__props.config.useLabel ? (openBlock(), createBlock(unref(TMagicTooltip), {
454
+ shouldRenderLeafField.value && __props.config.tip && type.value === "checkbox" && !__props.config.useLabel ? (openBlock(), createBlock(unref(TMagicTooltip), {
452
455
  key: 0,
453
456
  placement: "top"
454
457
  }, {
@@ -470,7 +473,7 @@ var Container_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
470
473
  "show-after-diff": true
471
474
  }
472
475
  }), {
473
- label: withCtx(() => [renderSlot(_ctx.$slots, "label", {
476
+ label: withCtx(() => [shouldRenderLeafField.value ? renderSlot(_ctx.$slots, "label", {
474
477
  config: __props.config,
475
478
  type: type.value,
476
479
  text: text.value,
@@ -488,8 +491,8 @@ var Container_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
488
491
  "use-label",
489
492
  "label-title",
490
493
  "text"
491
- ])])]),
492
- default: withCtx(() => [tooltip.value.text ? (openBlock(), createBlock(unref(TMagicTooltip), {
494
+ ])], void 0, 0) : createCommentVNode("v-if", true)]),
495
+ default: withCtx(() => [shouldRenderLeafField.value ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [tooltip.value.text ? (openBlock(), createBlock(unref(TMagicTooltip), {
493
496
  key: 0,
494
497
  placement: tooltip.value.placement
495
498
  }, {
@@ -502,10 +505,10 @@ var Container_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
502
505
  }, 8, ["placement"])) : (openBlock(), createBlock(resolveDynamicComponent(tagName.value), mergeProps({ key: 1 }, fieldsProps.value, {
503
506
  model: __props.model,
504
507
  onChange: onChangeHandler
505
- }), null, 16, ["model"]))]),
508
+ }), null, 16, ["model"]))], 64)) : createCommentVNode("v-if", true)]),
506
509
  _: 3
507
510
  }, 16, ["style", "class"]),
508
- __props.config.tip && type.value === "checkbox" && !__props.config.useLabel ? (openBlock(), createBlock(unref(TMagicTooltip), {
511
+ shouldRenderLeafField.value && __props.config.tip && type.value === "checkbox" && !__props.config.useLabel ? (openBlock(), createBlock(unref(TMagicTooltip), {
509
512
  key: 1,
510
513
  placement: "top"
511
514
  }, {
package/dist/es/index.js CHANGED
@@ -1,10 +1,10 @@
1
- import "./_virtual/_rolldown/runtime.js";
2
1
  import { FORM_DIFF_CONFIG_KEY, FORM_SILENT_MODE_KEY, FORM_TYPE_MATCH_VALID_KEY } from "./schema.js";
3
- import { clearTypeMatchRules, deleteTypeMatchRule, getTypeMatchRule, registerTypeMatchRule, registerTypeMatchRules, validateTypeMatch } from "./utils/typeMatch.js";
2
+ import { MAX_SUGGESTION_OPTIONS, clearTypeMatchRules, deleteTypeMatchRule, getTypeMatchRule, optionSuggestion, registerTypeMatchRule, registerTypeMatchRules, stringifyExampleValue, validateTypeMatch } from "./utils/typeMatch.js";
4
3
  import { adaptFormValidator, applyExtendState, createObjectProp, createValues, datetimeFormatter, display, filterFunction, getDataByPage, getRules, initValue, sortArray, sortChange } from "./utils/form.js";
5
4
  import { useAddField } from "./utils/useAddField.js";
6
5
  import Hidden_default from "./fields/Hidden.js";
7
6
  import { deleteField, getField, registerField } from "./utils/config.js";
7
+ import { clearSilentLeafFieldTypes, getSilentLeafFieldTypes, registerSilentLeafFieldTypes } from "./utils/silentLeafFieldTypes.js";
8
8
  import Container_default from "./containers/Container.js";
9
9
  import Form_default from "./Form.js";
10
10
  import { stripTabItemsLazy, submitForm, validateForm } from "./submitForm.js";
@@ -38,6 +38,7 @@ import Cascader_default from "./fields/Cascader.js";
38
38
  import DynamicField_default from "./fields/DynamicField.js";
39
39
  import plugin_default from "./plugin.js";
40
40
  export * from "@tmagic/form-schema";
41
+ //#region packages/form/src/index.ts
41
42
  var createForm = (config) => config;
42
43
  //#endregion
43
- export { FORM_DIFF_CONFIG_KEY, FORM_SILENT_MODE_KEY, FORM_TYPE_MATCH_VALID_KEY, Cascader_default as MCascader, Checkbox_default as MCheckbox, CheckboxGroup_default as MCheckboxGroup, ColorPicker_default as MColorPicker, Container_default as MContainer, Date_default as MDate, DateTime_default as MDateTime, Daterange_default as MDaterange, Display_default as MDisplay, DynamicField_default as MDynamicField, Fieldset_default as MFieldset, FlexLayout_default as MFlexLayout, Form_default as MForm, FormBox_default as MFormBox, FormDialog_default as MFormDialog, FormDrawer_default as MFormDrawer, TableGroupList_default as MGroupList, Hidden_default as MHidden, Link_default as MLink, Number_default as MNumber, NumberRange_default as MNumberRange, Panel_default as MPanel, RadioGroup_default as MRadioGroup, Row_default as MRow, Select_default as MSelect, Switch_default as MSwitch, TableGroupList_default as MTable, TableGroupList_default as MTableGroupList, Tabs_default as MTabs, Text_default as MText, Textarea_default as MTextarea, Time_default as MTime, Timerange_default as MTimerange, adaptFormValidator, applyExtendState, clearTypeMatchRules, createForm, createObjectProp, createValues, datetimeFormatter, plugin_default as default, deleteField as deleteFormField, deleteTypeMatchRule, display, filterFunction, getDataByPage, getField as getFormField, getRules, getTypeMatchRule, initValue, registerField as registerFormField, registerTypeMatchRule, registerTypeMatchRules, sortArray, sortChange, stripTabItemsLazy, submitForm, useAddField, validateForm, validateTypeMatch };
44
+ export { FORM_DIFF_CONFIG_KEY, FORM_SILENT_MODE_KEY, FORM_TYPE_MATCH_VALID_KEY, MAX_SUGGESTION_OPTIONS, Cascader_default as MCascader, Checkbox_default as MCheckbox, CheckboxGroup_default as MCheckboxGroup, ColorPicker_default as MColorPicker, Container_default as MContainer, Date_default as MDate, DateTime_default as MDateTime, Daterange_default as MDaterange, Display_default as MDisplay, DynamicField_default as MDynamicField, Fieldset_default as MFieldset, FlexLayout_default as MFlexLayout, Form_default as MForm, FormBox_default as MFormBox, FormDialog_default as MFormDialog, FormDrawer_default as MFormDrawer, TableGroupList_default as MGroupList, Hidden_default as MHidden, Link_default as MLink, Number_default as MNumber, NumberRange_default as MNumberRange, Panel_default as MPanel, RadioGroup_default as MRadioGroup, Row_default as MRow, Select_default as MSelect, Switch_default as MSwitch, TableGroupList_default as MTable, TableGroupList_default as MTableGroupList, Tabs_default as MTabs, Text_default as MText, Textarea_default as MTextarea, Time_default as MTime, Timerange_default as MTimerange, adaptFormValidator, applyExtendState, clearSilentLeafFieldTypes, clearTypeMatchRules, createForm, createObjectProp, createValues, datetimeFormatter, plugin_default as default, deleteField as deleteFormField, deleteTypeMatchRule, display, filterFunction, getDataByPage, getField as getFormField, getRules, getSilentLeafFieldTypes, getTypeMatchRule, initValue, optionSuggestion, registerField as registerFormField, registerSilentLeafFieldTypes, registerTypeMatchRule, registerTypeMatchRules, sortArray, sortChange, stringifyExampleValue, stripTabItemsLazy, submitForm, useAddField, validateForm, validateTypeMatch };
package/dist/es/schema.js CHANGED
@@ -1,4 +1,3 @@
1
- import "./_virtual/_rolldown/runtime.js";
2
1
  export * from "@tmagic/form-schema";
3
2
  //#region packages/form/src/schema.ts
4
3
  var FORM_DIFF_CONFIG_KEY = Symbol("mFormDiffConfig");
@@ -6,11 +5,12 @@ var FORM_TYPE_MATCH_VALID_KEY = Symbol("mFormTypeMatchValid");
6
5
  /**
7
6
  * 静默模式标记,由 `submitForm` / `validateForm` 以隐藏方式挂载临时表单时 provide(debug 弹层模式不提供)。
8
7
  *
9
- * 重型字段组件(如 vs-code)可 inject 该标记并跳过自身渲染:字段校验由 FormItem 基于 model 值完成,
10
- * 与叶子 UI 组件实例无关,跳过可省去无谓的实例化开销(如 monaco worker / model 的创建)。
8
+ * Container 会基于该标记,并对照 `getSilentLeafFieldTypes()`(默认 `LEAF_FIELD_TYPES`)
9
+ * 跳过叶子字段的渲染,只保留 FormItem:字段校验由 FormItem 基于 model 值完成,与叶子 UI 组件实例无关。
10
+ * 重型字段组件(如 vs-code)也可 inject 该标记跳过自身渲染,省去无谓的实例化开销。
11
11
  *
12
12
  * 注意:仅「挂载无值副作用」(不在 onMounted/watch immediate 中 emit change、不依赖 DOM 计算值)的
13
- * 字段组件可以安全跳过,接入前需逐一审计。
13
+ * 字段组件可以安全跳过,接入前需逐一审计;业务扩展请使用 `registerSilentLeafFieldTypes`。
14
14
  */
15
15
  var FORM_SILENT_MODE_KEY = Symbol("mFormSilentMode");
16
16
  //#endregion
@@ -85,13 +85,14 @@ var mountFormInstance = (options) => {
85
85
  return () => h(userWrapper);
86
86
  }
87
87
  }) : userWrapper;
88
- const app = createApp(hidden ? defineComponent({
88
+ const rootComponent = hidden ? defineComponent({
89
89
  name: "MFormSilentProvider",
90
90
  setup() {
91
91
  provide(FORM_SILENT_MODE_KEY, true);
92
92
  return () => h(wrapperComponent);
93
93
  }
94
- }) : wrapperComponent);
94
+ }) : wrapperComponent;
95
+ const app = createApp(rootComponent);
95
96
  instance.app = app;
96
97
  if (appContext) Object.assign(app._context, appContext);
97
98
  if (!skipTimeout) timer = setTimeout(() => {
@@ -0,0 +1,49 @@
1
+ import { toLine } from "@tmagic/utils";
2
+ //#region packages/form/src/utils/silentLeafFieldTypes.ts
3
+ /**
4
+ * 可在静默校验模式下跳过渲染的内置叶子字段(默认集合)。
5
+ *
6
+ * 这些字段只渲染一个输入控件,内部没有嵌套 FormItem,且不会依赖组件挂载修改 model;
7
+ * 字段值由初始化逻辑处理(包括 defaultValue),因此跳过不影响校验结果。
8
+ *
9
+ * 业务侧可通过 `registerSilentLeafFieldTypes` 追加已审计的安全自定义字段。
10
+ */
11
+ var LEAF_FIELD_TYPES = /* @__PURE__ */ new Set([
12
+ "text",
13
+ "textarea",
14
+ "number",
15
+ "time",
16
+ "daterange",
17
+ "timerange",
18
+ "checkbox",
19
+ "radio-group",
20
+ "switch",
21
+ "select",
22
+ "cascader",
23
+ "color-picker",
24
+ "link"
25
+ ]);
26
+ /** 业务侧追加的静默叶子字段(不含内置默认集合) */
27
+ var extraSilentLeafFieldTypes = /* @__PURE__ */ new Set();
28
+ /**
29
+ * 注册可在静默校验中跳过渲染的叶子字段 type(追加到默认 `LEAF_FIELD_TYPES` 之上)。
30
+ *
31
+ * 仅应纳入「无嵌套 FormItem、无挂载值副作用」的字段;复合 / 动态子表单不可加入。
32
+ */
33
+ var registerSilentLeafFieldTypes = (types) => {
34
+ for (const type of types) {
35
+ if (typeof type !== "string" || !type) continue;
36
+ extraSilentLeafFieldTypes.add(toLine(type));
37
+ }
38
+ };
39
+ /** 当前生效的静默叶子字段集合:内置默认 ∪ 已注册扩展 */
40
+ var getSilentLeafFieldTypes = () => {
41
+ if (extraSilentLeafFieldTypes.size === 0) return LEAF_FIELD_TYPES;
42
+ return /* @__PURE__ */ new Set([...LEAF_FIELD_TYPES, ...extraSilentLeafFieldTypes]);
43
+ };
44
+ /** 清空业务侧追加的静默叶子字段(不影响内置默认集合;主要用于单测) */
45
+ var clearSilentLeafFieldTypes = () => {
46
+ extraSilentLeafFieldTypes.clear();
47
+ };
48
+ //#endregion
49
+ export { LEAF_FIELD_TYPES, clearSilentLeafFieldTypes, getSilentLeafFieldTypes, registerSilentLeafFieldTypes };
@@ -89,17 +89,20 @@ var stringifyExampleValue = (value) => {
89
89
  }
90
90
  return String(value);
91
91
  };
92
+ /** 参考建议中可选值全量展示上限;超出时仅举例 EXAMPLE_SUGGESTION_COUNT 个并标明总数。 */
92
93
  var MAX_SUGGESTION_OPTIONS = 20;
94
+ var EXAMPLE_SUGGESTION_COUNT = 5;
93
95
  /**
94
- * 生成「请使用以下某一个值:xxx;xxx」形式的参考建议;无可选值时返回空字符串(不追加建议)。
95
- * 可选值超过 MAX_SUGGESTION_OPTIONS 个时仅展示前若干个并以「等」省略。
96
+ * 生成可选项参考建议;无可选值时返回空字符串(不追加建议)。
97
+ * 未超过 MAX_SUGGESTION_OPTIONS 时全部列举;超过时仅举例前 EXAMPLE_SUGGESTION_COUNT 个并标明总数,避免 AI 误以为仅有举例值合法。
96
98
  */
97
99
  var optionSuggestion = (optionValues) => {
98
100
  const values = optionValues.filter((item) => typeof item !== "undefined");
99
101
  if (!values.length) return "";
100
- const shown = values.slice(0, MAX_SUGGESTION_OPTIONS).map(stringifyExampleValue);
101
- const suffix = values.length > MAX_SUGGESTION_OPTIONS ? " 等" : "";
102
- return `请使用以下某一个值:${shown.join(";")}${suffix}`;
102
+ const truncated = values.length > 20;
103
+ const shown = values.slice(0, truncated ? EXAMPLE_SUGGESTION_COUNT : values.length).map(stringifyExampleValue);
104
+ if (truncated) return `请从可选项中选用合法值(共 ${values.length} 个,例如:${shown.join(";")})`;
105
+ return `请使用以下某一个值:${shown.join(";")}`;
103
106
  };
104
107
  /**
105
108
  * 基于真实 options 生成类型不匹配场景的「参考示例值」。
@@ -484,4 +487,4 @@ var createTypeMatchValidator = (mForm, props, rule) => {
484
487
  };
485
488
  };
486
489
  //#endregion
487
- export { clearTypeMatchRules, createTypeMatchValidator, deleteTypeMatchRule, getTypeMatchRule, registerTypeMatchRule, registerTypeMatchRules, validateTypeMatch };
490
+ export { MAX_SUGGESTION_OPTIONS, clearTypeMatchRules, createTypeMatchValidator, deleteTypeMatchRule, getTypeMatchRule, optionSuggestion, registerTypeMatchRule, registerTypeMatchRules, stringifyExampleValue, validateTypeMatch };