tchao 0.1.2

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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../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","../../../src/widget/npm.ts"],"sourcesContent":["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","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"],"mappings":"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","names":["ConvexClient","anyApi","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","domToJpeg","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"]}
package/package.json ADDED
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "tchao",
3
+ "version": "0.1.2",
4
+ "description": "JavaScript SDK for Tchao chat widget",
5
+ "main": "./dist/npm.js",
6
+ "module": "./dist/npm.mjs",
7
+ "types": "./dist/npm.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/npm.d.ts",
11
+ "import": "./dist/npm.mjs",
12
+ "require": "./dist/npm.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist"
17
+ ],
18
+ "keywords": [
19
+ "tchao",
20
+ "chat",
21
+ "widget",
22
+ "sdk",
23
+ "customer-support",
24
+ "live-chat"
25
+ ],
26
+ "author": "Tchao",
27
+ "license": "MIT",
28
+ "dependencies": {
29
+ "convex": "^1.31.6",
30
+ "modern-screenshot": "^4.6.7"
31
+ },
32
+ "devDependencies": {
33
+ "tsup": "^8.5.0",
34
+ "typescript": "^5.9.3"
35
+ },
36
+ "repository": {
37
+ "type": "git",
38
+ "url": "https://github.com/tchao-app/tchao"
39
+ },
40
+ "peerDependencies": {
41
+ "convex": ">=1.0.0"
42
+ },
43
+ "peerDependenciesMeta": {
44
+ "convex": {
45
+ "optional": true
46
+ }
47
+ },
48
+ "scripts": {
49
+ "build": "tsup",
50
+ "dev": "tsup --watch",
51
+ "typecheck": "tsc --noEmit",
52
+ "release:patch": "npm version patch && pnpm publish --access public",
53
+ "release:minor": "npm version minor && pnpm publish --access public",
54
+ "release:major": "npm version major && pnpm publish --access public"
55
+ }
56
+ }