@product7/feedback-sdk 1.0.6 → 1.0.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.
@@ -1 +1 @@
1
- {"version":3,"file":"feedback-sdk.min.js","sources":["../src/utils/errors.js","../src/core/APIService.js","../src/core/EventBus.js","../src/utils/helpers.js","../src/widgets/BaseWidget.js","../src/widgets/ButtonWidget.js","../src/widgets/InlineWidget.js","../src/widgets/TabWidget.js","../src/widgets/WidgetFactory.js","../src/core/FeedbackSDK.js","../src/index.js","../src/styles/styles.js"],"sourcesContent":["export class SDKError extends Error {\n\tconstructor(message, cause) {\n\t\tsuper(message);\n\t\tthis.name = 'SDKError';\n\t\tthis.cause = cause;\n\n\t\tif (Error.captureStackTrace) {\n\t\t\tError.captureStackTrace(this, SDKError);\n\t\t}\n\t}\n}\n\nexport class APIError extends Error {\n\tconstructor(status, message, response) {\n\t\tsuper(message);\n\t\tthis.name = 'APIError';\n\t\tthis.status = status;\n\t\tthis.response = response;\n\n\t\tif (Error.captureStackTrace) {\n\t\t\tError.captureStackTrace(this, APIError);\n\t\t}\n\t}\n\n\tisNetworkError() {\n\t\treturn this.status === 0;\n\t}\n\n\tisClientError() {\n\t\treturn this.status >= 400 && this.status < 500;\n\t}\n\n\tisServerError() {\n\t\treturn this.status >= 500 && this.status < 600;\n\t}\n}\n\nexport class WidgetError extends Error {\n\tconstructor(message, widgetType, widgetId) {\n\t\tsuper(message);\n\t\tthis.name = 'WidgetError';\n\t\tthis.widgetType = widgetType;\n\t\tthis.widgetId = widgetId;\n\n\t\tif (Error.captureStackTrace) {\n\t\t\tError.captureStackTrace(this, WidgetError);\n\t\t}\n\t}\n}\n\nexport class ConfigError extends Error {\n\tconstructor(message, configKey) {\n\t\tsuper(message);\n\t\tthis.name = 'ConfigError';\n\t\tthis.configKey = configKey;\n\n\t\tif (Error.captureStackTrace) {\n\t\t\tError.captureStackTrace(this, ConfigError);\n\t\t}\n\t}\n}\n\nexport class ValidationError extends Error {\n\tconstructor(message, field, value) {\n\t\tsuper(message);\n\t\tthis.name = 'ValidationError';\n\t\tthis.field = field;\n\t\tthis.value = value;\n\n\t\tif (Error.captureStackTrace) {\n\t\t\tError.captureStackTrace(this, ValidationError);\n\t\t}\n\t}\n}\n\nexport class ErrorHandler {\n\tconstructor(debug = false) {\n\t\tthis.debug = debug;\n\t}\n\n\thandle(error, context = '') {\n\t\tconst errorInfo = {\n\t\t\tname: error.name,\n\t\t\tmessage: error.message,\n\t\t\tcontext,\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t};\n\n\t\tif (error instanceof APIError) {\n\t\t\terrorInfo.status = error.status;\n\t\t\terrorInfo.type = 'api';\n\t\t} else if (error instanceof WidgetError) {\n\t\t\terrorInfo.widgetType = error.widgetType;\n\t\t\terrorInfo.widgetId = error.widgetId;\n\t\t\terrorInfo.type = 'widget';\n\t\t} else if (error instanceof ConfigError) {\n\t\t\terrorInfo.configKey = error.configKey;\n\t\t\terrorInfo.type = 'config';\n\t\t} else if (error instanceof ValidationError) {\n\t\t\terrorInfo.field = error.field;\n\t\t\terrorInfo.value = error.value;\n\t\t\terrorInfo.type = 'validation';\n\t\t} else {\n\t\t\terrorInfo.type = 'unknown';\n\t\t}\n\n\t\tif (this.debug) {\n\t\t\tconsole.error('[FeedbackSDK Error]', errorInfo, error);\n\t\t} else {\n\t\t\tconsole.error('[FeedbackSDK Error]', error.message);\n\t\t}\n\n\t\treturn errorInfo;\n\t}\n\n\tgetUserMessage(error) {\n\t\tif (error instanceof APIError) {\n\t\t\tif (error.isNetworkError()) {\n\t\t\t\treturn 'Network error. Please check your connection and try again.';\n\t\t\t} else if (error.isClientError()) {\n\t\t\t\treturn 'Invalid request. Please check your input and try again.';\n\t\t\t} else if (error.isServerError()) {\n\t\t\t\treturn 'Server error. Please try again later.';\n\t\t\t}\n\t\t\treturn 'Failed to submit feedback. Please try again.';\n\t\t}\n\n\t\tif (error instanceof ValidationError) {\n\t\t\treturn `Please check your ${error.field}: ${error.message}`;\n\t\t}\n\n\t\tif (error instanceof ConfigError) {\n\t\t\treturn 'Configuration error. Please check your SDK setup.';\n\t\t}\n\n\t\tif (error instanceof WidgetError) {\n\t\t\treturn 'Widget error. Please try refreshing the page.';\n\t\t}\n\n\t\treturn 'An unexpected error occurred. Please try again.';\n\t}\n}\n","import { APIError } from '../utils/errors.js';\n\nexport class APIService {\n\tconstructor(config = {}) {\n\t\tthis.workspace = config.workspace;\n\t\tthis.sessionToken = null;\n\t\tthis.sessionExpiry = null;\n\t\tthis.userContext = config.userContext || null;\n\n\t\tif (config.apiUrl) {\n\t\t\tthis.baseURL = config.apiUrl;\n\t\t} else if (this.workspace) {\n\t\t\tthis.baseURL = `https://${this.workspace}.api.staging.product7.io/api/v1`;\n\t\t} else {\n\t\t\tthis.baseURL = 'https://api.staging.product7.io/api/v1';\n\t\t}\n\n\t\tthis._loadStoredSession();\n\t}\n\n\tasync init(userContext = null) {\n\t\tif (userContext) {\n\t\t\tthis.userContext = userContext;\n\t\t}\n\n\t\tif (this.isSessionValid()) {\n\t\t\treturn { sessionToken: this.sessionToken };\n\t\t}\n\n\t\tif (!this.userContext || !this.workspace) {\n\t\t\tconst error = `Missing ${!this.workspace ? 'workspace' : 'user context'} for initialization`;\n\t\t\tthrow new APIError(400, error);\n\t\t}\n\n\t\tconst payload = {\n\t\t\tworkspace: this.workspace,\n\t\t\tuser: this.userContext,\n\t\t};\n\n\t\ttry {\n\t\t\tconst response = await this._makeRequest('/widget/init', {\n\t\t\t\tmethod: 'POST',\n\t\t\t\tbody: JSON.stringify(payload),\n\t\t\t\theaders: {\n\t\t\t\t\t'Content-Type': 'application/json',\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tthis.sessionToken = response.session_token;\n\t\t\tthis.sessionExpiry = new Date(Date.now() + response.expires_in * 1000);\n\t\t\tthis._storeSession();\n\n\t\t\treturn {\n\t\t\t\tsessionToken: this.sessionToken,\n\t\t\t\tconfig: response.config || {},\n\t\t\t\texpiresIn: response.expires_in,\n\t\t\t};\n\t\t} catch (error) {\n\t\t\tthrow new APIError(\n\t\t\t\terror.status || 500,\n\t\t\t\t`Failed to initialize widget: ${error.message}`,\n\t\t\t\terror.response\n\t\t\t);\n\t\t}\n\t}\n\n\tasync submitFeedback(feedbackData) {\n\t\tif (!this.isSessionValid()) {\n\t\t\tawait this.init();\n\t\t}\n\n\t\tif (!this.sessionToken) {\n\t\t\tthrow new APIError(401, 'No valid session token available');\n\t\t}\n\n\t\tconst payload = {\n\t\t\tboard: feedbackData.board_id || feedbackData.board || feedbackData.boardId,\n\t\t\ttitle: feedbackData.title,\n\t\t\tcontent: feedbackData.content,\n\t\t\tattachments: feedbackData.attachments || [],\n\t\t};\n\n\t\ttry {\n\t\t\tconst response = await this._makeRequest('/widget/feedback', {\n\t\t\t\tmethod: 'POST',\n\t\t\t\tbody: JSON.stringify(payload),\n\t\t\t\theaders: {\n\t\t\t\t\t'Content-Type': 'application/json',\n\t\t\t\t\tAuthorization: `Bearer ${this.sessionToken}`,\n\t\t\t\t},\n\t\t\t});\n\n\t\t\treturn response;\n\t\t} catch (error) {\n\t\t\tif (error.status === 401) {\n\t\t\t\tthis.sessionToken = null;\n\t\t\t\tthis.sessionExpiry = null;\n\t\t\t\tawait this.init();\n\t\t\t\treturn this.submitFeedback(feedbackData);\n\t\t\t}\n\n\t\t\tthrow new APIError(\n\t\t\t\terror.status || 500,\n\t\t\t\t`Failed to submit feedback: ${error.message}`,\n\t\t\t\terror.response\n\t\t\t);\n\t\t}\n\t}\n\n\tisSessionValid() {\n\t\treturn (\n\t\t\tthis.sessionToken && this.sessionExpiry && new Date() < this.sessionExpiry\n\t\t);\n\t}\n\n\tsetUserContext(userContext) {\n\t\tthis.userContext = userContext;\n\t\tif (typeof localStorage !== 'undefined') {\n\t\t\tlocalStorage.setItem('feedbackSDK_userContext', JSON.stringify(userContext));\n\t\t}\n\t}\n\n\tgetUserContext() {\n\t\treturn this.userContext;\n\t}\n\n\tclearSession() {\n\t\tthis.sessionToken = null;\n\t\tthis.sessionExpiry = null;\n\t\tif (typeof localStorage !== 'undefined') {\n\t\t\tlocalStorage.removeItem('feedbackSDK_session');\n\t\t\tlocalStorage.removeItem('feedbackSDK_userContext');\n\t\t}\n\t}\n\n\t_storeSession() {\n\t\tif (typeof localStorage === 'undefined') return;\n\n\t\ttry {\n\t\t\tconst sessionData = {\n\t\t\t\ttoken: this.sessionToken,\n\t\t\t\texpiry: this.sessionExpiry.toISOString(),\n\t\t\t\tworkspace: this.workspace,\n\t\t\t};\n\t\t\tlocalStorage.setItem('feedbackSDK_session', JSON.stringify(sessionData));\n\t\t} catch (error) {\n\t\t\t// Silently fail if localStorage is not available\n\t\t}\n\t}\n\n\t_loadStoredSession() {\n\t\tif (typeof localStorage === 'undefined') return false;\n\n\t\ttry {\n\t\t\tconst stored = localStorage.getItem('feedbackSDK_session');\n\t\t\tif (!stored) return false;\n\n\t\t\tconst sessionData = JSON.parse(stored);\n\t\t\tthis.sessionToken = sessionData.token;\n\t\t\tthis.sessionExpiry = new Date(sessionData.expiry);\n\n\t\t\treturn this.isSessionValid();\n\t\t} catch (error) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tasync _makeRequest(endpoint, options = {}) {\n\t\tconst url = `${this.baseURL}${endpoint}`;\n\n\t\ttry {\n\t\t\tconst response = await fetch(url, options);\n\n\t\t\tif (!response.ok) {\n\t\t\t\tlet errorMessage = `HTTP ${response.status}`;\n\t\t\t\tlet responseData = null;\n\n\t\t\t\ttry {\n\t\t\t\t\tresponseData = await response.json();\n\t\t\t\t\terrorMessage = responseData.message || responseData.error || errorMessage;\n\t\t\t\t} catch (e) {\n\t\t\t\t\terrorMessage = (await response.text()) || errorMessage;\n\t\t\t\t}\n\n\t\t\t\tthrow new APIError(response.status, errorMessage, responseData);\n\t\t\t}\n\n\t\t\tconst contentType = response.headers.get('content-type');\n\t\t\tif (contentType && contentType.includes('application/json')) {\n\t\t\t\treturn await response.json();\n\t\t\t}\n\n\t\t\treturn await response.text();\n\t\t} catch (error) {\n\t\t\tif (error instanceof APIError) {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\tthrow new APIError(0, error.message, null);\n\t\t}\n\t}\n}","export class EventBus {\n\tconstructor() {\n\t\tthis.events = new Map();\n\t}\n\n\ton(event, callback) {\n\t\tif (!this.events.has(event)) {\n\t\t\tthis.events.set(event, []);\n\t\t}\n\t\tthis.events.get(event).push(callback);\n\n\t\treturn () => this.off(event, callback);\n\t}\n\n\toff(event, callback) {\n\t\tconst callbacks = this.events.get(event);\n\t\tif (callbacks) {\n\t\t\tconst index = callbacks.indexOf(callback);\n\t\t\tif (index > -1) {\n\t\t\t\tcallbacks.splice(index, 1);\n\t\t\t}\n\t\t}\n\t}\n\n\temit(event, data) {\n\t\tconst callbacks = this.events.get(event);\n\t\tif (callbacks) {\n\t\t\tcallbacks.forEach((callback) => {\n\t\t\t\ttry {\n\t\t\t\t\tcallback(data);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconsole.error('[FeedbackSDK] Event callback error:', error);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\n\tonce(event, callback) {\n\t\tconst unsubscribe = this.on(event, (data) => {\n\t\t\tcallback(data);\n\t\t\tunsubscribe();\n\t\t});\n\t\treturn unsubscribe;\n\t}\n\n\tclear() {\n\t\tthis.events.clear();\n\t}\n\n\tgetListenerCount(event) {\n\t\tconst callbacks = this.events.get(event);\n\t\treturn callbacks ? callbacks.length : 0;\n\t}\n}\n","export function generateId(prefix = 'feedback') {\n\tconst timestamp = Date.now();\n\tconst random = Math.random().toString(36).substring(2, 9);\n\treturn `${prefix}_${timestamp}_${random}`;\n}\n\nexport function deepMerge(target, source) {\n\tconst result = { ...target };\n\n\tfor (const key in source) {\n\t\tif (source.hasOwnProperty(key)) {\n\t\t\tif (\n\t\t\t\tsource[key] &&\n\t\t\t\ttypeof source[key] === 'object' &&\n\t\t\t\t!Array.isArray(source[key])\n\t\t\t) {\n\t\t\t\tresult[key] = deepMerge(target[key] || {}, source[key]);\n\t\t\t} else {\n\t\t\t\tresult[key] = source[key];\n\t\t\t}\n\t\t}\n\t}\n\n\treturn result;\n}\n\nexport function debounce(func, wait) {\n\tlet timeout;\n\treturn function executedFunction(...args) {\n\t\tconst later = () => {\n\t\t\tclearTimeout(timeout);\n\t\t\tfunc(...args);\n\t\t};\n\t\tclearTimeout(timeout);\n\t\ttimeout = setTimeout(later, wait);\n\t};\n}\n\nexport function throttle(func, limit) {\n\tlet lastFunc;\n\tlet lastRan;\n\treturn function (...args) {\n\t\tif (!lastRan) {\n\t\t\tfunc(...args);\n\t\t\tlastRan = Date.now();\n\t\t} else {\n\t\t\tclearTimeout(lastFunc);\n\t\t\tlastFunc = setTimeout(\n\t\t\t\t() => {\n\t\t\t\t\tif (Date.now() - lastRan >= limit) {\n\t\t\t\t\t\tfunc(...args);\n\t\t\t\t\t\tlastRan = Date.now();\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tlimit - (Date.now() - lastRan)\n\t\t\t);\n\t\t}\n\t};\n}\n\nexport function isValidEmail(email) {\n\tif (!email || typeof email !== 'string') return false;\n\n\tconst emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n\treturn emailRegex.test(email.trim());\n}\n\nexport function sanitizeHTML(str) {\n\tif (!str || typeof str !== 'string') return '';\n\n\tconst div = document.createElement('div');\n\tdiv.textContent = str;\n\treturn div.innerHTML;\n}\n\nexport function getCSSProperty(element, property, fallback = '') {\n\tif (!element || !property) return fallback;\n\n\ttry {\n\t\tconst style = window.getComputedStyle(element);\n\t\treturn style.getPropertyValue(property) || fallback;\n\t} catch (error) {\n\t\treturn fallback;\n\t}\n}\n\nexport function isInViewport(element) {\n\tif (!element) return false;\n\n\tconst rect = element.getBoundingClientRect();\n\treturn (\n\t\trect.top >= 0 &&\n\t\trect.left >= 0 &&\n\t\trect.bottom <=\n\t\t\t(window.innerHeight || document.documentElement.clientHeight) &&\n\t\trect.right <= (window.innerWidth || document.documentElement.clientWidth)\n\t);\n}\n\nexport function scrollToElement(element, options = {}) {\n\tif (!element) return;\n\n\tconst defaultOptions = {\n\t\tbehavior: 'smooth',\n\t\tblock: 'center',\n\t\tinline: 'nearest',\n\t};\n\n\telement.scrollIntoView({ ...defaultOptions, ...options });\n}\n\nexport function getBrowserInfo() {\n\tconst userAgent = navigator.userAgent;\n\tconst platform = navigator.platform;\n\n\treturn {\n\t\tuserAgent,\n\t\tplatform,\n\t\tlanguage: navigator.language || navigator.userLanguage,\n\t\tcookieEnabled: navigator.cookieEnabled,\n\t\tscreenResolution: `${screen.width}x${screen.height}`,\n\t\twindowSize: `${window.innerWidth}x${window.innerHeight}`,\n\t\ttimezone: Intl.DateTimeFormat().resolvedOptions().timeZone,\n\t};\n}\n\nexport function formatFileSize(bytes) {\n\tif (bytes === 0) return '0 Bytes';\n\n\tconst k = 1024;\n\tconst sizes = ['Bytes', 'KB', 'MB', 'GB'];\n\tconst i = Math.floor(Math.log(bytes) / Math.log(k));\n\n\treturn parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];\n}\n\nexport function delay(ms) {\n\treturn new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport function safeJsonParse(str, fallback = null) {\n\ttry {\n\t\treturn JSON.parse(str);\n\t} catch (error) {\n\t\treturn fallback;\n\t}\n}\n\nexport function escapeRegex(string) {\n\treturn string.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\nexport function getNestedProperty(obj, path, defaultValue = undefined) {\n\tif (!obj || !path) return defaultValue;\n\n\tconst keys = path.split('.');\n\tlet current = obj;\n\n\tfor (const key of keys) {\n\t\tif (current === null || current === undefined || !(key in current)) {\n\t\t\treturn defaultValue;\n\t\t}\n\t\tcurrent = current[key];\n\t}\n\n\treturn current;\n}\n\nexport function setNestedProperty(obj, path, value) {\n\tif (!obj || !path) return obj;\n\n\tconst keys = path.split('.');\n\tconst lastKey = keys.pop();\n\tlet current = obj;\n\n\tfor (const key of keys) {\n\t\tif (!(key in current) || typeof current[key] !== 'object') {\n\t\t\tcurrent[key] = {};\n\t\t}\n\t\tcurrent = current[key];\n\t}\n\n\tcurrent[lastKey] = value;\n\treturn obj;\n}\n\nexport function isBrowser() {\n\treturn typeof window !== 'undefined' && typeof document !== 'undefined';\n}\n\nexport function isMobile() {\n\tif (!isBrowser()) return false;\n\n\treturn (\n\t\t/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(\n\t\t\tnavigator.userAgent\n\t\t) || window.innerWidth <= 768\n\t);\n}\n\nexport function getCurrentTimestamp() {\n\treturn new Date().toISOString();\n}\n\nexport function validateConfig(config, required = []) {\n\tconst missing = [];\n\n\tfor (const key of required) {\n\t\tif (!config[key]) {\n\t\t\tmissing.push(key);\n\t\t}\n\t}\n\n\tif (missing.length > 0) {\n\t\tthrow new Error(`Missing required configuration: ${missing.join(', ')}`);\n\t}\n\n\treturn true;\n}\n","export class BaseWidget {\n\tconstructor(options = {}) {\n\t\tthis.id = options.id;\n\t\tthis.sdk = options.sdk;\n\t\tthis.apiService = options.apiService;\n\t\tthis.type = options.type || 'base';\n\n\t\tthis.options = {\n\t\t\tcontainer: null,\n\t\t\tposition: this.sdk.config.position,\n\t\t\ttheme: this.sdk.config.theme,\n\t\t\tboardId: this.sdk.config.boardId,\n\t\t\tautoShow: false,\n\t\t\tshowBackdrop: true,\n\t\t\tcustomStyles: {},\n\t\t\t...options,\n\t\t};\n\n\t\tthis.element = null;\n\t\tthis.panelElement = null;\n\t\tthis.backdropElement = null;\n\t\tthis.mounted = false;\n\t\tthis.destroyed = false;\n\n\t\tthis.state = {\n\t\t\tisOpen: false,\n\t\t\tisSubmitting: false,\n\t\t\ttitle: '',\n\t\t\tcontent: '',\n\t\t\temail: '',\n\t\t\tattachments: [],\n\t\t\terrors: {},\n\t\t};\n\n\t\tthis._bindMethods();\n\t}\n\n\tmount(container) {\n\t\tif (this.mounted || this.destroyed) return this;\n\n\t\tif (typeof container === 'string') {\n\t\t\tcontainer = document.querySelector(container);\n\t\t}\n\n\t\tif (!container) {\n\t\t\tcontainer = document.body;\n\t\t}\n\n\t\tthis.container = container;\n\t\tthis.element = this._render();\n\t\tthis.container.appendChild(this.element);\n\n\t\tthis.mounted = true;\n\t\tthis._attachEvents();\n\t\tthis.onMount();\n\n\t\tif (this.options.autoShow) {\n\t\t\tthis.show();\n\t\t}\n\n\t\tthis.sdk.eventBus.emit('widget:mounted', { widget: this });\n\t\treturn this;\n\t}\n\n\tshow() {\n\t\tif (this.element) {\n\t\t\tthis.element.style.display = 'block';\n\t\t}\n\t\treturn this;\n\t}\n\n\thide() {\n\t\tif (this.element) {\n\t\t\tthis.element.style.display = 'none';\n\t\t}\n\t\treturn this;\n\t}\n\n\topenPanel() {\n\t\tthis.state.isOpen = true;\n\t\tthis._renderPanel();\n\t\t\n\t\trequestAnimationFrame(() => {\n\t\t\tif (this.panelElement) {\n\t\t\t\tthis.panelElement.classList.add('open');\n\t\t\t}\n\t\t\tif (this.backdropElement) {\n\t\t\t\tthis.backdropElement.classList.add('show');\n\t\t\t}\n\t\t});\n\t}\n\n\tclosePanel() {\n\t\tif (this.panelElement) {\n\t\t\tthis.panelElement.classList.remove('open');\n\t\t}\n\t\tif (this.backdropElement) {\n\t\t\tthis.backdropElement.classList.remove('show');\n\t\t}\n\n\t\tsetTimeout(() => {\n\t\t\tthis.state.isOpen = false;\n\t\t\tif (this.panelElement && this.panelElement.parentNode) {\n\t\t\t\tthis.panelElement.parentNode.removeChild(this.panelElement);\n\t\t\t\tthis.panelElement = null;\n\t\t\t}\n\t\t\tif (this.backdropElement && this.backdropElement.parentNode) {\n\t\t\t\tthis.backdropElement.parentNode.removeChild(this.backdropElement);\n\t\t\t\tthis.backdropElement = null;\n\t\t\t}\n\t\t\tthis._resetForm();\n\t\t}, 300);\n\t}\n\n\tasync submitFeedback() {\n\t\tif (this.state.isSubmitting) return;\n\n\t\tthis._hideError();\n\n\t\ttry {\n\t\t\tthis.state.isSubmitting = true;\n\t\t\tthis._updateSubmitButton();\n\n\t\t\tconst payload = {\n\t\t\t\ttitle: this.state.title || 'Feedback',\n\t\t\t\tcontent: this.state.content,\n\t\t\t\temail: this.state.email,\n\t\t\t\tboard_id: this.options.boardId,\n\t\t\t\tattachments: this.state.attachments,\n\t\t\t};\n\n\t\t\tif (!this.state.content.trim()) {\n\t\t\t\tthis._showError('Please enter your feedback message.');\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst response = await this.apiService.submitFeedback(payload);\n\n\t\t\tthis._showSuccessMessage();\n\t\t\tthis.closePanel();\n\n\t\t\tthis.sdk.eventBus.emit('feedback:submitted', {\n\t\t\t\twidget: this,\n\t\t\t\tfeedback: response,\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tthis._showError('Failed to submit feedback. Please try again.');\n\t\t\tthis.sdk.eventBus.emit('feedback:error', { widget: this, error });\n\t\t} finally {\n\t\t\tthis.state.isSubmitting = false;\n\t\t\tthis._updateSubmitButton();\n\t\t}\n\t}\n\n\thandleConfigUpdate(newConfig) {\n\t\tthis.options.theme = newConfig.theme;\n\t\tif (this.element) {\n\t\t\tthis._updateTheme();\n\t\t}\n\t}\n\n\tdestroy() {\n\t\tif (this.destroyed) return;\n\n\t\tthis.onDestroy();\n\t\tthis.closePanel();\n\n\t\tif (this.element && this.element.parentNode) {\n\t\t\tthis.element.parentNode.removeChild(this.element);\n\t\t}\n\n\t\tthis.destroyed = true;\n\t\tthis.mounted = false;\n\t\tthis.sdk.eventBus.emit('widget:destroyed', { widget: this });\n\t}\n\n\tonMount() {}\n\tonDestroy() {}\n\n\t_render() {\n\t\tthrow new Error('_render() must be implemented by concrete widget');\n\t}\n\n\t_attachEvents() {\n\t\t// Override in concrete widgets\n\t}\n\n\t_bindMethods() {\n\t\tthis.openPanel = this.openPanel.bind(this);\n\t\tthis.closePanel = this.closePanel.bind(this);\n\t\tthis.submitFeedback = this.submitFeedback.bind(this);\n\t}\n\n\t_renderPanel() {\n\t\tif (this.panelElement) return;\n\n\t\tif (this.options.showBackdrop) {\n\t\t\tthis.backdropElement = document.createElement('div');\n\t\t\tthis.backdropElement.className = 'feedback-panel-backdrop';\n\t\t\tdocument.body.appendChild(this.backdropElement);\n\n\t\t\tthis.backdropElement.addEventListener('click', this.closePanel);\n\t\t}\n\n\t\tthis.panelElement = document.createElement('div');\n\t\tthis.panelElement.className = `feedback-panel theme-${this.options.theme}`;\n\t\tthis.panelElement.innerHTML = this._getPanelHTML();\n\n\t\tdocument.body.appendChild(this.panelElement);\n\t\tthis._attachPanelEvents();\n\n\t\tconst firstInput = this.panelElement.querySelector('input, textarea');\n\t\tif (firstInput) {\n\t\t\tsetTimeout(() => firstInput.focus(), 350);\n\t\t}\n\t}\n\n\t_getPanelHTML() {\n\t\treturn `\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\">&times;</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 `;\n\t}\n\n\t_attachPanelEvents() {\n\t\tconst panel = this.panelElement;\n\n\t\tpanel\n\t\t\t.querySelector('.feedback-panel-close')\n\t\t\t.addEventListener('click', this.closePanel);\n\n\t\tconst form = panel.querySelector('.feedback-form');\n\t\tform.addEventListener('submit', (e) => {\n\t\t\te.preventDefault();\n\t\t\tthis.submitFeedback();\n\t\t});\n\n\t\tpanel\n\t\t\t.querySelector('input[name=\"title\"]')\n\t\t\t.addEventListener('input', (e) => {\n\t\t\t\tthis.state.title = e.target.value;\n\t\t\t});\n\n\t\tpanel\n\t\t\t.querySelector('textarea[name=\"content\"]')\n\t\t\t.addEventListener('input', (e) => {\n\t\t\t\tthis.state.content = e.target.value;\n\t\t\t});\n\n\t\tconst handleEscape = (e) => {\n\t\t\tif (e.key === 'Escape') {\n\t\t\t\tthis.closePanel();\n\t\t\t\tdocument.removeEventListener('keydown', handleEscape);\n\t\t\t}\n\t\t};\n\t\tdocument.addEventListener('keydown', handleEscape);\n\t}\n\n\t_updateSubmitButton() {\n\t\tif (this.panelElement) {\n\t\t\tconst submitBtn = this.panelElement.querySelector('.feedback-btn-submit');\n\t\t\tif (submitBtn) {\n\t\t\t\tsubmitBtn.textContent = this.state.isSubmitting\n\t\t\t\t\t? 'Sending...'\n\t\t\t\t\t: 'Send Feedback';\n\t\t\t\tsubmitBtn.disabled = this.state.isSubmitting;\n\t\t\t}\n\t\t}\n\t}\n\n\t_showError(message) {\n\t\tif (this.panelElement) {\n\t\t\tconst errorElement = this.panelElement.querySelector('.feedback-error');\n\t\t\tif (errorElement) {\n\t\t\t\terrorElement.textContent = message;\n\t\t\t\terrorElement.classList.add('show');\n\t\t\t}\n\t\t}\n\t}\n\n\t_hideError() {\n\t\tif (this.panelElement) {\n\t\t\tconst errorElement = this.panelElement.querySelector('.feedback-error');\n\t\t\tif (errorElement) {\n\t\t\t\terrorElement.classList.remove('show');\n\t\t\t}\n\t\t}\n\t}\n\n\t_showSuccessMessage() {\n\t\tconst notification = document.createElement('div');\n\t\tnotification.className = 'feedback-success-notification';\n\t\tnotification.innerHTML = `\n <div class=\"feedback-success-content\">\n <div class=\"feedback-success-icon\">✓</div>\n <span>Feedback submitted successfully!</span>\n <button class=\"feedback-success-close\" aria-label=\"Close\">&times;</button>\n </div>\n `;\n\n\t\tdocument.body.appendChild(notification);\n\n\t\tconst closeBtn = notification.querySelector('.feedback-success-close');\n\t\tconst closeNotification = () => {\n\t\t\tif (notification.parentNode) {\n\t\t\t\tnotification.style.opacity = '0';\n\t\t\t\tsetTimeout(() => {\n\t\t\t\t\tif (notification.parentNode) {\n\t\t\t\t\t\tnotification.parentNode.removeChild(notification);\n\t\t\t\t\t}\n\t\t\t\t}, 300);\n\t\t\t}\n\t\t};\n\n\t\tcloseBtn.addEventListener('click', closeNotification);\n\n\t\tsetTimeout(closeNotification, 4000);\n\t}\n\n\t_resetForm() {\n\t\tthis.state.title = '';\n\t\tthis.state.content = '';\n\t\tthis.state.email = '';\n\t\tthis.state.errors = {};\n\t}\n\n\t_updateTheme() {\n\t\tif (this.element) {\n\t\t\tthis.element.className = this.element.className.replace(\n\t\t\t\t/theme-\\w+/,\n\t\t\t\t`theme-${this.options.theme}`\n\t\t\t);\n\t\t}\n\t\tif (this.panelElement) {\n\t\t\tthis.panelElement.className = this.panelElement.className.replace(\n\t\t\t\t/theme-\\w+/,\n\t\t\t\t`theme-${this.options.theme}`\n\t\t\t);\n\t\t}\n\t}\n\n\topenModal() {\n\t\tthis.openPanel();\n\t}\n\n\tcloseModal() {\n\t\tthis.closePanel();\n\t}\n}","import { BaseWidget } from './BaseWidget.js';\n\nexport class ButtonWidget extends BaseWidget {\n\tconstructor(options) {\n\t\tsuper({ ...options, type: 'button' });\n\t}\n\n\t_render() {\n\t\tconst button = document.createElement('div');\n\t\tbutton.className = `feedback-widget feedback-widget-button theme-${this.options.theme} position-${this.options.position}`;\n\t\tbutton.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 `;\n\n\t\tif (this.options.customStyles) {\n\t\t\tObject.assign(button.style, this.options.customStyles);\n\t\t}\n\n\t\treturn button;\n\t}\n\n\t_attachEvents() {\n\t\tconst button = this.element.querySelector('.feedback-trigger-btn');\n\t\tbutton.addEventListener('click', this.openPanel);\n\n\t\tbutton.addEventListener('mouseenter', () => {\n\t\t\tif (!this.state.isSubmitting) {\n\t\t\t\tbutton.style.transform = 'translateY(-2px)';\n\t\t\t}\n\t\t});\n\n\t\tbutton.addEventListener('mouseleave', () => {\n\t\t\tbutton.style.transform = 'translateY(0)';\n\t\t});\n\t}\n\n\tupdateText(text) {\n\t\tconst button = this.element?.querySelector('.feedback-trigger-btn');\n\t\tif (button) {\n\t\t\tconst textNode = button.childNodes[button.childNodes.length - 1];\n\t\t\tif (textNode && textNode.nodeType === Node.TEXT_NODE) {\n\t\t\t\ttextNode.textContent = text;\n\t\t\t}\n\t\t}\n\t}\n\n\tupdatePosition(position) {\n\t\tthis.options.position = position;\n\t\tif (this.element) {\n\t\t\tthis.element.className = this.element.className.replace(\n\t\t\t\t/position-\\w+-\\w+/,\n\t\t\t\t`position-${position}`\n\t\t\t);\n\t\t}\n\t}\n}","import { BaseWidget } from './BaseWidget.js';\n\nexport class InlineWidget extends BaseWidget {\n\tconstructor(options) {\n\t\tsuper({ ...options, type: 'inline' });\n\t}\n\n\t_render() {\n\t\tconst widget = document.createElement('div');\n\t\twidget.className = `feedback-widget feedback-widget-inline theme-${this.options.theme}`;\n\t\twidget.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 `;\n\n\t\tif (this.options.customStyles) {\n\t\t\tObject.assign(widget.style, this.options.customStyles);\n\t\t}\n\n\t\treturn widget;\n\t}\n\n\t_attachEvents() {\n\t\tconst form = this.element.querySelector('.feedback-inline-form');\n\n\t\tform.addEventListener('submit', (e) => {\n\t\t\te.preventDefault();\n\t\t\tthis.submitFeedback();\n\t\t});\n\n\t\tform.querySelector('input[name=\"title\"]').addEventListener('input', (e) => {\n\t\t\tthis.state.title = e.target.value;\n\t\t});\n\n\t\tform\n\t\t\t.querySelector('textarea[name=\"content\"]')\n\t\t\t.addEventListener('input', (e) => {\n\t\t\t\tthis.state.content = e.target.value;\n\t\t\t});\n\n\t\tform.querySelector('input[name=\"email\"]').addEventListener('input', (e) => {\n\t\t\tthis.state.email = e.target.value;\n\t\t});\n\t}\n\n\topenModal() {\n\t\tconst textarea = this.element.querySelector('textarea[name=\"content\"]');\n\t\tif (textarea) {\n\t\t\ttextarea.focus();\n\t\t}\n\t}\n\n\tcloseModal() {\n\t\t// Inline widget doesn't use modal\n\t}\n\n\t_showSuccessMessage() {\n\t\tconst widget = this.element.querySelector('.feedback-inline-content');\n\t\tconst originalContent = widget.innerHTML;\n\n\t\twidget.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 `;\n\n\t\tconst resetBtn = widget.querySelector('.feedback-btn-reset');\n\t\tresetBtn.addEventListener('click', () => {\n\t\t\twidget.innerHTML = originalContent;\n\t\t\tthis._attachEvents();\n\t\t\tthis._resetForm();\n\t\t});\n\t}\n\n\t_showError(message) {\n\t\tconst errorElement = this.element.querySelector('.feedback-error');\n\t\tif (errorElement) {\n\t\t\terrorElement.textContent = message;\n\t\t\terrorElement.style.display = 'block';\n\n\t\t\tsetTimeout(() => {\n\t\t\t\tif (errorElement) {\n\t\t\t\t\terrorElement.style.display = 'none';\n\t\t\t\t}\n\t\t\t}, 5000);\n\t\t}\n\t}\n\n\t_updateSubmitButton() {\n\t\tconst submitBtn = this.element.querySelector('.feedback-btn-submit');\n\t\tif (submitBtn) {\n\t\t\tsubmitBtn.textContent = this.state.isSubmitting\n\t\t\t\t? 'Sending...'\n\t\t\t\t: 'Send Feedback';\n\t\t\tsubmitBtn.disabled = this.state.isSubmitting;\n\t\t}\n\t}\n\n\tupdateTitle(title) {\n\t\tconst titleElement = this.element?.querySelector('h3');\n\t\tif (titleElement) {\n\t\t\ttitleElement.textContent = title;\n\t\t}\n\t}\n\n\tsetPlaceholder(field, placeholder) {\n\t\tconst input = this.element?.querySelector(`[name=\"${field}\"]`);\n\t\tif (input) {\n\t\t\tinput.placeholder = placeholder;\n\t\t}\n\t}\n}\n","import { BaseWidget } from './BaseWidget.js';\n\nexport class TabWidget extends BaseWidget {\n\tconstructor(options) {\n\t\tsuper({ ...options, type: 'tab' });\n\t}\n\n\t_render() {\n\t\tconst tab = document.createElement('div');\n\t\ttab.className = `feedback-widget feedback-widget-tab theme-${this.options.theme} position-${this.options.position}`;\n\t\ttab.innerHTML = `\n <div class=\"feedback-tab-trigger\">\n <span class=\"feedback-tab-text\">Feedback</span>\n </div>\n `;\n\n\t\tif (this.options.customStyles) {\n\t\t\tObject.assign(tab.style, this.options.customStyles);\n\t\t}\n\n\t\treturn tab;\n\t}\n\n\t_attachEvents() {\n\t\tconst tab = this.element.querySelector('.feedback-tab-trigger');\n\t\ttab.addEventListener('click', this.openModal);\n\n\t\ttab.addEventListener('mouseenter', () => {\n\t\t\tif (!this.state.isSubmitting) {\n\t\t\t\ttab.style.transform = this._getHoverTransform();\n\t\t\t}\n\t\t});\n\n\t\ttab.addEventListener('mouseleave', () => {\n\t\t\ttab.style.transform = 'none';\n\t\t});\n\t}\n\n\t_getHoverTransform() {\n\t\tconst position = this.options.position;\n\t\tif (position.includes('right')) {\n\t\t\treturn 'translateX(-5px)';\n\t\t} else if (position.includes('left')) {\n\t\t\treturn 'translateX(5px)';\n\t\t}\n\t\treturn 'none';\n\t}\n\n\tupdateText(text) {\n\t\tconst textElement = this.element?.querySelector('.feedback-tab-text');\n\t\tif (textElement) {\n\t\t\ttextElement.textContent = text;\n\t\t}\n\t}\n\n\tupdatePosition(position) {\n\t\tthis.options.position = position;\n\t\tif (this.element) {\n\t\t\tthis.element.className = this.element.className.replace(\n\t\t\t\t/position-\\w+-\\w+/,\n\t\t\t\t`position-${position}`\n\t\t\t);\n\t\t}\n\t}\n}\n","import { SDKError } from '../utils/errors.js';\nimport { ButtonWidget } from './ButtonWidget.js';\nimport { InlineWidget } from './InlineWidget.js';\nimport { TabWidget } from './TabWidget.js';\n\nexport class WidgetFactory {\n\tstatic widgets = new Map([\n\t\t['button', ButtonWidget],\n\t\t['tab', TabWidget],\n\t\t['inline', InlineWidget],\n\t]);\n\n\tstatic register(type, WidgetClass) {\n\t\tif (typeof type !== 'string' || !type.trim()) {\n\t\t\tthrow new SDKError('Widget type must be a non-empty string');\n\t\t}\n\n\t\tif (typeof WidgetClass !== 'function') {\n\t\t\tthrow new SDKError('Widget class must be a constructor function');\n\t\t}\n\n\t\tthis.widgets.set(type, WidgetClass);\n\t}\n\n\tstatic create(type, options = {}) {\n\t\tconst WidgetClass = this.widgets.get(type);\n\n\t\tif (!WidgetClass) {\n\t\t\tconst availableTypes = Array.from(this.widgets.keys()).join(', ');\n\t\t\tthrow new SDKError(\n\t\t\t\t`Unknown widget type: ${type}. Available types: ${availableTypes}`\n\t\t\t);\n\t\t}\n\n\t\ttry {\n\t\t\treturn new WidgetClass(options);\n\t\t} catch (error) {\n\t\t\tthrow new SDKError(\n\t\t\t\t`Failed to create widget of type '${type}': ${error.message}`,\n\t\t\t\terror\n\t\t\t);\n\t\t}\n\t}\n\n\tstatic getAvailableTypes() {\n\t\treturn Array.from(this.widgets.keys());\n\t}\n\n\tstatic isTypeRegistered(type) {\n\t\treturn this.widgets.has(type);\n\t}\n\n\tstatic unregister(type) {\n\t\treturn this.widgets.delete(type);\n\t}\n\n\tstatic clear() {\n\t\tthis.widgets.clear();\n\t}\n\n\tstatic getWidgetClass(type) {\n\t\treturn this.widgets.get(type);\n\t}\n}\n","import { ConfigError, SDKError } from '../utils/errors.js';\nimport { deepMerge, generateId } from '../utils/helpers.js';\nimport { WidgetFactory } from '../widgets/WidgetFactory.js';\nimport { APIService } from './APIService.js';\nimport { EventBus } from './EventBus.js';\n\nexport class FeedbackSDK {\n\tconstructor(config = {}) {\n\t\tthis.config = this._validateAndMergeConfig(config);\n\t\tthis.initialized = false;\n\t\tthis.widgets = new Map();\n\t\tthis.eventBus = new EventBus();\n\n\t\tthis.apiService = new APIService({\n\t\t\tapiUrl: this.config.apiUrl,\n\t\t\tworkspace: this.config.workspace,\n\t\t\tuserContext: this.config.userContext,\n\t\t});\n\n\t\tthis._bindMethods();\n\t}\n\n\tasync init() {\n\t\tif (this.initialized) {\n\t\t\treturn { alreadyInitialized: true };\n\t\t}\n\n\t\ttry {\n\t\t\tconst initData = await this.apiService.init(this.config.userContext);\n\n\t\t\tif (initData.config) {\n\t\t\t\tthis.config = deepMerge(this.config, initData.config);\n\t\t\t}\n\n\t\t\tthis.initialized = true;\n\t\t\tthis.eventBus.emit('sdk:initialized', {\n\t\t\t\tconfig: this.config,\n\t\t\t\tsessionToken: initData.sessionToken,\n\t\t\t});\n\n\t\t\treturn {\n\t\t\t\tinitialized: true,\n\t\t\t\tconfig: initData.config || {},\n\t\t\t\tsessionToken: initData.sessionToken,\n\t\t\t\texpiresIn: initData.expiresIn,\n\t\t\t};\n\t\t} catch (error) {\n\t\t\tthis.eventBus.emit('sdk:error', { error });\n\t\t\tthrow new SDKError(`Failed to initialize SDK: ${error.message}`, error);\n\t\t}\n\t}\n\n\tcreateWidget(type = 'button', options = {}) {\n\t\tif (!this.initialized) {\n\t\t\tthrow new SDKError('SDK must be initialized before creating widgets. Call init() first.');\n\t\t}\n\n\t\tconst widgetId = generateId('widget');\n\t\tconst widgetOptions = {\n\t\t\tid: widgetId,\n\t\t\tsdk: this,\n\t\t\tapiService: this.apiService,\n\t\t\t...this.config,\n\t\t\t...options,\n\t\t};\n\n\t\ttry {\n\t\t\tconst widget = WidgetFactory.create(type, widgetOptions);\n\t\t\tthis.widgets.set(widgetId, widget);\n\t\t\tthis.eventBus.emit('widget:created', { widget, type });\n\t\t\treturn widget;\n\t\t} catch (error) {\n\t\t\tthrow new SDKError(`Failed to create widget: ${error.message}`, error);\n\t\t}\n\t}\n\n\tgetWidget(id) {\n\t\treturn this.widgets.get(id);\n\t}\n\n\tgetAllWidgets() {\n\t\treturn Array.from(this.widgets.values());\n\t}\n\n\tdestroyWidget(id) {\n\t\tconst widget = this.widgets.get(id);\n\t\tif (widget) {\n\t\t\twidget.destroy();\n\t\t\tthis.widgets.delete(id);\n\t\t\tthis.eventBus.emit('widget:removed', { widgetId: id });\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\tdestroyAllWidgets() {\n\t\tfor (const widget of this.widgets.values()) {\n\t\t\twidget.destroy();\n\t\t}\n\t\tthis.widgets.clear();\n\t\tthis.eventBus.emit('widgets:cleared');\n\t}\n\n\tupdateConfig(newConfig) {\n\t\tconst oldConfig = { ...this.config };\n\t\tthis.config = this._validateAndMergeConfig(newConfig, this.config);\n\n\t\tfor (const widget of this.widgets.values()) {\n\t\t\twidget.handleConfigUpdate(this.config);\n\t\t}\n\n\t\tthis.eventBus.emit('config:updated', {\n\t\t\toldConfig,\n\t\t\tnewConfig: this.config,\n\t\t});\n\t}\n\n\tsetUserContext(userContext) {\n\t\tthis.config.userContext = userContext;\n\t\tif (this.apiService) {\n\t\t\tthis.apiService.setUserContext(userContext);\n\t\t}\n\t\tthis.eventBus.emit('user:updated', { userContext });\n\t}\n\n\tgetUserContext() {\n\t\treturn this.config.userContext || (this.apiService ? this.apiService.getUserContext() : null);\n\t}\n\n\tasync reinitialize(newUserContext = null) {\n\t\tthis.apiService.clearSession();\n\t\tthis.initialized = false;\n\n\t\tif (newUserContext) {\n\t\t\tthis.setUserContext(newUserContext);\n\t\t}\n\n\t\treturn this.init();\n\t}\n\n\ton(event, callback) {\n\t\tthis.eventBus.on(event, callback);\n\t\treturn this;\n\t}\n\n\toff(event, callback) {\n\t\tthis.eventBus.off(event, callback);\n\t\treturn this;\n\t}\n\n\tonce(event, callback) {\n\t\tthis.eventBus.once(event, callback);\n\t\treturn this;\n\t}\n\n\temit(event, data) {\n\t\tthis.eventBus.emit(event, data);\n\t\treturn this;\n\t}\n\n\tdestroy() {\n\t\tthis.destroyAllWidgets();\n\t\tthis.eventBus.removeAllListeners();\n\t\tthis.apiService.clearSession();\n\t\tthis.initialized = false;\n\t\tthis.eventBus.emit('sdk:destroyed');\n\t}\n\n\t_validateAndMergeConfig(newConfig, existingConfig = {}) {\n\t\tconst defaultConfig = {\n\t\t\tapiUrl: null,\n\t\t\tworkspace: null,\n\t\t\tuserContext: null,\n\t\t\tposition: 'bottom-right',\n\t\t\ttheme: 'light',\n\t\t\tboardId: 'general',\n\t\t\tautoShow: true,\n\t\t\tdebug: false,\n\t\t};\n\n\t\tconst mergedConfig = deepMerge(deepMerge(defaultConfig, existingConfig), newConfig);\n\n\t\tif (!mergedConfig.workspace) {\n\t\t\tthrow new ConfigError('Missing required configuration: workspace');\n\t\t}\n\n\t\tif (mergedConfig.userContext) {\n\t\t\tthis._validateUserContext(mergedConfig.userContext);\n\t\t}\n\n\t\treturn mergedConfig;\n\t}\n\n\t_validateUserContext(userContext) {\n\t\tif (!userContext.user_id && !userContext.email) {\n\t\t\tthrow new ConfigError('User context must include at least user_id or email');\n\t\t}\n\n\t\tconst validStructure = {\n\t\t\tuser_id: 'string',\n\t\t\temail: 'string',\n\t\t\tname: 'string',\n\t\t\tcustom_fields: 'object',\n\t\t\tcompany: 'object',\n\t\t};\n\n\t\tfor (const [key, expectedType] of Object.entries(validStructure)) {\n\t\t\tif (userContext[key] && typeof userContext[key] !== expectedType) {\n\t\t\t\tthrow new ConfigError(`User context field '${key}' must be of type '${expectedType}'`);\n\t\t\t}\n\t\t}\n\t}\n\n\t_bindMethods() {\n\t\tthis.createWidget = this.createWidget.bind(this);\n\t\tthis.destroyWidget = this.destroyWidget.bind(this);\n\t\tthis.updateConfig = this.updateConfig.bind(this);\n\t}\n\n\tstatic create(config) {\n\t\treturn new FeedbackSDK(config);\n\t}\n\n\tstatic async createAndInit(config) {\n\t\tconst sdk = new FeedbackSDK(config);\n\t\tawait sdk.init();\n\t\treturn sdk;\n\t}\n\n\tstatic extractUserContextFromAuth(authData) {\n\t\tif (!authData) return null;\n\n\t\treturn {\n\t\t\tuser_id: authData.sub || authData.id || authData.user_id,\n\t\t\temail: authData.email,\n\t\t\tname: authData.name || authData.display_name || authData.full_name,\n\t\t\tcustom_fields: {\n\t\t\t\trole: authData.role,\n\t\t\t\tplan: authData.plan || authData.subscription?.plan,\n\t\t\t\t...(authData.custom_fields || {}),\n\t\t\t},\n\t\t\tcompany: authData.company || authData.organization ? {\n\t\t\t\tid: authData.company?.id || authData.organization?.id,\n\t\t\t\tname: authData.company?.name || authData.organization?.name,\n\t\t\t\tmonthly_spend: authData.company?.monthly_spend,\n\t\t\t} : undefined,\n\t\t};\n\t}\n}\n","import { APIService } from './core/APIService.js';\nimport { EventBus } from './core/EventBus.js';\nimport { FeedbackSDK } from './core/FeedbackSDK.js';\nimport { CSS_STYLES } from './styles/styles.js';\nimport {\n\tAPIError,\n\tConfigError,\n\tSDKError,\n\tValidationError,\n\tWidgetError,\n} from './utils/errors.js';\nimport * as helpers from './utils/helpers.js';\nimport { BaseWidget } from './widgets/BaseWidget.js';\nimport { ButtonWidget } from './widgets/ButtonWidget.js';\nimport { InlineWidget } from './widgets/InlineWidget.js';\nimport { TabWidget } from './widgets/TabWidget.js';\nimport { WidgetFactory } from './widgets/WidgetFactory.js';\n\nfunction injectStyles() {\n\tif (typeof document !== 'undefined' && !document.querySelector('#feedback-sdk-styles')) {\n\t\tconst style = document.createElement('style');\n\t\tstyle.id = 'feedback-sdk-styles';\n\t\tstyle.textContent = CSS_STYLES;\n\t\tdocument.head.appendChild(style);\n\t}\n}\n\nfunction autoInit() {\n\tif (typeof window !== 'undefined' && window.FeedbackSDKConfig) {\n\t\tinjectStyles();\n\n\t\tconst config = { ...window.FeedbackSDKConfig };\n\t\tconst sdk = new FeedbackSDK(config);\n\n\t\tsdk\n\t\t\t.init()\n\t\t\t.then((initData) => {\n\t\t\t\twindow.FeedbackSDK.instance = sdk;\n\n\t\t\t\tif (window.FeedbackSDKConfig.autoCreate) {\n\t\t\t\t\tconst widgets = Array.isArray(window.FeedbackSDKConfig.autoCreate)\n\t\t\t\t\t\t? window.FeedbackSDKConfig.autoCreate\n\t\t\t\t\t\t: [window.FeedbackSDKConfig.autoCreate];\n\n\t\t\t\t\twidgets.forEach((widgetConfig) => {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst widget = sdk.createWidget(\n\t\t\t\t\t\t\t\twidgetConfig.type || 'button',\n\t\t\t\t\t\t\t\twidgetConfig\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\twidget.mount(widgetConfig.container);\n\t\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t\tconsole.error('[FeedbackSDK] Failed to create widget:', error);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tif (typeof CustomEvent !== 'undefined') {\n\t\t\t\t\tconst event = new CustomEvent('FeedbackSDKReady', {\n\t\t\t\t\t\tdetail: { sdk, config, initData },\n\t\t\t\t\t});\n\t\t\t\t\twindow.dispatchEvent(event);\n\t\t\t\t}\n\t\t\t})\n\t\t\t.catch((error) => {\n\t\t\t\tconsole.error('[FeedbackSDK] Auto-initialization failed:', error);\n\n\t\t\t\tif (typeof CustomEvent !== 'undefined') {\n\t\t\t\t\tconst event = new CustomEvent('FeedbackSDKError', {\n\t\t\t\t\t\tdetail: { error, config, phase: 'initialization' },\n\t\t\t\t\t});\n\t\t\t\t\twindow.dispatchEvent(event);\n\t\t\t\t}\n\t\t\t});\n\t}\n}\n\nfunction handleDOMReady() {\n\tif (typeof document !== 'undefined') {\n\t\tif (document.readyState === 'loading') {\n\t\t\tdocument.addEventListener('DOMContentLoaded', autoInit);\n\t\t} else {\n\t\t\tsetTimeout(autoInit, 0);\n\t\t}\n\t}\n}\n\nconst FeedbackSDKExport = {\n\tFeedbackSDK,\n\tBaseWidget,\n\tButtonWidget,\n\tTabWidget,\n\tInlineWidget,\n\tWidgetFactory,\n\tEventBus,\n\tAPIService,\n\tSDKError,\n\tAPIError,\n\tWidgetError,\n\tConfigError,\n\tValidationError,\n\thelpers,\n\tcreate: (config) => {\n\t\tinjectStyles();\n\t\treturn new FeedbackSDK(config);\n\t},\n\tversion: '1.0.0',\n\tinstance: null,\n\n\tisReady: () => Boolean(FeedbackSDKExport.instance),\n\tgetInstance: () => FeedbackSDKExport.instance,\n\n\tsetUserContext: (userContext) => {\n\t\tif (FeedbackSDKExport.instance) {\n\t\t\tFeedbackSDKExport.instance.setUserContext(userContext);\n\t\t} else {\n\t\t\tif (typeof window !== 'undefined') {\n\t\t\t\twindow.FeedbackSDKUserContext = userContext;\n\t\t\t}\n\t\t}\n\t},\n\n\tinitWithUser: async (config, userContext) => {\n\t\tinjectStyles();\n\t\tconst fullConfig = { ...config, userContext };\n\t\tconst sdk = new FeedbackSDK(fullConfig);\n\t\tawait sdk.init();\n\n\t\tif (typeof window !== 'undefined') {\n\t\t\twindow.FeedbackSDK.instance = sdk;\n\t\t}\n\n\t\treturn sdk;\n\t},\n\n\tonReady: (callback) => {\n\t\tif (typeof window !== 'undefined') {\n\t\t\tif (FeedbackSDKExport.isReady()) {\n\t\t\t\tcallback(FeedbackSDKExport.instance);\n\t\t\t} else {\n\t\t\t\twindow.addEventListener(\n\t\t\t\t\t'FeedbackSDKReady',\n\t\t\t\t\t(event) => {\n\t\t\t\t\t\tcallback(event.detail.sdk, event.detail);\n\t\t\t\t\t},\n\t\t\t\t\t{ once: true }\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t},\n\n\tonError: (callback) => {\n\t\tif (typeof window !== 'undefined') {\n\t\t\twindow.addEventListener('FeedbackSDKError', (event) => {\n\t\t\t\tcallback(event.detail.error, event.detail);\n\t\t\t});\n\t\t}\n\t},\n\n\textractUserContext: FeedbackSDK.extractUserContextFromAuth,\n};\n\nif (typeof window !== 'undefined') {\n\twindow.FeedbackSDK = FeedbackSDKExport;\n\thandleDOMReady();\n}\n\nexport default FeedbackSDKExport;\n\nexport {\n\tAPIError,\n\tAPIService,\n\tBaseWidget,\n\tButtonWidget,\n\tConfigError,\n\tEventBus,\n\tFeedbackSDK,\n\thelpers,\n\tInlineWidget,\n\tSDKError,\n\tTabWidget,\n\tValidationError,\n\tWidgetError,\n\tWidgetFactory,\n};","export const CSS_STYLES = `\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`;"],"names":["SDKError","Error","constructor","message","cause","super","this","name","captureStackTrace","APIError","status","response","isNetworkError","isClientError","isServerError","WidgetError","widgetType","widgetId","ConfigError","configKey","ValidationError","field","value","APIService","config","workspace","sessionToken","sessionExpiry","userContext","apiUrl","baseURL","_loadStoredSession","init","isSessionValid","error","payload","user","_makeRequest","method","body","JSON","stringify","headers","session_token","Date","now","expires_in","_storeSession","expiresIn","submitFeedback","feedbackData","board","board_id","boardId","title","content","attachments","Authorization","setUserContext","localStorage","setItem","getUserContext","clearSession","removeItem","sessionData","token","expiry","toISOString","stored","getItem","parse","endpoint","options","url","fetch","ok","errorMessage","responseData","json","e","text","contentType","get","includes","EventBus","events","Map","on","event","callback","has","set","push","off","callbacks","index","indexOf","splice","emit","data","forEach","console","once","unsubscribe","clear","getListenerCount","length","generateId","prefix","Math","random","toString","substring","deepMerge","target","source","result","key","hasOwnProperty","Array","isArray","isBrowser","window","document","func","wait","timeout","args","clearTimeout","setTimeout","ms","Promise","resolve","string","replace","bytes","i","floor","log","parseFloat","pow","toFixed","userAgent","navigator","platform","language","userLanguage","cookieEnabled","screenResolution","screen","width","height","windowSize","innerWidth","innerHeight","timezone","Intl","DateTimeFormat","resolvedOptions","timeZone","element","property","fallback","getComputedStyle","getPropertyValue","obj","path","defaultValue","undefined","keys","split","current","rect","getBoundingClientRect","top","left","bottom","documentElement","clientHeight","right","clientWidth","test","email","trim","str","div","createElement","textContent","innerHTML","scrollIntoView","behavior","block","inline","lastKey","pop","limit","lastFunc","lastRan","required","missing","join","BaseWidget","id","sdk","apiService","type","container","position","theme","autoShow","showBackdrop","customStyles","panelElement","backdropElement","mounted","destroyed","state","isOpen","isSubmitting","errors","_bindMethods","mount","querySelector","_render","appendChild","_attachEvents","onMount","show","eventBus","widget","style","display","hide","openPanel","_renderPanel","requestAnimationFrame","classList","add","closePanel","remove","parentNode","removeChild","_resetForm","_hideError","_updateSubmitButton","_showError","_showSuccessMessage","feedback","handleConfigUpdate","newConfig","_updateTheme","destroy","onDestroy","bind","className","addEventListener","_getPanelHTML","_attachPanelEvents","firstInput","focus","panel","preventDefault","handleEscape","removeEventListener","submitBtn","disabled","errorElement","notification","closeNotification","opacity","openModal","closeModal","ButtonWidget","button","Object","assign","transform","updateText","textNode","childNodes","nodeType","Node","TEXT_NODE","updatePosition","InlineWidget","form","textarea","originalContent","updateTitle","titleElement","setPlaceholder","placeholder","input","TabWidget","tab","_getHoverTransform","textElement","WidgetFactory","static","register","WidgetClass","widgets","create","availableTypes","from","getAvailableTypes","isTypeRegistered","unregister","delete","getWidgetClass","FeedbackSDK","_validateAndMergeConfig","initialized","alreadyInitialized","initData","createWidget","widgetOptions","getWidget","getAllWidgets","values","destroyWidget","destroyAllWidgets","updateConfig","oldConfig","reinitialize","newUserContext","removeAllListeners","existingConfig","mergedConfig","debug","_validateUserContext","user_id","validStructure","custom_fields","company","expectedType","entries","createAndInit","extractUserContextFromAuth","authData","sub","display_name","full_name","role","plan","subscription","organization","monthly_spend","injectStyles","head","autoInit","FeedbackSDKConfig","then","instance","autoCreate","widgetConfig","CustomEvent","detail","dispatchEvent","catch","phase","FeedbackSDKExport","helpers","version","isReady","Boolean","getInstance","FeedbackSDKUserContext","initWithUser","async","fullConfig","onReady","onError","extractUserContext","readyState"],"mappings":"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"}
1
+ {"version":3,"file":"feedback-sdk.min.js","sources":["../src/utils/errors.js","../src/core/APIService.js","../src/core/EventBus.js","../src/utils/helpers.js","../src/widgets/BaseWidget.js","../src/widgets/ButtonWidget.js","../src/widgets/InlineWidget.js","../src/widgets/TabWidget.js","../src/widgets/WidgetFactory.js","../src/core/FeedbackSDK.js","../src/index.js","../src/styles/styles.js"],"sourcesContent":["export class SDKError extends Error {\n\tconstructor(message, cause) {\n\t\tsuper(message);\n\t\tthis.name = 'SDKError';\n\t\tthis.cause = cause;\n\n\t\tif (Error.captureStackTrace) {\n\t\t\tError.captureStackTrace(this, SDKError);\n\t\t}\n\t}\n}\n\nexport class APIError extends Error {\n\tconstructor(status, message, response) {\n\t\tsuper(message);\n\t\tthis.name = 'APIError';\n\t\tthis.status = status;\n\t\tthis.response = response;\n\n\t\tif (Error.captureStackTrace) {\n\t\t\tError.captureStackTrace(this, APIError);\n\t\t}\n\t}\n\n\tisNetworkError() {\n\t\treturn this.status === 0;\n\t}\n\n\tisClientError() {\n\t\treturn this.status >= 400 && this.status < 500;\n\t}\n\n\tisServerError() {\n\t\treturn this.status >= 500 && this.status < 600;\n\t}\n}\n\nexport class WidgetError extends Error {\n\tconstructor(message, widgetType, widgetId) {\n\t\tsuper(message);\n\t\tthis.name = 'WidgetError';\n\t\tthis.widgetType = widgetType;\n\t\tthis.widgetId = widgetId;\n\n\t\tif (Error.captureStackTrace) {\n\t\t\tError.captureStackTrace(this, WidgetError);\n\t\t}\n\t}\n}\n\nexport class ConfigError extends Error {\n\tconstructor(message, configKey) {\n\t\tsuper(message);\n\t\tthis.name = 'ConfigError';\n\t\tthis.configKey = configKey;\n\n\t\tif (Error.captureStackTrace) {\n\t\t\tError.captureStackTrace(this, ConfigError);\n\t\t}\n\t}\n}\n\nexport class ValidationError extends Error {\n\tconstructor(message, field, value) {\n\t\tsuper(message);\n\t\tthis.name = 'ValidationError';\n\t\tthis.field = field;\n\t\tthis.value = value;\n\n\t\tif (Error.captureStackTrace) {\n\t\t\tError.captureStackTrace(this, ValidationError);\n\t\t}\n\t}\n}\n\nexport class ErrorHandler {\n\tconstructor(debug = false) {\n\t\tthis.debug = debug;\n\t}\n\n\thandle(error, context = '') {\n\t\tconst errorInfo = {\n\t\t\tname: error.name,\n\t\t\tmessage: error.message,\n\t\t\tcontext,\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t};\n\n\t\tif (error instanceof APIError) {\n\t\t\terrorInfo.status = error.status;\n\t\t\terrorInfo.type = 'api';\n\t\t} else if (error instanceof WidgetError) {\n\t\t\terrorInfo.widgetType = error.widgetType;\n\t\t\terrorInfo.widgetId = error.widgetId;\n\t\t\terrorInfo.type = 'widget';\n\t\t} else if (error instanceof ConfigError) {\n\t\t\terrorInfo.configKey = error.configKey;\n\t\t\terrorInfo.type = 'config';\n\t\t} else if (error instanceof ValidationError) {\n\t\t\terrorInfo.field = error.field;\n\t\t\terrorInfo.value = error.value;\n\t\t\terrorInfo.type = 'validation';\n\t\t} else {\n\t\t\terrorInfo.type = 'unknown';\n\t\t}\n\n\t\tif (this.debug) {\n\t\t\tconsole.error('[FeedbackSDK Error]', errorInfo, error);\n\t\t} else {\n\t\t\tconsole.error('[FeedbackSDK Error]', error.message);\n\t\t}\n\n\t\treturn errorInfo;\n\t}\n\n\tgetUserMessage(error) {\n\t\tif (error instanceof APIError) {\n\t\t\tif (error.isNetworkError()) {\n\t\t\t\treturn 'Network error. Please check your connection and try again.';\n\t\t\t} else if (error.isClientError()) {\n\t\t\t\treturn 'Invalid request. Please check your input and try again.';\n\t\t\t} else if (error.isServerError()) {\n\t\t\t\treturn 'Server error. Please try again later.';\n\t\t\t}\n\t\t\treturn 'Failed to submit feedback. Please try again.';\n\t\t}\n\n\t\tif (error instanceof ValidationError) {\n\t\t\treturn `Please check your ${error.field}: ${error.message}`;\n\t\t}\n\n\t\tif (error instanceof ConfigError) {\n\t\t\treturn 'Configuration error. Please check your SDK setup.';\n\t\t}\n\n\t\tif (error instanceof WidgetError) {\n\t\t\treturn 'Widget error. Please try refreshing the page.';\n\t\t}\n\n\t\treturn 'An unexpected error occurred. Please try again.';\n\t}\n}\n","import { APIError } from '../utils/errors.js';\n\nexport class APIService {\n\tconstructor(config = {}) {\n\t\tthis.workspace = config.workspace;\n\t\tthis.sessionToken = null;\n\t\tthis.sessionExpiry = null;\n\t\tthis.userContext = config.userContext || null;\n\n\t\tif (config.apiUrl) {\n\t\t\tthis.baseURL = config.apiUrl;\n\t\t} else if (this.workspace) {\n\t\t\tthis.baseURL = `https://${this.workspace}.staging.api.product7.io/api/v1`;\n\t\t} else {\n\t\t\tthis.baseURL = 'https://staging.api.product7.io/api/v1';\n\t\t}\n\n\t\tthis._loadStoredSession();\n\t}\n\n\tasync init(userContext = null) {\n\t\tif (userContext) {\n\t\t\tthis.userContext = userContext;\n\t\t}\n\n\t\tif (this.isSessionValid()) {\n\t\t\treturn { sessionToken: this.sessionToken };\n\t\t}\n\n\t\tif (!this.userContext || !this.workspace) {\n\t\t\tconst error = `Missing ${!this.workspace ? 'workspace' : 'user context'} for initialization`;\n\t\t\tthrow new APIError(400, error);\n\t\t}\n\n\t\tconst payload = {\n\t\t\tworkspace: this.workspace,\n\t\t\tuser: this.userContext,\n\t\t};\n\n\t\ttry {\n\t\t\tconst response = await this._makeRequest('/widget/init', {\n\t\t\t\tmethod: 'POST',\n\t\t\t\tbody: JSON.stringify(payload),\n\t\t\t\theaders: {\n\t\t\t\t\t'Content-Type': 'application/json',\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tthis.sessionToken = response.session_token;\n\t\t\tthis.sessionExpiry = new Date(Date.now() + response.expires_in * 1000);\n\t\t\tthis._storeSession();\n\n\t\t\treturn {\n\t\t\t\tsessionToken: this.sessionToken,\n\t\t\t\tconfig: response.config || {},\n\t\t\t\texpiresIn: response.expires_in,\n\t\t\t};\n\t\t} catch (error) {\n\t\t\tthrow new APIError(\n\t\t\t\terror.status || 500,\n\t\t\t\t`Failed to initialize widget: ${error.message}`,\n\t\t\t\terror.response\n\t\t\t);\n\t\t}\n\t}\n\n\tasync submitFeedback(feedbackData) {\n\t\tif (!this.isSessionValid()) {\n\t\t\tawait this.init();\n\t\t}\n\n\t\tif (!this.sessionToken) {\n\t\t\tthrow new APIError(401, 'No valid session token available');\n\t\t}\n\n\t\tconst payload = {\n\t\t\tboard: feedbackData.board_id || feedbackData.board || feedbackData.boardId,\n\t\t\ttitle: feedbackData.title,\n\t\t\tcontent: feedbackData.content,\n\t\t\tattachments: feedbackData.attachments || [],\n\t\t};\n\n\t\ttry {\n\t\t\tconst response = await this._makeRequest('/widget/feedback', {\n\t\t\t\tmethod: 'POST',\n\t\t\t\tbody: JSON.stringify(payload),\n\t\t\t\theaders: {\n\t\t\t\t\t'Content-Type': 'application/json',\n\t\t\t\t\tAuthorization: `Bearer ${this.sessionToken}`,\n\t\t\t\t},\n\t\t\t});\n\n\t\t\treturn response;\n\t\t} catch (error) {\n\t\t\tif (error.status === 401) {\n\t\t\t\tthis.sessionToken = null;\n\t\t\t\tthis.sessionExpiry = null;\n\t\t\t\tawait this.init();\n\t\t\t\treturn this.submitFeedback(feedbackData);\n\t\t\t}\n\n\t\t\tthrow new APIError(\n\t\t\t\terror.status || 500,\n\t\t\t\t`Failed to submit feedback: ${error.message}`,\n\t\t\t\terror.response\n\t\t\t);\n\t\t}\n\t}\n\n\tisSessionValid() {\n\t\treturn (\n\t\t\tthis.sessionToken && this.sessionExpiry && new Date() < this.sessionExpiry\n\t\t);\n\t}\n\n\tsetUserContext(userContext) {\n\t\tthis.userContext = userContext;\n\t\tif (typeof localStorage !== 'undefined') {\n\t\t\tlocalStorage.setItem('feedbackSDK_userContext', JSON.stringify(userContext));\n\t\t}\n\t}\n\n\tgetUserContext() {\n\t\treturn this.userContext;\n\t}\n\n\tclearSession() {\n\t\tthis.sessionToken = null;\n\t\tthis.sessionExpiry = null;\n\t\tif (typeof localStorage !== 'undefined') {\n\t\t\tlocalStorage.removeItem('feedbackSDK_session');\n\t\t\tlocalStorage.removeItem('feedbackSDK_userContext');\n\t\t}\n\t}\n\n\t_storeSession() {\n\t\tif (typeof localStorage === 'undefined') return;\n\n\t\ttry {\n\t\t\tconst sessionData = {\n\t\t\t\ttoken: this.sessionToken,\n\t\t\t\texpiry: this.sessionExpiry.toISOString(),\n\t\t\t\tworkspace: this.workspace,\n\t\t\t};\n\t\t\tlocalStorage.setItem('feedbackSDK_session', JSON.stringify(sessionData));\n\t\t} catch (error) {\n\t\t\t// Silently fail if localStorage is not available\n\t\t}\n\t}\n\n\t_loadStoredSession() {\n\t\tif (typeof localStorage === 'undefined') return false;\n\n\t\ttry {\n\t\t\tconst stored = localStorage.getItem('feedbackSDK_session');\n\t\t\tif (!stored) return false;\n\n\t\t\tconst sessionData = JSON.parse(stored);\n\t\t\tthis.sessionToken = sessionData.token;\n\t\t\tthis.sessionExpiry = new Date(sessionData.expiry);\n\n\t\t\treturn this.isSessionValid();\n\t\t} catch (error) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tasync _makeRequest(endpoint, options = {}) {\n\t\tconst url = `${this.baseURL}${endpoint}`;\n\n\t\ttry {\n\t\t\tconst response = await fetch(url, options);\n\n\t\t\tif (!response.ok) {\n\t\t\t\tlet errorMessage = `HTTP ${response.status}`;\n\t\t\t\tlet responseData = null;\n\n\t\t\t\ttry {\n\t\t\t\t\tresponseData = await response.json();\n\t\t\t\t\terrorMessage = responseData.message || responseData.error || errorMessage;\n\t\t\t\t} catch (e) {\n\t\t\t\t\terrorMessage = (await response.text()) || errorMessage;\n\t\t\t\t}\n\n\t\t\t\tthrow new APIError(response.status, errorMessage, responseData);\n\t\t\t}\n\n\t\t\tconst contentType = response.headers.get('content-type');\n\t\t\tif (contentType && contentType.includes('application/json')) {\n\t\t\t\treturn await response.json();\n\t\t\t}\n\n\t\t\treturn await response.text();\n\t\t} catch (error) {\n\t\t\tif (error instanceof APIError) {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\tthrow new APIError(0, error.message, null);\n\t\t}\n\t}\n}","export class EventBus {\n\tconstructor() {\n\t\tthis.events = new Map();\n\t}\n\n\ton(event, callback) {\n\t\tif (!this.events.has(event)) {\n\t\t\tthis.events.set(event, []);\n\t\t}\n\t\tthis.events.get(event).push(callback);\n\n\t\treturn () => this.off(event, callback);\n\t}\n\n\toff(event, callback) {\n\t\tconst callbacks = this.events.get(event);\n\t\tif (callbacks) {\n\t\t\tconst index = callbacks.indexOf(callback);\n\t\t\tif (index > -1) {\n\t\t\t\tcallbacks.splice(index, 1);\n\t\t\t}\n\t\t}\n\t}\n\n\temit(event, data) {\n\t\tconst callbacks = this.events.get(event);\n\t\tif (callbacks) {\n\t\t\tcallbacks.forEach((callback) => {\n\t\t\t\ttry {\n\t\t\t\t\tcallback(data);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconsole.error('[FeedbackSDK] Event callback error:', error);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\n\tonce(event, callback) {\n\t\tconst unsubscribe = this.on(event, (data) => {\n\t\t\tcallback(data);\n\t\t\tunsubscribe();\n\t\t});\n\t\treturn unsubscribe;\n\t}\n\n\tclear() {\n\t\tthis.events.clear();\n\t}\n\n\tgetListenerCount(event) {\n\t\tconst callbacks = this.events.get(event);\n\t\treturn callbacks ? callbacks.length : 0;\n\t}\n}\n","export function generateId(prefix = 'feedback') {\n\tconst timestamp = Date.now();\n\tconst random = Math.random().toString(36).substring(2, 9);\n\treturn `${prefix}_${timestamp}_${random}`;\n}\n\nexport function deepMerge(target, source) {\n\tconst result = { ...target };\n\n\tfor (const key in source) {\n\t\tif (source.hasOwnProperty(key)) {\n\t\t\tif (\n\t\t\t\tsource[key] &&\n\t\t\t\ttypeof source[key] === 'object' &&\n\t\t\t\t!Array.isArray(source[key])\n\t\t\t) {\n\t\t\t\tresult[key] = deepMerge(target[key] || {}, source[key]);\n\t\t\t} else {\n\t\t\t\tresult[key] = source[key];\n\t\t\t}\n\t\t}\n\t}\n\n\treturn result;\n}\n\nexport function debounce(func, wait) {\n\tlet timeout;\n\treturn function executedFunction(...args) {\n\t\tconst later = () => {\n\t\t\tclearTimeout(timeout);\n\t\t\tfunc(...args);\n\t\t};\n\t\tclearTimeout(timeout);\n\t\ttimeout = setTimeout(later, wait);\n\t};\n}\n\nexport function throttle(func, limit) {\n\tlet lastFunc;\n\tlet lastRan;\n\treturn function (...args) {\n\t\tif (!lastRan) {\n\t\t\tfunc(...args);\n\t\t\tlastRan = Date.now();\n\t\t} else {\n\t\t\tclearTimeout(lastFunc);\n\t\t\tlastFunc = setTimeout(\n\t\t\t\t() => {\n\t\t\t\t\tif (Date.now() - lastRan >= limit) {\n\t\t\t\t\t\tfunc(...args);\n\t\t\t\t\t\tlastRan = Date.now();\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tlimit - (Date.now() - lastRan)\n\t\t\t);\n\t\t}\n\t};\n}\n\nexport function isValidEmail(email) {\n\tif (!email || typeof email !== 'string') return false;\n\n\tconst emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n\treturn emailRegex.test(email.trim());\n}\n\nexport function sanitizeHTML(str) {\n\tif (!str || typeof str !== 'string') return '';\n\n\tconst div = document.createElement('div');\n\tdiv.textContent = str;\n\treturn div.innerHTML;\n}\n\nexport function getCSSProperty(element, property, fallback = '') {\n\tif (!element || !property) return fallback;\n\n\ttry {\n\t\tconst style = window.getComputedStyle(element);\n\t\treturn style.getPropertyValue(property) || fallback;\n\t} catch (error) {\n\t\treturn fallback;\n\t}\n}\n\nexport function isInViewport(element) {\n\tif (!element) return false;\n\n\tconst rect = element.getBoundingClientRect();\n\treturn (\n\t\trect.top >= 0 &&\n\t\trect.left >= 0 &&\n\t\trect.bottom <=\n\t\t\t(window.innerHeight || document.documentElement.clientHeight) &&\n\t\trect.right <= (window.innerWidth || document.documentElement.clientWidth)\n\t);\n}\n\nexport function scrollToElement(element, options = {}) {\n\tif (!element) return;\n\n\tconst defaultOptions = {\n\t\tbehavior: 'smooth',\n\t\tblock: 'center',\n\t\tinline: 'nearest',\n\t};\n\n\telement.scrollIntoView({ ...defaultOptions, ...options });\n}\n\nexport function getBrowserInfo() {\n\tconst userAgent = navigator.userAgent;\n\tconst platform = navigator.platform;\n\n\treturn {\n\t\tuserAgent,\n\t\tplatform,\n\t\tlanguage: navigator.language || navigator.userLanguage,\n\t\tcookieEnabled: navigator.cookieEnabled,\n\t\tscreenResolution: `${screen.width}x${screen.height}`,\n\t\twindowSize: `${window.innerWidth}x${window.innerHeight}`,\n\t\ttimezone: Intl.DateTimeFormat().resolvedOptions().timeZone,\n\t};\n}\n\nexport function formatFileSize(bytes) {\n\tif (bytes === 0) return '0 Bytes';\n\n\tconst k = 1024;\n\tconst sizes = ['Bytes', 'KB', 'MB', 'GB'];\n\tconst i = Math.floor(Math.log(bytes) / Math.log(k));\n\n\treturn parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];\n}\n\nexport function delay(ms) {\n\treturn new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport function safeJsonParse(str, fallback = null) {\n\ttry {\n\t\treturn JSON.parse(str);\n\t} catch (error) {\n\t\treturn fallback;\n\t}\n}\n\nexport function escapeRegex(string) {\n\treturn string.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\nexport function getNestedProperty(obj, path, defaultValue = undefined) {\n\tif (!obj || !path) return defaultValue;\n\n\tconst keys = path.split('.');\n\tlet current = obj;\n\n\tfor (const key of keys) {\n\t\tif (current === null || current === undefined || !(key in current)) {\n\t\t\treturn defaultValue;\n\t\t}\n\t\tcurrent = current[key];\n\t}\n\n\treturn current;\n}\n\nexport function setNestedProperty(obj, path, value) {\n\tif (!obj || !path) return obj;\n\n\tconst keys = path.split('.');\n\tconst lastKey = keys.pop();\n\tlet current = obj;\n\n\tfor (const key of keys) {\n\t\tif (!(key in current) || typeof current[key] !== 'object') {\n\t\t\tcurrent[key] = {};\n\t\t}\n\t\tcurrent = current[key];\n\t}\n\n\tcurrent[lastKey] = value;\n\treturn obj;\n}\n\nexport function isBrowser() {\n\treturn typeof window !== 'undefined' && typeof document !== 'undefined';\n}\n\nexport function isMobile() {\n\tif (!isBrowser()) return false;\n\n\treturn (\n\t\t/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(\n\t\t\tnavigator.userAgent\n\t\t) || window.innerWidth <= 768\n\t);\n}\n\nexport function getCurrentTimestamp() {\n\treturn new Date().toISOString();\n}\n\nexport function validateConfig(config, required = []) {\n\tconst missing = [];\n\n\tfor (const key of required) {\n\t\tif (!config[key]) {\n\t\t\tmissing.push(key);\n\t\t}\n\t}\n\n\tif (missing.length > 0) {\n\t\tthrow new Error(`Missing required configuration: ${missing.join(', ')}`);\n\t}\n\n\treturn true;\n}\n","export class BaseWidget {\n\tconstructor(options = {}) {\n\t\tthis.id = options.id;\n\t\tthis.sdk = options.sdk;\n\t\tthis.apiService = options.apiService;\n\t\tthis.type = options.type || 'base';\n\n\t\tthis.options = {\n\t\t\tcontainer: null,\n\t\t\tposition: this.sdk.config.position,\n\t\t\ttheme: this.sdk.config.theme,\n\t\t\tboardId: this.sdk.config.boardId,\n\t\t\tautoShow: false,\n\t\t\tshowBackdrop: true,\n\t\t\tcustomStyles: {},\n\t\t\t...options,\n\t\t};\n\n\t\tthis.element = null;\n\t\tthis.panelElement = null;\n\t\tthis.backdropElement = null;\n\t\tthis.mounted = false;\n\t\tthis.destroyed = false;\n\n\t\tthis.state = {\n\t\t\tisOpen: false,\n\t\t\tisSubmitting: false,\n\t\t\ttitle: '',\n\t\t\tcontent: '',\n\t\t\temail: '',\n\t\t\tattachments: [],\n\t\t\terrors: {},\n\t\t};\n\n\t\tthis._bindMethods();\n\t}\n\n\tmount(container) {\n\t\tif (this.mounted || this.destroyed) return this;\n\n\t\tif (typeof container === 'string') {\n\t\t\tcontainer = document.querySelector(container);\n\t\t}\n\n\t\tif (!container) {\n\t\t\tcontainer = document.body;\n\t\t}\n\n\t\tthis.container = container;\n\t\tthis.element = this._render();\n\t\tthis.container.appendChild(this.element);\n\n\t\tthis.mounted = true;\n\t\tthis._attachEvents();\n\t\tthis.onMount();\n\n\t\tif (this.options.autoShow) {\n\t\t\tthis.show();\n\t\t}\n\n\t\tthis.sdk.eventBus.emit('widget:mounted', { widget: this });\n\t\treturn this;\n\t}\n\n\tshow() {\n\t\tif (this.element) {\n\t\t\tthis.element.style.display = 'block';\n\t\t}\n\t\treturn this;\n\t}\n\n\thide() {\n\t\tif (this.element) {\n\t\t\tthis.element.style.display = 'none';\n\t\t}\n\t\treturn this;\n\t}\n\n\topenPanel() {\n\t\tthis.state.isOpen = true;\n\t\tthis._renderPanel();\n\t\t\n\t\trequestAnimationFrame(() => {\n\t\t\tif (this.panelElement) {\n\t\t\t\tthis.panelElement.classList.add('open');\n\t\t\t}\n\t\t\tif (this.backdropElement) {\n\t\t\t\tthis.backdropElement.classList.add('show');\n\t\t\t}\n\t\t});\n\t}\n\n\tclosePanel() {\n\t\tif (this.panelElement) {\n\t\t\tthis.panelElement.classList.remove('open');\n\t\t}\n\t\tif (this.backdropElement) {\n\t\t\tthis.backdropElement.classList.remove('show');\n\t\t}\n\n\t\tsetTimeout(() => {\n\t\t\tthis.state.isOpen = false;\n\t\t\tif (this.panelElement && this.panelElement.parentNode) {\n\t\t\t\tthis.panelElement.parentNode.removeChild(this.panelElement);\n\t\t\t\tthis.panelElement = null;\n\t\t\t}\n\t\t\tif (this.backdropElement && this.backdropElement.parentNode) {\n\t\t\t\tthis.backdropElement.parentNode.removeChild(this.backdropElement);\n\t\t\t\tthis.backdropElement = null;\n\t\t\t}\n\t\t\tthis._resetForm();\n\t\t}, 300);\n\t}\n\n\tasync submitFeedback() {\n\t\tif (this.state.isSubmitting) return;\n\n\t\tthis._hideError();\n\n\t\ttry {\n\t\t\tthis.state.isSubmitting = true;\n\t\t\tthis._updateSubmitButton();\n\n\t\t\tconst payload = {\n\t\t\t\ttitle: this.state.title || 'Feedback',\n\t\t\t\tcontent: this.state.content,\n\t\t\t\temail: this.state.email,\n\t\t\t\tboard_id: this.options.boardId,\n\t\t\t\tattachments: this.state.attachments,\n\t\t\t};\n\n\t\t\tif (!this.state.content.trim()) {\n\t\t\t\tthis._showError('Please enter your feedback message.');\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst response = await this.apiService.submitFeedback(payload);\n\n\t\t\tthis._showSuccessMessage();\n\t\t\tthis.closePanel();\n\n\t\t\tthis.sdk.eventBus.emit('feedback:submitted', {\n\t\t\t\twidget: this,\n\t\t\t\tfeedback: response,\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tthis._showError('Failed to submit feedback. Please try again.');\n\t\t\tthis.sdk.eventBus.emit('feedback:error', { widget: this, error });\n\t\t} finally {\n\t\t\tthis.state.isSubmitting = false;\n\t\t\tthis._updateSubmitButton();\n\t\t}\n\t}\n\n\thandleConfigUpdate(newConfig) {\n\t\tthis.options.theme = newConfig.theme;\n\t\tif (this.element) {\n\t\t\tthis._updateTheme();\n\t\t}\n\t}\n\n\tdestroy() {\n\t\tif (this.destroyed) return;\n\n\t\tthis.onDestroy();\n\t\tthis.closePanel();\n\n\t\tif (this.element && this.element.parentNode) {\n\t\t\tthis.element.parentNode.removeChild(this.element);\n\t\t}\n\n\t\tthis.destroyed = true;\n\t\tthis.mounted = false;\n\t\tthis.sdk.eventBus.emit('widget:destroyed', { widget: this });\n\t}\n\n\tonMount() {}\n\tonDestroy() {}\n\n\t_render() {\n\t\tthrow new Error('_render() must be implemented by concrete widget');\n\t}\n\n\t_attachEvents() {\n\t\t// Override in concrete widgets\n\t}\n\n\t_bindMethods() {\n\t\tthis.openPanel = this.openPanel.bind(this);\n\t\tthis.closePanel = this.closePanel.bind(this);\n\t\tthis.submitFeedback = this.submitFeedback.bind(this);\n\t}\n\n\t_renderPanel() {\n\t\tif (this.panelElement) return;\n\n\t\tif (this.options.showBackdrop) {\n\t\t\tthis.backdropElement = document.createElement('div');\n\t\t\tthis.backdropElement.className = 'feedback-panel-backdrop';\n\t\t\tdocument.body.appendChild(this.backdropElement);\n\n\t\t\tthis.backdropElement.addEventListener('click', this.closePanel);\n\t\t}\n\n\t\tthis.panelElement = document.createElement('div');\n\t\tthis.panelElement.className = `feedback-panel theme-${this.options.theme}`;\n\t\tthis.panelElement.innerHTML = this._getPanelHTML();\n\n\t\tdocument.body.appendChild(this.panelElement);\n\t\tthis._attachPanelEvents();\n\n\t\tconst firstInput = this.panelElement.querySelector('input, textarea');\n\t\tif (firstInput) {\n\t\t\tsetTimeout(() => firstInput.focus(), 350);\n\t\t}\n\t}\n\n\t_getPanelHTML() {\n\t\treturn `\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\">&times;</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 `;\n\t}\n\n\t_attachPanelEvents() {\n\t\tconst panel = this.panelElement;\n\n\t\tpanel\n\t\t\t.querySelector('.feedback-panel-close')\n\t\t\t.addEventListener('click', this.closePanel);\n\n\t\tconst form = panel.querySelector('.feedback-form');\n\t\tform.addEventListener('submit', (e) => {\n\t\t\te.preventDefault();\n\t\t\tthis.submitFeedback();\n\t\t});\n\n\t\tpanel\n\t\t\t.querySelector('input[name=\"title\"]')\n\t\t\t.addEventListener('input', (e) => {\n\t\t\t\tthis.state.title = e.target.value;\n\t\t\t});\n\n\t\tpanel\n\t\t\t.querySelector('textarea[name=\"content\"]')\n\t\t\t.addEventListener('input', (e) => {\n\t\t\t\tthis.state.content = e.target.value;\n\t\t\t});\n\n\t\tconst handleEscape = (e) => {\n\t\t\tif (e.key === 'Escape') {\n\t\t\t\tthis.closePanel();\n\t\t\t\tdocument.removeEventListener('keydown', handleEscape);\n\t\t\t}\n\t\t};\n\t\tdocument.addEventListener('keydown', handleEscape);\n\t}\n\n\t_updateSubmitButton() {\n\t\tif (this.panelElement) {\n\t\t\tconst submitBtn = this.panelElement.querySelector('.feedback-btn-submit');\n\t\t\tif (submitBtn) {\n\t\t\t\tsubmitBtn.textContent = this.state.isSubmitting\n\t\t\t\t\t? 'Sending...'\n\t\t\t\t\t: 'Send Feedback';\n\t\t\t\tsubmitBtn.disabled = this.state.isSubmitting;\n\t\t\t}\n\t\t}\n\t}\n\n\t_showError(message) {\n\t\tif (this.panelElement) {\n\t\t\tconst errorElement = this.panelElement.querySelector('.feedback-error');\n\t\t\tif (errorElement) {\n\t\t\t\terrorElement.textContent = message;\n\t\t\t\terrorElement.classList.add('show');\n\t\t\t}\n\t\t}\n\t}\n\n\t_hideError() {\n\t\tif (this.panelElement) {\n\t\t\tconst errorElement = this.panelElement.querySelector('.feedback-error');\n\t\t\tif (errorElement) {\n\t\t\t\terrorElement.classList.remove('show');\n\t\t\t}\n\t\t}\n\t}\n\n\t_showSuccessMessage() {\n\t\tconst notification = document.createElement('div');\n\t\tnotification.className = 'feedback-success-notification';\n\t\tnotification.innerHTML = `\n <div class=\"feedback-success-content\">\n <div class=\"feedback-success-icon\">✓</div>\n <span>Feedback submitted successfully!</span>\n <button class=\"feedback-success-close\" aria-label=\"Close\">&times;</button>\n </div>\n `;\n\n\t\tdocument.body.appendChild(notification);\n\n\t\tconst closeBtn = notification.querySelector('.feedback-success-close');\n\t\tconst closeNotification = () => {\n\t\t\tif (notification.parentNode) {\n\t\t\t\tnotification.style.opacity = '0';\n\t\t\t\tsetTimeout(() => {\n\t\t\t\t\tif (notification.parentNode) {\n\t\t\t\t\t\tnotification.parentNode.removeChild(notification);\n\t\t\t\t\t}\n\t\t\t\t}, 300);\n\t\t\t}\n\t\t};\n\n\t\tcloseBtn.addEventListener('click', closeNotification);\n\n\t\tsetTimeout(closeNotification, 4000);\n\t}\n\n\t_resetForm() {\n\t\tthis.state.title = '';\n\t\tthis.state.content = '';\n\t\tthis.state.email = '';\n\t\tthis.state.errors = {};\n\t}\n\n\t_updateTheme() {\n\t\tif (this.element) {\n\t\t\tthis.element.className = this.element.className.replace(\n\t\t\t\t/theme-\\w+/,\n\t\t\t\t`theme-${this.options.theme}`\n\t\t\t);\n\t\t}\n\t\tif (this.panelElement) {\n\t\t\tthis.panelElement.className = this.panelElement.className.replace(\n\t\t\t\t/theme-\\w+/,\n\t\t\t\t`theme-${this.options.theme}`\n\t\t\t);\n\t\t}\n\t}\n\n\topenModal() {\n\t\tthis.openPanel();\n\t}\n\n\tcloseModal() {\n\t\tthis.closePanel();\n\t}\n}","import { BaseWidget } from './BaseWidget.js';\n\nexport class ButtonWidget extends BaseWidget {\n\tconstructor(options) {\n\t\tsuper({ ...options, type: 'button' });\n\t}\n\n\t_render() {\n\t\tconst button = document.createElement('div');\n\t\tbutton.className = `feedback-widget feedback-widget-button theme-${this.options.theme} position-${this.options.position}`;\n\t\tbutton.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 `;\n\n\t\tif (this.options.customStyles) {\n\t\t\tObject.assign(button.style, this.options.customStyles);\n\t\t}\n\n\t\treturn button;\n\t}\n\n\t_attachEvents() {\n\t\tconst button = this.element.querySelector('.feedback-trigger-btn');\n\t\tbutton.addEventListener('click', this.openPanel);\n\n\t\tbutton.addEventListener('mouseenter', () => {\n\t\t\tif (!this.state.isSubmitting) {\n\t\t\t\tbutton.style.transform = 'translateY(-2px)';\n\t\t\t}\n\t\t});\n\n\t\tbutton.addEventListener('mouseleave', () => {\n\t\t\tbutton.style.transform = 'translateY(0)';\n\t\t});\n\t}\n\n\tupdateText(text) {\n\t\tconst button = this.element?.querySelector('.feedback-trigger-btn');\n\t\tif (button) {\n\t\t\tconst textNode = button.childNodes[button.childNodes.length - 1];\n\t\t\tif (textNode && textNode.nodeType === Node.TEXT_NODE) {\n\t\t\t\ttextNode.textContent = text;\n\t\t\t}\n\t\t}\n\t}\n\n\tupdatePosition(position) {\n\t\tthis.options.position = position;\n\t\tif (this.element) {\n\t\t\tthis.element.className = this.element.className.replace(\n\t\t\t\t/position-\\w+-\\w+/,\n\t\t\t\t`position-${position}`\n\t\t\t);\n\t\t}\n\t}\n}","import { BaseWidget } from './BaseWidget.js';\n\nexport class InlineWidget extends BaseWidget {\n\tconstructor(options) {\n\t\tsuper({ ...options, type: 'inline' });\n\t}\n\n\t_render() {\n\t\tconst widget = document.createElement('div');\n\t\twidget.className = `feedback-widget feedback-widget-inline theme-${this.options.theme}`;\n\t\twidget.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 `;\n\n\t\tif (this.options.customStyles) {\n\t\t\tObject.assign(widget.style, this.options.customStyles);\n\t\t}\n\n\t\treturn widget;\n\t}\n\n\t_attachEvents() {\n\t\tconst form = this.element.querySelector('.feedback-inline-form');\n\n\t\tform.addEventListener('submit', (e) => {\n\t\t\te.preventDefault();\n\t\t\tthis.submitFeedback();\n\t\t});\n\n\t\tform.querySelector('input[name=\"title\"]').addEventListener('input', (e) => {\n\t\t\tthis.state.title = e.target.value;\n\t\t});\n\n\t\tform\n\t\t\t.querySelector('textarea[name=\"content\"]')\n\t\t\t.addEventListener('input', (e) => {\n\t\t\t\tthis.state.content = e.target.value;\n\t\t\t});\n\n\t\tform.querySelector('input[name=\"email\"]').addEventListener('input', (e) => {\n\t\t\tthis.state.email = e.target.value;\n\t\t});\n\t}\n\n\topenModal() {\n\t\tconst textarea = this.element.querySelector('textarea[name=\"content\"]');\n\t\tif (textarea) {\n\t\t\ttextarea.focus();\n\t\t}\n\t}\n\n\tcloseModal() {\n\t\t// Inline widget doesn't use modal\n\t}\n\n\t_showSuccessMessage() {\n\t\tconst widget = this.element.querySelector('.feedback-inline-content');\n\t\tconst originalContent = widget.innerHTML;\n\n\t\twidget.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 `;\n\n\t\tconst resetBtn = widget.querySelector('.feedback-btn-reset');\n\t\tresetBtn.addEventListener('click', () => {\n\t\t\twidget.innerHTML = originalContent;\n\t\t\tthis._attachEvents();\n\t\t\tthis._resetForm();\n\t\t});\n\t}\n\n\t_showError(message) {\n\t\tconst errorElement = this.element.querySelector('.feedback-error');\n\t\tif (errorElement) {\n\t\t\terrorElement.textContent = message;\n\t\t\terrorElement.style.display = 'block';\n\n\t\t\tsetTimeout(() => {\n\t\t\t\tif (errorElement) {\n\t\t\t\t\terrorElement.style.display = 'none';\n\t\t\t\t}\n\t\t\t}, 5000);\n\t\t}\n\t}\n\n\t_updateSubmitButton() {\n\t\tconst submitBtn = this.element.querySelector('.feedback-btn-submit');\n\t\tif (submitBtn) {\n\t\t\tsubmitBtn.textContent = this.state.isSubmitting\n\t\t\t\t? 'Sending...'\n\t\t\t\t: 'Send Feedback';\n\t\t\tsubmitBtn.disabled = this.state.isSubmitting;\n\t\t}\n\t}\n\n\tupdateTitle(title) {\n\t\tconst titleElement = this.element?.querySelector('h3');\n\t\tif (titleElement) {\n\t\t\ttitleElement.textContent = title;\n\t\t}\n\t}\n\n\tsetPlaceholder(field, placeholder) {\n\t\tconst input = this.element?.querySelector(`[name=\"${field}\"]`);\n\t\tif (input) {\n\t\t\tinput.placeholder = placeholder;\n\t\t}\n\t}\n}\n","import { BaseWidget } from './BaseWidget.js';\n\nexport class TabWidget extends BaseWidget {\n\tconstructor(options) {\n\t\tsuper({ ...options, type: 'tab' });\n\t}\n\n\t_render() {\n\t\tconst tab = document.createElement('div');\n\t\ttab.className = `feedback-widget feedback-widget-tab theme-${this.options.theme} position-${this.options.position}`;\n\t\ttab.innerHTML = `\n <div class=\"feedback-tab-trigger\">\n <span class=\"feedback-tab-text\">Feedback</span>\n </div>\n `;\n\n\t\tif (this.options.customStyles) {\n\t\t\tObject.assign(tab.style, this.options.customStyles);\n\t\t}\n\n\t\treturn tab;\n\t}\n\n\t_attachEvents() {\n\t\tconst tab = this.element.querySelector('.feedback-tab-trigger');\n\t\ttab.addEventListener('click', this.openModal);\n\n\t\ttab.addEventListener('mouseenter', () => {\n\t\t\tif (!this.state.isSubmitting) {\n\t\t\t\ttab.style.transform = this._getHoverTransform();\n\t\t\t}\n\t\t});\n\n\t\ttab.addEventListener('mouseleave', () => {\n\t\t\ttab.style.transform = 'none';\n\t\t});\n\t}\n\n\t_getHoverTransform() {\n\t\tconst position = this.options.position;\n\t\tif (position.includes('right')) {\n\t\t\treturn 'translateX(-5px)';\n\t\t} else if (position.includes('left')) {\n\t\t\treturn 'translateX(5px)';\n\t\t}\n\t\treturn 'none';\n\t}\n\n\tupdateText(text) {\n\t\tconst textElement = this.element?.querySelector('.feedback-tab-text');\n\t\tif (textElement) {\n\t\t\ttextElement.textContent = text;\n\t\t}\n\t}\n\n\tupdatePosition(position) {\n\t\tthis.options.position = position;\n\t\tif (this.element) {\n\t\t\tthis.element.className = this.element.className.replace(\n\t\t\t\t/position-\\w+-\\w+/,\n\t\t\t\t`position-${position}`\n\t\t\t);\n\t\t}\n\t}\n}\n","import { SDKError } from '../utils/errors.js';\nimport { ButtonWidget } from './ButtonWidget.js';\nimport { InlineWidget } from './InlineWidget.js';\nimport { TabWidget } from './TabWidget.js';\n\nexport class WidgetFactory {\n\tstatic widgets = new Map([\n\t\t['button', ButtonWidget],\n\t\t['tab', TabWidget],\n\t\t['inline', InlineWidget],\n\t]);\n\n\tstatic register(type, WidgetClass) {\n\t\tif (typeof type !== 'string' || !type.trim()) {\n\t\t\tthrow new SDKError('Widget type must be a non-empty string');\n\t\t}\n\n\t\tif (typeof WidgetClass !== 'function') {\n\t\t\tthrow new SDKError('Widget class must be a constructor function');\n\t\t}\n\n\t\tthis.widgets.set(type, WidgetClass);\n\t}\n\n\tstatic create(type, options = {}) {\n\t\tconst WidgetClass = this.widgets.get(type);\n\n\t\tif (!WidgetClass) {\n\t\t\tconst availableTypes = Array.from(this.widgets.keys()).join(', ');\n\t\t\tthrow new SDKError(\n\t\t\t\t`Unknown widget type: ${type}. Available types: ${availableTypes}`\n\t\t\t);\n\t\t}\n\n\t\ttry {\n\t\t\treturn new WidgetClass(options);\n\t\t} catch (error) {\n\t\t\tthrow new SDKError(\n\t\t\t\t`Failed to create widget of type '${type}': ${error.message}`,\n\t\t\t\terror\n\t\t\t);\n\t\t}\n\t}\n\n\tstatic getAvailableTypes() {\n\t\treturn Array.from(this.widgets.keys());\n\t}\n\n\tstatic isTypeRegistered(type) {\n\t\treturn this.widgets.has(type);\n\t}\n\n\tstatic unregister(type) {\n\t\treturn this.widgets.delete(type);\n\t}\n\n\tstatic clear() {\n\t\tthis.widgets.clear();\n\t}\n\n\tstatic getWidgetClass(type) {\n\t\treturn this.widgets.get(type);\n\t}\n}\n","import { ConfigError, SDKError } from '../utils/errors.js';\nimport { deepMerge, generateId } from '../utils/helpers.js';\nimport { WidgetFactory } from '../widgets/WidgetFactory.js';\nimport { APIService } from './APIService.js';\nimport { EventBus } from './EventBus.js';\n\nexport class FeedbackSDK {\n\tconstructor(config = {}) {\n\t\tthis.config = this._validateAndMergeConfig(config);\n\t\tthis.initialized = false;\n\t\tthis.widgets = new Map();\n\t\tthis.eventBus = new EventBus();\n\n\t\tthis.apiService = new APIService({\n\t\t\tapiUrl: this.config.apiUrl,\n\t\t\tworkspace: this.config.workspace,\n\t\t\tuserContext: this.config.userContext,\n\t\t});\n\n\t\tthis._bindMethods();\n\t}\n\n\tasync init() {\n\t\tif (this.initialized) {\n\t\t\treturn { alreadyInitialized: true };\n\t\t}\n\n\t\ttry {\n\t\t\tconst initData = await this.apiService.init(this.config.userContext);\n\n\t\t\tif (initData.config) {\n\t\t\t\tthis.config = deepMerge(this.config, initData.config);\n\t\t\t}\n\n\t\t\tthis.initialized = true;\n\t\t\tthis.eventBus.emit('sdk:initialized', {\n\t\t\t\tconfig: this.config,\n\t\t\t\tsessionToken: initData.sessionToken,\n\t\t\t});\n\n\t\t\treturn {\n\t\t\t\tinitialized: true,\n\t\t\t\tconfig: initData.config || {},\n\t\t\t\tsessionToken: initData.sessionToken,\n\t\t\t\texpiresIn: initData.expiresIn,\n\t\t\t};\n\t\t} catch (error) {\n\t\t\tthis.eventBus.emit('sdk:error', { error });\n\t\t\tthrow new SDKError(`Failed to initialize SDK: ${error.message}`, error);\n\t\t}\n\t}\n\n\tcreateWidget(type = 'button', options = {}) {\n\t\tif (!this.initialized) {\n\t\t\tthrow new SDKError('SDK must be initialized before creating widgets. Call init() first.');\n\t\t}\n\n\t\tconst widgetId = generateId('widget');\n\t\tconst widgetOptions = {\n\t\t\tid: widgetId,\n\t\t\tsdk: this,\n\t\t\tapiService: this.apiService,\n\t\t\t...this.config,\n\t\t\t...options,\n\t\t};\n\n\t\ttry {\n\t\t\tconst widget = WidgetFactory.create(type, widgetOptions);\n\t\t\tthis.widgets.set(widgetId, widget);\n\t\t\tthis.eventBus.emit('widget:created', { widget, type });\n\t\t\treturn widget;\n\t\t} catch (error) {\n\t\t\tthrow new SDKError(`Failed to create widget: ${error.message}`, error);\n\t\t}\n\t}\n\n\tgetWidget(id) {\n\t\treturn this.widgets.get(id);\n\t}\n\n\tgetAllWidgets() {\n\t\treturn Array.from(this.widgets.values());\n\t}\n\n\tdestroyWidget(id) {\n\t\tconst widget = this.widgets.get(id);\n\t\tif (widget) {\n\t\t\twidget.destroy();\n\t\t\tthis.widgets.delete(id);\n\t\t\tthis.eventBus.emit('widget:removed', { widgetId: id });\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\tdestroyAllWidgets() {\n\t\tfor (const widget of this.widgets.values()) {\n\t\t\twidget.destroy();\n\t\t}\n\t\tthis.widgets.clear();\n\t\tthis.eventBus.emit('widgets:cleared');\n\t}\n\n\tupdateConfig(newConfig) {\n\t\tconst oldConfig = { ...this.config };\n\t\tthis.config = this._validateAndMergeConfig(newConfig, this.config);\n\n\t\tfor (const widget of this.widgets.values()) {\n\t\t\twidget.handleConfigUpdate(this.config);\n\t\t}\n\n\t\tthis.eventBus.emit('config:updated', {\n\t\t\toldConfig,\n\t\t\tnewConfig: this.config,\n\t\t});\n\t}\n\n\tsetUserContext(userContext) {\n\t\tthis.config.userContext = userContext;\n\t\tif (this.apiService) {\n\t\t\tthis.apiService.setUserContext(userContext);\n\t\t}\n\t\tthis.eventBus.emit('user:updated', { userContext });\n\t}\n\n\tgetUserContext() {\n\t\treturn this.config.userContext || (this.apiService ? this.apiService.getUserContext() : null);\n\t}\n\n\tasync reinitialize(newUserContext = null) {\n\t\tthis.apiService.clearSession();\n\t\tthis.initialized = false;\n\n\t\tif (newUserContext) {\n\t\t\tthis.setUserContext(newUserContext);\n\t\t}\n\n\t\treturn this.init();\n\t}\n\n\ton(event, callback) {\n\t\tthis.eventBus.on(event, callback);\n\t\treturn this;\n\t}\n\n\toff(event, callback) {\n\t\tthis.eventBus.off(event, callback);\n\t\treturn this;\n\t}\n\n\tonce(event, callback) {\n\t\tthis.eventBus.once(event, callback);\n\t\treturn this;\n\t}\n\n\temit(event, data) {\n\t\tthis.eventBus.emit(event, data);\n\t\treturn this;\n\t}\n\n\tdestroy() {\n\t\tthis.destroyAllWidgets();\n\t\tthis.eventBus.removeAllListeners();\n\t\tthis.apiService.clearSession();\n\t\tthis.initialized = false;\n\t\tthis.eventBus.emit('sdk:destroyed');\n\t}\n\n\t_validateAndMergeConfig(newConfig, existingConfig = {}) {\n\t\tconst defaultConfig = {\n\t\t\tapiUrl: null,\n\t\t\tworkspace: null,\n\t\t\tuserContext: null,\n\t\t\tposition: 'bottom-right',\n\t\t\ttheme: 'light',\n\t\t\tboardId: 'general',\n\t\t\tautoShow: true,\n\t\t\tdebug: false,\n\t\t};\n\n\t\tconst mergedConfig = deepMerge(deepMerge(defaultConfig, existingConfig), newConfig);\n\n\t\tif (!mergedConfig.workspace) {\n\t\t\tthrow new ConfigError('Missing required configuration: workspace');\n\t\t}\n\n\t\tif (mergedConfig.userContext) {\n\t\t\tthis._validateUserContext(mergedConfig.userContext);\n\t\t}\n\n\t\treturn mergedConfig;\n\t}\n\n\t_validateUserContext(userContext) {\n\t\tif (!userContext.user_id && !userContext.email) {\n\t\t\tthrow new ConfigError('User context must include at least user_id or email');\n\t\t}\n\n\t\tconst validStructure = {\n\t\t\tuser_id: 'string',\n\t\t\temail: 'string',\n\t\t\tname: 'string',\n\t\t\tcustom_fields: 'object',\n\t\t\tcompany: 'object',\n\t\t};\n\n\t\tfor (const [key, expectedType] of Object.entries(validStructure)) {\n\t\t\tif (userContext[key] && typeof userContext[key] !== expectedType) {\n\t\t\t\tthrow new ConfigError(`User context field '${key}' must be of type '${expectedType}'`);\n\t\t\t}\n\t\t}\n\t}\n\n\t_bindMethods() {\n\t\tthis.createWidget = this.createWidget.bind(this);\n\t\tthis.destroyWidget = this.destroyWidget.bind(this);\n\t\tthis.updateConfig = this.updateConfig.bind(this);\n\t}\n\n\tstatic create(config) {\n\t\treturn new FeedbackSDK(config);\n\t}\n\n\tstatic async createAndInit(config) {\n\t\tconst sdk = new FeedbackSDK(config);\n\t\tawait sdk.init();\n\t\treturn sdk;\n\t}\n\n\tstatic extractUserContextFromAuth(authData) {\n\t\tif (!authData) return null;\n\n\t\treturn {\n\t\t\tuser_id: authData.sub || authData.id || authData.user_id,\n\t\t\temail: authData.email,\n\t\t\tname: authData.name || authData.display_name || authData.full_name,\n\t\t\tcustom_fields: {\n\t\t\t\trole: authData.role,\n\t\t\t\tplan: authData.plan || authData.subscription?.plan,\n\t\t\t\t...(authData.custom_fields || {}),\n\t\t\t},\n\t\t\tcompany: authData.company || authData.organization ? {\n\t\t\t\tid: authData.company?.id || authData.organization?.id,\n\t\t\t\tname: authData.company?.name || authData.organization?.name,\n\t\t\t\tmonthly_spend: authData.company?.monthly_spend,\n\t\t\t} : undefined,\n\t\t};\n\t}\n}\n","import { APIService } from './core/APIService.js';\nimport { EventBus } from './core/EventBus.js';\nimport { FeedbackSDK } from './core/FeedbackSDK.js';\nimport { CSS_STYLES } from './styles/styles.js';\nimport {\n\tAPIError,\n\tConfigError,\n\tSDKError,\n\tValidationError,\n\tWidgetError,\n} from './utils/errors.js';\nimport * as helpers from './utils/helpers.js';\nimport { BaseWidget } from './widgets/BaseWidget.js';\nimport { ButtonWidget } from './widgets/ButtonWidget.js';\nimport { InlineWidget } from './widgets/InlineWidget.js';\nimport { TabWidget } from './widgets/TabWidget.js';\nimport { WidgetFactory } from './widgets/WidgetFactory.js';\n\nfunction injectStyles() {\n\tif (typeof document !== 'undefined' && !document.querySelector('#feedback-sdk-styles')) {\n\t\tconst style = document.createElement('style');\n\t\tstyle.id = 'feedback-sdk-styles';\n\t\tstyle.textContent = CSS_STYLES;\n\t\tdocument.head.appendChild(style);\n\t}\n}\n\nfunction autoInit() {\n\tif (typeof window !== 'undefined' && window.FeedbackSDKConfig) {\n\t\tinjectStyles();\n\n\t\tconst config = { ...window.FeedbackSDKConfig };\n\t\tconst sdk = new FeedbackSDK(config);\n\n\t\tsdk\n\t\t\t.init()\n\t\t\t.then((initData) => {\n\t\t\t\twindow.FeedbackSDK.instance = sdk;\n\n\t\t\t\tif (window.FeedbackSDKConfig.autoCreate) {\n\t\t\t\t\tconst widgets = Array.isArray(window.FeedbackSDKConfig.autoCreate)\n\t\t\t\t\t\t? window.FeedbackSDKConfig.autoCreate\n\t\t\t\t\t\t: [window.FeedbackSDKConfig.autoCreate];\n\n\t\t\t\t\twidgets.forEach((widgetConfig) => {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst widget = sdk.createWidget(\n\t\t\t\t\t\t\t\twidgetConfig.type || 'button',\n\t\t\t\t\t\t\t\twidgetConfig\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\twidget.mount(widgetConfig.container);\n\t\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t\tconsole.error('[FeedbackSDK] Failed to create widget:', error);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tif (typeof CustomEvent !== 'undefined') {\n\t\t\t\t\tconst event = new CustomEvent('FeedbackSDKReady', {\n\t\t\t\t\t\tdetail: { sdk, config, initData },\n\t\t\t\t\t});\n\t\t\t\t\twindow.dispatchEvent(event);\n\t\t\t\t}\n\t\t\t})\n\t\t\t.catch((error) => {\n\t\t\t\tconsole.error('[FeedbackSDK] Auto-initialization failed:', error);\n\n\t\t\t\tif (typeof CustomEvent !== 'undefined') {\n\t\t\t\t\tconst event = new CustomEvent('FeedbackSDKError', {\n\t\t\t\t\t\tdetail: { error, config, phase: 'initialization' },\n\t\t\t\t\t});\n\t\t\t\t\twindow.dispatchEvent(event);\n\t\t\t\t}\n\t\t\t});\n\t}\n}\n\nfunction handleDOMReady() {\n\tif (typeof document !== 'undefined') {\n\t\tif (document.readyState === 'loading') {\n\t\t\tdocument.addEventListener('DOMContentLoaded', autoInit);\n\t\t} else {\n\t\t\tsetTimeout(autoInit, 0);\n\t\t}\n\t}\n}\n\nconst FeedbackSDKExport = {\n\tFeedbackSDK,\n\tBaseWidget,\n\tButtonWidget,\n\tTabWidget,\n\tInlineWidget,\n\tWidgetFactory,\n\tEventBus,\n\tAPIService,\n\tSDKError,\n\tAPIError,\n\tWidgetError,\n\tConfigError,\n\tValidationError,\n\thelpers,\n\tcreate: (config) => {\n\t\tinjectStyles();\n\t\treturn new FeedbackSDK(config);\n\t},\n\tversion: '1.0.0',\n\tinstance: null,\n\n\tisReady: () => Boolean(FeedbackSDKExport.instance),\n\tgetInstance: () => FeedbackSDKExport.instance,\n\n\tsetUserContext: (userContext) => {\n\t\tif (FeedbackSDKExport.instance) {\n\t\t\tFeedbackSDKExport.instance.setUserContext(userContext);\n\t\t} else {\n\t\t\tif (typeof window !== 'undefined') {\n\t\t\t\twindow.FeedbackSDKUserContext = userContext;\n\t\t\t}\n\t\t}\n\t},\n\n\tinitWithUser: async (config, userContext) => {\n\t\tinjectStyles();\n\t\tconst fullConfig = { ...config, userContext };\n\t\tconst sdk = new FeedbackSDK(fullConfig);\n\t\tawait sdk.init();\n\n\t\tif (typeof window !== 'undefined') {\n\t\t\twindow.FeedbackSDK.instance = sdk;\n\t\t}\n\n\t\treturn sdk;\n\t},\n\n\tonReady: (callback) => {\n\t\tif (typeof window !== 'undefined') {\n\t\t\tif (FeedbackSDKExport.isReady()) {\n\t\t\t\tcallback(FeedbackSDKExport.instance);\n\t\t\t} else {\n\t\t\t\twindow.addEventListener(\n\t\t\t\t\t'FeedbackSDKReady',\n\t\t\t\t\t(event) => {\n\t\t\t\t\t\tcallback(event.detail.sdk, event.detail);\n\t\t\t\t\t},\n\t\t\t\t\t{ once: true }\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t},\n\n\tonError: (callback) => {\n\t\tif (typeof window !== 'undefined') {\n\t\t\twindow.addEventListener('FeedbackSDKError', (event) => {\n\t\t\t\tcallback(event.detail.error, event.detail);\n\t\t\t});\n\t\t}\n\t},\n\n\textractUserContext: FeedbackSDK.extractUserContextFromAuth,\n};\n\nif (typeof window !== 'undefined') {\n\twindow.FeedbackSDK = FeedbackSDKExport;\n\thandleDOMReady();\n}\n\nexport default FeedbackSDKExport;\n\nexport {\n\tAPIError,\n\tAPIService,\n\tBaseWidget,\n\tButtonWidget,\n\tConfigError,\n\tEventBus,\n\tFeedbackSDK,\n\thelpers,\n\tInlineWidget,\n\tSDKError,\n\tTabWidget,\n\tValidationError,\n\tWidgetError,\n\tWidgetFactory,\n};","export const CSS_STYLES = `\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`;"],"names":["SDKError","Error","constructor","message","cause","super","this","name","captureStackTrace","APIError","status","response","isNetworkError","isClientError","isServerError","WidgetError","widgetType","widgetId","ConfigError","configKey","ValidationError","field","value","APIService","config","workspace","sessionToken","sessionExpiry","userContext","apiUrl","baseURL","_loadStoredSession","init","isSessionValid","error","payload","user","_makeRequest","method","body","JSON","stringify","headers","session_token","Date","now","expires_in","_storeSession","expiresIn","submitFeedback","feedbackData","board","board_id","boardId","title","content","attachments","Authorization","setUserContext","localStorage","setItem","getUserContext","clearSession","removeItem","sessionData","token","expiry","toISOString","stored","getItem","parse","endpoint","options","url","fetch","ok","errorMessage","responseData","json","e","text","contentType","get","includes","EventBus","events","Map","on","event","callback","has","set","push","off","callbacks","index","indexOf","splice","emit","data","forEach","console","once","unsubscribe","clear","getListenerCount","length","generateId","prefix","Math","random","toString","substring","deepMerge","target","source","result","key","hasOwnProperty","Array","isArray","isBrowser","window","document","func","wait","timeout","args","clearTimeout","setTimeout","ms","Promise","resolve","string","replace","bytes","i","floor","log","parseFloat","pow","toFixed","userAgent","navigator","platform","language","userLanguage","cookieEnabled","screenResolution","screen","width","height","windowSize","innerWidth","innerHeight","timezone","Intl","DateTimeFormat","resolvedOptions","timeZone","element","property","fallback","getComputedStyle","getPropertyValue","obj","path","defaultValue","undefined","keys","split","current","rect","getBoundingClientRect","top","left","bottom","documentElement","clientHeight","right","clientWidth","test","email","trim","str","div","createElement","textContent","innerHTML","scrollIntoView","behavior","block","inline","lastKey","pop","limit","lastFunc","lastRan","required","missing","join","BaseWidget","id","sdk","apiService","type","container","position","theme","autoShow","showBackdrop","customStyles","panelElement","backdropElement","mounted","destroyed","state","isOpen","isSubmitting","errors","_bindMethods","mount","querySelector","_render","appendChild","_attachEvents","onMount","show","eventBus","widget","style","display","hide","openPanel","_renderPanel","requestAnimationFrame","classList","add","closePanel","remove","parentNode","removeChild","_resetForm","_hideError","_updateSubmitButton","_showError","_showSuccessMessage","feedback","handleConfigUpdate","newConfig","_updateTheme","destroy","onDestroy","bind","className","addEventListener","_getPanelHTML","_attachPanelEvents","firstInput","focus","panel","preventDefault","handleEscape","removeEventListener","submitBtn","disabled","errorElement","notification","closeNotification","opacity","openModal","closeModal","ButtonWidget","button","Object","assign","transform","updateText","textNode","childNodes","nodeType","Node","TEXT_NODE","updatePosition","InlineWidget","form","textarea","originalContent","updateTitle","titleElement","setPlaceholder","placeholder","input","TabWidget","tab","_getHoverTransform","textElement","WidgetFactory","static","register","WidgetClass","widgets","create","availableTypes","from","getAvailableTypes","isTypeRegistered","unregister","delete","getWidgetClass","FeedbackSDK","_validateAndMergeConfig","initialized","alreadyInitialized","initData","createWidget","widgetOptions","getWidget","getAllWidgets","values","destroyWidget","destroyAllWidgets","updateConfig","oldConfig","reinitialize","newUserContext","removeAllListeners","existingConfig","mergedConfig","debug","_validateUserContext","user_id","validStructure","custom_fields","company","expectedType","entries","createAndInit","extractUserContextFromAuth","authData","sub","display_name","full_name","role","plan","subscription","organization","monthly_spend","injectStyles","head","autoInit","FeedbackSDKConfig","then","instance","autoCreate","widgetConfig","CustomEvent","detail","dispatchEvent","catch","phase","FeedbackSDKExport","helpers","version","isReady","Boolean","getInstance","FeedbackSDKUserContext","initWithUser","async","fullConfig","onReady","onError","extractUserContext","readyState"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@product7/feedback-sdk",
3
- "version": "1.0.6",
3
+ "version": "1.0.8",
4
4
  "description": "JavaScript SDK for integrating Product7 feedback widgets into any website",
5
5
  "main": "dist/feedback-sdk.js",
6
6
  "module": "src/index.js",
@@ -10,9 +10,9 @@ export class APIService {
10
10
  if (config.apiUrl) {
11
11
  this.baseURL = config.apiUrl;
12
12
  } else if (this.workspace) {
13
- this.baseURL = `https://${this.workspace}.api.staging.product7.io/api/v1`;
13
+ this.baseURL = `https://${this.workspace}.staging.api.product7.io/api/v1`;
14
14
  } else {
15
- this.baseURL = 'https://api.staging.product7.io/api/v1';
15
+ this.baseURL = 'https://staging.api.product7.io/api/v1';
16
16
  }
17
17
 
18
18
  this._loadStoredSession();