@tmagic/form 1.8.0-beta.0 → 1.8.0-beta.10

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 (61) hide show
  1. package/dist/es/Form.vue_vue_type_script_setup_true_lang.js +103 -26
  2. package/dist/es/FormBox.vue_vue_type_script_setup_true_lang.js +7 -1
  3. package/dist/es/FormDialog.vue_vue_type_script_setup_true_lang.js +7 -1
  4. package/dist/es/FormDrawer.vue_vue_type_script_setup_true_lang.js +7 -1
  5. package/dist/es/containers/Col.vue_vue_type_script_setup_true_lang.js +1 -1
  6. package/dist/es/containers/Container.vue_vue_type_script_setup_true_lang.js +195 -78
  7. package/dist/es/containers/Fieldset.vue_vue_type_script_setup_true_lang.js +5 -3
  8. package/dist/es/containers/FlexLayout.vue_vue_type_script_setup_true_lang.js +1 -1
  9. package/dist/es/containers/FormLabel.vue_vue_type_script_setup_true_lang.js +1 -1
  10. package/dist/es/containers/GroupList.vue_vue_type_script_setup_true_lang.js +6 -3
  11. package/dist/es/containers/GroupListItem.vue_vue_type_script_setup_true_lang.js +10 -9
  12. package/dist/es/containers/Panel.vue_vue_type_script_setup_true_lang.js +1 -1
  13. package/dist/es/containers/Row.vue_vue_type_script_setup_true_lang.js +1 -1
  14. package/dist/es/containers/Step.vue_vue_type_script_setup_true_lang.js +1 -1
  15. package/dist/es/containers/Tabs.vue_vue_type_script_setup_true_lang.js +6 -3
  16. package/dist/es/containers/table/ActionsColumn.vue_vue_type_script_setup_true_lang.js +1 -1
  17. package/dist/es/containers/table/SortColumn.vue_vue_type_script_setup_true_lang.js +1 -1
  18. package/dist/es/containers/table/Table.vue_vue_type_script_setup_true_lang.js +4 -4
  19. package/dist/es/containers/table-group-list/TableGroupList.vue_vue_type_script_setup_true_lang.js +1 -1
  20. package/dist/es/fields/Cascader.vue_vue_type_script_setup_true_lang.js +1 -1
  21. package/dist/es/fields/Checkbox.vue_vue_type_script_setup_true_lang.js +1 -1
  22. package/dist/es/fields/CheckboxGroup.vue_vue_type_script_setup_true_lang.js +1 -1
  23. package/dist/es/fields/ColorPicker.vue_vue_type_script_setup_true_lang.js +1 -1
  24. package/dist/es/fields/Date.vue_vue_type_script_setup_true_lang.js +1 -1
  25. package/dist/es/fields/DateTime.vue_vue_type_script_setup_true_lang.js +1 -1
  26. package/dist/es/fields/Daterange.vue_vue_type_script_setup_true_lang.js +1 -1
  27. package/dist/es/fields/Display.vue_vue_type_script_setup_true_lang.js +1 -1
  28. package/dist/es/fields/DynamicField.vue_vue_type_script_setup_true_lang.js +1 -1
  29. package/dist/es/fields/Hidden.vue_vue_type_script_setup_true_lang.js +1 -1
  30. package/dist/es/fields/Link.vue_vue_type_script_setup_true_lang.js +1 -1
  31. package/dist/es/fields/Number.vue_vue_type_script_setup_true_lang.js +1 -1
  32. package/dist/es/fields/NumberRange.vue_vue_type_script_setup_true_lang.js +1 -1
  33. package/dist/es/fields/RadioGroup.vue_vue_type_script_setup_true_lang.js +1 -1
  34. package/dist/es/fields/Select.vue_vue_type_script_setup_true_lang.js +1 -1
  35. package/dist/es/fields/Switch.vue_vue_type_script_setup_true_lang.js +1 -1
  36. package/dist/es/fields/Text.vue_vue_type_script_setup_true_lang.js +1 -1
  37. package/dist/es/fields/Textarea.vue_vue_type_script_setup_true_lang.js +1 -1
  38. package/dist/es/fields/Time.vue_vue_type_script_setup_true_lang.js +1 -1
  39. package/dist/es/fields/Timerange.vue_vue_type_script_setup_true_lang.js +1 -1
  40. package/dist/es/index.js +2 -1
  41. package/dist/es/schema.js +4 -0
  42. package/dist/es/style.css +4 -1
  43. package/dist/es/submitForm.js +14 -2
  44. package/dist/es/utils/form.js +2 -2
  45. package/dist/style.css +4 -1
  46. package/dist/tmagic-form.umd.cjs +1844 -1610
  47. package/package.json +5 -5
  48. package/src/Form.vue +148 -24
  49. package/src/FormBox.vue +4 -0
  50. package/src/FormDialog.vue +4 -0
  51. package/src/FormDrawer.vue +4 -0
  52. package/src/containers/Container.vue +178 -54
  53. package/src/containers/Fieldset.vue +5 -2
  54. package/src/containers/GroupList.vue +1 -1
  55. package/src/containers/GroupListItem.vue +4 -3
  56. package/src/containers/Tabs.vue +10 -2
  57. package/src/containers/table/Table.vue +9 -3
  58. package/src/schema.ts +47 -0
  59. package/src/submitForm.ts +34 -3
  60. package/src/theme/container.scss +4 -1
  61. package/types/index.d.ts +1005 -421
