{"$schema":"https://ui.shadcn.com/schema/registry-item.json","name":"stepper","type":"registry:component","title":"Stepper","description":"Numbered steps joined by a line that fills as you move forward. Finished steps trade their number for a check and can be clicked to go back.","author":"Ryan","dependencies":["clsx","lucide-react","tailwind-merge"],"registryDependencies":[],"files":[{"path":"components/motion/stepper.tsx","type":"registry:component","target":"@components/motion/stepper.tsx","content":"\"use client\";\n// easeui.dev/components/motion/stepper\n\nimport { Check } from \"lucide-react\";\nimport { cn } from \"@/lib/utils\";\n\nexport interface StepperStep {\n  label: string;\n  /** A short line under the label. */\n  description?: string;\n}\n\nexport interface StepperProps {\n  steps: StepperStep[];\n  /** The step in progress, counting from 0. Steps before it show as done. */\n  current: number;\n  /** Lets people jump back to a finished step. Leave unset to make the steps display only. */\n  onStepClick?: (index: number) => void;\n  className?: string;\n}\n\n/**\n * Numbered steps joined by a line that fills as you move forward. Finished steps trade their\n * number for a check, and the line between two steps fills from the left.\n */\nexport function Stepper({ steps, current, onStepClick, className }: StepperProps) {\n  return (\n    <ol className={cn(\"flex w-full items-start\", className)}>\n      {steps.map((step, index) => {\n        const done = index < current;\n        const active = index === current;\n        const clickable = Boolean(onStepClick) && done;\n        const Tag = clickable ? \"button\" : \"div\";\n\n        return (\n          <li key={step.label} className={cn(\"relative flex min-w-0 flex-col items-center\", index < steps.length - 1 ? \"flex-1\" : \"\")}>\n            {index < steps.length - 1 ? (\n              // The line to the next step. It sits behind the circles and fills from the left.\n              <span aria-hidden=\"true\" className=\"absolute left-[calc(50%+18px)] right-[calc(-50%+18px)] top-4 h-0.5 overflow-hidden rounded-full bg-foreground/10\">\n                <span\n                  className=\"block h-full origin-left rounded-full bg-accent transition-transform duration-300 ease-out motion-reduce:transition-none\"\n                  style={{ transform: `scaleX(${done ? 1 : 0})` }}\n                />\n              </span>\n            ) : null}\n\n            <Tag\n              {...(clickable ? { type: \"button\" as const, onClick: () => onStepClick?.(index) } : {})}\n              aria-current={active ? \"step\" : undefined}\n              className={cn(\n                \"relative flex flex-col items-center gap-2 rounded-lg px-1 text-center outline-none\",\n                clickable && \"cursor-pointer focus-visible:ring-2 focus-visible:ring-foreground/40\",\n              )}\n            >\n              {/* Number and check share one spot and crossfade, so the circle never changes size. */}\n              <span\n                className={cn(\n                  \"relative grid h-8 w-8 place-items-center rounded-full text-sm font-medium tabular-nums transition-[background-color,color,box-shadow] duration-200 ease-out\",\n                  done && \"bg-accent text-accent-foreground\",\n                  active && \"bg-background text-foreground shadow-[0_0_0_2px_var(--accent)]\",\n                  !done && !active && \"bg-background text-muted-foreground shadow-[0_0_0_1px_var(--border-strong)]\",\n                )}\n              >\n                <span className={cn(\"col-start-1 row-start-1 transition-[opacity,scale] duration-200 ease-out\", done ? \"scale-50 opacity-0\" : \"scale-100 opacity-100\")}>\n                  {index + 1}\n                </span>\n                <Check\n                  aria-hidden=\"true\"\n                  strokeWidth={3}\n                  className={cn(\"col-start-1 row-start-1 h-4 w-4 transition-[opacity,scale] duration-200 ease-out\", done ? \"scale-100 opacity-100\" : \"scale-50 opacity-0\")}\n                />\n              </span>\n              <span className=\"flex max-w-32 flex-col gap-0.5\">\n                <span className={cn(\"truncate text-sm font-medium transition-colors duration-200\", active || done ? \"text-foreground\" : \"text-muted-foreground\")}>\n                  {step.label}\n                </span>\n                {step.description ? <span className=\"hidden truncate text-xs text-muted-foreground sm:block\">{step.description}</span> : null}\n              </span>\n              <span className=\"sr-only\">{done ? \", done\" : active ? \", current step\" : \"\"}</span>\n            </Tag>\n          </li>\n        );\n      })}\n    </ol>\n  );\n}\n"},{"path":"lib/utils.ts","type":"registry:lib","target":"@lib/utils.ts","content":"import { clsx, type ClassValue } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\nexport function cn(...inputs: ClassValue[]) {\n  return twMerge(clsx(inputs))\n}\n"}]}