@cloudflare/ai-search-snippet 0.0.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +573 -0
- package/dist/clouds.json +417 -0
- package/dist/main.d.ts +359 -0
- package/dist/search-snippet.es.js +3413 -0
- package/dist/search-snippet.es.js.map +1 -0
- package/dist/search-snippet.umd.js +2206 -0
- package/dist/search-snippet.umd.js.map +1 -0
- package/dist/vite.svg +1 -0
- package/package.json +66 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search-snippet.es.js","sources":["../src/utils/index.ts","../src/api/index.ts","../src/api/ai-search.ts","../src/styles/chat.ts","../src/styles/theme.ts","../src/constants.ts","../src/utils/markdown.ts","../src/components/chat-view.ts","../src/components/chat-bubble-snippet.ts","../src/components/chat-page-snippet.ts","../src/styles/search.ts","../src/components/search-bar-snippet.ts","../src/styles/modal.ts","../src/components/search-modal-snippet.ts"],"sourcesContent":["/**\n * Utility functions for the Search Snippet Library\n */\n\nimport { AISearchClient } from '../api/ai-search.ts';\nimport type { Client } from '../api/index.ts';\n\n/**\n * Debounce function to limit API calls\n */\nexport function debounce<T extends (...args: unknown[]) => unknown>(\n func: T,\n wait: number\n): (...args: Parameters<T>) => void {\n let timeout: number | undefined;\n\n return function executedFunction(...args: Parameters<T>) {\n const later = () => {\n clearTimeout(timeout);\n func(...args);\n };\n\n clearTimeout(timeout);\n timeout = setTimeout(later, wait) as unknown as number;\n };\n}\n\n/**\n * Sanitize HTML to prevent XSS attacks\n */\nexport function sanitizeHTML(html: string): string {\n const div = document.createElement('div');\n div.textContent = html;\n return div.innerHTML;\n}\n\n/**\n * Escape HTML entities\n */\nexport function escapeHTML(text: string): string {\n const div = document.createElement('div');\n div.textContent = text;\n return div.innerHTML;\n}\n\n/**\n * Decode HTML entities (e.g., & -> &, & -> &)\n */\nexport function decodeHTMLEntities(text: string): string {\n const doc = new DOMParser().parseFromString(text, 'text/html');\n return doc.documentElement.textContent || '';\n}\n\n/**\n * Format timestamp to readable date\n */\nexport function formatTimestamp(timestamp: number): string {\n const date = new Date(timestamp);\n const now = new Date();\n const diff = now.getTime() - date.getTime();\n\n // Less than a minute\n if (diff < 60000) {\n return 'Just now';\n }\n\n // Less than an hour\n if (diff < 3600000) {\n const minutes = Math.floor(diff / 60000);\n return `${minutes} ${minutes === 1 ? 'minute' : 'minutes'} ago`;\n }\n\n // Less than a day\n if (diff < 86400000) {\n const hours = Math.floor(diff / 3600000);\n return `${hours} ${hours === 1 ? 'hour' : 'hours'} ago`;\n }\n\n // Format as date\n return date.toLocaleString(undefined, {\n month: 'short',\n day: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n });\n}\n\n/**\n * Generate unique ID\n */\nexport function generateId(prefix = 'id'): string {\n return `${prefix}-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n}\n\n/**\n * Parse attributes from element\n */\nexport function parseAttribute(value: string | null, defaultValue: string): string {\n return value !== null ? value : defaultValue;\n}\n\nexport function parseBooleanAttribute(value: string | null, defaultValue: boolean): boolean {\n if (value === null) return defaultValue;\n return value === 'true' || value === '';\n}\n\nexport function parseNumberAttribute(value: string | null, defaultValue: number): number {\n if (value === null) return defaultValue;\n const parsed = Number.parseInt(value, 10);\n return Number.isNaN(parsed) ? defaultValue : parsed;\n}\n\n/**\n * Create custom event\n */\nexport function createCustomEvent<T>(name: string, detail: T): CustomEvent<T> {\n return new CustomEvent(name, {\n detail,\n bubbles: true,\n composed: true,\n cancelable: true,\n });\n}\n\n/**\n * Create API client\n */\nexport function createClient(apiUrl: string): Client {\n if (!apiUrl) {\n throw new Error('API URL is required');\n }\n\n return new AISearchClient(apiUrl);\n}\n","/** biome-ignore-all lint/correctness/noUnusedFunctionParameters: this is a placeholder */\nimport type { ChatTypes, RequestState, SearchError, SearchOptions, SearchResult } from '../types';\n\nexport class Client {\n activeRequests: Map<string, RequestState> = new Map();\n baseUrl: string;\n constructor(baseUrl: string) {\n this.baseUrl = baseUrl.replace(/\\/$/, ''); // Remove trailing slash;\n }\n\n search(_query: string, _options?: SearchOptions): Promise<SearchResult[]> {\n throw new Error('Not implemented');\n }\n\n searchStream(\n _query: string,\n _options?: SearchOptions\n ): AsyncGenerator<SearchResult | SearchError, void, undefined> {\n throw new Error('Not implemented');\n }\n\n chat(_message: string, _options?: SearchOptions): AsyncGenerator<ChatTypes, void, undefined> {\n throw new Error('Not implemented');\n }\n\n cancelRequest(_requestId: string): void {\n throw new Error('Not implemented');\n }\n\n cancelAllRequests(): void {\n throw new Error('Not implemented');\n }\n}\n","/**\n * NLWeb API Client\n * Handles all API communication with retry logic, streaming support, and request cancellation\n */\n\nimport type {\n AISearchAPIResponse,\n ChatTextResponse,\n ChatTypes,\n SearchError,\n SearchOptions,\n SearchResult,\n} from '../types/index.ts';\nimport { decodeHTMLEntities } from '../utils/index.ts';\nimport { Client } from './index.ts';\n\nexport class AISearchClient extends Client {\n private request(\n options: SearchOptions = {},\n operation: 'ai-search' | 'search' | 'chat/completions',\n signal?: AbortSignal\n ): Promise<Response> {\n return fetch(`${this.baseUrl}/${operation}`, {\n method: 'POST',\n body: JSON.stringify({\n messages: [{ role: 'user', content: options.query }],\n stream: options.streaming,\n max_results: options.maxResults,\n }),\n headers: {\n 'Content-Type': 'application/json',\n },\n signal,\n });\n }\n\n /**\n * Performs a search query with optional streaming\n */\n async search(query: string, options: Omit<SearchOptions, 'query'> = {}): Promise<SearchResult[]> {\n const requestId = this.generateRequestId();\n const controller = new AbortController();\n const signal = options.signal || controller.signal;\n\n this.registerRequest(requestId, controller);\n\n try {\n const response = await this.request(\n {\n query,\n streaming: false,\n maxResults: 30,\n } satisfies SearchOptions,\n 'search',\n signal\n );\n\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n\n if (!response.body) {\n throw new Error('Response body is empty');\n }\n const result: AISearchAPIResponse = await response.json();\n if (result.success && result.result) {\n // Aggregate by item.key, keeping the highest vector_score for duplicates\n const aggregated = new Map<\n string,\n { chunk: (typeof result.result.chunks)[0]; score: number }\n >();\n\n for (const chunk of result.result.chunks) {\n const key = chunk.item.key;\n const score = chunk.scoring_details.vector_score;\n\n if (!aggregated.has(key) || (aggregated.get(key)?.score ?? 0) < score) {\n aggregated.set(key, { chunk, score });\n }\n }\n\n // Sort by score descending and return top 10\n return Array.from(aggregated.values())\n .sort((a, b) => b.score - a.score)\n .slice(0, 10)\n .map(\n ({ chunk }) =>\n ({\n type: 'result',\n id: chunk.id,\n title: decodeHTMLEntities(chunk.item.metadata.title),\n description: decodeHTMLEntities(chunk.item.metadata.description),\n url: chunk.item.key,\n image: chunk.item.metadata.image || undefined,\n metadata: chunk.item.metadata as unknown as Record<string, unknown>,\n }) satisfies SearchResult\n );\n }\n\n if (result.success === false) {\n // @ts-expect-error need to check this\n throw new Error(result.error);\n }\n throw new Error('Unknown error');\n } finally {\n this.unregisterRequest(requestId);\n }\n }\n\n async *searchStream(\n query: string,\n options?: SearchOptions\n ): AsyncGenerator<SearchResult | SearchError, void, undefined> {\n const requestId = this.generateRequestId();\n const controller = new AbortController();\n const signal = options?.signal || controller.signal;\n\n this.registerRequest(requestId, controller);\n\n const response = await this.request(\n {\n query,\n streaming: true,\n } satisfies SearchOptions,\n 'ai-search',\n signal\n );\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n if (!response.body) {\n throw new Error('Response body is empty');\n }\n\n let chunks = '';\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n const chunk = decoder.decode(value, { stream: true });\n chunks += chunk;\n }\n\n const result: string = chunks\n .replaceAll('data: ', '')\n .trim()\n .split('\\n\\n')\n .map((chunk) => {\n return JSON.parse(chunk) as { response: string };\n })\n .map((chunk) => chunk.response)\n .join('');\n\n yield {\n type: 'result',\n id: '',\n title: '',\n description: result,\n url: '',\n metadata: {},\n };\n }\n\n async *chat(query: string, options?: SearchOptions): AsyncGenerator<ChatTypes, void, undefined> {\n const controller = new AbortController();\n const signal = options?.signal || controller.signal;\n // const prevQueries: string[] = JSON.parse(localStorage.getItem('prevQueries') || '[]');\n // prevQueries.push(query);\n // localStorage.setItem('prevQueries', JSON.stringify(prevQueries));\n const response = await this.request(\n {\n query,\n streaming: false,\n } satisfies SearchOptions,\n 'chat/completions',\n signal\n );\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n if (!response.body) {\n throw new Error('Response body is empty');\n }\n const result = (await response.json()) as {\n choices: {\n message: {\n content: string;\n };\n }[];\n };\n\n yield {\n type: 'text',\n message: result.choices.map((choice) => choice.message.content).join(''),\n } satisfies ChatTextResponse;\n\n // for (const item of result.data) {\n // yield {\n // type: 'result',\n // id: item.filename,\n // title: item.filename,\n // description: item.content.text,\n // url: item.filename,\n // metadata: item.attributes\n // ,\n // } satisfies ChatResult;\n // }\n\n return;\n }\n\n /**\n * Cancels an active request by ID\n */\n cancelRequest(requestId: string): void {\n const request = this.activeRequests.get(requestId);\n if (request) {\n request.controller.abort();\n this.unregisterRequest(requestId);\n }\n }\n\n /**\n * Cancels all active requests\n */\n cancelAllRequests(): void {\n for (const [requestId] of this.activeRequests) {\n this.cancelRequest(requestId);\n }\n }\n\n /**\n * Register an active request\n */\n private registerRequest(id: string, controller: AbortController): void {\n this.activeRequests.set(id, {\n id,\n controller,\n timestamp: Date.now(),\n });\n }\n\n /**\n * Unregister a completed request\n */\n private unregisterRequest(id: string): void {\n this.activeRequests.delete(id);\n }\n\n /**\n * Generate unique request ID\n */\n private generateRequestId(): string {\n return `req-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n }\n}\n","/**\n * Chat mode specific styles\n */\n\nexport const chatStyles = `\n/* Chat container */\n.chat-container {\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow-y: auto;\n}\n\n/* Messages area */\n.chat-messages {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n padding: var(--search-snippet-spacing-md);\n display: flex;\n flex-direction: column;\n gap: var(--search-snippet-spacing-md);\n}\n\n.chat-messages::-webkit-scrollbar {\n width: 8px;\n}\n\n.chat-messages::-webkit-scrollbar-track {\n background: var(--search-snippet-surface);\n}\n\n.chat-messages::-webkit-scrollbar-thumb {\n background: var(--search-snippet-border-color);\n border-radius: var(--search-snippet-border-radius);\n}\n\n.chat-messages::-webkit-scrollbar-thumb:hover {\n background: var(--search-snippet-text-secondary);\n}\n\n/* Message */\n.chat-message {\n display: flex;\n gap: var(--search-snippet-spacing-sm);\n max-width: 85%;\n animation: slideIn var(--search-snippet-animation-duration) ease-out;\n}\n\n@keyframes slideIn {\n from {\n opacity: 0;\n transform: translateY(10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n.chat-message-user {\n align-self: flex-end;\n flex-direction: row-reverse;\n}\n\n.chat-message-assistant {\n align-self: flex-start;\n}\n\n.chat-message-system {\n align-self: center;\n max-width: 100%;\n}\n\n/* Message avatar */\n.chat-message-avatar {\n width: 32px;\n height: 32px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n font-size: var(--search-snippet-font-size-sm);\n font-weight: var(--search-snippet-font-weight-bold);\n background: var(--search-snippet-primary-color);\n color: white;\n}\n\n.chat-message-assistant .chat-message-avatar {\n background: var(--search-snippet-surface);\n color: var(--search-snippet-text-color);\n border: var(--search-snippet-border-width) solid var(--search-snippet-border-color);\n}\n\n/* Message content */\n.chat-message-content {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: var(--search-snippet-spacing-xs);\n max-width: 100%;\n}\n\n.chat-message-content ol, .chat-message-content ul {\n margin-inline-start: 16px;\n}\n\n.chat-message-content ol li, .chat-message-content ul li {\n padding-inline-start: 0;\n}\n\n.chat-message-bubble {\n padding: var(--search-snippet-spacing-sm) var(--search-snippet-spacing-md);\n border-radius: var(--search-snippet-border-radius);\n word-wrap: break-word;\n overflow-wrap: break-word;\n}\n\n.chat-message-user .chat-message-bubble {\n background: var(--search-snippet-user-message-bg);\n color: var(--search-snippet-user-message-text);\n border-top-right-radius: var(--search-snippet-spacing-xs);\n}\n\n.chat-message-assistant .chat-message-bubble {\n background: var(--search-snippet-assistant-message-bg);\n color: var(--search-snippet-assistant-message-text);\n border-top-left-radius: var(--search-snippet-spacing-xs);\n border: var(--search-snippet-border-width) solid var(--search-snippet-border-color);\n}\n\n.chat-message-system .chat-message-bubble {\n background: var(--search-snippet-system-message-bg);\n color: var(--search-snippet-system-message-text);\n text-align: center;\n font-size: var(--search-snippet-font-size-sm);\n padding: var(--search-snippet-spacing-xs) var(--search-snippet-spacing-md);\n}\n\n.chat-message-text {\n font-size: var(--search-snippet-font-size-base);\n line-height: 1.5;\n white-space: wrap;\n}\n.chat-message-text li{\n padding-inline-start: var(--search-snippet-spacing-md);\n}\n\n.chat-message-metadata {\n display: flex;\n align-items: center;\n gap: var(--search-snippet-spacing-sm);\n font-size: var(--search-snippet-font-size-sm);\n color: var(--search-snippet-text-secondary);\n}\n\n.chat-message-user .chat-message-metadata {\n justify-content: flex-end;\n}\n\n.chat-message-time {\n opacity: 0.7;\n}\n\n/* Streaming indicator */\n.chat-streaming {\n display: flex;\n align-items: center;\n gap: var(--search-snippet-spacing-xs);\n}\n\n.chat-streaming-dot {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n background: currentColor;\n animation: pulse 1.4s ease-in-out infinite;\n}\n\n.chat-streaming-dot:nth-child(2) {\n animation-delay: 0.2s;\n}\n\n.chat-streaming-dot:nth-child(3) {\n animation-delay: 0.4s;\n}\n\n@keyframes pulse {\n 0%, 80%, 100% {\n opacity: 0.3;\n transform: scale(0.8);\n }\n 40% {\n opacity: 1;\n transform: scale(1);\n }\n}\n\n/* Input area */\n.chat-input-area {\n padding: var(--search-snippet-spacing-md);\n border-top: var(--search-snippet-border-width) solid var(--search-snippet-border-color);\n background: var(--search-snippet-surface);\n}\n\n.chat-input-wrapper {\n display: flex;\n gap: var(--search-snippet-spacing-sm);\n align-items: flex-end;\n}\n\n.chat-input {\n flex: 1;\n min-height: var(--search-snippet-input-height);\n max-height: 120px;\n padding: var(--search-snippet-spacing-sm) var(--search-snippet-spacing-md);\n font-family: var(--search-snippet-font-family);\n font-size: var(--search-snippet-font-size-base);\n line-height: var(--search-snippet-line-height);\n color: var(--search-snippet-text-color);\n background: var(--search-snippet-background);\n border: var(--search-snippet-border-width) solid var(--search-snippet-border-color);\n border-radius: var(--search-snippet-border-radius);\n outline: none;\n resize: vertical;\n transition: var(--search-snippet-transition);\n}\n\n.chat-input:focus {\n border-color: var(--search-snippet-primary-color);\n box-shadow: 0 0 0 3px var(--search-snippet-focus-ring);\n}\n\n.chat-input::placeholder {\n color: var(--search-snippet-text-secondary);\n}\n\n.chat-input:disabled {\n background: var(--search-snippet-surface);\n cursor: not-allowed;\n opacity: 0.6;\n}\n\n.chat-send-button {\n flex-shrink: 0;\n height: var(--search-snippet-input-height);\n padding: 0 var(--search-snippet-spacing-lg);\n}\n\n.chat-send-button:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n/* Empty chat state */\n.chat-empty {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: var(--search-snippet-spacing-xxl);\n gap: var(--search-snippet-spacing-md);\n color: var(--search-snippet-text-secondary);\n text-align: center;\n height: 100%;\n}\n\n.chat-empty-icon {\n width: 64px;\n height: 64px;\n opacity: 0.5;\n}\n\n.chat-empty-title {\n font-size: var(--search-snippet-font-size-lg);\n font-weight: var(--search-snippet-font-weight-medium);\n color: var(--search-snippet-text-color);\n}\n\n.chat-empty-description {\n font-size: var(--search-snippet-font-size-sm);\n}\n\n/* Code blocks in messages */\n.chat-message-bubble pre {\n background: var(--search-snippet-surface);\n padding: var(--search-snippet-spacing-sm);\n border-radius: var(--search-snippet-border-radius);\n overflow-x: auto;\n font-family: var(--search-snippet-font-family-mono);\n font-size: var(--search-snippet-font-size-sm);\n margin: var(--search-snippet-spacing-xs) 0;\n}\n\n.chat-message-bubble code {\n font-family: var(--search-snippet-font-family-mono);\n font-size: 0.9em;\n background: var(--search-snippet-surface);\n padding: 2px 4px;\n border-radius: var(--search-snippet-border-radius);\n}\n\n.chat-message-bubble pre code {\n background: none;\n padding: 0;\n}\n\n/* Links in messages */\n.chat-message-bubble a {\n color: var(--search-snippet-primary-color);\n text-decoration: underline;\n}\n\n.chat-message-bubble a:hover {\n text-decoration: none;\n}\n`;\n","/**\n * CSS Theme with comprehensive CSS custom properties\n */\n\nexport const baseStyles = `\n:host {\n /* Colors - Light Mode */\n --search-snippet-primary-color: #2563eb;\n --search-snippet-primary-hover: #0f51dfff;\n --search-snippet-background: #ffffff;\n --search-snippet-surface: #f8f9fa;\n --search-snippet-text-color: #212529;\n --search-snippet-text-secondary: #6c757d;\n --search-snippet-border-color: #dee2e6;\n --search-snippet-hover-background: #f1f3f5;\n --search-snippet-focus-ring: #0066cc40;\n --search-snippet-error-color: #dc3545;\n --search-snippet-error-background: #f8d7da;\n --search-snippet-success-color: #28a745;\n --search-snippet-success-background: #d4edda;\n --search-snippet-warning-color: #ffc107;\n --search-snippet-warning-background: #fff3cd;\n \n /* Message Colors */\n --search-snippet-user-message-bg: #0066cc;\n --search-snippet-user-message-text: #ffffff;\n --search-snippet-assistant-message-bg: #f1f3f5;\n --search-snippet-assistant-message-text: #212529;\n --search-snippet-system-message-bg: #fff3cd;\n --search-snippet-system-message-text: #856404;\n \n /* Typography */\n --search-snippet-font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', \n 'Helvetica Neue', Arial, sans-serif, 'Apple Color Emoji', \n 'Segoe UI Emoji', 'Segoe UI Symbol';\n --search-snippet-font-family-mono: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace;\n --search-snippet-font-size-base: 14px;\n --search-snippet-font-size-sm: 12px;\n --search-snippet-font-size-lg: 16px;\n --search-snippet-font-size-xl: 18px;\n --search-snippet-line-height: 1.5;\n --search-snippet-font-weight-normal: 400;\n --search-snippet-font-weight-medium: 500;\n --search-snippet-font-weight-bold: 600;\n \n /* Spacing */\n --search-snippet-spacing-xs: 4px;\n --search-snippet-spacing-sm: 8px;\n --search-snippet-spacing-md: 12px;\n --search-snippet-spacing-lg: 16px;\n --search-snippet-spacing-xl: 24px;\n --search-snippet-spacing-xxl: 32px;\n \n /* Sizing */\n --search-snippet-width: 100%;\n --search-snippet-max-width: 100%;\n --search-snippet-min-width: 320px;\n --search-snippet-max-height: 600px;\n --search-snippet-input-height: 44px;\n --search-snippet-button-height: 36px;\n --search-snippet-icon-size: 20px;\n \n /* Border */\n --search-snippet-border-width: 1px;\n --search-snippet-border-radius: 18px;\n \n /* Shadows */\n --search-snippet-shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);\n --search-snippet-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n --search-snippet-shadow-md: 0 4px 12px rgba(0, 0, 0, 0.15);\n --search-snippet-shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.2);\n --search-snippet-shadow-inner: inset 0 2px 4px 0 rgba(0, 0, 0, 0.06);\n \n /* Animation */\n --search-snippet-transition-fast: 150ms ease;\n --search-snippet-transition: 200ms ease;\n --search-snippet-transition-slow: 300ms ease;\n --search-snippet-animation-duration: 0.2s;\n \n /* Z-index */\n --search-snippet-z-dropdown: 1000;\n --search-snippet-z-modal: 1050;\n --search-snippet-z-popover: 1060;\n --search-snippet-z-tooltip: 1070;\n \n /* Layout */\n display: block;\n width: var(--search-snippet-width);\n max-width: var(--search-snippet-max-width);\n min-width: var(--search-snippet-min-width);\n font-family: var(--search-snippet-font-family);\n font-size: var(--search-snippet-font-size-base);\n line-height: var(--search-snippet-line-height);\n color: var(--search-snippet-text-color);\n\n\n /* Search */\n --search-snippet-icon-size: 20px;\n --search-snippet-icon-margin-left: 6px;\n --search-snippet-result-item-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);\n\n /* Chat Bubble */\n --chat-bubble-button-shadow: 0 8px 24px rgba(0, 0, 0, 0.2);\n --chat-bubble-window-shadow: 0 8px 24px rgba(0, 0, 0, 0.2);\n --chat-bubble-button-size: 60px;\n --chat-bubble-button-radius: 50%;\n --chat-bubble-button-icon-size: 28px;\n --chat-bubble-button-icon-color: white;\n --chat-bubble-button-bottom: 20px;\n --chat-bubble-button-right: 20px;\n --chat-bubble-button-z-index: 9999;\n --chat-bubble-position: fixed;\n\n\n}\n\n:host(:not([theme=\"dark\"])) {\n /* Colors - Light Mode */\n --search-snippet-primary-color: #2563eb;\n --search-snippet-primary-hover: #0f51dfff;\n --search-snippet-background: #ffffff;\n --search-snippet-surface: #f8f9fa;\n --search-snippet-text-color: #212529;\n --search-snippet-text-secondary: #6c757d;\n --search-snippet-border-color: #dee2e6;\n --search-snippet-hover-background: #f1f3f5;\n --search-snippet-focus-ring: #0066cc40;\n --search-snippet-error-color: #dc3545;\n --search-snippet-error-background: #f8d7da;\n --search-snippet-success-color: #28a745;\n --search-snippet-success-background: #d4edda;\n --search-snippet-warning-color: #ffc107;\n --search-snippet-warning-background: #fff3cd;\n \n /* Message Colors */\n --search-snippet-user-message-bg: #0066cc;\n --search-snippet-user-message-text: #ffffff;\n --search-snippet-assistant-message-bg: #f1f3f5;\n --search-snippet-assistant-message-text: #212529;\n --search-snippet-system-message-bg: #fff3cd;\n --search-snippet-system-message-text: #856404;\n}\n\n/* Dark Mode */\n@media (prefers-color-scheme: dark) {\n :host(:not([theme=\"light\"])) {\n --search-snippet-primary-color: #2563eb;\n --search-snippet-primary-hover: #0f51dfff;\n --search-snippet-background: #1a1b1e;\n --search-snippet-surface: #25262b;\n --search-snippet-text-color: #c1c2c5;\n --search-snippet-text-secondary: #909296;\n --search-snippet-border-color: #373a40;\n --search-snippet-hover-background: #2c2e33;\n --search-snippet-focus-ring: #4dabf740;\n --search-snippet-error-color: #ff6b6b;\n --search-snippet-error-background: #3d1f1f;\n --search-snippet-success-color: #51cf66;\n --search-snippet-success-background: #1f3d24;\n --search-snippet-warning-color: #ffd43b;\n --search-snippet-warning-background: #3d3419;\n \n --search-snippet-user-message-bg: #4dabf7;\n --search-snippet-user-message-text: #1a1b1e;\n --search-snippet-assistant-message-bg: #2c2e33;\n --search-snippet-assistant-message-text: #c1c2c5;\n --search-snippet-system-message-bg: #3d3419;\n --search-snippet-system-message-text: #ffd43b;\n color-scheme: dark;\n }\n}\n\n/* Auto theme support */\n:host([theme=\"light\"]) {\n color-scheme: light;\n}\n\n\n/* Base reset */\n* {\n box-sizing: border-box;\n margin: 0;\n padding: 0;\n}\n\n/* Container */\n.container {\n background: var(--search-snippet-background);\n border: var(--search-snippet-border-width) solid var(--search-snippet-border-color);\n border-radius: var(--search-snippet-border-radius);\n box-shadow: var(--search-snippet-shadow);\n overflow: hidden;\n display: flex;\n flex-direction: column;\n}\n\n/* Header */\n.header {\n padding: var(--search-snippet-spacing-md);\n border-bottom: var(--search-snippet-border-width) solid var(--search-snippet-border-color);\n background: var(--search-snippet-surface);\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--search-snippet-spacing-md);\n}\n\n.header-title {\n font-size: var(--search-snippet-font-size-lg);\n font-weight: var(--search-snippet-font-weight-bold);\n color: var(--search-snippet-text-color);\n}\n\n/* Input */\n.input-wrapper {\n position: relative;\n display: flex;\n align-items: center;\n gap: var(--search-snippet-spacing-sm);\n}\n\n.input {\n width: 100%;\n height: var(--search-snippet-input-height);\n padding: var(--search-snippet-spacing-sm) var(--search-snippet-spacing-md);\n font-family: var(--search-snippet-font-family);\n font-size: var(--search-snippet-font-size-base);\n line-height: var(--search-snippet-line-height);\n color: var(--search-snippet-text-color);\n background: var(--search-snippet-background);\n border: var(--search-snippet-border-width) solid var(--search-snippet-border-color);\n border-radius: var(--search-snippet-border-radius);\n outline: none;\n transition: var(--search-snippet-transition);\n}\n\n.input:focus {\n border-color: var(--search-snippet-primary-color);\n box-shadow: 0 0 0 3px var(--search-snippet-focus-ring);\n}\n\n.input::placeholder {\n color: var(--search-snippet-text-secondary);\n}\n\n.input:disabled {\n background: var(--search-snippet-surface);\n cursor: not-allowed;\n opacity: 0.6;\n}\n\n/* Button */\n.button {\n height: var(--search-snippet-button-height);\n padding: 0 var(--search-snippet-spacing-lg);\n font-family: var(--search-snippet-font-family);\n font-size: var(--search-snippet-font-size-base);\n font-weight: var(--search-snippet-font-weight-medium);\n color: #ffffff;\n background: var(--search-snippet-primary-color);\n border: none;\n border-radius: var(--search-snippet-border-radius);\n cursor: pointer;\n outline: none;\n transition: var(--search-snippet-transition);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--search-snippet-spacing-sm);\n white-space: nowrap;\n}\n\n.button:hover:not(:disabled) {\n background: var(--search-snippet-primary-hover);\n}\n\n.button:focus-visible {\n box-shadow: 0 0 0 3px var(--search-snippet-focus-ring);\n}\n\n.button:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.button-secondary {\n background: var(--search-snippet-surface);\n color: var(--search-snippet-text-color);\n border: var(--search-snippet-border-width) solid var(--search-snippet-border-color);\n}\n\n.button-secondary:hover:not(:disabled) {\n background: var(--search-snippet-hover-background);\n}\n\n/* Content area */\n.content {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n padding: var(--search-snippet-spacing-md);\n}\n\n/* Scrollbar styling */\n.content::-webkit-scrollbar {\n width: 8px;\n}\n\n.content::-webkit-scrollbar-track {\n background: var(--search-snippet-surface);\n}\n\n.content::-webkit-scrollbar-thumb {\n background: var(--search-snippet-border-color);\n border-radius: var(--search-snippet-border-radius);\n}\n\n.content::-webkit-scrollbar-thumb:hover {\n background: var(--search-snippet-text-secondary);\n}\n\n/* Loading spinner */\n.loading {\n display: inline-block;\n width: var(--search-snippet-icon-size);\n height: var(--search-snippet-icon-size);\n border: 2px solid currentColor;\n border-top-color: transparent;\n border-radius: 50%;\n animation: spin 0.6s linear infinite;\n}\n\n@keyframes spin {\n to { transform: rotate(360deg); }\n}\n\n/* Error message */\n.error {\n padding: var(--search-snippet-spacing-md);\n color: var(--search-snippet-error-color);\n background: var(--search-snippet-error-background);\n border-radius: var(--search-snippet-border-radius);\n font-size: var(--search-snippet-font-size-sm);\n}\n\n/* Empty state */\n.empty {\n padding: var(--search-snippet-spacing-xl);\n text-align: center;\n color: var(--search-snippet-text-secondary);\n}\n\n/* Accessibility */\n.sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border-width: 0;\n}\n\n/* Focus visible polyfill */\n.focus-visible:focus {\n outline: 2px solid var(--search-snippet-primary-color);\n outline-offset: 2px;\n}\n\n/* Powered by branding - block style (for sidebars) */\n.powered-by {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: var(--search-snippet-spacing-xs);\n padding: var(--search-snippet-spacing-sm) var(--search-snippet-spacing-md);\n font-size: var(--search-snippet-font-size-sm);\n color: var(--search-snippet-text-secondary);\n background: var(--search-snippet-surface);\n border-top: var(--search-snippet-border-width) solid var(--search-snippet-border-color);\n margin-top: auto;\n flex-shrink: 0;\n}\n\n.powered-by svg {\n width: 16px;\n height: 16px;\n flex-shrink: 0;\n}\n\n.powered-by a,\n.powered-by-inline a {\n color: var(--search-snippet-text-secondary);\n text-decoration: none;\n transition: color var(--search-snippet-transition-fast);\n display: inline-flex;\n align-items: center;\n gap: 4px;\n}\n\n.powered-by a:hover,\n.powered-by-inline a:hover {\n color: var(--search-snippet-primary-color);\n}\n\n/* Powered by branding - inline style (for headers/subtle placement) */\n.powered-by-inline {\n font-size: var(--search-snippet-font-size-sm);\n color: var(--search-snippet-text-secondary);\n padding: var(--search-snippet-spacing-xs) 0;\n text-align: center;\n}\n`;\n","/**\n * Cloudflare AI Search branding constants\n */\n\nexport const CLOUDFLARE_LOGO_SVG = `<svg width=\"32\" height=\"10\" viewBox=\"0 0 412 186\" xmlns=\"http://www.w3.org/2000/svg\" aria-label=\"Cloudflare\" role=\"img\">\n <path fill=\"#f38020\" d=\"m280.8395,183.31456c11,-26 -4,-38 -19,-38l-148,-2c-4,0 -4,-6 1,-7l150,-2c17,-1 37,-15 43,-33c0,0 10,-21 9,-24a97,97 0 0 0 -187,-11c-38,-25 -78,9 -69,46c-48,3 -65,46 -60,72c0,1 1,2 3,2l274,0c1,0 3,-1 3,-3z\"/>\n <path fill=\"#faae40\" d=\"m330.8395,81.31456c-4,0 -6,-1 -7,1l-5,21c-5,16 3,30 20,31l32,2c4,0 4,6 -1,7l-33,1c-36,4 -46,39 -46,39c0,2 0,3 2,3l113,0l3,-2a81,81 0 0 0 -78,-103\"/>\n</svg>`;\n\nexport const CLOUDFLARE_SEARCH_URL = 'https://search.ai.cloudflare.com';\n\nexport const POWERED_BY_BRANDING = `Powered by <a href=\"${CLOUDFLARE_SEARCH_URL}\" target=\"_blank\" rel=\"noopener noreferrer\">Cloudflare AI Search ${CLOUDFLARE_LOGO_SVG}</a>`;\n","/**\n * Converts markdown text to HTML\n * Supports: headers, bold, italic, links, lists, code blocks, inline code, blockquotes, and horizontal rules\n */\nexport function markdownToHtml(markdown: string): string {\n let html = markdown;\n\n // Escape HTML characters first to prevent XSS\n html = escapeHtml(html);\n\n // Process code blocks first (to protect from other transformations)\n html = html.replace(/```([\\s\\S]*?)```/g, (_, code) => `<pre><code>${code.trim()}</code></pre>`);\n\n // Split into lines for block-level processing\n const lines = html.split('\\n');\n const processedLines: string[] = [];\n let inList = false;\n let listType = '';\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n\n // Headers (h1-h6)\n const headerMatch = line.match(/^(#{1,6})\\s+(.+)$/);\n if (headerMatch) {\n const level = headerMatch[1].length;\n const content = headerMatch[2];\n processedLines.push(`<h${level}>${processInlineMarkdown(content)}</h${level}>`);\n continue;\n }\n\n // Horizontal rule\n if (line.match(/^---+$/)) {\n processedLines.push('<hr />');\n continue;\n }\n\n // Blockquote\n if (line.match(/^>\\s+/)) {\n const content = line.replace(/^>\\s+/, '');\n processedLines.push(`<blockquote>${processInlineMarkdown(content)}</blockquote>`);\n continue;\n }\n\n // Unordered list\n const ulMatch = line.match(/^[-*]\\s+(.+)$/);\n if (ulMatch) {\n if (!inList || listType !== 'ul') {\n if (inList) processedLines.push(`</${listType}>`);\n processedLines.push('<ul>');\n inList = true;\n listType = 'ul';\n }\n processedLines.push(`<li>${processInlineMarkdown(ulMatch[1])}</li>`);\n continue;\n }\n\n // Ordered list\n const olMatch = line.match(/^\\d+\\.\\s+(.+)$/);\n if (olMatch) {\n if (!inList || listType !== 'ol') {\n if (inList) processedLines.push(`</${listType}>`);\n processedLines.push('<ol>');\n inList = true;\n listType = 'ol';\n }\n processedLines.push(`<li>${processInlineMarkdown(olMatch[1])}</li>`);\n continue;\n }\n\n // Close list if we're no longer in one\n if (inList) {\n processedLines.push(`</${listType}>`);\n inList = false;\n listType = '';\n }\n\n // Empty line\n if (line.trim() === '') {\n processedLines.push('<br />');\n continue;\n }\n\n // Regular paragraph\n processedLines.push(`<p>${processInlineMarkdown(line)}</p>`);\n }\n\n // Close any open list\n if (inList) {\n processedLines.push(`</${listType}>`);\n }\n\n return processedLines.join('\\n');\n}\n\n/**\n * Process inline markdown elements (bold, italic, links, inline code)\n */\nfunction processInlineMarkdown(text: string): string {\n let result = text;\n\n // Inline code (before other inline elements)\n result = result.replace(/`([^`]+)`/g, '<code>$1</code>');\n\n // Bold and italic (***text***)\n result = result.replace(/\\*\\*\\*(.+?)\\*\\*\\*/g, '<strong><em>$1</em></strong>');\n result = result.replace(/___(.+?)___/g, '<strong><em>$1</em></strong>');\n\n // Bold (**text** or __text__)\n result = result.replace(/\\*\\*(.+?)\\*\\*/g, '<strong>$1</strong>');\n result = result.replace(/__(.+?)__/g, '<strong>$1</strong>');\n\n // Italic (*text* or _text_)\n result = result.replace(/\\*(.+?)\\*/g, '<em>$1</em>');\n result = result.replace(/_(.+?)_/g, '<em>$1</em>');\n\n // Links [text](url)\n result = result.replace(\n /\\[([^\\]]+)\\]\\(([^)]+)\\)/g,\n '<a href=\"$2\" target=\"_blank\" rel=\"noopener noreferrer\">$1</a>'\n );\n\n return result;\n}\n\n/**\n * Escape HTML characters to prevent XSS\n */\nfunction escapeHtml(text: string): string {\n const htmlEntities: Record<string, string> = {\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": ''',\n };\n\n return text.replace(/[&<>\"']/g, (char) => htmlEntities[char] || char);\n}\n","/**\n * ChatView Component\n * Handles chat interface with streaming support\n */\n\nimport type { Client } from '../api/index.ts';\nimport type { SearchSnippetProps } from '../types/index.ts';\nimport { createCustomEvent, escapeHTML, formatTimestamp, generateId } from '../utils/index.ts';\nimport { markdownToHtml } from '../utils/markdown.ts';\nexport interface Message {\n id: string;\n role: 'user' | 'assistant' | 'system';\n content: string;\n timestamp: number;\n metadata?: Record<string, unknown>;\n}\nexport class ChatView {\n private container: HTMLElement;\n private client: Client;\n private props: SearchSnippetProps;\n private inputElement: HTMLTextAreaElement | null = null;\n private messagesContainer: HTMLElement | null = null;\n private sendButton: HTMLButtonElement | null = null;\n private messages: Message[] = [];\n private isStreaming = false;\n private currentStreamingMessageId: string | null = null;\n\n // Event handler references for cleanup\n private handleInputResize: ((e: Event) => void) | null = null;\n private handleInputKeydown: ((e: KeyboardEvent) => void) | null = null;\n private handleSendClick: (() => void) | null = null;\n\n constructor(container: HTMLElement, client: Client, props: SearchSnippetProps) {\n this.container = container;\n this.client = client;\n this.props = props;\n\n this.render();\n this.attachEventListeners();\n }\n\n /**\n * Render the chat interface\n */\n private render(): void {\n this.container.innerHTML = `\n <div class=\"chat-container\">\n <div class=\"chat-messages\">\n <div class=\"chat-empty\">\n <svg class=\"chat-empty-icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\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\"></path>\n </svg>\n <div class=\"chat-empty-title\">Start a Conversation</div>\n <div class=\"chat-empty-description\">\n Send a message to begin chatting\n </div>\n </div>\n </div>\n <div class=\"chat-input-area\">\n <div class=\"chat-input-wrapper\">\n <textarea\n class=\"chat-input\"\n placeholder=\"${escapeHTML(this.props.placeholder || 'Type a message...')}\"\n aria-label=\"Chat message input\"\n style=\"height: 40px;\"\n rows=\"1\"\n ></textarea>\n <button class=\"button chat-send-button\" aria-label=\"Send message\">\n <span>Send</span>\n </button>\n </div>\n </div>\n </div>\n `;\n\n this.messagesContainer = this.container.querySelector('.chat-messages');\n this.inputElement = this.container.querySelector('.chat-input');\n this.sendButton = this.container.querySelector('.chat-send-button');\n }\n\n /**\n * Attach event listeners\n */\n private attachEventListeners(): void {\n if (!this.inputElement || !this.sendButton) return;\n\n // Auto-resize textarea\n this.handleInputResize = (e: Event) => {\n const target = e.target as HTMLTextAreaElement;\n target.style.height = 'auto';\n target.style.height = `${target.scrollHeight}px`;\n };\n this.inputElement.addEventListener('input', this.handleInputResize);\n\n // Enter to send (Shift+Enter for new line)\n this.handleInputKeydown = (e: KeyboardEvent) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n this.handleSendMessage();\n }\n };\n this.inputElement.addEventListener('keydown', this.handleInputKeydown);\n\n // Send button click\n this.handleSendClick = () => {\n this.handleSendMessage();\n };\n this.sendButton.addEventListener('click', this.handleSendClick);\n }\n\n /**\n * Handle send message\n */\n private async handleSendMessage(): Promise<void> {\n if (!this.inputElement || this.isStreaming) return;\n\n const content = this.inputElement.value.trim();\n if (content.length === 0) return;\n\n // Clear input\n this.inputElement.value = '';\n this.inputElement.style.height = 'auto';\n\n // Send message\n await this.sendMessage(content);\n }\n\n /**\n * Send a message\n */\n public async sendMessage(content: string): Promise<void> {\n // Add user message\n const userMessage: Message = {\n id: generateId('msg'),\n role: 'user',\n content,\n timestamp: Date.now(),\n };\n\n this.addMessage(userMessage);\n this.renderMessages(true);\n this.setStreamingState(true);\n\n // Create placeholder for assistant response\n const assistantMessageId = generateId('msg');\n const assistantMessage: Message = {\n id: assistantMessageId,\n role: 'assistant',\n content: '',\n timestamp: Date.now(),\n };\n\n this.addMessage(assistantMessage);\n this.currentStreamingMessageId = assistantMessageId;\n this.renderMessages(true);\n\n try {\n // Stream the response\n const stream = this.client.chat(content);\n\n let fullContent = '';\n\n for await (const chunk of stream) {\n if (chunk.type === 'text' && chunk.message) {\n fullContent += chunk.message;\n this.updateStreamingMessage(assistantMessageId, fullContent);\n } else if (chunk.type === 'error') {\n this.showErrorInMessage(assistantMessageId, chunk.message || 'Unknown error');\n break;\n }\n // else if (chunk.type === 'done') {\n // break;\n // }\n }\n\n // Update final message\n const messageIndex = this.messages.findIndex((m) => m.id === assistantMessageId);\n if (messageIndex !== -1) {\n this.messages[messageIndex].content = fullContent;\n }\n\n // Emit message event\n this.container.dispatchEvent(createCustomEvent('message', { message: assistantMessage }));\n } catch (error) {\n this.showErrorInMessage(assistantMessageId, (error as Error).message);\n\n // Emit error event\n this.container.dispatchEvent(\n createCustomEvent('error', {\n error: {\n message: (error as Error).message,\n code: 'CHAT_ERROR',\n },\n })\n );\n } finally {\n this.setStreamingState(false);\n this.renderMessages();\n this.currentStreamingMessageId = null;\n }\n }\n\n /**\n * Add a message to the chat\n */\n private addMessage(message: Message): void {\n this.messages.push(message);\n this.renderMessages();\n }\n\n /**\n * Update streaming message content\n */\n private updateStreamingMessage(messageId: string, content: string): void {\n const messageIndex = this.messages.findIndex((m) => m.id === messageId);\n if (messageIndex !== -1) {\n this.messages[messageIndex].content = content;\n this.renderMessages(true);\n }\n }\n\n /**\n * Show error in message\n */\n private showErrorInMessage(messageId: string, error: string): void {\n const messageIndex = this.messages.findIndex((m) => m.id === messageId);\n if (messageIndex !== -1) {\n this.messages[messageIndex].content = `Error: ${error}`;\n this.renderMessages();\n }\n }\n\n /**\n * Render all messages\n */\n private renderMessages(isStreaming = false): void {\n if (!this.messagesContainer) return;\n\n if (this.messages.length === 0) {\n this.messagesContainer.innerHTML = `\n <div class=\"chat-empty\">\n <svg class=\"chat-empty-icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\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\"></path>\n </svg>\n <div class=\"chat-empty-title\">Start a Conversation</div>\n <div class=\"chat-empty-description\">\n Send a message to begin chatting\n </div>\n </div>\n `;\n return;\n }\n\n const messagesHTML = this.messages\n .map((message) =>\n this.renderMessage(message, isStreaming && message.id === this.currentStreamingMessageId)\n )\n .join('');\n\n this.messagesContainer.innerHTML = messagesHTML;\n\n // Scroll to bottom\n this.scrollToBottom();\n }\n\n /**\n * Render a single message\n */\n private renderMessage(message: Message, isStreaming = false): string {\n const roleClass = `chat-message-${message.role}`;\n const avatar = message.role === 'user' ? 'U' : 'AI';\n\n return `\n <div class=\"chat-message ${roleClass}\">\n <div class=\"chat-message-avatar\">${avatar}</div>\n <div class=\"chat-message-content\">\n <div class=\"chat-message-bubble\">\n ${message.content ? `<div class=\"chat-message-text\">${markdownToHtml(message.content)}</div>` : ''}\n ${isStreaming ? '<div class=\"chat-streaming\"><span class=\"chat-streaming-dot\"></span><span class=\"chat-streaming-dot\"></span><span class=\"chat-streaming-dot\"></span></div>' : ''}\n </div>\n <div class=\"chat-message-metadata\">\n <span class=\"chat-message-time\">${formatTimestamp(message.timestamp)}</span>\n </div>\n </div>\n </div>\n `;\n }\n\n /**\n * Scroll to bottom of messages\n */\n private scrollToBottom(): void {\n if (!this.messagesContainer) return;\n\n requestAnimationFrame(() => {\n if (this.messagesContainer) {\n this.messagesContainer.scrollTop = this.messagesContainer.scrollHeight;\n }\n });\n }\n\n /**\n * Set streaming state\n */\n private setStreamingState(streaming: boolean): void {\n this.isStreaming = streaming;\n\n if (this.inputElement) {\n this.inputElement.disabled = streaming;\n }\n\n if (this.sendButton) {\n this.sendButton.disabled = streaming;\n this.sendButton.innerHTML = streaming ? '<div class=\"loading\"></div>' : '<span>Send</span>';\n }\n }\n\n /**\n * Get all messages\n */\n public getMessages(): Message[] {\n return [...this.messages];\n }\n\n /**\n * Clear all messages\n */\n public clearMessages(): void {\n this.messages = [];\n this.renderMessages();\n }\n\n /**\n * Set messages (for restoring history)\n */\n public setMessages(messages: Message[]): void {\n this.messages = [...messages];\n this.renderMessages();\n }\n\n /**\n * Destroy and cleanup\n */\n public destroy(): void {\n if (this.isStreaming) {\n this.client.cancelAllRequests();\n }\n\n // Remove event listeners\n if (this.inputElement) {\n if (this.handleInputResize) {\n this.inputElement.removeEventListener('input', this.handleInputResize);\n }\n if (this.handleInputKeydown) {\n this.inputElement.removeEventListener('keydown', this.handleInputKeydown);\n }\n }\n\n if (this.sendButton && this.handleSendClick) {\n this.sendButton.removeEventListener('click', this.handleSendClick);\n }\n\n // Clear handler references\n this.handleInputResize = null;\n this.handleInputKeydown = null;\n this.handleSendClick = null;\n }\n}\n","/**\n * Chat Bubble Snippet\n * A floating chat widget that expands from a bubble button\n * Fixed position in bottom-right corner\n */\n\nimport type { Client } from '../api/index.ts';\nimport { chatStyles } from '../styles/chat.ts';\nimport { baseStyles } from '../styles/theme.ts';\nimport type { SearchSnippetProps } from '../types/index.ts';\nimport {\n createClient,\n createCustomEvent,\n parseAttribute,\n parseBooleanAttribute,\n} from '../utils/index.ts';\nimport { POWERED_BY_BRANDING } from '../constants.ts';\nimport type { Message } from './chat-view.ts';\nimport { ChatView } from './chat-view.ts';\n\nconst COMPONENT_NAME = 'chat-bubble-snippet';\n\nexport class ChatBubbleSnippet extends HTMLElement {\n private shadow: ShadowRoot;\n private client: Client | null = null;\n private chatView: ChatView | null = null;\n private container: HTMLElement | null = null;\n private isExpanded = false;\n private isMinimized = false;\n\n // Event handler references for cleanup\n private handleBubbleClick: (() => void) | null = null;\n private handleCloseClick: (() => void) | null = null;\n private handleMinimizeClick: (() => void) | null = null;\n private handleClearClick: (() => void) | null = null;\n\n static get observedAttributes() {\n return ['api-url', 'placeholder', 'theme', 'hide-branding'] as const;\n }\n\n constructor() {\n super();\n this.shadow = this.attachShadow({ mode: 'open' });\n }\n\n connectedCallback(): void {\n this.render();\n this.initializeClient();\n this.dispatchEvent(createCustomEvent('ready', undefined));\n }\n\n disconnectedCallback(): void {\n this.cleanup();\n }\n\n attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void {\n if (oldValue === newValue) return;\n\n if (name === 'api-url') {\n this.initializeClient();\n } else if (name === 'theme') {\n // Theme changes are handled automatically by CSS :host([theme]) selectors\n this.updateTheme(newValue);\n }\n }\n\n private getProps(): SearchSnippetProps {\n return {\n apiUrl: parseAttribute(this.getAttribute('api-url'), 'http://localhost:3000'),\n placeholder: parseAttribute(this.getAttribute('placeholder'), 'Type a message...'),\n theme: parseAttribute(this.getAttribute('theme'), 'auto') as 'light' | 'dark' | 'auto',\n hideBranding: parseBooleanAttribute(this.getAttribute('hide-branding'), false),\n };\n }\n\n private initializeClient(): void {\n const props = this.getProps();\n\n if (!props.apiUrl) {\n console.error('ChatBubbleSnippet: api-url attribute is required');\n return;\n }\n\n try {\n this.client = createClient(props.apiUrl);\n } catch (error) {\n console.error('ChatBubbleSnippet:', error);\n }\n }\n\n private render(): void {\n const style = document.createElement('style');\n style.textContent = `${baseStyles}\\n${chatStyles}\\n${this.getBubbleStyles()}`;\n\n this.container = document.createElement('div');\n this.container.className = 'chat-bubble-widget';\n this.container.innerHTML = this.getBaseHTML();\n\n this.shadow.innerHTML = '';\n this.shadow.appendChild(style);\n this.shadow.appendChild(this.container);\n\n this.attachEventListeners();\n }\n\n private getBubbleStyles(): string {\n return `\n .chat-bubble-widget {\n position: var(--chat-bubble-position);\n bottom: var(--chat-bubble-button-bottom);\n right: var(--chat-bubble-button-right);\n z-index: var(--chat-bubble-button-z-index);\n font-family: var(--search-snippet-font-family);\n font-size: var(--search-snippet-font-size-base);\n }\n\n .bubble-button {\n width: var(--chat-bubble-button-size);\n height: var(--chat-bubble-button-size);\n border-radius: var(--chat-bubble-button-radius);\n background: var(--search-snippet-primary-color);\n border: none;\n cursor: pointer;\n box-shadow: var(--chat-bubble-button-shadow);\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.3s ease;\n position: relative;\n }\n\n .bubble-button:hover {\n background: var(--search-snippet-primary-hover);\n transform: scale(1.05);\n }\n\n .bubble-button svg {\n width: var(--chat-bubble-button-icon-size);\n height: var(--chat-bubble-button-icon-size);\n color: var(--chat-bubble-button-icon-color);\n }\n\n .bubble-button.hidden {\n opacity: 0;\n pointer-events: none;\n transform: scale(0);\n }\n\n .chat-window {\n position: absolute;\n bottom: 0;\n right: 0;\n width: 380px;\n height: 500px;\n background: var(--search-snippet-background);\n border-radius: var(--search-snippet-border-radius);\n box-shadow: var(--chat-bubble-window-shadow);\n display: flex;\n flex-direction: column;\n opacity: 0;\n transform: scale(0.8) translateY(20px);\n transform-origin: bottom right;\n transition: all 0.3s cubic-bezier(0.68, -0.55, 0.265, 1.55);\n pointer-events: none;\n overflow: hidden;\n border: var(--search-snippet-border-width) solid var(--search-snippet-border-color);\n }\n\n .chat-window.expanded {\n opacity: 1;\n transform: scale(1) translateY(0);\n pointer-events: auto;\n }\n\n .chat-window.minimized {\n height: 58px;\n overflow: hidden;\n }\n\n .chat-header {\n background: var(--search-snippet-surface);\n padding: var(--search-snippet-spacing-md);\n border-bottom: var(--search-snippet-border-width) solid var(--search-snippet-border-color);\n display: flex;\n align-items: center;\n justify-content: space-between;\n flex-shrink: 0;\n }\n\n .chat-header-title {\n font-weight: var(--search-snippet-font-weight-bold);\n color: var(--search-snippet-text-color);\n display: flex;\n align-items: center;\n gap: var(--search-snippet-spacing-sm);\n font-size: var(--search-snippet-font-size-lg);\n }\n\n .chat-header-title svg {\n width: 20px;\n height: 20px;\n }\n\n .chat-header-actions {\n display: flex;\n gap: var(--search-snippet-spacing-xs);\n }\n\n .icon-button {\n width: 32px;\n height: 32px;\n border: none;\n background: transparent;\n border-radius: var(--search-snippet-border-radius);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: background var(--search-snippet-transition-fast);\n color: var(--search-snippet-text-color);\n }\n\n .icon-button:hover {\n background: var(--search-snippet-hover-background);\n }\n\n .icon-button svg {\n width: 18px;\n height: 18px;\n }\n\n .chat-content {\n flex: 1;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n }\n\n @media (max-width: 480px) {\n .chat-window {\n width: calc(100vw - 40px);\n max-width: 400px;\n }\n }\n `;\n }\n\n private getBaseHTML(): string {\n const props = this.getProps();\n const brandingHTML = props.hideBranding\n ? ''\n : `<div class=\"powered-by\">${POWERED_BY_BRANDING}</div>`;\n\n return `\n <button class=\"bubble-button\" aria-label=\"Open chat\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\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\"></path>\n </svg>\n </button>\n <div class=\"chat-window\">\n <div class=\"chat-header\">\n <div class=\"chat-header-title\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\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\"></path>\n </svg>\n <span>Chat</span>\n </div>\n <div class=\"chat-header-actions\">\n <button class=\"icon-button clear-button\" aria-label=\"Clear history\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <polyline points=\"3 6 5 6 21 6\"></polyline>\n <path d=\"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2\"></path>\n </svg>\n </button>\n <button class=\"icon-button minimize-button\" aria-label=\"Minimize\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\"></line>\n </svg>\n </button>\n <button class=\"icon-button close-button\" aria-label=\"Close\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line>\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line>\n </svg>\n </button>\n </div>\n </div>\n <div class=\"chat-content\"></div>\n ${brandingHTML}\n </div>\n `;\n }\n\n private attachEventListeners(): void {\n const bubbleButton = this.shadow.querySelector('.bubble-button');\n const closeButton = this.shadow.querySelector('.close-button');\n const minimizeButton = this.shadow.querySelector('.minimize-button');\n const clearButton = this.shadow.querySelector('.clear-button');\n\n this.handleBubbleClick = () => this.toggleChat();\n this.handleCloseClick = () => this.closeChat();\n this.handleMinimizeClick = () => this.toggleMinimize();\n this.handleClearClick = () => this.clearChat();\n\n bubbleButton?.addEventListener('click', this.handleBubbleClick);\n closeButton?.addEventListener('click', this.handleCloseClick);\n minimizeButton?.addEventListener('click', this.handleMinimizeClick);\n clearButton?.addEventListener('click', this.handleClearClick);\n }\n\n private removeEventListeners(): void {\n const bubbleButton = this.shadow.querySelector('.bubble-button');\n const closeButton = this.shadow.querySelector('.close-button');\n const minimizeButton = this.shadow.querySelector('.minimize-button');\n const clearButton = this.shadow.querySelector('.clear-button');\n\n if (this.handleBubbleClick) {\n bubbleButton?.removeEventListener('click', this.handleBubbleClick);\n }\n if (this.handleCloseClick) {\n closeButton?.removeEventListener('click', this.handleCloseClick);\n }\n if (this.handleMinimizeClick) {\n minimizeButton?.removeEventListener('click', this.handleMinimizeClick);\n }\n if (this.handleClearClick) {\n clearButton?.removeEventListener('click', this.handleClearClick);\n }\n\n // Clear handler references\n this.handleBubbleClick = null;\n this.handleCloseClick = null;\n this.handleMinimizeClick = null;\n this.handleClearClick = null;\n }\n\n private toggleChat(): void {\n this.isExpanded = !this.isExpanded;\n const bubbleButton = this.shadow.querySelector('.bubble-button');\n const chatWindow = this.shadow.querySelector('.chat-window');\n\n if (this.isExpanded) {\n bubbleButton?.classList.add('hidden');\n chatWindow?.classList.add('expanded');\n this.initializeChatView();\n } else {\n bubbleButton?.classList.remove('hidden');\n chatWindow?.classList.remove('expanded');\n }\n }\n\n private closeChat(): void {\n this.isExpanded = false;\n this.isMinimized = false;\n const bubbleButton = this.shadow.querySelector('.bubble-button');\n const chatWindow = this.shadow.querySelector('.chat-window');\n\n bubbleButton?.classList.remove('hidden');\n chatWindow?.classList.remove('expanded', 'minimized');\n }\n\n private toggleMinimize(): void {\n this.isMinimized = !this.isMinimized;\n const chatWindow = this.shadow.querySelector('.chat-window');\n\n if (this.isMinimized) {\n chatWindow?.classList.add('minimized');\n } else {\n chatWindow?.classList.remove('minimized');\n }\n }\n\n private initializeChatView(): void {\n if (this.chatView || !this.client) return;\n\n const chatContent = this.shadow.querySelector('.chat-content') as HTMLElement;\n if (!chatContent) return;\n\n const props = this.getProps();\n this.chatView = new ChatView(chatContent, this.client, props);\n }\n\n private updateTheme(theme: string | null): void {\n // CSS :host([theme]) selectors handle theming automatically\n // For 'auto' mode, remove the attribute to let @media (prefers-color-scheme) work\n const validTheme = theme === 'light' || theme === 'dark' ? theme : null;\n\n if (\n validTheme === null &&\n this.hasAttribute('theme') &&\n this.getAttribute('theme') !== 'auto'\n ) {\n this.removeAttribute('theme');\n }\n }\n\n private cleanup(): void {\n this.removeEventListeners();\n\n if (this.client) {\n this.client.cancelAllRequests();\n }\n\n if (this.chatView) {\n this.chatView.destroy();\n }\n }\n\n // Public API\n public clearChat(): void {\n this.chatView?.clearMessages();\n }\n\n public async sendMessage(content: string): Promise<void> {\n if (this.chatView) {\n await this.chatView.sendMessage(content);\n }\n }\n\n public getMessages(): Message[] {\n return this.chatView?.getMessages() || [];\n }\n}\n\n// Register the custom element\nif (!customElements.get(COMPONENT_NAME)) {\n customElements.define(COMPONENT_NAME, ChatBubbleSnippet);\n}\n","/**\n * Chat Page Snippet\n * A full-page chat interface with history support\n */\n\nimport type { Client } from '../api/index.ts';\nimport { chatStyles } from '../styles/chat.ts';\nimport { baseStyles } from '../styles/theme.ts';\nimport type { SearchSnippetProps } from '../types/index.ts';\nimport {\n createClient,\n createCustomEvent,\n parseAttribute,\n parseBooleanAttribute,\n} from '../utils/index.ts';\nimport { POWERED_BY_BRANDING } from '../constants.ts';\nimport type { Message } from './chat-view.ts';\nimport { ChatView } from './chat-view.ts';\n\nconst COMPONENT_NAME = 'chat-page-snippet';\nconst STORAGE_KEY = 'chat-page-sessions';\n\ninterface ChatSession {\n id: string;\n title: string;\n messages: Message[];\n createdAt: number;\n updatedAt: number;\n}\n\nexport class ChatPageSnippet extends HTMLElement {\n private shadow: ShadowRoot;\n private client: Client | null = null;\n private chatView: ChatView | null = null;\n private container: HTMLElement | null = null;\n private sessions: ChatSession[] = [];\n private currentSessionId: string | null = null;\n private sidebarCollapsed = false;\n\n // Event handler references for cleanup\n private handleClearClick: (() => void) | null = null;\n private handleNewChatClick: (() => void) | null = null;\n private handleToggleSidebarClick: (() => void) | null = null;\n private handleChatListClick: ((e: Event) => void) | null = null;\n private handleMessageEvent: (() => void) | null = null;\n\n static get observedAttributes() {\n return ['api-url', 'placeholder', 'theme', 'hide-branding'] as const;\n }\n\n constructor() {\n super();\n this.shadow = this.attachShadow({ mode: 'open' });\n this.loadSessions();\n }\n\n connectedCallback(): void {\n this.render();\n this.initializeClient();\n this.setupView();\n this.dispatchEvent(createCustomEvent('ready', undefined));\n }\n\n disconnectedCallback(): void {\n this.saveCurrentSession();\n this.cleanup();\n }\n\n attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void {\n if (oldValue === newValue) return;\n\n if (name === 'api-url') {\n this.initializeClient();\n this.setupView();\n } else if (name === 'theme') {\n // Theme changes are handled automatically by CSS :host([theme]) selectors\n this.updateTheme(newValue);\n }\n }\n\n private getProps(): SearchSnippetProps {\n return {\n apiUrl: parseAttribute(this.getAttribute('api-url'), 'http://localhost:3000'),\n placeholder: parseAttribute(this.getAttribute('placeholder'), 'Type a message...'),\n theme: parseAttribute(this.getAttribute('theme'), 'auto') as 'light' | 'dark' | 'auto',\n hideBranding: parseBooleanAttribute(this.getAttribute('hide-branding'), false),\n };\n }\n\n private initializeClient(): void {\n const props = this.getProps();\n\n if (!props.apiUrl) {\n console.error('ChatPageSnippet: api-url attribute is required');\n return;\n }\n\n try {\n this.client = createClient(props.apiUrl);\n } catch (error) {\n console.error('ChatPageSnippet:', error);\n }\n }\n\n private render(): void {\n const style = document.createElement('style');\n style.textContent = `${baseStyles}\\n${chatStyles}\\n${this.getPageStyles()}`;\n\n this.container = document.createElement('div');\n this.container.className = 'chat-page-container';\n this.container.innerHTML = this.getBaseHTML();\n\n this.shadow.innerHTML = '';\n this.shadow.appendChild(style);\n this.shadow.appendChild(this.container);\n\n this.attachEventListeners();\n }\n\n private getPageStyles(): string {\n return `\n :host {\n display: block;\n width: 100%;\n height: 100vh;\n }\n\n .chat-page-container {\n display: flex;\n height: 100%;\n background: var(--search-snippet-background);\n }\n\n /* Sidebar styles */\n .chat-sidebar {\n width: 280px;\n min-width: 280px;\n background: var(--search-snippet-surface);\n border-right: var(--search-snippet-border-width) solid var(--search-snippet-border-color);\n display: flex;\n flex-direction: column;\n transition: var(--search-snippet-transition);\n overflow: hidden;\n }\n\n .chat-sidebar.collapsed {\n width: 0;\n min-width: 0;\n border-right: none;\n }\n\n .sidebar-header {\n padding: var(--search-snippet-spacing-lg);\n border-bottom: var(--search-snippet-border-width) solid var(--search-snippet-border-color);\n display: flex;\n align-items: center;\n justify-content: space-between;\n flex-shrink: 0;\n height: 69px;\n }\n\n .sidebar-title {\n font-size: var(--search-snippet-font-size-lg);\n font-weight: var(--search-snippet-font-weight-bold);\n color: var(--search-snippet-text-color);\n }\n\n .new-chat-button {\n width: 100%;\n height: var(--search-snippet-button-height);\n margin: var(--search-snippet-spacing-md) var(--search-snippet-spacing-lg);\n padding: 0 var(--search-snippet-spacing-lg);\n font-family: var(--search-snippet-font-family);\n font-size: var(--search-snippet-font-size-base);\n font-weight: var(--search-snippet-font-weight-medium);\n color: #fff;\n background: var(--search-snippet-primary-color);\n border: none;\n border-radius: var(--search-snippet-border-radius);\n cursor: pointer;\n outline: none;\n transition: var(--search-snippet-transition);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--search-snippet-spacing-sm);\n box-sizing: border-box;\n width: calc(100% - var(--search-snippet-spacing-lg) * 2);\n }\n\n .new-chat-button:hover {\n opacity: 0.9;\n }\n\n .new-chat-button svg {\n width: 16px;\n height: 16px;\n }\n\n .chat-list {\n flex: 1;\n overflow-y: auto;\n padding: var(--search-snippet-spacing-sm);\n }\n\n .chat-list-item {\n display: flex;\n align-items: center;\n padding: var(--search-snippet-spacing-md) var(--search-snippet-spacing-lg);\n margin-bottom: var(--search-snippet-spacing-xs);\n border-radius: var(--search-snippet-border-radius);\n cursor: pointer;\n transition: var(--search-snippet-transition);\n gap: var(--search-snippet-spacing-sm);\n }\n\n .chat-list-item:hover {\n background: var(--search-snippet-hover-background);\n }\n\n .chat-list-item.active {\n background: var(--search-snippet-hover-background);\n border: var(--search-snippet-border-width) solid var(--search-snippet-border-color);\n }\n\n .chat-list-item-content {\n flex: 1;\n min-width: 0;\n }\n\n .chat-list-item-title {\n font-size: var(--search-snippet-font-size-base);\n font-weight: var(--search-snippet-font-weight-medium);\n color: var(--search-snippet-text-color);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .chat-list-item-date {\n font-size: var(--search-snippet-font-size-sm);\n color: var(--search-snippet-text-secondary);\n margin-top: 2px;\n }\n\n .chat-list-item-delete {\n opacity: 0;\n background: none;\n border: none;\n padding: var(--search-snippet-spacing-xs);\n cursor: pointer;\n color: var(--search-snippet-text-secondary);\n border-radius: var(--search-snippet-border-radius-sm);\n transition: var(--search-snippet-transition);\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .chat-list-item:hover .chat-list-item-delete {\n opacity: 1;\n }\n\n .chat-list-item-delete:hover {\n background: var(--search-snippet-error-background, rgba(239, 68, 68, 0.1));\n color: var(--search-snippet-error-color, #ef4444);\n }\n\n .chat-list-item-delete svg {\n width: 14px;\n height: 14px;\n }\n\n .chat-list-empty {\n padding: var(--search-snippet-spacing-xl);\n text-align: center;\n color: var(--search-snippet-text-secondary);\n font-size: var(--search-snippet-font-size-sm);\n }\n\n /* Main content area */\n .chat-main {\n flex: 1;\n display: flex;\n flex-direction: column;\n min-width: 0;\n }\n\n .chat-page-header {\n background: var(--search-snippet-surface);\n padding: var(--search-snippet-spacing-lg);\n border-bottom: var(--search-snippet-border-width) solid var(--search-snippet-border-color);\n display: flex;\n align-items: center;\n justify-content: space-between;\n flex-shrink: 0;\n }\n\n .chat-page-header-left {\n display: flex;\n align-items: center;\n gap: var(--search-snippet-spacing-md);\n }\n\n .toggle-sidebar-button {\n width: 36px;\n height: 36px;\n padding: 0;\n font-family: var(--search-snippet-font-family);\n color: var(--search-snippet-text-color);\n background: var(--search-snippet-background);\n border: var(--search-snippet-border-width) solid var(--search-snippet-border-color);\n border-radius: var(--search-snippet-border-radius);\n cursor: pointer;\n outline: none;\n transition: var(--search-snippet-transition);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n }\n\n .toggle-sidebar-button:hover {\n background: var(--search-snippet-hover-background);\n }\n\n .toggle-sidebar-button svg {\n width: 18px;\n height: 18px;\n }\n\n .chat-page-header-title {\n font-size: var(--search-snippet-font-size-xl);\n font-weight: var(--search-snippet-font-weight-bold);\n color: var(--search-snippet-text-color);\n display: flex;\n align-items: center;\n gap: var(--search-snippet-spacing-md);\n }\n\n .chat-page-header-title svg {\n width: 28px;\n height: 28px;\n }\n\n .chat-page-header-actions {\n display: flex;\n gap: var(--search-snippet-spacing-sm);\n }\n\n .header-button {\n height: var(--search-snippet-button-height);\n padding: 0 var(--search-snippet-spacing-lg);\n font-family: var(--search-snippet-font-family);\n font-size: var(--search-snippet-font-size-base);\n font-weight: var(--search-snippet-font-weight-medium);\n color: var(--search-snippet-text-color);\n background: var(--search-snippet-background);\n border: var(--search-snippet-border-width) solid var(--search-snippet-border-color);\n border-radius: var(--search-snippet-border-radius);\n cursor: pointer;\n outline: none;\n transition: var(--search-snippet-transition);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--search-snippet-spacing-sm);\n }\n\n .header-button:hover {\n background: var(--search-snippet-hover-background);\n }\n\n .header-button svg {\n width: 16px;\n height: 16px;\n }\n\n .chat-page-content {\n flex: 1;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n width: 100%;\n }\n\n .container {\n border: none;\n box-shadow: none;\n height: 100%;\n width: 100%;\n background: var(--search-snippet-background);\n border-radius: 0;\n }\n `;\n }\n\n private getBaseHTML(): string {\n const props = this.getProps();\n const brandingHTML = props.hideBranding\n ? ''\n : `<div class=\"powered-by\">${POWERED_BY_BRANDING}</div>`;\n\n return `\n <div class=\"chat-sidebar\">\n <div class=\"sidebar-header\">\n <span class=\"sidebar-title\">History</span>\n </div>\n <button class=\"new-chat-button\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M12 5v14M5 12h14\"></path>\n </svg>\n New Chat\n </button>\n <div class=\"chat-list\"></div>\n ${brandingHTML}\n </div>\n <div class=\"chat-main\">\n <div class=\"chat-page-header\">\n <div class=\"chat-page-header-left\">\n <button class=\"toggle-sidebar-button\" title=\"Toggle sidebar\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M3 12h18M3 6h18M3 18h18\"></path>\n </svg>\n </button>\n <div class=\"chat-page-header-title\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\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\"></path>\n </svg>\n <span>Chat</span>\n </div>\n </div>\n <div class=\"chat-page-header-actions\">\n <button class=\"header-button clear-button\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M3 6h18M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2\"></path>\n </svg>\n Clear Chat\n </button>\n </div>\n </div>\n <div class=\"chat-page-content\">\n <div class=\"container\"></div>\n </div>\n </div>\n `;\n }\n\n private attachEventListeners(): void {\n const clearButton = this.shadow.querySelector('.clear-button');\n const newChatButton = this.shadow.querySelector('.new-chat-button');\n const toggleSidebarButton = this.shadow.querySelector('.toggle-sidebar-button');\n const chatList = this.shadow.querySelector('.chat-list');\n\n this.handleClearClick = () => this.clearCurrentChat();\n this.handleNewChatClick = () => this.createNewChat();\n this.handleToggleSidebarClick = () => this.toggleSidebar();\n this.handleChatListClick = (e: Event) => this.onChatListClick(e);\n\n clearButton?.addEventListener('click', this.handleClearClick);\n newChatButton?.addEventListener('click', this.handleNewChatClick);\n toggleSidebarButton?.addEventListener('click', this.handleToggleSidebarClick);\n chatList?.addEventListener('click', this.handleChatListClick);\n }\n\n private removeEventListeners(): void {\n const clearButton = this.shadow.querySelector('.clear-button');\n const newChatButton = this.shadow.querySelector('.new-chat-button');\n const toggleSidebarButton = this.shadow.querySelector('.toggle-sidebar-button');\n const chatList = this.shadow.querySelector('.chat-list');\n const chatContent = this.shadow.querySelector('.container') as HTMLElement;\n\n if (this.handleClearClick) {\n clearButton?.removeEventListener('click', this.handleClearClick);\n }\n if (this.handleNewChatClick) {\n newChatButton?.removeEventListener('click', this.handleNewChatClick);\n }\n if (this.handleToggleSidebarClick) {\n toggleSidebarButton?.removeEventListener('click', this.handleToggleSidebarClick);\n }\n if (this.handleChatListClick) {\n chatList?.removeEventListener('click', this.handleChatListClick);\n }\n if (this.handleMessageEvent && chatContent) {\n chatContent.removeEventListener('message', this.handleMessageEvent);\n }\n\n // Clear handler references\n this.handleClearClick = null;\n this.handleNewChatClick = null;\n this.handleToggleSidebarClick = null;\n this.handleChatListClick = null;\n this.handleMessageEvent = null;\n }\n\n private setupView(): void {\n if (!this.client) return;\n\n const chatContent = this.shadow.querySelector('.container') as HTMLElement;\n if (!chatContent) return;\n\n const props = this.getProps();\n this.chatView = new ChatView(chatContent, this.client, props);\n\n // Load current session or create new one\n if (this.sessions.length === 0) {\n this.createNewChat();\n } else {\n // Load the most recent session\n const lastSession = this.sessions[0];\n this.switchToSession(lastSession.id);\n }\n\n // Listen for new messages to save session\n this.handleMessageEvent = () => {\n this.saveCurrentSession();\n this.updateSessionTitle();\n this.renderChatList();\n };\n chatContent.addEventListener('message', this.handleMessageEvent);\n\n this.renderChatList();\n }\n\n private generateSessionId(): string {\n return `session_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;\n }\n\n private loadSessions(): void {\n try {\n const stored = localStorage.getItem(STORAGE_KEY);\n if (stored) {\n this.sessions = JSON.parse(stored);\n // Sort by updatedAt descending\n this.sessions.sort((a, b) => b.updatedAt - a.updatedAt);\n }\n } catch (error) {\n console.error('Failed to load chat sessions:', error);\n }\n }\n\n private saveSessions(): void {\n try {\n localStorage.setItem(STORAGE_KEY, JSON.stringify(this.sessions));\n } catch (error) {\n console.error('Failed to save chat sessions:', error);\n }\n }\n\n private saveCurrentSession(): void {\n if (!this.currentSessionId || !this.chatView) return;\n\n const sessionIndex = this.sessions.findIndex((s) => s.id === this.currentSessionId);\n if (sessionIndex !== -1) {\n this.sessions[sessionIndex].messages = this.chatView.getMessages();\n this.sessions[sessionIndex].updatedAt = Date.now();\n this.saveSessions();\n }\n }\n\n private updateSessionTitle(): void {\n if (!this.currentSessionId) return;\n\n const session = this.sessions.find((s) => s.id === this.currentSessionId);\n if (session && session.messages.length > 0 && session.title === 'New Chat') {\n const firstUserMessage = session.messages.find((m) => m.role === 'user');\n if (firstUserMessage) {\n session.title =\n firstUserMessage.content.slice(0, 50) +\n (firstUserMessage.content.length > 50 ? '...' : '');\n this.saveSessions();\n }\n }\n }\n\n private createNewChat(): void {\n // Save current session first\n this.saveCurrentSession();\n\n const newSession: ChatSession = {\n id: this.generateSessionId(),\n title: 'New Chat',\n messages: [],\n createdAt: Date.now(),\n updatedAt: Date.now(),\n };\n\n this.sessions.unshift(newSession);\n this.currentSessionId = newSession.id;\n this.saveSessions();\n\n // Clear the chat view\n this.chatView?.clearMessages();\n this.renderChatList();\n }\n\n private switchToSession(sessionId: string): void {\n if (sessionId === this.currentSessionId) return;\n\n // Save current session first\n this.saveCurrentSession();\n\n const session = this.sessions.find((s) => s.id === sessionId);\n if (session && this.chatView) {\n this.currentSessionId = sessionId;\n this.chatView.setMessages(session.messages);\n this.renderChatList();\n }\n }\n\n private deleteSession(sessionId: string): void {\n const sessionIndex = this.sessions.findIndex((s) => s.id === sessionId);\n if (sessionIndex === -1) return;\n\n this.sessions.splice(sessionIndex, 1);\n this.saveSessions();\n\n // If we deleted the current session, switch to another or create new\n if (sessionId === this.currentSessionId) {\n if (this.sessions.length > 0) {\n this.switchToSession(this.sessions[0].id);\n } else {\n this.createNewChat();\n }\n }\n\n this.renderChatList();\n }\n\n private clearCurrentChat(): void {\n if (!this.currentSessionId) return;\n\n const session = this.sessions.find((s) => s.id === this.currentSessionId);\n if (session) {\n session.messages = [];\n session.title = 'New Chat';\n session.updatedAt = Date.now();\n this.saveSessions();\n }\n\n this.chatView?.clearMessages();\n this.renderChatList();\n }\n\n private toggleSidebar(): void {\n this.sidebarCollapsed = !this.sidebarCollapsed;\n const sidebar = this.shadow.querySelector('.chat-sidebar');\n sidebar?.classList.toggle('collapsed', this.sidebarCollapsed);\n }\n\n private onChatListClick(e: Event): void {\n const target = e.target as HTMLElement;\n\n // Handle delete button click\n const deleteButton = target.closest('.chat-list-item-delete');\n if (deleteButton) {\n e.stopPropagation();\n const sessionId = deleteButton.getAttribute('data-session-id');\n if (sessionId) {\n this.deleteSession(sessionId);\n }\n return;\n }\n\n // Handle chat item click\n const chatItem = target.closest('.chat-list-item');\n if (chatItem) {\n const sessionId = chatItem.getAttribute('data-session-id');\n if (sessionId) {\n this.switchToSession(sessionId);\n }\n }\n }\n\n private renderChatList(): void {\n const chatList = this.shadow.querySelector('.chat-list');\n if (!chatList) return;\n\n if (this.sessions.length === 0) {\n chatList.innerHTML = '<div class=\"chat-list-empty\">No chats yet</div>';\n return;\n }\n\n chatList.innerHTML = this.sessions.map((session) => this.renderChatListItem(session)).join('');\n }\n\n private renderChatListItem(session: ChatSession): string {\n const isActive = session.id === this.currentSessionId;\n const date = this.formatDate(session.updatedAt);\n\n return `\n <div class=\"chat-list-item ${isActive ? 'active' : ''}\" data-session-id=\"${session.id}\">\n <div class=\"chat-list-item-content\">\n <div class=\"chat-list-item-title\">${this.escapeHTML(session.title)}</div>\n <div class=\"chat-list-item-date\">${date}</div>\n </div>\n <button class=\"chat-list-item-delete\" data-session-id=\"${session.id}\" title=\"Delete chat\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M3 6h18M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2\"></path>\n </svg>\n </button>\n </div>\n `;\n }\n\n private formatDate(timestamp: number): string {\n const date = new Date(timestamp);\n const now = new Date();\n const diffMs = now.getTime() - date.getTime();\n const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24));\n\n if (diffDays === 0) {\n return date.toLocaleTimeString(undefined, { hour: '2-digit', minute: '2-digit' });\n } else if (diffDays === 1) {\n return 'Yesterday';\n } else if (diffDays < 7) {\n return date.toLocaleDateString(undefined, { weekday: 'long' });\n } else {\n return date.toLocaleDateString(undefined, { month: 'short', day: 'numeric' });\n }\n }\n\n private escapeHTML(str: string): string {\n const div = document.createElement('div');\n div.textContent = str;\n return div.innerHTML;\n }\n\n private updateTheme(theme: string | null): void {\n // CSS :host([theme]) selectors handle theming automatically\n // For 'auto' mode, remove the attribute to let @media (prefers-color-scheme) work\n const validTheme = theme === 'light' || theme === 'dark' ? theme : null;\n\n if (\n validTheme === null &&\n this.hasAttribute('theme') &&\n this.getAttribute('theme') !== 'auto'\n ) {\n this.removeAttribute('theme');\n }\n }\n\n private cleanup(): void {\n this.removeEventListeners();\n\n if (this.client) {\n this.client.cancelAllRequests();\n }\n\n if (this.chatView) {\n this.chatView.destroy();\n }\n }\n\n // Public API\n public clearChat(): void {\n this.clearCurrentChat();\n }\n\n public async sendMessage(content: string): Promise<void> {\n if (this.chatView) {\n await this.chatView.sendMessage(content);\n this.saveCurrentSession();\n }\n }\n\n public getMessages(): Message[] {\n return this.chatView?.getMessages() || [];\n }\n\n public getSessions(): ChatSession[] {\n return [...this.sessions];\n }\n\n public getCurrentSession(): ChatSession | null {\n return this.sessions.find((s) => s.id === this.currentSessionId) || null;\n }\n}\n\n// Register the custom element\nif (!customElements.get(COMPONENT_NAME)) {\n customElements.define(COMPONENT_NAME, ChatPageSnippet);\n}\n","/**\n * Search mode specific styles\n */\n\nexport const searchStyles = `\n/* Search view states */\n.search-view {\n transition: var(--search-snippet-transition-slow);\n background: var(--search-snippet-background);\n border-radius: var(--search-snippet-border-radius);\n padding: 0px;\n}\n\n.search-view-collapsed {\n max-height: 60px;\n}\n\n.search-view-expanded {\n max-height: var(--search-snippet-max-height);\n}\n\n\n.search-icon {\n width: var(--search-snippet-icon-size);\n height: var(--search-snippet-icon-size);\n margin-left: var(--search-snippet-icon-margin-left);\n color: var(--search-snippet-text-color);\n}\n\n/* Search input wrapper */\n.search-input-wrapper {\n display: grid;\n grid-template-columns: auto 1fr auto;\n align-items: center;\n gap: var(--search-snippet-spacing-sm);\n overflow: hidden;\n transition: max-width var(--search-snippet-transition-slow), \n opacity var(--search-snippet-transition);\n padding: var(--search-snippet-spacing-sm);\n border-radius: var(--search-snippet-border-radius);\n border: var(--search-snippet-border-width) solid var(--search-snippet-border-color);\n}\n\n\n\n.search-input {\n flex: 1;\n border: none;\n outline: none;\n background: transparent;\n color: var(--search-snippet-text-color);\n font-size: var(--search-snippet-font-size-base);\n font-weight: var(--search-snippet-font-weight-medium);\n box-shadow: none;\n padding: 0;\n}\n\n.search-input::placeholder {\n color: var(--search-snippet-text-secondary);\n}\n\n.search-view:has(.search-input:not(:placeholder-shown)) .search-input-wrapper, .search-view:has(.search-input:not(:placeholder-shown)) {\n border-bottom-left-radius: 0;\n border-bottom-right-radius: 0;\n}\n\n.search-view:focus-within {\n border-color: var(--search-snippet-primary-color);\n box-shadow: inset 0 0 0 3px var(--search-snippet-focus-ring);\n}\n\n.search-view:has(.search-input:not(:placeholder-shown)) .search-content {\n max-height: 600px;\n opacity: 1;\n overflow-y: auto;\n padding: 8px;\n}\n\n.search-submit-button {\n flex-shrink: 0;\n \n border-radius: max(var(--search-snippet-button-min-border-radius, 4px), calc(var(--search-snippet-border-radius) - var(--search-snippet-spacing-sm)))\n}\n\n/* Search content */\n.search-content {\n max-height: 0;\n opacity: 0;\n transition: max-height var(--search-snippet-transition-slow),\n opacity var(--search-snippet-transition);\n position: absolute;\n width: 100%;\n background: var(--search-snippet-background);\n border-bottom-left-radius: var(--search-snippet-border-radius);\n border-bottom-right-radius: var(--search-snippet-border-radius);\n border: var(--search-snippet-border-width) solid var(--search-snippet-border-color);\n border-top: none;\n}\n\n.search-content::-webkit-scrollbar {\n width: 8px;\n height: 100px;\n}\n\n.search-content::-webkit-scrollbar-track {\n background: var(--search-snippet-surface);\n \n}\n\n.search-content::-webkit-scrollbar-thumb {\n background: var(--search-snippet-border-color);\n border-radius: var(--search-snippet-border-radius);\n}\n\n.search-content::-webkit-scrollbar-thumb:hover {\n background: var(--search-snippet-text-secondary);\n}\n\n.container {\n overflow: unset;\n position: relative;\n border: none;\n}\n\n.container:has(.search-input:not(:placeholder-shown)) {\n border-bottom-left-radius: 0;\n border-bottom-right-radius: 0;\n}\n\n\n/* Override header for search mode */\n\n/* Search results */\n.search-results {\n display: flex;\n flex-direction: column;\n gap: var(--search-snippet-spacing-sm);\n}\n\n.search-result-item {\n display: flex;\n flex-direction: row;\n align-items: flex-start;\n gap: var(--search-snippet-spacing-md);\n padding: var(--search-snippet-spacing-md);\n background: var(--search-snippet-surface);\n border: var(--search-snippet-border-width) solid var(--search-snippet-border-color);\n border-radius: var(--search-snippet-border-radius);\n cursor: pointer;\n transition: var(--search-snippet-transition);\n}\n\n/* Image thumbnail container */\n.search-result-image-container {\n flex-shrink: 0;\n width: 64px;\n height: 64px;\n border-radius: calc(var(--search-snippet-border-radius) - 4px);\n overflow: hidden;\n background: var(--search-snippet-surface);\n border: var(--search-snippet-border-width) solid var(--search-snippet-border-color);\n position: relative;\n}\n\n.search-result-image {\n width: 100%;\n height: 100%;\n object-fit: cover;\n opacity: 0;\n transition: opacity var(--search-snippet-transition);\n}\n\n.search-result-image.loaded {\n opacity: 1;\n}\n\n/* Loading shimmer */\n.search-result-image-loading {\n position: absolute;\n inset: 0;\n background: linear-gradient(\n 90deg,\n var(--search-snippet-surface) 25%,\n var(--search-snippet-border-color) 50%,\n var(--search-snippet-surface) 75%\n );\n background-size: 200% 100%;\n animation: search-image-shimmer 1.5s infinite;\n}\n\n@keyframes search-image-shimmer {\n 0% { background-position: 200% 0; }\n 100% { background-position: -200% 0; }\n}\n\n/* Placeholder icon */\n.search-result-image-placeholder {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--search-snippet-text-secondary);\n opacity: 0.5;\n}\n\n.search-result-image-placeholder svg {\n width: 24px;\n height: 24px;\n}\n\n/* Content wrapper */\n.search-result-content {\n flex: 1;\n min-width: 0;\n}\n\n.search-result-item:hover {\n background: var(--search-snippet-hover-background);\n border-color: var(--search-snippet-primary-color);\n transform: translateY(-1px);\n box-shadow: var(--search-snippet-result-item-shadow);\n}\n\n.search-result-item:focus-visible {\n outline: 2px solid var(--search-snippet-primary-color);\n outline-offset: 2px;\n}\n\n.search-result-title {\n font-size: var(--search-snippet-font-size-base);\n font-weight: var(--search-snippet-font-weight-medium);\n color: var(--search-snippet-text-color);\n margin-bottom: var(--search-snippet-spacing-xs);\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n\n.search-result-snippet {\n font-size: var(--search-snippet-font-size-sm);\n color: var(--search-snippet-text-secondary);\n line-height: 1.6;\n display: -webkit-box;\n -webkit-line-clamp: 3;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n\n.search-result-url {\n font-size: var(--search-snippet-font-size-sm);\n color: var(--search-snippet-primary-color);\n margin-top: var(--search-snippet-spacing-xs);\n text-decoration: none;\n display: inline-block;\n}\n\n.search-result-url:hover {\n text-decoration: underline;\n}\n\n/* Search header */\n.search-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: var(--search-snippet-spacing-md);\n padding-bottom: var(--search-snippet-spacing-sm);\n border-bottom: var(--search-snippet-border-width) solid var(--search-snippet-border-color);\n}\n\n.search-count {\n font-size: var(--search-snippet-font-size-sm);\n color: var(--search-snippet-text-secondary);\n}\n\n/* Search footer */\n.search-footer {\n padding: var(--search-snippet-spacing-md);\n border-top: var(--search-snippet-border-width) solid var(--search-snippet-border-color);\n display: flex;\n align-items: center;\n justify-content: center;\n gap: var(--search-snippet-spacing-sm);\n}\n\n/* Loading state for search */\n.search-loading {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: var(--search-snippet-spacing-xxl);\n gap: var(--search-snippet-spacing-md);\n color: var(--search-snippet-text-secondary);\n}\n\n/* Empty search state */\n.search-empty {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: var(--search-snippet-spacing-xxl);\n gap: var(--search-snippet-spacing-md);\n color: var(--search-snippet-text-secondary);\n text-align: center;\n}\n\n.search-empty-icon {\n width: 64px;\n height: 64px;\n opacity: 0.5;\n}\n\n.search-empty-title {\n font-size: var(--search-snippet-font-size-lg);\n font-weight: var(--search-snippet-font-weight-medium);\n color: var(--search-snippet-text-color);\n}\n\n.search-empty-description {\n font-size: var(--search-snippet-font-size-sm);\n}\n\n/* Highlight matching text */\n.search-highlight {\n background: var(--search-snippet-warning-background);\n color: var(--search-snippet-warning-color);\n padding: 1px 2px;\n border-radius: 2px;\n font-weight: var(--search-snippet-font-weight-medium);\n}\n`;\n","/**\n * Search Bar Snippet\n * A search bar with results display\n */\n\nimport type { Client } from '../api/index.ts';\nimport { searchStyles } from '../styles/search.ts';\nimport { baseStyles } from '../styles/theme.ts';\nimport type { SearchResult, SearchSnippetProps } from '../types/index.ts';\nimport {\n createClient,\n createCustomEvent,\n debounce,\n escapeHTML,\n parseAttribute,\n parseBooleanAttribute,\n parseNumberAttribute,\n} from '../utils/index.ts';\nimport { POWERED_BY_BRANDING } from '../constants.ts';\n\nconst COMPONENT_NAME = 'search-bar-snippet';\n\nexport class SearchBarSnippet extends HTMLElement {\n private shadow: ShadowRoot;\n private client: Client | null = null;\n private container: HTMLElement | null = null;\n private inputElement: HTMLInputElement | null = null;\n private resultsContainer: HTMLElement | null = null;\n private searchButton: HTMLButtonElement | null = null;\n private isLoading = false;\n private currentQuery = '';\n private debouncedSearch: ((query: string) => void) | null = null;\n\n // Event handler references for cleanup\n private handleInputChange: ((e: Event) => void) | null = null;\n private handleInputKeydownEnter: ((e: KeyboardEvent) => void) | null = null;\n private handleInputKeydownEscape: ((e: KeyboardEvent) => void) | null = null;\n private handleSearchButtonClick: (() => void) | null = null;\n\n static get observedAttributes() {\n return [\n 'api-url',\n 'placeholder',\n 'max-results',\n 'debounce-ms',\n 'theme',\n 'hide-branding',\n ] as const;\n }\n\n constructor() {\n super();\n this.shadow = this.attachShadow({ mode: 'open' });\n }\n\n connectedCallback(): void {\n this.initializeClient();\n this.render();\n this.dispatchEvent(createCustomEvent('ready', undefined));\n }\n\n disconnectedCallback(): void {\n this.cleanup();\n }\n\n attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void {\n if (oldValue === newValue) return;\n\n if (name === 'api-url') {\n this.initializeClient();\n } else if (name === 'theme') {\n // Theme changes are handled automatically by CSS :host([theme]) selectors\n // But we trigger this to ensure any dynamic updates are applied\n this.updateTheme(newValue);\n }\n }\n\n private getProps(): SearchSnippetProps {\n return {\n apiUrl: parseAttribute(this.getAttribute('api-url'), 'http://localhost:3000'),\n placeholder: parseAttribute(this.getAttribute('placeholder'), 'Search...'),\n maxResults: parseNumberAttribute(this.getAttribute('max-results'), 10),\n debounceMs: parseNumberAttribute(this.getAttribute('debounce-ms'), 300),\n theme: parseAttribute(this.getAttribute('theme'), 'auto') as 'light' | 'dark' | 'auto',\n hideBranding: parseBooleanAttribute(this.getAttribute('hide-branding'), false),\n };\n }\n\n private initializeClient(): void {\n const props = this.getProps();\n\n if (!props.apiUrl) {\n console.error('SearchBarSnippet: api-url attribute is required');\n return;\n }\n\n try {\n this.client = createClient(props.apiUrl);\n } catch (error) {\n console.error('SearchBarSnippet:', error);\n }\n }\n\n private render(): void {\n const props = this.getProps();\n\n // Create debounced search function\n const searchFn = (query: string) => this.performSearch(query);\n this.debouncedSearch = debounce(\n searchFn as (...args: unknown[]) => unknown,\n props.debounceMs || 400\n ) as (query: string) => void;\n\n const style = document.createElement('style');\n style.textContent = `${baseStyles}\\n${searchStyles}`;\n\n this.container = document.createElement('div');\n this.container.className = 'container';\n this.container.innerHTML = `\n <div class=\"search-view\"> \n <div class=\"search-input-wrapper\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" class=\"search-icon\" height=\"24px\" viewBox=\"0 -960 960 960\" width=\"24px\" fill=\"currentColor\"><path d=\"M784-120 532-372q-30 24-69 38t-83 14q-109 0-184.5-75.5T120-580q0-109 75.5-184.5T380-840q109 0 184.5 75.5T640-580q0 44-14 83t-38 69l252 252-56 56ZM380-400q75 0 127.5-52.5T560-580q0-75-52.5-127.5T380-760q-75 0-127.5 52.5T200-580q0 75 52.5 127.5T380-400Z\"/></svg>\n <input\n type=\"text\"\n name=\"search-input\"\n class=\"search-input\"\n placeholder=\"${escapeHTML(props.placeholder || 'Search...')}\"\n aria-label=\"Search input\"\n autocomplete=\"off\"\n />\n <button class=\"button search-submit-button\" aria-label=\"Search\">\n <span>Search</span>\n </button>\n </div>\n <div class=\"search-content\">\n <div class=\"search-results-wrapper\">\n <!-- Results will be inserted here -->\n </div>\n </div>\n </div>\n `;\n\n this.shadow.innerHTML = '';\n this.shadow.appendChild(style);\n this.shadow.appendChild(this.container);\n\n // Get references to elements\n this.inputElement = this.container.querySelector('.search-input');\n this.resultsContainer = this.container.querySelector('.search-results-wrapper');\n this.searchButton = this.container.querySelector('.search-submit-button');\n\n this.attachEventListeners();\n }\n\n private attachEventListeners(): void {\n if (!this.inputElement) return;\n\n // Input event for real-time search\n this.handleInputChange = (e: Event) => {\n const target = e.target as HTMLInputElement;\n const query = target.value.trim();\n\n if (query.length > 0 && this.debouncedSearch) {\n this.debouncedSearch(query);\n } else {\n this.showEmptyState();\n }\n };\n this.inputElement.addEventListener('input', this.handleInputChange);\n\n // Enter key to search immediately\n this.handleInputKeydownEnter = (e: KeyboardEvent) => {\n if (e.key === 'Enter') {\n const query = (e.target as HTMLInputElement).value.trim();\n if (query.length > 0) {\n this.performSearch(query);\n }\n }\n };\n this.inputElement.addEventListener('keydown', this.handleInputKeydownEnter);\n\n this.handleInputKeydownEscape = (e: KeyboardEvent) => {\n if (e.key === 'Escape' && this.inputElement) {\n this.inputElement.value = '';\n }\n };\n window.addEventListener('keydown', this.handleInputKeydownEscape);\n\n // Search button click\n if (this.searchButton) {\n this.handleSearchButtonClick = () => {\n const query = this.inputElement?.value.trim() || '';\n if (query.length > 0) {\n this.performSearch(query);\n }\n };\n this.searchButton.addEventListener('click', this.handleSearchButtonClick);\n }\n }\n\n private async performSearch(query: string): Promise<void> {\n if (this.isLoading || query === this.currentQuery || !this.client) return;\n\n this.currentQuery = query;\n this.isLoading = true;\n this.showLoadingState();\n\n try {\n const results = await this.client.search(query, { streaming: false });\n this.displayResults(results, query);\n } catch (error) {\n this.showErrorState((error as Error).message);\n } finally {\n this.isLoading = false;\n }\n }\n\n private displayResults(results: SearchResult[], query: string): void {\n if (!this.resultsContainer) return;\n\n if (results.length === 0) {\n this.showNoResultsState(query);\n return;\n }\n const props = this.getProps();\n const brandingHTML = props.hideBranding\n ? ''\n : `<div class=\"powered-by-inline\">${POWERED_BY_BRANDING}</div>`;\n\n const resultsHTML = `\n <div class=\"search-header\">\n <div class=\"search-count\">\n Found ${results.length} result${results.length === 1 ? '' : 's'}\n </div>\n ${brandingHTML}\n </div>\n <div class=\"search-results\">\n ${results.map((result) => this.renderResult(result)).join('')}\n </div>\n `;\n\n this.resultsContainer.innerHTML = resultsHTML;\n\n // Attach click handlers to results\n this.attachResultHandlers();\n }\n\n private renderResult(result: SearchResult): string {\n const imageHTML = this.renderResultImage(result.image, result.title);\n\n return `\n <div class=\"search-result-item\" role=\"button\" tabindex=\"0\" data-result-id=\"${escapeHTML(result.url || '')}\">\n ${imageHTML}\n <div class=\"search-result-content\">\n <div class=\"search-result-title\">${escapeHTML(result.title || '')}</div>\n <div class=\"search-result-snippet\">${escapeHTML(result.description || '')}</div>\n ${result.url ? `<a href=\"${escapeHTML(result.url)}\" class=\"search-result-url\">${escapeHTML(result.url)}</a>` : ''}\n </div>\n </div>\n `;\n }\n\n private renderResultImage(imageUrl: string | undefined, alt: string): string {\n const placeholderSVG = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\"><path d=\"M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z\"/><polyline points=\"14 2 14 8 20 8\"/><line x1=\"16\" y1=\"13\" x2=\"8\" y2=\"13\"/><line x1=\"16\" y1=\"17\" x2=\"8\" y2=\"17\"/><polyline points=\"10 9 9 9 8 9\"/></svg>`;\n\n if (!imageUrl) {\n return `\n <div class=\"search-result-image-container\">\n <div class=\"search-result-image-placeholder\">${placeholderSVG}</div>\n </div>\n `;\n }\n\n return `\n <div class=\"search-result-image-container\">\n <div class=\"search-result-image-loading\"></div>\n <div class=\"search-result-image-placeholder\" style=\"display: none;\">${placeholderSVG}</div>\n <img \n class=\"search-result-image\" \n src=\"${escapeHTML(imageUrl)}\" \n alt=\"${escapeHTML(alt)}\"\n loading=\"lazy\"\n />\n </div>\n `;\n }\n\n private attachResultHandlers(): void {\n const resultItems = this.container?.querySelectorAll('.search-result-item');\n if (!resultItems) return;\n\n for (const item of resultItems) {\n item.addEventListener('click', () => {\n const resultId = item.getAttribute('data-result-id');\n console.log('Result clicked:', resultId);\n });\n\n // Keyboard accessibility\n item.addEventListener('keydown', (e) => {\n if ((e as KeyboardEvent).key === 'Enter' || (e as KeyboardEvent).key === ' ') {\n (item as HTMLElement).click();\n }\n });\n }\n\n // Image load/error handlers\n const images = this.container?.querySelectorAll('.search-result-image');\n images?.forEach((img) => {\n img.addEventListener('load', () => {\n img.classList.add('loaded');\n const container = img.closest('.search-result-image-container');\n container?.querySelector('.search-result-image-loading')?.remove();\n });\n\n img.addEventListener('error', () => {\n const container = img.closest('.search-result-image-container');\n container?.querySelector('.search-result-image-loading')?.remove();\n const placeholder = container?.querySelector(\n '.search-result-image-placeholder'\n ) as HTMLElement;\n if (placeholder) placeholder.style.display = 'flex';\n (img as HTMLElement).style.display = 'none';\n });\n });\n }\n\n private showLoadingState(): void {\n if (!this.resultsContainer) return;\n\n this.resultsContainer.innerHTML = `\n <div class=\"search-loading\">\n <div class=\"loading\" aria-label=\"Loading\"></div>\n <div>Searching...</div>\n </div>\n `;\n }\n\n private showEmptyState(): void {\n if (!this.resultsContainer) return;\n\n this.resultsContainer.innerHTML = `\n <div class=\"search-empty\">\n <svg class=\"search-empty-icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <circle cx=\"11\" cy=\"11\" r=\"8\"></circle>\n <path d=\"m21 21-4.35-4.35\"></path>\n </svg>\n <div class=\"search-empty-title\">Start Searching</div>\n <div class=\"search-empty-description\">\n Enter a query to search for results\n </div>\n </div>\n `;\n }\n\n private showNoResultsState(query: string): void {\n if (!this.resultsContainer) return;\n\n this.resultsContainer.innerHTML = `\n <div class=\"search-empty\">\n <svg class=\"search-empty-icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <circle cx=\"11\" cy=\"11\" r=\"8\"></circle>\n <line x1=\"21\" y1=\"21\" x2=\"16.65\" y2=\"16.65\"></line>\n </svg>\n <div class=\"search-empty-title\">No Results Found</div>\n <div class=\"search-empty-description\">\n No results found for \"${escapeHTML(query)}\"\n </div>\n </div>\n `;\n }\n\n private showErrorState(message: string): void {\n if (!this.resultsContainer) return;\n\n this.resultsContainer.innerHTML = `\n <div class=\"error\">\n <strong>Error:</strong> ${escapeHTML(message)}\n </div>\n `;\n }\n\n private updateTheme(theme: string | null): void {\n // CSS custom properties via :host([theme]) selectors handle the actual theming\n // This method is here for any additional theme-related logic if needed\n const validTheme = theme === 'light' || theme === 'dark' || theme === 'auto' ? theme : 'auto';\n\n // Ensure the attribute is set on the host for CSS selectors\n if (validTheme === 'auto') {\n // Let the @media (prefers-color-scheme) handle it\n this.removeAttribute('theme');\n } else {\n this.setAttribute('theme', validTheme);\n }\n }\n\n private cleanup(): void {\n if (this.client) {\n this.client.cancelAllRequests();\n }\n\n // Remove event listeners\n if (this.inputElement) {\n if (this.handleInputChange) {\n this.inputElement.removeEventListener('input', this.handleInputChange);\n }\n if (this.handleInputKeydownEnter) {\n this.inputElement.removeEventListener('keydown', this.handleInputKeydownEnter);\n }\n if (this.handleInputKeydownEscape) {\n window.removeEventListener('keydown', this.handleInputKeydownEscape);\n }\n }\n\n if (this.searchButton && this.handleSearchButtonClick) {\n this.searchButton.removeEventListener('click', this.handleSearchButtonClick);\n }\n\n // Clear handler references\n this.handleInputChange = null;\n this.handleInputKeydownEnter = null;\n this.handleInputKeydownEscape = null;\n this.handleSearchButtonClick = null;\n }\n\n // Public API\n public async search(query: string): Promise<void> {\n await this.performSearch(query);\n }\n}\n\n// Register the custom element\nif (!customElements.get(COMPONENT_NAME)) {\n customElements.define(COMPONENT_NAME, SearchBarSnippet);\n}\n","/**\n * Modal search combobox specific styles\n */\n\nexport const modalStyles = `\n/* Modal backdrop */\n.modal-backdrop {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.5);\n backdrop-filter: blur(4px);\n z-index: var(--search-snippet-z-modal);\n opacity: 0;\n visibility: hidden;\n transition: opacity var(--search-snippet-transition), visibility var(--search-snippet-transition);\n}\n\n.modal-backdrop.open {\n opacity: 1;\n visibility: visible;\n}\n\n/* Modal container */\n.modal-container {\n position: fixed;\n top: 15%;\n left: 50%;\n transform: translateX(-50%) scale(0.95);\n width: 90%;\n max-width: 600px;\n max-height: 70vh;\n background: var(--search-snippet-background);\n border: var(--search-snippet-border-width) solid var(--search-snippet-border-color);\n border-radius: var(--search-snippet-border-radius);\n box-shadow: var(--search-snippet-shadow-lg);\n z-index: calc(var(--search-snippet-z-modal) + 1);\n display: flex;\n flex-direction: column;\n opacity: 0;\n visibility: hidden;\n transition: opacity var(--search-snippet-transition), \n visibility var(--search-snippet-transition),\n transform var(--search-snippet-transition);\n}\n\n.modal-container.open {\n opacity: 1;\n visibility: visible;\n transform: translateX(-50%) scale(1);\n}\n\n/* Modal header with search input */\n.modal-header {\n display: flex;\n align-items: center;\n gap: var(--search-snippet-spacing-sm);\n padding: var(--search-snippet-spacing-md);\n border-bottom: var(--search-snippet-border-width) solid var(--search-snippet-border-color);\n}\n\n.modal-search-icon {\n width: var(--search-snippet-icon-size);\n height: var(--search-snippet-icon-size);\n color: var(--search-snippet-text-secondary);\n flex-shrink: 0;\n}\n\n.modal-search-input {\n flex: 1;\n border: none;\n outline: none;\n background: transparent;\n color: var(--search-snippet-text-color);\n font-size: var(--search-snippet-font-size-lg);\n font-family: var(--search-snippet-font-family);\n font-weight: var(--search-snippet-font-weight-normal);\n padding: var(--search-snippet-spacing-xs) 0;\n}\n\n.modal-search-input::placeholder {\n color: var(--search-snippet-text-secondary);\n}\n\n.modal-shortcut-hint {\n display: flex;\n align-items: center;\n gap: var(--search-snippet-spacing-xs);\n color: var(--search-snippet-text-secondary);\n font-size: var(--search-snippet-font-size-sm);\n flex-shrink: 0;\n}\n\n.modal-kbd {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 24px;\n height: 22px;\n padding: 0 var(--search-snippet-spacing-xs);\n background: var(--search-snippet-surface);\n border: var(--search-snippet-border-width) solid var(--search-snippet-border-color);\n border-radius: 4px;\n font-size: var(--search-snippet-font-size-sm);\n font-family: var(--search-snippet-font-family);\n color: var(--search-snippet-text-secondary);\n}\n\n/* Modal content (results area) */\n.modal-content {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n padding: var(--search-snippet-spacing-sm);\n}\n\n.modal-content::-webkit-scrollbar {\n width: 8px;\n}\n\n.modal-content::-webkit-scrollbar-track {\n background: var(--search-snippet-surface);\n}\n\n.modal-content::-webkit-scrollbar-thumb {\n background: var(--search-snippet-border-color);\n border-radius: var(--search-snippet-border-radius);\n}\n\n.modal-content::-webkit-scrollbar-thumb:hover {\n background: var(--search-snippet-text-secondary);\n}\n\n/* Results list */\n.modal-results {\n display: flex;\n flex-direction: column;\n gap: var(--search-snippet-spacing-xs);\n}\n\n.modal-result-item {\n padding: var(--search-snippet-spacing-md);\n background: transparent;\n border: var(--search-snippet-border-width) solid transparent;\n border-radius: calc(var(--search-snippet-border-radius) - 4px);\n cursor: pointer;\n transition: var(--search-snippet-transition-fast);\n display: flex;\n flex-direction: row;\n align-items: flex-start;\n gap: var(--search-snippet-spacing-md);\n}\n\n/* Image thumbnail container */\n.modal-result-image-container {\n flex-shrink: 0;\n width: 48px;\n height: 48px;\n border-radius: 6px;\n overflow: hidden;\n background: var(--search-snippet-surface);\n border: var(--search-snippet-border-width) solid var(--search-snippet-border-color);\n position: relative;\n}\n\n.modal-result-image {\n width: 100%;\n height: 100%;\n object-fit: cover;\n opacity: 0;\n transition: opacity var(--search-snippet-transition);\n}\n\n.modal-result-image.loaded {\n opacity: 1;\n}\n\n/* Loading shimmer */\n.modal-result-image-loading {\n position: absolute;\n inset: 0;\n background: linear-gradient(\n 90deg,\n var(--search-snippet-surface) 25%,\n var(--search-snippet-border-color) 50%,\n var(--search-snippet-surface) 75%\n );\n background-size: 200% 100%;\n animation: modal-image-shimmer 1.5s infinite;\n}\n\n@keyframes modal-image-shimmer {\n 0% { background-position: 200% 0; }\n 100% { background-position: -200% 0; }\n}\n\n/* Placeholder icon */\n.modal-result-image-placeholder {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--search-snippet-text-secondary);\n opacity: 0.5;\n}\n\n.modal-result-image-placeholder svg {\n width: 20px;\n height: 20px;\n}\n\n/* Content wrapper */\n.modal-result-content {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: var(--search-snippet-spacing-xs);\n}\n\n.modal-result-item:hover,\n.modal-result-item.active {\n background: var(--search-snippet-hover-background);\n border-color: var(--search-snippet-border-color);\n}\n\n.modal-result-item.active {\n border-color: var(--search-snippet-primary-color);\n background: var(--search-snippet-focus-ring);\n}\n\n.modal-result-item:focus-visible {\n outline: 2px solid var(--search-snippet-primary-color);\n outline-offset: -2px;\n}\n\n.modal-result-title {\n font-size: var(--search-snippet-font-size-base);\n font-weight: var(--search-snippet-font-weight-medium);\n color: var(--search-snippet-text-color);\n display: -webkit-box;\n -webkit-line-clamp: 1;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n\n.modal-result-description {\n font-size: var(--search-snippet-font-size-sm);\n color: var(--search-snippet-text-secondary);\n line-height: 1.5;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n\n.modal-result-url {\n font-size: var(--search-snippet-font-size-sm);\n color: var(--search-snippet-primary-color);\n text-decoration: none;\n display: inline-block;\n max-width: 100%;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.modal-result-url:hover {\n text-decoration: underline;\n}\n\n/* Result group header */\n.modal-group-header {\n padding: var(--search-snippet-spacing-sm) var(--search-snippet-spacing-md);\n font-size: var(--search-snippet-font-size-sm);\n font-weight: var(--search-snippet-font-weight-medium);\n color: var(--search-snippet-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.05em;\n}\n\n/* Loading state */\n.modal-loading {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: var(--search-snippet-spacing-xxl);\n gap: var(--search-snippet-spacing-md);\n color: var(--search-snippet-text-secondary);\n}\n\n/* Empty state */\n.modal-empty {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: var(--search-snippet-spacing-xxl);\n gap: var(--search-snippet-spacing-md);\n color: var(--search-snippet-text-secondary);\n text-align: center;\n}\n\n.modal-empty-icon {\n width: 48px;\n height: 48px;\n opacity: 0.5;\n}\n\n.modal-empty-title {\n font-size: var(--search-snippet-font-size-base);\n font-weight: var(--search-snippet-font-weight-medium);\n color: var(--search-snippet-text-color);\n}\n\n.modal-empty-description {\n font-size: var(--search-snippet-font-size-sm);\n}\n\n/* Footer */\n.modal-footer {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: var(--search-snippet-spacing-sm) var(--search-snippet-spacing-md);\n border-top: var(--search-snippet-border-width) solid var(--search-snippet-border-color);\n background: var(--search-snippet-surface);\n font-size: var(--search-snippet-font-size-sm);\n color: var(--search-snippet-text-secondary);\n border-radius: 0 0 var(--search-snippet-border-radius) var(--search-snippet-border-radius);\n}\n\n.modal-footer-hints {\n display: flex;\n align-items: center;\n gap: var(--search-snippet-spacing-md);\n}\n\n.modal-footer-hint {\n display: flex;\n align-items: center;\n gap: var(--search-snippet-spacing-xs);\n}\n\n.modal-footer-hint .modal-kbd {\n min-width: 20px;\n height: 20px;\n font-size: 11px;\n}\n\n/* Results count */\n.modal-results-count {\n font-size: var(--search-snippet-font-size-sm);\n color: var(--search-snippet-text-secondary);\n}\n\n/* Powered by in modal footer */\n.modal-footer .powered-by-inline {\n font-size: var(--search-snippet-font-size-sm);\n color: var(--search-snippet-text-secondary);\n}\n\n.modal-footer .powered-by-inline a {\n color: var(--search-snippet-text-secondary);\n text-decoration: none;\n transition: color var(--search-snippet-transition-fast);\n}\n\n.modal-footer .powered-by-inline a:hover {\n color: var(--search-snippet-primary-color);\n}\n\n/* Responsive adjustments */\n@media (max-width: 640px) {\n .modal-container {\n top: 10%;\n width: 95%;\n max-height: 80vh;\n }\n\n .modal-footer-hints {\n display: none;\n }\n}\n\n/* Animation for modal open */\n@keyframes modal-slide-in {\n from {\n opacity: 0;\n transform: translateX(-50%) scale(0.95) translateY(-10px);\n }\n to {\n opacity: 1;\n transform: translateX(-50%) scale(1) translateY(0);\n }\n}\n\n.modal-container.open {\n animation: modal-slide-in var(--search-snippet-transition) ease-out;\n}\n`;\n","/**\n * Search Modal Snippet\n * A modal combobox search component with keyboard navigation\n * Opens with Cmd/Ctrl+K shortcut by default\n */\n\nimport type { Client } from '../api/index.ts';\nimport { modalStyles } from '../styles/modal.ts';\nimport { baseStyles } from '../styles/theme.ts';\nimport type { SearchResult, SearchSnippetProps } from '../types/index.ts';\nimport {\n createClient,\n createCustomEvent,\n debounce,\n escapeHTML,\n parseAttribute,\n parseBooleanAttribute,\n parseNumberAttribute,\n} from '../utils/index.ts';\nimport { POWERED_BY_BRANDING } from '../constants.ts';\n\nconst COMPONENT_NAME = 'search-modal-snippet';\n\nexport interface SearchModalProps extends SearchSnippetProps {\n /** Keyboard shortcut key (default: 'k') */\n shortcut?: string;\n /** Whether to use meta key (Cmd on Mac) or ctrl key */\n useMetaKey?: boolean;\n}\n\nexport class SearchModalSnippet extends HTMLElement {\n private shadow: ShadowRoot;\n private client: Client | null = null;\n private backdrop: HTMLElement | null = null;\n private modal: HTMLElement | null = null;\n private inputElement: HTMLInputElement | null = null;\n private resultsContainer: HTMLElement | null = null;\n private footerCount: HTMLElement | null = null;\n private isOpen = false;\n private isLoading = false;\n private results: SearchResult[] = [];\n private activeIndex = -1;\n private debouncedSearch: ((query: string) => void) | null = null;\n\n // Event handler references for cleanup\n private handleGlobalKeydown: ((e: KeyboardEvent) => void) | null = null;\n private handleInputChange: ((e: Event) => void) | null = null;\n private handleInputKeydown: ((e: KeyboardEvent) => void) | null = null;\n private handleBackdropClick: ((e: MouseEvent) => void) | null = null;\n\n // Scroll lock state\n private savedBodyStyles: {\n overflow: string;\n position: string;\n top: string;\n width: string;\n } | null = null;\n private savedHtmlOverflow: string | null = null;\n\n static get observedAttributes() {\n return [\n 'api-url',\n 'placeholder',\n 'max-results',\n 'theme',\n 'shortcut',\n 'use-meta-key',\n 'debounce-ms',\n 'hide-branding',\n ] as const;\n }\n\n constructor() {\n super();\n this.shadow = this.attachShadow({ mode: 'open' });\n }\n\n connectedCallback(): void {\n this.initializeClient();\n this.render();\n this.attachGlobalKeyboardShortcut();\n this.dispatchEvent(createCustomEvent('ready', undefined));\n }\n\n disconnectedCallback(): void {\n this.cleanup();\n }\n\n attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void {\n if (oldValue === newValue) return;\n\n if (name === 'api-url') {\n this.initializeClient();\n } else if (name === 'theme') {\n this.updateTheme(newValue);\n }\n }\n\n private getProps(): SearchModalProps {\n return {\n apiUrl: parseAttribute(this.getAttribute('api-url'), 'http://localhost:3000'),\n placeholder: parseAttribute(this.getAttribute('placeholder'), 'Search...'),\n maxResults: parseNumberAttribute(this.getAttribute('max-results'), 10),\n debounceMs: parseNumberAttribute(this.getAttribute('debounce-ms'), 300),\n theme: parseAttribute(this.getAttribute('theme'), 'auto') as 'light' | 'dark' | 'auto',\n shortcut: parseAttribute(this.getAttribute('shortcut'), 'k'),\n useMetaKey: this.getAttribute('use-meta-key') !== 'false',\n hideBranding: parseBooleanAttribute(this.getAttribute('hide-branding'), false),\n };\n }\n\n private initializeClient(): void {\n const props = this.getProps();\n\n if (!props.apiUrl) {\n console.error('SearchModalSnippet: api-url attribute is required');\n return;\n }\n\n try {\n this.client = createClient(props.apiUrl);\n } catch (error) {\n console.error('SearchModalSnippet:', error);\n }\n }\n\n private render(): void {\n const props = this.getProps();\n\n // Create debounced search function\n const searchFn = (query: string) => this.performSearch(query);\n this.debouncedSearch = debounce(\n searchFn as (...args: unknown[]) => unknown,\n props.debounceMs || 300\n ) as (query: string) => void;\n\n const style = document.createElement('style');\n style.textContent = `${baseStyles}\\n${modalStyles}`;\n\n const brandingHTML = props.hideBranding\n ? ''\n : `<div class=\"powered-by-inline\">${POWERED_BY_BRANDING}</div>`;\n\n const container = document.createElement('div');\n container.innerHTML = `\n <div class=\"modal-backdrop\" role=\"presentation\"></div>\n <div class=\"modal-container\" role=\"dialog\" aria-modal=\"true\" aria-labelledby=\"modal-title\">\n <div class=\"modal-header\">\n <svg class=\"modal-search-icon\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 -960 960 960\" fill=\"currentColor\">\n <path d=\"M784-120 532-372q-30 24-69 38t-83 14q-109 0-184.5-75.5T120-580q0-109 75.5-184.5T380-840q109 0 184.5 75.5T640-580q0 44-14 83t-38 69l252 252-56 56ZM380-400q75 0 127.5-52.5T560-580q0-75-52.5-127.5T380-760q-75 0-127.5 52.5T200-580q0 75 52.5 127.5T380-400Z\"/>\n </svg>\n <input\n type=\"text\"\n class=\"modal-search-input\"\n placeholder=\"${escapeHTML(props.placeholder || 'Search...')}\"\n aria-label=\"Search\"\n aria-autocomplete=\"list\"\n aria-controls=\"modal-results-list\"\n aria-expanded=\"false\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n />\n </div>\n <div class=\"modal-content\">\n <div class=\"modal-results\" id=\"modal-results-list\" role=\"listbox\" aria-label=\"Search results\">\n ${this.renderEmptyState()}\n </div>\n </div>\n <div class=\"modal-footer\">\n <div class=\"modal-footer-hints\">\n <div class=\"modal-footer-hint\">\n <kbd class=\"modal-kbd\">↑</kbd>\n <kbd class=\"modal-kbd\">↓</kbd>\n <span>Navigate</span>\n </div>\n <div class=\"modal-footer-hint\">\n <kbd class=\"modal-kbd\">↵</kbd>\n <span>Select</span>\n </div>\n <div class=\"modal-footer-hint\">\n <kbd class=\"modal-kbd\">Esc</kbd>\n <span>Close</span>\n </div>\n </div>\n ${brandingHTML}\n </div>\n </div>\n `;\n\n this.shadow.innerHTML = '';\n this.shadow.appendChild(style);\n this.shadow.appendChild(container);\n\n // Get references to elements\n this.backdrop = this.shadow.querySelector('.modal-backdrop');\n this.modal = this.shadow.querySelector('.modal-container');\n this.inputElement = this.shadow.querySelector('.modal-search-input');\n this.resultsContainer = this.shadow.querySelector('.modal-results');\n this.footerCount = this.shadow.querySelector('.modal-results-count');\n\n this.attachEventListeners();\n }\n\n private attachGlobalKeyboardShortcut(): void {\n const props = this.getProps();\n const shortcutKey = props.shortcut?.toLowerCase() || 'k';\n\n this.handleGlobalKeydown = (e: KeyboardEvent) => {\n // Check for shortcut to open modal\n const modifierPressed = props.useMetaKey ? e.metaKey || e.ctrlKey : e.ctrlKey;\n\n if (modifierPressed && e.key.toLowerCase() === shortcutKey && !this.isOpen) {\n e.preventDefault();\n this.open();\n }\n };\n\n document.addEventListener('keydown', this.handleGlobalKeydown);\n }\n\n private attachEventListeners(): void {\n if (!this.inputElement || !this.backdrop) return;\n\n // Input change event\n this.handleInputChange = (e: Event) => {\n const target = e.target as HTMLInputElement;\n const query = target.value.trim();\n\n if (query.length > 0 && this.debouncedSearch) {\n this.debouncedSearch(query);\n } else {\n this.results = [];\n this.activeIndex = -1;\n this.showEmptyState();\n }\n };\n this.inputElement.addEventListener('input', this.handleInputChange);\n\n // Keyboard navigation\n this.handleInputKeydown = (e: KeyboardEvent) => {\n switch (e.key) {\n case 'ArrowDown':\n e.preventDefault();\n this.navigateResults(1);\n break;\n case 'ArrowUp':\n e.preventDefault();\n this.navigateResults(-1);\n break;\n case 'Enter':\n e.preventDefault();\n this.selectActiveResult();\n break;\n case 'Escape':\n e.preventDefault();\n this.close();\n break;\n }\n };\n this.inputElement.addEventListener('keydown', this.handleInputKeydown);\n\n // Backdrop click to close\n this.handleBackdropClick = (e: MouseEvent) => {\n if (e.target === this.backdrop) {\n this.close();\n }\n };\n this.backdrop.addEventListener('click', this.handleBackdropClick);\n }\n\n private navigateResults(direction: number): void {\n if (this.results.length === 0) return;\n\n const newIndex = this.activeIndex + direction;\n\n if (newIndex < 0) {\n this.activeIndex = this.results.length - 1;\n } else if (newIndex >= this.results.length) {\n this.activeIndex = 0;\n } else {\n this.activeIndex = newIndex;\n }\n\n this.updateActiveResult();\n }\n\n private updateActiveResult(): void {\n const items = this.resultsContainer?.querySelectorAll('.modal-result-item');\n if (!items) return;\n\n items.forEach((item, index) => {\n if (index === this.activeIndex) {\n item.classList.add('active');\n item.setAttribute('aria-selected', 'true');\n // Scroll into view if needed\n (item as HTMLElement).scrollIntoView({ block: 'nearest' });\n } else {\n item.classList.remove('active');\n item.setAttribute('aria-selected', 'false');\n }\n });\n\n // Update aria-activedescendant\n if (this.inputElement && this.activeIndex >= 0) {\n this.inputElement.setAttribute('aria-activedescendant', `result-${this.activeIndex}`);\n } else if (this.inputElement) {\n this.inputElement.removeAttribute('aria-activedescendant');\n }\n }\n\n private selectActiveResult(): void {\n if (this.activeIndex < 0 || this.activeIndex >= this.results.length) {\n // If no result selected but there's a query, perform immediate search\n const query = this.inputElement?.value.trim();\n if (query && query.length > 0) {\n this.performSearch(query);\n }\n return;\n }\n\n const result = this.results[this.activeIndex];\n this.dispatchEvent(\n createCustomEvent('result-select', {\n result,\n index: this.activeIndex,\n })\n );\n\n // Navigate to URL if present\n if (result.url) {\n window.location.href = result.url;\n }\n\n this.close();\n }\n\n private async performSearch(query: string): Promise<void> {\n if (this.isLoading || !this.client) return;\n\n this.isLoading = true;\n this.showLoadingState();\n\n try {\n const results = await this.client.search(query, { streaming: false });\n const props = this.getProps();\n this.results = results.slice(0, props.maxResults || 10);\n this.activeIndex = this.results.length > 0 ? 0 : -1;\n this.displayResults(this.results, query);\n } catch (error) {\n this.showErrorState((error as Error).message);\n } finally {\n this.isLoading = false;\n }\n }\n\n private displayResults(results: SearchResult[], query: string): void {\n if (!this.resultsContainer) return;\n\n if (results.length === 0) {\n this.showNoResultsState(query);\n return;\n }\n\n const resultsHTML = results.map((result, index) => this.renderResult(result, index)).join('');\n\n this.resultsContainer.innerHTML = resultsHTML;\n\n // Update footer count\n if (this.footerCount) {\n this.footerCount.textContent = `${results.length} result${results.length === 1 ? '' : 's'}`;\n }\n\n // Update aria-expanded\n if (this.inputElement) {\n this.inputElement.setAttribute('aria-expanded', 'true');\n }\n\n // Attach click handlers\n this.attachResultHandlers();\n\n // Update active state\n this.updateActiveResult();\n }\n\n private renderResult(result: SearchResult, index: number): string {\n const imageHTML = this.renderResultImage(result.image, result.title);\n\n return `\n <div \n class=\"modal-result-item${index === this.activeIndex ? ' active' : ''}\" \n role=\"option\" \n id=\"result-${index}\"\n aria-selected=\"${index === this.activeIndex}\"\n tabindex=\"-1\"\n data-index=\"${index}\"\n data-url=\"${escapeHTML(result.url || '')}\"\n >\n ${imageHTML}\n <div class=\"modal-result-content\">\n <div class=\"modal-result-title\">${escapeHTML(result.title || '')}</div>\n ${result.description ? `<div class=\"modal-result-description\">${escapeHTML(result.description)}</div>` : ''}\n ${result.url ? `<a href=\"${escapeHTML(result.url)}\" class=\"modal-result-url\" tabindex=\"-1\">${escapeHTML(result.url)}</a>` : ''}\n </div>\n </div>\n `;\n }\n\n private renderResultImage(imageUrl: string | undefined, alt: string): string {\n const placeholderSVG = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\"><path d=\"M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z\"/><polyline points=\"14 2 14 8 20 8\"/><line x1=\"16\" y1=\"13\" x2=\"8\" y2=\"13\"/><line x1=\"16\" y1=\"17\" x2=\"8\" y2=\"17\"/><polyline points=\"10 9 9 9 8 9\"/></svg>`;\n\n if (!imageUrl) {\n return `\n <div class=\"modal-result-image-container\">\n <div class=\"modal-result-image-placeholder\">${placeholderSVG}</div>\n </div>\n `;\n }\n\n return `\n <div class=\"modal-result-image-container\">\n <div class=\"modal-result-image-loading\"></div>\n <div class=\"modal-result-image-placeholder\" style=\"display: none;\">${placeholderSVG}</div>\n <img \n class=\"modal-result-image\" \n src=\"${escapeHTML(imageUrl)}\" \n alt=\"${escapeHTML(alt)}\"\n loading=\"lazy\"\n />\n </div>\n `;\n }\n\n private attachResultHandlers(): void {\n const items = this.resultsContainer?.querySelectorAll('.modal-result-item');\n if (!items) return;\n\n items.forEach((item, index) => {\n item.addEventListener('click', (e) => {\n // Don't navigate if clicking the URL link directly\n if ((e.target as HTMLElement).classList.contains('modal-result-url')) {\n return;\n }\n this.activeIndex = index;\n this.selectActiveResult();\n });\n\n item.addEventListener('mouseenter', () => {\n this.activeIndex = index;\n this.updateActiveResult();\n });\n });\n\n // Image load/error handlers\n const images = this.resultsContainer?.querySelectorAll('.modal-result-image');\n images?.forEach((img) => {\n img.addEventListener('load', () => {\n img.classList.add('loaded');\n const container = img.closest('.modal-result-image-container');\n container?.querySelector('.modal-result-image-loading')?.remove();\n });\n\n img.addEventListener('error', () => {\n const container = img.closest('.modal-result-image-container');\n container?.querySelector('.modal-result-image-loading')?.remove();\n const placeholder = container?.querySelector(\n '.modal-result-image-placeholder'\n ) as HTMLElement;\n if (placeholder) placeholder.style.display = 'flex';\n (img as HTMLElement).style.display = 'none';\n });\n });\n }\n\n private renderEmptyState(): string {\n return `\n <div class=\"modal-empty\">\n <svg class=\"modal-empty-icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <circle cx=\"11\" cy=\"11\" r=\"8\"></circle>\n <path d=\"m21 21-4.35-4.35\"></path>\n </svg>\n <div class=\"modal-empty-description\">Start typing to search</div>\n </div>\n `;\n }\n\n private showEmptyState(): void {\n if (!this.resultsContainer) return;\n this.resultsContainer.innerHTML = this.renderEmptyState();\n\n if (this.footerCount) {\n this.footerCount.textContent = '';\n }\n\n if (this.inputElement) {\n this.inputElement.setAttribute('aria-expanded', 'false');\n }\n }\n\n private showLoadingState(): void {\n if (!this.resultsContainer) return;\n\n this.resultsContainer.innerHTML = `\n <div class=\"modal-loading\">\n <div class=\"loading\" aria-label=\"Loading\"></div>\n <div>Searching...</div>\n </div>\n `;\n\n if (this.footerCount) {\n this.footerCount.textContent = 'Searching...';\n }\n }\n\n private showNoResultsState(query: string): void {\n if (!this.resultsContainer) return;\n\n this.resultsContainer.innerHTML = `\n <div class=\"modal-empty\">\n <svg class=\"modal-empty-icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <circle cx=\"11\" cy=\"11\" r=\"8\"></circle>\n <line x1=\"21\" y1=\"21\" x2=\"16.65\" y2=\"16.65\"></line>\n </svg>\n <div class=\"modal-empty-title\">No results found</div>\n <div class=\"modal-empty-description\">No results for \"${escapeHTML(query)}\"</div>\n </div>\n `;\n\n if (this.footerCount) {\n this.footerCount.textContent = '0 results';\n }\n\n if (this.inputElement) {\n this.inputElement.setAttribute('aria-expanded', 'false');\n }\n }\n\n private showErrorState(message: string): void {\n if (!this.resultsContainer) return;\n\n this.resultsContainer.innerHTML = `\n <div class=\"error\">\n <strong>Error:</strong> ${escapeHTML(message)}\n </div>\n `;\n\n if (this.footerCount) {\n this.footerCount.textContent = 'Error';\n }\n }\n\n private updateTheme(theme: string | null): void {\n const validTheme = theme === 'light' || theme === 'dark' || theme === 'auto' ? theme : 'auto';\n\n if (validTheme === 'auto') {\n this.removeAttribute('theme');\n } else {\n this.setAttribute('theme', validTheme);\n }\n }\n\n private lockBodyScroll(): void {\n // Save current body styles\n const scrollY = window.scrollY;\n this.savedBodyStyles = {\n overflow: document.body.style.overflow,\n position: document.body.style.position,\n top: document.body.style.top,\n width: document.body.style.width,\n };\n this.savedHtmlOverflow = document.documentElement.style.overflow;\n\n // Apply scroll lock styles to both html and body for cross-browser support\n document.documentElement.style.overflow = 'hidden';\n document.body.style.overflow = 'hidden';\n document.body.style.position = 'fixed';\n document.body.style.top = `-${scrollY}px`;\n document.body.style.width = '100%';\n }\n\n private unlockBodyScroll(): void {\n if (!this.savedBodyStyles) return;\n\n // Get the scroll position from the top style\n const scrollY = Math.abs(Number.parseInt(document.body.style.top || '0', 10));\n\n // Restore original styles\n document.documentElement.style.overflow = this.savedHtmlOverflow || '';\n document.body.style.overflow = this.savedBodyStyles.overflow;\n document.body.style.position = this.savedBodyStyles.position;\n document.body.style.top = this.savedBodyStyles.top;\n document.body.style.width = this.savedBodyStyles.width;\n\n // Restore scroll position\n window.scrollTo(0, scrollY);\n\n this.savedBodyStyles = null;\n this.savedHtmlOverflow = null;\n }\n\n private cleanup(): void {\n // Remove global keyboard listener\n if (this.handleGlobalKeydown) {\n document.removeEventListener('keydown', this.handleGlobalKeydown);\n this.handleGlobalKeydown = null;\n }\n\n // Remove element event listeners\n if (this.inputElement) {\n if (this.handleInputChange) {\n this.inputElement.removeEventListener('input', this.handleInputChange);\n }\n if (this.handleInputKeydown) {\n this.inputElement.removeEventListener('keydown', this.handleInputKeydown);\n }\n }\n\n if (this.backdrop && this.handleBackdropClick) {\n this.backdrop.removeEventListener('click', this.handleBackdropClick);\n }\n\n // Clear handler references\n this.handleInputChange = null;\n this.handleInputKeydown = null;\n this.handleBackdropClick = null;\n\n // Cancel any pending requests\n if (this.client) {\n this.client.cancelAllRequests();\n }\n }\n\n // Public API\n\n /**\n * Open the search modal\n */\n public open(): void {\n if (this.isOpen) return;\n\n this.isOpen = true;\n this.backdrop?.classList.add('open');\n this.modal?.classList.add('open');\n\n // Focus input after animation completes\n // Use double rAF to ensure DOM has updated and transitions have started\n requestAnimationFrame(() => {\n requestAnimationFrame(() => {\n this.inputElement?.focus();\n });\n });\n\n // Prevent body scroll (save current styles to restore later)\n this.lockBodyScroll();\n\n this.dispatchEvent(createCustomEvent('open', undefined));\n }\n\n /**\n * Close the search modal\n */\n public close(): void {\n if (!this.isOpen) return;\n\n this.isOpen = false;\n this.backdrop?.classList.remove('open');\n this.modal?.classList.remove('open');\n\n // Clear state\n if (this.inputElement) {\n this.inputElement.value = '';\n }\n this.results = [];\n this.activeIndex = -1;\n this.showEmptyState();\n\n // Restore body scroll\n this.unlockBodyScroll();\n\n this.dispatchEvent(createCustomEvent('close', undefined));\n }\n\n /**\n * Toggle the search modal open/closed\n */\n public toggle(): void {\n if (this.isOpen) {\n this.close();\n } else {\n this.open();\n }\n }\n\n /**\n * Perform a search programmatically\n */\n public async search(query: string): Promise<void> {\n if (!this.isOpen) {\n this.open();\n }\n\n if (this.inputElement) {\n this.inputElement.value = query;\n }\n\n await this.performSearch(query);\n }\n\n /**\n * Get current search results\n */\n public getResults(): SearchResult[] {\n return [...this.results];\n }\n\n /**\n * Check if modal is currently open\n */\n public isModalOpen(): boolean {\n return this.isOpen;\n }\n}\n\n// Register the custom element\nif (!customElements.get(COMPONENT_NAME)) {\n customElements.define(COMPONENT_NAME, SearchModalSnippet);\n}\n"],"names":["debounce","func","wait","timeout","args","later","escapeHTML","text","div","decodeHTMLEntities","formatTimestamp","timestamp","date","diff","minutes","hours","generateId","prefix","parseAttribute","value","defaultValue","parseBooleanAttribute","parseNumberAttribute","parsed","createCustomEvent","name","detail","createClient","apiUrl","AISearchClient","Client","baseUrl","__publicField","_query","_options","_message","_requestId","options","operation","signal","query","requestId","controller","response","result","aggregated","chunk","key","score","a","b","chunks","reader","decoder","done","choice","request","id","chatStyles","baseStyles","CLOUDFLARE_LOGO_SVG","CLOUDFLARE_SEARCH_URL","POWERED_BY_BRANDING","markdownToHtml","markdown","html","escapeHtml","_","code","lines","processedLines","inList","listType","i","line","headerMatch","level","content","processInlineMarkdown","ulMatch","olMatch","htmlEntities","char","ChatView","container","client","props","e","target","userMessage","assistantMessageId","assistantMessage","stream","fullContent","messageIndex","m","error","message","messageId","isStreaming","messagesHTML","roleClass","avatar","streaming","messages","COMPONENT_NAME","ChatBubbleSnippet","oldValue","newValue","style","bubbleButton","closeButton","minimizeButton","clearButton","chatWindow","chatContent","theme","STORAGE_KEY","ChatPageSnippet","newChatButton","toggleSidebarButton","chatList","lastSession","stored","sessionIndex","s","session","firstUserMessage","newSession","sessionId","deleteButton","chatItem","isActive","diffMs","diffDays","str","searchStyles","SearchBarSnippet","searchFn","results","brandingHTML","resultsHTML","imageHTML","imageUrl","alt","placeholderSVG","resultItems","item","resultId","img","placeholder","validTheme","modalStyles","SearchModalSnippet","shortcutKey","direction","newIndex","items","index","scrollY"],"mappings":"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A;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GCAbC,IAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA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AA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GC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AAgBgC,CAAgB;AC5ajD,MAAMe,IAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA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"}
|