{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "input-otp",
  "title": "Input OTP",
  "description": "An accessible one-time passcode input with composable groups, slots, separators, validation, paste, and autofill support.",
  "dependencies": [
    "input-otp"
  ],
  "files": [
    {
      "path": "registry/rivetui/components/input-otp/input-otp.tsx",
      "content": "\"use client\";\n\nimport { OTPInput, OTPInputContext } from \"input-otp\";\nimport * as React from \"react\";\n\nimport { cn } from \"@/lib/utils\";\n\ntype InputOTPState = {\n  disabled: boolean;\n  invalid: boolean;\n};\n\nconst InputOTPStateContext = React.createContext<InputOTPState>({\n  disabled: false,\n  invalid: false,\n});\n\ntype ComposedOTPInputProps = Extract<\n  React.ComponentProps<typeof OTPInput>,\n  { children: React.ReactNode }\n>;\n\ntype InputOTPProps = Omit<ComposedOTPInputProps, \"defaultValue\" | \"onChange\"> & {\n  defaultValue?: string;\n  onValueChange?: (value: string) => void;\n};\n\nfunction InputOTP({\n  \"aria-invalid\": ariaInvalid,\n  autoComplete = \"one-time-code\",\n  className,\n  containerClassName,\n  defaultValue = \"\",\n  disabled = false,\n  onValueChange,\n  value: valueProp,\n  ...props\n}: InputOTPProps) {\n  const [uncontrolledValue, setUncontrolledValue] = React.useState(defaultValue);\n  const value = valueProp ?? uncontrolledValue;\n  const invalid = ariaInvalid !== undefined && ariaInvalid !== false && ariaInvalid !== \"false\";\n\n  function handleChange(nextValue: string) {\n    if (valueProp === undefined) {\n      setUncontrolledValue(nextValue);\n    }\n\n    onValueChange?.(nextValue);\n  }\n\n  return (\n    <InputOTPStateContext.Provider value={{ disabled, invalid }}>\n      <OTPInput\n        data-slot=\"input-otp\"\n        aria-invalid={ariaInvalid}\n        autoComplete={autoComplete}\n        disabled={disabled}\n        value={value}\n        onChange={handleChange}\n        containerClassName={cn(\n          \"group flex max-w-full items-center gap-2 has-disabled:cursor-not-allowed\",\n          containerClassName,\n        )}\n        className={cn(\"disabled:cursor-not-allowed\", className)}\n        {...props}\n      />\n    </InputOTPStateContext.Provider>\n  );\n}\n\nfunction InputOTPGroup({ className, ...props }: React.ComponentProps<\"div\">) {\n  return (\n    <div\n      data-slot=\"input-otp-group\"\n      className={cn(\n        \"flex items-center [&>[data-slot=input-otp-slot]+[data-slot=input-otp-slot]]:-ml-px\",\n        className,\n      )}\n      {...props}\n    />\n  );\n}\n\nfunction InputOTPSlot({\n  className,\n  index,\n  ...props\n}: React.ComponentProps<\"div\"> & { index: number }) {\n  const inputContext = React.useContext(OTPInputContext);\n  const { disabled, invalid } = React.useContext(InputOTPStateContext);\n  const { char, hasFakeCaret, isActive, placeholderChar } = inputContext.slots[index] ?? {};\n\n  return (\n    <div\n      data-slot=\"input-otp-slot\"\n      data-active={isActive ? \"\" : undefined}\n      data-disabled={disabled ? \"\" : undefined}\n      data-invalid={invalid ? \"\" : undefined}\n      className={cn(\n        \"relative flex size-11 items-center justify-center border border-input bg-background font-mono text-lg tabular-nums outline-none transition-[background-color,border-color,box-shadow,color,opacity] duration-100 data-active:z-10 data-active:border-foreground/50 data-active:bg-muted/30 data-disabled:bg-muted data-disabled:text-muted-foreground data-disabled:opacity-60 data-invalid:border-destructive group-has-[:focus-visible]:data-active:border-ring group-has-[:focus-visible]:data-active:ring-2 group-has-[:focus-visible]:data-active:ring-ring/40 group-has-[:focus-visible]:data-active:data-invalid:border-destructive group-has-[:focus-visible]:data-active:data-invalid:ring-destructive/25 motion-reduce:transition-none\",\n        className,\n      )}\n      {...props}\n    >\n      {char ??\n        (placeholderChar ? <span className=\"text-muted-foreground\">{placeholderChar}</span> : null)}\n      {hasFakeCaret ? (\n        <span\n          className=\"pointer-events-none absolute h-5 w-px animate-pulse bg-foreground motion-reduce:animate-none\"\n          aria-hidden=\"true\"\n        />\n      ) : null}\n    </div>\n  );\n}\n\nfunction InputOTPSeparator({ className, ...props }: React.ComponentProps<\"div\">) {\n  return (\n    <div\n      data-slot=\"input-otp-separator\"\n      aria-hidden=\"true\"\n      className={cn(\"flex w-3 items-center justify-center\", className)}\n      {...props}\n    >\n      <span className=\"h-px w-2 bg-border\" />\n    </div>\n  );\n}\n\nexport {\n  REGEXP_ONLY_CHARS,\n  REGEXP_ONLY_DIGITS,\n  REGEXP_ONLY_DIGITS_AND_CHARS,\n} from \"input-otp\";\nexport type { InputOTPProps };\nexport { InputOTP, InputOTPGroup, InputOTPSeparator, InputOTPSlot };\n",
      "type": "registry:ui"
    }
  ],
  "type": "registry:ui"
}