import { useState, forwardRef, useMemo } from 'react'; import { getWebProps } from 'react-native-unistyles/web'; import { AvatarProps } from './types'; import { avatarStyles } from './Avatar.styles'; import useMergeRefs from '../hooks/useMergeRefs'; import { getWebAriaProps } from '../utils/accessibility'; import type { IdealystElement } from '../utils/refTypes'; import { flattenStyle } from '../utils/flattenStyle'; /** * User or entity representation with image support and fallback initials. * Available in circle or square shapes with multiple sizes. */ const Avatar = forwardRef(({ src, alt, fallback, size = 'md', shape = 'circle', color, style, testID, id, // Accessibility props accessibilityLabel, accessibilityHint, accessibilityDisabled, accessibilityHidden, accessibilityRole, }, ref) => { // Generate ARIA props const ariaProps = useMemo(() => { return getWebAriaProps({ accessibilityLabel: accessibilityLabel ?? alt, accessibilityHint, accessibilityDisabled, accessibilityHidden, accessibilityRole: accessibilityRole ?? 'img', }); }, [accessibilityLabel, alt, accessibilityHint, accessibilityDisabled, accessibilityHidden, accessibilityRole]); const [hasError, setHasError] = useState(false); avatarStyles.useVariants({ size, shape, }); const avatarStyleArray = [(avatarStyles.avatar as any)({ color }), flattenStyle(style)]; const avatarProps = getWebProps(avatarStyleArray); // Generate fallback text styles with proper theming and size const fallbackStyleArray = [(avatarStyles.fallback as any)({ color })]; const fallbackProps = getWebProps(fallbackStyleArray); const handleImageError = () => { setHasError(true); }; const mergedRef = useMergeRefs(ref, avatarProps.ref); return (
{src && !hasError ? ( {alt} ) : ( {fallback} )}
); }); Avatar.displayName = 'Avatar'; export default Avatar;