@product7/feedback-sdk 1.1.5 → 1.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,2 +1,2 @@
1
- !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).FeedbackSDK={})}(this,function(e){"use strict";class t extends Error{constructor(e,n){super(e),this.name="SDKError",this.cause=n,Error.captureStackTrace&&Error.captureStackTrace(this,t)}}class n extends Error{constructor(e,t,s){super(t),this.name="APIError",this.status=e,this.response=s,Error.captureStackTrace&&Error.captureStackTrace(this,n)}isNetworkError(){return 0===this.status}isClientError(){return this.status>=400&&this.status<500}isServerError(){return this.status>=500&&this.status<600}}class s extends Error{constructor(e,t,n){super(e),this.name="WidgetError",this.widgetType=t,this.widgetId=n,Error.captureStackTrace&&Error.captureStackTrace(this,s)}}class i extends Error{constructor(e,t){super(e),this.name="ConfigError",this.configKey=t,Error.captureStackTrace&&Error.captureStackTrace(this,i)}}class o extends Error{constructor(e,t,n){super(e),this.name="ValidationError",this.field=t,this.value=n,Error.captureStackTrace&&Error.captureStackTrace(this,o)}}const r={primaryColor:"#21244A",backgroundColor:"#ffffff",textColor:"#1F2937",boardId:"feature-requests",size:"medium",displayMode:"modal"},a={production:{base:"https://api.product7.io/api/v1",withWorkspace:e=>`https://${e}.api.product7.io/api/v1`},staging:{base:"https://staging.api.product7.io/api/v1",withWorkspace:e=>`https://${e}.staging.api.product7.io/api/v1`}};class d{constructor(e={}){if(this.workspace=e.workspace,this.sessionToken=null,this.sessionExpiry=null,this.userContext=e.userContext||null,this.mock=e.mock||!1,this.env=e.env||"production",e.apiUrl)this.baseURL=e.apiUrl;else{const e=a[this.env]||a.production;this.baseURL=this.workspace?e.withWorkspace(this.workspace):e.base}this._loadStoredSession()}async init(e=null){if(e&&(this.userContext=e),this.isSessionValid())return{sessionToken:this.sessionToken};if(!this.userContext||!this.workspace){const e=`Missing ${this.workspace?"user context":"workspace"} for initialization`;throw new n(400,e)}if(this.mock)return this.sessionToken="mock_session_"+Date.now(),this.sessionExpiry=new Date(Date.now()+36e5),this._storeSession(),{sessionToken:this.sessionToken,config:r,expiresIn:3600};const t={workspace:this.workspace,user:this.userContext};try{const e=await this._makeRequest("/widget/init",{method:"POST",body:JSON.stringify(t),headers:{"Content-Type":"application/json"}});return this.sessionToken=e.session_token,this.sessionExpiry=new Date(Date.now()+1e3*e.expires_in),this._storeSession(),{sessionToken:this.sessionToken,config:e.config||{},expiresIn:e.expires_in}}catch(e){throw new n(e.status||500,`Failed to initialize widget: ${e.message}`,e.response)}}async submitFeedback(e){if(this.isSessionValid()||await this.init(),!this.sessionToken)throw new n(401,"No valid session token available");if(this.mock)return await new Promise(e=>setTimeout(e,500)),{success:!0,data:{id:"mock_post_"+Date.now(),title:e.title,content:e.content},message:"Feedback submitted successfully!"};const t={board:e.board_id||e.board||e.boardId,title:e.title,content:e.content,attachments:e.attachments||[]};try{return await this._makeRequest("/widget/feedback",{method:"POST",body:JSON.stringify(t),headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.sessionToken}`}})}catch(t){if(401===t.status)return this.sessionToken=null,this.sessionExpiry=null,await this.init(),this.submitFeedback(e);throw new n(t.status||500,`Failed to submit feedback: ${t.message}`,t.response)}}isSessionValid(){return this.sessionToken&&this.sessionExpiry&&new Date<this.sessionExpiry}setUserContext(e){this.userContext=e,"undefined"!=typeof localStorage&&localStorage.setItem("feedbackSDK_userContext",JSON.stringify(e))}getUserContext(){return this.userContext}clearSession(){this.sessionToken=null,this.sessionExpiry=null,"undefined"!=typeof localStorage&&(localStorage.removeItem("feedbackSDK_session"),localStorage.removeItem("feedbackSDK_userContext"))}_storeSession(){if("undefined"!=typeof localStorage)try{const e={token:this.sessionToken,expiry:this.sessionExpiry.toISOString(),workspace:this.workspace};localStorage.setItem("feedbackSDK_session",JSON.stringify(e))}catch(e){}}_loadStoredSession(){if("undefined"==typeof localStorage)return!1;try{const e=localStorage.getItem("feedbackSDK_session");if(!e)return!1;const t=JSON.parse(e);return this.sessionToken=t.token,this.sessionExpiry=new Date(t.expiry),this.isSessionValid()}catch(e){return!1}}async _makeRequest(e,t={}){const s=`${this.baseURL}${e}`;try{const e=await fetch(s,t);if(!e.ok){let t=`HTTP ${e.status}`,s=null;try{s=await e.json(),t=s.message||s.error||t}catch(n){t=await e.text()||t}throw new n(e.status,t,s)}const i=e.headers.get("content-type");return i&&i.includes("application/json")?await e.json():await e.text()}catch(e){if(e instanceof n)throw e;throw new n(0,e.message,null)}}}class c{constructor(){this.events=new Map}on(e,t){return this.events.has(e)||this.events.set(e,[]),this.events.get(e).push(t),()=>this.off(e,t)}off(e,t){const n=this.events.get(e);if(n){const e=n.indexOf(t);e>-1&&n.splice(e,1)}}emit(e,t){const n=this.events.get(e);n&&n.forEach(e=>{try{e(t)}catch(e){console.error("[FeedbackSDK] Event callback error:",e)}})}once(e,t){const n=this.on(e,e=>{t(e),n()});return n}clear(){this.events.clear()}getListenerCount(e){const t=this.events.get(e);return t?t.length:0}}function l(e="feedback"){return`${e}_${Date.now()}_${Math.random().toString(36).substring(2,9)}`}function u(e,t){const n={...e};for(const s in t)t.hasOwnProperty(s)&&(t[s]&&"object"==typeof t[s]&&!Array.isArray(t[s])?n[s]=u(e[s]||{},t[s]):n[s]=t[s]);return n}function p(){return"undefined"!=typeof window&&"undefined"!=typeof document}var h=Object.freeze({__proto__:null,debounce:function(e,t){let n;return function(...s){clearTimeout(n),n=setTimeout(()=>{clearTimeout(n),e(...s)},t)}},deepMerge:u,delay:function(e){return new Promise(t=>setTimeout(t,e))},escapeRegex:function(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")},formatFileSize:function(e){if(0===e)return"0 Bytes";const t=Math.floor(Math.log(e)/Math.log(1024));return parseFloat((e/Math.pow(1024,t)).toFixed(2))+" "+["Bytes","KB","MB","GB"][t]},generateId:l,getBrowserInfo:function(){return{userAgent:navigator.userAgent,platform:navigator.platform,language:navigator.language||navigator.userLanguage,cookieEnabled:navigator.cookieEnabled,screenResolution:`${screen.width}x${screen.height}`,windowSize:`${window.innerWidth}x${window.innerHeight}`,timezone:Intl.DateTimeFormat().resolvedOptions().timeZone}},getCSSProperty:function(e,t,n=""){if(!e||!t)return n;try{return window.getComputedStyle(e).getPropertyValue(t)||n}catch(e){return n}},getCurrentTimestamp:function(){return(new Date).toISOString()},getNestedProperty:function(e,t,n=void 0){if(!e||!t)return n;const s=t.split(".");let i=e;for(const e of s){if(null==i||!(e in i))return n;i=i[e]}return i},isBrowser:p,isInViewport:function(e){if(!e)return!1;const t=e.getBoundingClientRect();return t.top>=0&&t.left>=0&&t.bottom<=(window.innerHeight||document.documentElement.clientHeight)&&t.right<=(window.innerWidth||document.documentElement.clientWidth)},isMobile:function(){return!!p()&&(/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)||window.innerWidth<=768)},isValidEmail:function(e){return!(!e||"string"!=typeof e)&&/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(e.trim())},safeJsonParse:function(e,t=null){try{return JSON.parse(e)}catch(e){return t}},sanitizeHTML:function(e){if(!e||"string"!=typeof e)return"";const t=document.createElement("div");return t.textContent=e,t.innerHTML},scrollToElement:function(e,t={}){if(!e)return;e.scrollIntoView({behavior:"smooth",block:"center",inline:"nearest",...t})},setNestedProperty:function(e,t,n){if(!e||!t)return e;const s=t.split("."),i=s.pop();let o=e;for(const e of s)e in o&&"object"==typeof o[e]||(o[e]={}),o=o[e];return o[i]=n,e},throttle:function(e,t){let n,s;return function(...i){s?(clearTimeout(n),n=setTimeout(()=>{Date.now()-s>=t&&(e(...i),s=Date.now())},t-(Date.now()-s))):(e(...i),s=Date.now())}},validateConfig:function(e,t=[]){const n=[];for(const s of t)e[s]||n.push(s);if(n.length>0)throw new Error(`Missing required configuration: ${n.join(", ")}`);return!0}});class f{constructor(e={}){this.id=e.id,this.sdk=e.sdk,this.apiService=e.apiService,this.type=e.type||"base",this.options={container:null,position:this.sdk.config.position,boardId:this.sdk.config.boardId,displayMode:e.displayMode||"panel",size:e.size||"medium",primaryColor:e.primaryColor||"#21244A",backgroundColor:e.backgroundColor||"#ffffff",textColor:e.textColor||"#1F2937",autoShow:!1,showBackdrop:!0,customStyles:{},...e},this.element=null,this.panelElement=null,this.backdropElement=null,this.mounted=!1,this.destroyed=!1,this.state={isOpen:!1,isLoading:!1,isSubmitting:!1,title:"",content:"",email:"",attachments:[],errors:{}},this._bindMethods()}mount(e){return this.mounted||this.destroyed||("string"==typeof e&&(e=document.querySelector(e)),e||(e=document.body),this.container=e,this.element=this._render(),this.container.appendChild(this.element),this.mounted=!0,this._attachEvents(),this.onMount(),this.options.autoShow&&this.show(),this.sdk.eventBus.emit("widget:mounted",{widget:this})),this}show(){return this.element&&(this.element.style.display="block"),this}hide(){return this.element&&(this.element.style.display="none"),this}openPanel(){this.state.isOpen=!0,"modal"===this.options.displayMode?(this._showLoadingModal(),setTimeout(()=>{this._hideLoadingModal(),this._renderPanel(),requestAnimationFrame(()=>{this.panelElement&&this.panelElement.classList.add("open"),this.backdropElement&&this.backdropElement.classList.add("show")})},600)):(this._renderPanel(),requestAnimationFrame(()=>{this.panelElement&&this.panelElement.classList.add("open"),this.backdropElement&&this.backdropElement.classList.add("show")}))}_showLoadingModal(){this.state.isLoading=!0,this.backdropElement=document.createElement("div"),this.backdropElement.className="feedback-panel-backdrop",document.body.appendChild(this.backdropElement),this.loadingElement=document.createElement("div"),this.loadingElement.className=`feedback-loading-modal theme-${this.options.theme}`,this.loadingElement.innerHTML='\n\t\t\t<div class="feedback-loading-spinner"></div>\n\t\t',document.body.appendChild(this.loadingElement),requestAnimationFrame(()=>{this.backdropElement.classList.add("show"),this.loadingElement.classList.add("show")})}_hideLoadingModal(){this.state.isLoading=!1,this.loadingElement&&(this.loadingElement.remove(),this.loadingElement=null)}closePanel(){this.panelElement&&this.panelElement.classList.remove("open"),this.backdropElement&&this.backdropElement.classList.remove("show"),setTimeout(()=>{this.state.isOpen=!1,this.panelElement&&this.panelElement.parentNode&&(this.panelElement.parentNode.removeChild(this.panelElement),this.panelElement=null),this.backdropElement&&this.backdropElement.parentNode&&(this.backdropElement.parentNode.removeChild(this.backdropElement),this.backdropElement=null),this._resetForm()},300)}async submitFeedback(){if(!this.state.isSubmitting){this._hideError();try{this.state.isSubmitting=!0,this._updateSubmitButton();const e={title:this.state.title||"Feedback",content:this.state.content,email:this.state.email,board_id:this.options.boardId,attachments:this.state.attachments};if(!this.state.content.trim())return void this._showError("Please enter your feedback message.");const t=await this.apiService.submitFeedback(e);this._showSuccessMessage(),this.closePanel(),this.sdk.eventBus.emit("feedback:submitted",{widget:this,feedback:t})}catch(e){this._showError("Failed to submit feedback. Please try again."),this.sdk.eventBus.emit("feedback:error",{widget:this,error:e})}finally{this.state.isSubmitting=!1,this._updateSubmitButton()}}}handleConfigUpdate(e){this.options.theme=e.theme,this.element&&this._updateTheme()}destroy(){this.destroyed||(this.onDestroy(),this.closePanel(),this.element&&this.element.parentNode&&this.element.parentNode.removeChild(this.element),this.destroyed=!0,this.mounted=!1,this.sdk.eventBus.emit("widget:destroyed",{widget:this}))}onMount(){}onDestroy(){}_render(){throw new Error("_render() must be implemented by concrete widget")}_attachEvents(){}_bindMethods(){this.openPanel=this.openPanel.bind(this),this.closePanel=this.closePanel.bind(this),this.submitFeedback=this.submitFeedback.bind(this)}_renderPanel(){if(this.panelElement)return;this.options.showBackdrop&&!this.backdropElement&&(this.backdropElement=document.createElement("div"),this.backdropElement.className="feedback-panel-backdrop",document.body.appendChild(this.backdropElement),this.backdropElement.addEventListener("click",this.closePanel));const e="modal"===this.options.displayMode?"feedback-modal":"feedback-panel",t=`size-${this.options.size}`;this.panelElement=document.createElement("div"),this.panelElement.className=`${e} ${t}`,this.panelElement.style.setProperty("--primary-color",this.options.primaryColor),this.panelElement.style.setProperty("--bg-color",this.options.backgroundColor),this.panelElement.style.setProperty("--text-color",this.options.textColor),this.panelElement.innerHTML=this._getPanelHTML(),document.body.appendChild(this.panelElement),this._attachPanelEvents();const n=this.panelElement.querySelector("input, textarea");n&&setTimeout(()=>n.focus(),350)}_getPanelHTML(){return`\n <div class="feedback-panel-content">\n <div class="feedback-panel-header">\n <h3>Share Your Thoughts</h3>\n <button class="feedback-panel-close" type="button" aria-label="Close">&times;</button>\n </div>\n <div class="feedback-panel-body">\n <form class="feedback-form">\n <div class="feedback-form-group">\n <div class="feedback-input-container">\n <input \n type="text" \n id="feedback-title-${this.id}" \n name="title" \n placeholder="Title"\n value="${this.state.title}"\n />\n <textarea \n id="feedback-content-${this.id}" \n name="content" \n placeholder="Tell us what's on your mind..."\n required\n >${this.state.content}</textarea>\n </div>\n </div>\n <div class="feedback-error" role="alert"></div>\n <div class="feedback-form-group">\n <button type="submit" class="feedback-btn feedback-btn-submit">\n ${this.state.isSubmitting?"Sending...":"Submit Feedback"}\n </button>\n </div>\n </form>\n </div>\n </div>\n `}_attachPanelEvents(){const e=this.panelElement;e.querySelector(".feedback-panel-close").addEventListener("click",this.closePanel);e.querySelector(".feedback-form").addEventListener("submit",e=>{e.preventDefault(),this.submitFeedback()}),e.querySelector('input[name="title"]').addEventListener("input",e=>{this.state.title=e.target.value}),e.querySelector('textarea[name="content"]').addEventListener("input",e=>{this.state.content=e.target.value});const t=e=>{"Escape"===e.key&&(this.closePanel(),document.removeEventListener("keydown",t))};document.addEventListener("keydown",t)}_updateSubmitButton(){if(this.panelElement){const e=this.panelElement.querySelector(".feedback-btn-submit");e&&(e.textContent=this.state.isSubmitting?"Sending...":"Send Feedback",e.disabled=this.state.isSubmitting)}}_showError(e){if(this.panelElement){const t=this.panelElement.querySelector(".feedback-error");t&&(t.textContent=e,t.classList.add("show"))}}_hideError(){if(this.panelElement){const e=this.panelElement.querySelector(".feedback-error");e&&e.classList.remove("show")}}_showSuccessMessage(){const e=document.createElement("div");e.className="feedback-success-notification",e.innerHTML='\n <div class="feedback-success-content">\n <div class="feedback-success-icon">✓</div>\n <span>Feedback submitted successfully!</span>\n <button class="feedback-success-close" aria-label="Close">&times;</button>\n </div>\n ',document.body.appendChild(e);const t=()=>{e.parentNode&&(e.style.opacity="0",setTimeout(()=>{e.parentNode&&e.parentNode.removeChild(e)},300))};e.querySelector(".feedback-success-close").addEventListener("click",t),setTimeout(t,4e3)}_resetForm(){this.state.title="",this.state.content="",this.state.email="",this.state.errors={}}_updateTheme(){this.element&&(this.element.className=this.element.className.replace(/theme-\w+/,`theme-${this.options.theme}`)),this.panelElement&&(this.panelElement.className=this.panelElement.className.replace(/theme-\w+/,`theme-${this.options.theme}`))}openModal(){this.openPanel()}closeModal(){this.closePanel()}}class m extends f{constructor(e){super({...e,type:"button"})}_render(){const e=document.createElement("div");return e.className=`feedback-widget feedback-widget-button theme-${this.options.theme} position-${this.options.position}`,e.innerHTML='\n <button class="feedback-trigger-btn" type="button" aria-label="Send feedback">\n <svg width="28" height="32" viewBox="0 0 28 32" fill="none" xmlns="http://www.w3.org/2000/svg">\n <path fill-rule="evenodd" clip-rule="evenodd" d="M15.0615 5.28044C8.5161 4.42949 3.30825 11.1456 5.89967 17.6588C6.9321 20.2538 9.06268 22.2644 11.8777 23.1968C16.2682 24.6507 18.4038 22.3222 19.0483 23.9691C19.4055 24.8894 18.7282 25.3209 17.988 25.4938C10.9146 27.15 5.15304 22.7566 3.5869 17.5531C1.52205 10.6941 5.98684 4.6667 11.3483 3.41065C17.8801 1.88094 24.0325 6.19355 24.3926 12.7175C24.7448 19.0921 18.6217 24.5978 11.927 22.2036C10.8789 21.8285 8.8419 20.6682 8.46823 19.858C8.06026 18.9727 8.80261 18.1725 9.68285 18.3576C10.2223 18.4726 10.3116 18.8706 11.3161 19.5372C14.4549 21.6213 19.1276 20.6132 21.2046 17.0972C23.991 12.3817 21.0481 6.05351 15.06 5.27758L15.0615 5.28044Z" fill="#21244A"/>\n <path fill-rule="evenodd" clip-rule="evenodd" d="M15.2492 2.19833C11.944 1.71463 8.88819 3.07214 6.91479 4.49682C2.27067 7.85488 0.76169 14.5038 3.49672 19.8731C4.08535 21.0096 4.84379 22.0497 5.7459 22.9576L7.16343 24.2515C7.67214 24.9131 7.27203 25.7176 6.64115 25.9269C5.13502 26.4271 2.0499 21.8172 1.42044 20.5383C0.0872204 17.8297 -0.312889 14.9047 0.242977 11.503C1.66908 2.77063 11.221 -2.51652 19.7197 1.21021C27.7548 4.73331 30.2733 15.4555 23.9351 22.0773C23.3107 22.7296 21.6352 24.4823 20.6278 23.8907C20.0076 23.5263 19.8933 22.6446 20.5192 22.1238C21.0301 21.6986 21.4759 21.435 21.9896 20.9734C23.6665 19.4688 25.2562 16.8752 25.3477 13.5636C25.4427 10.2055 24.1266 7.5848 22.3904 5.74859C20.6392 3.89665 18.6751 2.69919 15.2456 2.19691L15.2492 2.19833Z" fill="#F69F06"/>\n <path fill-rule="evenodd" clip-rule="evenodd" d="M8.48332 27.2217C7.93817 26.265 8.89987 25.3776 10.1352 25.8641C15.5653 27.9926 18.3081 25.5269 19.0255 27.0823C19.2655 27.6039 19.0448 28.1619 18.7354 28.3863C17.9895 28.9257 14.82 28.9343 13.9262 28.8714C12.9071 28.8053 11.897 28.6377 10.9111 28.3713C10.0888 28.1348 8.88057 27.9247 8.48189 27.2281L8.48332 27.2217Z" fill="#21244A"/>\n <path fill-rule="evenodd" clip-rule="evenodd" d="M15.8722 31.0607C15.7765 32.1381 14.579 32.0331 13.5766 31.9545C12.5742 31.8759 11.5203 31.8502 11.601 30.7013C11.6789 29.5882 12.8035 29.7532 13.8274 29.8332C14.4425 29.8811 15.9951 29.681 15.8722 31.0607Z" fill="#21244A"/>\n </svg>\n </button>\n ',this.options.customStyles&&Object.assign(e.style,this.options.customStyles),e}_attachEvents(){const e=this.element.querySelector(".feedback-trigger-btn");e.addEventListener("click",this.openPanel),e.addEventListener("mouseenter",()=>{this.state.isSubmitting||(e.style.transform="scale(1.1)")}),e.addEventListener("mouseleave",()=>{e.style.transform="scale(1)"})}updateText(e){console.warn("ButtonWidget: Text display is disabled for circular design")}updatePosition(e){this.options.position=e,this.element&&(this.element.className=this.element.className.replace(/position-\w+-\w+/,`position-${e}`))}}class b extends f{constructor(e){super({...e,type:"inline"})}_render(){const e=document.createElement("div");return e.className=`feedback-widget feedback-widget-inline theme-${this.options.theme}`,e.innerHTML=`\n <div class="feedback-inline-content">\n <h3>Send us your feedback</h3>\n <form class="feedback-inline-form">\n <div class="feedback-form-group">\n <input \n type="text" \n name="title" \n placeholder="Title (optional)"\n value="${this.state.title}"\n />\n </div>\n <div class="feedback-form-group">\n <textarea \n name="content" \n placeholder="Your feedback..."\n required\n >${this.state.content}</textarea>\n </div>\n <div class="feedback-form-group">\n <input \n type="email" \n name="email" \n placeholder="Email (optional)"\n value="${this.state.email}"\n />\n </div>\n <button type="submit" class="feedback-btn feedback-btn-submit">\n Send Feedback\n </button>\n <div class="feedback-error" style="display: none;"></div>\n </form>\n </div>\n `,this.options.customStyles&&Object.assign(e.style,this.options.customStyles),e}_attachEvents(){const e=this.element.querySelector(".feedback-inline-form");e.addEventListener("submit",e=>{e.preventDefault(),this.submitFeedback()}),e.querySelector('input[name="title"]').addEventListener("input",e=>{this.state.title=e.target.value}),e.querySelector('textarea[name="content"]').addEventListener("input",e=>{this.state.content=e.target.value}),e.querySelector('input[name="email"]').addEventListener("input",e=>{this.state.email=e.target.value})}openModal(){const e=this.element.querySelector('textarea[name="content"]');e&&e.focus()}closeModal(){}_showSuccessMessage(){const e=this.element.querySelector(".feedback-inline-content"),t=e.innerHTML;e.innerHTML='\n <div class="feedback-success">\n <div class="feedback-success-icon">✓</div>\n <h3>Thank you!</h3>\n <p>Your feedback has been submitted successfully.</p>\n <button class="feedback-btn feedback-btn-reset">Send Another</button>\n </div>\n ';e.querySelector(".feedback-btn-reset").addEventListener("click",()=>{e.innerHTML=t,this._attachEvents(),this._resetForm()})}_showError(e){const t=this.element.querySelector(".feedback-error");t&&(t.textContent=e,t.style.display="block",setTimeout(()=>{t&&(t.style.display="none")},5e3))}_updateSubmitButton(){const e=this.element.querySelector(".feedback-btn-submit");e&&(e.textContent=this.state.isSubmitting?"Sending...":"Send Feedback",e.disabled=this.state.isSubmitting)}updateTitle(e){const t=this.element?.querySelector("h3");t&&(t.textContent=e)}setPlaceholder(e,t){const n=this.element?.querySelector(`[name="${e}"]`);n&&(n.placeholder=t)}}class y extends f{constructor(e){super({...e,type:"survey"}),this.surveyOptions={surveyType:e.surveyType||"nps",position:e.position||"bottom-right",title:e.title||null,description:e.description||null,lowLabel:e.lowLabel||null,highLabel:e.highLabel||null,customQuestions:e.customQuestions||[],theme:e.theme||"light",onSubmit:e.onSubmit||null,onDismiss:e.onDismiss||null},this.surveyState={score:null,feedback:"",customAnswers:{},isVisible:!1}}_render(){const e=document.createElement("div");return e.className="feedback-survey-container",e.style.display="none",e}_attachEvents(){}show(){return this._renderSurvey(),this.surveyState.isVisible=!0,this.sdk.eventBus.emit("survey:shown",{widget:this,type:this.surveyOptions.surveyType}),this}hide(){return this._closeSurvey(),this}_renderSurvey(){this._closeSurvey();const e=this._getSurveyConfig(),t=this._getPositionStyles(),n="dark"===this.surveyOptions.theme?"background: #1a1a1a; color: #fff;":"background: #fff; color: #1d1d1f;";"center"===this.surveyOptions.position&&(this.backdropElement=document.createElement("div"),this.backdropElement.className="feedback-survey-backdrop",document.body.appendChild(this.backdropElement),this.backdropElement.addEventListener("click",()=>this._handleDismiss())),this.surveyElement=document.createElement("div"),this.surveyElement.className=`feedback-survey feedback-survey-${this.surveyOptions.position} theme-${this.surveyOptions.theme}`,this.surveyElement.style.cssText=`position: fixed; ${t} z-index: 10000; ${n} border-radius: 16px; box-shadow: 0 20px 60px rgba(0,0,0,0.3); padding: 24px; min-width: 320px; max-width: 400px; font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;`,this.surveyElement.innerHTML=`\n\t\t\t<button class="feedback-survey-close" style="position: absolute; top: 12px; right: 12px; background: none; border: none; font-size: 20px; cursor: pointer; color: ${"dark"===this.surveyOptions.theme?"#888":"#86868b"}; line-height: 1;">&times;</button>\n\t\t\t<h3 class="feedback-survey-title" style="margin: 0 0 8px 0; font-size: 18px; font-weight: 600; padding-right: 24px;">${e.title}</h3>\n\t\t\t<p class="feedback-survey-description" style="color: ${"dark"===this.surveyOptions.theme?"#aaa":"#86868b"}; margin: 0 0 20px 0; font-size: 14px;">${e.description}</p>\n\t\t\t<div class="feedback-survey-content">${e.html}</div>\n\t\t\t<div class="feedback-survey-feedback" style="margin-top: 16px;">\n\t\t\t\t<textarea class="feedback-survey-textarea" placeholder="Any additional feedback? (optional)" style="width: 100%; padding: 12px; border: 1px solid ${"dark"===this.surveyOptions.theme?"#333":"#d2d2d7"}; border-radius: 8px; font-size: 14px; resize: none; height: 80px; background: ${"dark"===this.surveyOptions.theme?"#2a2a2a":"#fff"}; color: ${"dark"===this.surveyOptions.theme?"#fff":"#1d1d1f"}; font-family: inherit; box-sizing: border-box;"></textarea>\n\t\t\t</div>\n\t\t\t<button class="feedback-survey-submit" style="width: 100%; margin-top: 12px; padding: 12px; background: #007aff; color: white; border: none; border-radius: 8px; font-size: 14px; font-weight: 500; cursor: pointer; font-family: inherit;">Submit</button>\n\t\t`,document.body.appendChild(this.surveyElement),this._attachSurveyEvents(),requestAnimationFrame(()=>{this.surveyElement.style.opacity="1",this.surveyElement.style.transform="center"===this.surveyOptions.position?"translate(-50%, -50%) scale(1)":"translateY(0)"})}_getSurveyConfig(){const e={nps:{title:this.surveyOptions.title||"How likely are you to recommend us?",description:this.surveyOptions.description||"On a scale of 0-10, how likely are you to recommend our product to a friend or colleague?",html:`\n\t\t\t\t\t<div class="feedback-survey-nps" style="display: flex; justify-content: space-between; gap: 4px;">\n\t\t\t\t\t\t${[...Array(11).keys()].map(e=>`\n\t\t\t\t\t\t\t<button class="feedback-survey-nps-btn" data-score="${e}" style="width: 28px; height: 36px; border: 1px solid ${"dark"===this.surveyOptions.theme?"#444":"#d2d2d7"}; border-radius: 6px; background: ${"dark"===this.surveyOptions.theme?"#2a2a2a":"#f8f9fa"}; cursor: pointer; font-size: 12px; color: ${"dark"===this.surveyOptions.theme?"#fff":"#1d1d1f"}; transition: all 0.15s;">${e}</button>\n\t\t\t\t\t\t`).join("")}\n\t\t\t\t\t</div>\n\t\t\t\t\t<div style="display: flex; justify-content: space-between; margin-top: 8px; font-size: 11px; color: ${"dark"===this.surveyOptions.theme?"#888":"#86868b"};">\n\t\t\t\t\t\t<span>${this.surveyOptions.lowLabel||"Not likely"}</span>\n\t\t\t\t\t\t<span>${this.surveyOptions.highLabel||"Very likely"}</span>\n\t\t\t\t\t</div>\n\t\t\t\t`},csat:{title:this.surveyOptions.title||"How satisfied are you?",description:this.surveyOptions.description||"How would you rate your overall satisfaction with our product?",html:`\n\t\t\t\t\t<div class="feedback-survey-csat" style="display: flex; justify-content: center; gap: 16px;">\n\t\t\t\t\t\t${["😞","😕","😐","🙂","😄"].map((e,t)=>`\n\t\t\t\t\t\t\t<button class="feedback-survey-csat-btn" data-score="${t+1}" style="background: none; border: none; cursor: pointer; font-size: 36px; transition: transform 0.15s; padding: 8px;">${e}</button>\n\t\t\t\t\t\t`).join("")}\n\t\t\t\t\t</div>\n\t\t\t\t\t<div style="display: flex; justify-content: space-between; margin-top: 8px; font-size: 11px; color: ${"dark"===this.surveyOptions.theme?"#888":"#86868b"};">\n\t\t\t\t\t\t<span>${this.surveyOptions.lowLabel||"Very dissatisfied"}</span>\n\t\t\t\t\t\t<span>${this.surveyOptions.highLabel||"Very satisfied"}</span>\n\t\t\t\t\t</div>\n\t\t\t\t`},ces:{title:this.surveyOptions.title||"How easy was it?",description:this.surveyOptions.description||"How easy was it to accomplish your task today?",html:`\n\t\t\t\t\t<div class="feedback-survey-ces" style="display: flex; justify-content: space-between; gap: 8px;">\n\t\t\t\t\t\t${["Very Difficult","Difficult","Neutral","Easy","Very Easy"].map((e,t)=>`\n\t\t\t\t\t\t\t<button class="feedback-survey-ces-btn" data-score="${t+1}" style="flex: 1; padding: 12px 8px; border: 1px solid ${"dark"===this.surveyOptions.theme?"#444":"#d2d2d7"}; border-radius: 8px; background: ${"dark"===this.surveyOptions.theme?"#2a2a2a":"#f8f9fa"}; cursor: pointer; font-size: 11px; color: ${"dark"===this.surveyOptions.theme?"#fff":"#1d1d1f"}; transition: all 0.15s;">${e}</button>\n\t\t\t\t\t\t`).join("")}\n\t\t\t\t\t</div>\n\t\t\t\t`},custom:{title:this.surveyOptions.title||"Quick Feedback",description:this.surveyOptions.description||"Help us improve by answering a few questions.",html:this._renderCustomQuestions()}};return e[this.surveyOptions.surveyType]||e.nps}_renderCustomQuestions(){return this.surveyOptions.customQuestions&&0!==this.surveyOptions.customQuestions.length?this.surveyOptions.customQuestions.map((e,t)=>`\n\t\t\t<div style="margin-bottom: 16px;">\n\t\t\t\t<label style="display: block; margin-bottom: 6px; font-size: 13px; font-weight: 500;">${e.label}</label>\n\t\t\t\t${this._renderQuestionInput(e,t)}\n\t\t\t</div>\n\t\t`).join(""):`\n\t\t\t\t<div style="margin-bottom: 16px;">\n\t\t\t\t\t<label style="display: block; margin-bottom: 6px; font-size: 13px; font-weight: 500;">What feature do you use most?</label>\n\t\t\t\t\t<select class="feedback-survey-select" data-question="feature" style="width: 100%; padding: 10px; border: 1px solid ${"dark"===this.surveyOptions.theme?"#444":"#d2d2d7"}; border-radius: 8px; font-size: 14px; background: ${"dark"===this.surveyOptions.theme?"#2a2a2a":"#fff"}; color: ${"dark"===this.surveyOptions.theme?"#fff":"#1d1d1f"};">\n\t\t\t\t\t\t<option value="">Select a feature</option>\n\t\t\t\t\t\t<option value="feedback">Feedback Collection</option>\n\t\t\t\t\t\t<option value="surveys">Surveys</option>\n\t\t\t\t\t\t<option value="analytics">Analytics</option>\n\t\t\t\t\t\t<option value="integrations">Integrations</option>\n\t\t\t\t\t</select>\n\t\t\t\t</div>\n\t\t\t\t<div>\n\t\t\t\t\t<label style="display: block; margin-bottom: 6px; font-size: 13px; font-weight: 500;">How often do you use it?</label>\n\t\t\t\t\t<div class="feedback-survey-frequency" style="display: flex; gap: 8px;">\n\t\t\t\t\t\t${["Daily","Weekly","Monthly","Rarely"].map(e=>`\n\t\t\t\t\t\t\t<button class="feedback-survey-freq-btn" data-freq="${e}" style="flex: 1; padding: 10px; border: 1px solid ${"dark"===this.surveyOptions.theme?"#444":"#d2d2d7"}; border-radius: 8px; background: ${"dark"===this.surveyOptions.theme?"#2a2a2a":"#f8f9fa"}; cursor: pointer; font-size: 12px; color: ${"dark"===this.surveyOptions.theme?"#fff":"#1d1d1f"}; transition: all 0.15s;">${e}</button>\n\t\t\t\t\t\t`).join("")}\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t`}_renderQuestionInput(e,t){switch(e.type){case"select":return`\n\t\t\t\t\t<select class="feedback-survey-select" data-question="${e.id||t}" style="width: 100%; padding: 10px; border: 1px solid ${"dark"===this.surveyOptions.theme?"#444":"#d2d2d7"}; border-radius: 8px; font-size: 14px; background: ${"dark"===this.surveyOptions.theme?"#2a2a2a":"#fff"}; color: ${"dark"===this.surveyOptions.theme?"#fff":"#1d1d1f"};">\n\t\t\t\t\t\t<option value="">${e.placeholder||"Select an option"}</option>\n\t\t\t\t\t\t${e.options.map(e=>`<option value="${e.value}">${e.label}</option>`).join("")}\n\t\t\t\t\t</select>\n\t\t\t\t`;case"text":return`\n\t\t\t\t\t<input type="text" class="feedback-survey-input" data-question="${e.id||t}" placeholder="${e.placeholder||""}" style="width: 100%; padding: 10px; border: 1px solid ${"dark"===this.surveyOptions.theme?"#444":"#d2d2d7"}; border-radius: 8px; font-size: 14px; background: ${"dark"===this.surveyOptions.theme?"#2a2a2a":"#fff"}; color: ${"dark"===this.surveyOptions.theme?"#fff":"#1d1d1f"}; box-sizing: border-box;">\n\t\t\t\t`;default:return""}}_getPositionStyles(){const e={"bottom-right":"bottom: 24px; right: 24px; opacity: 0; transform: translateY(20px); transition: all 0.3s ease;","bottom-left":"bottom: 24px; left: 24px; opacity: 0; transform: translateY(20px); transition: all 0.3s ease;",center:"top: 50%; left: 50%; transform: translate(-50%, -50%) scale(0.95); opacity: 0; transition: all 0.3s ease;",bottom:"bottom: 0; left: 0; right: 0; border-radius: 16px 16px 0 0; max-width: none; opacity: 0; transform: translateY(20px); transition: all 0.3s ease;"};return e[this.surveyOptions.position]||e["bottom-right"]}_attachSurveyEvents(){if(!this.surveyElement)return;this.surveyElement.querySelector(".feedback-survey-close").addEventListener("click",()=>this._handleDismiss());this.surveyElement.querySelector(".feedback-survey-submit").addEventListener("click",()=>this._handleSubmit());this.surveyElement.querySelector(".feedback-survey-textarea").addEventListener("input",e=>{this.surveyState.feedback=e.target.value}),this._attachTypeSpecificEvents(),this._escapeHandler=e=>{"Escape"===e.key&&this._handleDismiss()},document.addEventListener("keydown",this._escapeHandler)}_attachTypeSpecificEvents(){const e=this.surveyOptions.surveyType;"nps"===e&&this.surveyElement.querySelectorAll(".feedback-survey-nps-btn").forEach(e=>{e.addEventListener("click",()=>this._selectNPS(parseInt(e.dataset.score))),e.addEventListener("mouseenter",()=>{this.surveyState.score!==parseInt(e.dataset.score)&&(e.style.borderColor="#007aff")}),e.addEventListener("mouseleave",()=>{this.surveyState.score!==parseInt(e.dataset.score)&&(e.style.borderColor="dark"===this.surveyOptions.theme?"#444":"#d2d2d7")})}),"csat"===e&&this.surveyElement.querySelectorAll(".feedback-survey-csat-btn").forEach(e=>{e.addEventListener("click",()=>this._selectCSAT(parseInt(e.dataset.score))),e.addEventListener("mouseenter",()=>{e.style.transform="scale(1.1)"}),e.addEventListener("mouseleave",()=>{this.surveyState.score!==parseInt(e.dataset.score)&&(e.style.transform="scale(1)")})}),"ces"===e&&this.surveyElement.querySelectorAll(".feedback-survey-ces-btn").forEach(e=>{e.addEventListener("click",()=>this._selectCES(parseInt(e.dataset.score))),e.addEventListener("mouseenter",()=>{this.surveyState.score!==parseInt(e.dataset.score)&&(e.style.borderColor="#007aff")}),e.addEventListener("mouseleave",()=>{this.surveyState.score!==parseInt(e.dataset.score)&&(e.style.borderColor="dark"===this.surveyOptions.theme?"#444":"#d2d2d7")})}),"custom"===e&&(this.surveyElement.querySelectorAll(".feedback-survey-freq-btn").forEach(e=>{e.addEventListener("click",()=>this._selectFrequency(e.dataset.freq))}),this.surveyElement.querySelectorAll(".feedback-survey-select").forEach(e=>{e.addEventListener("change",t=>{this.surveyState.customAnswers[e.dataset.question]=t.target.value})}),this.surveyElement.querySelectorAll(".feedback-survey-input").forEach(e=>{e.addEventListener("input",t=>{this.surveyState.customAnswers[e.dataset.question]=t.target.value})}))}_selectNPS(e){this.surveyState.score=e,this.surveyElement.querySelectorAll(".feedback-survey-nps-btn").forEach(t=>{parseInt(t.dataset.score)===e?(t.style.background="#007aff",t.style.borderColor="#007aff",t.style.color="#fff"):(t.style.background="dark"===this.surveyOptions.theme?"#2a2a2a":"#f8f9fa",t.style.borderColor="dark"===this.surveyOptions.theme?"#444":"#d2d2d7",t.style.color="dark"===this.surveyOptions.theme?"#fff":"#1d1d1f")})}_selectCSAT(e){this.surveyState.score=e,this.surveyElement.querySelectorAll(".feedback-survey-csat-btn").forEach(t=>{const n=parseInt(t.dataset.score);t.style.transform=n===e?"scale(1.2)":"scale(1)"})}_selectCES(e){this.surveyState.score=e,this.surveyElement.querySelectorAll(".feedback-survey-ces-btn").forEach(t=>{parseInt(t.dataset.score)===e?(t.style.background="#007aff",t.style.borderColor="#007aff",t.style.color="#fff"):(t.style.background="dark"===this.surveyOptions.theme?"#2a2a2a":"#f8f9fa",t.style.borderColor="dark"===this.surveyOptions.theme?"#444":"#d2d2d7",t.style.color="dark"===this.surveyOptions.theme?"#fff":"#1d1d1f")})}_selectFrequency(e){this.surveyState.customAnswers.frequency=e,this.surveyElement.querySelectorAll(".feedback-survey-freq-btn").forEach(t=>{t.dataset.freq===e?(t.style.background="#007aff",t.style.borderColor="#007aff",t.style.color="#fff"):(t.style.background="dark"===this.surveyOptions.theme?"#2a2a2a":"#f8f9fa",t.style.borderColor="dark"===this.surveyOptions.theme?"#444":"#d2d2d7",t.style.color="dark"===this.surveyOptions.theme?"#fff":"#1d1d1f")})}async _handleSubmit(){const e=this.surveyOptions.surveyType;if(("nps"===e||"csat"===e||"ces"===e)&&null===this.surveyState.score)return void this._showError("Please select a rating");const t={type:e,score:this.surveyState.score,feedback:this.surveyState.feedback,customAnswers:this.surveyState.customAnswers,timestamp:(new Date).toISOString()};if(this.surveyOptions.onSubmit&&this.surveyOptions.onSubmit(t),!this.sdk.config.mock)try{await this.apiService.submitSurveyResponse(t)}catch(e){console.error("[SurveyWidget] Failed to submit survey:",e)}this.sdk.eventBus.emit("survey:submitted",{widget:this,response:t}),this._closeSurvey(),this._showSuccessNotification()}_handleDismiss(){this.surveyOptions.onDismiss&&this.surveyOptions.onDismiss(),this.sdk.eventBus.emit("survey:dismissed",{widget:this}),this._closeSurvey()}_showError(e){const t=this.surveyElement.querySelector(".feedback-survey-error");t&&t.remove();const n=document.createElement("div");n.className="feedback-survey-error",n.style.cssText="color: #ef4444; font-size: 13px; margin-top: 8px; text-align: center;",n.textContent=e;const s=this.surveyElement.querySelector(".feedback-survey-submit");s.parentNode.insertBefore(n,s),setTimeout(()=>n.remove(),3e3)}_showSuccessNotification(){const e=document.createElement("div");e.className="feedback-survey-success",e.style.cssText="\n\t\t\tposition: fixed;\n\t\t\ttop: 24px;\n\t\t\tright: 24px;\n\t\t\tbackground: #10b981;\n\t\t\tcolor: white;\n\t\t\tpadding: 16px 24px;\n\t\t\tborder-radius: 12px;\n\t\t\tfont-size: 14px;\n\t\t\tfont-weight: 500;\n\t\t\tz-index: 10001;\n\t\t\tbox-shadow: 0 10px 40px rgba(0,0,0,0.2);\n\t\t\tfont-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;\n\t\t",e.innerHTML='\n\t\t\t<div style="display: flex; align-items: center; gap: 8px;">\n\t\t\t\t<span style="font-size: 18px;">✓</span>\n\t\t\t\t<span>Thank you for your feedback!</span>\n\t\t\t</div>\n\t\t',document.body.appendChild(e),setTimeout(()=>{e.style.opacity="0",e.style.transition="opacity 0.3s ease",setTimeout(()=>e.remove(),300)},3e3)}_closeSurvey(){this._escapeHandler&&(document.removeEventListener("keydown",this._escapeHandler),this._escapeHandler=null);const e=this.surveyElement,t=this.backdropElement;e&&(e.style.opacity="0",e.style.transform="center"===this.surveyOptions.position?"translate(-50%, -50%) scale(0.95)":"translateY(20px)",setTimeout(()=>{e&&e.parentNode&&e.parentNode.removeChild(e)},300),this.surveyElement=null),t&&(t.style.opacity="0",setTimeout(()=>{t&&t.parentNode&&t.parentNode.removeChild(t)},300),this.backdropElement=null),this.surveyState={score:null,feedback:"",customAnswers:{},isVisible:!1}}destroy(){this._closeSurvey(),super.destroy()}}class g extends f{constructor(e){super({...e,type:"tab"})}_render(){const e=document.createElement("div");return e.className=`feedback-widget feedback-widget-tab theme-${this.options.theme} position-${this.options.position}`,e.innerHTML='\n <div class="feedback-tab-trigger">\n <span class="feedback-tab-text">Feedback</span>\n </div>\n ',this.options.customStyles&&Object.assign(e.style,this.options.customStyles),e}_attachEvents(){const e=this.element.querySelector(".feedback-tab-trigger");e.addEventListener("click",this.openModal),e.addEventListener("mouseenter",()=>{this.state.isSubmitting||(e.style.transform=this._getHoverTransform())}),e.addEventListener("mouseleave",()=>{e.style.transform="none"})}_getHoverTransform(){const e=this.options.position;return e.includes("right")?"translateX(-5px)":e.includes("left")?"translateX(5px)":"none"}updateText(e){const t=this.element?.querySelector(".feedback-tab-text");t&&(t.textContent=e)}updatePosition(e){this.options.position=e,this.element&&(this.element.className=this.element.className.replace(/position-\w+-\w+/,`position-${e}`))}}class k{static widgets=new Map([["button",m],["tab",g],["inline",b],["survey",y]]);static register(e,n){if("string"!=typeof e||!e.trim())throw new t("Widget type must be a non-empty string");if("function"!=typeof n)throw new t("Widget class must be a constructor function");this.widgets.set(e,n)}static create(e,n={}){const s=this.widgets.get(e);if(!s){const n=Array.from(this.widgets.keys()).join(", ");throw new t(`Unknown widget type: ${e}. Available types: ${n}`)}try{return new s(n)}catch(n){throw new t(`Failed to create widget of type '${e}': ${n.message}`,n)}}static getAvailableTypes(){return Array.from(this.widgets.keys())}static isTypeRegistered(e){return this.widgets.has(e)}static unregister(e){return this.widgets.delete(e)}static clear(){this.widgets.clear()}static getWidgetClass(e){return this.widgets.get(e)}}class v{constructor(e={}){this.config=this._validateAndMergeConfig(e),this.initialized=!1,this.widgets=new Map,this.eventBus=new c,this.apiService=new d({apiUrl:this.config.apiUrl,workspace:this.config.workspace,userContext:this.config.userContext,mock:this.config.mock,env:this.config.env}),this._bindMethods()}async init(){if(this.initialized)return{alreadyInitialized:!0};try{const e=await this.apiService.init(this.config.userContext);return e.config&&(this.config=u(e.config,this.config)),this.initialized=!0,this.eventBus.emit("sdk:initialized",{config:this.config,sessionToken:e.sessionToken}),{initialized:!0,config:e.config||{},sessionToken:e.sessionToken,expiresIn:e.expiresIn}}catch(e){throw this.eventBus.emit("sdk:error",{error:e}),new t(`Failed to initialize SDK: ${e.message}`,e)}}createWidget(e="button",n={}){if(!this.initialized)throw new t("SDK must be initialized before creating widgets. Call init() first.");const s=l("widget"),i={id:s,sdk:this,apiService:this.apiService,...this.config,...n};try{const t=k.create(e,i);return this.widgets.set(s,t),this.eventBus.emit("widget:created",{widget:t,type:e}),t}catch(e){throw new t(`Failed to create widget: ${e.message}`,e)}}getWidget(e){return this.widgets.get(e)}showSurvey(e={}){if(!this.initialized)throw new t("SDK must be initialized before showing surveys. Call init() first.");const n=this.createWidget("survey",{surveyType:e.surveyType||e.type||"nps",position:e.position||"bottom-right",theme:e.theme||this.config.theme||"light",title:e.title,description:e.description,lowLabel:e.lowLabel,highLabel:e.highLabel,customQuestions:e.customQuestions,onSubmit:e.onSubmit,onDismiss:e.onDismiss});return n.mount(),n.show(),n}getAllWidgets(){return Array.from(this.widgets.values())}destroyWidget(e){const t=this.widgets.get(e);return!!t&&(t.destroy(),this.widgets.delete(e),this.eventBus.emit("widget:removed",{widgetId:e}),!0)}destroyAllWidgets(){for(const e of this.widgets.values())e.destroy();this.widgets.clear(),this.eventBus.emit("widgets:cleared")}updateConfig(e){const t={...this.config};this.config=this._validateAndMergeConfig(e,this.config);for(const e of this.widgets.values())e.handleConfigUpdate(this.config);this.eventBus.emit("config:updated",{oldConfig:t,newConfig:this.config})}setUserContext(e){this.config.userContext=e,this.apiService&&this.apiService.setUserContext(e),this.eventBus.emit("user:updated",{userContext:e})}getUserContext(){return this.config.userContext||(this.apiService?this.apiService.getUserContext():null)}async reinitialize(e=null){return this.apiService.clearSession(),this.initialized=!1,e&&this.setUserContext(e),this.init()}on(e,t){return this.eventBus.on(e,t),this}off(e,t){return this.eventBus.off(e,t),this}once(e,t){return this.eventBus.once(e,t),this}emit(e,t){return this.eventBus.emit(e,t),this}destroy(){this.destroyAllWidgets(),this.eventBus.removeAllListeners(),this.apiService.clearSession(),this.initialized=!1,this.eventBus.emit("sdk:destroyed")}_validateAndMergeConfig(e,t={}){const n=u(u({apiUrl:null,workspace:null,userContext:null,position:"bottom-right",theme:"light",boardId:"general",autoShow:!0,debug:!1,mock:!1,env:"production"},t),e);if(!n.workspace)throw new i("Missing required configuration: workspace");return n.userContext&&this._validateUserContext(n.userContext),n}_validateUserContext(e){if(!e.user_id&&!e.email)throw new i("User context must include at least user_id or email");const t={user_id:"string",email:"string",name:"string",custom_fields:"object",company:"object"};for(const[n,s]of Object.entries(t))if(e[n]&&typeof e[n]!==s)throw new i(`User context field '${n}' must be of type '${s}'`)}_bindMethods(){this.createWidget=this.createWidget.bind(this),this.destroyWidget=this.destroyWidget.bind(this),this.updateConfig=this.updateConfig.bind(this)}static create(e){return new v(e)}static async createAndInit(e){const t=new v(e);return await t.init(),t}static extractUserContextFromAuth(e){return e?{user_id:e.sub||e.id||e.user_id,email:e.email,name:e.name||e.display_name||e.full_name,custom_fields:{role:e.role,plan:e.plan||e.subscription?.plan,...e.custom_fields||{}},company:e.company||e.organization?{id:e.company?.id||e.organization?.id,name:e.company?.name||e.organization?.name,monthly_spend:e.company?.monthly_spend}:void 0}:null}}function x(){if("undefined"!=typeof document&&!document.querySelector("#feedback-sdk-styles")){const e=document.createElement("style");e.id="feedback-sdk-styles",e.textContent="\n.feedback-widget {\n font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n font-size: 14px;\n line-height: 1.4;\n z-index: 999999;\n box-sizing: border-box;\n}\n\n.feedback-widget *,\n.feedback-widget *::before,\n.feedback-widget *::after {\n box-sizing: border-box;\n}\n\n.feedback-widget-button {\n position: fixed;\n z-index: 999999;\n}\n\n.feedback-widget-button.position-bottom-right {\n bottom: 20px;\n right: 20px;\n}\n\n.feedback-widget-button.position-bottom-left {\n bottom: 20px;\n left: 20px;\n}\n\n.feedback-widget-button.position-top-right {\n top: 20px;\n right: 20px;\n}\n\n.feedback-widget-button.position-top-left {\n top: 20px;\n left: 20px;\n}\n\n.feedback-widget-button.position-bottom-center {\n bottom: 20px;\n left: 50%;\n transform: translateX(-50%);\n}\n\n.feedback-widget-button.position-top-center {\n top: 20px;\n left: 50%;\n transform: translateX(-50%);\n}\n\n.feedback-widget-button.position-center {\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n}\n\n/* New button design - white with elevation */\n.feedback-trigger-btn {\n width: 52px;\n height: 52px;\n border-radius: 50%;\n border: none;\n background: #ffffff;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n box-shadow: \n -2px -2px 8px rgba(255, 255, 255, 0.8),\n 0 4px 16px rgba(0, 0, 0, 0.12),\n 0 2px 8px rgba(0, 0, 0, 0.08);\n transition: all 0.15s cubic-bezier(0.4, 0, 0.2, 1);\n padding: 0;\n}\n\n.feedback-trigger-btn:hover {\n box-shadow: \n -3px -3px 12px rgba(255, 255, 255, 0.9),\n 0 6px 20px rgba(0, 0, 0, 0.15),\n 0 3px 10px rgba(0, 0, 0, 0.1);\n transform: translateY(-2px);\n}\n\n.feedback-trigger-btn:active {\n transform: translateY(0px);\n box-shadow: \n -2px -2px 8px rgba(255, 255, 255, 0.8),\n 0 2px 12px rgba(0, 0, 0, 0.1),\n 0 1px 6px rgba(0, 0, 0, 0.08);\n}\n\n.feedback-trigger-btn svg {\n flex-shrink: 0;\n width: 22px;\n height: 25px;\n}\n\n.feedback-trigger-btn svg path {\n fill: #21244A;\n}\n\n/* Loading Modal */\n.feedback-loading-modal {\n position: fixed;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%) scale(0.9);\n z-index: 1000001;\n opacity: 0;\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.feedback-loading-modal.show {\n opacity: 1;\n transform: translate(-50%, -50%) scale(1);\n}\n\n.feedback-loading-spinner {\n width: 48px;\n height: 48px;\n border: 4px solid rgba(0, 0, 0, 0.1);\n border-top-color: #21244A;\n border-radius: 50%;\n animation: spin 0.8s linear infinite;\n}\n\n@keyframes spin {\n to { transform: rotate(360deg); }\n}\n\n/* Modal Styles (centered) */\n.feedback-modal {\n position: fixed;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%) scale(0.9);\n width: 480px;\n max-width: 90vw;\n max-height: 85vh;\n z-index: 1000000;\n opacity: 0;\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n font-family: inherit;\n}\n\n.feedback-modal.open {\n opacity: 1;\n transform: translate(-50%, -50%) scale(1);\n}\n\n.feedback-modal .feedback-panel-content {\n max-height: 85vh;\n overflow-y: auto;\n}\n\n/* Size variants */\n.feedback-modal.size-small {\n width: 360px;\n}\n\n.feedback-modal.size-medium {\n width: 480px;\n}\n\n.feedback-modal.size-large {\n width: 600px;\n}\n\n.feedback-panel.size-small {\n width: 320px;\n}\n\n.feedback-panel.size-medium {\n width: 420px;\n}\n\n.feedback-panel.size-large {\n width: 520px;\n}\n\n/* Side Panel Styles */\n.feedback-panel {\n position: fixed;\n bottom: 80px;\n right: 24px;\n width: 420px;\n max-height: 500px;\n z-index: 1000000;\n transform: translateX(calc(100% + 24px));\n transition: transform 0.35s cubic-bezier(0.4, 0, 0.2, 1);\n font-family: inherit;\n}\n\n.feedback-panel.open {\n transform: translateX(0);\n}\n\n.feedback-panel-backdrop {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.4);\n backdrop-filter: blur(4px);\n opacity: 0;\n transition: opacity 0.3s ease;\n pointer-events: none;\n z-index: 999999;\n}\n\n.feedback-panel-backdrop.show {\n opacity: 1;\n pointer-events: auto;\n}\n\n.feedback-panel-content {\n background: var(--bg-color, #ffffff);\n color: var(--text-color, #171717);\n height: 100%;\n display: flex;\n flex-direction: column;\n border-radius: 12px;\n border: 1px solid #e5e5e5;\n}\n\n.feedback-panel-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 24px 24px 20px 24px;\n flex-shrink: 0;\n}\n\n.feedback-panel-header h3 {\n margin: 0;\n font-size: 18px;\n font-weight: 600;\n color: var(--text-color, #171717);\n}\n\n.feedback-panel-close {\n background: none;\n border: none;\n font-size: 20px;\n cursor: pointer;\n color: #737373;\n padding: 0;\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 8px;\n transition: all 0.15s ease;\n}\n\n.feedback-panel-close:hover {\n background: #f5f5f5;\n color: #171717;\n}\n\n.feedback-panel-close:focus-visible {\n outline: 2px solid var(--primary-color, #21244A);\n outline-offset: 2px;\n}\n\n.feedback-panel-body {\n flex: 1;\n overflow-y: auto;\n padding: 0 24px 24px 24px;\n}\n\n.feedback-form {\n display: flex;\n flex-direction: column;\n height: 100%;\n}\n\n.feedback-form-group {\n margin-bottom: 16px;\n}\n\n.feedback-form-group:last-child {\n margin-bottom: 0;\n}\n\n/* Unified input container */\n.feedback-input-container {\n border: 1px solid #e5e5e5;\n border-radius: 8px;\n padding: 16px;\n background: #ffffff;\n transition: all 0.15s ease;\n}\n\n.feedback-input-container:focus-within {\n border-color: var(--primary-color, #21244A);\n box-shadow: 0 0 0 3px rgba(33, 36, 74, 0.08);\n}\n\n.feedback-form-group input,\n.feedback-form-group textarea {\n width: 100%;\n border: none;\n padding: 0;\n font-size: 14px;\n font-family: inherit;\n color: var(--text-color, #171717);\n background: transparent;\n outline: none;\n resize: none;\n}\n\n.feedback-form-group input {\n font-weight: 600;\n font-size: 15px;\n margin-bottom: 12px;\n}\n\n.feedback-form-group input::placeholder {\n color: #737373;\n font-weight: 600;\n}\n\n.feedback-form-group textarea {\n min-height: 120px;\n font-weight: 400;\n}\n\n.feedback-form-group textarea::placeholder {\n color: #a3a3a3;\n font-weight: 400;\n}\n\n.feedback-btn {\n position: relative;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n overflow: hidden;\n border-radius: 8px;\n border: none;\n height: 44px;\n padding: 10px 18px;\n font-size: 15px;\n font-weight: 500;\n font-family: inherit;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n\n.feedback-btn:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.feedback-btn:focus-visible {\n outline: 2px solid #21244A;\n outline-offset: 2px;\n}\n\n.feedback-btn-submit {\n background: var(--primary-color, #21244A);\n color: white;\n width: 100%;\n}\n\n.feedback-btn-submit:hover:not(:disabled) {\n background: #2d3159;\n}\n\n.feedback-btn-submit:active:not(:disabled) {\n transform: scale(0.98);\n}\n\n.feedback-error {\n background: #FEF2F2;\n border: 1px solid #FEE2E2;\n color: #DC2626;\n padding: 12px 14px;\n border-radius: 8px;\n font-size: 13px;\n margin-top: 12px;\n display: none;\n}\n\n.feedback-error.show {\n display: block;\n}\n\n.feedback-success-notification {\n position: fixed;\n top: 24px;\n right: 24px;\n z-index: 1000002;\n background: white;\n border: 1px solid #D1FAE5;\n border-radius: 12px;\n box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);\n animation: slideInRight 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n min-width: 320px;\n}\n\n.feedback-success-content {\n display: flex;\n align-items: center;\n padding: 16px 20px;\n gap: 12px;\n}\n\n.feedback-success-icon {\n width: 20px;\n height: 20px;\n border-radius: 50%;\n background: #10B981;\n color: white;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 12px;\n font-weight: 600;\n flex-shrink: 0;\n}\n\n.feedback-success-content span {\n color: #065F46;\n font-weight: 500;\n font-size: 14px;\n flex: 1;\n}\n\n.feedback-success-close {\n background: none;\n border: none;\n color: #6B7280;\n cursor: pointer;\n font-size: 20px;\n padding: 0;\n width: 24px;\n height: 24px;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.2s ease;\n border-radius: 4px;\n flex-shrink: 0;\n}\n\n.feedback-success-close:hover {\n background: #F3F4F6;\n color: #374151;\n}\n\n.feedback-success-close:focus-visible {\n outline: 2px solid #21244A;\n outline-offset: 2px;\n}\n\n@keyframes slideInRight {\n from {\n transform: translateX(400px);\n opacity: 0;\n }\n to {\n transform: translateX(0);\n opacity: 1;\n }\n}\n\n@keyframes fadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n.feedback-panel-backdrop {\n animation: fadeIn 0.3s ease;\n}\n\n@media (max-width: 768px) {\n .feedback-panel {\n width: 100%;\n top: auto;\n bottom: 0;\n right: 0;\n left: 0;\n height: 85vh;\n max-height: 85vh;\n transform: translateY(100%);\n border-radius: 20px 20px 0 0;\n }\n \n .feedback-panel.open {\n transform: translateY(0);\n }\n \n .feedback-panel-content {\n border-radius: 20px 20px 0 0;\n }\n \n .feedback-panel-header {\n padding: 20px;\n position: relative;\n }\n \n .feedback-panel-header::before {\n content: '';\n position: absolute;\n top: 8px;\n left: 50%;\n transform: translateX(-50%);\n width: 40px;\n height: 4px;\n background: #D1D5DB;\n border-radius: 2px;\n }\n \n .feedback-panel-body {\n padding: 20px;\n }\n \n .feedback-widget-button {\n bottom: 16px;\n right: 16px;\n }\n \n .feedback-widget-button.position-bottom-left {\n left: 16px;\n }\n \n .feedback-success-notification {\n top: 16px;\n right: 16px;\n left: 16px;\n min-width: auto;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .feedback-trigger-btn,\n .feedback-btn,\n .feedback-panel,\n .feedback-panel-backdrop,\n .feedback-success-notification {\n transition: none;\n animation: none;\n }\n}\n\n@media print {\n .feedback-widget,\n .feedback-panel,\n .feedback-panel-backdrop,\n .feedback-success-notification {\n display: none !important;\n }\n}\n",document.head.appendChild(e)}}function w(){if("undefined"!=typeof window&&window.FeedbackSDKConfig){x();const e={...window.FeedbackSDKConfig},t=new v(e);t.init().then(n=>{if(window.FeedbackSDK.instance=t,window.FeedbackSDKConfig.autoCreate){(Array.isArray(window.FeedbackSDKConfig.autoCreate)?window.FeedbackSDKConfig.autoCreate:[window.FeedbackSDKConfig.autoCreate]).forEach(e=>{try{t.createWidget(e.type||"button",e).mount(e.container)}catch(e){console.error("[FeedbackSDK] Failed to create widget:",e)}})}if("undefined"!=typeof CustomEvent){const s=new CustomEvent("FeedbackSDKReady",{detail:{sdk:t,config:e,initData:n}});window.dispatchEvent(s)}}).catch(t=>{if(console.error("[FeedbackSDK] Auto-initialization failed:",t),"undefined"!=typeof CustomEvent){const n=new CustomEvent("FeedbackSDKError",{detail:{error:t,config:e,phase:"initialization"}});window.dispatchEvent(n)}})}}const E={FeedbackSDK:v,BaseWidget:f,ButtonWidget:m,TabWidget:g,InlineWidget:b,SurveyWidget:y,WidgetFactory:k,EventBus:c,APIService:d,SDKError:t,APIError:n,WidgetError:s,ConfigError:i,ValidationError:o,helpers:h,create:e=>(x(),new v(e)),version:"1.0.0",instance:null,isReady:()=>Boolean(E.instance),getInstance:()=>E.instance,setUserContext:e=>{E.instance?E.instance.setUserContext(e):"undefined"!=typeof window&&(window.FeedbackSDKUserContext=e)},initWithUser:async(e,t)=>{x();const n={...e,userContext:t},s=new v(n);return await s.init(),"undefined"!=typeof window&&(window.FeedbackSDK.instance=s),s},onReady:e=>{"undefined"!=typeof window&&(E.isReady()?e(E.instance):window.addEventListener("FeedbackSDKReady",t=>{e(t.detail.sdk,t.detail)},{once:!0}))},onError:e=>{"undefined"!=typeof window&&window.addEventListener("FeedbackSDKError",t=>{e(t.detail.error,t.detail)})},extractUserContext:v.extractUserContextFromAuth};"undefined"!=typeof window&&(window.FeedbackSDK=E,"undefined"!=typeof document&&("loading"===document.readyState?document.addEventListener("DOMContentLoaded",w):setTimeout(w,0))),e.APIError=n,e.APIService=d,e.BaseWidget=f,e.ButtonWidget=m,e.ConfigError=i,e.EventBus=c,e.FeedbackSDK=v,e.InlineWidget=b,e.SDKError=t,e.SurveyWidget=y,e.TabWidget=g,e.ValidationError=o,e.WidgetError=s,e.WidgetFactory=k,e.default=E,e.helpers=h,Object.defineProperty(e,"__esModule",{value:!0})});
1
+ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).FeedbackSDK={})}(this,function(e){"use strict";class t extends Error{constructor(e,n){super(e),this.name="SDKError",this.cause=n,Error.captureStackTrace&&Error.captureStackTrace(this,t)}}class n extends Error{constructor(e,t,s){super(t),this.name="APIError",this.status=e,this.response=s,Error.captureStackTrace&&Error.captureStackTrace(this,n)}isNetworkError(){return 0===this.status}isClientError(){return this.status>=400&&this.status<500}isServerError(){return this.status>=500&&this.status<600}}class s extends Error{constructor(e,t,n){super(e),this.name="WidgetError",this.widgetType=t,this.widgetId=n,Error.captureStackTrace&&Error.captureStackTrace(this,s)}}class i extends Error{constructor(e,t){super(e),this.name="ConfigError",this.configKey=t,Error.captureStackTrace&&Error.captureStackTrace(this,i)}}class o extends Error{constructor(e,t,n){super(e),this.name="ValidationError",this.field=t,this.value=n,Error.captureStackTrace&&Error.captureStackTrace(this,o)}}const r={primaryColor:"#21244A",backgroundColor:"#ffffff",textColor:"#1F2937",boardId:"feature-requests",size:"medium",displayMode:"modal"},a={production:{base:"https://api.product7.io/api/v1",withWorkspace:e=>`https://${e}.api.product7.io/api/v1`},staging:{base:"https://staging.api.product7.io/api/v1",withWorkspace:e=>`https://${e}.staging.api.product7.io/api/v1`}};class d{constructor(e={}){if(this.workspace=e.workspace,this.sessionToken=null,this.sessionExpiry=null,this.userContext=e.userContext||null,this.mock=e.mock||!1,this.env=e.env||"production",e.apiUrl)this.baseURL=e.apiUrl;else{const e=a[this.env]||a.production;this.baseURL=this.workspace?e.withWorkspace(this.workspace):e.base}this._loadStoredSession()}async init(e=null){if(e&&(this.userContext=e),this.isSessionValid())return{sessionToken:this.sessionToken};if(!this.userContext||!this.workspace){const e=`Missing ${this.workspace?"user context":"workspace"} for initialization`;throw new n(400,e)}if(this.mock)return this.sessionToken="mock_session_"+Date.now(),this.sessionExpiry=new Date(Date.now()+36e5),this._storeSession(),{sessionToken:this.sessionToken,config:r,expiresIn:3600};const t={workspace:this.workspace,user:this.userContext};try{const e=await this._makeRequest("/widget/init",{method:"POST",body:JSON.stringify(t),headers:{"Content-Type":"application/json"}});return this.sessionToken=e.session_token,this.sessionExpiry=new Date(Date.now()+1e3*e.expires_in),this._storeSession(),{sessionToken:this.sessionToken,config:e.config||{},expiresIn:e.expires_in}}catch(e){throw new n(e.status||500,`Failed to initialize widget: ${e.message}`,e.response)}}async submitFeedback(e){if(this.isSessionValid()||await this.init(),!this.sessionToken)throw new n(401,"No valid session token available");if(this.mock)return await new Promise(e=>setTimeout(e,500)),{success:!0,data:{id:"mock_post_"+Date.now(),title:e.title,content:e.content},message:"Feedback submitted successfully!"};const t={board:e.board_id||e.board||e.boardId,title:e.title,content:e.content,attachments:e.attachments||[]};try{return await this._makeRequest("/widget/feedback",{method:"POST",body:JSON.stringify(t),headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.sessionToken}`}})}catch(t){if(401===t.status)return this.sessionToken=null,this.sessionExpiry=null,await this.init(),this.submitFeedback(e);throw new n(t.status||500,`Failed to submit feedback: ${t.message}`,t.response)}}isSessionValid(){return this.sessionToken&&this.sessionExpiry&&new Date<this.sessionExpiry}setUserContext(e){this.userContext=e,"undefined"!=typeof localStorage&&localStorage.setItem("feedbackSDK_userContext",JSON.stringify(e))}getUserContext(){return this.userContext}clearSession(){this.sessionToken=null,this.sessionExpiry=null,"undefined"!=typeof localStorage&&(localStorage.removeItem("feedbackSDK_session"),localStorage.removeItem("feedbackSDK_userContext"))}_storeSession(){if("undefined"!=typeof localStorage)try{const e={token:this.sessionToken,expiry:this.sessionExpiry.toISOString(),workspace:this.workspace};localStorage.setItem("feedbackSDK_session",JSON.stringify(e))}catch(e){}}_loadStoredSession(){if("undefined"==typeof localStorage)return!1;try{const e=localStorage.getItem("feedbackSDK_session");if(!e)return!1;const t=JSON.parse(e);return this.sessionToken=t.token,this.sessionExpiry=new Date(t.expiry),this.isSessionValid()}catch(e){return!1}}async _makeRequest(e,t={}){const s=`${this.baseURL}${e}`;try{const e=await fetch(s,t);if(!e.ok){let t=`HTTP ${e.status}`,s=null;try{s=await e.json(),t=s.message||s.error||t}catch(n){t=await e.text()||t}throw new n(e.status,t,s)}const i=e.headers.get("content-type");return i&&i.includes("application/json")?await e.json():await e.text()}catch(e){if(e instanceof n)throw e;throw new n(0,e.message,null)}}}class c{constructor(){this.events=new Map}on(e,t){return this.events.has(e)||this.events.set(e,[]),this.events.get(e).push(t),()=>this.off(e,t)}off(e,t){const n=this.events.get(e);if(n){const e=n.indexOf(t);e>-1&&n.splice(e,1)}}emit(e,t){const n=this.events.get(e);n&&n.forEach(e=>{try{e(t)}catch(e){console.error("[FeedbackSDK] Event callback error:",e)}})}once(e,t){const n=this.on(e,e=>{t(e),n()});return n}clear(){this.events.clear()}getListenerCount(e){const t=this.events.get(e);return t?t.length:0}}function l(e="feedback"){return`${e}_${Date.now()}_${Math.random().toString(36).substring(2,9)}`}function u(e,t){const n={...e};for(const s in t)t.hasOwnProperty(s)&&(t[s]&&"object"==typeof t[s]&&!Array.isArray(t[s])?n[s]=u(e[s]||{},t[s]):n[s]=t[s]);return n}function p(){return"undefined"!=typeof window&&"undefined"!=typeof document}var h=Object.freeze({__proto__:null,debounce:function(e,t){let n;return function(...s){clearTimeout(n),n=setTimeout(()=>{clearTimeout(n),e(...s)},t)}},deepMerge:u,delay:function(e){return new Promise(t=>setTimeout(t,e))},escapeRegex:function(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")},formatFileSize:function(e){if(0===e)return"0 Bytes";const t=Math.floor(Math.log(e)/Math.log(1024));return parseFloat((e/Math.pow(1024,t)).toFixed(2))+" "+["Bytes","KB","MB","GB"][t]},generateId:l,getBrowserInfo:function(){return{userAgent:navigator.userAgent,platform:navigator.platform,language:navigator.language||navigator.userLanguage,cookieEnabled:navigator.cookieEnabled,screenResolution:`${screen.width}x${screen.height}`,windowSize:`${window.innerWidth}x${window.innerHeight}`,timezone:Intl.DateTimeFormat().resolvedOptions().timeZone}},getCSSProperty:function(e,t,n=""){if(!e||!t)return n;try{return window.getComputedStyle(e).getPropertyValue(t)||n}catch(e){return n}},getCurrentTimestamp:function(){return(new Date).toISOString()},getNestedProperty:function(e,t,n=void 0){if(!e||!t)return n;const s=t.split(".");let i=e;for(const e of s){if(null==i||!(e in i))return n;i=i[e]}return i},isBrowser:p,isInViewport:function(e){if(!e)return!1;const t=e.getBoundingClientRect();return t.top>=0&&t.left>=0&&t.bottom<=(window.innerHeight||document.documentElement.clientHeight)&&t.right<=(window.innerWidth||document.documentElement.clientWidth)},isMobile:function(){return!!p()&&(/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)||window.innerWidth<=768)},isValidEmail:function(e){return!(!e||"string"!=typeof e)&&/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(e.trim())},safeJsonParse:function(e,t=null){try{return JSON.parse(e)}catch(e){return t}},sanitizeHTML:function(e){if(!e||"string"!=typeof e)return"";const t=document.createElement("div");return t.textContent=e,t.innerHTML},scrollToElement:function(e,t={}){if(!e)return;e.scrollIntoView({behavior:"smooth",block:"center",inline:"nearest",...t})},setNestedProperty:function(e,t,n){if(!e||!t)return e;const s=t.split("."),i=s.pop();let o=e;for(const e of s)e in o&&"object"==typeof o[e]||(o[e]={}),o=o[e];return o[i]=n,e},throttle:function(e,t){let n,s;return function(...i){s?(clearTimeout(n),n=setTimeout(()=>{Date.now()-s>=t&&(e(...i),s=Date.now())},t-(Date.now()-s))):(e(...i),s=Date.now())}},validateConfig:function(e,t=[]){const n=[];for(const s of t)e[s]||n.push(s);if(n.length>0)throw new Error(`Missing required configuration: ${n.join(", ")}`);return!0}});class f{constructor(e={}){this.id=e.id,this.sdk=e.sdk,this.apiService=e.apiService,this.type=e.type||"base",this.options={container:null,position:this.sdk.config.position,boardId:this.sdk.config.boardId,displayMode:e.displayMode||"panel",size:e.size||"medium",primaryColor:e.primaryColor||"#21244A",backgroundColor:e.backgroundColor||"#ffffff",textColor:e.textColor||"#1F2937",autoShow:!1,showBackdrop:!0,customStyles:{},...e},this.element=null,this.panelElement=null,this.backdropElement=null,this.mounted=!1,this.destroyed=!1,this.state={isOpen:!1,isLoading:!1,isSubmitting:!1,title:"",content:"",email:"",attachments:[],errors:{}},this._bindMethods()}mount(e){return this.mounted||this.destroyed||("string"==typeof e&&(e=document.querySelector(e)),e||(e=document.body),this.container=e,this.element=this._render(),this.container.appendChild(this.element),this.mounted=!0,this._attachEvents(),this.onMount(),this.options.autoShow&&this.show(),this.sdk.eventBus.emit("widget:mounted",{widget:this})),this}show(){return this.element&&(this.element.style.display="block"),this}hide(){return this.element&&(this.element.style.display="none"),this}openPanel(){this.state.isOpen=!0,"modal"===this.options.displayMode?(this._showLoadingModal(),setTimeout(()=>{this._hideLoadingModal(),this._renderPanel(),requestAnimationFrame(()=>{this.panelElement&&this.panelElement.classList.add("open"),this.backdropElement&&this.backdropElement.classList.add("show")})},600)):(this._renderPanel(),requestAnimationFrame(()=>{this.panelElement&&this.panelElement.classList.add("open"),this.backdropElement&&this.backdropElement.classList.add("show")}))}_showLoadingModal(){this.state.isLoading=!0,this.backdropElement=document.createElement("div"),this.backdropElement.className="feedback-panel-backdrop",document.body.appendChild(this.backdropElement),this.loadingElement=document.createElement("div"),this.loadingElement.className=`feedback-loading-modal theme-${this.options.theme}`,this.loadingElement.innerHTML='\n\t\t\t<div class="feedback-loading-spinner"></div>\n\t\t',document.body.appendChild(this.loadingElement),requestAnimationFrame(()=>{this.backdropElement.classList.add("show"),this.loadingElement.classList.add("show")})}_hideLoadingModal(){this.state.isLoading=!1,this.loadingElement&&(this.loadingElement.remove(),this.loadingElement=null)}closePanel(){this.panelElement&&this.panelElement.classList.remove("open"),this.backdropElement&&this.backdropElement.classList.remove("show"),setTimeout(()=>{this.state.isOpen=!1,this.panelElement&&this.panelElement.parentNode&&(this.panelElement.parentNode.removeChild(this.panelElement),this.panelElement=null),this.backdropElement&&this.backdropElement.parentNode&&(this.backdropElement.parentNode.removeChild(this.backdropElement),this.backdropElement=null),this._resetForm()},300)}async submitFeedback(){if(!this.state.isSubmitting){this._hideError();try{this.state.isSubmitting=!0,this._updateSubmitButton();const e={title:this.state.title||"Feedback",content:this.state.content,email:this.state.email,board_id:this.options.boardId,attachments:this.state.attachments};if(!this.state.content.trim())return void this._showError("Please enter your feedback message.");const t=await this.apiService.submitFeedback(e);this._showSuccessMessage(),this.closePanel(),this.sdk.eventBus.emit("feedback:submitted",{widget:this,feedback:t})}catch(e){this._showError("Failed to submit feedback. Please try again."),this.sdk.eventBus.emit("feedback:error",{widget:this,error:e})}finally{this.state.isSubmitting=!1,this._updateSubmitButton()}}}handleConfigUpdate(e){this.options.theme=e.theme,this.element&&this._updateTheme()}destroy(){this.destroyed||(this.onDestroy(),this.closePanel(),this.element&&this.element.parentNode&&this.element.parentNode.removeChild(this.element),this.destroyed=!0,this.mounted=!1,this.sdk.eventBus.emit("widget:destroyed",{widget:this}))}onMount(){}onDestroy(){}_render(){throw new Error("_render() must be implemented by concrete widget")}_attachEvents(){}_bindMethods(){this.openPanel=this.openPanel.bind(this),this.closePanel=this.closePanel.bind(this),this.submitFeedback=this.submitFeedback.bind(this)}_renderPanel(){if(this.panelElement)return;this.options.showBackdrop&&!this.backdropElement&&(this.backdropElement=document.createElement("div"),this.backdropElement.className="feedback-panel-backdrop",document.body.appendChild(this.backdropElement),this.backdropElement.addEventListener("click",this.closePanel));const e="modal"===this.options.displayMode?"feedback-modal":"feedback-panel",t=`size-${this.options.size}`;this.panelElement=document.createElement("div"),this.panelElement.className=`${e} ${t}`,this.panelElement.style.setProperty("--primary-color",this.options.primaryColor),this.panelElement.style.setProperty("--bg-color",this.options.backgroundColor),this.panelElement.style.setProperty("--text-color",this.options.textColor),this.panelElement.innerHTML=this._getPanelHTML(),document.body.appendChild(this.panelElement),this._attachPanelEvents();const n=this.panelElement.querySelector("input, textarea");n&&setTimeout(()=>n.focus(),350)}_getPanelHTML(){return`\n <div class="feedback-panel-content">\n <div class="feedback-panel-header">\n <h3>Share Your Thoughts</h3>\n <button class="feedback-panel-close" type="button" aria-label="Close">&times;</button>\n </div>\n <div class="feedback-panel-body">\n <form class="feedback-form">\n <div class="feedback-form-group">\n <div class="feedback-input-container">\n <input \n type="text" \n id="feedback-title-${this.id}" \n name="title" \n placeholder="Title"\n value="${this.state.title}"\n />\n <textarea \n id="feedback-content-${this.id}" \n name="content" \n placeholder="Tell us what's on your mind..."\n required\n >${this.state.content}</textarea>\n </div>\n </div>\n <div class="feedback-error" role="alert"></div>\n <div class="feedback-form-group">\n <button type="submit" class="feedback-btn feedback-btn-submit">\n ${this.state.isSubmitting?"Sending...":"Submit Feedback"}\n </button>\n </div>\n </form>\n </div>\n </div>\n `}_attachPanelEvents(){const e=this.panelElement;e.querySelector(".feedback-panel-close").addEventListener("click",this.closePanel);e.querySelector(".feedback-form").addEventListener("submit",e=>{e.preventDefault(),this.submitFeedback()}),e.querySelector('input[name="title"]').addEventListener("input",e=>{this.state.title=e.target.value}),e.querySelector('textarea[name="content"]').addEventListener("input",e=>{this.state.content=e.target.value});const t=e=>{"Escape"===e.key&&(this.closePanel(),document.removeEventListener("keydown",t))};document.addEventListener("keydown",t)}_updateSubmitButton(){if(this.panelElement){const e=this.panelElement.querySelector(".feedback-btn-submit");e&&(e.textContent=this.state.isSubmitting?"Sending...":"Send Feedback",e.disabled=this.state.isSubmitting)}}_showError(e){if(this.panelElement){const t=this.panelElement.querySelector(".feedback-error");t&&(t.textContent=e,t.classList.add("show"))}}_hideError(){if(this.panelElement){const e=this.panelElement.querySelector(".feedback-error");e&&e.classList.remove("show")}}_showSuccessMessage(){const e=document.createElement("div");e.className="feedback-success-notification",e.innerHTML='\n <div class="feedback-success-content">\n <div class="feedback-success-icon">✓</div>\n <span>Feedback submitted successfully!</span>\n <button class="feedback-success-close" aria-label="Close">&times;</button>\n </div>\n ',document.body.appendChild(e);const t=()=>{e.parentNode&&(e.style.opacity="0",setTimeout(()=>{e.parentNode&&e.parentNode.removeChild(e)},300))};e.querySelector(".feedback-success-close").addEventListener("click",t),setTimeout(t,4e3)}_resetForm(){this.state.title="",this.state.content="",this.state.email="",this.state.errors={}}_updateTheme(){this.element&&(this.element.className=this.element.className.replace(/theme-\w+/,`theme-${this.options.theme}`)),this.panelElement&&(this.panelElement.className=this.panelElement.className.replace(/theme-\w+/,`theme-${this.options.theme}`))}openModal(){this.openPanel()}closeModal(){this.closePanel()}}class m extends f{constructor(e){super({...e,type:"button"})}_render(){const e=document.createElement("div");return e.className=`feedback-widget feedback-widget-button theme-${this.options.theme} position-${this.options.position}`,e.innerHTML='\n <button class="feedback-trigger-btn" type="button" aria-label="Send feedback">\n <svg width="28" height="32" viewBox="0 0 28 32" fill="none" xmlns="http://www.w3.org/2000/svg">\n <path fill-rule="evenodd" clip-rule="evenodd" d="M15.0615 5.28044C8.5161 4.42949 3.30825 11.1456 5.89967 17.6588C6.9321 20.2538 9.06268 22.2644 11.8777 23.1968C16.2682 24.6507 18.4038 22.3222 19.0483 23.9691C19.4055 24.8894 18.7282 25.3209 17.988 25.4938C10.9146 27.15 5.15304 22.7566 3.5869 17.5531C1.52205 10.6941 5.98684 4.6667 11.3483 3.41065C17.8801 1.88094 24.0325 6.19355 24.3926 12.7175C24.7448 19.0921 18.6217 24.5978 11.927 22.2036C10.8789 21.8285 8.8419 20.6682 8.46823 19.858C8.06026 18.9727 8.80261 18.1725 9.68285 18.3576C10.2223 18.4726 10.3116 18.8706 11.3161 19.5372C14.4549 21.6213 19.1276 20.6132 21.2046 17.0972C23.991 12.3817 21.0481 6.05351 15.06 5.27758L15.0615 5.28044Z" fill="#21244A"/>\n <path fill-rule="evenodd" clip-rule="evenodd" d="M15.2492 2.19833C11.944 1.71463 8.88819 3.07214 6.91479 4.49682C2.27067 7.85488 0.76169 14.5038 3.49672 19.8731C4.08535 21.0096 4.84379 22.0497 5.7459 22.9576L7.16343 24.2515C7.67214 24.9131 7.27203 25.7176 6.64115 25.9269C5.13502 26.4271 2.0499 21.8172 1.42044 20.5383C0.0872204 17.8297 -0.312889 14.9047 0.242977 11.503C1.66908 2.77063 11.221 -2.51652 19.7197 1.21021C27.7548 4.73331 30.2733 15.4555 23.9351 22.0773C23.3107 22.7296 21.6352 24.4823 20.6278 23.8907C20.0076 23.5263 19.8933 22.6446 20.5192 22.1238C21.0301 21.6986 21.4759 21.435 21.9896 20.9734C23.6665 19.4688 25.2562 16.8752 25.3477 13.5636C25.4427 10.2055 24.1266 7.5848 22.3904 5.74859C20.6392 3.89665 18.6751 2.69919 15.2456 2.19691L15.2492 2.19833Z" fill="#F69F06"/>\n <path fill-rule="evenodd" clip-rule="evenodd" d="M8.48332 27.2217C7.93817 26.265 8.89987 25.3776 10.1352 25.8641C15.5653 27.9926 18.3081 25.5269 19.0255 27.0823C19.2655 27.6039 19.0448 28.1619 18.7354 28.3863C17.9895 28.9257 14.82 28.9343 13.9262 28.8714C12.9071 28.8053 11.897 28.6377 10.9111 28.3713C10.0888 28.1348 8.88057 27.9247 8.48189 27.2281L8.48332 27.2217Z" fill="#21244A"/>\n <path fill-rule="evenodd" clip-rule="evenodd" d="M15.8722 31.0607C15.7765 32.1381 14.579 32.0331 13.5766 31.9545C12.5742 31.8759 11.5203 31.8502 11.601 30.7013C11.6789 29.5882 12.8035 29.7532 13.8274 29.8332C14.4425 29.8811 15.9951 29.681 15.8722 31.0607Z" fill="#21244A"/>\n </svg>\n </button>\n ',this.options.customStyles&&Object.assign(e.style,this.options.customStyles),e}_attachEvents(){const e=this.element.querySelector(".feedback-trigger-btn");e.addEventListener("click",this.openPanel),e.addEventListener("mouseenter",()=>{this.state.isSubmitting||(e.style.transform="scale(1.1)")}),e.addEventListener("mouseleave",()=>{e.style.transform="scale(1)"})}updateText(e){console.warn("ButtonWidget: Text display is disabled for circular design")}updatePosition(e){this.options.position=e,this.element&&(this.element.className=this.element.className.replace(/position-\w+-\w+/,`position-${e}`))}}class b extends f{constructor(e){super({...e,type:"inline"})}_render(){const e=document.createElement("div");return e.className=`feedback-widget feedback-widget-inline theme-${this.options.theme}`,e.innerHTML=`\n <div class="feedback-inline-content">\n <h3>Send us your feedback</h3>\n <form class="feedback-inline-form">\n <div class="feedback-form-group">\n <input \n type="text" \n name="title" \n placeholder="Title (optional)"\n value="${this.state.title}"\n />\n </div>\n <div class="feedback-form-group">\n <textarea \n name="content" \n placeholder="Your feedback..."\n required\n >${this.state.content}</textarea>\n </div>\n <div class="feedback-form-group">\n <input \n type="email" \n name="email" \n placeholder="Email (optional)"\n value="${this.state.email}"\n />\n </div>\n <button type="submit" class="feedback-btn feedback-btn-submit">\n Send Feedback\n </button>\n <div class="feedback-error" style="display: none;"></div>\n </form>\n </div>\n `,this.options.customStyles&&Object.assign(e.style,this.options.customStyles),e}_attachEvents(){const e=this.element.querySelector(".feedback-inline-form");e.addEventListener("submit",e=>{e.preventDefault(),this.submitFeedback()}),e.querySelector('input[name="title"]').addEventListener("input",e=>{this.state.title=e.target.value}),e.querySelector('textarea[name="content"]').addEventListener("input",e=>{this.state.content=e.target.value}),e.querySelector('input[name="email"]').addEventListener("input",e=>{this.state.email=e.target.value})}openModal(){const e=this.element.querySelector('textarea[name="content"]');e&&e.focus()}closeModal(){}_showSuccessMessage(){const e=this.element.querySelector(".feedback-inline-content"),t=e.innerHTML;e.innerHTML='\n <div class="feedback-success">\n <div class="feedback-success-icon">✓</div>\n <h3>Thank you!</h3>\n <p>Your feedback has been submitted successfully.</p>\n <button class="feedback-btn feedback-btn-reset">Send Another</button>\n </div>\n ';e.querySelector(".feedback-btn-reset").addEventListener("click",()=>{e.innerHTML=t,this._attachEvents(),this._resetForm()})}_showError(e){const t=this.element.querySelector(".feedback-error");t&&(t.textContent=e,t.style.display="block",setTimeout(()=>{t&&(t.style.display="none")},5e3))}_updateSubmitButton(){const e=this.element.querySelector(".feedback-btn-submit");e&&(e.textContent=this.state.isSubmitting?"Sending...":"Send Feedback",e.disabled=this.state.isSubmitting)}updateTitle(e){const t=this.element?.querySelector("h3");t&&(t.textContent=e)}setPlaceholder(e,t){const n=this.element?.querySelector(`[name="${e}"]`);n&&(n.placeholder=t)}}class y extends f{constructor(e){super({...e,type:"survey"}),this.surveyOptions={surveyType:e.surveyType||"nps",position:e.position||"bottom-right",title:e.title||null,description:e.description||null,lowLabel:e.lowLabel||null,highLabel:e.highLabel||null,customQuestions:e.customQuestions||[],theme:e.theme||"light",onSubmit:e.onSubmit||null,onDismiss:e.onDismiss||null},this.surveyState={score:null,feedback:"",customAnswers:{},isVisible:!1}}_render(){const e=document.createElement("div");return e.className="feedback-survey-container",e.style.display="none",e}_attachEvents(){}show(){return this._renderSurvey(),this.surveyState.isVisible=!0,this.sdk.eventBus.emit("survey:shown",{widget:this,type:this.surveyOptions.surveyType}),this}hide(){return this._closeSurvey(),this}_renderSurvey(){this._closeSurvey();const e=this._getSurveyConfig(),t=this._getPositionStyles(),n="dark"===this.surveyOptions.theme?"background: #1a1a1a; color: #fff;":"background: #fff; color: #1d1d1f;";"center"===this.surveyOptions.position&&(this.backdropElement=document.createElement("div"),this.backdropElement.className="feedback-survey-backdrop",document.body.appendChild(this.backdropElement),this.backdropElement.addEventListener("click",()=>this._handleDismiss())),this.surveyElement=document.createElement("div"),this.surveyElement.className=`feedback-survey feedback-survey-${this.surveyOptions.position} theme-${this.surveyOptions.theme}`,this.surveyElement.style.cssText=`position: fixed; ${t} z-index: 10000; ${n} border-radius: 16px; box-shadow: 0 20px 60px rgba(0,0,0,0.3); padding: 24px; min-width: 320px; max-width: 400px; font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;`,this.surveyElement.innerHTML=`\n\t\t\t<button class="feedback-survey-close" style="position: absolute; top: 12px; right: 12px; background: none; border: none; font-size: 20px; cursor: pointer; color: ${"dark"===this.surveyOptions.theme?"#888":"#86868b"}; line-height: 1;">&times;</button>\n\t\t\t<h3 class="feedback-survey-title" style="margin: 0 0 8px 0; font-size: 18px; font-weight: 600; padding-right: 24px;">${e.title}</h3>\n\t\t\t<p class="feedback-survey-description" style="color: ${"dark"===this.surveyOptions.theme?"#aaa":"#86868b"}; margin: 0 0 20px 0; font-size: 14px;">${e.description}</p>\n\t\t\t<div class="feedback-survey-content">${e.html}</div>\n\t\t\t<div class="feedback-survey-feedback" style="margin-top: 16px;">\n\t\t\t\t<textarea class="feedback-survey-textarea" placeholder="Any additional feedback? (optional)" style="width: 100%; padding: 12px; border: 1px solid ${"dark"===this.surveyOptions.theme?"#333":"#d2d2d7"}; border-radius: 8px; font-size: 14px; resize: none; height: 80px; background: ${"dark"===this.surveyOptions.theme?"#2a2a2a":"#fff"}; color: ${"dark"===this.surveyOptions.theme?"#fff":"#1d1d1f"}; font-family: inherit; box-sizing: border-box;"></textarea>\n\t\t\t</div>\n\t\t\t<button class="feedback-survey-submit" style="width: 100%; margin-top: 12px; padding: 12px; background: #007aff; color: white; border: none; border-radius: 8px; font-size: 14px; font-weight: 500; cursor: pointer; font-family: inherit;">Submit</button>\n\t\t`,document.body.appendChild(this.surveyElement),this._attachSurveyEvents(),requestAnimationFrame(()=>{this.surveyElement.style.opacity="1",this.surveyElement.style.transform="center"===this.surveyOptions.position?"translate(-50%, -50%) scale(1)":"translateY(0)"})}_getSurveyConfig(){const e={nps:{title:this.surveyOptions.title||"How likely are you to recommend us?",description:this.surveyOptions.description||"On a scale of 0-10, how likely are you to recommend our product to a friend or colleague?",html:`\n\t\t\t\t\t<div class="feedback-survey-nps" style="display: flex; justify-content: space-between; gap: 4px;">\n\t\t\t\t\t\t${[...Array(11).keys()].map(e=>`\n\t\t\t\t\t\t\t<button class="feedback-survey-nps-btn" data-score="${e}" style="width: 28px; height: 36px; border: 1px solid ${"dark"===this.surveyOptions.theme?"#444":"#d2d2d7"}; border-radius: 6px; background: ${"dark"===this.surveyOptions.theme?"#2a2a2a":"#f8f9fa"}; cursor: pointer; font-size: 12px; color: ${"dark"===this.surveyOptions.theme?"#fff":"#1d1d1f"}; transition: all 0.15s;">${e}</button>\n\t\t\t\t\t\t`).join("")}\n\t\t\t\t\t</div>\n\t\t\t\t\t<div style="display: flex; justify-content: space-between; margin-top: 8px; font-size: 11px; color: ${"dark"===this.surveyOptions.theme?"#888":"#86868b"};">\n\t\t\t\t\t\t<span>${this.surveyOptions.lowLabel||"Not likely"}</span>\n\t\t\t\t\t\t<span>${this.surveyOptions.highLabel||"Very likely"}</span>\n\t\t\t\t\t</div>\n\t\t\t\t`},csat:{title:this.surveyOptions.title||"How satisfied are you?",description:this.surveyOptions.description||"How would you rate your overall satisfaction with our product?",html:`\n\t\t\t\t\t<div class="feedback-survey-csat" style="display: flex; justify-content: center; gap: 16px;">\n\t\t\t\t\t\t${["😞","😕","😐","🙂","😄"].map((e,t)=>`\n\t\t\t\t\t\t\t<button class="feedback-survey-csat-btn" data-score="${t+1}" style="background: none; border: none; cursor: pointer; font-size: 36px; transition: transform 0.15s; padding: 8px;">${e}</button>\n\t\t\t\t\t\t`).join("")}\n\t\t\t\t\t</div>\n\t\t\t\t\t<div style="display: flex; justify-content: space-between; margin-top: 8px; font-size: 11px; color: ${"dark"===this.surveyOptions.theme?"#888":"#86868b"};">\n\t\t\t\t\t\t<span>${this.surveyOptions.lowLabel||"Very dissatisfied"}</span>\n\t\t\t\t\t\t<span>${this.surveyOptions.highLabel||"Very satisfied"}</span>\n\t\t\t\t\t</div>\n\t\t\t\t`},ces:{title:this.surveyOptions.title||"How easy was it?",description:this.surveyOptions.description||"How easy was it to accomplish your task today?",html:`\n\t\t\t\t\t<div class="feedback-survey-ces" style="display: flex; justify-content: space-between; gap: 8px;">\n\t\t\t\t\t\t${["Very Difficult","Difficult","Neutral","Easy","Very Easy"].map((e,t)=>`\n\t\t\t\t\t\t\t<button class="feedback-survey-ces-btn" data-score="${t+1}" style="flex: 1; padding: 12px 8px; border: 1px solid ${"dark"===this.surveyOptions.theme?"#444":"#d2d2d7"}; border-radius: 8px; background: ${"dark"===this.surveyOptions.theme?"#2a2a2a":"#f8f9fa"}; cursor: pointer; font-size: 11px; color: ${"dark"===this.surveyOptions.theme?"#fff":"#1d1d1f"}; transition: all 0.15s;">${e}</button>\n\t\t\t\t\t\t`).join("")}\n\t\t\t\t\t</div>\n\t\t\t\t`},custom:{title:this.surveyOptions.title||"Quick Feedback",description:this.surveyOptions.description||"Help us improve by answering a few questions.",html:this._renderCustomQuestions()}};return e[this.surveyOptions.surveyType]||e.nps}_renderCustomQuestions(){return this.surveyOptions.customQuestions&&0!==this.surveyOptions.customQuestions.length?this.surveyOptions.customQuestions.map((e,t)=>`\n\t\t\t<div style="margin-bottom: 16px;">\n\t\t\t\t<label style="display: block; margin-bottom: 6px; font-size: 13px; font-weight: 500;">${e.label}</label>\n\t\t\t\t${this._renderQuestionInput(e,t)}\n\t\t\t</div>\n\t\t`).join(""):`\n\t\t\t\t<div style="margin-bottom: 16px;">\n\t\t\t\t\t<label style="display: block; margin-bottom: 6px; font-size: 13px; font-weight: 500;">What feature do you use most?</label>\n\t\t\t\t\t<select class="feedback-survey-select" data-question="feature" style="width: 100%; padding: 10px; border: 1px solid ${"dark"===this.surveyOptions.theme?"#444":"#d2d2d7"}; border-radius: 8px; font-size: 14px; background: ${"dark"===this.surveyOptions.theme?"#2a2a2a":"#fff"}; color: ${"dark"===this.surveyOptions.theme?"#fff":"#1d1d1f"};">\n\t\t\t\t\t\t<option value="">Select a feature</option>\n\t\t\t\t\t\t<option value="feedback">Feedback Collection</option>\n\t\t\t\t\t\t<option value="surveys">Surveys</option>\n\t\t\t\t\t\t<option value="analytics">Analytics</option>\n\t\t\t\t\t\t<option value="integrations">Integrations</option>\n\t\t\t\t\t</select>\n\t\t\t\t</div>\n\t\t\t\t<div>\n\t\t\t\t\t<label style="display: block; margin-bottom: 6px; font-size: 13px; font-weight: 500;">How often do you use it?</label>\n\t\t\t\t\t<div class="feedback-survey-frequency" style="display: flex; gap: 8px;">\n\t\t\t\t\t\t${["Daily","Weekly","Monthly","Rarely"].map(e=>`\n\t\t\t\t\t\t\t<button class="feedback-survey-freq-btn" data-freq="${e}" style="flex: 1; padding: 10px; border: 1px solid ${"dark"===this.surveyOptions.theme?"#444":"#d2d2d7"}; border-radius: 8px; background: ${"dark"===this.surveyOptions.theme?"#2a2a2a":"#f8f9fa"}; cursor: pointer; font-size: 12px; color: ${"dark"===this.surveyOptions.theme?"#fff":"#1d1d1f"}; transition: all 0.15s;">${e}</button>\n\t\t\t\t\t\t`).join("")}\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t`}_renderQuestionInput(e,t){switch(e.type){case"select":return`\n\t\t\t\t\t<select class="feedback-survey-select" data-question="${e.id||t}" style="width: 100%; padding: 10px; border: 1px solid ${"dark"===this.surveyOptions.theme?"#444":"#d2d2d7"}; border-radius: 8px; font-size: 14px; background: ${"dark"===this.surveyOptions.theme?"#2a2a2a":"#fff"}; color: ${"dark"===this.surveyOptions.theme?"#fff":"#1d1d1f"};">\n\t\t\t\t\t\t<option value="">${e.placeholder||"Select an option"}</option>\n\t\t\t\t\t\t${e.options.map(e=>`<option value="${e.value}">${e.label}</option>`).join("")}\n\t\t\t\t\t</select>\n\t\t\t\t`;case"text":return`\n\t\t\t\t\t<input type="text" class="feedback-survey-input" data-question="${e.id||t}" placeholder="${e.placeholder||""}" style="width: 100%; padding: 10px; border: 1px solid ${"dark"===this.surveyOptions.theme?"#444":"#d2d2d7"}; border-radius: 8px; font-size: 14px; background: ${"dark"===this.surveyOptions.theme?"#2a2a2a":"#fff"}; color: ${"dark"===this.surveyOptions.theme?"#fff":"#1d1d1f"}; box-sizing: border-box;">\n\t\t\t\t`;default:return""}}_getPositionStyles(){const e={"bottom-right":"bottom: 24px; right: 24px; opacity: 0; transform: translateY(20px); transition: all 0.3s ease;","bottom-left":"bottom: 24px; left: 24px; opacity: 0; transform: translateY(20px); transition: all 0.3s ease;",center:"top: 50%; left: 50%; transform: translate(-50%, -50%) scale(0.95); opacity: 0; transition: all 0.3s ease;",bottom:"bottom: 0; left: 0; right: 0; border-radius: 16px 16px 0 0; max-width: none; opacity: 0; transform: translateY(20px); transition: all 0.3s ease;"};return e[this.surveyOptions.position]||e["bottom-right"]}_attachSurveyEvents(){if(!this.surveyElement)return;this.surveyElement.querySelector(".feedback-survey-close").addEventListener("click",()=>this._handleDismiss());this.surveyElement.querySelector(".feedback-survey-submit").addEventListener("click",()=>this._handleSubmit());this.surveyElement.querySelector(".feedback-survey-textarea").addEventListener("input",e=>{this.surveyState.feedback=e.target.value}),this._attachTypeSpecificEvents(),this._escapeHandler=e=>{"Escape"===e.key&&this._handleDismiss()},document.addEventListener("keydown",this._escapeHandler)}_attachTypeSpecificEvents(){const e=this.surveyOptions.surveyType;"nps"===e&&this.surveyElement.querySelectorAll(".feedback-survey-nps-btn").forEach(e=>{e.addEventListener("click",()=>this._selectNPS(parseInt(e.dataset.score))),e.addEventListener("mouseenter",()=>{this.surveyState.score!==parseInt(e.dataset.score)&&(e.style.borderColor="#007aff")}),e.addEventListener("mouseleave",()=>{this.surveyState.score!==parseInt(e.dataset.score)&&(e.style.borderColor="dark"===this.surveyOptions.theme?"#444":"#d2d2d7")})}),"csat"===e&&this.surveyElement.querySelectorAll(".feedback-survey-csat-btn").forEach(e=>{e.addEventListener("click",()=>this._selectCSAT(parseInt(e.dataset.score))),e.addEventListener("mouseenter",()=>{e.style.transform="scale(1.1)"}),e.addEventListener("mouseleave",()=>{this.surveyState.score!==parseInt(e.dataset.score)&&(e.style.transform="scale(1)")})}),"ces"===e&&this.surveyElement.querySelectorAll(".feedback-survey-ces-btn").forEach(e=>{e.addEventListener("click",()=>this._selectCES(parseInt(e.dataset.score))),e.addEventListener("mouseenter",()=>{this.surveyState.score!==parseInt(e.dataset.score)&&(e.style.borderColor="#007aff")}),e.addEventListener("mouseleave",()=>{this.surveyState.score!==parseInt(e.dataset.score)&&(e.style.borderColor="dark"===this.surveyOptions.theme?"#444":"#d2d2d7")})}),"custom"===e&&(this.surveyElement.querySelectorAll(".feedback-survey-freq-btn").forEach(e=>{e.addEventListener("click",()=>this._selectFrequency(e.dataset.freq))}),this.surveyElement.querySelectorAll(".feedback-survey-select").forEach(e=>{e.addEventListener("change",t=>{this.surveyState.customAnswers[e.dataset.question]=t.target.value})}),this.surveyElement.querySelectorAll(".feedback-survey-input").forEach(e=>{e.addEventListener("input",t=>{this.surveyState.customAnswers[e.dataset.question]=t.target.value})}))}_selectNPS(e){this.surveyState.score=e,this.surveyElement.querySelectorAll(".feedback-survey-nps-btn").forEach(t=>{parseInt(t.dataset.score)===e?(t.style.background="#007aff",t.style.borderColor="#007aff",t.style.color="#fff"):(t.style.background="dark"===this.surveyOptions.theme?"#2a2a2a":"#f8f9fa",t.style.borderColor="dark"===this.surveyOptions.theme?"#444":"#d2d2d7",t.style.color="dark"===this.surveyOptions.theme?"#fff":"#1d1d1f")})}_selectCSAT(e){this.surveyState.score=e,this.surveyElement.querySelectorAll(".feedback-survey-csat-btn").forEach(t=>{const n=parseInt(t.dataset.score);t.style.transform=n===e?"scale(1.2)":"scale(1)"})}_selectCES(e){this.surveyState.score=e,this.surveyElement.querySelectorAll(".feedback-survey-ces-btn").forEach(t=>{parseInt(t.dataset.score)===e?(t.style.background="#007aff",t.style.borderColor="#007aff",t.style.color="#fff"):(t.style.background="dark"===this.surveyOptions.theme?"#2a2a2a":"#f8f9fa",t.style.borderColor="dark"===this.surveyOptions.theme?"#444":"#d2d2d7",t.style.color="dark"===this.surveyOptions.theme?"#fff":"#1d1d1f")})}_selectFrequency(e){this.surveyState.customAnswers.frequency=e,this.surveyElement.querySelectorAll(".feedback-survey-freq-btn").forEach(t=>{t.dataset.freq===e?(t.style.background="#007aff",t.style.borderColor="#007aff",t.style.color="#fff"):(t.style.background="dark"===this.surveyOptions.theme?"#2a2a2a":"#f8f9fa",t.style.borderColor="dark"===this.surveyOptions.theme?"#444":"#d2d2d7",t.style.color="dark"===this.surveyOptions.theme?"#fff":"#1d1d1f")})}async _handleSubmit(){const e=this.surveyOptions.surveyType;if(("nps"===e||"csat"===e||"ces"===e)&&null===this.surveyState.score)return void this._showError("Please select a rating");const t={type:e,score:this.surveyState.score,feedback:this.surveyState.feedback,customAnswers:this.surveyState.customAnswers,timestamp:(new Date).toISOString()};if(this.surveyOptions.onSubmit&&this.surveyOptions.onSubmit(t),!this.sdk.config.mock)try{await this.apiService.submitSurveyResponse(t)}catch(e){console.error("[SurveyWidget] Failed to submit survey:",e)}this.sdk.eventBus.emit("survey:submitted",{widget:this,response:t}),this._closeSurvey(),this._showSuccessNotification()}_handleDismiss(){this.surveyOptions.onDismiss&&this.surveyOptions.onDismiss(),this.sdk.eventBus.emit("survey:dismissed",{widget:this}),this._closeSurvey()}_showError(e){const t=this.surveyElement.querySelector(".feedback-survey-error");t&&t.remove();const n=document.createElement("div");n.className="feedback-survey-error",n.style.cssText="color: #ef4444; font-size: 13px; margin-top: 8px; text-align: center;",n.textContent=e;const s=this.surveyElement.querySelector(".feedback-survey-submit");s.parentNode.insertBefore(n,s),setTimeout(()=>n.remove(),3e3)}_showSuccessNotification(){const e=document.createElement("div");e.className="feedback-survey-success",e.style.cssText="\n\t\t\tposition: fixed;\n\t\t\ttop: 24px;\n\t\t\tright: 24px;\n\t\t\tbackground: #10b981;\n\t\t\tcolor: white;\n\t\t\tpadding: 16px 24px;\n\t\t\tborder-radius: 12px;\n\t\t\tfont-size: 14px;\n\t\t\tfont-weight: 500;\n\t\t\tz-index: 10001;\n\t\t\tbox-shadow: 0 10px 40px rgba(0,0,0,0.2);\n\t\t\tfont-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;\n\t\t",e.innerHTML='\n\t\t\t<div style="display: flex; align-items: center; gap: 8px;">\n\t\t\t\t<span style="font-size: 18px;">✓</span>\n\t\t\t\t<span>Thank you for your feedback!</span>\n\t\t\t</div>\n\t\t',document.body.appendChild(e),setTimeout(()=>{e.style.opacity="0",e.style.transition="opacity 0.3s ease",setTimeout(()=>e.remove(),300)},3e3)}_closeSurvey(){this._escapeHandler&&(document.removeEventListener("keydown",this._escapeHandler),this._escapeHandler=null);const e=this.surveyElement,t=this.backdropElement;e&&(e.style.opacity="0",e.style.transform="center"===this.surveyOptions.position?"translate(-50%, -50%) scale(0.95)":"translateY(20px)",setTimeout(()=>{e&&e.parentNode&&e.parentNode.removeChild(e)},300),this.surveyElement=null),t&&(t.style.opacity="0",setTimeout(()=>{t&&t.parentNode&&t.parentNode.removeChild(t)},300),this.backdropElement=null),this.surveyState={score:null,feedback:"",customAnswers:{},isVisible:!1}}destroy(){this._closeSurvey(),super.destroy()}}class g extends f{constructor(e){super({...e,type:"tab"})}_render(){const e=document.createElement("div");return e.className=`feedback-widget feedback-widget-tab theme-${this.options.theme} position-${this.options.position}`,e.innerHTML='\n <div class="feedback-tab-trigger">\n <span class="feedback-tab-text">Feedback</span>\n </div>\n ',this.options.customStyles&&Object.assign(e.style,this.options.customStyles),e}_attachEvents(){const e=this.element.querySelector(".feedback-tab-trigger");e.addEventListener("click",this.openModal),e.addEventListener("mouseenter",()=>{this.state.isSubmitting||(e.style.transform=this._getHoverTransform())}),e.addEventListener("mouseleave",()=>{e.style.transform="none"})}_getHoverTransform(){const e=this.options.position;return e.includes("right")?"translateX(-5px)":e.includes("left")?"translateX(5px)":"none"}updateText(e){const t=this.element?.querySelector(".feedback-tab-text");t&&(t.textContent=e)}updatePosition(e){this.options.position=e,this.element&&(this.element.className=this.element.className.replace(/position-\w+-\w+/,`position-${e}`))}}class k{static widgets=new Map([["button",m],["tab",g],["inline",b],["survey",y]]);static register(e,n){if("string"!=typeof e||!e.trim())throw new t("Widget type must be a non-empty string");if("function"!=typeof n)throw new t("Widget class must be a constructor function");this.widgets.set(e,n)}static create(e,n={}){const s=this.widgets.get(e);if(!s){const n=Array.from(this.widgets.keys()).join(", ");throw new t(`Unknown widget type: ${e}. Available types: ${n}`)}try{return new s(n)}catch(n){throw new t(`Failed to create widget of type '${e}': ${n.message}`,n)}}static getAvailableTypes(){return Array.from(this.widgets.keys())}static isTypeRegistered(e){return this.widgets.has(e)}static unregister(e){return this.widgets.delete(e)}static clear(){this.widgets.clear()}static getWidgetClass(e){return this.widgets.get(e)}}class v{constructor(e={}){this.config=this._validateAndMergeConfig(e),this.initialized=!1,this.widgets=new Map,this.eventBus=new c,this.apiService=new d({apiUrl:this.config.apiUrl,workspace:this.config.workspace,userContext:this.config.userContext,mock:this.config.mock,env:this.config.env}),this._bindMethods()}async init(){if(this.initialized)return{alreadyInitialized:!0};try{const e=await this.apiService.init(this.config.userContext);return e.config&&(this.config=u(e.config,this.config)),this.initialized=!0,this.eventBus.emit("sdk:initialized",{config:this.config,sessionToken:e.sessionToken}),{initialized:!0,config:e.config||{},sessionToken:e.sessionToken,expiresIn:e.expiresIn}}catch(e){throw this.eventBus.emit("sdk:error",{error:e}),new t(`Failed to initialize SDK: ${e.message}`,e)}}createWidget(e="button",n={}){if(!this.initialized)throw new t("SDK must be initialized before creating widgets. Call init() first.");const s=l("widget"),i={id:s,sdk:this,apiService:this.apiService,...this.config,...n};try{const t=k.create(e,i);return this.widgets.set(s,t),this.eventBus.emit("widget:created",{widget:t,type:e}),t}catch(e){throw new t(`Failed to create widget: ${e.message}`,e)}}getWidget(e){return this.widgets.get(e)}showSurvey(e={}){if(!this.initialized)throw new t("SDK must be initialized before showing surveys. Call init() first.");const n=this.createWidget("survey",{surveyType:e.surveyType||e.type||"nps",position:e.position||"bottom-right",theme:e.theme||this.config.theme||"light",title:e.title,description:e.description,lowLabel:e.lowLabel,highLabel:e.highLabel,customQuestions:e.customQuestions,onSubmit:e.onSubmit,onDismiss:e.onDismiss});return n.mount(),n.show(),n}getAllWidgets(){return Array.from(this.widgets.values())}destroyWidget(e){const t=this.widgets.get(e);return!!t&&(t.destroy(),this.widgets.delete(e),this.eventBus.emit("widget:removed",{widgetId:e}),!0)}destroyAllWidgets(){for(const e of this.widgets.values())e.destroy();this.widgets.clear(),this.eventBus.emit("widgets:cleared")}updateConfig(e){const t={...this.config};this.config=this._validateAndMergeConfig(e,this.config);for(const e of this.widgets.values())e.handleConfigUpdate(this.config);this.eventBus.emit("config:updated",{oldConfig:t,newConfig:this.config})}setUserContext(e){this.config.userContext=e,this.apiService&&this.apiService.setUserContext(e),this.eventBus.emit("user:updated",{userContext:e})}getUserContext(){return this.config.userContext||(this.apiService?this.apiService.getUserContext():null)}async reinitialize(e=null){return this.apiService.clearSession(),this.initialized=!1,e&&this.setUserContext(e),this.init()}on(e,t){return this.eventBus.on(e,t),this}off(e,t){return this.eventBus.off(e,t),this}once(e,t){return this.eventBus.once(e,t),this}emit(e,t){return this.eventBus.emit(e,t),this}destroy(){this.destroyAllWidgets(),this.eventBus.removeAllListeners(),this.apiService.clearSession(),this.initialized=!1,this.eventBus.emit("sdk:destroyed")}_validateAndMergeConfig(e,t={}){const n=u(u({apiUrl:null,workspace:null,userContext:null,position:"bottom-right",theme:"light",boardId:"general",autoShow:!0,debug:!1,mock:!1,env:"production"},t),e);if(!n.workspace)throw new i("Missing required configuration: workspace");return n.userContext&&this._validateUserContext(n.userContext),n}_validateUserContext(e){if(!e.user_id&&!e.email)throw new i("User context must include at least user_id or email");const t={user_id:"string",email:"string",name:"string",custom_fields:"object",company:"object"};for(const[n,s]of Object.entries(t))if(e[n]&&typeof e[n]!==s)throw new i(`User context field '${n}' must be of type '${s}'`)}_bindMethods(){this.createWidget=this.createWidget.bind(this),this.destroyWidget=this.destroyWidget.bind(this),this.updateConfig=this.updateConfig.bind(this)}static create(e){return new v(e)}static async createAndInit(e){const t=new v(e);return await t.init(),t}static extractUserContextFromAuth(e){return e?{user_id:e.sub||e.id||e.user_id,email:e.email,name:e.name||e.display_name||e.full_name,custom_fields:{role:e.role,plan:e.plan||e.subscription?.plan,...e.custom_fields||{}},company:e.company||e.organization?{id:e.company?.id||e.organization?.id,name:e.company?.name||e.organization?.name,monthly_spend:e.company?.monthly_spend}:void 0}:null}}function x(){if("undefined"!=typeof document&&!document.querySelector("#feedback-sdk-styles")){const e=document.createElement("style");e.id="feedback-sdk-styles",e.textContent="\n.feedback-widget {\n font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n font-size: 14px;\n line-height: 1.4;\n z-index: 999999;\n box-sizing: border-box;\n}\n\n.feedback-widget *,\n.feedback-widget *::before,\n.feedback-widget *::after {\n box-sizing: border-box;\n}\n\n.feedback-widget-button {\n position: fixed;\n z-index: 999999;\n}\n\n.feedback-widget-button.position-bottom-right {\n bottom: 20px;\n right: 20px;\n}\n\n.feedback-widget-button.position-bottom-left {\n bottom: 20px;\n left: 20px;\n}\n\n.feedback-widget-button.position-top-right {\n top: 20px;\n right: 20px;\n}\n\n.feedback-widget-button.position-top-left {\n top: 20px;\n left: 20px;\n}\n\n.feedback-widget-button.position-bottom-center {\n bottom: 20px;\n left: 50%;\n transform: translateX(-50%);\n}\n\n.feedback-widget-button.position-top-center {\n top: 20px;\n left: 50%;\n transform: translateX(-50%);\n}\n\n.feedback-widget-button.position-center {\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n}\n\n/* New button design - white with elevation */\n.feedback-trigger-btn {\n width: 52px;\n height: 52px;\n border-radius: 50%;\n border: none;\n background: #ffffff;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n box-shadow: \n 0 2px 8px rgba(0, 0, 0, 0.08),\n 0 4px 16px rgba(0, 0, 0, 0.06);\n transition: all 0.15s cubic-bezier(0.4, 0, 0.2, 1);\n padding: 0;\n}\n\n.feedback-trigger-btn:hover {\n box-shadow: \n 0 4px 12px rgba(0, 0, 0, 0.1),\n 0 8px 24px rgba(0, 0, 0, 0.08);\n transform: translateY(-2px);\n}\n\n.feedback-trigger-btn:active {\n transform: translateY(0px);\n box-shadow: \n 0 2px 6px rgba(0, 0, 0, 0.08),\n 0 1px 4px rgba(0, 0, 0, 0.06);\n}\n.feedback-trigger-btn svg {\n flex-shrink: 0;\n width: 22px;\n height: 25px;\n}\n\n.feedback-trigger-btn svg path {\n fill: #21244A;\n}\n\n/* Loading Modal */\n.feedback-loading-modal {\n position: fixed;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%) scale(0.9);\n z-index: 1000001;\n opacity: 0;\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.feedback-loading-modal.show {\n opacity: 1;\n transform: translate(-50%, -50%) scale(1);\n}\n\n.feedback-loading-spinner {\n width: 48px;\n height: 48px;\n border: 4px solid rgba(0, 0, 0, 0.1);\n border-top-color: #21244A;\n border-radius: 50%;\n animation: spin 0.8s linear infinite;\n}\n\n@keyframes spin {\n to { transform: rotate(360deg); }\n}\n\n/* Modal Styles (centered) */\n.feedback-modal {\n position: fixed;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%) scale(0.9);\n width: 480px;\n max-width: 90vw;\n max-height: 85vh;\n z-index: 1000000;\n opacity: 0;\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n font-family: inherit;\n}\n\n.feedback-modal.open {\n opacity: 1;\n transform: translate(-50%, -50%) scale(1);\n}\n\n.feedback-modal .feedback-panel-content {\n max-height: 85vh;\n overflow-y: auto;\n}\n\n/* Size variants */\n.feedback-modal.size-small {\n width: 360px;\n}\n\n.feedback-modal.size-medium {\n width: 480px;\n}\n\n.feedback-modal.size-large {\n width: 600px;\n}\n\n.feedback-panel.size-small {\n width: 320px;\n}\n\n.feedback-panel.size-medium {\n width: 420px;\n}\n\n.feedback-panel.size-large {\n width: 520px;\n}\n\n/* Side Panel Styles */\n.feedback-panel {\n position: fixed;\n bottom: 80px;\n right: 24px;\n width: 420px;\n max-height: 500px;\n z-index: 1000000;\n transform: translateX(calc(100% + 24px));\n transition: transform 0.35s cubic-bezier(0.4, 0, 0.2, 1);\n font-family: inherit;\n}\n\n.feedback-panel.open {\n transform: translateX(0);\n}\n\n.feedback-panel-backdrop {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.4);\n backdrop-filter: blur(4px);\n opacity: 0;\n transition: opacity 0.3s ease;\n pointer-events: none;\n z-index: 999999;\n}\n\n.feedback-panel-backdrop.show {\n opacity: 1;\n pointer-events: auto;\n}\n\n.feedback-panel-content {\n background: var(--bg-color, #ffffff);\n color: var(--text-color, #171717);\n height: 100%;\n display: flex;\n flex-direction: column;\n border-radius: 12px;\n border: 1px solid #e5e5e5;\n}\n\n.feedback-panel-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 24px 24px 20px 24px;\n flex-shrink: 0;\n}\n\n.feedback-panel-header h3 {\n margin: 0;\n font-size: 18px;\n font-weight: 600;\n color: var(--text-color, #171717);\n}\n\n.feedback-panel-close {\n background: none;\n border: none;\n font-size: 20px;\n cursor: pointer;\n color: #737373;\n padding: 0;\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 8px;\n transition: all 0.15s ease;\n}\n\n.feedback-panel-close:hover {\n background: #f5f5f5;\n color: #171717;\n}\n\n.feedback-panel-close:focus-visible {\n outline: 2px solid var(--primary-color, #21244A);\n outline-offset: 2px;\n}\n\n.feedback-panel-body {\n flex: 1;\n overflow-y: auto;\n padding: 0 24px 24px 24px;\n}\n\n.feedback-form {\n display: flex;\n flex-direction: column;\n height: 100%;\n}\n\n.feedback-form-group {\n margin-bottom: 16px;\n}\n\n.feedback-form-group:last-child {\n margin-bottom: 0;\n}\n\n/* Unified input container */\n.feedback-input-container {\n border: 1px solid #e5e5e5;\n border-radius: 8px;\n padding: 16px;\n background: #ffffff;\n transition: all 0.15s ease;\n}\n\n.feedback-input-container:focus-within {\n border-color: var(--primary-color, #21244A);\n box-shadow: 0 0 0 3px rgba(33, 36, 74, 0.08);\n}\n\n.feedback-form-group input,\n.feedback-form-group textarea {\n width: 100%;\n border: none;\n padding: 0;\n font-size: 14px;\n font-family: inherit;\n color: var(--text-color, #171717);\n background: transparent;\n outline: none;\n resize: none;\n}\n\n.feedback-form-group input {\n font-weight: 600;\n font-size: 15px;\n margin-bottom: 12px;\n}\n\n.feedback-form-group input::placeholder {\n color: #737373;\n font-weight: 600;\n}\n\n.feedback-form-group textarea {\n min-height: 120px;\n font-weight: 400;\n}\n\n.feedback-form-group textarea::placeholder {\n color: #a3a3a3;\n font-weight: 400;\n}\n\n.feedback-btn {\n position: relative;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n overflow: hidden;\n border-radius: 8px;\n border: none;\n height: 44px;\n padding: 10px 18px;\n font-size: 15px;\n font-weight: 500;\n font-family: inherit;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n\n.feedback-btn:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.feedback-btn:focus-visible {\n outline: 2px solid #21244A;\n outline-offset: 2px;\n}\n\n.feedback-btn-submit {\n background: var(--primary-color, #21244A);\n color: white;\n width: 100%;\n}\n\n.feedback-btn-submit:hover:not(:disabled) {\n background: #2d3159;\n}\n\n.feedback-btn-submit:active:not(:disabled) {\n transform: scale(0.98);\n}\n\n.feedback-error {\n background: #FEF2F2;\n border: 1px solid #FEE2E2;\n color: #DC2626;\n padding: 12px 14px;\n border-radius: 8px;\n font-size: 13px;\n margin-top: 12px;\n display: none;\n}\n\n.feedback-error.show {\n display: block;\n}\n\n.feedback-success-notification {\n position: fixed;\n top: 24px;\n right: 24px;\n z-index: 1000002;\n background: white;\n border: 1px solid #D1FAE5;\n border-radius: 12px;\n box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);\n animation: slideInRight 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n min-width: 320px;\n}\n\n.feedback-success-content {\n display: flex;\n align-items: center;\n padding: 16px 20px;\n gap: 12px;\n}\n\n.feedback-success-icon {\n width: 20px;\n height: 20px;\n border-radius: 50%;\n background: #10B981;\n color: white;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 12px;\n font-weight: 600;\n flex-shrink: 0;\n}\n\n.feedback-success-content span {\n color: #065F46;\n font-weight: 500;\n font-size: 14px;\n flex: 1;\n}\n\n.feedback-success-close {\n background: none;\n border: none;\n color: #6B7280;\n cursor: pointer;\n font-size: 20px;\n padding: 0;\n width: 24px;\n height: 24px;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.2s ease;\n border-radius: 4px;\n flex-shrink: 0;\n}\n\n.feedback-success-close:hover {\n background: #F3F4F6;\n color: #374151;\n}\n\n.feedback-success-close:focus-visible {\n outline: 2px solid #21244A;\n outline-offset: 2px;\n}\n\n@keyframes slideInRight {\n from {\n transform: translateX(400px);\n opacity: 0;\n }\n to {\n transform: translateX(0);\n opacity: 1;\n }\n}\n\n@keyframes fadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n.feedback-panel-backdrop {\n animation: fadeIn 0.3s ease;\n}\n\n@media (max-width: 768px) {\n .feedback-panel {\n width: 100%;\n top: auto;\n bottom: 0;\n right: 0;\n left: 0;\n height: 85vh;\n max-height: 85vh;\n transform: translateY(100%);\n border-radius: 20px 20px 0 0;\n }\n \n .feedback-panel.open {\n transform: translateY(0);\n }\n \n .feedback-panel-content {\n border-radius: 20px 20px 0 0;\n }\n \n .feedback-panel-header {\n padding: 20px;\n position: relative;\n }\n \n .feedback-panel-header::before {\n content: '';\n position: absolute;\n top: 8px;\n left: 50%;\n transform: translateX(-50%);\n width: 40px;\n height: 4px;\n background: #D1D5DB;\n border-radius: 2px;\n }\n \n .feedback-panel-body {\n padding: 20px;\n }\n \n .feedback-widget-button {\n bottom: 16px;\n right: 16px;\n }\n \n .feedback-widget-button.position-bottom-left {\n left: 16px;\n }\n \n .feedback-success-notification {\n top: 16px;\n right: 16px;\n left: 16px;\n min-width: auto;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .feedback-trigger-btn,\n .feedback-btn,\n .feedback-panel,\n .feedback-panel-backdrop,\n .feedback-success-notification {\n transition: none;\n animation: none;\n }\n}\n\n@media print {\n .feedback-widget,\n .feedback-panel,\n .feedback-panel-backdrop,\n .feedback-success-notification {\n display: none !important;\n }\n}\n",document.head.appendChild(e)}}function w(){if("undefined"!=typeof window&&window.FeedbackSDKConfig){x();const e={...window.FeedbackSDKConfig},t=new v(e);t.init().then(n=>{if(window.FeedbackSDK.instance=t,window.FeedbackSDKConfig.autoCreate){(Array.isArray(window.FeedbackSDKConfig.autoCreate)?window.FeedbackSDKConfig.autoCreate:[window.FeedbackSDKConfig.autoCreate]).forEach(e=>{try{t.createWidget(e.type||"button",e).mount(e.container)}catch(e){console.error("[FeedbackSDK] Failed to create widget:",e)}})}if("undefined"!=typeof CustomEvent){const s=new CustomEvent("FeedbackSDKReady",{detail:{sdk:t,config:e,initData:n}});window.dispatchEvent(s)}}).catch(t=>{if(console.error("[FeedbackSDK] Auto-initialization failed:",t),"undefined"!=typeof CustomEvent){const n=new CustomEvent("FeedbackSDKError",{detail:{error:t,config:e,phase:"initialization"}});window.dispatchEvent(n)}})}}const E={FeedbackSDK:v,BaseWidget:f,ButtonWidget:m,TabWidget:g,InlineWidget:b,SurveyWidget:y,WidgetFactory:k,EventBus:c,APIService:d,SDKError:t,APIError:n,WidgetError:s,ConfigError:i,ValidationError:o,helpers:h,create:e=>(x(),new v(e)),version:"1.0.0",instance:null,isReady:()=>Boolean(E.instance),getInstance:()=>E.instance,setUserContext:e=>{E.instance?E.instance.setUserContext(e):"undefined"!=typeof window&&(window.FeedbackSDKUserContext=e)},initWithUser:async(e,t)=>{x();const n={...e,userContext:t},s=new v(n);return await s.init(),"undefined"!=typeof window&&(window.FeedbackSDK.instance=s),s},onReady:e=>{"undefined"!=typeof window&&(E.isReady()?e(E.instance):window.addEventListener("FeedbackSDKReady",t=>{e(t.detail.sdk,t.detail)},{once:!0}))},onError:e=>{"undefined"!=typeof window&&window.addEventListener("FeedbackSDKError",t=>{e(t.detail.error,t.detail)})},extractUserContext:v.extractUserContextFromAuth};"undefined"!=typeof window&&(window.FeedbackSDK=E,"undefined"!=typeof document&&("loading"===document.readyState?document.addEventListener("DOMContentLoaded",w):setTimeout(w,0))),e.APIError=n,e.APIService=d,e.BaseWidget=f,e.ButtonWidget=m,e.ConfigError=i,e.EventBus=c,e.FeedbackSDK=v,e.InlineWidget=b,e.SDKError=t,e.SurveyWidget=y,e.TabWidget=g,e.ValidationError=o,e.WidgetError=s,e.WidgetFactory=k,e.default=E,e.helpers=h,Object.defineProperty(e,"__esModule",{value:!0})});
2
2
  //# sourceMappingURL=feedback-sdk.min.js.map