parent
							
								
									9df8317ece
								
							
						
					
					
						commit
						39e5824699
					
				|  | @ -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. | ||||
|  |  | |||
|  | @ -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'; | ||||
|  | @ -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; | ||||
| 
 | ||||
|  | @ -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>>>; | ||||
|  | @ -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(() => { | ||||
|  | @ -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) => { | ||||
|  | @ -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} | ||||
|  | @ -259,7 +269,7 @@ const Select = defineComponent({ | |||
|           optionLabelRender={slots.optionLabel} | ||||
|           maxTagPlaceholder={props.maxTagPlaceholder || slots.maxTagPlaceholder} | ||||
|           showArrow={hasFeedback || showArrow} | ||||
|         ></RcSelect> | ||||
|         ></RcSelect>, | ||||
|       ); | ||||
|     }; | ||||
|   }, | ||||
|  |  | |||
|  | @ -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 | ||||
| --- | ||||
| 
 | ||||
| 下拉选择器。 | ||||
|  | @ -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 | - |  | | ||||
|  |  | |||
|  | @ -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; | ||||
|  | @ -1,7 +1,342 @@ | |||
| import '../../style/index.less'; | ||||
| import './index.less'; | ||||
| import type { CSSObject } from '../../_util/cssinjs'; | ||||
| import type { FullToken, GenerateStyle } from '../../theme/internal'; | ||||
| import { genComponentStyleHook, mergeToken } from '../../theme/internal'; | ||||
| import genDropdownStyle from './dropdown'; | ||||
| import genMultipleStyle from './multiple'; | ||||
| import genSingleStyle from './single'; | ||||
| import { resetComponent, resetIcon, textEllipsis } from '../../_style'; | ||||
| import { genCompactItemStyle } from '../../_style/compact-item'; | ||||
| 
 | ||||
| // style dependencies | ||||
| import '../../empty/style'; | ||||
| export interface ComponentToken { | ||||
|   zIndexPopup: number; | ||||
| } | ||||
| 
 | ||||
| // deps-lint-skip: form | ||||
| export interface SelectToken extends FullToken<'Select'> { | ||||
|   rootPrefixCls: string; | ||||
|   inputPaddingHorizontalBase: number; | ||||
| } | ||||
| 
 | ||||
| // ============================= Selector ============================= | ||||
| const genSelectorStyle: GenerateStyle<SelectToken, CSSObject> = token => { | ||||
|   const { componentCls } = token; | ||||
| 
 | ||||
|   return { | ||||
|     position: 'relative', | ||||
|     backgroundColor: token.colorBgContainer, | ||||
|     border: `${token.lineWidth}px ${token.lineType} ${token.colorBorder}`, | ||||
|     transition: `all ${token.motionDurationMid} ${token.motionEaseInOut}`, | ||||
| 
 | ||||
|     input: { | ||||
|       cursor: 'pointer', | ||||
|     }, | ||||
| 
 | ||||
|     [`${componentCls}-show-search&`]: { | ||||
|       cursor: 'text', | ||||
| 
 | ||||
|       input: { | ||||
|         cursor: 'auto', | ||||
|         color: 'inherit', | ||||
|       }, | ||||
|     }, | ||||
| 
 | ||||
|     [`${componentCls}-disabled&`]: { | ||||
|       color: token.colorTextDisabled, | ||||
|       background: token.colorBgContainerDisabled, | ||||
|       cursor: 'not-allowed', | ||||
| 
 | ||||
|       [`${componentCls}-multiple&`]: { | ||||
|         background: token.colorBgContainerDisabled, | ||||
|       }, | ||||
| 
 | ||||
|       input: { | ||||
|         cursor: 'not-allowed', | ||||
|       }, | ||||
|     }, | ||||
|   }; | ||||
| }; | ||||
| 
 | ||||
