diff --git a/components/select/index.tsx b/components/select/index.tsx index c6a9f10fc..30c2a8bc7 100644 --- a/components/select/index.tsx +++ b/components/select/index.tsx @@ -1,12 +1,12 @@ -import { computed, defineComponent, inject, ref, VNodeChild, App, PropType, Plugin } from 'vue'; +import { computed, defineComponent, ref, VNodeChild, App, PropType, Plugin } from 'vue'; import omit from 'omit.js'; import classNames from '../_util/classNames'; import RcSelect, { Option, OptGroup, SelectProps as RcSelectProps, BaseProps } from '../vc-select'; import { OptionProps as OptionPropsType } from '../vc-select/Option'; -import { defaultConfigProvider } from '../config-provider'; import getIcons from './utils/iconUtil'; import PropTypes from '../_util/vue-types'; import { tuple } from '../_util/type'; +import useConfigInject from '../_util/hooks/useConfigInject'; type RawValue = string | number; @@ -74,11 +74,10 @@ const Select = defineComponent({ props: SelectProps(), SECRET_COMBOBOX_MODE_DO_NOT_USE: 'SECRET_COMBOBOX_MODE_DO_NOT_USE', emits: ['change', 'update:value'], - setup(props: any, { attrs, emit }) { + slots: ['notFoundContent', 'suffixIcon', 'itemIcon', 'removeIcon', 'clearIcon', 'dropdownRender'], + setup(props, { attrs, emit, slots, expose }) { const selectRef = ref(null); - const configProvider = inject('configProvider', defaultConfigProvider); - const focus = () => { if (selectRef.value) { selectRef.value.focus(); @@ -104,122 +103,100 @@ const Select = defineComponent({ return mode; }); - const prefixCls = computed(() => { - return configProvider.getPrefixCls('select', props.prefixCls); - }); + const { prefixCls, direction, configProvider } = useConfigInject('select', props); const mergedClassName = computed(() => - classNames( - { - [`${prefixCls.value}-lg`]: props.size === 'large', - [`${prefixCls.value}-sm`]: props.size === 'small', - [`${prefixCls.value}-rtl`]: props.direction === 'rtl', - [`${prefixCls.value}-borderless`]: !props.bordered, - }, - attrs.class, - ), + classNames({ + [`${prefixCls.value}-lg`]: props.size === 'large', + [`${prefixCls.value}-sm`]: props.size === 'small', + [`${prefixCls.value}-rtl`]: direction.value === 'rtl', + [`${prefixCls.value}-borderless`]: !props.bordered, + }), ); const triggerChange = (...args: any[]) => { emit('update:value', args[0]); emit('change', ...args); }; - return { - selectRef, - mergedClassName, - mode, - focus, + expose({ blur, - configProvider, - triggerChange, - prefixCls, - }; - }, - render() { - const { - configProvider, - mode, - mergedClassName, - triggerChange, - prefixCls, - $slots: slots, - $props, - } = this as any; - const props: SelectTypes = $props; - const { - notFoundContent, - listHeight = 256, - listItemHeight = 24, - getPopupContainer, - dropdownClassName, - direction, - virtual, - dropdownMatchSelectWidth, - } = props; - - const { renderEmpty, getPopupContainer: getContextPopupContainer } = configProvider; - - const isMultiple = mode === 'multiple' || mode === 'tags'; - - // ===================== Empty ===================== - let mergedNotFound: VNodeChild; - if (notFoundContent !== undefined) { - mergedNotFound = notFoundContent; - } else if (slots.notFoundContent) { - mergedNotFound = slots.notFoundContent(); - } else if (mode === 'combobox') { - mergedNotFound = null; - } else { - mergedNotFound = renderEmpty('Select') as any; - } - - // ===================== Icons ===================== - const { suffixIcon, itemIcon, removeIcon, clearIcon } = getIcons( - { - ...this.$props, - multiple: isMultiple, - prefixCls, - }, - slots, - ); - - const selectProps = omit(props, [ - 'prefixCls', - 'suffixIcon', - 'itemIcon', - 'removeIcon', - 'clearIcon', - 'size', - 'bordered', - ]) as any; - - const rcSelectRtlDropDownClassName = classNames(dropdownClassName, { - [`${prefixCls}-dropdown-${direction}`]: direction === 'rtl', + focus, }); - return ( - - {slots.default?.()} - - ); + return () => { + const { + notFoundContent, + listHeight = 256, + listItemHeight = 24, + getPopupContainer, + dropdownClassName, + virtual, + dropdownMatchSelectWidth, + } = props; + + const { renderEmpty, getPopupContainer: getContextPopupContainer } = configProvider; + + const isMultiple = mode.value === 'multiple' || mode.value === 'tags'; + + // ===================== Empty ===================== + let mergedNotFound: VNodeChild; + if (notFoundContent !== undefined) { + mergedNotFound = notFoundContent; + } else if (slots.notFoundContent) { + mergedNotFound = slots.notFoundContent(); + } else if (mode.value === 'combobox') { + mergedNotFound = null; + } else { + mergedNotFound = renderEmpty('Select') as any; + } + + // ===================== Icons ===================== + const { suffixIcon, itemIcon, removeIcon, clearIcon } = getIcons( + { + ...props, + multiple: isMultiple, + prefixCls: prefixCls.value, + }, + slots, + ); + + const selectProps = omit(props, [ + 'prefixCls', + 'suffixIcon', + 'itemIcon', + 'removeIcon', + 'clearIcon', + 'size', + 'bordered', + ]); + + const rcSelectRtlDropDownClassName = classNames(dropdownClassName, { + [`${prefixCls.value}-dropdown-${direction.value}`]: direction.value === 'rtl', + }); + return ( + + {slots.default?.()} + + ); + }; }, }); /* istanbul ignore next */