{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "avatar",
  "type": "registry:ui",
  "dependencies": [
    "@base-ui/react",
    "clsx",
    "tailwind-merge",
    "class-variance-authority"
  ],
  "registryDependencies": [],
  "files": [
    {
      "path": "avatar.tsx",
      "target": "components/ui/avatar.tsx",
      "type": "registry:ui",
      "content": "\"use client\";\nimport { Avatar as Base } from \"@base-ui/react/avatar\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport * as React from \"react\";\nimport { cn } from \"@/lib/utils\";\n\nconst rootVariants = cva(\n  \"relative inline-flex shrink-0 select-none items-center justify-center rounded-full ring-1 ring-inset ring-border\",\n  {\n    variants: {\n      size: {\n        sm: \"h-8 w-8\",\n        md: \"h-10 w-10\",\n        lg: \"h-14 w-14\",\n      },\n    },\n    defaultVariants: { size: \"md\" },\n  },\n);\n\nconst fallbackVariants = cva(\n  \"flex h-full w-full items-center justify-center font-semibold\",\n  {\n    variants: {\n      size: {\n        sm: \"text-xs\",\n        md: \"text-sm\",\n        lg: \"text-base\",\n      },\n      tone: {\n        solid: \"bg-accent-2 text-on-accent\",\n        accent: \"bg-accent-tint font-bold text-on-tint\",\n        neutral: \"bg-surface-2 text-muted\",\n      },\n    },\n    defaultVariants: { size: \"md\", tone: \"solid\" },\n  },\n);\n\nexport type AvatarTone = \"solid\" | \"accent\" | \"neutral\";\n\nconst dotVariants = cva(\n  \"absolute right-0 bottom-0 rounded-full ring-2 ring-surface\",\n  {\n    variants: {\n      size: {\n        sm: \"h-2 w-2\",\n        md: \"h-2.5 w-2.5\",\n        lg: \"h-3.5 w-3.5\",\n      },\n      status: {\n        online: \"bg-live animate-live-pulse\",\n        away: \"bg-warning\",\n        busy: \"bg-danger\",\n        offline: \"bg-border-strong\",\n      },\n    },\n    defaultVariants: { size: \"md\", status: \"offline\" },\n  },\n);\n\nexport type AvatarStatus = \"online\" | \"away\" | \"busy\" | \"offline\";\n\nexport interface AvatarProps\n  extends Omit<\n      React.ComponentPropsWithoutRef<typeof Base.Root>,\n      \"render\" | \"className\"\n    >,\n    VariantProps<typeof rootVariants> {\n  className?: string;\n  src?: string;\n  alt: string;\n  fallback?: string;\n  status?: AvatarStatus;\n  /** Fallback fill: solid accent (default), tinted accent, or neutral. */\n  tone?: AvatarTone;\n}\n\nexport const Avatar = React.forwardRef<HTMLSpanElement, AvatarProps>(\n  ({ className, src, alt, fallback, size, status, tone, ...props }, ref) => {\n    return (\n      <Base.Root\n        ref={ref}\n        className={cn(rootVariants({ size }), className)}\n        {...props}\n      >\n        <span className=\"flex h-full w-full items-center justify-center overflow-hidden rounded-full bg-surface-2\">\n          {src ? (\n            <Base.Image\n              src={src}\n              alt={alt}\n              className=\"h-full w-full object-cover\"\n            />\n          ) : null}\n          <Base.Fallback className={fallbackVariants({ size, tone })}>\n            {fallback}\n          </Base.Fallback>\n        </span>\n        {status ? (\n          <span aria-hidden=\"true\" className={dotVariants({ size, status })} />\n        ) : null}\n      </Base.Root>\n    );\n  },\n);\nAvatar.displayName = \"Avatar\";\n"
    },
    {
      "path": "avatar-group.tsx",
      "target": "components/ui/avatar-group.tsx",
      "type": "registry:ui",
      "content": "import * as React from \"react\";\nimport { cn } from \"@/lib/utils\";\n\nexport type AvatarGroupSize = \"sm\" | \"md\" | \"lg\";\nexport type AvatarGroupTone = \"solid\" | \"accent\" | \"neutral\";\n\nexport interface AvatarGroupProps extends React.HTMLAttributes<HTMLDivElement> {\n  /** Cap the visible avatars; the rest collapse into a \"+N\" chip. */\n  max?: number;\n  size?: AvatarGroupSize;\n  /** Caption after the stack, e.g. \"25+ active users\". */\n  label?: React.ReactNode;\n  /** Colors the overflow chip to match a tinted cluster. Defaults to neutral. */\n  tone?: AvatarGroupTone;\n}\n\nconst overlap: Record<AvatarGroupSize, string> = {\n  sm: \"-ml-1.5\",\n  md: \"-ml-2\",\n  lg: \"-ml-2.5\",\n};\n\nconst overflowChip: Record<AvatarGroupSize, string> = {\n  sm: \"size-8 text-[0.7rem]\",\n  md: \"size-10 text-xs\",\n  lg: \"size-14 text-sm\",\n};\n\nconst chipTone: Record<AvatarGroupTone, string> = {\n  solid: \"bg-accent-2 text-on-accent\",\n  accent: \"bg-accent-tint text-on-tint\",\n  neutral: \"bg-surface-2 text-muted\",\n};\n\nexport const AvatarGroup = React.forwardRef<HTMLDivElement, AvatarGroupProps>(\n  (\n    {\n      className,\n      max,\n      size = \"md\",\n      label,\n      tone = \"neutral\",\n      children,\n      ...props\n    },\n    ref,\n  ) => {\n    const all = React.Children.toArray(children);\n    const shown = max != null ? all.slice(0, max) : all;\n    const overflow = all.length - shown.length;\n\n    return (\n      <div ref={ref} className={cn(\"flex items-center\", className)} {...props}>\n        <div className=\"flex items-center\">\n          {shown.map((child, i) => (\n            <span\n              key={(child as React.ReactElement).key}\n              className={cn(\n                \"rounded-full shadow-raised ring-2 ring-surface\",\n                i > 0 && overlap[size],\n              )}\n            >\n              {child}\n            </span>\n          ))}\n          {overflow > 0 && (\n            <span\n              className={cn(\n                \"inline-flex items-center justify-center rounded-full font-bold tabular-nums shadow-raised ring-2 ring-surface\",\n                overlap[size],\n                overflowChip[size],\n                chipTone[tone],\n              )}\n            >\n              +{overflow}\n            </span>\n          )}\n        </div>\n        {label != null && (\n          <span className=\"ml-3 text-sm font-medium text-muted\">{label}</span>\n        )}\n      </div>\n    );\n  },\n);\nAvatarGroup.displayName = \"AvatarGroup\";\n"
    }
  ]
}