|
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