{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "poll",
  "title": "Poll",
  "author": "Ben Hofstetter <ben.hofstetter@gmail.com>",
  "description": "An interactive poll component with vote bars, result visibility modes, and response change support. Accepts poll data and vote callbacks.",
  "type": "registry:component",
  "categories": [
    "snax"
  ],
  "dependencies": [
    "lucide-react"
  ],
  "files": [
    {
      "path": "src/registry/components/poll/poll.tsx",
      "content": "\"use client\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Check } from \"lucide-react\"\n\nexport type PollOption = string | { text: string; image?: string }\n\nexport function getOptionText(opt: PollOption): string {\n  return typeof opt === \"string\" ? opt : opt?.text || \"\"\n}\n\nexport function Poll({\n  question,\n  description,\n  options = [],\n  pollType = \"classic\",\n  voteCounts = [],\n  votedIndex = null,\n  showResults = false,\n  allowResponseChange = false,\n  submitting = false,\n  onVote,\n  className,\n}: React.ComponentProps<\"div\"> & {\n  question: string\n  description?: string\n  options: PollOption[]\n  pollType?: \"classic\" | \"versus\" | \"binary\"\n  voteCounts?: number[]\n  votedIndex?: number | null\n  showResults?: boolean\n  allowResponseChange?: boolean\n  submitting?: boolean\n  onVote?: (index: number) => void\n}) {\n  const totalVotes = (voteCounts || []).reduce((sum, v) => sum + (v || 0), 0)\n  const hasVoted = votedIndex !== null\n\n  return (\n    <div className={cn(\"rounded-md border bg-background p-5\", className)}>\n      <p className=\"mb-1.5 font-mono text-[0.6875rem] font-medium tracking-[0.2em] text-muted-foreground uppercase\">\n        {pollType === \"versus\" ? \"Versus Poll\" : pollType === \"binary\" ? \"Binary Poll\" : \"Poll\"}\n      </p>\n      <h3 className=\"mb-1 text-lg font-medium tracking-tight text-balance\">{question}</h3>\n      {description && (\n        <p className=\"mb-4 text-sm text-muted-foreground text-balance\">{description}</p>\n      )}\n      <div className={pollType === \"versus\" ? \"grid grid-cols-2 gap-2\" : \"space-y-2\"}>\n        {options.map((option, index) => {\n          const votes = (voteCounts || [])[index] || 0\n          const pct = totalVotes > 0 ? Math.round((votes / totalVotes) * 100) : 0\n          const isVoted = votedIndex === index\n          return (\n            <button\n              key={index}\n              onClick={() => onVote?.(index)}\n              disabled={(hasVoted && !allowResponseChange) || submitting}\n              className={cn(\n                \"relative overflow-hidden rounded-md border px-3 py-2 text-left text-sm transition-all\",\n                isVoted ? \"border-foreground\" : hasVoted ? \"border-border\" : \"border-border hover:border-foreground\",\n                hasVoted && !allowResponseChange ? \"cursor-default\" : \"cursor-pointer\",\n              )}\n            >\n              {showResults && (\n                <div className=\"absolute inset-y-0 left-0 bg-foreground/8\" style={{ width: `${pct}%` }} />\n              )}\n              <span className=\"relative flex items-center justify-between gap-2\">\n                <span className=\"flex items-center gap-2\">\n                  {isVoted && <Check className=\"size-3.5\" />}\n                  {getOptionText(option)}\n                </span>\n                {showResults && <span className=\"font-mono text-xs text-muted-foreground\">{pct}%</span>}\n              </span>\n            </button>\n          )\n        })}\n      </div>\n      {showResults && totalVotes > 0 && (\n        <p className=\"mt-3 font-mono text-xs text-muted-foreground\">\n          {totalVotes} {totalVotes === 1 ? \"vote\" : \"votes\"}\n        </p>\n      )}\n      {hasVoted && allowResponseChange && (\n        <p className=\"mt-2 text-xs text-muted-foreground\">Click another option to change your vote.</p>\n      )}\n    </div>\n  )\n}",
      "type": "registry:component",
      "target": "@components/poll.tsx"
    }
  ]
}