| // ============================== Status ============================== | ||||
| const genStatusStyle = ( | ||||
|   rootSelectCls: string, | ||||
|   token: { | ||||
|     componentCls: string; | ||||
|     antCls: string; | ||||
|     borderHoverColor: string; | ||||
|     outlineColor: string; | ||||
|     controlOutlineWidth: number; | ||||
|     controlLineWidth: number; | ||||
|   }, | ||||
|   overwriteDefaultBorder: boolean = false, | ||||
| ): CSSObject => { | ||||
|   const { componentCls, borderHoverColor, outlineColor, antCls } = token; | ||||
| 
 | ||||
|   const overwriteStyle: CSSObject = overwriteDefaultBorder | ||||
|     ? { | ||||
|         [`${componentCls}-selector`]: { | ||||
|           borderColor: borderHoverColor, | ||||
|         }, | ||||
|       } | ||||
|     : {}; | ||||
| 
 | ||||
|   return { | ||||
|     [rootSelectCls]: { | ||||
|       [`&:not(${componentCls}-disabled):not(${componentCls}-customize-input):not(${antCls}-pagination-size-changer)`]: | ||||
|         { | ||||
|           ...overwriteStyle, | ||||
| 
 | ||||
|           [`${componentCls}-focused& ${componentCls}-selector`]: { | ||||
|             borderColor: borderHoverColor, | ||||
|             boxShadow: `0 0 0 ${token.controlOutlineWidth}px ${outlineColor}`, | ||||
|             borderInlineEndWidth: `${token.controlLineWidth}px !important`, | ||||
|             outline: 0, | ||||
|           }, | ||||
| 
 | ||||
|           [`&:hover ${componentCls}-selector`]: { | ||||
|             borderColor: borderHoverColor, | ||||
|             borderInlineEndWidth: `${token.controlLineWidth}px !important`, | ||||
|           }, | ||||
|         }, | ||||
|     }, | ||||
|   }; | ||||
| }; | ||||
| 
 | ||||
| // ============================== Styles ============================== | ||||
| // /* Reset search input style */ | ||||
| const getSearchInputWithoutBorderStyle: GenerateStyle<SelectToken, CSSObject> = token => { | ||||
|   const { componentCls } = token; | ||||
| 
 | ||||
|   return { | ||||
|     [`${componentCls}-selection-search-input`]: { | ||||
|       margin: 0, | ||||
|       padding: 0, | ||||
|       background: 'transparent', | ||||
|       border: 'none', | ||||
|       outline: 'none', | ||||
|       appearance: 'none', | ||||
| 
 | ||||
|       '&::-webkit-search-cancel-button': { | ||||
|         display: 'none', | ||||
|         '-webkit-appearance': 'none', | ||||
|       }, | ||||
|     }, | ||||
|   }; | ||||
| }; | ||||
| 
 | ||||
