| import cn from "@utils/classnames"; | |
| import { type ChangeEvent, type ReactNode, forwardRef } from "react"; | |
| import { FormError } from "../index.ts"; | |
| import LabelTooltip from "./LabelTooltip.tsx"; | |
| interface InputTextProps { | |
| label: string; | |
| placeholder?: string; | |
| error?: string; | |
| required?: boolean; | |
| className?: string; | |
| id?: string; | |
| disabled?: boolean; | |
| value?: string | number; | |
| onChange?: (e: ChangeEvent<HTMLInputElement>) => void; | |
| hideLabel?: boolean; | |
| tooltip?: string | ReactNode; | |
| type?: "text" | "number" | "email" | "password" | "url" | "tel"; | |
| min?: number; | |
| max?: number; | |
| step?: number; | |
| } | |
| const InputText = forwardRef<HTMLInputElement, InputTextProps>( | |
| ( | |
| { | |
| label, | |
| placeholder, | |
| error, | |
| required, | |
| className = "", | |
| id, | |
| hideLabel = false, | |
| type = "text", | |
| min, | |
| max, | |
| step, | |
| tooltip = "", | |
| ...props | |
| }, | |
| ref | |
| ) => { | |
| return ( | |
| <div className={cn("flex flex-col gap-2", className)}> | |
| <label | |
| htmlFor={id} | |
| className={cn( | |
| "relative text-sm font-medium text-gray-900 dark:text-gray-100", | |
| { | |
| "clip-[rect(0,0,0,0)] sr-only absolute m-[-1px] h-px w-px overflow-hidden border-0 p-0 whitespace-nowrap": | |
| hideLabel, | |
| } | |
| )} | |
| > | |
| {label} | |
| {required && ( | |
| <span className="ml-1 text-blue-500 dark:text-blue-400">*</span> | |
| )} | |
| {tooltip !== "" && <LabelTooltip text={<>{tooltip}</>} />} | |
| </label> | |
| <input | |
| ref={ref} | |
| type={type} | |
| id={id} | |
| placeholder={placeholder} | |
| min={min} | |
| max={max} | |
| step={step} | |
| className={cn( | |
| "w-full rounded-md border px-3 py-2 text-sm transition-colors focus:ring-2 focus:ring-offset-2 focus:outline-none", | |
| "bg-white text-gray-900 dark:bg-gray-800 dark:text-gray-100", | |
| "focus:ring-offset-white dark:focus:ring-offset-gray-900", | |
| error | |
| ? "border-red-300 focus:border-red-500 focus:ring-red-500 dark:border-red-700 dark:focus:border-red-600 dark:focus:ring-red-600" | |
| : "border-gray-300 focus:border-yellow-500 focus:ring-yellow-500 dark:border-gray-600 dark:focus:border-yellow-400 dark:focus:ring-yellow-400", | |
| "placeholder:text-gray-400 dark:placeholder:text-gray-500" | |
| )} | |
| {...props} | |
| /> | |
| {error && <FormError>{error}</FormError>} | |
| </div> | |
| ); | |
| } | |
| ); | |
| InputText.displayName = "InputText"; | |
| export default InputText; | |