Skip to content

refactor:select #6295

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Feb 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion components/select/index.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
category: Components
type: Data Entry
title: Select
cover: https://gw.alipayobjects.com/zos/alicdn/_0XzgOis7/Select.svg
cover: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*zo76T7KQx2UAAAAAAAAAAAAADrJ8AQ/original
---

Select component to select value from options.
Expand Down
48 changes: 29 additions & 19 deletions components/select/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { App, PropType, Plugin, ExtractPropTypes } from 'vue';
import type { App, Plugin, ExtractPropTypes } from 'vue';
import { computed, defineComponent, ref } from 'vue';
import classNames from '../_util/classNames';
import type { BaseSelectRef } from '../vc-select';
Expand All @@ -16,6 +16,10 @@ import type { SizeType } from '../config-provider';
import { initDefaultProps } from '../_util/props-util';
import type { InputStatus } from '../_util/statusUtils';
import { getStatusClassNames, getMergedStatus } from '../_util/statusUtils';
import { stringType, someType, functionType, booleanType } from '../_util/type';

// CSSINJS
import useStyle from './style';

type RawValue = string | number;

Expand All @@ -37,23 +41,19 @@ export const selectProps = () => ({
'getRawInputElement',
'backfill',
]),
value: {
type: [Array, Object, String, Number] as PropType<SelectValue>,
},
defaultValue: {
type: [Array, Object, String, Number] as PropType<SelectValue>,
},
value: someType<SelectValue>([Array, Object, String, Number]),
defaultValue: someType<SelectValue>([Array, Object, String, Number]),
notFoundContent: PropTypes.any,
suffixIcon: PropTypes.any,
itemIcon: PropTypes.any,
size: String as PropType<SizeType>,
mode: String as PropType<'multiple' | 'tags' | 'SECRET_COMBOBOX_MODE_DO_NOT_USE'>,
bordered: { type: Boolean, default: true },
size: stringType<SizeType>(),
mode: stringType<'multiple' | 'tags' | 'SECRET_COMBOBOX_MODE_DO_NOT_USE'>(),
bordered: booleanType(true),
transitionName: String,
choiceTransitionName: { type: String, default: '' },
placement: String as PropType<SelectCommonPlacement>,
status: String as PropType<InputStatus>,
'onUpdate:value': Function as PropType<(val: SelectValue) => void>,
choiceTransitionName: stringType(''),
placement: stringType<SelectCommonPlacement>(),
status: stringType<InputStatus>(),
'onUpdate:value': functionType<(val: SelectValue) => void>(),
});

