import {
forwardRef,
type InputHTMLAttributes,
type TextareaHTMLAttributes,
} from "react";
interface InputProps extends InputHTMLAttributes {
label?: string;
error?: string;
hint?: string;
leftIcon?: React.ReactNode;
rightIcon?: React.ReactNode;
}
export const Input = forwardRef(
(
{ label, error, hint, leftIcon, rightIcon, className = "", id, ...props },
ref,
) => {
const inputId = id || label?.toLowerCase().replace(/\s+/g, "-");
const errorId = error ? `${inputId}-error` : undefined;
const hintId = hint ? `${inputId}-hint` : undefined;
const describedBy =
[errorId, hintId].filter(Boolean).join(" ") || undefined;
return (
{label && (
)}
{leftIcon && (
{leftIcon}
)}
{rightIcon && (
{rightIcon}
)}
{error && (
{error}
)}
{hint && !error && (
{hint}
)}
);
},
);
Input.displayName = "Input";
interface TextareaProps extends TextareaHTMLAttributes {
label?: string;
error?: string;
hint?: string;
}
export const Textarea = forwardRef(
({ label, error, hint, className = "", id, ...props }, ref) => {
const textareaId = id || label?.toLowerCase().replace(/\s+/g, "-");
const errorId = error ? `${textareaId}-error` : undefined;
const hintId = hint ? `${textareaId}-hint` : undefined;
const describedBy =
[errorId, hintId].filter(Boolean).join(" ") || undefined;
return (
{label && (
)}
{error && (
{error}
)}
{hint && !error && (
{hint}
)}
);
},
);
Textarea.displayName = "Textarea";