@veltra/desktop 1.3.7 → 1.3.8
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.vue.d.ts +5 -5
- 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.vue.d.ts +2 -2
- package/dist/components/input/input.vue.d.ts +4 -4
- package/dist/components/multi-select/multi-select.vue.d.ts +3 -3
- package/dist/components/multi-tree-select/multi-tree-select.vue.d.ts +5 -5
- package/dist/components/number-input/number-input.vue.d.ts +4 -4
- package/dist/components/number-range-input/number-range-input.vue.d.ts +2 -2
- package/dist/components/password-input/password-input.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 +42 -51
- package/dist/components/select/select.js.map +1 -1
- package/dist/components/select/select.vue.d.ts +6 -14
- package/dist/components/steps/steps.vue.d.ts +3 -3
- package/dist/components/textarea/textarea.vue.d.ts +4 -4
- package/dist/components/tree-select/tree-select.js +40 -33
- package/dist/components/tree-select/tree-select.js.map +1 -1
- package/dist/components/tree-select/tree-select.vue.d.ts +5 -5
- package/dist/types/select.d.ts +5 -4
- package/dist/types/tree-select.d.ts +4 -2
- package/package.json +6 -6
- package/src/components/select/__test__/select.test.ts +77 -2
- package/src/components/select/select.vue +39 -47
- package/src/components/tree-select/__test__/tree-select.test.ts +133 -0
- package/src/components/tree-select/tree-select.vue +44 -38
- package/src/types/select.ts +5 -4
- package/src/types/tree-select.ts +4 -3
|
@@ -6,11 +6,11 @@ type __VLS_Slots = {
|
|
|
6
6
|
default?: () => VNode[];
|
|
7
7
|
};
|
|
8
8
|
declare const __VLS_base: import("vue").DefineComponent<ActionGroupProps, _ActionGroupExposed, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<ActionGroupProps> & Readonly<{}>, {
|
|
9
|
-
size: "small" | "default" | "large";
|
|
10
9
|
type: import("@veltra/utils").ColorType;
|
|
10
|
+
size: "small" | "default" | "large";
|
|
11
11
|
text: boolean;
|
|
12
|
-
max: number;
|
|
13
12
|
circle: boolean;
|
|
13
|
+
max: number;
|
|
14
14
|
loading: boolean;
|
|
15
15
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
16
16
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
@@ -14,8 +14,8 @@ declare const __VLS_base: import("vue").DefineComponent<ActionProps, {}, {}, {},
|
|
|
14
14
|
}, string, import("vue").PublicProps, Readonly<ActionProps> & Readonly<{
|
|
15
15
|
onRun?: (() => any) | undefined;
|
|
16
16
|
}>, {
|
|
17
|
-
size: import("@veltra/utils").ComponentSize;
|
|
18
17
|
type: ButtonType;
|
|
18
|
+
size: import("@veltra/utils").ComponentSize;
|
|
19
19
|
text: boolean;
|
|
20
20
|
circle: boolean;
|
|
21
21
|
loading: boolean;
|
|
@@ -23,11 +23,11 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, _Auto
|
|
|
23
23
|
"onUpdate:modelValue"?: ((value: string) => any) | undefined;
|
|
24
24
|
onSelect?: ((value: string) => any) | undefined;
|
|
25
25
|
}>, {
|
|
26
|
-
disabled: boolean;
|
|
27
|
-
readonly: boolean;
|
|
28
26
|
placeholder: string;
|
|
29
27
|
clearable: boolean;
|
|
30
28
|
allowCustom: boolean;
|
|
29
|
+
disabled: boolean;
|
|
30
|
+
readonly: boolean;
|
|
31
31
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
32
32
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
33
33
|
declare const _default: typeof __VLS_export;
|
|
@@ -3,26 +3,26 @@ import "../../types/index.js";
|
|
|
3
3
|
//#region src/components/cascade/cascade.vue.d.ts
|
|
4
4
|
declare const __VLS_export: import("vue").DefineComponent<CascadeProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
5
5
|
"update:modelValue": (value?: string | string[] | undefined) => any;
|
|
6
|
-
change: (...args: [item?: Record<string, any> | undefined] | [items: Record<string, any>[]]) => any;
|
|
7
6
|
clear: () => any;
|
|
7
|
+
change: (...args: [item?: Record<string, any> | undefined] | [items: Record<string, any>[]]) => any;
|
|
8
8
|
"update:label": (label?: string | string[] | undefined) => any;
|
|
9
9
|
}, string, import("vue").PublicProps, Readonly<CascadeProps> & Readonly<{
|
|
10
10
|
"onUpdate:modelValue"?: ((value?: string | string[] | undefined) => any) | undefined;
|
|
11
|
-
onChange?: ((...args: [item?: Record<string, any> | undefined] | [items: Record<string, any>[]]) => any) | undefined;
|
|
12
11
|
onClear?: (() => any) | undefined;
|
|
12
|
+
onChange?: ((...args: [item?: Record<string, any> | undefined] | [items: Record<string, any>[]]) => any) | undefined;
|
|
13
13
|
"onUpdate:label"?: ((label?: string | string[] | undefined) => any) | undefined;
|
|
14
14
|
}>, {
|
|
15
|
-
disabled: boolean;
|
|
16
|
-
readonly: boolean;
|
|
17
15
|
labelKey: string;
|
|
18
16
|
valueKey: string;
|
|
19
17
|
childrenKey: string;
|
|
20
18
|
data: Record<string, any>[];
|
|
21
19
|
placeholder: string;
|
|
22
20
|
clearable: boolean;
|
|
21
|
+
disabled: boolean;
|
|
22
|
+
readonly: boolean;
|
|
23
23
|
filterable: boolean;
|
|
24
|
-
separator: string;
|
|
25
24
|
visibilityLimit: number;
|
|
25
|
+
separator: string;
|
|
26
26
|
showFullPath: boolean;
|
|
27
27
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
28
28
|
declare const _default: typeof __VLS_export;
|
|
@@ -18,9 +18,9 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {
|
|
|
18
18
|
"onUpdate:modelValue"?: ((checked: boolean) => any) | undefined;
|
|
19
19
|
onChange?: ((checked: boolean) => any) | undefined;
|
|
20
20
|
}>, {
|
|
21
|
+
type: import("@veltra/utils").ColorType;
|
|
21
22
|
disabled: boolean;
|
|
22
23
|
readonly: boolean;
|
|
23
|
-
type: import("@veltra/utils").ColorType;
|
|
24
24
|
round: boolean;
|
|
25
25
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
26
26
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
@@ -13,10 +13,10 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {},
|
|
|
13
13
|
}, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
|
|
14
14
|
"onUpdate:modelValue"?: ((value: any[]) => any) | undefined;
|
|
15
15
|
}>, {
|
|
16
|
-
disabled: boolean;
|
|
17
|
-
readonly: boolean;
|
|
18
16
|
labelKey: string;
|
|
19
17
|
valueKey: string;
|
|
18
|
+
disabled: boolean;
|
|
19
|
+
readonly: boolean;
|
|
20
20
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
21
21
|
declare const _default: typeof __VLS_export;
|
|
22
22
|
//#endregion
|
|
@@ -12,12 +12,12 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {},
|
|
|
12
12
|
"update:lang": (value: CodeEditorLang | undefined) => any;
|
|
13
13
|
} & {
|
|
14
14
|
"update:modelValue": (value: string) => any;
|
|
15
|
-
"update:lang": (value: CodeEditorLang | undefined) => any;
|
|
16
15
|
change: (value: string) => any;
|
|
16
|
+
"update:lang": (value: CodeEditorLang | undefined) => any;
|
|
17
17
|
}, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
|
|
18
18
|
"onUpdate:modelValue"?: ((value: string) => any) | undefined;
|
|
19
|
-
"onUpdate:lang"?: ((value: CodeEditorLang | undefined) => any) | undefined;
|
|
20
19
|
onChange?: ((value: string) => any) | undefined;
|
|
20
|
+
"onUpdate:lang"?: ((value: CodeEditorLang | undefined) => any) | undefined;
|
|
21
21
|
}>, {
|
|
22
22
|
disabled: boolean;
|
|
23
23
|
readonly: boolean;
|
|
@@ -8,8 +8,8 @@ declare const __VLS_export: import("vue").DefineComponent<DatePanelProps, {}, {}
|
|
|
8
8
|
"onSelect:range-date"?: ((rangeDate?: [import("@cat-kit/core").Dater, import("@cat-kit/core").Dater] | undefined) => any) | undefined;
|
|
9
9
|
"onSelect:date"?: ((date: import("@cat-kit/core").Dater) => any) | undefined;
|
|
10
10
|
}>, {
|
|
11
|
-
size: import("@veltra/utils").ComponentSize;
|
|
12
11
|
type: "date" | "month" | "year";
|
|
12
|
+
size: import("@veltra/utils").ComponentSize;
|
|
13
13
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
14
14
|
declare const _default: typeof __VLS_export;
|
|
15
15
|
//#endregion
|
|
@@ -6,11 +6,11 @@ declare const __VLS_export: import("vue").DefineComponent<DatePickerProps, {}, {
|
|
|
6
6
|
}, string, import("vue").PublicProps, Readonly<DatePickerProps> & Readonly<{
|
|
7
7
|
"onUpdate:modelValue"?: ((value?: string | number | Date | undefined) => any) | undefined;
|
|
8
8
|
}>, {
|
|
9
|
-
disabled: boolean;
|
|
10
|
-
readonly: boolean;
|
|
11
9
|
type: "date" | "month" | "year";
|
|
12
10
|
placeholder: string;
|
|
13
11
|
clearable: boolean;
|
|
12
|
+
disabled: boolean;
|
|
13
|
+
readonly: boolean;
|
|
14
14
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
15
15
|
declare const _default: typeof __VLS_export;
|
|
16
16
|
//#endregion
|
|
@@ -6,11 +6,11 @@ declare const __VLS_export: import("vue").DefineComponent<DateRangePickerProps,
|
|
|
6
6
|
}, string, import("vue").PublicProps, Readonly<DateRangePickerProps> & Readonly<{
|
|
7
7
|
"onUpdate:modelValue"?: ((value?: [string, string] | undefined) => any) | undefined;
|
|
8
8
|
}>, {
|
|
9
|
-
disabled: boolean;
|
|
10
|
-
readonly: boolean;
|
|
11
9
|
type: "date" | "month" | "year";
|
|
12
10
|
placeholder: [string, string];
|
|
13
11
|
clearable: boolean;
|
|
12
|
+
disabled: boolean;
|
|
13
|
+
readonly: boolean;
|
|
14
14
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
15
15
|
declare const _default: typeof __VLS_export;
|
|
16
16
|
//#endregion
|
|
@@ -16,8 +16,8 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, _Inpu
|
|
|
16
16
|
"update:modelValue": (value: string | undefined) => any;
|
|
17
17
|
} & {
|
|
18
18
|
"update:modelValue": (value: string) => any;
|
|
19
|
-
change: (value: string) => any;
|
|
20
19
|
clear: () => any;
|
|
20
|
+
change: (value: string) => any;
|
|
21
21
|
"suffix:click": (value?: string | undefined) => any;
|
|
22
22
|
"prefix:click": (value?: string | undefined) => any;
|
|
23
23
|
focus: (value?: string | undefined) => any;
|
|
@@ -25,18 +25,18 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, _Inpu
|
|
|
25
25
|
"native:input": (ev: Event) => any;
|
|
26
26
|
}, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
|
|
27
27
|
"onUpdate:modelValue"?: ((value: string) => any) | undefined;
|
|
28
|
-
onChange?: ((value: string) => any) | undefined;
|
|
29
28
|
onClear?: (() => any) | undefined;
|
|
29
|
+
onChange?: ((value: string) => any) | undefined;
|
|
30
30
|
"onSuffix:click"?: ((value?: string | undefined) => any) | undefined;
|
|
31
31
|
"onPrefix:click"?: ((value?: string | undefined) => any) | undefined;
|
|
32
32
|
onFocus?: ((value?: string | undefined) => any) | undefined;
|
|
33
33
|
onBlur?: ((value?: string | undefined) => any) | undefined;
|
|
34
34
|
"onNative:input"?: ((ev: Event) => any) | undefined;
|
|
35
35
|
}>, {
|
|
36
|
-
disabled: boolean;
|
|
37
|
-
readonly: boolean;
|
|
38
36
|
placeholder: string;
|
|
39
37
|
clearable: boolean;
|
|
38
|
+
disabled: boolean;
|
|
39
|
+
readonly: boolean;
|
|
40
40
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
41
41
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
42
42
|
declare const _default: typeof __VLS_export;
|
|
@@ -27,13 +27,13 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {
|
|
|
27
27
|
"onUpdate:modelValue"?: ((value: any[]) => any) | undefined;
|
|
28
28
|
onChange?: ((options: Record<string, any>[]) => any) | undefined;
|
|
29
29
|
}>, {
|
|
30
|
-
disabled: boolean;
|
|
31
|
-
readonly: boolean;
|
|
32
|
-
minWidth: string;
|
|
33
30
|
labelKey: string;
|
|
34
31
|
valueKey: string;
|
|
35
32
|
placeholder: string;
|
|
36
33
|
clearable: boolean;
|
|
34
|
+
disabled: boolean;
|
|
35
|
+
readonly: boolean;
|
|
36
|
+
minWidth: string;
|
|
37
37
|
visibilityLimit: number;
|
|
38
38
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
39
39
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
@@ -14,22 +14,22 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {
|
|
|
14
14
|
"update:modelValue": (value: (string | number)[]) => any;
|
|
15
15
|
} & {
|
|
16
16
|
"update:modelValue": (value: any[]) => any;
|
|
17
|
-
change: (checked: Record<string, any>[]) => any;
|
|
18
17
|
clear: () => any;
|
|
18
|
+
change: (checked: Record<string, any>[]) => any;
|
|
19
19
|
}, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
|
|
20
20
|
"onUpdate:modelValue"?: ((value: any[]) => any) | undefined;
|
|
21
|
-
onChange?: ((checked: Record<string, any>[]) => any) | undefined;
|
|
22
21
|
onClear?: (() => any) | undefined;
|
|
22
|
+
onChange?: ((checked: Record<string, any>[]) => any) | undefined;
|
|
23
23
|
}>, {
|
|
24
|
-
disabled: boolean;
|
|
25
|
-
readonly: boolean;
|
|
26
|
-
minWidth: string;
|
|
27
24
|
expandAll: boolean;
|
|
28
25
|
labelKey: string;
|
|
29
26
|
valueKey: string;
|
|
30
27
|
placeholder: string;
|
|
31
28
|
clearable: boolean;
|
|
29
|
+
disabled: boolean;
|
|
30
|
+
readonly: boolean;
|
|
32
31
|
filterable: boolean;
|
|
32
|
+
minWidth: string;
|
|
33
33
|
visibilityLimit: number;
|
|
34
34
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
35
35
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
@@ -15,17 +15,17 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {
|
|
|
15
15
|
"update:modelValue": (value: number | undefined) => any;
|
|
16
16
|
} & {
|
|
17
17
|
"update:modelValue": (value?: number | undefined) => any;
|
|
18
|
-
change: (value?: number | undefined) => any;
|
|
19
18
|
clear: () => any;
|
|
19
|
+
change: (value?: number | undefined) => any;
|
|
20
20
|
}, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
|
|
21
21
|
"onUpdate:modelValue"?: ((value?: number | undefined) => any) | undefined;
|
|
22
|
-
onChange?: ((value?: number | undefined) => any) | undefined;
|
|
23
22
|
onClear?: (() => any) | undefined;
|
|
23
|
+
onChange?: ((value?: number | undefined) => any) | undefined;
|
|
24
24
|
}>, {
|
|
25
|
-
disabled: boolean;
|
|
26
|
-
readonly: boolean;
|
|
27
25
|
placeholder: string;
|
|
28
26
|
clearable: boolean;
|
|
27
|
+
disabled: boolean;
|
|
28
|
+
readonly: boolean;
|
|
29
29
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
30
30
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
31
31
|
declare const _default: typeof __VLS_export;
|
|
@@ -23,12 +23,12 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {},
|
|
|
23
23
|
"onUpdate:start"?: ((value: number | undefined) => any) | undefined;
|
|
24
24
|
"onUpdate:end"?: ((value: number | undefined) => any) | undefined;
|
|
25
25
|
}>, {
|
|
26
|
+
clearable: boolean;
|
|
26
27
|
disabled: boolean;
|
|
27
28
|
readonly: boolean;
|
|
28
|
-
|
|
29
|
+
separator: string;
|
|
29
30
|
startPlaceholder: string;
|
|
30
31
|
endPlaceholder: string;
|
|
31
|
-
separator: string;
|
|
32
32
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
33
33
|
declare const _default: typeof __VLS_export;
|
|
34
34
|
//#endregion
|
|
@@ -14,9 +14,9 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {
|
|
|
14
14
|
}, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
|
|
15
15
|
"onUpdate:modelValue"?: ((value: string | undefined) => any) | undefined;
|
|
16
16
|
}>, {
|
|
17
|
+
clearable: boolean;
|
|
17
18
|
disabled: boolean;
|
|
18
19
|
readonly: boolean;
|
|
19
|
-
clearable: boolean;
|
|
20
20
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
21
21
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
22
22
|
declare const _default: typeof __VLS_export;
|
|
@@ -15,10 +15,10 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {},
|
|
|
15
15
|
"onUpdate:modelValue"?: ((value: any) => any) | undefined;
|
|
16
16
|
onChange?: ((item: Record<string, any>) => any) | undefined;
|
|
17
17
|
}>, {
|
|
18
|
-
disabled: boolean;
|
|
19
|
-
readonly: boolean;
|
|
20
18
|
labelKey: string;
|
|
21
19
|
valueKey: string;
|
|
20
|
+
disabled: boolean;
|
|
21
|
+
readonly: boolean;
|
|
22
22
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
23
23
|
declare const _default: typeof __VLS_export;
|
|
24
24
|
//#endregion
|
|
@@ -12,9 +12,9 @@ declare const __VLS_export: import("vue").DefineComponent<RichTextEditorProps &
|
|
|
12
12
|
}> & Readonly<{
|
|
13
13
|
"onUpdate:modelValue"?: ((value: string | undefined) => any) | undefined;
|
|
14
14
|
}>, {
|
|
15
|
+
placeholder: string;
|
|
15
16
|
disabled: boolean;
|
|
16
17
|
readonly: boolean;
|
|
17
|
-
placeholder: string;
|
|
18
18
|
format: RichTextFormat;
|
|
19
19
|
toolbar: ToolbarItem[];
|
|
20
20
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
@@ -5,8 +5,8 @@ import _sfc_main$4 from "../dropdown/dropdown.js";
|
|
|
5
5
|
import input_default from "../input/input.js";
|
|
6
6
|
import { useKeyboard } from "./use-keyboard.js";
|
|
7
7
|
import { useOptions } from "./use-options.js";
|
|
8
|
-
import { Fragment, Transition, computed, createBlock, createCommentVNode, createElementBlock, createSlots, createTextVNode, createVNode, defineComponent,
|
|
9
|
-
import { useFormFallbackProps, useVirtualizer } from "@veltra/compositions";
|
|
8
|
+
import { Fragment, Transition, computed, createBlock, createCommentVNode, createElementBlock, createSlots, createTextVNode, createVNode, defineComponent, mergeProps, nextTick, normalizeClass, normalizeStyle, openBlock, renderList, renderSlot, shallowRef, toDisplayString, unref, useTemplateRef, watch, withCtx, withModifiers } from "vue";
|
|
9
|
+
import { useFormFallbackProps, useUserAction, useVirtualizer } from "@veltra/compositions";
|
|
10
10
|
import { FORM_EMPTY_CONTENT, bem, fieldKey, injectFormContext, scrollIntoContainerView, withUnit } from "@veltra/utils";
|
|
11
11
|
import { ArrowDown, Close } from "@veltra/icons/normal";
|
|
12
12
|
import { o } from "@cat-kit/core";
|
|
@@ -21,9 +21,8 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
|
|
|
21
21
|
name: "USelect",
|
|
22
22
|
inheritAttrs: false,
|
|
23
23
|
__name: "select",
|
|
24
|
-
props:
|
|
24
|
+
props: {
|
|
25
25
|
modelValue: {},
|
|
26
|
-
text: {},
|
|
27
26
|
options: {},
|
|
28
27
|
valueKey: { default: "value" },
|
|
29
28
|
labelKey: { default: "label" },
|
|
@@ -53,15 +52,12 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
|
|
|
53
52
|
},
|
|
54
53
|
rules: {},
|
|
55
54
|
size: {}
|
|
56
|
-
},
|
|
57
|
-
|
|
58
|
-
"
|
|
59
|
-
}),
|
|
60
|
-
emits: /*@__PURE__*/ mergeModels([
|
|
61
|
-
"update:label",
|
|
55
|
+
},
|
|
56
|
+
emits: [
|
|
57
|
+
"update:text",
|
|
62
58
|
"update:modelValue",
|
|
63
59
|
"change"
|
|
64
|
-
],
|
|
60
|
+
],
|
|
65
61
|
setup(__props, { emit: __emit }) {
|
|
66
62
|
const props = __props;
|
|
67
63
|
const emit = __emit;
|
|
@@ -76,7 +72,8 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
|
|
|
76
72
|
readonly: false
|
|
77
73
|
});
|
|
78
74
|
const currentIndex = shallowRef(-1);
|
|
79
|
-
|
|
75
|
+
/** 内部展示文案,仅由选项推导;通过 update:text 单向通知父级 */
|
|
76
|
+
const label = shallowRef();
|
|
80
77
|
const selected = shallowRef();
|
|
81
78
|
const displayedValue = computed(() => {
|
|
82
79
|
if (label.value) return label.value;
|
|
@@ -88,7 +85,7 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
|
|
|
88
85
|
const filterable = computed(() => {
|
|
89
86
|
return props.filterable || typeof props.options === "function";
|
|
90
87
|
});
|
|
91
|
-
const { queryString, options, temOptionsToCreatedOptions, clearCreatedOptions } = useOptions({ props });
|
|
88
|
+
const { queryString, options, allOptions, temOptionsToCreatedOptions, clearCreatedOptions } = useOptions({ props });
|
|
92
89
|
const dropdownVisible = shallowRef(false);
|
|
93
90
|
/**
|
|
94
91
|
* 是否处于查询态:决定触发输入框显示查询串还是选中标签。
|
|
@@ -126,40 +123,38 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
|
|
|
126
123
|
e.stopPropagation();
|
|
127
124
|
if (!dropdownVisible.value) dropdownRef.value?.open();
|
|
128
125
|
}
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
126
|
+
const { userAction, isUserActive } = useUserAction();
|
|
127
|
+
/** 更新内部文案;值变化时单向 emit update:text */
|
|
128
|
+
function setLabel(next) {
|
|
129
|
+
if (label.value === next) return;
|
|
130
|
+
label.value = next;
|
|
131
|
+
emit("update:text", next);
|
|
132
132
|
}
|
|
133
|
-
/**
|
|
134
|
-
|
|
135
|
-
*/
|
|
136
|
-
function unlock(preferredValue) {
|
|
137
|
-
nextTick(() => {
|
|
138
|
-
userSelecting = false;
|
|
139
|
-
syncSelected(preferredValue !== void 0 ? preferredValue : props.modelValue, options.value);
|
|
140
|
-
});
|
|
141
|
-
}
|
|
142
|
-
/** 按 modelValue 与选项列表同步高亮索引、选中项与显示标签 */
|
|
143
|
-
function syncSelected(modelValue, options) {
|
|
133
|
+
/** 按 modelValue 与完整选项列表同步高亮索引、选中项与显示标签(外部回显用,O(n)) */
|
|
134
|
+
function syncSelected(modelValue, sourceOptions) {
|
|
144
135
|
if (queryString.value) {
|
|
145
|
-
currentIndex.value = options
|
|
136
|
+
currentIndex.value = options.value.length ? 0 : -1;
|
|
146
137
|
return;
|
|
147
138
|
}
|
|
148
|
-
if (!
|
|
139
|
+
if (!sourceOptions?.length) return;
|
|
149
140
|
if (modelValue !== void 0 && modelValue !== null && modelValue !== "") {
|
|
150
|
-
currentIndex.value =
|
|
151
|
-
selected.value = currentIndex.value >= 0 ?
|
|
152
|
-
|
|
141
|
+
currentIndex.value = sourceOptions.findIndex((option) => o(option).get(valueKey.value) === modelValue);
|
|
142
|
+
selected.value = currentIndex.value >= 0 ? sourceOptions[currentIndex.value] : void 0;
|
|
143
|
+
setLabel(selected.value ? o(selected.value).get(labelKey.value) : void 0);
|
|
153
144
|
} else {
|
|
154
145
|
currentIndex.value = -1;
|
|
155
146
|
selected.value = void 0;
|
|
156
|
-
|
|
147
|
+
setLabel(void 0);
|
|
157
148
|
}
|
|
158
149
|
}
|
|
159
|
-
watch([() => props.modelValue,
|
|
160
|
-
if (
|
|
161
|
-
syncSelected(modelValue,
|
|
150
|
+
watch([() => props.modelValue, allOptions], ([modelValue]) => {
|
|
151
|
+
if (isUserActive()) return;
|
|
152
|
+
syncSelected(modelValue, allOptions.value);
|
|
162
153
|
}, { immediate: true });
|
|
154
|
+
watch([queryString, options], () => {
|
|
155
|
+
if (!queryString.value) return;
|
|
156
|
+
currentIndex.value = options.value.length ? 0 : -1;
|
|
157
|
+
});
|
|
163
158
|
const baseVirtualEnabled = computed(() => options.value.length > 80);
|
|
164
159
|
const virtualEnabled = computed(() => baseVirtualEnabled.value && !props.grid);
|
|
165
160
|
const { virtualizer, items } = useVirtualizer({
|
|
@@ -212,13 +207,12 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
|
|
|
212
207
|
const handleDropdownVisible = (visible) => {
|
|
213
208
|
if (!visible) queryString.value = "";
|
|
214
209
|
};
|
|
215
|
-
/**
|
|
216
|
-
const handleSelect = (option, _index) => {
|
|
217
|
-
lock();
|
|
210
|
+
/** 单选:用户动作内 O(1) 写入值与文案,跳过 modelValue 回显的 O(n) 查找 */
|
|
211
|
+
const handleSelect = userAction((option, _index) => {
|
|
218
212
|
const value = option?.[valueKey.value];
|
|
219
213
|
selected.value = option;
|
|
220
214
|
emit("update:modelValue", value);
|
|
221
|
-
|
|
215
|
+
setLabel(option?.[labelKey.value]);
|
|
222
216
|
emit("change", option);
|
|
223
217
|
if (option.__isTemp) temOptionsToCreatedOptions();
|
|
224
218
|
querying.value = false;
|
|
@@ -226,19 +220,16 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
|
|
|
226
220
|
currentIndex.value = options.value.findIndex((item) => o(item).get(valueKey.value) === value);
|
|
227
221
|
if (currentIndex.value >= 0) selected.value = options.value[currentIndex.value];
|
|
228
222
|
dropdownRef.value?.close();
|
|
229
|
-
|
|
230
|
-
};
|
|
223
|
+
});
|
|
231
224
|
/** 清除选项 */
|
|
232
|
-
const handleClear = () => {
|
|
233
|
-
lock();
|
|
225
|
+
const handleClear = userAction(() => {
|
|
234
226
|
selected.value = void 0;
|
|
235
227
|
currentIndex.value = -1;
|
|
236
|
-
|
|
228
|
+
setLabel(void 0);
|
|
237
229
|
clearCreatedOptions();
|
|
238
230
|
emit("update:modelValue", void 0);
|
|
239
231
|
emit("change", void 0);
|
|
240
|
-
|
|
241
|
-
};
|
|
232
|
+
});
|
|
242
233
|
function getCurrentEl() {
|
|
243
234
|
return scrollRef.value?.contentRef?.querySelector("li.is-selected");
|
|
244
235
|
}
|
|
@@ -290,11 +281,11 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
|
|
|
290
281
|
class: normalizeClass(unref(cls).e("clear")),
|
|
291
282
|
title: "清除",
|
|
292
283
|
key: "clear",
|
|
293
|
-
onClick: withModifiers(handleClear, ["stop"])
|
|
284
|
+
onClick: withModifiers(unref(handleClear), ["stop"])
|
|
294
285
|
}, {
|
|
295
286
|
default: withCtx(() => [createVNode(unref(Close))]),
|
|
296
287
|
_: 1
|
|
297
|
-
}, 8, ["class"])) : (openBlock(), createBlock(unref(_sfc_main$1), {
|
|
288
|
+
}, 8, ["class", "onClick"])) : (openBlock(), createBlock(unref(_sfc_main$1), {
|
|
298
289
|
class: normalizeClass(unref(cls).e("arrow")),
|
|
299
290
|
key: "arrow"
|
|
300
291
|
}, {
|
|
@@ -335,7 +326,7 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
|
|
|
335
326
|
default: withCtx(() => [virtualEnabled.value ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [createCommentVNode(" @vue-ignore "), (openBlock(true), createElementBlock(Fragment, null, renderList(virtualOptions.value, ({ option, index, val, label, key, offset }) => {
|
|
336
327
|
return openBlock(), createElementBlock("li", {
|
|
337
328
|
class: normalizeClass([unref(optionClass), unref(bem).is("selected", index === currentIndex.value)]),
|
|
338
|
-
onClick: ($event) => handleSelect(option, index),
|
|
329
|
+
onClick: ($event) => unref(handleSelect)(option, index),
|
|
339
330
|
key,
|
|
340
331
|
style: normalizeStyle({ transform: `translateY(${offset}px)` }),
|
|
341
332
|
"data-index": index,
|
|
@@ -348,7 +339,7 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
|
|
|
348
339
|
}), 128))], 64)) : (openBlock(true), createElementBlock(Fragment, { key: 1 }, renderList(unref(options), (option, index) => {
|
|
349
340
|
return openBlock(), createElementBlock("li", {
|
|
350
341
|
class: normalizeClass([unref(optionClass), unref(bem).is("selected", index === currentIndex.value)]),
|
|
351
|
-
onClick: ($event) => handleSelect(option, index),
|
|
342
|
+
onClick: ($event) => unref(handleSelect)(option, index),
|
|
352
343
|
"data-index": index,
|
|
353
344
|
title: unref(o)(option).get(labelKey.value),
|
|
354
345
|
key: unref(o)(option).get(valueKey.value)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"select.js","names":["$attrs","$slots"],"sources":["../../../src/components/select/select.vue"],"sourcesContent":["<template>\n <u-dropdown\n v-if=\"!readonly\"\n v-bind=\"$attrs\"\n trigger=\"click\"\n :class=\"[cls.b, bem.is('disabled', disabled)]\"\n ref=\"dropdownRef\"\n v-model:visible=\"dropdownVisible\"\n :content-class=\"[cls.e('panel'), cls.em('panel', size), contentClass]\"\n :content-style=\"contentStyle\"\n :disabled=\"disabled\"\n :min-width=\"minWidth\"\n :width=\"width\"\n @keydown=\"handleKeydown\"\n @update:visible=\"handleDropdownVisible\"\n @mouseenter=\"hovered = true\"\n @mouseleave=\"hovered = false\"\n >\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 @keydown=\"handleKeydown\"\n :native-readonly=\"!filterable || !querying\"\n @click.capture=\"handleTriggerClickCapture\"\n >\n <template #prefix v-if=\"$slots.prefix\">\n <slot name=\"prefix\" />\n </template>\n\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\">\n <ArrowDown />\n </u-icon>\n </transition>\n </template>\n </u-input>\n </template>\n\n <!-- 下拉内容 -->\n <template #content>\n <!--\n 单选列表。虚拟化启用时,内容容器 height 由 useVirtualizer 命令式写入;\n 此处 content-style 仅承担 grid 相关样式,避免 height 变化触发模板重渲染。\n -->\n <u-scroll\n v-if=\"options.length\"\n tag=\"ul\"\n :class=\"cls.e('options')\"\n ref=\"scrollRef\"\n :content-class=\"[\n cls.e('options-wrap'),\n bem.is('virtual', virtualEnabled),\n bem.is('grid', !!grid)\n ]\"\n :content-style=\"{\n gridTemplateColumns: grid ? `repeat(${grid.cols}, minmax(0px, 1fr))` : undefined,\n gridGap: grid ? withUnit(grid.gap, 'px') : undefined\n }\"\n >\n <template v-if=\"virtualEnabled\">\n <!-- @vue-ignore -->\n <li\n v-for=\"{ option, index, val, label, key, offset } of virtualOptions\"\n :class=\"[optionClass, bem.is('selected', index === currentIndex)]\"\n @click=\"handleSelect(option, index)\"\n :key=\"key\"\n :style=\"{ transform: `translateY(${offset}px)` }\"\n :data-index=\"index\"\n :ref=\"(el) => measureElement(index, el as Element | null)\"\n >\n <slot v-bind=\"{ option, index }\">\n {{ label }}\n </slot>\n </li>\n </template>\n\n <template v-else>\n <li\n v-for=\"(option, index) of options\"\n :class=\"[optionClass, bem.is('selected', index === currentIndex)]\"\n @click=\"handleSelect(option, index)\"\n :data-index=\"index\"\n :title=\"o(option).get(labelKey)\"\n :key=\"o(option).get(valueKey)\"\n >\n <slot v-bind=\"{ option, index }\">\n {{ o(option).get(labelKey) }}\n </slot>\n </li>\n </template>\n </u-scroll>\n\n <div v-else :class=\"cls.e('empty')\">\n <UEmpty />\n </div>\n </template>\n </u-dropdown>\n\n <template v-else>\n {{ displayedValue || FORM_EMPTY_CONTENT }}\n </template>\n</template>\n\n<script lang=\"ts\" setup>\nimport { o } from '@cat-kit/core'\nimport { useFormFallbackProps, useVirtualizer } from '@veltra/compositions'\nimport { ArrowDown, Close } from '@veltra/icons/normal'\nimport { bem, fieldKey, FORM_EMPTY_CONTENT, scrollIntoContainerView, withUnit } from '@veltra/utils'\nimport { injectFormContext } from '@veltra/utils'\nimport { computed, nextTick, shallowRef, useTemplateRef, watch } from 'vue'\n\nimport type {\n SelectEmits,\n SelectProps,\n _SelectExposed,\n DropdownExposed,\n InputExposed,\n ScrollExposed\n} from '../../types'\nimport { UDropdown } from '../dropdown'\nimport { UEmpty } from '../empty'\nimport { UIcon } from '../icon'\nimport { UInput } from '../input'\nimport { UScroll } from '../scroll'\nimport { useKeyboard } from './use-keyboard'\nimport { useOptions } from './use-options'\n\ndefineOptions({ name: 'USelect', inheritAttrs: false })\n\nconst props = withDefaults(defineProps<SelectProps>(), {\n labelKey: 'label',\n valueKey: 'value',\n placeholder: '请选择',\n clearable: true,\n disabled: undefined,\n readonly: undefined\n})\n\nconst emit = defineEmits<SelectEmits>()\n\ndefineSlots<{\n /** 前缀插槽 */\n prefix?: () => any\n /** 默认插槽 */\n default?: (scope: { option: Record<string, any>; index: number }) => any\n}>()\n\nconst cls = bem('select')\n\nconst labelKey = computed(() => fieldKey(props.labelKey, 'label'))\nconst valueKey = computed(() => fieldKey(props.valueKey, 'value'))\n\nconst optionClass = cls.e('option')\n\nconst { formProps } = injectFormContext()\nconst { size, disabled, readonly } = useFormFallbackProps([formProps ?? {}, props], {\n size: 'default',\n disabled: false,\n readonly: false\n})\n\nconst currentIndex = shallowRef(-1)\nconst label = defineModel('text')\nconst selected = shallowRef<Record<string, any>>()\n\nconst displayedValue = computed(() => {\n if (label.value) return label.value\n\n return selected.value ? o(selected.value).get(labelKey.value) : String(props.modelValue ?? '')\n})\n\nconst dropdownRef = shallowRef<DropdownExposed>()\nconst scrollRef = shallowRef<ScrollExposed>()\nconst inputRef = useTemplateRef<InputExposed>('inputRef')\n\nconst filterable = computed(() => {\n return props.filterable || typeof props.options === 'function'\n})\n\nconst { queryString, options, temOptionsToCreatedOptions, clearCreatedOptions } = useOptions({\n props\n})\n\nconst dropdownVisible = shallowRef(false)\n\n/**\n * 是否处于查询态:决定触发输入框显示查询串还是选中标签。\n * 与面板可见状态解耦 —— 选择后立即退出查询态,\n * 不等面板关闭动画结束(否则显示值会延迟一个动画时长才恢复)。\n */\nconst querying = shallowRef(false)\n\n/** 触发输入框的值:查询态下承载查询串,否则展示选中标签 */\nconst inputValue = computed(() => {\n if (filterable.value && querying.value) return queryString.value\n return displayedValue.value\n})\n\n/** 查询态下已选标签降级为占位提示 */\nconst inputPlaceholder = computed(() => {\n if (filterable.value && querying.value && displayedValue.value) {\n return displayedValue.value\n }\n return props.placeholder\n})\n\nfunction handleQueryInput(value: string) {\n if (!filterable.value) return\n queryString.value = value\n}\n\nconst hovered = shallowRef(false)\n\n/** 悬停且存在选中值时展示清除按钮(替代下拉箭头) */\nconst showClear = computed(() => {\n return props.clearable && !disabled.value && hovered.value && !!displayedValue.value\n})\n\n/**\n * 过滤模式下拦截输入区域的点击:\n * 阻止 dropdown 的 trigger 开合切换,保持面板展开以不中断输入。\n * 非输入区域(箭头、留白)放行,维持原开合行为。\n */\nfunction handleTriggerClickCapture(e: MouseEvent) {\n if (!filterable.value || disabled.value) return\n if (!(e.target instanceof HTMLInputElement)) return\n\n e.stopPropagation()\n if (!dropdownVisible.value) dropdownRef.value?.open()\n}\n\n// TODO: 优化\nlet userSelecting = false\nfunction lock() {\n userSelecting = true\n}\n\n/**\n * @param preferredValue 选择时传入刚提交的值,避免 nextTick 时 props.modelValue 尚未回传而用旧值覆盖高亮/标签\n */\nfunction unlock(preferredValue?: any) {\n nextTick(() => {\n userSelecting = false\n // 选择/清除会同步重建选项列表(临时项转正、查询串清空),\n // 重建触发的回显在锁定期间被跳过,解锁后按最新列表重同步一次,\n // 避免高亮停留在选择前的旧索引上\n const value = preferredValue !== undefined ? preferredValue : props.modelValue\n syncSelected(value, options.value)\n })\n}\n\n/** 按 modelValue 与选项列表同步高亮索引、选中项与显示标签 */\nfunction syncSelected(modelValue: any, options: Record<string, any>[] | undefined) {\n // 查询输入期间高亮第一项(创建模式下通常是临时项,便于回车创建)\n if (queryString.value) {\n currentIndex.value = options?.length ? 0 : -1\n return\n }\n\n if (!options?.length) return\n\n if (modelValue !== undefined && modelValue !== null && modelValue !== '') {\n currentIndex.value = options.findIndex((option) => o(option).get(valueKey.value) === modelValue)\n selected.value = currentIndex.value >= 0 ? options[currentIndex.value] : undefined\n label.value = selected.value ? o(selected.value).get(labelKey.value) : undefined\n } else {\n currentIndex.value = -1\n selected.value = undefined\n label.value = undefined\n }\n}\n\n// 回显\nwatch(\n [() => props.modelValue, options],\n ([modelValue, options]) => {\n if (userSelecting) return\n syncSelected(modelValue, options)\n },\n { immediate: true }\n)\n\nconst baseVirtualEnabled = computed(() => options.value.length > 80)\nconst virtualEnabled = computed(() => baseVirtualEnabled.value && !props.grid)\n\nconst { virtualizer, items } = useVirtualizer({\n count: computed(() => options.value.length),\n scrollEl: () => scrollRef.value?.containerRef ?? null,\n contentEl: () => (virtualEnabled.value ? (scrollRef.value?.contentRef ?? null) : null),\n gap: 4,\n estimateSize: () => 40\n})\n\nconst virtualOptions = computed(() => {\n const _options = options.value\n return items.value.map((item) => {\n const option = _options[item.index]!\n return {\n option,\n index: item.index,\n label: o(option).get(labelKey.value),\n val: o(option).get(valueKey.value),\n key: item.index,\n offset: item.start\n }\n })\n})\n\nconst measureElement: (index: number, el: Element | null) => void = (index, el) =>\n virtualizer.measureElement(index, el)\n\nfunction scrollTo(index: number): void {\n virtualizer.scrollToIndex(index, { align: 'center' })\n}\n\nwatch([scrollRef, virtualEnabled], ([scroll, virtualEnabled]) => {\n if (!scroll || !props.modelValue) return\n\n if (virtualEnabled) {\n const index = options.value.findIndex((option) => option === selected.value)\n index !== -1 && dropdownVisible.value && nextTick(() => scrollTo(index))\n } else {\n const selectedEl = scroll?.contentRef?.getElementsByClassName('is-selected')[0]\n if (selectedEl) {\n scrollIntoContainerView(selectedEl as HTMLElement, scroll.containerRef ?? null)\n }\n }\n})\n\nwatch(dropdownVisible, (visible) => {\n if (visible) {\n // 面板展开后进入查询态并聚焦输入框,可以立即输入查询\n if (filterable.value) {\n queryString.value = ''\n querying.value = true\n nextTick(() => inputRef.value?.el?.focus())\n }\n } else {\n querying.value = false\n queryString.value = ''\n }\n})\n\nconst handleDropdownVisible = (visible: boolean) => {\n if (!visible) {\n queryString.value = ''\n }\n}\n\n/** 单选 */\nconst handleSelect = (option: Record<string, any>, _index: number) => {\n lock()\n const value = option?.[valueKey.value]\n selected.value = option\n\n emit('update:modelValue', value)\n label.value = option?.[labelKey.value]\n emit('change', option)\n if (option.__isTemp) {\n // 转正后列表同步重建为完整源(临时项置顶索引失效),必须按 value 重定位\n temOptionsToCreatedOptions()\n }\n // 立即退出查询态,输入框同步恢复显示选中标签\n querying.value = false\n queryString.value = ''\n // 按当前列表定位高亮,避免创建项转正后仍停留在点击时的临时索引(通常为 0)\n currentIndex.value = options.value.findIndex((item) => o(item).get(valueKey.value) === value)\n if (currentIndex.value >= 0) {\n selected.value = options.value[currentIndex.value]\n }\n dropdownRef.value?.close()\n\n unlock(value)\n}\n\n/** 清除选项 */\nconst handleClear = () => {\n lock()\n selected.value = undefined\n currentIndex.value = -1\n label.value = undefined\n clearCreatedOptions()\n emit('update:modelValue', undefined)\n emit('change', undefined)\n unlock(null)\n}\n\nfunction getCurrentEl() {\n return scrollRef.value?.contentRef?.querySelector('li.is-selected') as HTMLElement | undefined\n}\n\nconst { handleKeydown } = useKeyboard({\n options,\n currentIndex,\n selectOption: handleSelect,\n getCurrentEl\n})\n</script>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"select.js","names":["$attrs","$slots"],"sources":["../../../src/components/select/select.vue"],"sourcesContent":["<template>\n <u-dropdown\n v-if=\"!readonly\"\n v-bind=\"$attrs\"\n trigger=\"click\"\n :class=\"[cls.b, bem.is('disabled', disabled)]\"\n ref=\"dropdownRef\"\n v-model:visible=\"dropdownVisible\"\n :content-class=\"[cls.e('panel'), cls.em('panel', size), contentClass]\"\n :content-style=\"contentStyle\"\n :disabled=\"disabled\"\n :min-width=\"minWidth\"\n :width=\"width\"\n @keydown=\"handleKeydown\"\n @update:visible=\"handleDropdownVisible\"\n @mouseenter=\"hovered = true\"\n @mouseleave=\"hovered = false\"\n >\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 @keydown=\"handleKeydown\"\n :native-readonly=\"!filterable || !querying\"\n @click.capture=\"handleTriggerClickCapture\"\n >\n <template #prefix v-if=\"$slots.prefix\">\n <slot name=\"prefix\" />\n </template>\n\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\">\n <ArrowDown />\n </u-icon>\n </transition>\n </template>\n </u-input>\n </template>\n\n <!-- 下拉内容 -->\n <template #content>\n <!--\n 单选列表。虚拟化启用时,内容容器 height 由 useVirtualizer 命令式写入;\n 此处 content-style 仅承担 grid 相关样式,避免 height 变化触发模板重渲染。\n -->\n <u-scroll\n v-if=\"options.length\"\n tag=\"ul\"\n :class=\"cls.e('options')\"\n ref=\"scrollRef\"\n :content-class=\"[\n cls.e('options-wrap'),\n bem.is('virtual', virtualEnabled),\n bem.is('grid', !!grid)\n ]\"\n :content-style=\"{\n gridTemplateColumns: grid ? `repeat(${grid.cols}, minmax(0px, 1fr))` : undefined,\n gridGap: grid ? withUnit(grid.gap, 'px') : undefined\n }\"\n >\n <template v-if=\"virtualEnabled\">\n <!-- @vue-ignore -->\n <li\n v-for=\"{ option, index, val, label, key, offset } of virtualOptions\"\n :class=\"[optionClass, bem.is('selected', index === currentIndex)]\"\n @click=\"handleSelect(option, index)\"\n :key=\"key\"\n :style=\"{ transform: `translateY(${offset}px)` }\"\n :data-index=\"index\"\n :ref=\"(el) => measureElement(index, el as Element | null)\"\n >\n <slot v-bind=\"{ option, index }\">\n {{ label }}\n </slot>\n </li>\n </template>\n\n <template v-else>\n <li\n v-for=\"(option, index) of options\"\n :class=\"[optionClass, bem.is('selected', index === currentIndex)]\"\n @click=\"handleSelect(option, index)\"\n :data-index=\"index\"\n :title=\"o(option).get(labelKey)\"\n :key=\"o(option).get(valueKey)\"\n >\n <slot v-bind=\"{ option, index }\">\n {{ o(option).get(labelKey) }}\n </slot>\n </li>\n </template>\n </u-scroll>\n\n <div v-else :class=\"cls.e('empty')\">\n <UEmpty />\n </div>\n </template>\n </u-dropdown>\n\n <template v-else>\n {{ displayedValue || FORM_EMPTY_CONTENT }}\n </template>\n</template>\n\n<script lang=\"ts\" setup>\nimport { o } from '@cat-kit/core'\nimport { useFormFallbackProps, useUserAction, useVirtualizer } from '@veltra/compositions'\nimport { ArrowDown, Close } from '@veltra/icons/normal'\nimport { bem, fieldKey, FORM_EMPTY_CONTENT, scrollIntoContainerView, withUnit } from '@veltra/utils'\nimport { injectFormContext } from '@veltra/utils'\nimport { computed, nextTick, shallowRef, useTemplateRef, watch } from 'vue'\n\nimport type {\n SelectEmits,\n SelectProps,\n _SelectExposed,\n DropdownExposed,\n InputExposed,\n ScrollExposed\n} from '../../types'\nimport { UDropdown } from '../dropdown'\nimport { UEmpty } from '../empty'\nimport { UIcon } from '../icon'\nimport { UInput } from '../input'\nimport { UScroll } from '../scroll'\nimport { useKeyboard } from './use-keyboard'\nimport { useOptions } from './use-options'\n\ndefineOptions({ name: 'USelect', inheritAttrs: false })\n\nconst props = withDefaults(defineProps<SelectProps>(), {\n labelKey: 'label',\n valueKey: 'value',\n placeholder: '请选择',\n clearable: true,\n disabled: undefined,\n readonly: undefined\n})\n\nconst emit = defineEmits<SelectEmits>()\n\ndefineSlots<{\n /** 前缀插槽 */\n prefix?: () => any\n /** 默认插槽 */\n default?: (scope: { option: Record<string, any>; index: number }) => any\n}>()\n\nconst cls = bem('select')\n\nconst labelKey = computed(() => fieldKey(props.labelKey, 'label'))\nconst valueKey = computed(() => fieldKey(props.valueKey, 'value'))\n\nconst optionClass = cls.e('option')\n\nconst { formProps } = injectFormContext()\nconst { size, disabled, readonly } = useFormFallbackProps([formProps ?? {}, props], {\n size: 'default',\n disabled: false,\n readonly: false\n})\n\nconst currentIndex = shallowRef(-1)\n/** 内部展示文案,仅由选项推导;通过 update:text 单向通知父级 */\nconst label = shallowRef<string>()\nconst selected = shallowRef<Record<string, any>>()\n\nconst displayedValue = computed(() => {\n if (label.value) return label.value\n\n return selected.value ? o(selected.value).get(labelKey.value) : String(props.modelValue ?? '')\n})\n\nconst dropdownRef = shallowRef<DropdownExposed>()\nconst scrollRef = shallowRef<ScrollExposed>()\nconst inputRef = useTemplateRef<InputExposed>('inputRef')\n\nconst filterable = computed(() => {\n return props.filterable || typeof props.options === 'function'\n})\n\nconst { queryString, options, allOptions, temOptionsToCreatedOptions, clearCreatedOptions } =\n useOptions({ props })\n\nconst dropdownVisible = shallowRef(false)\n\n/**\n * 是否处于查询态:决定触发输入框显示查询串还是选中标签。\n * 与面板可见状态解耦 —— 选择后立即退出查询态,\n * 不等面板关闭动画结束(否则显示值会延迟一个动画时长才恢复)。\n */\nconst querying = shallowRef(false)\n\n/** 触发输入框的值:查询态下承载查询串,否则展示选中标签 */\nconst inputValue = computed(() => {\n if (filterable.value && querying.value) return queryString.value\n return displayedValue.value\n})\n\n/** 查询态下已选标签降级为占位提示 */\nconst inputPlaceholder = computed(() => {\n if (filterable.value && querying.value && displayedValue.value) {\n return displayedValue.value\n }\n return props.placeholder\n})\n\nfunction handleQueryInput(value: string) {\n if (!filterable.value) return\n queryString.value = value\n}\n\nconst hovered = shallowRef(false)\n\n/** 悬停且存在选中值时展示清除按钮(替代下拉箭头) */\nconst showClear = computed(() => {\n return props.clearable && !disabled.value && hovered.value && !!displayedValue.value\n})\n\n/**\n * 过滤模式下拦截输入区域的点击:\n * 阻止 dropdown 的 trigger 开合切换,保持面板展开以不中断输入。\n * 非输入区域(箭头、留白)放行,维持原开合行为。\n */\nfunction handleTriggerClickCapture(e: MouseEvent) {\n if (!filterable.value || disabled.value) return\n if (!(e.target instanceof HTMLInputElement)) return\n\n e.stopPropagation()\n if (!dropdownVisible.value) dropdownRef.value?.open()\n}\n\nconst { userAction, isUserActive } = useUserAction()\n\n/** 更新内部文案;值变化时单向 emit update:text */\nfunction setLabel(next?: string) {\n if (label.value === next) return\n label.value = next\n emit('update:text', next)\n}\n\n/** 按 modelValue 与完整选项列表同步高亮索引、选中项与显示标签(外部回显用,O(n)) */\nfunction syncSelected(modelValue: any, sourceOptions: Record<string, any>[] | undefined) {\n // 查询输入期间高亮第一项(创建模式下通常是临时项,便于回车创建)\n if (queryString.value) {\n currentIndex.value = options.value.length ? 0 : -1\n return\n }\n\n if (!sourceOptions?.length) return\n\n if (modelValue !== undefined && modelValue !== null && modelValue !== '') {\n currentIndex.value = sourceOptions.findIndex(\n (option) => o(option).get(valueKey.value) === modelValue\n )\n selected.value = currentIndex.value >= 0 ? sourceOptions[currentIndex.value] : undefined\n setLabel(selected.value ? o(selected.value).get(labelKey.value) : undefined)\n } else {\n currentIndex.value = -1\n selected.value = undefined\n setLabel(undefined)\n }\n}\n\n// 回显:以 allOptions 匹配,避免过滤列表缺项时清掉已选文案;用户动作期内跳过\nwatch(\n [() => props.modelValue, allOptions],\n ([modelValue]) => {\n if (isUserActive()) return\n syncSelected(modelValue, allOptions.value)\n },\n { immediate: true }\n)\n\n// 过滤时单独同步高亮(allOptions 不变,不会触发上方回显 watch)\nwatch([queryString, options], () => {\n if (!queryString.value) return\n currentIndex.value = options.value.length ? 0 : -1\n})\n\nconst baseVirtualEnabled = computed(() => options.value.length > 80)\nconst virtualEnabled = computed(() => baseVirtualEnabled.value && !props.grid)\n\nconst { virtualizer, items } = useVirtualizer({\n count: computed(() => options.value.length),\n scrollEl: () => scrollRef.value?.containerRef ?? null,\n contentEl: () => (virtualEnabled.value ? (scrollRef.value?.contentRef ?? null) : null),\n gap: 4,\n estimateSize: () => 40\n})\n\nconst virtualOptions = computed(() => {\n const _options = options.value\n return items.value.map((item) => {\n const option = _options[item.index]!\n return {\n option,\n index: item.index,\n label: o(option).get(labelKey.value),\n val: o(option).get(valueKey.value),\n key: item.index,\n offset: item.start\n }\n })\n})\n\nconst measureElement: (index: number, el: Element | null) => void = (index, el) =>\n virtualizer.measureElement(index, el)\n\nfunction scrollTo(index: number): void {\n virtualizer.scrollToIndex(index, { align: 'center' })\n}\n\nwatch([scrollRef, virtualEnabled], ([scroll, virtualEnabled]) => {\n if (!scroll || !props.modelValue) return\n\n if (virtualEnabled) {\n const index = options.value.findIndex((option) => option === selected.value)\n index !== -1 && dropdownVisible.value && nextTick(() => scrollTo(index))\n } else {\n const selectedEl = scroll?.contentRef?.getElementsByClassName('is-selected')[0]\n if (selectedEl) {\n scrollIntoContainerView(selectedEl as HTMLElement, scroll.containerRef ?? null)\n }\n }\n})\n\nwatch(dropdownVisible, (visible) => {\n if (visible) {\n // 面板展开后进入查询态并聚焦输入框,可以立即输入查询\n if (filterable.value) {\n queryString.value = ''\n querying.value = true\n nextTick(() => inputRef.value?.el?.focus())\n }\n } else {\n querying.value = false\n queryString.value = ''\n }\n})\n\nconst handleDropdownVisible = (visible: boolean) => {\n if (!visible) {\n queryString.value = ''\n }\n}\n\n/** 单选:用户动作内 O(1) 写入值与文案,跳过 modelValue 回显的 O(n) 查找 */\nconst handleSelect = userAction((option: Record<string, any>, _index: number) => {\n const value = option?.[valueKey.value]\n selected.value = option\n\n emit('update:modelValue', value)\n setLabel(option?.[labelKey.value])\n emit('change', option)\n if (option.__isTemp) {\n // 转正后列表同步重建为完整源(临时项置顶索引失效),必须按 value 重定位\n temOptionsToCreatedOptions()\n }\n // 立即退出查询态,输入框同步恢复显示选中标签\n querying.value = false\n queryString.value = ''\n // 按当前列表定位高亮,避免创建项转正后仍停留在点击时的临时索引(通常为 0)\n currentIndex.value = options.value.findIndex((item) => o(item).get(valueKey.value) === value)\n if (currentIndex.value >= 0) {\n selected.value = options.value[currentIndex.value]\n }\n dropdownRef.value?.close()\n})\n\n/** 清除选项 */\nconst handleClear = userAction(() => {\n selected.value = undefined\n currentIndex.value = -1\n setLabel(undefined)\n clearCreatedOptions()\n emit('update:modelValue', undefined)\n emit('change', undefined)\n})\n\nfunction getCurrentEl() {\n return scrollRef.value?.contentRef?.querySelector('li.is-selected') as HTMLElement | undefined\n}\n\nconst { handleKeydown } = useKeyboard({\n options,\n currentIndex,\n selectOption: handleSelect,\n getCurrentEl\n})\n</script>\n"],"mappings":"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"}
|