mirror of
https://github.com/ant-design/ant-design.git
synced 2025-01-18 14:13:37 +08:00
refactor: Cascader cssinjs (#34374)
This commit is contained in:
parent
4f2a8bed37
commit
de24558a6c
@ -98,6 +98,8 @@ export interface DerivativeToken extends Omit<DesignToken, 'duration'> {
|
|||||||
warningOutlineColor: string;
|
warningOutlineColor: string;
|
||||||
itemActiveBackground: string;
|
itemActiveBackground: string;
|
||||||
|
|
||||||
|
highlightColor: string;
|
||||||
|
|
||||||
linkColor: string;
|
linkColor: string;
|
||||||
fontSizeSM: number;
|
fontSizeSM: number;
|
||||||
fontSizeLG: number;
|
fontSizeLG: number;
|
||||||
@ -154,6 +156,8 @@ function derivative(designToken: DesignToken): DerivativeToken {
|
|||||||
warningHoverColor: warningColors[4],
|
warningHoverColor: warningColors[4],
|
||||||
warningOutlineColor: new TinyColor(warningColor).setAlpha(0.2).toRgbString(),
|
warningOutlineColor: new TinyColor(warningColor).setAlpha(0.2).toRgbString(),
|
||||||
|
|
||||||
|
highlightColor: errorColors[4], // FIXME: Should not align with error color
|
||||||
|
|
||||||
itemActiveBackground: primaryColors[0],
|
itemActiveBackground: primaryColors[0],
|
||||||
|
|
||||||
linkColor: primaryColor,
|
linkColor: primaryColor,
|
||||||
|
@ -22,6 +22,8 @@ import getIcons from '../select/utils/iconUtil';
|
|||||||
import { getTransitionName, getTransitionDirection, SelectCommonPlacement } from '../_util/motion';
|
import { getTransitionName, getTransitionDirection, SelectCommonPlacement } from '../_util/motion';
|
||||||
import { FormItemStatusContext } from '../form/context';
|
import { FormItemStatusContext } from '../form/context';
|
||||||
import { getMergedStatus, getStatusClassNames, InputStatus } from '../_util/statusUtils';
|
import { getMergedStatus, getStatusClassNames, InputStatus } from '../_util/statusUtils';
|
||||||
|
import useStyle from './style';
|
||||||
|
import useSelectStyle from '../select/style';
|
||||||
|
|
||||||
// Align the design since we use `rc-select` in root. This help:
|
// Align the design since we use `rc-select` in root. This help:
|
||||||
// - List search content will show all content
|
// - List search content will show all content
|
||||||
@ -140,6 +142,7 @@ const Cascader = React.forwardRef((props: CascaderProps<any>, ref: React.Ref<Cas
|
|||||||
direction: rootDirection,
|
direction: rootDirection,
|
||||||
// virtual,
|
// virtual,
|
||||||
// dropdownMatchSelectWidth,
|
// dropdownMatchSelectWidth,
|
||||||
|
iconPrefixCls,
|
||||||
} = useContext(ConfigContext);
|
} = useContext(ConfigContext);
|
||||||
|
|
||||||
const mergedDirection = direction || rootDirection;
|
const mergedDirection = direction || rootDirection;
|
||||||
@ -172,6 +175,9 @@ const Cascader = React.forwardRef((props: CascaderProps<any>, ref: React.Ref<Cas
|
|||||||
const prefixCls = getPrefixCls('select', customizePrefixCls);
|
const prefixCls = getPrefixCls('select', customizePrefixCls);
|
||||||
const cascaderPrefixCls = getPrefixCls('cascader', customizePrefixCls);
|
const cascaderPrefixCls = getPrefixCls('cascader', customizePrefixCls);
|
||||||
|
|
||||||
|
const [wrapSelectSSR, hashId] = useSelectStyle(rootPrefixCls, prefixCls, iconPrefixCls);
|
||||||
|
const [wrapCascaderSSR] = useStyle(cascaderPrefixCls);
|
||||||
|
|
||||||
// =================== Dropdown ====================
|
// =================== Dropdown ====================
|
||||||
const mergedDropdownClassName = classNames(
|
const mergedDropdownClassName = classNames(
|
||||||
dropdownClassName || popupClassName,
|
dropdownClassName || popupClassName,
|
||||||
@ -179,6 +185,7 @@ const Cascader = React.forwardRef((props: CascaderProps<any>, ref: React.Ref<Cas
|
|||||||
{
|
{
|
||||||
[`${cascaderPrefixCls}-dropdown-rtl`]: mergedDirection === 'rtl',
|
[`${cascaderPrefixCls}-dropdown-rtl`]: mergedDirection === 'rtl',
|
||||||
},
|
},
|
||||||
|
hashId,
|
||||||
);
|
);
|
||||||
|
|
||||||
// ==================== Search =====================
|
// ==================== Search =====================
|
||||||
@ -245,7 +252,7 @@ const Cascader = React.forwardRef((props: CascaderProps<any>, ref: React.Ref<Cas
|
|||||||
};
|
};
|
||||||
|
|
||||||
// ==================== Render =====================
|
// ==================== Render =====================
|
||||||
return (
|
const renderNode = (
|
||||||
<RcCascader
|
<RcCascader
|
||||||
prefixCls={prefixCls}
|
prefixCls={prefixCls}
|
||||||
className={classNames(
|
className={classNames(
|
||||||
@ -258,6 +265,7 @@ const Cascader = React.forwardRef((props: CascaderProps<any>, ref: React.Ref<Cas
|
|||||||
},
|
},
|
||||||
getStatusClassNames(prefixCls, mergedStatus, hasFeedback),
|
getStatusClassNames(prefixCls, mergedStatus, hasFeedback),
|
||||||
className,
|
className,
|
||||||
|
hashId,
|
||||||
)}
|
)}
|
||||||
{...(restProps as any)}
|
{...(restProps as any)}
|
||||||
direction={mergedDirection}
|
direction={mergedDirection}
|
||||||
@ -284,6 +292,8 @@ const Cascader = React.forwardRef((props: CascaderProps<any>, ref: React.Ref<Cas
|
|||||||
showArrow={hasFeedback || showArrow}
|
showArrow={hasFeedback || showArrow}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
return wrapCascaderSSR(wrapSelectSSR(renderNode));
|
||||||
}) as (<OptionType extends BaseOptionType | DefaultOptionType = DefaultOptionType>(
|
}) as (<OptionType extends BaseOptionType | DefaultOptionType = DefaultOptionType>(
|
||||||
props: React.PropsWithChildren<CascaderProps<OptionType>> & { ref?: React.Ref<CascaderRef> },
|
props: React.PropsWithChildren<CascaderProps<OptionType>> & { ref?: React.Ref<CascaderRef> },
|
||||||
) => React.ReactElement) & {
|
) => React.ReactElement) & {
|
||||||
|
@ -1,104 +1,104 @@
|
|||||||
@import '../../style/themes/index';
|
// @import '../../style/themes/index';
|
||||||
@import '../../style/mixins/index';
|
// @import '../../style/mixins/index';
|
||||||
@import '../../input/style/mixin';
|
// @import '../../input/style/mixin';
|
||||||
@import '../../checkbox/style/mixin';
|
// @import '../../checkbox/style/mixin';
|
||||||
|
|
||||||
@cascader-prefix-cls: ~'@{ant-prefix}-cascader';
|
// @cascader-prefix-cls: ~'@{ant-prefix}-cascader';
|
||||||
|
|
||||||
.antCheckboxFn(@checkbox-prefix-cls: ~'@{cascader-prefix-cls}-checkbox');
|
// .antCheckboxFn(@checkbox-prefix-cls: ~'@{cascader-prefix-cls}-checkbox');
|
||||||
|
|
||||||
.@{cascader-prefix-cls} {
|
// .@{cascader-prefix-cls} {
|
||||||
width: 184px;
|
// width: 184px;
|
||||||
|
|
||||||
&-checkbox {
|
// &-checkbox {
|
||||||
top: 0;
|
// top: 0;
|
||||||
margin-right: @padding-xs;
|
// margin-right: @padding-xs;
|
||||||
}
|
// }
|
||||||
|
|
||||||
&-menus {
|
// &-menus {
|
||||||
display: flex;
|
// display: flex;
|
||||||
flex-wrap: nowrap;
|
// flex-wrap: nowrap;
|
||||||
align-items: flex-start;
|
// align-items: flex-start;
|
||||||
|
|
||||||
&.@{cascader-prefix-cls}-menu-empty {
|
// &.@{cascader-prefix-cls}-menu-empty {
|
||||||
.@{cascader-prefix-cls}-menu {
|
// .@{cascader-prefix-cls}-menu {
|
||||||
width: 100%;
|
// width: 100%;
|
||||||
height: auto;
|
// height: auto;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
&-menu {
|
// &-menu {
|
||||||
min-width: 111px;
|
// min-width: 111px;
|
||||||
height: 180px;
|
// height: 180px;
|
||||||
margin: 0;
|
// margin: 0;
|
||||||
margin: -@dropdown-edge-child-vertical-padding 0;
|
// margin: -@dropdown-edge-child-vertical-padding 0;
|
||||||
padding: @cascader-dropdown-edge-child-vertical-padding 0;
|
// padding: @cascader-dropdown-edge-child-vertical-padding 0;
|
||||||
overflow: auto;
|
// overflow: auto;
|
||||||
vertical-align: top;
|
// vertical-align: top;
|
||||||
list-style: none;
|
// list-style: none;
|
||||||
border-right: @border-width-base @border-style-base @cascader-menu-border-color-split;
|
// border-right: @border-width-base @border-style-base @cascader-menu-border-color-split;
|
||||||
-ms-overflow-style: -ms-autohiding-scrollbar; // https://github.com/ant-design/ant-design/issues/11857
|
// -ms-overflow-style: -ms-autohiding-scrollbar; // https://github.com/ant-design/ant-design/issues/11857
|
||||||
|
|
||||||
&-item {
|
// &-item {
|
||||||
display: flex;
|
// display: flex;
|
||||||
flex-wrap: nowrap;
|
// flex-wrap: nowrap;
|
||||||
align-items: center;
|
// align-items: center;
|
||||||
padding: @cascader-dropdown-vertical-padding @control-padding-horizontal;
|
// padding: @cascader-dropdown-vertical-padding @control-padding-horizontal;
|
||||||
overflow: hidden;
|
// overflow: hidden;
|
||||||
line-height: @cascader-dropdown-line-height;
|
// line-height: @cascader-dropdown-line-height;
|
||||||
white-space: nowrap;
|
// white-space: nowrap;
|
||||||
text-overflow: ellipsis;
|
// text-overflow: ellipsis;
|
||||||
cursor: pointer;
|
// cursor: pointer;
|
||||||
transition: all 0.3s;
|
// transition: all 0.3s;
|
||||||
|
|
||||||
&:hover {
|
// &:hover {
|
||||||
background: @item-hover-bg;
|
// background: @item-hover-bg;
|
||||||
}
|
// }
|
||||||
|
|
||||||
&-disabled {
|
// &-disabled {
|
||||||
color: @disabled-color;
|
// color: @disabled-color;
|
||||||
cursor: not-allowed;
|
// cursor: not-allowed;
|
||||||
|
|
||||||
&:hover {
|
// &:hover {
|
||||||
background: transparent;
|
// background: transparent;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
.@{cascader-prefix-cls}-menu-empty & {
|
// .@{cascader-prefix-cls}-menu-empty & {
|
||||||
color: @disabled-color;
|
// color: @disabled-color;
|
||||||
cursor: default;
|
// cursor: default;
|
||||||
pointer-events: none;
|
// pointer-events: none;
|
||||||
}
|
// }
|
||||||
|
|
||||||
&-active:not(&-disabled) {
|
// &-active:not(&-disabled) {
|
||||||
&,
|
// &,
|
||||||
&:hover {
|
// &:hover {
|
||||||
font-weight: @select-item-selected-font-weight;
|
// font-weight: @select-item-selected-font-weight;
|
||||||
background-color: @cascader-item-selected-bg;
|
// background-color: @cascader-item-selected-bg;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
&-content {
|
// &-content {
|
||||||
flex: auto;
|
// flex: auto;
|
||||||
}
|
// }
|
||||||
|
|
||||||
&-expand &-expand-icon,
|
// &-expand &-expand-icon,
|
||||||
&-loading-icon {
|
// &-loading-icon {
|
||||||
margin-left: @padding-xss;
|
// margin-left: @padding-xss;
|
||||||
color: @text-color-secondary;
|
// color: @text-color-secondary;
|
||||||
font-size: 10px;
|
// font-size: 10px;
|
||||||
|
|
||||||
.@{cascader-prefix-cls}-menu-item-disabled& {
|
// .@{cascader-prefix-cls}-menu-item-disabled& {
|
||||||
color: @disabled-color;
|
// color: @disabled-color;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
&-keyword {
|
// &-keyword {
|
||||||
color: @highlight-color;
|
// color: @highlight-color;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
@import './rtl';
|
// @import './rtl';
|
||||||
|
@ -1,8 +1,172 @@
|
|||||||
import '../../style/index.less';
|
// import '../../style/index.less';
|
||||||
import './index.less';
|
// import './index.less';
|
||||||
|
|
||||||
// style dependencies
|
// // style dependencies
|
||||||
import '../../empty/style';
|
// import '../../empty/style';
|
||||||
import '../../select/style';
|
// import '../../select/style';
|
||||||
|
|
||||||
// deps-lint-skip: form
|
// // deps-lint-skip: form
|
||||||
|
|
||||||
|
// deps-lint-skip-all
|
||||||
|
import { CSSInterpolation } from '@ant-design/cssinjs';
|
||||||
|
import {
|
||||||
|
DerivativeToken,
|
||||||
|
useStyleRegister,
|
||||||
|
useToken,
|
||||||
|
UseComponentStyleResult,
|
||||||
|
} from '../../_util/theme';
|
||||||
|
import { getStyle as getCheckboxStyle } from '../../checkbox/style';
|
||||||
|
|
||||||
|
interface CascaderToken extends DerivativeToken {
|
||||||
|
cascaderCls: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
// =============================== Base ===============================
|
||||||
|
const genBaseStyle = (token: CascaderToken): CSSInterpolation => {
|
||||||
|
const { cascaderCls } = token;
|
||||||
|
const cascaderMenuItemCls = `${cascaderCls}-menu-item`;
|
||||||
|
const iconCls = `
|
||||||
|
${cascaderMenuItemCls}-expand ${cascaderMenuItemCls}-expand-icon,
|
||||||
|
${cascaderMenuItemCls}-loading-icon
|
||||||
|
`;
|
||||||
|
|
||||||
|
const itemPaddingVertical = Math.round(
|
||||||
|
(token.controlHeight - token.fontSize * token.lineHeight) / 2,
|
||||||
|
);
|
||||||
|
|
||||||
|
return [
|
||||||
|
// =====================================================
|
||||||
|
// == Control ==
|
||||||
|
// =====================================================
|
||||||
|
{
|
||||||
|
[cascaderCls]: {
|
||||||
|
width: 184, // FIXME: hardcode in v4
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
// =====================================================
|
||||||
|
// == Popup ==
|
||||||
|
// =====================================================
|
||||||
|
{
|
||||||
|
[`${cascaderCls}-dropdown`]: {
|
||||||
|
[cascaderCls]: {
|
||||||
|
// ================== Checkbox ==================
|
||||||
|
'&-checkbox': {
|
||||||
|
top: 0,
|
||||||
|
marginInlineEnd: token.paddingXS,
|
||||||
|
},
|
||||||
|
|
||||||
|
// ==================== Menu ====================
|
||||||
|
// >>> Menus
|
||||||
|
'&-menus': {
|
||||||
|
display: 'flex',
|
||||||
|
flexWrap: 'nowrap',
|
||||||
|
alignItems: 'flex-start',
|
||||||
|
|
||||||
|
[`&${cascaderCls}-menu-empty`]: {
|
||||||
|
[`${cascaderCls}-menu`]: {
|
||||||
|
width: '100%',
|
||||||
|
height: 'auto',
|
||||||
|
|
||||||
|
[cascaderMenuItemCls]: {
|
||||||
|
color: token.textColorDisabled,
|
||||||
|
cursor: 'default',
|
||||||
|
pointerEvents: 'none',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
// >>> Menu
|
||||||
|
'&-menu': {
|
||||||
|
minWidth: 111, // FIXME: hardcode in v4
|
||||||
|
height: 180, // FIXME: hardcode in v4
|
||||||
|
margin: `-${token.paddingXS}px 0`,
|
||||||
|
padding: `${token.paddingXS}px 0`,
|
||||||
|
overflow: 'auto',
|
||||||
|
verticalAlign: 'top',
|
||||||
|
listStyle: 'none',
|
||||||
|
borderInlineEnd: `${token.borderWidth}px ${token.borderStyle} ${token.borderColorSplit}`,
|
||||||
|
'-ms-overflow-style': '-ms-autohiding-scrollbar', // https://github.com/ant-design/ant-design/issues/11857
|
||||||
|
|
||||||
|
'&-item': {
|
||||||
|
display: 'flex',
|
||||||
|
flexWrap: 'nowrap',
|
||||||
|
alignItems: 'center',
|
||||||
|
padding: `${itemPaddingVertical}px ${token.paddingSM}px`,
|
||||||
|
overflow: 'hidden',
|
||||||
|
lineHeight: token.lineHeight,
|
||||||
|
whiteSpace: 'nowrap',
|
||||||
|
textOverflow: 'ellipsis',
|
||||||
|
cursor: 'pointer',
|
||||||
|
transition: `all ${token.duration}`,
|
||||||
|
|
||||||
|
'&:hover': {
|
||||||
|
background: token.itemHoverBackground,
|
||||||
|
},
|
||||||
|
' &-disabled': {
|
||||||
|
color: token.textColorDisabled,
|
||||||
|
cursor: 'not-allowed',
|
||||||
|
|
||||||
|
'&:hover': {
|
||||||
|
background: 'transparent',
|
||||||
|
},
|
||||||
|
|
||||||
|
[iconCls]: {
|
||||||
|
color: token.textColorDisabled,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
[`&-active:not(${cascaderMenuItemCls}-disabled)`]: {
|
||||||
|
[`&, &:hover`]: {
|
||||||
|
fontWeight: 600, // FIXME: hardcode
|
||||||
|
backgroundColor: token.itemActiveBackground,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
'&-content': {
|
||||||
|
flex: 'auto',
|
||||||
|
},
|
||||||
|
|
||||||
|
[iconCls]: {
|
||||||
|
marginInlineStart: token.paddingXXS,
|
||||||
|
color: token.textColorSecondary,
|
||||||
|
fontSize: 10, // FIXME: hardcode in v4
|
||||||
|
},
|
||||||
|
|
||||||
|
'&-keyword': {
|
||||||
|
color: token.highlightColor,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// =====================================================
|
||||||
|
// == RTL ==
|
||||||
|
// =====================================================
|
||||||
|
{
|
||||||
|
[`${cascaderCls}-dropdown-rtl`]: {
|
||||||
|
direction: 'rtl',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
// ============================== Export ==============================
|
||||||
|
export default function useStyle(prefixCls: string): UseComponentStyleResult {
|
||||||
|
const [theme, token, hashId] = useToken();
|
||||||
|
|
||||||
|
const cascaderToken: CascaderToken = {
|
||||||
|
...token,
|
||||||
|
cascaderCls: `.${prefixCls}`,
|
||||||
|
};
|
||||||
|
|
||||||
|
return [
|
||||||
|
useStyleRegister({ theme, token, hashId, path: [prefixCls] }, () => [
|
||||||
|
getCheckboxStyle(`${prefixCls}-checkbox`, token, hashId),
|
||||||
|
genBaseStyle(cascaderToken),
|
||||||
|
]),
|
||||||
|
hashId,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user