{ "$schema": "https://ui.aodesu.com/schema/registry-item.json", "name": "avatar", "type": "registry:ui", "files": [ { "path": "registry/aodesu/ui/avatar.tsx", "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { ComponentPropsWithoutRef } from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\ninterface AvatarProps extends React.HTMLAttributes {}\n\nfunction getInitials(name: string | undefined | null): string {\n if (!name || typeof name !== \"string\") return \"??\"\n\n const cleanedName = name.trim()\n if (cleanedName.length === 0) return \"??\"\n\n const nameParts = cleanedName.split(/\\s+/).filter((part) => part.length > 0)\n\n if (nameParts.length === 0) return \"??\"\n\n if (nameParts.length === 1) {\n return cleanedName.slice(0, 2).toUpperCase()\n }\n\n return (nameParts[0][0] + nameParts[nameParts.length - 1][0]).toUpperCase()\n}\n\ninterface AvatarProps {\n className?: string\n imageProps?: ComponentPropsWithoutRef<\"img\">\n fallbackProps?: ComponentPropsWithoutRef<\"div\">\n alt?: string\n src?: string\n}\n\nexport default function Avatar({\n className,\n imageProps,\n fallbackProps,\n alt,\n src,\n ...props\n}: AvatarProps & ComponentPropsWithoutRef<\"div\">) {\n return (\n \n \n {getInitials(alt)}\n \n )\n}\n\nfunction AvatarContainer({ className, ...props }: AvatarProps) {\n return (\n \n )\n}\n\ninterface AvatarImageProps extends React.ImgHTMLAttributes {}\n\nfunction AvatarImage({\n className,\n onLoad,\n onError,\n ...props\n}: AvatarImageProps) {\n const [hasError, setHasError] = React.useState(false)\n const { alt } = props\n\n // Reset error state when src changes\n React.useEffect(() => {\n setHasError(false)\n }, [props.src])\n\n if (hasError) {\n return null\n }\n\n return (\n {\n setHasError(true)\n onError?.(e)\n }}\n {...props}\n />\n )\n}\n\ninterface AvatarFallbackProps extends React.HTMLAttributes {\n delayMs?: number\n}\n\nfunction AvatarFallback({\n className,\n delayMs = 0,\n children,\n ...props\n}: AvatarFallbackProps) {\n const [isVisible, setIsVisible] = React.useState(delayMs === 0)\n\n React.useEffect(() => {\n if (delayMs > 0) {\n const timer = setTimeout(() => setIsVisible(true), delayMs)\n return () => clearTimeout(timer)\n }\n }, [delayMs])\n\n if (!isVisible) {\n return null\n }\n\n return (\n \n {children}\n \n )\n}\n\nexport { AvatarContainer, AvatarFallback, AvatarImage }\n", "type": "registry:ui" } ] }