{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "stepper",
  "title": "Stepper",
  "description": "A composable sequence indicator with controlled progress, step navigation, and horizontal or vertical layouts.",
  "files": [
    {
      "path": "registry/rivetui/components/stepper/stepper.tsx",
      "content": "\"use client\";\n\nimport * as React from \"react\";\n\nimport { cn } from \"@/lib/utils\";\n\ntype StepperOrientation = \"horizontal\" | \"vertical\";\ntype StepperState = \"complete\" | \"current\" | \"upcoming\";\n\ntype StepperContextValue = {\n  disabled: boolean;\n  orientation: StepperOrientation;\n  value: number;\n  setValue: (value: number) => void;\n};\n\ntype StepperItemContextValue = {\n  disabled: boolean;\n  orientation: StepperOrientation;\n  state: StepperState;\n  step: number;\n  setValue: (value: number) => void;\n};\n\nconst StepperContext = React.createContext<StepperContextValue | null>(null);\nconst StepperItemContext = React.createContext<StepperItemContextValue | null>(null);\n\nfunction useStepperContext() {\n  const context = React.useContext(StepperContext);\n\n  if (!context) {\n    throw new Error(\"Stepper components must be used within <Stepper>.\");\n  }\n\n  return context;\n}\n\nfunction useStepperItemContext() {\n  const context = React.useContext(StepperItemContext);\n\n  if (!context) {\n    throw new Error(\"Stepper item components must be used within <StepperItem>.\");\n  }\n\n  return context;\n}\n\ntype StepperProps = Omit<React.ComponentProps<\"ol\">, \"defaultValue\" | \"onChange\"> & {\n  value?: number;\n  defaultValue?: number;\n  onValueChange?: (value: number) => void;\n  orientation?: StepperOrientation;\n  disabled?: boolean;\n};\n\nfunction Stepper({\n  value,\n  defaultValue = 1,\n  onValueChange,\n  orientation = \"horizontal\",\n  disabled = false,\n  className,\n  ...props\n}: StepperProps) {\n  const [internalValue, setInternalValue] = React.useState(defaultValue);\n  const currentValue = value ?? internalValue;\n\n  function setValue(nextValue: number) {\n    if (disabled || nextValue === currentValue) {\n      return;\n    }\n\n    if (value === undefined) {\n      setInternalValue(nextValue);\n    }\n\n    onValueChange?.(nextValue);\n  }\n\n  return (\n    <StepperContext.Provider value={{ disabled, orientation, value: currentValue, setValue }}>\n      <ol\n        data-slot=\"stepper\"\n        data-orientation={orientation}\n        data-disabled={disabled ? \"\" : undefined}\n        className={cn(\n          \"flex w-full min-w-0 data-[orientation=horizontal]:overflow-x-auto data-[orientation=horizontal]:[scrollbar-width:none] data-[orientation=vertical]:flex-col data-[orientation=horizontal]:[&::-webkit-scrollbar]:hidden\",\n          className,\n        )}\n        {...props}\n      />\n    </StepperContext.Provider>\n  );\n}\n\ntype StepperItemProps = React.ComponentProps<\"li\"> & {\n  step: number;\n  disabled?: boolean;\n};\n\nfunction StepperItem({ step, disabled = false, className, ...props }: StepperItemProps) {\n  const stepper = useStepperContext();\n  const isDisabled = stepper.disabled || disabled;\n  const state: StepperState =\n    step === stepper.value ? \"current\" : step < stepper.value ? \"complete\" : \"upcoming\";\n\n  return (\n    <StepperItemContext.Provider\n      value={{\n        disabled: isDisabled,\n        orientation: stepper.orientation,\n        state,\n        step,\n        setValue: stepper.setValue,\n      }}\n    >\n      <li\n        data-slot=\"stepper-item\"\n        data-state={state}\n        data-orientation={stepper.orientation}\n        data-disabled={isDisabled ? \"\" : undefined}\n        className={cn(\n          \"group/stepper-item relative min-w-0 last:[&>[data-slot=stepper-separator]]:hidden data-disabled:opacity-40 data-[orientation=horizontal]:min-w-44 data-[orientation=horizontal]:flex-1 data-[orientation=horizontal]:pr-5 data-[orientation=vertical]:pb-6\",\n          className,\n        )}\n        {...props}\n      />\n    </StepperItemContext.Provider>\n  );\n}\n\nfunction StepperTrigger({\n  type = \"button\",\n  disabled = false,\n  className,\n  onClick,\n  ...props\n}: React.ComponentProps<\"button\">) {\n  const item = useStepperItemContext();\n  const isDisabled = item.disabled || disabled;\n\n  function handleClick(event: React.MouseEvent<HTMLButtonElement>) {\n    onClick?.(event);\n\n    if (!event.defaultPrevented) {\n      item.setValue(item.step);\n    }\n  }\n\n  return (\n    <button\n      data-slot=\"stepper-trigger\"\n      data-state={item.state}\n      data-orientation={item.orientation}\n      aria-current={item.state === \"current\" ? \"step\" : undefined}\n      type={type}\n      disabled={isDisabled}\n      className={cn(\n        \"group/stepper-trigger relative z-10 grid w-full cursor-pointer appearance-none items-start border-0 bg-transparent p-0 text-left outline-none disabled:cursor-not-allowed data-[orientation=horizontal]:grid-cols-1 data-[orientation=horizontal]:gap-y-3 data-[orientation=vertical]:grid-cols-[2rem_minmax(0,1fr)] data-[orientation=vertical]:gap-x-3\",\n        className,\n      )}\n      onClick={handleClick}\n      {...props}\n    />\n  );\n}\n\nfunction StepperIndicator({ className, children, ...props }: React.ComponentProps<\"span\">) {\n  const item = useStepperItemContext();\n  const stateLabel =\n    item.state === \"complete\"\n      ? \"Completed step\"\n      : item.state === \"current\"\n        ? \"Current step\"\n        : \"Upcoming step\";\n\n  return (\n    <span\n      data-slot=\"stepper-indicator\"\n      data-state={item.state}\n      className={cn(\n        \"relative z-10 inline-flex size-8 shrink-0 items-center justify-center border border-border bg-background font-mono text-[0.625rem] font-medium tabular-nums text-muted-foreground transition-[background-color,border-color,box-shadow,color] duration-100 group-focus-visible/stepper-trigger:border-ring group-focus-visible/stepper-trigger:ring-2 group-focus-visible/stepper-trigger:ring-ring/40 data-[state=complete]:border-foreground data-[state=complete]:bg-foreground data-[state=complete]:text-background data-[state=current]:border-foreground data-[state=current]:text-foreground motion-reduce:transition-none\",\n        className,\n      )}\n      {...props}\n    >\n      <span className=\"sr-only\">{stateLabel}: </span>\n      {children ?? <span aria-hidden=\"true\">{String(item.step).padStart(2, \"0\")}</span>}\n    </span>\n  );\n}\n\nfunction StepperContent({ className, ...props }: React.ComponentProps<\"span\">) {\n  const item = useStepperItemContext();\n\n  return (\n    <span\n      data-slot=\"stepper-content\"\n      data-orientation={item.orientation}\n      className={cn(\n        \"grid min-w-0 gap-1 data-[orientation=horizontal]:pr-4 data-[orientation=vertical]:pt-0.5\",\n        className,\n      )}\n      {...props}\n    />\n  );\n}\n\nfunction StepperTitle({ className, ...props }: React.ComponentProps<\"span\">) {\n  const item = useStepperItemContext();\n\n  return (\n    <span\n      data-slot=\"stepper-title\"\n      data-state={item.state}\n      className={cn(\n        \"text-sm font-medium leading-5 text-foreground data-[state=upcoming]:text-muted-foreground\",\n        className,\n      )}\n      {...props}\n    />\n  );\n}\n\nfunction StepperDescription({ className, ...props }: React.ComponentProps<\"span\">) {\n  return (\n    <span\n      data-slot=\"stepper-description\"\n      className={cn(\"text-sm leading-5 text-muted-foreground\", className)}\n      {...props}\n    />\n  );\n}\n\nfunction StepperSeparator({ className, ...props }: React.ComponentProps<\"span\">) {\n  const item = useStepperItemContext();\n\n  return (\n    <span\n      data-slot=\"stepper-separator\"\n      data-state={item.state}\n      data-orientation={item.orientation}\n      aria-hidden=\"true\"\n      className={cn(\n        \"pointer-events-none absolute bg-border data-[state=complete]:bg-foreground data-[orientation=horizontal]:top-4 data-[orientation=horizontal]:right-0 data-[orientation=horizontal]:left-8 data-[orientation=horizontal]:h-px data-[orientation=vertical]:top-8 data-[orientation=vertical]:bottom-0 data-[orientation=vertical]:left-4 data-[orientation=vertical]:w-px\",\n        className,\n      )}\n      {...props}\n    />\n  );\n}\n\nexport type { StepperItemProps, StepperOrientation, StepperProps, StepperState };\nexport {\n  Stepper,\n  StepperContent,\n  StepperDescription,\n  StepperIndicator,\n  StepperItem,\n  StepperSeparator,\n  StepperTitle,\n  StepperTrigger,\n};\n",
      "type": "registry:ui"
    }
  ],
  "type": "registry:ui"
}