'use client' import { forwardRef, isValidElement, useMemo } from 'react' import classNames from 'classnames' import { isEmpty } from '~/src/utils/type' import { useAvatarContext } from '~/src/components/AlphaAvatar/AvatarSizeContext' import { SmoothCornersBox, type SmoothCornersBoxProps, } from '~/src/components/SmoothCornersBox' import { Status, type StatusSize } from '~/src/components/Status' import type { AvatarProps, AvatarSize } from './Avatar.types' import defaultAvatarUrl from './assets/default-avatar.svg' import useProgressiveImage from './useProgressiveImage' import styles from './Avatar.module.scss' function getStatusSize(size: AvatarSize): StatusSize { switch (size) { case '90': case '120': return 'l' default: return 'm' } } function getShadow(size: AvatarSize): SmoothCornersBoxProps['shadow'] { const spreadRadius = (() => { switch (size) { case '90': return 3 case '120': return 4 default: return 2 } })() return { spreadRadius, color: 'surface-higher', } } export function useAvatarRadiusToken() { return '42%' as const } export const AVATAR_WRAPPER_TEST_ID = 'bezier-avatar-wrapper' const AVATAR_TEST_ID = 'bezier-avatar' const STATUS_WRAPPER_TEST_ID = 'bezier-status-wrapper' /** * `Avatar` is a component for representing some profile image. * @example * * ```tsx * * ``` */ export const Avatar = forwardRef(function Avatar( { avatarUrl = '', fallbackUrl = defaultAvatarUrl, size: sizeProps = '24', name, disabled = false, showBorder = false, smoothCorners = true, status, className, children, ...rest }, forwardedRef ) { const avatarGroupContext = useAvatarContext() const size = avatarGroupContext?.size ?? sizeProps const loadedAvatarUrl = useProgressiveImage(avatarUrl, fallbackUrl) const AVATAR_BORDER_RADIUS = useAvatarRadiusToken() const StatusComponent = useMemo(() => { if ( (isEmpty(children) && !status) || (children && !isValidElement(children)) ) { return null } const Contents = (() => { if (children) { return children } if (status) { return ( ) } return null })() return ( Contents && (
{Contents}
) ) }, [status, size, children]) return (
= 72 && styles['big-size'], showBorder && styles.bordered )} disabled={!smoothCorners} borderRadius={AVATAR_BORDER_RADIUS} shadow={showBorder ? getShadow(size) : undefined} backgroundColor="surface" backgroundImage={loadedAvatarUrl} data-testid={AVATAR_TEST_ID} > {StatusComponent}
) })