| // =============================== Base =============================== | ||||
| const genBaseStyle: GenerateStyle<SelectToken> = token => { | ||||
|   const { componentCls, inputPaddingHorizontalBase, iconCls } = token; | ||||
| 
 | ||||
|   return { | ||||
|     [componentCls]: { | ||||
|       ...resetComponent(token), | ||||
|       position: 'relative', | ||||
|       display: 'inline-block', | ||||
|       cursor: 'pointer', | ||||
| 
 | ||||
|       [`&:not(${componentCls}-customize-input) ${componentCls}-selector`]: { | ||||
|         ...genSelectorStyle(token), | ||||
|         ...getSearchInputWithoutBorderStyle(token), | ||||
|       }, | ||||
| 
 | ||||
|       // [`&:not(&-disabled):hover ${selectCls}-selector`]: { | ||||
|       //   ...genHoverStyle(token), | ||||
|       // }, | ||||
| 
 | ||||
|       // ======================== Selection ======================== | ||||
|       [`${componentCls}-selection-item`]: { | ||||
|         flex: 1, | ||||
|         fontWeight: 'normal', | ||||
|         ...textEllipsis, | ||||
|       }, | ||||
| 
 | ||||
|       // ======================= Placeholder ======================= | ||||
|       [`${componentCls}-selection-placeholder`]: { | ||||
|         ...textEllipsis, | ||||
|         flex: 1, | ||||
|         color: token.colorTextPlaceholder, | ||||
|         pointerEvents: 'none', | ||||
|       }, | ||||
| 
 | ||||
|       // ========================== Arrow ========================== | ||||
|       [`${componentCls}-arrow`]: { | ||||
|         ...resetIcon(), | ||||
|         position: 'absolute', | ||||
|         top: '50%', | ||||
|         insetInlineStart: 'auto', | ||||
|         insetInlineEnd: inputPaddingHorizontalBase, | ||||
|         height: token.fontSizeIcon, | ||||
|         marginTop: -token.fontSizeIcon / 2, | ||||
|         color: token.colorTextQuaternary, | ||||
|         fontSize: token.fontSizeIcon, | ||||
|         lineHeight: 1, | ||||
|         textAlign: 'center', | ||||
|         pointerEvents: 'none', | ||||
|         display: 'flex', | ||||
|         alignItems: 'center', | ||||
| 
 | ||||
|         [iconCls]: { | ||||
|           verticalAlign: 'top', | ||||
|           transition: `transform ${token.motionDurationSlow}`, | ||||
| 
 | ||||
|           '> svg': { | ||||
|             verticalAlign: 'top', | ||||
|           }, | ||||
| 
 | ||||
|           [`&:not(${componentCls}-suffix)`]: { | ||||
|             pointerEvents: 'auto', | ||||
|           }, | ||||
|         }, | ||||
| 
 | ||||
|         [`${componentCls}-disabled &`]: { | ||||
|           cursor: 'not-allowed', | ||||
|         }, | ||||
| 
 | ||||
|         '> *:not(:last-child)': { | ||||
|           marginInlineEnd: 8, // FIXME: magic | ||||
|         }, | ||||
|       }, | ||||
| 
 | ||||
|       // ========================== Clear ========================== | ||||
|       [`${componentCls}-clear`]: { | ||||
|         position: 'absolute', | ||||
|         top: '50%', | ||||
|         insetInlineStart: 'auto', | ||||
|         insetInlineEnd: inputPaddingHorizontalBase, | ||||
|         zIndex: 1, | ||||
|         display: 'inline-block', | ||||
|         width: token.fontSizeIcon, | ||||
|         height: token.fontSizeIcon, | ||||
|         marginTop: -token.fontSizeIcon / 2, | ||||
|         color: token.colorTextQuaternary, | ||||
|         fontSize: token.fontSizeIcon, | ||||
|         fontStyle: 'normal', | ||||
|         lineHeight: 1, | ||||
|         textAlign: 'center', | ||||
|         textTransform: 'none', | ||||
|         background: token.colorBgContainer, | ||||
|         cursor: 'pointer', | ||||
|         opacity: 0, | ||||
|         transition: `color ${token.motionDurationMid} ease, opacity ${token.motionDurationSlow} ease`, | ||||
|         textRendering: 'auto', | ||||
| 
 | ||||
|         '&:before': { | ||||
|           display: 'block', | ||||
|         }, | ||||
| 
 | ||||
|         '&:hover': { | ||||
|           color: token.colorTextTertiary, | ||||
|         }, | ||||
|       }, | ||||
| 
 | ||||
|       '&:hover': { | ||||
|         [`${componentCls}-clear`]: { | ||||
|           opacity: 1, | ||||
|         }, | ||||
|       }, | ||||
|     }, | ||||
| 
 | ||||
|     // ========================= Feedback ========================== | ||||
|     [`${componentCls}-has-feedback`]: { | ||||
|       [`${componentCls}-clear`]: { | ||||
|         insetInlineEnd: inputPaddingHorizontalBase + token.fontSize + token.paddingXXS, | ||||
|       }, | ||||
|     }, | ||||
|   }; | ||||
| }; | ||||
| 
 | ||||
| // ============================== Styles ============================== | ||||
| const genSelectStyle: GenerateStyle<SelectToken> = token => { | ||||
|   const { componentCls } = token; | ||||
| 
 | ||||
|   return [ | ||||
|     { | ||||
|       [componentCls]: { | ||||
|         // ==================== BorderLess ==================== | ||||
|         [`&-borderless ${componentCls}-selector`]: { | ||||
|           backgroundColor: `transparent !important`, | ||||
|           borderColor: `transparent !important`, | ||||
|           boxShadow: `none !important`, | ||||
|         }, | ||||
| 
 | ||||
|         // ==================== In Form ==================== | ||||
|         [`&${componentCls}-in-form-item`]: { | ||||
|           width: '100%', | ||||
|         }, | ||||
|       }, | ||||
|     }, | ||||
| 
 | ||||
|     // ===================================================== | ||||
|     // ==                       LTR                       == | ||||
|     // ===================================================== | ||||
|     // Base | ||||
|     genBaseStyle(token), | ||||
| 
 | ||||
|     // Single | ||||
|     genSingleStyle(token), | ||||
| 
 | ||||
|     // Multiple | ||||
|     genMultipleStyle(token), | ||||
| 
 | ||||
|     // Dropdown | ||||
|     genDropdownStyle(token), | ||||
| 
 | ||||
|     // ===================================================== | ||||
|     // ==                       RTL                       == | ||||
|     // ===================================================== | ||||
|     { | ||||
|       [`${componentCls}-rtl`]: { | ||||
|         direction: 'rtl', | ||||
|       }, | ||||
|     }, | ||||
| 
 | ||||
|     // ===================================================== | ||||
|     // ==                     Status                      == | ||||
|     // ===================================================== | ||||
|     genStatusStyle( | ||||
|       componentCls, | ||||
|       mergeToken<any>(token, { | ||||
|         borderHoverColor: token.colorPrimaryHover, | ||||
|         outlineColor: token.controlOutline, | ||||
|       }), | ||||
|     ), | ||||
|     genStatusStyle( | ||||
|       `${componentCls}-status-error`, | ||||
|       mergeToken<any>(token, { | ||||
|         borderHoverColor: token.colorErrorHover, | ||||
|         outlineColor: token.colorErrorOutline, | ||||
|       }), | ||||
|       true, | ||||
|     ), | ||||
|     genStatusStyle( | ||||
|       `${componentCls}-status-warning`, | ||||
|       mergeToken<any>(token, { | ||||
|         borderHoverColor: token.colorWarningHover, | ||||
|         outlineColor: token.colorWarningOutline, | ||||
|       }), | ||||
|       true, | ||||
|     ), | ||||
|     // ===================================================== | ||||
|     // ==             Space Compact                       == | ||||
|     // ===================================================== | ||||
|     genCompactItemStyle(token, { | ||||
|       borderElCls: `${componentCls}-selector`, | ||||
|       focusElCls: `${componentCls}-focused`, | ||||
|     }), | ||||
|   ]; | ||||
| }; | ||||
| 
 | ||||
