UNPKG

finform-react-builder

Version:

A powerful, flexible React form builder with dynamic field rendering, custom validation, multi-step forms, Material-UI integration, image component support, toggle/radio buttons, switches, autocomplete, and advanced button positioning

621 lines (539 loc) 14.1 kB
# finform-react-builder A powerful, flexible React form builder with dynamic field rendering, custom validation, and Material-UI integration. [![npm version](https://badge.fury.io/js/finform-react-builder.svg)](https://www.npmjs.com/package/finform-react-builder) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) ## 🚨 Migration Notice **If you're currently using this package from GitHub Packages**, you'll need to update your installation: ```bash # Remove the old package npm uninstall @finflow-analytics/finform-react-builder # Install from public npm registry npm install finform-react-builder ``` If you have a `.npmrc` file with GitHub Packages configuration, remove the line: ``` @finflow-analytics:registry=https://npm.pkg.github.com ``` ## ✨ Features - 🎨 **Material-UI Integration** - Beautiful, responsive form components - 🔧 **Dynamic Field Rendering** - Support for text, email, password, number, select, checkbox, date, and textarea fields - ✅ **Advanced Validation** - Built-in validation with custom regex patterns and validation functions - 📱 **Responsive Grid System** - Flexible column-based layout system - 🎯 **TypeScript Support** - Full type safety and IntelliSense support - 🚀 **Easy Integration** - Simple API with sensible defaults - 🔄 **Real-time Validation** - Instant feedback with react-hook-form - 🎨 **Customizable** - Highly configurable with custom validation rules - 🔄 **Multi-Step Forms** - Support for step-by-step form completion with smart navigation - 💾 **Stateless Design** - Works with data from backend/config without local storage dependencies ## 📦 Installation ```bash npm install finform-react-builder ``` ### Peer Dependencies Make sure you have the required peer dependencies installed: ```bash npm install react react-dom @mui/material @emotion/react @emotion/styled ``` ## 🚀 Quick Start ```tsx import React from 'react'; import { FinForm, FieldConfig } from 'finform-react-builder'; const fields: FieldConfig[] = [ { name: 'firstName', label: 'First Name', type: 'text', placeholder: 'Enter your first name', required: true, col: 6 }, { name: 'lastName', label: 'Last Name', type: 'text', placeholder: 'Enter your last name', required: true, col: 6 }, { name: 'email', label: 'Email', type: 'email', placeholder: 'Enter your email', required: true, col: 12 } ]; function App() { const handleSubmit = (data: any) => { console.log('Form submitted:', data); }; return ( <FinForm fields={fields} onSubmit={handleSubmit} submitButtonText="Submit Form" /> ); } export default App; ``` ## 📋 Field Types ### Text Fields ```tsx { name: 'username', label: 'Username', type: 'text', placeholder: 'Enter username', validation: { pattern: /^[a-zA-Z0-9_]+$/, message: 'Username can only contain letters, numbers, and underscores' } } ``` ### Email Fields ```tsx { name: 'email', label: 'Email Address', type: 'email', placeholder: 'Enter your email', required: true } ``` ### Number Fields ```tsx { name: 'age', label: 'Age', type: 'number', placeholder: 'Enter your age', validation: { min: 18, max: 120, message: 'Age must be between 18 and 120' } } ``` ### Select Fields ```tsx { name: 'country', label: 'Country', type: 'select', options: [ { label: 'United States', value: 'us' }, { label: 'Canada', value: 'ca' }, { label: 'United Kingdom', value: 'uk' } ], required: true } ``` ### Date Fields ```tsx { name: 'birthDate', label: 'Birth Date', type: 'date', validation: { custom: (value) => { const today = new Date(); const birthDate = new Date(value); return birthDate < today; }, message: 'Birth date must be in the past' } } ``` ### Image Fields ```tsx { name: 'profileImage', label: 'Profile Image', type: 'image', src: 'https://example.com/image.jpg', alt: 'User profile image', width: 300, height: 200, style: { border: '2px solid #e0e0e0', borderRadius: '8px' }, onClick: () => { console.log('Image clicked!'); } } ``` ### Textarea Fields ```tsx { name: 'bio', label: 'Biography', type: 'textarea', placeholder: 'Tell us about yourself...', validation: { maxLength: 500, message: 'Biography must be less than 500 characters' } } ``` ### Checkbox Fields ```tsx { name: 'newsletter', label: 'Subscribe to Newsletter', type: 'checkbox', required: true } ``` ## 🔧 Advanced Validation ### Custom Regex Patterns ```tsx { name: 'phoneNumber', label: 'Phone Number', type: 'text', placeholder: '+1 (555) 123-4567', validation: { pattern: /^\+?[1-9]\d{1,14}$/, message: 'Please enter a valid phone number' } } ``` ### Custom Validation Functions ```tsx { name: 'password', label: 'Password', type: 'password', placeholder: 'Enter password', validation: { minLength: 8, custom: (value) => { const hasUpperCase = /[A-Z]/.test(value); const hasLowerCase = /[a-z]/.test(value); const hasNumbers = /\d/.test(value); const hasSpecialChar = /[!@#$%^&*(),.?":{}|<>]/.test(value); return hasUpperCase && hasLowerCase && hasNumbers && hasSpecialChar; }, message: 'Password must contain uppercase, lowercase, number and special character' } } ``` ## 📐 Grid System Use the responsive grid system to control field layout: ```tsx // Full width field { name: 'description', type: 'textarea', col: 12 } // Half width fields { name: 'firstName', type: 'text', col: 6 } { name: 'lastName', type: 'text', col: 6 } // Responsive breakpoints { name: 'address', type: 'text', xs: 12, // Full width on extra small screens md: 8, // 8/12 width on medium screens lg: 6 // Half width on large screens } ``` ## 🔄 Multi-Step Forms FinForm supports multi-step forms with smart navigation and completion tracking. Perfect for complex forms that need to be broken down into manageable steps. ### Basic Multi-Step Form ```tsx const multiStepFields: FieldConfig[] = [ // Step 1: Personal Information { name: 'firstName', label: 'First Name', type: 'text', required: true, step: 1, col: 6, }, { name: 'lastName', label: 'Last Name', type: 'text', required: true, step: 1, col: 6, }, { name: 'email', label: 'Email Address', type: 'email', required: true, step: 1, col: 12, }, // Step 2: Address Information { name: 'street', label: 'Street Address', type: 'text', required: true, step: 2, col: 12, }, { name: 'city', label: 'City', type: 'text', required: true, step: 2, col: 6, }, { name: 'state', label: 'State', type: 'select', required: true, step: 2, col: 3, options: [ { label: 'California', value: 'CA' }, { label: 'New York', value: 'NY' }, { label: 'Texas', value: 'TX' }, ], }, { name: 'zipCode', label: 'ZIP Code', type: 'text', required: true, step: 2, col: 3, validation: { pattern: /^\d{5}(-\d{4})?$/, message: 'Please enter a valid ZIP code', }, }, // Step 3: Preferences { name: 'newsletter', label: 'Subscribe to Newsletter', type: 'checkbox', step: 3, col: 12, }, { name: 'preferences', label: 'Communication Preferences', type: 'select', step: 3, col: 6, options: [ { label: 'Email', value: 'email' }, { label: 'Phone', value: 'phone' }, { label: 'Both', value: 'both' }, ], }, ]; function MultiStepForm() { const [currentStep, setCurrentStep] = useState(1); const handleStepChange = (step: number, totalSteps: number) => { console.log(`Moving to step ${step} of ${totalSteps}`); setCurrentStep(step); }; return ( <FinForm fields={multiStepFields} onSubmit={(data) => console.log('Form submitted:', data)} isMultiStep={true} currentStep={currentStep} onStepChange={handleStepChange} submitButtonText="Complete Registration" stepNavigationProps={{ showStepNumbers: true, showStepTitles: true, stepTitles: ['Personal Info', 'Address', 'Preferences'], }} /> ); } ``` ### Smart Step Navigation with Backend Data The form automatically detects completed steps and starts from the first incomplete step when data is provided: ```tsx // Data from backend showing user has completed step 1 const backendData = { firstName: 'John', lastName: 'Doe', email: 'john.doe@example.com', // Step 2 and 3 are empty }; function SmartMultiStepForm() { return ( <FinForm fields={multiStepFields} onSubmit={(data) => console.log('Form submitted:', data)} defaultValues={backendData} isMultiStep={true} // Form will automatically start at step 2 since step 1 is complete submitButtonText="Complete Registration" /> ); } ``` ### Multi-Step Form Props | Prop | Type | Description | Default | |------|------|-------------|---------| | `isMultiStep` | `boolean` | Enable multi-step functionality | `false` | | `currentStep` | `number` | Current step (controlled by parent) | `1` | | `onStepChange` | `(step: number, totalSteps: number) => void` | Step change callback | - | | `showStepNavigation` | `boolean` | Show step navigation | `true` | | `stepNavigationProps` | `object` | Step navigation configuration | `{}` | ### Step Navigation Configuration ```tsx stepNavigationProps={{ showStepNumbers: true, // Show step numbers showStepTitles: true, // Show step titles stepTitles: ['Step 1', 'Step 2', 'Step 3'], // Custom step titles }} ``` ### Field Step Assignment Add a `step` property to any field to assign it to a specific step: ```tsx { name: 'fieldName', label: 'Field Label', type: 'text', step: 1, // This field will appear in step 1 required: true, } ``` ## 🎛️ API Reference ### FinForm Props | Prop | Type | Description | Required | |------|------|-------------|----------| | `fields` | `FieldConfig[]` | Array of field configurations | ✅ | | `onSubmit` | `(data: any) => void` | Form submission handler | ✅ | | `onChange` | `(data: any) => void` | Form change handler | ❌ | | `submitButtonText` | `string` | Submit button text | ❌ | | `defaultValues` | `Record<string, any>` | Default form values | ❌ | | `isMultiStep` | `boolean` | Enable multi-step functionality | ❌ | | `currentStep` | `number` | Current step (controlled by parent) | ❌ | | `onStepChange` | `(step: number, totalSteps: number) => void` | Step change callback | ❌ | | `showStepNavigation` | `boolean` | Show step navigation | ❌ | | `stepNavigationProps` | `object` | Step navigation configuration | ❌ | ### Field Configuration ```tsx interface BaseField { name: string; label: string; type: 'text' | 'email' | 'password' | 'number' | 'select' | 'checkbox' | 'date' | 'textarea' | 'image'; placeholder?: string; required?: boolean; disabled?: boolean; validation?: ValidationRule; step?: number; // Step number for multi-step forms (1-based) col?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12; xs?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12; sm?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12; md?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12; lg?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12; xl?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12; } interface ImageField extends BaseField { type: 'image'; src?: string; // Image source URL alt?: string; // Alt text for accessibility width?: number | string; // Image width height?: number | string; // Image height style?: React.CSSProperties; // Custom styles className?: string; // Custom CSS class onClick?: () => void; // Click handler } ``` ### Validation Rules ```tsx interface ValidationRule { pattern?: string | RegExp; message?: string; required?: boolean; minLength?: number; maxLength?: number; min?: number; max?: number; custom?: (value: any) => boolean | string; } ``` ## 💡 Examples ### Complete Registration Form ```tsx const registrationFields: FieldConfig[] = [ { name: 'firstName', label: 'First Name', type: 'text', placeholder: 'Enter first name', required: true, col: 6 }, { name: 'lastName', label: 'Last Name', type: 'text', placeholder: 'Enter last name', required: true, col: 6 }, { name: 'email', label: 'Email', type: 'email', placeholder: 'Enter email address', required: true, col: 12 }, { name: 'password', label: 'Password', type: 'password', placeholder: 'Enter password', required: true, col: 6, validation: { minLength: 8, pattern: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]/, message: 'Password must be at least 8 characters with uppercase, lowercase, number and special character' } }, { name: 'confirmPassword', label: 'Confirm Password', type: 'password', placeholder: 'Confirm password', required: true, col: 6 }, { name: 'agreeToTerms', label: 'I agree to the Terms and Conditions', type: 'checkbox', required: true, col: 12 } ]; ``` ## 🛠️ Development ### Building the Library ```bash # Build for production npm run build:lib # Build types only npm run build:types ``` ### Running Development Server ```bash npm run dev ``` ## 📄 License MIT © [Ritik](https://github.com/finflow-analytics/finform) ## 🤝 Contributing Contributions, issues and feature requests are welcome! Feel free to check [issues page](https://github.com/finflow-analytics/finform/issues). ## 📞 Support If you like this project, please ⭐ star it on [GitHub](https://github.com/finflow-analytics/finform)!