@@ -1,12 +1,13 @@
1
+ import { FORM_DIFF_CONFIG_KEY } from "./schema.js";
1
2
  import { getConfig } from "./utils/config.js";
2
3
  import { initValue } from "./utils/form.js";
3
4
  import Container_default from "./containers/Container.js";
4
- import { Fragment, createBlock, createCommentVNode, createElementBlock, defineComponent, normalizeStyle, openBlock, provide, reactive, ref, renderList, shallowRef, toRaw, unref, useTemplateRef, watch, watchEffect, withCtx } from "vue";
5
+ import { Fragment, createBlock, createCommentVNode, createElementBlock, createSlots, defineComponent, mergeProps, normalizeStyle, openBlock, provide, reactive, ref, renderList, renderSlot, shallowRef, toRaw, unref, useTemplateRef, watch, watchEffect, withCtx } from "vue";
5
6
  import { cloneDeep, isEqual } from "lodash-es";
6
7
  import { TMagicForm, tMagicMessage, tMagicMessageBox } from "@tmagic/design";
7
8
  import { setValueByKeyPath } from "@tmagic/utils";
8
9
  //#region packages/form/src/Form.vue?vue&type=script&setup=true&lang.ts
9
- var Form_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
10
+ var Form_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
10
11
  name: "MForm",
11
12
  __name: "Form",
12
13
  props: {
@@ -34,7 +35,13 @@ var Form_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineCom
34
35
  keyProp: { default: "__key" },
35
36
  popperClass: {},
36
37
  preventSubmitDefault: { type: Boolean },
37
- extendState: {}
38
+ useFieldTextInError: {
39
+ type: Boolean,
40
+ default: true
41
+ },
42
+ extendState: {},
43
+ showDiff: {},
44
+ selfDiffFieldTypes: {}
38
45
  },
