This commit is contained in:
2026-05-25 17:08:18 +08:00
parent df501f6151
commit f1259b71b5
9178 changed files with 1626125 additions and 0 deletions
+70
View File
@@ -0,0 +1,70 @@
import * as React from 'react';
import type { Tab, TabBarExtraContent } from '@rc-component/tabs/lib/interface';
import type { SemanticClassNamesType, SemanticStylesType } from '../_util/hooks';
import type { SizeType } from '../config-provider/SizeContext';
import type { TabsProps } from '../tabs';
export type CardType = 'inner';
/**
* Note: `default` is deprecated and will be removed in v7, please use `medium` instead.
*/
export type CardSize = Exclude<SizeType, 'large'> | 'default';
export interface CardTabListType extends Omit<Tab, 'label'> {
key: string;
/** @deprecated Please use `label` instead */
tab?: React.ReactNode;
label?: React.ReactNode;
}
export type CardSemanticName = keyof CardSemanticClassNames & keyof CardSemanticStyles;
export type CardSemanticClassNames = {
root?: string;
header?: string;
body?: string;
extra?: string;
title?: string;
actions?: string;
cover?: string;
};
export type CardSemanticStyles = {
root?: React.CSSProperties;
header?: React.CSSProperties;
body?: React.CSSProperties;
extra?: React.CSSProperties;
title?: React.CSSProperties;
actions?: React.CSSProperties;
cover?: React.CSSProperties;
};
export type CardClassNamesType = SemanticClassNamesType<CardProps, CardSemanticClassNames>;
export type CardStylesType = SemanticStylesType<CardProps, CardSemanticStyles>;
export interface CardProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'title'> {
prefixCls?: string;
title?: React.ReactNode;
extra?: React.ReactNode;
/** @deprecated Please use `variant` instead */
bordered?: boolean;
/** @deprecated Please use `styles.header` instead */
headStyle?: React.CSSProperties;
/** @deprecated Please use `styles.body` instead */
bodyStyle?: React.CSSProperties;
style?: React.CSSProperties;
loading?: boolean;
hoverable?: boolean;
children?: React.ReactNode;
id?: string;
className?: string;
rootClassName?: string;
size?: CardSize;
type?: CardType;
cover?: React.ReactNode;
actions?: React.ReactNode[];
tabList?: CardTabListType[];
tabBarExtraContent?: TabBarExtraContent;
onTabChange?: (key: string) => void;
activeTabKey?: string;
defaultActiveTabKey?: string;
tabProps?: TabsProps;
classNames?: CardClassNamesType;
styles?: CardStylesType;
variant?: 'borderless' | 'outlined';
}
declare const Card: React.ForwardRefExoticComponent<CardProps & React.RefAttributes<HTMLDivElement>>;
export default Card;
+198
View File
@@ -0,0 +1,198 @@
"use client";
import * as React from 'react';
import { omit, toArray } from '@rc-component/util';
import { clsx } from 'clsx';
import { useMergeSemantic } from '../_util/hooks';
import { devUseWarning } from '../_util/warning';
import { useComponentConfig } from '../config-provider/context';
import useSize from '../config-provider/hooks/useSize';
import useVariant from '../form/hooks/useVariants';
import Skeleton from '../skeleton';
import Tabs from '../tabs';
import CardGrid from './CardGrid';
import useStyle from './style';
const ActionNode = props => {
const {
actionClasses,
actions = [],
actionStyle
} = props;
return /*#__PURE__*/React.createElement("ul", {
className: actionClasses,
style: actionStyle
}, actions.map((action, index) => {
// Move this out since eslint not allow index key
// And eslint-disable makes conflict with rollup
// ref https://github.com/ant-design/ant-design/issues/46022
const key = `action-${index}`;
return /*#__PURE__*/React.createElement("li", {
style: {
width: `${100 / actions.length}%`
},
key: key
}, /*#__PURE__*/React.createElement("span", null, action));
}));
};
const Card = /*#__PURE__*/React.forwardRef((props, ref) => {
const {
prefixCls: customizePrefixCls,
className,
rootClassName,
style,
extra,
headStyle = {},
bodyStyle = {},
title,
loading,
bordered,
variant: customVariant,
size: customizeSize,
type,
cover,
actions,
tabList,
children,
activeTabKey,
defaultActiveTabKey,
tabBarExtraContent,
hoverable,
tabProps = {},
classNames,
styles,
...rest
} = props;
const {
getPrefixCls,
direction,
className: contextClassName,
style: contextStyle,
classNames: contextClassNames,
styles: contextStyles
} = useComponentConfig('card');
const [variant] = useVariant('card', customVariant, bordered);
if (process.env.NODE_ENV !== 'production') {
const warning = devUseWarning('Card');
warning.deprecated(customizeSize !== 'default', 'size="default"', 'size="medium"');
}
const mergedSize = useSize(customizeSize);
// =========== Merged Props for Semantic ==========
const mergedProps = {
...props,
size: mergedSize,
variant: variant
};
const [mergedClassNames, mergedStyles] = useMergeSemantic([contextClassNames, classNames], [contextStyles, styles], {
props: mergedProps
});
// =================Warning===================
if (process.env.NODE_ENV !== 'production') {
const warning = devUseWarning('Card');
[['headStyle', 'styles.header'], ['bodyStyle', 'styles.body'], ['bordered', 'variant']].forEach(([deprecatedName, newName]) => {
warning.deprecated(!(deprecatedName in props), deprecatedName, newName);
});
}
const onTabChange = key => {
props.onTabChange?.(key);
};
const childNodes = React.useMemo(() => toArray(children), [children]);
const isContainGrid = React.useMemo(() => childNodes.some(child => /*#__PURE__*/React.isValidElement(child) && child.type === CardGrid), [childNodes]);
const prefixCls = getPrefixCls('card', customizePrefixCls);
const [hashId, cssVarCls] = useStyle(prefixCls);
const loadingBlock = /*#__PURE__*/React.createElement(Skeleton, {
loading: true,
active: true,
paragraph: {
rows: 4
},
title: false
}, children);
const hasActiveTabKey = activeTabKey !== undefined;
const extraProps = {
...tabProps,
[hasActiveTabKey ? 'activeKey' : 'defaultActiveKey']: hasActiveTabKey ? activeTabKey : defaultActiveTabKey,
tabBarExtraContent
};
let head;
const tabSize = mergedSize !== 'small' ? 'large' : mergedSize;
const tabs = tabList ? (/*#__PURE__*/React.createElement(Tabs, {
size: tabSize,
...extraProps,
className: `${prefixCls}-head-tabs`,
onChange: onTabChange,
items: tabList.map(({
tab,
...item
}) => ({
label: tab,
...item
}))
})) : null;
if (title || extra || tabs) {
const headClasses = clsx(`${prefixCls}-head`, mergedClassNames.header);
const titleClasses = clsx(`${prefixCls}-head-title`, mergedClassNames.title);
const extraClasses = clsx(`${prefixCls}-extra`, mergedClassNames.extra);
const mergedHeadStyle = {
...headStyle,
...mergedStyles.header
};
head = /*#__PURE__*/React.createElement("div", {
className: headClasses,
style: mergedHeadStyle
}, /*#__PURE__*/React.createElement("div", {
className: `${prefixCls}-head-wrapper`
}, title && (/*#__PURE__*/React.createElement("div", {
className: titleClasses,
style: mergedStyles.title
}, title)), extra && (/*#__PURE__*/React.createElement("div", {
className: extraClasses,
style: mergedStyles.extra
}, extra))), tabs);
}
const coverClasses = clsx(`${prefixCls}-cover`, mergedClassNames.cover);
const coverDom = cover ? (/*#__PURE__*/React.createElement("div", {
className: coverClasses,
style: mergedStyles.cover
}, cover)) : null;
const bodyClasses = clsx(`${prefixCls}-body`, mergedClassNames.body);
const mergedBodyStyle = {
...bodyStyle,
...mergedStyles.body
};
const body = loading || childNodes.length ? (/*#__PURE__*/React.createElement("div", {
className: bodyClasses,
style: mergedBodyStyle
}, loading ? loadingBlock : children)) : null;
const actionClasses = clsx(`${prefixCls}-actions`, mergedClassNames.actions);
const actionDom = actions?.length ? (/*#__PURE__*/React.createElement(ActionNode, {
actionClasses: actionClasses,
actionStyle: mergedStyles.actions,
actions: actions
})) : null;
const divProps = omit(rest, ['onTabChange']);
const classString = clsx(prefixCls, contextClassName, {
[`${prefixCls}-loading`]: loading,
[`${prefixCls}-bordered`]: variant !== 'borderless',
[`${prefixCls}-hoverable`]: hoverable,
[`${prefixCls}-contain-grid`]: isContainGrid,
[`${prefixCls}-contain-tabs`]: tabList?.length,
[`${prefixCls}-small`]: mergedSize === 'small',
[`${prefixCls}-type-${type}`]: !!type,
[`${prefixCls}-rtl`]: direction === 'rtl'
}, className, rootClassName, hashId, cssVarCls, mergedClassNames.root);
const mergedStyle = {
...mergedStyles.root,
...contextStyle,
...style
};
return /*#__PURE__*/React.createElement("div", {
ref: ref,
...divProps,
className: classString,
style: mergedStyle
}, head, coverDom, body, actionDom);
});
if (process.env.NODE_ENV !== 'production') {
Card.displayName = 'Card';
}
export default Card;
+9
View File
@@ -0,0 +1,9 @@
import * as React from 'react';
export interface CardGridProps extends React.HTMLAttributes<HTMLDivElement> {
prefixCls?: string;
className?: string;
hoverable?: boolean;
style?: React.CSSProperties;
}
declare const CardGrid: React.FC<CardGridProps>;
export default CardGrid;
+27
View File
@@ -0,0 +1,27 @@
"use client";
import * as React from 'react';
import { clsx } from 'clsx';
import { ConfigContext } from '../config-provider';
const CardGrid = ({
prefixCls,
className,
hoverable = true,
...rest
}) => {
const {
getPrefixCls
} = React.useContext(ConfigContext);
const prefix = getPrefixCls('card', prefixCls);
const classString = clsx(`${prefix}-grid`, className, {
[`${prefix}-grid-hoverable`]: hoverable
});
return /*#__PURE__*/React.createElement("div", {
...rest,
className: classString
});
};
if (process.env.NODE_ENV !== 'production') {
CardGrid.displayName = 'CardGrid';
}
export default CardGrid;
+31
View File
@@ -0,0 +1,31 @@
import * as React from 'react';
import type { SemanticClassNamesType, SemanticStylesType } from '../_util/hooks';
export type CardMetaSemanticName = keyof CardMetaSemanticClassNames & keyof CardMetaSemanticStyles;
export type CardMetaSemanticClassNames = {
root?: string;
section?: string;
avatar?: string;
title?: string;
description?: string;
};
export type CardMetaSemanticStyles = {
root?: React.CSSProperties;
section?: React.CSSProperties;
avatar?: React.CSSProperties;
title?: React.CSSProperties;
description?: React.CSSProperties;
};
export type CardMetaClassNamesType = SemanticClassNamesType<CardMetaProps, CardMetaSemanticClassNames>;
export type CardMetaStylesType = SemanticStylesType<CardMetaProps, CardMetaSemanticStyles>;
export interface CardMetaProps {
prefixCls?: string;
style?: React.CSSProperties;
className?: string;
avatar?: React.ReactNode;
title?: React.ReactNode;
description?: React.ReactNode;
classNames?: CardMetaClassNamesType;
styles?: CardMetaStylesType;
}
declare const CardMeta: React.FC<CardMetaProps>;
export default CardMeta;
+66
View File
@@ -0,0 +1,66 @@
"use client";
import * as React from 'react';
import { clsx } from 'clsx';
import { useMergeSemantic } from '../_util/hooks';
import { useComponentConfig } from '../config-provider/context';
const CardMeta = props => {
const {
prefixCls: customizePrefixCls,
className,
avatar,
title,
description,
style,
classNames: cardMetaClassNames,
styles,
...restProps
} = props;
const {
getPrefixCls,
className: contextClassName,
style: contextStyle,
classNames: contextClassNames,
styles: contextStyles
} = useComponentConfig('cardMeta');
const prefixCls = getPrefixCls('card', customizePrefixCls);
const metaPrefixCls = `${prefixCls}-meta`;
const [mergedClassNames, mergedStyles] = useMergeSemantic([contextClassNames, cardMetaClassNames], [contextStyles, styles], {
props
});
const rootClassNames = clsx(metaPrefixCls, className, contextClassName, mergedClassNames.root);
const rootStyles = {
...contextStyle,
...mergedStyles.root,
...style
};
const avatarClassNames = clsx(`${metaPrefixCls}-avatar`, mergedClassNames.avatar);
const titleClassNames = clsx(`${metaPrefixCls}-title`, mergedClassNames.title);
const descriptionClassNames = clsx(`${metaPrefixCls}-description`, mergedClassNames.description);
const sectionClassNames = clsx(`${metaPrefixCls}-section`, mergedClassNames.section);
const avatarDom = avatar ? (/*#__PURE__*/React.createElement("div", {
className: avatarClassNames,
style: mergedStyles.avatar
}, avatar)) : null;
const titleDom = title ? (/*#__PURE__*/React.createElement("div", {
className: titleClassNames,
style: mergedStyles.title
}, title)) : null;
const descriptionDom = description ? (/*#__PURE__*/React.createElement("div", {
className: descriptionClassNames,
style: mergedStyles.description
}, description)) : null;
const MetaDetail = titleDom || descriptionDom ? (/*#__PURE__*/React.createElement("div", {
className: sectionClassNames,
style: mergedStyles.section
}, titleDom, descriptionDom)) : null;
return /*#__PURE__*/React.createElement("div", {
...restProps,
className: rootClassNames,
style: rootStyles
}, avatarDom, MetaDetail);
};
if (process.env.NODE_ENV !== 'production') {
CardMeta.displayName = 'CardMeta';
}
export default CardMeta;
+13
View File
@@ -0,0 +1,13 @@
import InternalCard from './Card';
import CardGrid from './CardGrid';
import CardMeta from './CardMeta';
export type { CardProps, CardSemanticClassNames, CardSemanticName, CardSemanticStyles, CardTabListType, } from './Card';
export type { CardGridProps } from './CardGrid';
export type { CardMetaProps, CardMetaSemanticClassNames, CardMetaSemanticName, CardMetaSemanticStyles, } from './CardMeta';
type InternalCardType = typeof InternalCard;
export interface CardInterface extends InternalCardType {
Grid: typeof CardGrid;
Meta: typeof CardMeta;
}
declare const Card: CardInterface;
export default Card;
+9
View File
@@ -0,0 +1,9 @@
"use client";
import InternalCard from './Card';
import CardGrid from './CardGrid';
import CardMeta from './CardMeta';
const Card = InternalCard;
Card.Grid = CardGrid;
Card.Meta = CardMeta;
export default Card;
+71
View File
@@ -0,0 +1,71 @@
import type { GetDefaultToken } from '../../theme/internal';
export interface ComponentToken {
/**
* @desc 卡片头部背景色
* @descEN Background color of card header
*/
headerBg: string;
/**
* @desc 卡片头部文字大小
* @descEN Font size of card header
*/
headerFontSize: number | string;
/**
* @desc 小号卡片头部文字大小
* @descEN Font size of small card header
*/
headerFontSizeSM: number | string;
/**
* @desc 卡片头部高度
* @descEN Height of card header
*/
headerHeight: number | string;
/**
* @desc 小号卡片头部高度
* @descEN Height of small card header
*/
headerHeightSM: number | string;
/**
* @desc 小号卡片内边距
* @descEN Padding of small card body
*/
bodyPaddingSM: number;
/**
* @desc 小号卡片头部内边距
* @descEN Padding of small card head
*/
headerPaddingSM: number;
/**
* @desc 卡片内边距
* @descEN Padding of card body
*/
bodyPadding: number;
/**
* @desc 卡片头部内边距
* @descEN Padding of card head
*/
headerPadding: number;
/**
* @desc 操作区背景色
* @descEN Background color of card actions
*/
actionsBg: string;
/**
* @desc 操作区每一项的外间距
* @descEN Margin of each item in card actions
*/
actionsLiMargin: string;
/**
* @desc 内置标签页组件下间距
* @descEN Margin bottom of tabs component
*/
tabsMarginBottom: number;
/**
* @desc 额外区文字颜色
* @descEN Text color of extra area
*/
extraColor: string;
}
export declare const prepareComponentToken: GetDefaultToken<'Card'>;
declare const _default: (prefixCls: string, rootCls?: string) => readonly [string, string];
export default _default;
+364
View File
@@ -0,0 +1,364 @@
import { unit } from '@ant-design/cssinjs';
import { clearFix, resetComponent, textEllipsis } from '../../style';
import { genStyleHooks, mergeToken } from '../../theme/internal';
// ============================== Styles ==============================
// ============================== Head ==============================
const genCardHeadStyle = token => {
const {
antCls,
componentCls,
headerHeight,
headerPadding,
tabsMarginBottom
} = token;
return {
display: 'flex',
justifyContent: 'center',
flexDirection: 'column',
minHeight: headerHeight,
marginBottom: -1,
// Fix card grid overflow bug: https://gw.alipayobjects.com/zos/rmsportal/XonYxBikwpgbqIQBeuhk.png
padding: `0 ${unit(headerPadding)}`,
color: token.colorTextHeading,
fontWeight: token.fontWeightStrong,
fontSize: token.headerFontSize,
background: token.headerBg,
borderBottom: `${unit(token.lineWidth)} ${token.lineType} ${token.colorBorderSecondary}`,
borderRadius: `${unit(token.borderRadiusLG)} ${unit(token.borderRadiusLG)} 0 0`,
...clearFix(),
'&-wrapper': {
width: '100%',
display: 'flex',
alignItems: 'center'
},
'&-title': {
display: 'inline-block',
flex: 1,
...textEllipsis,
[`
> ${componentCls}-typography,
> ${componentCls}-typography-edit-content
`]: {
insetInlineStart: 0,
marginTop: 0,
marginBottom: 0
}
},
[`${antCls}-tabs-top`]: {
clear: 'both',
marginBottom: tabsMarginBottom,
color: token.colorText,
fontWeight: 'normal',
fontSize: token.fontSize,
'&-bar': {
borderBottom: `${unit(token.lineWidth)} ${token.lineType} ${token.colorBorderSecondary}`
}
}
};
};
// ============================== Grid ==============================
const genCardGridStyle = token => {
const {
cardPaddingBase,
colorBorderSecondary,
cardShadow,
lineWidth
} = token;
return {
width: '33.33%',
padding: cardPaddingBase,
border: 0,
borderRadius: 0,
boxShadow: `
${unit(lineWidth)} 0 0 0 ${colorBorderSecondary},
0 ${unit(lineWidth)} 0 0 ${colorBorderSecondary},
${unit(lineWidth)} ${unit(lineWidth)} 0 0 ${colorBorderSecondary},
${unit(lineWidth)} 0 0 0 ${colorBorderSecondary} inset,
0 ${unit(lineWidth)} 0 0 ${colorBorderSecondary} inset;
`,
transition: `all ${token.motionDurationMid}`,
'&-hoverable:hover': {
position: 'relative',
zIndex: 1,
boxShadow: cardShadow
}
};
};
// ============================== Actions ==============================
const genCardActionsStyle = token => {
const {
componentCls,
iconCls,
actionsLiMargin,
cardActionsIconSize,
colorBorderSecondary,
actionsBg
} = token;
return {
margin: 0,
padding: 0,
listStyle: 'none',
background: actionsBg,
borderTop: `${unit(token.lineWidth)} ${token.lineType} ${colorBorderSecondary}`,
display: 'flex',
borderRadius: `0 0 ${unit(token.borderRadiusLG)} ${unit(token.borderRadiusLG)}`,
...clearFix(),
'& > li': {
margin: actionsLiMargin,
color: token.colorTextDescription,
textAlign: 'center',
'> span': {
position: 'relative',
display: 'block',
minWidth: token.calc(token.cardActionsIconSize).mul(2).equal(),
fontSize: token.fontSize,
lineHeight: token.lineHeight,
cursor: 'pointer',
'&:hover': {
color: token.colorPrimary,
transition: `color ${token.motionDurationMid}`
},
[`a:not(${componentCls}-btn), > ${iconCls}`]: {
display: 'inline-block',
width: '100%',
color: token.colorIcon,
lineHeight: unit(token.fontHeight),
transition: `color ${token.motionDurationMid}`,
'&:hover': {
color: token.colorPrimary
}
},
[`> ${iconCls}`]: {
fontSize: cardActionsIconSize,
lineHeight: unit(token.calc(cardActionsIconSize).mul(token.lineHeight).equal())
}
},
'&:not(:last-child)': {
borderInlineEnd: `${unit(token.lineWidth)} ${token.lineType} ${colorBorderSecondary}`
}
}
};
};
// ============================== Meta ==============================
const genCardMetaStyle = token => ({
margin: `${unit(token.calc(token.marginXXS).mul(-1).equal())} 0`,
display: 'flex',
...clearFix(),
'&-avatar': {
paddingInlineEnd: token.padding
},
'&-section': {
overflow: 'hidden',
flex: 1,
'> div:not(:last-child)': {
marginBottom: token.marginXS
}
},
'&-title': {
color: token.colorTextHeading,
fontWeight: token.fontWeightStrong,
fontSize: token.fontSizeLG,
...textEllipsis
},
'&-description': {
color: token.colorTextDescription
}
});
// ============================== Inner ==============================
const genCardTypeInnerStyle = token => {
const {
componentCls,
colorFillAlter,
headerPadding,
bodyPadding
} = token;
return {
[`${componentCls}-head`]: {
padding: `0 ${unit(headerPadding)}`,
background: colorFillAlter,
'&-title': {
fontSize: token.fontSize
}
},
[`${componentCls}-body`]: {
padding: `${unit(token.padding)} ${unit(bodyPadding)}`
}
};
};
// ============================== Loading ==============================
const genCardLoadingStyle = token => {
const {
componentCls
} = token;
return {
overflow: 'hidden',
[`${componentCls}-body`]: {
userSelect: 'none'
}
};
};
// ============================== Basic ==============================
const genCardStyle = token => {
const {
componentCls,
cardShadow,
cardHeadPadding,
colorBorderSecondary,
boxShadowTertiary,
bodyPadding,
extraColor,
motionDurationMid
} = token;
return {
[componentCls]: {
...resetComponent(token),
position: 'relative',
background: token.colorBgContainer,
borderRadius: token.borderRadiusLG,
[`&:not(${componentCls}-bordered)`]: {
boxShadow: boxShadowTertiary
},
[`${componentCls}-head`]: genCardHeadStyle(token),
[`${componentCls}-extra`]: {
// https://stackoverflow.com/a/22429853/3040605
marginInlineStart: 'auto',
color: extraColor,
fontWeight: 'normal',
fontSize: token.fontSize
},
[`${componentCls}-body`]: {
padding: bodyPadding,
borderRadius: `0 0 ${unit(token.borderRadiusLG)} ${unit(token.borderRadiusLG)}`,
'&:first-child': {
borderStartStartRadius: token.borderRadiusLG,
borderStartEndRadius: token.borderRadiusLG
},
'&:not(:last-child)': {
borderEndStartRadius: 0,
borderEndEndRadius: 0
}
},
[`${componentCls}-grid`]: genCardGridStyle(token),
[`${componentCls}-cover`]: {
'> *': {
display: 'block',
width: '100%',
borderRadius: `${unit(token.borderRadiusLG)} ${unit(token.borderRadiusLG)} 0 0`
}
},
[`${componentCls}-actions`]: genCardActionsStyle(token),
[`${componentCls}-meta`]: genCardMetaStyle(token)
},
[`${componentCls}-bordered`]: {
border: `${unit(token.lineWidth)} ${token.lineType} ${colorBorderSecondary}`,
[`${componentCls}-cover`]: {
marginTop: -1,
marginInlineStart: -1,
marginInlineEnd: -1
}
},
[`${componentCls}-hoverable`]: {
cursor: 'pointer',
transition: [`box-shadow`, `border-color`].map(prop => `${prop} ${motionDurationMid}`).join(', '),
'&:hover': {
borderColor: 'transparent',
boxShadow: cardShadow
}
},
[`${componentCls}-contain-grid`]: {
borderRadius: `${unit(token.borderRadiusLG)} ${unit(token.borderRadiusLG)} 0 0 `,
// Reset border radius when no head exists
[`&:not(:has(> ${componentCls}-head))`]: {
borderRadius: 0
},
[`${componentCls}-body`]: {
display: 'flex',
flexWrap: 'wrap'
},
[`&:not(${componentCls}-loading) ${componentCls}-body`]: {
marginBlockStart: token.calc(token.lineWidth).mul(-1).equal(),
marginInlineStart: token.calc(token.lineWidth).mul(-1).equal(),
padding: 0
}
},
[`${componentCls}-contain-tabs`]: {
[`> div${componentCls}-head`]: {
minHeight: 0,
[`${componentCls}-head-title, ${componentCls}-extra`]: {
paddingTop: cardHeadPadding
}
}
},
[`${componentCls}-type-inner`]: genCardTypeInnerStyle(token),
[`${componentCls}-loading`]: genCardLoadingStyle(token),
[`${componentCls}-rtl`]: {
direction: 'rtl'
}
};
};
// ============================== Size ==============================
const genCardSizeStyle = token => {
const {
componentCls,
bodyPaddingSM,
headerPaddingSM,
headerHeightSM,
headerFontSizeSM
} = token;
return {
[`${componentCls}-small`]: {
[`> ${componentCls}-head`]: {
minHeight: headerHeightSM,
padding: `0 ${unit(headerPaddingSM)}`,
fontSize: headerFontSizeSM,
[`> ${componentCls}-head-wrapper`]: {
[`> ${componentCls}-extra`]: {
fontSize: token.fontSize
}
}
},
[`> ${componentCls}-body`]: {
padding: bodyPaddingSM
}
},
[`${componentCls}-small${componentCls}-contain-tabs`]: {
[`> ${componentCls}-head`]: {
[`${componentCls}-head-title, ${componentCls}-extra`]: {
paddingTop: 0,
display: 'flex',
alignItems: 'center'
}
}
}
};
};
export const prepareComponentToken = token => ({
headerBg: 'transparent',
headerFontSize: token.fontSizeLG,
headerFontSizeSM: token.fontSize,
headerHeight: token.fontSizeLG * token.lineHeightLG + token.padding * 2,
headerHeightSM: token.fontSize * token.lineHeight + token.paddingXS * 2,
actionsBg: token.colorBgContainer,
actionsLiMargin: `${token.paddingSM}px 0`,
tabsMarginBottom: -token.padding - token.lineWidth,
extraColor: token.colorText,
bodyPaddingSM: 12,
// Fixed padding.
headerPaddingSM: 12,
bodyPadding: token.bodyPadding ?? token.paddingLG,
headerPadding: token.headerPadding ?? token.paddingLG
});
// ============================== Export ==============================
export default genStyleHooks('Card', token => {
const cardToken = mergeToken(token, {
cardShadow: token.boxShadowCard,
cardHeadPadding: token.padding,
cardPaddingBase: token.paddingLG,
cardActionsIconSize: token.fontSize
});
return [
// Style
genCardStyle(cardToken),
// Size
genCardSizeStyle(cardToken)];
}, prepareComponentToken);