mirror of
https://github.com/ant-design/ant-design.git
synced 2025-06-07 01:13:58 +08:00
Merge branch 'next' into next-merge-feature
This commit is contained in:
commit
9f3dc50df6
2
.github/workflows/pr-check-ci.yml
vendored
2
.github/workflows/pr-check-ci.yml
vendored
@ -13,7 +13,7 @@ jobs:
|
||||
with:
|
||||
filter-label: 'BranchAutoMerge'
|
||||
filter-creator-authority: 'write'
|
||||
filter-head-ref: 'master, feature, next, master-merge-feature, feature-merge-master, next-merge-master'
|
||||
filter-head-ref: 'master, feature, next, master-merge-feature, feature-merge-master, next-merge-master, next-merge-feature'
|
||||
filter-support-fork: false
|
||||
skip-run-names: 'deploy preview, pr-check-ci, build preview failed, suggest-related-links'
|
||||
conflict-review-body: '😅 This branch has conflicts that must be resolved!'
|
||||
|
@ -2,7 +2,7 @@ import React from 'react';
|
||||
import { CSSInterpolation, Theme, useCacheToken, useStyleRegister } from '@ant-design/cssinjs';
|
||||
import defaultSeedToken, { derivative as defaultDerivative } from './themes/default';
|
||||
import version from '../../version';
|
||||
import { resetComponent, resetIcon, clearFix } from './util';
|
||||
import { resetComponent, resetIcon, clearFix, roundedArrow } from './util';
|
||||
import formatToken from './util/alias';
|
||||
import {
|
||||
initSlideMotion,
|
||||
@ -29,6 +29,7 @@ export {
|
||||
resetComponent,
|
||||
resetIcon,
|
||||
clearFix,
|
||||
roundedArrow,
|
||||
initSlideMotion,
|
||||
slideUpIn,
|
||||
slideUpOut,
|
||||
|
@ -1,5 +1,7 @@
|
||||
import * as React from 'react';
|
||||
import type { ComponentToken as ButtonComponentToken } from '../../button/style';
|
||||
import type { ComponentToken as DividerComponentToken } from '../../divider/style';
|
||||
import type { ComponentToken as TypographyComponentToken } from '../../typography/style';
|
||||
|
||||
export const PresetColors = [
|
||||
'blue',
|
||||
@ -32,6 +34,8 @@ export interface OverrideToken {
|
||||
|
||||
// Customize component
|
||||
button?: ButtonComponentToken;
|
||||
divider?: DividerComponentToken;
|
||||
typography?: TypographyComponentToken;
|
||||
}
|
||||
|
||||
/** Final token which contains the components level override */
|
||||
@ -87,6 +91,7 @@ export interface SeedToken extends PresetColorType {
|
||||
// zIndex
|
||||
/** Base zIndex of component like BackTop, Affix which can be cover by large popup */
|
||||
zIndexBase: number;
|
||||
zIndexPopover: number;
|
||||
/** Base popup component zIndex */
|
||||
zIndexPopup: number;
|
||||
}
|
||||
@ -195,6 +200,9 @@ export interface AliasToken extends Omit<DerivativeToken, OmitDerivativeKey> {
|
||||
fontSizeHeading4: number;
|
||||
fontSizeHeading5: number;
|
||||
|
||||
/** For heading like h1, h2, h3 or option selected item */
|
||||
fontWeightStrong: number;
|
||||
|
||||
// LineHeight
|
||||
lineHeight: number;
|
||||
lineHeightLG: number;
|
||||
@ -253,6 +261,7 @@ export interface AliasToken extends Omit<DerivativeToken, OmitDerivativeKey> {
|
||||
paddingXXS: number;
|
||||
paddingLG: number;
|
||||
marginXS: number;
|
||||
marginSM: number;
|
||||
marginLG: number;
|
||||
marginXXS: number;
|
||||
}
|
||||
|
@ -194,6 +194,7 @@ const seedToken: SeedToken = {
|
||||
|
||||
// zIndex
|
||||
zIndexBase: 0,
|
||||
zIndexPopover: 1030,
|
||||
zIndexPopup: 1000,
|
||||
};
|
||||
|
||||
|
@ -79,8 +79,9 @@ export default function formatToken(derivativeToken: RawMergedToken): AliasToken
|
||||
controlLineType: 'solid',
|
||||
controlRadius: mergedToken.radiusBase,
|
||||
colorBorder: new TinyColor({ h: 0, s: 0, v: 85 }).toHexString(),
|
||||
colorSplit: new TinyColor({ h: 0, s: 0, v: 94 }).toHexString(),
|
||||
colorSplit: 'rgba(0, 0, 0, 0.06)',
|
||||
controlItemBgActive: primaryColors[0],
|
||||
fontWeightStrong: 600,
|
||||
|
||||
// 🔥🔥🔥🔥🔥🔥🔥🔥🔥 All TMP Token leaves here 🔥🔥🔥🔥🔥🔥🔥🔥🔥
|
||||
// FIXME: Handle this when derivative is ready
|
||||
@ -97,21 +98,21 @@ export default function formatToken(derivativeToken: RawMergedToken): AliasToken
|
||||
linkHoverDecoration: 'none',
|
||||
linkFocusDecoration: 'none',
|
||||
|
||||
controlPaddingHorizontal: 16,
|
||||
controlPaddingHorizontalSM: 12,
|
||||
controlPaddingHorizontal: 12,
|
||||
controlPaddingHorizontalSM: 8,
|
||||
|
||||
padding: 16,
|
||||
margin: 16,
|
||||
|
||||
paddingXXS: 2,
|
||||
paddingXS: 4,
|
||||
paddingSM: 8,
|
||||
paddingLG: 32,
|
||||
paddingXXS: 4,
|
||||
paddingXS: 8,
|
||||
paddingSM: 12,
|
||||
paddingLG: 24,
|
||||
|
||||
marginXXS: 2,
|
||||
marginXS: 4,
|
||||
// marginSM: 8,
|
||||
marginLG: 32,
|
||||
marginXXS: 4,
|
||||
marginXS: 8,
|
||||
marginSM: 12,
|
||||
marginLG: 24,
|
||||
|
||||
boxShadow: `
|
||||
0 3px 6px -4px rgba(0, 0, 0, 0.12),
|
||||
|
@ -2,6 +2,8 @@
|
||||
import { CSSObject } from '@ant-design/cssinjs';
|
||||
import type { DerivativeToken } from '..';
|
||||
|
||||
export { roundedArrow } from './roundedArrow';
|
||||
|
||||
export const resetComponent = (token: DerivativeToken): CSSObject => ({
|
||||
boxSizing: 'border-box',
|
||||
margin: 0,
|
||||
@ -15,7 +17,8 @@ export const resetComponent = (token: DerivativeToken): CSSObject => ({
|
||||
});
|
||||
|
||||
export const resetIcon = (): CSSObject => ({
|
||||
display: 'inline-block',
|
||||
display: 'inline-flex',
|
||||
alignItems: 'center',
|
||||
color: 'inherit',
|
||||
fontStyle: 'normal',
|
||||
lineHeight: 0,
|
||||
|
39
components/_util/theme/util/roundedArrow.tsx
Normal file
39
components/_util/theme/util/roundedArrow.tsx
Normal file
@ -0,0 +1,39 @@
|
||||
/* eslint-disable import/prefer-default-export */
|
||||
import { CSSObject } from '@ant-design/cssinjs';
|
||||
import seedToken from '../themes/default';
|
||||
|
||||
export const roundedArrow = (width: number, outerRadius: number, bgColor: string): CSSObject => {
|
||||
const cornerHeight = outerRadius * (1 - 1 / Math.sqrt(2));
|
||||
const { radiusBase } = seedToken;
|
||||
|
||||
const ax = width - cornerHeight;
|
||||
const ay = 2 * width + cornerHeight;
|
||||
const bx = ax + outerRadius * (1 / Math.sqrt(2));
|
||||
const by = 2 * width;
|
||||
const cx = 2 * width - radiusBase;
|
||||
const cy = 2 * width;
|
||||
const dx = 2 * width;
|
||||
const dy = 2 * width - radiusBase;
|
||||
const fx = 2 * width + cornerHeight;
|
||||
const fy = width - cornerHeight;
|
||||
const ex = 2 * width;
|
||||
const ey = fy + outerRadius * (1 / Math.sqrt(2));
|
||||
|
||||
return {
|
||||
borderRadius: `0 0 ${radiusBase}px 0`,
|
||||
pointerEvents: 'none',
|
||||
|
||||
'&::before': {
|
||||
position: 'absolute',
|
||||
top: -width,
|
||||
insetInlineStart: -width,
|
||||
width: width * 3,
|
||||
height: width * 3,
|
||||
background: `linear-gradient(to left, ${bgColor} 50%, ${bgColor} 50%) no-repeat ${Math.ceil(
|
||||
-width + 1,
|
||||
)}px ${Math.ceil(-width + 1)}px`,
|
||||
content: '""',
|
||||
clipPath: `path('M ${ax} ${ay} A ${outerRadius} ${outerRadius} 0 0 1 ${bx} ${by} L ${cx} ${cy} A ${radiusBase} ${radiusBase} 0 0 0 ${dx} ${dy} L ${ex} ${ey} A ${outerRadius} ${outerRadius} 0 0 1 ${fx} ${fy} Z')`,
|
||||
},
|
||||
};
|
||||
};
|
@ -123,7 +123,7 @@ const genBaseStyle: GenerateStyle<CascaderToken> = (token, hashId) => {
|
||||
|
||||
[`&-active:not(${cascaderMenuItemCls}-disabled)`]: {
|
||||
[`&, &:hover`]: {
|
||||
fontWeight: 600, // FIXME: hardcode
|
||||
fontWeight: token.fontWeightStrong,
|
||||
backgroundColor: token.controlItemBgActive,
|
||||
},
|
||||
},
|
||||
|
@ -184,7 +184,7 @@ export const genCheckboxStyle: GenerateStyle<CheckboxToken> = (token, hashId) =>
|
||||
'&:after': {
|
||||
opacity: 1,
|
||||
transform: 'rotate(45deg) scale(1) translate(-50%,-50%)',
|
||||
transition: `all ${token.motionDurationSlow} ${token.motionEaseOutBack} 0.1s`,
|
||||
transition: `all ${token.motionDurationSlow} ${token.motionEaseOutBack} ${token.motionDurationFast}`,
|
||||
},
|
||||
},
|
||||
|
||||
|
@ -40,6 +40,7 @@ import Rate from '../../rate';
|
||||
import Select from '../../select';
|
||||
import Skeleton from '../../skeleton';
|
||||
import Slider from '../../slider';
|
||||
// eslint-disable-next-line import/no-named-as-default
|
||||
import Spin from '../../spin';
|
||||
import Statistic from '../../statistic';
|
||||
import Steps from '../../steps';
|
||||
|
@ -60,7 +60,7 @@ const Cell: React.FC<CellProps> = ({
|
||||
colSpan={span}
|
||||
>
|
||||
<div className={`${itemPrefixCls}-item-container`}>
|
||||
{label && (
|
||||
{(label || label === 0) && (
|
||||
<span
|
||||
className={classNames(`${itemPrefixCls}-item-label`, {
|
||||
[`${itemPrefixCls}-item-no-colon`]: !colon,
|
||||
@ -70,7 +70,7 @@ const Cell: React.FC<CellProps> = ({
|
||||
{label}
|
||||
</span>
|
||||
)}
|
||||
{content && (
|
||||
{(content || content === 0) && (
|
||||
<span className={classNames(`${itemPrefixCls}-item-content`)} style={contentStyle}>
|
||||
{content}
|
||||
</span>
|
||||
|
@ -209,6 +209,46 @@ exports[`Descriptions column is number 1`] = `
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Descriptions number 0 should render correct 1`] = `
|
||||
<div
|
||||
class="ant-descriptions"
|
||||
>
|
||||
<div
|
||||
class="ant-descriptions-view"
|
||||
>
|
||||
<table>
|
||||
<tbody>
|
||||
<tr
|
||||
class="ant-descriptions-row"
|
||||
>
|
||||
<td
|
||||
class="ant-descriptions-item"
|
||||
colspan="1"
|
||||
>
|
||||
<div
|
||||
class="ant-descriptions-item-container"
|
||||
>
|
||||
<span
|
||||
class="ant-descriptions-item-label"
|
||||
style="color: red;"
|
||||
>
|
||||
0
|
||||
</span>
|
||||
<span
|
||||
class="ant-descriptions-item-content"
|
||||
style="color: red;"
|
||||
>
|
||||
0
|
||||
</span>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Descriptions should work with React Fragment 1`] = `
|
||||
<div
|
||||
class="ant-descriptions"
|
||||
|
@ -238,4 +238,15 @@ describe('Descriptions', () => {
|
||||
wrapper.setProps({ extra: undefined });
|
||||
expect(wrapper.find('.ant-descriptions-extra').exists()).toBe(false);
|
||||
});
|
||||
|
||||
it('number 0 should render correct', () => {
|
||||
const wrapper = mount(
|
||||
<Descriptions>
|
||||
<Descriptions.Item label={0} labelStyle={{ color: 'red' }} contentStyle={{ color: 'red' }}>
|
||||
{0}
|
||||
</Descriptions.Item>
|
||||
</Descriptions>,
|
||||
);
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
@ -9,14 +9,14 @@ import {
|
||||
GenerateStyle,
|
||||
} from '../../_util/theme';
|
||||
|
||||
interface DividerToken extends DerivativeToken {
|
||||
/** Component only token. Which will handle additional calculation of alias token */
|
||||
export interface ComponentToken {
|
||||
sizePaddingEdgeHorizontal: number;
|
||||
}
|
||||
|
||||
interface DividerToken extends DerivativeToken, ComponentToken {
|
||||
dividerCls: string;
|
||||
|
||||
dividerBorderColor: string;
|
||||
|
||||
dividerBorderWidth: number;
|
||||
|
||||
dividerNotDefaultTextPadding: number;
|
||||
dividerVerticalGutterMargin: number;
|
||||
dividerHorizontalWithTextGutterMargin: number;
|
||||
dividerHorizontalGutterMargin: number;
|
||||
@ -24,12 +24,12 @@ interface DividerToken extends DerivativeToken {
|
||||
|
||||
// ============================== Shared ==============================
|
||||
const genSharedDividerStyle: GenerateStyle<DividerToken> = (token): CSSObject => {
|
||||
const { dividerCls } = token;
|
||||
const { dividerCls, sizePaddingEdgeHorizontal, colorSplit, controlLineWidth } = token;
|
||||
|
||||
return {
|
||||
[dividerCls]: {
|
||||
...resetComponent(token),
|
||||
borderBlockStart: `${token.dividerBorderWidth}px solid ${token.dividerBorderColor}`,
|
||||
borderBlockStart: `${controlLineWidth}px solid ${colorSplit}`,
|
||||
|
||||
// vertical
|
||||
'&-vertical': {
|
||||
@ -40,7 +40,7 @@ const genSharedDividerStyle: GenerateStyle<DividerToken> = (token): CSSObject =>
|
||||
margin: `0 ${token.dividerVerticalGutterMargin}px`,
|
||||
verticalAlign: 'middle',
|
||||
borderTop: 0,
|
||||
borderInlineStart: `${token.dividerBorderWidth}px solid ${token.dividerBorderColor}`,
|
||||
borderInlineStart: `${controlLineWidth}px solid ${colorSplit}`,
|
||||
},
|
||||
|
||||
'&-horizontal': {
|
||||
@ -59,13 +59,13 @@ const genSharedDividerStyle: GenerateStyle<DividerToken> = (token): CSSObject =>
|
||||
fontSize: token.fontSizeLG,
|
||||
whiteSpace: 'nowrap',
|
||||
textAlign: 'center',
|
||||
borderBlockStart: `0 ${token.dividerBorderColor}`,
|
||||
borderBlockStart: `0 ${colorSplit}`,
|
||||
|
||||
'&::before, &::after': {
|
||||
position: 'relative',
|
||||
top: '50%',
|
||||
width: '50%',
|
||||
borderBlockStart: `${token.dividerBorderWidth}px solid transparent`,
|
||||
borderBlockStart: `${controlLineWidth}px solid transparent`,
|
||||
// Chrome not accept `inherit` in `border-top`
|
||||
borderBlockStartColor: 'inherit',
|
||||
borderBlockEnd: 0,
|
||||
@ -105,10 +105,10 @@ const genSharedDividerStyle: GenerateStyle<DividerToken> = (token): CSSObject =>
|
||||
|
||||
'&-dashed': {
|
||||
background: 'none',
|
||||
borderColor: token.dividerBorderColor,
|
||||
borderColor: colorSplit,
|
||||
borderStyle: 'dashed',
|
||||
borderWidth: 0,
|
||||
borderBlockStart: `${token.dividerBorderWidth}px`,
|
||||
borderBlockStart: `${controlLineWidth}px`,
|
||||
},
|
||||
|
||||
'&-horizontal&-with-text&-dashed': {
|
||||
@ -118,7 +118,7 @@ const genSharedDividerStyle: GenerateStyle<DividerToken> = (token): CSSObject =>
|
||||
},
|
||||
|
||||
'&-vertical&-dashed': {
|
||||
borderWidth: `0 0 0 ${token.dividerBorderWidth}px`,
|
||||
borderWidth: `0 0 0 ${controlLineWidth}px`,
|
||||
},
|
||||
|
||||
'&-plain&-with-text': {
|
||||
@ -136,8 +136,8 @@ const genSharedDividerStyle: GenerateStyle<DividerToken> = (token): CSSObject =>
|
||||
width: '100%',
|
||||
},
|
||||
|
||||
'.ant-divider-inner-text': {
|
||||
paddingInlineStart: `${token.dividerNotDefaultTextPadding}px`,
|
||||
[`${dividerCls}-inner-text`]: {
|
||||
paddingInlineStart: sizePaddingEdgeHorizontal,
|
||||
},
|
||||
},
|
||||
|
||||
@ -150,8 +150,8 @@ const genSharedDividerStyle: GenerateStyle<DividerToken> = (token): CSSObject =>
|
||||
width: 0,
|
||||
},
|
||||
|
||||
'.ant-divider-inner-text': {
|
||||
paddingInlineEnd: `${token.dividerNotDefaultTextPadding}px`,
|
||||
[`${dividerCls}-inner-text`]: {
|
||||
paddingInlineEnd: sizePaddingEdgeHorizontal,
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -161,35 +161,31 @@ const genSharedDividerStyle: GenerateStyle<DividerToken> = (token): CSSObject =>
|
||||
// ============================== Export ==============================
|
||||
export default function useStyle(prefixCls: string): UseComponentStyleResult {
|
||||
const [theme, token, hashId] = useToken();
|
||||
// FIXME
|
||||
const dividerBorderColor = 'rgba(0, 0, 0, 6%)';
|
||||
|
||||
const dividerBorderWidth = token.controlLineWidth;
|
||||
|
||||
const dividerNotDefaultTextPadding = 0;
|
||||
const dividerVerticalGutterMargin = token.marginXS;
|
||||
const dividerHorizontalWithTextGutterMargin = token.margin;
|
||||
const dividerHorizontalGutterMargin = token.marginLG;
|
||||
|
||||
const dividerToken: DividerToken = {
|
||||
...token,
|
||||
|
||||
dividerCls: `.${prefixCls}`,
|
||||
|
||||
dividerBorderColor,
|
||||
|
||||
dividerBorderWidth,
|
||||
|
||||
dividerNotDefaultTextPadding,
|
||||
dividerVerticalGutterMargin,
|
||||
dividerHorizontalWithTextGutterMargin,
|
||||
dividerHorizontalGutterMargin,
|
||||
};
|
||||
|
||||
return [
|
||||
useStyleRegister({ theme, token, hashId, path: [prefixCls] }, () => [
|
||||
genSharedDividerStyle(dividerToken),
|
||||
]),
|
||||
useStyleRegister({ theme, token, hashId, path: [prefixCls] }, () => {
|
||||
const { divider } = token;
|
||||
|
||||
const dividerVerticalGutterMargin = token.marginSM;
|
||||
const dividerHorizontalWithTextGutterMargin = token.margin;
|
||||
const dividerHorizontalGutterMargin = token.marginLG;
|
||||
|
||||
const dividerToken: DividerToken = {
|
||||
...token,
|
||||
|
||||
dividerCls: `.${prefixCls}`,
|
||||
|
||||
sizePaddingEdgeHorizontal: 0,
|
||||
|
||||
dividerVerticalGutterMargin,
|
||||
dividerHorizontalWithTextGutterMargin,
|
||||
dividerHorizontalGutterMargin,
|
||||
|
||||
...divider,
|
||||
};
|
||||
|
||||
return [genSharedDividerStyle(dividerToken)];
|
||||
}),
|
||||
hashId,
|
||||
];
|
||||
}
|
||||
|
@ -4,6 +4,9 @@ import CloseOutlined from '@ant-design/icons/CloseOutlined';
|
||||
import classNames from 'classnames';
|
||||
import { ConfigContext } from '../config-provider';
|
||||
import { tuple } from '../_util/type';
|
||||
// CSSINJS
|
||||
import useStyle from './style';
|
||||
|
||||
import useForceUpdate from '../_util/hooks/useForceUpdate';
|
||||
|
||||
type DrawerRef = {
|
||||
@ -109,8 +112,13 @@ const Drawer = React.forwardRef<DrawerRef, DrawerProps>(
|
||||
const parentDrawer = React.useContext(DrawerContext);
|
||||
const destroyClose = React.useRef<boolean>(false);
|
||||
|
||||
const { getPopupContainer, getPrefixCls, direction } = React.useContext(ConfigContext);
|
||||
const { getPopupContainer, getPrefixCls, direction, iconPrefixCls } =
|
||||
React.useContext(ConfigContext);
|
||||
const prefixCls = getPrefixCls('drawer', customizePrefixCls);
|
||||
|
||||
// Style
|
||||
const [wrapSSR, hashId] = useStyle(prefixCls, iconPrefixCls);
|
||||
|
||||
const getContainer =
|
||||
// 有可能为 false,所以不能直接判断
|
||||
customizeGetContainer === undefined && getPopupContainer
|
||||
@ -297,10 +305,11 @@ const Drawer = React.forwardRef<DrawerRef, DrawerProps>(
|
||||
[`${prefixCls}-rtl`]: direction === 'rtl',
|
||||
},
|
||||
className,
|
||||
hashId,
|
||||
);
|
||||
const offsetStyle = mask ? getOffsetStyle() : {};
|
||||
|
||||
return (
|
||||
return wrapSSR(
|
||||
<DrawerContext.Provider value={operations}>
|
||||
<RcDrawer
|
||||
handler={false}
|
||||
@ -323,7 +332,7 @@ const Drawer = React.forwardRef<DrawerRef, DrawerProps>(
|
||||
>
|
||||
{renderBody()}
|
||||
</RcDrawer>
|
||||
</DrawerContext.Provider>
|
||||
</DrawerContext.Provider>,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
@ -1,6 +1,6 @@
|
||||
@import '../../style/themes/index';
|
||||
@import '../../style/mixins/index';
|
||||
@import './drawer';
|
||||
@import './rtl';
|
||||
|
||||
.popover-customize-bg(@drawer-prefix-cls, @popover-background);
|
||||
//@import '../../style/themes/index';
|
||||
//@import '../../style/mixins/index';
|
||||
//@import './drawer';
|
||||
//@import './rtl';
|
||||
//
|
||||
//.popover-customize-bg(@drawer-prefix-cls, @popover-background);
|
||||
|
@ -1,3 +1,338 @@
|
||||
// deps-lint-skip: empty
|
||||
import '../../style/index.less';
|
||||
import './index.less';
|
||||
// deps-lint-skip-all
|
||||
import { CSSObject, Keyframes } from '@ant-design/cssinjs';
|
||||
import { TinyColor } from '@ctrl/tinycolor';
|
||||
import {
|
||||
DerivativeToken,
|
||||
GenerateStyle,
|
||||
UseComponentStyleResult,
|
||||
useStyleRegister,
|
||||
useToken,
|
||||
} from '../../_util/theme';
|
||||
|
||||
export interface DrawerToken extends DerivativeToken {
|
||||
prefixCls: string;
|
||||
iconPrefixCls: string;
|
||||
drawerHeaderCloseSize: number;
|
||||
shadow1Right: string;
|
||||
shadow1Left: string;
|
||||
shadow1Up: string;
|
||||
shadow1Down: string;
|
||||
drawerTitleLineHeight: number;
|
||||
closeRight: number;
|
||||
white: string;
|
||||
black: string;
|
||||
paddingMd: number;
|
||||
modalFooterPaddingVertical: number;
|
||||
modalFooterPaddingHorizontal: number;
|
||||
hoverColor: string;
|
||||
borderColorSplit: string;
|
||||
borderStyle: string;
|
||||
textColorSecondary: string;
|
||||
motionEaseOut: string;
|
||||
drawerPrefixCls: string;
|
||||
}
|
||||
|
||||
const antdDrawerFadeIn = new Keyframes('antNoWrapperZoomBadgeIn', {
|
||||
'0%': { opacity: 0 },
|
||||
'100%': { opacity: 1 },
|
||||
});
|
||||
|
||||
// =============================== Base ===============================
|
||||
const genBaseStyle: GenerateStyle<DrawerToken> = (
|
||||
token: DrawerToken,
|
||||
hashId: string,
|
||||
): CSSObject => {
|
||||
const {
|
||||
drawerPrefixCls,
|
||||
motionEaseOut,
|
||||
motionDurationSlow,
|
||||
fontSizeLG,
|
||||
drawerTitleLineHeight,
|
||||
white,
|
||||
closeRight,
|
||||
paddingLG,
|
||||
paddingMd,
|
||||
lineWidth,
|
||||
borderStyle,
|
||||
radiusBase,
|
||||
fontSize,
|
||||
lineHeight,
|
||||
modalFooterPaddingVertical,
|
||||
modalFooterPaddingHorizontal,
|
||||
borderColorSplit,
|
||||
zIndexPopup,
|
||||
colorText,
|
||||
textColorSecondary,
|
||||
hoverColor,
|
||||
} = token;
|
||||
|
||||
return {
|
||||
[`${drawerPrefixCls}`]: {
|
||||
// FIXME: Seems useless?
|
||||
// @drawer-header-close-padding: ceil(((drawerHeaderCloseSize - @font-size-lg) / 2));
|
||||
position: 'fixed',
|
||||
zIndex: zIndexPopup,
|
||||
width: 0,
|
||||
height: '100%',
|
||||
transition: `width 0s ease ${motionDurationSlow}, height 0s ease ${motionDurationSlow}`,
|
||||
[`${drawerPrefixCls}-content-wrapper`]: {
|
||||
position: 'absolute',
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
transition: `transform ${motionDurationSlow} ${motionEaseOut},box-shadow ${motionDurationSlow} ${motionEaseOut}`,
|
||||
[`${drawerPrefixCls}-content`]: {
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
position: 'relative',
|
||||
zIndex: 1,
|
||||
overflow: 'auto',
|
||||
backgroundColor: white,
|
||||
backgroundClip: `padding-box`,
|
||||
border: 0,
|
||||
[`${drawerPrefixCls}-wrapper-body`]: {
|
||||
display: 'flex',
|
||||
flexFlow: 'column nowrap',
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
[`${drawerPrefixCls}-header`]: {
|
||||
position: 'relative',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
padding: `${paddingMd}px ${paddingLG}px`, // FIXME px
|
||||
color: colorText,
|
||||
background: white,
|
||||
borderBottom: `${lineWidth}px ${borderStyle} ${borderColorSplit}`, // FIXME px
|
||||
borderRadius: `${radiusBase}px ${radiusBase}px 0 0`, // FIXME px
|
||||
|
||||
[`${drawerPrefixCls}-header-title`]: {
|
||||
display: 'flex',
|
||||
flex: 1,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
[`${drawerPrefixCls}-title`]: {
|
||||
flex: 1,
|
||||
margin: 0,
|
||||
color: colorText,
|
||||
fontWeight: 500,
|
||||
fontSize: fontSizeLG,
|
||||
lineHeight: drawerTitleLineHeight,
|
||||
},
|
||||
[`${drawerPrefixCls}-close`]: {
|
||||
display: 'inline-block',
|
||||
marginRight: closeRight,
|
||||
color: textColorSecondary,
|
||||
fontWeight: 700,
|
||||
fontSize: fontSizeLG,
|
||||
fontStyle: 'normal',
|
||||
lineHeight: 1,
|
||||
textAlign: 'center',
|
||||
textTransform: 'none',
|
||||
textDecoration: 'none',
|
||||
background: 'transparent',
|
||||
border: 0,
|
||||
outline: 0,
|
||||
cursor: 'pointer',
|
||||
transition: `color ${motionDurationSlow}`,
|
||||
textRendering: 'auto',
|
||||
|
||||
[`${drawerPrefixCls}:focus,${drawerPrefixCls}:hover`]: {
|
||||
color: hoverColor,
|
||||
textDecoration: 'none',
|
||||
},
|
||||
},
|
||||
},
|
||||
[`${drawerPrefixCls}-header-close-only`]: {
|
||||
paddingBottom: 0,
|
||||
border: 'none',
|
||||
},
|
||||
},
|
||||
[`${drawerPrefixCls}-body`]: {
|
||||
flexGrow: 1,
|
||||
padding: paddingLG,
|
||||
overflow: 'auto',
|
||||
fontSize,
|
||||
lineHeight,
|
||||
wordWrap: 'break-word',
|
||||
},
|
||||
[`${drawerPrefixCls}-footer`]: {
|
||||
flexShrink: 0,
|
||||
padding: `${modalFooterPaddingVertical}px ${modalFooterPaddingHorizontal}px`, // FIXME px
|
||||
borderTop: `${lineWidth}px ${borderStyle} ${borderColorSplit}`, // FIXME px
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
[`${drawerPrefixCls}-mask`]: {
|
||||
position: 'absolute',
|
||||
insetBlockStart: 0,
|
||||
insetInlineStart: 0,
|
||||
width: '100%',
|
||||
height: 0,
|
||||
backgroundColor: textColorSecondary,
|
||||
opacity: 0,
|
||||
transition: `opacity ${motionDurationSlow} linear, height 0s ease ${motionDurationSlow}`,
|
||||
pointerEvents: 'none',
|
||||
},
|
||||
},
|
||||
[`${drawerPrefixCls}${drawerPrefixCls}-open ${drawerPrefixCls}-mask`]: {
|
||||
height: '100%',
|
||||
opacity: 1,
|
||||
transition: 'none',
|
||||
animation: `${antdDrawerFadeIn.getName(hashId)} ${motionDurationSlow} ${motionEaseOut}`,
|
||||
pointerEvents: 'auto',
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
const genDrawerStyle: GenerateStyle<DrawerToken> = (token: DrawerToken) => {
|
||||
const {
|
||||
drawerPrefixCls,
|
||||
motionDurationSlow,
|
||||
shadow1Right,
|
||||
shadow1Left,
|
||||
shadow1Down,
|
||||
shadow1Up,
|
||||
lineWidth,
|
||||
motionEaseOut,
|
||||
} = token;
|
||||
|
||||
return {
|
||||
// =================== left,right ===================
|
||||
[`${drawerPrefixCls}-left`]: {
|
||||
insetInlineStart: 0,
|
||||
insetBlockStart: 0,
|
||||
width: 0,
|
||||
height: '100%',
|
||||
[`${drawerPrefixCls}-content-wrapper`]: {
|
||||
height: '100%',
|
||||
insetInlineStart: 0,
|
||||
},
|
||||
},
|
||||
[`${drawerPrefixCls}-left${drawerPrefixCls}-open`]: {
|
||||
width: '100%',
|
||||
transition: `transform ${motionDurationSlow} ${motionEaseOut}`,
|
||||
[`${drawerPrefixCls}-content-wrapper`]: {
|
||||
boxShadow: shadow1Right,
|
||||
},
|
||||
},
|
||||
[`${drawerPrefixCls}-right`]: {
|
||||
insetInlineEnd: 0,
|
||||
insetBlockStart: 0,
|
||||
width: 0,
|
||||
height: '100%',
|
||||
[`${drawerPrefixCls}-content-wrapper`]: {
|
||||
height: '100%',
|
||||
insetInlineEnd: 0,
|
||||
},
|
||||
},
|
||||
[`${drawerPrefixCls}-right${drawerPrefixCls}-open`]: {
|
||||
width: '100%',
|
||||
transition: `transform ${motionDurationSlow} ${motionEaseOut}`,
|
||||
[`${drawerPrefixCls}-content-wrapper`]: {
|
||||
boxShadow: shadow1Left,
|
||||
},
|
||||
},
|
||||
// https://github.com/ant-design/ant-design/issues/18607, Avoid edge alignment bug.
|
||||
[`${drawerPrefixCls}-right${drawerPrefixCls}-open.no-mask`]: {
|
||||
insetInlineEnd: lineWidth,
|
||||
transform: `translateX(${lineWidth})`,
|
||||
},
|
||||
|
||||
// =================== top,bottom ===================
|
||||
[`${drawerPrefixCls}-top,${drawerPrefixCls}-bottom`]: {
|
||||
insetInlineStart: 0,
|
||||
width: '100%',
|
||||
height: 0,
|
||||
[`${drawerPrefixCls}-content-wrapper`]: {
|
||||
width: '100%',
|
||||
},
|
||||
},
|
||||
|
||||
[`${drawerPrefixCls}-top${drawerPrefixCls}-open,${drawerPrefixCls}-bottom${drawerPrefixCls}-open`]:
|
||||
{
|
||||
height: '100%',
|
||||
transition: `transform ${motionDurationSlow} ${motionEaseOut}`,
|
||||
},
|
||||
|
||||
[`${drawerPrefixCls}-top`]: {
|
||||
insetBlockStart: 0,
|
||||
},
|
||||
|
||||
[`${drawerPrefixCls}-top${drawerPrefixCls}-open`]: {
|
||||
[`${drawerPrefixCls}-content-wrapper`]: {
|
||||
boxShadow: shadow1Down,
|
||||
},
|
||||
},
|
||||
|
||||
[`${drawerPrefixCls}-bottom`]: {
|
||||
bottom: 0,
|
||||
[`${drawerPrefixCls}-content-wrapper`]: {
|
||||
bottom: 0,
|
||||
},
|
||||
},
|
||||
|
||||
[`${drawerPrefixCls}-bottom${drawerPrefixCls}-bottom-open`]: {
|
||||
[`${drawerPrefixCls}-content-wrapper`]: {
|
||||
boxShadow: shadow1Up,
|
||||
},
|
||||
},
|
||||
|
||||
[`${drawerPrefixCls}-bottom${drawerPrefixCls}-bottom-open.no-mask`]: {
|
||||
insetBlockEnd: lineWidth,
|
||||
transform: `translateY(${lineWidth})`,
|
||||
},
|
||||
|
||||
// ==================== Hook Components ===================
|
||||
// FIXME: Seems useless?
|
||||
// .@{picker-prefix-cls} {
|
||||
// &-clear {
|
||||
// background: @popover-background,
|
||||
// }
|
||||
// }
|
||||
};
|
||||
};
|
||||
|
||||
// ============================== Export ==============================
|
||||
export default function useStyle(
|
||||
prefixCls: string,
|
||||
iconPrefixCls: string,
|
||||
): UseComponentStyleResult {
|
||||
const [theme, token, hashId] = useToken();
|
||||
const drawerToken: DrawerToken = {
|
||||
...token,
|
||||
prefixCls,
|
||||
iconPrefixCls,
|
||||
drawerPrefixCls: `.${prefixCls}`,
|
||||
|
||||
black: '#000', // FIXME: hard code
|
||||
white: '#fff', // FIXME: hard code
|
||||
drawerHeaderCloseSize: 56, // FIXME: hard code
|
||||
shadow1Right:
|
||||
'6px 0 16px -8px rgba(0, 0, 0, 0.08), 9px 0 28px 0 rgba(0, 0, 0, 0.05),12px 0 48px 16px rgba(0, 0, 0, 0.03)', // FIXME: hard code in v4
|
||||
shadow1Left:
|
||||
'-6px 0 16px -8px rgba(0, 0, 0, 0.08), -9px 0 28px 0 rgba(0, 0, 0, 0.05), -12px 0 48px 16px rgba(0, 0, 0, 0.03)', // FIXME: hard code in v4
|
||||
shadow1Up:
|
||||
'0 -6px 16px -8px rgba(0, 0, 0, 0.32), 0 -9px 28px 0 rgba(0, 0, 0, 0.2),0 -12px 48px 16px rgba(0, 0, 0, 0.12)', // FIXME: hard code in v4
|
||||
shadow1Down:
|
||||
'0 6px 16px -8px rgba(0, 0, 0, 0.32), 0 9px 28px 0 rgba(0, 0, 0, 0.2), 0 12px 48px 16px rgba(0, 0, 0, 0.12)', // FIXME: hard code in v4
|
||||
drawerTitleLineHeight: 1.375, // FIXME: hard code
|
||||
closeRight: 22, // FIXME: hard code
|
||||
paddingMd: 16, // FIXME: hard code
|
||||
modalFooterPaddingVertical: 10, // FIXME: hard code
|
||||
modalFooterPaddingHorizontal: 16, // FIXME: hard code
|
||||
borderColorSplit: new TinyColor({ h: 0, s: 0, v: 94 }).toHexString(), // FIXME: hard code
|
||||
hoverColor: new TinyColor('#000').setAlpha(0.75).toRgbString(), // FIXME: hard code
|
||||
textColorSecondary: new TinyColor('#000').setAlpha(0.45).toRgbString(), // FIXME: hard code
|
||||
borderStyle: 'solid', // FIXME: hard code
|
||||
motionEaseOut: 'cubic-bezier(0.215, 0.61, 0.355, 1)', // FIXME: hard code
|
||||
};
|
||||
|
||||
return [
|
||||
useStyleRegister({ theme, token, hashId, path: [prefixCls] }, () => [
|
||||
genBaseStyle(drawerToken, hashId),
|
||||
genDrawerStyle(drawerToken),
|
||||
]),
|
||||
hashId,
|
||||
];
|
||||
}
|
||||
|
@ -75,7 +75,7 @@ const genInputLargeStyle = (token: InputToken): CSSObject => {
|
||||
};
|
||||
|
||||
const genInputSmallStyle = (token: InputToken): CSSObject => ({
|
||||
padding: `${token.inputPaddingVerticalSM}px ${token.paddingXS - 1}px`,
|
||||
padding: `${token.inputPaddingVerticalSM}px ${token.controlPaddingHorizontalSM - 1}px`,
|
||||
});
|
||||
|
||||
export const genStatusStyle = (token: InputToken): CSSObject => {
|
||||
@ -785,7 +785,7 @@ export const initInputToken = (
|
||||
...token,
|
||||
prefixCls,
|
||||
iconPrefixCls,
|
||||
inputAffixMargin: token.marginXXS,
|
||||
inputAffixMargin: token.marginXS,
|
||||
inputPaddingVertical: Math.max(
|
||||
Math.round(((token.controlHeight - token.fontSize * token.lineHeight) / 2) * 10) / 10 -
|
||||
token.controlLineWidth,
|
||||
@ -799,7 +799,7 @@ export const initInputToken = (
|
||||
token.controlLineWidth,
|
||||
0,
|
||||
),
|
||||
inputPaddingHorizontal: token.paddingSM - token.controlLineWidth,
|
||||
inputPaddingHorizontal: token.controlPaddingHorizontal - token.controlLineWidth,
|
||||
inputBorderHoverColor: token.colorPrimaryHover,
|
||||
inputBorderActiveColor: token.colorPrimaryHover,
|
||||
});
|
||||
|
@ -1,5 +1,6 @@
|
||||
import * as React from 'react';
|
||||
import classNames from 'classnames';
|
||||
// eslint-disable-next-line import/no-named-as-default
|
||||
import Spin, { SpinProps } from '../spin';
|
||||
import useBreakpoint from '../grid/hooks/useBreakpoint';
|
||||
import { Breakpoint, responsiveArray } from '../_util/responsiveObserve';
|
||||
|
@ -3,6 +3,7 @@ import classNames from 'classnames';
|
||||
import RcMentions from 'rc-mentions';
|
||||
import { MentionsProps as RcMentionsProps } from 'rc-mentions/lib/Mentions';
|
||||
import { composeRef } from 'rc-util/lib/ref';
|
||||
// eslint-disable-next-line import/no-named-as-default
|
||||
import Spin from '../spin';
|
||||
import { ConfigContext } from '../config-provider';
|
||||
import { FormItemInputContext } from '../form/context';
|
||||
|
@ -188,7 +188,7 @@ Array [
|
||||
`;
|
||||
|
||||
exports[`renders ./components/notification/demo/placement.md extend context correctly 1`] = `
|
||||
<div>
|
||||
Array [
|
||||
<div
|
||||
class="ant-space ant-space-horizontal ant-space-align-center"
|
||||
>
|
||||
@ -255,11 +255,11 @@ exports[`renders ./components/notification/demo/placement.md extend context corr
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-divider ant-divider-horizontal"
|
||||
role="separator"
|
||||
/>
|
||||
/>,
|
||||
<div
|
||||
class="ant-space ant-space-horizontal ant-space-align-center"
|
||||
>
|
||||
@ -326,11 +326,11 @@ exports[`renders ./components/notification/demo/placement.md extend context corr
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-divider ant-divider-horizontal"
|
||||
role="separator"
|
||||
/>
|
||||
/>,
|
||||
<div
|
||||
class="ant-space ant-space-horizontal ant-space-align-center"
|
||||
>
|
||||
@ -397,8 +397,8 @@ exports[`renders ./components/notification/demo/placement.md extend context corr
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>,
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`renders ./components/notification/demo/update.md extend context correctly 1`] = `
|
||||
|
@ -188,7 +188,7 @@ Array [
|
||||
`;
|
||||
|
||||
exports[`renders ./components/notification/demo/placement.md correctly 1`] = `
|
||||
<div>
|
||||
Array [
|
||||
<div
|
||||
class="ant-space ant-space-horizontal ant-space-align-center"
|
||||
>
|
||||
@ -255,11 +255,11 @@ exports[`renders ./components/notification/demo/placement.md correctly 1`] = `
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-divider ant-divider-horizontal"
|
||||
role="separator"
|
||||
/>
|
||||
/>,
|
||||
<div
|
||||
class="ant-space ant-space-horizontal ant-space-align-center"
|
||||
>
|
||||
@ -326,11 +326,11 @@ exports[`renders ./components/notification/demo/placement.md correctly 1`] = `
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-divider ant-divider-horizontal"
|
||||
role="separator"
|
||||
/>
|
||||
/>,
|
||||
<div
|
||||
class="ant-space ant-space-horizontal ant-space-align-center"
|
||||
>
|
||||
@ -397,8 +397,8 @@ exports[`renders ./components/notification/demo/placement.md correctly 1`] = `
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>,
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`renders ./components/notification/demo/update.md correctly 1`] = `
|
||||
|
@ -41,8 +41,9 @@ describe('Notification.placement', () => {
|
||||
});
|
||||
style = getStyle($$('.ant-notification-top')[0]);
|
||||
expect(style.top).toBe('50px');
|
||||
expect(style.left).toBe('0px');
|
||||
expect(style.right).toBe('0px');
|
||||
expect(style.left).toBe('50%');
|
||||
expect(style.transform).toBe('translateX(-50%)');
|
||||
expect(style.right).toBe('');
|
||||
expect(style.bottom).toBe('');
|
||||
|
||||
open({
|
||||
@ -86,8 +87,9 @@ describe('Notification.placement', () => {
|
||||
});
|
||||
style = getStyle($$('.ant-notification-bottom')[0]);
|
||||
expect(style.top).toBe('');
|
||||
expect(style.left).toBe('0px');
|
||||
expect(style.right).toBe('0px');
|
||||
expect(style.left).toBe('50%');
|
||||
expect(style.transform).toBe('translateX(-50%)');
|
||||
expect(style.right).toBe('');
|
||||
expect(style.bottom).toBe('100px');
|
||||
|
||||
open({
|
||||
|
@ -7,11 +7,11 @@ title:
|
||||
|
||||
## zh-CN
|
||||
|
||||
通知从右上角、右下角、左下角、左上角弹出。
|
||||
使用 `placement` 可以配置通知从右上角、右下角、左下角、左上角弹出。
|
||||
|
||||
## en-US
|
||||
|
||||
A notification box can appear from the `topRight`, `bottomRight`, `bottomLeft` or `topLeft` of the viewport.
|
||||
A notification box can appear from the `topRight`, `bottomRight`, `bottomLeft` or `topLeft` of the viewport via `placement`.
|
||||
|
||||
```jsx
|
||||
import { Button, notification, Divider, Space } from 'antd';
|
||||
@ -34,40 +34,54 @@ const openNotification = placement => {
|
||||
};
|
||||
|
||||
ReactDOM.render(
|
||||
<div>
|
||||
<>
|
||||
<Space>
|
||||
<Button type="primary" onClick={() => openNotification('top')}>
|
||||
<BorderTopOutlined />
|
||||
<Button type="primary" onClick={() => openNotification('top')} icon={<BorderTopOutlined />}>
|
||||
top
|
||||
</Button>
|
||||
<Button type="primary" onClick={() => openNotification('bottom')}>
|
||||
<BorderBottomOutlined />
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={() => openNotification('bottom')}
|
||||
icon={<BorderBottomOutlined />}
|
||||
>
|
||||
bottom
|
||||
</Button>
|
||||
</Space>
|
||||
<Divider />
|
||||
<Space>
|
||||
<Button type="primary" onClick={() => openNotification('topLeft')}>
|
||||
<RadiusUpleftOutlined />
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={() => openNotification('topLeft')}
|
||||
icon={<RadiusUpleftOutlined />}
|
||||
>
|
||||
topLeft
|
||||
</Button>
|
||||
<Button type="primary" onClick={() => openNotification('topRight')}>
|
||||
<RadiusUprightOutlined />
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={() => openNotification('topRight')}
|
||||
icon={<RadiusUprightOutlined />}
|
||||
>
|
||||
topRight
|
||||
</Button>
|
||||
</Space>
|
||||
<Divider />
|
||||
<Space>
|
||||
<Button type="primary" onClick={() => openNotification('bottomLeft')}>
|
||||
<RadiusBottomleftOutlined />
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={() => openNotification('bottomLeft')}
|
||||
icon={<RadiusBottomleftOutlined />}
|
||||
>
|
||||
bottomLeft
|
||||
</Button>
|
||||
<Button type="primary" onClick={() => openNotification('bottomRight')}>
|
||||
<RadiusBottomrightOutlined />
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={() => openNotification('bottomRight')}
|
||||
icon={<RadiusBottomrightOutlined />}
|
||||
>
|
||||
bottomRight
|
||||
</Button>
|
||||
</Space>
|
||||
</div>,
|
||||
</>,
|
||||
mountNode,
|
||||
);
|
||||
```
|
||||
|
@ -87,8 +87,9 @@ function getPlacementStyle(
|
||||
switch (placement) {
|
||||
case 'top':
|
||||
style = {
|
||||
left: 0,
|
||||
right: 0,
|
||||
left: '50%',
|
||||
transform: 'translateX(-50%)',
|
||||
right: 'auto',
|
||||
top,
|
||||
bottom: 'auto',
|
||||
};
|
||||
@ -109,8 +110,9 @@ function getPlacementStyle(
|
||||
break;
|
||||
case 'bottom':
|
||||
style = {
|
||||
left: 0,
|
||||
right: 0,
|
||||
left: '50%',
|
||||
transform: 'translateX(-50%)',
|
||||
right: 'auto',
|
||||
top: 'auto',
|
||||
bottom,
|
||||
};
|
||||
|
@ -16,25 +16,6 @@
|
||||
z-index: @zindex-notification;
|
||||
margin-right: @notification-margin-edge;
|
||||
|
||||
&-top,
|
||||
&-bottom,
|
||||
&-topLeft,
|
||||
&-bottomLeft {
|
||||
margin-right: 0;
|
||||
margin-left: @notification-margin-edge;
|
||||
|
||||
.@{notification-prefix-cls}-fade-enter.@{notification-prefix-cls}-fade-enter-active,
|
||||
.@{notification-prefix-cls}-fade-appear.@{notification-prefix-cls}-fade-appear-active {
|
||||
animation-name: NotificationLeftFadeIn;
|
||||
}
|
||||
}
|
||||
|
||||
&-top,
|
||||
&-bottom {
|
||||
margin-right: auto;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
&-close-icon {
|
||||
font-size: @font-size-base;
|
||||
cursor: pointer;
|
||||
@ -206,18 +187,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes NotificationLeftFadeIn {
|
||||
0% {
|
||||
right: @notification-width;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
right: 0;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes NotificationFadeOut {
|
||||
0% {
|
||||
max-height: 150px;
|
||||
@ -235,3 +204,4 @@
|
||||
}
|
||||
|
||||
@import './rtl';
|
||||
@import './placement';
|
||||
|
68
components/notification/style/placement.less
Normal file
68
components/notification/style/placement.less
Normal file
@ -0,0 +1,68 @@
|
||||
.@{notification-prefix-cls} {
|
||||
&-top,
|
||||
&-bottom {
|
||||
margin-right: 0;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
&-top {
|
||||
.@{notification-prefix-cls}-fade-enter.@{notification-prefix-cls}-fade-enter-active,
|
||||
.@{notification-prefix-cls}-fade-appear.@{notification-prefix-cls}-fade-appear-active {
|
||||
animation-name: NotificationTopFadeIn;
|
||||
}
|
||||
}
|
||||
|
||||
&-bottom {
|
||||
.@{notification-prefix-cls}-fade-enter.@{notification-prefix-cls}-fade-enter-active,
|
||||
.@{notification-prefix-cls}-fade-appear.@{notification-prefix-cls}-fade-appear-active {
|
||||
animation-name: NotificationBottomFadeIn;
|
||||
}
|
||||
}
|
||||
|
||||
&-topLeft,
|
||||
&-bottomLeft {
|
||||
margin-right: 0;
|
||||
margin-left: @notification-margin-edge;
|
||||
|
||||
.@{notification-prefix-cls}-fade-enter.@{notification-prefix-cls}-fade-enter-active,
|
||||
.@{notification-prefix-cls}-fade-appear.@{notification-prefix-cls}-fade-appear-active {
|
||||
animation-name: NotificationLeftFadeIn;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes NotificationTopFadeIn {
|
||||
0% {
|
||||
margin-top: -100%;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
margin-top: 0;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes NotificationBottomFadeIn {
|
||||
0% {
|
||||
margin-bottom: -100%;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
margin-bottom: 0;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes NotificationLeftFadeIn {
|
||||
0% {
|
||||
right: @notification-width;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
right: 0;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
@ -1,17 +1,21 @@
|
||||
import * as React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import Tooltip, { AbstractTooltipProps, TooltipPlacement } from '../tooltip';
|
||||
import { ConfigContext } from '../config-provider';
|
||||
import { getRenderPropValue, RenderFunction } from '../_util/getRenderPropValue';
|
||||
import { getTransitionName } from '../_util/motion';
|
||||
|
||||
// CSSINJS
|
||||
import useStyle from './style';
|
||||
|
||||
export interface PopoverProps extends AbstractTooltipProps {
|
||||
title?: React.ReactNode | RenderFunction;
|
||||
content?: React.ReactNode | RenderFunction;
|
||||
}
|
||||
|
||||
const Popover = React.forwardRef<unknown, PopoverProps>(
|
||||
({ prefixCls: customizePrefixCls, title, content, ...otherProps }, ref) => {
|
||||
const { getPrefixCls } = React.useContext(ConfigContext);
|
||||
({ prefixCls: customizePrefixCls, title, content, overlayClassName, ...otherProps }, ref) => {
|
||||
const { getPrefixCls, iconPrefixCls } = React.useContext(ConfigContext);
|
||||
|
||||
const getOverlay = (prefixCls: string) => {
|
||||
if (!title && !content) return undefined;
|
||||
@ -24,16 +28,20 @@ const Popover = React.forwardRef<unknown, PopoverProps>(
|
||||
};
|
||||
|
||||
const prefixCls = getPrefixCls('popover', customizePrefixCls);
|
||||
const [wrapSSR, hashId] = useStyle(prefixCls, iconPrefixCls);
|
||||
const rootPrefixCls = getPrefixCls();
|
||||
|
||||
return (
|
||||
const overlayCls = classNames(overlayClassName, hashId);
|
||||
|
||||
return wrapSSR(
|
||||
<Tooltip
|
||||
{...otherProps}
|
||||
prefixCls={prefixCls}
|
||||
overlayClassName={overlayCls}
|
||||
ref={ref as any}
|
||||
overlay={getOverlay(prefixCls)}
|
||||
transitionName={getTransitionName(rootPrefixCls, 'zoom-big', otherProps.transitionName)}
|
||||
/>
|
||||
/>,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
@ -1,258 +1,258 @@
|
||||
@import '../../style/themes/index';
|
||||
@import '../../style/mixins/index';
|
||||
// @import '../../style/themes/index';
|
||||
// @import '../../style/mixins/index';
|
||||
|
||||
@popover-prefix-cls: ~'@{ant-prefix}-popover';
|
||||
// @popover-prefix-cls: ~'@{ant-prefix}-popover';
|
||||
|
||||
@popover-arrow-rotate-width: sqrt(@popover-arrow-width * @popover-arrow-width * 2);
|
||||
// @popover-arrow-rotate-width: sqrt(@popover-arrow-width * @popover-arrow-width * 2);
|
||||
|
||||
@popover-arrow-offset-vertical: 12px;
|
||||
@popover-arrow-offset-horizontal: 16px;
|
||||
// @popover-arrow-offset-vertical: 12px;
|
||||
// @popover-arrow-offset-horizontal: 16px;
|
||||
|
||||
.@{popover-prefix-cls} {
|
||||
.reset-component();
|
||||
// .@{popover-prefix-cls} {
|
||||
// .reset-component();
|
||||
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: @zindex-popover;
|
||||
font-weight: normal;
|
||||
white-space: normal;
|
||||
text-align: left;
|
||||
cursor: auto;
|
||||
user-select: text;
|
||||
// position: absolute;
|
||||
// top: 0;
|
||||
// left: 0;
|
||||
// z-index: @zindex-popover;
|
||||
// font-weight: normal;
|
||||
// white-space: normal;
|
||||
// text-align: left;
|
||||
// cursor: auto;
|
||||
// user-select: text;
|
||||
|
||||
&::after {
|
||||
position: absolute;
|
||||
background: fade(@white, 1%);
|
||||
content: '';
|
||||
}
|
||||
// &::after {
|
||||
// position: absolute;
|
||||
// background: fade(@white, 1%);
|
||||
// content: '';
|
||||
// }
|
||||
|
||||
&-hidden {
|
||||
display: none;
|
||||
}
|
||||
// &-hidden {
|
||||
// display: none;
|
||||
// }
|
||||
|
||||
// Offset the popover to account for the popover arrow
|
||||
&-placement-top,
|
||||
&-placement-topLeft,
|
||||
&-placement-topRight {
|
||||
padding-bottom: @popover-distance;
|
||||
}
|
||||
// // Offset the popover to account for the popover arrow
|
||||
// &-placement-top,
|
||||
// &-placement-topLeft,
|
||||
// &-placement-topRight {
|
||||
// padding-bottom: @popover-distance;
|
||||
// }
|
||||
|
||||
&-placement-right,
|
||||
&-placement-rightTop,
|
||||
&-placement-rightBottom {
|
||||
padding-left: @popover-distance;
|
||||
}
|
||||
// &-placement-right,
|
||||
// &-placement-rightTop,
|
||||
// &-placement-rightBottom {
|
||||
// padding-left: @popover-distance;
|
||||
// }
|
||||
|
||||
&-placement-bottom,
|
||||
&-placement-bottomLeft,
|
||||
&-placement-bottomRight {
|
||||
padding-top: @popover-distance;
|
||||
}
|
||||
// &-placement-bottom,
|
||||
// &-placement-bottomLeft,
|
||||
// &-placement-bottomRight {
|
||||
// padding-top: @popover-distance;
|
||||
// }
|
||||
|
||||
&-placement-left,
|
||||
&-placement-leftTop,
|
||||
&-placement-leftBottom {
|
||||
padding-right: @popover-distance;
|
||||
}
|
||||
// &-placement-left,
|
||||
// &-placement-leftTop,
|
||||
// &-placement-leftBottom {
|
||||
// padding-right: @popover-distance;
|
||||
// }
|
||||
|
||||
&-inner {
|
||||
background-color: @popover-bg;
|
||||
background-clip: padding-box;
|
||||
border-radius: @border-radius-base;
|
||||
box-shadow: @box-shadow-base;
|
||||
box-shadow: ~'0 0 8px @{shadow-color} \9';
|
||||
}
|
||||
// &-inner {
|
||||
// background-color: @popover-bg;
|
||||
// background-clip: padding-box;
|
||||
// border-radius: @border-radius-base;
|
||||
// box-shadow: @box-shadow-base;
|
||||
// box-shadow: ~'0 0 8px @{shadow-color} \9';
|
||||
// }
|
||||
|
||||
@media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) {
|
||||
/* IE10+ */
|
||||
&-inner {
|
||||
box-shadow: @box-shadow-base;
|
||||
}
|
||||
}
|
||||
// @media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) {
|
||||
// /* IE10+ */
|
||||
// &-inner {
|
||||
// box-shadow: @box-shadow-base;
|
||||
// }
|
||||
// }
|
||||
|
||||
&-title {
|
||||
min-width: @popover-min-width;
|
||||
min-height: @popover-min-height;
|
||||
margin: 0; // reset heading margin
|
||||
padding: 5px @popover-padding-horizontal 4px;
|
||||
color: @heading-color;
|
||||
font-weight: 500;
|
||||
border-bottom: 1px solid @border-color-split;
|
||||
}
|
||||
// &-title {
|
||||
// min-width: @popover-min-width;
|
||||
// min-height: @popover-min-height;
|
||||
// margin: 0; // reset heading margin
|
||||
// padding: 5px @popover-padding-horizontal 4px;
|
||||
// color: @heading-color;
|
||||
// font-weight: 500;
|
||||
// border-bottom: 1px solid @border-color-split;
|
||||
// }
|
||||
|
||||
&-inner-content {
|
||||
padding: @padding-sm @popover-padding-horizontal;
|
||||
color: @popover-color;
|
||||
}
|
||||
// &-inner-content {
|
||||
// padding: @padding-sm @popover-padding-horizontal;
|
||||
// color: @popover-color;
|
||||
// }
|
||||
|
||||
&-message {
|
||||
position: relative;
|
||||
padding: 4px 0 12px;
|
||||
color: @popover-color;
|
||||
font-size: @font-size-base;
|
||||
> .@{iconfont-css-prefix} {
|
||||
position: absolute;
|
||||
top: (
|
||||
4px + ((@line-height-base * @font-size-base - @font-size-base) / 2)
|
||||
); // 4px for padding-top, 4px for vertical middle
|
||||
color: @warning-color;
|
||||
font-size: @font-size-base;
|
||||
}
|
||||
// &-message {
|
||||
// position: relative;
|
||||
// padding: 4px 0 12px;
|
||||
// color: @popover-color;
|
||||
// font-size: @font-size-base;
|
||||
// > .@{iconfont-css-prefix} {
|
||||
// position: absolute;
|
||||
// top: (
|
||||
// 4px + ((@line-height-base * @font-size-base - @font-size-base) / 2)
|
||||
// ); // 4px for padding-top, 4px for vertical middle
|
||||
// color: @warning-color;
|
||||
// font-size: @font-size-base;
|
||||
// }
|
||||
|
||||
&-title {
|
||||
padding-left: @font-size-base + 8px;
|
||||
}
|
||||
}
|
||||
// &-title {
|
||||
// padding-left: @font-size-base + 8px;
|
||||
// }
|
||||
// }
|
||||
|
||||
&-buttons {
|
||||
margin-bottom: 4px;
|
||||
text-align: right;
|
||||
// &-buttons {
|
||||
// margin-bottom: 4px;
|
||||
// text-align: right;
|
||||
|
||||
button {
|
||||
margin-left: 8px;
|
||||
}
|
||||
}
|
||||
// button {
|
||||
// margin-left: 8px;
|
||||
// }
|
||||
// }
|
||||
|
||||
// Arrows
|
||||
&-arrow {
|
||||
position: absolute;
|
||||
display: block;
|
||||
width: @popover-arrow-rotate-width;
|
||||
height: @popover-arrow-rotate-width;
|
||||
overflow: hidden;
|
||||
background: transparent;
|
||||
pointer-events: none;
|
||||
// // Arrows
|
||||
// &-arrow {
|
||||
// position: absolute;
|
||||
// display: block;
|
||||
// width: @popover-arrow-rotate-width;
|
||||
// height: @popover-arrow-rotate-width;
|
||||
// overflow: hidden;
|
||||
// background: transparent;
|
||||
// pointer-events: none;
|
||||
|
||||
&-content {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
display: block;
|
||||
width: @popover-arrow-width;
|
||||
height: @popover-arrow-width;
|
||||
margin: auto;
|
||||
background-color: @popover-bg;
|
||||
content: '';
|
||||
pointer-events: auto;
|
||||
.roundedArrow(@popover-arrow-width, 5px, @popover-bg);
|
||||
}
|
||||
}
|
||||
// &-content {
|
||||
// position: absolute;
|
||||
// top: 0;
|
||||
// right: 0;
|
||||
// bottom: 0;
|
||||
// left: 0;
|
||||
// display: block;
|
||||
// width: @popover-arrow-width;
|
||||
// height: @popover-arrow-width;
|
||||
// margin: auto;
|
||||
// background-color: @popover-bg;
|
||||
// content: '';
|
||||
// pointer-events: auto;
|
||||
// .roundedArrow(@popover-arrow-width, 5px, @popover-bg);
|
||||
// }
|
||||
// }
|
||||
|
||||
&-placement-top &-arrow,
|
||||
&-placement-topLeft &-arrow,
|
||||
&-placement-topRight &-arrow {
|
||||
bottom: @popover-distance - @popover-arrow-rotate-width;
|
||||
// &-placement-top &-arrow,
|
||||
// &-placement-topLeft &-arrow,
|
||||
// &-placement-topRight &-arrow {
|
||||
// bottom: @popover-distance - @popover-arrow-rotate-width;
|
||||
|
||||
&-content {
|
||||
box-shadow: 3px 3px 7px fade(@black, 7%);
|
||||
transform: translateY((-@popover-arrow-rotate-width / 2)) rotate(45deg);
|
||||
}
|
||||
}
|
||||
// &-content {
|
||||
// box-shadow: 3px 3px 7px fade(@black, 7%);
|
||||
// transform: translateY((-@popover-arrow-rotate-width / 2)) rotate(45deg);
|
||||
// }
|
||||
// }
|
||||
|
||||
&-placement-top &-arrow {
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
// &-placement-top &-arrow {
|
||||
// left: 50%;
|
||||
// transform: translateX(-50%);
|
||||
// }
|
||||
|
||||
&-placement-topLeft &-arrow {
|
||||
left: @popover-arrow-offset-horizontal;
|
||||
}
|
||||
// &-placement-topLeft &-arrow {
|
||||
// left: @popover-arrow-offset-horizontal;
|
||||
// }
|
||||
|
||||
&-placement-topRight &-arrow {
|
||||
right: @popover-arrow-offset-horizontal;
|
||||
}
|
||||
// &-placement-topRight &-arrow {
|
||||
// right: @popover-arrow-offset-horizontal;
|
||||
// }
|
||||
|
||||
&-placement-right &-arrow,
|
||||
&-placement-rightTop &-arrow,
|
||||
&-placement-rightBottom &-arrow {
|
||||
left: @popover-distance - @popover-arrow-rotate-width;
|
||||
// &-placement-right &-arrow,
|
||||
// &-placement-rightTop &-arrow,
|
||||
// &-placement-rightBottom &-arrow {
|
||||
// left: @popover-distance - @popover-arrow-rotate-width;
|
||||
|
||||
&-content {
|
||||
box-shadow: 3px 3px 7px fade(@black, 7%);
|
||||
transform: translateX((@popover-arrow-rotate-width / 2)) rotate(135deg);
|
||||
}
|
||||
}
|
||||
// &-content {
|
||||
// box-shadow: 3px 3px 7px fade(@black, 7%);
|
||||
// transform: translateX((@popover-arrow-rotate-width / 2)) rotate(135deg);
|
||||
// }
|
||||
// }
|
||||
|
||||
&-placement-right &-arrow {
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
// &-placement-right &-arrow {
|
||||
// top: 50%;
|
||||
// transform: translateY(-50%);
|
||||
// }
|
||||
|
||||
&-placement-rightTop &-arrow {
|
||||
top: @popover-arrow-offset-vertical;
|
||||
}
|
||||
// &-placement-rightTop &-arrow {
|
||||
// top: @popover-arrow-offset-vertical;
|
||||
// }
|
||||
|
||||
&-placement-rightBottom &-arrow {
|
||||
bottom: @popover-arrow-offset-vertical;
|
||||
}
|
||||
// &-placement-rightBottom &-arrow {
|
||||
// bottom: @popover-arrow-offset-vertical;
|
||||
// }
|
||||
|
||||
&-placement-bottom &-arrow,
|
||||
&-placement-bottomLeft &-arrow,
|
||||
&-placement-bottomRight &-arrow {
|
||||
top: @popover-distance - @popover-arrow-rotate-width;
|
||||
// &-placement-bottom &-arrow,
|
||||
// &-placement-bottomLeft &-arrow,
|
||||
// &-placement-bottomRight &-arrow {
|
||||
// top: @popover-distance - @popover-arrow-rotate-width;
|
||||
|
||||
&-content {
|
||||
box-shadow: 2px 2px 5px fade(@black, 6%);
|
||||
transform: translateY((@popover-arrow-rotate-width / 2)) rotate(-135deg);
|
||||
}
|
||||
}
|
||||
// &-content {
|
||||
// box-shadow: 2px 2px 5px fade(@black, 6%);
|
||||
// transform: translateY((@popover-arrow-rotate-width / 2)) rotate(-135deg);
|
||||
// }
|
||||
// }
|
||||
|
||||
&-placement-bottom &-arrow {
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
// &-placement-bottom &-arrow {
|
||||
// left: 50%;
|
||||
// transform: translateX(-50%);
|
||||
// }
|
||||
|
||||
&-placement-bottomLeft &-arrow {
|
||||
left: @popover-arrow-offset-horizontal;
|
||||
}
|
||||
// &-placement-bottomLeft &-arrow {
|
||||
// left: @popover-arrow-offset-horizontal;
|
||||
// }
|
||||
|
||||
&-placement-bottomRight &-arrow {
|
||||
right: @popover-arrow-offset-horizontal;
|
||||
}
|
||||
// &-placement-bottomRight &-arrow {
|
||||
// right: @popover-arrow-offset-horizontal;
|
||||
// }
|
||||
|
||||
&-placement-left &-arrow,
|
||||
&-placement-leftTop &-arrow,
|
||||
&-placement-leftBottom &-arrow {
|
||||
right: @popover-distance - @popover-arrow-rotate-width;
|
||||
// &-placement-left &-arrow,
|
||||
// &-placement-leftTop &-arrow,
|
||||
// &-placement-leftBottom &-arrow {
|
||||
// right: @popover-distance - @popover-arrow-rotate-width;
|
||||
|
||||
&-content {
|
||||
box-shadow: 3px 3px 7px fade(@black, 7%);
|
||||
transform: translateX((-@popover-arrow-rotate-width / 2)) rotate(-45deg);
|
||||
}
|
||||
}
|
||||
// &-content {
|
||||
// box-shadow: 3px 3px 7px fade(@black, 7%);
|
||||
// transform: translateX((-@popover-arrow-rotate-width / 2)) rotate(-45deg);
|
||||
// }
|
||||
// }
|
||||
|
||||
&-placement-left &-arrow {
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
// &-placement-left &-arrow {
|
||||
// top: 50%;
|
||||
// transform: translateY(-50%);
|
||||
// }
|
||||
|
||||
&-placement-leftTop &-arrow {
|
||||
top: @popover-arrow-offset-vertical;
|
||||
}
|
||||
// &-placement-leftTop &-arrow {
|
||||
// top: @popover-arrow-offset-vertical;
|
||||
// }
|
||||
|
||||
&-placement-leftBottom &-arrow {
|
||||
bottom: @popover-arrow-offset-vertical;
|
||||
}
|
||||
}
|
||||
// &-placement-leftBottom &-arrow {
|
||||
// bottom: @popover-arrow-offset-vertical;
|
||||
// }
|
||||
// }
|
||||
|
||||
.generator-popover-preset-color(@i: length(@preset-colors)) when (@i > 0) {
|
||||
.generator-popover-preset-color(@i - 1);
|
||||
@color: extract(@preset-colors, @i);
|
||||
@lightColor: '@{color}-6';
|
||||
.@{popover-prefix-cls}-@{color} {
|
||||
.@{popover-prefix-cls}-inner {
|
||||
background-color: @@lightColor;
|
||||
}
|
||||
.@{popover-prefix-cls}-arrow {
|
||||
&-content {
|
||||
background-color: @@lightColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.generator-popover-preset-color();
|
||||
// .generator-popover-preset-color(@i: length(@preset-colors)) when (@i > 0) {
|
||||
// .generator-popover-preset-color(@i - 1);
|
||||
// @color: extract(@preset-colors, @i);
|
||||
// @lightColor: '@{color}-6';
|
||||
// .@{popover-prefix-cls}-@{color} {
|
||||
// .@{popover-prefix-cls}-inner {
|
||||
// background-color: @@lightColor;
|
||||
// }
|
||||
// .@{popover-prefix-cls}-arrow {
|
||||
// &-content {
|
||||
// background-color: @@lightColor;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// .generator-popover-preset-color();
|
||||
|
||||
@import './rtl';
|
||||
// @import './rtl';
|
||||
|
@ -1,5 +1,394 @@
|
||||
import '../../style/index.less';
|
||||
import './index.less';
|
||||
// import '../../style/index.less';
|
||||
// import './index.less';
|
||||
|
||||
// style dependencies
|
||||
// deps-lint-skip: tooltip
|
||||
|
||||
// deps-lint-skip-all
|
||||
import { TinyColor } from '@ctrl/tinycolor';
|
||||
import { CSSInterpolation, CSSObject } from '@ant-design/cssinjs';
|
||||
import {
|
||||
PresetColors,
|
||||
PresetColorType,
|
||||
DerivativeToken,
|
||||
useStyleRegister,
|
||||
useToken,
|
||||
UseComponentStyleResult,
|
||||
GenerateStyle,
|
||||
resetComponent,
|
||||
roundedArrow,
|
||||
} from '../../_util/theme';
|
||||
|
||||
// FIXME
|
||||
type PopoverToken = DerivativeToken & {
|
||||
popoverCls: string;
|
||||
iconPrefixCls: string;
|
||||
popoverBg: string;
|
||||
popoverColor: string;
|
||||
popoverMinWidth: number;
|
||||
popoverMinHeight: number;
|
||||
popoverArrowWidth: number;
|
||||
popoverArrowColor: string;
|
||||
popoverArrowOuterColor: string;
|
||||
popoverDistance: number;
|
||||
popoverPaddingHorizonta: number;
|
||||
popoverArrowRotateWidth: number;
|
||||
popoverArrowOffsetVertical: number;
|
||||
popoverArrowOffsetHorizontal: number;
|
||||
};
|
||||
|
||||
const genBaseStyle: GenerateStyle<PopoverToken> = token => {
|
||||
const {
|
||||
popoverCls,
|
||||
iconPrefixCls,
|
||||
popoverBg,
|
||||
popoverColor,
|
||||
popoverMinWidth,
|
||||
popoverMinHeight,
|
||||
popoverArrowWidth,
|
||||
popoverPaddingHorizonta,
|
||||
popoverArrowRotateWidth,
|
||||
|
||||
boxShadow,
|
||||
colorSplit,
|
||||
colorTextHeading,
|
||||
colorWarning,
|
||||
fontSize,
|
||||
marginSM,
|
||||
marginXS,
|
||||
lineHeight,
|
||||
radiusBase: borderRadius,
|
||||
paddingSM,
|
||||
zIndexPopover,
|
||||
} = token;
|
||||
|
||||
return {
|
||||
[popoverCls]: {
|
||||
...resetComponent(token),
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
insetInlineStart: 0,
|
||||
zIndex: zIndexPopover,
|
||||
fontWeight: 'normal',
|
||||
whiteSpace: 'normal',
|
||||
textAlign: 'start',
|
||||
cursor: 'auto',
|
||||
userSelect: 'text',
|
||||
|
||||
'&::after': {
|
||||
position: 'absolute',
|
||||
// FIXME
|
||||
background: new TinyColor('#fff').setAlpha(0.01).toRgbString(),
|
||||
content: '""',
|
||||
},
|
||||
|
||||
'&-rtl': {
|
||||
direction: 'rtl',
|
||||
},
|
||||
|
||||
'&-hidden': {
|
||||
display: 'none',
|
||||
},
|
||||
|
||||
[`${popoverCls}-inner`]: {
|
||||
backgroundColor: popoverBg,
|
||||
backgroundClip: 'padding-box',
|
||||
borderRadius,
|
||||
boxShadow,
|
||||
},
|
||||
|
||||
[`${popoverCls}-title`]: {
|
||||
minWidth: popoverMinWidth,
|
||||
minHeight: popoverMinHeight,
|
||||
margin: 0,
|
||||
// FIXME
|
||||
padding: `5px ${popoverPaddingHorizonta}px 4px`,
|
||||
color: colorTextHeading,
|
||||
fontWeight: 500,
|
||||
// FIXME
|
||||
borderBottom: `1px solid ${colorSplit}`,
|
||||
},
|
||||
|
||||
[`${popoverCls}-inner-content`]: {
|
||||
padding: `${paddingSM}px ${popoverPaddingHorizonta}px`,
|
||||
color: popoverColor,
|
||||
},
|
||||
|
||||
// FIXME 没找到使用地方,先保留
|
||||
'&-message': {
|
||||
position: 'relative',
|
||||
// FIXME
|
||||
padding: '4px 0 12px',
|
||||
color: popoverColor,
|
||||
fontSize,
|
||||
|
||||
[`> .${iconPrefixCls}`]: {
|
||||
position: 'absolute',
|
||||
// FIXME
|
||||
top: 4 + (lineHeight * fontSize - fontSize) / 2,
|
||||
color: colorWarning,
|
||||
fontSize,
|
||||
},
|
||||
|
||||
'&-title': {
|
||||
// FIXME
|
||||
paddingInlineStart: fontSize + 8,
|
||||
},
|
||||
},
|
||||
|
||||
// FIXME 没找到使用地方,先保留
|
||||
'&-buttons': {
|
||||
marginBottom: marginXS,
|
||||
textAlign: 'end',
|
||||
|
||||
button: {
|
||||
marginInlineStart: marginSM,
|
||||
},
|
||||
},
|
||||
|
||||
[`${popoverCls}-arrow`]: {
|
||||
position: 'absolute',
|
||||
display: 'block',
|
||||
width: popoverArrowRotateWidth,
|
||||
height: popoverArrowRotateWidth,
|
||||
overflow: 'hidden',
|
||||
background: 'transparent',
|
||||
pointerEvents: 'none',
|
||||
|
||||
'&-content': {
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
insetInlineEnd: 0,
|
||||
bottom: 0,
|
||||
insetInlineStart: 0,
|
||||
display: 'block',
|
||||
width: popoverArrowWidth,
|
||||
height: popoverArrowWidth,
|
||||
margin: 'auto',
|
||||
backgroundColor: popoverBg,
|
||||
content: '""',
|
||||
pointerEvents: 'auto',
|
||||
...roundedArrow(popoverArrowWidth, 5, popoverBg),
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
const genPlacementStyle: GenerateStyle<PopoverToken> = token => {
|
||||
const {
|
||||
popoverCls,
|
||||
popoverDistance,
|
||||
popoverArrowRotateWidth,
|
||||
popoverArrowOffsetHorizontal,
|
||||
popoverArrowOffsetVertical,
|
||||
} = token;
|
||||
|
||||
return {
|
||||
[popoverCls]: {
|
||||
[`
|
||||
&-placement-top,
|
||||
&-placement-topLeft,
|
||||
&-placement-topRight
|
||||
`]: {
|
||||
paddingBottom: popoverDistance,
|
||||
},
|
||||
|
||||
[`
|
||||
&-placement-right,
|
||||
&-placement-rightTop,
|
||||
&-placement-rightBottom
|
||||
`]: {
|
||||
paddingLeft: popoverDistance,
|
||||
},
|
||||
|
||||
[`
|
||||
&-placement-bottom,
|
||||
&-placement-bottomLeft,
|
||||
&-placement-bottomRight
|
||||
`]: {
|
||||
paddingTop: popoverDistance,
|
||||
},
|
||||
|
||||
[`
|
||||
&-placement-left,
|
||||
&-placement-leftTop,
|
||||
&-placement-leftBottom
|
||||
`]: {
|
||||
paddingRight: popoverDistance,
|
||||
},
|
||||
|
||||
[`
|
||||
&-placement-top ${popoverCls}-arrow,
|
||||
&-placement-topLeft ${popoverCls}-arrow,
|
||||
&-placement-topRight ${popoverCls}-arrow
|
||||
`]: {
|
||||
bottom: popoverDistance - popoverArrowRotateWidth,
|
||||
|
||||
'&-content': {
|
||||
// FIXME
|
||||
boxShadow: `3px 3px 7px ${new TinyColor('#000').setAlpha(0.07).toRgbString()}`,
|
||||
transform: `translateY(-${popoverArrowRotateWidth / 2}px) rotate(45deg)`,
|
||||
},
|
||||
},
|
||||
|
||||
[`&-placement-top ${popoverCls}-arrow`]: {
|
||||
insetInlineStart: '50%',
|
||||
transform: 'translateX(-50%)',
|
||||
},
|
||||
|
||||
[`&-placement-topLeft ${popoverCls}-arrow`]: {
|
||||
insetInlineStart: popoverArrowOffsetHorizontal,
|
||||
},
|
||||
|
||||
[`&-placement-topRight ${popoverCls}-arrow`]: {
|
||||
insetInlineEnd: popoverArrowOffsetHorizontal,
|
||||
},
|
||||
|
||||
[`
|
||||
&-placement-right ${popoverCls}-arrow,
|
||||
&-placement-rightTop ${popoverCls}-arrow,
|
||||
&-placement-rightBottom ${popoverCls}-arrow
|
||||
`]: {
|
||||
insetInlineStart: popoverDistance - popoverArrowRotateWidth,
|
||||
|
||||
'&-content': {
|
||||
// FIXME
|
||||
boxShadow: `3px 3px 7px ${new TinyColor('#000').setAlpha(0.07).toRgbString()}`,
|
||||
transform: `translateX(${popoverArrowRotateWidth / 2}px) rotate(135deg)`,
|
||||
},
|
||||
},
|
||||
|
||||
[`&-placement-right ${popoverCls}-arrow`]: {
|
||||
top: '50%',
|
||||
transform: 'translateY(-50%)',
|
||||
},
|
||||
|
||||
[`&-placement-rightTop ${popoverCls}-arrow`]: {
|
||||
top: popoverArrowOffsetVertical,
|
||||
},
|
||||
|
||||
[`&-placement-rightBottom ${popoverCls}-arrow`]: {
|
||||
bottom: popoverArrowOffsetVertical,
|
||||
},
|
||||
|
||||
[`
|
||||
&-placement-bottom ${popoverCls}-arrow,
|
||||
&-placement-bottomLeft ${popoverCls}-arrow,
|
||||
&-placement-bottomRight ${popoverCls}-arrow
|
||||
`]: {
|
||||
top: popoverDistance - popoverArrowRotateWidth,
|
||||
|
||||
'&-content': {
|
||||
// FIXME
|
||||
boxShadow: `2px 2px 5px ${new TinyColor('#000').setAlpha(0.06).toRgbString()}`,
|
||||
transform: `translateY(${popoverArrowRotateWidth / 2}px) rotate(-135deg)`,
|
||||
},
|
||||
},
|
||||
|
||||
[`&-placement-bottom ${popoverCls}-arrow`]: {
|
||||
insetInlineStart: '50%',
|
||||
transform: 'translateX(-50%)',
|
||||
},
|
||||
|
||||
[`&-placement-bottomLeft ${popoverCls}-arrow`]: {
|
||||
insetInlineStart: popoverArrowOffsetHorizontal,
|
||||
},
|
||||
|
||||
[`&-placement-bottomRight ${popoverCls}-arrow`]: {
|
||||
insetInlineEnd: popoverArrowOffsetHorizontal,
|
||||
},
|
||||
|
||||
[`
|
||||
&-placement-left ${popoverCls}-arrow,
|
||||
&-placement-leftTop ${popoverCls}-arrow,
|
||||
&-placement-leftBottom ${popoverCls}-arrow
|
||||
`]: {
|
||||
insetInlineEnd: popoverDistance - popoverArrowRotateWidth,
|
||||
|
||||
'&-content': {
|
||||
// FIXME
|
||||
boxShadow: `3px 3px 7px ${new TinyColor('#000').setAlpha(0.07).toRgbString()}`,
|
||||
transform: `translateX(-${popoverArrowRotateWidth / 2}px) rotate(-45deg)`,
|
||||
},
|
||||
},
|
||||
|
||||
[`&-placement-left ${popoverCls}-arrow`]: {
|
||||
top: '50%',
|
||||
transform: 'translateY(-50%)',
|
||||
},
|
||||
|
||||
[`&-placement-leftTop ${popoverCls}-arrow`]: {
|
||||
top: popoverArrowOffsetVertical,
|
||||
},
|
||||
|
||||
[`&-placement-leftBottom ${popoverCls}-arrow`]: {
|
||||
bottom: popoverArrowOffsetVertical,
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
// FIXME: special preset colors
|
||||
const genColorStyle: GenerateStyle<PopoverToken> = token => {
|
||||
const { popoverCls } = token;
|
||||
|
||||
return PresetColors.reduce((prev: CSSObject, colorKey: keyof PresetColorType) => {
|
||||
const lightColor = token[`${colorKey}-6`];
|
||||
return {
|
||||
...prev,
|
||||
[`${popoverCls}-${colorKey}`]: {
|
||||
[`${popoverCls}-inner`]: {
|
||||
backgroundColor: lightColor,
|
||||
},
|
||||
[`${popoverCls}-arrow`]: {
|
||||
'&-content': {
|
||||
backgroundColor: lightColor,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
}, {} as CSSObject);
|
||||
};
|
||||
|
||||
export const genPopoverStyle: GenerateStyle<PopoverToken> = (
|
||||
token: PopoverToken,
|
||||
): CSSInterpolation => [genBaseStyle(token), genPlacementStyle(token), genColorStyle(token)];
|
||||
|
||||
export default function useStyle(
|
||||
prefixCls: string,
|
||||
iconPrefixCls: string,
|
||||
): UseComponentStyleResult {
|
||||
const [theme, token, hashId] = useToken();
|
||||
|
||||
const popoverBg = token.colorBg;
|
||||
// FIXME
|
||||
const popoverArrowWidth = 8 * Math.sqrt(2);
|
||||
|
||||
const popoverToken = {
|
||||
...token,
|
||||
popoverCls: `.${prefixCls}`,
|
||||
iconPrefixCls,
|
||||
popoverBg,
|
||||
popoverColor: token.colorText,
|
||||
// FIXME
|
||||
popoverMinWidth: 177,
|
||||
popoverMinHeight: 32,
|
||||
popoverArrowWidth,
|
||||
popoverArrowColor: popoverBg,
|
||||
popoverArrowOuterColor: popoverBg,
|
||||
popoverDistance: popoverArrowWidth + 4,
|
||||
popoverPaddingHorizonta: token.padding,
|
||||
popoverArrowRotateWidth: Math.sqrt(popoverArrowWidth * popoverArrowWidth * 2),
|
||||
// FIXME
|
||||
popoverArrowOffsetVertical: 12,
|
||||
popoverArrowOffsetHorizontal: 16,
|
||||
};
|
||||
|
||||
return [
|
||||
useStyleRegister({ theme, token, hashId, path: [prefixCls] }, () => [
|
||||
genPopoverStyle(popoverToken),
|
||||
]),
|
||||
hashId,
|
||||
];
|
||||
}
|
||||
|
@ -123,7 +123,7 @@ const genSingleStyle: GenerateStyle<SelectToken> = (token, hashId) => {
|
||||
|
||||
[`&-selected:not(${selectItemCls}-option-disabled)`]: {
|
||||
color: token.colorText,
|
||||
fontWeight: 600, // FIXME: Need design token?
|
||||
fontWeight: token.fontWeightStrong,
|
||||
backgroundColor: token.controlItemBgActive,
|
||||
|
||||
[`${selectItemCls}-option-state`]: {
|
||||
|
@ -96,7 +96,6 @@ const genStatusStyle = (
|
||||
|
||||
[`${selectCls}-focused& ${selectCls}-selector`]: {
|
||||
borderColor: borderHoverColor,
|
||||
// FIXME: missing variable of `@input-outline-offset`
|
||||
boxShadow: `0 0 0 ${token.controlOutlineWidth}px ${outlineColor}`,
|
||||
borderInlineEndWidth: `${token.controlLineWidth}px !important`,
|
||||
outline: 0,
|
||||
@ -241,8 +240,10 @@ const genBaseStyle: GenerateStyle<SelectToken> = token => {
|
||||
'&:hover': {
|
||||
color: token.colorTextSecondary,
|
||||
},
|
||||
},
|
||||
|
||||
[`${selectCls}:hover &`]: {
|
||||
'&:hover': {
|
||||
[`${selectCls}-clear`]: {
|
||||
opacity: 1,
|
||||
},
|
||||
},
|
||||
@ -251,7 +252,7 @@ const genBaseStyle: GenerateStyle<SelectToken> = token => {
|
||||
// ========================= Feedback ==========================
|
||||
[`${selectCls}-has-feedback`]: {
|
||||
[`${selectCls}-clear`]: {
|
||||
insetInlineEnd: token.padding * 2,
|
||||
insetInlineEnd: inputPaddingHorizontalBase + token.fontSize + token.paddingXXS,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
@ -148,7 +148,6 @@ function genSizeStyle(token: SelectToken, suffix?: string): CSSObject {
|
||||
display: 'inline-flex',
|
||||
position: 'relative',
|
||||
maxWidth: '100%',
|
||||
// FIXME: no sure this style
|
||||
marginInlineStart: token.inputPaddingHorizontalBase - selectItemDist,
|
||||
|
||||
[`
|
||||
|
@ -1,7 +1,7 @@
|
||||
import * as React from 'react';
|
||||
import omit from 'rc-util/lib/omit';
|
||||
import classNames from 'classnames';
|
||||
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
|
||||
import { ConfigContext } from '../config-provider';
|
||||
import Element, { SkeletonElementProps } from './Element';
|
||||
|
||||
export interface AvatarProps extends Omit<SkeletonElementProps, 'shape'> {
|
||||
@ -9,25 +9,24 @@ export interface AvatarProps extends Omit<SkeletonElementProps, 'shape'> {
|
||||
}
|
||||
|
||||
const SkeletonAvatar = (props: AvatarProps) => {
|
||||
const renderSkeletonAvatar = ({ getPrefixCls }: ConfigConsumerProps) => {
|
||||
const { prefixCls: customizePrefixCls, className, active } = props;
|
||||
const prefixCls = getPrefixCls('skeleton', customizePrefixCls);
|
||||
const otherProps = omit(props, ['prefixCls', 'className']);
|
||||
const cls = classNames(
|
||||
prefixCls,
|
||||
`${prefixCls}-element`,
|
||||
{
|
||||
[`${prefixCls}-active`]: active,
|
||||
},
|
||||
className,
|
||||
);
|
||||
return (
|
||||
<div className={cls}>
|
||||
<Element prefixCls={`${prefixCls}-avatar`} {...otherProps} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
return <ConfigConsumer>{renderSkeletonAvatar}</ConfigConsumer>;
|
||||
const { prefixCls: customizePrefixCls, className, active } = props;
|
||||
const { getPrefixCls } = React.useContext(ConfigContext);
|
||||
const prefixCls = getPrefixCls('skeleton', customizePrefixCls);
|
||||
|
||||
const otherProps = omit(props, ['prefixCls', 'className']);
|
||||
const cls = classNames(
|
||||
prefixCls,
|
||||
`${prefixCls}-element`,
|
||||
{
|
||||
[`${prefixCls}-active`]: active,
|
||||
},
|
||||
className,
|
||||
);
|
||||
return (
|
||||
<div className={cls}>
|
||||
<Element prefixCls={`${prefixCls}-avatar`} {...otherProps} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
SkeletonAvatar.defaultProps = {
|
||||
|
@ -2,7 +2,7 @@ import * as React from 'react';
|
||||
import omit from 'rc-util/lib/omit';
|
||||
import classNames from 'classnames';
|
||||
import Element, { SkeletonElementProps } from './Element';
|
||||
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
|
||||
import { ConfigContext } from '../config-provider';
|
||||
|
||||
export interface SkeletonButtonProps extends Omit<SkeletonElementProps, 'size'> {
|
||||
size?: 'large' | 'small' | 'default';
|
||||
@ -10,26 +10,25 @@ export interface SkeletonButtonProps extends Omit<SkeletonElementProps, 'size'>
|
||||
}
|
||||
|
||||
const SkeletonButton = (props: SkeletonButtonProps) => {
|
||||
const renderSkeletonButton = ({ getPrefixCls }: ConfigConsumerProps) => {
|
||||
const { prefixCls: customizePrefixCls, className, active, block = false } = props;
|
||||
const prefixCls = getPrefixCls('skeleton', customizePrefixCls);
|
||||
const otherProps = omit(props, ['prefixCls']);
|
||||
const cls = classNames(
|
||||
prefixCls,
|
||||
`${prefixCls}-element`,
|
||||
{
|
||||
[`${prefixCls}-active`]: active,
|
||||
[`${prefixCls}-block`]: block,
|
||||
},
|
||||
className,
|
||||
);
|
||||
return (
|
||||
<div className={cls}>
|
||||
<Element prefixCls={`${prefixCls}-button`} {...otherProps} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
return <ConfigConsumer>{renderSkeletonButton}</ConfigConsumer>;
|
||||
const { prefixCls: customizePrefixCls, className, active, block = false } = props;
|
||||
const { getPrefixCls } = React.useContext(ConfigContext);
|
||||
const prefixCls = getPrefixCls('skeleton', customizePrefixCls);
|
||||
|
||||
const otherProps = omit(props, ['prefixCls']);
|
||||
const cls = classNames(
|
||||
prefixCls,
|
||||
`${prefixCls}-element`,
|
||||
{
|
||||
[`${prefixCls}-active`]: active,
|
||||
[`${prefixCls}-block`]: block,
|
||||
},
|
||||
className,
|
||||
);
|
||||
return (
|
||||
<div className={cls}>
|
||||
<Element prefixCls={`${prefixCls}-button`} {...otherProps} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
SkeletonButton.defaultProps = {
|
||||
|
@ -1,7 +1,7 @@
|
||||
import * as React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import { SkeletonElementProps } from './Element';
|
||||
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
|
||||
import { ConfigContext } from '../config-provider';
|
||||
|
||||
export interface SkeletonImageProps
|
||||
extends Omit<SkeletonElementProps, 'size' | 'shape' | 'active'> {}
|
||||
@ -10,26 +10,24 @@ const path =
|
||||
'M365.714286 329.142857q0 45.714286-32.036571 77.677714t-77.677714 32.036571-77.677714-32.036571-32.036571-77.677714 32.036571-77.677714 77.677714-32.036571 77.677714 32.036571 32.036571 77.677714zM950.857143 548.571429l0 256-804.571429 0 0-109.714286 182.857143-182.857143 91.428571 91.428571 292.571429-292.571429zM1005.714286 146.285714l-914.285714 0q-7.460571 0-12.873143 5.412571t-5.412571 12.873143l0 694.857143q0 7.460571 5.412571 12.873143t12.873143 5.412571l914.285714 0q7.460571 0 12.873143-5.412571t5.412571-12.873143l0-694.857143q0-7.460571-5.412571-12.873143t-12.873143-5.412571zM1097.142857 164.571429l0 694.857143q0 37.741714-26.843429 64.585143t-64.585143 26.843429l-914.285714 0q-37.741714 0-64.585143-26.843429t-26.843429-64.585143l0-694.857143q0-37.741714 26.843429-64.585143t64.585143-26.843429l914.285714 0q37.741714 0 64.585143 26.843429t26.843429 64.585143z';
|
||||
|
||||
const SkeletonImage = (props: SkeletonImageProps) => {
|
||||
const renderSkeletonImage = ({ getPrefixCls }: ConfigConsumerProps) => {
|
||||
const { prefixCls: customizePrefixCls, className, style } = props;
|
||||
const prefixCls = getPrefixCls('skeleton', customizePrefixCls);
|
||||
const cls = classNames(prefixCls, `${prefixCls}-element`, className);
|
||||
const { prefixCls: customizePrefixCls, className, style } = props;
|
||||
const { getPrefixCls } = React.useContext(ConfigContext);
|
||||
const prefixCls = getPrefixCls('skeleton', customizePrefixCls);
|
||||
const cls = classNames(prefixCls, `${prefixCls}-element`, className);
|
||||
|
||||
return (
|
||||
<div className={cls}>
|
||||
<div className={classNames(`${prefixCls}-image`, className)} style={style}>
|
||||
<svg
|
||||
viewBox="0 0 1098 1024"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className={`${prefixCls}-image-svg`}
|
||||
>
|
||||
<path d={path} className={`${prefixCls}-image-path`} />
|
||||
</svg>
|
||||
</div>
|
||||
return (
|
||||
<div className={cls}>
|
||||
<div className={classNames(`${prefixCls}-image`, className)} style={style}>
|
||||
<svg
|
||||
viewBox="0 0 1098 1024"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className={`${prefixCls}-image-svg`}
|
||||
>
|
||||
<path d={path} className={`${prefixCls}-image-path`} />
|
||||
</svg>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
return <ConfigConsumer>{renderSkeletonImage}</ConfigConsumer>;
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SkeletonImage;
|
||||
|
@ -2,7 +2,7 @@ import * as React from 'react';
|
||||
import omit from 'rc-util/lib/omit';
|
||||
import classNames from 'classnames';
|
||||
import Element, { SkeletonElementProps } from './Element';
|
||||
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
|
||||
import { ConfigContext } from '../config-provider';
|
||||
|
||||
export interface SkeletonInputProps extends Omit<SkeletonElementProps, 'size' | 'shape'> {
|
||||
size?: 'large' | 'small' | 'default';
|
||||
@ -10,26 +10,25 @@ export interface SkeletonInputProps extends Omit<SkeletonElementProps, 'size' |
|
||||
}
|
||||
|
||||
const SkeletonInput = (props: SkeletonInputProps) => {
|
||||
const renderSkeletonInput = ({ getPrefixCls }: ConfigConsumerProps) => {
|
||||
const { prefixCls: customizePrefixCls, className, active, block } = props;
|
||||
const prefixCls = getPrefixCls('skeleton', customizePrefixCls);
|
||||
const otherProps = omit(props, ['prefixCls']);
|
||||
const cls = classNames(
|
||||
prefixCls,
|
||||
`${prefixCls}-element`,
|
||||
{
|
||||
[`${prefixCls}-active`]: active,
|
||||
[`${prefixCls}-block`]: block,
|
||||
},
|
||||
className,
|
||||
);
|
||||
return (
|
||||
<div className={cls}>
|
||||
<Element prefixCls={`${prefixCls}-input`} {...otherProps} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
return <ConfigConsumer>{renderSkeletonInput}</ConfigConsumer>;
|
||||
const { prefixCls: customizePrefixCls, className, active, block } = props;
|
||||
const { getPrefixCls } = React.useContext(ConfigContext);
|
||||
const prefixCls = getPrefixCls('skeleton', customizePrefixCls);
|
||||
|
||||
const otherProps = omit(props, ['prefixCls']);
|
||||
const cls = classNames(
|
||||
prefixCls,
|
||||
`${prefixCls}-element`,
|
||||
{
|
||||
[`${prefixCls}-active`]: active,
|
||||
[`${prefixCls}-block`]: block,
|
||||
},
|
||||
className,
|
||||
);
|
||||
return (
|
||||
<div className={cls}>
|
||||
<Element prefixCls={`${prefixCls}-input`} {...otherProps} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
SkeletonInput.defaultProps = {
|
||||
|
@ -2,7 +2,7 @@ import * as React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import Title, { SkeletonTitleProps } from './Title';
|
||||
import Paragraph, { SkeletonParagraphProps } from './Paragraph';
|
||||
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
|
||||
import { ConfigContext } from '../config-provider';
|
||||
import Element from './Element';
|
||||
import SkeletonAvatar, { AvatarProps } from './Avatar';
|
||||
import SkeletonButton from './Button';
|
||||
@ -72,99 +72,96 @@ function getParagraphBasicProps(hasAvatar: boolean, hasTitle: boolean): Skeleton
|
||||
}
|
||||
|
||||
const Skeleton = (props: SkeletonProps) => {
|
||||
const renderSkeleton = ({ getPrefixCls, direction }: ConfigConsumerProps) => {
|
||||
const {
|
||||
prefixCls: customizePrefixCls,
|
||||
loading,
|
||||
className,
|
||||
style,
|
||||
children,
|
||||
avatar,
|
||||
title,
|
||||
paragraph,
|
||||
active,
|
||||
round,
|
||||
} = props;
|
||||
const {
|
||||
prefixCls: customizePrefixCls,
|
||||
loading,
|
||||
className,
|
||||
style,
|
||||
children,
|
||||
avatar,
|
||||
title,
|
||||
paragraph,
|
||||
active,
|
||||
round,
|
||||
} = props;
|
||||
|
||||
const prefixCls = getPrefixCls('skeleton', customizePrefixCls);
|
||||
const { getPrefixCls, direction } = React.useContext(ConfigContext);
|
||||
const prefixCls = getPrefixCls('skeleton', customizePrefixCls);
|
||||
|
||||
if (loading || !('loading' in props)) {
|
||||
const hasAvatar = !!avatar;
|
||||
const hasTitle = !!title;
|
||||
const hasParagraph = !!paragraph;
|
||||
if (loading || !('loading' in props)) {
|
||||
const hasAvatar = !!avatar;
|
||||
const hasTitle = !!title;
|
||||
const hasParagraph = !!paragraph;
|
||||
|
||||
// Avatar
|
||||
let avatarNode;
|
||||
if (hasAvatar) {
|
||||
const avatarProps: SkeletonAvatarProps = {
|
||||
prefixCls: `${prefixCls}-avatar`,
|
||||
...getAvatarBasicProps(hasTitle, hasParagraph),
|
||||
...getComponentProps(avatar),
|
||||
};
|
||||
// We direct use SkeletonElement as avatar in skeleton internal.
|
||||
avatarNode = (
|
||||
<div className={`${prefixCls}-header`}>
|
||||
<Element {...avatarProps} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
let contentNode;
|
||||
if (hasTitle || hasParagraph) {
|
||||
// Title
|
||||
let $title;
|
||||
if (hasTitle) {
|
||||
const titleProps: SkeletonTitleProps = {
|
||||
prefixCls: `${prefixCls}-title`,
|
||||
...getTitleBasicProps(hasAvatar, hasParagraph),
|
||||
...getComponentProps(title),
|
||||
};
|
||||
|
||||
$title = <Title {...titleProps} />;
|
||||
}
|
||||
|
||||
// Paragraph
|
||||
let paragraphNode;
|
||||
if (hasParagraph) {
|
||||
const paragraphProps: SkeletonParagraphProps = {
|
||||
prefixCls: `${prefixCls}-paragraph`,
|
||||
...getParagraphBasicProps(hasAvatar, hasTitle),
|
||||
...getComponentProps(paragraph),
|
||||
};
|
||||
|
||||
paragraphNode = <Paragraph {...paragraphProps} />;
|
||||
}
|
||||
|
||||
contentNode = (
|
||||
<div className={`${prefixCls}-content`}>
|
||||
{$title}
|
||||
{paragraphNode}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const cls = classNames(
|
||||
prefixCls,
|
||||
{
|
||||
[`${prefixCls}-with-avatar`]: hasAvatar,
|
||||
[`${prefixCls}-active`]: active,
|
||||
[`${prefixCls}-rtl`]: direction === 'rtl',
|
||||
[`${prefixCls}-round`]: round,
|
||||
},
|
||||
className,
|
||||
);
|
||||
|
||||
return (
|
||||
<div className={cls} style={style}>
|
||||
{avatarNode}
|
||||
{contentNode}
|
||||
// Avatar
|
||||
let avatarNode;
|
||||
if (hasAvatar) {
|
||||
const avatarProps: SkeletonAvatarProps = {
|
||||
prefixCls: `${prefixCls}-avatar`,
|
||||
...getAvatarBasicProps(hasTitle, hasParagraph),
|
||||
...getComponentProps(avatar),
|
||||
};
|
||||
// We direct use SkeletonElement as avatar in skeleton internal.
|
||||
avatarNode = (
|
||||
<div className={`${prefixCls}-header`}>
|
||||
<Element {...avatarProps} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return children;
|
||||
};
|
||||
return <ConfigConsumer>{renderSkeleton}</ConfigConsumer>;
|
||||
let contentNode;
|
||||
if (hasTitle || hasParagraph) {
|
||||
// Title
|
||||
let $title;
|
||||
if (hasTitle) {
|
||||
const titleProps: SkeletonTitleProps = {
|
||||
prefixCls: `${prefixCls}-title`,
|
||||
...getTitleBasicProps(hasAvatar, hasParagraph),
|
||||
...getComponentProps(title),
|
||||
};
|
||||
|
||||
$title = <Title {...titleProps} />;
|
||||
}
|
||||
|
||||
// Paragraph
|
||||
let paragraphNode;
|
||||
if (hasParagraph) {
|
||||
const paragraphProps: SkeletonParagraphProps = {
|
||||
prefixCls: `${prefixCls}-paragraph`,
|
||||
...getParagraphBasicProps(hasAvatar, hasTitle),
|
||||
...getComponentProps(paragraph),
|
||||
};
|
||||
|
||||
paragraphNode = <Paragraph {...paragraphProps} />;
|
||||
}
|
||||
|
||||
contentNode = (
|
||||
<div className={`${prefixCls}-content`}>
|
||||
{$title}
|
||||
{paragraphNode}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const cls = classNames(
|
||||
prefixCls,
|
||||
{
|
||||
[`${prefixCls}-with-avatar`]: hasAvatar,
|
||||
[`${prefixCls}-active`]: active,
|
||||
[`${prefixCls}-rtl`]: direction === 'rtl',
|
||||
[`${prefixCls}-round`]: round,
|
||||
},
|
||||
className,
|
||||
);
|
||||
|
||||
return (
|
||||
<div className={cls} style={style}>
|
||||
{avatarNode}
|
||||
{contentNode}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return React.isValidElement(children) ? children : null;
|
||||
};
|
||||
|
||||
Skeleton.defaultProps = {
|
||||
|
@ -1,18 +1,11 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Spin if indicator set null should not be render default indicator 1`] = `
|
||||
<Spin
|
||||
indicator={null}
|
||||
size="default"
|
||||
spinning={true}
|
||||
wrapperClassName=""
|
||||
>
|
||||
<div
|
||||
aria-busy={true}
|
||||
aria-live="polite"
|
||||
className="ant-spin ant-spin-spinning"
|
||||
/>
|
||||
</Spin>
|
||||
<div
|
||||
aria-busy="true"
|
||||
aria-live="polite"
|
||||
class="ant-spin ant-spin-spinning"
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`Spin rtl render component should be rendered correctly in RTL direction 1`] = `
|
||||
@ -53,19 +46,13 @@ exports[`Spin should render custom indicator when it's set 1`] = `
|
||||
`;
|
||||
|
||||
exports[`Spin should support static method Spin.setDefaultIndicator 1`] = `
|
||||
<Spin
|
||||
size="default"
|
||||
spinning={true}
|
||||
wrapperClassName=""
|
||||
<div
|
||||
aria-busy="true"
|
||||
aria-live="polite"
|
||||
class="ant-spin ant-spin-spinning"
|
||||
>
|
||||
<div
|
||||
aria-busy={true}
|
||||
aria-live="polite"
|
||||
className="ant-spin ant-spin-spinning"
|
||||
>
|
||||
<em
|
||||
className="custom-spinner ant-spin-dot"
|
||||
/>
|
||||
</div>
|
||||
</Spin>
|
||||
<em
|
||||
class="custom-spinner ant-spin-dot"
|
||||
/>
|
||||
</div>
|
||||
`;
|
||||
|
@ -1,6 +1,7 @@
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import Spin from '..';
|
||||
// eslint-disable-next-line import/no-named-as-default
|
||||
import Spin, { Spin as SpinClass } from '..';
|
||||
import { sleep } from '../../../tests/utils';
|
||||
|
||||
describe('delay spinning', () => {
|
||||
@ -24,8 +25,8 @@ describe('delay spinning', () => {
|
||||
|
||||
it('should cancel debounce function when unmount', async () => {
|
||||
const wrapper = mount(<Spin spinning delay={100} />);
|
||||
const spy = jest.spyOn(wrapper.instance().updateSpinning, 'cancel');
|
||||
expect(wrapper.instance().updateSpinning.cancel).toEqual(expect.any(Function));
|
||||
const spy = jest.spyOn(wrapper.find(SpinClass).instance().updateSpinning, 'cancel');
|
||||
expect(wrapper.find(SpinClass).instance().updateSpinning.cancel).toEqual(expect.any(Function));
|
||||
expect(spy).not.toHaveBeenCalled();
|
||||
wrapper.unmount();
|
||||
expect(spy).toHaveBeenCalled();
|
||||
|
@ -1,6 +1,7 @@
|
||||
import React from 'react';
|
||||
import { render, mount } from 'enzyme';
|
||||
import Spin from '..';
|
||||
// eslint-disable-next-line import/no-named-as-default
|
||||
import Spin, { Spin as SpinClass } from '..';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
import rtlTest from '../../../tests/shared/rtlTest';
|
||||
|
||||
@ -26,20 +27,20 @@ describe('Spin', () => {
|
||||
|
||||
it('should be controlled by spinning', () => {
|
||||
const wrapper = mount(<Spin spinning={false} />);
|
||||
expect(wrapper.instance().state.spinning).toBe(false);
|
||||
expect(wrapper.find(SpinClass).instance().state.spinning).toBe(false);
|
||||
wrapper.setProps({ spinning: true });
|
||||
expect(wrapper.instance().state.spinning).toBe(true);
|
||||
expect(wrapper.find(SpinClass).instance().state.spinning).toBe(true);
|
||||
});
|
||||
|
||||
it('if indicator set null should not be render default indicator', () => {
|
||||
const wrapper = mount(<Spin indicator={null} />);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should support static method Spin.setDefaultIndicator', () => {
|
||||
Spin.setDefaultIndicator(<em className="custom-spinner" />);
|
||||
const wrapper = mount(<Spin />);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
Spin.setDefaultIndicator(null);
|
||||
});
|
||||
|
||||
|
@ -2,9 +2,10 @@ import * as React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import omit from 'rc-util/lib/omit';
|
||||
import debounce from 'lodash/debounce';
|
||||
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
|
||||
import { ConfigConsumer, ConfigConsumerProps, ConfigContext } from '../config-provider';
|
||||
import { tuple } from '../_util/type';
|
||||
import { isValidElement, cloneElement } from '../_util/reactNode';
|
||||
import useStyle from './style/index';
|
||||
|
||||
const SpinSizes = tuple('small', 'default', 'large');
|
||||
export type SpinSize = typeof SpinSizes[number];
|
||||
@ -22,6 +23,15 @@ export interface SpinProps {
|
||||
indicator?: SpinIndicator;
|
||||
}
|
||||
|
||||
export interface SpinClassProps extends SpinProps {
|
||||
hashId: string;
|
||||
spinPrefixCls: string;
|
||||
}
|
||||
|
||||
export type SpinFCType = React.FC<SpinProps> & {
|
||||
setDefaultIndicator: (indicator: React.ReactNode) => void;
|
||||
};
|
||||
|
||||
export interface SpinState {
|
||||
spinning?: boolean;
|
||||
notCssAnimationSupported?: boolean;
|
||||
@ -30,7 +40,7 @@ export interface SpinState {
|
||||
// Render indicator
|
||||
let defaultIndicator: React.ReactNode = null;
|
||||
|
||||
function renderIndicator(prefixCls: string, props: SpinProps): React.ReactNode {
|
||||
function renderIndicator(prefixCls: string, props: SpinClassProps): React.ReactNode {
|
||||
const { indicator } = props;
|
||||
const dotClassName = `${prefixCls}-dot`;
|
||||
|
||||
@ -65,20 +75,16 @@ function shouldDelay(spinning?: boolean, delay?: number): boolean {
|
||||
return !!spinning && !!delay && !isNaN(Number(delay));
|
||||
}
|
||||
|
||||
class Spin extends React.Component<SpinProps, SpinState> {
|
||||
export class Spin extends React.Component<SpinClassProps, SpinState> {
|
||||
static defaultProps = {
|
||||
spinning: true,
|
||||
size: 'default' as SpinSize,
|
||||
wrapperClassName: '',
|
||||
};
|
||||
|
||||
static setDefaultIndicator(indicator: React.ReactNode) {
|
||||
defaultIndicator = indicator;
|
||||
}
|
||||
|
||||
originalUpdateSpinning: () => void;
|
||||
|
||||
constructor(props: SpinProps) {
|
||||
constructor(props: SpinClassProps) {
|
||||
super(props);
|
||||
|
||||
const { spinning, delay } = props;
|
||||
@ -103,7 +109,7 @@ class Spin extends React.Component<SpinProps, SpinState> {
|
||||
this.cancelExistingSpin();
|
||||
}
|
||||
|
||||
debouncifyUpdateSpinning = (props?: SpinProps) => {
|
||||
debouncifyUpdateSpinning = (props?: SpinClassProps) => {
|
||||
const { delay } = props || this.props;
|
||||
if (delay) {
|
||||
this.cancelExistingSpin();
|
||||
@ -130,9 +136,10 @@ class Spin extends React.Component<SpinProps, SpinState> {
|
||||
return !!(this.props && typeof this.props.children !== 'undefined');
|
||||
}
|
||||
|
||||
renderSpin = ({ getPrefixCls, direction }: ConfigConsumerProps) => {
|
||||
renderSpin = ({ direction }: ConfigConsumerProps) => {
|
||||
const {
|
||||
prefixCls: customizePrefixCls,
|
||||
spinPrefixCls: prefixCls,
|
||||
hashId,
|
||||
className,
|
||||
size,
|
||||
tip,
|
||||
@ -142,7 +149,6 @@ class Spin extends React.Component<SpinProps, SpinState> {
|
||||
} = this.props;
|
||||
const { spinning } = this.state;
|
||||
|
||||
const prefixCls = getPrefixCls('spin', customizePrefixCls);
|
||||
const spinClassName = classNames(
|
||||
prefixCls,
|
||||
{
|
||||
@ -153,10 +159,11 @@ class Spin extends React.Component<SpinProps, SpinState> {
|
||||
[`${prefixCls}-rtl`]: direction === 'rtl',
|
||||
},
|
||||
className,
|
||||
hashId,
|
||||
);
|
||||
|
||||
// fix https://fb.me/react-unknown-prop
|
||||
const divProps = omit(restProps, ['spinning', 'delay', 'indicator']);
|
||||
const divProps = omit(restProps, ['spinning', 'delay', 'indicator', 'prefixCls']);
|
||||
|
||||
const spinElement = (
|
||||
<div
|
||||
@ -175,7 +182,10 @@ class Spin extends React.Component<SpinProps, SpinState> {
|
||||
[`${prefixCls}-blur`]: spinning,
|
||||
});
|
||||
return (
|
||||
<div {...divProps} className={classNames(`${prefixCls}-nested-loading`, wrapperClassName)}>
|
||||
<div
|
||||
{...divProps}
|
||||
className={classNames(`${prefixCls}-nested-loading`, wrapperClassName, hashId)}
|
||||
>
|
||||
{spinning && <div key="loading">{spinElement}</div>}
|
||||
<div className={containerClassName} key="container">
|
||||
{this.props.children}
|
||||
@ -191,4 +201,28 @@ class Spin extends React.Component<SpinProps, SpinState> {
|
||||
}
|
||||
}
|
||||
|
||||
export default Spin;
|
||||
const SpinFC: SpinFCType = (props: SpinProps) => {
|
||||
const { prefixCls: customizePrefixCls } = props;
|
||||
const { getPrefixCls } = React.useContext(ConfigContext);
|
||||
|
||||
const spinPrefixCls = getPrefixCls('spin', customizePrefixCls);
|
||||
|
||||
const [wrapSSR, hashId] = useStyle(spinPrefixCls);
|
||||
|
||||
const spinClassProps: SpinClassProps = {
|
||||
...props,
|
||||
spinPrefixCls,
|
||||
hashId,
|
||||
};
|
||||
return wrapSSR(<Spin {...spinClassProps} />);
|
||||
};
|
||||
|
||||
SpinFC.setDefaultIndicator = (indicator: React.ReactNode) => {
|
||||
defaultIndicator = indicator;
|
||||
};
|
||||
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
SpinFC.displayName = 'Spin';
|
||||
}
|
||||
|
||||
export default SpinFC;
|
||||
|
@ -1,2 +1,244 @@
|
||||
import '../../style/index.less';
|
||||
import './index.less';
|
||||
// deps-lint-skip-all
|
||||
import { CSSObject, Keyframes } from '@ant-design/cssinjs';
|
||||
import {
|
||||
useStyleRegister,
|
||||
useToken,
|
||||
resetComponent,
|
||||
GenerateStyle,
|
||||
UseComponentStyleResult,
|
||||
} from '../../_util/theme';
|
||||
import type { DerivativeToken } from '../../_util/theme';
|
||||
|
||||
interface SpinToken extends DerivativeToken {
|
||||
spinCls: string;
|
||||
spinDotDefault: string;
|
||||
spinDotSize: number;
|
||||
spinDotSizeSM: number;
|
||||
spinDotSizeLG: number;
|
||||
}
|
||||
|
||||
const antSpinMove = new Keyframes('antSpinMove', {
|
||||
to: { opacity: 1 },
|
||||
});
|
||||
|
||||
const antRotate = new Keyframes('antRotate', {
|
||||
to: { transform: 'rotate(405deg)' },
|
||||
});
|
||||
|
||||
const genSpinStyle: GenerateStyle<SpinToken> = (token: SpinToken, hashId: string): CSSObject => ({
|
||||
[`${token.spinCls}`]: {
|
||||
...resetComponent(token),
|
||||
position: 'absolute',
|
||||
display: 'none',
|
||||
color: token.colorPrimary,
|
||||
textAlign: 'center',
|
||||
verticalAlign: 'middle',
|
||||
opacity: 0,
|
||||
transition: `transform ${token.motionDurationSlow} ${token.motionEaseInOutCirc}`,
|
||||
|
||||
'&-spinning': {
|
||||
position: 'static',
|
||||
display: 'inline-block',
|
||||
opacity: 1,
|
||||
},
|
||||
|
||||
'&-nested-loading': {
|
||||
position: 'relative',
|
||||
[`> div > ${token.spinCls}`]: {
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
insetInlineStart: 0,
|
||||
zIndex: 4,
|
||||
display: 'block',
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
maxHeight: 400, // FIXME: hard code in v4
|
||||
|
||||
[`${token.spinCls}-dot`]: {
|
||||
position: 'absolute',
|
||||
top: '50%',
|
||||
insetInlineStart: '50%',
|
||||
margin: -token.spinDotSize / 2,
|
||||
},
|
||||
|
||||
[`${token.spinCls}-text`]: {
|
||||
position: 'absolute',
|
||||
top: '50%',
|
||||
width: '100%',
|
||||
paddingTop: (token.spinDotSize - token.fontSize) / 2 + 2,
|
||||
textShadow: `0 1px 2px ${token.colorBgComponent}`,
|
||||
},
|
||||
|
||||
[`&${token.spinCls}-show-text ${token.spinCls}-dot`]: {
|
||||
marginTop: -(token.spinDotSize / 2) - 10,
|
||||
},
|
||||
|
||||
[`> div > ${token.spinCls}-sm`]: {
|
||||
[`${token.spinCls}-dot`]: {
|
||||
margin: -token.spinDotSizeSM / 2,
|
||||
},
|
||||
[`${token.spinCls}-text`]: {
|
||||
paddingTop: (token.spinDotSizeSM - token.fontSize) / 2 + 2,
|
||||
},
|
||||
[`&${token.spinCls}-show-text ${token.spinCls}-dot`]: {
|
||||
marginTop: -(token.spinDotSizeSM / 2) - 10,
|
||||
},
|
||||
},
|
||||
|
||||
[`> div > ${token.spinCls}-lg`]: {
|
||||
[`${token.spinCls}-dot`]: {
|
||||
margin: -(token.spinDotSizeLG / 2),
|
||||
},
|
||||
[`${token.spinCls}-text`]: {
|
||||
paddingTop: (token.spinDotSizeLG - token.fontSize) / 2 + 2,
|
||||
},
|
||||
[`&${token.spinCls}-show-text ${token.spinCls}-dot`]: {
|
||||
marginTop: -(token.spinDotSizeLG / 2) - 10,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
[`${token.spinCls}-container`]: {
|
||||
position: 'relative',
|
||||
transition: `opacity ${token.motionDurationSlow}`,
|
||||
|
||||
'&::after': {
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
insetInlineEnd: 0,
|
||||
bottom: 0,
|
||||
insetInlineStart: 0,
|
||||
zIndex: 10,
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
background: token.colorBgComponent,
|
||||
opacity: 0,
|
||||
transition: `all ${token.motionDurationSlow}`,
|
||||
content: '""',
|
||||
pointerEvents: 'none',
|
||||
},
|
||||
},
|
||||
|
||||
[`${token.spinCls}-blur`]: {
|
||||
clear: 'both',
|
||||
opacity: 0.5,
|
||||
userSelect: 'none',
|
||||
pointerEvents: 'none',
|
||||
|
||||
[`&::after`]: {
|
||||
opacity: 0.4,
|
||||
pointerEvents: 'auto',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// tip
|
||||
// ------------------------------
|
||||
[`&-tip`]: {
|
||||
color: token.spinDotDefault,
|
||||
},
|
||||
|
||||
// dots
|
||||
// ------------------------------
|
||||
[`${token.spinCls}-dot`]: {
|
||||
position: 'relative',
|
||||
display: 'inline-block',
|
||||
fontSize: token.spinDotSize,
|
||||
width: '1em',
|
||||
height: '1em',
|
||||
|
||||
'&-item': {
|
||||
position: 'absolute',
|
||||
display: 'block',
|
||||
width: 9, // FIXME: hard code in v4
|
||||
height: 9, // FIXME: hard code in v4
|
||||
backgroundColor: token.colorPrimary,
|
||||
borderRadius: '100%',
|
||||
transform: 'scale(0.75)',
|
||||
transformOrigin: '50% 50%',
|
||||
opacity: 0.3,
|
||||
animation: `${antSpinMove.getName(hashId)} 1s infinite linear alternate`,
|
||||
|
||||
'&:nth-child(1)': {
|
||||
top: 0,
|
||||
insetInlineStart: 0,
|
||||
},
|
||||
|
||||
'&:nth-child(2)': {
|
||||
top: 0,
|
||||
insetInlineEnd: 0,
|
||||
animationDelay: '0.4s',
|
||||
},
|
||||
|
||||
'&:nth-child(3)': {
|
||||
insetInlineEnd: 0,
|
||||
bottom: 0,
|
||||
animationDelay: '0.8s',
|
||||
},
|
||||
|
||||
'&:nth-child(4)': {
|
||||
bottom: 0,
|
||||
insetInlineStart: 0,
|
||||
animationDelay: '1.2s',
|
||||
},
|
||||
},
|
||||
|
||||
'&-spin': {
|
||||
transform: 'rotate(45deg)',
|
||||
animation: `${antRotate.getName(hashId)} 1.2s infinite linear`,
|
||||
},
|
||||
},
|
||||
|
||||
// Sizes
|
||||
// ------------------------------
|
||||
|
||||
// small
|
||||
[`&-sm ${token.spinCls}-dot`]: {
|
||||
fontSize: token.spinDotSizeSM,
|
||||
|
||||
i: {
|
||||
width: 6, // FIXME: hard code in v4
|
||||
height: 6, // FIXME: hard code in v4
|
||||
},
|
||||
},
|
||||
|
||||
// large
|
||||
[`&-lg ${token.spinCls}-dot`]: {
|
||||
fontSize: token.spinDotSizeLG,
|
||||
|
||||
i: {
|
||||
width: 14, // FIXME: hard code in v4
|
||||
height: 14, // FIXME: hard code in v4
|
||||
},
|
||||
},
|
||||
|
||||
[`&${token.spinCls}-show-text ${token.spinCls}-text`]: {
|
||||
display: 'block',
|
||||
},
|
||||
|
||||
// animation
|
||||
antSpinMove,
|
||||
antRotate,
|
||||
},
|
||||
});
|
||||
|
||||
// ============================== Export ==============================
|
||||
export default function useStyle(prefixCls: string): UseComponentStyleResult {
|
||||
const [theme, token, hashId] = useToken();
|
||||
|
||||
const spinToken: SpinToken = {
|
||||
...token,
|
||||
spinCls: `.${prefixCls}`,
|
||||
spinDotDefault: token.colorTextSecondary,
|
||||
spinDotSize: 20, // FIXME: hard code in v4
|
||||
spinDotSizeSM: 14, // FIXME: hard code in v4
|
||||
spinDotSizeLG: 32, // FIXME: hard code in v4
|
||||
};
|
||||
|
||||
return [
|
||||
useStyleRegister({ theme, token, hashId, path: [prefixCls] }, () => [
|
||||
genSpinStyle(spinToken, hashId),
|
||||
]),
|
||||
hashId,
|
||||
];
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import omit from 'rc-util/lib/omit';
|
||||
import RcTable, { Summary } from 'rc-table';
|
||||
import { TableProps as RcTableProps, INTERNAL_HOOKS } from 'rc-table/lib/Table';
|
||||
import { convertChildrenToColumns } from 'rc-table/lib/hooks/useColumns';
|
||||
// eslint-disable-next-line import/no-named-as-default
|
||||
import Spin, { SpinProps } from '../spin';
|
||||
import Pagination from '../pagination';
|
||||
import { TooltipProps } from '../tooltip';
|
||||
|
@ -28,12 +28,12 @@ Ant Design has 3 types of Tabs for different situations.
|
||||
| centered | Centers tabs | boolean | false | 4.4.0 |
|
||||
| defaultActiveKey | Initial active TabPane's key, if `activeKey` is not set | string | - | |
|
||||
| hideAdd | Hide plus icon or not. Only works while `type="editable-card"` | boolean | false | |
|
||||
| moreIcon | The custom icon of ellipsis | ReactNode | <EllipsisOutlined /> | 4.14.0 |
|
||||
| moreIcon | The custom icon of ellipsis | ReactNode | <EllipsisOutlined /> | 4.14.0 |
|
||||
| renderTabBar | Replace the TabBar | (props: DefaultTabBarProps, DefaultTabBar: React.ComponentClass) => React.ReactElement | - | |
|
||||
| size | Preset tab bar size | `large` \| `default` \| `small` | `default` | |
|
||||
| tabBarExtraContent | Extra content in tab bar | ReactNode \| {left?: ReactNode, right?: ReactNode} | - | object: 4.6.0 |
|
||||
| tabBarGutter | The gap between tabs | number | - | |
|
||||
| tabBarStyle | Tab bar style object | object | - | |
|
||||
| tabBarStyle | Tab bar style object | CSSProperties | - | |
|
||||
| tabPosition | Position of tabs | `top` \| `right` \| `bottom` \| `left` | `top` | |
|
||||
| destroyInactiveTabPane | Whether destroy inactive TabPane when change tab | boolean | false | |
|
||||
| type | Basic style of tabs | `line` \| `card` \| `editable-card` | `line` | |
|
||||
|
@ -36,7 +36,7 @@ Ant Design 依次提供了三级选项卡,分别用于不同的场景。
|
||||
| size | 大小,提供 `large` `default` 和 `small` 三种大小 | string | `default` | |
|
||||
| tabBarExtraContent | tab bar 上额外的元素 | ReactNode \| {left?: ReactNode, right?: ReactNode} | - | object: 4.6.0 |
|
||||
| tabBarGutter | tabs 之间的间隙 | number | - | |
|
||||
| tabBarStyle | tab bar 的样式对象 | object | - | |
|
||||
| tabBarStyle | tab bar 的样式对象 | CSSProperties | - | |
|
||||
| tabPosition | 页签位置,可选值有 `top` `right` `bottom` `left` | string | `top` | |
|
||||
| destroyInactiveTabPane | 被隐藏时是否销毁 DOM 结构 | boolean | false | |
|
||||
| type | 页签的基本样式,可选 `line`、`card` `editable-card` 类型 | string | `line` | |
|
||||
@ -47,9 +47,9 @@ Ant Design 依次提供了三级选项卡,分别用于不同的场景。
|
||||
|
||||
### Tabs.TabPane
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
| --- | --- | --- | --- |
|
||||
| closeIcon | 自定义关闭图标,`在 type="editable-card"`时有效 | ReactNode | - |
|
||||
| forceRender | 被隐藏时是否渲染 DOM 结构 | boolean | false |
|
||||
| key | 对应 activeKey | string | - |
|
||||
| tab | 选项卡头显示文字 | ReactNode | - |
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
| ----------- | ----------------------------------------------- | --------- | ------ |
|
||||
| closeIcon | 自定义关闭图标,`在 type="editable-card"`时有效 | ReactNode | - |
|
||||
| forceRender | 被隐藏时是否渲染 DOM 结构 | boolean | false |
|
||||
| key | 对应 activeKey | string | - |
|
||||
| tab | 选项卡头显示文字 | ReactNode | - |
|
||||
|
@ -26,7 +26,7 @@ const treeNodeFX = new Keyframes('ant-tree-node-fx-do-not-use', {
|
||||
const getSwitchStyle = (prefixCls: string, token: DerivativeToken): CSSObject => ({
|
||||
[`.${prefixCls}-switcher-icon`]: {
|
||||
display: 'inline-block',
|
||||
fontSize: 10, // FIXME: missing token
|
||||
fontSize: 10,
|
||||
verticalAlign: 'baseline',
|
||||
|
||||
svg: {
|
||||
|
@ -1,6 +1,6 @@
|
||||
// deps-lint-skip-all
|
||||
import { useStyleRegister, useToken } from '../../_util/theme';
|
||||
import type { UseComponentStyleResult, GenerateStyle } from '../../_util/theme';
|
||||
import type { UseComponentStyleResult, GenerateStyle, AliasToken } from '../../_util/theme';
|
||||
import { operationUnit } from '../../_util/theme/util/operationUnit';
|
||||
import {
|
||||
getTitleStyles,
|
||||
@ -10,12 +10,22 @@ import {
|
||||
getCopiableStyles,
|
||||
getEllipsisStyles,
|
||||
} from './mixins';
|
||||
import type { TypographyToken } from './mixins';
|
||||
|
||||
/** Component only token. Which will handle additional calculation of alias token */
|
||||
export interface ComponentToken {
|
||||
sizeMarginHeadingVerticalStart: number | string;
|
||||
sizeMarginHeadingVerticalEnd: number | string;
|
||||
}
|
||||
|
||||
export interface TypographyToken extends AliasToken, ComponentToken {
|
||||
typographyCls: string;
|
||||
}
|
||||
|
||||
const genTypographyStyle: GenerateStyle<TypographyToken> = token => {
|
||||
const { prefixCls, titleMarginTop } = token.typography;
|
||||
const { typographyCls, sizeMarginHeadingVerticalStart } = token;
|
||||
|
||||
return {
|
||||
[`.${prefixCls}`]: {
|
||||
[typographyCls]: {
|
||||
color: token.colorText,
|
||||
overflowWrap: 'break-word',
|
||||
'&&-secondary': {
|
||||
@ -59,7 +69,7 @@ const genTypographyStyle: GenerateStyle<TypographyToken> = token => {
|
||||
& + h4&,
|
||||
& + h5&
|
||||
`]: {
|
||||
marginTop: titleMarginTop,
|
||||
marginTop: sizeMarginHeadingVerticalStart,
|
||||
},
|
||||
|
||||
[`
|
||||
@ -79,7 +89,7 @@ const genTypographyStyle: GenerateStyle<TypographyToken> = token => {
|
||||
+ h4,
|
||||
+ h5
|
||||
`]: {
|
||||
marginTop: titleMarginTop,
|
||||
marginTop: sizeMarginHeadingVerticalStart,
|
||||
},
|
||||
},
|
||||
|
||||
@ -89,9 +99,9 @@ const genTypographyStyle: GenerateStyle<TypographyToken> = token => {
|
||||
|
||||
// Operation
|
||||
[`
|
||||
.${prefixCls}-expand,
|
||||
.${prefixCls}-edit,
|
||||
.${prefixCls}-copy
|
||||
${typographyCls}-expand,
|
||||
${typographyCls}-edit,
|
||||
${typographyCls}-copy
|
||||
`]: {
|
||||
...operationUnit(token),
|
||||
marginInlineStart: token.marginXXS,
|
||||
@ -114,20 +124,23 @@ const genTypographyStyle: GenerateStyle<TypographyToken> = token => {
|
||||
export default function useStyle(prefixCls: string): UseComponentStyleResult {
|
||||
const [theme, token, hashId] = useToken();
|
||||
|
||||
const typographyToken: TypographyToken = {
|
||||
...token,
|
||||
typography: {
|
||||
prefixCls,
|
||||
titleMarginTop: '1.2em',
|
||||
titleMarginBottom: '0.5em',
|
||||
titleFontWeight: 600,
|
||||
},
|
||||
};
|
||||
|
||||
return [
|
||||
useStyleRegister({ theme, token, hashId, path: [prefixCls] }, () => [
|
||||
genTypographyStyle(typographyToken),
|
||||
]),
|
||||
useStyleRegister({ theme, token, hashId, path: [prefixCls] }, () => {
|
||||
const { typography } = token;
|
||||
|
||||
const typographyToken: TypographyToken = {
|
||||
...token,
|
||||
|
||||
typographyCls: `.${prefixCls}`,
|
||||
|
||||
sizeMarginHeadingVerticalStart: '1.2em',
|
||||
sizeMarginHeadingVerticalEnd: '0.5em',
|
||||
|
||||
...typography,
|
||||
};
|
||||
|
||||
return [genTypographyStyle(typographyToken)];
|
||||
}),
|
||||
hashId,
|
||||
];
|
||||
}
|
||||
|
@ -9,37 +9,28 @@
|
||||
*/
|
||||
import { gold } from '@ant-design/colors';
|
||||
import type { CSSObject } from '@ant-design/cssinjs';
|
||||
import type { DerivativeToken, GenerateStyle } from '../../_util/theme';
|
||||
import type { GenerateStyle } from '../../_util/theme';
|
||||
import { operationUnit } from '../../_util/theme/util/operationUnit';
|
||||
import { initInputToken } from '../../input/style';
|
||||
|
||||
export interface TypographyToken extends DerivativeToken {
|
||||
typography: {
|
||||
prefixCls: string;
|
||||
titleMarginTop: string;
|
||||
titleMarginBottom: string;
|
||||
titleFontWeight: number;
|
||||
};
|
||||
}
|
||||
import type { TypographyToken } from '.';
|
||||
|
||||
// eslint-disable-next-line import/prefer-default-export
|
||||
const getTitleStyle = ({
|
||||
fontSize,
|
||||
lineHeight,
|
||||
color,
|
||||
typographyToken,
|
||||
}: {
|
||||
fontSize: number;
|
||||
lineHeight: number;
|
||||
color: string;
|
||||
typographyToken: TypographyToken['typography'];
|
||||
}) => ({
|
||||
marginBottom: typographyToken.titleMarginBottom,
|
||||
color,
|
||||
fontWeight: typographyToken.titleFontWeight,
|
||||
fontSize,
|
||||
lineHeight,
|
||||
});
|
||||
const getTitleStyle = (
|
||||
fontSize: number,
|
||||
lineHeight: number,
|
||||
color: string,
|
||||
token: TypographyToken,
|
||||
) => {
|
||||
const { sizeMarginHeadingVerticalEnd, fontWeightStrong } = token;
|
||||
|
||||
return {
|
||||
marginBottom: sizeMarginHeadingVerticalEnd,
|
||||
color,
|
||||
fontWeight: fontWeightStrong,
|
||||
fontSize,
|
||||
lineHeight,
|
||||
};
|
||||
};
|
||||
|
||||
// eslint-disable-next-line import/prefer-default-export
|
||||
export const getTitleStyles: GenerateStyle<TypographyToken, CSSObject> = token => {
|
||||
@ -54,39 +45,43 @@ export const getTitleStyles: GenerateStyle<TypographyToken, CSSObject> = token =
|
||||
div&-h${headingLevel} > textarea,
|
||||
h${headingLevel}
|
||||
`
|
||||
] = getTitleStyle({
|
||||
fontSize: token[`fontSizeHeading${headingLevel}`],
|
||||
lineHeight: token[`lineHeightHeading${headingLevel}`],
|
||||
color: token.colorTextHeading,
|
||||
typographyToken: token.typography,
|
||||
});
|
||||
] = getTitleStyle(
|
||||
token[`fontSizeHeading${headingLevel}`],
|
||||
token[`lineHeightHeading${headingLevel}`],
|
||||
token.colorTextHeading,
|
||||
token,
|
||||
);
|
||||
});
|
||||
return styles;
|
||||
};
|
||||
|
||||
export const getLinkStyles: GenerateStyle<TypographyToken, CSSObject> = token => ({
|
||||
'a&, a': {
|
||||
...operationUnit(token),
|
||||
textDecoration: token.linkDecoration,
|
||||
export const getLinkStyles: GenerateStyle<TypographyToken, CSSObject> = token => {
|
||||
const { typographyCls } = token;
|
||||
|
||||
'&:active, &:hover': {
|
||||
textDecoration: token.linkHoverDecoration,
|
||||
},
|
||||
|
||||
[`&[disabled], &.${token.typography.prefixCls}-disabled`]: {
|
||||
color: token.colorTextDisabled,
|
||||
cursor: 'not-allowed',
|
||||
return {
|
||||
'a&, a': {
|
||||
...operationUnit(token),
|
||||
textDecoration: token.linkDecoration,
|
||||
|
||||
'&:active, &:hover': {
|
||||
color: '@disabled-color',
|
||||
textDecoration: token.linkHoverDecoration,
|
||||
},
|
||||
|
||||
'&:active': {
|
||||
pointerEvents: 'none',
|
||||
[`&[disabled], &${typographyCls}-disabled`]: {
|
||||
color: token.colorTextDisabled,
|
||||
cursor: 'not-allowed',
|
||||
|
||||
'&:active, &:hover': {
|
||||
color: token.colorTextDisabled,
|
||||
},
|
||||
|
||||
'&:active': {
|
||||
pointerEvents: 'none',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
export const getResetStyles = (): CSSObject => ({
|
||||
code: {
|
||||
@ -188,6 +183,8 @@ export const getResetStyles = (): CSSObject => ({
|
||||
});
|
||||
|
||||
export const getEditableStyles: GenerateStyle<TypographyToken, CSSObject> = token => {
|
||||
const { typographyCls } = token;
|
||||
|
||||
const inputToken = initInputToken(token, '', '');
|
||||
const inputShift = inputToken.inputPaddingVertical + 1;
|
||||
return {
|
||||
@ -200,7 +197,7 @@ export const getEditableStyles: GenerateStyle<TypographyToken, CSSObject> = toke
|
||||
marginBottom: `calc(1em - ${inputShift}px)`,
|
||||
},
|
||||
|
||||
[`.${token.typography.prefixCls}-edit-content-confirm`]: {
|
||||
[`${typographyCls}-edit-content-confirm`]: {
|
||||
position: 'absolute',
|
||||
insetInlineEnd: token.marginXS + 2,
|
||||
insetBlockEnd: token.marginXS,
|
||||
|
Loading…
Reference in New Issue
Block a user