{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "quiz-assessment-runner",
  "title": "Quiz Assessment Runner",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-react/blocks/quiz-assessment-runner/QuizAssessmentRunner.tsx",
      "content": "'use client'\n\nimport * as React from 'react'\nimport {\n  AlertCircle,\n  Check,\n  CheckCircle2,\n  ChevronLeft,\n  ChevronRight,\n  Clock,\n  FileCode,\n  Flag,\n  Lightbulb,\n  LogOut,\n  RotateCcw,\n  XCircle,\n} from 'lucide-react'\nimport { cn } from '@/lib/utils'\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@/components/ui/card'\nimport {\n  Dialog,\n  DialogContent,\n  DialogDescription,\n  DialogFooter,\n  DialogHeader,\n  DialogTitle,\n} from '@/components/ui/dialog'\nimport { Progress } from '@/components/ui/progress'\nimport { Separator } from '@/components/ui/separator'\n\nexport interface QuizOption {\n  id: string\n  text: string\n}\n\nexport interface QuizQuestion {\n  id: number\n  category: string\n  prompt: string\n  codeSnippet?: string\n  codeLanguage?: string\n  options: QuizOption[]\n  correctOptionId: string\n  explanation: string\n}\n\nexport interface QuizAssessmentRunnerProps {\n  initialQuestion?: number\n  initialTimeRemaining?: number\n  initialAnswers?: Record<number, string>\n  initialFlagged?: number[]\n  initialSubmitted?: boolean\n  className?: string\n}\n\nconst defaultQuestions: QuizQuestion[] = [\n  {\n    id: 1,\n    category: 'Architecture',\n    prompt:\n      'What is the primary architectural difference between a UI Primitive and a UI Block in the UIPKGE component registry?',\n    codeSnippet: `// Primitive (registry:ui) vs Block (registry:block)\\nconst Primitive = <Button variant=\"outline\">Save Changes</Button>\\nconst Block = <QuizAssessmentRunner initialQuestion={1} />`,\n    codeLanguage: 'TypeScript',\n    options: [\n      {\n        id: 'A',\n        text: 'Primitives are pre-compiled npm packages, while Blocks are static JSON schema files.',\n      },\n      {\n        id: 'B',\n        text: 'Primitives encapsulate low-level mechanics and styling tokens, while Blocks compose primitives into transparent, copy-pastable domain layouts.',\n      },\n      {\n        id: 'C',\n        text: 'Primitives can only be rendered server-side, while Blocks require client-side WebSockets.',\n      },\n      {\n        id: 'D',\n        text: 'Primitives require Zod runtime validation schemas, while Blocks only support TypeScript interfaces.',\n      },\n    ],\n    correctOptionId: 'B',\n    explanation:\n      'In the UIPKGE architecture, primitives (registry:ui) encapsulate accessibility, focus states, and styling tokens, whereas blocks (registry:block) compose those primitives raw into unabstracted layouts where developers own and customize the code.',\n  },\n  {\n    id: 2,\n    category: 'Vue 3.5 SSR',\n    prompt:\n      'Why must CVA (Class Variance Authority) variant functions in Vue registry components be placed in a dedicated `<name>.variants.ts` file rather than `index.ts`?',\n    codeSnippet: `// button.variants.ts\\nexport const buttonVariants = cva(...)\\n\\n// Button.vue\\nimport { buttonVariants } from './button.variants'\\n\\n// index.ts\\nexport { default as Button } from './Button.vue'\\nexport { buttonVariants } from './button.variants'`,\n    codeLanguage: 'TypeScript',\n    options: [\n      {\n        id: 'A',\n        text: 'To comply with ECMAScript dynamic tree-shaking requirements for bundlers.',\n      },\n      {\n        id: 'B',\n        text: 'To prevent Vue SSR circular module dependency deadlocks where $setup.xxxVariants is undefined at runtime.',\n      },\n      {\n        id: 'C',\n        text: 'Because TypeScript forbids exporting types and constants from the same index file.',\n      },\n      {\n        id: 'D',\n        text: 'To enable hot-module replacement specifically for PostCSS variable transformations.',\n      },\n    ],\n    correctOptionId: 'B',\n    explanation:\n      'Circular imports between Component.vue and index.ts cause runtime evaluation failures during SSR/SSG pre-rendering, resulting in \"$setup.xxxVariants is not a function\" errors.',\n  },\n  {\n    id: 3,\n    category: 'Design Tokens',\n    prompt: \"Which Tailwind CSS v4 directive establishes the OKLCH design token mapping in UIPKGE's theme layer?\",\n    codeSnippet: `@theme inline {\\n  --color-background: var(--background);\\n  --color-foreground: var(--foreground);\\n  --color-primary: var(--primary);\\n  --color-card: var(--card);\\n}`,\n    codeLanguage: 'CSS',\n    options: [\n      {\n        id: 'A',\n        text: '@apply tokens.oklch;',\n      },\n      {\n        id: 'B',\n        text: '@theme inline',\n      },\n      {\n        id: 'C',\n        text: \"@config 'tailwind.theme.ts';\",\n      },\n      {\n        id: 'D',\n        text: '@utility theme-variables;',\n      },\n    ],\n    correctOptionId: 'B',\n    explanation:\n      'Tailwind CSS v4 uses `@theme inline` blocks to bind OKLCH CSS variables directly to Tailwind utility classes without needing a separate tailwind.config.js file.',\n  },\n  {\n    id: 4,\n    category: 'Reka UI / Vue',\n    prompt:\n      'When authoring polymorphic components in Vue 3.5 with Reka UI, which pattern cleanly strips the class prop for `cn()` forwarding?',\n    codeSnippet: `const props = defineProps<ButtonProps>()\\nconst delegatedProps = reactiveOmit(props, 'class')\\nconst forwarded = useForwardProps(delegatedProps)`,\n    codeLanguage: 'TypeScript',\n    options: [\n      {\n        id: 'A',\n        text: \"Directly passing v-bind='props' to the template without stripping the class prop.\",\n      },\n      {\n        id: 'B',\n        text: \"Using reactiveOmit(props, 'class') combined with useForwardProps and explicit :class='cn(...)'.\",\n      },\n      {\n        id: 'C',\n        text: 'Using Object.assign({}, props) inside an onMounted lifecycle hook.',\n      },\n      {\n        id: 'D',\n        text: \"Using v-bind='$attrs' with inheritAttrs: true set on the SFC.\",\n      },\n    ],\n    correctOptionId: 'B',\n    explanation:\n      'reactiveOmit from @vueuse/core strips the class attribute while retaining reactivity, allowing custom class names to merge via cn() on the root element.',\n  },\n  {\n    id: 5,\n    category: 'Design Craft',\n    prompt:\n      'Why is the sub-12px micro-text rule (avoiding `text-xs`, `text-xs`) strictly enforced in UIPKGE craft standards?',\n    codeSnippet: `// ❌ Anti-pattern:\\n<span class=\"text-xs uppercase text-muted-foreground\">Status</span>\\n\\n// ✅ Standard-compliant:\\n<span class=\"text-xs font-medium uppercase text-muted-foreground\">Status</span>`,\n    codeLanguage: 'HTML',\n    options: [\n      {\n        id: 'A',\n        text: 'Sub-12px text triggers subpixel antialiasing rendering bugs on macOS WebKit.',\n      },\n      {\n        id: 'B',\n        text: 'Arbitrary micro-text degrades legibility, violates WCAG AA contrast guidelines, and fragments typographic scale discipline.',\n      },\n      {\n        id: 'C',\n        text: 'Tailwind CSS v4 ignores arbitrary bracket pixel values in production builds.',\n      },\n      {\n        id: 'D',\n        text: 'Screen readers automatically skip DOM elements rendered smaller than 12px.',\n      },\n    ],\n    correctOptionId: 'B',\n    explanation:\n      'UIPKGE design craft mandates semantic typography starting at text-xs (12px) for badges and metadata to maintain readability and systematic hierarchy across devices.',\n  },\n  {\n    id: 6,\n    category: 'React Architecture',\n    prompt:\n      'In the React registry mirror, what headless primitive pattern allows consumers to pass custom trigger elements via `asChild`?',\n    codeSnippet: `const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\\n  ({ className, asChild = false, ...props }, ref) => {\\n    const Comp = asChild ? Slot : 'button'\\n    return <Comp data-slot=\"quiz-assessment-runner\" ref={ref} className={cn(buttonVariants(), className)} {...props} />\\n  }\\n)`,\n    codeLanguage: 'TSX',\n    options: [\n      {\n        id: 'A',\n        text: 'Radix UI Slot primitive forwarded with asChild boolean prop.',\n      },\n      {\n        id: 'B',\n        text: 'React cloneElement with recursive prop decoration.',\n      },\n      {\n        id: 'C',\n        text: 'Custom Shadow DOM web component injection.',\n      },\n      {\n        id: 'D',\n        text: 'Direct DOM mutation through React portal boundaries.',\n      },\n    ],\n    correctOptionId: 'A',\n    explanation:\n      'The Radix UI Slot primitive merges props and event listeners directly onto its immediate child, enabling seamless element composition without wrapper DIVs.',\n  },\n  {\n    id: 7,\n    category: 'Typography / UX',\n    prompt:\n      'Which CSS font utility prevents numerical values like timers, counters, and metrics from causing horizontal layout shift during updates?',\n    codeSnippet: `<div class=\"font-mono text-sm font-semibold tabular-nums text-foreground\">\\n  18:42 remaining\\n</div>`,\n    codeLanguage: 'HTML',\n    options: [\n      {\n        id: 'A',\n        text: 'tabular-nums (font-variant-numeric: tabular-nums)',\n      },\n      {\n        id: 'B',\n        text: 'font-stretch-condensed',\n      },\n      {\n        id: 'C',\n        text: 'tracking-tightest',\n      },\n      {\n        id: 'D',\n        text: 'text-balance',\n      },\n    ],\n    correctOptionId: 'A',\n    explanation:\n      'tabular-nums enforces uniform width for numerical glyphs (0-9), preventing visual jitter when numbers change in timers and live feeds.',\n  },\n  {\n    id: 8,\n    category: 'Registry Conventions',\n    prompt: 'What is the core rule regarding data arrays and tile layout abstractions when authoring UIPKGE blocks?',\n    codeSnippet: `// ✅ Allowed in blocks:\\n<div class=\"grid grid-cols-1 md:grid-cols-3 gap-4\">\\n  <Card><CardHeader><CardTitle>Total Revenue</CardTitle></CardHeader>...</Card>\\n  <Card><CardHeader><CardTitle>Active Users</CardTitle></CardHeader>...</Card>\\n</div>`,\n    codeLanguage: 'TSX',\n    options: [\n      {\n        id: 'A',\n        text: 'Always abstract card lists into a generic <StatCard items={data} /> primitive.',\n      },\n      {\n        id: 'B',\n        text: 'Blocks must compose primitives raw and top-to-bottom so developers can inspect and edit layout structure directly.',\n      },\n      {\n        id: 'C',\n        text: 'Never render more than two cards per block layout.',\n      },\n      {\n        id: 'D',\n        text: 'All block components must persist their state to IndexedDB storage.',\n      },\n    ],\n    correctOptionId: 'B',\n    explanation:\n      'UIPKGE explicitly bans monolithic StatCard-shaped primitives. Blocks must expose raw primitive composition inline so users have full ownership of the rendered markup.',\n  },\n  {\n    id: 9,\n    category: 'Accessibility (a11y)',\n    prompt:\n      'Which focus ring class pattern guarantees high-contrast keyboard accessibility without creating persistent outlines on mouse clicks?',\n    codeSnippet: `class=\"focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:outline-none\"`,\n    codeLanguage: 'HTML',\n    options: [\n      {\n        id: 'A',\n        text: 'focus:outline-none with no replacement outline or ring.',\n      },\n      {\n        id: 'B',\n        text: 'focus-visible:ring-2 focus-visible:ring-ring with visible focus ring tokens.',\n      },\n      {\n        id: 'C',\n        text: 'active:scale-95 on all interactive mouse events.',\n      },\n      {\n        id: 'D',\n        text: 'hover:border-destructive on standard form input elements.',\n      },\n    ],\n    correctOptionId: 'B',\n    explanation:\n      'focus-visible only applies the focus ring when keyboard navigation is detected, preserving clean aesthetics on mouse clicks while strictly satisfying WCAG 2.1 criteria.',\n  },\n  {\n    id: 10,\n    category: 'Registry Distribution',\n    prompt: 'What is the purpose of the `registryDependencies` array in `<name>.registry.ts` item manifests?',\n    codeSnippet: `export default defineRegistryItem({\\n  name: 'quiz-assessment-runner',\\n  type: 'registry:block',\\n  registryDependencies: [\\n    'https://uipkge.dev/r/badge.json',\\n    'https://uipkge.dev/r/button.json',\\n    'https://uipkge.dev/r/card.json',\\n  ],\\n})`,\n    codeLanguage: 'TypeScript',\n    options: [\n      {\n        id: 'A',\n        text: 'It publishes private registry tarballs directly to npmjs.com.',\n      },\n      {\n        id: 'B',\n        text: 'It instructs shadcn / shadcn-vue CLIs to transitively resolve and copy required UI primitives into the consumer project.',\n      },\n      {\n        id: 'C',\n        text: 'It configures Webpack chunk splitting for client-side routing.',\n      },\n      {\n        id: 'D',\n        text: 'It generates backend database migration tables automatically.',\n      },\n    ],\n    correctOptionId: 'B',\n    explanation:\n      'registryDependencies allows shadcn and shadcn-vue CLI tools to resolve and download all required component dependencies when installing a block.',\n  },\n]\n\nexport function QuizAssessmentRunner({\n  initialQuestion = 1,\n  initialTimeRemaining = 1122,\n  initialAnswers = {},\n  initialFlagged = [],\n  initialSubmitted = false,\n  className,\n}: QuizAssessmentRunnerProps) {\n  const totalQuestions = defaultQuestions.length\n  const [currentQuestionIndex, setCurrentQuestionIndex] = React.useState(\n    Math.max(0, Math.min(initialQuestion - 1, totalQuestions - 1)),\n  )\n  const [answers, setAnswers] = React.useState<Record<number, string>>(initialAnswers)\n  const [flagged, setFlagged] = React.useState<Set<number>>(new Set(initialFlagged))\n  const [timeRemaining, setTimeRemaining] = React.useState(initialTimeRemaining)\n  const [isSubmitted, setIsSubmitted] = React.useState(initialSubmitted)\n  const [isSubmitDialogOpen, setIsSubmitDialogOpen] = React.useState(false)\n  const [isExitDialogOpen, setIsExitDialogOpen] = React.useState(false)\n  const [reviewFilter, setReviewFilter] = React.useState<'all' | 'correct' | 'incorrect' | 'flagged'>('all')\n\n  React.useEffect(() => {\n    if (isSubmitted) return\n\n    const interval = setInterval(() => {\n      setTimeRemaining((prev) => {\n        if (prev <= 1) {\n          clearInterval(interval)\n          setIsSubmitted(true)\n          setIsSubmitDialogOpen(false)\n          return 0\n        }\n        return prev - 1\n      })\n    }, 1000)\n\n    return () => clearInterval(interval)\n  }, [isSubmitted])\n\n  const currentQuestion = defaultQuestions[currentQuestionIndex]\n\n  const answeredCount = Object.keys(answers).length\n  const flaggedCount = flagged.size\n  const unansweredCount = totalQuestions - answeredCount\n  const progressPercentage = Math.round((answeredCount / totalQuestions) * 100)\n\n  const correctCount = React.useMemo(() => {\n    return defaultQuestions.filter((q) => answers[q.id] === q.correctOptionId).length\n  }, [answers])\n\n  const incorrectCount = React.useMemo(() => {\n    return defaultQuestions.filter((q) => answers[q.id] && answers[q.id] !== q.correctOptionId).length\n  }, [answers])\n\n  const scorePercentage = Math.round((correctCount / totalQuestions) * 100)\n  const isPassed = scorePercentage >= 80\n\n  const gradeLabel = React.useMemo(() => {\n    if (scorePercentage >= 90) return 'Grade A (Mastery)'\n    if (scorePercentage >= 80) return 'Grade B (Proficient)'\n    if (scorePercentage >= 70) return 'Grade C (Needs Review)'\n    return 'Grade F (Did Not Pass)'\n  }, [scorePercentage])\n\n  const formattedTime = React.useMemo(() => {\n    const mins = Math.floor(Math.max(0, timeRemaining) / 60)\n    const secs = Math.max(0, timeRemaining) % 60\n    return `${String(mins).padStart(2, '0')}:${String(secs).padStart(2, '0')}`\n  }, [timeRemaining])\n\n  const timeSpentFormatted = React.useMemo(() => {\n    const spent = Math.max(0, initialTimeRemaining - timeRemaining)\n    const mins = Math.floor(spent / 60)\n    const secs = spent % 60\n    return `${mins}m ${String(secs).padStart(2, '0')}s`\n  }, [initialTimeRemaining, timeRemaining])\n\n  const filteredReviewQuestions = React.useMemo(() => {\n    if (reviewFilter === 'correct') {\n      return defaultQuestions.filter((q) => answers[q.id] === q.correctOptionId)\n    }\n    if (reviewFilter === 'incorrect') {\n      return defaultQuestions.filter((q) => answers[q.id] !== q.correctOptionId)\n    }\n    if (reviewFilter === 'flagged') {\n      return defaultQuestions.filter((q) => flagged.has(q.id))\n    }\n    return defaultQuestions\n  }, [reviewFilter, answers, flagged])\n\n  const toggleFlag = (questionId: number) => {\n    setFlagged((prev) => {\n      const next = new Set(prev)\n      if (next.has(questionId)) {\n        next.delete(questionId)\n      } else {\n        next.add(questionId)\n      }\n      return next\n    })\n  }\n\n  const selectOption = (optionId: string) => {\n    setAnswers((prev) => ({\n      ...prev,\n      [currentQuestion.id]: optionId,\n    }))\n  }\n\n  const goToQuestion = (index: number) => {\n    setCurrentQuestionIndex(Math.max(0, Math.min(index, totalQuestions - 1)))\n  }\n\n  const prevQuestion = () => {\n    if (currentQuestionIndex > 0) {\n      setCurrentQuestionIndex((prev) => prev - 1)\n    }\n  }\n\n  const nextQuestion = () => {\n    if (currentQuestionIndex < totalQuestions - 1) {\n      setCurrentQuestionIndex((prev) => prev + 1)\n    } else {\n      setIsSubmitDialogOpen(true)\n    }\n  }\n\n  const submitExam = () => {\n    setIsSubmitted(true)\n    setIsSubmitDialogOpen(false)\n  }\n\n  const retakeQuiz = () => {\n    setAnswers({})\n    setFlagged(new Set())\n    setTimeRemaining(initialTimeRemaining)\n    setCurrentQuestionIndex(0)\n    setIsSubmitted(false)\n    setReviewFilter('all')\n  }\n\n  const confirmExit = () => {\n    setIsExitDialogOpen(false)\n    retakeQuiz()\n  }\n\n  return (\n    <div className={cn('mx-auto w-full max-w-6xl space-y-6', className)}>\n      {/* ================================================================= */}\n      {/* VIEW 1: ACTIVE QUIZ EXAM RUNNER */}\n      {/* ================================================================= */}\n      {!isSubmitted ? (\n        <>\n          {/* Quiz Top Bar / Header */}\n          <Card className=\"border-border bg-card shadow-xs\">\n            <CardContent className=\"p-4 sm:p-5\">\n              <div className=\"flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between\">\n                <div className=\"space-y-1\">\n                  <div className=\"flex flex-wrap items-center gap-2\">\n                    <Badge variant=\"secondary\" className=\"text-xs font-medium\">\n                      Certification Assessment\n                    </Badge>\n                    <Badge variant=\"outline\" className=\"text-muted-foreground font-mono text-xs\">\n                      Exam #TS-804\n                    </Badge>\n                  </div>\n                  <h1 className=\"text-foreground text-base font-bold tracking-tight sm:text-lg\">\n                    TypeScript & Component Architecture Certification Quiz\n                  </h1>\n                </div>\n\n                <div className=\"flex flex-wrap items-center gap-2.5 sm:gap-3\">\n                  {/* Timer Pill */}\n                  <div\n                    className={cn(\n                      'flex items-center gap-2 rounded-lg border px-3 py-1.5 text-xs font-medium shadow-xs transition-colors',\n                      timeRemaining < 300\n                        ? 'border-destructive/40 bg-destructive/10 text-destructive'\n                        : 'border-border bg-muted/50 text-foreground',\n                    )}\n                  >\n                    <Clock className=\"size-3.5 shrink-0\" />\n                    <span className=\"font-mono font-semibold tabular-nums\">{formattedTime}</span>\n                    <span className=\"text-muted-foreground text-xs\">remaining</span>\n                  </div>\n\n                  {/* Question Counter Pill */}\n                  <Badge variant=\"outline\" className=\"h-8 px-2.5 text-xs font-medium tabular-nums\">\n                    Question {currentQuestionIndex + 1} of {totalQuestions}\n                  </Badge>\n\n                  {/* Exit Button */}\n                  <Button\n                    variant=\"ghost\"\n                    size=\"sm\"\n                    className=\"text-muted-foreground hover:text-foreground text-xs\"\n                    onClick={() => setIsExitDialogOpen(true)}\n                  >\n                    <LogOut className=\"mr-1.5 size-3.5\" />\n                    Exit Quiz\n                  </Button>\n                </div>\n              </div>\n            </CardContent>\n          </Card>\n\n          {/* 2-Column Quiz Canvas */}\n          <div className=\"grid grid-cols-1 items-start gap-6 lg:grid-cols-12\">\n            {/* Left: Question & Options Card */}\n            <div className=\"space-y-6 lg:col-span-8\">\n              <Card className=\"border-border shadow-xs\">\n                <CardHeader className=\"space-y-3 pb-4\">\n                  <div className=\"flex items-center justify-between gap-2\">\n                    <div className=\"flex items-center gap-2\">\n                      <Badge variant=\"secondary\" className=\"text-xs font-medium\">\n                        {currentQuestion.category}\n                      </Badge>\n                      <span className=\"text-muted-foreground text-xs font-medium tabular-nums\">\n                        Question {currentQuestionIndex + 1} of {totalQuestions}\n                      </span>\n                    </div>\n\n                    {/* Flag for Review Toggle Button */}\n                    <Button\n                      variant=\"outline\"\n                      size=\"sm\"\n                      className={cn(\n                        'text-xs',\n                        flagged.has(currentQuestion.id)\n                          ? 'border-warning/40 bg-warning/10 text-warning font-semibold'\n                          : 'text-muted-foreground hover:text-foreground',\n                      )}\n                      onClick={() => toggleFlag(currentQuestion.id)}\n                    >\n                      <Flag\n                        className={cn(\n                          'mr-1.5 size-3.5',\n                          flagged.has(currentQuestion.id) ? 'fill-warning text-warning' : '',\n                        )}\n                      />\n                      {flagged.has(currentQuestion.id) ? 'Flagged' : 'Flag for Review'}\n                    </Button>\n                  </div>\n\n                  {/* Question Prompt Text */}\n                  <CardTitle className=\"text-foreground text-base leading-relaxed font-semibold sm:text-lg\">\n                    {currentQuestion.prompt}\n                  </CardTitle>\n                </CardHeader>\n\n                <CardContent className=\"space-y-5\">\n                  {/* Code Snippet Box (if available) */}\n                  {currentQuestion.codeSnippet && (\n                    <div className=\"border-border/80 bg-muted/40 dark:bg-muted/20 overflow-hidden rounded-lg border\">\n                      <div className=\"border-border/70 bg-muted/80 dark:bg-muted/40 flex items-center justify-between border-b px-3.5 py-1.5\">\n                        <div className=\"flex items-center gap-2\">\n                          <FileCode className=\"text-muted-foreground size-3.5\" />\n                          <span className=\"text-muted-foreground font-mono text-xs font-medium\">\n                            {currentQuestion.codeLanguage || 'TypeScript'}\n                          </span>\n                        </div>\n                        <span className=\"text-muted-foreground font-mono text-xs\">Context</span>\n                      </div>\n                      <pre className=\"text-foreground/90 overflow-x-auto p-4 font-mono text-xs leading-relaxed whitespace-pre\">\n                        <code>{currentQuestion.codeSnippet}</code>\n                      </pre>\n                    </div>\n                  )}\n\n                  {/* 4 Radio Option Cards */}\n                  <div className=\"space-y-3\">\n                    <p className=\"text-muted-foreground text-xs font-semibold tracking-wider uppercase\">\n                      Select the correct answer:\n                    </p>\n\n                    <div className=\"grid gap-2.5\">\n                      {currentQuestion.options.map((opt) => {\n                        const isSelected = answers[currentQuestion.id] === opt.id\n                        return (\n                          <div\n                            key={opt.id}\n                            role=\"button\"\n                            tabIndex={0}\n                            className={cn(\n                              'group relative flex cursor-pointer items-start gap-3.5 rounded-lg border p-3.5 text-left transition-colors sm:p-4',\n                              'focus-visible:ring-ring select-none focus-visible:ring-2 focus-visible:outline-none',\n                              isSelected\n                                ? 'border-primary bg-primary/[0.04] dark:bg-primary/10 ring-primary shadow-xs ring-1'\n                                : 'border-border bg-card hover:bg-muted/40 hover:border-muted-foreground/30',\n                            )}\n                            onClick={() => selectOption(opt.id)}\n                            onKeyDown={(e) => {\n                              if (e.key === ' ' || e.key === 'Enter') {\n                                e.preventDefault()\n                                selectOption(opt.id)\n                              }\n                            }}\n                          >\n                            {/* Letter Circle Badge (A, B, C, D) */}\n                            <div\n                              className={cn(\n                                'mt-0.5 flex size-6 shrink-0 items-center justify-center rounded-full border text-xs font-bold transition-colors',\n                                isSelected\n                                  ? 'border-primary bg-primary text-primary-foreground'\n                                  : 'border-border bg-muted/60 text-muted-foreground group-hover:border-foreground/30 group-hover:text-foreground',\n                              )}\n                            >\n                              {opt.id}\n                            </div>\n\n                            {/* Option Text */}\n                            <div className=\"flex-1 space-y-0.5\">\n                              <p className=\"text-foreground text-sm leading-relaxed font-medium\">{opt.text}</p>\n                            </div>\n\n                            {/* Selected Check Icon */}\n                            {isSelected && (\n                              <div className=\"text-primary mt-0.5 shrink-0\">\n                                <Check className=\"size-4\" />\n                              </div>\n                            )}\n                          </div>\n                        )\n                      })}\n                    </div>\n                  </div>\n                </CardContent>\n\n                <CardFooter className=\"border-border bg-muted/10 flex flex-wrap items-center justify-between gap-3 border-t p-4 sm:p-5\">\n                  <Button\n                    variant=\"outline\"\n                    size=\"sm\"\n                    disabled={currentQuestionIndex === 0}\n                    className=\"text-xs\"\n                    onClick={prevQuestion}\n                  >\n                    <ChevronLeft className=\"mr-1 size-4\" />\n                    Previous Question\n                  </Button>\n\n                  <div className=\"flex items-center gap-2\">\n                    {currentQuestionIndex === totalQuestions - 1 ? (\n                      <Button\n                        variant=\"default\"\n                        size=\"sm\"\n                        className=\"text-xs font-medium\"\n                        onClick={() => setIsSubmitDialogOpen(true)}\n                      >\n                        <CheckCircle2 className=\"mr-1.5 size-4\" />\n                        Review & Submit\n                      </Button>\n                    ) : (\n                      <Button variant=\"default\" size=\"sm\" className=\"text-xs font-medium\" onClick={nextQuestion}>\n                        Save & Next\n                        <ChevronRight className=\"ml-1 size-4\" />\n                      </Button>\n                    )}\n                  </div>\n                </CardFooter>\n              </Card>\n            </div>\n\n            {/* Right: Question Navigation Sidebar */}\n            <div className=\"space-y-4 lg:sticky lg:top-6 lg:col-span-4\">\n              <Card className=\"border-border shadow-xs\">\n                <CardHeader className=\"pb-3\">\n                  <div className=\"flex items-center justify-between\">\n                    <CardTitle className=\"text-sm font-semibold\">Question Navigator</CardTitle>\n                    <Badge variant=\"outline\" className=\"font-mono text-xs tabular-nums\">\n                      {answeredCount}/{totalQuestions} done\n                    </Badge>\n                  </div>\n                  <CardDescription className=\"text-xs\">Jump directly to any question or review status.</CardDescription>\n                </CardHeader>\n\n                <CardContent className=\"space-y-4\">\n                  {/* Progress Bar */}\n                  <div className=\"space-y-1.5\">\n                    <div className=\"flex items-center justify-between text-xs\">\n                      <span className=\"text-muted-foreground font-medium\">Exam Progress</span>\n                      <span className=\"text-foreground font-semibold tabular-nums\">{progressPercentage}% Complete</span>\n                    </div>\n                    <Progress value={progressPercentage} className=\"h-2\" />\n                  </div>\n\n                  <Separator />\n\n                  {/* 10 Question Number Grid */}\n                  <div className=\"space-y-2\">\n                    <span className=\"text-muted-foreground text-xs font-semibold tracking-wider uppercase\">\n                      Questions\n                    </span>\n\n                    <div className=\"grid grid-cols-5 gap-2\">\n                      {defaultQuestions.map((q, idx) => {\n                        const isCurrent = idx === currentQuestionIndex\n                        const isAnswered = Boolean(answers[q.id])\n                        const isFlag = flagged.has(q.id)\n\n                        return (\n                          <button\n                            key={q.id}\n                            type=\"button\"\n                            className={cn(\n                              'relative flex size-10 items-center justify-center rounded-lg border text-xs font-semibold tabular-nums transition-colors',\n                              'focus-visible:ring-ring cursor-pointer focus-visible:ring-2 focus-visible:outline-none',\n                              isCurrent\n                                ? 'border-primary bg-primary/10 text-primary ring-primary font-bold shadow-xs ring-2'\n                                : isAnswered\n                                  ? 'border-success/30 bg-success/10 text-success hover:bg-success/20 text-success'\n                                  : isFlag\n                                    ? 'border-warning/30 bg-warning/10 text-warning hover:bg-warning/20 text-warning'\n                                    : 'border-border bg-muted/40 text-muted-foreground hover:bg-muted hover:text-foreground',\n                            )}\n                            onClick={() => goToQuestion(idx)}\n                          >\n                            {q.id}\n\n                            {/* Mini status indicator on badge */}\n                            {isFlag && !isCurrent && (\n                              <span\n                                className=\"ring-background bg-warning absolute -top-1 -right-1 size-2 rounded-full ring-2\"\n                                title=\"Flagged\"\n                              />\n                            )}\n                          </button>\n                        )\n                      })}\n                    </div>\n                  </div>\n\n                  {/* Legend */}\n                  <div className=\"border-border/70 bg-muted/30 space-y-2 rounded-lg border p-3 text-xs\">\n                    <span className=\"text-foreground font-medium\">Status Legend</span>\n                    <div className=\"text-muted-foreground grid grid-cols-2 gap-2\">\n                      <div className=\"flex items-center gap-1.5\">\n                        <span className=\"bg-success size-2 rounded-full\" />\n                        <span>Answered ({answeredCount})</span>\n                      </div>\n                      <div className=\"flex items-center gap-1.5\">\n                        <span className=\"bg-warning size-2 rounded-full\" />\n                        <span>Flagged ({flaggedCount})</span>\n                      </div>\n                      <div className=\"flex items-center gap-1.5\">\n                        <span className=\"bg-primary size-2 rounded-full\" />\n                        <span>Current</span>\n                      </div>\n                      <div className=\"flex items-center gap-1.5\">\n                        <span className=\"bg-muted-foreground/40 size-2 rounded-full\" />\n                        <span>Unanswered ({unansweredCount})</span>\n                      </div>\n                    </div>\n                  </div>\n\n                  <Separator />\n\n                  {/* Submit Button */}\n                  <Button\n                    variant=\"default\"\n                    className=\"h-10 w-full text-xs font-semibold shadow-xs\"\n                    onClick={() => setIsSubmitDialogOpen(true)}\n                  >\n                    <CheckCircle2 className=\"mr-2 size-4\" />\n                    Submit Exam\n                  </Button>\n                </CardContent>\n              </Card>\n            </div>\n          </div>\n        </>\n      ) : (\n        /* ================================================================= */\n        /* VIEW 2: QUIZ RESULTS SUMMARY SCREEN */\n        /* ================================================================= */\n        <div className=\"space-y-6\">\n          {/* Results Hero Score Card */}\n          <Card className=\"border-border bg-card overflow-hidden shadow-xs\">\n            <div className=\"border-border bg-muted/20 border-b p-6 sm:p-8\">\n              <div className=\"flex flex-col gap-6 sm:flex-row sm:items-center sm:justify-between\">\n                <div className=\"space-y-2\">\n                  <div className=\"flex flex-wrap items-center gap-2\">\n                    <Badge\n                      variant={isPassed ? 'secondary' : 'outline'}\n                      className={cn(\n                        'text-xs font-semibold',\n                        isPassed\n                          ? 'border-success/30 bg-success/10 text-success'\n                          : 'bg-destructive/10 text-destructive border-destructive/30',\n                      )}\n                    >\n                      {isPassed ? 'PASSED · CERTIFIED' : 'DID NOT PASS · RETAKE RECOMMENDED'}\n                    </Badge>\n                    <Badge variant=\"outline\" className=\"text-muted-foreground font-mono text-xs\">\n                      Exam Code #TS-804\n                    </Badge>\n                  </div>\n\n                  <h1 className=\"text-foreground text-2xl font-bold tracking-tight sm:text-3xl\">\n                    <span className=\"font-mono tabular-nums\">{scorePercentage}%</span> Score · {gradeLabel}\n                  </h1>\n                  <p className=\"text-muted-foreground max-w-xl text-sm\">\n                    {isPassed\n                      ? 'Congratulations! You have satisfied the technical competency standards for TypeScript and UIPKGE Component Architecture.'\n                      : 'You scored below the 80% certification threshold. Review the explanations below and retake the assessment when ready.'}\n                  </p>\n                </div>\n\n                <div className=\"flex shrink-0 items-center gap-3\">\n                  <Button variant=\"default\" size=\"sm\" className=\"text-xs font-semibold\" onClick={retakeQuiz}>\n                    <RotateCcw className=\"mr-1.5 size-3.5\" />\n                    Retake Exam\n                  </Button>\n                </div>\n              </div>\n            </div>\n\n            {/* 4 KPI Summary Cards */}\n            <CardContent className=\"p-6\">\n              <div className=\"grid grid-cols-2 gap-4 lg:grid-cols-4\">\n                <div className=\"border-border bg-card space-y-1 rounded-lg border p-4\">\n                  <span className=\"text-muted-foreground text-xs font-medium\">Total Score</span>\n                  <div className=\"text-foreground text-xl font-bold tabular-nums\">\n                    {correctCount} <span className=\"text-muted-foreground text-sm font-normal\">/ {totalQuestions}</span>\n                  </div>\n                  <div className=\"text-muted-foreground font-mono text-xs\">{scorePercentage}% accuracy</div>\n                </div>\n\n                <div className=\"border-border bg-card space-y-1 rounded-lg border p-4\">\n                  <span className=\"text-muted-foreground text-xs font-medium\">Result Status</span>\n                  <div className={cn('text-xl font-bold', isPassed ? 'text-success' : 'text-destructive')}>\n                    {isPassed ? 'Passed' : 'Failed'}\n                  </div>\n                  <div className=\"text-muted-foreground font-mono text-xs\">Passing threshold: 80%</div>\n                </div>\n\n                <div className=\"border-border bg-card space-y-1 rounded-lg border p-4\">\n                  <span className=\"text-muted-foreground text-xs font-medium\">Time Elapsed</span>\n                  <div className=\"text-foreground font-mono text-xl font-bold tabular-nums\">{timeSpentFormatted}</div>\n                  <div className=\"text-muted-foreground font-mono text-xs\">18m 42s allocated</div>\n                </div>\n\n                <div className=\"border-border bg-card space-y-1 rounded-lg border p-4\">\n                  <span className=\"text-muted-foreground text-xs font-medium\">Flagged Questions</span>\n                  <div className=\"text-foreground text-xl font-bold tabular-nums\">{flaggedCount}</div>\n                  <div className=\"text-muted-foreground font-mono text-xs\">Reviewed items</div>\n                </div>\n              </div>\n            </CardContent>\n          </Card>\n\n          {/* Question Review Section */}\n          <Card className=\"border-border shadow-xs\">\n            <CardHeader className=\"pb-4\">\n              <div className=\"flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between\">\n                <div>\n                  <CardTitle className=\"text-base font-semibold\">Answer Review & Explanations</CardTitle>\n                  <CardDescription className=\"text-xs\">\n                    Detailed technical breakdown for every question in the assessment.\n                  </CardDescription>\n                </div>\n\n                {/* Filter Buttons */}\n                <div className=\"flex flex-wrap items-center gap-1.5\">\n                  <Button\n                    variant={reviewFilter === 'all' ? 'default' : 'outline'}\n                    size=\"sm\"\n                    className=\"h-7.5 px-2.5 text-xs\"\n                    onClick={() => setReviewFilter('all')}\n                  >\n                    All ({totalQuestions})\n                  </Button>\n                  <Button\n                    variant={reviewFilter === 'correct' ? 'default' : 'outline'}\n                    size=\"sm\"\n                    className=\"h-7.5 px-2.5 text-xs\"\n                    onClick={() => setReviewFilter('correct')}\n                  >\n                    Correct ({correctCount})\n                  </Button>\n                  <Button\n                    variant={reviewFilter === 'incorrect' ? 'default' : 'outline'}\n                    size=\"sm\"\n                    className=\"h-7.5 px-2.5 text-xs\"\n                    onClick={() => setReviewFilter('incorrect')}\n                  >\n                    Incorrect ({incorrectCount})\n                  </Button>\n                  <Button\n                    variant={reviewFilter === 'flagged' ? 'default' : 'outline'}\n                    size=\"sm\"\n                    className=\"h-7.5 px-2.5 text-xs\"\n                    onClick={() => setReviewFilter('flagged')}\n                  >\n                    Flagged ({flaggedCount})\n                  </Button>\n                </div>\n              </div>\n            </CardHeader>\n\n            <CardContent className=\"space-y-4\">\n              {filteredReviewQuestions.map((q) => {\n                const isCorrect = answers[q.id] === q.correctOptionId\n                const isFlag = flagged.has(q.id)\n\n                return (\n                  <div\n                    key={q.id}\n                    className={cn(\n                      'space-y-4 rounded-lg border p-4 transition-colors sm:p-5',\n                      isCorrect\n                        ? 'border-success/30 bg-success/[0.02] bg-success/[0.05]'\n                        : 'border-destructive/30 bg-destructive/[0.02] dark:bg-destructive/[0.05]',\n                    )}\n                  >\n                    {/* Question Header */}\n                    <div className=\"flex flex-wrap items-center justify-between gap-2\">\n                      <div className=\"flex items-center gap-2\">\n                        <Badge variant=\"outline\" className=\"text-xs font-bold tabular-nums\">\n                          Question {q.id}\n                        </Badge>\n                        <Badge variant=\"secondary\" className=\"text-xs\">\n                          {q.category}\n                        </Badge>\n                        {isFlag && (\n                          <Badge variant=\"outline\" className=\"border-warning/40 bg-warning/10 text-warning text-xs\">\n                            <Flag className=\"fill-warning mr-1 size-3\" />\n                            Flagged\n                          </Badge>\n                        )}\n                      </div>\n\n                      <Badge\n                        variant={isCorrect ? 'secondary' : 'outline'}\n                        className={cn(\n                          'text-xs font-semibold',\n                          isCorrect\n                            ? 'border-success/30 bg-success/10 text-success'\n                            : 'bg-destructive/10 text-destructive border-destructive/30',\n                        )}\n                      >\n                        {isCorrect ? <CheckCircle2 className=\"mr-1 size-3.5\" /> : <XCircle className=\"mr-1 size-3.5\" />}\n                        {isCorrect ? 'Correct (+10 pts)' : answers[q.id] ? 'Incorrect (0 pts)' : 'Unanswered (0 pts)'}\n                      </Badge>\n                    </div>\n\n                    {/* Question Prompt */}\n                    <p className=\"text-foreground text-sm leading-relaxed font-semibold\">{q.prompt}</p>\n\n                    {/* Optional Context Snippet */}\n                    {q.codeSnippet && (\n                      <div className=\"border-border/80 bg-muted/40 dark:bg-muted/20 overflow-hidden rounded-md border\">\n                        <pre className=\"text-foreground/80 overflow-x-auto p-3 font-mono text-xs leading-relaxed whitespace-pre\">\n                          <code>{q.codeSnippet}</code>\n                        </pre>\n                      </div>\n                    )}\n\n                    {/* Answer Comparison Cards */}\n                    <div className=\"grid gap-2 sm:grid-cols-2\">\n                      {/* User's Answer */}\n                      <div\n                        className={cn(\n                          'space-y-1 rounded-md border p-3 text-xs',\n                          isCorrect\n                            ? 'border-success/30 bg-success/10 text-foreground text-success'\n                            : 'border-destructive/30 bg-destructive/10 text-destructive',\n                        )}\n                      >\n                        <span className=\"block text-xs font-semibold tracking-wider uppercase opacity-80\">\n                          Your Response:\n                        </span>\n                        <div className=\"font-medium\">\n                          {answers[q.id] ? (\n                            <>\n                              <span className=\"mr-1 font-bold\">Option {answers[q.id]}:</span>\n                              <span>{q.options.find((o) => o.id === answers[q.id])?.text}</span>\n                            </>\n                          ) : (\n                            'No answer submitted'\n                          )}\n                        </div>\n                      </div>\n\n                      {/* Correct Answer */}\n                      <div className=\"border-success/30 bg-success/10 text-foreground text-success space-y-1 rounded-md border p-3 text-xs\">\n                        <span className=\"block text-xs font-semibold tracking-wider uppercase opacity-80\">\n                          Correct Answer:\n                        </span>\n                        <div className=\"font-medium\">\n                          <span className=\"mr-1 font-bold\">Option {q.correctOptionId}:</span>\n                          <span>{q.options.find((o) => o.id === q.correctOptionId)?.text}</span>\n                        </div>\n                      </div>\n                    </div>\n\n                    {/* Technical Explanation Box */}\n                    <div className=\"border-border/80 bg-muted/40 text-muted-foreground space-y-1 rounded-md border p-3 text-xs\">\n                      <div className=\"text-foreground flex items-center gap-1.5 font-semibold\">\n                        <Lightbulb className=\"text-primary size-3.5\" />\n                        <span>Architectural Explanation:</span>\n                      </div>\n                      <p className=\"leading-relaxed\">{q.explanation}</p>\n                    </div>\n                  </div>\n                )\n              })}\n            </CardContent>\n\n            <CardFooter className=\"border-border bg-muted/10 flex items-center justify-between border-t p-4 sm:p-5\">\n              <span className=\"text-muted-foreground font-mono text-xs\">Exam ID: 804-FE-UIPKGE</span>\n              <Button variant=\"default\" size=\"sm\" className=\"text-xs\" onClick={retakeQuiz}>\n                <RotateCcw className=\"mr-1.5 size-3.5\" />\n                Retake Assessment\n              </Button>\n            </CardFooter>\n          </Card>\n        </div>\n      )}\n\n      {/* ================================================================= */}\n      {/* DIALOG: CONFIRM EXAM SUBMISSION */}\n      {/* ================================================================= */}\n      <Dialog open={isSubmitDialogOpen} onOpenChange={setIsSubmitDialogOpen}>\n        <DialogContent className=\"sm:max-w-md\">\n          <DialogHeader>\n            <DialogTitle className=\"text-base font-semibold\">Submit Assessment?</DialogTitle>\n            <DialogDescription className=\"text-xs\">\n              Review your completion status before finalizing your submission.\n            </DialogDescription>\n          </DialogHeader>\n\n          <div className=\"space-y-3 py-2 text-xs\">\n            <div className=\"grid grid-cols-3 gap-2 text-center\">\n              <div className=\"border-border bg-muted/40 space-y-0.5 rounded-lg border p-2.5\">\n                <span className=\"text-muted-foreground\">Answered</span>\n                <p className=\"text-foreground text-base font-bold tabular-nums\">\n                  {answeredCount}/{totalQuestions}\n                </p>\n              </div>\n              <div className=\"border-border bg-muted/40 space-y-0.5 rounded-lg border p-2.5\">\n                <span className=\"text-muted-foreground\">Flagged</span>\n                <p className=\"text-warning text-warning text-base font-bold tabular-nums\">{flaggedCount}</p>\n              </div>\n              <div className=\"border-border bg-muted/40 space-y-0.5 rounded-lg border p-2.5\">\n                <span className=\"text-muted-foreground\">Unanswered</span>\n                <p\n                  className={cn(\n                    'text-base font-bold tabular-nums',\n                    unansweredCount > 0 ? 'text-destructive' : 'text-foreground',\n                  )}\n                >\n                  {unansweredCount}\n                </p>\n              </div>\n            </div>\n\n            {unansweredCount > 0 && (\n              <div className=\"border-warning/30 bg-warning/10 text-warning flex items-start gap-2 rounded-lg border p-3 text-xs\">\n                <AlertCircle className=\"mt-0.5 size-4 shrink-0\" />\n                <p>\n                  You have{' '}\n                  <strong>\n                    {unansweredCount} unanswered question{unansweredCount === 1 ? '' : 's'}\n                  </strong>\n                  . Unanswered questions receive 0 points.\n                </p>\n              </div>\n            )}\n\n            <p className=\"text-muted-foreground text-xs\">\n              Once submitted, you will immediately receive your final score and detailed technical explanations.\n            </p>\n          </div>\n\n          <DialogFooter className=\"gap-2 sm:gap-0\">\n            <Button variant=\"outline\" size=\"sm\" className=\"text-xs\" onClick={() => setIsSubmitDialogOpen(false)}>\n              Continue Quiz\n            </Button>\n            <Button variant=\"default\" size=\"sm\" className=\"text-xs font-semibold\" onClick={submitExam}>\n              Confirm & Submit\n            </Button>\n          </DialogFooter>\n        </DialogContent>\n      </Dialog>\n\n      {/* ================================================================= */}\n      {/* DIALOG: CONFIRM EXIT */}\n      {/* ================================================================= */}\n      <Dialog open={isExitDialogOpen} onOpenChange={setIsExitDialogOpen}>\n        <DialogContent className=\"sm:max-w-md\">\n          <DialogHeader>\n            <DialogTitle className=\"text-base font-semibold\">Exit Assessment?</DialogTitle>\n            <DialogDescription className=\"text-xs\">\n              Are you sure you want to exit? Your answers for this session will be cleared.\n            </DialogDescription>\n          </DialogHeader>\n\n          <div className=\"text-muted-foreground py-2 text-xs\">\n            You have answered {answeredCount} of {totalQuestions} questions. Exiting now will reset your attempt.\n          </div>\n\n          <DialogFooter className=\"gap-2 sm:gap-0\">\n            <Button variant=\"outline\" size=\"sm\" className=\"text-xs\" onClick={() => setIsExitDialogOpen(false)}>\n              Cancel\n            </Button>\n            <Button variant=\"destructive\" size=\"sm\" className=\"text-xs\" onClick={confirmExit}>\n              Exit Quiz\n            </Button>\n          </DialogFooter>\n        </DialogContent>\n      </Dialog>\n    </div>\n  )\n}\n\nexport default QuizAssessmentRunner\n",
      "type": "registry:block",
      "target": "~/components/blocks/QuizAssessmentRunner.tsx"
    }
  ],
  "dependencies": [
    "lucide-react"
  ],
  "devDependencies": [],
  "registryDependencies": [
    "https://uipkge.dev/r/react/badge.json",
    "https://uipkge.dev/r/react/button.json",
    "https://uipkge.dev/r/react/card.json",
    "https://uipkge.dev/r/react/dialog.json",
    "https://uipkge.dev/r/react/progress.json",
    "https://uipkge.dev/r/react/separator.json"
  ],
  "description": "Interactive multiple-choice exam & quiz assessment runner: 2-column test canvas with real-time countdown timer, question navigator grid with status indicators (completed, active, flagged, unanswered), syntax-highlighted code snippets, single-choice selection cards, submit confirmation modal, and comprehensive score breakdown with review explanations.",
  "categories": [
    "education",
    "app"
  ]
}