'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 ? (

) : (
{defaultAvatar}
)}
{badge && (
)}
);
}