input.tsx
Overview
The input.tsx file provides a set of reusable, customizable React input components designed to handle various input scenarios with consistent styling and enhanced functionalities. It includes a base Input component with controlled and uncontrolled value handling, and several extended components:
ExpandedInput— Adds optional prefix and suffix elements around the input.SearchInput— A specialized input with a search icon prefix.InnerBlurInput/BlurInput— Manages input value updates on blur instead of on every change.NumberInput— Handles numeric inputs with value conversion and type safety.
These components enable consistent UI/UX patterns for input fields across the application, integrating with utility functions and icons, and support forwarding refs for integration with forms or external libraries.
Components and Exports
1. Input
Description
The core input component wrapping a native HTML <input> element, supporting controlled and uncontrolled usage. It normalizes numeric input changes by converting string values to numbers before propagating changes.
Declaration
const Input = React.forwardRef<HTMLInputElement, InputProps>(
({ className, type, value, onChange, ...props }, ref) => { ... }
);
Props
InputProps extends standard React input attributes (React.InputHTMLAttributes<HTMLInputElement>) with optional:
value?: string | number | readonly string[] | undefined
Parameters
className(string): Additional CSS classes.type(string): Input type attribute (e.g., "text", "number").value(string | number | readonly string[] | undefined): Controlled input value.onChange(function): Change event handler.ref(React.Ref): Ref forwarded to the input element.Other native input props spread into the
<input>element.
Behavior
Determines if the component is controlled by checking if
valueprop is defined.For
type="number", converts the input string to a number or empty string before callingonChange.Applies a comprehensive set of default CSS classes for styling.
Supports forwarding refs for DOM access.
Usage Example
<Input
type="text"
value={textValue}
onChange={(e) => setTextValue(e.target.value)}
className="custom-input"
/>
2. ExpandedInput
Description
An enhanced input wrapper that allows injecting prefix and suffix React nodes (e.g., icons or buttons) inside the input field container, positioned absolutely within the input wrapper.
Declaration
const ExpandedInput = ({
prefix,
suffix,
className,
...props
}: ExpandedInputProps) => { ... }
Props
prefix?: React.ReactNode— Element to render inside the input on the left.suffix?: React.ReactNode— Element to render inside the input on the right.All other
InputPropsexceptprefix(omitted).
Behavior
Renders a container
<div>with relative positioning.Renders prefix and suffix in absolutely positioned
<span>elements vertically centered.Adjusts input padding (
pl-8for prefix,pr-8for suffix) for spacing.Passes remaining props to the underlying
Input.
Usage Example
<ExpandedInput
prefix={<SomeIcon />}
suffix={<ClearButton />}
value={value}
onChange={handleChange}
/>
3. SearchInput
Description
A specialized input component for search functionality. It composes ExpandedInput with a search icon as a prefix.
Declaration
const SearchInput = (props: InputProps) => { ... }
Props
All
InputProps.
Behavior
Uses the
Searchicon from thelucide-reactlibrary as a prefix.Passes all other props to
ExpandedInput.
Usage Example
<SearchInput
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
/>
4. InnerBlurInput / BlurInput
Description
An input component that delays propagating changes to the parent until the input loses focus (onBlur event). This avoids frequent updates while typing.
BlurInput is a memoized version of InnerBlurInput for optimization.
Declaration
const InnerBlurInput = React.forwardRef<
HTMLInputElement,
InputProps & { value: Value; onChange(value: Value): void }
>(({ value, onChange, ...props }, ref) => { ... });
export const BlurInput = React.memo(InnerBlurInput);
Props
value: string | number | readonly string[] | undefined — Current input value.onChange(value: Value): void— Callback triggered on input blur to update value.Other standard input props.
Behavior
Maintains internal state
valto track input value locally.Updates internal state on every
onChangeevent.Calls the passed
onChangeprop only ononBlurwith the latest value.Synchronizes internal state if the
valueprop changes externally.
Usage Example
const [value, setValue] = React.useState('');
<BlurInput
value={value}
onChange={(val) => setValue(val)}
/>
5. NumberInput
Description
A numeric input component that ensures the value passed to onChange is a number, converting from string input.
Declaration
const NumberInput = React.forwardRef<
HTMLInputElement,
NumberInputProps & { value: Value; onChange(value: Value): void }
>(function NumberInput({ onChange, ...props }, ref) { ... });
Props
onChange?(value: number): void— Callback with numeric value.value: string | number | readonly string[] | undefined.Other
InputProps.
Behavior
Sets input type to
"number".Converts empty string to
0and other values to numbers before callingonChange.
Usage Example
const [num, setNum] = React.useState<number>(0);
<NumberInput
value={num}
onChange={(val) => setNum(val)}
/>
Important Implementation Details
Controlled vs Uncontrolled Inputs: The base
Inputcomponent supports both controlled (valueprop defined) and uncontrolled (defaultValue) usage, determining which to use internally.Numeric Input Handling: For inputs with
type="number", theInputcomponent normalizes value changes by converting string inputs to numbers, ensuring theonChangehandler receives numeric values.Prefix/Suffix Wrapping:
ExpandedInputuses absolute positioning and padding adjustments to overlay prefix/suffix elements inside the input field container without breaking layout.Delayed Change Propagation:
InnerBlurInputdelays theonChangecallback until the input loses focus, improving performance and UX in scenarios where immediate updates are unnecessary.Memoization Optimization:
BlurInputmemoizesInnerBlurInputto avoid unnecessary re-renders.Ref Forwarding: All main input components forward refs to the underlying
<input>element, enabling integration with form libraries or imperative focus management.Styling: Uses a utility function
cn(likely a classnames/clsx wrapper) to combine static and dynamic CSS classes for consistent styling. The input features focus ring, disabled styles, and file input reset styles.Development Tooling:
InnerBlurInputincludeswhyDidYouRenderflag for development-time render tracking.
Interaction with Other Parts of the System
Utility Function
cn: Used for conditional and combined class names; imported from@/lib/utils.Icon Component
Search: Fromlucide-react, used for search input prefix.CSS Classes: The input styling depends on existing CSS variables and classes such as
border-input,bg-bg-card,ring-ring, etc., which are defined elsewhere in the application's style system.Forwarded Props & Refs: Designed for smooth integration with form handling libraries or higher-order components.
Exports: Components like
Input,ExpandedInput,SearchInput,BlurInput, andNumberInputare exported for consumption across the application.
Visual Diagram
classDiagram
class Input {
+value: string | number | readonly string[] | undefined
+onChange(event: React.ChangeEvent<HTMLInputElement>): void
+ref: React.Ref<HTMLInputElement>
+handleChange(e: React.ChangeEvent<HTMLInputElement>): void
}
class ExpandedInput {
+prefix?: React.ReactNode
+suffix?: React.ReactNode
+className?: string
+props: InputProps
}
class SearchInput {
+props: InputProps
}
class InnerBlurInput {
+value: string | number | readonly string[] | undefined
+onChange(value: string | number | readonly string[] | undefined): void
+ref: React.Ref<HTMLInputElement>
+handleChange(e: React.ChangeEvent<HTMLInputElement>): void
+handleBlur(e: React.FocusEvent<HTMLInputElement>): void
-val: string | number | readonly string[] | undefined (state)
}
class BlurInput {
<<memoized>> InnerBlurInput
}
class NumberInput {
+value: string | number | readonly string[] | undefined
+onChange(value: number): void
+ref: React.Ref<HTMLInputElement>
}
ExpandedInput --> Input : uses >
SearchInput --> ExpandedInput : uses >
InnerBlurInput --> Input : uses >
BlurInput --|> InnerBlurInput
NumberInput --> Input : uses >
Summary
The input.tsx file provides a modular, extensible set of React input components with advanced features such as controlled/uncontrolled modes, input value normalization, prefix/suffix adornments, delayed update on blur, and numeric input handling. These components ensure consistent styling and behavior across the application, improve usability, and support integration with form libraries via ref forwarding.
They interact with utility functions and icon libraries and are designed for easy extension and reuse.