39
46
  emits: [
40
47
  "change",
@@ -52,14 +59,45 @@ var Form_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineCom
52
59
  const lastValuesProcessed = ref({});
53
60
  const fields = /* @__PURE__ */ new Map();
54
61
  const requestFuc = getConfig("request");
62
+ /**
63
+ * formState 实现说明:
64
+ *
65
+ * 1. 与 props 直接对应的字段(config / initValues / lastValues / isCompare / parentValues /
66
+ * keyProp / popperClass)使用「访问器(getter)」定义,每次读取都会回到 `props.xxx`
67
+ * 取最新值,不存在「props 变了但 formState 还没同步过来」的中间态。
68
+ *
69
+ * 2. `values` / `lastValuesProcessed` 是 ref,Vue 的 `reactive` 会自动解包,因此每次
70
+ * 访问 `formState.values` / `formState.lastValuesProcessed` 也都是当前 ref 值。
71
+ *
72
+ * 3. `extendState` 注入的字段在下方的 `watchEffect` 中合并到 `formState`:
73
+ * - data 描述符(普通字段)通过 `formState[key] = value` 写入,走 reactive proxy 的
74
+ * set,触发依赖通知;`extendState` 同步段读到的响应式数据变化时会自动重跑,
75
+ * 把最新值刷进 formState。
76
+ * - accessor 描述符(`{ get stage() { return ... } }`)按原样写入,调用方可以控制
77
+ * 读时求值,每次读取都会重新执行 getter。
78
+ */
55
79
  const formState = reactive({
56
- keyProp: props.keyProp,
57
- popperClass: props.popperClass,
58
- config: props.config,
59
- initValues: props.initValues,
60
- isCompare: props.isCompare,
61
- lastValues: props.lastValues,
62
- parentValues: props.parentValues,
80
+ get keyProp() {
81
+ return props.keyProp;
82
+ },
83
+ get popperClass() {
84
+ return props.popperClass;
85
+ },
86
+ get config() {
87
+ return props.config;
88
+ },
89
+ get initValues() {
90
+ return props.initValues;
91
+ },
92
+ get isCompare() {
93
+ return props.isCompare;
94
+ },
95
+ get lastValues() {
96
+ return props.lastValues;
97
+ },
98
+ get parentValues() {
99
+ return props.parentValues;
100
+ },
63
101
  values,
64
102
  lastValuesProcessed,
65
103
  $emit: emit,
@@ -76,22 +114,57 @@ var Form_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineCom
76
114
  });
77
115
  }
78
116
  });
