{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "ranked-list",
  "title": "Ranked List",
  "author": "Ben Hofstetter <ben.hofstetter@gmail.com>",
  "description": "An interactive ranked list with optional community voting, item links, and descriptions. Accepts items as props.",
  "type": "registry:component",
  "categories": [
    "snax"
  ],
  "dependencies": [
    "lucide-react"
  ],
  "files": [
    {
      "path": "src/registry/components/ranked-list/ranked-list.tsx",
      "content": "\"use client\"\n\nimport { cn } from \"@/lib/utils\"\nimport { ArrowUp, ExternalLink } from \"lucide-react\"\nimport { useState } from \"react\"\n\nexport type RankedItem = {\n  title: string\n  description?: string\n  url?: string\n  image?: string\n  votes?: number\n}\n\nexport function RankedList({\n  title,\n  description,\n  items = [],\n  votingEnabled = false,\n  className,\n}: React.ComponentProps<\"div\"> & {\n  title: string\n  description?: string\n  items: RankedItem[]\n  votingEnabled?: boolean\n}) {\n  const [voteState, setVoteState] = useState<Record<number, boolean>>({})\n\n  const handleVote = (index: number) => {\n    setVoteState((prev) => ({ ...prev, [index]: !prev[index] }))\n  }\n\n  return (\n    <div className={cn(\"rounded-md border bg-background p-5\", className)}>\n      <h3 className=\"mb-1 text-lg font-medium tracking-tight\">{title}</h3>\n      {description && (\n        <p className=\"mb-4 text-sm text-muted-foreground text-balance\">{description}</p>\n      )}\n      <ol className=\"space-y-2\">\n        {items.map((item, index) => {\n          const voteCount = (item.votes || 0) + (voteState[index] ? 1 : 0)\n          const hasVoted = voteState[index] === true\n          return (\n            <li\n              key={index}\n              className=\"flex items-start gap-3 rounded-md border border-border p-3\"\n            >\n              <span className=\"flex size-6 shrink-0 items-center justify-center rounded-full bg-muted font-mono text-xs font-medium\">\n                {index + 1}\n              </span>\n              <div className=\"min-w-0 flex-1\">\n                <div className=\"flex items-center gap-2\">\n                  <p className=\"truncate text-sm font-medium\">{item.title}</p>\n                  {item.url && (\n                    <a\n                      href={item.url}\n                      target=\"_blank\"\n                      rel=\"noopener noreferrer\"\n                      className=\"text-muted-foreground hover:text-foreground\"\n                    >\n                      <ExternalLink className=\"size-3\" />\n                    </a>\n                  )}\n                </div>\n                {item.description && (\n                  <p className=\"mt-0.5 text-xs text-muted-foreground\">{item.description}</p>\n                )}\n              </div>\n              {votingEnabled && (\n                <button\n                  onClick={() => handleVote(index)}\n                  className={cn(\n                    \"flex flex-col items-center gap-0.5 rounded-md border px-2 py-1 text-xs transition-all\",\n                    hasVoted ? \"border-foreground bg-foreground text-background\" : \"border-border hover:border-foreground\",\n                  )}\n                >\n                  <ArrowUp className=\"size-3\" />\n                  <span className=\"font-mono\">{voteCount}</span>\n                </button>\n              )}\n            </li>\n          )\n        })}\n      </ol>\n    </div>\n  )\n}",
      "type": "registry:component",
      "target": "@components/ranked-list.tsx"
    }
  ]
}