@reform-society/agera-survey 0.1.0 → 0.1.1
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 +17 -12
- package/dist/index.global.js +3239 -4
- package/dist/index.global.js.map +1 -0
- package/package.json +5 -5
package/dist/index.global.js
CHANGED
|
@@ -1,6 +1,3142 @@
|
|
|
1
|
-
"use strict";var AgeraSurvey=(()=>{var Ut=Object.create;var K=Object.defineProperty;var Bt=Object.getOwnPropertyDescriptor;var _t=Object.getOwnPropertyNames;var Wt=Object.getPrototypeOf,Qt=Object.prototype.hasOwnProperty;var Gt=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),Yt=(e,t)=>{for(var r in t)K(e,r,{get:t[r],enumerable:!0})},Ne=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of _t(t))!Qt.call(e,i)&&i!==r&&K(e,i,{get:()=>t[i],enumerable:!(n=Bt(t,i))||n.enumerable});return e};var x=(e,t,r)=>(r=e!=null?Ut(Wt(e)):{},Ne(t||!e||!e.__esModule?K(r,"default",{value:e,enumerable:!0}):r,e)),Jt=e=>Ne(K({},"__esModule",{value:!0}),e);var L=Gt((qe,X)=>{"use strict";(function(e,t){"use strict";typeof define=="function"&&define.amd?define(t):typeof X=="object"&&X.exports?X.exports=t():e.log=t()})(qe,function(){"use strict";var e=function(){},t="undefined",r=typeof window!==t&&typeof window.navigator!==t&&/Trident\/|MSIE /.test(window.navigator.userAgent),n=["trace","debug","info","warn","error"],i={},o=null;function s(p,v){var d=p[v];if(typeof d.bind=="function")return d.bind(p);try{return Function.prototype.bind.call(d,p)}catch{return function(){return Function.prototype.apply.apply(d,[p,arguments])}}}function a(){console.log&&(console.log.apply?console.log.apply(console,arguments):Function.prototype.apply.apply(console.log,[console,arguments])),console.trace&&console.trace()}function u(p){return p==="debug"&&(p="log"),typeof console===t?!1:p==="trace"&&r?a:console[p]!==void 0?s(console,p):console.log!==void 0?s(console,"log"):e}function l(){for(var p=this.getLevel(),v=0;v<n.length;v++){var d=n[v];this[d]=v<p?e:this.methodFactory(d,p,this.name)}if(this.log=this.debug,typeof console===t&&p<this.levels.SILENT)return"No console available for logging"}function f(p){return function(){typeof console!==t&&(l.call(this),this[p].apply(this,arguments))}}function m(p,v,d){return u(p)||f.apply(this,arguments)}function c(p,v){var d=this,$,fe,V,P="loglevel";typeof p=="string"?P+=":"+p:typeof p=="symbol"&&(P=void 0);function zt(b){var A=(n[b]||"silent").toUpperCase();if(!(typeof window===t||!P)){try{window.localStorage[P]=A;return}catch{}try{window.document.cookie=encodeURIComponent(P)+"="+A+";"}catch{}}}function Re(){var b;if(!(typeof window===t||!P)){try{b=window.localStorage[P]}catch{}if(typeof b===t)try{var A=window.document.cookie,J=encodeURIComponent(P),De=A.indexOf(J+"=");De!==-1&&(b=/^([^;]+)/.exec(A.slice(De+J.length+1))[1])}catch{}return d.levels[b]===void 0&&(b=void 0),b}}function Vt(){if(!(typeof window===t||!P)){try{window.localStorage.removeItem(P)}catch{}try{window.document.cookie=encodeURIComponent(P)+"=; expires=Thu, 01 Jan 1970 00:00:00 UTC"}catch{}}}function _(b){var A=b;if(typeof A=="string"&&d.levels[A.toUpperCase()]!==void 0&&(A=d.levels[A.toUpperCase()]),typeof A=="number"&&A>=0&&A<=d.levels.SILENT)return A;throw new TypeError("log.setLevel() called with invalid level: "+b)}d.name=p,d.levels={TRACE:0,DEBUG:1,INFO:2,WARN:3,ERROR:4,SILENT:5},d.methodFactory=v||m,d.getLevel=function(){return V??fe??$},d.setLevel=function(b,A){return V=_(b),A!==!1&&zt(V),l.call(d)},d.setDefaultLevel=function(b){fe=_(b),Re()||d.setLevel(b,!1)},d.resetLevel=function(){V=null,Vt(),l.call(d)},d.enableAll=function(b){d.setLevel(d.levels.TRACE,b)},d.disableAll=function(b){d.setLevel(d.levels.SILENT,b)},d.rebuild=function(){if(o!==d&&($=_(o.getLevel())),l.call(d),o===d)for(var b in i)i[b].rebuild()},$=_(o?o.getLevel():"WARN");var ke=Re();ke!=null&&(V=_(ke)),l.call(d)}o=new c,o.getLogger=function(v){if(typeof v!="symbol"&&typeof v!="string"||v==="")throw new TypeError("You must supply a name when creating a logger.");var d=i[v];return d||(d=i[v]=new c(v,o.methodFactory)),d};var g=typeof window!==t?window.log:void 0;return o.noConflict=function(){return typeof window!==t&&window.log===o&&(window.log=g),o},o.getLoggers=function(){return i},o.default=o,o})});var Gn={};Yt(Gn,{init:()=>de});var N=x(L(),1);var Fe={name:"@reform-society/agera-survey",version:"0.1.0",description:"Multi-step survey runtime for Webflow",type:"module",main:"dist/index.global.js",types:"dist/index.d.ts",files:["dist/index.global.js"],repository:{type:"git",url:"git+https://github.com/reform-society/agera-survey-app.git",directory:"packages/agera-survey"},keywords:["webflow","survey","form","multi-step"],author:"Reform Society",license:"MIT",publishConfig:{access:"public",provenance:!0},scripts:{dev:"tsup src/index.ts --format iife --global-name AgeraSurvey --watch --out-dir dist --sourcemap",build:"tsup src/index.ts --format iife --global-name AgeraSurvey --out-dir dist --minify","build:analyze":"tsup src/index.ts --format iife --global-name AgeraSurvey --out-dir dist --minify --metafile",lint:"eslint src",typecheck:"tsc --noEmit",check:"pnpm lint; pnpm typecheck"},devDependencies:{"@agera/config":"workspace:*",loglevel:"^1.9.2",nanostores:"^0.11.3","libphonenumber-js":"1.12.25",tsup:"^8.3.5",typescript:"^5.7.2"}};var Oe=Fe.version;var y=x(L(),1);var I=[],q=0,Z=4,Xt=0,ee=e=>{let t=[],r={get(){return r.lc||r.listen(()=>{})(),r.value},lc:0,listen(n){return r.lc=t.push(n),()=>{for(let o=q+Z;o<I.length;)I[o]===n?I.splice(o,Z):o+=Z;let i=t.indexOf(n);~i&&(t.splice(i,1),--r.lc||r.off())}},notify(n,i){Xt++;let o=!I.length;for(let s of t)I.push(s,r.value,n,i);if(o){for(q=0;q<I.length;q+=Z)I[q](I[q+1],I[q+2],I[q+3]);I.length=0}},off(){},set(n){let i=r.value;i!==n&&(r.value=n,r.notify(i))},subscribe(n){let i=r.listen(n);return n(r.value),i},value:e};return r};var h=ee({id:typeof crypto<"u"&&"randomUUID"in crypto?crypto.randomUUID():`${Date.now()}`,answers:{},startedAt:new Date}),w=ee({current:"",path:[]});function $e(){if(typeof window>"u")return;let e=window.localStorage.getItem("as:session");if(e)try{let t=JSON.parse(e);h.set({...t,startedAt:new Date(t.startedAt)})}catch{window.localStorage.removeItem("as:session")}h.subscribe(t=>{try{window.localStorage.setItem("as:session",JSON.stringify(t))}catch{}})}var M=x(L(),1);var pe=x(L(),1),Zt="https://cdn.jsdelivr.net/npm/libphonenumber-js@1.12.25/max/index.js",en="https://unpkg.com/libphonenumber-js@1.12.25/max/index.js",te=null,W=null;async function me(){return te||W||(W=(async()=>{let e=[Zt,en],t=null;for(let n of e)try{let o=await import(n),s=o.parsePhoneNumberFromString||o.default?.parsePhoneNumberFromString||o.default,a=o.AsYouType||o.default?.AsYouType,u=o.getCountryCallingCode||o.default?.getCountryCallingCode;if(!s||typeof s!="function")throw new Error("parsePhoneNumberFromString not found in module");if(!a||typeof a!="function")throw new Error("AsYouType not found in module");if(!u||typeof u!="function")throw new Error("getCountryCallingCode not found in module");return te={parsePhoneNumberFromString:s,AsYouType:a,getCountryCallingCode:u},te}catch(i){t=i instanceof Error?i:new Error(String(i)),pe.default.warn(`[phone-lib] Failed to load from ${n}, trying fallback...`,t)}let r=new Error(`Failed to load libphonenumber-js from all CDN URLs. Last error: ${t?.message}`);throw pe.default.error("[phone-lib] Failed to load libphonenumber-js from all CDNs:",r),W=null,r})(),W)}async function ne(){try{return(await me())?.parsePhoneNumberFromString??null}catch{return null}}async function ze(){try{return(await me())?.AsYouType??null}catch{return null}}async function Ve(){try{return(await me())?.getCountryCallingCode??null}catch{return null}}var ge={"sv-SE":{required:"Detta f\xE4lt \xE4r obligatoriskt",email:"V\xE4nligen ange en giltig e-postadress",phone:"V\xE4nligen ange ett giltigt telefonnummer",pattern:"Ogiltigt format",min:"F\xF6r kort",max:"F\xF6r l\xE5ngt"},"nb-NO":{required:"Dette feltet er obligatorisk",email:"Vennligst oppgi en gyldig e-postadresse",phone:"Vennligst oppgi et gyldig telefonnummer",pattern:"Ugyldig format",min:"For kort",max:"For lang"},no:{required:"Dette feltet er obligatorisk",email:"Vennligst oppgi en gyldig e-postadresse",phone:"Vennligst oppgi et gyldig telefonnummer",pattern:"Ugyldig format",min:"For kort",max:"For lang"},"da-DK":{required:"Dette felt er p\xE5kr\xE6vet",email:"Indtast venligst en gyldig e-mailadresse",phone:"Indtast venligst et gyldigt telefonnummer",pattern:"Ugyldigt format",min:"For kort",max:"For lang"},"en-US":{required:"This field is required",email:"Please enter a valid email",phone:"Please enter a valid phone number",pattern:"Invalid format",min:"Too short",max:"Too long"},en:{required:"This field is required",email:"Please enter a valid email",phone:"Please enter a valid phone number",pattern:"Invalid format",min:"Too short",max:"Too long"},"de-DE":{required:"Dieses Feld ist erforderlich",email:"Bitte geben Sie eine g\xFCltige E-Mail-Adresse ein",phone:"Bitte geben Sie eine g\xFCltige Telefonnummer ein",pattern:"Ung\xFCltiges Format",min:"Zu kurz",max:"Zu lang"},"es-ES":{required:"Este campo es obligatorio",email:"Por favor, introduce un correo electr\xF3nico v\xE1lido",phone:"Por favor, introduce un n\xFAmero de tel\xE9fono v\xE1lido",pattern:"Formato no v\xE1lido",min:"Demasiado corto",max:"Demasiado largo"},"fi-FI":{required:"T\xE4m\xE4 kentt\xE4 on pakollinen",email:"Anna kelvollinen s\xE4hk\xF6postiosoite",phone:"Anna kelvollinen puhelinnumero",pattern:"Virheellinen muoto",min:"Liian lyhyt",max:"Liian pitk\xE4"},"fr-FR":{required:"Ce champ est obligatoire",email:"Veuillez saisir une adresse e-mail valide",phone:"Veuillez saisir un num\xE9ro de t\xE9l\xE9phone valide",pattern:"Format invalide",min:"Trop court",max:"Trop long"}};function je(){let e=ge.en;if(typeof document>"u")return e;let t=document.documentElement.lang;if(!t)return e;let r=ge[t];if(r)return r;let n=t.split("-")[0];if(n){let i=ge[n];if(i)return i}return e}var T=x(L(),1);var tn=new Set(["__quiz__"]);function nn(e){let t={};return e.querySelectorAll("input, textarea, select").forEach(n=>{if(!n.name&&!n.hasAttribute("as-element-id"))return;let i=[];n.name&&i.push(n.name);let o=n.getAttribute("as-element-id");o&&i.push(o);let s=n.value;if(n instanceof HTMLInputElement&&n.type==="checkbox")s=!!n.checked;else if(n instanceof HTMLInputElement&&n.type==="radio"){if(!n.checked)return;s=n.value}i.forEach(a=>{t[a]=s})}),t}function ye(e){if(typeof document>"u"||!e)return;let t=h.get(),r=nn(e),n=rn(t.answers,r);on(t.answers,n)&&h.set({...t,answers:n})}function rn(e,t){let r={...t};for(let[n,i]of Object.entries(e))(!(n in r)||tn.has(n))&&(r[n]=i);return r}function on(e,t){let r=Object.keys(e),n=Object.keys(t);if(r.length!==n.length)return!0;for(let i of n)if(e[i]!==t[i])return!0;return!1}function Ue(){if(typeof document>"u")return{style:{}};let e=document.getElementById("as-aria-live");if(!e){e=document.createElement("div"),e.id="as-aria-live",e.setAttribute("aria-live","polite"),e.setAttribute("aria-atomic","true");let t=e;t.style.position="absolute",t.style.left="-10000px",t.style.width="1px",t.style.height="1px",t.style.overflow="hidden",document.body.appendChild(e)}return e}function Be(e,t){if(e.startsWith("env.")){let r=e.slice(4).split(".");if(r[0]==="utm"&&r[1])return new URLSearchParams(typeof window<"u"?window.location.search:"").get(`utm_${r[1]}`);if(r[0])return t[r[0]]}if(e.startsWith("quiz.")){let r=e.slice(5).split("."),n=t.__quiz__;if(!n)return;if(r[0]==="winner"){if(r.length===1)return n.winner;if(r[1]==="score")return n.winnerScore}return r[0]==="scores"&&r[1]?n.scores?.[r[1]]:void 0}return t[e]}function H(e,t){switch(e){case"slide-left-right":return t==="in"?"slide-in-left":"slide-out-right";case"slide-right-left":return t==="in"?"slide-in-right":"slide-out-left";case"slide-up-down":return t==="in"?"slide-in-up":"slide-out-down";case"slide-down-up":return t==="in"?"slide-in-down":"slide-out-up";case"scale":return t==="in"?"scale-in":"scale-out";case"fade":return"fade";default:return"fade"}}function R(e,t,r){let n={initial:{},target:{}};switch(e){case"fade":r==="in"?(n.initial={opacity:"0"},n.target={opacity:"1"}):(n.initial={opacity:"1"},n.target={opacity:"0"});break;case"slide-in-left":n.initial={transform:`translateX(-${t})`,opacity:"0"},n.target={transform:"translateX(0)",opacity:"1"};break;case"slide-in-right":n.initial={transform:`translateX(${t})`,opacity:"0"},n.target={transform:"translateX(0)",opacity:"1"};break;case"slide-in-up":n.initial={transform:`translateY(-${t})`,opacity:"0"},n.target={transform:"translateY(0)",opacity:"1"};break;case"slide-in-down":n.initial={transform:`translateY(${t})`,opacity:"0"},n.target={transform:"translateY(0)",opacity:"1"};break;case"slide-out-left":n.initial={transform:"translateX(0)",opacity:"1"},n.target={transform:`translateX(-${t})`,opacity:"0"};break;case"slide-out-right":n.initial={transform:"translateX(0)",opacity:"1"},n.target={transform:`translateX(${t})`,opacity:"0"};break;case"slide-out-up":n.initial={transform:"translateY(0)",opacity:"1"},n.target={transform:`translateY(-${t})`,opacity:"0"};break;case"slide-out-down":n.initial={transform:"translateY(0)",opacity:"1"},n.target={transform:`translateY(${t})`,opacity:"0"};break;case"scale-in":n.initial={transform:"scale(0.98)",opacity:"0"},n.target={transform:"scale(1)",opacity:"1"};break;case"scale-out":n.initial={transform:"scale(1)",opacity:"1"},n.target={transform:"scale(0.98)",opacity:"0"};break}return n}function Qe(e,t={}){let{defaultDuration:r="300ms",defaultDistance:n="24px",onComplete:i,displayValue:o=""}=t,s=window.matchMedia("(prefers-reduced-motion: reduce)").matches;if(e.style.display=o,e.removeAttribute("hidden"),e.removeAttribute("aria-hidden"),s){e.style.opacity="1",i?.();return}let a=e.getAttribute("as-transition-in")||e.getAttribute("as-transition")||"fade",u=H(a,"in"),l=e.getAttribute("as-transition-distance")||n,f=e.getAttribute("as-transition-speed-in")||e.getAttribute("as-transition-speed"),m=R(u,l,"in"),c=window.getComputedStyle(e),g=F(c.transitionDuration,c.transitionDelay)>0,p=!1,v=c.transitionProperty||"";/(^|,|\s)(all|transform|opacity)(,|\s|$)/.test(v)||(e.style.transitionProperty="opacity, transform",p=!0),!g&&!f&&(e.style.transitionDuration=r,p||(e.style.transitionProperty="opacity, transform",p=!0)),f&&D(e,f),Object.assign(e.style,m.initial),e.offsetHeight,requestAnimationFrame(()=>{Object.assign(e.style,m.target),k(e,()=>{!g&&!f&&(e.style.transitionDuration=""),f&&(e.style.transitionDuration=""),p&&(e.style.transitionProperty=""),i?.()})})}function Ge(e,t={}){let{defaultDuration:r="300ms",defaultDistance:n="24px",onComplete:i}=t;if(window.matchMedia("(prefers-reduced-motion: reduce)").matches){e.style.display="none",e.setAttribute("aria-hidden","true"),i?.();return}let s=e.getAttribute("as-transition-out")||e.getAttribute("as-transition")||"fade",a=H(s,"out"),u=e.getAttribute("as-transition-distance")||n,l=e.getAttribute("as-transition-speed-out")||e.getAttribute("as-transition-speed"),f=R(a,u,"out"),m=window.getComputedStyle(e),c=F(m.transitionDuration,m.transitionDelay)>0,g=!1,p=m.transitionProperty||"";/(^|,|\s)(all|transform|opacity)(,|\s|$)/.test(p)||(e.style.transitionProperty="opacity, transform",g=!0),!c&&!l&&(e.style.transitionDuration=r,g||(e.style.transitionProperty="opacity, transform",g=!0)),l&&D(e,l),Object.assign(e.style,f.target),k(e,()=>{e.style.display="none",e.setAttribute("aria-hidden","true"),j(e),!c&&!l&&(e.style.transitionDuration=""),l&&(e.style.transitionDuration=""),g&&(e.style.transitionProperty=""),i?.()})}function Ye(e,t,r){let n={containerDisplay:e.style.display,containerAlignItems:e.style.alignItems,containerJustifyItems:e.style.justifyItems,incGridArea:t.style.gridArea,incZIndex:t.style.zIndex,outGridArea:r.style.gridArea,outZIndex:r.style.zIndex},i=window.getComputedStyle(e).display;return i!=="grid"&&i!=="inline-grid"&&(e.style.display="grid"),t.style.gridArea="1 / 1 / 2 / 2",r.style.gridArea="1 / 1 / 2 / 2",t.style.zIndex="1",r.style.zIndex="2",()=>{e.style.display=n.containerDisplay,e.style.alignItems=n.containerAlignItems,e.style.justifyItems=n.containerJustifyItems,t.style.gridArea=n.incGridArea,t.style.zIndex=n.incZIndex,r.style.gridArea=n.outGridArea,r.style.zIndex=n.outZIndex}}function Je(e,t,r){if(e.style.display="",e.setAttribute("aria-hidden","false"),e.removeAttribute("inert"),t){e.style.opacity="1",r(e);return}let n=e.getAttribute("as-transition-in")||e.getAttribute("as-transition")||"fade",i=H(n,"in"),o=e.getAttribute("as-transition-distance")||"24px",s=e.getAttribute("as-transition-speed-in")||e.getAttribute("as-transition-speed"),a=R(i,o,"in"),u=window.getComputedStyle(e),l=F(u.transitionDuration,u.transitionDelay)>0,f=!1,m=!1,c=u.transitionProperty||"";/(^|,|\s)(all|transform|opacity)(,|\s|$)/.test(c)||(e.style.transitionProperty="opacity, transform",f=!0),!l&&!s&&(e.style.transitionDuration="300ms",f||(e.style.transitionProperty="opacity, transform",f=!0)),e.style.willChange!=="opacity, transform"&&(e.style.willChange="opacity, transform",m=!0),s&&D(e,s),Object.assign(e.style,a.initial),e.offsetHeight,requestAnimationFrame(()=>{Object.assign(e.style,a.target),k(e,()=>{r(e),!l&&!s&&(e.style.transitionDuration=""),s&&(e.style.transitionDuration=""),f&&(e.style.transitionProperty=""),m&&(e.style.willChange="")})})}function be(e,t){if(t){e.style.setProperty("display","none","important"),e.setAttribute("aria-hidden","true"),e.setAttribute("inert","");return}let r=e.getAttribute("as-transition-out")||e.getAttribute("as-transition")||"fade",n=H(r,"out"),i=e.getAttribute("as-transition-distance")||"24px",o=e.getAttribute("as-transition-speed-out")||e.getAttribute("as-transition-speed"),s=R(n,i,"out"),a=window.getComputedStyle(e),u=F(a.transitionDuration,a.transitionDelay)>0,l=!1,f=!1,m=a.transitionProperty||"";/(^|,|\s)(all|transform|opacity)(,|\s|$)/.test(m)||(e.style.transitionProperty="opacity, transform",l=!0),!u&&!o&&(e.style.transitionDuration="300ms",l||(e.style.transitionProperty="opacity, transform",l=!0)),e.style.willChange!=="opacity, transform"&&(e.style.willChange="opacity, transform",f=!0),o&&D(e,o),Object.assign(e.style,s.target),k(e,()=>{e.style.setProperty("display","none","important"),e.setAttribute("aria-hidden","true"),e.setAttribute("inert",""),j(e),!u&&!o&&(e.style.transitionDuration=""),o&&(e.style.transitionDuration=""),l&&(e.style.transitionProperty=""),f&&(e.style.willChange="")})}function k(e,t){let r=window.getComputedStyle(e),n=r.transitionDuration,i=r.transitionDelay,o=F(n,i);if(o===0){t();return}let s=!1,a=setTimeout(()=>{s||(s=!0,t())},o+50),u=l=>{l.target===e&&!s&&(s=!0,clearTimeout(a),e.removeEventListener("transitionend",u),e.removeEventListener("animationend",u),t())};e.addEventListener("transitionend",u),e.addEventListener("animationend",u)}function D(e,t){let n=window.getComputedStyle(e).transitionDuration;switch(t){case"fast":e.style.transitionDuration=_e(n,.7);break;case"normal":break;case"slow":e.style.transitionDuration=_e(n,1.5);break;default:e.style.transitionDuration=t;break}}function _e(e,t){return e.split(",").map(n=>n.trim()).map(n=>{let i=n.match(/^([\d.]+)(m?s)$/);if(!i||!i[1]||!i[2])return n;let o=parseFloat(i[1]),s=i[2];return`${o*t}${s}`}).join(", ")}function F(e,t){let r=e.split(",").map(o=>We(o.trim())),n=t.split(",").map(o=>We(o.trim())),i=0;for(let o=0;o<r.length;o++){let s=r[o]||0,a=n[o]||n[0]||0,u=s+a;u>i&&(i=u)}return i}function We(e){let t=e.match(/^([\d.]+)(m?s)$/);if(!t||!t[1]||!t[2])return 0;let r=parseFloat(t[1]);return t[2]==="ms"?r:r*1e3}function j(e){e.style.opacity="",e.style.translate="",e.style.scale="",e.style.transform=""}function tt(e){e&&(ye(e),an(e),he(),Ze(),sn(),h.subscribe(()=>{he(),Ze()}),T.default.debug("[conditions] Initialized"))}function re(e,t){try{let r=JSON.parse(e);return z(r,t)}catch(r){return T.default.error("[conditions] Invalid predicate JSON:",r),!1}}function z(e,t){if("all"in e)return e.all.every(n=>z(n,t));if("any"in e)return e.any.some(n=>z(n,t));if("not"in e)return!z(e.not,t);if("field"in e&&"op"in e){let{field:r,op:n,value:i}=e,o=Be(r,t);switch(n){case"eq":return o===i;case"neq":return o!==i;case"in":return Array.isArray(i)&&i.includes(o);case"nin":return Array.isArray(i)&&!i.includes(o);case"gt":return Number(o)>Number(i);case"gte":return Number(o)>=Number(i);case"lt":return Number(o)<Number(i);case"lte":return Number(o)<=Number(i);case"exists":return o!=null;case"truthy":return!!o;case"falsy":return!o;case"contains":return String(o).includes(String(i));case"starts_with":return String(o).startsWith(String(i));case"ends_with":return String(o).endsWith(String(i));default:return!1}}return!1}function he(){if(typeof document>"u")return;let e=h.get().answers;document.querySelectorAll("[as-show-if]").forEach(t=>{let r=t.getAttribute("as-show-if");if(!r)return;let n=re(r,e);Ke(t,n)}),document.querySelectorAll("[as-hide-if]").forEach(t=>{let r=t.getAttribute("as-hide-if");if(!r)return;let n=re(r,e);Ke(t,!n)})}function Ke(e,t){let r=cn(e);if(t!==r){if(t){ln(e),T.default.debug("[conditions] Showing element with transition");return}un(e),T.default.debug("[conditions] Hiding element with transition")}}function sn(){if(typeof document>"u"||typeof MutationObserver>"u")return;new MutationObserver(()=>{T.default.debug("[conditions] DOM mutation detected, re-applying visibility"),he()}).observe(document.body,{childList:!0,subtree:!0})}function an(e){let t=()=>{ye(e)};e.addEventListener("input",t),e.addEventListener("change",t)}function ln(e){let t=nt(),r=rt(e);if(T.default.debug("[conditions] show transition start",{token:r,skipAnimation:t,element:ie(e)}),e.dataset.asVisibilityState="visible",dn(e),e.setAttribute("aria-hidden","false"),e.removeAttribute("inert"),t){j(e),e.style.opacity="",e.style.transform="",T.default.debug("[conditions] show transition skipped (reduced motion)",{token:r});return}let n=e.getAttribute("as-transition-in")||e.getAttribute("as-transition")||"fade",i=H(n,"in"),o=e.getAttribute("as-transition-distance")||"24px",s=e.getAttribute("as-transition-speed-in")||e.getAttribute("as-transition-speed"),a=R(i,o,"in"),u=window.getComputedStyle(e),l=F(u.transitionDuration,u.transitionDelay)>0,f=u.transitionProperty||"",m=/(^|,|\s)(all|transform|opacity)(,|\s|$)/.test(f),c=e.style.transitionProperty,g=e.style.transitionDuration,p=e.style.willChange;e.style.transitionProperty="none",e.style.transitionDuration="0ms",Object.assign(e.style,a.initial),e.offsetHeight,requestAnimationFrame(()=>{if(!ve(e,r)){T.default.debug("[conditions] show transition aborted before animation (token mismatch)",{token:r}),e.style.transitionProperty=c,e.style.transitionDuration=g,e.style.willChange=p;return}let v=!1,d=!1,$=!1;m?e.style.transitionProperty=c:(e.style.transitionProperty="opacity, transform",v=!0),s?D(e,s):l?e.style.transitionDuration=g:(e.style.transitionDuration="300ms",d=!0),e.style.willChange!=="opacity, transform"&&(e.style.willChange="opacity, transform",$=!0),Object.assign(e.style,a.target),k(e,()=>{if(!ve(e,r)){T.default.debug("[conditions] show transition cleanup skipped (token mismatch)",{token:r});return}(d||s)&&(e.style.transitionDuration=g),v&&(e.style.transitionProperty=c),$&&(e.style.willChange=p),T.default.debug("[conditions] show transition complete",{token:r,element:ie(e)})})})}function un(e){let t=nt(),r=rt(e);if(T.default.debug("[conditions] hide transition start",{token:r,skipAnimation:t,element:ie(e)}),e.dataset.asVisibilityState="hidden",t){Xe(e),e.setAttribute("aria-hidden","true"),e.setAttribute("inert",""),j(e),T.default.debug("[conditions] hide transition skipped (reduced motion)",{token:r});return}let n=e.getAttribute("as-transition-out")||e.getAttribute("as-transition")||"fade",i=H(n,"out"),o=e.getAttribute("as-transition-distance")||"24px",s=e.getAttribute("as-transition-speed-out")||e.getAttribute("as-transition-speed"),a=R(i,o,"out"),u=window.getComputedStyle(e),l=F(u.transitionDuration,u.transitionDelay)>0,f=!1,m=!1,c=u.transitionProperty||"";/(^|,|\s)(all|transform|opacity)(,|\s|$)/.test(c)||(e.style.transitionProperty="opacity, transform",f=!0),!l&&!s&&(e.style.transitionDuration="300ms",f||(e.style.transitionProperty="opacity, transform",f=!0)),e.style.willChange!=="opacity, transform"&&(e.style.willChange="opacity, transform",m=!0),s&&D(e,s),Object.assign(e.style,a.target),k(e,()=>{if(!ve(e,r)){T.default.debug("[conditions] hide transition cleanup skipped (token mismatch)",{token:r});return}Xe(e),e.setAttribute("aria-hidden","true"),e.setAttribute("inert",""),j(e),(!l&&!s||s)&&(e.style.transitionDuration=""),f&&(e.style.transitionProperty=""),m&&(e.style.willChange=""),T.default.debug("[conditions] hide transition complete",{token:r,element:ie(e)})})}function nt(){return typeof window>"u"||typeof window.matchMedia!="function"?!1:window.matchMedia("(prefers-reduced-motion: reduce)").matches}function rt(e){let t=typeof crypto<"u"&&"randomUUID"in crypto?crypto.randomUUID():`${Date.now()}-${Math.random().toString(16).slice(2)}`;return e.dataset.asVisibilityToken=t,t}function ve(e,t){return e.dataset.asVisibilityToken===t}function cn(e){let t=e.dataset.asVisibilityState;return t==="visible"?!0:!(t==="hidden"||e.getAttribute("aria-hidden")==="true"||e.style.display==="none")}function dn(e){e.style.removeProperty("display");let t=e.dataset.asDisplayCache;if(t&&t!=="none"){e.style.display=t;return}t||(e.style.display="")}function Xe(e){fn(e),e.style.setProperty("display","none","important")}function fn(e){if(e.dataset.asDisplayCache&&e.dataset.asDisplayCache!=="none")return;let t=e.style.display;if(t&&t!=="none"){e.dataset.asDisplayCache=t;return}if(typeof window<"u"&&typeof window.getComputedStyle=="function"){let r=window.getComputedStyle(e).display;r&&r!=="none"&&(e.dataset.asDisplayCache=r)}}function ie(e){let t=e.id?`#${e.id}`:"",r=e.getAttribute("as-element-id"),n=r?`[${r}]`:"";return`<${e.tagName.toLowerCase()}${t}${n}>`}function it(e,t){try{let r=JSON.parse(e);for(let n of r)if(z(n.if,t))return n.then;return null}catch(r){return T.default.error("[conditions] Invalid next-map JSON:",r),null}}function Ze(){if(typeof document>"u")return;let e=h.get().answers;document.querySelectorAll("[as-disable-if]").forEach(t=>{let r=t.getAttribute("as-disable-if");if(!r)return;let n=re(r,e);et(t,n)}),document.querySelectorAll("[as-enable-if]").forEach(t=>{let r=t.getAttribute("as-enable-if");if(!r)return;let n=re(r,e);et(t,!n)})}function et(e,t){if(!e.hasAttribute("data-as-original-tabindex")&&e.hasAttribute("tabindex")&&e.setAttribute("data-as-original-tabindex",e.getAttribute("tabindex")||"0"),t)(e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement||e instanceof HTMLSelectElement||e instanceof HTMLButtonElement)&&(e.disabled=!0),e.setAttribute("aria-disabled","true"),e.setAttribute("tabindex","-1"),e.classList.add("as-disabled"),e.removeAttribute("aria-invalid"),e.removeAttribute("aria-describedby");else{(e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement||e instanceof HTMLSelectElement||e instanceof HTMLButtonElement)&&(e.disabled=!1),e.removeAttribute("aria-disabled");let r=e.getAttribute("data-as-original-tabindex");r?(e.setAttribute("tabindex",r),e.removeAttribute("data-as-original-tabindex")):e.removeAttribute("tabindex"),e.classList.remove("as-disabled")}}function ot(e){return(e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement||e instanceof HTMLSelectElement||e instanceof HTMLButtonElement)&&e.disabled?!0:e.classList.contains("as-disabled")}var st={defaultDuration:"200ms",defaultDistance:"12px"},pn={required:e=>e.trim()!=="",email:e=>/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(e),pattern:(e,t)=>new RegExp(t).test(e),min:(e,t)=>e.length>=Number(t),max:(e,t)=>e.length<=Number(t)};function at(e){if(e.dataset.asErrorDisplay)return;let t="",r=e.style.display;if(r&&r!=="none"&&(t=r),!t&&typeof window<"u"&&typeof window.getComputedStyle=="function"){let n=window.getComputedStyle(e).display;n&&n!=="none"&&(t=n)}t||(t=e.tagName==="SPAN"||e.tagName==="LABEL"?"inline":"block"),e.dataset.asErrorDisplay=t}function lt(e){e.dataset.asErrorDefault||(e.dataset.asErrorDefault=e.textContent??""),at(e),e.hasAttribute("role")||e.setAttribute("role","alert"),e.hasAttribute("aria-live")||e.setAttribute("aria-live","polite")}function we(e,t){at(e);let r=e.hasAttribute("as-transition"),n=e.dataset.asErrorDisplay||"block";t?r?Qe(e,{...st,displayValue:n}):(e.style.display=n,e.removeAttribute("hidden"),e.removeAttribute("aria-hidden")):r?Ge(e,st):(e.style.display="none",e.setAttribute("aria-hidden","true"))}function mn(e){if(typeof document>"u")return;let t=[];e instanceof HTMLElement&&e.hasAttribute("as-error-for")&&t.push(e),e.querySelectorAll("[as-error-for]").forEach(r=>{t.includes(r)||t.push(r)});for(let r of t){lt(r);let n=r.dataset.asErrorActive==="true";we(r,n)}}async function gn(e,t){try{let r=await ne();if(!r)return M.default.warn("[validation] Phone library not available"),!1;let n=t?.getAttribute("as-phone-region")||void 0,i=e.trim().startsWith("+");if(M.default.debug("[validation] Validating phone:",e,"has + prefix:",i,"region:",n),i){let o=r(e);if(M.default.debug("[validation] Parse international:",o?"success":"failed"),o&&typeof o.isValid=="function"){let s=o.isValid();return M.default.debug("[validation] Country:",o.country,"isValid:",s),s}return M.default.debug("[validation] International number validation failed"),!1}else{if(!n)return M.default.debug("[validation] No region specified for national number"),!1;let o=r(e,n);if(M.default.debug("[validation] Parse with region:",o?"success":"failed"),o&&typeof o.isValid=="function"){let s=o.isValid();return M.default.debug("[validation] Country:",o.country,"isValid:",s),s}return M.default.debug("[validation] National number validation failed"),!1}}catch(r){return M.default.error("[validation] Failed to validate phone number:",r),!1}}function ut(e){mn(e),M.default.debug("[validation] Initialized")}async function U(e){if(typeof document>"u")return!0;let t=document.querySelector(`[as-step="${e}"]`);if(!t)return!0;let r=Array.from(t.querySelectorAll("input, textarea, select"));for(let n of r){if(ot(n)){oe(n);continue}if(vn(n)){oe(n);continue}let o=(n.getAttribute("as-validate")||"").split("|").map(l=>l.trim()).filter(Boolean),s=[],a=new Set;(n.hasAttribute("required")||n.required===!0)&&(s.push("required"),a.add("required"));for(let l of o)l&&(a.has(l)||(a.add(l),s.push(l)));if(s.length===0){oe(n);continue}let u=wn(n);for(let l of s){let[f,m]=l.split(":"),c=f||"",g;if(c==="phone")g=await gn(u,n);else if(c==="required")g=En(n,t);else{let p=pn[c];g=p?p(u,m??""):!0}if(!g)return yn(n,bn(n,c)),!1}oe(n)}return!0}function yn(e,t){let r=ct(e);if(r){dt(e);let i=hn(r);r.textContent=t,r.dataset.asErrorActive="true",we(r,!0),e.setAttribute("aria-invalid","true"),i&&e.setAttribute("aria-describedby",i);return}let n=e.nextElementSibling;(!n||!n.classList.contains("as-error"))&&(n=document.createElement("div"),n.className="as-error",n.setAttribute("role","alert"),e.parentElement?.insertBefore(n,e.nextSibling)),n.textContent=t,e.setAttribute("aria-invalid","true"),e.setAttribute("aria-describedby",n.id=`err-${typeof crypto<"u"&&"randomUUID"in crypto?crypto.randomUUID():Date.now()}`)}function oe(e){let t=ct(e);if(t){let r=t.dataset.asErrorDefault??"";t.textContent=r,delete t.dataset.asErrorActive,we(t,!1)}else dt(e);e.removeAttribute("aria-invalid"),e.removeAttribute("aria-describedby")}function ct(e){let t=e.getAttribute("as-element-id")||e.getAttribute("id")||e.getAttribute("name");return t?(e.closest("[as-step]")??document).querySelector(`[as-error-for="${t}"]`)??null:null}function dt(e){let t=e.nextElementSibling;t&&t.classList.contains("as-error")&&t.remove()}function bn(e,t){let r=e.getAttribute("as-error-message");if(r)return r;let n=e.getAttribute("as-error-messages");if(n)try{let o=JSON.parse(n);if(o[t])return o[t]}catch{}return je()[t]||"Invalid input"}function hn(e){if(lt(e),!e.id){let t=typeof crypto<"u"&&typeof crypto.randomUUID=="function"?crypto.randomUUID():`err-${Date.now()}`;e.id=t}return e.id}function vn(e){return e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement||e instanceof HTMLSelectElement?e.disabled:!1}function wn(e){if(e instanceof HTMLInputElement){let{type:t}=e;if(t==="checkbox"||t==="radio")return e.checked?e.value||"on":"";if(t==="file")return e.files&&e.files.length>0?"selected":""}return e instanceof HTMLSelectElement&&e.multiple?Array.from(e.selectedOptions).map(t=>t.value).join(","):e.value??""}function En(e,t){if(e instanceof HTMLInputElement){if(e.disabled)return!0;switch(e.type){case"checkbox":return e.checked;case"radio":{let r=e.name;if(!r)return e.checked;let n=`input[type="radio"][name="${An(r)}"]`,i=t.querySelectorAll(n);for(let o of Array.from(i))if(!o.disabled&&o.checked)return!0;return!1}case"file":return!!(e.files&&e.files.length>0);default:return e.value.trim()!==""}}return e instanceof HTMLSelectElement?e.disabled?!0:e.multiple?e.selectedOptions.length>0:e.value.trim()!=="":e instanceof HTMLTextAreaElement?e.disabled?!0:e.value.trim()!=="":!0}function An(e){return typeof CSS<"u"&&typeof CSS.escape=="function"?CSS.escape(e):e.replace(/["\\]/g,"\\$&")}var C=x(L(),1);var S=x(L(),1);var Ee=new Map;function ft(e){let t=Ae();if(!t){S.default.debug("[basin] No endpoint found in meta tag, skipping Basin integration");return}Tn(e),typeof window<"u"&&window.addEventListener("beforeunload",()=>{let r=Te();r.set("basinjsdraft","true"),navigator.sendBeacon(t,r)}),S.default.debug("[basin] Initialized with endpoint:",t)}function Ae(){if(typeof document>"u")return"";let e=document.querySelector('meta[name="as:basin-endpoint"]');if(e?.content)return e.content;let t=document.body;return t?.hasAttribute("as-basin-endpoint")&&t.getAttribute("as-basin-endpoint")||""}async function pt(e){if(typeof window>"u")return"";let t=window.localStorage.getItem("as:basin-jwt");if(t)return t;try{let r=await fetch(`${e}/generate_jwt`,{method:"GET",headers:{"Content-Type":"application/json",Accept:"application/json"}});if(!r.ok)return S.default.warn("[basin] JWT endpoint returned",r.status,"- multistep may not be supported"),"";let n=await r.json();return n.jwt?(window.localStorage.setItem("as:basin-jwt",n.jwt),n.jwt):""}catch(r){return S.default.warn("[basin] Failed to fetch JWT (multistep may not be supported):",r),""}}async function se(e){let t=Ae();if(!t){S.default.warn("[basin] No endpoint, skipping partial submission");return}let r=await pt(t),n=Te();r&&n.append("basinjwt",r),n.append("basinjsmultistep","true"),n.append("basinjsdraft","true");let i=mt(e);if(n.append("basinjsstep",String(i)),S.default.getLevel()<=S.default.levels.DEBUG){S.default.debug(`[basin] Sending partial submission for step: ${e}`);let o=[];n.forEach((s,a)=>{o.push(` ${a}: ${typeof s=="string"?s.substring(0,100):"[File]"}`)}),S.default.debug(`[basin] FormData contents:
|
|
2
|
-
|
|
3
|
-
`)}`)}try{let o=await fetch(t,{method:"POST",body:n,keepalive:!0});if(!o.ok){S.default.warn("[basin] Partial submission failed with status:",o.status);return}S.default.debug("[basin] Sent partial submission for step:",e)}catch(o){S.default.error("[basin] Failed to send partial submission:",o)}}async function ae(e){let t=Ae();if(!t){S.default.warn("[basin] No endpoint, skipping final submission");return}let r=await pt(t),n=Te();r&&n.append("basinjwt",r),n.append("basinjsmultistep","true"),n.append("basinjsdraft","false");try{await fetch(t,{method:"POST",body:n,keepalive:!0}),S.default.debug("[basin] Sent final submission for step:",e)}catch(i){S.default.error("[basin] Failed to send final submission:",i)}}function Te(){let e=new FormData;if(typeof document<"u"){document.querySelectorAll('input[name]:not([type="file"]), textarea[name], select[name]').forEach(n=>{let i=n.name;i&&(n instanceof HTMLInputElement?n.type==="checkbox"?n.checked&&e.append(i,n.value||"on"):n.type==="radio"?n.checked&&e.append(i,n.value):n.value&&e.append(i,n.value):(n instanceof HTMLTextAreaElement||n instanceof HTMLSelectElement)&&n.value&&e.append(i,n.value))});let r=document.querySelectorAll('input[type="file"][name]');Sn(e,r)}if(e.append("frombasinjs","false"),e.append("agera_version","0.1.1"),typeof window<"u"){let t=new URLSearchParams(window.location.search);["source","medium","campaign","term","content"].forEach(r=>{let n=t.get(`utm_${r}`);n&&e.append(`utm_${r}`,n)})}return e}function Tn(e){e.querySelectorAll("input, textarea, select").forEach(r=>{r.name&&(Ee.set(r.name,{displayedAt:new Date}),r.addEventListener("focus",()=>{let n=Ee.get(r.name);n&&!n.firstFocusedAt&&(n.firstFocusedAt=new Date)},{once:!0}),r.addEventListener("input",()=>{let n=Ee.get(r.name);n&&(n.firstAnsweredAt||(n.firstAnsweredAt=new Date),n.lastEditedAt=new Date)}))})}function Sn(e,t){t.forEach(r=>{r.files&&r.name&&Array.from(r.files).forEach(n=>{e.append(r.name,n)})})}function gt(e){e&&(Ln(e),C.default.debug("[redirect] Initialized"))}function Ln(e){e.querySelectorAll("[as-redirect]").forEach(t=>{t.dataset.asRedirectBound!=="true"&&(t.addEventListener("click",r=>{if(r.defaultPrevented)return;let n=r.currentTarget;if(n.hasAttribute("as-next")){C.default.debug("[redirect] Skipping auto-click handler because element also has [as-next]");return}r.preventDefault();let i=n.closest("[as-step]"),o=Cn(i);if(!o){C.default.warn("[redirect] Could not resolve step for redirect trigger:",Hn(n));return}(async()=>{if(In(n,i)&&!await U(o)){C.default.debug("[redirect] Validation failed, aborting redirect click");return}await Le(o,n)})()}),t.dataset.asRedirectBound="true")})}async function Le(e,t){if(typeof document>"u"||typeof window>"u")return;let r=document.querySelector(`[as-step="${e}"]`),n=t instanceof Element?t:null,i=Mn(r,n);if(await ae(e),!i){C.default.debug("[redirect] No redirect configured, final submission sent");return}let o=xn(i.url,i.preserveUtm,i.includeSession,h.get().id);if(C.default.debug("[redirect] Redirecting via %s to: %s",i.source,o),i.useReplace){window.location.replace(o);return}window.location.assign(o)}function xn(e,t,r,n){if(typeof window>"u")return e;let i=new URL(e,window.location.origin);return t&&new URLSearchParams(window.location.search).forEach((s,a)=>{s&&a.toLowerCase().startsWith("utm")&&i.searchParams.set(a,s)}),r&&n&&i.searchParams.set("sessionId",n),i.toString()}function le(e,t){if(!e||!e.hasAttribute(t))return null;let r=e.getAttribute(t);if(!r)return!0;let n=r.trim().toLowerCase();return!["false","0","off","no"].includes(n)}function Mn(e,t){let r=h.get().answers,n=t?.getAttribute("as-redirect-map")??e?.getAttribute("as-redirect-map");if(n){let o=Pn(n,r);if(o)return{url:o.to,preserveUtm:o.preserveUtm??!0,includeSession:o.includeSession??!1,useReplace:o.replace??!1,source:"map"};C.default.debug("[redirect] Redirect map evaluated with no matching rule, falling back to attribute")}let i=t?.getAttribute("as-redirect")??e?.getAttribute("as-redirect");return i?{url:i,preserveUtm:Se("as-redirect-preserve-utm",t,e,!0),includeSession:Se("as-redirect-include-session",t,e,!1),useReplace:Se("as-redirect-replace",t,e,!1),source:"attribute"}:null}function Se(e,t,r,n){return le(t,e)??le(r,e)??n}function Pn(e,t){try{let r=JSON.parse(e);if(!Array.isArray(r))return C.default.warn("[redirect] as-redirect-map must be an array of rules"),null;for(let n of r){if(!n||typeof n.to!="string"||n.to.trim()===""){C.default.warn("[redirect] Redirect map rule missing a 'to' URL, skipping");continue}if(!n.if||z(n.if,t))return n}}catch(r){C.default.error("[redirect] Invalid as-redirect-map JSON:",r)}return null}function In(e,t){return le(e,"as-redirect-validate")??le(t,"as-redirect-validate")??!0}function Cn(e){return e?.hasAttribute("as-step")?e.getAttribute("as-step"):w.get().current||null}function Hn(e){let t=e.getAttribute("id"),r=e.closest("[as-step]")?.getAttribute("as-step");return`<${e.tagName.toLowerCase()}${t?`#${t}`:""}${r?` step="${r}"`:""}>`}function yt(){document.addEventListener("keydown",e=>{if(e.key==="Enter"&&e.target instanceof HTMLInputElement){let t=document.querySelector(`[as-step="${w.get().current}"] [as-next]`);t instanceof HTMLElement&&(e.preventDefault(),t.click())}})}function xe(e){let t=Ue();t.textContent=e}function Me(e){let t=e.querySelector("input, textarea, select, button");t&&setTimeout(()=>t.focus(),100)}var Rn=80;function kn(){return typeof document>"u"?!0:document.body?.getAttribute("as-partial-submissions")?.toLowerCase()!=="off"}function bt(e){let t=e.querySelector(":focus");t&&(y.default.debug("[steps] \u{1F532} Blurring focused element before hiding step"),t.blur())}function ht(e){let t=Array.from(e.querySelectorAll("[as-step]"));if(t.length===0)return;let r=t[0]?.getAttribute("as-step");r&&(w.set({current:r,path:[r]}),y.default.debug(`[steps] First step already visible: ${r}`)),Nn(e),yt()}function Q(e,t){y.default.debug(`[steps] \u{1F4C4} showStep called: "${e}"${t?` (from: "${t}")`:""}`);let r=Array.from(document.querySelectorAll("[as-step]")),n=typeof window<"u"&&window.matchMedia("(prefers-reduced-motion: reduce)").matches,i=document.querySelector(`[as-step="${e}"]`),o=t?document.querySelector(`[as-step="${t}"]`):null;if(!i){y.default.warn(`[steps] \u274C Cannot show step "${e}" - element not found`);return}y.default.debug(`[steps] \u{1F3AC} Transition: ${n?"reduced motion":"animated"}`),t&&t!==e&&kn()&&(y.default.debug(`[steps] \u{1F4BE} Triggering background partial submission for: "${t}"`),se(t).catch(a=>{y.default.error("[steps] Background partial submission failed:",a)})),r.forEach(a=>{let u=a.getAttribute("as-step");if(u!==e&&u!==t){let l=a;bt(l),l.style.setProperty("display","none","important"),l.setAttribute("aria-hidden","true"),l.setAttribute("inert","")}});let s;if(i&&o&&!n){let a=i.parentElement;a&&(s=Ye(a,i,o));let u=i.getAttribute("as-transition-in")||i.getAttribute("as-transition")||"fade",l=H(u,"in"),f=i.getAttribute("as-transition-distance")||"24px",m=i.getAttribute("as-transition-speed-in")||i.getAttribute("as-transition-speed"),c=R(l,f,"in");i.style.display="",i.style.visibility="hidden",i.setAttribute("aria-hidden","true"),i.setAttribute("inert","");let g=i.style.transitionProperty;i.style.transitionProperty="none",Object.assign(i.style,c.initial),i.offsetHeight,o&&bt(o),be(o,!1),k(o,()=>{setTimeout(()=>{i.setAttribute("aria-hidden","false"),i.removeAttribute("inert"),i.style.transitionProperty="opacity, transform",i.style.transitionDuration="300ms",m&&D(i,m),i.style.willChange!=="opacity, transform"&&(i.style.willChange="opacity, transform"),i.style.visibility="visible",Object.assign(i.style,c.target),k(i,()=>{i.style.transitionDuration="",i.style.transitionProperty=g,i.style.willChange="",Me(i),s&&s()})},Rn)});return}i&&Je(i,n,Me),o&&be(o,n),xe(`Step: ${e}`),y.default.debug(`[steps] \u2705 Step visible: "${e}"`)}function Dn(e){let t=Array.from(document.querySelectorAll("[as-step]")),n=document.querySelector(`[as-step="${e}"]`)?.getAttribute("as-next-map");if(n){y.default.debug("[steps] \u{1F5FA}\uFE0F Evaluating next-map for conditional routing");let s=h.get().answers,a=it(n,s);if(a)return y.default.debug(`[steps] \u2713 Next-map resolved to: "${a}"`),a;y.default.debug("[steps] \u26A0\uFE0F Next-map evaluation returned no match, falling back to linear")}let i=t.findIndex(s=>s.getAttribute("as-step")===e),o=t[i+1]?.getAttribute("as-step")||e;return o!==e&&y.default.debug(`[steps] \u{1F4CB} Linear next step: "${o}"`),o}function Nn(e){e.querySelectorAll("[as-next]").forEach(t=>{t.addEventListener("click",r=>{let n=r.currentTarget;(async()=>{let{current:i,path:o}=w.get();if(y.default.debug(`[steps] \u{1F537} Next button clicked on step: ${i}`),y.default.debug(`[steps] Validating step: ${i}`),!await U(i)){y.default.debug(`[steps] \u274C Validation failed, staying on step: ${i}`);return}y.default.debug("[steps] \u2713 Validation passed");let a=Dn(i);a!==i?(y.default.debug(`[steps] \u27A1\uFE0F Navigating from "${i}" to "${a}"`),w.set({current:a,path:[...o,a]}),Q(a,i)):(y.default.debug("[steps] \u{1F3C1} No next step found, checking for redirect"),await Le(i,n))})()})}),e.querySelectorAll("[as-back]").forEach(t=>{t.addEventListener("click",()=>{let{current:r,path:n}=w.get();if(y.default.debug(`[steps] \u{1F519} Back button clicked on step: ${r}`),n.length>1){let i=n.slice(0,-1),o=i[i.length-1];o&&(y.default.debug(`[steps] \u2B05\uFE0F Navigating back from "${r}" to "${o}"`),w.set({current:o,path:i}),Q(o,r))}else y.default.debug("[steps] \u26A0\uFE0F Cannot go back, already at first step")})}),e.querySelectorAll("[as-goto]").forEach(t=>{let r=null;t.addEventListener("click",n=>{let i=t.getAttribute("as-goto");if(!i||i.trim()==="")return;let o=n.currentTarget,{current:s}=w.get();y.default.debug(`[steps] \u{1F3AF} Goto clicked on step "${s}", target: "${i}" (element: ${o.tagName})`),r&&(clearTimeout(r),r=null,y.default.debug("[steps] \u23F1\uFE0F Cleared previous goto timeout"));let a=o.tagName==="BUTTON"||o.tagName==="A",u=o.tagName==="A",l=a||u?0:500,f=()=>{let{current:m,path:c}=w.get();if(!document.querySelector(`[as-step="${i}"]`)){y.default.warn(`[steps] \u274C Target step not found: ${i}`);return}y.default.debug(`[steps] \u2197\uFE0F Goto navigating from "${m}" to "${i}"`),w.set({current:i,path:[...c,i]}),Q(i,m)};l>0?(y.default.debug(`[steps] \u23F1\uFE0F Debouncing goto by ${l}ms`),r=setTimeout(f,l)):f()})}),e.querySelectorAll("[as-restart]").forEach(t=>{t.addEventListener("click",()=>{y.default.debug("[steps] \u{1F504} Restart button clicked, resetting survey"),window.agera?.survey?.reset()})})}function mt(e){if(typeof document>"u")return 1;let r=Array.from(document.querySelectorAll("[as-step]")).findIndex(n=>n.getAttribute("as-step")===e);return r>=0?r+1:1}var Lt=x(L(),1);var Ie=x(L(),1);function vt(e,t=document){return e.closest("[as-step]")||t}function G(e){return e?e.split("|").map(t=>t.trim()).filter(Boolean):[]}function Pe(e,t){return G(e).includes(t)}function wt(e){return Array.from(e).some(t=>Pe(t.getAttribute("as-validate"),"required"))}function Et(e){return["true","false",""].includes(e.toLowerCase())}function At(e,t){return e.querySelectorAll(`input[type="radio"][name="${t}"]`)}function ue(e,t){t.length>0?e.setAttribute("as-validate",t.join("|")):e.removeAttribute("as-validate")}function Tt(e,t,r="input, select, textarea"){let n=[],i=new Set,o=r.split(",").map(s=>`${s.trim()}[${t}]`).join(", ");return e.querySelectorAll(o).forEach(s=>{i.has(s)||(i.add(s),n.push({attrElement:s,input:s}))}),e.querySelectorAll(`label[${t}]`).forEach(s=>{let a=s.querySelector(r);a&&!i.has(a)&&(i.add(a),n.push({attrElement:s,input:a}))}),n}function Ce(e){let t=e||document;t.querySelectorAll("[as-radio-other-input]").forEach(r=>{let n=r,i=vt(n,t),o=r.getAttribute("as-radio-other-input")||"",s=null;if(Et(o)&&(o=""),o?(s=qn(i,o),s&&(o=s.name)):(s=Fn(n,i),s&&(o=s.name)),!s||!o){Ie.default.debug("[components:radio-other-input] 'other' radio not found near input",n);return}let a=At(i,o);On(n,s,a)}),Ie.default.debug("[components:radio-other-input] Initialized")}function qn(e,t){let r=e.querySelectorAll('input[type="radio"][value="other"]');for(let n of r)if(n.name.toLowerCase()===t.toLowerCase())return n;return null}function Fn(e,t){let r=e.parentElement;for(;r&&r!==t.parentElement;){let n=r.querySelector('input[type="radio"][value="other"]');if(n)return n;r=r.parentElement}return t.querySelector('input[type="radio"][value="other"]')}function On(e,t,r){e.removeAttribute("name");let n=e.getAttribute("as-validate"),i=e.hasAttribute("required"),o=Pe(n,"required"),s=wt(r),a=e.hasAttribute("as-radio-other-required"),u=s||a,l=()=>{let c=e.value.trim();t.value=c||"other"},f=()=>{if(u)if(t.checked){let c=G(n);c.includes("required")||c.push("required"),ue(e,c),e.setAttribute("required","")}else{if(n!==null)if(o)e.setAttribute("as-validate",n);else{let c=G(e.getAttribute("as-validate")).filter(g=>g!=="required");ue(e,c)}else{let c=G(e.getAttribute("as-validate")).filter(g=>g!=="required");ue(e,c)}i||e.removeAttribute("required")}};r.forEach(c=>{c.addEventListener("change",()=>{c===t&&t.checked&&(l(),setTimeout(()=>{e.focus()},0)),f()})});let m=()=>{t.checked||(t.checked=!0,t.dispatchEvent(new Event("change",{bubbles:!0})))};e.addEventListener("click",m),e.addEventListener("focus",m),e.addEventListener("input",l),e.addEventListener("change",l),e.addEventListener("blur",l),l(),f()}var E=x(L(),1);function He(e){(e||document).querySelectorAll("[as-phone-format]").forEach(r=>{let n=r.getAttribute("as-phone-region")||void 0,i=r.getAttribute("as-phone-format")||"INTERNATIONAL",o=null,s=!1;St(n).then(a=>{o=a}),r.addEventListener("focus",()=>{$n(r,i,n,s,a=>{s=a})}),r.addEventListener("input",()=>{zn(r,n,o,a=>{o=a})}),r.addEventListener("blur",()=>{Vn(r,i,n)})}),E.default.debug("[components:phone-format] Initialized")}async function St(e){try{let t=await ze();return t?new t(e):null}catch(t){return E.default.warn("[components:phone-format] Failed to initialize AsYouType:",t),null}}async function $n(e,t,r,n,i){if(n||e.value.trim()){E.default.debug("[components:phone-format] Skipping prefill - already prefilled or has value");return}try{if(E.default.debug("[components:phone-format] Focus handler triggered, format:",t,"region:",r),t.toUpperCase()!=="INTERNATIONAL"){E.default.debug("[components:phone-format] Format is not INTERNATIONAL, skipping prefill");return}if(!r){E.default.debug("[components:phone-format] No region specified, skipping prefill");return}E.default.debug("[components:phone-format] Loading phone library...");let o=await Ve();if(!o){E.default.warn("[components:phone-format] Phone library not available");return}if(e.value.trim()){E.default.debug("[components:phone-format] Field now has value, skipping prefill");return}E.default.debug("[components:phone-format] Getting calling code for region:",r);let s=o(r);E.default.debug("[components:phone-format] Calling code:",s),s?(e.value="+"+s+" ",i(!0),E.default.debug("[components:phone-format] Prefilled country code:",e.value),e.setSelectionRange(e.value.length,e.value.length)):E.default.warn("[components:phone-format] Could not get calling code for region:",r)}catch(o){E.default.error("[components:phone-format] Failed to prefill country code:",o)}}async function zn(e,t,r,n){try{if(!r){let a=await St(t);if(!a)return;n(a),r=a}let i=e.selectionStart||0,o=e.value;r.reset();let s=r.input(o);if(s!==o){e.value=s;let a=s.length-o.length,u=Math.max(0,Math.min(i+a,s.length));e.setSelectionRange(u,u)}}catch(i){E.default.warn("[components:phone-format] Failed to auto-format phone number:",i)}}async function Vn(e,t,r){try{let n=e.value.trim();if(!n)return;let i=await ne();if(!i)return;let o=i(n);if(!o&&r&&(o=i(n,r)),o&&o.isValid&&o.isValid()){let s=jn(o,t,n);e.value=s}}catch(n){E.default.warn("[components:phone-format] Failed to format phone number on blur:",n)}}function jn(e,t,r){switch(t.toUpperCase()){case"E164":return e.format?e.format("E.164"):r;case"NATIONAL":return e.formatNational?e.formatNational():r;case"INTERNATIONAL":default:if(e.formatInternational){let n=e.formatInternational();if(r.replace(/\s/g,"")===n.replace(/\s/g,""))return n}return r}}function xt(e){Ce(e),He(e),Lt.default.debug("[components] Initialized")}var Pt=x(L(),1);function It(e){w.subscribe(()=>Mt()),Mt(),Pt.default.debug("[progress] Initialized")}function Mt(){if(typeof document>"u")return;let{current:e}=w.get(),t=Array.from(document.querySelectorAll("[as-step]")),r=t.length,n=t.findIndex(i=>i.getAttribute("as-step")===e);document.querySelectorAll('[as-progress="bar"]').forEach(i=>{let o=i.querySelector(".as-progress-bar");o||(o=document.createElement("div"),o.className="as-progress-bar",i.appendChild(o)),o.style.width=`${(n+1)/r*100}%`}),document.querySelectorAll('[as-progress="fraction"]').forEach(i=>{i.textContent=`${n+1} / ${r}`}),document.querySelectorAll('[as-progress="steps"]').forEach(i=>{i.innerHTML=t.map((o,s)=>`<span class="as-step-dot ${s<n?"completed":s===n?"current":"pending"}"></span>`).join("")})}var O=x(L(),1);function Ht(e){if(!e.hasAttribute("as-quiz")){O.default.debug("[quiz] Quiz mode not enabled");return}O.default.info("[quiz] Initializing quiz mode"),Rt(e),Un(e),Ct(),h.subscribe(()=>{Ct()}),O.default.debug("[quiz] Quiz mode initialized")}function Un(e){e.querySelectorAll("input, select, textarea").forEach(r=>{r.addEventListener("change",()=>{O.default.debug("[quiz] Answer changed, recalculating scores"),Rt(e)})})}function Rt(e){let t={};Tt(e,"as-weight").forEach(({attrElement:a,input:u})=>{let l=a.getAttribute("as-weight");if(l)try{let f=JSON.parse(l);if(Bn(u))for(let[c,g]of Object.entries(f))typeof g=="number"&&g>0&&(t[c]=(t[c]||0)+g)}catch(f){O.default.warn("[quiz] Invalid as-weight JSON:",a,f)}}),e.querySelectorAll("option[as-weight]:checked").forEach(a=>{let u=a.getAttribute("as-weight");if(u)try{let l=JSON.parse(u);for(let[f,m]of Object.entries(l))typeof m=="number"&&m>0&&(t[f]=(t[f]||0)+m)}catch(l){O.default.warn("[quiz] Invalid as-weight JSON on option:",a,l)}});let i=Wn(t),o=h.get(),s={...o.answers,__quiz__:i};h.set({...o,quiz:i,answers:s}),O.default.debug("[quiz] Scores updated:",i)}function Bn(e){return e instanceof HTMLInputElement&&e.type==="radio"||e instanceof HTMLInputElement&&e.type==="checkbox"?e.checked:e instanceof HTMLInputElement&&e.hasAttribute("as-radio-other-input")?_n(e)?.checked===!0&&e.value.trim()!=="":e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement?e.value.trim()!=="":e instanceof HTMLSelectElement?e.value!=="":!1}function _n(e){let t=e.getAttribute("as-radio-other-input"),r=e.closest("[as-step]")||document;if(t&&t!==""&&t!=="true"){let i=Array.from(r.querySelectorAll('input[type="radio"]')).filter(o=>o.name.toLowerCase()===t.toLowerCase());return i.find(o=>o.checked)||i[i.length-1]||null}let n=e.parentElement;for(;n&&n!==r;){let i=n.querySelector('input[type="radio"]');if(i)return i;n=n.parentElement}return null}function Wn(e){let t=Object.keys(e);if(t.length===0)return{scores:{},winner:null,winnerScore:0,ties:[]};let r=Math.max(...Object.values(e)),n=t.filter(i=>e[i]===r);return n.length===1?{scores:e,winner:n[0],winnerScore:r,ties:[]}:{scores:e,winner:n[0],winnerScore:r,ties:n}}function Ct(){let t=h.get().quiz;t&&(document.querySelectorAll("[as-quiz-category]").forEach(r=>{let n=r.getAttribute("as-quiz-category");!n||n===""||n==="true"?r.textContent=t.winner||"":r.textContent=t.winner===n?n:""}),document.querySelectorAll("[as-quiz-score]").forEach(r=>{let n=r.getAttribute("as-quiz-score");if(!n||n===""||n==="true")r.textContent=String(t.winnerScore);else if(n==="all")r.textContent=JSON.stringify(t.scores);else{let i=t.scores[n]||0;r.textContent=String(i)}}))}function ce(){return h.get().quiz||null}function kt(){return ce()?.scores||{}}function Dt(){return ce()?.winner||null}var Y=x(L(),1),B=null,Nt=!1;function Qn(){if(typeof document>"u"||document.getElementById("as-pre-css"))return;let e=document.createElement("style");e.id="as-pre-css",e.textContent='[as-step]~[as-step]{display:none!important;}[as-error-for]:not([data-as-error-active="true"]){display:none;}';let t=document.head||document.getElementsByTagName("head")[0]||document.documentElement;t.insertBefore(e,t.firstChild),Y.default.debug("[prehide] Injected pre-CSS to hide non-first steps")}function qt(){if(typeof document>"u")return;Qn();function e(r,n){let i=r;n!==0&&(i.style.display="none",i.setAttribute("aria-hidden","true"),i.setAttribute("inert",""))}let t=document.querySelectorAll("[as-step]");t.forEach((r,n)=>e(r,n)),t.length>0&&Y.default.debug(`[prehide] Hidden ${t.length-1} non-first steps before paint`),!B&&typeof MutationObserver<"u"&&(B=new MutationObserver(r=>{if(!Nt)for(let n of r)n.addedNodes.forEach(i=>{if(i.nodeType===Node.ELEMENT_NODE){let o=i;o.hasAttribute("as-step")&&e(o,1),o.querySelectorAll("[as-step]").forEach(s=>e(s,1))}})}),B.observe(document.documentElement,{childList:!0,subtree:!0}))}function Ft(){Nt=!0,B&&(B.disconnect(),B=null,Y.default.debug("[prehide] Observer stopped"));let e=document.getElementById("as-pre-css");e&&(e.remove(),Y.default.debug("[prehide] Removed pre-CSS, inline styles now control visibility"))}var Ot=x(L(),1);function $t(){if(typeof document>"u"||document.getElementById("as-runtime-css"))return;let e=document.createElement("style");e.id="as-runtime-css",e.textContent=`
|
|
1
|
+
"use strict";
|
|
2
|
+
var AgeraSurvey = (() => {
|
|
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 __commonJS = (cb, mod) => function __require() {
|
|
10
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
11
|
+
};
|
|
12
|
+
var __export = (target, all) => {
|
|
13
|
+
for (var name in all)
|
|
14
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
15
|
+
};
|
|
16
|
+
var __copyProps = (to, from, except, desc) => {
|
|
17
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
18
|
+
for (let key of __getOwnPropNames(from))
|
|
19
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
20
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
21
|
+
}
|
|
22
|
+
return to;
|
|
23
|
+
};
|
|
24
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
25
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
26
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
27
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
28
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
29
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
30
|
+
mod
|
|
31
|
+
));
|
|
32
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
33
|
+
|
|
34
|
+
// ../../node_modules/.pnpm/loglevel@1.9.2/node_modules/loglevel/lib/loglevel.js
|
|
35
|
+
var require_loglevel = __commonJS({
|
|
36
|
+
"../../node_modules/.pnpm/loglevel@1.9.2/node_modules/loglevel/lib/loglevel.js"(exports, module) {
|
|
37
|
+
"use strict";
|
|
38
|
+
(function(root, definition) {
|
|
39
|
+
"use strict";
|
|
40
|
+
if (typeof define === "function" && define.amd) {
|
|
41
|
+
define(definition);
|
|
42
|
+
} else if (typeof module === "object" && module.exports) {
|
|
43
|
+
module.exports = definition();
|
|
44
|
+
} else {
|
|
45
|
+
root.log = definition();
|
|
46
|
+
}
|
|
47
|
+
})(exports, function() {
|
|
48
|
+
"use strict";
|
|
49
|
+
var noop = function() {
|
|
50
|
+
};
|
|
51
|
+
var undefinedType = "undefined";
|
|
52
|
+
var isIE = typeof window !== undefinedType && typeof window.navigator !== undefinedType && /Trident\/|MSIE /.test(window.navigator.userAgent);
|
|
53
|
+
var logMethods = [
|
|
54
|
+
"trace",
|
|
55
|
+
"debug",
|
|
56
|
+
"info",
|
|
57
|
+
"warn",
|
|
58
|
+
"error"
|
|
59
|
+
];
|
|
60
|
+
var _loggersByName = {};
|
|
61
|
+
var defaultLogger = null;
|
|
62
|
+
function bindMethod(obj, methodName) {
|
|
63
|
+
var method = obj[methodName];
|
|
64
|
+
if (typeof method.bind === "function") {
|
|
65
|
+
return method.bind(obj);
|
|
66
|
+
} else {
|
|
67
|
+
try {
|
|
68
|
+
return Function.prototype.bind.call(method, obj);
|
|
69
|
+
} catch (e) {
|
|
70
|
+
return function() {
|
|
71
|
+
return Function.prototype.apply.apply(method, [obj, arguments]);
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
function traceForIE() {
|
|
77
|
+
if (console.log) {
|
|
78
|
+
if (console.log.apply) {
|
|
79
|
+
console.log.apply(console, arguments);
|
|
80
|
+
} else {
|
|
81
|
+
Function.prototype.apply.apply(console.log, [console, arguments]);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
if (console.trace) console.trace();
|
|
85
|
+
}
|
|
86
|
+
function realMethod(methodName) {
|
|
87
|
+
if (methodName === "debug") {
|
|
88
|
+
methodName = "log";
|
|
89
|
+
}
|
|
90
|
+
if (typeof console === undefinedType) {
|
|
91
|
+
return false;
|
|
92
|
+
} else if (methodName === "trace" && isIE) {
|
|
93
|
+
return traceForIE;
|
|
94
|
+
} else if (console[methodName] !== void 0) {
|
|
95
|
+
return bindMethod(console, methodName);
|
|
96
|
+
} else if (console.log !== void 0) {
|
|
97
|
+
return bindMethod(console, "log");
|
|
98
|
+
} else {
|
|
99
|
+
return noop;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
function replaceLoggingMethods() {
|
|
103
|
+
var level = this.getLevel();
|
|
104
|
+
for (var i = 0; i < logMethods.length; i++) {
|
|
105
|
+
var methodName = logMethods[i];
|
|
106
|
+
this[methodName] = i < level ? noop : this.methodFactory(methodName, level, this.name);
|
|
107
|
+
}
|
|
108
|
+
this.log = this.debug;
|
|
109
|
+
if (typeof console === undefinedType && level < this.levels.SILENT) {
|
|
110
|
+
return "No console available for logging";
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
function enableLoggingWhenConsoleArrives(methodName) {
|
|
114
|
+
return function() {
|
|
115
|
+
if (typeof console !== undefinedType) {
|
|
116
|
+
replaceLoggingMethods.call(this);
|
|
117
|
+
this[methodName].apply(this, arguments);
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
function defaultMethodFactory(methodName, _level, _loggerName) {
|
|
122
|
+
return realMethod(methodName) || enableLoggingWhenConsoleArrives.apply(this, arguments);
|
|
123
|
+
}
|
|
124
|
+
function Logger(name, factory) {
|
|
125
|
+
var self = this;
|
|
126
|
+
var inheritedLevel;
|
|
127
|
+
var defaultLevel;
|
|
128
|
+
var userLevel;
|
|
129
|
+
var storageKey = "loglevel";
|
|
130
|
+
if (typeof name === "string") {
|
|
131
|
+
storageKey += ":" + name;
|
|
132
|
+
} else if (typeof name === "symbol") {
|
|
133
|
+
storageKey = void 0;
|
|
134
|
+
}
|
|
135
|
+
function persistLevelIfPossible(levelNum) {
|
|
136
|
+
var levelName = (logMethods[levelNum] || "silent").toUpperCase();
|
|
137
|
+
if (typeof window === undefinedType || !storageKey) return;
|
|
138
|
+
try {
|
|
139
|
+
window.localStorage[storageKey] = levelName;
|
|
140
|
+
return;
|
|
141
|
+
} catch (ignore) {
|
|
142
|
+
}
|
|
143
|
+
try {
|
|
144
|
+
window.document.cookie = encodeURIComponent(storageKey) + "=" + levelName + ";";
|
|
145
|
+
} catch (ignore) {
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
function getPersistedLevel() {
|
|
149
|
+
var storedLevel;
|
|
150
|
+
if (typeof window === undefinedType || !storageKey) return;
|
|
151
|
+
try {
|
|
152
|
+
storedLevel = window.localStorage[storageKey];
|
|
153
|
+
} catch (ignore) {
|
|
154
|
+
}
|
|
155
|
+
if (typeof storedLevel === undefinedType) {
|
|
156
|
+
try {
|
|
157
|
+
var cookie = window.document.cookie;
|
|
158
|
+
var cookieName = encodeURIComponent(storageKey);
|
|
159
|
+
var location = cookie.indexOf(cookieName + "=");
|
|
160
|
+
if (location !== -1) {
|
|
161
|
+
storedLevel = /^([^;]+)/.exec(
|
|
162
|
+
cookie.slice(location + cookieName.length + 1)
|
|
163
|
+
)[1];
|
|
164
|
+
}
|
|
165
|
+
} catch (ignore) {
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
if (self.levels[storedLevel] === void 0) {
|
|
169
|
+
storedLevel = void 0;
|
|
170
|
+
}
|
|
171
|
+
return storedLevel;
|
|
172
|
+
}
|
|
173
|
+
function clearPersistedLevel() {
|
|
174
|
+
if (typeof window === undefinedType || !storageKey) return;
|
|
175
|
+
try {
|
|
176
|
+
window.localStorage.removeItem(storageKey);
|
|
177
|
+
} catch (ignore) {
|
|
178
|
+
}
|
|
179
|
+
try {
|
|
180
|
+
window.document.cookie = encodeURIComponent(storageKey) + "=; expires=Thu, 01 Jan 1970 00:00:00 UTC";
|
|
181
|
+
} catch (ignore) {
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
function normalizeLevel(input) {
|
|
185
|
+
var level = input;
|
|
186
|
+
if (typeof level === "string" && self.levels[level.toUpperCase()] !== void 0) {
|
|
187
|
+
level = self.levels[level.toUpperCase()];
|
|
188
|
+
}
|
|
189
|
+
if (typeof level === "number" && level >= 0 && level <= self.levels.SILENT) {
|
|
190
|
+
return level;
|
|
191
|
+
} else {
|
|
192
|
+
throw new TypeError("log.setLevel() called with invalid level: " + input);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
self.name = name;
|
|
196
|
+
self.levels = {
|
|
197
|
+
"TRACE": 0,
|
|
198
|
+
"DEBUG": 1,
|
|
199
|
+
"INFO": 2,
|
|
200
|
+
"WARN": 3,
|
|
201
|
+
"ERROR": 4,
|
|
202
|
+
"SILENT": 5
|
|
203
|
+
};
|
|
204
|
+
self.methodFactory = factory || defaultMethodFactory;
|
|
205
|
+
self.getLevel = function() {
|
|
206
|
+
if (userLevel != null) {
|
|
207
|
+
return userLevel;
|
|
208
|
+
} else if (defaultLevel != null) {
|
|
209
|
+
return defaultLevel;
|
|
210
|
+
} else {
|
|
211
|
+
return inheritedLevel;
|
|
212
|
+
}
|
|
213
|
+
};
|
|
214
|
+
self.setLevel = function(level, persist) {
|
|
215
|
+
userLevel = normalizeLevel(level);
|
|
216
|
+
if (persist !== false) {
|
|
217
|
+
persistLevelIfPossible(userLevel);
|
|
218
|
+
}
|
|
219
|
+
return replaceLoggingMethods.call(self);
|
|
220
|
+
};
|
|
221
|
+
self.setDefaultLevel = function(level) {
|
|
222
|
+
defaultLevel = normalizeLevel(level);
|
|
223
|
+
if (!getPersistedLevel()) {
|
|
224
|
+
self.setLevel(level, false);
|
|
225
|
+
}
|
|
226
|
+
};
|
|
227
|
+
self.resetLevel = function() {
|
|
228
|
+
userLevel = null;
|
|
229
|
+
clearPersistedLevel();
|
|
230
|
+
replaceLoggingMethods.call(self);
|
|
231
|
+
};
|
|
232
|
+
self.enableAll = function(persist) {
|
|
233
|
+
self.setLevel(self.levels.TRACE, persist);
|
|
234
|
+
};
|
|
235
|
+
self.disableAll = function(persist) {
|
|
236
|
+
self.setLevel(self.levels.SILENT, persist);
|
|
237
|
+
};
|
|
238
|
+
self.rebuild = function() {
|
|
239
|
+
if (defaultLogger !== self) {
|
|
240
|
+
inheritedLevel = normalizeLevel(defaultLogger.getLevel());
|
|
241
|
+
}
|
|
242
|
+
replaceLoggingMethods.call(self);
|
|
243
|
+
if (defaultLogger === self) {
|
|
244
|
+
for (var childName in _loggersByName) {
|
|
245
|
+
_loggersByName[childName].rebuild();
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
};
|
|
249
|
+
inheritedLevel = normalizeLevel(
|
|
250
|
+
defaultLogger ? defaultLogger.getLevel() : "WARN"
|
|
251
|
+
);
|
|
252
|
+
var initialLevel = getPersistedLevel();
|
|
253
|
+
if (initialLevel != null) {
|
|
254
|
+
userLevel = normalizeLevel(initialLevel);
|
|
255
|
+
}
|
|
256
|
+
replaceLoggingMethods.call(self);
|
|
257
|
+
}
|
|
258
|
+
defaultLogger = new Logger();
|
|
259
|
+
defaultLogger.getLogger = function getLogger(name) {
|
|
260
|
+
if (typeof name !== "symbol" && typeof name !== "string" || name === "") {
|
|
261
|
+
throw new TypeError("You must supply a name when creating a logger.");
|
|
262
|
+
}
|
|
263
|
+
var logger = _loggersByName[name];
|
|
264
|
+
if (!logger) {
|
|
265
|
+
logger = _loggersByName[name] = new Logger(
|
|
266
|
+
name,
|
|
267
|
+
defaultLogger.methodFactory
|
|
268
|
+
);
|
|
269
|
+
}
|
|
270
|
+
return logger;
|
|
271
|
+
};
|
|
272
|
+
var _log = typeof window !== undefinedType ? window.log : void 0;
|
|
273
|
+
defaultLogger.noConflict = function() {
|
|
274
|
+
if (typeof window !== undefinedType && window.log === defaultLogger) {
|
|
275
|
+
window.log = _log;
|
|
276
|
+
}
|
|
277
|
+
return defaultLogger;
|
|
278
|
+
};
|
|
279
|
+
defaultLogger.getLoggers = function getLoggers() {
|
|
280
|
+
return _loggersByName;
|
|
281
|
+
};
|
|
282
|
+
defaultLogger["default"] = defaultLogger;
|
|
283
|
+
return defaultLogger;
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
// src/index.ts
|
|
289
|
+
var index_exports = {};
|
|
290
|
+
__export(index_exports, {
|
|
291
|
+
init: () => init
|
|
292
|
+
});
|
|
293
|
+
var import_loglevel14 = __toESM(require_loglevel(), 1);
|
|
294
|
+
|
|
295
|
+
// package.json
|
|
296
|
+
var package_default = {
|
|
297
|
+
name: "@reform-society/agera-survey",
|
|
298
|
+
version: "0.1.0",
|
|
299
|
+
description: "Multi-step survey runtime for Webflow",
|
|
300
|
+
type: "module",
|
|
301
|
+
main: "dist/index.global.js",
|
|
302
|
+
types: "dist/index.d.ts",
|
|
303
|
+
files: [
|
|
304
|
+
"dist"
|
|
305
|
+
],
|
|
306
|
+
repository: {
|
|
307
|
+
type: "git",
|
|
308
|
+
url: "git+https://github.com/reform-society/agera-survey-app.git",
|
|
309
|
+
directory: "packages/agera-survey"
|
|
310
|
+
},
|
|
311
|
+
author: "Reform Society",
|
|
312
|
+
license: "UNLICENSED",
|
|
313
|
+
private: false,
|
|
314
|
+
publishConfig: {
|
|
315
|
+
access: "public",
|
|
316
|
+
provenance: true
|
|
317
|
+
},
|
|
318
|
+
scripts: {
|
|
319
|
+
dev: "tsup src/index.ts --format iife --global-name AgeraSurvey --watch --out-dir dist --sourcemap",
|
|
320
|
+
build: "tsup src/index.ts --format iife --global-name AgeraSurvey --out-dir dist --minify",
|
|
321
|
+
"build:analyze": "tsup src/index.ts --format iife --global-name AgeraSurvey --out-dir dist --minify --metafile",
|
|
322
|
+
lint: "eslint src",
|
|
323
|
+
typecheck: "tsc --noEmit",
|
|
324
|
+
check: "pnpm lint; pnpm typecheck"
|
|
325
|
+
},
|
|
326
|
+
devDependencies: {
|
|
327
|
+
"@agera/config": "workspace:*",
|
|
328
|
+
loglevel: "^1.9.2",
|
|
329
|
+
nanostores: "^0.11.3",
|
|
330
|
+
"libphonenumber-js": "1.12.25",
|
|
331
|
+
tsup: "^8.5.1",
|
|
332
|
+
typescript: "^5.7.2"
|
|
333
|
+
}
|
|
334
|
+
};
|
|
335
|
+
|
|
336
|
+
// ../agera-config/src/index.ts
|
|
337
|
+
var RUNTIME_VERSION = package_default.version;
|
|
338
|
+
var IS_PRODUCTION_BUILD = typeof __BUILD_MODE__ !== "undefined" && __BUILD_MODE__ === "production";
|
|
339
|
+
|
|
340
|
+
// src/features/steps.ts
|
|
341
|
+
var import_loglevel6 = __toESM(require_loglevel(), 1);
|
|
342
|
+
|
|
343
|
+
// ../../node_modules/.pnpm/nanostores@0.11.4/node_modules/nanostores/atom/index.js
|
|
344
|
+
var listenerQueue = [];
|
|
345
|
+
var lqIndex = 0;
|
|
346
|
+
var QUEUE_ITEMS_PER_LISTENER = 4;
|
|
347
|
+
var epoch = 0;
|
|
348
|
+
var atom = (initialValue) => {
|
|
349
|
+
let listeners = [];
|
|
350
|
+
let $atom = {
|
|
351
|
+
get() {
|
|
352
|
+
if (!$atom.lc) {
|
|
353
|
+
$atom.listen(() => {
|
|
354
|
+
})();
|
|
355
|
+
}
|
|
356
|
+
return $atom.value;
|
|
357
|
+
},
|
|
358
|
+
lc: 0,
|
|
359
|
+
listen(listener) {
|
|
360
|
+
$atom.lc = listeners.push(listener);
|
|
361
|
+
return () => {
|
|
362
|
+
for (let i = lqIndex + QUEUE_ITEMS_PER_LISTENER; i < listenerQueue.length; ) {
|
|
363
|
+
if (listenerQueue[i] === listener) {
|
|
364
|
+
listenerQueue.splice(i, QUEUE_ITEMS_PER_LISTENER);
|
|
365
|
+
} else {
|
|
366
|
+
i += QUEUE_ITEMS_PER_LISTENER;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
let index = listeners.indexOf(listener);
|
|
370
|
+
if (~index) {
|
|
371
|
+
listeners.splice(index, 1);
|
|
372
|
+
if (!--$atom.lc) $atom.off();
|
|
373
|
+
}
|
|
374
|
+
};
|
|
375
|
+
},
|
|
376
|
+
notify(oldValue, changedKey) {
|
|
377
|
+
epoch++;
|
|
378
|
+
let runListenerQueue = !listenerQueue.length;
|
|
379
|
+
for (let listener of listeners) {
|
|
380
|
+
listenerQueue.push(
|
|
381
|
+
listener,
|
|
382
|
+
$atom.value,
|
|
383
|
+
oldValue,
|
|
384
|
+
changedKey
|
|
385
|
+
);
|
|
386
|
+
}
|
|
387
|
+
if (runListenerQueue) {
|
|
388
|
+
for (lqIndex = 0; lqIndex < listenerQueue.length; lqIndex += QUEUE_ITEMS_PER_LISTENER) {
|
|
389
|
+
listenerQueue[lqIndex](
|
|
390
|
+
listenerQueue[lqIndex + 1],
|
|
391
|
+
listenerQueue[lqIndex + 2],
|
|
392
|
+
listenerQueue[lqIndex + 3]
|
|
393
|
+
);
|
|
394
|
+
}
|
|
395
|
+
listenerQueue.length = 0;
|
|
396
|
+
}
|
|
397
|
+
},
|
|
398
|
+
/* It will be called on last listener unsubscribing.
|
|
399
|
+
We will redefine it in onMount and onStop. */
|
|
400
|
+
off() {
|
|
401
|
+
},
|
|
402
|
+
set(newValue) {
|
|
403
|
+
let oldValue = $atom.value;
|
|
404
|
+
if (oldValue !== newValue) {
|
|
405
|
+
$atom.value = newValue;
|
|
406
|
+
$atom.notify(oldValue);
|
|
407
|
+
}
|
|
408
|
+
},
|
|
409
|
+
subscribe(listener) {
|
|
410
|
+
let unbind = $atom.listen(listener);
|
|
411
|
+
listener($atom.value);
|
|
412
|
+
return unbind;
|
|
413
|
+
},
|
|
414
|
+
value: initialValue
|
|
415
|
+
};
|
|
416
|
+
if (false) {
|
|
417
|
+
$atom[clean] = () => {
|
|
418
|
+
listeners = [];
|
|
419
|
+
$atom.lc = 0;
|
|
420
|
+
$atom.off();
|
|
421
|
+
};
|
|
422
|
+
}
|
|
423
|
+
return $atom;
|
|
424
|
+
};
|
|
425
|
+
|
|
426
|
+
// src/core/stores.ts
|
|
427
|
+
var sessionStore = atom({
|
|
428
|
+
id: typeof crypto !== "undefined" && "randomUUID" in crypto ? crypto.randomUUID() : `${Date.now()}`,
|
|
429
|
+
answers: {},
|
|
430
|
+
startedAt: /* @__PURE__ */ new Date()
|
|
431
|
+
});
|
|
432
|
+
var stepsStore = atom({
|
|
433
|
+
current: "",
|
|
434
|
+
path: []
|
|
435
|
+
});
|
|
436
|
+
function persistSession() {
|
|
437
|
+
if (typeof window === "undefined") return;
|
|
438
|
+
const stored = window.localStorage.getItem("as:session");
|
|
439
|
+
if (stored) {
|
|
440
|
+
try {
|
|
441
|
+
const parsed = JSON.parse(stored);
|
|
442
|
+
sessionStore.set({
|
|
443
|
+
...parsed,
|
|
444
|
+
startedAt: new Date(parsed.startedAt)
|
|
445
|
+
});
|
|
446
|
+
} catch {
|
|
447
|
+
window.localStorage.removeItem("as:session");
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
sessionStore.subscribe((state) => {
|
|
451
|
+
try {
|
|
452
|
+
window.localStorage.setItem("as:session", JSON.stringify(state));
|
|
453
|
+
} catch {
|
|
454
|
+
}
|
|
455
|
+
});
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
// src/features/validation.ts
|
|
459
|
+
var import_loglevel3 = __toESM(require_loglevel(), 1);
|
|
460
|
+
|
|
461
|
+
// src/features/utils/phone-lib.ts
|
|
462
|
+
var import_loglevel = __toESM(require_loglevel(), 1);
|
|
463
|
+
var CDN_URL_PRIMARY = "https://cdn.jsdelivr.net/npm/libphonenumber-js@1.12.25/max/index.js";
|
|
464
|
+
var CDN_URL_FALLBACK = "https://unpkg.com/libphonenumber-js@1.12.25/max/index.js";
|
|
465
|
+
var phoneLibCache = null;
|
|
466
|
+
var loadingPromise = null;
|
|
467
|
+
async function loadPhoneLib() {
|
|
468
|
+
if (phoneLibCache) {
|
|
469
|
+
return phoneLibCache;
|
|
470
|
+
}
|
|
471
|
+
if (loadingPromise) {
|
|
472
|
+
return loadingPromise;
|
|
473
|
+
}
|
|
474
|
+
loadingPromise = (async () => {
|
|
475
|
+
const urls = [CDN_URL_PRIMARY, CDN_URL_FALLBACK];
|
|
476
|
+
let lastError = null;
|
|
477
|
+
for (const url of urls) {
|
|
478
|
+
try {
|
|
479
|
+
const module = await import(
|
|
480
|
+
/* @vite-ignore */
|
|
481
|
+
url
|
|
482
|
+
);
|
|
483
|
+
const moduleExports = module;
|
|
484
|
+
const parsePhoneNumberFromString = moduleExports.parsePhoneNumberFromString || moduleExports.default?.parsePhoneNumberFromString || moduleExports.default;
|
|
485
|
+
const AsYouType = moduleExports.AsYouType || moduleExports.default?.AsYouType;
|
|
486
|
+
const getCountryCallingCode = moduleExports.getCountryCallingCode || moduleExports.default?.getCountryCallingCode;
|
|
487
|
+
if (!parsePhoneNumberFromString || typeof parsePhoneNumberFromString !== "function") {
|
|
488
|
+
throw new Error("parsePhoneNumberFromString not found in module");
|
|
489
|
+
}
|
|
490
|
+
if (!AsYouType || typeof AsYouType !== "function") {
|
|
491
|
+
throw new Error("AsYouType not found in module");
|
|
492
|
+
}
|
|
493
|
+
if (!getCountryCallingCode || typeof getCountryCallingCode !== "function") {
|
|
494
|
+
throw new Error("getCountryCallingCode not found in module");
|
|
495
|
+
}
|
|
496
|
+
phoneLibCache = { parsePhoneNumberFromString, AsYouType, getCountryCallingCode };
|
|
497
|
+
return phoneLibCache;
|
|
498
|
+
} catch (error2) {
|
|
499
|
+
lastError = error2 instanceof Error ? error2 : new Error(String(error2));
|
|
500
|
+
import_loglevel.default.warn(`[phone-lib] Failed to load from ${url}, trying fallback...`, lastError);
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
const error = new Error(
|
|
504
|
+
`Failed to load libphonenumber-js from all CDN URLs. Last error: ${lastError?.message}`
|
|
505
|
+
);
|
|
506
|
+
import_loglevel.default.error("[phone-lib] Failed to load libphonenumber-js from all CDNs:", error);
|
|
507
|
+
loadingPromise = null;
|
|
508
|
+
throw error;
|
|
509
|
+
})();
|
|
510
|
+
return loadingPromise;
|
|
511
|
+
}
|
|
512
|
+
async function getParsePhoneNumberFromString() {
|
|
513
|
+
try {
|
|
514
|
+
const lib = await loadPhoneLib();
|
|
515
|
+
return lib?.parsePhoneNumberFromString ?? null;
|
|
516
|
+
} catch {
|
|
517
|
+
return null;
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
async function getAsYouType() {
|
|
521
|
+
try {
|
|
522
|
+
const lib = await loadPhoneLib();
|
|
523
|
+
return lib?.AsYouType ?? null;
|
|
524
|
+
} catch {
|
|
525
|
+
return null;
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
async function getGetCountryCallingCode() {
|
|
529
|
+
try {
|
|
530
|
+
const lib = await loadPhoneLib();
|
|
531
|
+
return lib?.getCountryCallingCode ?? null;
|
|
532
|
+
} catch {
|
|
533
|
+
return null;
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
// src/features/validation-messages.ts
|
|
538
|
+
var errorMessages = {
|
|
539
|
+
// Swedish (Sweden)
|
|
540
|
+
"sv-SE": {
|
|
541
|
+
required: "Detta f\xE4lt \xE4r obligatoriskt",
|
|
542
|
+
email: "V\xE4nligen ange en giltig e-postadress",
|
|
543
|
+
phone: "V\xE4nligen ange ett giltigt telefonnummer",
|
|
544
|
+
pattern: "Ogiltigt format",
|
|
545
|
+
min: "F\xF6r kort",
|
|
546
|
+
max: "F\xF6r l\xE5ngt"
|
|
547
|
+
},
|
|
548
|
+
// Norwegian Bokmål (Norway)
|
|
549
|
+
"nb-NO": {
|
|
550
|
+
required: "Dette feltet er obligatorisk",
|
|
551
|
+
email: "Vennligst oppgi en gyldig e-postadresse",
|
|
552
|
+
phone: "Vennligst oppgi et gyldig telefonnummer",
|
|
553
|
+
pattern: "Ugyldig format",
|
|
554
|
+
min: "For kort",
|
|
555
|
+
max: "For lang"
|
|
556
|
+
},
|
|
557
|
+
// Norwegian (fallback)
|
|
558
|
+
no: {
|
|
559
|
+
required: "Dette feltet er obligatorisk",
|
|
560
|
+
email: "Vennligst oppgi en gyldig e-postadresse",
|
|
561
|
+
phone: "Vennligst oppgi et gyldig telefonnummer",
|
|
562
|
+
pattern: "Ugyldig format",
|
|
563
|
+
min: "For kort",
|
|
564
|
+
max: "For lang"
|
|
565
|
+
},
|
|
566
|
+
// Danish (Denmark)
|
|
567
|
+
"da-DK": {
|
|
568
|
+
required: "Dette felt er p\xE5kr\xE6vet",
|
|
569
|
+
email: "Indtast venligst en gyldig e-mailadresse",
|
|
570
|
+
phone: "Indtast venligst et gyldigt telefonnummer",
|
|
571
|
+
pattern: "Ugyldigt format",
|
|
572
|
+
min: "For kort",
|
|
573
|
+
max: "For lang"
|
|
574
|
+
},
|
|
575
|
+
// English (United States)
|
|
576
|
+
"en-US": {
|
|
577
|
+
required: "This field is required",
|
|
578
|
+
email: "Please enter a valid email",
|
|
579
|
+
phone: "Please enter a valid phone number",
|
|
580
|
+
pattern: "Invalid format",
|
|
581
|
+
min: "Too short",
|
|
582
|
+
max: "Too long"
|
|
583
|
+
},
|
|
584
|
+
// English (fallback)
|
|
585
|
+
en: {
|
|
586
|
+
required: "This field is required",
|
|
587
|
+
email: "Please enter a valid email",
|
|
588
|
+
phone: "Please enter a valid phone number",
|
|
589
|
+
pattern: "Invalid format",
|
|
590
|
+
min: "Too short",
|
|
591
|
+
max: "Too long"
|
|
592
|
+
},
|
|
593
|
+
// German (Germany)
|
|
594
|
+
"de-DE": {
|
|
595
|
+
required: "Dieses Feld ist erforderlich",
|
|
596
|
+
email: "Bitte geben Sie eine g\xFCltige E-Mail-Adresse ein",
|
|
597
|
+
phone: "Bitte geben Sie eine g\xFCltige Telefonnummer ein",
|
|
598
|
+
pattern: "Ung\xFCltiges Format",
|
|
599
|
+
min: "Zu kurz",
|
|
600
|
+
max: "Zu lang"
|
|
601
|
+
},
|
|
602
|
+
// Spanish (Spain)
|
|
603
|
+
"es-ES": {
|
|
604
|
+
required: "Este campo es obligatorio",
|
|
605
|
+
email: "Por favor, introduce un correo electr\xF3nico v\xE1lido",
|
|
606
|
+
phone: "Por favor, introduce un n\xFAmero de tel\xE9fono v\xE1lido",
|
|
607
|
+
pattern: "Formato no v\xE1lido",
|
|
608
|
+
min: "Demasiado corto",
|
|
609
|
+
max: "Demasiado largo"
|
|
610
|
+
},
|
|
611
|
+
// Finnish (Finland)
|
|
612
|
+
"fi-FI": {
|
|
613
|
+
required: "T\xE4m\xE4 kentt\xE4 on pakollinen",
|
|
614
|
+
email: "Anna kelvollinen s\xE4hk\xF6postiosoite",
|
|
615
|
+
phone: "Anna kelvollinen puhelinnumero",
|
|
616
|
+
pattern: "Virheellinen muoto",
|
|
617
|
+
min: "Liian lyhyt",
|
|
618
|
+
max: "Liian pitk\xE4"
|
|
619
|
+
},
|
|
620
|
+
// French (France)
|
|
621
|
+
"fr-FR": {
|
|
622
|
+
required: "Ce champ est obligatoire",
|
|
623
|
+
email: "Veuillez saisir une adresse e-mail valide",
|
|
624
|
+
phone: "Veuillez saisir un num\xE9ro de t\xE9l\xE9phone valide",
|
|
625
|
+
pattern: "Format invalide",
|
|
626
|
+
min: "Trop court",
|
|
627
|
+
max: "Trop long"
|
|
628
|
+
}
|
|
629
|
+
};
|
|
630
|
+
function getErrorMessagesForLanguage() {
|
|
631
|
+
const defaultMessages = errorMessages.en;
|
|
632
|
+
if (typeof document === "undefined") {
|
|
633
|
+
return defaultMessages;
|
|
634
|
+
}
|
|
635
|
+
const lang = document.documentElement.lang;
|
|
636
|
+
if (!lang) {
|
|
637
|
+
return defaultMessages;
|
|
638
|
+
}
|
|
639
|
+
const exactMatch = errorMessages[lang];
|
|
640
|
+
if (exactMatch) {
|
|
641
|
+
return exactMatch;
|
|
642
|
+
}
|
|
643
|
+
const prefix = lang.split("-")[0];
|
|
644
|
+
if (prefix) {
|
|
645
|
+
const prefixMatch = errorMessages[prefix];
|
|
646
|
+
if (prefixMatch) {
|
|
647
|
+
return prefixMatch;
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
return defaultMessages;
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
// src/features/conditions.ts
|
|
654
|
+
var import_loglevel2 = __toESM(require_loglevel(), 1);
|
|
655
|
+
|
|
656
|
+
// src/core/utils.ts
|
|
657
|
+
var PRESERVED_ANSWER_KEYS = /* @__PURE__ */ new Set(["__quiz__"]);
|
|
658
|
+
function getAnswersFromInputs(root) {
|
|
659
|
+
const answers = {};
|
|
660
|
+
const inputs = root.querySelectorAll(
|
|
661
|
+
"input, textarea, select"
|
|
662
|
+
);
|
|
663
|
+
inputs.forEach((input) => {
|
|
664
|
+
if (!input.name && !input.hasAttribute("as-element-id")) return;
|
|
665
|
+
const keys = [];
|
|
666
|
+
if (input.name) keys.push(input.name);
|
|
667
|
+
const logicId = input.getAttribute("as-element-id");
|
|
668
|
+
if (logicId) keys.push(logicId);
|
|
669
|
+
let value = input.value;
|
|
670
|
+
if (input instanceof HTMLInputElement && input.type === "checkbox") {
|
|
671
|
+
value = Boolean(input.checked);
|
|
672
|
+
} else if (input instanceof HTMLInputElement && input.type === "radio") {
|
|
673
|
+
if (!input.checked) return;
|
|
674
|
+
value = input.value;
|
|
675
|
+
}
|
|
676
|
+
keys.forEach((key) => {
|
|
677
|
+
answers[key] = value;
|
|
678
|
+
});
|
|
679
|
+
});
|
|
680
|
+
return answers;
|
|
681
|
+
}
|
|
682
|
+
function syncAnswersFromInputs(root) {
|
|
683
|
+
if (typeof document === "undefined") return;
|
|
684
|
+
if (!root) return;
|
|
685
|
+
const session = sessionStore.get();
|
|
686
|
+
const domAnswers = getAnswersFromInputs(root);
|
|
687
|
+
const mergedAnswers = mergeAnswers(session.answers, domAnswers);
|
|
688
|
+
if (answersChanged(session.answers, mergedAnswers)) {
|
|
689
|
+
sessionStore.set({ ...session, answers: mergedAnswers });
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
function mergeAnswers(previous, dom) {
|
|
693
|
+
const merged = { ...dom };
|
|
694
|
+
for (const [key, value] of Object.entries(previous)) {
|
|
695
|
+
if (!(key in merged) || PRESERVED_ANSWER_KEYS.has(key)) {
|
|
696
|
+
merged[key] = value;
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
return merged;
|
|
700
|
+
}
|
|
701
|
+
function answersChanged(previous, next) {
|
|
702
|
+
const prevKeys = Object.keys(previous);
|
|
703
|
+
const nextKeys = Object.keys(next);
|
|
704
|
+
if (prevKeys.length !== nextKeys.length) {
|
|
705
|
+
return true;
|
|
706
|
+
}
|
|
707
|
+
for (const key of nextKeys) {
|
|
708
|
+
if (previous[key] !== next[key]) {
|
|
709
|
+
return true;
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
return false;
|
|
713
|
+
}
|
|
714
|
+
function ensureAriaLiveRegion() {
|
|
715
|
+
if (typeof document === "undefined") {
|
|
716
|
+
return { style: {} };
|
|
717
|
+
}
|
|
718
|
+
let region = document.getElementById("as-aria-live");
|
|
719
|
+
if (!region) {
|
|
720
|
+
region = document.createElement("div");
|
|
721
|
+
region.id = "as-aria-live";
|
|
722
|
+
region.setAttribute("aria-live", "polite");
|
|
723
|
+
region.setAttribute("aria-atomic", "true");
|
|
724
|
+
const el = region;
|
|
725
|
+
el.style.position = "absolute";
|
|
726
|
+
el.style.left = "-10000px";
|
|
727
|
+
el.style.width = "1px";
|
|
728
|
+
el.style.height = "1px";
|
|
729
|
+
el.style.overflow = "hidden";
|
|
730
|
+
document.body.appendChild(region);
|
|
731
|
+
}
|
|
732
|
+
return region;
|
|
733
|
+
}
|
|
734
|
+
function resolveField(field, answers) {
|
|
735
|
+
if (field.startsWith("env.")) {
|
|
736
|
+
const path = field.slice(4).split(".");
|
|
737
|
+
if (path[0] === "utm" && path[1]) {
|
|
738
|
+
const params = new URLSearchParams(
|
|
739
|
+
typeof window !== "undefined" ? window.location.search : ""
|
|
740
|
+
);
|
|
741
|
+
return params.get(`utm_${path[1]}`);
|
|
742
|
+
}
|
|
743
|
+
if (path[0]) {
|
|
744
|
+
return answers[path[0]];
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
if (field.startsWith("quiz.")) {
|
|
748
|
+
const path = field.slice(5).split(".");
|
|
749
|
+
const quizResults = answers["__quiz__"];
|
|
750
|
+
if (!quizResults) return void 0;
|
|
751
|
+
if (path[0] === "winner") {
|
|
752
|
+
if (path.length === 1) {
|
|
753
|
+
return quizResults.winner;
|
|
754
|
+
}
|
|
755
|
+
if (path[1] === "score") {
|
|
756
|
+
return quizResults.winnerScore;
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
if (path[0] === "scores" && path[1]) {
|
|
760
|
+
const scores = quizResults.scores;
|
|
761
|
+
return scores?.[path[1]];
|
|
762
|
+
}
|
|
763
|
+
return void 0;
|
|
764
|
+
}
|
|
765
|
+
return answers[field];
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
// src/features/utils/transition-presets.ts
|
|
769
|
+
function resolvePreset(preset, direction) {
|
|
770
|
+
switch (preset) {
|
|
771
|
+
// Unified horizontal combos
|
|
772
|
+
case "slide-left-right":
|
|
773
|
+
return direction === "in" ? "slide-in-left" : "slide-out-right";
|
|
774
|
+
case "slide-right-left":
|
|
775
|
+
return direction === "in" ? "slide-in-right" : "slide-out-left";
|
|
776
|
+
// Unified vertical combos
|
|
777
|
+
case "slide-up-down":
|
|
778
|
+
return direction === "in" ? "slide-in-up" : "slide-out-down";
|
|
779
|
+
case "slide-down-up":
|
|
780
|
+
return direction === "in" ? "slide-in-down" : "slide-out-up";
|
|
781
|
+
// Unified scale
|
|
782
|
+
case "scale":
|
|
783
|
+
return direction === "in" ? "scale-in" : "scale-out";
|
|
784
|
+
// Unified fade
|
|
785
|
+
case "fade":
|
|
786
|
+
return "fade";
|
|
787
|
+
default:
|
|
788
|
+
return "fade";
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
function getPresetStyles(preset, distance, direction) {
|
|
792
|
+
const styles = {
|
|
793
|
+
initial: {},
|
|
794
|
+
target: {}
|
|
795
|
+
};
|
|
796
|
+
switch (preset) {
|
|
797
|
+
case "fade":
|
|
798
|
+
if (direction === "in") {
|
|
799
|
+
styles.initial = { opacity: "0" };
|
|
800
|
+
styles.target = { opacity: "1" };
|
|
801
|
+
} else {
|
|
802
|
+
styles.initial = { opacity: "1" };
|
|
803
|
+
styles.target = { opacity: "0" };
|
|
804
|
+
}
|
|
805
|
+
break;
|
|
806
|
+
case "slide-in-left":
|
|
807
|
+
styles.initial = { transform: `translateX(-${distance})`, opacity: "0" };
|
|
808
|
+
styles.target = { transform: "translateX(0)", opacity: "1" };
|
|
809
|
+
break;
|
|
810
|
+
case "slide-in-right":
|
|
811
|
+
styles.initial = { transform: `translateX(${distance})`, opacity: "0" };
|
|
812
|
+
styles.target = { transform: "translateX(0)", opacity: "1" };
|
|
813
|
+
break;
|
|
814
|
+
case "slide-in-up":
|
|
815
|
+
styles.initial = { transform: `translateY(-${distance})`, opacity: "0" };
|
|
816
|
+
styles.target = { transform: "translateY(0)", opacity: "1" };
|
|
817
|
+
break;
|
|
818
|
+
case "slide-in-down":
|
|
819
|
+
styles.initial = { transform: `translateY(${distance})`, opacity: "0" };
|
|
820
|
+
styles.target = { transform: "translateY(0)", opacity: "1" };
|
|
821
|
+
break;
|
|
822
|
+
case "slide-out-left":
|
|
823
|
+
styles.initial = { transform: "translateX(0)", opacity: "1" };
|
|
824
|
+
styles.target = { transform: `translateX(-${distance})`, opacity: "0" };
|
|
825
|
+
break;
|
|
826
|
+
case "slide-out-right":
|
|
827
|
+
styles.initial = { transform: "translateX(0)", opacity: "1" };
|
|
828
|
+
styles.target = { transform: `translateX(${distance})`, opacity: "0" };
|
|
829
|
+
break;
|
|
830
|
+
case "slide-out-up":
|
|
831
|
+
styles.initial = { transform: "translateY(0)", opacity: "1" };
|
|
832
|
+
styles.target = { transform: `translateY(-${distance})`, opacity: "0" };
|
|
833
|
+
break;
|
|
834
|
+
case "slide-out-down":
|
|
835
|
+
styles.initial = { transform: "translateY(0)", opacity: "1" };
|
|
836
|
+
styles.target = { transform: `translateY(${distance})`, opacity: "0" };
|
|
837
|
+
break;
|
|
838
|
+
case "scale-in":
|
|
839
|
+
styles.initial = { transform: "scale(0.98)", opacity: "0" };
|
|
840
|
+
styles.target = { transform: "scale(1)", opacity: "1" };
|
|
841
|
+
break;
|
|
842
|
+
case "scale-out":
|
|
843
|
+
styles.initial = { transform: "scale(1)", opacity: "1" };
|
|
844
|
+
styles.target = { transform: "scale(0.98)", opacity: "0" };
|
|
845
|
+
break;
|
|
846
|
+
}
|
|
847
|
+
return styles;
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
// src/features/utils/transitions.ts
|
|
851
|
+
function showWithTransition(el, options = {}) {
|
|
852
|
+
const {
|
|
853
|
+
defaultDuration = "300ms",
|
|
854
|
+
defaultDistance = "24px",
|
|
855
|
+
onComplete,
|
|
856
|
+
displayValue = ""
|
|
857
|
+
} = options;
|
|
858
|
+
const prefersReducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
859
|
+
el.style.display = displayValue;
|
|
860
|
+
el.removeAttribute("hidden");
|
|
861
|
+
el.removeAttribute("aria-hidden");
|
|
862
|
+
if (prefersReducedMotion) {
|
|
863
|
+
el.style.opacity = "1";
|
|
864
|
+
onComplete?.();
|
|
865
|
+
return;
|
|
866
|
+
}
|
|
867
|
+
const transitionInBase = el.getAttribute("as-transition-in") || el.getAttribute("as-transition") || "fade";
|
|
868
|
+
const transitionIn = resolvePreset(transitionInBase, "in");
|
|
869
|
+
const distance = el.getAttribute("as-transition-distance") || defaultDistance;
|
|
870
|
+
const speedIn = el.getAttribute("as-transition-speed-in") || el.getAttribute("as-transition-speed");
|
|
871
|
+
const preset = getPresetStyles(transitionIn, distance, "in");
|
|
872
|
+
const computed = window.getComputedStyle(el);
|
|
873
|
+
const hasTransitionDuration = computeMaxEndTime(computed.transitionDuration, computed.transitionDelay) > 0;
|
|
874
|
+
let appliedTransitionProperty = false;
|
|
875
|
+
const propStr = computed.transitionProperty || "";
|
|
876
|
+
const hasNeededProps = /(^|,|\s)(all|transform|opacity)(,|\s|$)/.test(propStr);
|
|
877
|
+
if (!hasNeededProps) {
|
|
878
|
+
el.style.transitionProperty = "opacity, transform";
|
|
879
|
+
appliedTransitionProperty = true;
|
|
880
|
+
}
|
|
881
|
+
if (!hasTransitionDuration && !speedIn) {
|
|
882
|
+
el.style.transitionDuration = defaultDuration;
|
|
883
|
+
if (!appliedTransitionProperty) {
|
|
884
|
+
el.style.transitionProperty = "opacity, transform";
|
|
885
|
+
appliedTransitionProperty = true;
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
if (speedIn) {
|
|
889
|
+
applySpeedOverride(el, speedIn);
|
|
890
|
+
}
|
|
891
|
+
Object.assign(el.style, preset.initial);
|
|
892
|
+
void el.offsetHeight;
|
|
893
|
+
requestAnimationFrame(() => {
|
|
894
|
+
Object.assign(el.style, preset.target);
|
|
895
|
+
waitForTransitionEnd(el, () => {
|
|
896
|
+
if (!hasTransitionDuration && !speedIn) {
|
|
897
|
+
el.style.transitionDuration = "";
|
|
898
|
+
}
|
|
899
|
+
if (speedIn) {
|
|
900
|
+
el.style.transitionDuration = "";
|
|
901
|
+
}
|
|
902
|
+
if (appliedTransitionProperty) {
|
|
903
|
+
el.style.transitionProperty = "";
|
|
904
|
+
}
|
|
905
|
+
onComplete?.();
|
|
906
|
+
});
|
|
907
|
+
});
|
|
908
|
+
}
|
|
909
|
+
function hideWithTransition(el, options = {}) {
|
|
910
|
+
const { defaultDuration = "300ms", defaultDistance = "24px", onComplete } = options;
|
|
911
|
+
const prefersReducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
912
|
+
if (prefersReducedMotion) {
|
|
913
|
+
el.style.display = "none";
|
|
914
|
+
el.setAttribute("aria-hidden", "true");
|
|
915
|
+
onComplete?.();
|
|
916
|
+
return;
|
|
917
|
+
}
|
|
918
|
+
const transitionOutBase = el.getAttribute("as-transition-out") || el.getAttribute("as-transition") || "fade";
|
|
919
|
+
const transitionOut = resolvePreset(transitionOutBase, "out");
|
|
920
|
+
const distance = el.getAttribute("as-transition-distance") || defaultDistance;
|
|
921
|
+
const speedOut = el.getAttribute("as-transition-speed-out") || el.getAttribute("as-transition-speed");
|
|
922
|
+
const preset = getPresetStyles(transitionOut, distance, "out");
|
|
923
|
+
const computed = window.getComputedStyle(el);
|
|
924
|
+
const hasTransitionDuration = computeMaxEndTime(computed.transitionDuration, computed.transitionDelay) > 0;
|
|
925
|
+
let appliedTransitionProperty = false;
|
|
926
|
+
const propStr = computed.transitionProperty || "";
|
|
927
|
+
const hasNeededProps = /(^|,|\s)(all|transform|opacity)(,|\s|$)/.test(propStr);
|
|
928
|
+
if (!hasNeededProps) {
|
|
929
|
+
el.style.transitionProperty = "opacity, transform";
|
|
930
|
+
appliedTransitionProperty = true;
|
|
931
|
+
}
|
|
932
|
+
if (!hasTransitionDuration && !speedOut) {
|
|
933
|
+
el.style.transitionDuration = defaultDuration;
|
|
934
|
+
if (!appliedTransitionProperty) {
|
|
935
|
+
el.style.transitionProperty = "opacity, transform";
|
|
936
|
+
appliedTransitionProperty = true;
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
if (speedOut) {
|
|
940
|
+
applySpeedOverride(el, speedOut);
|
|
941
|
+
}
|
|
942
|
+
Object.assign(el.style, preset.target);
|
|
943
|
+
waitForTransitionEnd(el, () => {
|
|
944
|
+
el.style.display = "none";
|
|
945
|
+
el.setAttribute("aria-hidden", "true");
|
|
946
|
+
clearTransitionStyles(el);
|
|
947
|
+
if (!hasTransitionDuration && !speedOut) {
|
|
948
|
+
el.style.transitionDuration = "";
|
|
949
|
+
}
|
|
950
|
+
if (speedOut) {
|
|
951
|
+
el.style.transitionDuration = "";
|
|
952
|
+
}
|
|
953
|
+
if (appliedTransitionProperty) {
|
|
954
|
+
el.style.transitionProperty = "";
|
|
955
|
+
}
|
|
956
|
+
onComplete?.();
|
|
957
|
+
});
|
|
958
|
+
}
|
|
959
|
+
function applyGridStack(container, incomingEl, outgoingEl) {
|
|
960
|
+
const prev = {
|
|
961
|
+
containerDisplay: container.style.display,
|
|
962
|
+
containerAlignItems: container.style.alignItems,
|
|
963
|
+
containerJustifyItems: container.style.justifyItems,
|
|
964
|
+
incGridArea: incomingEl.style.gridArea,
|
|
965
|
+
incZIndex: incomingEl.style.zIndex,
|
|
966
|
+
outGridArea: outgoingEl.style.gridArea,
|
|
967
|
+
outZIndex: outgoingEl.style.zIndex
|
|
968
|
+
};
|
|
969
|
+
const computedDisplay = window.getComputedStyle(container).display;
|
|
970
|
+
if (computedDisplay !== "grid" && computedDisplay !== "inline-grid") {
|
|
971
|
+
container.style.display = "grid";
|
|
972
|
+
}
|
|
973
|
+
incomingEl.style.gridArea = "1 / 1 / 2 / 2";
|
|
974
|
+
outgoingEl.style.gridArea = "1 / 1 / 2 / 2";
|
|
975
|
+
incomingEl.style.zIndex = "1";
|
|
976
|
+
outgoingEl.style.zIndex = "2";
|
|
977
|
+
return () => {
|
|
978
|
+
container.style.display = prev.containerDisplay;
|
|
979
|
+
container.style.alignItems = prev.containerAlignItems;
|
|
980
|
+
container.style.justifyItems = prev.containerJustifyItems;
|
|
981
|
+
incomingEl.style.gridArea = prev.incGridArea;
|
|
982
|
+
incomingEl.style.zIndex = prev.incZIndex;
|
|
983
|
+
outgoingEl.style.gridArea = prev.outGridArea;
|
|
984
|
+
outgoingEl.style.zIndex = prev.outZIndex;
|
|
985
|
+
};
|
|
986
|
+
}
|
|
987
|
+
function showStepWithTransition(el, skipAnimation, focusCallback) {
|
|
988
|
+
el.style.display = "";
|
|
989
|
+
el.setAttribute("aria-hidden", "false");
|
|
990
|
+
el.removeAttribute("inert");
|
|
991
|
+
if (skipAnimation) {
|
|
992
|
+
el.style.opacity = "1";
|
|
993
|
+
focusCallback(el);
|
|
994
|
+
return;
|
|
995
|
+
}
|
|
996
|
+
const transitionInBase = el.getAttribute("as-transition-in") || el.getAttribute("as-transition") || "fade";
|
|
997
|
+
const transitionIn = resolvePreset(transitionInBase, "in");
|
|
998
|
+
const distance = el.getAttribute("as-transition-distance") || "24px";
|
|
999
|
+
const speedIn = el.getAttribute("as-transition-speed-in") || el.getAttribute("as-transition-speed");
|
|
1000
|
+
const preset = getPresetStyles(transitionIn, distance, "in");
|
|
1001
|
+
const computed = window.getComputedStyle(el);
|
|
1002
|
+
const hasTransitionDuration = computeMaxEndTime(computed.transitionDuration, computed.transitionDelay) > 0;
|
|
1003
|
+
let appliedTransitionProperty = false;
|
|
1004
|
+
let appliedWillChange = false;
|
|
1005
|
+
const propStr = computed.transitionProperty || "";
|
|
1006
|
+
const hasNeededProps = /(^|,|\s)(all|transform|opacity)(,|\s|$)/.test(propStr);
|
|
1007
|
+
if (!hasNeededProps) {
|
|
1008
|
+
el.style.transitionProperty = "opacity, transform";
|
|
1009
|
+
appliedTransitionProperty = true;
|
|
1010
|
+
}
|
|
1011
|
+
if (!hasTransitionDuration && !speedIn) {
|
|
1012
|
+
el.style.transitionDuration = "300ms";
|
|
1013
|
+
if (!appliedTransitionProperty) {
|
|
1014
|
+
el.style.transitionProperty = "opacity, transform";
|
|
1015
|
+
appliedTransitionProperty = true;
|
|
1016
|
+
}
|
|
1017
|
+
}
|
|
1018
|
+
if (el.style.willChange !== "opacity, transform") {
|
|
1019
|
+
el.style.willChange = "opacity, transform";
|
|
1020
|
+
appliedWillChange = true;
|
|
1021
|
+
}
|
|
1022
|
+
if (speedIn) {
|
|
1023
|
+
applySpeedOverride(el, speedIn);
|
|
1024
|
+
}
|
|
1025
|
+
Object.assign(el.style, preset.initial);
|
|
1026
|
+
void el.offsetHeight;
|
|
1027
|
+
requestAnimationFrame(() => {
|
|
1028
|
+
Object.assign(el.style, preset.target);
|
|
1029
|
+
waitForTransitionEnd(el, () => {
|
|
1030
|
+
focusCallback(el);
|
|
1031
|
+
if (!hasTransitionDuration && !speedIn) {
|
|
1032
|
+
el.style.transitionDuration = "";
|
|
1033
|
+
}
|
|
1034
|
+
if (speedIn) {
|
|
1035
|
+
el.style.transitionDuration = "";
|
|
1036
|
+
}
|
|
1037
|
+
if (appliedTransitionProperty) {
|
|
1038
|
+
el.style.transitionProperty = "";
|
|
1039
|
+
}
|
|
1040
|
+
if (appliedWillChange) {
|
|
1041
|
+
el.style.willChange = "";
|
|
1042
|
+
}
|
|
1043
|
+
});
|
|
1044
|
+
});
|
|
1045
|
+
}
|
|
1046
|
+
function hideStepWithTransition(el, skipAnimation) {
|
|
1047
|
+
if (skipAnimation) {
|
|
1048
|
+
el.style.setProperty("display", "none", "important");
|
|
1049
|
+
el.setAttribute("aria-hidden", "true");
|
|
1050
|
+
el.setAttribute("inert", "");
|
|
1051
|
+
return;
|
|
1052
|
+
}
|
|
1053
|
+
const transitionOutBase = el.getAttribute("as-transition-out") || el.getAttribute("as-transition") || "fade";
|
|
1054
|
+
const transitionOut = resolvePreset(transitionOutBase, "out");
|
|
1055
|
+
const distance = el.getAttribute("as-transition-distance") || "24px";
|
|
1056
|
+
const speedOut = el.getAttribute("as-transition-speed-out") || el.getAttribute("as-transition-speed");
|
|
1057
|
+
const preset = getPresetStyles(transitionOut, distance, "out");
|
|
1058
|
+
const computed = window.getComputedStyle(el);
|
|
1059
|
+
const hasTransitionDuration = computeMaxEndTime(computed.transitionDuration, computed.transitionDelay) > 0;
|
|
1060
|
+
let appliedTransitionProperty = false;
|
|
1061
|
+
let appliedWillChange = false;
|
|
1062
|
+
const propStr = computed.transitionProperty || "";
|
|
1063
|
+
const hasNeededProps = /(^|,|\s)(all|transform|opacity)(,|\s|$)/.test(propStr);
|
|
1064
|
+
if (!hasNeededProps) {
|
|
1065
|
+
el.style.transitionProperty = "opacity, transform";
|
|
1066
|
+
appliedTransitionProperty = true;
|
|
1067
|
+
}
|
|
1068
|
+
if (!hasTransitionDuration && !speedOut) {
|
|
1069
|
+
el.style.transitionDuration = "300ms";
|
|
1070
|
+
if (!appliedTransitionProperty) {
|
|
1071
|
+
el.style.transitionProperty = "opacity, transform";
|
|
1072
|
+
appliedTransitionProperty = true;
|
|
1073
|
+
}
|
|
1074
|
+
}
|
|
1075
|
+
if (el.style.willChange !== "opacity, transform") {
|
|
1076
|
+
el.style.willChange = "opacity, transform";
|
|
1077
|
+
appliedWillChange = true;
|
|
1078
|
+
}
|
|
1079
|
+
if (speedOut) {
|
|
1080
|
+
applySpeedOverride(el, speedOut);
|
|
1081
|
+
}
|
|
1082
|
+
Object.assign(el.style, preset.target);
|
|
1083
|
+
waitForTransitionEnd(el, () => {
|
|
1084
|
+
el.style.setProperty("display", "none", "important");
|
|
1085
|
+
el.setAttribute("aria-hidden", "true");
|
|
1086
|
+
el.setAttribute("inert", "");
|
|
1087
|
+
clearTransitionStyles(el);
|
|
1088
|
+
if (!hasTransitionDuration && !speedOut) {
|
|
1089
|
+
el.style.transitionDuration = "";
|
|
1090
|
+
}
|
|
1091
|
+
if (speedOut) {
|
|
1092
|
+
el.style.transitionDuration = "";
|
|
1093
|
+
}
|
|
1094
|
+
if (appliedTransitionProperty) {
|
|
1095
|
+
el.style.transitionProperty = "";
|
|
1096
|
+
}
|
|
1097
|
+
if (appliedWillChange) {
|
|
1098
|
+
el.style.willChange = "";
|
|
1099
|
+
}
|
|
1100
|
+
});
|
|
1101
|
+
}
|
|
1102
|
+
function waitForTransitionEnd(el, callback) {
|
|
1103
|
+
const computed = window.getComputedStyle(el);
|
|
1104
|
+
const duration = computed.transitionDuration;
|
|
1105
|
+
const delay = computed.transitionDelay;
|
|
1106
|
+
const maxEndTime = computeMaxEndTime(duration, delay);
|
|
1107
|
+
if (maxEndTime === 0) {
|
|
1108
|
+
callback();
|
|
1109
|
+
return;
|
|
1110
|
+
}
|
|
1111
|
+
let fired = false;
|
|
1112
|
+
const timeoutId = setTimeout(() => {
|
|
1113
|
+
if (!fired) {
|
|
1114
|
+
fired = true;
|
|
1115
|
+
callback();
|
|
1116
|
+
}
|
|
1117
|
+
}, maxEndTime + 50);
|
|
1118
|
+
const handler = (e) => {
|
|
1119
|
+
if (e.target === el && !fired) {
|
|
1120
|
+
fired = true;
|
|
1121
|
+
clearTimeout(timeoutId);
|
|
1122
|
+
el.removeEventListener("transitionend", handler);
|
|
1123
|
+
el.removeEventListener("animationend", handler);
|
|
1124
|
+
callback();
|
|
1125
|
+
}
|
|
1126
|
+
};
|
|
1127
|
+
el.addEventListener("transitionend", handler);
|
|
1128
|
+
el.addEventListener("animationend", handler);
|
|
1129
|
+
}
|
|
1130
|
+
function applySpeedOverride(el, speed) {
|
|
1131
|
+
const computed = window.getComputedStyle(el);
|
|
1132
|
+
const currentDuration = computed.transitionDuration;
|
|
1133
|
+
switch (speed) {
|
|
1134
|
+
case "fast":
|
|
1135
|
+
el.style.transitionDuration = scaleDuration(currentDuration, 0.7);
|
|
1136
|
+
break;
|
|
1137
|
+
case "normal":
|
|
1138
|
+
break;
|
|
1139
|
+
case "slow":
|
|
1140
|
+
el.style.transitionDuration = scaleDuration(currentDuration, 1.5);
|
|
1141
|
+
break;
|
|
1142
|
+
default:
|
|
1143
|
+
el.style.transitionDuration = speed;
|
|
1144
|
+
break;
|
|
1145
|
+
}
|
|
1146
|
+
}
|
|
1147
|
+
function scaleDuration(durationStr, scale) {
|
|
1148
|
+
const durations = durationStr.split(",").map((d) => d.trim());
|
|
1149
|
+
return durations.map((d) => {
|
|
1150
|
+
const match = d.match(/^([\d.]+)(m?s)$/);
|
|
1151
|
+
if (!match || !match[1] || !match[2]) return d;
|
|
1152
|
+
const value = parseFloat(match[1]);
|
|
1153
|
+
const unit = match[2];
|
|
1154
|
+
const scaled = value * scale;
|
|
1155
|
+
return `${scaled}${unit}`;
|
|
1156
|
+
}).join(", ");
|
|
1157
|
+
}
|
|
1158
|
+
function computeMaxEndTime(durationStr, delayStr) {
|
|
1159
|
+
const durations = durationStr.split(",").map((d) => parseTimeValue(d.trim()));
|
|
1160
|
+
const delays = delayStr.split(",").map((d) => parseTimeValue(d.trim()));
|
|
1161
|
+
let maxEndTime = 0;
|
|
1162
|
+
for (let i = 0; i < durations.length; i++) {
|
|
1163
|
+
const duration = durations[i] || 0;
|
|
1164
|
+
const delay = delays[i] || delays[0] || 0;
|
|
1165
|
+
const endTime = duration + delay;
|
|
1166
|
+
if (endTime > maxEndTime) {
|
|
1167
|
+
maxEndTime = endTime;
|
|
1168
|
+
}
|
|
1169
|
+
}
|
|
1170
|
+
return maxEndTime;
|
|
1171
|
+
}
|
|
1172
|
+
function parseTimeValue(value) {
|
|
1173
|
+
const match = value.match(/^([\d.]+)(m?s)$/);
|
|
1174
|
+
if (!match || !match[1] || !match[2]) return 0;
|
|
1175
|
+
const num = parseFloat(match[1]);
|
|
1176
|
+
const unit = match[2];
|
|
1177
|
+
return unit === "ms" ? num : num * 1e3;
|
|
1178
|
+
}
|
|
1179
|
+
function clearTransitionStyles(el) {
|
|
1180
|
+
el.style.opacity = "";
|
|
1181
|
+
el.style.translate = "";
|
|
1182
|
+
el.style.scale = "";
|
|
1183
|
+
el.style.transform = "";
|
|
1184
|
+
}
|
|
1185
|
+
|
|
1186
|
+
// src/features/conditions.ts
|
|
1187
|
+
function initConditions(root) {
|
|
1188
|
+
if (!root) return;
|
|
1189
|
+
syncAnswersFromInputs(root);
|
|
1190
|
+
attachAnswerSyncListeners(root);
|
|
1191
|
+
applyVisibility();
|
|
1192
|
+
applyEnableDisable();
|
|
1193
|
+
observeDOMMutations();
|
|
1194
|
+
sessionStore.subscribe(() => {
|
|
1195
|
+
applyVisibility();
|
|
1196
|
+
applyEnableDisable();
|
|
1197
|
+
});
|
|
1198
|
+
import_loglevel2.default.debug("[conditions] Initialized");
|
|
1199
|
+
}
|
|
1200
|
+
function evaluateShowIf(predicateJson, answers) {
|
|
1201
|
+
try {
|
|
1202
|
+
const predicate = JSON.parse(predicateJson);
|
|
1203
|
+
return evaluatePredicate(predicate, answers);
|
|
1204
|
+
} catch (error) {
|
|
1205
|
+
import_loglevel2.default.error("[conditions] Invalid predicate JSON:", error);
|
|
1206
|
+
return false;
|
|
1207
|
+
}
|
|
1208
|
+
}
|
|
1209
|
+
function evaluatePredicate(predicate, answers) {
|
|
1210
|
+
if ("all" in predicate) {
|
|
1211
|
+
const compositePred = predicate;
|
|
1212
|
+
return compositePred.all.every((p) => evaluatePredicate(p, answers));
|
|
1213
|
+
}
|
|
1214
|
+
if ("any" in predicate) {
|
|
1215
|
+
const compositePred = predicate;
|
|
1216
|
+
return compositePred.any.some((p) => evaluatePredicate(p, answers));
|
|
1217
|
+
}
|
|
1218
|
+
if ("not" in predicate) {
|
|
1219
|
+
const compositePred = predicate;
|
|
1220
|
+
return !evaluatePredicate(compositePred.not, answers);
|
|
1221
|
+
}
|
|
1222
|
+
if ("field" in predicate && "op" in predicate) {
|
|
1223
|
+
const { field, op, value } = predicate;
|
|
1224
|
+
const fieldValue = resolveField(field, answers);
|
|
1225
|
+
switch (op) {
|
|
1226
|
+
case "eq":
|
|
1227
|
+
return fieldValue === value;
|
|
1228
|
+
case "neq":
|
|
1229
|
+
return fieldValue !== value;
|
|
1230
|
+
case "in":
|
|
1231
|
+
return Array.isArray(value) && value.includes(fieldValue);
|
|
1232
|
+
case "nin":
|
|
1233
|
+
return Array.isArray(value) && !value.includes(fieldValue);
|
|
1234
|
+
case "gt":
|
|
1235
|
+
return Number(fieldValue) > Number(value);
|
|
1236
|
+
case "gte":
|
|
1237
|
+
return Number(fieldValue) >= Number(value);
|
|
1238
|
+
case "lt":
|
|
1239
|
+
return Number(fieldValue) < Number(value);
|
|
1240
|
+
case "lte":
|
|
1241
|
+
return Number(fieldValue) <= Number(value);
|
|
1242
|
+
case "exists":
|
|
1243
|
+
return fieldValue !== void 0 && fieldValue !== null;
|
|
1244
|
+
case "truthy":
|
|
1245
|
+
return Boolean(fieldValue);
|
|
1246
|
+
case "falsy":
|
|
1247
|
+
return !fieldValue;
|
|
1248
|
+
case "contains":
|
|
1249
|
+
return String(fieldValue).includes(String(value));
|
|
1250
|
+
case "starts_with":
|
|
1251
|
+
return String(fieldValue).startsWith(String(value));
|
|
1252
|
+
case "ends_with":
|
|
1253
|
+
return String(fieldValue).endsWith(String(value));
|
|
1254
|
+
default:
|
|
1255
|
+
return false;
|
|
1256
|
+
}
|
|
1257
|
+
}
|
|
1258
|
+
return false;
|
|
1259
|
+
}
|
|
1260
|
+
function applyVisibility() {
|
|
1261
|
+
if (typeof document === "undefined") return;
|
|
1262
|
+
const answers = sessionStore.get().answers;
|
|
1263
|
+
document.querySelectorAll("[as-show-if]").forEach((el) => {
|
|
1264
|
+
const predicate = el.getAttribute("as-show-if");
|
|
1265
|
+
if (!predicate) return;
|
|
1266
|
+
const visible = evaluateShowIf(predicate, answers);
|
|
1267
|
+
toggleVisibility(el, visible);
|
|
1268
|
+
});
|
|
1269
|
+
document.querySelectorAll("[as-hide-if]").forEach((el) => {
|
|
1270
|
+
const predicate = el.getAttribute("as-hide-if");
|
|
1271
|
+
if (!predicate) return;
|
|
1272
|
+
const shouldHide = evaluateShowIf(predicate, answers);
|
|
1273
|
+
toggleVisibility(el, !shouldHide);
|
|
1274
|
+
});
|
|
1275
|
+
}
|
|
1276
|
+
function toggleVisibility(el, visible) {
|
|
1277
|
+
const currentlyVisible = isElementVisible(el);
|
|
1278
|
+
if (visible === currentlyVisible) {
|
|
1279
|
+
return;
|
|
1280
|
+
}
|
|
1281
|
+
if (visible) {
|
|
1282
|
+
showElementWithTransition(el);
|
|
1283
|
+
import_loglevel2.default.debug("[conditions] Showing element with transition");
|
|
1284
|
+
return;
|
|
1285
|
+
}
|
|
1286
|
+
hideElementWithTransition(el);
|
|
1287
|
+
import_loglevel2.default.debug("[conditions] Hiding element with transition");
|
|
1288
|
+
}
|
|
1289
|
+
function observeDOMMutations() {
|
|
1290
|
+
if (typeof document === "undefined" || typeof MutationObserver === "undefined") return;
|
|
1291
|
+
const observer2 = new MutationObserver(() => {
|
|
1292
|
+
import_loglevel2.default.debug("[conditions] DOM mutation detected, re-applying visibility");
|
|
1293
|
+
applyVisibility();
|
|
1294
|
+
});
|
|
1295
|
+
observer2.observe(document.body, {
|
|
1296
|
+
childList: true,
|
|
1297
|
+
subtree: true
|
|
1298
|
+
});
|
|
1299
|
+
}
|
|
1300
|
+
function attachAnswerSyncListeners(root) {
|
|
1301
|
+
const handler = () => {
|
|
1302
|
+
syncAnswersFromInputs(root);
|
|
1303
|
+
};
|
|
1304
|
+
root.addEventListener("input", handler);
|
|
1305
|
+
root.addEventListener("change", handler);
|
|
1306
|
+
}
|
|
1307
|
+
function showElementWithTransition(el) {
|
|
1308
|
+
const skipAnimation = shouldSkipVisibilityAnimation();
|
|
1309
|
+
const token = updateVisibilityToken(el);
|
|
1310
|
+
import_loglevel2.default.debug("[conditions] show transition start", {
|
|
1311
|
+
token,
|
|
1312
|
+
skipAnimation,
|
|
1313
|
+
element: describeElement(el)
|
|
1314
|
+
});
|
|
1315
|
+
el.dataset.asVisibilityState = "visible";
|
|
1316
|
+
restoreDisplay(el);
|
|
1317
|
+
el.setAttribute("aria-hidden", "false");
|
|
1318
|
+
el.removeAttribute("inert");
|
|
1319
|
+
if (skipAnimation) {
|
|
1320
|
+
clearTransitionStyles(el);
|
|
1321
|
+
el.style.opacity = "";
|
|
1322
|
+
el.style.transform = "";
|
|
1323
|
+
import_loglevel2.default.debug("[conditions] show transition skipped (reduced motion)", { token });
|
|
1324
|
+
return;
|
|
1325
|
+
}
|
|
1326
|
+
const transitionInBase = el.getAttribute("as-transition-in") || el.getAttribute("as-transition") || "fade";
|
|
1327
|
+
const transitionIn = resolvePreset(transitionInBase, "in");
|
|
1328
|
+
const distance = el.getAttribute("as-transition-distance") || "24px";
|
|
1329
|
+
const speedIn = el.getAttribute("as-transition-speed-in") || el.getAttribute("as-transition-speed");
|
|
1330
|
+
const preset = getPresetStyles(transitionIn, distance, "in");
|
|
1331
|
+
const computed = window.getComputedStyle(el);
|
|
1332
|
+
const hasTransitionDuration = computeMaxEndTime(computed.transitionDuration, computed.transitionDelay) > 0;
|
|
1333
|
+
const propStr = computed.transitionProperty || "";
|
|
1334
|
+
const hasNeededProps = /(^|,|\s)(all|transform|opacity)(,|\s|$)/.test(propStr);
|
|
1335
|
+
const previousTransitionProperty = el.style.transitionProperty;
|
|
1336
|
+
const previousTransitionDuration = el.style.transitionDuration;
|
|
1337
|
+
const previousWillChange = el.style.willChange;
|
|
1338
|
+
el.style.transitionProperty = "none";
|
|
1339
|
+
el.style.transitionDuration = "0ms";
|
|
1340
|
+
Object.assign(el.style, preset.initial);
|
|
1341
|
+
void el.offsetHeight;
|
|
1342
|
+
requestAnimationFrame(() => {
|
|
1343
|
+
if (!isCurrentVisibilityToken(el, token)) {
|
|
1344
|
+
import_loglevel2.default.debug("[conditions] show transition aborted before animation (token mismatch)", {
|
|
1345
|
+
token
|
|
1346
|
+
});
|
|
1347
|
+
el.style.transitionProperty = previousTransitionProperty;
|
|
1348
|
+
el.style.transitionDuration = previousTransitionDuration;
|
|
1349
|
+
el.style.willChange = previousWillChange;
|
|
1350
|
+
return;
|
|
1351
|
+
}
|
|
1352
|
+
let appliedTransitionProperty = false;
|
|
1353
|
+
let appliedTransitionDuration = false;
|
|
1354
|
+
let appliedWillChange = false;
|
|
1355
|
+
if (hasNeededProps) {
|
|
1356
|
+
el.style.transitionProperty = previousTransitionProperty;
|
|
1357
|
+
} else {
|
|
1358
|
+
el.style.transitionProperty = "opacity, transform";
|
|
1359
|
+
appliedTransitionProperty = true;
|
|
1360
|
+
}
|
|
1361
|
+
if (speedIn) {
|
|
1362
|
+
applySpeedOverride(el, speedIn);
|
|
1363
|
+
} else if (!hasTransitionDuration) {
|
|
1364
|
+
el.style.transitionDuration = "300ms";
|
|
1365
|
+
appliedTransitionDuration = true;
|
|
1366
|
+
} else {
|
|
1367
|
+
el.style.transitionDuration = previousTransitionDuration;
|
|
1368
|
+
}
|
|
1369
|
+
if (el.style.willChange !== "opacity, transform") {
|
|
1370
|
+
el.style.willChange = "opacity, transform";
|
|
1371
|
+
appliedWillChange = true;
|
|
1372
|
+
}
|
|
1373
|
+
Object.assign(el.style, preset.target);
|
|
1374
|
+
waitForTransitionEnd(el, () => {
|
|
1375
|
+
if (!isCurrentVisibilityToken(el, token)) {
|
|
1376
|
+
import_loglevel2.default.debug("[conditions] show transition cleanup skipped (token mismatch)", { token });
|
|
1377
|
+
return;
|
|
1378
|
+
}
|
|
1379
|
+
if (appliedTransitionDuration || speedIn) {
|
|
1380
|
+
el.style.transitionDuration = previousTransitionDuration;
|
|
1381
|
+
}
|
|
1382
|
+
if (appliedTransitionProperty) {
|
|
1383
|
+
el.style.transitionProperty = previousTransitionProperty;
|
|
1384
|
+
}
|
|
1385
|
+
if (appliedWillChange) {
|
|
1386
|
+
el.style.willChange = previousWillChange;
|
|
1387
|
+
}
|
|
1388
|
+
import_loglevel2.default.debug("[conditions] show transition complete", {
|
|
1389
|
+
token,
|
|
1390
|
+
element: describeElement(el)
|
|
1391
|
+
});
|
|
1392
|
+
});
|
|
1393
|
+
});
|
|
1394
|
+
}
|
|
1395
|
+
function hideElementWithTransition(el) {
|
|
1396
|
+
const skipAnimation = shouldSkipVisibilityAnimation();
|
|
1397
|
+
const token = updateVisibilityToken(el);
|
|
1398
|
+
import_loglevel2.default.debug("[conditions] hide transition start", {
|
|
1399
|
+
token,
|
|
1400
|
+
skipAnimation,
|
|
1401
|
+
element: describeElement(el)
|
|
1402
|
+
});
|
|
1403
|
+
el.dataset.asVisibilityState = "hidden";
|
|
1404
|
+
if (skipAnimation) {
|
|
1405
|
+
setDisplayNone(el);
|
|
1406
|
+
el.setAttribute("aria-hidden", "true");
|
|
1407
|
+
el.setAttribute("inert", "");
|
|
1408
|
+
clearTransitionStyles(el);
|
|
1409
|
+
import_loglevel2.default.debug("[conditions] hide transition skipped (reduced motion)", { token });
|
|
1410
|
+
return;
|
|
1411
|
+
}
|
|
1412
|
+
const transitionOutBase = el.getAttribute("as-transition-out") || el.getAttribute("as-transition") || "fade";
|
|
1413
|
+
const transitionOut = resolvePreset(transitionOutBase, "out");
|
|
1414
|
+
const distance = el.getAttribute("as-transition-distance") || "24px";
|
|
1415
|
+
const speedOut = el.getAttribute("as-transition-speed-out") || el.getAttribute("as-transition-speed");
|
|
1416
|
+
const preset = getPresetStyles(transitionOut, distance, "out");
|
|
1417
|
+
const computed = window.getComputedStyle(el);
|
|
1418
|
+
const hasTransitionDuration = computeMaxEndTime(computed.transitionDuration, computed.transitionDelay) > 0;
|
|
1419
|
+
let appliedTransitionProperty = false;
|
|
1420
|
+
let appliedWillChange = false;
|
|
1421
|
+
const propStr = computed.transitionProperty || "";
|
|
1422
|
+
const hasNeededProps = /(^|,|\s)(all|transform|opacity)(,|\s|$)/.test(propStr);
|
|
1423
|
+
if (!hasNeededProps) {
|
|
1424
|
+
el.style.transitionProperty = "opacity, transform";
|
|
1425
|
+
appliedTransitionProperty = true;
|
|
1426
|
+
}
|
|
1427
|
+
if (!hasTransitionDuration && !speedOut) {
|
|
1428
|
+
el.style.transitionDuration = "300ms";
|
|
1429
|
+
if (!appliedTransitionProperty) {
|
|
1430
|
+
el.style.transitionProperty = "opacity, transform";
|
|
1431
|
+
appliedTransitionProperty = true;
|
|
1432
|
+
}
|
|
1433
|
+
}
|
|
1434
|
+
if (el.style.willChange !== "opacity, transform") {
|
|
1435
|
+
el.style.willChange = "opacity, transform";
|
|
1436
|
+
appliedWillChange = true;
|
|
1437
|
+
}
|
|
1438
|
+
if (speedOut) {
|
|
1439
|
+
applySpeedOverride(el, speedOut);
|
|
1440
|
+
}
|
|
1441
|
+
Object.assign(el.style, preset.target);
|
|
1442
|
+
waitForTransitionEnd(el, () => {
|
|
1443
|
+
if (!isCurrentVisibilityToken(el, token)) {
|
|
1444
|
+
import_loglevel2.default.debug("[conditions] hide transition cleanup skipped (token mismatch)", { token });
|
|
1445
|
+
return;
|
|
1446
|
+
}
|
|
1447
|
+
setDisplayNone(el);
|
|
1448
|
+
el.setAttribute("aria-hidden", "true");
|
|
1449
|
+
el.setAttribute("inert", "");
|
|
1450
|
+
clearTransitionStyles(el);
|
|
1451
|
+
if (!hasTransitionDuration && !speedOut) {
|
|
1452
|
+
el.style.transitionDuration = "";
|
|
1453
|
+
} else if (speedOut) {
|
|
1454
|
+
el.style.transitionDuration = "";
|
|
1455
|
+
}
|
|
1456
|
+
if (appliedTransitionProperty) {
|
|
1457
|
+
el.style.transitionProperty = "";
|
|
1458
|
+
}
|
|
1459
|
+
if (appliedWillChange) {
|
|
1460
|
+
el.style.willChange = "";
|
|
1461
|
+
}
|
|
1462
|
+
import_loglevel2.default.debug("[conditions] hide transition complete", {
|
|
1463
|
+
token,
|
|
1464
|
+
element: describeElement(el)
|
|
1465
|
+
});
|
|
1466
|
+
});
|
|
1467
|
+
}
|
|
1468
|
+
function shouldSkipVisibilityAnimation() {
|
|
1469
|
+
if (typeof window === "undefined" || typeof window.matchMedia !== "function") {
|
|
1470
|
+
return false;
|
|
1471
|
+
}
|
|
1472
|
+
return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
1473
|
+
}
|
|
1474
|
+
function updateVisibilityToken(el) {
|
|
1475
|
+
const token = typeof crypto !== "undefined" && "randomUUID" in crypto ? crypto.randomUUID() : `${Date.now()}-${Math.random().toString(16).slice(2)}`;
|
|
1476
|
+
el.dataset.asVisibilityToken = token;
|
|
1477
|
+
return token;
|
|
1478
|
+
}
|
|
1479
|
+
function isCurrentVisibilityToken(el, token) {
|
|
1480
|
+
return el.dataset.asVisibilityToken === token;
|
|
1481
|
+
}
|
|
1482
|
+
function isElementVisible(el) {
|
|
1483
|
+
const state = el.dataset.asVisibilityState;
|
|
1484
|
+
if (state === "visible") return true;
|
|
1485
|
+
if (state === "hidden") return false;
|
|
1486
|
+
if (el.getAttribute("aria-hidden") === "true") return false;
|
|
1487
|
+
if (el.style.display === "none") return false;
|
|
1488
|
+
return true;
|
|
1489
|
+
}
|
|
1490
|
+
function restoreDisplay(el) {
|
|
1491
|
+
el.style.removeProperty("display");
|
|
1492
|
+
const cached = el.dataset.asDisplayCache;
|
|
1493
|
+
if (cached && cached !== "none") {
|
|
1494
|
+
el.style.display = cached;
|
|
1495
|
+
return;
|
|
1496
|
+
}
|
|
1497
|
+
if (!cached) {
|
|
1498
|
+
el.style.display = "";
|
|
1499
|
+
}
|
|
1500
|
+
}
|
|
1501
|
+
function setDisplayNone(el) {
|
|
1502
|
+
cacheDisplay(el);
|
|
1503
|
+
el.style.setProperty("display", "none", "important");
|
|
1504
|
+
}
|
|
1505
|
+
function cacheDisplay(el) {
|
|
1506
|
+
if (el.dataset.asDisplayCache && el.dataset.asDisplayCache !== "none") {
|
|
1507
|
+
return;
|
|
1508
|
+
}
|
|
1509
|
+
const inlineDisplay = el.style.display;
|
|
1510
|
+
if (inlineDisplay && inlineDisplay !== "none") {
|
|
1511
|
+
el.dataset.asDisplayCache = inlineDisplay;
|
|
1512
|
+
return;
|
|
1513
|
+
}
|
|
1514
|
+
if (typeof window !== "undefined" && typeof window.getComputedStyle === "function") {
|
|
1515
|
+
const computedDisplay = window.getComputedStyle(el).display;
|
|
1516
|
+
if (computedDisplay && computedDisplay !== "none") {
|
|
1517
|
+
el.dataset.asDisplayCache = computedDisplay;
|
|
1518
|
+
}
|
|
1519
|
+
}
|
|
1520
|
+
}
|
|
1521
|
+
function describeElement(el) {
|
|
1522
|
+
const idPart = el.id ? `#${el.id}` : "";
|
|
1523
|
+
const logicId = el.getAttribute("as-element-id");
|
|
1524
|
+
const logicPart = logicId ? `[${logicId}]` : "";
|
|
1525
|
+
return `<${el.tagName.toLowerCase()}${idPart}${logicPart}>`;
|
|
1526
|
+
}
|
|
1527
|
+
function evaluateNextMap(nextMapJson, answers) {
|
|
1528
|
+
try {
|
|
1529
|
+
const nextMap = JSON.parse(nextMapJson);
|
|
1530
|
+
for (const rule of nextMap) {
|
|
1531
|
+
if (evaluatePredicate(rule.if, answers)) {
|
|
1532
|
+
return rule.then;
|
|
1533
|
+
}
|
|
1534
|
+
}
|
|
1535
|
+
return null;
|
|
1536
|
+
} catch (error) {
|
|
1537
|
+
import_loglevel2.default.error("[conditions] Invalid next-map JSON:", error);
|
|
1538
|
+
return null;
|
|
1539
|
+
}
|
|
1540
|
+
}
|
|
1541
|
+
function applyEnableDisable() {
|
|
1542
|
+
if (typeof document === "undefined") return;
|
|
1543
|
+
const answers = sessionStore.get().answers;
|
|
1544
|
+
document.querySelectorAll("[as-disable-if]").forEach((el) => {
|
|
1545
|
+
const predicate = el.getAttribute("as-disable-if");
|
|
1546
|
+
if (!predicate) return;
|
|
1547
|
+
const shouldDisable = evaluateShowIf(predicate, answers);
|
|
1548
|
+
setElementDisabled(el, shouldDisable);
|
|
1549
|
+
});
|
|
1550
|
+
document.querySelectorAll("[as-enable-if]").forEach((el) => {
|
|
1551
|
+
const predicate = el.getAttribute("as-enable-if");
|
|
1552
|
+
if (!predicate) return;
|
|
1553
|
+
const shouldEnable = evaluateShowIf(predicate, answers);
|
|
1554
|
+
setElementDisabled(el, !shouldEnable);
|
|
1555
|
+
});
|
|
1556
|
+
}
|
|
1557
|
+
function setElementDisabled(el, disabled) {
|
|
1558
|
+
if (!el.hasAttribute("data-as-original-tabindex") && el.hasAttribute("tabindex")) {
|
|
1559
|
+
el.setAttribute("data-as-original-tabindex", el.getAttribute("tabindex") || "0");
|
|
1560
|
+
}
|
|
1561
|
+
if (disabled) {
|
|
1562
|
+
if (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement || el instanceof HTMLSelectElement || el instanceof HTMLButtonElement) {
|
|
1563
|
+
el.disabled = true;
|
|
1564
|
+
}
|
|
1565
|
+
el.setAttribute("aria-disabled", "true");
|
|
1566
|
+
el.setAttribute("tabindex", "-1");
|
|
1567
|
+
el.classList.add("as-disabled");
|
|
1568
|
+
el.removeAttribute("aria-invalid");
|
|
1569
|
+
el.removeAttribute("aria-describedby");
|
|
1570
|
+
} else {
|
|
1571
|
+
if (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement || el instanceof HTMLSelectElement || el instanceof HTMLButtonElement) {
|
|
1572
|
+
el.disabled = false;
|
|
1573
|
+
}
|
|
1574
|
+
el.removeAttribute("aria-disabled");
|
|
1575
|
+
const originalTabIndex = el.getAttribute("data-as-original-tabindex");
|
|
1576
|
+
if (originalTabIndex) {
|
|
1577
|
+
el.setAttribute("tabindex", originalTabIndex);
|
|
1578
|
+
el.removeAttribute("data-as-original-tabindex");
|
|
1579
|
+
} else {
|
|
1580
|
+
el.removeAttribute("tabindex");
|
|
1581
|
+
}
|
|
1582
|
+
el.classList.remove("as-disabled");
|
|
1583
|
+
}
|
|
1584
|
+
}
|
|
1585
|
+
function isElementDisabled(el) {
|
|
1586
|
+
if (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement || el instanceof HTMLSelectElement || el instanceof HTMLButtonElement) {
|
|
1587
|
+
if (el.disabled) return true;
|
|
1588
|
+
}
|
|
1589
|
+
return el.classList.contains("as-disabled");
|
|
1590
|
+
}
|
|
1591
|
+
|
|
1592
|
+
// src/features/validation.ts
|
|
1593
|
+
var ERROR_TRANSITION_OPTIONS = {
|
|
1594
|
+
defaultDuration: "200ms",
|
|
1595
|
+
defaultDistance: "12px"
|
|
1596
|
+
};
|
|
1597
|
+
var validators = {
|
|
1598
|
+
required: (val) => val.trim() !== "",
|
|
1599
|
+
email: (val) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(val),
|
|
1600
|
+
pattern: (val, re) => new RegExp(re).test(val),
|
|
1601
|
+
min: (val, n) => val.length >= Number(n),
|
|
1602
|
+
max: (val, n) => val.length <= Number(n)
|
|
1603
|
+
};
|
|
1604
|
+
function ensureErrorTargetDisplay(target) {
|
|
1605
|
+
if (target.dataset.asErrorDisplay) return;
|
|
1606
|
+
let display = "";
|
|
1607
|
+
const inlineDisplay = target.style.display;
|
|
1608
|
+
if (inlineDisplay && inlineDisplay !== "none") {
|
|
1609
|
+
display = inlineDisplay;
|
|
1610
|
+
}
|
|
1611
|
+
if (!display && typeof window !== "undefined" && typeof window.getComputedStyle === "function") {
|
|
1612
|
+
const computed = window.getComputedStyle(target).display;
|
|
1613
|
+
if (computed && computed !== "none") {
|
|
1614
|
+
display = computed;
|
|
1615
|
+
}
|
|
1616
|
+
}
|
|
1617
|
+
if (!display) {
|
|
1618
|
+
display = target.tagName === "SPAN" || target.tagName === "LABEL" ? "inline" : "block";
|
|
1619
|
+
}
|
|
1620
|
+
target.dataset.asErrorDisplay = display;
|
|
1621
|
+
}
|
|
1622
|
+
function seedErrorTargetDefaults(target) {
|
|
1623
|
+
if (!target.dataset.asErrorDefault) {
|
|
1624
|
+
target.dataset.asErrorDefault = target.textContent ?? "";
|
|
1625
|
+
}
|
|
1626
|
+
ensureErrorTargetDisplay(target);
|
|
1627
|
+
if (!target.hasAttribute("role")) {
|
|
1628
|
+
target.setAttribute("role", "alert");
|
|
1629
|
+
}
|
|
1630
|
+
if (!target.hasAttribute("aria-live")) {
|
|
1631
|
+
target.setAttribute("aria-live", "polite");
|
|
1632
|
+
}
|
|
1633
|
+
}
|
|
1634
|
+
function applyErrorTargetVisibility(target, isActive) {
|
|
1635
|
+
ensureErrorTargetDisplay(target);
|
|
1636
|
+
const hasTransition = target.hasAttribute("as-transition");
|
|
1637
|
+
const display = target.dataset.asErrorDisplay || "block";
|
|
1638
|
+
if (isActive) {
|
|
1639
|
+
if (hasTransition) {
|
|
1640
|
+
showWithTransition(target, { ...ERROR_TRANSITION_OPTIONS, displayValue: display });
|
|
1641
|
+
} else {
|
|
1642
|
+
target.style.display = display;
|
|
1643
|
+
target.removeAttribute("hidden");
|
|
1644
|
+
target.removeAttribute("aria-hidden");
|
|
1645
|
+
}
|
|
1646
|
+
} else {
|
|
1647
|
+
if (hasTransition) {
|
|
1648
|
+
hideWithTransition(target, ERROR_TRANSITION_OPTIONS);
|
|
1649
|
+
} else {
|
|
1650
|
+
target.style.display = "none";
|
|
1651
|
+
target.setAttribute("aria-hidden", "true");
|
|
1652
|
+
}
|
|
1653
|
+
}
|
|
1654
|
+
}
|
|
1655
|
+
function initializeErrorTargets(root) {
|
|
1656
|
+
if (typeof document === "undefined") return;
|
|
1657
|
+
const targets = [];
|
|
1658
|
+
if (root instanceof HTMLElement && root.hasAttribute("as-error-for")) {
|
|
1659
|
+
targets.push(root);
|
|
1660
|
+
}
|
|
1661
|
+
root.querySelectorAll("[as-error-for]").forEach((target) => {
|
|
1662
|
+
if (!targets.includes(target)) {
|
|
1663
|
+
targets.push(target);
|
|
1664
|
+
}
|
|
1665
|
+
});
|
|
1666
|
+
for (const target of targets) {
|
|
1667
|
+
seedErrorTargetDefaults(target);
|
|
1668
|
+
const isActive = target.dataset.asErrorActive === "true";
|
|
1669
|
+
applyErrorTargetVisibility(target, isActive);
|
|
1670
|
+
}
|
|
1671
|
+
}
|
|
1672
|
+
async function validatePhone(val, input) {
|
|
1673
|
+
try {
|
|
1674
|
+
const parsePhoneNumberFromString = await getParsePhoneNumberFromString();
|
|
1675
|
+
if (!parsePhoneNumberFromString) {
|
|
1676
|
+
import_loglevel3.default.warn("[validation] Phone library not available");
|
|
1677
|
+
return false;
|
|
1678
|
+
}
|
|
1679
|
+
const region = input?.getAttribute("as-phone-region") || void 0;
|
|
1680
|
+
const hasInternationalPrefix = val.trim().startsWith("+");
|
|
1681
|
+
import_loglevel3.default.debug(
|
|
1682
|
+
"[validation] Validating phone:",
|
|
1683
|
+
val,
|
|
1684
|
+
"has + prefix:",
|
|
1685
|
+
hasInternationalPrefix,
|
|
1686
|
+
"region:",
|
|
1687
|
+
region
|
|
1688
|
+
);
|
|
1689
|
+
if (hasInternationalPrefix) {
|
|
1690
|
+
const parsed = parsePhoneNumberFromString(val);
|
|
1691
|
+
import_loglevel3.default.debug("[validation] Parse international:", parsed ? "success" : "failed");
|
|
1692
|
+
if (parsed && typeof parsed.isValid === "function") {
|
|
1693
|
+
const isValid = parsed.isValid();
|
|
1694
|
+
import_loglevel3.default.debug("[validation] Country:", parsed.country, "isValid:", isValid);
|
|
1695
|
+
return isValid;
|
|
1696
|
+
}
|
|
1697
|
+
import_loglevel3.default.debug("[validation] International number validation failed");
|
|
1698
|
+
return false;
|
|
1699
|
+
} else {
|
|
1700
|
+
if (!region) {
|
|
1701
|
+
import_loglevel3.default.debug("[validation] No region specified for national number");
|
|
1702
|
+
return false;
|
|
1703
|
+
}
|
|
1704
|
+
const parsed = parsePhoneNumberFromString(val, region);
|
|
1705
|
+
import_loglevel3.default.debug("[validation] Parse with region:", parsed ? "success" : "failed");
|
|
1706
|
+
if (parsed && typeof parsed.isValid === "function") {
|
|
1707
|
+
const isValid = parsed.isValid();
|
|
1708
|
+
import_loglevel3.default.debug("[validation] Country:", parsed.country, "isValid:", isValid);
|
|
1709
|
+
return isValid;
|
|
1710
|
+
}
|
|
1711
|
+
import_loglevel3.default.debug("[validation] National number validation failed");
|
|
1712
|
+
return false;
|
|
1713
|
+
}
|
|
1714
|
+
} catch (error) {
|
|
1715
|
+
import_loglevel3.default.error("[validation] Failed to validate phone number:", error);
|
|
1716
|
+
return false;
|
|
1717
|
+
}
|
|
1718
|
+
}
|
|
1719
|
+
function initValidation(_root) {
|
|
1720
|
+
initializeErrorTargets(_root);
|
|
1721
|
+
import_loglevel3.default.debug("[validation] Initialized");
|
|
1722
|
+
}
|
|
1723
|
+
async function validateStep(stepId) {
|
|
1724
|
+
if (typeof document === "undefined") return true;
|
|
1725
|
+
const stepEl = document.querySelector(`[as-step="${stepId}"]`);
|
|
1726
|
+
if (!stepEl) return true;
|
|
1727
|
+
const fields = Array.from(
|
|
1728
|
+
stepEl.querySelectorAll(
|
|
1729
|
+
"input, textarea, select"
|
|
1730
|
+
)
|
|
1731
|
+
);
|
|
1732
|
+
for (const field of fields) {
|
|
1733
|
+
if (isElementDisabled(field)) {
|
|
1734
|
+
clearError(field);
|
|
1735
|
+
continue;
|
|
1736
|
+
}
|
|
1737
|
+
if (isFieldDisabled(field)) {
|
|
1738
|
+
clearError(field);
|
|
1739
|
+
continue;
|
|
1740
|
+
}
|
|
1741
|
+
const rulesAttr = field.getAttribute("as-validate") || "";
|
|
1742
|
+
const rawTokens = rulesAttr.split("|").map((token) => token.trim()).filter(Boolean);
|
|
1743
|
+
const evaluationTokens = [];
|
|
1744
|
+
const seenTokens = /* @__PURE__ */ new Set();
|
|
1745
|
+
if (field.hasAttribute("required") || field.required === true) {
|
|
1746
|
+
evaluationTokens.push("required");
|
|
1747
|
+
seenTokens.add("required");
|
|
1748
|
+
}
|
|
1749
|
+
for (const token of rawTokens) {
|
|
1750
|
+
if (!token) continue;
|
|
1751
|
+
if (seenTokens.has(token)) continue;
|
|
1752
|
+
seenTokens.add(token);
|
|
1753
|
+
evaluationTokens.push(token);
|
|
1754
|
+
}
|
|
1755
|
+
if (evaluationTokens.length === 0) {
|
|
1756
|
+
clearError(field);
|
|
1757
|
+
continue;
|
|
1758
|
+
}
|
|
1759
|
+
const value = getFieldValue(field);
|
|
1760
|
+
for (const token of evaluationTokens) {
|
|
1761
|
+
const [name, param] = token.split(":");
|
|
1762
|
+
const ruleName = name || "";
|
|
1763
|
+
let valid;
|
|
1764
|
+
if (ruleName === "phone") {
|
|
1765
|
+
valid = await validatePhone(value, field);
|
|
1766
|
+
} else if (ruleName === "required") {
|
|
1767
|
+
valid = checkRequired(field, stepEl);
|
|
1768
|
+
} else {
|
|
1769
|
+
const validator = validators[ruleName];
|
|
1770
|
+
valid = validator ? validator(value, param ?? "") : true;
|
|
1771
|
+
}
|
|
1772
|
+
if (!valid) {
|
|
1773
|
+
showError(field, getErrorMessage(field, ruleName));
|
|
1774
|
+
return false;
|
|
1775
|
+
}
|
|
1776
|
+
}
|
|
1777
|
+
clearError(field);
|
|
1778
|
+
}
|
|
1779
|
+
return true;
|
|
1780
|
+
}
|
|
1781
|
+
function showError(input, message) {
|
|
1782
|
+
const target = resolveErrorTarget(input);
|
|
1783
|
+
if (target) {
|
|
1784
|
+
removeInjectedError(input);
|
|
1785
|
+
const targetId = prepareErrorTarget(target);
|
|
1786
|
+
target.textContent = message;
|
|
1787
|
+
target.dataset.asErrorActive = "true";
|
|
1788
|
+
applyErrorTargetVisibility(target, true);
|
|
1789
|
+
input.setAttribute("aria-invalid", "true");
|
|
1790
|
+
if (targetId) {
|
|
1791
|
+
input.setAttribute("aria-describedby", targetId);
|
|
1792
|
+
}
|
|
1793
|
+
return;
|
|
1794
|
+
}
|
|
1795
|
+
let errDiv = input.nextElementSibling;
|
|
1796
|
+
if (!errDiv || !errDiv.classList.contains("as-error")) {
|
|
1797
|
+
errDiv = document.createElement("div");
|
|
1798
|
+
errDiv.className = "as-error";
|
|
1799
|
+
errDiv.setAttribute("role", "alert");
|
|
1800
|
+
input.parentElement?.insertBefore(errDiv, input.nextSibling);
|
|
1801
|
+
}
|
|
1802
|
+
errDiv.textContent = message;
|
|
1803
|
+
input.setAttribute("aria-invalid", "true");
|
|
1804
|
+
input.setAttribute(
|
|
1805
|
+
"aria-describedby",
|
|
1806
|
+
errDiv.id = `err-${typeof crypto !== "undefined" && "randomUUID" in crypto ? crypto.randomUUID() : Date.now()}`
|
|
1807
|
+
);
|
|
1808
|
+
}
|
|
1809
|
+
function clearError(input) {
|
|
1810
|
+
const target = resolveErrorTarget(input);
|
|
1811
|
+
if (target) {
|
|
1812
|
+
const defaultText = target.dataset.asErrorDefault ?? "";
|
|
1813
|
+
target.textContent = defaultText;
|
|
1814
|
+
delete target.dataset.asErrorActive;
|
|
1815
|
+
applyErrorTargetVisibility(target, false);
|
|
1816
|
+
} else {
|
|
1817
|
+
removeInjectedError(input);
|
|
1818
|
+
}
|
|
1819
|
+
input.removeAttribute("aria-invalid");
|
|
1820
|
+
input.removeAttribute("aria-describedby");
|
|
1821
|
+
}
|
|
1822
|
+
function resolveErrorTarget(input) {
|
|
1823
|
+
const fieldId = input.getAttribute("as-element-id") || input.getAttribute("id") || input.getAttribute("name");
|
|
1824
|
+
if (!fieldId) return null;
|
|
1825
|
+
const scope = input.closest("[as-step]") ?? document;
|
|
1826
|
+
const target = scope.querySelector(`[as-error-for="${fieldId}"]`);
|
|
1827
|
+
return target ?? null;
|
|
1828
|
+
}
|
|
1829
|
+
function removeInjectedError(input) {
|
|
1830
|
+
const errDiv = input.nextElementSibling;
|
|
1831
|
+
if (errDiv && errDiv.classList.contains("as-error")) {
|
|
1832
|
+
errDiv.remove();
|
|
1833
|
+
}
|
|
1834
|
+
}
|
|
1835
|
+
function getErrorMessage(input, rule) {
|
|
1836
|
+
const customMsg = input.getAttribute("as-error-message");
|
|
1837
|
+
if (customMsg) return customMsg;
|
|
1838
|
+
const customMsgs = input.getAttribute("as-error-messages");
|
|
1839
|
+
if (customMsgs) {
|
|
1840
|
+
try {
|
|
1841
|
+
const parsed = JSON.parse(customMsgs);
|
|
1842
|
+
if (parsed[rule]) return parsed[rule];
|
|
1843
|
+
} catch {
|
|
1844
|
+
}
|
|
1845
|
+
}
|
|
1846
|
+
const messages = getErrorMessagesForLanguage();
|
|
1847
|
+
return messages[rule] || "Invalid input";
|
|
1848
|
+
}
|
|
1849
|
+
function prepareErrorTarget(target) {
|
|
1850
|
+
seedErrorTargetDefaults(target);
|
|
1851
|
+
if (!target.id) {
|
|
1852
|
+
const newId = typeof crypto !== "undefined" && typeof crypto.randomUUID === "function" ? crypto.randomUUID() : `err-${Date.now()}`;
|
|
1853
|
+
target.id = newId;
|
|
1854
|
+
}
|
|
1855
|
+
return target.id;
|
|
1856
|
+
}
|
|
1857
|
+
function isFieldDisabled(field) {
|
|
1858
|
+
if (field instanceof HTMLInputElement) return field.disabled;
|
|
1859
|
+
if (field instanceof HTMLTextAreaElement) return field.disabled;
|
|
1860
|
+
if (field instanceof HTMLSelectElement) return field.disabled;
|
|
1861
|
+
return false;
|
|
1862
|
+
}
|
|
1863
|
+
function getFieldValue(field) {
|
|
1864
|
+
if (field instanceof HTMLInputElement) {
|
|
1865
|
+
const { type } = field;
|
|
1866
|
+
if (type === "checkbox") {
|
|
1867
|
+
return field.checked ? field.value || "on" : "";
|
|
1868
|
+
}
|
|
1869
|
+
if (type === "radio") {
|
|
1870
|
+
return field.checked ? field.value || "on" : "";
|
|
1871
|
+
}
|
|
1872
|
+
if (type === "file") {
|
|
1873
|
+
return field.files && field.files.length > 0 ? "selected" : "";
|
|
1874
|
+
}
|
|
1875
|
+
}
|
|
1876
|
+
if (field instanceof HTMLSelectElement && field.multiple) {
|
|
1877
|
+
return Array.from(field.selectedOptions).map((option) => option.value).join(",");
|
|
1878
|
+
}
|
|
1879
|
+
return field.value ?? "";
|
|
1880
|
+
}
|
|
1881
|
+
function checkRequired(field, stepEl) {
|
|
1882
|
+
if (field instanceof HTMLInputElement) {
|
|
1883
|
+
if (field.disabled) return true;
|
|
1884
|
+
switch (field.type) {
|
|
1885
|
+
case "checkbox":
|
|
1886
|
+
return field.checked;
|
|
1887
|
+
case "radio": {
|
|
1888
|
+
const name = field.name;
|
|
1889
|
+
if (!name) {
|
|
1890
|
+
return field.checked;
|
|
1891
|
+
}
|
|
1892
|
+
const selector = `input[type="radio"][name="${escapeAttributeValue(name)}"]`;
|
|
1893
|
+
const radios = stepEl.querySelectorAll(selector);
|
|
1894
|
+
for (const radio of Array.from(radios)) {
|
|
1895
|
+
if (radio.disabled) continue;
|
|
1896
|
+
if (radio.checked) {
|
|
1897
|
+
return true;
|
|
1898
|
+
}
|
|
1899
|
+
}
|
|
1900
|
+
return false;
|
|
1901
|
+
}
|
|
1902
|
+
case "file":
|
|
1903
|
+
return Boolean(field.files && field.files.length > 0);
|
|
1904
|
+
default:
|
|
1905
|
+
return field.value.trim() !== "";
|
|
1906
|
+
}
|
|
1907
|
+
}
|
|
1908
|
+
if (field instanceof HTMLSelectElement) {
|
|
1909
|
+
if (field.disabled) return true;
|
|
1910
|
+
if (field.multiple) {
|
|
1911
|
+
return field.selectedOptions.length > 0;
|
|
1912
|
+
}
|
|
1913
|
+
return field.value.trim() !== "";
|
|
1914
|
+
}
|
|
1915
|
+
if (field instanceof HTMLTextAreaElement) {
|
|
1916
|
+
if (field.disabled) return true;
|
|
1917
|
+
return field.value.trim() !== "";
|
|
1918
|
+
}
|
|
1919
|
+
return true;
|
|
1920
|
+
}
|
|
1921
|
+
function escapeAttributeValue(value) {
|
|
1922
|
+
if (typeof CSS !== "undefined" && typeof CSS.escape === "function") {
|
|
1923
|
+
return CSS.escape(value);
|
|
1924
|
+
}
|
|
1925
|
+
return value.replace(/["\\]/g, "\\$&");
|
|
1926
|
+
}
|
|
1927
|
+
|
|
1928
|
+
// src/features/redirect.ts
|
|
1929
|
+
var import_loglevel5 = __toESM(require_loglevel(), 1);
|
|
1930
|
+
|
|
1931
|
+
// src/features/basin.ts
|
|
1932
|
+
var import_loglevel4 = __toESM(require_loglevel(), 1);
|
|
1933
|
+
var questionMetrics = /* @__PURE__ */ new Map();
|
|
1934
|
+
function initBasin(root) {
|
|
1935
|
+
const endpoint = getBasinEndpointFromMeta();
|
|
1936
|
+
if (!endpoint) {
|
|
1937
|
+
import_loglevel4.default.debug("[basin] No endpoint found in meta tag, skipping Basin integration");
|
|
1938
|
+
return;
|
|
1939
|
+
}
|
|
1940
|
+
recordQuestionMetrics(root);
|
|
1941
|
+
if (typeof window !== "undefined") {
|
|
1942
|
+
window.addEventListener("beforeunload", () => {
|
|
1943
|
+
const formData = collectFormData();
|
|
1944
|
+
formData.set("basinjsdraft", "true");
|
|
1945
|
+
navigator.sendBeacon(endpoint, formData);
|
|
1946
|
+
});
|
|
1947
|
+
}
|
|
1948
|
+
import_loglevel4.default.debug("[basin] Initialized with endpoint:", endpoint);
|
|
1949
|
+
}
|
|
1950
|
+
function getBasinEndpointFromMeta() {
|
|
1951
|
+
if (typeof document === "undefined") return "";
|
|
1952
|
+
const meta = document.querySelector('meta[name="as:basin-endpoint"]');
|
|
1953
|
+
if (meta?.content) return meta.content;
|
|
1954
|
+
const body = document.body;
|
|
1955
|
+
if (body?.hasAttribute("as-basin-endpoint")) {
|
|
1956
|
+
return body.getAttribute("as-basin-endpoint") || "";
|
|
1957
|
+
}
|
|
1958
|
+
return "";
|
|
1959
|
+
}
|
|
1960
|
+
async function fetchBasinJWT(endpoint) {
|
|
1961
|
+
if (typeof window === "undefined") return "";
|
|
1962
|
+
const cached = window.localStorage.getItem("as:basin-jwt");
|
|
1963
|
+
if (cached) return cached;
|
|
1964
|
+
try {
|
|
1965
|
+
const res = await fetch(`${endpoint}/generate_jwt`, {
|
|
1966
|
+
method: "GET",
|
|
1967
|
+
headers: {
|
|
1968
|
+
"Content-Type": "application/json",
|
|
1969
|
+
Accept: "application/json"
|
|
1970
|
+
}
|
|
1971
|
+
});
|
|
1972
|
+
if (!res.ok) {
|
|
1973
|
+
import_loglevel4.default.warn("[basin] JWT endpoint returned", res.status, "- multistep may not be supported");
|
|
1974
|
+
return "";
|
|
1975
|
+
}
|
|
1976
|
+
const data = await res.json();
|
|
1977
|
+
if (data.jwt) {
|
|
1978
|
+
window.localStorage.setItem("as:basin-jwt", data.jwt);
|
|
1979
|
+
return data.jwt;
|
|
1980
|
+
}
|
|
1981
|
+
return "";
|
|
1982
|
+
} catch (error) {
|
|
1983
|
+
import_loglevel4.default.warn("[basin] Failed to fetch JWT (multistep may not be supported):", error);
|
|
1984
|
+
return "";
|
|
1985
|
+
}
|
|
1986
|
+
}
|
|
1987
|
+
async function sendPartial(stepId) {
|
|
1988
|
+
const endpoint = getBasinEndpointFromMeta();
|
|
1989
|
+
if (!endpoint) {
|
|
1990
|
+
import_loglevel4.default.warn("[basin] No endpoint, skipping partial submission");
|
|
1991
|
+
return;
|
|
1992
|
+
}
|
|
1993
|
+
const jwt = await fetchBasinJWT(endpoint);
|
|
1994
|
+
const formData = collectFormData();
|
|
1995
|
+
if (jwt) {
|
|
1996
|
+
formData.append("basinjwt", jwt);
|
|
1997
|
+
}
|
|
1998
|
+
formData.append("basinjsmultistep", "true");
|
|
1999
|
+
formData.append("basinjsdraft", "true");
|
|
2000
|
+
const stepNumber = getStepPosition(stepId);
|
|
2001
|
+
formData.append("basinjsstep", String(stepNumber));
|
|
2002
|
+
if (import_loglevel4.default.getLevel() <= import_loglevel4.default.levels.DEBUG) {
|
|
2003
|
+
import_loglevel4.default.debug(`[basin] Sending partial submission for step: ${stepId}`);
|
|
2004
|
+
const entries = [];
|
|
2005
|
+
formData.forEach((value, key) => {
|
|
2006
|
+
entries.push(` ${key}: ${typeof value === "string" ? value.substring(0, 100) : "[File]"}`);
|
|
2007
|
+
});
|
|
2008
|
+
import_loglevel4.default.debug(`[basin] FormData contents:
|
|
2009
|
+
${entries.join("\n")}`);
|
|
2010
|
+
}
|
|
2011
|
+
try {
|
|
2012
|
+
const res = await fetch(endpoint, {
|
|
2013
|
+
method: "POST",
|
|
2014
|
+
body: formData,
|
|
2015
|
+
keepalive: true
|
|
2016
|
+
});
|
|
2017
|
+
if (!res.ok) {
|
|
2018
|
+
import_loglevel4.default.warn("[basin] Partial submission failed with status:", res.status);
|
|
2019
|
+
return;
|
|
2020
|
+
}
|
|
2021
|
+
import_loglevel4.default.debug("[basin] Sent partial submission for step:", stepId);
|
|
2022
|
+
} catch (error) {
|
|
2023
|
+
import_loglevel4.default.error("[basin] Failed to send partial submission:", error);
|
|
2024
|
+
}
|
|
2025
|
+
}
|
|
2026
|
+
async function sendFinal(stepId) {
|
|
2027
|
+
const endpoint = getBasinEndpointFromMeta();
|
|
2028
|
+
if (!endpoint) {
|
|
2029
|
+
import_loglevel4.default.warn("[basin] No endpoint, skipping final submission");
|
|
2030
|
+
return;
|
|
2031
|
+
}
|
|
2032
|
+
const jwt = await fetchBasinJWT(endpoint);
|
|
2033
|
+
const formData = collectFormData();
|
|
2034
|
+
if (jwt) {
|
|
2035
|
+
formData.append("basinjwt", jwt);
|
|
2036
|
+
}
|
|
2037
|
+
formData.append("basinjsmultistep", "true");
|
|
2038
|
+
formData.append("basinjsdraft", "false");
|
|
2039
|
+
try {
|
|
2040
|
+
await fetch(endpoint, { method: "POST", body: formData, keepalive: true });
|
|
2041
|
+
import_loglevel4.default.debug("[basin] Sent final submission for step:", stepId);
|
|
2042
|
+
} catch (error) {
|
|
2043
|
+
import_loglevel4.default.error("[basin] Failed to send final submission:", error);
|
|
2044
|
+
}
|
|
2045
|
+
}
|
|
2046
|
+
function collectFormData() {
|
|
2047
|
+
const formData = new FormData();
|
|
2048
|
+
if (typeof document !== "undefined") {
|
|
2049
|
+
const allInputs = document.querySelectorAll('input[name]:not([type="file"]), textarea[name], select[name]');
|
|
2050
|
+
allInputs.forEach((input) => {
|
|
2051
|
+
const name = input.name;
|
|
2052
|
+
if (!name) return;
|
|
2053
|
+
if (input instanceof HTMLInputElement) {
|
|
2054
|
+
if (input.type === "checkbox") {
|
|
2055
|
+
if (input.checked) {
|
|
2056
|
+
formData.append(name, input.value || "on");
|
|
2057
|
+
}
|
|
2058
|
+
} else if (input.type === "radio") {
|
|
2059
|
+
if (input.checked) {
|
|
2060
|
+
formData.append(name, input.value);
|
|
2061
|
+
}
|
|
2062
|
+
} else {
|
|
2063
|
+
if (input.value) {
|
|
2064
|
+
formData.append(name, input.value);
|
|
2065
|
+
}
|
|
2066
|
+
}
|
|
2067
|
+
} else if (input instanceof HTMLTextAreaElement || input instanceof HTMLSelectElement) {
|
|
2068
|
+
if (input.value) {
|
|
2069
|
+
formData.append(name, input.value);
|
|
2070
|
+
}
|
|
2071
|
+
}
|
|
2072
|
+
});
|
|
2073
|
+
const fileInputs = document.querySelectorAll('input[type="file"][name]');
|
|
2074
|
+
addFilesToFormData(formData, fileInputs);
|
|
2075
|
+
}
|
|
2076
|
+
formData.append("frombasinjs", "false");
|
|
2077
|
+
formData.append("agera_version", "0.1.1");
|
|
2078
|
+
if (typeof window !== "undefined") {
|
|
2079
|
+
const params = new URLSearchParams(window.location.search);
|
|
2080
|
+
["source", "medium", "campaign", "term", "content"].forEach((key) => {
|
|
2081
|
+
const val = params.get(`utm_${key}`);
|
|
2082
|
+
if (val) formData.append(`utm_${key}`, val);
|
|
2083
|
+
});
|
|
2084
|
+
}
|
|
2085
|
+
return formData;
|
|
2086
|
+
}
|
|
2087
|
+
function recordQuestionMetrics(root) {
|
|
2088
|
+
const inputs = root.querySelectorAll(
|
|
2089
|
+
"input, textarea, select"
|
|
2090
|
+
);
|
|
2091
|
+
inputs.forEach((input) => {
|
|
2092
|
+
if (!input.name) return;
|
|
2093
|
+
questionMetrics.set(input.name, { displayedAt: /* @__PURE__ */ new Date() });
|
|
2094
|
+
input.addEventListener(
|
|
2095
|
+
"focus",
|
|
2096
|
+
() => {
|
|
2097
|
+
const metrics = questionMetrics.get(input.name);
|
|
2098
|
+
if (metrics && !metrics.firstFocusedAt) {
|
|
2099
|
+
metrics.firstFocusedAt = /* @__PURE__ */ new Date();
|
|
2100
|
+
}
|
|
2101
|
+
},
|
|
2102
|
+
{ once: true }
|
|
2103
|
+
);
|
|
2104
|
+
input.addEventListener("input", () => {
|
|
2105
|
+
const metrics = questionMetrics.get(input.name);
|
|
2106
|
+
if (metrics) {
|
|
2107
|
+
if (!metrics.firstAnsweredAt) {
|
|
2108
|
+
metrics.firstAnsweredAt = /* @__PURE__ */ new Date();
|
|
2109
|
+
}
|
|
2110
|
+
metrics.lastEditedAt = /* @__PURE__ */ new Date();
|
|
2111
|
+
}
|
|
2112
|
+
});
|
|
2113
|
+
});
|
|
2114
|
+
}
|
|
2115
|
+
function addFilesToFormData(formData, fileInputs) {
|
|
2116
|
+
fileInputs.forEach((input) => {
|
|
2117
|
+
if (input.files && input.name) {
|
|
2118
|
+
Array.from(input.files).forEach((file) => {
|
|
2119
|
+
formData.append(input.name, file);
|
|
2120
|
+
});
|
|
2121
|
+
}
|
|
2122
|
+
});
|
|
2123
|
+
}
|
|
2124
|
+
|
|
2125
|
+
// src/features/redirect.ts
|
|
2126
|
+
function initRedirect(root) {
|
|
2127
|
+
if (!root) return;
|
|
2128
|
+
attachRedirectHandlers(root);
|
|
2129
|
+
import_loglevel5.default.debug("[redirect] Initialized");
|
|
2130
|
+
}
|
|
2131
|
+
function attachRedirectHandlers(root) {
|
|
2132
|
+
root.querySelectorAll("[as-redirect]").forEach((el) => {
|
|
2133
|
+
if (el.dataset.asRedirectBound === "true") return;
|
|
2134
|
+
el.addEventListener("click", (event) => {
|
|
2135
|
+
if (event.defaultPrevented) return;
|
|
2136
|
+
const trigger = event.currentTarget;
|
|
2137
|
+
if (trigger.hasAttribute("as-next")) {
|
|
2138
|
+
import_loglevel5.default.debug("[redirect] Skipping auto-click handler because element also has [as-next]");
|
|
2139
|
+
return;
|
|
2140
|
+
}
|
|
2141
|
+
event.preventDefault();
|
|
2142
|
+
const stepEl = trigger.closest("[as-step]");
|
|
2143
|
+
const stepId = getStepIdFromElement(stepEl);
|
|
2144
|
+
if (!stepId) {
|
|
2145
|
+
import_loglevel5.default.warn("[redirect] Could not resolve step for redirect trigger:", describe(trigger));
|
|
2146
|
+
return;
|
|
2147
|
+
}
|
|
2148
|
+
void (async () => {
|
|
2149
|
+
if (shouldValidateRedirect(trigger, stepEl)) {
|
|
2150
|
+
const isValid = await validateStep(stepId);
|
|
2151
|
+
if (!isValid) {
|
|
2152
|
+
import_loglevel5.default.debug("[redirect] Validation failed, aborting redirect click");
|
|
2153
|
+
return;
|
|
2154
|
+
}
|
|
2155
|
+
}
|
|
2156
|
+
await handleRedirect(stepId, trigger);
|
|
2157
|
+
})();
|
|
2158
|
+
});
|
|
2159
|
+
el.dataset.asRedirectBound = "true";
|
|
2160
|
+
});
|
|
2161
|
+
}
|
|
2162
|
+
async function handleRedirect(stepId, source) {
|
|
2163
|
+
if (typeof document === "undefined" || typeof window === "undefined") return;
|
|
2164
|
+
const stepEl = document.querySelector(`[as-step="${stepId}"]`);
|
|
2165
|
+
const sourceEl = source instanceof Element ? source : null;
|
|
2166
|
+
const selection = resolveRedirectSelection(stepEl, sourceEl);
|
|
2167
|
+
await sendFinal(stepId);
|
|
2168
|
+
if (!selection) {
|
|
2169
|
+
import_loglevel5.default.debug("[redirect] No redirect configured, final submission sent");
|
|
2170
|
+
return;
|
|
2171
|
+
}
|
|
2172
|
+
const url = buildRedirectUrl(
|
|
2173
|
+
selection.url,
|
|
2174
|
+
selection.preserveUtm,
|
|
2175
|
+
selection.includeSession,
|
|
2176
|
+
sessionStore.get().id
|
|
2177
|
+
);
|
|
2178
|
+
import_loglevel5.default.debug("[redirect] Redirecting via %s to: %s", selection.source, url);
|
|
2179
|
+
if (selection.useReplace) {
|
|
2180
|
+
window.location.replace(url);
|
|
2181
|
+
return;
|
|
2182
|
+
}
|
|
2183
|
+
window.location.assign(url);
|
|
2184
|
+
}
|
|
2185
|
+
function buildRedirectUrl(base, preserveUtm, includeSession, sessionId) {
|
|
2186
|
+
if (typeof window === "undefined") return base;
|
|
2187
|
+
const url = new URL(base, window.location.origin);
|
|
2188
|
+
if (preserveUtm) {
|
|
2189
|
+
const params = new URLSearchParams(window.location.search);
|
|
2190
|
+
params.forEach((val, key) => {
|
|
2191
|
+
if (!val) return;
|
|
2192
|
+
if (key.toLowerCase().startsWith("utm")) {
|
|
2193
|
+
url.searchParams.set(key, val);
|
|
2194
|
+
}
|
|
2195
|
+
});
|
|
2196
|
+
}
|
|
2197
|
+
if (includeSession && sessionId) {
|
|
2198
|
+
url.searchParams.set("sessionId", sessionId);
|
|
2199
|
+
}
|
|
2200
|
+
return url.toString();
|
|
2201
|
+
}
|
|
2202
|
+
function readBooleanAttr(el, name) {
|
|
2203
|
+
if (!el || !el.hasAttribute(name)) return null;
|
|
2204
|
+
const value = el.getAttribute(name);
|
|
2205
|
+
if (!value) return true;
|
|
2206
|
+
const normalized = value.trim().toLowerCase();
|
|
2207
|
+
if (["false", "0", "off", "no"].includes(normalized)) return false;
|
|
2208
|
+
return true;
|
|
2209
|
+
}
|
|
2210
|
+
function resolveRedirectSelection(stepEl, sourceEl) {
|
|
2211
|
+
const answers = sessionStore.get().answers;
|
|
2212
|
+
const mapAttr = sourceEl?.getAttribute("as-redirect-map") ?? stepEl?.getAttribute("as-redirect-map");
|
|
2213
|
+
if (mapAttr) {
|
|
2214
|
+
const mapRule = evaluateRedirectMap(mapAttr, answers);
|
|
2215
|
+
if (mapRule) {
|
|
2216
|
+
return {
|
|
2217
|
+
url: mapRule.to,
|
|
2218
|
+
preserveUtm: mapRule.preserveUtm ?? true,
|
|
2219
|
+
includeSession: mapRule.includeSession ?? false,
|
|
2220
|
+
useReplace: mapRule.replace ?? false,
|
|
2221
|
+
source: "map"
|
|
2222
|
+
};
|
|
2223
|
+
}
|
|
2224
|
+
import_loglevel5.default.debug("[redirect] Redirect map evaluated with no matching rule, falling back to attribute");
|
|
2225
|
+
}
|
|
2226
|
+
const url = sourceEl?.getAttribute("as-redirect") ?? stepEl?.getAttribute("as-redirect");
|
|
2227
|
+
if (!url) return null;
|
|
2228
|
+
return {
|
|
2229
|
+
url,
|
|
2230
|
+
preserveUtm: resolveBooleanPreference("as-redirect-preserve-utm", sourceEl, stepEl, true),
|
|
2231
|
+
includeSession: resolveBooleanPreference(
|
|
2232
|
+
"as-redirect-include-session",
|
|
2233
|
+
sourceEl,
|
|
2234
|
+
stepEl,
|
|
2235
|
+
false
|
|
2236
|
+
),
|
|
2237
|
+
useReplace: resolveBooleanPreference("as-redirect-replace", sourceEl, stepEl, false),
|
|
2238
|
+
source: "attribute"
|
|
2239
|
+
};
|
|
2240
|
+
}
|
|
2241
|
+
function resolveBooleanPreference(attr, primary, fallback, defaultValue) {
|
|
2242
|
+
const resolved = readBooleanAttr(primary, attr) ?? readBooleanAttr(fallback, attr);
|
|
2243
|
+
return resolved ?? defaultValue;
|
|
2244
|
+
}
|
|
2245
|
+
function evaluateRedirectMap(json, answers) {
|
|
2246
|
+
try {
|
|
2247
|
+
const parsed = JSON.parse(json);
|
|
2248
|
+
if (!Array.isArray(parsed)) {
|
|
2249
|
+
import_loglevel5.default.warn("[redirect] as-redirect-map must be an array of rules");
|
|
2250
|
+
return null;
|
|
2251
|
+
}
|
|
2252
|
+
for (const rule of parsed) {
|
|
2253
|
+
if (!rule || typeof rule.to !== "string" || rule.to.trim() === "") {
|
|
2254
|
+
import_loglevel5.default.warn("[redirect] Redirect map rule missing a 'to' URL, skipping");
|
|
2255
|
+
continue;
|
|
2256
|
+
}
|
|
2257
|
+
if (!rule.if || evaluatePredicate(rule.if, answers)) {
|
|
2258
|
+
return rule;
|
|
2259
|
+
}
|
|
2260
|
+
}
|
|
2261
|
+
} catch (error) {
|
|
2262
|
+
import_loglevel5.default.error("[redirect] Invalid as-redirect-map JSON:", error);
|
|
2263
|
+
}
|
|
2264
|
+
return null;
|
|
2265
|
+
}
|
|
2266
|
+
function shouldValidateRedirect(sourceEl, stepEl) {
|
|
2267
|
+
const result = readBooleanAttr(sourceEl, "as-redirect-validate") ?? readBooleanAttr(stepEl, "as-redirect-validate");
|
|
2268
|
+
return result ?? true;
|
|
2269
|
+
}
|
|
2270
|
+
function getStepIdFromElement(stepEl) {
|
|
2271
|
+
if (stepEl?.hasAttribute("as-step")) {
|
|
2272
|
+
return stepEl.getAttribute("as-step");
|
|
2273
|
+
}
|
|
2274
|
+
const current = stepsStore.get().current;
|
|
2275
|
+
return current || null;
|
|
2276
|
+
}
|
|
2277
|
+
function describe(el) {
|
|
2278
|
+
const id = el.getAttribute("id");
|
|
2279
|
+
const step = el.closest("[as-step]")?.getAttribute("as-step");
|
|
2280
|
+
return `<${el.tagName.toLowerCase()}${id ? `#${id}` : ""}${step ? ` step="${step}"` : ""}>`;
|
|
2281
|
+
}
|
|
2282
|
+
|
|
2283
|
+
// src/features/utils/keyboard.ts
|
|
2284
|
+
function attachKeyboardHandlers() {
|
|
2285
|
+
document.addEventListener("keydown", (e) => {
|
|
2286
|
+
if (e.key === "Enter" && e.target instanceof HTMLInputElement) {
|
|
2287
|
+
const nextBtn = document.querySelector(`[as-step="${stepsStore.get().current}"] [as-next]`);
|
|
2288
|
+
if (nextBtn instanceof HTMLElement) {
|
|
2289
|
+
e.preventDefault();
|
|
2290
|
+
nextBtn.click();
|
|
2291
|
+
}
|
|
2292
|
+
}
|
|
2293
|
+
});
|
|
2294
|
+
}
|
|
2295
|
+
|
|
2296
|
+
// src/features/utils/aria.ts
|
|
2297
|
+
function announceAria(message) {
|
|
2298
|
+
const region = ensureAriaLiveRegion();
|
|
2299
|
+
region.textContent = message;
|
|
2300
|
+
}
|
|
2301
|
+
function focusFirstInteractive(el) {
|
|
2302
|
+
const firstInput = el.querySelector("input, textarea, select, button");
|
|
2303
|
+
if (firstInput) {
|
|
2304
|
+
setTimeout(() => firstInput.focus(), 100);
|
|
2305
|
+
}
|
|
2306
|
+
}
|
|
2307
|
+
|
|
2308
|
+
// src/features/steps.ts
|
|
2309
|
+
var STEP_TRANSITION_GAP_MS = 80;
|
|
2310
|
+
var gotoAbortControllers = /* @__PURE__ */ new WeakMap();
|
|
2311
|
+
function isPartialSubmissionsEnabled() {
|
|
2312
|
+
if (typeof document === "undefined") return true;
|
|
2313
|
+
const body = document.body;
|
|
2314
|
+
const setting = body?.getAttribute("as-partial-submissions")?.toLowerCase();
|
|
2315
|
+
return setting !== "off";
|
|
2316
|
+
}
|
|
2317
|
+
function blurFocusedDescendant(container) {
|
|
2318
|
+
const focused = container.querySelector(":focus");
|
|
2319
|
+
if (focused) {
|
|
2320
|
+
import_loglevel6.default.debug(`[steps] \u{1F532} Blurring focused element before hiding step`);
|
|
2321
|
+
focused.blur();
|
|
2322
|
+
}
|
|
2323
|
+
}
|
|
2324
|
+
function initSteps(root) {
|
|
2325
|
+
const steps = Array.from(root.querySelectorAll("[as-step]"));
|
|
2326
|
+
if (steps.length === 0) return;
|
|
2327
|
+
const firstStepId = steps[0]?.getAttribute("as-step");
|
|
2328
|
+
if (firstStepId) {
|
|
2329
|
+
stepsStore.set({ current: firstStepId, path: [firstStepId] });
|
|
2330
|
+
import_loglevel6.default.debug(`[steps] First step already visible: ${firstStepId}`);
|
|
2331
|
+
}
|
|
2332
|
+
attachNavigationHandlers(root);
|
|
2333
|
+
attachKeyboardHandlers();
|
|
2334
|
+
}
|
|
2335
|
+
function showStep(stepId, previousStepId) {
|
|
2336
|
+
import_loglevel6.default.debug(
|
|
2337
|
+
`[steps] \u{1F4C4} showStep called: "${stepId}"${previousStepId ? ` (from: "${previousStepId}")` : ""}`
|
|
2338
|
+
);
|
|
2339
|
+
const steps = Array.from(document.querySelectorAll("[as-step]"));
|
|
2340
|
+
const prefersReducedMotion = typeof window !== "undefined" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
2341
|
+
const incomingEl = document.querySelector(`[as-step="${stepId}"]`);
|
|
2342
|
+
const outgoingEl = previousStepId ? document.querySelector(`[as-step="${previousStepId}"]`) : null;
|
|
2343
|
+
if (!incomingEl) {
|
|
2344
|
+
import_loglevel6.default.warn(`[steps] \u274C Cannot show step "${stepId}" - element not found`);
|
|
2345
|
+
return;
|
|
2346
|
+
}
|
|
2347
|
+
import_loglevel6.default.debug(`[steps] \u{1F3AC} Transition: ${prefersReducedMotion ? "reduced motion" : "animated"}`);
|
|
2348
|
+
if (previousStepId && previousStepId !== stepId && isPartialSubmissionsEnabled()) {
|
|
2349
|
+
import_loglevel6.default.debug(`[steps] \u{1F4BE} Triggering background partial submission for: "${previousStepId}"`);
|
|
2350
|
+
sendPartial(previousStepId).catch((error) => {
|
|
2351
|
+
import_loglevel6.default.error("[steps] Background partial submission failed:", error);
|
|
2352
|
+
});
|
|
2353
|
+
}
|
|
2354
|
+
steps.forEach((el) => {
|
|
2355
|
+
const id = el.getAttribute("as-step");
|
|
2356
|
+
if (id !== stepId && id !== previousStepId) {
|
|
2357
|
+
const htmlEl = el;
|
|
2358
|
+
blurFocusedDescendant(htmlEl);
|
|
2359
|
+
htmlEl.style.setProperty("display", "none", "important");
|
|
2360
|
+
htmlEl.setAttribute("aria-hidden", "true");
|
|
2361
|
+
htmlEl.setAttribute("inert", "");
|
|
2362
|
+
}
|
|
2363
|
+
});
|
|
2364
|
+
let restoreGridStack;
|
|
2365
|
+
if (incomingEl && outgoingEl && !prefersReducedMotion) {
|
|
2366
|
+
const container = incomingEl.parentElement;
|
|
2367
|
+
if (container) {
|
|
2368
|
+
restoreGridStack = applyGridStack(container, incomingEl, outgoingEl);
|
|
2369
|
+
}
|
|
2370
|
+
const transitionInBase = incomingEl.getAttribute("as-transition-in") || incomingEl.getAttribute("as-transition") || "fade";
|
|
2371
|
+
const transitionIn = resolvePreset(transitionInBase, "in");
|
|
2372
|
+
const distance = incomingEl.getAttribute("as-transition-distance") || "24px";
|
|
2373
|
+
const speedIn = incomingEl.getAttribute("as-transition-speed-in") || incomingEl.getAttribute("as-transition-speed");
|
|
2374
|
+
const presetIn = getPresetStyles(transitionIn, distance, "in");
|
|
2375
|
+
incomingEl.style.display = "";
|
|
2376
|
+
incomingEl.style.visibility = "hidden";
|
|
2377
|
+
incomingEl.setAttribute("aria-hidden", "true");
|
|
2378
|
+
incomingEl.setAttribute("inert", "");
|
|
2379
|
+
const prevTransitionProperty = incomingEl.style.transitionProperty;
|
|
2380
|
+
incomingEl.style.transitionProperty = "none";
|
|
2381
|
+
Object.assign(incomingEl.style, presetIn.initial);
|
|
2382
|
+
void incomingEl.offsetHeight;
|
|
2383
|
+
if (outgoingEl) {
|
|
2384
|
+
blurFocusedDescendant(outgoingEl);
|
|
2385
|
+
}
|
|
2386
|
+
hideStepWithTransition(outgoingEl, false);
|
|
2387
|
+
waitForTransitionEnd(outgoingEl, () => {
|
|
2388
|
+
setTimeout(() => {
|
|
2389
|
+
incomingEl.setAttribute("aria-hidden", "false");
|
|
2390
|
+
incomingEl.removeAttribute("inert");
|
|
2391
|
+
incomingEl.style.transitionProperty = "opacity, transform";
|
|
2392
|
+
incomingEl.style.transitionDuration = "300ms";
|
|
2393
|
+
if (speedIn) {
|
|
2394
|
+
applySpeedOverride(incomingEl, speedIn);
|
|
2395
|
+
}
|
|
2396
|
+
if (incomingEl.style.willChange !== "opacity, transform") {
|
|
2397
|
+
incomingEl.style.willChange = "opacity, transform";
|
|
2398
|
+
}
|
|
2399
|
+
incomingEl.style.visibility = "visible";
|
|
2400
|
+
Object.assign(incomingEl.style, presetIn.target);
|
|
2401
|
+
waitForTransitionEnd(incomingEl, () => {
|
|
2402
|
+
incomingEl.style.transitionDuration = "";
|
|
2403
|
+
incomingEl.style.transitionProperty = prevTransitionProperty;
|
|
2404
|
+
incomingEl.style.willChange = "";
|
|
2405
|
+
focusFirstInteractive(incomingEl);
|
|
2406
|
+
if (restoreGridStack) restoreGridStack();
|
|
2407
|
+
});
|
|
2408
|
+
}, STEP_TRANSITION_GAP_MS);
|
|
2409
|
+
});
|
|
2410
|
+
return;
|
|
2411
|
+
}
|
|
2412
|
+
if (incomingEl) {
|
|
2413
|
+
showStepWithTransition(incomingEl, prefersReducedMotion, focusFirstInteractive);
|
|
2414
|
+
}
|
|
2415
|
+
if (outgoingEl) {
|
|
2416
|
+
hideStepWithTransition(outgoingEl, prefersReducedMotion);
|
|
2417
|
+
}
|
|
2418
|
+
announceAria(`Step: ${stepId}`);
|
|
2419
|
+
import_loglevel6.default.debug(`[steps] \u2705 Step visible: "${stepId}"`);
|
|
2420
|
+
}
|
|
2421
|
+
function getNextStep(currentStepId) {
|
|
2422
|
+
const steps = Array.from(document.querySelectorAll("[as-step]"));
|
|
2423
|
+
const currentEl = document.querySelector(`[as-step="${currentStepId}"]`);
|
|
2424
|
+
const nextMap = currentEl?.getAttribute("as-next-map");
|
|
2425
|
+
if (nextMap) {
|
|
2426
|
+
import_loglevel6.default.debug(`[steps] \u{1F5FA}\uFE0F Evaluating next-map for conditional routing`);
|
|
2427
|
+
const answers = sessionStore.get().answers;
|
|
2428
|
+
const mappedStep = evaluateNextMap(nextMap, answers);
|
|
2429
|
+
if (mappedStep) {
|
|
2430
|
+
import_loglevel6.default.debug(`[steps] \u2713 Next-map resolved to: "${mappedStep}"`);
|
|
2431
|
+
return mappedStep;
|
|
2432
|
+
}
|
|
2433
|
+
import_loglevel6.default.debug(`[steps] \u26A0\uFE0F Next-map evaluation returned no match, falling back to linear`);
|
|
2434
|
+
}
|
|
2435
|
+
const idx = steps.findIndex((el) => el.getAttribute("as-step") === currentStepId);
|
|
2436
|
+
const nextStep = steps[idx + 1]?.getAttribute("as-step") || currentStepId;
|
|
2437
|
+
if (nextStep !== currentStepId) {
|
|
2438
|
+
import_loglevel6.default.debug(`[steps] \u{1F4CB} Linear next step: "${nextStep}"`);
|
|
2439
|
+
}
|
|
2440
|
+
return nextStep;
|
|
2441
|
+
}
|
|
2442
|
+
function attachNavigationHandlers(root) {
|
|
2443
|
+
root.querySelectorAll("[as-next]").forEach((btn) => {
|
|
2444
|
+
btn.addEventListener("click", (event) => {
|
|
2445
|
+
const trigger = event.currentTarget;
|
|
2446
|
+
void (async () => {
|
|
2447
|
+
const { current, path } = stepsStore.get();
|
|
2448
|
+
import_loglevel6.default.debug(`[steps] \u{1F537} Next button clicked on step: ${current}`);
|
|
2449
|
+
import_loglevel6.default.debug(`[steps] Validating step: ${current}`);
|
|
2450
|
+
const isValid = await validateStep(current);
|
|
2451
|
+
if (!isValid) {
|
|
2452
|
+
import_loglevel6.default.debug(`[steps] \u274C Validation failed, staying on step: ${current}`);
|
|
2453
|
+
return;
|
|
2454
|
+
}
|
|
2455
|
+
import_loglevel6.default.debug(`[steps] \u2713 Validation passed`);
|
|
2456
|
+
const nextId = getNextStep(current);
|
|
2457
|
+
if (nextId !== current) {
|
|
2458
|
+
import_loglevel6.default.debug(`[steps] \u27A1\uFE0F Navigating from "${current}" to "${nextId}"`);
|
|
2459
|
+
stepsStore.set({ current: nextId, path: [...path, nextId] });
|
|
2460
|
+
showStep(nextId, current);
|
|
2461
|
+
} else {
|
|
2462
|
+
import_loglevel6.default.debug(`[steps] \u{1F3C1} No next step found, checking for redirect`);
|
|
2463
|
+
await handleRedirect(current, trigger);
|
|
2464
|
+
}
|
|
2465
|
+
})();
|
|
2466
|
+
});
|
|
2467
|
+
});
|
|
2468
|
+
root.querySelectorAll("[as-back]").forEach((btn) => {
|
|
2469
|
+
btn.addEventListener("click", () => {
|
|
2470
|
+
const { current, path } = stepsStore.get();
|
|
2471
|
+
import_loglevel6.default.debug(`[steps] \u{1F519} Back button clicked on step: ${current}`);
|
|
2472
|
+
if (path.length > 1) {
|
|
2473
|
+
const newPath = path.slice(0, -1);
|
|
2474
|
+
const prevId = newPath[newPath.length - 1];
|
|
2475
|
+
if (prevId) {
|
|
2476
|
+
import_loglevel6.default.debug(`[steps] \u2B05\uFE0F Navigating back from "${current}" to "${prevId}"`);
|
|
2477
|
+
stepsStore.set({ current: prevId, path: newPath });
|
|
2478
|
+
showStep(prevId, current);
|
|
2479
|
+
}
|
|
2480
|
+
} else {
|
|
2481
|
+
import_loglevel6.default.debug(`[steps] \u26A0\uFE0F Cannot go back, already at first step`);
|
|
2482
|
+
}
|
|
2483
|
+
});
|
|
2484
|
+
});
|
|
2485
|
+
root.querySelectorAll("[as-goto]").forEach((btn) => {
|
|
2486
|
+
btn.addEventListener("click", (event) => {
|
|
2487
|
+
const targetId = btn.getAttribute("as-goto");
|
|
2488
|
+
if (!targetId || targetId.trim() === "") return;
|
|
2489
|
+
const target = event.currentTarget;
|
|
2490
|
+
const { current } = stepsStore.get();
|
|
2491
|
+
import_loglevel6.default.debug(
|
|
2492
|
+
`[steps] \u{1F3AF} Goto clicked on step "${current}", target: "${targetId}" (element: ${target.tagName})`
|
|
2493
|
+
);
|
|
2494
|
+
const existingController = gotoAbortControllers.get(btn);
|
|
2495
|
+
if (existingController) {
|
|
2496
|
+
existingController.abort();
|
|
2497
|
+
import_loglevel6.default.debug(`[steps] \u23F1\uFE0F Aborted previous goto timeout`);
|
|
2498
|
+
}
|
|
2499
|
+
const controller = new AbortController();
|
|
2500
|
+
gotoAbortControllers.set(btn, controller);
|
|
2501
|
+
const isButton = target.tagName === "BUTTON" || target.tagName === "A";
|
|
2502
|
+
const isLink = target.tagName === "A";
|
|
2503
|
+
const delay = isButton || isLink ? 0 : 250;
|
|
2504
|
+
const executeGoto = () => {
|
|
2505
|
+
if (controller.signal.aborted) {
|
|
2506
|
+
import_loglevel6.default.debug(`[steps] \u23F1\uFE0F Goto aborted, skipping navigation`);
|
|
2507
|
+
return;
|
|
2508
|
+
}
|
|
2509
|
+
const { current: current2, path } = stepsStore.get();
|
|
2510
|
+
const targetEl = document.querySelector(`[as-step="${targetId}"]`);
|
|
2511
|
+
if (!targetEl) {
|
|
2512
|
+
import_loglevel6.default.warn(`[steps] \u274C Target step not found: ${targetId}`);
|
|
2513
|
+
return;
|
|
2514
|
+
}
|
|
2515
|
+
import_loglevel6.default.debug(`[steps] \u2197\uFE0F Goto navigating from "${current2}" to "${targetId}"`);
|
|
2516
|
+
stepsStore.set({ current: targetId, path: [...path, targetId] });
|
|
2517
|
+
showStep(targetId, current2);
|
|
2518
|
+
};
|
|
2519
|
+
if (delay > 0) {
|
|
2520
|
+
import_loglevel6.default.debug(`[steps] \u23F1\uFE0F Debouncing goto by ${delay}ms`);
|
|
2521
|
+
const timeoutId = setTimeout(executeGoto, delay);
|
|
2522
|
+
controller.signal.addEventListener("abort", () => {
|
|
2523
|
+
clearTimeout(timeoutId);
|
|
2524
|
+
});
|
|
2525
|
+
} else {
|
|
2526
|
+
executeGoto();
|
|
2527
|
+
}
|
|
2528
|
+
});
|
|
2529
|
+
});
|
|
2530
|
+
root.querySelectorAll("[as-restart]").forEach((btn) => {
|
|
2531
|
+
btn.addEventListener("click", () => {
|
|
2532
|
+
import_loglevel6.default.debug(`[steps] \u{1F504} Restart button clicked, resetting survey`);
|
|
2533
|
+
window.agera?.survey?.reset();
|
|
2534
|
+
});
|
|
2535
|
+
});
|
|
2536
|
+
}
|
|
2537
|
+
function getStepPosition(stepId) {
|
|
2538
|
+
if (typeof document === "undefined") return 1;
|
|
2539
|
+
const steps = Array.from(document.querySelectorAll("[as-step]"));
|
|
2540
|
+
const index = steps.findIndex((el) => el.getAttribute("as-step") === stepId);
|
|
2541
|
+
return index >= 0 ? index + 1 : 1;
|
|
2542
|
+
}
|
|
2543
|
+
|
|
2544
|
+
// src/features/components/index.ts
|
|
2545
|
+
var import_loglevel9 = __toESM(require_loglevel(), 1);
|
|
2546
|
+
|
|
2547
|
+
// src/features/components/radio-other-input.ts
|
|
2548
|
+
var import_loglevel7 = __toESM(require_loglevel(), 1);
|
|
2549
|
+
|
|
2550
|
+
// src/features/components/helpers.ts
|
|
2551
|
+
function getStepScope(element, fallback = document) {
|
|
2552
|
+
return element.closest("[as-step]") || fallback;
|
|
2553
|
+
}
|
|
2554
|
+
function parseValidationRules(attributeValue) {
|
|
2555
|
+
if (!attributeValue) return [];
|
|
2556
|
+
return attributeValue.split("|").map((s) => s.trim()).filter(Boolean);
|
|
2557
|
+
}
|
|
2558
|
+
function hasValidationRule(attributeValue, rule) {
|
|
2559
|
+
return parseValidationRules(attributeValue).includes(rule);
|
|
2560
|
+
}
|
|
2561
|
+
function isRadioGroupRequired(radios) {
|
|
2562
|
+
return Array.from(radios).some(
|
|
2563
|
+
(radio) => hasValidationRule(radio.getAttribute("as-validate"), "required")
|
|
2564
|
+
);
|
|
2565
|
+
}
|
|
2566
|
+
function isBooleanLikeString(value) {
|
|
2567
|
+
return ["true", "false", ""].includes(value.toLowerCase());
|
|
2568
|
+
}
|
|
2569
|
+
function findRadiosByGroup(scope, groupName) {
|
|
2570
|
+
return scope.querySelectorAll(`input[type="radio"][name="${groupName}"]`);
|
|
2571
|
+
}
|
|
2572
|
+
function setValidationRules(input, rules) {
|
|
2573
|
+
if (rules.length > 0) {
|
|
2574
|
+
input.setAttribute("as-validate", rules.join("|"));
|
|
2575
|
+
} else {
|
|
2576
|
+
input.removeAttribute("as-validate");
|
|
2577
|
+
}
|
|
2578
|
+
}
|
|
2579
|
+
function findElementsWithAttribute(root, attrName, inputSelector = "input, select, textarea") {
|
|
2580
|
+
const results = [];
|
|
2581
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2582
|
+
const inputWithAttrSelector = inputSelector.split(",").map((s) => `${s.trim()}[${attrName}]`).join(", ");
|
|
2583
|
+
root.querySelectorAll(inputWithAttrSelector).forEach((input) => {
|
|
2584
|
+
if (!seen.has(input)) {
|
|
2585
|
+
seen.add(input);
|
|
2586
|
+
results.push({ attrElement: input, input });
|
|
2587
|
+
}
|
|
2588
|
+
});
|
|
2589
|
+
root.querySelectorAll(`label[${attrName}]`).forEach((label) => {
|
|
2590
|
+
const input = label.querySelector(inputSelector);
|
|
2591
|
+
if (input && !seen.has(input)) {
|
|
2592
|
+
seen.add(input);
|
|
2593
|
+
results.push({ attrElement: label, input });
|
|
2594
|
+
}
|
|
2595
|
+
});
|
|
2596
|
+
return results;
|
|
2597
|
+
}
|
|
2598
|
+
|
|
2599
|
+
// src/features/components/radio-other-input.ts
|
|
2600
|
+
function setupRadioOtherInput(container) {
|
|
2601
|
+
const root = container || document;
|
|
2602
|
+
root.querySelectorAll("[as-radio-other-input]").forEach((input) => {
|
|
2603
|
+
const inputEl = input;
|
|
2604
|
+
const stepRoot = getStepScope(inputEl, root);
|
|
2605
|
+
let groupName = input.getAttribute("as-radio-other-input") || "";
|
|
2606
|
+
let otherRadio = null;
|
|
2607
|
+
if (isBooleanLikeString(groupName)) {
|
|
2608
|
+
groupName = "";
|
|
2609
|
+
}
|
|
2610
|
+
if (groupName) {
|
|
2611
|
+
otherRadio = findOtherRadioByGroupName(stepRoot, groupName);
|
|
2612
|
+
if (otherRadio) {
|
|
2613
|
+
groupName = otherRadio.name;
|
|
2614
|
+
}
|
|
2615
|
+
} else {
|
|
2616
|
+
otherRadio = findClosestOtherRadio(inputEl, stepRoot);
|
|
2617
|
+
if (otherRadio) groupName = otherRadio.name;
|
|
2618
|
+
}
|
|
2619
|
+
if (!otherRadio || !groupName) {
|
|
2620
|
+
import_loglevel7.default.debug("[components:radio-other-input] 'other' radio not found near input", inputEl);
|
|
2621
|
+
return;
|
|
2622
|
+
}
|
|
2623
|
+
const allRadios = findRadiosByGroup(stepRoot, groupName);
|
|
2624
|
+
setupOtherInput(inputEl, otherRadio, allRadios);
|
|
2625
|
+
});
|
|
2626
|
+
import_loglevel7.default.debug("[components:radio-other-input] Initialized");
|
|
2627
|
+
}
|
|
2628
|
+
function findOtherRadioByGroupName(scope, groupName) {
|
|
2629
|
+
const allOtherRadios = scope.querySelectorAll(
|
|
2630
|
+
'input[type="radio"][value="other"]'
|
|
2631
|
+
);
|
|
2632
|
+
for (const radio of allOtherRadios) {
|
|
2633
|
+
if (radio.name.toLowerCase() === groupName.toLowerCase()) {
|
|
2634
|
+
return radio;
|
|
2635
|
+
}
|
|
2636
|
+
}
|
|
2637
|
+
return null;
|
|
2638
|
+
}
|
|
2639
|
+
function findClosestOtherRadio(inputEl, stepRoot) {
|
|
2640
|
+
let current = inputEl.parentElement;
|
|
2641
|
+
while (current && current !== stepRoot.parentElement) {
|
|
2642
|
+
const candidate = current.querySelector('input[type="radio"][value="other"]');
|
|
2643
|
+
if (candidate) return candidate;
|
|
2644
|
+
current = current.parentElement;
|
|
2645
|
+
}
|
|
2646
|
+
return stepRoot.querySelector('input[type="radio"][value="other"]');
|
|
2647
|
+
}
|
|
2648
|
+
function setupOtherInput(inputEl, otherRadio, allRadios) {
|
|
2649
|
+
inputEl.removeAttribute("name");
|
|
2650
|
+
const originalAsValidate = inputEl.getAttribute("as-validate");
|
|
2651
|
+
const originalRequired = inputEl.hasAttribute("required");
|
|
2652
|
+
const originalHasRequiredRule = hasValidationRule(originalAsValidate, "required");
|
|
2653
|
+
const groupHasRequired = isRadioGroupRequired(allRadios);
|
|
2654
|
+
const hasOtherRequiredAttr = inputEl.hasAttribute("as-radio-other-required");
|
|
2655
|
+
const enforceRequired = groupHasRequired || hasOtherRequiredAttr;
|
|
2656
|
+
const syncOtherValue = () => {
|
|
2657
|
+
const v = inputEl.value.trim();
|
|
2658
|
+
otherRadio.value = v || "other";
|
|
2659
|
+
};
|
|
2660
|
+
const applyConditionalRequired = () => {
|
|
2661
|
+
if (!enforceRequired) return;
|
|
2662
|
+
if (otherRadio.checked) {
|
|
2663
|
+
const base = parseValidationRules(originalAsValidate);
|
|
2664
|
+
if (!base.includes("required")) base.push("required");
|
|
2665
|
+
setValidationRules(inputEl, base);
|
|
2666
|
+
inputEl.setAttribute("required", "");
|
|
2667
|
+
} else {
|
|
2668
|
+
if (originalAsValidate !== null) {
|
|
2669
|
+
if (originalHasRequiredRule) {
|
|
2670
|
+
inputEl.setAttribute("as-validate", originalAsValidate);
|
|
2671
|
+
} else {
|
|
2672
|
+
const cur = parseValidationRules(inputEl.getAttribute("as-validate")).filter(
|
|
2673
|
+
(r) => r !== "required"
|
|
2674
|
+
);
|
|
2675
|
+
setValidationRules(inputEl, cur);
|
|
2676
|
+
}
|
|
2677
|
+
} else {
|
|
2678
|
+
const cur = parseValidationRules(inputEl.getAttribute("as-validate")).filter(
|
|
2679
|
+
(r) => r !== "required"
|
|
2680
|
+
);
|
|
2681
|
+
setValidationRules(inputEl, cur);
|
|
2682
|
+
}
|
|
2683
|
+
if (!originalRequired) inputEl.removeAttribute("required");
|
|
2684
|
+
}
|
|
2685
|
+
};
|
|
2686
|
+
allRadios.forEach((radio) => {
|
|
2687
|
+
radio.addEventListener("change", () => {
|
|
2688
|
+
if (radio === otherRadio && otherRadio.checked) {
|
|
2689
|
+
syncOtherValue();
|
|
2690
|
+
setTimeout(() => {
|
|
2691
|
+
inputEl.focus();
|
|
2692
|
+
}, 0);
|
|
2693
|
+
}
|
|
2694
|
+
applyConditionalRequired();
|
|
2695
|
+
});
|
|
2696
|
+
});
|
|
2697
|
+
const ensureOtherSelected = () => {
|
|
2698
|
+
if (!otherRadio.checked) {
|
|
2699
|
+
otherRadio.checked = true;
|
|
2700
|
+
otherRadio.dispatchEvent(new Event("change", { bubbles: true }));
|
|
2701
|
+
}
|
|
2702
|
+
};
|
|
2703
|
+
inputEl.addEventListener("click", ensureOtherSelected);
|
|
2704
|
+
inputEl.addEventListener("focus", ensureOtherSelected);
|
|
2705
|
+
inputEl.addEventListener("input", syncOtherValue);
|
|
2706
|
+
inputEl.addEventListener("change", syncOtherValue);
|
|
2707
|
+
inputEl.addEventListener("blur", syncOtherValue);
|
|
2708
|
+
syncOtherValue();
|
|
2709
|
+
applyConditionalRequired();
|
|
2710
|
+
}
|
|
2711
|
+
|
|
2712
|
+
// src/features/components/phone-format.ts
|
|
2713
|
+
var import_loglevel8 = __toESM(require_loglevel(), 1);
|
|
2714
|
+
function setupPhoneFormatting(container) {
|
|
2715
|
+
const root = container || document;
|
|
2716
|
+
root.querySelectorAll("[as-phone-format]").forEach((input) => {
|
|
2717
|
+
const region = input.getAttribute("as-phone-region") || void 0;
|
|
2718
|
+
const format = input.getAttribute("as-phone-format") || "INTERNATIONAL";
|
|
2719
|
+
let asYouTypeInstance = null;
|
|
2720
|
+
let hasPrefilled = false;
|
|
2721
|
+
void initializeAsYouType(region).then((instance) => {
|
|
2722
|
+
asYouTypeInstance = instance;
|
|
2723
|
+
});
|
|
2724
|
+
input.addEventListener("focus", () => {
|
|
2725
|
+
void handlePhoneFocus(input, format, region, hasPrefilled, (value) => {
|
|
2726
|
+
hasPrefilled = value;
|
|
2727
|
+
});
|
|
2728
|
+
});
|
|
2729
|
+
input.addEventListener("input", () => {
|
|
2730
|
+
void handlePhoneInput(input, region, asYouTypeInstance, (instance) => {
|
|
2731
|
+
asYouTypeInstance = instance;
|
|
2732
|
+
});
|
|
2733
|
+
});
|
|
2734
|
+
input.addEventListener("blur", () => {
|
|
2735
|
+
void handlePhoneBlur(input, format, region);
|
|
2736
|
+
});
|
|
2737
|
+
});
|
|
2738
|
+
import_loglevel8.default.debug("[components:phone-format] Initialized");
|
|
2739
|
+
}
|
|
2740
|
+
async function initializeAsYouType(region) {
|
|
2741
|
+
try {
|
|
2742
|
+
const AsYouType = await getAsYouType();
|
|
2743
|
+
if (!AsYouType) return null;
|
|
2744
|
+
return new AsYouType(region);
|
|
2745
|
+
} catch (error) {
|
|
2746
|
+
import_loglevel8.default.warn("[components:phone-format] Failed to initialize AsYouType:", error);
|
|
2747
|
+
return null;
|
|
2748
|
+
}
|
|
2749
|
+
}
|
|
2750
|
+
async function handlePhoneFocus(input, format, region, hasPrefilled, setHasPrefilled) {
|
|
2751
|
+
if (hasPrefilled || input.value.trim()) {
|
|
2752
|
+
import_loglevel8.default.debug("[components:phone-format] Skipping prefill - already prefilled or has value");
|
|
2753
|
+
return;
|
|
2754
|
+
}
|
|
2755
|
+
try {
|
|
2756
|
+
import_loglevel8.default.debug(
|
|
2757
|
+
"[components:phone-format] Focus handler triggered, format:",
|
|
2758
|
+
format,
|
|
2759
|
+
"region:",
|
|
2760
|
+
region
|
|
2761
|
+
);
|
|
2762
|
+
if (format.toUpperCase() !== "INTERNATIONAL") {
|
|
2763
|
+
import_loglevel8.default.debug("[components:phone-format] Format is not INTERNATIONAL, skipping prefill");
|
|
2764
|
+
return;
|
|
2765
|
+
}
|
|
2766
|
+
if (!region) {
|
|
2767
|
+
import_loglevel8.default.debug("[components:phone-format] No region specified, skipping prefill");
|
|
2768
|
+
return;
|
|
2769
|
+
}
|
|
2770
|
+
import_loglevel8.default.debug("[components:phone-format] Loading phone library...");
|
|
2771
|
+
const getCountryCallingCode = await getGetCountryCallingCode();
|
|
2772
|
+
if (!getCountryCallingCode) {
|
|
2773
|
+
import_loglevel8.default.warn("[components:phone-format] Phone library not available");
|
|
2774
|
+
return;
|
|
2775
|
+
}
|
|
2776
|
+
if (input.value.trim()) {
|
|
2777
|
+
import_loglevel8.default.debug("[components:phone-format] Field now has value, skipping prefill");
|
|
2778
|
+
return;
|
|
2779
|
+
}
|
|
2780
|
+
import_loglevel8.default.debug("[components:phone-format] Getting calling code for region:", region);
|
|
2781
|
+
const callingCode = getCountryCallingCode(region);
|
|
2782
|
+
import_loglevel8.default.debug("[components:phone-format] Calling code:", callingCode);
|
|
2783
|
+
if (callingCode) {
|
|
2784
|
+
input.value = "+" + callingCode + " ";
|
|
2785
|
+
setHasPrefilled(true);
|
|
2786
|
+
import_loglevel8.default.debug("[components:phone-format] Prefilled country code:", input.value);
|
|
2787
|
+
input.setSelectionRange(input.value.length, input.value.length);
|
|
2788
|
+
} else {
|
|
2789
|
+
import_loglevel8.default.warn("[components:phone-format] Could not get calling code for region:", region);
|
|
2790
|
+
}
|
|
2791
|
+
} catch (error) {
|
|
2792
|
+
import_loglevel8.default.error("[components:phone-format] Failed to prefill country code:", error);
|
|
2793
|
+
}
|
|
2794
|
+
}
|
|
2795
|
+
async function handlePhoneInput(input, region, asYouTypeInstance, setAsYouTypeInstance) {
|
|
2796
|
+
try {
|
|
2797
|
+
if (!asYouTypeInstance) {
|
|
2798
|
+
const instance = await initializeAsYouType(region);
|
|
2799
|
+
if (!instance) return;
|
|
2800
|
+
setAsYouTypeInstance(instance);
|
|
2801
|
+
asYouTypeInstance = instance;
|
|
2802
|
+
}
|
|
2803
|
+
const cursorPosition = input.selectionStart || 0;
|
|
2804
|
+
const value = input.value;
|
|
2805
|
+
asYouTypeInstance.reset();
|
|
2806
|
+
const formatted = asYouTypeInstance.input(value);
|
|
2807
|
+
if (formatted !== value) {
|
|
2808
|
+
input.value = formatted;
|
|
2809
|
+
const diff = formatted.length - value.length;
|
|
2810
|
+
const newPosition = Math.max(0, Math.min(cursorPosition + diff, formatted.length));
|
|
2811
|
+
input.setSelectionRange(newPosition, newPosition);
|
|
2812
|
+
}
|
|
2813
|
+
} catch (error) {
|
|
2814
|
+
import_loglevel8.default.warn("[components:phone-format] Failed to auto-format phone number:", error);
|
|
2815
|
+
}
|
|
2816
|
+
}
|
|
2817
|
+
async function handlePhoneBlur(input, format, region) {
|
|
2818
|
+
try {
|
|
2819
|
+
const value = input.value.trim();
|
|
2820
|
+
if (!value) return;
|
|
2821
|
+
const parsePhoneNumberFromString = await getParsePhoneNumberFromString();
|
|
2822
|
+
if (!parsePhoneNumberFromString) return;
|
|
2823
|
+
let parsed = parsePhoneNumberFromString(value);
|
|
2824
|
+
if (!parsed && region) {
|
|
2825
|
+
parsed = parsePhoneNumberFromString(value, region);
|
|
2826
|
+
}
|
|
2827
|
+
if (parsed && parsed.isValid && parsed.isValid()) {
|
|
2828
|
+
const formatted = formatPhoneNumber(parsed, format, value);
|
|
2829
|
+
input.value = formatted;
|
|
2830
|
+
}
|
|
2831
|
+
} catch (error) {
|
|
2832
|
+
import_loglevel8.default.warn("[components:phone-format] Failed to format phone number on blur:", error);
|
|
2833
|
+
}
|
|
2834
|
+
}
|
|
2835
|
+
function formatPhoneNumber(parsed, format, fallback) {
|
|
2836
|
+
switch (format.toUpperCase()) {
|
|
2837
|
+
case "E164":
|
|
2838
|
+
return parsed.format ? parsed.format("E.164") : fallback;
|
|
2839
|
+
case "NATIONAL":
|
|
2840
|
+
return parsed.formatNational ? parsed.formatNational() : fallback;
|
|
2841
|
+
case "INTERNATIONAL":
|
|
2842
|
+
default:
|
|
2843
|
+
if (parsed.formatInternational) {
|
|
2844
|
+
const properFormat = parsed.formatInternational();
|
|
2845
|
+
if (fallback.replace(/\s/g, "") === properFormat.replace(/\s/g, "")) {
|
|
2846
|
+
return properFormat;
|
|
2847
|
+
}
|
|
2848
|
+
}
|
|
2849
|
+
return fallback;
|
|
2850
|
+
}
|
|
2851
|
+
}
|
|
2852
|
+
|
|
2853
|
+
// src/features/components/index.ts
|
|
2854
|
+
function initComponents(root) {
|
|
2855
|
+
setupRadioOtherInput(root);
|
|
2856
|
+
setupPhoneFormatting(root);
|
|
2857
|
+
import_loglevel9.default.debug("[components] Initialized");
|
|
2858
|
+
}
|
|
2859
|
+
|
|
2860
|
+
// src/features/progress.ts
|
|
2861
|
+
var import_loglevel10 = __toESM(require_loglevel(), 1);
|
|
2862
|
+
function initProgress(_root) {
|
|
2863
|
+
stepsStore.subscribe(() => updateProgress());
|
|
2864
|
+
updateProgress();
|
|
2865
|
+
import_loglevel10.default.debug("[progress] Initialized");
|
|
2866
|
+
}
|
|
2867
|
+
function updateProgress() {
|
|
2868
|
+
if (typeof document === "undefined") return;
|
|
2869
|
+
const { current } = stepsStore.get();
|
|
2870
|
+
const steps = Array.from(document.querySelectorAll("[as-step]"));
|
|
2871
|
+
const total = steps.length;
|
|
2872
|
+
const currentIdx = steps.findIndex((el) => el.getAttribute("as-step") === current);
|
|
2873
|
+
document.querySelectorAll('[as-progress="bar"]').forEach((el) => {
|
|
2874
|
+
let bar = el.querySelector(".as-progress-bar");
|
|
2875
|
+
if (!bar) {
|
|
2876
|
+
bar = document.createElement("div");
|
|
2877
|
+
bar.className = "as-progress-bar";
|
|
2878
|
+
el.appendChild(bar);
|
|
2879
|
+
}
|
|
2880
|
+
bar.style.width = `${(currentIdx + 1) / total * 100}%`;
|
|
2881
|
+
});
|
|
2882
|
+
document.querySelectorAll('[as-progress="fraction"]').forEach((el) => {
|
|
2883
|
+
el.textContent = `${currentIdx + 1} / ${total}`;
|
|
2884
|
+
});
|
|
2885
|
+
document.querySelectorAll('[as-progress="steps"]').forEach((el) => {
|
|
2886
|
+
el.innerHTML = steps.map((_, idx) => {
|
|
2887
|
+
const status = idx < currentIdx ? "completed" : idx === currentIdx ? "current" : "pending";
|
|
2888
|
+
return `<span class="as-step-dot ${status}"></span>`;
|
|
2889
|
+
}).join("");
|
|
2890
|
+
});
|
|
2891
|
+
}
|
|
2892
|
+
|
|
2893
|
+
// src/features/quiz.ts
|
|
2894
|
+
var import_loglevel11 = __toESM(require_loglevel(), 1);
|
|
2895
|
+
function initQuiz(root) {
|
|
2896
|
+
if (!root.hasAttribute("as-quiz")) {
|
|
2897
|
+
import_loglevel11.default.debug("[quiz] Quiz mode not enabled");
|
|
2898
|
+
return;
|
|
2899
|
+
}
|
|
2900
|
+
import_loglevel11.default.info("[quiz] Initializing quiz mode");
|
|
2901
|
+
updateQuizScores(root);
|
|
2902
|
+
attachAnswerListeners(root);
|
|
2903
|
+
updateQuizDisplayElements();
|
|
2904
|
+
sessionStore.subscribe(() => {
|
|
2905
|
+
updateQuizDisplayElements();
|
|
2906
|
+
});
|
|
2907
|
+
import_loglevel11.default.debug("[quiz] Quiz mode initialized");
|
|
2908
|
+
}
|
|
2909
|
+
function attachAnswerListeners(root) {
|
|
2910
|
+
const inputs = root.querySelectorAll(
|
|
2911
|
+
"input, select, textarea"
|
|
2912
|
+
);
|
|
2913
|
+
inputs.forEach((input) => {
|
|
2914
|
+
input.addEventListener("change", () => {
|
|
2915
|
+
import_loglevel11.default.debug("[quiz] Answer changed, recalculating scores");
|
|
2916
|
+
updateQuizScores(root);
|
|
2917
|
+
});
|
|
2918
|
+
});
|
|
2919
|
+
}
|
|
2920
|
+
function updateQuizScores(root) {
|
|
2921
|
+
const scores = {};
|
|
2922
|
+
const weightedElements = findElementsWithAttribute(root, "as-weight");
|
|
2923
|
+
weightedElements.forEach(({ attrElement, input }) => {
|
|
2924
|
+
const weightAttr = attrElement.getAttribute("as-weight");
|
|
2925
|
+
if (!weightAttr) return;
|
|
2926
|
+
try {
|
|
2927
|
+
const weights = JSON.parse(weightAttr);
|
|
2928
|
+
const shouldCount = shouldInputContribute(input);
|
|
2929
|
+
if (shouldCount) {
|
|
2930
|
+
for (const [category, weight] of Object.entries(weights)) {
|
|
2931
|
+
if (typeof weight === "number" && weight > 0) {
|
|
2932
|
+
scores[category] = (scores[category] || 0) + weight;
|
|
2933
|
+
}
|
|
2934
|
+
}
|
|
2935
|
+
}
|
|
2936
|
+
} catch (error) {
|
|
2937
|
+
import_loglevel11.default.warn("[quiz] Invalid as-weight JSON:", attrElement, error);
|
|
2938
|
+
}
|
|
2939
|
+
});
|
|
2940
|
+
const selectedOptions = root.querySelectorAll("option[as-weight]:checked");
|
|
2941
|
+
selectedOptions.forEach((option) => {
|
|
2942
|
+
const weightAttr = option.getAttribute("as-weight");
|
|
2943
|
+
if (!weightAttr) return;
|
|
2944
|
+
try {
|
|
2945
|
+
const weights = JSON.parse(weightAttr);
|
|
2946
|
+
for (const [category, weight] of Object.entries(weights)) {
|
|
2947
|
+
if (typeof weight === "number" && weight > 0) {
|
|
2948
|
+
scores[category] = (scores[category] || 0) + weight;
|
|
2949
|
+
}
|
|
2950
|
+
}
|
|
2951
|
+
} catch (error) {
|
|
2952
|
+
import_loglevel11.default.warn("[quiz] Invalid as-weight JSON on option:", option, error);
|
|
2953
|
+
}
|
|
2954
|
+
});
|
|
2955
|
+
const results = calculateWinner(scores);
|
|
2956
|
+
const session = sessionStore.get();
|
|
2957
|
+
const updatedAnswers = {
|
|
2958
|
+
...session.answers,
|
|
2959
|
+
__quiz__: results
|
|
2960
|
+
};
|
|
2961
|
+
sessionStore.set({
|
|
2962
|
+
...session,
|
|
2963
|
+
quiz: results,
|
|
2964
|
+
answers: updatedAnswers
|
|
2965
|
+
});
|
|
2966
|
+
import_loglevel11.default.debug("[quiz] Scores updated:", results);
|
|
2967
|
+
}
|
|
2968
|
+
function shouldInputContribute(input) {
|
|
2969
|
+
if (input instanceof HTMLInputElement && input.type === "radio") {
|
|
2970
|
+
return input.checked;
|
|
2971
|
+
}
|
|
2972
|
+
if (input instanceof HTMLInputElement && input.type === "checkbox") {
|
|
2973
|
+
return input.checked;
|
|
2974
|
+
}
|
|
2975
|
+
if (input instanceof HTMLInputElement && input.hasAttribute("as-radio-other-input")) {
|
|
2976
|
+
const otherRadio = findAssociatedOtherRadio(input);
|
|
2977
|
+
return otherRadio?.checked === true && input.value.trim() !== "";
|
|
2978
|
+
}
|
|
2979
|
+
if (input instanceof HTMLInputElement || input instanceof HTMLTextAreaElement) {
|
|
2980
|
+
return input.value.trim() !== "";
|
|
2981
|
+
}
|
|
2982
|
+
if (input instanceof HTMLSelectElement) {
|
|
2983
|
+
return input.value !== "";
|
|
2984
|
+
}
|
|
2985
|
+
return false;
|
|
2986
|
+
}
|
|
2987
|
+
function findAssociatedOtherRadio(input) {
|
|
2988
|
+
const groupAttr = input.getAttribute("as-radio-other-input");
|
|
2989
|
+
const stepScope = input.closest("[as-step]") || document;
|
|
2990
|
+
if (groupAttr && groupAttr !== "" && groupAttr !== "true") {
|
|
2991
|
+
const radios = Array.from(
|
|
2992
|
+
stepScope.querySelectorAll(`input[type="radio"]`)
|
|
2993
|
+
).filter((r) => r.name.toLowerCase() === groupAttr.toLowerCase());
|
|
2994
|
+
return radios.find((r) => r.checked) || radios[radios.length - 1] || null;
|
|
2995
|
+
}
|
|
2996
|
+
let current = input.parentElement;
|
|
2997
|
+
while (current && current !== stepScope) {
|
|
2998
|
+
const radio = current.querySelector('input[type="radio"]');
|
|
2999
|
+
if (radio) return radio;
|
|
3000
|
+
current = current.parentElement;
|
|
3001
|
+
}
|
|
3002
|
+
return null;
|
|
3003
|
+
}
|
|
3004
|
+
function calculateWinner(scores) {
|
|
3005
|
+
const categories = Object.keys(scores);
|
|
3006
|
+
if (categories.length === 0) {
|
|
3007
|
+
return {
|
|
3008
|
+
scores: {},
|
|
3009
|
+
winner: null,
|
|
3010
|
+
winnerScore: 0,
|
|
3011
|
+
ties: []
|
|
3012
|
+
};
|
|
3013
|
+
}
|
|
3014
|
+
const maxScore = Math.max(...Object.values(scores));
|
|
3015
|
+
const winners = categories.filter((cat) => scores[cat] === maxScore);
|
|
3016
|
+
if (winners.length === 1) {
|
|
3017
|
+
return {
|
|
3018
|
+
scores,
|
|
3019
|
+
winner: winners[0],
|
|
3020
|
+
winnerScore: maxScore,
|
|
3021
|
+
ties: []
|
|
3022
|
+
};
|
|
3023
|
+
}
|
|
3024
|
+
return {
|
|
3025
|
+
scores,
|
|
3026
|
+
winner: winners[0],
|
|
3027
|
+
winnerScore: maxScore,
|
|
3028
|
+
ties: winners
|
|
3029
|
+
};
|
|
3030
|
+
}
|
|
3031
|
+
function updateQuizDisplayElements() {
|
|
3032
|
+
const session = sessionStore.get();
|
|
3033
|
+
const quiz = session.quiz;
|
|
3034
|
+
if (!quiz) return;
|
|
3035
|
+
document.querySelectorAll("[as-quiz-category]").forEach((el) => {
|
|
3036
|
+
const categoryAttr = el.getAttribute("as-quiz-category");
|
|
3037
|
+
if (!categoryAttr || categoryAttr === "" || categoryAttr === "true") {
|
|
3038
|
+
el.textContent = quiz.winner || "";
|
|
3039
|
+
} else {
|
|
3040
|
+
el.textContent = quiz.winner === categoryAttr ? categoryAttr : "";
|
|
3041
|
+
}
|
|
3042
|
+
});
|
|
3043
|
+
document.querySelectorAll("[as-quiz-score]").forEach((el) => {
|
|
3044
|
+
const categoryAttr = el.getAttribute("as-quiz-score");
|
|
3045
|
+
if (!categoryAttr || categoryAttr === "" || categoryAttr === "true") {
|
|
3046
|
+
el.textContent = String(quiz.winnerScore);
|
|
3047
|
+
} else if (categoryAttr === "all") {
|
|
3048
|
+
el.textContent = JSON.stringify(quiz.scores);
|
|
3049
|
+
} else {
|
|
3050
|
+
const score = quiz.scores[categoryAttr] || 0;
|
|
3051
|
+
el.textContent = String(score);
|
|
3052
|
+
}
|
|
3053
|
+
});
|
|
3054
|
+
}
|
|
3055
|
+
function getQuizResults() {
|
|
3056
|
+
const session = sessionStore.get();
|
|
3057
|
+
return session.quiz || null;
|
|
3058
|
+
}
|
|
3059
|
+
function getQuizScores() {
|
|
3060
|
+
const results = getQuizResults();
|
|
3061
|
+
return results?.scores || {};
|
|
3062
|
+
}
|
|
3063
|
+
function getQuizWinner() {
|
|
3064
|
+
const results = getQuizResults();
|
|
3065
|
+
return results?.winner || null;
|
|
3066
|
+
}
|
|
3067
|
+
|
|
3068
|
+
// src/core/prehide.ts
|
|
3069
|
+
var import_loglevel12 = __toESM(require_loglevel(), 1);
|
|
3070
|
+
var observer = null;
|
|
3071
|
+
var isInitComplete = false;
|
|
3072
|
+
function injectPreCSS() {
|
|
3073
|
+
if (typeof document === "undefined") return;
|
|
3074
|
+
if (document.getElementById("as-pre-css")) return;
|
|
3075
|
+
const style = document.createElement("style");
|
|
3076
|
+
style.id = "as-pre-css";
|
|
3077
|
+
style.textContent = `[as-step]~[as-step]{display:none!important;}[as-error-for]:not([data-as-error-active="true"]){display:none;}`;
|
|
3078
|
+
const head = document.head || document.getElementsByTagName("head")[0] || document.documentElement;
|
|
3079
|
+
head.insertBefore(style, head.firstChild);
|
|
3080
|
+
import_loglevel12.default.debug("[prehide] Injected pre-CSS to hide non-first steps");
|
|
3081
|
+
}
|
|
3082
|
+
function startPrehide() {
|
|
3083
|
+
if (typeof document === "undefined") return;
|
|
3084
|
+
injectPreCSS();
|
|
3085
|
+
function prehideStep(el, index) {
|
|
3086
|
+
const htmlEl = el;
|
|
3087
|
+
if (index === 0) return;
|
|
3088
|
+
htmlEl.style.display = "none";
|
|
3089
|
+
htmlEl.setAttribute("aria-hidden", "true");
|
|
3090
|
+
htmlEl.setAttribute("inert", "");
|
|
3091
|
+
}
|
|
3092
|
+
const steps = document.querySelectorAll("[as-step]");
|
|
3093
|
+
steps.forEach((step, index) => prehideStep(step, index));
|
|
3094
|
+
if (steps.length > 0) {
|
|
3095
|
+
import_loglevel12.default.debug(`[prehide] Hidden ${steps.length - 1} non-first steps before paint`);
|
|
3096
|
+
}
|
|
3097
|
+
if (!observer && typeof MutationObserver !== "undefined") {
|
|
3098
|
+
observer = new MutationObserver((mutations) => {
|
|
3099
|
+
if (isInitComplete) return;
|
|
3100
|
+
for (const mutation of mutations) {
|
|
3101
|
+
mutation.addedNodes.forEach((node) => {
|
|
3102
|
+
if (node.nodeType === Node.ELEMENT_NODE) {
|
|
3103
|
+
const el = node;
|
|
3104
|
+
if (el.hasAttribute("as-step")) {
|
|
3105
|
+
prehideStep(el, 1);
|
|
3106
|
+
}
|
|
3107
|
+
el.querySelectorAll("[as-step]").forEach((step) => prehideStep(step, 1));
|
|
3108
|
+
}
|
|
3109
|
+
});
|
|
3110
|
+
}
|
|
3111
|
+
});
|
|
3112
|
+
observer.observe(document.documentElement, {
|
|
3113
|
+
childList: true,
|
|
3114
|
+
subtree: true
|
|
3115
|
+
});
|
|
3116
|
+
}
|
|
3117
|
+
}
|
|
3118
|
+
function stopPrehide() {
|
|
3119
|
+
isInitComplete = true;
|
|
3120
|
+
if (observer) {
|
|
3121
|
+
observer.disconnect();
|
|
3122
|
+
observer = null;
|
|
3123
|
+
import_loglevel12.default.debug("[prehide] Observer stopped");
|
|
3124
|
+
}
|
|
3125
|
+
const preCSS = document.getElementById("as-pre-css");
|
|
3126
|
+
if (preCSS) {
|
|
3127
|
+
preCSS.remove();
|
|
3128
|
+
import_loglevel12.default.debug("[prehide] Removed pre-CSS, inline styles now control visibility");
|
|
3129
|
+
}
|
|
3130
|
+
}
|
|
3131
|
+
|
|
3132
|
+
// src/core/styles.ts
|
|
3133
|
+
var import_loglevel13 = __toESM(require_loglevel(), 1);
|
|
3134
|
+
function injectRuntimeStyles() {
|
|
3135
|
+
if (typeof document === "undefined") return;
|
|
3136
|
+
if (document.getElementById("as-runtime-css")) return;
|
|
3137
|
+
const style = document.createElement("style");
|
|
3138
|
+
style.id = "as-runtime-css";
|
|
3139
|
+
style.textContent = `
|
|
4
3140
|
/* Disabled elements styling */
|
|
5
3141
|
[as-disabled],
|
|
6
3142
|
[disabled][as-enable-if],
|
|
@@ -15,5 +3151,104 @@ ${o.join(`
|
|
|
15
3151
|
[as-quiz-score] {
|
|
16
3152
|
/* Authors can override these in Webflow */
|
|
17
3153
|
}
|
|
18
|
-
|
|
3154
|
+
`;
|
|
3155
|
+
const head = document.head || document.getElementsByTagName("head")[0] || document.documentElement;
|
|
3156
|
+
head.appendChild(style);
|
|
3157
|
+
import_loglevel13.default.debug("[styles] Injected runtime CSS");
|
|
3158
|
+
}
|
|
3159
|
+
|
|
3160
|
+
// src/index.ts
|
|
3161
|
+
import_loglevel14.default.setLevel("info");
|
|
3162
|
+
startPrehide();
|
|
3163
|
+
function init(options = {}) {
|
|
3164
|
+
if (options.debug) {
|
|
3165
|
+
import_loglevel14.default.setLevel("debug");
|
|
3166
|
+
}
|
|
3167
|
+
const surveyRoot = document.querySelector("[as-survey]");
|
|
3168
|
+
if (!surveyRoot) {
|
|
3169
|
+
import_loglevel14.default.warn("[agera-survey] No [as-survey] element found");
|
|
3170
|
+
return;
|
|
3171
|
+
}
|
|
3172
|
+
import_loglevel14.default.info("[agera-survey] Initializing");
|
|
3173
|
+
stopPrehide();
|
|
3174
|
+
injectRuntimeStyles();
|
|
3175
|
+
persistSession();
|
|
3176
|
+
initSteps(surveyRoot);
|
|
3177
|
+
initValidation(surveyRoot);
|
|
3178
|
+
initComponents(surveyRoot);
|
|
3179
|
+
initBasin(surveyRoot);
|
|
3180
|
+
initConditions(surveyRoot);
|
|
3181
|
+
initProgress(surveyRoot);
|
|
3182
|
+
initRedirect(surveyRoot);
|
|
3183
|
+
initQuiz(surveyRoot);
|
|
3184
|
+
import_loglevel14.default.info("[agera-survey] Ready");
|
|
3185
|
+
}
|
|
3186
|
+
if (typeof window !== "undefined") {
|
|
3187
|
+
if (!window.agera) {
|
|
3188
|
+
window.agera = {};
|
|
3189
|
+
}
|
|
3190
|
+
window.agera.survey = {
|
|
3191
|
+
init,
|
|
3192
|
+
version: RUNTIME_VERSION,
|
|
3193
|
+
reset: () => {
|
|
3194
|
+
window.localStorage.removeItem("as:session");
|
|
3195
|
+
window.localStorage.removeItem("as:basin-jwt");
|
|
3196
|
+
window.location.reload();
|
|
3197
|
+
},
|
|
3198
|
+
goToStep: (stepId) => showStep(stepId),
|
|
3199
|
+
getCurrentStep: () => stepsStore.get().current,
|
|
3200
|
+
getStepPath: () => stepsStore.get().path,
|
|
3201
|
+
getAnswers: () => sessionStore.get().answers,
|
|
3202
|
+
setAnswer: (key, value) => {
|
|
3203
|
+
const session = sessionStore.get();
|
|
3204
|
+
sessionStore.set({ ...session, answers: { ...session.answers, [key]: value } });
|
|
3205
|
+
},
|
|
3206
|
+
get dev() {
|
|
3207
|
+
return window.localStorage.getItem("as:dev") === "true";
|
|
3208
|
+
},
|
|
3209
|
+
set dev(enabled) {
|
|
3210
|
+
if (enabled) {
|
|
3211
|
+
window.localStorage.setItem("as:dev", "true");
|
|
3212
|
+
import_loglevel14.default.setLevel("debug");
|
|
3213
|
+
} else {
|
|
3214
|
+
window.localStorage.removeItem("as:dev");
|
|
3215
|
+
import_loglevel14.default.setLevel("info");
|
|
3216
|
+
}
|
|
3217
|
+
},
|
|
3218
|
+
validateCurrentStep: async () => {
|
|
3219
|
+
const current = stepsStore.get().current;
|
|
3220
|
+
if (!current) return true;
|
|
3221
|
+
return await validateStep(current);
|
|
3222
|
+
},
|
|
3223
|
+
triggerPartialSubmit: async () => {
|
|
3224
|
+
const current = stepsStore.get().current;
|
|
3225
|
+
if (current) {
|
|
3226
|
+
await sendPartial(current);
|
|
3227
|
+
}
|
|
3228
|
+
},
|
|
3229
|
+
triggerFinalSubmit: async () => {
|
|
3230
|
+
const current = stepsStore.get().current;
|
|
3231
|
+
if (current) {
|
|
3232
|
+
await sendFinal(current);
|
|
3233
|
+
}
|
|
3234
|
+
},
|
|
3235
|
+
getQuizResults: () => getQuizResults(),
|
|
3236
|
+
getQuizScores: () => getQuizScores(),
|
|
3237
|
+
getQuizWinner: () => getQuizWinner()
|
|
3238
|
+
};
|
|
3239
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
3240
|
+
const hasDevParam = urlParams.get("dev") === "true";
|
|
3241
|
+
const hasDevStorage = window.localStorage.getItem("as:dev") === "true";
|
|
3242
|
+
if (hasDevParam || hasDevStorage) {
|
|
3243
|
+
window.agera.survey.dev = true;
|
|
3244
|
+
import_loglevel14.default.info("[agera-survey] Debug mode enabled");
|
|
3245
|
+
}
|
|
3246
|
+
if (document.readyState === "loading") {
|
|
3247
|
+
document.addEventListener("DOMContentLoaded", () => init());
|
|
3248
|
+
} else {
|
|
3249
|
+
init();
|
|
3250
|
+
}
|
|
3251
|
+
}
|
|
3252
|
+
return __toCommonJS(index_exports);
|
|
3253
|
+
})();
|
|
19
3254
|
//# sourceMappingURL=index.global.js.map
|