{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "badge",
  "type": "registry:ui",
  "title": "Badge",
  "description": "Dependency-free inline status and metadata badge with constrained tone, variant, size, and decorative icon placement APIs.",
  "dependencies": [],
  "devDependencies": [],
  "registryDependencies": [
    "https://components.dethink.co.uk/r/dethink-base.json"
  ],
  "files": [
    {
      "path": "packages/components/src/components/badge/badge.tsx",
      "type": "registry:file",
      "target": "~/components/dethink/components/badge/badge.tsx",
      "content": "import { forwardRef, type HTMLAttributes, type ReactNode } from \"react\";\nimport { cn } from \"../../utils/cn\";\n\nexport type BadgeVariant = \"solid\" | \"soft\" | \"outline\" | \"subtle\";\nexport type BadgeTone =\n  \"neutral\" | \"primary\" | \"success\" | \"warning\" | \"destructive\" | \"info\";\nexport type BadgeSize = \"xs\" | \"sm\" | \"md\" | \"lg\";\nexport type BadgeIconPlacement = \"leading\" | \"trailing\";\n\nexport interface BadgeProps extends HTMLAttributes<HTMLSpanElement> {\n  variant?: BadgeVariant;\n  tone?: BadgeTone;\n  size?: BadgeSize;\n  icon?: ReactNode;\n  iconPlacement?: BadgeIconPlacement;\n  leadingIcon?: ReactNode;\n  trailingIcon?: ReactNode;\n}\n\nconst badgeBaseClasses =\n  \"inline-flex max-w-full shrink-0 items-center justify-center rounded-full border font-medium leading-none whitespace-nowrap align-baseline transition-colors contrast-more:border-current\";\n\nconst badgeVariantToneClasses: Record<\n  BadgeVariant,\n  Record<BadgeTone, string>\n> = {\n  solid: {\n    neutral: \"border-foreground bg-foreground text-background\",\n    primary: \"border-primary bg-primary text-primary-foreground\",\n    success: \"border-success bg-success text-success-foreground\",\n    warning: \"border-warning bg-warning text-warning-foreground\",\n    destructive:\n      \"border-destructive bg-destructive text-destructive-foreground\",\n    info: \"border-info bg-info text-info-foreground\",\n  },\n  soft: {\n    neutral: \"border-border bg-muted/70 text-foreground\",\n    primary: \"border-primary/20 bg-primary/10 text-foreground\",\n    success: \"border-success/25 bg-success/10 text-foreground\",\n    warning: \"border-warning/35 bg-warning/15 text-foreground\",\n    destructive: \"border-destructive/25 bg-destructive/10 text-foreground\",\n    info: \"border-info/25 bg-info/10 text-foreground\",\n  },\n  outline: {\n    neutral: \"border-border bg-background text-foreground\",\n    primary: \"border-primary/45 bg-background text-foreground\",\n    success: \"border-success/45 bg-background text-foreground\",\n    warning: \"border-warning/60 bg-background text-foreground\",\n    destructive: \"border-destructive/50 bg-background text-foreground\",\n    info: \"border-info/45 bg-background text-foreground\",\n  },\n  subtle: {\n    neutral: \"border-transparent bg-muted/35 text-foreground\",\n    primary: \"border-transparent bg-primary/5 text-foreground\",\n    success: \"border-transparent bg-success/10 text-foreground\",\n    warning: \"border-transparent bg-warning/10 text-foreground\",\n    destructive: \"border-transparent bg-destructive/10 text-foreground\",\n    info: \"border-transparent bg-info/10 text-foreground\",\n  },\n};\n\nconst badgeSizeClasses: Record<BadgeSize, string> = {\n  xs: \"[--badge-gap:var(--dt-space-1)] [--badge-min-height:calc(var(--dt-density-control)*0.52)] [--badge-px:var(--dt-space-1-5)] [--badge-py:0rem] text-[0.6875rem]\",\n  sm: \"[--badge-gap:var(--dt-space-1)] [--badge-min-height:calc(var(--dt-density-control)*0.6)] [--badge-px:var(--dt-space-2)] [--badge-py:var(--dt-space-0-5)] text-xs\",\n  md: \"[--badge-gap:var(--dt-space-1-5)] [--badge-min-height:calc(var(--dt-density-control)*0.72)] [--badge-px:var(--dt-space-2-5)] [--badge-py:var(--dt-space-1)] text-sm\",\n  lg: \"[--badge-gap:var(--dt-space-2)] [--badge-min-height:calc(var(--dt-density-control)*0.82)] [--badge-px:var(--dt-space-3)] [--badge-py:var(--dt-space-1)] text-sm\",\n};\n\nconst badgeIconBaseClasses =\n  \"pointer-events-none inline-flex shrink-0 items-center justify-center opacity-85\";\n\nconst badgeIconSizeClasses: Record<BadgeSize, string> = {\n  xs: \"size-3 [&>svg]:size-3\",\n  sm: \"size-3.5 [&>svg]:size-3.5\",\n  md: \"size-4 [&>svg]:size-4\",\n  lg: \"size-4 [&>svg]:size-4\",\n};\n\nexport function badgeClassNames({\n  className,\n  size = \"md\",\n  tone = \"neutral\",\n  variant = \"soft\",\n}: Pick<BadgeProps, \"className\" | \"size\" | \"tone\" | \"variant\"> = {}) {\n  return cn(\n    badgeBaseClasses,\n    badgeSizeClasses[size],\n    \"min-h-[var(--badge-min-height)] gap-[var(--badge-gap)] px-[var(--badge-px)] py-[var(--badge-py)]\",\n    badgeVariantToneClasses[variant][tone],\n    className,\n  );\n}\n\nfunction renderBadgeIcon(\n  icon: ReactNode,\n  slot: \"badge-leading-icon\" | \"badge-trailing-icon\",\n  size: BadgeSize,\n) {\n  if (!icon) {\n    return null;\n  }\n\n  return (\n    <span\n      aria-hidden=\"true\"\n      data-slot={slot}\n      className={cn(badgeIconBaseClasses, badgeIconSizeClasses[size])}\n    >\n      {icon}\n    </span>\n  );\n}\n\nexport const Badge = forwardRef<HTMLSpanElement, BadgeProps>(\n  (\n    {\n      children,\n      className,\n      icon,\n      iconPlacement = \"leading\",\n      leadingIcon,\n      size = \"md\",\n      tone = \"neutral\",\n      trailingIcon,\n      variant = \"soft\",\n      ...props\n    },\n    ref,\n  ) => {\n    const placedLeadingIcon =\n      icon && iconPlacement === \"leading\" ? icon : leadingIcon;\n    const placedTrailingIcon =\n      icon && iconPlacement === \"trailing\" ? icon : trailingIcon;\n\n    return (\n      <span\n        {...props}\n        ref={ref}\n        data-slot=\"badge\"\n        data-tone={tone}\n        data-variant={variant}\n        data-size={size}\n        data-icon-placement={icon ? iconPlacement : undefined}\n        className={badgeClassNames({ className, size, tone, variant })}\n      >\n        {renderBadgeIcon(placedLeadingIcon, \"badge-leading-icon\", size)}\n        {children}\n        {renderBadgeIcon(placedTrailingIcon, \"badge-trailing-icon\", size)}\n      </span>\n    );\n  },\n);\n\nBadge.displayName = \"Badge\";\n"
    },
    {
      "path": "packages/components/src/components/badge/index.ts",
      "type": "registry:file",
      "target": "~/components/dethink/components/badge/index.ts",
      "content": "export {\n  Badge,\n  badgeClassNames,\n  type BadgeIconPlacement,\n  type BadgeProps,\n  type BadgeSize,\n  type BadgeTone,\n  type BadgeVariant,\n} from \"./badge\";\n"
    },
    {
      "path": "packages/components/src/utils/cn.ts",
      "type": "registry:file",
      "target": "~/components/dethink/utils/cn.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}\n"
    }
  ]
}
