@diludilshad/form-builder-library
v1.0.9
Published
A powerful React library for building dynamic, drag-and-drop forms with a rich set of field types and customization options. Uses Tailwind CSS classes - requires Tailwind CSS as a peer dependency in your project.
Maintainers
Readme
Form Builder Library
A powerful React library for building dynamic, drag-and-drop forms with a rich set of field types and customization options. Uses Tailwind CSS classes - requires Tailwind CSS as a peer dependency in your project.
Features
- 🎨 Visual Form Builder - Drag and drop interface for creating forms
- 📝 Rich Field Types - 25+ field types including text, numbers, choices, dates, uploads, and more
- 🔧 Field Customization - Extensive settings for each field type
- 👀 Real-time Preview - See your form as users will see it
- 📱 Responsive Design - Works perfectly on desktop and mobile
- 💾 Local Storage - Automatic form persistence
- 🎯 Form Validation - Built-in validation rules and custom logic
- 🎨 Icon Support - Choose from 30+ icons for each field
- 🎨 Tailwind CSS - Uses Tailwind utility classes for styling
- 📦 Minimal Dependencies - Only React, React DOM, and Tailwind CSS required
Installation
npm install @diludilshad/form-builder-libraryPrerequisites
This library requires Tailwind CSS to be installed and configured in your project. If you haven't already set up Tailwind CSS, follow these steps:
- Install Tailwind CSS:
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p- Configure your
tailwind.config.js:
/** @type {import('tailwindcss').Config} */
export default {
content: [
"./index.html",
"./src/**/*.{js,ts,jsx,tsx}",
// Add this line to scan the form builder library
"./node_modules/@diludilshad/form-builder-library/**/*.{js,jsx}",
],
theme: {
extend: {},
},
plugins: [],
};- Add Tailwind directives to your CSS:
@tailwind base;
@tailwind components;
@tailwind utilities;Why Peer Dependency?
The Form Builder Library uses Tailwind CSS classes for styling. By using Tailwind as a peer dependency instead of bundling it:
- ✅ No Style Conflicts - Avoids duplicate Tailwind base styles
- ✅ Consistent Theming - Components use your project's Tailwind configuration
- ✅ Smaller Bundle Size - No duplicate CSS utilities
- ✅ Customization - Easy to customize colors, spacing, and other design tokens
Using in Your Project
Step 1: Create a New React Project
# Create a new React project
npx create-react-app my-form-app
cd my-form-app
# Or with Vite (recommended)
npm create vite@latest my-form-app -- --template react
cd my-form-app
npm installStep 2: Install Dependencies
# Install the form builder library
npm install @diludilshad/form-builder-library
# Install required peer dependencies
npm install tailwindcss postcss autoprefixerStep 3: Setup Tailwind CSS
# Initialize Tailwind
npx tailwindcss init -pUpdate your tailwind.config.js:
/** @type {import('tailwindcss').Config} */
export default {
content: [
"./index.html",
"./src/**/*.{js,ts,jsx,tsx}",
// IMPORTANT: Include the form builder library
"./node_modules/@diludilshad/form-builder-library/**/*.{js,jsx}",
],
theme: {
extend: {
// You can extend the theme to customize form builder appearance
colors: {
primary: {
50: "#eff6ff",
500: "#3b82f6",
600: "#2563eb",
700: "#1d4ed8",
},
},
},
},
plugins: [],
};Add to your src/index.css:
@tailwind base;
@tailwind components;
@tailwind utilities;Step 4: Basic Implementation
Create src/App.jsx:
import React, { useState } from "react";
import { BuilderForm, FormReader } from "@diludilshad/form-builder-library";
function App() {
const [currentView, setCurrentView] = useState("builder");
const [form, setForm] = useState({
name: "",
type: "",
description: "",
structure: [],
formsRules: [],
});
const handleSave = (formData) => {
console.log("Form saved:", formData);
setForm(formData);
// Here you would typically save to your backend
};
const handleFormSubmit = (values) => {
console.log("Form submitted:", values);
// Handle form submission
};
return (
<div className="min-h-screen bg-gray-100">
{/* Navigation */}
<nav className="bg-white shadow-sm border-b px-6 py-4">
<div className="flex space-x-4">
<button
onClick={() => setCurrentView("builder")}
className={`px-4 py-2 rounded-md ${
currentView === "builder"
? "bg-blue-500 text-white"
: "bg-gray-200 text-gray-700"
}`}
>
Form Builder
</button>
<button
onClick={() => setCurrentView("reader")}
className={`px-4 py-2 rounded-md ${
currentView === "reader"
? "bg-blue-500 text-white"
: "bg-gray-200 text-gray-700"
}`}
disabled={!form.structure?.length}
>
Form Preview
</button>
</div>
</nav>
{/* Content */}
{currentView === "builder" ? (
<BuilderForm
editFormId="demo-form"
form={form}
setForm={setForm}
onSave={handleSave}
/>
) : (
<div className="p-6">
<div className="max-w-2xl mx-auto bg-white rounded-lg shadow-sm p-6">
<FormReader
formData={form}
onSubmit={handleFormSubmit}
onFieldChange={(fieldId, value) => {
console.log(`Field ${fieldId} changed:`, value);
}}
/>
</div>
</div>
)}
</div>
);
}
export default App;Quick Start
Basic Form Builder
import React, { useState } from "react";
import { BuilderForm } from "@diludilshad/form-builder-library";
function App() {
const [form, setForm] = useState({
name: "",
type: "",
description: "",
structure: [],
formsRules: [],
});
const handleSave = (formData) => {
console.log("Form saved:", formData);
setForm(formData);
};
return (
<BuilderForm
editFormId="my-form-1"
form={form}
setForm={setForm}
onSave={handleSave}
/>
);
}Form Reader (Display Forms)
import React from "react";
import { FormReader } from "@diludilshad/form-builder-library";
function FormDisplay() {
const formData = {
name: "Contact Form",
description: "Please fill out this contact form",
structure: [
{
id: "name",
type: "single-line",
label: "Full Name",
placeholder: "Enter your full name",
required: true,
selectedIcon: "person",
},
{
id: "email",
type: "email",
label: "Email Address",
placeholder: "Enter your email",
required: true,
selectedIcon: "mail",
},
],
};
const handleSubmit = (values) => {
console.log("Form submitted:", values);
};
return (
<FormReader
formData={formData}
onSubmit={handleSubmit}
onFieldChange={(fieldId, value) => console.log(fieldId, value)}
/>
);
}Components
BuilderForm
The main form builder component with drag-and-drop functionality.
Props
| Prop | Type | Required | Default | Description |
| ------------ | -------- | -------- | ------- | ---------------------------------------------------------- |
| editFormId | string | Yes | - | Unique identifier for the form (used for localStorage key) |
| form | object | Yes | - | Current form state object |
| setForm | function | Yes | - | Function to update form state |
| onSave | function | No | - | Callback function called when form is saved |
Form Object Structure
{
name: string, // Form name
type: string, // Form type
description: string, // Form description
structure: array, // Array of form fields
formsRules: array // Array of validation rules
}FormReader
Component for displaying and collecting data from forms.
Props
| Prop | Type | Required | Default | Description |
| ------------------ | -------- | -------- | -------- | ------------------------------------ |
| formData | object | Yes | - | Form data object with structure |
| onSubmit | function | Yes | - | Called when form is submitted |
| onFieldChange | function | No | - | Called when any field value changes |
| initialValues | object | No | {} | Initial values for form fields |
| customSubmitText | string | No | "Submit" | Custom submit button text |
| customCancelText | string | No | "Cancel" | Custom cancel button text |
| onCancel | function | No | - | Called when cancel button is clicked |
| className | string | No | "" | Additional CSS classes |
| formRules | array | No | [] | Form validation rules |
FormPreview
Component for previewing forms in builder mode.
Props
| Prop | Type | Required | Default | Description |
| --------------- | -------- | -------- | ------- | ------------------------------- |
| formFields | array | Yes | - | Array of form fields |
| previewData | object | No | {} | Preview data |
| isTestMode | boolean | No | false | Whether in test mode |
| formRules | array | No | [] | Form validation rules |
| onExit | function | Yes | - | Called when exiting preview |
| onSubmit | function | Yes | - | Called when form is submitted |
| onFieldUpdate | function | No | - | Called when field values change |
Field Types
Basic Information Fields
- Name (
name) - Person icon, blue color - Address (
address) - Location icon, green color - Phone (
phone) - Call icon, purple color - Email (
email) - Mail icon, red color - Website (
website) - Globe icon, indigo color
Text Fields
- Single Line (
single-line) - Document icon, orange color - Dynamic Single Line (
dynamic-single-line) - Document icon, orange color - Multi Line (
multi-line) - Reader icon, teal color - Rich Text (
rich-text) - Options icon, indigo color
Number Fields
- Number (
number) - 123 icon, purple color - Decimal (
decimal) - .00 icon, emerald color - Formula (
formula) - fx icon, pink color - Currency (
currency) - Wallet icon, yellow color
Choice Fields
- Dropdown (
dropdown) - Chevron down icon, blue color - Radio (
radio) - Radio button icon, green color - Checkbox (
checkbox) - Checkbox icon, purple color - Multiple Choice (
multiple-choice) - List icon, teal color - Image Choices (
image-choices) - Images icon, pink color - Matrix Choice (
matrix-choice) - Grid icon, indigo color - Table (
table) - Grid icon, orange color
Date & Time Fields
- Date (
date) - Calendar icon, orange color - Time (
time) - Time icon, blue color - Date-Time (
date-time) - Calendar clear icon, green color - Month-Year (
month-year) - MY icon, amber color
Upload Fields
- File Upload (
file-upload) - Document attach icon, green color - Image Upload (
image-upload) - Cloud upload icon, teal color - Audio/Video Upload (
audio-video-upload) - Musical notes icon, purple color
Rating & Scale Fields
- Rating (
rating) - Star icon, yellow color - Slider (
slider) - Options icon, pink color
Layout Fields
- Section (
section-header) - Remove icon, gray color
Field Structure
Each field in the form structure has the following properties:
{
id: string, // Unique field identifier
type: string, // Field type (see above)
label: string, // Field label
placeholder: string, // Field placeholder text
required: boolean, // Whether field is required
selectedIcon: string, // Icon identifier
iconColor: string, // Icon color class
options: array, // Options for choice fields
validation: object, // Field-specific validation rules
settings: object, // Field-specific settings
// ... other field-specific properties
}Form Rules
Form rules allow you to create conditional logic and validation:
{
id: string, // Unique rule identifier
name: string, // Rule name
conditions: array, // Array of conditions
actions: array, // Array of actions
enabled: boolean // Whether rule is active
}LocalStorage Persistence
The BuilderForm component automatically saves form data to localStorage using the editFormId as the key:
localStorage.setItem(`form_${editFormId}`, JSON.stringify(formData));Available Icons
The library includes 30+ icons from react-icons/io5:
person,location,call,mail,globedocument,reader,wallet,calendar,timebusiness,briefcase,home,car,airplanetrain,bus,restaurant,shirt,ticketid-card,checkmark,heart,music,cameragame,book,school,medical,fitnesspalette
Examples
Complete Example with Both Builder and Reader
import React, { useState } from "react";
import { BuilderForm, FormReader } from "@diludilshad/form-builder-library";
function FormBuilderApp() {
const [formData, setFormData] = useState(null);
const [isBuilderMode, setIsBuilderMode] = useState(true);
const [formValues, setFormValues] = useState({});
const handleSaveForm = (formData) => {
console.log("Form saved:", formData);
setFormData(formData);
};
const handleFormSubmit = (values) => {
console.log("Form submitted:", values);
setFormValues(values);
alert("Form submitted successfully!");
};
return (
<div className="min-h-screen bg-gray-50">
<div className="max-w-7xl mx-auto py-8 px-4">
<div className="text-center mb-8">
<h1 className="text-3xl font-bold text-gray-900 mb-4">
Form Builder Library
</h1>
<div className="flex justify-center space-x-4 mb-8">
<button
onClick={() => setIsBuilderMode(true)}
className={`px-4 py-2 rounded-md font-medium ${
isBuilderMode
? "bg-blue-600 text-white"
: "bg-white text-gray-700 border border-gray-300 hover:bg-gray-50"
}`}
>
Builder Mode
</button>
<button
onClick={() => setIsBuilderMode(false)}
className={`px-4 py-2 rounded-md font-medium ${
!isBuilderMode
? "bg-blue-600 text-white"
: "bg-white text-gray-700 border border-gray-300 hover:bg-gray-50"
}`}
>
Reader Mode
</button>
</div>
</div>
{isBuilderMode ? (
<BuilderForm
editFormId="example-form"
form={
formData || {
name: "",
type: "",
description: "",
structure: [],
formsRules: [],
}
}
setForm={setFormData}
onSave={handleSaveForm}
/>
) : (
formData && (
<div className="max-w-2xl mx-auto">
<FormReader
formData={formData}
onSubmit={handleFormSubmit}
onFieldChange={(fieldId, value) =>
console.log("Field changed:", fieldId, value)
}
/>
</div>
)
)}
</div>
</div>
);
}
export default FormBuilderApp;Custom Form with Validation
import React from "react";
import { FormReader } from "@diludilshad/form-builder-library";
function CustomForm() {
const formData = {
name: "Registration Form",
description: "Please complete your registration",
structure: [
{
id: "fullName",
type: "single-line",
label: "Full Name",
placeholder: "Enter your full name",
required: true,
selectedIcon: "person",
validation: {
minLength: 2,
maxLength: 50,
pattern: "^[a-zA-Z\\s]+$",
},
},
{
id: "email",
type: "email",
label: "Email Address",
placeholder: "Enter your email",
required: true,
selectedIcon: "mail",
validation: {
pattern: "^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$",
},
},
{
id: "country",
type: "dropdown",
label: "Country",
placeholder: "Select your country",
required: true,
selectedIcon: "location",
options: [
{ value: "us", label: "United States" },
{ value: "uk", label: "United Kingdom" },
{ value: "ca", label: "Canada" },
{ value: "au", label: "Australia" },
],
},
],
};
const formRules = [
{
id: "email-validation",
name: "Email Validation",
conditions: [
{
fieldId: "email",
operator: "contains",
value: "@",
},
],
actions: [
{
type: "show_field",
fieldId: "fullName",
},
],
enabled: true,
},
];
return (
<FormReader
formData={formData}
formRules={formRules}
onSubmit={(values) => {
console.log("Registration submitted:", values);
// Handle form submission
}}
onFieldChange={(fieldId, value) => {
console.log(`${fieldId} changed to:`, value);
}}
customSubmitText="Register"
customCancelText="Back"
/>
);
}Development
Prerequisites
- Node.js >= 16.0.0
- React >= 18.0.0
- React DOM >= 18.0.0
Installation
git clone https://github.com/diludilshad/form-builder-library.git
cd form-builder-library
npm installDevelopment Server
npm run devBuilding
npm run buildType Checking
npm run type-checkLinting
npm run lintAdvanced Usage & Integration
Backend Integration
Saving Forms to Database
import React, { useState, useEffect } from "react";
import { BuilderForm } from "@diludilshad/form-builder-library";
function FormBuilderPage() {
const [form, setForm] = useState(null);
const [loading, setLoading] = useState(true);
// Load existing form
useEffect(() => {
const loadForm = async () => {
try {
const response = await fetch("/api/forms/123");
const formData = await response.json();
setForm(formData);
} catch (error) {
console.error("Failed to load form:", error);
setForm({
name: "",
type: "",
description: "",
structure: [],
formsRules: [],
});
} finally {
setLoading(false);
}
};
loadForm();
}, []);
const handleSave = async (formData) => {
try {
const response = await fetch("/api/forms/123", {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(formData),
});
if (response.ok) {
console.log("Form saved successfully!");
setForm(formData);
}
} catch (error) {
console.error("Failed to save form:", error);
}
};
if (loading) return <div className="p-6">Loading...</div>;
return (
<BuilderForm
editFormId="form-123"
form={form}
setForm={setForm}
onSave={handleSave}
/>
);
}Processing Form Submissions
import React from "react";
import { FormReader } from "@diludilshad/form-builder-library";
function PublicForm({ formId }) {
const [formData, setFormData] = useState(null);
useEffect(() => {
fetch(`/api/forms/${formId}/public`)
.then((res) => res.json())
.then(setFormData);
}, [formId]);
const handleSubmit = async (values) => {
try {
const response = await fetch(`/api/forms/${formId}/submissions`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
formId,
submittedAt: new Date().toISOString(),
values,
}),
});
if (response.ok) {
alert("Form submitted successfully!");
}
} catch (error) {
console.error("Submission failed:", error);
alert("Failed to submit form. Please try again.");
}
};
if (!formData) return <div>Loading form...</div>;
return (
<div className="max-w-2xl mx-auto p-6">
<FormReader
formData={formData}
onSubmit={handleSubmit}
onFieldChange={(fieldId, value) => {
// Optional: Auto-save draft
localStorage.setItem(
`draft_${formId}`,
JSON.stringify({
...JSON.parse(localStorage.getItem(`draft_${formId}`) || "{}"),
[fieldId]: value,
})
);
}}
/>
</div>
);
}Framework Integration
Next.js Setup
// next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
transpilePackages: ["@diludilshad/form-builder-library"],
};
module.exports = nextConfig;// tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
"./pages/**/*.{js,ts,jsx,tsx,mdx}",
"./components/**/*.{js,ts,jsx,tsx,mdx}",
"./app/**/*.{js,ts,jsx,tsx,mdx}",
// Include form builder library
"./node_modules/@diludilshad/form-builder-library/**/*.{js,jsx}",
],
theme: {
extend: {},
},
plugins: [],
};Vite Setup
// vite.config.js
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
export default defineConfig({
plugins: [react()],
optimizeDeps: {
include: ["@diludilshad/form-builder-library"],
},
});Custom Styling & Theming
Override Default Colors
// tailwind.config.js
module.exports = {
theme: {
extend: {
colors: {
// Override primary colors used by form builder
primary: {
50: "#fdf2f8",
500: "#ec4899", // Pink instead of blue
600: "#db2777",
700: "#be185d",
},
},
},
},
};Custom CSS Classes
/* src/index.css */
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer components {
/* Customize form builder styles */
.form-builder-container {
@apply bg-gradient-to-br from-purple-50 to-pink-50;
}
.form-field-item {
@apply border-purple-200 hover:border-purple-400;
}
.form-builder-button {
@apply bg-gradient-to-r from-purple-600 to-pink-600 hover:from-purple-700 hover:to-pink-700;
}
}State Management Integration
Redux Integration
import { useSelector, useDispatch } from "react-redux";
import { BuilderForm } from "@diludilshad/form-builder-library";
import { updateForm, saveForm } from "./store/formSlice";
function ReduxFormBuilder() {
const dispatch = useDispatch();
const form = useSelector((state) => state.forms.currentForm);
return (
<BuilderForm
editFormId="redux-form"
form={form}
setForm={(formData) => dispatch(updateForm(formData))}
onSave={(formData) => dispatch(saveForm(formData))}
/>
);
}Performance Optimization
Lazy Loading
import React, { lazy, Suspense } from "react";
// Lazy load the form builder
const BuilderForm = lazy(() =>
import("@diludilshad/form-builder-library").then((module) => ({
default: module.BuilderForm,
}))
);
function App() {
return (
<Suspense fallback={<div className="p-6">Loading Form Builder...</div>}>
<BuilderForm {...props} />
</Suspense>
);
}Troubleshooting
Common Issues
1. Styles not applying:
# Make sure Tailwind is scanning the library
# Check your tailwind.config.js includes:
"./node_modules/@diludilshad/form-builder-library/**/*.{js,jsx}"2. TypeScript errors:
// Add to your tsconfig.json
{
"compilerOptions": {
"moduleResolution": "node",
"skipLibCheck": true
}
}3. Build errors in production:
// For Webpack-based builds, add to webpack.config.js
module.exports = {
resolve: {
alias: {
"@diludilshad/form-builder-library": require.resolve(
"@diludilshad/form-builder-library"
),
},
},
};Browser Support
- Chrome >= 88
- Firefox >= 85
- Safari >= 14
- Edge >= 88
License
MIT License - see LICENSE file for details.
Contributing
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Support
- 📧 Email: [email protected]
- 🐛 Issues: GitHub Issues
- 📖 Documentation: GitHub Wiki
Changelog
v1.0.5
- Added 30+ field types
- Improved drag and drop functionality
- Enhanced form validation
- Added icon support
- Bundled Tailwind CSS
- Zero additional dependencies
Made with ❤️ by Dilshad
