{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "stepper",
  "title": "Stepper",
  "description": "Stepper component",
  "files": [
    {
      "path": "src/components/ui/stepper.tsx",
      "content": "import { Slot } from '@radix-ui/react-slot'\nimport { CheckIcon, LoaderCircleIcon } from 'lucide-react'\nimport * as React from 'react'\nimport { createContext, useContext } from 'react'\n\nimport { cn } from '@/lib/utils'\n\n// Types\ntype StepperContextValue = {\n\tactiveStep: number\n\tsetActiveStep: (step: number) => void\n\torientation: 'horizontal' | 'vertical'\n}\n\ntype StepItemContextValue = {\n\tstep: number\n\tstate: StepState\n\tisDisabled: boolean\n\tisLoading: boolean\n}\n\ntype StepState = 'active' | 'completed' | 'inactive' | 'loading'\n\n// Contexts\nconst StepperContext = createContext<StepperContextValue | undefined>(undefined)\nconst StepItemContext = createContext<StepItemContextValue | undefined>(\n\tundefined,\n)\n\nconst useStepper = () => {\n\tconst context = useContext(StepperContext)\n\tif (!context) {\n\t\tthrow new Error('useStepper must be used within a Stepper')\n\t}\n\treturn context\n}\n\nconst useStepItem = () => {\n\tconst context = useContext(StepItemContext)\n\tif (!context) {\n\t\tthrow new Error('useStepItem must be used within a StepperItem')\n\t}\n\treturn context\n}\n\n// Components\ninterface StepperProps extends React.HTMLAttributes<HTMLDivElement> {\n\tdefaultValue?: number\n\tvalue?: number\n\tonValueChange?: (value: number) => void\n\torientation?: 'horizontal' | 'vertical'\n}\n\nfunction Stepper({\n\tdefaultValue = 0,\n\tvalue,\n\tonValueChange,\n\torientation = 'horizontal',\n\tclassName,\n\t...props\n}: StepperProps) {\n\tconst [activeStep, setInternalStep] = React.useState(defaultValue)\n\n\tconst setActiveStep = React.useCallback(\n\t\t(step: number) => {\n\t\t\tif (value === undefined) {\n\t\t\t\tsetInternalStep(step)\n\t\t\t}\n\t\t\tonValueChange?.(step)\n\t\t},\n\t\t[value, onValueChange],\n\t)\n\n\tconst currentStep = value ?? activeStep\n\n\treturn (\n\t\t<StepperContext.Provider\n\t\t\tvalue={{\n\t\t\t\tactiveStep: currentStep,\n\t\t\t\torientation,\n\t\t\t\tsetActiveStep,\n\t\t\t}}\n\t\t>\n\t\t\t<div\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'group/stepper inline-flex data-[orientation=horizontal]:w-full data-[orientation=horizontal]:flex-row data-[orientation=vertical]:flex-col',\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\tdata-orientation={orientation}\n\t\t\t\tdata-slot=\"stepper\"\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t</StepperContext.Provider>\n\t)\n}\n\n// StepperItem\ninterface StepperItemProps extends React.HTMLAttributes<HTMLDivElement> {\n\tstep: number\n\tcompleted?: boolean\n\tdisabled?: boolean\n\tloading?: boolean\n}\n\nfunction StepperItem({\n\tstep,\n\tcompleted = false,\n\tdisabled = false,\n\tloading = false,\n\tclassName,\n\tchildren,\n\t...props\n}: StepperItemProps) {\n\tconst { activeStep } = useStepper()\n\n\tconst state: StepState =\n\t\tcompleted || step < activeStep\n\t\t\t? 'completed'\n\t\t\t: activeStep === step\n\t\t\t\t? 'active'\n\t\t\t\t: 'inactive'\n\n\tconst isLoading = loading && step === activeStep\n\n\treturn (\n\t\t<StepItemContext.Provider\n\t\t\tvalue={{ isDisabled: disabled, isLoading, state, step }}\n\t\t>\n\t\t\t<div\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'group/step flex items-center group-data-[orientation=horizontal]/stepper:flex-row group-data-[orientation=vertical]/stepper:flex-col',\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\tdata-slot=\"stepper-item\"\n\t\t\t\tdata-state={state}\n\t\t\t\t{...(isLoading ? { 'data-loading': true } : {})}\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t</div>\n\t\t</StepItemContext.Provider>\n\t)\n}\n\n// StepperTrigger\ninterface StepperTriggerProps\n\textends React.ButtonHTMLAttributes<HTMLButtonElement> {\n\tasChild?: boolean\n}\n\nfunction StepperTrigger({\n\tasChild = false,\n\tclassName,\n\tchildren,\n\t...props\n}: StepperTriggerProps) {\n\tconst { setActiveStep } = useStepper()\n\tconst { step, isDisabled } = useStepItem()\n\n\tif (asChild) {\n\t\tconst Comp = asChild ? Slot : 'span'\n\t\treturn (\n\t\t\t<Comp className={className} data-slot=\"stepper-trigger\">\n\t\t\t\t{children}\n\t\t\t</Comp>\n\t\t)\n\t}\n\n\treturn (\n\t\t<button\n\t\t\tclassName={cn(\n\t\t\t\t'inline-flex items-center gap-3 rounded-full outline-none focus-visible:z-10 focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50',\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\tdata-slot=\"stepper-trigger\"\n\t\t\tdisabled={isDisabled}\n\t\t\tonClick={() => setActiveStep(step)}\n\t\t\ttype=\"button\"\n\t\t\t{...props}\n\t\t>\n\t\t\t{children}\n\t\t</button>\n\t)\n}\n\n// StepperIndicator\ninterface StepperIndicatorProps extends React.HTMLAttributes<HTMLDivElement> {\n\tasChild?: boolean\n}\n\nfunction StepperIndicator({\n\tasChild = false,\n\tclassName,\n\tchildren,\n\t...props\n}: StepperIndicatorProps) {\n\tconst { state, step, isLoading } = useStepItem()\n\n\treturn (\n\t\t<span\n\t\t\tclassName={cn(\n\t\t\t\t'relative flex size-6 shrink-0 items-center justify-center rounded-full bg-muted font-medium text-muted-foreground text-xs data-[state=active]:bg-primary data-[state=completed]:bg-primary data-[state=active]:text-primary-foreground data-[state=completed]:text-primary-foreground',\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\tdata-slot=\"stepper-indicator\"\n\t\t\tdata-state={state}\n\t\t\t{...props}\n\t\t>\n\t\t\t{asChild ? (\n\t\t\t\tchildren\n\t\t\t) : (\n\t\t\t\t<>\n\t\t\t\t\t<span className=\"transition-all group-data-[state=completed]/step:scale-0 group-data-loading/step:scale-0 group-data-[state=completed]/step:opacity-0 group-data-loading/step:opacity-0 group-data-loading/step:transition-none\">\n\t\t\t\t\t\t{step}\n\t\t\t\t\t</span>\n\t\t\t\t\t<CheckIcon\n\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\tclassName=\"absolute scale-0 opacity-0 transition-all group-data-[state=completed]/step:scale-100 group-data-[state=completed]/step:opacity-100\"\n\t\t\t\t\t\tsize={16}\n\t\t\t\t\t/>\n\t\t\t\t\t{isLoading && (\n\t\t\t\t\t\t<span className=\"absolute transition-all\">\n\t\t\t\t\t\t\t<LoaderCircleIcon\n\t\t\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\t\t\tclassName=\"animate-spin\"\n\t\t\t\t\t\t\t\tsize={14}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</span>\n\t\t\t\t\t)}\n\t\t\t\t</>\n\t\t\t)}\n\t\t</span>\n\t)\n}\n\n// StepperTitle\nfunction StepperTitle({\n\tclassName,\n\t...props\n}: React.HTMLAttributes<HTMLHeadingElement>) {\n\treturn (\n\t\t<h3\n\t\t\tclassName={cn('font-medium text-sm', className)}\n\t\t\tdata-slot=\"stepper-title\"\n\t\t\t{...props}\n\t\t/>\n\t)\n}\n\n// StepperDescription\nfunction StepperDescription({\n\tclassName,\n\t...props\n}: React.HTMLAttributes<HTMLParagraphElement>) {\n\treturn (\n\t\t<p\n\t\t\tclassName={cn('text-muted-foreground text-sm', className)}\n\t\t\tdata-slot=\"stepper-description\"\n\t\t\t{...props}\n\t\t/>\n\t)\n}\n\n// StepperSeparator\nfunction StepperSeparator({\n\tclassName,\n\t...props\n}: React.HTMLAttributes<HTMLDivElement>) {\n\treturn (\n\t\t<div\n\t\t\tclassName={cn(\n\t\t\t\t'm-0.5 bg-muted group-data-[orientation=horizontal]/stepper:h-0.5 group-data-[orientation=vertical]/stepper:h-12 group-data-[orientation=horizontal]/stepper:w-full group-data-[orientation=vertical]/stepper:w-0.5 group-data-[orientation=horizontal]/stepper:flex-1 group-data-[state=completed]/step:bg-primary',\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\tdata-slot=\"stepper-separator\"\n\t\t\t{...props}\n\t\t/>\n\t)\n}\n\nexport {\n\tStepper,\n\tStepperDescription,\n\tStepperIndicator,\n\tStepperItem,\n\tStepperSeparator,\n\tStepperTitle,\n\tStepperTrigger,\n}\n",
      "type": "registry:component",
      "target": "components/ui/stepper.tsx"
    }
  ],
  "type": "registry:component"
}