{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "quiz",
  "title": "Quiz",
  "author": "Ben Hofstetter <ben.hofstetter@gmail.com>",
  "description": "An interactive quiz component for trivia and personality quizzes. Accepts questions (without correct answers) and a server-computed result. Never exposes correct_index to the client.",
  "type": "registry:component",
  "categories": [
    "snax"
  ],
  "dependencies": [
    "lucide-react"
  ],
  "files": [
    {
      "path": "src/registry/components/quiz/quiz.tsx",
      "content": "\"use client\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Check, X, RotateCcw } from \"lucide-react\"\n\nexport type QuizQuestion = {\n  question: string\n  options: string[]\n}\n\nexport type QuizResult = {\n  score: number\n  total: number\n  results: { question_index: number; correct: boolean }[]\n  result_profile?: { title: string; description?: string } | null\n}\n\nexport function Quiz({\n  title,\n  description,\n  questions = [],\n  isPersonality = false,\n  result = null,\n  answers = {},\n  submitted = false,\n  submitting = false,\n  onAnswer,\n  onSubmit,\n  onReset,\n  className,\n}: React.ComponentProps<\"div\"> & {\n  questions: QuizQuestion[]\n  isPersonality?: boolean\n  result?: QuizResult | null\n  answers?: Record<number, number>\n  submitted?: boolean\n  submitting?: boolean\n  onAnswer?: (questionIndex: number, optionIndex: number) => void\n  onSubmit?: () => void\n  onReset?: () => void\n}) {\n  const resultMap: Record<number, boolean> = {}\n  if (result?.results) {\n    for (const r of result.results) {\n      resultMap[r.question_index] = r.correct\n    }\n  }\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        {isPersonality ? \"Personality Quiz\" : \"Trivia Quiz\"}\n      </p>\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\n      <div className=\"space-y-5\">\n        {questions.map((q, qIndex) => (\n          <div key={qIndex}>\n            <p className=\"mb-2 text-sm font-medium\">\n              {qIndex + 1}. {q.question}\n            </p>\n            <div className=\"space-y-1.5\">\n              {(q.options || []).map((option, oIndex) => {\n                const isSelected = answers[qIndex] === oIndex\n                const isCorrect = submitted && resultMap[qIndex] === true && isSelected\n                const isWrong = submitted && resultMap[qIndex] === false && isSelected\n                return (\n                  <button\n                    key={oIndex}\n                    onClick={() => !submitted && onAnswer?.(qIndex, oIndex)}\n                    disabled={submitted}\n                    className={cn(\n                      \"flex w-full items-center gap-2 rounded-md border px-3 py-2 text-left text-sm transition-all\",\n                      isCorrect ? \"border-foreground\"\n                        : isWrong ? \"border-destructive\"\n                        : isSelected ? \"border-foreground\"\n                        : \"border-border hover:border-foreground\",\n                      submitted ? \"cursor-default\" : \"cursor-pointer\",\n                    )}\n                  >\n                    <span className=\"flex-1\">{option}</span>\n                    {isCorrect && <Check className=\"size-3.5\" />}\n                    {isWrong && <X className=\"size-3.5\" />}\n                  </button>\n                )\n              })}\n            </div>\n          </div>\n        ))}\n      </div>\n\n      <div className=\"mt-5 flex items-center gap-3\">\n        {!submitted ? (\n          <button\n            onClick={onSubmit}\n            disabled={submitting || Object.keys(answers).length < questions.length}\n            className=\"rounded-lg bg-primary px-4 py-1.5 text-sm font-medium text-primary-foreground transition-all hover:opacity-90 disabled:opacity-40\"\n          >\n            {submitting ? \"Submitting…\" : \"Submit Answers\"}\n          </button>\n        ) : (\n          <>\n            {!isPersonality && (\n              <p className=\"text-sm font-medium\">\n                Score: {result?.score ?? 0} / {result?.total ?? questions.length}\n              </p>\n            )}\n            {isPersonality && result?.result_profile && (\n              <div>\n                <p className=\"text-sm font-medium\">{result.result_profile.title}</p>\n                {result.result_profile.description && (\n                  <p className=\"text-sm text-muted-foreground\">{result.result_profile.description}</p>\n                )}\n              </div>\n            )}\n            <button\n              onClick={onReset}\n              className=\"flex items-center gap-1.5 rounded-lg border border-input px-3 py-1.5 text-sm hover:bg-accent transition-all\"\n            >\n              <RotateCcw className=\"size-3.5\" /> Try Again\n            </button>\n          </>\n        )}\n      </div>\n    </div>\n  )\n}",
      "type": "registry:component",
      "target": "@components/quiz.tsx"
    }
  ]
}