@veltra/desktop 1.7.11 → 1.7.13
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.
- package/dist/components/batch-edit/batch-edit-form.js +2 -6
- package/dist/components/batch-edit/batch-edit-form.js.map +1 -1
- package/dist/components/batch-edit/batch-edit.js +0 -1
- package/dist/components/batch-edit/batch-edit.js.map +1 -1
- package/dist/components/batch-edit/helper.d.ts +1 -2
- package/dist/components/condition-editor/core/evaluator.d.ts +4 -5
- package/dist/components/contextmenu/api.d.ts +1 -2
- package/dist/components/contextmenu/di.d.ts +2 -3
- package/dist/components/form/form.js.map +1 -1
- package/dist/components/form/form.vue_vue_type_script_setup_true_lang.js +12 -13
- package/dist/components/form/form.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/form/use-node-interceptor.js +31 -3
- package/dist/components/form/use-node-interceptor.js.map +1 -1
- package/dist/components/form-item/form-item.js.map +1 -1
- package/dist/components/form-item/form-item.vue_vue_type_script_setup_true_lang.js +1 -2
- package/dist/components/form-item/form-item.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/loading/directive.d.ts +1 -2
- package/dist/components/message/message.d.ts +1 -2
- package/dist/components/message-confirm/message-confirm.d.ts +1 -2
- package/dist/components/notification/notification.d.ts +1 -2
- package/dist/components/table/node/col.js +19 -0
- package/dist/components/table/node/col.js.map +1 -1
- package/dist/components/table/table-cell.js +2 -0
- package/dist/components/table/table-cell.js.map +1 -1
- package/dist/components/table/table-foot.js +2 -0
- package/dist/components/table/table-foot.js.map +1 -1
- package/dist/components/table/table-head.js +1 -0
- package/dist/components/table/table-head.js.map +1 -1
- package/dist/components/table/table-row.js +2 -0
- package/dist/components/table/table-row.js.map +1 -1
- package/dist/components/table/use-columns.d.ts +1 -2
- package/dist/index.d.ts +2 -2
- package/dist/install.d.ts +3 -3
- package/dist/types/action.d.ts +7 -8
- package/dist/types/animation.d.ts +4 -5
- package/dist/types/auto-complete.d.ts +4 -5
- package/dist/types/badge.d.ts +4 -5
- package/dist/types/batch-edit.d.ts +9 -12
- package/dist/types/breadcrumb.d.ts +6 -7
- package/dist/types/button.d.ts +5 -6
- package/dist/types/calendar.d.ts +7 -8
- package/dist/types/card.d.ts +7 -8
- package/dist/types/cascade.d.ts +6 -7
- package/dist/types/check-tag.d.ts +4 -5
- package/dist/types/checkbox-group.d.ts +3 -4
- package/dist/types/checkbox.d.ts +5 -6
- package/dist/types/code-editor.d.ts +5 -6
- package/dist/types/collapse.d.ts +6 -7
- package/dist/types/condition-editor.d.ts +11 -12
- package/dist/types/contextmenu.d.ts +5 -6
- package/dist/types/css-transition.d.ts +4 -5
- package/dist/types/date-panel.d.ts +3 -4
- package/dist/types/date-picker.d.ts +5 -6
- package/dist/types/date-range-picker.d.ts +6 -7
- package/dist/types/dialog.d.ts +5 -6
- package/dist/types/drawer.d.ts +6 -7
- package/dist/types/dropdown.d.ts +4 -5
- package/dist/types/dual-nav.d.ts +6 -7
- package/dist/types/empty.d.ts +4 -5
- package/dist/types/expression-editor.d.ts +6 -7
- package/dist/types/file-picker.d.ts +4 -5
- package/dist/types/file-viewer.d.ts +6 -7
- package/dist/types/float-button.d.ts +5 -6
- package/dist/types/form-item.d.ts +3 -4
- package/dist/types/form.d.ts +4 -7
- package/dist/types/gantt-chart.d.ts +4 -5
- package/dist/types/grid-input.d.ts +4 -5
- package/dist/types/grid.d.ts +7 -8
- package/dist/types/group-input.d.ts +4 -5
- package/dist/types/group-nav.d.ts +3 -4
- package/dist/types/icon.d.ts +3 -4
- package/dist/types/image-cropper.d.ts +9 -10
- package/dist/types/index.d.ts +2 -2
- package/dist/types/input.d.ts +4 -5
- package/dist/types/layout.d.ts +4 -5
- package/dist/types/list.d.ts +4 -5
- package/dist/types/loading.d.ts +5 -6
- package/dist/types/message-confirm.d.ts +8 -9
- package/dist/types/message.d.ts +8 -9
- package/dist/types/multi-auto-complete.d.ts +4 -5
- package/dist/types/multi-select.d.ts +4 -5
- package/dist/types/multi-tree-select.d.ts +4 -5
- package/dist/types/nav.d.ts +5 -6
- package/dist/types/node-render.d.ts +2 -3
- package/dist/types/notification.d.ts +8 -9
- package/dist/types/number-input.d.ts +3 -4
- package/dist/types/number-range-input.d.ts +4 -5
- package/dist/types/number.d.ts +3 -4
- package/dist/types/paginator.d.ts +4 -5
- package/dist/types/palette.d.ts +7 -8
- package/dist/types/password-input.d.ts +4 -5
- package/dist/types/pop-confirm.d.ts +4 -5
- package/dist/types/pop.d.ts +4 -5
- package/dist/types/progress-nodes.d.ts +4 -5
- package/dist/types/progress.d.ts +4 -5
- package/dist/types/quick-batch-edit.d.ts +4 -5
- package/dist/types/radio-group.d.ts +4 -5
- package/dist/types/radio.d.ts +4 -5
- package/dist/types/rich-text-editor.d.ts +6 -7
- package/dist/types/scroll.d.ts +5 -6
- package/dist/types/segment.d.ts +5 -6
- package/dist/types/select.d.ts +4 -5
- package/dist/types/slider.d.ts +4 -5
- package/dist/types/steps.d.ts +5 -6
- package/dist/types/switch.d.ts +4 -5
- package/dist/types/table-editor.d.ts +4 -5
- package/dist/types/table.d.ts +23 -13
- package/dist/types/tabs.d.ts +13 -14
- package/dist/types/tag.d.ts +3 -4
- package/dist/types/text-editor.d.ts +5 -6
- package/dist/types/text.d.ts +4 -5
- package/dist/types/textarea.d.ts +4 -5
- package/dist/types/theme.d.ts +3 -4
- package/dist/types/tip.d.ts +6 -7
- package/dist/types/tree-select.d.ts +4 -5
- package/dist/types/tree.d.ts +6 -6
- package/dist/types/watermark.d.ts +4 -5
- package/package.json +5 -5
- package/src/components/batch-edit/__test__/batch-edit.test.ts +0 -138
- package/src/components/batch-edit/batch-edit-form.vue +2 -16
- package/src/components/form/__test__/form.test.ts +125 -33
- package/src/components/form/form.vue +10 -11
- package/src/components/form/use-node-interceptor.ts +36 -2
- package/src/components/form-item/__test__/form-item.test.ts +1 -10
- package/src/components/form-item/form-item.vue +2 -9
- package/src/components/table/__test__/column-style.test.ts +67 -0
- package/src/components/table/node/col.ts +30 -1
- package/src/components/table/table-cell.vue +7 -2
- package/src/components/table/table-foot.vue +2 -0
- package/src/components/table/table-head.tsx +1 -0
- package/src/components/table/table-row.tsx +2 -0
- package/src/types/batch-edit.ts +0 -2
- package/src/types/form.ts +0 -2
- package/src/types/table.ts +12 -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,
|
|
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
|
|
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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"}
|
|
@@ -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":"
|
|
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"}
|
|
@@ -6,7 +6,6 @@ import "../../types/index.js";
|
|
|
6
6
|
* @param columns 列
|
|
7
7
|
* @returns
|
|
8
8
|
*/
|
|
9
|
-
declare function defineBatchEditColumns(columns: BatchEditColumn[]): BatchEditColumn[];
|
|
9
|
+
export declare function defineBatchEditColumns(columns: BatchEditColumn[]): BatchEditColumn[];
|
|
10
10
|
//#endregion
|
|
11
|
-
export { defineBatchEditColumns };
|
|
12
11
|
//# sourceMappingURL=helper.d.ts.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ConditionExpression, ConditionField, ConditionGroup, ConditionLeaf } from "../../../types/condition-editor.js";
|
|
2
2
|
import "../../../types/index.js";
|
|
3
3
|
//#region src/components/condition-editor/core/evaluator.d.ts
|
|
4
|
-
interface EvaluateOptions {
|
|
4
|
+
export interface EvaluateOptions {
|
|
5
5
|
/** 字段定义 —— 提供后按字段类型做类型感知比较 */
|
|
6
6
|
fields?: ConditionField[];
|
|
7
7
|
/** 上下文数据,用于解析 `kind: 'variable'` 引用 */
|
|
@@ -15,9 +15,8 @@ interface EvaluateOptions {
|
|
|
15
15
|
* - 不完整的叶子(field/operator 缺失、或缺少所需值且 operator 需要值)按 `false` 计
|
|
16
16
|
* - 同组内 AND/OR 按 **从左到右、等优先级** 求值;需要更高优先级请用子分组
|
|
17
17
|
*/
|
|
18
|
-
declare function evaluate(expression: ConditionExpression, options?: EvaluateOptions): boolean;
|
|
19
|
-
declare function createEmptyGroup(): ConditionGroup;
|
|
20
|
-
declare function createEmptyLeaf(): ConditionLeaf;
|
|
18
|
+
export declare function evaluate(expression: ConditionExpression, options?: EvaluateOptions): boolean;
|
|
19
|
+
export declare function createEmptyGroup(): ConditionGroup;
|
|
20
|
+
export declare function createEmptyLeaf(): ConditionLeaf;
|
|
21
21
|
//#endregion
|
|
22
|
-
export { EvaluateOptions, createEmptyGroup, createEmptyLeaf, evaluate };
|
|
23
22
|
//# sourceMappingURL=evaluator.d.ts.map
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { ContextmenuProps } from "../../types/contextmenu.js";
|
|
2
2
|
import "../../types/index.js";
|
|
3
3
|
//#region src/components/contextmenu/api.d.ts
|
|
4
|
-
declare const contextmenu: {
|
|
4
|
+
export declare const contextmenu: {
|
|
5
5
|
pop(options: ContextmenuProps): void;
|
|
6
6
|
};
|
|
7
7
|
//#endregion
|
|
8
|
-
export { contextmenu };
|
|
9
8
|
//# sourceMappingURL=api.d.ts.map
|
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
import { ComputedRef, InjectionKey } from "vue";
|
|
2
2
|
import { BEM } from "@veltra/utils";
|
|
3
3
|
//#region src/components/contextmenu/di.d.ts
|
|
4
|
-
declare const ContextmenuRootDIKey: InjectionKey<{
|
|
4
|
+
export declare const ContextmenuRootDIKey: InjectionKey<{
|
|
5
5
|
cls: BEM<'contextmenu'>;
|
|
6
6
|
onItemClickStart: () => void;
|
|
7
7
|
onItemClickEnd: () => void;
|
|
8
8
|
}>;
|
|
9
|
-
declare const ContextmenuPanelDIKey: InjectionKey<{
|
|
9
|
+
export declare const ContextmenuPanelDIKey: InjectionKey<{
|
|
10
10
|
showIconColumn: ComputedRef<boolean>;
|
|
11
11
|
showArrowColumn: ComputedRef<boolean>;
|
|
12
12
|
}>;
|
|
13
13
|
//#endregion
|
|
14
|
-
export { ContextmenuPanelDIKey, ContextmenuRootDIKey };
|
|
15
14
|
//# sourceMappingURL=di.d.ts.map
|
|
@@ -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=\"
|
|
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:
|
|
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:
|
|
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=\"
|
|
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":"
|
|
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 <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 {
|
|
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":""}
|
|
@@ -30,12 +30,11 @@ var form_item_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
|
|
|
30
30
|
const props = __props;
|
|
31
31
|
const emit = __emit;
|
|
32
32
|
/** 表单组件上下文 */
|
|
33
|
-
const { formProps, registerField, unregisterField, shouldValidate, handleFieldUpdate
|
|
33
|
+
const { formProps, registerField, unregisterField, shouldValidate, handleFieldUpdate } = injectFormContext();
|
|
34
34
|
function wrapControlChange(node) {
|
|
35
35
|
if (!node || typeof node.type === "symbol") return node;
|
|
36
36
|
return cloneVNode(node, { onChange: (...args) => {
|
|
37
37
|
emit("change", ...args);
|
|
38
|
-
if (props.field) handleFieldChange?.(props.field, ...args);
|
|
39
38
|
} });
|
|
40
39
|
}
|
|
41
40
|
/**
|
|
@@ -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 <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 {
|
|
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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"}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { ObjectDirective } from "vue";
|
|
2
2
|
//#region src/components/loading/directive.d.ts
|
|
3
|
-
declare const vLoading: ObjectDirective<HTMLElement>;
|
|
3
|
+
export declare const vLoading: ObjectDirective<HTMLElement>;
|
|
4
4
|
//#endregion
|
|
5
|
-
export { vLoading };
|
|
6
5
|
//# sourceMappingURL=directive.d.ts.map
|
|
@@ -2,7 +2,6 @@ import { Message } from "../../types/message.js";
|
|
|
2
2
|
import "../../types/index.js";
|
|
3
3
|
//#region src/components/message/message.d.ts
|
|
4
4
|
/** --- 导出 API --- */
|
|
5
|
-
declare const message: Message;
|
|
5
|
+
export declare const message: Message;
|
|
6
6
|
//#endregion
|
|
7
|
-
export { message };
|
|
8
7
|
//# sourceMappingURL=message.d.ts.map
|
|
@@ -2,7 +2,6 @@ import { MessageConfirm } from "../../types/message-confirm.js";
|
|
|
2
2
|
import "../../types/index.js";
|
|
3
3
|
//#region src/components/message-confirm/message-confirm.d.ts
|
|
4
4
|
/** --- 导出 API --- */
|
|
5
|
-
declare const messageConfirm: MessageConfirm;
|
|
5
|
+
export declare const messageConfirm: MessageConfirm;
|
|
6
6
|
//#endregion
|
|
7
|
-
export { messageConfirm };
|
|
8
7
|
//# sourceMappingURL=message-confirm.d.ts.map
|
|
@@ -2,7 +2,6 @@ import { Notification } from "../../types/notification.js";
|
|
|
2
2
|
import "../../types/index.js";
|
|
3
3
|
//#region src/components/notification/notification.d.ts
|
|
4
4
|
/** --- 导出 API --- */
|
|
5
|
-
declare const notification: Notification;
|
|
5
|
+
export declare const notification: Notification;
|
|
6
6
|
//#endregion
|
|
7
|
-
export { notification };
|
|
8
7
|
//# sourceMappingURL=notification.d.ts.map
|
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
import { isReactive, reactive, shallowReactive } from "vue";
|
|
2
|
+
import { withUnit } from "@veltra/utils";
|
|
2
3
|
import { TreeNode } from "@cat-kit/core";
|
|
3
4
|
//#region src/components/table/node/col.ts
|
|
5
|
+
function normalizeColumnStyle(style) {
|
|
6
|
+
if (!style) return void 0;
|
|
7
|
+
const result = {};
|
|
8
|
+
if (style.color !== void 0) result.color = style.color;
|
|
9
|
+
if (style.fontSize !== void 0) {
|
|
10
|
+
const fontSize = withUnit(style.fontSize, "px");
|
|
11
|
+
if (fontSize !== void 0) result.fontSize = fontSize;
|
|
12
|
+
}
|
|
13
|
+
return Object.keys(result).length ? result : void 0;
|
|
14
|
+
}
|
|
4
15
|
var ColumnNode = class extends TreeNode {
|
|
5
16
|
/** 叶子节点数量 */
|
|
6
17
|
leafs;
|
|
@@ -35,6 +46,14 @@ var ColumnNode = class extends TreeNode {
|
|
|
35
46
|
set headerAlign(val) {
|
|
36
47
|
this.data.headerAlign = val;
|
|
37
48
|
}
|
|
49
|
+
/** 表体/表尾单元格样式 */
|
|
50
|
+
get cellStyle() {
|
|
51
|
+
return normalizeColumnStyle(this.data.style);
|
|
52
|
+
}
|
|
53
|
+
/** 表头单元格样式 */
|
|
54
|
+
get headerCellStyle() {
|
|
55
|
+
return normalizeColumnStyle(this.data.headerStyle ?? this.data.style);
|
|
56
|
+
}
|
|
38
57
|
/** 宽度 */
|
|
39
58
|
get width() {
|
|
40
59
|
const width = this.data.width ?? this.derived.allocatedWidth;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"col.js","names":[],"sources":["../../../../src/components/table/node/col.ts"],"sourcesContent":["import { TreeNode } from '@cat-kit/core'\nimport { isReactive, reactive, shallowReactive } from 'vue'\n\nimport type { TableColumn, TableColumnAlign } from '../../../types'\n\nexport class ColumnNode extends TreeNode<TableColumn, ColumnNode> {\n declare children?: ColumnNode[] | undefined\n declare parent?: ColumnNode\n /** 叶子节点数量 */\n leafs?: number\n\n nextNode: ColumnNode | null = null\n\n /** 列key */\n get key(): string {\n return this.data.key\n }\n set key(val) {\n this.data.key = val\n }\n /** 列名 */\n get name(): string {\n return this.data.name\n }\n set name(val) {\n this.data.name = val\n }\n\n /**\n * 列对齐方式\n * @default 'left'\n */\n get align(): TableColumnAlign {\n return this.data.align ?? 'left'\n }\n set align(val) {\n this.data.align = val\n }\n\n get headerAlign(): TableColumnAlign {\n return this.data.headerAlign ?? this.align\n }\n set headerAlign(val) {\n this.data.headerAlign = val\n }\n\n /** 宽度 */\n get width(): number | undefined {\n const width = this.data.width ?? this.derived.allocatedWidth\n if (!width || (this.minWidth && width && width < this.minWidth)) {\n return this.minWidth\n }\n return width\n }\n set width(val) {\n if (this.minWidth && val && val < this.minWidth) {\n val = this.minWidth\n }\n this.data.width = val\n // 显式宽度(配置/拖拽)优先于分配宽度,旧的分配结果直接作废\n this.derived.allocatedWidth = undefined\n }\n\n /**\n * 列宽分配算法写入的宽度。\n * 与用户列配置 `data.width` 隔离:分配结果不回写列配置对象,\n * 避免列森林重建(重挂载 / v-if / columns 引用变化)时把上一次的\n * 分配残留误判为显式 width,导致列宽被永久锁定、容器变窄后出现滚动条。\n */\n get allocatedWidth(): number | undefined {\n return this.derived.allocatedWidth\n }\n set allocatedWidth(val: number | undefined) {\n this.derived.allocatedWidth = val\n }\n /** 最小宽度 */\n get minWidth(): number | undefined {\n const minWidth = this.data.minWidth\n if (!minWidth && this.isLeaf) {\n return 100\n }\n return minWidth\n }\n set minWidth(val) {\n this.data.minWidth = val\n }\n\n /** 列固定方向 */\n get fixed(): 'left' | 'right' | undefined {\n if (this.depth > 0) return\n return this.data.fixed\n }\n set fixed(val) {\n this.data.fixed = val\n }\n\n /** 是否是左侧的最后一个固定列 */\n get isLastFixed(): boolean {\n return this.data.isLastFixed ?? false\n }\n\n /** 是否是右侧的第一个固定列 */\n get isFirstFixed(): boolean {\n return this.data.isFirstFixed ?? false\n }\n\n /** 是否是可调整宽度的列 */\n get resizable(): boolean {\n return this.data.resizable ?? true\n }\n\n /**\n * 是否在列配置上显式指定了 width,或经表头拖拽锁定。\n * 此类列不参与剩余宽度的均分。\n */\n explicitWidth: boolean\n\n style: Record<string, number> = reactive({})\n\n /** 派生状态(响应式),与用户列配置 data 隔离 */\n private readonly derived = shallowReactive<{ allocatedWidth?: number }>({\n allocatedWidth: undefined\n })\n\n constructor(val: TableColumn, index: number, depth: number, parent?: ColumnNode) {\n super(isReactive(val) ? val : shallowReactive(val), index, depth, parent)\n this.explicitWidth = val.width !== undefined\n }\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"col.js","names":[],"sources":["../../../../src/components/table/node/col.ts"],"sourcesContent":["import { TreeNode } from '@cat-kit/core'\nimport { withUnit } from '@veltra/utils'\nimport { isReactive, reactive, shallowReactive } from 'vue'\n\nimport type { TableColumn, TableColumnAlign, TableColumnStyle } from '../../../types'\n\nfunction normalizeColumnStyle(style?: TableColumnStyle): Record<string, string> | undefined {\n if (!style) return undefined\n\n const result: Record<string, string> = {}\n\n if (style.color !== undefined) {\n result.color = style.color\n }\n if (style.fontSize !== undefined) {\n const fontSize = withUnit(style.fontSize, 'px')\n if (fontSize !== undefined) {\n result.fontSize = fontSize\n }\n }\n\n return Object.keys(result).length ? result : undefined\n}\n\nexport class ColumnNode extends TreeNode<TableColumn, ColumnNode> {\n declare children?: ColumnNode[] | undefined\n declare parent?: ColumnNode\n /** 叶子节点数量 */\n leafs?: number\n\n nextNode: ColumnNode | null = null\n\n /** 列key */\n get key(): string {\n return this.data.key\n }\n set key(val) {\n this.data.key = val\n }\n /** 列名 */\n get name(): string {\n return this.data.name\n }\n set name(val) {\n this.data.name = val\n }\n\n /**\n * 列对齐方式\n * @default 'left'\n */\n get align(): TableColumnAlign {\n return this.data.align ?? 'left'\n }\n set align(val) {\n this.data.align = val\n }\n\n get headerAlign(): TableColumnAlign {\n return this.data.headerAlign ?? this.align\n }\n set headerAlign(val) {\n this.data.headerAlign = val\n }\n\n /** 表体/表尾单元格样式 */\n get cellStyle(): Record<string, string> | undefined {\n return normalizeColumnStyle(this.data.style)\n }\n\n /** 表头单元格样式 */\n get headerCellStyle(): Record<string, string> | undefined {\n return normalizeColumnStyle(this.data.headerStyle ?? this.data.style)\n }\n\n /** 宽度 */\n get width(): number | undefined {\n const width = this.data.width ?? this.derived.allocatedWidth\n if (!width || (this.minWidth && width && width < this.minWidth)) {\n return this.minWidth\n }\n return width\n }\n set width(val) {\n if (this.minWidth && val && val < this.minWidth) {\n val = this.minWidth\n }\n this.data.width = val\n // 显式宽度(配置/拖拽)优先于分配宽度,旧的分配结果直接作废\n this.derived.allocatedWidth = undefined\n }\n\n /**\n * 列宽分配算法写入的宽度。\n * 与用户列配置 `data.width` 隔离:分配结果不回写列配置对象,\n * 避免列森林重建(重挂载 / v-if / columns 引用变化)时把上一次的\n * 分配残留误判为显式 width,导致列宽被永久锁定、容器变窄后出现滚动条。\n */\n get allocatedWidth(): number | undefined {\n return this.derived.allocatedWidth\n }\n set allocatedWidth(val: number | undefined) {\n this.derived.allocatedWidth = val\n }\n /** 最小宽度 */\n get minWidth(): number | undefined {\n const minWidth = this.data.minWidth\n if (!minWidth && this.isLeaf) {\n return 100\n }\n return minWidth\n }\n set minWidth(val) {\n this.data.minWidth = val\n }\n\n /** 列固定方向 */\n get fixed(): 'left' | 'right' | undefined {\n if (this.depth > 0) return\n return this.data.fixed\n }\n set fixed(val) {\n this.data.fixed = val\n }\n\n /** 是否是左侧的最后一个固定列 */\n get isLastFixed(): boolean {\n return this.data.isLastFixed ?? false\n }\n\n /** 是否是右侧的第一个固定列 */\n get isFirstFixed(): boolean {\n return this.data.isFirstFixed ?? false\n }\n\n /** 是否是可调整宽度的列 */\n get resizable(): boolean {\n return this.data.resizable ?? true\n }\n\n /**\n * 是否在列配置上显式指定了 width,或经表头拖拽锁定。\n * 此类列不参与剩余宽度的均分。\n */\n explicitWidth: boolean\n\n style: Record<string, number> = reactive({})\n\n /** 派生状态(响应式),与用户列配置 data 隔离 */\n private readonly derived = shallowReactive<{ allocatedWidth?: number }>({\n allocatedWidth: undefined\n })\n\n constructor(val: TableColumn, index: number, depth: number, parent?: ColumnNode) {\n super(isReactive(val) ? val : shallowReactive(val), index, depth, parent)\n this.explicitWidth = val.width !== undefined\n }\n}\n"],"mappings":";;;;AAMA,SAAS,qBAAqB,OAA8D;CAC1F,IAAI,CAAC,OAAO,OAAO,KAAA;CAEnB,MAAM,SAAiC,CAAC;CAExC,IAAI,MAAM,UAAU,KAAA,GAClB,OAAO,QAAQ,MAAM;CAEvB,IAAI,MAAM,aAAa,KAAA,GAAW;EAChC,MAAM,WAAW,SAAS,MAAM,UAAU,IAAI;EAC9C,IAAI,aAAa,KAAA,GACf,OAAO,WAAW;CAEtB;CAEA,OAAO,OAAO,KAAK,MAAM,CAAC,CAAC,SAAS,SAAS,KAAA;AAC/C;AAEA,IAAa,aAAb,cAAgC,SAAkC;;CAIhE;CAEA,WAA8B;;CAG9B,IAAI,MAAc;EAChB,OAAO,KAAK,KAAK;CACnB;CACA,IAAI,IAAI,KAAK;EACX,KAAK,KAAK,MAAM;CAClB;;CAEA,IAAI,OAAe;EACjB,OAAO,KAAK,KAAK;CACnB;CACA,IAAI,KAAK,KAAK;EACZ,KAAK,KAAK,OAAO;CACnB;;;;;CAMA,IAAI,QAA0B;EAC5B,OAAO,KAAK,KAAK,SAAS;CAC5B;CACA,IAAI,MAAM,KAAK;EACb,KAAK,KAAK,QAAQ;CACpB;CAEA,IAAI,cAAgC;EAClC,OAAO,KAAK,KAAK,eAAe,KAAK;CACvC;CACA,IAAI,YAAY,KAAK;EACnB,KAAK,KAAK,cAAc;CAC1B;;CAGA,IAAI,YAAgD;EAClD,OAAO,qBAAqB,KAAK,KAAK,KAAK;CAC7C;;CAGA,IAAI,kBAAsD;EACxD,OAAO,qBAAqB,KAAK,KAAK,eAAe,KAAK,KAAK,KAAK;CACtE;;CAGA,IAAI,QAA4B;EAC9B,MAAM,QAAQ,KAAK,KAAK,SAAS,KAAK,QAAQ;EAC9C,IAAI,CAAC,SAAU,KAAK,YAAY,SAAS,QAAQ,KAAK,UACpD,OAAO,KAAK;EAEd,OAAO;CACT;CACA,IAAI,MAAM,KAAK;EACb,IAAI,KAAK,YAAY,OAAO,MAAM,KAAK,UACrC,MAAM,KAAK;EAEb,KAAK,KAAK,QAAQ;EAElB,KAAK,QAAQ,iBAAiB,KAAA;CAChC;;;;;;;CAQA,IAAI,iBAAqC;EACvC,OAAO,KAAK,QAAQ;CACtB;CACA,IAAI,eAAe,KAAyB;EAC1C,KAAK,QAAQ,iBAAiB;CAChC;;CAEA,IAAI,WAA+B;EACjC,MAAM,WAAW,KAAK,KAAK;EAC3B,IAAI,CAAC,YAAY,KAAK,QACpB,OAAO;EAET,OAAO;CACT;CACA,IAAI,SAAS,KAAK;EAChB,KAAK,KAAK,WAAW;CACvB;;CAGA,IAAI,QAAsC;EACxC,IAAI,KAAK,QAAQ,GAAG;EACpB,OAAO,KAAK,KAAK;CACnB;CACA,IAAI,MAAM,KAAK;EACb,KAAK,KAAK,QAAQ;CACpB;;CAGA,IAAI,cAAuB;EACzB,OAAO,KAAK,KAAK,eAAe;CAClC;;CAGA,IAAI,eAAwB;EAC1B,OAAO,KAAK,KAAK,gBAAgB;CACnC;;CAGA,IAAI,YAAqB;EACvB,OAAO,KAAK,KAAK,aAAa;CAChC;;;;;CAMA;CAEA,QAAgC,SAAS,CAAC,CAAC;;CAG3C,UAA2B,gBAA6C,EACtE,gBAAgB,KAAA,EAClB,CAAC;CAED,YAAY,KAAkB,OAAe,OAAe,QAAqB;EAC/E,MAAM,WAAW,GAAG,IAAI,MAAM,gBAAgB,GAAG,GAAG,OAAO,OAAO,MAAM;EACxE,KAAK,gBAAgB,IAAI,UAAU,KAAA;CACrC;AACF"}
|
|
@@ -9,6 +9,7 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
|
|
|
9
9
|
cellClass: {},
|
|
10
10
|
left: {},
|
|
11
11
|
right: {},
|
|
12
|
+
cellStyle: {},
|
|
12
13
|
rowspan: {},
|
|
13
14
|
colspan: {}
|
|
14
15
|
},
|
|
@@ -22,6 +23,7 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
|
|
|
22
23
|
* 这里变成「完全受控」的纯渲染单元。
|
|
23
24
|
*/
|
|
24
25
|
const style = computed(() => ({
|
|
26
|
+
...__props.cellStyle,
|
|
25
27
|
left: withUnit(__props.left, "px"),
|
|
26
28
|
right: withUnit(__props.right, "px")
|
|
27
29
|
}));
|