A powerful and flexible form builder and renderer library built with React, TypeScript, and Tailwind CSS. Create dynamic forms with advanced features like conditional logic, validation, and repeatable sections.
npm install formcrafter
import { FormBuilder, FormRenderer, FormBuilderProvider, ThemeProvider } from 'formcrafter';
function App() {
const handleSubmit = (data: Record<string, any>) => {
console.log('Form submitted:', data);
};
return (
<ThemeProvider defaultTheme="light" storageKey="theme">
<FormBuilderProvider>
<div className="container mx-auto">
<FormBuilder />
<FormRenderer onSubmit={handleSubmit} />
</div>
</FormBuilderProvider>
</ThemeProvider>
);
}
The form schema defines the structure and behavior of your form:
interface FormSchema {
title: string;
description: string;
fields: FormField[];
settings: {
showProgressBar: boolean;
showPageTitles: boolean;
confirmationMessage: string;
};
}
interface FormField {
id: string;
type: FieldType;
label: string;
required: boolean;
placeholder?: string;
helpText?: string;
options?: FieldOption[];
validations?: FieldValidation;
conditions?: Condition[];
subFields?: FormField[]; // For repeatable sections
}
interface FieldValidation {
min?: number;
max?: number;
minLength?: number;
maxLength?: number;
pattern?: string;
customMessage?: string;
allowedFileTypes?: string[];
maxFileSize?: number;
maxFiles?: number;
}
Built-in validation using Zod with support for:
// Text field validation
const textValidation = {
minLength: 3,
maxLength: 100,
pattern: '^[A-Za-z0-9]+$',
customMessage: 'Please enter alphanumeric characters only'
};
// Number field validation
const numberValidation = {
min: 0,
max: 100,
customMessage: 'Please enter a number between 0 and 100'
};
// File upload validation
const fileValidation = {
maxFileSize: 5000000, // 5MB
allowedFileTypes: ['.jpg', '.png', '.pdf'],
maxFiles: 3
};
Show or hide fields based on other field values:
const conditions = [
{
sourceFieldId: 'question1',
operator: 'equals',
value: 'yes'
},
{
sourceFieldId: 'age',
operator: 'greaterThan',
value: 18
}
];
Supported operators:
equals
notEquals
contains
notContains
greaterThan
lessThan
isEmpty
isNotEmpty
FormCrafter uses Tailwind CSS with a fully customizable theme:
// tailwind.config.js
module.exports = {
theme: {
extend: {
colors: {
primary: {
DEFAULT: 'hsl(var(--primary))',
foreground: 'hsl(var(--primary-foreground))',
},
secondary: {
DEFAULT: 'hsl(var(--secondary))',
foreground: 'hsl(var(--secondary-foreground))',
},
// Add custom colors
},
borderRadius: {
lg: 'var(--radius)',
md: 'calc(var(--radius) - 2px)',
sm: 'calc(var(--radius) - 4px)',
},
}
}
};
import { z } from 'zod';
const customValidation = z.object({
email: z.string().email('Invalid email format'),
password: z.string()
.min(8, 'Password must be at least 8 characters')
.regex(/[A-Z]/, 'Password must contain at least one uppercase letter')
.regex(/[0-9]/, 'Password must contain at least one number'),
});
Create dynamic form sections:
const repeatableField = {
id: 'contacts',
type: 'repeatable',
label: 'Contact Information',
subFields: [
{
id: 'name',
type: 'text',
label: 'Name',
required: true
},
{
id: 'email',
type: 'email',
label: 'Email',
required: true
}
],
validations: {
min: 1,
max: 5
}
};
Create grid-based survey questions:
const matrixField = {
id: 'satisfaction',
type: 'matrix',
label: 'Satisfaction Survey',
options: [
{ id: '1', value: 'row1', label: 'Service Quality' },
{ id: '2', value: 'row2', label: 'Response Time' },
{ id: '3', value: 'col1', label: 'Poor', isColumn: true },
{ id: '4', value: 'col2', label: 'Fair', isColumn: true },
{ id: '5', value: 'col3', label: 'Good', isColumn: true }
]
};
FormCrafter supports all modern browsers:
We welcome contributions! Please follow these steps:
FormCrafter is MIT licensed.