@rtstic.dev/pulse 0.0.52 → 0.0.53
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/dist/form/index.js +2 -2
- package/package.json +1 -1
package/dist/form/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";(()=>{var T=Object.create;var y=Object.defineProperty;var M=Object.getOwnPropertyDescriptor;var L=Object.getOwnPropertyNames;var H=Object.getPrototypeOf,I=Object.prototype.hasOwnProperty;var q=(c=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(c,{get:(t,e)=>(typeof require<"u"?require:t)[e]}):c)(function(c){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+c+'" is not supported')});var k=(c,t,e,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of L(t))!I.call(c,n)&&n!==e&&y(c,n,{get:()=>t[n],enumerable:!(r=M(t,n))||r.enumerable});return c};var x=(c,t,e)=>(e=c!=null?T(H(c)):{},k(t||!c||!c.__esModule?y(e,"default",{value:c,enumerable:!0}):e,c));function S(c={}){let{root:t=document,initialCountry:e="us",separateDialCode:r=!0,countryCodeSelector:n='input[pulse-form-field="country-code"]',onInit:i,onError:o=
|
|
2
|
-
e.g. <script src="https://cdn.jsdelivr.net/npm/intl-tel-input@25/build/js/intlTelInput.min.js"><\/script>`),s)}function E(c,t){try{let e=c.getSelectedCountryData?.();if(!e?.dialCode)return;document.querySelectorAll(t).forEach(r=>{r.value=`+${e.dialCode}`})}catch{}}function F(c){return c.closest("[pulse-form-block]")?.getAttribute("pulse-field-name")??"unknown"}var v=window.location.host==="influur-staging.webflow.io";function d(c,...t){v&&console.warn(`[MSF:${c}]`,...t)}function m(c,...t){v&&console.error(`[MSF:${c}]`,...t)}var w={1:[{selector:'[data-action="back"]',property:"display",value:"none"},{selector:'[pricing-form-element="progress-fill"]',property:"width",value:"50%"},{selector:"[data-step-1-terms]",property:"display",value:"block"}],2:[{selector:'[data-action="back"]',property:"display",value:"flex"},{selector:'[pricing-form-element="progress-fill"]',property:"width",value:"100%"},{selector:"[data-step-1-terms]",property:"display",value:"none"}]},b=[{type:"company_type",name:"Record Label / Music Distributor","calender-name":"valeria","embed-url":"https://meetings.hubspot.com/valeria-angelini/pulse-valeria-and-alessandra?embed=true"},{type:"industry",name:"Financial Services","calender-name":"david","embed-url":"https://meetings.hubspot.com/david-zarate2?embed=true"},{type:"industry",name:"Sports","calender-name":"steven","embed-url":"https://meetings.hubspot.com/steven-campos?embed=true"},{type:"industry",name:"Beauty","calender-name":"albany","embed-url":"https://meetings.hubspot.com/david-zarate2?embed=true"},{type:"industry",name:"Music","calender-name":"steven","embed-url":"https://meetings.hubspot.com/steven-campos?embed=true"},{type:"industry",name:"Customer Packaged Goods","calender-name":"david","embed-url":"https://meetings.hubspot.com/david-zarate2?embed=true"},{type:"industry",name:"Other","calender-name":"david","embed-url":"https://meetings.hubspot.com/david-zarate2?embed=true"}],g={required:"This field is required",email_invalid:"Please enter a valid email address",email_company:"Please use your company email address",phone_invalid:"Please enter a valid phone number",selection_required:"Please select at least one option",legal_required:"You must accept this to continue"},A={"pulse-demo":["pulse-demo-only","common-fields"],"white-glove-services":["white-glove-only","common-fields"]},C={1:{heading:"Your info",subheading:"Pulse is launching March 2025. Spots for onboarding cohort 1 are limited.",counter:"Step 1/2"},2:{heading:"Personalize",subheading:"Help us personalize your demo.",counter:"Step 2/2"}},h=class{constructor(t,e){this.currentStepIndex=0;this.stepHasBeenValidated=!1;this.originalRequired=new WeakMap;this.fieldState=new Map;this.isFormSubmitted=!1;this.isFormStarted=!1;this.form=t,this.itiInstances=e,this.steps=Array.from(t.querySelectorAll('[data-msf="step"]')),this.steps.length===0&&m("init","No steps found! Check [data-msf='step'] selectors in HTML."),this.steps.forEach((r,n)=>{r.dataset.step||d("init",`Step element at index ${n} is missing data-step attribute`)}),this.bindEvents(),this.cacheOriginalRequiredState(),this.initializeFieldState(),this.showStep(0),this.applyFlowConditions(),this.syncAllFieldState()}bindEvents(){let t=()=>{this.isFormStarted||(this.isFormStarted=!0,this.startAbandonmentCheck())};this.form.addEventListener("input",t),this.form.addEventListener("change",t),this.form.addEventListener("click",e=>{let r=e.target;if(!r)return;let n=r.closest("[data-action]");if(!n)return;let i=n.dataset.action;i==="next"&&(e.preventDefault(),this.next()),i==="back"&&(e.preventDefault(),this.back())}),this.form.addEventListener("submit",e=>{e.preventDefault()}),this.form.addEventListener("input",e=>{let r=e.target;r&&(!(r instanceof HTMLInputElement)&&!(r instanceof HTMLTextAreaElement)&&!(r instanceof HTMLSelectElement)||this.handleLiveValidation())}),this.itiInstances.forEach((e,r)=>{r.addEventListener("countrychange",()=>{this.stepHasBeenValidated&&this.handleLiveValidation()})}),this.form.addEventListener("change",e=>{let r=e.target;r&&r instanceof HTMLInputElement&&r.type==="radio"&&r.name==="flow-type"&&this.applyFlowConditions()}),this.form.addEventListener("input",e=>{let r=e.target;if(!r)return;let n=r.closest("[data-field-key]");if(!n)return;let i=n.dataset.fieldKey;i&&this.updateFieldState(i)}),this.form.addEventListener("change",e=>{let r=e.target;if(!r)return;let n=r.closest("[data-field-key]");if(!n)return;let i=n.dataset.fieldKey;i&&this.updateFieldState(i)})}handleLiveValidation(){if(!this.stepHasBeenValidated)return;let t=this.validateStep(this.currentStepIndex);this.clearErrors(),Object.keys(t).length>0&&this.showErrors(t)}showStep(t){if(t<0||t>=this.steps.length){m("showStep",`Invalid step index: ${t} (total steps: ${this.steps.length})`);return}this.steps.forEach((r,n)=>{r.style.display=n===t?"flex":"none"}),this.currentStepIndex=t,this.stepHasBeenValidated=!1,this.clearErrors();let e=t+1;this.updateStepText(e),this.applyStepStyles(e)}next(){this.stepHasBeenValidated=!0;let t=this.validateStep(this.currentStepIndex);if(Object.keys(t).length>0){this.clearErrors(),this.showErrors(t),this.focusFirstError(t);return}this.clearErrors(),this.stepHasBeenValidated=!1;let e=this.currentStepIndex+1;if(e>=this.steps.length){let n=this.steps[this.currentStepIndex].querySelector('[data-action="next"]');if(n){let s=n.querySelector("[data-action-text]");s?s.textContent="Submitting...":d("next","No [data-action-text] element found inside next button")}else d("next","No [data-action='next'] button found in current step");this.mirrorFieldStateToDOM(),this.loadCalendarEmbed();let i=document.getElementById("webflow-form-submit"),o=document.getElementById("hubspot-form-submit");i||m("submit","Missing #webflow-form-submit button in DOM!"),o||m("submit","Missing #hubspot-form-submit button in DOM!"),i&&o?(this.setSubmissionType("manual"),i.click(),o.click(),this.isFormSubmitted=!0):m("submit","One or both submit buttons not found \u2014 form NOT submitted");return}this.showStep(e)}showErrors(t){Object.entries(t).forEach(([e,r])=>{let n=this.form.querySelector(`[data-required-group="${e}"]`)||this.form.querySelector(`[data-required-legal="${e}"]`);if(n){n.classList.add("has-error");let s=n.querySelector(".field-error");s||(s=document.createElement("div"),s.className="field-error",n.appendChild(s)),s.textContent=g[r],s.setAttribute("data-error-code",r);return}let i=this.form.querySelector(`[name="${e}"]`);if(!i){d("showErrors",`Cannot find field or group for error key: "${e}"`);return}i.classList.add("has-error");let o=i.parentElement?.querySelector(".field-error");o||(o=document.createElement("div"),o.className="field-error",i.parentElement?.appendChild(o)),o.textContent=g[r],o.setAttribute("data-error-code",r)})}clearErrors(){let t=this.form.querySelectorAll(".field-error"),e=this.form.querySelectorAll(".has-error");t.forEach(r=>r.remove()),e.forEach(r=>r.classList.remove("has-error"))}back(){let t=this.currentStepIndex-1;t<0||this.showStep(t)}getFieldsForStep(t){let e=this.steps[t];return e?Array.from(e.querySelectorAll("input, select, textarea")):(m("getFieldsForStep",`Step at index ${t} does not exist`),[])}validateStep(t){let e={};this.getFieldsForStep(t).forEach(s=>{let l=s.name;if(!l||s.type==="checkbox"||s.type==="radio")return;let a=s.value.trim();if(s.hasAttribute("required")&&!a){e[l]="required";return}if(s.type==="email"&&a){if(!this.isValidEmailFormat(a)){e[l]="email_invalid";return}if(!this.isCompanyEmail(a)){e[l]="email_company";return}}if(s.type==="tel"&&a&&this.validatePhoneField(s)){e[l]="phone_invalid";return}});let n=this.validateRequiredSelectionGroups(t),i=this.validateLegalGroups(t);return{...e,...n,...i}}validateRequiredSelectionGroups(t){let e=this.steps[t],r={};return e.querySelectorAll("[data-required-group]").forEach(i=>{let o=i.dataset.requiredGroup;if(!o)return;let l=Array.from(i.querySelectorAll('input[type="checkbox"], input[type="radio"]')).filter(u=>!u.disabled);if(l.length===0)return;l.some(u=>u.checked)||(r[o]="selection_required")}),r}validateLegalGroups(t){let e=this.steps[t],r={};return e.querySelectorAll("[data-required-legal]").forEach(i=>{let o=i.dataset.requiredLegal;if(!o)return;let s=i.querySelector('input[type="checkbox"]');!s||s.disabled||s.checked||(r[o]="legal_required")}),r}startAbandonmentCheck(){setTimeout(()=>{if(this.isFormSubmitted)return;let t=this.getFormStateJSON().find(s=>s["field-name"]==="email"),e=this.getFormStateJSON().find(s=>s["field-name"]==="first_name"),r=this.getFormStateJSON().find(s=>s["field-name"]==="last_name"),n=t&&t.value&&this.isValidEmailFormat(t.value),i=e&&e.value.trim().length>0,o=r&&r.value.trim().length>0;if(n&&i&&o){console.warn("[MSF] User is likely to skip the form submission \u2014 losing a lead. Email:",t.value),this.mirrorFieldStateToDOM();let s=document.getElementById("hubspot-form-submit");s?(this.setSubmissionType("automated"),s.click()):m("abandonCheck","Missing #hubspot-form-submit button in DOM!")}},30*60*1e3)}setSubmissionType(t){let e=document.getElementById("submission_type");e?e.value=t:d("setSubmissionType","No element found with id 'submission_type'")}isValidEmailFormat(t){return/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(t)}isCompanyEmail(t){let e=["gmail.com","yahoo.com","hotmail.com","outlook.com","icloud.com","aol.com"],r=t.split("@")[1]?.toLowerCase();return r?!e.includes(r):!1}validatePhoneField(t){let e=this.itiInstances.get(t);return e?t.value.trim()?e.isValidNumber()?null:"phone_invalid":null:(d("phoneValidation",`No ITI instance found for field "${t.name}" \u2014 skipping phone validation`),null)}focusFirstError(t){let e=Object.keys(t)[0];if(!e)return;let r=this.form.querySelector(`[data-required-group="${e}"]`)||this.form.querySelector(`[data-required-legal="${e}"]`);if(r){let i=r.querySelector("input, select, textarea");i&&i.focus();return}let n=this.form.querySelector(`[name="${e}"]`);n&&n.focus()}getFlowType(){let t=this.form.querySelector('[data-required-group="flow-type"]');return t?t.querySelector('input[type="radio"]:checked')?.value??null:(d("getFlowType",'No [data-required-group="flow-type"] element found'),null)}applyFlowConditions(){let t=this.getFlowType();if(!t)return;let e=A[t]||[];e.length===0&&d("flowConditions",`No FLOW_CONDITIONS entry for flow type: "${t}"`),this.form.querySelectorAll("[data-conditional]").forEach(n=>{let i=n.dataset.conditional;if(!i)return;let o=e.includes(i),s=n.querySelectorAll("input, select, textarea");if(o)n.style.display="",s.forEach(l=>{l.disabled=!1,this.originalRequired.get(l)&&l.setAttribute("required","true")});else{n.style.display="none",s.forEach(a=>{a.disabled=!0,a.removeAttribute("required"),a instanceof HTMLInputElement?a.type==="checkbox"||a.type==="radio"?a.checked=!1:a.value="":a instanceof HTMLSelectElement?a.selectedIndex=0:a instanceof HTMLTextAreaElement&&(a.value="");let u=a.closest("[data-field-key]");if(!u)return;let p=u.dataset.fieldKey;if(!p)return;let f=this.fieldState.get(p);f&&(f.required=!1,f.valid=!0,f.value="",this.fieldState.set(p,f))});let l=n.dataset.fieldKey;if(l){let a=this.fieldState.get(l);a&&(a.required=!1,a.valid=!0,a.value="",this.fieldState.set(l,a))}this.clearErrorsInBlock(n)}}),this.updateValidityForStep(this.currentStepIndex+1)}cacheOriginalRequiredState(){this.form.querySelectorAll("input, select, textarea").forEach(e=>{let r=e.hasAttribute("required");this.originalRequired.set(e,r)})}clearErrorsInBlock(t){t.querySelectorAll(".field-error").forEach(e=>e.remove()),t.querySelectorAll(".has-error").forEach(e=>e.classList.remove("has-error"))}initializeFieldState(){this.form.querySelectorAll("[data-field-key]").forEach(e=>{let r=e.dataset.fieldKey;if(!r)return;let n=e.closest("[data-msf='step']"),i=n?Number(n.dataset.step):this.currentStepIndex+1;n||d("initFieldState",`Field "${r}" is not inside a [data-msf="step"] element \u2014 defaulting to step ${i}`),this.fieldState.set(r,{"field-name":r,value:"",required:!1,valid:!0,"step-number":i})})}updateFieldState(t){let e=this.form.querySelector(`[data-field-key="${t}"]`);if(!e){d("updateFieldState",`No element found for field key: "${t}"`);return}let r="",n=!1;if(e.hasAttribute("data-group")){let l=Array.from(e.querySelectorAll("input[type='radio'], input[type='checkbox']")).filter(a=>!a.disabled);if(n=e.hasAttribute("data-required-group"),l.some(a=>a.type==="radio")){let a=l.find(u=>u.checked);a?r=a.closest("label")?.querySelector("span")?.textContent?.trim()??a.value??"":r=""}else r=l.filter(u=>u.checked).map(u=>u.closest("label")?.querySelector("span")?.textContent?.trim()??u.value??"").join(",")}else if(e.hasAttribute("data-required-legal")){let l=e.querySelector("input[type='checkbox']");l&&!l.disabled&&(n=!0,r=l.checked?"true":"false")}else(e instanceof HTMLInputElement||e instanceof HTMLSelectElement||e instanceof HTMLTextAreaElement)&&(n=e.hasAttribute("required")&&!e.disabled,e instanceof HTMLInputElement&&e.type==="checkbox"?r=e.checked?"true":"false":r=e.value.trim());let i=e.closest("[data-msf='step']"),o=i?Number(i.dataset.step):this.currentStepIndex+1,s=this.fieldState.get(t);if(!s){d("updateFieldState",`No state entry for key "${t}" \u2014 was it initialized?`);return}s.value=r,s.required=n,s["step-number"]=o,this.fieldState.set(t,s),this.updateValidityForStep(o)}updateValidityForStep(t){let e=this.steps.findIndex(i=>Number(i.dataset.step)===t);if(e===-1){d("updateValidity",`No step element found with data-step="${t}"`);return}let r=this.validateStep(e);Array.from(this.fieldState.values()).filter(i=>i["step-number"]===t).forEach(i=>{i.valid=!r[i["field-name"]]})}getFormStateJSON(){return Array.from(this.fieldState.values())}updateStepText(t){let e=C[t];if(!e){d("updateStepText",`No STEP_TEXT config for step ${t}`);return}if(e.heading){let r=this.form.querySelector('[data-dynamic-text="heading"]');r?r.textContent=e.heading:d("updateStepText",'Missing [data-dynamic-text="heading"] element')}if(e.subheading){let r=this.form.querySelector('[data-dynamic-text="subheading"]');r?r.textContent=e.subheading:d("updateStepText",'Missing [data-dynamic-text="subheading"] element')}if(e.counter){let r=this.form.querySelector('[data-dynamic-text="counter"]');r?r.textContent=e.counter:d("updateStepText",'Missing [data-dynamic-text="counter"] element')}}syncAllFieldState(){this.fieldState.forEach((t,e)=>{this.updateFieldState(e)})}mirrorFieldStateToDOM(){let t=this.getFormStateJSON(),e=document.getElementById("form-hubspot-book-a-demo");if(!e){m("mirror","HubSpot form #form-hubspot-book-a-demo NOT FOUND in DOM!");return}t.forEach(r=>{let n=e?.querySelector(`[data-mirror="${r["field-name"]}"]`);if(!n){d("mirror",`No mirror element for data-mirror="${r["field-name"]}"`);return}n instanceof HTMLInputElement&&n.disabled||(n instanceof HTMLInputElement?n.type==="checkbox"?n.checked=r.value==="true":n.type==="radio"?n.checked=n.value===r.value:n.value=r.value:n.value=r.value)})}resolveCalendarEntry(){let t=this.fieldState.get("company_type")?.value??"",e=this.fieldState.get("industry")?.value??"";switch(!0){case!!t:return b.find(r=>r.type==="company_type"&&r.name===t)??null;case!!e:return b.find(r=>r.type==="industry"&&r.name===e)??null;default:return null}}loadCalendarEmbed(){let t=document.querySelector("[hs-calender-block]");if(!t){m("calendar","No [hs-calender-block] element found in DOM!");return}let e=this.resolveCalendarEntry();if(!e){t.setAttribute("hs-calender-block-active","false"),t.innerHTML="",document.querySelectorAll("[hs-thankyou-block-active]").forEach(a=>a.setAttribute("hs-thankyou-block-active","true"));return}t.setAttribute("hs-calender-block-active","true"),t.innerHTML="",document.querySelectorAll("[hs-thankyou-block-active]").forEach(l=>l.setAttribute("hs-thankyou-block-active","false"));let n=document.createElement("div");n.className="meetings-iframe-container",n.setAttribute("data-src",e["embed-url"]),t.appendChild(n);let i="https://static.hsappstatic.net/MeetingsEmbed/ex/MeetingsEmbedCode.js",o=document.querySelector(`script[src="${i}"]`);o&&o.remove();let s=document.createElement("script");s.type="text/javascript",s.src=i,s.addEventListener("error",l=>{m("calendar","HubSpot meetings script FAILED to load:",l)}),t.appendChild(s)}applyStepStyles(t){let e=w[t];if(!e){d("applyStepStyles",`No STEP_STYLES config for step ${t}`);return}e.forEach(({selector:r,property:n,value:i})=>{let o=document.querySelectorAll(r);o.length===0&&d("applyStepStyles",`Selector "${r}" matched 0 elements`),o.forEach(s=>{s.style.setProperty(n,i)})})}};document.addEventListener("DOMContentLoaded",()=>{let c=document.querySelector('[data-msf="form"]');if(!c){m("boot",'No form element found with [data-msf="form"] \u2014 MultiStepForm NOT initialized');return}let t;try{t=S({root:c})}catch(e){m("boot","intl-tel-input initialization FAILED:",e),t=new Map}try{let e=new h(c,t);window.msf=e}catch(e){m("boot","MultiStepForm constructor THREW:",e)}});})();
|
|
1
|
+
"use strict";(()=>{var T=Object.create;var y=Object.defineProperty;var M=Object.getOwnPropertyDescriptor;var L=Object.getOwnPropertyNames;var H=Object.getPrototypeOf,I=Object.prototype.hasOwnProperty;var q=(c=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(c,{get:(t,e)=>(typeof require<"u"?require:t)[e]}):c)(function(c){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+c+'" is not supported')});var k=(c,t,e,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of L(t))!I.call(c,n)&&n!==e&&y(c,n,{get:()=>t[n],enumerable:!(r=M(t,n))||r.enumerable});return c};var x=(c,t,e)=>(e=c!=null?T(H(c)):{},k(t||!c||!c.__esModule?y(e,"default",{value:c,enumerable:!0}):e,c));function S(c={}){let{root:t=document,initialCountry:e="us",separateDialCode:r=!0,countryCodeSelector:n='input[pulse-form-field="country-code"]',onInit:i,onError:o=d=>console.warn(`[initIntlTelInput] ${d}`)}=c,s=new Map,l=window.intlTelInput;return l?(t.querySelectorAll('input[type="tel"]').forEach(d=>{try{let p=l(d,{initialCountry:e,separateDialCode:r,strictMode:!1,loadUtils:()=>import("https://cdn.jsdelivr.net/npm/intl-tel-input@25/build/js/utils.js")});s.set(d,p),E(p,n),d.addEventListener("countrychange",()=>{E(p,n)}),i?.(d,p)}catch(p){o(`Failed to init on input inside "${F(d)}"`,p)}}),s):(o(`intlTelInput not found on window. Include the script before calling this function.
|
|
2
|
+
e.g. <script src="https://cdn.jsdelivr.net/npm/intl-tel-input@25/build/js/intlTelInput.min.js"><\/script>`),s)}function E(c,t){try{let e=c.getSelectedCountryData?.();if(!e?.dialCode)return;document.querySelectorAll(t).forEach(r=>{r.value=`+${e.dialCode}`})}catch{}}function F(c){return c.closest("[pulse-form-block]")?.getAttribute("pulse-field-name")??"unknown"}var v=window.location.host==="influur-staging.webflow.io";function u(c,...t){v&&console.warn(`[MSF:${c}]`,...t)}function m(c,...t){v&&console.error(`[MSF:${c}]`,...t)}var w={1:[{selector:'[data-action="back"]',property:"display",value:"none"},{selector:'[pricing-form-element="progress-fill"]',property:"width",value:"50%"},{selector:"[data-step-1-terms]",property:"display",value:"block"}],2:[{selector:'[data-action="back"]',property:"display",value:"flex"},{selector:'[pricing-form-element="progress-fill"]',property:"width",value:"100%"},{selector:"[data-step-1-terms]",property:"display",value:"none"}]},b=[{type:"company_type",name:"Record Label / Music Distributor","calender-name":"valeria","embed-url":"https://meetings.hubspot.com/valeria-angelini/pulse-valeria-and-alessandra?embed=true"},{type:"industry",name:"Financial Services","calender-name":"david","embed-url":"https://meetings.hubspot.com/david-zarate2?embed=true"},{type:"industry",name:"Sports","calender-name":"steven","embed-url":"https://meetings.hubspot.com/steven-campos?embed=true"},{type:"industry",name:"Beauty","calender-name":"albany","embed-url":"https://meetings.hubspot.com/david-zarate2?embed=true"},{type:"industry",name:"Music","calender-name":"steven","embed-url":"https://meetings.hubspot.com/steven-campos?embed=true"},{type:"industry",name:"Customer Packaged Goods","calender-name":"david","embed-url":"https://meetings.hubspot.com/david-zarate2?embed=true"},{type:"industry",name:"Other","calender-name":"david","embed-url":"https://meetings.hubspot.com/david-zarate2?embed=true"}],g={required:"This field is required",email_invalid:"Please enter a valid email address",email_company:"Please use your company email address",phone_invalid:"Please enter a valid phone number",selection_required:"Please select at least one option",legal_required:"You must accept this to continue"},A={"pulse-demo":["pulse-demo-only","common-fields"],"white-glove-services":["white-glove-only","common-fields"]},C={1:{heading:"Your info",subheading:"Pulse is launching March 2025. Spots for onboarding cohort 1 are limited.",counter:"Step 1/2"},2:{heading:"Personalize",subheading:"Help us personalize your demo.",counter:"Step 2/2"}},h=class{constructor(t,e){this.currentStepIndex=0;this.stepHasBeenValidated=!1;this.originalRequired=new WeakMap;this.fieldState=new Map;this.isFormSubmitted=!1;this.isFormStarted=!1;this.form=t,this.itiInstances=e,this.steps=Array.from(t.querySelectorAll('[data-msf="step"]')),this.steps.length===0&&m("init","No steps found! Check [data-msf='step'] selectors in HTML."),this.steps.forEach((r,n)=>{r.dataset.step||u("init",`Step element at index ${n} is missing data-step attribute`)}),this.bindEvents(),this.cacheOriginalRequiredState(),this.initializeFieldState(),this.showStep(0),this.applyFlowConditions(),this.syncAllFieldState()}bindEvents(){let t=()=>{this.isFormStarted||(this.isFormStarted=!0,this.startAbandonmentCheck())};this.form.addEventListener("input",t),this.form.addEventListener("change",t),this.form.addEventListener("click",e=>{let r=e.target;if(!r)return;let n=r.closest("[data-action]");if(!n)return;let i=n.dataset.action;i==="next"&&(e.preventDefault(),this.next()),i==="back"&&(e.preventDefault(),this.back())}),this.form.addEventListener("submit",e=>{e.preventDefault()}),this.form.addEventListener("input",e=>{let r=e.target;r&&(!(r instanceof HTMLInputElement)&&!(r instanceof HTMLTextAreaElement)&&!(r instanceof HTMLSelectElement)||this.handleLiveValidation())}),this.itiInstances.forEach((e,r)=>{r.addEventListener("countrychange",()=>{this.stepHasBeenValidated&&this.handleLiveValidation()})}),this.form.addEventListener("change",e=>{let r=e.target;r&&r instanceof HTMLInputElement&&r.type==="radio"&&r.name==="flow-type"&&this.applyFlowConditions()}),this.form.addEventListener("input",e=>{let r=e.target;if(!r)return;let n=r.closest("[data-field-key]");if(!n)return;let i=n.dataset.fieldKey;i&&this.updateFieldState(i)}),this.form.addEventListener("change",e=>{let r=e.target;if(!r)return;let n=r.closest("[data-field-key]");if(!n)return;let i=n.dataset.fieldKey;i&&this.updateFieldState(i)})}handleLiveValidation(){if(!this.stepHasBeenValidated)return;let t=this.validateStep(this.currentStepIndex);this.clearErrors(),Object.keys(t).length>0&&this.showErrors(t)}showStep(t){if(t<0||t>=this.steps.length){m("showStep",`Invalid step index: ${t} (total steps: ${this.steps.length})`);return}this.steps.forEach((r,n)=>{r.style.display=n===t?"flex":"none"}),this.currentStepIndex=t,this.stepHasBeenValidated=!1,this.clearErrors();let e=t+1;this.updateStepText(e),this.applyStepStyles(e)}next(){this.stepHasBeenValidated=!0;let t=this.validateStep(this.currentStepIndex);if(Object.keys(t).length>0){this.clearErrors(),this.showErrors(t),this.focusFirstError(t);return}this.clearErrors(),this.stepHasBeenValidated=!1;let e=this.currentStepIndex+1;if(e>=this.steps.length){let n=this.steps[this.currentStepIndex].querySelector('[data-action="next"]');if(n){let s=n.querySelector("[data-action-text]");s?s.textContent="Submitting...":u("next","No [data-action-text] element found inside next button")}else u("next","No [data-action='next'] button found in current step");this.mirrorFieldStateToDOM(),this.loadCalendarEmbed();let i=document.getElementById("webflow-form-submit"),o=document.getElementById("hubspot-form-submit");i||m("submit","Missing #webflow-form-submit button in DOM!"),o||m("submit","Missing #hubspot-form-submit button in DOM!"),i&&o?(this.setSubmissionType("manual"),i.click(),o.click(),this.isFormSubmitted=!0):m("submit","One or both submit buttons not found \u2014 form NOT submitted");return}this.showStep(e)}showErrors(t){Object.entries(t).forEach(([e,r])=>{let n=this.form.querySelector(`[data-required-group="${e}"]`)||this.form.querySelector(`[data-required-legal="${e}"]`);if(n){n.classList.add("has-error");let s=n.querySelector(".field-error");s||(s=document.createElement("div"),s.className="field-error",n.appendChild(s)),s.textContent=g[r],s.setAttribute("data-error-code",r);return}let i=this.form.querySelector(`[name="${e}"]`);if(!i){u("showErrors",`Cannot find field or group for error key: "${e}"`);return}i.classList.add("has-error");let o=i.parentElement?.querySelector(".field-error");o||(o=document.createElement("div"),o.className="field-error",i.parentElement?.appendChild(o)),o.textContent=g[r],o.setAttribute("data-error-code",r)})}clearErrors(){let t=this.form.querySelectorAll(".field-error"),e=this.form.querySelectorAll(".has-error");t.forEach(r=>r.remove()),e.forEach(r=>r.classList.remove("has-error"))}back(){let t=this.currentStepIndex-1;t<0||this.showStep(t)}getFieldsForStep(t){let e=this.steps[t];return e?Array.from(e.querySelectorAll("input, select, textarea")):(m("getFieldsForStep",`Step at index ${t} does not exist`),[])}validateStep(t){let e={};this.getFieldsForStep(t).forEach(s=>{let l=s.name;if(!l||s.type==="checkbox"||s.type==="radio")return;let a=s.value.trim();if(s.hasAttribute("required")&&!a){e[l]="required";return}if(s.type==="email"&&a){if(!this.isValidEmailFormat(a)){e[l]="email_invalid";return}if(!this.isCompanyEmail(a)){e[l]="email_company";return}}if(s.type==="tel"&&a&&this.validatePhoneField(s)){e[l]="phone_invalid";return}});let n=this.validateRequiredSelectionGroups(t),i=this.validateLegalGroups(t);return{...e,...n,...i}}validateRequiredSelectionGroups(t){let e=this.steps[t],r={};return e.querySelectorAll("[data-required-group]").forEach(i=>{let o=i.dataset.requiredGroup;if(!o)return;let l=Array.from(i.querySelectorAll('input[type="checkbox"], input[type="radio"]')).filter(d=>!d.disabled);if(l.length===0)return;l.some(d=>d.checked)||(r[o]="selection_required")}),r}validateLegalGroups(t){let e=this.steps[t],r={};return e.querySelectorAll("[data-required-legal]").forEach(i=>{let o=i.dataset.requiredLegal;if(!o)return;let s=i.querySelector('input[type="checkbox"]');!s||s.disabled||s.checked||(r[o]="legal_required")}),r}startAbandonmentCheck(){setTimeout(()=>{if(this.isFormSubmitted)return;let t=this.getFormStateJSON().find(s=>s["field-name"]==="email"),e=this.getFormStateJSON().find(s=>s["field-name"]==="first_name"),r=this.getFormStateJSON().find(s=>s["field-name"]==="last_name"),n=t&&t.value&&this.isValidEmailFormat(t.value),i=e&&e.value.trim().length>0,o=r&&r.value.trim().length>0;if(n&&i&&o){console.warn("[MSF] User is likely to skip the form submission \u2014 losing a lead. Email:",t.value),this.mirrorFieldStateToDOM();let s=document.getElementById("hubspot-form-submit");s?(this.setSubmissionType("automated"),s.click()):m("abandonCheck","Missing #hubspot-form-submit button in DOM!")}},30*60*1e3)}setSubmissionType(t){let e=document.getElementById("submission_type");e?e.value=t:u("setSubmissionType","No element found with id 'submission_type'")}isValidEmailFormat(t){return/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(t)}isCompanyEmail(t){let e=["gmail.com","yahoo.com","hotmail.com","outlook.com","icloud.com","aol.com"],r=t.split("@")[1]?.toLowerCase();return r?!e.includes(r):!1}validatePhoneField(t){let e=this.itiInstances.get(t);return e?t.value.trim()?e.isValidNumber()?null:"phone_invalid":null:(u("phoneValidation",`No ITI instance found for field "${t.name}" \u2014 skipping phone validation`),null)}focusFirstError(t){let e=Object.keys(t)[0];if(!e)return;let r=this.form.querySelector(`[data-required-group="${e}"]`)||this.form.querySelector(`[data-required-legal="${e}"]`);if(r){let i=r.querySelector("input, select, textarea");i&&i.focus();return}let n=this.form.querySelector(`[name="${e}"]`);n&&n.focus()}getFlowType(){let t=this.form.querySelector('[data-required-group="flow-type"]');return t?t.querySelector('input[type="radio"]:checked')?.value??null:(u("getFlowType",'No [data-required-group="flow-type"] element found'),null)}applyFlowConditions(){let t=this.getFlowType();if(!t)return;let e=A[t]||[];e.length===0&&u("flowConditions",`No FLOW_CONDITIONS entry for flow type: "${t}"`),this.form.querySelectorAll("[data-conditional]").forEach(n=>{let i=n.dataset.conditional;if(!i)return;let o=e.includes(i),s=n.querySelectorAll("input, select, textarea");if(o)n.style.display="",s.forEach(l=>{l.disabled=!1,this.originalRequired.get(l)&&l.setAttribute("required","true")});else{n.style.display="none",s.forEach(a=>{a.disabled=!0,a.removeAttribute("required"),a instanceof HTMLInputElement?a.type==="checkbox"||a.type==="radio"?a.checked=!1:a.value="":a instanceof HTMLSelectElement?a.selectedIndex=0:a instanceof HTMLTextAreaElement&&(a.value="");let d=a.closest("[data-field-key]");if(!d)return;let p=d.dataset.fieldKey;if(!p)return;let f=this.fieldState.get(p);f&&(f.required=!1,f.valid=!0,f.value="",this.fieldState.set(p,f))});let l=n.dataset.fieldKey;if(l){let a=this.fieldState.get(l);a&&(a.required=!1,a.valid=!0,a.value="",this.fieldState.set(l,a))}this.clearErrorsInBlock(n)}}),this.updateValidityForStep(this.currentStepIndex+1)}cacheOriginalRequiredState(){this.form.querySelectorAll("input, select, textarea").forEach(e=>{let r=e.hasAttribute("required");this.originalRequired.set(e,r)})}clearErrorsInBlock(t){t.querySelectorAll(".field-error").forEach(e=>e.remove()),t.querySelectorAll(".has-error").forEach(e=>e.classList.remove("has-error"))}initializeFieldState(){this.form.querySelectorAll("[data-field-key]").forEach(e=>{let r=e.dataset.fieldKey;if(!r)return;let n=e.closest("[data-msf='step']"),i=n?Number(n.dataset.step):this.currentStepIndex+1;n||u("initFieldState",`Field "${r}" is not inside a [data-msf="step"] element \u2014 defaulting to step ${i}`),this.fieldState.set(r,{"field-name":r,value:"",required:!1,valid:!0,"step-number":i})})}updateFieldState(t){let e=this.form.querySelector(`[data-field-key="${t}"]`);if(!e){u("updateFieldState",`No element found for field key: "${t}"`);return}let r="",n=!1;if(e.hasAttribute("data-group")){let l=Array.from(e.querySelectorAll("input[type='radio'], input[type='checkbox']")).filter(a=>!a.disabled);if(n=e.hasAttribute("data-required-group"),l.some(a=>a.type==="radio")){let a=l.find(d=>d.checked);a?r=a.closest("label")?.querySelector("span")?.textContent?.trim()??a.value??"":r=""}else r=l.filter(d=>d.checked).map(d=>d.closest("label")?.querySelector("span")?.textContent?.trim()??d.value??"").join(",")}else if(e.hasAttribute("data-required-legal")){let l=e.querySelector("input[type='checkbox']");l&&!l.disabled&&(n=!0,r=l.checked?"true":"false")}else(e instanceof HTMLInputElement||e instanceof HTMLSelectElement||e instanceof HTMLTextAreaElement)&&(n=e.hasAttribute("required")&&!e.disabled,e instanceof HTMLInputElement&&e.type==="checkbox"?r=e.checked?"true":"false":r=e.value.trim());let i=e.closest("[data-msf='step']"),o=i?Number(i.dataset.step):this.currentStepIndex+1,s=this.fieldState.get(t);if(!s){u("updateFieldState",`No state entry for key "${t}" \u2014 was it initialized?`);return}s.value=r,s.required=n,s["step-number"]=o,this.fieldState.set(t,s),this.updateValidityForStep(o)}updateValidityForStep(t){let e=this.steps.findIndex(i=>Number(i.dataset.step)===t);if(e===-1){u("updateValidity",`No step element found with data-step="${t}"`);return}let r=this.validateStep(e);Array.from(this.fieldState.values()).filter(i=>i["step-number"]===t).forEach(i=>{i.valid=!r[i["field-name"]]})}getFormStateJSON(){return Array.from(this.fieldState.values())}updateStepText(t){let e=C[t];if(!e){u("updateStepText",`No STEP_TEXT config for step ${t}`);return}if(e.heading){let r=this.form.querySelector('[data-dynamic-text="heading"]');r?r.textContent=e.heading:u("updateStepText",'Missing [data-dynamic-text="heading"] element')}if(e.subheading){let r=this.form.querySelector('[data-dynamic-text="subheading"]');r?r.textContent=e.subheading:u("updateStepText",'Missing [data-dynamic-text="subheading"] element')}if(e.counter){let r=this.form.querySelector('[data-dynamic-text="counter"]');r?r.textContent=e.counter:u("updateStepText",'Missing [data-dynamic-text="counter"] element')}}syncAllFieldState(){this.fieldState.forEach((t,e)=>{this.updateFieldState(e)})}mirrorFieldStateToDOM(){let t=this.getFormStateJSON(),e=document.getElementById("form-hubspot-book-a-demo");if(!e){m("mirror","HubSpot form #form-hubspot-book-a-demo NOT FOUND in DOM!");return}t.forEach(r=>{let n=e?.querySelector(`[data-mirror="${r["field-name"]}"]`);if(!n){u("mirror",`No mirror element for data-mirror="${r["field-name"]}"`);return}n instanceof HTMLInputElement&&n.disabled||(n instanceof HTMLInputElement?n.type==="checkbox"?n.checked=r.value==="true":n.type==="radio"?n.checked=n.value===r.value:n.value=r.value:n.value=r.value)})}resolveCalendarEntry(){let t=this.fieldState.get("company_type")?.value??"",e=this.fieldState.get("industry")?.value??"";return b.find(r=>r.type==="company_type"&&r.name===t)??b.find(r=>r.type==="industry"&&r.name===e)??null}loadCalendarEmbed(){let t=document.querySelector("[hs-calender-block]");if(!t){m("calendar","No [hs-calender-block] element found in DOM!");return}let e=this.resolveCalendarEntry();if(!e){t.setAttribute("hs-calender-block-active","false"),t.innerHTML="",document.querySelectorAll("[hs-thankyou-block-active]").forEach(a=>a.setAttribute("hs-thankyou-block-active","true"));return}t.setAttribute("hs-calender-block-active","true"),t.innerHTML="",document.querySelectorAll("[hs-thankyou-block-active]").forEach(l=>l.setAttribute("hs-thankyou-block-active","false"));let n=document.createElement("div");n.className="meetings-iframe-container",n.setAttribute("data-src",e["embed-url"]),t.appendChild(n);let i="https://static.hsappstatic.net/MeetingsEmbed/ex/MeetingsEmbedCode.js",o=document.querySelector(`script[src="${i}"]`);o&&o.remove();let s=document.createElement("script");s.type="text/javascript",s.src=i,s.addEventListener("error",l=>{m("calendar","HubSpot meetings script FAILED to load:",l)}),t.appendChild(s)}applyStepStyles(t){let e=w[t];if(!e){u("applyStepStyles",`No STEP_STYLES config for step ${t}`);return}e.forEach(({selector:r,property:n,value:i})=>{let o=document.querySelectorAll(r);o.length===0&&u("applyStepStyles",`Selector "${r}" matched 0 elements`),o.forEach(s=>{s.style.setProperty(n,i)})})}};document.addEventListener("DOMContentLoaded",()=>{let c=document.querySelector('[data-msf="form"]');if(!c){m("boot",'No form element found with [data-msf="form"] \u2014 MultiStepForm NOT initialized');return}let t;try{t=S({root:c})}catch(e){m("boot","intl-tel-input initialization FAILED:",e),t=new Map}try{let e=new h(c,t);window.msf=e}catch(e){m("boot","MultiStepForm constructor THREW:",e)}});})();
|