79
- watchEffect(async () => {
80
- formState.initValues = props.initValues;
81
- formState.lastValues = props.lastValues;
82
- formState.isCompare = props.isCompare;
83
- formState.config = props.config;
84
- formState.keyProp = props.keyProp;
85
- formState.popperClass = props.popperClass;
86
- formState.parentValues = props.parentValues;
87
- if (typeof props.extendState === "function") {
88
- const state = await props.extendState(formState) || {};
89
- Object.entries(state).forEach(([key, value]) => {
90
- formState[key] = value;
91
- });
117
+ /**
118
+ * `extendState` 的同步段(直到第一个 `await` 之前)所访问的任何响应式数据,
119
+ * 都会被 `watchEffect` 自动跟踪。这样可以兼容历史用法 ——
120
+ *
121
+ * extendState: (formState) => ({
122
+ * username: store.username, // 同步读 store,会被跟踪
123
+ * env: store.env,
124
+ * })
125
+ *
126
+ * `store.username` 变化时,整个 effect 重跑,新值会被刷进 `formState`。
127
+ *
128
+ * prop 派生字段(initValues / config / ...)已经在上方用 getter 定义,
129
+ * 这里不再重复同步;因此 `props.initValues` 这类高频变化也不会再触发
130
+ * `extendState` 重跑(旧版的性能问题修复点)。
131
+ *
132
+ * 实现细节:
133
+ * - data 描述符:通过 `formState[key] = value` 走 reactive proxy 的 set,
134
+ * 触发依赖通知;与旧版「逐项赋值」语义完全等价。
135
+ * - accessor 描述符(`{ get stage() {...} }`)按原样写入 formState,调用方
136
+ * 可以自行控制读时求值;强制 `configurable: true` 以便下一次重跑可再 define。
137
+ */
138
+ watchEffect(async (onCleanup) => {
139
+ const { extendState } = props;
140
+ if (typeof extendState !== "function") return;
141
+ let stale = false;
142
+ onCleanup(() => {
143
+ stale = true;
144
+ });
145
+ let state = {};
146
+ try {
147
+ state = await extendState(formState) || {};
148
+ } catch (e) {
149
+ console.error("[MForm] extendState failed:", e);
150
+ return;
151
+ }
152
+ if (stale) return;
153
+ for (const [key, descriptor] of Object.entries(Object.getOwnPropertyDescriptors(state))) if ("value" in descriptor) formState[key] = state[key];
154
+ else {
155
+ descriptor.configurable = true;
156
+ Object.defineProperty(formState, key, descriptor);
92
157
  }
93
158
  });
94
159
  provide("mForm", formState);
160
+ provide(FORM_DIFF_CONFIG_KEY, {
161
+ get showDiff() {
162
+ return props.showDiff;
163
+ },
164
+ get selfDiffFieldTypes() {
165
+ return props.selfDiffFieldTypes;
166
+ }
167
+ });
95
168
  const changeRecords = shallowRef([]);
96
169
  watch([() => props.config, () => props.initValues], ([config], [preConfig]) => {
97
170
  changeRecords.value = [];
@@ -176,7 +249,7 @@ var Form_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineCom
176
249
  Object.entries(invalidFields).forEach(([prop, ValidateError]) => {
177
250
  ValidateError.forEach(({ field, message }) => {
178
251
  const name = field || prop;
179
- const text = getTextByName(name, props.config) || name;
252
+ const text = (props.useFieldTextInError ? getTextByName(name, props.config) : void 0) || name;
180
253
  error.push(`${text} -> ${message}`);
181
254
  });
182
255
  });
@@ -208,7 +281,11 @@ var Form_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineCom
208
281
  "step-active": __props.stepActive,
209
282
  size: __props.size,
210
283
  onChange: changeHandler
211
- }, null, 8, [
284
+ }, createSlots({ _: 2 }, [_ctx.$slots.label ? {
285
+ name: "label",
286
+ fn: withCtx((labelProps) => [renderSlot(_ctx.$slots, "label", mergeProps({ ref_for: true }, labelProps))]),
287
+ key: "0"
288
+ } : void 0]), 1032, [
212
289
  "disabled",
213
290
  "config",
214
291
  "model",
@@ -219,7 +296,7 @@ var Form_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineCom
219
296
  "size"
220
297
  ]);
221
298
  }), 128)) : createCommentVNode("v-if", true)]),
222
- _: 1
299
+ _: 3
223
300
  }, 8, [
224
301
  "model",
225
302
  "label-width",
@@ -3,7 +3,7 @@ import { computed, createElementBlock, createElementVNode, createTextVNode, crea
3
3
  import { TMagicButton, TMagicScrollbar } from "@tmagic/design";
4
4
  //#region packages/form/src/FormBox.vue?vue&type=script&setup=true&lang.ts
5
5
  var footerHeight = 60;
6
- var FormBox_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
6
+ var FormBox_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
7
7
  name: "MFormBox",
8
8
  __name: "FormBox",
9
9
  props: {
@@ -19,6 +19,10 @@ var FormBox_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ define
19
19
  inline: { type: Boolean },
20
20
  labelPosition: {},
21
21
  preventSubmitDefault: { type: Boolean },
22
+ useFieldTextInError: {
23
+ type: Boolean,
24
+ default: true
25
+ },
22
26
  extendState: {}
23
27
  },
24
28
  emits: [
@@ -81,6 +85,7 @@ var FormBox_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ define
81
85
  "label-position": __props.labelPosition,
82
86
  inline: __props.inline,
83
87
  "prevent-submit-default": __props.preventSubmitDefault,
88
+ "use-field-text-in-error": __props.useFieldTextInError,
84
89
  "extend-state": __props.extendState,
85
90
  onChange: changeHandler
86
91
  }, null, 8, [
@@ -93,6 +98,7 @@ var FormBox_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ define
93
98
  "label-position",
94
99
  "inline",
95
100
  "prevent-submit-default",
101
+ "use-field-text-in-error",
96
102
  "extend-state"
97
103
  ]), renderSlot(_ctx.$slots, "default")]),
98
104
  _: 3