| // ============================== Export ============================== | ||||
| export default genComponentStyleHook( | ||||
|   'Select', | ||||
|   (token, { rootPrefixCls }) => { | ||||
|     const selectToken: SelectToken = mergeToken<SelectToken>(token, { | ||||
|       rootPrefixCls, | ||||
|       inputPaddingHorizontalBase: token.paddingSM - 1, | ||||
|     }); | ||||
| 
 | ||||
|     return [genSelectStyle(selectToken)]; | ||||
|   }, | ||||
|   token => ({ | ||||
|     zIndexPopup: token.zIndexPopupBase + 50, | ||||
|   }), | ||||
| ); | ||||
|  |  | |||
|  | @ -0,0 +1,239 @@ | |||
| import type { CSSInterpolation, CSSObject } from '../../_util/cssinjs'; | ||||
| import type { SelectToken } from '.'; | ||||
| import { mergeToken } from '../../theme/internal'; | ||||
| import { resetIcon } from '../../_style'; | ||||
| 
 | ||||
| const FIXED_ITEM_MARGIN = 2; | ||||
| 
 | ||||
| function getSelectItemStyle({ | ||||
|   controlHeightSM, | ||||
|   controlHeight, | ||||
|   lineWidth: borderWidth, | ||||
| }: SelectToken) { | ||||
|   const selectItemDist = (controlHeight - controlHeightSM) / 2 - borderWidth; | ||||
|   const selectItemMargin = Math.ceil(selectItemDist / 2); | ||||
|   return [selectItemDist, selectItemMargin]; | ||||
| } | ||||
| 
 | ||||
