@gridcore/react-smart-input
v0.1.1
Published
A smart input fields component library for React
Downloads
120
Readme
React Smart Input
A comprehensive, type-safe form input component library for React with built-in Formik integration.
Features
- 🎨 Beautiful, modern UI with Tailwind CSS
- 📝 Multiple input types (text, email, password, number, tel, select, textarea, date, month, checkbox)
- ✅ Built-in Formik integration with auto-scroll to errors
- 🎯 Type-safe with TypeScript
- 🎨 Customizable primary colors
- 🔍 Smart select with search and keyboard navigation
- 📅 Advanced date picker with month/year selection
- 🏷️ Multi-select with tags and checkboxes
- 🎯 Select All functionality for multi-select
- 📦 Standalone Chip component for tags
- 👁️ Password visibility toggle
- 🎭 Icons and suffix support
- 📏 Min/Max length validation
- 🏷️ Built-in label support for all fields
- 📋 JSON-based form rendering
- 🔄 Auto-positioning dropdowns (flip when no space)
- ⌨️ FormWrapper with keyboard shortcuts (Ctrl+J, Ctrl+S, Ctrl+P, Ctrl+R)
- 🎯 Jump to field functionality
- 🖱️ Right-click context menu
- ♿ Accessible and keyboard-friendly
Installation
npm install @gridcore/react-smart-input lucide-reactFor Formik integration:
npm install formik yupImport Options
Individual Components
import { InputField } from '@gridcore/react-smart-input';
import { SelectField } from '@gridcore/react-smart-input';
import { CheckboxField } from '@gridcore/react-smart-input';
import { TextAreaField } from '@gridcore/react-smart-input';
import { DatePicker } from '@gridcore/react-smart-input';
import { MonthPicker } from '@gridcore/react-smart-input';Universal Field Component
import { Field } from '@gridcore/react-smart-input';Formik Integration
import { FormikField } from '@gridcore/react-smart-input';
import { Formik, Form } from 'formik';
import * as Yup from 'yup';All at Once
import {
InputField,
SelectField,
CheckboxField,
TextAreaField,
DatePicker,
MonthPicker,
Field,
FormikField,
JsonForm,
FormWrapper
} from '@gridcore/react-smart-input';Usage Examples
1. Text Input
import { InputField } from '@gridcore/react-smart-input';
function MyForm() {
const [name, setName] = useState('');
return (
<InputField
type="text"
value={name}
onChange={setName}
placeholder="Enter your name"
/>
);
}2. Email Input
<InputField
type="email"
value={email}
onChange={setEmail}
placeholder="Enter your email"
/>3. Password Input (with toggle)
<InputField
type="password"
value={password}
onChange={setPassword}
placeholder="Enter password"
/>4. Number Input
<InputField
type="number"
value={age}
onChange={setAge}
placeholder="Enter age"
/>5. Phone Input
<InputField
type="tel"
value={phone}
onChange={setPhone}
placeholder="Enter phone number"
/>6. Select Dropdown
import { SelectField } from '@gridcore/react-smart-input';
<SelectField
value={country}
onChange={setCountry}
options={[
{ value: 'us', label: 'United States' },
{ value: 'uk', label: 'United Kingdom' },
{ value: 'ca', label: 'Canada' }
]}
placeholder="Select country"
/>7. Multi-Select with Tags
<SelectField
value={skills}
onChange={setSkills}
options={[
{ value: 'react', label: 'React' },
{ value: 'typescript', label: 'TypeScript' },
{ value: 'nodejs', label: 'Node.js' }
]}
placeholder="Select skills"
multiple
showTags
showCheckboxes
showSelectAll
/>8. Chip Component
import { Chip } from '@gridcore/react-smart-input';
<Chip label="React" onRemove={() => {}} primaryColor="purple-600" />
<Chip label="TypeScript" />9. Textarea
import { TextAreaField } from '@gridcore/react-smart-input';
<TextAreaField
value={description}
onChange={setDescription}
placeholder="Enter description"
rows={4}
/>9. Date Picker
import { DatePicker } from '@gridcore/react-smart-input';
<DatePicker
value={birthDate}
onChange={setBirthDate}
placeholder="Select date"
maxDate="2010-12-31"
minDate="1950-01-01"
/>10. Month Picker
import { MonthPicker } from '@gridcore/react-smart-input';
<MonthPicker
value={startMonth}
onChange={setStartMonth}
placeholder="Select month"
/>11. Checkbox
import { CheckboxField } from '@gridcore/react-smart-input';
<CheckboxField
value={agreed}
onChange={setAgreed}
/>12. Using Field Component (Type-based)
import { Field } from '@gridcore/react-smart-input';
// Text input
<Field type="text" value={name} onChange={setName} placeholder="Name" />
// Select
<Field
type="select"
value={country}
onChange={setCountry}
options={[{ value: 'us', label: 'USA' }]}
placeholder="Select country"
/>
// Date
<Field type="date" value={date} onChange={setDate} placeholder="Select date" />
// Textarea
<Field type="textarea" value={bio} onChange={setBio} rows={3} />
// Checkbox
<Field type="checkbox" value={agreed} onChange={setAgreed} />13. With Icons and Suffix
import { Mail, Lock } from 'lucide-react';
<InputField
type="email"
value={email}
onChange={setEmail}
leftIcon={<Mail className="w-4 h-4" />}
placeholder="Email"
/>
<InputField
type="password"
value={password}
onChange={setPassword}
leftIcon={<Lock className="w-4 h-4" />}
placeholder="Password"
/>
<InputField
type="number"
value={price}
onChange={setPrice}
suffix="USD"
placeholder="Price"
/>14. Min/Max Length Validation
<InputField
type="text"
value={username}
onChange={setUsername}
minLength={3}
maxLength={20}
placeholder="Username (3-20 chars)"
/>
<TextAreaField
value={bio}
onChange={setBio}
minLength={10}
maxLength={500}
placeholder="Bio (10-500 chars)"
rows={4}
/>15. JSON Form (Auto-render from Schema)
import { JsonForm } from '@gridcore/react-smart-input';
import { Formik, Form } from 'formik';
import * as Yup from 'yup';
const schema = [
{ name: 'name', type: 'text', label: 'Name', placeholder: 'Enter name', minLength: 3, maxLength: 50 },
{ name: 'email', type: 'email', label: 'Email', placeholder: 'Enter email' },
{ name: 'country', type: 'select', label: 'Country', options: [
{ value: 'us', label: 'United States' },
{ value: 'uk', label: 'United Kingdom' }
]},
{ name: 'bio', type: 'textarea', label: 'Bio', rows: 3, maxLength: 200 },
{ name: 'birthDate', type: 'date', label: 'Birth Date' },
{ name: 'agree', type: 'checkbox', checkboxText: 'I agree to terms' }
];
function MyForm() {
return (
<Formik
initialValues={{ name: '', email: '', country: '', bio: '', birthDate: '', agree: false }}
validationSchema={Yup.object({
name: Yup.string().required('Required'),
email: Yup.string().email('Invalid').required('Required'),
country: Yup.string().required('Required'),
birthDate: Yup.string().required('Required'),
agree: Yup.boolean().oneOf([true], 'Must agree')
})}
onSubmit={(values) => console.log(values)}
>
<Form>
<JsonForm schema={schema} />
<button type="submit">Submit</button>
</Form>
</Formik>
);
}15b. JSON Form with Grid Layout
// 2-column grid layout
const schema = [
{ name: 'firstName', type: 'text', label: 'First Name' },
{ name: 'lastName', type: 'text', label: 'Last Name' },
{ name: 'email', type: 'email', label: 'Email', colSpan: 2 }, // spans 2 columns
{ name: 'phone', type: 'tel', label: 'Phone' },
{ name: 'city', type: 'text', label: 'City' },
{ name: 'bio', type: 'textarea', label: 'Bio', rows: 3, colSpan: 2 } // spans 2 columns
];
<JsonForm schema={schema} columns={2} />
// 3-column grid layout
const schema3Col = [
{ name: 'field1', type: 'text', label: 'Field 1' },
{ name: 'field2', type: 'text', label: 'Field 2' },
{ name: 'field3', type: 'text', label: 'Field 3' },
{ name: 'fullWidth', type: 'textarea', label: 'Full Width', colSpan: 3 }
];
<JsonForm schema={schema3Col} columns={3} />16. Address Form (Common Fields)
import { JsonForm } from '@gridcore/react-smart-input';
import { Formik, Form } from 'formik';
import * as Yup from 'yup';
const addressSchema = [
{ name: 'fullName', type: 'text', label: 'Full Name', placeholder: 'John Doe' },
{ name: 'email', type: 'email', label: 'Email', placeholder: '[email protected]' },
{ name: 'phone', type: 'tel', label: 'Phone Number', placeholder: '+1 (555) 000-0000' },
{ name: 'address1', type: 'text', label: 'Address Line 1', placeholder: '123 Main Street' },
{ name: 'address2', type: 'text', label: 'Address Line 2', placeholder: 'Apt 4B (Optional)' },
{ name: 'city', type: 'text', label: 'City', placeholder: 'New York' },
{ name: 'state', type: 'select', label: 'State/Province', placeholder: 'Select state', options: [
{ value: 'ny', label: 'New York' },
{ value: 'ca', label: 'California' },
{ value: 'tx', label: 'Texas' },
{ value: 'fl', label: 'Florida' }
]},
{ name: 'zipCode', type: 'text', label: 'ZIP/Postal Code', placeholder: '10001', maxLength: 10 },
{ name: 'country', type: 'select', label: 'Country', placeholder: 'Select country', options: [
{ value: 'us', label: 'United States' },
{ value: 'ca', label: 'Canada' },
{ value: 'uk', label: 'United Kingdom' },
{ value: 'au', label: 'Australia' },
{ value: 'de', label: 'Germany' },
{ value: 'fr', label: 'France' },
{ value: 'in', label: 'India' },
{ value: 'jp', label: 'Japan' }
]}
];
function AddressForm() {
return (
<Formik
initialValues={{
fullName: '', email: '', phone: '', address1: '', address2: '',
city: '', state: '', zipCode: '', country: ''
}}
validationSchema={Yup.object({
fullName: Yup.string().required('Name is required'),
email: Yup.string().email('Invalid email').required('Email is required'),
phone: Yup.string().required('Phone is required'),
address1: Yup.string().required('Address is required'),
city: Yup.string().required('City is required'),
state: Yup.string().required('State is required'),
zipCode: Yup.string().required('ZIP code is required'),
country: Yup.string().required('Country is required')
})}
onSubmit={(values) => console.log(values)}
>
<Form>
<JsonForm schema={addressSchema} />
<button type="submit">Submit</button>
</Form>
</Formik>
);
}18. FormWrapper - Jump to Field & Keyboard Shortcuts
import { FormWrapper, InputField, SelectField, TextAreaField } from '@gridcore/react-smart-input';
import { Formik, Form } from 'formik';
// With JsonForm (automatic)
function MyForm() {
return (
<Formik
initialValues={{ employee_name: '', department: '', description: '' }}
onSubmit={handleSubmit}
>
{({ values, submitForm, resetForm }) => (
<Form>
<JsonForm
schema={[
{ name: 'employee_name', type: 'text', label: 'Employee Name' },
{ name: 'department', type: 'select', label: 'Department', options: deptOptions },
{ name: 'description', type: 'textarea', label: 'Description' }
]}
columns={2}
enableFormWrapper={true}
formValues={values}
onSave={submitForm}
onReset={resetForm}
onPrint={() => window.print()}
primaryColor="purple-600"
/>
</Form>
)}
</Formik>
);
}
// Manual wrapper for custom forms
function CustomForm() {
const [formData, setFormData] = useState({
employee_name: '',
department: '',
description: ''
});
return (
<FormWrapper
formFields={formData}
excludeFields={['id', 'created_at']}
onSave={handleSave}
onPrint={() => window.print()}
onReset={handleReset}
primaryColor="purple-600"
>
<InputField
name="employee_name"
label="Employee Name"
value={formData.employee_name}
onChange={(val) => setFormData({...formData, employee_name: val})}
/>
<SelectField
name="department"
label="Department"
value={formData.department}
onChange={(val) => setFormData({...formData, department: val})}
options={deptOptions}
/>
<TextAreaField
name="description"
label="Description"
value={formData.description}
onChange={(val) => setFormData({...formData, description: val})}
/>
</FormWrapper>
);
}Keyboard Shortcuts:
Ctrl+J(Cmd+J on Mac): Jump to fieldCtrl+S(Cmd+S on Mac): Save formCtrl+P(Cmd+P on Mac): Print formCtrl+R(Cmd+R on Mac): Reset form- Right-click: Context menu
Requirements:
- Fields must have
nameprop for jump-to-field to work - Pass
formValuesto JsonForm orformFieldsto FormWrapper
17. Formik Integration
import { FormikField } from '@gridcore/react-smart-input';
import { Formik, Form } from 'formik';
import * as Yup from 'yup';
const validationSchema = Yup.object({
fullName: Yup.string().required('Name is required'),
email: Yup.string().email('Invalid email').required('Required'),
password: Yup.string().min(6, 'Too short').required('Required'),
country: Yup.string().required('Required'),
skills: Yup.array().min(1, 'Select at least one'),
birthDate: Yup.string().required('Required'),
phone: Yup.string().matches(/^[0-9+\-\s()]*$/, 'Invalid phone'),
age: Yup.number().positive().integer(),
bio: Yup.string().max(200, 'Too long'),
terms: Yup.boolean().oneOf([true], 'Must accept')
});
function MyForm() {
return (
<Formik
initialValues={{
fullName: '',
email: '',
password: '',
country: '',
skills: [],
birthDate: '',
phone: '',
age: '',
bio: '',
terms: false
}}
validationSchema={validationSchema}
onSubmit={(values) => {
console.log(values);
}}
>
<Form>
<FormikField
type="text"
name="fullName"
label="Full Name"
placeholder="Enter your name"
/>
<FormikField
type="email"
name="email"
label="Email"
placeholder="Enter email"
/>
<FormikField
type="password"
name="password"
label="Password"
placeholder="Enter password"
/>
<FormikField
type="select"
name="country"
label="Country"
placeholder="Select country"
options={[
{ value: 'us', label: 'United States' },
{ value: 'uk', label: 'United Kingdom' }
]}
/>
<FormikField
type="select"
name="skills"
label="Skills"
placeholder="Select skills"
multiple
showTags
options={[
{ value: 'react', label: 'React' },
{ value: 'typescript', label: 'TypeScript' }
]}
/>
<FormikField
type="date"
name="birthDate"
label="Birth Date"
placeholder="Select date"
/>
<FormikField
type="tel"
name="phone"
label="Phone"
placeholder="Enter phone"
/>
<FormikField
type="number"
name="age"
label="Age"
placeholder="Enter age"
/>
<FormikField
type="textarea"
name="bio"
label="Bio"
placeholder="Tell us about yourself"
rows={4}
/>
<FormikField
type="checkbox"
name="terms"
label="I accept terms and conditions"
/>
<button type="submit">Submit</button>
</Form>
</Formik>
);
}Props
Common Props (All Components)
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| value | string \| boolean \| string[] | - | Field value |
| onChange | function | - | Change handler |
| className | string | '' | Additional CSS classes |
| label | string | - | Field label (renders above field) |
| primaryColor | string | 'purple-600' | Primary color for focus states |
| disabled | boolean | false | Disable field |
InputField Props
| Prop | Type | Description |
|------|------|-------------|
| type | 'text' \| 'email' \| 'password' \| 'number' \| 'tel' \| 'file' | Input type |
| placeholder | string | Placeholder text |
| leftIcon | ReactNode | Icon on left side |
| rightIcon | ReactNode | Icon on right side |
| suffix | string | Suffix text |
| minLength | number | Minimum character length |
| maxLength | number | Maximum character length |
| label | string | Field label |
SelectField Props
| Prop | Type | Description |
|------|------|-------------|
| options | { value: string; label: string }[] | Options array |
| multiple | boolean | Enable multi-select |
| showTags | boolean | Show selected as tags (for multi-select) |
| showCheckboxes | boolean | Show checkboxes (default: true when multiple=true) |
| showSelectAll | boolean | Show "Select All" button (default: true when multiple=true) |
| position | 'top' \| 'bottom' | Dropdown position (auto-adjusts if no space) |
| hideSelectOption | boolean | Hide "Select option" placeholder |
| label | string | Field label |
Chip Props
| Prop | Type | Description |
|------|------|-------------|
| label | string | Chip text content |
| onRemove | () => void | Callback when X button clicked |
| className | string | Additional CSS classes |
| primaryColor | string | Primary color (default: 'purple-600') |
DatePicker Props
| Prop | Type | Description |
|------|------|-------------|
| minDate | string | Minimum date (YYYY-MM-DD) |
| maxDate | string | Maximum date (YYYY-MM-DD) |
| position | 'top' \| 'bottom' \| 'left' \| 'right' | Calendar position (auto-adjusts if no space) |
TextAreaField Props
| Prop | Type | Description |
|------|------|-------------|
| rows | number | Number of rows |
| minLength | number | Minimum character length |
| maxLength | number | Maximum character length |
| label | string | Field label |
FormikField Props
| Prop | Type | Description |
|------|------|-------------|
| name | string | Formik field name (required) |
| label | string | Field label (for non-checkbox fields) |
| checkboxText | string | Label text for checkbox fields |
| showError | boolean | Show validation error message |
JsonForm Props
| Prop | Type | Description |
|------|------|-------------|
| schema | JsonFieldConfig[] | Array of field configurations |
| className | string | Container CSS classes |
| columns | number | Number of columns (1-4, default: 1) |
| enableFormWrapper | boolean | Enable FormWrapper (default: false) |
| formValues | Record<string, any> | Form values for jump-to-field |
| onSave | () => void | Save handler (Ctrl+S) |
| onPrint | () => void | Print handler (Ctrl+P) |
| onReset | () => void | Reset handler (Ctrl+R) |
| primaryColor | string | Primary color (default: 'purple-600') |
| excludeFields | string[] | Fields to exclude from jump list |
Note: Fields in JsonForm have automatic spacing. Use columns prop for grid layout.
JsonFieldConfig
| Prop | Type | Description |
|------|------|-------------|
| name | string | Field name (required) |
| type | string | Field type (required) |
| label | string | Field label |
| checkboxText | string | Label for checkbox (use instead of label) |
| colSpan | number | Column span in grid layout (1-4) |
| placeholder | string | Placeholder text |
| options | array | Options for select fields |
| multiple | boolean | Enable multi-select |
| showTags | boolean | Show tags for multi-select |
| showCheckboxes | boolean | Show checkboxes in multi-select |
| showSelectAll | boolean | Show "Select All" in multi-select |
| minLength | number | Min character length |
| maxLength | number | Max character length |
| rows | number | Rows for textarea |
| showError | boolean | Show validation errors |
| ...any other field props | - | All field-specific props supported |
FormWrapper Props
| Prop | Type | Description |
|------|------|-------------|
| children | ReactNode | Form content (required) |
| formFields | Record<string, any> | Form data object for field list |
| excludeFields | string[] | Fields to exclude from jump list |
| onSave | () => void | Save handler (Ctrl+S) |
| onPrint | () => void | Print handler (Ctrl+P) |
| onReset | () => void | Reset handler (Ctrl+R) |
| primaryColor | string | Highlight color (default: 'purple-600') |
Features
Built-in Label Support
All field components (InputField, SelectField, TextAreaField, DatePicker, MonthPicker, CheckboxField) support a label prop that renders a label above the field. No need for manual label wrappers.
Multi-Select Enhancements
- Checkboxes display by default when
multiple=true - "Select All" button automatically shown for multi-select
- Chip/tag display for selected items
- Clear all button on hover
JSON Form Rendering
Render entire forms from JSON schema with automatic field spacing and full validation support. Supports grid layouts with customizable columns and column spans.
Chip Component
Standalone component for displaying removable tags with customizable colors.
Min/Max Length Validation
InputField and TextAreaField support minLength and maxLength props for character validation.
Auto-positioning Dropdowns
DatePicker, MonthPicker, and SelectField automatically adjust their position (top/bottom) when there's insufficient space in the viewport.
Auto-scroll to Error (Formik)
When form validation fails, automatically scrolls to the first field with an error.
Keyboard Navigation (Select)
- Arrow Up/Down: Navigate options
- Enter: Select highlighted option
- Escape: Close dropdown
Date Input Validation
Automatically validates and formats date input (DD-MM-YYYY).
Password Toggle
Click eye icon to show/hide password.
FormWrapper Features
- Keyboard Shortcuts: Ctrl+J (jump to field), Ctrl+S (save), Ctrl+P (print), Ctrl+R (reset)
- Jump to Field: Press Ctrl+J to open a searchable modal, select a field, and automatically scroll and focus
- Context Menu: Right-click anywhere in the form to access all actions
- Field Highlighting: Jumped fields are highlighted with a colored border for 2 seconds
- Requirements: Fields must have
nameprop for jump-to-field functionality
See FORM_WRAPPER.md for detailed documentation.
Customization
Custom Colors
<InputField
type="text"
value={name}
onChange={setName}
primaryColor="blue-600"
/>Custom Styling
<InputField
type="text"
value={name}
onChange={setName}
className="custom-class"
/>License
MIT
Author
GridCore
