@sonordev/site-kit 7.1.2 → 7.2.0
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/AGENTS.md +1 -1
- package/CHANGELOG.md +51 -0
- package/README.md +9 -8
- package/agent-manifest.json +12 -4
- package/dist/{AnalyticsProvider-ZB33W6MC.js → AnalyticsProvider-SLFFBRPE.js} +4 -4
- package/dist/{ArticleViewTracker-GMHYLLLZ.js → ArticleViewTracker-TM5AMGN2.js} +3 -3
- package/dist/{BlocksPopup-EA6LYL25.js → BlocksPopup-YJNJIVPO.js} +5 -5
- package/dist/ChatWidget-XKOSH66S.js +17 -0
- package/dist/{FileField-QKA3JB2Q.js → FileField-CI4UL5SH.js} +3 -3
- package/dist/{FormSpotlight-AQTIA5TP.js → FormSpotlight-F2AAEGBN.js} +20 -6
- package/dist/{FormStage-FDTLTP3B.js → FormStage-BI5R5CNC.js} +27 -7
- package/dist/ManagedForm-G6COGHXL.js +16 -0
- package/dist/{ManagedNewsletterForm-J6QSAGGP.js → ManagedNewsletterForm-BO3WCGXX.js} +7 -5
- package/dist/{SignalCore-JZNXOLNT.js → SignalCore-ZA6WHKBR.js} +3 -3
- package/dist/SiteChat-YJADDTKG.js +5 -0
- package/dist/{SiteDesignReporter-W4EJUSTE.js → SiteDesignReporter-5YAW36AQ.js} +5 -5
- package/dist/SitePopups-ST5PMKZE.js +10 -0
- package/dist/SitemapSync-RJTEBINX.js +8 -0
- package/dist/_client/booking-widget.js +5 -5
- package/dist/affiliates/index.js +3 -3
- package/dist/analytics/index.js +4 -4
- package/dist/analytics/send-gate.d.ts +1 -1
- package/dist/articles/index.js +2 -2
- package/dist/articles/server-ui.js +3 -2
- package/dist/articles/server.js +2 -1
- package/dist/{engage → chat}/ChatWidget.d.ts +7 -6
- package/dist/{engage → chat}/EchoUiActions.d.ts +1 -1
- package/dist/chat/SiteChat.d.ts +25 -0
- package/dist/{engage → chat}/brand-color.d.ts +1 -1
- package/dist/{engage → chat}/chat-messages.d.ts +1 -1
- package/dist/{engage → chat}/echo-config.d.ts +1 -1
- package/dist/chat/index.d.ts +10 -6
- package/dist/chat/index.js +14 -8
- package/dist/{engage → chat}/launcher-placement.d.ts +1 -7
- package/dist/{engage → chat}/socket-loader.d.ts +2 -2
- package/dist/chat/types.d.ts +136 -0
- package/dist/chunk-27FISYK4.js +4 -0
- package/dist/{chunk-LUXVWITO.js → chunk-4NTBQNHA.js} +247 -78
- package/dist/{chunk-V3PUVBME.js → chunk-5V2V5C3Y.js} +2 -4
- package/dist/{chunk-Q4W23JYM.js → chunk-5YCEMV2L.js} +1 -1
- package/dist/{chunk-RHNWA34F.js → chunk-64DKGVEI.js} +41 -7
- package/dist/{chunk-GLHQ3LRO.js → chunk-6U3VLV2C.js} +1 -1
- package/dist/{chunk-WWSHFRDL.js → chunk-BC4Y3S3D.js} +1 -1
- package/dist/{chunk-JSZN6LDZ.js → chunk-BF7TZYC3.js} +38 -31
- package/dist/{chunk-M3YEPKP7.js → chunk-BKY2ZNM7.js} +1 -1
- package/dist/{chunk-AQSNPZY4.js → chunk-C2FZBUSS.js} +80 -1
- package/dist/{chunk-NK4CSJNP.js → chunk-CF5QNFYU.js} +2 -2
- package/dist/{chunk-D5EC5KVO.js → chunk-D5DCBD4Y.js} +2 -2
- package/dist/{chunk-3SDOQUUF.js → chunk-D6ZC7XKZ.js} +2 -2
- package/dist/chunk-EJVQJCG5.js +370 -0
- package/dist/{chunk-AH5Q262S.js → chunk-F24FNCTK.js} +1 -1
- package/dist/{chunk-V6FDQLR7.js → chunk-FR6BYFPC.js} +53 -21
- package/dist/{chunk-UXOGCKL6.js → chunk-GEXT7BTE.js} +1 -1
- package/dist/{chunk-JTU2GOM4.js → chunk-GGORNBSC.js} +18 -6
- package/dist/{chunk-ERXXITG4.js → chunk-HGFAEDG3.js} +1 -1
- package/dist/chunk-HODO5BX5.js +28 -0
- package/dist/chunk-HW7B43E5.js +14 -0
- package/dist/{chunk-CSTQDNGK.js → chunk-IAM3D3RL.js} +43 -24
- package/dist/{chunk-PGMVL4AB.js → chunk-JJ3DELUL.js} +2 -2
- package/dist/{chunk-ILU5I6RW.js → chunk-JMLK6MH7.js} +1 -1
- package/dist/{chunk-YEMPUQVU.js → chunk-JWTQS5F5.js} +2 -2
- package/dist/{chunk-VDF5DFWT.js → chunk-K4ZHAURD.js} +1 -1
- package/dist/chunk-NV72HZ4W.js +45 -0
- package/dist/{chunk-4Y5FWDPM.js → chunk-NZ4RXN3G.js} +55 -7
- package/dist/chunk-OWZ7ATLZ.js +187 -0
- package/dist/{chunk-TXBAOEKG.js → chunk-PKGN32AU.js} +5 -4
- package/dist/chunk-Q6E4OPGG.js +40 -0
- package/dist/{chunk-QEDHRBAT.js → chunk-QL6XNPSD.js} +2 -2
- package/dist/{chunk-JBE46QJZ.js → chunk-R46IQIGK.js} +1 -1
- package/dist/{chunk-6WIQCXOO.js → chunk-RPZ7OQGD.js} +1 -1
- package/dist/{chunk-PHYMNUJU.js → chunk-S54ECQGY.js} +1 -1
- package/dist/{chunk-VGH4MDTU.js → chunk-VHKEF5ZB.js} +1 -1
- package/dist/{chunk-HF57LG73.js → chunk-VO3JYRT5.js} +43 -29
- package/dist/chunk-VWWITFWM.js +300 -0
- package/dist/{chunk-CIG5UL2S.js → chunk-ZTLMPUO6.js} +3 -2
- package/dist/client/index.js +3 -3
- package/dist/commerce/index.js +4 -4
- package/dist/contracts/color.d.ts +1 -1
- package/dist/contracts/entries.d.ts +1 -1
- package/dist/contracts/error-page.d.ts +183 -0
- package/dist/contracts/llms.d.ts +1 -0
- package/dist/contracts/proposal-sitemap.d.ts +130 -0
- package/dist/contracts/schema-placeholders.d.ts +87 -0
- package/dist/engage/EngageWidget.d.ts +13 -12
- package/dist/engage/index.d.ts +10 -9
- package/dist/engage/index.js +31 -35
- package/dist/engage/types.d.ts +19 -244
- package/dist/fleet/FleetHeartbeat.d.ts +1 -1
- package/dist/fleet/index.js +4 -4
- package/dist/forms/FormEnhancer.d.ts +25 -12
- package/dist/forms/ServerForm.d.ts +11 -10
- package/dist/forms/StaticForm.d.ts +3 -1
- package/dist/forms/field-autocomplete.d.ts +28 -0
- package/dist/forms/form-dom-values.d.ts +42 -0
- package/dist/forms/index.js +11 -9
- package/dist/forms/server.js +6 -4
- package/dist/forms/static.js +3 -2
- package/dist/forms/submitForm.d.ts +8 -1
- package/dist/forms/types.d.ts +41 -2
- package/dist/forms/useForm.d.ts +21 -4
- package/dist/forms/webmcp.d.ts +38 -0
- package/dist/images/index.js +4 -4
- package/dist/index.d.ts +4 -1
- package/dist/index.js +1 -1
- package/dist/layout/SiteKitClientProviders.d.ts +3 -3
- package/dist/layout/SiteKitLayout.d.ts +4 -4
- package/dist/layout/client.d.ts +3 -3
- package/dist/layout/client.js +7 -7
- package/dist/layout/index.js +8 -8
- package/dist/layout/types.d.ts +5 -4
- package/dist/llms/contract.js +1 -1
- package/dist/llms/index.js +6 -6
- package/dist/maps/index.js +3 -3
- package/dist/mcp/index.js +2 -14
- package/dist/mcp/sonor.js +14 -11
- package/dist/revalidate/index.js +2 -2
- package/dist/seo/client.js +4 -4
- package/dist/seo/index.js +15 -8
- package/dist/seo/llms/contract.js +1 -1
- package/dist/seo/llms.js +6 -6
- package/dist/seo/register-sitemap-cli.js +1 -1
- package/dist/seo/sitemap.js +4 -4
- package/dist/server/index.js +2 -2
- package/dist/shared/dialog.d.ts +27 -0
- package/dist/shared/identity.d.ts +1 -1
- package/dist/shared/layers.d.ts +7 -0
- package/dist/shared/mid-form.d.ts +53 -0
- package/dist/shared/reporting-gate.d.ts +1 -1
- package/dist/shared/version.d.ts +1 -1
- package/dist/shared/visual-viewport-gap.d.ts +1 -1
- package/dist/signal/index.js +2 -2
- package/dist/signal/types.d.ts +1 -1
- package/dist/sitemap/index.js +4 -4
- package/dist/{socket-loader-R24ZSRSQ.js → socket-loader-CGIPEG74.js} +1 -1
- package/dist/sync/index.js +5 -5
- package/dist/types.d.ts +3 -1
- package/dist/{web-vitals.attribution-GD6LGLVF.js → web-vitals.attribution-N2PCCF4Q.js} +1 -1
- package/dist/website/BlocksPopup.d.ts +1 -1
- package/dist/website/PopupBlocks.d.ts +5 -2
- package/dist/website/SitePopups.d.ts +25 -0
- package/dist/website/images.js +4 -4
- package/dist/website/index.js +6 -6
- package/dist/website/popup-rules.d.ts +46 -0
- package/dist/website/popup-types.d.ts +113 -0
- package/dist/website/popups.d.ts +2 -6
- package/dist/website/popups.js +6 -14
- package/dist/{writeLLMsTxt-G3JBNBC5.js → writeLLMsTxt-OV24LQVL.js} +3 -3
- package/docs/MIGRATING-TO-7.md +41 -9
- package/docs.json +2 -1
- package/package.json +2 -2
- package/src/analytics/README.md +2 -2
- package/src/articles/README.md +4 -1
- package/src/{engage → chat}/README.md +63 -62
- package/src/forms/README.md +49 -3
- package/src/layout/README.md +8 -5
- package/src/seo/README.md +3 -1
- package/src/sync/README.md +10 -0
- package/src/website/README.md +133 -0
- package/dist/ChatWidget-UCDWMWCW.js +0 -15
- package/dist/EngageWidget-7ZYSK4GE.js +0 -11
- package/dist/ManagedForm-H7BVAH2W.js +0 -14
- package/dist/SitemapSync-XBANGKHZ.js +0 -8
- package/dist/chunk-NDF4A5JM.js +0 -37
- package/dist/chunk-VLARKWZU.js +0 -100
- package/dist/chunk-YCJT4JJG.js +0 -837
- package/dist/engage/DesignRenderer.d.ts +0 -57
- package/dist/engage/element-rules.d.ts +0 -38
|
@@ -89,4 +89,83 @@ function isFieldComplete(field, values, isVisible = (f) => isFieldVisible(f, val
|
|
|
89
89
|
return validateField(field, values, isVisible) === null;
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
-
|
|
92
|
+
// src/forms/form-dom-values.ts
|
|
93
|
+
function isUnreadable(field) {
|
|
94
|
+
return isDisplayOnly(field) || field.field_type === "file";
|
|
95
|
+
}
|
|
96
|
+
function controlsNamed(form, name) {
|
|
97
|
+
const out = [];
|
|
98
|
+
for (const el of Array.from(form.elements)) {
|
|
99
|
+
const control = el;
|
|
100
|
+
if (control.name === name && !control.disabled) out.push(control);
|
|
101
|
+
}
|
|
102
|
+
return out;
|
|
103
|
+
}
|
|
104
|
+
function isInput(el, type) {
|
|
105
|
+
return el.tagName === "INPUT" && el.type === type;
|
|
106
|
+
}
|
|
107
|
+
function isBlank(value) {
|
|
108
|
+
return isEmptyValue(value) || value === false || typeof value === "string" && value.trim() === "";
|
|
109
|
+
}
|
|
110
|
+
function readField(field, controls) {
|
|
111
|
+
switch (field.field_type) {
|
|
112
|
+
case "checkbox": {
|
|
113
|
+
const boxes = controls.filter((c) => isInput(c, "checkbox"));
|
|
114
|
+
if (boxes.length === 0) return void 0;
|
|
115
|
+
const isGroup = boxes.length > 1 || boxes[0].getAttribute("value") !== null;
|
|
116
|
+
return isGroup ? boxes.filter((b) => b.checked).map((b) => b.value) : boxes[0].checked;
|
|
117
|
+
}
|
|
118
|
+
case "radio": {
|
|
119
|
+
const chosen = controls.find((c) => isInput(c, "radio") && c.checked);
|
|
120
|
+
return chosen ? chosen.value : void 0;
|
|
121
|
+
}
|
|
122
|
+
case "rating": {
|
|
123
|
+
const chosen = controls.find((c) => isInput(c, "radio") && c.checked);
|
|
124
|
+
return chosen ? Number(chosen.value) : void 0;
|
|
125
|
+
}
|
|
126
|
+
case "multi-select": {
|
|
127
|
+
const select = controls.find((c) => c.tagName === "SELECT");
|
|
128
|
+
return select ? Array.from(select.selectedOptions, (o) => o.value) : void 0;
|
|
129
|
+
}
|
|
130
|
+
case "slider": {
|
|
131
|
+
const range = controls[0];
|
|
132
|
+
return range && range.value !== "" ? Number(range.value) : void 0;
|
|
133
|
+
}
|
|
134
|
+
default: {
|
|
135
|
+
const control = controls[0];
|
|
136
|
+
return control ? control.value : void 0;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
function readFormControlValues(form, fields, honeypotName) {
|
|
141
|
+
const out = {};
|
|
142
|
+
if (!form || !fields) return out;
|
|
143
|
+
for (const field of fields) {
|
|
144
|
+
if (!field.slug || field.slug === honeypotName || isUnreadable(field)) continue;
|
|
145
|
+
const controls = controlsNamed(form, field.slug);
|
|
146
|
+
if (controls.length === 0) continue;
|
|
147
|
+
const value = readField(field, controls);
|
|
148
|
+
if (!isBlank(value)) out[field.slug] = value;
|
|
149
|
+
}
|
|
150
|
+
return out;
|
|
151
|
+
}
|
|
152
|
+
function shellValuesToCarry(form, fields, honeypotName) {
|
|
153
|
+
const values = readFormControlValues(form, fields, honeypotName);
|
|
154
|
+
for (const field of fields || []) {
|
|
155
|
+
const value = values[field.slug];
|
|
156
|
+
if (value === void 0) continue;
|
|
157
|
+
const fallback = field.default_value ?? "";
|
|
158
|
+
if (!Array.isArray(value) && String(value) === String(fallback)) delete values[field.slug];
|
|
159
|
+
}
|
|
160
|
+
return values;
|
|
161
|
+
}
|
|
162
|
+
function unseenControlValues(form, fields, honeypotName, state) {
|
|
163
|
+
const dom = readFormControlValues(form, fields, honeypotName);
|
|
164
|
+
const unseen = {};
|
|
165
|
+
for (const [slug, value] of Object.entries(dom)) {
|
|
166
|
+
if (isBlank(state[slug])) unseen[slug] = value;
|
|
167
|
+
}
|
|
168
|
+
return unseen;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
export { isDisplayOnly, isEmptyValue, isFieldComplete, isFieldVisible, shellValuesToCarry, unseenControlValues, validateField };
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
import { sanitizeFleetVersion, buildFleetHeartbeatPayload } from './chunk-ZTZQPYP6.js';
|
|
3
3
|
import { useDeferredActivation } from './chunk-YC7ELZS3.js';
|
|
4
4
|
import { resolveAnalyticsTarget } from './chunk-43OCZ3JA.js';
|
|
5
|
-
import { sonorFetch } from './chunk-
|
|
6
|
-
import { SITE_KIT_VERSION } from './chunk-
|
|
5
|
+
import { sonorFetch } from './chunk-D6ZC7XKZ.js';
|
|
6
|
+
import { SITE_KIT_VERSION } from './chunk-F24FNCTK.js';
|
|
7
7
|
import { useRef, useEffect } from 'react';
|
|
8
8
|
|
|
9
9
|
// src/fleet/heartbeat.ts
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import { isEmptyValue, isDisplayOnly } from './chunk-
|
|
2
|
+
import { isEmptyValue, isDisplayOnly } from './chunk-C2FZBUSS.js';
|
|
3
3
|
import { useMemo, useState, useRef, useEffect } from 'react';
|
|
4
4
|
|
|
5
5
|
var NO_CONTROLS = {};
|
|
@@ -26,7 +26,7 @@ function useFieldControls(fields) {
|
|
|
26
26
|
}
|
|
27
27
|
if (needsFile && !requested.current.file) {
|
|
28
28
|
requested.current.file = true;
|
|
29
|
-
import('./FileField-
|
|
29
|
+
import('./FileField-CI4UL5SH.js').then((m) => {
|
|
30
30
|
if (!cancelled) setControls((prev) => ({ ...prev, File: m.FileField }));
|
|
31
31
|
}).catch(() => {
|
|
32
32
|
requested.current.file = false;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { isTokenMode, getFreshCredential, isSiteToken, refreshSiteToken, currentCredential, credentialBreakerId } from './chunk-
|
|
2
|
-
import { SITE_KIT_VERSION } from './chunk-
|
|
1
|
+
import { isTokenMode, getFreshCredential, isSiteToken, refreshSiteToken, currentCredential, credentialBreakerId } from './chunk-K4ZHAURD.js';
|
|
2
|
+
import { SITE_KIT_VERSION } from './chunk-F24FNCTK.js';
|
|
3
3
|
|
|
4
4
|
// src/shared/fetchWithRetry.ts
|
|
5
5
|
function backoffDelay(attempt, response) {
|
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { DEFAULT_WIDGET_Z_INDEX } from './chunk-27FISYK4.js';
|
|
3
|
+
import { getOrCreateVisitorId } from './chunk-24QZEO3Q.js';
|
|
4
|
+
import { resolveAnalyticsTarget } from './chunk-43OCZ3JA.js';
|
|
5
|
+
import { sonorFetch } from './chunk-D6ZC7XKZ.js';
|
|
6
|
+
import { useState, useEffect, useCallback, useRef } from 'react';
|
|
7
|
+
import ReactDOM from 'react-dom';
|
|
8
|
+
import dynamic from 'next/dynamic';
|
|
9
|
+
import { usePathname } from 'next/navigation';
|
|
10
|
+
import { jsx, Fragment } from 'react/jsx-runtime';
|
|
11
|
+
|
|
12
|
+
// src/shared/mid-form.ts
|
|
13
|
+
var BUTTON_TYPES = /* @__PURE__ */ new Set(["button", "submit", "reset", "image"]);
|
|
14
|
+
var UNREACHABLE = '[inert],[aria-hidden="true"],[data-sk-honeypot]';
|
|
15
|
+
var typedInto = /* @__PURE__ */ new WeakSet();
|
|
16
|
+
var watched = /* @__PURE__ */ new WeakSet();
|
|
17
|
+
function watchFormInput(doc = document) {
|
|
18
|
+
if (watched.has(doc)) return;
|
|
19
|
+
watched.add(doc);
|
|
20
|
+
const note = (e) => {
|
|
21
|
+
const target = e.composedPath?.()[0] ?? e.target;
|
|
22
|
+
if (target) typedInto.add(target);
|
|
23
|
+
};
|
|
24
|
+
doc.addEventListener("input", note, true);
|
|
25
|
+
doc.addEventListener("change", note, true);
|
|
26
|
+
}
|
|
27
|
+
function isFillable(el) {
|
|
28
|
+
if (!el) return false;
|
|
29
|
+
const tag = el.tagName;
|
|
30
|
+
if (tag !== "INPUT" && tag !== "TEXTAREA" && tag !== "SELECT") return false;
|
|
31
|
+
if (tag === "INPUT") {
|
|
32
|
+
const type = el.type;
|
|
33
|
+
if (type === "hidden" || BUTTON_TYPES.has(type)) return false;
|
|
34
|
+
}
|
|
35
|
+
return !el.closest(UNREACHABLE);
|
|
36
|
+
}
|
|
37
|
+
function belongsToForm(el) {
|
|
38
|
+
return Boolean(el.form ?? el.closest("form"));
|
|
39
|
+
}
|
|
40
|
+
function focused(doc) {
|
|
41
|
+
let el = doc.activeElement;
|
|
42
|
+
while (el?.shadowRoot?.activeElement) el = el.shadowRoot.activeElement;
|
|
43
|
+
return el;
|
|
44
|
+
}
|
|
45
|
+
function renderedSelected(option) {
|
|
46
|
+
return option.defaultSelected || option.hasAttribute("selected");
|
|
47
|
+
}
|
|
48
|
+
function selectChanged(select) {
|
|
49
|
+
const options = Array.from(select.options);
|
|
50
|
+
if (select.multiple) return options.some((o) => o.selected !== renderedSelected(o));
|
|
51
|
+
if (!select.value) return false;
|
|
52
|
+
const initial = [...options].reverse().find(renderedSelected) ?? options.find((o) => !o.disabled);
|
|
53
|
+
return select.options[select.selectedIndex] !== initial;
|
|
54
|
+
}
|
|
55
|
+
function isFilled(el) {
|
|
56
|
+
if (!isFillable(el)) return false;
|
|
57
|
+
const typed = typedInto.has(el);
|
|
58
|
+
if (!typed && (el.disabled || el.tagName !== "SELECT" && el.readOnly)) return false;
|
|
59
|
+
if (el.tagName === "SELECT") return selectChanged(el);
|
|
60
|
+
const field = el;
|
|
61
|
+
if (field.type === "checkbox" || field.type === "radio") {
|
|
62
|
+
const box = field;
|
|
63
|
+
return box.checked !== box.defaultChecked;
|
|
64
|
+
}
|
|
65
|
+
return field.value.trim() !== "" && (typed || field.value !== field.defaultValue);
|
|
66
|
+
}
|
|
67
|
+
function isVisitorMidForm(doc = document) {
|
|
68
|
+
if (doc.querySelector('[data-sk-state="submitting"]')) return true;
|
|
69
|
+
if (doc.querySelector('[data-sk-form-mount][data-sk-carried="true"] form')) return true;
|
|
70
|
+
const active = focused(doc);
|
|
71
|
+
if (active && belongsToForm(active) && (isFillable(active) || active.tagName === "IFRAME")) return true;
|
|
72
|
+
for (const form of Array.from(doc.forms)) {
|
|
73
|
+
for (const el of Array.from(form.elements)) if (isFilled(el)) return true;
|
|
74
|
+
}
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
function whenNotMidForm(open, options = {}) {
|
|
78
|
+
const { doc = document, settleMs = 1500, pollMs = 5e3 } = options;
|
|
79
|
+
if (!isVisitorMidForm(doc)) {
|
|
80
|
+
open();
|
|
81
|
+
return () => {
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
let done = false;
|
|
85
|
+
let settle;
|
|
86
|
+
const stop = () => {
|
|
87
|
+
done = true;
|
|
88
|
+
clearTimeout(settle);
|
|
89
|
+
clearInterval(poll);
|
|
90
|
+
doc.removeEventListener("focusout", onFocusOut, true);
|
|
91
|
+
};
|
|
92
|
+
const check = () => {
|
|
93
|
+
if (done || isVisitorMidForm(doc)) return;
|
|
94
|
+
stop();
|
|
95
|
+
open();
|
|
96
|
+
};
|
|
97
|
+
const onFocusOut = () => {
|
|
98
|
+
clearTimeout(settle);
|
|
99
|
+
settle = setTimeout(check, settleMs);
|
|
100
|
+
};
|
|
101
|
+
const poll = setInterval(check, pollMs);
|
|
102
|
+
doc.addEventListener("focusout", onFocusOut, true);
|
|
103
|
+
return stop;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// src/website/popup-rules.ts
|
|
107
|
+
function matchPath(pathname, pattern) {
|
|
108
|
+
if (pattern.endsWith("*")) return pathname.startsWith(pattern.slice(0, -1));
|
|
109
|
+
return pathname === pattern;
|
|
110
|
+
}
|
|
111
|
+
function deviceFromUserAgent(ua) {
|
|
112
|
+
if (/tablet|ipad|playbook|silk/i.test(ua)) return "tablet";
|
|
113
|
+
if (/mobile|iphone|ipod|android|blackberry|opera mini|iemobile/i.test(ua)) return "mobile";
|
|
114
|
+
return "desktop";
|
|
115
|
+
}
|
|
116
|
+
function seenKey(popupId) {
|
|
117
|
+
return `_engage_${popupId}`;
|
|
118
|
+
}
|
|
119
|
+
function isEligible(popup, pathname, device, store, now = Date.now()) {
|
|
120
|
+
const pages = popup.targeting?.pages;
|
|
121
|
+
if (pages) {
|
|
122
|
+
if (pages.exclude?.some((p) => matchPath(pathname, p))) return false;
|
|
123
|
+
if (pages.include && !pages.include.some((p) => matchPath(pathname, p))) return false;
|
|
124
|
+
}
|
|
125
|
+
if (popup.targeting?.devices && !popup.targeting.devices.includes(device)) return false;
|
|
126
|
+
const frequency = popup.trigger?.frequency;
|
|
127
|
+
if (frequency) {
|
|
128
|
+
const key = seenKey(popup.id);
|
|
129
|
+
if (frequency.type === "once") {
|
|
130
|
+
if (store.local?.getItem(key)) return false;
|
|
131
|
+
} else if (frequency.type === "once-per-session") {
|
|
132
|
+
if (store.session?.getItem(key)) return false;
|
|
133
|
+
} else if (frequency.type === "every-n-days" && frequency.days) {
|
|
134
|
+
const last = store.local?.getItem(key);
|
|
135
|
+
if (last && now - parseInt(last, 10) < frequency.days * 864e5) return false;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return true;
|
|
139
|
+
}
|
|
140
|
+
var PLACEMENT = {
|
|
141
|
+
popup: "popup",
|
|
142
|
+
bar: "bar",
|
|
143
|
+
nudge: "slide-in",
|
|
144
|
+
"slide-in": "slide-in"
|
|
145
|
+
};
|
|
146
|
+
function popupPlacement(popup) {
|
|
147
|
+
if (!popup.blocks?.length) return void 0;
|
|
148
|
+
return popup.layout?.placement ?? PLACEMENT[popup.type] ?? "popup";
|
|
149
|
+
}
|
|
150
|
+
function waitsForForms(popup) {
|
|
151
|
+
return popupPlacement(popup) !== "bar";
|
|
152
|
+
}
|
|
153
|
+
function activatePopup(active, id, popups) {
|
|
154
|
+
if (active.includes(id)) return active;
|
|
155
|
+
const isPopup = (popupId) => {
|
|
156
|
+
const popup = popups.find((p) => p.id === popupId);
|
|
157
|
+
return popup ? popupPlacement(popup) === "popup" : false;
|
|
158
|
+
};
|
|
159
|
+
if (isPopup(id) && active.some(isPopup)) return active;
|
|
160
|
+
return [...active, id];
|
|
161
|
+
}
|
|
162
|
+
var LazyBlocksPopup = dynamic(
|
|
163
|
+
() => import('./BlocksPopup-YJNJIVPO.js').then((m) => ({ default: m.BlocksPopup })),
|
|
164
|
+
{ ssr: false }
|
|
165
|
+
);
|
|
166
|
+
function SitePopups(props) {
|
|
167
|
+
const target = resolveAnalyticsTarget(props);
|
|
168
|
+
if (!target) return null;
|
|
169
|
+
return /* @__PURE__ */ jsx(AllowedSitePopups, { ...props, ...target });
|
|
170
|
+
}
|
|
171
|
+
function AllowedSitePopups({
|
|
172
|
+
apiUrl,
|
|
173
|
+
apiKey,
|
|
174
|
+
zIndex = DEFAULT_WIDGET_Z_INDEX,
|
|
175
|
+
debug = false
|
|
176
|
+
}) {
|
|
177
|
+
const pathname = usePathname();
|
|
178
|
+
const [popups, setPopups] = useState([]);
|
|
179
|
+
const [active, setActive] = useState([]);
|
|
180
|
+
const [dismissed, setDismissed] = useState(/* @__PURE__ */ new Set());
|
|
181
|
+
useEffect(() => {
|
|
182
|
+
let cancelled = false;
|
|
183
|
+
async function load() {
|
|
184
|
+
const visitorId = getOrCreateVisitorId();
|
|
185
|
+
const url = typeof window !== "undefined" ? window.location.href : "";
|
|
186
|
+
try {
|
|
187
|
+
const response = await sonorFetch(
|
|
188
|
+
`${apiUrl.replace(/\/$/, "")}/engage/widget/elements?url=${encodeURIComponent(url)}&visitorId=${encodeURIComponent(visitorId)}&deviceType=${getDeviceType()}`,
|
|
189
|
+
{},
|
|
190
|
+
{ apiKey }
|
|
191
|
+
);
|
|
192
|
+
if (!response.ok) {
|
|
193
|
+
if (debug) console.error("[SitePopups] Error loading popups:", response.statusText);
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
const json = await response.json();
|
|
197
|
+
const list = json.data?.elements ?? json.elements ?? [];
|
|
198
|
+
const drawable = list.filter((popup) => popupPlacement(popup) !== void 0);
|
|
199
|
+
if (debug) console.log("[SitePopups] Loaded popups:", drawable);
|
|
200
|
+
if (!cancelled) setPopups(drawable);
|
|
201
|
+
} catch (error) {
|
|
202
|
+
if (debug) console.error("[SitePopups] Error loading popups:", error);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
load();
|
|
206
|
+
return () => {
|
|
207
|
+
cancelled = true;
|
|
208
|
+
};
|
|
209
|
+
}, [apiUrl, apiKey, debug]);
|
|
210
|
+
useEffect(() => {
|
|
211
|
+
watchFormInput();
|
|
212
|
+
}, []);
|
|
213
|
+
useEffect(() => {
|
|
214
|
+
if (!popups.length) return;
|
|
215
|
+
const store = { local: storageOrNull("local"), session: storageOrNull("session") };
|
|
216
|
+
const device = getDeviceType();
|
|
217
|
+
const eligible = popups.filter((popup) => !dismissed.has(popup.id) && isEligible(popup, pathname, device, store));
|
|
218
|
+
if (debug) console.log("[SitePopups] Eligible popups:", eligible);
|
|
219
|
+
const eligibleIds = new Set(eligible.map((p) => p.id));
|
|
220
|
+
setActive((prev) => {
|
|
221
|
+
const kept = prev.filter((id) => eligibleIds.has(id));
|
|
222
|
+
return kept.length === prev.length ? prev : kept;
|
|
223
|
+
});
|
|
224
|
+
const cleanups = [];
|
|
225
|
+
const activate = (popup) => {
|
|
226
|
+
const show = () => setActive((prev) => activatePopup(prev, popup.id, popups));
|
|
227
|
+
if (waitsForForms(popup)) cleanups.push(whenNotMidForm(show));
|
|
228
|
+
else show();
|
|
229
|
+
};
|
|
230
|
+
eligible.forEach((popup) => {
|
|
231
|
+
const trigger = popup.trigger;
|
|
232
|
+
if (trigger?.type === "immediate" || !trigger?.type) {
|
|
233
|
+
activate(popup);
|
|
234
|
+
} else if (trigger.type === "delay" && trigger.delay) {
|
|
235
|
+
const timer = setTimeout(() => activate(popup), trigger.delay * 1e3);
|
|
236
|
+
cleanups.push(() => clearTimeout(timer));
|
|
237
|
+
} else if (trigger.type === "exit-intent") {
|
|
238
|
+
const handleMouseLeave = (e) => {
|
|
239
|
+
if (e.clientY < 10) {
|
|
240
|
+
activate(popup);
|
|
241
|
+
document.removeEventListener("mouseleave", handleMouseLeave);
|
|
242
|
+
}
|
|
243
|
+
};
|
|
244
|
+
document.addEventListener("mouseleave", handleMouseLeave);
|
|
245
|
+
cleanups.push(() => document.removeEventListener("mouseleave", handleMouseLeave));
|
|
246
|
+
} else if (trigger.type === "scroll" && trigger.scrollPercentage) {
|
|
247
|
+
const handleScroll = () => {
|
|
248
|
+
const scrollPercent = window.scrollY / (document.body.scrollHeight - window.innerHeight) * 100;
|
|
249
|
+
if (scrollPercent >= (trigger.scrollPercentage || 50)) {
|
|
250
|
+
activate(popup);
|
|
251
|
+
window.removeEventListener("scroll", handleScroll);
|
|
252
|
+
}
|
|
253
|
+
};
|
|
254
|
+
window.addEventListener("scroll", handleScroll, { passive: true });
|
|
255
|
+
cleanups.push(() => window.removeEventListener("scroll", handleScroll));
|
|
256
|
+
}
|
|
257
|
+
});
|
|
258
|
+
return () => {
|
|
259
|
+
cleanups.forEach((fn) => fn());
|
|
260
|
+
};
|
|
261
|
+
}, [popups, pathname, dismissed, debug]);
|
|
262
|
+
const recordSeen = useCallback((popupId) => {
|
|
263
|
+
const popup = popups.find((p) => p.id === popupId);
|
|
264
|
+
if (!popup?.trigger?.frequency) return;
|
|
265
|
+
try {
|
|
266
|
+
if (popup.trigger.frequency.type === "once-per-session") {
|
|
267
|
+
sessionStorage.setItem(seenKey(popupId), "true");
|
|
268
|
+
} else {
|
|
269
|
+
localStorage.setItem(seenKey(popupId), Date.now().toString());
|
|
270
|
+
}
|
|
271
|
+
} catch {
|
|
272
|
+
}
|
|
273
|
+
}, [popups]);
|
|
274
|
+
const handleDismiss = useCallback((popupId) => {
|
|
275
|
+
setDismissed((prev) => /* @__PURE__ */ new Set([...prev, popupId]));
|
|
276
|
+
setActive((prev) => prev.filter((id) => id !== popupId));
|
|
277
|
+
recordSeen(popupId);
|
|
278
|
+
}, [recordSeen]);
|
|
279
|
+
if (typeof document === "undefined" || !active.length) return null;
|
|
280
|
+
return ReactDOM.createPortal(
|
|
281
|
+
/* @__PURE__ */ jsx(Fragment, { children: active.map((popupId) => {
|
|
282
|
+
const popup = popups.find((p) => p.id === popupId);
|
|
283
|
+
if (!popup) return null;
|
|
284
|
+
return /* @__PURE__ */ jsx(
|
|
285
|
+
PopupView,
|
|
286
|
+
{
|
|
287
|
+
popup,
|
|
288
|
+
onDismiss: () => handleDismiss(popup.id),
|
|
289
|
+
onEngaged: () => recordSeen(popup.id),
|
|
290
|
+
zIndex,
|
|
291
|
+
apiUrl,
|
|
292
|
+
apiKey
|
|
293
|
+
},
|
|
294
|
+
popup.id
|
|
295
|
+
);
|
|
296
|
+
}) }),
|
|
297
|
+
document.body
|
|
298
|
+
);
|
|
299
|
+
}
|
|
300
|
+
function PopupView({
|
|
301
|
+
popup,
|
|
302
|
+
onDismiss,
|
|
303
|
+
onEngaged,
|
|
304
|
+
zIndex,
|
|
305
|
+
apiUrl,
|
|
306
|
+
apiKey
|
|
307
|
+
}) {
|
|
308
|
+
const rootRef = useRef(null);
|
|
309
|
+
const counted = useRef(false);
|
|
310
|
+
useEffect(() => {
|
|
311
|
+
const el = rootRef.current;
|
|
312
|
+
if (!el || counted.current) return;
|
|
313
|
+
const observer = new IntersectionObserver(
|
|
314
|
+
([entry]) => {
|
|
315
|
+
if (entry.isIntersecting && !counted.current) {
|
|
316
|
+
counted.current = true;
|
|
317
|
+
trackPopupEvent(apiUrl, apiKey, "impression", { elementId: popup.id });
|
|
318
|
+
observer.disconnect();
|
|
319
|
+
}
|
|
320
|
+
},
|
|
321
|
+
{ threshold: 0.5 }
|
|
322
|
+
);
|
|
323
|
+
observer.observe(el);
|
|
324
|
+
return () => observer.disconnect();
|
|
325
|
+
}, [apiUrl, apiKey, popup.id]);
|
|
326
|
+
const layout = popup.layout;
|
|
327
|
+
const position = layout?.corner ?? popup.config?.position;
|
|
328
|
+
const corner = position === "bottom-left" || position === "top-left" || position === "top-right" ? position : "bottom-right";
|
|
329
|
+
return /* @__PURE__ */ jsx(
|
|
330
|
+
LazyBlocksPopup,
|
|
331
|
+
{
|
|
332
|
+
blocks: popup.blocks,
|
|
333
|
+
placement: popupPlacement(popup) ?? "popup",
|
|
334
|
+
edge: layout?.edge,
|
|
335
|
+
accent: layout?.accent,
|
|
336
|
+
corner,
|
|
337
|
+
zIndex,
|
|
338
|
+
rootRef,
|
|
339
|
+
elementId: popup.id,
|
|
340
|
+
onClose: onDismiss,
|
|
341
|
+
onButton: (url) => {
|
|
342
|
+
onEngaged();
|
|
343
|
+
trackPopupEvent(apiUrl, apiKey, "click", { elementId: popup.id, action: "navigate", url });
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
);
|
|
347
|
+
}
|
|
348
|
+
function trackPopupEvent(apiUrl, apiKey, endpoint, data) {
|
|
349
|
+
const visitorId = typeof localStorage !== "undefined" ? localStorage.getItem("_sk_vid") : null;
|
|
350
|
+
sonorFetch(`${apiUrl.replace(/\/$/, "")}/engage/widget/${endpoint}`, {
|
|
351
|
+
method: "POST",
|
|
352
|
+
headers: { "Content-Type": "application/json" },
|
|
353
|
+
body: JSON.stringify({ ...data, visitorId, pageUrl: window.location.href }),
|
|
354
|
+
keepalive: true
|
|
355
|
+
}, { apiKey, retries: 0 }).catch(() => {
|
|
356
|
+
});
|
|
357
|
+
}
|
|
358
|
+
function getDeviceType() {
|
|
359
|
+
if (typeof navigator === "undefined") return "desktop";
|
|
360
|
+
return deviceFromUserAgent(navigator.userAgent);
|
|
361
|
+
}
|
|
362
|
+
function storageOrNull(kind) {
|
|
363
|
+
try {
|
|
364
|
+
return kind === "local" ? window.localStorage : window.sessionStorage;
|
|
365
|
+
} catch {
|
|
366
|
+
return null;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
export { SitePopups };
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { readAgentSubmit, formToolAttributes } from './chunk-Q6E4OPGG.js';
|
|
3
|
+
import { isFieldVisible, validateField, isFieldComplete, unseenControlValues } from './chunk-C2FZBUSS.js';
|
|
4
|
+
import { normalizeFormConfig, DEFAULT_FORM_SUCCESS_MESSAGE } from './chunk-5SQK3D53.js';
|
|
4
5
|
import { DEFAULT_HONEYPOT_FIELD } from './chunk-NJCTQH2P.js';
|
|
5
6
|
import { onPageLeave } from './chunk-L2V5PUFN.js';
|
|
6
7
|
import { uuid } from './chunk-GJWI74ZZ.js';
|
|
7
|
-
import { sonorFetch, sonorBeacon } from './chunk-
|
|
8
|
+
import { sonorFetch, sonorBeacon } from './chunk-D6ZC7XKZ.js';
|
|
8
9
|
import { useRef, useCallback, useEffect, useState, useMemo } from 'react';
|
|
9
10
|
|
|
10
11
|
// src/forms/field-interactions.ts
|
|
@@ -567,7 +568,8 @@ async function submitForm({
|
|
|
567
568
|
config,
|
|
568
569
|
values,
|
|
569
570
|
honeypotValue,
|
|
570
|
-
formLoadedAt
|
|
571
|
+
formLoadedAt,
|
|
572
|
+
agentInvoked
|
|
571
573
|
}) {
|
|
572
574
|
const { apiUrl, apiKey } = getApiConfig();
|
|
573
575
|
if (!apiKey) {
|
|
@@ -606,7 +608,8 @@ async function submitForm({
|
|
|
606
608
|
// Sub-site host — preserved on form_submissions for lead attribution
|
|
607
609
|
// across multi-site projects. Resolved by SiteKitClientProviders.
|
|
608
610
|
site: typeof window !== "undefined" ? window.__SITE_KIT_SITE__ || window.location.host : void 0,
|
|
609
|
-
_formLoadedAt: formLoadedAt
|
|
611
|
+
_formLoadedAt: formLoadedAt,
|
|
612
|
+
...agentInvoked ? { agentInvoked: true } : {}
|
|
610
613
|
}
|
|
611
614
|
};
|
|
612
615
|
const response = await sonorFetch(
|
|
@@ -800,23 +803,24 @@ function useForm(formIdOrSlug, options = {}) {
|
|
|
800
803
|
setErrors(newErrors);
|
|
801
804
|
return Object.keys(newErrors).length === 0;
|
|
802
805
|
}, [fields, validateField2]);
|
|
803
|
-
const
|
|
806
|
+
const validateAllFor = useCallback((vals) => {
|
|
807
|
+
const visible = (field) => isFieldVisible(field, vals);
|
|
804
808
|
const newErrors = {};
|
|
805
809
|
for (const field of allFields) {
|
|
806
|
-
const error =
|
|
810
|
+
const error = validateField(field, vals, visible);
|
|
807
811
|
if (error) newErrors[field.slug] = error;
|
|
808
812
|
}
|
|
809
813
|
setErrors(newErrors);
|
|
810
|
-
return
|
|
811
|
-
}, [allFields
|
|
812
|
-
const buildVisibleValues = useCallback(() => {
|
|
814
|
+
return newErrors;
|
|
815
|
+
}, [allFields]);
|
|
816
|
+
const buildVisibleValues = useCallback((vals) => {
|
|
813
817
|
const out = {};
|
|
814
818
|
for (const field of allFields) {
|
|
815
|
-
if (!
|
|
816
|
-
if (field.slug in
|
|
819
|
+
if (!isFieldVisible(field, vals)) continue;
|
|
820
|
+
if (field.slug in vals) out[field.slug] = vals[field.slug];
|
|
817
821
|
}
|
|
818
822
|
return out;
|
|
819
|
-
}, [allFields
|
|
823
|
+
}, [allFields]);
|
|
820
824
|
const setFieldValue = useCallback((key, value) => {
|
|
821
825
|
setValuesState((prev) => ({ ...prev, [key]: value }));
|
|
822
826
|
trackFieldChange(key);
|
|
@@ -862,19 +866,25 @@ function useForm(formIdOrSlug, options = {}) {
|
|
|
862
866
|
trackStepChange(targetStep);
|
|
863
867
|
}
|
|
864
868
|
}, [totalSteps, trackStepChange]);
|
|
865
|
-
const submit = useCallback(async () => {
|
|
866
|
-
if (!form) return;
|
|
867
|
-
if (isSubmittingRef.current) return;
|
|
868
|
-
|
|
869
|
+
const submit = useCallback(async (options2) => {
|
|
870
|
+
if (!form) return { status: "failed", message: "The form is still loading." };
|
|
871
|
+
if (isSubmittingRef.current) return { status: "busy" };
|
|
872
|
+
const domFills = options2 && typeof options2 === "object" && options2.domFills && typeof options2.domFills === "object" ? options2.domFills : null;
|
|
873
|
+
const agentInvoked = !!options2 && typeof options2 === "object" && options2.agentInvoked === true;
|
|
874
|
+
const vals = domFills && Object.keys(domFills).length > 0 ? { ...values, ...domFills } : values;
|
|
875
|
+
if (vals !== values) setValuesState(vals);
|
|
876
|
+
const invalid = validateAllFor(vals);
|
|
877
|
+
if (Object.keys(invalid).length > 0) return { status: "invalid", errors: invalid };
|
|
869
878
|
isSubmittingRef.current = true;
|
|
870
879
|
setIsSubmitting(true);
|
|
871
880
|
setSubmitError(null);
|
|
872
881
|
try {
|
|
873
882
|
const data = await submitForm({
|
|
874
883
|
config: form,
|
|
875
|
-
values: buildVisibleValues(),
|
|
884
|
+
values: buildVisibleValues(vals),
|
|
876
885
|
honeypotValue: "",
|
|
877
|
-
formLoadedAt: formLoadedAt()
|
|
886
|
+
formLoadedAt: formLoadedAt(),
|
|
887
|
+
agentInvoked
|
|
878
888
|
});
|
|
879
889
|
trackComplete();
|
|
880
890
|
setIsComplete(true);
|
|
@@ -883,15 +893,35 @@ function useForm(formIdOrSlug, options = {}) {
|
|
|
883
893
|
if (finalRedirect) {
|
|
884
894
|
window.location.href = finalRedirect;
|
|
885
895
|
}
|
|
896
|
+
const confirmation = typeof form.success_message === "string" && form.success_message.trim() ? form.success_message.trim() : DEFAULT_FORM_SUCCESS_MESSAGE;
|
|
897
|
+
return { status: "sent", message: confirmation, submissionId: data.submissionId || void 0 };
|
|
886
898
|
} catch (error) {
|
|
887
899
|
console.error("[useForm] Submission error:", error);
|
|
888
|
-
|
|
900
|
+
const message = "Something went wrong sending your submission. Please try again.";
|
|
901
|
+
setSubmitError(message);
|
|
889
902
|
onError?.(error);
|
|
903
|
+
return { status: "failed", message };
|
|
890
904
|
} finally {
|
|
891
905
|
isSubmittingRef.current = false;
|
|
892
906
|
setIsSubmitting(false);
|
|
893
907
|
}
|
|
894
|
-
}, [form,
|
|
908
|
+
}, [form, values, validateAllFor, buildVisibleValues, trackComplete, onSuccess, onError, redirectUrl]);
|
|
909
|
+
const handleSubmit = useCallback((event) => {
|
|
910
|
+
event.preventDefault();
|
|
911
|
+
const agent = readAgentSubmit(event.nativeEvent);
|
|
912
|
+
if (form?.is_multi_step && step < totalSteps) {
|
|
913
|
+
const moved = nextStep();
|
|
914
|
+
agent.respond(
|
|
915
|
+
Promise.resolve(
|
|
916
|
+
moved ? { status: "next_step", step: step + 1, totalSteps } : { status: "invalid", errors: {} }
|
|
917
|
+
)
|
|
918
|
+
);
|
|
919
|
+
return;
|
|
920
|
+
}
|
|
921
|
+
const domFills = unseenControlValues(event.currentTarget, allFields, "", values);
|
|
922
|
+
agent.respond(submit({ agentInvoked: agent.invoked, domFills }));
|
|
923
|
+
}, [form, step, totalSteps, nextStep, allFields, values, submit]);
|
|
924
|
+
const toolAttributes = useMemo(() => form ? formToolAttributes(form) : null, [form]);
|
|
895
925
|
const reset = useCallback(() => {
|
|
896
926
|
setValuesState(initialValues);
|
|
897
927
|
setErrors({});
|
|
@@ -926,6 +956,8 @@ function useForm(formIdOrSlug, options = {}) {
|
|
|
926
956
|
validateField: validateField2,
|
|
927
957
|
isFieldVisible: isFieldVisible2,
|
|
928
958
|
submit,
|
|
959
|
+
handleSubmit,
|
|
960
|
+
toolAttributes,
|
|
929
961
|
isSubmitting,
|
|
930
962
|
isComplete,
|
|
931
963
|
reset,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { locToPath, isMalformedSitemapPath, inferPageType } from './chunk-YVKRYQRG.js';
|
|
3
3
|
import { resolveAnalyticsTarget } from './chunk-43OCZ3JA.js';
|
|
4
|
-
import { sonorFetch } from './chunk-
|
|
4
|
+
import { sonorFetch } from './chunk-D6ZC7XKZ.js';
|
|
5
5
|
import { useRef, useEffect } from 'react';
|
|
6
6
|
|
|
7
7
|
var SYNC_STAMP_KEY = "_sk_sitemap_synced_at";
|