| function genSizeStyle(token: SelectToken, suffix?: string): CSSObject { | ||||
|   const { componentCls, iconCls } = token; | ||||
| 
 | ||||
|   const selectOverflowPrefixCls = `${componentCls}-selection-overflow`; | ||||
| 
 | ||||
|   const selectItemHeight = token.controlHeightSM; | ||||
|   const [selectItemDist] = getSelectItemStyle(token); | ||||
| 
 | ||||
|   const suffixCls = suffix ? `${componentCls}-${suffix}` : ''; | ||||
| 
 | ||||
|   return { | ||||
|     [`${componentCls}-multiple${suffixCls}`]: { | ||||
|       fontSize: token.fontSize, | ||||
| 
 | ||||
|       /** | ||||
|        * Do not merge `height` & `line-height` under style with `selection` & `search`, since chrome | ||||
|        * may update to redesign with its align logic. | ||||
|        */ | ||||
|       // =========================== Overflow =========================== | ||||
|       [selectOverflowPrefixCls]: { | ||||
|         position: 'relative', | ||||
|         display: 'flex', | ||||
|         flex: 'auto', | ||||
|         flexWrap: 'wrap', | ||||
|         maxWidth: '100%', | ||||
| 
 | ||||
|         '&-item': { | ||||
|           flex: 'none', | ||||
|           alignSelf: 'center', | ||||
|           maxWidth: '100%', | ||||
|           display: 'inline-flex', | ||||
|         }, | ||||
|       }, | ||||
| 
 | ||||
|       // ========================= Selector ========================= | ||||
|       [`${componentCls}-selector`]: { | ||||
|         display: 'flex', | ||||
|         flexWrap: 'wrap', | ||||
|         alignItems: 'center', | ||||
|         // Multiple is little different that horizontal is follow the vertical | ||||
|         padding: `${selectItemDist - FIXED_ITEM_MARGIN}px ${FIXED_ITEM_MARGIN * 2}px`, | ||||
|         borderRadius: token.borderRadius, | ||||
| 
 | ||||
|         [`${componentCls}-show-search&`]: { | ||||
|           cursor: 'text', | ||||
|         }, | ||||
| 
 | ||||
|         [`${componentCls}-disabled&`]: { | ||||
|           background: token.colorBgContainerDisabled, | ||||
|           cursor: 'not-allowed', | ||||
|         }, | ||||
| 
 | ||||
|         '&:after': { | ||||
|           display: 'inline-block', | ||||
|           width: 0, | ||||
|           margin: `${FIXED_ITEM_MARGIN}px 0`, | ||||
|           lineHeight: `${selectItemHeight}px`, | ||||
|           content: '"\\a0"', | ||||
|         }, | ||||
|       }, | ||||
| 
 | ||||
|       [` | ||||
|         &${componentCls}-show-arrow ${componentCls}-selector, | ||||
|         &${componentCls}-allow-clear ${componentCls}-selector | ||||
|       `]: { | ||||
|         paddingInlineEnd: token.fontSizeIcon + token.controlPaddingHorizontal, | ||||
|       }, | ||||
| 
 | ||||
|       // ======================== Selections ======================== | ||||
|       [`${componentCls}-selection-item`]: { | ||||
|         position: 'relative', | ||||
|         display: 'flex', | ||||
|         flex: 'none', | ||||
|         boxSizing: 'border-box', | ||||
|         maxWidth: '100%', | ||||
|         height: selectItemHeight, | ||||
|         marginTop: FIXED_ITEM_MARGIN, | ||||
|         marginBottom: FIXED_ITEM_MARGIN, | ||||
|         lineHeight: `${selectItemHeight - token.lineWidth * 2}px`, | ||||
|         background: token.colorFillSecondary, | ||||
|         border: `${token.lineWidth}px solid ${token.colorSplit}`, | ||||
|         borderRadius: token.borderRadiusSM, | ||||
|         cursor: 'default', | ||||
|         transition: `font-size ${token.motionDurationSlow}, line-height ${token.motionDurationSlow}, height ${token.motionDurationSlow}`, | ||||
|         userSelect: 'none', | ||||
|         marginInlineEnd: FIXED_ITEM_MARGIN * 2, | ||||
|         paddingInlineStart: token.paddingXS, | ||||
|         paddingInlineEnd: token.paddingXS / 2, | ||||
| 
 | ||||
|         [`${componentCls}-disabled&`]: { | ||||
|           color: token.colorTextDisabled, | ||||
|           borderColor: token.colorBorder, | ||||
|           cursor: 'not-allowed', | ||||
|         }, | ||||
| 
 | ||||
|         // It's ok not to do this, but 24px makes bottom narrow in view should adjust | ||||
|         '&-content': { | ||||
|           display: 'inline-block', | ||||
|           marginInlineEnd: token.paddingXS / 2, | ||||
|           overflow: 'hidden', | ||||
|           whiteSpace: 'pre', // fix whitespace wrapping. custom tags display all whitespace within. | ||||
|           textOverflow: 'ellipsis', | ||||
|         }, | ||||
| 
 | ||||
|         '&-remove': { | ||||
|           ...resetIcon(), | ||||
| 
 | ||||
|           display: 'inline-block', | ||||
|           color: token.colorIcon, | ||||
|           fontWeight: 'bold', | ||||
|           fontSize: 10, | ||||
|           lineHeight: 'inherit', | ||||
|           cursor: 'pointer', | ||||
| 
 | ||||
|           [`> ${iconCls}`]: { | ||||
|             verticalAlign: '-0.2em', | ||||
|           }, | ||||
| 
 | ||||
|           '&:hover': { | ||||
|             color: token.colorIconHover, | ||||
|           }, | ||||
|         }, | ||||
|       }, | ||||
| 
 | ||||
|       // ========================== Input ========================== | ||||
|       [`${selectOverflowPrefixCls}-item + ${selectOverflowPrefixCls}-item`]: { | ||||
|         [`${componentCls}-selection-search`]: { | ||||
|           marginInlineStart: 0, | ||||
|         }, | ||||
|       }, | ||||
| 
 | ||||
|       [`${componentCls}-selection-search`]: { | ||||
|         display: 'inline-flex', | ||||
|         position: 'relative', | ||||
|         maxWidth: '100%', | ||||
|         marginInlineStart: token.inputPaddingHorizontalBase - selectItemDist, | ||||
| 
 | ||||
|         [` | ||||
|           &-input, | ||||
|           &-mirror | ||||
|         `]: { | ||||
|           height: selectItemHeight, | ||||
|           fontFamily: token.fontFamily, | ||||
|           lineHeight: `${selectItemHeight}px`, | ||||
|           transition: `all ${token.motionDurationSlow}`, | ||||
|         }, | ||||
| 
 | ||||
|         '&-input': { | ||||
|           width: '100%', | ||||
|           minWidth: 4.1, // fix search cursor missing | ||||
|         }, | ||||
| 
 | ||||
|         '&-mirror': { | ||||
|           position: 'absolute', | ||||
|           top: 0, | ||||
|           insetInlineStart: 0, | ||||
|           insetInlineEnd: 'auto', | ||||
|           zIndex: 999, | ||||
|           whiteSpace: 'pre', // fix whitespace wrapping caused width calculation bug | ||||
|           visibility: 'hidden', | ||||
|         }, | ||||
|       }, | ||||
| 
 | ||||
|       // ======================= Placeholder ======================= | ||||
|       [`${componentCls}-selection-placeholder `]: { | ||||
|         position: 'absolute', | ||||
|         top: '50%', | ||||
|         insetInlineStart: token.inputPaddingHorizontalBase, | ||||
|         insetInlineEnd: token.inputPaddingHorizontalBase, | ||||
|         transform: 'translateY(-50%)', | ||||
|         transition: `all ${token.motionDurationSlow}`, | ||||
|       }, | ||||
|     }, | ||||
|   }; | ||||
| } | ||||
| 
 | ||||
