'use client' import { forwardRef, isValidElement, useMemo } from 'react' import classNames from 'classnames' import { isEmpty } from '~/src/utils/type' import { SmoothCornersBox, type SmoothCornersBoxProps, } from '~/src/components/SmoothCornersBox' import { Status, type StatusSize } from '~/src/components/Status' import type { AvatarProps } from './Avatar.types' import defaultAvatarUrl from './assets/default-avatar.svg' import useProgressiveImage from './useProgressiveImage' import styles from './Avatar.module.scss' const shadow: SmoothCornersBoxProps['shadow'] = { spreadRadius: 2, color: 'surface-high', } 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 = '24', name, disabled = false, showBorder = false, smoothCorners = true, status, className, children, ...rest }, forwardedRef ) { const loadedAvatarUrl = useProgressiveImage(avatarUrl, fallbackUrl) const AVATAR_BORDER_RADIUS = useAvatarRadiusToken() const StatusComponent = useMemo(() => { if ( (isEmpty(children) && !status) || (children && !isValidElement(children)) ) { return null } const statusSize: StatusSize = (() => { switch (size) { case '90': case '120': return 'l' default: return 'm' } })() 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 ? shadow : undefined} backgroundColor="surface" backgroundImage={loadedAvatarUrl} data-testid={AVATAR_TEST_ID} > {StatusComponent}
) })