|
1 | 1 | import type { App, Plugin, VNode, ExtractPropTypes } from 'vue';
|
2 |
| -import { defineComponent, inject, provide } from 'vue'; |
| 2 | +import { defineComponent, ref } from 'vue'; |
3 | 3 | import Select, { selectProps } from '../select';
|
4 | 4 | import PropTypes from '../_util/vue-types';
|
5 |
| -import { defaultConfigProvider } from '../config-provider'; |
6 |
| -import { getComponent, getOptionProps, isValidElement, getSlot } from '../_util/props-util'; |
| 5 | +import { isValidElement, flattenChildren } from '../_util/props-util'; |
7 | 6 | import warning from '../_util/warning';
|
8 | 7 | import Option from './Option';
|
9 | 8 | import OptGroup from './OptGroup';
|
10 | 9 | import omit from '../_util/omit';
|
| 10 | +import useConfigInject from '../_util/hooks/useConfigInject'; |
11 | 11 |
|
12 | 12 | function isSelectOptionOrSelectOptGroup(child: any): boolean {
|
13 | 13 | return child?.type?.isSelectOption || child?.type?.isSelectOptGroup;
|
@@ -46,109 +46,98 @@ const AutoComplete = defineComponent({
|
46 | 46 | slots: ['option'],
|
47 | 47 | Option,
|
48 | 48 | OptGroup,
|
49 |
| - setup(props, { slots }) { |
| 49 | + setup(props, { slots, attrs, expose }) { |
50 | 50 | warning(
|
51 |
| - !(props.dataSource !== undefined || 'dataSource' in slots), |
| 51 | + !('dataSource' in slots), |
52 | 52 | 'AutoComplete',
|
53 |
| - '`dataSource` is deprecated, please use `options` instead.', |
| 53 | + '`dataSource` slot is deprecated, please use props `options` instead.', |
54 | 54 | );
|
55 |
| - return { |
56 |
| - configProvider: inject('configProvider', defaultConfigProvider), |
57 |
| - popupRef: null, |
58 |
| - select: null, |
59 |
| - }; |
60 |
| - }, |
61 |
| - created() { |
62 |
| - provide('savePopupRef', this.savePopupRef); |
63 |
| - }, |
64 |
| - methods: { |
65 |
| - savePopupRef(ref: VNode) { |
66 |
| - this.popupRef = ref; |
67 |
| - }, |
68 |
| - saveSelect(node: VNode) { |
69 |
| - this.select = node; |
70 |
| - }, |
71 |
| - getInputElement() { |
72 |
| - const children = getSlot(this); |
| 55 | + warning( |
| 56 | + !('options' in slots), |
| 57 | + 'AutoComplete', |
| 58 | + '`options` slot is deprecated, please use props `options` instead.', |
| 59 | + ); |
| 60 | + const selectRef = ref(); |
| 61 | + const getInputElement = () => { |
| 62 | + const children = flattenChildren(slots.default?.()); |
73 | 63 | const element = children.length ? children[0] : undefined;
|
74 | 64 | return element;
|
75 |
| - }, |
| 65 | + }; |
76 | 66 |
|
77 |
| - focus() { |
78 |
| - if (this.select) { |
79 |
| - this.select.focus(); |
80 |
| - } |
81 |
| - }, |
| 67 | + const focus = () => { |
| 68 | + selectRef.value?.focus(); |
| 69 | + }; |
| 70 | + |
| 71 | + const blur = () => { |
| 72 | + selectRef.value?.blur(); |
| 73 | + }; |
82 | 74 |
|
83 |
| - blur() { |
84 |
| - if (this.select) { |
85 |
| - this.select.blur(); |
| 75 | + expose({ |
| 76 | + focus, |
| 77 | + blur, |
| 78 | + }); |
| 79 | + const { prefixCls } = useConfigInject('select', props); |
| 80 | + return () => { |
| 81 | + const { size, dataSource, notFoundContent = slots.notFoundContent?.() } = props; |
| 82 | + let optionChildren: VNode[]; |
| 83 | + const { class: className } = attrs; |
| 84 | + const cls = { |
| 85 | + [className as string]: !!className, |
| 86 | + [`${prefixCls.value}-lg`]: size === 'large', |
| 87 | + [`${prefixCls.value}-sm`]: size === 'small', |
| 88 | + [`${prefixCls.value}-show-search`]: true, |
| 89 | + [`${prefixCls.value}-auto-complete`]: true, |
| 90 | + }; |
| 91 | + if (props.options === undefined) { |
| 92 | + const childArray = slots.dataSource?.() || slots.options?.() || []; |
| 93 | + if (childArray.length && isSelectOptionOrSelectOptGroup(childArray[0])) { |
| 94 | + optionChildren = childArray; |
| 95 | + } else { |
| 96 | + optionChildren = dataSource |
| 97 | + ? dataSource.map((item: any) => { |
| 98 | + if (isValidElement(item)) { |
| 99 | + return item; |
| 100 | + } |
| 101 | + switch (typeof item) { |
| 102 | + case 'string': |
| 103 | + return ( |
| 104 | + <Option key={item} value={item}> |
| 105 | + {item} |
| 106 | + </Option> |
| 107 | + ); |
| 108 | + case 'object': |
| 109 | + return ( |
| 110 | + <Option key={item.value} value={item.value}> |
| 111 | + {item.text} |
| 112 | + </Option> |
| 113 | + ); |
| 114 | + default: |
| 115 | + throw new Error( |
| 116 | + 'AutoComplete[dataSource] only supports type `string[] | Object[]`.', |
| 117 | + ); |
| 118 | + } |
| 119 | + }) |
| 120 | + : []; |
| 121 | + } |
86 | 122 | }
|
87 |
| - }, |
88 |
| - }, |
89 | 123 |
|
90 |
| - render() { |
91 |
| - const { size, prefixCls: customizePrefixCls, dataSource } = this; |
92 |
| - let optionChildren: VNode[]; |
93 |
| - const { getPrefixCls } = this.configProvider; |
94 |
| - const prefixCls = getPrefixCls('select', customizePrefixCls); |
95 |
| - const { class: className } = this.$attrs; |
96 |
| - const cls = { |
97 |
| - [className as string]: !!className, |
98 |
| - [`${prefixCls}-lg`]: size === 'large', |
99 |
| - [`${prefixCls}-sm`]: size === 'small', |
100 |
| - [`${prefixCls}-show-search`]: true, |
101 |
| - [`${prefixCls}-auto-complete`]: true, |
102 |
| - }; |
103 |
| - let childArray = getSlot(this, 'dataSource'); |
104 |
| - if ('options' in this.$slots) { |
105 |
| - childArray = getSlot(this, 'options'); |
106 |
| - } |
107 |
| - if (childArray.length && isSelectOptionOrSelectOptGroup(childArray[0])) { |
108 |
| - optionChildren = childArray; |
109 |
| - } else { |
110 |
| - optionChildren = dataSource |
111 |
| - ? dataSource.map((item: any) => { |
112 |
| - if (isValidElement(item)) { |
113 |
| - return item; |
114 |
| - } |
115 |
| - switch (typeof item) { |
116 |
| - case 'string': |
117 |
| - return ( |
118 |
| - <Option key={item} value={item}> |
119 |
| - {item} |
120 |
| - </Option> |
121 |
| - ); |
122 |
| - case 'object': |
123 |
| - return ( |
124 |
| - <Option key={item.value} value={item.value}> |
125 |
| - {item.text} |
126 |
| - </Option> |
127 |
| - ); |
128 |
| - default: |
129 |
| - throw new Error( |
130 |
| - 'AutoComplete[dataSource] only supports type `string[] | Object[]`.', |
131 |
| - ); |
132 |
| - } |
133 |
| - }) |
134 |
| - : []; |
135 |
| - } |
136 |
| - const selectProps = { |
137 |
| - ...omit(getOptionProps(this) as any, ['dataSource', 'optionLabelProp']), |
138 |
| - ...this.$attrs, |
139 |
| - mode: Select.SECRET_COMBOBOX_MODE_DO_NOT_USE, |
140 |
| - // optionLabelProp, |
141 |
| - getInputElement: this.getInputElement, |
142 |
| - notFoundContent: getComponent(this, 'notFoundContent'), |
143 |
| - // placeholder: '', |
144 |
| - class: cls, |
145 |
| - ref: this.saveSelect, |
| 124 | + const selectProps = { |
| 125 | + ...omit(props, ['dataSource', 'optionLabelProp']), |
| 126 | + ...attrs, |
| 127 | + mode: Select.SECRET_COMBOBOX_MODE_DO_NOT_USE, |
| 128 | + // optionLabelProp, |
| 129 | + getInputElement, |
| 130 | + notFoundContent, |
| 131 | + // placeholder: '', |
| 132 | + class: cls, |
| 133 | + ref: selectRef, |
| 134 | + }; |
| 135 | + return ( |
| 136 | + <Select {...selectProps} v-slots={{ option: slots.option }}> |
| 137 | + {optionChildren} |
| 138 | + </Select> |
| 139 | + ); |
146 | 140 | };
|
147 |
| - return ( |
148 |
| - <Select {...selectProps} v-slots={{ option: this.$slots.option }}> |
149 |
| - {optionChildren} |
150 |
| - </Select> |
151 |
| - ); |
152 | 141 | },
|
153 | 142 | });
|
154 | 143 |
|
|
0 commit comments