mirror of
https://github.com/ant-design/ant-design.git
synced 2025-01-19 06:43:16 +08:00
refactor: Dropdown cssinjs support (#35214)
* chore: init * chore: dropdown style * chore: more style * chore: icon style * chore: more style * chore: diff shows the cache path * chore: motion support * chore: more style * feat: status * chore: sub menu style * chore: all dropdown style * fix: ts * chore: update snapshot * Update components/dropdown/style/index.tsx Co-authored-by: MadCcc <1075746765@qq.com> * chore: update style Co-authored-by: MadCcc <1075746765@qq.com>
This commit is contained in:
parent
690608d1c2
commit
b4730281a9
@ -1,6 +1,7 @@
|
||||
import type * as React from 'react';
|
||||
import type { ComponentToken as ButtonComponentToken } from '../../button/style';
|
||||
import type { ComponentToken as DividerComponentToken } from '../../divider/style';
|
||||
import type { ComponentToken as DropdownComponentToken } from '../../dropdown/style';
|
||||
import type { ComponentToken as EmptyComponentToken } from '../../empty/style';
|
||||
import type { ComponentToken as CascaderComponentToken } from '../../cascader/style';
|
||||
import type { ComponentToken as InputNumberComponentToken } from '../../input-number/style';
|
||||
@ -57,6 +58,7 @@ export interface OverrideToken {
|
||||
Descriptions?: {};
|
||||
Divider?: DividerComponentToken;
|
||||
Drawer?: {};
|
||||
Dropdown?: DropdownComponentToken;
|
||||
Empty?: EmptyComponentToken;
|
||||
Form?: {};
|
||||
Grid?: {};
|
||||
@ -133,6 +135,7 @@ export interface SeedToken extends PresetColorType {
|
||||
// Size
|
||||
sizeUnit: number;
|
||||
sizeBaseStep: number;
|
||||
sizePopupArrow: number;
|
||||
|
||||
// Control Base
|
||||
controlHeight: number;
|
||||
@ -297,6 +300,8 @@ export interface AliasToken extends Omit<DerivativeToken, OmitDerivativeKey> {
|
||||
colorBgComponentDisabled: string;
|
||||
|
||||
// =============== Legacy: should be remove ===============
|
||||
colorLoadingOpacity: number;
|
||||
|
||||
padding: number;
|
||||
margin: number;
|
||||
|
||||
|
@ -189,6 +189,7 @@ const seedToken: SeedToken = {
|
||||
// Size
|
||||
sizeUnit: 4,
|
||||
sizeBaseStep: 4,
|
||||
sizePopupArrow: 8 * Math.sqrt(2),
|
||||
|
||||
// Control Base
|
||||
controlHeight: 32,
|
||||
|
@ -99,6 +99,8 @@ export default function formatToken(derivativeToken: RawMergedToken): AliasToken
|
||||
// warningColors,
|
||||
// errorColors,
|
||||
|
||||
colorLoadingOpacity: 0.65,
|
||||
|
||||
colorSuccessSecondary: successColors[2],
|
||||
colorWarningSecondary: warningColors[2],
|
||||
colorErrorSecondary: errorColors[2],
|
||||
|
@ -9,16 +9,22 @@ export type OverrideTokenWithoutDerivative = Omit<OverrideToken, 'derivative'>;
|
||||
export type OverrideComponent = keyof OverrideTokenWithoutDerivative;
|
||||
export type GlobalTokenWithComponent<ComponentName extends OverrideComponent> = GlobalToken &
|
||||
OverrideToken[ComponentName];
|
||||
export type StyleInfo = {
|
||||
|
||||
export interface StyleInfo {
|
||||
hashId: string;
|
||||
prefixCls: string;
|
||||
rootPrefixCls: string;
|
||||
iconPrefixCls: string;
|
||||
};
|
||||
}
|
||||
|
||||
export type TokenWithCommonCls<T> = T & {
|
||||
/** Wrap component class with `.` prefix */
|
||||
componentCls: string;
|
||||
/** Origin prefix which do not have `.` prefix */
|
||||
prefixCls: string;
|
||||
/** Wrap icon class with `.` prefix */
|
||||
iconCls: string;
|
||||
/** Wrap ant prefixCls class with `.` prefix */
|
||||
antCls: string;
|
||||
};
|
||||
export type FullToken<ComponentName extends OverrideComponent> = TokenWithCommonCls<
|
||||
|
@ -1,11 +1,34 @@
|
||||
import type { GenerateStyle } from '../../_util/theme';
|
||||
import type { ButtonToken } from '.';
|
||||
|
||||
const genButtonBorderStyle = (buttonTypeCls: string, borderColor: string) => ({
|
||||
// Border
|
||||
[`> span, > ${buttonTypeCls}`]: {
|
||||
'&:not(:last-child)': {
|
||||
[`&, & > ${buttonTypeCls}`]: {
|
||||
'&:not(:disabled)': {
|
||||
borderInlineEndColor: borderColor,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
'&:not(:first-child)': {
|
||||
[`&, & > ${buttonTypeCls}`]: {
|
||||
'&:not(:disabled)': {
|
||||
borderInlineStartColor: borderColor,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const genGroupStyle: GenerateStyle<ButtonToken> = token => {
|
||||
const { componentCls, fontSizeBase, controlLineWidth, colorPrimaryHover } = token;
|
||||
const { componentCls, fontSizeBase, controlLineWidth, colorPrimaryHover, colorErrorHover } =
|
||||
token;
|
||||
|
||||
return {
|
||||
[`${componentCls}-group`]: {
|
||||
[`${componentCls}-group`]: [
|
||||
{
|
||||
position: 'relative',
|
||||
display: 'inline-flex',
|
||||
|
||||
@ -15,10 +38,6 @@ const genGroupStyle: GenerateStyle<ButtonToken> = token => {
|
||||
[`&, & > ${componentCls}`]: {
|
||||
borderStartEndRadius: 0,
|
||||
borderEndEndRadius: 0,
|
||||
|
||||
'&:not(:disabled)': {
|
||||
borderInlineEndColor: colorPrimaryHover,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@ -28,10 +47,6 @@ const genGroupStyle: GenerateStyle<ButtonToken> = token => {
|
||||
[`&, & > ${componentCls}`]: {
|
||||
borderStartStartRadius: 0,
|
||||
borderEndStartRadius: 0,
|
||||
|
||||
'&:not(:disabled)': {
|
||||
borderInlineStartColor: colorPrimaryHover,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -55,6 +70,11 @@ const genGroupStyle: GenerateStyle<ButtonToken> = token => {
|
||||
fontSize: fontSizeBase,
|
||||
},
|
||||
},
|
||||
|
||||
// Border Color
|
||||
genButtonBorderStyle(`${componentCls}-primary`, colorPrimaryHover),
|
||||
genButtonBorderStyle(`${componentCls}-danger`, colorErrorHover),
|
||||
],
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -326,7 +326,7 @@ const genSizeButtonStyle = (token: ButtonToken, sizePrefixCls: string = ''): CSS
|
||||
|
||||
// Loading
|
||||
[`&${componentCls}-loading`]: {
|
||||
opacity: 0.65,
|
||||
opacity: token.colorLoadingOpacity,
|
||||
cursor: 'default',
|
||||
},
|
||||
|
||||
|
@ -12875,7 +12875,7 @@ exports[`ConfigProvider components Dropdown normal 1`] = `
|
||||
|
||||
exports[`ConfigProvider components Dropdown prefixCls 1`] = `
|
||||
<div
|
||||
class="ant-btn-group prefix-Dropdown"
|
||||
class="ant-btn-group prefix-Dropdown-button"
|
||||
>
|
||||
<button
|
||||
class="ant-btn ant-btn-default"
|
||||
|
@ -6,6 +6,7 @@ import { ButtonHTMLType } from '../button/button';
|
||||
import { ButtonGroupProps } from '../button/button-group';
|
||||
import { ConfigContext } from '../config-provider';
|
||||
import Dropdown, { DropdownProps } from './dropdown';
|
||||
import useStyle from './style';
|
||||
|
||||
const ButtonGroup = Button.Group;
|
||||
|
||||
@ -63,7 +64,10 @@ const DropdownButton: DropdownButtonInterface = props => {
|
||||
...restProps
|
||||
} = props;
|
||||
|
||||
const prefixCls = getPrefixCls('dropdown-button', customizePrefixCls);
|
||||
const prefixCls = getPrefixCls('dropdown', customizePrefixCls);
|
||||
const buttonPrefixCls = `${prefixCls}-button`;
|
||||
const [wrapSSR, hashId] = useStyle(prefixCls);
|
||||
|
||||
const dropdownProps = {
|
||||
align,
|
||||
overlay,
|
||||
@ -106,11 +110,11 @@ const DropdownButton: DropdownButtonInterface = props => {
|
||||
|
||||
const [leftButtonToRender, rightButtonToRender] = buttonsRender!([leftButton, rightButton]);
|
||||
|
||||
return (
|
||||
<ButtonGroup {...restProps} className={classNames(prefixCls, className)}>
|
||||
return wrapSSR(
|
||||
<ButtonGroup {...restProps} className={classNames(buttonPrefixCls, className, hashId)}>
|
||||
{leftButtonToRender}
|
||||
<Dropdown {...dropdownProps}>{rightButtonToRender}</Dropdown>
|
||||
</ButtonGroup>
|
||||
</ButtonGroup>,
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -8,6 +8,7 @@ import devWarning from '../_util/devWarning';
|
||||
import { tuple } from '../_util/type';
|
||||
import { cloneElement } from '../_util/reactNode';
|
||||
import getPlacements from '../_util/placements';
|
||||
import useStyle from './style';
|
||||
|
||||
const Placements = tuple(
|
||||
'topLeft',
|
||||
@ -165,6 +166,8 @@ const Dropdown: DropdownInterface = props => {
|
||||
} = props;
|
||||
|
||||
const prefixCls = getPrefixCls('dropdown', customizePrefixCls);
|
||||
const [wrapSSR, hashId] = useStyle(prefixCls);
|
||||
|
||||
const child = React.Children.only(children) as React.ReactElement<any>;
|
||||
|
||||
const dropdownTrigger = cloneElement(child, {
|
||||
@ -178,7 +181,7 @@ const Dropdown: DropdownInterface = props => {
|
||||
disabled,
|
||||
});
|
||||
|
||||
const overlayClassNameCustomized = classNames(overlayClassName, {
|
||||
const overlayClassNameCustomized = classNames(overlayClassName, hashId, {
|
||||
[`${prefixCls}-rtl`]: direction === 'rtl',
|
||||
});
|
||||
|
||||
@ -193,7 +196,7 @@ const Dropdown: DropdownInterface = props => {
|
||||
autoAdjustOverflow: true,
|
||||
});
|
||||
|
||||
return (
|
||||
return wrapSSR(
|
||||
<RcDropdown
|
||||
alignPoint={alignPoint}
|
||||
{...props}
|
||||
@ -208,7 +211,7 @@ const Dropdown: DropdownInterface = props => {
|
||||
placement={getPlacement()}
|
||||
>
|
||||
{dropdownTrigger}
|
||||
</RcDropdown>
|
||||
</RcDropdown>,
|
||||
);
|
||||
};
|
||||
|
||||
|
26
components/dropdown/style/button.tsx
Normal file
26
components/dropdown/style/button.tsx
Normal file
@ -0,0 +1,26 @@
|
||||
import type { GenerateStyle } from '../../_util/theme';
|
||||
import type { DropdownToken } from '.';
|
||||
|
||||
const genButtonStyle: GenerateStyle<DropdownToken> = token => {
|
||||
const { componentCls, antCls, paddingXS, colorLoadingOpacity } = token;
|
||||
|
||||
return {
|
||||
[`${componentCls}-button`]: {
|
||||
whiteSpace: 'nowrap',
|
||||
|
||||
[`&${antCls}-btn-group > ${antCls}-btn`]: {
|
||||
[`&-loading, &-loading + ${antCls}-btn`]: {
|
||||
cursor: 'default',
|
||||
pointerEvents: 'none',
|
||||
opacity: colorLoadingOpacity,
|
||||
},
|
||||
|
||||
[`&:last-child:not(:first-child):not(${antCls}-btn-icon-only)`]: {
|
||||
paddingInline: paddingXS,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export default genButtonStyle;
|
@ -1,394 +1,394 @@
|
||||
@import '../../style/themes/index';
|
||||
@import '../../style/mixins/index';
|
||||
@import './status';
|
||||
// @import '../../style/themes/index';
|
||||
// @import '../../style/mixins/index';
|
||||
// @import './status';
|
||||
|
||||
@dropdown-prefix-cls: ~'@{ant-prefix}-dropdown';
|
||||
// @dropdown-prefix-cls: ~'@{ant-prefix}-dropdown';
|
||||
|
||||
.@{dropdown-prefix-cls} {
|
||||
.reset-component();
|
||||
// .@{dropdown-prefix-cls} {
|
||||
// .reset-component();
|
||||
|
||||
position: absolute;
|
||||
top: -9999px;
|
||||
left: -9999px;
|
||||
z-index: @zindex-dropdown;
|
||||
display: block;
|
||||
// position: absolute;
|
||||
// top: -9999px;
|
||||
// left: -9999px;
|
||||
// z-index: @zindex-dropdown;
|
||||
// display: block;
|
||||
|
||||
&::before {
|
||||
position: absolute;
|
||||
top: -@popover-distance + @popover-arrow-width;
|
||||
right: 0;
|
||||
bottom: -@popover-distance + @popover-arrow-width;
|
||||
left: -7px;
|
||||
z-index: -9999;
|
||||
opacity: 0.0001;
|
||||
content: ' ';
|
||||
}
|
||||
// &::before {
|
||||
// position: absolute;
|
||||
// top: -@popover-distance + @popover-arrow-width;
|
||||
// right: 0;
|
||||
// bottom: -@popover-distance + @popover-arrow-width;
|
||||
// left: -7px;
|
||||
// z-index: -9999;
|
||||
// opacity: 0.0001;
|
||||
// content: ' ';
|
||||
// }
|
||||
|
||||
&-wrap {
|
||||
position: relative;
|
||||
// &-wrap {
|
||||
// position: relative;
|
||||
|
||||
.@{ant-prefix}-btn > .@{iconfont-css-prefix}-down {
|
||||
font-size: 10px;
|
||||
}
|
||||
// .@{ant-prefix}-btn > .@{iconfont-css-prefix}-down {
|
||||
// font-size: 10px;
|
||||
// }
|
||||
|
||||
.@{iconfont-css-prefix}-down::before {
|
||||
transition: transform @animation-duration-base;
|
||||
}
|
||||
}
|
||||
// .@{iconfont-css-prefix}-down::before {
|
||||
// transition: transform @animation-duration-base;
|
||||
// }
|
||||
// }
|
||||
|
||||
&-wrap-open {
|
||||
.@{iconfont-css-prefix}-down::before {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
}
|
||||
// &-wrap-open {
|
||||
// .@{iconfont-css-prefix}-down::before {
|
||||
// transform: rotate(180deg);
|
||||
// }
|
||||
// }
|
||||
|
||||
&-hidden,
|
||||
&-menu-hidden,
|
||||
&-menu-submenu-hidden {
|
||||
display: none;
|
||||
}
|
||||
// &-hidden,
|
||||
// &-menu-hidden,
|
||||
// &-menu-submenu-hidden {
|
||||
// display: none;
|
||||
// }
|
||||
|
||||
// Offset the popover to account for the dropdown arrow
|
||||
&-show-arrow&-placement-topLeft,
|
||||
&-show-arrow&-placement-top,
|
||||
&-show-arrow&-placement-topRight {
|
||||
padding-bottom: @popover-distance;
|
||||
}
|
||||
// // Offset the popover to account for the dropdown arrow
|
||||
// &-show-arrow&-placement-topLeft,
|
||||
// &-show-arrow&-placement-top,
|
||||
// &-show-arrow&-placement-topRight {
|
||||
// padding-bottom: @popover-distance;
|
||||
// }
|
||||
|
||||
&-show-arrow&-placement-bottomLeft,
|
||||
&-show-arrow&-placement-bottom,
|
||||
&-show-arrow&-placement-bottomRight {
|
||||
padding-top: @popover-distance;
|
||||
}
|
||||
// &-show-arrow&-placement-bottomLeft,
|
||||
// &-show-arrow&-placement-bottom,
|
||||
// &-show-arrow&-placement-bottomRight {
|
||||
// padding-top: @popover-distance;
|
||||
// }
|
||||
|
||||
// Arrows
|
||||
// .popover-arrow is outer, .popover-arrow:after is inner
|
||||
// // Arrows
|
||||
// // .popover-arrow is outer, .popover-arrow:after is inner
|
||||
|
||||
&-arrow {
|
||||
position: absolute;
|
||||
z-index: 1; // lift it up so the menu wouldn't cask shadow on it
|
||||
display: block;
|
||||
width: @popover-arrow-width;
|
||||
height: @popover-arrow-width;
|
||||
background: linear-gradient(
|
||||
135deg,
|
||||
transparent 40%,
|
||||
@popover-bg 40%
|
||||
); // Use linear-gradient to prevent arrow from covering text
|
||||
.roundedArrow(@popover-arrow-width, 5px, @popover-bg);
|
||||
}
|
||||
// &-arrow {
|
||||
// position: absolute;
|
||||
// z-index: 1; // lift it up so the menu wouldn't cask shadow on it
|
||||
// display: block;
|
||||
// width: @popover-arrow-width;
|
||||
// height: @popover-arrow-width;
|
||||
// background: linear-gradient(
|
||||
// 135deg,
|
||||
// transparent 40%,
|
||||
// @popover-bg 40%
|
||||
// ); // Use linear-gradient to prevent arrow from covering text
|
||||
// .roundedArrow(@popover-arrow-width, 5px, @popover-bg);
|
||||
// }
|
||||
|
||||
&-placement-top > &-arrow,
|
||||
&-placement-topLeft > &-arrow,
|
||||
&-placement-topRight > &-arrow {
|
||||
bottom: @popover-arrow-width * sqrt((1 / 2)) + 2px;
|
||||
box-shadow: 3px 3px 7px -3px fade(@black, 10%);
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
// &-placement-top > &-arrow,
|
||||
// &-placement-topLeft > &-arrow,
|
||||
// &-placement-topRight > &-arrow {
|
||||
// bottom: @popover-arrow-width * sqrt((1 / 2)) + 2px;
|
||||
// box-shadow: 3px 3px 7px -3px fade(@black, 10%);
|
||||
// transform: rotate(45deg);
|
||||
// }
|
||||
|
||||
&-placement-top > &-arrow {
|
||||
left: 50%;
|
||||
transform: translateX(-50%) rotate(45deg);
|
||||
}
|
||||
// &-placement-top > &-arrow {
|
||||
// left: 50%;
|
||||
// transform: translateX(-50%) rotate(45deg);
|
||||
// }
|
||||
|
||||
&-placement-topLeft > &-arrow {
|
||||
left: 16px;
|
||||
}
|
||||
// &-placement-topLeft > &-arrow {
|
||||
// left: 16px;
|
||||
// }
|
||||
|
||||
&-placement-topRight > &-arrow {
|
||||
right: 16px;
|
||||
}
|
||||
// &-placement-topRight > &-arrow {
|
||||
// right: 16px;
|
||||
// }
|
||||
|
||||
&-placement-bottom > &-arrow,
|
||||
&-placement-bottomLeft > &-arrow,
|
||||
&-placement-bottomRight > &-arrow {
|
||||
top: (@popover-arrow-width + 2px) * sqrt((1 / 2));
|
||||
box-shadow: 2px 2px 5px -2px fade(@black, 10%);
|
||||
transform: rotate(-135deg) translateY(-0.5px);
|
||||
}
|
||||
// &-placement-bottom > &-arrow,
|
||||
// &-placement-bottomLeft > &-arrow,
|
||||
// &-placement-bottomRight > &-arrow {
|
||||
// top: (@popover-arrow-width + 2px) * sqrt((1 / 2));
|
||||
// box-shadow: 2px 2px 5px -2px fade(@black, 10%);
|
||||
// transform: rotate(-135deg) translateY(-0.5px);
|
||||
// }
|
||||
|
||||
&-placement-bottom > &-arrow {
|
||||
left: 50%;
|
||||
transform: translateX(-50%) rotate(-135deg) translateY(-0.5px);
|
||||
}
|
||||
// &-placement-bottom > &-arrow {
|
||||
// left: 50%;
|
||||
// transform: translateX(-50%) rotate(-135deg) translateY(-0.5px);
|
||||
// }
|
||||
|
||||
&-placement-bottomLeft > &-arrow {
|
||||
left: 16px;
|
||||
}
|
||||
// &-placement-bottomLeft > &-arrow {
|
||||
// left: 16px;
|
||||
// }
|
||||
|
||||
&-placement-bottomRight > &-arrow {
|
||||
right: 16px;
|
||||
}
|
||||
// &-placement-bottomRight > &-arrow {
|
||||
// right: 16px;
|
||||
// }
|
||||
|
||||
&-menu {
|
||||
position: relative;
|
||||
margin: 0;
|
||||
padding: @dropdown-edge-child-vertical-padding 0;
|
||||
text-align: left;
|
||||
list-style-type: none;
|
||||
background-color: @dropdown-menu-bg;
|
||||
background-clip: padding-box;
|
||||
border-radius: @border-radius-base;
|
||||
outline: none;
|
||||
box-shadow: @box-shadow-base;
|
||||
// &-menu {
|
||||
// position: relative;
|
||||
// margin: 0;
|
||||
// padding: @dropdown-edge-child-vertical-padding 0;
|
||||
// text-align: left;
|
||||
// list-style-type: none;
|
||||
// background-color: @dropdown-menu-bg;
|
||||
// background-clip: padding-box;
|
||||
// border-radius: @border-radius-base;
|
||||
// outline: none;
|
||||
// box-shadow: @box-shadow-base;
|
||||
|
||||
&-item-group-title {
|
||||
padding: 5px @control-padding-horizontal;
|
||||
color: @text-color-secondary;
|
||||
transition: all @animation-duration-slow;
|
||||
}
|
||||
// &-item-group-title {
|
||||
// padding: 5px @control-padding-horizontal;
|
||||
// color: @text-color-secondary;
|
||||
// transition: all @animation-duration-slow;
|
||||
// }
|
||||
|
||||
&-submenu-popup {
|
||||
position: absolute;
|
||||
z-index: @zindex-dropdown;
|
||||
background: transparent;
|
||||
box-shadow: none;
|
||||
transform-origin: 0 0;
|
||||
// &-submenu-popup {
|
||||
// position: absolute;
|
||||
// z-index: @zindex-dropdown;
|
||||
// background: transparent;
|
||||
// box-shadow: none;
|
||||
// transform-origin: 0 0;
|
||||
|
||||
ul,
|
||||
li {
|
||||
list-style: none;
|
||||
}
|
||||
// ul,
|
||||
// li {
|
||||
// list-style: none;
|
||||
// }
|
||||
|
||||
ul {
|
||||
margin-right: 0.3em;
|
||||
margin-left: 0.3em;
|
||||
}
|
||||
}
|
||||
// ul {
|
||||
// margin-right: 0.3em;
|
||||
// margin-left: 0.3em;
|
||||
// }
|
||||
// }
|
||||
|
||||
// ======================= Item Content =======================
|
||||
&-item {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
// // ======================= Item Content =======================
|
||||
// &-item {
|
||||
// position: relative;
|
||||
// display: flex;
|
||||
// align-items: center;
|
||||
// }
|
||||
|
||||
&-item-icon {
|
||||
min-width: 12px;
|
||||
margin-right: 8px;
|
||||
font-size: @font-size-sm;
|
||||
}
|
||||
// &-item-icon {
|
||||
// min-width: 12px;
|
||||
// margin-right: 8px;
|
||||
// font-size: @font-size-sm;
|
||||
// }
|
||||
|
||||
&-title-content {
|
||||
flex: auto;
|
||||
// &-title-content {
|
||||
// flex: auto;
|
||||
|
||||
> a {
|
||||
color: inherit;
|
||||
transition: all @animation-duration-slow;
|
||||
// > a {
|
||||
// color: inherit;
|
||||
// transition: all @animation-duration-slow;
|
||||
|
||||
&:hover {
|
||||
color: inherit;
|
||||
}
|
||||
// &:hover {
|
||||
// color: inherit;
|
||||
// }
|
||||
|
||||
&::after {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
content: '';
|
||||
}
|
||||
}
|
||||
}
|
||||
// &::after {
|
||||
// position: absolute;
|
||||
// top: 0;
|
||||
// right: 0;
|
||||
// bottom: 0;
|
||||
// left: 0;
|
||||
// content: '';
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// =========================== Item ===========================
|
||||
&-item,
|
||||
&-submenu-title {
|
||||
clear: both;
|
||||
margin: 0;
|
||||
padding: @dropdown-vertical-padding @control-padding-horizontal;
|
||||
color: @text-color;
|
||||
font-weight: normal;
|
||||
font-size: @dropdown-font-size;
|
||||
line-height: @dropdown-line-height;
|
||||
cursor: pointer;
|
||||
transition: all @animation-duration-slow;
|
||||
// // =========================== Item ===========================
|
||||
// &-item,
|
||||
// &-submenu-title {
|
||||
// clear: both;
|
||||
// margin: 0;
|
||||
// padding: @dropdown-vertical-padding @control-padding-horizontal;
|
||||
// color: @text-color;
|
||||
// font-weight: normal;
|
||||
// font-size: @dropdown-font-size;
|
||||
// line-height: @dropdown-line-height;
|
||||
// cursor: pointer;
|
||||
// transition: all @animation-duration-slow;
|
||||
|
||||
&:first-child {
|
||||
& when (@dropdown-edge-child-vertical-padding = 0) {
|
||||
border-radius: @border-radius-base @border-radius-base 0 0;
|
||||
}
|
||||
}
|
||||
// &:first-child {
|
||||
// & when (@dropdown-edge-child-vertical-padding = 0) {
|
||||
// border-radius: @border-radius-base @border-radius-base 0 0;
|
||||
// }
|
||||
// }
|
||||
|
||||
&:last-child {
|
||||
& when (@dropdown-edge-child-vertical-padding = 0) {
|
||||
border-radius: 0 0 @border-radius-base @border-radius-base;
|
||||
}
|
||||
}
|
||||
// &:last-child {
|
||||
// & when (@dropdown-edge-child-vertical-padding = 0) {
|
||||
// border-radius: 0 0 @border-radius-base @border-radius-base;
|
||||
// }
|
||||
// }
|
||||
|
||||
&-selected {
|
||||
color: @dropdown-selected-color;
|
||||
background-color: @dropdown-selected-bg;
|
||||
}
|
||||
// &-selected {
|
||||
// color: @dropdown-selected-color;
|
||||
// background-color: @dropdown-selected-bg;
|
||||
// }
|
||||
|
||||
&:hover,
|
||||
&&-active {
|
||||
background-color: @item-hover-bg;
|
||||
}
|
||||
// &:hover,
|
||||
// &&-active {
|
||||
// background-color: @item-hover-bg;
|
||||
// }
|
||||
|
||||
&-disabled {
|
||||
color: @disabled-color;
|
||||
cursor: not-allowed;
|
||||
// &-disabled {
|
||||
// color: @disabled-color;
|
||||
// cursor: not-allowed;
|
||||
|
||||
&:hover {
|
||||
color: @disabled-color;
|
||||
background-color: @dropdown-menu-submenu-disabled-bg;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
// &:hover {
|
||||
// color: @disabled-color;
|
||||
// background-color: @dropdown-menu-submenu-disabled-bg;
|
||||
// cursor: not-allowed;
|
||||
// }
|
||||
|
||||
a {
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
// a {
|
||||
// pointer-events: none;
|
||||
// }
|
||||
// }
|
||||
|
||||
&-divider {
|
||||
height: 1px;
|
||||
margin: 4px 0;
|
||||
overflow: hidden;
|
||||
line-height: 0;
|
||||
background-color: @border-color-split;
|
||||
}
|
||||
// &-divider {
|
||||
// height: 1px;
|
||||
// margin: 4px 0;
|
||||
// overflow: hidden;
|
||||
// line-height: 0;
|
||||
// background-color: @border-color-split;
|
||||
// }
|
||||
|
||||
.@{dropdown-prefix-cls}-menu-submenu-expand-icon {
|
||||
position: absolute;
|
||||
right: @padding-xs;
|
||||
// .@{dropdown-prefix-cls}-menu-submenu-expand-icon {
|
||||
// position: absolute;
|
||||
// right: @padding-xs;
|
||||
|
||||
.@{dropdown-prefix-cls}-menu-submenu-arrow-icon {
|
||||
margin-right: 0 !important;
|
||||
color: @text-color-secondary;
|
||||
font-size: 10px;
|
||||
font-style: normal;
|
||||
}
|
||||
}
|
||||
}
|
||||
// .@{dropdown-prefix-cls}-menu-submenu-arrow-icon {
|
||||
// margin-right: 0 !important;
|
||||
// color: @text-color-secondary;
|
||||
// font-size: 10px;
|
||||
// font-style: normal;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
&-item-group-list {
|
||||
margin: 0 8px;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
// &-item-group-list {
|
||||
// margin: 0 8px;
|
||||
// padding: 0;
|
||||
// list-style: none;
|
||||
// }
|
||||
|
||||
&-submenu-title {
|
||||
padding-right: @control-padding-horizontal + @font-size-sm;
|
||||
}
|
||||
// &-submenu-title {
|
||||
// padding-right: @control-padding-horizontal + @font-size-sm;
|
||||
// }
|
||||
|
||||
&-submenu-vertical {
|
||||
position: relative;
|
||||
}
|
||||
// &-submenu-vertical {
|
||||
// position: relative;
|
||||
// }
|
||||
|
||||
&-submenu-vertical > & {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 100%;
|
||||
min-width: 100%;
|
||||
margin-left: 4px;
|
||||
transform-origin: 0 0;
|
||||
}
|
||||
// &-submenu-vertical > & {
|
||||
// position: absolute;
|
||||
// top: 0;
|
||||
// left: 100%;
|
||||
// min-width: 100%;
|
||||
// margin-left: 4px;
|
||||
// transform-origin: 0 0;
|
||||
// }
|
||||
|
||||
&-submenu&-submenu-disabled .@{dropdown-prefix-cls}-menu-submenu-title {
|
||||
&,
|
||||
.@{dropdown-prefix-cls}-menu-submenu-arrow-icon {
|
||||
color: @disabled-color;
|
||||
background-color: @dropdown-menu-submenu-disabled-bg;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
// &-submenu&-submenu-disabled .@{dropdown-prefix-cls}-menu-submenu-title {
|
||||
// &,
|
||||
// .@{dropdown-prefix-cls}-menu-submenu-arrow-icon {
|
||||
// color: @disabled-color;
|
||||
// background-color: @dropdown-menu-submenu-disabled-bg;
|
||||
// cursor: not-allowed;
|
||||
// }
|
||||
// }
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/19264
|
||||
&-submenu-selected &-submenu-title {
|
||||
color: @primary-color;
|
||||
}
|
||||
}
|
||||
// // https://github.com/ant-design/ant-design/issues/19264
|
||||
// &-submenu-selected &-submenu-title {
|
||||
// color: @primary-color;
|
||||
// }
|
||||
// }
|
||||
|
||||
&.@{ant-prefix}-slide-down-enter.@{ant-prefix}-slide-down-enter-active&-placement-bottomLeft,
|
||||
&.@{ant-prefix}-slide-down-appear.@{ant-prefix}-slide-down-appear-active&-placement-bottomLeft,
|
||||
&.@{ant-prefix}-slide-down-enter.@{ant-prefix}-slide-down-enter-active&-placement-bottom,
|
||||
&.@{ant-prefix}-slide-down-appear.@{ant-prefix}-slide-down-appear-active&-placement-bottom,
|
||||
&.@{ant-prefix}-slide-down-enter.@{ant-prefix}-slide-down-enter-active&-placement-bottomRight,
|
||||
&.@{ant-prefix}-slide-down-appear.@{ant-prefix}-slide-down-appear-active&-placement-bottomRight {
|
||||
animation-name: antSlideUpIn;
|
||||
}
|
||||
// &.@{ant-prefix}-slide-down-enter.@{ant-prefix}-slide-down-enter-active&-placement-bottomLeft,
|
||||
// &.@{ant-prefix}-slide-down-appear.@{ant-prefix}-slide-down-appear-active&-placement-bottomLeft,
|
||||
// &.@{ant-prefix}-slide-down-enter.@{ant-prefix}-slide-down-enter-active&-placement-bottom,
|
||||
// &.@{ant-prefix}-slide-down-appear.@{ant-prefix}-slide-down-appear-active&-placement-bottom,
|
||||
// &.@{ant-prefix}-slide-down-enter.@{ant-prefix}-slide-down-enter-active&-placement-bottomRight,
|
||||
// &.@{ant-prefix}-slide-down-appear.@{ant-prefix}-slide-down-appear-active&-placement-bottomRight {
|
||||
// animation-name: antSlideUpIn;
|
||||
// }
|
||||
|
||||
&.@{ant-prefix}-slide-up-enter.@{ant-prefix}-slide-up-enter-active&-placement-topLeft,
|
||||
&.@{ant-prefix}-slide-up-appear.@{ant-prefix}-slide-up-appear-active&-placement-topLeft,
|
||||
&.@{ant-prefix}-slide-up-enter.@{ant-prefix}-slide-up-enter-active&-placement-top,
|
||||
&.@{ant-prefix}-slide-up-appear.@{ant-prefix}-slide-up-appear-active&-placement-top,
|
||||
&.@{ant-prefix}-slide-up-enter.@{ant-prefix}-slide-up-enter-active&-placement-topRight,
|
||||
&.@{ant-prefix}-slide-up-appear.@{ant-prefix}-slide-up-appear-active&-placement-topRight {
|
||||
animation-name: antSlideDownIn;
|
||||
}
|
||||
// &.@{ant-prefix}-slide-up-enter.@{ant-prefix}-slide-up-enter-active&-placement-topLeft,
|
||||
// &.@{ant-prefix}-slide-up-appear.@{ant-prefix}-slide-up-appear-active&-placement-topLeft,
|
||||
// &.@{ant-prefix}-slide-up-enter.@{ant-prefix}-slide-up-enter-active&-placement-top,
|
||||
// &.@{ant-prefix}-slide-up-appear.@{ant-prefix}-slide-up-appear-active&-placement-top,
|
||||
// &.@{ant-prefix}-slide-up-enter.@{ant-prefix}-slide-up-enter-active&-placement-topRight,
|
||||
// &.@{ant-prefix}-slide-up-appear.@{ant-prefix}-slide-up-appear-active&-placement-topRight {
|
||||
// animation-name: antSlideDownIn;
|
||||
// }
|
||||
|
||||
&.@{ant-prefix}-slide-down-leave.@{ant-prefix}-slide-down-leave-active&-placement-bottomLeft,
|
||||
&.@{ant-prefix}-slide-down-leave.@{ant-prefix}-slide-down-leave-active&-placement-bottom,
|
||||
&.@{ant-prefix}-slide-down-leave.@{ant-prefix}-slide-down-leave-active&-placement-bottomRight {
|
||||
animation-name: antSlideUpOut;
|
||||
}
|
||||
// &.@{ant-prefix}-slide-down-leave.@{ant-prefix}-slide-down-leave-active&-placement-bottomLeft,
|
||||
// &.@{ant-prefix}-slide-down-leave.@{ant-prefix}-slide-down-leave-active&-placement-bottom,
|
||||
// &.@{ant-prefix}-slide-down-leave.@{ant-prefix}-slide-down-leave-active&-placement-bottomRight {
|
||||
// animation-name: antSlideUpOut;
|
||||
// }
|
||||
|
||||
&.@{ant-prefix}-slide-up-leave.@{ant-prefix}-slide-up-leave-active&-placement-topLeft,
|
||||
&.@{ant-prefix}-slide-up-leave.@{ant-prefix}-slide-up-leave-active&-placement-top,
|
||||
&.@{ant-prefix}-slide-up-leave.@{ant-prefix}-slide-up-leave-active&-placement-topRight {
|
||||
animation-name: antSlideDownOut;
|
||||
}
|
||||
}
|
||||
// &.@{ant-prefix}-slide-up-leave.@{ant-prefix}-slide-up-leave-active&-placement-topLeft,
|
||||
// &.@{ant-prefix}-slide-up-leave.@{ant-prefix}-slide-up-leave-active&-placement-top,
|
||||
// &.@{ant-prefix}-slide-up-leave.@{ant-prefix}-slide-up-leave-active&-placement-topRight {
|
||||
// animation-name: antSlideDownOut;
|
||||
// }
|
||||
// }
|
||||
|
||||
.@{dropdown-prefix-cls}-trigger,
|
||||
.@{dropdown-prefix-cls}-link,
|
||||
.@{dropdown-prefix-cls}-button {
|
||||
> .@{iconfont-css-prefix}.@{iconfont-css-prefix}-down {
|
||||
font-size: 10px;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
}
|
||||
// .@{dropdown-prefix-cls}-trigger,
|
||||
// .@{dropdown-prefix-cls}-link,
|
||||
// .@{dropdown-prefix-cls}-button {
|
||||
// > .@{iconfont-css-prefix}.@{iconfont-css-prefix}-down {
|
||||
// font-size: 10px;
|
||||
// vertical-align: baseline;
|
||||
// }
|
||||
// }
|
||||
|
||||
.@{dropdown-prefix-cls}-button {
|
||||
white-space: nowrap;
|
||||
// .@{dropdown-prefix-cls}-button {
|
||||
// white-space: nowrap;
|
||||
|
||||
&.@{ant-prefix}-btn-group > .@{ant-prefix}-btn {
|
||||
&-loading,
|
||||
&-loading + .@{ant-prefix}-btn {
|
||||
cursor: default;
|
||||
pointer-events: none;
|
||||
}
|
||||
// &.@{ant-prefix}-btn-group > .@{ant-prefix}-btn {
|
||||
// &-loading,
|
||||
// &-loading + .@{ant-prefix}-btn {
|
||||
// cursor: default;
|
||||
// pointer-events: none;
|
||||
// }
|
||||
|
||||
&-loading + .@{ant-prefix}-btn::before {
|
||||
display: block;
|
||||
}
|
||||
// &-loading + .@{ant-prefix}-btn::before {
|
||||
// display: block;
|
||||
// }
|
||||
|
||||
&:last-child:not(:first-child):not(.@{ant-prefix}-btn-icon-only) {
|
||||
padding-right: @padding-xs;
|
||||
padding-left: @padding-xs;
|
||||
}
|
||||
}
|
||||
}
|
||||
// &:last-child:not(:first-child):not(.@{ant-prefix}-btn-icon-only) {
|
||||
// padding-right: @padding-xs;
|
||||
// padding-left: @padding-xs;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/4903
|
||||
.@{dropdown-prefix-cls}-menu-dark {
|
||||
&,
|
||||
.@{dropdown-prefix-cls}-menu {
|
||||
background: @menu-dark-bg;
|
||||
}
|
||||
.@{dropdown-prefix-cls}-menu-item,
|
||||
.@{dropdown-prefix-cls}-menu-submenu-title,
|
||||
.@{dropdown-prefix-cls}-menu-item > a,
|
||||
.@{dropdown-prefix-cls}-menu-item > .@{iconfont-css-prefix} + span > a {
|
||||
color: @text-color-secondary-dark;
|
||||
.@{dropdown-prefix-cls}-menu-submenu-arrow::after {
|
||||
color: @text-color-secondary-dark;
|
||||
}
|
||||
// // https://github.com/ant-design/ant-design/issues/4903
|
||||
// .@{dropdown-prefix-cls}-menu-dark {
|
||||
// &,
|
||||
// .@{dropdown-prefix-cls}-menu {
|
||||
// background: @menu-dark-bg;
|
||||
// }
|
||||
// .@{dropdown-prefix-cls}-menu-item,
|
||||
// .@{dropdown-prefix-cls}-menu-submenu-title,
|
||||
// .@{dropdown-prefix-cls}-menu-item > a,
|
||||
// .@{dropdown-prefix-cls}-menu-item > .@{iconfont-css-prefix} + span > a {
|
||||
// color: @text-color-secondary-dark;
|
||||
// .@{dropdown-prefix-cls}-menu-submenu-arrow::after {
|
||||
// color: @text-color-secondary-dark;
|
||||
// }
|
||||
|
||||
&:hover {
|
||||
color: @text-color-inverse;
|
||||
background: transparent;
|
||||
}
|
||||
}
|
||||
.@{dropdown-prefix-cls}-menu-item-selected {
|
||||
&,
|
||||
&:hover,
|
||||
> a {
|
||||
color: @text-color-inverse;
|
||||
background: @primary-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
// &:hover {
|
||||
// color: @text-color-inverse;
|
||||
// background: transparent;
|
||||
// }
|
||||
// }
|
||||
// .@{dropdown-prefix-cls}-menu-item-selected {
|
||||
// &,
|
||||
// &:hover,
|
||||
// > a {
|
||||
// color: @text-color-inverse;
|
||||
// background: @primary-color;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
@import './rtl';
|
||||
// @import './rtl';
|
||||
|
@ -1,5 +1,458 @@
|
||||
import '../../style/index.less';
|
||||
import './index.less';
|
||||
// deps-lint-skip-all
|
||||
import {
|
||||
GenerateStyle,
|
||||
resetComponent,
|
||||
FullToken,
|
||||
genComponentStyleHook,
|
||||
mergeToken,
|
||||
roundedArrow,
|
||||
} from '../../_util/theme';
|
||||
import {
|
||||
initSlideMotion,
|
||||
slideUpIn,
|
||||
slideUpOut,
|
||||
slideDownIn,
|
||||
slideDownOut,
|
||||
} from '../../style/motion';
|
||||
import genButtonStyle from './button';
|
||||
import genStatusStyle from './status';
|
||||
|
||||
// style dependencies
|
||||
import '../../button/style';
|
||||
export interface ComponentToken {
|
||||
zIndexDropdown: number;
|
||||
}
|
||||
|
||||
export interface DropdownToken extends FullToken<'Dropdown'> {
|
||||
rootPrefixCls: string;
|
||||
dropdownArrowDistance: number;
|
||||
dropdownArrowOffset: number;
|
||||
dropdownPaddingVertical: number;
|
||||
dropdownEdgeChildVerticalPadding: number;
|
||||
menuCls: string;
|
||||
}
|
||||
|
||||
// =============================== Base ===============================
|
||||
const genBaseStyle: GenerateStyle<DropdownToken> = token => {
|
||||
const {
|
||||
rootPrefixCls,
|
||||
componentCls,
|
||||
menuCls,
|
||||
zIndexDropdown,
|
||||
dropdownArrowDistance,
|
||||
dropdownArrowOffset,
|
||||
sizePopupArrow,
|
||||
antCls,
|
||||
iconCls,
|
||||
colorBgComponent,
|
||||
motionDurationMid,
|
||||
motionDurationSlow,
|
||||
dropdownPaddingVertical,
|
||||
fontSizeBase,
|
||||
dropdownEdgeChildVerticalPadding,
|
||||
radiusBase,
|
||||
colorTextDisabled,
|
||||
fontSizeIcon,
|
||||
controlPaddingHorizontal,
|
||||
} = token;
|
||||
|
||||
return [
|
||||
{
|
||||
[componentCls]: {
|
||||
...resetComponent(token),
|
||||
|
||||
position: 'absolute',
|
||||
top: -9999,
|
||||
left: {
|
||||
_skip_check_: true,
|
||||
value: -9999,
|
||||
},
|
||||
zIndex: zIndexDropdown,
|
||||
display: 'block',
|
||||
|
||||
// A placeholder out of dropdown visible range to avoid close when user moving
|
||||
'&::before': {
|
||||
position: 'absolute',
|
||||
insetBlock: -dropdownArrowDistance + sizePopupArrow,
|
||||
// insetInlineStart: -7, // FIXME: Seems not work for hidden element
|
||||
zIndex: -9999,
|
||||
opacity: 0.0001,
|
||||
content: '""',
|
||||
},
|
||||
|
||||
[`${componentCls}-wrap`]: {
|
||||
position: 'relative',
|
||||
|
||||
[`${antCls}-btn > ${iconCls}-down`]: {
|
||||
fontSize: fontSizeIcon,
|
||||
},
|
||||
|
||||
[`${iconCls}-down::before`]: {
|
||||
transition: `transform ${motionDurationMid}`,
|
||||
},
|
||||
},
|
||||
|
||||
[`${componentCls}-wrap-open`]: {
|
||||
[`${iconCls}-down::before`]: {
|
||||
transform: `rotate(180deg)`,
|
||||
},
|
||||
},
|
||||
|
||||
[`
|
||||
&-hidden,
|
||||
&-menu-hidden,
|
||||
&-menu-submenu-hidden
|
||||
`]: {
|
||||
display: 'none',
|
||||
},
|
||||
|
||||
// =============================================================
|
||||
// == Arrow ==
|
||||
// =============================================================
|
||||
// Offset the popover to account for the dropdown arrow
|
||||
[`
|
||||
&-show-arrow&-placement-topLeft,
|
||||
&-show-arrow&-placement-top,
|
||||
&-show-arrow&-placement-topRight
|
||||
`]: {
|
||||
paddingBottom: dropdownArrowDistance,
|
||||
},
|
||||
|
||||
[`
|
||||
&-show-arrow&-placement-bottomLeft,
|
||||
&-show-arrow&-placement-bottom,
|
||||
&-show-arrow&-placement-bottomRight
|
||||
`]: {
|
||||
paddingTop: dropdownArrowDistance,
|
||||
},
|
||||
|
||||
// Note: .popover-arrow is outer, .popover-arrow:after is inner
|
||||
[`${componentCls}-arrow`]: {
|
||||
position: 'absolute',
|
||||
zIndex: 1, // lift it up so the menu wouldn't cask shadow on it
|
||||
display: 'block',
|
||||
width: sizePopupArrow,
|
||||
height: sizePopupArrow,
|
||||
// Use linear-gradient to prevent arrow from covering text
|
||||
background: `linear-gradient(135deg, transparent 40%, ${colorBgComponent} 40%)`,
|
||||
|
||||
...roundedArrow(sizePopupArrow, 5, colorBgComponent),
|
||||
},
|
||||
|
||||
[`
|
||||
&-placement-top > ${componentCls}-arrow,
|
||||
&-placement-topLeft > ${componentCls}-arrow,
|
||||
&-placement-topRight > ${componentCls}-arrow
|
||||
`]: {
|
||||
bottom: sizePopupArrow * Math.sqrt(1 / 2) + 2,
|
||||
boxShadow: `3px 3px 7px -3px rgba(0, 0, 0, 0.1)`, // FIXME: hardcode
|
||||
transform: 'rotate(45deg)',
|
||||
},
|
||||
|
||||
[`&-placement-top > ${componentCls}-arrow`]: {
|
||||
left: {
|
||||
_skip_check_: true,
|
||||
value: '50%',
|
||||
},
|
||||
transform: 'translateX(-50%) rotate(45deg)',
|
||||
},
|
||||
|
||||
[`&-placement-topLeft > ${componentCls}-arrow`]: {
|
||||
left: {
|
||||
_skip_check_: true,
|
||||
value: dropdownArrowOffset,
|
||||
},
|
||||
},
|
||||
|
||||
[`&-placement-topRight > ${componentCls}-arrow`]: {
|
||||
right: {
|
||||
_skip_check_: true,
|
||||
value: dropdownArrowOffset,
|
||||
},
|
||||
},
|
||||
|
||||
[`
|
||||
&-placement-bottom > ${componentCls}-arrow,
|
||||
&-placement-bottomLeft > ${componentCls}-arrow,
|
||||
&-placement-bottomRight > ${componentCls}-arrow
|
||||
`]: {
|
||||
top: (sizePopupArrow + 2) * Math.sqrt(1 / 2),
|
||||
boxShadow: `2px 2px 5px -2px rgba(0, 0, 0, 0.1)`, // FIXME: hardcode
|
||||
transform: `rotate(-135deg) translateY(-0.5px)`, // FIXME: hardcode
|
||||
},
|
||||
|
||||
[`&-placement-bottom > ${componentCls}-arrow`]: {
|
||||
left: {
|
||||
_skip_check_: true,
|
||||
value: '50%',
|
||||
},
|
||||
transform: `translateX(-50%) rotate(-135deg) translateY(-0.5px)`,
|
||||
},
|
||||
|
||||
[`&-placement-bottomLeft > ${componentCls}-arrow`]: {
|
||||
left: {
|
||||
_skip_check_: true,
|
||||
value: dropdownArrowOffset,
|
||||
},
|
||||
},
|
||||
|
||||
[`&-placement-bottomRight > ${componentCls}-arrow`]: {
|
||||
right: {
|
||||
_skip_check_: true,
|
||||
value: dropdownArrowOffset,
|
||||
},
|
||||
},
|
||||
|
||||
// =============================================================
|
||||
// == Motion ==
|
||||
// =============================================================
|
||||
// When position is not enough for dropdown, the placement will revert.
|
||||
// We will handle this with revert motion name.
|
||||
[`&${antCls}-slide-down-enter${antCls}-slide-down-enter-active&-placement-bottomLeft,
|
||||
&${antCls}-slide-down-appear${antCls}-slide-down-appear-active&-placement-bottomLeft
|
||||
&${antCls}-slide-down-enter${antCls}-slide-down-enter-active&-placement-bottom,
|
||||
&${antCls}-slide-down-appear${antCls}-slide-down-appear-active&-placement-bottom,
|
||||
&${antCls}-slide-down-enter${antCls}-slide-down-enter-active&-placement-bottomRight,
|
||||
&${antCls}-slide-down-appear${antCls}-slide-down-appear-active&-placement-bottomRight`]: {
|
||||
animationName: slideUpIn,
|
||||
},
|
||||
|
||||
[`&${antCls}-slide-up-enter${antCls}-slide-up-enter-active&-placement-topLeft,
|
||||
&${antCls}-slide-up-appear${antCls}-slide-up-appear-active&-placement-topLeft,
|
||||
&${antCls}-slide-up-enter${antCls}-slide-up-enter-active&-placement-top,
|
||||
&${antCls}-slide-up-appear${antCls}-slide-up-appear-active&-placement-top,
|
||||
&${antCls}-slide-up-enter${antCls}-slide-up-enter-active&-placement-topRight,
|
||||
&${antCls}-slide-up-appear${antCls}-slide-up-appear-active&-placement-topRight`]: {
|
||||
animationName: slideDownIn,
|
||||
},
|
||||
|
||||
[`&${antCls}-slide-down-leave${antCls}-slide-down-leave-active&-placement-bottomLeft,
|
||||
&${antCls}-slide-down-leave${antCls}-slide-down-leave-active&-placement-bottom,
|
||||
&${antCls}-slide-down-leave${antCls}-slide-down-leave-active&-placement-bottomRight`]: {
|
||||
animationName: slideUpOut,
|
||||
},
|
||||
|
||||
[`&${antCls}-slide-up-leave${antCls}-slide-up-leave-active&-placement-topLeft,
|
||||
&${antCls}-slide-up-leave${antCls}-slide-up-leave-active&-placement-top,
|
||||
&${antCls}-slide-up-leave${antCls}-slide-up-leave-active&-placement-topRight`]: {
|
||||
animationName: slideDownOut,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
// =============================================================
|
||||
// == Menu ==
|
||||
// =============================================================
|
||||
[`${componentCls} ${menuCls}`]: {
|
||||
position: 'relative',
|
||||
margin: 0,
|
||||
},
|
||||
|
||||
[`${menuCls}-submenu-popup`]: {
|
||||
position: 'absolute',
|
||||
zIndex: zIndexDropdown,
|
||||
background: 'transparent',
|
||||
boxShadow: 'none',
|
||||
transformOrigin: '0 0',
|
||||
|
||||
'ul,li': {
|
||||
listStyle: 'none',
|
||||
},
|
||||
|
||||
ul: {
|
||||
marginInline: '0.3em',
|
||||
},
|
||||
},
|
||||
|
||||
[`${componentCls}, ${componentCls}-menu-submenu`]: {
|
||||
[menuCls]: {
|
||||
padding: `${dropdownEdgeChildVerticalPadding}px 0`,
|
||||
listStyleType: 'none',
|
||||
backgroundColor: colorBgComponent,
|
||||
backgroundClip: 'padding-box',
|
||||
borderRadius: token.controlRadius,
|
||||
outline: 'none',
|
||||
boxShadow: token.boxShadow,
|
||||
|
||||
[`${menuCls}-item-group-title`]: {
|
||||
padding: `${dropdownPaddingVertical}px ${controlPaddingHorizontal}px`,
|
||||
color: token.colorTextSecondary,
|
||||
transition: `all ${motionDurationSlow}`,
|
||||
},
|
||||
|
||||
// ======================= Item Content =======================
|
||||
[`${menuCls}-item`]: {
|
||||
position: 'relative',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
},
|
||||
|
||||
[`${menuCls}-item-icon`]: {
|
||||
minWidth: fontSizeBase,
|
||||
marginInlineEnd: token.marginXS,
|
||||
fontSize: token.fontSizeSM,
|
||||
},
|
||||
|
||||
[`${menuCls}-title-content`]: {
|
||||
flex: 'auto',
|
||||
|
||||
'> a': {
|
||||
color: 'inherit',
|
||||
transition: `all ${motionDurationSlow}`,
|
||||
|
||||
'&:hover': {
|
||||
color: 'inherit',
|
||||
},
|
||||
|
||||
'&::after': {
|
||||
position: 'absolute',
|
||||
inset: 0,
|
||||
content: '""',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// =========================== Item ===========================
|
||||
[`${menuCls}-item, ${menuCls}-submenu-title`]: {
|
||||
clear: 'both',
|
||||
margin: 0,
|
||||
padding: `${dropdownPaddingVertical}px ${controlPaddingHorizontal}px`,
|
||||
color: token.colorText,
|
||||
fontWeight: 'normal',
|
||||
fontSize: fontSizeBase,
|
||||
lineHeight: token.lineHeight,
|
||||
cursor: 'pointer',
|
||||
transition: `all ${motionDurationSlow}`,
|
||||
|
||||
'&:first-child': !dropdownEdgeChildVerticalPadding
|
||||
? {
|
||||
borderRadius: `${radiusBase}px ${radiusBase}px 0 0`,
|
||||
}
|
||||
: [],
|
||||
|
||||
'&:last-child': !dropdownEdgeChildVerticalPadding
|
||||
? {
|
||||
borderRadius: `0 0 ${radiusBase}px ${radiusBase}px`,
|
||||
}
|
||||
: [],
|
||||
|
||||
'&-selected': {
|
||||
color: token.colorPrimary,
|
||||
backgroundColor: token.controlItemBgActive,
|
||||
},
|
||||
|
||||
[`&:hover, &-active`]: {
|
||||
backgroundColor: token.controlItemBgHover,
|
||||
},
|
||||
|
||||
'&-disabled': {
|
||||
color: colorTextDisabled,
|
||||
cursor: 'not-allowed',
|
||||
|
||||
'&:hover': {
|
||||
color: colorTextDisabled,
|
||||
backgroundColor: colorBgComponent,
|
||||
cursor: 'not-allowed',
|
||||
},
|
||||
|
||||
a: {
|
||||
pointerEvents: 'none',
|
||||
},
|
||||
},
|
||||
|
||||
'&-divider': {
|
||||
height: 1, // By design
|
||||
margin: `${token.marginXXS}px 0`,
|
||||
overflow: 'hidden',
|
||||
lineHeight: 0,
|
||||
backgroundColor: token.colorSplit,
|
||||
},
|
||||
|
||||
[`${componentCls}-menu-submenu-expand-icon`]: {
|
||||
position: 'absolute',
|
||||
insetInlineEnd: token.paddingXS,
|
||||
|
||||
[`${componentCls}-menu-submenu-arrow-icon`]: {
|
||||
marginInlineEnd: '0 !important',
|
||||
color: token.colorTextSecondary,
|
||||
fontSize: fontSizeIcon,
|
||||
fontStyle: 'normal',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
[`${menuCls}-item-group-list`]: {
|
||||
margin: `0 ${token.marginXS}px`,
|
||||
padding: 0,
|
||||
listStyle: 'none',
|
||||
},
|
||||
|
||||
[`${menuCls}-submenu-title`]: {
|
||||
paddingInlineEnd: controlPaddingHorizontal + token.fontSizeSM,
|
||||
},
|
||||
|
||||
[`${menuCls}-submenu-vertical`]: {
|
||||
position: 'relative',
|
||||
},
|
||||
|
||||
[`${menuCls}-submenu${menuCls}-submenu-disabled ${componentCls}-menu-submenu-title`]: {
|
||||
[`&, ${componentCls}-menu-submenu-arrow-icon`]: {
|
||||
color: colorTextDisabled,
|
||||
backgroundColor: colorBgComponent,
|
||||
cursor: 'not-allowed',
|
||||
},
|
||||
},
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/19264
|
||||
[`${menuCls}-submenu-selected ${componentCls}-menu-submenu-title`]: {
|
||||
color: token.colorPrimary,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// Follow code may reuse in other components
|
||||
[
|
||||
initSlideMotion(rootPrefixCls, 'slide-up', slideUpIn, slideUpOut, token),
|
||||
initSlideMotion(rootPrefixCls, 'slide-down', slideDownIn, slideDownOut, token),
|
||||
slideUpIn,
|
||||
slideUpOut,
|
||||
slideDownIn,
|
||||
slideDownOut,
|
||||
],
|
||||
];
|
||||
};
|
||||
|
||||
// ============================== Export ==============================
|
||||
export default genComponentStyleHook(
|
||||
'Dropdown',
|
||||
(token, { rootPrefixCls }) => {
|
||||
const {
|
||||
marginXXS,
|
||||
sizePopupArrow,
|
||||
controlHeight,
|
||||
fontSizeBase,
|
||||
lineHeight,
|
||||
paddingXXS,
|
||||
componentCls,
|
||||
} = token;
|
||||
|
||||
const dropdownPaddingVertical = (controlHeight - fontSizeBase * lineHeight) / 2;
|
||||
|
||||
const dropdownToken = mergeToken<DropdownToken>(token, {
|
||||
menuCls: `${componentCls}-menu`,
|
||||
rootPrefixCls,
|
||||
dropdownArrowDistance: sizePopupArrow + marginXXS,
|
||||
dropdownArrowOffset: (sizePopupArrow / Math.sqrt(2)) * 2,
|
||||
dropdownPaddingVertical,
|
||||
dropdownEdgeChildVerticalPadding: paddingXXS,
|
||||
});
|
||||
return [
|
||||
genBaseStyle(dropdownToken),
|
||||
genButtonStyle(dropdownToken),
|
||||
genStatusStyle(dropdownToken),
|
||||
];
|
||||
},
|
||||
token => ({
|
||||
zIndexDropdown: token.zIndexPopup + 50,
|
||||
}),
|
||||
);
|
||||
|
@ -1,90 +1,90 @@
|
||||
@import '../../style/themes/index';
|
||||
@import '../../style/mixins/index';
|
||||
// @import '../../style/themes/index';
|
||||
// @import '../../style/mixins/index';
|
||||
|
||||
@dropdown-prefix-cls: ~'@{ant-prefix}-dropdown';
|
||||
// @dropdown-prefix-cls: ~'@{ant-prefix}-dropdown';
|
||||
|
||||
.@{dropdown-prefix-cls} {
|
||||
&-rtl {
|
||||
direction: rtl;
|
||||
}
|
||||
// .@{dropdown-prefix-cls} {
|
||||
// &-rtl {
|
||||
// direction: rtl;
|
||||
// }
|
||||
|
||||
&::before {
|
||||
.@{dropdown-prefix-cls}-rtl& {
|
||||
right: -7px;
|
||||
left: 0;
|
||||
}
|
||||
}
|
||||
// &::before {
|
||||
// .@{dropdown-prefix-cls}-rtl& {
|
||||
// right: -7px;
|
||||
// left: 0;
|
||||
// }
|
||||
// }
|
||||
|
||||
&-menu {
|
||||
&&-rtl {
|
||||
direction: rtl;
|
||||
text-align: right;
|
||||
}
|
||||
// &-menu {
|
||||
// &&-rtl {
|
||||
// direction: rtl;
|
||||
// text-align: right;
|
||||
// }
|
||||
|
||||
&-item-group-title {
|
||||
.@{dropdown-prefix-cls}-rtl &,
|
||||
.@{dropdown-prefix-cls}-menu-submenu-rtl & {
|
||||
direction: rtl;
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
// &-item-group-title {
|
||||
// .@{dropdown-prefix-cls}-rtl &,
|
||||
// .@{dropdown-prefix-cls}-menu-submenu-rtl & {
|
||||
// direction: rtl;
|
||||
// text-align: right;
|
||||
// }
|
||||
// }
|
||||
|
||||
&-submenu-popup {
|
||||
&.@{dropdown-prefix-cls}-menu-submenu-rtl {
|
||||
transform-origin: 100% 0;
|
||||
}
|
||||
// &-submenu-popup {
|
||||
// &.@{dropdown-prefix-cls}-menu-submenu-rtl {
|
||||
// transform-origin: 100% 0;
|
||||
// }
|
||||
|
||||
ul,
|
||||
li {
|
||||
.@{dropdown-prefix-cls}-rtl & {
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
}
|
||||
// ul,
|
||||
// li {
|
||||
// .@{dropdown-prefix-cls}-rtl & {
|
||||
// text-align: right;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
&-item,
|
||||
&-submenu-title {
|
||||
.@{dropdown-prefix-cls}-rtl & {
|
||||
text-align: right;
|
||||
}
|
||||
// &-item,
|
||||
// &-submenu-title {
|
||||
// .@{dropdown-prefix-cls}-rtl & {
|
||||
// text-align: right;
|
||||
// }
|
||||
|
||||
> .@{iconfont-css-prefix}:first-child,
|
||||
> span > .@{iconfont-css-prefix}:first-child {
|
||||
.@{dropdown-prefix-cls}-rtl & {
|
||||
margin-right: 0;
|
||||
margin-left: 8px;
|
||||
}
|
||||
}
|
||||
// > .@{iconfont-css-prefix}:first-child,
|
||||
// > span > .@{iconfont-css-prefix}:first-child {
|
||||
// .@{dropdown-prefix-cls}-rtl & {
|
||||
// margin-right: 0;
|
||||
// margin-left: 8px;
|
||||
// }
|
||||
// }
|
||||
|
||||
.@{dropdown-prefix-cls}-menu-submenu-expand-icon {
|
||||
.@{dropdown-prefix-cls}-rtl & {
|
||||
right: auto;
|
||||
left: @padding-xs;
|
||||
}
|
||||
// .@{dropdown-prefix-cls}-menu-submenu-expand-icon {
|
||||
// .@{dropdown-prefix-cls}-rtl & {
|
||||
// right: auto;
|
||||
// left: @padding-xs;
|
||||
// }
|
||||
|
||||
.@{dropdown-prefix-cls}-menu-submenu-arrow-icon {
|
||||
.@{dropdown-prefix-cls}-rtl & {
|
||||
margin-left: 0 !important;
|
||||
transform: scaleX(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// .@{dropdown-prefix-cls}-menu-submenu-arrow-icon {
|
||||
// .@{dropdown-prefix-cls}-rtl & {
|
||||
// margin-left: 0 !important;
|
||||
// transform: scaleX(-1);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
&-submenu-title {
|
||||
.@{dropdown-prefix-cls}-rtl & {
|
||||
padding-right: @control-padding-horizontal;
|
||||
padding-left: @control-padding-horizontal + @font-size-sm;
|
||||
}
|
||||
}
|
||||
// &-submenu-title {
|
||||
// .@{dropdown-prefix-cls}-rtl & {
|
||||
// padding-right: @control-padding-horizontal;
|
||||
// padding-left: @control-padding-horizontal + @font-size-sm;
|
||||
// }
|
||||
// }
|
||||
|
||||
&-submenu-vertical > & {
|
||||
.@{dropdown-prefix-cls}-rtl & {
|
||||
right: 100%;
|
||||
left: 0;
|
||||
margin-right: 4px;
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// &-submenu-vertical > & {
|
||||
// .@{dropdown-prefix-cls}-rtl & {
|
||||
// right: 100%;
|
||||
// left: 0;
|
||||
// margin-right: 4px;
|
||||
// margin-left: 0;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
@ -1,14 +1,14 @@
|
||||
@import (reference) '../../style/themes/index';
|
||||
// @import (reference) '../../style/themes/index';
|
||||
|
||||
@dropdown-prefix-cls: ~'@{ant-prefix}-dropdown';
|
||||
// @dropdown-prefix-cls: ~'@{ant-prefix}-dropdown';
|
||||
|
||||
.@{dropdown-prefix-cls}-menu-item {
|
||||
&&-danger {
|
||||
color: @error-color;
|
||||
// .@{dropdown-prefix-cls}-menu-item {
|
||||
// &&-danger {
|
||||
// color: @error-color;
|
||||
|
||||
&:hover {
|
||||
color: @text-color-inverse;
|
||||
background-color: @error-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
// &:hover {
|
||||
// color: @text-color-inverse;
|
||||
// background-color: @error-color;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
25
components/dropdown/style/status.tsx
Normal file
25
components/dropdown/style/status.tsx
Normal file
@ -0,0 +1,25 @@
|
||||
import type { GenerateStyle } from '../../_util/theme';
|
||||
import type { DropdownToken } from '.';
|
||||
|
||||
const genStatusStyle: GenerateStyle<DropdownToken> = token => {
|
||||
const { componentCls, menuCls, colorError, colorTextLightSolid } = token;
|
||||
|
||||
const itemCls = `${menuCls}-item`;
|
||||
|
||||
return {
|
||||
[`${componentCls}, ${componentCls}-menu-submenu`]: {
|
||||
[`${menuCls} ${itemCls}`]: {
|
||||
[`&${itemCls}-danger`]: {
|
||||
color: colorError,
|
||||
|
||||
'&:hover': {
|
||||
color: colorTextLightSolid,
|
||||
backgroundColor: colorError,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export default genStatusStyle;
|
@ -62,6 +62,7 @@ const InternalMenu = forwardRef<MenuRef, InternalMenuProps>((props, ref) => {
|
||||
} = props;
|
||||
|
||||
const passedProps = omit(restProps, ['collapsedWidth']);
|
||||
const injectFromDropdown = (props as any)['data-dropdown-inject'];
|
||||
|
||||
// ========================= Items ===========================
|
||||
const mergedChildren = useItems(items) || children;
|
||||
@ -101,7 +102,7 @@ const InternalMenu = forwardRef<MenuRef, InternalMenuProps>((props, ref) => {
|
||||
};
|
||||
|
||||
const prefixCls = getPrefixCls('menu', customizePrefixCls);
|
||||
const [wrapSSR, hashId] = useStyle(prefixCls);
|
||||
const [wrapSSR, hashId] = useStyle(prefixCls, !injectFromDropdown);
|
||||
const menuClassName = classNames(`${prefixCls}-${theme}`, className);
|
||||
|
||||
// ======================== Context ==========================
|
||||
|
@ -1,7 +1,13 @@
|
||||
// deps-lint-skip-all
|
||||
import { CSSObject } from '@ant-design/cssinjs';
|
||||
import { TinyColor } from '@ctrl/tinycolor';
|
||||
import { genComponentStyleHook, resetComponent, clearFix, mergeToken } from '../../_util/theme';
|
||||
import {
|
||||
genComponentStyleHook,
|
||||
resetComponent,
|
||||
clearFix,
|
||||
mergeToken,
|
||||
UseComponentStyleResult,
|
||||
} from '../../_util/theme';
|
||||
import type { GenerateStyle, FullToken } from '../../_util/theme';
|
||||
|
||||
/** Component only token. Which will handle additional calculation of alias token */
|
||||
@ -1028,7 +1034,13 @@ const genBaseStyle: GenerateStyle<MenuToken, CSSObject> = (token): CSSObject =>
|
||||
};
|
||||
|
||||
// ============================== Export ==============================
|
||||
export default genComponentStyleHook('Menu', token => {
|
||||
export default (prefixCls: string, injectStyle: boolean): UseComponentStyleResult => {
|
||||
const useOriginHook = genComponentStyleHook('Menu', token => {
|
||||
// Dropdown will handle menu style self. We do not need to handle this.
|
||||
if (injectStyle === false) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const MenuToken = mergeToken<MenuToken>(token, {
|
||||
black: '#000', // FIXME: hard code in v4
|
||||
componentBackground: '#fff', // FIXME: hard code in v4
|
||||
@ -1064,3 +1076,6 @@ export default genComponentStyleHook('Menu', token => {
|
||||
genStatusStyle(MenuToken),
|
||||
];
|
||||
});
|
||||
|
||||
return useOriginHook(prefixCls);
|
||||
};
|
||||
|
@ -115,7 +115,7 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"@ant-design/colors": "^6.0.0",
|
||||
"@ant-design/cssinjs": "^0.0.0-alpha.31",
|
||||
"@ant-design/cssinjs": "^0.0.0-alpha.33",
|
||||
"@ant-design/icons": "^4.7.0",
|
||||
"@ant-design/react-slick": "~0.28.1",
|
||||
"@babel/runtime": "^7.12.5",
|
||||
|
@ -15,23 +15,18 @@ export interface PreviewProps {
|
||||
onClose: () => void;
|
||||
}
|
||||
|
||||
export default function Preview({ visible, onClose }: PreviewProps) {
|
||||
const [styleList, setStyleList] = React.useState<string[]>([]);
|
||||
function formatStyle(style: string) {
|
||||
let formatted = style;
|
||||
|
||||
React.useEffect(() => {
|
||||
const observer = new MutationObserver(() => {
|
||||
const latestStyles = Array.from(document.querySelectorAll('style[data-css-hash]'))
|
||||
.map(style => style?.innerHTML || '')
|
||||
// Break lines
|
||||
.map(style => style.replace(/{/g, ' {\n'))
|
||||
.map(style => style.replace(/}/g, '}\n'))
|
||||
.map(style => style.replace(/;/g, ';\n'))
|
||||
formatted = formatted.replace(/{/g, ' {\n').replace(/}/g, '}\n').replace(/;/g, ';\n');
|
||||
|
||||
// Line convert
|
||||
.map(style => {
|
||||
const lines = style.split(/[\n\r]+/);
|
||||
{
|
||||
const lines = formatted.split(/[\n\r]+/);
|
||||
let leftParenthesis = false;
|
||||
|
||||
return lines
|
||||
formatted = lines
|
||||
.map(line => {
|
||||
if (line.includes('}')) {
|
||||
leftParenthesis = false;
|
||||
@ -51,9 +46,23 @@ export default function Preview({ visible, onClose }: PreviewProps) {
|
||||
return line;
|
||||
})
|
||||
.join('\n');
|
||||
})
|
||||
// Format
|
||||
.filter(txt => txt);
|
||||
}
|
||||
|
||||
return formatted;
|
||||
}
|
||||
|
||||
export default function Preview({ visible, onClose }: PreviewProps) {
|
||||
const [styleList, setStyleList] = React.useState<{ text: string; path: string }[]>([]);
|
||||
|
||||
React.useEffect(() => {
|
||||
const observer = new MutationObserver(() => {
|
||||
const latestStyles = Array.from(document.querySelectorAll('style[data-css-hash]'))
|
||||
.filter(style => style)
|
||||
.map(style => ({
|
||||
text: formatStyle(style.innerHTML),
|
||||
path: style.getAttribute('data-dev-cache-path')!,
|
||||
}))
|
||||
.filter(style => style.text);
|
||||
|
||||
setStyleList(latestStyles);
|
||||
});
|
||||
@ -67,11 +76,14 @@ export default function Preview({ visible, onClose }: PreviewProps) {
|
||||
const formatStyles = React.useMemo(
|
||||
() =>
|
||||
styleList.map(style => {
|
||||
const lines = style
|
||||
const lines = style.text
|
||||
.split(/[\n\r]+/)
|
||||
.map(line => (line.includes('{') ? line.replace(/,/g, ',\n') : line))
|
||||
.join('\n');
|
||||
return hljs.highlight(lines, { language: 'css' }).value;
|
||||
return {
|
||||
...style,
|
||||
text: hljs.highlight(lines, { language: 'css' }).value,
|
||||
};
|
||||
}),
|
||||
[styleList],
|
||||
);
|
||||
@ -80,8 +92,8 @@ export default function Preview({ visible, onClose }: PreviewProps) {
|
||||
type Item = { status: STATUS; line: string; source?: string };
|
||||
const list: Item[] = [];
|
||||
|
||||
styleList.forEach(style => {
|
||||
const lines = style.split(/[\n\r]+/);
|
||||
styleList.forEach(({ text }) => {
|
||||
const lines = text.split(/[\n\r]+/);
|
||||
|
||||
lines.forEach((line, index) => {
|
||||
const status = getValidateStatus(line);
|
||||
@ -130,8 +142,11 @@ export default function Preview({ visible, onClose }: PreviewProps) {
|
||||
<Tabs>
|
||||
<Tabs.TabPane tab="Style" key="style">
|
||||
<Typography>
|
||||
{formatStyles.map((style, index) => (
|
||||
<pre key={index} dangerouslySetInnerHTML={{ __html: style }} />
|
||||
{formatStyles.map(({ text, path }, index) => (
|
||||
<pre
|
||||
key={index}
|
||||
dangerouslySetInnerHTML={{ __html: `🐚 Cache: ${path}\n\n${text}` }}
|
||||
/>
|
||||
))}
|
||||
</Typography>
|
||||
</Tabs.TabPane>
|
||||
|
@ -1,4 +1,6 @@
|
||||
# V5 breaking change 记录
|
||||
|
||||
- Dropdown 魔改包裹元素样式移除,请使用 Space 组件
|
||||
- Dropdown
|
||||
- 魔改包裹元素样式移除,请使用 Space 组件
|
||||
- DropdownButton 的 prefixCls 改为 `dropdown`
|
||||
- Upload List 结构变化
|
||||
|
Loading…
Reference in New Issue
Block a user