@product7/feedback-sdk 1.2.6 → 1.2.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +35 -35
- package/dist/README.md +35 -35
- package/dist/feedback-sdk.js +719 -660
- package/dist/feedback-sdk.js.map +1 -1
- package/dist/feedback-sdk.min.js +1 -1
- package/dist/feedback-sdk.min.js.map +1 -1
- package/package.json +1 -1
- package/src/core/APIService.js +66 -41
- package/src/core/FeedbackSDK.js +5 -3
- package/src/core/WebSocketService.js +3 -1
- package/src/widgets/BaseWidget.js +6 -4
- package/src/widgets/MessengerWidget.js +22 -7
- package/src/widgets/messenger/views/ChatView.js +12 -4
- package/src/widgets/messenger/views/HomeView.js +7 -2
- package/types/index.d.ts +49 -0
|
@@ -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/ChangelogWidget.js","../src/widgets/InlineWidget.js","../src/widgets/messenger/MessengerState.js","../src/widgets/messenger/components/MessengerLauncher.js","../src/widgets/messenger/components/NavigationTabs.js","../src/widgets/messenger/components/MessengerPanel.js","../src/widgets/messenger/views/ChangelogView.js","../src/widgets/messenger/views/ChatView.js","../src/widgets/messenger/views/ConversationsView.js","../src/widgets/messenger/views/HelpView.js","../src/widgets/messenger/views/HomeView.js","../src/core/WebSocketService.js","../src/widgets/MessengerWidget.js","../src/widgets/SurveyWidget.js","../src/widgets/TabWidget.js","../src/widgets/WidgetFactory.js","../src/core/FeedbackSDK.js","../src/index.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\nconst MOCK_CONFIG = {\n\tprimaryColor: '#21244A',\n\tbackgroundColor: '#ffffff',\n\ttextColor: '#1F2937',\n\tboardId: 'feature-requests',\n\tsize: 'medium',\n\tdisplayMode: 'modal',\n};\n\n// Mock changelogs for development\nconst MOCK_CHANGELOGS = [\n\t{\n\t\tid: 'changelog_1',\n\t\ttitle:\n\t\t\t'Feature prioritization, multiple roadmaps, and feature request analytics.',\n\t\texcerpt:\n\t\t\t'We are super excited to bring you the long-waited feature prioritization together with many quality updates!',\n\t\tdescription:\n\t\t\t'We are super excited to bring you the long-waited feature prioritization together with many quality updates!',\n\t\tcover_image:\n\t\t\t'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAwIiBoZWlnaHQ9IjI1MCIgdmlld0JveD0iMCAwIDQwMCAyNTAiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHJlY3Qgd2lkdGg9IjQwMCIgaGVpZ2h0PSIyNTAiIGZpbGw9IiNEQkVBRkUiLz48cmVjdCB4PSIyMCIgeT0iMjAiIHdpZHRoPSIzNjAiIGhlaWdodD0iMjEwIiByeD0iOCIgZmlsbD0id2hpdGUiIHN0cm9rZT0iIzE1NUVFRiIgc3Ryb2tlLXdpZHRoPSIyIi8+PHJlY3QgeD0iMzAiIHk9IjQwIiB3aWR0aD0iODAiIGhlaWdodD0iOCIgcng9IjQiIGZpbGw9IiNFNUU3RUIiLz48cmVjdCB4PSIzMCIgeT0iNjAiIHdpZHRoPSIxNDAiIGhlaWdodD0iNDAiIHJ4PSI0IiBmaWxsPSIjRjNGNEY2Ii8+PHRleHQgeD0iNDAiIHk9Ijg1IiBmb250LWZhbWlseT0ic3lzdGVtLXVpIiBmb250LXNpemU9IjE2IiBmb250LXdlaWdodD0iNjAwIiBmaWxsPSIjMUYyOTM3Ij4yMDA8L3RleHQ+PHRleHQgeD0iNDAiIHk9Ijk1IiBmb250LWZhbWlseT0ic3lzdGVtLXVpIiBmb250LXNpemU9IjgiIGZpbGw9IiM2QjcyODAiPlBvc3RzPC90ZXh0PjxyZWN0IHg9IjE4MCIgeT0iNjAiIHdpZHRoPSI4MCIgaGVpZ2h0PSI0MCIgcng9IjQiIGZpbGw9IiNGM0Y0RjYiLz48cmVjdCB4PSIyNzAiIHk9IjYwIiB3aWR0aD0iODAiIGhlaWdodD0iNDAiIHJ4PSI0IiBmaWxsPSIjRjNGNEY2Ii8+PHBhdGggZD0iTTMwIDEzMEgzNzBNMzAgMTUwSDM3ME0zMCAxNzBIMzcwTTMwIDE5MEgzNzAiIHN0cm9rZT0iI0U1RTdFQiIgc3Ryb2tlLXdpZHRoPSIxIi8+PHBhdGggZD0iTTUwIDE2MEwxMDAgMTQwTDE1MCAxNTBMMjAwIDEzMEwyNTAgMTM1TDMwMCAxMjBMMzUwIDEyNSIgc3Ryb2tlPSIjMTU1RUVGIiBzdHJva2Utd2lkdGg9IjIiIGZpbGw9Im5vbmUiLz48L3N2Zz4=',\n\t\tslug: 'feature-prioritization-roadmaps-analytics',\n\t\tpublished_at: '2025-03-15T10:00:00Z',\n\t\tlabels: [\n\t\t\t{ name: 'New Feature', color: '#10B981' },\n\t\t\t{ name: 'Analytics', color: '#6366F1' },\n\t\t],\n\t\tstatus: 'published',\n\t},\n\t{\n\t\tid: 'changelog_2',\n\t\ttitle: 'Dark mode support and UI improvements',\n\t\texcerpt:\n\t\t\t'You asked for it, we delivered! Dark mode is now available across all pages.',\n\t\tdescription:\n\t\t\t'You asked for it, we delivered! Dark mode is now available across all pages.',\n\t\tcover_image:\n\t\t\t'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAwIiBoZWlnaHQ9IjI1MCIgdmlld0JveD0iMCAwIDQwMCAyNTAiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHJlY3Qgd2lkdGg9IjQwMCIgaGVpZ2h0PSIyNTAiIGZpbGw9IiMxRjI5MzciLz48cmVjdCB4PSIyMCIgeT0iMjAiIHdpZHRoPSIzNjAiIGhlaWdodD0iMjEwIiByeD0iOCIgZmlsbD0iIzM3NDE1MSIgc3Ryb2tlPSIjNEI1NTYzIiBzdHJva2Utd2lkdGg9IjEiLz48Y2lyY2xlIGN4PSIyMDAiIGN5PSIxMjUiIHI9IjQwIiBmaWxsPSIjRkJCRjI0Ii8+PHBhdGggZD0iTTIyMCAxMjVDMjIwIDEzNiAyMTEgMTQ1IDIwMCAxNDVDMTg5IDE0NSAxODAgMTM2IDE4MCAxMjVDMTgwIDExNCAxODkgMTA1IDIwMCAxMDVDMjExIDEwNSAyMjAgMTE0IDIyMCAxMjVaIiBmaWxsPSIjMUYyOTM3Ii8+PC9zdmc+',\n\t\tslug: 'dark-mode-ui-improvements',\n\t\tpublished_at: '2025-03-01T10:00:00Z',\n\t\tlabels: [{ name: 'Enhancement', color: '#8B5CF6' }],\n\t\tstatus: 'published',\n\t},\n\t{\n\t\tid: 'changelog_3',\n\t\ttitle: 'Performance improvements and bug fixes',\n\t\texcerpt:\n\t\t\t'This release includes major performance improvements and several bug fixes.',\n\t\tdescription:\n\t\t\t'This release includes major performance improvements and several bug fixes.',\n\t\tslug: 'performance-improvements-bug-fixes',\n\t\tpublished_at: '2025-02-15T10:00:00Z',\n\t\tlabels: [\n\t\t\t{ name: 'Bug Fix', color: '#EF4444' },\n\t\t\t{ name: 'Performance', color: '#F59E0B' },\n\t\t],\n\t\tstatus: 'published',\n\t},\n];\n\n// Mock conversations for development\nconst MOCK_CONVERSATIONS = [\n\t{\n\t\tid: 'conv_1',\n\t\tsubject: 'Question about pricing',\n\t\tstatus: 'open',\n\t\tlast_message_at: new Date(Date.now() - 49 * 60 * 1000).toISOString(),\n\t\tcreated_at: new Date(Date.now() - 2 * 24 * 60 * 60 * 1000).toISOString(),\n\t\tunread: 1,\n\t\tassigned_user: {\n\t\t\tid: 'user_1',\n\t\t\tname: 'Sarah',\n\t\t\tavatar: null,\n\t\t},\n\t},\n\t{\n\t\tid: 'conv_2',\n\t\tsubject: 'Feature request',\n\t\tstatus: 'open',\n\t\tlast_message_at: new Date(Date.now() - 6 * 24 * 60 * 60 * 1000).toISOString(),\n\t\tcreated_at: new Date(Date.now() - 10 * 24 * 60 * 60 * 1000).toISOString(),\n\t\tunread: 0,\n\t\tassigned_user: {\n\t\t\tid: 'user_2',\n\t\t\tname: 'Tom',\n\t\t\tavatar: null,\n\t\t},\n\t},\n];\n\n// Mock messages for development\nconst MOCK_MESSAGES = {\n\tconv_1: [\n\t\t{\n\t\t\tid: 'msg_1',\n\t\t\tcontent: \"Hi there! 👋 I'm Sarah. How can I help you today?\",\n\t\t\tsender_type: 'agent',\n\t\t\tsender_name: 'Sarah',\n\t\t\tsender_avatar: null,\n\t\t\tcreated_at: new Date(Date.now() - 50 * 60 * 1000).toISOString(),\n\t\t},\n\t\t{\n\t\t\tid: 'msg_2',\n\t\t\tcontent: 'Hi! I have a question about your enterprise pricing.',\n\t\t\tsender_type: 'customer',\n\t\t\tcreated_at: new Date(Date.now() - 49 * 60 * 1000).toISOString(),\n\t\t},\n\t],\n\tconv_2: [\n\t\t{\n\t\t\tid: 'msg_3',\n\t\t\tcontent: \"Hello! I'm Tom from the product team.\",\n\t\t\tsender_type: 'agent',\n\t\t\tsender_name: 'Tom',\n\t\t\tsender_avatar: null,\n\t\t\tcreated_at: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString(),\n\t\t},\n\t\t{\n\t\t\tid: 'msg_4',\n\t\t\tcontent: 'I would love to see a dark mode feature!',\n\t\t\tsender_type: 'customer',\n\t\t\tcreated_at: new Date(Date.now() - 6 * 24 * 60 * 60 * 1000 - 30 * 60 * 1000).toISOString(),\n\t\t},\n\t\t{\n\t\t\tid: 'msg_5',\n\t\t\tcontent: \"Great suggestion! That feature will be available next week. I'll let you know when it's ready.\",\n\t\t\tsender_type: 'agent',\n\t\t\tsender_name: 'Tom',\n\t\t\tsender_avatar: null,\n\t\t\tcreated_at: new Date(Date.now() - 6 * 24 * 60 * 60 * 1000).toISOString(),\n\t\t},\n\t],\n};\n\n// Mock help collections for development\nconst MOCK_HELP_COLLECTIONS = [\n\t{\n\t\tid: 'collection_1',\n\t\ttitle: 'Product Overview',\n\t\tdescription: 'See how your AI-first customer service solution works.',\n\t\tarticleCount: 24,\n\t\ticon: 'ph-book-open',\n\t\turl: '#',\n\t},\n\t{\n\t\tid: 'collection_2',\n\t\ttitle: 'Getting Started',\n\t\tdescription: 'Everything you need to know to get started with Product7.',\n\t\tarticleCount: 30,\n\t\ticon: 'ph-rocket',\n\t\turl: '#',\n\t},\n\t{\n\t\tid: 'collection_3',\n\t\ttitle: 'AI Agent',\n\t\tdescription: 'Resolving customer questions instantly and accurately—from live chat to email.',\n\t\tarticleCount: 82,\n\t\ticon: 'ph-robot',\n\t\turl: '#',\n\t},\n\t{\n\t\tid: 'collection_4',\n\t\ttitle: 'Channels',\n\t\tdescription: 'Enabling the channels you use to communicate with customers, all from the Inbox.',\n\t\tarticleCount: 45,\n\t\ticon: 'ph-chat-circle',\n\t\turl: '#',\n\t},\n\t{\n\t\tid: 'collection_5',\n\t\ttitle: 'Billing & Payments',\n\t\tdescription: 'Manage your subscription, invoices, and payment methods.',\n\t\tarticleCount: 12,\n\t\ticon: 'ph-credit-card',\n\t\turl: '#',\n\t},\n];\n\n// Mock surveys for development\nconst MOCK_SURVEYS = [\n\t{\n\t\tid: 'mock_nps_survey',\n\t\ttype: 'nps',\n\t\ttitle: 'How likely are you to recommend us?',\n\t\tdescription: 'Your feedback helps us improve',\n\t\tlow_label: 'Not likely',\n\t\thigh_label: 'Very likely',\n\t\ttrigger: 'manual',\n\t\tstatus: 'active',\n\t},\n\t{\n\t\tid: 'mock_csat_survey',\n\t\ttype: 'csat',\n\t\ttitle: 'How satisfied are you?',\n\t\tdescription: 'Rate your experience with our product',\n\t\ttrigger: 'manual',\n\t\tstatus: 'active',\n\t},\n\t{\n\t\tid: 'mock_ces_survey',\n\t\ttype: 'ces',\n\t\ttitle: 'How easy was it?',\n\t\tdescription: 'Rate the ease of completing your task',\n\t\tlow_label: 'Very difficult',\n\t\thigh_label: 'Very easy',\n\t\ttrigger: 'manual',\n\t\tstatus: 'active',\n\t},\n];\n\n// Environment URLs\nconst ENV_URLS = {\n\tproduction: {\n\t\tbase: 'https://api.product7.io/api/v1',\n\t\twithWorkspace: (workspace) => `https://${workspace}.api.product7.io/api/v1`,\n\t},\n\tstaging: {\n\t\tbase: 'https://staging.api.product7.io/api/v1',\n\t\twithWorkspace: (workspace) =>\n\t\t\t`https://${workspace}.staging.api.product7.io/api/v1`,\n\t},\n};\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\t\tthis.mock = config.mock || false;\n\t\tthis.env = config.env || 'production';\n\n\t\tif (config.apiUrl) {\n\t\t\tthis.baseURL = config.apiUrl;\n\t\t} else {\n\t\t\tconst envConfig = ENV_URLS[this.env] || ENV_URLS.production;\n\t\t\tthis.baseURL = this.workspace\n\t\t\t\t? envConfig.withWorkspace(this.workspace)\n\t\t\t\t: envConfig.base;\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\t// Mock mode - return fake session\n\t\tif (this.mock) {\n\t\t\tthis.sessionToken = 'mock_session_' + Date.now();\n\t\t\tthis.sessionExpiry = new Date(Date.now() + 3600 * 1000);\n\t\t\tthis._storeSession();\n\t\t\treturn {\n\t\t\t\tsessionToken: this.sessionToken,\n\t\t\t\tconfig: MOCK_CONFIG,\n\t\t\t\texpiresIn: 3600,\n\t\t\t};\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\t// Mock mode - simulate success\n\t\tif (this.mock) {\n\t\t\tawait new Promise((resolve) => setTimeout(resolve, 500));\n\t\t\treturn {\n\t\t\t\tsuccess: true,\n\t\t\t\tdata: {\n\t\t\t\t\tid: 'mock_post_' + Date.now(),\n\t\t\t\t\ttitle: feedbackData.title,\n\t\t\t\t\tcontent: feedbackData.content,\n\t\t\t\t},\n\t\t\t\tmessage: 'Feedback submitted successfully!',\n\t\t\t};\n\t\t}\n\n\t\tconst payload = {\n\t\t\tboard:\n\t\t\t\tfeedbackData.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\t/**\n\t * Get active surveys for the current user/context\n\t * @param {Object} context - Optional context overrides for targeting\n\t * @param {string} context.url - Override current URL\n\t * @param {Object} context.userProperties - Additional user properties\n\t * @returns {Promise<Array>} Array of active surveys matching targeting rules\n\t */\n\tasync getActiveSurveys(context = {}) {\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\t// Mock mode - return mock surveys\n\t\tif (this.mock) {\n\t\t\tawait new Promise((resolve) => setTimeout(resolve, 200));\n\t\t\treturn {\n\t\t\t\tsuccess: true,\n\t\t\t\tdata: MOCK_SURVEYS,\n\t\t\t};\n\t\t}\n\n\t\ttry {\n\t\t\tconst queryParams = new URLSearchParams();\n\n\t\t\t// Auto-detect current URL or use provided override\n\t\t\tconst currentUrl =\n\t\t\t\tcontext.url ||\n\t\t\t\t(typeof window !== 'undefined' ? window.location.href : '');\n\t\t\tif (currentUrl) {\n\t\t\t\tqueryParams.append('url', currentUrl);\n\t\t\t}\n\n\t\t\t// Auto-detect device info\n\t\t\tconst deviceInfo = this._getDeviceInfo();\n\t\t\tif (deviceInfo.device) queryParams.append('device', deviceInfo.device);\n\t\t\tif (deviceInfo.browser) queryParams.append('browser', deviceInfo.browser);\n\t\t\tif (deviceInfo.os) queryParams.append('os', deviceInfo.os);\n\n\t\t\t// Add user properties if provided\n\t\t\tif (context.userProperties) {\n\t\t\t\tqueryParams.append(\n\t\t\t\t\t'user_properties',\n\t\t\t\t\tJSON.stringify(context.userProperties)\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst endpoint = `/widget/surveys/active${queryParams.toString() ? '?' + queryParams.toString() : ''}`;\n\n\t\t\tconst response = await this._makeRequest(endpoint, {\n\t\t\t\tmethod: 'GET',\n\t\t\t\theaders: {\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.getActiveSurveys(context);\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 get active surveys: ${error.message}`,\n\t\t\t\terror.response\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Auto-detect device, browser, and OS info\n\t * @returns {Object} Device info object\n\t */\n\t_getDeviceInfo() {\n\t\tif (typeof navigator === 'undefined') {\n\t\t\treturn { device: null, browser: null, os: null };\n\t\t}\n\n\t\tconst ua = navigator.userAgent;\n\n\t\t// Detect device type\n\t\tlet device = 'desktop';\n\t\tif (/Mobi|Android/i.test(ua)) {\n\t\t\tdevice = /Tablet|iPad/i.test(ua) ? 'tablet' : 'mobile';\n\t\t}\n\n\t\t// Detect browser\n\t\tlet browser = 'unknown';\n\t\tif (ua.includes('Firefox')) browser = 'firefox';\n\t\telse if (ua.includes('Edg')) browser = 'edge';\n\t\telse if (ua.includes('Chrome')) browser = 'chrome';\n\t\telse if (ua.includes('Safari')) browser = 'safari';\n\t\telse if (ua.includes('Opera') || ua.includes('OPR')) browser = 'opera';\n\n\t\t// Detect OS\n\t\tlet os = 'unknown';\n\t\tif (ua.includes('Windows')) os = 'windows';\n\t\telse if (ua.includes('Mac')) os = 'macos';\n\t\telse if (ua.includes('Linux')) os = 'linux';\n\t\telse if (ua.includes('Android')) os = 'android';\n\t\telse if (ua.includes('iPhone') || ua.includes('iPad')) os = 'ios';\n\n\t\treturn { device, browser, os };\n\t}\n\n\t/**\n\t * Submit a survey response\n\t * @param {string} surveyId - The survey ID\n\t * @param {Object} responseData - The survey response data\n\t * @param {number|string} responseData.rating - The rating/score value\n\t * @param {string} responseData.feedback - Optional text feedback\n\t * @param {Object} responseData.answers - For custom surveys, key-value pairs\n\t * @returns {Promise<Object>} Submission result\n\t */\n\tasync submitSurveyResponse(surveyId, responseData) {\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\tif (!surveyId) {\n\t\t\tthrow new APIError(400, 'Survey ID is required');\n\t\t}\n\n\t\t// Mock mode - simulate success\n\t\tif (this.mock) {\n\t\t\tawait new Promise((resolve) => setTimeout(resolve, 300));\n\t\t\treturn {\n\t\t\t\tsuccess: true,\n\t\t\t\tdata: {\n\t\t\t\t\tid: 'mock_response_' + Date.now(),\n\t\t\t\t\tsurvey_id: surveyId,\n\t\t\t\t\t...responseData,\n\t\t\t\t},\n\t\t\t\tmessage: 'Survey response submitted successfully!',\n\t\t\t};\n\t\t}\n\n\t\tconst payload = {\n\t\t\trating: responseData.rating,\n\t\t\tfeedback: responseData.feedback || '',\n\t\t\tanswers: responseData.answers || {},\n\t\t};\n\n\t\ttry {\n\t\t\tconst response = await this._makeRequest(\n\t\t\t\t`/widget/surveys/${surveyId}/responses`,\n\t\t\t\t{\n\t\t\t\t\tmethod: 'POST',\n\t\t\t\t\tbody: JSON.stringify(payload),\n\t\t\t\t\theaders: {\n\t\t\t\t\t\t'Content-Type': 'application/json',\n\t\t\t\t\t\tAuthorization: `Bearer ${this.sessionToken}`,\n\t\t\t\t\t},\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.submitSurveyResponse(surveyId, responseData);\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 survey response: ${error.message}`,\n\t\t\t\terror.response\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Dismiss a survey (mark as seen but not completed)\n\t * @param {string} surveyId - The survey ID to dismiss\n\t * @returns {Promise<Object>} Dismissal result\n\t */\n\tasync dismissSurvey(surveyId) {\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\tif (!surveyId) {\n\t\t\tthrow new APIError(400, 'Survey ID is required');\n\t\t}\n\n\t\t// Mock mode - simulate success\n\t\tif (this.mock) {\n\t\t\tawait new Promise((resolve) => setTimeout(resolve, 100));\n\t\t\treturn {\n\t\t\t\tsuccess: true,\n\t\t\t\tmessage: 'Survey dismissed successfully',\n\t\t\t};\n\t\t}\n\n\t\ttry {\n\t\t\tconst response = await this._makeRequest(\n\t\t\t\t`/widget/surveys/${surveyId}/dismiss`,\n\t\t\t\t{\n\t\t\t\t\tmethod: 'POST',\n\t\t\t\t\theaders: {\n\t\t\t\t\t\tAuthorization: `Bearer ${this.sessionToken}`,\n\t\t\t\t\t},\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.dismissSurvey(surveyId);\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 dismiss survey: ${error.message}`,\n\t\t\t\terror.response\n\t\t\t);\n\t\t}\n\t}\n\n\t// ==========================================\n\t// MESSENGER / CHAT ENDPOINTS\n\t// ==========================================\n\n\t/**\n\t * Get messenger settings\n\t * @returns {Promise<Object>} Messenger settings\n\t */\n\tasync getMessengerSettings() {\n\t\tif (!this.isSessionValid()) {\n\t\t\tawait this.init();\n\t\t}\n\n\t\tif (this.mock) {\n\t\t\treturn {\n\t\t\t\tstatus: true,\n\t\t\t\tdata: {\n\t\t\t\t\tenabled: true,\n\t\t\t\t\tgreeting_message: 'Hi there! How can we help you today?',\n\t\t\t\t\tteam_name: 'Support Team',\n\t\t\t\t\tresponse_time: 'Usually replies within a few minutes',\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\n\t\treturn this._makeRequest('/widget/messenger/settings', {\n\t\t\tmethod: 'GET',\n\t\t\theaders: { Authorization: `Bearer ${this.sessionToken}` },\n\t\t});\n\t}\n\n\t/**\n\t * Check if agents are online\n\t * @returns {Promise<Object>} Agent availability status\n\t */\n\tasync checkAgentsOnline() {\n\t\tif (!this.isSessionValid()) {\n\t\t\tawait this.init();\n\t\t}\n\n\t\tif (this.mock) {\n\t\t\treturn {\n\t\t\t\tstatus: true,\n\t\t\t\tdata: {\n\t\t\t\t\tagents_online: true,\n\t\t\t\t\tonline_count: 2,\n\t\t\t\t\tresponse_time: 'Usually replies within a few minutes',\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\n\t\treturn this._makeRequest('/widget/messenger/agents/online', {\n\t\t\tmethod: 'GET',\n\t\t\theaders: { Authorization: `Bearer ${this.sessionToken}` },\n\t\t});\n\t}\n\n\t/**\n\t * Get all conversations for the current contact\n\t * @param {Object} options - Query options\n\t * @param {number} options.page - Page number\n\t * @param {number} options.limit - Items per page\n\t * @returns {Promise<Object>} Conversations list\n\t */\n\tasync getConversations(options = {}) {\n\t\tif (!this.isSessionValid()) {\n\t\t\tawait this.init();\n\t\t}\n\n\t\tif (this.mock) {\n\t\t\tawait new Promise((resolve) => setTimeout(resolve, 300));\n\t\t\treturn {\n\t\t\t\tstatus: true,\n\t\t\t\tdata: MOCK_CONVERSATIONS,\n\t\t\t\tmeta: { total: MOCK_CONVERSATIONS.length, page: 1, limit: 20 },\n\t\t\t};\n\t\t}\n\n\t\tconst params = new URLSearchParams();\n\t\tif (options.page) params.append('page', options.page);\n\t\tif (options.limit) params.append('limit', options.limit);\n\n\t\tconst endpoint = `/widget/messenger/conversations${params.toString() ? '?' + params.toString() : ''}`;\n\t\treturn this._makeRequest(endpoint, {\n\t\t\tmethod: 'GET',\n\t\t\theaders: { Authorization: `Bearer ${this.sessionToken}` },\n\t\t});\n\t}\n\n\t/**\n\t * Get a single conversation with messages\n\t * @param {string} conversationId - Conversation ID\n\t * @returns {Promise<Object>} Conversation with messages\n\t */\n\tasync getConversation(conversationId) {\n\t\tif (!this.isSessionValid()) {\n\t\t\tawait this.init();\n\t\t}\n\n\t\tif (this.mock) {\n\t\t\tawait new Promise((resolve) => setTimeout(resolve, 200));\n\t\t\tconst conv = MOCK_CONVERSATIONS.find((c) => c.id === conversationId);\n\t\t\treturn {\n\t\t\t\tstatus: true,\n\t\t\t\tdata: {\n\t\t\t\t\t...conv,\n\t\t\t\t\tmessages: MOCK_MESSAGES[conversationId] || [],\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\n\t\treturn this._makeRequest(`/widget/messenger/conversations/${conversationId}`, {\n\t\t\tmethod: 'GET',\n\t\t\theaders: { Authorization: `Bearer ${this.sessionToken}` },\n\t\t});\n\t}\n\n\t/**\n\t * Get messages for a conversation\n\t * @param {string} conversationId - Conversation ID\n\t * @param {Object} options - Query options\n\t * @returns {Promise<Object>} Messages list\n\t */\n\tasync getMessages(conversationId, options = {}) {\n\t\tif (!this.isSessionValid()) {\n\t\t\tawait this.init();\n\t\t}\n\n\t\tif (this.mock) {\n\t\t\tawait new Promise((resolve) => setTimeout(resolve, 200));\n\t\t\treturn {\n\t\t\t\tstatus: true,\n\t\t\t\tdata: MOCK_MESSAGES[conversationId] || [],\n\t\t\t};\n\t\t}\n\n\t\tconst params = new URLSearchParams();\n\t\tif (options.page) params.append('page', options.page);\n\t\tif (options.limit) params.append('limit', options.limit);\n\n\t\tconst endpoint = `/widget/messenger/conversations/${conversationId}/messages${params.toString() ? '?' + params.toString() : ''}`;\n\t\treturn this._makeRequest(endpoint, {\n\t\t\tmethod: 'GET',\n\t\t\theaders: { Authorization: `Bearer ${this.sessionToken}` },\n\t\t});\n\t}\n\n\t/**\n\t * Start a new conversation\n\t * @param {Object} data - Conversation data\n\t * @param {string} data.message - Initial message content\n\t * @param {string} data.subject - Optional subject\n\t * @returns {Promise<Object>} Created conversation\n\t */\n\tasync startConversation(data) {\n\t\tif (!this.isSessionValid()) {\n\t\t\tawait this.init();\n\t\t}\n\n\t\tif (this.mock) {\n\t\t\tawait new Promise((resolve) => setTimeout(resolve, 300));\n\t\t\tconst newConv = {\n\t\t\t\tid: 'conv_' + Date.now(),\n\t\t\t\tsubject: data.subject || 'New conversation',\n\t\t\t\tstatus: 'open',\n\t\t\t\tlast_message_at: new Date().toISOString(),\n\t\t\t\tcreated_at: new Date().toISOString(),\n\t\t\t\tmessages: [\n\t\t\t\t\t{\n\t\t\t\t\t\tid: 'msg_' + Date.now(),\n\t\t\t\t\t\tcontent: data.message,\n\t\t\t\t\t\tsender_type: 'customer',\n\t\t\t\t\t\tcreated_at: new Date().toISOString(),\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t};\n\t\t\tMOCK_CONVERSATIONS.unshift(newConv);\n\t\t\tMOCK_MESSAGES[newConv.id] = newConv.messages;\n\t\t\treturn { status: true, data: newConv };\n\t\t}\n\n\t\treturn this._makeRequest('/widget/messenger/conversations', {\n\t\t\tmethod: 'POST',\n\t\t\theaders: {\n\t\t\t\t'Content-Type': 'application/json',\n\t\t\t\tAuthorization: `Bearer ${this.sessionToken}`,\n\t\t\t},\n\t\t\tbody: JSON.stringify({\n\t\t\t\tmessage: data.message,\n\t\t\t\tsubject: data.subject || '',\n\t\t\t}),\n\t\t});\n\t}\n\n\t/**\n\t * Send a message in a conversation\n\t * @param {string} conversationId - Conversation ID\n\t * @param {Object} data - Message data\n\t * @param {string} data.content - Message content\n\t * @returns {Promise<Object>} Sent message\n\t */\n\tasync sendMessage(conversationId, data) {\n\t\tif (!this.isSessionValid()) {\n\t\t\tawait this.init();\n\t\t}\n\n\t\tif (this.mock) {\n\t\t\tawait new Promise((resolve) => setTimeout(resolve, 200));\n\t\t\tconst newMessage = {\n\t\t\t\tid: 'msg_' + Date.now(),\n\t\t\t\tcontent: data.content,\n\t\t\t\tsender_type: 'customer',\n\t\t\t\tcreated_at: new Date().toISOString(),\n\t\t\t};\n\t\t\tif (!MOCK_MESSAGES[conversationId]) {\n\t\t\t\tMOCK_MESSAGES[conversationId] = [];\n\t\t\t}\n\t\t\tMOCK_MESSAGES[conversationId].push(newMessage);\n\t\t\treturn { status: true, data: newMessage };\n\t\t}\n\n\t\treturn this._makeRequest(`/widget/messenger/conversations/${conversationId}/messages`, {\n\t\t\tmethod: 'POST',\n\t\t\theaders: {\n\t\t\t\t'Content-Type': 'application/json',\n\t\t\t\tAuthorization: `Bearer ${this.sessionToken}`,\n\t\t\t},\n\t\t\tbody: JSON.stringify({ content: data.content }),\n\t\t});\n\t}\n\n\t/**\n\t * Send typing indicator\n\t * @param {string} conversationId - Conversation ID\n\t * @param {boolean} isTyping - Whether user is typing\n\t * @returns {Promise<Object>} Response\n\t */\n\tasync sendTypingIndicator(conversationId, isTyping) {\n\t\tif (!this.isSessionValid()) {\n\t\t\tawait this.init();\n\t\t}\n\n\t\tif (this.mock) {\n\t\t\treturn { status: true };\n\t\t}\n\n\t\treturn this._makeRequest(`/widget/messenger/conversations/${conversationId}/typing`, {\n\t\t\tmethod: 'POST',\n\t\t\theaders: {\n\t\t\t\t'Content-Type': 'application/json',\n\t\t\t\tAuthorization: `Bearer ${this.sessionToken}`,\n\t\t\t},\n\t\t\tbody: JSON.stringify({ is_typing: isTyping }),\n\t\t});\n\t}\n\n\t/**\n\t * Mark conversation as read\n\t * @param {string} conversationId - Conversation ID\n\t * @returns {Promise<Object>} Response\n\t */\n\tasync markConversationAsRead(conversationId) {\n\t\tif (!this.isSessionValid()) {\n\t\t\tawait this.init();\n\t\t}\n\n\t\tif (this.mock) {\n\t\t\treturn { status: true };\n\t\t}\n\n\t\treturn this._makeRequest(`/widget/messenger/conversations/${conversationId}/read`, {\n\t\t\tmethod: 'POST',\n\t\t\theaders: { Authorization: `Bearer ${this.sessionToken}` },\n\t\t});\n\t}\n\n\t/**\n\t * Get unread count\n\t * @returns {Promise<Object>} Unread count data\n\t */\n\tasync getUnreadCount() {\n\t\tif (!this.isSessionValid()) {\n\t\t\tawait this.init();\n\t\t}\n\n\t\tif (this.mock) {\n\t\t\tconst count = MOCK_CONVERSATIONS.reduce((sum, c) => sum + (c.unread || 0), 0);\n\t\t\treturn {\n\t\t\t\tstatus: true,\n\t\t\t\tdata: { unread_count: count, unread_conversations: count > 0 ? 1 : 0 },\n\t\t\t};\n\t\t}\n\n\t\treturn this._makeRequest('/widget/messenger/unread', {\n\t\t\tmethod: 'GET',\n\t\t\theaders: { Authorization: `Bearer ${this.sessionToken}` },\n\t\t});\n\t}\n\n\t/**\n\t * Submit conversation rating\n\t * @param {string} conversationId - Conversation ID\n\t * @param {Object} data - Rating data\n\t * @param {number} data.rating - Rating (1-5 or thumbs up/down)\n\t * @param {string} data.comment - Optional comment\n\t * @returns {Promise<Object>} Response\n\t */\n\tasync submitRating(conversationId, data) {\n\t\tif (!this.isSessionValid()) {\n\t\t\tawait this.init();\n\t\t}\n\n\t\tif (this.mock) {\n\t\t\treturn { status: true, message: 'Thank you for your feedback!' };\n\t\t}\n\n\t\treturn this._makeRequest(`/widget/messenger/conversations/${conversationId}/rate`, {\n\t\t\tmethod: 'POST',\n\t\t\theaders: {\n\t\t\t\t'Content-Type': 'application/json',\n\t\t\t\tAuthorization: `Bearer ${this.sessionToken}`,\n\t\t\t},\n\t\t\tbody: JSON.stringify({\n\t\t\t\trating: data.rating,\n\t\t\t\tcomment: data.comment || '',\n\t\t\t}),\n\t\t});\n\t}\n\n\t/**\n\t * Identify contact (for logged-in users)\n\t * @param {Object} data - Contact data\n\t * @param {string} data.email - Email address\n\t * @param {string} data.name - Name\n\t * @returns {Promise<Object>} Response\n\t */\n\tasync identifyContact(data) {\n\t\tif (!this.isSessionValid()) {\n\t\t\tawait this.init();\n\t\t}\n\n\t\tif (this.mock) {\n\t\t\treturn { status: true, message: 'Contact identified' };\n\t\t}\n\n\t\treturn this._makeRequest('/widget/messenger/identify', {\n\t\t\tmethod: 'POST',\n\t\t\theaders: {\n\t\t\t\t'Content-Type': 'application/json',\n\t\t\t\tAuthorization: `Bearer ${this.sessionToken}`,\n\t\t\t},\n\t\t\tbody: JSON.stringify(data),\n\t\t});\n\t}\n\n\t// ==========================================\n\t// HELP ARTICLES ENDPOINTS\n\t// ==========================================\n\n\t/**\n\t * Get help collections\n\t * @param {Object} options - Query options\n\t * @returns {Promise<Object>} Collections list\n\t */\n\tasync getHelpCollections(options = {}) {\n\t\tif (!this.isSessionValid()) {\n\t\t\tawait this.init();\n\t\t}\n\n\t\tif (this.mock) {\n\t\t\tawait new Promise((resolve) => setTimeout(resolve, 200));\n\t\t\treturn { status: true, data: MOCK_HELP_COLLECTIONS };\n\t\t}\n\n\t\tconst params = new URLSearchParams();\n\t\tif (options.limit) params.append('limit', options.limit);\n\n\t\tconst endpoint = `/widget/help/collections${params.toString() ? '?' + params.toString() : ''}`;\n\t\treturn this._makeRequest(endpoint, {\n\t\t\tmethod: 'GET',\n\t\t\theaders: { Authorization: `Bearer ${this.sessionToken}` },\n\t\t});\n\t}\n\n\t/**\n\t * Search help articles\n\t * @param {string} query - Search query\n\t * @param {Object} options - Query options\n\t * @returns {Promise<Object>} Search results\n\t */\n\tasync searchHelpArticles(query, options = {}) {\n\t\tif (!this.isSessionValid()) {\n\t\t\tawait this.init();\n\t\t}\n\n\t\tif (this.mock) {\n\t\t\tawait new Promise((resolve) => setTimeout(resolve, 200));\n\t\t\tconst filtered = MOCK_HELP_COLLECTIONS.filter(\n\t\t\t\t(c) =>\n\t\t\t\t\tc.title.toLowerCase().includes(query.toLowerCase()) ||\n\t\t\t\t\tc.description.toLowerCase().includes(query.toLowerCase())\n\t\t\t);\n\t\t\treturn { status: true, data: filtered };\n\t\t}\n\n\t\tconst params = new URLSearchParams({ q: query });\n\t\tif (options.limit) params.append('limit', options.limit);\n\n\t\treturn this._makeRequest(`/widget/help/search?${params.toString()}`, {\n\t\t\tmethod: 'GET',\n\t\t\theaders: { Authorization: `Bearer ${this.sessionToken}` },\n\t\t});\n\t}\n\n\t// ==========================================\n\t// CHANGELOG ENDPOINTS\n\t// ==========================================\n\n\t/**\n\t * Get published changelogs\n\t * @param {Object} options - Optional query parameters\n\t * @param {number} options.limit - Number of changelogs to fetch\n\t * @param {number} options.offset - Offset for pagination\n\t * @returns {Promise<Object>} Changelogs response\n\t */\n\tasync getChangelogs(options = {}) {\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\t// Mock mode - return mock changelogs\n\t\tif (this.mock) {\n\t\t\tawait new Promise((resolve) => setTimeout(resolve, 300));\n\t\t\treturn {\n\t\t\t\tsuccess: true,\n\t\t\t\tdata: MOCK_CHANGELOGS,\n\t\t\t};\n\t\t}\n\n\t\ttry {\n\t\t\tconst queryParams = new URLSearchParams();\n\t\t\tif (options.limit) queryParams.append('limit', options.limit);\n\t\t\tif (options.offset) queryParams.append('offset', options.offset);\n\n\t\t\tconst endpoint = `/widget/changelogs${queryParams.toString() ? '?' + queryParams.toString() : ''}`;\n\n\t\t\tconst response = await this._makeRequest(endpoint, {\n\t\t\t\tmethod: 'GET',\n\t\t\t\theaders: {\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.getChangelogs(options);\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 get changelogs: ${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(\n\t\t\t\t'feedbackSDK_userContext',\n\t\t\t\tJSON.stringify(userContext)\n\t\t\t);\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 =\n\t\t\t\t\t\tresponseData.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}\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\tstatic STORAGE_KEY = 'feedback_submitted';\n\tstatic DEFAULT_COOLDOWN_DAYS = 30; // Don't show for 30 days after submission\n\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\tboardId: this.sdk.config.boardId,\n\t\t\tdisplayMode: options.displayMode || 'panel',\n\t\t\tsize: options.size || 'medium',\n\t\t\tprimaryColor: options.primaryColor || '#21244A',\n\t\t\tbackgroundColor: options.backgroundColor || '#ffffff',\n\t\t\ttextColor: options.textColor || '#1F2937',\n\t\t\tautoShow: false,\n\t\t\tshowBackdrop: true,\n\t\t\tcustomStyles: {},\n\t\t\tsuppressAfterSubmission: true, // Don't show widget again after submission\n\t\t\tsuppressionDays: BaseWidget.DEFAULT_COOLDOWN_DAYS,\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\tisLoading: 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\t// Check if feedback was recently submitted and should be suppressed\n\t\tif (this.options.suppressAfterSubmission && this._hasRecentlySubmitted()) {\n\t\t\tthis.sdk.eventBus.emit('widget:suppressed', {\n\t\t\t\twidget: this,\n\t\t\t\treason: 'recently_submitted'\n\t\t\t});\n\t\t\treturn this;\n\t\t}\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\n\t\tif (this.options.displayMode === 'modal') {\n\t\t\tthis._showLoadingModal();\n\t\t\t// Simulate loading delay then show form\n\t\t\tsetTimeout(() => {\n\t\t\t\tthis._hideLoadingModal();\n\t\t\t\tthis._renderPanel();\n\t\t\t\trequestAnimationFrame(() => {\n\t\t\t\t\tif (this.panelElement) {\n\t\t\t\t\t\tthis.panelElement.classList.add('open');\n\t\t\t\t\t}\n\t\t\t\t\tif (this.backdropElement) {\n\t\t\t\t\t\tthis.backdropElement.classList.add('show');\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}, 600);\n\t\t} else {\n\t\t\tthis._renderPanel();\n\t\t\trequestAnimationFrame(() => {\n\t\t\t\tif (this.panelElement) {\n\t\t\t\t\tthis.panelElement.classList.add('open');\n\t\t\t\t}\n\t\t\t\tif (this.backdropElement) {\n\t\t\t\t\tthis.backdropElement.classList.add('show');\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\n\t_showLoadingModal() {\n\t\tthis.state.isLoading = true;\n\n\t\t// Create backdrop\n\t\tthis.backdropElement = document.createElement('div');\n\t\tthis.backdropElement.className = 'feedback-panel-backdrop';\n\t\tdocument.body.appendChild(this.backdropElement);\n\n\t\t// Create loading modal\n\t\tthis.loadingElement = document.createElement('div');\n\t\tthis.loadingElement.className = `feedback-loading-modal theme-${this.options.theme}`;\n\t\tthis.loadingElement.innerHTML = `\n\t\t\t<div class=\"feedback-loading-spinner\"></div>\n\t\t`;\n\t\tdocument.body.appendChild(this.loadingElement);\n\n\t\trequestAnimationFrame(() => {\n\t\t\tthis.backdropElement.classList.add('show');\n\t\t\tthis.loadingElement.classList.add('show');\n\t\t});\n\t}\n\n\t_hideLoadingModal() {\n\t\tthis.state.isLoading = false;\n\t\tif (this.loadingElement) {\n\t\t\tthis.loadingElement.remove();\n\t\t\tthis.loadingElement = null;\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\t// Track that feedback was submitted\n\t\t\tthis._trackSubmission();\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/**\n\t * Track that feedback was submitted to localStorage\n\t */\n\t_trackSubmission() {\n\t\ttry {\n\t\t\tconst workspace = this.sdk.config.workspace;\n\t\t\tconst storageKey = `${BaseWidget.STORAGE_KEY}_${workspace}`;\n\t\t\tconst data = {\n\t\t\t\tsubmittedAt: Date.now(),\n\t\t\t\tboardId: this.options.boardId,\n\t\t\t};\n\t\t\tlocalStorage.setItem(storageKey, JSON.stringify(data));\n\t\t} catch (e) {\n\t\t\t// localStorage may not be available\n\t\t\tconsole.warn('Failed to track feedback submission:', e);\n\t\t}\n\t}\n\n\t/**\n\t * Check if feedback was recently submitted (within cooldown period)\n\t * Uses backend tracking (preferred) with localStorage as fallback\n\t * @returns {boolean} true if feedback was submitted within the cooldown period\n\t */\n\t_hasRecentlySubmitted() {\n\t\tconst cooldownMs = this.options.suppressionDays * 24 * 60 * 60 * 1000;\n\t\tconst now = Date.now();\n\n\t\t// Check backend tracking first (from init response)\n\t\tif (this.sdk.config.last_feedback_at) {\n\t\t\ttry {\n\t\t\t\tconst backendTimestamp = new Date(this.sdk.config.last_feedback_at).getTime();\n\t\t\t\tif ((now - backendTimestamp) < cooldownMs) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t} catch (e) {\n\t\t\t\t// Invalid date format, continue to localStorage check\n\t\t\t}\n\t\t}\n\n\t\t// Fallback to localStorage\n\t\ttry {\n\t\t\tconst workspace = this.sdk.config.workspace;\n\t\t\tconst storageKey = `${BaseWidget.STORAGE_KEY}_${workspace}`;\n\t\t\tconst stored = localStorage.getItem(storageKey);\n\n\t\t\tif (!stored) return false;\n\n\t\t\tconst data = JSON.parse(stored);\n\t\t\tconst submittedAt = data.submittedAt;\n\n\t\t\treturn (now - submittedAt) < cooldownMs;\n\t\t} catch (e) {\n\t\t\t// localStorage may not be available or data is corrupted\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Clear the submission tracking (allow showing the widget again)\n\t */\n\tclearSubmissionTracking() {\n\t\ttry {\n\t\t\tconst workspace = this.sdk.config.workspace;\n\t\t\tconst storageKey = `${BaseWidget.STORAGE_KEY}_${workspace}`;\n\t\t\tlocalStorage.removeItem(storageKey);\n\t\t} catch (e) {\n\t\t\tconsole.warn('Failed to clear submission tracking:', e);\n\t\t}\n\t}\n\n\t/**\n\t * Check if the widget should be shown based on submission history\n\t * @returns {boolean} true if the widget should be shown\n\t */\n\tshouldShow() {\n\t\tif (!this.options.suppressAfterSubmission) return true;\n\t\treturn !this._hasRecentlySubmitted();\n\t}\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 && !this.backdropElement) {\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\tconst modeClass =\n\t\t\tthis.options.displayMode === 'modal'\n\t\t\t\t? 'feedback-modal'\n\t\t\t\t: 'feedback-panel';\n\t\tconst sizeClass = `size-${this.options.size}`;\n\t\tthis.panelElement = document.createElement('div');\n\t\tthis.panelElement.className = `${modeClass} ${sizeClass}`;\n\t\tthis.panelElement.style.setProperty(\n\t\t\t'--primary-color',\n\t\t\tthis.options.primaryColor\n\t\t);\n\t\tthis.panelElement.style.setProperty(\n\t\t\t'--bg-color',\n\t\t\tthis.options.backgroundColor\n\t\t);\n\t\tthis.panelElement.style.setProperty('--text-color', this.options.textColor);\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\">×</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\">×</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}\n","import { BaseWidget } from './BaseWidget.js';\n\nexport class ButtonWidget extends BaseWidget {\n\tconstructor(options) {\n\t\tsuper({ ...options, type: 'button' });\n\t\tthis.isMinimized = false;\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 class=\"feedback-icon\" width=\"20\" height=\"20\" viewBox=\"0 0 256 256\" fill=\"currentColor\">\n <path d=\"M216,80H184V48a16,16,0,0,0-16-16H40A16,16,0,0,0,24,48V176a8,8,0,0,0,13,6.22L72,154V184a16,16,0,0,0,16,16h93.59L219,230.22a8,8,0,0,0,5,1.78,8,8,0,0,0,8-8V96A16,16,0,0,0,216,80ZM66.55,137.78,40,159.25V48H168v88H71.58A8,8,0,0,0,66.55,137.78ZM216,207.25l-26.55-21.47a8,8,0,0,0-5-1.78H88V152h80a16,16,0,0,0,16-16V96h32Z\"/>\n </svg>\n <span class=\"feedback-text\">Feedback</span>\n \n <div class=\"feedback-minimize-icon\">\n <svg viewBox=\"0 0 256 256\">\n <path d=\"M213.66,53.66,163.31,104H192a8,8,0,0,1,0,16H144a8,8,0,0,1-8-8V64a8,8,0,0,1,16,0V92.69l50.34-50.35a8,8,0,0,1,11.32,11.32ZM112,136H64a8,8,0,0,0,0,16H92.69L42.34,202.34a8,8,0,0,0,11.32,11.32L104,163.31V192a8,8,0,0,0,16,0V144A8,8,0,0,0,112,136Z\"/>\n </svg>\n </div>\n \n <div class=\"feedback-expand-icon\">\n <svg viewBox=\"0 0 256 256\">\n <path d=\"M112,40V64.69L61.66,14.34A8,8,0,0,0,50.34,25.66L100.69,76H72a8,8,0,0,0,0,16h48a8,8,0,0,0,8-8V36A8,8,0,0,0,112,40Zm131.06,70.61a8,8,0,0,0-8.72,1.73L184,162.69V136a8,8,0,0,0-16,0v48a8,8,0,0,0,8,8h48a8,8,0,0,0,0-16H195.31l50.35-50.34A8,8,0,0,0,243.06,110.61Z\"/>\n </svg>\n </div>\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\tconst minimizeIcon = this.element.querySelector('.feedback-minimize-icon');\n\t\tconst expandIcon = this.element.querySelector('.feedback-expand-icon');\n\n\t\t// Add click handlers directly to the icons\n\t\tminimizeIcon.addEventListener('click', (e) => {\n\t\t\te.stopPropagation();\n\t\t\te.preventDefault();\n\t\t\tthis.minimize();\n\t\t});\n\n\t\texpandIcon.addEventListener('click', (e) => {\n\t\t\te.stopPropagation();\n\t\t\te.preventDefault();\n\t\t\tthis.restore();\n\t\t});\n\n\t\t// Main button click handler\n\t\tbutton.addEventListener('click', (e) => {\n\t\t\t// Check if the click originated from an icon\n\t\t\tif (\n\t\t\t\te.target.closest('.feedback-minimize-icon') ||\n\t\t\t\te.target.closest('.feedback-expand-icon')\n\t\t\t) {\n\t\t\t\treturn; // Let the icon handlers deal with it\n\t\t\t}\n\n\t\t\tif (!this.isMinimized) {\n\t\t\t\tthis.openPanel();\n\t\t\t}\n\t\t});\n\n\t\tbutton.addEventListener('mouseenter', () => {\n\t\t\tif (!this.state.isSubmitting && !this.isMinimized) {\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\tif (!this.isMinimized) {\n\t\t\t\tbutton.style.transform = 'translateY(0)';\n\t\t\t}\n\t\t});\n\t}\n\n\tminimize() {\n\t\tthis.isMinimized = true;\n\t\tthis.element.classList.add('minimized');\n\t}\n\n\trestore() {\n\t\tthis.isMinimized = false;\n\t\tthis.element.classList.remove('minimized');\n\t}\n\n\tmount(container) {\n\t\tsuper.mount(container);\n\t}\n\n\tupdateText(text) {\n\t\tconst textEl = this.element?.querySelector('.feedback-text');\n\t\tif (textEl) {\n\t\t\ttextEl.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 { BaseWidget } from './BaseWidget.js';\n\nexport class ChangelogWidget extends BaseWidget {\n\tconstructor(options) {\n\t\tsuper({ ...options, type: 'changelog' });\n\t\tthis.changelogs = [];\n\t\tthis.isLoading = false;\n\t\tthis.modalElement = null;\n\t\tthis.sidebarElement = null;\n\t\tthis.currentIndex = 0;\n\t}\n\n\t_render() {\n\t\tconst trigger = document.createElement('div');\n\t\ttrigger.className = `feedback-widget changelog-widget theme-${this.options.theme} position-${this.options.position}`;\n\t\ttrigger.innerHTML = `\n\t\t\t<button class=\"changelog-trigger-btn\" type=\"button\" aria-label=\"View Updates\">\n\t\t\t\t<svg class=\"changelog-icon\" width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n\t\t\t\t\t<path d=\"M5.8 21L7.4 14L2 9.2L9.2 8.6L12 2L14.8 8.6L22 9.2L16.6 14L18.2 21L12 17.3L5.8 21Z\"/>\n\t\t\t\t</svg>\n\t\t\t\t<span class=\"changelog-text\">${this.options.triggerText || \"What's New\"}</span>\n\t\t\t\t<span class=\"changelog-confetti-emoji\">🎉</span>\n\t\t\t\t${this.options.showBadge ? '<span class=\"changelog-badge\"></span>' : ''}\n\t\t\t</button>\n\t\t`;\n\n\t\tif (this.options.customStyles) {\n\t\t\tObject.assign(trigger.style, this.options.customStyles);\n\t\t}\n\n\t\treturn trigger;\n\t}\n\n\t_attachEvents() {\n\t\tconst button = this.element.querySelector('.changelog-trigger-btn');\n\n\t\tbutton.addEventListener('click', () => {\n\t\t\tthis.openSidebar();\n\t\t});\n\n\t\tbutton.addEventListener('mouseenter', () => {\n\t\t\tbutton.style.transform = 'translateY(-2px)';\n\t\t});\n\n\t\tbutton.addEventListener('mouseleave', () => {\n\t\t\tbutton.style.transform = 'translateY(0)';\n\t\t});\n\t}\n\n\t// ==================== POPUP MODAL ====================\n\n\tasync openModal() {\n\t\tif (this.modalElement) return;\n\n\t\tthis.state.isOpen = true;\n\t\tthis._createModal();\n\n\t\t// Load changelogs if not already loaded\n\t\tif (this.changelogs.length === 0) {\n\t\t\tawait this._loadChangelogs();\n\t\t}\n\n\t\tthis.currentIndex = 0;\n\t\tthis._renderCurrentChangelog();\n\n\t\t// Prevent body scroll\n\t\tdocument.body.style.overflow = 'hidden';\n\n\t\trequestAnimationFrame(() => {\n\t\t\tif (this.modalElement) {\n\t\t\t\tthis.modalElement.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\tcloseModal() {\n\t\t// Restore body scroll\n\t\tdocument.body.style.overflow = '';\n\n\t\tif (this.modalElement) {\n\t\t\tthis.modalElement.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.modalElement && this.modalElement.parentNode) {\n\t\t\t\tthis.modalElement.parentNode.removeChild(this.modalElement);\n\t\t\t\tthis.modalElement = 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}, 300);\n\t}\n\n\t_createModal() {\n\t\t// Create backdrop\n\t\tthis.backdropElement = document.createElement('div');\n\t\tthis.backdropElement.className = 'changelog-modal-backdrop';\n\t\tdocument.body.appendChild(this.backdropElement);\n\t\tthis.backdropElement.addEventListener('click', () => this.closeModal());\n\n\t\t// Create modal\n\t\tthis.modalElement = document.createElement('div');\n\t\tthis.modalElement.className = `changelog-modal theme-${this.options.theme}`;\n\t\tthis.modalElement.innerHTML = `\n\t\t\t<div class=\"changelog-modal-container\">\n\t\t\t\t<button class=\"changelog-modal-close\" type=\"button\" aria-label=\"Close\">×</button>\n\t\t\t\t<div class=\"changelog-modal-content\">\n\t\t\t\t\t<div class=\"changelog-loading\">\n\t\t\t\t\t\t<div class=\"changelog-loading-spinner\"></div>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t`;\n\n\t\tdocument.body.appendChild(this.modalElement);\n\n\t\t// Prevent clicks inside modal from closing it\n\t\tthis.modalElement\n\t\t\t.querySelector('.changelog-modal-container')\n\t\t\t.addEventListener('click', (e) => {\n\t\t\t\te.stopPropagation();\n\t\t\t});\n\n\t\t// Attach close button event\n\t\tthis.modalElement\n\t\t\t.querySelector('.changelog-modal-close')\n\t\t\t.addEventListener('click', () => this.closeModal());\n\n\t\t// Handle escape key\n\t\tthis._escapeHandler = (e) => {\n\t\t\tif (e.key === 'Escape') {\n\t\t\t\tthis.closeModal();\n\t\t\t}\n\t\t};\n\t\tdocument.addEventListener('keydown', this._escapeHandler);\n\t}\n\n\t// ==================== LIST MODAL ====================\n\n\tasync openSidebar() {\n\t\tif (this.listModalElement) return;\n\n\t\t// Close popup modal if open\n\t\tif (this.modalElement) {\n\t\t\tthis.closeModal();\n\t\t\tawait new Promise((resolve) => setTimeout(resolve, 350));\n\t\t}\n\n\t\tthis.state.isOpen = true;\n\t\tthis._createListModal();\n\n\t\t// Load changelogs if not already loaded\n\t\tif (this.changelogs.length === 0) {\n\t\t\tawait this._loadChangelogs();\n\t\t}\n\n\t\tthis._renderChangelogList();\n\n\t\t// Prevent body scroll\n\t\tdocument.body.style.overflow = 'hidden';\n\n\t\trequestAnimationFrame(() => {\n\t\t\tif (this.listModalElement) {\n\t\t\t\tthis.listModalElement.classList.add('open');\n\t\t\t\t// Trigger confetti animation\n\t\t\t\tthis._showConfetti();\n\t\t\t}\n\t\t\tif (this.listModalBackdropElement) {\n\t\t\t\tthis.listModalBackdropElement.classList.add('show');\n\t\t\t}\n\t\t});\n\t}\n\n\t_showConfetti() {\n\t\tconst colors = [\n\t\t\t'#FF6B6B',\n\t\t\t'#4ECDC4',\n\t\t\t'#FFE66D',\n\t\t\t'#95E1D3',\n\t\t\t'#F38181',\n\t\t\t'#AA96DA',\n\t\t\t'#FCBAD3',\n\t\t\t'#A8D8EA',\n\t\t];\n\t\tconst confettiCount = 50;\n\t\tconst container = document.createElement('div');\n\t\tcontainer.className = 'changelog-confetti-container';\n\t\tdocument.body.appendChild(container);\n\n\t\tfor (let i = 0; i < confettiCount; i++) {\n\t\t\tconst confetti = document.createElement('div');\n\t\t\tconfetti.className = 'changelog-confetti';\n\t\t\tconfetti.style.left = Math.random() * 100 + '%';\n\t\t\tconfetti.style.backgroundColor =\n\t\t\t\tcolors[Math.floor(Math.random() * colors.length)];\n\t\t\tconfetti.style.animationDelay = Math.random() * 0.5 + 's';\n\t\t\tconfetti.style.animationDuration = Math.random() * 1 + 1.5 + 's';\n\n\t\t\t// Random shapes\n\t\t\tconst shapes = ['circle', 'square', 'rectangle'];\n\t\t\tconst shape = shapes[Math.floor(Math.random() * shapes.length)];\n\t\t\tif (shape === 'circle') {\n\t\t\t\tconfetti.style.borderRadius = '50%';\n\t\t\t\tconfetti.style.width = Math.random() * 8 + 4 + 'px';\n\t\t\t\tconfetti.style.height = confetti.style.width;\n\t\t\t} else if (shape === 'rectangle') {\n\t\t\t\tconfetti.style.width = Math.random() * 4 + 3 + 'px';\n\t\t\t\tconfetti.style.height = Math.random() * 10 + 8 + 'px';\n\t\t\t} else {\n\t\t\t\tconfetti.style.width = Math.random() * 8 + 4 + 'px';\n\t\t\t\tconfetti.style.height = confetti.style.width;\n\t\t\t}\n\n\t\t\tcontainer.appendChild(confetti);\n\t\t}\n\n\t\t// Remove confetti after animation\n\t\tsetTimeout(() => {\n\t\t\tif (container.parentNode) {\n\t\t\t\tcontainer.parentNode.removeChild(container);\n\t\t\t}\n\t\t}, 2500);\n\t}\n\n\tcloseSidebar() {\n\t\t// Restore body scroll\n\t\tdocument.body.style.overflow = '';\n\n\t\tif (this.listModalElement) {\n\t\t\tthis.listModalElement.classList.remove('open');\n\t\t}\n\t\tif (this.listModalBackdropElement) {\n\t\t\tthis.listModalBackdropElement.classList.remove('show');\n\t\t}\n\n\t\tsetTimeout(() => {\n\t\t\tthis.state.isOpen = false;\n\t\t\tif (this.listModalElement && this.listModalElement.parentNode) {\n\t\t\t\tthis.listModalElement.parentNode.removeChild(this.listModalElement);\n\t\t\t\tthis.listModalElement = null;\n\t\t\t}\n\t\t\tif (\n\t\t\t\tthis.listModalBackdropElement &&\n\t\t\t\tthis.listModalBackdropElement.parentNode\n\t\t\t) {\n\t\t\t\tthis.listModalBackdropElement.parentNode.removeChild(\n\t\t\t\t\tthis.listModalBackdropElement\n\t\t\t\t);\n\t\t\t\tthis.listModalBackdropElement = null;\n\t\t\t}\n\t\t\tif (this._listModalEscapeHandler) {\n\t\t\t\tdocument.removeEventListener('keydown', this._listModalEscapeHandler);\n\t\t\t}\n\t\t}, 300);\n\t}\n\n\t_createListModal() {\n\t\t// Create backdrop\n\t\tthis.listModalBackdropElement = document.createElement('div');\n\t\tthis.listModalBackdropElement.className = 'changelog-list-modal-backdrop';\n\t\tdocument.body.appendChild(this.listModalBackdropElement);\n\t\tthis.listModalBackdropElement.addEventListener('click', () =>\n\t\t\tthis.closeSidebar()\n\t\t);\n\n\t\t// Create list modal\n\t\tthis.listModalElement = document.createElement('div');\n\t\tthis.listModalElement.className = `changelog-list-modal theme-${this.options.theme}`;\n\t\tthis.listModalElement.innerHTML = `\n\t\t\t<div class=\"changelog-list-modal-container\">\n\t\t\t\t<div class=\"changelog-list-modal-header\">\n\t\t\t\t\t<h2>${this.options.title || \"What's New\"} 🎉</h2>\n\t\t\t\t\t<button class=\"changelog-list-modal-close\" type=\"button\" aria-label=\"Close\">×</button>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"changelog-list-modal-body\">\n\t\t\t\t\t<div class=\"changelog-loading\">\n\t\t\t\t\t\t<div class=\"changelog-loading-spinner\"></div>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t`;\n\n\t\tdocument.body.appendChild(this.listModalElement);\n\n\t\t// Prevent clicks inside modal from closing it\n\t\tthis.listModalElement\n\t\t\t.querySelector('.changelog-list-modal-container')\n\t\t\t.addEventListener('click', (e) => {\n\t\t\t\te.stopPropagation();\n\t\t\t});\n\n\t\t// Attach close button event\n\t\tthis.listModalElement\n\t\t\t.querySelector('.changelog-list-modal-close')\n\t\t\t.addEventListener('click', () => this.closeSidebar());\n\n\t\t// Handle escape key\n\t\tthis._listModalEscapeHandler = (e) => {\n\t\t\tif (e.key === 'Escape') {\n\t\t\t\tthis.closeSidebar();\n\t\t\t}\n\t\t};\n\t\tdocument.addEventListener('keydown', this._listModalEscapeHandler);\n\t}\n\n\t_renderChangelogList() {\n\t\tconst body = this.listModalElement.querySelector(\n\t\t\t'.changelog-list-modal-body'\n\t\t);\n\n\t\tif (this.isLoading) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.changelogs.length === 0) {\n\t\t\tbody.innerHTML = `\n\t\t\t\t<div class=\"changelog-empty\">\n\t\t\t\t\t<svg width=\"48\" height=\"48\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\">\n\t\t\t\t\t\t<path d=\"M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z\"/>\n\t\t\t\t\t\t<polyline points=\"14,2 14,8 20,8\"/>\n\t\t\t\t\t</svg>\n\t\t\t\t\t<p>No updates yet</p>\n\t\t\t\t</div>\n\t\t\t`;\n\t\t\treturn;\n\t\t}\n\n\t\tbody.innerHTML = `\n\t\t\t<div class=\"changelog-list\">\n\t\t\t\t${this.changelogs.map((changelog, index) => this._renderChangelogListItem(changelog, index)).join('')}\n\t\t\t</div>\n\t\t`;\n\n\t\t// Attach click events to items\n\t\tbody.querySelectorAll('.changelog-list-item').forEach((item, index) => {\n\t\t\titem.addEventListener('click', () => {\n\t\t\t\tconst changelog = this.changelogs[index];\n\t\t\t\tthis._handleViewUpdate(changelog);\n\t\t\t});\n\t\t});\n\t}\n\n\t_renderChangelogListItem(changelog, index) {\n\t\tconst hasImage = changelog.cover_image || changelog.image;\n\t\tconst imageUrl = changelog.cover_image || changelog.image;\n\t\tconst date = changelog.published_at\n\t\t\t? this._formatDate(changelog.published_at)\n\t\t\t: '';\n\n\t\treturn `\n\t\t\t<div class=\"changelog-list-item\" data-index=\"${index}\">\n\t\t\t\t<div class=\"changelog-list-item-main\">\n\t\t\t\t\t${\n\t\t\t\t\t\thasImage\n\t\t\t\t\t\t\t? `\n\t\t\t\t\t\t<div class=\"changelog-list-item-image\">\n\t\t\t\t\t\t\t<img src=\"${imageUrl}\" alt=\"${changelog.title}\" loading=\"lazy\" />\n\t\t\t\t\t\t</div>\n\t\t\t\t\t`\n\t\t\t\t\t\t\t: ''\n\t\t\t\t\t}\n\t\t\t\t\t<div class=\"changelog-list-item-content\">\n\t\t\t\t\t\t${date ? `<span class=\"changelog-list-item-date\">${date}</span>` : ''}\n\t\t\t\t\t\t${\n\t\t\t\t\t\t\tchangelog.labels && changelog.labels.length > 0\n\t\t\t\t\t\t\t\t? `\n\t\t\t\t\t\t\t<div class=\"changelog-list-item-labels\">\n\t\t\t\t\t\t\t\t${changelog.labels\n\t\t\t\t\t\t\t\t\t.map(\n\t\t\t\t\t\t\t\t\t\t(label) => `\n\t\t\t\t\t\t\t\t\t<span class=\"changelog-label\" style=\"background-color: ${label.color || '#E5E7EB'}; color: ${this._getContrastColor(label.color || '#E5E7EB')}\">${label.name}</span>\n\t\t\t\t\t\t\t\t`\n\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t.join('')}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t`\n\t\t\t\t\t\t\t\t: ''\n\t\t\t\t\t\t}\n\t\t\t\t\t\t<h3 class=\"changelog-list-item-title\">${changelog.title}</h3>\n\t\t\t\t\t\t${\n\t\t\t\t\t\t\tchangelog.excerpt || changelog.description\n\t\t\t\t\t\t\t\t? `\n\t\t\t\t\t\t\t<p class=\"changelog-list-item-description\">${changelog.excerpt || changelog.description}</p>\n\t\t\t\t\t\t`\n\t\t\t\t\t\t\t\t: ''\n\t\t\t\t\t\t}\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"changelog-list-item-arrow\">\n\t\t\t\t\t<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n\t\t\t\t\t\t<path d=\"M9 18l6-6-6-6\"/>\n\t\t\t\t\t</svg>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t`;\n\t}\n\n\tasync _loadChangelogs() {\n\t\tthis.isLoading = true;\n\n\t\ttry {\n\t\t\tconst result = await this.apiService.getChangelogs();\n\t\t\tthis.changelogs = result.data || [];\n\t\t\tthis.sdk.eventBus.emit('changelog:loaded', {\n\t\t\t\tchangelogs: this.changelogs,\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tthis.changelogs = [];\n\t\t\tthis.sdk.eventBus.emit('changelog:error', { error });\n\t\t} finally {\n\t\t\tthis.isLoading = false;\n\t\t}\n\t}\n\n\t_renderCurrentChangelog() {\n\t\tconst content = this.modalElement.querySelector('.changelog-modal-content');\n\n\t\tif (this.isLoading) {\n\t\t\treturn; // Keep showing loading spinner\n\t\t}\n\n\t\tif (this.changelogs.length === 0) {\n\t\t\tcontent.innerHTML = `\n\t\t\t\t<div class=\"changelog-empty\">\n\t\t\t\t\t<svg width=\"48\" height=\"48\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\">\n\t\t\t\t\t\t<path d=\"M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z\"/>\n\t\t\t\t\t\t<polyline points=\"14,2 14,8 20,8\"/>\n\t\t\t\t\t</svg>\n\t\t\t\t\t<p>No updates yet</p>\n\t\t\t\t</div>\n\t\t\t`;\n\t\t\treturn;\n\t\t}\n\n\t\tconst changelog = this.changelogs[this.currentIndex];\n\t\tconst hasImage = changelog.cover_image || changelog.image;\n\t\tconst imageUrl = changelog.cover_image || changelog.image;\n\t\tconst hasMultiple = this.changelogs.length > 1;\n\n\t\tcontent.innerHTML = `\n\t\t\t<div class=\"changelog-popup-item\">\n\t\t\t\t${\n\t\t\t\t\thasImage\n\t\t\t\t\t\t? `\n\t\t\t\t\t<div class=\"changelog-popup-image\">\n\t\t\t\t\t\t<img src=\"${imageUrl}\" alt=\"${changelog.title}\" loading=\"lazy\" />\n\t\t\t\t\t</div>\n\t\t\t\t`\n\t\t\t\t\t\t: ''\n\t\t\t\t}\n\t\t\t\t<div class=\"changelog-popup-body\">\n\t\t\t\t\t<h2 class=\"changelog-popup-title\">${changelog.title}</h2>\n\t\t\t\t\t${\n\t\t\t\t\t\tchangelog.excerpt || changelog.description\n\t\t\t\t\t\t\t? `\n\t\t\t\t\t\t<p class=\"changelog-popup-description\">${changelog.excerpt || changelog.description}</p>\n\t\t\t\t\t`\n\t\t\t\t\t\t\t: ''\n\t\t\t\t\t}\n\t\t\t\t\t<button class=\"changelog-popup-btn\" type=\"button\">\n\t\t\t\t\t\t${this.options.viewButtonText || 'View Update'}\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"changelog-popup-footer\">\n\t\t\t\t\t${\n\t\t\t\t\t\thasMultiple\n\t\t\t\t\t\t\t? `\n\t\t\t\t\t\t<div class=\"changelog-popup-dots\">\n\t\t\t\t\t\t\t${this.changelogs\n\t\t\t\t\t\t\t\t.map(\n\t\t\t\t\t\t\t\t\t(_, i) => `\n\t\t\t\t\t\t\t\t<span class=\"changelog-dot ${i === this.currentIndex ? 'active' : ''}\" data-index=\"${i}\"></span>\n\t\t\t\t\t\t\t`\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t.join('')}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t`\n\t\t\t\t\t\t\t: ''\n\t\t\t\t\t}\n\t\t\t\t\t<button class=\"changelog-view-all-btn\" type=\"button\">\n\t\t\t\t\t\tView all updates\n\t\t\t\t\t\t<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n\t\t\t\t\t\t\t<path d=\"M5 12h14M12 5l7 7-7 7\"/>\n\t\t\t\t\t\t</svg>\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t`;\n\n\t\t// Attach view button event\n\t\tcontent\n\t\t\t.querySelector('.changelog-popup-btn')\n\t\t\t.addEventListener('click', () => {\n\t\t\t\tthis._handleViewUpdate(changelog);\n\t\t\t});\n\n\t\t// Attach view all button event\n\t\tcontent\n\t\t\t.querySelector('.changelog-view-all-btn')\n\t\t\t.addEventListener('click', () => {\n\t\t\t\tthis.closeModal();\n\t\t\t\tsetTimeout(() => this.openSidebar(), 350);\n\t\t\t});\n\n\t\t// Attach dot navigation events\n\t\tif (hasMultiple) {\n\t\t\tcontent.querySelectorAll('.changelog-dot').forEach((dot) => {\n\t\t\t\tdot.addEventListener('click', (e) => {\n\t\t\t\t\tconst index = parseInt(e.target.dataset.index, 10);\n\t\t\t\t\tthis.currentIndex = index;\n\t\t\t\t\tthis._renderCurrentChangelog();\n\t\t\t\t});\n\t\t\t});\n\t\t}\n\t}\n\n\t_handleViewUpdate(changelog) {\n\t\tthis.sdk.eventBus.emit('changelog:view', { changelog });\n\n\t\t// If there's a URL, open it\n\t\tif (changelog.url || changelog.slug) {\n\t\t\tconst url =\n\t\t\t\tchangelog.url ||\n\t\t\t\t`${this.options.changelogBaseUrl || ''}/${changelog.slug}`;\n\t\t\tif (this.options.openInNewTab !== false) {\n\t\t\t\twindow.open(url, '_blank', 'noopener,noreferrer');\n\t\t\t} else {\n\t\t\t\twindow.location.href = url;\n\t\t\t}\n\t\t}\n\n\t\t// Custom callback if provided\n\t\tif (typeof this.options.onViewUpdate === 'function') {\n\t\t\tthis.options.onViewUpdate(changelog);\n\t\t}\n\t}\n\n\t_formatDate(dateString) {\n\t\tconst date = new Date(dateString);\n\t\tconst options = { year: 'numeric', month: 'short', day: 'numeric' };\n\t\treturn date.toLocaleDateString('en-US', options);\n\t}\n\n\t_getContrastColor(hexColor) {\n\t\t// Remove # if present\n\t\tconst hex = hexColor.replace('#', '');\n\t\tconst r = parseInt(hex.substr(0, 2), 16);\n\t\tconst g = parseInt(hex.substr(2, 2), 16);\n\t\tconst b = parseInt(hex.substr(4, 2), 16);\n\t\t// Calculate luminance\n\t\tconst luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255;\n\t\treturn luminance > 0.5 ? '#1F2937' : '#FFFFFF';\n\t}\n\n\thideBadge() {\n\t\tconst badge = this.element?.querySelector('.changelog-badge');\n\t\tif (badge) {\n\t\t\tbadge.style.display = 'none';\n\t\t}\n\t}\n\n\tshowBadge() {\n\t\tconst badge = this.element?.querySelector('.changelog-badge');\n\t\tif (badge) {\n\t\t\tbadge.style.display = 'block';\n\t\t}\n\t}\n\n\tnextChangelog() {\n\t\tif (this.currentIndex < this.changelogs.length - 1) {\n\t\t\tthis.currentIndex++;\n\t\t\tthis._renderCurrentChangelog();\n\t\t}\n\t}\n\n\tprevChangelog() {\n\t\tif (this.currentIndex > 0) {\n\t\t\tthis.currentIndex--;\n\t\t\tthis._renderCurrentChangelog();\n\t\t}\n\t}\n\n\tasync refresh() {\n\t\tthis.changelogs = [];\n\t\tawait this._loadChangelogs();\n\t\tif (this.modalElement) {\n\t\t\tthis.currentIndex = 0;\n\t\t\tthis._renderCurrentChangelog();\n\t\t}\n\t\tif (this.listModalElement) {\n\t\t\tthis._renderChangelogList();\n\t\t}\n\t}\n\n\tmount(container) {\n\t\tsuper.mount(container);\n\t}\n\n\tdestroy() {\n\t\tif (this._escapeHandler) {\n\t\t\tdocument.removeEventListener('keydown', this._escapeHandler);\n\t\t}\n\t\tif (this._listModalEscapeHandler) {\n\t\t\tdocument.removeEventListener('keydown', this._listModalEscapeHandler);\n\t\t}\n\t\tthis.closeModal();\n\t\tthis.closeSidebar();\n\t\tsuper.destroy();\n\t}\n}\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","/**\n * MessengerState - State management for the Messenger widget\n */\nexport class MessengerState {\n\tconstructor(options = {}) {\n\t\tthis.currentView = 'home'; // 'home', 'messages', 'chat', 'help', 'changelog'\n\t\tthis.isOpen = false;\n\t\tthis.unreadCount = 0;\n\t\tthis.activeConversationId = null;\n\n\t\t// Conversations\n\t\tthis.conversations = [];\n\t\tthis.messages = {}; // { conversationId: [messages] }\n\n\t\t// Help articles\n\t\tthis.helpArticles = [];\n\t\tthis.helpSearchQuery = '';\n\n\t\t// Changelog\n\t\tthis.homeChangelogItems = [];\n\t\tthis.changelogItems = [];\n\n\t\t// Team info\n\t\tthis.teamName = options.teamName || 'Support';\n\t\tthis.teamAvatars = options.teamAvatars || [];\n\t\tthis.welcomeMessage = options.welcomeMessage || 'How can we help?';\n\n\t\t// User info\n\t\tthis.userContext = options.userContext || null;\n\n\t\t// Feature flags\n\t\tthis.enableHelp = options.enableHelp !== false;\n\t\tthis.enableChangelog = options.enableChangelog !== false;\n\n\t\t// Agent availability\n\t\tthis.agentsOnline = false;\n\t\tthis.onlineCount = 0;\n\t\tthis.responseTime = 'Usually replies within a few minutes';\n\n\t\t// Typing indicators\n\t\tthis.typingUsers = {}; // { conversationId: { userName, timestamp } }\n\n\t\t// Loading states\n\t\tthis.isLoading = false;\n\t\tthis.isLoadingMessages = false;\n\n\t\t// Listeners\n\t\tthis._listeners = new Set();\n\t}\n\n\t/**\n\t * Subscribe to state changes\n\t */\n\tsubscribe(callback) {\n\t\tthis._listeners.add(callback);\n\t\treturn () => this._listeners.delete(callback);\n\t}\n\n\t/**\n\t * Notify all listeners of state change\n\t */\n\t_notify(changeType, data) {\n\t\tthis._listeners.forEach((cb) => cb(changeType, data, this));\n\t}\n\n\t/**\n\t * Set current view\n\t */\n\tsetView(view) {\n\t\tconst previousView = this.currentView;\n\t\tthis.currentView = view;\n\t\tthis._notify('viewChange', { previousView, currentView: view });\n\t}\n\n\t/**\n\t * Toggle panel open/closed\n\t */\n\tsetOpen(isOpen) {\n\t\tthis.isOpen = isOpen;\n\t\tthis._notify('openChange', { isOpen });\n\t}\n\n\t/**\n\t * Set active conversation for chat view\n\t */\n\tsetActiveConversation(conversationId) {\n\t\tthis.activeConversationId = conversationId;\n\t\tthis._notify('conversationChange', { conversationId });\n\t}\n\n\t/**\n\t * Update conversations list\n\t */\n\tsetConversations(conversations) {\n\t\tthis.conversations = conversations;\n\t\tthis._updateUnreadCount();\n\t\tthis._notify('conversationsUpdate', { conversations });\n\t}\n\n\t/**\n\t * Add a new conversation\n\t */\n\taddConversation(conversation) {\n\t\tthis.conversations.unshift(conversation);\n\t\tthis._updateUnreadCount();\n\t\tthis._notify('conversationAdded', { conversation });\n\t}\n\n\t/**\n\t * Update messages for a conversation\n\t */\n\tsetMessages(conversationId, messages) {\n\t\tthis.messages[conversationId] = messages;\n\t\tthis._notify('messagesUpdate', { conversationId, messages });\n\t}\n\n\t/**\n\t * Add a message to a conversation\n\t */\n\taddMessage(conversationId, message) {\n\t\tif (!this.messages[conversationId]) {\n\t\t\tthis.messages[conversationId] = [];\n\t\t}\n\t\tthis.messages[conversationId].push(message);\n\n\t\t// Update conversation preview\n\t\tconst conv = this.conversations.find((c) => c.id === conversationId);\n\t\tif (conv) {\n\t\t\tconv.lastMessage = message.content;\n\t\t\tconv.lastMessageTime = message.timestamp;\n\t\t\tif (!message.isOwn) {\n\t\t\t\tconv.unread = (conv.unread || 0) + 1;\n\t\t\t\tthis._updateUnreadCount();\n\t\t\t}\n\t\t}\n\n\t\tthis._notify('messageAdded', { conversationId, message });\n\t}\n\n\t/**\n\t * Mark conversation as read\n\t */\n\tmarkAsRead(conversationId) {\n\t\tconst conv = this.conversations.find((c) => c.id === conversationId);\n\t\tif (conv && conv.unread > 0) {\n\t\t\tconv.unread = 0;\n\t\t\tthis._updateUnreadCount();\n\t\t\tthis._notify('conversationRead', { conversationId });\n\t\t}\n\t}\n\n\t/**\n\t * Update unread count\n\t */\n\t_updateUnreadCount() {\n\t\tthis.unreadCount = this.conversations.reduce(\n\t\t\t(sum, c) => sum + (c.unread || 0),\n\t\t\t0\n\t\t);\n\t\tthis._notify('unreadCountChange', { count: this.unreadCount });\n\t}\n\n\t/**\n\t * Set help articles\n\t */\n\tsetHelpArticles(articles) {\n\t\tthis.helpArticles = articles;\n\t\tthis._notify('helpArticlesUpdate', { articles });\n\t}\n\n\t/**\n\t * Set help search query\n\t */\n\tsetHelpSearchQuery(query) {\n\t\tthis.helpSearchQuery = query;\n\t\tthis._notify('helpSearchChange', { query });\n\t}\n\n\t/**\n\t * Set home changelog items\n\t */\n\tsetHomeChangelogItems(items) {\n\t\tthis.homeChangelogItems = items;\n\t\tthis._notify('homeChangelogUpdate', { items });\n\t}\n\n\t/**\n\t * Set changelog items\n\t */\n\tsetChangelogItems(items) {\n\t\tthis.changelogItems = items;\n\t\tthis._notify('changelogUpdate', { items });\n\t}\n\n\t/**\n\t * Get current conversation\n\t */\n\tgetActiveConversation() {\n\t\treturn this.conversations.find((c) => c.id === this.activeConversationId);\n\t}\n\n\t/**\n\t * Get messages for active conversation\n\t */\n\tgetActiveMessages() {\n\t\treturn this.messages[this.activeConversationId] || [];\n\t}\n\n\t/**\n\t * Get filtered help articles\n\t */\n\tgetFilteredHelpArticles() {\n\t\tif (!this.helpSearchQuery) {\n\t\t\treturn this.helpArticles;\n\t\t}\n\t\tconst query = this.helpSearchQuery.toLowerCase();\n\t\treturn this.helpArticles.filter(\n\t\t\t(article) =>\n\t\t\t\tarticle.title.toLowerCase().includes(query) ||\n\t\t\t\t(article.description &&\n\t\t\t\t\tarticle.description.toLowerCase().includes(query))\n\t\t);\n\t}\n\n\t/**\n\t * Reset state\n\t */\n\treset() {\n\t\tthis.currentView = 'home';\n\t\tthis.activeConversationId = null;\n\t\tthis.helpSearchQuery = '';\n\t\tthis._notify('reset', {});\n\t}\n}\n","/**\n * MessengerLauncher - Floating trigger button for messenger\n */\nexport class MessengerLauncher {\n\tconstructor(state, options = {}) {\n\t\tthis.state = state;\n\t\tthis.options = {\n\t\t\tposition: options.position || 'bottom-right',\n\t\t\tprimaryColor: options.primaryColor || '#1c1c1e',\n\t\t\t...options,\n\t\t};\n\t\tthis.element = null;\n\t\tthis._unsubscribe = null;\n\t}\n\n\trender() {\n\t\tthis.element = document.createElement('div');\n\t\tthis.element.className = `messenger-launcher messenger-launcher-${this.options.position}`;\n\n\t\tthis._updateContent();\n\t\tthis._attachEvents();\n\n\t\t// Subscribe to state changes\n\t\tthis._unsubscribe = this.state.subscribe((type, data) => {\n\t\t\tif (type === 'openChange') {\n\t\t\t\tthis._updateIcon();\n\t\t\t}\n\t\t\tif (type === 'unreadCountChange') {\n\t\t\t\tthis._updateBadge();\n\t\t\t}\n\t\t});\n\n\t\treturn this.element;\n\t}\n\n\t_updateContent() {\n\t\tconst badgeHtml =\n\t\t\tthis.state.unreadCount > 0\n\t\t\t\t? `<span class=\"messenger-launcher-badge\">${this.state.unreadCount > 9 ? '9+' : this.state.unreadCount}</span>`\n\t\t\t\t: '';\n\n\t\tthis.element.innerHTML = `\n\t\t\t<button class=\"messenger-launcher-btn\" aria-label=\"Open messenger\" style=\"background: ${this.options.primaryColor};\">\n\t\t\t\t<span class=\"messenger-launcher-icon messenger-launcher-icon-chat\">\n\t\t\t\t\t<i class=\"ph ph-chat-circle-dots\" style=\"font-size: 24px;\"></i>\n\t\t\t\t</span>\n\t\t\t\t<span class=\"messenger-launcher-icon messenger-launcher-icon-close\" style=\"display: none;\">\n\t\t\t\t\t<i class=\"ph ph-x\" style=\"font-size: 24px;\"></i>\n\t\t\t\t</span>\n\t\t\t\t${badgeHtml}\n\t\t\t</button>\n\t\t`;\n\t}\n\n\t_attachEvents() {\n\t\tthis.element\n\t\t\t.querySelector('.messenger-launcher-btn')\n\t\t\t.addEventListener('click', () => {\n\t\t\t\tthis.state.setOpen(!this.state.isOpen);\n\t\t\t});\n\t}\n\n\t_updateIcon() {\n\t\tconst chatIcon = this.element.querySelector(\n\t\t\t'.messenger-launcher-icon-chat'\n\t\t);\n\t\tconst closeIcon = this.element.querySelector(\n\t\t\t'.messenger-launcher-icon-close'\n\t\t);\n\n\t\tif (this.state.isOpen) {\n\t\t\tchatIcon.style.display = 'none';\n\t\t\tcloseIcon.style.display = 'flex';\n\t\t\tthis.element.classList.add('messenger-launcher-open');\n\t\t} else {\n\t\t\tchatIcon.style.display = 'flex';\n\t\t\tcloseIcon.style.display = 'none';\n\t\t\tthis.element.classList.remove('messenger-launcher-open');\n\t\t}\n\t}\n\n\t_updateBadge() {\n\t\tconst existingBadge = this.element.querySelector(\n\t\t\t'.messenger-launcher-badge'\n\t\t);\n\t\tif (existingBadge) {\n\t\t\texistingBadge.remove();\n\t\t}\n\n\t\tif (this.state.unreadCount > 0 && !this.state.isOpen) {\n\t\t\tconst badge = document.createElement('span');\n\t\t\tbadge.className = 'messenger-launcher-badge';\n\t\t\tbadge.textContent =\n\t\t\t\tthis.state.unreadCount > 9 ? '9+' : this.state.unreadCount;\n\t\t\tthis.element.querySelector('.messenger-launcher-btn').appendChild(badge);\n\t\t}\n\t}\n\n\tshow() {\n\t\tif (this.element) {\n\t\t\tthis.element.style.display = 'block';\n\t\t}\n\t}\n\n\thide() {\n\t\tif (this.element) {\n\t\t\tthis.element.style.display = 'none';\n\t\t}\n\t}\n\n\tdestroy() {\n\t\tif (this._unsubscribe) {\n\t\t\tthis._unsubscribe();\n\t\t}\n\t\tif (this.element && this.element.parentNode) {\n\t\t\tthis.element.parentNode.removeChild(this.element);\n\t\t}\n\t}\n}\n","/**\n * NavigationTabs - Bottom navigation for messenger\n */\nexport class NavigationTabs {\n\tconstructor(state, options = {}) {\n\t\tthis.state = state;\n\t\tthis.options = options;\n\t\tthis.element = null;\n\t\tthis._unsubscribe = null;\n\t}\n\n\trender() {\n\t\tthis.element = document.createElement('div');\n\t\tthis.element.className = 'messenger-nav';\n\n\t\tthis._updateContent();\n\t\tthis._attachEvents();\n\n\t\t// Subscribe to state changes\n\t\tthis._unsubscribe = this.state.subscribe((type) => {\n\t\t\tif (type === 'viewChange' || type === 'unreadCountChange') {\n\t\t\t\tthis._updateActiveTab();\n\t\t\t}\n\t\t});\n\n\t\treturn this.element;\n\t}\n\n\t_getTabs() {\n\t\tconst tabs = [\n\t\t\t{ id: 'home', label: 'Home', icon: this._getHomeIcon() },\n\t\t\t{\n\t\t\t\tid: 'messages',\n\t\t\t\tlabel: 'Messages',\n\t\t\t\ticon: this._getMessagesIcon(),\n\t\t\t\tbadge: this.state.unreadCount,\n\t\t\t},\n\t\t];\n\n\t\tif (this.state.enableHelp) {\n\t\t\ttabs.push({ id: 'help', label: 'Help', icon: this._getHelpIcon() });\n\t\t}\n\n\t\tif (this.state.enableChangelog) {\n\t\t\ttabs.push({\n\t\t\t\tid: 'changelog',\n\t\t\t\tlabel: 'Changelog',\n\t\t\t\ticon: this._getChangelogIcon(),\n\t\t\t});\n\t\t}\n\n\t\treturn tabs;\n\t}\n\n\t_updateContent() {\n\t\tconst tabs = this._getTabs();\n\t\tconst tabsHtml = tabs\n\t\t\t.map((tab) => {\n\t\t\t\tconst isActive = this.state.currentView === tab.id;\n\t\t\t\tconst badgeHtml =\n\t\t\t\t\ttab.badge && tab.badge > 0\n\t\t\t\t\t\t? `<span class=\"messenger-nav-badge\">${tab.badge > 9 ? '9+' : tab.badge}</span>`\n\t\t\t\t\t\t: '';\n\n\t\t\t\treturn `\n\t\t\t\t<button class=\"messenger-nav-tab ${isActive ? 'active' : ''}\" data-tab=\"${tab.id}\">\n\t\t\t\t\t<span class=\"messenger-nav-icon\">${tab.icon}</span>\n\t\t\t\t\t<span class=\"messenger-nav-label\">${tab.label}</span>\n\t\t\t\t\t${badgeHtml}\n\t\t\t\t</button>\n\t\t\t`;\n\t\t\t})\n\t\t\t.join('');\n\n\t\tthis.element.innerHTML = tabsHtml;\n\t}\n\n\t_attachEvents() {\n\t\tthis.element.addEventListener('click', (e) => {\n\t\t\tconst tab = e.target.closest('.messenger-nav-tab');\n\t\t\tif (tab) {\n\t\t\t\tconst tabId = tab.dataset.tab;\n\t\t\t\tthis.state.setView(tabId);\n\t\t\t}\n\t\t});\n\t}\n\n\t_updateActiveTab() {\n\t\tconst tabs = this.element.querySelectorAll('.messenger-nav-tab');\n\t\ttabs.forEach((tab) => {\n\t\t\tconst isActive = tab.dataset.tab === this.state.currentView;\n\t\t\ttab.classList.toggle('active', isActive);\n\n\t\t\t// Update badge if messages tab\n\t\t\tif (tab.dataset.tab === 'messages') {\n\t\t\t\tconst existingBadge = tab.querySelector('.messenger-nav-badge');\n\t\t\t\tif (existingBadge) existingBadge.remove();\n\n\t\t\t\tif (this.state.unreadCount > 0) {\n\t\t\t\t\tconst badge = document.createElement('span');\n\t\t\t\t\tbadge.className = 'messenger-nav-badge';\n\t\t\t\t\tbadge.textContent =\n\t\t\t\t\t\tthis.state.unreadCount > 9 ? '9+' : this.state.unreadCount;\n\t\t\t\t\ttab.appendChild(badge);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\n\t_getHomeIcon() {\n\t\treturn `<i class=\"ph-duotone ph-house\" style=\"font-size: 24px;\"></i>`;\n\t}\n\n\t_getMessagesIcon() {\n\t\treturn `<i class=\"ph-duotone ph-chat\" style=\"font-size: 24px;\"></i>`;\n\t}\n\n\t_getHelpIcon() {\n\t\treturn `<i class=\"ph-duotone ph-question\" style=\"font-size: 24px;\"></i>`;\n\t}\n\n\t_getChangelogIcon() {\n\t\treturn `<i class=\"ph-duotone ph-megaphone\" style=\"font-size: 24px;\"></i>`;\n\t}\n\n\tdestroy() {\n\t\tif (this._unsubscribe) {\n\t\t\tthis._unsubscribe();\n\t\t}\n\t\tif (this.element && this.element.parentNode) {\n\t\t\tthis.element.parentNode.removeChild(this.element);\n\t\t}\n\t}\n}\n","/**\n * MessengerPanel - Main panel container for messenger\n */\nimport { NavigationTabs } from './NavigationTabs.js';\n\nexport class MessengerPanel {\n\tconstructor(state, options = {}) {\n\t\tthis.state = state;\n\t\tthis.options = {\n\t\t\tposition: options.position || 'bottom-right',\n\t\t\ttheme: options.theme || 'dark',\n\t\t\t...options,\n\t\t};\n\t\tthis.element = null;\n\t\tthis.navigationTabs = null;\n\t\tthis.currentViewComponent = null;\n\t\tthis.viewRegistry = {};\n\t\tthis._unsubscribe = null;\n\t}\n\n\t/**\n\t * Register view components\n\t */\n\tregisterView(name, ViewClass) {\n\t\tthis.viewRegistry[name] = ViewClass;\n\t}\n\n\trender() {\n\t\tthis.element = document.createElement('div');\n\t\tthis.element.className = `messenger-panel messenger-panel-${this.options.position} theme-${this.options.theme}`;\n\n\t\tthis.element.innerHTML = `\n\t\t\t<div class=\"messenger-panel-content\">\n\t\t\t\t<div class=\"messenger-panel-views\"></div>\n\t\t\t\t<div class=\"messenger-panel-nav\"></div>\n\t\t\t</div>\n\t\t`;\n\n\t\t// Render navigation tabs\n\t\tthis.navigationTabs = new NavigationTabs(this.state, this.options);\n\t\tconst navContainer = this.element.querySelector('.messenger-panel-nav');\n\t\tnavContainer.appendChild(this.navigationTabs.render());\n\n\t\t// Render initial view\n\t\tthis._renderCurrentView();\n\n\t\t// Subscribe to state changes\n\t\tthis._unsubscribe = this.state.subscribe((type) => {\n\t\t\tif (type === 'viewChange') {\n\t\t\t\tthis._renderCurrentView();\n\t\t\t}\n\t\t});\n\n\t\treturn this.element;\n\t}\n\n\t_renderCurrentView() {\n\t\tconst viewsContainer = this.element.querySelector('.messenger-panel-views');\n\n\t\t// Destroy current view if exists\n\t\tif (this.currentViewComponent && this.currentViewComponent.destroy) {\n\t\t\tthis.currentViewComponent.destroy();\n\t\t}\n\n\t\t// Clear container\n\t\tviewsContainer.innerHTML = '';\n\n\t\t// Get view class\n\t\tconst ViewClass = this.viewRegistry[this.state.currentView];\n\t\tif (ViewClass) {\n\t\t\tthis.currentViewComponent = new ViewClass(this.state, this.options);\n\t\t\tviewsContainer.appendChild(this.currentViewComponent.render());\n\t\t} else {\n\t\t\tviewsContainer.innerHTML = `<div class=\"messenger-view-placeholder\">View not found: ${this.state.currentView}</div>`;\n\t\t}\n\t}\n\n\t/**\n\t * Show the panel with animation\n\t */\n\tshow() {\n\t\tif (this.element) {\n\t\t\tthis.element.style.display = 'block';\n\t\t\t// Trigger animation\n\t\t\trequestAnimationFrame(() => {\n\t\t\t\tthis.element.classList.add('open');\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Hide the panel with animation\n\t */\n\thide() {\n\t\tif (this.element) {\n\t\t\tthis.element.classList.remove('open');\n\t\t\t// Wait for animation to complete\n\t\t\tsetTimeout(() => {\n\t\t\t\tif (this.element) {\n\t\t\t\t\tthis.element.style.display = 'none';\n\t\t\t\t}\n\t\t\t}, 300);\n\t\t}\n\t}\n\n\t/**\n\t * Set panel header content (used by views)\n\t */\n\tsetHeader(headerContent) {\n\t\tconst header = this.element.querySelector('.messenger-panel-header');\n\t\tif (header) {\n\t\t\theader.innerHTML = headerContent;\n\t\t}\n\t}\n\n\tdestroy() {\n\t\tif (this._unsubscribe) {\n\t\t\tthis._unsubscribe();\n\t\t}\n\t\tif (this.navigationTabs) {\n\t\t\tthis.navigationTabs.destroy();\n\t\t}\n\t\tif (this.currentViewComponent && this.currentViewComponent.destroy) {\n\t\t\tthis.currentViewComponent.destroy();\n\t\t}\n\t\tif (this.element && this.element.parentNode) {\n\t\t\tthis.element.parentNode.removeChild(this.element);\n\t\t}\n\t}\n}\n","/**\n * ChangelogView - Changelog and announcements\n */\nexport class ChangelogView {\n\tconstructor(state, options = {}) {\n\t\tthis.state = state;\n\t\tthis.options = options;\n\t\tthis.element = null;\n\t\tthis._unsubscribe = null;\n\t}\n\n\trender() {\n\t\tthis.element = document.createElement('div');\n\t\tthis.element.className = 'messenger-view messenger-changelog-view';\n\n\t\tthis._updateContent();\n\n\t\t// Subscribe to state changes\n\t\tthis._unsubscribe = this.state.subscribe((type) => {\n\t\t\tif (type === 'changelogUpdate') {\n\t\t\t\tthis._updateChangelogList();\n\t\t\t}\n\t\t});\n\n\t\treturn this.element;\n\t}\n\n\t_updateContent() {\n\t\tconst avatarsHtml = this._renderTeamAvatars();\n\n\t\tthis.element.innerHTML = `\n\t\t\t<div class=\"messenger-changelog-header\">\n\t\t\t\t<h2>Changelog</h2>\n\t\t\t\t<button class=\"messenger-close-btn\" aria-label=\"Close\">\n\t\t\t\t\t<i class=\"ph ph-x\" style=\"font-size: 20px;\"></i>\n\t\t\t\t</button>\n\t\t\t</div>\n\n\t\t\t<div class=\"messenger-changelog-subheader\">\n\t\t\t\t<span class=\"messenger-changelog-latest\">Latest</span>\n\t\t\t\t<div class=\"messenger-changelog-team\">\n\t\t\t\t\t<span>From ${this.state.teamName}</span>\n\t\t\t\t\t${avatarsHtml}\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t<div class=\"messenger-changelog-body\">\n\t\t\t\t<div class=\"messenger-changelog-list\"></div>\n\t\t\t</div>\n\t\t`;\n\n\t\tthis._updateChangelogList();\n\t\tthis._attachEvents();\n\t}\n\n\t_updateChangelogList() {\n\t\tconst changelogContainer = this.element.querySelector(\n\t\t\t'.messenger-changelog-list'\n\t\t);\n\t\tconst changelogItems = this.state.changelogItems;\n\n\t\tif (changelogItems.length === 0) {\n\t\t\tchangelogContainer.innerHTML = this._renderEmptyState();\n\t\t\treturn;\n\t\t}\n\n\t\tchangelogContainer.innerHTML = changelogItems\n\t\t\t.map((item) => this._renderChangelogCard(item))\n\t\t\t.join('');\n\n\t\t// Attach click events\n\t\tthis._attachChangelogEvents();\n\t}\n\n\t_renderChangelogCard(item) {\n\t\tconst tagsHtml =\n\t\t\titem.tags && item.tags.length > 0\n\t\t\t\t? `<div class=\"messenger-changelog-tags\">\n\t\t\t\t${item.tags.map((tag) => `<span class=\"messenger-changelog-tag\">${tag}</span>`).join('')}\n\t\t\t</div>`\n\t\t\t\t: '';\n\n\t\tconst dateStr = this._formatDate(item.publishedAt || item.date);\n\n\t\treturn `\n\t\t\t<div class=\"messenger-changelog-card\" data-changelog-id=\"${item.id}\">\n\t\t\t\t${\n\t\t\t\t\titem.coverImage\n\t\t\t\t\t\t? `\n\t\t\t\t\t<div class=\"messenger-changelog-cover\">\n\t\t\t\t\t\t<img src=\"${item.coverImage}\" alt=\"${item.title}\" onerror=\"this.style.display='none';\" />\n\t\t\t\t\t</div>\n\t\t\t\t`\n\t\t\t\t\t\t: ''\n\t\t\t\t}\n\t\t\t\t<div class=\"messenger-changelog-content\">\n\t\t\t\t\t${tagsHtml}\n\t\t\t\t\t<h3 class=\"messenger-changelog-title\">${item.title}</h3>\n\t\t\t\t\t${item.description ? `<p class=\"messenger-changelog-description\">${this._truncateText(item.description, 100)}</p>` : ''}\n\t\t\t\t\t<div class=\"messenger-changelog-meta\">\n\t\t\t\t\t\t<span class=\"messenger-changelog-date\">${dateStr}</span>\n\t\t\t\t\t\t<i class=\"ph ph-caret-right messenger-changelog-arrow\" style=\"font-size: 16px;\"></i>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t`;\n\t}\n\n\t_renderTeamAvatars() {\n\t\tconst avatars = this.state.teamAvatars;\n\t\tif (!avatars || avatars.length === 0) {\n\t\t\treturn `\n\t\t\t\t<div class=\"messenger-avatar-stack messenger-avatar-stack-tiny\">\n\t\t\t\t\t<div class=\"messenger-avatar messenger-avatar-tiny\" style=\"background: #5856d6;\">S</div>\n\t\t\t\t</div>\n\t\t\t`;\n\t\t}\n\n\t\tconst colors = ['#5856d6', '#007aff', '#34c759'];\n\t\tconst avatarItems = avatars\n\t\t\t.slice(0, 2)\n\t\t\t.map((avatar, i) => {\n\t\t\t\tif (typeof avatar === 'string' && avatar.startsWith('http')) {\n\t\t\t\t\treturn `<img class=\"messenger-avatar messenger-avatar-tiny\" src=\"${avatar}\" alt=\"Team member\" style=\"z-index: ${2 - i};\" />`;\n\t\t\t\t}\n\t\t\t\treturn `<div class=\"messenger-avatar messenger-avatar-tiny\" style=\"background: ${colors[i % colors.length]}; z-index: ${2 - i};\">${avatar.charAt(0).toUpperCase()}</div>`;\n\t\t\t})\n\t\t\t.join('');\n\n\t\treturn `<div class=\"messenger-avatar-stack messenger-avatar-stack-tiny\">${avatarItems}</div>`;\n\t}\n\n\t_renderEmptyState() {\n\t\treturn `\n\t\t\t<div class=\"messenger-changelog-empty\">\n\t\t\t\t<div class=\"messenger-changelog-empty-icon\">\n\t\t\t\t\t<i class=\"ph ph-megaphone\" style=\"font-size: 48px;\"></i>\n\t\t\t\t</div>\n\t\t\t\t<h3>No changelog yet</h3>\n\t\t\t\t<p>Check back later for updates</p>\n\t\t\t</div>\n\t\t`;\n\t}\n\n\t_formatDate(dateString) {\n\t\tif (!dateString) return '';\n\t\tconst date = new Date(dateString);\n\t\treturn date.toLocaleDateString('en-US', {\n\t\t\tmonth: 'short',\n\t\t\tday: 'numeric',\n\t\t\tyear: 'numeric',\n\t\t});\n\t}\n\n\t_truncateText(text, maxLength) {\n\t\tif (!text) return '';\n\t\tif (text.length <= maxLength) return text;\n\t\treturn text.substring(0, maxLength).trim() + '...';\n\t}\n\n\t_attachEvents() {\n\t\t// Close button\n\t\tthis.element\n\t\t\t.querySelector('.messenger-close-btn')\n\t\t\t.addEventListener('click', () => {\n\t\t\t\tthis.state.setOpen(false);\n\t\t\t});\n\n\t\tthis._attachChangelogEvents();\n\t}\n\n\t_attachChangelogEvents() {\n\t\tthis.element\n\t\t\t.querySelectorAll('.messenger-changelog-card')\n\t\t\t.forEach((card) => {\n\t\t\t\tcard.addEventListener('click', () => {\n\t\t\t\t\tconst changelogId = card.dataset.changelogId;\n\t\t\t\t\tconst changelogItem = this.state.changelogItems.find(\n\t\t\t\t\t\t(n) => n.id === changelogId\n\t\t\t\t\t);\n\t\t\t\t\tif (changelogItem && changelogItem.url) {\n\t\t\t\t\t\twindow.open(changelogItem.url, '_blank');\n\t\t\t\t\t} else if (this.options.onChangelogClick) {\n\t\t\t\t\t\tthis.options.onChangelogClick(changelogItem);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t});\n\t}\n\n\tdestroy() {\n\t\tif (this._unsubscribe) {\n\t\t\tthis._unsubscribe();\n\t\t}\n\t\tif (this.element && this.element.parentNode) {\n\t\t\tthis.element.parentNode.removeChild(this.element);\n\t\t}\n\t}\n}\n","/**\n * ChatView - Individual conversation chat\n */\nexport class ChatView {\n\tconstructor(state, options = {}) {\n\t\tthis.state = state;\n\t\tthis.options = options;\n\t\tthis.element = null;\n\t\tthis._unsubscribe = null;\n\t\tthis._typingTimeout = null;\n\t\tthis._isTyping = false;\n\t\tthis._typingIndicator = null;\n\t}\n\n\trender() {\n\t\tthis.element = document.createElement('div');\n\t\tthis.element.className = 'messenger-view messenger-chat-view';\n\n\t\tthis._updateContent();\n\n\t\t// Subscribe to state changes\n\t\tthis._unsubscribe = this.state.subscribe((type, data) => {\n\t\t\tif (\n\t\t\t\ttype === 'messageAdded' &&\n\t\t\t\tdata.conversationId === this.state.activeConversationId\n\t\t\t) {\n\t\t\t\tthis._hideTypingIndicator();\n\t\t\t\tthis._appendMessage(data.message);\n\t\t\t\tthis._scrollToBottom();\n\t\t\t} else if (\n\t\t\t\ttype === 'typingStarted' &&\n\t\t\t\tdata.conversationId === this.state.activeConversationId\n\t\t\t) {\n\t\t\t\tthis._showTypingIndicator(data.userName);\n\t\t\t} else if (\n\t\t\t\ttype === 'typingStopped' &&\n\t\t\t\tdata.conversationId === this.state.activeConversationId\n\t\t\t) {\n\t\t\t\tthis._hideTypingIndicator();\n\t\t\t} else if (type === 'messagesUpdate' && data.conversationId === this.state.activeConversationId) {\n\t\t\t\tthis._updateContent();\n\t\t\t}\n\t\t});\n\n\t\treturn this.element;\n\t}\n\n\t_updateContent() {\n\t\tconst conversation = this.state.getActiveConversation();\n\t\tconst messages = this.state.getActiveMessages();\n\t\tconst isNewConversation = !this.state.activeConversationId;\n\n\t\tconst messagesHtml =\n\t\t\tmessages.length === 0\n\t\t\t\t? this._renderEmptyState(isNewConversation)\n\t\t\t\t: messages.map((msg) => this._renderMessage(msg)).join('');\n\n\t\tconst avatarHtml = this._renderConversationAvatar(conversation);\n\t\tconst title = isNewConversation\n\t\t\t? 'New conversation'\n\t\t\t: conversation?.title || 'Chat with team';\n\t\tconst placeholder = isNewConversation\n\t\t\t? 'Start typing your message...'\n\t\t\t: 'Write a message...';\n\n\t\tthis.element.innerHTML = `\n\t\t\t<div class=\"messenger-chat-header\">\n\t\t\t\t<button class=\"messenger-back-btn\" aria-label=\"Back\">\n\t\t\t\t\t<i class=\"ph ph-caret-left\" style=\"font-size: 20px;\"></i>\n\t\t\t\t</button>\n\t\t\t\t<div class=\"messenger-chat-header-info\">\n\t\t\t\t\t${avatarHtml}\n\t\t\t\t\t<span class=\"messenger-chat-title\">${title}</span>\n\t\t\t\t</div>\n\t\t\t\t<button class=\"messenger-close-btn\" aria-label=\"Close\">\n\t\t\t\t\t<i class=\"ph ph-x\" style=\"font-size: 20px;\"></i>\n\t\t\t\t</button>\n\t\t\t</div>\n\n\t\t\t<div class=\"messenger-chat-messages\">\n\t\t\t\t${messagesHtml}\n\t\t\t\t<div class=\"messenger-typing-indicator\" style=\"display: none;\">\n\t\t\t\t\t<div class=\"messenger-typing-dots\">\n\t\t\t\t\t\t<span></span><span></span><span></span>\n\t\t\t\t\t</div>\n\t\t\t\t\t<span class=\"messenger-typing-text\"></span>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t<div class=\"messenger-chat-compose\">\n\t\t\t\t<div class=\"messenger-compose-input-wrapper\">\n\t\t\t\t\t<textarea class=\"messenger-compose-input\" placeholder=\"${placeholder}\" rows=\"1\"></textarea>\n\t\t\t\t</div>\n\t\t\t\t<button class=\"messenger-compose-send\" aria-label=\"Send\" disabled>\n\t\t\t\t\t<i class=\"ph ph-paper-plane-tilt\" style=\"font-size: 20px;\"></i>\n\t\t\t\t</button>\n\t\t\t</div>\n\t\t`;\n\n\t\tthis._typingIndicator = this.element.querySelector('.messenger-typing-indicator');\n\t\tthis._attachEvents();\n\t\tthis._scrollToBottom();\n\t}\n\n\t_renderEmptyState(isNewConversation = false) {\n\t\tconst avatarHtml = this._renderTeamAvatars();\n\t\tconst responseTime = this.state.responseTime || 'We typically reply within a few minutes';\n\t\tconst isOnline = this.state.agentsOnline;\n\n\t\treturn `\n\t\t\t<div class=\"messenger-chat-empty\">\n\t\t\t\t<div class=\"messenger-chat-empty-avatars\">${avatarHtml}</div>\n\t\t\t\t<h3>${isNewConversation ? 'Start a new conversation' : 'Start the conversation'}</h3>\n\t\t\t\t<p>Send us a message and we'll get back to you as soon as possible.</p>\n\t\t\t\t<div class=\"messenger-chat-availability\">\n\t\t\t\t\t<span class=\"messenger-availability-dot ${isOnline ? 'messenger-availability-online' : 'messenger-availability-away'}\"></span>\n\t\t\t\t\t<span>${isOnline ? \"We're online now\" : responseTime}</span>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t`;\n\t}\n\n\t_renderMessage(message) {\n\t\tconst isOwn = message.isOwn;\n\t\tconst messageClass = isOwn\n\t\t\t? 'messenger-message-own'\n\t\t\t: 'messenger-message-received';\n\t\tconst timeStr = this._formatMessageTime(message.timestamp);\n\n\t\tif (isOwn) {\n\t\t\treturn `\n\t\t\t\t<div class=\"messenger-message ${messageClass}\">\n\t\t\t\t\t<div class=\"messenger-message-bubble\">\n\t\t\t\t\t\t<div class=\"messenger-message-content\">${this._formatMessageContent(message.content)}</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"messenger-message-time\">${timeStr}</div>\n\t\t\t\t</div>\n\t\t\t`;\n\t\t}\n\n\t\tconst avatarHtml = this._renderSenderAvatar(message.sender);\n\t\treturn `\n\t\t\t<div class=\"messenger-message ${messageClass}\">\n\t\t\t\t<div class=\"messenger-message-avatar\">${avatarHtml}</div>\n\t\t\t\t<div class=\"messenger-message-wrapper\">\n\t\t\t\t\t<div class=\"messenger-message-sender\">${message.sender?.name || 'Support'}</div>\n\t\t\t\t\t<div class=\"messenger-message-bubble\">\n\t\t\t\t\t\t<div class=\"messenger-message-content\">${this._formatMessageContent(message.content)}</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"messenger-message-time\">${timeStr}</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t`;\n\t}\n\n\t_renderSenderAvatar(sender) {\n\t\tif (sender?.avatarUrl) {\n\t\t\treturn `<img class=\"messenger-avatar messenger-avatar-small\" src=\"${sender.avatarUrl}\" alt=\"${sender.name}\" />`;\n\t\t}\n\t\tconst initial = (sender?.name || 'S').charAt(0).toUpperCase();\n\t\treturn `<div class=\"messenger-avatar messenger-avatar-small\" style=\"background: #5856d6;\">${initial}</div>`;\n\t}\n\n\t_renderConversationAvatar(conversation) {\n\t\tif (!conversation?.participants?.length) {\n\t\t\treturn `<div class=\"messenger-avatar messenger-avatar-small\" style=\"background: #5856d6;\">S</div>`;\n\t\t}\n\t\tconst p = conversation.participants[0];\n\t\tif (p.avatarUrl) {\n\t\t\treturn `<img class=\"messenger-avatar messenger-avatar-small\" src=\"${p.avatarUrl}\" alt=\"${p.name}\" />`;\n\t\t}\n\t\treturn `<div class=\"messenger-avatar messenger-avatar-small\" style=\"background: #5856d6;\">${(p.name || 'S').charAt(0).toUpperCase()}</div>`;\n\t}\n\n\t_renderTeamAvatars() {\n\t\tconst avatars = this.state.teamAvatars;\n\t\tif (!avatars || avatars.length === 0) {\n\t\t\treturn `\n\t\t\t\t<div class=\"messenger-avatar-stack\">\n\t\t\t\t\t<div class=\"messenger-avatar\" style=\"background: #5856d6;\">S</div>\n\t\t\t\t\t<div class=\"messenger-avatar\" style=\"background: #007aff;\">T</div>\n\t\t\t\t</div>\n\t\t\t`;\n\t\t}\n\n\t\tconst colors = ['#5856d6', '#007aff', '#34c759', '#ff9500', '#ff3b30'];\n\t\tconst avatarItems = avatars\n\t\t\t.slice(0, 3)\n\t\t\t.map((avatar, i) => {\n\t\t\t\tif (typeof avatar === 'string' && avatar.startsWith('http')) {\n\t\t\t\t\treturn `<img class=\"messenger-avatar\" src=\"${avatar}\" alt=\"Team member\" style=\"z-index: ${3 - i};\" />`;\n\t\t\t\t}\n\t\t\t\treturn `<div class=\"messenger-avatar\" style=\"background: ${colors[i % colors.length]}; z-index: ${3 - i};\">${avatar.charAt(0).toUpperCase()}</div>`;\n\t\t\t})\n\t\t\t.join('');\n\n\t\treturn `<div class=\"messenger-avatar-stack\">${avatarItems}</div>`;\n\t}\n\n\t_formatMessageTime(timestamp) {\n\t\tif (!timestamp) return '';\n\t\tconst date = new Date(timestamp);\n\t\treturn date.toLocaleTimeString('en-US', {\n\t\t\thour: 'numeric',\n\t\t\tminute: '2-digit',\n\t\t\thour12: true,\n\t\t});\n\t}\n\n\t_formatMessageContent(content) {\n\t\tif (!content) return '';\n\t\t// Basic HTML escaping and line breaks\n\t\treturn content\n\t\t\t.replace(/&/g, '&')\n\t\t\t.replace(/</g, '<')\n\t\t\t.replace(/>/g, '>')\n\t\t\t.replace(/\\n/g, '<br>');\n\t}\n\n\t_appendMessage(message) {\n\t\tconst messagesContainer = this.element.querySelector(\n\t\t\t'.messenger-chat-messages'\n\t\t);\n\t\tconst emptyState = messagesContainer.querySelector('.messenger-chat-empty');\n\t\tif (emptyState) {\n\t\t\temptyState.remove();\n\t\t}\n\n\t\tconst messageHtml = this._renderMessage(message);\n\t\tconst tempDiv = document.createElement('div');\n\t\ttempDiv.innerHTML = messageHtml;\n\t\tmessagesContainer.appendChild(tempDiv.firstElementChild);\n\t}\n\n\t_scrollToBottom() {\n\t\tconst messagesContainer = this.element.querySelector(\n\t\t\t'.messenger-chat-messages'\n\t\t);\n\t\tif (messagesContainer) {\n\t\t\tsetTimeout(() => {\n\t\t\t\tmessagesContainer.scrollTop = messagesContainer.scrollHeight;\n\t\t\t}, 50);\n\t\t}\n\t}\n\n\t_attachEvents() {\n\t\t// Back button\n\t\tthis.element\n\t\t\t.querySelector('.messenger-back-btn')\n\t\t\t.addEventListener('click', () => {\n\t\t\t\tthis.state.setView('messages');\n\t\t\t});\n\n\t\t// Close button\n\t\tthis.element\n\t\t\t.querySelector('.messenger-close-btn')\n\t\t\t.addEventListener('click', () => {\n\t\t\t\tthis.state.setOpen(false);\n\t\t\t});\n\n\t\t// Compose input\n\t\tconst input = this.element.querySelector('.messenger-compose-input');\n\t\tconst sendBtn = this.element.querySelector('.messenger-compose-send');\n\n\t\tinput.addEventListener('input', () => {\n\t\t\t// Auto-resize textarea\n\t\t\tinput.style.height = 'auto';\n\t\t\tinput.style.height = Math.min(input.scrollHeight, 120) + 'px';\n\n\t\t\t// Enable/disable send button\n\t\t\tsendBtn.disabled = !input.value.trim();\n\n\t\t\t// Send typing indicator\n\t\t\tif (input.value.trim()) {\n\t\t\t\tthis._startTyping();\n\t\t\t}\n\t\t});\n\n\t\tinput.addEventListener('keydown', (e) => {\n\t\t\tif (e.key === 'Enter' && !e.shiftKey) {\n\t\t\t\te.preventDefault();\n\t\t\t\tthis._sendMessage();\n\t\t\t}\n\t\t});\n\n\t\tsendBtn.addEventListener('click', () => {\n\t\t\tthis._sendMessage();\n\t\t});\n\t}\n\n\t_sendMessage() {\n\t\tconst input = this.element.querySelector('.messenger-compose-input');\n\t\tconst content = input.value.trim();\n\n\t\tif (!content) return;\n\n\t\t// Stop typing indicator\n\t\tthis._stopTyping();\n\n\t\tconst isNewConversation = !this.state.activeConversationId;\n\n\t\tif (isNewConversation) {\n\t\t\t// Start a new conversation\n\t\t\tif (this.options.onStartConversation) {\n\t\t\t\tthis.options.onStartConversation(content);\n\t\t\t}\n\t\t} else {\n\t\t\t// Add message to existing conversation\n\t\t\tconst message = {\n\t\t\t\tid: 'msg_' + Date.now(),\n\t\t\t\tcontent: content,\n\t\t\t\tisOwn: true,\n\t\t\t\ttimestamp: new Date().toISOString(),\n\t\t\t};\n\n\t\t\tthis.state.addMessage(this.state.activeConversationId, message);\n\n\t\t\t// Emit event for API integration\n\t\t\tif (this.options.onSendMessage) {\n\t\t\t\tthis.options.onSendMessage(this.state.activeConversationId, message);\n\t\t\t}\n\t\t}\n\n\t\t// Clear input\n\t\tinput.value = '';\n\t\tinput.style.height = 'auto';\n\t\tthis.element.querySelector('.messenger-compose-send').disabled = true;\n\t}\n\n\t_startTyping() {\n\t\tif (!this._isTyping && this.state.activeConversationId) {\n\t\t\tthis._isTyping = true;\n\t\t\tif (this.options.onTyping) {\n\t\t\t\tthis.options.onTyping(this.state.activeConversationId, true);\n\t\t\t}\n\t\t}\n\n\t\t// Reset typing timeout\n\t\tif (this._typingTimeout) {\n\t\t\tclearTimeout(this._typingTimeout);\n\t\t}\n\t\tthis._typingTimeout = setTimeout(() => {\n\t\t\tthis._stopTyping();\n\t\t}, 3000);\n\t}\n\n\t_stopTyping() {\n\t\tif (this._isTyping && this.state.activeConversationId) {\n\t\t\tthis._isTyping = false;\n\t\t\tif (this.options.onTyping) {\n\t\t\t\tthis.options.onTyping(this.state.activeConversationId, false);\n\t\t\t}\n\t\t}\n\t\tif (this._typingTimeout) {\n\t\t\tclearTimeout(this._typingTimeout);\n\t\t\tthis._typingTimeout = null;\n\t\t}\n\t}\n\n\t_showTypingIndicator(userName) {\n\t\tif (this._typingIndicator) {\n\t\t\tthis._typingIndicator.style.display = 'flex';\n\t\t\tconst textEl = this._typingIndicator.querySelector('.messenger-typing-text');\n\t\t\tif (textEl) {\n\t\t\t\ttextEl.textContent = `${userName || 'Support'} is typing...`;\n\t\t\t}\n\t\t\tthis._scrollToBottom();\n\t\t}\n\t}\n\n\t_hideTypingIndicator() {\n\t\tif (this._typingIndicator) {\n\t\t\tthis._typingIndicator.style.display = 'none';\n\t\t}\n\t}\n\n\tdestroy() {\n\t\tif (this._unsubscribe) {\n\t\t\tthis._unsubscribe();\n\t\t}\n\t\tif (this._typingTimeout) {\n\t\t\tclearTimeout(this._typingTimeout);\n\t\t}\n\t\tthis._stopTyping();\n\t\tif (this.element && this.element.parentNode) {\n\t\t\tthis.element.parentNode.removeChild(this.element);\n\t\t}\n\t}\n}\n","/**\n * ConversationsView - Message thread list\n */\nexport class ConversationsView {\n\tconstructor(state, options = {}) {\n\t\tthis.state = state;\n\t\tthis.options = options;\n\t\tthis.element = null;\n\t\tthis._unsubscribe = null;\n\t}\n\n\trender() {\n\t\tthis.element = document.createElement('div');\n\t\tthis.element.className = 'messenger-view messenger-conversations-view';\n\n\t\tthis._updateContent();\n\t\tthis._attachEvents();\n\n\t\t// Subscribe to state changes\n\t\tthis._unsubscribe = this.state.subscribe((type) => {\n\t\t\tif (\n\t\t\t\ttype === 'conversationsUpdate' ||\n\t\t\t\ttype === 'conversationAdded' ||\n\t\t\t\ttype === 'conversationRead'\n\t\t\t) {\n\t\t\t\tthis._updateContent();\n\t\t\t}\n\t\t});\n\n\t\treturn this.element;\n\t}\n\n\t_updateContent() {\n\t\tconst conversations = this.state.conversations;\n\t\tconst avatarsHtml = this._renderAvatarStack();\n\n\t\tlet conversationsHtml;\n\t\tif (conversations.length === 0) {\n\t\t\tconversationsHtml = `\n\t\t\t\t<div class=\"messenger-conversations-empty\">\n\t\t\t\t\t<div class=\"messenger-conversations-empty-icon\">\n\t\t\t\t\t\t<i class=\"ph ph-chat\" style=\"font-size: 48px;\"></i>\n\t\t\t\t\t</div>\n\t\t\t\t\t<h3>No conversations yet</h3>\n\t\t\t\t\t<p>Start a new conversation with our team</p>\n\t\t\t\t</div>\n\t\t\t`;\n\t\t} else {\n\t\t\tconversationsHtml = `\n\t\t\t\t<div class=\"messenger-conversations-list\">\n\t\t\t\t\t${conversations.map((conv) => this._renderConversationItem(conv)).join('')}\n\t\t\t\t</div>\n\t\t\t`;\n\t\t}\n\n\t\tthis.element.innerHTML = `\n\t\t\t<div class=\"messenger-conversations-header\">\n\t\t\t\t<h2>Messages</h2>\n\t\t\t\t<button class=\"messenger-close-btn\" aria-label=\"Close\">\n\t\t\t\t\t<i class=\"ph ph-x\" style=\"font-size: 20px;\"></i>\n\t\t\t\t</button>\n\t\t\t</div>\n\n\t\t\t<div class=\"messenger-conversations-body\">\n\t\t\t\t${conversationsHtml}\n\t\t\t</div>\n\n\t\t\t<div class=\"messenger-conversations-footer\">\n\t\t\t\t<button class=\"messenger-new-message-btn\">\n\t\t\t\t\t<div class=\"messenger-new-message-avatars\">${avatarsHtml}</div>\n\t\t\t\t\t<span>Send us a message</span>\n\t\t\t\t\t<i class=\"ph ph-arrow-right\" style=\"font-size: 16px;\"></i>\n\t\t\t\t</button>\n\t\t\t</div>\n\t\t`;\n\n\t\tthis._attachEvents();\n\t}\n\n\t_renderConversationItem(conversation) {\n\t\tconst unreadClass = conversation.unread > 0 ? 'unread' : '';\n\t\tconst timeAgo = this._formatTimeAgo(conversation.lastMessageTime);\n\t\tconst avatarsHtml = this._renderConversationAvatars(\n\t\t\tconversation.participants\n\t\t);\n\n\t\treturn `\n\t\t\t<div class=\"messenger-conversation-item ${unreadClass}\" data-conversation-id=\"${conversation.id}\">\n\t\t\t\t<div class=\"messenger-conversation-avatars\">\n\t\t\t\t\t${avatarsHtml}\n\t\t\t\t</div>\n\t\t\t\t<div class=\"messenger-conversation-content\">\n\t\t\t\t\t<div class=\"messenger-conversation-header\">\n\t\t\t\t\t\t<span class=\"messenger-conversation-title\">${conversation.title || 'Chat with team'}</span>\n\t\t\t\t\t\t<span class=\"messenger-conversation-time\">${timeAgo}</span>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"messenger-conversation-preview\">\n\t\t\t\t\t\t${conversation.unread > 0 ? '<span class=\"messenger-unread-dot\"></span>' : ''}\n\t\t\t\t\t\t<span class=\"messenger-conversation-message\">${this._truncateMessage(conversation.lastMessage)}</span>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t`;\n\t}\n\n\t_renderConversationAvatars(participants) {\n\t\tif (!participants || participants.length === 0) {\n\t\t\treturn `<div class=\"messenger-avatar messenger-avatar-medium\" style=\"background: #5856d6;\">S</div>`;\n\t\t}\n\n\t\tconst p = participants[0];\n\t\tif (p.avatarUrl) {\n\t\t\treturn `<img class=\"messenger-avatar messenger-avatar-medium\" src=\"${p.avatarUrl}\" alt=\"${p.name}\" />`;\n\t\t}\n\t\treturn `<div class=\"messenger-avatar messenger-avatar-medium\" style=\"background: ${this._getAvatarColor(0)};\">${(p.name || 'S').charAt(0).toUpperCase()}</div>`;\n\t}\n\n\t_renderAvatarStack() {\n\t\tconst avatars = this.state.teamAvatars;\n\t\tif (!avatars || avatars.length === 0) {\n\t\t\treturn `\n\t\t\t\t<div class=\"messenger-avatar-stack messenger-avatar-stack-small\">\n\t\t\t\t\t<div class=\"messenger-avatar messenger-avatar-small\" style=\"background: #5856d6;\">S</div>\n\t\t\t\t\t<div class=\"messenger-avatar messenger-avatar-small\" style=\"background: #007aff;\">T</div>\n\t\t\t\t</div>\n\t\t\t`;\n\t\t}\n\n\t\tconst avatarItems = avatars\n\t\t\t.slice(0, 2)\n\t\t\t.map((avatar, i) => {\n\t\t\t\tif (typeof avatar === 'string' && avatar.startsWith('http')) {\n\t\t\t\t\treturn `<img class=\"messenger-avatar messenger-avatar-small\" src=\"${avatar}\" alt=\"Team member\" style=\"z-index: ${2 - i};\" />`;\n\t\t\t\t}\n\t\t\t\treturn `<div class=\"messenger-avatar messenger-avatar-small\" style=\"background: ${this._getAvatarColor(i)}; z-index: ${2 - i};\">${avatar.charAt(0).toUpperCase()}</div>`;\n\t\t\t})\n\t\t\t.join('');\n\n\t\treturn `<div class=\"messenger-avatar-stack messenger-avatar-stack-small\">${avatarItems}</div>`;\n\t}\n\n\t_getAvatarColor(index) {\n\t\tconst colors = ['#5856d6', '#007aff', '#34c759', '#ff9500', '#ff3b30'];\n\t\treturn colors[index % colors.length];\n\t}\n\n\t_formatTimeAgo(timestamp) {\n\t\tif (!timestamp) return '';\n\t\tconst date = new Date(timestamp);\n\t\tconst now = new Date();\n\t\tconst diffMs = now - date;\n\t\tconst diffMins = Math.floor(diffMs / 60000);\n\t\tconst diffHours = Math.floor(diffMs / 3600000);\n\t\tconst diffDays = Math.floor(diffMs / 86400000);\n\n\t\tif (diffMins < 1) return 'now';\n\t\tif (diffMins < 60) return `${diffMins}m`;\n\t\tif (diffHours < 24) return `${diffHours}h`;\n\t\tif (diffDays < 7) return `${diffDays}d`;\n\t\treturn date.toLocaleDateString('en-US', { month: 'short', day: 'numeric' });\n\t}\n\n\t_truncateMessage(message) {\n\t\tif (!message) return 'No messages yet';\n\t\tconst maxLength = 50;\n\t\tif (message.length <= maxLength) return message;\n\t\treturn message.substring(0, maxLength) + '...';\n\t}\n\n\t_attachEvents() {\n\t\t// Close button\n\t\tconst closeBtn = this.element.querySelector('.messenger-close-btn');\n\t\tif (closeBtn) {\n\t\t\tcloseBtn.addEventListener('click', () => {\n\t\t\t\tthis.state.setOpen(false);\n\t\t\t});\n\t\t}\n\n\t\t// Conversation items\n\t\tthis.element\n\t\t\t.querySelectorAll('.messenger-conversation-item')\n\t\t\t.forEach((item) => {\n\t\t\t\titem.addEventListener('click', () => {\n\t\t\t\t\tconst convId = item.dataset.conversationId;\n\t\t\t\t\tthis.state.setActiveConversation(convId);\n\t\t\t\t\tthis.state.markAsRead(convId);\n\t\t\t\t\tthis.state.setView('chat');\n\n\t\t\t\t\t// Notify widget to fetch messages\n\t\t\t\t\tif (this.options.onSelectConversation) {\n\t\t\t\t\t\tthis.options.onSelectConversation(convId);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t});\n\n\t\t// New message button\n\t\tconst newMsgBtn = this.element.querySelector('.messenger-new-message-btn');\n\t\tif (newMsgBtn) {\n\t\t\tnewMsgBtn.addEventListener('click', () => {\n\t\t\t\tthis._startNewConversation();\n\t\t\t});\n\t\t}\n\t}\n\n\t_startNewConversation() {\n\t\t// Set view to chat with no active conversation (new conversation mode)\n\t\tthis.state.setActiveConversation(null);\n\t\tthis.state.setView('chat');\n\n\t\t// Notify widget to handle new conversation flow\n\t\tif (this.options.onStartNewConversation) {\n\t\t\tthis.options.onStartNewConversation();\n\t\t}\n\t}\n\n\tdestroy() {\n\t\tif (this._unsubscribe) {\n\t\t\tthis._unsubscribe();\n\t\t}\n\t\tif (this.element && this.element.parentNode) {\n\t\t\tthis.element.parentNode.removeChild(this.element);\n\t\t}\n\t}\n}\n","/**\n * HelpView - Help collections browse with Intercom-style design\n */\nexport class HelpView {\n\tconstructor(state, options = {}) {\n\t\tthis.state = state;\n\t\tthis.options = options;\n\t\tthis.element = null;\n\t\tthis._unsubscribe = null;\n\t}\n\n\trender() {\n\t\tthis.element = document.createElement('div');\n\t\tthis.element.className = 'messenger-view messenger-help-view';\n\n\t\tthis._updateContent();\n\n\t\t// Subscribe to state changes\n\t\tthis._unsubscribe = this.state.subscribe((type) => {\n\t\t\tif (type === 'helpArticlesUpdate' || type === 'helpSearchChange') {\n\t\t\t\tthis._updateCollectionsList();\n\t\t\t}\n\t\t});\n\n\t\treturn this.element;\n\t}\n\n\t_updateContent() {\n\t\tconst searchQuery = this.state.helpSearchQuery || '';\n\t\tconst collections = this.state.helpArticles || [];\n\t\tconst collectionCount = collections.length;\n\n\t\tthis.element.innerHTML = `\n\t\t\t<div class=\"messenger-help-header\">\n\t\t\t\t<h2>Help</h2>\n\t\t\t\t<button class=\"messenger-close-btn\" aria-label=\"Close\">\n\t\t\t\t\t<i class=\"ph ph-x\" style=\"font-size: 20px;\"></i>\n\t\t\t\t</button>\n\t\t\t</div>\n\n\t\t\t<div class=\"messenger-help-search\">\n\t\t\t\t<div class=\"messenger-help-search-wrapper\">\n\t\t\t\t\t<input\n\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\tclass=\"messenger-help-search-input\"\n\t\t\t\t\t\tplaceholder=\"Search for help\"\n\t\t\t\t\t\tvalue=\"${searchQuery}\"\n\t\t\t\t\t/>\n\t\t\t\t\t<i class=\"ph ph-magnifying-glass messenger-help-search-icon\" style=\"font-size: 18px;\"></i>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t<div class=\"messenger-help-body\">\n\t\t\t\t<div class=\"messenger-help-collections-header\">\n\t\t\t\t\t${collectionCount} collections\n\t\t\t\t</div>\n\t\t\t\t<div class=\"messenger-help-collections\"></div>\n\t\t\t</div>\n\t\t`;\n\n\t\tthis._updateCollectionsList();\n\t\tthis._attachEvents();\n\t}\n\n\t_updateCollectionsList() {\n\t\tconst collectionsContainer = this.element.querySelector(\n\t\t\t'.messenger-help-collections'\n\t\t);\n\t\tconst collections = this.state.helpArticles || [];\n\t\tconst searchQuery = (this.state.helpSearchQuery || '').toLowerCase();\n\n\t\t// Filter collections by search\n\t\tconst filteredCollections = searchQuery\n\t\t\t? collections.filter(\n\t\t\t\t\t(c) =>\n\t\t\t\t\t\tc.title.toLowerCase().includes(searchQuery) ||\n\t\t\t\t\t\t(c.description && c.description.toLowerCase().includes(searchQuery))\n\t\t\t\t)\n\t\t\t: collections;\n\n\t\t// Update collection count\n\t\tconst headerEl = this.element.querySelector(\n\t\t\t'.messenger-help-collections-header'\n\t\t);\n\t\tif (headerEl) {\n\t\t\theaderEl.textContent = `${filteredCollections.length} collections`;\n\t\t}\n\n\t\tif (filteredCollections.length === 0) {\n\t\t\tcollectionsContainer.innerHTML = this._renderEmptyState();\n\t\t\treturn;\n\t\t}\n\n\t\tcollectionsContainer.innerHTML = filteredCollections\n\t\t\t.map((collection) => this._renderCollectionItem(collection))\n\t\t\t.join('');\n\n\t\t// Attach click events\n\t\tthis._attachCollectionEvents();\n\t}\n\n\t_renderCollectionItem(collection) {\n\t\tconst articleCount = collection.articleCount || 0;\n\t\treturn `\n\t\t\t<div class=\"messenger-help-collection\" data-collection-id=\"${collection.id}\">\n\t\t\t\t<div class=\"messenger-help-collection-content\">\n\t\t\t\t\t<h3 class=\"messenger-help-collection-title\">${collection.title}</h3>\n\t\t\t\t\t<p class=\"messenger-help-collection-desc\">${collection.description || ''}</p>\n\t\t\t\t\t<span class=\"messenger-help-collection-count\">${articleCount} articles</span>\n\t\t\t\t</div>\n\t\t\t\t<i class=\"ph ph-caret-right messenger-help-collection-arrow\" style=\"font-size: 20px;\"></i>\n\t\t\t</div>\n\t\t`;\n\t}\n\n\t_renderEmptyState() {\n\t\tconst isSearching = this.state.helpSearchQuery;\n\n\t\tif (isSearching) {\n\t\t\treturn `\n\t\t\t\t<div class=\"messenger-help-empty\">\n\t\t\t\t\t<div class=\"messenger-help-empty-icon\">\n\t\t\t\t\t\t<i class=\"ph ph-magnifying-glass\" style=\"font-size: 48px;\"></i>\n\t\t\t\t\t</div>\n\t\t\t\t\t<h3>No results found</h3>\n\t\t\t\t\t<p>Try a different search term</p>\n\t\t\t\t</div>\n\t\t\t`;\n\t\t}\n\n\t\treturn `\n\t\t\t<div class=\"messenger-help-empty\">\n\t\t\t\t<div class=\"messenger-help-empty-icon\">\n\t\t\t\t\t<i class=\"ph ph-question\" style=\"font-size: 48px;\"></i>\n\t\t\t\t</div>\n\t\t\t\t<h3>Help collections</h3>\n\t\t\t\t<p>No collections available yet</p>\n\t\t\t</div>\n\t\t`;\n\t}\n\n\t_attachEvents() {\n\t\t// Close button\n\t\tthis.element\n\t\t\t.querySelector('.messenger-close-btn')\n\t\t\t.addEventListener('click', () => {\n\t\t\t\tthis.state.setOpen(false);\n\t\t\t});\n\n\t\t// Search input\n\t\tconst searchInput = this.element.querySelector(\n\t\t\t'.messenger-help-search-input'\n\t\t);\n\t\tlet searchTimeout;\n\t\tsearchInput.addEventListener('input', (e) => {\n\t\t\tclearTimeout(searchTimeout);\n\t\t\tsearchTimeout = setTimeout(() => {\n\t\t\t\tthis.state.setHelpSearchQuery(e.target.value);\n\t\t\t}, 300);\n\t\t});\n\n\t\tthis._attachCollectionEvents();\n\t}\n\n\t_attachCollectionEvents() {\n\t\tthis.element\n\t\t\t.querySelectorAll('.messenger-help-collection')\n\t\t\t.forEach((item) => {\n\t\t\t\titem.addEventListener('click', () => {\n\t\t\t\t\tconst collectionId = item.dataset.collectionId;\n\t\t\t\t\tconst collection = this.state.helpArticles.find(\n\t\t\t\t\t\t(c) => c.id === collectionId\n\t\t\t\t\t);\n\t\t\t\t\tif (collection && collection.url) {\n\t\t\t\t\t\twindow.open(collection.url, '_blank');\n\t\t\t\t\t} else if (this.options.onArticleClick) {\n\t\t\t\t\t\tthis.options.onArticleClick(collection);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t});\n\t}\n\n\tdestroy() {\n\t\tif (this._unsubscribe) {\n\t\t\tthis._unsubscribe();\n\t\t}\n\t\tif (this.element && this.element.parentNode) {\n\t\t\tthis.element.parentNode.removeChild(this.element);\n\t\t}\n\t}\n}\n","/**\n * HomeView - Welcome screen with team info and quick actions\n */\nexport class HomeView {\n\tconstructor(state, options = {}) {\n\t\tthis.state = state;\n\t\tthis.options = options;\n\t\tthis.element = null;\n\t\tthis._unsubscribe = null;\n\t}\n\n\trender() {\n\t\tthis.element = document.createElement('div');\n\t\tthis.element.className = 'messenger-view messenger-home-view';\n\n\t\tthis._updateContent();\n\n\t\t// Subscribe to state changes to re-render when data loads\n\t\tthis._unsubscribe = this.state.subscribe((type) => {\n\t\t\tif (type === 'homeChangelogUpdate' || type === 'conversationsUpdate' || type === 'availabilityUpdate') {\n\t\t\t\tthis._updateContent();\n\t\t\t}\n\t\t});\n\n\t\treturn this.element;\n\t}\n\n\t_updateContent() {\n\t\tconst avatarsHtml = this._renderAvatarStack();\n\t\tconst recentChangelogHtml = this._renderRecentChangelog();\n\n\t\tthis.element.innerHTML = `\n\t\t\t<div class=\"messenger-home-header\">\n\t\t\t\t<div class=\"messenger-home-header-top\">\n\t\t\t\t\t<div class=\"messenger-home-logo\">\n\t\t\t\t\t\t${this.options.logoUrl ? `<img src=\"${this.options.logoUrl}\" alt=\"${this.state.teamName}\" />` : ''}\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"messenger-home-avatars\">${avatarsHtml}</div>\n\t\t\t\t\t<button class=\"messenger-close-btn\" aria-label=\"Close\">\n\t\t\t\t\t\t<i class=\"ph ph-x\" style=\"font-size: 20px;\"></i>\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"messenger-home-welcome\">\n\t\t\t\t\t<span class=\"messenger-home-greeting\">Hello there.</span>\n\t\t\t\t\t<span class=\"messenger-home-question\">${this.state.welcomeMessage}</span>\n\t\t\t\t\t${this._renderAvailabilityStatus()}\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t<div class=\"messenger-home-body\">\n\t\t\t\t<button class=\"messenger-home-message-btn\">\n\t\t\t\t\t<span>Send us a message</span>\n\t\t\t\t\t<i class=\"ph ph-arrow-right\" style=\"font-size: 16px;\"></i>\n\t\t\t\t</button>\n\n\t\t\t\t${this._renderFeaturedCard()}\n\n\t\t\t\t${recentChangelogHtml}\n\t\t\t</div>\n\t\t`;\n\n\t\tthis._attachEvents();\n\t}\n\n\t_renderAvatarStack() {\n\t\tconst avatars = this.state.teamAvatars;\n\t\tif (!avatars || avatars.length === 0) {\n\t\t\t// Default avatars with initials\n\t\t\treturn `\n\t\t\t\t<div class=\"messenger-avatar-stack\">\n\t\t\t\t\t<div class=\"messenger-avatar\" style=\"background: #5856d6;\">S</div>\n\t\t\t\t\t<div class=\"messenger-avatar\" style=\"background: #007aff;\">T</div>\n\t\t\t\t</div>\n\t\t\t`;\n\t\t}\n\n\t\tconst avatarItems = avatars\n\t\t\t.slice(0, 3)\n\t\t\t.map((avatar, i) => {\n\t\t\t\tif (typeof avatar === 'string' && avatar.startsWith('http')) {\n\t\t\t\t\treturn `<img class=\"messenger-avatar\" src=\"${avatar}\" alt=\"Team member\" style=\"z-index: ${3 - i};\" />`;\n\t\t\t\t}\n\t\t\t\treturn `<div class=\"messenger-avatar\" style=\"background: ${this._getAvatarColor(i)}; z-index: ${3 - i};\">${avatar.charAt(0).toUpperCase()}</div>`;\n\t\t\t})\n\t\t\t.join('');\n\n\t\treturn `<div class=\"messenger-avatar-stack\">${avatarItems}</div>`;\n\t}\n\n\t_getAvatarColor(index) {\n\t\tconst colors = ['#5856d6', '#007aff', '#34c759', '#ff9500', '#ff3b30'];\n\t\treturn colors[index % colors.length];\n\t}\n\n\t_renderAvailabilityStatus() {\n\t\tconst isOnline = this.state.agentsOnline;\n\t\tconst responseTime = this.state.responseTime || 'We typically reply within a few minutes';\n\n\t\tif (isOnline) {\n\t\t\treturn `\n\t\t\t\t<div class=\"messenger-home-availability\">\n\t\t\t\t\t<span class=\"messenger-availability-dot messenger-availability-online\"></span>\n\t\t\t\t\t<span class=\"messenger-availability-text\">We're online now</span>\n\t\t\t\t</div>\n\t\t\t`;\n\t\t}\n\n\t\treturn `\n\t\t\t<div class=\"messenger-home-availability\">\n\t\t\t\t<span class=\"messenger-availability-dot messenger-availability-away\"></span>\n\t\t\t\t<span class=\"messenger-availability-text\">${responseTime}</span>\n\t\t\t</div>\n\t\t`;\n\t}\n\n\t_renderFeaturedCard() {\n\t\t// Only show if there's featured content configured\n\t\tif (!this.options.featuredContent) {\n\t\t\treturn '';\n\t\t}\n\n\t\tconst { title, description, imageUrl, action } =\n\t\t\tthis.options.featuredContent;\n\n\t\treturn `\n\t\t\t<div class=\"messenger-home-featured\">\n\t\t\t\t${imageUrl ? `<img src=\"${imageUrl}\" alt=\"${title}\" class=\"messenger-home-featured-image\" onerror=\"this.style.display='none';\" />` : ''}\n\t\t\t\t<div class=\"messenger-home-featured-content\">\n\t\t\t\t\t<h3>${title}</h3>\n\t\t\t\t\t<p>${description}</p>\n\t\t\t\t</div>\n\t\t\t\t${action ? `<button class=\"messenger-home-featured-btn\" data-action=\"${action.type}\" data-value=\"${action.value}\">${action.label}</button>` : ''}\n\t\t\t</div>\n\t\t`;\n\t}\n\n\t_renderRecentChangelog() {\n\t\t// Show recent changelog preview as cards with images\n\t\tconst changelogItems = this.state.homeChangelogItems;\n\t\tif (changelogItems.length === 0) {\n\t\t\treturn '';\n\t\t}\n\n\t\tconst changelogHtml = changelogItems\n\t\t\t.map(\n\t\t\t\t(item) => `\n\t\t\t<div class=\"messenger-home-changelog-card\" data-changelog-id=\"${item.id}\">\n\t\t\t\t${\n\t\t\t\t\titem.coverImage\n\t\t\t\t\t\t? `\n\t\t\t\t\t<div class=\"messenger-home-changelog-cover\">\n\t\t\t\t\t\t<img src=\"${item.coverImage}\" alt=\"${item.title}\" onerror=\"this.style.display='none';\" />\n\t\t\t\t\t\t${item.coverText ? `<span class=\"messenger-home-changelog-cover-text\">${item.coverText}</span>` : ''}\n\t\t\t\t\t</div>\n\t\t\t\t`\n\t\t\t\t\t\t: ''\n\t\t\t\t}\n\t\t\t\t<div class=\"messenger-home-changelog-card-content\">\n\t\t\t\t\t<h4 class=\"messenger-home-changelog-card-title\">${item.title}</h4>\n\t\t\t\t\t<p class=\"messenger-home-changelog-card-desc\">${item.description || ''}</p>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t`\n\t\t\t)\n\t\t\t.join('');\n\n\t\treturn `\n\t\t\t<div class=\"messenger-home-changelog-section\">\n\t\t\t\t${changelogHtml}\n\t\t\t</div>\n\t\t`;\n\t}\n\n\t_formatDate(dateString) {\n\t\tif (!dateString) return '';\n\t\tconst date = new Date(dateString);\n\t\tconst now = new Date();\n\t\tconst diffDays = Math.floor((now - date) / (1000 * 60 * 60 * 24));\n\n\t\tif (diffDays === 0) return 'Today';\n\t\tif (diffDays === 1) return 'Yesterday';\n\t\tif (diffDays < 7) return `${diffDays}d ago`;\n\t\treturn date.toLocaleDateString('en-US', { month: 'short', day: 'numeric' });\n\t}\n\n\t_attachEvents() {\n\t\t// Close button\n\t\tthis.element\n\t\t\t.querySelector('.messenger-close-btn')\n\t\t\t.addEventListener('click', () => {\n\t\t\t\tthis.state.setOpen(false);\n\t\t\t});\n\n\t\t// Send message button\n\t\tthis.element\n\t\t\t.querySelector('.messenger-home-message-btn')\n\t\t\t.addEventListener('click', () => {\n\t\t\t\tthis.state.setView('messages');\n\t\t\t});\n\n\t\t// Changelog items\n\t\tthis.element\n\t\t\t.querySelectorAll('.messenger-home-changelog-item')\n\t\t\t.forEach((item) => {\n\t\t\t\titem.addEventListener('click', () => {\n\t\t\t\t\t// Navigate to changelog view with specific item selected\n\t\t\t\t\tthis.state.setView('changelog');\n\t\t\t\t});\n\t\t\t});\n\n\t\t// See all changelog\n\t\tconst seeAllBtn = this.element.querySelector(\n\t\t\t'.messenger-home-changelog-all'\n\t\t);\n\t\tif (seeAllBtn) {\n\t\t\tseeAllBtn.addEventListener('click', () => {\n\t\t\t\tthis.state.setView('changelog');\n\t\t\t});\n\t\t}\n\n\t\t// Featured card action\n\t\tconst featuredBtn = this.element.querySelector(\n\t\t\t'.messenger-home-featured-btn'\n\t\t);\n\t\tif (featuredBtn) {\n\t\t\tfeaturedBtn.addEventListener('click', () => {\n\t\t\t\tconst action = featuredBtn.dataset.action;\n\t\t\t\tconst value = featuredBtn.dataset.value;\n\t\t\t\tif (action === 'url') {\n\t\t\t\t\twindow.open(value, '_blank');\n\t\t\t\t} else if (action === 'view') {\n\t\t\t\t\tthis.state.setView(value);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\n\tdestroy() {\n\t\tif (this._unsubscribe) {\n\t\t\tthis._unsubscribe();\n\t\t}\n\t\tif (this.element && this.element.parentNode) {\n\t\t\tthis.element.parentNode.removeChild(this.element);\n\t\t}\n\t}\n}\n","/**\n * WebSocketService - Real-time communication for messenger widget\n */\n\nexport class WebSocketService {\n\tconstructor(config = {}) {\n\t\tthis.baseURL = config.baseURL || '';\n\t\tthis.workspace = config.workspace || '';\n\t\tthis.sessionToken = config.sessionToken || null;\n\t\tthis.mock = config.mock || false;\n\n\t\tthis.ws = null;\n\t\tthis.reconnectAttempts = 0;\n\t\tthis.maxReconnectAttempts = 5;\n\t\tthis.reconnectDelay = 1000;\n\t\tthis.pingInterval = null;\n\t\tthis.isConnected = false;\n\n\t\t// Event listeners\n\t\tthis._listeners = new Map();\n\n\t\t// Bind methods\n\t\tthis._onOpen = this._onOpen.bind(this);\n\t\tthis._onMessage = this._onMessage.bind(this);\n\t\tthis._onClose = this._onClose.bind(this);\n\t\tthis._onError = this._onError.bind(this);\n\t}\n\n\t/**\n\t * Connect to WebSocket server\n\t */\n\tconnect(sessionToken = null) {\n\t\tif (sessionToken) {\n\t\t\tthis.sessionToken = sessionToken;\n\t\t}\n\n\t\tif (!this.sessionToken) {\n\t\t\tconsole.warn('[WebSocket] No session token provided');\n\t\t\treturn;\n\t\t}\n\n\t\t// Mock mode - simulate connection\n\t\tif (this.mock) {\n\t\t\tthis.isConnected = true;\n\t\t\tthis._emit('connected', {});\n\t\t\tthis._startMockResponses();\n\t\t\treturn;\n\t\t}\n\n\t\t// Build WebSocket URL\n\t\tconst wsProtocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';\n\t\tlet wsURL = this.baseURL.replace(/^https?:/, wsProtocol);\n\t\twsURL = wsURL.replace('/api/v1', '');\n\t\twsURL = `${wsURL}/api/v1/widget/messenger/ws?token=${encodeURIComponent(this.sessionToken)}`;\n\n\t\ttry {\n\t\t\tthis.ws = new WebSocket(wsURL);\n\t\t\tthis.ws.onopen = this._onOpen;\n\t\t\tthis.ws.onmessage = this._onMessage;\n\t\t\tthis.ws.onclose = this._onClose;\n\t\t\tthis.ws.onerror = this._onError;\n\t\t} catch (error) {\n\t\t\tconsole.error('[WebSocket] Connection error:', error);\n\t\t\tthis._scheduleReconnect();\n\t\t}\n\t}\n\n\t/**\n\t * Disconnect from WebSocket server\n\t */\n\tdisconnect() {\n\t\tthis.isConnected = false;\n\t\tthis.reconnectAttempts = this.maxReconnectAttempts; // Prevent reconnection\n\n\t\tif (this.pingInterval) {\n\t\t\tclearInterval(this.pingInterval);\n\t\t\tthis.pingInterval = null;\n\t\t}\n\n\t\tif (this.ws) {\n\t\t\tthis.ws.close();\n\t\t\tthis.ws = null;\n\t\t}\n\n\t\tif (this._mockInterval) {\n\t\t\tclearInterval(this._mockInterval);\n\t\t\tthis._mockInterval = null;\n\t\t}\n\t}\n\n\t/**\n\t * Subscribe to events\n\t * @param {string} event - Event name\n\t * @param {Function} callback - Event handler\n\t * @returns {Function} Unsubscribe function\n\t */\n\ton(event, callback) {\n\t\tif (!this._listeners.has(event)) {\n\t\t\tthis._listeners.set(event, new Set());\n\t\t}\n\t\tthis._listeners.get(event).add(callback);\n\t\treturn () => this._listeners.get(event).delete(callback);\n\t}\n\n\t/**\n\t * Remove event listener\n\t */\n\toff(event, callback) {\n\t\tif (this._listeners.has(event)) {\n\t\t\tthis._listeners.get(event).delete(callback);\n\t\t}\n\t}\n\n\t/**\n\t * Send message through WebSocket\n\t */\n\tsend(type, payload = {}) {\n\t\tif (!this.isConnected) {\n\t\t\tconsole.warn('[WebSocket] Not connected, cannot send message');\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.mock) {\n\t\t\t// Mock mode - just log\n\t\t\tconsole.log('[WebSocket Mock] Sending:', type, payload);\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.ws && this.ws.readyState === WebSocket.OPEN) {\n\t\t\tthis.ws.send(JSON.stringify({ type, payload }));\n\t\t}\n\t}\n\n\t// Private methods\n\n\t_onOpen() {\n\t\tconsole.log('[WebSocket] Connected');\n\t\tthis.isConnected = true;\n\t\tthis.reconnectAttempts = 0;\n\t\tthis._emit('connected', {});\n\n\t\t// Start ping interval to keep connection alive\n\t\tthis.pingInterval = setInterval(() => {\n\t\t\tthis.send('ping', {});\n\t\t}, 30000);\n\t}\n\n\t_onMessage(event) {\n\t\ttry {\n\t\t\tconst data = JSON.parse(event.data);\n\t\t\tconst { type, payload } = data;\n\n\t\t\t// Handle different event types\n\t\t\tswitch (type) {\n\t\t\t\tcase 'message:new':\n\t\t\t\t\tthis._emit('message', payload);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'typing:started':\n\t\t\t\t\tthis._emit('typing_started', payload);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'typing:stopped':\n\t\t\t\t\tthis._emit('typing_stopped', payload);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'conversation:updated':\n\t\t\t\t\tthis._emit('conversation_updated', payload);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'conversation:closed':\n\t\t\t\t\tthis._emit('conversation_closed', payload);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'availability:changed':\n\t\t\t\t\tthis._emit('availability_changed', payload);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'pong':\n\t\t\t\t\t// Ping response, ignore\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tconsole.log('[WebSocket] Unknown event:', type, payload);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconsole.error('[WebSocket] Failed to parse message:', error);\n\t\t}\n\t}\n\n\t_onClose(event) {\n\t\tconsole.log('[WebSocket] Disconnected:', event.code, event.reason);\n\t\tthis.isConnected = false;\n\n\t\tif (this.pingInterval) {\n\t\t\tclearInterval(this.pingInterval);\n\t\t\tthis.pingInterval = null;\n\t\t}\n\n\t\tthis._emit('disconnected', { code: event.code, reason: event.reason });\n\t\tthis._scheduleReconnect();\n\t}\n\n\t_onError(error) {\n\t\tconsole.error('[WebSocket] Error:', error);\n\t\tthis._emit('error', { error });\n\t}\n\n\t_scheduleReconnect() {\n\t\tif (this.reconnectAttempts >= this.maxReconnectAttempts) {\n\t\t\tconsole.log('[WebSocket] Max reconnect attempts reached');\n\t\t\tthis._emit('reconnect_failed', {});\n\t\t\treturn;\n\t\t}\n\n\t\tthis.reconnectAttempts++;\n\t\tconst delay = this.reconnectDelay * Math.pow(2, this.reconnectAttempts - 1);\n\t\tconsole.log(`[WebSocket] Reconnecting in ${delay}ms (attempt ${this.reconnectAttempts})`);\n\n\t\tsetTimeout(() => {\n\t\t\tthis.connect();\n\t\t}, delay);\n\t}\n\n\t_emit(event, data) {\n\t\tif (this._listeners.has(event)) {\n\t\t\tthis._listeners.get(event).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(`[WebSocket] Error in ${event} handler:`, error);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\n\t// Mock support for development\n\t_startMockResponses() {\n\t\t// Simulate agent typing and responses\n\t\tthis._mockInterval = setInterval(() => {\n\t\t\t// Randomly emit typing or message events for demo\n\t\t\tconst random = Math.random();\n\t\t\tif (random < 0.1) {\n\t\t\t\tthis._emit('typing_started', {\n\t\t\t\t\tconversation_id: 'conv_1',\n\t\t\t\t\tuser_id: 'agent_1',\n\t\t\t\t\tuser_name: 'Sarah',\n\t\t\t\t\tis_agent: true,\n\t\t\t\t});\n\n\t\t\t\t// Stop typing after 2 seconds\n\t\t\t\tsetTimeout(() => {\n\t\t\t\t\tthis._emit('typing_stopped', {\n\t\t\t\t\t\tconversation_id: 'conv_1',\n\t\t\t\t\t\tuser_id: 'agent_1',\n\t\t\t\t\t});\n\t\t\t\t}, 2000);\n\t\t\t}\n\t\t}, 10000);\n\t}\n\n\t/**\n\t * Simulate receiving a message (for mock mode)\n\t */\n\tsimulateMessage(conversationId, message) {\n\t\tif (this.mock) {\n\t\t\tthis._emit('message', {\n\t\t\t\tconversation_id: conversationId,\n\t\t\t\tmessage: {\n\t\t\t\t\tid: 'msg_' + Date.now(),\n\t\t\t\t\tcontent: message.content,\n\t\t\t\t\tsender_type: message.sender_type || 'agent',\n\t\t\t\t\tsender_name: message.sender_name || 'Support',\n\t\t\t\t\tsender_avatar: message.sender_avatar || null,\n\t\t\t\t\tcreated_at: new Date().toISOString(),\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\t}\n}\n","/**\n * MessengerWidget - Full-featured Messenger/Chat widget\n */\nimport { BaseWidget } from './BaseWidget.js';\nimport { MessengerState } from './messenger/MessengerState.js';\nimport { MessengerLauncher } from './messenger/components/MessengerLauncher.js';\nimport { MessengerPanel } from './messenger/components/MessengerPanel.js';\nimport { ChangelogView } from './messenger/views/ChangelogView.js';\nimport { ChatView } from './messenger/views/ChatView.js';\nimport { ConversationsView } from './messenger/views/ConversationsView.js';\nimport { HelpView } from './messenger/views/HelpView.js';\nimport { HomeView } from './messenger/views/HomeView.js';\nimport { WebSocketService } from '../core/WebSocketService.js';\n\nexport class MessengerWidget extends BaseWidget {\n\tconstructor(options) {\n\t\tsuper({ ...options, type: 'messenger' });\n\n\t\tthis.messengerOptions = {\n\t\t\tposition: options.position || 'bottom-right',\n\t\t\ttheme: options.theme || 'light',\n\t\t\tteamName: options.teamName || 'Support',\n\t\t\tteamAvatars: options.teamAvatars || [],\n\t\t\twelcomeMessage: options.welcomeMessage || 'How can we help?',\n\t\t\tenableHelp: options.enableHelp !== false,\n\t\t\tenableChangelog: options.enableChangelog !== false,\n\t\t\tlogoUrl: options.logoUrl || 'https://feedback-sdk.product7.io/p7.png',\n\t\t\tfeaturedContent: options.featuredContent || null,\n\t\t\tprimaryColor: options.primaryColor || '#1c1c1e',\n\t\t\t// Callbacks\n\t\t\tonSendMessage: options.onSendMessage || null,\n\t\t\tonArticleClick: options.onArticleClick || null,\n\t\t\tonChangelogClick: options.onChangelogClick || null,\n\t\t};\n\n\t\t// Create state\n\t\tthis.messengerState = new MessengerState({\n\t\t\tteamName: this.messengerOptions.teamName,\n\t\t\tteamAvatars: this.messengerOptions.teamAvatars,\n\t\t\twelcomeMessage: this.messengerOptions.welcomeMessage,\n\t\t\tenableHelp: this.messengerOptions.enableHelp,\n\t\t\tenableChangelog: this.messengerOptions.enableChangelog,\n\t\t\tuserContext: this.sdk?.apiService?.getUserContext() || null,\n\t\t});\n\n\t\tthis.launcher = null;\n\t\tthis.panel = null;\n\t\tthis.wsService = null;\n\t\tthis._wsUnsubscribers = [];\n\n\t\t// Bind methods\n\t\tthis._handleOpenChange = this._handleOpenChange.bind(this);\n\t\tthis._handleWebSocketMessage = this._handleWebSocketMessage.bind(this);\n\t\tthis._handleTypingStarted = this._handleTypingStarted.bind(this);\n\t\tthis._handleTypingStopped = this._handleTypingStopped.bind(this);\n\t}\n\n\t_render() {\n\t\t// Create container\n\t\tconst container = document.createElement('div');\n\t\tcontainer.className = `messenger-widget theme-${this.messengerOptions.theme}`;\n\t\tcontainer.style.zIndex = '999999';\n\n\t\t// Create launcher\n\t\tthis.launcher = new MessengerLauncher(this.messengerState, {\n\t\t\tposition: this.messengerOptions.position,\n\t\t\tprimaryColor: this.messengerOptions.primaryColor,\n\t\t});\n\t\tcontainer.appendChild(this.launcher.render());\n\n\t\t// Create panel with all callbacks\n\t\tthis.panel = new MessengerPanel(this.messengerState, {\n\t\t\tposition: this.messengerOptions.position,\n\t\t\ttheme: this.messengerOptions.theme,\n\t\t\tprimaryColor: this.messengerOptions.primaryColor,\n\t\t\tlogoUrl: this.messengerOptions.logoUrl,\n\t\t\tfeaturedContent: this.messengerOptions.featuredContent,\n\t\t\t// Chat callbacks\n\t\t\tonSendMessage:\n\t\t\t\tthis.messengerOptions.onSendMessage ||\n\t\t\t\tthis._handleSendMessage.bind(this),\n\t\t\tonStartConversation: this._handleStartConversation.bind(this),\n\t\t\tonTyping: this.sendTypingIndicator.bind(this),\n\t\t\t// Conversation list callbacks\n\t\t\tonSelectConversation: this._handleSelectConversation.bind(this),\n\t\t\tonStartNewConversation: this._handleNewConversationClick.bind(this),\n\t\t\t// Article/changelog callbacks\n\t\t\tonArticleClick: this.messengerOptions.onArticleClick,\n\t\t\tonChangelogClick: this.messengerOptions.onChangelogClick,\n\t\t});\n\n\t\t// Register views\n\t\tthis.panel.registerView('home', HomeView);\n\t\tthis.panel.registerView('messages', ConversationsView);\n\t\tthis.panel.registerView('chat', ChatView);\n\t\tthis.panel.registerView('help', HelpView);\n\t\tthis.panel.registerView('changelog', ChangelogView);\n\n\t\tcontainer.appendChild(this.panel.render());\n\t\tthis.panel.hide();\n\n\t\treturn container;\n\t}\n\n\t_attachEvents() {\n\t\t// Subscribe to state changes\n\t\tthis._stateUnsubscribe = this.messengerState.subscribe((type, data) => {\n\t\t\tif (type === 'openChange') {\n\t\t\t\tthis._handleOpenChange(data.isOpen);\n\t\t\t}\n\t\t});\n\t}\n\n\t_handleOpenChange(isOpen) {\n\t\tif (isOpen) {\n\t\t\tthis.panel.show();\n\t\t\tthis.sdk.eventBus.emit('messenger:opened', { widget: this });\n\t\t} else {\n\t\t\tthis.panel.hide();\n\t\t\tthis.messengerState.reset();\n\t\t\tthis.sdk.eventBus.emit('messenger:closed', { widget: this });\n\t\t}\n\t}\n\n\t/**\n\t * Handle starting a new conversation\n\t */\n\tasync _handleStartConversation(messageContent) {\n\t\ttry {\n\t\t\tawait this.startNewConversation(messageContent);\n\t\t} catch (error) {\n\t\t\tconsole.error('[MessengerWidget] Failed to start conversation:', error);\n\t\t}\n\t}\n\n\t/**\n\t * Handle selecting a conversation from the list\n\t */\n\tasync _handleSelectConversation(conversationId) {\n\t\ttry {\n\t\t\tawait this.fetchMessages(conversationId);\n\t\t} catch (error) {\n\t\t\tconsole.error('[MessengerWidget] Failed to fetch messages:', error);\n\t\t}\n\t}\n\n\t/**\n\t * Handle clicking \"new conversation\" button\n\t */\n\t_handleNewConversationClick() {\n\t\t// View is already changed by ConversationsView\n\t\t// This is for any additional setup needed\n\t}\n\n\tasync _handleSendMessage(conversationId, message) {\n\t\t// Emit event for external listeners\n\t\tthis.sdk.eventBus.emit('messenger:messageSent', {\n\t\t\twidget: this,\n\t\t\tconversationId,\n\t\t\tmessage,\n\t\t});\n\n\t\ttry {\n\t\t\t// Send message through API\n\t\t\tconst response = await this.apiService.sendMessage(conversationId, {\n\t\t\t\tcontent: message.content,\n\t\t\t});\n\n\t\t\tif (response.status && response.data) {\n\t\t\t\t// Update the message ID with server-assigned ID\n\t\t\t\t// Message is already added to state optimistically in ChatView\n\t\t\t\tconsole.log('[MessengerWidget] Message sent:', response.data.id);\n\t\t\t}\n\n\t\t\t// In mock mode, simulate an agent response after a delay\n\t\t\tif (this.apiService?.mock) {\n\t\t\t\tsetTimeout(() => {\n\t\t\t\t\tconst mockResponse = {\n\t\t\t\t\t\tid: 'msg_' + Date.now(),\n\t\t\t\t\t\tcontent: \"Thanks for your message! We'll get back to you soon.\",\n\t\t\t\t\t\tisOwn: false,\n\t\t\t\t\t\ttimestamp: new Date().toISOString(),\n\t\t\t\t\t\tsender: {\n\t\t\t\t\t\t\tname: 'Support Team',\n\t\t\t\t\t\t\tavatarUrl: null,\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\t\t\t\t\tthis.messengerState.addMessage(conversationId, mockResponse);\n\t\t\t\t}, 1500);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconsole.error('[MessengerWidget] Failed to send message:', error);\n\t\t\t// Could add error handling UI here\n\t\t}\n\t}\n\n\t/**\n\t * Handle incoming WebSocket message\n\t */\n\t_handleWebSocketMessage(data) {\n\t\tconst { conversation_id, message } = data;\n\n\t\t// Transform message to local format\n\t\tconst localMessage = {\n\t\t\tid: message.id,\n\t\t\tcontent: message.content,\n\t\t\tisOwn: message.sender_type === 'customer',\n\t\t\ttimestamp: message.created_at,\n\t\t\tsender: {\n\t\t\t\tname: message.sender_name || 'Support',\n\t\t\t\tavatarUrl: message.sender_avatar || null,\n\t\t\t},\n\t\t};\n\n\t\t// Add message to state\n\t\tthis.messengerState.addMessage(conversation_id, localMessage);\n\n\t\t// Update unread count if panel is closed or viewing different conversation\n\t\tif (!this.messengerState.isOpen || this.messengerState.activeConversationId !== conversation_id) {\n\t\t\tthis._updateUnreadCount();\n\t\t}\n\t}\n\n\t/**\n\t * Handle typing started event\n\t */\n\t_handleTypingStarted(data) {\n\t\tif (data.is_agent) {\n\t\t\tthis.messengerState._notify('typingStarted', {\n\t\t\t\tconversationId: data.conversation_id,\n\t\t\t\tuserName: data.user_name,\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Handle typing stopped event\n\t */\n\t_handleTypingStopped(data) {\n\t\tthis.messengerState._notify('typingStopped', {\n\t\t\tconversationId: data.conversation_id,\n\t\t});\n\t}\n\n\t/**\n\t * Update unread count from API\n\t */\n\tasync _updateUnreadCount() {\n\t\ttry {\n\t\t\tconst response = await this.apiService.getUnreadCount();\n\t\t\tif (response.status && response.data) {\n\t\t\t\tthis.messengerState.unreadCount = response.data.unread_count || 0;\n\t\t\t\tthis.messengerState._notify('unreadCountChange', { count: this.messengerState.unreadCount });\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconsole.error('[MessengerWidget] Failed to get unread count:', error);\n\t\t}\n\t}\n\n\t/**\n\t * Initialize WebSocket connection\n\t */\n\t_initWebSocket() {\n\t\tif (this.wsService) {\n\t\t\tthis.wsService.disconnect();\n\t\t}\n\n\t\tthis.wsService = new WebSocketService({\n\t\t\tbaseURL: this.apiService.baseURL,\n\t\t\tworkspace: this.apiService.workspace,\n\t\t\tsessionToken: this.apiService.sessionToken,\n\t\t\tmock: this.apiService.mock,\n\t\t});\n\n\t\t// Subscribe to WebSocket events\n\t\tthis._wsUnsubscribers.push(\n\t\t\tthis.wsService.on('message', this._handleWebSocketMessage)\n\t\t);\n\t\tthis._wsUnsubscribers.push(\n\t\t\tthis.wsService.on('typing_started', this._handleTypingStarted)\n\t\t);\n\t\tthis._wsUnsubscribers.push(\n\t\t\tthis.wsService.on('typing_stopped', this._handleTypingStopped)\n\t\t);\n\t\tthis._wsUnsubscribers.push(\n\t\t\tthis.wsService.on('connected', () => {\n\t\t\t\tconsole.log('[MessengerWidget] WebSocket connected');\n\t\t\t})\n\t\t);\n\t\tthis._wsUnsubscribers.push(\n\t\t\tthis.wsService.on('disconnected', () => {\n\t\t\t\tconsole.log('[MessengerWidget] WebSocket disconnected');\n\t\t\t})\n\t\t);\n\n\t\t// Connect\n\t\tthis.wsService.connect();\n\t}\n\n\t/**\n\t * Open the messenger panel\n\t */\n\topen() {\n\t\tthis.messengerState.setOpen(true);\n\t}\n\n\t/**\n\t * Close the messenger panel\n\t */\n\tclose() {\n\t\tthis.messengerState.setOpen(false);\n\t}\n\n\t/**\n\t * Toggle the messenger panel\n\t */\n\ttoggle() {\n\t\tthis.messengerState.setOpen(!this.messengerState.isOpen);\n\t}\n\n\t/**\n\t * Navigate to a specific view\n\t */\n\tnavigateTo(view) {\n\t\tthis.messengerState.setView(view);\n\t\tif (!this.messengerState.isOpen) {\n\t\t\tthis.open();\n\t\t}\n\t}\n\n\t/**\n\t * Set conversations\n\t */\n\tsetConversations(conversations) {\n\t\tthis.messengerState.setConversations(conversations);\n\t}\n\n\t/**\n\t * Add a message to a conversation\n\t */\n\taddMessage(conversationId, message) {\n\t\tthis.messengerState.addMessage(conversationId, message);\n\t}\n\n\t/**\n\t * Set help articles\n\t */\n\tsetHelpArticles(articles) {\n\t\tthis.messengerState.setHelpArticles(articles);\n\t}\n\n\t/**\n\t * Set home changelog items\n\t */\n\tsetHomeChangelogItems(items) {\n\t\tthis.messengerState.setHomeChangelogItems(items);\n\t}\n\n\t/**\n\t * Set changelog items\n\t */\n\tsetChangelogItems(items) {\n\t\tthis.messengerState.setChangelogItems(items);\n\t}\n\n\t/**\n\t * Update unread count (for external updates)\n\t */\n\tsetUnreadCount(count) {\n\t\tthis.messengerState.unreadCount = count;\n\t\tthis.messengerState._notify('unreadCountChange', { count });\n\t}\n\n\t/**\n\t * Get current state\n\t */\n\tgetState() {\n\t\treturn {\n\t\t\tisOpen: this.messengerState.isOpen,\n\t\t\tcurrentView: this.messengerState.currentView,\n\t\t\tunreadCount: this.messengerState.unreadCount,\n\t\t\tconversations: this.messengerState.conversations,\n\t\t};\n\t}\n\n\t/**\n\t * Load initial data (mock or API)\n\t */\n\tasync loadInitialData() {\n\t\t// Load conversations\n\t\ttry {\n\t\t\tconst conversations = await this._fetchConversations();\n\t\t\tthis.messengerState.setConversations(conversations);\n\t\t} catch (error) {\n\t\t\tconsole.error('[MessengerWidget] Failed to load conversations:', error);\n\t\t}\n\n\t\t// Load help articles if enabled\n\t\tif (this.messengerOptions.enableHelp) {\n\t\t\ttry {\n\t\t\t\tconst articles = await this._fetchHelpArticles();\n\t\t\t\tthis.messengerState.setHelpArticles(articles);\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error('[MessengerWidget] Failed to load help articles:', error);\n\t\t\t}\n\t\t}\n\n\t\t// Load changelog if enabled\n\t\tif (this.messengerOptions.enableChangelog) {\n\t\t\ttry {\n\t\t\t\tconst { homeItems, changelogItems } = await this._fetchChangelog();\n\t\t\t\tthis.messengerState.setHomeChangelogItems(homeItems);\n\t\t\t\tthis.messengerState.setChangelogItems(changelogItems);\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error('[MessengerWidget] Failed to load changelog:', error);\n\t\t\t}\n\t\t}\n\t}\n\n\tasync _fetchConversations() {\n\t\ttry {\n\t\t\tconst response = await this.apiService.getConversations();\n\t\t\tif (response.status && response.data) {\n\t\t\t\t// Transform API response to local format\n\t\t\t\treturn response.data.map((conv) => ({\n\t\t\t\t\tid: conv.id,\n\t\t\t\t\ttitle: conv.subject || `Chat with ${conv.assigned_user?.name || 'Support'}`,\n\t\t\t\t\tparticipants: conv.assigned_user\n\t\t\t\t\t\t? [{ name: conv.assigned_user.name, avatarUrl: conv.assigned_user.avatar }]\n\t\t\t\t\t\t: [{ name: 'Support', avatarUrl: null }],\n\t\t\t\t\tlastMessage: conv.preview || conv.snippet || '',\n\t\t\t\t\tlastMessageTime: conv.last_message_at,\n\t\t\t\t\tunread: conv.unread || 0,\n\t\t\t\t\tstatus: conv.status,\n\t\t\t\t}));\n\t\t\t}\n\t\t\treturn [];\n\t\t} catch (error) {\n\t\t\tconsole.error('[MessengerWidget] Failed to fetch conversations:', error);\n\t\t\treturn [];\n\t\t}\n\t}\n\n\tasync _fetchHelpArticles() {\n\t\ttry {\n\t\t\tconst response = await this.apiService.getHelpCollections();\n\t\t\tif (response.status && response.data) {\n\t\t\t\t// Transform API response to local format\n\t\t\t\treturn response.data.map((collection) => ({\n\t\t\t\t\tid: collection.id,\n\t\t\t\t\ttitle: collection.title || collection.name,\n\t\t\t\t\tdescription: collection.description || '',\n\t\t\t\t\tarticleCount: collection.article_count || collection.articleCount || 0,\n\t\t\t\t\ticon: collection.icon || 'ph-book-open',\n\t\t\t\t\turl: collection.url || `#/help/${collection.slug || collection.id}`,\n\t\t\t\t}));\n\t\t\t}\n\t\t\treturn [];\n\t\t} catch (error) {\n\t\t\tconsole.error('[MessengerWidget] Failed to fetch help articles:', error);\n\t\t\treturn [];\n\t\t}\n\t}\n\n\t/**\n\t * Fetch messages for a conversation\n\t */\n\tasync fetchMessages(conversationId) {\n\t\ttry {\n\t\t\tconst response = await this.apiService.getConversation(conversationId);\n\t\t\tif (response.status && response.data) {\n\t\t\t\tconst messages = (response.data.messages || []).map((msg) => ({\n\t\t\t\t\tid: msg.id,\n\t\t\t\t\tcontent: msg.content,\n\t\t\t\t\tisOwn: msg.sender_type === 'customer',\n\t\t\t\t\ttimestamp: msg.created_at,\n\t\t\t\t\tsender: {\n\t\t\t\t\t\tname: msg.sender_name || (msg.sender_type === 'customer' ? 'You' : 'Support'),\n\t\t\t\t\t\tavatarUrl: msg.sender_avatar || null,\n\t\t\t\t\t},\n\t\t\t\t}));\n\t\t\t\tthis.messengerState.setMessages(conversationId, messages);\n\n\t\t\t\t// Mark as read\n\t\t\t\tawait this.apiService.markConversationAsRead(conversationId);\n\t\t\t\tthis.messengerState.markAsRead(conversationId);\n\n\t\t\t\treturn messages;\n\t\t\t}\n\t\t\treturn [];\n\t\t} catch (error) {\n\t\t\tconsole.error('[MessengerWidget] Failed to fetch messages:', error);\n\t\t\treturn [];\n\t\t}\n\t}\n\n\t/**\n\t * Start a new conversation\n\t */\n\tasync startNewConversation(message, subject = '') {\n\t\ttry {\n\t\t\tconst response = await this.apiService.startConversation({\n\t\t\t\tmessage,\n\t\t\t\tsubject,\n\t\t\t});\n\n\t\t\tif (response.status && response.data) {\n\t\t\t\tconst conv = response.data;\n\t\t\t\tconst newConversation = {\n\t\t\t\t\tid: conv.id,\n\t\t\t\t\ttitle: conv.subject || 'New conversation',\n\t\t\t\t\tparticipants: [{ name: 'Support', avatarUrl: null }],\n\t\t\t\t\tlastMessage: message,\n\t\t\t\t\tlastMessageTime: conv.created_at || new Date().toISOString(),\n\t\t\t\t\tunread: 0,\n\t\t\t\t\tstatus: 'open',\n\t\t\t\t};\n\n\t\t\t\t// Add to state\n\t\t\t\tthis.messengerState.addConversation(newConversation);\n\n\t\t\t\t// Set initial message in messages cache\n\t\t\t\tthis.messengerState.setMessages(conv.id, [\n\t\t\t\t\t{\n\t\t\t\t\t\tid: 'msg_' + Date.now(),\n\t\t\t\t\t\tcontent: message,\n\t\t\t\t\t\tisOwn: true,\n\t\t\t\t\t\ttimestamp: new Date().toISOString(),\n\t\t\t\t\t},\n\t\t\t\t]);\n\n\t\t\t\t// Navigate to chat\n\t\t\t\tthis.messengerState.setActiveConversation(conv.id);\n\t\t\t\tthis.messengerState.setView('chat');\n\n\t\t\t\treturn conv;\n\t\t\t}\n\t\t\treturn null;\n\t\t} catch (error) {\n\t\t\tconsole.error('[MessengerWidget] Failed to start conversation:', error);\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Send typing indicator\n\t */\n\tasync sendTypingIndicator(conversationId, isTyping) {\n\t\ttry {\n\t\t\tawait this.apiService.sendTypingIndicator(conversationId, isTyping);\n\t\t} catch (error) {\n\t\t\t// Silently fail - typing indicators are not critical\n\t\t}\n\t}\n\n\t/**\n\t * Check agent availability\n\t */\n\tasync checkAgentAvailability() {\n\t\ttry {\n\t\t\tconst response = await this.apiService.checkAgentsOnline();\n\t\t\tif (response.status && response.data) {\n\t\t\t\tthis.messengerState.agentsOnline = response.data.agents_online;\n\t\t\t\tthis.messengerState.onlineCount = response.data.online_count || 0;\n\t\t\t\tthis.messengerState.responseTime = response.data.response_time || '';\n\t\t\t\tthis.messengerState._notify('availabilityUpdate', response.data);\n\t\t\t\treturn response.data;\n\t\t\t}\n\t\t\treturn { agents_online: false, online_count: 0 };\n\t\t} catch (error) {\n\t\t\tconsole.error('[MessengerWidget] Failed to check availability:', error);\n\t\t\treturn { agents_online: false, online_count: 0 };\n\t\t}\n\t}\n\n\tasync _fetchChangelog() {\n\t\t// Mock data for now - simulating changelog API response\n\t\tif (this.apiService?.mock) {\n\t\t\treturn {\n\t\t\t\thomeItems: [\n\t\t\t\t\t{\n\t\t\t\t\t\tid: 'changelog_5',\n\t\t\t\t\t\ttitle: 'New integrations available',\n\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t'Connect with more tools you love and streamline your workflow.',\n\t\t\t\t\t\ttags: ['Integration'],\n\t\t\t\t\t\tcoverImage: 'https://feedback-sdk.product7.io/700x400__5_.png',\n\t\t\t\t\t\tcoverText: null,\n\t\t\t\t\t\tpublishedAt: new Date(\n\t\t\t\t\t\t\tDate.now() - 14 * 24 * 60 * 60 * 1000\n\t\t\t\t\t\t).toISOString(),\n\t\t\t\t\t\turl: '#',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tid: 'changelog_2',\n\t\t\t\t\t\ttitle: 'A new era of Insights has arrived',\n\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t'We announced Fin Insights, a groundbreaking, AI-powered product that gives you complete visibility into every customer conversation.',\n\t\t\t\t\t\ttags: ['New feature', 'AI'],\n\t\t\t\t\t\tcoverImage:\n\t\t\t\t\t\t\t'https://feedback-sdk.product7.io/Intercom_Messenger__1_.jpg',\n\t\t\t\t\t\tcoverText: 'Watch our major product launch on-demand',\n\t\t\t\t\t\tpublishedAt: new Date(\n\t\t\t\t\t\t\tDate.now() - 5 * 24 * 60 * 60 * 1000\n\t\t\t\t\t\t).toISOString(),\n\t\t\t\t\t\turl: '#',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tid: 'changelog_1',\n\t\t\t\t\t\ttitle: 'The 2025 Customer Service Transformation Report',\n\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t'Learn how AI has transformed customer service from the ground up—rewriting its economics and reshaping expectations.',\n\t\t\t\t\t\ttags: ['Report'],\n\t\t\t\t\t\tcoverImage:\n\t\t\t\t\t\t\t'https://feedback-sdk.product7.io/Main_Report_Email_Header.png',\n\t\t\t\t\t\tcoverText: 'Customer service trends as we know them are dead.',\n\t\t\t\t\t\tpublishedAt: new Date(\n\t\t\t\t\t\t\tDate.now() - 2 * 24 * 60 * 60 * 1000\n\t\t\t\t\t\t).toISOString(),\n\t\t\t\t\t\turl: '#',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tchangelogItems: [\n\t\t\t\t\t{\n\t\t\t\t\t\tid: 'changelog_4',\n\t\t\t\t\t\ttitle: 'Enhanced conversation analytics',\n\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t'Get deeper insights into your customer conversations with our new analytics dashboard.',\n\t\t\t\t\t\ttags: ['Analytics'],\n\t\t\t\t\t\tcoverImage:\n\t\t\t\t\t\t\t'https://feedback-sdk.product7.io/cgangelog-Frame%202087334450.jpg',\n\t\t\t\t\t\tcoverText: null,\n\t\t\t\t\t\tpublishedAt: new Date(\n\t\t\t\t\t\t\tDate.now() - 10 * 24 * 60 * 60 * 1000\n\t\t\t\t\t\t).toISOString(),\n\t\t\t\t\t\turl: '#',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tid: 'changelog_3',\n\t\t\t\t\t\ttitle: 'Escalation guidance for complex issues',\n\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t'New AI-powered escalation guidance helps your team handle complex customer issues more effectively.',\n\t\t\t\t\t\ttags: ['New feature', 'AI'],\n\t\t\t\t\t\tcoverImage:\n\t\t\t\t\t\t\t'https://feedback-sdk.product7.io/cgangelog-image-escalation-guidance-event@2x.png',\n\t\t\t\t\t\tcoverText: null,\n\t\t\t\t\t\tpublishedAt: new Date(\n\t\t\t\t\t\t\tDate.now() - 7 * 24 * 60 * 60 * 1000\n\t\t\t\t\t\t).toISOString(),\n\t\t\t\t\t\turl: '#',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t};\n\t\t}\n\n\t\t// Fetch changelogs from API\n\t\tconst response = await this.apiService.getChangelogs({ limit: 20 });\n\t\tconst changelogs = response.data || [];\n\n\t\t// Map API response to expected format\n\t\tconst mappedItems = changelogs.map((item) => ({\n\t\t\tid: item.id,\n\t\t\ttitle: item.title,\n\t\t\tdescription: item.excerpt || item.description || '',\n\t\t\ttags: item.labels ? item.labels.map((label) => label.name) : [],\n\t\t\tcoverImage: item.cover_image || null,\n\t\t\tcoverText: null,\n\t\t\tpublishedAt: item.published_at,\n\t\t\turl: item.slug ? `/changelog/${item.slug}` : '#',\n\t\t}));\n\n\t\treturn {\n\t\t\thomeItems: mappedItems.slice(0, 3),\n\t\t\tchangelogItems: mappedItems,\n\t\t};\n\t}\n\n\tonMount() {\n\t\t// Load initial data after mounting\n\t\tthis.loadInitialData();\n\n\t\t// Initialize WebSocket for real-time updates\n\t\tif (this.apiService?.sessionToken) {\n\t\t\tthis._initWebSocket();\n\t\t}\n\n\t\t// Check agent availability\n\t\tthis.checkAgentAvailability();\n\n\t\t// Periodically check availability (every 60 seconds)\n\t\tthis._availabilityInterval = setInterval(() => {\n\t\t\tthis.checkAgentAvailability();\n\t\t}, 60000);\n\t}\n\n\tonDestroy() {\n\t\tif (this._stateUnsubscribe) {\n\t\t\tthis._stateUnsubscribe();\n\t\t}\n\n\t\t// Clean up WebSocket\n\t\tif (this.wsService) {\n\t\t\tthis.wsService.disconnect();\n\t\t}\n\n\t\t// Clean up WebSocket event listeners\n\t\tthis._wsUnsubscribers.forEach((unsub) => unsub());\n\t\tthis._wsUnsubscribers = [];\n\n\t\t// Clean up availability interval\n\t\tif (this._availabilityInterval) {\n\t\t\tclearInterval(this._availabilityInterval);\n\t\t}\n\t}\n\n\tdestroy() {\n\t\tif (this.launcher) {\n\t\t\tthis.launcher.destroy();\n\t\t}\n\t\tif (this.panel) {\n\t\t\tthis.panel.destroy();\n\t\t}\n\t\tthis.onDestroy();\n\t\tsuper.destroy();\n\t}\n}\n","import { BaseWidget } from './BaseWidget.js';\n\nexport class SurveyWidget extends BaseWidget {\n\tconstructor(options) {\n\t\tsuper({ ...options, type: 'survey' });\n\n\t\tthis.surveyOptions = {\n\t\t\tsurveyId: options.surveyId || null, // Backend survey ID for API calls\n\t\t\tsurveyType: options.surveyType || 'nps', // 'nps', 'csat', 'ces', 'custom'\n\t\t\tposition: options.position || 'bottom-right', // 'bottom-right', 'bottom-left', 'center', 'bottom'\n\t\t\ttitle: options.title || null,\n\t\t\tdescription: options.description || null,\n\t\t\tlowLabel: options.lowLabel || null,\n\t\t\thighLabel: options.highLabel || null,\n\t\t\tcustomQuestions: options.customQuestions || [],\n\t\t\ttheme: options.theme || 'light',\n\t\t\tonSubmit: options.onSubmit || null,\n\t\t\tonDismiss: options.onDismiss || null,\n\t\t};\n\n\t\tthis.surveyState = {\n\t\t\tscore: null,\n\t\t\tfeedback: '',\n\t\t\tcustomAnswers: {},\n\t\t\tisVisible: false,\n\t\t};\n\t}\n\n\t_render() {\n\t\t// Survey widget doesn't render a trigger button, it's shown programmatically\n\t\tconst container = document.createElement('div');\n\t\tcontainer.className = 'feedback-survey-container';\n\t\tcontainer.style.display = 'none';\n\t\treturn container;\n\t}\n\n\t_attachEvents() {\n\t\t// Events are attached when survey is shown\n\t}\n\n\tshow() {\n\t\tthis._renderSurvey();\n\t\tthis.surveyState.isVisible = true;\n\t\tthis.sdk.eventBus.emit('survey:shown', {\n\t\t\twidget: this,\n\t\t\ttype: this.surveyOptions.surveyType,\n\t\t});\n\t\treturn this;\n\t}\n\n\thide() {\n\t\tthis._closeSurvey();\n\t\treturn this;\n\t}\n\n\t_renderSurvey() {\n\t\t// Remove any existing survey\n\t\tthis._closeSurvey();\n\n\t\tconst config = this._getSurveyConfig();\n\t\tconst positionStyles = this._getPositionStyles();\n\t\tconst themeStyles =\n\t\t\tthis.surveyOptions.theme === 'dark'\n\t\t\t\t? 'background: #1a1a1a; color: #fff;'\n\t\t\t\t: 'background: #fff; color: #1d1d1f;';\n\n\t\t// Create backdrop for center position\n\t\tif (this.surveyOptions.position === 'center') {\n\t\t\tthis.backdropElement = document.createElement('div');\n\t\t\tthis.backdropElement.className = 'feedback-survey-backdrop';\n\t\t\tdocument.body.appendChild(this.backdropElement);\n\t\t\tthis.backdropElement.addEventListener('click', () =>\n\t\t\t\tthis._handleDismiss()\n\t\t\t);\n\t\t}\n\n\t\tthis.surveyElement = document.createElement('div');\n\t\tthis.surveyElement.className = `feedback-survey feedback-survey-${this.surveyOptions.position} theme-${this.surveyOptions.theme}`;\n\t\tthis.surveyElement.style.cssText = `position: fixed; ${positionStyles} z-index: 10000; ${themeStyles} border-radius: 16px; box-shadow: 0 20px 60px rgba(0,0,0,0.3); padding: 24px; min-width: 320px; max-width: 400px; font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;`;\n\n\t\tthis.surveyElement.innerHTML = `\n\t\t\t<button class=\"feedback-survey-close\" style=\"position: absolute; top: 12px; right: 12px; background: none; border: none; font-size: 20px; cursor: pointer; color: ${this.surveyOptions.theme === 'dark' ? '#888' : '#86868b'}; line-height: 1;\">×</button>\n\t\t\t<h3 class=\"feedback-survey-title\" style=\"margin: 0 0 8px 0; font-size: 18px; font-weight: 600; padding-right: 24px;\">${config.title}</h3>\n\t\t\t<p class=\"feedback-survey-description\" style=\"color: ${this.surveyOptions.theme === 'dark' ? '#aaa' : '#86868b'}; margin: 0 0 20px 0; font-size: 14px;\">${config.description}</p>\n\t\t\t<div class=\"feedback-survey-content\">${config.html}</div>\n\t\t\t<div class=\"feedback-survey-feedback\" style=\"margin-top: 16px;\">\n\t\t\t\t<textarea class=\"feedback-survey-textarea\" placeholder=\"Any additional feedback? (optional)\" style=\"width: 100%; padding: 12px; border: 1px solid ${this.surveyOptions.theme === 'dark' ? '#333' : '#d2d2d7'}; border-radius: 8px; font-size: 14px; resize: none; height: 80px; background: ${this.surveyOptions.theme === 'dark' ? '#2a2a2a' : '#fff'}; color: ${this.surveyOptions.theme === 'dark' ? '#fff' : '#1d1d1f'}; font-family: inherit; box-sizing: border-box;\"></textarea>\n\t\t\t</div>\n\t\t\t<button class=\"feedback-survey-submit\" style=\"width: 100%; margin-top: 12px; padding: 12px; background: #007aff; color: white; border: none; border-radius: 8px; font-size: 14px; font-weight: 500; cursor: pointer; font-family: inherit;\">Submit</button>\n\t\t`;\n\n\t\tdocument.body.appendChild(this.surveyElement);\n\t\tthis._attachSurveyEvents();\n\n\t\t// Animate in\n\t\trequestAnimationFrame(() => {\n\t\t\tthis.surveyElement.style.opacity = '1';\n\t\t\tthis.surveyElement.style.transform =\n\t\t\t\tthis.surveyOptions.position === 'center'\n\t\t\t\t\t? 'translate(-50%, -50%) scale(1)'\n\t\t\t\t\t: 'translateY(0)';\n\t\t});\n\t}\n\n\t_getSurveyConfig() {\n\t\tconst configs = {\n\t\t\tnps: {\n\t\t\t\ttitle:\n\t\t\t\t\tthis.surveyOptions.title || 'How likely are you to recommend us?',\n\t\t\t\tdescription:\n\t\t\t\t\tthis.surveyOptions.description ||\n\t\t\t\t\t'On a scale of 0-10, how likely are you to recommend our product to a friend or colleague?',\n\t\t\t\thtml: `\n\t\t\t\t\t<div class=\"feedback-survey-nps\" style=\"display: flex; justify-content: space-between; gap: 4px;\">\n\t\t\t\t\t\t${[...Array(11).keys()]\n\t\t\t\t\t\t\t.map(\n\t\t\t\t\t\t\t\t(n) => `\n\t\t\t\t\t\t\t<button class=\"feedback-survey-nps-btn\" data-score=\"${n}\" style=\"width: 28px; height: 36px; border: 1px solid ${this.surveyOptions.theme === 'dark' ? '#444' : '#d2d2d7'}; border-radius: 6px; background: ${this.surveyOptions.theme === 'dark' ? '#2a2a2a' : '#f8f9fa'}; cursor: pointer; font-size: 12px; color: ${this.surveyOptions.theme === 'dark' ? '#fff' : '#1d1d1f'}; transition: all 0.15s;\">${n}</button>\n\t\t\t\t\t\t`\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t.join('')}\n\t\t\t\t\t</div>\n\t\t\t\t\t<div style=\"display: flex; justify-content: space-between; margin-top: 8px; font-size: 11px; color: ${this.surveyOptions.theme === 'dark' ? '#888' : '#86868b'};\">\n\t\t\t\t\t\t<span>${this.surveyOptions.lowLabel || 'Not likely'}</span>\n\t\t\t\t\t\t<span>${this.surveyOptions.highLabel || 'Very likely'}</span>\n\t\t\t\t\t</div>\n\t\t\t\t`,\n\t\t\t},\n\t\t\tcsat: {\n\t\t\t\ttitle: this.surveyOptions.title || 'How satisfied are you?',\n\t\t\t\tdescription:\n\t\t\t\t\tthis.surveyOptions.description ||\n\t\t\t\t\t'How would you rate your overall satisfaction with our product?',\n\t\t\t\thtml: `\n\t\t\t\t\t<div class=\"feedback-survey-csat\" style=\"display: flex; justify-content: center; gap: 16px;\">\n\t\t\t\t\t\t${['😞', '😕', '😐', '🙂', '😄']\n\t\t\t\t\t\t\t.map(\n\t\t\t\t\t\t\t\t(emoji, i) => `\n\t\t\t\t\t\t\t<button class=\"feedback-survey-csat-btn\" data-score=\"${i + 1}\" style=\"background: none; border: none; cursor: pointer; font-size: 36px; transition: transform 0.15s; padding: 8px;\">${emoji}</button>\n\t\t\t\t\t\t`\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t.join('')}\n\t\t\t\t\t</div>\n\t\t\t\t\t<div style=\"display: flex; justify-content: space-between; margin-top: 8px; font-size: 11px; color: ${this.surveyOptions.theme === 'dark' ? '#888' : '#86868b'};\">\n\t\t\t\t\t\t<span>${this.surveyOptions.lowLabel || 'Very dissatisfied'}</span>\n\t\t\t\t\t\t<span>${this.surveyOptions.highLabel || 'Very satisfied'}</span>\n\t\t\t\t\t</div>\n\t\t\t\t`,\n\t\t\t},\n\t\t\tces: {\n\t\t\t\ttitle: this.surveyOptions.title || 'How easy was it?',\n\t\t\t\tdescription:\n\t\t\t\t\tthis.surveyOptions.description ||\n\t\t\t\t\t'How easy was it to accomplish your task today?',\n\t\t\t\thtml: `\n\t\t\t\t\t<div class=\"feedback-survey-ces\" style=\"display: flex; justify-content: space-between; gap: 8px;\">\n\t\t\t\t\t\t${['Very Difficult', 'Difficult', 'Neutral', 'Easy', 'Very Easy']\n\t\t\t\t\t\t\t.map(\n\t\t\t\t\t\t\t\t(label, i) => `\n\t\t\t\t\t\t\t<button class=\"feedback-survey-ces-btn\" data-score=\"${i + 1}\" style=\"flex: 1; padding: 12px 8px; border: 1px solid ${this.surveyOptions.theme === 'dark' ? '#444' : '#d2d2d7'}; border-radius: 8px; background: ${this.surveyOptions.theme === 'dark' ? '#2a2a2a' : '#f8f9fa'}; cursor: pointer; font-size: 11px; color: ${this.surveyOptions.theme === 'dark' ? '#fff' : '#1d1d1f'}; transition: all 0.15s;\">${label}</button>\n\t\t\t\t\t\t`\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t.join('')}\n\t\t\t\t\t</div>\n\t\t\t\t`,\n\t\t\t},\n\t\t\tcustom: {\n\t\t\t\ttitle: this.surveyOptions.title || 'Quick Feedback',\n\t\t\t\tdescription:\n\t\t\t\t\tthis.surveyOptions.description ||\n\t\t\t\t\t'Help us improve by answering a few questions.',\n\t\t\t\thtml: this._renderCustomQuestions(),\n\t\t\t},\n\t\t};\n\n\t\treturn configs[this.surveyOptions.surveyType] || configs.nps;\n\t}\n\n\t_renderCustomQuestions() {\n\t\tif (\n\t\t\t!this.surveyOptions.customQuestions ||\n\t\t\tthis.surveyOptions.customQuestions.length === 0\n\t\t) {\n\t\t\t// Default custom questions\n\t\t\treturn `\n\t\t\t\t<div style=\"margin-bottom: 16px;\">\n\t\t\t\t\t<label style=\"display: block; margin-bottom: 6px; font-size: 13px; font-weight: 500;\">What feature do you use most?</label>\n\t\t\t\t\t<select class=\"feedback-survey-select\" data-question=\"feature\" style=\"width: 100%; padding: 10px; border: 1px solid ${this.surveyOptions.theme === 'dark' ? '#444' : '#d2d2d7'}; border-radius: 8px; font-size: 14px; background: ${this.surveyOptions.theme === 'dark' ? '#2a2a2a' : '#fff'}; color: ${this.surveyOptions.theme === 'dark' ? '#fff' : '#1d1d1f'};\">\n\t\t\t\t\t\t<option value=\"\">Select a feature</option>\n\t\t\t\t\t\t<option value=\"feedback\">Feedback Collection</option>\n\t\t\t\t\t\t<option value=\"surveys\">Surveys</option>\n\t\t\t\t\t\t<option value=\"analytics\">Analytics</option>\n\t\t\t\t\t\t<option value=\"integrations\">Integrations</option>\n\t\t\t\t\t</select>\n\t\t\t\t</div>\n\t\t\t\t<div>\n\t\t\t\t\t<label style=\"display: block; margin-bottom: 6px; font-size: 13px; font-weight: 500;\">How often do you use it?</label>\n\t\t\t\t\t<div class=\"feedback-survey-frequency\" style=\"display: flex; gap: 8px;\">\n\t\t\t\t\t\t${['Daily', 'Weekly', 'Monthly', 'Rarely']\n\t\t\t\t\t\t\t.map(\n\t\t\t\t\t\t\t\t(freq) => `\n\t\t\t\t\t\t\t<button class=\"feedback-survey-freq-btn\" data-freq=\"${freq}\" style=\"flex: 1; padding: 10px; border: 1px solid ${this.surveyOptions.theme === 'dark' ? '#444' : '#d2d2d7'}; border-radius: 8px; background: ${this.surveyOptions.theme === 'dark' ? '#2a2a2a' : '#f8f9fa'}; cursor: pointer; font-size: 12px; color: ${this.surveyOptions.theme === 'dark' ? '#fff' : '#1d1d1f'}; transition: all 0.15s;\">${freq}</button>\n\t\t\t\t\t\t`\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t.join('')}\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t`;\n\t\t}\n\n\t\treturn this.surveyOptions.customQuestions\n\t\t\t.map(\n\t\t\t\t(q, index) => `\n\t\t\t<div style=\"margin-bottom: 16px;\">\n\t\t\t\t<label style=\"display: block; margin-bottom: 6px; font-size: 13px; font-weight: 500;\">${q.label}</label>\n\t\t\t\t${this._renderQuestionInput(q, index)}\n\t\t\t</div>\n\t\t`\n\t\t\t)\n\t\t\t.join('');\n\t}\n\n\t_renderQuestionInput(question, index) {\n\t\tswitch (question.type) {\n\t\t\tcase 'select':\n\t\t\t\treturn `\n\t\t\t\t\t<select class=\"feedback-survey-select\" data-question=\"${question.id || index}\" style=\"width: 100%; padding: 10px; border: 1px solid ${this.surveyOptions.theme === 'dark' ? '#444' : '#d2d2d7'}; border-radius: 8px; font-size: 14px; background: ${this.surveyOptions.theme === 'dark' ? '#2a2a2a' : '#fff'}; color: ${this.surveyOptions.theme === 'dark' ? '#fff' : '#1d1d1f'};\">\n\t\t\t\t\t\t<option value=\"\">${question.placeholder || 'Select an option'}</option>\n\t\t\t\t\t\t${question.options.map((opt) => `<option value=\"${opt.value}\">${opt.label}</option>`).join('')}\n\t\t\t\t\t</select>\n\t\t\t\t`;\n\t\t\tcase 'text':\n\t\t\t\treturn `\n\t\t\t\t\t<input type=\"text\" class=\"feedback-survey-input\" data-question=\"${question.id || index}\" placeholder=\"${question.placeholder || ''}\" style=\"width: 100%; padding: 10px; border: 1px solid ${this.surveyOptions.theme === 'dark' ? '#444' : '#d2d2d7'}; border-radius: 8px; font-size: 14px; background: ${this.surveyOptions.theme === 'dark' ? '#2a2a2a' : '#fff'}; color: ${this.surveyOptions.theme === 'dark' ? '#fff' : '#1d1d1f'}; box-sizing: border-box;\">\n\t\t\t\t`;\n\t\t\tdefault:\n\t\t\t\treturn '';\n\t\t}\n\t}\n\n\t_getPositionStyles() {\n\t\tconst positions = {\n\t\t\t'bottom-right':\n\t\t\t\t'bottom: 24px; right: 24px; opacity: 0; transform: translateY(20px); transition: all 0.3s ease;',\n\t\t\t'bottom-left':\n\t\t\t\t'bottom: 24px; left: 24px; opacity: 0; transform: translateY(20px); transition: all 0.3s ease;',\n\t\t\tcenter:\n\t\t\t\t'top: 50%; left: 50%; transform: translate(-50%, -50%) scale(0.95); opacity: 0; transition: all 0.3s ease;',\n\t\t\tbottom:\n\t\t\t\t'bottom: 0; left: 0; right: 0; border-radius: 16px 16px 0 0; max-width: none; opacity: 0; transform: translateY(20px); transition: all 0.3s ease;',\n\t\t};\n\t\treturn positions[this.surveyOptions.position] || positions['bottom-right'];\n\t}\n\n\t_attachSurveyEvents() {\n\t\tif (!this.surveyElement) return;\n\n\t\t// Close button\n\t\tconst closeBtn = this.surveyElement.querySelector('.feedback-survey-close');\n\t\tcloseBtn.addEventListener('click', () => this._handleDismiss());\n\n\t\t// Submit button\n\t\tconst submitBtn = this.surveyElement.querySelector(\n\t\t\t'.feedback-survey-submit'\n\t\t);\n\t\tsubmitBtn.addEventListener('click', () => this._handleSubmit());\n\n\t\t// Feedback textarea\n\t\tconst textarea = this.surveyElement.querySelector(\n\t\t\t'.feedback-survey-textarea'\n\t\t);\n\t\ttextarea.addEventListener('input', (e) => {\n\t\t\tthis.surveyState.feedback = e.target.value;\n\t\t});\n\n\t\t// Survey type specific events\n\t\tthis._attachTypeSpecificEvents();\n\n\t\t// Escape key\n\t\tthis._escapeHandler = (e) => {\n\t\t\tif (e.key === 'Escape') {\n\t\t\t\tthis._handleDismiss();\n\t\t\t}\n\t\t};\n\t\tdocument.addEventListener('keydown', this._escapeHandler);\n\t}\n\n\t_attachTypeSpecificEvents() {\n\t\tconst type = this.surveyOptions.surveyType;\n\n\t\tif (type === 'nps') {\n\t\t\tthis.surveyElement\n\t\t\t\t.querySelectorAll('.feedback-survey-nps-btn')\n\t\t\t\t.forEach((btn) => {\n\t\t\t\t\tbtn.addEventListener('click', () =>\n\t\t\t\t\t\tthis._selectNPS(parseInt(btn.dataset.score))\n\t\t\t\t\t);\n\t\t\t\t\tbtn.addEventListener('mouseenter', () => {\n\t\t\t\t\t\tif (this.surveyState.score !== parseInt(btn.dataset.score)) {\n\t\t\t\t\t\t\tbtn.style.borderColor = '#007aff';\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\tbtn.addEventListener('mouseleave', () => {\n\t\t\t\t\t\tif (this.surveyState.score !== parseInt(btn.dataset.score)) {\n\t\t\t\t\t\t\tbtn.style.borderColor =\n\t\t\t\t\t\t\t\tthis.surveyOptions.theme === 'dark' ? '#444' : '#d2d2d7';\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t}\n\n\t\tif (type === 'csat') {\n\t\t\tthis.surveyElement\n\t\t\t\t.querySelectorAll('.feedback-survey-csat-btn')\n\t\t\t\t.forEach((btn) => {\n\t\t\t\t\tbtn.addEventListener('click', () =>\n\t\t\t\t\t\tthis._selectCSAT(parseInt(btn.dataset.score))\n\t\t\t\t\t);\n\t\t\t\t\tbtn.addEventListener('mouseenter', () => {\n\t\t\t\t\t\tbtn.style.transform = 'scale(1.1)';\n\t\t\t\t\t});\n\t\t\t\t\tbtn.addEventListener('mouseleave', () => {\n\t\t\t\t\t\tif (this.surveyState.score !== parseInt(btn.dataset.score)) {\n\t\t\t\t\t\t\tbtn.style.transform = 'scale(1)';\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t}\n\n\t\tif (type === 'ces') {\n\t\t\tthis.surveyElement\n\t\t\t\t.querySelectorAll('.feedback-survey-ces-btn')\n\t\t\t\t.forEach((btn) => {\n\t\t\t\t\tbtn.addEventListener('click', () =>\n\t\t\t\t\t\tthis._selectCES(parseInt(btn.dataset.score))\n\t\t\t\t\t);\n\t\t\t\t\tbtn.addEventListener('mouseenter', () => {\n\t\t\t\t\t\tif (this.surveyState.score !== parseInt(btn.dataset.score)) {\n\t\t\t\t\t\t\tbtn.style.borderColor = '#007aff';\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\tbtn.addEventListener('mouseleave', () => {\n\t\t\t\t\t\tif (this.surveyState.score !== parseInt(btn.dataset.score)) {\n\t\t\t\t\t\t\tbtn.style.borderColor =\n\t\t\t\t\t\t\t\tthis.surveyOptions.theme === 'dark' ? '#444' : '#d2d2d7';\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t}\n\n\t\tif (type === 'custom') {\n\t\t\t// Frequency buttons\n\t\t\tthis.surveyElement\n\t\t\t\t.querySelectorAll('.feedback-survey-freq-btn')\n\t\t\t\t.forEach((btn) => {\n\t\t\t\t\tbtn.addEventListener('click', () =>\n\t\t\t\t\t\tthis._selectFrequency(btn.dataset.freq)\n\t\t\t\t\t);\n\t\t\t\t});\n\n\t\t\t// Select inputs\n\t\t\tthis.surveyElement\n\t\t\t\t.querySelectorAll('.feedback-survey-select')\n\t\t\t\t.forEach((select) => {\n\t\t\t\t\tselect.addEventListener('change', (e) => {\n\t\t\t\t\t\tthis.surveyState.customAnswers[select.dataset.question] =\n\t\t\t\t\t\t\te.target.value;\n\t\t\t\t\t});\n\t\t\t\t});\n\n\t\t\t// Text inputs\n\t\t\tthis.surveyElement\n\t\t\t\t.querySelectorAll('.feedback-survey-input')\n\t\t\t\t.forEach((input) => {\n\t\t\t\t\tinput.addEventListener('input', (e) => {\n\t\t\t\t\t\tthis.surveyState.customAnswers[input.dataset.question] =\n\t\t\t\t\t\t\te.target.value;\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t}\n\t}\n\n\t_selectNPS(score) {\n\t\tthis.surveyState.score = score;\n\t\tthis.surveyElement\n\t\t\t.querySelectorAll('.feedback-survey-nps-btn')\n\t\t\t.forEach((btn) => {\n\t\t\t\tconst btnScore = parseInt(btn.dataset.score);\n\t\t\t\tif (btnScore === score) {\n\t\t\t\t\tbtn.style.background = '#007aff';\n\t\t\t\t\tbtn.style.borderColor = '#007aff';\n\t\t\t\t\tbtn.style.color = '#fff';\n\t\t\t\t} else {\n\t\t\t\t\tbtn.style.background =\n\t\t\t\t\t\tthis.surveyOptions.theme === 'dark' ? '#2a2a2a' : '#f8f9fa';\n\t\t\t\t\tbtn.style.borderColor =\n\t\t\t\t\t\tthis.surveyOptions.theme === 'dark' ? '#444' : '#d2d2d7';\n\t\t\t\t\tbtn.style.color =\n\t\t\t\t\t\tthis.surveyOptions.theme === 'dark' ? '#fff' : '#1d1d1f';\n\t\t\t\t}\n\t\t\t});\n\t}\n\n\t_selectCSAT(score) {\n\t\tthis.surveyState.score = score;\n\t\tthis.surveyElement\n\t\t\t.querySelectorAll('.feedback-survey-csat-btn')\n\t\t\t.forEach((btn) => {\n\t\t\t\tconst btnScore = parseInt(btn.dataset.score);\n\t\t\t\tbtn.style.transform = btnScore === score ? 'scale(1.2)' : 'scale(1)';\n\t\t\t});\n\t}\n\n\t_selectCES(score) {\n\t\tthis.surveyState.score = score;\n\t\tthis.surveyElement\n\t\t\t.querySelectorAll('.feedback-survey-ces-btn')\n\t\t\t.forEach((btn) => {\n\t\t\t\tconst btnScore = parseInt(btn.dataset.score);\n\t\t\t\tif (btnScore === score) {\n\t\t\t\t\tbtn.style.background = '#007aff';\n\t\t\t\t\tbtn.style.borderColor = '#007aff';\n\t\t\t\t\tbtn.style.color = '#fff';\n\t\t\t\t} else {\n\t\t\t\t\tbtn.style.background =\n\t\t\t\t\t\tthis.surveyOptions.theme === 'dark' ? '#2a2a2a' : '#f8f9fa';\n\t\t\t\t\tbtn.style.borderColor =\n\t\t\t\t\t\tthis.surveyOptions.theme === 'dark' ? '#444' : '#d2d2d7';\n\t\t\t\t\tbtn.style.color =\n\t\t\t\t\t\tthis.surveyOptions.theme === 'dark' ? '#fff' : '#1d1d1f';\n\t\t\t\t}\n\t\t\t});\n\t}\n\n\t_selectFrequency(freq) {\n\t\tthis.surveyState.customAnswers.frequency = freq;\n\t\tthis.surveyElement\n\t\t\t.querySelectorAll('.feedback-survey-freq-btn')\n\t\t\t.forEach((btn) => {\n\t\t\t\tif (btn.dataset.freq === freq) {\n\t\t\t\t\tbtn.style.background = '#007aff';\n\t\t\t\t\tbtn.style.borderColor = '#007aff';\n\t\t\t\t\tbtn.style.color = '#fff';\n\t\t\t\t} else {\n\t\t\t\t\tbtn.style.background =\n\t\t\t\t\t\tthis.surveyOptions.theme === 'dark' ? '#2a2a2a' : '#f8f9fa';\n\t\t\t\t\tbtn.style.borderColor =\n\t\t\t\t\t\tthis.surveyOptions.theme === 'dark' ? '#444' : '#d2d2d7';\n\t\t\t\t\tbtn.style.color =\n\t\t\t\t\t\tthis.surveyOptions.theme === 'dark' ? '#fff' : '#1d1d1f';\n\t\t\t\t}\n\t\t\t});\n\t}\n\n\tasync _handleSubmit() {\n\t\tconst type = this.surveyOptions.surveyType;\n\n\t\t// Validate\n\t\tif (\n\t\t\t(type === 'nps' || type === 'csat' || type === 'ces') &&\n\t\t\tthis.surveyState.score === null\n\t\t) {\n\t\t\tthis._showError('Please select a rating');\n\t\t\treturn;\n\t\t}\n\n\t\tconst responseData = {\n\t\t\trating: this.surveyState.score,\n\t\t\tfeedback: this.surveyState.feedback,\n\t\t\tanswers: this.surveyState.customAnswers,\n\t\t};\n\n\t\tconst response = {\n\t\t\ttype: type,\n\t\t\tscore: this.surveyState.score,\n\t\t\tfeedback: this.surveyState.feedback,\n\t\t\tcustomAnswers: this.surveyState.customAnswers,\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t};\n\n\t\t// Call onSubmit callback if provided\n\t\tif (this.surveyOptions.onSubmit) {\n\t\t\tthis.surveyOptions.onSubmit(response);\n\t\t}\n\n\t\t// Submit to API\n\t\ttry {\n\t\t\tconst surveyId =\n\t\t\t\tthis.surveyOptions.surveyId || `local_${type}_${Date.now()}`;\n\t\t\tawait this.apiService.submitSurveyResponse(surveyId, responseData);\n\t\t} catch (error) {\n\t\t\tconsole.error('[SurveyWidget] Failed to submit survey:', error);\n\t\t}\n\n\t\tthis.sdk.eventBus.emit('survey:submitted', { widget: this, response });\n\n\t\tthis._closeSurvey();\n\t\tthis._showSuccessNotification();\n\t}\n\n\tasync _handleDismiss() {\n\t\t// Call dismiss API if survey has a backend ID\n\t\tif (this.surveyOptions.surveyId) {\n\t\t\ttry {\n\t\t\t\tawait this.apiService.dismissSurvey(this.surveyOptions.surveyId);\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error('[SurveyWidget] Failed to dismiss survey:', error);\n\t\t\t}\n\t\t}\n\n\t\tif (this.surveyOptions.onDismiss) {\n\t\t\tthis.surveyOptions.onDismiss();\n\t\t}\n\t\tthis.sdk.eventBus.emit('survey:dismissed', { widget: this });\n\t\tthis._closeSurvey();\n\t}\n\n\t_showError(message) {\n\t\t// Simple error display - could be enhanced\n\t\tconst existing = this.surveyElement.querySelector('.feedback-survey-error');\n\t\tif (existing) existing.remove();\n\n\t\tconst error = document.createElement('div');\n\t\terror.className = 'feedback-survey-error';\n\t\terror.style.cssText =\n\t\t\t'color: #ef4444; font-size: 13px; margin-top: 8px; text-align: center;';\n\t\terror.textContent = message;\n\n\t\tconst submitBtn = this.surveyElement.querySelector(\n\t\t\t'.feedback-survey-submit'\n\t\t);\n\t\tsubmitBtn.parentNode.insertBefore(error, submitBtn);\n\n\t\tsetTimeout(() => error.remove(), 3000);\n\t}\n\n\t_showSuccessNotification() {\n\t\tconst notification = document.createElement('div');\n\t\tnotification.className = 'feedback-survey-success';\n\t\tnotification.style.cssText = `\n\t\t\tposition: fixed;\n\t\t\ttop: 24px;\n\t\t\tright: 24px;\n\t\t\tbackground: #10b981;\n\t\t\tcolor: white;\n\t\t\tpadding: 16px 24px;\n\t\t\tborder-radius: 12px;\n\t\t\tfont-size: 14px;\n\t\t\tfont-weight: 500;\n\t\t\tz-index: 10001;\n\t\t\tbox-shadow: 0 10px 40px rgba(0,0,0,0.2);\n\t\t\tfont-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;\n\t\t`;\n\t\tnotification.innerHTML = `\n\t\t\t<div style=\"display: flex; align-items: center; gap: 8px;\">\n\t\t\t\t<span style=\"font-size: 18px;\">✓</span>\n\t\t\t\t<span>Thank you for your feedback!</span>\n\t\t\t</div>\n\t\t`;\n\t\tdocument.body.appendChild(notification);\n\n\t\tsetTimeout(() => {\n\t\t\tnotification.style.opacity = '0';\n\t\t\tnotification.style.transition = 'opacity 0.3s ease';\n\t\t\tsetTimeout(() => notification.remove(), 300);\n\t\t}, 3000);\n\t}\n\n\t_closeSurvey() {\n\t\tif (this._escapeHandler) {\n\t\t\tdocument.removeEventListener('keydown', this._escapeHandler);\n\t\t\tthis._escapeHandler = null;\n\t\t}\n\n\t\t// Capture references to avoid race conditions with setTimeout\n\t\tconst surveyEl = this.surveyElement;\n\t\tconst backdropEl = this.backdropElement;\n\n\t\tif (surveyEl) {\n\t\t\tsurveyEl.style.opacity = '0';\n\t\t\tsurveyEl.style.transform =\n\t\t\t\tthis.surveyOptions.position === 'center'\n\t\t\t\t\t? 'translate(-50%, -50%) scale(0.95)'\n\t\t\t\t\t: 'translateY(20px)';\n\t\t\tsetTimeout(() => {\n\t\t\t\tif (surveyEl && surveyEl.parentNode) {\n\t\t\t\t\tsurveyEl.parentNode.removeChild(surveyEl);\n\t\t\t\t}\n\t\t\t}, 300);\n\t\t\tthis.surveyElement = null;\n\t\t}\n\n\t\tif (backdropEl) {\n\t\t\tbackdropEl.style.opacity = '0';\n\t\t\tsetTimeout(() => {\n\t\t\t\tif (backdropEl && backdropEl.parentNode) {\n\t\t\t\t\tbackdropEl.parentNode.removeChild(backdropEl);\n\t\t\t\t}\n\t\t\t}, 300);\n\t\t\tthis.backdropElement = null;\n\t\t}\n\n\t\tthis.surveyState = {\n\t\t\tscore: null,\n\t\t\tfeedback: '',\n\t\t\tcustomAnswers: {},\n\t\t\tisVisible: false,\n\t\t};\n\t}\n\n\tdestroy() {\n\t\tthis._closeSurvey();\n\t\tsuper.destroy();\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 { ChangelogWidget } from './ChangelogWidget.js';\nimport { InlineWidget } from './InlineWidget.js';\nimport { MessengerWidget } from './MessengerWidget.js';\nimport { SurveyWidget } from './SurveyWidget.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\t['survey', SurveyWidget],\n\t\t['messenger', MessengerWidget],\n\t\t['changelog', ChangelogWidget],\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\tmock: this.config.mock,\n\t\t\tenv: this.config.env,\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\t// Merge backend config as base, local config overrides\n\t\t\tif (initData.config) {\n\t\t\t\tthis.config = deepMerge(initData.config, this.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(\n\t\t\t\t'SDK must be initialized before creating widgets. Call init() first.'\n\t\t\t);\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\t/**\n\t * Fetch active surveys from the backend\n\t * @param {Object} context - Optional context for targeting\n\t * @param {string} context.page - Current page/route\n\t * @param {string} context.event - Event trigger name\n\t * @returns {Promise<Array>} Array of active survey configurations\n\t */\n\tasync getActiveSurveys(context = {}) {\n\t\tif (!this.initialized) {\n\t\t\tthrow new SDKError(\n\t\t\t\t'SDK must be initialized before fetching surveys. Call init() first.'\n\t\t\t);\n\t\t}\n\n\t\ttry {\n\t\t\tconst result = await this.apiService.getActiveSurveys(context);\n\t\t\treturn result.data || [];\n\t\t} catch (error) {\n\t\t\tthis.eventBus.emit('sdk:error', { error });\n\t\t\tthrow new SDKError(\n\t\t\t\t`Failed to fetch active surveys: ${error.message}`,\n\t\t\t\terror\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Show a survey by its backend ID\n\t * Fetches survey configuration from the backend and displays it\n\t * @param {string} surveyId - The backend survey ID\n\t * @param {Object} options - Additional display options\n\t * @param {string} options.position - Position override\n\t * @param {string} options.theme - Theme override\n\t * @param {Function} options.onSubmit - Callback when survey is submitted\n\t * @param {Function} options.onDismiss - Callback when survey is dismissed\n\t * @returns {Promise<SurveyWidget>} The survey widget instance\n\t */\n\tasync showSurveyById(surveyId, options = {}) {\n\t\tif (!this.initialized) {\n\t\t\tthrow new SDKError(\n\t\t\t\t'SDK must be initialized before showing surveys. Call init() first.'\n\t\t\t);\n\t\t}\n\n\t\t// Fetch active surveys to find the one with matching ID\n\t\tconst surveys = await this.getActiveSurveys();\n\t\tconst surveyConfig = surveys.find((s) => s.id === surveyId);\n\n\t\tif (!surveyConfig) {\n\t\t\tthrow new SDKError(\n\t\t\t\t`Survey with ID '${surveyId}' not found or not active`\n\t\t\t);\n\t\t}\n\n\t\treturn this.showSurvey({\n\t\t\tsurveyId: surveyConfig.id,\n\t\t\tsurveyType: surveyConfig.type,\n\t\t\ttitle: surveyConfig.title,\n\t\t\tdescription: surveyConfig.description,\n\t\t\tlowLabel: surveyConfig.low_label,\n\t\t\thighLabel: surveyConfig.high_label,\n\t\t\tcustomQuestions: surveyConfig.questions,\n\t\t\t...options,\n\t\t});\n\t}\n\n\t/**\n\t * Show a survey widget (local/manual mode)\n\t * For backend-driven surveys, use showSurveyById() instead\n\t * @param {Object} options - Survey options\n\t * @param {string} options.surveyId - Backend survey ID (for API tracking)\n\t * @param {string} options.surveyType - Type of survey: 'nps', 'csat', 'ces', 'custom'\n\t * @param {string} options.position - Position: 'bottom-right', 'bottom-left', 'center', 'bottom'\n\t * @param {string} options.theme - Theme: 'light', 'dark'\n\t * @param {string} options.title - Custom title\n\t * @param {string} options.description - Custom description\n\t * @param {string} options.lowLabel - Low end label\n\t * @param {string} options.highLabel - High end label\n\t * @param {Function} options.onSubmit - Callback when survey is submitted\n\t * @param {Function} options.onDismiss - Callback when survey is dismissed\n\t * @returns {SurveyWidget} The survey widget instance\n\t */\n\tshowSurvey(options = {}) {\n\t\tif (!this.initialized) {\n\t\t\tthrow new SDKError(\n\t\t\t\t'SDK must be initialized before showing surveys. Call init() first.'\n\t\t\t);\n\t\t}\n\n\t\tconst surveyWidget = this.createWidget('survey', {\n\t\t\tsurveyId: options.surveyId,\n\t\t\tsurveyType: options.surveyType || options.type || 'nps',\n\t\t\tposition: options.position || 'bottom-right',\n\t\t\ttheme: options.theme || this.config.theme || 'light',\n\t\t\ttitle: options.title,\n\t\t\tdescription: options.description,\n\t\t\tlowLabel: options.lowLabel,\n\t\t\thighLabel: options.highLabel,\n\t\t\tcustomQuestions: options.customQuestions,\n\t\t\tonSubmit: options.onSubmit,\n\t\t\tonDismiss: options.onDismiss,\n\t\t});\n\n\t\tsurveyWidget.mount();\n\t\tsurveyWidget.show();\n\n\t\treturn surveyWidget;\n\t}\n\n\t/**\n\t * Show a changelog widget with sidebar\n\t * @param {Object} options - Changelog widget options\n\t * @param {string} options.position - Position: 'bottom-right', 'bottom-left', 'top-right', 'top-left'\n\t * @param {string} options.theme - Theme: 'light', 'dark'\n\t * @param {string} options.title - Sidebar title\n\t * @param {string} options.triggerText - Text on the trigger button\n\t * @param {boolean} options.showBadge - Show notification badge\n\t * @param {string} options.viewButtonText - Text for the view update button\n\t * @param {string} options.changelogBaseUrl - Base URL for changelog links\n\t * @param {boolean} options.openInNewTab - Open changelog links in new tab (default: true)\n\t * @param {Function} options.onViewUpdate - Callback when user clicks view update\n\t * @returns {ChangelogWidget} The changelog widget instance\n\t */\n\tshowChangelog(options = {}) {\n\t\tif (!this.initialized) {\n\t\t\tthrow new SDKError(\n\t\t\t\t'SDK must be initialized before showing changelog. Call init() first.'\n\t\t\t);\n\t\t}\n\n\t\tconst changelogWidget = this.createWidget('changelog', {\n\t\t\tposition: options.position || 'bottom-right',\n\t\t\ttheme: options.theme || this.config.theme || 'light',\n\t\t\ttitle: options.title || \"What's New\",\n\t\t\ttriggerText: options.triggerText || \"What's New\",\n\t\t\tshowBadge: options.showBadge !== false,\n\t\t\tviewButtonText: options.viewButtonText || 'View Update',\n\t\t\tchangelogBaseUrl: options.changelogBaseUrl,\n\t\t\topenInNewTab: options.openInNewTab,\n\t\t\tonViewUpdate: options.onViewUpdate,\n\t\t});\n\n\t\tchangelogWidget.mount();\n\t\tchangelogWidget.show();\n\n\t\treturn changelogWidget;\n\t}\n\n\t/**\n\t * Get changelogs from the backend\n\t * @param {Object} options - Optional query parameters\n\t * @param {number} options.limit - Number of changelogs to fetch\n\t * @param {number} options.offset - Offset for pagination\n\t * @returns {Promise<Array>} Array of changelog entries\n\t */\n\tasync getChangelogs(options = {}) {\n\t\tif (!this.initialized) {\n\t\t\tthrow new SDKError(\n\t\t\t\t'SDK must be initialized before fetching changelogs. Call init() first.'\n\t\t\t);\n\t\t}\n\n\t\ttry {\n\t\t\tconst result = await this.apiService.getChangelogs(options);\n\t\t\treturn result.data || [];\n\t\t} catch (error) {\n\t\t\tthis.eventBus.emit('sdk:error', { error });\n\t\t\tthrow new SDKError(`Failed to fetch changelogs: ${error.message}`, error);\n\t\t}\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 (\n\t\t\tthis.config.userContext ||\n\t\t\t(this.apiService ? this.apiService.getUserContext() : null)\n\t\t);\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/**\n\t * Check if feedback was recently submitted for this workspace\n\t * Uses backend tracking (preferred) with localStorage as fallback\n\t * @param {number} cooldownDays - Days to consider as \"recently\" (default: 30)\n\t * @returns {boolean} true if feedback was submitted within the cooldown period\n\t */\n\thasFeedbackBeenSubmitted(cooldownDays = 30) {\n\t\tconst cooldownMs = cooldownDays * 24 * 60 * 60 * 1000;\n\t\tconst now = Date.now();\n\n\t\t// Check backend tracking first (from init response)\n\t\tif (this.config.last_feedback_at) {\n\t\t\ttry {\n\t\t\t\tconst backendTimestamp = new Date(this.config.last_feedback_at).getTime();\n\t\t\t\tif ((now - backendTimestamp) < cooldownMs) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t} catch (e) {\n\t\t\t\t// Invalid date format, continue to localStorage check\n\t\t\t}\n\t\t}\n\n\t\t// Fallback to localStorage\n\t\ttry {\n\t\t\tconst storageKey = `feedback_submitted_${this.config.workspace}`;\n\t\t\tconst stored = localStorage.getItem(storageKey);\n\t\t\tif (!stored) return false;\n\n\t\t\tconst data = JSON.parse(stored);\n\t\t\treturn (now - data.submittedAt) < cooldownMs;\n\t\t} catch (e) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Clear the feedback submission tracking (allow showing widgets again)\n\t */\n\tclearFeedbackSubmissionTracking() {\n\t\ttry {\n\t\t\tconst storageKey = `feedback_submitted_${this.config.workspace}`;\n\t\t\tlocalStorage.removeItem(storageKey);\n\t\t\tthis.eventBus.emit('feedback:trackingCleared');\n\t\t} catch (e) {\n\t\t\tconsole.warn('Failed to clear feedback tracking:', e);\n\t\t}\n\t}\n\n\t_detectEnvironment() {\n\t\tif (typeof window === 'undefined') {\n\t\t\treturn 'production';\n\t\t}\n\n\t\tconst hostname = window.location.hostname.toLowerCase();\n\n\t\tif (\n\t\t\thostname.includes('staging') ||\n\t\t\thostname.includes('localhost') ||\n\t\t\thostname.includes('127.0.0.1') ||\n\t\t\thostname.includes('.local')\n\t\t) {\n\t\t\treturn 'staging';\n\t\t}\n\n\t\treturn 'production';\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\tmock: false,\n\t\t\tenv: this._detectEnvironment(),\n\t\t};\n\n\t\tconst mergedConfig = deepMerge(\n\t\t\tdeepMerge(defaultConfig, existingConfig),\n\t\t\tnewConfig\n\t\t);\n\n\t\tif (!newConfig.env && !existingConfig.env) {\n\t\t\tmergedConfig.env = this._detectEnvironment();\n\t\t}\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(\n\t\t\t\t'User context must include at least user_id or email'\n\t\t\t);\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(\n\t\t\t\t\t`User context field '${key}' must be of type '${expectedType}'`\n\t\t\t\t);\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:\n\t\t\t\tauthData.company || authData.organization\n\t\t\t\t\t? {\n\t\t\t\t\t\t\tid: authData.company?.id || authData.organization?.id,\n\t\t\t\t\t\t\tname: authData.company?.name || authData.organization?.name,\n\t\t\t\t\t\t\tmonthly_spend: authData.company?.monthly_spend,\n\t\t\t\t\t\t}\n\t\t\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 { MESSENGER_STYLES } from './styles/messengerStyles.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 { ChangelogWidget } from './widgets/ChangelogWidget.js';\nimport { InlineWidget } from './widgets/InlineWidget.js';\nimport { MessengerWidget } from './widgets/MessengerWidget.js';\nimport { SurveyWidget } from './widgets/SurveyWidget.js';\nimport { TabWidget } from './widgets/TabWidget.js';\nimport { WidgetFactory } from './widgets/WidgetFactory.js';\n\nfunction injectStyles() {\n\tif (\n\t\ttypeof document !== 'undefined' &&\n\t\t!document.querySelector('#feedback-sdk-styles')\n\t) {\n\t\tconst style = document.createElement('style');\n\t\tstyle.id = 'feedback-sdk-styles';\n\t\tstyle.textContent = CSS_STYLES + MESSENGER_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\tChangelogWidget,\n\tTabWidget,\n\tInlineWidget,\n\tSurveyWidget,\n\tMessengerWidget,\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\tChangelogWidget,\n\tConfigError,\n\tEventBus,\n\tFeedbackSDK,\n\thelpers,\n\tInlineWidget,\n\tMessengerWidget,\n\tSDKError,\n\tSurveyWidget,\n\tTabWidget,\n\tValidationError,\n\tWidgetError,\n\tWidgetFactory,\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","MOCK_CONFIG","primaryColor","backgroundColor","textColor","boardId","size","displayMode","MOCK_CHANGELOGS","id","title","excerpt","description","cover_image","slug","published_at","labels","color","MOCK_CONVERSATIONS","subject","last_message_at","Date","now","toISOString","created_at","unread","assigned_user","avatar","MOCK_MESSAGES","conv_1","content","sender_type","sender_name","sender_avatar","conv_2","MOCK_HELP_COLLECTIONS","articleCount","icon","url","MOCK_SURVEYS","type","low_label","high_label","trigger","ENV_URLS","production","base","withWorkspace","workspace","staging","APIService","config","sessionToken","sessionExpiry","userContext","mock","env","apiUrl","baseURL","envConfig","_loadStoredSession","init","isSessionValid","error","_storeSession","expiresIn","payload","user","_makeRequest","method","body","JSON","stringify","headers","session_token","expires_in","submitFeedback","feedbackData","Promise","resolve","setTimeout","success","data","board","board_id","attachments","Authorization","getActiveSurveys","context","queryParams","URLSearchParams","currentUrl","window","location","href","append","deviceInfo","_getDeviceInfo","device","browser","os","userProperties","endpoint","toString","navigator","ua","userAgent","test","includes","submitSurveyResponse","surveyId","responseData","survey_id","rating","feedback","answers","dismissSurvey","getMessengerSettings","enabled","greeting_message","team_name","response_time","checkAgentsOnline","agents_online","online_count","getConversations","options","meta","total","length","page","limit","params","getConversation","conversationId","find","c","messages","getMessages","startConversation","newConv","unshift","sendMessage","newMessage","push","sendTypingIndicator","isTyping","is_typing","markConversationAsRead","getUnreadCount","count","reduce","sum","unread_count","unread_conversations","submitRating","comment","identifyContact","getHelpCollections","searchHelpArticles","query","filter","toLowerCase","q","getChangelogs","offset","setUserContext","localStorage","setItem","getUserContext","clearSession","removeItem","sessionData","token","expiry","stored","getItem","parse","fetch","ok","errorMessage","json","e","text","contentType","get","EventBus","events","Map","on","event","callback","has","set","off","callbacks","index","indexOf","splice","emit","forEach","console","once","unsubscribe","clear","getListenerCount","generateId","prefix","Math","random","substring","deepMerge","target","source","result","key","hasOwnProperty","Array","isArray","isBrowser","document","func","wait","timeout","args","clearTimeout","ms","string","replace","bytes","i","floor","log","parseFloat","pow","toFixed","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","email","trim","str","div","createElement","textContent","innerHTML","scrollIntoView","behavior","block","inline","lastKey","pop","lastFunc","lastRan","required","missing","join","BaseWidget","static","sdk","apiService","container","position","autoShow","showBackdrop","customStyles","suppressAfterSubmission","suppressionDays","DEFAULT_COOLDOWN_DAYS","panelElement","backdropElement","mounted","destroyed","state","isOpen","isLoading","isSubmitting","errors","_bindMethods","mount","_hasRecentlySubmitted","eventBus","widget","reason","querySelector","_render","appendChild","_attachEvents","onMount","show","style","display","hide","openPanel","_showLoadingModal","_hideLoadingModal","_renderPanel","requestAnimationFrame","classList","add","className","loadingElement","theme","remove","closePanel","parentNode","removeChild","_resetForm","_hideError","_updateSubmitButton","_showError","_trackSubmission","_showSuccessMessage","handleConfigUpdate","newConfig","_updateTheme","destroy","onDestroy","storageKey","STORAGE_KEY","submittedAt","warn","cooldownMs","last_feedback_at","getTime","clearSubmissionTracking","shouldShow","bind","addEventListener","modeClass","sizeClass","setProperty","_getPanelHTML","_attachPanelEvents","firstInput","focus","panel","preventDefault","handleEscape","removeEventListener","submitBtn","disabled","errorElement","notification","closeNotification","opacity","openModal","closeModal","ButtonWidget","isMinimized","button","Object","assign","minimizeIcon","expandIcon","stopPropagation","minimize","restore","closest","transform","updateText","textEl","updatePosition","ChangelogWidget","changelogs","modalElement","sidebarElement","currentIndex","triggerText","showBadge","openSidebar","_createModal","_loadChangelogs","_renderCurrentChangelog","overflow","_escapeHandler","listModalElement","_createListModal","_renderChangelogList","_showConfetti","listModalBackdropElement","colors","confetti","animationDelay","animationDuration","shapes","shape","borderRadius","closeSidebar","_listModalEscapeHandler","map","changelog","_renderChangelogListItem","querySelectorAll","item","_handleViewUpdate","hasImage","image","imageUrl","date","_formatDate","label","_getContrastColor","hasMultiple","viewButtonText","_","dot","parseInt","dataset","changelogBaseUrl","openInNewTab","open","onViewUpdate","dateString","toLocaleDateString","year","month","day","hexColor","hex","substr","hideBadge","badge","nextChangelog","prevChangelog","refresh","InlineWidget","form","textarea","originalContent","updateTitle","titleElement","setPlaceholder","placeholder","input","MessengerState","currentView","unreadCount","activeConversationId","conversations","helpArticles","helpSearchQuery","homeChangelogItems","changelogItems","teamName","teamAvatars","welcomeMessage","enableHelp","enableChangelog","agentsOnline","onlineCount","responseTime","typingUsers","isLoadingMessages","_listeners","Set","subscribe","delete","_notify","changeType","cb","setView","view","previousView","setOpen","setActiveConversation","setConversations","_updateUnreadCount","addConversation","conversation","setMessages","addMessage","conv","lastMessage","lastMessageTime","timestamp","isOwn","markAsRead","setHelpArticles","articles","setHelpSearchQuery","setHomeChangelogItems","items","setChangelogItems","getActiveConversation","getActiveMessages","getFilteredHelpArticles","article","reset","MessengerLauncher","_unsubscribe","render","_updateContent","_updateIcon","_updateBadge","badgeHtml","chatIcon","closeIcon","existingBadge","NavigationTabs","_updateActiveTab","_getTabs","tabs","_getHomeIcon","_getMessagesIcon","_getHelpIcon","_getChangelogIcon","tabsHtml","tab","isActive","tabId","toggle","MessengerPanel","navigationTabs","currentViewComponent","viewRegistry","registerView","ViewClass","_renderCurrentView","viewsContainer","setHeader","headerContent","header","ChangelogView","_updateChangelogList","avatarsHtml","_renderTeamAvatars","changelogContainer","_renderChangelogCard","_attachChangelogEvents","_renderEmptyState","tagsHtml","tags","tag","dateStr","publishedAt","coverImage","_truncateText","avatars","slice","startsWith","charAt","toUpperCase","maxLength","card","changelogId","changelogItem","n","onChangelogClick","ChatView","_typingTimeout","_isTyping","_typingIndicator","_hideTypingIndicator","_appendMessage","_scrollToBottom","_showTypingIndicator","userName","isNewConversation","messagesHtml","msg","_renderMessage","avatarHtml","_renderConversationAvatar","isOnline","messageClass","timeStr","_formatMessageTime","_formatMessageContent","_renderSenderAvatar","sender","avatarUrl","participants","p","toLocaleTimeString","hour","minute","hour12","messagesContainer","emptyState","messageHtml","tempDiv","firstElementChild","scrollTop","scrollHeight","sendBtn","min","_startTyping","shiftKey","_sendMessage","_stopTyping","onStartConversation","onSendMessage","onTyping","ConversationsView","_renderAvatarStack","conversationsHtml","_renderConversationItem","unreadClass","timeAgo","_formatTimeAgo","_renderConversationAvatars","_truncateMessage","_getAvatarColor","diffMs","diffMins","diffHours","diffDays","closeBtn","convId","onSelectConversation","newMsgBtn","_startNewConversation","onStartNewConversation","HelpView","_updateCollectionsList","searchQuery","collectionCount","collectionsContainer","collections","filteredCollections","headerEl","collection","_renderCollectionItem","_attachCollectionEvents","searchTimeout","collectionId","onArticleClick","HomeView","recentChangelogHtml","_renderRecentChangelog","logoUrl","_renderAvailabilityStatus","_renderFeaturedCard","featuredContent","action","coverText","seeAllBtn","featuredBtn","WebSocketService","ws","reconnectAttempts","maxReconnectAttempts","reconnectDelay","pingInterval","isConnected","_onOpen","_onMessage","_onClose","_onError","connect","_emit","_startMockResponses","wsProtocol","protocol","wsURL","encodeURIComponent","WebSocket","onopen","onmessage","onclose","onerror","_scheduleReconnect","disconnect","clearInterval","close","_mockInterval","send","readyState","OPEN","setInterval","code","delay","conversation_id","user_id","user_name","is_agent","simulateMessage","MessengerWidget","messengerOptions","messengerState","launcher","wsService","_wsUnsubscribers","_handleOpenChange","_handleWebSocketMessage","_handleTypingStarted","_handleTypingStopped","zIndex","_handleSendMessage","_handleStartConversation","_handleSelectConversation","_handleNewConversationClick","_stateUnsubscribe","messageContent","startNewConversation","fetchMessages","mockResponse","localMessage","_initWebSocket","navigateTo","setUnreadCount","getState","loadInitialData","_fetchConversations","_fetchHelpArticles","homeItems","_fetchChangelog","preview","snippet","article_count","newConversation","checkAgentAvailability","mappedItems","_availabilityInterval","unsub","SurveyWidget","surveyOptions","surveyType","lowLabel","highLabel","customQuestions","onSubmit","onDismiss","surveyState","score","customAnswers","isVisible","_renderSurvey","_closeSurvey","_getSurveyConfig","positionStyles","_getPositionStyles","themeStyles","_handleDismiss","surveyElement","cssText","html","_attachSurveyEvents","configs","nps","csat","emoji","ces","custom","_renderCustomQuestions","_renderQuestionInput","freq","question","opt","positions","center","_handleSubmit","_attachTypeSpecificEvents","btn","_selectNPS","borderColor","_selectCSAT","_selectCES","_selectFrequency","select","background","btnScore","frequency","_showSuccessNotification","existing","insertBefore","transition","surveyEl","backdropEl","TabWidget","_getHoverTransform","textElement","WidgetFactory","register","WidgetClass","widgets","create","availableTypes","from","getAvailableTypes","isTypeRegistered","unregister","getWidgetClass","FeedbackSDK","_validateAndMergeConfig","initialized","alreadyInitialized","initData","createWidget","widgetOptions","getWidget","showSurveyById","surveyConfig","s","showSurvey","questions","surveyWidget","showChangelog","changelogWidget","getAllWidgets","values","destroyWidget","destroyAllWidgets","updateConfig","oldConfig","reinitialize","newUserContext","removeAllListeners","hasFeedbackBeenSubmitted","cooldownDays","clearFeedbackSubmissionTracking","_detectEnvironment","hostname","existingConfig","mergedConfig","debug","_validateUserContext","validStructure","custom_fields","company","expectedType","entries","createAndInit","extractUserContextFromAuth","authData","sub","display_name","full_name","role","plan","subscription","organization","monthly_spend","injectStyles","CSS_STYLES","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"],"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/ChangelogWidget.js","../src/widgets/InlineWidget.js","../src/core/WebSocketService.js","../src/widgets/messenger/MessengerState.js","../src/widgets/messenger/components/MessengerLauncher.js","../src/widgets/messenger/components/NavigationTabs.js","../src/widgets/messenger/components/MessengerPanel.js","../src/widgets/messenger/views/ChangelogView.js","../src/widgets/messenger/views/ChatView.js","../src/widgets/messenger/views/ConversationsView.js","../src/widgets/messenger/views/HelpView.js","../src/widgets/messenger/views/HomeView.js","../src/widgets/MessengerWidget.js","../src/widgets/SurveyWidget.js","../src/widgets/TabWidget.js","../src/widgets/WidgetFactory.js","../src/core/FeedbackSDK.js","../src/index.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\nconst MOCK_CONFIG = {\n\tprimaryColor: '#21244A',\n\tbackgroundColor: '#ffffff',\n\ttextColor: '#1F2937',\n\tboardId: 'feature-requests',\n\tsize: 'medium',\n\tdisplayMode: 'modal',\n};\n\n// Mock changelogs for development\nconst MOCK_CHANGELOGS = [\n\t{\n\t\tid: 'changelog_1',\n\t\ttitle:\n\t\t\t'Feature prioritization, multiple roadmaps, and feature request analytics.',\n\t\texcerpt:\n\t\t\t'We are super excited to bring you the long-waited feature prioritization together with many quality updates!',\n\t\tdescription:\n\t\t\t'We are super excited to bring you the long-waited feature prioritization together with many quality updates!',\n\t\tcover_image:\n\t\t\t'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAwIiBoZWlnaHQ9IjI1MCIgdmlld0JveD0iMCAwIDQwMCAyNTAiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHJlY3Qgd2lkdGg9IjQwMCIgaGVpZ2h0PSIyNTAiIGZpbGw9IiNEQkVBRkUiLz48cmVjdCB4PSIyMCIgeT0iMjAiIHdpZHRoPSIzNjAiIGhlaWdodD0iMjEwIiByeD0iOCIgZmlsbD0id2hpdGUiIHN0cm9rZT0iIzE1NUVFRiIgc3Ryb2tlLXdpZHRoPSIyIi8+PHJlY3QgeD0iMzAiIHk9IjQwIiB3aWR0aD0iODAiIGhlaWdodD0iOCIgcng9IjQiIGZpbGw9IiNFNUU3RUIiLz48cmVjdCB4PSIzMCIgeT0iNjAiIHdpZHRoPSIxNDAiIGhlaWdodD0iNDAiIHJ4PSI0IiBmaWxsPSIjRjNGNEY2Ii8+PHRleHQgeD0iNDAiIHk9Ijg1IiBmb250LWZhbWlseT0ic3lzdGVtLXVpIiBmb250LXNpemU9IjE2IiBmb250LXdlaWdodD0iNjAwIiBmaWxsPSIjMUYyOTM3Ij4yMDA8L3RleHQ+PHRleHQgeD0iNDAiIHk9Ijk1IiBmb250LWZhbWlseT0ic3lzdGVtLXVpIiBmb250LXNpemU9IjgiIGZpbGw9IiM2QjcyODAiPlBvc3RzPC90ZXh0PjxyZWN0IHg9IjE4MCIgeT0iNjAiIHdpZHRoPSI4MCIgaGVpZ2h0PSI0MCIgcng9IjQiIGZpbGw9IiNGM0Y0RjYiLz48cmVjdCB4PSIyNzAiIHk9IjYwIiB3aWR0aD0iODAiIGhlaWdodD0iNDAiIHJ4PSI0IiBmaWxsPSIjRjNGNEY2Ii8+PHBhdGggZD0iTTMwIDEzMEgzNzBNMzAgMTUwSDM3ME0zMCAxNzBIMzcwTTMwIDE5MEgzNzAiIHN0cm9rZT0iI0U1RTdFQiIgc3Ryb2tlLXdpZHRoPSIxIi8+PHBhdGggZD0iTTUwIDE2MEwxMDAgMTQwTDE1MCAxNTBMMjAwIDEzMEwyNTAgMTM1TDMwMCAxMjBMMzUwIDEyNSIgc3Ryb2tlPSIjMTU1RUVGIiBzdHJva2Utd2lkdGg9IjIiIGZpbGw9Im5vbmUiLz48L3N2Zz4=',\n\t\tslug: 'feature-prioritization-roadmaps-analytics',\n\t\tpublished_at: '2025-03-15T10:00:00Z',\n\t\tlabels: [\n\t\t\t{ name: 'New Feature', color: '#10B981' },\n\t\t\t{ name: 'Analytics', color: '#6366F1' },\n\t\t],\n\t\tstatus: 'published',\n\t},\n\t{\n\t\tid: 'changelog_2',\n\t\ttitle: 'Dark mode support and UI improvements',\n\t\texcerpt:\n\t\t\t'You asked for it, we delivered! Dark mode is now available across all pages.',\n\t\tdescription:\n\t\t\t'You asked for it, we delivered! Dark mode is now available across all pages.',\n\t\tcover_image:\n\t\t\t'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAwIiBoZWlnaHQ9IjI1MCIgdmlld0JveD0iMCAwIDQwMCAyNTAiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHJlY3Qgd2lkdGg9IjQwMCIgaGVpZ2h0PSIyNTAiIGZpbGw9IiMxRjI5MzciLz48cmVjdCB4PSIyMCIgeT0iMjAiIHdpZHRoPSIzNjAiIGhlaWdodD0iMjEwIiByeD0iOCIgZmlsbD0iIzM3NDE1MSIgc3Ryb2tlPSIjNEI1NTYzIiBzdHJva2Utd2lkdGg9IjEiLz48Y2lyY2xlIGN4PSIyMDAiIGN5PSIxMjUiIHI9IjQwIiBmaWxsPSIjRkJCRjI0Ii8+PHBhdGggZD0iTTIyMCAxMjVDMjIwIDEzNiAyMTEgMTQ1IDIwMCAxNDVDMTg5IDE0NSAxODAgMTM2IDE4MCAxMjVDMTgwIDExNCAxODkgMTA1IDIwMCAxMDVDMjExIDEwNSAyMjAgMTE0IDIyMCAxMjVaIiBmaWxsPSIjMUYyOTM3Ii8+PC9zdmc+',\n\t\tslug: 'dark-mode-ui-improvements',\n\t\tpublished_at: '2025-03-01T10:00:00Z',\n\t\tlabels: [{ name: 'Enhancement', color: '#8B5CF6' }],\n\t\tstatus: 'published',\n\t},\n\t{\n\t\tid: 'changelog_3',\n\t\ttitle: 'Performance improvements and bug fixes',\n\t\texcerpt:\n\t\t\t'This release includes major performance improvements and several bug fixes.',\n\t\tdescription:\n\t\t\t'This release includes major performance improvements and several bug fixes.',\n\t\tslug: 'performance-improvements-bug-fixes',\n\t\tpublished_at: '2025-02-15T10:00:00Z',\n\t\tlabels: [\n\t\t\t{ name: 'Bug Fix', color: '#EF4444' },\n\t\t\t{ name: 'Performance', color: '#F59E0B' },\n\t\t],\n\t\tstatus: 'published',\n\t},\n];\n\n// Mock conversations for development\nconst MOCK_CONVERSATIONS = [\n\t{\n\t\tid: 'conv_1',\n\t\tsubject: 'Question about pricing',\n\t\tstatus: 'open',\n\t\tlast_message_at: new Date(Date.now() - 49 * 60 * 1000).toISOString(),\n\t\tcreated_at: new Date(Date.now() - 2 * 24 * 60 * 60 * 1000).toISOString(),\n\t\tunread: 1,\n\t\tassigned_user: {\n\t\t\tid: 'user_1',\n\t\t\tname: 'Sarah',\n\t\t\tavatar: null,\n\t\t},\n\t},\n\t{\n\t\tid: 'conv_2',\n\t\tsubject: 'Feature request',\n\t\tstatus: 'open',\n\t\tlast_message_at: new Date(\n\t\t\tDate.now() - 6 * 24 * 60 * 60 * 1000\n\t\t).toISOString(),\n\t\tcreated_at: new Date(Date.now() - 10 * 24 * 60 * 60 * 1000).toISOString(),\n\t\tunread: 0,\n\t\tassigned_user: {\n\t\t\tid: 'user_2',\n\t\t\tname: 'Tom',\n\t\t\tavatar: null,\n\t\t},\n\t},\n];\n\n// Mock messages for development\nconst MOCK_MESSAGES = {\n\tconv_1: [\n\t\t{\n\t\t\tid: 'msg_1',\n\t\t\tcontent: \"Hi there! 👋 I'm Sarah. How can I help you today?\",\n\t\t\tsender_type: 'agent',\n\t\t\tsender_name: 'Sarah',\n\t\t\tsender_avatar: null,\n\t\t\tcreated_at: new Date(Date.now() - 50 * 60 * 1000).toISOString(),\n\t\t},\n\t\t{\n\t\t\tid: 'msg_2',\n\t\t\tcontent: 'Hi! I have a question about your enterprise pricing.',\n\t\t\tsender_type: 'customer',\n\t\t\tcreated_at: new Date(Date.now() - 49 * 60 * 1000).toISOString(),\n\t\t},\n\t],\n\tconv_2: [\n\t\t{\n\t\t\tid: 'msg_3',\n\t\t\tcontent: \"Hello! I'm Tom from the product team.\",\n\t\t\tsender_type: 'agent',\n\t\t\tsender_name: 'Tom',\n\t\t\tsender_avatar: null,\n\t\t\tcreated_at: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString(),\n\t\t},\n\t\t{\n\t\t\tid: 'msg_4',\n\t\t\tcontent: 'I would love to see a dark mode feature!',\n\t\t\tsender_type: 'customer',\n\t\t\tcreated_at: new Date(\n\t\t\t\tDate.now() - 6 * 24 * 60 * 60 * 1000 - 30 * 60 * 1000\n\t\t\t).toISOString(),\n\t\t},\n\t\t{\n\t\t\tid: 'msg_5',\n\t\t\tcontent:\n\t\t\t\t\"Great suggestion! That feature will be available next week. I'll let you know when it's ready.\",\n\t\t\tsender_type: 'agent',\n\t\t\tsender_name: 'Tom',\n\t\t\tsender_avatar: null,\n\t\t\tcreated_at: new Date(Date.now() - 6 * 24 * 60 * 60 * 1000).toISOString(),\n\t\t},\n\t],\n};\n\n// Mock help collections for development\nconst MOCK_HELP_COLLECTIONS = [\n\t{\n\t\tid: 'collection_1',\n\t\ttitle: 'Product Overview',\n\t\tdescription: 'See how your AI-first customer service solution works.',\n\t\tarticleCount: 24,\n\t\ticon: 'ph-book-open',\n\t\turl: '#',\n\t},\n\t{\n\t\tid: 'collection_2',\n\t\ttitle: 'Getting Started',\n\t\tdescription: 'Everything you need to know to get started with Product7.',\n\t\tarticleCount: 30,\n\t\ticon: 'ph-rocket',\n\t\turl: '#',\n\t},\n\t{\n\t\tid: 'collection_3',\n\t\ttitle: 'AI Agent',\n\t\tdescription:\n\t\t\t'Resolving customer questions instantly and accurately—from live chat to email.',\n\t\tarticleCount: 82,\n\t\ticon: 'ph-robot',\n\t\turl: '#',\n\t},\n\t{\n\t\tid: 'collection_4',\n\t\ttitle: 'Channels',\n\t\tdescription:\n\t\t\t'Enabling the channels you use to communicate with customers, all from the Inbox.',\n\t\tarticleCount: 45,\n\t\ticon: 'ph-chat-circle',\n\t\turl: '#',\n\t},\n\t{\n\t\tid: 'collection_5',\n\t\ttitle: 'Billing & Payments',\n\t\tdescription: 'Manage your subscription, invoices, and payment methods.',\n\t\tarticleCount: 12,\n\t\ticon: 'ph-credit-card',\n\t\turl: '#',\n\t},\n];\n\n// Mock surveys for development\nconst MOCK_SURVEYS = [\n\t{\n\t\tid: 'mock_nps_survey',\n\t\ttype: 'nps',\n\t\ttitle: 'How likely are you to recommend us?',\n\t\tdescription: 'Your feedback helps us improve',\n\t\tlow_label: 'Not likely',\n\t\thigh_label: 'Very likely',\n\t\ttrigger: 'manual',\n\t\tstatus: 'active',\n\t},\n\t{\n\t\tid: 'mock_csat_survey',\n\t\ttype: 'csat',\n\t\ttitle: 'How satisfied are you?',\n\t\tdescription: 'Rate your experience with our product',\n\t\ttrigger: 'manual',\n\t\tstatus: 'active',\n\t},\n\t{\n\t\tid: 'mock_ces_survey',\n\t\ttype: 'ces',\n\t\ttitle: 'How easy was it?',\n\t\tdescription: 'Rate the ease of completing your task',\n\t\tlow_label: 'Very difficult',\n\t\thigh_label: 'Very easy',\n\t\ttrigger: 'manual',\n\t\tstatus: 'active',\n\t},\n];\n\n// Environment URLs\nconst ENV_URLS = {\n\tproduction: {\n\t\tbase: 'https://api.product7.io/api/v1',\n\t\twithWorkspace: (workspace) => `https://${workspace}.api.product7.io/api/v1`,\n\t},\n\tstaging: {\n\t\tbase: 'https://staging.api.product7.io/api/v1',\n\t\twithWorkspace: (workspace) =>\n\t\t\t`https://${workspace}.staging.api.product7.io/api/v1`,\n\t},\n};\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\t\tthis.mock = config.mock || false;\n\t\tthis.env = config.env || 'production';\n\n\t\tif (config.apiUrl) {\n\t\t\tthis.baseURL = config.apiUrl;\n\t\t} else {\n\t\t\tconst envConfig = ENV_URLS[this.env] || ENV_URLS.production;\n\t\t\tthis.baseURL = this.workspace\n\t\t\t\t? envConfig.withWorkspace(this.workspace)\n\t\t\t\t: envConfig.base;\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\t// Mock mode - return fake session\n\t\tif (this.mock) {\n\t\t\tthis.sessionToken = 'mock_session_' + Date.now();\n\t\t\tthis.sessionExpiry = new Date(Date.now() + 3600 * 1000);\n\t\t\tthis._storeSession();\n\t\t\treturn {\n\t\t\t\tsessionToken: this.sessionToken,\n\t\t\t\tconfig: MOCK_CONFIG,\n\t\t\t\texpiresIn: 3600,\n\t\t\t};\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\t// Mock mode - simulate success\n\t\tif (this.mock) {\n\t\t\tawait new Promise((resolve) => setTimeout(resolve, 500));\n\t\t\treturn {\n\t\t\t\tsuccess: true,\n\t\t\t\tdata: {\n\t\t\t\t\tid: 'mock_post_' + Date.now(),\n\t\t\t\t\ttitle: feedbackData.title,\n\t\t\t\t\tcontent: feedbackData.content,\n\t\t\t\t},\n\t\t\t\tmessage: 'Feedback submitted successfully!',\n\t\t\t};\n\t\t}\n\n\t\tconst payload = {\n\t\t\tboard:\n\t\t\t\tfeedbackData.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\t/**\n\t * Get active surveys for the current user/context\n\t * @param {Object} context - Optional context overrides for targeting\n\t * @param {string} context.url - Override current URL\n\t * @param {Object} context.userProperties - Additional user properties\n\t * @returns {Promise<Array>} Array of active surveys matching targeting rules\n\t */\n\tasync getActiveSurveys(context = {}) {\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\t// Mock mode - return mock surveys\n\t\tif (this.mock) {\n\t\t\tawait new Promise((resolve) => setTimeout(resolve, 200));\n\t\t\treturn {\n\t\t\t\tsuccess: true,\n\t\t\t\tdata: MOCK_SURVEYS,\n\t\t\t};\n\t\t}\n\n\t\ttry {\n\t\t\tconst queryParams = new URLSearchParams();\n\n\t\t\t// Auto-detect current URL or use provided override\n\t\t\tconst currentUrl =\n\t\t\t\tcontext.url ||\n\t\t\t\t(typeof window !== 'undefined' ? window.location.href : '');\n\t\t\tif (currentUrl) {\n\t\t\t\tqueryParams.append('url', currentUrl);\n\t\t\t}\n\n\t\t\t// Auto-detect device info\n\t\t\tconst deviceInfo = this._getDeviceInfo();\n\t\t\tif (deviceInfo.device) queryParams.append('device', deviceInfo.device);\n\t\t\tif (deviceInfo.browser) queryParams.append('browser', deviceInfo.browser);\n\t\t\tif (deviceInfo.os) queryParams.append('os', deviceInfo.os);\n\n\t\t\t// Add user properties if provided\n\t\t\tif (context.userProperties) {\n\t\t\t\tqueryParams.append(\n\t\t\t\t\t'user_properties',\n\t\t\t\t\tJSON.stringify(context.userProperties)\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst endpoint = `/widget/surveys/active${queryParams.toString() ? '?' + queryParams.toString() : ''}`;\n\n\t\t\tconst response = await this._makeRequest(endpoint, {\n\t\t\t\tmethod: 'GET',\n\t\t\t\theaders: {\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.getActiveSurveys(context);\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 get active surveys: ${error.message}`,\n\t\t\t\terror.response\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Auto-detect device, browser, and OS info\n\t * @returns {Object} Device info object\n\t */\n\t_getDeviceInfo() {\n\t\tif (typeof navigator === 'undefined') {\n\t\t\treturn { device: null, browser: null, os: null };\n\t\t}\n\n\t\tconst ua = navigator.userAgent;\n\n\t\t// Detect device type\n\t\tlet device = 'desktop';\n\t\tif (/Mobi|Android/i.test(ua)) {\n\t\t\tdevice = /Tablet|iPad/i.test(ua) ? 'tablet' : 'mobile';\n\t\t}\n\n\t\t// Detect browser\n\t\tlet browser = 'unknown';\n\t\tif (ua.includes('Firefox')) browser = 'firefox';\n\t\telse if (ua.includes('Edg')) browser = 'edge';\n\t\telse if (ua.includes('Chrome')) browser = 'chrome';\n\t\telse if (ua.includes('Safari')) browser = 'safari';\n\t\telse if (ua.includes('Opera') || ua.includes('OPR')) browser = 'opera';\n\n\t\t// Detect OS\n\t\tlet os = 'unknown';\n\t\tif (ua.includes('Windows')) os = 'windows';\n\t\telse if (ua.includes('Mac')) os = 'macos';\n\t\telse if (ua.includes('Linux')) os = 'linux';\n\t\telse if (ua.includes('Android')) os = 'android';\n\t\telse if (ua.includes('iPhone') || ua.includes('iPad')) os = 'ios';\n\n\t\treturn { device, browser, os };\n\t}\n\n\t/**\n\t * Submit a survey response\n\t * @param {string} surveyId - The survey ID\n\t * @param {Object} responseData - The survey response data\n\t * @param {number|string} responseData.rating - The rating/score value\n\t * @param {string} responseData.feedback - Optional text feedback\n\t * @param {Object} responseData.answers - For custom surveys, key-value pairs\n\t * @returns {Promise<Object>} Submission result\n\t */\n\tasync submitSurveyResponse(surveyId, responseData) {\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\tif (!surveyId) {\n\t\t\tthrow new APIError(400, 'Survey ID is required');\n\t\t}\n\n\t\t// Mock mode - simulate success\n\t\tif (this.mock) {\n\t\t\tawait new Promise((resolve) => setTimeout(resolve, 300));\n\t\t\treturn {\n\t\t\t\tsuccess: true,\n\t\t\t\tdata: {\n\t\t\t\t\tid: 'mock_response_' + Date.now(),\n\t\t\t\t\tsurvey_id: surveyId,\n\t\t\t\t\t...responseData,\n\t\t\t\t},\n\t\t\t\tmessage: 'Survey response submitted successfully!',\n\t\t\t};\n\t\t}\n\n\t\tconst payload = {\n\t\t\trating: responseData.rating,\n\t\t\tfeedback: responseData.feedback || '',\n\t\t\tanswers: responseData.answers || {},\n\t\t};\n\n\t\ttry {\n\t\t\tconst response = await this._makeRequest(\n\t\t\t\t`/widget/surveys/${surveyId}/responses`,\n\t\t\t\t{\n\t\t\t\t\tmethod: 'POST',\n\t\t\t\t\tbody: JSON.stringify(payload),\n\t\t\t\t\theaders: {\n\t\t\t\t\t\t'Content-Type': 'application/json',\n\t\t\t\t\t\tAuthorization: `Bearer ${this.sessionToken}`,\n\t\t\t\t\t},\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.submitSurveyResponse(surveyId, responseData);\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 survey response: ${error.message}`,\n\t\t\t\terror.response\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Dismiss a survey (mark as seen but not completed)\n\t * @param {string} surveyId - The survey ID to dismiss\n\t * @returns {Promise<Object>} Dismissal result\n\t */\n\tasync dismissSurvey(surveyId) {\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\tif (!surveyId) {\n\t\t\tthrow new APIError(400, 'Survey ID is required');\n\t\t}\n\n\t\t// Mock mode - simulate success\n\t\tif (this.mock) {\n\t\t\tawait new Promise((resolve) => setTimeout(resolve, 100));\n\t\t\treturn {\n\t\t\t\tsuccess: true,\n\t\t\t\tmessage: 'Survey dismissed successfully',\n\t\t\t};\n\t\t}\n\n\t\ttry {\n\t\t\tconst response = await this._makeRequest(\n\t\t\t\t`/widget/surveys/${surveyId}/dismiss`,\n\t\t\t\t{\n\t\t\t\t\tmethod: 'POST',\n\t\t\t\t\theaders: {\n\t\t\t\t\t\tAuthorization: `Bearer ${this.sessionToken}`,\n\t\t\t\t\t},\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.dismissSurvey(surveyId);\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 dismiss survey: ${error.message}`,\n\t\t\t\terror.response\n\t\t\t);\n\t\t}\n\t}\n\n\t// ==========================================\n\t// MESSENGER / CHAT ENDPOINTS\n\t// ==========================================\n\n\t/**\n\t * Get messenger settings\n\t * @returns {Promise<Object>} Messenger settings\n\t */\n\tasync getMessengerSettings() {\n\t\tif (!this.isSessionValid()) {\n\t\t\tawait this.init();\n\t\t}\n\n\t\tif (this.mock) {\n\t\t\treturn {\n\t\t\t\tstatus: true,\n\t\t\t\tdata: {\n\t\t\t\t\tenabled: true,\n\t\t\t\t\tgreeting_message: 'Hi there! How can we help you today?',\n\t\t\t\t\tteam_name: 'Support Team',\n\t\t\t\t\tresponse_time: 'Usually replies within a few minutes',\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\n\t\treturn this._makeRequest('/widget/messenger/settings', {\n\t\t\tmethod: 'GET',\n\t\t\theaders: { Authorization: `Bearer ${this.sessionToken}` },\n\t\t});\n\t}\n\n\t/**\n\t * Check if agents are online\n\t * @returns {Promise<Object>} Agent availability status\n\t */\n\tasync checkAgentsOnline() {\n\t\tif (!this.isSessionValid()) {\n\t\t\tawait this.init();\n\t\t}\n\n\t\tif (this.mock) {\n\t\t\treturn {\n\t\t\t\tstatus: true,\n\t\t\t\tdata: {\n\t\t\t\t\tagents_online: true,\n\t\t\t\t\tonline_count: 2,\n\t\t\t\t\tresponse_time: 'Usually replies within a few minutes',\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\n\t\treturn this._makeRequest('/widget/messenger/agents/online', {\n\t\t\tmethod: 'GET',\n\t\t\theaders: { Authorization: `Bearer ${this.sessionToken}` },\n\t\t});\n\t}\n\n\t/**\n\t * Get all conversations for the current contact\n\t * @param {Object} options - Query options\n\t * @param {number} options.page - Page number\n\t * @param {number} options.limit - Items per page\n\t * @returns {Promise<Object>} Conversations list\n\t */\n\tasync getConversations(options = {}) {\n\t\tif (!this.isSessionValid()) {\n\t\t\tawait this.init();\n\t\t}\n\n\t\tif (this.mock) {\n\t\t\tawait new Promise((resolve) => setTimeout(resolve, 300));\n\t\t\treturn {\n\t\t\t\tstatus: true,\n\t\t\t\tdata: MOCK_CONVERSATIONS,\n\t\t\t\tmeta: { total: MOCK_CONVERSATIONS.length, page: 1, limit: 20 },\n\t\t\t};\n\t\t}\n\n\t\tconst params = new URLSearchParams();\n\t\tif (options.page) params.append('page', options.page);\n\t\tif (options.limit) params.append('limit', options.limit);\n\n\t\tconst endpoint = `/widget/messenger/conversations${params.toString() ? '?' + params.toString() : ''}`;\n\t\treturn this._makeRequest(endpoint, {\n\t\t\tmethod: 'GET',\n\t\t\theaders: { Authorization: `Bearer ${this.sessionToken}` },\n\t\t});\n\t}\n\n\t/**\n\t * Get a single conversation with messages\n\t * @param {string} conversationId - Conversation ID\n\t * @returns {Promise<Object>} Conversation with messages\n\t */\n\tasync getConversation(conversationId) {\n\t\tif (!this.isSessionValid()) {\n\t\t\tawait this.init();\n\t\t}\n\n\t\tif (this.mock) {\n\t\t\tawait new Promise((resolve) => setTimeout(resolve, 200));\n\t\t\tconst conv = MOCK_CONVERSATIONS.find((c) => c.id === conversationId);\n\t\t\treturn {\n\t\t\t\tstatus: true,\n\t\t\t\tdata: {\n\t\t\t\t\t...conv,\n\t\t\t\t\tmessages: MOCK_MESSAGES[conversationId] || [],\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\n\t\treturn this._makeRequest(\n\t\t\t`/widget/messenger/conversations/${conversationId}`,\n\t\t\t{\n\t\t\t\tmethod: 'GET',\n\t\t\t\theaders: { Authorization: `Bearer ${this.sessionToken}` },\n\t\t\t}\n\t\t);\n\t}\n\n\t/**\n\t * Get messages for a conversation\n\t * @param {string} conversationId - Conversation ID\n\t * @param {Object} options - Query options\n\t * @returns {Promise<Object>} Messages list\n\t */\n\tasync getMessages(conversationId, options = {}) {\n\t\tif (!this.isSessionValid()) {\n\t\t\tawait this.init();\n\t\t}\n\n\t\tif (this.mock) {\n\t\t\tawait new Promise((resolve) => setTimeout(resolve, 200));\n\t\t\treturn {\n\t\t\t\tstatus: true,\n\t\t\t\tdata: MOCK_MESSAGES[conversationId] || [],\n\t\t\t};\n\t\t}\n\n\t\tconst params = new URLSearchParams();\n\t\tif (options.page) params.append('page', options.page);\n\t\tif (options.limit) params.append('limit', options.limit);\n\n\t\tconst endpoint = `/widget/messenger/conversations/${conversationId}/messages${params.toString() ? '?' + params.toString() : ''}`;\n\t\treturn this._makeRequest(endpoint, {\n\t\t\tmethod: 'GET',\n\t\t\theaders: { Authorization: `Bearer ${this.sessionToken}` },\n\t\t});\n\t}\n\n\t/**\n\t * Start a new conversation\n\t * @param {Object} data - Conversation data\n\t * @param {string} data.message - Initial message content\n\t * @param {string} data.subject - Optional subject\n\t * @returns {Promise<Object>} Created conversation\n\t */\n\tasync startConversation(data) {\n\t\tif (!this.isSessionValid()) {\n\t\t\tawait this.init();\n\t\t}\n\n\t\tif (this.mock) {\n\t\t\tawait new Promise((resolve) => setTimeout(resolve, 300));\n\t\t\tconst newConv = {\n\t\t\t\tid: 'conv_' + Date.now(),\n\t\t\t\tsubject: data.subject || 'New conversation',\n\t\t\t\tstatus: 'open',\n\t\t\t\tlast_message_at: new Date().toISOString(),\n\t\t\t\tcreated_at: new Date().toISOString(),\n\t\t\t\tmessages: [\n\t\t\t\t\t{\n\t\t\t\t\t\tid: 'msg_' + Date.now(),\n\t\t\t\t\t\tcontent: data.message,\n\t\t\t\t\t\tsender_type: 'customer',\n\t\t\t\t\t\tcreated_at: new Date().toISOString(),\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t};\n\t\t\tMOCK_CONVERSATIONS.unshift(newConv);\n\t\t\tMOCK_MESSAGES[newConv.id] = newConv.messages;\n\t\t\treturn { status: true, data: newConv };\n\t\t}\n\n\t\treturn this._makeRequest('/widget/messenger/conversations', {\n\t\t\tmethod: 'POST',\n\t\t\theaders: {\n\t\t\t\t'Content-Type': 'application/json',\n\t\t\t\tAuthorization: `Bearer ${this.sessionToken}`,\n\t\t\t},\n\t\t\tbody: JSON.stringify({\n\t\t\t\tmessage: data.message,\n\t\t\t\tsubject: data.subject || '',\n\t\t\t}),\n\t\t});\n\t}\n\n\t/**\n\t * Send a message in a conversation\n\t * @param {string} conversationId - Conversation ID\n\t * @param {Object} data - Message data\n\t * @param {string} data.content - Message content\n\t * @returns {Promise<Object>} Sent message\n\t */\n\tasync sendMessage(conversationId, data) {\n\t\tif (!this.isSessionValid()) {\n\t\t\tawait this.init();\n\t\t}\n\n\t\tif (this.mock) {\n\t\t\tawait new Promise((resolve) => setTimeout(resolve, 200));\n\t\t\tconst newMessage = {\n\t\t\t\tid: 'msg_' + Date.now(),\n\t\t\t\tcontent: data.content,\n\t\t\t\tsender_type: 'customer',\n\t\t\t\tcreated_at: new Date().toISOString(),\n\t\t\t};\n\t\t\tif (!MOCK_MESSAGES[conversationId]) {\n\t\t\t\tMOCK_MESSAGES[conversationId] = [];\n\t\t\t}\n\t\t\tMOCK_MESSAGES[conversationId].push(newMessage);\n\t\t\treturn { status: true, data: newMessage };\n\t\t}\n\n\t\treturn this._makeRequest(\n\t\t\t`/widget/messenger/conversations/${conversationId}/messages`,\n\t\t\t{\n\t\t\t\tmethod: 'POST',\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\tbody: JSON.stringify({ content: data.content }),\n\t\t\t}\n\t\t);\n\t}\n\n\t/**\n\t * Send typing indicator\n\t * @param {string} conversationId - Conversation ID\n\t * @param {boolean} isTyping - Whether user is typing\n\t * @returns {Promise<Object>} Response\n\t */\n\tasync sendTypingIndicator(conversationId, isTyping) {\n\t\tif (!this.isSessionValid()) {\n\t\t\tawait this.init();\n\t\t}\n\n\t\tif (this.mock) {\n\t\t\treturn { status: true };\n\t\t}\n\n\t\treturn this._makeRequest(\n\t\t\t`/widget/messenger/conversations/${conversationId}/typing`,\n\t\t\t{\n\t\t\t\tmethod: 'POST',\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\tbody: JSON.stringify({ is_typing: isTyping }),\n\t\t\t}\n\t\t);\n\t}\n\n\t/**\n\t * Mark conversation as read\n\t * @param {string} conversationId - Conversation ID\n\t * @returns {Promise<Object>} Response\n\t */\n\tasync markConversationAsRead(conversationId) {\n\t\tif (!this.isSessionValid()) {\n\t\t\tawait this.init();\n\t\t}\n\n\t\tif (this.mock) {\n\t\t\treturn { status: true };\n\t\t}\n\n\t\treturn this._makeRequest(\n\t\t\t`/widget/messenger/conversations/${conversationId}/read`,\n\t\t\t{\n\t\t\t\tmethod: 'POST',\n\t\t\t\theaders: { Authorization: `Bearer ${this.sessionToken}` },\n\t\t\t}\n\t\t);\n\t}\n\n\t/**\n\t * Get unread count\n\t * @returns {Promise<Object>} Unread count data\n\t */\n\tasync getUnreadCount() {\n\t\tif (!this.isSessionValid()) {\n\t\t\tawait this.init();\n\t\t}\n\n\t\tif (this.mock) {\n\t\t\tconst count = MOCK_CONVERSATIONS.reduce(\n\t\t\t\t(sum, c) => sum + (c.unread || 0),\n\t\t\t\t0\n\t\t\t);\n\t\t\treturn {\n\t\t\t\tstatus: true,\n\t\t\t\tdata: { unread_count: count, unread_conversations: count > 0 ? 1 : 0 },\n\t\t\t};\n\t\t}\n\n\t\treturn this._makeRequest('/widget/messenger/unread', {\n\t\t\tmethod: 'GET',\n\t\t\theaders: { Authorization: `Bearer ${this.sessionToken}` },\n\t\t});\n\t}\n\n\t/**\n\t * Submit conversation rating\n\t * @param {string} conversationId - Conversation ID\n\t * @param {Object} data - Rating data\n\t * @param {number} data.rating - Rating (1-5 or thumbs up/down)\n\t * @param {string} data.comment - Optional comment\n\t * @returns {Promise<Object>} Response\n\t */\n\tasync submitRating(conversationId, data) {\n\t\tif (!this.isSessionValid()) {\n\t\t\tawait this.init();\n\t\t}\n\n\t\tif (this.mock) {\n\t\t\treturn { status: true, message: 'Thank you for your feedback!' };\n\t\t}\n\n\t\treturn this._makeRequest(\n\t\t\t`/widget/messenger/conversations/${conversationId}/rate`,\n\t\t\t{\n\t\t\t\tmethod: 'POST',\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\tbody: JSON.stringify({\n\t\t\t\t\trating: data.rating,\n\t\t\t\t\tcomment: data.comment || '',\n\t\t\t\t}),\n\t\t\t}\n\t\t);\n\t}\n\n\t/**\n\t * Identify contact (for logged-in users)\n\t * @param {Object} data - Contact data\n\t * @param {string} data.email - Email address\n\t * @param {string} data.name - Name\n\t * @returns {Promise<Object>} Response\n\t */\n\tasync identifyContact(data) {\n\t\tif (!this.isSessionValid()) {\n\t\t\tawait this.init();\n\t\t}\n\n\t\tif (this.mock) {\n\t\t\treturn { status: true, message: 'Contact identified' };\n\t\t}\n\n\t\treturn this._makeRequest('/widget/messenger/identify', {\n\t\t\tmethod: 'POST',\n\t\t\theaders: {\n\t\t\t\t'Content-Type': 'application/json',\n\t\t\t\tAuthorization: `Bearer ${this.sessionToken}`,\n\t\t\t},\n\t\t\tbody: JSON.stringify(data),\n\t\t});\n\t}\n\n\t// ==========================================\n\t// HELP ARTICLES ENDPOINTS\n\t// ==========================================\n\n\t/**\n\t * Get help collections\n\t * @param {Object} options - Query options\n\t * @returns {Promise<Object>} Collections list\n\t */\n\tasync getHelpCollections(options = {}) {\n\t\tif (!this.isSessionValid()) {\n\t\t\tawait this.init();\n\t\t}\n\n\t\tif (this.mock) {\n\t\t\tawait new Promise((resolve) => setTimeout(resolve, 200));\n\t\t\treturn { status: true, data: MOCK_HELP_COLLECTIONS };\n\t\t}\n\n\t\tconst params = new URLSearchParams();\n\t\tif (options.limit) params.append('limit', options.limit);\n\n\t\tconst endpoint = `/widget/help/collections${params.toString() ? '?' + params.toString() : ''}`;\n\t\treturn this._makeRequest(endpoint, {\n\t\t\tmethod: 'GET',\n\t\t\theaders: { Authorization: `Bearer ${this.sessionToken}` },\n\t\t});\n\t}\n\n\t/**\n\t * Search help articles\n\t * @param {string} query - Search query\n\t * @param {Object} options - Query options\n\t * @returns {Promise<Object>} Search results\n\t */\n\tasync searchHelpArticles(query, options = {}) {\n\t\tif (!this.isSessionValid()) {\n\t\t\tawait this.init();\n\t\t}\n\n\t\tif (this.mock) {\n\t\t\tawait new Promise((resolve) => setTimeout(resolve, 200));\n\t\t\tconst filtered = MOCK_HELP_COLLECTIONS.filter(\n\t\t\t\t(c) =>\n\t\t\t\t\tc.title.toLowerCase().includes(query.toLowerCase()) ||\n\t\t\t\t\tc.description.toLowerCase().includes(query.toLowerCase())\n\t\t\t);\n\t\t\treturn { status: true, data: filtered };\n\t\t}\n\n\t\tconst params = new URLSearchParams({ q: query });\n\t\tif (options.limit) params.append('limit', options.limit);\n\n\t\treturn this._makeRequest(`/widget/help/search?${params.toString()}`, {\n\t\t\tmethod: 'GET',\n\t\t\theaders: { Authorization: `Bearer ${this.sessionToken}` },\n\t\t});\n\t}\n\n\t// ==========================================\n\t// CHANGELOG ENDPOINTS\n\t// ==========================================\n\n\t/**\n\t * Get published changelogs\n\t * @param {Object} options - Optional query parameters\n\t * @param {number} options.limit - Number of changelogs to fetch\n\t * @param {number} options.offset - Offset for pagination\n\t * @returns {Promise<Object>} Changelogs response\n\t */\n\tasync getChangelogs(options = {}) {\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\t// Mock mode - return mock changelogs\n\t\tif (this.mock) {\n\t\t\tawait new Promise((resolve) => setTimeout(resolve, 300));\n\t\t\treturn {\n\t\t\t\tsuccess: true,\n\t\t\t\tdata: MOCK_CHANGELOGS,\n\t\t\t};\n\t\t}\n\n\t\ttry {\n\t\t\tconst queryParams = new URLSearchParams();\n\t\t\tif (options.limit) queryParams.append('limit', options.limit);\n\t\t\tif (options.offset) queryParams.append('offset', options.offset);\n\n\t\t\tconst endpoint = `/widget/changelogs${queryParams.toString() ? '?' + queryParams.toString() : ''}`;\n\n\t\t\tconst response = await this._makeRequest(endpoint, {\n\t\t\t\tmethod: 'GET',\n\t\t\t\theaders: {\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.getChangelogs(options);\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 get changelogs: ${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(\n\t\t\t\t'feedbackSDK_userContext',\n\t\t\t\tJSON.stringify(userContext)\n\t\t\t);\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 =\n\t\t\t\t\t\tresponseData.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}\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\tstatic STORAGE_KEY = 'feedback_submitted';\n\tstatic DEFAULT_COOLDOWN_DAYS = 30; // Don't show for 30 days after submission\n\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\tboardId: this.sdk.config.boardId,\n\t\t\tdisplayMode: options.displayMode || 'panel',\n\t\t\tsize: options.size || 'medium',\n\t\t\tprimaryColor: options.primaryColor || '#21244A',\n\t\t\tbackgroundColor: options.backgroundColor || '#ffffff',\n\t\t\ttextColor: options.textColor || '#1F2937',\n\t\t\tautoShow: false,\n\t\t\tshowBackdrop: true,\n\t\t\tcustomStyles: {},\n\t\t\tsuppressAfterSubmission: true, // Don't show widget again after submission\n\t\t\tsuppressionDays: BaseWidget.DEFAULT_COOLDOWN_DAYS,\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\tisLoading: 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\t// Check if feedback was recently submitted and should be suppressed\n\t\tif (this.options.suppressAfterSubmission && this._hasRecentlySubmitted()) {\n\t\t\tthis.sdk.eventBus.emit('widget:suppressed', {\n\t\t\t\twidget: this,\n\t\t\t\treason: 'recently_submitted',\n\t\t\t});\n\t\t\treturn this;\n\t\t}\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\n\t\tif (this.options.displayMode === 'modal') {\n\t\t\tthis._showLoadingModal();\n\t\t\t// Simulate loading delay then show form\n\t\t\tsetTimeout(() => {\n\t\t\t\tthis._hideLoadingModal();\n\t\t\t\tthis._renderPanel();\n\t\t\t\trequestAnimationFrame(() => {\n\t\t\t\t\tif (this.panelElement) {\n\t\t\t\t\t\tthis.panelElement.classList.add('open');\n\t\t\t\t\t}\n\t\t\t\t\tif (this.backdropElement) {\n\t\t\t\t\t\tthis.backdropElement.classList.add('show');\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}, 600);\n\t\t} else {\n\t\t\tthis._renderPanel();\n\t\t\trequestAnimationFrame(() => {\n\t\t\t\tif (this.panelElement) {\n\t\t\t\t\tthis.panelElement.classList.add('open');\n\t\t\t\t}\n\t\t\t\tif (this.backdropElement) {\n\t\t\t\t\tthis.backdropElement.classList.add('show');\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\n\t_showLoadingModal() {\n\t\tthis.state.isLoading = true;\n\n\t\t// Create backdrop\n\t\tthis.backdropElement = document.createElement('div');\n\t\tthis.backdropElement.className = 'feedback-panel-backdrop';\n\t\tdocument.body.appendChild(this.backdropElement);\n\n\t\t// Create loading modal\n\t\tthis.loadingElement = document.createElement('div');\n\t\tthis.loadingElement.className = `feedback-loading-modal theme-${this.options.theme}`;\n\t\tthis.loadingElement.innerHTML = `\n\t\t\t<div class=\"feedback-loading-spinner\"></div>\n\t\t`;\n\t\tdocument.body.appendChild(this.loadingElement);\n\n\t\trequestAnimationFrame(() => {\n\t\t\tthis.backdropElement.classList.add('show');\n\t\t\tthis.loadingElement.classList.add('show');\n\t\t});\n\t}\n\n\t_hideLoadingModal() {\n\t\tthis.state.isLoading = false;\n\t\tif (this.loadingElement) {\n\t\t\tthis.loadingElement.remove();\n\t\t\tthis.loadingElement = null;\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\t// Track that feedback was submitted\n\t\t\tthis._trackSubmission();\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/**\n\t * Track that feedback was submitted to localStorage\n\t */\n\t_trackSubmission() {\n\t\ttry {\n\t\t\tconst workspace = this.sdk.config.workspace;\n\t\t\tconst storageKey = `${BaseWidget.STORAGE_KEY}_${workspace}`;\n\t\t\tconst data = {\n\t\t\t\tsubmittedAt: Date.now(),\n\t\t\t\tboardId: this.options.boardId,\n\t\t\t};\n\t\t\tlocalStorage.setItem(storageKey, JSON.stringify(data));\n\t\t} catch (e) {\n\t\t\t// localStorage may not be available\n\t\t\tconsole.warn('Failed to track feedback submission:', e);\n\t\t}\n\t}\n\n\t/**\n\t * Check if feedback was recently submitted (within cooldown period)\n\t * Uses backend tracking (preferred) with localStorage as fallback\n\t * @returns {boolean} true if feedback was submitted within the cooldown period\n\t */\n\t_hasRecentlySubmitted() {\n\t\tconst cooldownMs = this.options.suppressionDays * 24 * 60 * 60 * 1000;\n\t\tconst now = Date.now();\n\n\t\t// Check backend tracking first (from init response)\n\t\tif (this.sdk.config.last_feedback_at) {\n\t\t\ttry {\n\t\t\t\tconst backendTimestamp = new Date(\n\t\t\t\t\tthis.sdk.config.last_feedback_at\n\t\t\t\t).getTime();\n\t\t\t\tif (now - backendTimestamp < cooldownMs) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t} catch (e) {\n\t\t\t\t// Invalid date format, continue to localStorage check\n\t\t\t}\n\t\t}\n\n\t\t// Fallback to localStorage\n\t\ttry {\n\t\t\tconst workspace = this.sdk.config.workspace;\n\t\t\tconst storageKey = `${BaseWidget.STORAGE_KEY}_${workspace}`;\n\t\t\tconst stored = localStorage.getItem(storageKey);\n\n\t\t\tif (!stored) return false;\n\n\t\t\tconst data = JSON.parse(stored);\n\t\t\tconst submittedAt = data.submittedAt;\n\n\t\t\treturn now - submittedAt < cooldownMs;\n\t\t} catch (e) {\n\t\t\t// localStorage may not be available or data is corrupted\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Clear the submission tracking (allow showing the widget again)\n\t */\n\tclearSubmissionTracking() {\n\t\ttry {\n\t\t\tconst workspace = this.sdk.config.workspace;\n\t\t\tconst storageKey = `${BaseWidget.STORAGE_KEY}_${workspace}`;\n\t\t\tlocalStorage.removeItem(storageKey);\n\t\t} catch (e) {\n\t\t\tconsole.warn('Failed to clear submission tracking:', e);\n\t\t}\n\t}\n\n\t/**\n\t * Check if the widget should be shown based on submission history\n\t * @returns {boolean} true if the widget should be shown\n\t */\n\tshouldShow() {\n\t\tif (!this.options.suppressAfterSubmission) return true;\n\t\treturn !this._hasRecentlySubmitted();\n\t}\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 && !this.backdropElement) {\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\tconst modeClass =\n\t\t\tthis.options.displayMode === 'modal'\n\t\t\t\t? 'feedback-modal'\n\t\t\t\t: 'feedback-panel';\n\t\tconst sizeClass = `size-${this.options.size}`;\n\t\tthis.panelElement = document.createElement('div');\n\t\tthis.panelElement.className = `${modeClass} ${sizeClass}`;\n\t\tthis.panelElement.style.setProperty(\n\t\t\t'--primary-color',\n\t\t\tthis.options.primaryColor\n\t\t);\n\t\tthis.panelElement.style.setProperty(\n\t\t\t'--bg-color',\n\t\t\tthis.options.backgroundColor\n\t\t);\n\t\tthis.panelElement.style.setProperty('--text-color', this.options.textColor);\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\">×</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\">×</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}\n","import { BaseWidget } from './BaseWidget.js';\n\nexport class ButtonWidget extends BaseWidget {\n\tconstructor(options) {\n\t\tsuper({ ...options, type: 'button' });\n\t\tthis.isMinimized = false;\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 class=\"feedback-icon\" width=\"20\" height=\"20\" viewBox=\"0 0 256 256\" fill=\"currentColor\">\n <path d=\"M216,80H184V48a16,16,0,0,0-16-16H40A16,16,0,0,0,24,48V176a8,8,0,0,0,13,6.22L72,154V184a16,16,0,0,0,16,16h93.59L219,230.22a8,8,0,0,0,5,1.78,8,8,0,0,0,8-8V96A16,16,0,0,0,216,80ZM66.55,137.78,40,159.25V48H168v88H71.58A8,8,0,0,0,66.55,137.78ZM216,207.25l-26.55-21.47a8,8,0,0,0-5-1.78H88V152h80a16,16,0,0,0,16-16V96h32Z\"/>\n </svg>\n <span class=\"feedback-text\">Feedback</span>\n \n <div class=\"feedback-minimize-icon\">\n <svg viewBox=\"0 0 256 256\">\n <path d=\"M213.66,53.66,163.31,104H192a8,8,0,0,1,0,16H144a8,8,0,0,1-8-8V64a8,8,0,0,1,16,0V92.69l50.34-50.35a8,8,0,0,1,11.32,11.32ZM112,136H64a8,8,0,0,0,0,16H92.69L42.34,202.34a8,8,0,0,0,11.32,11.32L104,163.31V192a8,8,0,0,0,16,0V144A8,8,0,0,0,112,136Z\"/>\n </svg>\n </div>\n \n <div class=\"feedback-expand-icon\">\n <svg viewBox=\"0 0 256 256\">\n <path d=\"M112,40V64.69L61.66,14.34A8,8,0,0,0,50.34,25.66L100.69,76H72a8,8,0,0,0,0,16h48a8,8,0,0,0,8-8V36A8,8,0,0,0,112,40Zm131.06,70.61a8,8,0,0,0-8.72,1.73L184,162.69V136a8,8,0,0,0-16,0v48a8,8,0,0,0,8,8h48a8,8,0,0,0,0-16H195.31l50.35-50.34A8,8,0,0,0,243.06,110.61Z\"/>\n </svg>\n </div>\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\tconst minimizeIcon = this.element.querySelector('.feedback-minimize-icon');\n\t\tconst expandIcon = this.element.querySelector('.feedback-expand-icon');\n\n\t\t// Add click handlers directly to the icons\n\t\tminimizeIcon.addEventListener('click', (e) => {\n\t\t\te.stopPropagation();\n\t\t\te.preventDefault();\n\t\t\tthis.minimize();\n\t\t});\n\n\t\texpandIcon.addEventListener('click', (e) => {\n\t\t\te.stopPropagation();\n\t\t\te.preventDefault();\n\t\t\tthis.restore();\n\t\t});\n\n\t\t// Main button click handler\n\t\tbutton.addEventListener('click', (e) => {\n\t\t\t// Check if the click originated from an icon\n\t\t\tif (\n\t\t\t\te.target.closest('.feedback-minimize-icon') ||\n\t\t\t\te.target.closest('.feedback-expand-icon')\n\t\t\t) {\n\t\t\t\treturn; // Let the icon handlers deal with it\n\t\t\t}\n\n\t\t\tif (!this.isMinimized) {\n\t\t\t\tthis.openPanel();\n\t\t\t}\n\t\t});\n\n\t\tbutton.addEventListener('mouseenter', () => {\n\t\t\tif (!this.state.isSubmitting && !this.isMinimized) {\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\tif (!this.isMinimized) {\n\t\t\t\tbutton.style.transform = 'translateY(0)';\n\t\t\t}\n\t\t});\n\t}\n\n\tminimize() {\n\t\tthis.isMinimized = true;\n\t\tthis.element.classList.add('minimized');\n\t}\n\n\trestore() {\n\t\tthis.isMinimized = false;\n\t\tthis.element.classList.remove('minimized');\n\t}\n\n\tmount(container) {\n\t\tsuper.mount(container);\n\t}\n\n\tupdateText(text) {\n\t\tconst textEl = this.element?.querySelector('.feedback-text');\n\t\tif (textEl) {\n\t\t\ttextEl.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 { BaseWidget } from './BaseWidget.js';\n\nexport class ChangelogWidget extends BaseWidget {\n\tconstructor(options) {\n\t\tsuper({ ...options, type: 'changelog' });\n\t\tthis.changelogs = [];\n\t\tthis.isLoading = false;\n\t\tthis.modalElement = null;\n\t\tthis.sidebarElement = null;\n\t\tthis.currentIndex = 0;\n\t}\n\n\t_render() {\n\t\tconst trigger = document.createElement('div');\n\t\ttrigger.className = `feedback-widget changelog-widget theme-${this.options.theme} position-${this.options.position}`;\n\t\ttrigger.innerHTML = `\n\t\t\t<button class=\"changelog-trigger-btn\" type=\"button\" aria-label=\"View Updates\">\n\t\t\t\t<svg class=\"changelog-icon\" width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n\t\t\t\t\t<path d=\"M5.8 21L7.4 14L2 9.2L9.2 8.6L12 2L14.8 8.6L22 9.2L16.6 14L18.2 21L12 17.3L5.8 21Z\"/>\n\t\t\t\t</svg>\n\t\t\t\t<span class=\"changelog-text\">${this.options.triggerText || \"What's New\"}</span>\n\t\t\t\t<span class=\"changelog-confetti-emoji\">🎉</span>\n\t\t\t\t${this.options.showBadge ? '<span class=\"changelog-badge\"></span>' : ''}\n\t\t\t</button>\n\t\t`;\n\n\t\tif (this.options.customStyles) {\n\t\t\tObject.assign(trigger.style, this.options.customStyles);\n\t\t}\n\n\t\treturn trigger;\n\t}\n\n\t_attachEvents() {\n\t\tconst button = this.element.querySelector('.changelog-trigger-btn');\n\n\t\tbutton.addEventListener('click', () => {\n\t\t\tthis.openSidebar();\n\t\t});\n\n\t\tbutton.addEventListener('mouseenter', () => {\n\t\t\tbutton.style.transform = 'translateY(-2px)';\n\t\t});\n\n\t\tbutton.addEventListener('mouseleave', () => {\n\t\t\tbutton.style.transform = 'translateY(0)';\n\t\t});\n\t}\n\n\t// ==================== POPUP MODAL ====================\n\n\tasync openModal() {\n\t\tif (this.modalElement) return;\n\n\t\tthis.state.isOpen = true;\n\t\tthis._createModal();\n\n\t\t// Load changelogs if not already loaded\n\t\tif (this.changelogs.length === 0) {\n\t\t\tawait this._loadChangelogs();\n\t\t}\n\n\t\tthis.currentIndex = 0;\n\t\tthis._renderCurrentChangelog();\n\n\t\t// Prevent body scroll\n\t\tdocument.body.style.overflow = 'hidden';\n\n\t\trequestAnimationFrame(() => {\n\t\t\tif (this.modalElement) {\n\t\t\t\tthis.modalElement.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\tcloseModal() {\n\t\t// Restore body scroll\n\t\tdocument.body.style.overflow = '';\n\n\t\tif (this.modalElement) {\n\t\t\tthis.modalElement.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.modalElement && this.modalElement.parentNode) {\n\t\t\t\tthis.modalElement.parentNode.removeChild(this.modalElement);\n\t\t\t\tthis.modalElement = 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}, 300);\n\t}\n\n\t_createModal() {\n\t\t// Create backdrop\n\t\tthis.backdropElement = document.createElement('div');\n\t\tthis.backdropElement.className = 'changelog-modal-backdrop';\n\t\tdocument.body.appendChild(this.backdropElement);\n\t\tthis.backdropElement.addEventListener('click', () => this.closeModal());\n\n\t\t// Create modal\n\t\tthis.modalElement = document.createElement('div');\n\t\tthis.modalElement.className = `changelog-modal theme-${this.options.theme}`;\n\t\tthis.modalElement.innerHTML = `\n\t\t\t<div class=\"changelog-modal-container\">\n\t\t\t\t<button class=\"changelog-modal-close\" type=\"button\" aria-label=\"Close\">×</button>\n\t\t\t\t<div class=\"changelog-modal-content\">\n\t\t\t\t\t<div class=\"changelog-loading\">\n\t\t\t\t\t\t<div class=\"changelog-loading-spinner\"></div>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t`;\n\n\t\tdocument.body.appendChild(this.modalElement);\n\n\t\t// Prevent clicks inside modal from closing it\n\t\tthis.modalElement\n\t\t\t.querySelector('.changelog-modal-container')\n\t\t\t.addEventListener('click', (e) => {\n\t\t\t\te.stopPropagation();\n\t\t\t});\n\n\t\t// Attach close button event\n\t\tthis.modalElement\n\t\t\t.querySelector('.changelog-modal-close')\n\t\t\t.addEventListener('click', () => this.closeModal());\n\n\t\t// Handle escape key\n\t\tthis._escapeHandler = (e) => {\n\t\t\tif (e.key === 'Escape') {\n\t\t\t\tthis.closeModal();\n\t\t\t}\n\t\t};\n\t\tdocument.addEventListener('keydown', this._escapeHandler);\n\t}\n\n\t// ==================== LIST MODAL ====================\n\n\tasync openSidebar() {\n\t\tif (this.listModalElement) return;\n\n\t\t// Close popup modal if open\n\t\tif (this.modalElement) {\n\t\t\tthis.closeModal();\n\t\t\tawait new Promise((resolve) => setTimeout(resolve, 350));\n\t\t}\n\n\t\tthis.state.isOpen = true;\n\t\tthis._createListModal();\n\n\t\t// Load changelogs if not already loaded\n\t\tif (this.changelogs.length === 0) {\n\t\t\tawait this._loadChangelogs();\n\t\t}\n\n\t\tthis._renderChangelogList();\n\n\t\t// Prevent body scroll\n\t\tdocument.body.style.overflow = 'hidden';\n\n\t\trequestAnimationFrame(() => {\n\t\t\tif (this.listModalElement) {\n\t\t\t\tthis.listModalElement.classList.add('open');\n\t\t\t\t// Trigger confetti animation\n\t\t\t\tthis._showConfetti();\n\t\t\t}\n\t\t\tif (this.listModalBackdropElement) {\n\t\t\t\tthis.listModalBackdropElement.classList.add('show');\n\t\t\t}\n\t\t});\n\t}\n\n\t_showConfetti() {\n\t\tconst colors = [\n\t\t\t'#FF6B6B',\n\t\t\t'#4ECDC4',\n\t\t\t'#FFE66D',\n\t\t\t'#95E1D3',\n\t\t\t'#F38181',\n\t\t\t'#AA96DA',\n\t\t\t'#FCBAD3',\n\t\t\t'#A8D8EA',\n\t\t];\n\t\tconst confettiCount = 50;\n\t\tconst container = document.createElement('div');\n\t\tcontainer.className = 'changelog-confetti-container';\n\t\tdocument.body.appendChild(container);\n\n\t\tfor (let i = 0; i < confettiCount; i++) {\n\t\t\tconst confetti = document.createElement('div');\n\t\t\tconfetti.className = 'changelog-confetti';\n\t\t\tconfetti.style.left = Math.random() * 100 + '%';\n\t\t\tconfetti.style.backgroundColor =\n\t\t\t\tcolors[Math.floor(Math.random() * colors.length)];\n\t\t\tconfetti.style.animationDelay = Math.random() * 0.5 + 's';\n\t\t\tconfetti.style.animationDuration = Math.random() * 1 + 1.5 + 's';\n\n\t\t\t// Random shapes\n\t\t\tconst shapes = ['circle', 'square', 'rectangle'];\n\t\t\tconst shape = shapes[Math.floor(Math.random() * shapes.length)];\n\t\t\tif (shape === 'circle') {\n\t\t\t\tconfetti.style.borderRadius = '50%';\n\t\t\t\tconfetti.style.width = Math.random() * 8 + 4 + 'px';\n\t\t\t\tconfetti.style.height = confetti.style.width;\n\t\t\t} else if (shape === 'rectangle') {\n\t\t\t\tconfetti.style.width = Math.random() * 4 + 3 + 'px';\n\t\t\t\tconfetti.style.height = Math.random() * 10 + 8 + 'px';\n\t\t\t} else {\n\t\t\t\tconfetti.style.width = Math.random() * 8 + 4 + 'px';\n\t\t\t\tconfetti.style.height = confetti.style.width;\n\t\t\t}\n\n\t\t\tcontainer.appendChild(confetti);\n\t\t}\n\n\t\t// Remove confetti after animation\n\t\tsetTimeout(() => {\n\t\t\tif (container.parentNode) {\n\t\t\t\tcontainer.parentNode.removeChild(container);\n\t\t\t}\n\t\t}, 2500);\n\t}\n\n\tcloseSidebar() {\n\t\t// Restore body scroll\n\t\tdocument.body.style.overflow = '';\n\n\t\tif (this.listModalElement) {\n\t\t\tthis.listModalElement.classList.remove('open');\n\t\t}\n\t\tif (this.listModalBackdropElement) {\n\t\t\tthis.listModalBackdropElement.classList.remove('show');\n\t\t}\n\n\t\tsetTimeout(() => {\n\t\t\tthis.state.isOpen = false;\n\t\t\tif (this.listModalElement && this.listModalElement.parentNode) {\n\t\t\t\tthis.listModalElement.parentNode.removeChild(this.listModalElement);\n\t\t\t\tthis.listModalElement = null;\n\t\t\t}\n\t\t\tif (\n\t\t\t\tthis.listModalBackdropElement &&\n\t\t\t\tthis.listModalBackdropElement.parentNode\n\t\t\t) {\n\t\t\t\tthis.listModalBackdropElement.parentNode.removeChild(\n\t\t\t\t\tthis.listModalBackdropElement\n\t\t\t\t);\n\t\t\t\tthis.listModalBackdropElement = null;\n\t\t\t}\n\t\t\tif (this._listModalEscapeHandler) {\n\t\t\t\tdocument.removeEventListener('keydown', this._listModalEscapeHandler);\n\t\t\t}\n\t\t}, 300);\n\t}\n\n\t_createListModal() {\n\t\t// Create backdrop\n\t\tthis.listModalBackdropElement = document.createElement('div');\n\t\tthis.listModalBackdropElement.className = 'changelog-list-modal-backdrop';\n\t\tdocument.body.appendChild(this.listModalBackdropElement);\n\t\tthis.listModalBackdropElement.addEventListener('click', () =>\n\t\t\tthis.closeSidebar()\n\t\t);\n\n\t\t// Create list modal\n\t\tthis.listModalElement = document.createElement('div');\n\t\tthis.listModalElement.className = `changelog-list-modal theme-${this.options.theme}`;\n\t\tthis.listModalElement.innerHTML = `\n\t\t\t<div class=\"changelog-list-modal-container\">\n\t\t\t\t<div class=\"changelog-list-modal-header\">\n\t\t\t\t\t<h2>${this.options.title || \"What's New\"} 🎉</h2>\n\t\t\t\t\t<button class=\"changelog-list-modal-close\" type=\"button\" aria-label=\"Close\">×</button>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"changelog-list-modal-body\">\n\t\t\t\t\t<div class=\"changelog-loading\">\n\t\t\t\t\t\t<div class=\"changelog-loading-spinner\"></div>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t`;\n\n\t\tdocument.body.appendChild(this.listModalElement);\n\n\t\t// Prevent clicks inside modal from closing it\n\t\tthis.listModalElement\n\t\t\t.querySelector('.changelog-list-modal-container')\n\t\t\t.addEventListener('click', (e) => {\n\t\t\t\te.stopPropagation();\n\t\t\t});\n\n\t\t// Attach close button event\n\t\tthis.listModalElement\n\t\t\t.querySelector('.changelog-list-modal-close')\n\t\t\t.addEventListener('click', () => this.closeSidebar());\n\n\t\t// Handle escape key\n\t\tthis._listModalEscapeHandler = (e) => {\n\t\t\tif (e.key === 'Escape') {\n\t\t\t\tthis.closeSidebar();\n\t\t\t}\n\t\t};\n\t\tdocument.addEventListener('keydown', this._listModalEscapeHandler);\n\t}\n\n\t_renderChangelogList() {\n\t\tconst body = this.listModalElement.querySelector(\n\t\t\t'.changelog-list-modal-body'\n\t\t);\n\n\t\tif (this.isLoading) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.changelogs.length === 0) {\n\t\t\tbody.innerHTML = `\n\t\t\t\t<div class=\"changelog-empty\">\n\t\t\t\t\t<svg width=\"48\" height=\"48\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\">\n\t\t\t\t\t\t<path d=\"M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z\"/>\n\t\t\t\t\t\t<polyline points=\"14,2 14,8 20,8\"/>\n\t\t\t\t\t</svg>\n\t\t\t\t\t<p>No updates yet</p>\n\t\t\t\t</div>\n\t\t\t`;\n\t\t\treturn;\n\t\t}\n\n\t\tbody.innerHTML = `\n\t\t\t<div class=\"changelog-list\">\n\t\t\t\t${this.changelogs.map((changelog, index) => this._renderChangelogListItem(changelog, index)).join('')}\n\t\t\t</div>\n\t\t`;\n\n\t\t// Attach click events to items\n\t\tbody.querySelectorAll('.changelog-list-item').forEach((item, index) => {\n\t\t\titem.addEventListener('click', () => {\n\t\t\t\tconst changelog = this.changelogs[index];\n\t\t\t\tthis._handleViewUpdate(changelog);\n\t\t\t});\n\t\t});\n\t}\n\n\t_renderChangelogListItem(changelog, index) {\n\t\tconst hasImage = changelog.cover_image || changelog.image;\n\t\tconst imageUrl = changelog.cover_image || changelog.image;\n\t\tconst date = changelog.published_at\n\t\t\t? this._formatDate(changelog.published_at)\n\t\t\t: '';\n\n\t\treturn `\n\t\t\t<div class=\"changelog-list-item\" data-index=\"${index}\">\n\t\t\t\t<div class=\"changelog-list-item-main\">\n\t\t\t\t\t${\n\t\t\t\t\t\thasImage\n\t\t\t\t\t\t\t? `\n\t\t\t\t\t\t<div class=\"changelog-list-item-image\">\n\t\t\t\t\t\t\t<img src=\"${imageUrl}\" alt=\"${changelog.title}\" loading=\"lazy\" />\n\t\t\t\t\t\t</div>\n\t\t\t\t\t`\n\t\t\t\t\t\t\t: ''\n\t\t\t\t\t}\n\t\t\t\t\t<div class=\"changelog-list-item-content\">\n\t\t\t\t\t\t${date ? `<span class=\"changelog-list-item-date\">${date}</span>` : ''}\n\t\t\t\t\t\t${\n\t\t\t\t\t\t\tchangelog.labels && changelog.labels.length > 0\n\t\t\t\t\t\t\t\t? `\n\t\t\t\t\t\t\t<div class=\"changelog-list-item-labels\">\n\t\t\t\t\t\t\t\t${changelog.labels\n\t\t\t\t\t\t\t\t\t.map(\n\t\t\t\t\t\t\t\t\t\t(label) => `\n\t\t\t\t\t\t\t\t\t<span class=\"changelog-label\" style=\"background-color: ${label.color || '#E5E7EB'}; color: ${this._getContrastColor(label.color || '#E5E7EB')}\">${label.name}</span>\n\t\t\t\t\t\t\t\t`\n\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t.join('')}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t`\n\t\t\t\t\t\t\t\t: ''\n\t\t\t\t\t\t}\n\t\t\t\t\t\t<h3 class=\"changelog-list-item-title\">${changelog.title}</h3>\n\t\t\t\t\t\t${\n\t\t\t\t\t\t\tchangelog.excerpt || changelog.description\n\t\t\t\t\t\t\t\t? `\n\t\t\t\t\t\t\t<p class=\"changelog-list-item-description\">${changelog.excerpt || changelog.description}</p>\n\t\t\t\t\t\t`\n\t\t\t\t\t\t\t\t: ''\n\t\t\t\t\t\t}\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"changelog-list-item-arrow\">\n\t\t\t\t\t<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n\t\t\t\t\t\t<path d=\"M9 18l6-6-6-6\"/>\n\t\t\t\t\t</svg>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t`;\n\t}\n\n\tasync _loadChangelogs() {\n\t\tthis.isLoading = true;\n\n\t\ttry {\n\t\t\tconst result = await this.apiService.getChangelogs();\n\t\t\tthis.changelogs = result.data || [];\n\t\t\tthis.sdk.eventBus.emit('changelog:loaded', {\n\t\t\t\tchangelogs: this.changelogs,\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tthis.changelogs = [];\n\t\t\tthis.sdk.eventBus.emit('changelog:error', { error });\n\t\t} finally {\n\t\t\tthis.isLoading = false;\n\t\t}\n\t}\n\n\t_renderCurrentChangelog() {\n\t\tconst content = this.modalElement.querySelector('.changelog-modal-content');\n\n\t\tif (this.isLoading) {\n\t\t\treturn; // Keep showing loading spinner\n\t\t}\n\n\t\tif (this.changelogs.length === 0) {\n\t\t\tcontent.innerHTML = `\n\t\t\t\t<div class=\"changelog-empty\">\n\t\t\t\t\t<svg width=\"48\" height=\"48\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\">\n\t\t\t\t\t\t<path d=\"M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z\"/>\n\t\t\t\t\t\t<polyline points=\"14,2 14,8 20,8\"/>\n\t\t\t\t\t</svg>\n\t\t\t\t\t<p>No updates yet</p>\n\t\t\t\t</div>\n\t\t\t`;\n\t\t\treturn;\n\t\t}\n\n\t\tconst changelog = this.changelogs[this.currentIndex];\n\t\tconst hasImage = changelog.cover_image || changelog.image;\n\t\tconst imageUrl = changelog.cover_image || changelog.image;\n\t\tconst hasMultiple = this.changelogs.length > 1;\n\n\t\tcontent.innerHTML = `\n\t\t\t<div class=\"changelog-popup-item\">\n\t\t\t\t${\n\t\t\t\t\thasImage\n\t\t\t\t\t\t? `\n\t\t\t\t\t<div class=\"changelog-popup-image\">\n\t\t\t\t\t\t<img src=\"${imageUrl}\" alt=\"${changelog.title}\" loading=\"lazy\" />\n\t\t\t\t\t</div>\n\t\t\t\t`\n\t\t\t\t\t\t: ''\n\t\t\t\t}\n\t\t\t\t<div class=\"changelog-popup-body\">\n\t\t\t\t\t<h2 class=\"changelog-popup-title\">${changelog.title}</h2>\n\t\t\t\t\t${\n\t\t\t\t\t\tchangelog.excerpt || changelog.description\n\t\t\t\t\t\t\t? `\n\t\t\t\t\t\t<p class=\"changelog-popup-description\">${changelog.excerpt || changelog.description}</p>\n\t\t\t\t\t`\n\t\t\t\t\t\t\t: ''\n\t\t\t\t\t}\n\t\t\t\t\t<button class=\"changelog-popup-btn\" type=\"button\">\n\t\t\t\t\t\t${this.options.viewButtonText || 'View Update'}\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"changelog-popup-footer\">\n\t\t\t\t\t${\n\t\t\t\t\t\thasMultiple\n\t\t\t\t\t\t\t? `\n\t\t\t\t\t\t<div class=\"changelog-popup-dots\">\n\t\t\t\t\t\t\t${this.changelogs\n\t\t\t\t\t\t\t\t.map(\n\t\t\t\t\t\t\t\t\t(_, i) => `\n\t\t\t\t\t\t\t\t<span class=\"changelog-dot ${i === this.currentIndex ? 'active' : ''}\" data-index=\"${i}\"></span>\n\t\t\t\t\t\t\t`\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t.join('')}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t`\n\t\t\t\t\t\t\t: ''\n\t\t\t\t\t}\n\t\t\t\t\t<button class=\"changelog-view-all-btn\" type=\"button\">\n\t\t\t\t\t\tView all updates\n\t\t\t\t\t\t<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n\t\t\t\t\t\t\t<path d=\"M5 12h14M12 5l7 7-7 7\"/>\n\t\t\t\t\t\t</svg>\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t`;\n\n\t\t// Attach view button event\n\t\tcontent\n\t\t\t.querySelector('.changelog-popup-btn')\n\t\t\t.addEventListener('click', () => {\n\t\t\t\tthis._handleViewUpdate(changelog);\n\t\t\t});\n\n\t\t// Attach view all button event\n\t\tcontent\n\t\t\t.querySelector('.changelog-view-all-btn')\n\t\t\t.addEventListener('click', () => {\n\t\t\t\tthis.closeModal();\n\t\t\t\tsetTimeout(() => this.openSidebar(), 350);\n\t\t\t});\n\n\t\t// Attach dot navigation events\n\t\tif (hasMultiple) {\n\t\t\tcontent.querySelectorAll('.changelog-dot').forEach((dot) => {\n\t\t\t\tdot.addEventListener('click', (e) => {\n\t\t\t\t\tconst index = parseInt(e.target.dataset.index, 10);\n\t\t\t\t\tthis.currentIndex = index;\n\t\t\t\t\tthis._renderCurrentChangelog();\n\t\t\t\t});\n\t\t\t});\n\t\t}\n\t}\n\n\t_handleViewUpdate(changelog) {\n\t\tthis.sdk.eventBus.emit('changelog:view', { changelog });\n\n\t\t// If there's a URL, open it\n\t\tif (changelog.url || changelog.slug) {\n\t\t\tconst url =\n\t\t\t\tchangelog.url ||\n\t\t\t\t`${this.options.changelogBaseUrl || ''}/${changelog.slug}`;\n\t\t\tif (this.options.openInNewTab !== false) {\n\t\t\t\twindow.open(url, '_blank', 'noopener,noreferrer');\n\t\t\t} else {\n\t\t\t\twindow.location.href = url;\n\t\t\t}\n\t\t}\n\n\t\t// Custom callback if provided\n\t\tif (typeof this.options.onViewUpdate === 'function') {\n\t\t\tthis.options.onViewUpdate(changelog);\n\t\t}\n\t}\n\n\t_formatDate(dateString) {\n\t\tconst date = new Date(dateString);\n\t\tconst options = { year: 'numeric', month: 'short', day: 'numeric' };\n\t\treturn date.toLocaleDateString('en-US', options);\n\t}\n\n\t_getContrastColor(hexColor) {\n\t\t// Remove # if present\n\t\tconst hex = hexColor.replace('#', '');\n\t\tconst r = parseInt(hex.substr(0, 2), 16);\n\t\tconst g = parseInt(hex.substr(2, 2), 16);\n\t\tconst b = parseInt(hex.substr(4, 2), 16);\n\t\t// Calculate luminance\n\t\tconst luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255;\n\t\treturn luminance > 0.5 ? '#1F2937' : '#FFFFFF';\n\t}\n\n\thideBadge() {\n\t\tconst badge = this.element?.querySelector('.changelog-badge');\n\t\tif (badge) {\n\t\t\tbadge.style.display = 'none';\n\t\t}\n\t}\n\n\tshowBadge() {\n\t\tconst badge = this.element?.querySelector('.changelog-badge');\n\t\tif (badge) {\n\t\t\tbadge.style.display = 'block';\n\t\t}\n\t}\n\n\tnextChangelog() {\n\t\tif (this.currentIndex < this.changelogs.length - 1) {\n\t\t\tthis.currentIndex++;\n\t\t\tthis._renderCurrentChangelog();\n\t\t}\n\t}\n\n\tprevChangelog() {\n\t\tif (this.currentIndex > 0) {\n\t\t\tthis.currentIndex--;\n\t\t\tthis._renderCurrentChangelog();\n\t\t}\n\t}\n\n\tasync refresh() {\n\t\tthis.changelogs = [];\n\t\tawait this._loadChangelogs();\n\t\tif (this.modalElement) {\n\t\t\tthis.currentIndex = 0;\n\t\t\tthis._renderCurrentChangelog();\n\t\t}\n\t\tif (this.listModalElement) {\n\t\t\tthis._renderChangelogList();\n\t\t}\n\t}\n\n\tmount(container) {\n\t\tsuper.mount(container);\n\t}\n\n\tdestroy() {\n\t\tif (this._escapeHandler) {\n\t\t\tdocument.removeEventListener('keydown', this._escapeHandler);\n\t\t}\n\t\tif (this._listModalEscapeHandler) {\n\t\t\tdocument.removeEventListener('keydown', this._listModalEscapeHandler);\n\t\t}\n\t\tthis.closeModal();\n\t\tthis.closeSidebar();\n\t\tsuper.destroy();\n\t}\n}\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","/**\n * WebSocketService - Real-time communication for messenger widget\n */\n\nexport class WebSocketService {\n\tconstructor(config = {}) {\n\t\tthis.baseURL = config.baseURL || '';\n\t\tthis.workspace = config.workspace || '';\n\t\tthis.sessionToken = config.sessionToken || null;\n\t\tthis.mock = config.mock || false;\n\n\t\tthis.ws = null;\n\t\tthis.reconnectAttempts = 0;\n\t\tthis.maxReconnectAttempts = 5;\n\t\tthis.reconnectDelay = 1000;\n\t\tthis.pingInterval = null;\n\t\tthis.isConnected = false;\n\n\t\t// Event listeners\n\t\tthis._listeners = new Map();\n\n\t\t// Bind methods\n\t\tthis._onOpen = this._onOpen.bind(this);\n\t\tthis._onMessage = this._onMessage.bind(this);\n\t\tthis._onClose = this._onClose.bind(this);\n\t\tthis._onError = this._onError.bind(this);\n\t}\n\n\t/**\n\t * Connect to WebSocket server\n\t */\n\tconnect(sessionToken = null) {\n\t\tif (sessionToken) {\n\t\t\tthis.sessionToken = sessionToken;\n\t\t}\n\n\t\tif (!this.sessionToken) {\n\t\t\tconsole.warn('[WebSocket] No session token provided');\n\t\t\treturn;\n\t\t}\n\n\t\t// Mock mode - simulate connection\n\t\tif (this.mock) {\n\t\t\tthis.isConnected = true;\n\t\t\tthis._emit('connected', {});\n\t\t\tthis._startMockResponses();\n\t\t\treturn;\n\t\t}\n\n\t\t// Build WebSocket URL\n\t\tconst wsProtocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';\n\t\tlet wsURL = this.baseURL.replace(/^https?:/, wsProtocol);\n\t\twsURL = wsURL.replace('/api/v1', '');\n\t\twsURL = `${wsURL}/api/v1/widget/messenger/ws?token=${encodeURIComponent(this.sessionToken)}`;\n\n\t\ttry {\n\t\t\tthis.ws = new WebSocket(wsURL);\n\t\t\tthis.ws.onopen = this._onOpen;\n\t\t\tthis.ws.onmessage = this._onMessage;\n\t\t\tthis.ws.onclose = this._onClose;\n\t\t\tthis.ws.onerror = this._onError;\n\t\t} catch (error) {\n\t\t\tconsole.error('[WebSocket] Connection error:', error);\n\t\t\tthis._scheduleReconnect();\n\t\t}\n\t}\n\n\t/**\n\t * Disconnect from WebSocket server\n\t */\n\tdisconnect() {\n\t\tthis.isConnected = false;\n\t\tthis.reconnectAttempts = this.maxReconnectAttempts; // Prevent reconnection\n\n\t\tif (this.pingInterval) {\n\t\t\tclearInterval(this.pingInterval);\n\t\t\tthis.pingInterval = null;\n\t\t}\n\n\t\tif (this.ws) {\n\t\t\tthis.ws.close();\n\t\t\tthis.ws = null;\n\t\t}\n\n\t\tif (this._mockInterval) {\n\t\t\tclearInterval(this._mockInterval);\n\t\t\tthis._mockInterval = null;\n\t\t}\n\t}\n\n\t/**\n\t * Subscribe to events\n\t * @param {string} event - Event name\n\t * @param {Function} callback - Event handler\n\t * @returns {Function} Unsubscribe function\n\t */\n\ton(event, callback) {\n\t\tif (!this._listeners.has(event)) {\n\t\t\tthis._listeners.set(event, new Set());\n\t\t}\n\t\tthis._listeners.get(event).add(callback);\n\t\treturn () => this._listeners.get(event).delete(callback);\n\t}\n\n\t/**\n\t * Remove event listener\n\t */\n\toff(event, callback) {\n\t\tif (this._listeners.has(event)) {\n\t\t\tthis._listeners.get(event).delete(callback);\n\t\t}\n\t}\n\n\t/**\n\t * Send message through WebSocket\n\t */\n\tsend(type, payload = {}) {\n\t\tif (!this.isConnected) {\n\t\t\tconsole.warn('[WebSocket] Not connected, cannot send message');\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.mock) {\n\t\t\t// Mock mode - just log\n\t\t\tconsole.log('[WebSocket Mock] Sending:', type, payload);\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.ws && this.ws.readyState === WebSocket.OPEN) {\n\t\t\tthis.ws.send(JSON.stringify({ type, payload }));\n\t\t}\n\t}\n\n\t// Private methods\n\n\t_onOpen() {\n\t\tconsole.log('[WebSocket] Connected');\n\t\tthis.isConnected = true;\n\t\tthis.reconnectAttempts = 0;\n\t\tthis._emit('connected', {});\n\n\t\t// Start ping interval to keep connection alive\n\t\tthis.pingInterval = setInterval(() => {\n\t\t\tthis.send('ping', {});\n\t\t}, 30000);\n\t}\n\n\t_onMessage(event) {\n\t\ttry {\n\t\t\tconst data = JSON.parse(event.data);\n\t\t\tconst { type, payload } = data;\n\n\t\t\t// Handle different event types\n\t\t\tswitch (type) {\n\t\t\t\tcase 'message:new':\n\t\t\t\t\tthis._emit('message', payload);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'typing:started':\n\t\t\t\t\tthis._emit('typing_started', payload);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'typing:stopped':\n\t\t\t\t\tthis._emit('typing_stopped', payload);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'conversation:updated':\n\t\t\t\t\tthis._emit('conversation_updated', payload);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'conversation:closed':\n\t\t\t\t\tthis._emit('conversation_closed', payload);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'availability:changed':\n\t\t\t\t\tthis._emit('availability_changed', payload);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'pong':\n\t\t\t\t\t// Ping response, ignore\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tconsole.log('[WebSocket] Unknown event:', type, payload);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconsole.error('[WebSocket] Failed to parse message:', error);\n\t\t}\n\t}\n\n\t_onClose(event) {\n\t\tconsole.log('[WebSocket] Disconnected:', event.code, event.reason);\n\t\tthis.isConnected = false;\n\n\t\tif (this.pingInterval) {\n\t\t\tclearInterval(this.pingInterval);\n\t\t\tthis.pingInterval = null;\n\t\t}\n\n\t\tthis._emit('disconnected', { code: event.code, reason: event.reason });\n\t\tthis._scheduleReconnect();\n\t}\n\n\t_onError(error) {\n\t\tconsole.error('[WebSocket] Error:', error);\n\t\tthis._emit('error', { error });\n\t}\n\n\t_scheduleReconnect() {\n\t\tif (this.reconnectAttempts >= this.maxReconnectAttempts) {\n\t\t\tconsole.log('[WebSocket] Max reconnect attempts reached');\n\t\t\tthis._emit('reconnect_failed', {});\n\t\t\treturn;\n\t\t}\n\n\t\tthis.reconnectAttempts++;\n\t\tconst delay = this.reconnectDelay * Math.pow(2, this.reconnectAttempts - 1);\n\t\tconsole.log(\n\t\t\t`[WebSocket] Reconnecting in ${delay}ms (attempt ${this.reconnectAttempts})`\n\t\t);\n\n\t\tsetTimeout(() => {\n\t\t\tthis.connect();\n\t\t}, delay);\n\t}\n\n\t_emit(event, data) {\n\t\tif (this._listeners.has(event)) {\n\t\t\tthis._listeners.get(event).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(`[WebSocket] Error in ${event} handler:`, error);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\n\t// Mock support for development\n\t_startMockResponses() {\n\t\t// Simulate agent typing and responses\n\t\tthis._mockInterval = setInterval(() => {\n\t\t\t// Randomly emit typing or message events for demo\n\t\t\tconst random = Math.random();\n\t\t\tif (random < 0.1) {\n\t\t\t\tthis._emit('typing_started', {\n\t\t\t\t\tconversation_id: 'conv_1',\n\t\t\t\t\tuser_id: 'agent_1',\n\t\t\t\t\tuser_name: 'Sarah',\n\t\t\t\t\tis_agent: true,\n\t\t\t\t});\n\n\t\t\t\t// Stop typing after 2 seconds\n\t\t\t\tsetTimeout(() => {\n\t\t\t\t\tthis._emit('typing_stopped', {\n\t\t\t\t\t\tconversation_id: 'conv_1',\n\t\t\t\t\t\tuser_id: 'agent_1',\n\t\t\t\t\t});\n\t\t\t\t}, 2000);\n\t\t\t}\n\t\t}, 10000);\n\t}\n\n\t/**\n\t * Simulate receiving a message (for mock mode)\n\t */\n\tsimulateMessage(conversationId, message) {\n\t\tif (this.mock) {\n\t\t\tthis._emit('message', {\n\t\t\t\tconversation_id: conversationId,\n\t\t\t\tmessage: {\n\t\t\t\t\tid: 'msg_' + Date.now(),\n\t\t\t\t\tcontent: message.content,\n\t\t\t\t\tsender_type: message.sender_type || 'agent',\n\t\t\t\t\tsender_name: message.sender_name || 'Support',\n\t\t\t\t\tsender_avatar: message.sender_avatar || null,\n\t\t\t\t\tcreated_at: new Date().toISOString(),\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\t}\n}\n","/**\n * MessengerState - State management for the Messenger widget\n */\nexport class MessengerState {\n\tconstructor(options = {}) {\n\t\tthis.currentView = 'home'; // 'home', 'messages', 'chat', 'help', 'changelog'\n\t\tthis.isOpen = false;\n\t\tthis.unreadCount = 0;\n\t\tthis.activeConversationId = null;\n\n\t\t// Conversations\n\t\tthis.conversations = [];\n\t\tthis.messages = {}; // { conversationId: [messages] }\n\n\t\t// Help articles\n\t\tthis.helpArticles = [];\n\t\tthis.helpSearchQuery = '';\n\n\t\t// Changelog\n\t\tthis.homeChangelogItems = [];\n\t\tthis.changelogItems = [];\n\n\t\t// Team info\n\t\tthis.teamName = options.teamName || 'Support';\n\t\tthis.teamAvatars = options.teamAvatars || [];\n\t\tthis.welcomeMessage = options.welcomeMessage || 'How can we help?';\n\n\t\t// User info\n\t\tthis.userContext = options.userContext || null;\n\n\t\t// Feature flags\n\t\tthis.enableHelp = options.enableHelp !== false;\n\t\tthis.enableChangelog = options.enableChangelog !== false;\n\n\t\t// Agent availability\n\t\tthis.agentsOnline = false;\n\t\tthis.onlineCount = 0;\n\t\tthis.responseTime = 'Usually replies within a few minutes';\n\n\t\t// Typing indicators\n\t\tthis.typingUsers = {}; // { conversationId: { userName, timestamp } }\n\n\t\t// Loading states\n\t\tthis.isLoading = false;\n\t\tthis.isLoadingMessages = false;\n\n\t\t// Listeners\n\t\tthis._listeners = new Set();\n\t}\n\n\t/**\n\t * Subscribe to state changes\n\t */\n\tsubscribe(callback) {\n\t\tthis._listeners.add(callback);\n\t\treturn () => this._listeners.delete(callback);\n\t}\n\n\t/**\n\t * Notify all listeners of state change\n\t */\n\t_notify(changeType, data) {\n\t\tthis._listeners.forEach((cb) => cb(changeType, data, this));\n\t}\n\n\t/**\n\t * Set current view\n\t */\n\tsetView(view) {\n\t\tconst previousView = this.currentView;\n\t\tthis.currentView = view;\n\t\tthis._notify('viewChange', { previousView, currentView: view });\n\t}\n\n\t/**\n\t * Toggle panel open/closed\n\t */\n\tsetOpen(isOpen) {\n\t\tthis.isOpen = isOpen;\n\t\tthis._notify('openChange', { isOpen });\n\t}\n\n\t/**\n\t * Set active conversation for chat view\n\t */\n\tsetActiveConversation(conversationId) {\n\t\tthis.activeConversationId = conversationId;\n\t\tthis._notify('conversationChange', { conversationId });\n\t}\n\n\t/**\n\t * Update conversations list\n\t */\n\tsetConversations(conversations) {\n\t\tthis.conversations = conversations;\n\t\tthis._updateUnreadCount();\n\t\tthis._notify('conversationsUpdate', { conversations });\n\t}\n\n\t/**\n\t * Add a new conversation\n\t */\n\taddConversation(conversation) {\n\t\tthis.conversations.unshift(conversation);\n\t\tthis._updateUnreadCount();\n\t\tthis._notify('conversationAdded', { conversation });\n\t}\n\n\t/**\n\t * Update messages for a conversation\n\t */\n\tsetMessages(conversationId, messages) {\n\t\tthis.messages[conversationId] = messages;\n\t\tthis._notify('messagesUpdate', { conversationId, messages });\n\t}\n\n\t/**\n\t * Add a message to a conversation\n\t */\n\taddMessage(conversationId, message) {\n\t\tif (!this.messages[conversationId]) {\n\t\t\tthis.messages[conversationId] = [];\n\t\t}\n\t\tthis.messages[conversationId].push(message);\n\n\t\t// Update conversation preview\n\t\tconst conv = this.conversations.find((c) => c.id === conversationId);\n\t\tif (conv) {\n\t\t\tconv.lastMessage = message.content;\n\t\t\tconv.lastMessageTime = message.timestamp;\n\t\t\tif (!message.isOwn) {\n\t\t\t\tconv.unread = (conv.unread || 0) + 1;\n\t\t\t\tthis._updateUnreadCount();\n\t\t\t}\n\t\t}\n\n\t\tthis._notify('messageAdded', { conversationId, message });\n\t}\n\n\t/**\n\t * Mark conversation as read\n\t */\n\tmarkAsRead(conversationId) {\n\t\tconst conv = this.conversations.find((c) => c.id === conversationId);\n\t\tif (conv && conv.unread > 0) {\n\t\t\tconv.unread = 0;\n\t\t\tthis._updateUnreadCount();\n\t\t\tthis._notify('conversationRead', { conversationId });\n\t\t}\n\t}\n\n\t/**\n\t * Update unread count\n\t */\n\t_updateUnreadCount() {\n\t\tthis.unreadCount = this.conversations.reduce(\n\t\t\t(sum, c) => sum + (c.unread || 0),\n\t\t\t0\n\t\t);\n\t\tthis._notify('unreadCountChange', { count: this.unreadCount });\n\t}\n\n\t/**\n\t * Set help articles\n\t */\n\tsetHelpArticles(articles) {\n\t\tthis.helpArticles = articles;\n\t\tthis._notify('helpArticlesUpdate', { articles });\n\t}\n\n\t/**\n\t * Set help search query\n\t */\n\tsetHelpSearchQuery(query) {\n\t\tthis.helpSearchQuery = query;\n\t\tthis._notify('helpSearchChange', { query });\n\t}\n\n\t/**\n\t * Set home changelog items\n\t */\n\tsetHomeChangelogItems(items) {\n\t\tthis.homeChangelogItems = items;\n\t\tthis._notify('homeChangelogUpdate', { items });\n\t}\n\n\t/**\n\t * Set changelog items\n\t */\n\tsetChangelogItems(items) {\n\t\tthis.changelogItems = items;\n\t\tthis._notify('changelogUpdate', { items });\n\t}\n\n\t/**\n\t * Get current conversation\n\t */\n\tgetActiveConversation() {\n\t\treturn this.conversations.find((c) => c.id === this.activeConversationId);\n\t}\n\n\t/**\n\t * Get messages for active conversation\n\t */\n\tgetActiveMessages() {\n\t\treturn this.messages[this.activeConversationId] || [];\n\t}\n\n\t/**\n\t * Get filtered help articles\n\t */\n\tgetFilteredHelpArticles() {\n\t\tif (!this.helpSearchQuery) {\n\t\t\treturn this.helpArticles;\n\t\t}\n\t\tconst query = this.helpSearchQuery.toLowerCase();\n\t\treturn this.helpArticles.filter(\n\t\t\t(article) =>\n\t\t\t\tarticle.title.toLowerCase().includes(query) ||\n\t\t\t\t(article.description &&\n\t\t\t\t\tarticle.description.toLowerCase().includes(query))\n\t\t);\n\t}\n\n\t/**\n\t * Reset state\n\t */\n\treset() {\n\t\tthis.currentView = 'home';\n\t\tthis.activeConversationId = null;\n\t\tthis.helpSearchQuery = '';\n\t\tthis._notify('reset', {});\n\t}\n}\n","/**\n * MessengerLauncher - Floating trigger button for messenger\n */\nexport class MessengerLauncher {\n\tconstructor(state, options = {}) {\n\t\tthis.state = state;\n\t\tthis.options = {\n\t\t\tposition: options.position || 'bottom-right',\n\t\t\tprimaryColor: options.primaryColor || '#1c1c1e',\n\t\t\t...options,\n\t\t};\n\t\tthis.element = null;\n\t\tthis._unsubscribe = null;\n\t}\n\n\trender() {\n\t\tthis.element = document.createElement('div');\n\t\tthis.element.className = `messenger-launcher messenger-launcher-${this.options.position}`;\n\n\t\tthis._updateContent();\n\t\tthis._attachEvents();\n\n\t\t// Subscribe to state changes\n\t\tthis._unsubscribe = this.state.subscribe((type, data) => {\n\t\t\tif (type === 'openChange') {\n\t\t\t\tthis._updateIcon();\n\t\t\t}\n\t\t\tif (type === 'unreadCountChange') {\n\t\t\t\tthis._updateBadge();\n\t\t\t}\n\t\t});\n\n\t\treturn this.element;\n\t}\n\n\t_updateContent() {\n\t\tconst badgeHtml =\n\t\t\tthis.state.unreadCount > 0\n\t\t\t\t? `<span class=\"messenger-launcher-badge\">${this.state.unreadCount > 9 ? '9+' : this.state.unreadCount}</span>`\n\t\t\t\t: '';\n\n\t\tthis.element.innerHTML = `\n\t\t\t<button class=\"messenger-launcher-btn\" aria-label=\"Open messenger\" style=\"background: ${this.options.primaryColor};\">\n\t\t\t\t<span class=\"messenger-launcher-icon messenger-launcher-icon-chat\">\n\t\t\t\t\t<i class=\"ph ph-chat-circle-dots\" style=\"font-size: 24px;\"></i>\n\t\t\t\t</span>\n\t\t\t\t<span class=\"messenger-launcher-icon messenger-launcher-icon-close\" style=\"display: none;\">\n\t\t\t\t\t<i class=\"ph ph-x\" style=\"font-size: 24px;\"></i>\n\t\t\t\t</span>\n\t\t\t\t${badgeHtml}\n\t\t\t</button>\n\t\t`;\n\t}\n\n\t_attachEvents() {\n\t\tthis.element\n\t\t\t.querySelector('.messenger-launcher-btn')\n\t\t\t.addEventListener('click', () => {\n\t\t\t\tthis.state.setOpen(!this.state.isOpen);\n\t\t\t});\n\t}\n\n\t_updateIcon() {\n\t\tconst chatIcon = this.element.querySelector(\n\t\t\t'.messenger-launcher-icon-chat'\n\t\t);\n\t\tconst closeIcon = this.element.querySelector(\n\t\t\t'.messenger-launcher-icon-close'\n\t\t);\n\n\t\tif (this.state.isOpen) {\n\t\t\tchatIcon.style.display = 'none';\n\t\t\tcloseIcon.style.display = 'flex';\n\t\t\tthis.element.classList.add('messenger-launcher-open');\n\t\t} else {\n\t\t\tchatIcon.style.display = 'flex';\n\t\t\tcloseIcon.style.display = 'none';\n\t\t\tthis.element.classList.remove('messenger-launcher-open');\n\t\t}\n\t}\n\n\t_updateBadge() {\n\t\tconst existingBadge = this.element.querySelector(\n\t\t\t'.messenger-launcher-badge'\n\t\t);\n\t\tif (existingBadge) {\n\t\t\texistingBadge.remove();\n\t\t}\n\n\t\tif (this.state.unreadCount > 0 && !this.state.isOpen) {\n\t\t\tconst badge = document.createElement('span');\n\t\t\tbadge.className = 'messenger-launcher-badge';\n\t\t\tbadge.textContent =\n\t\t\t\tthis.state.unreadCount > 9 ? '9+' : this.state.unreadCount;\n\t\t\tthis.element.querySelector('.messenger-launcher-btn').appendChild(badge);\n\t\t}\n\t}\n\n\tshow() {\n\t\tif (this.element) {\n\t\t\tthis.element.style.display = 'block';\n\t\t}\n\t}\n\n\thide() {\n\t\tif (this.element) {\n\t\t\tthis.element.style.display = 'none';\n\t\t}\n\t}\n\n\tdestroy() {\n\t\tif (this._unsubscribe) {\n\t\t\tthis._unsubscribe();\n\t\t}\n\t\tif (this.element && this.element.parentNode) {\n\t\t\tthis.element.parentNode.removeChild(this.element);\n\t\t}\n\t}\n}\n","/**\n * NavigationTabs - Bottom navigation for messenger\n */\nexport class NavigationTabs {\n\tconstructor(state, options = {}) {\n\t\tthis.state = state;\n\t\tthis.options = options;\n\t\tthis.element = null;\n\t\tthis._unsubscribe = null;\n\t}\n\n\trender() {\n\t\tthis.element = document.createElement('div');\n\t\tthis.element.className = 'messenger-nav';\n\n\t\tthis._updateContent();\n\t\tthis._attachEvents();\n\n\t\t// Subscribe to state changes\n\t\tthis._unsubscribe = this.state.subscribe((type) => {\n\t\t\tif (type === 'viewChange' || type === 'unreadCountChange') {\n\t\t\t\tthis._updateActiveTab();\n\t\t\t}\n\t\t});\n\n\t\treturn this.element;\n\t}\n\n\t_getTabs() {\n\t\tconst tabs = [\n\t\t\t{ id: 'home', label: 'Home', icon: this._getHomeIcon() },\n\t\t\t{\n\t\t\t\tid: 'messages',\n\t\t\t\tlabel: 'Messages',\n\t\t\t\ticon: this._getMessagesIcon(),\n\t\t\t\tbadge: this.state.unreadCount,\n\t\t\t},\n\t\t];\n\n\t\tif (this.state.enableHelp) {\n\t\t\ttabs.push({ id: 'help', label: 'Help', icon: this._getHelpIcon() });\n\t\t}\n\n\t\tif (this.state.enableChangelog) {\n\t\t\ttabs.push({\n\t\t\t\tid: 'changelog',\n\t\t\t\tlabel: 'Changelog',\n\t\t\t\ticon: this._getChangelogIcon(),\n\t\t\t});\n\t\t}\n\n\t\treturn tabs;\n\t}\n\n\t_updateContent() {\n\t\tconst tabs = this._getTabs();\n\t\tconst tabsHtml = tabs\n\t\t\t.map((tab) => {\n\t\t\t\tconst isActive = this.state.currentView === tab.id;\n\t\t\t\tconst badgeHtml =\n\t\t\t\t\ttab.badge && tab.badge > 0\n\t\t\t\t\t\t? `<span class=\"messenger-nav-badge\">${tab.badge > 9 ? '9+' : tab.badge}</span>`\n\t\t\t\t\t\t: '';\n\n\t\t\t\treturn `\n\t\t\t\t<button class=\"messenger-nav-tab ${isActive ? 'active' : ''}\" data-tab=\"${tab.id}\">\n\t\t\t\t\t<span class=\"messenger-nav-icon\">${tab.icon}</span>\n\t\t\t\t\t<span class=\"messenger-nav-label\">${tab.label}</span>\n\t\t\t\t\t${badgeHtml}\n\t\t\t\t</button>\n\t\t\t`;\n\t\t\t})\n\t\t\t.join('');\n\n\t\tthis.element.innerHTML = tabsHtml;\n\t}\n\n\t_attachEvents() {\n\t\tthis.element.addEventListener('click', (e) => {\n\t\t\tconst tab = e.target.closest('.messenger-nav-tab');\n\t\t\tif (tab) {\n\t\t\t\tconst tabId = tab.dataset.tab;\n\t\t\t\tthis.state.setView(tabId);\n\t\t\t}\n\t\t});\n\t}\n\n\t_updateActiveTab() {\n\t\tconst tabs = this.element.querySelectorAll('.messenger-nav-tab');\n\t\ttabs.forEach((tab) => {\n\t\t\tconst isActive = tab.dataset.tab === this.state.currentView;\n\t\t\ttab.classList.toggle('active', isActive);\n\n\t\t\t// Update badge if messages tab\n\t\t\tif (tab.dataset.tab === 'messages') {\n\t\t\t\tconst existingBadge = tab.querySelector('.messenger-nav-badge');\n\t\t\t\tif (existingBadge) existingBadge.remove();\n\n\t\t\t\tif (this.state.unreadCount > 0) {\n\t\t\t\t\tconst badge = document.createElement('span');\n\t\t\t\t\tbadge.className = 'messenger-nav-badge';\n\t\t\t\t\tbadge.textContent =\n\t\t\t\t\t\tthis.state.unreadCount > 9 ? '9+' : this.state.unreadCount;\n\t\t\t\t\ttab.appendChild(badge);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\n\t_getHomeIcon() {\n\t\treturn `<i class=\"ph-duotone ph-house\" style=\"font-size: 24px;\"></i>`;\n\t}\n\n\t_getMessagesIcon() {\n\t\treturn `<i class=\"ph-duotone ph-chat\" style=\"font-size: 24px;\"></i>`;\n\t}\n\n\t_getHelpIcon() {\n\t\treturn `<i class=\"ph-duotone ph-question\" style=\"font-size: 24px;\"></i>`;\n\t}\n\n\t_getChangelogIcon() {\n\t\treturn `<i class=\"ph-duotone ph-megaphone\" style=\"font-size: 24px;\"></i>`;\n\t}\n\n\tdestroy() {\n\t\tif (this._unsubscribe) {\n\t\t\tthis._unsubscribe();\n\t\t}\n\t\tif (this.element && this.element.parentNode) {\n\t\t\tthis.element.parentNode.removeChild(this.element);\n\t\t}\n\t}\n}\n","/**\n * MessengerPanel - Main panel container for messenger\n */\nimport { NavigationTabs } from './NavigationTabs.js';\n\nexport class MessengerPanel {\n\tconstructor(state, options = {}) {\n\t\tthis.state = state;\n\t\tthis.options = {\n\t\t\tposition: options.position || 'bottom-right',\n\t\t\ttheme: options.theme || 'dark',\n\t\t\t...options,\n\t\t};\n\t\tthis.element = null;\n\t\tthis.navigationTabs = null;\n\t\tthis.currentViewComponent = null;\n\t\tthis.viewRegistry = {};\n\t\tthis._unsubscribe = null;\n\t}\n\n\t/**\n\t * Register view components\n\t */\n\tregisterView(name, ViewClass) {\n\t\tthis.viewRegistry[name] = ViewClass;\n\t}\n\n\trender() {\n\t\tthis.element = document.createElement('div');\n\t\tthis.element.className = `messenger-panel messenger-panel-${this.options.position} theme-${this.options.theme}`;\n\n\t\tthis.element.innerHTML = `\n\t\t\t<div class=\"messenger-panel-content\">\n\t\t\t\t<div class=\"messenger-panel-views\"></div>\n\t\t\t\t<div class=\"messenger-panel-nav\"></div>\n\t\t\t</div>\n\t\t`;\n\n\t\t// Render navigation tabs\n\t\tthis.navigationTabs = new NavigationTabs(this.state, this.options);\n\t\tconst navContainer = this.element.querySelector('.messenger-panel-nav');\n\t\tnavContainer.appendChild(this.navigationTabs.render());\n\n\t\t// Render initial view\n\t\tthis._renderCurrentView();\n\n\t\t// Subscribe to state changes\n\t\tthis._unsubscribe = this.state.subscribe((type) => {\n\t\t\tif (type === 'viewChange') {\n\t\t\t\tthis._renderCurrentView();\n\t\t\t}\n\t\t});\n\n\t\treturn this.element;\n\t}\n\n\t_renderCurrentView() {\n\t\tconst viewsContainer = this.element.querySelector('.messenger-panel-views');\n\n\t\t// Destroy current view if exists\n\t\tif (this.currentViewComponent && this.currentViewComponent.destroy) {\n\t\t\tthis.currentViewComponent.destroy();\n\t\t}\n\n\t\t// Clear container\n\t\tviewsContainer.innerHTML = '';\n\n\t\t// Get view class\n\t\tconst ViewClass = this.viewRegistry[this.state.currentView];\n\t\tif (ViewClass) {\n\t\t\tthis.currentViewComponent = new ViewClass(this.state, this.options);\n\t\t\tviewsContainer.appendChild(this.currentViewComponent.render());\n\t\t} else {\n\t\t\tviewsContainer.innerHTML = `<div class=\"messenger-view-placeholder\">View not found: ${this.state.currentView}</div>`;\n\t\t}\n\t}\n\n\t/**\n\t * Show the panel with animation\n\t */\n\tshow() {\n\t\tif (this.element) {\n\t\t\tthis.element.style.display = 'block';\n\t\t\t// Trigger animation\n\t\t\trequestAnimationFrame(() => {\n\t\t\t\tthis.element.classList.add('open');\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Hide the panel with animation\n\t */\n\thide() {\n\t\tif (this.element) {\n\t\t\tthis.element.classList.remove('open');\n\t\t\t// Wait for animation to complete\n\t\t\tsetTimeout(() => {\n\t\t\t\tif (this.element) {\n\t\t\t\t\tthis.element.style.display = 'none';\n\t\t\t\t}\n\t\t\t}, 300);\n\t\t}\n\t}\n\n\t/**\n\t * Set panel header content (used by views)\n\t */\n\tsetHeader(headerContent) {\n\t\tconst header = this.element.querySelector('.messenger-panel-header');\n\t\tif (header) {\n\t\t\theader.innerHTML = headerContent;\n\t\t}\n\t}\n\n\tdestroy() {\n\t\tif (this._unsubscribe) {\n\t\t\tthis._unsubscribe();\n\t\t}\n\t\tif (this.navigationTabs) {\n\t\t\tthis.navigationTabs.destroy();\n\t\t}\n\t\tif (this.currentViewComponent && this.currentViewComponent.destroy) {\n\t\t\tthis.currentViewComponent.destroy();\n\t\t}\n\t\tif (this.element && this.element.parentNode) {\n\t\t\tthis.element.parentNode.removeChild(this.element);\n\t\t}\n\t}\n}\n","/**\n * ChangelogView - Changelog and announcements\n */\nexport class ChangelogView {\n\tconstructor(state, options = {}) {\n\t\tthis.state = state;\n\t\tthis.options = options;\n\t\tthis.element = null;\n\t\tthis._unsubscribe = null;\n\t}\n\n\trender() {\n\t\tthis.element = document.createElement('div');\n\t\tthis.element.className = 'messenger-view messenger-changelog-view';\n\n\t\tthis._updateContent();\n\n\t\t// Subscribe to state changes\n\t\tthis._unsubscribe = this.state.subscribe((type) => {\n\t\t\tif (type === 'changelogUpdate') {\n\t\t\t\tthis._updateChangelogList();\n\t\t\t}\n\t\t});\n\n\t\treturn this.element;\n\t}\n\n\t_updateContent() {\n\t\tconst avatarsHtml = this._renderTeamAvatars();\n\n\t\tthis.element.innerHTML = `\n\t\t\t<div class=\"messenger-changelog-header\">\n\t\t\t\t<h2>Changelog</h2>\n\t\t\t\t<button class=\"messenger-close-btn\" aria-label=\"Close\">\n\t\t\t\t\t<i class=\"ph ph-x\" style=\"font-size: 20px;\"></i>\n\t\t\t\t</button>\n\t\t\t</div>\n\n\t\t\t<div class=\"messenger-changelog-subheader\">\n\t\t\t\t<span class=\"messenger-changelog-latest\">Latest</span>\n\t\t\t\t<div class=\"messenger-changelog-team\">\n\t\t\t\t\t<span>From ${this.state.teamName}</span>\n\t\t\t\t\t${avatarsHtml}\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t<div class=\"messenger-changelog-body\">\n\t\t\t\t<div class=\"messenger-changelog-list\"></div>\n\t\t\t</div>\n\t\t`;\n\n\t\tthis._updateChangelogList();\n\t\tthis._attachEvents();\n\t}\n\n\t_updateChangelogList() {\n\t\tconst changelogContainer = this.element.querySelector(\n\t\t\t'.messenger-changelog-list'\n\t\t);\n\t\tconst changelogItems = this.state.changelogItems;\n\n\t\tif (changelogItems.length === 0) {\n\t\t\tchangelogContainer.innerHTML = this._renderEmptyState();\n\t\t\treturn;\n\t\t}\n\n\t\tchangelogContainer.innerHTML = changelogItems\n\t\t\t.map((item) => this._renderChangelogCard(item))\n\t\t\t.join('');\n\n\t\t// Attach click events\n\t\tthis._attachChangelogEvents();\n\t}\n\n\t_renderChangelogCard(item) {\n\t\tconst tagsHtml =\n\t\t\titem.tags && item.tags.length > 0\n\t\t\t\t? `<div class=\"messenger-changelog-tags\">\n\t\t\t\t${item.tags.map((tag) => `<span class=\"messenger-changelog-tag\">${tag}</span>`).join('')}\n\t\t\t</div>`\n\t\t\t\t: '';\n\n\t\tconst dateStr = this._formatDate(item.publishedAt || item.date);\n\n\t\treturn `\n\t\t\t<div class=\"messenger-changelog-card\" data-changelog-id=\"${item.id}\">\n\t\t\t\t${\n\t\t\t\t\titem.coverImage\n\t\t\t\t\t\t? `\n\t\t\t\t\t<div class=\"messenger-changelog-cover\">\n\t\t\t\t\t\t<img src=\"${item.coverImage}\" alt=\"${item.title}\" onerror=\"this.style.display='none';\" />\n\t\t\t\t\t</div>\n\t\t\t\t`\n\t\t\t\t\t\t: ''\n\t\t\t\t}\n\t\t\t\t<div class=\"messenger-changelog-content\">\n\t\t\t\t\t${tagsHtml}\n\t\t\t\t\t<h3 class=\"messenger-changelog-title\">${item.title}</h3>\n\t\t\t\t\t${item.description ? `<p class=\"messenger-changelog-description\">${this._truncateText(item.description, 100)}</p>` : ''}\n\t\t\t\t\t<div class=\"messenger-changelog-meta\">\n\t\t\t\t\t\t<span class=\"messenger-changelog-date\">${dateStr}</span>\n\t\t\t\t\t\t<i class=\"ph ph-caret-right messenger-changelog-arrow\" style=\"font-size: 16px;\"></i>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t`;\n\t}\n\n\t_renderTeamAvatars() {\n\t\tconst avatars = this.state.teamAvatars;\n\t\tif (!avatars || avatars.length === 0) {\n\t\t\treturn `\n\t\t\t\t<div class=\"messenger-avatar-stack messenger-avatar-stack-tiny\">\n\t\t\t\t\t<div class=\"messenger-avatar messenger-avatar-tiny\" style=\"background: #5856d6;\">S</div>\n\t\t\t\t</div>\n\t\t\t`;\n\t\t}\n\n\t\tconst colors = ['#5856d6', '#007aff', '#34c759'];\n\t\tconst avatarItems = avatars\n\t\t\t.slice(0, 2)\n\t\t\t.map((avatar, i) => {\n\t\t\t\tif (typeof avatar === 'string' && avatar.startsWith('http')) {\n\t\t\t\t\treturn `<img class=\"messenger-avatar messenger-avatar-tiny\" src=\"${avatar}\" alt=\"Team member\" style=\"z-index: ${2 - i};\" />`;\n\t\t\t\t}\n\t\t\t\treturn `<div class=\"messenger-avatar messenger-avatar-tiny\" style=\"background: ${colors[i % colors.length]}; z-index: ${2 - i};\">${avatar.charAt(0).toUpperCase()}</div>`;\n\t\t\t})\n\t\t\t.join('');\n\n\t\treturn `<div class=\"messenger-avatar-stack messenger-avatar-stack-tiny\">${avatarItems}</div>`;\n\t}\n\n\t_renderEmptyState() {\n\t\treturn `\n\t\t\t<div class=\"messenger-changelog-empty\">\n\t\t\t\t<div class=\"messenger-changelog-empty-icon\">\n\t\t\t\t\t<i class=\"ph ph-megaphone\" style=\"font-size: 48px;\"></i>\n\t\t\t\t</div>\n\t\t\t\t<h3>No changelog yet</h3>\n\t\t\t\t<p>Check back later for updates</p>\n\t\t\t</div>\n\t\t`;\n\t}\n\n\t_formatDate(dateString) {\n\t\tif (!dateString) return '';\n\t\tconst date = new Date(dateString);\n\t\treturn date.toLocaleDateString('en-US', {\n\t\t\tmonth: 'short',\n\t\t\tday: 'numeric',\n\t\t\tyear: 'numeric',\n\t\t});\n\t}\n\n\t_truncateText(text, maxLength) {\n\t\tif (!text) return '';\n\t\tif (text.length <= maxLength) return text;\n\t\treturn text.substring(0, maxLength).trim() + '...';\n\t}\n\n\t_attachEvents() {\n\t\t// Close button\n\t\tthis.element\n\t\t\t.querySelector('.messenger-close-btn')\n\t\t\t.addEventListener('click', () => {\n\t\t\t\tthis.state.setOpen(false);\n\t\t\t});\n\n\t\tthis._attachChangelogEvents();\n\t}\n\n\t_attachChangelogEvents() {\n\t\tthis.element\n\t\t\t.querySelectorAll('.messenger-changelog-card')\n\t\t\t.forEach((card) => {\n\t\t\t\tcard.addEventListener('click', () => {\n\t\t\t\t\tconst changelogId = card.dataset.changelogId;\n\t\t\t\t\tconst changelogItem = this.state.changelogItems.find(\n\t\t\t\t\t\t(n) => n.id === changelogId\n\t\t\t\t\t);\n\t\t\t\t\tif (changelogItem && changelogItem.url) {\n\t\t\t\t\t\twindow.open(changelogItem.url, '_blank');\n\t\t\t\t\t} else if (this.options.onChangelogClick) {\n\t\t\t\t\t\tthis.options.onChangelogClick(changelogItem);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t});\n\t}\n\n\tdestroy() {\n\t\tif (this._unsubscribe) {\n\t\t\tthis._unsubscribe();\n\t\t}\n\t\tif (this.element && this.element.parentNode) {\n\t\t\tthis.element.parentNode.removeChild(this.element);\n\t\t}\n\t}\n}\n","/**\n * ChatView - Individual conversation chat\n */\nexport class ChatView {\n\tconstructor(state, options = {}) {\n\t\tthis.state = state;\n\t\tthis.options = options;\n\t\tthis.element = null;\n\t\tthis._unsubscribe = null;\n\t\tthis._typingTimeout = null;\n\t\tthis._isTyping = false;\n\t\tthis._typingIndicator = null;\n\t}\n\n\trender() {\n\t\tthis.element = document.createElement('div');\n\t\tthis.element.className = 'messenger-view messenger-chat-view';\n\n\t\tthis._updateContent();\n\n\t\t// Subscribe to state changes\n\t\tthis._unsubscribe = this.state.subscribe((type, data) => {\n\t\t\tif (\n\t\t\t\ttype === 'messageAdded' &&\n\t\t\t\tdata.conversationId === this.state.activeConversationId\n\t\t\t) {\n\t\t\t\tthis._hideTypingIndicator();\n\t\t\t\tthis._appendMessage(data.message);\n\t\t\t\tthis._scrollToBottom();\n\t\t\t} else if (\n\t\t\t\ttype === 'typingStarted' &&\n\t\t\t\tdata.conversationId === this.state.activeConversationId\n\t\t\t) {\n\t\t\t\tthis._showTypingIndicator(data.userName);\n\t\t\t} else if (\n\t\t\t\ttype === 'typingStopped' &&\n\t\t\t\tdata.conversationId === this.state.activeConversationId\n\t\t\t) {\n\t\t\t\tthis._hideTypingIndicator();\n\t\t\t} else if (\n\t\t\t\ttype === 'messagesUpdate' &&\n\t\t\t\tdata.conversationId === this.state.activeConversationId\n\t\t\t) {\n\t\t\t\tthis._updateContent();\n\t\t\t}\n\t\t});\n\n\t\treturn this.element;\n\t}\n\n\t_updateContent() {\n\t\tconst conversation = this.state.getActiveConversation();\n\t\tconst messages = this.state.getActiveMessages();\n\t\tconst isNewConversation = !this.state.activeConversationId;\n\n\t\tconst messagesHtml =\n\t\t\tmessages.length === 0\n\t\t\t\t? this._renderEmptyState(isNewConversation)\n\t\t\t\t: messages.map((msg) => this._renderMessage(msg)).join('');\n\n\t\tconst avatarHtml = this._renderConversationAvatar(conversation);\n\t\tconst title = isNewConversation\n\t\t\t? 'New conversation'\n\t\t\t: conversation?.title || 'Chat with team';\n\t\tconst placeholder = isNewConversation\n\t\t\t? 'Start typing your message...'\n\t\t\t: 'Write a message...';\n\n\t\tthis.element.innerHTML = `\n\t\t\t<div class=\"messenger-chat-header\">\n\t\t\t\t<button class=\"messenger-back-btn\" aria-label=\"Back\">\n\t\t\t\t\t<i class=\"ph ph-caret-left\" style=\"font-size: 20px;\"></i>\n\t\t\t\t</button>\n\t\t\t\t<div class=\"messenger-chat-header-info\">\n\t\t\t\t\t${avatarHtml}\n\t\t\t\t\t<span class=\"messenger-chat-title\">${title}</span>\n\t\t\t\t</div>\n\t\t\t\t<button class=\"messenger-close-btn\" aria-label=\"Close\">\n\t\t\t\t\t<i class=\"ph ph-x\" style=\"font-size: 20px;\"></i>\n\t\t\t\t</button>\n\t\t\t</div>\n\n\t\t\t<div class=\"messenger-chat-messages\">\n\t\t\t\t${messagesHtml}\n\t\t\t\t<div class=\"messenger-typing-indicator\" style=\"display: none;\">\n\t\t\t\t\t<div class=\"messenger-typing-dots\">\n\t\t\t\t\t\t<span></span><span></span><span></span>\n\t\t\t\t\t</div>\n\t\t\t\t\t<span class=\"messenger-typing-text\"></span>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t<div class=\"messenger-chat-compose\">\n\t\t\t\t<div class=\"messenger-compose-input-wrapper\">\n\t\t\t\t\t<textarea class=\"messenger-compose-input\" placeholder=\"${placeholder}\" rows=\"1\"></textarea>\n\t\t\t\t</div>\n\t\t\t\t<button class=\"messenger-compose-send\" aria-label=\"Send\" disabled>\n\t\t\t\t\t<i class=\"ph ph-paper-plane-tilt\" style=\"font-size: 20px;\"></i>\n\t\t\t\t</button>\n\t\t\t</div>\n\t\t`;\n\n\t\tthis._typingIndicator = this.element.querySelector(\n\t\t\t'.messenger-typing-indicator'\n\t\t);\n\t\tthis._attachEvents();\n\t\tthis._scrollToBottom();\n\t}\n\n\t_renderEmptyState(isNewConversation = false) {\n\t\tconst avatarHtml = this._renderTeamAvatars();\n\t\tconst responseTime =\n\t\t\tthis.state.responseTime || 'We typically reply within a few minutes';\n\t\tconst isOnline = this.state.agentsOnline;\n\n\t\treturn `\n\t\t\t<div class=\"messenger-chat-empty\">\n\t\t\t\t<div class=\"messenger-chat-empty-avatars\">${avatarHtml}</div>\n\t\t\t\t<h3>${isNewConversation ? 'Start a new conversation' : 'Start the conversation'}</h3>\n\t\t\t\t<p>Send us a message and we'll get back to you as soon as possible.</p>\n\t\t\t\t<div class=\"messenger-chat-availability\">\n\t\t\t\t\t<span class=\"messenger-availability-dot ${isOnline ? 'messenger-availability-online' : 'messenger-availability-away'}\"></span>\n\t\t\t\t\t<span>${isOnline ? \"We're online now\" : responseTime}</span>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t`;\n\t}\n\n\t_renderMessage(message) {\n\t\tconst isOwn = message.isOwn;\n\t\tconst messageClass = isOwn\n\t\t\t? 'messenger-message-own'\n\t\t\t: 'messenger-message-received';\n\t\tconst timeStr = this._formatMessageTime(message.timestamp);\n\n\t\tif (isOwn) {\n\t\t\treturn `\n\t\t\t\t<div class=\"messenger-message ${messageClass}\">\n\t\t\t\t\t<div class=\"messenger-message-bubble\">\n\t\t\t\t\t\t<div class=\"messenger-message-content\">${this._formatMessageContent(message.content)}</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"messenger-message-time\">${timeStr}</div>\n\t\t\t\t</div>\n\t\t\t`;\n\t\t}\n\n\t\tconst avatarHtml = this._renderSenderAvatar(message.sender);\n\t\treturn `\n\t\t\t<div class=\"messenger-message ${messageClass}\">\n\t\t\t\t<div class=\"messenger-message-avatar\">${avatarHtml}</div>\n\t\t\t\t<div class=\"messenger-message-wrapper\">\n\t\t\t\t\t<div class=\"messenger-message-sender\">${message.sender?.name || 'Support'}</div>\n\t\t\t\t\t<div class=\"messenger-message-bubble\">\n\t\t\t\t\t\t<div class=\"messenger-message-content\">${this._formatMessageContent(message.content)}</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"messenger-message-time\">${timeStr}</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t`;\n\t}\n\n\t_renderSenderAvatar(sender) {\n\t\tif (sender?.avatarUrl) {\n\t\t\treturn `<img class=\"messenger-avatar messenger-avatar-small\" src=\"${sender.avatarUrl}\" alt=\"${sender.name}\" />`;\n\t\t}\n\t\tconst initial = (sender?.name || 'S').charAt(0).toUpperCase();\n\t\treturn `<div class=\"messenger-avatar messenger-avatar-small\" style=\"background: #5856d6;\">${initial}</div>`;\n\t}\n\n\t_renderConversationAvatar(conversation) {\n\t\tif (!conversation?.participants?.length) {\n\t\t\treturn `<div class=\"messenger-avatar messenger-avatar-small\" style=\"background: #5856d6;\">S</div>`;\n\t\t}\n\t\tconst p = conversation.participants[0];\n\t\tif (p.avatarUrl) {\n\t\t\treturn `<img class=\"messenger-avatar messenger-avatar-small\" src=\"${p.avatarUrl}\" alt=\"${p.name}\" />`;\n\t\t}\n\t\treturn `<div class=\"messenger-avatar messenger-avatar-small\" style=\"background: #5856d6;\">${(p.name || 'S').charAt(0).toUpperCase()}</div>`;\n\t}\n\n\t_renderTeamAvatars() {\n\t\tconst avatars = this.state.teamAvatars;\n\t\tif (!avatars || avatars.length === 0) {\n\t\t\treturn `\n\t\t\t\t<div class=\"messenger-avatar-stack\">\n\t\t\t\t\t<div class=\"messenger-avatar\" style=\"background: #5856d6;\">S</div>\n\t\t\t\t\t<div class=\"messenger-avatar\" style=\"background: #007aff;\">T</div>\n\t\t\t\t</div>\n\t\t\t`;\n\t\t}\n\n\t\tconst colors = ['#5856d6', '#007aff', '#34c759', '#ff9500', '#ff3b30'];\n\t\tconst avatarItems = avatars\n\t\t\t.slice(0, 3)\n\t\t\t.map((avatar, i) => {\n\t\t\t\tif (typeof avatar === 'string' && avatar.startsWith('http')) {\n\t\t\t\t\treturn `<img class=\"messenger-avatar\" src=\"${avatar}\" alt=\"Team member\" style=\"z-index: ${3 - i};\" />`;\n\t\t\t\t}\n\t\t\t\treturn `<div class=\"messenger-avatar\" style=\"background: ${colors[i % colors.length]}; z-index: ${3 - i};\">${avatar.charAt(0).toUpperCase()}</div>`;\n\t\t\t})\n\t\t\t.join('');\n\n\t\treturn `<div class=\"messenger-avatar-stack\">${avatarItems}</div>`;\n\t}\n\n\t_formatMessageTime(timestamp) {\n\t\tif (!timestamp) return '';\n\t\tconst date = new Date(timestamp);\n\t\treturn date.toLocaleTimeString('en-US', {\n\t\t\thour: 'numeric',\n\t\t\tminute: '2-digit',\n\t\t\thour12: true,\n\t\t});\n\t}\n\n\t_formatMessageContent(content) {\n\t\tif (!content) return '';\n\t\t// Basic HTML escaping and line breaks\n\t\treturn content\n\t\t\t.replace(/&/g, '&')\n\t\t\t.replace(/</g, '<')\n\t\t\t.replace(/>/g, '>')\n\t\t\t.replace(/\\n/g, '<br>');\n\t}\n\n\t_appendMessage(message) {\n\t\tconst messagesContainer = this.element.querySelector(\n\t\t\t'.messenger-chat-messages'\n\t\t);\n\t\tconst emptyState = messagesContainer.querySelector('.messenger-chat-empty');\n\t\tif (emptyState) {\n\t\t\temptyState.remove();\n\t\t}\n\n\t\tconst messageHtml = this._renderMessage(message);\n\t\tconst tempDiv = document.createElement('div');\n\t\ttempDiv.innerHTML = messageHtml;\n\t\tmessagesContainer.appendChild(tempDiv.firstElementChild);\n\t}\n\n\t_scrollToBottom() {\n\t\tconst messagesContainer = this.element.querySelector(\n\t\t\t'.messenger-chat-messages'\n\t\t);\n\t\tif (messagesContainer) {\n\t\t\tsetTimeout(() => {\n\t\t\t\tmessagesContainer.scrollTop = messagesContainer.scrollHeight;\n\t\t\t}, 50);\n\t\t}\n\t}\n\n\t_attachEvents() {\n\t\t// Back button\n\t\tthis.element\n\t\t\t.querySelector('.messenger-back-btn')\n\t\t\t.addEventListener('click', () => {\n\t\t\t\tthis.state.setView('messages');\n\t\t\t});\n\n\t\t// Close button\n\t\tthis.element\n\t\t\t.querySelector('.messenger-close-btn')\n\t\t\t.addEventListener('click', () => {\n\t\t\t\tthis.state.setOpen(false);\n\t\t\t});\n\n\t\t// Compose input\n\t\tconst input = this.element.querySelector('.messenger-compose-input');\n\t\tconst sendBtn = this.element.querySelector('.messenger-compose-send');\n\n\t\tinput.addEventListener('input', () => {\n\t\t\t// Auto-resize textarea\n\t\t\tinput.style.height = 'auto';\n\t\t\tinput.style.height = Math.min(input.scrollHeight, 120) + 'px';\n\n\t\t\t// Enable/disable send button\n\t\t\tsendBtn.disabled = !input.value.trim();\n\n\t\t\t// Send typing indicator\n\t\t\tif (input.value.trim()) {\n\t\t\t\tthis._startTyping();\n\t\t\t}\n\t\t});\n\n\t\tinput.addEventListener('keydown', (e) => {\n\t\t\tif (e.key === 'Enter' && !e.shiftKey) {\n\t\t\t\te.preventDefault();\n\t\t\t\tthis._sendMessage();\n\t\t\t}\n\t\t});\n\n\t\tsendBtn.addEventListener('click', () => {\n\t\t\tthis._sendMessage();\n\t\t});\n\t}\n\n\t_sendMessage() {\n\t\tconst input = this.element.querySelector('.messenger-compose-input');\n\t\tconst content = input.value.trim();\n\n\t\tif (!content) return;\n\n\t\t// Stop typing indicator\n\t\tthis._stopTyping();\n\n\t\tconst isNewConversation = !this.state.activeConversationId;\n\n\t\tif (isNewConversation) {\n\t\t\t// Start a new conversation\n\t\t\tif (this.options.onStartConversation) {\n\t\t\t\tthis.options.onStartConversation(content);\n\t\t\t}\n\t\t} else {\n\t\t\t// Add message to existing conversation\n\t\t\tconst message = {\n\t\t\t\tid: 'msg_' + Date.now(),\n\t\t\t\tcontent: content,\n\t\t\t\tisOwn: true,\n\t\t\t\ttimestamp: new Date().toISOString(),\n\t\t\t};\n\n\t\t\tthis.state.addMessage(this.state.activeConversationId, message);\n\n\t\t\t// Emit event for API integration\n\t\t\tif (this.options.onSendMessage) {\n\t\t\t\tthis.options.onSendMessage(this.state.activeConversationId, message);\n\t\t\t}\n\t\t}\n\n\t\t// Clear input\n\t\tinput.value = '';\n\t\tinput.style.height = 'auto';\n\t\tthis.element.querySelector('.messenger-compose-send').disabled = true;\n\t}\n\n\t_startTyping() {\n\t\tif (!this._isTyping && this.state.activeConversationId) {\n\t\t\tthis._isTyping = true;\n\t\t\tif (this.options.onTyping) {\n\t\t\t\tthis.options.onTyping(this.state.activeConversationId, true);\n\t\t\t}\n\t\t}\n\n\t\t// Reset typing timeout\n\t\tif (this._typingTimeout) {\n\t\t\tclearTimeout(this._typingTimeout);\n\t\t}\n\t\tthis._typingTimeout = setTimeout(() => {\n\t\t\tthis._stopTyping();\n\t\t}, 3000);\n\t}\n\n\t_stopTyping() {\n\t\tif (this._isTyping && this.state.activeConversationId) {\n\t\t\tthis._isTyping = false;\n\t\t\tif (this.options.onTyping) {\n\t\t\t\tthis.options.onTyping(this.state.activeConversationId, false);\n\t\t\t}\n\t\t}\n\t\tif (this._typingTimeout) {\n\t\t\tclearTimeout(this._typingTimeout);\n\t\t\tthis._typingTimeout = null;\n\t\t}\n\t}\n\n\t_showTypingIndicator(userName) {\n\t\tif (this._typingIndicator) {\n\t\t\tthis._typingIndicator.style.display = 'flex';\n\t\t\tconst textEl = this._typingIndicator.querySelector(\n\t\t\t\t'.messenger-typing-text'\n\t\t\t);\n\t\t\tif (textEl) {\n\t\t\t\ttextEl.textContent = `${userName || 'Support'} is typing...`;\n\t\t\t}\n\t\t\tthis._scrollToBottom();\n\t\t}\n\t}\n\n\t_hideTypingIndicator() {\n\t\tif (this._typingIndicator) {\n\t\t\tthis._typingIndicator.style.display = 'none';\n\t\t}\n\t}\n\n\tdestroy() {\n\t\tif (this._unsubscribe) {\n\t\t\tthis._unsubscribe();\n\t\t}\n\t\tif (this._typingTimeout) {\n\t\t\tclearTimeout(this._typingTimeout);\n\t\t}\n\t\tthis._stopTyping();\n\t\tif (this.element && this.element.parentNode) {\n\t\t\tthis.element.parentNode.removeChild(this.element);\n\t\t}\n\t}\n}\n","/**\n * ConversationsView - Message thread list\n */\nexport class ConversationsView {\n\tconstructor(state, options = {}) {\n\t\tthis.state = state;\n\t\tthis.options = options;\n\t\tthis.element = null;\n\t\tthis._unsubscribe = null;\n\t}\n\n\trender() {\n\t\tthis.element = document.createElement('div');\n\t\tthis.element.className = 'messenger-view messenger-conversations-view';\n\n\t\tthis._updateContent();\n\t\tthis._attachEvents();\n\n\t\t// Subscribe to state changes\n\t\tthis._unsubscribe = this.state.subscribe((type) => {\n\t\t\tif (\n\t\t\t\ttype === 'conversationsUpdate' ||\n\t\t\t\ttype === 'conversationAdded' ||\n\t\t\t\ttype === 'conversationRead'\n\t\t\t) {\n\t\t\t\tthis._updateContent();\n\t\t\t}\n\t\t});\n\n\t\treturn this.element;\n\t}\n\n\t_updateContent() {\n\t\tconst conversations = this.state.conversations;\n\t\tconst avatarsHtml = this._renderAvatarStack();\n\n\t\tlet conversationsHtml;\n\t\tif (conversations.length === 0) {\n\t\t\tconversationsHtml = `\n\t\t\t\t<div class=\"messenger-conversations-empty\">\n\t\t\t\t\t<div class=\"messenger-conversations-empty-icon\">\n\t\t\t\t\t\t<i class=\"ph ph-chat\" style=\"font-size: 48px;\"></i>\n\t\t\t\t\t</div>\n\t\t\t\t\t<h3>No conversations yet</h3>\n\t\t\t\t\t<p>Start a new conversation with our team</p>\n\t\t\t\t</div>\n\t\t\t`;\n\t\t} else {\n\t\t\tconversationsHtml = `\n\t\t\t\t<div class=\"messenger-conversations-list\">\n\t\t\t\t\t${conversations.map((conv) => this._renderConversationItem(conv)).join('')}\n\t\t\t\t</div>\n\t\t\t`;\n\t\t}\n\n\t\tthis.element.innerHTML = `\n\t\t\t<div class=\"messenger-conversations-header\">\n\t\t\t\t<h2>Messages</h2>\n\t\t\t\t<button class=\"messenger-close-btn\" aria-label=\"Close\">\n\t\t\t\t\t<i class=\"ph ph-x\" style=\"font-size: 20px;\"></i>\n\t\t\t\t</button>\n\t\t\t</div>\n\n\t\t\t<div class=\"messenger-conversations-body\">\n\t\t\t\t${conversationsHtml}\n\t\t\t</div>\n\n\t\t\t<div class=\"messenger-conversations-footer\">\n\t\t\t\t<button class=\"messenger-new-message-btn\">\n\t\t\t\t\t<div class=\"messenger-new-message-avatars\">${avatarsHtml}</div>\n\t\t\t\t\t<span>Send us a message</span>\n\t\t\t\t\t<i class=\"ph ph-arrow-right\" style=\"font-size: 16px;\"></i>\n\t\t\t\t</button>\n\t\t\t</div>\n\t\t`;\n\n\t\tthis._attachEvents();\n\t}\n\n\t_renderConversationItem(conversation) {\n\t\tconst unreadClass = conversation.unread > 0 ? 'unread' : '';\n\t\tconst timeAgo = this._formatTimeAgo(conversation.lastMessageTime);\n\t\tconst avatarsHtml = this._renderConversationAvatars(\n\t\t\tconversation.participants\n\t\t);\n\n\t\treturn `\n\t\t\t<div class=\"messenger-conversation-item ${unreadClass}\" data-conversation-id=\"${conversation.id}\">\n\t\t\t\t<div class=\"messenger-conversation-avatars\">\n\t\t\t\t\t${avatarsHtml}\n\t\t\t\t</div>\n\t\t\t\t<div class=\"messenger-conversation-content\">\n\t\t\t\t\t<div class=\"messenger-conversation-header\">\n\t\t\t\t\t\t<span class=\"messenger-conversation-title\">${conversation.title || 'Chat with team'}</span>\n\t\t\t\t\t\t<span class=\"messenger-conversation-time\">${timeAgo}</span>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"messenger-conversation-preview\">\n\t\t\t\t\t\t${conversation.unread > 0 ? '<span class=\"messenger-unread-dot\"></span>' : ''}\n\t\t\t\t\t\t<span class=\"messenger-conversation-message\">${this._truncateMessage(conversation.lastMessage)}</span>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t`;\n\t}\n\n\t_renderConversationAvatars(participants) {\n\t\tif (!participants || participants.length === 0) {\n\t\t\treturn `<div class=\"messenger-avatar messenger-avatar-medium\" style=\"background: #5856d6;\">S</div>`;\n\t\t}\n\n\t\tconst p = participants[0];\n\t\tif (p.avatarUrl) {\n\t\t\treturn `<img class=\"messenger-avatar messenger-avatar-medium\" src=\"${p.avatarUrl}\" alt=\"${p.name}\" />`;\n\t\t}\n\t\treturn `<div class=\"messenger-avatar messenger-avatar-medium\" style=\"background: ${this._getAvatarColor(0)};\">${(p.name || 'S').charAt(0).toUpperCase()}</div>`;\n\t}\n\n\t_renderAvatarStack() {\n\t\tconst avatars = this.state.teamAvatars;\n\t\tif (!avatars || avatars.length === 0) {\n\t\t\treturn `\n\t\t\t\t<div class=\"messenger-avatar-stack messenger-avatar-stack-small\">\n\t\t\t\t\t<div class=\"messenger-avatar messenger-avatar-small\" style=\"background: #5856d6;\">S</div>\n\t\t\t\t\t<div class=\"messenger-avatar messenger-avatar-small\" style=\"background: #007aff;\">T</div>\n\t\t\t\t</div>\n\t\t\t`;\n\t\t}\n\n\t\tconst avatarItems = avatars\n\t\t\t.slice(0, 2)\n\t\t\t.map((avatar, i) => {\n\t\t\t\tif (typeof avatar === 'string' && avatar.startsWith('http')) {\n\t\t\t\t\treturn `<img class=\"messenger-avatar messenger-avatar-small\" src=\"${avatar}\" alt=\"Team member\" style=\"z-index: ${2 - i};\" />`;\n\t\t\t\t}\n\t\t\t\treturn `<div class=\"messenger-avatar messenger-avatar-small\" style=\"background: ${this._getAvatarColor(i)}; z-index: ${2 - i};\">${avatar.charAt(0).toUpperCase()}</div>`;\n\t\t\t})\n\t\t\t.join('');\n\n\t\treturn `<div class=\"messenger-avatar-stack messenger-avatar-stack-small\">${avatarItems}</div>`;\n\t}\n\n\t_getAvatarColor(index) {\n\t\tconst colors = ['#5856d6', '#007aff', '#34c759', '#ff9500', '#ff3b30'];\n\t\treturn colors[index % colors.length];\n\t}\n\n\t_formatTimeAgo(timestamp) {\n\t\tif (!timestamp) return '';\n\t\tconst date = new Date(timestamp);\n\t\tconst now = new Date();\n\t\tconst diffMs = now - date;\n\t\tconst diffMins = Math.floor(diffMs / 60000);\n\t\tconst diffHours = Math.floor(diffMs / 3600000);\n\t\tconst diffDays = Math.floor(diffMs / 86400000);\n\n\t\tif (diffMins < 1) return 'now';\n\t\tif (diffMins < 60) return `${diffMins}m`;\n\t\tif (diffHours < 24) return `${diffHours}h`;\n\t\tif (diffDays < 7) return `${diffDays}d`;\n\t\treturn date.toLocaleDateString('en-US', { month: 'short', day: 'numeric' });\n\t}\n\n\t_truncateMessage(message) {\n\t\tif (!message) return 'No messages yet';\n\t\tconst maxLength = 50;\n\t\tif (message.length <= maxLength) return message;\n\t\treturn message.substring(0, maxLength) + '...';\n\t}\n\n\t_attachEvents() {\n\t\t// Close button\n\t\tconst closeBtn = this.element.querySelector('.messenger-close-btn');\n\t\tif (closeBtn) {\n\t\t\tcloseBtn.addEventListener('click', () => {\n\t\t\t\tthis.state.setOpen(false);\n\t\t\t});\n\t\t}\n\n\t\t// Conversation items\n\t\tthis.element\n\t\t\t.querySelectorAll('.messenger-conversation-item')\n\t\t\t.forEach((item) => {\n\t\t\t\titem.addEventListener('click', () => {\n\t\t\t\t\tconst convId = item.dataset.conversationId;\n\t\t\t\t\tthis.state.setActiveConversation(convId);\n\t\t\t\t\tthis.state.markAsRead(convId);\n\t\t\t\t\tthis.state.setView('chat');\n\n\t\t\t\t\t// Notify widget to fetch messages\n\t\t\t\t\tif (this.options.onSelectConversation) {\n\t\t\t\t\t\tthis.options.onSelectConversation(convId);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t});\n\n\t\t// New message button\n\t\tconst newMsgBtn = this.element.querySelector('.messenger-new-message-btn');\n\t\tif (newMsgBtn) {\n\t\t\tnewMsgBtn.addEventListener('click', () => {\n\t\t\t\tthis._startNewConversation();\n\t\t\t});\n\t\t}\n\t}\n\n\t_startNewConversation() {\n\t\t// Set view to chat with no active conversation (new conversation mode)\n\t\tthis.state.setActiveConversation(null);\n\t\tthis.state.setView('chat');\n\n\t\t// Notify widget to handle new conversation flow\n\t\tif (this.options.onStartNewConversation) {\n\t\t\tthis.options.onStartNewConversation();\n\t\t}\n\t}\n\n\tdestroy() {\n\t\tif (this._unsubscribe) {\n\t\t\tthis._unsubscribe();\n\t\t}\n\t\tif (this.element && this.element.parentNode) {\n\t\t\tthis.element.parentNode.removeChild(this.element);\n\t\t}\n\t}\n}\n","/**\n * HelpView - Help collections browse with Intercom-style design\n */\nexport class HelpView {\n\tconstructor(state, options = {}) {\n\t\tthis.state = state;\n\t\tthis.options = options;\n\t\tthis.element = null;\n\t\tthis._unsubscribe = null;\n\t}\n\n\trender() {\n\t\tthis.element = document.createElement('div');\n\t\tthis.element.className = 'messenger-view messenger-help-view';\n\n\t\tthis._updateContent();\n\n\t\t// Subscribe to state changes\n\t\tthis._unsubscribe = this.state.subscribe((type) => {\n\t\t\tif (type === 'helpArticlesUpdate' || type === 'helpSearchChange') {\n\t\t\t\tthis._updateCollectionsList();\n\t\t\t}\n\t\t});\n\n\t\treturn this.element;\n\t}\n\n\t_updateContent() {\n\t\tconst searchQuery = this.state.helpSearchQuery || '';\n\t\tconst collections = this.state.helpArticles || [];\n\t\tconst collectionCount = collections.length;\n\n\t\tthis.element.innerHTML = `\n\t\t\t<div class=\"messenger-help-header\">\n\t\t\t\t<h2>Help</h2>\n\t\t\t\t<button class=\"messenger-close-btn\" aria-label=\"Close\">\n\t\t\t\t\t<i class=\"ph ph-x\" style=\"font-size: 20px;\"></i>\n\t\t\t\t</button>\n\t\t\t</div>\n\n\t\t\t<div class=\"messenger-help-search\">\n\t\t\t\t<div class=\"messenger-help-search-wrapper\">\n\t\t\t\t\t<input\n\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\tclass=\"messenger-help-search-input\"\n\t\t\t\t\t\tplaceholder=\"Search for help\"\n\t\t\t\t\t\tvalue=\"${searchQuery}\"\n\t\t\t\t\t/>\n\t\t\t\t\t<i class=\"ph ph-magnifying-glass messenger-help-search-icon\" style=\"font-size: 18px;\"></i>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t<div class=\"messenger-help-body\">\n\t\t\t\t<div class=\"messenger-help-collections-header\">\n\t\t\t\t\t${collectionCount} collections\n\t\t\t\t</div>\n\t\t\t\t<div class=\"messenger-help-collections\"></div>\n\t\t\t</div>\n\t\t`;\n\n\t\tthis._updateCollectionsList();\n\t\tthis._attachEvents();\n\t}\n\n\t_updateCollectionsList() {\n\t\tconst collectionsContainer = this.element.querySelector(\n\t\t\t'.messenger-help-collections'\n\t\t);\n\t\tconst collections = this.state.helpArticles || [];\n\t\tconst searchQuery = (this.state.helpSearchQuery || '').toLowerCase();\n\n\t\t// Filter collections by search\n\t\tconst filteredCollections = searchQuery\n\t\t\t? collections.filter(\n\t\t\t\t\t(c) =>\n\t\t\t\t\t\tc.title.toLowerCase().includes(searchQuery) ||\n\t\t\t\t\t\t(c.description && c.description.toLowerCase().includes(searchQuery))\n\t\t\t\t)\n\t\t\t: collections;\n\n\t\t// Update collection count\n\t\tconst headerEl = this.element.querySelector(\n\t\t\t'.messenger-help-collections-header'\n\t\t);\n\t\tif (headerEl) {\n\t\t\theaderEl.textContent = `${filteredCollections.length} collections`;\n\t\t}\n\n\t\tif (filteredCollections.length === 0) {\n\t\t\tcollectionsContainer.innerHTML = this._renderEmptyState();\n\t\t\treturn;\n\t\t}\n\n\t\tcollectionsContainer.innerHTML = filteredCollections\n\t\t\t.map((collection) => this._renderCollectionItem(collection))\n\t\t\t.join('');\n\n\t\t// Attach click events\n\t\tthis._attachCollectionEvents();\n\t}\n\n\t_renderCollectionItem(collection) {\n\t\tconst articleCount = collection.articleCount || 0;\n\t\treturn `\n\t\t\t<div class=\"messenger-help-collection\" data-collection-id=\"${collection.id}\">\n\t\t\t\t<div class=\"messenger-help-collection-content\">\n\t\t\t\t\t<h3 class=\"messenger-help-collection-title\">${collection.title}</h3>\n\t\t\t\t\t<p class=\"messenger-help-collection-desc\">${collection.description || ''}</p>\n\t\t\t\t\t<span class=\"messenger-help-collection-count\">${articleCount} articles</span>\n\t\t\t\t</div>\n\t\t\t\t<i class=\"ph ph-caret-right messenger-help-collection-arrow\" style=\"font-size: 20px;\"></i>\n\t\t\t</div>\n\t\t`;\n\t}\n\n\t_renderEmptyState() {\n\t\tconst isSearching = this.state.helpSearchQuery;\n\n\t\tif (isSearching) {\n\t\t\treturn `\n\t\t\t\t<div class=\"messenger-help-empty\">\n\t\t\t\t\t<div class=\"messenger-help-empty-icon\">\n\t\t\t\t\t\t<i class=\"ph ph-magnifying-glass\" style=\"font-size: 48px;\"></i>\n\t\t\t\t\t</div>\n\t\t\t\t\t<h3>No results found</h3>\n\t\t\t\t\t<p>Try a different search term</p>\n\t\t\t\t</div>\n\t\t\t`;\n\t\t}\n\n\t\treturn `\n\t\t\t<div class=\"messenger-help-empty\">\n\t\t\t\t<div class=\"messenger-help-empty-icon\">\n\t\t\t\t\t<i class=\"ph ph-question\" style=\"font-size: 48px;\"></i>\n\t\t\t\t</div>\n\t\t\t\t<h3>Help collections</h3>\n\t\t\t\t<p>No collections available yet</p>\n\t\t\t</div>\n\t\t`;\n\t}\n\n\t_attachEvents() {\n\t\t// Close button\n\t\tthis.element\n\t\t\t.querySelector('.messenger-close-btn')\n\t\t\t.addEventListener('click', () => {\n\t\t\t\tthis.state.setOpen(false);\n\t\t\t});\n\n\t\t// Search input\n\t\tconst searchInput = this.element.querySelector(\n\t\t\t'.messenger-help-search-input'\n\t\t);\n\t\tlet searchTimeout;\n\t\tsearchInput.addEventListener('input', (e) => {\n\t\t\tclearTimeout(searchTimeout);\n\t\t\tsearchTimeout = setTimeout(() => {\n\t\t\t\tthis.state.setHelpSearchQuery(e.target.value);\n\t\t\t}, 300);\n\t\t});\n\n\t\tthis._attachCollectionEvents();\n\t}\n\n\t_attachCollectionEvents() {\n\t\tthis.element\n\t\t\t.querySelectorAll('.messenger-help-collection')\n\t\t\t.forEach((item) => {\n\t\t\t\titem.addEventListener('click', () => {\n\t\t\t\t\tconst collectionId = item.dataset.collectionId;\n\t\t\t\t\tconst collection = this.state.helpArticles.find(\n\t\t\t\t\t\t(c) => c.id === collectionId\n\t\t\t\t\t);\n\t\t\t\t\tif (collection && collection.url) {\n\t\t\t\t\t\twindow.open(collection.url, '_blank');\n\t\t\t\t\t} else if (this.options.onArticleClick) {\n\t\t\t\t\t\tthis.options.onArticleClick(collection);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t});\n\t}\n\n\tdestroy() {\n\t\tif (this._unsubscribe) {\n\t\t\tthis._unsubscribe();\n\t\t}\n\t\tif (this.element && this.element.parentNode) {\n\t\t\tthis.element.parentNode.removeChild(this.element);\n\t\t}\n\t}\n}\n","/**\n * HomeView - Welcome screen with team info and quick actions\n */\nexport class HomeView {\n\tconstructor(state, options = {}) {\n\t\tthis.state = state;\n\t\tthis.options = options;\n\t\tthis.element = null;\n\t\tthis._unsubscribe = null;\n\t}\n\n\trender() {\n\t\tthis.element = document.createElement('div');\n\t\tthis.element.className = 'messenger-view messenger-home-view';\n\n\t\tthis._updateContent();\n\n\t\t// Subscribe to state changes to re-render when data loads\n\t\tthis._unsubscribe = this.state.subscribe((type) => {\n\t\t\tif (\n\t\t\t\ttype === 'homeChangelogUpdate' ||\n\t\t\t\ttype === 'conversationsUpdate' ||\n\t\t\t\ttype === 'availabilityUpdate'\n\t\t\t) {\n\t\t\t\tthis._updateContent();\n\t\t\t}\n\t\t});\n\n\t\treturn this.element;\n\t}\n\n\t_updateContent() {\n\t\tconst avatarsHtml = this._renderAvatarStack();\n\t\tconst recentChangelogHtml = this._renderRecentChangelog();\n\n\t\tthis.element.innerHTML = `\n\t\t\t<div class=\"messenger-home-header\">\n\t\t\t\t<div class=\"messenger-home-header-top\">\n\t\t\t\t\t<div class=\"messenger-home-logo\">\n\t\t\t\t\t\t${this.options.logoUrl ? `<img src=\"${this.options.logoUrl}\" alt=\"${this.state.teamName}\" />` : ''}\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"messenger-home-avatars\">${avatarsHtml}</div>\n\t\t\t\t\t<button class=\"messenger-close-btn\" aria-label=\"Close\">\n\t\t\t\t\t\t<i class=\"ph ph-x\" style=\"font-size: 20px;\"></i>\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"messenger-home-welcome\">\n\t\t\t\t\t<span class=\"messenger-home-greeting\">Hello there.</span>\n\t\t\t\t\t<span class=\"messenger-home-question\">${this.state.welcomeMessage}</span>\n\t\t\t\t\t${this._renderAvailabilityStatus()}\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t<div class=\"messenger-home-body\">\n\t\t\t\t<button class=\"messenger-home-message-btn\">\n\t\t\t\t\t<span>Send us a message</span>\n\t\t\t\t\t<i class=\"ph ph-arrow-right\" style=\"font-size: 16px;\"></i>\n\t\t\t\t</button>\n\n\t\t\t\t${this._renderFeaturedCard()}\n\n\t\t\t\t${recentChangelogHtml}\n\t\t\t</div>\n\t\t`;\n\n\t\tthis._attachEvents();\n\t}\n\n\t_renderAvatarStack() {\n\t\tconst avatars = this.state.teamAvatars;\n\t\tif (!avatars || avatars.length === 0) {\n\t\t\t// Default avatars with initials\n\t\t\treturn `\n\t\t\t\t<div class=\"messenger-avatar-stack\">\n\t\t\t\t\t<div class=\"messenger-avatar\" style=\"background: #5856d6;\">S</div>\n\t\t\t\t\t<div class=\"messenger-avatar\" style=\"background: #007aff;\">T</div>\n\t\t\t\t</div>\n\t\t\t`;\n\t\t}\n\n\t\tconst avatarItems = avatars\n\t\t\t.slice(0, 3)\n\t\t\t.map((avatar, i) => {\n\t\t\t\tif (typeof avatar === 'string' && avatar.startsWith('http')) {\n\t\t\t\t\treturn `<img class=\"messenger-avatar\" src=\"${avatar}\" alt=\"Team member\" style=\"z-index: ${3 - i};\" />`;\n\t\t\t\t}\n\t\t\t\treturn `<div class=\"messenger-avatar\" style=\"background: ${this._getAvatarColor(i)}; z-index: ${3 - i};\">${avatar.charAt(0).toUpperCase()}</div>`;\n\t\t\t})\n\t\t\t.join('');\n\n\t\treturn `<div class=\"messenger-avatar-stack\">${avatarItems}</div>`;\n\t}\n\n\t_getAvatarColor(index) {\n\t\tconst colors = ['#5856d6', '#007aff', '#34c759', '#ff9500', '#ff3b30'];\n\t\treturn colors[index % colors.length];\n\t}\n\n\t_renderAvailabilityStatus() {\n\t\tconst isOnline = this.state.agentsOnline;\n\t\tconst responseTime =\n\t\t\tthis.state.responseTime || 'We typically reply within a few minutes';\n\n\t\tif (isOnline) {\n\t\t\treturn `\n\t\t\t\t<div class=\"messenger-home-availability\">\n\t\t\t\t\t<span class=\"messenger-availability-dot messenger-availability-online\"></span>\n\t\t\t\t\t<span class=\"messenger-availability-text\">We're online now</span>\n\t\t\t\t</div>\n\t\t\t`;\n\t\t}\n\n\t\treturn `\n\t\t\t<div class=\"messenger-home-availability\">\n\t\t\t\t<span class=\"messenger-availability-dot messenger-availability-away\"></span>\n\t\t\t\t<span class=\"messenger-availability-text\">${responseTime}</span>\n\t\t\t</div>\n\t\t`;\n\t}\n\n\t_renderFeaturedCard() {\n\t\t// Only show if there's featured content configured\n\t\tif (!this.options.featuredContent) {\n\t\t\treturn '';\n\t\t}\n\n\t\tconst { title, description, imageUrl, action } =\n\t\t\tthis.options.featuredContent;\n\n\t\treturn `\n\t\t\t<div class=\"messenger-home-featured\">\n\t\t\t\t${imageUrl ? `<img src=\"${imageUrl}\" alt=\"${title}\" class=\"messenger-home-featured-image\" onerror=\"this.style.display='none';\" />` : ''}\n\t\t\t\t<div class=\"messenger-home-featured-content\">\n\t\t\t\t\t<h3>${title}</h3>\n\t\t\t\t\t<p>${description}</p>\n\t\t\t\t</div>\n\t\t\t\t${action ? `<button class=\"messenger-home-featured-btn\" data-action=\"${action.type}\" data-value=\"${action.value}\">${action.label}</button>` : ''}\n\t\t\t</div>\n\t\t`;\n\t}\n\n\t_renderRecentChangelog() {\n\t\t// Show recent changelog preview as cards with images\n\t\tconst changelogItems = this.state.homeChangelogItems;\n\t\tif (changelogItems.length === 0) {\n\t\t\treturn '';\n\t\t}\n\n\t\tconst changelogHtml = changelogItems\n\t\t\t.map(\n\t\t\t\t(item) => `\n\t\t\t<div class=\"messenger-home-changelog-card\" data-changelog-id=\"${item.id}\">\n\t\t\t\t${\n\t\t\t\t\titem.coverImage\n\t\t\t\t\t\t? `\n\t\t\t\t\t<div class=\"messenger-home-changelog-cover\">\n\t\t\t\t\t\t<img src=\"${item.coverImage}\" alt=\"${item.title}\" onerror=\"this.style.display='none';\" />\n\t\t\t\t\t\t${item.coverText ? `<span class=\"messenger-home-changelog-cover-text\">${item.coverText}</span>` : ''}\n\t\t\t\t\t</div>\n\t\t\t\t`\n\t\t\t\t\t\t: ''\n\t\t\t\t}\n\t\t\t\t<div class=\"messenger-home-changelog-card-content\">\n\t\t\t\t\t<h4 class=\"messenger-home-changelog-card-title\">${item.title}</h4>\n\t\t\t\t\t<p class=\"messenger-home-changelog-card-desc\">${item.description || ''}</p>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t`\n\t\t\t)\n\t\t\t.join('');\n\n\t\treturn `\n\t\t\t<div class=\"messenger-home-changelog-section\">\n\t\t\t\t${changelogHtml}\n\t\t\t</div>\n\t\t`;\n\t}\n\n\t_formatDate(dateString) {\n\t\tif (!dateString) return '';\n\t\tconst date = new Date(dateString);\n\t\tconst now = new Date();\n\t\tconst diffDays = Math.floor((now - date) / (1000 * 60 * 60 * 24));\n\n\t\tif (diffDays === 0) return 'Today';\n\t\tif (diffDays === 1) return 'Yesterday';\n\t\tif (diffDays < 7) return `${diffDays}d ago`;\n\t\treturn date.toLocaleDateString('en-US', { month: 'short', day: 'numeric' });\n\t}\n\n\t_attachEvents() {\n\t\t// Close button\n\t\tthis.element\n\t\t\t.querySelector('.messenger-close-btn')\n\t\t\t.addEventListener('click', () => {\n\t\t\t\tthis.state.setOpen(false);\n\t\t\t});\n\n\t\t// Send message button\n\t\tthis.element\n\t\t\t.querySelector('.messenger-home-message-btn')\n\t\t\t.addEventListener('click', () => {\n\t\t\t\tthis.state.setView('messages');\n\t\t\t});\n\n\t\t// Changelog items\n\t\tthis.element\n\t\t\t.querySelectorAll('.messenger-home-changelog-item')\n\t\t\t.forEach((item) => {\n\t\t\t\titem.addEventListener('click', () => {\n\t\t\t\t\t// Navigate to changelog view with specific item selected\n\t\t\t\t\tthis.state.setView('changelog');\n\t\t\t\t});\n\t\t\t});\n\n\t\t// See all changelog\n\t\tconst seeAllBtn = this.element.querySelector(\n\t\t\t'.messenger-home-changelog-all'\n\t\t);\n\t\tif (seeAllBtn) {\n\t\t\tseeAllBtn.addEventListener('click', () => {\n\t\t\t\tthis.state.setView('changelog');\n\t\t\t});\n\t\t}\n\n\t\t// Featured card action\n\t\tconst featuredBtn = this.element.querySelector(\n\t\t\t'.messenger-home-featured-btn'\n\t\t);\n\t\tif (featuredBtn) {\n\t\t\tfeaturedBtn.addEventListener('click', () => {\n\t\t\t\tconst action = featuredBtn.dataset.action;\n\t\t\t\tconst value = featuredBtn.dataset.value;\n\t\t\t\tif (action === 'url') {\n\t\t\t\t\twindow.open(value, '_blank');\n\t\t\t\t} else if (action === 'view') {\n\t\t\t\t\tthis.state.setView(value);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\n\tdestroy() {\n\t\tif (this._unsubscribe) {\n\t\t\tthis._unsubscribe();\n\t\t}\n\t\tif (this.element && this.element.parentNode) {\n\t\t\tthis.element.parentNode.removeChild(this.element);\n\t\t}\n\t}\n}\n","/**\n * MessengerWidget - Full-featured Messenger/Chat widget\n */\nimport { WebSocketService } from '../core/WebSocketService.js';\nimport { BaseWidget } from './BaseWidget.js';\nimport { MessengerState } from './messenger/MessengerState.js';\nimport { MessengerLauncher } from './messenger/components/MessengerLauncher.js';\nimport { MessengerPanel } from './messenger/components/MessengerPanel.js';\nimport { ChangelogView } from './messenger/views/ChangelogView.js';\nimport { ChatView } from './messenger/views/ChatView.js';\nimport { ConversationsView } from './messenger/views/ConversationsView.js';\nimport { HelpView } from './messenger/views/HelpView.js';\nimport { HomeView } from './messenger/views/HomeView.js';\n\nexport class MessengerWidget extends BaseWidget {\n\tconstructor(options) {\n\t\tsuper({ ...options, type: 'messenger' });\n\n\t\tthis.messengerOptions = {\n\t\t\tposition: options.position || 'bottom-right',\n\t\t\ttheme: options.theme || 'light',\n\t\t\tteamName: options.teamName || 'Support',\n\t\t\tteamAvatars: options.teamAvatars || [],\n\t\t\twelcomeMessage: options.welcomeMessage || 'How can we help?',\n\t\t\tenableHelp: options.enableHelp !== false,\n\t\t\tenableChangelog: options.enableChangelog !== false,\n\t\t\tlogoUrl: options.logoUrl || 'https://feedback-sdk.product7.io/p7.png',\n\t\t\tfeaturedContent: options.featuredContent || null,\n\t\t\tprimaryColor: options.primaryColor || '#1c1c1e',\n\t\t\t// Callbacks\n\t\t\tonSendMessage: options.onSendMessage || null,\n\t\t\tonArticleClick: options.onArticleClick || null,\n\t\t\tonChangelogClick: options.onChangelogClick || null,\n\t\t};\n\n\t\t// Create state\n\t\tthis.messengerState = new MessengerState({\n\t\t\tteamName: this.messengerOptions.teamName,\n\t\t\tteamAvatars: this.messengerOptions.teamAvatars,\n\t\t\twelcomeMessage: this.messengerOptions.welcomeMessage,\n\t\t\tenableHelp: this.messengerOptions.enableHelp,\n\t\t\tenableChangelog: this.messengerOptions.enableChangelog,\n\t\t\tuserContext: this.sdk?.apiService?.getUserContext() || null,\n\t\t});\n\n\t\tthis.launcher = null;\n\t\tthis.panel = null;\n\t\tthis.wsService = null;\n\t\tthis._wsUnsubscribers = [];\n\n\t\t// Bind methods\n\t\tthis._handleOpenChange = this._handleOpenChange.bind(this);\n\t\tthis._handleWebSocketMessage = this._handleWebSocketMessage.bind(this);\n\t\tthis._handleTypingStarted = this._handleTypingStarted.bind(this);\n\t\tthis._handleTypingStopped = this._handleTypingStopped.bind(this);\n\t}\n\n\t_render() {\n\t\t// Create container\n\t\tconst container = document.createElement('div');\n\t\tcontainer.className = `messenger-widget theme-${this.messengerOptions.theme}`;\n\t\tcontainer.style.zIndex = '999999';\n\n\t\t// Create launcher\n\t\tthis.launcher = new MessengerLauncher(this.messengerState, {\n\t\t\tposition: this.messengerOptions.position,\n\t\t\tprimaryColor: this.messengerOptions.primaryColor,\n\t\t});\n\t\tcontainer.appendChild(this.launcher.render());\n\n\t\t// Create panel with all callbacks\n\t\tthis.panel = new MessengerPanel(this.messengerState, {\n\t\t\tposition: this.messengerOptions.position,\n\t\t\ttheme: this.messengerOptions.theme,\n\t\t\tprimaryColor: this.messengerOptions.primaryColor,\n\t\t\tlogoUrl: this.messengerOptions.logoUrl,\n\t\t\tfeaturedContent: this.messengerOptions.featuredContent,\n\t\t\t// Chat callbacks\n\t\t\tonSendMessage:\n\t\t\t\tthis.messengerOptions.onSendMessage ||\n\t\t\t\tthis._handleSendMessage.bind(this),\n\t\t\tonStartConversation: this._handleStartConversation.bind(this),\n\t\t\tonTyping: this.sendTypingIndicator.bind(this),\n\t\t\t// Conversation list callbacks\n\t\t\tonSelectConversation: this._handleSelectConversation.bind(this),\n\t\t\tonStartNewConversation: this._handleNewConversationClick.bind(this),\n\t\t\t// Article/changelog callbacks\n\t\t\tonArticleClick: this.messengerOptions.onArticleClick,\n\t\t\tonChangelogClick: this.messengerOptions.onChangelogClick,\n\t\t});\n\n\t\t// Register views\n\t\tthis.panel.registerView('home', HomeView);\n\t\tthis.panel.registerView('messages', ConversationsView);\n\t\tthis.panel.registerView('chat', ChatView);\n\t\tthis.panel.registerView('help', HelpView);\n\t\tthis.panel.registerView('changelog', ChangelogView);\n\n\t\tcontainer.appendChild(this.panel.render());\n\t\tthis.panel.hide();\n\n\t\treturn container;\n\t}\n\n\t_attachEvents() {\n\t\t// Subscribe to state changes\n\t\tthis._stateUnsubscribe = this.messengerState.subscribe((type, data) => {\n\t\t\tif (type === 'openChange') {\n\t\t\t\tthis._handleOpenChange(data.isOpen);\n\t\t\t}\n\t\t});\n\t}\n\n\t_handleOpenChange(isOpen) {\n\t\tif (isOpen) {\n\t\t\tthis.panel.show();\n\t\t\tthis.sdk.eventBus.emit('messenger:opened', { widget: this });\n\t\t} else {\n\t\t\tthis.panel.hide();\n\t\t\tthis.messengerState.reset();\n\t\t\tthis.sdk.eventBus.emit('messenger:closed', { widget: this });\n\t\t}\n\t}\n\n\t/**\n\t * Handle starting a new conversation\n\t */\n\tasync _handleStartConversation(messageContent) {\n\t\ttry {\n\t\t\tawait this.startNewConversation(messageContent);\n\t\t} catch (error) {\n\t\t\tconsole.error('[MessengerWidget] Failed to start conversation:', error);\n\t\t}\n\t}\n\n\t/**\n\t * Handle selecting a conversation from the list\n\t */\n\tasync _handleSelectConversation(conversationId) {\n\t\ttry {\n\t\t\tawait this.fetchMessages(conversationId);\n\t\t} catch (error) {\n\t\t\tconsole.error('[MessengerWidget] Failed to fetch messages:', error);\n\t\t}\n\t}\n\n\t/**\n\t * Handle clicking \"new conversation\" button\n\t */\n\t_handleNewConversationClick() {\n\t\t// View is already changed by ConversationsView\n\t\t// This is for any additional setup needed\n\t}\n\n\tasync _handleSendMessage(conversationId, message) {\n\t\t// Emit event for external listeners\n\t\tthis.sdk.eventBus.emit('messenger:messageSent', {\n\t\t\twidget: this,\n\t\t\tconversationId,\n\t\t\tmessage,\n\t\t});\n\n\t\ttry {\n\t\t\t// Send message through API\n\t\t\tconst response = await this.apiService.sendMessage(conversationId, {\n\t\t\t\tcontent: message.content,\n\t\t\t});\n\n\t\t\tif (response.status && response.data) {\n\t\t\t\t// Update the message ID with server-assigned ID\n\t\t\t\t// Message is already added to state optimistically in ChatView\n\t\t\t\tconsole.log('[MessengerWidget] Message sent:', response.data.id);\n\t\t\t}\n\n\t\t\t// In mock mode, simulate an agent response after a delay\n\t\t\tif (this.apiService?.mock) {\n\t\t\t\tsetTimeout(() => {\n\t\t\t\t\tconst mockResponse = {\n\t\t\t\t\t\tid: 'msg_' + Date.now(),\n\t\t\t\t\t\tcontent: \"Thanks for your message! We'll get back to you soon.\",\n\t\t\t\t\t\tisOwn: false,\n\t\t\t\t\t\ttimestamp: new Date().toISOString(),\n\t\t\t\t\t\tsender: {\n\t\t\t\t\t\t\tname: 'Support Team',\n\t\t\t\t\t\t\tavatarUrl: null,\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\t\t\t\t\tthis.messengerState.addMessage(conversationId, mockResponse);\n\t\t\t\t}, 1500);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconsole.error('[MessengerWidget] Failed to send message:', error);\n\t\t\t// Could add error handling UI here\n\t\t}\n\t}\n\n\t/**\n\t * Handle incoming WebSocket message\n\t */\n\t_handleWebSocketMessage(data) {\n\t\tconst { conversation_id, message } = data;\n\n\t\t// Transform message to local format\n\t\tconst localMessage = {\n\t\t\tid: message.id,\n\t\t\tcontent: message.content,\n\t\t\tisOwn: message.sender_type === 'customer',\n\t\t\ttimestamp: message.created_at,\n\t\t\tsender: {\n\t\t\t\tname: message.sender_name || 'Support',\n\t\t\t\tavatarUrl: message.sender_avatar || null,\n\t\t\t},\n\t\t};\n\n\t\t// Add message to state\n\t\tthis.messengerState.addMessage(conversation_id, localMessage);\n\n\t\t// Update unread count if panel is closed or viewing different conversation\n\t\tif (\n\t\t\t!this.messengerState.isOpen ||\n\t\t\tthis.messengerState.activeConversationId !== conversation_id\n\t\t) {\n\t\t\tthis._updateUnreadCount();\n\t\t}\n\t}\n\n\t/**\n\t * Handle typing started event\n\t */\n\t_handleTypingStarted(data) {\n\t\tif (data.is_agent) {\n\t\t\tthis.messengerState._notify('typingStarted', {\n\t\t\t\tconversationId: data.conversation_id,\n\t\t\t\tuserName: data.user_name,\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Handle typing stopped event\n\t */\n\t_handleTypingStopped(data) {\n\t\tthis.messengerState._notify('typingStopped', {\n\t\t\tconversationId: data.conversation_id,\n\t\t});\n\t}\n\n\t/**\n\t * Update unread count from API\n\t */\n\tasync _updateUnreadCount() {\n\t\ttry {\n\t\t\tconst response = await this.apiService.getUnreadCount();\n\t\t\tif (response.status && response.data) {\n\t\t\t\tthis.messengerState.unreadCount = response.data.unread_count || 0;\n\t\t\t\tthis.messengerState._notify('unreadCountChange', {\n\t\t\t\t\tcount: this.messengerState.unreadCount,\n\t\t\t\t});\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconsole.error('[MessengerWidget] Failed to get unread count:', error);\n\t\t}\n\t}\n\n\t/**\n\t * Initialize WebSocket connection\n\t */\n\t_initWebSocket() {\n\t\tif (this.wsService) {\n\t\t\tthis.wsService.disconnect();\n\t\t}\n\n\t\tthis.wsService = new WebSocketService({\n\t\t\tbaseURL: this.apiService.baseURL,\n\t\t\tworkspace: this.apiService.workspace,\n\t\t\tsessionToken: this.apiService.sessionToken,\n\t\t\tmock: this.apiService.mock,\n\t\t});\n\n\t\t// Subscribe to WebSocket events\n\t\tthis._wsUnsubscribers.push(\n\t\t\tthis.wsService.on('message', this._handleWebSocketMessage)\n\t\t);\n\t\tthis._wsUnsubscribers.push(\n\t\t\tthis.wsService.on('typing_started', this._handleTypingStarted)\n\t\t);\n\t\tthis._wsUnsubscribers.push(\n\t\t\tthis.wsService.on('typing_stopped', this._handleTypingStopped)\n\t\t);\n\t\tthis._wsUnsubscribers.push(\n\t\t\tthis.wsService.on('connected', () => {\n\t\t\t\tconsole.log('[MessengerWidget] WebSocket connected');\n\t\t\t})\n\t\t);\n\t\tthis._wsUnsubscribers.push(\n\t\t\tthis.wsService.on('disconnected', () => {\n\t\t\t\tconsole.log('[MessengerWidget] WebSocket disconnected');\n\t\t\t})\n\t\t);\n\n\t\t// Connect\n\t\tthis.wsService.connect();\n\t}\n\n\t/**\n\t * Open the messenger panel\n\t */\n\topen() {\n\t\tthis.messengerState.setOpen(true);\n\t}\n\n\t/**\n\t * Close the messenger panel\n\t */\n\tclose() {\n\t\tthis.messengerState.setOpen(false);\n\t}\n\n\t/**\n\t * Toggle the messenger panel\n\t */\n\ttoggle() {\n\t\tthis.messengerState.setOpen(!this.messengerState.isOpen);\n\t}\n\n\t/**\n\t * Navigate to a specific view\n\t */\n\tnavigateTo(view) {\n\t\tthis.messengerState.setView(view);\n\t\tif (!this.messengerState.isOpen) {\n\t\t\tthis.open();\n\t\t}\n\t}\n\n\t/**\n\t * Set conversations\n\t */\n\tsetConversations(conversations) {\n\t\tthis.messengerState.setConversations(conversations);\n\t}\n\n\t/**\n\t * Add a message to a conversation\n\t */\n\taddMessage(conversationId, message) {\n\t\tthis.messengerState.addMessage(conversationId, message);\n\t}\n\n\t/**\n\t * Set help articles\n\t */\n\tsetHelpArticles(articles) {\n\t\tthis.messengerState.setHelpArticles(articles);\n\t}\n\n\t/**\n\t * Set home changelog items\n\t */\n\tsetHomeChangelogItems(items) {\n\t\tthis.messengerState.setHomeChangelogItems(items);\n\t}\n\n\t/**\n\t * Set changelog items\n\t */\n\tsetChangelogItems(items) {\n\t\tthis.messengerState.setChangelogItems(items);\n\t}\n\n\t/**\n\t * Update unread count (for external updates)\n\t */\n\tsetUnreadCount(count) {\n\t\tthis.messengerState.unreadCount = count;\n\t\tthis.messengerState._notify('unreadCountChange', { count });\n\t}\n\n\t/**\n\t * Get current state\n\t */\n\tgetState() {\n\t\treturn {\n\t\t\tisOpen: this.messengerState.isOpen,\n\t\t\tcurrentView: this.messengerState.currentView,\n\t\t\tunreadCount: this.messengerState.unreadCount,\n\t\t\tconversations: this.messengerState.conversations,\n\t\t};\n\t}\n\n\t/**\n\t * Load initial data (mock or API)\n\t */\n\tasync loadInitialData() {\n\t\t// Load conversations\n\t\ttry {\n\t\t\tconst conversations = await this._fetchConversations();\n\t\t\tthis.messengerState.setConversations(conversations);\n\t\t} catch (error) {\n\t\t\tconsole.error('[MessengerWidget] Failed to load conversations:', error);\n\t\t}\n\n\t\t// Load help articles if enabled\n\t\tif (this.messengerOptions.enableHelp) {\n\t\t\ttry {\n\t\t\t\tconst articles = await this._fetchHelpArticles();\n\t\t\t\tthis.messengerState.setHelpArticles(articles);\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error('[MessengerWidget] Failed to load help articles:', error);\n\t\t\t}\n\t\t}\n\n\t\t// Load changelog if enabled\n\t\tif (this.messengerOptions.enableChangelog) {\n\t\t\ttry {\n\t\t\t\tconst { homeItems, changelogItems } = await this._fetchChangelog();\n\t\t\t\tthis.messengerState.setHomeChangelogItems(homeItems);\n\t\t\t\tthis.messengerState.setChangelogItems(changelogItems);\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error('[MessengerWidget] Failed to load changelog:', error);\n\t\t\t}\n\t\t}\n\t}\n\n\tasync _fetchConversations() {\n\t\ttry {\n\t\t\tconst response = await this.apiService.getConversations();\n\t\t\tif (response.status && response.data) {\n\t\t\t\t// Transform API response to local format\n\t\t\t\treturn response.data.map((conv) => ({\n\t\t\t\t\tid: conv.id,\n\t\t\t\t\ttitle:\n\t\t\t\t\t\tconv.subject ||\n\t\t\t\t\t\t`Chat with ${conv.assigned_user?.name || 'Support'}`,\n\t\t\t\t\tparticipants: conv.assigned_user\n\t\t\t\t\t\t? [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tname: conv.assigned_user.name,\n\t\t\t\t\t\t\t\t\tavatarUrl: conv.assigned_user.avatar,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t: [{ name: 'Support', avatarUrl: null }],\n\t\t\t\t\tlastMessage: conv.preview || conv.snippet || '',\n\t\t\t\t\tlastMessageTime: conv.last_message_at,\n\t\t\t\t\tunread: conv.unread || 0,\n\t\t\t\t\tstatus: conv.status,\n\t\t\t\t}));\n\t\t\t}\n\t\t\treturn [];\n\t\t} catch (error) {\n\t\t\tconsole.error('[MessengerWidget] Failed to fetch conversations:', error);\n\t\t\treturn [];\n\t\t}\n\t}\n\n\tasync _fetchHelpArticles() {\n\t\ttry {\n\t\t\tconst response = await this.apiService.getHelpCollections();\n\t\t\tif (response.status && response.data) {\n\t\t\t\t// Transform API response to local format\n\t\t\t\treturn response.data.map((collection) => ({\n\t\t\t\t\tid: collection.id,\n\t\t\t\t\ttitle: collection.title || collection.name,\n\t\t\t\t\tdescription: collection.description || '',\n\t\t\t\t\tarticleCount:\n\t\t\t\t\t\tcollection.article_count || collection.articleCount || 0,\n\t\t\t\t\ticon: collection.icon || 'ph-book-open',\n\t\t\t\t\turl: collection.url || `#/help/${collection.slug || collection.id}`,\n\t\t\t\t}));\n\t\t\t}\n\t\t\treturn [];\n\t\t} catch (error) {\n\t\t\tconsole.error('[MessengerWidget] Failed to fetch help articles:', error);\n\t\t\treturn [];\n\t\t}\n\t}\n\n\t/**\n\t * Fetch messages for a conversation\n\t */\n\tasync fetchMessages(conversationId) {\n\t\ttry {\n\t\t\tconst response = await this.apiService.getConversation(conversationId);\n\t\t\tif (response.status && response.data) {\n\t\t\t\tconst messages = (response.data.messages || []).map((msg) => ({\n\t\t\t\t\tid: msg.id,\n\t\t\t\t\tcontent: msg.content,\n\t\t\t\t\tisOwn: msg.sender_type === 'customer',\n\t\t\t\t\ttimestamp: msg.created_at,\n\t\t\t\t\tsender: {\n\t\t\t\t\t\tname:\n\t\t\t\t\t\t\tmsg.sender_name ||\n\t\t\t\t\t\t\t(msg.sender_type === 'customer' ? 'You' : 'Support'),\n\t\t\t\t\t\tavatarUrl: msg.sender_avatar || null,\n\t\t\t\t\t},\n\t\t\t\t}));\n\t\t\t\tthis.messengerState.setMessages(conversationId, messages);\n\n\t\t\t\t// Mark as read\n\t\t\t\tawait this.apiService.markConversationAsRead(conversationId);\n\t\t\t\tthis.messengerState.markAsRead(conversationId);\n\n\t\t\t\treturn messages;\n\t\t\t}\n\t\t\treturn [];\n\t\t} catch (error) {\n\t\t\tconsole.error('[MessengerWidget] Failed to fetch messages:', error);\n\t\t\treturn [];\n\t\t}\n\t}\n\n\t/**\n\t * Start a new conversation\n\t */\n\tasync startNewConversation(message, subject = '') {\n\t\ttry {\n\t\t\tconst response = await this.apiService.startConversation({\n\t\t\t\tmessage,\n\t\t\t\tsubject,\n\t\t\t});\n\n\t\t\tif (response.status && response.data) {\n\t\t\t\tconst conv = response.data;\n\t\t\t\tconst newConversation = {\n\t\t\t\t\tid: conv.id,\n\t\t\t\t\ttitle: conv.subject || 'New conversation',\n\t\t\t\t\tparticipants: [{ name: 'Support', avatarUrl: null }],\n\t\t\t\t\tlastMessage: message,\n\t\t\t\t\tlastMessageTime: conv.created_at || new Date().toISOString(),\n\t\t\t\t\tunread: 0,\n\t\t\t\t\tstatus: 'open',\n\t\t\t\t};\n\n\t\t\t\t// Add to state\n\t\t\t\tthis.messengerState.addConversation(newConversation);\n\n\t\t\t\t// Set initial message in messages cache\n\t\t\t\tthis.messengerState.setMessages(conv.id, [\n\t\t\t\t\t{\n\t\t\t\t\t\tid: 'msg_' + Date.now(),\n\t\t\t\t\t\tcontent: message,\n\t\t\t\t\t\tisOwn: true,\n\t\t\t\t\t\ttimestamp: new Date().toISOString(),\n\t\t\t\t\t},\n\t\t\t\t]);\n\n\t\t\t\t// Navigate to chat\n\t\t\t\tthis.messengerState.setActiveConversation(conv.id);\n\t\t\t\tthis.messengerState.setView('chat');\n\n\t\t\t\treturn conv;\n\t\t\t}\n\t\t\treturn null;\n\t\t} catch (error) {\n\t\t\tconsole.error('[MessengerWidget] Failed to start conversation:', error);\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Send typing indicator\n\t */\n\tasync sendTypingIndicator(conversationId, isTyping) {\n\t\ttry {\n\t\t\tawait this.apiService.sendTypingIndicator(conversationId, isTyping);\n\t\t} catch (error) {\n\t\t\t// Silently fail - typing indicators are not critical\n\t\t}\n\t}\n\n\t/**\n\t * Check agent availability\n\t */\n\tasync checkAgentAvailability() {\n\t\ttry {\n\t\t\tconst response = await this.apiService.checkAgentsOnline();\n\t\t\tif (response.status && response.data) {\n\t\t\t\tthis.messengerState.agentsOnline = response.data.agents_online;\n\t\t\t\tthis.messengerState.onlineCount = response.data.online_count || 0;\n\t\t\t\tthis.messengerState.responseTime = response.data.response_time || '';\n\t\t\t\tthis.messengerState._notify('availabilityUpdate', response.data);\n\t\t\t\treturn response.data;\n\t\t\t}\n\t\t\treturn { agents_online: false, online_count: 0 };\n\t\t} catch (error) {\n\t\t\tconsole.error('[MessengerWidget] Failed to check availability:', error);\n\t\t\treturn { agents_online: false, online_count: 0 };\n\t\t}\n\t}\n\n\tasync _fetchChangelog() {\n\t\t// Mock data for now - simulating changelog API response\n\t\tif (this.apiService?.mock) {\n\t\t\treturn {\n\t\t\t\thomeItems: [\n\t\t\t\t\t{\n\t\t\t\t\t\tid: 'changelog_5',\n\t\t\t\t\t\ttitle: 'New integrations available',\n\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t'Connect with more tools you love and streamline your workflow.',\n\t\t\t\t\t\ttags: ['Integration'],\n\t\t\t\t\t\tcoverImage: 'https://feedback-sdk.product7.io/700x400__5_.png',\n\t\t\t\t\t\tcoverText: null,\n\t\t\t\t\t\tpublishedAt: new Date(\n\t\t\t\t\t\t\tDate.now() - 14 * 24 * 60 * 60 * 1000\n\t\t\t\t\t\t).toISOString(),\n\t\t\t\t\t\turl: '#',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tid: 'changelog_2',\n\t\t\t\t\t\ttitle: 'A new era of Insights has arrived',\n\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t'We announced Fin Insights, a groundbreaking, AI-powered product that gives you complete visibility into every customer conversation.',\n\t\t\t\t\t\ttags: ['New feature', 'AI'],\n\t\t\t\t\t\tcoverImage:\n\t\t\t\t\t\t\t'https://feedback-sdk.product7.io/Intercom_Messenger__1_.jpg',\n\t\t\t\t\t\tcoverText: 'Watch our major product launch on-demand',\n\t\t\t\t\t\tpublishedAt: new Date(\n\t\t\t\t\t\t\tDate.now() - 5 * 24 * 60 * 60 * 1000\n\t\t\t\t\t\t).toISOString(),\n\t\t\t\t\t\turl: '#',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tid: 'changelog_1',\n\t\t\t\t\t\ttitle: 'The 2025 Customer Service Transformation Report',\n\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t'Learn how AI has transformed customer service from the ground up—rewriting its economics and reshaping expectations.',\n\t\t\t\t\t\ttags: ['Report'],\n\t\t\t\t\t\tcoverImage:\n\t\t\t\t\t\t\t'https://feedback-sdk.product7.io/Main_Report_Email_Header.png',\n\t\t\t\t\t\tcoverText: 'Customer service trends as we know them are dead.',\n\t\t\t\t\t\tpublishedAt: new Date(\n\t\t\t\t\t\t\tDate.now() - 2 * 24 * 60 * 60 * 1000\n\t\t\t\t\t\t).toISOString(),\n\t\t\t\t\t\turl: '#',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tchangelogItems: [\n\t\t\t\t\t{\n\t\t\t\t\t\tid: 'changelog_4',\n\t\t\t\t\t\ttitle: 'Enhanced conversation analytics',\n\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t'Get deeper insights into your customer conversations with our new analytics dashboard.',\n\t\t\t\t\t\ttags: ['Analytics'],\n\t\t\t\t\t\tcoverImage:\n\t\t\t\t\t\t\t'https://feedback-sdk.product7.io/cgangelog-Frame%202087334450.jpg',\n\t\t\t\t\t\tcoverText: null,\n\t\t\t\t\t\tpublishedAt: new Date(\n\t\t\t\t\t\t\tDate.now() - 10 * 24 * 60 * 60 * 1000\n\t\t\t\t\t\t).toISOString(),\n\t\t\t\t\t\turl: '#',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tid: 'changelog_3',\n\t\t\t\t\t\ttitle: 'Escalation guidance for complex issues',\n\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t'New AI-powered escalation guidance helps your team handle complex customer issues more effectively.',\n\t\t\t\t\t\ttags: ['New feature', 'AI'],\n\t\t\t\t\t\tcoverImage:\n\t\t\t\t\t\t\t'https://feedback-sdk.product7.io/cgangelog-image-escalation-guidance-event@2x.png',\n\t\t\t\t\t\tcoverText: null,\n\t\t\t\t\t\tpublishedAt: new Date(\n\t\t\t\t\t\t\tDate.now() - 7 * 24 * 60 * 60 * 1000\n\t\t\t\t\t\t).toISOString(),\n\t\t\t\t\t\turl: '#',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t};\n\t\t}\n\n\t\t// Fetch changelogs from API\n\t\tconst response = await this.apiService.getChangelogs({ limit: 20 });\n\t\tconst changelogs = response.data || [];\n\n\t\t// Map API response to expected format\n\t\tconst mappedItems = changelogs.map((item) => ({\n\t\t\tid: item.id,\n\t\t\ttitle: item.title,\n\t\t\tdescription: item.excerpt || item.description || '',\n\t\t\ttags: item.labels ? item.labels.map((label) => label.name) : [],\n\t\t\tcoverImage: item.cover_image || null,\n\t\t\tcoverText: null,\n\t\t\tpublishedAt: item.published_at,\n\t\t\turl: item.slug ? `/changelog/${item.slug}` : '#',\n\t\t}));\n\n\t\treturn {\n\t\t\thomeItems: mappedItems.slice(0, 3),\n\t\t\tchangelogItems: mappedItems,\n\t\t};\n\t}\n\n\tonMount() {\n\t\t// Load initial data after mounting\n\t\tthis.loadInitialData();\n\n\t\t// Initialize WebSocket for real-time updates\n\t\tif (this.apiService?.sessionToken) {\n\t\t\tthis._initWebSocket();\n\t\t}\n\n\t\t// Check agent availability\n\t\tthis.checkAgentAvailability();\n\n\t\t// Periodically check availability (every 60 seconds)\n\t\tthis._availabilityInterval = setInterval(() => {\n\t\t\tthis.checkAgentAvailability();\n\t\t}, 60000);\n\t}\n\n\tonDestroy() {\n\t\tif (this._stateUnsubscribe) {\n\t\t\tthis._stateUnsubscribe();\n\t\t}\n\n\t\t// Clean up WebSocket\n\t\tif (this.wsService) {\n\t\t\tthis.wsService.disconnect();\n\t\t}\n\n\t\t// Clean up WebSocket event listeners\n\t\tthis._wsUnsubscribers.forEach((unsub) => unsub());\n\t\tthis._wsUnsubscribers = [];\n\n\t\t// Clean up availability interval\n\t\tif (this._availabilityInterval) {\n\t\t\tclearInterval(this._availabilityInterval);\n\t\t}\n\t}\n\n\tdestroy() {\n\t\tif (this.launcher) {\n\t\t\tthis.launcher.destroy();\n\t\t}\n\t\tif (this.panel) {\n\t\t\tthis.panel.destroy();\n\t\t}\n\t\tthis.onDestroy();\n\t\tsuper.destroy();\n\t}\n}\n","import { BaseWidget } from './BaseWidget.js';\n\nexport class SurveyWidget extends BaseWidget {\n\tconstructor(options) {\n\t\tsuper({ ...options, type: 'survey' });\n\n\t\tthis.surveyOptions = {\n\t\t\tsurveyId: options.surveyId || null, // Backend survey ID for API calls\n\t\t\tsurveyType: options.surveyType || 'nps', // 'nps', 'csat', 'ces', 'custom'\n\t\t\tposition: options.position || 'bottom-right', // 'bottom-right', 'bottom-left', 'center', 'bottom'\n\t\t\ttitle: options.title || null,\n\t\t\tdescription: options.description || null,\n\t\t\tlowLabel: options.lowLabel || null,\n\t\t\thighLabel: options.highLabel || null,\n\t\t\tcustomQuestions: options.customQuestions || [],\n\t\t\ttheme: options.theme || 'light',\n\t\t\tonSubmit: options.onSubmit || null,\n\t\t\tonDismiss: options.onDismiss || null,\n\t\t};\n\n\t\tthis.surveyState = {\n\t\t\tscore: null,\n\t\t\tfeedback: '',\n\t\t\tcustomAnswers: {},\n\t\t\tisVisible: false,\n\t\t};\n\t}\n\n\t_render() {\n\t\t// Survey widget doesn't render a trigger button, it's shown programmatically\n\t\tconst container = document.createElement('div');\n\t\tcontainer.className = 'feedback-survey-container';\n\t\tcontainer.style.display = 'none';\n\t\treturn container;\n\t}\n\n\t_attachEvents() {\n\t\t// Events are attached when survey is shown\n\t}\n\n\tshow() {\n\t\tthis._renderSurvey();\n\t\tthis.surveyState.isVisible = true;\n\t\tthis.sdk.eventBus.emit('survey:shown', {\n\t\t\twidget: this,\n\t\t\ttype: this.surveyOptions.surveyType,\n\t\t});\n\t\treturn this;\n\t}\n\n\thide() {\n\t\tthis._closeSurvey();\n\t\treturn this;\n\t}\n\n\t_renderSurvey() {\n\t\t// Remove any existing survey\n\t\tthis._closeSurvey();\n\n\t\tconst config = this._getSurveyConfig();\n\t\tconst positionStyles = this._getPositionStyles();\n\t\tconst themeStyles =\n\t\t\tthis.surveyOptions.theme === 'dark'\n\t\t\t\t? 'background: #1a1a1a; color: #fff;'\n\t\t\t\t: 'background: #fff; color: #1d1d1f;';\n\n\t\t// Create backdrop for center position\n\t\tif (this.surveyOptions.position === 'center') {\n\t\t\tthis.backdropElement = document.createElement('div');\n\t\t\tthis.backdropElement.className = 'feedback-survey-backdrop';\n\t\t\tdocument.body.appendChild(this.backdropElement);\n\t\t\tthis.backdropElement.addEventListener('click', () =>\n\t\t\t\tthis._handleDismiss()\n\t\t\t);\n\t\t}\n\n\t\tthis.surveyElement = document.createElement('div');\n\t\tthis.surveyElement.className = `feedback-survey feedback-survey-${this.surveyOptions.position} theme-${this.surveyOptions.theme}`;\n\t\tthis.surveyElement.style.cssText = `position: fixed; ${positionStyles} z-index: 10000; ${themeStyles} border-radius: 16px; box-shadow: 0 20px 60px rgba(0,0,0,0.3); padding: 24px; min-width: 320px; max-width: 400px; font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;`;\n\n\t\tthis.surveyElement.innerHTML = `\n\t\t\t<button class=\"feedback-survey-close\" style=\"position: absolute; top: 12px; right: 12px; background: none; border: none; font-size: 20px; cursor: pointer; color: ${this.surveyOptions.theme === 'dark' ? '#888' : '#86868b'}; line-height: 1;\">×</button>\n\t\t\t<h3 class=\"feedback-survey-title\" style=\"margin: 0 0 8px 0; font-size: 18px; font-weight: 600; padding-right: 24px;\">${config.title}</h3>\n\t\t\t<p class=\"feedback-survey-description\" style=\"color: ${this.surveyOptions.theme === 'dark' ? '#aaa' : '#86868b'}; margin: 0 0 20px 0; font-size: 14px;\">${config.description}</p>\n\t\t\t<div class=\"feedback-survey-content\">${config.html}</div>\n\t\t\t<div class=\"feedback-survey-feedback\" style=\"margin-top: 16px;\">\n\t\t\t\t<textarea class=\"feedback-survey-textarea\" placeholder=\"Any additional feedback? (optional)\" style=\"width: 100%; padding: 12px; border: 1px solid ${this.surveyOptions.theme === 'dark' ? '#333' : '#d2d2d7'}; border-radius: 8px; font-size: 14px; resize: none; height: 80px; background: ${this.surveyOptions.theme === 'dark' ? '#2a2a2a' : '#fff'}; color: ${this.surveyOptions.theme === 'dark' ? '#fff' : '#1d1d1f'}; font-family: inherit; box-sizing: border-box;\"></textarea>\n\t\t\t</div>\n\t\t\t<button class=\"feedback-survey-submit\" style=\"width: 100%; margin-top: 12px; padding: 12px; background: #007aff; color: white; border: none; border-radius: 8px; font-size: 14px; font-weight: 500; cursor: pointer; font-family: inherit;\">Submit</button>\n\t\t`;\n\n\t\tdocument.body.appendChild(this.surveyElement);\n\t\tthis._attachSurveyEvents();\n\n\t\t// Animate in\n\t\trequestAnimationFrame(() => {\n\t\t\tthis.surveyElement.style.opacity = '1';\n\t\t\tthis.surveyElement.style.transform =\n\t\t\t\tthis.surveyOptions.position === 'center'\n\t\t\t\t\t? 'translate(-50%, -50%) scale(1)'\n\t\t\t\t\t: 'translateY(0)';\n\t\t});\n\t}\n\n\t_getSurveyConfig() {\n\t\tconst configs = {\n\t\t\tnps: {\n\t\t\t\ttitle:\n\t\t\t\t\tthis.surveyOptions.title || 'How likely are you to recommend us?',\n\t\t\t\tdescription:\n\t\t\t\t\tthis.surveyOptions.description ||\n\t\t\t\t\t'On a scale of 0-10, how likely are you to recommend our product to a friend or colleague?',\n\t\t\t\thtml: `\n\t\t\t\t\t<div class=\"feedback-survey-nps\" style=\"display: flex; justify-content: space-between; gap: 4px;\">\n\t\t\t\t\t\t${[...Array(11).keys()]\n\t\t\t\t\t\t\t.map(\n\t\t\t\t\t\t\t\t(n) => `\n\t\t\t\t\t\t\t<button class=\"feedback-survey-nps-btn\" data-score=\"${n}\" style=\"width: 28px; height: 36px; border: 1px solid ${this.surveyOptions.theme === 'dark' ? '#444' : '#d2d2d7'}; border-radius: 6px; background: ${this.surveyOptions.theme === 'dark' ? '#2a2a2a' : '#f8f9fa'}; cursor: pointer; font-size: 12px; color: ${this.surveyOptions.theme === 'dark' ? '#fff' : '#1d1d1f'}; transition: all 0.15s;\">${n}</button>\n\t\t\t\t\t\t`\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t.join('')}\n\t\t\t\t\t</div>\n\t\t\t\t\t<div style=\"display: flex; justify-content: space-between; margin-top: 8px; font-size: 11px; color: ${this.surveyOptions.theme === 'dark' ? '#888' : '#86868b'};\">\n\t\t\t\t\t\t<span>${this.surveyOptions.lowLabel || 'Not likely'}</span>\n\t\t\t\t\t\t<span>${this.surveyOptions.highLabel || 'Very likely'}</span>\n\t\t\t\t\t</div>\n\t\t\t\t`,\n\t\t\t},\n\t\t\tcsat: {\n\t\t\t\ttitle: this.surveyOptions.title || 'How satisfied are you?',\n\t\t\t\tdescription:\n\t\t\t\t\tthis.surveyOptions.description ||\n\t\t\t\t\t'How would you rate your overall satisfaction with our product?',\n\t\t\t\thtml: `\n\t\t\t\t\t<div class=\"feedback-survey-csat\" style=\"display: flex; justify-content: center; gap: 16px;\">\n\t\t\t\t\t\t${['😞', '😕', '😐', '🙂', '😄']\n\t\t\t\t\t\t\t.map(\n\t\t\t\t\t\t\t\t(emoji, i) => `\n\t\t\t\t\t\t\t<button class=\"feedback-survey-csat-btn\" data-score=\"${i + 1}\" style=\"background: none; border: none; cursor: pointer; font-size: 36px; transition: transform 0.15s; padding: 8px;\">${emoji}</button>\n\t\t\t\t\t\t`\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t.join('')}\n\t\t\t\t\t</div>\n\t\t\t\t\t<div style=\"display: flex; justify-content: space-between; margin-top: 8px; font-size: 11px; color: ${this.surveyOptions.theme === 'dark' ? '#888' : '#86868b'};\">\n\t\t\t\t\t\t<span>${this.surveyOptions.lowLabel || 'Very dissatisfied'}</span>\n\t\t\t\t\t\t<span>${this.surveyOptions.highLabel || 'Very satisfied'}</span>\n\t\t\t\t\t</div>\n\t\t\t\t`,\n\t\t\t},\n\t\t\tces: {\n\t\t\t\ttitle: this.surveyOptions.title || 'How easy was it?',\n\t\t\t\tdescription:\n\t\t\t\t\tthis.surveyOptions.description ||\n\t\t\t\t\t'How easy was it to accomplish your task today?',\n\t\t\t\thtml: `\n\t\t\t\t\t<div class=\"feedback-survey-ces\" style=\"display: flex; justify-content: space-between; gap: 8px;\">\n\t\t\t\t\t\t${['Very Difficult', 'Difficult', 'Neutral', 'Easy', 'Very Easy']\n\t\t\t\t\t\t\t.map(\n\t\t\t\t\t\t\t\t(label, i) => `\n\t\t\t\t\t\t\t<button class=\"feedback-survey-ces-btn\" data-score=\"${i + 1}\" style=\"flex: 1; padding: 12px 8px; border: 1px solid ${this.surveyOptions.theme === 'dark' ? '#444' : '#d2d2d7'}; border-radius: 8px; background: ${this.surveyOptions.theme === 'dark' ? '#2a2a2a' : '#f8f9fa'}; cursor: pointer; font-size: 11px; color: ${this.surveyOptions.theme === 'dark' ? '#fff' : '#1d1d1f'}; transition: all 0.15s;\">${label}</button>\n\t\t\t\t\t\t`\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t.join('')}\n\t\t\t\t\t</div>\n\t\t\t\t`,\n\t\t\t},\n\t\t\tcustom: {\n\t\t\t\ttitle: this.surveyOptions.title || 'Quick Feedback',\n\t\t\t\tdescription:\n\t\t\t\t\tthis.surveyOptions.description ||\n\t\t\t\t\t'Help us improve by answering a few questions.',\n\t\t\t\thtml: this._renderCustomQuestions(),\n\t\t\t},\n\t\t};\n\n\t\treturn configs[this.surveyOptions.surveyType] || configs.nps;\n\t}\n\n\t_renderCustomQuestions() {\n\t\tif (\n\t\t\t!this.surveyOptions.customQuestions ||\n\t\t\tthis.surveyOptions.customQuestions.length === 0\n\t\t) {\n\t\t\t// Default custom questions\n\t\t\treturn `\n\t\t\t\t<div style=\"margin-bottom: 16px;\">\n\t\t\t\t\t<label style=\"display: block; margin-bottom: 6px; font-size: 13px; font-weight: 500;\">What feature do you use most?</label>\n\t\t\t\t\t<select class=\"feedback-survey-select\" data-question=\"feature\" style=\"width: 100%; padding: 10px; border: 1px solid ${this.surveyOptions.theme === 'dark' ? '#444' : '#d2d2d7'}; border-radius: 8px; font-size: 14px; background: ${this.surveyOptions.theme === 'dark' ? '#2a2a2a' : '#fff'}; color: ${this.surveyOptions.theme === 'dark' ? '#fff' : '#1d1d1f'};\">\n\t\t\t\t\t\t<option value=\"\">Select a feature</option>\n\t\t\t\t\t\t<option value=\"feedback\">Feedback Collection</option>\n\t\t\t\t\t\t<option value=\"surveys\">Surveys</option>\n\t\t\t\t\t\t<option value=\"analytics\">Analytics</option>\n\t\t\t\t\t\t<option value=\"integrations\">Integrations</option>\n\t\t\t\t\t</select>\n\t\t\t\t</div>\n\t\t\t\t<div>\n\t\t\t\t\t<label style=\"display: block; margin-bottom: 6px; font-size: 13px; font-weight: 500;\">How often do you use it?</label>\n\t\t\t\t\t<div class=\"feedback-survey-frequency\" style=\"display: flex; gap: 8px;\">\n\t\t\t\t\t\t${['Daily', 'Weekly', 'Monthly', 'Rarely']\n\t\t\t\t\t\t\t.map(\n\t\t\t\t\t\t\t\t(freq) => `\n\t\t\t\t\t\t\t<button class=\"feedback-survey-freq-btn\" data-freq=\"${freq}\" style=\"flex: 1; padding: 10px; border: 1px solid ${this.surveyOptions.theme === 'dark' ? '#444' : '#d2d2d7'}; border-radius: 8px; background: ${this.surveyOptions.theme === 'dark' ? '#2a2a2a' : '#f8f9fa'}; cursor: pointer; font-size: 12px; color: ${this.surveyOptions.theme === 'dark' ? '#fff' : '#1d1d1f'}; transition: all 0.15s;\">${freq}</button>\n\t\t\t\t\t\t`\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t.join('')}\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t`;\n\t\t}\n\n\t\treturn this.surveyOptions.customQuestions\n\t\t\t.map(\n\t\t\t\t(q, index) => `\n\t\t\t<div style=\"margin-bottom: 16px;\">\n\t\t\t\t<label style=\"display: block; margin-bottom: 6px; font-size: 13px; font-weight: 500;\">${q.label}</label>\n\t\t\t\t${this._renderQuestionInput(q, index)}\n\t\t\t</div>\n\t\t`\n\t\t\t)\n\t\t\t.join('');\n\t}\n\n\t_renderQuestionInput(question, index) {\n\t\tswitch (question.type) {\n\t\t\tcase 'select':\n\t\t\t\treturn `\n\t\t\t\t\t<select class=\"feedback-survey-select\" data-question=\"${question.id || index}\" style=\"width: 100%; padding: 10px; border: 1px solid ${this.surveyOptions.theme === 'dark' ? '#444' : '#d2d2d7'}; border-radius: 8px; font-size: 14px; background: ${this.surveyOptions.theme === 'dark' ? '#2a2a2a' : '#fff'}; color: ${this.surveyOptions.theme === 'dark' ? '#fff' : '#1d1d1f'};\">\n\t\t\t\t\t\t<option value=\"\">${question.placeholder || 'Select an option'}</option>\n\t\t\t\t\t\t${question.options.map((opt) => `<option value=\"${opt.value}\">${opt.label}</option>`).join('')}\n\t\t\t\t\t</select>\n\t\t\t\t`;\n\t\t\tcase 'text':\n\t\t\t\treturn `\n\t\t\t\t\t<input type=\"text\" class=\"feedback-survey-input\" data-question=\"${question.id || index}\" placeholder=\"${question.placeholder || ''}\" style=\"width: 100%; padding: 10px; border: 1px solid ${this.surveyOptions.theme === 'dark' ? '#444' : '#d2d2d7'}; border-radius: 8px; font-size: 14px; background: ${this.surveyOptions.theme === 'dark' ? '#2a2a2a' : '#fff'}; color: ${this.surveyOptions.theme === 'dark' ? '#fff' : '#1d1d1f'}; box-sizing: border-box;\">\n\t\t\t\t`;\n\t\t\tdefault:\n\t\t\t\treturn '';\n\t\t}\n\t}\n\n\t_getPositionStyles() {\n\t\tconst positions = {\n\t\t\t'bottom-right':\n\t\t\t\t'bottom: 24px; right: 24px; opacity: 0; transform: translateY(20px); transition: all 0.3s ease;',\n\t\t\t'bottom-left':\n\t\t\t\t'bottom: 24px; left: 24px; opacity: 0; transform: translateY(20px); transition: all 0.3s ease;',\n\t\t\tcenter:\n\t\t\t\t'top: 50%; left: 50%; transform: translate(-50%, -50%) scale(0.95); opacity: 0; transition: all 0.3s ease;',\n\t\t\tbottom:\n\t\t\t\t'bottom: 0; left: 0; right: 0; border-radius: 16px 16px 0 0; max-width: none; opacity: 0; transform: translateY(20px); transition: all 0.3s ease;',\n\t\t};\n\t\treturn positions[this.surveyOptions.position] || positions['bottom-right'];\n\t}\n\n\t_attachSurveyEvents() {\n\t\tif (!this.surveyElement) return;\n\n\t\t// Close button\n\t\tconst closeBtn = this.surveyElement.querySelector('.feedback-survey-close');\n\t\tcloseBtn.addEventListener('click', () => this._handleDismiss());\n\n\t\t// Submit button\n\t\tconst submitBtn = this.surveyElement.querySelector(\n\t\t\t'.feedback-survey-submit'\n\t\t);\n\t\tsubmitBtn.addEventListener('click', () => this._handleSubmit());\n\n\t\t// Feedback textarea\n\t\tconst textarea = this.surveyElement.querySelector(\n\t\t\t'.feedback-survey-textarea'\n\t\t);\n\t\ttextarea.addEventListener('input', (e) => {\n\t\t\tthis.surveyState.feedback = e.target.value;\n\t\t});\n\n\t\t// Survey type specific events\n\t\tthis._attachTypeSpecificEvents();\n\n\t\t// Escape key\n\t\tthis._escapeHandler = (e) => {\n\t\t\tif (e.key === 'Escape') {\n\t\t\t\tthis._handleDismiss();\n\t\t\t}\n\t\t};\n\t\tdocument.addEventListener('keydown', this._escapeHandler);\n\t}\n\n\t_attachTypeSpecificEvents() {\n\t\tconst type = this.surveyOptions.surveyType;\n\n\t\tif (type === 'nps') {\n\t\t\tthis.surveyElement\n\t\t\t\t.querySelectorAll('.feedback-survey-nps-btn')\n\t\t\t\t.forEach((btn) => {\n\t\t\t\t\tbtn.addEventListener('click', () =>\n\t\t\t\t\t\tthis._selectNPS(parseInt(btn.dataset.score))\n\t\t\t\t\t);\n\t\t\t\t\tbtn.addEventListener('mouseenter', () => {\n\t\t\t\t\t\tif (this.surveyState.score !== parseInt(btn.dataset.score)) {\n\t\t\t\t\t\t\tbtn.style.borderColor = '#007aff';\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\tbtn.addEventListener('mouseleave', () => {\n\t\t\t\t\t\tif (this.surveyState.score !== parseInt(btn.dataset.score)) {\n\t\t\t\t\t\t\tbtn.style.borderColor =\n\t\t\t\t\t\t\t\tthis.surveyOptions.theme === 'dark' ? '#444' : '#d2d2d7';\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t}\n\n\t\tif (type === 'csat') {\n\t\t\tthis.surveyElement\n\t\t\t\t.querySelectorAll('.feedback-survey-csat-btn')\n\t\t\t\t.forEach((btn) => {\n\t\t\t\t\tbtn.addEventListener('click', () =>\n\t\t\t\t\t\tthis._selectCSAT(parseInt(btn.dataset.score))\n\t\t\t\t\t);\n\t\t\t\t\tbtn.addEventListener('mouseenter', () => {\n\t\t\t\t\t\tbtn.style.transform = 'scale(1.1)';\n\t\t\t\t\t});\n\t\t\t\t\tbtn.addEventListener('mouseleave', () => {\n\t\t\t\t\t\tif (this.surveyState.score !== parseInt(btn.dataset.score)) {\n\t\t\t\t\t\t\tbtn.style.transform = 'scale(1)';\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t}\n\n\t\tif (type === 'ces') {\n\t\t\tthis.surveyElement\n\t\t\t\t.querySelectorAll('.feedback-survey-ces-btn')\n\t\t\t\t.forEach((btn) => {\n\t\t\t\t\tbtn.addEventListener('click', () =>\n\t\t\t\t\t\tthis._selectCES(parseInt(btn.dataset.score))\n\t\t\t\t\t);\n\t\t\t\t\tbtn.addEventListener('mouseenter', () => {\n\t\t\t\t\t\tif (this.surveyState.score !== parseInt(btn.dataset.score)) {\n\t\t\t\t\t\t\tbtn.style.borderColor = '#007aff';\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\tbtn.addEventListener('mouseleave', () => {\n\t\t\t\t\t\tif (this.surveyState.score !== parseInt(btn.dataset.score)) {\n\t\t\t\t\t\t\tbtn.style.borderColor =\n\t\t\t\t\t\t\t\tthis.surveyOptions.theme === 'dark' ? '#444' : '#d2d2d7';\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t}\n\n\t\tif (type === 'custom') {\n\t\t\t// Frequency buttons\n\t\t\tthis.surveyElement\n\t\t\t\t.querySelectorAll('.feedback-survey-freq-btn')\n\t\t\t\t.forEach((btn) => {\n\t\t\t\t\tbtn.addEventListener('click', () =>\n\t\t\t\t\t\tthis._selectFrequency(btn.dataset.freq)\n\t\t\t\t\t);\n\t\t\t\t});\n\n\t\t\t// Select inputs\n\t\t\tthis.surveyElement\n\t\t\t\t.querySelectorAll('.feedback-survey-select')\n\t\t\t\t.forEach((select) => {\n\t\t\t\t\tselect.addEventListener('change', (e) => {\n\t\t\t\t\t\tthis.surveyState.customAnswers[select.dataset.question] =\n\t\t\t\t\t\t\te.target.value;\n\t\t\t\t\t});\n\t\t\t\t});\n\n\t\t\t// Text inputs\n\t\t\tthis.surveyElement\n\t\t\t\t.querySelectorAll('.feedback-survey-input')\n\t\t\t\t.forEach((input) => {\n\t\t\t\t\tinput.addEventListener('input', (e) => {\n\t\t\t\t\t\tthis.surveyState.customAnswers[input.dataset.question] =\n\t\t\t\t\t\t\te.target.value;\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t}\n\t}\n\n\t_selectNPS(score) {\n\t\tthis.surveyState.score = score;\n\t\tthis.surveyElement\n\t\t\t.querySelectorAll('.feedback-survey-nps-btn')\n\t\t\t.forEach((btn) => {\n\t\t\t\tconst btnScore = parseInt(btn.dataset.score);\n\t\t\t\tif (btnScore === score) {\n\t\t\t\t\tbtn.style.background = '#007aff';\n\t\t\t\t\tbtn.style.borderColor = '#007aff';\n\t\t\t\t\tbtn.style.color = '#fff';\n\t\t\t\t} else {\n\t\t\t\t\tbtn.style.background =\n\t\t\t\t\t\tthis.surveyOptions.theme === 'dark' ? '#2a2a2a' : '#f8f9fa';\n\t\t\t\t\tbtn.style.borderColor =\n\t\t\t\t\t\tthis.surveyOptions.theme === 'dark' ? '#444' : '#d2d2d7';\n\t\t\t\t\tbtn.style.color =\n\t\t\t\t\t\tthis.surveyOptions.theme === 'dark' ? '#fff' : '#1d1d1f';\n\t\t\t\t}\n\t\t\t});\n\t}\n\n\t_selectCSAT(score) {\n\t\tthis.surveyState.score = score;\n\t\tthis.surveyElement\n\t\t\t.querySelectorAll('.feedback-survey-csat-btn')\n\t\t\t.forEach((btn) => {\n\t\t\t\tconst btnScore = parseInt(btn.dataset.score);\n\t\t\t\tbtn.style.transform = btnScore === score ? 'scale(1.2)' : 'scale(1)';\n\t\t\t});\n\t}\n\n\t_selectCES(score) {\n\t\tthis.surveyState.score = score;\n\t\tthis.surveyElement\n\t\t\t.querySelectorAll('.feedback-survey-ces-btn')\n\t\t\t.forEach((btn) => {\n\t\t\t\tconst btnScore = parseInt(btn.dataset.score);\n\t\t\t\tif (btnScore === score) {\n\t\t\t\t\tbtn.style.background = '#007aff';\n\t\t\t\t\tbtn.style.borderColor = '#007aff';\n\t\t\t\t\tbtn.style.color = '#fff';\n\t\t\t\t} else {\n\t\t\t\t\tbtn.style.background =\n\t\t\t\t\t\tthis.surveyOptions.theme === 'dark' ? '#2a2a2a' : '#f8f9fa';\n\t\t\t\t\tbtn.style.borderColor =\n\t\t\t\t\t\tthis.surveyOptions.theme === 'dark' ? '#444' : '#d2d2d7';\n\t\t\t\t\tbtn.style.color =\n\t\t\t\t\t\tthis.surveyOptions.theme === 'dark' ? '#fff' : '#1d1d1f';\n\t\t\t\t}\n\t\t\t});\n\t}\n\n\t_selectFrequency(freq) {\n\t\tthis.surveyState.customAnswers.frequency = freq;\n\t\tthis.surveyElement\n\t\t\t.querySelectorAll('.feedback-survey-freq-btn')\n\t\t\t.forEach((btn) => {\n\t\t\t\tif (btn.dataset.freq === freq) {\n\t\t\t\t\tbtn.style.background = '#007aff';\n\t\t\t\t\tbtn.style.borderColor = '#007aff';\n\t\t\t\t\tbtn.style.color = '#fff';\n\t\t\t\t} else {\n\t\t\t\t\tbtn.style.background =\n\t\t\t\t\t\tthis.surveyOptions.theme === 'dark' ? '#2a2a2a' : '#f8f9fa';\n\t\t\t\t\tbtn.style.borderColor =\n\t\t\t\t\t\tthis.surveyOptions.theme === 'dark' ? '#444' : '#d2d2d7';\n\t\t\t\t\tbtn.style.color =\n\t\t\t\t\t\tthis.surveyOptions.theme === 'dark' ? '#fff' : '#1d1d1f';\n\t\t\t\t}\n\t\t\t});\n\t}\n\n\tasync _handleSubmit() {\n\t\tconst type = this.surveyOptions.surveyType;\n\n\t\t// Validate\n\t\tif (\n\t\t\t(type === 'nps' || type === 'csat' || type === 'ces') &&\n\t\t\tthis.surveyState.score === null\n\t\t) {\n\t\t\tthis._showError('Please select a rating');\n\t\t\treturn;\n\t\t}\n\n\t\tconst responseData = {\n\t\t\trating: this.surveyState.score,\n\t\t\tfeedback: this.surveyState.feedback,\n\t\t\tanswers: this.surveyState.customAnswers,\n\t\t};\n\n\t\tconst response = {\n\t\t\ttype: type,\n\t\t\tscore: this.surveyState.score,\n\t\t\tfeedback: this.surveyState.feedback,\n\t\t\tcustomAnswers: this.surveyState.customAnswers,\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t};\n\n\t\t// Call onSubmit callback if provided\n\t\tif (this.surveyOptions.onSubmit) {\n\t\t\tthis.surveyOptions.onSubmit(response);\n\t\t}\n\n\t\t// Submit to API\n\t\ttry {\n\t\t\tconst surveyId =\n\t\t\t\tthis.surveyOptions.surveyId || `local_${type}_${Date.now()}`;\n\t\t\tawait this.apiService.submitSurveyResponse(surveyId, responseData);\n\t\t} catch (error) {\n\t\t\tconsole.error('[SurveyWidget] Failed to submit survey:', error);\n\t\t}\n\n\t\tthis.sdk.eventBus.emit('survey:submitted', { widget: this, response });\n\n\t\tthis._closeSurvey();\n\t\tthis._showSuccessNotification();\n\t}\n\n\tasync _handleDismiss() {\n\t\t// Call dismiss API if survey has a backend ID\n\t\tif (this.surveyOptions.surveyId) {\n\t\t\ttry {\n\t\t\t\tawait this.apiService.dismissSurvey(this.surveyOptions.surveyId);\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error('[SurveyWidget] Failed to dismiss survey:', error);\n\t\t\t}\n\t\t}\n\n\t\tif (this.surveyOptions.onDismiss) {\n\t\t\tthis.surveyOptions.onDismiss();\n\t\t}\n\t\tthis.sdk.eventBus.emit('survey:dismissed', { widget: this });\n\t\tthis._closeSurvey();\n\t}\n\n\t_showError(message) {\n\t\t// Simple error display - could be enhanced\n\t\tconst existing = this.surveyElement.querySelector('.feedback-survey-error');\n\t\tif (existing) existing.remove();\n\n\t\tconst error = document.createElement('div');\n\t\terror.className = 'feedback-survey-error';\n\t\terror.style.cssText =\n\t\t\t'color: #ef4444; font-size: 13px; margin-top: 8px; text-align: center;';\n\t\terror.textContent = message;\n\n\t\tconst submitBtn = this.surveyElement.querySelector(\n\t\t\t'.feedback-survey-submit'\n\t\t);\n\t\tsubmitBtn.parentNode.insertBefore(error, submitBtn);\n\n\t\tsetTimeout(() => error.remove(), 3000);\n\t}\n\n\t_showSuccessNotification() {\n\t\tconst notification = document.createElement('div');\n\t\tnotification.className = 'feedback-survey-success';\n\t\tnotification.style.cssText = `\n\t\t\tposition: fixed;\n\t\t\ttop: 24px;\n\t\t\tright: 24px;\n\t\t\tbackground: #10b981;\n\t\t\tcolor: white;\n\t\t\tpadding: 16px 24px;\n\t\t\tborder-radius: 12px;\n\t\t\tfont-size: 14px;\n\t\t\tfont-weight: 500;\n\t\t\tz-index: 10001;\n\t\t\tbox-shadow: 0 10px 40px rgba(0,0,0,0.2);\n\t\t\tfont-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;\n\t\t`;\n\t\tnotification.innerHTML = `\n\t\t\t<div style=\"display: flex; align-items: center; gap: 8px;\">\n\t\t\t\t<span style=\"font-size: 18px;\">✓</span>\n\t\t\t\t<span>Thank you for your feedback!</span>\n\t\t\t</div>\n\t\t`;\n\t\tdocument.body.appendChild(notification);\n\n\t\tsetTimeout(() => {\n\t\t\tnotification.style.opacity = '0';\n\t\t\tnotification.style.transition = 'opacity 0.3s ease';\n\t\t\tsetTimeout(() => notification.remove(), 300);\n\t\t}, 3000);\n\t}\n\n\t_closeSurvey() {\n\t\tif (this._escapeHandler) {\n\t\t\tdocument.removeEventListener('keydown', this._escapeHandler);\n\t\t\tthis._escapeHandler = null;\n\t\t}\n\n\t\t// Capture references to avoid race conditions with setTimeout\n\t\tconst surveyEl = this.surveyElement;\n\t\tconst backdropEl = this.backdropElement;\n\n\t\tif (surveyEl) {\n\t\t\tsurveyEl.style.opacity = '0';\n\t\t\tsurveyEl.style.transform =\n\t\t\t\tthis.surveyOptions.position === 'center'\n\t\t\t\t\t? 'translate(-50%, -50%) scale(0.95)'\n\t\t\t\t\t: 'translateY(20px)';\n\t\t\tsetTimeout(() => {\n\t\t\t\tif (surveyEl && surveyEl.parentNode) {\n\t\t\t\t\tsurveyEl.parentNode.removeChild(surveyEl);\n\t\t\t\t}\n\t\t\t}, 300);\n\t\t\tthis.surveyElement = null;\n\t\t}\n\n\t\tif (backdropEl) {\n\t\t\tbackdropEl.style.opacity = '0';\n\t\t\tsetTimeout(() => {\n\t\t\t\tif (backdropEl && backdropEl.parentNode) {\n\t\t\t\t\tbackdropEl.parentNode.removeChild(backdropEl);\n\t\t\t\t}\n\t\t\t}, 300);\n\t\t\tthis.backdropElement = null;\n\t\t}\n\n\t\tthis.surveyState = {\n\t\t\tscore: null,\n\t\t\tfeedback: '',\n\t\t\tcustomAnswers: {},\n\t\t\tisVisible: false,\n\t\t};\n\t}\n\n\tdestroy() {\n\t\tthis._closeSurvey();\n\t\tsuper.destroy();\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 { ChangelogWidget } from './ChangelogWidget.js';\nimport { InlineWidget } from './InlineWidget.js';\nimport { MessengerWidget } from './MessengerWidget.js';\nimport { SurveyWidget } from './SurveyWidget.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\t['survey', SurveyWidget],\n\t\t['messenger', MessengerWidget],\n\t\t['changelog', ChangelogWidget],\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\tmock: this.config.mock,\n\t\t\tenv: this.config.env,\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\t// Merge backend config as base, local config overrides\n\t\t\tif (initData.config) {\n\t\t\t\tthis.config = deepMerge(initData.config, this.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(\n\t\t\t\t'SDK must be initialized before creating widgets. Call init() first.'\n\t\t\t);\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\t/**\n\t * Fetch active surveys from the backend\n\t * @param {Object} context - Optional context for targeting\n\t * @param {string} context.page - Current page/route\n\t * @param {string} context.event - Event trigger name\n\t * @returns {Promise<Array>} Array of active survey configurations\n\t */\n\tasync getActiveSurveys(context = {}) {\n\t\tif (!this.initialized) {\n\t\t\tthrow new SDKError(\n\t\t\t\t'SDK must be initialized before fetching surveys. Call init() first.'\n\t\t\t);\n\t\t}\n\n\t\ttry {\n\t\t\tconst result = await this.apiService.getActiveSurveys(context);\n\t\t\treturn result.data || [];\n\t\t} catch (error) {\n\t\t\tthis.eventBus.emit('sdk:error', { error });\n\t\t\tthrow new SDKError(\n\t\t\t\t`Failed to fetch active surveys: ${error.message}`,\n\t\t\t\terror\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Show a survey by its backend ID\n\t * Fetches survey configuration from the backend and displays it\n\t * @param {string} surveyId - The backend survey ID\n\t * @param {Object} options - Additional display options\n\t * @param {string} options.position - Position override\n\t * @param {string} options.theme - Theme override\n\t * @param {Function} options.onSubmit - Callback when survey is submitted\n\t * @param {Function} options.onDismiss - Callback when survey is dismissed\n\t * @returns {Promise<SurveyWidget>} The survey widget instance\n\t */\n\tasync showSurveyById(surveyId, options = {}) {\n\t\tif (!this.initialized) {\n\t\t\tthrow new SDKError(\n\t\t\t\t'SDK must be initialized before showing surveys. Call init() first.'\n\t\t\t);\n\t\t}\n\n\t\t// Fetch active surveys to find the one with matching ID\n\t\tconst surveys = await this.getActiveSurveys();\n\t\tconst surveyConfig = surveys.find((s) => s.id === surveyId);\n\n\t\tif (!surveyConfig) {\n\t\t\tthrow new SDKError(\n\t\t\t\t`Survey with ID '${surveyId}' not found or not active`\n\t\t\t);\n\t\t}\n\n\t\treturn this.showSurvey({\n\t\t\tsurveyId: surveyConfig.id,\n\t\t\tsurveyType: surveyConfig.type,\n\t\t\ttitle: surveyConfig.title,\n\t\t\tdescription: surveyConfig.description,\n\t\t\tlowLabel: surveyConfig.low_label,\n\t\t\thighLabel: surveyConfig.high_label,\n\t\t\tcustomQuestions: surveyConfig.questions,\n\t\t\t...options,\n\t\t});\n\t}\n\n\t/**\n\t * Show a survey widget (local/manual mode)\n\t * For backend-driven surveys, use showSurveyById() instead\n\t * @param {Object} options - Survey options\n\t * @param {string} options.surveyId - Backend survey ID (for API tracking)\n\t * @param {string} options.surveyType - Type of survey: 'nps', 'csat', 'ces', 'custom'\n\t * @param {string} options.position - Position: 'bottom-right', 'bottom-left', 'center', 'bottom'\n\t * @param {string} options.theme - Theme: 'light', 'dark'\n\t * @param {string} options.title - Custom title\n\t * @param {string} options.description - Custom description\n\t * @param {string} options.lowLabel - Low end label\n\t * @param {string} options.highLabel - High end label\n\t * @param {Function} options.onSubmit - Callback when survey is submitted\n\t * @param {Function} options.onDismiss - Callback when survey is dismissed\n\t * @returns {SurveyWidget} The survey widget instance\n\t */\n\tshowSurvey(options = {}) {\n\t\tif (!this.initialized) {\n\t\t\tthrow new SDKError(\n\t\t\t\t'SDK must be initialized before showing surveys. Call init() first.'\n\t\t\t);\n\t\t}\n\n\t\tconst surveyWidget = this.createWidget('survey', {\n\t\t\tsurveyId: options.surveyId,\n\t\t\tsurveyType: options.surveyType || options.type || 'nps',\n\t\t\tposition: options.position || 'bottom-right',\n\t\t\ttheme: options.theme || this.config.theme || 'light',\n\t\t\ttitle: options.title,\n\t\t\tdescription: options.description,\n\t\t\tlowLabel: options.lowLabel,\n\t\t\thighLabel: options.highLabel,\n\t\t\tcustomQuestions: options.customQuestions,\n\t\t\tonSubmit: options.onSubmit,\n\t\t\tonDismiss: options.onDismiss,\n\t\t});\n\n\t\tsurveyWidget.mount();\n\t\tsurveyWidget.show();\n\n\t\treturn surveyWidget;\n\t}\n\n\t/**\n\t * Show a changelog widget with sidebar\n\t * @param {Object} options - Changelog widget options\n\t * @param {string} options.position - Position: 'bottom-right', 'bottom-left', 'top-right', 'top-left'\n\t * @param {string} options.theme - Theme: 'light', 'dark'\n\t * @param {string} options.title - Sidebar title\n\t * @param {string} options.triggerText - Text on the trigger button\n\t * @param {boolean} options.showBadge - Show notification badge\n\t * @param {string} options.viewButtonText - Text for the view update button\n\t * @param {string} options.changelogBaseUrl - Base URL for changelog links\n\t * @param {boolean} options.openInNewTab - Open changelog links in new tab (default: true)\n\t * @param {Function} options.onViewUpdate - Callback when user clicks view update\n\t * @returns {ChangelogWidget} The changelog widget instance\n\t */\n\tshowChangelog(options = {}) {\n\t\tif (!this.initialized) {\n\t\t\tthrow new SDKError(\n\t\t\t\t'SDK must be initialized before showing changelog. Call init() first.'\n\t\t\t);\n\t\t}\n\n\t\tconst changelogWidget = this.createWidget('changelog', {\n\t\t\tposition: options.position || 'bottom-right',\n\t\t\ttheme: options.theme || this.config.theme || 'light',\n\t\t\ttitle: options.title || \"What's New\",\n\t\t\ttriggerText: options.triggerText || \"What's New\",\n\t\t\tshowBadge: options.showBadge !== false,\n\t\t\tviewButtonText: options.viewButtonText || 'View Update',\n\t\t\tchangelogBaseUrl: options.changelogBaseUrl,\n\t\t\topenInNewTab: options.openInNewTab,\n\t\t\tonViewUpdate: options.onViewUpdate,\n\t\t});\n\n\t\tchangelogWidget.mount();\n\t\tchangelogWidget.show();\n\n\t\treturn changelogWidget;\n\t}\n\n\t/**\n\t * Get changelogs from the backend\n\t * @param {Object} options - Optional query parameters\n\t * @param {number} options.limit - Number of changelogs to fetch\n\t * @param {number} options.offset - Offset for pagination\n\t * @returns {Promise<Array>} Array of changelog entries\n\t */\n\tasync getChangelogs(options = {}) {\n\t\tif (!this.initialized) {\n\t\t\tthrow new SDKError(\n\t\t\t\t'SDK must be initialized before fetching changelogs. Call init() first.'\n\t\t\t);\n\t\t}\n\n\t\ttry {\n\t\t\tconst result = await this.apiService.getChangelogs(options);\n\t\t\treturn result.data || [];\n\t\t} catch (error) {\n\t\t\tthis.eventBus.emit('sdk:error', { error });\n\t\t\tthrow new SDKError(`Failed to fetch changelogs: ${error.message}`, error);\n\t\t}\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 (\n\t\t\tthis.config.userContext ||\n\t\t\t(this.apiService ? this.apiService.getUserContext() : null)\n\t\t);\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/**\n\t * Check if feedback was recently submitted for this workspace\n\t * Uses backend tracking (preferred) with localStorage as fallback\n\t * @param {number} cooldownDays - Days to consider as \"recently\" (default: 30)\n\t * @returns {boolean} true if feedback was submitted within the cooldown period\n\t */\n\thasFeedbackBeenSubmitted(cooldownDays = 30) {\n\t\tconst cooldownMs = cooldownDays * 24 * 60 * 60 * 1000;\n\t\tconst now = Date.now();\n\n\t\t// Check backend tracking first (from init response)\n\t\tif (this.config.last_feedback_at) {\n\t\t\ttry {\n\t\t\t\tconst backendTimestamp = new Date(\n\t\t\t\t\tthis.config.last_feedback_at\n\t\t\t\t).getTime();\n\t\t\t\tif (now - backendTimestamp < cooldownMs) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t} catch (e) {\n\t\t\t\t// Invalid date format, continue to localStorage check\n\t\t\t}\n\t\t}\n\n\t\t// Fallback to localStorage\n\t\ttry {\n\t\t\tconst storageKey = `feedback_submitted_${this.config.workspace}`;\n\t\t\tconst stored = localStorage.getItem(storageKey);\n\t\t\tif (!stored) return false;\n\n\t\t\tconst data = JSON.parse(stored);\n\t\t\treturn now - data.submittedAt < cooldownMs;\n\t\t} catch (e) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Clear the feedback submission tracking (allow showing widgets again)\n\t */\n\tclearFeedbackSubmissionTracking() {\n\t\ttry {\n\t\t\tconst storageKey = `feedback_submitted_${this.config.workspace}`;\n\t\t\tlocalStorage.removeItem(storageKey);\n\t\t\tthis.eventBus.emit('feedback:trackingCleared');\n\t\t} catch (e) {\n\t\t\tconsole.warn('Failed to clear feedback tracking:', e);\n\t\t}\n\t}\n\n\t_detectEnvironment() {\n\t\tif (typeof window === 'undefined') {\n\t\t\treturn 'production';\n\t\t}\n\n\t\tconst hostname = window.location.hostname.toLowerCase();\n\n\t\tif (\n\t\t\thostname.includes('staging') ||\n\t\t\thostname.includes('localhost') ||\n\t\t\thostname.includes('127.0.0.1') ||\n\t\t\thostname.includes('.local')\n\t\t) {\n\t\t\treturn 'staging';\n\t\t}\n\n\t\treturn 'production';\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\tmock: false,\n\t\t\tenv: this._detectEnvironment(),\n\t\t};\n\n\t\tconst mergedConfig = deepMerge(\n\t\t\tdeepMerge(defaultConfig, existingConfig),\n\t\t\tnewConfig\n\t\t);\n\n\t\tif (!newConfig.env && !existingConfig.env) {\n\t\t\tmergedConfig.env = this._detectEnvironment();\n\t\t}\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(\n\t\t\t\t'User context must include at least user_id or email'\n\t\t\t);\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(\n\t\t\t\t\t`User context field '${key}' must be of type '${expectedType}'`\n\t\t\t\t);\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:\n\t\t\t\tauthData.company || authData.organization\n\t\t\t\t\t? {\n\t\t\t\t\t\t\tid: authData.company?.id || authData.organization?.id,\n\t\t\t\t\t\t\tname: authData.company?.name || authData.organization?.name,\n\t\t\t\t\t\t\tmonthly_spend: authData.company?.monthly_spend,\n\t\t\t\t\t\t}\n\t\t\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 { MESSENGER_STYLES } from './styles/messengerStyles.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 { ChangelogWidget } from './widgets/ChangelogWidget.js';\nimport { InlineWidget } from './widgets/InlineWidget.js';\nimport { MessengerWidget } from './widgets/MessengerWidget.js';\nimport { SurveyWidget } from './widgets/SurveyWidget.js';\nimport { TabWidget } from './widgets/TabWidget.js';\nimport { WidgetFactory } from './widgets/WidgetFactory.js';\n\nfunction injectStyles() {\n\tif (\n\t\ttypeof document !== 'undefined' &&\n\t\t!document.querySelector('#feedback-sdk-styles')\n\t) {\n\t\tconst style = document.createElement('style');\n\t\tstyle.id = 'feedback-sdk-styles';\n\t\tstyle.textContent = CSS_STYLES + MESSENGER_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\tChangelogWidget,\n\tTabWidget,\n\tInlineWidget,\n\tSurveyWidget,\n\tMessengerWidget,\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\tChangelogWidget,\n\tConfigError,\n\tEventBus,\n\tFeedbackSDK,\n\thelpers,\n\tInlineWidget,\n\tMessengerWidget,\n\tSDKError,\n\tSurveyWidget,\n\tTabWidget,\n\tValidationError,\n\tWidgetError,\n\tWidgetFactory,\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","MOCK_CONFIG","primaryColor","backgroundColor","textColor","boardId","size","displayMode","MOCK_CHANGELOGS","id","title","excerpt","description","cover_image","slug","published_at","labels","color","MOCK_CONVERSATIONS","subject","last_message_at","Date","now","toISOString","created_at","unread","assigned_user","avatar","MOCK_MESSAGES","conv_1","content","sender_type","sender_name","sender_avatar","conv_2","MOCK_HELP_COLLECTIONS","articleCount","icon","url","MOCK_SURVEYS","type","low_label","high_label","trigger","ENV_URLS","production","base","withWorkspace","workspace","staging","APIService","config","sessionToken","sessionExpiry","userContext","mock","env","apiUrl","baseURL","envConfig","_loadStoredSession","init","isSessionValid","error","_storeSession","expiresIn","payload","user","_makeRequest","method","body","JSON","stringify","headers","session_token","expires_in","submitFeedback","feedbackData","Promise","resolve","setTimeout","success","data","board","board_id","attachments","Authorization","getActiveSurveys","context","queryParams","URLSearchParams","currentUrl","window","location","href","append","deviceInfo","_getDeviceInfo","device","browser","os","userProperties","endpoint","toString","navigator","ua","userAgent","test","includes","submitSurveyResponse","surveyId","responseData","survey_id","rating","feedback","answers","dismissSurvey","getMessengerSettings","enabled","greeting_message","team_name","response_time","checkAgentsOnline","agents_online","online_count","getConversations","options","meta","total","length","page","limit","params","getConversation","conversationId","find","c","messages","getMessages","startConversation","newConv","unshift","sendMessage","newMessage","push","sendTypingIndicator","isTyping","is_typing","markConversationAsRead","getUnreadCount","count","reduce","sum","unread_count","unread_conversations","submitRating","comment","identifyContact","getHelpCollections","searchHelpArticles","query","filter","toLowerCase","q","getChangelogs","offset","setUserContext","localStorage","setItem","getUserContext","clearSession","removeItem","sessionData","token","expiry","stored","getItem","parse","fetch","ok","errorMessage","json","e","text","contentType","get","EventBus","events","Map","on","event","callback","has","set","off","callbacks","index","indexOf","splice","emit","forEach","console","once","unsubscribe","clear","getListenerCount","generateId","prefix","Math","random","substring","deepMerge","target","source","result","key","hasOwnProperty","Array","isArray","isBrowser","document","func","wait","timeout","args","clearTimeout","ms","string","replace","bytes","i","floor","log","parseFloat","pow","toFixed","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","email","trim","str","div","createElement","textContent","innerHTML","scrollIntoView","behavior","block","inline","lastKey","pop","lastFunc","lastRan","required","missing","join","BaseWidget","static","sdk","apiService","container","position","autoShow","showBackdrop","customStyles","suppressAfterSubmission","suppressionDays","DEFAULT_COOLDOWN_DAYS","panelElement","backdropElement","mounted","destroyed","state","isOpen","isLoading","isSubmitting","errors","_bindMethods","mount","_hasRecentlySubmitted","eventBus","widget","reason","querySelector","_render","appendChild","_attachEvents","onMount","show","style","display","hide","openPanel","_showLoadingModal","_hideLoadingModal","_renderPanel","requestAnimationFrame","classList","add","className","loadingElement","theme","remove","closePanel","parentNode","removeChild","_resetForm","_hideError","_updateSubmitButton","_showError","_trackSubmission","_showSuccessMessage","handleConfigUpdate","newConfig","_updateTheme","destroy","onDestroy","storageKey","STORAGE_KEY","submittedAt","warn","cooldownMs","last_feedback_at","getTime","clearSubmissionTracking","shouldShow","bind","addEventListener","modeClass","sizeClass","setProperty","_getPanelHTML","_attachPanelEvents","firstInput","focus","panel","preventDefault","handleEscape","removeEventListener","submitBtn","disabled","errorElement","notification","closeNotification","opacity","openModal","closeModal","ButtonWidget","isMinimized","button","Object","assign","minimizeIcon","expandIcon","stopPropagation","minimize","restore","closest","transform","updateText","textEl","updatePosition","ChangelogWidget","changelogs","modalElement","sidebarElement","currentIndex","triggerText","showBadge","openSidebar","_createModal","_loadChangelogs","_renderCurrentChangelog","overflow","_escapeHandler","listModalElement","_createListModal","_renderChangelogList","_showConfetti","listModalBackdropElement","colors","confetti","animationDelay","animationDuration","shapes","shape","borderRadius","closeSidebar","_listModalEscapeHandler","map","changelog","_renderChangelogListItem","querySelectorAll","item","_handleViewUpdate","hasImage","image","imageUrl","date","_formatDate","label","_getContrastColor","hasMultiple","viewButtonText","_","dot","parseInt","dataset","changelogBaseUrl","openInNewTab","open","onViewUpdate","dateString","toLocaleDateString","year","month","day","hexColor","hex","substr","hideBadge","badge","nextChangelog","prevChangelog","refresh","InlineWidget","form","textarea","originalContent","updateTitle","titleElement","setPlaceholder","placeholder","input","WebSocketService","ws","reconnectAttempts","maxReconnectAttempts","reconnectDelay","pingInterval","isConnected","_listeners","_onOpen","_onMessage","_onClose","_onError","connect","_emit","_startMockResponses","wsProtocol","protocol","wsURL","encodeURIComponent","WebSocket","onopen","onmessage","onclose","onerror","_scheduleReconnect","disconnect","clearInterval","close","_mockInterval","Set","delete","send","readyState","OPEN","setInterval","code","delay","conversation_id","user_id","user_name","is_agent","simulateMessage","MessengerState","currentView","unreadCount","activeConversationId","conversations","helpArticles","helpSearchQuery","homeChangelogItems","changelogItems","teamName","teamAvatars","welcomeMessage","enableHelp","enableChangelog","agentsOnline","onlineCount","responseTime","typingUsers","isLoadingMessages","subscribe","_notify","changeType","cb","setView","view","previousView","setOpen","setActiveConversation","setConversations","_updateUnreadCount","addConversation","conversation","setMessages","addMessage","conv","lastMessage","lastMessageTime","timestamp","isOwn","markAsRead","setHelpArticles","articles","setHelpSearchQuery","setHomeChangelogItems","items","setChangelogItems","getActiveConversation","getActiveMessages","getFilteredHelpArticles","article","reset","MessengerLauncher","_unsubscribe","render","_updateContent","_updateIcon","_updateBadge","badgeHtml","chatIcon","closeIcon","existingBadge","NavigationTabs","_updateActiveTab","_getTabs","tabs","_getHomeIcon","_getMessagesIcon","_getHelpIcon","_getChangelogIcon","tabsHtml","tab","isActive","tabId","toggle","MessengerPanel","navigationTabs","currentViewComponent","viewRegistry","registerView","ViewClass","_renderCurrentView","viewsContainer","setHeader","headerContent","header","ChangelogView","_updateChangelogList","avatarsHtml","_renderTeamAvatars","changelogContainer","_renderChangelogCard","_attachChangelogEvents","_renderEmptyState","tagsHtml","tags","tag","dateStr","publishedAt","coverImage","_truncateText","avatars","slice","startsWith","charAt","toUpperCase","maxLength","card","changelogId","changelogItem","n","onChangelogClick","ChatView","_typingTimeout","_isTyping","_typingIndicator","_hideTypingIndicator","_appendMessage","_scrollToBottom","_showTypingIndicator","userName","isNewConversation","messagesHtml","msg","_renderMessage","avatarHtml","_renderConversationAvatar","isOnline","messageClass","timeStr","_formatMessageTime","_formatMessageContent","_renderSenderAvatar","sender","avatarUrl","participants","p","toLocaleTimeString","hour","minute","hour12","messagesContainer","emptyState","messageHtml","tempDiv","firstElementChild","scrollTop","scrollHeight","sendBtn","min","_startTyping","shiftKey","_sendMessage","_stopTyping","onStartConversation","onSendMessage","onTyping","ConversationsView","_renderAvatarStack","conversationsHtml","_renderConversationItem","unreadClass","timeAgo","_formatTimeAgo","_renderConversationAvatars","_truncateMessage","_getAvatarColor","diffMs","diffMins","diffHours","diffDays","closeBtn","convId","onSelectConversation","newMsgBtn","_startNewConversation","onStartNewConversation","HelpView","_updateCollectionsList","searchQuery","collectionCount","collectionsContainer","collections","filteredCollections","headerEl","collection","_renderCollectionItem","_attachCollectionEvents","searchTimeout","collectionId","onArticleClick","HomeView","recentChangelogHtml","_renderRecentChangelog","logoUrl","_renderAvailabilityStatus","_renderFeaturedCard","featuredContent","action","coverText","seeAllBtn","featuredBtn","MessengerWidget","messengerOptions","messengerState","launcher","wsService","_wsUnsubscribers","_handleOpenChange","_handleWebSocketMessage","_handleTypingStarted","_handleTypingStopped","zIndex","_handleSendMessage","_handleStartConversation","_handleSelectConversation","_handleNewConversationClick","_stateUnsubscribe","messageContent","startNewConversation","fetchMessages","mockResponse","localMessage","_initWebSocket","navigateTo","setUnreadCount","getState","loadInitialData","_fetchConversations","_fetchHelpArticles","homeItems","_fetchChangelog","preview","snippet","article_count","newConversation","checkAgentAvailability","mappedItems","_availabilityInterval","unsub","SurveyWidget","surveyOptions","surveyType","lowLabel","highLabel","customQuestions","onSubmit","onDismiss","surveyState","score","customAnswers","isVisible","_renderSurvey","_closeSurvey","_getSurveyConfig","positionStyles","_getPositionStyles","themeStyles","_handleDismiss","surveyElement","cssText","html","_attachSurveyEvents","configs","nps","csat","emoji","ces","custom","_renderCustomQuestions","_renderQuestionInput","freq","question","opt","positions","center","_handleSubmit","_attachTypeSpecificEvents","btn","_selectNPS","borderColor","_selectCSAT","_selectCES","_selectFrequency","select","background","btnScore","frequency","_showSuccessNotification","existing","insertBefore","transition","surveyEl","backdropEl","TabWidget","_getHoverTransform","textElement","WidgetFactory","register","WidgetClass","widgets","create","availableTypes","from","getAvailableTypes","isTypeRegistered","unregister","getWidgetClass","FeedbackSDK","_validateAndMergeConfig","initialized","alreadyInitialized","initData","createWidget","widgetOptions","getWidget","showSurveyById","surveyConfig","s","showSurvey","questions","surveyWidget","showChangelog","changelogWidget","getAllWidgets","values","destroyWidget","destroyAllWidgets","updateConfig","oldConfig","reinitialize","newUserContext","removeAllListeners","hasFeedbackBeenSubmitted","cooldownDays","clearFeedbackSubmissionTracking","_detectEnvironment","hostname","existingConfig","mergedConfig","debug","_validateUserContext","validStructure","custom_fields","company","expectedType","entries","createAndInit","extractUserContextFromAuth","authData","sub","display_name","full_name","role","plan","subscription","organization","monthly_spend","injectStyles","CSS_STYLES","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"],"mappings":"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"}
|