{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "avatar-group",
  "type": "registry:ui",
  "title": "Avatar Group",
  "description": "Overlapping avatar circles that expand smoothly to reveal each user's name on hover.",
  "author": "Ahdeetai <https://aditya.is-cool.dev>",
  "registryDependencies": [],
  "dependencies": ["clsx", "tailwind-merge"],
  "files": [
    {
      "type": "registry:ui",
      "path": "components/ui/avatar-group.tsx",
      "content": "'use client';\nimport { useState, useEffect, useRef } from 'react';\nimport { cn } from '@/lib/utils';\n\ninterface Avatar {\n  imageUrl: string;\n  name: string;\n}\n\ninterface AvatarGroupProps {\n  className?: string;\n  avatarUrls: Avatar[];\n}\n\nconst AvatarGroup = ({ className, avatarUrls }: AvatarGroupProps) => {\n  const [hoveredIndex, setHoveredIndex] = useState<number | null>(null);\n  const containerRef = useRef<HTMLDivElement>(null);\n\n  useEffect(() => {\n    const handleClickOutside = (event: MouseEvent | TouchEvent) => {\n      if (\n        containerRef.current &&\n        !containerRef.current.contains(event.target as Node)\n      ) {\n        setHoveredIndex(null);\n      }\n    };\n\n    document.addEventListener('mousedown', handleClickOutside);\n    document.addEventListener('touchstart', handleClickOutside);\n\n    return () => {\n      document.removeEventListener('mousedown', handleClickOutside);\n      document.removeEventListener('touchstart', handleClickOutside);\n    };\n  }, []);\n\n  const handleInteraction = (\n    index: number,\n    e: React.MouseEvent | React.TouchEvent,\n  ) => {\n    e.preventDefault();\n    setHoveredIndex(hoveredIndex === index ? null : index);\n  };\n\n  return (\n    <div\n      ref={containerRef}\n      className={cn('z-10 flex -space-x-4 rtl:space-x-reverse', className)}\n    >\n      {avatarUrls.map((avatar, index) => {\n        const isHovered = hoveredIndex === index;\n        const showName = isHovered;\n\n        return (\n          <div\n            key={index}\n            onMouseEnter={() => setHoveredIndex(index)}\n            onMouseLeave={() => setHoveredIndex(null)}\n            onTouchEnd={(e) => handleInteraction(index, e)}\n            onClick={(e) => handleInteraction(index, e)}\n            className={cn(\n              'relative flex items-center gap-0 rounded-full cursor-pointer touch-none',\n              'transition-all duration-500 ease-out',\n              ' hover:z-10',\n              showName ? 'pr-6 pl-2 py-2' : 'p-0.5',\n            )}\n          >\n            <div className='relative shrink-0'>\n              <img\n                src={avatar.imageUrl}\n                alt={avatar.name}\n                width={40}\n                height={40}\n                className={cn(\n                  'h-10 w-10 rounded-full object-cover border-2 border-white dark:border-gray-800',\n                  'transition-all duration-500 ease-out',\n                  'hover:scale-105',\n                )}\n              />\n            </div>\n\n            <div\n              className={cn(\n                'grid transition-all duration-500 ease-out',\n                showName\n                  ? 'grid-cols-[1fr] opacity-100 ml-2'\n                  : 'grid-cols-[0fr] opacity-0 ml-0',\n              )}\n            >\n              <div className='overflow-hidden'>\n                <span\n                  className={cn(\n                    'text-sm font-medium whitespace-nowrap block',\n                    'transition-colors duration-300 text-foreground',\n                  )}\n                >\n                  {avatar.name}\n                </span>\n              </div>\n            </div>\n          </div>\n        );\n      })}\n    </div>\n  );\n};\n\nexport { AvatarGroup };\n"
    },
    {
      "type": "registry:lib",
      "path": "lib/utils.ts",
      "content": "import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n  return twMerge(clsx(inputs));\n}"
    }
  ]
}