@@ -3,7 +3,7 @@ import { computed, createBlock, createCommentVNode, createElementBlock, createEl
3
3
  import { TMagicButton, TMagicCol, TMagicDialog, TMagicRow } from "@tmagic/design";
4
4
  //#region packages/form/src/FormDialog.vue?vue&type=script&setup=true&lang.ts
5
5
  var _hoisted_1 = { style: { "min-height": "1px" } };
6
- var FormDialog_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
6
+ var FormDialog_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
7
7
  name: "MFormDialog",
8
8
  __name: "FormDialog",
9
9
  props: {
@@ -41,6 +41,10 @@ var FormDialog_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ def
41
41
  type: Boolean,
42
42
  default: true
43
43
  },
44
+ useFieldTextInError: {
45
+ type: Boolean,
46
+ default: true
47
+ },
44
48
  extendState: {}
45
49
  },
46
50
  emits: [
@@ -191,6 +195,7 @@ var FormDialog_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ def
191
195
  "label-position": __props.labelPosition,
192
196
  inline: __props.inline,
193
197
  "prevent-submit-default": __props.preventSubmitDefault,
198
+ "use-field-text-in-error": __props.useFieldTextInError,
194
199
  "extend-state": __props.extendState,
195
200
  onChange: changeHandler
196
201
  }, null, 8, [
@@ -204,6 +209,7 @@ var FormDialog_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ def
204
209
  "label-position",
205
210
  "inline",
206
211
  "prevent-submit-default",
212
+ "use-field-text-in-error",
207
213
  "extend-state"
208
214
  ]), renderSlot(_ctx.$slots, "default")], 4)) : createCommentVNode("v-if", true)]),
209
215
  _: 3
@@ -3,7 +3,7 @@ import { createBlock, createCommentVNode, createElementBlock, createElementVNode
3
3
  import { TMagicButton, TMagicCol, TMagicDrawer, TMagicRow } from "@tmagic/design";
4
4
  //#region packages/form/src/FormDrawer.vue?vue&type=script&setup=true&lang.ts
5
5
  var _hoisted_1 = { style: { "min-height": "1px" } };
6
- var FormDrawer_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
6
+ var FormDrawer_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
7
7
  name: "MFormDialog",
8
8
  __name: "FormDrawer",
9
9
  props: {
@@ -24,6 +24,10 @@ var FormDrawer_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ def
24
24
  inline: { type: Boolean },
25
25
  labelPosition: {},
26
26
  preventSubmitDefault: { type: Boolean },
27
+ useFieldTextInError: {
28
+ type: Boolean,
29
+ default: true
30
+ },
27
31
  beforeClose: {},
28
32
  extendState: {}
29
33
  },
@@ -149,6 +153,7 @@ var FormDrawer_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ def
149
153
  "label-position": __props.labelPosition,
150
154
  inline: __props.inline,
151
155
  "prevent-submit-default": __props.preventSubmitDefault,
156
+ "use-field-text-in-error": __props.useFieldTextInError,
152
157
  "extend-state": __props.extendState,
153
158
  onChange: changeHandler
154
159
  }, null, 8, [
@@ -161,6 +166,7 @@ var FormDrawer_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ def
161
166
  "label-position",
162
167
  "inline",
163
168
  "prevent-submit-default",
169
+ "use-field-text-in-error",
164
170
  "extend-state"
165
171
  ]), renderSlot(_ctx.$slots, "default")], 512)) : createCommentVNode("v-if", true)]),
166
172
  _: 3
@@ -3,7 +3,7 @@ import Container_default from "./Container.js";
3
3
  import { computed, createBlock, createVNode, defineComponent, inject, openBlock, unref, vShow, withCtx, withDirectives } from "vue";
4
4
  import { TMagicCol } from "@tmagic/design";
5
5
  //#region packages/form/src/containers/Col.vue?vue&type=script&setup=true&lang.ts
6
- var Col_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
6
+ var Col_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
7
7
  name: "MFormCol",
8
8
  __name: "Col",
9
9
  props: {