extended-dynamic-forms
Version:
Extended React JSON Schema Form (RJSF) v6 with custom components, widgets, templates, layouts, and form events
1,156 lines (935 loc) โข 37.4 kB
Markdown
# Extended Dynamic Forms
**A revolutionary extension library for [React JSON Schema Form (RJSF)](https://github.com/rjsf-team/react-jsonschema-form)** that transforms schema-driven forms into sophisticated, enterprise-ready applications with O(N) performance and professional UI components.
Built on top of the excellent RJSF v6 foundation, this library introduces the **Three Pillars v2 Architecture** for conditional logic, multi-step wizard orchestration, central event systems with webhook integration, and a comprehensive suite of 25+ Ant Design components.
[](https://www.npmjs.com/package/extended-dynamic-forms)
[](https://github.com/user/extended-dynamic-forms/blob/main/LICENSE)
[](https://github.com/rjsf-team/react-jsonschema-form)
[](https://www.typescriptlang.org/)
[](#standalone-javascript-support)
## Why Extended Dynamic Forms?
While [RJSF](https://github.com/rjsf-team/react-jsonschema-form) provides an excellent foundation for generating forms from JSON Schema, enterprise applications demand more sophisticated capabilities:
### ๐ **Performance Revolution**
- **O(N) Conditional Logic**: Advanced Three Pillars v2 architecture vs traditional O(MรN) systems
- **Optimized Array Processing**: Per-item evaluation with dynamic array conditionals
- **Memory Efficient**: Immutable schema processing with intelligent caching
### ๐ฏ **Enterprise-Grade Features**
- **Complex Conditional Logic**: Multi-field dependencies, nested conditions, and dynamic validation
- **Multi-Step Workflows**: Automatic wizard detection with step-aware conditional logic
- **Real-Time Integration**: Production-ready webhooks with retry logic and error isolation
- **Professional UI**: Comprehensive suite of enhanced Ant Design components with consistent styling
### ๐ **Developer Experience**
- **Dual Architecture Support**: Modern React hooks + vanilla JavaScript compatibility
- **Type-Safe Throughout**: Comprehensive TypeScript interfaces and validation
- **Rich Ecosystem**: Interactive playground with comprehensive real-world demos
- **Migration Ready**: Automated v1-to-v2 conversion utilities
This library transforms RJSF from a simple form generator into a complete enterprise form solution while preserving its declarative approach.
## Core Features
### ๐ Three Pillars v2 Architecture (Recommended)
- **UI Logic Pillar**: Control form appearance with JSON Patch operations
- **Schema Logic Pillar**: Modify data structure when truly needed
- **Validation Logic Pillar**: Dynamic validation rules without schema changes
- **O(N) Performance**: Superior array handling vs v1's O(MรN)
- **React Hooks**: Modern, declarative API with `useConditionalUi`, `useConditionalSchema`, `useConditionalValidation`
### ๐ฏ Declarative Conditional Logic
- Define complex form behavior without code
- Dynamic array support with per-item evaluation
- Compatible with `json-rules-engine` format
- Built-in migration utilities from v1 to v2
For example, you can integrate existing business logic:
```tsx
import { engine } from './rules-engine'; // Your configured json-rules-engine instance
const uiRules: UiRule[] = [{
name: 'Apply business logic for premium users',
// The condition can be a promise-based async function
condition: async (formData) => {
const { events } = await engine.run(formData);
return events.some(event => event.type === 'show-premium-feature');
},
effect: [...]
}];
```
### ๐งโโ๏ธ Multi-Step Wizard Forms
- Automatic step detection from schema structure
- **Full conditional logic support** with step-aware rule processing
- Built-in progress indicators and navigation
- Per-step validation
- Supports both v1 conditions (deprecated) and v2 Three Pillars architecture
**Step-Aware Conditional Logic**
The `WizardForm` automatically filters and transforms conditional rules to work within the current step's context. This means you can define conditions that reference fields across different steps, and the wizard will intelligently apply only the relevant rules for the active step:
```tsx
// Define steps with prefixed field names to avoid collisions
const schema = {
type: 'object',
properties: {
STEP_PERSONAL: {
type: 'object',
title: 'Personal Information',
properties: {
isUSCitizen: { type: 'boolean', title: 'Are you a US Citizen?' },
ssn: { type: 'string', title: 'Social Security Number' }
}
}
// ... other steps
}
};
// Use v2 UiRules to handle step-aware conditionals
const uiRules: UiRule[] = [{
name: 'Show SSN only for US Citizens in Personal step',
condition: (formData) => !formData.STEP_PERSONAL?.isUSCitizen,
effect: [
{ op: 'add', path: '/STEP_PERSONAL/properties/ssn/ui:widget', value: 'hidden' }
]
}];
// The WizardForm handles the step isolation automatically
```
### ๐ Central Event Orchestration
- Unified event system for all field interactions
- Webhook integration with retry logic
- Real-time form analytics capabilities
- Debounced event processing
### ๐จ Ant Design Components
- Complete widget suite built with Ant Design v5
- Enhanced standard widgets with event integration
- Custom widgets: Rating, Color Picker, Range Slider
- Professional field components: Address, Phone, Currency
### โก Form Lifecycle Hooks
- Intercept and modify form data at key stages
- `beforeSubmit`, `afterSubmit`, `beforeValidation`, `afterValidation`
- Ideal for data transformation, logging, or triggering side effects
### ๐ฆ Additional Features
- **TypeScript**: Full type safety and IntelliSense with comprehensive interface definitions
- **Performance**: Optimized re-renders and memoization with intelligent caching
- **Extensible**: Add custom widgets, fields, and actions with clean APIs
- **Well-Tested**: Extensive test suite covering all major features and edge cases
- **Developer Experience**: Interactive playground with dozens of real-world demos
### ๐ Standalone JavaScript Support
**Complete vanilla JavaScript compatibility** with a production-ready UMD bundle that includes React, Ant Design, and all dependencies:
```html
<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/extended-dynamic-forms/dist/standalone.umd.js"></script>
<link rel="stylesheet" href="https://unpkg.com/extended-dynamic-forms/dist/style.css">
</head>
<body>
<div id="form-container"></div>
<script>
const { createForm, createWizard } = ExtendedDynamicForms;
// Create a complete form without React knowledge
const form = createForm({
schema: {
type: 'object',
properties: {
name: { type: 'string', title: 'Full Name' },
email: { type: 'string', format: 'email', title: 'Email' }
}
},
container: document.getElementById('form-container'),
onSubmit: (data) => console.log('Form submitted:', data)
});
</script>
</body>
</html>
```
**Important Notes on Conditional Logic in Vanilla JS:**
- **Only v1 conditions are supported** - The Three Pillars v2 architecture requires React hooks
- Use the `conditionals` prop with v1 format: `{ rules: [...] }`
- Subject to v1's O(MรN) performance for array conditionals
- For v2 benefits, use the React-based API instead
```javascript
// Vanilla JS supports only v1 conditionals
ExtendedDynamicForms.createForm({
container: '#my-form',
schema: schema,
conditionals: {
rules: [
{
conditions: { showField: true },
event: { type: 'show', params: { field: 'conditionalField' } }
}
]
}
});
```
**Perfect for:**
- WordPress/Drupal integrations
- Legacy applications
- CMS form builders
- No-build environments
- PHP/ASP.NET applications
## Credits & Acknowledgments
This library is built on top of [React JSON Schema Form (RJSF)](https://github.com/rjsf-team/react-jsonschema-form), an amazing open-source project that provides the core form generation engine. We extend RJSF's capabilities while maintaining full compatibility with its ecosystem.
Special thanks to the RJSF team and contributors for creating such a flexible and well-architected foundation.
## Installation
### React Projects
```bash
npm install extended-dynamic-forms
# or
yarn add extended-dynamic-forms
# or
pnpm add extended-dynamic-forms
```
### Standalone JavaScript (No Build Required)
```html
<!-- Production CDN -->
<script src="https://unpkg.com/extended-dynamic-forms@latest/dist/standalone.umd.js"></script>
<link rel="stylesheet" href="https://unpkg.com/extended-dynamic-forms@latest/dist/style.css">
<!-- Or download and host locally -->
<script src="./path/to/extended-dynamic-forms-standalone.js"></script>
```
### Peer Dependencies
**Current Version**: `0.1.19` - Optimized for **RJSF v6** with Three Pillars v2 architecture.
```json
{
"react": "^18.0.0 || ^19.0.0",
"react-dom": "^18.0.0 || ^19.0.0",
"antd": "^5.24.0"
}
```
> **React 19 Support**: This library supports both React 18 and React 19. See [REACT-19-COMPATIBILITY.md](./REACT-19-COMPATIBILITY.md) for migration details.
**RJSF Dependencies** (automatically handled):
- `@rjsf/core`: ^6.0.0+
- `@rjsf/utils`: ^6.0.0+
- `@rjsf/validator-ajv8`: ^6.0.0+
- `@rjsf/antd`: ^6.0.0+
> **Development Note**: This library is currently developed against RJSF v6 and includes all necessary RJSF dependencies. No additional RJSF packages need to be installed separately.
**Additional Dependencies**:
- `dayjs`: ^1.11.13 (Date handling)
- `json-rules-engine-simplified`: ^0.2.0 (v1 conditional logic)
> **Note**: This library is specifically built for RJSF v6 to leverage the latest performance improvements and API enhancements. All examples and documentation assume RJSF v6.
## Setup
### CSS Requirements
This package uses Ant Design components. Import the CSS in your application:
```tsx
// In your main entry file (e.g., App.tsx or index.tsx)
import 'extended-dynamic-forms/dist/style.css'; // Or your specific CSS entry point
```
### Theming & Customization
Since Extended Dynamic Forms uses Ant Design components, you can customize the appearance using Ant Design's powerful theming system:
```tsx
import { ConfigProvider, theme } from 'antd';
import { ExtendedForm, WizardForm } from 'extended-dynamic-forms';
function App() {
return (
<ConfigProvider
theme={{
token: {
colorPrimary: '#00b96b',
borderRadius: 8,
fontSize: 16,
},
algorithm: theme.darkAlgorithm, // Optional: Use dark theme
}}
>
<WizardForm
schema={schema}
uiSchema={uiSchema}
conditionals={conditionals}
/>
</ConfigProvider>
);
}
```
## Three Pillars v2 Architecture (Recommended Approach)
> โ ๏ธ **IMPORTANT**: The v1 conditional system is deprecated. We strongly recommend using the Three Pillars v2 architecture for all new implementations.
The Three Pillars v2 system provides superior performance, cleaner separation of concerns, and better maintainability. It consists of three independent pillars:
### 1. UI Logic Pillar (`useConditionalUi`)
Controls form appearance using JSON Patch operations:
```tsx
// Note: v2 conditionals require deep import for optimal tree-shaking
import { useConditionalUi, UiRule } from 'extended-dynamic-forms/conditionals/v2';
// Define UI rules with JSON Patch operations
const uiRules: UiRule[] = [
{
name: 'Show shipping address when required',
condition: (formData) => formData.requiresShipping === true,
effect: [{ op: 'remove', path: '/shippingAddress/ui:widget' }],
order: 1
},
{
name: 'Dynamic country fields',
condition: (formData) => formData.shippingAddress?.country === 'USA',
effect: [
{ op: 'remove', path: '/shippingAddress/state/ui:widget' },
{ op: 'add', path: '/shippingAddress/province/ui:widget', value: 'hidden' }
],
order: 2
}
];
const baseUiSchema = {
shippingAddress: {
'ui:widget': 'hidden', // Initially hidden
state: { 'ui:widget': 'text' },
province: { 'ui:widget': 'hidden' } // Initially hidden
}
};
// In your component
function MyForm() {
const [formData, setFormData] = useState({});
// IMPORTANT: Define rules outside render or memoize them!
const conditionalUiSchema = useConditionalUi(uiRules, baseUiSchema, formData);
return (
<ExtendedForm
schema={schema}
uiSchema={conditionalUiSchema}
formData={formData}
onChange={({ formData }) => setFormData(formData)}
/>
);
}
```
### 2. Schema Logic Pillar (`useConditionalSchema`)
Modifies JSON Schema structure (use sparingly - prefer UI or Validation pillars):
```tsx
import { useConditionalSchema, SchemaRule } from 'extended-dynamic-forms/conditionals/v2';
const schemaRules: SchemaRule[] = [
{
name: 'Add premium fields',
condition: (formData) => formData.accountType === 'premium',
effect: [
{
op: 'add',
path: '/properties/premiumFeatures',
value: {
type: 'object',
properties: {
priority: { type: 'string', enum: ['high', 'medium', 'low'] }
}
}
}
]
}
];
const conditionalSchema = useConditionalSchema(schemaRules, baseSchema, formData);
```
### 3. Validation Logic Pillar (`useConditionalValidation`)
Adds conditional validation without modifying schema:
```tsx
import { useMemo } from 'react';
import { useConditionalValidation, ValidationRule, createCustomValidate } from 'extended-dynamic-forms/conditionals/v2';
const validationRules: ValidationRule[] = [
{
name: 'Require consent for minors',
condition: (formData) => formData.age < 18,
effect: {
type: 'validation',
validate: (errors, formData) => {
if (!formData.parentConsent) {
errors.parentConsent.addError('Parent consent is required for minors');
}
}
}
}
];
// In your component
function MyForm({ schema }) {
const [formData, setFormData] = useState({});
// 1. Get the conditional validation configuration
const conditionalValidationConfig = useConditionalValidation(validationRules, {}, formData);
// 2. Create the memoized validate function
const customValidate = useMemo(
() => createCustomValidate(conditionalValidationConfig),
[conditionalValidationConfig]
);
// 3. Use with ExtendedForm
return (
<ExtendedForm
schema={schema}
formData={formData}
onChange={({ formData }) => setFormData(formData)}
customValidate={customValidate}
/>
);
}
```
### Dynamic Arrays with O(N) Performance
#### **The Performance Revolution: `createDynamicArrayItemsUiSchema`**
One of the most significant breakthroughs in v2 is the `createDynamicArrayItemsUiSchema` function, which enables **true O(N) performance** for array conditionals. This is a fundamental improvement over traditional form libraries that struggle with dynamic array logic.
**How It Works:**
- **Per-Item Evaluation**: Each array item's conditionals are evaluated independently during render
- **No Rule Explosion**: Unlike v1's wildcard expansion, no rules are multiplied by array size
- **React-Optimized**: Leverages React's rendering cycle for optimal performance
```tsx
import { createDynamicArrayItemsUiSchema } from 'extended-dynamic-forms/conditionals/v2';
// Define per-item conditional logic - this function runs for each array item
const directorItemConditions = (director, index) => ({
shareholdingPercentage: {
'ui:widget': director.hasShareholding ? 'percentage' : 'hidden'
},
tfn: {
'ui:widget': director.isAustralianResident ? 'text' : 'hidden'
},
passport: {
'ui:widget': !director.isAustralianResident ? 'text' : 'hidden'
},
// Add visual indicator for the chairman
'ui:classNames': index === 0 ? 'chairman-director' : 'regular-director'
});
// Apply to your array field
const uiSchema = {
directors: {
'ui:title': 'Company Directors',
'ui:description': 'Add all company directors and their details',
items: createDynamicArrayItemsUiSchema(directorItemConditions)
}
};
```
**Performance Comparison:**
```typescript
// โ Traditional approach: O(MรN) - Rules ร Array Items
// With 10 rules and 50 directors = 500 evaluations
// โ
v2 approach: O(N) - Per-item evaluation
// With 50 directors = 50 evaluations (regardless of rule complexity)
```
**Advanced Patterns:**
```tsx
// Complex business logic with multiple conditions
const productItemConditions = (product, index) => {
const baseConfig = {
price: { 'ui:widget': 'currency' },
quantity: { 'ui:widget': 'number' }
};
// Category-specific fields
if (product.category === 'software') {
baseConfig.licenseType = { 'ui:widget': 'select' };
baseConfig.maintenancePeriod = { 'ui:widget': 'hidden' };
}
// Subscription-specific logic
if (product.billingType === 'subscription') {
baseConfig.recurringPrice = { 'ui:widget': 'currency' };
baseConfig.billingCycle = { 'ui:widget': 'select' };
}
return baseConfig;
};
```
### Performance Best Practices
> โ ๏ธ **Critical**: Always define rules and base schemas outside render or memoize them!
```tsx
// โ BAD - Creates new objects every render
function MyForm() {
const conditionalUiSchema = useConditionalUi(
[{ condition: () => true, effect: [...] }], // New array every render!
{ field: { 'ui:widget': 'text' } }, // New object every render!
formData
);
}
// โ
GOOD - Stable references
const rules = [{ condition: () => true, effect: [...] }];
const baseUiSchema = { field: { 'ui:widget': 'text' } };
function MyForm() {
const conditionalUiSchema = useConditionalUi(rules, baseUiSchema, formData);
}
```
### Migration from v1 to v2
```tsx
import {
migrateV1ToUiRules,
generateMigrationReport,
analyzeRules
} from 'extended-dynamic-forms/conditionals/v2';
// Analyze existing rules
const analysis = analyzeRules(v1Rules);
// Auto-migrate UI rules
const { rules: migratedRules, report } = migrateV1ToUiRules(v1Rules);
// Generate detailed migration report
const migrationReport = generateMigrationReport(v1Rules, {
includeExamples: true,
outputFormat: 'markdown'
});
```
## Quick Start
### Simple Wizard Form (Recommended)
The `WizardForm` component automatically detects multi-step forms and handles navigation. It fully supports conditional logic through either v1 conditions (deprecated) or the recommended Three Pillars v2 architecture:
```tsx
import { useState } from 'react';
import { WizardForm } from 'extended-dynamic-forms';
import { useConditionalUi, UiRule } from 'extended-dynamic-forms/conditionals/v2';
import schema from './schema.json';
import baseUiSchema from './ui-schema.json';
import webhooks from './webhooks.json';
// Example: v2 Three Pillars approach (recommended)
const uiRules: UiRule[] = [
{
name: 'Show tax ID in company step when listed',
condition: (formData) => formData.STEP_COMPANY?.isListedCompany === true,
effect: [{ op: 'remove', path: '/STEP_COMPANY/taxId/ui:widget' }]
},
{
name: 'Show shareholding percentage for directors with shares',
condition: (formData) => formData.STEP_DIRECTORS?.directors?.some(d => d.hasShareholding),
effect: [{ op: 'remove', path: '/STEP_DIRECTORS/directors/items/shareholdingPercentage/ui:widget' }]
}
];
function App() {
const [formData, setFormData] = useState({});
const conditionalUiSchema = useConditionalUi(uiRules, baseUiSchema, formData);
return (
<WizardForm
schema={schema}
uiSchema={conditionalUiSchema}
formData={formData}
onChange={({ formData }) => setFormData(formData)}
webhooks={webhooks}
onSubmit={(data) => console.log('Submitted:', data.formData)}
/>
);
}
// Alternative: v1 conditions approach (deprecated but still supported)
const v1Conditions = [
{
conditions: { "STEP_COMPANY.isListedCompany": true },
event: { type: "show", params: { field: "STEP_COMPANY.taxId" } }
},
{
conditions: { "STEP_DIRECTORS.directors[*].hasShareholding": true },
event: { type: "require", params: { field: "STEP_DIRECTORS.directors[*].shareholdingPercentage" } }
}
];
// Pass v1 conditions directly to WizardForm
<WizardForm
schema={schema}
uiSchema={uiSchema}
conditions={v1Conditions} // WizardForm handles step-aware transformation
onSubmit={(data) => console.log('Submitted:', data.formData)}
/>
```
### Basic Form with Three Pillars v2
```tsx
import { ExtendedForm } from 'extended-dynamic-forms';
import { useConditionalUi, UiRule } from 'extended-dynamic-forms/conditionals/v2';
const schema = {
type: 'object',
properties: {
isStudent: { type: 'boolean', title: 'Are you a student?' },
studentId: { type: 'string', title: 'Student ID' },
school: { type: 'string', title: 'School Name' }
}
};
const baseUiSchema = {
studentId: { 'ui:widget': 'text' },
school: { 'ui:widget': 'text' }
};
// Define UI rules outside component
const uiRules: UiRule[] = [
{
name: 'Show student fields when student',
condition: (formData) => !formData.isStudent,
effect: [
{ op: 'add', path: '/studentId/ui:widget', value: 'hidden' },
{ op: 'add', path: '/school/ui:widget', value: 'hidden' }
]
}
];
function App() {
const [formData, setFormData] = useState({});
const conditionalUiSchema = useConditionalUi(uiRules, baseUiSchema, formData);
return (
<ExtendedForm
schema={schema}
uiSchema={conditionalUiSchema}
formData={formData}
onChange={({ formData }) => setFormData(formData)}
/>
);
}
```
## Custom Widgets
### Available Widgets
The library includes enhanced versions of all standard RJSF widgets plus custom ones:
#### Custom Widgets
```tsx
// Color Picker
const uiSchema = {
favoriteColor: {
'ui:widget': 'color'
}
};
// Rating Widget
const uiSchema = {
satisfaction: {
'ui:widget': 'rating',
'ui:options': {
max: 10 // default is 5
}
}
};
// Range Slider
const schema = {
volume: {
type: 'number',
minimum: 0,
maximum: 100
}
};
const uiSchema = {
volume: {
'ui:widget': 'range'
}
};
// File Upload
const uiSchema = {
documents: {
'ui:widget': 'file',
'ui:options': {
accept: '.pdf,.doc,.docx',
multiple: true
}
}
};
```
#### Enhanced Standard Widgets
All standard RJSF widgets are enhanced with:
- **Event Integration**: Automatic integration with the central event system
- **Ant Design Styling**: Modern, consistent appearance
- **Error States**: Proper error indication and messaging
- **Accessibility**: Enhanced ARIA support
## Central Event Orchestration System
### Field-Level Event Handling
```tsx
import { ExtendedForm, type FormFieldEvent } from 'extended-dynamic-forms';
<ExtendedForm
schema={schema}
uiSchema={uiSchema}
formData={formData}
// Field-level event handlers
onFieldFocus={(event: FormFieldEvent) => {
console.log(`Field ${event.fieldId} focused:`, event.fieldValue);
}}
onFieldChange={(event: FormFieldEvent) => {
console.log(`Field ${event.fieldId} changed:`, event.fieldValue);
// Real-time validation or processing
}}
onFieldBlur={(event: FormFieldEvent) => {
console.log(`Field ${event.fieldId} blurred:`, event.fieldValue);
}}
/>
```
### Webhook Integration
Configure multiple webhook endpoints to receive real-time form events:
```tsx
import { ExtendedForm, type WebhookConfig } from 'extended-dynamic-forms';
const webhookConfigs: WebhookConfig[] = [
{
url: 'https://api.yourapp.com/form-events',
method: 'POST',
events: ['change', 'blur'], // Only trigger on change and blur
debounceMs: 500, // Wait 500ms before sending
retries: 3, // Retry failed requests
timeout: 5000, // 5 second timeout
headers: {
'Authorization': 'Bearer your-api-token',
'X-Form-ID': 'contact-form'
}
}
];
<ExtendedForm
schema={schema}
uiSchema={uiSchema}
webhooks={webhookConfigs}
/>
```
## V1 Conditional System (Deprecated)
> โ ๏ธ **DEPRECATED**: The v1 conditional system is deprecated and will be removed in a future version. Use the Three Pillars v2 system for all new implementations.
The v1 system uses imperative engines with O(MรN) performance for arrays. While still functional, it has significant limitations compared to v2.
### Basic V1 Usage (Not Recommended)
```tsx
import { ExtendedForm } from 'extended-dynamic-forms';
const conditionals = {
rules: [
{
conditions: { isStudent: true },
event: { type: "require", params: { field: ["studentId", "school"] } }
},
{
conditions: { isStudent: false },
event: { type: "remove", params: { field: ["studentId", "school"] } }
}
]
};
<ExtendedForm
schema={schema}
uiSchema={uiSchema}
conditionals={conditionals}
/>
```
### Why Migrate to v2?
- **Performance**: O(N) vs O(MรN) for arrays
- **Maintainability**: Clear separation of concerns
- **Type Safety**: Full TypeScript support
- **Predictability**: No complex rule interactions
- **Modern React**: Hooks-based architecture
## API Reference
### ExtendedFormProps
```typescript
interface ExtendedFormProps<T = any, S extends RJSFSchema = RJSFSchema, F = any> extends FormProps<T, S, F> {
// Standard RJSF props
schema: S;
uiSchema?: UiSchema<T, S, F>;
formData?: T;
onSubmit?: (data: IChangeEvent<T, S, F>, event?: React.FormEvent<HTMLFormElement>) => void;
onChange?: (data: IChangeEvent<T, S, F>) => void;
// Field-level event handlers
onFieldFocus?: (event: FormFieldEvent) => Promise<void> | void;
onFieldBlur?: (event: FormFieldEvent) => Promise<void> | void;
onFieldChange?: (event: FormFieldEvent) => Promise<void> | void;
// Webhook configuration
webhooks?: WebhookConfig[];
// Conditional logic (v1 - deprecated)
conditionals?: ConditionalConfig;
// Form lifecycle events
beforeSubmit?: (data: T) => Promise<T> | T;
afterSubmit?: (data: T) => Promise<void> | void;
beforeValidation?: (data: T) => Promise<T> | T;
afterValidation?: (data: T, errors: RJSFValidationError[]) => Promise<void> | void;
}
```
### Three Pillars v2 Hooks
```typescript
// UI Logic Pillar
function useConditionalUi(
rules: UiRule[],
baseUiSchema: UiSchema,
formData: any
): UiSchema
// Schema Logic Pillar
function useConditionalSchema(
rules: SchemaRule[],
baseSchema: RJSFSchema,
formData: any
): RJSFSchema
// Validation Logic Pillar
function useConditionalValidation(
rules: ValidationRule[],
baseConfig: ValidationConfig,
formData: any
): ValidationConfig
```
## Real-World Use Cases
### ๐ข Enterprise Business Applications
**Australian Company Registration** (Featured Demo)
```tsx
// Complete 5-step wizard with dynamic conditionals
const companyOnboardingSchema = {
STEP_COMPANY: { /* Company details */ },
STEP_DIRECTORS: { /* Dynamic director array */ },
STEP_ADDRESS: { /* Address with postal logic */ },
STEP_FINANCIAL: { /* Banking with international support */ },
STEP_COMPLIANCE: { /* Regulatory requirements */ }
};
// Per-director conditionals with O(N) performance
const uiSchema = {
STEP_DIRECTORS: {
directors: {
items: createDynamicArrayItemsUiSchema((director) => ({
tfn: { 'ui:widget': director.isAustralianResident ? 'text' : 'hidden' },
passport: { 'ui:widget': !director.isAustralianResident ? 'text' : 'hidden' }
}))
}
}
};
```
### ๐ผ Multi-Step Workflows
**Loan Applications**
- Conditional document requirements based on loan type
- Income verification with employment status logic
- Asset declaration with property type conditionals
**Employee Onboarding**
- Role-based form sections (technical vs. non-technical)
- Security clearance workflows
- Benefits enrollment with eligibility rules
**Grant Applications**
- Multi-stage submissions with validation gates
- Budget calculations with category-based rules
- Compliance checks based on funding type
### ๐ Dynamic Array Management
**Board of Directors Management**
```tsx
// Professional-grade array handling with O(N) performance
import { createDynamicArrayItemsUiSchema } from 'extended-dynamic-forms';
const uiSchema = {
STEP_DIRECTORS: {
directors: {
items: createDynamicArrayItemsUiSchema((director, index) => ({
shareholdingPercentage: {
'ui:widget': director.hasShareholding ? 'percentage' : 'hidden'
},
tfn: {
'ui:widget': director.isAustralianResident ? 'text' : 'hidden'
},
passport: {
'ui:widget': !director.isAustralianResident ? 'text' : 'hidden'
}
}))
}
}
};
```
**Product Configurations**
- Dynamic product options based on category
- Pricing calculations with quantity breaks
- Feature availability by subscription tier
**Address Management**
- International vs. domestic address formats
- State/province selection based on country
- Postal code validation by region
### ๐ CMS & Integration Use Cases
**WordPress/Drupal Forms**
```html
<!-- Standalone JavaScript integration -->
<script>
const { createWizard } = ExtendedDynamicForms;
createWizard({
schema: wpFormSchema,
container: '#wp-form-container',
onSubmit: (data) => {
// Submit to WordPress REST API
wp.apiRequest({ path: '/wp/v2/forms', method: 'POST', data });
}
});
</script>
```
**Legacy System Modernization**
- Drop-in replacement for static HTML forms
- Progressive enhancement of existing forms
- No-build deployment to production environments
## Architecture
Extended Dynamic Forms uses a layered architecture that cleanly extends RJSF:
```
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Three Pillars v2 (Conditional System) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Application Layer (WizardForm) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Event Layer (FormEventHub) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Component Layer (Widgets/Fields/Templates) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Base Layer (@rjsf/antd) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
```
## Feature Comparison
| Feature | Basic RJSF | Extended Dynamic Forms |
|---------|------------|----------------------|
| **Form Generation** | โ
JSON Schema | โ
Enhanced JSON Schema |
| **UI Components** | Basic HTML | โ
Comprehensive Ant Design Suite |
| **Conditional Logic** | โ Manual | โ
Three Pillars v2 (O(N)) |
| **Multi-Step Forms** | โ Manual | โ
Automatic Wizard Detection |
| **Event System** | Basic onChange | โ
Central Event Orchestration |
| **Webhook Integration** | โ None | โ
Production-Ready with Retry |
| **Array Conditionals** | โ None | โ
Per-Item O(N) Performance |
| **TypeScript** | Partial | โ
Comprehensive Type Definitions |
| **Standalone JS** | โ React Only | โ
Complete UMD Bundle |
| **Testing** | Basic | โ
Extensive Test Coverage |
| **Performance** | Standard | โ
Optimized with Caching |
| **Validation** | Basic | โ
Dynamic + Custom Rules |
| **Developer Tools** | Limited | โ
Interactive Playground |
## Development
### ๐ Quick Start
```bash
# Clone and setup
git clone https://github.com/user/extended-dynamic-forms.git
cd extended-dynamic-forms
npm install
# Start development with playground
npm run dev # Launches interactive playground
npm run playground # Alternative playground command
# Development workflow
npm run test # Run complete test suite
npm run test:ui # Visual test runner
npm run lint # ESLint validation
npm run format # Prettier formatting
```
### ๐ฆ Build Commands
```bash
# Library builds
npm run build # TypeScript + Vite library build
npm run build:vanilla # Standalone UMD bundle
npm run build:all # Both library and standalone
# Production validation
npm run preview # Preview library build
npm run serve:examples # Serve vanilla JS examples
```
### ๐งช Testing
**Test Coverage**: Extensive test suite with focus on:
- **Conditional Logic**: Comprehensive coverage for v1 and v2 systems
- **Wizard Forms**: Step navigation and validation
- **Performance**: Array conditional optimization
- **Integration**: Component interaction testing
```bash
npm run test # Run complete test suite
npm run test -- --grep "conditional" # Test conditional logic
npm run test -- --grep "wizard" # Test wizard forms
npm run test -- --grep "array" # Test array handling
```
### ๐๏ธ Architecture
**Build Configuration**:
- **Library**: ES + UMD via Vite with TypeScript declarations
- **Standalone**: Complete UMD bundle with React/antd included
- **External Dependencies**: React, antd marked as externals in library build
- **Type Generation**: `vite-plugin-dts` for .d.ts files
**File Structure**:
```
src/
โโโ ExtendedForm.tsx # Main form wrapper
โโโ WizardForm.tsx # Multi-step orchestrator
โโโ conditionals/ # v1 + v2 conditional systems
โ โโโ v2/ # Three Pillars architecture
โ โโโ DynamicArrayConditionalEngine.ts
โโโ events/ # Central event orchestration
โโโ widgets/ # Enhanced component suite
โโโ components/ # Field and template components
โโโ utils/ # Form manipulation utilities
```
## Examples & Demos
### ๐ฎ Interactive Playground
The library includes a comprehensive **interactive playground** with extensive real-world demos demonstrating all features:
```bash
# Run the playground locally
npm run dev
# or
npm run playground
```
### ๐ Demo Categories
#### **Three Pillars v2 Demonstrations**
- **Global UI Rules**: Dynamic show/hide with JSON Patch operations
- **Dynamic Array Items**: Per-item conditional logic with O(N) performance
- **Conditional Validation**: Custom validation rules without schema changes
- **Migration Examples**: Automated v1-to-v2 rule conversion
#### **๐งโโ๏ธ Wizard Form Showcases**
- **Australian Company Onboarding**: 5-step enterprise form with:
- Dynamic director arrays with per-item conditionals
- Real-time fee calculations based on business rules
- Complex validation (ABN/ACN numbers, postcodes)
- Step-aware conditional logic
- Professional business workflow
#### **๐ Event System Demos**
- **Real-time Form Analytics**: Webhook integration with retry logic
- **Field-Level Event Handling**: Focus/blur/change event orchestration
- **Webhook Configuration**: Multiple endpoints with custom headers
#### **๐จ Widget Showcase**
- **Enhanced Standard Widgets**: All RJSF widgets with Ant Design styling
- **Custom Widgets**: Color picker, rating, range slider, file upload
- **Professional Fields**: Address, currency, phone number components
### ๐ฑ Vanilla JavaScript Examples
Complete standalone examples in `/examples/vanilla-js/`:
```html
<!-- Basic Form -->
basic-form.html <!-- Simple contact form -->
conditional-form.html <!-- Dynamic field visibility -->
wizard-form.html <!-- Multi-step onboarding -->
```
### ๐ Live Demo Links
- **[Playground](https://extended-dynamic-forms-playground.vercel.app)** - Interactive demo environment
- **[Australian Company Onboarding](https://extended-dynamic-forms-playground.vercel.app/wizard/australian-company)** - Full enterprise form showcase
- **[Three Pillars v2 Demo](https://extended-dynamic-forms-playground.vercel.app/conditionals/three-pillars)** - Modern conditional logic patterns
## Contributing
We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
## Community & Support
- ๐ [Documentation](https://extended-dynamic-forms.dev)
- ๐ [Issue Tracker](https://github.com/user/extended-dynamic-forms/issues)
- ๐ฌ [Discussions](https://github.com/user/extended-dynamic-forms/discussions)
- ๐ง [Email Support](mailto:support@extended-dynamic-forms.dev)
<p align="center">
Built with โค๏ธ on top of <a href="https://github.com/rjsf-team/react-jsonschema-form">React JSON Schema Form</a>
</p>