@veltra/desktop 1.7.10 → 1.7.12

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 (42) hide show
  1. package/dist/components/batch-edit/batch-edit-form.js +2 -6
  2. package/dist/components/batch-edit/batch-edit-form.js.map +1 -1
  3. package/dist/components/batch-edit/batch-edit.js +0 -1
  4. package/dist/components/batch-edit/batch-edit.js.map +1 -1
  5. package/dist/components/button/button.js +0 -1
  6. package/dist/components/button/button.js.map +1 -1
  7. package/dist/components/drawer/drawer.js +18 -10
  8. package/dist/components/drawer/drawer.js.map +1 -1
  9. package/dist/components/drawer/style2.css +15 -0
  10. package/dist/components/form/form.js.map +1 -1
  11. package/dist/components/form/form.vue_vue_type_script_setup_true_lang.js +12 -13
  12. package/dist/components/form/form.vue_vue_type_script_setup_true_lang.js.map +1 -1
  13. package/dist/components/form/use-node-interceptor.js +31 -3
  14. package/dist/components/form/use-node-interceptor.js.map +1 -1
  15. package/dist/components/form-item/form-item.js.map +1 -1
  16. package/dist/components/form-item/form-item.vue_vue_type_script_setup_true_lang.js +14 -8
  17. package/dist/components/form-item/form-item.vue_vue_type_script_setup_true_lang.js.map +1 -1
  18. package/dist/types/action.d.ts +6 -1
  19. package/dist/types/batch-edit.d.ts +0 -2
  20. package/dist/types/button.d.ts +5 -1
  21. package/dist/types/drawer.d.ts +6 -3
  22. package/dist/types/form.d.ts +0 -2
  23. package/dist/types/layout.d.ts +2 -0
  24. package/package.json +5 -5
  25. package/src/components/batch-edit/__test__/batch-edit.test.ts +0 -138
  26. package/src/components/batch-edit/batch-edit-form.vue +2 -16
  27. package/src/components/button/__test__/button.test.ts +48 -0
  28. package/src/components/button/button.vue +1 -8
  29. package/src/components/drawer/__test__/drawer.test.ts +118 -0
  30. package/src/components/drawer/drawer.vue +5 -2
  31. package/src/components/drawer/style.scss +15 -0
  32. package/src/components/form/__test__/form.test.ts +167 -31
  33. package/src/components/form/form.vue +10 -11
  34. package/src/components/form/use-node-interceptor.ts +36 -2
  35. package/src/components/form-item/__test__/form-item.test.ts +40 -10
  36. package/src/components/form-item/form-item.vue +14 -17
  37. package/src/types/action.ts +6 -1
  38. package/src/types/batch-edit.ts +0 -2
  39. package/src/types/button.ts +5 -1
  40. package/src/types/drawer.ts +6 -3
  41. package/src/types/form.ts +0 -2
  42. package/src/types/layout.ts +2 -0
@@ -15,7 +15,7 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
15
15
  __name: "batch-edit-form",
