@sonordev/site-kit 4.0.1 → 4.0.2
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/agent-manifest.json +6 -1
- package/dist/AnalyticsProvider-5SX4ZRGN.js +31 -0
- package/dist/{AnalyticsProvider-UE34SYF2.js.map → AnalyticsProvider-5SX4ZRGN.js.map} +1 -1
- package/dist/AnalyticsProvider-6DIRTRRA.mjs +10 -0
- package/dist/{AnalyticsProvider-NSXC6IOO.mjs.map → AnalyticsProvider-6DIRTRRA.mjs.map} +1 -1
- package/dist/ChatWidget-3SUC7HZA.js +20 -0
- package/dist/{ChatWidget-OW37OU3Z.js.map → ChatWidget-3SUC7HZA.js.map} +1 -1
- package/dist/ChatWidget-JTTERPI5.mjs +11 -0
- package/dist/{ChatWidget-ASWCGCJJ.mjs.map → ChatWidget-JTTERPI5.mjs.map} +1 -1
- package/dist/DatePicker-4WNKNNCV.mjs +4 -0
- package/dist/DatePicker-4WNKNNCV.mjs.map +1 -0
- package/dist/DatePicker-VPZR7RU3.js +13 -0
- package/dist/DatePicker-VPZR7RU3.js.map +1 -0
- package/dist/EngageWidget-3MDY2W5G.mjs +9 -0
- package/dist/{EngageWidget-67UZ3P5P.mjs.map → EngageWidget-3MDY2W5G.mjs.map} +1 -1
- package/dist/EngageWidget-YVAIP2NW.js +18 -0
- package/dist/{EngageWidget-MXOCMVBQ.js.map → EngageWidget-YVAIP2NW.js.map} +1 -1
- package/dist/FileField-PD52URLX.js +91 -0
- package/dist/FileField-PD52URLX.js.map +1 -0
- package/dist/FileField-XMBF3XCG.mjs +85 -0
- package/dist/FileField-XMBF3XCG.mjs.map +1 -0
- package/dist/{FormSpotlight-6MXGX6TU.mjs → FormSpotlight-72TYHDPV.mjs} +7 -6
- package/dist/FormSpotlight-72TYHDPV.mjs.map +1 -0
- package/dist/{FormSpotlight-LOR57ENP.js → FormSpotlight-AL6KGMGG.js} +20 -19
- package/dist/FormSpotlight-AL6KGMGG.js.map +1 -0
- package/dist/{FormStage-ZLZD5EW4.mjs → FormStage-GNBPJ7WX.mjs} +6 -6
- package/dist/FormStage-GNBPJ7WX.mjs.map +1 -0
- package/dist/{FormStage-H35FBWTX.js → FormStage-NLO52ER2.js} +16 -16
- package/dist/FormStage-NLO52ER2.js.map +1 -0
- package/dist/ManagedForm-2SYVMJY6.mjs +14 -0
- package/dist/ManagedForm-2SYVMJY6.mjs.map +1 -0
- package/dist/ManagedForm-XWN3TVQQ.js +23 -0
- package/dist/ManagedForm-XWN3TVQQ.js.map +1 -0
- package/dist/{SignalCore-HEXXYFSX.mjs → SignalCore-4NOVH33M.mjs} +5 -5
- package/dist/{SignalCore-HEXXYFSX.mjs.map → SignalCore-4NOVH33M.mjs.map} +1 -1
- package/dist/{SignalCore-EUMJIPDK.js → SignalCore-PD75O7GB.js} +11 -11
- package/dist/{SignalCore-EUMJIPDK.js.map → SignalCore-PD75O7GB.js.map} +1 -1
- package/dist/SitemapSync-KKUF43DS.js +17 -0
- package/dist/{SitemapSync-HKUEDDG6.js.map → SitemapSync-KKUF43DS.js.map} +1 -1
- package/dist/SitemapSync-UH6VZ55T.mjs +8 -0
- package/dist/{SitemapSync-T4QDPMFG.mjs.map → SitemapSync-UH6VZ55T.mjs.map} +1 -1
- package/dist/analytics/index.js +9 -9
- package/dist/analytics/index.mjs +4 -4
- package/dist/{chunk-ZGQUIL7L.js → chunk-2ACKOMAL.js} +105 -514
- package/dist/chunk-2ACKOMAL.js.map +1 -0
- package/dist/{chunk-L5Q2ZJJM.js → chunk-2MIOQYF5.js} +6 -6
- package/dist/{chunk-L5Q2ZJJM.js.map → chunk-2MIOQYF5.js.map} +1 -1
- package/dist/{chunk-XCCW4Y3B.mjs → chunk-53RHVKTD.mjs} +5 -5
- package/dist/{chunk-XCCW4Y3B.mjs.map → chunk-53RHVKTD.mjs.map} +1 -1
- package/dist/{chunk-VL2WAC22.js → chunk-5QVXHD6V.js} +14 -14
- package/dist/{chunk-VL2WAC22.js.map → chunk-5QVXHD6V.js.map} +1 -1
- package/dist/{chunk-QABZPSHD.js → chunk-62Z4D3QR.js} +5 -5
- package/dist/{chunk-QABZPSHD.js.map → chunk-62Z4D3QR.js.map} +1 -1
- package/dist/{chunk-PVE6G5XQ.mjs → chunk-6PNWJXAE.mjs} +3 -3
- package/dist/{chunk-PVE6G5XQ.mjs.map → chunk-6PNWJXAE.mjs.map} +1 -1
- package/dist/{chunk-DG34TZ6T.mjs → chunk-6ZFXASW6.mjs} +4 -4
- package/dist/{chunk-DG34TZ6T.mjs.map → chunk-6ZFXASW6.mjs.map} +1 -1
- package/dist/{chunk-YNIZKOEW.js → chunk-A624YYDG.js} +2 -2
- package/dist/{chunk-YNIZKOEW.js.map → chunk-A624YYDG.js.map} +1 -1
- package/dist/chunk-AJNT5GCU.mjs +183 -0
- package/dist/chunk-AJNT5GCU.mjs.map +1 -0
- package/dist/chunk-AQA4PFMJ.mjs +44 -0
- package/dist/chunk-AQA4PFMJ.mjs.map +1 -0
- package/dist/{chunk-62QRWS2I.mjs → chunk-B7J7SU5A.mjs} +8 -8
- package/dist/{chunk-62QRWS2I.mjs.map → chunk-B7J7SU5A.mjs.map} +1 -1
- package/dist/chunk-DVYYGHSG.js +285 -0
- package/dist/chunk-DVYYGHSG.js.map +1 -0
- package/dist/{chunk-5GPFPMDQ.mjs → chunk-FGN27J35.mjs} +4 -4
- package/dist/{chunk-5GPFPMDQ.mjs.map → chunk-FGN27J35.mjs.map} +1 -1
- package/dist/{chunk-Z74IVGJB.mjs → chunk-FZ643CZK.mjs} +4 -4
- package/dist/{chunk-Z74IVGJB.mjs.map → chunk-FZ643CZK.mjs.map} +1 -1
- package/dist/{chunk-2LKWN26R.mjs → chunk-GCS4XZHC.mjs} +3 -3
- package/dist/{chunk-2LKWN26R.mjs.map → chunk-GCS4XZHC.mjs.map} +1 -1
- package/dist/{chunk-6535RSF5.mjs → chunk-HOB2A6JM.mjs} +3 -3
- package/dist/{chunk-6535RSF5.mjs.map → chunk-HOB2A6JM.mjs.map} +1 -1
- package/dist/{chunk-CTZHLX2B.mjs → chunk-JFVEKSZT.mjs} +5 -182
- package/dist/chunk-JFVEKSZT.mjs.map +1 -0
- package/dist/{chunk-JGTIVQIN.mjs → chunk-KNYK2VLX.mjs} +3 -3
- package/dist/{chunk-JGTIVQIN.mjs.map → chunk-KNYK2VLX.mjs.map} +1 -1
- package/dist/{chunk-LYDTOFXJ.mjs → chunk-LB7LHVWI.mjs} +107 -503
- package/dist/chunk-LB7LHVWI.mjs.map +1 -0
- package/dist/{chunk-RZW4XVG5.js → chunk-LP6MC2RH.js} +14 -14
- package/dist/{chunk-RZW4XVG5.js.map → chunk-LP6MC2RH.js.map} +1 -1
- package/dist/chunk-LVCUT2OX.js +148 -0
- package/dist/chunk-LVCUT2OX.js.map +1 -0
- package/dist/chunk-LYAU5PRS.js +8 -0
- package/dist/{chunk-34WY5XN2.js.map → chunk-LYAU5PRS.js.map} +1 -1
- package/dist/{chunk-WHGVQJG4.js → chunk-MPACJDDG.js} +8 -8
- package/dist/{chunk-WHGVQJG4.js.map → chunk-MPACJDDG.js.map} +1 -1
- package/dist/{chunk-NDB7EIOI.js → chunk-MRRTAJWQ.js} +3 -3
- package/dist/{chunk-NDB7EIOI.js.map → chunk-MRRTAJWQ.js.map} +1 -1
- package/dist/chunk-MU3D5IO7.mjs +283 -0
- package/dist/chunk-MU3D5IO7.mjs.map +1 -0
- package/dist/chunk-MZY3MEUO.mjs +138 -0
- package/dist/chunk-MZY3MEUO.mjs.map +1 -0
- package/dist/chunk-NCWVR4BU.mjs +508 -0
- package/dist/chunk-NCWVR4BU.mjs.map +1 -0
- package/dist/{chunk-52K556WM.js → chunk-NJN467OM.js} +14 -14
- package/dist/{chunk-52K556WM.js.map → chunk-NJN467OM.js.map} +1 -1
- package/dist/{chunk-MJY7LYOV.mjs → chunk-NWJX6NHR.mjs} +4 -4
- package/dist/{chunk-MJY7LYOV.mjs.map → chunk-NWJX6NHR.mjs.map} +1 -1
- package/dist/chunk-NWPNFCNY.js +511 -0
- package/dist/chunk-NWPNFCNY.js.map +1 -0
- package/dist/{chunk-NU5DJUVI.js → chunk-OP5FYTWJ.js} +12 -192
- package/dist/chunk-OP5FYTWJ.js.map +1 -0
- package/dist/{chunk-YGWWLTH5.js → chunk-PGND73EV.js} +4 -4
- package/dist/{chunk-YGWWLTH5.js.map → chunk-PGND73EV.js.map} +1 -1
- package/dist/chunk-QO5NS62X.js +46 -0
- package/dist/chunk-QO5NS62X.js.map +1 -0
- package/dist/chunk-QTN3F7D7.mjs +6 -0
- package/dist/{chunk-6GFEJH4F.mjs.map → chunk-QTN3F7D7.mjs.map} +1 -1
- package/dist/chunk-R4PCXP3F.mjs +60 -0
- package/dist/chunk-R4PCXP3F.mjs.map +1 -0
- package/dist/{chunk-Q7HLRTZA.js → chunk-RAX3HS4T.js} +15 -15
- package/dist/{chunk-Q7HLRTZA.js.map → chunk-RAX3HS4T.js.map} +1 -1
- package/dist/{chunk-I424AZPT.js → chunk-T2YAEBEY.js} +4 -4
- package/dist/{chunk-I424AZPT.js.map → chunk-T2YAEBEY.js.map} +1 -1
- package/dist/{chunk-6SHBMFYM.mjs → chunk-T5DXYGWK.mjs} +3 -3
- package/dist/{chunk-6SHBMFYM.mjs.map → chunk-T5DXYGWK.mjs.map} +1 -1
- package/dist/{chunk-KHJYA64F.mjs → chunk-U2CJZ6O5.mjs} +2 -2
- package/dist/{chunk-KHJYA64F.mjs.map → chunk-U2CJZ6O5.mjs.map} +1 -1
- package/dist/{chunk-XAMUTD4I.mjs → chunk-UBNVD567.mjs} +3 -3
- package/dist/{chunk-XAMUTD4I.mjs.map → chunk-UBNVD567.mjs.map} +1 -1
- package/dist/chunk-UQPUFRXF.mjs +104 -0
- package/dist/chunk-UQPUFRXF.mjs.map +1 -0
- package/dist/chunk-VLY3SFNH.js +64 -0
- package/dist/chunk-VLY3SFNH.js.map +1 -0
- package/dist/{chunk-DPTNQVMK.mjs → chunk-VUIQLKJB.mjs} +3 -3
- package/dist/{chunk-DPTNQVMK.mjs.map → chunk-VUIQLKJB.mjs.map} +1 -1
- package/dist/chunk-WHVUSVHA.js +110 -0
- package/dist/chunk-WHVUSVHA.js.map +1 -0
- package/dist/{chunk-QXIVUWQZ.js → chunk-WNNY2BCV.js} +8 -8
- package/dist/{chunk-QXIVUWQZ.js.map → chunk-WNNY2BCV.js.map} +1 -1
- package/dist/{chunk-EDFZ6EMM.js → chunk-WXKEYKE6.js} +15 -15
- package/dist/{chunk-EDFZ6EMM.js.map → chunk-WXKEYKE6.js.map} +1 -1
- package/dist/{chunk-4JEJTQYC.mjs → chunk-XNPITFJ5.mjs} +3 -3
- package/dist/{chunk-4JEJTQYC.mjs.map → chunk-XNPITFJ5.mjs.map} +1 -1
- package/dist/{chunk-OIBQYBEL.mjs → chunk-XRC3JZAK.mjs} +3 -3
- package/dist/{chunk-OIBQYBEL.mjs.map → chunk-XRC3JZAK.mjs.map} +1 -1
- package/dist/{chunk-CBUK2XB3.js → chunk-Y26LKDE4.js} +9 -9
- package/dist/{chunk-CBUK2XB3.js.map → chunk-Y26LKDE4.js.map} +1 -1
- package/dist/{chunk-LDRE2ELU.js → chunk-ZK5VSIRO.js} +12 -12
- package/dist/{chunk-LDRE2ELU.js.map → chunk-ZK5VSIRO.js.map} +1 -1
- package/dist/{chunk-62RQTXHX.js → chunk-ZPG4GTU7.js} +5 -5
- package/dist/{chunk-62RQTXHX.js.map → chunk-ZPG4GTU7.js.map} +1 -1
- package/dist/chunk-ZRGCKWIT.js +188 -0
- package/dist/chunk-ZRGCKWIT.js.map +1 -0
- package/dist/cli/index.js +3 -3
- package/dist/cli/index.mjs +1 -1
- package/dist/client/index.js +5 -5
- package/dist/client/index.mjs +4 -4
- package/dist/commerce/index.js +56 -56
- package/dist/commerce/index.mjs +5 -5
- package/dist/engage/index.js +10 -9
- package/dist/engage/index.js.map +1 -1
- package/dist/engage/index.mjs +7 -6
- package/dist/engage/index.mjs.map +1 -1
- package/dist/fleet/index.js +9 -9
- package/dist/fleet/index.mjs +5 -5
- package/dist/forms/FileField.d.ts +31 -0
- package/dist/forms/FileField.d.ts.map +1 -0
- package/dist/forms/FormClient.d.ts +10 -1
- package/dist/forms/FormClient.d.ts.map +1 -1
- package/dist/forms/FormEnhancer.d.ts +72 -0
- package/dist/forms/FormEnhancer.d.ts.map +1 -0
- package/dist/forms/FormField.d.ts +26 -3
- package/dist/forms/FormField.d.ts.map +1 -1
- package/dist/forms/FormSpotlight.d.ts.map +1 -1
- package/dist/forms/FormStage.d.ts.map +1 -1
- package/dist/forms/HoneypotField.d.ts +8 -2
- package/dist/forms/HoneypotField.d.ts.map +1 -1
- package/dist/forms/ManagedForm.d.ts +1 -1
- package/dist/forms/ManagedForm.d.ts.map +1 -1
- package/dist/forms/ServerForm.d.ts +73 -0
- package/dist/forms/ServerForm.d.ts.map +1 -0
- package/dist/forms/StaticForm.d.ts +50 -0
- package/dist/forms/StaticForm.d.ts.map +1 -0
- package/dist/forms/field-controls.d.ts +7 -0
- package/dist/forms/field-controls.d.ts.map +1 -0
- package/dist/forms/index.d.ts +7 -0
- package/dist/forms/index.d.ts.map +1 -1
- package/dist/forms/index.js +33 -557
- package/dist/forms/index.js.map +1 -1
- package/dist/forms/index.mjs +14 -550
- package/dist/forms/index.mjs.map +1 -1
- package/dist/forms/normalize-config.d.ts +18 -0
- package/dist/forms/normalize-config.d.ts.map +1 -0
- package/dist/forms/server.d.ts +5 -0
- package/dist/forms/server.d.ts.map +1 -1
- package/dist/forms/server.js +47 -0
- package/dist/forms/server.js.map +1 -1
- package/dist/forms/server.mjs +44 -1
- package/dist/forms/server.mjs.map +1 -1
- package/dist/forms/static-form.test.d.ts +2 -0
- package/dist/forms/static-form.test.d.ts.map +1 -0
- package/dist/forms/static.d.ts +17 -0
- package/dist/forms/static.d.ts.map +1 -0
- package/dist/forms/static.js +20 -0
- package/dist/forms/static.js.map +1 -0
- package/dist/forms/static.mjs +11 -0
- package/dist/forms/static.mjs.map +1 -0
- package/dist/forms/types.d.ts +7 -0
- package/dist/forms/types.d.ts.map +1 -1
- package/dist/forms/useForm.d.ts.map +1 -1
- package/dist/images/index.js +11 -11
- package/dist/images/index.mjs +4 -4
- package/dist/index.js +109 -109
- package/dist/index.mjs +9 -9
- package/dist/layout/client.js +9 -9
- package/dist/layout/client.mjs +8 -8
- package/dist/layout/index.js +11 -11
- package/dist/layout/index.mjs +9 -9
- package/dist/maps/index.js +5 -5
- package/dist/maps/index.mjs +3 -3
- package/dist/search/index.js +4 -4
- package/dist/search/index.mjs +3 -3
- package/dist/seo/client.js +5 -5
- package/dist/seo/client.mjs +4 -4
- package/dist/seo/index.js +14 -14
- package/dist/seo/index.mjs +6 -6
- package/dist/seo/server.js +5 -5
- package/dist/seo/server.mjs +1 -1
- package/dist/server/index.js +3 -3
- package/dist/server/index.mjs +2 -2
- package/dist/shared/build-entries.d.ts +6 -0
- package/dist/shared/build-entries.d.ts.map +1 -1
- package/dist/shared/version.d.ts +1 -1
- package/dist/signal/index.js +11 -11
- package/dist/signal/index.mjs +2 -2
- package/dist/sync/index.js +16 -16
- package/dist/sync/index.mjs +4 -4
- package/package.json +9 -4
- package/dist/AnalyticsProvider-NSXC6IOO.mjs +0 -10
- package/dist/AnalyticsProvider-UE34SYF2.js +0 -31
- package/dist/ChatWidget-ASWCGCJJ.mjs +0 -10
- package/dist/ChatWidget-OW37OU3Z.js +0 -19
- package/dist/EngageWidget-67UZ3P5P.mjs +0 -9
- package/dist/EngageWidget-MXOCMVBQ.js +0 -18
- package/dist/FormSpotlight-6MXGX6TU.mjs.map +0 -1
- package/dist/FormSpotlight-LOR57ENP.js.map +0 -1
- package/dist/FormStage-H35FBWTX.js.map +0 -1
- package/dist/FormStage-ZLZD5EW4.mjs.map +0 -1
- package/dist/SitemapSync-HKUEDDG6.js +0 -17
- package/dist/SitemapSync-T4QDPMFG.mjs +0 -8
- package/dist/chunk-34WY5XN2.js +0 -8
- package/dist/chunk-6GFEJH4F.mjs +0 -6
- package/dist/chunk-CTZHLX2B.mjs.map +0 -1
- package/dist/chunk-LYDTOFXJ.mjs.map +0 -1
- package/dist/chunk-NU5DJUVI.js.map +0 -1
- package/dist/chunk-ZGQUIL7L.js.map +0 -1
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { useMemo, useState, useRef, useEffect } from 'react';
|
|
3
|
+
|
|
4
|
+
// src/forms/field-controls.ts
|
|
5
|
+
var NO_CONTROLS = {};
|
|
6
|
+
function useFieldControls(fields) {
|
|
7
|
+
const needsDate = useMemo(
|
|
8
|
+
() => (fields ?? []).some((f) => f.field_type === "date" || f.field_type === "datetime"),
|
|
9
|
+
[fields]
|
|
10
|
+
);
|
|
11
|
+
const needsFile = useMemo(
|
|
12
|
+
() => (fields ?? []).some((f) => f.field_type === "file"),
|
|
13
|
+
[fields]
|
|
14
|
+
);
|
|
15
|
+
const [controls, setControls] = useState(NO_CONTROLS);
|
|
16
|
+
const requested = useRef({ date: false, file: false });
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
let cancelled = false;
|
|
19
|
+
if (needsDate && !requested.current.date) {
|
|
20
|
+
requested.current.date = true;
|
|
21
|
+
import('./DatePicker-4WNKNNCV.mjs').then((m) => {
|
|
22
|
+
if (!cancelled) setControls((prev) => ({ ...prev, Date: m.DatePicker }));
|
|
23
|
+
}).catch(() => {
|
|
24
|
+
requested.current.date = false;
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
if (needsFile && !requested.current.file) {
|
|
28
|
+
requested.current.file = true;
|
|
29
|
+
import('./FileField-XMBF3XCG.mjs').then((m) => {
|
|
30
|
+
if (!cancelled) setControls((prev) => ({ ...prev, File: m.FileField }));
|
|
31
|
+
}).catch(() => {
|
|
32
|
+
requested.current.file = false;
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
return () => {
|
|
36
|
+
cancelled = true;
|
|
37
|
+
};
|
|
38
|
+
}, [needsDate, needsFile]);
|
|
39
|
+
return controls;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// src/forms/experience-plan.ts
|
|
43
|
+
var NON_QUESTION_TYPES = ["heading", "section_header", "paragraph", "hidden"];
|
|
44
|
+
function stageQuestions(config) {
|
|
45
|
+
const input = (config.fields || []).filter(
|
|
46
|
+
(f) => !NON_QUESTION_TYPES.includes(f.field_type)
|
|
47
|
+
);
|
|
48
|
+
if (!config.is_multi_step || !config.steps?.length) {
|
|
49
|
+
return input.map((field) => ({ field }));
|
|
50
|
+
}
|
|
51
|
+
const ordered = [...config.steps].sort((a, b) => a.step_number - b.step_number);
|
|
52
|
+
const out = [];
|
|
53
|
+
const claimed = /* @__PURE__ */ new Set();
|
|
54
|
+
for (const step of ordered) {
|
|
55
|
+
for (const field of input) {
|
|
56
|
+
if (field.step_id === step.id) {
|
|
57
|
+
out.push({ field, step });
|
|
58
|
+
claimed.add(field.id);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
for (const field of input) {
|
|
63
|
+
if (!claimed.has(field.id)) out.push({ field });
|
|
64
|
+
}
|
|
65
|
+
return out;
|
|
66
|
+
}
|
|
67
|
+
var WIDTH_FRACTION = {
|
|
68
|
+
full: 1,
|
|
69
|
+
half: 1 / 2,
|
|
70
|
+
third: 1 / 3,
|
|
71
|
+
quarter: 1 / 4
|
|
72
|
+
};
|
|
73
|
+
function stageViews(config) {
|
|
74
|
+
const questions = stageQuestions(config);
|
|
75
|
+
const views = [];
|
|
76
|
+
let open = null;
|
|
77
|
+
let openWidth = 0;
|
|
78
|
+
const close = () => {
|
|
79
|
+
if (open) views.push(open);
|
|
80
|
+
open = null;
|
|
81
|
+
openWidth = 0;
|
|
82
|
+
};
|
|
83
|
+
for (const q of questions) {
|
|
84
|
+
const fraction = WIDTH_FRACTION[q.field.width] ?? 1;
|
|
85
|
+
const chapterChanged = open && open.step?.id !== q.step?.id;
|
|
86
|
+
if (fraction >= 1 || chapterChanged) close();
|
|
87
|
+
if (!open) {
|
|
88
|
+
open = { fields: [q.field], step: q.step };
|
|
89
|
+
openWidth = fraction;
|
|
90
|
+
if (fraction >= 1) close();
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
if (openWidth + fraction > 1.0001) close();
|
|
94
|
+
if (!open) {
|
|
95
|
+
open = { fields: [q.field], step: q.step };
|
|
96
|
+
openWidth = fraction;
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
open.fields.push(q.field);
|
|
100
|
+
openWidth += fraction;
|
|
101
|
+
}
|
|
102
|
+
close();
|
|
103
|
+
return views;
|
|
104
|
+
}
|
|
105
|
+
function countStageViews(config) {
|
|
106
|
+
return stageViews(config).length;
|
|
107
|
+
}
|
|
108
|
+
function countStageQuestions(config) {
|
|
109
|
+
return stageQuestions(config).length;
|
|
110
|
+
}
|
|
111
|
+
function stageEstimate(questionCount) {
|
|
112
|
+
const seconds = questionCount * 8;
|
|
113
|
+
if (seconds < 50) return `about ${Math.max(15, Math.ceil(seconds / 5) * 5)} seconds`;
|
|
114
|
+
if (seconds <= 90) return "about a minute";
|
|
115
|
+
return `about ${Math.round(seconds / 60)} minutes`;
|
|
116
|
+
}
|
|
117
|
+
function stageFirstName(value) {
|
|
118
|
+
if (typeof value !== "string") return null;
|
|
119
|
+
const token = value.trim().split(/\s+/)[0];
|
|
120
|
+
if (!token || token.length > 24) return null;
|
|
121
|
+
return token;
|
|
122
|
+
}
|
|
123
|
+
function isEmptyValue(value) {
|
|
124
|
+
if (value === void 0 || value === null || value === "") return true;
|
|
125
|
+
if (Array.isArray(value)) return value.length === 0;
|
|
126
|
+
return false;
|
|
127
|
+
}
|
|
128
|
+
function formatAnswer(value) {
|
|
129
|
+
if (isEmptyValue(value)) return null;
|
|
130
|
+
if (Array.isArray(value)) return value.map(String).join(", ");
|
|
131
|
+
if (typeof value === "boolean") return value ? "Yes" : "No";
|
|
132
|
+
return String(value);
|
|
133
|
+
}
|
|
134
|
+
var AUTO_ADVANCE_TYPES = ["radio", "select", "rating"];
|
|
135
|
+
|
|
136
|
+
export { AUTO_ADVANCE_TYPES, countStageQuestions, countStageViews, formatAnswer, isEmptyValue, stageEstimate, stageFirstName, stageViews, useFieldControls };
|
|
137
|
+
//# sourceMappingURL=chunk-MZY3MEUO.mjs.map
|
|
138
|
+
//# sourceMappingURL=chunk-MZY3MEUO.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/forms/field-controls.ts","../src/forms/experience-plan.ts"],"names":[],"mappings":"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","file":"chunk-MZY3MEUO.mjs","sourcesContent":["'use client'\n\n/**\n * The field controls that need React hooks, loaded only when a form actually\n * has a field that uses them.\n *\n * FormField deliberately does NOT import these. DatePicker carries 17 hooks\n * and FileField holds upload state; importing them there put both in\n * FormField's chunk, which the build stamps `'use client'` — so a Server\n * Component rendering a single text input shipped 38 KB of date picker to the\n * browser. Injecting them from the client side keeps FormField hook-free and\n * therefore server-renderable, which is the whole basis of StaticForm.\n *\n * Injection alone still put both controls in the forms entry's eager graph,\n * because a module-level constant referencing them is a static import: every\n * form paid for the date picker, and most forms have no date field. They are\n * now fetched on demand, per control, from the field list.\n *\n * The wait costs nothing visually. FormField already renders the native\n * control when a control is absent (static mode does exactly this), so a date\n * field paints as `<input type=\"date\">` and upgrades in place when the chunk\n * lands — the same enhancement path a no-JS visitor never leaves.\n *\n * Every client renderer of <FormField> (FormClient, FormSpotlight, FormStage)\n * calls this hook, so the experiences and the classic form always offer\n * identical controls.\n */\n\nimport { useEffect, useMemo, useRef, useState } from 'react'\nimport type { FormField as FormFieldType } from './types'\n\nexport interface FieldControls {\n Date?: React.ComponentType<any>\n File?: React.ComponentType<any>\n}\n\n/** Stable identity for the common case (no date, no file) — no render churn. */\nconst NO_CONTROLS: FieldControls = {}\n\nexport function useFieldControls(fields: FormFieldType[] | undefined): FieldControls {\n const needsDate = useMemo(\n () => (fields ?? []).some((f) => f.field_type === 'date' || f.field_type === 'datetime'),\n [fields],\n )\n const needsFile = useMemo(\n () => (fields ?? []).some((f) => f.field_type === 'file'),\n [fields],\n )\n\n const [controls, setControls] = useState<FieldControls>(NO_CONTROLS)\n // Guards re-import when a conditional field toggles visibility mid-fill.\n const requested = useRef({ date: false, file: false })\n\n useEffect(() => {\n let cancelled = false\n\n if (needsDate && !requested.current.date) {\n requested.current.date = true\n import('./DatePicker')\n .then((m) => {\n if (!cancelled) setControls((prev) => ({ ...prev, Date: m.DatePicker }))\n })\n .catch(() => {\n // Chunk never arrived — the native date input stays, which submits\n // the same value. A failed fetch must not cost the lead.\n requested.current.date = false\n })\n }\n\n if (needsFile && !requested.current.file) {\n requested.current.file = true\n import('./FileField')\n .then((m) => {\n if (!cancelled) setControls((prev) => ({ ...prev, File: m.FileField }))\n })\n .catch(() => {\n requested.current.file = false\n })\n }\n\n return () => {\n cancelled = true\n }\n }, [needsDate, needsFile])\n\n return controls\n}\n","/**\n * Shared planning helpers for the alternate form experiences (stage,\n * spotlight). Pure data — no React, no CSS — so FormClient can import the\n * counts it needs for tracking WITHOUT pulling an experience component (and\n * its stylesheet) into every site's forms bundle. The components themselves\n * are lazy-loaded; this module is the only part that ships eagerly.\n */\n\nimport type {\n FormField as FormFieldType,\n FormStep,\n ManagedFormConfig,\n} from './types'\n\n/** Display-only / non-question field types — never staged. */\nconst NON_QUESTION_TYPES = ['heading', 'section_header', 'paragraph', 'hidden']\n\nexport interface StageQuestion {\n field: FormFieldType\n /** The step (chapter) this question belongs to, when the form is multi-step. */\n step?: FormStep\n}\n\nexport interface StageView {\n fields: FormFieldType[]\n step?: FormStep\n}\n\n/**\n * Flatten a form into its ordered question list. Steps become chapters:\n * multi-step forms iterate steps in step_number order (fields are already\n * sorted by sort_order via normalizeFormConfig); stepless fields trail.\n */\nexport function stageQuestions(config: ManagedFormConfig): StageQuestion[] {\n const input = (config.fields || []).filter(\n (f) => !NON_QUESTION_TYPES.includes(f.field_type),\n )\n if (!config.is_multi_step || !config.steps?.length) {\n return input.map((field) => ({ field }))\n }\n const ordered = [...config.steps].sort((a, b) => a.step_number - b.step_number)\n const out: StageQuestion[] = []\n const claimed = new Set<string>()\n for (const step of ordered) {\n for (const field of input) {\n if (field.step_id === step.id) {\n out.push({ field, step })\n claimed.add(field.id)\n }\n }\n }\n for (const field of input) {\n if (!claimed.has(field.id)) out.push({ field })\n }\n return out\n}\n\nconst WIDTH_FRACTION: Record<string, number> = {\n full: 1,\n half: 1 / 2,\n third: 1 / 3,\n quarter: 1 / 4,\n}\n\n/**\n * Group questions into beats using the classic grid's own row math:\n * consecutive sub-full-width fields fill a row (2 halves, 3 thirds...) and\n * that row is one beat; a full-width field closes any open row and stands\n * alone; a chapter change always starts a fresh beat.\n */\nexport function stageViews(config: ManagedFormConfig): StageView[] {\n const questions = stageQuestions(config)\n const views: StageView[] = []\n let open: StageView | null = null\n let openWidth = 0\n\n const close = () => {\n if (open) views.push(open)\n open = null\n openWidth = 0\n }\n\n for (const q of questions) {\n const fraction = WIDTH_FRACTION[q.field.width] ?? 1\n const chapterChanged = open && open.step?.id !== q.step?.id\n if (fraction >= 1 || chapterChanged) close()\n if (!open) {\n open = { fields: [q.field], step: q.step }\n openWidth = fraction\n if (fraction >= 1) close()\n continue\n }\n if (openWidth + fraction > 1.0001) close()\n if (!open) {\n open = { fields: [q.field], step: q.step }\n openWidth = fraction\n continue\n }\n open.fields.push(q.field)\n openWidth += fraction\n }\n close()\n return views\n}\n\nexport function countStageViews(config: ManagedFormConfig): number {\n return stageViews(config).length\n}\n\nexport function countStageQuestions(config: ManagedFormConfig): number {\n return stageQuestions(config).length\n}\n\n/**\n * Honest, friendly time estimate: \"about 40 seconds\".\n * ~8s per question, rounded to something a human would actually say.\n */\nexport function stageEstimate(questionCount: number): string {\n const seconds = questionCount * 8\n if (seconds < 50) return `about ${Math.max(15, Math.ceil(seconds / 5) * 5)} seconds`\n if (seconds <= 90) return 'about a minute'\n return `about ${Math.round(seconds / 60)} minutes`\n}\n\n/** First name for the greeting — conservative: short, single token, else null. */\nexport function stageFirstName(value: unknown): string | null {\n if (typeof value !== 'string') return null\n const token = value.trim().split(/\\s+/)[0]\n if (!token || token.length > 24) return null\n return token\n}\n\nexport function isEmptyValue(value: unknown): boolean {\n if (value === undefined || value === null || value === '') return true\n if (Array.isArray(value)) return value.length === 0\n return false\n}\n\nexport function formatAnswer(value: unknown): string | null {\n if (isEmptyValue(value)) return null\n if (Array.isArray(value)) return value.map(String).join(', ')\n if (typeof value === 'boolean') return value ? 'Yes' : 'No'\n return String(value)\n}\n\n/** Single-select types where picking an answer advances after a lock-in beat. */\nexport const AUTO_ADVANCE_TYPES = ['radio', 'select', 'rating']\n"]}
|
|
@@ -0,0 +1,508 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { countStageViews, countStageQuestions, useFieldControls } from './chunk-MZY3MEUO.mjs';
|
|
3
|
+
import { HoneypotField, NativeFallbackFields, nativeFormProps } from './chunk-R4PCXP3F.mjs';
|
|
4
|
+
import { DelightStyles, FormMomentum, FormField } from './chunk-LB7LHVWI.mjs';
|
|
5
|
+
import { useFormTracking, useForm } from './chunk-JFVEKSZT.mjs';
|
|
6
|
+
import { submitForm, DEFAULT_FORM_SUCCESS_MESSAGE } from './chunk-AJNT5GCU.mjs';
|
|
7
|
+
import { DEFAULT_HONEYPOT_FIELD } from './chunk-TMVKRQGJ.mjs';
|
|
8
|
+
import { useState, useRef, useMemo, useEffect, useCallback } from 'react';
|
|
9
|
+
import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
|
|
10
|
+
|
|
11
|
+
function FormClient({
|
|
12
|
+
config,
|
|
13
|
+
className,
|
|
14
|
+
onSuccess,
|
|
15
|
+
onError,
|
|
16
|
+
customRender,
|
|
17
|
+
experience,
|
|
18
|
+
nativeReturnTo,
|
|
19
|
+
defaultValues
|
|
20
|
+
}) {
|
|
21
|
+
const [values, setValues] = useState(() => {
|
|
22
|
+
const defaults = {};
|
|
23
|
+
for (const field of config.fields || []) {
|
|
24
|
+
if (field.default_value !== void 0 && field.default_value !== null) {
|
|
25
|
+
defaults[field.slug] = field.default_value;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return { ...defaults, ...defaultValues || {} };
|
|
29
|
+
});
|
|
30
|
+
const [errors, setErrors] = useState({});
|
|
31
|
+
const [step, setStep] = useState(1);
|
|
32
|
+
const [stepDirection, setStepDirection] = useState("forward");
|
|
33
|
+
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
34
|
+
const [isComplete, setIsComplete] = useState(false);
|
|
35
|
+
const [submitError, setSubmitError] = useState(null);
|
|
36
|
+
const [honeypotValue, setHoneypotValue] = useState("");
|
|
37
|
+
const [touched, setTouched] = useState({});
|
|
38
|
+
const honeypotFieldName = config.honeypot_field || DEFAULT_HONEYPOT_FIELD;
|
|
39
|
+
const formLoadedAt = useRef(Date.now());
|
|
40
|
+
const isSubmittingRef = useRef(false);
|
|
41
|
+
const stageBeatCount = useMemo(() => countStageViews(config), [config]);
|
|
42
|
+
const questionCount = useMemo(() => countStageQuestions(config), [config]);
|
|
43
|
+
const requested = experience ?? (config.layout === "stage" ? "stage" : config.layout === "classic" ? "classic" : "spotlight");
|
|
44
|
+
const resolvedExperience = !customRender && questionCount > 0 && requested !== "classic" ? requested : "classic";
|
|
45
|
+
const fieldControls = useFieldControls(config.fields);
|
|
46
|
+
const { trackStepChange, trackComplete } = useFormTracking({
|
|
47
|
+
formId: config.id,
|
|
48
|
+
// Alternate experiences report their unit (beat / field index) as the
|
|
49
|
+
// step — form_analytics becomes a drop-off funnel with zero API changes.
|
|
50
|
+
totalSteps: resolvedExperience === "stage" ? stageBeatCount : resolvedExperience === "spotlight" ? questionCount : config.total_steps
|
|
51
|
+
});
|
|
52
|
+
const [Celebration, setCelebration] = useState(null);
|
|
53
|
+
useEffect(() => {
|
|
54
|
+
if (!isSubmitting && !isComplete) return;
|
|
55
|
+
let cancelled = false;
|
|
56
|
+
import('./FormCelebration-7CBANVNS.mjs').then((m) => {
|
|
57
|
+
if (!cancelled) setCelebration(() => m.FormCelebration);
|
|
58
|
+
}).catch(() => {
|
|
59
|
+
});
|
|
60
|
+
return () => {
|
|
61
|
+
cancelled = true;
|
|
62
|
+
};
|
|
63
|
+
}, [isSubmitting, isComplete]);
|
|
64
|
+
const [Experience, setExperience] = useState(null);
|
|
65
|
+
useEffect(() => {
|
|
66
|
+
if (resolvedExperience === "classic") {
|
|
67
|
+
setExperience(null);
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
let cancelled = false;
|
|
71
|
+
const load = resolvedExperience === "stage" ? import('./FormStage-GNBPJ7WX.mjs').then((m) => m.FormStage) : import('./FormSpotlight-72TYHDPV.mjs').then((m) => m.FormSpotlight);
|
|
72
|
+
load.then((Component) => {
|
|
73
|
+
if (!cancelled) setExperience(() => Component);
|
|
74
|
+
}).catch((err) => {
|
|
75
|
+
console.error("[Forms] Experience failed to load; using classic form:", err);
|
|
76
|
+
});
|
|
77
|
+
return () => {
|
|
78
|
+
cancelled = true;
|
|
79
|
+
};
|
|
80
|
+
}, [resolvedExperience]);
|
|
81
|
+
const currentFields = useMemo(() => {
|
|
82
|
+
if (!config.is_multi_step) {
|
|
83
|
+
return config.fields || [];
|
|
84
|
+
}
|
|
85
|
+
const currentStepConfig2 = config.steps?.find((s) => s.step_number === step);
|
|
86
|
+
if (!currentStepConfig2) return config.fields || [];
|
|
87
|
+
return (config.fields || []).filter((f) => f.step_id === currentStepConfig2.id);
|
|
88
|
+
}, [config, step]);
|
|
89
|
+
const isFieldVisible = useCallback((field) => {
|
|
90
|
+
if (!field.conditional?.show_when) return true;
|
|
91
|
+
const { field: condField, operator, value } = field.conditional.show_when;
|
|
92
|
+
const fieldValue = values[condField];
|
|
93
|
+
switch (operator) {
|
|
94
|
+
case "equals":
|
|
95
|
+
return fieldValue === value;
|
|
96
|
+
case "not_equals":
|
|
97
|
+
return fieldValue !== value;
|
|
98
|
+
case "contains":
|
|
99
|
+
return String(fieldValue).includes(String(value));
|
|
100
|
+
case "not_contains":
|
|
101
|
+
return !String(fieldValue).includes(String(value));
|
|
102
|
+
case "is_empty":
|
|
103
|
+
return !fieldValue || fieldValue === "";
|
|
104
|
+
case "not_empty":
|
|
105
|
+
return !!fieldValue && fieldValue !== "";
|
|
106
|
+
case "greater_than":
|
|
107
|
+
return Number(fieldValue) > Number(value);
|
|
108
|
+
case "less_than":
|
|
109
|
+
return Number(fieldValue) < Number(value);
|
|
110
|
+
default:
|
|
111
|
+
return true;
|
|
112
|
+
}
|
|
113
|
+
}, [values]);
|
|
114
|
+
const validateField = useCallback((field) => {
|
|
115
|
+
if (!isFieldVisible(field)) return null;
|
|
116
|
+
if (["heading", "section_header", "paragraph", "hidden"].includes(field.field_type)) return null;
|
|
117
|
+
const value = values[field.slug];
|
|
118
|
+
const rules = field.validation || {};
|
|
119
|
+
if (field.is_required && (!value || value === "")) {
|
|
120
|
+
return rules.custom_error || `${field.label} is required`;
|
|
121
|
+
}
|
|
122
|
+
if (!value) return null;
|
|
123
|
+
const strValue = String(value);
|
|
124
|
+
if (rules.min_length && strValue.length < rules.min_length) {
|
|
125
|
+
return `${field.label} must be at least ${rules.min_length} characters`;
|
|
126
|
+
}
|
|
127
|
+
if (rules.max_length && strValue.length > rules.max_length) {
|
|
128
|
+
return `${field.label} must be no more than ${rules.max_length} characters`;
|
|
129
|
+
}
|
|
130
|
+
if (rules.min !== void 0 && Number(value) < rules.min) {
|
|
131
|
+
return `${field.label} must be at least ${rules.min}`;
|
|
132
|
+
}
|
|
133
|
+
if (rules.max !== void 0 && Number(value) > rules.max) {
|
|
134
|
+
return `${field.label} must be no more than ${rules.max}`;
|
|
135
|
+
}
|
|
136
|
+
if (rules.pattern) {
|
|
137
|
+
try {
|
|
138
|
+
if (!new RegExp(rules.pattern).test(strValue)) {
|
|
139
|
+
return rules.custom_error || `${field.label} is invalid`;
|
|
140
|
+
}
|
|
141
|
+
} catch {
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
if (field.field_type === "email" && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(strValue)) {
|
|
145
|
+
return "Please enter a valid email address";
|
|
146
|
+
}
|
|
147
|
+
if (field.field_type === "phone" && !/^[\d\s\-\+\(\)]+$/.test(strValue)) {
|
|
148
|
+
return "Please enter a valid phone number";
|
|
149
|
+
}
|
|
150
|
+
return null;
|
|
151
|
+
}, [values, isFieldVisible]);
|
|
152
|
+
const fieldIsComplete = useCallback((field) => {
|
|
153
|
+
if (!isFieldVisible(field)) return false;
|
|
154
|
+
if (["heading", "section_header", "paragraph", "hidden"].includes(field.field_type)) return false;
|
|
155
|
+
const value = values[field.slug];
|
|
156
|
+
if (value === void 0 || value === null || value === "") return false;
|
|
157
|
+
return validateField(field) === null;
|
|
158
|
+
}, [values, isFieldVisible, validateField]);
|
|
159
|
+
const momentum = useMemo(() => {
|
|
160
|
+
const measurable = (config.fields || []).filter(
|
|
161
|
+
(f) => f.is_required && isFieldVisible(f) && !["heading", "section_header", "paragraph", "hidden"].includes(f.field_type)
|
|
162
|
+
);
|
|
163
|
+
return { done: measurable.filter(fieldIsComplete).length, total: measurable.length };
|
|
164
|
+
}, [config, isFieldVisible, fieldIsComplete]);
|
|
165
|
+
const validateStep = useCallback(() => {
|
|
166
|
+
const newErrors = {};
|
|
167
|
+
for (const field of currentFields) {
|
|
168
|
+
const error = validateField(field);
|
|
169
|
+
if (error) {
|
|
170
|
+
newErrors[field.slug] = error;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
setErrors(newErrors);
|
|
174
|
+
return Object.keys(newErrors).length === 0;
|
|
175
|
+
}, [currentFields, validateField]);
|
|
176
|
+
const validateAll = useCallback(() => {
|
|
177
|
+
const allFields = config.fields || [];
|
|
178
|
+
const newErrors = {};
|
|
179
|
+
for (const field of allFields) {
|
|
180
|
+
const error = validateField(field);
|
|
181
|
+
if (error) newErrors[field.slug] = error;
|
|
182
|
+
}
|
|
183
|
+
setErrors(newErrors);
|
|
184
|
+
if (Object.keys(newErrors).length === 0) return { ok: true, firstErrorStep: null };
|
|
185
|
+
let firstErrorStep = null;
|
|
186
|
+
if (config.is_multi_step && config.steps) {
|
|
187
|
+
const ordered = [...config.steps].sort((a, b) => a.step_number - b.step_number);
|
|
188
|
+
for (const s of ordered) {
|
|
189
|
+
if (allFields.some((f) => f.step_id === s.id && newErrors[f.slug])) {
|
|
190
|
+
firstErrorStep = s.step_number;
|
|
191
|
+
break;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
return { ok: false, firstErrorStep };
|
|
196
|
+
}, [config, validateField]);
|
|
197
|
+
const buildVisibleValues = useCallback(() => {
|
|
198
|
+
const out = {};
|
|
199
|
+
for (const field of config.fields || []) {
|
|
200
|
+
if (!isFieldVisible(field)) continue;
|
|
201
|
+
if (field.slug in values) out[field.slug] = values[field.slug];
|
|
202
|
+
}
|
|
203
|
+
return out;
|
|
204
|
+
}, [config, values, isFieldVisible]);
|
|
205
|
+
const setFieldValue = useCallback((key, value) => {
|
|
206
|
+
setTouched((prev) => prev[key] ? prev : { ...prev, [key]: true });
|
|
207
|
+
setValues((prev) => ({ ...prev, [key]: value }));
|
|
208
|
+
if (errors[key]) {
|
|
209
|
+
setErrors((prev) => {
|
|
210
|
+
const next = { ...prev };
|
|
211
|
+
delete next[key];
|
|
212
|
+
return next;
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
}, [errors]);
|
|
216
|
+
const nextStep = useCallback(() => {
|
|
217
|
+
if (!validateStep()) return false;
|
|
218
|
+
if (step < config.total_steps) {
|
|
219
|
+
const newStep = step + 1;
|
|
220
|
+
setStepDirection("forward");
|
|
221
|
+
setStep(newStep);
|
|
222
|
+
trackStepChange(newStep);
|
|
223
|
+
return true;
|
|
224
|
+
}
|
|
225
|
+
return false;
|
|
226
|
+
}, [step, config.total_steps, validateStep, trackStepChange]);
|
|
227
|
+
const prevStep = useCallback(() => {
|
|
228
|
+
if (step > 1) {
|
|
229
|
+
const newStep = step - 1;
|
|
230
|
+
setStepDirection("back");
|
|
231
|
+
setStep(newStep);
|
|
232
|
+
trackStepChange(newStep);
|
|
233
|
+
}
|
|
234
|
+
}, [step, trackStepChange]);
|
|
235
|
+
const goToStep = useCallback((targetStep) => {
|
|
236
|
+
if (targetStep >= 1 && targetStep <= config.total_steps) {
|
|
237
|
+
setStepDirection(targetStep < step ? "back" : "forward");
|
|
238
|
+
setStep(targetStep);
|
|
239
|
+
trackStepChange(targetStep);
|
|
240
|
+
}
|
|
241
|
+
}, [step, config.total_steps, trackStepChange]);
|
|
242
|
+
const submit = useCallback(async () => {
|
|
243
|
+
if (isSubmittingRef.current) return;
|
|
244
|
+
const { ok, firstErrorStep } = validateAll();
|
|
245
|
+
if (!ok) {
|
|
246
|
+
if (firstErrorStep != null) {
|
|
247
|
+
setStepDirection("back");
|
|
248
|
+
setStep(firstErrorStep);
|
|
249
|
+
}
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
isSubmittingRef.current = true;
|
|
253
|
+
setIsSubmitting(true);
|
|
254
|
+
setSubmitError(null);
|
|
255
|
+
try {
|
|
256
|
+
const data = await submitForm({
|
|
257
|
+
config,
|
|
258
|
+
values: buildVisibleValues(),
|
|
259
|
+
honeypotValue: config.honeypot_enabled ? honeypotValue : "",
|
|
260
|
+
formLoadedAt: formLoadedAt.current
|
|
261
|
+
});
|
|
262
|
+
trackComplete();
|
|
263
|
+
setIsComplete(true);
|
|
264
|
+
onSuccess?.(data);
|
|
265
|
+
if (config.redirect_url) {
|
|
266
|
+
window.location.href = config.redirect_url;
|
|
267
|
+
}
|
|
268
|
+
} catch (error) {
|
|
269
|
+
console.error("[Forms] Submission error:", error);
|
|
270
|
+
setSubmitError("Something went wrong sending your submission. Please try again.");
|
|
271
|
+
onError?.(error);
|
|
272
|
+
} finally {
|
|
273
|
+
isSubmittingRef.current = false;
|
|
274
|
+
setIsSubmitting(false);
|
|
275
|
+
}
|
|
276
|
+
}, [config, honeypotValue, validateAll, buildVisibleValues, trackComplete, onSuccess, onError]);
|
|
277
|
+
const progress = useMemo(() => {
|
|
278
|
+
return Math.round(step / config.total_steps * 100);
|
|
279
|
+
}, [step, config.total_steps]);
|
|
280
|
+
const currentStepConfig = useMemo(
|
|
281
|
+
() => config.steps?.find((s) => s.step_number === step),
|
|
282
|
+
[config.steps, step]
|
|
283
|
+
);
|
|
284
|
+
const stepPanelRef = useRef(null);
|
|
285
|
+
const hasNavigatedRef = useRef(false);
|
|
286
|
+
useEffect(() => {
|
|
287
|
+
if (!config.is_multi_step) return;
|
|
288
|
+
if (!hasNavigatedRef.current) {
|
|
289
|
+
hasNavigatedRef.current = true;
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
stepPanelRef.current?.focus();
|
|
293
|
+
}, [step, config.is_multi_step]);
|
|
294
|
+
const renderProps = {
|
|
295
|
+
config,
|
|
296
|
+
fields: currentFields,
|
|
297
|
+
step,
|
|
298
|
+
totalSteps: config.total_steps,
|
|
299
|
+
values,
|
|
300
|
+
errors,
|
|
301
|
+
isSubmitting,
|
|
302
|
+
progress,
|
|
303
|
+
nextStep,
|
|
304
|
+
prevStep,
|
|
305
|
+
goToStep,
|
|
306
|
+
submit,
|
|
307
|
+
setFieldValue,
|
|
308
|
+
isFieldVisible
|
|
309
|
+
};
|
|
310
|
+
if (isComplete) {
|
|
311
|
+
const raw = config.success_message;
|
|
312
|
+
const message = typeof raw === "string" && raw.trim().length > 0 ? raw.trim() : DEFAULT_FORM_SUCCESS_MESSAGE;
|
|
313
|
+
if (Celebration) return /* @__PURE__ */ jsx(Celebration, { message, className });
|
|
314
|
+
return /* @__PURE__ */ jsx("div", { className, "data-sk-part": "celebration-fallback", role: "status", children: /* @__PURE__ */ jsx("p", { children: message }) });
|
|
315
|
+
}
|
|
316
|
+
if (customRender) {
|
|
317
|
+
return /* @__PURE__ */ jsx(Fragment, { children: customRender(renderProps) });
|
|
318
|
+
}
|
|
319
|
+
if (resolvedExperience !== "classic" && Experience) {
|
|
320
|
+
const bundle = {
|
|
321
|
+
config,
|
|
322
|
+
values,
|
|
323
|
+
errors,
|
|
324
|
+
touched,
|
|
325
|
+
isSubmitting,
|
|
326
|
+
submitError,
|
|
327
|
+
momentum,
|
|
328
|
+
className,
|
|
329
|
+
setFieldValue,
|
|
330
|
+
validateField,
|
|
331
|
+
isFieldVisible,
|
|
332
|
+
fieldIsComplete,
|
|
333
|
+
applyFieldError: (slug, message) => setErrors((prev) => ({ ...prev, [slug]: message })),
|
|
334
|
+
submit,
|
|
335
|
+
trackStepChange,
|
|
336
|
+
honeypot: config.honeypot_enabled ? /* @__PURE__ */ jsx(
|
|
337
|
+
HoneypotField,
|
|
338
|
+
{
|
|
339
|
+
name: honeypotFieldName,
|
|
340
|
+
value: honeypotValue,
|
|
341
|
+
onChange: setHoneypotValue
|
|
342
|
+
}
|
|
343
|
+
) : null
|
|
344
|
+
};
|
|
345
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
346
|
+
/* @__PURE__ */ jsx(DelightStyles, {}),
|
|
347
|
+
/* @__PURE__ */ jsx(Experience, { ...bundle })
|
|
348
|
+
] });
|
|
349
|
+
}
|
|
350
|
+
return /* @__PURE__ */ jsxs(
|
|
351
|
+
"form",
|
|
352
|
+
{
|
|
353
|
+
"data-sk-state": isSubmitting ? "submitting" : "idle",
|
|
354
|
+
"data-sk-ready": momentum.total > 0 && momentum.done >= momentum.total && step >= config.total_steps ? "true" : void 0,
|
|
355
|
+
className: `sk-form ${className || ""}`,
|
|
356
|
+
...nativeFormProps(config),
|
|
357
|
+
onSubmit: (e) => {
|
|
358
|
+
e.preventDefault();
|
|
359
|
+
if (step < config.total_steps) {
|
|
360
|
+
nextStep();
|
|
361
|
+
} else {
|
|
362
|
+
submit();
|
|
363
|
+
}
|
|
364
|
+
},
|
|
365
|
+
children: [
|
|
366
|
+
/* @__PURE__ */ jsx(DelightStyles, {}),
|
|
367
|
+
/* @__PURE__ */ jsx(FormMomentum, { done: momentum.done, total: momentum.total }),
|
|
368
|
+
config.is_multi_step && /* @__PURE__ */ jsxs("div", { className: "sk-form__progress", children: [
|
|
369
|
+
/* @__PURE__ */ jsxs("div", { className: "sk-form__progress-header", children: [
|
|
370
|
+
/* @__PURE__ */ jsxs("span", { className: "sk-form__progress-step", children: [
|
|
371
|
+
"Step ",
|
|
372
|
+
step,
|
|
373
|
+
" of ",
|
|
374
|
+
config.total_steps
|
|
375
|
+
] }),
|
|
376
|
+
config.show_progress && /* @__PURE__ */ jsxs("span", { className: "sk-form__progress-percent", children: [
|
|
377
|
+
progress,
|
|
378
|
+
"%"
|
|
379
|
+
] })
|
|
380
|
+
] }),
|
|
381
|
+
/* @__PURE__ */ jsx(
|
|
382
|
+
"div",
|
|
383
|
+
{
|
|
384
|
+
className: "sk-form__progress-track",
|
|
385
|
+
role: "progressbar",
|
|
386
|
+
"aria-valuemin": 1,
|
|
387
|
+
"aria-valuemax": config.total_steps,
|
|
388
|
+
"aria-valuenow": step,
|
|
389
|
+
"aria-valuetext": `Step ${step} of ${config.total_steps}`,
|
|
390
|
+
children: /* @__PURE__ */ jsx("div", { className: "sk-form__progress-bar", style: { width: `${progress}%` } })
|
|
391
|
+
}
|
|
392
|
+
),
|
|
393
|
+
/* @__PURE__ */ jsx("ol", { className: "sk-form__progress-dots", "aria-hidden": "true", children: Array.from({ length: config.total_steps }, (_, i) => i + 1).map((n) => /* @__PURE__ */ jsx(
|
|
394
|
+
"li",
|
|
395
|
+
{
|
|
396
|
+
className: "sk-form__progress-dot" + (n === step ? " sk-form__progress-dot--current" : "") + (n < step ? " sk-form__progress-dot--done" : "")
|
|
397
|
+
},
|
|
398
|
+
n
|
|
399
|
+
)) })
|
|
400
|
+
] }),
|
|
401
|
+
/* @__PURE__ */ jsxs(
|
|
402
|
+
"div",
|
|
403
|
+
{
|
|
404
|
+
ref: stepPanelRef,
|
|
405
|
+
tabIndex: -1,
|
|
406
|
+
className: "sk-form__step" + (config.is_multi_step ? ` sk-form__step--${stepDirection}` : ""),
|
|
407
|
+
children: [
|
|
408
|
+
config.is_multi_step && (currentStepConfig?.title || currentStepConfig?.description) && /* @__PURE__ */ jsxs("div", { className: "sk-form__step-intro", children: [
|
|
409
|
+
currentStepConfig.title && /* @__PURE__ */ jsx("h3", { className: "sk-form__step-title", children: currentStepConfig.title }),
|
|
410
|
+
currentStepConfig.description && /* @__PURE__ */ jsx("p", { className: "sk-form__step-description", children: currentStepConfig.description })
|
|
411
|
+
] }),
|
|
412
|
+
/* @__PURE__ */ jsx("div", { className: "sk-form__fields", children: currentFields.map((field) => {
|
|
413
|
+
if (!isFieldVisible(field)) return null;
|
|
414
|
+
return /* @__PURE__ */ jsx("div", { className: `sk-form__field-wrapper sk-form__field-wrapper--${field.width || "full"}`, children: /* @__PURE__ */ jsx(
|
|
415
|
+
FormField,
|
|
416
|
+
{
|
|
417
|
+
field,
|
|
418
|
+
value: values[field.slug],
|
|
419
|
+
error: errors[field.slug],
|
|
420
|
+
showValid: !!touched[field.slug] && !errors[field.slug] && fieldIsComplete(field),
|
|
421
|
+
onChange: (value) => setFieldValue(field.slug, value),
|
|
422
|
+
controls: fieldControls
|
|
423
|
+
}
|
|
424
|
+
) }, field.id);
|
|
425
|
+
}) })
|
|
426
|
+
]
|
|
427
|
+
},
|
|
428
|
+
step
|
|
429
|
+
),
|
|
430
|
+
/* @__PURE__ */ jsxs(
|
|
431
|
+
"div",
|
|
432
|
+
{
|
|
433
|
+
className: "sk-form__actions",
|
|
434
|
+
style: { justifyContent: step > 1 ? "space-between" : "flex-end" },
|
|
435
|
+
children: [
|
|
436
|
+
step > 1 && /* @__PURE__ */ jsx("button", { type: "button", className: "sk-form__btn sk-form__btn--back", onClick: prevStep, children: "Back" }),
|
|
437
|
+
/* @__PURE__ */ jsx("button", { type: "submit", className: "sk-form__btn sk-form__btn--submit", disabled: isSubmitting, children: isSubmitting ? "Submitting..." : step < config.total_steps ? "Next" : config.submit_button_text })
|
|
438
|
+
]
|
|
439
|
+
}
|
|
440
|
+
),
|
|
441
|
+
submitError && /* @__PURE__ */ jsx(
|
|
442
|
+
"p",
|
|
443
|
+
{
|
|
444
|
+
className: "sk-form__submit-error",
|
|
445
|
+
role: "alert",
|
|
446
|
+
style: { color: "var(--sk-error, #dc2626)", fontSize: 14, marginTop: 12 },
|
|
447
|
+
children: submitError
|
|
448
|
+
}
|
|
449
|
+
),
|
|
450
|
+
config.honeypot_enabled && /* @__PURE__ */ jsx(
|
|
451
|
+
HoneypotField,
|
|
452
|
+
{
|
|
453
|
+
name: honeypotFieldName,
|
|
454
|
+
value: honeypotValue,
|
|
455
|
+
onChange: setHoneypotValue
|
|
456
|
+
}
|
|
457
|
+
),
|
|
458
|
+
/* @__PURE__ */ jsx(NativeFallbackFields, { config, returnTo: nativeReturnTo })
|
|
459
|
+
]
|
|
460
|
+
}
|
|
461
|
+
);
|
|
462
|
+
}
|
|
463
|
+
function ManagedForm({
|
|
464
|
+
formId,
|
|
465
|
+
projectId,
|
|
466
|
+
className,
|
|
467
|
+
onSuccess,
|
|
468
|
+
onError,
|
|
469
|
+
initialConfig,
|
|
470
|
+
experience,
|
|
471
|
+
nativeReturnTo,
|
|
472
|
+
defaultValues,
|
|
473
|
+
children
|
|
474
|
+
}) {
|
|
475
|
+
const {
|
|
476
|
+
form,
|
|
477
|
+
isLoading,
|
|
478
|
+
fetchError
|
|
479
|
+
} = useForm(formId, {
|
|
480
|
+
projectId,
|
|
481
|
+
onSuccess,
|
|
482
|
+
onError,
|
|
483
|
+
initialForm: initialConfig
|
|
484
|
+
});
|
|
485
|
+
if (isLoading) {
|
|
486
|
+
return /* @__PURE__ */ jsx("div", { className, children: /* @__PURE__ */ jsx("p", { style: { color: "#6b7280" }, children: "Loading form..." }) });
|
|
487
|
+
}
|
|
488
|
+
if (fetchError || !form) {
|
|
489
|
+
return /* @__PURE__ */ jsx("div", { className, children: /* @__PURE__ */ jsx("p", { style: { color: "var(--sk-error, #dc2626)" }, children: fetchError?.message || "Form not found or inactive." }) });
|
|
490
|
+
}
|
|
491
|
+
return /* @__PURE__ */ jsx(
|
|
492
|
+
FormClient,
|
|
493
|
+
{
|
|
494
|
+
config: form,
|
|
495
|
+
className,
|
|
496
|
+
onSuccess,
|
|
497
|
+
onError,
|
|
498
|
+
customRender: children,
|
|
499
|
+
experience,
|
|
500
|
+
nativeReturnTo,
|
|
501
|
+
defaultValues
|
|
502
|
+
}
|
|
503
|
+
);
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
export { FormClient, ManagedForm };
|
|
507
|
+
//# sourceMappingURL=chunk-NCWVR4BU.mjs.map
|
|
508
|
+
//# sourceMappingURL=chunk-NCWVR4BU.mjs.map
|