forked from Tencent/tdesign-mobile-react
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(avatar): update avatar style to v2, alignment vue mobile
feat Tencent#536
- Loading branch information
Showing
11 changed files
with
235 additions
and
174 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,89 +1,83 @@ | ||
import React, { useContext, useMemo, Ref, useState } from 'react'; | ||
import type { FC } from 'react'; | ||
import React, { useContext } from 'react'; | ||
import cls from 'classnames'; | ||
import type { TdAvatarProps } from './type'; | ||
import Badge from '../badge/index'; | ||
import { StyledProps } from '../common'; | ||
import { ConfigContext } from '../config-provider'; | ||
import useSizeHook from './hooks/useSizeHooks'; | ||
import AvatarGroup from './AvatarGroup'; | ||
import forwardRefWithStatics from '../_util/forwardRefWithStatics'; | ||
import Image from 'tdesign-mobile-react/image'; | ||
import Badge from 'tdesign-mobile-react/badge'; | ||
import { AvatarGroupContext } from './AvatarGroupContext'; | ||
import { isValidSize } from '../_common/js/avatar/utils'; | ||
import parseTNode from '../_util/parseTNode'; | ||
import useDefaultProps from '../hooks/useDefaultProps'; | ||
import { usePrefixClass } from '../hooks/useClass'; | ||
import { avatarDefaultProps } from './defaultProps'; | ||
import type { TdAvatarProps } from './type'; | ||
import type { StyledProps } from '../common'; | ||
|
||
export interface AvatarProps extends TdAvatarProps, StyledProps { | ||
children?: React.ReactNode; | ||
} | ||
export interface AvatarProps extends TdAvatarProps, StyledProps {} | ||
|
||
const Avatar = forwardRefWithStatics( | ||
(props: AvatarProps, ref: Ref<HTMLDivElement>) => { | ||
const { | ||
size = '', | ||
shape = 'circle', | ||
icon, | ||
children, | ||
hideOnLoadFailed = false, | ||
image = '', | ||
badgeProps, | ||
alt = '', | ||
onError, | ||
className, | ||
...restProps | ||
} = props; | ||
const { size: avatarGroupSize } = useContext(AvatarGroupContext) || {}; | ||
const sizeCls = useSizeHook(size || avatarGroupSize); | ||
const [sizeValue] = useState(size || avatarGroupSize); | ||
const { classPrefix } = useContext(ConfigContext); | ||
const baseAvatarCls = `${classPrefix}-avatar`; | ||
const Avatar: FC<AvatarProps> = (props) => { | ||
const { | ||
size = '', | ||
shape = 'circle', | ||
icon, | ||
children, | ||
hideOnLoadFailed = false, | ||
image = '', | ||
badgeProps, | ||
alt = '', | ||
imageProps, | ||
onError, | ||
} = useDefaultProps(props, avatarDefaultProps); | ||
const avatarGroupProps = useContext(AvatarGroupContext) || {}; | ||
const rootClassName = usePrefixClass('avatar'); | ||
|
||
const isIconOnly = icon && !children; | ||
const { size: avatarGroupSize, shape: avatarGroupShape } = avatarGroupProps; | ||
const hasAvatarGroupProps = Object.keys(avatarGroupProps).length > 0; | ||
const shapeValue = shape || avatarGroupShape || 'circle'; | ||
const sizeValue = size || avatarGroupSize; | ||
const isCustomSize = !isValidSize(sizeValue); | ||
|
||
const avatarCls = cls( | ||
baseAvatarCls, | ||
{ | ||
[sizeCls]: true, | ||
[`${baseAvatarCls}--${shape}`]: shape, | ||
}, | ||
className, | ||
); | ||
const avatarClasses = cls( | ||
rootClassName, | ||
`${rootClassName}-${isCustomSize ? 'medium' : sizeValue}`, | ||
`${rootClassName}-${shapeValue}`, | ||
{ | ||
[`${rootClassName}--border ${rootClassName}--border-${isCustomSize ? 'medium' : sizeValue}`]: hasAvatarGroupProps, | ||
}, | ||
); | ||
|
||
// size 没有命中原有 size 规则且 size 仍有值, 推断为 size 值 | ||
const customSize = useMemo(() => { | ||
if (sizeCls === '' && sizeValue) { | ||
return { | ||
width: sizeValue, | ||
height: sizeValue, | ||
}; | ||
const customSize = isCustomSize | ||
? { | ||
height: sizeValue, | ||
width: sizeValue, | ||
'font-size': `${(Number.parseInt(sizeValue, 10) / 8) * 3 + 2}px`, | ||
} | ||
return {}; | ||
}, [sizeCls, sizeValue]); | ||
: {}; | ||
|
||
const iconCls = `${baseAvatarCls}__icon`; | ||
const badgeCls = `${baseAvatarCls}__badge`; | ||
const innerCls = `${baseAvatarCls}__inner`; | ||
const handleImgLoaderError = (context: any) => { | ||
onError?.(context); | ||
}; | ||
|
||
const renderIcon = <div className={iconCls}>{icon}</div>; | ||
const renderImage = <img style={customSize} alt={alt} src={image} onError={onError}></img>; | ||
const renderContent = <>{children}</>; | ||
const renderBadge = <Badge {...badgeProps}></Badge>; | ||
const renderAvatar = () => { | ||
if (image && !hideOnLoadFailed) { | ||
return <Image src={image} alt={alt} {...imageProps} onError={handleImgLoaderError} />; | ||
} | ||
if (icon) { | ||
return <div className={`${rootClassName}__icon`}>{icon}</div>; | ||
} | ||
return parseTNode(children); | ||
}; | ||
|
||
const isShowImage = image && !hideOnLoadFailed; | ||
const isShowBadge = !!badgeProps; | ||
|
||
return ( | ||
<div ref={ref} className={avatarCls} style={customSize} {...restProps}> | ||
<div className={innerCls}> | ||
{isShowImage && renderImage} | ||
{!isShowImage && isIconOnly && renderIcon} | ||
{!isShowImage && !isIconOnly && renderContent} | ||
</div> | ||
{isShowBadge && <div className={badgeCls}>{renderBadge}</div>} | ||
return ( | ||
<div className={`${rootClassName}__wrapper`}> | ||
<div className={`${rootClassName}__badge`}> | ||
<Badge {...badgeProps}> | ||
<div className={avatarClasses} style={customSize}> | ||
{renderAvatar()} | ||
</div> | ||
</Badge> | ||
</div> | ||
); | ||
}, | ||
{ | ||
Group: AvatarGroup, | ||
}, | ||
); | ||
|
||
Avatar.displayName = 'Avatar'; | ||
</div> | ||
); | ||
}; | ||
|
||
export default Avatar; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
:: BASE_DOC :: | ||
|
||
## API | ||
|
||
|
||
### AvatarGroup Props | ||
|
||
name | type | default | description | required | ||
-- | -- | -- | -- | -- | ||
className | String | - | className of component | N | ||
style | Object | - | CSS(Cascading Style Sheets),Typescript:`React.CSSProperties` | N | ||
cascading | String | 'right-up' | multiple images cascading。options: left-up/right-up。Typescript:`CascadingValue` `type CascadingValue = 'left-up' \| 'right-up'`。[see more ts definition](https://github.com/Tencent/tdesign-mobile-react/tree/develop/src/avatar/type.ts) | N | ||
collapseAvatar | TNode | - | Typescript:`string \| TNode`。[see more ts definition](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N | ||
max | Number | - | \- | N | ||
shape | String | - | shape。options: circle/round。Typescript:`ShapeEnum`。[see more ts definition](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N | ||
size | String | - | size | N | ||
onCollapsedItemClick | Function | | Typescript:`(context: { e: MouseEvent }) => void`<br/> | N |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
:: BASE_DOC :: | ||
|
||
## API | ||
|
||
|
||
### AvatarGroup Props | ||
|
||
名称 | 类型 | 默认值 | 描述 | 必传 | ||
-- | -- | -- | -- | -- | ||
className | String | - | 类名 | N | ||
style | Object | - | 样式,TS 类型:`React.CSSProperties` | N | ||
cascading | String | 'right-up' | 图片之间的层叠关系,可选值:左侧图片在上和右侧图片在上。可选项:left-up/right-up。TS 类型:`CascadingValue` `type CascadingValue = 'left-up' \| 'right-up'`。[详细类型定义](https://github.com/Tencent/tdesign-mobile-react/tree/develop/src/avatar/type.ts) | N | ||
collapseAvatar | TNode | - | 头像数量超出时,会出现一个头像折叠元素。该元素内容可自定义。默认为 `+N`。示例:`+5`,`...`, `更多`。TS 类型:`string \| TNode`。[通用类型定义](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N | ||
max | Number | - | 能够同时显示的最多头像数量 | N | ||
shape | String | - | 形状。优先级低于 Avatar.shape。可选项:circle/round。TS 类型:`ShapeEnum`。[通用类型定义](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N | ||
size | String | - | 尺寸,示例值:small/medium/large/24px/38px 等。优先级低于 Avatar.size | N | ||
onCollapsedItemClick | Function | | TS 类型:`(context: { e: MouseEvent }) => void`<br/>点击头像折叠元素触发 | N |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
:: BASE_DOC :: | ||
|
||
## API | ||
|
||
### Avatar Props | ||
|
||
name | type | default | description | required | ||
-- | -- | -- | -- | -- | ||
className | String | - | className of component | N | ||
style | Object | - | CSS(Cascading Style Sheets),Typescript:`React.CSSProperties` | N | ||
alt | String | - | show it when url is not valid | N | ||
badgeProps | Object | - | Typescript:`BadgeProps`,[Badge API Documents](./badge?tab=api)。[see more ts definition](https://github.com/Tencent/tdesign-mobile-react/tree/develop/src/avatar/type.ts) | N | ||
children | TNode | - | children, same as `content`。Typescript:`string \| TNode`。[see more ts definition](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N | ||
hideOnLoadFailed | Boolean | false | hide image when loading image failed | N | ||
icon | TElement | - | use icon to fill。Typescript:`TNode`。[see more ts definition](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N | ||
image | String | - | images url | N | ||
imageProps | Object | - | Typescript:`ImageProps`,[Image API Documents](./image?tab=api)。[see more ts definition](https://github.com/Tencent/tdesign-mobile-react/tree/develop/src/avatar/type.ts) | N | ||
shape | String | - | shape。options: circle/round。Typescript:`ShapeEnum`。[see more ts definition](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N | ||
size | String | - | size | N | ||
onError | Function | | Typescript:`(context: { e: Event }) => void`<br/>trigger on image load failed | N | ||
|
||
|
||
### AvatarGroup Props | ||
|
||
name | type | default | description | required | ||
-- | -- | -- | -- | -- | ||
className | String | - | className of component | N | ||
style | Object | - | CSS(Cascading Style Sheets),Typescript:`React.CSSProperties` | N | ||
cascading | String | 'right-up' | multiple images cascading。options: left-up/right-up。Typescript:`CascadingValue` `type CascadingValue = 'left-up' \| 'right-up'`。[see more ts definition](https://github.com/Tencent/tdesign-mobile-react/tree/develop/src/avatar/type.ts) | N | ||
collapseAvatar | TNode | - | Typescript:`string \| TNode`。[see more ts definition](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N | ||
max | Number | - | \- | N | ||
shape | String | - | shape。options: circle/round。Typescript:`ShapeEnum`。[see more ts definition](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N | ||
size | String | - | size | N | ||
onCollapsedItemClick | Function | | Typescript:`(context: { e: MouseEvent }) => void`<br/> | N |
Oops, something went wrong.