{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "avatar",
  "type": "registry:ui",
  "title": "Avatar، AvatarGroup",
  "description": "آواتار",
  "registryDependencies": [
    "https://kashi.sepantapouya.com/r/cx.json",
    "https://kashi.sepantapouya.com/r/kashi-provider.json",
    "https://kashi.sepantapouya.com/r/utils.json"
  ],
  "files": [
    {
      "path": "registry/kashi/Avatar.tsx",
      "type": "registry:ui",
      "target": "components/kashi/Avatar.tsx",
      "content": "\"use client\";\n\nimport { Children, forwardRef, useState, type HTMLAttributes, type ReactNode } from \"react\";\nimport { cx } from \"./cx\";\nimport { toFaDigits } from \"./utils\";\nimport { useKashi } from \"./KashiProvider\";\n\nexport type AvatarSize = \"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\" | \"2xl\";\nexport type AvatarStatus = \"online\" | \"offline\" | \"busy\" | \"away\";\n\n\n/** حروف اول دو کلمهٔ اول؛ با نیم‌فاصله تا حروف فارسی به هم نچسبند */\nexport function initials(name: string, max = 2): string {\n  return name\n    .trim()\n    .split(/\\s+/)\n    .slice(0, max)\n    .map((w) => w[0])\n    .join(\"‌\")\n    .toUpperCase();\n}\n\nconst TONES = [\"brand\", \"info\", \"success\", \"warning\", \"error\"] as const;\n\n/** رنگ ثابت از روی نام؛ یکسان در هر بار و هر دستگاه */\nexport function autoTone(name: string): (typeof TONES)[number] {\n  let h = 0;\n  for (const ch of name.trim()) h = (h * 31 + ch.codePointAt(0)!) >>> 0;\n  return TONES[h % TONES.length];\n}\n\nexport interface AvatarProps extends HTMLAttributes<HTMLSpanElement> {\n  /** نام شخص — برای alt تصویر و حروف اول جایگزین */\n  name: string;\n  src?: string;\n  /** @default \"md\" */\n  size?: AvatarSize;\n  square?: boolean;\n  /** رنگ برند برای حالت حروف اول */\n  brand?: boolean;\n  /** «auto»: رنگ ثابت از روی نام (هر شخص همیشه یک رنگ)، یا یکی از رنگ‌ها */\n  color?: \"auto\" | \"neutral\" | \"brand\" | \"info\" | \"success\" | \"warning\" | \"error\";\n  status?: AvatarStatus;\n  /** برچسب‌های وضعیت برای صفحه‌خوان (پیش‌فرض فارسی) */\n  statusLabels?: Partial<Record<AvatarStatus, string>>;\n}\n\nexport const Avatar = forwardRef<HTMLSpanElement, AvatarProps>(function Avatar(\n  { name, src, size = \"md\", square = false, brand = false, color, status, statusLabels, className, ...rest },\n  ref,\n) {\n  const [failed, setFailed] = useState(false);\n  const showImage = src && !failed;\n  const tone = color === \"auto\" ? autoTone(name) : color ?? (brand ? \"brand\" : \"neutral\");\n  const { messages: M } = useKashi();\n  const statusText = status ? (statusLabels?.[status] ?? M.avatar[status]) : undefined;\n  return (\n    <span\n      ref={ref}\n      role=\"img\"\n      aria-label={statusText ? `${name}${M.common.list}${statusText}` : name}\n      data-tone={tone}\n      className={cx(\"k-avatar\", size !== \"md\" && `k-avatar--${size}`, square && \"k-avatar--square\", tone !== \"neutral\" && `k-avatar--${tone}`, className)}\n      {...rest}\n    >\n      {showImage ? (\n        <img className=\"k-avatar__image\" src={src} alt=\"\" onError={() => setFailed(true)} />\n      ) : (\n        <span aria-hidden=\"true\">{initials(name, size === \"xs\" || size === \"sm\" ? 1 : 2)}</span>\n      )}\n      {status && <span className={`k-avatar__status k-avatar__status--${status}`} aria-hidden=\"true\" />}\n    </span>\n  );\n});\n\nexport interface AvatarGroupProps extends HTMLAttributes<HTMLDivElement> {\n  /** حداکثر تعداد نمایش؛ بقیه به شکل «+۳» */\n  max?: number;\n  /** اندازهٔ آواتار «+n» @default \"md\" */\n  size?: AvatarSize;\n  /** @default (n) => `${n} نفر دیگر` */\n  moreLabel?: (count: number) => string;\n  children: ReactNode;\n}\n\nexport function AvatarGroup({ max, size = \"md\", moreLabel, className, children, ...rest }: AvatarGroupProps) {\n  const { messages: M, n } = useKashi();\n  moreLabel ??= (x: number) => M.avatar.more(n(x));\n  const items = Children.toArray(children);\n  const visible = max ? items.slice(0, max) : items;\n  const extra = items.length - visible.length;\n  return (\n    <div role=\"group\" className={cx(\"k-avatar-group\", className)} {...rest}>\n      {visible}\n      {extra > 0 && (\n        <span role=\"img\" aria-label={moreLabel(extra)} className={cx(\"k-avatar\", size !== \"md\" && `k-avatar--${size}`)}>\n          <span aria-hidden=\"true\">+{n(extra)}</span>\n        </span>\n      )}\n    </div>\n  );\n}\n"
    }
  ]
}