@rtstic.dev/pulse 0.0.55 → 0.0.56

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.
@@ -1,2 +1,790 @@
1
- "use strict";(()=>{var Q=Object.create;var R=Object.defineProperty;var G=Object.getOwnPropertyDescriptor;var $=Object.getOwnPropertyNames;var X=Object.getPrototypeOf,j=Object.prototype.hasOwnProperty;var J=(e=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(e,{get:(t,r)=>(typeof require<"u"?require:t)[r]}):e)(function(e){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+e+'" is not supported')});var K=(e,t,r,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let l of $(t))!j.call(e,l)&&l!==r&&R(e,l,{get:()=>t[l],enumerable:!(o=G(t,l))||o.enumerable});return e};var W=(e,t,r)=>(r=e!=null?Q(X(e)):{},K(t||!e||!e.__esModule?R(r,"default",{value:e,enumerable:!0}):r,e));function S(e={}){let{root:t=document,initialCountry:r="us",separateDialCode:o=!0,countryCodeSelector:l='input[pulse-form-field="country-code"]',onInit:n,onError:i=m=>console.warn(`[initIntlTelInput] ${m}`)}=e,u=new Map,d=window.intlTelInput;return d?(t.querySelectorAll('input[type="tel"]').forEach(m=>{try{let a=d(m,{initialCountry:r,separateDialCode:o,strictMode:!1,loadUtils:()=>import("https://cdn.jsdelivr.net/npm/intl-tel-input@25/build/js/utils.js")});u.set(m,a),M(a,l),m.addEventListener("countrychange",()=>{M(a,l)}),n?.(m,a)}catch(a){i(`Failed to init on input inside "${z(m)}"`,a)}}),u):(i(`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>`),u)}function M(e,t){try{let r=e.getSelectedCountryData?.();if(!r?.dialCode)return;document.querySelectorAll(t).forEach(o=>{o.value=`+${r.dialCode}`})}catch{}}function z(e){return e.closest("[pulse-form-block]")?.getAttribute("pulse-field-name")??"unknown"}var Z=["text","email","phone","checkbox","radio","select","legal"],ee=["true","atleast-one","only-one"],s={REQUIRED_INPUT:"ERR_REQUIRED",REQUIRED_LEGAL:"ERR_LEGAL_REQUIRED",REQUIRED_SELECT:"ERR_SELECT_REQUIRED",ATLEAST_ONE:"ERR_ATLEAST_ONE",ONLY_ONE_NONE:"ERR_ONLY_ONE_NONE",ONLY_ONE_EXCEEDED:"ERR_ONLY_ONE_EXCEEDED",INVALID_EMAIL:"ERR_INVALID_EMAIL",INVALID_PHONE:"ERR_INVALID_PHONE",PHONE_TOO_SHORT:"ERR_PHONE_TOO_SHORT",PHONE_TOO_LONG:"ERR_PHONE_TOO_LONG",PHONE_INVALID_COUNTRY:"ERR_PHONE_INVALID_COUNTRY"},T={[s.REQUIRED_INPUT]:"This field is required.",[s.REQUIRED_LEGAL]:"You must accept this to continue.",[s.REQUIRED_SELECT]:"Please select an option.",[s.ATLEAST_ONE]:"Please select at least one option.",[s.ONLY_ONE_NONE]:"Please select one option.",[s.ONLY_ONE_EXCEEDED]:"Only one option can be selected.",[s.INVALID_EMAIL]:"Please enter a valid email address.",[s.INVALID_PHONE]:"Please enter a valid phone number.",[s.PHONE_TOO_SHORT]:"Phone number is too short.",[s.PHONE_TOO_LONG]:"Phone number is too long.",[s.PHONE_INVALID_COUNTRY]:"Invalid country code."};function te(e){let t=e.querySelector("input, textarea");return t?t.value.trim():null}function re(e){let t=e.querySelector('input[type="email"]');return t?t.value.trim():null}function ne(e){let t=e.querySelector('input[type="tel"]');return t?t.value.trim():null}function oe(e){let t=e.querySelectorAll('input[type="checkbox"]'),r=[];return t.forEach(o=>{if(o.checked){let l=o.getAttribute("data-name")?.trim();r.push(l||o.value||"on")}}),r}function le(e){let t=e.querySelectorAll('input[type="radio"]');for(let r of t)if(r.checked)return r.closest("label")?.textContent?.trim()||r.value||"on";return null}function ie(e){let t=e.querySelector("select");if(!t)return null;let r=t.value.trim();return!r||t.selectedIndex===0?null:r}function se(e){let t=e.querySelector('input[type="checkbox"]');return t?t.checked:!1}function I(e,t){switch(e){case"text":return te(t);case"email":return re(t);case"phone":return ne(t);case"checkbox":return oe(t);case"radio":return le(t);case"select":return ie(t);case"legal":return se(t);default:return null}}function ce(e){let t=e.getAttribute("required-selection")?.trim().toLowerCase();return!t||!ee.includes(t)?null:t}function ae(e){return e.getAttribute("mirror-value")?.trim().toLowerCase()==="true"}var ue={0:s.INVALID_PHONE,1:s.PHONE_INVALID_COUNTRY,2:s.PHONE_TOO_SHORT,3:s.PHONE_TOO_LONG,4:s.INVALID_PHONE};function de(e){return e?/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(e)?null:{code:s.INVALID_EMAIL,message:T[s.INVALID_EMAIL]}:null}function me(e,t){let r=e.value.trim();if(!r)return null;let o=t?.get(e);if(o)try{if(o.isValidNumber())return null;let n=o.getValidationError?.()??0,i=ue[n]||s.INVALID_PHONE;return{code:i,message:T[i]}}catch{return{code:s.INVALID_PHONE,message:T[s.INVALID_PHONE]}}let l=r.replace(/\D/g,"");return l.length<7?{code:s.PHONE_TOO_SHORT,message:T[s.PHONE_TOO_SHORT]}:l.length>15?{code:s.PHONE_TOO_LONG,message:T[s.PHONE_TOO_LONG]}:null}function O(e,t,r,o,l){if(t)switch(t){case"true":{if(e==="legal"&&r!==!0)return{code:s.REQUIRED_LEGAL,message:T[s.REQUIRED_LEGAL]};if(e==="select"&&!r)return{code:s.REQUIRED_SELECT,message:T[s.REQUIRED_SELECT]};if((e==="text"||e==="email"||e==="phone")&&(!r||typeof r=="string"&&r===""))return{code:s.REQUIRED_INPUT,message:T[s.REQUIRED_INPUT]};break}case"atleast-one":{if(Array.isArray(r)?r.length===0:!r)return{code:s.ATLEAST_ONE,message:T[s.ATLEAST_ONE]};break}case"only-one":{if(Array.isArray(r)){if(r.length===0)return{code:s.ONLY_ONE_NONE,message:T[s.ONLY_ONE_NONE]};if(r.length>1)return{code:s.ONLY_ONE_EXCEEDED,message:T[s.ONLY_ONE_EXCEEDED]}}else if(!r)return{code:s.ONLY_ONE_NONE,message:T[s.ONLY_ONE_NONE]};break}}if(e==="email"&&typeof r=="string"&&r){let n=de(r);if(n)return n}if(e==="phone"&&typeof r=="string"&&r){let n=o.querySelector('input[type="tel"]');if(n){let i=me(n,l);if(i)return i}}return null}function x(e={}){let{validate:t=!1,root:r=document,itiInstances:o}=e,l=r.querySelectorAll("[pulse-form-block]"),n=[];return l.forEach(i=>{let u=i.getAttribute("pulse-form-block")?.trim().toLowerCase();if(!u||!Z.includes(u))return;let d=u,f=i.getAttribute("pulse-field-name")?.trim();if(!f)return;let m=ce(i),a=ae(i),p=I(d,i),E=t?O(d,m,p,i,o):null;n.push({"form-block":d,"field-name":f,value:p,required:m,"mirror-value":a,error:E})}),n}var F=[],Ee=["text","email","phone","checkbox","radio","select","legal"],A=[];function _(e){return A.push(e),()=>{let t=A.indexOf(e);t!==-1&&A.splice(t,1)}}function P(){for(let e of A)try{e(F)}catch(t){console.error("[SampleForm] Error in onFieldsUpdate callback:",t)}}function v(e=document){return F=x({root:e}),window.PulseFormData=F,P(),console.log(`[SampleForm] Initialised ${F.length} fields.`),F}function k(e=document){let t=e.querySelectorAll("[pulse-form-block]");t.forEach(r=>{let o=r.getAttribute("pulse-form-block")?.trim().toLowerCase();if(!o||!Ee.includes(o))return;let l=()=>fe(r,e);switch(o){case"text":case"email":{let n=r.querySelector("input, textarea");n&&(n.addEventListener("input",l),n.addEventListener("change",l));break}case"phone":{let n=r.querySelector('input[type="tel"]');n&&(n.addEventListener("input",l),n.addEventListener("change",l),n.addEventListener("keyup",l),n.addEventListener("countrychange",l));break}case"checkbox":case"legal":{r.querySelectorAll('input[type="checkbox"]').forEach(n=>n.addEventListener("change",l));break}case"radio":{r.querySelectorAll('input[type="radio"]').forEach(n=>n.addEventListener("change",l));break}case"select":{let n=r.querySelector("select");n&&n.addEventListener("change",l);break}}}),console.log(`[SampleForm] Listeners bound to ${t.length} blocks.`)}function fe(e,t){let r=e.getAttribute("pulse-form-block")?.trim().toLowerCase(),o=e.getAttribute("pulse-field-name")?.trim();if(!o)return;let l=I(r,e),n=F.findIndex(i=>i["field-name"]===o);n!==-1&&(F[n]={...F[n],value:l,error:null},window.PulseFormData=F,P())}function y(){return F}var pe=["true","atleast-one","only-one"];function q(e,t={}){let{root:r=document,requiredAttribute:o="required-selection"}=t,l=[...e];return r.querySelectorAll("[pulse-form-block]").forEach(n=>{let i=n.getAttribute("pulse-field-name")?.trim();if(!i)return;let u=l.findIndex(m=>m["field-name"]===i);if(u===-1)return;let d=n.getAttribute(o)?.trim().toLowerCase()||"",f=pe.includes(d)?d:null;l[u]={...l[u],required:f}}),l}function C(e,t=document){t.querySelectorAll("[pulse-form-block]").forEach(r=>{let o=r.getAttribute("pulse-field-name")?.trim();if(!o)return;let l=e.find(n=>n["field-name"]===o);l&&(l.required?r.setAttribute("required-selection",l.required):r.removeAttribute("required-selection"))})}var Le="data-original-required-selection";function D(e,t={}){let{root:r=document,fieldName:o="flow-type",flowAttribute:l="form-flow",activeAttribute:n="form-flow-active",requiredAttribute:i="required-selection",originalRequiredAttribute:u=Le}=t,d=e.find(a=>a["field-name"]===o);if(!d)return e;let f=d.value;return r.querySelectorAll(`[${l}]`).forEach(a=>{let E=a.getAttribute(l)?.trim()===f;a.setAttribute(n,E?"true":"false");let c=[];a.hasAttribute("pulse-form-block")&&c.push(a),a.querySelectorAll("[pulse-form-block]").forEach(L=>{c.push(L)}),c.forEach(L=>{if(!L.hasAttribute(u)){let g=L.getAttribute(i)?.trim()||"";L.setAttribute(u,g)}if(E){let g=L.getAttribute(u)||"";L.setAttribute(i,g||"false")}else L.setAttribute(i,"false")})}),q(e,{root:r,requiredAttribute:i})}function V(e,t={}){let{root:r=document,onMissingInput:o,onMissingTarget:l}=t,n=e.filter(u=>u["mirror-value"]===!0);if(n.length===0)return;let i=r.querySelectorAll("[pulse-form-block-mirror]");n.forEach(u=>{let d=u["field-name"],f=!1;i.forEach(m=>{if(m.getAttribute("pulse-form-block-mirror")?.trim()!==d)return;f=!0;let p=m.querySelector("input, textarea, select");if(!p){o?.(d,m);return}Te(p,u.value)}),f||l?.(d)})}function Te(e,t){typeof t=="string"?e.value=t:typeof t=="boolean"?e instanceof HTMLInputElement&&e.type==="checkbox"?e.checked=t:e.value=String(t):Array.isArray(t)?e.value=t.join(", "):e.value=""}var N={errorClass:"pulse-form-error",wrapperErrorClass:"has-error",focusFirst:!0};function U(e,t){return t??e}function ge(e){let t=new Set;return e.querySelectorAll("[pulse-form-block]").forEach(r=>{let o=r.getAttribute("pulse-field-name")?.trim();o&&t.add(o)}),t}function h(e,t={}){let{root:r=document,scope:o,itiInstances:l,errorClass:n=N.errorClass,wrapperErrorClass:i=N.wrapperErrorClass,focusFirst:u=N.focusFirst}=t,d=U(r,o),f=d.querySelectorAll("[pulse-form-block]"),m=ge(d);ye(d,n,i);let a=e.map(c=>{if(!m.has(c["field-name"]))return c;let L=Ne(f,c["field-name"]);if(!L)return{...c,error:null};let g=O(c["form-block"],c.required,c.value,L,l);return g&&w(L,g,n,i),{...c,error:g}}),E=a.filter(c=>m.has(c["field-name"])).every(c=>c.error===null);return!E&&u&&Ie(d,i),{fields:a,isValid:E}}function H(e){let{root:t=document,scope:r,itiInstances:o,errorClass:l=N.errorClass,wrapperErrorClass:n=N.wrapperErrorClass,getFields:i,onFieldValidated:u}=e,d=["text","email","phone","checkbox","radio","select","legal"];U(t,r).querySelectorAll("[pulse-form-block]").forEach(a=>{let p=a.getAttribute("pulse-form-block")?.trim().toLowerCase();if(!p||!d.includes(p))return;let E=()=>{if(!a.classList.contains(n))return;let c=a.getAttribute("pulse-field-name")?.trim();if(!c)return;let g=i().find(Y=>Y["field-name"]===c);if(!g)return;let B=I(p,a),b=O(p,g.required,B,a,o);b?w(a,b,l,n):Fe(a,l,n),u?.(c,b)};switch(p){case"text":case"email":{let c=a.querySelector("input, textarea");c&&(c.addEventListener("input",E),c.addEventListener("change",E));break}case"phone":{let c=a.querySelector('input[type="tel"]');c&&(c.addEventListener("input",E),c.addEventListener("change",E),c.addEventListener("keyup",E),c.addEventListener("countrychange",E));break}case"checkbox":case"legal":{a.querySelectorAll('input[type="checkbox"]').forEach(c=>c.addEventListener("change",E));break}case"radio":{a.querySelectorAll('input[type="radio"]').forEach(c=>c.addEventListener("change",E));break}case"select":{let c=a.querySelector("select");c&&c.addEventListener("change",E);break}}})}function w(e,t,r,o){let l=e.querySelector(`.${r}`);l&&l.remove();let n=document.createElement("span");n.className=r,n.textContent=t.message,n.setAttribute("data-error-code",t.code),n.setAttribute("data-field-name",e.getAttribute("pulse-field-name")?.trim()||""),e.classList.add(o),e.appendChild(n)}function Fe(e,t,r){let o=e.querySelector(`.${t}`);o&&o.remove(),e.classList.remove(r)}function ye(e,t,r){e.querySelectorAll(`.${t}`).forEach(o=>o.remove()),e.querySelectorAll("[pulse-form-block]").forEach(o=>o.classList.remove(r))}function Ie(e,t){let r=e.querySelector(`[pulse-form-block].${t}`);if(!r)return;r.scrollIntoView({behavior:"smooth",block:"center"});let o=r.querySelector("input, textarea, select");o&&setTimeout(()=>o.focus(),400)}function Ne(e,t){return Array.from(e).find(r=>r.getAttribute("pulse-field-name")?.trim()===t)}document.addEventListener("DOMContentLoaded",()=>{let e=S();_(n=>{let i=D(n);window.PulseFormData=i}),_(n=>V(n)),v(),C(y()),k();let t=document.getElementById("step-2-container"),r=document.getElementById("step-2-button");H({scope:t,getFields:y,itiInstances:e}),r.addEventListener("click",n=>{n.preventDefault();let{fields:i,isValid:u}=h(y(),{scope:t,itiInstances:e});window.PulseFormData=i,u&&console.log("Step 2 valid, moving on...")});let o=document.getElementById("step-3-container"),l=document.getElementById("step-3-button");H({scope:o,getFields:y,itiInstances:e}),l.addEventListener("click",n=>{n.preventDefault(),console.log("step 3 clicked");let{fields:i,isValid:u}=h(y(),{scope:o,itiInstances:e});window.PulseFormData=i,console.log("Step 3 valid",u),u&&console.log("Step 3 valid, proceeding to submit...")})});})();
1
+ "use strict";
2
+ (() => {
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
10
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
11
+ }) : x)(function(x) {
12
+ if (typeof require !== "undefined") return require.apply(this, arguments);
13
+ throw Error('Dynamic require of "' + x + '" is not supported');
14
+ });
15
+ var __copyProps = (to, from, except, desc) => {
16
+ if (from && typeof from === "object" || typeof from === "function") {
17
+ for (let key of __getOwnPropNames(from))
18
+ if (!__hasOwnProp.call(to, key) && key !== except)
19
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
20
+ }
21
+ return to;
22
+ };
23
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
24
+ // If the importer is in node compatibility mode or this is not an ESM
25
+ // file that has been converted to a CommonJS file using a Babel-
26
+ // compatible transform (i.e. "__esModule" has not been set), then set
27
+ // "default" to the CommonJS "module.exports" for node compatibility.
28
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
29
+ mod
30
+ ));
31
+
32
+ // src/form/utils/initIntlTelInput.ts
33
+ function initIntlTelInput(options = {}) {
34
+ const {
35
+ root = document,
36
+ initialCountry = "us",
37
+ separateDialCode = true,
38
+ countryCodeSelector = 'input[pulse-form-field="country-code"]',
39
+ onInit,
40
+ onError = (msg) => console.warn(`[initIntlTelInput] ${msg}`)
41
+ } = options;
42
+ const instances = /* @__PURE__ */ new Map();
43
+ const intlTelInput = window.intlTelInput;
44
+ if (!intlTelInput) {
45
+ onError(
46
+ 'intlTelInput not found on window. Include the script before calling this function.\ne.g. <script src="https://cdn.jsdelivr.net/npm/intl-tel-input@25/build/js/intlTelInput.min.js"><\/script>'
47
+ );
48
+ return instances;
49
+ }
50
+ const phoneInputs = root.querySelectorAll(
51
+ 'input[type="tel"]'
52
+ );
53
+ phoneInputs.forEach((input) => {
54
+ try {
55
+ const iti = intlTelInput(input, {
56
+ initialCountry,
57
+ separateDialCode,
58
+ strictMode: false,
59
+ // @ts-ignore — runtime CDN import
60
+ loadUtils: () => import(
61
+ // @ts-ignore — runtime CDN import, not a TS module
62
+ "https://cdn.jsdelivr.net/npm/intl-tel-input@25/build/js/utils.js"
63
+ )
64
+ });
65
+ instances.set(input, iti);
66
+ fillCountryCode(iti, countryCodeSelector);
67
+ input.addEventListener("countrychange", () => {
68
+ fillCountryCode(iti, countryCodeSelector);
69
+ });
70
+ onInit?.(input, iti);
71
+ } catch (err) {
72
+ onError(`Failed to init on input inside "${fieldNameOf(input)}"`, err);
73
+ }
74
+ });
75
+ return instances;
76
+ }
77
+ function fillCountryCode(iti, selector) {
78
+ try {
79
+ const countryData = iti.getSelectedCountryData?.();
80
+ if (!countryData?.dialCode) return;
81
+ document.querySelectorAll(selector).forEach((input) => {
82
+ input.value = `+${countryData.dialCode}`;
83
+ });
84
+ } catch {
85
+ }
86
+ }
87
+ function fieldNameOf(input) {
88
+ return input.closest("[pulse-form-block]")?.getAttribute("pulse-field-name") ?? "unknown";
89
+ }
90
+
91
+ // src/form/utils/collectFormFields.ts
92
+ var VALID_BLOCK_TYPES = [
93
+ "text",
94
+ "email",
95
+ "phone",
96
+ "checkbox",
97
+ "radio",
98
+ "select",
99
+ "legal"
100
+ ];
101
+ var VALID_REQUIRED_VALUES = [
102
+ "true",
103
+ "atleast-one",
104
+ "only-one"
105
+ ];
106
+ var ERROR_CODES = {
107
+ REQUIRED_INPUT: "ERR_REQUIRED",
108
+ REQUIRED_LEGAL: "ERR_LEGAL_REQUIRED",
109
+ REQUIRED_SELECT: "ERR_SELECT_REQUIRED",
110
+ ATLEAST_ONE: "ERR_ATLEAST_ONE",
111
+ ONLY_ONE_NONE: "ERR_ONLY_ONE_NONE",
112
+ ONLY_ONE_EXCEEDED: "ERR_ONLY_ONE_EXCEEDED",
113
+ INVALID_EMAIL: "ERR_INVALID_EMAIL",
114
+ INVALID_PHONE: "ERR_INVALID_PHONE",
115
+ PHONE_TOO_SHORT: "ERR_PHONE_TOO_SHORT",
116
+ PHONE_TOO_LONG: "ERR_PHONE_TOO_LONG",
117
+ PHONE_INVALID_COUNTRY: "ERR_PHONE_INVALID_COUNTRY"
118
+ };
119
+ var ERROR_MESSAGES = {
120
+ [ERROR_CODES.REQUIRED_INPUT]: "This field is required.",
121
+ [ERROR_CODES.REQUIRED_LEGAL]: "You must accept this to continue.",
122
+ [ERROR_CODES.REQUIRED_SELECT]: "Please select an option.",
123
+ [ERROR_CODES.ATLEAST_ONE]: "Please select at least one option.",
124
+ [ERROR_CODES.ONLY_ONE_NONE]: "Please select one option.",
125
+ [ERROR_CODES.ONLY_ONE_EXCEEDED]: "Only one option can be selected.",
126
+ [ERROR_CODES.INVALID_EMAIL]: "Please enter a valid email address.",
127
+ [ERROR_CODES.INVALID_PHONE]: "Please enter a valid phone number.",
128
+ [ERROR_CODES.PHONE_TOO_SHORT]: "Phone number is too short.",
129
+ [ERROR_CODES.PHONE_TOO_LONG]: "Phone number is too long.",
130
+ [ERROR_CODES.PHONE_INVALID_COUNTRY]: "Invalid country code."
131
+ };
132
+ function extractTextValue(wrapper) {
133
+ const input = wrapper.querySelector(
134
+ "input, textarea"
135
+ );
136
+ return input ? input.value.trim() : null;
137
+ }
138
+ function extractEmailValue(wrapper) {
139
+ const input = wrapper.querySelector('input[type="email"]');
140
+ return input ? input.value.trim() : null;
141
+ }
142
+ function extractPhoneValue(wrapper) {
143
+ const input = wrapper.querySelector('input[type="tel"]');
144
+ return input ? input.value.trim() : null;
145
+ }
146
+ function extractCheckboxValues(wrapper) {
147
+ const checkboxes = wrapper.querySelectorAll(
148
+ 'input[type="checkbox"]'
149
+ );
150
+ const values = [];
151
+ checkboxes.forEach((cb) => {
152
+ if (cb.checked) {
153
+ const name = cb.getAttribute("data-name")?.trim();
154
+ values.push(name || cb.value || "on");
155
+ }
156
+ });
157
+ return values;
158
+ }
159
+ function extractRadioValue(wrapper) {
160
+ const radios = wrapper.querySelectorAll(
161
+ 'input[type="radio"]'
162
+ );
163
+ for (const radio of radios) {
164
+ if (radio.checked) {
165
+ const label = radio.closest("label")?.textContent?.trim();
166
+ return label || radio.value || "on";
167
+ }
168
+ }
169
+ return null;
170
+ }
171
+ function extractSelectValue(wrapper) {
172
+ const select = wrapper.querySelector("select");
173
+ if (!select) return null;
174
+ const val = select.value.trim();
175
+ if (!val || select.selectedIndex === 0) return null;
176
+ return val;
177
+ }
178
+ function extractLegalValue(wrapper) {
179
+ const checkbox = wrapper.querySelector(
180
+ 'input[type="checkbox"]'
181
+ );
182
+ return checkbox ? checkbox.checked : false;
183
+ }
184
+ function extractValue(type, wrapper) {
185
+ switch (type) {
186
+ case "text":
187
+ return extractTextValue(wrapper);
188
+ case "email":
189
+ return extractEmailValue(wrapper);
190
+ case "phone":
191
+ return extractPhoneValue(wrapper);
192
+ case "checkbox":
193
+ return extractCheckboxValues(wrapper);
194
+ case "radio":
195
+ return extractRadioValue(wrapper);
196
+ case "select":
197
+ return extractSelectValue(wrapper);
198
+ case "legal":
199
+ return extractLegalValue(wrapper);
200
+ default:
201
+ return null;
202
+ }
203
+ }
204
+ function parseRequired(wrapper) {
205
+ const raw = wrapper.getAttribute("required-selection")?.trim().toLowerCase();
206
+ if (!raw || !VALID_REQUIRED_VALUES.includes(raw))
207
+ return null;
208
+ return raw;
209
+ }
210
+ function parseMirrorValue(wrapper) {
211
+ return wrapper.getAttribute("mirror-value")?.trim().toLowerCase() === "true";
212
+ }
213
+ var PHONE_ITI_ERROR_MAP = {
214
+ 0: ERROR_CODES.INVALID_PHONE,
215
+ 1: ERROR_CODES.PHONE_INVALID_COUNTRY,
216
+ 2: ERROR_CODES.PHONE_TOO_SHORT,
217
+ 3: ERROR_CODES.PHONE_TOO_LONG,
218
+ 4: ERROR_CODES.INVALID_PHONE
219
+ };
220
+ function validateEmail(value) {
221
+ if (!value) return null;
222
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
223
+ if (!emailRegex.test(value)) {
224
+ return {
225
+ code: ERROR_CODES.INVALID_EMAIL,
226
+ message: ERROR_MESSAGES[ERROR_CODES.INVALID_EMAIL]
227
+ };
228
+ }
229
+ return null;
230
+ }
231
+ function validatePhone(input, itiInstances) {
232
+ const value = input.value.trim();
233
+ if (!value) return null;
234
+ const iti = itiInstances?.get(input);
235
+ if (iti) {
236
+ try {
237
+ if (iti.isValidNumber()) return null;
238
+ const errorCode = iti.getValidationError?.() ?? 0;
239
+ const code = PHONE_ITI_ERROR_MAP[errorCode] || ERROR_CODES.INVALID_PHONE;
240
+ return { code, message: ERROR_MESSAGES[code] };
241
+ } catch {
242
+ return {
243
+ code: ERROR_CODES.INVALID_PHONE,
244
+ message: ERROR_MESSAGES[ERROR_CODES.INVALID_PHONE]
245
+ };
246
+ }
247
+ }
248
+ const digits = value.replace(/\D/g, "");
249
+ if (digits.length < 7)
250
+ return {
251
+ code: ERROR_CODES.PHONE_TOO_SHORT,
252
+ message: ERROR_MESSAGES[ERROR_CODES.PHONE_TOO_SHORT]
253
+ };
254
+ if (digits.length > 15)
255
+ return {
256
+ code: ERROR_CODES.PHONE_TOO_LONG,
257
+ message: ERROR_MESSAGES[ERROR_CODES.PHONE_TOO_LONG]
258
+ };
259
+ return null;
260
+ }
261
+ function getFieldError(type, required, value, wrapper, itiInstances) {
262
+ if (required) {
263
+ switch (required) {
264
+ case "true": {
265
+ if (type === "legal" && value !== true)
266
+ return {
267
+ code: ERROR_CODES.REQUIRED_LEGAL,
268
+ message: ERROR_MESSAGES[ERROR_CODES.REQUIRED_LEGAL]
269
+ };
270
+ if (type === "select" && !value)
271
+ return {
272
+ code: ERROR_CODES.REQUIRED_SELECT,
273
+ message: ERROR_MESSAGES[ERROR_CODES.REQUIRED_SELECT]
274
+ };
275
+ if ((type === "text" || type === "email" || type === "phone") && (!value || typeof value === "string" && value === ""))
276
+ return {
277
+ code: ERROR_CODES.REQUIRED_INPUT,
278
+ message: ERROR_MESSAGES[ERROR_CODES.REQUIRED_INPUT]
279
+ };
280
+ break;
281
+ }
282
+ case "atleast-one": {
283
+ const empty = Array.isArray(value) ? value.length === 0 : !value;
284
+ if (empty)
285
+ return {
286
+ code: ERROR_CODES.ATLEAST_ONE,
287
+ message: ERROR_MESSAGES[ERROR_CODES.ATLEAST_ONE]
288
+ };
289
+ break;
290
+ }
291
+ case "only-one": {
292
+ if (Array.isArray(value)) {
293
+ if (value.length === 0)
294
+ return {
295
+ code: ERROR_CODES.ONLY_ONE_NONE,
296
+ message: ERROR_MESSAGES[ERROR_CODES.ONLY_ONE_NONE]
297
+ };
298
+ if (value.length > 1)
299
+ return {
300
+ code: ERROR_CODES.ONLY_ONE_EXCEEDED,
301
+ message: ERROR_MESSAGES[ERROR_CODES.ONLY_ONE_EXCEEDED]
302
+ };
303
+ } else if (!value) {
304
+ return {
305
+ code: ERROR_CODES.ONLY_ONE_NONE,
306
+ message: ERROR_MESSAGES[ERROR_CODES.ONLY_ONE_NONE]
307
+ };
308
+ }
309
+ break;
310
+ }
311
+ }
312
+ }
313
+ if (type === "email" && typeof value === "string" && value) {
314
+ const emailError = validateEmail(value);
315
+ if (emailError) return emailError;
316
+ }
317
+ if (type === "phone" && typeof value === "string" && value) {
318
+ const phoneInput = wrapper.querySelector(
319
+ 'input[type="tel"]'
320
+ );
321
+ if (phoneInput) {
322
+ const phoneError = validatePhone(phoneInput, itiInstances);
323
+ if (phoneError) return phoneError;
324
+ }
325
+ }
326
+ return null;
327
+ }
328
+ function collectFormFields(options = {}) {
329
+ const { validate = false, root = document, itiInstances } = options;
330
+ const wrappers = root.querySelectorAll("[pulse-form-block]");
331
+ const fields = [];
332
+ wrappers.forEach((wrapper) => {
333
+ const rawType = wrapper.getAttribute("pulse-form-block")?.trim().toLowerCase();
334
+ if (!rawType || !VALID_BLOCK_TYPES.includes(rawType))
335
+ return;
336
+ const blockType = rawType;
337
+ const fieldName = wrapper.getAttribute("pulse-field-name")?.trim();
338
+ if (!fieldName) return;
339
+ const required = parseRequired(wrapper);
340
+ const mirrorValue = parseMirrorValue(wrapper);
341
+ const value = extractValue(blockType, wrapper);
342
+ const error = validate ? getFieldError(blockType, required, value, wrapper, itiInstances) : null;
343
+ fields.push({
344
+ "form-block": blockType,
345
+ "field-name": fieldName,
346
+ value,
347
+ required,
348
+ "mirror-value": mirrorValue,
349
+ error
350
+ });
351
+ });
352
+ return fields;
353
+ }
354
+
355
+ // src/form/utils/initFormControls.ts
356
+ var _fields = [];
357
+ var VALID_BLOCK_TYPES2 = [
358
+ "text",
359
+ "email",
360
+ "phone",
361
+ "checkbox",
362
+ "radio",
363
+ "select",
364
+ "legal"
365
+ ];
366
+ var _updateCallbacks = [];
367
+ function onFieldsUpdate(cb) {
368
+ _updateCallbacks.push(cb);
369
+ return () => {
370
+ const idx = _updateCallbacks.indexOf(cb);
371
+ if (idx !== -1) _updateCallbacks.splice(idx, 1);
372
+ };
373
+ }
374
+ function notifyUpdate() {
375
+ for (const cb of _updateCallbacks) {
376
+ try {
377
+ cb(_fields);
378
+ } catch (err) {
379
+ console.error("[SampleForm] Error in onFieldsUpdate callback:", err);
380
+ }
381
+ }
382
+ }
383
+ function initFormJSON(root = document) {
384
+ _fields = collectFormFields({ root });
385
+ window.PulseFormData = _fields;
386
+ notifyUpdate();
387
+ console.log(`[SampleForm] Initialised ${_fields.length} fields.`);
388
+ return _fields;
389
+ }
390
+ function bindFormListeners(root = document) {
391
+ const wrappers = root.querySelectorAll("[pulse-form-block]");
392
+ wrappers.forEach((wrapper) => {
393
+ const type = wrapper.getAttribute("pulse-form-block")?.trim().toLowerCase();
394
+ if (!type || !VALID_BLOCK_TYPES2.includes(type)) return;
395
+ const onChange = () => handleChange(wrapper, root);
396
+ switch (type) {
397
+ case "text":
398
+ case "email": {
399
+ const input = wrapper.querySelector(
400
+ "input, textarea"
401
+ );
402
+ if (input) {
403
+ input.addEventListener("input", onChange);
404
+ input.addEventListener("change", onChange);
405
+ }
406
+ break;
407
+ }
408
+ case "phone": {
409
+ const phoneInput = wrapper.querySelector('input[type="tel"]');
410
+ if (phoneInput) {
411
+ phoneInput.addEventListener("input", onChange);
412
+ phoneInput.addEventListener("change", onChange);
413
+ phoneInput.addEventListener("keyup", onChange);
414
+ phoneInput.addEventListener("countrychange", onChange);
415
+ }
416
+ break;
417
+ }
418
+ case "checkbox":
419
+ case "legal": {
420
+ wrapper.querySelectorAll('input[type="checkbox"]').forEach((cb) => cb.addEventListener("change", onChange));
421
+ break;
422
+ }
423
+ case "radio": {
424
+ wrapper.querySelectorAll('input[type="radio"]').forEach((r) => r.addEventListener("change", onChange));
425
+ break;
426
+ }
427
+ case "select": {
428
+ const select = wrapper.querySelector("select");
429
+ if (select) select.addEventListener("change", onChange);
430
+ break;
431
+ }
432
+ }
433
+ });
434
+ console.log(`[SampleForm] Listeners bound to ${wrappers.length} blocks.`);
435
+ }
436
+ function handleChange(wrapper, root) {
437
+ const rawType = wrapper.getAttribute("pulse-form-block")?.trim().toLowerCase();
438
+ const fieldName = wrapper.getAttribute("pulse-field-name")?.trim();
439
+ if (!fieldName) return;
440
+ const value = extractValue(rawType, wrapper);
441
+ const idx = _fields.findIndex((f) => f["field-name"] === fieldName);
442
+ if (idx === -1) return;
443
+ _fields[idx] = { ..._fields[idx], value, error: null };
444
+ window.PulseFormData = _fields;
445
+ notifyUpdate();
446
+ }
447
+ function getFormFields() {
448
+ return _fields;
449
+ }
450
+
451
+ // src/form/utils/updateRequiredFields.ts
452
+ var VALID_REQUIRED = ["true", "atleast-one", "only-one"];
453
+ function updateRequiredFields(fields, options = {}) {
454
+ const {
455
+ root = document,
456
+ requiredAttribute = "required-selection"
457
+ } = options;
458
+ const updated = [...fields];
459
+ root.querySelectorAll("[pulse-form-block]").forEach((block) => {
460
+ const fieldName = block.getAttribute("pulse-field-name")?.trim();
461
+ if (!fieldName) return;
462
+ const idx = updated.findIndex((f) => f["field-name"] === fieldName);
463
+ if (idx === -1) return;
464
+ const raw = block.getAttribute(requiredAttribute)?.trim().toLowerCase() || "";
465
+ const parsed = VALID_REQUIRED.includes(raw) ? raw : null;
466
+ updated[idx] = { ...updated[idx], required: parsed };
467
+ });
468
+ return updated;
469
+ }
470
+ function syncRequiredToDOM(fields, root = document) {
471
+ root.querySelectorAll("[pulse-form-block]").forEach((block) => {
472
+ const name = block.getAttribute("pulse-field-name")?.trim();
473
+ if (!name) return;
474
+ const field = fields.find((f) => f["field-name"] === name);
475
+ if (!field) return;
476
+ if (field.required) {
477
+ block.setAttribute("required-selection", field.required);
478
+ } else {
479
+ block.removeAttribute("required-selection");
480
+ }
481
+ });
482
+ }
483
+
484
+ // src/form/utils/updateFlowType.ts
485
+ var ORIGINAL_ATTR_DEFAULT = "data-original-required-selection";
486
+ function updateFlowType(fields, options = {}) {
487
+ const {
488
+ root = document,
489
+ fieldName = "flow-type",
490
+ flowAttribute = "form-flow",
491
+ activeAttribute = "form-flow-active",
492
+ requiredAttribute = "required-selection",
493
+ originalRequiredAttribute = ORIGINAL_ATTR_DEFAULT
494
+ } = options;
495
+ const flowField = fields.find((f) => f["field-name"] === fieldName);
496
+ if (!flowField) return fields;
497
+ const flowValue = flowField.value;
498
+ root.querySelectorAll(`[${flowAttribute}]`).forEach((el) => {
499
+ const elValue = el.getAttribute(flowAttribute)?.trim();
500
+ const isActive = elValue === flowValue;
501
+ el.setAttribute(activeAttribute, isActive ? "true" : "false");
502
+ const blocks = [];
503
+ if (el.hasAttribute("pulse-form-block")) {
504
+ blocks.push(el);
505
+ }
506
+ el.querySelectorAll("[pulse-form-block]").forEach((child) => {
507
+ blocks.push(child);
508
+ });
509
+ blocks.forEach((block) => {
510
+ if (!block.hasAttribute(originalRequiredAttribute)) {
511
+ const current = block.getAttribute(requiredAttribute)?.trim() || "";
512
+ block.setAttribute(originalRequiredAttribute, current);
513
+ }
514
+ if (isActive) {
515
+ const original = block.getAttribute(originalRequiredAttribute) || "";
516
+ block.setAttribute(requiredAttribute, original || "false");
517
+ } else {
518
+ block.setAttribute(requiredAttribute, "false");
519
+ }
520
+ });
521
+ });
522
+ const updated = updateRequiredFields(fields, { root, requiredAttribute });
523
+ return updated;
524
+ }
525
+
526
+ // src/form/utils/fillMirrorValues.ts
527
+ function fillMirrorValues(fields, options = {}) {
528
+ const { root = document, onMissingInput, onMissingTarget } = options;
529
+ const mirrorFields = fields.filter((f) => f["mirror-value"] === true);
530
+ if (mirrorFields.length === 0) return;
531
+ const mirrorTargets = root.querySelectorAll(
532
+ "[pulse-form-block-mirror]"
533
+ );
534
+ mirrorFields.forEach((field) => {
535
+ const fieldName = field["field-name"];
536
+ let found = false;
537
+ mirrorTargets.forEach((target) => {
538
+ const mirrorAttr = target.getAttribute("pulse-form-block-mirror")?.trim();
539
+ if (mirrorAttr !== fieldName) return;
540
+ found = true;
541
+ const input = target.querySelector("input, textarea, select");
542
+ if (!input) {
543
+ onMissingInput?.(fieldName, target);
544
+ return;
545
+ }
546
+ writeValueToInput(input, field.value);
547
+ });
548
+ if (!found) {
549
+ onMissingTarget?.(fieldName);
550
+ }
551
+ });
552
+ }
553
+ function writeValueToInput(input, value) {
554
+ if (typeof value === "string") {
555
+ input.value = value;
556
+ } else if (typeof value === "boolean") {
557
+ if (input instanceof HTMLInputElement && input.type === "checkbox") {
558
+ input.checked = value;
559
+ } else {
560
+ input.value = String(value);
561
+ }
562
+ } else if (Array.isArray(value)) {
563
+ input.value = value.join(", ");
564
+ } else {
565
+ input.value = "";
566
+ }
567
+ }
568
+
569
+ // src/form/utils/validateForm.ts
570
+ var DEFAULTS = {
571
+ errorClass: "pulse-form-error",
572
+ wrapperErrorClass: "has-error",
573
+ focusFirst: true
574
+ };
575
+ function resolveTarget(root, scope) {
576
+ return scope ?? root;
577
+ }
578
+ function getScopedFieldNames(target) {
579
+ const names = /* @__PURE__ */ new Set();
580
+ target.querySelectorAll("[pulse-form-block]").forEach((w) => {
581
+ const name = w.getAttribute("pulse-field-name")?.trim();
582
+ if (name) names.add(name);
583
+ });
584
+ return names;
585
+ }
586
+ function validateForm(fields, options = {}) {
587
+ const {
588
+ root = document,
589
+ scope,
590
+ itiInstances,
591
+ errorClass = DEFAULTS.errorClass,
592
+ wrapperErrorClass = DEFAULTS.wrapperErrorClass,
593
+ focusFirst = DEFAULTS.focusFirst
594
+ } = options;
595
+ const target = resolveTarget(root, scope);
596
+ const wrappers = target.querySelectorAll("[pulse-form-block]");
597
+ const scopedNames = getScopedFieldNames(target);
598
+ clearAllErrors(target, errorClass, wrapperErrorClass);
599
+ const validated = fields.map((field) => {
600
+ if (!scopedNames.has(field["field-name"])) return field;
601
+ const wrapper = findWrapper(wrappers, field["field-name"]);
602
+ if (!wrapper) return { ...field, error: null };
603
+ const error = getFieldError(
604
+ field["form-block"],
605
+ field.required,
606
+ field.value,
607
+ wrapper,
608
+ itiInstances
609
+ );
610
+ if (error) {
611
+ showError(wrapper, error, errorClass, wrapperErrorClass);
612
+ }
613
+ return { ...field, error };
614
+ });
615
+ const scopedFields = validated.filter((f) => scopedNames.has(f["field-name"]));
616
+ const isValid = scopedFields.every((f) => f.error === null);
617
+ if (!isValid && focusFirst) {
618
+ focusFirstError(target, wrapperErrorClass);
619
+ }
620
+ return { fields: validated, isValid };
621
+ }
622
+ function bindValidationListeners(options) {
623
+ const {
624
+ root = document,
625
+ scope,
626
+ itiInstances,
627
+ errorClass = DEFAULTS.errorClass,
628
+ wrapperErrorClass = DEFAULTS.wrapperErrorClass,
629
+ getFields,
630
+ onFieldValidated
631
+ } = options;
632
+ const VALID_TYPES = [
633
+ "text",
634
+ "email",
635
+ "phone",
636
+ "checkbox",
637
+ "radio",
638
+ "select",
639
+ "legal"
640
+ ];
641
+ const target = resolveTarget(root, scope);
642
+ const wrappers = target.querySelectorAll("[pulse-form-block]");
643
+ wrappers.forEach((wrapper) => {
644
+ const type = wrapper.getAttribute("pulse-form-block")?.trim().toLowerCase();
645
+ if (!type || !VALID_TYPES.includes(type)) return;
646
+ const onChange = () => {
647
+ if (!wrapper.classList.contains(wrapperErrorClass)) return;
648
+ const fieldName = wrapper.getAttribute("pulse-field-name")?.trim();
649
+ if (!fieldName) return;
650
+ const fields = getFields();
651
+ const field = fields.find((f) => f["field-name"] === fieldName);
652
+ if (!field) return;
653
+ const value = extractValue(type, wrapper);
654
+ const error = getFieldError(type, field.required, value, wrapper, itiInstances);
655
+ if (!error) {
656
+ clearError(wrapper, errorClass, wrapperErrorClass);
657
+ } else {
658
+ showError(wrapper, error, errorClass, wrapperErrorClass);
659
+ }
660
+ onFieldValidated?.(fieldName, error);
661
+ };
662
+ switch (type) {
663
+ case "text":
664
+ case "email": {
665
+ const input = wrapper.querySelector(
666
+ "input, textarea"
667
+ );
668
+ if (input) {
669
+ input.addEventListener("input", onChange);
670
+ input.addEventListener("change", onChange);
671
+ }
672
+ break;
673
+ }
674
+ case "phone": {
675
+ const phoneInput = wrapper.querySelector('input[type="tel"]');
676
+ if (phoneInput) {
677
+ phoneInput.addEventListener("input", onChange);
678
+ phoneInput.addEventListener("change", onChange);
679
+ phoneInput.addEventListener("keyup", onChange);
680
+ phoneInput.addEventListener("countrychange", onChange);
681
+ }
682
+ break;
683
+ }
684
+ case "checkbox":
685
+ case "legal": {
686
+ wrapper.querySelectorAll('input[type="checkbox"]').forEach((cb) => cb.addEventListener("change", onChange));
687
+ break;
688
+ }
689
+ case "radio": {
690
+ wrapper.querySelectorAll('input[type="radio"]').forEach((r) => r.addEventListener("change", onChange));
691
+ break;
692
+ }
693
+ case "select": {
694
+ const select = wrapper.querySelector("select");
695
+ if (select) select.addEventListener("change", onChange);
696
+ break;
697
+ }
698
+ }
699
+ });
700
+ }
701
+ function showError(wrapper, error, errorClass, wrapperErrorClass) {
702
+ const existing = wrapper.querySelector(`.${errorClass}`);
703
+ if (existing) existing.remove();
704
+ const span = document.createElement("span");
705
+ span.className = errorClass;
706
+ span.textContent = error.message;
707
+ span.setAttribute("data-error-code", error.code);
708
+ span.setAttribute(
709
+ "data-field-name",
710
+ wrapper.getAttribute("pulse-field-name")?.trim() || ""
711
+ );
712
+ wrapper.classList.add(wrapperErrorClass);
713
+ wrapper.appendChild(span);
714
+ }
715
+ function clearError(wrapper, errorClass, wrapperErrorClass) {
716
+ const span = wrapper.querySelector(`.${errorClass}`);
717
+ if (span) span.remove();
718
+ wrapper.classList.remove(wrapperErrorClass);
719
+ }
720
+ function clearAllErrors(target, errorClass, wrapperErrorClass) {
721
+ target.querySelectorAll(`.${errorClass}`).forEach((el) => el.remove());
722
+ target.querySelectorAll("[pulse-form-block]").forEach((el) => el.classList.remove(wrapperErrorClass));
723
+ }
724
+ function focusFirstError(target, wrapperErrorClass) {
725
+ const first = target.querySelector(
726
+ `[pulse-form-block].${wrapperErrorClass}`
727
+ );
728
+ if (!first) return;
729
+ first.scrollIntoView({ behavior: "smooth", block: "center" });
730
+ const focusable = first.querySelector(
731
+ "input, textarea, select"
732
+ );
733
+ if (focusable) setTimeout(() => focusable.focus(), 400);
734
+ }
735
+ function findWrapper(wrappers, fieldName) {
736
+ return Array.from(wrappers).find(
737
+ (w) => w.getAttribute("pulse-field-name")?.trim() === fieldName
738
+ );
739
+ }
740
+
741
+ // src/form/pricing.ts
742
+ document.addEventListener("DOMContentLoaded", () => {
743
+ const itiInstances = initIntlTelInput();
744
+ onFieldsUpdate((fields) => {
745
+ const updated = updateFlowType(fields);
746
+ window.PulseFormData = updated;
747
+ });
748
+ onFieldsUpdate((fields) => fillMirrorValues(fields));
749
+ initFormJSON();
750
+ syncRequiredToDOM(getFormFields());
751
+ bindFormListeners();
752
+ const step2Container = document.getElementById("step-2-container");
753
+ const step2Button = document.getElementById("step-2-button");
754
+ bindValidationListeners({
755
+ scope: step2Container,
756
+ getFields: getFormFields,
757
+ itiInstances
758
+ });
759
+ step2Button.addEventListener("click", (e) => {
760
+ e.preventDefault();
761
+ const { fields, isValid } = validateForm(getFormFields(), {
762
+ scope: step2Container,
763
+ itiInstances
764
+ });
765
+ window.PulseFormData = fields;
766
+ if (!isValid) return;
767
+ console.log("Step 2 valid, moving on...");
768
+ });
769
+ const step3Container = document.getElementById("step-3-container");
770
+ const step3Button = document.getElementById("step-3-button");
771
+ bindValidationListeners({
772
+ scope: step3Container,
773
+ getFields: getFormFields,
774
+ itiInstances
775
+ });
776
+ step3Button.addEventListener("click", (e) => {
777
+ e.preventDefault();
778
+ console.log("step 3 clicked");
779
+ const { fields, isValid } = validateForm(getFormFields(), {
780
+ scope: step3Container,
781
+ itiInstances
782
+ });
783
+ window.PulseFormData = fields;
784
+ console.log("Step 3 valid", isValid);
785
+ if (!isValid) return;
786
+ console.log("Step 3 valid, proceeding to submit...");
787
+ });
788
+ });
789
+ })();
790
+ //# sourceMappingURL=pricing.js.map