tchao 0.1.2 → 1.0.0
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 +143 -100
- package/dist/npm.d.mts +106 -69
- package/dist/npm.d.ts +106 -69
- package/dist/npm.js +1 -1440
- package/dist/npm.js.map +1 -1
- package/dist/npm.mjs +1 -1440
- package/dist/npm.mjs.map +1 -1
- package/dist/react.d.mts +68 -0
- package/dist/react.d.ts +68 -0
- package/dist/react.js +2 -0
- package/dist/react.js.map +1 -0
- package/dist/react.mjs +2 -0
- package/dist/react.mjs.map +1 -0
- package/package.json +17 -13
package/dist/npm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/widget/npm.ts","../../../src/widget/convex-client.ts","../../../src/widget/config.ts","../../../src/widget/styles.ts","../../../src/widget/ui.ts","../../../src/widget/api.ts","../../../src/widget/draft.ts","../../../src/widget/notifications.ts","../../../src/widget/realtime.ts","../../../src/widget/screenshot.ts","../../../src/widget/sdk.ts","../../../src/widget/tracking.ts","../../../src/widget/core.ts"],"sourcesContent":["import { cleanup, initWidget, type TchaoInitConfig } from \"./core\";\nimport { TchaoSDK } from \"./sdk\";\nimport type {\n ConversationStatus,\n Message,\n MessageReaction,\n MessageStatus,\n SenderType,\n ThemeMode,\n VisitorInfo,\n WidgetConfig,\n WidgetPosition,\n WidgetStyle,\n SDKEventMap,\n SDKMethods,\n} from \"./types\";\n\nexport type TchaoConfig = TchaoInitConfig;\n\nexport type TchaoInstance = SDKMethods & {\n destroy: () => void;\n};\n\nexport type TchaoEvents = SDKEventMap;\n\nexport type {\n VisitorInfo,\n WidgetConfig,\n Message,\n MessageReaction,\n SenderType,\n ConversationStatus,\n MessageStatus,\n WidgetPosition,\n WidgetStyle,\n ThemeMode,\n};\n\nexport async function init(config: TchaoConfig): Promise<TchaoInstance> {\n if (!config.websiteId) {\n throw new Error(\"websiteId is required\");\n }\n\n const sdk = await initWidget(config);\n\n return Object.assign(sdk, {\n destroy: cleanup,\n }) as TchaoInstance;\n}\n\nexport const Tchao = {\n init,\n};\n\nexport { TchaoSDK };\n\nexport default Tchao;\n","import { ConvexClient } from \"convex/browser\";\nimport { anyApi } from \"convex/server\";\n\nimport type { Message, PresenceStatus, WebsiteConfig } from \"./types\";\n\nlet client: ConvexClient | null = null;\nlet convexUrl: string | null = null;\n\ntype ConvexMessage = {\n _id: string;\n content: string;\n senderType: \"VISITOR\" | \"AGENT\" | \"AI\" | \"SYSTEM\";\n senderId: string;\n screenshot?: string;\n image?: string;\n createdAt: number;\n updatedAt?: number;\n reactions?: { emoji: string; userIds: string[] }[];\n};\n\ntype ConversationData = {\n conversation: {\n _id: string;\n status: \"OPEN\" | \"IN_PROGRESS\" | \"CLOSED\";\n visitorDraft?: string;\n };\n messages: ConvexMessage[];\n};\n\nexport function initConvexClient(url: string): ConvexClient {\n if (client && convexUrl === url) {\n return client;\n }\n\n if (client) {\n void client.close();\n }\n\n convexUrl = url;\n client = new ConvexClient(url);\n return client;\n}\n\nexport function getConvexClient(): ConvexClient | null {\n return client;\n}\n\nexport function destroyConvexClient(): void {\n if (client) {\n void client.close();\n client = null;\n convexUrl = null;\n }\n}\n\nfunction convertMessage(m: ConvexMessage): Message {\n return {\n id: m._id,\n content: m.content,\n senderType: m.senderType,\n senderId: m.senderId,\n screenshot: m.screenshot,\n image: m.image,\n timestamp: m.createdAt,\n reactions: m.reactions,\n };\n}\n\nexport async function convexFetchConfig(\n websiteId: string,\n): Promise<WebsiteConfig | null> {\n if (!client) return null;\n\n const result = await client.query(anyApi.widget.getConfig, { websiteId });\n if (!result) return null;\n\n return {\n id: result._id,\n name: result.name,\n tagline: result.tagline ?? null,\n primaryColor: result.primaryColor,\n position: result.position as \"bottom-right\" | \"bottom-left\",\n widgetStyle: result.widgetStyle as \"bubble\" | \"name_line\" | \"question_cta\",\n themeMode: result.themeMode as \"light\" | \"dark\" | \"system\",\n agentImage: result.agentImage ?? null,\n agentName: result.agentName ?? null,\n agentRole: result.agentRole ?? null,\n agentWelcomeMessage: result.agentWelcomeMessage ?? null,\n hidePoweredBy: result.hidePoweredBy,\n };\n}\n\nexport async function convexGetOrCreateConversation(\n websiteId: string,\n visitorId: string,\n url: string,\n visitorMeta?: Record<string, unknown>,\n): Promise<{\n conversationId: string;\n isNew: boolean;\n lastVisitorMessageAt?: number;\n} | null> {\n if (!client) return null;\n\n const result = await client.mutation(anyApi.widget.getOrCreateConversation, {\n websiteId,\n visitorId,\n url,\n visitorMeta,\n });\n\n return {\n conversationId: result.conversationId,\n isNew: result.isNew,\n lastVisitorMessageAt: result.lastVisitorMessageAt,\n };\n}\n\nexport async function convexFetchConversation(\n conversationId: string,\n visitorId: string,\n): Promise<{\n conversation: { id: string; status: string; websiteId: string };\n messages: Message[];\n} | null> {\n if (!client) return null;\n\n const result = (await client.query(anyApi.widget.getConversation, {\n conversationId,\n visitorId,\n })) as ConversationData | null;\n\n if (!result) return null;\n\n return {\n conversation: {\n id: result.conversation._id,\n status: result.conversation.status,\n websiteId: \"\",\n },\n messages: result.messages.map(convertMessage),\n };\n}\n\nexport async function convexSendMessage(\n conversationId: string,\n visitorId: string,\n content: string,\n screenshot?: string | null,\n url?: string,\n image?: string | null,\n): Promise<Message | null> {\n if (!client) return null;\n\n const result = await client.mutation(anyApi.widget.sendMessage, {\n conversationId,\n visitorId,\n content,\n screenshot: screenshot ?? undefined,\n image: image ?? undefined,\n url,\n });\n\n return {\n id: result._id,\n content: result.content,\n senderType: result.senderType,\n senderId: result.senderId,\n screenshot: result.screenshot,\n image: result.image,\n timestamp: result.createdAt,\n };\n}\n\nexport async function convexUpdateDraft(\n conversationId: string,\n draft: string,\n): Promise<boolean> {\n if (!client) return false;\n\n await client.mutation(anyApi.widget.updateDraft, {\n conversationId,\n draft,\n });\n\n return true;\n}\n\nexport async function convexUpdateNavigation(\n conversationId: string,\n url: string,\n): Promise<boolean> {\n if (!client) return false;\n\n await client.mutation(anyApi.widget.updateNavigation, {\n conversationId,\n url,\n });\n\n return true;\n}\n\nexport async function convexMarkAsRead(\n conversationId: string,\n visitorId: string,\n): Promise<{ updated: number }> {\n if (!client) return { updated: 0 };\n\n const result = await client.mutation(anyApi.widget.markAsRead, {\n conversationId,\n visitorId,\n });\n\n return result;\n}\n\nexport async function convexIdentify(\n conversationId: string,\n visitorId: string,\n info: { name?: string; email?: string; avatar?: string; metadata?: unknown },\n): Promise<{ success: boolean; name?: string }> {\n if (!client) return { success: false };\n\n const result = await client.mutation(anyApi.widget.identify, {\n conversationId,\n visitorId,\n name: info.name,\n email: info.email,\n avatar: info.avatar,\n metadata: info.metadata,\n });\n\n return result;\n}\n\nexport async function convexGetAgentPresence(\n websiteId: string,\n): Promise<PresenceStatus> {\n if (!client) return \"away\";\n\n const result = await client.query(anyApi.widget.getAgentPresence, {\n websiteId,\n });\n\n return result.status;\n}\n\nexport async function convexUpdateVisitorPresence(\n conversationId: string,\n status: PresenceStatus,\n): Promise<void> {\n if (!client) return;\n\n await client.mutation(anyApi.widget.updateVisitorPresence, {\n conversationId,\n status,\n });\n}\n\nexport async function convexAddReaction(\n messageId: string,\n emoji: string,\n visitorId: string,\n): Promise<boolean> {\n if (!client) return false;\n\n await client.mutation(anyApi.widget.addReaction, {\n messageId,\n emoji,\n visitorId,\n });\n\n return true;\n}\n\nexport type ConversationSubscriptionCallback = (\n data: {\n conversation: {\n status: \"OPEN\" | \"IN_PROGRESS\" | \"CLOSED\";\n visitorDraft?: string;\n };\n messages: Message[];\n } | null,\n) => void;\n\nexport type AgentPresenceCallback = (status: PresenceStatus) => void;\n\nconst noop = (): void => {\n // No-op unsubscribe function for when client is not available\n};\n\nexport function subscribeToConversation(\n conversationId: string,\n visitorId: string,\n callback: ConversationSubscriptionCallback,\n): () => void {\n if (!client) return noop;\n\n return client.onUpdate(\n anyApi.widget.getConversation,\n { conversationId, visitorId },\n (result: ConversationData | null) => {\n if (!result) {\n callback(null);\n return;\n }\n\n callback({\n conversation: {\n status: result.conversation.status,\n visitorDraft: result.conversation.visitorDraft,\n },\n messages: result.messages.map(convertMessage),\n });\n },\n );\n}\n\nexport function subscribeToAgentPresence(\n websiteId: string,\n callback: AgentPresenceCallback,\n): () => void {\n if (!client) return noop;\n\n return client.onUpdate(\n anyApi.widget.getAgentPresence,\n { websiteId },\n (result: { status: PresenceStatus }) => {\n callback(result.status);\n },\n );\n}\n","import type {\n ConversationState,\n PresenceStatus,\n WebsiteConfig,\n WidgetConfig,\n} from \"./types\";\n\nconst VISITOR_ID_KEY = \"tchao_visitor_id\";\nconst CONVERSATION_ID_PREFIX = \"tchao_conversation_id_\";\nconst EMAIL_CAPTURED_PREFIX = \"tchao_email_captured_\";\nconst LAST_SCREENSHOT_DATE_PREFIX = \"tchao_last_screenshot_\";\n\nexport const STALE_CONVERSATION_MS = 2 * 24 * 60 * 60 * 1000; // 2 days in milliseconds\n\nfunction generateVisitorId(): string {\n return `v_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`;\n}\n\nfunction getStoredVisitorId(): string {\n try {\n const stored = localStorage.getItem(VISITOR_ID_KEY);\n if (stored) return stored;\n const newId = generateVisitorId();\n localStorage.setItem(VISITOR_ID_KEY, newId);\n return newId;\n } catch {\n return generateVisitorId();\n }\n}\n\nfunction getConversationKey(websiteId: string): string {\n return `${CONVERSATION_ID_PREFIX}${websiteId}`;\n}\n\nfunction getStoredConversationId(websiteId: string): string | null {\n if (!websiteId) return null;\n try {\n return localStorage.getItem(getConversationKey(websiteId));\n } catch {\n return null;\n }\n}\n\nfunction setStoredConversationId(websiteId: string, id: string): void {\n if (!websiteId) return;\n try {\n localStorage.setItem(getConversationKey(websiteId), id);\n } catch {\n // Ignore storage errors\n }\n}\n\nfunction removeStoredConversationId(websiteId: string): void {\n if (!websiteId) return;\n try {\n localStorage.removeItem(getConversationKey(websiteId));\n } catch {\n // Ignore storage errors\n }\n}\n\nfunction getEmailCapturedKey(websiteId: string): string {\n return `${EMAIL_CAPTURED_PREFIX}${websiteId}`;\n}\n\nfunction getStoredEmailCaptured(websiteId: string): boolean {\n if (!websiteId) return false;\n try {\n return localStorage.getItem(getEmailCapturedKey(websiteId)) === \"true\";\n } catch {\n return false;\n }\n}\n\nfunction setStoredEmailCaptured(websiteId: string, captured: boolean): void {\n if (!websiteId) return;\n try {\n localStorage.setItem(getEmailCapturedKey(websiteId), String(captured));\n } catch {\n // Ignore storage errors\n }\n}\n\nfunction getLastScreenshotDateKey(websiteId: string): string {\n return `${LAST_SCREENSHOT_DATE_PREFIX}${websiteId}`;\n}\n\nfunction getStoredLastScreenshotDate(websiteId: string): string | null {\n if (!websiteId) return null;\n try {\n return localStorage.getItem(getLastScreenshotDateKey(websiteId));\n } catch {\n return null;\n }\n}\n\nfunction setStoredLastScreenshotDate(websiteId: string, date: string): void {\n if (!websiteId) return;\n try {\n localStorage.setItem(getLastScreenshotDateKey(websiteId), date);\n } catch {\n // Ignore storage errors\n }\n}\n\nfunction detectApiBaseUrl(): string {\n const script = document.currentScript as HTMLScriptElement | null;\n if (script?.src) {\n const url = new URL(script.src);\n return url.origin;\n }\n return window.location.origin;\n}\n\nexport const widgetConfig: WidgetConfig = {\n websiteId: \"\",\n apiBaseUrl: detectApiBaseUrl(),\n position: \"bottom-right\",\n primaryColor: \"#6366f1\",\n widgetStyle: \"bubble\",\n themeMode: \"system\",\n};\n\nexport let websiteConfig: WebsiteConfig | null = null;\n\nexport const conversationState: ConversationState & {\n emailCaptured: boolean;\n lastVisitorMessageAt: number | null;\n} = {\n id: null,\n websiteId: \"\",\n visitorId: getStoredVisitorId(),\n messages: [],\n status: \"OPEN\",\n isOpen: false,\n emailCaptured: false,\n lastVisitorMessageAt: null,\n};\n\nexport function initConversationForWebsite(websiteId: string): void {\n conversationState.websiteId = websiteId;\n conversationState.id = getStoredConversationId(websiteId);\n conversationState.emailCaptured = getStoredEmailCaptured(websiteId);\n conversationState.messages = [];\n}\n\nexport function updateWidgetConfig(config: Partial<WidgetConfig>): void {\n Object.assign(widgetConfig, config);\n}\n\nexport function updateWebsiteConfig(config: WebsiteConfig): void {\n websiteConfig = config;\n widgetConfig.primaryColor = config.primaryColor;\n widgetConfig.position = config.position;\n widgetConfig.widgetStyle = config.widgetStyle;\n widgetConfig.themeMode = config.themeMode;\n if (config.convexUrl) {\n widgetConfig.convexUrl = config.convexUrl;\n }\n}\n\nexport function updateConversationId(id: string): void {\n conversationState.id = id;\n setStoredConversationId(conversationState.websiteId, id);\n}\n\nexport function addMessage(message: ConversationState[\"messages\"][0]): void {\n const exists = conversationState.messages.some((m) => m.id === message.id);\n if (!exists) {\n conversationState.messages.push(message);\n }\n}\n\nexport function removeMessage(messageId: string): void {\n conversationState.messages = conversationState.messages.filter(\n (m) => m.id !== messageId,\n );\n}\n\nexport function updateMessageStatusInState(\n messageId: string,\n status: \"sending\" | \"sent\" | \"failed\",\n): void {\n const message = conversationState.messages.find((m) => m.id === messageId);\n if (message) {\n message.status = status;\n }\n}\n\nexport function updateMessageIdInState(\n tempId: string,\n realId: string,\n): boolean {\n const message = conversationState.messages.find((m) => m.id === tempId);\n if (message) {\n message.id = realId;\n return true;\n }\n return false;\n}\n\nexport function setConversationOpen(isOpen: boolean): void {\n conversationState.isOpen = isOpen;\n}\n\nexport let isMaximized = false;\n\nexport function setMaximized(maximized: boolean): void {\n isMaximized = maximized;\n}\n\nexport function clearStoredConversation(): void {\n conversationState.id = null;\n conversationState.messages = [];\n removeStoredConversationId(conversationState.websiteId);\n}\n\nexport function setMessages(messages: ConversationState[\"messages\"]): void {\n conversationState.messages = messages;\n}\n\nexport function setEmailCaptured(captured: boolean): void {\n conversationState.emailCaptured = captured;\n setStoredEmailCaptured(conversationState.websiteId, captured);\n}\n\nexport function setLastVisitorMessageAt(timestamp: number | null): void {\n conversationState.lastVisitorMessageAt = timestamp;\n}\n\nexport let agentPresenceStatus: PresenceStatus = \"away\";\n\nexport function setAgentPresenceStatus(status: PresenceStatus): void {\n agentPresenceStatus = status;\n}\n\nexport let widgetLoadedAt: number = Date.now();\n\nexport function initWidgetLoadedAt(): void {\n widgetLoadedAt = Date.now();\n}\n\nconst UNREAD_MESSAGE_IDS_PREFIX = \"tchao_unread_ids_\";\n\nfunction getUnreadIdsKey(websiteId: string): string {\n return `${UNREAD_MESSAGE_IDS_PREFIX}${websiteId}`;\n}\n\nfunction getStoredUnreadIds(websiteId: string): Set<string> {\n if (!websiteId) return new Set();\n try {\n const stored = localStorage.getItem(getUnreadIdsKey(websiteId));\n if (stored) {\n return new Set(JSON.parse(stored) as string[]);\n }\n } catch {\n // Ignore storage errors\n }\n return new Set();\n}\n\nfunction setStoredUnreadIds(websiteId: string, ids: Set<string>): void {\n if (!websiteId) return;\n try {\n localStorage.setItem(\n getUnreadIdsKey(websiteId),\n JSON.stringify(Array.from(ids)),\n );\n } catch {\n // Ignore storage errors\n }\n}\n\nexport let unreadMessageIds = new Set<string>();\n\nexport function initUnreadMessageIds(websiteId: string): void {\n unreadMessageIds = getStoredUnreadIds(websiteId);\n}\n\nexport function addUnreadMessageId(messageId: string): void {\n unreadMessageIds.add(messageId);\n setStoredUnreadIds(conversationState.websiteId, unreadMessageIds);\n}\n\nexport function markMessagesAsReadLocally(): void {\n unreadMessageIds.clear();\n setStoredUnreadIds(conversationState.websiteId, unreadMessageIds);\n}\n\nexport function getUnreadCount(): number {\n return unreadMessageIds.size;\n}\n\nexport function getResolvedTheme(): \"light\" | \"dark\" {\n const themeMode = widgetConfig.themeMode ?? \"system\";\n if (themeMode === \"system\") {\n return window.matchMedia(\"(prefers-color-scheme: dark)\").matches\n ? \"dark\"\n : \"light\";\n }\n return themeMode;\n}\n\nfunction getTodayDateString(): string {\n return new Date().toISOString().split(\"T\")[0];\n}\n\nexport function hasScreenshotToday(): boolean {\n const lastDate = getStoredLastScreenshotDate(conversationState.websiteId);\n return lastDate === getTodayDateString();\n}\n\nexport function markScreenshotTaken(): void {\n setStoredLastScreenshotDate(conversationState.websiteId, getTodayDateString());\n}\n","export function getWidgetStyles(\n primaryColor: string,\n position: string,\n theme: \"light\" | \"dark\" = \"light\",\n): string {\n const isRight = position === \"bottom-right\";\n const isDark = theme === \"dark\";\n\n const colors = {\n bg: isDark ? \"#1f2937\" : \"white\",\n bgSecondary: isDark ? \"#374151\" : \"#f9fafb\",\n bgTertiary: isDark ? \"#4b5563\" : \"#f3f4f6\",\n text: isDark ? \"#f9fafb\" : \"#1f2937\",\n textSecondary: isDark ? \"#d1d5db\" : \"#6b7280\",\n textMuted: isDark ? \"#9ca3af\" : \"#9ca3af\",\n border: isDark ? \"#374151\" : \"#e5e7eb\",\n shadow: isDark ? \"rgba(0, 0, 0, 0.4)\" : \"rgba(0, 0, 0, 0.15)\",\n };\n\n return `\n :host {\n all: initial;\n display: block;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;\n font-size: 14px;\n line-height: 1.5;\n color: ${colors.text};\n -webkit-text-size-adjust: 100%;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n }\n\n *, *::before, *::after {\n box-sizing: border-box;\n margin: 0;\n padding: 0;\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n color: inherit;\n }\n\n .tchao-container {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;\n font-size: 14px;\n line-height: 1.5;\n color: ${colors.text};\n position: fixed;\n bottom: 20px;\n ${isRight ? \"right: 20px;\" : \"left: 20px;\"}\n z-index: 2147483647;\n }\n\n .tchao-bubble {\n position: relative;\n width: 56px;\n height: 56px;\n border-radius: 50%;\n background: ${primaryColor};\n border: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n transition: transform 0.2s, box-shadow 0.2s;\n }\n\n .tchao-bubble:hover {\n transform: scale(1.05);\n box-shadow: 0 6px 16px rgba(0, 0, 0, 0.2);\n }\n\n .tchao-bubble svg {\n width: 28px;\n height: 28px;\n fill: white;\n }\n\n .tchao-unread-badge {\n position: absolute;\n top: -4px;\n right: -4px;\n min-width: 20px;\n height: 20px;\n padding: 0 6px;\n background: #ef4444;\n color: white;\n font-size: 11px;\n font-weight: 600;\n border-radius: 10px;\n display: flex;\n align-items: center;\n justify-content: center;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\n }\n\n .tchao-window {\n position: absolute;\n bottom: 70px;\n ${isRight ? \"right: 0;\" : \"left: 0;\"}\n width: 380px;\n height: 560px;\n background: ${colors.bg};\n border-radius: 16px;\n box-shadow: 0 8px 32px ${colors.shadow};\n display: flex;\n flex-direction: column;\n overflow: hidden;\n animation: tchao-slide-in 0.2s ease-out;\n }\n\n .tchao-window.hidden {\n display: none;\n }\n\n @keyframes tchao-slide-in {\n from {\n opacity: 0;\n transform: translateY(10px) scale(0.95);\n }\n to {\n opacity: 1;\n transform: translateY(0) scale(1);\n }\n }\n\n .tchao-header {\n padding: 16px 20px;\n background: ${primaryColor};\n color: white;\n display: flex;\n align-items: center;\n gap: 12px;\n }\n\n .tchao-header-avatar {\n width: 40px;\n height: 40px;\n border-radius: 50%;\n background: rgba(255, 255, 255, 0.2);\n display: flex;\n align-items: center;\n justify-content: center;\n overflow: hidden;\n }\n\n .tchao-header-avatar img {\n width: 100%;\n height: 100%;\n object-fit: cover;\n }\n\n .tchao-header-info {\n flex: 1;\n }\n\n .tchao-header-name-row {\n display: flex;\n align-items: center;\n gap: 8px;\n }\n\n .tchao-header-name {\n font-weight: 600;\n font-size: 16px;\n }\n\n .tchao-header-tagline {\n font-size: 12px;\n opacity: 0.9;\n }\n\n .tchao-header-status {\n display: flex;\n align-items: center;\n gap: 4px;\n font-size: 11px;\n font-weight: 500;\n padding: 3px 8px;\n border-radius: 9999px;\n background: rgba(255, 255, 255, 0.15);\n color: rgba(255, 255, 255, 0.9);\n }\n\n .tchao-header-status.online {\n background: rgba(34, 197, 94, 0.2);\n color: #4ade80;\n }\n\n .tchao-header-status.idle {\n background: rgba(234, 179, 8, 0.2);\n color: #facc15;\n }\n\n .tchao-header-status-dot {\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: rgba(255, 255, 255, 0.6);\n }\n\n .tchao-header-status.online .tchao-header-status-dot {\n background: #22c55e;\n }\n\n .tchao-header-status.idle .tchao-header-status-dot {\n background: #eab308;\n }\n\n .tchao-close {\n background: none;\n border: none;\n cursor: pointer;\n padding: 4px;\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 0.8;\n transition: opacity 0.2s;\n }\n\n .tchao-close:hover {\n opacity: 1;\n }\n\n .tchao-close svg {\n width: 20px;\n height: 20px;\n fill: white;\n }\n\n .tchao-maximize {\n background: none;\n border: none;\n cursor: pointer;\n padding: 4px;\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 0.8;\n transition: opacity 0.2s;\n }\n\n .tchao-maximize:hover {\n opacity: 1;\n }\n\n .tchao-maximize svg {\n width: 20px;\n height: 20px;\n fill: white;\n }\n\n .tchao-messages {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n padding: 16px;\n display: flex;\n flex-direction: column;\n gap: 12px;\n }\n\n .tchao-message {\n max-width: 80%;\n padding: 10px 14px;\n border-radius: 16px;\n word-wrap: break-word;\n }\n\n .tchao-message.visitor {\n align-self: flex-end;\n background: ${primaryColor};\n color: white;\n border-bottom-right-radius: 4px;\n }\n\n .tchao-message.agent,\n .tchao-message.ai {\n align-self: flex-start;\n background: ${colors.bgTertiary};\n color: ${colors.text};\n border-bottom-left-radius: 4px;\n }\n\n .tchao-message.ai {\n background: ${isDark ? \"#064e3b\" : \"#ecfdf5\"};\n }\n\n .tchao-message a {\n color: inherit;\n text-decoration: underline;\n cursor: pointer;\n transition: opacity 0.2s;\n }\n\n .tchao-message a:hover {\n opacity: 0.7;\n }\n\n .tchao-message-time {\n font-size: 10px;\n opacity: 0.7;\n margin-top: 4px;\n }\n\n .tchao-reactions {\n display: flex;\n flex-wrap: wrap;\n gap: 4px;\n margin-top: 4px;\n }\n\n .tchao-reactions {\n position: absolute;\n bottom: -10px;\n display: flex;\n align-items: center;\n gap: 2px;\n background: ${colors.bg};\n border-radius: 9999px;\n padding: 2px 4px;\n box-shadow: 0 4px 6px -1px ${colors.shadow}, 0 2px 4px -2px ${colors.shadow};\n border: 1px solid ${colors.border};\n }\n\n .tchao-message-group-visitor .tchao-reactions {\n left: 4px;\n }\n\n .tchao-message-group-agent .tchao-reactions {\n right: 4px;\n }\n\n .tchao-reaction {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 20px;\n height: 20px;\n border: none;\n background: transparent;\n cursor: pointer;\n font-size: 12px;\n border-radius: 50%;\n transition: transform 0.15s;\n }\n\n .tchao-reaction:hover {\n transform: scale(1.25);\n }\n\n .tchao-reaction-count {\n font-size: 10px;\n font-weight: 500;\n color: ${colors.textMuted};\n padding-right: 2px;\n padding-left: 1px;\n }\n\n .tchao-message-bubble-wrapper {\n position: relative;\n }\n\n .tchao-message-row {\n position: relative;\n }\n\n .tchao-message-actions {\n position: absolute;\n top: 50%;\n transform: translateY(-50%);\n display: flex;\n align-items: center;\n gap: 2px;\n opacity: 0;\n transition: opacity 0.15s;\n pointer-events: none;\n }\n\n .tchao-message-row:hover .tchao-message-actions {\n opacity: 1;\n pointer-events: auto;\n }\n\n .tchao-message-group-visitor .tchao-message-actions {\n left: -52px;\n flex-direction: row;\n }\n\n .tchao-message-group-agent .tchao-message-actions {\n right: -52px;\n flex-direction: row-reverse;\n }\n\n .tchao-message-action-btn {\n width: 24px;\n height: 24px;\n border-radius: 4px;\n background: transparent;\n border: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: background 0.15s;\n position: relative;\n }\n\n .tchao-message-action-btn:hover {\n background: ${isDark ? \"rgba(255, 255, 255, 0.1)\" : \"rgba(0, 0, 0, 0.05)\"};\n }\n\n .tchao-message-action-btn svg {\n width: 14px;\n height: 14px;\n fill: ${colors.textMuted};\n }\n\n .tchao-reaction-picker {\n position: absolute;\n bottom: calc(100% + 4px);\n left: 50%;\n transform: translateX(-50%);\n background: ${colors.bg};\n border-radius: 8px;\n box-shadow: 0 4px 12px ${colors.shadow};\n padding: 4px;\n display: flex;\n gap: 2px;\n z-index: 10;\n }\n\n .tchao-reaction-picker.hidden {\n display: none;\n }\n\n .tchao-reaction-picker-btn {\n width: 28px;\n height: 28px;\n border: none;\n background: transparent;\n cursor: pointer;\n font-size: 16px;\n border-radius: 4px;\n transition: background 0.15s;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .tchao-reaction-picker-btn:hover {\n background: ${colors.bgTertiary};\n }\n\n .tchao-message-dropdown {\n position: absolute;\n top: calc(100% + 4px);\n right: 0;\n background: ${colors.bg};\n border-radius: 8px;\n box-shadow: 0 4px 12px ${colors.shadow};\n min-width: 120px;\n z-index: 10;\n overflow: hidden;\n }\n\n .tchao-message-dropdown.hidden {\n display: none;\n }\n\n .tchao-dropdown-item {\n display: flex;\n align-items: center;\n gap: 8px;\n width: 100%;\n padding: 8px 12px;\n border: none;\n background: none;\n cursor: pointer;\n font-size: 13px;\n color: ${colors.text};\n text-align: left;\n transition: background 0.15s;\n }\n\n .tchao-dropdown-item:hover {\n background: ${colors.bgTertiary};\n }\n\n .tchao-dropdown-item svg {\n width: 14px;\n height: 14px;\n fill: ${colors.textSecondary};\n }\n\n .tchao-toast {\n position: fixed;\n bottom: 100px;\n left: 50%;\n transform: translateX(-50%);\n background: #1f2937;\n color: white;\n padding: 8px 14px;\n border-radius: 6px;\n font-size: 13px;\n z-index: 2147483647;\n animation: tchao-toast-in 0.2s ease-out;\n }\n\n @keyframes tchao-toast-in {\n from {\n opacity: 0;\n transform: translateX(-50%) translateY(10px);\n }\n to {\n opacity: 1;\n transform: translateX(-50%) translateY(0);\n }\n }\n\n .tchao-message-content {\n display: flex;\n flex-direction: column;\n gap: 8px;\n }\n\n .tchao-message-image {\n max-width: 100%;\n max-height: 200px;\n border-radius: 12px;\n cursor: pointer;\n object-fit: cover;\n transition: opacity 0.2s;\n }\n\n .tchao-message-image:hover {\n opacity: 0.9;\n }\n\n .tchao-message-with-avatar {\n display: flex;\n gap: 8px;\n align-items: flex-start;\n }\n\n .tchao-message-avatar {\n width: 28px;\n height: 28px;\n border-radius: 50%;\n background: rgba(0, 0, 0, 0.1);\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n overflow: hidden;\n }\n\n .tchao-message-avatar img {\n width: 100%;\n height: 100%;\n object-fit: cover;\n }\n\n .tchao-message-avatar svg {\n width: 16px;\n height: 16px;\n fill: #6b7280;\n }\n\n .tchao-message-group {\n display: flex;\n gap: 8px;\n align-items: flex-end;\n }\n\n .tchao-message-group-agent {\n flex-direction: row;\n }\n\n .tchao-message-group-visitor {\n flex-direction: row-reverse;\n }\n\n .tchao-bubbles-container {\n display: flex;\n flex-direction: column;\n gap: 2px;\n max-width: 80%;\n }\n\n .tchao-message-group-agent .tchao-bubbles-container {\n align-items: flex-start;\n }\n\n .tchao-message-group-visitor .tchao-bubbles-container {\n align-items: flex-end;\n }\n\n .tchao-message-group .tchao-message {\n max-width: 100%;\n }\n\n .tchao-message-group-agent .tchao-message {\n border-bottom-left-radius: 4px;\n }\n\n .tchao-message-group-agent .tchao-message:first-child {\n border-top-left-radius: 16px;\n border-bottom-left-radius: 4px;\n }\n\n .tchao-message-group-agent .tchao-message:last-of-type {\n border-bottom-left-radius: 16px;\n }\n\n .tchao-message-group-visitor .tchao-message {\n border-bottom-right-radius: 4px;\n }\n\n .tchao-message-group-visitor .tchao-message:first-child {\n border-top-right-radius: 16px;\n border-bottom-right-radius: 4px;\n }\n\n .tchao-message-group-visitor .tchao-message:last-of-type {\n border-bottom-right-radius: 16px;\n }\n\n .tchao-group-time {\n font-size: 10px;\n color: #9ca3af;\n margin-top: 4px;\n }\n\n .tchao-message-group-visitor .tchao-group-time {\n text-align: right;\n }\n\n .tchao-typing-indicator {\n display: flex;\n gap: 8px;\n align-items: flex-start;\n padding: 4px 0;\n }\n\n .tchao-typing-bubble {\n display: flex;\n align-items: center;\n gap: 4px;\n padding: 8px 12px;\n background: ${colors.bgTertiary};\n border-radius: 12px;\n color: ${colors.textSecondary};\n font-size: 13px;\n }\n\n .tchao-typing-text {\n font-style: italic;\n }\n\n .tchao-typing-dots {\n display: flex;\n gap: 2px;\n }\n\n .tchao-typing-dots span {\n width: 4px;\n height: 4px;\n background: ${colors.textMuted};\n border-radius: 50%;\n animation: tchao-typing-bounce 1.4s infinite ease-in-out;\n }\n\n .tchao-typing-dots span:nth-child(1) {\n animation-delay: -0.32s;\n }\n\n .tchao-typing-dots span:nth-child(2) {\n animation-delay: -0.16s;\n }\n\n @keyframes tchao-typing-bounce {\n 0%, 80%, 100% {\n transform: scale(0.8);\n opacity: 0.5;\n }\n 40% {\n transform: scale(1);\n opacity: 1;\n }\n }\n\n .tchao-welcome {\n padding: 24px 20px;\n color: ${colors.textSecondary};\n }\n\n .tchao-welcome-card {\n background: ${colors.bgSecondary};\n border-radius: 16px;\n padding: 20px;\n }\n\n .tchao-welcome-quote {\n font-size: 16px;\n font-style: italic;\n color: ${colors.text};\n margin-bottom: 16px;\n }\n\n .tchao-welcome-agent {\n display: flex;\n align-items: center;\n gap: 12px;\n }\n\n .tchao-welcome-avatar {\n width: 40px;\n height: 40px;\n border-radius: 50%;\n background: ${colors.border};\n overflow: hidden;\n flex-shrink: 0;\n }\n\n .tchao-welcome-avatar img {\n width: 100%;\n height: 100%;\n object-fit: cover;\n }\n\n .tchao-welcome-info {\n flex: 1;\n }\n\n .tchao-welcome-name {\n font-size: 14px;\n font-weight: 600;\n color: ${colors.text};\n }\n\n .tchao-welcome-name span {\n font-weight: 400;\n color: ${colors.textSecondary};\n }\n\n .tchao-welcome-status {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 13px;\n color: #10b981;\n }\n\n .tchao-welcome-status.idle {\n color: #eab308;\n }\n\n .tchao-welcome-status.away {\n color: #9ca3af;\n }\n\n .tchao-welcome-status-dot {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n background: #10b981;\n }\n\n .tchao-welcome-status.idle .tchao-welcome-status-dot {\n background: #eab308;\n }\n\n .tchao-welcome-status.away .tchao-welcome-status-dot {\n background: #9ca3af;\n }\n\n .tchao-input-area {\n padding: 16px;\n border-top: 1px solid ${colors.border};\n background: ${colors.bg};\n display: flex;\n flex-direction: column;\n gap: 8px;\n }\n\n .tchao-input-row {\n display: flex;\n gap: 8px;\n align-items: flex-end;\n }\n\n .tchao-image-btn {\n width: 40px;\n height: 40px;\n border-radius: 50%;\n background: ${colors.bgTertiary};\n border: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: background 0.2s;\n flex-shrink: 0;\n }\n\n .tchao-image-btn:hover {\n background: ${colors.border};\n }\n\n .tchao-image-btn svg {\n width: 20px;\n height: 20px;\n fill: ${colors.textSecondary};\n }\n\n .tchao-mic-btn {\n width: 40px;\n height: 40px;\n border-radius: 50%;\n background: ${colors.bgTertiary};\n border: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: background 0.2s, transform 0.2s;\n flex-shrink: 0;\n }\n\n .tchao-mic-btn:hover {\n background: ${colors.border};\n }\n\n .tchao-mic-btn svg {\n width: 20px;\n height: 20px;\n fill: ${colors.textSecondary};\n }\n\n .tchao-mic-btn.recording {\n background: #ef4444;\n animation: pulse-recording 1.5s ease-in-out infinite;\n }\n\n .tchao-mic-btn.recording svg {\n fill: white;\n }\n\n @keyframes pulse-recording {\n 0%, 100% {\n transform: scale(1);\n box-shadow: 0 0 0 0 rgba(239, 68, 68, 0.4);\n }\n 50% {\n transform: scale(1.05);\n box-shadow: 0 0 0 8px rgba(239, 68, 68, 0);\n }\n }\n\n .tchao-emoji-container {\n position: relative;\n }\n\n .tchao-emoji-btn {\n width: 40px;\n height: 40px;\n border-radius: 50%;\n background: ${colors.bgTertiary};\n border: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: background 0.2s;\n flex-shrink: 0;\n }\n\n .tchao-emoji-btn:hover {\n background: ${colors.border};\n }\n\n .tchao-emoji-btn svg {\n width: 20px;\n height: 20px;\n fill: ${colors.textSecondary};\n }\n\n .tchao-emoji-picker {\n position: absolute;\n bottom: 48px;\n left: 0;\n background: ${colors.bg};\n border-radius: 12px;\n box-shadow: 0 4px 12px ${colors.shadow};\n padding: 8px;\n display: flex;\n gap: 4px;\n z-index: 10;\n }\n\n .tchao-emoji-picker.hidden {\n display: none;\n }\n\n .tchao-emoji-picker-btn {\n width: 36px;\n height: 36px;\n border: none;\n background: transparent;\n cursor: pointer;\n font-size: 20px;\n border-radius: 8px;\n transition: background 0.2s;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .tchao-emoji-picker-btn:hover {\n background: ${colors.bgTertiary};\n }\n\n .tchao-image-preview {\n display: flex;\n gap: 8px;\n padding: 8px;\n background: ${colors.bgSecondary};\n border-radius: 12px;\n }\n\n .tchao-image-preview-item {\n position: relative;\n display: inline-block;\n }\n\n .tchao-image-preview-item img {\n width: 60px;\n height: 60px;\n border-radius: 8px;\n object-fit: cover;\n }\n\n .tchao-image-preview-remove {\n position: absolute;\n top: -6px;\n right: -6px;\n width: 20px;\n height: 20px;\n border-radius: 50%;\n background: #ef4444;\n border: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .tchao-image-preview-remove svg {\n width: 12px;\n height: 12px;\n fill: white;\n }\n\n .tchao-drag-over {\n position: relative;\n }\n\n .tchao-drag-over::after {\n content: 'Drop image here';\n position: absolute;\n inset: 0;\n background: rgba(99, 102, 241, 0.9);\n color: white;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 16px;\n font-weight: 500;\n z-index: 100;\n border-radius: 16px;\n pointer-events: none;\n }\n\n .tchao-drop-error {\n background: #ef4444;\n color: white;\n padding: 8px 16px;\n border-radius: 8px;\n text-align: center;\n margin: 8px;\n font-size: 13px;\n animation: tchao-fade-in 0.2s ease;\n }\n\n @keyframes tchao-fade-in {\n from { opacity: 0; transform: translateY(-4px); }\n to { opacity: 1; transform: translateY(0); }\n }\n\n .tchao-image-modal {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.9);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 2147483647;\n padding: 20px;\n }\n\n .tchao-image-modal img {\n max-width: 100%;\n max-height: 100%;\n object-fit: contain;\n border-radius: 8px;\n }\n\n .tchao-image-modal-close {\n position: absolute;\n top: 20px;\n right: 20px;\n width: 40px;\n height: 40px;\n border-radius: 50%;\n background: rgba(255, 255, 255, 0.2);\n border: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .tchao-image-modal-close svg {\n width: 24px;\n height: 24px;\n fill: white;\n }\n\n .tchao-input {\n flex: 1;\n border: 1px solid ${colors.border};\n border-radius: 20px;\n padding: 10px 16px;\n font-size: 14px;\n resize: none;\n max-height: 100px;\n font-family: inherit;\n outline: none;\n transition: border-color 0.2s;\n overflow-y: auto;\n scrollbar-width: none;\n -ms-overflow-style: none;\n background: ${colors.bg};\n color: ${colors.text};\n }\n\n .tchao-input::-webkit-scrollbar {\n display: none;\n }\n\n .tchao-input:focus {\n border-color: ${primaryColor};\n }\n\n .tchao-send {\n width: 40px;\n height: 40px;\n border-radius: 50%;\n background: ${primaryColor};\n border: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: opacity 0.2s;\n }\n\n .tchao-send:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .tchao-send svg {\n width: 20px;\n height: 20px;\n fill: white;\n }\n\n .tchao-powered {\n text-align: center;\n padding: 8px;\n font-size: 11px;\n color: ${colors.textMuted};\n background: ${colors.bgSecondary};\n }\n\n .tchao-powered a {\n color: ${colors.textSecondary};\n text-decoration: none;\n }\n\n .tchao-powered a:hover {\n text-decoration: underline;\n }\n\n .tchao-email-popup {\n background: ${colors.bgSecondary};\n border-radius: 12px;\n padding: 8px;\n margin-bottom: 4px;\n position: relative;\n animation: tchao-slide-in 0.2s ease-out;\n }\n\n .tchao-email-popup-text {\n font-size: 13px;\n color: ${colors.text};\n margin-bottom: 4px;\n }\n\n .tchao-email-popup-row {\n display: flex;\n gap: 8px;\n }\n\n .tchao-email-popup-input {\n flex: 1;\n border: 1px solid ${colors.border};\n border-radius: 8px;\n padding: 8px 12px;\n font-size: 13px;\n outline: none;\n transition: border-color 0.2s;\n background: ${colors.bg};\n color: ${colors.text};\n }\n\n .tchao-email-popup-input:focus {\n border-color: ${primaryColor};\n }\n\n .tchao-email-popup-submit {\n background: ${primaryColor};\n color: white;\n border: none;\n border-radius: 8px;\n padding: 8px 16px;\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: opacity 0.2s;\n }\n\n .tchao-email-popup-submit:hover {\n opacity: 0.9;\n }\n\n .tchao-email-popup-submit:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .tchao-email-popup-close {\n position: absolute;\n top: 8px;\n right: 8px;\n background: none;\n border: none;\n cursor: pointer;\n padding: 4px;\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 0.5;\n transition: opacity 0.2s;\n }\n\n .tchao-email-popup-close:hover {\n opacity: 1;\n }\n\n .tchao-email-popup-close svg {\n width: 14px;\n height: 14px;\n fill: ${colors.textSecondary};\n }\n\n @media (max-width: 480px) {\n .tchao-window {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n width: 100%;\n height: 100%;\n border-radius: 0;\n }\n }\n\n .tchao-window.maximized {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: auto;\n width: 100%;\n max-width: 420px;\n height: 100%;\n border-radius: 0;\n animation: tchao-maximize-in 0.2s ease-out;\n }\n\n @keyframes tchao-maximize-in {\n from {\n opacity: 0.9;\n transform: translateX(20px);\n }\n to {\n opacity: 1;\n transform: translateX(0);\n }\n }\n\n @media (max-width: 480px) {\n .tchao-window.maximized {\n max-width: 100%;\n }\n }\n\n /* Name Line Launcher Style */\n .tchao-launcher-name-line {\n display: flex;\n align-items: center;\n gap: 12px;\n background: ${primaryColor};\n padding: 8px 16px 8px 8px;\n border-radius: 50px;\n cursor: pointer;\n box-shadow: 0 4px 12px ${colors.shadow};\n transition: transform 0.2s, box-shadow 0.2s;\n border: none;\n }\n\n .tchao-launcher-name-line:hover {\n transform: scale(1.02);\n box-shadow: 0 6px 16px rgba(0, 0, 0, 0.2);\n }\n\n .tchao-launcher-name-line-avatar {\n width: 48px;\n height: 48px;\n border-radius: 50%;\n background: rgba(255, 255, 255, 0.2);\n overflow: hidden;\n flex-shrink: 0;\n }\n\n .tchao-launcher-name-line-avatar img {\n width: 100%;\n height: 100%;\n object-fit: cover;\n }\n\n .tchao-launcher-name-line-info {\n display: flex;\n flex-direction: column;\n gap: 2px;\n color: white;\n }\n\n .tchao-launcher-name-line-name {\n display: flex;\n align-items: center;\n gap: 6px;\n font-weight: 600;\n font-size: 14px;\n }\n\n .tchao-launcher-name-line-status {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n background: #22c55e;\n }\n\n .tchao-launcher-name-line-role {\n font-size: 12px;\n opacity: 0.9;\n }\n\n .tchao-launcher-name-line-cta {\n background: white;\n color: ${primaryColor};\n border: none;\n border-radius: 20px;\n padding: 8px 16px;\n font-size: 13px;\n font-weight: 600;\n cursor: pointer;\n margin-left: 8px;\n transition: opacity 0.2s;\n }\n\n .tchao-launcher-name-line-cta:hover {\n opacity: 0.9;\n }\n\n /* Question CTA Launcher Style */\n .tchao-launcher-question-cta {\n display: flex;\n flex-direction: column;\n gap: 10px;\n background: ${colors.bg};\n padding: 14px;\n border-radius: 12px;\n box-shadow: 0 4px 16px ${colors.shadow};\n border: 1px solid ${colors.border};\n max-width: 224px;\n cursor: default;\n }\n\n .tchao-launcher-question-cta-header {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n gap: 8px;\n }\n\n .tchao-launcher-question-cta-text {\n flex: 1;\n }\n\n .tchao-launcher-question-cta-title {\n font-weight: 700;\n font-size: 14px;\n color: ${colors.text};\n margin-bottom: 2px;\n }\n\n .tchao-launcher-question-cta-subtitle {\n font-size: 12px;\n color: ${colors.textSecondary};\n }\n\n .tchao-launcher-question-cta-avatars {\n display: flex;\n align-items: center;\n flex-shrink: 0;\n }\n\n .tchao-launcher-question-cta-avatar {\n width: 28px;\n height: 28px;\n border-radius: 50%;\n background: ${colors.bgTertiary};\n overflow: hidden;\n margin-left: -6px;\n border: 2px solid ${colors.bg};\n }\n\n .tchao-launcher-question-cta-avatar:first-child {\n margin-left: 0;\n }\n\n .tchao-launcher-question-cta-avatar img {\n width: 100%;\n height: 100%;\n object-fit: cover;\n }\n\n .tchao-launcher-question-cta-icon {\n width: 28px;\n height: 28px;\n border-radius: 50%;\n background: ${primaryColor};\n display: flex;\n align-items: center;\n justify-content: center;\n margin-left: -6px;\n border: 2px solid ${colors.bg};\n }\n\n .tchao-launcher-question-cta-icon svg {\n width: 12px;\n height: 12px;\n fill: white;\n }\n\n .tchao-launcher-question-cta-buttons {\n display: flex;\n gap: 8px;\n }\n\n .tchao-launcher-question-cta-btn {\n flex: 1;\n padding: 8px 16px;\n border-radius: 9999px;\n font-size: 12px;\n font-weight: 600;\n cursor: pointer;\n transition: opacity 0.2s;\n border: none;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n }\n\n .tchao-launcher-question-cta-btn.primary {\n background: ${primaryColor};\n color: white;\n }\n\n .tchao-launcher-question-cta-btn.primary svg {\n width: 14px;\n height: 14px;\n fill: white;\n }\n\n .tchao-launcher-question-cta-btn.secondary {\n background: ${colors.bgTertiary};\n color: ${colors.text};\n }\n\n .tchao-launcher-question-cta-btn:hover {\n opacity: 0.9;\n }\n\n /* Bubble with badge - ensure it shows for all launcher types */\n .tchao-launcher-badge {\n position: absolute;\n top: -4px;\n right: -4px;\n min-width: 20px;\n height: 20px;\n padding: 0 6px;\n background: #ef4444;\n color: white;\n font-size: 11px;\n font-weight: 600;\n border-radius: 10px;\n display: flex;\n align-items: center;\n justify-content: center;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\n }\n `;\n}\n","import {\n agentPresenceStatus,\n conversationState,\n getResolvedTheme,\n websiteConfig,\n widgetConfig,\n} from \"./config\";\nimport { getWidgetStyles } from \"./styles\";\nimport type {\n Message,\n MessageReaction,\n PresenceStatus,\n WidgetStyle,\n} from \"./types\";\n\ninterface ISpeechRecognition extends EventTarget {\n continuous: boolean;\n interimResults: boolean;\n lang: string;\n onresult: ((event: ISpeechRecognitionEvent) => void) | null;\n onerror: ((event: ISpeechRecognitionErrorEvent) => void) | null;\n onend: (() => void) | null;\n onstart: (() => void) | null;\n start: () => void;\n stop: () => void;\n abort: () => void;\n}\n\ninterface ISpeechRecognitionEvent {\n resultIndex: number;\n results: ISpeechRecognitionResultList;\n}\n\ninterface ISpeechRecognitionResultList {\n [index: number]: ISpeechRecognitionResult;\n length: number;\n item: (index: number) => ISpeechRecognitionResult;\n}\n\ninterface ISpeechRecognitionResult {\n [index: number]: ISpeechRecognitionAlternative;\n isFinal: boolean;\n length: number;\n item: (index: number) => ISpeechRecognitionAlternative;\n}\n\ninterface ISpeechRecognitionAlternative {\n transcript: string;\n confidence: number;\n}\n\ninterface ISpeechRecognitionErrorEvent {\n error: string;\n message: string;\n}\n\ntype ISpeechRecognitionConstructor = new () => ISpeechRecognition;\n\ndeclare global {\n interface Window {\n SpeechRecognition?: ISpeechRecognitionConstructor;\n webkitSpeechRecognition?: ISpeechRecognitionConstructor;\n }\n}\n\nconst ICONS = {\n chat: `<svg viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M20 2H4c-1.1 0-2 .9-2 2v18l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm0 14H6l-2 2V4h16v12z\"/></svg>`,\n close: `<svg viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z\"/></svg>`,\n send: `<svg viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M2.01 21L23 12 2.01 3 2 10l15 2-15 2z\"/></svg>`,\n image: `<svg viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M21 19V5c0-1.1-.9-2-2-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2zM8.5 13.5l2.5 3.01L14.5 12l4.5 6H5l3.5-4.5z\"/></svg>`,\n maximize: `<svg viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z\"/></svg>`,\n minimize: `<svg viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M5 16h3v3h2v-5H5v2zm3-8H5v2h5V5H8v3zm6 11h2v-3h3v-2h-5v5zm2-11V5h-2v5h5V8h-3z\"/></svg>`,\n emoji: `<svg viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zm3.5-9c.83 0 1.5-.67 1.5-1.5S16.33 8 15.5 8 14 8.67 14 9.5s.67 1.5 1.5 1.5zm-7 0c.83 0 1.5-.67 1.5-1.5S9.33 8 8.5 8 7 8.67 7 9.5 7.67 11 8.5 11zm3.5 6.5c2.33 0 4.31-1.46 5.11-3.5H6.89c.8 2.04 2.78 3.5 5.11 3.5z\"/></svg>`,\n smile: `<svg viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zm3.5-9c.83 0 1.5-.67 1.5-1.5S16.33 8 15.5 8 14 8.67 14 9.5s.67 1.5 1.5 1.5zm-7 0c.83 0 1.5-.67 1.5-1.5S9.33 8 8.5 8 7 8.67 7 9.5 7.67 11 8.5 11zm3.5 6.5c2.33 0 4.31-1.46 5.11-3.5H6.89c.8 2.04 2.78 3.5 5.11 3.5z\"/></svg>`,\n more: `<svg viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M6 10c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm12 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm-6 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z\"/></svg>`,\n copy: `<svg viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z\"/></svg>`,\n mic: `<svg viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M12 14c1.66 0 3-1.34 3-3V5c0-1.66-1.34-3-3-3S9 3.34 9 5v6c0 1.66 1.34 3 3 3zm-1-9c0-.55.45-1 1-1s1 .45 1 1v6c0 .55-.45 1-1 1s-1-.45-1-1V5zm6 6c0 2.76-2.24 5-5 5s-5-2.24-5-5H5c0 3.53 2.61 6.43 6 6.92V21h2v-3.08c3.39-.49 6-3.39 6-6.92h-2z\"/></svg>`,\n} as const;\n\nconst WIDGET_EMOJIS = [\"👍\", \"❤️\", \"😂\", \"😮\", \"😢\"] as const;\n\nconst URL_REGEX =\n /\\b(https?:\\/\\/[^\\s<>[\\]{}|\\\\^`\"']+|www\\.[^\\s<>[\\]{}|\\\\^`\"']+\\.[^\\s<>[\\]{}|\\\\^`\"']+)/gi;\n\nfunction cleanUrl(url: string): string {\n return url.replace(/[.,;:!?)]+$/, \"\");\n}\n\nfunction linkifyHtml(text: string): string {\n const div = document.createElement(\"div\");\n div.textContent = text;\n const escaped = div.innerHTML;\n return escaped.replace(URL_REGEX, (match) => {\n const url = cleanUrl(match);\n const trailing = match.slice(url.length);\n const href = url.startsWith(\"http\") ? url : `https://${url}`;\n return `<a href=\"${href}\" target=\"_blank\" rel=\"noopener noreferrer\">${url}</a>${trailing}`;\n });\n}\n\ntype UICallbacks = {\n onSend: (content: string, imageUrl?: string | null) => void;\n onInput: (content: string) => void;\n onToggle: () => void;\n onMaximize: () => void;\n onImageSelect?: (file: File) => Promise<string | null>;\n onEmailSubmit?: (email: string) => Promise<void>;\n onEmailDismiss?: () => void;\n onReaction?: (messageId: string, emoji: string) => Promise<void>;\n};\n\nclass ChatWidgetUI {\n private shadowRoot: ShadowRoot | null = null;\n private container: HTMLDivElement | null = null;\n private elements = {\n messagesContainer: null as HTMLDivElement | null,\n inputElement: null as HTMLTextAreaElement | null,\n imagePreviewContainer: null as HTMLDivElement | null,\n emailPopupContainer: null as HTMLDivElement | null,\n typingIndicator: null as HTMLDivElement | null,\n honeypotInput: null as HTMLInputElement | null,\n unreadBadge: null as HTMLSpanElement | null,\n micButton: null as HTMLButtonElement | null,\n };\n private pendingImageUrl: string | null = null;\n private callbacks: UICallbacks | null = null;\n private readonly speechState: {\n recognition: ISpeechRecognition | null;\n isRecording: boolean;\n } = { recognition: null, isRecording: false };\n\n create(callbacks: UICallbacks): void {\n this.callbacks = callbacks;\n this.container = document.createElement(\"div\");\n this.container.id = \"tchao-widget\";\n document.body.appendChild(this.container);\n\n this.shadowRoot = this.container.attachShadow({ mode: \"closed\" });\n\n const theme = getResolvedTheme();\n const style = document.createElement(\"style\");\n style.textContent = getWidgetStyles(\n widgetConfig.primaryColor ?? \"#6366f1\",\n widgetConfig.position ?? \"bottom-right\",\n theme,\n );\n this.shadowRoot.appendChild(style);\n\n const wrapper = document.createElement(\"div\");\n wrapper.className = \"tchao-container\";\n this.shadowRoot.appendChild(wrapper);\n\n const widgetStyle = (widgetConfig.widgetStyle ?? \"bubble\") as WidgetStyle;\n this.renderLauncher(wrapper, callbacks.onToggle, widgetStyle);\n this.renderWindow(wrapper, callbacks);\n }\n\n destroy(): void {\n this.speechState.recognition?.abort();\n this.container?.remove();\n this.container = null;\n this.shadowRoot = null;\n this.elements = {\n messagesContainer: null,\n inputElement: null,\n imagePreviewContainer: null,\n emailPopupContainer: null,\n typingIndicator: null,\n honeypotInput: null,\n unreadBadge: null,\n micButton: null,\n };\n this.pendingImageUrl = null;\n this.callbacks = null;\n }\n\n setWindowVisible(visible: boolean): void {\n if (!this.shadowRoot) return;\n const window = this.shadowRoot.querySelector(\".tchao-window\");\n window?.classList.toggle(\"hidden\", !visible);\n if (visible) {\n this.elements.inputElement?.focus();\n const container = this.elements.messagesContainer;\n if (container) {\n requestAnimationFrame(() => {\n requestAnimationFrame(() => {\n container.scrollTop = container.scrollHeight;\n });\n });\n }\n }\n }\n\n setMaximized(maximized: boolean): void {\n if (!this.shadowRoot) return;\n const window = this.shadowRoot.querySelector(\".tchao-window\");\n const maximizeBtn = this.shadowRoot.querySelector(\".tchao-maximize\");\n window?.classList.toggle(\"maximized\", maximized);\n if (maximizeBtn) {\n maximizeBtn.innerHTML = maximized ? ICONS.minimize : ICONS.maximize;\n maximizeBtn.setAttribute(\n \"aria-label\",\n maximized ? \"Minimize chat\" : \"Maximize chat\",\n );\n }\n }\n\n appendMessage(message: Message): void {\n const container = this.elements.messagesContainer;\n if (!container) return;\n\n container.querySelector(\".tchao-welcome\")?.remove();\n\n const isAgent =\n message.senderType === \"AGENT\" || message.senderType === \"AI\";\n const isVisitor = message.senderType === \"VISITOR\";\n\n const lastGroup = container.querySelector(\n \".tchao-message-group:last-child\",\n ) as HTMLElement | null;\n const lastGroupIsAgent = lastGroup?.classList.contains(\n \"tchao-message-group-agent\",\n );\n const lastGroupIsVisitor = lastGroup?.classList.contains(\n \"tchao-message-group-visitor\",\n );\n\n const canAppendToGroup =\n (isAgent && lastGroupIsAgent) || (isVisitor && lastGroupIsVisitor);\n\n if (canAppendToGroup && lastGroup) {\n const bubblesContainer = lastGroup.querySelector(\n \".tchao-bubbles-container\",\n );\n if (bubblesContainer) {\n const timeEl = bubblesContainer.querySelector(\".tchao-group-time\");\n if (timeEl) timeEl.remove();\n\n const row = document.createElement(\"div\");\n row.className = \"tchao-message-row\";\n\n const bubbleWrapper = document.createElement(\"div\");\n bubbleWrapper.className = \"tchao-message-bubble-wrapper\";\n\n const bubble = document.createElement(\"div\");\n bubble.dataset.messageId = message.id;\n bubble.className = `tchao-message ${message.senderType.toLowerCase()}`;\n if (message.status === \"sending\") {\n bubble.style.opacity = \"0.7\";\n }\n this.appendMessageContent(bubble, message, true);\n bubbleWrapper.appendChild(bubble);\n\n if (message.reactions && message.reactions.length > 0) {\n bubbleWrapper.appendChild(this.createReactionsDisplay(message));\n }\n\n row.appendChild(bubbleWrapper);\n row.appendChild(this.createMessageActions(message));\n\n bubblesContainer.appendChild(row);\n\n const newTimeEl = document.createElement(\"div\");\n newTimeEl.className = \"tchao-group-time\";\n newTimeEl.textContent = this.formatTime(message.timestamp);\n bubblesContainer.appendChild(newTimeEl);\n }\n } else {\n this.renderMessageGroup([message], container);\n }\n\n container.scrollTop = container.scrollHeight;\n }\n\n renderExistingMessages(messages: Message[]): void {\n const container = this.elements.messagesContainer;\n if (!container) return;\n\n container.innerHTML = \"\";\n\n if (messages.length === 0) {\n container.appendChild(this.createWelcomeScreen());\n return;\n }\n\n const groups = this.groupMessagesBySender(messages);\n groups.forEach((group) => this.renderMessageGroup(group, container));\n requestAnimationFrame(() => {\n requestAnimationFrame(() => {\n container.scrollTop = container.scrollHeight;\n });\n });\n }\n\n updateMessageStatus(\n messageId: string,\n status: \"sending\" | \"sent\" | \"failed\",\n ): void {\n const container = this.elements.messagesContainer;\n if (!container) return;\n\n const messageEl = container.querySelector(\n `[data-message-id=\"${messageId}\"]`,\n ) as HTMLElement | null;\n if (!messageEl) return;\n\n if (status === \"sent\") {\n messageEl.style.opacity = \"1\";\n } else if (status === \"failed\") {\n messageEl.style.opacity = \"1\";\n messageEl.style.borderColor = \"#ef4444\";\n }\n }\n\n showTypingIndicator(): void {\n const container = this.elements.messagesContainer;\n if (!container || this.elements.typingIndicator) return;\n\n const indicator = document.createElement(\"div\");\n indicator.className = \"tchao-typing-indicator\";\n indicator.appendChild(this.createAvatar());\n\n const bubble = document.createElement(\"div\");\n bubble.className = \"tchao-typing-bubble\";\n bubble.innerHTML = `\n <span class=\"tchao-typing-text\">is typing</span>\n <span class=\"tchao-typing-dots\">\n <span></span><span></span><span></span>\n </span>\n `;\n indicator.appendChild(bubble);\n\n this.elements.typingIndicator = indicator;\n container.appendChild(indicator);\n container.scrollTop = container.scrollHeight;\n }\n\n hideTypingIndicator(): void {\n this.elements.typingIndicator?.remove();\n this.elements.typingIndicator = null;\n }\n\n updateAgentPresenceUI(status: PresenceStatus): void {\n if (!this.shadowRoot) return;\n\n const statusTextMap: Record<PresenceStatus, string> = {\n online: \"Available now\",\n idle: \"Idle\",\n away: \"Away\",\n };\n const statusText = statusTextMap[status];\n\n this.updateStatusElement(\"#tchao-header-status\", status, statusText);\n this.updateStatusElement(\"#tchao-welcome-status\", status, statusText);\n }\n\n showEmailPopup(): void {\n if (this.elements.emailPopupContainer) {\n this.elements.emailPopupContainer.style.display = \"block\";\n }\n }\n\n hideEmailPopup(): void {\n if (this.elements.emailPopupContainer) {\n this.elements.emailPopupContainer.style.display = \"none\";\n }\n }\n\n getHoneypotValue(): string {\n return this.elements.honeypotInput?.value ?? \"\";\n }\n\n updateUnreadBadge(count: number): void {\n if (!this.elements.unreadBadge) return;\n\n if (count > 0) {\n this.elements.unreadBadge.textContent =\n count > 99 ? \"99+\" : String(count);\n this.elements.unreadBadge.style.display = \"flex\";\n } else {\n this.elements.unreadBadge.style.display = \"none\";\n }\n }\n\n updateMessageReactions(\n messageId: string,\n reactions: MessageReaction[],\n ): void {\n const container = this.elements.messagesContainer;\n if (!container) return;\n\n const messageEl = container.querySelector(\n `[data-message-id=\"${messageId}\"]`,\n ) as HTMLElement | null;\n\n if (!messageEl) return;\n\n const bubbleWrapper = messageEl.parentElement;\n if (!bubbleWrapper?.classList.contains(\"tchao-message-bubble-wrapper\"))\n return;\n\n const existingReactions = bubbleWrapper.querySelector(\n \".tchao-reactions\",\n );\n if (existingReactions) {\n existingReactions.remove();\n }\n\n if (reactions.length > 0) {\n const totalCount = reactions.reduce(\n (acc, r) => acc + r.userIds.length,\n 0,\n );\n\n const reactionsContainer = document.createElement(\"div\");\n reactionsContainer.className = \"tchao-reactions\";\n reactionsContainer.dataset.messageReactions = messageId;\n\n reactions.forEach((reaction) => {\n const btn = document.createElement(\"button\");\n btn.type = \"button\";\n btn.className = \"tchao-reaction\";\n btn.textContent = reaction.emoji;\n btn.addEventListener(\"click\", () => {\n void this.callbacks?.onReaction?.(messageId, reaction.emoji);\n });\n reactionsContainer.appendChild(btn);\n });\n\n if (totalCount > 1) {\n const countEl = document.createElement(\"span\");\n countEl.className = \"tchao-reaction-count\";\n countEl.textContent = String(totalCount);\n reactionsContainer.appendChild(countEl);\n }\n\n bubbleWrapper.appendChild(reactionsContainer);\n }\n }\n\n updateMessageContent(messageId: string, content: string): void {\n const container = this.elements.messagesContainer;\n if (!container) return;\n\n const messageEl = container.querySelector(\n `[data-message-id=\"${messageId}\"]`,\n ) as HTMLElement | null;\n if (!messageEl) return;\n\n const textEl = messageEl.querySelector(\n \"div[style*='white-space']\",\n ) as HTMLElement | null;\n if (textEl) {\n textEl.innerHTML = linkifyHtml(content);\n }\n }\n\n updateMessageId(tempId: string, realId: string): void {\n const container = this.elements.messagesContainer;\n if (!container) return;\n\n const messageEl = container.querySelector(\n `[data-message-id=\"${tempId}\"]`,\n ) as HTMLElement | null;\n\n if (messageEl) {\n messageEl.dataset.messageId = realId;\n }\n }\n\n // --- Private Render Methods ---\n\n private groupMessagesBySender(messages: Message[]): Message[][] {\n const groups: Message[][] = [];\n let currentGroup: Message[] = [];\n\n for (const msg of messages) {\n if (\n currentGroup.length === 0 ||\n currentGroup[0].senderType === msg.senderType\n ) {\n currentGroup.push(msg);\n } else {\n groups.push(currentGroup);\n currentGroup = [msg];\n }\n }\n\n if (currentGroup.length > 0) {\n groups.push(currentGroup);\n }\n\n return groups;\n }\n\n private renderMessageGroup(group: Message[], container: HTMLElement): void {\n const firstMessage = group[0];\n const lastMessage = group[group.length - 1];\n const isAgent =\n firstMessage.senderType === \"AGENT\" || firstMessage.senderType === \"AI\";\n\n const groupWrapper = document.createElement(\"div\");\n groupWrapper.className = isAgent\n ? \"tchao-message-group tchao-message-group-agent\"\n : \"tchao-message-group tchao-message-group-visitor\";\n\n if (isAgent) {\n groupWrapper.appendChild(this.createAvatar());\n }\n\n const bubblesContainer = document.createElement(\"div\");\n bubblesContainer.className = \"tchao-bubbles-container\";\n\n group.forEach((message) => {\n const row = document.createElement(\"div\");\n row.className = \"tchao-message-row\";\n\n const bubbleWrapper = document.createElement(\"div\");\n bubbleWrapper.className = \"tchao-message-bubble-wrapper\";\n\n const bubble = document.createElement(\"div\");\n bubble.dataset.messageId = message.id;\n bubble.className = `tchao-message ${message.senderType.toLowerCase()}`;\n\n if (message.status === \"sending\") {\n bubble.style.opacity = \"0.7\";\n }\n\n this.appendMessageContent(bubble, message, true);\n bubbleWrapper.appendChild(bubble);\n\n if (message.reactions && message.reactions.length > 0) {\n bubbleWrapper.appendChild(this.createReactionsDisplay(message));\n }\n\n row.appendChild(bubbleWrapper);\n row.appendChild(this.createMessageActions(message));\n\n bubblesContainer.appendChild(row);\n });\n\n const timeEl = document.createElement(\"div\");\n timeEl.className = \"tchao-group-time\";\n timeEl.textContent = this.formatTime(lastMessage.timestamp);\n bubblesContainer.appendChild(timeEl);\n\n groupWrapper.appendChild(bubblesContainer);\n container.appendChild(groupWrapper);\n }\n\n private renderLauncher(\n parent: HTMLElement,\n onToggle: () => void,\n style: WidgetStyle,\n ): void {\n switch (style) {\n case \"name_line\":\n this.renderNameLineLauncher(parent, onToggle);\n break;\n case \"question_cta\":\n this.renderQuestionCtaLauncher(parent, onToggle);\n break;\n case \"bubble\":\n default:\n this.renderBubbleLauncher(parent, onToggle);\n break;\n }\n }\n\n private renderBubbleLauncher(\n parent: HTMLElement,\n onToggle: () => void,\n ): void {\n const bubble = document.createElement(\"button\");\n bubble.className = \"tchao-bubble\";\n bubble.innerHTML = ICONS.chat;\n bubble.setAttribute(\"aria-label\", \"Open chat\");\n bubble.addEventListener(\"click\", onToggle);\n\n this.elements.unreadBadge = document.createElement(\"span\");\n this.elements.unreadBadge.className = \"tchao-unread-badge\";\n this.elements.unreadBadge.style.display = \"none\";\n bubble.appendChild(this.elements.unreadBadge);\n\n parent.appendChild(bubble);\n }\n\n private renderNameLineLauncher(\n parent: HTMLElement,\n onToggle: () => void,\n ): void {\n const launcher = document.createElement(\"button\");\n launcher.className = \"tchao-launcher-name-line\";\n launcher.setAttribute(\"aria-label\", \"Open chat\");\n launcher.addEventListener(\"click\", onToggle);\n\n const avatar = document.createElement(\"div\");\n avatar.className = \"tchao-launcher-name-line-avatar\";\n if (websiteConfig?.agentImage) {\n const img = document.createElement(\"img\");\n img.src = websiteConfig.agentImage;\n img.alt = websiteConfig.agentName ?? \"Agent\";\n avatar.appendChild(img);\n }\n launcher.appendChild(avatar);\n\n const info = document.createElement(\"div\");\n info.className = \"tchao-launcher-name-line-info\";\n\n const nameRow = document.createElement(\"div\");\n nameRow.className = \"tchao-launcher-name-line-name\";\n\n const statusDot = document.createElement(\"span\");\n statusDot.className = \"tchao-launcher-name-line-status\";\n nameRow.appendChild(statusDot);\n\n const nameText = document.createTextNode(\n websiteConfig?.agentName ?? \"Support\",\n );\n nameRow.appendChild(nameText);\n info.appendChild(nameRow);\n\n if (websiteConfig?.agentRole) {\n const role = document.createElement(\"div\");\n role.className = \"tchao-launcher-name-line-role\";\n role.textContent = websiteConfig.agentRole;\n info.appendChild(role);\n }\n launcher.appendChild(info);\n\n const cta = document.createElement(\"span\");\n cta.className = \"tchao-launcher-name-line-cta\";\n cta.textContent = \"Chat\";\n launcher.appendChild(cta);\n\n this.elements.unreadBadge = document.createElement(\"span\");\n this.elements.unreadBadge.className = \"tchao-launcher-badge\";\n this.elements.unreadBadge.style.display = \"none\";\n launcher.appendChild(this.elements.unreadBadge);\n\n parent.appendChild(launcher);\n }\n\n private renderQuestionCtaLauncher(\n parent: HTMLElement,\n onToggle: () => void,\n ): void {\n const launcher = document.createElement(\"div\");\n launcher.className = \"tchao-launcher-question-cta\";\n\n const header = document.createElement(\"div\");\n header.className = \"tchao-launcher-question-cta-header\";\n\n const textSection = document.createElement(\"div\");\n textSection.className = \"tchao-launcher-question-cta-text\";\n\n const title = document.createElement(\"div\");\n title.className = \"tchao-launcher-question-cta-title\";\n title.textContent = \"Questions? Chat with us.\";\n textSection.appendChild(title);\n\n const subtitle = document.createElement(\"div\");\n subtitle.className = \"tchao-launcher-question-cta-subtitle\";\n subtitle.textContent =\n agentPresenceStatus === \"online\" ? \"We're online\" : \"We'll reply soon\";\n textSection.appendChild(subtitle);\n\n header.appendChild(textSection);\n\n const avatars = document.createElement(\"div\");\n avatars.className = \"tchao-launcher-question-cta-avatars\";\n\n if (websiteConfig?.agentImage) {\n const avatar = document.createElement(\"div\");\n avatar.className = \"tchao-launcher-question-cta-avatar\";\n const img = document.createElement(\"img\");\n img.src = websiteConfig.agentImage;\n img.alt = websiteConfig.agentName ?? \"Agent\";\n avatar.appendChild(img);\n avatars.appendChild(avatar);\n }\n\n const iconCircle = document.createElement(\"div\");\n iconCircle.className = \"tchao-launcher-question-cta-icon\";\n iconCircle.innerHTML = ICONS.chat;\n avatars.appendChild(iconCircle);\n\n header.appendChild(avatars);\n launcher.appendChild(header);\n\n const buttons = document.createElement(\"div\");\n buttons.className = \"tchao-launcher-question-cta-buttons\";\n\n const chatBtn = document.createElement(\"button\");\n chatBtn.className = \"tchao-launcher-question-cta-btn primary\";\n chatBtn.textContent = \"Start Chat\";\n chatBtn.addEventListener(\"click\", onToggle);\n buttons.appendChild(chatBtn);\n\n launcher.appendChild(buttons);\n\n this.elements.unreadBadge = document.createElement(\"span\");\n this.elements.unreadBadge.className = \"tchao-launcher-badge\";\n this.elements.unreadBadge.style.display = \"none\";\n launcher.appendChild(this.elements.unreadBadge);\n\n parent.appendChild(launcher);\n }\n\n private renderWindow(parent: HTMLElement, callbacks: UICallbacks): void {\n const window = document.createElement(\"div\");\n window.className = \"tchao-window hidden\";\n window.setAttribute(\"role\", \"dialog\");\n window.setAttribute(\"aria-label\", \"Chat window\");\n\n this.renderHeader(window, callbacks.onToggle, callbacks.onMaximize);\n this.renderMessages(window);\n this.renderInputArea(window, callbacks);\n this.renderPoweredBy(window);\n this.setupDragDrop(window, callbacks);\n\n parent.appendChild(window);\n }\n\n private renderHeader(\n parent: HTMLElement,\n onClose: () => void,\n onMaximize: () => void,\n ): void {\n const header = document.createElement(\"div\");\n header.className = \"tchao-header\";\n\n header.appendChild(this.createAvatar(\"tchao-header-avatar\"));\n\n const info = document.createElement(\"div\");\n info.className = \"tchao-header-info\";\n\n const nameRow = document.createElement(\"div\");\n nameRow.className = \"tchao-header-name-row\";\n\n const name = document.createElement(\"div\");\n name.className = \"tchao-header-name\";\n name.textContent =\n websiteConfig?.agentName ?? websiteConfig?.name ?? \"Support\";\n nameRow.appendChild(name);\n\n nameRow.appendChild(\n this.createStatusBadge(\"tchao-header-status\", agentPresenceStatus),\n );\n info.appendChild(nameRow);\n\n if (websiteConfig?.agentRole) {\n const tagline = document.createElement(\"div\");\n tagline.className = \"tchao-header-tagline\";\n tagline.textContent = websiteConfig.agentRole;\n info.appendChild(tagline);\n }\n header.appendChild(info);\n\n const maximizeBtn = document.createElement(\"button\");\n maximizeBtn.className = \"tchao-maximize\";\n maximizeBtn.innerHTML = ICONS.maximize;\n maximizeBtn.setAttribute(\"aria-label\", \"Maximize chat\");\n maximizeBtn.addEventListener(\"click\", onMaximize);\n header.appendChild(maximizeBtn);\n\n const closeBtn = document.createElement(\"button\");\n closeBtn.className = \"tchao-close\";\n closeBtn.innerHTML = ICONS.close;\n closeBtn.setAttribute(\"aria-label\", \"Close chat\");\n closeBtn.addEventListener(\"click\", onClose);\n header.appendChild(closeBtn);\n\n parent.appendChild(header);\n }\n\n private renderMessages(parent: HTMLElement): void {\n this.elements.messagesContainer = document.createElement(\"div\");\n this.elements.messagesContainer.className = \"tchao-messages\";\n\n if (conversationState.messages.length === 0) {\n this.elements.messagesContainer.appendChild(this.createWelcomeScreen());\n } else {\n conversationState.messages.forEach((msg) => this.appendMessage(msg));\n }\n\n parent.appendChild(this.elements.messagesContainer);\n }\n\n private renderInputArea(parent: HTMLElement, callbacks: UICallbacks): void {\n const inputArea = document.createElement(\"div\");\n inputArea.className = \"tchao-input-area\";\n\n // Email popup\n this.elements.emailPopupContainer = document.createElement(\"div\");\n this.elements.emailPopupContainer.className = \"tchao-email-popup\";\n this.elements.emailPopupContainer.style.display = \"none\";\n this.renderEmailPopupContent(this.elements.emailPopupContainer, callbacks);\n inputArea.appendChild(this.elements.emailPopupContainer);\n\n // Image preview\n this.elements.imagePreviewContainer = document.createElement(\"div\");\n this.elements.imagePreviewContainer.className = \"tchao-image-preview\";\n this.elements.imagePreviewContainer.style.display = \"none\";\n inputArea.appendChild(this.elements.imagePreviewContainer);\n\n // Honeypot field (hidden from humans, bots will fill it)\n this.elements.honeypotInput = document.createElement(\"input\");\n this.elements.honeypotInput.type = \"text\";\n this.elements.honeypotInput.name = \"website\";\n this.elements.honeypotInput.autocomplete = \"one-time-code\";\n this.elements.honeypotInput.tabIndex = -1;\n this.elements.honeypotInput.setAttribute(\"aria-hidden\", \"true\");\n this.elements.honeypotInput.style.cssText =\n \"position: absolute; left: -9999px; top: -9999px; opacity: 0; pointer-events: none;\";\n inputArea.appendChild(this.elements.honeypotInput);\n\n // Input row\n const inputRow = document.createElement(\"div\");\n inputRow.className = \"tchao-input-row\";\n\n const fileInput = document.createElement(\"input\");\n fileInput.type = \"file\";\n fileInput.accept = \"image/*\";\n fileInput.style.display = \"none\";\n fileInput.addEventListener(\"change\", async () =>\n this.handleFileSelect(fileInput, callbacks),\n );\n inputRow.appendChild(fileInput);\n\n const imageBtn = document.createElement(\"button\");\n imageBtn.className = \"tchao-image-btn\";\n imageBtn.innerHTML = ICONS.image;\n imageBtn.setAttribute(\"aria-label\", \"Attach image\");\n imageBtn.addEventListener(\"click\", () => fileInput.click());\n inputRow.appendChild(imageBtn);\n\n this.elements.inputElement = document.createElement(\"textarea\");\n this.elements.inputElement.className = \"tchao-input\";\n this.elements.inputElement.placeholder = \"Type a message...\";\n this.elements.inputElement.rows = 1;\n this.elements.inputElement.addEventListener(\"input\", () => {\n callbacks.onInput(this.elements.inputElement?.value ?? \"\");\n this.autoResizeTextarea();\n });\n this.elements.inputElement.addEventListener(\"keydown\", (e) => {\n if (e.key === \"Enter\" && !e.shiftKey) {\n e.preventDefault();\n this.handleSend(callbacks.onSend);\n }\n });\n inputRow.appendChild(this.elements.inputElement);\n\n if (this.isSpeechRecognitionSupported()) {\n this.elements.micButton = document.createElement(\"button\");\n this.elements.micButton.className = \"tchao-mic-btn\";\n this.elements.micButton.innerHTML = ICONS.mic;\n this.elements.micButton.setAttribute(\"aria-label\", \"Voice input\");\n this.elements.micButton.addEventListener(\"click\", () =>\n this.toggleSpeechRecognition(),\n );\n inputRow.appendChild(this.elements.micButton);\n }\n\n const sendBtn = document.createElement(\"button\");\n sendBtn.className = \"tchao-send\";\n sendBtn.innerHTML = ICONS.send;\n sendBtn.setAttribute(\"aria-label\", \"Send message\");\n sendBtn.addEventListener(\"click\", () => this.handleSend(callbacks.onSend));\n inputRow.appendChild(sendBtn);\n\n inputArea.appendChild(inputRow);\n parent.appendChild(inputArea);\n }\n\n private renderEmailPopupContent(\n parent: HTMLElement,\n callbacks: UICallbacks,\n ): void {\n const text = document.createElement(\"div\");\n text.className = \"tchao-email-popup-text\";\n text.textContent = \"Enter your email to receive notifications\";\n parent.appendChild(text);\n\n const row = document.createElement(\"div\");\n row.className = \"tchao-email-popup-row\";\n\n const input = document.createElement(\"input\");\n input.type = \"email\";\n input.className = \"tchao-email-popup-input\";\n input.placeholder = \"your@email.com\";\n row.appendChild(input);\n\n const submitBtn = document.createElement(\"button\");\n submitBtn.className = \"tchao-email-popup-submit\";\n submitBtn.textContent = \"Save\";\n\n const handleSubmit = async () => {\n const email = input.value.trim();\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n if (!emailRegex.test(email)) return;\n\n submitBtn.disabled = true;\n submitBtn.textContent = \"...\";\n\n try {\n await callbacks.onEmailSubmit?.(email);\n this.hideEmailPopup();\n } finally {\n submitBtn.disabled = false;\n submitBtn.textContent = \"Save\";\n }\n };\n\n input.addEventListener(\"keydown\", (e) => {\n if (e.key === \"Enter\") {\n e.preventDefault();\n void handleSubmit();\n }\n });\n\n submitBtn.addEventListener(\"click\", handleSubmit);\n row.appendChild(submitBtn);\n parent.appendChild(row);\n\n const closeBtn = document.createElement(\"button\");\n closeBtn.className = \"tchao-email-popup-close\";\n closeBtn.innerHTML = ICONS.close;\n closeBtn.addEventListener(\"click\", () => {\n callbacks.onEmailDismiss?.();\n this.hideEmailPopup();\n });\n parent.appendChild(closeBtn);\n }\n\n private renderPoweredBy(parent: HTMLElement): void {\n if (websiteConfig?.hidePoweredBy) return;\n const powered = document.createElement(\"div\");\n powered.className = \"tchao-powered\";\n powered.innerHTML = `Powered by <a href=\"https://tchao.app\" target=\"_blank\" rel=\"noopener\">Tchao</a>`;\n parent.appendChild(powered);\n }\n\n // --- Private Helper Methods ---\n\n private createAvatar(className = \"tchao-message-avatar\"): HTMLDivElement {\n const avatar = document.createElement(\"div\");\n avatar.className = className;\n\n if (websiteConfig?.agentImage) {\n const img = document.createElement(\"img\");\n img.src = websiteConfig.agentImage;\n img.alt = websiteConfig.agentName ?? \"Agent\";\n avatar.appendChild(img);\n } else {\n avatar.innerHTML = ICONS.chat;\n }\n\n return avatar;\n }\n\n private createReactionsDisplay(message: Message): HTMLDivElement {\n const reactionsContainer = document.createElement(\"div\");\n reactionsContainer.className = \"tchao-reactions\";\n reactionsContainer.dataset.messageReactions = message.id;\n\n const reactions = message.reactions ?? [];\n const totalCount = reactions.reduce((acc, r) => acc + r.userIds.length, 0);\n\n reactions.forEach((reaction) => {\n const btn = document.createElement(\"button\");\n btn.type = \"button\";\n btn.className = \"tchao-reaction\";\n btn.textContent = reaction.emoji;\n btn.addEventListener(\"click\", () => {\n void this.callbacks?.onReaction?.(message.id, reaction.emoji);\n });\n reactionsContainer.appendChild(btn);\n });\n\n if (totalCount > 1) {\n const countEl = document.createElement(\"span\");\n countEl.className = \"tchao-reaction-count\";\n countEl.textContent = String(totalCount);\n reactionsContainer.appendChild(countEl);\n }\n\n return reactionsContainer;\n }\n\n private createMessageActions(message: Message): HTMLDivElement {\n const actionsContainer = document.createElement(\"div\");\n actionsContainer.className = \"tchao-message-actions\";\n\n const reactionBtn = document.createElement(\"button\");\n reactionBtn.className = \"tchao-message-action-btn\";\n reactionBtn.innerHTML = ICONS.smile;\n reactionBtn.setAttribute(\"aria-label\", \"Add reaction\");\n\n const reactionPicker = document.createElement(\"div\");\n reactionPicker.className = \"tchao-reaction-picker hidden\";\n WIDGET_EMOJIS.forEach((emoji) => {\n const btn = document.createElement(\"button\");\n btn.type = \"button\";\n btn.className = \"tchao-reaction-picker-btn\";\n btn.textContent = emoji;\n btn.addEventListener(\"click\", (e) => {\n e.stopPropagation();\n reactionPicker.classList.add(\"hidden\");\n void this.callbacks?.onReaction?.(message.id, emoji);\n });\n reactionPicker.appendChild(btn);\n });\n\n reactionBtn.addEventListener(\"click\", (e) => {\n e.stopPropagation();\n this.closeAllPopovers();\n reactionPicker.classList.toggle(\"hidden\");\n });\n\n actionsContainer.appendChild(reactionBtn);\n actionsContainer.appendChild(reactionPicker);\n\n const moreBtn = document.createElement(\"button\");\n moreBtn.className = \"tchao-message-action-btn\";\n moreBtn.innerHTML = ICONS.more;\n moreBtn.setAttribute(\"aria-label\", \"More actions\");\n\n const dropdown = document.createElement(\"div\");\n dropdown.className = \"tchao-message-dropdown hidden\";\n\n const copyItem = document.createElement(\"button\");\n copyItem.className = \"tchao-dropdown-item\";\n copyItem.innerHTML = `${ICONS.copy}<span>Copy</span>`;\n copyItem.addEventListener(\"click\", (e) => {\n e.stopPropagation();\n dropdown.classList.add(\"hidden\");\n void navigator.clipboard.writeText(message.content);\n this.showToast(\"Message copied\");\n });\n dropdown.appendChild(copyItem);\n\n moreBtn.addEventListener(\"click\", (e) => {\n e.stopPropagation();\n this.closeAllPopovers();\n dropdown.classList.toggle(\"hidden\");\n });\n\n actionsContainer.appendChild(moreBtn);\n actionsContainer.appendChild(dropdown);\n\n return actionsContainer;\n }\n\n private closeAllPopovers(): void {\n if (!this.shadowRoot) return;\n this.shadowRoot\n .querySelectorAll(\".tchao-reaction-picker, .tchao-message-dropdown\")\n .forEach((el) => el.classList.add(\"hidden\"));\n }\n\n private showToast(message: string): void {\n if (!this.shadowRoot) return;\n\n const existing = this.shadowRoot.querySelector(\".tchao-toast\");\n if (existing) existing.remove();\n\n const toast = document.createElement(\"div\");\n toast.className = \"tchao-toast\";\n toast.textContent = message;\n this.shadowRoot.appendChild(toast);\n\n setTimeout(() => toast.remove(), 2000);\n }\n\n private createStatusBadge(\n id: string,\n status: PresenceStatus,\n ): HTMLDivElement {\n const statusTextMap: Record<PresenceStatus, string> = {\n online: \"Available now\",\n idle: \"Idle\",\n away: \"Away\",\n };\n\n const badge = document.createElement(\"div\");\n badge.className = `${id.replace(\"#\", \"\")} ${status}`;\n badge.id = id.replace(\"#\", \"\");\n\n const dot = document.createElement(\"span\");\n dot.className = `${id.replace(\"#\", \"\")}-dot`;\n badge.appendChild(dot);\n\n const text = document.createElement(\"span\");\n text.className = `${id.replace(\"#\", \"\")}-text`;\n text.textContent = statusTextMap[status];\n badge.appendChild(text);\n\n return badge;\n }\n\n private updateStatusElement(\n selector: string,\n status: PresenceStatus,\n text: string,\n ): void {\n const element = this.shadowRoot?.querySelector(\n selector,\n ) as HTMLElement | null;\n if (!element) return;\n\n const baseClass = selector.replace(\"#\", \"\");\n element.className = `${baseClass} ${status}`;\n\n const textEl = element.querySelector(\n `.${baseClass}-text`,\n ) as HTMLElement | null;\n if (textEl) {\n textEl.textContent = text;\n }\n }\n\n private createMessageBubble(\n message: Message,\n senderClass: string,\n ): HTMLDivElement {\n const msgEl = document.createElement(\"div\");\n msgEl.className = `tchao-message ${senderClass}`;\n this.appendMessageContent(msgEl, message);\n return msgEl;\n }\n\n private appendMessageContent(\n parent: HTMLElement,\n message: Message,\n hideTime = false,\n ): void {\n if (message.image) {\n const imageUrl = message.image;\n const img = document.createElement(\"img\");\n img.src = imageUrl;\n img.alt = \"Attached image\";\n img.className = \"tchao-message-image\";\n img.addEventListener(\"click\", () => this.showImageModal(imageUrl));\n parent.appendChild(img);\n }\n\n if (message.content && message.content !== \"📷\") {\n const text = document.createElement(\"div\");\n text.style.whiteSpace = \"pre-wrap\";\n text.innerHTML = linkifyHtml(message.content);\n parent.appendChild(text);\n }\n\n if (!hideTime) {\n const time = document.createElement(\"div\");\n time.className = \"tchao-message-time\";\n time.textContent = this.formatTime(message.timestamp);\n parent.appendChild(time);\n }\n }\n\n private createWelcomeScreen(): HTMLElement {\n const welcome = document.createElement(\"div\");\n welcome.className = \"tchao-welcome\";\n\n const card = document.createElement(\"div\");\n card.className = \"tchao-welcome-card\";\n\n const quote = document.createElement(\"div\");\n quote.className = \"tchao-welcome-quote\";\n const message =\n websiteConfig?.agentWelcomeMessage ??\n \"Hey there! Ask me anything, I'm here to help.\";\n quote.textContent = `\"${message}\"`;\n card.appendChild(quote);\n\n const agent = document.createElement(\"div\");\n agent.className = \"tchao-welcome-agent\";\n\n const avatar = document.createElement(\"div\");\n avatar.className = \"tchao-welcome-avatar\";\n if (websiteConfig?.agentImage) {\n const img = document.createElement(\"img\");\n img.src = websiteConfig.agentImage;\n img.alt = websiteConfig.agentName ?? \"Agent\";\n avatar.appendChild(img);\n }\n agent.appendChild(avatar);\n\n const info = document.createElement(\"div\");\n info.className = \"tchao-welcome-info\";\n\n const name = document.createElement(\"div\");\n name.className = \"tchao-welcome-name\";\n const agentName = websiteConfig?.agentName ?? \"Support\";\n const agentRole = websiteConfig?.agentRole;\n name.innerHTML = agentRole\n ? `${agentName} <span>- ${agentRole}</span>`\n : agentName;\n info.appendChild(name);\n\n info.appendChild(this.createWelcomeStatusBadge(agentPresenceStatus));\n\n agent.appendChild(info);\n card.appendChild(agent);\n welcome.appendChild(card);\n\n return welcome;\n }\n\n private createWelcomeStatusBadge(status: PresenceStatus): HTMLDivElement {\n const statusTextMap: Record<PresenceStatus, string> = {\n online: \"Available now\",\n idle: \"Idle\",\n away: \"Away\",\n };\n\n const statusEl = document.createElement(\"div\");\n statusEl.className = `tchao-welcome-status ${status}`;\n statusEl.id = \"tchao-welcome-status\";\n\n const dot = document.createElement(\"div\");\n dot.className = \"tchao-welcome-status-dot\";\n statusEl.appendChild(dot);\n\n const text = document.createElement(\"span\");\n text.className = \"tchao-welcome-status-text\";\n text.textContent = statusTextMap[status];\n statusEl.appendChild(text);\n\n return statusEl;\n }\n\n private showImageModal(imageUrl: string): void {\n if (!this.shadowRoot) return;\n\n const modal = document.createElement(\"div\");\n modal.className = \"tchao-image-modal\";\n\n const img = document.createElement(\"img\");\n img.src = imageUrl;\n img.alt = \"Full size image\";\n modal.appendChild(img);\n\n const closeBtn = document.createElement(\"button\");\n closeBtn.className = \"tchao-image-modal-close\";\n closeBtn.innerHTML = ICONS.close;\n closeBtn.addEventListener(\"click\", () => modal.remove());\n modal.appendChild(closeBtn);\n\n modal.addEventListener(\"click\", (e) => {\n if (e.target === modal) modal.remove();\n });\n\n this.shadowRoot.appendChild(modal);\n }\n\n private async handleFileSelect(\n fileInput: HTMLInputElement,\n callbacks: UICallbacks,\n ): Promise<void> {\n const file = fileInput.files?.[0];\n if (file && callbacks.onImageSelect) {\n this.showImagePreview(file);\n const url = await callbacks.onImageSelect(file);\n if (url) {\n this.pendingImageUrl = url;\n } else {\n this.clearImagePreview();\n }\n }\n fileInput.value = \"\";\n }\n\n private showImagePreview(file: File): void {\n const container = this.elements.imagePreviewContainer;\n if (!container) return;\n\n const reader = new FileReader();\n reader.onload = (e) => {\n container.innerHTML = \"\";\n container.style.display = \"flex\";\n\n const previewItem = document.createElement(\"div\");\n previewItem.className = \"tchao-image-preview-item\";\n\n const img = document.createElement(\"img\");\n img.src = e.target?.result as string;\n img.alt = \"Preview\";\n previewItem.appendChild(img);\n\n const removeBtn = document.createElement(\"button\");\n removeBtn.className = \"tchao-image-preview-remove\";\n removeBtn.innerHTML = ICONS.close;\n removeBtn.addEventListener(\"click\", () => this.clearImagePreview());\n previewItem.appendChild(removeBtn);\n\n container.appendChild(previewItem);\n };\n reader.readAsDataURL(file);\n }\n\n private clearImagePreview(): void {\n const container = this.elements.imagePreviewContainer;\n if (container) {\n container.innerHTML = \"\";\n container.style.display = \"none\";\n }\n this.pendingImageUrl = null;\n }\n\n private setupDragDrop(window: HTMLElement, callbacks: UICallbacks): void {\n let dragCounter = 0;\n\n window.addEventListener(\"dragenter\", (e) => {\n e.preventDefault();\n e.stopPropagation();\n dragCounter++;\n if (dragCounter === 1) {\n window.classList.add(\"tchao-drag-over\");\n }\n });\n\n window.addEventListener(\"dragleave\", (e) => {\n e.preventDefault();\n e.stopPropagation();\n dragCounter--;\n if (dragCounter === 0) {\n window.classList.remove(\"tchao-drag-over\");\n }\n });\n\n window.addEventListener(\"dragover\", (e) => {\n e.preventDefault();\n e.stopPropagation();\n });\n\n window.addEventListener(\"drop\", (e) => {\n e.preventDefault();\n e.stopPropagation();\n dragCounter = 0;\n window.classList.remove(\"tchao-drag-over\");\n\n const files = e.dataTransfer?.files;\n if (!files || files.length === 0) return;\n\n const file = files[0];\n void this.handleDroppedFile(file, callbacks);\n });\n }\n\n private async handleDroppedFile(\n file: File,\n callbacks: UICallbacks,\n ): Promise<void> {\n const MAX_SIZE = 2 * 1024 * 1024; // 2MB\n\n if (!file.type.startsWith(\"image/\")) {\n this.showDropError(\"Only images are allowed\");\n return;\n }\n\n if (file.size > MAX_SIZE) {\n this.showDropError(\"Image too large (max 2MB)\");\n return;\n }\n\n if (!callbacks.onImageSelect) return;\n\n this.showImagePreview(file);\n const url = await callbacks.onImageSelect(file);\n if (url) {\n this.pendingImageUrl = url;\n } else {\n this.clearImagePreview();\n }\n }\n\n private showDropError(message: string): void {\n const container = this.elements.messagesContainer;\n if (!container) return;\n\n const existing = container.querySelector(\".tchao-drop-error\");\n if (existing) existing.remove();\n\n const error = document.createElement(\"div\");\n error.className = \"tchao-drop-error\";\n error.textContent = message;\n container.appendChild(error);\n\n setTimeout(() => error.remove(), 3000);\n }\n\n private handleSend(\n onSend: (content: string, imageUrl?: string | null) => void,\n ): void {\n const input = this.elements.inputElement;\n if (!input) return;\n\n const content = input.value.trim();\n const imageUrl = this.pendingImageUrl;\n\n if (!content && !imageUrl) return;\n\n onSend(content || \"📷\", imageUrl);\n input.value = \"\";\n this.autoResizeTextarea();\n this.clearImagePreview();\n }\n\n private autoResizeTextarea(): void {\n const input = this.elements.inputElement;\n if (!input) return;\n input.style.height = \"auto\";\n input.style.height = `${Math.min(input.scrollHeight, 100)}px`;\n }\n\n private formatTime(timestamp: number): string {\n const date = new Date(timestamp);\n return date.toLocaleTimeString([], { hour: \"2-digit\", minute: \"2-digit\" });\n }\n\n private isSpeechRecognitionSupported(): boolean {\n return !!(window.SpeechRecognition || window.webkitSpeechRecognition);\n }\n\n private toggleSpeechRecognition(): void {\n if (this.speechState.isRecording) {\n this.stopSpeechRecognition();\n } else {\n this.startSpeechRecognition();\n }\n }\n\n private startSpeechRecognition(): void {\n const SpeechRecognitionAPI =\n window.SpeechRecognition || window.webkitSpeechRecognition;\n if (!SpeechRecognitionAPI) return;\n\n const recognition = new SpeechRecognitionAPI();\n recognition.continuous = false;\n recognition.interimResults = true;\n recognition.lang = navigator.language || \"en-US\";\n\n recognition.onstart = () => {\n this.speechState.isRecording = true;\n this.elements.micButton?.classList.add(\"recording\");\n };\n\n recognition.onresult = (event: ISpeechRecognitionEvent) => {\n let transcript = \"\";\n for (let i = event.resultIndex; i < event.results.length; i++) {\n transcript += event.results[i][0].transcript;\n }\n\n if (this.elements.inputElement) {\n const currentValue = this.elements.inputElement.value;\n const lastFinalIndex = currentValue.lastIndexOf(\"█\");\n const baseText =\n lastFinalIndex >= 0\n ? currentValue.substring(0, lastFinalIndex)\n : currentValue;\n\n if (event.results[event.results.length - 1].isFinal) {\n this.elements.inputElement.value = `${baseText + transcript} `;\n } else {\n this.elements.inputElement.value = `${baseText + transcript}█`;\n }\n this.autoResizeTextarea();\n this.callbacks?.onInput(this.elements.inputElement.value);\n }\n };\n\n recognition.onerror = (event: ISpeechRecognitionErrorEvent) => {\n const errorMessages: Record<string, string> = {\n \"network\": \"Voice service unavailable - try disabling ad blocker\",\n \"not-allowed\": \"Microphone access denied\",\n \"service-not-allowed\": \"Speech service not available\",\n \"audio-capture\": \"No microphone found\",\n \"language-not-supported\": \"Language not supported\",\n };\n\n if (event.error !== \"no-speech\" && event.error !== \"aborted\") {\n const message = errorMessages[event.error] ?? `Voice input error: ${event.error}`;\n this.showToast(message);\n }\n this.stopSpeechRecognition();\n };\n\n recognition.onend = () => {\n if (this.elements.inputElement) {\n this.elements.inputElement.value =\n this.elements.inputElement.value.replace(/█/g, \"\");\n }\n this.speechState.isRecording = false;\n this.elements.micButton?.classList.remove(\"recording\");\n };\n\n this.speechState.recognition = recognition;\n\n try {\n recognition.start();\n } catch {\n this.showToast(\"Could not start voice input\");\n }\n }\n\n private stopSpeechRecognition(): void {\n if (this.speechState.recognition) {\n this.speechState.recognition.stop();\n this.speechState.recognition = null;\n }\n this.speechState.isRecording = false;\n this.elements.micButton?.classList.remove(\"recording\");\n }\n}\n\n// Singleton instance\nconst widgetUI = new ChatWidgetUI();\n\n// Public API (backwards compatible exports)\nexport function createWidget(callbacks: UICallbacks): void {\n widgetUI.create(callbacks);\n}\n\nexport function destroyWidget(): void {\n widgetUI.destroy();\n}\n\nexport function setWindowVisible(visible: boolean): void {\n widgetUI.setWindowVisible(visible);\n}\n\nexport function appendMessage(message: Message): void {\n widgetUI.appendMessage(message);\n}\n\nexport function renderExistingMessages(messages: Message[]): void {\n widgetUI.renderExistingMessages(messages);\n}\n\nexport function updateMessageStatus(\n messageId: string,\n status: \"sending\" | \"sent\" | \"failed\",\n): void {\n widgetUI.updateMessageStatus(messageId, status);\n}\n\nexport function showTypingIndicator(): void {\n widgetUI.showTypingIndicator();\n}\n\nexport function hideTypingIndicator(): void {\n widgetUI.hideTypingIndicator();\n}\n\nexport function updateAgentPresenceUI(status: PresenceStatus): void {\n widgetUI.updateAgentPresenceUI(status);\n}\n\nexport function showEmailPopup(): void {\n widgetUI.showEmailPopup();\n}\n\nexport function hideEmailPopup(): void {\n widgetUI.hideEmailPopup();\n}\n\nexport function setMaximized(maximized: boolean): void {\n widgetUI.setMaximized(maximized);\n}\n\nexport function getHoneypotValue(): string {\n return widgetUI.getHoneypotValue();\n}\n\nexport function updateUnreadBadge(count: number): void {\n widgetUI.updateUnreadBadge(count);\n}\n\nexport function updateMessageReactions(\n messageId: string,\n reactions: MessageReaction[],\n): void {\n widgetUI.updateMessageReactions(messageId, reactions);\n}\n\nexport function updateMessageContent(messageId: string, content: string): void {\n widgetUI.updateMessageContent(messageId, content);\n}\n\nexport function updateMessageId(tempId: string, realId: string): void {\n widgetUI.updateMessageId(tempId, realId);\n}\n","import {\n convexAddReaction,\n convexFetchConfig,\n convexFetchConversation,\n convexGetOrCreateConversation,\n convexIdentify,\n convexMarkAsRead,\n convexSendMessage,\n convexUpdateDraft,\n convexUpdateNavigation,\n getConvexClient,\n} from \"./convex-client\";\nimport { widgetConfig, widgetLoadedAt } from \"./config\";\nimport { getHoneypotValue } from \"./ui\";\nimport type { Message, VisitorInfo, WebsiteConfig } from \"./types\";\n\ntype ApiResponse<T> = { data: T } | { error: string };\n\nasync function apiCall<T>(\n endpoint: string,\n options?: RequestInit,\n): Promise<ApiResponse<T>> {\n try {\n const response = await fetch(`${widgetConfig.apiBaseUrl}${endpoint}`, {\n ...options,\n headers: {\n \"Content-Type\": \"application/json\",\n ...options?.headers,\n },\n });\n\n if (!response.ok) {\n const errorData = await response.json().catch(() => ({}));\n return {\n error: (errorData as { message?: string }).message ?? \"Request failed\",\n };\n }\n\n const data = (await response.json()) as T;\n return { data };\n } catch (err) {\n return { error: err instanceof Error ? err.message : \"Network error\" };\n }\n}\n\nexport async function fetchConfig(\n websiteId: string,\n): Promise<ApiResponse<WebsiteConfig>> {\n const client = getConvexClient();\n\n if (client) {\n try {\n const result = await convexFetchConfig(websiteId);\n if (result) {\n return { data: result };\n }\n return { error: \"Website not found\" };\n } catch (err) {\n return { error: err instanceof Error ? err.message : \"Convex error\" };\n }\n }\n\n return apiCall<WebsiteConfig>(`/api/widget/config/${websiteId}`);\n}\n\nexport async function fetchConversation(\n conversationId: string,\n visitorId: string,\n): Promise<\n ApiResponse<{\n conversation: { id: string; status: string; websiteId: string };\n messages: Message[];\n }>\n> {\n const client = getConvexClient();\n\n if (client) {\n try {\n const result = await convexFetchConversation(conversationId, visitorId);\n if (result) {\n return { data: result };\n }\n return { error: \"Conversation not found\" };\n } catch (err) {\n return { error: err instanceof Error ? err.message : \"Convex error\" };\n }\n }\n\n return apiCall(\n `/api/widget/conversation/${conversationId}?visitorId=${encodeURIComponent(visitorId)}`,\n );\n}\n\nexport async function createConversation(\n websiteId: string,\n visitorId: string,\n url: string,\n visitorMeta?: Record<string, unknown>,\n): Promise<\n ApiResponse<{\n conversationId: string;\n isNew: boolean;\n lastVisitorMessageAt?: number;\n }>\n> {\n const client = getConvexClient();\n\n if (client) {\n try {\n const result = await convexGetOrCreateConversation(\n websiteId,\n visitorId,\n url,\n visitorMeta,\n );\n if (result) {\n return { data: result };\n }\n return { error: \"Failed to create conversation\" };\n } catch (err) {\n return { error: err instanceof Error ? err.message : \"Convex error\" };\n }\n }\n\n return apiCall<{\n conversationId: string;\n isNew: boolean;\n lastVisitorMessageAt?: number;\n }>(\"/api/widget/conversation\", {\n method: \"POST\",\n body: JSON.stringify({\n websiteId,\n visitorId,\n url,\n visitorMeta,\n honeypot: getHoneypotValue(),\n loadedAt: widgetLoadedAt,\n }),\n });\n}\n\nexport async function sendMessage(\n conversationId: string,\n visitorId: string,\n content: string,\n screenshot?: string | null,\n url?: string,\n image?: string | null,\n): Promise<ApiResponse<{ message: Message }>> {\n const client = getConvexClient();\n\n if (client) {\n try {\n const result = await convexSendMessage(\n conversationId,\n visitorId,\n content,\n screenshot,\n url,\n image,\n );\n if (result) {\n return { data: { message: result } };\n }\n return { error: \"Failed to send message\" };\n } catch (err) {\n return { error: err instanceof Error ? err.message : \"Convex error\" };\n }\n }\n\n return apiCall<{ message: Message }>(\"/api/widget/message\", {\n method: \"POST\",\n body: JSON.stringify({\n conversationId,\n content,\n screenshot,\n url,\n image,\n honeypot: getHoneypotValue(),\n loadedAt: widgetLoadedAt,\n }),\n });\n}\n\nexport async function uploadImage(\n file: File,\n): Promise<ApiResponse<{ url: string }>> {\n try {\n const formData = new FormData();\n formData.append(\"file\", file);\n\n const response = await fetch(\n `${widgetConfig.apiBaseUrl}/api/widget/upload`,\n {\n method: \"POST\",\n body: formData,\n },\n );\n\n if (!response.ok) {\n const errorData = await response.json().catch(() => ({}));\n return {\n error: (errorData as { error?: string }).error ?? \"Upload failed\",\n };\n }\n\n const data = (await response.json()) as { url: string };\n return { data };\n } catch (err) {\n return { error: err instanceof Error ? err.message : \"Upload error\" };\n }\n}\n\nexport async function sendDraft(\n conversationId: string,\n draft: string,\n): Promise<ApiResponse<{ success: boolean }>> {\n const client = getConvexClient();\n\n if (client) {\n try {\n const result = await convexUpdateDraft(conversationId, draft);\n return { data: { success: result } };\n } catch (err) {\n return { error: err instanceof Error ? err.message : \"Convex error\" };\n }\n }\n\n return apiCall<{ success: boolean }>(\"/api/widget/draft\", {\n method: \"POST\",\n body: JSON.stringify({ conversationId, draft }),\n });\n}\n\nexport async function identifyVisitor(\n conversationId: string,\n visitorId: string,\n info: VisitorInfo,\n): Promise<ApiResponse<{ success: boolean }>> {\n const client = getConvexClient();\n\n if (client) {\n try {\n const result = await convexIdentify(conversationId, visitorId, info);\n return { data: result };\n } catch (err) {\n return { error: err instanceof Error ? err.message : \"Convex error\" };\n }\n }\n\n return apiCall<{ success: boolean }>(\"/api/widget/identify\", {\n method: \"POST\",\n body: JSON.stringify({ conversationId, ...info }),\n });\n}\n\nexport async function identifyWithEmail(\n conversationId: string,\n visitorId: string,\n email: string,\n): Promise<ApiResponse<{ success: boolean; name?: string }>> {\n const client = getConvexClient();\n\n if (client) {\n try {\n const result = await convexIdentify(conversationId, visitorId, { email });\n return { data: result };\n } catch (err) {\n return { error: err instanceof Error ? err.message : \"Convex error\" };\n }\n }\n\n return apiCall<{ success: boolean; name?: string }>(\"/api/widget/identify\", {\n method: \"POST\",\n body: JSON.stringify({ conversationId, email, generateName: true }),\n });\n}\n\nexport async function sendNavigation(\n conversationId: string,\n url: string,\n): Promise<ApiResponse<{ success: boolean }>> {\n const client = getConvexClient();\n\n if (client) {\n try {\n const result = await convexUpdateNavigation(conversationId, url);\n return { data: { success: result } };\n } catch (err) {\n return { error: err instanceof Error ? err.message : \"Convex error\" };\n }\n }\n\n return apiCall<{ success: boolean }>(\"/api/widget/navigation\", {\n method: \"POST\",\n body: JSON.stringify({ conversationId, url }),\n });\n}\n\nexport async function markMessagesAsRead(\n conversationId: string,\n visitorId: string,\n): Promise<ApiResponse<{ updated: number }>> {\n const client = getConvexClient();\n\n if (client) {\n try {\n const result = await convexMarkAsRead(conversationId, visitorId);\n return { data: result };\n } catch (err) {\n return { error: err instanceof Error ? err.message : \"Convex error\" };\n }\n }\n\n return apiCall<{ updated: number }>(\"/api/widget/read\", {\n method: \"POST\",\n body: JSON.stringify({ conversationId, visitorId }),\n });\n}\n\nexport async function addReaction(\n messageId: string,\n emoji: string,\n visitorId: string,\n): Promise<ApiResponse<{ success: boolean }>> {\n const client = getConvexClient();\n\n if (client) {\n try {\n const result = await convexAddReaction(messageId, emoji, visitorId);\n return { data: { success: result } };\n } catch (err) {\n return { error: err instanceof Error ? err.message : \"Convex error\" };\n }\n }\n\n return { error: \"Convex client not available\" };\n}\n","import { sendDraft } from \"./api\";\n\nconst DRAFT_INTERVAL_MS = 5000;\n\nexport class DraftTracker {\n private readonly conversationId: string;\n private interval: ReturnType<typeof setInterval> | null = null;\n private lastSentDraft = \"\";\n private currentDraft = \"\";\n\n constructor(conversationId: string) {\n this.conversationId = conversationId;\n this.startInterval();\n }\n\n track(draft: string): void {\n this.currentDraft = draft;\n }\n\n clear(): void {\n this.currentDraft = \"\";\n if (this.lastSentDraft !== \"\") {\n this.lastSentDraft = \"\";\n void sendDraft(this.conversationId, \"\");\n }\n }\n\n destroy(): void {\n if (this.interval) {\n clearInterval(this.interval);\n this.interval = null;\n }\n }\n\n private startInterval(): void {\n this.interval = setInterval(() => {\n this.sendIfChanged();\n }, DRAFT_INTERVAL_MS);\n }\n\n private sendIfChanged(): void {\n if (this.currentDraft !== this.lastSentDraft) {\n this.lastSentDraft = this.currentDraft;\n void sendDraft(this.conversationId, this.currentDraft);\n }\n }\n}\n","import { conversationState, widgetConfig } from \"./config\";\n\nlet audioUnlocked = false;\nlet notificationAudio: HTMLAudioElement | null = null;\nlet notificationInitialized = false;\n\nfunction getAudio(): HTMLAudioElement | null {\n if (!notificationAudio) {\n const soundUrl = `${widgetConfig.apiBaseUrl}/sounds/notification.mp3`;\n notificationAudio = new Audio(soundUrl);\n notificationAudio.volume = 0.5;\n }\n return notificationAudio;\n}\n\nfunction unlockAudio(): void {\n if (audioUnlocked) return;\n\n const audio = getAudio();\n if (!audio) return;\n\n audio\n .play()\n .then(() => {\n audio.pause();\n audio.currentTime = 0;\n audioUnlocked = true;\n })\n .catch(() => {\n // Autoplay blocked, will try again on next user interaction\n });\n}\n\nexport function initNotificationSound(): void {\n if (notificationInitialized) return;\n notificationInitialized = true;\n\n const events: (keyof DocumentEventMap)[] = [\"click\", \"touchstart\", \"keydown\"];\n\n const handler = () => {\n unlockAudio();\n events.forEach((event) => {\n document.removeEventListener(event, handler);\n });\n };\n\n events.forEach((event) => {\n document.addEventListener(event, handler, { once: false });\n });\n}\n\nexport function playNotificationSound(): void {\n if (!shouldPlaySound()) return;\n\n const audio = getAudio();\n if (!audio) return;\n\n audio.currentTime = 0;\n audio.play().catch(() => {\n // Autoplay blocked - sound won't play until user interacts\n });\n}\n\nfunction shouldPlaySound(): boolean {\n if (conversationState.isOpen && !document.hidden) return false;\n return true;\n}\n\nexport function cleanupNotificationSound(): void {\n notificationAudio = null;\n audioUnlocked = false;\n notificationInitialized = false;\n}\n","import {\n convexGetAgentPresence,\n convexUpdateVisitorPresence,\n getConvexClient,\n subscribeToAgentPresence,\n subscribeToConversation,\n} from \"./convex-client\";\nimport { conversationState, setAgentPresenceStatus } from \"./config\";\nimport type {\n ConversationStatus,\n Message,\n MessageReaction,\n PresenceStatus,\n} from \"./types\";\n\ntype MessageReactionEvent = {\n id: string;\n conversationId: string;\n reactions: MessageReaction[];\n};\n\ntype MessageUpdateEvent = {\n id: string;\n conversationId: string;\n content: string;\n updatedAt: number;\n};\n\ntype RealtimeEvent =\n | { type: \"message.new\"; data: Message }\n | {\n type: \"conversation.status\";\n data: { conversationId: string; status: ConversationStatus };\n }\n | {\n type: \"agent.draft\";\n data: { conversationId: string; draft: string };\n }\n | {\n type: \"presence.agent\";\n data: { websiteId: string; status: PresenceStatus };\n }\n | {\n type: \"message.reaction\";\n data: MessageReactionEvent;\n }\n | {\n type: \"message.update\";\n data: MessageUpdateEvent;\n };\n\ntype RealtimeCallback = (event: RealtimeEvent) => void;\n\ntype PresenceCallback = (status: PresenceStatus) => void;\n\nexport class WebsitePresenceClient {\n private readonly websiteId: string;\n private readonly callbacks = new Set<PresenceCallback>();\n private disposed = false;\n private unsubscribe: (() => void) | null = null;\n\n constructor(websiteId: string) {\n this.websiteId = websiteId;\n }\n\n connect(): void {\n if (this.disposed) return;\n\n const client = getConvexClient();\n if (!client) return;\n\n this.unsubscribe = subscribeToAgentPresence(this.websiteId, (status) => {\n setAgentPresenceStatus(status);\n this.callbacks.forEach((cb) => cb(status));\n });\n }\n\n on(callback: PresenceCallback): void {\n this.callbacks.add(callback);\n }\n\n off(callback: PresenceCallback): void {\n this.callbacks.delete(callback);\n }\n\n disconnect(): void {\n this.disposed = true;\n if (this.unsubscribe) {\n this.unsubscribe();\n this.unsubscribe = null;\n }\n }\n}\n\nexport class RealtimeClient {\n private readonly conversationId: string;\n private readonly visitorId: string;\n private readonly callbacks = new Set<RealtimeCallback>();\n private lastMessageCount = 0;\n private lastMessages: Message[] = [];\n private lastStatus: ConversationStatus | null = null;\n private unsubscribe: (() => void) | null = null;\n\n constructor(conversationId: string) {\n this.conversationId = conversationId;\n this.visitorId = conversationState.visitorId;\n }\n\n connect(): void {\n const client = getConvexClient();\n if (!client) return;\n\n this.unsubscribe = subscribeToConversation(\n this.conversationId,\n this.visitorId,\n (data) => {\n if (!data) return;\n\n const currentMessages = data.messages;\n\n if (currentMessages.length > this.lastMessageCount) {\n const newMessages = currentMessages.slice(this.lastMessageCount);\n for (const msg of newMessages) {\n this.callbacks.forEach((cb) =>\n cb({\n type: \"message.new\",\n data: msg,\n }),\n );\n }\n }\n\n for (const msg of currentMessages) {\n const prevMsg = this.lastMessages.find((m) => m.id === msg.id);\n if (prevMsg) {\n if (prevMsg.content !== msg.content) {\n this.callbacks.forEach((cb) =>\n cb({\n type: \"message.update\",\n data: {\n id: msg.id,\n conversationId: this.conversationId,\n content: msg.content,\n updatedAt: Date.now(),\n },\n }),\n );\n }\n if (\n JSON.stringify(prevMsg.reactions) !==\n JSON.stringify(msg.reactions)\n ) {\n this.callbacks.forEach((cb) =>\n cb({\n type: \"message.reaction\",\n data: {\n id: msg.id,\n conversationId: this.conversationId,\n reactions: msg.reactions ?? [],\n },\n }),\n );\n }\n }\n }\n\n this.lastMessageCount = currentMessages.length;\n this.lastMessages = currentMessages;\n\n if (data.conversation.status !== this.lastStatus) {\n this.lastStatus = data.conversation.status;\n this.callbacks.forEach((cb) =>\n cb({\n type: \"conversation.status\",\n data: {\n conversationId: this.conversationId,\n status: data.conversation.status,\n },\n }),\n );\n }\n },\n );\n }\n\n on(callback: RealtimeCallback): void {\n this.callbacks.add(callback);\n }\n\n off(callback: RealtimeCallback): void {\n this.callbacks.delete(callback);\n }\n\n disconnect(): void {\n if (this.unsubscribe) {\n this.unsubscribe();\n this.unsubscribe = null;\n }\n }\n}\n\nconst HEARTBEAT_INTERVAL = 30000;\nlet heartbeatInterval: ReturnType<typeof setInterval> | null = null;\n\nexport async function sendVisitorPresence(\n conversationId: string,\n _websiteId: string,\n status: PresenceStatus,\n): Promise<void> {\n const client = getConvexClient();\n if (!client) return;\n\n try {\n await convexUpdateVisitorPresence(conversationId, status);\n } catch {\n // Ignore errors\n }\n}\n\nexport function startVisitorHeartbeat(\n conversationId: string,\n websiteId: string,\n): void {\n stopVisitorHeartbeat();\n void sendVisitorPresence(conversationId, websiteId, \"online\");\n heartbeatInterval = setInterval(() => {\n void sendVisitorPresence(conversationId, websiteId, \"online\");\n }, HEARTBEAT_INTERVAL);\n}\n\nexport function stopVisitorHeartbeat(): void {\n if (heartbeatInterval) {\n clearInterval(heartbeatInterval);\n heartbeatInterval = null;\n }\n}\n\nexport async function fetchInitialAgentPresence(\n websiteId: string,\n): Promise<PresenceStatus> {\n const client = getConvexClient();\n if (!client) return \"away\";\n\n try {\n const status = await convexGetAgentPresence(websiteId);\n setAgentPresenceStatus(status);\n return status;\n } catch {\n return \"away\";\n }\n}\n","import { domToJpeg } from \"modern-screenshot\";\n\nexport type PageContext = {\n url: string;\n title: string;\n referrer: string;\n viewport: {\n width: number;\n height: number;\n };\n screenResolution: {\n width: number;\n height: number;\n };\n userAgent: string;\n language: string;\n timestamp: string;\n};\n\nexport function capturePageContext(): PageContext {\n return {\n url: window.location.href,\n title: document.title,\n referrer: document.referrer,\n viewport: {\n width: window.innerWidth,\n height: window.innerHeight,\n },\n screenResolution: {\n width: window.screen.width,\n height: window.screen.height,\n },\n userAgent: navigator.userAgent,\n language: navigator.language,\n timestamp: new Date().toISOString(),\n };\n}\n\nexport async function captureScreenshot(): Promise<string | null> {\n try {\n const dataUrl = await domToJpeg(document.body, {\n scale: 0.5,\n quality: 0.7,\n filter: (node) => {\n if (node instanceof HTMLElement && node.id === \"tchao-widget\") {\n return false;\n }\n return true;\n },\n });\n\n return dataUrl;\n } catch {\n return JSON.stringify(capturePageContext());\n }\n}\n","import type {\n SDKEventMap,\n SDKMethods,\n VisitorInfo,\n WidgetConfig,\n} from \"./types\";\n\ntype EventListeners = {\n [K in keyof SDKEventMap]: Set<SDKEventMap[K]>;\n};\n\nexport class TchaoSDK implements SDKMethods {\n private readonly listeners: EventListeners = {\n message: new Set(),\n open: new Set(),\n close: new Set(),\n ready: new Set(),\n };\n\n private showCallback: (() => void) | null = null;\n private hideCallback: (() => void) | null = null;\n private toggleCallback: (() => void) | null = null;\n private openCallback: (() => void) | null = null;\n private identifyCallback: ((info: VisitorInfo) => void) | null = null;\n private configCallback: ((opts: Partial<WidgetConfig>) => void) | null = null;\n\n setCallbacks(callbacks: {\n show: () => void;\n hide: () => void;\n toggle: () => void;\n open: () => void;\n identify: (info: VisitorInfo) => void;\n config: (opts: Partial<WidgetConfig>) => void;\n }): void {\n this.showCallback = callbacks.show;\n this.hideCallback = callbacks.hide;\n this.toggleCallback = callbacks.toggle;\n this.openCallback = callbacks.open;\n this.identifyCallback = callbacks.identify;\n this.configCallback = callbacks.config;\n }\n\n show(): void {\n this.showCallback?.();\n }\n\n hide(): void {\n this.hideCallback?.();\n }\n\n toggle(): void {\n this.toggleCallback?.();\n }\n\n open(): void {\n this.openCallback?.();\n }\n\n identify(info: VisitorInfo): void {\n this.identifyCallback?.(info);\n }\n\n config(opts: Partial<WidgetConfig>): void {\n this.configCallback?.(opts);\n }\n\n on<K extends keyof SDKEventMap>(event: K, callback: SDKEventMap[K]): void {\n this.listeners[event].add(callback as SDKEventMap[K]);\n }\n\n off<K extends keyof SDKEventMap>(event: K, callback: SDKEventMap[K]): void {\n this.listeners[event].delete(callback as SDKEventMap[K]);\n }\n\n emit<K extends keyof SDKEventMap>(\n event: K,\n ...args: Parameters<SDKEventMap[K]>\n ): void {\n this.listeners[event].forEach((cb) => {\n (cb as (...args: Parameters<SDKEventMap[K]>) => void)(...args);\n });\n }\n}\n","type UrlChangeCallback = (url: string) => void;\n\nlet isTracking = false;\nconst callbacks = new Set<UrlChangeCallback>();\nlet lastUrl = \"\";\n\nfunction notifyUrlChange(url: string): void {\n if (url !== lastUrl) {\n lastUrl = url;\n callbacks.forEach((cb) => cb(url));\n }\n}\n\nfunction handlePopState(): void {\n notifyUrlChange(window.location.href);\n}\n\nconst originalPushState = history.pushState.bind(history);\nconst originalReplaceState = history.replaceState.bind(history);\n\nfunction patchedPushState(\n data: unknown,\n unused: string,\n url?: string | URL | null,\n): void {\n originalPushState(data, unused, url);\n setTimeout(() => notifyUrlChange(window.location.href), 0);\n}\n\nfunction patchedReplaceState(\n data: unknown,\n unused: string,\n url?: string | URL | null,\n): void {\n originalReplaceState(data, unused, url);\n setTimeout(() => notifyUrlChange(window.location.href), 0);\n}\n\nexport function initUrlTracking(onUrlChange: UrlChangeCallback): () => void {\n callbacks.add(onUrlChange);\n lastUrl = window.location.href;\n\n if (!isTracking) {\n isTracking = true;\n window.addEventListener(\"popstate\", handlePopState);\n history.pushState = patchedPushState;\n history.replaceState = patchedReplaceState;\n }\n\n return () => {\n callbacks.delete(onUrlChange);\n\n if (callbacks.size === 0 && isTracking) {\n isTracking = false;\n window.removeEventListener(\"popstate\", handlePopState);\n history.pushState = originalPushState;\n history.replaceState = originalReplaceState;\n }\n };\n}\n\nexport function getCurrentUrl(): string {\n return window.location.href;\n}\n","import {\n addReaction,\n createConversation,\n fetchConfig,\n fetchConversation,\n identifyVisitor,\n identifyWithEmail,\n markMessagesAsRead,\n sendMessage,\n sendNavigation,\n uploadImage,\n} from \"./api\";\nimport { destroyConvexClient, initConvexClient } from \"./convex-client\";\nimport {\n addMessage,\n addUnreadMessageId,\n clearStoredConversation,\n conversationState,\n getUnreadCount,\n hasScreenshotToday,\n initConversationForWebsite,\n initUnreadMessageIds,\n isMaximized,\n markMessagesAsReadLocally,\n markScreenshotTaken,\n removeMessage,\n setConversationOpen,\n setEmailCaptured,\n setLastVisitorMessageAt,\n setMaximized as setMaximizedState,\n setMessages,\n STALE_CONVERSATION_MS,\n updateConversationId,\n updateMessageIdInState,\n updateMessageStatusInState,\n updateWebsiteConfig,\n updateWidgetConfig,\n widgetConfig,\n} from \"./config\";\nimport { DraftTracker } from \"./draft\";\nimport {\n cleanupNotificationSound,\n initNotificationSound,\n playNotificationSound,\n} from \"./notifications\";\nimport {\n fetchInitialAgentPresence,\n RealtimeClient,\n sendVisitorPresence,\n startVisitorHeartbeat,\n stopVisitorHeartbeat,\n WebsitePresenceClient,\n} from \"./realtime\";\nimport { captureScreenshot } from \"./screenshot\";\nimport { TchaoSDK } from \"./sdk\";\nimport { getCurrentUrl, initUrlTracking } from \"./tracking\";\nimport type { Message, VisitorInfo } from \"./types\";\nimport {\n appendMessage,\n createWidget,\n destroyWidget,\n hideTypingIndicator,\n renderExistingMessages,\n setMaximized as setMaximizedUI,\n setWindowVisible,\n showEmailPopup,\n showTypingIndicator,\n updateAgentPresenceUI,\n updateMessageContent,\n updateMessageId,\n updateMessageReactions,\n updateMessageStatus,\n updateUnreadBadge,\n} from \"./ui\";\n\nlet realtimeClient: RealtimeClient | null = null;\nlet websitePresenceClient: WebsitePresenceClient | null = null;\nlet draftTracker: DraftTracker | null = null;\nlet urlTrackingCleanup: (() => void) | null = null;\nlet isInitialized = false;\nconst visibilityState = { cleanup: null as (() => void) | null };\nconst conversationPromiseState = {\n promise: null as Promise<string | null> | null,\n};\n\nconst sdk = new TchaoSDK();\n\nfunction setupWebsitePresence(websiteId: string): void {\n if (websitePresenceClient) {\n websitePresenceClient.disconnect();\n }\n\n websitePresenceClient = new WebsitePresenceClient(websiteId);\n websitePresenceClient.on((status) => {\n updateAgentPresenceUI(status);\n });\n websitePresenceClient.connect();\n}\n\nexport type TchaoInitConfig = {\n websiteId: string;\n host?: string;\n};\n\nexport async function initWidget(config: TchaoInitConfig): Promise<TchaoSDK> {\n if (isInitialized) return sdk;\n\n const { websiteId, host } = config;\n\n if (!websiteId) {\n throw new Error(\"websiteId is required\");\n }\n\n if (host) {\n widgetConfig.apiBaseUrl = host;\n }\n\n widgetConfig.websiteId = websiteId;\n initConversationForWebsite(websiteId);\n initUnreadMessageIds(websiteId);\n\n const configResult = await fetchConfig(websiteId);\n if (\"error\" in configResult) {\n throw new Error(configResult.error);\n }\n\n updateWebsiteConfig(configResult.data);\n\n if (widgetConfig.convexUrl) {\n initConvexClient(widgetConfig.convexUrl);\n }\n\n void fetchInitialAgentPresence(websiteId).then((status) => {\n updateAgentPresenceUI(status);\n });\n\n setupWebsitePresence(websiteId);\n\n sdk.setCallbacks({\n show: () => setWindowVisible(true),\n hide: () => {\n setWindowVisible(false);\n setConversationOpen(false);\n },\n toggle: handleToggle,\n open: handleOpen,\n identify: handleIdentify,\n config: (opts) => updateWidgetConfig(opts),\n });\n\n createWidget({\n onSend: handleSendMessage,\n onInput: handleInput,\n onToggle: handleToggle,\n onMaximize: handleMaximize,\n onImageSelect: handleImageSelect,\n onEmailSubmit: handleEmailSubmit,\n onEmailDismiss: handleEmailDismiss,\n onReaction: handleReaction,\n });\n\n initNotificationSound();\n updateUnreadBadge(getUnreadCount());\n\n if (conversationState.id) {\n void preloadConversation();\n }\n\n isInitialized = true;\n sdk.emit(\"ready\");\n\n return sdk;\n}\n\nexport function checkAutoOpenFromUrl(): void {\n const url = new URL(window.location.href);\n const shouldOpen = url.searchParams.get(\"tchao_open\");\n\n if (shouldOpen === \"true\") {\n url.searchParams.delete(\"tchao_open\");\n window.history.replaceState({}, \"\", url.toString());\n handleOpen();\n }\n}\n\nfunction getConvexHttpUrl(): string {\n const convexUrl = widgetConfig.convexUrl;\n if (!convexUrl) return \"\";\n return convexUrl.replace(\".cloud\", \".site\");\n}\n\nfunction setupVisibilityTracking(): void {\n if (visibilityState.cleanup) {\n visibilityState.cleanup();\n }\n\n const handleVisibilityChange = (): void => {\n if (!conversationState.id) return;\n\n if (document.visibilityState === \"hidden\") {\n void sendVisitorPresence(\n conversationState.id,\n widgetConfig.websiteId,\n \"idle\",\n );\n } else {\n void sendVisitorPresence(\n conversationState.id,\n widgetConfig.websiteId,\n \"online\",\n );\n }\n };\n\n const handleBeforeUnload = (): void => {\n if (!conversationState.id) return;\n\n const convexHttpUrl = getConvexHttpUrl();\n if (convexHttpUrl) {\n const data = JSON.stringify({\n conversationId: conversationState.id,\n status: \"away\",\n });\n const blob = new Blob([data], { type: \"application/json\" });\n navigator.sendBeacon(`${convexHttpUrl}/presence/visitor`, blob);\n }\n };\n\n document.addEventListener(\"visibilitychange\", handleVisibilityChange);\n window.addEventListener(\"beforeunload\", handleBeforeUnload);\n\n visibilityState.cleanup = () => {\n document.removeEventListener(\"visibilitychange\", handleVisibilityChange);\n window.removeEventListener(\"beforeunload\", handleBeforeUnload);\n };\n}\n\nasync function preloadConversation(): Promise<void> {\n if (!conversationState.id || realtimeClient) return;\n\n const result = await fetchConversation(\n conversationState.id,\n conversationState.visitorId,\n );\n\n if (\"error\" in result) {\n clearStoredConversation();\n return;\n }\n\n setMessages(result.data.messages);\n setupRealtime(conversationState.id);\n setupUrlTracking(conversationState.id);\n draftTracker = new DraftTracker(conversationState.id);\n}\n\nasync function ensureConversationInternal(): Promise<string | null> {\n if (conversationState.id) {\n if (realtimeClient) {\n renderExistingMessages(conversationState.messages);\n return conversationState.id;\n }\n\n const existingResult = await fetchConversation(\n conversationState.id,\n conversationState.visitorId,\n );\n\n if (\"error\" in existingResult) {\n clearStoredConversation();\n renderExistingMessages([]);\n return null;\n } else {\n setMessages(existingResult.data.messages);\n renderExistingMessages(existingResult.data.messages);\n setupRealtime(conversationState.id);\n setupUrlTracking(conversationState.id);\n draftTracker = new DraftTracker(conversationState.id);\n return conversationState.id;\n }\n }\n\n const result = await createConversation(\n widgetConfig.websiteId,\n conversationState.visitorId,\n getCurrentUrl(),\n getVisitorMeta(),\n );\n\n if (\"error\" in result) {\n return null;\n }\n\n updateConversationId(result.data.conversationId);\n setLastVisitorMessageAt(result.data.lastVisitorMessageAt ?? null);\n setupRealtime(result.data.conversationId);\n setupUrlTracking(result.data.conversationId);\n draftTracker = new DraftTracker(result.data.conversationId);\n\n return result.data.conversationId;\n}\n\nasync function ensureConversation(): Promise<string | null> {\n if (conversationPromiseState.promise) {\n return conversationPromiseState.promise;\n }\n\n conversationPromiseState.promise = ensureConversationInternal().finally(\n () => {\n conversationPromiseState.promise = null;\n },\n );\n\n return conversationPromiseState.promise;\n}\n\nfunction setupRealtime(conversationId: string): void {\n if (realtimeClient) {\n realtimeClient.disconnect();\n stopVisitorHeartbeat();\n }\n\n realtimeClient = new RealtimeClient(conversationId);\n realtimeClient.on((event) => {\n if (event.type === \"message.new\") {\n if (event.data.senderType === \"VISITOR\") {\n const tempMessage = conversationState.messages.find(\n (m) => m.id.startsWith(\"temp_\") && m.content === event.data.content,\n );\n if (tempMessage) {\n const tempId = tempMessage.id;\n updateMessageIdInState(tempId, event.data.id);\n updateMessageId(tempId, event.data.id);\n }\n } else {\n hideTypingIndicator();\n addMessage(event.data);\n appendMessage(event.data);\n sdk.emit(\"message\", event.data);\n\n if (\n event.data.senderType === \"AGENT\" ||\n event.data.senderType === \"AI\"\n ) {\n playNotificationSound();\n\n if (!conversationState.isOpen) {\n addUnreadMessageId(event.data.id);\n updateUnreadBadge(getUnreadCount());\n } else if (conversationState.id) {\n void markMessagesAsRead(\n conversationState.id,\n conversationState.visitorId,\n );\n }\n }\n }\n }\n if (event.type === \"agent.draft\") {\n if (event.data.draft) {\n showTypingIndicator();\n } else {\n hideTypingIndicator();\n }\n }\n if (event.type === \"presence.agent\") {\n updateAgentPresenceUI(event.data.status);\n }\n if (event.type === \"message.reaction\") {\n updateMessageReactions(event.data.id, event.data.reactions);\n }\n if (event.type === \"message.update\") {\n updateMessageContent(event.data.id, event.data.content);\n }\n });\n realtimeClient.connect();\n\n startVisitorHeartbeat(conversationId, widgetConfig.websiteId);\n setupVisibilityTracking();\n}\n\nfunction setupUrlTracking(conversationId: string): void {\n urlTrackingCleanup = initUrlTracking((url) => {\n void sendNavigation(conversationId, url);\n });\n}\n\nfunction handleToggle(): void {\n const newState = !conversationState.isOpen;\n setConversationOpen(newState);\n setWindowVisible(newState);\n\n if (newState) {\n markMessagesAsReadLocally();\n updateUnreadBadge(0);\n sdk.emit(\"open\");\n if (conversationState.id) {\n void ensureConversation();\n void markMessagesAsRead(\n conversationState.id,\n conversationState.visitorId,\n );\n }\n } else {\n sdk.emit(\"close\");\n }\n}\n\nfunction handleOpen(): void {\n if (!conversationState.isOpen) {\n handleToggle();\n }\n}\n\nfunction handleMaximize(): void {\n const newState = !isMaximized;\n setMaximizedState(newState);\n setMaximizedUI(newState);\n}\n\nfunction isConversationStale(): boolean {\n const lastMessageAt = conversationState.lastVisitorMessageAt;\n if (lastMessageAt === null) return true;\n return Date.now() - lastMessageAt > STALE_CONVERSATION_MS;\n}\n\nasync function handleSendMessage(\n content: string,\n imageUrl?: string | null,\n): Promise<void> {\n const isFirstMessage = conversationState.messages.length === 0;\n const isStale = isConversationStale();\n const alreadyScreenshotToday = hasScreenshotToday();\n const shouldCaptureScreenshot =\n !alreadyScreenshotToday && (isFirstMessage || isStale);\n\n const tempMessage: Message = {\n id: `temp_${Date.now()}`,\n content,\n senderType: \"VISITOR\",\n senderId: conversationState.visitorId,\n image: imageUrl ?? null,\n timestamp: Date.now(),\n status: \"sending\",\n };\n\n addMessage(tempMessage);\n appendMessage(tempMessage);\n\n const conversationId = await ensureConversation();\n if (!conversationId) {\n removeMessage(tempMessage.id);\n updateMessageStatus(tempMessage.id, \"failed\");\n return;\n }\n\n draftTracker?.clear();\n\n let screenshot: string | null = null;\n if (shouldCaptureScreenshot) {\n screenshot = await captureScreenshot();\n if (screenshot) {\n markScreenshotTaken();\n }\n }\n\n try {\n await sendMessage(\n conversationId,\n conversationState.visitorId,\n content,\n screenshot,\n getCurrentUrl(),\n imageUrl,\n );\n updateMessageStatusInState(tempMessage.id, \"sent\");\n updateMessageStatus(tempMessage.id, \"sent\");\n setLastVisitorMessageAt(Date.now());\n } catch {\n updateMessageStatusInState(tempMessage.id, \"failed\");\n updateMessageStatus(tempMessage.id, \"failed\");\n }\n\n if (isFirstMessage && !conversationState.emailCaptured) {\n showEmailPopup();\n }\n}\n\nasync function handleImageSelect(file: File): Promise<string | null> {\n const result = await uploadImage(file);\n if (\"error\" in result) {\n return null;\n }\n return result.data.url;\n}\n\nfunction handleInput(content: string): void {\n if (conversationState.id && draftTracker) {\n draftTracker.track(content);\n }\n}\n\nasync function handleIdentify(info: VisitorInfo): Promise<void> {\n const conversationId = await ensureConversation();\n if (!conversationId) return;\n\n await identifyVisitor(conversationId, conversationState.visitorId, info);\n}\n\nasync function handleEmailSubmit(email: string): Promise<void> {\n const conversationId = await ensureConversation();\n if (!conversationId) return;\n\n const result = await identifyWithEmail(\n conversationId,\n conversationState.visitorId,\n email,\n );\n if (!(\"error\" in result)) {\n setEmailCaptured(true);\n }\n}\n\nfunction handleEmailDismiss(): void {\n setEmailCaptured(true);\n}\n\nasync function handleReaction(messageId: string, emoji: string): Promise<void> {\n await addReaction(messageId, emoji, conversationState.visitorId);\n}\n\nfunction getVisitorMeta(): Record<string, unknown> {\n return {\n userAgent: navigator.userAgent,\n language: navigator.language,\n screenWidth: window.screen.width,\n screenHeight: window.screen.height,\n timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,\n };\n}\n\nexport function cleanup(): void {\n if (conversationState.id) {\n void sendVisitorPresence(\n conversationState.id,\n widgetConfig.websiteId,\n \"away\",\n );\n }\n stopVisitorHeartbeat();\n visibilityState.cleanup?.();\n realtimeClient?.disconnect();\n websitePresenceClient?.disconnect();\n draftTracker?.destroy();\n urlTrackingCleanup?.();\n cleanupNotificationSound();\n destroyConvexClient();\n destroyWidget();\n setMaximizedState(false);\n isInitialized = false;\n}\n\nexport function getSDK(): TchaoSDK {\n return sdk;\n}\n"],"mappings":"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","names":["npm_exports","__export","Tchao","TchaoSDK","npm_default","init","__toCommonJS","import_browser","import_server","client","convexUrl","initConvexClient","url","getConvexClient","destroyConvexClient","convertMessage","m","convexFetchConfig","websiteId","result","convexGetOrCreateConversation","visitorId","visitorMeta","convexFetchConversation","conversationId","convexSendMessage","content","screenshot","image","convexUpdateDraft","draft","convexUpdateNavigation","convexMarkAsRead","convexIdentify","info","convexGetAgentPresence","convexUpdateVisitorPresence","status","convexAddReaction","messageId","emoji","noop","subscribeToConversation","callback","subscribeToAgentPresence","VISITOR_ID_KEY","CONVERSATION_ID_PREFIX","EMAIL_CAPTURED_PREFIX","LAST_SCREENSHOT_DATE_PREFIX","generateVisitorId","getStoredVisitorId","stored","VISITOR_ID_KEY","newId","getConversationKey","websiteId","CONVERSATION_ID_PREFIX","getStoredConversationId","setStoredConversationId","id","removeStoredConversationId","getEmailCapturedKey","EMAIL_CAPTURED_PREFIX","getStoredEmailCaptured","setStoredEmailCaptured","captured","getLastScreenshotDateKey","LAST_SCREENSHOT_DATE_PREFIX","getStoredLastScreenshotDate","setStoredLastScreenshotDate","date","detectApiBaseUrl","script","widgetConfig","websiteConfig","conversationState","initConversationForWebsite","updateWidgetConfig","config","updateWebsiteConfig","updateConversationId","addMessage","message","m","removeMessage","messageId","updateMessageStatusInState","status","updateMessageIdInState","tempId","realId","setConversationOpen","isOpen","isMaximized","setMaximized","maximized","clearStoredConversation","setMessages","messages","setEmailCaptured","setLastVisitorMessageAt","timestamp","agentPresenceStatus","setAgentPresenceStatus","widgetLoadedAt","UNREAD_MESSAGE_IDS_PREFIX","getUnreadIdsKey","websiteId","getStoredUnreadIds","stored","setStoredUnreadIds","ids","unreadMessageIds","initUnreadMessageIds","addUnreadMessageId","messageId","conversationState","markMessagesAsReadLocally","getUnreadCount","getResolvedTheme","themeMode","widgetConfig","getTodayDateString","hasScreenshotToday","getStoredLastScreenshotDate","markScreenshotTaken","setStoredLastScreenshotDate","getWidgetStyles","primaryColor","position","theme","isRight","isDark","colors","ICONS","WIDGET_EMOJIS","URL_REGEX","cleanUrl","url","linkifyHtml","text","div","match","trailing","ChatWidgetUI","callbacks","theme","getResolvedTheme","style","getWidgetStyles","widgetConfig","wrapper","widgetStyle","visible","container","maximized","window","maximizeBtn","message","isAgent","isVisitor","lastGroup","lastGroupIsAgent","lastGroupIsVisitor","bubblesContainer","timeEl","row","bubbleWrapper","bubble","newTimeEl","messages","group","messageId","status","messageEl","indicator","statusText","count","reactions","existingReactions","totalCount","acc","r","reactionsContainer","reaction","btn","countEl","content","textEl","tempId","realId","groups","currentGroup","msg","firstMessage","lastMessage","groupWrapper","parent","onToggle","launcher","avatar","websiteConfig","img","info","nameRow","statusDot","nameText","role","cta","header","textSection","title","subtitle","agentPresenceStatus","avatars","iconCircle","buttons","chatBtn","onClose","onMaximize","name","tagline","closeBtn","conversationState","inputArea","inputRow","fileInput","imageBtn","e","sendBtn","input","submitBtn","handleSubmit","email","powered","className","actionsContainer","reactionBtn","reactionPicker","emoji","moreBtn","dropdown","copyItem","el","existing","toast","id","statusTextMap","badge","dot","selector","element","baseClass","senderClass","msgEl","hideTime","imageUrl","time","welcome","card","quote","agent","agentName","agentRole","statusEl","modal","file","reader","previewItem","removeBtn","dragCounter","files","error","onSend","timestamp","SpeechRecognitionAPI","recognition","event","transcript","i","currentValue","lastFinalIndex","baseText","errorMessages","widgetUI","createWidget","destroyWidget","setWindowVisible","appendMessage","renderExistingMessages","updateMessageStatus","showTypingIndicator","hideTypingIndicator","updateAgentPresenceUI","showEmailPopup","setMaximized","maximized","widgetUI","getHoneypotValue","updateUnreadBadge","count","updateMessageReactions","messageId","reactions","updateMessageContent","content","updateMessageId","tempId","realId","apiCall","endpoint","options","response","widgetConfig","err","fetchConfig","websiteId","getConvexClient","result","convexFetchConfig","fetchConversation","conversationId","visitorId","convexFetchConversation","createConversation","url","visitorMeta","convexGetOrCreateConversation","getHoneypotValue","widgetLoadedAt","sendMessage","content","screenshot","image","convexSendMessage","uploadImage","file","formData","sendDraft","draft","convexUpdateDraft","identifyVisitor","info","convexIdentify","identifyWithEmail","email","sendNavigation","convexUpdateNavigation","markMessagesAsRead","convexMarkAsRead","addReaction","messageId","emoji","convexAddReaction","DRAFT_INTERVAL_MS","DraftTracker","conversationId","draft","sendDraft","audioUnlocked","notificationAudio","notificationInitialized","getAudio","soundUrl","widgetConfig","unlockAudio","audio","initNotificationSound","events","handler","event","playNotificationSound","shouldPlaySound","conversationState","cleanupNotificationSound","WebsitePresenceClient","websiteId","getConvexClient","subscribeToAgentPresence","status","setAgentPresenceStatus","cb","callback","RealtimeClient","conversationId","conversationState","subscribeToConversation","data","currentMessages","newMessages","msg","prevMsg","m","HEARTBEAT_INTERVAL","heartbeatInterval","sendVisitorPresence","_websiteId","convexUpdateVisitorPresence","startVisitorHeartbeat","stopVisitorHeartbeat","fetchInitialAgentPresence","convexGetAgentPresence","import_modern_screenshot","capturePageContext","captureScreenshot","node","TchaoSDK","callbacks","info","opts","event","callback","args","cb","isTracking","callbacks","lastUrl","notifyUrlChange","url","cb","handlePopState","originalPushState","originalReplaceState","patchedPushState","data","unused","patchedReplaceState","initUrlTracking","onUrlChange","getCurrentUrl","realtimeClient","websitePresenceClient","draftTracker","urlTrackingCleanup","isInitialized","visibilityState","conversationPromiseState","sdk","TchaoSDK","setupWebsitePresence","websiteId","WebsitePresenceClient","status","updateAgentPresenceUI","initWidget","config","host","widgetConfig","initConversationForWebsite","initUnreadMessageIds","configResult","fetchConfig","updateWebsiteConfig","initConvexClient","fetchInitialAgentPresence","setWindowVisible","setConversationOpen","handleToggle","handleOpen","handleIdentify","opts","updateWidgetConfig","createWidget","handleSendMessage","handleInput","handleMaximize","handleImageSelect","handleEmailSubmit","handleEmailDismiss","handleReaction","initNotificationSound","updateUnreadBadge","getUnreadCount","conversationState","preloadConversation","getConvexHttpUrl","convexUrl","widgetConfig","setupVisibilityTracking","visibilityState","handleVisibilityChange","conversationState","sendVisitorPresence","handleBeforeUnload","convexHttpUrl","data","blob","preloadConversation","realtimeClient","result","fetchConversation","clearStoredConversation","setMessages","setupRealtime","setupUrlTracking","draftTracker","DraftTracker","ensureConversationInternal","renderExistingMessages","existingResult","createConversation","getCurrentUrl","getVisitorMeta","updateConversationId","setLastVisitorMessageAt","ensureConversation","conversationPromiseState","conversationId","stopVisitorHeartbeat","RealtimeClient","event","tempMessage","m","tempId","updateMessageIdInState","updateMessageId","hideTypingIndicator","addMessage","appendMessage","sdk","playNotificationSound","markMessagesAsRead","addUnreadMessageId","updateUnreadBadge","getUnreadCount","showTypingIndicator","updateAgentPresenceUI","updateMessageReactions","updateMessageContent","startVisitorHeartbeat","urlTrackingCleanup","initUrlTracking","url","sendNavigation","handleToggle","newState","setConversationOpen","setWindowVisible","markMessagesAsReadLocally","handleOpen","handleMaximize","isMaximized","setMaximized","isConversationStale","lastMessageAt","handleSendMessage","content","imageUrl","isFirstMessage","isStale","shouldCaptureScreenshot","hasScreenshotToday","removeMessage","updateMessageStatus","screenshot","captureScreenshot","markScreenshotTaken","sendMessage","updateMessageStatusInState","showEmailPopup","handleImageSelect","file","uploadImage","handleInput","handleIdentify","info","identifyVisitor","handleEmailSubmit","email","identifyWithEmail","setEmailCaptured","handleEmailDismiss","handleReaction","messageId","emoji","addReaction","cleanup","websitePresenceClient","cleanupNotificationSound","destroyConvexClient","destroyWidget","isInitialized","init","config","sdk","initWidget","cleanup","Tchao","npm_default","Tchao"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/widget/npm.ts"],"sourcesContent":["export type VisitorInfo = {\n name?: string;\n email?: string;\n avatar?: string;\n metadata?: Record<string, unknown>;\n};\n\nexport type WidgetConfig = {\n websiteId: string;\n position?: \"bottom-right\" | \"bottom-left\";\n primaryColor?: string;\n widgetStyle?: \"bubble\" | \"name_line\" | \"question_cta\";\n themeMode?: \"light\" | \"dark\" | \"system\";\n agentName?: string;\n agentRole?: string;\n agentImage?: string;\n agentWelcomeMessage?: string;\n hidePoweredBy?: boolean;\n bubbleIcon?: string;\n};\n\nexport type TchaoConfig = {\n websiteId: string;\n host?: string;\n convexUrl?: string;\n position?: \"bottom-right\" | \"bottom-left\";\n primaryColor?: string;\n widgetStyle?: \"bubble\" | \"name_line\" | \"question_cta\";\n themeMode?: \"light\" | \"dark\" | \"system\";\n agentName?: string;\n agentRole?: string;\n agentImage?: string;\n agentWelcomeMessage?: string;\n hidePoweredBy?: boolean;\n bubbleIcon?: string;\n};\n\nexport type Message = {\n content: string;\n sender: string;\n timestamp: number;\n};\n\nexport type TchaoEventMap = {\n message: (message: Message) => void;\n open: () => void;\n close: () => void;\n ready: () => void;\n};\n\nexport type TchaoEvent = keyof TchaoEventMap;\n\nexport type TchaoInstance = {\n show: () => void;\n hide: () => void;\n toggle: () => void;\n open: (message?: string) => void;\n identify: (info: VisitorInfo) => void;\n config: () => Partial<WidgetConfig>;\n on: <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]) => void;\n off: <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]) => void;\n destroy: () => void;\n isReady: () => boolean;\n};\n\ntype InternalTchaoInstance = {\n show: () => void;\n hide: () => void;\n toggle: () => void;\n open: (message?: string) => void;\n identify: (info: VisitorInfo) => void;\n config: () => Partial<WidgetConfig>;\n on: (event: string, callback: (...args: unknown[]) => void) => void;\n off: (event: string, callback: (...args: unknown[]) => void) => void;\n};\n\ndeclare global {\n interface Window {\n Tchao?: InternalTchaoInstance;\n __TCHAO_CONFIG__?: TchaoConfig;\n }\n}\n\nconst WIDGET_SCRIPT_URL = \"https://tchao.app/widget.js\";\n\nlet scriptLoaded = false;\nlet scriptPromise: Promise<void> | null = null;\nlet initialized = false;\nlet currentInstance: TchaoInstance | null = null;\n\ntype QueuedCall =\n | { type: \"show\" }\n | { type: \"hide\" }\n | { type: \"toggle\" }\n | { type: \"open\"; message?: string }\n | { type: \"identify\"; info: VisitorInfo }\n | { type: \"on\"; event: string; callback: (...args: unknown[]) => void }\n | { type: \"off\"; event: string; callback: (...args: unknown[]) => void };\n\nconst callQueue: QueuedCall[] = [];\n\nfunction flushQueue(): void {\n while (callQueue.length > 0) {\n const call = callQueue.shift();\n if (!call || !window.Tchao) continue;\n\n try {\n switch (call.type) {\n case \"show\":\n window.Tchao.show();\n break;\n case \"hide\":\n window.Tchao.hide();\n break;\n case \"toggle\":\n window.Tchao.toggle();\n break;\n case \"open\":\n window.Tchao.open(call.message);\n break;\n case \"identify\":\n window.Tchao.identify(call.info);\n break;\n case \"on\":\n window.Tchao.on(call.event, call.callback);\n break;\n case \"off\":\n window.Tchao.off(call.event, call.callback);\n break;\n }\n } catch {\n // Silent fail\n }\n }\n}\n\nasync function loadScript(config: TchaoConfig): Promise<void> {\n if (scriptPromise) return scriptPromise;\n\n scriptPromise = new Promise((resolve, reject) => {\n if (scriptLoaded && window.Tchao) {\n resolve();\n return;\n }\n\n const existingScript = document.querySelector(\n 'script[data-tchao-widget]'\n ) as HTMLScriptElement | null;\n\n if (existingScript) {\n scriptLoaded = true;\n resolve();\n return;\n }\n\n window.__TCHAO_CONFIG__ = config;\n\n const script = document.createElement(\"script\");\n script.src = config.host ? `${config.host}/widget.js` : WIDGET_SCRIPT_URL;\n script.async = true;\n script.dataset.websiteId = config.websiteId;\n script.dataset.tchaoWidget = \"true\";\n\n script.onload = () => {\n scriptLoaded = true;\n resolve();\n };\n\n script.onerror = () => {\n reject(new Error(\"Failed to load Tchao widget script\"));\n };\n\n document.head.appendChild(script);\n });\n\n return scriptPromise;\n}\n\nasync function waitForTchao(): Promise<void> {\n return new Promise((resolve, reject) => {\n let attempts = 0;\n const check = () => {\n if (window.Tchao) {\n resolve();\n } else if (attempts >= 50) {\n reject(new Error(\"Tchao widget failed to initialize\"));\n } else {\n attempts++;\n setTimeout(check, 100);\n }\n };\n check();\n });\n}\n\nasync function init(config: TchaoConfig): Promise<TchaoInstance> {\n if (!config.websiteId) {\n throw new Error(\"websiteId is required\");\n }\n\n if (initialized && window.Tchao && currentInstance) {\n return currentInstance;\n }\n\n await loadScript(config);\n await waitForTchao();\n\n if (!window.Tchao) {\n throw new Error(\"Tchao widget failed to initialize\");\n }\n\n initialized = true;\n currentInstance = createInstance();\n flushQueue();\n return currentInstance;\n}\n\nfunction createInstance(): TchaoInstance {\n return {\n show: () => {\n try {\n window.Tchao?.show();\n } catch {\n // Silent fail\n }\n },\n hide: () => {\n try {\n window.Tchao?.hide();\n } catch {\n // Silent fail\n }\n },\n toggle: () => {\n try {\n window.Tchao?.toggle();\n } catch {\n // Silent fail\n }\n },\n open: (message?: string) => {\n try {\n window.Tchao?.open(message);\n } catch {\n // Silent fail\n }\n },\n identify: (info: VisitorInfo) => {\n try {\n window.Tchao?.identify(info);\n } catch {\n // Silent fail\n }\n },\n config: () => {\n try {\n return window.Tchao?.config() ?? {};\n } catch {\n return {};\n }\n },\n on: <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]) => {\n try {\n window.Tchao?.on(event, callback as (...args: unknown[]) => void);\n } catch {\n // Silent fail\n }\n },\n off: <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]) => {\n try {\n window.Tchao?.off(event, callback as (...args: unknown[]) => void);\n } catch {\n // Silent fail\n }\n },\n isReady: () => initialized && !!window.Tchao,\n destroy: () => {\n try {\n const script = document.querySelector('script[data-tchao-widget]');\n if (script) script.remove();\n const widget = document.getElementById(\"tchao-widget-root\");\n if (widget) widget.remove();\n scriptLoaded = false;\n scriptPromise = null;\n initialized = false;\n currentInstance = null;\n callQueue.length = 0;\n delete window.__TCHAO_CONFIG__;\n delete window.Tchao;\n } catch {\n // Silent fail\n }\n },\n };\n}\n\nfunction safeCall<T>(fn: () => T, fallback: T): T {\n try {\n return fn();\n } catch {\n return fallback;\n }\n}\n\n/**\n * Safe API that works before initialization.\n * Calls are queued and executed once the widget is ready.\n */\nexport const tchao = {\n /**\n * Initialize the widget. Returns a promise that resolves with the instance.\n */\n init,\n\n /**\n * Show the widget launcher. Safe to call before init.\n */\n show: (): void => {\n if (window.Tchao) {\n safeCall(() => window.Tchao?.show(), undefined);\n } else {\n callQueue.push({ type: \"show\" });\n }\n },\n\n /**\n * Hide the widget launcher. Safe to call before init.\n */\n hide: (): void => {\n if (window.Tchao) {\n safeCall(() => window.Tchao?.hide(), undefined);\n } else {\n callQueue.push({ type: \"hide\" });\n }\n },\n\n /**\n * Toggle the chat window. Safe to call before init.\n */\n toggle: (): void => {\n if (window.Tchao) {\n safeCall(() => window.Tchao?.toggle(), undefined);\n } else {\n callQueue.push({ type: \"toggle\" });\n }\n },\n\n /**\n * Open the chat window. Safe to call before init.\n */\n open: (message?: string): void => {\n if (window.Tchao) {\n safeCall(() => window.Tchao?.open(message), undefined);\n } else {\n callQueue.push({ type: \"open\", message });\n }\n },\n\n /**\n * Identify the visitor. Safe to call before init.\n */\n identify: (info: VisitorInfo): void => {\n if (window.Tchao) {\n safeCall(() => window.Tchao?.identify(info), undefined);\n } else {\n callQueue.push({ type: \"identify\", info });\n }\n },\n\n /**\n * Get the current widget configuration.\n */\n config: (): Partial<WidgetConfig> => {\n return safeCall(() => window.Tchao?.config() ?? {}, {});\n },\n\n /**\n * Subscribe to widget events. Safe to call before init.\n */\n on: <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]): void => {\n if (window.Tchao) {\n safeCall(\n () => window.Tchao?.on(event, callback as (...args: unknown[]) => void),\n undefined\n );\n } else {\n callQueue.push({\n type: \"on\",\n event,\n callback: callback as (...args: unknown[]) => void,\n });\n }\n },\n\n /**\n * Unsubscribe from widget events.\n */\n off: <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]): void => {\n if (window.Tchao) {\n safeCall(\n () =>\n window.Tchao?.off(event, callback as (...args: unknown[]) => void),\n undefined\n );\n } else {\n callQueue.push({\n type: \"off\",\n event,\n callback: callback as (...args: unknown[]) => void,\n });\n }\n },\n\n /**\n * Destroy the widget and clean up resources.\n */\n destroy: (): void => {\n if (currentInstance) {\n currentInstance.destroy();\n }\n },\n\n /**\n * Check if the widget is ready.\n */\n isReady: (): boolean => initialized && !!window.Tchao,\n\n /**\n * Get the current instance (null if not initialized).\n */\n getInstance: (): TchaoInstance | null => currentInstance,\n};\n\nexport const Tchao = {\n init,\n};\n\nexport { init };\nexport default Tchao;\n"],"mappings":"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","names":["npm_exports","__export","Tchao","npm_default","init","tchao","__toCommonJS","WIDGET_SCRIPT_URL","scriptLoaded","scriptPromise","initialized","currentInstance","callQueue","flushQueue","call","loadScript","config","resolve","reject","script","waitForTchao","attempts","check","createInstance","message","info","event","callback","widget","safeCall","fn","fallback","npm_default","Tchao"]}
|