import clsx from "clsx"; import { ChangeEvent, FC, FocusEvent, HTMLAttributes, HTMLInputTypeAttribute, useEffect, useState, } from "react"; import { v4 as uuidv4 } from "uuid"; import styles from "./styles.module.css"; interface InputProps extends HTMLAttributes { min?: number; max?: number; autoComplete?: string; } export interface InputFieldProps extends HTMLAttributes { errorMessage?: string; initialValue?: string | number | null; label: string; maxLength?: number; placeholder?: string; type?: HTMLInputTypeAttribute; inputProps?: InputProps; } export const InputField: FC = ({ className, errorMessage, initialValue = "", inputProps, label, maxLength, onBlur, onChange, onFocus, placeholder, type = "text", ...props }) => { // Set default error message if not provided errorMessage ||= `The maximum length is ${maxLength} characters.`; // Set up component state and a shared id const [value, setValue] = useState(initialValue); const [showError, setShowError] = useState(false); const id = props.id ?? `input-field-${uuidv4()}`; const handleChange = (e: ChangeEvent) => { const valueLength = e.target.value.length; if (maxLength) { // If the value length exceeds maxLength, show error if (valueLength > maxLength) { setShowError(true); //return; Prevent further processing if maxLength exceeded return; } // If the value length is equal to maxLength, show error if (valueLength === maxLength) { setShowError(true); } // If the value length is less than maxLength, hide error if (valueLength < maxLength) { setShowError(false); } } // Update component state setValue(e.target.value); // Call the provided onChange handler if it exists if (onChange) onChange(e); return; }; const handleBlur = (e: FocusEvent) => { const intValue = parseInt(e.target.value); // If entered value is below the minimum, reset to minimum if ( !isNaN(intValue) && inputProps?.min !== undefined && intValue < inputProps.min ) { setValue(inputProps.min); } // If entered value is above the maximum and no initialValue exists, reset to maximum if ( !isNaN(intValue) && inputProps?.max !== undefined && intValue > inputProps.max ) { setValue(inputProps.max); } // Call the provided onBlur handler if it exists if (onBlur) onBlur(e); // Reset error state on blur setShowError(false); }; const handleFocus = (e: FocusEvent) => { // Call the provided onFocus handler if it exists if (onFocus) onFocus(e); // Check for maxLength error const valueLength = e.target.value.length; if (maxLength && valueLength > maxLength - 1) setShowError(true); }; useEffect(() => { // Update the value when initialValue changes setValue(initialValue); // Reset error state when initial value changes setShowError(false); }, [initialValue]); const inputAttrs = { id, type, placeholder }; return (
{showError && {errorMessage}}
); };