{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "avatar",
  "title": "Avatar",
  "author": "AniBT <https://anibt.net>",
  "description": "AniBT die-cut avatar: the white sticker rim and shadow, round for people and rounded-square for groups, initials in the round face on the pink wash, plus shadcn's AvatarBadge, AvatarGroup and AvatarGroupCount.",
  "dependencies": [
    "class-variance-authority",
    "radix-ui"
  ],
  "registryDependencies": [
    "@anibt/theme"
  ],
  "files": [
    {
      "path": "registry/anibt/ui/avatar.tsx",
      "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { Avatar as AvatarPrimitive } from \"radix-ui\"\n\nimport { cn } from \"@/lib/utils\"\n\n/**\n * Avatar — an AniBT 「贴纸手账」 die-cut sticker of a face or a logo.\n *\n * Every avatar wears the sticker rim (`anibt-rim`: a 2px white edge and the\n * small sticker shadow) unless `rim={false}`. People are round; groups and\n * organisations are `shape=\"rounded\"` (a 28% corner), which is how A tells\n * the two apart. The fallback is the round face on the pink wash.\n *\n * Sizes: `xs` 20 (inline beside a name), `sm` 24, `default` 32, `lg` 40,\n * `xl` 64 (a profile head). The names `sm` / `default` / `lg` and the\n * exports `AvatarBadge`, `AvatarGroup`, `AvatarGroupCount` are shadcn's, so\n * this file can replace `components/ui/avatar.tsx`.\n *\n * Radix underneath: the image is shown once it has loaded, the fallback\n * until then and whenever it fails.\n */\nconst avatarVariants = cva(\n  \"group/avatar relative inline-flex shrink-0 select-none overflow-visible align-middle data-[shape=circle]:rounded-full data-[shape=rounded]:rounded-[28%]\",\n  {\n    variants: {\n      size: {\n        xs: \"size-5\",\n        sm: \"size-6\",\n        default: \"size-8\",\n        lg: \"size-10\",\n        xl: \"size-16\",\n      },\n      rim: {\n        true: \"anibt-rim\",\n        false: \"\",\n      },\n    },\n    defaultVariants: {\n      size: \"default\",\n      rim: true,\n    },\n  }\n)\n\ntype AvatarProps = React.ComponentProps<typeof AvatarPrimitive.Root> &\n  VariantProps<typeof avatarVariants> & {\n    /** `circle` for people, `rounded` for groups and organisations. */\n    shape?: \"circle\" | \"rounded\"\n  }\n\nfunction Avatar({ className, size, rim, shape = \"circle\", ...props }: AvatarProps) {\n  return (\n    <AvatarPrimitive.Root\n      data-slot=\"avatar\"\n      data-size={size ?? \"default\"}\n      data-shape={shape}\n      className={cn(avatarVariants({ size, rim }), className)}\n      {...props}\n    />\n  )\n}\n\nfunction AvatarImage({ className, ...props }: React.ComponentProps<typeof AvatarPrimitive.Image>) {\n  return (\n    <AvatarPrimitive.Image\n      data-slot=\"avatar-image\"\n      className={cn(\"aspect-square size-full rounded-[inherit] object-cover\", className)}\n      {...props}\n    />\n  )\n}\n\nfunction AvatarFallback({ className, ...props }: React.ComponentProps<typeof AvatarPrimitive.Fallback>) {\n  return (\n    <AvatarPrimitive.Fallback\n      data-slot=\"avatar-fallback\"\n      className={cn(\n        \"flex size-full items-center justify-center overflow-hidden rounded-[inherit] bg-accent font-anibt-display text-[13px] leading-none font-semibold text-accent-foreground\",\n        \"group-data-[size=xs]/avatar:text-[12px] group-data-[size=sm]/avatar:text-[12px] group-data-[size=lg]/avatar:text-[15px] group-data-[size=xl]/avatar:text-[22px]\",\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nconst avatarBadgeVariants = cva(\n  \"absolute -right-0.5 -bottom-0.5 z-10 inline-flex size-2.5 items-center justify-center rounded-full shadow-[0_0_0_2px_var(--anibt-sticker-edge)] select-none group-data-[size=lg]/avatar:size-3 group-data-[size=sm]/avatar:size-2 group-data-[size=xl]/avatar:right-0.5 group-data-[size=xl]/avatar:bottom-0.5 group-data-[size=xl]/avatar:size-4 group-data-[size=xs]/avatar:size-2 [&>svg]:size-2 group-data-[size=sm]/avatar:[&>svg]:hidden group-data-[size=xs]/avatar:[&>svg]:hidden\",\n  {\n    variants: {\n      tone: {\n        mark: \"bg-anibt-mark text-white\",\n        ok: \"bg-anibt-ok-fill text-white\",\n        time: \"bg-anibt-time text-white\",\n        warn: \"bg-anibt-warn-fill text-white\",\n        mute: \"bg-muted-foreground text-white\",\n      },\n    },\n    defaultVariants: {\n      tone: \"mark\",\n    },\n  }\n)\n\n/** A dot on the corner: online, live, a new item. Say the state in words nearby. */\nfunction AvatarBadge({\n  className,\n  tone,\n  ...props\n}: React.ComponentProps<\"span\"> & VariantProps<typeof avatarBadgeVariants>) {\n  return (\n    <span\n      data-slot=\"avatar-badge\"\n      className={cn(avatarBadgeVariants({ tone }), className)}\n      {...props}\n    />\n  )\n}\n\n/** Overlapping avatars; each rim keeps its neighbour apart. */\nfunction AvatarGroup({ className, ...props }: React.ComponentProps<\"div\">) {\n  return (\n    <div\n      data-slot=\"avatar-group\"\n      className={cn(\"group/avatar-group flex items-center -space-x-1.5\", className)}\n      {...props}\n    />\n  )\n}\n\n/** The `+N` at the end of a group, as a quiet count sticker. */\nfunction AvatarGroupCount({ className, ...props }: React.ComponentProps<\"div\">) {\n  return (\n    <div\n      data-slot=\"avatar-group-count\"\n      className={cn(\n        \"relative inline-flex size-8 shrink-0 items-center justify-center rounded-full bg-muted font-anibt-display text-[12px] font-semibold text-muted-foreground shadow-[0_0_0_2px_var(--anibt-sticker-edge),var(--anibt-shadow-sticker)]\",\n        \"group-has-data-[size=xs]/avatar-group:size-5 group-has-data-[size=sm]/avatar-group:size-6 group-has-data-[size=lg]/avatar-group:size-10 group-has-data-[size=xl]/avatar-group:size-16 [&>svg]:size-4\",\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nexport {\n  Avatar,\n  AvatarImage,\n  AvatarFallback,\n  AvatarBadge,\n  AvatarGroup,\n  AvatarGroupCount,\n  avatarVariants,\n}\nexport type { AvatarProps }\n",
      "type": "registry:ui"
    }
  ],
  "categories": [
    "display"
  ],
  "type": "registry:ui"
}