extended-dynamic-forms 0.3.6 → 0.3.8
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 +179 -70
- package/dist/icons/LucideIcon.d.ts +11 -0
- package/dist/index.es.js +43450 -14219
- package/dist/index.umd.js +7750 -55
- package/dist/widgets/base/types.d.ts +164 -0
- package/dist/widgets/base/utils.d.ts +36 -1
- package/dist/widgets/choice/ChoiceWidget.types.d.ts +20 -0
- package/dist/widgets/date/TimeWidget.d.ts +9 -0
- package/dist/widgets/date/dayjsSetup.d.ts +3 -0
- package/dist/widgets/date/index.d.ts +1 -0
- package/dist/widgets/index.d.ts +10 -0
- package/dist/widgets/input/AlertWidget.d.ts +10 -0
- package/dist/widgets/input/ImageWidget.d.ts +10 -0
- package/dist/widgets/input/SwitchWidget.d.ts +9 -0
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# Extended Dynamic Forms
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## Declarative Configuration (JSON-only)
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Conditional logic is configured with pure JSON via `x-edf:rules` in your `schema` and `uiSchema`. Function-based conditions and external hooks are not required and should not be used in app code.
|
|
6
6
|
|
|
7
7
|
## Project Status
|
|
8
8
|
|
|
@@ -18,12 +18,20 @@ All conditional logic now uses **JsonLogic rules only** for conditions. Function
|
|
|
18
18
|
|
|
19
19
|
Extended Dynamic Forms is an extension library for React JSON Schema Form (RJSF) v6 that adds:
|
|
20
20
|
|
|
21
|
-
- **
|
|
21
|
+
- **Declarative conditionals** with O(N) performance (rules + dynamic arrays)
|
|
22
22
|
- **Multi-step wizard forms** with automatic step detection
|
|
23
23
|
- **Central event orchestration** with webhook support
|
|
24
24
|
- **25+ Ant Design components** for professional UI
|
|
25
25
|
- **TypeScript-first** development with full type safety
|
|
26
26
|
|
|
27
|
+
### Ant Design Prop Pass-through
|
|
28
|
+
|
|
29
|
+
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.
|
|
30
|
+
|
|
31
|
+
- DatePicker notes:
|
|
32
|
+
- JSON-only flags: `disablePastDates`, `disableFutureDates`, `disableWeekends` (builds `disabledDate` internally)
|
|
33
|
+
- Range support: set `ui:options.range: true` to render AntD `RangePicker` (see examples below)
|
|
34
|
+
|
|
27
35
|
## Installation
|
|
28
36
|
|
|
29
37
|
**Note:** This library currently requires local development setup and cannot be installed via npm due to local file dependencies.
|
|
@@ -43,71 +51,62 @@ npm run dev
|
|
|
43
51
|
|
|
44
52
|
## Core Architecture
|
|
45
53
|
|
|
46
|
-
###
|
|
54
|
+
### Declarative Conditionals (JSON-only)
|
|
47
55
|
|
|
48
|
-
|
|
56
|
+
Embed rules directly inside your configs. EDF evaluates JsonLogic `condition` and applies JSON Patch `effect` internally. No hooks, functions, or classes in user code.
|
|
49
57
|
|
|
50
|
-
|
|
51
|
-
|
|
58
|
+
- UI rules → `uiSchema['x-edf:rules']`
|
|
59
|
+
- Schema rules → `schema['x-edf:rules']`
|
|
52
60
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
}]
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
#### 2. Schema Logic Pillar
|
|
66
|
-
Modifies JSON Schema structure dynamically (use sparingly):
|
|
67
|
-
|
|
68
|
-
```typescript
|
|
69
|
-
const schemaRules: SchemaRule[] = [{
|
|
70
|
-
name: 'Add premium fields',
|
|
71
|
-
condition: { "==": [{ "var": "accountType" }, "premium"] },
|
|
72
|
-
effect: [{ op: 'add', path: '/properties/premiumFeatures', value: {...} }]
|
|
73
|
-
}];
|
|
61
|
+
Example (UI rules):
|
|
62
|
+
```json
|
|
63
|
+
{
|
|
64
|
+
"x-edf:rules": [
|
|
65
|
+
{
|
|
66
|
+
"name": "Show license number when has license",
|
|
67
|
+
"condition": { "==": [{ "var": "hasDriversLicense" }, true] },
|
|
68
|
+
"effect": [{ "op": "remove", "path": "/licenseNumber/ui:widget" }]
|
|
69
|
+
}
|
|
70
|
+
]
|
|
71
|
+
}
|
|
74
72
|
```
|
|
75
73
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
validate: (errors, formData) => {
|
|
87
|
-
if (!formData.parentConsent) {
|
|
88
|
-
errors.parentConsent.__errors = ['Parent consent required'];
|
|
89
|
-
}
|
|
74
|
+
Example (Schema rules):
|
|
75
|
+
```json
|
|
76
|
+
{
|
|
77
|
+
"x-edf:rules": [
|
|
78
|
+
{
|
|
79
|
+
"name": "Add premium fields",
|
|
80
|
+
"condition": { "==": [{ "var": "accountType" }, "premium"] },
|
|
81
|
+
"effect": [
|
|
82
|
+
{ "op": "add", "path": "/properties/premiumFeatures", "value": { "type": "object" } }
|
|
83
|
+
]
|
|
90
84
|
}
|
|
91
|
-
|
|
92
|
-
}
|
|
85
|
+
]
|
|
86
|
+
}
|
|
93
87
|
```
|
|
94
88
|
|
|
95
89
|
### Dynamic Arrays with O(N) Performance
|
|
96
90
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
```typescript
|
|
100
|
-
import { createDynamicArrayItemsUiSchema } from 'extended-dynamic-forms/conditionals/v2';
|
|
91
|
+
Use declarative `ui:dynamicItems` with per-item JsonLogic. No functions:
|
|
101
92
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
93
|
+
```json
|
|
94
|
+
{
|
|
95
|
+
"directors": {
|
|
96
|
+
"items": {
|
|
97
|
+
"ui:dynamicItems": {
|
|
98
|
+
"base": { "shareholdingPercentage": { "ui:widget": "hidden" } },
|
|
99
|
+
"rules": [
|
|
100
|
+
{
|
|
101
|
+
"condition": { "===": [{ "var": "hasShareholding" }, true] },
|
|
102
|
+
"ui": { "shareholdingPercentage": { "ui:widget": "updown" } },
|
|
103
|
+
"otherwise": { "shareholdingPercentage": { "ui:widget": "hidden" } }
|
|
104
|
+
}
|
|
105
|
+
]
|
|
107
106
|
}
|
|
108
|
-
}
|
|
107
|
+
}
|
|
109
108
|
}
|
|
110
|
-
}
|
|
109
|
+
}
|
|
111
110
|
```
|
|
112
111
|
|
|
113
112
|
## Multi-Step Wizard Forms
|
|
@@ -119,7 +118,7 @@ import { WizardForm } from 'extended-dynamic-forms';
|
|
|
119
118
|
|
|
120
119
|
<WizardForm
|
|
121
120
|
schema={wizardSchema}
|
|
122
|
-
uiSchema={
|
|
121
|
+
uiSchema={uiSchema}
|
|
123
122
|
formData={formData}
|
|
124
123
|
onStepChange={(fromStep, toStep) => {
|
|
125
124
|
console.log(`Step ${fromStep} → ${toStep}`);
|
|
@@ -141,8 +140,8 @@ const schema = {
|
|
|
141
140
|
}
|
|
142
141
|
};
|
|
143
142
|
|
|
144
|
-
// Conditions
|
|
145
|
-
|
|
143
|
+
// Conditions refer to flattened form data (no STEP_ prefix)
|
|
144
|
+
// Example rule (in uiSchema.x-edf:rules): { "==": [{ "var": "hasDriversLicense" }, true] }
|
|
146
145
|
```
|
|
147
146
|
|
|
148
147
|
Note on wizard detection:
|
|
@@ -345,6 +344,88 @@ Common patterns for migrating from function-based conditions:
|
|
|
345
344
|
}
|
|
346
345
|
```
|
|
347
346
|
|
|
347
|
+
#### Text Input with Variant and Auto-complete
|
|
348
|
+
```json
|
|
349
|
+
{
|
|
350
|
+
"schema": { "type": "string", "title": "Username" },
|
|
351
|
+
"uiSchema": {
|
|
352
|
+
"ui:widget": "text",
|
|
353
|
+
"ui:options": {
|
|
354
|
+
"variant": "outlined",
|
|
355
|
+
"autoFocus": true,
|
|
356
|
+
"autoComplete": "username",
|
|
357
|
+
"allowClear": true
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
#### Date Range (RangePicker)
|
|
364
|
+
```json
|
|
365
|
+
{
|
|
366
|
+
"schema": {
|
|
367
|
+
"type": "array",
|
|
368
|
+
"title": "Date Range",
|
|
369
|
+
"items": { "type": "string" },
|
|
370
|
+
"minItems": 2,
|
|
371
|
+
"maxItems": 2
|
|
372
|
+
},
|
|
373
|
+
"uiSchema": {
|
|
374
|
+
"ui:widget": "date",
|
|
375
|
+
"ui:options": {
|
|
376
|
+
"range": true,
|
|
377
|
+
"format": "YYYY-MM-DD",
|
|
378
|
+
"placeholder": ["Start date", "End date"],
|
|
379
|
+
"picker": "date"
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
With time selection:
|
|
386
|
+
```json
|
|
387
|
+
{
|
|
388
|
+
"schema": {
|
|
389
|
+
"type": "array",
|
|
390
|
+
"title": "Date Range With Time",
|
|
391
|
+
"items": { "type": "string" },
|
|
392
|
+
"minItems": 2,
|
|
393
|
+
"maxItems": 2
|
|
394
|
+
},
|
|
395
|
+
"uiSchema": {
|
|
396
|
+
"ui:widget": "date",
|
|
397
|
+
"ui:options": {
|
|
398
|
+
"range": true,
|
|
399
|
+
"showTime": true,
|
|
400
|
+
"format": "YYYY-MM-DD HH:mm",
|
|
401
|
+
"placeholder": ["Start date/time", "End date/time"]
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
Month range:
|
|
408
|
+
```json
|
|
409
|
+
{
|
|
410
|
+
"schema": {
|
|
411
|
+
"type": "array",
|
|
412
|
+
"title": "Month Range",
|
|
413
|
+
"items": { "type": "string" },
|
|
414
|
+
"minItems": 2,
|
|
415
|
+
"maxItems": 2
|
|
416
|
+
},
|
|
417
|
+
"uiSchema": {
|
|
418
|
+
"ui:widget": "date",
|
|
419
|
+
"ui:options": {
|
|
420
|
+
"range": true,
|
|
421
|
+
"picker": "month",
|
|
422
|
+
"format": "YYYY-MM",
|
|
423
|
+
"placeholder": ["Start month", "End month"]
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
```
|
|
428
|
+
|
|
348
429
|
#### Number Input with Range
|
|
349
430
|
```json
|
|
350
431
|
{
|
|
@@ -394,6 +475,25 @@ Common patterns for migrating from function-based conditions:
|
|
|
394
475
|
}
|
|
395
476
|
```
|
|
396
477
|
|
|
478
|
+
#### Choice Widget with AntD props (Dropdown)
|
|
479
|
+
```json
|
|
480
|
+
{
|
|
481
|
+
"schema": { "type": "string", "title": "Country" },
|
|
482
|
+
"uiSchema": {
|
|
483
|
+
"ui:widget": "choice",
|
|
484
|
+
"ui:options": {
|
|
485
|
+
"choiceConfig": {
|
|
486
|
+
"presentationMode": "dropdown",
|
|
487
|
+
"dataSource": { "type": "static", "options": [
|
|
488
|
+
{ "label": "USA", "value": "us" }, { "label": "UK", "value": "uk" }
|
|
489
|
+
]},
|
|
490
|
+
"antd": { "select": { "dropdownMatchSelectWidth": 280, "placement": "bottomLeft" } }
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
```
|
|
496
|
+
|
|
397
497
|
#### Choice Widget (Radio Group)
|
|
398
498
|
```json
|
|
399
499
|
{
|
|
@@ -459,7 +559,7 @@ Common patterns for migrating from function-based conditions:
|
|
|
459
559
|
"format": "data-url"
|
|
460
560
|
},
|
|
461
561
|
"uiSchema": {
|
|
462
|
-
"ui:widget": "
|
|
562
|
+
"ui:widget": "fileUpload",
|
|
463
563
|
"ui:options": {
|
|
464
564
|
"accept": ".pdf,.doc,.docx",
|
|
465
565
|
"maxSize": 5242880,
|
|
@@ -469,6 +569,23 @@ Common patterns for migrating from function-based conditions:
|
|
|
469
569
|
}
|
|
470
570
|
```
|
|
471
571
|
|
|
572
|
+
#### File Upload (Ant Upload options)
|
|
573
|
+
```json
|
|
574
|
+
{
|
|
575
|
+
"schema": { "type": "string", "title": "Profile Picture" },
|
|
576
|
+
"uiSchema": {
|
|
577
|
+
"ui:widget": "fileUpload",
|
|
578
|
+
"ui:options": {
|
|
579
|
+
"useAntUpload": true,
|
|
580
|
+
"listType": "picture-card",
|
|
581
|
+
"showUploadList": { "showPreviewIcon": true, "showRemoveIcon": true },
|
|
582
|
+
"maxCount": 1,
|
|
583
|
+
"accept": "image/*"
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
```
|
|
588
|
+
|
|
472
589
|
#### Color Picker
|
|
473
590
|
```json
|
|
474
591
|
{
|
|
@@ -558,7 +675,7 @@ npm run format # Prettier
|
|
|
558
675
|
```
|
|
559
676
|
src/
|
|
560
677
|
├── components/ # Core form components
|
|
561
|
-
├── conditionals/ #
|
|
678
|
+
├── conditionals/ # Declarative conditional engines (internal)
|
|
562
679
|
│ └── v2/ # Current implementation
|
|
563
680
|
├── events/ # Event orchestration
|
|
564
681
|
├── layouts/ # Layout systems
|
|
@@ -592,16 +709,8 @@ Run `npm run dev` to explore examples.
|
|
|
592
709
|
Full TypeScript support with exported types:
|
|
593
710
|
|
|
594
711
|
```typescript
|
|
595
|
-
import {
|
|
596
|
-
|
|
597
|
-
WizardForm,
|
|
598
|
-
UiRule,
|
|
599
|
-
SchemaRule,
|
|
600
|
-
ValidationRule,
|
|
601
|
-
JsonLogicRule,
|
|
602
|
-
FormEvent,
|
|
603
|
-
WebhookConfig
|
|
604
|
-
} from 'extended-dynamic-forms';
|
|
712
|
+
import { ExtendedForm, WizardForm } from 'extended-dynamic-forms';
|
|
713
|
+
// Config is JSON-only; rules are embedded via x-edf:rules
|
|
605
714
|
```
|
|
606
715
|
|
|
607
716
|
## Contributing
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
|
|
3
|
+
export interface LucideIconProps {
|
|
4
|
+
name: string;
|
|
5
|
+
size?: number;
|
|
6
|
+
color?: string;
|
|
7
|
+
strokeWidth?: number;
|
|
8
|
+
className?: string;
|
|
9
|
+
style?: React.CSSProperties;
|
|
10
|
+
}
|
|
11
|
+
export declare const LucideIcon: React.FC<LucideIconProps>;
|