@bootdesk/js-web-adapter-react 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/components/ChatWidget.tsx","../src/hooks/useChatClient.ts","../src/hooks/useMessages.ts","../src/hooks/useStreaming.ts","../src/hooks/useTyping.ts","../src/hooks/usePushNotifications.ts","../src/hooks/useAttachmentUpload.ts","../src/types/AttachmentUpload.ts","../src/hooks/useBridge.ts","../src/i18n/LocaleProvider.tsx","../src/i18n/types.ts","../src/i18n/locales/en.json","../src/i18n/locales/en-US.json","../src/i18n/locales/en-GB.json","../src/i18n/locales/pt.json","../src/i18n/locales/pt-BR.json","../src/i18n/locales/pt-PT.json","../src/i18n/locales/es.json","../src/i18n/mergeLocale.ts","../src/components/FloatingButton.tsx","../src/components/Header.tsx","../src/components/MessageList.tsx","../src/cards/CardContext.tsx","../src/utils/markdown.tsx","../src/cards/DefaultCard.tsx","../src/cards/ImageCard.tsx","../src/utils/formatSize.ts","../src/cards/FileCard.tsx","../src/cards/CardRenderer.tsx","../src/components/MessageContent.tsx","../src/utils/formatTimestamp.ts","../src/components/InputArea.tsx","../src/components/Dropzone.tsx","../src/components/AttachmentList.tsx","../src/components/TypingIndicator.tsx","../src/providers/ChatProvider.tsx","../src/components/ErrorBoundary.tsx","../src/components/PushPermissionPrompt.tsx","../src/components/PushToggle.tsx"],"sourcesContent":["export { ChatWidget } from \"./components/ChatWidget\";\nexport type { ChatWidgetProps } from \"./components/ChatWidget\";\n\nexport { Header } from \"./components/Header\";\nexport { MessageList } from \"./components/MessageList\";\nexport { MessageContent } from \"./components/MessageContent\";\nexport { InputArea } from \"./components/InputArea\";\nexport { TypingIndicator } from \"./components/TypingIndicator\";\nexport { FloatingButton } from \"./components/FloatingButton\";\n\nexport { CardRenderer } from \"./cards/CardRenderer\";\nexport { DefaultCard } from \"./cards/DefaultCard\";\nexport { ImageCardComponent as ImageCardComponent } from \"./cards/ImageCard\";\nexport { FileCardComponent as FileCardComponent } from \"./cards/FileCard\";\nexport { CardProvider, useCardRegistry } from \"./cards/CardContext\";\nexport { ChatProvider, useChatContext } from \"./providers/ChatProvider\";\nexport type { CardRendererProps, CardRenderer as CardRendererType } from \"./cards/types\";\n\nexport { useChatClient } from \"./hooks/useChatClient\";\nexport { useMessages } from \"./hooks/useMessages\";\nexport { useStreaming } from \"./hooks/useStreaming\";\nexport { useTyping } from \"./hooks/useTyping\";\nexport { useCardRegistry as useCardRendererRegistry } from \"./cards/CardContext\";\n\nexport { MarkdownRenderer, renderMarkdown } from \"./utils/markdown\";\n\nexport { ErrorBoundary } from \"./components/ErrorBoundary\";\nexport { Dropzone } from \"./components/Dropzone\";\nexport { AttachmentList } from \"./components/AttachmentList\";\nexport { useAttachmentUpload } from \"./hooks/useAttachmentUpload\";\nexport type {\n PendingAttachment,\n AttachmentUploadConfig,\n SimpleUploadConfig,\n UploadConfig,\n SignedUploadUrl,\n} from \"./types/AttachmentUpload\";\n\nexport { LocaleProvider, useLocale, registerLocale, getAvailableLocales } from \"./i18n\";\nexport type { LocaleStrings, PartialLocaleStrings, LocaleConfig, SupportedLocale } from \"./i18n\";\n\nexport { PushPermissionPrompt } from \"./components/PushPermissionPrompt\";\nexport { PushToggle } from \"./components/PushToggle\";\nexport { usePushNotifications } from \"./hooks/usePushNotifications\";\nexport type {\n PushSubscriptionStatus,\n PushConfig,\n PushEventData,\n} from \"@bootdesk/js-web-adapter-core\";\nexport { PushManager, createPushSubscriptionHandlers } from \"@bootdesk/js-web-adapter-core\";\n\nexport type { Message, User, Card, PHPCard, CustomCard } from \"@bootdesk/js-web-adapter-core\";\n\nexport {\n WebChatClient,\n PusherBroadcastClient,\n LaravelEchoBroadcastClient,\n} from \"@bootdesk/js-web-adapter-core\";\n","import React, { useState, useCallback, useEffect } from \"react\";\nimport { WebChatClient } from \"@bootdesk/js-web-adapter-core\";\n\nimport { useBridge, useMessages, useTyping } from \"../hooks\";\nimport { FloatingButton } from \"./FloatingButton\";\nimport { Header } from \"./Header\";\nimport { MessageList } from \"./MessageList\";\nimport { InputArea } from \"./InputArea\";\nimport { TypingIndicator } from \"./TypingIndicator\";\n\ntype DisplayMode = \"floating\" | \"fullscreen\" | \"embedded\";\nexport type ThemeMode = \"light\" | \"dark\" | \"auto\";\n\nexport interface ChatWidgetProps {\n client: WebChatClient;\n initialMode?: DisplayMode;\n theme?: ThemeMode;\n onThemeChange?: (theme: ThemeMode) => void;\n position?: \"bottom-right\" | \"bottom-left\" | \"top-right\" | \"top-left\";\n className?: {\n container?: string;\n header?: string;\n messageList?: string;\n inputArea?: string;\n };\n showClose?: boolean;\n showFullscreenToggle?: boolean;\n title?: string;\n placeholder?: string;\n onOpen?: () => void;\n onClose?: () => void;\n embedded?: boolean;\n floatingButton?: {\n icon?: React.ReactNode;\n openIcon?: React.ReactNode;\n badgeCount?: number;\n size?: number;\n backgroundColor?: string;\n ariaLabel?: string;\n className?: string;\n };\n enableAttachments?: boolean;\n uploadConfig?: import(\"../types/AttachmentUpload\").UploadConfig;\n accept?: string;\n maxFileSize?: number;\n renderPushPrompt?: () => React.ReactNode;\n}\n\nexport function ChatWidget({\n client,\n initialMode = \"floating\",\n theme: themeProp,\n onThemeChange,\n position = \"bottom-right\",\n className,\n showClose = true,\n showFullscreenToggle = true,\n title = \"Chat\",\n placeholder = \"Type a message...\",\n onOpen,\n onClose,\n embedded,\n floatingButton,\n enableAttachments = false,\n uploadConfig,\n accept,\n maxFileSize,\n renderPushPrompt,\n}: ChatWidgetProps): React.JSX.Element {\n const {\n config: iframeConfig,\n isInIframe,\n notifyMessage,\n notifyViewportConfig,\n onNotificationClicked,\n } = useBridge();\n\n const autoEmbedded = isInIframe && embedded !== false;\n const effectiveEmbedded = embedded === true || autoEmbedded;\n const effectiveMode = effectiveEmbedded ? \"embedded\" : initialMode;\n\n const [theme, setTheme] = useState<ThemeMode>(() => {\n if (themeProp) return themeProp;\n try {\n const stored = localStorage.getItem(\"chat-theme\");\n if (stored === \"light\" || stored === \"dark\" || stored === \"auto\") return stored;\n } catch {}\n return \"auto\";\n });\n const [systemDark, setSystemDark] = useState(\n () =>\n typeof window !== \"undefined\" && window.matchMedia(\"(prefers-color-scheme: dark)\").matches,\n );\n\n const effectiveTheme: ThemeMode = theme === \"auto\" ? (systemDark ? \"dark\" : \"light\") : theme;\n\n useEffect(() => {\n if (themeProp && themeProp !== theme) {\n setTheme(themeProp);\n try {\n localStorage.setItem(\"chat-theme\", themeProp);\n } catch {}\n }\n }, [themeProp]);\n\n useEffect(() => {\n if (theme !== \"auto\") return;\n const mq = window.matchMedia(\"(prefers-color-scheme: dark)\");\n const handler = (e: MediaQueryListEvent) => setSystemDark(e.matches);\n mq.addEventListener(\"change\", handler);\n return () => mq.removeEventListener(\"change\", handler);\n }, [theme]);\n\n const handleThemeChange = (newTheme: ThemeMode): void => {\n setTheme(newTheme);\n try {\n localStorage.setItem(\"chat-theme\", newTheme);\n } catch {}\n onThemeChange?.(newTheme);\n };\n\n const [isOpen, setIsOpen] = useState(effectiveMode === \"fullscreen\");\n const [displayMode, setDisplayMode] = useState<DisplayMode>(effectiveMode);\n const [isConnected] = useState(true);\n\n const [isSmallScreen, setIsSmallScreen] = useState(\n () => typeof window !== \"undefined\" && window.innerWidth < 800,\n );\n\n useEffect(() => {\n const mq = window.matchMedia(\"(max-width: 799px)\");\n const handler = (e: MediaQueryListEvent) => {\n setIsSmallScreen(e.matches);\n if (e.matches) setDisplayMode(\"fullscreen\");\n };\n setIsSmallScreen(mq.matches);\n if (mq.matches) setDisplayMode(\"fullscreen\");\n mq.addEventListener(\"change\", handler);\n return () => mq.removeEventListener(\"change\", handler);\n }, []);\n\n useEffect(() => {\n if (initialMode !== \"fullscreen\") return;\n if (!isSmallScreen) setIsOpen(true);\n }, [initialMode, isSmallScreen]);\n\n useEffect(() => {\n if (isInIframe) {\n notifyViewportConfig(\"interactive-widget=resizes-content\");\n return () => notifyViewportConfig(\"\");\n }\n\n const isFullscreen = displayMode === \"fullscreen\" || isSmallScreen;\n const active = isOpen && isFullscreen;\n\n const meta = document.querySelector('meta[name=\"viewport\"]');\n if (!meta) return;\n\n if (active) {\n const original = meta.getAttribute(\"content\") ?? \"\";\n if (!original.includes(\"interactive-widget=\")) {\n meta.setAttribute(\"content\", `${original}, interactive-widget=resizes-content`);\n }\n return () => {\n meta.setAttribute(\"content\", original);\n };\n }\n }, [isOpen, displayMode, isSmallScreen, isInIframe, notifyViewportConfig]);\n\n const { messages, sendMessage, loading, isLoadingHistory, reloadMessages } = useMessages(\n client,\n isOpen || effectiveEmbedded,\n );\n const { isSomeoneTyping } = useTyping(client);\n\n useEffect(() => {\n if (!isInIframe || !iframeConfig) return;\n if (iframeConfig.theme?.cssVariables) {\n const root = document.documentElement;\n for (const [key, value] of Object.entries(iframeConfig.theme.cssVariables)) {\n root.style.setProperty(key, value as string);\n }\n }\n const mode = (iframeConfig as any).theme?.mode;\n if (mode === \"light\" || mode === \"dark\" || mode === \"auto\") {\n setTheme(mode);\n }\n }, [isInIframe, iframeConfig]);\n\n useEffect(() => {\n if (!isInIframe) return;\n onNotificationClicked(() => {\n reloadMessages();\n });\n }, [isInIframe, onNotificationClicked, reloadMessages]);\n\n const effectiveTitle = (isInIframe && iframeConfig?.title) || title;\n const effectivePlaceholder = (isInIframe && iframeConfig?.placeholder) || placeholder;\n\n const currentUserId = \"getCurrentUserId\" in client ? client.getCurrentUserId() : \"\";\n\n const handleSend = useCallback(\n async (\n text: string,\n attachments: Array<{ url: string; name: string; mimeType: string; size: number }> = [],\n ) => {\n await sendMessage(text, attachments);\n if (isInIframe) {\n notifyMessage(text);\n }\n },\n [sendMessage, isInIframe, notifyMessage],\n );\n\n const handleActionClick = useCallback(\n (messageId: string, actionId: string, value: string) => {\n client.sendAction(messageId, actionId, value).catch((err) => {\n console.error(\"Action failed:\", err);\n });\n },\n [client],\n );\n\n const handleReactionClick = useCallback((_messageId: string, _emoji: string) => {}, []);\n\n const toggleOpen = useCallback(() => {\n setIsOpen((prev) => {\n if (!prev) onOpen?.();\n else onClose?.();\n return !prev;\n });\n }, [onOpen, onClose]);\n\n const toggleFullscreen = useCallback(() => {\n setDisplayMode((prev) => (prev === \"fullscreen\" ? \"floating\" : \"fullscreen\"));\n }, []);\n\n const close = useCallback(() => {\n setIsOpen(false);\n setDisplayMode(\"floating\");\n onClose?.();\n }, [onClose]);\n\n const embeddedClose = useCallback(() => {\n if (isInIframe) {\n window.parent.postMessage({ type: \"chat-close\" }, \"*\");\n }\n }, [isInIframe]);\n\n if (effectiveEmbedded) {\n return (\n <div\n className=\"flex flex-col h-full min-h-[300px] overflow-hidden bg-chat-background\"\n data-chat-widget=\"embedded\"\n data-chat-theme={effectiveTheme}\n >\n <Header\n title={effectiveTitle}\n isFullscreen={false}\n showConnectionStatus\n isConnected={isConnected}\n className={className?.header}\n theme={theme}\n onThemeChange={handleThemeChange}\n onClose={isInIframe ? embeddedClose : undefined}\n />\n\n <MessageList\n messages={messages}\n currentUserId={currentUserId}\n isLoading={isLoadingHistory || loading}\n onActionClick={handleActionClick}\n onReactionClick={handleReactionClick}\n className={className?.messageList}\n />\n\n {isSomeoneTyping && <TypingIndicator />}\n\n {renderPushPrompt?.()}\n\n <InputArea\n onSend={handleSend}\n placeholder={effectivePlaceholder}\n className={className?.inputArea}\n enableAttachments={enableAttachments}\n uploadConfig={uploadConfig}\n accept={accept}\n maxFileSize={maxFileSize}\n />\n </div>\n );\n }\n\n return (\n <>\n {!effectiveEmbedded && !isOpen && (\n <FloatingButton\n onClick={toggleOpen}\n isOpen={isOpen}\n position={position}\n icon={floatingButton?.icon}\n openIcon={floatingButton?.openIcon}\n badgeCount={floatingButton?.badgeCount}\n size={floatingButton?.size}\n backgroundColor={floatingButton?.backgroundColor}\n ariaLabel={floatingButton?.ariaLabel}\n className={floatingButton?.className}\n />\n )}\n\n {isOpen && (\n <div\n className={`flex flex-col overflow-hidden ${\n displayMode === \"fullscreen\"\n ? \"fixed inset-0 z-50\"\n : `absolute ${position === \"bottom-right\" ? \"bottom-20 right-5\" : position === \"bottom-left\" ? \"bottom-20 left-5\" : \"\"} w-[480px] max-w-[min(800px,calc(100dvw-40px))] h-dvh max-h-[min(600px,80dvh)] z-10 shadow-xl border border-chat-border rounded-2xl`\n } bg-chat-background`}\n data-chat-widget={displayMode}\n data-chat-position={position}\n data-chat-theme={effectiveTheme}\n >\n <Header\n title={effectiveTitle}\n onClose={displayMode === \"floating\" ? close : showClose ? close : undefined}\n onToggleFullscreen={\n showFullscreenToggle && !isSmallScreen ? toggleFullscreen : undefined\n }\n isFullscreen={displayMode === \"fullscreen\"}\n showConnectionStatus\n isConnected={isConnected}\n className={className?.header}\n theme={theme}\n onThemeChange={handleThemeChange}\n />\n\n <MessageList\n messages={messages}\n currentUserId={currentUserId}\n isLoading={isLoadingHistory || loading}\n onActionClick={handleActionClick}\n onReactionClick={handleReactionClick}\n className={className?.messageList}\n />\n\n {isSomeoneTyping && <TypingIndicator />}\n\n {renderPushPrompt?.()}\n\n <InputArea\n onSend={handleSend}\n placeholder={effectivePlaceholder}\n disabled={loading}\n className={className?.inputArea}\n enableAttachments={enableAttachments}\n uploadConfig={uploadConfig}\n accept={accept}\n maxFileSize={maxFileSize}\n />\n </div>\n )}\n </>\n );\n}\n","import { useEffect, useMemo } from \"react\";\nimport { WebChatClient, WebChatClientConfig, BroadcastClient } from \"@bootdesk/js-web-adapter-core\";\n\nexport function useChatClient(\n config: Omit<WebChatClientConfig, \"broadcastClient\"> & {\n broadcastClient?: BroadcastClient;\n },\n): WebChatClient {\n const client = useMemo(() => new WebChatClient(config), [config]);\n\n useEffect(() => {\n client.connect().catch((error) => {\n console.error(\"Failed to connect chat client:\", error);\n });\n\n return () => {\n client.disconnect();\n };\n }, [client]);\n\n return client;\n}\n","import { useState, useEffect, useCallback, useRef } from \"react\";\nimport { WebChatClient } from \"@bootdesk/js-web-adapter-core\";\nimport { Message } from \"@bootdesk/js-web-adapter-core\";\n\ninterface UseMessagesResult {\n messages: Message[];\n loading: boolean;\n isLoadingHistory: boolean;\n hasMore: boolean;\n loadMore: () => Promise<void>;\n reloadMessages: () => Promise<void>;\n retryLoad: () => Promise<void>;\n loadError: Error | null;\n canEdit: boolean;\n canDelete: boolean;\n canReact: boolean;\n sendMessage: (\n text: string,\n attachments?: Array<{\n url: string;\n name: string;\n mimeType: string;\n size: number;\n }>,\n ) => Promise<void>;\n editMessage: (id: string, text: string) => Promise<void>;\n deleteMessage: (id: string) => Promise<void>;\n addReaction: (id: string, emoji: string) => Promise<void>;\n removeReaction: (id: string, emoji: string) => Promise<void>;\n}\n\nexport function useMessages(client: WebChatClient, enabled = true): UseMessagesResult {\n const [messages, setMessages] = useState<Message[]>([]);\n const [loading, setLoading] = useState(false);\n const [isLoadingHistory, setIsLoadingHistory] = useState(false);\n const [hasMore, setHasMore] = useState(false);\n const [nextCursor, setNextCursor] = useState<number | undefined>(undefined);\n const [loadError, setLoadError] = useState<Error | null>(null);\n\n const abortRef = useRef<AbortController | null>(null);\n\n useEffect(() => {\n if (!enabled) return;\n\n if (abortRef.current) {\n abortRef.current.abort();\n }\n\n const controller = new AbortController();\n abortRef.current = controller;\n const { signal } = controller;\n\n setIsLoadingHistory(true);\n setLoadError(null);\n\n const loadInitial = async () => {\n try {\n const result = await client.loadMessages({ limit: 50, skipStateSeed: true }, signal);\n if (signal.aborted) return;\n setMessages(result.messages);\n setHasMore(result.hasMore);\n setNextCursor(result.nextCursor);\n } catch (error) {\n if (signal.aborted) return;\n setLoadError(error instanceof Error ? error : new Error(\"Failed to load messages\"));\n } finally {\n if (!signal.aborted) {\n setIsLoadingHistory(false);\n }\n }\n };\n\n loadInitial();\n\n return () => {\n controller.abort();\n if (abortRef.current === controller) {\n abortRef.current = null;\n }\n };\n }, [client, enabled]);\n\n const reloadMessages = useCallback(async () => {\n setIsLoadingHistory(true);\n setLoadError(null);\n try {\n const result = await client.loadMessages({ limit: 50, skipStateSeed: true });\n setMessages(result.messages);\n setHasMore(result.hasMore);\n setNextCursor(result.nextCursor);\n } catch (error) {\n setLoadError(error instanceof Error ? error : new Error(\"Failed to reload messages\"));\n } finally {\n setIsLoadingHistory(false);\n }\n }, [client]);\n\n const retryLoad = useCallback(async () => {\n setLoadError(null);\n setIsLoadingHistory(true);\n try {\n const result = await client.loadMessages({ limit: 50, skipStateSeed: true });\n setMessages(result.messages);\n setHasMore(result.hasMore);\n setNextCursor(result.nextCursor);\n } catch (error) {\n setLoadError(error instanceof Error ? error : new Error(\"Failed to load messages\"));\n } finally {\n setIsLoadingHistory(false);\n }\n }, [client]);\n\n useEffect(() => {\n const unsubscribes: Array<() => void> = [];\n\n unsubscribes.push(\n client.addEventListener(\"message:added\", (message: Message) => {\n setMessages((prev) => {\n if (prev.some((m) => m.id === message.id)) return prev;\n return [...prev, message];\n });\n }),\n );\n\n const features = client.getFeatures();\n if (features.editMessages) {\n unsubscribes.push(\n client.addEventListener(\n \"message:edited\",\n ({ messageId, newText }: { messageId: string; newText: string }) => {\n setMessages((prev) =>\n prev.map((msg) =>\n msg.id === messageId ? { ...msg, content: { ...msg.content, text: newText } } : msg,\n ),\n );\n },\n ),\n );\n }\n\n if (features.deleteMessages) {\n unsubscribes.push(\n client.addEventListener(\"message:deleted\", ({ messageId }: { messageId: string }) => {\n setMessages((prev) => prev.filter((msg) => msg.id !== messageId));\n }),\n );\n }\n\n if (features.reactions) {\n unsubscribes.push(\n client.addEventListener(\n \"reaction:added\",\n ({ messageId, emoji }: { messageId: string; emoji: string }) => {\n setMessages((prev) =>\n prev.map((msg) => {\n if (msg.id !== messageId || !msg.reactions) return msg;\n const existing = msg.reactions.find((r) => r.emoji === emoji);\n if (existing) {\n return {\n ...msg,\n reactions: msg.reactions.map((r) =>\n r.emoji === emoji ? { ...r, count: r.count + 1 } : r,\n ),\n };\n }\n return {\n ...msg,\n reactions: [...msg.reactions, { emoji, count: 1, users: [] }],\n };\n }),\n );\n },\n ),\n );\n\n unsubscribes.push(\n client.addEventListener(\n \"reaction:removed\",\n ({ messageId, emoji }: { messageId: string; emoji: string }) => {\n setMessages((prev) =>\n prev.map((msg) => {\n if (msg.id !== messageId || !msg.reactions) return msg;\n const idx = msg.reactions.findIndex((r) => r.emoji === emoji);\n if (idx === -1) return msg;\n const updated = [...msg.reactions];\n if (updated[idx].count <= 1) {\n updated.splice(idx, 1);\n } else {\n updated[idx] = { ...updated[idx], count: updated[idx].count - 1 };\n }\n return { ...msg, reactions: updated };\n }),\n );\n },\n ),\n );\n }\n\n return () => {\n unsubscribes.forEach((unsub) => unsub());\n };\n }, [client]);\n\n const sendMessage = useCallback(\n async (\n text: string,\n attachments?: Array<{\n url: string;\n name: string;\n mimeType: string;\n size: number;\n }>,\n ) => {\n setLoading(true);\n try {\n await client.sendMessage(text, attachments || []);\n } finally {\n setLoading(false);\n }\n },\n [client],\n );\n\n const editMessage = useCallback(\n async (id: string, text: string) => {\n if (!client.getFeatures().editMessages) {\n throw new Error(\"Edit messages not enabled. Set features.editMessages = true.\");\n }\n const endpoint = client.getEndpoints().editMessage || \"/api/chat/messages/{id}/edit\";\n await client.getHttpClient().editMessage(id, text, endpoint);\n setMessages((prev) =>\n prev.map((msg) => (msg.id === id ? { ...msg, content: { ...msg.content, text } } : msg)),\n );\n },\n [client],\n );\n\n const deleteMessage = useCallback(\n async (id: string) => {\n if (!client.getFeatures().deleteMessages) {\n throw new Error(\"Delete messages not enabled. Set features.deleteMessages = true.\");\n }\n const endpoint = client.getEndpoints().deleteMessage || \"/api/chat/messages/{id}\";\n await client.getHttpClient().deleteMessage(id, endpoint);\n setMessages((prev) => prev.filter((msg) => msg.id !== id));\n },\n [client],\n );\n\n const addReaction = useCallback(\n async (id: string, emoji: string) => {\n await client.addReaction(id, emoji);\n },\n [client],\n );\n\n const removeReaction = useCallback(\n async (id: string, emoji: string) => {\n await client.removeReaction(id, emoji);\n },\n [client],\n );\n\n const loadMore = useCallback(async () => {\n if (!nextCursor || isLoadingHistory) return;\n\n setIsLoadingHistory(true);\n try {\n const result = await client.loadMessages({\n limit: 50,\n before: nextCursor,\n });\n setMessages((prev) => [...result.messages, ...prev]);\n setHasMore(result.hasMore);\n setNextCursor(result.nextCursor);\n } catch (error) {\n console.error(\"Failed to load more messages:\", error);\n } finally {\n setIsLoadingHistory(false);\n }\n }, [client, nextCursor, isLoadingHistory]);\n\n const features = client.getFeatures();\n const canEdit = !!features.editMessages;\n const canDelete = !!features.deleteMessages;\n const canReact = !!features.reactions;\n\n return {\n messages,\n loading,\n isLoadingHistory,\n hasMore,\n loadMore,\n reloadMessages,\n retryLoad,\n loadError,\n canEdit,\n canDelete,\n canReact,\n sendMessage,\n editMessage,\n deleteMessage,\n addReaction,\n removeReaction,\n };\n}\n","import { useState, useEffect } from \"react\";\nimport { WebChatClient } from \"@bootdesk/js-web-adapter-core\";\n\ninterface StreamingState {\n messageId: string;\n fullText: string;\n isComplete: boolean;\n}\n\ninterface UseStreamingResult {\n streamingMessages: Map<string, StreamingState>;\n isStreaming: boolean;\n}\n\nexport function useStreaming(client: WebChatClient): UseStreamingResult {\n const [streamingMessages, setStreamingMessages] = useState<Map<string, StreamingState>>(\n new Map(),\n );\n\n useEffect(() => {\n const unsub = client.onStreamingChunk((event) => {\n setStreamingMessages((prev) => {\n const next = new Map(prev);\n\n const existing = next.get(event.messageId);\n const newText = (existing?.fullText || \"\") + event.chunk;\n\n if (event.isFinal) {\n next.delete(event.messageId);\n } else {\n next.set(event.messageId, {\n messageId: event.messageId,\n fullText: newText,\n isComplete: event.isFinal,\n });\n }\n\n return next;\n });\n });\n\n return unsub;\n }, [client]);\n\n const isStreaming = streamingMessages.size > 0;\n\n return { streamingMessages, isStreaming };\n}\n","import { useState, useEffect, useRef } from \"react\";\nimport { WebChatClient } from \"@bootdesk/js-web-adapter-core\";\n\ninterface UseTypingResult {\n typingUsers: Set<string>;\n isSomeoneTyping: boolean;\n}\n\nexport function useTyping(client: WebChatClient): UseTypingResult {\n const [typingUsers, setTypingUsers] = useState<Set<string>>(new Set());\n const timeoutsRef = useRef<Map<string, ReturnType<typeof setTimeout>>>(new Map());\n\n useEffect(() => {\n const unsub = client.onTypingStarted((event) => {\n const existing = timeoutsRef.current.get(event.userId);\n if (existing) clearTimeout(existing);\n\n setTypingUsers((prev) => new Set(prev).add(event.userId));\n\n const timeoutId = setTimeout(() => {\n timeoutsRef.current.delete(event.userId);\n setTypingUsers((prev) => {\n const next = new Set(prev);\n next.delete(event.userId);\n return next;\n });\n }, 3000);\n\n timeoutsRef.current.set(event.userId, timeoutId);\n });\n\n return () => {\n unsub();\n for (const id of timeoutsRef.current.values()) {\n clearTimeout(id);\n }\n timeoutsRef.current.clear();\n };\n }, [client]);\n\n const isSomeoneTyping = typingUsers.size > 0;\n\n return { typingUsers, isSomeoneTyping };\n}\n","import { useState, useEffect, useCallback, useRef } from \"react\";\nimport { PushManager, PushConfig, PushSubscriptionStatus } from \"@bootdesk/js-web-adapter-core\";\n\ninterface UsePushNotificationsOptions {\n enabled?: boolean;\n getVapidPublicKey: () => Promise<string>;\n onSubscribe: PushConfig[\"onSubscribe\"];\n onUnsubscribe: PushConfig[\"onUnsubscribe\"];\n serviceWorkerUrl?: string;\n notificationOptions?: PushConfig[\"notificationOptions\"];\n}\n\nexport function usePushNotifications(options: UsePushNotificationsOptions) {\n const { enabled = false } = options;\n const [status, setStatus] = useState<PushSubscriptionStatus>(\"unsupported\");\n const pushManagerRef = useRef<PushManager | null>(null);\n\n useEffect(() => {\n if (!enabled) return;\n\n const pushManager = new PushManager({\n getVapidPublicKey: options.getVapidPublicKey,\n onSubscribe: options.onSubscribe,\n onUnsubscribe: options.onUnsubscribe,\n serviceWorkerUrl: options.serviceWorkerUrl,\n notificationOptions: options.notificationOptions,\n });\n\n pushManagerRef.current = pushManager;\n\n const unsubscribeStatus = pushManager.onStatusChange(setStatus);\n\n pushManager.initialize();\n\n return () => {\n unsubscribeStatus();\n };\n }, [enabled]);\n\n const subscribe = useCallback(async () => {\n await pushManagerRef.current?.subscribe();\n }, []);\n\n const unsubscribe = useCallback(async () => {\n await pushManagerRef.current?.unsubscribe();\n }, []);\n\n return {\n status,\n isSupported: PushManager.isSupported(),\n isSubscribed: status === \"subscribed\",\n subscribe,\n unsubscribe,\n };\n}\n","import { useState, useCallback, useRef } from \"react\";\nimport { PendingAttachment, UploadConfig, isMultiStepUpload } from \"../types/AttachmentUpload\";\n\nfunction generateAttachmentId(): string {\n return `att-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n}\n\nexport function useAttachmentUpload(uploadConfig: UploadConfig) {\n const [attachments, setAttachments] = useState<PendingAttachment[]>([]);\n const abortControllers = useRef<Map<string, AbortController>>(new Map());\n const uploadFileRef = useRef<(attachment: PendingAttachment) => Promise<void>>();\n\n const addFiles = useCallback((files: FileList | File[]) => {\n const fileArray = Array.isArray(files) ? files : Array.from(files);\n\n const newAttachments: PendingAttachment[] = fileArray.map((file) => ({\n id: generateAttachmentId(),\n file,\n name: file.name,\n mimeType: file.type,\n size: file.size,\n status: \"pending\",\n progress: 0,\n }));\n\n setAttachments((prev) => [...prev, ...newAttachments]);\n\n newAttachments.forEach((att) => uploadFileRef.current?.(att));\n }, []);\n\n const uploadFile = useCallback(\n async (attachment: PendingAttachment) => {\n const controller = new AbortController();\n abortControllers.current.set(attachment.id, controller);\n\n try {\n setAttachments((prev) =>\n prev.map((a) =>\n a.id === attachment.id ? { ...a, status: \"uploading\", progress: 0 } : a,\n ),\n );\n\n if (isMultiStepUpload(uploadConfig)) {\n const signedUrl = await uploadConfig.requestSignedUrl({\n name: attachment.name,\n mimeType: attachment.mimeType,\n size: attachment.size,\n });\n\n if (controller.signal.aborted) return;\n\n const uploadSuccess = await uploadConfig.uploadToSignedUrl(\n signedUrl,\n attachment.file,\n (progress) => {\n setAttachments((prev) =>\n prev.map((a) => (a.id === attachment.id ? { ...a, progress } : a)),\n );\n },\n );\n\n if (controller.signal.aborted) return;\n\n if (!uploadSuccess) {\n throw new Error(\"Upload to signed URL failed\");\n }\n\n const finalUrl = await uploadConfig.confirmUpload(signedUrl, {\n name: attachment.name,\n mimeType: attachment.mimeType,\n size: attachment.size,\n });\n\n setAttachments((prev) =>\n prev.map((a) =>\n a.id === attachment.id\n ? { ...a, status: \"uploaded\", progress: 100, url: finalUrl }\n : a,\n ),\n );\n } else {\n const formData = new FormData();\n formData.append(\"file\", attachment.file);\n\n const xhr = new XMLHttpRequest();\n\n xhr.upload.addEventListener(\"progress\", (e) => {\n if (e.lengthComputable) {\n const progress = Math.round((e.loaded / e.total) * 100);\n setAttachments((prev) =>\n prev.map((a) => (a.id === attachment.id ? { ...a, progress } : a)),\n );\n }\n });\n\n const response = await new Promise<{ url: string }>((resolve, reject) => {\n xhr.onload = () => {\n if (xhr.status >= 200 && xhr.status < 300) {\n resolve(JSON.parse(xhr.responseText));\n } else {\n reject(new Error(`Upload failed: ${xhr.status}`));\n }\n };\n xhr.onerror = () => reject(new Error(\"Network error\"));\n xhr.onabort = () => reject(new Error(\"Upload cancelled\"));\n\n xhr.open(\"POST\", uploadConfig.endpoint);\n if (uploadConfig.headers) {\n Object.entries(uploadConfig.headers).forEach(([key, value]) => {\n xhr.setRequestHeader(key, value);\n });\n }\n xhr.send(formData);\n });\n\n setAttachments((prev) =>\n prev.map((a) =>\n a.id === attachment.id\n ? { ...a, status: \"uploaded\", progress: 100, url: response.url }\n : a,\n ),\n );\n }\n } catch (error) {\n if (controller.signal.aborted) return;\n\n setAttachments((prev) =>\n prev.map((a) =>\n a.id === attachment.id\n ? {\n ...a,\n status: \"error\",\n error: error instanceof Error ? error.message : \"Upload failed\",\n }\n : a,\n ),\n );\n } finally {\n abortControllers.current.delete(attachment.id);\n }\n },\n [uploadConfig],\n );\n\n uploadFileRef.current = uploadFile;\n\n const removeAttachment = useCallback((id: string) => {\n const controller = abortControllers.current.get(id);\n if (controller) {\n controller.abort();\n }\n setAttachments((prev) => prev.filter((a) => a.id !== id));\n }, []);\n\n const clearAttachments = useCallback(() => {\n abortControllers.current.forEach((c) => c.abort());\n abortControllers.current.clear();\n setAttachments([]);\n }, []);\n\n const resetUploads = useCallback(() => {\n setAttachments((prev) =>\n prev.map((a) =>\n a.status === \"error\" ? { ...a, status: \"pending\", progress: 0, error: undefined } : a,\n ),\n );\n }, []);\n\n const getUploadedAttachments = useCallback(() => {\n return attachments.filter((a) => a.status === \"uploaded\" && a.url);\n }, [attachments]);\n\n const isUploading = attachments.some((a) => a.status === \"uploading\");\n\n const isComplete =\n attachments.length > 0 &&\n attachments.every((a) => a.status === \"uploaded\" || a.status === \"error\");\n\n return {\n attachments,\n addFiles,\n removeAttachment,\n clearAttachments,\n resetUploads,\n getUploadedAttachments,\n isUploading,\n isComplete,\n };\n}\n","export interface PendingAttachment {\n id: string;\n file: File;\n name: string;\n mimeType: string;\n size: number;\n status: \"pending\" | \"uploading\" | \"uploaded\" | \"error\";\n progress: number;\n url?: string;\n error?: string;\n}\n\nexport interface SignedUploadUrl {\n uploadUrl: string;\n finalUrl: string;\n headers?: Record<string, string>;\n metadata?: Record<string, unknown>;\n}\n\nexport interface AttachmentUploadConfig {\n requestSignedUrl: (file: {\n name: string;\n mimeType: string;\n size: number;\n }) => Promise<SignedUploadUrl>;\n uploadToSignedUrl: (\n signedUrl: SignedUploadUrl,\n file: File,\n onProgress?: (pct: number) => void,\n ) => Promise<boolean>;\n confirmUpload: (\n signedUrl: SignedUploadUrl,\n fileMeta: { name: string; mimeType: string; size: number },\n ) => Promise<string>;\n}\n\nexport interface SimpleUploadConfig {\n endpoint: string;\n headers?: Record<string, string>;\n}\n\nexport type UploadConfig = AttachmentUploadConfig | SimpleUploadConfig;\n\nexport function isMultiStepUpload(config: UploadConfig): config is AttachmentUploadConfig {\n return \"requestSignedUrl\" in config;\n}\n","import { useState, useCallback, useEffect, useRef } from \"react\";\n\ninterface BridgeResult {\n config: any;\n isInIframe: boolean;\n notifyMessage: (text: string) => void;\n notifyViewportConfig: (viewportContent: string) => void;\n onNotificationClicked: (cb: () => void) => void;\n}\n\nexport function useBridge(): BridgeResult {\n const notificationCbRef = useRef<(() => void) | null>(null);\n const [config, setConfig] = useState<any>(null);\n\n const isInIframe = typeof window !== \"undefined\" && window !== window.parent;\n\n const notifyMessage = useCallback(\n (text: string) => {\n if (!isInIframe) return;\n window.parent.postMessage({ type: \"chat-message\", text }, \"*\");\n },\n [isInIframe],\n );\n\n const notifyViewportConfig = useCallback(\n (viewportContent: string) => {\n if (!isInIframe) return;\n window.parent.postMessage({ type: \"chat-viewport-config\", content: viewportContent }, \"*\");\n },\n [isInIframe],\n );\n\n const onNotificationClicked = useCallback((cb: () => void) => {\n notificationCbRef.current = cb;\n }, []);\n\n useEffect(() => {\n if (!isInIframe) return;\n\n function handleMessage(event: MessageEvent) {\n const data = event.data as Record<string, unknown>;\n if (!data || typeof data !== \"object\" || !data.type) return;\n\n if (data.type === \"chat-config\") {\n const configData = { ...data };\n delete configData.type;\n setConfig(configData);\n }\n\n if (data.type === \"chat-notification-clicked\") {\n notificationCbRef.current?.();\n }\n }\n\n window.addEventListener(\"message\", handleMessage);\n return () => window.removeEventListener(\"message\", handleMessage);\n }, [isInIframe]);\n\n return { config, isInIframe, notifyMessage, notifyViewportConfig, onNotificationClicked };\n}\n","import React, { createContext, useContext, useMemo } from \"react\";\nimport { LocaleStrings, LocaleConfig } from \"./types\";\nimport { mergeLocale } from \"./mergeLocale\";\n\ninterface LocaleContextValue {\n locale: string;\n strings: LocaleStrings;\n t: (path: string) => string;\n}\n\nconst LocaleContext = createContext<LocaleContextValue | undefined>(undefined);\n\ninterface LocaleProviderProps {\n children: React.ReactNode;\n locale?: LocaleConfig | string;\n}\n\nexport function LocaleProvider({ children, locale }: LocaleProviderProps): React.JSX.Element {\n const config = useMemo<LocaleConfig>(() => {\n if (!locale) return { locale: \"en\" };\n if (typeof locale === \"string\") return { locale };\n return locale;\n }, [locale]);\n\n const value = useMemo(() => {\n const strings = mergeLocale(config.locale, config.overrides);\n\n const t = (path: string): string => {\n const parts = path.split(\".\");\n let current: any = strings;\n for (const part of parts) {\n if (current == null) return path;\n current = current[part];\n }\n return typeof current === \"string\" ? current : path;\n };\n\n return { locale: config.locale, strings, t };\n }, [config.locale, config.overrides]);\n\n return <LocaleContext.Provider value={value}>{children}</LocaleContext.Provider>;\n}\n\nexport function useLocale(): LocaleContextValue {\n const context = useContext(LocaleContext);\n if (!context) {\n const strings = mergeLocale(\"en\");\n return {\n locale: \"en\",\n strings,\n t: (path: string) => {\n const parts = path.split(\".\");\n let current: any = strings;\n for (const part of parts) {\n if (current == null) return path;\n current = current[part];\n }\n return typeof current === \"string\" ? current : path;\n },\n };\n }\n return context;\n}\n","export interface LocaleStrings {\n chatWidget: {\n title: string;\n placeholder: string;\n openChat: string;\n closeChat: string;\n connectionStatus: {\n connected: string;\n disconnected: string;\n };\n };\n inputArea: {\n send: string;\n uploading: string;\n dropzone: {\n dropFiles: string;\n dropOrClick: string;\n };\n };\n typingIndicator: {\n typing: string;\n isTyping: string;\n };\n messageList: {\n emptyState: string;\n };\n attachmentList: {\n remove: string;\n uploadFailed: string;\n };\n header: {\n enterFullscreen: string;\n exitFullscreen: string;\n closeChat: string;\n lightMode: string;\n darkMode: string;\n autoMode: string;\n };\n floatingButton: {\n openChat: string;\n closeChat: string;\n };\n common: {\n loading: string;\n error: string;\n retry: string;\n cancel: string;\n download: string;\n };\n}\n\nexport type SupportedLocale = \"en\" | \"en-US\" | \"en-GB\" | \"pt\" | \"pt-BR\" | \"pt-PT\" | \"es\";\n\nexport function getBaseLocale(locale: string): string {\n return locale.split(\"-\")[0] || locale;\n}\n\nexport function getFallbackChain(locale: string): string[] {\n const base = getBaseLocale(locale);\n if (locale === base) {\n return [locale, \"en\"];\n }\n return [locale, base, \"en\"];\n}\n\nexport type PartialLocaleStrings = Partial<{\n [K in keyof LocaleStrings]: Partial<LocaleStrings[K]>;\n}> & {\n chatWidget?: Partial<LocaleStrings[\"chatWidget\"]> & {\n connectionStatus?: Partial<LocaleStrings[\"chatWidget\"][\"connectionStatus\"]>;\n };\n inputArea?: Partial<LocaleStrings[\"inputArea\"]> & {\n dropzone?: Partial<LocaleStrings[\"inputArea\"][\"dropzone\"]>;\n };\n messageList?: Partial<LocaleStrings[\"messageList\"]>;\n common?: Partial<LocaleStrings[\"common\"]>;\n};\n\nexport interface LocaleConfig {\n locale: string;\n overrides?: PartialLocaleStrings;\n}\n","{\n \"chatWidget\": {\n \"title\": \"Chat\",\n \"placeholder\": \"Type a message...\",\n \"openChat\": \"Open chat\",\n \"closeChat\": \"Close chat\",\n \"connectionStatus\": {\n \"connected\": \"Connected\",\n \"disconnected\": \"Disconnected\"\n }\n },\n \"inputArea\": {\n \"send\": \"Send\",\n \"uploading\": \"Uploading...\",\n \"dropzone\": {\n \"dropFiles\": \"Drop files here\",\n \"dropOrClick\": \"Drop or click to attach\"\n }\n },\n \"typingIndicator\": {\n \"typing\": \"typing\",\n \"isTyping\": \"is typing...\"\n },\n \"messageList\": {\n \"emptyState\": \"No messages yet. Start the conversation!\"\n },\n \"attachmentList\": {\n \"remove\": \"Remove\",\n \"uploadFailed\": \"Upload failed\"\n },\n \"header\": {\n \"enterFullscreen\": \"Enter fullscreen\",\n \"exitFullscreen\": \"Exit fullscreen\",\n \"closeChat\": \"Close chat\",\n \"lightMode\": \"Light mode\",\n \"darkMode\": \"Dark mode\",\n \"autoMode\": \"System theme\"\n },\n \"floatingButton\": {\n \"openChat\": \"Open chat\",\n \"closeChat\": \"Close chat\"\n },\n \"common\": {\n \"loading\": \"Loading...\",\n \"error\": \"Error\",\n \"retry\": \"Retry\",\n \"cancel\": \"Cancel\",\n \"download\": \"Download\"\n }\n}\n","{\n \"chatWidget\": {\n \"title\": \"Chat\"\n }\n}\n","{\n \"chatWidget\": {\n \"title\": \"Chat\"\n },\n \"common\": {\n \"loading\": \"Loading...\"\n }\n}\n","{\n \"chatWidget\": {\n \"title\": \"Chat\",\n \"placeholder\": \"Digite uma mensagem...\",\n \"openChat\": \"Abrir chat\",\n \"closeChat\": \"Fechar chat\",\n \"connectionStatus\": {\n \"connected\": \"Conectado\",\n \"disconnected\": \"Desconectado\"\n }\n },\n \"inputArea\": {\n \"send\": \"Enviar\",\n \"uploading\": \"Enviando...\",\n \"dropzone\": {\n \"dropFiles\": \"Solte arquivos aqui\",\n \"dropOrClick\": \"Solte ou clique para anexar\"\n }\n },\n \"typingIndicator\": {\n \"typing\": \"digitando\",\n \"isTyping\": \"está digitando...\"\n },\n \"messageList\": {\n \"emptyState\": \"Nenhuma mensagem ainda. Inicie a conversa!\"\n },\n \"attachmentList\": {\n \"remove\": \"Remover\",\n \"uploadFailed\": \"Falha no envio\"\n },\n \"header\": {\n \"enterFullscreen\": \"Tela cheia\",\n \"exitFullscreen\": \"Sair da tela cheia\",\n \"closeChat\": \"Fechar chat\"\n },\n \"floatingButton\": {\n \"openChat\": \"Abrir chat\",\n \"closeChat\": \"Fechar chat\"\n },\n \"common\": {\n \"loading\": \"Carregando...\",\n \"error\": \"Erro\",\n \"retry\": \"Tentar novamente\",\n \"cancel\": \"Cancelar\",\n \"download\": \"Baixar\"\n }\n}\n","{\n \"chatWidget\": {\n \"placeholder\": \"Digite uma mensagem...\"\n },\n \"inputArea\": {\n \"send\": \"Enviar\",\n \"uploading\": \"Enviando...\",\n \"dropzone\": {\n \"dropFiles\": \"Solte arquivos aqui\",\n \"dropOrClick\": \"Solte ou clique para anexar\"\n }\n },\n \"typingIndicator\": {\n \"isTyping\": \"está digitando...\"\n },\n \"attachmentList\": {\n \"uploadFailed\": \"Falha no envio\"\n },\n \"common\": {\n \"loading\": \"Carregando...\",\n \"retry\": \"Tentar novamente\"\n }\n}\n","{\n \"chatWidget\": {\n \"placeholder\": \"Escreva uma mensagem...\"\n },\n \"inputArea\": {\n \"send\": \"Enviar\",\n \"uploading\": \"A enviar...\",\n \"dropzone\": {\n \"dropFiles\": \"Largue ficheiros aqui\",\n \"dropOrClick\": \"Largue ou clique para anexar\"\n }\n },\n \"typingIndicator\": {\n \"isTyping\": \"está a escrever...\"\n },\n \"attachmentList\": {\n \"uploadFailed\": \"Falha no envio\"\n },\n \"common\": {\n \"loading\": \"A carregar...\",\n \"retry\": \"Tentar novamente\"\n }\n}\n","{\n \"chatWidget\": {\n \"title\": \"Chat\",\n \"placeholder\": \"Escribe un mensaje...\",\n \"openChat\": \"Abrir chat\",\n \"closeChat\": \"Cerrar chat\",\n \"connectionStatus\": {\n \"connected\": \"Conectado\",\n \"disconnected\": \"Desconectado\"\n }\n },\n \"inputArea\": {\n \"send\": \"Enviar\",\n \"uploading\": \"Subiendo...\",\n \"dropzone\": {\n \"dropFiles\": \"Suelta archivos aquí\",\n \"dropOrClick\": \"Suelta o haz clic para adjuntar\"\n }\n },\n \"typingIndicator\": {\n \"typing\": \"escribiendo\",\n \"isTyping\": \"está escribiendo...\"\n },\n \"messageList\": {\n \"emptyState\": \"No hay mensajes todavía. ¡Inicia la conversación!\"\n },\n \"attachmentList\": {\n \"remove\": \"Eliminar\",\n \"uploadFailed\": \"Error al subir\"\n },\n \"header\": {\n \"enterFullscreen\": \"Pantalla completa\",\n \"exitFullscreen\": \"Salir de pantalla completa\",\n \"closeChat\": \"Cerrar chat\"\n },\n \"floatingButton\": {\n \"openChat\": \"Abrir chat\",\n \"closeChat\": \"Cerrar chat\"\n },\n \"common\": {\n \"loading\": \"Cargando...\",\n \"error\": \"Error\",\n \"retry\": \"Reintentar\",\n \"cancel\": \"Cancelar\",\n \"download\": \"Descargar\"\n }\n}\n","import { LocaleStrings, PartialLocaleStrings, getFallbackChain } from \"./types\";\nimport en from \"./locales/en.json\";\nimport enUS from \"./locales/en-US.json\";\nimport enGB from \"./locales/en-GB.json\";\nimport pt from \"./locales/pt.json\";\nimport ptBR from \"./locales/pt-BR.json\";\nimport ptPT from \"./locales/pt-PT.json\";\nimport es from \"./locales/es.json\";\n\nfunction deepMerge(target: Record<string, any>, source: Record<string, any>): Record<string, any> {\n const result: Record<string, any> = { ...target };\n for (const key of Object.keys(source)) {\n const sourceVal = source[key];\n const targetVal = target[key];\n if (\n sourceVal &&\n typeof sourceVal === \"object\" &&\n !Array.isArray(sourceVal) &&\n targetVal &&\n typeof targetVal === \"object\" &&\n !Array.isArray(targetVal)\n ) {\n result[key] = deepMerge(targetVal, sourceVal);\n } else if (sourceVal !== undefined) {\n result[key] = sourceVal;\n }\n }\n return result;\n}\n\nconst systemLocales: Record<string, LocaleStrings> = {\n en: en as LocaleStrings,\n \"en-US\": deepMerge(en as LocaleStrings, enUS as Partial<LocaleStrings>) as LocaleStrings,\n \"en-GB\": deepMerge(en as LocaleStrings, enGB as Partial<LocaleStrings>) as LocaleStrings,\n pt: pt as LocaleStrings,\n \"pt-BR\": deepMerge(pt as LocaleStrings, ptBR as Partial<LocaleStrings>) as LocaleStrings,\n \"pt-PT\": deepMerge(pt as LocaleStrings, ptPT as Partial<LocaleStrings>) as LocaleStrings,\n es: es as LocaleStrings,\n};\n\nexport function registerLocale(locale: string, strings: LocaleStrings): void {\n systemLocales[locale] = strings;\n}\n\nexport function mergeLocale(locale: string, overrides?: PartialLocaleStrings): LocaleStrings {\n const chain = getFallbackChain(locale);\n\n let base = systemLocales[\"en\"] || (en as LocaleStrings);\n\n for (const code of chain) {\n if (code === \"en\") continue;\n const localeStrings = systemLocales[code];\n if (localeStrings) {\n base = deepMerge(base, localeStrings) as unknown as LocaleStrings;\n }\n }\n\n if (!overrides) return base;\n\n return deepMerge(base, overrides) as LocaleStrings;\n}\n\nexport function getAvailableLocales(): string[] {\n return Object.keys(systemLocales);\n}\n","import React from \"react\";\nimport { useLocale } from \"../i18n/LocaleProvider\";\n\ninterface FloatingButtonProps {\n onClick: () => void;\n isOpen: boolean;\n position?: \"bottom-right\" | \"bottom-left\" | \"top-right\" | \"top-left\";\n className?: string;\n icon?: React.ReactNode;\n openIcon?: React.ReactNode;\n badgeCount?: number;\n size?: number;\n backgroundColor?: string;\n ariaLabel?: string;\n}\n\nexport function FloatingButton({\n onClick,\n isOpen,\n position = \"bottom-right\",\n className,\n icon,\n openIcon,\n badgeCount,\n size = 60,\n backgroundColor,\n ariaLabel,\n}: FloatingButtonProps): React.JSX.Element {\n const { t } = useLocale();\n\n const positionClasses: Record<string, string> = {\n \"bottom-right\": \"fixed bottom-5 right-5\",\n \"bottom-left\": \"fixed bottom-5 left-5\",\n \"top-right\": \"fixed top-5 right-5\",\n \"top-left\": \"fixed top-5 left-5\",\n };\n\n const iconSize = Math.floor(size * 0.4);\n\n return (\n <button\n onClick={onClick}\n className={`${positionClasses[position]} chat-floating-button hover:scale-105 transition-transform ${className || \"\"}`}\n style={{ width: size, height: size, backgroundColor }}\n data-chat-floating-button=\"true\"\n data-testid=\"chat-floating-button\"\n aria-label={\n ariaLabel || (isOpen ? t(\"floatingButton.closeChat\") : t(\"floatingButton.openChat\"))\n }\n >\n {badgeCount && badgeCount > 0 && (\n <span\n className=\"absolute -top-1 -right-1 min-w-5 h-5 rounded-full bg-chat-error text-white text-xs font-bold flex items-center justify-center px-1\"\n data-chat-badge=\"true\"\n >\n {badgeCount > 99 ? \"99+\" : badgeCount}\n </span>\n )}\n\n {isOpen\n ? openIcon ||\n icon || (\n <svg\n width={iconSize}\n height={iconSize}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"#fff\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M18 6L6 18M6 6l12 12\" />\n </svg>\n )\n : icon || (\n <svg\n width={iconSize}\n height={iconSize}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"#fff\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\" />\n </svg>\n )}\n </button>\n );\n}\n","import React from \"react\";\nimport { useLocale } from \"../i18n/LocaleProvider\";\n\ninterface HeaderProps {\n title?: string;\n onClose?: () => void;\n onToggleFullscreen?: () => void;\n isFullscreen?: boolean;\n showConnectionStatus?: boolean;\n isConnected?: boolean;\n className?: string;\n theme?: string;\n onThemeChange?: (theme: \"light\" | \"dark\" | \"auto\") => void;\n}\n\nexport function Header({\n title = \"Chat\",\n onClose,\n onToggleFullscreen,\n isFullscreen = false,\n showConnectionStatus = true,\n isConnected = true,\n className,\n theme,\n onThemeChange,\n}: HeaderProps): React.JSX.Element {\n const { t } = useLocale();\n\n return (\n <div\n className={`chat-header ${className || \"\"}`}\n data-chat-header=\"true\"\n data-testid=\"chat-header\"\n >\n <div className=\"flex items-center gap-2\">\n {showConnectionStatus && (\n <div\n className={`w-2 h-2 rounded-full ${isConnected ? \"bg-chat-success\" : \"bg-chat-error\"}`}\n data-chat-connection-status=\"true\"\n title={isConnected ? \"Connected\" : \"Disconnected\"}\n />\n )}\n <h2 className=\"m-0 text-base font-semibold text-chat-text\">{title}</h2>\n </div>\n\n <div className=\"flex items-center gap-1\">\n {onThemeChange && (\n <button\n onClick={() =>\n onThemeChange(theme === \"light\" ? \"dark\" : theme === \"dark\" ? \"auto\" : \"light\")\n }\n className=\"p-1 bg-transparent border-none cursor-pointer text-chat-text-secondary rounded hover:bg-chat-surface transition\"\n data-chat-theme-toggle=\"true\"\n aria-label={\n theme === \"light\"\n ? t(\"header.darkMode\")\n : theme === \"dark\"\n ? t(\"header.autoMode\")\n : t(\"header.lightMode\")\n }\n title={\n theme === \"light\"\n ? t(\"header.darkMode\")\n : theme === \"dark\"\n ? t(\"header.autoMode\")\n : t(\"header.lightMode\")\n }\n >\n {theme === \"light\" ? (\n <svg\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z\" />\n </svg>\n ) : theme === \"dark\" ? (\n <svg\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"5\" />\n <line x1=\"12\" y1=\"1\" x2=\"12\" y2=\"3\" />\n <line x1=\"12\" y1=\"21\" x2=\"12\" y2=\"23\" />\n <line x1=\"4.22\" y1=\"4.22\" x2=\"5.64\" y2=\"5.64\" />\n <line x1=\"18.36\" y1=\"18.36\" x2=\"19.78\" y2=\"19.78\" />\n <line x1=\"1\" y1=\"12\" x2=\"3\" y2=\"12\" />\n <line x1=\"21\" y1=\"12\" x2=\"23\" y2=\"12\" />\n <line x1=\"4.22\" y1=\"19.78\" x2=\"5.64\" y2=\"18.36\" />\n <line x1=\"18.36\" y1=\"5.64\" x2=\"19.78\" y2=\"4.22\" />\n </svg>\n ) : (\n <svg\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <rect x=\"2\" y=\"3\" width=\"20\" height=\"14\" rx=\"2\" ry=\"2\" />\n <line x1=\"8\" y1=\"21\" x2=\"16\" y2=\"21\" />\n <line x1=\"12\" y1=\"17\" x2=\"12\" y2=\"21\" />\n </svg>\n )}\n </button>\n )}\n\n {onToggleFullscreen && (\n <button\n onClick={onToggleFullscreen}\n className=\"p-1 bg-transparent border-none cursor-pointer text-chat-text-secondary rounded hover:bg-chat-surface transition\"\n data-chat-fullscreen-toggle=\"true\"\n aria-label={isFullscreen ? t(\"header.exitFullscreen\") : t(\"header.enterFullscreen\")}\n title={isFullscreen ? t(\"header.exitFullscreen\") : t(\"header.enterFullscreen\")}\n >\n {isFullscreen ? (\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M8 3v3a2 2 0 0 1-2 2H3m18 0h-3a2 2 0 0 1-2-2V3m0 18v-3a2 2 0 0 1 2-2h3M3 16h3a2 2 0 0 1 2 2v3\" />\n </svg>\n ) : (\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3\" />\n </svg>\n )}\n </button>\n )}\n\n {onClose && (\n <button\n onClick={onClose}\n className=\"p-1 bg-transparent border-none cursor-pointer text-chat-text-secondary rounded hover:bg-chat-surface transition\"\n data-chat-close=\"true\"\n aria-label={t(\"header.closeChat\")}\n >\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n >\n <path d=\"M18 6L6 18M6 6l12 12\" />\n </svg>\n </button>\n )}\n </div>\n </div>\n );\n}\n","import React, { useRef, useEffect, useMemo } from \"react\";\nimport { Message } from \"@bootdesk/js-web-adapter-core\";\nimport { MessageContent } from \"./MessageContent\";\nimport { useLocale } from \"../i18n/LocaleProvider\";\nimport { formatTimestamp } from \"../utils/formatTimestamp\";\n\ninterface MessageListProps {\n messages: Message[];\n currentUserId: string;\n isLoading?: boolean;\n onReactionClick?: (messageId: string, emoji: string) => void;\n onActionClick?: (messageId: string, actionId: string, value: string) => void;\n className?: string;\n}\n\nexport function MessageList({\n messages,\n currentUserId,\n isLoading = false,\n onReactionClick,\n onActionClick,\n className,\n}: MessageListProps): React.JSX.Element {\n const { t } = useLocale();\n const containerRef = useRef<HTMLDivElement>(null);\n const listEndRef = useRef<HTMLDivElement>(null);\n const hasInitiallyScrolled = useRef(false);\n const isNearBottom = useRef(true);\n\n useEffect(() => {\n if (!hasInitiallyScrolled.current && messages.length > 0) {\n listEndRef.current?.scrollIntoView?.();\n hasInitiallyScrolled.current = true;\n }\n }, [messages.length]);\n\n const prevMessagesLength = useRef(messages.length);\n\n useEffect(() => {\n if (messages.length > prevMessagesLength.current) {\n listEndRef.current?.scrollIntoView?.({ behavior: \"smooth\" });\n }\n prevMessagesLength.current = messages.length;\n }, [messages.length]);\n\n useEffect(() => {\n const el = containerRef.current;\n if (!el) return;\n\n const handleScroll = () => {\n const threshold = 100;\n isNearBottom.current = el.scrollHeight - el.scrollTop - el.clientHeight < threshold;\n };\n\n el.addEventListener(\"scroll\", handleScroll, { passive: true });\n\n const observer = new ResizeObserver(() => {\n if (isNearBottom.current) {\n listEndRef.current?.scrollIntoView?.({ behavior: \"smooth\" });\n }\n });\n\n observer.observe(el);\n\n return () => {\n el.removeEventListener(\"scroll\", handleScroll);\n observer.disconnect();\n };\n }, []);\n\n const groupedMessages = useMemo(() => {\n const groups: Array<{ user: string; messages: Message[] }> = [];\n let currentGroup: { user: string; messages: Message[] } | null = null;\n\n for (const message of messages) {\n const userId = message.author.id;\n\n if (!currentGroup || currentGroup.user !== userId) {\n if (currentGroup) {\n groups.push(currentGroup);\n }\n currentGroup = { user: userId, messages: [message] };\n } else {\n currentGroup.messages.push(message);\n }\n }\n\n if (currentGroup) {\n groups.push(currentGroup);\n }\n\n return groups;\n }, [messages]);\n\n return (\n <div\n ref={containerRef}\n className={`chat-message-list flex-1 min-h-0 overflow-y-auto ${className || \"\"}`}\n data-chat-message-list=\"true\"\n data-testid=\"chat-message-list\"\n >\n {groupedMessages.length === 0 && !isLoading && (\n <div className=\"flex flex-col items-center justify-center h-full min-h-[200px] text-center px-6\">\n <div className=\"text-chat-text-secondary text-sm\">{t(\"messageList.emptyState\")}</div>\n </div>\n )}\n\n {groupedMessages.map((group, groupIndex) => {\n const isOwn = group.user === currentUserId;\n const firstMessage = group.messages[0]!;\n\n return (\n <div key={`${group.user}-${groupIndex}`} className=\"flex flex-col gap-1\">\n {firstMessage.author.name && (\n <div className=\"text-xs text-chat-text-secondary\">{firstMessage.author.name}</div>\n )}\n\n {group.messages.map((message, msgIndex) => (\n <div key={message.id} className=\"flex flex-col\" data-chat-message-id={message.id}>\n <div className={isOwn ? \"chat-message-bubble-own\" : \"chat-message-bubble-other\"}>\n <MessageContent message={message} onActionClick={onActionClick} />\n </div>\n\n {message.reactions && message.reactions.length > 0 && (\n <div className=\"flex gap-1 mt-1\">\n {message.reactions.map((reaction, rIndex) => (\n <button\n key={`${reaction.emoji}-${rIndex}`}\n onClick={() => onReactionClick?.(message.id, reaction.emoji)}\n className={`flex items-center gap-1 px-2 py-0.5 border border-chat-border rounded-full text-sm cursor-pointer transition ${\n reaction.hasReacted\n ? \"bg-chat-surface\"\n : \"bg-transparent hover:bg-chat-surface\"\n }`}\n data-chat-reaction={reaction.emoji}\n >\n <span>{reaction.emoji}</span>\n <span className=\"text-chat-text-secondary\">{reaction.count}</span>\n </button>\n ))}\n </div>\n )}\n\n {msgIndex === 0 && (\n <div className=\"text-xs text-chat-text-secondary mt-1\">\n {formatTimestamp(message.timestamp)}\n </div>\n )}\n </div>\n ))}\n </div>\n );\n })}\n\n {isLoading && groupedMessages.length === 0 && (\n <div className=\"flex items-center justify-center min-h-[200px]\" data-chat-loading=\"true\">\n <div className=\"flex gap-1.5\">\n <span\n className=\"w-2 h-2 rounded-full bg-chat-text-secondary animate-bounce\"\n style={{ animationDelay: \"0ms\" }}\n />\n <span\n className=\"w-2 h-2 rounded-full bg-chat-text-secondary animate-bounce\"\n style={{ animationDelay: \"160ms\" }}\n />\n <span\n className=\"w-2 h-2 rounded-full bg-chat-text-secondary animate-bounce\"\n style={{ animationDelay: \"320ms\" }}\n />\n </div>\n </div>\n )}\n\n {isLoading && groupedMessages.length > 0 && (\n <div className=\"flex justify-center py-4\" data-chat-loading=\"true\">\n <div className=\"text-chat-text-secondary\">{t(\"common.loading\")}</div>\n </div>\n )}\n\n <div ref={listEndRef} className=\"h-px\" />\n </div>\n );\n}\n","import React, { createContext, useContext, useMemo } from \"react\";\nimport { CardRenderer, CardRendererMap } from \"./types\";\nimport { DefaultCard } from \"./DefaultCard\";\nimport { ImageCardComponent } from \"./ImageCard\";\nimport { FileCardComponent } from \"./FileCard\";\n\ninterface CardContextValue {\n renderers: CardRendererMap;\n registerRenderer: (type: string, renderer: CardRenderer) => void;\n getRenderer: (type: string) => CardRenderer | undefined;\n}\n\nconst CardContext = createContext<CardContextValue | undefined>(undefined);\n\ninterface CardProviderProps {\n children: React.ReactNode;\n renderers?: Record<string, CardRenderer>;\n}\n\nexport function CardProvider({ children, renderers }: CardProviderProps): React.JSX.Element {\n const value = useMemo(() => {\n const defaultRenderers: CardRendererMap = new Map([\n [\"card\", DefaultCard],\n [\"image\", ImageCardComponent],\n [\"file\", FileCardComponent],\n ]);\n\n if (renderers) {\n Object.entries(renderers).forEach(([type, renderer]) => {\n defaultRenderers.set(type, renderer);\n });\n }\n\n return {\n renderers: defaultRenderers,\n registerRenderer: (type: string, renderer: CardRenderer) => {\n defaultRenderers.set(type, renderer);\n },\n getRenderer: (type: string) => {\n return defaultRenderers.get(type);\n },\n };\n }, [renderers]);\n\n return <CardContext.Provider value={value}>{children}</CardContext.Provider>;\n}\n\nexport function useCardRegistry() {\n const context = useContext(CardContext);\n if (!context) {\n throw new Error(\"useCardRegistry must be used within CardProvider\");\n }\n return context;\n}\n","import React from \"react\";\nimport { marked } from \"marked\";\nimport DOMPurify from \"dompurify\";\n\nconst renderer = new marked.Renderer();\nrenderer.link = ({ href, text }): string => {\n return `<a href=\"${href}\" target=\"_blank\" rel=\"noopener noreferrer\">${text}</a>`;\n};\n\nmarked.setOptions({\n gfm: true,\n breaks: true,\n renderer,\n});\n\nexport function renderMarkdown(text: string): string {\n const rawHtml = marked.parse(text) as string;\n return DOMPurify.sanitize(rawHtml, { ADD_ATTR: [\"target\"] });\n}\n\nexport function MarkdownRenderer({\n text,\n className,\n}: {\n text: string;\n className?: string;\n}): React.JSX.Element {\n return (\n <div\n className={`prose prose-sm max-w-none prose-headings:font-semibold prose-a:text-chat-primary prose-a:no-underline hover:prose-a:underline prose-code:bg-chat-surface prose-code:px-1 prose-code:py-0.5 prose-code:rounded prose-code:font-mono prose-code:text-sm prose-blockquote:border-l-chat-border prose-blockquote:text-chat-text-secondary ${className || \"\"}`}\n dangerouslySetInnerHTML={{ __html: renderMarkdown(text) }}\n />\n );\n}\n","import React from \"react\";\nimport { PHPCard } from \"@bootdesk/js-web-adapter-core\";\nimport { CardRendererProps } from \"./types\";\nimport { MarkdownRenderer } from \"../utils/markdown\";\n\nexport function DefaultCard({\n card: rawCard,\n onActionClick,\n}: CardRendererProps): React.JSX.Element | null {\n if (rawCard.type !== \"card\") {\n return null;\n }\n\n const card = rawCard as PHPCard;\n\n return (\n <div\n className=\"border border-chat-border rounded-lg overflow-hidden max-w-sm bg-[var(--chat-background)]\"\n data-chat-card=\"default\"\n >\n {card.header && (\n <div className=\"px-3 py-2 bg-chat-surface border-b border-chat-border font-semibold text-sm\">\n <MarkdownRenderer text={card.header} />\n </div>\n )}\n\n {card.image && (\n <img\n src={card.image.url}\n alt={card.image.alt || \"\"}\n className=\"block w-full h-auto max-h-48 object-cover\"\n data-chat-card-image=\"true\"\n />\n )}\n\n {card.sections?.map((section, index) => (\n <div key={index} className=\"px-3 py-2\" data-chat-section={index}>\n {section.text && (\n <div className=\"mb-2 text-sm leading-relaxed\">\n <MarkdownRenderer text={section.text} />\n </div>\n )}\n\n {section.fields?.map((field, fieldIndex) => (\n <div key={fieldIndex} className=\"mb-1 last:mb-0\" data-chat-field={fieldIndex}>\n {field.title && (\n <div className=\"text-xs text-chat-text-secondary font-medium\">{field.title}</div>\n )}\n <div className=\"text-sm text-chat-text\">{field.value}</div>\n </div>\n ))}\n </div>\n ))}\n\n {card.elements?.map((element, elIndex) => {\n switch (element.type) {\n case \"text\":\n return (\n <div\n key={`el-${elIndex}`}\n className={`px-3 py-2 text-sm ${\n element.style === \"muted\"\n ? \"text-chat-text-secondary\"\n : element.style === \"bold\"\n ? \"text-chat-text font-bold\"\n : \"text-chat-text\"\n }`}\n >\n <MarkdownRenderer text={element.content} />\n </div>\n );\n case \"divider\":\n return <hr key={`el-${elIndex}`} className=\"border-0 border-t border-chat-border\" />;\n case \"link\":\n return (\n <a\n key={`el-${elIndex}`}\n href={element.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"block px-3 py-2 text-chat-primary text-sm no-underline hover:underline\"\n >\n {element.label}\n </a>\n );\n case \"table\":\n return (\n <table key={`el-${elIndex}`} className=\"w-full border-collapse text-xs\">\n {element.headers.length > 0 && (\n <thead>\n <tr>\n {element.headers.map((h, i) => (\n <th\n key={i}\n className=\"px-2 py-1 text-left border-b border-chat-border font-semibold\"\n >\n {h}\n </th>\n ))}\n </tr>\n </thead>\n )}\n <tbody>\n {element.rows.map((row, rIdx) => (\n <tr key={rIdx}>\n {row.map((cell, cIdx) => (\n <td key={cIdx} className=\"px-2 py-1 border-b border-chat-border\">\n {cell}\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n );\n case \"link_button\":\n return (\n <a\n key={`el-${elIndex}`}\n href={element.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className={`block px-2 py-1.5 mx-2 my-1 rounded text-sm font-medium text-center no-underline ${\n element.style === \"primary\"\n ? \"bg-chat-primary text-white\"\n : element.style === \"danger\"\n ? \"bg-chat-error text-white\"\n : \"bg-chat-surface text-chat-text hover:bg-chat-background\"\n }`}\n >\n {element.label}\n </a>\n );\n case \"image\":\n return (\n <img\n key={`el-${elIndex}`}\n src={element.url}\n alt={element.alt || \"\"}\n className=\"block w-full h-auto max-h-36 object-cover\"\n />\n );\n default:\n return null;\n }\n })}\n\n {card.actions && card.actions.length > 0 && (\n <div className=\"flex flex-wrap gap-2 px-3 py-2\" data-chat-actions=\"true\">\n {card.actions.map((action) => (\n <button\n key={action.id}\n onClick={() => onActionClick?.(action.id, action.value || \"\")}\n className={`px-3 py-1.5 border border-chat-border rounded text-sm font-medium transition cursor-pointer ${\n action.style === \"primary\"\n ? \"bg-chat-primary text-white border-transparent hover:bg-chat-primary-hover\"\n : action.style === \"danger\"\n ? \"bg-chat-error text-white border-transparent hover:opacity-90\"\n : \"bg-chat-surface text-chat-text hover:bg-chat-background\"\n }`}\n data-chat-action={action.id}\n >\n {action.label}\n </button>\n ))}\n </div>\n )}\n </div>\n );\n}\n","import React from \"react\";\nimport { ImageCard as ImageCardType } from \"@bootdesk/js-web-adapter-core\";\nimport { CardRendererProps } from \"./types\";\n\nexport function ImageCardComponent({ card: rawCard }: CardRendererProps): React.JSX.Element | null {\n if (rawCard.type !== \"image\") {\n return null;\n }\n\n const card = rawCard as ImageCardType;\n\n return (\n <div className=\"rounded-lg overflow-hidden max-w-full\" data-chat-card=\"image\">\n <img\n src={card.url}\n alt={card.alt || \"\"}\n className=\"block max-w-full h-auto\"\n data-chat-image=\"true\"\n />\n {card.title && <div className=\"px-3 py-2 text-sm bg-chat-surface\">{card.title}</div>}\n </div>\n );\n}\n","export function formatSize(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n}\n","import React from \"react\";\nimport { FileCard as FileCardType } from \"@bootdesk/js-web-adapter-core\";\nimport { CardRendererProps } from \"./types\";\nimport { formatSize } from \"../utils/formatSize\";\n\nexport function FileCardComponent({ card: rawCard }: CardRendererProps): React.JSX.Element | null {\n if (rawCard.type !== \"file\") {\n return null;\n }\n\n const card = rawCard as FileCardType;\n\n return (\n <div\n className=\"flex items-center gap-3 p-3 border border-chat-border rounded-lg max-w-xs\"\n data-chat-card=\"file\"\n >\n <div className=\"w-10 h-10 flex items-center justify-center bg-chat-surface rounded\">📄</div>\n\n <div className=\"flex-1 min-w-0\">\n <div className=\"text-sm font-medium truncate\">{card.name}</div>\n {card.size && (\n <div className=\"text-xs text-chat-text-secondary\">{formatSize(card.size)}</div>\n )}\n </div>\n\n <a\n href={card.url}\n download={card.name}\n className=\"px-3 py-2 bg-chat-primary text-white rounded text-sm font-medium no-underline hover:opacity-90\"\n data-chat-file-download=\"true\"\n >\n Download\n </a>\n </div>\n );\n}\n","import React from \"react\";\nimport { Card, CustomCard } from \"@bootdesk/js-web-adapter-core\";\nimport { CardRendererProps } from \"./types\";\nimport { useCardRegistry } from \"./CardContext\";\nimport { DefaultCard } from \"./DefaultCard\";\n\nexport function CardRenderer({ card, onActionClick }: CardRendererProps): React.JSX.Element | null {\n const { getRenderer } = useCardRegistry();\n\n const Renderer = getRenderer(card.type);\n\n if (Renderer) {\n return <Renderer card={card} onActionClick={onActionClick} />;\n }\n\n if (isPHPCard(card)) {\n return <DefaultCard card={card} onActionClick={onActionClick} />;\n }\n\n return (\n <div style={{ padding: \"8px\", background: \"#f3f4f6\", borderRadius: \"4px\" }}>\n <pre style={{ fontSize: \"12px\", overflow: \"auto\" }}>{JSON.stringify(card, null, 2)}</pre>\n </div>\n );\n}\n\nfunction isPHPCard(card: Card | CustomCard): card is Card {\n return card.type === \"card\";\n}\n","import React from \"react\";\nimport { Message } from \"@bootdesk/js-web-adapter-core\";\nimport { CardRenderer } from \"../cards/CardRenderer\";\nimport { MarkdownRenderer } from \"../utils/markdown\";\n\ninterface MessageContentProps {\n message: Message;\n onActionClick?: (messageId: string, actionId: string, value: string) => void;\n}\n\nexport function MessageContent({ message, onActionClick }: MessageContentProps): React.JSX.Element {\n return (\n <div data-chat-message-content=\"true\">\n {message.content.text && !message.content.cards?.length && (\n <div className=\"break-words text-sm leading-relaxed\" data-chat-text=\"true\">\n <MarkdownRenderer text={message.content.text} />\n </div>\n )}\n\n {message.content.cards?.map((card, index) => (\n <div key={index} className={index > 0 ? \"mt-2\" : undefined}>\n <CardRenderer\n card={card}\n onActionClick={(actionId, value) => onActionClick?.(message.id, actionId, value)}\n />\n </div>\n ))}\n\n {message.attachments?.map((attachment) => {\n const isImage = attachment.type === \"image\" || attachment.mimeType?.startsWith(\"image/\");\n\n return (\n <div key={attachment.id} className=\"mt-2\">\n {isImage ? (\n <a href={attachment.url} target=\"_blank\" rel=\"noopener noreferrer\">\n <img\n src={attachment.url}\n alt={attachment.name || \"Image\"}\n className=\"max-w-full rounded object-cover\"\n loading=\"lazy\"\n data-chat-attachment={attachment.id}\n />\n </a>\n ) : (\n <a\n href={attachment.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"inline-flex items-center gap-2 px-3 py-2 bg-chat-surface rounded text-sm no-underline text-chat-text hover:bg-chat-background transition\"\n data-chat-attachment={attachment.id}\n >\n 📎 {attachment.name}\n </a>\n )}\n </div>\n );\n })}\n </div>\n );\n}\n","export function formatTimestamp(timestamp: number): string {\n const date = new Date(timestamp);\n const now = new Date();\n const diffMs = now.getTime() - date.getTime();\n const diffMins = Math.floor(diffMs / 60000);\n\n if (diffMins < 1) return \"Just now\";\n if (diffMins < 60) return `${diffMins}m ago`;\n if (diffMins < 1440) return `${Math.floor(diffMins / 60)}h ago`;\n return date.toLocaleDateString();\n}\n","import React, { useState, useRef, useEffect } from \"react\";\nimport { useAttachmentUpload } from \"../hooks/useAttachmentUpload\";\nimport { Dropzone } from \"./Dropzone\";\nimport { AttachmentList } from \"./AttachmentList\";\nimport { useLocale } from \"../i18n/LocaleProvider\";\n\ninterface InputAreaProps {\n onSend: (\n text: string,\n attachments: Array<{ url: string; name: string; mimeType: string; size: number }>,\n ) => Promise<void>;\n disabled?: boolean;\n placeholder?: string;\n className?: string;\n enableAttachments?: boolean;\n uploadConfig?: import(\"../types/AttachmentUpload\").UploadConfig;\n accept?: string;\n maxFileSize?: number;\n}\n\nexport function InputArea({\n onSend,\n disabled = false,\n placeholder = \"Type a message...\",\n className,\n enableAttachments = false,\n uploadConfig,\n accept,\n maxFileSize,\n}: InputAreaProps): React.JSX.Element {\n const [text, setText] = useState(\"\");\n const [showDropzone, setShowDropzone] = useState(false);\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n const sendingRef = useRef(false);\n\n const { attachments, addFiles, removeAttachment, clearAttachments, isUploading } =\n useAttachmentUpload(uploadConfig!);\n\n const { t } = useLocale();\n\n useEffect(() => {\n const textarea = textareaRef.current;\n if (!textarea) return;\n textarea.style.height = \"auto\";\n textarea.style.height = Math.min(textarea.scrollHeight, 120) + \"px\";\n }, [text]);\n\n const handleSubmit = async () => {\n const trimmed = text.trim();\n if ((!trimmed && attachments.length === 0) || disabled || sendingRef.current) return;\n if (isUploading) return;\n\n sendingRef.current = true;\n\n const uploadedAttachments = attachments\n .filter((a) => a.status === \"uploaded\" && a.url)\n .map((a) => ({\n url: a.url!,\n name: a.name,\n mimeType: a.mimeType,\n size: a.size,\n }));\n\n setText(\"\");\n setShowDropzone(false);\n clearAttachments();\n try {\n await onSend(trimmed, uploadedAttachments);\n } finally {\n sendingRef.current = false;\n }\n setTimeout(() => textareaRef.current?.focus(), 0);\n };\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (e.key === \"Enter\" && !e.shiftKey) {\n e.preventDefault();\n handleSubmit();\n }\n };\n\n const canSend =\n (text.trim().length > 0 || attachments.some((a) => a.status === \"uploaded\")) && !isUploading;\n\n return (\n <div\n className={`chat-input-area ${className || \"\"}`}\n data-chat-input-area=\"true\"\n data-testid=\"chat-input-area\"\n >\n {enableAttachments && attachments.length > 0 && (\n <AttachmentList attachments={attachments} onRemove={removeAttachment} />\n )}\n\n {enableAttachments && showDropzone && uploadConfig && (\n <Dropzone\n onFilesSelected={addFiles}\n disabled={disabled || isUploading}\n accept={accept}\n maxSize={maxFileSize}\n />\n )}\n\n <div className=\"flex gap-3\">\n {enableAttachments && uploadConfig && (\n <button\n onClick={() => setShowDropzone((prev) => !prev)}\n disabled={disabled}\n className={`p-2 rounded-lg cursor-pointer transition ${\n showDropzone\n ? \"bg-chat-primary/10 text-chat-primary\"\n : \"bg-transparent text-chat-text-secondary\"\n } disabled:cursor-not-allowed disabled:opacity-50`}\n data-chat-attachment-toggle=\"true\"\n aria-label=\"Toggle file attachment\"\n >\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48\" />\n </svg>\n </button>\n )}\n\n <textarea\n ref={textareaRef}\n value={text}\n onChange={(e) => setText(e.target.value)}\n onKeyDown={handleKeyDown}\n placeholder={placeholder}\n className=\"chat-input\"\n data-chat-input=\"true\"\n rows={1}\n />\n\n <button\n onClick={handleSubmit}\n disabled={disabled || !canSend}\n className=\"chat-send-button\"\n data-chat-send-button=\"true\"\n aria-label={t(\"inputArea.send\")}\n >\n {isUploading ? (\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"animate-spin\"\n >\n <path d=\"M21 12a9 9 0 1 1-6.219-8.56\" />\n </svg>\n ) : (\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <line x1=\"22\" y1=\"2\" x2=\"11\" y2=\"13\" />\n <polygon points=\"22 2 15 22 11 13 2 9 22 2\" />\n </svg>\n )}\n </button>\n </div>\n </div>\n );\n}\n","import React, { useCallback, useState, useRef } from \"react\";\nimport { useLocale } from \"../i18n/LocaleProvider\";\n\ninterface DropzoneProps {\n onFilesSelected: (files: FileList | File[]) => void;\n disabled?: boolean;\n accept?: string;\n maxSize?: number;\n multiple?: boolean;\n className?: string;\n}\n\nexport function Dropzone({\n onFilesSelected,\n disabled = false,\n accept,\n maxSize,\n multiple = true,\n className,\n}: DropzoneProps): React.JSX.Element {\n const { t } = useLocale();\n const [isDragging, setIsDragging] = useState(false);\n const inputRef = useRef<HTMLInputElement>(null);\n const dragCounter = useRef(0);\n\n const handleDragEnter = useCallback((e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n dragCounter.current++;\n if (e.dataTransfer.items && e.dataTransfer.items.length > 0) {\n setIsDragging(true);\n }\n }, []);\n\n const handleDragLeave = useCallback((e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n dragCounter.current--;\n if (dragCounter.current === 0) {\n setIsDragging(false);\n }\n }, []);\n\n const handleDragOver = useCallback((e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n }, []);\n\n const handleDrop = useCallback(\n (e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setIsDragging(false);\n dragCounter.current = 0;\n if (disabled) return;\n\n const files = e.dataTransfer.files;\n if (files && files.length > 0) {\n const filtered = filterFiles(files, maxSize, accept);\n if (filtered.length > 0) {\n onFilesSelected(multiple ? filtered : [filtered[0]!]);\n }\n }\n },\n [disabled, maxSize, accept, multiple, onFilesSelected],\n );\n\n const handleInputChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n if (disabled) return;\n const files = e.target.files;\n if (files && files.length > 0) {\n const filtered = filterFiles(files, maxSize, accept);\n if (filtered.length > 0) {\n onFilesSelected(multiple ? filtered : [filtered[0]!]);\n }\n }\n if (inputRef.current) inputRef.current.value = \"\";\n },\n [disabled, maxSize, accept, multiple, onFilesSelected],\n );\n\n const handleClick = useCallback(() => {\n inputRef.current?.click();\n }, []);\n\n function filterFiles(files: FileList, maxSize?: number, accept?: string): File[] {\n return Array.from(files).filter((file) => {\n if (maxSize && file.size > maxSize) return false;\n if (accept) {\n const accepted = accept.split(\",\").map((a) => a.trim().toLowerCase());\n const mimeType = file.type.toLowerCase();\n const ext = \".\" + file.name.split(\".\").pop()?.toLowerCase();\n return accepted.some((a) => {\n if (a.endsWith(\"/*\")) return mimeType.startsWith(a.replace(\"/*\", \"/\"));\n return a === mimeType || a === ext;\n });\n }\n return true;\n });\n }\n\n return (\n <div\n role=\"button\"\n tabIndex={0}\n onClick={handleClick}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") handleClick();\n }}\n onDragEnter={handleDragEnter}\n onDragLeave={handleDragLeave}\n onDragOver={handleDragOver}\n onDrop={handleDrop}\n className={`flex items-center justify-center p-2 border-2 border-dashed rounded-lg cursor-pointer transition ${\n isDragging ? \"border-chat-primary bg-chat-primary/10\" : \"border-chat-border\"\n } ${disabled ? \"cursor-not-allowed opacity-50\" : \"\"} ${className || \"\"}`}\n data-chat-dropzone=\"true\"\n data-testid=\"chat-dropzone\"\n >\n <input\n ref={inputRef}\n type=\"file\"\n accept={accept}\n multiple={multiple}\n onChange={handleInputChange}\n className=\"hidden\"\n disabled={disabled}\n aria-hidden=\"true\"\n />\n <div className=\"text-center\">\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke={isDragging ? \"var(--chat-primary)\" : \"var(--chat-text-secondary)\"}\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"mx-auto mb-1\"\n >\n <path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\" />\n <polyline points=\"17 8 12 3 7 8\" />\n <line x1=\"12\" y1=\"3\" x2=\"12\" y2=\"15\" />\n </svg>\n <div className=\"text-xs text-chat-text-secondary\">\n {isDragging ? t(\"inputArea.dropzone.dropFiles\") : t(\"inputArea.dropzone.dropOrClick\")}\n </div>\n </div>\n </div>\n );\n}\n","import React from \"react\";\nimport { PendingAttachment } from \"../types/AttachmentUpload\";\nimport { useLocale } from \"../i18n/LocaleProvider\";\nimport { formatSize } from \"../utils/formatSize\";\n\ninterface AttachmentListProps {\n attachments: PendingAttachment[];\n onRemove?: (id: string) => void;\n className?: string;\n}\n\nexport function AttachmentList({\n attachments,\n onRemove,\n className,\n}: AttachmentListProps): React.JSX.Element {\n const { t } = useLocale();\n\n if (attachments.length === 0) return <></>;\n\n function getFileIcon(mimeType: string): string {\n if (mimeType.startsWith(\"image/\")) return \"🖼️\";\n if (mimeType === \"application/pdf\") return \"📄\";\n if (mimeType.includes(\"video\")) return \"🎬\";\n if (mimeType.includes(\"audio\")) return \"🎵\";\n return \"📎\";\n }\n\n return (\n <div className={`flex flex-wrap gap-1 p-1 ${className || \"\"}`} data-chat-attachment-list=\"true\">\n {attachments.map((att) => (\n <div\n key={att.id}\n className={`flex items-center gap-1 px-2 py-1 text-xs rounded border max-w-[200px] ${\n att.status === \"error\"\n ? \"bg-chat-error/15 border-chat-error\"\n : \"bg-chat-surface shadow-sm border-chat-border\"\n }`}\n data-chat-attachment-item={att.id}\n >\n <span>{getFileIcon(att.mimeType)}</span>\n <div className=\"flex-1 min-w-0\">\n <div\n className={`overflow-hidden text-ellipsis whitespace-nowrap ${\n att.status === \"error\" ? \"text-chat-error\" : \"text-chat-text\"\n }`}\n >\n {att.name}\n </div>\n <div className=\"text-[10px] text-chat-text-secondary\">\n {att.status === \"uploading\"\n ? `${att.progress}%`\n : att.status === \"error\"\n ? att.error || t(\"attachmentList.uploadFailed\")\n : formatSize(att.size)}\n </div>\n {att.status === \"uploading\" && (\n <div className=\"h-0.5 bg-chat-border rounded overflow-hidden mt-0.5\">\n <div\n className=\"h-full bg-chat-primary transition-[width] duration-150\"\n style={{ width: `${att.progress}%` }}\n />\n </div>\n )}\n </div>\n {onRemove && att.status !== \"uploading\" && (\n <button\n onClick={() => onRemove(att.id)}\n className=\"bg-none border-none cursor-pointer text-chat-text-secondary p-0.5 leading-none hover:text-chat-error\"\n aria-label={`Remove ${att.name}`}\n >\n ×\n </button>\n )}\n </div>\n ))}\n </div>\n );\n}\n","import React from \"react\";\nimport { useLocale } from \"../i18n/LocaleProvider\";\n\ninterface TypingIndicatorProps {\n users?: string[];\n}\n\nexport function TypingIndicator({ users = [] }: TypingIndicatorProps): React.JSX.Element {\n const { t } = useLocale();\n\n return (\n <div\n className=\"chat-typing-indicator\"\n data-chat-typing-indicator=\"true\"\n data-testid=\"chat-typing-indicator\"\n >\n <span className=\"flex items-center gap-2\">\n <span className=\"flex gap-1\">\n <span\n className=\"w-1.5 h-1.5 rounded-full bg-chat-text-secondary animate-bounce\"\n style={{ animationDelay: \"0ms\" }}\n />\n <span\n className=\"w-1.5 h-1.5 rounded-full bg-chat-text-secondary animate-bounce\"\n style={{ animationDelay: \"160ms\" }}\n />\n <span\n className=\"w-1.5 h-1.5 rounded-full bg-chat-text-secondary animate-bounce\"\n style={{ animationDelay: \"320ms\" }}\n />\n </span>\n {users.length > 0 && ` ${users[0]} ${t(\"typingIndicator.isTyping\")}`}\n </span>\n </div>\n );\n}\n","import React, { createContext, useContext } from \"react\";\nimport { WebChatClient } from \"@bootdesk/js-web-adapter-core\";\nimport { CardProvider } from \"../cards/CardContext\";\nimport type { CardRenderer } from \"../cards/types\";\n\ninterface ChatContextValue {\n client: WebChatClient;\n}\n\nconst ChatContext = createContext<ChatContextValue | undefined>(undefined);\n\ninterface ChatProviderProps {\n children: React.ReactNode;\n client: WebChatClient;\n cardRenderers?: Record<string, CardRenderer>;\n}\n\nexport function ChatProvider({\n children,\n client,\n cardRenderers,\n}: ChatProviderProps): React.JSX.Element {\n return (\n <CardProvider renderers={cardRenderers}>\n <ChatContext.Provider value={{ client }}>{children}</ChatContext.Provider>\n </CardProvider>\n );\n}\n\nexport function useChatContext(): ChatContextValue {\n const context = useContext(ChatContext);\n if (!context) {\n throw new Error(\"useChatContext must be used within ChatProvider\");\n }\n return context;\n}\n\nexport { ChatWidget } from \"../components/ChatWidget\";\n","import React, { Component } from \"react\";\nimport type { ReactNode } from \"react\";\n\ninterface ErrorBoundaryProps {\n children: ReactNode;\n fallback?: ReactNode | ((error: Error) => ReactNode);\n onError?: (error: Error, errorInfo: React.ErrorInfo) => void;\n}\n\ninterface ErrorBoundaryState {\n error: Error | null;\n}\n\nexport class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {\n constructor(props: ErrorBoundaryProps) {\n super(props);\n this.state = { error: null };\n }\n\n static getDerivedStateFromError(error: Error): ErrorBoundaryState {\n return { error };\n }\n\n componentDidCatch(error: Error, errorInfo: React.ErrorInfo): void {\n this.props.onError?.(error, errorInfo);\n }\n\n render(): ReactNode {\n if (!this.state.error) return this.props.children;\n\n const { fallback } = this.props;\n if (typeof fallback === \"function\") {\n return (fallback as (error: Error) => ReactNode)(this.state.error);\n }\n if (fallback) return fallback;\n\n return (\n <div\n className=\"flex flex-col items-center justify-center p-6 text-center\"\n data-chat-error-boundary=\"true\"\n >\n <div className=\"text-chat-error text-lg font-semibold mb-2\">Something went wrong</div>\n <div className=\"text-chat-text-secondary text-sm mb-4\">{this.state.error.message}</div>\n <button\n onClick={() => this.setState({ error: null })}\n className=\"px-4 py-2 bg-chat-primary text-white rounded text-sm cursor-pointer hover:opacity-90\"\n >\n Try again\n </button>\n </div>\n );\n }\n}\n","import React, { useState } from \"react\";\nimport { usePushNotifications } from \"../hooks/usePushNotifications\";\nimport { useLocale } from \"../i18n/LocaleProvider\";\n\ninterface PushPermissionPromptProps {\n autoHide?: boolean;\n title?: string;\n description?: string;\n onStatusChange?: (enabled: boolean) => void;\n getVapidPublicKey: () => Promise<string>;\n onSubscribe: (sub: PushSubscriptionJSON) => Promise<void>;\n onUnsubscribe: (sub: PushSubscriptionJSON) => Promise<void>;\n}\n\nexport function PushPermissionPrompt({\n autoHide = true,\n title,\n description,\n onStatusChange,\n getVapidPublicKey,\n onSubscribe,\n onUnsubscribe,\n}: PushPermissionPromptProps) {\n const { t } = useLocale();\n const { status, isSupported, isSubscribed, subscribe, unsubscribe } = usePushNotifications({\n enabled: true,\n getVapidPublicKey,\n onSubscribe,\n onUnsubscribe,\n });\n\n const [dismissed, setDismissed] = useState(false);\n\n if (!isSupported) return null;\n if (autoHide && (isSubscribed || status === \"denied\")) return null;\n if (dismissed) return null;\n\n const handleEnable = async () => {\n await subscribe();\n onStatusChange?.(true);\n };\n\n const handleDisable = async () => {\n await unsubscribe();\n onStatusChange?.(false);\n };\n\n return (\n <div\n className=\"p-3 bg-chat-surface rounded-lg flex items-start gap-3\"\n data-chat-push-prompt=\"true\"\n >\n <div className=\"flex-1\">\n <div className=\"font-semibold mb-1 text-chat-text\">{title || t(\"push.title\")}</div>\n <div className=\"text-sm text-chat-text-secondary\">\n {description || t(\"push.description\")}\n </div>\n </div>\n <div className=\"flex gap-2\">\n {!isSubscribed && status !== \"denied\" && (\n <button\n onClick={handleEnable}\n className=\"px-3 py-1.5 bg-chat-primary text-white border-none rounded cursor-pointer text-sm hover:opacity-90\"\n >\n {t(\"push.enable\")}\n </button>\n )}\n {isSubscribed && (\n <button\n onClick={handleDisable}\n className=\"px-3 py-1.5 bg-transparent text-chat-text-secondary border border-chat-border rounded cursor-pointer text-sm hover:bg-chat-surface\"\n >\n {t(\"push.disable\")}\n </button>\n )}\n <button\n onClick={() => setDismissed(true)}\n className=\"px-1.5 bg-transparent border-none cursor-pointer text-chat-text-secondary hover:text-chat-text\"\n >\n ✕\n </button>\n </div>\n </div>\n );\n}\n","import React from \"react\";\nimport { usePushNotifications } from \"../hooks/usePushNotifications\";\nimport { useLocale } from \"../i18n/LocaleProvider\";\n\ninterface PushToggleProps {\n getVapidPublicKey: () => Promise<string>;\n onSubscribe: (sub: PushSubscriptionJSON) => Promise<void>;\n onUnsubscribe: (sub: PushSubscriptionJSON) => Promise<void>;\n}\n\nexport function PushToggle({ getVapidPublicKey, onSubscribe, onUnsubscribe }: PushToggleProps) {\n const { t } = useLocale();\n const { status, isSupported, isSubscribed, subscribe, unsubscribe } = usePushNotifications({\n enabled: true,\n getVapidPublicKey,\n onSubscribe,\n onUnsubscribe,\n });\n\n if (!isSupported) {\n return <div className=\"text-sm text-chat-text-secondary\">{t(\"push.unsupported\")}</div>;\n }\n\n if (status === \"denied\") {\n return <div className=\"text-sm text-chat-text-secondary\">{t(\"push.denied\")}</div>;\n }\n\n return (\n <label className=\"flex items-center gap-2 cursor-pointer\">\n <input\n type=\"checkbox\"\n checked={isSubscribed}\n onChange={async (e) => {\n if (e.target.checked) await subscribe();\n else await unsubscribe();\n }}\n disabled={status === \"subscribing\"}\n className=\"w-4 h-4 cursor-pointer\"\n />\n <span className=\"text-sm\">\n {status === \"subscribing\" ? t(\"push.subscribing\") : t(\"push.notifications\")}\n </span>\n </label>\n );\n}\n"],"mappings":"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","names":["import_react","import_react","features","import_react","import_react","import_react","import_js_web_adapter_core","import_react","import_react","import_react","import_jsx_runtime","import_jsx_runtime","import_react","import_react","import_jsx_runtime","DOMPurify","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","renderer","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_react","import_react","import_jsx_runtime","maxSize","accept","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_jsx_runtime","import_js_web_adapter_core"]}