16
16
  setup(__props, { expose: __expose }) {
17
17
  const batchEditCtx = inject(BatchEditDIKey);
18
- const { cls, props, state, emit, handleClose, handleSave, staticFeatures, dynamicFeatures, syncing } = batchEditCtx;
18
+ const { cls, props, state, handleClose, handleSave, staticFeatures, dynamicFeatures, syncing } = batchEditCtx;
19
19
  const focused = toRef(batchEditCtx, "focused");
20
20
  const formComponentRef = shallowRef();
21
21
  __expose({
@@ -28,9 +28,6 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
28
28
  if (syncing.value) return;
29
29
  if (state.row && props.quickEdit) o(state.row.data).set(field, value);
30
30
  }
31
- function handleFormFieldChange(field, ...args) {
32
- emit("field:change", field, ...args);
33
- }
34
31
  const creatable = computed(() => {
35
32
  if (state.formActionType !== "create") return false;
36
33
  return staticFeatures.value.has("create") || dynamicFeatures.value.create?.(state.row);
@@ -89,8 +86,7 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
89
86
  model: unref(props).model,
90
87
  readonly: unref(props).readonly,
91
88
  "label-width": unref(props).labelWidth,
92
- "onField:update": handleFieldUpdate,
93
- "onField:change": handleFormFieldChange
89
+ "onField:update": handleFieldUpdate
94
90
  }, {
95
91
  default: withCtx(() => [renderSlot(_ctx.$slots, "default", normalizeProps(guardReactiveProps({
96
92
  row: unref(state).row,
@@ -1 +1 @@
1
- {"version":3,"file":"batch-edit-form.js","names":[],"sources":["../../../src/components/batch-edit/batch-edit-form.vue"],"sourcesContent":["<template>\n <!-- 表单常驻挂载(快照只在挂载时对传入的 model 拍一次),仅用 v-show 控制显隐 -->\n <aside :class=\"cls.e('form')\" v-if=\"!!props.model\" v-show=\"state.formVisible\">\n <header :class=\"cls.e('form-header')\">\n <span :class=\"[cls.e('form-icon'), bem.is(state.formActionType)]\">\n <u-icon>\n <component :is=\"headerInfo.icon\" />\n </u-icon>\n </span>\n <div :class=\"cls.e('form-title')\">\n <h3 :class=\"cls.e('form-title-text')\">{{ headerInfo.title }}</h3>\n </div>\n <u-button\n :class=\"cls.e('form-close')\"\n :icon=\"Close\"\n text\n circle\n size=\"small\"\n title=\"关闭\"\n @click=\"handleClose\"\n />\n </header>\n\n <u-scroll always :class=\"cls.e('form-body')\">\n <transition name=\"fade\" appear mode=\"out-in\">\n <u-form\n ref=\"formComponentRef\"\n :model=\"props.model\"\n :readonly=\"props.readonly\"\n :label-width=\"props.labelWidth\"\n @field:update=\"handleFieldUpdate\"\n @field:change=\"handleFormFieldChange\"\n >\n <slot\n v-bind=\"{\n row: state.row,\n parentRow: state.parentRow,\n formActionType: state.formActionType,\n depth: state.depth,\n indexes: state.indexPath,\n index: state.row?.index\n }\"\n />\n </u-form>\n </transition>\n </u-scroll>\n\n <footer :class=\"cls.e('form-footer')\">\n <span :class=\"cls.e('form-hint')\">\n <template v-if=\"props.readonly\"> 只读模式 </template>\n\n <span :class=\"{ [bem.is('concealed')]: !focused }\">\n <template v-if=\"!(state.formActionType === 'update' && props.quickEdit)\">\n <u-kbd>Ctrl + S</u-kbd> 保存 ·\n </template>\n <u-kbd>Esc</u-kbd> 关闭\n </span>\n </span>\n\n <div :class=\"cls.e('form-actions')\">\n <u-button size=\"small\" text :loading=\"state.loading\" @click=\"handleClose\"> 取消 </u-button>\n <u-button\n v-if=\"showSaveBtn\"\n type=\"primary\"\n size=\"small\"\n title=\"保存\"\n :icon=\"Save\"\n :loading=\"state.loading\"\n @click=\"handleSave\"\n />\n </div>\n </footer>\n </aside>\n</template>\n\n<script lang=\"ts\" setup>\nimport { o } from '@cat-kit/core'\nimport { Close, Save } from '@veltra/icons/normal'\nimport { bem } from '@veltra/utils'\nimport { computed, inject, shallowRef, toRef } from 'vue'\n\nimport type { _FormExposed, FormExposed } from '../../types/form'\nimport { UButton } from '../button'\nimport { UForm } from '../form'\nimport { UIcon } from '../icon'\nimport { UKbd } from '../kbd'\nimport { UScroll } from '../scroll'\nimport { BatchEditDIKey } from './di'\nimport { FORM_ACTION_HEADER_MAP } from './form-action-header'\n\ndefineOptions({ name: 'UBatchEditForm' })\n\nconst batchEditCtx = inject(BatchEditDIKey)!\n\nconst {\n cls,\n props,\n state,\n emit,\n handleClose,\n handleSave,\n staticFeatures,\n dynamicFeatures,\n syncing\n} = batchEditCtx\n\nconst focused = toRef(batchEditCtx, 'focused')\n\nconst formComponentRef = shallowRef<FormExposed>()\n\ndefineExpose<_FormExposed>({\n el: toRef(() => formComponentRef.value?.el),\n validate: () => formComponentRef.value?.validate() ?? Promise.resolve(true),\n clearValidate: () => formComponentRef.value?.clearValidate(),\n reset: () => formComponentRef.value?.reset()\n})\n\nfunction handleFieldUpdate(field: string, value: any) {\n // 编程方式重置/回显期间不写回行数据,避免默认值污染源数据\n if (syncing.value) return\n\n if (state.row && props.quickEdit) {\n o(state.row.data).set(field, value)\n }\n}\n\nfunction handleFormFieldChange(field: string, ...args: any[]) {\n emit('field:change', field, ...args)\n}\n\nconst creatable = computed(() => {\n if (state.formActionType !== 'create') return false\n return staticFeatures.value.has('create') || dynamicFeatures.value.create?.(state.row)\n})\n\nconst creatableChild = computed(() => {\n if (state.formActionType !== 'createChild') return false\n return (\n staticFeatures.value.has('createChild') || dynamicFeatures.value.createChild?.(state.parentRow)\n )\n})\n\nconst updatable = computed(() => {\n if (state.formActionType !== 'update') return false\n return staticFeatures.value.has('update') || dynamicFeatures.value.update?.(state.row)\n})\n\nconst showSaveBtn = computed(() => {\n if (props.readonly) return false\n if (props.quickEdit && state.formActionType === 'update') return false\n return creatable.value || updatable.value || creatableChild.value\n})\n\nconst headerInfo = computed(() => FORM_ACTION_HEADER_MAP[state.formActionType])\n</script>\n"],"mappings":"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"}
1
+ {"version":3,"file":"batch-edit-form.js","names":[],"sources":["../../../src/components/batch-edit/batch-edit-form.vue"],"sourcesContent":["<template>\n <!-- 表单常驻挂载(快照只在挂载时对传入的 model 拍一次),仅用 v-show 控制显隐 -->\n <aside :class=\"cls.e('form')\" v-if=\"!!props.model\" v-show=\"state.formVisible\">\n <header :class=\"cls.e('form-header')\">\n <span :class=\"[cls.e('form-icon'), bem.is(state.formActionType)]\">\n <u-icon>\n <component :is=\"headerInfo.icon\" />\n </u-icon>\n </span>\n <div :class=\"cls.e('form-title')\">\n <h3 :class=\"cls.e('form-title-text')\">{{ headerInfo.title }}</h3>\n </div>\n <u-button\n :class=\"cls.e('form-close')\"\n :icon=\"Close\"\n text\n circle\n size=\"small\"\n title=\"关闭\"\n @click=\"handleClose\"\n />\n </header>\n\n <u-scroll always :class=\"cls.e('form-body')\">\n <transition name=\"fade\" appear mode=\"out-in\">\n <u-form\n ref=\"formComponentRef\"\n :model=\"props.model\"\n :readonly=\"props.readonly\"\n :label-width=\"props.labelWidth\"\n @field:update=\"handleFieldUpdate\"\n >\n <slot\n v-bind=\"{\n row: state.row,\n parentRow: state.parentRow,\n formActionType: state.formActionType,\n depth: state.depth,\n indexes: state.indexPath,\n index: state.row?.index\n }\"\n />\n </u-form>\n </transition>\n </u-scroll>\n\n <footer :class=\"cls.e('form-footer')\">\n <span :class=\"cls.e('form-hint')\">\n <template v-if=\"props.readonly\"> 只读模式 </template>\n\n <span :class=\"{ [bem.is('concealed')]: !focused }\">\n <template v-if=\"!(state.formActionType === 'update' && props.quickEdit)\">\n <u-kbd>Ctrl + S</u-kbd> 保存 ·\n </template>\n <u-kbd>Esc</u-kbd> 关闭\n </span>\n </span>\n\n <div :class=\"cls.e('form-actions')\">\n <u-button size=\"small\" text :loading=\"state.loading\" @click=\"handleClose\"> 取消 </u-button>\n <u-button\n v-if=\"showSaveBtn\"\n type=\"primary\"\n size=\"small\"\n title=\"保存\"\n :icon=\"Save\"\n :loading=\"state.loading\"\n @click=\"handleSave\"\n />\n </div>\n </footer>\n </aside>\n</template>\n\n<script lang=\"ts\" setup>\nimport { o } from '@cat-kit/core'\nimport { Close, Save } from '@veltra/icons/normal'\nimport { bem } from '@veltra/utils'\nimport { computed, inject, shallowRef, toRef } from 'vue'\n\nimport type { _FormExposed, FormExposed } from '../../types/form'\nimport { UButton } from '../button'\nimport { UForm } from '../form'\nimport { UIcon } from '../icon'\nimport { UKbd } from '../kbd'\nimport { UScroll } from '../scroll'\nimport { BatchEditDIKey } from './di'\nimport { FORM_ACTION_HEADER_MAP } from './form-action-header'\n\ndefineOptions({ name: 'UBatchEditForm' })\n\nconst batchEditCtx = inject(BatchEditDIKey)!\n\nconst { cls, props, state, handleClose, handleSave, staticFeatures, dynamicFeatures, syncing } =\n batchEditCtx\n\nconst focused = toRef(batchEditCtx, 'focused')\n\nconst formComponentRef = shallowRef<FormExposed>()\n\ndefineExpose<_FormExposed>({\n el: toRef(() => formComponentRef.value?.el),\n validate: () => formComponentRef.value?.validate() ?? Promise.resolve(true),\n clearValidate: () => formComponentRef.value?.clearValidate(),\n reset: () => formComponentRef.value?.reset()\n})\n\nfunction handleFieldUpdate(field: string, value: any) {\n // 编程方式重置/回显期间不写回行数据,避免默认值污染源数据\n if (syncing.value) return\n\n if (state.row && props.quickEdit) {\n o(state.row.data).set(field, value)\n }\n}\n\nconst creatable = computed(() => {\n if (state.formActionType !== 'create') return false\n return staticFeatures.value.has('create') || dynamicFeatures.value.create?.(state.row)\n})\n\nconst creatableChild = computed(() => {\n if (state.formActionType !== 'createChild') return false\n return (\n staticFeatures.value.has('createChild') || dynamicFeatures.value.createChild?.(state.parentRow)\n )\n})\n\nconst updatable = computed(() => {\n if (state.formActionType !== 'update') return false\n return staticFeatures.value.has('update') || dynamicFeatures.value.update?.(state.row)\n})\n\nconst showSaveBtn = computed(() => {\n if (props.readonly) return false\n if (props.quickEdit && state.formActionType === 'update') return false\n return creatable.value || updatable.value || creatableChild.value\n})\n\nconst headerInfo = computed(() => FORM_ACTION_HEADER_MAP[state.formActionType])\n</script>\n"],"mappings":"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"}
@@ -46,7 +46,6 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
46
46
  textEllipsis: { type: Boolean }
47
47
  },
48
48
  emits: [
49
- "field:change",
50
49
  "update:data",
51
50
  "create",
52
51
  "create-prev",
@@ -1 +1 @@
1
- {"version":3,"file":"batch-edit.js","names":[],"sources":["../../../src/components/batch-edit/batch-edit.vue"],"sourcesContent":["<template>\n <u-layout\n :class=\"cls.b\"\n :cols=\"cols\"\n rows=\"minmax(0, 1fr) \"\n gap=\"8px\"\n resizable\n tabindex=\"-1\"\n @focusin=\"handleFocusIn\"\n @focusout=\"handleFocusOut\"\n @keydown.capture=\"handleKeydown\"\n >\n <!-- 编辑列表 -->\n <BatchEditList :slots=\"slots\" />\n\n <!-- 编辑表单 -->\n <BatchEditForm ref=\"form\" v-slot=\"scoped\">\n <slot name=\"form\" v-bind=\"scoped\" />\n </BatchEditForm>\n </u-layout>\n</template>\n\n<script lang=\"ts\" setup>\nimport { bem } from '@veltra/utils'\nimport { computed, provide, useTemplateRef } from 'vue'\n\nimport type { BatchEditEmits, BatchEditProps, BatchEditSlots, FormExposed } from '../../types'\nimport { ULayout } from '../layout'\nimport BatchEditForm from './batch-edit-form.vue'\nimport BatchEditList from './batch-edit-list.vue'\nimport { BatchEditDIKey } from './di'\nimport { useEditState } from './use-edit-state'\nimport { useFeatures } from './use-features'\nimport { useHandlers } from './use-handlers'\nimport { useShortcutKey } from './use-shortcut-key'\n\ndefineOptions({ name: 'UBatchEdit' })\n\nconst props = withDefaults(defineProps<BatchEditProps>(), { cols: () => ['1fr', '420px'] })\n\nconst emit = defineEmits<BatchEditEmits>()\n\nconst slots = defineSlots<BatchEditSlots>()\n\nconst cls = bem('batch-edit')\n\nconst formRef = useTemplateRef<FormExposed>('form')\n\nconst { state, resetState, syncing } = useEditState({ props, formRef })\n\nconst { staticFeatures, dynamicFeatures } = useFeatures({ props })\n\nconst handlers = useHandlers({ props, emit, state, resetState, formRef })\n\n// 快捷键处理\nconst { handleFocusIn, handleFocusOut, handleKeydown, focused } = useShortcutKey({\n props,\n onSave: handlers.handleSave,\n onClose: handlers.handleClose,\n state\n})\n\nconst cols = computed(() => {\n return state.formVisible ? props.cols : undefined\n})\n\nprovide(BatchEditDIKey, {\n cls,\n props,\n emit,\n state,\n staticFeatures,\n dynamicFeatures,\n focused,\n syncing,\n ...handlers\n})\n</script>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAsCA,MAAM,QAAQ;EAEd,MAAM,OAAO;EAEb,MAAM,QAAQ,SAAA;EAEd,MAAM,MAAM,IAAI,YAAY;EAE5B,MAAM,UAAU,eAA4B,MAAM;EAElD,MAAM,EAAE,OAAO,YAAY,YAAY,aAAa;GAAE;GAAO;EAAQ,CAAC;EAEtE,MAAM,EAAE,gBAAgB,oBAAoB,YAAY,EAAE,MAAM,CAAC;EAEjE,MAAM,WAAW,YAAY;GAAE;GAAO;GAAM;GAAO;GAAY;EAAQ,CAAC;EAGxE,MAAM,EAAE,eAAe,gBAAgB,eAAe,YAAY,eAAe;GAC/E;GACA,QAAQ,SAAS;GACjB,SAAS,SAAS;GAClB;EACF,CAAC;EAED,MAAM,OAAO,eAAe;GAC1B,OAAO,MAAM,cAAc,MAAM,OAAO,KAAA;EAC1C,CAAC;EAED,QAAQ,gBAAgB;GACtB;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA,GAAG;EACL,CAAC;;GA3EC,OAAA,UAAA,GAAA,YAkBW,MAAA,WAAA,GAAA;IAjBR,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,CAAC;IACZ,MAAM,KAAA;IACP,MAAK;IACL,KAAI;IACJ,WAAA;IACA,UAAS;IACR,WAAS,MAAA,aAAA;IACT,YAAU,MAAA,cAAA;IACO,kBAAA,MAAA,aAAA;;IAElB,SAAA,cAAa;KAAb,mBAAA,QAAA;KACA,YAAgC,aAAA,EAAT,MAAK,CAAA;KAE5B,mBAAA,QAAA;KACA,YAEgB,aAAA,EAFD,KAAI,OAAM,GAAA;MACvB,SAAA,SADgC,WAAM,CACtC,WAAoC,KAAA,QAAA,QAAA,eAAA,mBAAV,MAAM,CAAA,CAAA,CAAA,CAAA"}
1
+ {"version":3,"file":"batch-edit.js","names":[],"sources":["../../../src/components/batch-edit/batch-edit.vue"],"sourcesContent":["<template>\n <u-layout\n :class=\"cls.b\"\n :cols=\"cols\"\n rows=\"minmax(0, 1fr) \"\n gap=\"8px\"\n resizable\n tabindex=\"-1\"\n @focusin=\"handleFocusIn\"\n @focusout=\"handleFocusOut\"\n @keydown.capture=\"handleKeydown\"\n >\n <!-- 编辑列表 -->\n <BatchEditList :slots=\"slots\" />\n\n <!-- 编辑表单 -->\n <BatchEditForm ref=\"form\" v-slot=\"scoped\">\n <slot name=\"form\" v-bind=\"scoped\" />\n </BatchEditForm>\n </u-layout>\n</template>\n\n<script lang=\"ts\" setup>\nimport { bem } from '@veltra/utils'\nimport { computed, provide, useTemplateRef } from 'vue'\n\nimport type { BatchEditEmits, BatchEditProps, BatchEditSlots, FormExposed } from '../../types'\nimport { ULayout } from '../layout'\nimport BatchEditForm from './batch-edit-form.vue'\nimport BatchEditList from './batch-edit-list.vue'\nimport { BatchEditDIKey } from './di'\nimport { useEditState } from './use-edit-state'\nimport { useFeatures } from './use-features'\nimport { useHandlers } from './use-handlers'\nimport { useShortcutKey } from './use-shortcut-key'\n\ndefineOptions({ name: 'UBatchEdit' })\n\nconst props = withDefaults(defineProps<BatchEditProps>(), { cols: () => ['1fr', '420px'] })\n\nconst emit = defineEmits<BatchEditEmits>()\n\nconst slots = defineSlots<BatchEditSlots>()\n\nconst cls = bem('batch-edit')\n\nconst formRef = useTemplateRef<FormExposed>('form')\n\nconst { state, resetState, syncing } = useEditState({ props, formRef })\n\nconst { staticFeatures, dynamicFeatures } = useFeatures({ props })\n\nconst handlers = useHandlers({ props, emit, state, resetState, formRef })\n\n// 快捷键处理\nconst { handleFocusIn, handleFocusOut, handleKeydown, focused } = useShortcutKey({\n props,\n onSave: handlers.handleSave,\n onClose: handlers.handleClose,\n state\n})\n\nconst cols = computed(() => {\n return state.formVisible ? props.cols : undefined\n})\n\nprovide(BatchEditDIKey, {\n cls,\n props,\n emit,\n state,\n staticFeatures,\n dynamicFeatures,\n focused,\n syncing,\n ...handlers\n})\n</script>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAsCA,MAAM,QAAQ;EAEd,MAAM,OAAO;EAEb,MAAM,QAAQ,SAAA;EAEd,MAAM,MAAM,IAAI,YAAY;EAE5B,MAAM,UAAU,eAA4B,MAAM;EAElD,MAAM,EAAE,OAAO,YAAY,YAAY,aAAa;GAAE;GAAO;EAAQ,CAAC;EAEtE,MAAM,EAAE,gBAAgB,oBAAoB,YAAY,EAAE,MAAM,CAAC;EAEjE,MAAM,WAAW,YAAY;GAAE;GAAO;GAAM;GAAO;GAAY;EAAQ,CAAC;EAGxE,MAAM,EAAE,eAAe,gBAAgB,eAAe,YAAY,eAAe;GAC/E;GACA,QAAQ,SAAS;GACjB,SAAS,SAAS;GAClB;EACF,CAAC;EAED,MAAM,OAAO,eAAe;GAC1B,OAAO,MAAM,cAAc,MAAM,OAAO,KAAA;EAC1C,CAAC;EAED,QAAQ,gBAAgB;GACtB;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA,GAAG;EACL,CAAC;;GA3EC,OAAA,UAAA,GAAA,YAkBW,MAAA,WAAA,GAAA;IAjBR,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,CAAC;IACZ,MAAM,KAAA;IACP,MAAK;IACL,KAAI;IACJ,WAAA;IACA,UAAS;IACR,WAAS,MAAA,aAAA;IACT,YAAU,MAAA,cAAA;IACO,kBAAA,MAAA,aAAA;;IAElB,SAAA,cAAa;KAAb,mBAAA,QAAA;KACA,YAAgC,aAAA,EAAT,MAAK,CAAA;KAE5B,mBAAA,QAAA;KACA,YAEgB,aAAA,EAFD,KAAI,OAAM,GAAA;MACvB,SAAA,SADgC,WAAM,CACtC,WAAoC,KAAA,QAAA,QAAA,eAAA,mBAAV,MAAM,CAAA,CAAA,CAAA,CAAA"}
@@ -65,7 +65,6 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
65
65
  return withDirectives((openBlock(), createElementBlock("button", {
66
66
  class: normalizeClass(classList.value),
67
67
  type: "button",
68
- "aria-label": "button",
69
68
  ref_key: "buttonRef",
70
69
  ref: buttonRef,
71
70
  onClick: handleClick
@@ -1 +1 @@
1
- {"version":3,"file":"button.js","names":[],"sources":["../../../src/components/button/button.vue"],"sourcesContent":["<template>\n <button\n :class=\"classList\"\n type=\"button\"\n aria-label=\"button\"\n ref=\"buttonRef\"\n v-ripple=\"ripple\"\n @click=\"handleClick\"\n >\n <!-- 加载图标 -->\n <u-icon v-if=\"loading\" :class=\"[bem.is('loading')]\" :size=\"iconSize\">\n <component :is=\"loadingIcon\" />\n </u-icon>\n\n <!-- 左侧图标 -->\n <u-icon v-if=\"!!icon && iconPosition === 'left' && !loading\" :size=\"iconSize\">\n <component :is=\"icon\" />\n </u-icon>\n\n <slot />\n\n <!-- 右侧图标 -->\n <u-icon v-if=\"!!icon && iconPosition === 'right'\" :size=\"iconSize\">\n <component :is=\"icon\" />\n </u-icon>\n </button>\n</template>\n\n<script lang=\"ts\" setup>\nimport { useFallbackProps } from '@veltra/compositions'\nimport { vRipple } from '@veltra/directives'\nimport { Loading } from '@veltra/icons'\nimport { bem } from '@veltra/utils'\nimport { computed, shallowRef } from 'vue'\n\nimport type { ButtonEmits, ButtonProps, _ButtonExposed, ComponentSize } from '../../types'\nimport { UIcon } from '../icon'\n\ndefineOptions({ name: 'UButton' })\n\nconst props = withDefaults(defineProps<ButtonProps>(), {\n iconPosition: 'left',\n loadingIcon: () => Loading,\n disabled: false,\n propagate: true\n})\n\nconst { size } = useFallbackProps([props], { size: 'default' as ComponentSize })\n\nconst emit = defineEmits<ButtonEmits>()\n\nconst cls = bem('button')\n\nconst classList = computed(() => {\n return [\n cls.b,\n cls.m(size.value),\n props.type && cls.m('color-' + props.type),\n bem.is('circle', props.circle),\n bem.is('disabled', props.disabled),\n bem.is('loading', props.loading),\n bem.is('plain', props.plain),\n bem.is('text', props.text)\n ]\n})\n\nconst ripple = computed(() => {\n if (props.disabled || props.loading || props.text) return false\n if (props.plain && props.type) {\n return bem.is(`ripple-${props.type}`)\n }\n return true\n})\n\nconst handleClick = (e: MouseEvent) => {\n if (props.disabled || props.loading) {\n e.stopPropagation()\n return\n }\n\n !props.propagate && e.stopPropagation()\n\n emit('click', e)\n}\n\nconst buttonRef = shallowRef<HTMLButtonElement>()\n\nconst exposed: _ButtonExposed = { el: buttonRef }\n\ndefineExpose(exposed)\n</script>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAwCA,MAAM,QAAQ;EAOd,MAAM,EAAE,SAAS,iBAAiB,CAAC,KAAK,GAAG,EAAE,MAAM,UAA2B,CAAC;EAE/E,MAAM,OAAO;EAEb,MAAM,MAAM,IAAI,QAAQ;EAExB,MAAM,YAAY,eAAe;GAC/B,OAAO;IACL,IAAI;IACJ,IAAI,EAAE,KAAK,KAAK;IAChB,MAAM,QAAQ,IAAI,EAAE,WAAW,MAAM,IAAI;IACzC,IAAI,GAAG,UAAU,MAAM,MAAM;IAC7B,IAAI,GAAG,YAAY,MAAM,QAAQ;IACjC,IAAI,GAAG,WAAW,MAAM,OAAO;IAC/B,IAAI,GAAG,SAAS,MAAM,KAAK;IAC3B,IAAI,GAAG,QAAQ,MAAM,IAAI;GAC3B;EACF,CAAC;EAED,MAAM,SAAS,eAAe;GAC5B,IAAI,MAAM,YAAY,MAAM,WAAW,MAAM,MAAM,OAAO;GAC1D,IAAI,MAAM,SAAS,MAAM,MACvB,OAAO,IAAI,GAAG,UAAU,MAAM,MAAM;GAEtC,OAAO;EACT,CAAC;EAED,MAAM,eAAe,MAAkB;GACrC,IAAI,MAAM,YAAY,MAAM,SAAS;IACnC,EAAE,gBAAgB;IAClB;GACF;GAEA,CAAC,MAAM,aAAa,EAAE,gBAAgB;GAEtC,KAAK,SAAS,CAAC;EACjB;EAEA,MAAM,YAAY,WAA8B;EAIhD,SAAa,EAFqB,IAAI,UAEzB,CAAO;;GAxFlB,OAAA,gBAAA,UAAA,GAAA,mBAwBS,UAAA;IAvBN,OAAK,eAAE,UAAA,KAAS;IACjB,MAAK;IACL,cAAW;IACP,SAAA;IAAJ,KAAI;IAEH,SAAO;;IAER,mBAAA,QAAA;IACc,QAAA,WAAd,UAAA,GAAA,YAES,MAAA,WAAA,GAAA;;KAFe,OAAK,eAAA,CAAG,MAAA,GAAA,CAAG,CAAC,GAAE,SAAA,CAAA,CAAA;KAAe,MAAM,QAAA;;KACzD,SAAA,cAA+B,EAA/B,UAAA,GAAA,YAA+B,wBAAf,QAAA,WAAW,CAAA,EAAA,CAAA;;;IAG7B,mBAAA,QAAA;IACgB,CAAA,CAAA,QAAA,QAAQ,QAAA,iBAAY,UAAA,CAAgB,QAAA,WAApD,UAAA,GAAA,YAES,MAAA,WAAA,GAAA;;KAFqD,MAAM,QAAA;;KAClE,SAAA,cAAwB,EAAxB,UAAA,GAAA,YAAwB,wBAAR,QAAA,IAAI,CAAA,EAAA,CAAA;;;IAGtB,WAAQ,KAAA,QAAA,SAAA;IAER,mBAAA,QAAA;IACgB,CAAA,CAAA,QAAA,QAAQ,QAAA,iBAAY,WAApC,UAAA,GAAA,YAES,MAAA,WAAA,GAAA;;KAF0C,MAAM,QAAA;;KACvD,SAAA,cAAwB,EAAxB,UAAA,GAAA,YAAwB,wBAAR,QAAA,IAAI,CAAA,EAAA,CAAA;;;GAjBZ,GAAA,CAAA,IAAA,CAAA,CAAA,MAAA,OAAA,GAAA,OAAA,KAAM,CAAA,CAAA"}
1
+ {"version":3,"file":"button.js","names":[],"sources":["../../../src/components/button/button.vue"],"sourcesContent":["<template>\n <button :class=\"classList\" type=\"button\" ref=\"buttonRef\" v-ripple=\"ripple\" @click=\"handleClick\">\n <!-- 加载图标 -->\n <u-icon v-if=\"loading\" :class=\"[bem.is('loading')]\" :size=\"iconSize\">\n <component :is=\"loadingIcon\" />\n </u-icon>\n\n <!-- 左侧图标 -->\n <u-icon v-if=\"!!icon && iconPosition === 'left' && !loading\" :size=\"iconSize\">\n <component :is=\"icon\" />\n </u-icon>\n\n <slot />\n\n <!-- 右侧图标 -->\n <u-icon v-if=\"!!icon && iconPosition === 'right'\" :size=\"iconSize\">\n <component :is=\"icon\" />\n </u-icon>\n </button>\n</template>\n\n<script lang=\"ts\" setup>\nimport { useFallbackProps } from '@veltra/compositions'\nimport { vRipple } from '@veltra/directives'\nimport { Loading } from '@veltra/icons'\nimport { bem } from '@veltra/utils'\nimport { computed, shallowRef } from 'vue'\n\nimport type { ButtonEmits, ButtonProps, _ButtonExposed, ComponentSize } from '../../types'\nimport { UIcon } from '../icon'\n\ndefineOptions({ name: 'UButton' })\n\nconst props = withDefaults(defineProps<ButtonProps>(), {\n iconPosition: 'left',\n loadingIcon: () => Loading,\n disabled: false,\n propagate: true\n})\n\nconst { size } = useFallbackProps([props], { size: 'default' as ComponentSize })\n\nconst emit = defineEmits<ButtonEmits>()\n\nconst cls = bem('button')\n\nconst classList = computed(() => {\n return [\n cls.b,\n cls.m(size.value),\n props.type && cls.m('color-' + props.type),\n bem.is('circle', props.circle),\n bem.is('disabled', props.disabled),\n bem.is('loading', props.loading),\n bem.is('plain', props.plain),\n bem.is('text', props.text)\n ]\n})\n\nconst ripple = computed(() => {\n if (props.disabled || props.loading || props.text) return false\n if (props.plain && props.type) {\n return bem.is(`ripple-${props.type}`)\n }\n return true\n})\n\nconst handleClick = (e: MouseEvent) => {\n if (props.disabled || props.loading) {\n e.stopPropagation()\n return\n }\n\n !props.propagate && e.stopPropagation()\n\n emit('click', e)\n}\n\nconst buttonRef = shallowRef<HTMLButtonElement>()\n\nconst exposed: _ButtonExposed = { el: buttonRef }\n\ndefineExpose(exposed)\n</script>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiCA,MAAM,QAAQ;EAOd,MAAM,EAAE,SAAS,iBAAiB,CAAC,KAAK,GAAG,EAAE,MAAM,UAA2B,CAAC;EAE/E,MAAM,OAAO;EAEb,MAAM,MAAM,IAAI,QAAQ;EAExB,MAAM,YAAY,eAAe;GAC/B,OAAO;IACL,IAAI;IACJ,IAAI,EAAE,KAAK,KAAK;IAChB,MAAM,QAAQ,IAAI,EAAE,WAAW,MAAM,IAAI;IACzC,IAAI,GAAG,UAAU,MAAM,MAAM;IAC7B,IAAI,GAAG,YAAY,MAAM,QAAQ;IACjC,IAAI,GAAG,WAAW,MAAM,OAAO;IAC/B,IAAI,GAAG,SAAS,MAAM,KAAK;IAC3B,IAAI,GAAG,QAAQ,MAAM,IAAI;GAC3B;EACF,CAAC;EAED,MAAM,SAAS,eAAe;GAC5B,IAAI,MAAM,YAAY,MAAM,WAAW,MAAM,MAAM,OAAO;GAC1D,IAAI,MAAM,SAAS,MAAM,MACvB,OAAO,IAAI,GAAG,UAAU,MAAM,MAAM;GAEtC,OAAO;EACT,CAAC;EAED,MAAM,eAAe,MAAkB;GACrC,IAAI,MAAM,YAAY,MAAM,SAAS;IACnC,EAAE,gBAAgB;IAClB;GACF;GAEA,CAAC,MAAM,aAAa,EAAE,gBAAgB;GAEtC,KAAK,SAAS,CAAC;EACjB;EAEA,MAAM,YAAY,WAA8B;EAIhD,SAAa,EAFqB,IAAI,UAEzB,CAAO;;GAjFlB,OAAA,gBAAA,UAAA,GAAA,mBAiBS,UAAA;IAjBA,OAAK,eAAE,UAAA,KAAS;IAAE,MAAK;IAAa,SAAA;IAAJ,KAAI;IAA+B,SAAO;;IACjF,mBAAA,QAAA;IACc,QAAA,WAAd,UAAA,GAAA,YAES,MAAA,WAAA,GAAA;;KAFe,OAAK,eAAA,CAAG,MAAA,GAAA,CAAG,CAAC,GAAE,SAAA,CAAA,CAAA;KAAe,MAAM,QAAA;;KACzD,SAAA,cAA+B,EAA/B,UAAA,GAAA,YAA+B,wBAAf,QAAA,WAAW,CAAA,EAAA,CAAA;;;IAG7B,mBAAA,QAAA;IACgB,CAAA,CAAA,QAAA,QAAQ,QAAA,iBAAY,UAAA,CAAgB,QAAA,WAApD,UAAA,GAAA,YAES,MAAA,WAAA,GAAA;;KAFqD,MAAM,QAAA;;KAClE,SAAA,cAAwB,EAAxB,UAAA,GAAA,YAAwB,wBAAR,QAAA,IAAI,CAAA,EAAA,CAAA;;;IAGtB,WAAQ,KAAA,QAAA,SAAA;IAER,mBAAA,QAAA;IACgB,CAAA,CAAA,QAAA,QAAQ,QAAA,iBAAY,WAApC,UAAA,GAAA,YAES,MAAA,WAAA,GAAA;;KAF0C,MAAM,QAAA;;KACvD,SAAA,cAAwB,EAAxB,UAAA,GAAA,YAAwB,wBAAR,QAAA,IAAI,CAAA,EAAA,CAAA;;;GAf2C,GAAA,CAAA,IAAA,CAAA,CAAA,MAAA,OAAA,GAAA,OAAA,KAAM,CAAA,CAAA"}
@@ -1,5 +1,5 @@
1
1
  import _sfc_main$1 from "../icon/icon.js";
2
- import { Teleport, Transition, computed, createBlock, createCommentVNode, createElementBlock, createVNode, defineComponent, mergeModels, mergeProps, normalizeClass, normalizeStyle, openBlock, renderSlot, shallowRef, unref, useModel, withCtx, withModifiers } from "vue";
2
+ import { Teleport, Transition, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createVNode, defineComponent, mergeModels, mergeProps, normalizeClass, normalizeStyle, openBlock, renderSlot, shallowRef, toDisplayString, unref, useModel, withCtx, withModifiers } from "vue";
3
3
  import { bem, zIndex } from "@veltra/utils";
4
4
  import { Close } from "@veltra/icons/normal";
5
5
  //#region src/components/drawer/drawer.vue
@@ -54,7 +54,8 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
54
54
  return openBlock(), createBlock(Teleport, { to: "body" }, [createVNode(Transition, {
55
55
  name: "fade",
56
56
  mode: "out-in",
57
- onEnter
57
+ onEnter,
58
+ onAfterLeave: _cache[1] || (_cache[1] = ($event) => emit("closed"))
58
59
  }, {
59
60
  default: withCtx(() => [overlayVisible.value ? (openBlock(), createElementBlock("div", {
60
61
  key: 0,
@@ -70,14 +71,21 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
70
71
  class: drawerClass.value,
71
72
  style: drawerStyle.value,
72
73
  onClick: _cache[0] || (_cache[0] = withModifiers(() => {}, ["stop"]))
73
- }), [__props.showClose ? (openBlock(), createElementBlock("span", {
74
- key: 0,
75
- class: normalizeClass(unref(cls).e("close")),
76
- onClick: close
77
- }, [createVNode(unref(_sfc_main$1), null, {
78
- default: withCtx(() => [createVNode(unref(Close))]),
79
- _: 1
80
- })], 2)) : createCommentVNode("v-if", true), renderSlot(_ctx.$slots, "default")], 16)) : createCommentVNode("v-if", true)]),
74
+ }), [
75
+ __props.title ? (openBlock(), createElementBlock("div", {
76
+ key: 0,
77
+ class: normalizeClass(unref(cls).e("header"))
78
+ }, [createElementVNode("span", { class: normalizeClass(unref(cls).e("title")) }, toDisplayString(__props.title), 3)], 2)) : createCommentVNode("v-if", true),
79
+ __props.showClose ? (openBlock(), createElementBlock("span", {
80
+ key: 1,
81
+ class: normalizeClass(unref(cls).e("close")),
82
+ onClick: close
83
+ }, [createVNode(unref(_sfc_main$1), null, {
84
+ default: withCtx(() => [createVNode(unref(Close))]),
85
+ _: 1
86
+ })], 2)) : createCommentVNode("v-if", true),
87
+ renderSlot(_ctx.$slots, "default")
88
+ ], 16)) : createCommentVNode("v-if", true)]),
81
89
  _: 3
82
90
  }, 8, ["name"])], 6)) : createCommentVNode("v-if", true)]),
83
91
  _: 3
@@ -1 +1 @@
1
- {"version":3,"file":"drawer.js","names":["$attrs"],"sources":["../../../src/components/drawer/drawer.vue"],"sourcesContent":["<template>\n <Teleport to=\"body\">\n <transition name=\"fade\" mode=\"out-in\" @enter=\"onEnter\">\n <div v-if=\"overlayVisible\" :class=\"overlayCls.b\" :style=\"{ zIndex: zIndex() }\" @click=\"close\">\n <transition :name=\"transitionName\" appear @after-leave=\"onAfterDrawerLeave\">\n <div\n v-bind=\"$attrs\"\n v-if=\"drawerVisible\"\n :class=\"drawerClass\"\n :style=\"drawerStyle\"\n @click.stop\n >\n <span :class=\"cls.e('close')\" @click=\"close\" v-if=\"showClose\">\n <u-icon><Close /></u-icon>\n </span>\n <slot />\n </div>\n </transition>\n </div>\n </transition>\n </Teleport>\n</template>\n\n<script lang=\"ts\" setup>\nimport { Close } from '@veltra/icons/normal'\nimport { bem, zIndex } from '@veltra/utils'\nimport { computed, shallowRef } from 'vue'\n\nimport type { DrawerProps, DrawerEmits } from '../../types'\nimport { UIcon } from '../icon'\n\ndefineOptions({ name: 'UDrawer', inheritAttrs: false })\n\nconst props = withDefaults(defineProps<DrawerProps>(), { direction: 'right', closable: true })\n\nconst emit = defineEmits<DrawerEmits>()\n\nconst cls = bem('drawer')\nconst overlayCls = bem('drawer-overlay')\n\nconst overlayVisible = defineModel<boolean>({ default: false })\n\nconst drawerVisible = shallowRef(false)\n\n// 根据方向计算过渡动画名称\nconst transitionName = computed(() => {\n return `drawer-slide-${props.direction}`\n})\n\n// 计算抽屉样式类\nconst drawerClass = computed(() => {\n return [cls.b, bem.is(props.direction)]\n})\n\n// 计算抽屉样式\nconst drawerStyle = computed(() => {\n const style: Record<string, string> = {}\n\n return style\n})\n\nconst onEnter = () => {\n drawerVisible.value = true\n}\n\nconst onAfterDrawerLeave = () => {\n overlayVisible.value = false\n}\n\n// 关闭抽屉\nconst close = () => {\n drawerVisible.value = false\n emit('close')\n}\n</script>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;EAiCA,MAAM,QAAQ;EAEd,MAAM,OAAO;EAEb,MAAM,MAAM,IAAI,QAAQ;EACxB,MAAM,aAAa,IAAI,gBAAgB;EAEvC,MAAM,iBAAiB,SAAoB,SAAA,YAAmB;EAE9D,MAAM,gBAAgB,WAAW,KAAK;EAGtC,MAAM,iBAAiB,eAAe;GACpC,OAAO,gBAAgB,MAAM;EAC/B,CAAC;EAGD,MAAM,cAAc,eAAe;GACjC,OAAO,CAAC,IAAI,GAAG,IAAI,GAAG,MAAM,SAAS,CAAC;EACxC,CAAC;EAGD,MAAM,cAAc,eAAe;GAGjC,OAAO,CAAA;EACT,CAAC;EAED,MAAM,gBAAgB;GACpB,cAAc,QAAQ;EACxB;EAEA,MAAM,2BAA2B;GAC/B,eAAe,QAAQ;EACzB;EAGA,MAAM,cAAc;GAClB,cAAc,QAAQ;GACtB,KAAK,OAAO;EACd;;GAxEE,OAAA,UAAA,GAAA,YAmBW,UAAA,EAnBD,IAAG,OAAM,GAAA,CACjB,YAiBa,YAAA;IAjBD,MAAK;IAAO,MAAK;IAAiB;;IAC5C,SAAA,cAeM,CAfK,eAAA,SAAX,UAAA,GAAA,mBAeM,OAAA;;KAfsB,OAAK,eAAE,MAAA,UAAA,CAAU,CAAC,CAAC;KAAG,OAAK,eAAA,EAAA,QAAY,MAAA,MAAA,CAAM,CAAA,EAAA,CAAA;KAAO,SAAO;IACrF,GAAA,CAAA,YAaa,YAAA;KAbA,MAAM,eAAA;KAAgB,QAAA;KAAQ,cAAa;;KACtD,SAAA,cAWM,CATE,cAAA,SAFR,UAAA,GAAA,mBAWM,OAXN,WAWM,EAAA,KAAA,EAAA,GAVIA,KAAAA,QAAM;MAEb,OAAO,YAAA;MACP,OAAO,YAAA;MACP,SAAK,OAAA,OAAA,OAAA,KAAA,oBAAN,CAAA,GAAW,CAAA,MAAA,CAAA;KAEwC,CAAA,GAAA,CAAA,QAAA,aAAnD,UAAA,GAAA,mBAEO,QAAA;;MAFA,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,EAAC,OAAA,CAAA;MAAY,SAAO;KACpC,GAAA,CAAA,YAA0B,MAAA,WAAA,GAAA,MAAA;MAAlB,SAAA,cAAS,CAAT,YAAS,MAAA,KAAA,CAAA,CAAA,CAAA;;KAEnB,CAAA,CAAA,GAAA,CAAA,KAAA,mBAAA,QAAA,IAAA,GAAA,WAAQ,KAAA,QAAA,SAAA,CAAA,GAAA,EAAA,KAAA,mBAAA,QAAA,IAAA,CAAA,CAAA"}
1
+ {"version":3,"file":"drawer.js","names":["$attrs"],"sources":["../../../src/components/drawer/drawer.vue"],"sourcesContent":["<template>\n <Teleport to=\"body\">\n <transition name=\"fade\" mode=\"out-in\" @enter=\"onEnter\" @after-leave=\"emit('closed')\">\n <div v-if=\"overlayVisible\" :class=\"overlayCls.b\" :style=\"{ zIndex: zIndex() }\" @click=\"close\">\n <transition :name=\"transitionName\" appear @after-leave=\"onAfterDrawerLeave\">\n <div\n v-bind=\"$attrs\"\n v-if=\"drawerVisible\"\n :class=\"drawerClass\"\n :style=\"drawerStyle\"\n @click.stop\n >\n <div v-if=\"title\" :class=\"cls.e('header')\">\n <span :class=\"cls.e('title')\">{{ title }}</span>\n </div>\n <span :class=\"cls.e('close')\" @click=\"close\" v-if=\"showClose\">\n <u-icon><Close /></u-icon>\n </span>\n <slot />\n </div>\n </transition>\n </div>\n </transition>\n </Teleport>\n</template>\n\n<script lang=\"ts\" setup>\nimport { Close } from '@veltra/icons/normal'\nimport { bem, zIndex } from '@veltra/utils'\nimport { computed, shallowRef } from 'vue'\n\nimport type { DrawerProps, DrawerEmits } from '../../types'\nimport { UIcon } from '../icon'\n\ndefineOptions({ name: 'UDrawer', inheritAttrs: false })\n\nconst props = withDefaults(defineProps<DrawerProps>(), { direction: 'right' })\n\nconst emit = defineEmits<DrawerEmits>()\n\nconst cls = bem('drawer')\nconst overlayCls = bem('drawer-overlay')\n\nconst overlayVisible = defineModel<boolean>({ default: false })\n\nconst drawerVisible = shallowRef(false)\n\n// 根据方向计算过渡动画名称\nconst transitionName = computed(() => {\n return `drawer-slide-${props.direction}`\n})\n\n// 计算抽屉样式类\nconst drawerClass = computed(() => {\n return [cls.b, bem.is(props.direction)]\n})\n\n// 计算抽屉样式\nconst drawerStyle = computed(() => {\n const style: Record<string, string> = {}\n\n return style\n})\n\nconst onEnter = () => {\n drawerVisible.value = true\n}\n\nconst onAfterDrawerLeave = () => {\n overlayVisible.value = false\n}\n\n// 关闭抽屉\nconst close = () => {\n drawerVisible.value = false\n emit('close')\n}\n</script>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;EAoCA,MAAM,QAAQ;EAEd,MAAM,OAAO;EAEb,MAAM,MAAM,IAAI,QAAQ;EACxB,MAAM,aAAa,IAAI,gBAAgB;EAEvC,MAAM,iBAAiB,SAAoB,SAAA,YAAmB;EAE9D,MAAM,gBAAgB,WAAW,KAAK;EAGtC,MAAM,iBAAiB,eAAe;GACpC,OAAO,gBAAgB,MAAM;EAC/B,CAAC;EAGD,MAAM,cAAc,eAAe;GACjC,OAAO,CAAC,IAAI,GAAG,IAAI,GAAG,MAAM,SAAS,CAAC;EACxC,CAAC;EAGD,MAAM,cAAc,eAAe;GAGjC,OAAO,CAAA;EACT,CAAC;EAED,MAAM,gBAAgB;GACpB,cAAc,QAAQ;EACxB;EAEA,MAAM,2BAA2B;GAC/B,eAAe,QAAQ;EACzB;EAGA,MAAM,cAAc;GAClB,cAAc,QAAQ;GACtB,KAAK,OAAO;EACd;;GA3EE,OAAA,UAAA,GAAA,YAsBW,UAAA,EAtBD,IAAG,OAAM,GAAA,CACjB,YAoBa,YAAA;IApBD,MAAK;IAAO,MAAK;IAAiB;IAAU,cAAW,OAAA,OAAA,OAAA,MAAA,WAAE,KAAI,QAAA;;IACvE,SAAA,cAkBM,CAlBK,eAAA,SAAX,UAAA,GAAA,mBAkBM,OAAA;;KAlBsB,OAAK,eAAE,MAAA,UAAA,CAAU,CAAC,CAAC;KAAG,OAAK,eAAA,EAAA,QAAY,MAAA,MAAA,CAAM,CAAA,EAAA,CAAA;KAAO,SAAO;IACrF,GAAA,CAAA,YAgBa,YAAA;KAhBA,MAAM,eAAA;KAAgB,QAAA;KAAQ,cAAa;;KACtD,SAAA,cAcM,CAZE,cAAA,SAFR,UAAA,GAAA,mBAcM,OAdN,WAcM,EAAA,KAAA,EAAA,GAbIA,KAAAA,QAAM;MAEb,OAAO,YAAA;MACP,OAAO,YAAA;MACP,SAAK,OAAA,OAAA,OAAA,KAAA,oBAAN,CAAA,GAAW,CAAA,MAAA,CAAA;;MAEA,QAAA,SAAX,UAAA,GAAA,mBAEM,OAAA;;OAFa,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,EAAC,QAAA,CAAA;MAC7B,GAAA,CAAA,mBAAgD,QAAA,EAAzC,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,EAAC,OAAA,CAAA,EAAc,GAAA,gBAAA,QAAA,KAAK,GAAA,CAAA,CAAA,GAAA,CAAA,KAAA,mBAAA,QAAA,IAAA;MAEW,QAAA,aAAnD,UAAA,GAAA,mBAEO,QAAA;;OAFA,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,EAAC,OAAA,CAAA;OAAY,SAAO;MACpC,GAAA,CAAA,YAA0B,MAAA,WAAA,GAAA,MAAA;OAAlB,SAAA,cAAS,CAAT,YAAS,MAAA,KAAA,CAAA,CAAA,CAAA;;;MAEnB,WAAQ,KAAA,QAAA,SAAA"}
@@ -34,6 +34,21 @@
34
34
  align-items: center;
35
35
  justify-content: center;
36
36
  }
37
+ .u-drawer__header {
38
+ height: 48px;
39
+ flex-shrink: 0;
40
+ padding: 0 var(--u-gap-default);
41
+ font-size: var(--u-font-size-title-default);
42
+ border-bottom: var(--u-border);
43
+ display: flex;
44
+ justify-content: flex-start;
45
+ align-items: center;
46
+ flex-wrap: nowrap;
47
+ }
48
+ .u-drawer__title {
49
+ font-weight: 600;
50
+ line-height: 1em;
51
+ }
37
52
  .u-drawer.is-right {
38
53
  top: 4px;
39
54
  bottom: 4px;
@@ -1 +1 @@
1
- {"version":3,"file":"form.js","names":[],"sources":["../../../src/components/form/form.vue"],"sourcesContent":["<template>\n <u-grid\n tag=\"form\"\n ref=\"grid\"\n @submit.prevent\n gap=\"0 12px\"\n :cols=\"cols || breakpointCols\"\n :class=\"[cls.b, bem.is('readonly', readonly)]\"\n >\n <template\n v-for=\"{ node, isFormItem, formItemProps, field, modelValue } of getSlotsNodes()\"\n :key=\"node.key\"\n >\n <u-form-item v-if=\"!isFormItem && field\" v-bind=\"formItemProps\">\n <component\n :is=\"node\"\n :model-value=\"modelValue ?? o(model ?? {}).get(field)\"\n @update:model-value=\"handleUpdateValue(field, $event)\"\n />\n <div v-if=\"shouldShowModified(field)\" :class=\"cls.e('data-before')\">\n <span :class=\"cls.e('changed-tag')\">{{ modifiedLabel }}</span>\n <component :is=\"node\" readonly :model-value=\"getBaselineFieldValue(field)\" />\n </div>\n </u-form-item>\n\n <component v-else :is=\"node\" />\n </template>\n </u-grid>\n</template>\n\n<script lang=\"tsx\" setup>\nimport { o } from '@cat-kit/core'\nimport { bem } from '@veltra/utils'\nimport { provideFormContext } from '@veltra/utils'\nimport { nextTick, toRef, useTemplateRef } from 'vue'\n\nimport type { BreakCols, FormProps, _FormExposed, FormEmits } from '../../types'\nimport { UFormItem } from '../form-item'\nimport { UGrid } from '../grid'\nimport { isFieldModified } from './is-field-modified'\nimport { useFormFields } from './use-form-fields'\nimport { useNodeInterceptor } from './use-node-interceptor'\n\ndefineOptions({ name: 'UForm' })\n\nconst props = withDefaults(defineProps<FormProps>(), { modifiedLabel: '变更前:' })\n\nconst emit = defineEmits<FormEmits>()\n\ndefineSlots<{ default(props?: { data: Record<string, any> | undefined }): any }>()\n\nconst cls = bem('form')\nconst formItemCls = bem('form-item')\nconst gridRef = useTemplateRef('grid')\n\nconst breakpointCols: BreakCols = { xs: 1, md: 2, lg: 3, xl: 4, default: 4 }\n\nconst {\n validate: runValidate,\n clearValidate,\n reset,\n registerField,\n unregisterField,\n shouldValidate,\n getBaselineModel\n} = useFormFields({ props })\n\nasync function validate(keys?: string[]) {\n const valid = await runValidate(keys)\n if (!valid) {\n await nextTick()\n\n gridRef.value?.el\n ?.querySelector(`.${formItemCls.e('error-text')}`)\n ?.scrollIntoView({ block: 'center' })\n }\n return valid\n}\n\nfunction handleFieldUpdate(field: string, value: any) {\n emit('field:update', field, value)\n}\n\nfunction handleFieldChange(field: string, ...args: any[]) {\n emit('field:change', field, ...args)\n}\n\nprovideFormContext({\n formProps: props,\n registerField,\n unregisterField,\n validateFields: validate,\n shouldValidate,\n handleFieldUpdate,\n handleFieldChange\n})\n\nconst { getSlotsNodes } = useNodeInterceptor()\n\nfunction handleUpdateValue(field: string, value: any) {\n if (!props.model) return\n o(props.model).set(field, value)\n}\n\nfunction getBaselineFieldValue(field: string) {\n return o(getBaselineModel() ?? {}).get(field)\n}\n\nfunction shouldShowModified(field: string) {\n if (!props.showModified) return false\n const baseline = getBaselineModel()\n if (!baseline || !props.model) return false\n const current = o(props.model).get(field)\n const initial = o(baseline).get(field)\n return isFieldModified(current, initial)\n}\n\ndefineExpose<_FormExposed>({ el: toRef(() => gridRef.value?.el), validate, clearValidate, reset })\n</script>\n"],"mappings":""}
1
+ {"version":3,"file":"form.js","names":[],"sources":["../../../src/components/form/form.vue"],"sourcesContent":["<template>\n <u-grid\n tag=\"form\"\n ref=\"grid\"\n @submit.prevent\n gap=\"0 12px\"\n :cols=\"cols || breakpointCols\"\n :class=\"[cls.b, bem.is('readonly', readonly)]\"\n >\n <template\n v-for=\"{ node, isFormItem, formItemProps, field, modelValue, renderKey } of getSlotsNodes()\"\n :key=\"renderKey\"\n >\n <u-form-item v-if=\"!isFormItem && field\" v-bind=\"formItemProps\">\n <component\n :is=\"node\"\n :model-value=\"modelValue ?? o(model ?? {}).get(field)\"\n @update:model-value=\"handleUpdateValue(field, $event)\"\n />\n <div v-if=\"shouldShowModified(field)\" :class=\"cls.e('data-before')\">\n <span :class=\"cls.e('changed-tag')\">{{ modifiedLabel }}</span>\n <component :is=\"createModifiedPreview(node, field)\" />\n </div>\n </u-form-item>\n\n <component v-else :is=\"node\" />\n </template>\n </u-grid>\n</template>\n\n<script lang=\"tsx\" setup>\nimport { o } from '@cat-kit/core'\nimport { bem } from '@veltra/utils'\nimport { provideFormContext } from '@veltra/utils'\nimport { nextTick, toRef, useTemplateRef, type VNode } from 'vue'\n\nimport type { BreakCols, FormProps, _FormExposed, FormEmits } from '../../types'\nimport { UFormItem } from '../form-item'\nimport { UGrid } from '../grid'\nimport { isFieldModified } from './is-field-modified'\nimport { useFormFields } from './use-form-fields'\nimport { forkUnmountedVNode, useNodeInterceptor } from './use-node-interceptor'\n\ndefineOptions({ name: 'UForm' })\n\nconst props = withDefaults(defineProps<FormProps>(), { modifiedLabel: '变更前:' })\n\nconst emit = defineEmits<FormEmits>()\n\ndefineSlots<{ default(props?: { data: Record<string, any> | undefined }): any }>()\n\nconst cls = bem('form')\nconst formItemCls = bem('form-item')\nconst gridRef = useTemplateRef('grid')\n\nconst breakpointCols: BreakCols = { xs: 1, md: 2, lg: 3, xl: 4, default: 4 }\n\nconst {\n validate: runValidate,\n clearValidate,\n reset,\n registerField,\n unregisterField,\n shouldValidate,\n getBaselineModel\n} = useFormFields({ props })\n\nasync function validate(keys?: string[]) {\n const valid = await runValidate(keys)\n if (!valid) {\n await nextTick()\n\n gridRef.value?.el\n ?.querySelector(`.${formItemCls.e('error-text')}`)\n ?.scrollIntoView({ block: 'center' })\n }\n return valid\n}\n\nfunction handleFieldUpdate(field: string, value: any) {\n emit('field:update', field, value)\n}\n\nprovideFormContext({\n formProps: props,\n registerField,\n unregisterField,\n validateFields: validate,\n shouldValidate,\n handleFieldUpdate\n})\n\nconst { getSlotsNodes } = useNodeInterceptor()\n\nfunction handleUpdateValue(field: string, value: any) {\n if (!props.model) return\n o(props.model).set(field, value)\n}\n\nfunction getBaselineFieldValue(field: string) {\n return o(getBaselineModel() ?? {}).get(field)\n}\n\nfunction createModifiedPreview(node: VNode, field: string) {\n return forkUnmountedVNode(node, { readonly: true, modelValue: getBaselineFieldValue(field) })\n}\n\nfunction shouldShowModified(field: string) {\n if (!props.showModified) return false\n const baseline = getBaselineModel()\n if (!baseline || !props.model) return false\n const current = o(props.model).get(field)\n const initial = o(baseline).get(field)\n return isFieldModified(current, initial)\n}\n\ndefineExpose<_FormExposed>({ el: toRef(() => gridRef.value?.el), validate, clearValidate, reset })\n</script>\n"],"mappings":""}
@@ -2,7 +2,7 @@ import _sfc_main from "../grid/grid.js";
2
2
  import form_item_default from "../form-item/form-item.js";
3
3
  import { isFieldModified } from "./is-field-modified.js";
4
4
  import { useFormFields } from "./use-form-fields.js";
5
- import { useNodeInterceptor } from "./use-node-interceptor.js";
5
+ import { forkUnmountedVNode, useNodeInterceptor } from "./use-node-interceptor.js";
6
6
  import { Fragment, createBlock, createCommentVNode, createElementBlock, createElementVNode, defineComponent, mergeProps, nextTick, normalizeClass, openBlock, renderList, resolveDynamicComponent, toDisplayString, toRef, unref, useTemplateRef, withCtx, withModifiers } from "vue";
7
7
  import { bem, provideFormContext } from "@veltra/utils";
8
8
  import { o } from "@cat-kit/core";
@@ -23,7 +23,7 @@ var form_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineCompo
23
23
  disabled: { type: Boolean },
24
24
  size: {}
25
25
  },
26
- emits: ["field:change", "field:update"],
26
+ emits: ["field:update"],
27
27
  setup(__props, { expose: __expose, emit: __emit }) {
28
28
  const props = __props;
29
29
  const emit = __emit;
@@ -49,17 +49,13 @@ var form_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineCompo
49
49
  function handleFieldUpdate(field, value) {
50
50
  emit("field:update", field, value);
51
51
  }
52
- function handleFieldChange(field, ...args) {
53
- emit("field:change", field, ...args);
54
- }
55
52
  provideFormContext({
56
53
  formProps: props,
57
54
  registerField,
58
55
  unregisterField,
59
56
  validateFields: validate,
60
57
  shouldValidate,
61
- handleFieldUpdate,
62
- handleFieldChange
58
+ handleFieldUpdate
63
59
  });
64
60
  const { getSlotsNodes } = useNodeInterceptor();
65
61
  function handleUpdateValue(field, value) {
@@ -69,6 +65,12 @@ var form_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineCompo
69
65
  function getBaselineFieldValue(field) {
70
66
  return o(getBaselineModel() ?? {}).get(field);
71
67
  }
68
+ function createModifiedPreview(node, field) {
69
+ return forkUnmountedVNode(node, {
70
+ readonly: true,
71
+ modelValue: getBaselineFieldValue(field)
72
+ });
73
+ }
72
74
  function shouldShowModified(field) {
73
75
  if (!props.showModified) return false;
74
76
  const baseline = getBaselineModel();
@@ -92,8 +94,8 @@ var form_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineCompo
92
94
  cols: __props.cols || breakpointCols,
93
95
  class: normalizeClass([unref(cls).b, unref(bem).is("readonly", __props.readonly)])
94
96
  }, {
95
- default: withCtx(() => [(openBlock(true), createElementBlock(Fragment, null, renderList(unref(getSlotsNodes)(), ({ node, isFormItem, formItemProps, field, modelValue }) => {
96
- return openBlock(), createElementBlock(Fragment, { key: node.key }, [!isFormItem && field ? (openBlock(), createBlock(unref(form_item_default), mergeProps({
97
+ default: withCtx(() => [(openBlock(true), createElementBlock(Fragment, null, renderList(unref(getSlotsNodes)(), ({ node, isFormItem, formItemProps, field, modelValue, renderKey }) => {
98
+ return openBlock(), createElementBlock(Fragment, { key: renderKey }, [!isFormItem && field ? (openBlock(), createBlock(unref(form_item_default), mergeProps({
97
99
  key: 0,
98
100
  ref_for: true
99
101
  }, formItemProps), {
@@ -103,10 +105,7 @@ var form_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineCompo
103
105
  }, null, 8, ["model-value", "onUpdate:modelValue"])), shouldShowModified(field) ? (openBlock(), createElementBlock("div", {
104
106
  key: 0,
105
107
  class: normalizeClass(unref(cls).e("data-before"))
106
- }, [createElementVNode("span", { class: normalizeClass(unref(cls).e("changed-tag")) }, toDisplayString(__props.modifiedLabel), 3), (openBlock(), createBlock(resolveDynamicComponent(node), {
107
- readonly: "",
108
- "model-value": getBaselineFieldValue(field)
109
- }, null, 8, ["model-value"]))], 2)) : createCommentVNode("v-if", true)]),
108
+ }, [createElementVNode("span", { class: normalizeClass(unref(cls).e("changed-tag")) }, toDisplayString(__props.modifiedLabel), 3), (openBlock(), createBlock(resolveDynamicComponent(createModifiedPreview(node, field))))], 2)) : createCommentVNode("v-if", true)]),
110
109
  _: 2
111
110
  }, 1040)) : (openBlock(), createBlock(resolveDynamicComponent(node), { key: 1 }))], 64);
112
111
  }), 128))]),
@@ -1 +1 @@
1
- {"version":3,"file":"form.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/form/form.vue"],"sourcesContent":["<template>\n <u-grid\n tag=\"form\"\n ref=\"grid\"\n @submit.prevent\n gap=\"0 12px\"\n :cols=\"cols || breakpointCols\"\n :class=\"[cls.b, bem.is('readonly', readonly)]\"\n >\n <template\n v-for=\"{ node, isFormItem, formItemProps, field, modelValue } of getSlotsNodes()\"\n :key=\"node.key\"\n >\n <u-form-item v-if=\"!isFormItem && field\" v-bind=\"formItemProps\">\n <component\n :is=\"node\"\n :model-value=\"modelValue ?? o(model ?? {}).get(field)\"\n @update:model-value=\"handleUpdateValue(field, $event)\"\n />\n <div v-if=\"shouldShowModified(field)\" :class=\"cls.e('data-before')\">\n <span :class=\"cls.e('changed-tag')\">{{ modifiedLabel }}</span>\n <component :is=\"node\" readonly :model-value=\"getBaselineFieldValue(field)\" />\n </div>\n </u-form-item>\n\n <component v-else :is=\"node\" />\n </template>\n </u-grid>\n</template>\n\n<script lang=\"tsx\" setup>\nimport { o } from '@cat-kit/core'\nimport { bem } from '@veltra/utils'\nimport { provideFormContext } from '@veltra/utils'\nimport { nextTick, toRef, useTemplateRef } from 'vue'\n\nimport type { BreakCols, FormProps, _FormExposed, FormEmits } from '../../types'\nimport { UFormItem } from '../form-item'\nimport { UGrid } from '../grid'\nimport { isFieldModified } from './is-field-modified'\nimport { useFormFields } from './use-form-fields'\nimport { useNodeInterceptor } from './use-node-interceptor'\n\ndefineOptions({ name: 'UForm' })\n\nconst props = withDefaults(defineProps<FormProps>(), { modifiedLabel: '变更前:' })\n\nconst emit = defineEmits<FormEmits>()\n\ndefineSlots<{ default(props?: { data: Record<string, any> | undefined }): any }>()\n\nconst cls = bem('form')\nconst formItemCls = bem('form-item')\nconst gridRef = useTemplateRef('grid')\n\nconst breakpointCols: BreakCols = { xs: 1, md: 2, lg: 3, xl: 4, default: 4 }\n\nconst {\n validate: runValidate,\n clearValidate,\n reset,\n registerField,\n unregisterField,\n shouldValidate,\n getBaselineModel\n} = useFormFields({ props })\n\nasync function validate(keys?: string[]) {\n const valid = await runValidate(keys)\n if (!valid) {\n await nextTick()\n\n gridRef.value?.el\n ?.querySelector(`.${formItemCls.e('error-text')}`)\n ?.scrollIntoView({ block: 'center' })\n }\n return valid\n}\n\nfunction handleFieldUpdate(field: string, value: any) {\n emit('field:update', field, value)\n}\n\nfunction handleFieldChange(field: string, ...args: any[]) {\n emit('field:change', field, ...args)\n}\n\nprovideFormContext({\n formProps: props,\n registerField,\n unregisterField,\n validateFields: validate,\n shouldValidate,\n handleFieldUpdate,\n handleFieldChange\n})\n\nconst { getSlotsNodes } = useNodeInterceptor()\n\nfunction handleUpdateValue(field: string, value: any) {\n if (!props.model) return\n o(props.model).set(field, value)\n}\n\nfunction getBaselineFieldValue(field: string) {\n return o(getBaselineModel() ?? {}).get(field)\n}\n\nfunction shouldShowModified(field: string) {\n if (!props.showModified) return false\n const baseline = getBaselineModel()\n if (!baseline || !props.model) return false\n const current = o(props.model).get(field)\n const initial = o(baseline).get(field)\n return isFieldModified(current, initial)\n}\n\ndefineExpose<_FormExposed>({ el: toRef(() => gridRef.value?.el), validate, clearValidate, reset })\n</script>\n"],"mappings":"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"}
1
+ {"version":3,"file":"form.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/form/form.vue"],"sourcesContent":["<template>\n <u-grid\n tag=\"form\"\n ref=\"grid\"\n @submit.prevent\n gap=\"0 12px\"\n :cols=\"cols || breakpointCols\"\n :class=\"[cls.b, bem.is('readonly', readonly)]\"\n >\n <template\n v-for=\"{ node, isFormItem, formItemProps, field, modelValue, renderKey } of getSlotsNodes()\"\n :key=\"renderKey\"\n >\n <u-form-item v-if=\"!isFormItem && field\" v-bind=\"formItemProps\">\n <component\n :is=\"node\"\n :model-value=\"modelValue ?? o(model ?? {}).get(field)\"\n @update:model-value=\"handleUpdateValue(field, $event)\"\n />\n <div v-if=\"shouldShowModified(field)\" :class=\"cls.e('data-before')\">\n <span :class=\"cls.e('changed-tag')\">{{ modifiedLabel }}</span>\n <component :is=\"createModifiedPreview(node, field)\" />\n </div>\n </u-form-item>\n\n <component v-else :is=\"node\" />\n </template>\n </u-grid>\n</template>\n\n<script lang=\"tsx\" setup>\nimport { o } from '@cat-kit/core'\nimport { bem } from '@veltra/utils'\nimport { provideFormContext } from '@veltra/utils'\nimport { nextTick, toRef, useTemplateRef, type VNode } from 'vue'\n\nimport type { BreakCols, FormProps, _FormExposed, FormEmits } from '../../types'\nimport { UFormItem } from '../form-item'\nimport { UGrid } from '../grid'\nimport { isFieldModified } from './is-field-modified'\nimport { useFormFields } from './use-form-fields'\nimport { forkUnmountedVNode, useNodeInterceptor } from './use-node-interceptor'\n\ndefineOptions({ name: 'UForm' })\n\nconst props = withDefaults(defineProps<FormProps>(), { modifiedLabel: '变更前:' })\n\nconst emit = defineEmits<FormEmits>()\n\ndefineSlots<{ default(props?: { data: Record<string, any> | undefined }): any }>()\n\nconst cls = bem('form')\nconst formItemCls = bem('form-item')\nconst gridRef = useTemplateRef('grid')\n\nconst breakpointCols: BreakCols = { xs: 1, md: 2, lg: 3, xl: 4, default: 4 }\n\nconst {\n validate: runValidate,\n clearValidate,\n reset,\n registerField,\n unregisterField,\n shouldValidate,\n getBaselineModel\n} = useFormFields({ props })\n\nasync function validate(keys?: string[]) {\n const valid = await runValidate(keys)\n if (!valid) {\n await nextTick()\n\n gridRef.value?.el\n ?.querySelector(`.${formItemCls.e('error-text')}`)\n ?.scrollIntoView({ block: 'center' })\n }\n return valid\n}\n\nfunction handleFieldUpdate(field: string, value: any) {\n emit('field:update', field, value)\n}\n\nprovideFormContext({\n formProps: props,\n registerField,\n unregisterField,\n validateFields: validate,\n shouldValidate,\n handleFieldUpdate\n})\n\nconst { getSlotsNodes } = useNodeInterceptor()\n\nfunction handleUpdateValue(field: string, value: any) {\n if (!props.model) return\n o(props.model).set(field, value)\n}\n\nfunction getBaselineFieldValue(field: string) {\n return o(getBaselineModel() ?? {}).get(field)\n}\n\nfunction createModifiedPreview(node: VNode, field: string) {\n return forkUnmountedVNode(node, { readonly: true, modelValue: getBaselineFieldValue(field) })\n}\n\nfunction shouldShowModified(field: string) {\n if (!props.showModified) return false\n const baseline = getBaselineModel()\n if (!baseline || !props.model) return false\n const current = o(props.model).get(field)\n const initial = o(baseline).get(field)\n return isFieldModified(current, initial)\n}\n\ndefineExpose<_FormExposed>({ el: toRef(() => gridRef.value?.el), validate, clearValidate, reset })\n</script>\n"],"mappings":"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"}
@@ -1,7 +1,25 @@
1
- import { useSlots } from "vue";
1
+ import { cloneVNode, useSlots } from "vue";
2
2
  import { extractNormalVNodes } from "@veltra/utils";
3
3
  import { o } from "@cat-kit/core";
4
4
  //#region src/components/form/use-node-interceptor.ts
5
+ function getVNodeTypeName(node) {
6
+ const type = node.type;
7
+ if (typeof type === "string") return type;
8
+ if (typeof type === "object" && type) return type.name || type.__name || "";
9
+ return "";
10
+ }
11
+ /**
12
+ * 从源 vnode 派生一份未挂载副本。
13
+ * Vue 的 cloneVNode 会拷贝 el/component,同一源 vnode 渲两次会把实例从编辑控件抢走。
14
+ */
15
+ function forkUnmountedVNode(node, extra) {
16
+ const forked = extra ? cloneVNode(node, extra) : cloneVNode(node);
17
+ forked.el = null;
18
+ forked.component = null;
19
+ forked.anchor = null;
20
+ forked.suspense = null;
21
+ return forked;
22
+ }
5
23
  /**
6
24
  * 虚拟node拦截
7
25
  * @returns
@@ -13,6 +31,7 @@ function useNodeInterceptor() {
13
31
  if (!nodes?.length) return null;
14
32
  const flattedNodes = extractNormalVNodes(nodes);
15
33
  const results = [];
34
+ const seen = /* @__PURE__ */ new Map();
16
35
  let i = 0;
17
36
  while (i < flattedNodes.length) {
18
37
  const node = flattedNodes[i];
@@ -28,12 +47,21 @@ function useNodeInterceptor() {
28
47
  "readonly",
29
48
  "field"
30
49
  ]);
50
+ let renderKey;
51
+ if (node.key != null) renderKey = node.key;
52
+ else {
53
+ const base = `${getVNodeTypeName(node)}:${field ?? ""}`;
54
+ const n = seen.get(base) ?? 0;
55
+ seen.set(base, n + 1);
56
+ renderKey = n === 0 ? `uform:${base}` : `uform:${base}#${n}`;
57
+ }
31
58
  results.push({
32
59
  isFormItem,
33
60
  formItemProps,
34
61
  node,
35
62
  field,
36
- modelValue: props?.["model-value"] ?? props?.modelValue
63
+ modelValue: props?.["model-value"] ?? props?.modelValue,
64
+ renderKey
37
65
  });
38
66
  }
39
67
  return results;
@@ -41,6 +69,6 @@ function useNodeInterceptor() {
41
69
  return { getSlotsNodes };
42
70
  }
43
71
  //#endregion
44
- export { useNodeInterceptor };
72
+ export { forkUnmountedVNode, useNodeInterceptor };
45
73
 
46
74
  //# sourceMappingURL=use-node-interceptor.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-node-interceptor.js","names":[],"sources":["../../../src/components/form/use-node-interceptor.ts"],"sourcesContent":["import { o } from '@cat-kit/core'\nimport { extractNormalVNodes } from '@veltra/utils'\nimport { useSlots, type VNode } from 'vue'\n\nexport type SlotRenderItem = {\n isFormItem: boolean\n formItemProps?: Record<string, any>\n node: VNode\n field?: string\n modelValue?: any\n}\n\n/**\n * 虚拟node拦截\n * @returns\n */\nexport function useNodeInterceptor(): { getSlotsNodes: () => SlotRenderItem[] | null } {\n const slots = useSlots()\n\n function getSlotsNodes() {\n const nodes = slots.default?.()\n if (!nodes?.length) return null\n\n const flattedNodes = extractNormalVNodes(nodes)\n\n const results: SlotRenderItem[] = []\n\n let i = 0\n while (i < flattedNodes.length) {\n const node = flattedNodes[i]!\n i++\n\n const { props, type } = node\n const field = props?.field as string | undefined\n const isFormItem = (type as any)?.name === 'UFormItem'\n\n const formItemProps = o((props ?? {}) as Record<string, any>).pick([\n 'label',\n 'rules',\n 'span',\n 'tips',\n 'readonly',\n 'field'\n ]) as Record<string, any>\n\n results.push({\n isFormItem,\n formItemProps,\n node,\n field,\n modelValue: props?.['model-value'] ?? props?.modelValue\n })\n }\n\n return results\n }\n\n return { getSlotsNodes }\n}\n"],"mappings":";;;;;;;;AAgBA,SAAgB,qBAAuE;CACrF,MAAM,QAAQ,SAAS;CAEvB,SAAS,gBAAgB;EACvB,MAAM,QAAQ,MAAM,UAAU;EAC9B,IAAI,CAAC,OAAO,QAAQ,OAAO;EAE3B,MAAM,eAAe,oBAAoB,KAAK;EAE9C,MAAM,UAA4B,CAAC;EAEnC,IAAI,IAAI;EACR,OAAO,IAAI,aAAa,QAAQ;GAC9B,MAAM,OAAO,aAAa;GAC1B;GAEA,MAAM,EAAE,OAAO,SAAS;GACxB,MAAM,QAAQ,OAAO;GACrB,MAAM,aAAc,MAAc,SAAS;GAE3C,MAAM,gBAAgB,EAAG,SAAS,CAAC,CAAyB,CAAC,CAAC,KAAK;IACjE;IACA;IACA;IACA;IACA;IACA;GACF,CAAC;GAED,QAAQ,KAAK;IACX;IACA;IACA;IACA;IACA,YAAY,QAAQ,kBAAkB,OAAO;GAC/C,CAAC;EACH;EAEA,OAAO;CACT;CAEA,OAAO,EAAE,cAAc;AACzB"}
1
+ {"version":3,"file":"use-node-interceptor.js","names":[],"sources":["../../../src/components/form/use-node-interceptor.ts"],"sourcesContent":["import { o } from '@cat-kit/core'\nimport { extractNormalVNodes } from '@veltra/utils'\nimport { cloneVNode, useSlots, type VNode } from 'vue'\n\nexport type SlotRenderItem = {\n isFormItem: boolean\n formItemProps?: Record<string, any>\n node: VNode\n field?: string\n modelValue?: any\n /** v-for 身份:调用方 :key 优先,否则 type+field+出现次序 */\n renderKey: string | number | symbol\n}\n\nfunction getVNodeTypeName(node: VNode): string {\n const type = node.type as { name?: string; __name?: string } | string\n if (typeof type === 'string') return type\n if (typeof type === 'object' && type) return type.name || type.__name || ''\n return ''\n}\n\n/**\n * 从源 vnode 派生一份未挂载副本。\n * Vue 的 cloneVNode 会拷贝 el/component,同一源 vnode 渲两次会把实例从编辑控件抢走。\n */\nexport function forkUnmountedVNode(node: VNode, extra?: Record<string, unknown>): VNode {\n const forked = extra ? cloneVNode(node, extra) : cloneVNode(node)\n forked.el = null\n forked.component = null\n forked.anchor = null\n forked.suspense = null\n return forked\n}\n\n/**\n * 虚拟node拦截\n * @returns\n */\nexport function useNodeInterceptor(): { getSlotsNodes: () => SlotRenderItem[] | null } {\n const slots = useSlots()\n\n function getSlotsNodes() {\n const nodes = slots.default?.()\n if (!nodes?.length) return null\n\n const flattedNodes = extractNormalVNodes(nodes)\n\n const results: SlotRenderItem[] = []\n const seen = new Map<string, number>()\n\n let i = 0\n while (i < flattedNodes.length) {\n const node = flattedNodes[i]!\n i++\n\n const { props, type } = node\n const field = props?.field as string | undefined\n const isFormItem = (type as any)?.name === 'UFormItem'\n\n const formItemProps = o((props ?? {}) as Record<string, any>).pick([\n 'label',\n 'rules',\n 'span',\n 'tips',\n 'readonly',\n 'field'\n ]) as Record<string, any>\n\n let renderKey: string | number | symbol\n if (node.key != null) {\n renderKey = node.key\n } else {\n const base = `${getVNodeTypeName(node)}:${field ?? ''}`\n const n = seen.get(base) ?? 0\n seen.set(base, n + 1)\n renderKey = n === 0 ? `uform:${base}` : `uform:${base}#${n}`\n }\n\n results.push({\n isFormItem,\n formItemProps,\n node,\n field,\n modelValue: props?.['model-value'] ?? props?.modelValue,\n renderKey\n })\n }\n\n return results\n }\n\n return { getSlotsNodes }\n}\n"],"mappings":";;;;AAcA,SAAS,iBAAiB,MAAqB;CAC7C,MAAM,OAAO,KAAK;CAClB,IAAI,OAAO,SAAS,UAAU,OAAO;CACrC,IAAI,OAAO,SAAS,YAAY,MAAM,OAAO,KAAK,QAAQ,KAAK,UAAU;CACzE,OAAO;AACT;;;;;AAMA,SAAgB,mBAAmB,MAAa,OAAwC;CACtF,MAAM,SAAS,QAAQ,WAAW,MAAM,KAAK,IAAI,WAAW,IAAI;CAChE,OAAO,KAAK;CACZ,OAAO,YAAY;CACnB,OAAO,SAAS;CAChB,OAAO,WAAW;CAClB,OAAO;AACT;;;;;AAMA,SAAgB,qBAAuE;CACrF,MAAM,QAAQ,SAAS;CAEvB,SAAS,gBAAgB;EACvB,MAAM,QAAQ,MAAM,UAAU;EAC9B,IAAI,CAAC,OAAO,QAAQ,OAAO;EAE3B,MAAM,eAAe,oBAAoB,KAAK;EAE9C,MAAM,UAA4B,CAAC;EACnC,MAAM,uBAAO,IAAI,IAAoB;EAErC,IAAI,IAAI;EACR,OAAO,IAAI,aAAa,QAAQ;GAC9B,MAAM,OAAO,aAAa;GAC1B;GAEA,MAAM,EAAE,OAAO,SAAS;GACxB,MAAM,QAAQ,OAAO;GACrB,MAAM,aAAc,MAAc,SAAS;GAE3C,MAAM,gBAAgB,EAAG,SAAS,CAAC,CAAyB,CAAC,CAAC,KAAK;IACjE;IACA;IACA;IACA;IACA;IACA;GACF,CAAC;GAED,IAAI;GACJ,IAAI,KAAK,OAAO,MACd,YAAY,KAAK;QACZ;IACL,MAAM,OAAO,GAAG,iBAAiB,IAAI,EAAE,GAAG,SAAS;IACnD,MAAM,IAAI,KAAK,IAAI,IAAI,KAAK;IAC5B,KAAK,IAAI,MAAM,IAAI,CAAC;IACpB,YAAY,MAAM,IAAI,SAAS,SAAS,SAAS,KAAK,GAAG;GAC3D;GAEA,QAAQ,KAAK;IACX;IACA;IACA;IACA;IACA,YAAY,QAAQ,kBAAkB,OAAO;IAC7C;GACF,CAAC;EACH;EAEA,OAAO;CACT;CAEA,OAAO,EAAE,cAAc;AACzB"}
@@ -1 +1 @@
1
- {"version":3,"file":"form-item.js","names":[],"sources":["../../../src/components/form-item/form-item.vue"],"sourcesContent":["<template>\n <u-grid-item :span=\"span\" :class=\"className\">\n <label\n v-if=\"props.label || $slots.label\"\n :class=\"[cls.e('label'), bem.is('required', !!rules?.required)]\"\n :style=\"labelStyles\"\n >\n <u-tip v-if=\"tips\" :content=\"tips\" :class=\"cls.e('tips')\" :show-delay=\"500\">\n <span :class=\"cls.e('tip-label')\">\n <slot name=\"label\">{{ label }}{{ labelPosition === 'top' ? '' : ':' }}</slot>\n </span>\n </u-tip>\n <template v-else>\n <slot name=\"label\">{{ label }}{{ labelPosition === 'top' ? '' : ':' }}</slot>\n </template>\n </label>\n\n <section :class=\"cls.e('wrapper')\">\n <div :class=\"cls.e('content')\">\n <ContentSlot />\n </div>\n\n <!-- 只有表单控件处于非只读状态时,才显示错误提示 -->\n <section :class=\"cls.e('error')\" v-if=\"!readonly && !formProps?.noTips\">\n <transition name=\"form-item-tips\" mode=\"out-in\">\n <span :class=\"cls.e('error-text')\" v-if=\"!!errorTip\">\n {{ errorTip }}\n </span>\n </transition>\n </section>\n </section>\n </u-grid-item>\n</template>\n\n<script lang=\"tsx\" setup>\nimport { o } from '@cat-kit/core'\nimport { useConfig, useFallbackProps } from '@veltra/compositions'\nimport { bem, withUnit } from '@veltra/utils'\nimport { injectFormContext } from '@veltra/utils'\nimport {\n type CSSProperties,\n type VNode,\n cloneVNode,\n computed,\n onBeforeUnmount,\n shallowRef,\n useSlots,\n watch\n} from 'vue'\n\nimport type { FormItemEmits, FormItemProps, ComponentSize } from '../../types'\nimport { UGridItem } from '../grid'\nimport { UTip } from '../tip'\nimport { formItemCls as cls, defineField } from './helper'\nimport { validateField } from './validate'\n\ndefineOptions({ name: 'UFormItem' })\n\nconst props = withDefaults(defineProps<FormItemProps>(), { readonly: undefined })\n\nconst emit = defineEmits<FormItemEmits>()\n\nconst slots = useSlots()\n\ndefineSlots<{\n /** 标签插槽 */\n label?: () => any\n default?: () => any\n}>()\n\n/** 表单组件上下文 */\nconst {\n formProps,\n registerField,\n unregisterField,\n shouldValidate,\n handleFieldUpdate,\n handleFieldChange\n} = injectFormContext()\n\nfunction wrapControlChange(node: VNode) {\n if (!node || typeof node.type === 'symbol') return node\n\n return cloneVNode(node, {\n onChange: (...args: any[]) => {\n emit('change', ...args)\n if (props.field) handleFieldChange?.(props.field, ...args)\n }\n })\n}\n\nfunction ContentSlot() {\n const nodes = slots.default?.() ?? []\n return nodes.map(wrapControlChange)\n}\n\nconst { config } = useConfig()\n\nconst { size, readonly } = useFallbackProps([formProps ?? {}, props], {\n size: 'default' as ComponentSize,\n readonly: false\n})\n\nconst errorTip = shallowRef<string>()\n/** 递增序号,丢弃过期的异步校验结果 */\nlet validateSeq = 0\n/** 最近一次 validate 的 Promise,供过期调用等待最新结果 */\nlet latestValidatePromise: Promise<boolean> = Promise.resolve(true)\n\nconst labelPosition = computed(() => props.labelPosition ?? formProps?.labelPosition ?? 'left')\n\nconst className = computed(() => {\n return [\n cls.b,\n cls.m(size.value),\n bem.is('error', !!errorTip.value),\n bem.is('label-top', labelPosition.value === 'top')\n ].join(' ')\n})\n\n/** label样式 */\nconst labelStyles = computed<CSSProperties>(() => {\n if (labelPosition.value === 'top') return {}\n return {\n width: withUnit(props.labelWidth ?? formProps?.labelWidth ?? config.form.labelWidth, 'px')\n }\n})\n\nconst fieldItem = defineField({\n clearValidate() {\n errorTip.value = ''\n },\n async validate() {\n if (!props.field || !formProps?.model || !props.rules || !shouldValidate?.()) return true\n\n const seq = ++validateSeq\n\n latestValidatePromise = validateField(formProps.model!, props.field!, props.rules!).then(\n (tip) => {\n if (seq !== validateSeq) return latestValidatePromise\n\n errorTip.value = tip\n return !errorTip.value\n }\n )\n return latestValidatePromise\n }\n})\n\nwatch(\n () => props.field,\n (field, oldField) => {\n if (oldField) {\n unregisterField?.(oldField)\n }\n if (field) {\n registerField?.(field, fieldItem)\n }\n },\n { immediate: true }\n)\n\nlet stopWatchFieldValue: (() => void) | undefined\n\nwatch(\n [() => formProps?.model, () => props.field],\n ([model, field]) => {\n stopWatchFieldValue?.()\n\n if (!field || !model) return\n\n stopWatchFieldValue = watch(\n () => o(model).get(field),\n (value) => {\n handleFieldUpdate?.(field, value)\n fieldItem.validate()\n }\n )\n },\n { immediate: true }\n)\n\nonBeforeUnmount(() => {\n props.field && unregisterField?.(props.field)\n})\n</script>\n"],"mappings":""}
1
+ {"version":3,"file":"form-item.js","names":[],"sources":["../../../src/components/form-item/form-item.vue"],"sourcesContent":["<template>\n <u-grid-item :span=\"span\" :class=\"className\">\n <label\n v-if=\"props.label || $slots.label\"\n :class=\"[cls.e('label'), bem.is('required', !!rules?.required)]\"\n :style=\"labelStyles\"\n >\n <u-tip v-if=\"tips\" :content=\"tips\" :class=\"cls.e('tips')\" :show-delay=\"500\">\n <span :class=\"cls.e('tip-label')\">\n <slot name=\"label\">{{ label }}{{ labelPosition === 'top' ? '' : ':' }}</slot>\n </span>\n </u-tip>\n <template v-else>\n <slot name=\"label\">{{ label }}{{ labelPosition === 'top' ? '' : ':' }}</slot>\n </template>\n </label>\n\n <section :class=\"cls.e('wrapper')\">\n <div :class=\"cls.e('content')\">\n <ContentSlot>\n <slot></slot>\n </ContentSlot>\n </div>\n\n <!-- 只有表单控件处于非只读状态时,才显示错误提示 -->\n <section :class=\"cls.e('error')\" v-if=\"!readonly && !formProps?.noTips\">\n <transition name=\"form-item-tips\" mode=\"out-in\">\n <span :class=\"cls.e('error-text')\" v-if=\"!!errorTip\">\n {{ errorTip }}\n </span>\n </transition>\n </section>\n </section>\n </u-grid-item>\n</template>\n\n<script lang=\"tsx\" setup>\nimport { o } from '@cat-kit/core'\nimport { useConfig, useFallbackProps } from '@veltra/compositions'\nimport { bem, extractNormalVNodes, withUnit } from '@veltra/utils'\nimport { injectFormContext } from '@veltra/utils'\nimport {\n type CSSProperties,\n type SetupContext,\n type VNode,\n cloneVNode,\n computed,\n onBeforeUnmount,\n shallowRef,\n watch\n} from 'vue'\n\nimport type { FormItemEmits, FormItemProps, ComponentSize } from '../../types'\nimport { UGridItem } from '../grid'\nimport { UTip } from '../tip'\nimport { formItemCls as cls, defineField } from './helper'\nimport { validateField } from './validate'\n\ndefineOptions({ name: 'UFormItem' })\n\nconst props = withDefaults(defineProps<FormItemProps>(), { readonly: undefined })\n\nconst emit = defineEmits<FormItemEmits>()\n\ndefineSlots<{\n /** 标签插槽 */\n label?: () => any\n default?: () => any\n}>()\n\n/** 表单组件上下文 */\nconst { formProps, registerField, unregisterField, shouldValidate, handleFieldUpdate } =\n injectFormContext()\n\nfunction wrapControlChange(node: VNode) {\n if (!node || typeof node.type === 'symbol') return node\n\n return cloneVNode(node, {\n onChange: (...args: any[]) => {\n emit('change', ...args)\n }\n })\n}\n\n/**\n * 承载默认插槽并拦截控件 change。\n * 必须经填充插槽接收内容(而非直接读 UFormItem 的 $slots):\n * 读父级 $slots 时组件自身没有更新路径,父级重渲染后动态 props(disabled、data 等)会冻结在首帧。\n */\nfunction ContentSlot(_: unknown, { slots }: SetupContext) {\n return extractNormalVNodes(slots.default?.() ?? []).map(wrapControlChange)\n}\n\nconst { config } = useConfig()\n\nconst { size, readonly } = useFallbackProps([formProps ?? {}, props], {\n size: 'default' as ComponentSize,\n readonly: false\n})\n\nconst errorTip = shallowRef<string>()\n/** 递增序号,丢弃过期的异步校验结果 */\nlet validateSeq = 0\n/** 最近一次 validate 的 Promise,供过期调用等待最新结果 */\nlet latestValidatePromise: Promise<boolean> = Promise.resolve(true)\n\nconst labelPosition = computed(() => props.labelPosition ?? formProps?.labelPosition ?? 'left')\n\nconst className = computed(() => {\n return [\n cls.b,\n cls.m(size.value),\n bem.is('error', !!errorTip.value),\n bem.is('label-top', labelPosition.value === 'top')\n ].join(' ')\n})\n\n/** label样式 */\nconst labelStyles = computed<CSSProperties>(() => {\n if (labelPosition.value === 'top') return {}\n return {\n width: withUnit(props.labelWidth ?? formProps?.labelWidth ?? config.form.labelWidth, 'px')\n }\n})\n\nconst fieldItem = defineField({\n clearValidate() {\n errorTip.value = ''\n },\n async validate() {\n if (!props.field || !formProps?.model || !props.rules || !shouldValidate?.()) return true\n\n const seq = ++validateSeq\n\n latestValidatePromise = validateField(formProps.model!, props.field!, props.rules!).then(\n (tip) => {\n if (seq !== validateSeq) return latestValidatePromise\n\n errorTip.value = tip\n return !errorTip.value\n }\n )\n return latestValidatePromise\n }\n})\n\nwatch(\n () => props.field,\n (field, oldField) => {\n if (oldField) {\n unregisterField?.(oldField)\n }\n if (field) {\n registerField?.(field, fieldItem)\n }\n },\n { immediate: true }\n)\n\nlet stopWatchFieldValue: (() => void) | undefined\n\nwatch(\n [() => formProps?.model, () => props.field],\n ([model, field]) => {\n stopWatchFieldValue?.()\n\n if (!field || !model) return\n\n stopWatchFieldValue = watch(\n () => o(model).get(field),\n (value) => {\n handleFieldUpdate?.(field, value)\n fieldItem.validate()\n }\n )\n },\n { immediate: true }\n)\n\nonBeforeUnmount(() => {\n props.field && unregisterField?.(props.field)\n})\n</script>\n"],"mappings":""}
@@ -2,9 +2,9 @@ import _sfc_main from "../tip/tip.js";
2
2
  import _sfc_main$1 from "../grid/grid-item.js";
3
3
  import { defineField, formItemCls } from "./helper.js";
4
4
  import { validateField } from "./validate.js";
5
- import { Transition, cloneVNode, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, normalizeClass, normalizeStyle, onBeforeUnmount, openBlock, renderSlot, shallowRef, toDisplayString, unref, useSlots, watch, withCtx } from "vue";
5
+ import { Transition, cloneVNode, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, normalizeClass, normalizeStyle, onBeforeUnmount, openBlock, renderSlot, shallowRef, toDisplayString, unref, watch, withCtx } from "vue";
6
6
  import { useConfig, useFallbackProps } from "@veltra/compositions";
7
- import { bem, injectFormContext, withUnit } from "@veltra/utils";
7
+ import { bem, extractNormalVNodes, injectFormContext, withUnit } from "@veltra/utils";
8
8
  import { o } from "@cat-kit/core";
9
9
  //#region src/components/form-item/form-item.vue?vue&type=script&setup=true&lang.tsx
10
10
  var form_item_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
@@ -29,18 +29,21 @@ var form_item_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
29
29
  setup(__props, { emit: __emit }) {
30
30
  const props = __props;
31
31
  const emit = __emit;
32
- const slots = useSlots();
33
32
  /** 表单组件上下文 */
34
- const { formProps, registerField, unregisterField, shouldValidate, handleFieldUpdate, handleFieldChange } = injectFormContext();
33
+ const { formProps, registerField, unregisterField, shouldValidate, handleFieldUpdate } = injectFormContext();
35
34
  function wrapControlChange(node) {
36
35
  if (!node || typeof node.type === "symbol") return node;
37
36
  return cloneVNode(node, { onChange: (...args) => {
38
37
  emit("change", ...args);
39
- if (props.field) handleFieldChange?.(props.field, ...args);
40
38
  } });
41
39
  }
42
- function ContentSlot() {
43
- return (slots.default?.() ?? []).map(wrapControlChange);
40
+ /**
41
+ * 承载默认插槽并拦截控件 change。
42
+ * 必须经填充插槽接收内容(而非直接读 UFormItem 的 $slots):
43
+ * 读父级 $slots 时组件自身没有更新路径,父级重渲染后动态 props(disabled、data 等)会冻结在首帧。
44
+ */
45
+ function ContentSlot(_, { slots }) {
46
+ return extractNormalVNodes(slots.default?.() ?? []).map(wrapControlChange);
44
47
  }
45
48
  const { config } = useConfig();
46
49
  const { size, readonly } = useFallbackProps([formProps ?? {}, props], {
@@ -115,7 +118,10 @@ var form_item_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
115
118
  default: withCtx(() => [createElementVNode("span", { class: normalizeClass(unref(formItemCls).e("tip-label")) }, [renderSlot(_ctx.$slots, "label", {}, () => [createTextVNode(toDisplayString(__props.label) + toDisplayString(labelPosition.value === "top" ? "" : ":"), 1)])], 2)]),
116
119
  _: 3
117
120
  }, 8, ["content", "class"])) : renderSlot(_ctx.$slots, "label", {}, () => [createTextVNode(toDisplayString(__props.label) + toDisplayString(labelPosition.value === "top" ? "" : ":"), 1)], void 0, 1)], 6)) : createCommentVNode("v-if", true), createElementVNode("section", { class: normalizeClass(unref(formItemCls).e("wrapper")) }, [
118
- createElementVNode("div", { class: normalizeClass(unref(formItemCls).e("content")) }, [createVNode(ContentSlot)], 2),
121
+ createElementVNode("div", { class: normalizeClass(unref(formItemCls).e("content")) }, [createVNode(ContentSlot, null, {
122
+ default: withCtx(() => [renderSlot(_ctx.$slots, "default")]),
123
+ _: 3
124
+ })], 2),
119
125
  createCommentVNode(" 只有表单控件处于非只读状态时,才显示错误提示 "),
120
126
  !unref(readonly) && !unref(formProps)?.noTips ? (openBlock(), createElementBlock("section", {
121
127
  key: 0,
@@ -1 +1 @@
1
- {"version":3,"file":"form-item.vue_vue_type_script_setup_true_lang.js","names":["$slots"],"sources":["../../../src/components/form-item/form-item.vue"],"sourcesContent":["<template>\n <u-grid-item :span=\"span\" :class=\"className\">\n <label\n v-if=\"props.label || $slots.label\"\n :class=\"[cls.e('label'), bem.is('required', !!rules?.required)]\"\n :style=\"labelStyles\"\n >\n <u-tip v-if=\"tips\" :content=\"tips\" :class=\"cls.e('tips')\" :show-delay=\"500\">\n <span :class=\"cls.e('tip-label')\">\n <slot name=\"label\">{{ label }}{{ labelPosition === 'top' ? '' : ':' }}</slot>\n </span>\n </u-tip>\n <template v-else>\n <slot name=\"label\">{{ label }}{{ labelPosition === 'top' ? '' : ':' }}</slot>\n </template>\n </label>\n\n <section :class=\"cls.e('wrapper')\">\n <div :class=\"cls.e('content')\">\n <ContentSlot />\n </div>\n\n <!-- 只有表单控件处于非只读状态时,才显示错误提示 -->\n <section :class=\"cls.e('error')\" v-if=\"!readonly && !formProps?.noTips\">\n <transition name=\"form-item-tips\" mode=\"out-in\">\n <span :class=\"cls.e('error-text')\" v-if=\"!!errorTip\">\n {{ errorTip }}\n </span>\n </transition>\n </section>\n </section>\n </u-grid-item>\n</template>\n\n<script lang=\"tsx\" setup>\nimport { o } from '@cat-kit/core'\nimport { useConfig, useFallbackProps } from '@veltra/compositions'\nimport { bem, withUnit } from '@veltra/utils'\nimport { injectFormContext } from '@veltra/utils'\nimport {\n type CSSProperties,\n type VNode,\n cloneVNode,\n computed,\n onBeforeUnmount,\n shallowRef,\n useSlots,\n watch\n} from 'vue'\n\nimport type { FormItemEmits, FormItemProps, ComponentSize } from '../../types'\nimport { UGridItem } from '../grid'\nimport { UTip } from '../tip'\nimport { formItemCls as cls, defineField } from './helper'\nimport { validateField } from './validate'\n\ndefineOptions({ name: 'UFormItem' })\n\nconst props = withDefaults(defineProps<FormItemProps>(), { readonly: undefined })\n\nconst emit = defineEmits<FormItemEmits>()\n\nconst slots = useSlots()\n\ndefineSlots<{\n /** 标签插槽 */\n label?: () => any\n default?: () => any\n}>()\n\n/** 表单组件上下文 */\nconst {\n formProps,\n registerField,\n unregisterField,\n shouldValidate,\n handleFieldUpdate,\n handleFieldChange\n} = injectFormContext()\n\nfunction wrapControlChange(node: VNode) {\n if (!node || typeof node.type === 'symbol') return node\n\n return cloneVNode(node, {\n onChange: (...args: any[]) => {\n emit('change', ...args)\n if (props.field) handleFieldChange?.(props.field, ...args)\n }\n })\n}\n\nfunction ContentSlot() {\n const nodes = slots.default?.() ?? []\n return nodes.map(wrapControlChange)\n}\n\nconst { config } = useConfig()\n\nconst { size, readonly } = useFallbackProps([formProps ?? {}, props], {\n size: 'default' as ComponentSize,\n readonly: false\n})\n\nconst errorTip = shallowRef<string>()\n/** 递增序号,丢弃过期的异步校验结果 */\nlet validateSeq = 0\n/** 最近一次 validate 的 Promise,供过期调用等待最新结果 */\nlet latestValidatePromise: Promise<boolean> = Promise.resolve(true)\n\nconst labelPosition = computed(() => props.labelPosition ?? formProps?.labelPosition ?? 'left')\n\nconst className = computed(() => {\n return [\n cls.b,\n cls.m(size.value),\n bem.is('error', !!errorTip.value),\n bem.is('label-top', labelPosition.value === 'top')\n ].join(' ')\n})\n\n/** label样式 */\nconst labelStyles = computed<CSSProperties>(() => {\n if (labelPosition.value === 'top') return {}\n return {\n width: withUnit(props.labelWidth ?? formProps?.labelWidth ?? config.form.labelWidth, 'px')\n }\n})\n\nconst fieldItem = defineField({\n clearValidate() {\n errorTip.value = ''\n },\n async validate() {\n if (!props.field || !formProps?.model || !props.rules || !shouldValidate?.()) return true\n\n const seq = ++validateSeq\n\n latestValidatePromise = validateField(formProps.model!, props.field!, props.rules!).then(\n (tip) => {\n if (seq !== validateSeq) return latestValidatePromise\n\n errorTip.value = tip\n return !errorTip.value\n }\n )\n return latestValidatePromise\n }\n})\n\nwatch(\n () => props.field,\n (field, oldField) => {\n if (oldField) {\n unregisterField?.(oldField)\n }\n if (field) {\n registerField?.(field, fieldItem)\n }\n },\n { immediate: true }\n)\n\nlet stopWatchFieldValue: (() => void) | undefined\n\nwatch(\n [() => formProps?.model, () => props.field],\n ([model, field]) => {\n stopWatchFieldValue?.()\n\n if (!field || !model) return\n\n stopWatchFieldValue = watch(\n () => o(model).get(field),\n (value) => {\n handleFieldUpdate?.(field, value)\n fieldItem.validate()\n }\n )\n },\n { immediate: true }\n)\n\nonBeforeUnmount(() => {\n props.field && unregisterField?.(props.field)\n})\n</script>\n"],"mappings":"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"}
1
+ {"version":3,"file":"form-item.vue_vue_type_script_setup_true_lang.js","names":["$slots"],"sources":["../../../src/components/form-item/form-item.vue"],"sourcesContent":["<template>\n <u-grid-item :span=\"span\" :class=\"className\">\n <label\n v-if=\"props.label || $slots.label\"\n :class=\"[cls.e('label'), bem.is('required', !!rules?.required)]\"\n :style=\"labelStyles\"\n >\n <u-tip v-if=\"tips\" :content=\"tips\" :class=\"cls.e('tips')\" :show-delay=\"500\">\n <span :class=\"cls.e('tip-label')\">\n <slot name=\"label\">{{ label }}{{ labelPosition === 'top' ? '' : ':' }}</slot>\n </span>\n </u-tip>\n <template v-else>\n <slot name=\"label\">{{ label }}{{ labelPosition === 'top' ? '' : ':' }}</slot>\n </template>\n </label>\n\n <section :class=\"cls.e('wrapper')\">\n <div :class=\"cls.e('content')\">\n <ContentSlot>\n <slot></slot>\n </ContentSlot>\n </div>\n\n <!-- 只有表单控件处于非只读状态时,才显示错误提示 -->\n <section :class=\"cls.e('error')\" v-if=\"!readonly && !formProps?.noTips\">\n <transition name=\"form-item-tips\" mode=\"out-in\">\n <span :class=\"cls.e('error-text')\" v-if=\"!!errorTip\">\n {{ errorTip }}\n </span>\n </transition>\n </section>\n </section>\n </u-grid-item>\n</template>\n\n<script lang=\"tsx\" setup>\nimport { o } from '@cat-kit/core'\nimport { useConfig, useFallbackProps } from '@veltra/compositions'\nimport { bem, extractNormalVNodes, withUnit } from '@veltra/utils'\nimport { injectFormContext } from '@veltra/utils'\nimport {\n type CSSProperties,\n type SetupContext,\n type VNode,\n cloneVNode,\n computed,\n onBeforeUnmount,\n shallowRef,\n watch\n} from 'vue'\n\nimport type { FormItemEmits, FormItemProps, ComponentSize } from '../../types'\nimport { UGridItem } from '../grid'\nimport { UTip } from '../tip'\nimport { formItemCls as cls, defineField } from './helper'\nimport { validateField } from './validate'\n\ndefineOptions({ name: 'UFormItem' })\n\nconst props = withDefaults(defineProps<FormItemProps>(), { readonly: undefined })\n\nconst emit = defineEmits<FormItemEmits>()\n\ndefineSlots<{\n /** 标签插槽 */\n label?: () => any\n default?: () => any\n}>()\n\n/** 表单组件上下文 */\nconst { formProps, registerField, unregisterField, shouldValidate, handleFieldUpdate } =\n injectFormContext()\n\nfunction wrapControlChange(node: VNode) {\n if (!node || typeof node.type === 'symbol') return node\n\n return cloneVNode(node, {\n onChange: (...args: any[]) => {\n emit('change', ...args)\n }\n })\n}\n\n/**\n * 承载默认插槽并拦截控件 change。\n * 必须经填充插槽接收内容(而非直接读 UFormItem 的 $slots):\n * 读父级 $slots 时组件自身没有更新路径,父级重渲染后动态 props(disabled、data 等)会冻结在首帧。\n */\nfunction ContentSlot(_: unknown, { slots }: SetupContext) {\n return extractNormalVNodes(slots.default?.() ?? []).map(wrapControlChange)\n}\n\nconst { config } = useConfig()\n\nconst { size, readonly } = useFallbackProps([formProps ?? {}, props], {\n size: 'default' as ComponentSize,\n readonly: false\n})\n\nconst errorTip = shallowRef<string>()\n/** 递增序号,丢弃过期的异步校验结果 */\nlet validateSeq = 0\n/** 最近一次 validate 的 Promise,供过期调用等待最新结果 */\nlet latestValidatePromise: Promise<boolean> = Promise.resolve(true)\n\nconst labelPosition = computed(() => props.labelPosition ?? formProps?.labelPosition ?? 'left')\n\nconst className = computed(() => {\n return [\n cls.b,\n cls.m(size.value),\n bem.is('error', !!errorTip.value),\n bem.is('label-top', labelPosition.value === 'top')\n ].join(' ')\n})\n\n/** label样式 */\nconst labelStyles = computed<CSSProperties>(() => {\n if (labelPosition.value === 'top') return {}\n return {\n width: withUnit(props.labelWidth ?? formProps?.labelWidth ?? config.form.labelWidth, 'px')\n }\n})\n\nconst fieldItem = defineField({\n clearValidate() {\n errorTip.value = ''\n },\n async validate() {\n if (!props.field || !formProps?.model || !props.rules || !shouldValidate?.()) return true\n\n const seq = ++validateSeq\n\n latestValidatePromise = validateField(formProps.model!, props.field!, props.rules!).then(\n (tip) => {\n if (seq !== validateSeq) return latestValidatePromise\n\n errorTip.value = tip\n return !errorTip.value\n }\n )\n return latestValidatePromise\n }\n})\n\nwatch(\n () => props.field,\n (field, oldField) => {\n if (oldField) {\n unregisterField?.(oldField)\n }\n if (field) {\n registerField?.(field, fieldItem)\n }\n },\n { immediate: true }\n)\n\nlet stopWatchFieldValue: (() => void) | undefined\n\nwatch(\n [() => formProps?.model, () => props.field],\n ([model, field]) => {\n stopWatchFieldValue?.()\n\n if (!field || !model) return\n\n stopWatchFieldValue = watch(\n () => o(model).get(field),\n (value) => {\n handleFieldUpdate?.(field, value)\n fieldItem.validate()\n }\n )\n },\n { immediate: true }\n)\n\nonBeforeUnmount(() => {\n props.field && unregisterField?.(props.field)\n})\n</script>\n"],"mappings":"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"}
@@ -3,7 +3,12 @@ import { ColorType, DeconstructValue } from "@veltra/utils";
3
3
  //#region src/types/action.d.ts
4
4
  /** 操作组件属性 */
5
5
  interface ActionProps extends ButtonProps {
6
- /** 是否需要确认 */
6
+ /**
7
+ * 是否需要确认:true 时点击只弹确认气泡(UPopConfirm),点气泡里的「确认」才触发 `run`
8
+ * @default false
9
+ * @description 不要在本项的 `run` 回调里再调 `messageConfirm`:`run` 触发时气泡已经确认过一次,
10
+ * 会变成两次确认。需要弹窗级确认时去掉 `needConfirm`,只在 `run` 里用 `messageConfirm`
11
+ */
7
12
  needConfirm?: boolean;
8
13
  /**
9
14
  * 是否始终位于下拉菜单中,无视 `max` 限制