import Badge, { BadgeAssets, BadgeProps, BadgeAssetsProps } from '../badge'; import Dot, { DotProps } from './Dot'; import Circle from '../common/circle'; import Image from '../image'; import { HTMLAttributes, PropsWithChildren, useState } from 'react'; import { clsx } from 'clsx'; import { getInitials, ProfileType, ProfileTypeBusiness, ProfileTypePersonal } from '../common'; import { Briefcase as BusinessProfileIcon, Profile as PersonalProfileIcon, } from '@transferwise/icons'; export type AvatarViewBadgeProps = Omit & Pick & { /** * Custom badge content */ asset?: React.ReactNode; }; export type Props = { imgSrc?: string | null; /** * Entity name (person (profile or recipient) or business name), it will be boilded down to 1 or 2 chars (initials) */ profileName?: string | null; profileType?: ProfileTypeBusiness | ProfileTypePersonal; size?: 16 | 24 | 32 | 40 | 48 | 56 | 72; badge?: AvatarViewBadgeProps; interactive?: boolean; selected?: boolean; style?: Pick; } & Pick< HTMLAttributes, 'id' | 'className' | 'children' | 'role' | 'aria-label' | 'aria-labelledby' | 'aria-hidden' >; function AvatarView({ children = undefined, size = 48, selected, badge, interactive = false, className, style, imgSrc, profileType, profileName, ...restProps }: Props) { return ( {children} ); } /** Size of badge depends on size of avatar */ const MAP_BADGE_ASSET_SIZE = { 16: 16, 24: 16, 32: 16, 40: 16, 48: 16, 56: 24, 72: 24, } satisfies Record; /** Border width for `selected` state determined by avatar size */ const MAP_SELECTED_BORDER_WIDTH = { 16: 1, 24: 1, 32: 1, 40: 2, 48: 2, 56: 2, 72: 2, }; /** Certain sizes of AvatarView has a custom offset for badge */ const MAP_BADGE_POSITION = { 24: -6, 32: -4, }; type BadgesProps = AvatarViewBadgeProps & PropsWithChildren<{ avatar: Pick; }>; /** * Adds build-in badges to AvatarView */ function Badges({ children, avatar, 'aria-label': ariaLabel, asset: customBadge, ...badgeAssets }: BadgesProps) { const { size = 48, selected } = avatar; const anyBadge = Object.values({ customBadge, ...badgeAssets }).filter(Boolean).length > 0; if ((!anyBadge && !selected) || size <= 16) { return children; } if (badgeAssets.type === 'notification' || badgeAssets.type === 'online') { return ( {children} ); } const badgeSize: BadgeAssetsProps['size'] = MAP_BADGE_ASSET_SIZE[size]; return ( {customBadge} ) : ( ) } style={{ // @ts-expect-error CSS custom props allowed '--badge-content-position': `${MAP_BADGE_POSITION[size] ?? 0}px`, }} > {children} ); } function AvatarViewContent({ children, imgSrc, profileName: name, profileType: type, }: PropsWithChildren>) { const [tryLoadImage, setTryLoadImage] = useState(true); if (children === undefined) { if (imgSrc && tryLoadImage) { return setTryLoadImage(false)} />; } if (type) { return type === ProfileType.BUSINESS ? : ; } if (name) { return getInitials(name); } return ; } return children; } export default AvatarView;