extended-dynamic-forms 0.3.13 → 0.4.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 +253 -674
- package/dist/WizardForm.d.ts +17 -2
- package/dist/components/FieldFeedbackContext.d.ts +4 -0
- package/dist/components/FieldStyleContext.d.ts +7 -0
- package/dist/components/SchemaSelectionContext.d.ts +20 -0
- package/dist/components/URLBlurValidationContext.d.ts +38 -0
- package/dist/components/fields/TextChangeScope.d.ts +28 -0
- package/dist/components/fields/TextEmptyArrayField.d.ts +3 -0
- package/dist/conditionals/v2/createConditionalEngineHook.d.ts +3 -1
- package/dist/conditionals/v2/index.d.ts +2 -1
- package/dist/conditionals/v2/types.d.ts +13 -0
- package/dist/conditionals/v2/utils/stepRules.d.ts +35 -0
- package/dist/events/FormEventContext.d.ts +3 -0
- package/dist/index.es.js +41796 -32825
- package/dist/index.umd.js +1618 -1606
- package/dist/layouts/wizard/WizardLayout.d.ts +1 -0
- package/dist/style.css +1 -1
- package/dist/utils/normalizeUrlValue.d.ts +3 -0
- package/dist/utils/urlValue.d.ts +12 -0
- package/dist/widgets/base/URLParts.d.ts +5 -0
- package/dist/widgets/base/URLPreviewLink.d.ts +5 -0
- package/dist/widgets/base/inputStyles.d.ts +4 -0
- package/dist/widgets/base/inputTypography.d.ts +3 -0
- package/dist/widgets/base/numberInputStyles.d.ts +4 -0
- package/dist/widgets/base/telephoneAddons.d.ts +3 -0
- package/dist/widgets/base/types.d.ts +15 -1
- package/dist/widgets/base/useInputChrome.d.ts +5 -0
- package/dist/widgets/base/utils.d.ts +9 -1
- package/dist/widgets/choice/ChoiceWidget.types.d.ts +2 -0
- package/dist/widgets/choice/dropdownValidation.d.ts +8 -0
- package/dist/widgets/choice/inlineChoiceValidation.d.ts +5 -0
- package/dist/widgets/choice/presenters/InlineChoiceGroup.d.ts +888 -0
- package/dist/widgets/date/DateTimeWidget.d.ts +2 -21
- package/dist/widgets/date/calendarConstraints.d.ts +5 -0
- package/dist/widgets/date/dateRangeValue.d.ts +20 -0
- package/dist/widgets/date/dateTimeValue.d.ts +15 -0
- package/dist/widgets/file/FileUploadWidget.d.ts +3 -32
- package/dist/widgets/index.d.ts +6 -6
- package/dist/widgets/input/TelephoneWidget.d.ts +1 -1
- package/dist/widgets/input/emailValidation.d.ts +7 -0
- package/dist/widgets/input/telephoneMask.d.ts +7 -0
- package/dist/widgets/input/telephoneOptions.d.ts +14 -0
- package/package.json +9 -11
package/README.md
CHANGED
|
@@ -1,741 +1,320 @@
|
|
|
1
1
|
# Extended Dynamic Forms
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
## Project Status
|
|
8
|
-
|
|
9
|
-
**Important Notes:**
|
|
10
|
-
- Requires RJSF source in sibling directory for development
|
|
11
|
-
- Cannot be installed from npm due to local file dependencies
|
|
12
|
-
- JSON logic conditions don't work with vanilla JavaScript builds
|
|
13
|
-
- Array drag-and-drop is not implemented
|
|
14
|
-
- Automated coverage is provided by logic and snapshot suites; component/UI tests
|
|
15
|
-
are intentionally omitted
|
|
16
|
-
- JSON Patch implementation supports add/remove/replace only (not move/copy/test)
|
|
17
|
-
|
|
18
|
-
## Overview
|
|
19
|
-
|
|
20
|
-
Extended Dynamic Forms is an extension library for React JSON Schema Form (RJSF) v6 that adds:
|
|
21
|
-
|
|
22
|
-
- **Declarative conditionals** with O(N) performance (rules + dynamic arrays)
|
|
23
|
-
- **Multi-step wizard forms** with automatic step detection
|
|
24
|
-
- **Central event orchestration** with webhook support
|
|
25
|
-
- **25+ Ant Design components** for professional UI
|
|
26
|
-
- **TypeScript-first** development with full type safety
|
|
27
|
-
|
|
28
|
-
### Ant Design Prop Pass-through
|
|
29
|
-
|
|
30
|
-
All custom widgets built on Ant Design components forward their props via `ui:options`. For example, Rate, Slider, DatePicker, Input, InputNumber, ColorPicker, and TimePicker can be configured using the same prop names from AntD. In addition, you can customize the containing `Form.Item` using `ui:options.formItem`. See docs/custom-widgets-configuration.md for details and examples.
|
|
31
|
-
|
|
32
|
-
- DatePicker notes:
|
|
33
|
-
- JSON-only flags: `disablePastDates`, `disableFutureDates`, `disableWeekends` (builds `disabledDate` internally)
|
|
34
|
-
- Range support: set `ui:options.range: true` to render AntD `RangePicker` (see examples below)
|
|
3
|
+
Extended Dynamic Forms (EDF) extends React JSON Schema Form (RJSF) v6 with
|
|
4
|
+
Ant Design widgets, JSON-configured conditional logic, multi-step forms and
|
|
5
|
+
field events. Use it in a React application with JSON Schema for data constraints
|
|
6
|
+
and `uiSchema` for presentation.
|
|
35
7
|
|
|
36
8
|
## Installation
|
|
37
9
|
|
|
38
|
-
**Note:** This library currently requires local development setup and cannot be installed via npm due to local file dependencies.
|
|
39
|
-
|
|
40
10
|
```bash
|
|
41
|
-
|
|
42
|
-
cd ..
|
|
43
|
-
git clone https://github.com/rjsf-team/react-jsonschema-form.git
|
|
44
|
-
|
|
45
|
-
# Setup Extended Dynamic Forms
|
|
46
|
-
cd extended-dynamic-forms
|
|
47
|
-
npm install
|
|
48
|
-
npm run dev
|
|
11
|
+
npm install extended-dynamic-forms
|
|
49
12
|
```
|
|
50
13
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
## Testing
|
|
54
|
-
|
|
55
|
-
The project uses Vitest with **Node** environment to cover pure logic and serialized
|
|
56
|
-
outputs. Component or DOM-level tests are intentionally excluded.
|
|
57
|
-
|
|
58
|
-
- Run the full suite: `npm test`
|
|
59
|
-
- Logic-only focus: `npm test -- tests/logic`
|
|
60
|
-
- Snapshot updates: `npm test -- tests/snapshots -- -u`
|
|
61
|
-
|
|
62
|
-
After pulling dependencies or updating `package.json`, run `npm install` (or
|
|
63
|
-
`yarn install`) so the lockfile reflects removed packages such as
|
|
64
|
-
`@testing-library/*` and `jsdom`.
|
|
65
|
-
|
|
66
|
-
## Core Architecture
|
|
67
|
-
|
|
68
|
-
### Declarative Conditionals (JSON-only)
|
|
14
|
+
Install compatible peer dependencies if your application does not already have them:
|
|
69
15
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
- UI rules → `uiSchema['x-edf:rules']`
|
|
73
|
-
- Schema rules → `schema['x-edf:rules']`
|
|
74
|
-
|
|
75
|
-
Example (UI rules):
|
|
76
|
-
```json
|
|
77
|
-
{
|
|
78
|
-
"x-edf:rules": [
|
|
79
|
-
{
|
|
80
|
-
"name": "Show license number when has license",
|
|
81
|
-
"condition": { "==": [{ "var": "hasDriversLicense" }, true] },
|
|
82
|
-
"effect": [{ "op": "remove", "path": "/licenseNumber/ui:widget" }]
|
|
83
|
-
}
|
|
84
|
-
]
|
|
85
|
-
}
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
Example (Schema rules):
|
|
89
|
-
```json
|
|
90
|
-
{
|
|
91
|
-
"x-edf:rules": [
|
|
92
|
-
{
|
|
93
|
-
"name": "Add premium fields",
|
|
94
|
-
"condition": { "==": [{ "var": "accountType" }, "premium"] },
|
|
95
|
-
"effect": [
|
|
96
|
-
{ "op": "add", "path": "/properties/premiumFeatures", "value": { "type": "object" } }
|
|
97
|
-
]
|
|
98
|
-
}
|
|
99
|
-
]
|
|
100
|
-
}
|
|
16
|
+
```bash
|
|
17
|
+
npm install 'react@^18.0.0' 'react-dom@^18.0.0' 'antd@^5.24.0' 'dayjs@^1.11.13'
|
|
101
18
|
```
|
|
102
19
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
```json
|
|
108
|
-
{
|
|
109
|
-
"directors": {
|
|
110
|
-
"items": {
|
|
111
|
-
"ui:dynamicItems": {
|
|
112
|
-
"base": { "shareholdingPercentage": { "ui:widget": "hidden" } },
|
|
113
|
-
"rules": [
|
|
114
|
-
{
|
|
115
|
-
"condition": { "===": [{ "var": "hasShareholding" }, true] },
|
|
116
|
-
"ui": { "shareholdingPercentage": { "ui:widget": "updown" } },
|
|
117
|
-
"otherwise": { "shareholdingPercentage": { "ui:widget": "hidden" } }
|
|
118
|
-
}
|
|
119
|
-
]
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
```
|
|
20
|
+
React and React DOM 19 are also supported by the peer ranges. Keep their major
|
|
21
|
+
versions aligned. RJSF and the AJV validator are included in the library bundle;
|
|
22
|
+
you do not need a sibling RJSF checkout.
|
|
125
23
|
|
|
126
|
-
|
|
24
|
+
Use ESM imports and include the exported stylesheet. TypeScript declarations are
|
|
25
|
+
provided; use an ESNext/Bundler-compatible module configuration.
|
|
127
26
|
|
|
128
|
-
|
|
27
|
+
## Features
|
|
129
28
|
|
|
130
|
-
|
|
131
|
-
|
|
29
|
+
- Single-page forms and wizards with step visibility, navigation and validation.
|
|
30
|
+
- Declarative JsonLogic conditions and JSON Patch effects in JSON configuration.
|
|
31
|
+
- Ant Design text, choice, numeric, date/time, file and display widgets.
|
|
32
|
+
- Per-field options, custom widgets, fields, templates and grid layouts.
|
|
33
|
+
- Field focus, blur and change events, submission hooks and webhook configuration.
|
|
132
34
|
|
|
133
|
-
|
|
134
|
-
schema={wizardSchema}
|
|
135
|
-
uiSchema={uiSchema}
|
|
136
|
-
formData={formData}
|
|
137
|
-
onStepChange={(fromStep, toStep) => {
|
|
138
|
-
console.log(`Step ${fromStep} → ${toStep}`);
|
|
139
|
-
}}
|
|
140
|
-
/>
|
|
141
|
-
```
|
|
35
|
+
## Basic usage
|
|
142
36
|
|
|
143
|
-
|
|
37
|
+
```tsx
|
|
38
|
+
import { useState } from 'react';
|
|
39
|
+
import { ExtendedForm, type RJSFSchema, type UiSchema } from 'extended-dynamic-forms';
|
|
40
|
+
import 'extended-dynamic-forms/dist/style.css';
|
|
144
41
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
42
|
+
const schema: RJSFSchema = {
|
|
43
|
+
type: 'object',
|
|
44
|
+
required: ['name'],
|
|
148
45
|
properties: {
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
46
|
+
name: { type: 'string', title: 'Name', minLength: 1 },
|
|
47
|
+
email: { type: 'string', title: 'Email', format: 'email' },
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const uiSchema: UiSchema = {
|
|
52
|
+
name: { 'ui:widget': 'text', 'ui:options': { allowClear: true } },
|
|
53
|
+
email: { 'ui:widget': 'email' },
|
|
155
54
|
};
|
|
156
55
|
|
|
157
|
-
|
|
158
|
-
|
|
56
|
+
export default function ContactForm() {
|
|
57
|
+
const [formData, setFormData] = useState({});
|
|
58
|
+
|
|
59
|
+
return (
|
|
60
|
+
<ExtendedForm
|
|
61
|
+
schema={schema}
|
|
62
|
+
uiSchema={uiSchema}
|
|
63
|
+
formData={formData}
|
|
64
|
+
onChange={({ formData }) => setFormData(formData)}
|
|
65
|
+
onSubmit={({ formData }) => console.log('Accepted answers', formData)}
|
|
66
|
+
/>
|
|
67
|
+
);
|
|
68
|
+
}
|
|
159
69
|
```
|
|
160
70
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
-
|
|
71
|
+
EDF supplies its widgets and validator by default. Override the RJSF `widgets`,
|
|
72
|
+
`fields` or `templates` props when your application needs custom rendering.
|
|
73
|
+
`customWidgets`, `validator` and commonly used RJSF types are exported from
|
|
74
|
+
`extended-dynamic-forms`; no private subpath import is needed.
|
|
165
75
|
|
|
166
|
-
|
|
76
|
+
## Multi-step forms
|
|
167
77
|
|
|
168
|
-
|
|
78
|
+
`WizardForm` detects steps from root properties beginning with `STEP_`. Define at
|
|
79
|
+
least two step objects to show wizard navigation; one step renders as a
|
|
80
|
+
single-page form.
|
|
169
81
|
|
|
170
82
|
```tsx
|
|
171
83
|
import { WizardForm } from 'extended-dynamic-forms';
|
|
84
|
+
import 'extended-dynamic-forms/dist/style.css';
|
|
172
85
|
|
|
173
86
|
const schema = {
|
|
174
87
|
type: 'object',
|
|
175
88
|
properties: {
|
|
176
|
-
|
|
89
|
+
STEP_PERSONAL: {
|
|
177
90
|
type: 'object',
|
|
178
|
-
title: 'Personal
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
};
|
|
189
|
-
|
|
190
|
-
const uiSchema = {
|
|
191
|
-
STEP_LAYOUT: {
|
|
192
|
-
'ui:field': 'LayoutGridField',
|
|
193
|
-
'ui:layoutGrid': {
|
|
194
|
-
'ui:row': [
|
|
195
|
-
{ 'ui:row': { gutter: [16,16], children: [
|
|
196
|
-
{ 'ui:col': { span: 12, children: ['firstName'] } },
|
|
197
|
-
{ 'ui:col': { span: 12, children: ['lastName'] } }
|
|
198
|
-
]}},
|
|
199
|
-
{ 'ui:row': { gutter: [16,16], children: [
|
|
200
|
-
{ 'ui:col': { span: 24, children: ['age'] } }
|
|
201
|
-
]}},
|
|
202
|
-
{ 'ui:row': { gutter: [16,16], children: [
|
|
203
|
-
{ 'ui:col': { span: 24, children: ['gender'] } }
|
|
204
|
-
]}},
|
|
205
|
-
{ 'ui:row': { gutter: [16,16], children: [
|
|
206
|
-
{ 'ui:col': { span: 24, children: ['favoriteBook'] } }
|
|
207
|
-
]}}
|
|
208
|
-
]
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
};
|
|
212
|
-
|
|
213
|
-
// LayoutGridField is included by default in EDF; no extra wiring needed
|
|
214
|
-
<WizardForm schema={schema} uiSchema={uiSchema} />
|
|
215
|
-
```
|
|
216
|
-
|
|
217
|
-
Notes:
|
|
218
|
-
- EDF includes `LayoutGridField` out of the box. Just set `ui:field: 'LayoutGridField'` on the step object.
|
|
219
|
-
- EDF variant uses `'ui:layoutGrid'` with AntD gutter and 24-grid spans. The RJSF canonical layout (`'ui:layout'` with 12-grid widths) is also parsed.
|
|
220
|
-
- You can still override or extend via the `fields` prop if needed.
|
|
221
|
-
- LayoutGridField now writes nested updates immutably using path metadata. This is enabled by default; set `ui:options.pathAware: false` on a step to fall back to the previous shallow merge behaviour.
|
|
222
|
-
|
|
223
|
-
## Event System & Webhooks
|
|
224
|
-
|
|
225
|
-
Central event orchestration for all form interactions:
|
|
226
|
-
|
|
227
|
-
```typescript
|
|
228
|
-
<ExtendedForm
|
|
229
|
-
schema={schema}
|
|
230
|
-
uiSchema={uiSchema}
|
|
231
|
-
webhooks={[{
|
|
232
|
-
url: 'https://api.example.com/events',
|
|
233
|
-
events: ['change', 'blur'],
|
|
234
|
-
debounceMs: 500,
|
|
235
|
-
retries: 3
|
|
236
|
-
}]}
|
|
237
|
-
onFieldChange={(event) => console.log(event.fieldId, event.fieldValue)}
|
|
238
|
-
/>
|
|
239
|
-
```
|
|
240
|
-
|
|
241
|
-
**Event Types:**
|
|
242
|
-
- `focus` - Field focus
|
|
243
|
-
- `blur` - Field blur
|
|
244
|
-
- `change` - Value changes
|
|
245
|
-
- `submit` - Form submission
|
|
246
|
-
- `stepChange` - Wizard navigation
|
|
247
|
-
- `validationError` - Validation failures
|
|
248
|
-
|
|
249
|
-
## Custom Widgets
|
|
250
|
-
|
|
251
|
-
All widgets must integrate with the event system:
|
|
252
|
-
|
|
253
|
-
```typescript
|
|
254
|
-
import { WidgetProps } from '@rjsf/utils';
|
|
255
|
-
import { useFieldEventHandlers } from 'extended-dynamic-forms/events';
|
|
256
|
-
|
|
257
|
-
export const CustomWidget: FC<WidgetProps> = ({ id, value, onChange, schema }) => {
|
|
258
|
-
const fieldEventHandlers = useFieldEventHandlers(id, schema);
|
|
259
|
-
|
|
260
|
-
const handleChange = async (newValue) => {
|
|
261
|
-
onChange(newValue); // RJSF update
|
|
262
|
-
await fieldEventHandlers.onChange(newValue); // Event system
|
|
263
|
-
};
|
|
264
|
-
|
|
265
|
-
return <Input value={value} onChange={(e) => handleChange(e.target.value)} />;
|
|
91
|
+
title: 'Personal details',
|
|
92
|
+
required: ['name'],
|
|
93
|
+
properties: { name: { type: 'string', minLength: 1 } },
|
|
94
|
+
},
|
|
95
|
+
STEP_CONTACT: {
|
|
96
|
+
type: 'object',
|
|
97
|
+
title: 'Contact details',
|
|
98
|
+
properties: { email: { type: 'string', format: 'email' } },
|
|
99
|
+
},
|
|
100
|
+
},
|
|
266
101
|
};
|
|
267
|
-
```
|
|
268
|
-
|
|
269
|
-
### Auto-registered by Default
|
|
270
|
-
- All EDF custom widgets are included by default; no wiring is required.
|
|
271
|
-
- Every widget is also exposed as a field, so you can use either `ui:widget` or `ui:field` with the same key.
|
|
272
|
-
|
|
273
|
-
Examples:
|
|
274
|
-
|
|
275
|
-
```json
|
|
276
|
-
{
|
|
277
|
-
"schema": { "type": "string", "title": "First Name" },
|
|
278
|
-
"uiSchema": { "ui:widget": "text" }
|
|
279
|
-
}
|
|
280
|
-
```
|
|
281
102
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
103
|
+
export default function RegistrationForm() {
|
|
104
|
+
return (
|
|
105
|
+
<WizardForm
|
|
106
|
+
schema={schema}
|
|
107
|
+
uiSchema={{}}
|
|
108
|
+
onStepChange={(stepIndex, data, stepId) => {
|
|
109
|
+
console.log('Current step', stepIndex, stepId, data);
|
|
110
|
+
}}
|
|
111
|
+
onLiveChange={(flatData) => console.log('Current answers', flatData)}
|
|
112
|
+
onSubmit={({ formData, flatFormData }) => {
|
|
113
|
+
console.log('Accepted step answers', formData);
|
|
114
|
+
console.log('Accepted flat answers', flatFormData);
|
|
115
|
+
}}
|
|
116
|
+
/>
|
|
117
|
+
);
|
|
286
118
|
}
|
|
287
119
|
```
|
|
288
120
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
```typescript
|
|
294
|
-
// Equality
|
|
295
|
-
// Before: (formData) => formData.field === "value"
|
|
296
|
-
// After: { "==": [{ "var": "field" }, "value"] }
|
|
297
|
-
|
|
298
|
-
// Boolean check
|
|
299
|
-
// Before: (formData) => formData.isEnabled
|
|
300
|
-
// After: { "var": "isEnabled" }
|
|
301
|
-
|
|
302
|
-
// AND condition
|
|
303
|
-
// Before: (formData) => formData.a && formData.b
|
|
304
|
-
// After: { "and": [{ "var": "a" }, { "var": "b" }] }
|
|
305
|
-
|
|
306
|
-
// Array contains
|
|
307
|
-
// Before: (formData) => formData.roles?.includes("admin")
|
|
308
|
-
// After: { "in": ["admin", { "var": "roles" }] }
|
|
309
|
-
```
|
|
310
|
-
|
|
311
|
-
## Available Widgets
|
|
312
|
-
|
|
313
|
-
### Complete Widget List
|
|
314
|
-
|
|
315
|
-
#### Choice Widget (Unified Selection)
|
|
316
|
-
- **ChoiceWidget** - Intelligent widget that automatically adapts based on schema:
|
|
317
|
-
- Renders as dropdown/select for regular choices
|
|
318
|
-
- Renders as radio group when `ui:widget` is "radio"
|
|
319
|
-
- Renders as checkbox group for multi-select arrays
|
|
320
|
-
- Supports static and dynamic data sources (API, WebSocket)
|
|
321
|
-
|
|
322
|
-
#### Text Input Widgets
|
|
323
|
-
- **TextWidget** - Standard text input with Ant Design styling
|
|
324
|
-
- **TextareaWidget** - Multi-line text input
|
|
325
|
-
- **PasswordWidget** - Password input with visibility toggle
|
|
121
|
+
Conditions use flat answer paths without the `STEP_` prefix. Initial answers may
|
|
122
|
+
be flat or nested under step keys; explicit nested snapshots take precedence.
|
|
123
|
+
Use distinct answer keys across steps when working with flat data.
|
|
326
124
|
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
-
|
|
331
|
-
|
|
332
|
-
|
|
125
|
+
Step visibility rules use `x-edf:stepRules`. Hidden steps are skipped in navigation
|
|
126
|
+
and excluded from structured submissions unless `includeHiddenStepsInSubmit` is
|
|
127
|
+
true; `flatFormData` retains the all-step context. `onStepChange` reports the
|
|
128
|
+
visible-step index; `onStepChangeDetailed` also includes the original index as
|
|
129
|
+
`allStepsIndex`. The last visible step can submit, and final submission validates
|
|
130
|
+
all visible steps, including an earlier step newly revealed by a later answer.
|
|
333
131
|
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
132
|
+
Array positions and blank array entries are preserved through editing and
|
|
133
|
+
navigation. Supplied strings with directly declared `pattern`, positive
|
|
134
|
+
`minLength`, or a valid explicit `maxLength` retain their characters for
|
|
135
|
+
validation. Other nested/edit blank-string normalization remains in place.
|
|
136
|
+
JSON Schema `required` checks presence. A positive `minLength` rejects an empty
|
|
137
|
+
string; rejecting whitespace-only answers requires an appropriate non-whitespace
|
|
138
|
+
`pattern`. Malformed schema patterns block progression and show configuration
|
|
139
|
+
errors by default; hiding the error list does not bypass validation.
|
|
337
140
|
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
141
|
+
`LayoutGridField` is included for step layouts. Configure `ui:field` as
|
|
142
|
+
`LayoutGridField` and use `ui:layoutGrid` with Ant Design's 24-column spans and
|
|
143
|
+
gutters. Custom fields and templates remain overridable.
|
|
341
144
|
|
|
342
|
-
|
|
343
|
-
- **FileWidget** - Basic file input
|
|
344
|
-
- **FileUploadWidget** - Enhanced upload with progress, preview, and base64 support
|
|
145
|
+
## Conditional logic
|
|
345
146
|
|
|
346
|
-
|
|
147
|
+
Put JsonLogic conditions and JSON Patch effects in `x-edf:rules` on the schema
|
|
148
|
+
or UI schema. Configuration is JSON-only; JavaScript source strings are not
|
|
149
|
+
executed.
|
|
347
150
|
|
|
348
|
-
|
|
349
|
-
```json
|
|
350
|
-
{
|
|
351
|
-
"schema": {
|
|
352
|
-
"type": "string",
|
|
353
|
-
"title": "Full Name"
|
|
354
|
-
},
|
|
355
|
-
"uiSchema": {
|
|
356
|
-
"ui:widget": "text",
|
|
357
|
-
"ui:placeholder": "Enter your full name"
|
|
358
|
-
}
|
|
359
|
-
}
|
|
360
|
-
```
|
|
361
|
-
|
|
362
|
-
#### Text Input with Variant and Auto-complete
|
|
363
|
-
```json
|
|
364
|
-
{
|
|
365
|
-
"schema": { "type": "string", "title": "Username" },
|
|
366
|
-
"uiSchema": {
|
|
367
|
-
"ui:widget": "text",
|
|
368
|
-
"ui:options": {
|
|
369
|
-
"variant": "outlined",
|
|
370
|
-
"autoFocus": true,
|
|
371
|
-
"autoComplete": "username",
|
|
372
|
-
"allowClear": true
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
```
|
|
377
|
-
|
|
378
|
-
#### Date Range (RangePicker)
|
|
379
|
-
```json
|
|
380
|
-
{
|
|
381
|
-
"schema": {
|
|
382
|
-
"type": "array",
|
|
383
|
-
"title": "Date Range",
|
|
384
|
-
"items": { "type": "string" },
|
|
385
|
-
"minItems": 2,
|
|
386
|
-
"maxItems": 2
|
|
387
|
-
},
|
|
388
|
-
"uiSchema": {
|
|
389
|
-
"ui:widget": "date",
|
|
390
|
-
"ui:options": {
|
|
391
|
-
"range": true,
|
|
392
|
-
"format": "YYYY-MM-DD",
|
|
393
|
-
"placeholder": ["Start date", "End date"],
|
|
394
|
-
"picker": "date"
|
|
395
|
-
}
|
|
396
|
-
}
|
|
397
|
-
}
|
|
398
|
-
```
|
|
399
|
-
|
|
400
|
-
With time selection:
|
|
401
|
-
```json
|
|
402
|
-
{
|
|
403
|
-
"schema": {
|
|
404
|
-
"type": "array",
|
|
405
|
-
"title": "Date Range With Time",
|
|
406
|
-
"items": { "type": "string" },
|
|
407
|
-
"minItems": 2,
|
|
408
|
-
"maxItems": 2
|
|
409
|
-
},
|
|
410
|
-
"uiSchema": {
|
|
411
|
-
"ui:widget": "date",
|
|
412
|
-
"ui:options": {
|
|
413
|
-
"range": true,
|
|
414
|
-
"showTime": true,
|
|
415
|
-
"format": "YYYY-MM-DD HH:mm",
|
|
416
|
-
"placeholder": ["Start date/time", "End date/time"]
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
```
|
|
151
|
+
For example, this schema rule adds a property when `accountType` is `premium`:
|
|
421
152
|
|
|
422
|
-
Month range:
|
|
423
153
|
```json
|
|
424
154
|
{
|
|
425
|
-
"
|
|
426
|
-
|
|
427
|
-
"
|
|
428
|
-
"items": { "type": "string" },
|
|
429
|
-
"minItems": 2,
|
|
430
|
-
"maxItems": 2
|
|
155
|
+
"type": "object",
|
|
156
|
+
"properties": {
|
|
157
|
+
"accountType": { "type": "string", "enum": ["basic", "premium"] }
|
|
431
158
|
},
|
|
432
|
-
"
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
"
|
|
436
|
-
"
|
|
437
|
-
|
|
438
|
-
|
|
159
|
+
"x-edf:rules": [
|
|
160
|
+
{
|
|
161
|
+
"name": "Premium details",
|
|
162
|
+
"condition": { "==": [{ "var": "accountType" }, "premium"] },
|
|
163
|
+
"effect": [
|
|
164
|
+
{ "op": "add", "path": "/properties/premiumFeatures", "value": { "type": "string" } }
|
|
165
|
+
]
|
|
439
166
|
}
|
|
440
|
-
|
|
167
|
+
]
|
|
441
168
|
}
|
|
442
169
|
```
|
|
443
170
|
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
"type": "number",
|
|
449
|
-
"title": "Age",
|
|
450
|
-
"minimum": 0,
|
|
451
|
-
"maximum": 120
|
|
452
|
-
},
|
|
453
|
-
"uiSchema": {
|
|
454
|
-
"ui:widget": "number"
|
|
455
|
-
}
|
|
456
|
-
}
|
|
457
|
-
```
|
|
171
|
+
UI rules belong in `uiSchema['x-edf:rules']`; schema rules belong in
|
|
172
|
+
`schema['x-edf:rules']`. Array-item presentation can use `ui:dynamicItems` with
|
|
173
|
+
per-item JsonLogic. Conditional requiredness changes validation, not just a
|
|
174
|
+
visual required marker.
|
|
458
175
|
|
|
459
|
-
|
|
460
|
-
```json
|
|
461
|
-
{
|
|
462
|
-
"schema": {
|
|
463
|
-
"type": "number",
|
|
464
|
-
"title": "Rate your experience",
|
|
465
|
-
"minimum": 0,
|
|
466
|
-
"maximum": 5
|
|
467
|
-
},
|
|
468
|
-
"uiSchema": {
|
|
469
|
-
"ui:widget": "rating",
|
|
470
|
-
"ui:options": {
|
|
471
|
-
"count": 5,
|
|
472
|
-
"allowHalf": true
|
|
473
|
-
}
|
|
474
|
-
}
|
|
475
|
-
}
|
|
476
|
-
```
|
|
176
|
+
## Widgets and options
|
|
477
177
|
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
{
|
|
481
|
-
"schema": {
|
|
482
|
-
"type": "string",
|
|
483
|
-
"title": "Country",
|
|
484
|
-
"enum": ["us", "uk", "au", "ca"],
|
|
485
|
-
"enumNames": ["United States", "United Kingdom", "Australia", "Canada"]
|
|
486
|
-
},
|
|
487
|
-
"uiSchema": {
|
|
488
|
-
"ui:widget": "choice"
|
|
489
|
-
}
|
|
490
|
-
}
|
|
491
|
-
```
|
|
178
|
+
Select a registered widget using `ui:widget`. The same registered key can also
|
|
179
|
+
be used as `ui:field`; an explicit field override controls its own rendering.
|
|
492
180
|
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
{ "label": "USA", "value": "us" }, { "label": "UK", "value": "uk" }
|
|
504
|
-
]},
|
|
505
|
-
"antd": { "select": { "dropdownMatchSelectWidth": 280, "placement": "bottomLeft" } }
|
|
506
|
-
}
|
|
507
|
-
}
|
|
508
|
-
}
|
|
509
|
-
}
|
|
510
|
-
```
|
|
181
|
+
| Input | Registered keys |
|
|
182
|
+
| --- | --- |
|
|
183
|
+
| Text | `text`, `textarea`, `password` |
|
|
184
|
+
| Email, URL and phone | `email`, `url`, `tel`, `telephone` |
|
|
185
|
+
| Number | `number`, `updown` |
|
|
186
|
+
| Choices | `choice` with dropdown, radio or checkbox presentation |
|
|
187
|
+
| Date and time | `date`, `time`, `datetime-local` |
|
|
188
|
+
| Visual inputs | `color`, `range`, `slider`, `rating`, `switch` |
|
|
189
|
+
| Files | `file`, `fileUpload` |
|
|
190
|
+
| Display | `title`, `heading`, `html`, `markdown`, `image`, `alert`, `spacer`, `divider` |
|
|
511
191
|
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
"type": "string",
|
|
517
|
-
"title": "Gender",
|
|
518
|
-
"enum": ["male", "female", "other"]
|
|
519
|
-
},
|
|
520
|
-
"uiSchema": {
|
|
521
|
-
"ui:widget": "choice",
|
|
522
|
-
"ui:options": {
|
|
523
|
-
"presenter": "radio"
|
|
524
|
-
}
|
|
525
|
-
}
|
|
526
|
-
}
|
|
527
|
-
```
|
|
192
|
+
Configure supported Ant Design props in `ui:options`. Container options belong
|
|
193
|
+
in `ui:options.formItem`; input styling and container styling are separate.
|
|
194
|
+
For the unified choice widget, use `ui:options.choiceConfig` for data sources,
|
|
195
|
+
presentation and presenter-specific Ant Design options.
|
|
528
196
|
|
|
529
|
-
#### Choice Widget (Checkbox Group - Multi-select)
|
|
530
197
|
```json
|
|
531
198
|
{
|
|
532
|
-
"
|
|
533
|
-
"
|
|
534
|
-
"title": "Interests",
|
|
535
|
-
"items": {
|
|
536
|
-
"type": "string",
|
|
537
|
-
"enum": ["sports", "music", "reading", "travel"]
|
|
538
|
-
},
|
|
539
|
-
"uniqueItems": true
|
|
540
|
-
},
|
|
541
|
-
"uiSchema": {
|
|
542
|
-
"ui:widget": "choice",
|
|
199
|
+
"name": {
|
|
200
|
+
"ui:widget": "text",
|
|
543
201
|
"ui:options": {
|
|
544
|
-
"
|
|
202
|
+
"allowClear": true,
|
|
203
|
+
"autoComplete": "name",
|
|
204
|
+
"variant": "outlined",
|
|
205
|
+
"style": { "fontSize": 18 },
|
|
206
|
+
"formItem": { "style": { "marginBottom": 24 } }
|
|
545
207
|
}
|
|
546
|
-
}
|
|
547
|
-
}
|
|
548
|
-
```
|
|
549
|
-
|
|
550
|
-
#### Date Picker
|
|
551
|
-
```json
|
|
552
|
-
{
|
|
553
|
-
"schema": {
|
|
554
|
-
"type": "string",
|
|
555
|
-
"title": "Date of Birth",
|
|
556
|
-
"format": "date"
|
|
557
208
|
},
|
|
558
|
-
"
|
|
209
|
+
"birthday": {
|
|
559
210
|
"ui:widget": "date",
|
|
560
|
-
"ui:options": {
|
|
561
|
-
"format": "DD/MM/YYYY",
|
|
562
|
-
"picker": "date"
|
|
563
|
-
}
|
|
564
|
-
}
|
|
565
|
-
}
|
|
566
|
-
```
|
|
567
|
-
|
|
568
|
-
#### File Upload
|
|
569
|
-
```json
|
|
570
|
-
{
|
|
571
|
-
"schema": {
|
|
572
|
-
"type": "string",
|
|
573
|
-
"title": "Resume",
|
|
574
|
-
"format": "data-url"
|
|
575
|
-
},
|
|
576
|
-
"uiSchema": {
|
|
577
|
-
"ui:widget": "fileUpload",
|
|
578
|
-
"ui:options": {
|
|
579
|
-
"accept": ".pdf,.doc,.docx",
|
|
580
|
-
"maxSize": 5242880,
|
|
581
|
-
"multiple": false
|
|
582
|
-
}
|
|
583
|
-
}
|
|
584
|
-
}
|
|
585
|
-
```
|
|
586
|
-
|
|
587
|
-
#### File Upload (Ant Upload options)
|
|
588
|
-
```json
|
|
589
|
-
{
|
|
590
|
-
"schema": { "type": "string", "title": "Profile Picture" },
|
|
591
|
-
"uiSchema": {
|
|
592
|
-
"ui:widget": "fileUpload",
|
|
593
|
-
"ui:options": {
|
|
594
|
-
"useAntUpload": true,
|
|
595
|
-
"listType": "picture-card",
|
|
596
|
-
"showUploadList": { "showPreviewIcon": true, "showRemoveIcon": true },
|
|
597
|
-
"maxCount": 1,
|
|
598
|
-
"accept": "image/*"
|
|
599
|
-
}
|
|
600
|
-
}
|
|
601
|
-
}
|
|
602
|
-
```
|
|
603
|
-
|
|
604
|
-
#### Color Picker
|
|
605
|
-
```json
|
|
606
|
-
{
|
|
607
|
-
"schema": {
|
|
608
|
-
"type": "string",
|
|
609
|
-
"title": "Favorite Color",
|
|
610
|
-
"format": "color"
|
|
611
|
-
},
|
|
612
|
-
"uiSchema": {
|
|
613
|
-
"ui:widget": "color"
|
|
614
|
-
}
|
|
615
|
-
}
|
|
616
|
-
```
|
|
617
|
-
|
|
618
|
-
#### Range/Slider Widget
|
|
619
|
-
```json
|
|
620
|
-
{
|
|
621
|
-
"schema": {
|
|
622
|
-
"type": "number",
|
|
623
|
-
"title": "Volume",
|
|
624
|
-
"minimum": 0,
|
|
625
|
-
"maximum": 100
|
|
626
|
-
},
|
|
627
|
-
"uiSchema": {
|
|
628
|
-
"ui:widget": "range",
|
|
629
|
-
"ui:options": {
|
|
630
|
-
"marks": {
|
|
631
|
-
"0": "Mute",
|
|
632
|
-
"50": "50%",
|
|
633
|
-
"100": "Max"
|
|
634
|
-
}
|
|
635
|
-
}
|
|
636
|
-
}
|
|
637
|
-
}
|
|
638
|
-
```
|
|
639
|
-
|
|
640
|
-
#### Hidden Field
|
|
641
|
-
```json
|
|
642
|
-
{
|
|
643
|
-
"schema": {
|
|
644
|
-
"type": "string",
|
|
645
|
-
"title": "User ID"
|
|
211
|
+
"ui:options": { "format": "DD/MM/YYYY", "disableFutureDates": true }
|
|
646
212
|
},
|
|
647
|
-
"
|
|
648
|
-
"ui:widget": "
|
|
213
|
+
"score": {
|
|
214
|
+
"ui:widget": "rating",
|
|
215
|
+
"ui:options": { "count": 5, "allowHalf": true }
|
|
649
216
|
}
|
|
650
217
|
}
|
|
651
218
|
```
|
|
652
219
|
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
220
|
+
- Choices can use schema enums or configured static/remote data sources. Single
|
|
221
|
+
choices emit scalars; multiple choices emit arrays. Remote paging is not implemented.
|
|
222
|
+
- Date options include `disablePastDates`, `disableFutureDates`,
|
|
223
|
+
`disableWeekends` and `range: true` for a range picker.
|
|
224
|
+
- Number options include `min`, `max`, `step`, `precision`, `groupSeparator`,
|
|
225
|
+
`decimalSeparator`, `controls`, `keyboard` and `changeOnWheel`. Display grouping
|
|
226
|
+
does not become part of numeric answers. Schema bounds validate independently
|
|
227
|
+
of input clamping.
|
|
228
|
+
- Exact decimals require `stringMode: true` with a string schema and suitable
|
|
229
|
+
string/decimal-aware validation. Numeric schemas convert values to JavaScript
|
|
230
|
+
numbers; numeric JSON Schema bounds do not validate decimal strings.
|
|
231
|
+
- Telephone `mask` uses `9` for a digit, `a` for an ASCII letter and `*` for any
|
|
232
|
+
character. Mask literals affect display, while answers retain digits and an
|
|
233
|
+
optional leading `+`. `useCountryMasks: true` enables country-pattern fallback;
|
|
234
|
+
an explicit field mask takes precedence. Letter slots are display-only.
|
|
235
|
+
- URL answers accept HTTP/HTTPS by default. `allowedProtocols` replaces those
|
|
236
|
+
defaults; `[]` rejects every nonempty URL. `javascript:`, `data:` and `vbscript:`
|
|
237
|
+
remain blocked even if listed. Link previews are restricted to HTTP/HTTPS.
|
|
238
|
+
- File upload options include `accept`, `maxSize`, `multiple` and Ant Upload
|
|
239
|
+
presentation controls. Use a schema compatible with the selected value mode.
|
|
240
|
+
|
|
241
|
+
Choice presenter-specific Ant Design options use `choiceConfig.antd`, such as
|
|
242
|
+
`choiceConfig.antd.select` for dropdown props.
|
|
243
|
+
|
|
244
|
+
## Values and validation
|
|
245
|
+
|
|
246
|
+
### Empty answers
|
|
247
|
+
|
|
248
|
+
The built-in Text widget emits `undefined` when cleared by default. Object
|
|
249
|
+
properties are omitted when serialized to JSON, including properties in array
|
|
250
|
+
items; callbacks may still contain undefined-valued own properties. Array rows
|
|
251
|
+
are not deleted or compacted. An explicit `emptyValue`, including `""` or `null`,
|
|
252
|
+
is an override and must satisfy the schema. Password, Textarea and other widget
|
|
253
|
+
empty defaults are not globally changed. Custom fields/widgets control their
|
|
254
|
+
own child-change behavior.
|
|
255
|
+
|
|
256
|
+
Stored/default answers are not rewritten on load. Turning off interaction
|
|
257
|
+
feedback does not disable Submit or Wizard Next validation. Change callbacks
|
|
258
|
+
can contain incomplete or invalid drafts; only accepted submissions should be
|
|
259
|
+
stored as completed responses.
|
|
260
|
+
|
|
261
|
+
### Date and time answers
|
|
262
|
+
|
|
263
|
+
| Widget/schema | Accepted answer |
|
|
264
|
+
| --- | --- |
|
|
265
|
+
| Single Date with `format: "date"` | Calendar day, `YYYY-MM-DD` |
|
|
266
|
+
| Time with `format: "time"` | Wall-clock time, `HH:mm:ss`, without timezone conversion |
|
|
267
|
+
| DateTime | UTC ISO instant with `Z`, displayed in the respondent's browser-local timezone |
|
|
268
|
+
| Calendar Date Range (`date` with `range: true`) | Pair of ISO calendar days, even with plain string item schemas |
|
|
269
|
+
|
|
270
|
+
Date/Time display formats do not change those schema-formatted answers. Native
|
|
271
|
+
Date/Time string schemas without their respective `format` retain configured-format
|
|
272
|
+
output. Explicit `showTime` / `withTime` ranges retain formatted time-bearing
|
|
273
|
+
pairs rather than the UTC DateTime contract.
|
|
274
|
+
|
|
275
|
+
DateTime rejects nonexistent daylight-saving times and requires an explicit
|
|
276
|
+
occurrence choice for repeated local times. Restored valid offset-bearing instants
|
|
277
|
+
and fractional-second precision are preserved until edited. Zone-less or invalid
|
|
278
|
+
saved DateTime strings require re-entry; no timezone is guessed. Pending invalid
|
|
279
|
+
edits block submission and wizard progression, even on optional fields, and can
|
|
280
|
+
emit the `Invalid date-time` draft marker. DateTime clear emits `undefined`
|
|
281
|
+
regardless of an old `emptyValue` setting.
|
|
282
|
+
|
|
283
|
+
Calendar ranges reject impossible, reversed and incomplete pairs. Clear emits
|
|
284
|
+
`[]`; optional schemas must allow zero items if clear should be valid. Required
|
|
285
|
+
ranges reject `[]`. Explicit `allowEmpty` endpoint options also need schemas
|
|
286
|
+
that permit an empty string at that endpoint. Calendar bounds compare local days;
|
|
287
|
+
an explicit `disabledDate` callback takes precedence over convenience flags,
|
|
288
|
+
while explicit bounds still apply.
|
|
289
|
+
|
|
290
|
+
When upgrading from 0.3.x, review the date/time, empty-answer and URL contracts
|
|
291
|
+
against your schemas, callbacks and stored responses. Do not rewrite persisted
|
|
292
|
+
or in-progress answers automatically. See the changelog for version-specific changes.
|
|
293
|
+
|
|
294
|
+
## Events and webhooks
|
|
295
|
+
|
|
296
|
+
`ExtendedForm` delivers `onFieldFocus`, `onFieldBlur` and `onFieldChange` events
|
|
297
|
+
with `fieldId` and `fieldValue`. `WizardForm` currently does not deliver those
|
|
298
|
+
field callback props; use `onLiveChange` to subscribe to wizard answer snapshots.
|
|
299
|
+
Use `onSubmit` for accepted form answers. Optional `webhooks` configure event
|
|
300
|
+
destinations, event names, debounce timing and retries. Keep endpoint authorization
|
|
301
|
+
and response-storage policy in your host application.
|
|
302
|
+
|
|
303
|
+
Custom widgets can import `useFieldEventHandlers` from the root package alongside
|
|
304
|
+
other event exports. Call the RJSF `onChange` to update the answer and the field
|
|
305
|
+
event handler to participate in EDF events.
|
|
306
|
+
|
|
307
|
+
## Known limitations
|
|
308
|
+
|
|
309
|
+
- CommonJS `require` is unsupported; use ESM imports. NodeNext declaration
|
|
310
|
+
compatibility is not established; use the ESNext/Bundler configuration above.
|
|
311
|
+
- The separate vanilla JavaScript build lacks JsonLogic support. Use the React
|
|
312
|
+
package for declarative conditional forms.
|
|
313
|
+
- Arrays do not support drag-and-drop.
|
|
314
|
+
- JSON Patch effects support `add`, `remove` and `replace` only, not `move`, `copy` or `test`.
|
|
315
|
+
|
|
316
|
+
## Links and license
|
|
317
|
+
|
|
318
|
+
- [npm package](https://www.npmjs.com/package/extended-dynamic-forms)
|
|
319
|
+
|
|
320
|
+
MIT. See [LICENSE](LICENSE).
|