1- import React , { FC } from "react" ;
1+ import React , { forwardRef } from "react" ;
22
33interface InputProps {
44 type ?: "text" | "number" | "email" | "password" | "date" | "time" | string ;
@@ -7,23 +7,25 @@ interface InputProps {
77 placeholder ?: string ;
88 defaultValue ?: string | number ;
99 onChange ?: ( e : React . ChangeEvent < HTMLInputElement > ) => void ;
10+ onBlur ?: ( e : React . FocusEvent < HTMLInputElement > ) => void ; // new
1011 className ?: string ;
1112 min ?: string | number ;
1213 max ?: string | number ;
1314 step ?: number ;
1415 disabled ?: boolean ;
1516 success ?: boolean ;
1617 error ?: boolean ;
17- hint ?: string ; // Optional hint text
18+ hint ?: string ;
1819}
1920
20- const Input : FC < InputProps > = ( {
21+ const Input = forwardRef < HTMLInputElement , InputProps > ( ( {
2122 type = "text" ,
2223 id,
2324 name,
2425 placeholder,
2526 defaultValue,
2627 onChange,
28+ onBlur, // new
2729 className = "" ,
2830 min,
2931 max,
@@ -32,53 +34,49 @@ const Input: FC<InputProps> = ({
3234 success = false ,
3335 error = false ,
3436 hint,
35- } ) => {
36- // Determine input styles based on state (disabled, success, error)
37+ ... rest // catch other props (like ref will be forwarded automatically)
38+ } , ref ) => {
3739 let inputClasses = `h-11 w-full rounded-lg border appearance-none px-4 py-2.5 text-sm shadow-theme-xs placeholder:text-gray-400 focus:outline-hidden focus:ring-3 dark:bg-gray-900 dark:text-white/90 dark:placeholder:text-white/30 dark:focus:border-brand-800 ${ className } ` ;
3840
39- // Add styles for the different states
4041 if ( disabled ) {
4142 inputClasses += ` text-gray-500 border-gray-300 cursor-not-allowed dark:bg-gray-800 dark:text-gray-400 dark:border-gray-700` ;
4243 } else if ( error ) {
43- inputClasses += ` text-error-800 border-error-500 focus:ring-3 focus:ring-error-500/10 dark:text-error-400 dark:border-error-500` ;
44+ inputClasses += ` text-error-800 border-error-500 focus:ring-3 focus:ring-error-500/10 dark:text-error-400 dark:border-error-500` ;
4445 } else if ( success ) {
45- inputClasses += ` text-success-500 border-success-400 focus:ring-success-500/10 focus:border-success-300 dark:text-success-400 dark:border-success-500` ;
46+ inputClasses += ` text-success-500 border-success-400 focus:ring-success-500/10 focus:border-success-300 dark:text-success-400 dark:border-success-500` ;
4647 } else {
4748 inputClasses += ` bg-transparent text-gray-800 border-gray-300 focus:border-brand-300 focus:ring-3 focus:ring-brand-500/10 dark:border-gray-700 dark:bg-gray-900 dark:text-white/90 dark:focus:border-brand-800` ;
4849 }
4950
5051 return (
5152 < div className = "relative" >
5253 < input
54+ ref = { ref }
5355 type = { type }
5456 id = { id }
5557 name = { name }
5658 placeholder = { placeholder }
5759 defaultValue = { defaultValue }
5860 onChange = { onChange }
61+ onBlur = { onBlur }
5962 min = { min }
6063 max = { max }
6164 step = { step }
6265 disabled = { disabled }
6366 className = { inputClasses }
67+ { ...rest }
6468 />
65-
66- { /* Optional Hint Text */ }
6769 { hint && (
68- < p
69- className = { `mt-1.5 text-xs ${
70- error
71- ? "text-error-500"
72- : success
73- ? "text-success-500"
74- : "text-gray-500"
75- } `}
76- >
70+ < p className = { `mt-1.5 text-xs ${
71+ error ? "text-error-500" : success ? "text-success-500" : "text-gray-500"
72+ } `} >
7773 { hint }
7874 </ p >
7975 ) }
8076 </ div >
8177 ) ;
82- } ;
78+ } ) ;
79+
80+ Input . displayName = "Input" ;
8381
8482export default Input ;
0 commit comments