@veltra/desktop 1.3.4 → 1.3.6
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/action/action-group.vue.d.ts +2 -2
- package/dist/components/action/action.vue.d.ts +1 -1
- package/dist/components/auto-complete/auto-complete.vue.d.ts +2 -2
- package/dist/components/cascade/cascade.js +8 -2
- package/dist/components/cascade/cascade.js.map +1 -1
- package/dist/components/cascade/cascade.vue.d.ts +4 -4
- package/dist/components/cascade/style2.css +4 -0
- package/dist/components/checkbox/checkbox-button.vue.d.ts +1 -1
- package/dist/components/checkbox-group/checkbox-group.vue.d.ts +2 -2
- package/dist/components/code-editor/code-editor.vue.d.ts +2 -2
- package/dist/components/date-panel/date-panel.vue.d.ts +1 -1
- package/dist/components/date-picker/date-picker.vue.d.ts +2 -2
- package/dist/components/date-range-picker/date-range-picker.js +5 -2
- package/dist/components/date-range-picker/date-range-picker.js.map +1 -1
- package/dist/components/date-range-picker/date-range-picker.vue.d.ts +2 -2
- package/dist/components/date-range-picker/style2.css +4 -0
- package/dist/components/empty/empty.vue.d.ts +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 +2 -2
- package/dist/components/form-item/form-item.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/form-item/style2.css +2 -1
- package/dist/components/grid-input/style2.css +3 -0
- package/dist/components/input/input.vue.d.ts +4 -4
- package/dist/components/multi-select/multi-select.js +67 -40
- package/dist/components/multi-select/multi-select.js.map +1 -1
- package/dist/components/multi-select/multi-select.vue.d.ts +6 -6
- package/dist/components/multi-select/style2.css +23 -10
- package/dist/components/multi-tree-select/multi-tree-select.js +52 -35
- package/dist/components/multi-tree-select/multi-tree-select.js.map +1 -1
- package/dist/components/multi-tree-select/multi-tree-select.vue.d.ts +4 -4
- package/dist/components/multi-tree-select/style2.css +26 -16
- package/dist/components/number-input/number-input.vue.d.ts +4 -4
- package/dist/components/number-range-input/number-range-input.vue.d.ts +1 -1
- package/dist/components/password-input/password-input.vue.d.ts +1 -1
- package/dist/components/pop-confirm/pop-confirm.vue.d.ts +1 -1
- package/dist/components/radio-group/radio-group.vue.d.ts +2 -2
- package/dist/components/rich-text-editor/rich-text-editor.vue.d.ts +1 -1
- package/dist/components/select/select.js +159 -95
- package/dist/components/select/select.js.map +1 -1
- package/dist/components/select/select.vue.d.ts +2 -2
- package/dist/components/select/style2.css +4 -17
- package/dist/components/select/use-options.js +67 -26
- package/dist/components/select/use-options.js.map +1 -1
- package/dist/components/steps/steps.vue.d.ts +2 -2
- package/dist/components/textarea/style2.css +1 -0
- package/dist/components/textarea/textarea.vue.d.ts +5 -5
- package/dist/components/tip/tip.vue.d.ts +1 -1
- package/dist/components/tree/use-tree-nodes.js +14 -17
- package/dist/components/tree/use-tree-nodes.js.map +1 -1
- package/dist/components/tree-select/style2.css +6 -15
- package/dist/components/tree-select/tree-select.js +95 -41
- package/dist/components/tree-select/tree-select.js.map +1 -1
- package/dist/components/tree-select/tree-select.vue.d.ts +4 -4
- package/dist/types/tree.d.ts +4 -1
- package/package.json +6 -6
- package/src/components/cascade/cascade.vue +15 -2
- package/src/components/cascade/style.scss +5 -0
- package/src/components/date-range-picker/date-range-picker.vue +9 -1
- package/src/components/date-range-picker/style.scss +5 -0
- package/src/components/form-item/form-item.vue +2 -2
- package/src/components/form-item/style.scss +2 -1
- package/src/components/grid-input/style.scss +1 -0
- package/src/components/multi-select/multi-select.vue +50 -19
- package/src/components/multi-select/style.scss +27 -4
- package/src/components/multi-tree-select/multi-tree-select.vue +34 -14
- package/src/components/multi-tree-select/style.scss +28 -9
- package/src/components/select/__test__/select.test.ts +110 -0
- package/src/components/select/select.vue +130 -46
- package/src/components/select/style.scss +5 -14
- package/src/components/select/use-options.ts +83 -39
- package/src/components/textarea/style.scss +1 -0
- package/src/components/tree/use-tree-nodes.ts +19 -24
- package/src/components/tree-select/style.scss +4 -8
- package/src/components/tree-select/tree-select.vue +90 -17
- package/src/types/tree.ts +4 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tree-select.js","names":["$attrs","$slots"],"sources":["../../../src/components/tree-select/tree-select.vue"],"sourcesContent":["<template>\n <u-dropdown\n v-if=\"!readonly\"\n v-bind=\"$attrs\"\n :class=\"[cls.b, bem.is('disabled', disabled)]\"\n trigger=\"click\"\n :content-class=\"[cls.e('panel'), cls.em('panel', size), contentClass]\"\n :content-style=\"contentStyle\"\n ref=\"dropdownRef\"\n :min-width=\"minWidth\"\n :width=\"width\"\n :disabled=\"disabled\"\n @update:visible=\"handleDropdownVisible\"\n >\n <template #trigger>\n <u-input\n :size=\"size\"\n :disabled=\"disabled\"\n :placeholder=\"placeholder\"\n :clearable=\"clearable\"\n :model-value=\"text ?? (model ? label : undefined)\"\n @clear=\"handleClear\"\n native-readonly\n >\n <template #prefix v-if=\"$slots.prefix\">\n <slot name=\"prefix\" />\n </template>\n <template #suffix>\n <u-icon :class=\"cls.e('arrow')\"><ArrowDown /></u-icon>\n </template>\n </u-input>\n </template>\n <template #content>\n <!-- 过滤器 -->\n <div v-if=\"filterable\" :class=\"[cls.e('content-filter'), cls.m(size)]\">\n <u-input placeholder=\"输入关键字进行过滤\" v-model=\"qs\">\n <template #suffix>\n <u-icon><Search /></u-icon>\n </template>\n </u-input>\n </div>\n <!-- 菜单列表 -->\n\n <u-tree\n v-bind=\"treeProps\"\n :selected=\"model\"\n @update:selected=\"handleSelect\"\n ref=\"treeRef\"\n selectable\n :class=\"cls.e('content-tree')\"\n :slots=\"slots\"\n scroll-to-view\n />\n </template>\n </u-dropdown>\n\n <template v-else>\n {{ text || label || FORM_EMPTY_CONTENT }}\n </template>\n</template>\n\n<script lang=\"ts\" setup>\nimport { dfs, o } from '@cat-kit/core'\nimport { useFormFallbackProps } from '@veltra/compositions'\nimport { ArrowDown, Search } from '@veltra/icons/normal'\nimport { bem, fieldKey, FORM_EMPTY_CONTENT } from '@veltra/utils'\nimport { injectFormContext } from '@veltra/utils'\nimport { computed, nextTick, shallowRef, watch } from 'vue'\n\nimport type { TreeSelectProps, TreeSelectEmits, TreeExposed } from '../../types'\nimport { UDropdown } from '../dropdown'\nimport { UIcon } from '../icon'\nimport { UInput } from '../input'\nimport { UTree } from '../tree'\nimport type { TreeSlotsScope } from '../tree/di'\n\ndefineOptions({ name: 'UTreeSelect', inheritAttrs: false })\n\nconst props = withDefaults(defineProps<TreeSelectProps>(), {\n labelKey: 'label',\n valueKey: 'value',\n placeholder: '请选择',\n expandAll: false,\n clearable: true,\n disabled: undefined,\n readonly: undefined,\n filterable: false,\n minWidth: '280px'\n})\n\nconst emit = defineEmits<TreeSelectEmits>()\n\nconst slots = defineSlots<{\n /** 默认插槽 */\n default?: (props: TreeSlotsScope) => any\n /** 前缀插槽 */\n prefix?: () => any\n}>()\n\nconst treeProps = computed(() => {\n return o(props as Record<string, any>).omit([\n 'tips',\n 'field',\n 'placeholder',\n 'disabled',\n 'label',\n 'readonly',\n 'contentClass',\n 'contentStyle',\n 'minWidth',\n 'width'\n ])\n})\n\nconst cls = bem('tree-select')\n\nconst labelKey = computed(() => fieldKey(props.labelKey, 'label'))\nconst valueKey = computed(() => fieldKey(props.valueKey, 'value'))\n\n/**过滤 */\nconst qs = shallowRef('')\nwatch(qs, (qs) => {\n treeRef.value?.filter(qs)\n})\n\nconst model = defineModel<string | number>()\n\nconst label = shallowRef<string>()\n\nconst { formProps } = injectFormContext()\n\nconst { size, disabled, readonly } = useFormFallbackProps([formProps ?? {}, props])\n\nconst treeRef = shallowRef<TreeExposed>()\n\nconst dropdownRef = shallowRef<InstanceType<typeof UDropdown>>()\n\n/**清空 */\nconst handleClear = () => {\n model.value = ''\n label.value = undefined\n emit('clear')\n emit('change', undefined)\n emit('update:text', '')\n}\n\nlet changedByEvent = false\nwatch(\n [() => props.data, model],\n ([data, model]) => {\n if (changedByEvent) return\n if (!data?.length || model === undefined) {\n label.value = undefined\n model = undefined\n return\n }\n\n let founded = false\n const childrenKey = props.childrenKey ?? 'children'\n data.some((item) => {\n dfs(\n item,\n (v) => {\n if (v[valueKey.value] === model) {\n label.value = v[labelKey.value]\n founded = true\n return true\n }\n },\n childrenKey\n )\n\n return founded\n })\n },\n { immediate: true }\n)\n\nconst handleSelect = (selected?: string | number, selectedData?: Record<string, any>) => {\n changedByEvent = true\n nextTick(() => {\n changedByEvent = false\n })\n\n model.value = selected ?? ''\n\n if (selectedData) {\n label.value = o(selectedData).get(labelKey.value)\n } else {\n label.value = ''\n }\n\n emit('change', selectedData)\n emit('update:text', label.value)\n dropdownRef.value?.close()\n}\n\nconst handleDropdownVisible = (visible: boolean) => {\n if (!visible) {\n qs.value = ''\n }\n}\n</script>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"tree-select.js","names":["$attrs","$slots"],"sources":["../../../src/components/tree-select/tree-select.vue"],"sourcesContent":["<template>\n <u-dropdown\n v-if=\"!readonly\"\n v-bind=\"$attrs\"\n :class=\"[cls.b, bem.is('disabled', disabled)]\"\n trigger=\"click\"\n :content-class=\"[cls.e('panel'), cls.em('panel', size), contentClass]\"\n :content-style=\"contentStyle\"\n ref=\"dropdownRef\"\n v-model:visible=\"dropdownVisible\"\n :min-width=\"minWidth\"\n :width=\"width\"\n :disabled=\"disabled\"\n @update:visible=\"handleDropdownVisible\"\n @mouseenter=\"hovered = true\"\n @mouseleave=\"hovered = false\"\n >\n <template #trigger>\n <u-input\n ref=\"inputRef\"\n :size=\"size\"\n :disabled=\"disabled\"\n :placeholder=\"inputPlaceholder\"\n :clearable=\"false\"\n :model-value=\"inputValue\"\n @update:model-value=\"handleQueryInput\"\n :native-readonly=\"!filterable || !querying\"\n @click.capture=\"handleTriggerClickCapture\"\n >\n <template #prefix v-if=\"$slots.prefix\">\n <slot name=\"prefix\" />\n </template>\n <template #suffix>\n <transition name=\"zoom-in\" mode=\"out-in\">\n <u-icon\n v-if=\"showClear\"\n :class=\"cls.e('clear')\"\n title=\"清除\"\n key=\"clear\"\n @click.stop=\"handleClear\"\n >\n <Close />\n </u-icon>\n <u-icon v-else :class=\"cls.e('arrow')\" key=\"arrow\"><ArrowDown /></u-icon>\n </transition>\n </template>\n </u-input>\n </template>\n <template #content>\n <!-- 菜单列表 -->\n\n <u-tree\n v-bind=\"treeProps\"\n :selected=\"model\"\n @update:selected=\"handleSelect\"\n ref=\"treeRef\"\n selectable\n :class=\"cls.e('content-tree')\"\n :slots=\"slots\"\n scroll-to-view\n />\n </template>\n </u-dropdown>\n\n <template v-else>\n {{ text || label || FORM_EMPTY_CONTENT }}\n </template>\n</template>\n\n<script lang=\"ts\" setup>\nimport { dfs, o } from '@cat-kit/core'\nimport { useFormFallbackProps } from '@veltra/compositions'\nimport { ArrowDown, Close } from '@veltra/icons/normal'\nimport { bem, fieldKey, FORM_EMPTY_CONTENT } from '@veltra/utils'\nimport { injectFormContext } from '@veltra/utils'\nimport { computed, nextTick, shallowRef, useTemplateRef, watch } from 'vue'\n\nimport type { TreeSelectProps, TreeSelectEmits, TreeExposed, InputExposed } from '../../types'\nimport { UDropdown } from '../dropdown'\nimport { UIcon } from '../icon'\nimport { UInput } from '../input'\nimport { UTree } from '../tree'\nimport type { TreeSlotsScope } from '../tree/di'\n\ndefineOptions({ name: 'UTreeSelect', inheritAttrs: false })\n\nconst props = withDefaults(defineProps<TreeSelectProps>(), {\n labelKey: 'label',\n valueKey: 'value',\n placeholder: '请选择',\n expandAll: false,\n clearable: true,\n disabled: undefined,\n readonly: undefined,\n filterable: false,\n minWidth: '280px'\n})\n\nconst emit = defineEmits<TreeSelectEmits>()\n\nconst slots = defineSlots<{\n /** 默认插槽 */\n default?: (props: TreeSlotsScope) => any\n /** 前缀插槽 */\n prefix?: () => any\n}>()\n\nconst treeProps = computed(() => {\n return o(props as Record<string, any>).omit([\n 'tips',\n 'field',\n 'placeholder',\n 'disabled',\n 'label',\n 'readonly',\n 'contentClass',\n 'contentStyle',\n 'minWidth',\n 'width'\n ])\n})\n\nconst cls = bem('tree-select')\n\nconst labelKey = computed(() => fieldKey(props.labelKey, 'label'))\nconst valueKey = computed(() => fieldKey(props.valueKey, 'value'))\n\n/**过滤 */\nconst qs = shallowRef('')\nwatch(qs, (qs) => {\n treeRef.value?.filter(qs)\n})\n\nconst model = defineModel<string | number>()\n\nconst label = shallowRef<string>()\n\nconst dropdownVisible = shallowRef(false)\n\n/**\n * 是否处于查询态:决定触发输入框显示查询串还是选中标签。\n * 与面板可见状态解耦 —— 选择后立即退出查询态,\n * 不等面板关闭动画结束(否则显示值会延迟一个动画时长才恢复)。\n */\nconst querying = shallowRef(false)\n\nconst inputRef = useTemplateRef<InputExposed>('inputRef')\n\n/** 触发输入框的值:查询态下承载查询串,否则展示选中标签 */\nconst inputValue = computed(() => {\n if (props.filterable && querying.value) return qs.value\n return props.text ?? (model.value ? label.value : undefined)\n})\n\n/** 查询态下已选标签降级为占位提示 */\nconst inputPlaceholder = computed(() => {\n const display = props.text ?? (model.value ? label.value : undefined)\n if (props.filterable && querying.value && display) {\n return display\n }\n return props.placeholder\n})\n\nfunction handleQueryInput(value: string) {\n if (!props.filterable) return\n qs.value = value\n}\n\nconst hovered = shallowRef(false)\n\n/** 悬停且存在选中值时展示清除按钮(替代下拉箭头) */\nconst showClear = computed(() => {\n if (!props.clearable || disabled.value || !hovered.value) return false\n return !!(props.text ?? (model.value ? label.value : undefined))\n})\n\n/**\n * 过滤模式下拦截输入区域的点击:\n * 阻止 dropdown 的 trigger 开合切换,保持面板展开以不中断输入。\n * 非输入区域(箭头、留白)放行,维持原开合行为。\n */\nfunction handleTriggerClickCapture(e: MouseEvent) {\n if (!props.filterable || disabled.value) return\n if (!(e.target instanceof HTMLInputElement)) return\n\n e.stopPropagation()\n if (!dropdownVisible.value) dropdownRef.value?.open()\n}\n\nwatch(dropdownVisible, (visible) => {\n if (visible && props.filterable) {\n // 面板展开后进入查询态并聚焦输入框,可以立即输入查询\n querying.value = true\n nextTick(() => inputRef.value?.el?.focus())\n } else if (!visible) {\n querying.value = false\n }\n})\n\nconst { formProps } = injectFormContext()\n\nconst { size, disabled, readonly } = useFormFallbackProps([formProps ?? {}, props])\n\nconst treeRef = shallowRef<TreeExposed>()\n\nconst dropdownRef = shallowRef<InstanceType<typeof UDropdown>>()\n\n/**清空 */\nconst handleClear = () => {\n model.value = ''\n label.value = undefined\n emit('clear')\n emit('change', undefined)\n emit('update:text', '')\n}\n\nlet changedByEvent = false\nwatch(\n [() => props.data, model],\n ([data, model]) => {\n if (changedByEvent) return\n if (!data?.length || model === undefined) {\n label.value = undefined\n model = undefined\n return\n }\n\n let founded = false\n const childrenKey = props.childrenKey ?? 'children'\n data.some((item) => {\n dfs(\n item,\n (v) => {\n if (v[valueKey.value] === model) {\n label.value = v[labelKey.value]\n founded = true\n return true\n }\n },\n childrenKey\n )\n\n return founded\n })\n },\n { immediate: true }\n)\n\nconst handleSelect = (selected?: string | number, selectedData?: Record<string, any>) => {\n changedByEvent = true\n nextTick(() => {\n changedByEvent = false\n })\n\n model.value = selected ?? ''\n\n if (selectedData) {\n label.value = o(selectedData).get(labelKey.value)\n } else {\n label.value = ''\n }\n\n emit('change', selectedData)\n emit('update:text', label.value)\n // 立即退出查询态,输入框同步恢复显示选中标签\n querying.value = false\n qs.value = ''\n dropdownRef.value?.close()\n}\n\nconst handleDropdownVisible = (visible: boolean) => {\n if (!visible) {\n qs.value = ''\n }\n}\n</script>\n"],"mappings":"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"}
|
|
@@ -17,17 +17,15 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {
|
|
|
17
17
|
"update:modelValue": (value: string | number | undefined) => any;
|
|
18
18
|
} & {
|
|
19
19
|
"update:modelValue": (value?: string | number | undefined) => any;
|
|
20
|
-
change: (selectedData?: Record<string, any> | undefined) => any;
|
|
21
20
|
clear: () => any;
|
|
21
|
+
change: (selectedData?: Record<string, any> | undefined) => any;
|
|
22
22
|
"update:text": (text?: string | undefined) => any;
|
|
23
23
|
}, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
|
|
24
24
|
"onUpdate:modelValue"?: ((value?: string | number | undefined) => any) | undefined;
|
|
25
|
-
onChange?: ((selectedData?: Record<string, any> | undefined) => any) | undefined;
|
|
26
25
|
onClear?: (() => any) | undefined;
|
|
26
|
+
onChange?: ((selectedData?: Record<string, any> | undefined) => any) | undefined;
|
|
27
27
|
"onUpdate:text"?: ((text?: string | undefined) => any) | undefined;
|
|
28
28
|
}>, {
|
|
29
|
-
disabled: boolean;
|
|
30
|
-
readonly: boolean;
|
|
31
29
|
expandAll: boolean;
|
|
32
30
|
labelKey: string;
|
|
33
31
|
valueKey: string;
|
|
@@ -35,6 +33,8 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {
|
|
|
35
33
|
clearable: boolean;
|
|
36
34
|
filterable: boolean;
|
|
37
35
|
minWidth: string;
|
|
36
|
+
disabled: boolean;
|
|
37
|
+
readonly: boolean;
|
|
38
38
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
39
39
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
40
40
|
declare const _default: typeof __VLS_export;
|
package/dist/types/tree.d.ts
CHANGED
|
@@ -33,7 +33,10 @@ interface TreeProps {
|
|
|
33
33
|
childrenKey?: string;
|
|
34
34
|
/** 数据 */
|
|
35
35
|
data?: Record<string, any>[];
|
|
36
|
-
/**
|
|
36
|
+
/**
|
|
37
|
+
* 禁止单选或多选的节点。
|
|
38
|
+
* 在整棵树构建完成后调用,可安全访问 `node.children` / `node.isLeaf`。
|
|
39
|
+
*/
|
|
37
40
|
disabledNode?: (item: Record<string, any>, node: TreeNode$1) => boolean;
|
|
38
41
|
/** 可多选 */
|
|
39
42
|
checkable?: boolean;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@veltra/desktop",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.6",
|
|
4
4
|
"files": [
|
|
5
5
|
"dist",
|
|
6
6
|
"src"
|
|
@@ -57,11 +57,11 @@
|
|
|
57
57
|
"@cat-kit/core": ">=1.1.8",
|
|
58
58
|
"@cat-kit/excel": ">=1.0.0",
|
|
59
59
|
"@cat-kit/fe": "^1.1.8",
|
|
60
|
-
"@veltra/compositions": "1.3.
|
|
61
|
-
"@veltra/directives": "1.3.
|
|
62
|
-
"@veltra/icons": "1.3.
|
|
63
|
-
"@veltra/styles": "1.3.
|
|
64
|
-
"@veltra/utils": "1.3.
|
|
60
|
+
"@veltra/compositions": "1.3.6",
|
|
61
|
+
"@veltra/directives": "1.3.6",
|
|
62
|
+
"@veltra/icons": "1.3.6",
|
|
63
|
+
"@veltra/styles": "1.3.6",
|
|
64
|
+
"@veltra/utils": "1.3.6",
|
|
65
65
|
"vue": ">=3.5.40"
|
|
66
66
|
},
|
|
67
67
|
"devDependencies": {
|
|
@@ -2,7 +2,13 @@
|
|
|
2
2
|
<u-dropdown
|
|
3
3
|
v-if="!readonly"
|
|
4
4
|
v-bind="$attrs"
|
|
5
|
-
:class="[
|
|
5
|
+
:class="[
|
|
6
|
+
cls.b,
|
|
7
|
+
bem.is('disabled', disabled),
|
|
8
|
+
bem.is('multiple', multiple),
|
|
9
|
+
cls.m(size),
|
|
10
|
+
bem.is('focus', multiple && dropdownVisible)
|
|
11
|
+
]"
|
|
6
12
|
:content-class="[cls.e('panel'), cls.em('panel', size)]"
|
|
7
13
|
trigger="click"
|
|
8
14
|
ref="dropdownRef"
|
|
@@ -10,7 +16,7 @@
|
|
|
10
16
|
width="auto"
|
|
11
17
|
@mouseenter="hovered = true"
|
|
12
18
|
@mouseleave="hovered = false"
|
|
13
|
-
@update:visible="
|
|
19
|
+
@update:visible="handleDropdownVisible"
|
|
14
20
|
>
|
|
15
21
|
<template #trigger>
|
|
16
22
|
<!-- 单选展示 -->
|
|
@@ -233,6 +239,13 @@ function handleClear() {
|
|
|
233
239
|
// 过滤
|
|
234
240
|
const qs = shallowRef<string>('')
|
|
235
241
|
|
|
242
|
+
const dropdownVisible = shallowRef(false)
|
|
243
|
+
|
|
244
|
+
const handleDropdownVisible = (visible: boolean) => {
|
|
245
|
+
dropdownVisible.value = visible
|
|
246
|
+
if (!visible) qs.value = ''
|
|
247
|
+
}
|
|
248
|
+
|
|
236
249
|
watch([qs, forest], ([qs, forest]) => {
|
|
237
250
|
const { filterable } = props
|
|
238
251
|
if (!filterable || !qs) {
|
|
@@ -23,6 +23,11 @@ $menu-name: $root-name + '-panel-item';
|
|
|
23
23
|
&:hover {
|
|
24
24
|
border-color: fn.use-var(color, primary);
|
|
25
25
|
}
|
|
26
|
+
|
|
27
|
+
@include m.is(focus) {
|
|
28
|
+
border-color: fn.use-var(color, primary);
|
|
29
|
+
box-shadow: fn.use-var(focus-ring);
|
|
30
|
+
}
|
|
26
31
|
}
|
|
27
32
|
|
|
28
33
|
@include m.size using ($size) {
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
:disabled="disabled"
|
|
11
11
|
@mouseenter.native="hovered = true"
|
|
12
12
|
@mouseleave.native="hovered = false"
|
|
13
|
+
@update:visible="dropdownVisible = $event"
|
|
13
14
|
>
|
|
14
15
|
<template #trigger>
|
|
15
16
|
<input
|
|
@@ -87,8 +88,15 @@ const emit = defineEmits<DateRangePickerEmits>()
|
|
|
87
88
|
|
|
88
89
|
const cls = bem('date-range-picker')
|
|
89
90
|
|
|
91
|
+
const dropdownVisible = shallowRef(false)
|
|
92
|
+
|
|
90
93
|
const className = computed(() => {
|
|
91
|
-
return [
|
|
94
|
+
return [
|
|
95
|
+
cls.b,
|
|
96
|
+
cls.m(size.value),
|
|
97
|
+
bem.is('disabled', disabled.value),
|
|
98
|
+
bem.is('focus', dropdownVisible.value)
|
|
99
|
+
]
|
|
92
100
|
})
|
|
93
101
|
|
|
94
102
|
const { formProps } = injectFormContext()
|
|
@@ -32,6 +32,11 @@ $root-name: date-range-picker;
|
|
|
32
32
|
border-color: fn.use-var(color, primary);
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
+
@include m.is(focus) {
|
|
36
|
+
border-color: fn.use-var(color, primary);
|
|
37
|
+
box-shadow: fn.use-var(focus-ring);
|
|
38
|
+
}
|
|
39
|
+
|
|
35
40
|
@include m.e(input) {
|
|
36
41
|
outline: none;
|
|
37
42
|
border: none;
|
|
@@ -7,11 +7,11 @@
|
|
|
7
7
|
>
|
|
8
8
|
<u-tip v-if="tips" :content="tips" :class="cls.e('tips')" :show-delay="500">
|
|
9
9
|
<span :class="cls.e('tip-label')">
|
|
10
|
-
<slot name="label">{{ label }}
|
|
10
|
+
<slot name="label">{{ label }}{{ labelPosition === 'top' ? '' : ':' }}</slot>
|
|
11
11
|
</span>
|
|
12
12
|
</u-tip>
|
|
13
13
|
<template v-else>
|
|
14
|
-
<slot name="label">{{ label }}
|
|
14
|
+
<slot name="label">{{ label }}{{ labelPosition === 'top' ? '' : ':' }}</slot>
|
|
15
15
|
</template>
|
|
16
16
|
</label>
|
|
17
17
|
|
|
@@ -28,7 +28,7 @@ $root-name: form-item;
|
|
|
28
28
|
color: fn.use-var(text-color, main);
|
|
29
29
|
text-align: right;
|
|
30
30
|
line-height: 1.3;
|
|
31
|
-
font-weight:
|
|
31
|
+
font-weight: 400;
|
|
32
32
|
|
|
33
33
|
@include m.flex($justify: flex-end);
|
|
34
34
|
|
|
@@ -99,6 +99,7 @@ $root-name: form-item;
|
|
|
99
99
|
padding-right: 0;
|
|
100
100
|
padding-bottom: 4px;
|
|
101
101
|
text-align: left;
|
|
102
|
+
color: fn.use-var(text-color, second);
|
|
102
103
|
justify-content: flex-start;
|
|
103
104
|
}
|
|
104
105
|
}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
v-bind="$attrs"
|
|
5
5
|
trigger="click"
|
|
6
6
|
ref="dropdownRef"
|
|
7
|
-
:class="[cls.b, cls.m(size), bem.is('disabled', disabled)]"
|
|
7
|
+
:class="[cls.b, cls.m(size), bem.is('disabled', disabled), bem.is('focus', dropdownVisible)]"
|
|
8
8
|
:content-class="[cls.e('panel'), cls.em('panel', size), contentClass]"
|
|
9
9
|
:content-style="contentStyle"
|
|
10
10
|
:min-width="minWidth"
|
|
@@ -16,11 +16,11 @@
|
|
|
16
16
|
>
|
|
17
17
|
<!-- 触发 -->
|
|
18
18
|
<template #trigger>
|
|
19
|
-
<span :class="cls.e('placeholder')" v-
|
|
19
|
+
<span :class="cls.e('placeholder')" v-if="!filterable && !model?.length">
|
|
20
20
|
{{ placeholder }}
|
|
21
21
|
</span>
|
|
22
22
|
|
|
23
|
-
<div v-if="model?.length" :class="cls.e('tags')">
|
|
23
|
+
<div v-if="model?.length || filterable" :class="cls.e('tags')">
|
|
24
24
|
<u-tag
|
|
25
25
|
v-for="option of tags"
|
|
26
26
|
:key="option[valueKey]"
|
|
@@ -31,6 +31,19 @@
|
|
|
31
31
|
{{ option[labelKey] }}
|
|
32
32
|
</u-tag>
|
|
33
33
|
<u-tag v-if="restTag" size="small"> {{ restTag }}+ </u-tag>
|
|
34
|
+
|
|
35
|
+
<!-- 内嵌查询输入框:承载过滤与回车创建 -->
|
|
36
|
+
<input
|
|
37
|
+
v-if="filterable"
|
|
38
|
+
ref="inputRef"
|
|
39
|
+
:class="cls.e('input')"
|
|
40
|
+
v-model="queryString"
|
|
41
|
+
:placeholder="model?.length ? '' : placeholder"
|
|
42
|
+
:disabled="disabled"
|
|
43
|
+
@click.stop="handleInputClick"
|
|
44
|
+
@focus="handleInputFocus"
|
|
45
|
+
@keydown.enter.prevent="handleCreateByEnter"
|
|
46
|
+
/>
|
|
34
47
|
</div>
|
|
35
48
|
|
|
36
49
|
<transition name="zoom-in" mode="out-in">
|
|
@@ -62,19 +75,6 @@
|
|
|
62
75
|
<span> 已选 {{ model?.length }}/{{ max ?? options?.length ?? 0 }} </span>
|
|
63
76
|
</div>
|
|
64
77
|
|
|
65
|
-
<!-- 过滤器 -->
|
|
66
|
-
<div v-if="filterable" :class="cls.e('content-filter')">
|
|
67
|
-
<u-input
|
|
68
|
-
placeholder="输入关键字进行过滤"
|
|
69
|
-
v-model="queryString"
|
|
70
|
-
@keydown.enter.prevent="handleCreateByEnter"
|
|
71
|
-
>
|
|
72
|
-
<template #suffix>
|
|
73
|
-
<u-icon><Search /></u-icon>
|
|
74
|
-
</template>
|
|
75
|
-
</u-input>
|
|
76
|
-
</div>
|
|
77
|
-
|
|
78
78
|
<!-- 多选列表 -->
|
|
79
79
|
<!--
|
|
80
80
|
虚拟化启用时内容容器 height 由 useVirtualizer 命令式写入;
|
|
@@ -143,10 +143,18 @@
|
|
|
143
143
|
<script lang="ts" setup>
|
|
144
144
|
import { o as chainObj } from '@cat-kit/core'
|
|
145
145
|
import { useFormFallbackProps, useVirtualizer } from '@veltra/compositions'
|
|
146
|
-
import { ArrowDown, Close
|
|
146
|
+
import { ArrowDown, Close } from '@veltra/icons/normal'
|
|
147
147
|
import { bem, fieldKey, FORM_EMPTY_CONTENT } from '@veltra/utils'
|
|
148
148
|
import { injectFormContext } from '@veltra/utils'
|
|
149
|
-
import {
|
|
149
|
+
import {
|
|
150
|
+
computed,
|
|
151
|
+
nextTick,
|
|
152
|
+
shallowRef,
|
|
153
|
+
shallowReactive,
|
|
154
|
+
watch,
|
|
155
|
+
provide,
|
|
156
|
+
useTemplateRef
|
|
157
|
+
} from 'vue'
|
|
150
158
|
|
|
151
159
|
import type {
|
|
152
160
|
MultiSelectEmits,
|
|
@@ -158,7 +166,6 @@ import { UCheckbox } from '../checkbox'
|
|
|
158
166
|
import { UDropdown } from '../dropdown'
|
|
159
167
|
import { UEmpty } from '../empty'
|
|
160
168
|
import { UIcon } from '../icon'
|
|
161
|
-
import { UInput } from '../input'
|
|
162
169
|
import { UScroll } from '../scroll'
|
|
163
170
|
import { useOptions } from '../select/use-options'
|
|
164
171
|
import { UTag } from '../tag'
|
|
@@ -319,12 +326,35 @@ const restTag = computed(() => {
|
|
|
319
326
|
return (model.value?.length ?? 0) - tags.value.length
|
|
320
327
|
})
|
|
321
328
|
|
|
329
|
+
const dropdownVisible = shallowRef(false)
|
|
330
|
+
|
|
331
|
+
const inputRef = useTemplateRef<HTMLInputElement>('inputRef')
|
|
332
|
+
|
|
322
333
|
const handleDropdownVisible = (visible: boolean) => {
|
|
334
|
+
dropdownVisible.value = visible
|
|
323
335
|
if (!visible) {
|
|
324
336
|
queryString.value = ''
|
|
325
337
|
}
|
|
326
338
|
}
|
|
327
339
|
|
|
340
|
+
/**
|
|
341
|
+
* 拦截输入区域的点击(@click.stop):阻止 dropdown 的 trigger 开合切换,
|
|
342
|
+
* 保持面板展开以不中断输入。
|
|
343
|
+
*/
|
|
344
|
+
const handleInputClick = () => {
|
|
345
|
+
if (!dropdownVisible.value) dropdownRef.value?.open()
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
const handleInputFocus = () => {
|
|
349
|
+
if (!dropdownVisible.value) dropdownRef.value?.open()
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/** 勾选后把焦点还给输入框,便于连续输入过滤 */
|
|
353
|
+
const refocusInput = () => {
|
|
354
|
+
if (!filterable.value) return
|
|
355
|
+
nextTick(() => inputRef.value?.focus())
|
|
356
|
+
}
|
|
357
|
+
|
|
328
358
|
const handleCheck = (option: Record<string, any>, checked: boolean) => {
|
|
329
359
|
if (checked) {
|
|
330
360
|
if (option.__isTemp && props.creatable) {
|
|
@@ -352,6 +382,7 @@ const handleCheck = (option: Record<string, any>, checked: boolean) => {
|
|
|
352
382
|
|
|
353
383
|
emitChange()
|
|
354
384
|
dropdownRef.value?.updateDropdown()
|
|
385
|
+
refocusInput()
|
|
355
386
|
}
|
|
356
387
|
|
|
357
388
|
/** 全选 */
|
|
@@ -36,13 +36,18 @@ $root-name: multi-select;
|
|
|
36
36
|
border-color: fn.use-var(color, primary);
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
+
@include m.is(focus) {
|
|
40
|
+
border-color: fn.use-var(color, primary);
|
|
41
|
+
box-shadow: fn.use-var(focus-ring);
|
|
42
|
+
}
|
|
43
|
+
|
|
39
44
|
@include m.e(ripple) {
|
|
40
45
|
background-color: fn.use-var(color, primary, light-7);
|
|
41
46
|
opacity: 0.5;
|
|
42
47
|
}
|
|
43
48
|
|
|
44
49
|
@include m.e(options) {
|
|
45
|
-
max-height:
|
|
50
|
+
max-height: 240px;
|
|
46
51
|
}
|
|
47
52
|
|
|
48
53
|
@include m.e(options-wrap) {
|
|
@@ -79,6 +84,27 @@ $root-name: multi-select;
|
|
|
79
84
|
@include m.flex($justify: flex-start, $align: center, $wrap: wrap);
|
|
80
85
|
}
|
|
81
86
|
|
|
87
|
+
@include m.e(input) {
|
|
88
|
+
flex: 1;
|
|
89
|
+
min-width: 60px;
|
|
90
|
+
padding: 0;
|
|
91
|
+
margin: 0;
|
|
92
|
+
border: none;
|
|
93
|
+
outline: none;
|
|
94
|
+
background: transparent;
|
|
95
|
+
font: inherit;
|
|
96
|
+
color: fn.use-var(text-color, main);
|
|
97
|
+
cursor: text;
|
|
98
|
+
|
|
99
|
+
&::placeholder {
|
|
100
|
+
color: fn.use-var(text-color, placeholder);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
&:disabled {
|
|
104
|
+
cursor: not-allowed;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
82
108
|
@include m.e(readonly-tags) {
|
|
83
109
|
padding-left: 0;
|
|
84
110
|
padding-right: 0;
|
|
@@ -104,9 +130,6 @@ $root-name: multi-select;
|
|
|
104
130
|
|
|
105
131
|
@include m.e(panel) {
|
|
106
132
|
@include m.size using ($size) {
|
|
107
|
-
@include m.bem($root-name, content-filter) {
|
|
108
|
-
padding: calc(fn.use-var(gap, $size) / 2) fn.use-var(gap, $size);
|
|
109
|
-
}
|
|
110
133
|
@include m.bem($root-name, content-header) {
|
|
111
134
|
padding: calc(fn.use-var(gap, $size) / 2) calc(fn.use-var(gap, $size) * 2);
|
|
112
135
|
border-bottom: fn.use-var(border);
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<u-dropdown
|
|
3
3
|
v-if="!readonly"
|
|
4
4
|
v-bind="$attrs"
|
|
5
|
-
:class="[cls.b, cls.m(size), bem.is('disabled', disabled)]"
|
|
5
|
+
:class="[cls.b, cls.m(size), bem.is('disabled', disabled), bem.is('focus', dropdownVisible)]"
|
|
6
6
|
trigger="click"
|
|
7
7
|
:content-class="[cls.e('panel'), cls.em('panel', size), contentClass]"
|
|
8
8
|
:content-style="contentStyle"
|
|
@@ -16,12 +16,12 @@
|
|
|
16
16
|
>
|
|
17
17
|
<template #trigger>
|
|
18
18
|
<!-- 默认展示 -->
|
|
19
|
-
<span :class="cls.e('placeholder')" v-
|
|
19
|
+
<span :class="cls.e('placeholder')" v-if="!filterable && !tags.length">
|
|
20
20
|
{{ placeholder }}
|
|
21
21
|
</span>
|
|
22
22
|
|
|
23
23
|
<!-- 选择的数据项 -->
|
|
24
|
-
<div v-if="tags.length" :class="cls.e('tags')">
|
|
24
|
+
<div v-if="tags.length || filterable" :class="cls.e('tags')">
|
|
25
25
|
<u-tag
|
|
26
26
|
v-for="(tag, index) in visibleTags"
|
|
27
27
|
:key="tag[valueKey]"
|
|
@@ -31,6 +31,18 @@
|
|
|
31
31
|
{{ tag[labelKey] }}
|
|
32
32
|
</u-tag>
|
|
33
33
|
<u-tag v-if="hiddenCount > 0">+{{ hiddenCount }}</u-tag>
|
|
34
|
+
|
|
35
|
+
<!-- 内嵌查询输入框:承载过滤 -->
|
|
36
|
+
<input
|
|
37
|
+
v-if="filterable"
|
|
38
|
+
ref="inputRef"
|
|
39
|
+
:class="cls.e('input')"
|
|
40
|
+
v-model="qs"
|
|
41
|
+
:placeholder="tags.length ? '' : placeholder"
|
|
42
|
+
:disabled="disabled"
|
|
43
|
+
@click.stop="handleInputClick"
|
|
44
|
+
@focus="handleInputFocus"
|
|
45
|
+
/>
|
|
34
46
|
</div>
|
|
35
47
|
<!-- 清空 icon -->
|
|
36
48
|
<transition name="zoom-in" mode="out-in">
|
|
@@ -59,14 +71,6 @@
|
|
|
59
71
|
{{ allExpanded ? '收起全部' : '展开全部' }}
|
|
60
72
|
</u-button>
|
|
61
73
|
</div>
|
|
62
|
-
<!-- 过滤器 -->
|
|
63
|
-
<div v-if="filterable" :class="[cls.e('content-filter'), cls.m(size)]">
|
|
64
|
-
<u-input placeholder="输入关键字进行过滤" v-model="qs">
|
|
65
|
-
<template #suffix>
|
|
66
|
-
<u-icon><Search /></u-icon>
|
|
67
|
-
</template>
|
|
68
|
-
</u-input>
|
|
69
|
-
</div>
|
|
70
74
|
<!-- 菜单列表 -->
|
|
71
75
|
<u-tree
|
|
72
76
|
v-bind="treeProps"
|
|
@@ -98,10 +102,10 @@
|
|
|
98
102
|
<script lang="ts" setup>
|
|
99
103
|
import { dfs, o } from '@cat-kit/core'
|
|
100
104
|
import { useFormFallbackProps } from '@veltra/compositions'
|
|
101
|
-
import { ArrowDown, Close
|
|
105
|
+
import { ArrowDown, Close } from '@veltra/icons/normal'
|
|
102
106
|
import { bem, fieldKey, FORM_EMPTY_CONTENT } from '@veltra/utils'
|
|
103
107
|
import { injectFormContext } from '@veltra/utils'
|
|
104
|
-
import { computed, nextTick, shallowRef, watch } from 'vue'
|
|
108
|
+
import { computed, nextTick, shallowRef, useTemplateRef, watch } from 'vue'
|
|
105
109
|
|
|
106
110
|
import type { MultiTreeSelectProps, MultiTreeSelectEmits, TreeExposed } from '../../types'
|
|
107
111
|
import type { DropdownExposed } from '../../types'
|
|
@@ -109,7 +113,6 @@ import { UButton } from '../button'
|
|
|
109
113
|
import { UCheckbox } from '../checkbox'
|
|
110
114
|
import { UDropdown } from '../dropdown'
|
|
111
115
|
import { UIcon } from '../icon'
|
|
112
|
-
import { UInput } from '../input'
|
|
113
116
|
import { UTag } from '../tag'
|
|
114
117
|
import { UTree } from '../tree'
|
|
115
118
|
import type { TreeSlotsScope } from '../tree/di'
|
|
@@ -306,9 +309,26 @@ const hiddenCount = computed(() => {
|
|
|
306
309
|
return 0
|
|
307
310
|
})
|
|
308
311
|
|
|
312
|
+
const dropdownVisible = shallowRef(false)
|
|
313
|
+
|
|
314
|
+
const inputRef = useTemplateRef<HTMLInputElement>('inputRef')
|
|
315
|
+
|
|
309
316
|
const handleDropdownVisible = (visible: boolean) => {
|
|
317
|
+
dropdownVisible.value = visible
|
|
310
318
|
if (!visible) {
|
|
311
319
|
qs.value = ''
|
|
312
320
|
}
|
|
313
321
|
}
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* 拦截输入区域的点击(@click.stop):阻止 dropdown 的 trigger 开合切换,
|
|
325
|
+
* 保持面板展开以不中断输入。
|
|
326
|
+
*/
|
|
327
|
+
const handleInputClick = () => {
|
|
328
|
+
if (!dropdownVisible.value) dropdownRef.value?.open()
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
const handleInputFocus = () => {
|
|
332
|
+
if (!dropdownVisible.value) dropdownRef.value?.open()
|
|
333
|
+
}
|
|
314
334
|
</script>
|
|
@@ -22,6 +22,11 @@ $root-name: multi-tree-select;
|
|
|
22
22
|
border-color: fn.use-var(color, primary);
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
@include m.is(focus) {
|
|
26
|
+
border-color: fn.use-var(color, primary);
|
|
27
|
+
box-shadow: fn.use-var(focus-ring);
|
|
28
|
+
}
|
|
29
|
+
|
|
25
30
|
@include m.size using ($size) {
|
|
26
31
|
min-height: fn.use-var(form-component-height, $size);
|
|
27
32
|
border-radius: fn.use-var(radius, $size);
|
|
@@ -58,16 +63,33 @@ $root-name: multi-tree-select;
|
|
|
58
63
|
color: fn.use-var(text-color, placeholder);
|
|
59
64
|
}
|
|
60
65
|
|
|
61
|
-
@include m.e(filter) {
|
|
62
|
-
margin-bottom: 4px;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
66
|
@include m.e(tags) {
|
|
66
67
|
flex-grow: 1;
|
|
67
68
|
overflow: hidden;
|
|
68
69
|
@include m.flex($justify: flex-start, $align: center, $wrap: wrap);
|
|
69
70
|
}
|
|
70
71
|
|
|
72
|
+
@include m.e(input) {
|
|
73
|
+
flex: 1;
|
|
74
|
+
min-width: 60px;
|
|
75
|
+
padding: 0;
|
|
76
|
+
margin: 0;
|
|
77
|
+
border: none;
|
|
78
|
+
outline: none;
|
|
79
|
+
background: transparent;
|
|
80
|
+
font: inherit;
|
|
81
|
+
color: fn.use-var(text-color, main);
|
|
82
|
+
cursor: text;
|
|
83
|
+
|
|
84
|
+
&::placeholder {
|
|
85
|
+
color: fn.use-var(text-color, placeholder);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
&:disabled {
|
|
89
|
+
cursor: not-allowed;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
71
93
|
@include m.e(readonly-tags) {
|
|
72
94
|
padding-left: 0;
|
|
73
95
|
padding-right: 0;
|
|
@@ -90,21 +112,18 @@ $root-name: multi-tree-select;
|
|
|
90
112
|
|
|
91
113
|
@include m.e(panel) {
|
|
92
114
|
@include m.size using ($size) {
|
|
93
|
-
@include m.bem($root-name, content-filter) {
|
|
94
|
-
padding: calc(fn.use-var(gap, $size) / 2) fn.use-var(gap, $size);
|
|
95
|
-
}
|
|
96
115
|
@include m.bem($root-name, content-header) {
|
|
97
116
|
padding: calc(fn.use-var(gap, $size) / 2) fn.use-var(gap, $size);
|
|
98
117
|
border-bottom: fn.use-var(border);
|
|
99
118
|
}
|
|
100
119
|
|
|
101
120
|
@include m.bem($root-name, content-tree) {
|
|
102
|
-
padding:
|
|
121
|
+
padding: fn.use-var(gap, $size);
|
|
103
122
|
}
|
|
104
123
|
}
|
|
105
124
|
}
|
|
106
125
|
|
|
107
126
|
@include m.e(content-tree) {
|
|
108
|
-
max-height:
|
|
127
|
+
max-height: 240px;
|
|
109
128
|
}
|
|
110
129
|
}
|