@product7/feedback-sdk 1.1.6 → 1.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/feedback-sdk.js +226 -215
- package/dist/feedback-sdk.js.map +1 -1
- package/dist/feedback-sdk.min.js +1 -1
- package/dist/feedback-sdk.min.js.map +1 -1
- package/package.json +1 -1
- package/src/styles/styles.js +185 -183
- package/src/widgets/BaseWidget.js +24 -21
- package/src/widgets/ButtonWidget.js +19 -13
package/dist/feedback-sdk.min.js
CHANGED
|
@@ -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">×</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">×</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;">×</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})});
|
|
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>Send Feedback</h3>\n <button class="feedback-panel-close" type="button" aria-label="Close">×</button>\n </div>\n <div class="feedback-panel-body">\n <form class="feedback-form">\n <div class="feedback-form-group">\n <label for="feedback-title-${this.id}">Title (optional)</label>\n <input \n type="text" \n id="feedback-title-${this.id}" \n name="title" \n placeholder="Brief description of your feedback"\n value="${this.state.title}"\n />\n </div>\n <div class="feedback-form-group">\n <label for="feedback-content-${this.id}">Message *</label>\n <textarea \n id="feedback-content-${this.id}" \n name="content" \n placeholder="Tell us what you think..."\n required\n >${this.state.content}</textarea>\n </div>\n <div class="feedback-error" role="alert"></div>\n <div class="feedback-form-actions">\n <button type="submit" class="feedback-btn feedback-btn-submit">\n ${this.state.isSubmitting?"Sending...":"Send 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">×</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 b 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">\n <svg width="20" height="20" viewBox="0 0 20 20" fill="currentColor">\n <path d="M2.003 5.884L10 9.882l7.997-3.998A2 2 0 0016 4H4a2 2 0 00-1.997 1.884z"/>\n <path d="M18 8.118l-8 4-8-4V14a2 2 0 002 2h12a2 2 0 002-2V8.118z"/>\n </svg>\n Feedback\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="translateY(-2px)")}),e.addEventListener("mouseleave",()=>{e.style.transform="translateY(0)"})}updateText(e){const t=this.element?.querySelector(".feedback-trigger-btn");if(t){const n=t.childNodes[t.childNodes.length-1];n&&n.nodeType===Node.TEXT_NODE&&(n.textContent=e)}}updatePosition(e){this.options.position=e,this.element&&(this.element.className=this.element.className.replace(/position-\w+-\w+/,`position-${e}`))}}class m 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;">×</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",b],["tab",g],["inline",m],["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: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', Oxygen, Ubuntu, Cantarell, 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-trigger-btn {\n position: relative;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 12px;\n height: 44px;\n overflow: hidden;\n border-radius: 0.5rem;\n border: none;\n padding: 10px 16px;\n font-size: 14px;\n font-weight: 500;\n font-family: inherit;\n cursor: pointer;\n transition: all 0.3s ease;\n color: white;\n background: #155EEF;\n box-shadow: 0 1px 2px 0 rgba(16, 24, 40, 0.05);\n}\n\n.feedback-trigger-btn:hover:not(:disabled) {\n background: #004EEB;\n box-shadow: 0 1px 2px 0 rgba(16, 24, 40, 0.1);\n}\n\n.feedback-trigger-btn:disabled {\n opacity: 0.7;\n cursor: not-allowed;\n}\n\n.feedback-trigger-btn:focus-visible {\n outline: 2px solid #155EEF;\n outline-offset: 2px;\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.1);\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: white;\n height: 100%;\n display: flex;\n flex-direction: column;\n border-radius: 16px;\n box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), \n 0 10px 10px -5px rgba(0, 0, 0, 0.04),\n 0 0 0 1px rgba(0, 0, 0, 0.05);\n}\n\n.feedback-panel.theme-dark .feedback-panel-content {\n background: #1F2937;\n color: white;\n}\n\n.feedback-panel-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 24px;\n border-bottom: 1px solid #E5E7EB;\n flex-shrink: 0;\n}\n\n.feedback-panel.theme-dark .feedback-panel-header {\n border-bottom-color: #374151;\n}\n\n.feedback-panel-header h3 {\n margin: 0;\n font-size: 18px;\n font-weight: 600;\n color: #111827;\n}\n\n.feedback-panel.theme-dark .feedback-panel-header h3 {\n color: white;\n}\n\n.feedback-panel-close {\n background: none;\n border: none;\n font-size: 24px;\n cursor: pointer;\n color: #6B7280;\n padding: 4px;\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 6px;\n transition: all 0.2s ease;\n}\n\n.feedback-panel-close:hover {\n background: #F3F4F6;\n color: #111827;\n}\n\n.feedback-panel-close:focus-visible {\n outline: 2px solid #155EEF;\n outline-offset: 2px;\n}\n\n.feedback-panel.theme-dark .feedback-panel-close {\n color: #9CA3AF;\n}\n\n.feedback-panel.theme-dark .feedback-panel-close:hover {\n background: #374151;\n color: white;\n}\n\n.feedback-panel-body {\n flex: 1;\n overflow-y: auto;\n padding: 24px;\n}\n\n.feedback-form {\n display: flex;\n flex-direction: column;\n height: 100%;\n}\n\n.feedback-form-group {\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin-bottom: 20px;\n}\n\n.feedback-form-group:last-child {\n margin-bottom: 0;\n}\n\n.feedback-form-group label {\n font-size: 14px;\n font-weight: 500;\n line-height: 1.25;\n color: #374151;\n}\n\n.feedback-panel.theme-dark .feedback-form-group label {\n color: #D1D5DB;\n}\n\n.feedback-form-group input {\n height: 44px;\n width: 100%;\n border-radius: 8px;\n border: 1px solid #D1D5DB;\n padding: 10px 14px;\n font-size: 15px;\n font-weight: 400;\n line-height: 1.5;\n color: #1F2937;\n font-family: inherit;\n outline: none;\n transition: all 0.2s ease;\n}\n\n.feedback-form-group input::placeholder {\n font-size: 15px;\n color: #9CA3AF;\n}\n\n.feedback-form-group input:focus {\n border-color: #155EEF;\n box-shadow: 0 0 0 3px rgba(21, 94, 239, 0.1);\n}\n\n.feedback-form-group input:focus-visible {\n outline: none;\n}\n\n.feedback-form-group textarea {\n min-height: 200px;\n width: 100%;\n resize: vertical;\n border-radius: 8px;\n border: 1px solid #D1D5DB;\n padding: 10px 14px;\n font-size: 15px;\n font-weight: 400;\n line-height: 1.5;\n color: #1F2937;\n font-family: inherit;\n outline: none;\n transition: all 0.2s ease;\n}\n\n.feedback-form-group textarea::placeholder {\n font-size: 15px;\n color: #9CA3AF;\n}\n\n.feedback-form-group textarea:focus {\n border-color: #155EEF;\n box-shadow: 0 0 0 3px rgba(21, 94, 239, 0.1);\n}\n\n.feedback-form-group textarea:focus-visible {\n outline: none;\n}\n\n.feedback-panel.theme-dark .feedback-form-group input,\n.feedback-panel.theme-dark .feedback-form-group textarea {\n background: #374151;\n border-color: #4B5563;\n color: white;\n}\n\n.feedback-panel.theme-dark .feedback-form-group input::placeholder,\n.feedback-panel.theme-dark .feedback-form-group textarea::placeholder {\n color: #6B7280;\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.2s 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 #155EEF;\n outline-offset: 2px;\n}\n\n.feedback-btn-submit {\n background: #155EEF;\n color: white;\n width: 100%;\n}\n\n.feedback-btn-submit:hover:not(:disabled) {\n background: #1A56DB;\n}\n\n.feedback-btn-submit:active:not(:disabled) {\n background: #1E429F;\n}\n\n.feedback-btn-cancel {\n background: transparent;\n color: #6B7280;\n border: 1px solid #D1D5DB;\n}\n\n.feedback-btn-cancel:hover:not(:disabled) {\n background: #F9FAFB;\n border-color: #9CA3AF;\n color: #374151;\n}\n\n.feedback-panel.theme-dark .feedback-btn-cancel {\n color: #D1D5DB;\n border-color: #4B5563;\n}\n\n.feedback-panel.theme-dark .feedback-btn-cancel:hover:not(:disabled) {\n background: #374151;\n}\n\n.feedback-form-actions {\n display: flex;\n flex-direction: column;\n gap: 12px;\n margin-top: auto;\n padding-top: 24px;\n}\n\n.feedback-error {\n color: #DC2626;\n font-size: 14px;\n font-weight: 400;\n margin-top: 8px;\n padding: 12px;\n background: #FEE2E2;\n border: 1px solid #FECACA;\n border-radius: 8px;\n display: none;\n}\n\n.feedback-error.show {\n display: block;\n}\n\n.feedback-panel.theme-dark .feedback-error {\n background: #7F1D1D;\n border-color: #991B1B;\n color: #FCA5A5;\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 #155EEF;\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.theme-dark .feedback-panel-header::before {\n background: #4B5563;\n }\n \n .feedback-panel-body {\n padding: 20px;\n }\n \n .feedback-form-group textarea {\n min-height: 150px;\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:b,TabWidget:g,InlineWidget:m,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=b,e.ConfigError=i,e.EventBus=c,e.FeedbackSDK=v,e.InlineWidget=m,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
|