export type SelectProps = Partial<ExtractPropTypes<ReturnType<typeof selectProps>>>;
Expand Down Expand Up @@ -123,6 +123,10 @@ const Select = defineComponent({
getPrefixCls,
getPopupContainer,
} = useConfigInject('select', props);

// style
const [wrapSSR, hashId] = useStyle(prefixCls);

const rootPrefixCls = computed(() => getPrefixCls());
// ===================== Placement =====================
const placement = computed(() => {
Expand Down Expand Up @@ -150,6 +154,7 @@ const Select = defineComponent({
[`${prefixCls.value}-in-form-item`]: formItemInputContext.isFormItemInput,
},
getStatusClassNames(prefixCls.value, mergedStatus.value, formItemInputContext.hasFeedback),
hashId.value,
),
);
const triggerChange: SelectProps['onChange'] = (...args) => {
Expand Down Expand Up @@ -224,10 +229,15 @@ const Select = defineComponent({
'status',
]);

const rcSelectRtlDropdownClassName = classNames(dropdownClassName, {
[`${prefixCls.value}-dropdown-${direction.value}`]: direction.value === 'rtl',
});
return (
const rcSelectRtlDropdownClassName = classNames(
dropdownClassName,
{
[`${prefixCls.value}-dropdown-${direction.value}`]: direction.value === 'rtl',
},
hashId.value,
);

return wrapSSR(
<RcSelect
ref={selectRef}
virtual={virtual}
Expand Down Expand Up @@ -259,7 +269,7 @@ const Select = defineComponent({
optionLabelRender={slots.optionLabel}
maxTagPlaceholder={props.maxTagPlaceholder || slots.maxTagPlaceholder}
showArrow={hasFeedback || showArrow}
></RcSelect>
></RcSelect>,
);
};
},
Expand Down
6 changes: 3 additions & 3 deletions components/select/index.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ category: Components
subtitle: 选择器
type: 数据录入
title: Select
cover: https://gw.alipayobjects.com/zos/alicdn/_0XzgOis7/Select.svg
cover: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*zo76T7KQx2UAAAAAAAAAAAAADrJ8AQ/original
---

下拉选择器。
Expand Down Expand Up @@ -60,8 +60,8 @@ cover: https://gw.alipayobjects.com/zos/alicdn/_0XzgOis7/Select.svg
| placement | 选择框弹出的位置 | `bottomLeft` `bottomRight` `topLeft` `topRight` | bottomLeft | 3.3.0 |
| removeIcon | 自定义的多选框清除图标 | VNode \| slot | - | |
| searchValue | 控制搜索文本 | string | - | |
| showArrow | 是否显示下拉小箭头 | boolean | 单选为true,多选为false | |
| showSearch | 配置是否可搜索 | boolean | 单选为false,多选为true | |
| showArrow | 是否显示下拉小箭头 | boolean | 单选为 true,多选为 false | |
| showSearch | 配置是否可搜索 | boolean | 单选为 false,多选为 true | |
| size | 选择框大小,可选 `large` `small` | string | default | |
| status | 设置校验状态 | 'error' \| 'warning' | - | 3.3.0 |
| suffixIcon | 自定义的选择框后缀图标 | VNode \| slot | - | |
Expand Down
166 changes: 166 additions & 0 deletions components/select/style/dropdown.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
import type { CSSObject } from '../../_util/cssinjs';
import type { SelectToken } from '.';
import {
initMoveMotion,
initSlideMotion,
slideDownIn,
slideDownOut,
slideUpIn,
slideUpOut,
} from '../../_style/motion';
import type { GenerateStyle } from '../../theme/internal';
import { resetComponent, textEllipsis } from '../../_style';

const genItemStyle: GenerateStyle<SelectToken, CSSObject> = token => {
const { controlPaddingHorizontal } = token;

return {
position: 'relative',
display: 'block',
minHeight: token.controlHeight,
padding: `${
(token.controlHeight - token.fontSize * token.lineHeight) / 2
}px ${controlPaddingHorizontal}px`,
color: token.colorText,
fontWeight: 'normal',
fontSize: token.fontSize,
lineHeight: token.lineHeight,
boxSizing: 'border-box',
};
};

const genSingleStyle: GenerateStyle<SelectToken> = token => {
const { antCls, componentCls } = token;

const selectItemCls = `${componentCls}-item`;

return [
{
[`${componentCls}-dropdown`]: {
// ========================== Popup ==========================
...resetComponent(token),

position: 'absolute',
top: -9999,
zIndex: token.zIndexPopup,
boxSizing: 'border-box',
padding: token.paddingXXS,
overflow: 'hidden',
fontSize: token.fontSize,
// Fix select render lag of long text in chrome
// https://github.com/ant-design/ant-design/issues/11456
// https://github.com/ant-design/ant-design/issues/11843
fontVariant: 'initial',
backgroundColor: token.colorBgElevated,
borderRadius: token.borderRadiusLG,
outline: 'none',
boxShadow: token.boxShadowSecondary,

[`
&${antCls}-slide-up-enter${antCls}-slide-up-enter-active${componentCls}-dropdown-placement-bottomLeft,
&${antCls}-slide-up-appear${antCls}-slide-up-appear-active${componentCls}-dropdown-placement-bottomLeft
`]: {
animationName: slideUpIn,
},

[`
&${antCls}-slide-up-enter${antCls}-slide-up-enter-active${componentCls}-dropdown-placement-topLeft,
&${antCls}-slide-up-appear${antCls}-slide-up-appear-active${componentCls}-dropdown-placement-topLeft
`]: {
animationName: slideDownIn,
},

[`&${antCls}-slide-up-leave${antCls}-slide-up-leave-active${componentCls}-dropdown-placement-bottomLeft`]:
{
animationName: slideUpOut,
},

[`&${antCls}-slide-up-leave${antCls}-slide-up-leave-active${componentCls}-dropdown-placement-topLeft`]:
{
animationName: slideDownOut,
},

'&-hidden': {
display: 'none',
},

'&-empty': {
color: token.colorTextDisabled,
},

// ========================= Options =========================
[`${selectItemCls}-empty`]: {
...genItemStyle(token),
color: token.colorTextDisabled,
},

[`${selectItemCls}`]: {
...genItemStyle(token),
cursor: 'pointer',
transition: `background ${token.motionDurationSlow} ease`,
borderRadius: token.borderRadiusSM,

// =========== Group ============
'&-group': {
color: token.colorTextDescription,
fontSize: token.fontSizeSM,
cursor: 'default',
},

// =========== Option ===========
'&-option': {
display: 'flex',

'&-content': {
flex: 'auto',
...textEllipsis,
},

'&-state': {
flex: 'none',
},

[`&-active:not(${selectItemCls}-option-disabled)`]: {
backgroundColor: token.controlItemBgHover,
},

[`&-selected:not(${selectItemCls}-option-disabled)`]: {
color: token.colorText,
fontWeight: token.fontWeightStrong,
backgroundColor: token.controlItemBgActive,

[`${selectItemCls}-option-state`]: {
color: token.colorPrimary,
},
},
'&-disabled': {
[`&${selectItemCls}-option-selected`]: {
backgroundColor: token.colorBgContainerDisabled,
},

color: token.colorTextDisabled,
cursor: 'not-allowed',
},

'&-grouped': {
paddingInlineStart: token.controlPaddingHorizontal * 2,
},
},
},

// =========================== RTL ===========================
'&-rtl': {
direction: 'rtl',
},
},
},

// Follow code may reuse in other components
initSlideMotion(token, 'slide-up'),
initSlideMotion(token, 'slide-down'),
initMoveMotion(token, 'move-up'),
initMoveMotion(token, 'move-down'),
];
};

export default genSingleStyle;
Loading