ant-design/components/avatar/style/index.ts

212 lines
4.7 KiB
TypeScript
Raw Normal View History

import { type CSSObject, unit } from '@ant-design/cssinjs';
import { resetComponent } from '../../style';
import type { FullToken, GenerateStyle, GetDefaultToken } from '../../theme/internal';
import { genStyleHooks, mergeToken } from '../../theme/internal';
export interface ComponentToken {
/**
* @desc
* @descEN Size of Avatar
*/
containerSize: number;
/**
* @desc
* @descEN Size of large Avatar
*/
containerSizeLG: number;
/**
* @desc
* @descEN Size of small Avatar
*/
containerSizeSM: number;
/**
* @desc
* @descEN Font size of Avatar
*/
textFontSize: number;
/**
* @desc
* @descEN Font size of large Avatar
*/
textFontSizeLG: number;
/**
* @desc
* @descEN Font size of small Avatar
*/
textFontSizeSM: number;
/**
* @desc
* @descEN Spacing between avatars in a group
*/
groupSpace: number;
/**
* @desc
* @descEN Overlapping of avatars in a group
*/
groupOverlapping: number;
/**
* @desc
* @descEN Border color of avatars in a group
*/
groupBorderColor: string;
}
type AvatarToken = FullToken<'Avatar'> & {
avatarBgColor: string;
avatarBg: string;
avatarColor: string;
};
const genBaseStyle: GenerateStyle<AvatarToken> = (token) => {
const {
antCls,
componentCls,
iconCls,
avatarBg,
avatarColor,
containerSize,
containerSizeLG,
containerSizeSM,
textFontSize,
textFontSizeLG,
textFontSizeSM,
borderRadius,
borderRadiusLG,
borderRadiusSM,
lineWidth,
lineType,
calc,
} = token;
// Avatar size style
const avatarSizeStyle = (size: number, fontSize: number, radius: number): CSSObject => ({
width: size,
height: size,
lineHeight: unit(calc(size).sub(calc(lineWidth).mul(2)).equal()),
borderRadius: '50%',
[`&${componentCls}-square`]: {
borderRadius: radius,
},
[`${componentCls}-string`]: {
position: 'absolute',
left: {
_skip_check_: true,
value: '50%',
},
transformOrigin: '0 center',
},
[`&${componentCls}-icon`]: {
fontSize,
[`> ${iconCls}`]: {
margin: 0,
},
},
});
return {
[componentCls]: {
...resetComponent(token),
position: 'relative',
display: 'inline-block',
overflow: 'hidden',
color: avatarColor,
whiteSpace: 'nowrap',
textAlign: 'center',
verticalAlign: 'middle',
background: avatarBg,
border: `${unit(lineWidth)} ${lineType} transparent`,
[`&-image`]: {
background: 'transparent',
},
[`${antCls}-image-img`]: {
display: 'block',
},
...avatarSizeStyle(containerSize, textFontSize, borderRadius),
[`&-lg`]: {
...avatarSizeStyle(containerSizeLG, textFontSizeLG, borderRadiusLG),
},
[`&-sm`]: {
...avatarSizeStyle(containerSizeSM, textFontSizeSM, borderRadiusSM),
},
'> img': {
display: 'block',
width: '100%',
height: '100%',
objectFit: 'cover',
},
},
};
};
const genGroupStyle: GenerateStyle<AvatarToken> = (token) => {
const { componentCls, groupBorderColor, groupOverlapping, groupSpace } = token;
return {
[`${componentCls}-group`]: {
display: 'inline-flex',
[`${componentCls}`]: {
borderColor: groupBorderColor,
},
[`> *:not(:first-child)`]: {
marginInlineStart: groupOverlapping,
},
},
[`${componentCls}-group-popover`]: {
[`${componentCls} + ${componentCls}`]: {
marginInlineStart: groupSpace,
},
},
};
};
export const prepareComponentToken: GetDefaultToken<'Avatar'> = (token) => {
const {
controlHeight,
controlHeightLG,
controlHeightSM,
fontSize,
fontSizeLG,
fontSizeXL,
fontSizeHeading3,
marginXS,
marginXXS,
colorBorderBg,
} = token;
return {
containerSize: controlHeight,
containerSizeLG: controlHeightLG,
containerSizeSM: controlHeightSM,
textFontSize: Math.round((fontSizeLG + fontSizeXL) / 2),
textFontSizeLG: fontSizeHeading3,
textFontSizeSM: fontSize,
groupSpace: marginXXS,
groupOverlapping: -marginXS,
groupBorderColor: colorBorderBg,
};
};
export default genStyleHooks(
'Avatar',
(token) => {
const { colorTextLightSolid, colorTextPlaceholder } = token;
const avatarToken = mergeToken<AvatarToken>(token, {
avatarBg: colorTextPlaceholder,
avatarColor: colorTextLightSolid,
});
return [genBaseStyle(avatarToken), genGroupStyle(avatarToken)];
},
prepareComponentToken,
);