extended-dynamic-forms 0.2.0 → 0.2.1
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 +427 -99
- package/dist/WizardForm.d.ts +4 -1
- package/dist/events/FormEventHub.d.ts +19 -2
- package/dist/index.es.js +6723 -6594
- package/dist/index.umd.js +22 -22
- package/dist/types/index.d.ts +6 -1
- package/dist/utils/fieldChangeDetector.d.ts +22 -0
- package/dist/vanilla-entry.d.ts +28 -0
- package/package.json +4 -4
- package/examples/conditional-v2-example.tsx +0 -64
- package/examples/dynamic-array-items-example.tsx +0 -211
- package/examples/form-devtools-example.tsx +0 -384
- package/examples/global-ui-rules-example.tsx +0 -371
- package/examples/vanilla-js/README.md +0 -212
- package/examples/vanilla-js/basic-form.html +0 -142
- package/examples/vanilla-js/conditional-form.html +0 -159
- package/examples/vanilla-js/wizard-form.html +0 -185
|
@@ -1,371 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { ExtendedForm } from '../src/ExtendedForm';
|
|
3
|
-
import { RJSFSchema, UiSchema, IChangeEvent } from '@rjsf/utils';
|
|
4
|
-
import { useConditionalUi, UiRule, JsonLogicRule } from '../src/conditionals/v2';
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Global UI Rules Example
|
|
8
|
-
*
|
|
9
|
-
* This example demonstrates the UI Logic Pillar of the Three Pillars architecture.
|
|
10
|
-
* It shows how to:
|
|
11
|
-
* 1. Show/hide form sections based on conditions
|
|
12
|
-
* 2. Dynamically change widget types
|
|
13
|
-
* 3. Modify field ordering based on user input
|
|
14
|
-
* 4. Handle data clearing in the onChange handler (separation of concerns)
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
// Type definition for our form data
|
|
18
|
-
type ShippingFormData = {
|
|
19
|
-
name: string;
|
|
20
|
-
email: string;
|
|
21
|
-
requiresShipping: boolean;
|
|
22
|
-
shippingAddress?: {
|
|
23
|
-
street?: string;
|
|
24
|
-
city?: string;
|
|
25
|
-
zipCode?: string;
|
|
26
|
-
country?: 'USA' | 'Canada' | 'Mexico' | 'Other';
|
|
27
|
-
state?: string;
|
|
28
|
-
province?: string;
|
|
29
|
-
region?: string;
|
|
30
|
-
internationalDetails?: string;
|
|
31
|
-
};
|
|
32
|
-
deliveryInstructions?: string;
|
|
33
|
-
expressShipping?: boolean;
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
// Schema definition for a comprehensive shipping form
|
|
37
|
-
const schema: RJSFSchema = {
|
|
38
|
-
type: 'object',
|
|
39
|
-
required: ['name', 'email'],
|
|
40
|
-
properties: {
|
|
41
|
-
name: {
|
|
42
|
-
type: 'string',
|
|
43
|
-
title: 'Full Name'
|
|
44
|
-
},
|
|
45
|
-
email: {
|
|
46
|
-
type: 'string',
|
|
47
|
-
format: 'email',
|
|
48
|
-
title: 'Email Address'
|
|
49
|
-
},
|
|
50
|
-
requiresShipping: {
|
|
51
|
-
type: 'boolean',
|
|
52
|
-
title: 'Requires Physical Shipping?',
|
|
53
|
-
default: false
|
|
54
|
-
},
|
|
55
|
-
shippingAddress: {
|
|
56
|
-
type: 'object',
|
|
57
|
-
title: 'Shipping Address',
|
|
58
|
-
required: ['street', 'city', 'zipCode', 'country'],
|
|
59
|
-
properties: {
|
|
60
|
-
street: {
|
|
61
|
-
type: 'string',
|
|
62
|
-
title: 'Street Address'
|
|
63
|
-
},
|
|
64
|
-
city: {
|
|
65
|
-
type: 'string',
|
|
66
|
-
title: 'City'
|
|
67
|
-
},
|
|
68
|
-
zipCode: {
|
|
69
|
-
type: 'string',
|
|
70
|
-
title: 'ZIP/Postal Code'
|
|
71
|
-
},
|
|
72
|
-
country: {
|
|
73
|
-
type: 'string',
|
|
74
|
-
title: 'Country',
|
|
75
|
-
enum: ['USA', 'Canada', 'Mexico', 'Other'],
|
|
76
|
-
default: 'USA'
|
|
77
|
-
},
|
|
78
|
-
// Different fields for different countries
|
|
79
|
-
state: {
|
|
80
|
-
type: 'string',
|
|
81
|
-
title: 'State',
|
|
82
|
-
enum: ['AL', 'AK', 'AZ', 'AR', 'CA', 'CO', 'CT', 'DE', 'FL', 'GA',
|
|
83
|
-
'HI', 'ID', 'IL', 'IN', 'IA', 'KS', 'KY', 'LA', 'ME', 'MD',
|
|
84
|
-
'MA', 'MI', 'MN', 'MS', 'MO', 'MT', 'NE', 'NV', 'NH', 'NJ',
|
|
85
|
-
'NM', 'NY', 'NC', 'ND', 'OH', 'OK', 'OR', 'PA', 'RI', 'SC',
|
|
86
|
-
'SD', 'TN', 'TX', 'UT', 'VT', 'VA', 'WA', 'WV', 'WI', 'WY']
|
|
87
|
-
},
|
|
88
|
-
province: {
|
|
89
|
-
type: 'string',
|
|
90
|
-
title: 'Province',
|
|
91
|
-
enum: ['AB', 'BC', 'MB', 'NB', 'NL', 'NS', 'NT', 'NU', 'ON', 'PE', 'QC', 'SK', 'YT']
|
|
92
|
-
},
|
|
93
|
-
region: {
|
|
94
|
-
type: 'string',
|
|
95
|
-
title: 'State/Province/Region'
|
|
96
|
-
},
|
|
97
|
-
internationalDetails: {
|
|
98
|
-
type: 'string',
|
|
99
|
-
title: 'International Shipping Details',
|
|
100
|
-
description: 'Please provide any special international shipping requirements'
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
},
|
|
104
|
-
deliveryInstructions: {
|
|
105
|
-
type: 'string',
|
|
106
|
-
title: 'Delivery Instructions',
|
|
107
|
-
description: 'Special instructions for the delivery person'
|
|
108
|
-
},
|
|
109
|
-
expressShipping: {
|
|
110
|
-
type: 'boolean',
|
|
111
|
-
title: 'Express Shipping (2-3 days)',
|
|
112
|
-
default: false
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
};
|
|
116
|
-
|
|
117
|
-
// Base UI Schema - defines the default UI configuration
|
|
118
|
-
const baseUiSchema: UiSchema = {
|
|
119
|
-
'ui:order': ['name', 'email', 'requiresShipping', 'shippingAddress', 'expressShipping', 'deliveryInstructions'],
|
|
120
|
-
name: {
|
|
121
|
-
'ui:autofocus': true,
|
|
122
|
-
'ui:placeholder': 'Enter your full name'
|
|
123
|
-
},
|
|
124
|
-
email: {
|
|
125
|
-
'ui:placeholder': 'email@example.com',
|
|
126
|
-
'ui:help': 'We\'ll use this for order confirmation'
|
|
127
|
-
},
|
|
128
|
-
shippingAddress: {
|
|
129
|
-
// Initially hidden until shipping is required
|
|
130
|
-
'ui:widget': 'hidden',
|
|
131
|
-
'ui:order': ['street', 'city', 'country', 'state', 'province', 'region', 'zipCode'],
|
|
132
|
-
street: {
|
|
133
|
-
'ui:placeholder': '123 Main St'
|
|
134
|
-
},
|
|
135
|
-
city: {
|
|
136
|
-
'ui:placeholder': 'New York'
|
|
137
|
-
},
|
|
138
|
-
zipCode: {
|
|
139
|
-
'ui:placeholder': '10001'
|
|
140
|
-
},
|
|
141
|
-
state: {
|
|
142
|
-
'ui:widget': 'select',
|
|
143
|
-
'ui:placeholder': 'Select a state'
|
|
144
|
-
},
|
|
145
|
-
province: {
|
|
146
|
-
'ui:placeholder': 'Select a province',
|
|
147
|
-
// Initially hidden
|
|
148
|
-
'ui:widget': 'hidden'
|
|
149
|
-
},
|
|
150
|
-
region: {
|
|
151
|
-
'ui:placeholder': 'Enter state/province/region',
|
|
152
|
-
// Initially hidden
|
|
153
|
-
'ui:widget': 'hidden'
|
|
154
|
-
},
|
|
155
|
-
internationalDetails: {
|
|
156
|
-
'ui:widget': 'hidden', // Hidden by default
|
|
157
|
-
'ui:options': {
|
|
158
|
-
rows: 3
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
},
|
|
162
|
-
deliveryInstructions: {
|
|
163
|
-
'ui:widget': 'hidden',
|
|
164
|
-
'ui:options': {
|
|
165
|
-
rows: 3
|
|
166
|
-
}
|
|
167
|
-
},
|
|
168
|
-
expressShipping: {
|
|
169
|
-
'ui:widget': 'hidden'
|
|
170
|
-
}
|
|
171
|
-
};
|
|
172
|
-
|
|
173
|
-
// Global UI Rules using JSON Patch operations
|
|
174
|
-
const globalUiRules: UiRule[] = [
|
|
175
|
-
// Rule 1: Show shipping address when shipping is required
|
|
176
|
-
{
|
|
177
|
-
name: 'Show shipping address when shipping required',
|
|
178
|
-
condition: { "===": [{ "var": "requiresShipping" }, true] } as JsonLogicRule,
|
|
179
|
-
effect: [
|
|
180
|
-
{ op: 'remove', path: '/shippingAddress/ui:widget' }
|
|
181
|
-
],
|
|
182
|
-
order: 1
|
|
183
|
-
},
|
|
184
|
-
|
|
185
|
-
// Rule 2: Show delivery instructions when shipping is required
|
|
186
|
-
{
|
|
187
|
-
name: 'Show delivery instructions when shipping required',
|
|
188
|
-
condition: { "===": [{ "var": "requiresShipping" }, true] } as JsonLogicRule,
|
|
189
|
-
effect: [
|
|
190
|
-
{ op: 'replace', path: '/deliveryInstructions/ui:widget', value: 'textarea' }
|
|
191
|
-
],
|
|
192
|
-
order: 2
|
|
193
|
-
},
|
|
194
|
-
|
|
195
|
-
// Rule 3: Show express shipping option when shipping is required
|
|
196
|
-
{
|
|
197
|
-
name: 'Show express shipping option when shipping required',
|
|
198
|
-
condition: { "===": [{ "var": "requiresShipping" }, true] } as JsonLogicRule,
|
|
199
|
-
effect: [
|
|
200
|
-
{ op: 'remove', path: '/expressShipping/ui:widget' }
|
|
201
|
-
],
|
|
202
|
-
order: 3
|
|
203
|
-
},
|
|
204
|
-
|
|
205
|
-
// Rule 4: Show state dropdown only for USA
|
|
206
|
-
{
|
|
207
|
-
name: 'Show state field for USA',
|
|
208
|
-
condition: {
|
|
209
|
-
"and": [
|
|
210
|
-
{ "===": [{ "var": "requiresShipping" }, true] },
|
|
211
|
-
{ "===": [{ "var": "shippingAddress.country" }, "USA"] }
|
|
212
|
-
]
|
|
213
|
-
} as JsonLogicRule,
|
|
214
|
-
effect: [
|
|
215
|
-
{ op: 'remove', path: '/shippingAddress/state/ui:widget' },
|
|
216
|
-
{ op: 'add', path: '/shippingAddress/province/ui:widget', value: 'hidden' },
|
|
217
|
-
{ op: 'add', path: '/shippingAddress/region/ui:widget', value: 'hidden' }
|
|
218
|
-
],
|
|
219
|
-
order: 4
|
|
220
|
-
},
|
|
221
|
-
|
|
222
|
-
// Rule 5: Show province dropdown only for Canada
|
|
223
|
-
{
|
|
224
|
-
name: 'Show province field for Canada',
|
|
225
|
-
condition: {
|
|
226
|
-
"and": [
|
|
227
|
-
{ "===": [{ "var": "requiresShipping" }, true] },
|
|
228
|
-
{ "===": [{ "var": "shippingAddress.country" }, "Canada"] }
|
|
229
|
-
]
|
|
230
|
-
} as JsonLogicRule,
|
|
231
|
-
effect: [
|
|
232
|
-
{ op: 'add', path: '/shippingAddress/state/ui:widget', value: 'hidden' },
|
|
233
|
-
{ op: 'remove', path: '/shippingAddress/province/ui:widget' },
|
|
234
|
-
{ op: 'add', path: '/shippingAddress/region/ui:widget', value: 'hidden' }
|
|
235
|
-
],
|
|
236
|
-
order: 5
|
|
237
|
-
},
|
|
238
|
-
|
|
239
|
-
// Rule 6: Show region text field for Mexico and Other
|
|
240
|
-
{
|
|
241
|
-
name: 'Show region field for Mexico and Other countries',
|
|
242
|
-
condition: {
|
|
243
|
-
"and": [
|
|
244
|
-
{ "===": [{ "var": "requiresShipping" }, true] },
|
|
245
|
-
{ "in": [{ "var": "shippingAddress.country" }, ["Mexico", "Other"]] }
|
|
246
|
-
]
|
|
247
|
-
} as JsonLogicRule,
|
|
248
|
-
effect: [
|
|
249
|
-
{ op: 'add', path: '/shippingAddress/state/ui:widget', value: 'hidden' },
|
|
250
|
-
{ op: 'add', path: '/shippingAddress/province/ui:widget', value: 'hidden' },
|
|
251
|
-
{ op: 'remove', path: '/shippingAddress/region/ui:widget' }
|
|
252
|
-
],
|
|
253
|
-
order: 6
|
|
254
|
-
},
|
|
255
|
-
|
|
256
|
-
// Rule 7: Show international details only for "Other" countries
|
|
257
|
-
{
|
|
258
|
-
name: 'Show international details for non-North American countries',
|
|
259
|
-
condition: {
|
|
260
|
-
"and": [
|
|
261
|
-
{ "===": [{ "var": "requiresShipping" }, true] },
|
|
262
|
-
{ "===": [{ "var": "shippingAddress.country" }, "Other"] }
|
|
263
|
-
]
|
|
264
|
-
} as JsonLogicRule,
|
|
265
|
-
effect: [
|
|
266
|
-
{ op: 'replace', path: '/shippingAddress/internationalDetails/ui:widget', value: 'textarea' }
|
|
267
|
-
],
|
|
268
|
-
order: 7
|
|
269
|
-
},
|
|
270
|
-
|
|
271
|
-
// Rule 8: Reorder fields to put international details at end when visible
|
|
272
|
-
{
|
|
273
|
-
name: 'Reorder fields for international shipping',
|
|
274
|
-
condition: {
|
|
275
|
-
"and": [
|
|
276
|
-
{ "===": [{ "var": "requiresShipping" }, true] },
|
|
277
|
-
{ "===": [{ "var": "shippingAddress.country" }, "Other"] }
|
|
278
|
-
]
|
|
279
|
-
} as JsonLogicRule,
|
|
280
|
-
effect: [
|
|
281
|
-
{
|
|
282
|
-
op: 'replace',
|
|
283
|
-
path: '/shippingAddress/ui:order',
|
|
284
|
-
value: ['street', 'city', 'country', 'region', 'zipCode', 'internationalDetails']
|
|
285
|
-
}
|
|
286
|
-
],
|
|
287
|
-
order: 8
|
|
288
|
-
}
|
|
289
|
-
];
|
|
290
|
-
|
|
291
|
-
export function GlobalUiRulesExample() {
|
|
292
|
-
const [formData, setFormData] = React.useState<ShippingFormData>({
|
|
293
|
-
name: '',
|
|
294
|
-
email: '',
|
|
295
|
-
requiresShipping: false,
|
|
296
|
-
shippingAddress: {
|
|
297
|
-
country: 'USA'
|
|
298
|
-
}
|
|
299
|
-
});
|
|
300
|
-
|
|
301
|
-
// Apply UI rules to base UI schema
|
|
302
|
-
// This is a pure function that only modifies the UI schema
|
|
303
|
-
const conditionalUiSchema = useConditionalUi(globalUiRules, baseUiSchema, formData);
|
|
304
|
-
|
|
305
|
-
// Handle form changes with data side effects
|
|
306
|
-
// This demonstrates the separation of concerns between UI and data logic
|
|
307
|
-
const handleChange = ({ formData: newFormData }: IChangeEvent<ShippingFormData>) => {
|
|
308
|
-
let dataToSet = { ...newFormData };
|
|
309
|
-
|
|
310
|
-
// DATA SIDE EFFECT: Clear shipping address when shipping is disabled
|
|
311
|
-
if (formData.requiresShipping && !newFormData.requiresShipping) {
|
|
312
|
-
dataToSet.shippingAddress = {
|
|
313
|
-
country: 'USA' // Reset to default country
|
|
314
|
-
};
|
|
315
|
-
dataToSet.deliveryInstructions = '';
|
|
316
|
-
dataToSet.expressShipping = false;
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
// DATA SIDE EFFECT: Clear state/province/region when country changes
|
|
320
|
-
const oldCountry = formData.shippingAddress?.country;
|
|
321
|
-
const newCountry = newFormData.shippingAddress?.country;
|
|
322
|
-
|
|
323
|
-
if (oldCountry !== newCountry && newFormData.shippingAddress) {
|
|
324
|
-
// Clear location fields when switching countries
|
|
325
|
-
delete dataToSet.shippingAddress.state;
|
|
326
|
-
delete dataToSet.shippingAddress.province;
|
|
327
|
-
delete dataToSet.shippingAddress.region;
|
|
328
|
-
delete dataToSet.shippingAddress.internationalDetails;
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
setFormData(dataToSet);
|
|
332
|
-
};
|
|
333
|
-
|
|
334
|
-
const handleSubmit = ({ formData }: IChangeEvent<ShippingFormData>) => {
|
|
335
|
-
console.log('Form submitted:', formData);
|
|
336
|
-
alert('Form submitted! Check console for details.');
|
|
337
|
-
};
|
|
338
|
-
|
|
339
|
-
return (
|
|
340
|
-
<div style={{ padding: '20px', maxWidth: '800px', margin: '0 auto' }}>
|
|
341
|
-
<h1>Global UI Rules Example</h1>
|
|
342
|
-
<p>
|
|
343
|
-
This example demonstrates the UI Logic Pillar of the Three Pillars conditional system.
|
|
344
|
-
Try toggling "Requires Physical Shipping" and changing countries to see dynamic UI updates.
|
|
345
|
-
</p>
|
|
346
|
-
|
|
347
|
-
<div style={{ marginBottom: '20px', padding: '10px', backgroundColor: '#f0f0f0', borderRadius: '4px' }}>
|
|
348
|
-
<h3>Features Demonstrated:</h3>
|
|
349
|
-
<ul>
|
|
350
|
-
<li>Show/hide form sections based on shipping requirement</li>
|
|
351
|
-
<li>Dynamic widget changes (state dropdown vs province dropdown vs region text field)</li>
|
|
352
|
-
<li>Conditional field ordering (international details appears at end)</li>
|
|
353
|
-
<li>Data clearing when sections are hidden (handled in onChange)</li>
|
|
354
|
-
</ul>
|
|
355
|
-
</div>
|
|
356
|
-
|
|
357
|
-
<ExtendedForm
|
|
358
|
-
schema={schema}
|
|
359
|
-
uiSchema={conditionalUiSchema}
|
|
360
|
-
formData={formData}
|
|
361
|
-
onChange={handleChange}
|
|
362
|
-
onSubmit={handleSubmit}
|
|
363
|
-
/>
|
|
364
|
-
|
|
365
|
-
<div style={{ marginTop: '20px', padding: '10px', backgroundColor: '#f9f9f9', borderRadius: '4px' }}>
|
|
366
|
-
<h4>Current Form Data:</h4>
|
|
367
|
-
<pre>{JSON.stringify(formData, null, 2)}</pre>
|
|
368
|
-
</div>
|
|
369
|
-
</div>
|
|
370
|
-
);
|
|
371
|
-
}
|
|
@@ -1,212 +0,0 @@
|
|
|
1
|
-
# Vanilla JS Usage Guide
|
|
2
|
-
|
|
3
|
-
This directory contains examples of how to use Extended Dynamic Forms as a vanilla JavaScript library without React knowledge.
|
|
4
|
-
|
|
5
|
-
## Quick Start
|
|
6
|
-
|
|
7
|
-
1. **Include the standalone bundle:**
|
|
8
|
-
```html
|
|
9
|
-
<script src="path/to/extended-dynamic-forms.standalone.js"></script>
|
|
10
|
-
```
|
|
11
|
-
|
|
12
|
-
2. **Create a basic form:**
|
|
13
|
-
```javascript
|
|
14
|
-
const form = ExtendedDynamicForms.createForm({
|
|
15
|
-
container: '#my-form',
|
|
16
|
-
schema: {
|
|
17
|
-
type: 'object',
|
|
18
|
-
properties: {
|
|
19
|
-
name: { type: 'string', title: 'Name' },
|
|
20
|
-
email: { type: 'string', format: 'email', title: 'Email' }
|
|
21
|
-
}
|
|
22
|
-
},
|
|
23
|
-
onChange: (formData) => console.log(formData),
|
|
24
|
-
onSubmit: (formData) => alert('Submitted: ' + JSON.stringify(formData))
|
|
25
|
-
});
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
## Examples
|
|
29
|
-
|
|
30
|
-
- **`basic-form.html`** - Simple contact form with validation
|
|
31
|
-
- **`conditional-form.html`** - Form with conditional field visibility
|
|
32
|
-
- **`wizard-form.html`** - Multi-step wizard form
|
|
33
|
-
|
|
34
|
-
## API Reference
|
|
35
|
-
|
|
36
|
-
### ExtendedDynamicForms.createForm(config)
|
|
37
|
-
|
|
38
|
-
Creates a standard form.
|
|
39
|
-
|
|
40
|
-
**Config Options:**
|
|
41
|
-
- `container` (string|HTMLElement) - Container selector or element
|
|
42
|
-
- `schema` (object) - JSON Schema defining form structure
|
|
43
|
-
- `uiSchema` (object) - UI customizations and widget selections
|
|
44
|
-
- `formData` (object) - Initial form data
|
|
45
|
-
- `onChange` (function) - Called when form data changes
|
|
46
|
-
- `onSubmit` (function) - Called when form is submitted
|
|
47
|
-
- `onError` (function) - Called when validation errors occur
|
|
48
|
-
- `conditionals` (object) - Conditional logic rules
|
|
49
|
-
- `webhooks` (array) - Webhook configurations
|
|
50
|
-
- `widgets` (object) - Custom widget overrides
|
|
51
|
-
- `fields` (object) - Custom field components
|
|
52
|
-
|
|
53
|
-
**Returns:**
|
|
54
|
-
- `setFormData(data)` - Update form data
|
|
55
|
-
- `destroy()` - Remove form from DOM
|
|
56
|
-
|
|
57
|
-
### ExtendedDynamicForms.createWizardForm(config)
|
|
58
|
-
|
|
59
|
-
Creates a multi-step wizard form.
|
|
60
|
-
|
|
61
|
-
**Config Options:**
|
|
62
|
-
- `container` (string|HTMLElement) - Container selector or element
|
|
63
|
-
- `steps` (array) - Array of step definitions
|
|
64
|
-
- `initialData` (object) - Initial form data
|
|
65
|
-
- `onStepChange` (function) - Called when step changes
|
|
66
|
-
- `onComplete` (function) - Called when wizard completes
|
|
67
|
-
- `conditionals` (object) - Conditional logic rules
|
|
68
|
-
|
|
69
|
-
### Schema Definition
|
|
70
|
-
|
|
71
|
-
JSON Schema format with additional UI enhancements:
|
|
72
|
-
|
|
73
|
-
```javascript
|
|
74
|
-
const schema = {
|
|
75
|
-
type: 'object',
|
|
76
|
-
properties: {
|
|
77
|
-
fieldName: {
|
|
78
|
-
type: 'string', // string, number, boolean, array, object
|
|
79
|
-
title: 'Display Name',
|
|
80
|
-
description: 'Help text',
|
|
81
|
-
minLength: 2, // Validation rules
|
|
82
|
-
pattern: '^[A-Za-z]+$'
|
|
83
|
-
}
|
|
84
|
-
},
|
|
85
|
-
required: ['fieldName']
|
|
86
|
-
};
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
### UI Schema
|
|
90
|
-
|
|
91
|
-
Customize field appearance and behavior:
|
|
92
|
-
|
|
93
|
-
```javascript
|
|
94
|
-
const uiSchema = {
|
|
95
|
-
fieldName: {
|
|
96
|
-
'ui:widget': 'textarea', // Widget type
|
|
97
|
-
'ui:placeholder': 'Enter text...',
|
|
98
|
-
'ui:autofocus': true,
|
|
99
|
-
'ui:options': {
|
|
100
|
-
rows: 4
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
};
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
### Available Widgets
|
|
107
|
-
|
|
108
|
-
- `text` - Single line text input
|
|
109
|
-
- `textarea` - Multi-line text area
|
|
110
|
-
- `email` - Email input with validation
|
|
111
|
-
- `password` - Password input (masked)
|
|
112
|
-
- `number` - Numeric input
|
|
113
|
-
- `select` - Dropdown selection
|
|
114
|
-
- `radio` - Radio button group
|
|
115
|
-
- `checkbox` - Single checkbox
|
|
116
|
-
- `checkboxes` - Multiple checkboxes
|
|
117
|
-
- `date` - Date picker
|
|
118
|
-
- `datetime` - Date and time picker
|
|
119
|
-
- `file` - File upload
|
|
120
|
-
- `hidden` - Hidden field
|
|
121
|
-
|
|
122
|
-
### Conditional Logic
|
|
123
|
-
|
|
124
|
-
Control field visibility and behavior based on form data:
|
|
125
|
-
|
|
126
|
-
```javascript
|
|
127
|
-
const conditionals = {
|
|
128
|
-
rules: [
|
|
129
|
-
{
|
|
130
|
-
conditions: { userType: 'business' },
|
|
131
|
-
event: {
|
|
132
|
-
type: 'require',
|
|
133
|
-
params: { field: ['businessName', 'taxId'] }
|
|
134
|
-
}
|
|
135
|
-
},
|
|
136
|
-
{
|
|
137
|
-
conditions: { age: { less: 18 } },
|
|
138
|
-
event: {
|
|
139
|
-
type: 'remove',
|
|
140
|
-
params: { field: 'driversLicense' }
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
]
|
|
144
|
-
};
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
### Webhook Integration
|
|
148
|
-
|
|
149
|
-
Send form events to external APIs:
|
|
150
|
-
|
|
151
|
-
```javascript
|
|
152
|
-
const webhooks = [{
|
|
153
|
-
url: 'https://api.example.com/form-events',
|
|
154
|
-
method: 'POST',
|
|
155
|
-
events: ['change', 'submit'],
|
|
156
|
-
debounceMs: 500,
|
|
157
|
-
retries: 3,
|
|
158
|
-
headers: {
|
|
159
|
-
'Authorization': 'Bearer your-token'
|
|
160
|
-
}
|
|
161
|
-
}];
|
|
162
|
-
```
|
|
163
|
-
|
|
164
|
-
## Building Standalone Version
|
|
165
|
-
|
|
166
|
-
To build the standalone version for vanilla JS:
|
|
167
|
-
|
|
168
|
-
```bash
|
|
169
|
-
npm run build:vanilla
|
|
170
|
-
```
|
|
171
|
-
|
|
172
|
-
This creates `dist/extended-dynamic-forms.standalone.js` with all dependencies bundled.
|
|
173
|
-
|
|
174
|
-
## Browser Compatibility
|
|
175
|
-
|
|
176
|
-
- Modern browsers (Chrome 80+, Firefox 75+, Safari 13+, Edge 80+)
|
|
177
|
-
- ES2018+ features required
|
|
178
|
-
- CSS Grid and Flexbox support needed for layouts
|
|
179
|
-
|
|
180
|
-
## Bundle Size
|
|
181
|
-
|
|
182
|
-
The standalone bundle is approximately 2-3MB (uncompressed) and includes:
|
|
183
|
-
- React and ReactDOM
|
|
184
|
-
- Ant Design components
|
|
185
|
-
- RJSF core libraries
|
|
186
|
-
- All form components and widgets
|
|
187
|
-
|
|
188
|
-
Consider using gzip compression on your server to reduce transfer size.
|
|
189
|
-
|
|
190
|
-
## Troubleshooting
|
|
191
|
-
|
|
192
|
-
**Forms not rendering:**
|
|
193
|
-
- Check browser console for errors
|
|
194
|
-
- Ensure container element exists in DOM
|
|
195
|
-
- Verify script is loaded after DOM ready
|
|
196
|
-
|
|
197
|
-
**Styling issues:**
|
|
198
|
-
- Include Ant Design CSS
|
|
199
|
-
- Check for CSS conflicts with existing styles
|
|
200
|
-
- Ensure proper viewport meta tag
|
|
201
|
-
|
|
202
|
-
**Validation not working:**
|
|
203
|
-
- Verify schema format is valid JSON Schema
|
|
204
|
-
- Check required field definitions
|
|
205
|
-
- Review conditional logic syntax
|
|
206
|
-
|
|
207
|
-
## Support
|
|
208
|
-
|
|
209
|
-
For issues and questions:
|
|
210
|
-
- Check the main repository documentation
|
|
211
|
-
- Review example HTML files
|
|
212
|
-
- Open issues on GitHub repository
|