@nodii/onboarding 0.1.0 → 0.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/README.md +46 -0
- package/dist/{chunk-KQTS47FC.js → chunk-A3DE2IAH.js} +30 -5
- package/dist/chunk-A3DE2IAH.js.map +1 -0
- package/dist/{chunk-U6AXKGYQ.js → chunk-DWFZA5T6.js} +10 -8
- package/dist/chunk-DWFZA5T6.js.map +1 -0
- package/dist/{chunk-F75ZJERM.js → chunk-KFHVZGX6.js} +34 -14
- package/dist/chunk-KFHVZGX6.js.map +1 -0
- package/dist/{chunk-U56GQITG.js → chunk-NDSBIB3N.js} +25 -5
- package/dist/chunk-NDSBIB3N.js.map +1 -0
- package/dist/chunk-OLWR5COK.js +10 -0
- package/dist/chunk-OLWR5COK.js.map +1 -0
- package/dist/{chunk-IPAKPLIF.js → chunk-OVULPWNZ.js} +341 -80
- package/dist/chunk-OVULPWNZ.js.map +1 -0
- package/dist/{chunk-LVJM4CTG.js → chunk-T7EWURTF.js} +34 -19
- package/dist/chunk-T7EWURTF.js.map +1 -0
- package/dist/{chunk-BMQINH6O.js → chunk-UHOFGWI7.js} +5 -4
- package/dist/chunk-UHOFGWI7.js.map +1 -0
- package/dist/{chunk-SIMLMQPT.js → chunk-WKN4U7QF.js} +3 -5
- package/dist/chunk-WKN4U7QF.js.map +1 -0
- package/dist/{chunk-AZE3NPSY.js → chunk-ZR6X3GSM.js} +3 -3
- package/dist/{chunk-AZE3NPSY.js.map → chunk-ZR6X3GSM.js.map} +1 -1
- package/dist/{client-CqE2dF9A.d.ts → client-NvqPpfQP.d.ts} +1 -1
- package/dist/consent/index.d.ts +3 -3
- package/dist/consent/index.js +2 -2
- package/dist/{controller-BQb62D0N.d.ts → controller-BLH3wnxl.d.ts} +1 -1
- package/dist/dynamic/index.d.ts +13 -5
- package/dist/dynamic/index.js +4 -3
- package/dist/form/index.d.ts +12 -4
- package/dist/form/index.js +2 -2
- package/dist/{index-Dqfa890U.d.ts → index-BMSbQGWP.d.ts} +23 -3
- package/dist/index.d.ts +8 -8
- package/dist/index.js +9 -8
- package/dist/{model-mnjAEtKe.d.ts → model-BI_I-D_V.d.ts} +16 -2
- package/dist/{model-ESLSEbi0.d.ts → model-CEwvHlWA.d.ts} +14 -1
- package/dist/render-EWQXF73I.js +5 -0
- package/dist/{render-DC7P2BGQ.js.map → render-EWQXF73I.js.map} +1 -1
- package/dist/{schema-BrXb9gnh.d.ts → schema-BrtjpXfL.d.ts} +0 -10
- package/dist/{signup-client-BL5DfarJ.d.ts → signup-client-CS95nkVO.d.ts} +4 -4
- package/dist/spec/index.d.ts +3 -3
- package/dist/spec/index.js +2 -2
- package/dist/submit/index.d.ts +5 -5
- package/dist/submit/index.js +3 -2
- package/dist/viewer/index.d.ts +3 -3
- package/dist/viewer/index.js +1 -1
- package/dist/widget/index.d.ts +61 -22
- package/dist/widget/index.js +9 -8
- package/package.json +1 -1
- package/dist/chunk-BMQINH6O.js.map +0 -1
- package/dist/chunk-F75ZJERM.js.map +0 -1
- package/dist/chunk-IPAKPLIF.js.map +0 -1
- package/dist/chunk-KQTS47FC.js.map +0 -1
- package/dist/chunk-LVJM4CTG.js.map +0 -1
- package/dist/chunk-SIMLMQPT.js.map +0 -1
- package/dist/chunk-U56GQITG.js.map +0 -1
- package/dist/chunk-U6AXKGYQ.js.map +0 -1
- package/dist/render-DC7P2BGQ.js +0 -5
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import { createContactFormState } from './chunk-
|
|
2
|
-
import {
|
|
3
|
-
import { createSignupStepper, optionValue } from './chunk-
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
1
|
+
import { createContactFormState } from './chunk-DWFZA5T6.js';
|
|
2
|
+
import { fetchOnboardingSpec, OnboardingSpecCache, defaultSpecCache, diffSpecFields } from './chunk-KFHVZGX6.js';
|
|
3
|
+
import { createSignupStepper, optionValue } from './chunk-A3DE2IAH.js';
|
|
4
|
+
import { isNavigableUrl } from './chunk-NDSBIB3N.js';
|
|
5
|
+
import { computePayloadFingerprint, generateIdempotencyKey, submitLead, computeSignupFingerprint, submitSignup } from './chunk-UHOFGWI7.js';
|
|
6
|
+
import { contactFormSchema } from './chunk-WKN4U7QF.js';
|
|
7
|
+
import { OnboardingBotChallengeError, OnboardingRateLimitError, OnboardingSpecStaleError, OnboardingConsentStaleError, OnboardingConsentIncompleteError, OnboardingSubdomainTakenError, OnboardingValidationError } from './chunk-XJTJPBJB.js';
|
|
6
8
|
import { loadRecaptcha, executeRecaptcha } from './chunk-7NS7ENJV.js';
|
|
7
9
|
|
|
8
10
|
// src/widget/dom-utils.ts
|
|
@@ -219,6 +221,35 @@ var DEFAULT_WIDGET_CSS = `
|
|
|
219
221
|
margin-bottom: var(--_spacing);
|
|
220
222
|
}
|
|
221
223
|
|
|
224
|
+
fieldset.nodii-onboarding-field {
|
|
225
|
+
border: none;
|
|
226
|
+
padding: 0;
|
|
227
|
+
margin-inline: 0;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
.nodii-onboarding-choices {
|
|
231
|
+
display: flex;
|
|
232
|
+
flex-wrap: wrap;
|
|
233
|
+
gap: calc(var(--_spacing) * 0.5);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
.nodii-onboarding-choice {
|
|
237
|
+
display: inline-flex;
|
|
238
|
+
align-items: center;
|
|
239
|
+
gap: calc(var(--_spacing) * 0.375);
|
|
240
|
+
padding: calc(var(--_spacing) * 0.375) calc(var(--_spacing) * 0.75);
|
|
241
|
+
border: 1px solid var(--_border);
|
|
242
|
+
border-radius: 999px;
|
|
243
|
+
background: var(--_input-bg);
|
|
244
|
+
font-size: 0.875rem;
|
|
245
|
+
color: var(--_label);
|
|
246
|
+
cursor: pointer;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
fieldset.nodii-onboarding-field.has-error .nodii-onboarding-choice {
|
|
250
|
+
border-color: var(--_error);
|
|
251
|
+
}
|
|
252
|
+
|
|
222
253
|
.nodii-onboarding-consent-row {
|
|
223
254
|
display: flex;
|
|
224
255
|
align-items: flex-start;
|
|
@@ -456,30 +487,32 @@ function el(tag, attrs = {}, children = []) {
|
|
|
456
487
|
}
|
|
457
488
|
return element;
|
|
458
489
|
}
|
|
490
|
+
function errorSlot(id) {
|
|
491
|
+
return el("div", {
|
|
492
|
+
class: "nodii-onboarding-field-error",
|
|
493
|
+
id: `${id}-error`,
|
|
494
|
+
role: "alert",
|
|
495
|
+
"aria-live": "polite"
|
|
496
|
+
});
|
|
497
|
+
}
|
|
459
498
|
function createFieldEl(id, label, input, required) {
|
|
460
499
|
const labelEl = el(
|
|
461
500
|
"label",
|
|
462
501
|
{ for: id, class: `nodii-onboarding-label${required ? " required" : ""}` },
|
|
463
502
|
[label]
|
|
464
503
|
);
|
|
465
|
-
|
|
466
|
-
class: "nodii-onboarding-field-error",
|
|
467
|
-
id: `${id}-error`,
|
|
468
|
-
role: "alert",
|
|
469
|
-
"aria-live": "polite"
|
|
470
|
-
});
|
|
471
|
-
const field = el("div", { class: "nodii-onboarding-field" }, [
|
|
504
|
+
return el("div", { class: "nodii-onboarding-field" }, [
|
|
472
505
|
labelEl,
|
|
473
506
|
input,
|
|
474
|
-
|
|
507
|
+
errorSlot(id)
|
|
475
508
|
]);
|
|
476
|
-
return field;
|
|
477
509
|
}
|
|
478
510
|
function setFieldError(container, fieldId, message) {
|
|
479
511
|
const errorEl = container.querySelector(idSelector(`${fieldId}-error`));
|
|
480
512
|
if (errorEl) errorEl.textContent = message;
|
|
481
513
|
const inputEl = container.querySelector(idSelector(fieldId));
|
|
482
514
|
if (inputEl) inputEl.classList.add("has-error");
|
|
515
|
+
return errorEl !== null;
|
|
483
516
|
}
|
|
484
517
|
function clearFieldErrors(container) {
|
|
485
518
|
for (const el4 of container.querySelectorAll(
|
|
@@ -493,24 +526,91 @@ function clearFieldErrors(container) {
|
|
|
493
526
|
}
|
|
494
527
|
function applyErrors(container, errors) {
|
|
495
528
|
clearFieldErrors(container);
|
|
529
|
+
let unplaced = 0;
|
|
496
530
|
for (const err of errors) {
|
|
497
|
-
|
|
531
|
+
const field = err.path.split(".")[0] ?? err.path;
|
|
532
|
+
if (!setFieldError(container, `nodii-${field}`, err.message)) unplaced++;
|
|
498
533
|
}
|
|
534
|
+
return unplaced;
|
|
535
|
+
}
|
|
536
|
+
function assertHostValues(options) {
|
|
537
|
+
if (options.privacyUrl !== void 0 && !isNavigableUrl(options.privacyUrl)) {
|
|
538
|
+
throw new OnboardingValidationError(
|
|
539
|
+
"mountContactForm: invalid privacyUrl: must be an http(s) URL, absolute or relative"
|
|
540
|
+
);
|
|
541
|
+
}
|
|
542
|
+
const shape = contactFormSchema.shape;
|
|
543
|
+
for (const [name, schema, value] of [
|
|
544
|
+
["intakeKind", shape.intakeKind, options.intakeKind],
|
|
545
|
+
["attribution", shape.attribution, options.attribution]
|
|
546
|
+
]) {
|
|
547
|
+
if (value === void 0) continue;
|
|
548
|
+
const parsed = schema.safeParse(value);
|
|
549
|
+
if (!parsed.success) {
|
|
550
|
+
const issue = parsed.error.issues[0];
|
|
551
|
+
throw new OnboardingValidationError(
|
|
552
|
+
`mountContactForm: invalid ${[name, ...issue?.path ?? []].join(".")}: ${issue?.message ?? "invalid"}`
|
|
553
|
+
);
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
var DEFAULT_SPEC_REFRESH_MS = 5 * 60 * 1e3;
|
|
558
|
+
function privacyDocumentUrl(spec) {
|
|
559
|
+
const url = spec?.consentPack?.documents.find(
|
|
560
|
+
(d) => d.docType === "privacy"
|
|
561
|
+
)?.downloadUrl;
|
|
562
|
+
return url && isNavigableUrl(url) ? url : void 0;
|
|
563
|
+
}
|
|
564
|
+
function choicesOf(spec, key) {
|
|
565
|
+
const field = spec?.forms.contact.fields.find((f) => f.key === key);
|
|
566
|
+
return (field?.options ?? []).map((option) => {
|
|
567
|
+
const value = optionValue(option);
|
|
568
|
+
const label = option !== null && typeof option === "object" && typeof option.label === "string" ? option.label : value;
|
|
569
|
+
return { value, label };
|
|
570
|
+
});
|
|
571
|
+
}
|
|
572
|
+
function isRequired(spec, key) {
|
|
573
|
+
return spec?.forms.contact.fields.find((f) => f.key === key)?.required === true;
|
|
574
|
+
}
|
|
575
|
+
function labelOf(spec, key, fallback) {
|
|
576
|
+
const label = spec?.forms.contact.fields.find((f) => f.key === key)?.label;
|
|
577
|
+
return label?.trim() ? label : fallback;
|
|
499
578
|
}
|
|
500
579
|
function mountContactForm(host, options) {
|
|
580
|
+
assertHostValues(options);
|
|
501
581
|
injectWidgetStyles();
|
|
502
|
-
const
|
|
503
|
-
|
|
504
|
-
|
|
582
|
+
const spec = options.spec;
|
|
583
|
+
const interests = choicesOf(spec, "interestModules");
|
|
584
|
+
const sizes = choicesOf(spec, "sizeBand");
|
|
585
|
+
const interestRequired = interests.length > 0 && isRequired(spec, "interestModules");
|
|
586
|
+
const privacyUrl = options.privacyUrl ?? privacyDocumentUrl(spec);
|
|
587
|
+
const siteKey = options.siteKey ?? spec?.botChallenge?.siteKey;
|
|
588
|
+
const formControl = createContactFormState({
|
|
589
|
+
requireInterest: interestRequired
|
|
590
|
+
});
|
|
591
|
+
formControl.setValue("intakeKind", options.intakeKind ?? "enquiry");
|
|
592
|
+
if (options.attribution) {
|
|
593
|
+
formControl.setValue("attribution", options.attribution);
|
|
594
|
+
}
|
|
595
|
+
if (siteKey) {
|
|
596
|
+
loadRecaptcha(siteKey).catch(() => {
|
|
505
597
|
});
|
|
506
598
|
}
|
|
507
599
|
const wrapper = el("div", { class: "nodii-onboarding-widget" });
|
|
508
|
-
const
|
|
600
|
+
const companyInput = el("input", {
|
|
601
|
+
type: "text",
|
|
602
|
+
id: "nodii-companyName",
|
|
603
|
+
name: "companyName",
|
|
604
|
+
class: "nodii-onboarding-input",
|
|
605
|
+
autocomplete: "organization",
|
|
606
|
+
maxlength: "200",
|
|
607
|
+
required: "required"
|
|
608
|
+
});
|
|
609
|
+
const contactInput = el("input", {
|
|
509
610
|
type: "text",
|
|
510
|
-
id: "nodii-
|
|
511
|
-
name: "
|
|
611
|
+
id: "nodii-contactName",
|
|
612
|
+
name: "contactName",
|
|
512
613
|
class: "nodii-onboarding-input",
|
|
513
|
-
placeholder: "Your name",
|
|
514
614
|
autocomplete: "name",
|
|
515
615
|
maxlength: "200",
|
|
516
616
|
required: "required"
|
|
@@ -529,8 +629,8 @@ function mountContactForm(host, options) {
|
|
|
529
629
|
id: "nodii-phone",
|
|
530
630
|
name: "phone",
|
|
531
631
|
class: "nodii-onboarding-input",
|
|
532
|
-
|
|
533
|
-
|
|
632
|
+
autocomplete: "tel",
|
|
633
|
+
maxlength: "40"
|
|
534
634
|
});
|
|
535
635
|
const messageInput = el("textarea", {
|
|
536
636
|
id: "nodii-message",
|
|
@@ -540,6 +640,34 @@ function mountContactForm(host, options) {
|
|
|
540
640
|
maxlength: "4000",
|
|
541
641
|
rows: "4"
|
|
542
642
|
});
|
|
643
|
+
const interestBoxes = interests.map(
|
|
644
|
+
(choice) => el("input", {
|
|
645
|
+
type: "checkbox",
|
|
646
|
+
name: "interestModules",
|
|
647
|
+
value: choice.value
|
|
648
|
+
})
|
|
649
|
+
);
|
|
650
|
+
const sizeSelect = el(
|
|
651
|
+
"select",
|
|
652
|
+
{ id: "nodii-sizeBand", name: "sizeBand", class: "nodii-onboarding-input" },
|
|
653
|
+
[
|
|
654
|
+
el("option", { value: "" }, ["Choose\u2026"]),
|
|
655
|
+
...sizes.map(
|
|
656
|
+
(choice) => el("option", { value: choice.value }, [choice.label])
|
|
657
|
+
)
|
|
658
|
+
]
|
|
659
|
+
);
|
|
660
|
+
const privacyBox = el("input", {
|
|
661
|
+
type: "checkbox",
|
|
662
|
+
id: "nodii-privacyNoticeAcknowledged",
|
|
663
|
+
name: "privacyNoticeAcknowledged",
|
|
664
|
+
required: "required"
|
|
665
|
+
});
|
|
666
|
+
const marketingBox = el("input", {
|
|
667
|
+
type: "checkbox",
|
|
668
|
+
id: "nodii-marketingOptIn",
|
|
669
|
+
name: "marketingOptIn"
|
|
670
|
+
});
|
|
543
671
|
const serverErrorEl = el("div", {
|
|
544
672
|
class: "nodii-onboarding-server-error",
|
|
545
673
|
role: "alert",
|
|
@@ -563,60 +691,165 @@ function mountContactForm(host, options) {
|
|
|
563
691
|
},
|
|
564
692
|
[options.submitLabel ?? "Get in touch"]
|
|
565
693
|
);
|
|
566
|
-
const recaptchaNotice = el(
|
|
567
|
-
"p",
|
|
568
|
-
{ class: "nodii-onboarding-recaptcha-notice" },
|
|
569
|
-
[
|
|
570
|
-
"Protected by reCAPTCHA. ",
|
|
571
|
-
Object.assign(
|
|
572
|
-
el("a", {
|
|
573
|
-
href: "https://policies.google.com/privacy",
|
|
574
|
-
target: "_blank",
|
|
575
|
-
rel: "noopener noreferrer"
|
|
576
|
-
}),
|
|
577
|
-
{ textContent: "Privacy" }
|
|
578
|
-
),
|
|
579
|
-
" & ",
|
|
580
|
-
Object.assign(
|
|
581
|
-
el("a", {
|
|
582
|
-
href: "https://policies.google.com/terms",
|
|
583
|
-
target: "_blank",
|
|
584
|
-
rel: "noopener noreferrer"
|
|
585
|
-
}),
|
|
586
|
-
{ textContent: "Terms" }
|
|
587
|
-
)
|
|
588
|
-
]
|
|
589
|
-
);
|
|
590
694
|
const form = el("form", {
|
|
591
695
|
novalidate: "true",
|
|
592
696
|
"aria-label": "Contact us"
|
|
593
697
|
});
|
|
594
|
-
form.appendChild(createFieldEl("nodii-name", "Name", nameInput, true));
|
|
595
|
-
form.appendChild(createFieldEl("nodii-email", "Email", emailInput, true));
|
|
596
698
|
form.appendChild(
|
|
597
|
-
createFieldEl(
|
|
699
|
+
createFieldEl(
|
|
700
|
+
"nodii-companyName",
|
|
701
|
+
labelOf(spec, "companyName", "Company name"),
|
|
702
|
+
companyInput,
|
|
703
|
+
true
|
|
704
|
+
)
|
|
705
|
+
);
|
|
706
|
+
form.appendChild(
|
|
707
|
+
createFieldEl(
|
|
708
|
+
"nodii-contactName",
|
|
709
|
+
labelOf(spec, "contactName", "Your name"),
|
|
710
|
+
contactInput,
|
|
711
|
+
true
|
|
712
|
+
)
|
|
713
|
+
);
|
|
714
|
+
form.appendChild(
|
|
715
|
+
createFieldEl(
|
|
716
|
+
"nodii-email",
|
|
717
|
+
labelOf(spec, "email", "Email"),
|
|
718
|
+
emailInput,
|
|
719
|
+
true
|
|
720
|
+
)
|
|
721
|
+
);
|
|
722
|
+
form.appendChild(
|
|
723
|
+
createFieldEl(
|
|
724
|
+
"nodii-phone",
|
|
725
|
+
`${labelOf(spec, "phone", "Phone")} (optional)`,
|
|
726
|
+
phoneInput,
|
|
727
|
+
false
|
|
728
|
+
)
|
|
729
|
+
);
|
|
730
|
+
if (interests.length > 0) {
|
|
731
|
+
form.appendChild(
|
|
732
|
+
el(
|
|
733
|
+
"fieldset",
|
|
734
|
+
{ id: "nodii-interestModules", class: "nodii-onboarding-field" },
|
|
735
|
+
[
|
|
736
|
+
el(
|
|
737
|
+
"legend",
|
|
738
|
+
{
|
|
739
|
+
class: `nodii-onboarding-label${interestRequired ? " required" : ""}`
|
|
740
|
+
},
|
|
741
|
+
[labelOf(spec, "interestModules", "What are you interested in?")]
|
|
742
|
+
),
|
|
743
|
+
el(
|
|
744
|
+
"div",
|
|
745
|
+
{ class: "nodii-onboarding-choices" },
|
|
746
|
+
interests.map(
|
|
747
|
+
(choice, i) => el("label", { class: "nodii-onboarding-choice" }, [
|
|
748
|
+
interestBoxes[i],
|
|
749
|
+
choice.label
|
|
750
|
+
])
|
|
751
|
+
)
|
|
752
|
+
),
|
|
753
|
+
errorSlot("nodii-interestModules")
|
|
754
|
+
]
|
|
755
|
+
)
|
|
756
|
+
);
|
|
757
|
+
}
|
|
758
|
+
if (sizes.length > 0) {
|
|
759
|
+
form.appendChild(
|
|
760
|
+
createFieldEl(
|
|
761
|
+
"nodii-sizeBand",
|
|
762
|
+
`${labelOf(spec, "sizeBand", "Team size")} (optional)`,
|
|
763
|
+
sizeSelect,
|
|
764
|
+
false
|
|
765
|
+
)
|
|
766
|
+
);
|
|
767
|
+
}
|
|
768
|
+
form.appendChild(
|
|
769
|
+
createFieldEl(
|
|
770
|
+
"nodii-message",
|
|
771
|
+
`${labelOf(spec, "message", "Message")} (optional)`,
|
|
772
|
+
messageInput,
|
|
773
|
+
false
|
|
774
|
+
)
|
|
598
775
|
);
|
|
776
|
+
const privacyLabel = ["I have read the "];
|
|
777
|
+
let privacyLink = null;
|
|
778
|
+
if (privacyUrl) {
|
|
779
|
+
privacyLink = Object.assign(
|
|
780
|
+
el("a", {
|
|
781
|
+
href: privacyUrl,
|
|
782
|
+
target: "_blank",
|
|
783
|
+
rel: "noopener noreferrer"
|
|
784
|
+
}),
|
|
785
|
+
{ textContent: "privacy notice" }
|
|
786
|
+
);
|
|
787
|
+
privacyLabel.push(privacyLink);
|
|
788
|
+
} else {
|
|
789
|
+
privacyLabel.push("privacy notice");
|
|
790
|
+
}
|
|
599
791
|
form.appendChild(
|
|
600
|
-
|
|
792
|
+
el("div", { class: "nodii-onboarding-field" }, [
|
|
793
|
+
el("label", { class: "nodii-onboarding-consent-row" }, [
|
|
794
|
+
privacyBox,
|
|
795
|
+
el("span", {}, privacyLabel)
|
|
796
|
+
]),
|
|
797
|
+
errorSlot("nodii-privacyNoticeAcknowledged")
|
|
798
|
+
])
|
|
799
|
+
);
|
|
800
|
+
form.appendChild(
|
|
801
|
+
el("label", { class: "nodii-onboarding-consent-row" }, [
|
|
802
|
+
marketingBox,
|
|
803
|
+
el("span", {}, [
|
|
804
|
+
labelOf(spec, "marketingOptIn", "Send me occasional product updates")
|
|
805
|
+
])
|
|
806
|
+
])
|
|
601
807
|
);
|
|
602
808
|
form.appendChild(serverErrorEl);
|
|
603
809
|
form.appendChild(submitBtn);
|
|
604
|
-
|
|
810
|
+
if (siteKey) {
|
|
811
|
+
form.appendChild(
|
|
812
|
+
el("p", { class: "nodii-onboarding-recaptcha-notice" }, [
|
|
813
|
+
"Protected by reCAPTCHA. ",
|
|
814
|
+
Object.assign(
|
|
815
|
+
el("a", {
|
|
816
|
+
href: "https://policies.google.com/privacy",
|
|
817
|
+
target: "_blank",
|
|
818
|
+
rel: "noopener noreferrer"
|
|
819
|
+
}),
|
|
820
|
+
{ textContent: "Privacy" }
|
|
821
|
+
),
|
|
822
|
+
" & ",
|
|
823
|
+
Object.assign(
|
|
824
|
+
el("a", {
|
|
825
|
+
href: "https://policies.google.com/terms",
|
|
826
|
+
target: "_blank",
|
|
827
|
+
rel: "noopener noreferrer"
|
|
828
|
+
}),
|
|
829
|
+
{ textContent: "Terms" }
|
|
830
|
+
)
|
|
831
|
+
])
|
|
832
|
+
);
|
|
833
|
+
}
|
|
605
834
|
wrapper.appendChild(successEl);
|
|
606
835
|
wrapper.appendChild(form);
|
|
607
836
|
host.appendChild(wrapper);
|
|
608
|
-
|
|
609
|
-
formControl.setValue("
|
|
610
|
-
|
|
611
|
-
emailInput.addEventListener("input", () => {
|
|
837
|
+
function syncValues() {
|
|
838
|
+
formControl.setValue("companyName", companyInput.value);
|
|
839
|
+
formControl.setValue("contactName", contactInput.value);
|
|
612
840
|
formControl.setValue("email", emailInput.value);
|
|
613
|
-
});
|
|
614
|
-
phoneInput.addEventListener("input", () => {
|
|
615
841
|
formControl.setValue("phone", phoneInput.value || void 0);
|
|
616
|
-
});
|
|
617
|
-
messageInput.addEventListener("input", () => {
|
|
618
842
|
formControl.setValue("message", messageInput.value || void 0);
|
|
619
|
-
|
|
843
|
+
formControl.setValue(
|
|
844
|
+
"interestModules",
|
|
845
|
+
interestBoxes.filter((box) => box.checked).map((box) => box.value)
|
|
846
|
+
);
|
|
847
|
+
formControl.setValue("sizeBand", sizeSelect.value || void 0);
|
|
848
|
+
formControl.setValue("privacyNoticeAcknowledged", privacyBox.checked);
|
|
849
|
+
formControl.setValue("marketingOptIn", marketingBox.checked);
|
|
850
|
+
}
|
|
851
|
+
form.addEventListener("input", syncValues);
|
|
852
|
+
form.addEventListener("change", syncValues);
|
|
620
853
|
const submitLabel = options.submitLabel ?? "Get in touch";
|
|
621
854
|
function renderSubmitButton(submitting) {
|
|
622
855
|
while (submitBtn.firstChild) {
|
|
@@ -634,9 +867,10 @@ function mountContactForm(host, options) {
|
|
|
634
867
|
const unsubscribe = formControl.subscribe((state) => {
|
|
635
868
|
submitBtn.disabled = state.status === "submitting";
|
|
636
869
|
renderSubmitButton(state.status === "submitting");
|
|
637
|
-
applyErrors(wrapper, state.errors);
|
|
638
|
-
|
|
639
|
-
|
|
870
|
+
const unplaced = applyErrors(wrapper, state.errors);
|
|
871
|
+
const formError = state.serverError ?? (unplaced > 0 ? "This form can\u2019t be sent right now." : null);
|
|
872
|
+
if (formError) {
|
|
873
|
+
serverErrorEl.textContent = formError;
|
|
640
874
|
serverErrorEl.style.display = "";
|
|
641
875
|
} else {
|
|
642
876
|
serverErrorEl.style.display = "none";
|
|
@@ -650,10 +884,7 @@ function mountContactForm(host, options) {
|
|
|
650
884
|
let lastFingerprint = null;
|
|
651
885
|
form.addEventListener("submit", async (event) => {
|
|
652
886
|
event.preventDefault();
|
|
653
|
-
|
|
654
|
-
formControl.setValue("email", emailInput.value);
|
|
655
|
-
formControl.setValue("phone", phoneInput.value || void 0);
|
|
656
|
-
formControl.setValue("message", messageInput.value || void 0);
|
|
887
|
+
syncValues();
|
|
657
888
|
const valid = formControl.validate();
|
|
658
889
|
if (!valid) return;
|
|
659
890
|
formControl.setSubmitting();
|
|
@@ -664,9 +895,9 @@ function mountContactForm(host, options) {
|
|
|
664
895
|
lastFingerprint = fingerprint;
|
|
665
896
|
}
|
|
666
897
|
let firstToken;
|
|
667
|
-
if (
|
|
898
|
+
if (siteKey) {
|
|
668
899
|
try {
|
|
669
|
-
firstToken = await executeRecaptcha(
|
|
900
|
+
firstToken = await executeRecaptcha(siteKey, "contact_submit", {
|
|
670
901
|
timeoutMs: options.timeoutMs
|
|
671
902
|
});
|
|
672
903
|
} catch (recaptchaErr) {
|
|
@@ -683,14 +914,14 @@ function mountContactForm(host, options) {
|
|
|
683
914
|
usedFirst = true;
|
|
684
915
|
return firstToken;
|
|
685
916
|
}
|
|
686
|
-
return executeRecaptcha(
|
|
917
|
+
return executeRecaptcha(siteKey, "contact_submit", {
|
|
687
918
|
timeoutMs: options.timeoutMs
|
|
688
919
|
});
|
|
689
920
|
};
|
|
690
921
|
try {
|
|
691
922
|
await submitLead(values, {
|
|
692
923
|
baseUrl: options.baseUrl,
|
|
693
|
-
...
|
|
924
|
+
...siteKey ? { botToken: tokenProvider } : {},
|
|
694
925
|
idempotencyKey,
|
|
695
926
|
fetch: options.fetch,
|
|
696
927
|
timeoutMs: options.timeoutMs
|
|
@@ -717,21 +948,45 @@ function mountContactForm(host, options) {
|
|
|
717
948
|
}
|
|
718
949
|
}
|
|
719
950
|
});
|
|
951
|
+
const refreshMs = options.specRefreshMs ?? DEFAULT_SPEC_REFRESH_MS;
|
|
952
|
+
let refreshing = false;
|
|
953
|
+
const specRefresh = privacyLink && !options.privacyUrl && refreshMs > 0 ? setInterval(() => {
|
|
954
|
+
if (refreshing || !wrapper.isConnected) return;
|
|
955
|
+
refreshing = true;
|
|
956
|
+
fetchOnboardingSpec({
|
|
957
|
+
baseUrl: options.baseUrl,
|
|
958
|
+
onboarder: options.onboarder,
|
|
959
|
+
fetch: options.fetch,
|
|
960
|
+
timeoutMs: options.timeoutMs,
|
|
961
|
+
cache: new OnboardingSpecCache()
|
|
962
|
+
}).then(
|
|
963
|
+
(fresh) => {
|
|
964
|
+
const url = privacyDocumentUrl(fresh);
|
|
965
|
+
if (url && privacyLink) privacyLink.href = url;
|
|
966
|
+
},
|
|
967
|
+
() => {
|
|
968
|
+
}
|
|
969
|
+
).finally(() => {
|
|
970
|
+
refreshing = false;
|
|
971
|
+
});
|
|
972
|
+
}, refreshMs) : void 0;
|
|
720
973
|
return {
|
|
721
974
|
unmount() {
|
|
975
|
+
clearInterval(specRefresh);
|
|
722
976
|
unsubscribe();
|
|
723
977
|
host.removeChild(wrapper);
|
|
724
978
|
},
|
|
725
979
|
reset() {
|
|
726
980
|
idempotencyKey = null;
|
|
727
981
|
lastFingerprint = null;
|
|
982
|
+
form.reset();
|
|
728
983
|
formControl.reset();
|
|
984
|
+
formControl.setValue("intakeKind", options.intakeKind ?? "enquiry");
|
|
985
|
+
if (options.attribution) {
|
|
986
|
+
formControl.setValue("attribution", options.attribution);
|
|
987
|
+
}
|
|
729
988
|
form.style.display = "";
|
|
730
989
|
successEl.style.display = "none";
|
|
731
|
-
nameInput.value = "";
|
|
732
|
-
emailInput.value = "";
|
|
733
|
-
phoneInput.value = "";
|
|
734
|
-
messageInput.value = "";
|
|
735
990
|
}
|
|
736
991
|
};
|
|
737
992
|
}
|
|
@@ -840,7 +1095,7 @@ function buildGateAffordance(control, doc, opts) {
|
|
|
840
1095
|
"Loading document\u2026"
|
|
841
1096
|
])
|
|
842
1097
|
);
|
|
843
|
-
const importViewer = opts.importViewer ?? (() => import('./render-
|
|
1098
|
+
const importViewer = opts.importViewer ?? (() => import('./render-EWQXF73I.js'));
|
|
844
1099
|
const loadViewer = () => {
|
|
845
1100
|
void (async () => {
|
|
846
1101
|
try {
|
|
@@ -1491,6 +1746,12 @@ function mountSignupForm(host, options) {
|
|
|
1491
1746
|
control.validateAll();
|
|
1492
1747
|
control.setError("Please accept all required documents to continue.");
|
|
1493
1748
|
options.onError?.(err);
|
|
1749
|
+
} else if (err instanceof OnboardingSubdomainTakenError) {
|
|
1750
|
+
control.setAccountError(
|
|
1751
|
+
"subdomain",
|
|
1752
|
+
"This workspace address is already taken. Choose another one."
|
|
1753
|
+
);
|
|
1754
|
+
options.onError?.(err);
|
|
1494
1755
|
} else if (err instanceof OnboardingBotChallengeError) {
|
|
1495
1756
|
control.setError(
|
|
1496
1757
|
"Bot protection check failed. Please refresh the page and try again."
|
|
@@ -1656,5 +1917,5 @@ var OnboardingWidget = {
|
|
|
1656
1917
|
};
|
|
1657
1918
|
|
|
1658
1919
|
export { DEFAULT_WIDGET_CSS, OnboardingWidget, consentDocElementId, cssEscape, idSelector, injectWidgetStyles, mountContactForm, mountSignupForm, renderConsentStep, updateConsentStep };
|
|
1659
|
-
//# sourceMappingURL=chunk-
|
|
1660
|
-
//# sourceMappingURL=chunk-
|
|
1920
|
+
//# sourceMappingURL=chunk-OVULPWNZ.js.map
|
|
1921
|
+
//# sourceMappingURL=chunk-OVULPWNZ.js.map
|