| export default function genMultipleStyle(token: SelectToken): CSSInterpolation { | ||||
|   const { componentCls } = token; | ||||
| 
 | ||||
|   const smallToken = mergeToken<SelectToken>(token, { | ||||
|     controlHeight: token.controlHeightSM, | ||||
|     controlHeightSM: token.controlHeightXS, | ||||
|     borderRadius: token.borderRadiusSM, | ||||
|     borderRadiusSM: token.borderRadiusXS, | ||||
|   }); | ||||
|   const [, smSelectItemMargin] = getSelectItemStyle(token); | ||||
| 
 | ||||
|   return [ | ||||
|     genSizeStyle(token), | ||||
|     // ======================== Small ======================== | ||||
|     // Shared | ||||
|     genSizeStyle(smallToken, 'sm'), | ||||
| 
 | ||||
|     // Padding | ||||
|     { | ||||
|       [`${componentCls}-multiple${componentCls}-sm`]: { | ||||
|         [`${componentCls}-selection-placeholder`]: { | ||||
|           insetInlineStart: token.controlPaddingHorizontalSM - token.lineWidth, | ||||
|           insetInlineEnd: 'auto', | ||||
|         }, | ||||
| 
 | ||||
|         // https://github.com/ant-design/ant-design/issues/29559 | ||||
|         [`${componentCls}-selection-search`]: { | ||||
|           marginInlineStart: smSelectItemMargin, | ||||
|         }, | ||||
|       }, | ||||
|     }, | ||||
| 
 | ||||
|     // ======================== Large ======================== | ||||
|     // Shared | ||||
|     genSizeStyle( | ||||
|       mergeToken<any>(token, { | ||||
|         fontSize: token.fontSizeLG, | ||||
|         controlHeight: token.controlHeightLG, | ||||
|         controlHeightSM: token.controlHeight, | ||||
|         borderRadius: token.borderRadiusLG, | ||||
|         borderRadiusSM: token.borderRadius, | ||||
|       }), | ||||
|       'lg', | ||||
|     ), | ||||
|   ]; | ||||
| } | ||||
|  | @ -0,0 +1,192 @@ | |||
| import type { CSSInterpolation, CSSObject } from '../../_util/cssinjs'; | ||||
| import { resetComponent } from '../../_style'; | ||||
| import type { SelectToken } from '.'; | ||||
| import { mergeToken } from '../../theme/internal'; | ||||
| 
 | ||||
