quala-widget
Version:
Smart feedback widget for SaaS trial optimization
3 lines (2 loc) • 24.9 kB
JavaScript
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("react"),require("react/jsx-runtime"),require("react-dom")):"function"==typeof define&&define.amd?define(["exports","react","react/jsx-runtime","react-dom"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).Quala={},e.React,e["react/jsx-runtime"],e.ReactDOM)}(this,(function(e,t,r,o){"use strict";var i=Object.defineProperty,n=(e,t,r)=>((e,t,r)=>t in e?i(e,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[t]=r)(e,"symbol"!=typeof t?t+"":t,r);function s(e,t){for(var r=0;r<t.length;r++){const o=t[r];if("string"!=typeof o&&!Array.isArray(o))for(const t in o)if("default"!==t&&!(t in e)){const r=Object.getOwnPropertyDescriptor(o,t);r&&Object.defineProperty(e,t,r.get?r:{enumerable:!0,get:()=>o[t]})}}return Object.freeze(Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}))}const a={colors:{primary:"#65c3c8",base200:"#efeae6",base300:"#e7e2df",success:"#87d039",successContent:"#ffffff"},widget:{fontFamily:"system-ui, -apple-system, sans-serif"},button:{base:{display:"inline-flex",alignItems:"center",justifyContent:"center",padding:"12px 24px",borderRadius:"12px",border:"none",fontSize:"14px",fontWeight:"600",cursor:"pointer",transition:"all 0.3s cubic-bezier(0.4, 0, 0.2, 1)",textDecoration:"none",outline:"none",boxShadow:"0 2px 4px rgba(0, 0, 0, 0.05)"},primary:{backgroundColor:"#65c3c8",color:"#ffffff"},primaryHover:{backgroundColor:"#5ab5ba",transform:"translateY(-1px)",boxShadow:"0 4px 8px rgba(0, 0, 0, 0.1)"},ghost:{backgroundColor:"transparent",color:"#291334",border:"1px solid #e7e2df"},ghostHover:{backgroundColor:"#efeae6",transform:"translateY(-1px)",boxShadow:"0 2px 4px rgba(0, 0, 0, 0.05)"},small:{padding:"8px 12px",fontSize:"12px",minWidth:"auto",width:"32px",height:"32px",borderRadius:"50%",boxShadow:"none"},loading:{opacity:.7,cursor:"not-allowed",transform:"none"}},modal:{backdrop:{position:"fixed",top:0,left:0,right:0,bottom:0,backgroundColor:"rgba(0, 0, 0, 0.5)",display:"flex",alignItems:"center",justifyContent:"center",zIndex:1e3,opacity:0,visibility:"hidden",transition:"all 0.3s cubic-bezier(0.4, 0, 0.2, 1)",backdropFilter:"blur(4px)"},backdropOpen:{opacity:1,visibility:"visible"},box:{backgroundColor:"#faf7f5",borderRadius:"24px",padding:"32px",width:"100%",maxWidth:"448px",maxHeight:"90vh",overflowY:"auto",position:"relative",boxShadow:"0 25px 50px -12px rgba(0, 0, 0, 0.25)",margin:"20px",transform:"scale(0.95) translateY(10px)",transition:"all 0.3s cubic-bezier(0.4, 0, 0.2, 1)"},boxOpen:{transform:"scale(1) translateY(0)"}},input:{base:{width:"100%",padding:"14px 16px",borderRadius:"12px",border:"2px solid #e7e2df",fontSize:"16px",backgroundColor:"#ffffff",color:"#291334",transition:"all 0.2s ease",outline:"none",boxShadow:"0 1px 2px rgba(0, 0, 0, 0.05)"},focus:{borderColor:"#65c3c8",boxShadow:"0 0 0 4px rgba(101, 195, 200, 0.15)",transform:"translateY(-1px)"},error:{borderColor:"#e74c3c",boxShadow:"0 0 0 4px rgba(231, 76, 60, 0.15)"},textarea:{resize:"none",minHeight:"100px",fontFamily:"inherit",lineHeight:"1.5"}},progress:{track:{width:"100%",height:"8px",backgroundColor:"#efeae6",borderRadius:"4px",overflow:"hidden",boxShadow:"inset 0 1px 2px rgba(0, 0, 0, 0.05)"},bar:{height:"100%",backgroundColor:"#65c3c8",borderRadius:"4px",transition:"width 0.5s cubic-bezier(0.4, 0, 0.2, 1)",boxShadow:"0 1px 2px rgba(0, 0, 0, 0.1)"}},rating:{container:{display:"flex",gap:"12px",justifyContent:"center",alignItems:"center",padding:"8px 0"},star:{width:"40px",height:"40px",cursor:"pointer",transition:"all 0.2s cubic-bezier(0.4, 0, 0.2, 1)",border:"none",background:"none",fontSize:"28px",color:"#e7e2df",display:"flex",alignItems:"center",justifyContent:"center"},starFilled:{color:"#eeaf3a",transform:"scale(1.1)"},starHover:{transform:"scale(1.2)",color:"#eeaf3a"}},radio:{container:{display:"flex",alignItems:"center",gap:"12px",padding:"16px",borderRadius:"12px",border:"2px solid #e7e2df",backgroundColor:"#ffffff",cursor:"pointer",transition:"all 0.2s cubic-bezier(0.4, 0, 0.2, 1)",boxShadow:"0 1px 2px rgba(0, 0, 0, 0.05)"},containerSelected:{borderColor:"#65c3c8",backgroundColor:"rgba(101, 195, 200, 0.05)",transform:"translateY(-1px)",boxShadow:"0 4px 8px rgba(0, 0, 0, 0.1)"},containerHover:{borderColor:"rgba(101, 195, 200, 0.5)",backgroundColor:"#efeae6",transform:"translateY(-1px)",boxShadow:"0 2px 4px rgba(0, 0, 0, 0.05)"},input:{width:"20px",height:"20px",accentColor:"#65c3c8"}},alert:{error:{display:"flex",alignItems:"center",gap:"12px",padding:"16px",borderRadius:"12px",backgroundColor:"rgba(231, 76, 60, 0.1)",border:"1px solid rgba(231, 76, 60, 0.2)",color:"#e74c3c",fontSize:"14px",boxShadow:"0 2px 4px rgba(0, 0, 0, 0.05)"}},text:{title:{fontSize:"28px",fontWeight:"700",color:"#291334",marginBottom:"12px",lineHeight:"1.2"},label:{fontSize:"16px",fontWeight:"500",color:"#291334",marginBottom:"8px",display:"block",lineHeight:"1.4"},small:{fontSize:"14px",color:"rgba(41, 19, 52, 0.7)",lineHeight:"1.5"},error:{fontSize:"14px",color:"#e74c3c",marginTop:"6px",display:"flex",alignItems:"center",gap:"6px"},required:{color:"#e74c3c",marginLeft:"2px"}}},l=({triggerText:e="Start Trial",title:o="Before you start your trial...",questions:i,onSubmit:n,onClose:s,onCancel:l,open:d,onComplete:c,modalStyle:u={}})=>{const h=void 0!==d,[g,p]=t.useState(!1),y=h?d:g,[f,b]=t.useState({}),[x,m]=t.useState({}),[w,k]=t.useState(!1),[v,S]=t.useState(!1),[C,T]=t.useState(0),j=t.useRef(null),I=t.useRef(null),Q=t.useCallback((()=>{I.current&&(I.current.style.height="auto",I.current.style.height=`${I.current.scrollHeight}px`)}),[]);t.useEffect((()=>{var e,t;if(y){const r=i[C];"textarea"===(null==r?void 0:r.type)?null==(e=I.current)||e.focus():"text"===(null==r?void 0:r.type)&&(null==(t=j.current)||t.focus()),Q()}}),[y,C,Q]),t.useEffect((()=>{Q()}),[f,Q]),t.useEffect((()=>{const e=e=>{"Escape"===e.key&&y&&z()};return window.addEventListener("keydown",e),()=>window.removeEventListener("keydown",e)}),[y]);const R=(e,t)=>{b((r=>({...r,[e]:t}))),m((t=>({...t,[e]:""})));const r=i[C];(null==r?void 0:r.id)!==e||"rating"!==r.type&&"boolean"!==r.type||setTimeout((()=>{C<i.length-1&&T(C+1)}),800)},O=async()=>{if((()=>{const e={};return i.forEach((({id:t,text:r,required:o,type:i="text"})=>{const n=f[t];!o||n&&("text"!==i&&"textarea"!==i||n.trim())||(e[t]=`${r} is required`)})),m(e),0===Object.keys(e).length})()){k(!0);try{await n(f),S(!0)}catch{m({form:"Submission failed. Please try again."})}finally{k(!1)}}},z=()=>{h||p(!1),v?null==c||c({answers:f}):null==l||l(),b({}),m({}),k(!1),S(!1),T(0),null==s||s()},q=(C+1)/i.length*100,E=t.useCallback((e=>{const t=i[e],r=f[t.id],o=t.type||"text";!t.required||r&&("text"!==o&&"textarea"!==o||r.trim())?(m((e=>({...e,[t.id]:""}))),T(e+1)):m((e=>({...e,[t.id]:`${t.text} is required`})))}),[i,f]),F=()=>({...a.input.focus,...u.inputFocusColor&&{borderColor:u.inputFocusColor,boxShadow:`0 0 0 3px ${u.inputFocusColor}20`}}),U=(e="primary",t=!1,r=!1)=>{const o={...a.button.base,..."primary"===e&&a.button.primary,..."ghost"===e&&a.button.ghost,..."small"===e&&a.button.small,...t&&"primary"===e&&a.button.primaryHover,...t&&"ghost"===e&&a.button.ghostHover,...r&&a.button.loading};return"primary"===e&&u.buttonColor&&(o.backgroundColor=u.buttonColor),"ghost"===e&&u.backButtonColor&&(o.backgroundColor=u.backButtonColor),o};return r.jsxs("div",{style:a.widget,children:[!h&&r.jsx("button",{onClick:()=>{h||p(!0)},style:{...U("primary"),...u.triggerColor&&{backgroundColor:u.triggerColor}},onMouseEnter:e=>{Object.assign(e.currentTarget.style,U("primary",!0))},onMouseLeave:e=>{Object.assign(e.currentTarget.style,U("primary",!1))},children:e}),r.jsx("div",{style:{...a.modal.backdrop,...y&&a.modal.backdropOpen,...u.modalColor&&{backgroundColor:u.modalColor}},onClick:e=>{e.target===e.currentTarget&&z()},children:r.jsxs("div",{style:{...a.modal.box,...y&&a.modal.boxOpen,...u.modalBoxColor&&{backgroundColor:u.modalBoxColor}},children:[r.jsx("button",{onClick:z,style:U("small"),onMouseEnter:e=>{e.currentTarget.style.backgroundColor=a.colors.base200},onMouseLeave:e=>{e.currentTarget.style.backgroundColor="transparent"},"aria-label":"Close modal",children:"✕"}),v?r.jsxs("div",{style:{textAlign:"center",padding:"32px 0"},children:[r.jsxs("div",{style:{marginBottom:"24px"},children:[r.jsx("div",{style:{width:"64px",height:"64px",backgroundColor:a.colors.success,color:a.colors.successContent,borderRadius:"50%",display:"flex",alignItems:"center",justifyContent:"center",margin:"0 auto 16px",fontSize:"32px"},children:"✓"}),r.jsx("h3",{style:a.text.title,children:"Thank you!"}),r.jsx("p",{style:a.text.small,children:"We'll get back to you shortly."})]}),r.jsx("button",{style:U("primary"),onClick:z,onMouseEnter:e=>{Object.assign(e.currentTarget.style,U("primary",!0))},onMouseLeave:e=>{Object.assign(e.currentTarget.style,U("primary",!1))},children:"Close"})]}):r.jsxs(r.Fragment,{children:[r.jsxs("div",{style:{marginBottom:"24px"},children:[r.jsx("h3",{style:a.text.title,children:o}),r.jsx("div",{style:{...a.progress.track,...u.progressTrackColor&&{backgroundColor:u.progressTrackColor}},children:r.jsx("div",{style:{...a.progress.bar,width:`${q}%`,...u.progressBarColor&&{backgroundColor:u.progressBarColor}}})}),r.jsxs("p",{style:{...a.text.small,marginTop:"8px"},children:["Step ",C+1," of ",i.length]})]}),r.jsxs("form",{onSubmit:e=>{e.preventDefault(),O()},style:{display:"flex",flexDirection:"column",gap:"24px"},children:[i.map((({id:e,text:t,required:o,type:n="text",options:s,placeholder:l},d)=>r.jsxs("div",{style:{opacity:d===C?1:0,display:d===C?"block":"none",transition:"opacity 0.3s ease"},children:[r.jsxs("label",{style:a.text.label,children:[t," ",o&&r.jsx("span",{style:a.text.required,children:"*"})]}),"text"===n&&r.jsx("input",{ref:d===C?j:null,type:"text",placeholder:l||"Your answer...",style:{...a.input.base,...x[e]&&a.input.error},value:f[e]||"",onChange:t=>R(e,t.target.value),onFocus:e=>{Object.assign(e.currentTarget.style,F())},onBlur:t=>{x[e]||(t.currentTarget.style.borderColor=a.colors.base300,t.currentTarget.style.boxShadow="none")},onKeyDown:e=>{"Enter"===e.key&&(e.preventDefault(),C<i.length-1?E(d):O())},required:o}),"textarea"===n&&r.jsx("textarea",{ref:d===C?I:null,placeholder:l||"Tell us more...",style:{...a.input.base,...a.input.textarea,...x[e]&&a.input.error,maxHeight:"200px",overflow:"hidden"},value:f[e]||"",onChange:t=>{R(e,t.target.value),Q()},onFocus:e=>{Object.assign(e.currentTarget.style,F())},onBlur:t=>{x[e]||(t.currentTarget.style.borderColor=a.colors.base300,t.currentTarget.style.boxShadow="none")},onKeyDown:e=>{(e.ctrlKey||e.metaKey)&&"Enter"===e.key&&(e.preventDefault(),C<i.length-1?E(d):O())},required:o}),"rating"===n&&r.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:"12px"},children:[r.jsx("div",{style:a.rating.container,children:[1,2,3,4,5].map((t=>r.jsx("button",{type:"button",style:{...a.rating.star,...f[e]&&parseInt(f[e])>=t&&a.rating.starFilled},onClick:()=>R(e,t.toString()),onMouseEnter:e=>{Object.assign(e.currentTarget.style,a.rating.starHover)},onMouseLeave:e=>{e.currentTarget.style.transform="scale(1)"},children:"★"},t)))}),r.jsxs("div",{style:{display:"flex",justifyContent:"space-between",...a.text.small},children:[r.jsx("span",{children:"Very Poor"}),r.jsx("span",{children:"Excellent"})]}),f[e]&&r.jsxs("div",{style:{textAlign:"center",...a.text.small,fontWeight:"500"},children:["Rating: ",f[e],"/5"]})]}),"multiple_choice"===n&&s&&r.jsx("div",{style:{display:"flex",flexDirection:"column",gap:"12px"},children:s.map(((t,o)=>r.jsxs("label",{style:{...a.radio.container,...f[e]===t&&a.radio.containerSelected},onMouseEnter:r=>{f[e]!==t&&Object.assign(r.currentTarget.style,a.radio.containerHover)},onMouseLeave:r=>{f[e]!==t&&(r.currentTarget.style.borderColor=a.colors.base300,r.currentTarget.style.backgroundColor="#ffffff")},children:[r.jsx("input",{type:"radio",name:`choice-${e}`,style:a.radio.input,checked:f[e]===t,onChange:()=>R(e,t)}),r.jsx("span",{style:{flex:1,fontWeight:"500"},children:t})]},o)))}),"boolean"===n&&r.jsxs("div",{style:{display:"flex",gap:"16px"},children:[r.jsxs("label",{style:{...a.radio.container,flex:1,justifyContent:"center",..."true"===f[e]&&a.radio.containerSelected},children:[r.jsx("input",{type:"radio",name:`bool-${e}`,style:a.radio.input,checked:"true"===f[e],onChange:()=>R(e,"true")}),r.jsx("span",{style:{fontWeight:"500"},children:"Yes"})]}),r.jsxs("label",{style:{...a.radio.container,flex:1,justifyContent:"center",..."false"===f[e]&&a.radio.containerSelected},children:[r.jsx("input",{type:"radio",name:`bool-${e}`,style:a.radio.input,checked:"false"===f[e],onChange:()=>R(e,"false")}),r.jsx("span",{style:{fontWeight:"500"},children:"No"})]})]}),x[e]&&r.jsx("div",{style:a.text.error,children:x[e]})]},e))),x.form&&r.jsxs("div",{style:a.alert.error,children:[r.jsx("span",{children:"⚠"}),r.jsx("span",{children:x.form})]}),r.jsxs("div",{style:{display:"flex",justifyContent:"space-between",gap:"16px",marginTop:"32px"},children:[C>0&&r.jsx("button",{type:"button",style:U("ghost"),onClick:()=>T(C-1),onMouseEnter:e=>{Object.assign(e.currentTarget.style,U("ghost",!0))},onMouseLeave:e=>{Object.assign(e.currentTarget.style,U("ghost",!1))},children:"Back"}),C<i.length-1?r.jsx("button",{type:"button",style:U("primary"),onClick:e=>{e.preventDefault(),E(C)},onMouseEnter:e=>{Object.assign(e.currentTarget.style,U("primary",!0))},onMouseLeave:e=>{Object.assign(e.currentTarget.style,U("primary",!1))},children:"Next"}):r.jsx("button",{type:"submit",style:U("primary",!1,w),disabled:w,onMouseEnter:e=>{w||Object.assign(e.currentTarget.style,U("primary",!0))},onMouseLeave:e=>{w||Object.assign(e.currentTarget.style,U("primary",!1))},children:w?"Submitting...":"Submit"})]})]})]}),r.jsxs("div",{style:{textAlign:"center",...a.text.small,marginTop:"24px",fontSize:"12px"},children:["Powered by ",r.jsx("a",{href:"https://getquala.xyz",target:"_blank",rel:"noopener noreferrer",style:{textDecoration:"underline",color:a.colors.primary},children:"Quala"})]})]})})]})},d=class e{constructor(){n(this,"createRootFn",null),n(this,"legacyRender",null),n(this,"isReady",!1),n(this,"debug",!1)}static getInstance(){return e.instance||(e.instance=new e),e.instance}setDebug(e){this.debug=e}log(e,...t){this.debug&&console.log(e,...t)}async initialize(){var e,t;if(!this.isReady){try{const e=require("react-dom/client");if(e&&e.createRoot)return this.createRootFn=e.createRoot,this.isReady=!0,void this.log("[Quala] Using direct require for react-dom/client")}catch(r){}try{const t=await Promise.resolve().then((()=>w));if(this.createRootFn=t.createRoot||(null==(e=t.default)?void 0:e.createRoot),this.createRootFn)return this.isReady=!0,void this.log("[Quala] Using dynamic import for react-dom/client")}catch(r){}try{const e=require("react-dom");if(e&&e.render)return this.legacyRender=e,this.isReady=!0,void this.log("[Quala] Using legacy ReactDOM.render")}catch(r){}try{const e=await import("react-dom");if(e.render||(null==(t=e.default)?void 0:t.render))return this.legacyRender=e.default||e,this.isReady=!0,void this.log("[Quala] Using dynamic import for legacy ReactDOM")}catch(r){console.error("[Quala] All React DOM loading methods failed")}}}createRoot(e){if(!this.isReady)throw new Error("[Quala] Renderer not ready. Call initialize() first.");if(this.createRootFn)return this.createRootFn(e);if(this.legacyRender)return{render:t=>{this.legacyRender.render(t,e)},unmount:()=>{this.legacyRender.unmountComponentAtNode&&this.legacyRender.unmountComponentAtNode(e)}};throw new Error("[Quala] No React rendering method available")}isInitialized(){return this.isReady}};n(d,"instance");let c=d;const u=new class{constructor(){n(this,"isInitialized",!1),n(this,"apiKey",""),n(this,"apiBaseUrl","https://www.getquala.xyz/api/widget"),n(this,"sessionToken",null),n(this,"currentQuestionGroupId",null),n(this,"currentTriggerId",null),n(this,"container"),n(this,"root"),n(this,"customStyles"),n(this,"renderer",c.getInstance()),n(this,"debug",!1)}log(e,...t){this.debug&&console.log(e,...t)}async initialize(e,t,r){if(this.apiKey=e,this.isInitialized=!0,this.customStyles=t,this.debug=(null==r?void 0:r.debug)||!1,this.renderer.setDebug(this.debug),(null==r?void 0:r.apiBaseUrl)&&(this.apiBaseUrl=r.apiBaseUrl),this.log("[Quala] SDK initialized with API URL:",this.apiBaseUrl),"undefined"!=typeof window){await this.renderer.initialize();const e=localStorage.getItem("quala:pending-user");if(e){const t=JSON.parse(e);localStorage.removeItem("quala:pending-user"),this.identifyUser(t)}}}getApiUrl(){return this.apiBaseUrl}setApiUrl(e){this.isInitialized?(this.apiBaseUrl=e,this.log("[Quala] API URL updated to:",this.apiBaseUrl)):console.warn("[Quala] SDK not initialized yet")}validateKey(){return this.isInitialized&&this.apiKey.length>0}async identifyUser(e){const t=Intl.DateTimeFormat().resolvedOptions().timeZone;if(!this.isInitialized)return console.warn("Quala not initialized yet. User will be identified after initialization."),void("undefined"!=typeof window&&localStorage.setItem("quala:pending-user",JSON.stringify(e)));try{const r=await fetch(`${this.apiBaseUrl}/init`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({apiKey:this.apiKey,userId:e.userId,email:e.email,trialStartDate:e.trialStartDate||(new Date).toISOString(),userTimezone:t})});if(!r.ok)throw new Error(`Init API failed: ${r.status}`);const o=await r.json();this.log("Init response",o),this.sessionToken=o.sessionToken,this.currentQuestionGroupId=o.questionGroupId||null,this.currentTriggerId=o.triggerId||null,"undefined"!=typeof window&&localStorage.setItem("quala:session",this.sessionToken),this.log("[Quala] User identified, ready for dashboard-controlled feedback"),this.trackEvent("user_identified",{userId:e.userId,email:e.email})}catch(r){console.error("Quala: Failed to identify user",r)}}trackEvent(e,t){this.validateKey()?(this.sessionToken&&fetch(`${this.apiBaseUrl}/track`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({sessionToken:this.sessionToken,event:this.mapEventName(e),data:t||{}})}).catch((e=>{console.error("[Quala] Track event failed:",e)})),this.log(`[Quala] Track event: ${e}`,t)):console.warn("Quala SDK not initialized or invalid API key")}mapEventName(e){return"page_visit"===e||"time_update"===e?e:"milestone_reached"===e?"milestone_reached":"feature_used"}async triggerSmartFeedback(){if(!this.validateKey()||!this.sessionToken)return void console.warn("Quala SDK not initialized or no active session");const e=await this.shouldShowFeedback();if(e.shouldShow){const t=e.delayMs||0;setTimeout((async()=>{await this.showDashboardWidget(),this.trackEvent("feedback_widget_triggered",{trigger:"automated",questionGroupId:this.currentQuestionGroupId,trigerId:this.currentTriggerId,delayMs:t})}),t)}}async shouldShowFeedback(){if(!this.sessionToken)return console.warn("Quala: No active session for triggering"),{shouldShow:!1};try{const e=await fetch(`${this.apiBaseUrl}/check-trigger`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({sessionToken:this.sessionToken})});if(!e.ok)return console.error("[Quala] Failed to check trigger conditions"),{shouldShow:!1};const t=await e.json();return this.currentQuestionGroupId=t.questionGroupId||null,this.currentTriggerId=t.triggerId||null,{shouldShow:t.shouldShow,delayMs:t.delayMs}}catch(e){return console.error("[Quala] Error checking if should show feedback:",e),{shouldShow:!1}}}async showDashboardWidget(){this.sessionToken&&this.currentQuestionGroupId?await this.showWidget():console.warn("[Quala] No session or question group available")}async showWidget(e){if(this.validateKey())if(this.sessionToken&&this.currentQuestionGroupId)try{const t=await fetch(`${this.apiBaseUrl}/questions?sessionToken=${this.sessionToken}&questionGroupId=${this.currentQuestionGroupId}`);if(!t.ok)throw new Error(`Questions API failed: ${t.status}`);const r=await t.json();if(!r.questions||0===r.questions.length)return void this.log("[Quala] No questions configured in dashboard");const o="We'd love your feedback";await this.renderWidget(o,r.questions,null==e?void 0:e.onComplete,null==e?void 0:e.onCancel)}catch(t){console.error("[Quala] Failed to load widget:",t)}else console.warn("[Quala] No active session. Call identifyUser() first.");else console.warn("Quala SDK not initialized or invalid API key")}async renderWidget(e,r,o,i){if(!this.container)if("undefined"!=typeof window){this.renderer.isInitialized()||await this.renderer.initialize();try{this.currentTriggerId&&this.markTriggerShown(),this.container=document.createElement("div"),document.body.appendChild(this.container),this.root=this.renderer.createRoot(this.container);const n=()=>{if(this.root&&this.container){try{this.root.unmount()}catch(e){console.warn("[Quala] Unmount failed:",e)}this.container.remove(),this.container=void 0,this.root=void 0}},s=async e=>{try{await this.submitAnswers(e),o&&o({answers:e})}catch(t){console.error("Quala: Submission failed",t)}},a=()=>{i&&i(),n()},d=r.map((e=>({id:e.id,text:e.text,required:e.required,type:e.type,options:e.options,placeholder:e.placeholder}))),c=t.createElement(l,{open:!0,title:e,questions:d,onSubmit:s,onCancel:a,onComplete:o,modalStyle:this.customStyles,onClose:n});this.root.render(c),this.trackEvent("feedback_widget_shown",{trigger:"manual",questionCount:r.length}),this.log("[Quala] Widget rendered successfully")}catch(n){console.error("[Quala] Failed to render widget:",n),this.container&&(this.container.remove(),this.container=void 0,this.root=void 0)}}else console.warn("[Quala] Cannot render widget on server side")}async markTriggerShown(){if(this.sessionToken&&this.currentTriggerId)try{if(!(await fetch(`${this.apiBaseUrl}/mark-trigger`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({sessionToken:this.sessionToken,triggerId:this.currentTriggerId})})).ok)return void console.error("[Quala] Failed to mark trigger as shown");this.log("[Quala] Trigger marked as shown")}catch(e){console.error("[Quala] Failed to mark trigger as shown:",e)}else console.warn("[Quala] Missing session token or trigger ID")}async submitAnswers(e){if(this.sessionToken&&this.currentQuestionGroupId)try{const t=await fetch(`${this.apiBaseUrl}/submit`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({sessionToken:this.sessionToken,answers:e,questionGroupId:this.currentQuestionGroupId,triggerId:this.currentTriggerId,triggerType:"auto"})});if(!t.ok)throw new Error(`Submit API failed: ${t.status}`);const r=await t.json();if(!r.success)throw new Error(r.message||"Submission failed");"undefined"!=typeof window&&localStorage.setItem("quala:lastResponse",Date.now().toString()),this.trackEvent("feedback_flow_complete"),this.log("[Quala] Feedback submitted successfully")}catch(t){console.error("[Quala] Failed to submit feedback:",t)}else console.error("[Quala] Missing session or question group for submission")}getSessionInfo(){return{sessionToken:this.sessionToken,questionGroupId:this.currentQuestionGroupId,triggerId:this.currentTriggerId,isInitialized:this.isInitialized,apiBaseUrl:this.apiBaseUrl,debug:this.debug}}async checkTriggerAvailable(){return(await this.shouldShowFeedback()).shouldShow}async refreshTriggerStatus(){if(this.sessionToken){try{if((await this.shouldShowFeedback()).shouldShow)return this.log("[Quala] Trigger now available after refresh"),!0}catch(e){console.error("[Quala] Failed to refresh trigger status:",e)}return!1}}destroy(){if(this.container&&this.root){try{this.root.unmount()}catch(e){console.warn("[Quala] Destroy failed:",e)}this.container.remove()}this.isInitialized=!1,this.sessionToken=null,this.currentQuestionGroupId=null,this.currentTriggerId=null,this.debug=!1,"undefined"!=typeof window&&(localStorage.removeItem("quala:session"),localStorage.removeItem("quala:pending-user"),localStorage.removeItem("quala:lastResponse"))}};function h(){return{identifyUser:e=>{u.identifyUser(e)},trackEvent:(e,t={})=>{u.trackEvent(e,t)},triggerSmartFeedback:async()=>{try{await u.triggerSmartFeedback()}catch(e){console.error("Quala: Trigger feedback error",e)}}}}const g=({apiKey:e,modalStyle:r,options:o})=>{t.useEffect((()=>(u.initialize(e,r,o),()=>{u.destroy()})),[e,null==o?void 0:o.apiBaseUrl,null==o?void 0:o.debug])},p="1.0.0",y={sdk:u,qualaSdk:u,useQuala:h,useQualaInit:g,QualaWidget:l,VERSION:p};function f(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var b,x={};var m=function(){if(b)return x;b=1;var e=o;return x.createRoot=e.createRoot,x.hydrateRoot=e.hydrateRoot,x}();const w=s({__proto__:null,default:f(m)},[m]);e.QualaWidget=l,e.VERSION=p,e.default=y,e.qualaSdk=u,e.useQuala=h,e.useQualaInit=g,Object.defineProperties(e,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})}));
//# sourceMappingURL=quala.umd.js.map