import type { RoleSemantics, SurfaceTheme } from '@ankhorage/surface';
import React from 'react';
import { Image } from 'react-native';
import type { AvatarProps, AvatarShape, AvatarSize } from '../../../../types/avatar';
import type { ZoraColor } from '../../../../types/theme';
import { Icon } from '../../../icon/public';
import { View } from '../../../layout/public';
import { withZoraThemeScope } from '../../../theme/adapters/inbound/withZoraThemeScope';
import { useZoraTheme } from '../../../theme/composition/useZoraTheme';
import { Text, type TextVariant } from '../../../typography/public';
import { resolveAvatarInitials } from '../../utils/resolveAvatarInitials';
/***
* Displays a user or entity avatar with image support and initials fallback.
*/
export const Avatar = withZoraThemeScope(AvatarInner);
function resolveAvatarSize(size: AvatarSize): number {
switch (size) {
case 'xs':
return 24;
case 's':
return 32;
case 'l':
return 48;
case 'xl':
return 64;
case 'm':
default:
return 40;
}
}
function resolveRoleSemantics(theme: SurfaceTheme, color: ZoraColor): RoleSemantics {
switch (color) {
case 'secondary':
return theme.semantics.secondary;
case 'tertiary':
return theme.semantics.accent;
case 'quaternary':
return theme.semantics.highlight;
case 'primary':
return theme.semantics.action.primary;
case 'error':
return theme.semantics.error;
case 'info':
return theme.semantics.info;
case 'danger':
return theme.semantics.action.danger;
case 'success':
return theme.semantics.success;
case 'warning':
return theme.semantics.warning;
case 'neutral':
default:
return theme.semantics.action.neutral;
}
}
function resolveTextColor(color: ZoraColor): ZoraColor | undefined {
return color === 'neutral' ? undefined : color;
}
function resolveTextVariant(size: AvatarSize): TextVariant {
switch (size) {
case 'xs':
case 's':
return 'caption';
case 'l':
return 'bodySmall';
case 'xl':
return 'lead';
case 'm':
default:
return 'label';
}
}
function resolveRadius(shape: AvatarShape): 'full' | 'l' {
return shape === 'circle' ? 'full' : 'l';
}
function AvatarInner({
themeId: _themeId,
mode: _mode,
testID,
source,
name,
initials,
iconFallback,
label,
size = 'm',
shape = 'circle',
color = 'neutral',
interactionPolicy: _interactionPolicy,
}: AvatarProps) {
const { theme } = useZoraTheme();
const resolvedSize = resolveAvatarSize(size);
const resolvedInitials = initials ?? resolveAvatarInitials(name);
const role = resolveRoleSemantics(theme, color);
const backgroundColor = color === 'neutral' ? theme.semantics.neutral.surface : role.softBg;
const contentColor = color === 'neutral' ? theme.semantics.content.default : role.base;
const radius = resolveRadius(shape);
const renderFallback = () => {
if (resolvedInitials) {
return (
{resolvedInitials}
);
}
if (iconFallback) {
const iconSize = Math.max(16, Math.round(resolvedSize * 0.48));
return ;
}
return null;
};
return (
{source ? (
) : (
renderFallback()
)}
);
}