{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "registry-install-card",
  "title": "Registry Install Card",
  "description": "A registry install surface with copy actions, JSON links, and compact usage metrics.",
  "dependencies": [
    "lucide-react",
    "motion"
  ],
  "registryDependencies": [
    "badge",
    "button",
    "card",
    "separator"
  ],
  "files": [
    {
      "path": "registry/corr/components/registry-install-card.tsx",
      "content": "\"use client\"\n\nimport {\n  ActivityIcon,\n  ExternalLinkIcon,\n  FileJsonIcon,\n  TerminalIcon,\n} from \"lucide-react\"\n\nimport { AnimatedCopyButton } from \"./animated-copy-button\"\nimport { Badge } from \"@/components/ui/badge\"\nimport { Button } from \"@/components/ui/button\"\nimport {\n  Card,\n  CardContent,\n  CardFooter,\n  CardHeader,\n  CardTitle,\n} from \"@/components/ui/card\"\nimport { Separator } from \"@/components/ui/separator\"\nimport { cn } from \"@/lib/utils\"\n\nexport type RegistryInstallCardMetrics = {\n  pageViews?: number\n  installCopies?: number\n  sourceCopies?: number\n  registryFetches?: number\n}\n\nexport type RegistryInstallCardProps = {\n  name: string\n  title?: string\n  description?: string\n  installUrl: string\n  registryUrl?: string\n  installCommand?: string\n  metrics?: RegistryInstallCardMetrics\n  onCopyInstall?: () => void\n  onCopyRegistryUrl?: () => void\n  className?: string\n}\n\nfunction formatCount(value = 0) {\n  return new Intl.NumberFormat(\"en\", { notation: \"compact\" }).format(value)\n}\n\nfunction metricTotal(metrics?: RegistryInstallCardMetrics) {\n  if (!metrics) return 0\n\n  return (\n    (metrics.pageViews ?? 0) +\n    (metrics.installCopies ?? 0) +\n    (metrics.sourceCopies ?? 0) +\n    (metrics.registryFetches ?? 0)\n  )\n}\n\nexport function RegistryInstallCard({\n  name,\n  title = name,\n  description,\n  installUrl,\n  registryUrl = installUrl,\n  installCommand = `npx shadcn@latest add ${installUrl}`,\n  metrics,\n  onCopyInstall,\n  onCopyRegistryUrl,\n  className,\n}: RegistryInstallCardProps) {\n  const total = metricTotal(metrics)\n\n  return (\n    <Card className={cn(\"overflow-hidden\", className)}>\n      <CardHeader>\n        <div className=\"flex items-start justify-between gap-3\">\n          <div className=\"min-w-0\">\n            <CardTitle className=\"truncate text-base\">{title}</CardTitle>\n            {description ? (\n              <p className=\"mt-1 text-sm leading-6 text-muted-foreground\">\n                {description}\n              </p>\n            ) : null}\n          </div>\n          <Badge variant=\"secondary\" className=\"shrink-0\">\n            {name}\n          </Badge>\n        </div>\n      </CardHeader>\n      <CardContent className=\"space-y-4\">\n        <div className=\"min-w-0 rounded-md border bg-muted/30 p-3\">\n          <div className=\"mb-2 flex items-center gap-2 text-xs font-medium text-muted-foreground\">\n            <TerminalIcon className=\"size-3.5\" />\n            Install command\n          </div>\n          <div className=\"overflow-x-auto font-mono text-xs whitespace-nowrap\">\n            {installCommand}\n          </div>\n        </div>\n\n        {metrics ? (\n          <div className=\"grid grid-cols-2 gap-2 sm:grid-cols-4\">\n            {[\n              [\"Views\", metrics.pageViews],\n              [\"Installs\", metrics.installCopies],\n              [\"Source\", metrics.sourceCopies],\n              [\"JSON\", metrics.registryFetches],\n            ].map(([label, value]) => (\n              <div key={label} className=\"rounded-md border bg-background p-2\">\n                <div className=\"text-sm font-semibold tabular-nums\">\n                  {formatCount(Number(value ?? 0))}\n                </div>\n                <div className=\"mt-1 text-[11px] text-muted-foreground\">\n                  {label}\n                </div>\n              </div>\n            ))}\n          </div>\n        ) : null}\n      </CardContent>\n      <Separator />\n      <CardFooter className=\"flex flex-wrap items-center justify-between gap-2 p-3\">\n        <div className=\"inline-flex items-center gap-1.5 text-xs text-muted-foreground\">\n          <ActivityIcon className=\"size-3.5\" />\n          <span>{formatCount(total)} tracked actions</span>\n        </div>\n        <div className=\"flex items-center gap-2\">\n          <AnimatedCopyButton\n            value={registryUrl}\n            label=\"JSON\"\n            copiedLabel=\"Copied JSON\"\n            icon={<FileJsonIcon className=\"size-3.5\" />}\n            variant=\"outline\"\n            size=\"sm\"\n            className=\"min-w-20\"\n            onCopy={onCopyRegistryUrl}\n          />\n          <AnimatedCopyButton\n            value={installCommand}\n            label=\"Copy install\"\n            copiedLabel=\"Copied\"\n            size=\"sm\"\n            variant=\"default\"\n            onCopy={onCopyInstall}\n          />\n          <Button type=\"button\" variant=\"ghost\" size=\"icon-sm\" asChild>\n            <a href={registryUrl} target=\"_blank\" rel=\"noreferrer\">\n              <ExternalLinkIcon />\n              <span className=\"sr-only\">Open registry JSON</span>\n            </a>\n          </Button>\n        </div>\n      </CardFooter>\n    </Card>\n  )\n}\n",
      "type": "registry:component"
    },
    {
      "path": "registry/corr/components/animated-copy-button.tsx",
      "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { Check, Copy } from \"lucide-react\"\n\nimport { Button } from \"@/components/ui/button\"\nimport { cn } from \"@/lib/utils\"\n\nexport function AnimatedCopyButton({\n  value,\n  label = \"Copy\",\n  copiedLabel = \"Copied\",\n  resetDelay = 1200,\n  icon,\n  onCopy,\n  className,\n  variant = \"outline\",\n  ...props\n}: {\n  value: string\n  label?: string\n  copiedLabel?: string\n  resetDelay?: number\n  icon?: React.ReactNode\n  onCopy?: () => void\n} & Omit<\n  React.ComponentProps<typeof Button>,\n  \"children\" | \"onClick\" | \"type\"\n>) {\n  const [copied, setCopied] = React.useState(false)\n\n  async function copy() {\n    await navigator.clipboard.writeText(value)\n    setCopied(true)\n    onCopy?.()\n    window.setTimeout(() => setCopied(false), resetDelay)\n  }\n\n  return (\n    <Button\n      type=\"button\"\n      variant={variant}\n      onClick={copy}\n      className={cn(\"min-w-24\", className)}\n      {...props}\n    >\n      <span className=\"inline-flex items-center gap-1.5\">\n        <span\n          className=\"t-icon-swap inline-grid size-3.5 shrink-0 place-items-center\"\n          data-state={copied ? \"b\" : \"a\"}\n          aria-hidden=\"true\"\n        >\n          <span className=\"t-icon inline-flex size-3.5 items-center justify-center\" data-icon=\"a\">\n            {icon ?? <Copy className=\"size-3.5\" />}\n          </span>\n          <span className=\"t-icon inline-flex size-3.5 items-center justify-center\" data-icon=\"b\">\n            <Check className=\"size-3.5\" />\n          </span>\n        </span>\n        {copied ? copiedLabel : label}\n      </span>\n    </Button>\n  )\n}\n",
      "type": "registry:component"
    }
  ],
  "type": "registry:component"
}