| 37 | } |
| 38 | |
| 39 | function InputOTPSlot({ |
| 40 | index, |
| 41 | className, |
| 42 | ...props |
| 43 | }: React.ComponentProps<"div"> & { |
| 44 | index: number |
| 45 | }) { |
| 46 | const inputOTPContext = React.useContext(OTPInputContext) |
| 47 | const { char, hasFakeCaret, isActive } = inputOTPContext?.slots[index] ?? {} |
| 48 | |
| 49 | return ( |
| 50 | <div |
| 51 | data-slot="input-otp-slot" |
| 52 | data-active={isActive} |
| 53 | className={cn( |
| 54 | "data-[active=true]:border-ring data-[active=true]:ring-ring/50 data-[active=true]:aria-invalid:ring-destructive/20 dark:data-[active=true]:aria-invalid:ring-destructive/40 aria-invalid:border-destructive data-[active=true]:aria-invalid:border-destructive dark:bg-input/30 border-input relative flex h-9 w-9 items-center justify-center border-y border-r text-sm shadow-xs transition-all outline-none first:rounded-l-md first:border-l last:rounded-r-md data-[active=true]:z-10 data-[active=true]:ring-[3px]", |
| 55 | className |
| 56 | )} |
| 57 | {...props} |
| 58 | > |
| 59 | {char} |
| 60 | {hasFakeCaret && ( |
| 61 | <div className="pointer-events-none absolute inset-0 flex items-center justify-center"> |
| 62 | <div className="animate-caret-blink bg-foreground h-4 w-px duration-1000" /> |
| 63 | </div> |
| 64 | )} |
| 65 | </div> |
| 66 | ) |
| 67 | } |
| 68 | |
| 69 | function InputOTPSeparator({ ...props }: React.ComponentProps<"div">) { |
| 70 | return ( |