果冻橙
2 years ago
committed by
GitHub
9 changed files with 973 additions and 31 deletions
@ -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', |
||||
), |
||||
]; |
||||
} |
Loading…
Reference in new issue