| function genSizeStyle(token: SelectToken, suffix?: string): CSSObject { | ||||
|   const { componentCls, inputPaddingHorizontalBase, borderRadius } = token; | ||||
| 
 | ||||
|   const selectHeightWithoutBorder = token.controlHeight - token.lineWidth * 2; | ||||
| 
 | ||||
|   const selectionItemPadding = Math.ceil(token.fontSize * 1.25); | ||||
| 
 | ||||
|   const suffixCls = suffix ? `${componentCls}-${suffix}` : ''; | ||||
| 
 | ||||
|   return { | ||||
|     [`${componentCls}-single${suffixCls}`]: { | ||||
|       fontSize: token.fontSize, | ||||
| 
 | ||||
|       // ========================= Selector ========================= | ||||
|       [`${componentCls}-selector`]: { | ||||
|         ...resetComponent(token), | ||||
| 
 | ||||
|         display: 'flex', | ||||
|         borderRadius, | ||||
| 
 | ||||
|         [`${componentCls}-selection-search`]: { | ||||
|           position: 'absolute', | ||||
|           top: 0, | ||||
|           insetInlineStart: inputPaddingHorizontalBase, | ||||
|           insetInlineEnd: inputPaddingHorizontalBase, | ||||
|           bottom: 0, | ||||
| 
 | ||||
|           '&-input': { | ||||
|             width: '100%', | ||||
|           }, | ||||
|         }, | ||||
| 
 | ||||
|         [` | ||||
|           ${componentCls}-selection-item, | ||||
|           ${componentCls}-selection-placeholder | ||||
|         `]: { | ||||
|           padding: 0, | ||||
|           lineHeight: `${selectHeightWithoutBorder}px`, | ||||
|           transition: `all ${token.motionDurationSlow}`, | ||||
| 
 | ||||
|           // Firefox inline-block position calculation is not same as Chrome & Safari. Patch this: | ||||
|           '@supports (-moz-appearance: meterbar)': { | ||||
|             lineHeight: `${selectHeightWithoutBorder}px`, | ||||
|           }, | ||||
|         }, | ||||
| 
 | ||||
|         [`${componentCls}-selection-item`]: { | ||||
|           position: 'relative', | ||||
|           userSelect: 'none', | ||||
|         }, | ||||
| 
 | ||||
|         [`${componentCls}-selection-placeholder`]: { | ||||
|           transition: 'none', | ||||
|           pointerEvents: 'none', | ||||
|         }, | ||||
| 
 | ||||
|         // For common baseline align | ||||
|         [[ | ||||
|           '&:after', | ||||
|           /* For '' value baseline align */ | ||||
|           `${componentCls}-selection-item:after`, | ||||
|           /* For undefined value baseline align */ | ||||
|           `${componentCls}-selection-placeholder:after`, | ||||
|         ].join(',')]: { | ||||
|           display: 'inline-block', | ||||
|           width: 0, | ||||
|           visibility: 'hidden', | ||||
|           content: '"\\a0"', | ||||
|         }, | ||||
|       }, | ||||
| 
 | ||||
|       [` | ||||
|         &${componentCls}-show-arrow ${componentCls}-selection-item, | ||||
|         &${componentCls}-show-arrow ${componentCls}-selection-placeholder | ||||
|       `]: { | ||||
|         paddingInlineEnd: selectionItemPadding, | ||||
|       }, | ||||
| 
 | ||||
|       // Opacity selection if open | ||||
|       [`&${componentCls}-open ${componentCls}-selection-item`]: { | ||||
|         color: token.colorTextPlaceholder, | ||||
|       }, | ||||
| 
 | ||||
|       // ========================== Input ========================== | ||||
|       // We only change the style of non-customize input which is only support by `combobox` mode. | ||||
|       // Not customize | ||||
|       [`&:not(${componentCls}-customize-input)`]: { | ||||
|         [`${componentCls}-selector`]: { | ||||
|           width: '100%', | ||||
|           height: token.controlHeight, | ||||
|           padding: `0 ${inputPaddingHorizontalBase}px`, | ||||
| 
 | ||||
|           [`${componentCls}-selection-search-input`]: { | ||||
|             height: selectHeightWithoutBorder, | ||||
|           }, | ||||
| 
 | ||||
|           '&:after': { | ||||
|             lineHeight: `${selectHeightWithoutBorder}px`, | ||||
|           }, | ||||
|         }, | ||||
|       }, | ||||
| 
 | ||||
|       [`&${componentCls}-customize-input`]: { | ||||
|         [`${componentCls}-selector`]: { | ||||
|           '&:after': { | ||||
|             display: 'none', | ||||
|           }, | ||||
| 
 | ||||
|           [`${componentCls}-selection-search`]: { | ||||
|             position: 'static', | ||||
|             width: '100%', | ||||
|           }, | ||||
| 
 | ||||
|           [`${componentCls}-selection-placeholder`]: { | ||||
|             position: 'absolute', | ||||
|             insetInlineStart: 0, | ||||
|             insetInlineEnd: 0, | ||||
|             padding: `0 ${inputPaddingHorizontalBase}px`, | ||||
| 
 | ||||
|             '&:after': { | ||||
|               display: 'none', | ||||
|             }, | ||||
|           }, | ||||
|         }, | ||||
|       }, | ||||
|     }, | ||||
|   }; | ||||
| } | ||||
| 
 | ||||
