'use client'; import { useIdentityContext } from '@/identity/components/IdentityProvider'; import { useAvatar } from '@/identity/hooks/useAvatar'; import { useName } from '@/identity/hooks/useName'; import type { AvatarProps } from '@/identity/types'; import { findComponent } from '@/internal/utils/findComponent'; import { Children, ImgHTMLAttributes, ReactNode, useMemo } from 'react'; import { defaultAvatarSVG } from '../../internal/svg/defaultAvatarSVG'; import { defaultLoadingSVG } from '../../internal/svg/defaultLoadingSVG'; import { cn } from '../../styles/theme'; import { Badge } from './Badge'; import { DisplayBadge } from './DisplayBadge'; import { Address } from 'viem'; /** * Represents an Avatar component that displays either a loading indicator, * a default avatar, or a custom avatar based on Ethereum Name Service (ENS). */ export function Avatar({ address = null, chain, className, defaultComponent, loadingComponent, children, ...props }: AvatarProps) { const { address: contextAddress } = useIdentityContext(); const accountAddress = address ?? contextAddress; if (!accountAddress) { console.error( 'Avatar: an Ethereum address must be provided to the Identity or Avatar component.', ); return null; } return ( {children} ); } function AvatarContent({ address = null, chain, className, defaultComponent, loadingComponent, children, name: nameOverride, avatar: avatarOverride, ...props }: AvatarProps) { const { address: contextAddress, chain: contextChain } = useIdentityContext(); const accountAddress = address ?? contextAddress; const accountChain = chain ?? contextChain; const { data: name, isLoading: isLoadingName } = useName({ address: accountAddress, chain: accountChain, }); const { data: avatar, isLoading: isLoadingAvatar } = useAvatar( { ensName: name ?? '', chain: accountChain }, { enabled: !!name }, ); const { resolvedName, resolvedAvatar } = useMemo(() => { return { resolvedName: nameOverride ?? name ?? '', resolvedAvatar: avatarOverride ?? avatar ?? '', }; }, [name, avatar, nameOverride, avatarOverride]); const badge = useMemo(() => { return Children.toArray(children).find(findComponent(Badge)); }, [children]); const defaultAvatar = defaultComponent || defaultAvatarSVG; const loadingAvatar = loadingComponent || defaultLoadingSVG; if (isLoadingName || isLoadingAvatar) { return (
{loadingAvatar}
); } return ( ); } function AvatarRenderer({ className, avatar, name, defaultAvatar, badge, accountAddress, ...rest }: { className?: string; avatar: string; name: string; defaultAvatar: ReactNode; badge: ReactNode; accountAddress: Address; } & ImgHTMLAttributes) { return (
{name && avatar ? ( {name} ) : (
{defaultAvatar}
)}
{badge && (
{badge}
)}
); }