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,142 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="UTF-8">
|
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
-
<title>Extended Dynamic Forms - Vanilla JS Example</title>
|
|
7
|
-
<!-- Ant Design CSS -->
|
|
8
|
-
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/antd@5.24.0/dist/reset.css">
|
|
9
|
-
<style>
|
|
10
|
-
body {
|
|
11
|
-
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial;
|
|
12
|
-
padding: 20px;
|
|
13
|
-
max-width: 800px;
|
|
14
|
-
margin: 0 auto;
|
|
15
|
-
}
|
|
16
|
-
.form-container {
|
|
17
|
-
background: #fff;
|
|
18
|
-
padding: 24px;
|
|
19
|
-
border-radius: 8px;
|
|
20
|
-
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
|
21
|
-
}
|
|
22
|
-
.form-data {
|
|
23
|
-
margin-top: 20px;
|
|
24
|
-
padding: 16px;
|
|
25
|
-
background: #f5f5f5;
|
|
26
|
-
border-radius: 4px;
|
|
27
|
-
font-family: monospace;
|
|
28
|
-
white-space: pre-wrap;
|
|
29
|
-
}
|
|
30
|
-
</style>
|
|
31
|
-
</head>
|
|
32
|
-
<body>
|
|
33
|
-
<h1>Extended Dynamic Forms - Vanilla JS Example</h1>
|
|
34
|
-
|
|
35
|
-
<div class="form-container">
|
|
36
|
-
<h2>Basic Contact Form</h2>
|
|
37
|
-
<div id="form-root"></div>
|
|
38
|
-
</div>
|
|
39
|
-
|
|
40
|
-
<div class="form-data">
|
|
41
|
-
<h3>Form Data:</h3>
|
|
42
|
-
<div id="form-output">{}</div>
|
|
43
|
-
</div>
|
|
44
|
-
|
|
45
|
-
<!-- Load the standalone library -->
|
|
46
|
-
<script src="../../dist/extended-dynamic-forms.standalone.js"></script>
|
|
47
|
-
|
|
48
|
-
<script>
|
|
49
|
-
// Wait for the library to load
|
|
50
|
-
window.addEventListener('DOMContentLoaded', function() {
|
|
51
|
-
// Define the form schema
|
|
52
|
-
const schema = {
|
|
53
|
-
type: 'object',
|
|
54
|
-
properties: {
|
|
55
|
-
firstName: {
|
|
56
|
-
type: 'string',
|
|
57
|
-
title: 'First Name',
|
|
58
|
-
minLength: 2
|
|
59
|
-
},
|
|
60
|
-
lastName: {
|
|
61
|
-
type: 'string',
|
|
62
|
-
title: 'Last Name'
|
|
63
|
-
},
|
|
64
|
-
email: {
|
|
65
|
-
type: 'string',
|
|
66
|
-
format: 'email',
|
|
67
|
-
title: 'Email Address'
|
|
68
|
-
},
|
|
69
|
-
age: {
|
|
70
|
-
type: 'number',
|
|
71
|
-
title: 'Age',
|
|
72
|
-
minimum: 0,
|
|
73
|
-
maximum: 120
|
|
74
|
-
},
|
|
75
|
-
subscribe: {
|
|
76
|
-
type: 'boolean',
|
|
77
|
-
title: 'Subscribe to newsletter',
|
|
78
|
-
default: false
|
|
79
|
-
},
|
|
80
|
-
country: {
|
|
81
|
-
type: 'string',
|
|
82
|
-
title: 'Country',
|
|
83
|
-
enum: ['us', 'ca', 'uk', 'au'],
|
|
84
|
-
enumNames: ['United States', 'Canada', 'United Kingdom', 'Australia']
|
|
85
|
-
}
|
|
86
|
-
},
|
|
87
|
-
required: ['firstName', 'lastName', 'email']
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
// Define UI customizations
|
|
91
|
-
const uiSchema = {
|
|
92
|
-
firstName: {
|
|
93
|
-
'ui:placeholder': 'Enter your first name',
|
|
94
|
-
'ui:autofocus': true
|
|
95
|
-
},
|
|
96
|
-
email: {
|
|
97
|
-
'ui:widget': 'email',
|
|
98
|
-
'ui:placeholder': 'your.email@example.com'
|
|
99
|
-
},
|
|
100
|
-
age: {
|
|
101
|
-
'ui:widget': 'updown'
|
|
102
|
-
},
|
|
103
|
-
country: {
|
|
104
|
-
'ui:widget': 'select',
|
|
105
|
-
'ui:placeholder': 'Select a country'
|
|
106
|
-
}
|
|
107
|
-
};
|
|
108
|
-
|
|
109
|
-
// Create the form
|
|
110
|
-
const form = ExtendedDynamicForms.createForm({
|
|
111
|
-
container: '#form-root',
|
|
112
|
-
schema: schema,
|
|
113
|
-
uiSchema: uiSchema,
|
|
114
|
-
formData: {
|
|
115
|
-
subscribe: true
|
|
116
|
-
},
|
|
117
|
-
onChange: function(formData) {
|
|
118
|
-
// Update the output display
|
|
119
|
-
document.getElementById('form-output').textContent =
|
|
120
|
-
JSON.stringify(formData, null, 2);
|
|
121
|
-
},
|
|
122
|
-
onSubmit: function(formData) {
|
|
123
|
-
alert('Form submitted!\n\n' + JSON.stringify(formData, null, 2));
|
|
124
|
-
},
|
|
125
|
-
onError: function(errors) {
|
|
126
|
-
console.error('Form errors:', errors);
|
|
127
|
-
}
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
// Example: Update form data after 3 seconds
|
|
131
|
-
setTimeout(function() {
|
|
132
|
-
form.setFormData({
|
|
133
|
-
firstName: 'John',
|
|
134
|
-
lastName: 'Doe',
|
|
135
|
-
email: 'john.doe@example.com',
|
|
136
|
-
subscribe: true
|
|
137
|
-
});
|
|
138
|
-
}, 3000);
|
|
139
|
-
});
|
|
140
|
-
</script>
|
|
141
|
-
</body>
|
|
142
|
-
</html>
|
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="UTF-8">
|
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
-
<title>Conditional Form - Vanilla JS</title>
|
|
7
|
-
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/antd@5.24.0/dist/reset.css">
|
|
8
|
-
<style>
|
|
9
|
-
body {
|
|
10
|
-
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Arial;
|
|
11
|
-
padding: 20px;
|
|
12
|
-
max-width: 800px;
|
|
13
|
-
margin: 0 auto;
|
|
14
|
-
background: #f0f2f5;
|
|
15
|
-
}
|
|
16
|
-
.form-container {
|
|
17
|
-
background: #fff;
|
|
18
|
-
padding: 24px;
|
|
19
|
-
border-radius: 8px;
|
|
20
|
-
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
|
21
|
-
margin-bottom: 20px;
|
|
22
|
-
}
|
|
23
|
-
.info-box {
|
|
24
|
-
background: #e6f7ff;
|
|
25
|
-
border: 1px solid #91d5ff;
|
|
26
|
-
padding: 12px;
|
|
27
|
-
border-radius: 4px;
|
|
28
|
-
margin-bottom: 20px;
|
|
29
|
-
}
|
|
30
|
-
</style>
|
|
31
|
-
</head>
|
|
32
|
-
<body>
|
|
33
|
-
<h1>Conditional Form Example</h1>
|
|
34
|
-
|
|
35
|
-
<div class="info-box">
|
|
36
|
-
This example demonstrates conditional logic where fields appear/disappear based on user selections.
|
|
37
|
-
</div>
|
|
38
|
-
|
|
39
|
-
<div class="form-container">
|
|
40
|
-
<div id="conditional-form"></div>
|
|
41
|
-
</div>
|
|
42
|
-
|
|
43
|
-
<script src="../../dist/extended-dynamic-forms.standalone.js"></script>
|
|
44
|
-
|
|
45
|
-
<script>
|
|
46
|
-
window.addEventListener('DOMContentLoaded', function() {
|
|
47
|
-
const schema = {
|
|
48
|
-
type: 'object',
|
|
49
|
-
properties: {
|
|
50
|
-
userType: {
|
|
51
|
-
type: 'string',
|
|
52
|
-
title: 'User Type',
|
|
53
|
-
enum: ['individual', 'business'],
|
|
54
|
-
enumNames: ['Individual', 'Business']
|
|
55
|
-
},
|
|
56
|
-
firstName: {
|
|
57
|
-
type: 'string',
|
|
58
|
-
title: 'First Name'
|
|
59
|
-
},
|
|
60
|
-
lastName: {
|
|
61
|
-
type: 'string',
|
|
62
|
-
title: 'Last Name'
|
|
63
|
-
},
|
|
64
|
-
businessName: {
|
|
65
|
-
type: 'string',
|
|
66
|
-
title: 'Business Name'
|
|
67
|
-
},
|
|
68
|
-
taxId: {
|
|
69
|
-
type: 'string',
|
|
70
|
-
title: 'Tax ID / EIN'
|
|
71
|
-
},
|
|
72
|
-
hasInternationalOperations: {
|
|
73
|
-
type: 'boolean',
|
|
74
|
-
title: 'International Operations'
|
|
75
|
-
},
|
|
76
|
-
countries: {
|
|
77
|
-
type: 'array',
|
|
78
|
-
title: 'Countries of Operation',
|
|
79
|
-
items: {
|
|
80
|
-
type: 'string'
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
},
|
|
84
|
-
required: ['userType']
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
const uiSchema = {
|
|
88
|
-
userType: {
|
|
89
|
-
'ui:widget': 'radio'
|
|
90
|
-
},
|
|
91
|
-
countries: {
|
|
92
|
-
'ui:widget': 'checkboxes',
|
|
93
|
-
'ui:options': {
|
|
94
|
-
inline: true
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
};
|
|
98
|
-
|
|
99
|
-
// Define conditional rules
|
|
100
|
-
const conditionals = {
|
|
101
|
-
rules: [
|
|
102
|
-
// Show individual fields
|
|
103
|
-
{
|
|
104
|
-
conditions: { userType: 'individual' },
|
|
105
|
-
event: {
|
|
106
|
-
type: 'remove',
|
|
107
|
-
params: { field: ['businessName', 'taxId', 'hasInternationalOperations', 'countries'] }
|
|
108
|
-
}
|
|
109
|
-
},
|
|
110
|
-
// Show business fields
|
|
111
|
-
{
|
|
112
|
-
conditions: { userType: 'business' },
|
|
113
|
-
event: {
|
|
114
|
-
type: 'remove',
|
|
115
|
-
params: { field: ['firstName', 'lastName'] }
|
|
116
|
-
}
|
|
117
|
-
},
|
|
118
|
-
// Show countries when international
|
|
119
|
-
{
|
|
120
|
-
conditions: {
|
|
121
|
-
userType: 'business',
|
|
122
|
-
hasInternationalOperations: { not: true }
|
|
123
|
-
},
|
|
124
|
-
event: {
|
|
125
|
-
type: 'remove',
|
|
126
|
-
params: { field: 'countries' }
|
|
127
|
-
}
|
|
128
|
-
},
|
|
129
|
-
// Make business fields required
|
|
130
|
-
{
|
|
131
|
-
conditions: { userType: 'business' },
|
|
132
|
-
event: {
|
|
133
|
-
type: 'require',
|
|
134
|
-
params: { field: ['businessName', 'taxId'] }
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
]
|
|
138
|
-
};
|
|
139
|
-
|
|
140
|
-
// Create the form with conditionals
|
|
141
|
-
ExtendedDynamicForms.createForm({
|
|
142
|
-
container: '#conditional-form',
|
|
143
|
-
schema: schema,
|
|
144
|
-
uiSchema: uiSchema,
|
|
145
|
-
conditionals: conditionals,
|
|
146
|
-
formData: {
|
|
147
|
-
userType: 'individual'
|
|
148
|
-
},
|
|
149
|
-
onChange: function(formData) {
|
|
150
|
-
console.log('Form data:', formData);
|
|
151
|
-
},
|
|
152
|
-
onSubmit: function(formData) {
|
|
153
|
-
alert('Submitted: ' + JSON.stringify(formData, null, 2));
|
|
154
|
-
}
|
|
155
|
-
});
|
|
156
|
-
});
|
|
157
|
-
</script>
|
|
158
|
-
</body>
|
|
159
|
-
</html>
|
|
@@ -1,185 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="UTF-8">
|
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
-
<title>Wizard Form - Vanilla JS</title>
|
|
7
|
-
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/antd@5.24.0/dist/reset.css">
|
|
8
|
-
<style>
|
|
9
|
-
body {
|
|
10
|
-
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Arial;
|
|
11
|
-
padding: 20px;
|
|
12
|
-
max-width: 900px;
|
|
13
|
-
margin: 0 auto;
|
|
14
|
-
background: #f0f2f5;
|
|
15
|
-
}
|
|
16
|
-
.wizard-container {
|
|
17
|
-
background: #fff;
|
|
18
|
-
padding: 24px;
|
|
19
|
-
border-radius: 8px;
|
|
20
|
-
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
|
21
|
-
min-height: 500px;
|
|
22
|
-
}
|
|
23
|
-
h1 {
|
|
24
|
-
text-align: center;
|
|
25
|
-
color: #1890ff;
|
|
26
|
-
}
|
|
27
|
-
</style>
|
|
28
|
-
</head>
|
|
29
|
-
<body>
|
|
30
|
-
<h1>Multi-Step Wizard Form</h1>
|
|
31
|
-
|
|
32
|
-
<div class="wizard-container">
|
|
33
|
-
<div id="wizard-form"></div>
|
|
34
|
-
</div>
|
|
35
|
-
|
|
36
|
-
<script src="../../dist/extended-dynamic-forms.standalone.js"></script>
|
|
37
|
-
|
|
38
|
-
<script>
|
|
39
|
-
window.addEventListener('DOMContentLoaded', function() {
|
|
40
|
-
// Define wizard steps
|
|
41
|
-
const steps = [
|
|
42
|
-
{
|
|
43
|
-
id: 'personal',
|
|
44
|
-
title: 'Personal Information',
|
|
45
|
-
schema: {
|
|
46
|
-
type: 'object',
|
|
47
|
-
properties: {
|
|
48
|
-
firstName: {
|
|
49
|
-
type: 'string',
|
|
50
|
-
title: 'First Name',
|
|
51
|
-
minLength: 2
|
|
52
|
-
},
|
|
53
|
-
lastName: {
|
|
54
|
-
type: 'string',
|
|
55
|
-
title: 'Last Name',
|
|
56
|
-
minLength: 2
|
|
57
|
-
},
|
|
58
|
-
dateOfBirth: {
|
|
59
|
-
type: 'string',
|
|
60
|
-
format: 'date',
|
|
61
|
-
title: 'Date of Birth'
|
|
62
|
-
}
|
|
63
|
-
},
|
|
64
|
-
required: ['firstName', 'lastName', 'dateOfBirth']
|
|
65
|
-
},
|
|
66
|
-
uiSchema: {
|
|
67
|
-
dateOfBirth: {
|
|
68
|
-
'ui:widget': 'date'
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
},
|
|
72
|
-
{
|
|
73
|
-
id: 'contact',
|
|
74
|
-
title: 'Contact Details',
|
|
75
|
-
schema: {
|
|
76
|
-
type: 'object',
|
|
77
|
-
properties: {
|
|
78
|
-
email: {
|
|
79
|
-
type: 'string',
|
|
80
|
-
format: 'email',
|
|
81
|
-
title: 'Email Address'
|
|
82
|
-
},
|
|
83
|
-
phone: {
|
|
84
|
-
type: 'string',
|
|
85
|
-
title: 'Phone Number',
|
|
86
|
-
pattern: '^[0-9-+()\\s]+$'
|
|
87
|
-
},
|
|
88
|
-
preferredContact: {
|
|
89
|
-
type: 'string',
|
|
90
|
-
title: 'Preferred Contact Method',
|
|
91
|
-
enum: ['email', 'phone', 'both'],
|
|
92
|
-
enumNames: ['Email', 'Phone', 'Both']
|
|
93
|
-
}
|
|
94
|
-
},
|
|
95
|
-
required: ['email', 'phone', 'preferredContact']
|
|
96
|
-
},
|
|
97
|
-
uiSchema: {
|
|
98
|
-
email: {
|
|
99
|
-
'ui:widget': 'email'
|
|
100
|
-
},
|
|
101
|
-
preferredContact: {
|
|
102
|
-
'ui:widget': 'radio'
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
},
|
|
106
|
-
{
|
|
107
|
-
id: 'address',
|
|
108
|
-
title: 'Address Information',
|
|
109
|
-
schema: {
|
|
110
|
-
type: 'object',
|
|
111
|
-
properties: {
|
|
112
|
-
street: {
|
|
113
|
-
type: 'string',
|
|
114
|
-
title: 'Street Address'
|
|
115
|
-
},
|
|
116
|
-
city: {
|
|
117
|
-
type: 'string',
|
|
118
|
-
title: 'City'
|
|
119
|
-
},
|
|
120
|
-
state: {
|
|
121
|
-
type: 'string',
|
|
122
|
-
title: 'State/Province'
|
|
123
|
-
},
|
|
124
|
-
postalCode: {
|
|
125
|
-
type: 'string',
|
|
126
|
-
title: 'Postal Code'
|
|
127
|
-
},
|
|
128
|
-
country: {
|
|
129
|
-
type: 'string',
|
|
130
|
-
title: 'Country',
|
|
131
|
-
enum: ['US', 'CA', 'UK', 'AU'],
|
|
132
|
-
enumNames: ['United States', 'Canada', 'United Kingdom', 'Australia']
|
|
133
|
-
}
|
|
134
|
-
},
|
|
135
|
-
required: ['street', 'city', 'country']
|
|
136
|
-
},
|
|
137
|
-
uiSchema: {
|
|
138
|
-
street: {
|
|
139
|
-
'ui:widget': 'textarea',
|
|
140
|
-
'ui:options': {
|
|
141
|
-
rows: 2
|
|
142
|
-
}
|
|
143
|
-
},
|
|
144
|
-
country: {
|
|
145
|
-
'ui:widget': 'select'
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
},
|
|
149
|
-
{
|
|
150
|
-
id: 'review',
|
|
151
|
-
title: 'Review & Submit',
|
|
152
|
-
schema: {
|
|
153
|
-
type: 'object',
|
|
154
|
-
properties: {
|
|
155
|
-
agreeToTerms: {
|
|
156
|
-
type: 'boolean',
|
|
157
|
-
title: 'I agree to the terms and conditions'
|
|
158
|
-
},
|
|
159
|
-
newsletter: {
|
|
160
|
-
type: 'boolean',
|
|
161
|
-
title: 'Subscribe to newsletter',
|
|
162
|
-
default: true
|
|
163
|
-
}
|
|
164
|
-
},
|
|
165
|
-
required: ['agreeToTerms']
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
];
|
|
169
|
-
|
|
170
|
-
// Create the wizard form
|
|
171
|
-
ExtendedDynamicForms.createWizardForm({
|
|
172
|
-
container: '#wizard-form',
|
|
173
|
-
steps: steps,
|
|
174
|
-
initialData: {},
|
|
175
|
-
onStepChange: function(step, formData) {
|
|
176
|
-
console.log('Step ' + step + ' data:', formData);
|
|
177
|
-
},
|
|
178
|
-
onComplete: function(formData) {
|
|
179
|
-
alert('Wizard completed!\n\nFinal data:\n' + JSON.stringify(formData, null, 2));
|
|
180
|
-
}
|
|
181
|
-
});
|
|
182
|
-
});
|
|
183
|
-
</script>
|
|
184
|
-
</body>
|
|
185
|
-
</html>
|