@duffcloudservices/site-forms 0.1.1 → 0.1.3
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 +274 -260
- package/dist/composables/useFormSubmission.d.ts +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +554 -398
- package/dist/index.js.map +1 -1
- package/dist/presets.d.ts +13 -0
- package/dist/site-forms.css +1 -0
- package/dist/types.d.ts +12 -2
- package/package.json +72 -73
- package/src/DcsForm.vue +295 -303
- package/src/__tests__/fields.test.ts +81 -82
- package/src/__tests__/multi-step.test.ts +45 -46
- package/src/__tests__/presets.test.ts +64 -0
- package/src/__tests__/schema.test.ts +41 -42
- package/src/__tests__/style-import.test.ts +9 -0
- package/src/__tests__/submission.test.ts +115 -77
- package/src/__tests__/validation.test.ts +29 -0
- package/src/__tests__/visible-if.test.ts +110 -111
- package/src/composables/useDcsForm.ts +201 -201
- package/src/composables/useFormSubmission.ts +113 -113
- package/src/composables/useFormValidation.ts +128 -127
- package/src/fields/DcsFormCheckbox.vue +35 -35
- package/src/fields/DcsFormCheckboxGroup.vue +52 -52
- package/src/fields/DcsFormDate.vue +34 -34
- package/src/fields/DcsFormFieldWrapper.vue +39 -39
- package/src/fields/DcsFormFile.vue +38 -38
- package/src/fields/DcsFormHidden.vue +17 -17
- package/src/fields/DcsFormHtmlBlock.vue +19 -19
- package/src/fields/DcsFormRadio.vue +45 -45
- package/src/fields/DcsFormSection.vue +19 -19
- package/src/fields/DcsFormSelect.vue +62 -62
- package/src/fields/DcsFormText.vue +54 -54
- package/src/fields/DcsFormTextarea.vue +43 -43
- package/src/index.ts +64 -51
- package/src/loaders/yaml.ts +51 -51
- package/src/presets.ts +192 -0
- package/src/schema/form-definition.schema.json +410 -45
- package/src/schema/validate.ts +58 -58
- package/src/shims.d.ts +10 -10
- package/src/style.css +256 -0
- package/src/types.ts +164 -140
package/src/style.css
ADDED
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
.dcs-form {
|
|
2
|
+
display: grid;
|
|
3
|
+
gap: 1.5rem;
|
|
4
|
+
width: 100%;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
.dcs-form__header {
|
|
8
|
+
display: grid;
|
|
9
|
+
gap: 0.5rem;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.dcs-form__title {
|
|
13
|
+
margin: 0;
|
|
14
|
+
font-size: clamp(1.875rem, 2vw + 1.25rem, 2.5rem);
|
|
15
|
+
font-weight: 700;
|
|
16
|
+
line-height: 1.1;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.dcs-form__description {
|
|
20
|
+
margin: 0;
|
|
21
|
+
font-size: 1rem;
|
|
22
|
+
line-height: 1.6;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.dcs-form__progress {
|
|
26
|
+
font-size: 0.95rem;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.dcs-form__fields {
|
|
30
|
+
display: grid;
|
|
31
|
+
gap: 1rem;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.dcs-form-field {
|
|
35
|
+
display: grid;
|
|
36
|
+
gap: 0.5rem;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.dcs-form-field__label {
|
|
40
|
+
display: inline-flex;
|
|
41
|
+
align-items: center;
|
|
42
|
+
gap: 0.2rem;
|
|
43
|
+
font-size: 0.95rem;
|
|
44
|
+
font-weight: 600;
|
|
45
|
+
line-height: 1.4;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.dcs-form-field__required {
|
|
49
|
+
font-weight: 700;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.dcs-form-input {
|
|
53
|
+
width: 100%;
|
|
54
|
+
min-height: 3rem;
|
|
55
|
+
padding: 0.75rem 0.95rem;
|
|
56
|
+
font: inherit;
|
|
57
|
+
line-height: 1.5;
|
|
58
|
+
color: inherit;
|
|
59
|
+
background: rgba(255, 255, 255, 0.96);
|
|
60
|
+
border: 1px solid rgba(15, 23, 42, 0.16);
|
|
61
|
+
border-radius: 0.875rem;
|
|
62
|
+
box-shadow: 0 1px 2px rgba(15, 23, 42, 0.08);
|
|
63
|
+
transition:
|
|
64
|
+
border-color 0.15s ease,
|
|
65
|
+
box-shadow 0.15s ease,
|
|
66
|
+
background-color 0.15s ease;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.dcs-form-input::placeholder {
|
|
70
|
+
color: rgba(71, 85, 105, 0.75);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.dcs-form-input:hover {
|
|
74
|
+
border-color: rgba(37, 99, 235, 0.38);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.dcs-form-input:focus,
|
|
78
|
+
.dcs-form-input:focus-visible {
|
|
79
|
+
outline: none;
|
|
80
|
+
border-color: rgba(37, 99, 235, 0.75);
|
|
81
|
+
box-shadow: 0 0 0 4px rgba(59, 130, 246, 0.18);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.dcs-form-input[aria-invalid='true'] {
|
|
85
|
+
border-color: rgba(220, 38, 38, 0.72);
|
|
86
|
+
box-shadow: 0 0 0 4px rgba(248, 113, 113, 0.18);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.dcs-form-textarea {
|
|
90
|
+
min-height: 10rem;
|
|
91
|
+
resize: vertical;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.dcs-form-file {
|
|
95
|
+
min-height: 3.25rem;
|
|
96
|
+
padding: 0.5rem 0.75rem;
|
|
97
|
+
cursor: pointer;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.dcs-form-file::file-selector-button {
|
|
101
|
+
margin: 0 0.85rem 0 0;
|
|
102
|
+
border: 0;
|
|
103
|
+
border-radius: 9999px;
|
|
104
|
+
padding: 0.65rem 1rem;
|
|
105
|
+
font: inherit;
|
|
106
|
+
font-weight: 700;
|
|
107
|
+
line-height: 1;
|
|
108
|
+
color: #fff;
|
|
109
|
+
background: linear-gradient(135deg, #1d4ed8, #2563eb);
|
|
110
|
+
box-shadow: 0 8px 18px rgba(37, 99, 235, 0.2);
|
|
111
|
+
cursor: pointer;
|
|
112
|
+
transition:
|
|
113
|
+
transform 0.15s ease,
|
|
114
|
+
box-shadow 0.15s ease,
|
|
115
|
+
opacity 0.15s ease;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
.dcs-form-file:hover::file-selector-button {
|
|
119
|
+
transform: translateY(-1px);
|
|
120
|
+
box-shadow: 0 10px 22px rgba(37, 99, 235, 0.26);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.dcs-form-file:disabled,
|
|
124
|
+
.dcs-form-file:disabled::file-selector-button {
|
|
125
|
+
cursor: not-allowed;
|
|
126
|
+
opacity: 0.7;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.dcs-form-select {
|
|
130
|
+
appearance: none;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
.dcs-form-field__help,
|
|
134
|
+
.dcs-form-field__error,
|
|
135
|
+
.dcs-form__submit-error {
|
|
136
|
+
margin: 0;
|
|
137
|
+
font-size: 0.875rem;
|
|
138
|
+
line-height: 1.5;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
.dcs-form-field__error,
|
|
142
|
+
.dcs-form__submit-error {
|
|
143
|
+
color: #b91c1c;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
.dcs-form__submit-error {
|
|
147
|
+
padding: 0.85rem 1rem;
|
|
148
|
+
border: 1px solid rgba(220, 38, 38, 0.28);
|
|
149
|
+
border-radius: 0.875rem;
|
|
150
|
+
background: rgba(254, 242, 242, 0.92);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
.dcs-form__actions {
|
|
154
|
+
display: flex;
|
|
155
|
+
flex-wrap: wrap;
|
|
156
|
+
gap: 0.75rem;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
.dcs-form__btn {
|
|
160
|
+
appearance: none;
|
|
161
|
+
border: 0;
|
|
162
|
+
border-radius: 9999px;
|
|
163
|
+
padding: 0.85rem 1.5rem;
|
|
164
|
+
font: inherit;
|
|
165
|
+
font-weight: 700;
|
|
166
|
+
line-height: 1;
|
|
167
|
+
cursor: pointer;
|
|
168
|
+
transition:
|
|
169
|
+
transform 0.15s ease,
|
|
170
|
+
box-shadow 0.15s ease,
|
|
171
|
+
opacity 0.15s ease;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
.dcs-form__btn:hover {
|
|
175
|
+
transform: translateY(-1px);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
.dcs-form__btn:focus,
|
|
179
|
+
.dcs-form__btn:focus-visible {
|
|
180
|
+
outline: none;
|
|
181
|
+
box-shadow: 0 0 0 4px rgba(59, 130, 246, 0.22);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
.dcs-form__btn:disabled {
|
|
185
|
+
opacity: 0.7;
|
|
186
|
+
cursor: not-allowed;
|
|
187
|
+
transform: none;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
.dcs-form__btn--submit,
|
|
191
|
+
.dcs-form__btn--next {
|
|
192
|
+
color: #fff;
|
|
193
|
+
background: linear-gradient(135deg, #1d4ed8, #2563eb);
|
|
194
|
+
box-shadow: 0 10px 24px rgba(37, 99, 235, 0.22);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
.dcs-form__btn--prev {
|
|
198
|
+
color: #0f172a;
|
|
199
|
+
background: rgba(255, 255, 255, 0.92);
|
|
200
|
+
box-shadow: 0 8px 20px rgba(15, 23, 42, 0.12);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
.dcs-form-checkbox-group,
|
|
204
|
+
.dcs-form-radio-group {
|
|
205
|
+
display: grid;
|
|
206
|
+
gap: 0.75rem;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
.dcs-form-checkbox,
|
|
210
|
+
.dcs-form-radio,
|
|
211
|
+
.dcs-form-checkbox-single {
|
|
212
|
+
display: flex;
|
|
213
|
+
align-items: flex-start;
|
|
214
|
+
gap: 0.65rem;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
.dcs-form-checkbox-single input,
|
|
218
|
+
.dcs-form-checkbox input,
|
|
219
|
+
.dcs-form-radio input {
|
|
220
|
+
margin-top: 0.2rem;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
.dcs-form-section {
|
|
224
|
+
display: grid;
|
|
225
|
+
gap: 0.4rem;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
.dcs-form-section__heading,
|
|
229
|
+
.dcs-form-section__help,
|
|
230
|
+
.dcs-form--missing p,
|
|
231
|
+
.dcs-form--success p {
|
|
232
|
+
margin: 0;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
@media (min-width: 768px) {
|
|
236
|
+
.dcs-form__fields {
|
|
237
|
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
238
|
+
gap: 1.25rem;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
.dcs-form-field--width-half {
|
|
242
|
+
grid-column: span 1;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
.dcs-form-field--width-full,
|
|
246
|
+
.dcs-form-field--width-auto,
|
|
247
|
+
.dcs-form-field--textarea,
|
|
248
|
+
.dcs-form-field--checkbox,
|
|
249
|
+
.dcs-form-field--checkbox-group,
|
|
250
|
+
.dcs-form-field--radio,
|
|
251
|
+
.dcs-form-field--section-heading,
|
|
252
|
+
.dcs-form-field--html-block,
|
|
253
|
+
.dcs-form-field--file {
|
|
254
|
+
grid-column: 1 / -1;
|
|
255
|
+
}
|
|
256
|
+
}
|
package/src/types.ts
CHANGED
|
@@ -1,140 +1,164 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Form type definitions — vendored snapshot of the canonical form types
|
|
3
|
-
* generated from `contracts/spec/domains/portal-site-forms.yaml` (see
|
|
4
|
-
* `contracts/generated/typescript/types.gen.ts`).
|
|
5
|
-
*
|
|
6
|
-
* This is an intentional fork of the generated types so the published
|
|
7
|
-
* package has zero runtime/peer dependency on the (workspace-internal,
|
|
8
|
-
* never published) `@dcs/contracts` package. When the form schema in
|
|
9
|
-
* `contracts/spec/domains/portal-site-forms.yaml` changes, refresh both
|
|
10
|
-
* this file and `src/schema/form-definition.schema.json`.
|
|
11
|
-
*
|
|
12
|
-
* Consumers should import these types from `@duffcloudservices/site-forms`
|
|
13
|
-
* so the package remains the single import surface for managed-form
|
|
14
|
-
* runtime code on customer sites.
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
export type PortalFormFieldType =
|
|
18
|
-
| 'text'
|
|
19
|
-
| 'email'
|
|
20
|
-
| 'tel'
|
|
21
|
-
| 'textarea'
|
|
22
|
-
| 'select'
|
|
23
|
-
| 'multiselect'
|
|
24
|
-
| 'radio'
|
|
25
|
-
| 'checkbox'
|
|
26
|
-
| 'checkbox-group'
|
|
27
|
-
| 'date'
|
|
28
|
-
| 'file'
|
|
29
|
-
| 'hidden'
|
|
30
|
-
| 'section-heading'
|
|
31
|
-
| 'html-block'
|
|
32
|
-
|
|
33
|
-
export type PortalFormFieldWidth = 'full' | 'half' | 'third'
|
|
34
|
-
|
|
35
|
-
export
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
export
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Form type definitions — vendored snapshot of the canonical form types
|
|
3
|
+
* generated from `contracts/spec/domains/portal-site-forms.yaml` (see
|
|
4
|
+
* `contracts/generated/typescript/types.gen.ts`).
|
|
5
|
+
*
|
|
6
|
+
* This is an intentional fork of the generated types so the published
|
|
7
|
+
* package has zero runtime/peer dependency on the (workspace-internal,
|
|
8
|
+
* never published) `@dcs/contracts` package. When the form schema in
|
|
9
|
+
* `contracts/spec/domains/portal-site-forms.yaml` changes, refresh both
|
|
10
|
+
* this file and `src/schema/form-definition.schema.json`.
|
|
11
|
+
*
|
|
12
|
+
* Consumers should import these types from `@duffcloudservices/site-forms`
|
|
13
|
+
* so the package remains the single import surface for managed-form
|
|
14
|
+
* runtime code on customer sites.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
export type PortalFormFieldType =
|
|
18
|
+
| 'text'
|
|
19
|
+
| 'email'
|
|
20
|
+
| 'tel'
|
|
21
|
+
| 'textarea'
|
|
22
|
+
| 'select'
|
|
23
|
+
| 'multiselect'
|
|
24
|
+
| 'radio'
|
|
25
|
+
| 'checkbox'
|
|
26
|
+
| 'checkbox-group'
|
|
27
|
+
| 'date'
|
|
28
|
+
| 'file'
|
|
29
|
+
| 'hidden'
|
|
30
|
+
| 'section-heading'
|
|
31
|
+
| 'html-block'
|
|
32
|
+
|
|
33
|
+
export type PortalFormFieldWidth = 'full' | 'half' | 'third'
|
|
34
|
+
|
|
35
|
+
export type PortalFormKind = 'freeform' | 'contact' | 'revenue-contractor' | 'resume-submission'
|
|
36
|
+
|
|
37
|
+
export type PortalFormFieldRole =
|
|
38
|
+
| 'custom'
|
|
39
|
+
| 'contact-name'
|
|
40
|
+
| 'contact-email'
|
|
41
|
+
| 'contact-phone'
|
|
42
|
+
| 'contact-company'
|
|
43
|
+
| 'subject'
|
|
44
|
+
| 'message'
|
|
45
|
+
| 'summary'
|
|
46
|
+
| 'image-attachments'
|
|
47
|
+
| 'resume'
|
|
48
|
+
| 'consent'
|
|
49
|
+
|
|
50
|
+
export interface PortalFormAttachmentPolicy {
|
|
51
|
+
expected?: boolean
|
|
52
|
+
required?: boolean
|
|
53
|
+
maxFiles?: number
|
|
54
|
+
maxFileSizeBytes?: number
|
|
55
|
+
accept?: string[]
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export interface PortalFormFieldOption {
|
|
59
|
+
value: string
|
|
60
|
+
label: string
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export interface PortalFormFieldValidation {
|
|
64
|
+
regex?: string
|
|
65
|
+
minLength?: number
|
|
66
|
+
maxLength?: number
|
|
67
|
+
min?: number
|
|
68
|
+
max?: number
|
|
69
|
+
accept?: string[]
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export interface PortalFormFieldVisibleIf {
|
|
73
|
+
fieldId: string
|
|
74
|
+
equals: string | number | boolean
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export interface PortalFormField {
|
|
78
|
+
id: string
|
|
79
|
+
type: PortalFormFieldType
|
|
80
|
+
label: string
|
|
81
|
+
helpText?: string
|
|
82
|
+
placeholder?: string
|
|
83
|
+
defaultValue?: string | number | boolean | string[]
|
|
84
|
+
required?: boolean
|
|
85
|
+
role?: PortalFormFieldRole
|
|
86
|
+
width?: PortalFormFieldWidth
|
|
87
|
+
options?: PortalFormFieldOption[]
|
|
88
|
+
validation?: PortalFormFieldValidation
|
|
89
|
+
visibleIf?: PortalFormFieldVisibleIf
|
|
90
|
+
/**
|
|
91
|
+
* Marks the field as collecting Protected Health Information.
|
|
92
|
+
* When true the value must never appear in notification emails
|
|
93
|
+
* or logs and the owning site must be in the Medical category
|
|
94
|
+
* (see `compliance.instructions.md`).
|
|
95
|
+
*/
|
|
96
|
+
phi?: boolean
|
|
97
|
+
html?: string
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export interface PortalFormStep {
|
|
101
|
+
id: string
|
|
102
|
+
title: string
|
|
103
|
+
description?: string
|
|
104
|
+
fieldIds: string[]
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export interface PortalFormSubmissionLeadConfig {
|
|
108
|
+
kind: 'lead'
|
|
109
|
+
category?: string
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export interface PortalFormSubmissionEmailConfig {
|
|
113
|
+
kind: 'email'
|
|
114
|
+
to: string[]
|
|
115
|
+
subjectTemplate?: string
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export interface PortalFormSubmissionWebhookConfig {
|
|
119
|
+
kind: 'webhook'
|
|
120
|
+
url: string
|
|
121
|
+
signingSecretRef?: string
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export type PortalFormSubmissionConfig =
|
|
125
|
+
| PortalFormSubmissionLeadConfig
|
|
126
|
+
| PortalFormSubmissionEmailConfig
|
|
127
|
+
| PortalFormSubmissionWebhookConfig
|
|
128
|
+
|
|
129
|
+
export interface PortalFormDefinition {
|
|
130
|
+
formId: string
|
|
131
|
+
formKind?: PortalFormKind
|
|
132
|
+
submitLabel?: string
|
|
133
|
+
successMessage?: string
|
|
134
|
+
submission: PortalFormSubmissionConfig
|
|
135
|
+
attachmentPolicy?: PortalFormAttachmentPolicy
|
|
136
|
+
steps?: PortalFormStep[]
|
|
137
|
+
fields: PortalFormField[]
|
|
138
|
+
version?: number
|
|
139
|
+
createdAt?: string
|
|
140
|
+
updatedAt?: string
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/** Map of field id -> current value held by the form. */
|
|
144
|
+
export type FormValues = Record<string, unknown>
|
|
145
|
+
|
|
146
|
+
/** Per-field validation errors keyed by field id. */
|
|
147
|
+
export type FormErrors = Record<string, string | undefined>
|
|
148
|
+
|
|
149
|
+
export interface DcsFormSubmitPayload {
|
|
150
|
+
formId: string
|
|
151
|
+
values: FormValues
|
|
152
|
+
captchaToken?: string
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
export interface DcsFormSubmitSuccess {
|
|
156
|
+
payload: DcsFormSubmitPayload
|
|
157
|
+
response: unknown
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export interface DcsFormSubmitError {
|
|
161
|
+
payload: DcsFormSubmitPayload
|
|
162
|
+
error: Error
|
|
163
|
+
status?: number
|
|
164
|
+
}
|