| export default function genSingleStyle(token: SelectToken): CSSInterpolation { | ||||
|   const { componentCls } = token; | ||||
| 
 | ||||
|   const inputPaddingHorizontalSM = token.controlPaddingHorizontalSM - token.lineWidth; | ||||
| 
 | ||||
|   return [ | ||||
|     genSizeStyle(token), | ||||
| 
 | ||||
|     // ======================== Small ======================== | ||||
|     // Shared | ||||
|     genSizeStyle( | ||||
|       mergeToken<any>(token, { | ||||
|         controlHeight: token.controlHeightSM, | ||||
|         borderRadius: token.borderRadiusSM, | ||||
|       }), | ||||
|       'sm', | ||||
|     ), | ||||
| 
 | ||||
|     // padding | ||||
|     { | ||||
|       [`${componentCls}-single${componentCls}-sm`]: { | ||||
|         [`&:not(${componentCls}-customize-input)`]: { | ||||
|           [`${componentCls}-selection-search`]: { | ||||
|             insetInlineStart: inputPaddingHorizontalSM, | ||||
|             insetInlineEnd: inputPaddingHorizontalSM, | ||||
|           }, | ||||
| 
 | ||||
|           [`${componentCls}-selector`]: { | ||||
|             padding: `0 ${inputPaddingHorizontalSM}px`, | ||||
|           }, | ||||
| 
 | ||||
|           // With arrow should provides `padding-right` to show the arrow | ||||
|           [`&${componentCls}-show-arrow ${componentCls}-selection-search`]: { | ||||
|             insetInlineEnd: inputPaddingHorizontalSM + token.fontSize * 1.5, | ||||
|           }, | ||||
| 
 | ||||
|           [` | ||||
|             &${componentCls}-show-arrow ${componentCls}-selection-item, | ||||
|             &${componentCls}-show-arrow ${componentCls}-selection-placeholder | ||||
|           `]: { | ||||
|             paddingInlineEnd: token.fontSize * 1.5, | ||||
|           }, | ||||
|         }, | ||||
|       }, | ||||
|     }, | ||||
| 
 | ||||
|     // ======================== Large ======================== | ||||
|     // Shared | ||||
|     genSizeStyle( | ||||
|       mergeToken<any>(token, { | ||||
|         controlHeight: token.controlHeightLG, | ||||
|         fontSize: token.fontSizeLG, | ||||
|         borderRadius: token.borderRadiusLG, | ||||
|       }), | ||||
|       'lg', | ||||
|     ), | ||||
|   ]; | ||||
| } | ||||
|  | @ -23,7 +23,7 @@ import './radio/style'; | |||
| // import './notification/style';
 | ||||
| // import './message/style';
 | ||||
| // import './spin/style';
 | ||||
| import './select/style'; | ||||
| // import './select/style';
 | ||||
| // import './switch/style';
 | ||||
| import './auto-complete/style'; | ||||
| // import './affix/style';
 | ||||
|  |  | |||
|  | @ -31,7 +31,7 @@ import type { ComponentToken as ProgressComponentToken } from '../../progress/st | |||
| import type { ComponentToken as RateComponentToken } from '../../rate/style'; | ||||
| import type { ComponentToken as ResultComponentToken } from '../../result/style'; | ||||
| // import type { ComponentToken as SegmentedComponentToken } from '../../segmented/style';
 | ||||
| // import type { ComponentToken as SelectComponentToken } from '../../select/style';
 | ||||
| import type { ComponentToken as SelectComponentToken } from '../../select/style'; | ||||
| import type { ComponentToken as SkeletonComponentToken } from '../../skeleton/style'; | ||||
| import type { ComponentToken as SliderComponentToken } from '../../slider/style'; | ||||
| import type { ComponentToken as SpaceComponentToken } from '../../space/style'; | ||||
|  | @ -90,7 +90,7 @@ export interface ComponentTokenMap { | |||
|   //   Radio?: RadioComponentToken;
 | ||||
|   Result?: ResultComponentToken; | ||||
|   //   Segmented?: SegmentedComponentToken;
 | ||||
|   //   Select?: SelectComponentToken;
 | ||||
|   Select?: SelectComponentToken; | ||||
|   Skeleton?: SkeletonComponentToken; | ||||
|   Slider?: SliderComponentToken; | ||||
|   Spin?: SpinComponentToken; | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 果冻橙
						果冻橙