@duffcloudservices/site-forms 0.1.2 → 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 +18 -4
- 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 -1
- package/dist/types.d.ts +12 -2
- package/package.json +1 -1
- package/src/DcsForm.vue +1 -9
- package/src/__tests__/fields.test.ts +0 -1
- package/src/__tests__/multi-step.test.ts +0 -1
- package/src/__tests__/presets.test.ts +64 -0
- package/src/__tests__/schema.test.ts +0 -1
- package/src/__tests__/submission.test.ts +40 -2
- package/src/__tests__/validation.test.ts +29 -0
- package/src/__tests__/visible-if.test.ts +1 -2
- package/src/composables/useFormSubmission.ts +3 -3
- package/src/composables/useFormValidation.ts +8 -7
- package/src/index.ts +11 -0
- package/src/presets.ts +192 -0
- package/src/schema/form-definition.schema.json +410 -45
- package/src/style.css +35 -0
- package/src/types.ts +26 -2
package/dist/index.js
CHANGED
|
@@ -1,197 +1,197 @@
|
|
|
1
|
-
import { reactive as X, ref as
|
|
1
|
+
import { reactive as X, ref as j, computed as f, defineComponent as S, createElementBlock as h, openBlock as d, normalizeClass as Z, renderSlot as k, createCommentVNode as w, createTextVNode as E, toDisplayString as b, createBlock as L, withCtx as I, createElementVNode as y, Fragment as D, renderList as R, watch as N, onMounted as ee, unref as c, resolveDynamicComponent as te } from "vue";
|
|
2
2
|
import ie from "ajv";
|
|
3
3
|
import re from "ajv-formats";
|
|
4
|
-
import
|
|
5
|
-
function
|
|
4
|
+
import J from "js-yaml";
|
|
5
|
+
function z(e, t) {
|
|
6
6
|
return e.visibleIf ? t[e.visibleIf.fieldId] === e.visibleIf.equals : !0;
|
|
7
7
|
}
|
|
8
8
|
function ne(e, t) {
|
|
9
9
|
if (e.type === "section-heading" || e.type === "html-block" || e.type === "hidden")
|
|
10
10
|
return;
|
|
11
|
-
const r = t == null ||
|
|
11
|
+
const i = typeof t == "string" ? t.trim() : t, r = t == null || i === "" || Array.isArray(t) && t.length === 0;
|
|
12
12
|
if (e.required && r)
|
|
13
13
|
return `${e.label} is required`;
|
|
14
14
|
if (r) return;
|
|
15
|
-
if (e.type === "email" && typeof
|
|
15
|
+
if (e.type === "email" && typeof i == "string" && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(i))
|
|
16
16
|
return `${e.label} must be a valid email address`;
|
|
17
|
-
const
|
|
18
|
-
if (
|
|
19
|
-
if (typeof
|
|
20
|
-
if (
|
|
21
|
-
return `${e.label} must be at least ${
|
|
22
|
-
if (
|
|
23
|
-
return `${e.label} must be at most ${
|
|
24
|
-
if (
|
|
17
|
+
const n = e.validation;
|
|
18
|
+
if (n) {
|
|
19
|
+
if (typeof i == "string") {
|
|
20
|
+
if (n.minLength != null && i.length < n.minLength)
|
|
21
|
+
return `${e.label} must be at least ${n.minLength} characters`;
|
|
22
|
+
if (n.maxLength != null && i.length > n.maxLength)
|
|
23
|
+
return `${e.label} must be at most ${n.maxLength} characters`;
|
|
24
|
+
if (n.regex)
|
|
25
25
|
try {
|
|
26
|
-
if (!new RegExp(
|
|
26
|
+
if (!new RegExp(n.regex).test(i))
|
|
27
27
|
return `${e.label} is invalid`;
|
|
28
28
|
} catch {
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
31
|
if (typeof t == "number") {
|
|
32
|
-
if (
|
|
33
|
-
return `${e.label} must be at least ${
|
|
34
|
-
if (
|
|
35
|
-
return `${e.label} must be at most ${
|
|
32
|
+
if (n.min != null && t < n.min)
|
|
33
|
+
return `${e.label} must be at least ${n.min}`;
|
|
34
|
+
if (n.max != null && t > n.max)
|
|
35
|
+
return `${e.label} must be at most ${n.max}`;
|
|
36
36
|
}
|
|
37
|
-
if (e.type === "file" &&
|
|
38
|
-
const
|
|
39
|
-
if (
|
|
40
|
-
return `${e.label} must be one of: ${
|
|
37
|
+
if (e.type === "file" && n.accept && n.accept.length > 0) {
|
|
38
|
+
const l = t;
|
|
39
|
+
if (l && typeof File < "u" && l instanceof File && !n.accept.some((u) => u.startsWith(".") ? l.name.toLowerCase().endsWith(u.toLowerCase()) : l.type === u))
|
|
40
|
+
return `${e.label} must be one of: ${n.accept.join(", ")}`;
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
|
-
function oe(e, t,
|
|
45
|
-
const
|
|
46
|
-
for (const
|
|
47
|
-
if (
|
|
48
|
-
const s = ne(
|
|
49
|
-
s && (
|
|
50
|
-
}
|
|
51
|
-
return
|
|
44
|
+
function oe(e, t, i) {
|
|
45
|
+
const r = {}, n = i ? new Set(i) : null;
|
|
46
|
+
for (const l of e.fields) {
|
|
47
|
+
if (n && !n.has(l.id) || !z(l, t)) continue;
|
|
48
|
+
const s = ne(l, t[l.id]);
|
|
49
|
+
s && (r[l.id] = s);
|
|
50
|
+
}
|
|
51
|
+
return r;
|
|
52
52
|
}
|
|
53
53
|
function se(e) {
|
|
54
54
|
return Object.values(e).some((t) => !!t);
|
|
55
55
|
}
|
|
56
|
-
function
|
|
56
|
+
function W(e) {
|
|
57
57
|
const t = {};
|
|
58
|
-
for (const
|
|
59
|
-
|
|
58
|
+
for (const i of e.fields)
|
|
59
|
+
i.defaultValue !== void 0 ? t[i.id] = i.defaultValue : i.type === "checkbox" ? t[i.id] = !1 : i.type === "multiselect" || i.type === "checkbox-group" ? t[i.id] = [] : t[i.id] = "";
|
|
60
60
|
return t;
|
|
61
61
|
}
|
|
62
62
|
function ae(e) {
|
|
63
|
-
const { definition: t } = e,
|
|
63
|
+
const { definition: t } = e, i = X(W(t)), r = j({}), n = j({}), l = j(!1), s = j(!1), u = j(null), a = j(0), o = f(() => t.fields), m = f(
|
|
64
64
|
() => t.steps && t.steps.length > 0 ? t.steps : null
|
|
65
|
-
), g =
|
|
66
|
-
const
|
|
67
|
-
return
|
|
68
|
-
}),
|
|
69
|
-
const
|
|
70
|
-
if (!
|
|
71
|
-
const
|
|
72
|
-
return t.fields.filter((
|
|
73
|
-
}),
|
|
74
|
-
const
|
|
75
|
-
return !
|
|
76
|
-
}),
|
|
77
|
-
() =>
|
|
65
|
+
), g = f(() => {
|
|
66
|
+
const p = m.value;
|
|
67
|
+
return p ? p[a.value] ?? null : null;
|
|
68
|
+
}), $ = f(() => {
|
|
69
|
+
const p = g.value;
|
|
70
|
+
if (!p) return t.fields;
|
|
71
|
+
const x = new Set(p.fieldIds);
|
|
72
|
+
return t.fields.filter((A) => x.has(A.id));
|
|
73
|
+
}), C = f(() => a.value === 0), T = f(() => {
|
|
74
|
+
const p = m.value;
|
|
75
|
+
return !p || a.value >= p.length - 1;
|
|
76
|
+
}), K = f(
|
|
77
|
+
() => $.value.filter((p) => z(p, i))
|
|
78
78
|
);
|
|
79
|
-
function
|
|
80
|
-
|
|
81
|
-
}
|
|
82
|
-
function
|
|
83
|
-
|
|
84
|
-
}
|
|
85
|
-
function
|
|
86
|
-
const
|
|
87
|
-
if (
|
|
88
|
-
const
|
|
89
|
-
for (const
|
|
90
|
-
|
|
91
|
-
|
|
79
|
+
function v(p, x) {
|
|
80
|
+
i[p] = x, r.value[p] && (r.value = { ...r.value, [p]: void 0 });
|
|
81
|
+
}
|
|
82
|
+
function V(p) {
|
|
83
|
+
n.value = { ...n.value, [p]: !0 };
|
|
84
|
+
}
|
|
85
|
+
function F(p) {
|
|
86
|
+
const x = oe(t, i, p);
|
|
87
|
+
if (p) {
|
|
88
|
+
const A = { ...r.value };
|
|
89
|
+
for (const B of p)
|
|
90
|
+
A[B] = x[B];
|
|
91
|
+
r.value = A;
|
|
92
92
|
} else
|
|
93
|
-
|
|
94
|
-
return !se(
|
|
93
|
+
r.value = x;
|
|
94
|
+
return !se(r.value);
|
|
95
95
|
}
|
|
96
|
-
function
|
|
97
|
-
const
|
|
98
|
-
return
|
|
96
|
+
function P() {
|
|
97
|
+
const p = g.value?.fieldIds;
|
|
98
|
+
return F(p);
|
|
99
99
|
}
|
|
100
|
-
function
|
|
101
|
-
return
|
|
100
|
+
function M() {
|
|
101
|
+
return F();
|
|
102
102
|
}
|
|
103
|
-
function
|
|
104
|
-
return !m.value || !
|
|
103
|
+
function _() {
|
|
104
|
+
return !m.value || !P() ? !1 : a.value < m.value.length - 1 ? (a.value++, !0) : !1;
|
|
105
105
|
}
|
|
106
106
|
function G() {
|
|
107
107
|
a.value > 0 && a.value--;
|
|
108
108
|
}
|
|
109
109
|
function Y() {
|
|
110
|
-
const
|
|
111
|
-
for (const
|
|
112
|
-
delete
|
|
113
|
-
Object.assign(
|
|
110
|
+
const p = W(t);
|
|
111
|
+
for (const x of Object.keys(i))
|
|
112
|
+
delete i[x];
|
|
113
|
+
Object.assign(i, p), r.value = {}, n.value = {}, l.value = !1, s.value = !1, u.value = null, a.value = 0;
|
|
114
114
|
}
|
|
115
115
|
function Q() {
|
|
116
|
-
const
|
|
117
|
-
for (const
|
|
118
|
-
|
|
119
|
-
return
|
|
116
|
+
const p = {};
|
|
117
|
+
for (const x of t.fields)
|
|
118
|
+
x.type === "section-heading" || x.type === "html-block" || z(x, i) && (p[x.id] = i[x.id]);
|
|
119
|
+
return p;
|
|
120
120
|
}
|
|
121
121
|
return {
|
|
122
|
-
values:
|
|
123
|
-
errors:
|
|
124
|
-
touched:
|
|
125
|
-
submitting:
|
|
122
|
+
values: i,
|
|
123
|
+
errors: r,
|
|
124
|
+
touched: n,
|
|
125
|
+
submitting: l,
|
|
126
126
|
submitted: s,
|
|
127
|
-
submitError:
|
|
128
|
-
fields:
|
|
127
|
+
submitError: u,
|
|
128
|
+
fields: o,
|
|
129
129
|
steps: m,
|
|
130
130
|
currentStepIndex: a,
|
|
131
131
|
currentStep: g,
|
|
132
|
-
currentStepFields:
|
|
133
|
-
isFirstStep:
|
|
134
|
-
isLastStep:
|
|
135
|
-
visibleFields:
|
|
136
|
-
setValue:
|
|
137
|
-
touch:
|
|
138
|
-
validateCurrentScope:
|
|
139
|
-
validateAll:
|
|
140
|
-
next:
|
|
132
|
+
currentStepFields: $,
|
|
133
|
+
isFirstStep: C,
|
|
134
|
+
isLastStep: T,
|
|
135
|
+
visibleFields: K,
|
|
136
|
+
setValue: v,
|
|
137
|
+
touch: V,
|
|
138
|
+
validateCurrentScope: P,
|
|
139
|
+
validateAll: M,
|
|
140
|
+
next: _,
|
|
141
141
|
prev: G,
|
|
142
142
|
reset: Y,
|
|
143
143
|
collectSubmissionValues: Q
|
|
144
144
|
};
|
|
145
145
|
}
|
|
146
146
|
async function le(e) {
|
|
147
|
-
const { apiBase: t, siteSlug:
|
|
148
|
-
|
|
149
|
-
)}/
|
|
147
|
+
const { apiBase: t, siteSlug: i, payload: r } = e, n = e.retries ?? 1, l = e.fetchImpl ?? fetch, s = `${t.replace(/\/$/, "")}/sites/${encodeURIComponent(
|
|
148
|
+
i
|
|
149
|
+
)}/forms/${encodeURIComponent(r.formId)}/submissions`, u = Object.values(r.values).some(
|
|
150
150
|
(m) => typeof File < "u" && m instanceof File
|
|
151
151
|
);
|
|
152
|
-
let a,
|
|
153
|
-
for (let m = 0; m <=
|
|
152
|
+
let a, o;
|
|
153
|
+
for (let m = 0; m <= n; m++)
|
|
154
154
|
try {
|
|
155
|
-
const g =
|
|
155
|
+
const g = u ? { method: "POST", body: de(r) } : {
|
|
156
156
|
method: "POST",
|
|
157
157
|
headers: { "Content-Type": "application/json" },
|
|
158
|
-
body: JSON.stringify(
|
|
159
|
-
},
|
|
160
|
-
if (
|
|
161
|
-
const
|
|
162
|
-
return { payload:
|
|
158
|
+
body: JSON.stringify(r)
|
|
159
|
+
}, $ = await l(s, g);
|
|
160
|
+
if (o = $.status, $.ok) {
|
|
161
|
+
const C = await ue($);
|
|
162
|
+
return { payload: r, response: C };
|
|
163
163
|
}
|
|
164
|
-
if (
|
|
165
|
-
const
|
|
164
|
+
if ($.status < 500) {
|
|
165
|
+
const C = await ce($);
|
|
166
166
|
throw {
|
|
167
|
-
payload:
|
|
168
|
-
status:
|
|
169
|
-
error: new Error(`Submission failed (${
|
|
167
|
+
payload: r,
|
|
168
|
+
status: $.status,
|
|
169
|
+
error: new Error(`Submission failed (${$.status}): ${C}`)
|
|
170
170
|
};
|
|
171
171
|
}
|
|
172
|
-
a = new Error(`Server error ${
|
|
172
|
+
a = new Error(`Server error ${$.status}`);
|
|
173
173
|
} catch (g) {
|
|
174
174
|
if (g && typeof g == "object" && "payload" in g && "error" in g)
|
|
175
175
|
throw g;
|
|
176
176
|
a = g;
|
|
177
177
|
}
|
|
178
178
|
throw {
|
|
179
|
-
payload:
|
|
180
|
-
status:
|
|
179
|
+
payload: r,
|
|
180
|
+
status: o,
|
|
181
181
|
error: a ?? new Error("Submission failed")
|
|
182
182
|
};
|
|
183
183
|
}
|
|
184
184
|
function de(e) {
|
|
185
185
|
const t = new FormData();
|
|
186
186
|
t.append("formId", e.formId), e.captchaToken && t.append("captchaToken", e.captchaToken);
|
|
187
|
-
for (const [
|
|
188
|
-
if (
|
|
189
|
-
if (
|
|
190
|
-
t.append(`values[${
|
|
191
|
-
else if (Array.isArray(
|
|
192
|
-
for (const
|
|
187
|
+
for (const [i, r] of Object.entries(e.values))
|
|
188
|
+
if (r != null)
|
|
189
|
+
if (r instanceof File)
|
|
190
|
+
t.append(`values[${i}]`, r);
|
|
191
|
+
else if (Array.isArray(r))
|
|
192
|
+
for (const n of r) t.append(`values[${i}][]`, String(n));
|
|
193
193
|
else
|
|
194
|
-
t.append(`values[${
|
|
194
|
+
t.append(`values[${i}]`, String(r));
|
|
195
195
|
return t;
|
|
196
196
|
}
|
|
197
197
|
async function ue(e) {
|
|
@@ -208,73 +208,73 @@ async function ce(e) {
|
|
|
208
208
|
return "";
|
|
209
209
|
}
|
|
210
210
|
}
|
|
211
|
-
const me = "http://json-schema.org/draft-07/schema#", fe = "https://duffcloudservices.com/schemas/form-definition.schema.json", pe = "PortalFormDefinition", he = "object", ve = "Portable form definition. This schema is the source of truth for\nboth the portal CRUD APIs and the `.dcs/forms/<formId>.yaml`\nfiles consumed by customer-site builds via `<DcsForm/>`.\n", be = ["formId", "title", "submission", "fields"], ge = { formId: { type: "string", description: "Kebab-case identifier, unique per site.", pattern: "^[a-z0-9][a-z0-9-]*$", minLength: 1, maxLength: 80, example: "contact" }, title: { type: "string", description: "Human-readable form title shown in the portal and rendered as the form heading.", minLength: 1, maxLength: 200, example: "Contact Us" }, description: { type: "string", description: "Optional descriptive text rendered above the fields.", maxLength: 2e3 }, submitLabel: { type: "string", description: 'Label for the submit button. Defaults to "Send" client-side.', maxLength: 80, example: "Send message" }, successMessage: { type: "string", description: "Confirmation message shown after a successful submission.", maxLength: 2e3, example: "Thanks — we'll be in touch shortly." }, submission: { $ref: "#/definitions/PortalFormSubmissionConfig" }, steps: { type: "array", description: "Optional multi-step grouping. When omitted, fields render as a single page.", items: { $ref: "#/definitions/PortalFormStep" } }, fields: { type: "array", description: "Flat list of all fields in the form. When `steps` is present,\nevery field referenced from a step's `fieldIds` must exist here.\n", items: { $ref: "#/definitions/PortalFormField" } }, version: { type: "integer", minimum: 1, description: "Monotonically increasing version, bumped on each save." }, createdAt: { type: "string", format: "date-time", description: "Form creation timestamp." }, updatedAt: { type: "string", format: "date-time", description: "Last modification timestamp." } }, ye = /* @__PURE__ */ JSON.parse('{"PortalFormFieldType":{"type":"string","description":"Field type controlling input rendering and validation. Includes\\nlayout-only types (`section-heading`, `html-block`) that render\\ndecorative content rather than capturing values, and `hidden`\\nfor prefilled values not displayed to the user.\\n","enum":["text","email","tel","textarea","select","multiselect","radio","checkbox","checkbox-group","date","file","hidden","section-heading","html-block"]},"PortalFormFieldWidth":{"type":"string","description":"Layout hint for the field within its row.","enum":["full","half","third"]},"PortalFormFieldOption":{"type":"object","description":"A single option for select / radio / checkbox-group fields.","required":["value","label"],"properties":{"value":{"type":"string","description":"Submitted value for this option."},"label":{"type":"string","description":"Human-readable label shown to the user."}}},"PortalFormFieldValidation":{"type":"object","description":"Optional validation rules applied to a field\'s value.","properties":{"regex":{"type":"string","description":"ECMAScript-compatible pattern the value must match."},"minLength":{"type":"integer","minimum":0,"description":"Minimum string length (text-like fields only)."},"maxLength":{"type":"integer","minimum":0,"description":"Maximum string length (text-like fields only)."},"min":{"type":"number","description":"Minimum numeric / date value."},"max":{"type":"number","description":"Maximum numeric / date value."},"accept":{"type":"array","description":"Accepted MIME types or file extensions for `file` fields.","items":{"type":"string"}}}},"PortalFormFieldVisibleIf":{"type":"object","description":"Single-predicate visibility rule. The field is shown only when\\nthe referenced sibling field\'s value equals `equals`. Future\\nrevisions may extend this with AND / OR composition; clients\\nshould treat unknown extra properties as opaque.\\n","required":["fieldId","equals"],"properties":{"fieldId":{"type":"string","description":"ID of the sibling field whose value gates visibility."},"equals":{"description":"Value (string, number, or boolean) the sibling field must equal.","oneOf":[{"type":"string"},{"type":"number"},{"type":"boolean"}]}}},"PortalFormField":{"type":"object","description":"A single field within a form definition.","required":["id","type","label"],"properties":{"id":{"type":"string","description":"Kebab-case identifier, unique within the form.","pattern":"^[a-z0-9][a-z0-9-]*$","minLength":1,"maxLength":80},"type":{"$ref":"#/definitions/PortalFormFieldType"},"label":{"type":"string","description":"Human-readable label rendered above the input.","minLength":1,"maxLength":200},"helpText":{"type":"string","description":"Optional helper / description text shown beneath the label.","maxLength":500},"placeholder":{"type":"string","description":"Optional placeholder shown inside empty inputs.","maxLength":200},"defaultValue":{"description":"Optional default value (string, number, boolean, or array of strings).","oneOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"array","items":{"type":"string"}}]},"required":{"type":"boolean","default":false,"description":"Whether the field must be supplied to submit the form."},"width":{"allOf":[{"$ref":"#/definitions/PortalFormFieldWidth"}],"default":"full"},"options":{"type":"array","description":"Options for `select`, `multiselect`, `radio`, `checkbox-group` fields.","items":{"$ref":"#/definitions/PortalFormFieldOption"}},"validation":{"$ref":"#/definitions/PortalFormFieldValidation"},"visibleIf":{"$ref":"#/definitions/PortalFormFieldVisibleIf"},"phi":{"type":"boolean","default":false,"description":"Marks the field as collecting Protected Health Information.\\nWhen true the value must never appear in notification emails\\nor logs and the owning site must be in the Medical category\\n(see `compliance.instructions.md`).\\n"},"html":{"type":"string","description":"Sanitized HTML body for `html-block` fields. Ignored for\\nother field types.\\n","maxLength":10000}}},"PortalFormStep":{"type":"object","description":"Optional grouping for multi-step (wizard-style) forms such as\\nthe KT Braun estate-planning questionnaires. When `steps` is\\nomitted on a form, all fields render as a single page.\\n","required":["id","title","fieldIds"],"properties":{"id":{"type":"string","description":"Kebab-case step identifier, unique within the form.","pattern":"^[a-z0-9][a-z0-9-]*$","minLength":1,"maxLength":80},"title":{"type":"string","description":"Step title shown in the wizard header.","minLength":1,"maxLength":200},"description":{"type":"string","description":"Optional descriptive text shown below the step title.","maxLength":1000},"fieldIds":{"type":"array","description":"Ordered list of field IDs that belong to this step.","items":{"type":"string","pattern":"^[a-z0-9][a-z0-9-]*$"}}}},"PortalFormSubmissionLeadConfig":{"type":"object","required":["kind"],"description":"Routes submissions into the existing PortalLeads pipeline.","properties":{"kind":{"type":"string","enum":["lead"]},"category":{"type":"string","description":"Service category id used to route the lead."}}},"PortalFormSubmissionEmailConfig":{"type":"object","required":["kind","to"],"description":"Routes submissions as a notification email to the listed recipients.","properties":{"kind":{"type":"string","enum":["email"]},"to":{"type":"array","minItems":1,"items":{"type":"string","format":"email"},"description":"Recipient email addresses."},"subjectTemplate":{"type":"string","description":"Optional subject-line template. Use `{title}` to interpolate\\nthe form\'s title; values are intentionally not interpolated\\ninto the subject line for compliance reasons.\\n","maxLength":200}}},"PortalFormSubmissionWebhookConfig":{"type":"object","required":["kind","url"],"description":"Posts the submission JSON to a third-party webhook.","properties":{"kind":{"type":"string","enum":["webhook"]},"url":{"type":"string","format":"uri","description":"HTTPS endpoint receiving the signed POST."},"signingSecretRef":{"type":"string","description":"Name of the Key Vault secret used to HMAC-sign the request.\\nThe secret value is never returned in API responses.\\n"}}},"PortalFormSubmissionConfig":{"description":"Discriminated union of submission destinations. Exactly one of\\n`lead`, `email`, or `webhook` shapes is used based on `kind`.\\n","oneOf":[{"$ref":"#/definitions/PortalFormSubmissionLeadConfig"},{"$ref":"#/definitions/PortalFormSubmissionEmailConfig"},{"$ref":"#/definitions/PortalFormSubmissionWebhookConfig"}],"discriminator":{"propertyName":"kind","mapping":{"lead":"#/definitions/PortalFormSubmissionLeadConfig","email":"#/definitions/PortalFormSubmissionEmailConfig","webhook":"#/definitions/PortalFormSubmissionWebhookConfig"}}},"PortalFormSummary":{"type":"object","description":"List-row projection of a form definition.","required":["formId","title","fieldCount"],"properties":{"formId":{"type":"string","description":"Kebab-case identifier.","pattern":"^[a-z0-9][a-z0-9-]*$","example":"contact"},"title":{"type":"string","description":"Human-readable title.","example":"Contact Us"},"description":{"type":"string","description":"Optional descriptive text."},"fieldCount":{"type":"integer","minimum":0,"description":"Number of input-bearing fields in the form.","example":4},"attachedPageSlugs":{"type":"array","description":"Slugs of pages that currently reference this form via `formId`.","items":{"type":"string"}},"submissionKind":{"type":"string","enum":["lead","email","webhook"],"description":"Submission destination kind."},"lastUpdated":{"type":"string","format":"date-time","description":"Last modification timestamp."}}},"PortalCreateFormRequest":{"type":"object","description":"Payload for creating a new form definition.","required":["formId","title","submission","fields"],"properties":{"formId":{"type":"string","description":"Kebab-case identifier, unique per site.","pattern":"^[a-z0-9][a-z0-9-]*$","minLength":1,"maxLength":80},"title":{"type":"string","minLength":1,"maxLength":200},"description":{"type":"string","maxLength":2000},"submitLabel":{"type":"string","maxLength":80},"successMessage":{"type":"string","maxLength":2000},"submission":{"$ref":"#/definitions/PortalFormSubmissionConfig"},"steps":{"type":"array","items":{"$ref":"#/definitions/PortalFormStep"}},"fields":{"type":"array","items":{"$ref":"#/definitions/PortalFormField"}}}},"PortalUpdateFormRequest":{"type":"object","description":"Payload for updating an existing form definition. The `formId`\\nis taken from the URL; supplying it in the body is optional and,\\nif present, must match the path.\\n","properties":{"formId":{"type":"string","pattern":"^[a-z0-9][a-z0-9-]*$","minLength":1,"maxLength":80,"description":"Optional echo of the path formId; must match if provided."},"title":{"type":"string","minLength":1,"maxLength":200},"description":{"type":"string","maxLength":2000},"submitLabel":{"type":"string","maxLength":80},"successMessage":{"type":"string","maxLength":2000},"submission":{"$ref":"#/definitions/PortalFormSubmissionConfig"},"steps":{"type":"array","items":{"$ref":"#/definitions/PortalFormStep"}},"fields":{"type":"array","items":{"$ref":"#/definitions/PortalFormField"}},"expectedVersion":{"type":"integer","minimum":1,"description":"Optional optimistic-concurrency token. When supplied, the\\nupdate is rejected with 409 if the stored form\'s `version`\\nno longer matches.\\n"}}},"PortalDuplicateFormRequest":{"type":"object","description":"Payload for cloning an existing form under a new formId.","required":["formId"],"properties":{"formId":{"type":"string","description":"Target kebab-case formId for the cloned form.","pattern":"^[a-z0-9][a-z0-9-]*$","minLength":1,"maxLength":80},"title":{"type":"string","description":"Optional title override; defaults to `<source title> (copy)`.","minLength":1,"maxLength":200}}},"PortalFormResponse":{"type":"object","description":"Full form definition response.","required":["form"],"properties":{"form":{"$ref":"#/definitions/PortalFormDefinition"},"attachedPageSlugs":{"type":"array","description":"Slugs of pages that currently reference this form via `formId`.","items":{"type":"string"}}}},"PortalFormListResponse":{"type":"object","required":["forms","totalCount"],"properties":{"forms":{"type":"array","items":{"$ref":"#/definitions/PortalFormSummary"}},"totalCount":{"type":"integer","minimum":0,"description":"Total number of forms matching the query.","example":3}}}}'), $e = {
|
|
211
|
+
const me = "http://json-schema.org/draft-07/schema#", fe = "https://duffcloudservices.com/schemas/form-definition.schema.json", pe = "PortalFormDefinition", he = "object", ye = "Portable form definition. This schema is the source of truth for\nboth the portal CRUD APIs and the `.dcs/forms/<formId>.yaml`\nfiles consumed by customer-site builds via `<DcsForm/>`.\n", be = ["formId", "submission", "fields"], ge = { formId: { type: "string", description: "Kebab-case identifier, unique per site.", pattern: "^[a-z0-9][a-z0-9-]*$", minLength: 1, maxLength: 80, example: "contact" }, formKind: { $ref: "#/definitions/PortalFormKind" }, submitLabel: { type: "string", description: 'Label for the submit button. Defaults to "Send" client-side.', maxLength: 80, example: "Send message" }, successMessage: { type: "string", description: "Confirmation message shown after a successful submission.", maxLength: 2e3, example: "Thanks — we'll be in touch shortly." }, submission: { $ref: "#/definitions/PortalFormSubmissionConfig" }, attachmentPolicy: { $ref: "#/definitions/PortalFormAttachmentPolicy" }, steps: { type: "array", description: "Optional multi-step grouping. When omitted, fields render as a single page.", items: { $ref: "#/definitions/PortalFormStep" } }, fields: { type: "array", description: "Flat list of all fields in the form. When `steps` is present,\nevery field referenced from a step's `fieldIds` must exist here.\n", items: { $ref: "#/definitions/PortalFormField" } }, version: { type: "integer", minimum: 1, description: "Monotonically increasing version, bumped on each save." }, createdAt: { type: "string", format: "date-time", description: "Form creation timestamp." }, updatedAt: { type: "string", format: "date-time", description: "Last modification timestamp." } }, ve = /* @__PURE__ */ JSON.parse('{"PortalFormKind":{"type":"string","description":"High-level form kind used by the visual page editor and submission\\npipeline. `freeform` preserves fully editable questionnaires; the\\nstandard values provide predictable field roles and routing for common\\nsite forms.\\n","enum":["freeform","contact","revenue-contractor","resume-submission"],"default":"freeform"},"PortalFormFieldRole":{"type":"string","description":"Semantic role for a field inside a standard form. Free-form forms may\\nomit roles or use `custom`; standard forms use roles so submissions can\\nbe surfaced consistently as contact messages, notifications, revenue\\ncontractor inquiries, or resume submissions without locking the editor\\nout of label/help-text changes.\\n","enum":["contact-name","contact-email","contact-phone","contact-company","subject","message","summary","image-attachments","resume","consent","custom"]},"PortalFormAttachmentPolicy":{"type":"object","description":"Attachment expectations for standard forms. For\\n`revenue-contractor`, image attachments are expected so contractors can\\ninclude project photos. For `resume-submission`, the resume field\\nshould accept document uploads. Free-form questionnaires can omit this.\\n","properties":{"expected":{"type":"boolean","default":false,"description":"Whether the standard flow should prompt for attachments."},"required":{"type":"boolean","default":false,"description":"Whether at least one attachment is required."},"maxFiles":{"type":"integer","minimum":1,"maximum":20,"description":"Maximum number of files accepted.","example":5},"maxFileSizeBytes":{"type":"integer","minimum":1,"description":"Maximum size per file in bytes.","example":10485760},"accept":{"type":"array","description":"Accepted MIME types or extensions (for example `image/*`).","items":{"type":"string"}}}},"PublicSiteFormContact":{"type":"object","description":"Normalized contact identity supplied with a public form submission.","properties":{"name":{"type":"string","maxLength":160},"email":{"type":"string","format":"email","maxLength":255},"phone":{"type":"string","maxLength":32},"company":{"type":"string","maxLength":160}}},"PublicSiteFormAttachment":{"type":"object","description":"Metadata for an attachment associated with a public form submission.","required":["fileName"],"properties":{"fileName":{"type":"string","maxLength":255},"contentType":{"type":"string","maxLength":120},"sizeBytes":{"type":"integer","minimum":0},"storageUrl":{"type":"string","format":"uri","description":"Internal or pre-uploaded storage URL when the binary was uploaded separately."}}},"PublicSiteFormSubmissionRequest":{"type":"object","description":"JSON request for public managed-form submissions.","required":["values"],"properties":{"formKind":{"$ref":"#/definitions/PortalFormKind"},"pageSlug":{"type":"string","description":"Optional visual-editor page slug where the form was rendered."},"contact":{"$ref":"#/definitions/PublicSiteFormContact"},"subject":{"type":"string","maxLength":200,"description":"Contact subject or inquiry title."},"summary":{"type":"string","maxLength":4000,"description":"Project, request, or applicant summary for standard flows."},"message":{"type":"string","maxLength":4000,"description":"Free-text message supplied by the submitter."},"values":{"type":"object","additionalProperties":true,"description":"Field id to submitted value map for the attached PortalFormDefinition."},"attachments":{"type":"array","description":"Attachment metadata for JSON submissions.","items":{"$ref":"#/definitions/PublicSiteFormAttachment"}},"source":{"type":"string","maxLength":120,"description":"Capture source such as `site-contact-page` or `visual-page-editor`."},"consent":{"type":"boolean","description":"Whether the submitter consented to follow-up."}}},"PublicSiteFormMultipartSubmissionRequest":{"type":"object","description":"Multipart request for public managed-form submissions with binary uploads.","properties":{"formKind":{"$ref":"#/definitions/PortalFormKind"},"pageSlug":{"type":"string"},"values":{"type":"string","description":"JSON-encoded field id to submitted value map."},"name":{"type":"string","maxLength":160},"email":{"type":"string","format":"email","maxLength":255},"phone":{"type":"string","maxLength":32},"company":{"type":"string","maxLength":160},"subject":{"type":"string","maxLength":200},"summary":{"type":"string","maxLength":4000},"message":{"type":"string","maxLength":4000},"attachments":{"type":"array","description":"Image or supporting files for standard form submissions.","items":{"type":"string","format":"binary"}},"resume":{"type":"string","format":"binary","description":"Resume document for `resume-submission` standard forms."},"source":{"type":"string","maxLength":120},"consent":{"type":"boolean"}}},"PublicSiteFormSubmissionResponse":{"type":"object","required":["id","status","submittedAt"],"properties":{"id":{"type":"string","description":"Unique submission identifier."},"status":{"type":"string","enum":["submitted","accepted","queued"]},"submittedAt":{"type":"string","format":"date-time"},"message":{"type":"string","description":"Friendly acknowledgement shown to the submitter."},"contactMessageId":{"type":"string","nullable":true,"description":"Future portal contact-message identifier when surfaced in the portal."},"notificationQueued":{"type":"boolean","description":"Whether a portal notification/contact-message handoff was queued."}}},"PortalFormFieldType":{"type":"string","description":"Field type controlling input rendering and validation. Includes\\nlayout-only types (`section-heading`, `html-block`) that render\\ndecorative content rather than capturing values, and `hidden`\\nfor prefilled values not displayed to the user.\\n","enum":["text","email","tel","textarea","select","multiselect","radio","checkbox","checkbox-group","date","file","hidden","section-heading","html-block"]},"PortalFormFieldWidth":{"type":"string","description":"Layout hint for the field within its row.","enum":["full","half","third"]},"PortalFormFieldOption":{"type":"object","description":"A single option for select / radio / checkbox-group fields.","required":["value","label"],"properties":{"value":{"type":"string","description":"Submitted value for this option."},"label":{"type":"string","description":"Human-readable label shown to the user."}}},"PortalFormFieldValidation":{"type":"object","description":"Optional validation rules applied to a field\'s value.","properties":{"regex":{"type":"string","description":"ECMAScript-compatible pattern the value must match."},"minLength":{"type":"integer","minimum":0,"description":"Minimum string length (text-like fields only)."},"maxLength":{"type":"integer","minimum":0,"description":"Maximum string length (text-like fields only)."},"min":{"type":"number","description":"Minimum numeric / date value."},"max":{"type":"number","description":"Maximum numeric / date value."},"accept":{"type":"array","description":"Accepted MIME types or file extensions for `file` fields.","items":{"type":"string"}}}},"PortalFormFieldVisibleIf":{"type":"object","description":"Single-predicate visibility rule. The field is shown only when\\nthe referenced sibling field\'s value equals `equals`. Future\\nrevisions may extend this with AND / OR composition; clients\\nshould treat unknown extra properties as opaque.\\n","required":["fieldId","equals"],"properties":{"fieldId":{"type":"string","description":"ID of the sibling field whose value gates visibility."},"equals":{"description":"Value (string, number, or boolean) the sibling field must equal.","oneOf":[{"type":"string"},{"type":"number"},{"type":"boolean"}]}}},"PortalFormField":{"type":"object","description":"A single field within a form definition.","required":["id","type","label"],"properties":{"id":{"type":"string","description":"Kebab-case identifier, unique within the form.","pattern":"^[a-z0-9][a-z0-9-]*$","minLength":1,"maxLength":80},"type":{"$ref":"#/definitions/PortalFormFieldType"},"role":{"$ref":"#/definitions/PortalFormFieldRole"},"label":{"type":"string","description":"Human-readable label rendered above the input.","minLength":1,"maxLength":200},"helpText":{"type":"string","description":"Optional helper / description text shown beneath the label.","maxLength":500},"placeholder":{"type":"string","description":"Optional placeholder shown inside empty inputs.","maxLength":200},"defaultValue":{"description":"Optional default value (string, number, boolean, or array of strings).","oneOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"array","items":{"type":"string"}}]},"required":{"type":"boolean","default":false,"description":"Whether the field must be supplied to submit the form."},"width":{"allOf":[{"$ref":"#/definitions/PortalFormFieldWidth"}],"default":"full"},"options":{"type":"array","description":"Options for `select`, `multiselect`, `radio`, `checkbox-group` fields.","items":{"$ref":"#/definitions/PortalFormFieldOption"}},"validation":{"$ref":"#/definitions/PortalFormFieldValidation"},"visibleIf":{"$ref":"#/definitions/PortalFormFieldVisibleIf"},"phi":{"type":"boolean","default":false,"description":"Marks the field as collecting Protected Health Information.\\nWhen true the value must never appear in notification emails\\nor logs and the owning site must be in the Medical category\\n(see `compliance.instructions.md`).\\n"},"html":{"type":"string","description":"Sanitized HTML body for `html-block` fields. Ignored for\\nother field types.\\n","maxLength":10000}}},"PortalFormStep":{"type":"object","description":"Optional grouping for multi-step (wizard-style) forms such as\\nthe KT Braun estate-planning questionnaires. When `steps` is\\nomitted on a form, all fields render as a single page.\\n","required":["id","title","fieldIds"],"properties":{"id":{"type":"string","description":"Kebab-case step identifier, unique within the form.","pattern":"^[a-z0-9][a-z0-9-]*$","minLength":1,"maxLength":80},"title":{"type":"string","description":"Step title shown in the wizard header.","minLength":1,"maxLength":200},"description":{"type":"string","description":"Optional descriptive text shown below the step title.","maxLength":1000},"fieldIds":{"type":"array","description":"Ordered list of field IDs that belong to this step.","items":{"type":"string","pattern":"^[a-z0-9][a-z0-9-]*$"}}}},"PortalFormSubmissionLeadConfig":{"type":"object","required":["kind"],"description":"Routes submissions into the existing PortalLeads pipeline.","properties":{"kind":{"type":"string","enum":["lead"]},"category":{"type":"string","description":"Service category id used to route the lead."}}},"PortalFormSubmissionEmailConfig":{"type":"object","required":["kind","to"],"description":"Routes submissions as a notification email to the listed recipients.","properties":{"kind":{"type":"string","enum":["email"]},"to":{"type":"array","minItems":1,"items":{"type":"string","format":"email"},"description":"Recipient email addresses."},"subjectTemplate":{"type":"string","description":"Optional subject-line template. Submitted values are intentionally\\nnot interpolated into the subject line for compliance reasons.\\n","maxLength":200}}},"PortalFormSubmissionWebhookConfig":{"type":"object","required":["kind","url"],"description":"Posts the submission JSON to a third-party webhook.","properties":{"kind":{"type":"string","enum":["webhook"]},"url":{"type":"string","format":"uri","description":"HTTPS endpoint receiving the signed POST."},"signingSecretRef":{"type":"string","description":"Name of the Key Vault secret used to HMAC-sign the request.\\nThe secret value is never returned in API responses.\\n"}}},"PortalFormSubmissionConfig":{"description":"Discriminated union of submission destinations. Exactly one of\\n`lead`, `email`, or `webhook` shapes is used based on `kind`.\\n","oneOf":[{"$ref":"#/definitions/PortalFormSubmissionLeadConfig"},{"$ref":"#/definitions/PortalFormSubmissionEmailConfig"},{"$ref":"#/definitions/PortalFormSubmissionWebhookConfig"}],"discriminator":{"propertyName":"kind","mapping":{"lead":"#/definitions/PortalFormSubmissionLeadConfig","email":"#/definitions/PortalFormSubmissionEmailConfig","webhook":"#/definitions/PortalFormSubmissionWebhookConfig"}}},"PortalFormSummary":{"type":"object","description":"List-row projection of a form definition.","required":["formId","fieldCount"],"properties":{"formId":{"type":"string","description":"Kebab-case identifier.","pattern":"^[a-z0-9][a-z0-9-]*$","example":"contact"},"formKind":{"$ref":"#/definitions/PortalFormKind"},"fieldCount":{"type":"integer","minimum":0,"description":"Number of input-bearing fields in the form.","example":4},"attachedPageSlugs":{"type":"array","description":"Slugs of pages that currently reference this form via `formId`.","items":{"type":"string"}},"submissionKind":{"type":"string","enum":["lead","email","webhook"],"description":"Submission destination kind."},"lastUpdated":{"type":"string","format":"date-time","description":"Last modification timestamp."}}},"PortalCreateFormRequest":{"type":"object","description":"Payload for creating a new form definition.","required":["formId","submission","fields"],"properties":{"formId":{"type":"string","description":"Kebab-case identifier, unique per site.","pattern":"^[a-z0-9][a-z0-9-]*$","minLength":1,"maxLength":80},"formKind":{"$ref":"#/definitions/PortalFormKind"},"submitLabel":{"type":"string","maxLength":80},"successMessage":{"type":"string","maxLength":2000},"submission":{"$ref":"#/definitions/PortalFormSubmissionConfig"},"attachmentPolicy":{"$ref":"#/definitions/PortalFormAttachmentPolicy"},"steps":{"type":"array","items":{"$ref":"#/definitions/PortalFormStep"}},"fields":{"type":"array","items":{"$ref":"#/definitions/PortalFormField"}}}},"PortalUpdateFormRequest":{"type":"object","description":"Payload for updating an existing form definition. The `formId`\\nis taken from the URL; supplying it in the body is optional and,\\nif present, must match the path.\\n","properties":{"formId":{"type":"string","pattern":"^[a-z0-9][a-z0-9-]*$","minLength":1,"maxLength":80,"description":"Optional echo of the path formId; must match if provided."},"formKind":{"$ref":"#/definitions/PortalFormKind"},"submitLabel":{"type":"string","maxLength":80},"successMessage":{"type":"string","maxLength":2000},"submission":{"$ref":"#/definitions/PortalFormSubmissionConfig"},"attachmentPolicy":{"$ref":"#/definitions/PortalFormAttachmentPolicy"},"steps":{"type":"array","items":{"$ref":"#/definitions/PortalFormStep"}},"fields":{"type":"array","items":{"$ref":"#/definitions/PortalFormField"}},"expectedVersion":{"type":"integer","minimum":1,"description":"Optional optimistic-concurrency token. When supplied, the\\nupdate is rejected with 409 if the stored form\'s `version`\\nno longer matches.\\n"}}},"PortalDuplicateFormRequest":{"type":"object","description":"Payload for cloning an existing form under a new formId.","required":["formId"],"properties":{"formId":{"type":"string","description":"Target kebab-case formId for the cloned form.","pattern":"^[a-z0-9][a-z0-9-]*$","minLength":1,"maxLength":80}}},"PortalFormResponse":{"type":"object","description":"Full form definition response.","required":["form"],"properties":{"form":{"$ref":"#/definitions/PortalFormDefinition"},"attachedPageSlugs":{"type":"array","description":"Slugs of pages that currently reference this form via `formId`.","items":{"type":"string"}}}},"PortalFormListResponse":{"type":"object","required":["forms","totalCount"],"properties":{"forms":{"type":"array","items":{"$ref":"#/definitions/PortalFormSummary"}},"totalCount":{"type":"integer","minimum":0,"description":"Total number of forms matching the query.","example":3}}},"PortalFormSubmission":{"type":"object","description":"A single recorded submission against a managed form. PHI fields are\\nreplaced with `[REDACTED]` for Medical-category sites, in which case\\n`redactedForPhi` is true.\\n","required":["id","formId","siteSlug","submittedAt","source","values","redactedForPhi"],"properties":{"id":{"type":"string","description":"Unique submission row key (reverse-chronological)."},"formId":{"type":"string"},"siteSlug":{"type":"string"},"formKind":{"$ref":"#/definitions/PortalFormKind"},"submittedAt":{"type":"string","format":"date-time"},"source":{"type":"string","description":"Capture channel (e.g. `web`, `import`)."},"values":{"type":"object","additionalProperties":true,"description":"Field id → submitted value map. PHI values are redacted."},"attachments":{"type":"array","description":"Attachment metadata captured with the submission.","items":{"$ref":"#/definitions/PublicSiteFormAttachment"}},"leadId":{"type":"string","nullable":true,"description":"Cross-reference to the lead row created by the legacy capture flow."},"contactMessageId":{"type":"string","nullable":true,"description":"Future portal contact-message identifier when surfaced in the portal."},"redactedForPhi":{"type":"boolean","description":"True when one or more values were replaced with the PHI placeholder."},"remoteIp":{"type":"string","nullable":true},"userAgent":{"type":"string","nullable":true}}},"PortalFormSubmissionSummary":{"type":"object","description":"List-view representation of a submission.","required":["id","formId","submittedAt","redactedForPhi","summary"],"properties":{"id":{"type":"string"},"formId":{"type":"string"},"formKind":{"$ref":"#/definitions/PortalFormKind"},"submittedAt":{"type":"string","format":"date-time"},"redactedForPhi":{"type":"boolean"},"summary":{"type":"string","description":"Short single-line preview suitable for the portal list view."}}},"PortalFormSubmissionListResponse":{"type":"object","required":["submissions"],"properties":{"submissions":{"type":"array","items":{"$ref":"#/definitions/PortalFormSubmissionSummary"}}}}}'), Fe = {
|
|
212
212
|
$schema: me,
|
|
213
213
|
$id: fe,
|
|
214
214
|
title: pe,
|
|
215
215
|
type: he,
|
|
216
|
-
description:
|
|
216
|
+
description: ye,
|
|
217
217
|
required: be,
|
|
218
218
|
properties: ge,
|
|
219
|
-
definitions:
|
|
219
|
+
definitions: ve
|
|
220
220
|
};
|
|
221
|
-
let
|
|
222
|
-
function
|
|
223
|
-
if (
|
|
221
|
+
let O = null;
|
|
222
|
+
function xe() {
|
|
223
|
+
if (O) return O;
|
|
224
224
|
const e = new ie({
|
|
225
225
|
allErrors: !0,
|
|
226
226
|
strict: !1,
|
|
227
227
|
discriminator: !1
|
|
228
228
|
});
|
|
229
|
-
return re(e),
|
|
229
|
+
return re(e), O = e.compile(Fe), O;
|
|
230
230
|
}
|
|
231
|
-
function
|
|
232
|
-
const t =
|
|
233
|
-
return { valid:
|
|
231
|
+
function $e(e) {
|
|
232
|
+
const t = xe(), i = t(e);
|
|
233
|
+
return { valid: i, errors: i ? [] : t.errors ?? [] };
|
|
234
234
|
}
|
|
235
|
-
function
|
|
236
|
-
const
|
|
237
|
-
return !
|
|
235
|
+
function we(e, t, i) {
|
|
236
|
+
const r = $e(t);
|
|
237
|
+
return !r.valid && i && console.warn(
|
|
238
238
|
`[@duffcloudservices/site-forms] Form "${e}" failed schema validation:`,
|
|
239
|
-
|
|
240
|
-
),
|
|
239
|
+
r.errors
|
|
240
|
+
), r;
|
|
241
241
|
}
|
|
242
|
-
function
|
|
242
|
+
function ke(e) {
|
|
243
243
|
const t = {};
|
|
244
|
-
for (const [
|
|
245
|
-
const
|
|
246
|
-
|
|
244
|
+
for (const [i, r] of Object.entries(e)) {
|
|
245
|
+
const n = Se(i), l = Pe(r);
|
|
246
|
+
l && (t[l.formId ?? n] = l);
|
|
247
247
|
}
|
|
248
248
|
return t;
|
|
249
249
|
}
|
|
250
|
-
function
|
|
250
|
+
function Se(e) {
|
|
251
251
|
return (e.split("/").pop() ?? e).replace(/\.ya?ml$/i, "");
|
|
252
252
|
}
|
|
253
|
-
function
|
|
253
|
+
function Pe(e) {
|
|
254
254
|
if (!e) return null;
|
|
255
255
|
if (typeof e == "string")
|
|
256
|
-
return
|
|
256
|
+
return J.load(e);
|
|
257
257
|
if (typeof e == "object") {
|
|
258
258
|
const t = e.default;
|
|
259
259
|
return t && typeof t == "object" ? t : e;
|
|
260
260
|
}
|
|
261
261
|
return null;
|
|
262
262
|
}
|
|
263
|
-
function
|
|
264
|
-
return
|
|
263
|
+
function Pt(e) {
|
|
264
|
+
return J.load(e);
|
|
265
265
|
}
|
|
266
|
-
const
|
|
266
|
+
const Ie = ["data-form-field-key"], Le = ["for"], qe = {
|
|
267
267
|
key: 0,
|
|
268
268
|
"aria-hidden": "true",
|
|
269
269
|
class: "dcs-form-field__required"
|
|
270
|
-
},
|
|
270
|
+
}, Ce = {
|
|
271
271
|
key: 0,
|
|
272
272
|
class: "dcs-form-field__help"
|
|
273
|
-
},
|
|
273
|
+
}, Ve = {
|
|
274
274
|
key: 0,
|
|
275
275
|
class: "dcs-form-field__error",
|
|
276
276
|
role: "alert"
|
|
277
|
-
}, q = /* @__PURE__ */
|
|
277
|
+
}, q = /* @__PURE__ */ S({
|
|
278
278
|
__name: "DcsFormFieldWrapper",
|
|
279
279
|
props: {
|
|
280
280
|
field: {},
|
|
@@ -282,30 +282,30 @@ const Ve = ["data-form-field-key"], we = ["for"], qe = {
|
|
|
282
282
|
inputId: {}
|
|
283
283
|
},
|
|
284
284
|
setup(e) {
|
|
285
|
-
return (t,
|
|
285
|
+
return (t, i) => (d(), h("div", {
|
|
286
286
|
class: Z(["dcs-form-field", [`dcs-form-field--${e.field.type}`, `dcs-form-field--width-${e.field.width ?? "full"}`]]),
|
|
287
287
|
"data-form-field-key": e.field.id
|
|
288
288
|
}, [
|
|
289
|
-
|
|
290
|
-
e.field.type !== "checkbox" && e.field.type !== "hidden" && e.field.type !== "section-heading" && e.field.type !== "html-block" ? (
|
|
289
|
+
k(t.$slots, "label", {}, () => [
|
|
290
|
+
e.field.type !== "checkbox" && e.field.type !== "hidden" && e.field.type !== "section-heading" && e.field.type !== "html-block" ? (d(), h("label", {
|
|
291
291
|
key: 0,
|
|
292
292
|
for: e.inputId ?? `field-${e.field.id}`,
|
|
293
293
|
class: "dcs-form-field__label"
|
|
294
294
|
}, [
|
|
295
|
-
|
|
296
|
-
e.field.required ? (
|
|
297
|
-
], 8,
|
|
295
|
+
E(b(e.field.label) + " ", 1),
|
|
296
|
+
e.field.required ? (d(), h("span", qe, "*")) : w("", !0)
|
|
297
|
+
], 8, Le)) : w("", !0)
|
|
298
298
|
]),
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
e.field.helpText ? (
|
|
299
|
+
k(t.$slots, "default"),
|
|
300
|
+
k(t.$slots, "help", {}, () => [
|
|
301
|
+
e.field.helpText ? (d(), h("p", Ce, b(e.field.helpText), 1)) : w("", !0)
|
|
302
302
|
]),
|
|
303
|
-
|
|
304
|
-
e.error ? (
|
|
303
|
+
k(t.$slots, "error", {}, () => [
|
|
304
|
+
e.error ? (d(), h("p", Ve, b(e.error), 1)) : w("", !0)
|
|
305
305
|
])
|
|
306
|
-
], 10,
|
|
306
|
+
], 10, Ie));
|
|
307
307
|
}
|
|
308
|
-
}),
|
|
308
|
+
}), je = ["id", "type", "name", "value", "placeholder", "required", "aria-invalid", "aria-describedby"], H = /* @__PURE__ */ S({
|
|
309
309
|
__name: "DcsFormText",
|
|
310
310
|
props: {
|
|
311
311
|
field: {},
|
|
@@ -314,8 +314,8 @@ const Ve = ["data-form-field-key"], we = ["for"], qe = {
|
|
|
314
314
|
},
|
|
315
315
|
emits: ["update:modelValue", "blur"],
|
|
316
316
|
setup(e, { emit: t }) {
|
|
317
|
-
const
|
|
318
|
-
switch (
|
|
317
|
+
const i = e, r = t, n = f(() => `field-${i.field.id}`), l = f(() => {
|
|
318
|
+
switch (i.field.type) {
|
|
319
319
|
case "email":
|
|
320
320
|
return "email";
|
|
321
321
|
case "tel":
|
|
@@ -324,37 +324,37 @@ const Ve = ["data-form-field-key"], we = ["for"], qe = {
|
|
|
324
324
|
return "text";
|
|
325
325
|
}
|
|
326
326
|
});
|
|
327
|
-
return (s,
|
|
327
|
+
return (s, u) => (d(), L(q, {
|
|
328
328
|
field: e.field,
|
|
329
329
|
error: e.error,
|
|
330
|
-
"input-id":
|
|
330
|
+
"input-id": n.value
|
|
331
331
|
}, {
|
|
332
|
-
default:
|
|
333
|
-
|
|
334
|
-
id:
|
|
332
|
+
default: I(() => [
|
|
333
|
+
k(s.$slots, "input", {
|
|
334
|
+
id: n.value,
|
|
335
335
|
value: e.modelValue,
|
|
336
|
-
onInput: (a) =>
|
|
337
|
-
onBlur: () =>
|
|
336
|
+
onInput: (a) => r("update:modelValue", a.target.value),
|
|
337
|
+
onBlur: () => r("blur")
|
|
338
338
|
}, () => [
|
|
339
|
-
|
|
340
|
-
id:
|
|
339
|
+
y("input", {
|
|
340
|
+
id: n.value,
|
|
341
341
|
class: "dcs-form-input",
|
|
342
|
-
type:
|
|
342
|
+
type: l.value,
|
|
343
343
|
name: e.field.id,
|
|
344
344
|
value: e.modelValue ?? "",
|
|
345
345
|
placeholder: e.field.placeholder,
|
|
346
346
|
required: e.field.required,
|
|
347
347
|
"aria-invalid": !!e.error,
|
|
348
|
-
"aria-describedby": e.error ? `${
|
|
349
|
-
onInput:
|
|
350
|
-
onBlur:
|
|
351
|
-
}, null, 40,
|
|
348
|
+
"aria-describedby": e.error ? `${n.value}-error` : void 0,
|
|
349
|
+
onInput: u[0] || (u[0] = (a) => r("update:modelValue", a.target.value)),
|
|
350
|
+
onBlur: u[1] || (u[1] = (a) => r("blur"))
|
|
351
|
+
}, null, 40, je)
|
|
352
352
|
])
|
|
353
353
|
]),
|
|
354
354
|
_: 3
|
|
355
355
|
}, 8, ["field", "error", "input-id"]));
|
|
356
356
|
}
|
|
357
|
-
}),
|
|
357
|
+
}), De = ["id", "name", "placeholder", "required", "aria-invalid", "value"], Te = /* @__PURE__ */ S({
|
|
358
358
|
__name: "DcsFormTextarea",
|
|
359
359
|
props: {
|
|
360
360
|
field: {},
|
|
@@ -363,21 +363,21 @@ const Ve = ["data-form-field-key"], we = ["for"], qe = {
|
|
|
363
363
|
},
|
|
364
364
|
emits: ["update:modelValue", "blur"],
|
|
365
365
|
setup(e, { emit: t }) {
|
|
366
|
-
const
|
|
367
|
-
return (
|
|
366
|
+
const i = e, r = t, n = f(() => `field-${i.field.id}`);
|
|
367
|
+
return (l, s) => (d(), L(q, {
|
|
368
368
|
field: e.field,
|
|
369
369
|
error: e.error,
|
|
370
|
-
"input-id":
|
|
370
|
+
"input-id": n.value
|
|
371
371
|
}, {
|
|
372
|
-
default:
|
|
373
|
-
|
|
374
|
-
id:
|
|
372
|
+
default: I(() => [
|
|
373
|
+
k(l.$slots, "input", {
|
|
374
|
+
id: n.value,
|
|
375
375
|
value: e.modelValue,
|
|
376
|
-
onInput: (
|
|
377
|
-
onBlur: () =>
|
|
376
|
+
onInput: (u) => r("update:modelValue", u.target.value),
|
|
377
|
+
onBlur: () => r("blur")
|
|
378
378
|
}, () => [
|
|
379
|
-
|
|
380
|
-
id:
|
|
379
|
+
y("textarea", {
|
|
380
|
+
id: n.value,
|
|
381
381
|
class: "dcs-form-input dcs-form-textarea",
|
|
382
382
|
name: e.field.id,
|
|
383
383
|
placeholder: e.field.placeholder,
|
|
@@ -385,19 +385,19 @@ const Ve = ["data-form-field-key"], we = ["for"], qe = {
|
|
|
385
385
|
"aria-invalid": !!e.error,
|
|
386
386
|
rows: "5",
|
|
387
387
|
value: e.modelValue ?? "",
|
|
388
|
-
onInput: s[0] || (s[0] = (
|
|
389
|
-
onBlur: s[1] || (s[1] = (
|
|
390
|
-
}, null, 40,
|
|
388
|
+
onInput: s[0] || (s[0] = (u) => r("update:modelValue", u.target.value)),
|
|
389
|
+
onBlur: s[1] || (s[1] = (u) => r("blur"))
|
|
390
|
+
}, null, 40, De)
|
|
391
391
|
])
|
|
392
392
|
]),
|
|
393
393
|
_: 3
|
|
394
394
|
}, 8, ["field", "error", "input-id"]));
|
|
395
395
|
}
|
|
396
|
-
}),
|
|
396
|
+
}), Me = ["id", "name", "required", "multiple", "aria-invalid", "value"], Ae = {
|
|
397
397
|
key: 0,
|
|
398
398
|
value: "",
|
|
399
399
|
disabled: ""
|
|
400
|
-
},
|
|
400
|
+
}, Oe = ["value"], Ee = /* @__PURE__ */ S({
|
|
401
401
|
__name: "DcsFormSelect",
|
|
402
402
|
props: {
|
|
403
403
|
field: {},
|
|
@@ -406,51 +406,51 @@ const Ve = ["data-form-field-key"], we = ["for"], qe = {
|
|
|
406
406
|
},
|
|
407
407
|
emits: ["update:modelValue", "blur"],
|
|
408
408
|
setup(e, { emit: t }) {
|
|
409
|
-
const
|
|
410
|
-
function
|
|
411
|
-
const
|
|
412
|
-
if (
|
|
409
|
+
const i = e, r = t, n = f(() => `field-${i.field.id}`), l = f(() => i.field.type === "multiselect"), s = f(() => i.field.options ?? []);
|
|
410
|
+
function u(a) {
|
|
411
|
+
const o = a.target;
|
|
412
|
+
if (l.value) {
|
|
413
413
|
const m = [];
|
|
414
|
-
for (const g of Array.from(
|
|
415
|
-
|
|
414
|
+
for (const g of Array.from(o.selectedOptions)) m.push(g.value);
|
|
415
|
+
r("update:modelValue", m);
|
|
416
416
|
} else
|
|
417
|
-
|
|
417
|
+
r("update:modelValue", o.value);
|
|
418
418
|
}
|
|
419
|
-
return (a,
|
|
419
|
+
return (a, o) => (d(), L(q, {
|
|
420
420
|
field: e.field,
|
|
421
421
|
error: e.error,
|
|
422
|
-
"input-id":
|
|
422
|
+
"input-id": n.value
|
|
423
423
|
}, {
|
|
424
|
-
default:
|
|
425
|
-
|
|
426
|
-
id:
|
|
424
|
+
default: I(() => [
|
|
425
|
+
k(a.$slots, "input", {
|
|
426
|
+
id: n.value,
|
|
427
427
|
value: e.modelValue,
|
|
428
428
|
options: s.value,
|
|
429
|
-
onChange:
|
|
429
|
+
onChange: u
|
|
430
430
|
}, () => [
|
|
431
|
-
|
|
432
|
-
id:
|
|
431
|
+
y("select", {
|
|
432
|
+
id: n.value,
|
|
433
433
|
class: "dcs-form-input dcs-form-select",
|
|
434
434
|
name: e.field.id,
|
|
435
435
|
required: e.field.required,
|
|
436
|
-
multiple:
|
|
436
|
+
multiple: l.value,
|
|
437
437
|
"aria-invalid": !!e.error,
|
|
438
|
-
value: e.modelValue ?? (
|
|
439
|
-
onChange:
|
|
440
|
-
onBlur:
|
|
438
|
+
value: e.modelValue ?? (l.value ? [] : ""),
|
|
439
|
+
onChange: u,
|
|
440
|
+
onBlur: o[0] || (o[0] = (m) => r("blur"))
|
|
441
441
|
}, [
|
|
442
|
-
|
|
443
|
-
(
|
|
442
|
+
l.value ? w("", !0) : (d(), h("option", Ae, b(e.field.placeholder ?? "Select…"), 1)),
|
|
443
|
+
(d(!0), h(D, null, R(s.value, (m) => (d(), h("option", {
|
|
444
444
|
key: m.value,
|
|
445
445
|
value: m.value
|
|
446
|
-
}, b(m.label), 9,
|
|
447
|
-
], 40,
|
|
446
|
+
}, b(m.label), 9, Oe))), 128))
|
|
447
|
+
], 40, Me)
|
|
448
448
|
])
|
|
449
449
|
]),
|
|
450
450
|
_: 3
|
|
451
451
|
}, 8, ["field", "error", "input-id"]));
|
|
452
452
|
}
|
|
453
|
-
}),
|
|
453
|
+
}), Re = ["aria-required", "aria-invalid"], Ke = { class: "sr-only" }, ze = ["name", "value", "checked", "onChange"], Be = /* @__PURE__ */ S({
|
|
454
454
|
__name: "DcsFormRadio",
|
|
455
455
|
props: {
|
|
456
456
|
field: {},
|
|
@@ -459,39 +459,39 @@ const Ve = ["data-form-field-key"], we = ["for"], qe = {
|
|
|
459
459
|
},
|
|
460
460
|
emits: ["update:modelValue"],
|
|
461
461
|
setup(e, { emit: t }) {
|
|
462
|
-
const
|
|
463
|
-
return (s,
|
|
462
|
+
const i = e, r = t, n = f(() => `field-${i.field.id}`), l = f(() => i.field.options ?? []);
|
|
463
|
+
return (s, u) => (d(), L(q, {
|
|
464
464
|
field: e.field,
|
|
465
465
|
error: e.error,
|
|
466
|
-
"input-id":
|
|
466
|
+
"input-id": n.value
|
|
467
467
|
}, {
|
|
468
|
-
default:
|
|
469
|
-
|
|
468
|
+
default: I(() => [
|
|
469
|
+
y("fieldset", {
|
|
470
470
|
class: "dcs-form-radio-group",
|
|
471
471
|
role: "radiogroup",
|
|
472
472
|
"aria-required": e.field.required,
|
|
473
473
|
"aria-invalid": !!e.error
|
|
474
474
|
}, [
|
|
475
|
-
|
|
476
|
-
(
|
|
475
|
+
y("legend", Ke, b(e.field.label), 1),
|
|
476
|
+
(d(!0), h(D, null, R(l.value, (a) => (d(), h("label", {
|
|
477
477
|
key: a.value,
|
|
478
478
|
class: "dcs-form-radio"
|
|
479
479
|
}, [
|
|
480
|
-
|
|
480
|
+
y("input", {
|
|
481
481
|
type: "radio",
|
|
482
482
|
name: e.field.id,
|
|
483
483
|
value: a.value,
|
|
484
484
|
checked: e.modelValue === a.value,
|
|
485
|
-
onChange: (
|
|
486
|
-
}, null, 40,
|
|
487
|
-
|
|
485
|
+
onChange: (o) => r("update:modelValue", a.value)
|
|
486
|
+
}, null, 40, ze),
|
|
487
|
+
y("span", null, b(a.label), 1)
|
|
488
488
|
]))), 128))
|
|
489
|
-
], 8,
|
|
489
|
+
], 8, Re)
|
|
490
490
|
]),
|
|
491
491
|
_: 1
|
|
492
492
|
}, 8, ["field", "error", "input-id"]));
|
|
493
493
|
}
|
|
494
|
-
}),
|
|
494
|
+
}), Ne = ["aria-required", "aria-invalid"], We = { class: "sr-only" }, He = ["name", "value", "checked", "onChange"], Ue = /* @__PURE__ */ S({
|
|
495
495
|
__name: "DcsFormCheckboxGroup",
|
|
496
496
|
props: {
|
|
497
497
|
field: {},
|
|
@@ -500,45 +500,45 @@ const Ve = ["data-form-field-key"], we = ["for"], qe = {
|
|
|
500
500
|
},
|
|
501
501
|
emits: ["update:modelValue"],
|
|
502
502
|
setup(e, { emit: t }) {
|
|
503
|
-
const
|
|
504
|
-
function
|
|
503
|
+
const i = e, r = t, n = f(() => `field-${i.field.id}`), l = f(() => i.field.options ?? []), s = f(() => i.modelValue ?? []);
|
|
504
|
+
function u(a, o) {
|
|
505
505
|
const m = new Set(s.value);
|
|
506
|
-
|
|
506
|
+
o ? m.add(a) : m.delete(a), r("update:modelValue", Array.from(m));
|
|
507
507
|
}
|
|
508
|
-
return (a,
|
|
508
|
+
return (a, o) => (d(), L(q, {
|
|
509
509
|
field: e.field,
|
|
510
510
|
error: e.error,
|
|
511
|
-
"input-id":
|
|
511
|
+
"input-id": n.value
|
|
512
512
|
}, {
|
|
513
|
-
default:
|
|
514
|
-
|
|
513
|
+
default: I(() => [
|
|
514
|
+
y("fieldset", {
|
|
515
515
|
class: "dcs-form-checkbox-group",
|
|
516
516
|
"aria-required": e.field.required,
|
|
517
517
|
"aria-invalid": !!e.error
|
|
518
518
|
}, [
|
|
519
|
-
|
|
520
|
-
(
|
|
519
|
+
y("legend", We, b(e.field.label), 1),
|
|
520
|
+
(d(!0), h(D, null, R(l.value, (m) => (d(), h("label", {
|
|
521
521
|
key: m.value,
|
|
522
522
|
class: "dcs-form-checkbox"
|
|
523
523
|
}, [
|
|
524
|
-
|
|
524
|
+
y("input", {
|
|
525
525
|
type: "checkbox",
|
|
526
526
|
name: `${e.field.id}[]`,
|
|
527
527
|
value: m.value,
|
|
528
528
|
checked: s.value.includes(m.value),
|
|
529
|
-
onChange: (g) =>
|
|
530
|
-
}, null, 40,
|
|
531
|
-
|
|
529
|
+
onChange: (g) => u(m.value, g.target.checked)
|
|
530
|
+
}, null, 40, He),
|
|
531
|
+
y("span", null, b(m.label), 1)
|
|
532
532
|
]))), 128))
|
|
533
|
-
], 8,
|
|
533
|
+
], 8, Ne)
|
|
534
534
|
]),
|
|
535
535
|
_: 1
|
|
536
536
|
}, 8, ["field", "error", "input-id"]));
|
|
537
537
|
}
|
|
538
|
-
}),
|
|
538
|
+
}), Je = { class: "sr-only" }, _e = ["for"], Ge = ["id", "name", "checked", "required", "aria-invalid"], Ye = {
|
|
539
539
|
key: 0,
|
|
540
540
|
"aria-hidden": "true"
|
|
541
|
-
}, Qe = /* @__PURE__ */
|
|
541
|
+
}, Qe = /* @__PURE__ */ S({
|
|
542
542
|
__name: "DcsFormCheckbox",
|
|
543
543
|
props: {
|
|
544
544
|
field: {},
|
|
@@ -547,39 +547,39 @@ const Ve = ["data-form-field-key"], we = ["for"], qe = {
|
|
|
547
547
|
},
|
|
548
548
|
emits: ["update:modelValue"],
|
|
549
549
|
setup(e, { emit: t }) {
|
|
550
|
-
const
|
|
551
|
-
return (
|
|
550
|
+
const i = e, r = t, n = f(() => `field-${i.field.id}`);
|
|
551
|
+
return (l, s) => (d(), L(q, {
|
|
552
552
|
field: e.field,
|
|
553
553
|
error: e.error,
|
|
554
|
-
"input-id":
|
|
554
|
+
"input-id": n.value
|
|
555
555
|
}, {
|
|
556
|
-
label:
|
|
557
|
-
|
|
556
|
+
label: I(() => [
|
|
557
|
+
y("span", Je, b(e.field.label), 1)
|
|
558
558
|
]),
|
|
559
|
-
default:
|
|
560
|
-
|
|
559
|
+
default: I(() => [
|
|
560
|
+
y("label", {
|
|
561
561
|
class: "dcs-form-checkbox-single",
|
|
562
|
-
for:
|
|
562
|
+
for: n.value
|
|
563
563
|
}, [
|
|
564
|
-
|
|
565
|
-
id:
|
|
564
|
+
y("input", {
|
|
565
|
+
id: n.value,
|
|
566
566
|
type: "checkbox",
|
|
567
567
|
name: e.field.id,
|
|
568
568
|
checked: !!e.modelValue,
|
|
569
569
|
required: e.field.required,
|
|
570
570
|
"aria-invalid": !!e.error,
|
|
571
|
-
onChange: s[0] || (s[0] = (
|
|
571
|
+
onChange: s[0] || (s[0] = (u) => r("update:modelValue", u.target.checked))
|
|
572
572
|
}, null, 40, Ge),
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
e.field.required ? (
|
|
573
|
+
y("span", null, [
|
|
574
|
+
E(b(e.field.label), 1),
|
|
575
|
+
e.field.required ? (d(), h("span", Ye, " *")) : w("", !0)
|
|
576
576
|
])
|
|
577
|
-
], 8,
|
|
577
|
+
], 8, _e)
|
|
578
578
|
]),
|
|
579
579
|
_: 1
|
|
580
580
|
}, 8, ["field", "error", "input-id"]));
|
|
581
581
|
}
|
|
582
|
-
}), Xe = ["id", "name", "required", "aria-invalid", "value"], Ze = /* @__PURE__ */
|
|
582
|
+
}), Xe = ["id", "name", "required", "aria-invalid", "value"], Ze = /* @__PURE__ */ S({
|
|
583
583
|
__name: "DcsFormDate",
|
|
584
584
|
props: {
|
|
585
585
|
field: {},
|
|
@@ -588,29 +588,29 @@ const Ve = ["data-form-field-key"], we = ["for"], qe = {
|
|
|
588
588
|
},
|
|
589
589
|
emits: ["update:modelValue", "blur"],
|
|
590
590
|
setup(e, { emit: t }) {
|
|
591
|
-
const
|
|
592
|
-
return (
|
|
591
|
+
const i = e, r = t, n = f(() => `field-${i.field.id}`);
|
|
592
|
+
return (l, s) => (d(), L(q, {
|
|
593
593
|
field: e.field,
|
|
594
594
|
error: e.error,
|
|
595
|
-
"input-id":
|
|
595
|
+
"input-id": n.value
|
|
596
596
|
}, {
|
|
597
|
-
default:
|
|
598
|
-
|
|
599
|
-
id:
|
|
597
|
+
default: I(() => [
|
|
598
|
+
y("input", {
|
|
599
|
+
id: n.value,
|
|
600
600
|
class: "dcs-form-input dcs-form-date",
|
|
601
601
|
type: "date",
|
|
602
602
|
name: e.field.id,
|
|
603
603
|
required: e.field.required,
|
|
604
604
|
"aria-invalid": !!e.error,
|
|
605
605
|
value: e.modelValue ?? "",
|
|
606
|
-
onInput: s[0] || (s[0] = (
|
|
607
|
-
onBlur: s[1] || (s[1] = (
|
|
606
|
+
onInput: s[0] || (s[0] = (u) => r("update:modelValue", u.target.value)),
|
|
607
|
+
onBlur: s[1] || (s[1] = (u) => r("blur"))
|
|
608
608
|
}, null, 40, Xe)
|
|
609
609
|
]),
|
|
610
610
|
_: 1
|
|
611
611
|
}, 8, ["field", "error", "input-id"]));
|
|
612
612
|
}
|
|
613
|
-
}), et = ["id", "name", "required", "aria-invalid", "accept"], tt = /* @__PURE__ */
|
|
613
|
+
}), et = ["id", "name", "required", "aria-invalid", "accept"], tt = /* @__PURE__ */ S({
|
|
614
614
|
__name: "DcsFormFile",
|
|
615
615
|
props: {
|
|
616
616
|
field: {},
|
|
@@ -619,39 +619,39 @@ const Ve = ["data-form-field-key"], we = ["for"], qe = {
|
|
|
619
619
|
},
|
|
620
620
|
emits: ["update:modelValue"],
|
|
621
621
|
setup(e, { emit: t }) {
|
|
622
|
-
const
|
|
623
|
-
function s(
|
|
624
|
-
const a =
|
|
625
|
-
|
|
622
|
+
const i = e, r = t, n = f(() => `field-${i.field.id}`), l = f(() => (i.field.validation?.accept ?? []).join(","));
|
|
623
|
+
function s(u) {
|
|
624
|
+
const a = u.target;
|
|
625
|
+
r("update:modelValue", a.files?.[0]);
|
|
626
626
|
}
|
|
627
|
-
return (
|
|
627
|
+
return (u, a) => (d(), L(q, {
|
|
628
628
|
field: e.field,
|
|
629
629
|
error: e.error,
|
|
630
|
-
"input-id":
|
|
630
|
+
"input-id": n.value
|
|
631
631
|
}, {
|
|
632
|
-
default:
|
|
633
|
-
|
|
634
|
-
id:
|
|
632
|
+
default: I(() => [
|
|
633
|
+
y("input", {
|
|
634
|
+
id: n.value,
|
|
635
635
|
class: "dcs-form-input dcs-form-file",
|
|
636
636
|
type: "file",
|
|
637
637
|
name: e.field.id,
|
|
638
638
|
required: e.field.required,
|
|
639
639
|
"aria-invalid": !!e.error,
|
|
640
|
-
accept:
|
|
640
|
+
accept: l.value || void 0,
|
|
641
641
|
onChange: s
|
|
642
642
|
}, null, 40, et)
|
|
643
643
|
]),
|
|
644
644
|
_: 1
|
|
645
645
|
}, 8, ["field", "error", "input-id"]));
|
|
646
646
|
}
|
|
647
|
-
}), it = ["name", "value", "data-form-field-key"], rt = /* @__PURE__ */
|
|
647
|
+
}), it = ["name", "value", "data-form-field-key"], rt = /* @__PURE__ */ S({
|
|
648
648
|
__name: "DcsFormHidden",
|
|
649
649
|
props: {
|
|
650
650
|
field: {},
|
|
651
651
|
modelValue: {}
|
|
652
652
|
},
|
|
653
653
|
setup(e) {
|
|
654
|
-
return (t,
|
|
654
|
+
return (t, i) => (d(), h("input", {
|
|
655
655
|
type: "hidden",
|
|
656
656
|
name: e.field.id,
|
|
657
657
|
value: e.modelValue ?? e.field.defaultValue ?? "",
|
|
@@ -661,46 +661,43 @@ const Ve = ["data-form-field-key"], we = ["for"], qe = {
|
|
|
661
661
|
}), nt = ["data-form-field-key"], ot = { class: "dcs-form-section__heading" }, st = {
|
|
662
662
|
key: 0,
|
|
663
663
|
class: "dcs-form-section__help"
|
|
664
|
-
}, at = /* @__PURE__ */
|
|
664
|
+
}, at = /* @__PURE__ */ S({
|
|
665
665
|
__name: "DcsFormSection",
|
|
666
666
|
props: {
|
|
667
667
|
field: {}
|
|
668
668
|
},
|
|
669
669
|
setup(e) {
|
|
670
|
-
return (t,
|
|
670
|
+
return (t, i) => (d(), h("div", {
|
|
671
671
|
class: "dcs-form-section",
|
|
672
672
|
"data-form-field-key": e.field.id
|
|
673
673
|
}, [
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
e.field.helpText ? (
|
|
674
|
+
k(t.$slots, "default", {}, () => [
|
|
675
|
+
y("h3", ot, b(e.field.label), 1),
|
|
676
|
+
e.field.helpText ? (d(), h("p", st, b(e.field.helpText), 1)) : w("", !0)
|
|
677
677
|
])
|
|
678
678
|
], 8, nt));
|
|
679
679
|
}
|
|
680
|
-
}), lt = ["data-form-field-key", "innerHTML"], dt = /* @__PURE__ */
|
|
680
|
+
}), lt = ["data-form-field-key", "innerHTML"], dt = /* @__PURE__ */ S({
|
|
681
681
|
__name: "DcsFormHtmlBlock",
|
|
682
682
|
props: {
|
|
683
683
|
field: {}
|
|
684
684
|
},
|
|
685
685
|
setup(e) {
|
|
686
|
-
return (t,
|
|
686
|
+
return (t, i) => (d(), h("div", {
|
|
687
687
|
class: "dcs-form-html-block",
|
|
688
688
|
"data-form-field-key": e.field.id,
|
|
689
689
|
innerHTML: e.field.html ?? ""
|
|
690
690
|
}, null, 8, lt));
|
|
691
691
|
}
|
|
692
|
-
}), U = {}, ut = ["data-form-key"], ct = ["data-form-key"], mt = ["data-form-key"], ft = {
|
|
693
|
-
key: 0,
|
|
694
|
-
class: "dcs-form__description"
|
|
695
|
-
}, vt = {
|
|
692
|
+
}), U = {}, ut = ["data-form-key"], ct = ["data-form-key"], mt = ["data-form-key"], ft = {
|
|
696
693
|
key: 0,
|
|
697
694
|
class: "dcs-form__progress",
|
|
698
695
|
"aria-live": "polite"
|
|
699
|
-
},
|
|
696
|
+
}, pt = { class: "dcs-form__fields" }, ht = {
|
|
700
697
|
key: 1,
|
|
701
698
|
class: "dcs-form__submit-error",
|
|
702
699
|
role: "alert"
|
|
703
|
-
}, yt = { class: "dcs-form__actions" },
|
|
700
|
+
}, yt = { class: "dcs-form__actions" }, bt = ["disabled"], It = /* @__PURE__ */ S({
|
|
704
701
|
__name: "DcsForm",
|
|
705
702
|
props: {
|
|
706
703
|
formId: {},
|
|
@@ -712,48 +709,47 @@ const Ve = ["data-form-field-key"], we = ["for"], qe = {
|
|
|
712
709
|
},
|
|
713
710
|
emits: ["submit-success", "submit-error", "validation-error"],
|
|
714
711
|
setup(e, { emit: t }) {
|
|
715
|
-
const
|
|
716
|
-
() =>
|
|
717
|
-
), s =
|
|
718
|
-
|
|
712
|
+
const i = e, r = t, n = /* @__PURE__ */ Object.assign({}), l = f(
|
|
713
|
+
() => ke(i.formsModules ?? n)
|
|
714
|
+
), s = f(() => i.definitionOverride ? i.definitionOverride : l.value[i.formId] ?? null), u = !1;
|
|
715
|
+
N(
|
|
719
716
|
s,
|
|
720
|
-
(
|
|
721
|
-
|
|
717
|
+
(v) => {
|
|
718
|
+
v && we(i.formId, v, u);
|
|
722
719
|
},
|
|
723
720
|
{ immediate: !0 }
|
|
724
721
|
);
|
|
725
|
-
const a =
|
|
722
|
+
const a = f(
|
|
726
723
|
() => s.value ?? {
|
|
727
|
-
formId:
|
|
728
|
-
title: "",
|
|
724
|
+
formId: i.formId,
|
|
729
725
|
submission: { kind: "lead" },
|
|
730
726
|
fields: []
|
|
731
727
|
}
|
|
732
|
-
),
|
|
733
|
-
|
|
728
|
+
), o = ae({ definition: a.value });
|
|
729
|
+
N(
|
|
734
730
|
() => a.value,
|
|
735
|
-
() =>
|
|
731
|
+
() => o.reset()
|
|
736
732
|
);
|
|
737
|
-
const m =
|
|
738
|
-
() =>
|
|
739
|
-
), g =
|
|
740
|
-
() =>
|
|
741
|
-
),
|
|
733
|
+
const m = f(
|
|
734
|
+
() => i.apiBase ?? U?.VITE_DCS_PUBLIC_API ?? ""
|
|
735
|
+
), g = f(
|
|
736
|
+
() => i.siteSlug ?? U?.VITE_DCS_SITE_SLUG ?? ""
|
|
737
|
+
), $ = f(
|
|
742
738
|
() => a.value.submitLabel ?? "Send"
|
|
743
739
|
);
|
|
744
|
-
function
|
|
745
|
-
switch (
|
|
740
|
+
function C(v) {
|
|
741
|
+
switch (v.type) {
|
|
746
742
|
case "text":
|
|
747
743
|
case "email":
|
|
748
744
|
case "tel":
|
|
749
|
-
return
|
|
745
|
+
return H;
|
|
750
746
|
case "textarea":
|
|
751
|
-
return
|
|
747
|
+
return Te;
|
|
752
748
|
case "select":
|
|
753
749
|
case "multiselect":
|
|
754
|
-
return
|
|
750
|
+
return Ee;
|
|
755
751
|
case "radio":
|
|
756
|
-
return
|
|
752
|
+
return Be;
|
|
757
753
|
case "checkbox-group":
|
|
758
754
|
return Ue;
|
|
759
755
|
case "checkbox":
|
|
@@ -769,129 +765,287 @@ const Ve = ["data-form-field-key"], we = ["for"], qe = {
|
|
|
769
765
|
case "html-block":
|
|
770
766
|
return dt;
|
|
771
767
|
default:
|
|
772
|
-
return
|
|
768
|
+
return H;
|
|
773
769
|
}
|
|
774
770
|
}
|
|
775
|
-
const
|
|
776
|
-
async function
|
|
777
|
-
if (
|
|
778
|
-
if (!
|
|
779
|
-
|
|
771
|
+
const T = j(null);
|
|
772
|
+
async function K(v) {
|
|
773
|
+
if (v.preventDefault(), !s.value) return;
|
|
774
|
+
if (!o.validateAll()) {
|
|
775
|
+
r("validation-error", o.errors.value);
|
|
780
776
|
return;
|
|
781
777
|
}
|
|
782
|
-
|
|
783
|
-
const
|
|
784
|
-
formId:
|
|
785
|
-
values:
|
|
786
|
-
captchaToken:
|
|
778
|
+
o.submitting.value = !0, o.submitError.value = null;
|
|
779
|
+
const F = {
|
|
780
|
+
formId: i.formId,
|
|
781
|
+
values: o.collectSubmissionValues(),
|
|
782
|
+
captchaToken: i.captchaToken
|
|
787
783
|
};
|
|
788
784
|
try {
|
|
789
|
-
const
|
|
785
|
+
const P = await le({
|
|
790
786
|
apiBase: m.value,
|
|
791
787
|
siteSlug: g.value,
|
|
792
|
-
payload:
|
|
788
|
+
payload: F
|
|
793
789
|
});
|
|
794
|
-
|
|
795
|
-
} catch (
|
|
796
|
-
const
|
|
797
|
-
|
|
790
|
+
o.submitted.value = !0, r("submit-success", P);
|
|
791
|
+
} catch (P) {
|
|
792
|
+
const M = P;
|
|
793
|
+
o.submitError.value = M.error?.message ?? "Submission failed", r("submit-error", M);
|
|
798
794
|
} finally {
|
|
799
|
-
|
|
795
|
+
o.submitting.value = !1;
|
|
800
796
|
}
|
|
801
797
|
}
|
|
802
798
|
return ee(() => {
|
|
803
799
|
s.value || console.warn(
|
|
804
|
-
`[@duffcloudservices/site-forms] No form definition found for "${
|
|
800
|
+
`[@duffcloudservices/site-forms] No form definition found for "${i.formId}". Expected a YAML at .dcs/forms/${i.formId}.yaml. In customer-site repos the YAML lives above the Vite root, so the internal auto-glob will not find it — pass formsModules explicitly: <DcsForm form-id="${i.formId}" :forms-modules="dcsFormsModules" />. See @duffcloudservices/site-forms README "Vite setup" section.`
|
|
805
801
|
);
|
|
806
|
-
}), (
|
|
802
|
+
}), (v, V) => s.value ? c(o).submitted.value ? (d(), h("div", {
|
|
807
803
|
key: 1,
|
|
808
804
|
class: "dcs-form dcs-form--success",
|
|
809
805
|
"data-form-key": e.formId
|
|
810
806
|
}, [
|
|
811
|
-
|
|
812
|
-
|
|
807
|
+
k(v.$slots, "success", { definition: s.value }, () => [
|
|
808
|
+
y("p", null, b(s.value.successMessage ?? "Thanks — we received your message."), 1)
|
|
813
809
|
])
|
|
814
|
-
], 8, ct)) : (
|
|
810
|
+
], 8, ct)) : (d(), h("form", {
|
|
815
811
|
key: 2,
|
|
816
812
|
ref_key: "formEl",
|
|
817
|
-
ref:
|
|
813
|
+
ref: T,
|
|
818
814
|
class: "dcs-form",
|
|
819
815
|
"data-form-key": e.formId,
|
|
820
816
|
novalidate: "",
|
|
821
|
-
onSubmit:
|
|
817
|
+
onSubmit: K
|
|
822
818
|
}, [
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
u(n).steps.value ? (l(), f("div", vt, [
|
|
830
|
-
S(y.$slots, "progress", {
|
|
831
|
-
current: u(n).currentStepIndex.value,
|
|
832
|
-
total: u(n).steps.value.length,
|
|
833
|
-
step: u(n).currentStep.value
|
|
819
|
+
k(v.$slots, "header", { definition: s.value }),
|
|
820
|
+
c(o).steps.value ? (d(), h("div", ft, [
|
|
821
|
+
k(v.$slots, "progress", {
|
|
822
|
+
current: c(o).currentStepIndex.value,
|
|
823
|
+
total: c(o).steps.value.length,
|
|
824
|
+
step: c(o).currentStep.value
|
|
834
825
|
}, () => [
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
], 64)) :
|
|
826
|
+
y("p", null, [
|
|
827
|
+
E(" Step " + b(c(o).currentStepIndex.value + 1) + " of " + b(c(o).steps.value.length) + " ", 1),
|
|
828
|
+
c(o).currentStep.value ? (d(), h(D, { key: 0 }, [
|
|
829
|
+
E(" — " + b(c(o).currentStep.value.title), 1)
|
|
830
|
+
], 64)) : w("", !0)
|
|
840
831
|
])
|
|
841
832
|
])
|
|
842
|
-
])) :
|
|
843
|
-
|
|
844
|
-
(
|
|
845
|
-
key:
|
|
846
|
-
field:
|
|
847
|
-
"model-value":
|
|
848
|
-
error:
|
|
849
|
-
"onUpdate:modelValue": (
|
|
850
|
-
onBlur: (
|
|
833
|
+
])) : w("", !0),
|
|
834
|
+
y("div", pt, [
|
|
835
|
+
(d(!0), h(D, null, R(c(o).visibleFields.value, (F) => (d(), L(te(C(F)), {
|
|
836
|
+
key: F.id,
|
|
837
|
+
field: F,
|
|
838
|
+
"model-value": c(o).values[F.id],
|
|
839
|
+
error: c(o).errors.value[F.id],
|
|
840
|
+
"onUpdate:modelValue": (P) => c(o).setValue(F.id, P),
|
|
841
|
+
onBlur: (P) => c(o).touch(F.id)
|
|
851
842
|
}, null, 40, ["field", "model-value", "error", "onUpdate:modelValue", "onBlur"]))), 128))
|
|
852
843
|
]),
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
isFirstStep:
|
|
857
|
-
isLastStep:
|
|
858
|
-
submitting:
|
|
859
|
-
prev:
|
|
860
|
-
next:
|
|
844
|
+
c(o).submitError.value ? (d(), h("div", ht, b(c(o).submitError.value), 1)) : w("", !0),
|
|
845
|
+
y("div", yt, [
|
|
846
|
+
k(v.$slots, "actions", {
|
|
847
|
+
isFirstStep: c(o).isFirstStep.value,
|
|
848
|
+
isLastStep: c(o).isLastStep.value,
|
|
849
|
+
submitting: c(o).submitting.value,
|
|
850
|
+
prev: c(o).prev,
|
|
851
|
+
next: c(o).next
|
|
861
852
|
}, () => [
|
|
862
|
-
|
|
853
|
+
c(o).steps.value && !c(o).isFirstStep.value ? (d(), h("button", {
|
|
863
854
|
key: 0,
|
|
864
855
|
type: "button",
|
|
865
856
|
class: "dcs-form__btn dcs-form__btn--prev",
|
|
866
|
-
onClick:
|
|
867
|
-
}, " Previous ")) :
|
|
868
|
-
|
|
857
|
+
onClick: V[0] || (V[0] = (F) => c(o).prev())
|
|
858
|
+
}, " Previous ")) : w("", !0),
|
|
859
|
+
c(o).steps.value && !c(o).isLastStep.value ? (d(), h("button", {
|
|
869
860
|
key: 1,
|
|
870
861
|
type: "button",
|
|
871
862
|
class: "dcs-form__btn dcs-form__btn--next",
|
|
872
|
-
onClick:
|
|
873
|
-
}, " Next ")) :
|
|
874
|
-
!
|
|
863
|
+
onClick: V[1] || (V[1] = (F) => c(o).next())
|
|
864
|
+
}, " Next ")) : w("", !0),
|
|
865
|
+
!c(o).steps.value || c(o).isLastStep.value ? (d(), h("button", {
|
|
875
866
|
key: 2,
|
|
876
867
|
type: "submit",
|
|
877
868
|
class: "dcs-form__btn dcs-form__btn--submit",
|
|
878
|
-
disabled:
|
|
879
|
-
}, b(
|
|
869
|
+
disabled: c(o).submitting.value
|
|
870
|
+
}, b(c(o).submitting.value ? "Sending…" : $.value), 9, bt)) : w("", !0)
|
|
880
871
|
])
|
|
881
872
|
])
|
|
882
|
-
], 40, mt)) : (
|
|
873
|
+
], 40, mt)) : (d(), h("div", {
|
|
883
874
|
key: 0,
|
|
884
875
|
class: "dcs-form dcs-form--missing",
|
|
885
876
|
"data-form-key": e.formId
|
|
886
877
|
}, [
|
|
887
|
-
|
|
888
|
-
|
|
878
|
+
k(v.$slots, "missing", { formId: e.formId }, () => [
|
|
879
|
+
y("p", null, "Form “" + b(e.formId) + "” is not configured.", 1)
|
|
889
880
|
])
|
|
890
881
|
], 8, ut));
|
|
891
882
|
}
|
|
892
|
-
})
|
|
883
|
+
}), Lt = {
|
|
884
|
+
contact: {
|
|
885
|
+
label: "Contact",
|
|
886
|
+
description: "Canonical contact form with standard contact fields."
|
|
887
|
+
},
|
|
888
|
+
"revenue-contractor": {
|
|
889
|
+
label: "Revenue contractor",
|
|
890
|
+
description: "Contact fields plus a required project summary and optional image upload."
|
|
891
|
+
},
|
|
892
|
+
"resume-submission": {
|
|
893
|
+
label: "Resume submission",
|
|
894
|
+
description: "Candidate contact fields plus a required resume upload."
|
|
895
|
+
},
|
|
896
|
+
custom: {
|
|
897
|
+
label: "Custom / free-form",
|
|
898
|
+
description: "Flexible starter that stays fully editable for questionnaires and bespoke intake."
|
|
899
|
+
}
|
|
900
|
+
}, gt = () => [
|
|
901
|
+
{ id: "name", type: "text", role: "contact-name", label: "Full name", required: !0, width: "full" },
|
|
902
|
+
{ id: "email", type: "email", role: "contact-email", label: "Email", required: !0, width: "half" },
|
|
903
|
+
{ id: "phone", type: "tel", role: "contact-phone", label: "Phone", width: "half" },
|
|
904
|
+
{ id: "company", type: "text", role: "contact-company", label: "Company", width: "full" },
|
|
905
|
+
{
|
|
906
|
+
id: "message",
|
|
907
|
+
type: "textarea",
|
|
908
|
+
role: "message",
|
|
909
|
+
label: "How can we help?",
|
|
910
|
+
required: !0,
|
|
911
|
+
width: "full",
|
|
912
|
+
validation: { minLength: 10, maxLength: 2e3 }
|
|
913
|
+
}
|
|
914
|
+
], vt = () => [
|
|
915
|
+
{ id: "name", type: "text", role: "contact-name", label: "Full name", required: !0, width: "full" },
|
|
916
|
+
{ id: "email", type: "email", role: "contact-email", label: "Email", required: !0, width: "half" },
|
|
917
|
+
{ id: "phone", type: "tel", role: "contact-phone", label: "Phone", required: !0, width: "half" },
|
|
918
|
+
{ id: "company", type: "text", role: "contact-company", label: "Company", width: "full" },
|
|
919
|
+
{
|
|
920
|
+
id: "message",
|
|
921
|
+
type: "textarea",
|
|
922
|
+
role: "summary",
|
|
923
|
+
label: "Project summary",
|
|
924
|
+
helpText: "Tell us what you want built, repaired, or updated.",
|
|
925
|
+
required: !0,
|
|
926
|
+
width: "full",
|
|
927
|
+
validation: { minLength: 20, maxLength: 4e3 }
|
|
928
|
+
},
|
|
929
|
+
{
|
|
930
|
+
id: "project-image",
|
|
931
|
+
type: "file",
|
|
932
|
+
role: "image-attachments",
|
|
933
|
+
label: "Reference image",
|
|
934
|
+
helpText: "Optional. Upload one photo or inspiration image to help us understand the request.",
|
|
935
|
+
width: "full",
|
|
936
|
+
validation: { accept: ["image/*"] }
|
|
937
|
+
}
|
|
938
|
+
], Ft = () => [
|
|
939
|
+
{ id: "name", type: "text", role: "contact-name", label: "Full name", required: !0, width: "full" },
|
|
940
|
+
{ id: "email", type: "email", role: "contact-email", label: "Email", required: !0, width: "half" },
|
|
941
|
+
{ id: "phone", type: "tel", role: "contact-phone", label: "Phone", width: "half" },
|
|
942
|
+
{ id: "position", type: "text", label: "Role you are applying for", width: "full" },
|
|
943
|
+
{
|
|
944
|
+
id: "message",
|
|
945
|
+
type: "textarea",
|
|
946
|
+
role: "message",
|
|
947
|
+
label: "Anything else we should know?",
|
|
948
|
+
width: "full",
|
|
949
|
+
validation: { maxLength: 2e3 }
|
|
950
|
+
},
|
|
951
|
+
{
|
|
952
|
+
id: "resume",
|
|
953
|
+
type: "file",
|
|
954
|
+
role: "resume",
|
|
955
|
+
label: "Resume",
|
|
956
|
+
required: !0,
|
|
957
|
+
width: "full",
|
|
958
|
+
validation: {
|
|
959
|
+
accept: [
|
|
960
|
+
"application/pdf",
|
|
961
|
+
"application/msword",
|
|
962
|
+
"application/vnd.openxmlformats-officedocument.wordprocessingml.document"
|
|
963
|
+
]
|
|
964
|
+
}
|
|
965
|
+
}
|
|
966
|
+
], xt = () => [
|
|
967
|
+
{ id: "name", type: "text", label: "Full name", required: !0, width: "full" },
|
|
968
|
+
{ id: "email", type: "email", label: "Email", required: !0, width: "half" },
|
|
969
|
+
{ id: "phone", type: "tel", label: "Phone", width: "half" },
|
|
970
|
+
{
|
|
971
|
+
id: "message",
|
|
972
|
+
type: "textarea",
|
|
973
|
+
label: "Message",
|
|
974
|
+
required: !0,
|
|
975
|
+
width: "full",
|
|
976
|
+
validation: { minLength: 10, maxLength: 2e3 }
|
|
977
|
+
}
|
|
978
|
+
];
|
|
979
|
+
function qt(e, t = {}) {
|
|
980
|
+
switch (e ?? "custom") {
|
|
981
|
+
case "contact":
|
|
982
|
+
return {
|
|
983
|
+
formId: t.formId ?? "contact",
|
|
984
|
+
formKind: "contact",
|
|
985
|
+
submitLabel: t.submitLabel ?? "Send",
|
|
986
|
+
successMessage: t.successMessage ?? "Thanks — we’ll be in touch shortly.",
|
|
987
|
+
submission: {
|
|
988
|
+
kind: "lead",
|
|
989
|
+
...t.leadCategory ? { category: t.leadCategory } : {}
|
|
990
|
+
},
|
|
991
|
+
fields: gt()
|
|
992
|
+
};
|
|
993
|
+
case "revenue-contractor":
|
|
994
|
+
return {
|
|
995
|
+
formId: t.formId ?? "contact",
|
|
996
|
+
formKind: "revenue-contractor",
|
|
997
|
+
submitLabel: t.submitLabel ?? "Request estimate",
|
|
998
|
+
successMessage: t.successMessage ?? "Thanks — we’ll review your project and follow up soon.",
|
|
999
|
+
submission: {
|
|
1000
|
+
kind: "lead",
|
|
1001
|
+
...t.leadCategory ? { category: t.leadCategory } : {}
|
|
1002
|
+
},
|
|
1003
|
+
attachmentPolicy: {
|
|
1004
|
+
expected: !0,
|
|
1005
|
+
required: !1,
|
|
1006
|
+
maxFiles: 5,
|
|
1007
|
+
accept: ["image/*"]
|
|
1008
|
+
},
|
|
1009
|
+
fields: vt()
|
|
1010
|
+
};
|
|
1011
|
+
case "resume-submission":
|
|
1012
|
+
return {
|
|
1013
|
+
formId: t.formId ?? "resume",
|
|
1014
|
+
formKind: "resume-submission",
|
|
1015
|
+
submitLabel: t.submitLabel ?? "Submit resume",
|
|
1016
|
+
successMessage: t.successMessage ?? "Thanks — your application was received.",
|
|
1017
|
+
submission: {
|
|
1018
|
+
kind: "lead",
|
|
1019
|
+
...t.leadCategory ? { category: t.leadCategory } : {}
|
|
1020
|
+
},
|
|
1021
|
+
attachmentPolicy: {
|
|
1022
|
+
expected: !0,
|
|
1023
|
+
required: !0,
|
|
1024
|
+
maxFiles: 1,
|
|
1025
|
+
accept: [
|
|
1026
|
+
"application/pdf",
|
|
1027
|
+
"application/msword",
|
|
1028
|
+
"application/vnd.openxmlformats-officedocument.wordprocessingml.document"
|
|
1029
|
+
]
|
|
1030
|
+
},
|
|
1031
|
+
fields: Ft()
|
|
1032
|
+
};
|
|
1033
|
+
default:
|
|
1034
|
+
return {
|
|
1035
|
+
formId: t.formId ?? "custom-form",
|
|
1036
|
+
formKind: "freeform",
|
|
1037
|
+
submitLabel: t.submitLabel ?? "Send",
|
|
1038
|
+
successMessage: t.successMessage ?? "Thanks — we received your submission.",
|
|
1039
|
+
submission: {
|
|
1040
|
+
kind: "lead",
|
|
1041
|
+
...t.leadCategory ? { category: t.leadCategory } : {}
|
|
1042
|
+
},
|
|
1043
|
+
fields: xt()
|
|
1044
|
+
};
|
|
1045
|
+
}
|
|
1046
|
+
}
|
|
893
1047
|
export {
|
|
894
|
-
|
|
1048
|
+
It as DcsForm,
|
|
895
1049
|
Qe as DcsFormCheckbox,
|
|
896
1050
|
Ue as DcsFormCheckboxGroup,
|
|
897
1051
|
Ze as DcsFormDate,
|
|
@@ -899,20 +1053,22 @@ export {
|
|
|
899
1053
|
tt as DcsFormFile,
|
|
900
1054
|
rt as DcsFormHidden,
|
|
901
1055
|
dt as DcsFormHtmlBlock,
|
|
902
|
-
|
|
1056
|
+
Be as DcsFormRadio,
|
|
903
1057
|
at as DcsFormSection,
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
1058
|
+
Ee as DcsFormSelect,
|
|
1059
|
+
H as DcsFormText,
|
|
1060
|
+
Te as DcsFormTextarea,
|
|
1061
|
+
Lt as STANDARD_FORM_PRESET_META,
|
|
1062
|
+
qt as buildStandardFormDefinition,
|
|
907
1063
|
se as hasErrors,
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
1064
|
+
z as isFieldVisible,
|
|
1065
|
+
ke as loadFormDefinitions,
|
|
1066
|
+
Pt as parseFormYaml,
|
|
911
1067
|
le as submitFormValues,
|
|
912
1068
|
ae as useDcsForm,
|
|
913
1069
|
ne as validateField,
|
|
914
1070
|
oe as validateForm,
|
|
915
|
-
|
|
916
|
-
|
|
1071
|
+
$e as validateFormDefinition,
|
|
1072
|
+
we as warnIfInvalid
|
|
917
1073
|
};
|
|
918
1074
|
//# sourceMappingURL=index.js.map
|