react-fatless-form
Version:
A lightweight React form package designed for simplicity that simplifies form handling and validation without unnecessary complexity or bloat.
343 lines (342 loc) • 10.7 kB
TypeScript
import React from "react";
type CommonProps = {
id?: string;
name: string;
label: string;
disabled?: boolean;
required?: boolean;
className?: string;
style?: React.CSSProperties;
};
export type InputProps = ({
type: "file";
accept?: string;
multiple?: boolean;
} & CommonProps) | ({
type: "date";
minDate?: Date;
maxDate?: Date;
timePicker?: boolean;
placeholder?: string;
rightIcon?: React.JSX.Element;
} & CommonProps) | ({
type: "time";
minTime?: string;
maxTime?: string;
placeholder?: string;
rightIcon?: React.JSX.Element;
} & CommonProps) | ({
type: "select";
options: {
label: string;
value: string | number;
}[];
loading?: boolean;
multiple?: boolean;
placeholder?: string;
} & CommonProps) | ({
type: "checkbox";
checked?: boolean;
options?: {
label: string;
value: string | number;
}[];
slider?: "rounded" | "default";
} & CommonProps) | ({
type: "radio";
options: {
label: string;
value: string | number;
}[];
} & CommonProps) | ({
type: "textarea";
cols?: number;
rows?: number;
wrap?: 'hard' | 'soft';
readonly?: boolean;
maxlength?: number;
placeholder?: string;
autofocus?: boolean;
} & CommonProps) | ({
type: "password";
placeholder?: string;
showStrengthIndicator?: boolean;
passwordPolicy?: (password: string) => {
strength: number;
message: string;
};
showIcon?: React.ReactNode;
hideIcon?: React.ReactNode;
autofocus?: boolean;
} & CommonProps) | ({
type: "text" | "number" | "email" | "tel" | "url";
placeholder?: string;
autofocus?: boolean;
autocomplete?: "on" | "off";
minlength?: number;
maxlength?: number;
pattern?: string;
readOnly?: boolean;
ref?: React.Ref<HTMLInputElement>;
} & CommonProps);
/**
* A versatile `Input` component that dynamically renders various types of form controls based on the `type` prop.
*
* ### Overview
* The `Input` component automatically integrates with form state management by handling `value` and `onChange` props internally.
* This ensures that developers only need to focus on providing the necessary configurations for their inputs, without worrying
* about manually managing state.
*
* ### Supported Input Types
* - **Text-based Inputs**: Includes `text`, `number`, `password`, etc.
* - **Textarea**: Multi-line text input with options for rows, columns, and wrapping.
* - **Checkbox**: Supports both standalone checkboxes and grouped checkboxes.
* - **Radio Buttons**: Renders a group of mutually exclusive options.
* - **Select Dropdown**: A dropdown menu with options for single or multiple selection.
* - **Date Picker**: Renders a date input with optional minimum and maximum date constraints.
* - `timePicker`: Enables time selection if `true`.
* - **File Input**: For uploading files, with support for specifying file types and allowing multiple file uploads.
*
* ### Key Features
* - **Dynamic Rendering**: Automatically renders the correct form control based on the `type` prop.
* - **Type-Safe Props**: Each input type enforces its own specific props, ensuring you pass only valid props.
* - **Styling Options**: Supports `className` and `style` props for customization.
*
* ### Common Props
* All input types support these shared props:
* - `name` (required): Name of the input field, used for form state management.
* - `label` (optional): A label displayed for the input field.
* - `disabled` (optional): Disables the input field if `true`.
* - `required` (optional): Marks the input field as required.
* - `className` (optional): Adds custom CSS class names to the component.
* - `style` (optional): Inline styles for the component.
*
* ### Type-Specific Props
* Each input type supports additional props specific to its functionality:
* - **File Input (`type: "file"`)**
* - `accept`: Specifies accepted file types (e.g., `.jpg,.png`).
* - `multiple`: Allows multiple file selection if `true`.
*
* - **Date Input (`type: "date"`)**
* - `minDate`: Minimum selectable date.
* - `maxDate`: Maximum selectable date.
* - `placeholder`: Placeholder text for the date input.
*
* - **Select Dropdown (`type: "select"`)**
* - `options`: Array of `{ label: string; value: string | number }` for the dropdown options.
* - `loading`: Displays a loading indicator if `true`.
* - `multiple`: Enables multi-select if `true`.
* - `placeholder`: Placeholder text for the dropdown.
*
*
*
* - **Checkbox (`type: "checkbox"`)**
* - `checked`: Indicates if the checkbox is selected.
* - `options`: Array of `{ label: string; value: string | number }` for grouped checkboxes.
* - `slider`: Visual style for the checkbox (e.g., `rounded`, `default`).
*
* #### Behavior
*
* - ***Single Checkbox***:
* - If `options` is not provided, it renders a single checkbox.
* - If `slider` is provided, the checkbox is styled as a switch.
* - ***Multiple Checkboxes***:
* - If `options` is provided and has at least one item, it renders a list of checkboxes.
* - If `options` is empty, the component renders nothing.
*
* - **Textarea (`type: "textarea"`)**
* - `cols`: Number of columns for the textarea.
* - `rows`: Number of rows for the textarea.
* - `wrap`: Text wrapping behavior (`hard` or `soft`).
* - `readonly`: Prevents text modification if `true`.
* - `maxlength`: Maximum number of characters allowed.
*
* - **Radio Buttons (`type: "radio"`)**:
* - `options`: Array of `{ label: string; value: string | number }` for radio button options.
*
* - **Text-based Inputs (`type: "text" | "number" | "password"`)**:
* - `placeholder`: Placeholder text for the input field.
* - `autofocus`: Automatically focuses on the input field if `true`.
* - `autocomplete`: Enables or disables autocomplete (`on` or `off`).
* - `maxlength`: Maximum number of characters allowed.
* - `pattern`: Regular expression pattern for input validation.
*
* - **Time Input (`type: "time"`)**:
* - `minTime`: Minimum selectable time in "hh:mm AM/PM" format.
* - `maxTime`: Maximum selectable time in "hh:mm AM/PM" format.
* - `placeholder`: Placeholder text for the time input.
* - `rightIcon`: Icon to display on the right side of the input.
*
* - **Password Input (`type: "password"`)**:
* - `placeholder`: Placeholder text for the password input.
* - `showStrengthIndicator`: Displays a password strength indicator if `true`.
* - `passwordPolicy`: Function that returns an object with `strength` (0-100) and `message` (e.g., "Weak", "Strong").
* - `showIcon`: Custom icon to display when the password is visible.
* - `hideIcon`: Custom icon to display when the password is hidden.
* - `autofocus`: Automatically focuses on the input field if `true`.
*
* ### Examples
*
* **1. Text Input**
* ```tsx
* <Input name="username" type="text" label="Username" placeholder="Enter your username" />
* ```
*
* **2. Checkbox Group**
* ```tsx
* <Input
* name="preferences"
* type="checkbox"
* label="Preferences"
* options={[
* { label: "Option 1", value: "option1" },
* { label: "Option 2", value: "option2" },
* ]}
* />
* ```
*
* **3. Radio Buttons**
* ```tsx
* <Input
* name="gender"
* type="radio"
* label="Gender"
* options={[
* { label: "Male", value: "male" },
* { label: "Female", value: "female" },
* ]}
* />
* ```
*
* **4. Select Dropdown**
* ```tsx
* <Input
* name="country"
* type="select"
* label="Country"
* options={[
* { label: "Kenya", value: "ke" },
* { label: "South Africa", value: "sa" },
* ]}
* placeholder="Choose your country"
* />
* ```
*
* **5. File Upload**
* ```tsx
* <Input name="resume" type="file" label="Upload Resume" accept=".pdf,.docx" multiple />
* ```
*
* **6. Date Picker**
* ```tsx
* <Input
* name="dob"
* type="date"
* label="Date of Birth"
* minDate={new Date()}
* maxDate={new Date(2033, 11, 31)}
* />
* ```
*
* **7. Time Picker**
* ```tsx
* <Input
* name="appointmentTime"
* type="time"
* label="Appointment Time"
* minTime="09:00 AM"
* maxTime="05:00 PM"
* />
* ```
*
* **8. Password Input**
* ```tsx
* <Input
* name="password"
* type="password"
* label="Password"
* placeholder="Enter your password"
* showStrengthIndicator
* passwordPolicy={(password) => {
* const strength = password.length > 8 ? 100 : 50;
* const message = strength === 100 ? "Strong" : "Weak";
* return { strength, message };
* }}
* />
* ```
*
* ### Usage Notes
* - Ensure the `type` matches the expected props; passing invalid props will result in a TypeScript error.
*/
export declare const Input: React.ForwardRefExoticComponent<(({
type: "file";
accept?: string;
multiple?: boolean;
} & CommonProps) | ({
type: "date";
minDate?: Date;
maxDate?: Date;
timePicker?: boolean;
placeholder?: string;
rightIcon?: React.JSX.Element;
} & CommonProps) | ({
type: "time";
minTime?: string;
maxTime?: string;
placeholder?: string;
rightIcon?: React.JSX.Element;
} & CommonProps) | ({
type: "select";
options: {
label: string;
value: string | number;
}[];
loading?: boolean;
multiple?: boolean;
placeholder?: string;
} & CommonProps) | ({
type: "checkbox";
checked?: boolean;
options?: {
label: string;
value: string | number;
}[];
slider?: "rounded" | "default";
} & CommonProps) | ({
type: "radio";
options: {
label: string;
value: string | number;
}[];
} & CommonProps) | ({
type: "textarea";
cols?: number;
rows?: number;
wrap?: "hard" | "soft";
readonly?: boolean;
maxlength?: number;
placeholder?: string;
autofocus?: boolean;
} & CommonProps) | ({
type: "password";
placeholder?: string;
showStrengthIndicator?: boolean;
passwordPolicy?: (password: string) => {
strength: number;
message: string;
};
showIcon?: React.ReactNode;
hideIcon?: React.ReactNode;
autofocus?: boolean;
} & CommonProps) | Omit<{
type: "text" | "number" | "email" | "tel" | "url";
placeholder?: string;
autofocus?: boolean;
autocomplete?: "on" | "off";
minlength?: number;
maxlength?: number;
pattern?: string;
readOnly?: boolean;
ref?: React.Ref<HTMLInputElement>;
} & CommonProps, "ref">) & React.RefAttributes<HTMLInputElement>>;
export default Input;