75 lines
2.4 KiB
TypeScript
75 lines
2.4 KiB
TypeScript
import React, { forwardRef, useId } from 'react';
|
|
import { cn } from '@/utils/utils';
|
|
|
|
const sizeStyles = {
|
|
sm: "px-3 py-1.5 text-xs",
|
|
md: "px-4 py-2.5 text-sm",
|
|
};
|
|
|
|
export interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {
|
|
label?: string;
|
|
error?: string;
|
|
sizeVariant?: keyof typeof sizeStyles; // Gestion de la taille
|
|
leftIcon?: React.ReactNode; // Icône optionnelle intégrée à gauche
|
|
rightIcon?: React.ReactNode; // Icône optionnelle intégrée à droite
|
|
}
|
|
|
|
export const Input = forwardRef<HTMLInputElement, InputProps>(
|
|
({
|
|
className,
|
|
label,
|
|
error,
|
|
id,
|
|
sizeVariant = 'md',
|
|
leftIcon,
|
|
rightIcon,
|
|
...props
|
|
}, ref) => {
|
|
const autoId = useId();
|
|
const inputId = id || autoId;
|
|
|
|
return (
|
|
<div className="w-full">
|
|
{label && (
|
|
<label htmlFor={inputId} className="block text-sm font-medium text-slate-700 mb-1.5">
|
|
{label} {props.required && <span className="text-blue-900 font-bold">*</span>}
|
|
</label>
|
|
)}
|
|
|
|
<div className="relative flex items-center w-full">
|
|
{/* Icône à gauche */}
|
|
{leftIcon && (
|
|
<span className="absolute left-3 text-slate-400 pointer-events-none flex items-center">
|
|
{leftIcon}
|
|
</span>
|
|
)}
|
|
|
|
<input
|
|
id={inputId}
|
|
ref={ref}
|
|
className={cn(
|
|
"flex w-full rounded-lg border border-slate-300 bg-white text-slate-900 placeholder:text-slate-400 focus:outline-none focus:ring-1 focus:ring-blue-900 focus:border-blue-900 disabled:cursor-not-allowed disabled:bg-slate-50 disabled:text-slate-500 shadow-sm transition-colors",
|
|
sizeStyles[sizeVariant],
|
|
leftIcon && "pl-9", // Décale le texte à droite si icône gauche
|
|
rightIcon && "pr-9", // Décale le texte à gauche si icône droite
|
|
error && "border-red-500 focus:ring-red-500 focus:border-red-500",
|
|
className
|
|
)}
|
|
{...props}
|
|
/>
|
|
|
|
{/* Icône à droite */}
|
|
{rightIcon && (
|
|
<span className="absolute right-3 text-slate-400 pointer-events-none flex items-center">
|
|
{rightIcon}
|
|
</span>
|
|
)}
|
|
</div>
|
|
|
|
{error && <p className="mt-1.5 text-xs font-medium text-red-500">{error}</p>}
|
|
</div>
|
|
);
|
|
}
|
|
);
|
|
|
|
Input.displayName = "Input"; |