LiveDisplayX / src / components / ui / input-opt.tsx
input-opt.tsx
Raw
"use client";

import * as React from "react";
import { OTPInput, SlotProps } from "input-otp";
import { cn } from "@/lib/utils";

const InputOTP = React.forwardRef<
  React.ElementRef<typeof OTPInput>,
  React.ComponentPropsWithoutRef<typeof OTPInput>
>(({ className, ...props }, ref) => (
  <OTPInput
    ref={ref}
    containerClassName={cn("flex items-center gap-2", className)}
    {...props}
  />
));
InputOTP.displayName = "InputOTP";

const InputOTPGroup = React.forwardRef<
  HTMLDivElement,
  React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
  <div
    ref={ref}
    className={cn("flex items-center", className)}
    {...props}
  />
));
InputOTPGroup.displayName = "InputOTPGroup";

const InputOTPSlot = React.forwardRef<
  HTMLInputElement,
  SlotProps & React.HTMLAttributes<HTMLInputElement>
>(({ char, hasFakeCaret, isActive, placeholderChar, className, ...props }, ref) => (
  <div
    className={cn(
      "relative w-10 h-10",
      "flex items-center justify-center",
      "border-2 border-border rounded-lg",
      "transition-all duration-200",
      "bg-white",
      isActive && "border-primary ring-2 ring-primary ring-offset-2",
      className
    )}
  >
    <input
      ref={ref}
      className={cn(
        "w-full h-full text-center text-lg font-medium",
        "bg-transparent",
        "absolute inset-0",
        "focus:outline-none focus:ring-0"
      )}
      {...props} // This will no longer include placeholderChar
    />
    {char}
    {hasFakeCaret && (
      <div className="pointer-events-none absolute inset-0 flex items-center justify-center animate-caret-blink">
        <div className="w-px h-8 bg-primary" />
      </div>
    )}
  </div>
));
InputOTPSlot.displayName = "InputOTPSlot";

export { InputOTP, InputOTPGroup, InputOTPSlot };