extended-dynamic-forms 0.1.14 → 0.1.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +251 -385
- package/dist/ExtendedForm.d.ts +1 -1
- package/dist/WizardForm.d.ts +26 -0
- package/dist/components/fields/AddressField.d.ts +0 -1
- package/dist/components/index.d.ts +10 -1
- package/dist/components/templates/FieldTemplate.d.ts +4 -0
- package/dist/components/templates/SubmitButton.d.ts +4 -0
- package/dist/components/templates/index.d.ts +2 -0
- package/dist/conditionals/ConditionalActions.d.ts +13 -0
- package/dist/conditionals/ConditionalContext.d.ts +32 -0
- package/dist/conditionals/DynamicArrayConditionalEngine.d.ts +77 -0
- package/dist/conditionals/SimpleConditionalEngine.d.ts +41 -0
- package/dist/conditionals/SmartJsonRulesTransformer.d.ts +10 -0
- package/dist/conditionals/index.d.ts +7 -4
- package/dist/events/index.d.ts +2 -2
- package/dist/index.d.ts +4 -5
- package/dist/index.es.js +43858 -14797
- package/dist/index.umd.js +390 -104
- package/dist/layouts/index.d.ts +2 -3
- package/dist/layouts/wizard/ProgressIndicator.d.ts +10 -0
- package/dist/layouts/wizard/StepNavigation.d.ts +11 -0
- package/dist/layouts/wizard/WizardLayout.d.ts +31 -0
- package/dist/layouts/wizard/WizardNavigation.d.ts +16 -0
- package/dist/layouts/wizard/WizardObjectFieldTemplate.d.ts +4 -0
- package/dist/layouts/wizard/WizardSectionTemplate.d.ts +11 -0
- package/dist/layouts/wizard/index.d.ts +7 -0
- package/dist/style.css +1 -1
- package/dist/types/index.d.ts +41 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/vanilla-wrapper.d.ts +0 -2
- package/package.json +39 -16
- package/dist/components/ui/badge.d.ts +0 -9
- package/dist/components/ui/button.d.ts +0 -11
- package/dist/components/ui/calendar.d.ts +0 -8
- package/dist/components/ui/card.d.ts +0 -8
- package/dist/components/ui/checkbox.d.ts +0 -4
- package/dist/components/ui/date-picker.d.ts +0 -13
- package/dist/components/ui/input.d.ts +0 -5
- package/dist/components/ui/label.d.ts +0 -5
- package/dist/components/ui/popover.d.ts +0 -6
- package/dist/components/ui/select.d.ts +0 -13
- package/dist/components/ui/slider.d.ts +0 -4
- package/dist/components/ui/textarea.d.ts +0 -5
- package/dist/conditionals/ConditionalForm.d.ts +0 -7
- package/dist/conditionals/initialStateUtils.d.ts +0 -18
- package/dist/conditionals/types.d.ts +0 -65
- package/dist/conditionals/utils.d.ts +0 -22
- package/dist/layouts/grid/GridLayout.d.ts +0 -11
- package/dist/layouts/horizontal/HorizontalLayout.d.ts +0 -10
- package/dist/layouts/vertical/VerticalLayout.d.ts +0 -9
- package/dist/lib/utils.d.ts +0 -3
package/README.md
CHANGED
|
@@ -1,20 +1,19 @@
|
|
|
1
1
|
# Extended Dynamic Forms
|
|
2
2
|
|
|
3
|
-
A comprehensive extension of React JSON Schema Form (RJSF)
|
|
3
|
+
A comprehensive extension of React JSON Schema Form (RJSF) v6 with Ant Design components, custom widgets, fields, layouts, and a powerful central event orchestration system with webhook capabilities.
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
|
-
- 🎨 **
|
|
8
|
-
- ✨ **
|
|
7
|
+
- 🎨 **Ant Design Integration**: Built on @rjsf/antd with modern, accessible components
|
|
8
|
+
- ✨ **Enhanced Widgets**: Color picker, date picker, file upload, range slider, rating widget, enhanced input controls
|
|
9
9
|
- 🏗️ **Custom Fields**: Address, phone number, currency input with formatting
|
|
10
|
-
-
|
|
10
|
+
- 🧙♂️ **Wizard Forms**: Multi-step forms with automatic step detection, progress tracking, and navigation
|
|
11
11
|
- 🎯 **Central Event Orchestration**: Unified system capturing all form field events (focus, blur, change)
|
|
12
12
|
- 🔗 **Webhook Integration**: Configure multiple webhook endpoints with debouncing and retry logic
|
|
13
|
+
- 🎭 **Advanced Conditional Logic**: Dynamic form behavior with JSON Rules Engine support and step-aware processing
|
|
13
14
|
- 🔧 **Enhanced Form Events**: Before/after submit and validation hooks plus field-level events
|
|
14
|
-
- 🚀 **Conditional Logic**: Show/hide fields, make fields required/optional based on complex conditions
|
|
15
15
|
- 📦 **TypeScript Support**: Fully typed with comprehensive type definitions
|
|
16
16
|
- ⚡ **Vite Powered**: Fast development and optimized builds
|
|
17
|
-
- 🎯 **Tailwind CSS**: Utility-first styling with full customization
|
|
18
17
|
- 🛡️ **Error Handling**: Robust error recovery and retry mechanisms
|
|
19
18
|
- ⚡ **Performance Optimized**: Debouncing, queuing, and async processing
|
|
20
19
|
|
|
@@ -34,10 +33,9 @@ This package requires the following peer dependencies:
|
|
|
34
33
|
{
|
|
35
34
|
"react": "^18.0.0",
|
|
36
35
|
"react-dom": "^18.0.0",
|
|
37
|
-
"@rjsf/core": "^5.
|
|
38
|
-
"@rjsf/utils": "^5.
|
|
39
|
-
"@rjsf/validator-ajv8": "^5.
|
|
40
|
-
"@rjsf/shadcn": "^0.1.0"
|
|
36
|
+
"@rjsf/core": "^5.0.0 || ^6.0.0-beta.10",
|
|
37
|
+
"@rjsf/utils": "^5.0.0 || ^6.0.0-beta.10",
|
|
38
|
+
"@rjsf/validator-ajv8": "^5.0.0 || ^6.0.0-beta.10"
|
|
41
39
|
}
|
|
42
40
|
```
|
|
43
41
|
|
|
@@ -45,31 +43,51 @@ This package requires the following peer dependencies:
|
|
|
45
43
|
|
|
46
44
|
### CSS Requirements
|
|
47
45
|
|
|
48
|
-
This package uses
|
|
46
|
+
This package uses Ant Design components. Import the CSS in your application:
|
|
49
47
|
|
|
50
48
|
```tsx
|
|
51
49
|
// In your main entry file (e.g., App.tsx or index.tsx)
|
|
52
|
-
import 'extended-dynamic-forms/dist/
|
|
50
|
+
import 'extended-dynamic-forms/dist/style.css'; // Or your specific CSS entry point
|
|
53
51
|
```
|
|
54
52
|
|
|
55
|
-
|
|
53
|
+
## Quick Start
|
|
54
|
+
|
|
55
|
+
### Simple Wizard Form (Recommended)
|
|
56
56
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
57
|
+
The `WizardForm` component automatically detects multi-step forms and handles navigation:
|
|
58
|
+
|
|
59
|
+
```tsx
|
|
60
|
+
import { WizardForm } from 'extended-dynamic-forms';
|
|
61
|
+
import schema from './schema.json';
|
|
62
|
+
import uiSchema from './ui-schema.json';
|
|
63
|
+
import conditions from './conditions.json';
|
|
64
|
+
import webhooks from './webhooks.json';
|
|
65
|
+
|
|
66
|
+
function App() {
|
|
67
|
+
return (
|
|
68
|
+
<WizardForm
|
|
69
|
+
schema={schema}
|
|
70
|
+
uiSchema={uiSchema}
|
|
71
|
+
conditions={conditions}
|
|
72
|
+
webhooks={webhooks}
|
|
73
|
+
onSubmit={(data) => console.log('Submitted:', data)}
|
|
74
|
+
/>
|
|
75
|
+
);
|
|
64
76
|
}
|
|
65
77
|
```
|
|
66
78
|
|
|
67
|
-
|
|
79
|
+
**WizardForm Features:**
|
|
80
|
+
- ✅ Auto-detects wizard structure (properties starting with `STEP_`)
|
|
81
|
+
- ✅ Creates progress tracking and navigation
|
|
82
|
+
- ✅ Handles step-aware conditional logic
|
|
83
|
+
- ✅ Manages form state and validation
|
|
84
|
+
- ✅ Integrates webhooks for real-time events
|
|
68
85
|
|
|
69
|
-
### Basic Form
|
|
86
|
+
### Basic Form (Using ExtendedForm)
|
|
87
|
+
|
|
88
|
+
For more control, use the `ExtendedForm` component directly:
|
|
70
89
|
|
|
71
90
|
```tsx
|
|
72
|
-
import React from 'react';
|
|
73
91
|
import { ExtendedForm } from 'extended-dynamic-forms';
|
|
74
92
|
|
|
75
93
|
const schema = {
|
|
@@ -94,127 +112,76 @@ const uiSchema = {
|
|
|
94
112
|
};
|
|
95
113
|
|
|
96
114
|
function App() {
|
|
97
|
-
const handleSubmit = ({ formData }) => {
|
|
98
|
-
console.log('Form data:', formData);
|
|
99
|
-
};
|
|
100
|
-
|
|
101
|
-
const handleFieldChange = (event) => {
|
|
102
|
-
console.log(`Field ${event.fieldId} changed to:`, event.fieldValue);
|
|
103
|
-
};
|
|
104
|
-
|
|
105
115
|
return (
|
|
106
116
|
<ExtendedForm
|
|
107
117
|
schema={schema}
|
|
108
118
|
uiSchema={uiSchema}
|
|
109
|
-
onSubmit={
|
|
110
|
-
onFieldChange={handleFieldChange}
|
|
119
|
+
onSubmit={({ formData }) => console.log(formData)}
|
|
111
120
|
/>
|
|
112
121
|
);
|
|
113
122
|
}
|
|
114
123
|
```
|
|
115
124
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
```tsx
|
|
119
|
-
import React from 'react';
|
|
120
|
-
import { ExtendedForm, WebhookConfig } from 'extended-dynamic-forms';
|
|
125
|
+
## Custom Widgets
|
|
121
126
|
|
|
122
|
-
|
|
123
|
-
{
|
|
124
|
-
url: 'https://your-api.com/webhooks/form-events',
|
|
125
|
-
events: ['change'],
|
|
126
|
-
debounceMs: 300,
|
|
127
|
-
headers: {
|
|
128
|
-
'Authorization': 'Bearer your-token'
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
];
|
|
127
|
+
### Available Widgets
|
|
132
128
|
|
|
133
|
-
|
|
134
|
-
return (
|
|
135
|
-
<ExtendedForm
|
|
136
|
-
schema={schema}
|
|
137
|
-
uiSchema={uiSchema}
|
|
138
|
-
webhooks={webhooks}
|
|
139
|
-
onSubmit={({ formData }) => {
|
|
140
|
-
console.log('Form submitted:', formData);
|
|
141
|
-
}}
|
|
142
|
-
onFieldFocus={(event) => {
|
|
143
|
-
console.log('Field focused:', event.fieldId);
|
|
144
|
-
}}
|
|
145
|
-
/>
|
|
146
|
-
);
|
|
147
|
-
}
|
|
148
|
-
```
|
|
129
|
+
The library includes enhanced versions of all standard RJSF widgets plus custom ones:
|
|
149
130
|
|
|
150
|
-
|
|
131
|
+
#### Custom Widgets
|
|
151
132
|
|
|
152
|
-
### Color Widget
|
|
153
133
|
```tsx
|
|
134
|
+
// Color Picker
|
|
154
135
|
const uiSchema = {
|
|
155
136
|
favoriteColor: {
|
|
156
137
|
'ui:widget': 'color'
|
|
157
138
|
}
|
|
158
139
|
};
|
|
159
|
-
```
|
|
160
140
|
|
|
161
|
-
|
|
162
|
-
```tsx
|
|
141
|
+
// Rating Widget
|
|
163
142
|
const uiSchema = {
|
|
164
|
-
|
|
165
|
-
'ui:widget': '
|
|
166
|
-
'ui:options': {
|
|
167
|
-
inputType: 'datetime-local', // or 'date', 'time'
|
|
168
|
-
minDate: '2000-01-01',
|
|
169
|
-
maxDate: '2025-12-31'
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
};
|
|
173
|
-
```
|
|
174
|
-
|
|
175
|
-
### File Widget
|
|
176
|
-
```tsx
|
|
177
|
-
const uiSchema = {
|
|
178
|
-
documents: {
|
|
179
|
-
'ui:widget': 'file',
|
|
143
|
+
satisfaction: {
|
|
144
|
+
'ui:widget': 'rating',
|
|
180
145
|
'ui:options': {
|
|
181
|
-
|
|
182
|
-
multiple: true
|
|
146
|
+
max: 10 // default is 5
|
|
183
147
|
}
|
|
184
148
|
}
|
|
185
149
|
};
|
|
186
|
-
```
|
|
187
150
|
|
|
188
|
-
|
|
189
|
-
```tsx
|
|
151
|
+
// Range Slider
|
|
190
152
|
const schema = {
|
|
191
153
|
volume: {
|
|
192
154
|
type: 'number',
|
|
193
155
|
minimum: 0,
|
|
194
|
-
maximum: 100
|
|
195
|
-
multipleOf: 5
|
|
156
|
+
maximum: 100
|
|
196
157
|
}
|
|
197
158
|
};
|
|
198
|
-
|
|
199
159
|
const uiSchema = {
|
|
200
160
|
volume: {
|
|
201
161
|
'ui:widget': 'range'
|
|
202
162
|
}
|
|
203
163
|
};
|
|
204
|
-
```
|
|
205
164
|
|
|
206
|
-
|
|
207
|
-
```tsx
|
|
165
|
+
// File Upload
|
|
208
166
|
const uiSchema = {
|
|
209
|
-
|
|
210
|
-
'ui:widget': '
|
|
167
|
+
documents: {
|
|
168
|
+
'ui:widget': 'file',
|
|
211
169
|
'ui:options': {
|
|
212
|
-
|
|
170
|
+
accept: '.pdf,.doc,.docx',
|
|
171
|
+
multiple: true
|
|
213
172
|
}
|
|
214
173
|
}
|
|
215
174
|
};
|
|
216
175
|
```
|
|
217
176
|
|
|
177
|
+
#### Enhanced Standard Widgets
|
|
178
|
+
|
|
179
|
+
All standard RJSF widgets are enhanced with:
|
|
180
|
+
- **Event Integration**: Automatic integration with the central event system
|
|
181
|
+
- **Ant Design Styling**: Modern, consistent appearance
|
|
182
|
+
- **Error States**: Proper error indication and messaging
|
|
183
|
+
- **Accessibility**: Enhanced ARIA support
|
|
184
|
+
|
|
218
185
|
## Custom Fields
|
|
219
186
|
|
|
220
187
|
### Address Field
|
|
@@ -263,9 +230,8 @@ const uiSchema = {
|
|
|
263
230
|
|
|
264
231
|
## Array Fields
|
|
265
232
|
|
|
266
|
-
|
|
233
|
+
The library provides Ant Design-styled array field templates with enhanced functionality:
|
|
267
234
|
|
|
268
|
-
### Basic Array Example
|
|
269
235
|
```tsx
|
|
270
236
|
const schema = {
|
|
271
237
|
type: 'object',
|
|
@@ -296,19 +262,15 @@ const uiSchema = {
|
|
|
296
262
|
};
|
|
297
263
|
```
|
|
298
264
|
|
|
299
|
-
|
|
300
|
-
- 🎨 **
|
|
301
|
-
- ➕ **Add
|
|
302
|
-
- 🗑️ **Remove
|
|
303
|
-
- 🔄 **Reordering**: Move items up/down with
|
|
304
|
-
- 📱 **Responsive**: Mobile-friendly
|
|
305
|
-
|
|
306
|
-
Arrays work seamlessly with all other custom widgets and fields in the library, including within nested structures.
|
|
265
|
+
**Array Features:**
|
|
266
|
+
- 🎨 **Ant Design Cards**: Clean, modern appearance
|
|
267
|
+
- ➕ **Add Button**: Prominent "Add [Item]" button
|
|
268
|
+
- 🗑️ **Remove Buttons**: Individual remove buttons for each item
|
|
269
|
+
- 🔄 **Reordering**: Move items up/down with controls
|
|
270
|
+
- 📱 **Responsive**: Mobile-friendly design
|
|
307
271
|
|
|
308
272
|
## Central Event Orchestration System
|
|
309
273
|
|
|
310
|
-
The library features a comprehensive event orchestration system that captures all form field events and enables webhook integration.
|
|
311
|
-
|
|
312
274
|
### Field-Level Event Handling
|
|
313
275
|
|
|
314
276
|
```tsx
|
|
@@ -322,29 +284,15 @@ import { ExtendedForm, FormFieldEvent } from 'extended-dynamic-forms';
|
|
|
322
284
|
// Field-level event handlers
|
|
323
285
|
onFieldFocus={(event: FormFieldEvent) => {
|
|
324
286
|
console.log(`Field ${event.fieldId} focused:`, event.fieldValue);
|
|
325
|
-
// Track user interactions for analytics
|
|
326
287
|
}}
|
|
327
288
|
|
|
328
289
|
onFieldChange={(event: FormFieldEvent) => {
|
|
329
290
|
console.log(`Field ${event.fieldId} changed:`, event.fieldValue);
|
|
330
291
|
// Real-time validation or processing
|
|
331
|
-
if (event.fieldId === 'root_email') {
|
|
332
|
-
validateEmailRealTime(event.fieldValue);
|
|
333
|
-
}
|
|
334
292
|
}}
|
|
335
293
|
|
|
336
294
|
onFieldBlur={(event: FormFieldEvent) => {
|
|
337
295
|
console.log(`Field ${event.fieldId} blurred:`, event.fieldValue);
|
|
338
|
-
// Format field values or trigger validation
|
|
339
|
-
}}
|
|
340
|
-
|
|
341
|
-
// Traditional form-level events (still supported)
|
|
342
|
-
beforeSubmit={async (data) => {
|
|
343
|
-
return { ...data, timestamp: Date.now() };
|
|
344
|
-
}}
|
|
345
|
-
|
|
346
|
-
afterSubmit={async (data) => {
|
|
347
|
-
console.log('Form submitted:', data);
|
|
348
296
|
}}
|
|
349
297
|
/>
|
|
350
298
|
```
|
|
@@ -366,17 +314,7 @@ const webhookConfigs: WebhookConfig[] = [
|
|
|
366
314
|
timeout: 5000, // 5 second timeout
|
|
367
315
|
headers: {
|
|
368
316
|
'Authorization': 'Bearer your-api-token',
|
|
369
|
-
'X-Form-ID': 'contact-form'
|
|
370
|
-
'Content-Type': 'application/json'
|
|
371
|
-
}
|
|
372
|
-
},
|
|
373
|
-
{
|
|
374
|
-
url: 'https://analytics.yourapp.com/field-interactions',
|
|
375
|
-
events: ['focus'], // Track focus events for analytics
|
|
376
|
-
debounceMs: 0, // No debouncing for real-time analytics
|
|
377
|
-
retries: 1,
|
|
378
|
-
headers: {
|
|
379
|
-
'X-Analytics-Key': 'your-analytics-key'
|
|
317
|
+
'X-Form-ID': 'contact-form'
|
|
380
318
|
}
|
|
381
319
|
}
|
|
382
320
|
];
|
|
@@ -385,20 +323,11 @@ const webhookConfigs: WebhookConfig[] = [
|
|
|
385
323
|
schema={schema}
|
|
386
324
|
uiSchema={uiSchema}
|
|
387
325
|
webhooks={webhookConfigs}
|
|
388
|
-
|
|
389
|
-
onFieldChange={(event) => {
|
|
390
|
-
// Local processing alongside webhooks
|
|
391
|
-
if (event.fieldId === 'root_email') {
|
|
392
|
-
setEmailValid(validateEmail(event.fieldValue));
|
|
393
|
-
}
|
|
394
|
-
}}
|
|
395
326
|
/>
|
|
396
327
|
```
|
|
397
328
|
|
|
398
329
|
### Webhook Payload Structure
|
|
399
330
|
|
|
400
|
-
Your webhook endpoints will receive payloads in this format:
|
|
401
|
-
|
|
402
331
|
```json
|
|
403
332
|
{
|
|
404
333
|
"event": {
|
|
@@ -422,232 +351,151 @@ Your webhook endpoints will receive payloads in this format:
|
|
|
422
351
|
}
|
|
423
352
|
```
|
|
424
353
|
|
|
425
|
-
|
|
354
|
+
## Advanced Conditional Logic System
|
|
426
355
|
|
|
427
|
-
|
|
428
|
-
- **Retry Logic**: Automatic retry with exponential backoff for failed requests
|
|
429
|
-
- **Error Isolation**: Webhook failures don't block form functionality
|
|
430
|
-
- **Event Filtering**: Configure which events trigger each webhook
|
|
431
|
-
- **Queue Management**: Asynchronous processing with proper ordering
|
|
432
|
-
- **Custom Headers**: Add authentication, tracking, or custom metadata
|
|
356
|
+
The library includes a comprehensive conditional logic system with support for JSON Rules Engine format and step-aware processing for wizard forms.
|
|
433
357
|
|
|
434
|
-
|
|
358
|
+
### Basic Conditional Logic
|
|
435
359
|
|
|
436
360
|
```tsx
|
|
437
|
-
import {
|
|
438
|
-
|
|
439
|
-
// Vertical Layout
|
|
440
|
-
<VerticalLayout spacing="medium">
|
|
441
|
-
<input />
|
|
442
|
-
<button />
|
|
443
|
-
</VerticalLayout>
|
|
444
|
-
|
|
445
|
-
// Horizontal Layout
|
|
446
|
-
<HorizontalLayout spacing="large" align="center">
|
|
447
|
-
<label />
|
|
448
|
-
<input />
|
|
449
|
-
</HorizontalLayout>
|
|
450
|
-
|
|
451
|
-
// Grid Layout
|
|
452
|
-
<GridLayout columns={3} gap="medium">
|
|
453
|
-
<Card />
|
|
454
|
-
<Card />
|
|
455
|
-
<Card />
|
|
456
|
-
</GridLayout>
|
|
457
|
-
```
|
|
458
|
-
|
|
459
|
-
## Use Cases
|
|
361
|
+
import { ExtendedForm } from 'extended-dynamic-forms';
|
|
362
|
+
import { smartTransformJsonRulesEngine } from 'extended-dynamic-forms';
|
|
460
363
|
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
364
|
+
const conditions = [
|
|
365
|
+
{
|
|
366
|
+
conditions: {
|
|
367
|
+
isStudent: true
|
|
368
|
+
},
|
|
369
|
+
event: {
|
|
370
|
+
type: "show",
|
|
371
|
+
params: { field: ["studentId", "school"] }
|
|
372
|
+
}
|
|
373
|
+
},
|
|
464
374
|
{
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
375
|
+
conditions: {
|
|
376
|
+
isStudent: false
|
|
377
|
+
},
|
|
378
|
+
event: {
|
|
379
|
+
type: "hide",
|
|
380
|
+
params: { field: ["studentId", "school"] }
|
|
381
|
+
}
|
|
469
382
|
}
|
|
470
383
|
];
|
|
471
384
|
|
|
472
|
-
//
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
### Auto-save & Recovery
|
|
476
|
-
```tsx
|
|
477
|
-
<ExtendedForm
|
|
478
|
-
schema={schema}
|
|
479
|
-
onFieldChange={(event) => {
|
|
480
|
-
// Auto-save to localStorage or server
|
|
481
|
-
localStorage.setItem(`form_${event.fieldId}`, event.fieldValue);
|
|
482
|
-
}}
|
|
483
|
-
webhooks={[{
|
|
484
|
-
url: 'https://api.yourapp.com/autosave',
|
|
485
|
-
events: ['change'],
|
|
486
|
-
debounceMs: 2000 // Save every 2 seconds
|
|
487
|
-
}]}
|
|
488
|
-
/>
|
|
489
|
-
```
|
|
385
|
+
// Transform JSON Rules Engine format to internal format
|
|
386
|
+
const transformedRules = smartTransformJsonRulesEngine(conditions);
|
|
490
387
|
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
const isValid = await validateEmailWithAPI(event.fieldValue);
|
|
498
|
-
setEmailValidation(isValid);
|
|
499
|
-
}
|
|
500
|
-
}}
|
|
501
|
-
webhooks={[{
|
|
502
|
-
url: 'https://validation.yourapp.com/validate',
|
|
503
|
-
events: ['blur'],
|
|
504
|
-
headers: { 'Content-Type': 'application/json' }
|
|
505
|
-
}]}
|
|
506
|
-
/>
|
|
507
|
-
```
|
|
388
|
+
const conditionalConfig = {
|
|
389
|
+
rules: transformedRules,
|
|
390
|
+
onSchemaChange: ({ schema, uiSchema }) => {
|
|
391
|
+
console.log('Schema updated:', { schema, uiSchema });
|
|
392
|
+
}
|
|
393
|
+
};
|
|
508
394
|
|
|
509
|
-
|
|
510
|
-
```tsx
|
|
511
|
-
<ExtendedForm
|
|
395
|
+
<ExtendedForm
|
|
512
396
|
schema={schema}
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
setShowStateField(true);
|
|
517
|
-
}
|
|
518
|
-
}}
|
|
397
|
+
uiSchema={uiSchema}
|
|
398
|
+
conditionals={conditionalConfig}
|
|
399
|
+
onChange={handleChange}
|
|
519
400
|
/>
|
|
520
401
|
```
|
|
521
402
|
|
|
522
|
-
|
|
403
|
+
### Wizard Form with Step-Aware Conditionals
|
|
523
404
|
|
|
524
|
-
|
|
525
|
-
- Show/hide fields based on other field values
|
|
526
|
-
- Make fields required/optional conditionally
|
|
527
|
-
- Enable/disable fields based on complex conditions
|
|
528
|
-
- Support multiple conditions with AND/OR logic
|
|
529
|
-
|
|
530
|
-
### Basic Conditional Example
|
|
405
|
+
The `WizardForm` component automatically handles step-aware conditional processing:
|
|
531
406
|
|
|
532
407
|
```tsx
|
|
533
|
-
import {
|
|
408
|
+
import { WizardForm } from 'extended-dynamic-forms';
|
|
534
409
|
|
|
535
|
-
|
|
410
|
+
// Schema with step structure
|
|
411
|
+
const wizardSchema = {
|
|
536
412
|
type: 'object',
|
|
537
413
|
properties: {
|
|
538
|
-
|
|
539
|
-
type: '
|
|
540
|
-
|
|
541
|
-
|
|
414
|
+
STEP_PERSONAL: {
|
|
415
|
+
type: 'object',
|
|
416
|
+
title: 'Personal Information',
|
|
417
|
+
properties: {
|
|
418
|
+
name: { type: 'string', title: 'Name' },
|
|
419
|
+
isStudent: { type: 'boolean', title: 'Are you a student?' },
|
|
420
|
+
studentId: { type: 'string', title: 'Student ID' }
|
|
421
|
+
}
|
|
542
422
|
},
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
423
|
+
STEP_CONTACT: {
|
|
424
|
+
type: 'object',
|
|
425
|
+
title: 'Contact Information',
|
|
426
|
+
properties: {
|
|
427
|
+
email: { type: 'string', format: 'email' },
|
|
428
|
+
phone: { type: 'string' }
|
|
429
|
+
}
|
|
430
|
+
}
|
|
547
431
|
}
|
|
548
432
|
};
|
|
549
433
|
|
|
550
|
-
|
|
434
|
+
// Conditions that reference step fields
|
|
435
|
+
const stepConditions = [
|
|
551
436
|
{
|
|
552
437
|
conditions: {
|
|
553
|
-
|
|
438
|
+
"STEP_PERSONAL.isStudent": false
|
|
554
439
|
},
|
|
555
440
|
event: {
|
|
556
|
-
type:
|
|
557
|
-
params: {
|
|
558
|
-
}
|
|
559
|
-
},
|
|
560
|
-
{
|
|
561
|
-
conditions: {
|
|
562
|
-
accountType: { equals: 'business' }
|
|
563
|
-
},
|
|
564
|
-
event: {
|
|
565
|
-
type: 'show',
|
|
566
|
-
params: { fields: ['businessName', 'taxId'] }
|
|
441
|
+
type: "hide",
|
|
442
|
+
params: { field: "STEP_PERSONAL.studentId" }
|
|
567
443
|
}
|
|
568
444
|
}
|
|
569
445
|
];
|
|
570
446
|
|
|
571
|
-
<
|
|
572
|
-
schema={
|
|
573
|
-
|
|
447
|
+
<WizardForm
|
|
448
|
+
schema={wizardSchema}
|
|
449
|
+
uiSchema={uiSchema}
|
|
450
|
+
conditions={stepConditions}
|
|
574
451
|
onSubmit={handleSubmit}
|
|
575
452
|
/>
|
|
576
453
|
```
|
|
577
454
|
|
|
578
|
-
###
|
|
455
|
+
### Supported Conditional Actions
|
|
456
|
+
The conditional engine directly supports the following actions (defined in `ConditionalActions.ts`):
|
|
457
|
+
- `show` - Makes fields visible (adds them back to the schema if previously removed).
|
|
458
|
+
- `remove` - Removes fields from the schema and uiSchema (effectively hides them).
|
|
459
|
+
- `enable` / `disable` - Enable or disable fields.
|
|
460
|
+
- `require` / `optional` - Make fields required or optional.
|
|
461
|
+
- `uiAppend` - Appends to existing uiSchema properties (e.g., concatenates classNames, merges `ui:order`).
|
|
462
|
+
- `uiOverride` - Overrides specific uiSchema fields.
|
|
463
|
+
- `uiReplace` - Replaces entire uiSchema sections.
|
|
464
|
+
- Custom actions - Register your own conditional actions
|
|
465
|
+
|
|
466
|
+
**Note on `smartTransformJsonRulesEngine`:**
|
|
467
|
+
When providing conditions in the JSON Rules Engine format (e.g., to `WizardForm` or by calling `smartTransformJsonRulesEngine` directly):
|
|
468
|
+
- Input rules with `event.type: "show"` are typically converted into an internal `remove` action with *inverted* conditions.
|
|
469
|
+
- Input rules with `event.type: "hide"` are converted into an internal `remove` action.
|
|
470
|
+
- Input rules with `event.type: "required"` or `"optional"` are transformed into internal `require` or `optional` actions, respectively.
|
|
471
|
+
|
|
472
|
+
### JSON Rules Engine Support
|
|
473
|
+
|
|
474
|
+
The library includes transformation utilities for json-rules-engine format:
|
|
579
475
|
|
|
580
476
|
```tsx
|
|
581
|
-
|
|
477
|
+
import { smartTransformJsonRulesEngine } from 'extended-dynamic-forms';
|
|
478
|
+
|
|
479
|
+
const jsonRulesEngineFormat = [
|
|
582
480
|
{
|
|
583
|
-
// Show state field when country is US AND has address
|
|
584
481
|
conditions: {
|
|
585
482
|
all: [
|
|
586
|
-
{ country: { equals: 'US' } },
|
|
587
|
-
{ hasAddress: { equals: true } }
|
|
588
|
-
]
|
|
589
|
-
},
|
|
590
|
-
event: {
|
|
591
|
-
type: 'show',
|
|
592
|
-
params: { fields: ['state', 'zipCode'] }
|
|
593
|
-
}
|
|
594
|
-
},
|
|
595
|
-
{
|
|
596
|
-
// Show verification for high income personal OR business accounts
|
|
597
|
-
conditions: {
|
|
598
|
-
any: [
|
|
599
|
-
{
|
|
600
|
-
all: [
|
|
601
|
-
{ accountType: { equals: 'personal' } },
|
|
602
|
-
{ income: { greaterThan: 100000 } }
|
|
603
|
-
]
|
|
604
|
-
},
|
|
605
483
|
{
|
|
606
|
-
|
|
484
|
+
fact: "age",
|
|
485
|
+
operator: "greaterThanInclusive",
|
|
486
|
+
value: 18
|
|
607
487
|
}
|
|
608
488
|
]
|
|
609
489
|
},
|
|
610
490
|
event: {
|
|
611
|
-
type:
|
|
612
|
-
params: {
|
|
491
|
+
type: "show",
|
|
492
|
+
params: { field: "driverLicense" }
|
|
613
493
|
}
|
|
614
494
|
}
|
|
615
495
|
];
|
|
616
|
-
```
|
|
617
|
-
|
|
618
|
-
### Available Conditions
|
|
619
|
-
|
|
620
|
-
- `equals` / `notEquals` - Exact value matching
|
|
621
|
-
- `greaterThan` / `lessThan` - Numeric comparisons
|
|
622
|
-
- `greaterThanOrEqual` / `lessThanOrEqual` - Inclusive numeric comparisons
|
|
623
|
-
- `contains` / `notContains` - String contains
|
|
624
|
-
- `in` / `notIn` - Value in array
|
|
625
|
-
- `empty` / `notEmpty` - Check if field has value
|
|
626
|
-
|
|
627
|
-
### Available Events
|
|
628
496
|
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
- `enable` / `disable` - Enable/disable fields
|
|
632
|
-
|
|
633
|
-
### Combining with Webhooks
|
|
634
|
-
|
|
635
|
-
```tsx
|
|
636
|
-
<ConditionalForm
|
|
637
|
-
schema={schema}
|
|
638
|
-
conditionalRules={rules}
|
|
639
|
-
webhooks={[
|
|
640
|
-
{
|
|
641
|
-
url: 'https://api.example.com/validate',
|
|
642
|
-
events: ['change'],
|
|
643
|
-
debounceMs: 500
|
|
644
|
-
}
|
|
645
|
-
]}
|
|
646
|
-
onFieldChange={(event) => {
|
|
647
|
-
// Local handling alongside conditional logic
|
|
648
|
-
console.log('Field changed:', event);
|
|
649
|
-
}}
|
|
650
|
-
/>
|
|
497
|
+
// Automatically transforms operators and structure
|
|
498
|
+
const internalRules = smartTransformJsonRulesEngine(jsonRulesEngineFormat);
|
|
651
499
|
```
|
|
652
500
|
|
|
653
501
|
## API Reference
|
|
@@ -660,17 +508,20 @@ interface ExtendedFormProps extends FormProps {
|
|
|
660
508
|
schema: RJSFSchema;
|
|
661
509
|
uiSchema?: UiSchema;
|
|
662
510
|
formData?: any;
|
|
663
|
-
onSubmit?: (data: any, event
|
|
511
|
+
onSubmit?: (data: import('@rjsf/utils').IChangeEvent<any, RJSFSchema, any>, event?: React.FormEvent<HTMLFormElement>) => void;
|
|
664
512
|
onChange?: (data: any) => void;
|
|
665
|
-
|
|
513
|
+
|
|
666
514
|
// Field-level event handlers
|
|
667
515
|
onFieldFocus?: (event: FormFieldEvent) => Promise<void> | void;
|
|
668
|
-
onFieldBlur?: (event: FormFieldEvent) => Promise<void> | void;
|
|
516
|
+
onFieldBlur?: (event: FormFieldEvent) => Promise<void> | void;
|
|
669
517
|
onFieldChange?: (event: FormFieldEvent) => Promise<void> | void;
|
|
670
518
|
|
|
671
519
|
// Webhook configuration
|
|
672
520
|
webhooks?: WebhookConfig[];
|
|
673
521
|
|
|
522
|
+
// Conditional logic
|
|
523
|
+
conditionals?: ConditionalConfig;
|
|
524
|
+
|
|
674
525
|
// Form lifecycle events
|
|
675
526
|
beforeSubmit?: (data: any) => Promise<any> | any;
|
|
676
527
|
afterSubmit?: (data: any) => Promise<void> | void;
|
|
@@ -679,6 +530,35 @@ interface ExtendedFormProps extends FormProps {
|
|
|
679
530
|
}
|
|
680
531
|
```
|
|
681
532
|
|
|
533
|
+
### WizardFormProps
|
|
534
|
+
|
|
535
|
+
```typescript
|
|
536
|
+
interface WizardFormProps {
|
|
537
|
+
// Required JSON configurations
|
|
538
|
+
schema: any;
|
|
539
|
+
uiSchema: any;
|
|
540
|
+
conditions?: any[];
|
|
541
|
+
webhooks?: WebhookConfig[];
|
|
542
|
+
|
|
543
|
+
// Optional initial data
|
|
544
|
+
formData?: any;
|
|
545
|
+
|
|
546
|
+
// Event handlers
|
|
547
|
+
onSubmit?: (data: any) => void;
|
|
548
|
+
onStepChange?: (step: number, data: any) => void;
|
|
549
|
+
onFieldFocus?: (event: any) => void;
|
|
550
|
+
onFieldBlur?: (event: any) => void;
|
|
551
|
+
onFieldChange?: (event: any) => void;
|
|
552
|
+
|
|
553
|
+
// UI customization
|
|
554
|
+
showProgressBar?: boolean;
|
|
555
|
+
showStepDescription?: boolean;
|
|
556
|
+
submitButtonText?: string;
|
|
557
|
+
liveValidate?: boolean;
|
|
558
|
+
showErrorList?: boolean;
|
|
559
|
+
}
|
|
560
|
+
```
|
|
561
|
+
|
|
682
562
|
### FormFieldEvent
|
|
683
563
|
|
|
684
564
|
```typescript
|
|
@@ -707,67 +587,6 @@ interface WebhookConfig {
|
|
|
707
587
|
}
|
|
708
588
|
```
|
|
709
589
|
|
|
710
|
-
### ConditionalRule
|
|
711
|
-
|
|
712
|
-
```typescript
|
|
713
|
-
interface ConditionalRule {
|
|
714
|
-
conditions: {
|
|
715
|
-
[fieldPath: string]: FieldCondition;
|
|
716
|
-
all?: Array<{ [fieldPath: string]: FieldCondition }>;
|
|
717
|
-
any?: Array<{ [fieldPath: string]: FieldCondition }>;
|
|
718
|
-
};
|
|
719
|
-
event: {
|
|
720
|
-
type: 'show' | 'hide' | 'require' | 'unrequire' | 'disable' | 'enable';
|
|
721
|
-
params: {
|
|
722
|
-
fields: string[];
|
|
723
|
-
};
|
|
724
|
-
};
|
|
725
|
-
}
|
|
726
|
-
|
|
727
|
-
interface FieldCondition {
|
|
728
|
-
equals?: any;
|
|
729
|
-
notEquals?: any;
|
|
730
|
-
greaterThan?: number;
|
|
731
|
-
lessThan?: number;
|
|
732
|
-
greaterThanOrEqual?: number;
|
|
733
|
-
lessThanOrEqual?: number;
|
|
734
|
-
contains?: string;
|
|
735
|
-
notContains?: string;
|
|
736
|
-
in?: any[];
|
|
737
|
-
notIn?: any[];
|
|
738
|
-
empty?: boolean;
|
|
739
|
-
notEmpty?: boolean;
|
|
740
|
-
}
|
|
741
|
-
```
|
|
742
|
-
|
|
743
|
-
## Utility Functions
|
|
744
|
-
|
|
745
|
-
```tsx
|
|
746
|
-
import { formDataUtils, schemaUtils, validationUtils } from 'extended-dynamic-forms';
|
|
747
|
-
|
|
748
|
-
// Form Data Utils
|
|
749
|
-
const clonedData = formDataUtils.cloneFormData(formData);
|
|
750
|
-
const mergedData = formDataUtils.mergeFormData(current, updates);
|
|
751
|
-
const nestedValue = formDataUtils.getNestedValue(data, 'user.address.city');
|
|
752
|
-
const updatedData = formDataUtils.setNestedValue(data, 'user.name', 'John');
|
|
753
|
-
const cleanData = formDataUtils.removeEmptyValues(data);
|
|
754
|
-
|
|
755
|
-
// Schema Utils
|
|
756
|
-
const required = schemaUtils.getRequiredFields(schema);
|
|
757
|
-
const isRequired = schemaUtils.isFieldRequired(schema, 'email');
|
|
758
|
-
const fieldSchema = schemaUtils.getFieldSchema(schema, 'user.address');
|
|
759
|
-
const merged = schemaUtils.mergeSchemas(schema1, schema2);
|
|
760
|
-
const paths = schemaUtils.getAllFieldPaths(schema);
|
|
761
|
-
|
|
762
|
-
// Validation Utils
|
|
763
|
-
const isEmail = validationUtils.isValidEmail('test@example.com');
|
|
764
|
-
const isPhone = validationUtils.isValidPhone('(555) 123-4567');
|
|
765
|
-
const isUrl = validationUtils.isValidUrl('https://example.com');
|
|
766
|
-
const isDate = validationUtils.isValidDate('2024-01-01');
|
|
767
|
-
const inRange = validationUtils.isInRange(5, 1, 10);
|
|
768
|
-
const message = validationUtils.getValidationMessage('required');
|
|
769
|
-
```
|
|
770
|
-
|
|
771
590
|
## Development
|
|
772
591
|
|
|
773
592
|
```bash
|
|
@@ -787,6 +606,53 @@ npm test
|
|
|
787
606
|
npm run lint
|
|
788
607
|
```
|
|
789
608
|
|
|
609
|
+
## Examples
|
|
610
|
+
|
|
611
|
+
The library includes comprehensive examples demonstrating all features. Run the development server to see them:
|
|
612
|
+
|
|
613
|
+
```bash
|
|
614
|
+
npm run dev
|
|
615
|
+
```
|
|
616
|
+
|
|
617
|
+
Key examples include:
|
|
618
|
+
|
|
619
|
+
- **Simple Wizard Example**: Multi-step company onboarding form
|
|
620
|
+
- **Conditional Logic Demo**: Dynamic field visibility and requirements
|
|
621
|
+
- **Event System Demo**: Real-time form analytics and webhooks
|
|
622
|
+
- **Custom Widget Showcase**: All available widgets and their options
|
|
623
|
+
|
|
624
|
+
## Use Cases
|
|
625
|
+
|
|
626
|
+
### Real-time Form Analytics
|
|
627
|
+
- Track user interactions and field completion rates
|
|
628
|
+
- Monitor form abandonment points
|
|
629
|
+
- Capture detailed user behavior data
|
|
630
|
+
|
|
631
|
+
### Auto-save & Recovery
|
|
632
|
+
- Automatically save form data as users type
|
|
633
|
+
- Implement form recovery after page reload
|
|
634
|
+
- Background data synchronization
|
|
635
|
+
|
|
636
|
+
### Dynamic Form Behavior
|
|
637
|
+
- Show/hide fields based on user input
|
|
638
|
+
- Change validation rules dynamically
|
|
639
|
+
- Progressive form enhancement
|
|
640
|
+
|
|
641
|
+
### Multi-step Workflows
|
|
642
|
+
- Complex onboarding processes
|
|
643
|
+
- Survey and questionnaire systems
|
|
644
|
+
- Application and registration forms
|
|
645
|
+
|
|
646
|
+
## Architecture
|
|
647
|
+
|
|
648
|
+
The library is built on three core principles:
|
|
649
|
+
|
|
650
|
+
1. **Wrapper Architecture**: Extends RJSF v6 without breaking existing functionality
|
|
651
|
+
2. **Central Event Orchestration**: All form interactions flow through a unified event system
|
|
652
|
+
3. **Conditional Logic Engine**: Dynamic schema transformations with comprehensive rule support
|
|
653
|
+
|
|
654
|
+
For detailed architectural information, see the [Developer Guide](./DEVELOPER_GUIDE.md).
|
|
655
|
+
|
|
790
656
|
## License
|
|
791
657
|
|
|
792
|
-
MIT
|
|
658
|
+
MIT
|