1import * as React from "react"
2import { OTPInput, OTPInputContext } from "input-otp"
3import { Dot } from "lucide-react"
4
5import { cn } from "@/lib/utils"
6
7const InputOTP = React.forwardRef<
8 React.ElementRef<typeof OTPInput>,
9 React.ComponentPropsWithoutRef<typeof OTPInput>
10>(({ className, containerClassName, ...props }, ref) => (
11 <OTPInput
12 ref={ref}
13 containerClassName={cn(
14 "flex items-center gap-2 has-disabled:opacity-50",
15 containerClassName
16 )}
17 className={cn("disabled:cursor-not-allowed", className)}
18 {...props}
19 />
20))
21InputOTP.displayName = "InputOTP"
22
23const InputOTPGroup = React.forwardRef<
24 React.ElementRef<"div">,
25 React.ComponentPropsWithoutRef<"div">
26>(({ className, ...props }, ref) => (
27 <div ref={ref} className={cn("flex items-center", className)} {...props} />
28))
29InputOTPGroup.displayName = "InputOTPGroup"
30
31const InputOTPSlot = React.forwardRef<
32 React.ElementRef<"div">,
33 React.ComponentPropsWithoutRef<"div"> & { index: number }
34>(({ index, className, ...props }, ref) => {
35 const inputOTPContext = React.useContext(OTPInputContext)
36 const { char, hasFakeCaret, isActive } = inputOTPContext.slots[index]
37
38 return (
39 <div
40 ref={ref}
41 className={cn(
42 "relative flex h-10 w-10 items-center justify-center border-y border-r border-input text-sm transition-all first:rounded-l-md first:border-l last:rounded-r-md",
43 isActive && "z-10 ring-2 ring-ring ring-offset-background",
44 className
45 )}
46 {...props}
47 >
48 {char}
49 {hasFakeCaret && (
50 <div className="pointer-events-none absolute inset-0 flex items-center justify-center">
51 <div className="h-4 w-px animate-caret-blink bg-foreground duration-1000" />
52 </div>
53 )}
54 </div>
55 )
56})
57InputOTPSlot.displayName = "InputOTPSlot"
58
59const InputOTPSeparator = React.forwardRef<
60 React.ElementRef<"div">,
61 React.ComponentPropsWithoutRef<"div">
62>(({ ...props }, ref) => (
63 <div ref={ref} role="separator" {...props}>
64 <Dot />
65 </div>
66))
67InputOTPSeparator.displayName = "InputOTPSeparator"
68
69export { InputOTP, InputOTPGroup, InputOTPSlot, InputOTPSeparator }