@gengage/assistant-fe 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +61 -0
- package/README.md +232 -0
- package/dist/assistant-fe.css +1 -0
- package/dist/chat/api.d.ts +87 -0
- package/dist/chat/api.d.ts.map +1 -0
- package/dist/chat/attachment-utils.d.ts +10 -0
- package/dist/chat/attachment-utils.d.ts.map +1 -0
- package/dist/chat/catalog.d.ts +1114 -0
- package/dist/chat/catalog.d.ts.map +1 -0
- package/dist/chat/components/AIGroupingCards.d.ts +4 -0
- package/dist/chat/components/AIGroupingCards.d.ts.map +1 -0
- package/dist/chat/components/AISuggestedSearchCards.d.ts +4 -0
- package/dist/chat/components/AISuggestedSearchCards.d.ts.map +1 -0
- package/dist/chat/components/AITopPicks.d.ts +4 -0
- package/dist/chat/components/AITopPicks.d.ts.map +1 -0
- package/dist/chat/components/CategoriesContainer.d.ts +4 -0
- package/dist/chat/components/CategoriesContainer.d.ts.map +1 -0
- package/dist/chat/components/ChatDrawer.d.ts +140 -0
- package/dist/chat/components/ChatDrawer.d.ts.map +1 -0
- package/dist/chat/components/ChoicePrompter.d.ts +16 -0
- package/dist/chat/components/ChoicePrompter.d.ts.map +1 -0
- package/dist/chat/components/ComparisonTable.d.ts +47 -0
- package/dist/chat/components/ComparisonTable.d.ts.map +1 -0
- package/dist/chat/components/FloatingComparisonButton.d.ts +11 -0
- package/dist/chat/components/FloatingComparisonButton.d.ts.map +1 -0
- package/dist/chat/components/GroundingReviewCard.d.ts +4 -0
- package/dist/chat/components/GroundingReviewCard.d.ts.map +1 -0
- package/dist/chat/components/KvkkBanner.d.ts +6 -0
- package/dist/chat/components/KvkkBanner.d.ts.map +1 -0
- package/dist/chat/components/Launcher.d.ts +25 -0
- package/dist/chat/components/Launcher.d.ts.map +1 -0
- package/dist/chat/components/PanelTopBar.d.ts +20 -0
- package/dist/chat/components/PanelTopBar.d.ts.map +1 -0
- package/dist/chat/components/ProactivePopup.d.ts +11 -0
- package/dist/chat/components/ProactivePopup.d.ts.map +1 -0
- package/dist/chat/components/ProsAndCons.d.ts +9 -0
- package/dist/chat/components/ProsAndCons.d.ts.map +1 -0
- package/dist/chat/components/ReviewHighlights.d.ts +3 -0
- package/dist/chat/components/ReviewHighlights.d.ts.map +1 -0
- package/dist/chat/components/ThumbnailsColumn.d.ts +23 -0
- package/dist/chat/components/ThumbnailsColumn.d.ts.map +1 -0
- package/dist/chat/components/actionClassifier.d.ts +13 -0
- package/dist/chat/components/actionClassifier.d.ts.map +1 -0
- package/dist/chat/components/productMentionLinker.d.ts +26 -0
- package/dist/chat/components/productMentionLinker.d.ts.map +1 -0
- package/dist/chat/components/renderUISpec.d.ts +15 -0
- package/dist/chat/components/renderUISpec.d.ts.map +1 -0
- package/dist/chat/components/typewriter.d.ts +25 -0
- package/dist/chat/components/typewriter.d.ts.map +1 -0
- package/dist/chat/extendedModeManager.d.ts +33 -0
- package/dist/chat/extendedModeManager.d.ts.map +1 -0
- package/dist/chat/index.d.ts +192 -0
- package/dist/chat/index.d.ts.map +1 -0
- package/dist/chat/locales/en.d.ts +3 -0
- package/dist/chat/locales/en.d.ts.map +1 -0
- package/dist/chat/locales/index.d.ts +6 -0
- package/dist/chat/locales/index.d.ts.map +1 -0
- package/dist/chat/locales/tr.d.ts +3 -0
- package/dist/chat/locales/tr.d.ts.map +1 -0
- package/dist/chat/types.d.ts +212 -0
- package/dist/chat/types.d.ts.map +1 -0
- package/dist/chat.cjs +2 -0
- package/dist/chat.cjs.map +1 -0
- package/dist/chat.iife.js +59 -0
- package/dist/chat.iife.js.map +1 -0
- package/dist/chat.js +11 -0
- package/dist/chat.js.map +1 -0
- package/dist/common/action-router.d.ts +30 -0
- package/dist/common/action-router.d.ts.map +1 -0
- package/dist/common/activity-tracker.d.ts +38 -0
- package/dist/common/activity-tracker.d.ts.map +1 -0
- package/dist/common/analytics-events.d.ts +90 -0
- package/dist/common/analytics-events.d.ts.map +1 -0
- package/dist/common/analytics.d.ts +58 -0
- package/dist/common/analytics.d.ts.map +1 -0
- package/dist/common/api-paths.d.ts +14 -0
- package/dist/common/api-paths.d.ts.map +1 -0
- package/dist/common/client.d.ts +20 -0
- package/dist/common/client.d.ts.map +1 -0
- package/dist/common/communication-bridge.d.ts +51 -0
- package/dist/common/communication-bridge.d.ts.map +1 -0
- package/dist/common/config-schema.d.ts +241 -0
- package/dist/common/config-schema.d.ts.map +1 -0
- package/dist/common/context.d.ts +28 -0
- package/dist/common/context.d.ts.map +1 -0
- package/dist/common/customization-factories.d.ts +63 -0
- package/dist/common/customization-factories.d.ts.map +1 -0
- package/dist/common/events.d.ts +47 -0
- package/dist/common/events.d.ts.map +1 -0
- package/dist/common/global-error-toast.d.ts +6 -0
- package/dist/common/global-error-toast.d.ts.map +1 -0
- package/dist/common/index.d.ts +36 -0
- package/dist/common/index.d.ts.map +1 -0
- package/dist/common/indexed-db.d.ts +74 -0
- package/dist/common/indexed-db.d.ts.map +1 -0
- package/dist/common/overlay.d.ts +64 -0
- package/dist/common/overlay.d.ts.map +1 -0
- package/dist/common/preflight.d.ts +12 -0
- package/dist/common/preflight.d.ts.map +1 -0
- package/dist/common/renderer/dom.d.ts +4 -0
- package/dist/common/renderer/dom.d.ts.map +1 -0
- package/dist/common/renderer/index.d.ts +5 -0
- package/dist/common/renderer/index.d.ts.map +1 -0
- package/dist/common/renderer/overrides.d.ts +24 -0
- package/dist/common/renderer/overrides.d.ts.map +1 -0
- package/dist/common/renderer/registry.d.ts +3 -0
- package/dist/common/renderer/registry.d.ts.map +1 -0
- package/dist/common/renderer/types.d.ts +20 -0
- package/dist/common/renderer/types.d.ts.map +1 -0
- package/dist/common/safe-html.d.ts +19 -0
- package/dist/common/safe-html.d.ts.map +1 -0
- package/dist/common/streaming.d.ts +32 -0
- package/dist/common/streaming.d.ts.map +1 -0
- package/dist/common/theme-utils.d.ts +16 -0
- package/dist/common/theme-utils.d.ts.map +1 -0
- package/dist/common/types.d.ts +298 -0
- package/dist/common/types.d.ts.map +1 -0
- package/dist/common/ui-theme.d.ts +10 -0
- package/dist/common/ui-theme.d.ts.map +1 -0
- package/dist/common/uuidv7.d.ts +8 -0
- package/dist/common/uuidv7.d.ts.map +1 -0
- package/dist/common/v1-protocol-adapter.d.ts +66 -0
- package/dist/common/v1-protocol-adapter.d.ts.map +1 -0
- package/dist/common/widget-base.d.ts +75 -0
- package/dist/common/widget-base.d.ts.map +1 -0
- package/dist/common.cjs +2 -0
- package/dist/common.cjs.map +1 -0
- package/dist/common.js +584 -0
- package/dist/common.js.map +1 -0
- package/dist/index-CFA70IGF.js +3626 -0
- package/dist/index-CFA70IGF.js.map +1 -0
- package/dist/index-Dfl89zpe.cjs +13 -0
- package/dist/index-Dfl89zpe.cjs.map +1 -0
- package/dist/index.cjs +2 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +59 -0
- package/dist/index.js.map +1 -0
- package/dist/qna/api.d.ts +22 -0
- package/dist/qna/api.d.ts.map +1 -0
- package/dist/qna/catalog.d.ts +140 -0
- package/dist/qna/catalog.d.ts.map +1 -0
- package/dist/qna/components/ButtonRow.d.ts +16 -0
- package/dist/qna/components/ButtonRow.d.ts.map +1 -0
- package/dist/qna/components/TextInput.d.ts +12 -0
- package/dist/qna/components/TextInput.d.ts.map +1 -0
- package/dist/qna/components/renderUISpec.d.ts +8 -0
- package/dist/qna/components/renderUISpec.d.ts.map +1 -0
- package/dist/qna/index.d.ts +34 -0
- package/dist/qna/index.d.ts.map +1 -0
- package/dist/qna/locales/en.d.ts +3 -0
- package/dist/qna/locales/en.d.ts.map +1 -0
- package/dist/qna/locales/index.d.ts +6 -0
- package/dist/qna/locales/index.d.ts.map +1 -0
- package/dist/qna/locales/tr.d.ts +3 -0
- package/dist/qna/locales/tr.d.ts.map +1 -0
- package/dist/qna/types.d.ts +62 -0
- package/dist/qna/types.d.ts.map +1 -0
- package/dist/qna.cjs +2 -0
- package/dist/qna.cjs.map +1 -0
- package/dist/qna.css +1 -0
- package/dist/qna.iife.js +48 -0
- package/dist/qna.iife.js.map +1 -0
- package/dist/qna.js +435 -0
- package/dist/qna.js.map +1 -0
- package/dist/simrel/api.d.ts +26 -0
- package/dist/simrel/api.d.ts.map +1 -0
- package/dist/simrel/catalog.d.ts +319 -0
- package/dist/simrel/catalog.d.ts.map +1 -0
- package/dist/simrel/components/GroupTabs.d.ts +17 -0
- package/dist/simrel/components/GroupTabs.d.ts.map +1 -0
- package/dist/simrel/components/ProductCard.d.ts +17 -0
- package/dist/simrel/components/ProductCard.d.ts.map +1 -0
- package/dist/simrel/components/ProductGrid.d.ts +17 -0
- package/dist/simrel/components/ProductGrid.d.ts.map +1 -0
- package/dist/simrel/components/renderUISpec.d.ts +8 -0
- package/dist/simrel/components/renderUISpec.d.ts.map +1 -0
- package/dist/simrel/index.d.ts +36 -0
- package/dist/simrel/index.d.ts.map +1 -0
- package/dist/simrel/locales/en.d.ts +3 -0
- package/dist/simrel/locales/en.d.ts.map +1 -0
- package/dist/simrel/locales/index.d.ts +6 -0
- package/dist/simrel/locales/index.d.ts.map +1 -0
- package/dist/simrel/locales/tr.d.ts +3 -0
- package/dist/simrel/locales/tr.d.ts.map +1 -0
- package/dist/simrel/types.d.ts +111 -0
- package/dist/simrel/types.d.ts.map +1 -0
- package/dist/simrel.cjs +2 -0
- package/dist/simrel.cjs.map +1 -0
- package/dist/simrel.css +1 -0
- package/dist/simrel.iife.js +48 -0
- package/dist/simrel.iife.js.map +1 -0
- package/dist/simrel.js +620 -0
- package/dist/simrel.js.map +1 -0
- package/dist/types-CeON7iBO.cjs +48 -0
- package/dist/types-CeON7iBO.cjs.map +1 -0
- package/dist/types-yxW8WA7u.js +4132 -0
- package/dist/types-yxW8WA7u.js.map +1 -0
- package/package.json +100 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-CFA70IGF.js","sources":["../src/common/uuidv7.ts","../src/common/communication-bridge.ts","../src/common/action-router.ts","../src/common/safe-html.ts","../src/chat/attachment-utils.ts","../src/chat/api.ts","../src/chat/locales/tr.ts","../src/chat/locales/en.ts","../src/chat/locales/index.ts","../src/chat/components/KvkkBanner.ts","../src/chat/components/PanelTopBar.ts","../src/chat/components/ThumbnailsColumn.ts","../src/chat/components/ChatDrawer.ts","../src/chat/components/Launcher.ts","../src/chat/components/ProactivePopup.ts","../src/common/activity-tracker.ts","../src/chat/components/ComparisonTable.ts","../src/chat/components/ReviewHighlights.ts","../src/chat/components/AITopPicks.ts","../src/chat/components/GroundingReviewCard.ts","../src/chat/components/AIGroupingCards.ts","../src/chat/components/AISuggestedSearchCards.ts","../src/chat/components/FloatingComparisonButton.ts","../src/chat/components/ProsAndCons.ts","../src/chat/components/CategoriesContainer.ts","../src/chat/components/renderUISpec.ts","../src/chat/components/typewriter.ts","../src/chat/components/productMentionLinker.ts","../src/chat/components/actionClassifier.ts","../src/chat/components/ChoicePrompter.ts","../src/common/indexed-db.ts","../src/chat/extendedModeManager.ts","../src/chat/catalog.ts","../src/chat/index.ts"],"sourcesContent":["/**\n * Zero-dependency UUIDv7 generator.\n *\n * 48-bit Unix-ms timestamp + random bits, version nibble 0x7, variant 0b10.\n * Lexicographically sortable — critical for thread ordering (threadA < threadB).\n */\n\nexport function uuidv7(): string {\n const now = Date.now();\n const bytes = new Uint8Array(16);\n crypto.getRandomValues(bytes);\n\n // 48-bit timestamp (big-endian) in bytes 0–5\n bytes[0] = (now / 2 ** 40) & 0xff;\n bytes[1] = (now / 2 ** 32) & 0xff;\n bytes[2] = (now / 2 ** 24) & 0xff;\n bytes[3] = (now / 2 ** 16) & 0xff;\n bytes[4] = (now / 2 ** 8) & 0xff;\n bytes[5] = now & 0xff;\n\n // Version 7: set high nibble of byte 6\n bytes[6] = (bytes[6]! & 0x0f) | 0x70;\n\n // Variant 10xx: set high bits of byte 8\n bytes[8] = (bytes[8]! & 0x3f) | 0x80;\n\n const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join('');\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;\n}\n","/**\n * Two-way communication bridge between the host page and embedded widgets.\n *\n * Host -> Widget: The host sends `window.postMessage({ gengage, type, payload })`.\n * The bridge validates the origin, checks the namespace, and routes to handlers.\n *\n * Widget -> Host: The bridge dispatches a `CustomEvent('gengage:bridge:message')`\n * on window so the host can listen without tight coupling.\n *\n * Built-in message types:\n * - 'addToCart' -- host confirms cart addition\n * - 'navigate' -- host navigates to URL\n * - 'openChat' -- programmatic open\n * - 'closeChat' -- programmatic close\n * - 'getContext' -- host requests current context\n */\n\nexport interface BridgeMessage {\n type: string;\n payload?: unknown;\n}\n\nexport interface CommunicationBridgeOptions {\n /** Widget namespace for message identification (e.g. 'chat', 'qna'). */\n namespace: string;\n /** Allowed origins for postMessage security (default: ['*']). */\n allowedOrigins?: string[];\n /** Callback when a message is received from the host. */\n onMessage?: (msg: BridgeMessage) => void;\n}\n\ntype BridgeHandler = (payload: unknown) => void;\n\nexport class CommunicationBridge {\n private readonly _namespace: string;\n private readonly _allowedOrigins: readonly string[];\n private readonly _onMessage: ((msg: BridgeMessage) => void) | undefined;\n private readonly _handlers = new Map<string, Set<BridgeHandler>>();\n private readonly _messageListener: (event: MessageEvent) => void;\n private _destroyed = false;\n\n constructor(options: CommunicationBridgeOptions) {\n this._namespace = options.namespace;\n this._allowedOrigins = options.allowedOrigins ?? ['*'];\n this._onMessage = options.onMessage;\n\n this._messageListener = (event: MessageEvent) => this._handlePostMessage(event);\n window.addEventListener('message', this._messageListener);\n }\n\n /** Send a message to the host page via CustomEvent on window. */\n send(type: string, payload?: unknown): void {\n if (this._destroyed) return;\n\n const detail: { namespace: string; type: string; payload?: unknown } = {\n namespace: this._namespace,\n type,\n };\n if (payload !== undefined) {\n detail.payload = payload;\n }\n\n window.dispatchEvent(\n new CustomEvent('gengage:bridge:message', {\n detail,\n bubbles: false,\n }),\n );\n }\n\n /**\n * Register a handler for a specific message type.\n * Returns an unsubscribe function.\n */\n on(type: string, handler: BridgeHandler): () => void {\n if (!this._handlers.has(type)) {\n this._handlers.set(type, new Set());\n }\n // The Map.get is guaranteed non-null after the set above\n const handlers = this._handlers.get(type)!;\n handlers.add(handler);\n\n return () => {\n handlers.delete(handler);\n if (handlers.size === 0) {\n this._handlers.delete(type);\n }\n };\n }\n\n /** Clean up all event listeners and handlers. */\n destroy(): void {\n if (this._destroyed) return;\n this._destroyed = true;\n window.removeEventListener('message', this._messageListener);\n this._handlers.clear();\n }\n\n // ---------------------------------------------------------------------------\n // Private\n // ---------------------------------------------------------------------------\n\n private _handlePostMessage(event: MessageEvent): void {\n if (this._destroyed) return;\n\n // Validate origin\n if (!this._isOriginAllowed(event.origin)) return;\n\n // Validate message shape: must be an object with { gengage, type }\n const data: unknown = event.data;\n if (!isValidBridgeData(data)) return;\n\n // Only process messages targeting this namespace\n if (data.gengage !== this._namespace) return;\n\n const msg: BridgeMessage = { type: data.type };\n if (data.payload !== undefined) {\n msg.payload = data.payload;\n }\n\n // Invoke the general onMessage callback\n this._onMessage?.(msg);\n\n // Route to type-specific handlers\n const handlers = this._handlers.get(msg.type);\n if (handlers) {\n for (const handler of handlers) {\n handler(msg.payload);\n }\n }\n }\n\n private _isOriginAllowed(origin: string): boolean {\n if (this._allowedOrigins.includes('*')) return true;\n return this._allowedOrigins.includes(origin);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Shape guard for incoming postMessage data. */\nfunction isValidBridgeData(data: unknown): data is { gengage: string; type: string; payload?: unknown } {\n if (typeof data !== 'object' || data === null) return false;\n const obj = data as Record<string, unknown>;\n return typeof obj['gengage'] === 'string' && typeof obj['type'] === 'string';\n}\n","import type { UnknownActionPolicy } from './config-schema.js';\nimport type { ActionPayload, StreamEventAction } from './types.js';\n\nexport interface HostActionHandlers {\n openChat?: (payload?: ActionPayload | unknown) => void;\n navigate?: (params: { url: string; newTab?: boolean }) => void;\n saveSession?: (params: { sessionId: string; sku: string }) => void;\n addToCart?: (params: { sku: string; quantity: number; cartCode: string }) => void;\n scriptCall?: (params: { name: string; payload?: Record<string, unknown> }) => void;\n unknown?: (action: StreamEventAction['action']) => void;\n}\n\nexport interface ActionRouterOptions {\n allowScriptCall?: boolean;\n unknownActionPolicy?: UnknownActionPolicy;\n logger?: Pick<Console, 'warn' | 'error' | 'debug'>;\n}\n\nconst defaultLogger: Pick<Console, 'warn' | 'error' | 'debug'> = console;\n\nexport function routeStreamAction(\n event: StreamEventAction,\n handlers: HostActionHandlers,\n options: ActionRouterOptions = {},\n): void {\n const action = event.action;\n const logger = options.logger ?? defaultLogger;\n\n switch (action.kind) {\n case 'open_chat': {\n handlers.openChat?.(action.payload);\n return;\n }\n case 'navigate': {\n if (typeof action.url !== 'string') {\n handleUnknownAction(action, handlers, options, logger);\n return;\n }\n const newTab = typeof action.newTab === 'boolean' ? action.newTab : undefined;\n if (handlers.navigate) {\n if (newTab !== undefined) {\n handlers.navigate({ url: action.url, newTab });\n } else {\n handlers.navigate({ url: action.url });\n }\n return;\n }\n defaultNavigate(action.url, newTab);\n return;\n }\n case 'save_session': {\n if (typeof action.sessionId !== 'string' || typeof action.sku !== 'string') {\n handleUnknownAction(action, handlers, options, logger);\n return;\n }\n handlers.saveSession?.({ sessionId: action.sessionId, sku: action.sku });\n return;\n }\n case 'add_to_cart': {\n if (\n typeof action.sku !== 'string' ||\n typeof action.quantity !== 'number' ||\n typeof action.cartCode !== 'string'\n ) {\n handleUnknownAction(action, handlers, options, logger);\n return;\n }\n handlers.addToCart?.({\n sku: action.sku,\n quantity: action.quantity,\n cartCode: action.cartCode,\n });\n return;\n }\n case 'script_call': {\n if (options.allowScriptCall === false) {\n handleUnknownAction(action, handlers, options, logger);\n return;\n }\n if (typeof action.name !== 'string') {\n handleUnknownAction(action, handlers, options, logger);\n return;\n }\n const payload = isRecord(action.payload) ? action.payload : undefined;\n if (payload !== undefined) {\n handlers.scriptCall?.({ name: action.name, payload });\n } else {\n handlers.scriptCall?.({ name: action.name });\n }\n return;\n }\n default: {\n handleUnknownAction(action, handlers, options, logger);\n }\n }\n}\n\nfunction handleUnknownAction(\n action: StreamEventAction['action'],\n handlers: HostActionHandlers,\n options: ActionRouterOptions,\n logger: Pick<Console, 'warn' | 'error' | 'debug'>,\n): void {\n const policy = options.unknownActionPolicy ?? 'log-and-ignore';\n if (policy === 'delegate') {\n handlers.unknown?.(action);\n if (!handlers.unknown) {\n logger.warn('[gengage] Unknown action received without delegate handler', action);\n }\n return;\n }\n\n if (policy === 'throw') {\n throw new Error(`[gengage] Unknown action kind: ${(action as { kind?: unknown }).kind}`);\n }\n\n logger.warn('[gengage] Unknown action ignored', action);\n}\n\nfunction defaultNavigate(url: string, newTab?: boolean): void {\n if (typeof window === 'undefined') return;\n if (newTab) {\n window.open(url, '_blank', 'noopener,noreferrer');\n return;\n }\n window.location.href = url;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n","/**\n * DOMParser-based HTML sanitizer.\n *\n * Backend sends HTML in assistant messages (e.g. KVKK notice).\n * This module strips dangerous elements/attributes while preserving\n * safe formatting tags.\n *\n * WARNING: Any new injection point that uses innerHTML must call this function first.\n */\n\nconst ALLOWED_TAGS = new Set([\n 'p',\n 'br',\n 'a',\n 'strong',\n 'b',\n 'em',\n 'i',\n 'u',\n 'ul',\n 'ol',\n 'li',\n 'h1',\n 'h2',\n 'h3',\n 'h4',\n 'h5',\n 'h6',\n 'span',\n 'div',\n 'table',\n 'thead',\n 'tbody',\n 'tr',\n 'th',\n 'td',\n 'hr',\n 'code',\n 'pre',\n 'blockquote',\n 'img',\n 'sup',\n 'sub',\n]);\n\n/** Elements removed entirely (children NOT promoted). */\nconst DISALLOWED_TAGS = new Set([\n 'script',\n 'iframe',\n 'object',\n 'embed',\n 'form',\n 'input',\n 'textarea',\n 'select',\n 'button',\n 'style',\n 'link',\n 'meta',\n]);\n\n/** Attributes allowed per-tag. `'*'` means any allowed tag. */\nconst ALLOWED_ATTRS: Record<string, Set<string>> = {\n '*': new Set(['class']),\n a: new Set(['href', 'target', 'rel']),\n img: new Set(['src', 'alt', 'width', 'height']),\n div: new Set(['style']),\n span: new Set(['style']),\n p: new Set(['style']),\n};\n\nfunction hasJavascriptProtocol(value: string): boolean {\n // Normalize whitespace + case then check\n return /^\\s*javascript\\s*:/i.test(value);\n}\n\nfunction sanitizeNode(node: Node, parent: Node): void {\n if (node.nodeType === Node.TEXT_NODE) return;\n\n if (node.nodeType !== Node.ELEMENT_NODE) {\n node.parentNode?.removeChild(node);\n return;\n }\n\n const el = node as Element;\n const tag = el.tagName.toLowerCase();\n\n // Disallowed: remove entirely (including children)\n if (DISALLOWED_TAGS.has(tag)) {\n el.parentNode?.removeChild(el);\n return;\n }\n\n // Unknown: unwrap (promote children to parent)\n if (!ALLOWED_TAGS.has(tag)) {\n const children = Array.from(el.childNodes);\n for (const child of children) {\n parent.insertBefore(child, el);\n }\n parent.removeChild(el);\n // Sanitize promoted children\n for (const child of children) {\n sanitizeNode(child, parent);\n }\n return;\n }\n\n // Sanitize attributes\n const globalAllowed = ALLOWED_ATTRS['*'] ?? new Set();\n const tagAllowed = ALLOWED_ATTRS[tag] ?? new Set();\n const attrs = Array.from(el.attributes);\n\n for (const attr of attrs) {\n const name = attr.name.toLowerCase();\n\n if (!globalAllowed.has(name) && !tagAllowed.has(name)) {\n el.removeAttribute(attr.name);\n continue;\n }\n\n // Strip javascript: protocol from any attribute value\n if (hasJavascriptProtocol(attr.value)) {\n el.removeAttribute(attr.name);\n continue;\n }\n }\n\n // Validate specific attribute values\n if (tag === 'a') {\n const href = el.getAttribute('href');\n if (href !== null) {\n const trimmed = href.trim().toLowerCase();\n if (!trimmed.startsWith('http://') && !trimmed.startsWith('https://') && !trimmed.startsWith('mailto:')) {\n el.removeAttribute('href');\n }\n }\n // Force safe link behavior\n el.setAttribute('target', '_blank');\n el.setAttribute('rel', 'noopener noreferrer');\n }\n\n if (tag === 'img') {\n const src = el.getAttribute('src');\n if (src !== null) {\n const trimmed = src.trim().toLowerCase();\n if (!trimmed.startsWith('https://')) {\n el.removeAttribute('src');\n }\n }\n }\n\n // Recurse into children (snapshot the list since we may mutate)\n const children = Array.from(el.childNodes);\n for (const child of children) {\n sanitizeNode(child, el);\n }\n}\n\n/**\n * Sanitize an HTML string for safe insertion via innerHTML.\n *\n * - Allowed tags are preserved; disallowed tags are removed entirely.\n * - Unknown tags are unwrapped (children promoted).\n * - `<a>` tags are forced to `target=\"_blank\" rel=\"noopener noreferrer\"`.\n * - Only `https://` is allowed for `<img src>`.\n */\nexport function sanitizeHtml(raw: string): string {\n if (!raw) return '';\n\n const doc = new DOMParser().parseFromString(raw, 'text/html');\n const body = doc.body;\n\n const children = Array.from(body.childNodes);\n for (const child of children) {\n sanitizeNode(child, body);\n }\n\n return body.innerHTML;\n}\n","export const ALLOWED_MIME_TYPES = ['image/jpeg', 'image/png', 'image/webp'] as const;\nexport const MAX_FILE_SIZE = 5 * 1024 * 1024; // 5 MB\n\nexport type ValidationResult = { ok: true } | { ok: false; reason: 'invalid_type' | 'too_large' };\n\nexport function validateImageFile(file: File): ValidationResult {\n if (!(ALLOWED_MIME_TYPES as readonly string[]).includes(file.type)) {\n return { ok: false, reason: 'invalid_type' };\n }\n if (file.size > MAX_FILE_SIZE) {\n return { ok: false, reason: 'too_large' };\n }\n return { ok: true };\n}\n","import { consumeStream } from '../common/streaming.js';\nimport { adaptV1Event } from '../common/v1-protocol-adapter.js';\nimport { buildChatEndpointUrl } from '../common/api-paths.js';\nimport type { StreamEvent, UISpec, PageContext } from '../common/types.js';\nimport type { ChatTransportConfig } from '../common/api-paths.js';\n\nexport interface BackendRequestMeta {\n outputLanguage: string;\n parentUrl: string;\n windowWidth: string;\n windowHeight: string;\n selfUrl: string;\n id: string;\n userId: string;\n appId: string;\n threads: unknown[];\n createdAt: string;\n kvkkApproved: boolean;\n voiceEnabled: boolean;\n threadId: string;\n isControlGroup: boolean;\n isMobile: boolean;\n viewId?: string;\n}\n\nexport interface ProcessActionRequest {\n account_id: string;\n session_id: string;\n correlation_id: string;\n user_id?: string;\n view_id?: string;\n action: {\n title: string;\n type: string;\n payload?: unknown;\n };\n sku?: string;\n page_type?: string;\n locale?: string;\n meta?: BackendRequestMeta;\n context?: {\n messages?: Array<{ role: string; content: string }>;\n [key: string]: unknown;\n };\n}\n\nexport interface ActionEnrichmentContext {\n pageContext?: PageContext | undefined;\n backendContext?: Record<string, unknown> | null | undefined;\n isMobile?: boolean | undefined;\n}\n\n/**\n * Enriches action payloads with fields the v1 backend expects.\n * Only adds fields that are not already present in the payload.\n */\nexport function enrichActionPayload(\n action: { title: string; type: string; payload?: unknown },\n ctx: ActionEnrichmentContext,\n): { title: string; type: string; payload?: unknown } {\n const type = action.type;\n const existing =\n action.payload != null && typeof action.payload === 'object' && !Array.isArray(action.payload)\n ? (action.payload as Record<string, unknown>)\n : {};\n\n // Helper: only set if not already present\n const merge = (additions: Record<string, unknown>): Record<string, unknown> => {\n const result = { ...existing };\n for (const [key, value] of Object.entries(additions)) {\n if (!(key in result)) {\n result[key] = value;\n }\n }\n return result;\n };\n\n switch (type) {\n case 'inputText': {\n const additions: Record<string, unknown> = {\n is_launcher: 0,\n };\n if (ctx.pageContext?.extra) additions['page_details'] = ctx.pageContext.extra;\n // is_suggested_text may already be set by adapter — don't overwrite\n if (!('is_suggested_text' in existing)) additions['is_suggested_text'] = 0;\n return { ...action, payload: merge(additions) };\n }\n\n case 'findSimilar': {\n const additions: Record<string, unknown> = {\n is_launcher: 0,\n };\n if (action.title) additions['text'] = action.title;\n if (action.title) additions['input'] = action.title;\n return { ...action, payload: merge(additions) };\n }\n\n case 'getComparisonTable': {\n // sku_list should already be set; no-op if present\n return action;\n }\n\n case 'addToCart': {\n const additions: Record<string, unknown> = {};\n if (!('error_message' in existing)) additions['error_message'] = '';\n return { ...action, payload: merge(additions) };\n }\n\n case 'reviewSummary': {\n const additions: Record<string, unknown> = {};\n if (ctx.pageContext?.sku && !('sku' in existing)) {\n additions['sku'] = ctx.pageContext.sku;\n }\n if (Object.keys(additions).length === 0) return action;\n return { ...action, payload: merge(additions) };\n }\n\n default:\n return action;\n }\n}\n\nexport interface StreamCallbacks {\n onTextChunk: (\n content: string,\n isFinal: boolean,\n extra?: {\n productMentions?: Array<{ sku: string; short_name: string }> | undefined;\n skuToProductItem?: Record<string, Record<string, unknown>> | undefined;\n conversationMode?: string | undefined;\n },\n ) => void;\n onUISpec: (spec: UISpec, widget: string, panelHint?: 'panel') => void;\n onAction: (event: StreamEvent) => void;\n onMetadata: (event: StreamEvent) => void;\n onError: (err: Error) => void;\n onDone: () => void;\n}\n\n/**\n * Action type mapping.\n * The backend's ActionType enum uses `inputText` for user messages,\n * while the frontend uses `user_message`. Map at the boundary.\n */\nconst ACTION_TYPE_MAP: Record<string, string> = {\n user_message: 'inputText',\n};\n\n/**\n * Builds the request body for `/chat/process_action`.\n *\n * Backend expects `type`, `payload`, and `title` at the top level —\n * matching chat_api.py's current schema.\n */\nfunction buildRequestBody(request: ProcessActionRequest): string {\n const { action, ...rest } = request;\n const mappedType = ACTION_TYPE_MAP[action.type] ?? action.type;\n const body: Record<string, unknown> = {\n ...rest,\n type: mappedType,\n title: action.title,\n };\n if (action.payload !== undefined) {\n // Backend expects payload as an object. Wrap string payloads for compatibility.\n body.payload = typeof action.payload === 'string' ? { text: action.payload } : action.payload;\n }\n return JSON.stringify(body);\n}\n\nexport function sendChatMessage(\n request: ProcessActionRequest,\n callbacks: StreamCallbacks,\n transport: ChatTransportConfig,\n): AbortController {\n const url = buildChatEndpointUrl('process_action', transport);\n const controller = new AbortController();\n\n const run = async (): Promise<void> => {\n try {\n const requestBody = buildRequestBody(request);\n\n // Use FormData only when an attachment is present; otherwise send JSON.\n const useFormData = transport.attachment !== undefined;\n\n let fetchInit: RequestInit;\n if (useFormData) {\n const formData = new FormData();\n formData.append('request', requestBody);\n if (transport.attachment !== undefined) {\n formData.append('attachment', transport.attachment);\n }\n fetchInit = {\n method: 'POST',\n body: formData,\n signal: controller.signal,\n };\n } else {\n fetchInit = {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: requestBody,\n signal: controller.signal,\n };\n }\n\n const response = await fetch(url, fetchInit);\n\n if (!response.ok) {\n callbacks.onError(new Error(`HTTP ${response.status}: ${response.statusText}`));\n return;\n }\n\n await consumeStream(response, {\n onEvent: (event: StreamEvent) => {\n const normalized = adaptV1Event(event as unknown as Record<string, unknown>);\n\n if (!normalized) return;\n\n switch (normalized.type) {\n case 'text_chunk':\n callbacks.onTextChunk(normalized.content, normalized.final === true, {\n productMentions: normalized.productMentions,\n skuToProductItem: normalized.skuToProductItem,\n conversationMode: normalized.conversationMode,\n });\n break;\n case 'ui_spec':\n callbacks.onUISpec(normalized.spec, normalized.widget, normalized.panelHint);\n break;\n case 'action':\n callbacks.onAction(normalized);\n break;\n case 'metadata':\n callbacks.onMetadata(normalized);\n break;\n case 'error':\n callbacks.onError(new Error(normalized.message));\n break;\n case 'done':\n callbacks.onDone();\n break;\n }\n },\n onError: callbacks.onError,\n signal: controller.signal,\n });\n } catch (err) {\n if (err instanceof DOMException && err.name === 'AbortError') return;\n callbacks.onError(err instanceof Error ? err : new Error(String(err)));\n }\n };\n\n void run();\n return controller;\n}\n\nexport async function fetchProactiveAction(\n request: { account_id: string; sku?: string; page_type?: string },\n transport: ChatTransportConfig,\n): Promise<{ title?: string; question?: string; actions?: unknown[] } | null> {\n const url = buildChatEndpointUrl('proactive_action', transport);\n try {\n const res = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(request),\n });\n if (!res.ok) return null;\n return (await res.json()) as { title?: string; question?: string; actions?: unknown[] };\n } catch {\n return null;\n }\n}\n","import type { ChatI18n } from '../types.js';\n\nexport const CHAT_I18N_TR: ChatI18n = {\n headerTitle: 'Ürün Uzmanı',\n inputPlaceholder: 'Ürün ara, soru sor',\n sendButton: 'Gönder',\n closeButton: 'Kapat',\n openButton: 'Sohbeti aç',\n newChatButton: 'Yeni sohbet',\n poweredBy: 'Powered by Gengage',\n errorMessage: 'Bir hata oluştu. Lütfen tekrar deneyin.',\n loadingMessage: 'Düşünüyorum...',\n productCtaLabel: 'İncele',\n attachImageButton: 'Resim ekle',\n removeAttachmentButton: 'Resmi kaldır',\n invalidFileType: 'Sadece JPEG, PNG ve WebP dosyaları destekleniyor.',\n fileTooLarge: \"Dosya boyutu 5 MB'dan küçük olmalıdır.\",\n aiTopPicksTitle: 'Sizin İçin En İyiler',\n roleWinner: 'En Beğendiğim',\n roleBestValue: 'En Uygun Fiyatlı',\n roleBestAlternative: 'En İyi Alternatif',\n viewDetails: 'Detayları Gör',\n groundingReviewCta: 'Yorumları Oku',\n variantsLabel: 'Varyantlar',\n sortRelated: 'Önerilen',\n sortPriceAsc: 'Fiyat ↑',\n sortPriceDesc: 'Fiyat ↓',\n compareSelected: 'Karşılaştır',\n panelTitleProductDetails: 'Ürün Detayı',\n panelTitleSimilarProducts: 'Benzer Ürünler',\n panelTitleComparisonResults: 'Karşılaştırma Sonuçları',\n panelTitleCategories: 'Kategoriler',\n inStockLabel: 'Stokta',\n outOfStockLabel: 'Tükendi',\n findSimilarLabel: 'Benzerlerini Bul',\n choicePrompterHeading: 'Kararsız mı kaldın?',\n choicePrompterSuggestion: 'Ürünleri seçip karşılaştırabilirsin',\n choicePrompterCta: 'Seç ve Karşılaştır',\n viewMoreLabel: 'Daha Fazla Göster',\n similarProductsLabel: 'Benzer Ürünler',\n};\n","import type { ChatI18n } from '../types.js';\n\nexport const CHAT_I18N_EN: ChatI18n = {\n headerTitle: 'Product Expert',\n inputPlaceholder: 'Search products, ask questions',\n sendButton: 'Send',\n closeButton: 'Close',\n openButton: 'Open chat',\n newChatButton: 'New chat',\n poweredBy: 'Powered by Gengage',\n errorMessage: 'Something went wrong. Please try again.',\n loadingMessage: 'Thinking...',\n productCtaLabel: 'View',\n attachImageButton: 'Attach image',\n removeAttachmentButton: 'Remove image',\n invalidFileType: 'Only JPEG, PNG and WebP files are supported.',\n fileTooLarge: 'File must be smaller than 5 MB.',\n aiTopPicksTitle: 'Top Picks for You',\n roleWinner: 'Top Pick',\n roleBestValue: 'Best Value',\n roleBestAlternative: 'Best Alternative',\n viewDetails: 'View Details',\n groundingReviewCta: 'Read Reviews',\n variantsLabel: 'Variants',\n sortRelated: 'Related',\n sortPriceAsc: 'Price ↑',\n sortPriceDesc: 'Price ↓',\n compareSelected: 'Compare',\n panelTitleProductDetails: 'Product Details',\n panelTitleSimilarProducts: 'Similar Products',\n panelTitleComparisonResults: 'Comparison Results',\n panelTitleCategories: 'Categories',\n inStockLabel: 'In Stock',\n outOfStockLabel: 'Out of Stock',\n findSimilarLabel: 'Find Similar',\n choicePrompterHeading: \"Can't decide?\",\n choicePrompterSuggestion: 'Select products to compare them',\n choicePrompterCta: 'Select & Compare',\n viewMoreLabel: 'Show More',\n similarProductsLabel: 'Similar Products',\n};\n","import type { ChatI18n } from '../types.js';\nimport { CHAT_I18N_TR } from './tr.js';\nimport { CHAT_I18N_EN } from './en.js';\n\nfunction normalizeLocale(locale?: string): string {\n if (!locale) return 'tr';\n return locale.toLowerCase().split('-')[0] ?? 'tr';\n}\n\nexport function resolveChatLocale(locale?: string): ChatI18n {\n switch (normalizeLocale(locale)) {\n case 'en':\n return CHAT_I18N_EN;\n default:\n return CHAT_I18N_TR;\n }\n}\n\nexport { CHAT_I18N_TR, CHAT_I18N_EN };\n","import { sanitizeHtml } from '../../common/safe-html.js';\n\nexport interface KvkkBannerOptions {\n htmlContent: string;\n onDismiss: () => void;\n}\n\nexport function createKvkkBanner(options: KvkkBannerOptions): HTMLElement {\n const banner = document.createElement('div');\n banner.className = 'gengage-chat-kvkk-banner';\n banner.setAttribute('role', 'alert');\n\n const content = document.createElement('div');\n content.className = 'gengage-chat-kvkk-content';\n content.innerHTML = sanitizeHtml(options.htmlContent);\n banner.appendChild(content);\n\n const dismiss = document.createElement('button');\n dismiss.className = 'gengage-chat-kvkk-dismiss';\n dismiss.type = 'button';\n dismiss.setAttribute('aria-label', 'Kapat');\n dismiss.textContent = '\\u00D7';\n dismiss.addEventListener('click', options.onDismiss);\n banner.appendChild(dismiss);\n\n return banner;\n}\n","/**\n * PanelTopBar — navigation bar at the top of the panel pane.\n *\n * Shows back/forward arrow buttons and a title derived from the current\n * panel content type.\n */\n\nexport interface PanelTopBarOptions {\n onBack: () => void;\n onForward: () => void;\n}\n\nexport class PanelTopBar {\n private _el: HTMLElement;\n private _backBtn: HTMLButtonElement;\n private _forwardBtn: HTMLButtonElement;\n private _titleEl: HTMLElement;\n\n constructor(options: PanelTopBarOptions) {\n this._el = document.createElement('div');\n this._el.className = 'gengage-chat-panel-topbar';\n\n this._backBtn = document.createElement('button');\n this._backBtn.className = 'gengage-chat-panel-topbar-back';\n this._backBtn.type = 'button';\n this._backBtn.disabled = true;\n this._backBtn.setAttribute('aria-label', 'Back');\n this._backBtn.textContent = '\\u2190'; // ←\n this._backBtn.addEventListener('click', () => options.onBack());\n\n this._titleEl = document.createElement('span');\n this._titleEl.className = 'gengage-chat-panel-topbar-title';\n\n this._forwardBtn = document.createElement('button');\n this._forwardBtn.className = 'gengage-chat-panel-topbar-forward';\n this._forwardBtn.type = 'button';\n this._forwardBtn.disabled = true;\n this._forwardBtn.setAttribute('aria-label', 'Forward');\n this._forwardBtn.textContent = '\\u2192'; // →\n this._forwardBtn.addEventListener('click', () => options.onForward());\n\n this._el.appendChild(this._backBtn);\n this._el.appendChild(this._titleEl);\n this._el.appendChild(this._forwardBtn);\n }\n\n update(canBack: boolean, canForward: boolean, title: string): void {\n this._backBtn.disabled = !canBack;\n this._forwardBtn.disabled = !canForward;\n this._titleEl.textContent = title;\n }\n\n getElement(): HTMLElement {\n return this._el;\n }\n}\n","/**\n * Vertical strip of product thumbnails along the right edge of the panel (results) pane.\n *\n * Clicking a thumbnail dispatches a rollback to the thread where that product was shown.\n */\n\nexport interface ThumbnailEntry {\n sku: string;\n imageUrl: string;\n threadId: string;\n}\n\nexport interface ThumbnailsColumnOptions {\n onThumbnailClick: (threadId: string) => void;\n}\n\nexport class ThumbnailsColumn {\n private readonly _el: HTMLElement;\n private readonly _onThumbnailClick: (threadId: string) => void;\n\n constructor(options: ThumbnailsColumnOptions) {\n this._onThumbnailClick = options.onThumbnailClick;\n\n this._el = document.createElement('div');\n this._el.className = 'gengage-chat-thumbnails-column';\n this._el.style.display = 'none';\n }\n\n getElement(): HTMLElement {\n return this._el;\n }\n\n setEntries(entries: ThumbnailEntry[]): void {\n // Deduplicate by SKU (keep first occurrence)\n const seen = new Set<string>();\n const unique: ThumbnailEntry[] = [];\n for (const entry of entries) {\n if (!seen.has(entry.sku)) {\n seen.add(entry.sku);\n unique.push(entry);\n }\n }\n\n this._el.innerHTML = '';\n\n for (const entry of unique) {\n const thumb = document.createElement('button');\n thumb.type = 'button';\n thumb.className = 'gengage-chat-thumbnail-btn';\n thumb.title = entry.sku;\n\n const img = document.createElement('img');\n img.className = 'gengage-chat-thumbnail-img';\n img.src = entry.imageUrl;\n img.alt = entry.sku;\n img.width = 40;\n img.height = 40;\n\n thumb.appendChild(img);\n thumb.addEventListener('click', () => {\n this._onThumbnailClick(entry.threadId);\n });\n\n this._el.appendChild(thumb);\n }\n }\n\n show(): void {\n this._el.style.display = '';\n }\n\n hide(): void {\n this._el.style.display = 'none';\n }\n}\n","import type { ChatI18n, ChatMessage } from '../types.js';\nimport { sanitizeHtml } from '../../common/safe-html.js';\nimport { CHAT_I18N_TR } from '../locales/index.js';\nimport { createKvkkBanner } from './KvkkBanner.js';\nimport { PanelTopBar } from './PanelTopBar.js';\nimport { ThumbnailsColumn } from './ThumbnailsColumn.js';\nimport type { ThumbnailEntry } from './ThumbnailsColumn.js';\n\n/** SVG icon map for suggested action chips/pills. Keys match backend icon names. */\nconst SUGGESTED_ACTION_ICONS: Record<string, string> = {\n search:\n '<svg viewBox=\"0 0 16 16\" class=\"gengage-chat-icon\"><circle cx=\"6.5\" cy=\"6.5\" r=\"5\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\"/><line x1=\"10\" y1=\"10\" x2=\"15\" y2=\"15\" stroke=\"currentColor\" stroke-width=\"1.5\"/></svg>',\n review:\n '<svg viewBox=\"0 0 16 16\" class=\"gengage-chat-icon\"><polygon points=\"8,1 10,6 15,6 11,9 12.5,14 8,11 3.5,14 5,9 1,6 6,6\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\"/></svg>',\n info: '<svg viewBox=\"0 0 16 16\" class=\"gengage-chat-icon\"><circle cx=\"8\" cy=\"8\" r=\"7\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\"/><line x1=\"8\" y1=\"7\" x2=\"8\" y2=\"12\" stroke=\"currentColor\" stroke-width=\"1.5\"/><circle cx=\"8\" cy=\"4.5\" r=\"0.8\" fill=\"currentColor\"/></svg>',\n similar:\n '<svg viewBox=\"0 0 16 16\" class=\"gengage-chat-icon\"><rect x=\"1\" y=\"3\" width=\"6\" height=\"6\" rx=\"1\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\"/><rect x=\"9\" y=\"3\" width=\"6\" height=\"6\" rx=\"1\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\"/></svg>',\n};\n\nexport { SUGGESTED_ACTION_ICONS };\n\nexport interface ChatDrawerOptions {\n i18n: ChatI18n;\n onSend: (text: string, attachment?: File) => void;\n onClose: () => void;\n onAttachment?: (file: File) => void;\n onPanelToggle?: () => void;\n onRollback?: (messageId: string) => void;\n headerTitle?: string | undefined;\n headerAvatarUrl?: string | undefined;\n headerBadge?: string | undefined;\n /** URL for the cart icon link in the header (e.g. \"/sepetim\"). */\n headerCartUrl?: string | undefined;\n /** Show a favorites (heart) toggle button in the header. */\n headerFavoritesToggle?: boolean | undefined;\n onFavoritesClick?: (() => void) | undefined;\n /** Callback fired when the panel back button is clicked. */\n onPanelBack?: (() => void) | undefined;\n /** Callback fired when the panel forward button is clicked. */\n onPanelForward?: (() => void) | undefined;\n /** Callback fired when a product thumbnail is clicked (for thread rollback). */\n onThumbnailClick?: ((threadId: string) => void) | undefined;\n /** Callback fired when a link in bot HTML is clicked. */\n onLinkClick?: ((url: string) => void) | undefined;\n}\n\nconst DEFAULT_I18N: ChatI18n = CHAT_I18N_TR;\n\nexport class ChatDrawer {\n private root: HTMLElement;\n private messagesEl: HTMLElement;\n private inputEl: HTMLTextAreaElement;\n private sendBtn: HTMLButtonElement;\n private i18n: ChatI18n;\n private onSend: (text: string, attachment?: File) => void;\n private _panelEl: HTMLElement;\n private _panelVisible = false;\n private _panelCollapsed = false;\n private _panelForceExpanded = false;\n private _dividerEl: HTMLElement;\n private _onPanelToggle: (() => void) | undefined = undefined;\n private _pendingAttachment: File | null = null;\n private _fileInput: HTMLInputElement;\n private _previewStrip: HTMLElement;\n private _previewName: HTMLElement;\n private _onAttachment: ((file: File) => void) | undefined = undefined;\n private _onRollback: ((messageId: string) => void) | undefined = undefined;\n private _onLinkClick: ((url: string) => void) | undefined = undefined;\n private _pillsEl: HTMLElement;\n private _kvkkSlot: HTMLElement;\n private _panelTopBar: PanelTopBar;\n private _userScrolledUp = false;\n private _scrollLockedUntil = 0;\n private _inputChipsEl: HTMLElement;\n private _thumbnailsColumn: ThumbnailsColumn;\n private _thinkingSteps: string[] = [];\n private _firstBotMessageIds: Set<string> = new Set();\n\n constructor(container: HTMLElement, options: ChatDrawerOptions) {\n this.i18n = { ...DEFAULT_I18N, ...options.i18n };\n this.onSend = options.onSend;\n if (options.onPanelToggle !== undefined) {\n this._onPanelToggle = options.onPanelToggle;\n }\n if (options.onAttachment !== undefined) {\n this._onAttachment = options.onAttachment;\n }\n if (options.onRollback !== undefined) {\n this._onRollback = options.onRollback;\n }\n if (options.onLinkClick !== undefined) {\n this._onLinkClick = options.onLinkClick;\n }\n\n this.root = document.createElement('div');\n this.root.className = 'gengage-chat-drawer';\n this.root.setAttribute('role', 'dialog');\n this.root.setAttribute('aria-label', this.i18n.headerTitle ?? 'Chat');\n this.root.setAttribute('aria-modal', 'false');\n\n // Header — branded dark bar\n const header = document.createElement('div');\n header.className = 'gengage-chat-header';\n\n const headerLeft = document.createElement('div');\n headerLeft.className = 'gengage-chat-header-left';\n\n if (options.headerAvatarUrl) {\n const avatar = document.createElement('img');\n avatar.className = 'gengage-chat-header-avatar';\n avatar.src = options.headerAvatarUrl;\n avatar.alt = options.headerTitle ?? 'Assistant';\n headerLeft.appendChild(avatar);\n }\n\n const headerInfo = document.createElement('div');\n headerInfo.className = 'gengage-chat-header-info';\n\n const titleRow = document.createElement('div');\n titleRow.className = 'gengage-chat-header-title-row';\n const title = document.createElement('span');\n title.className = 'gengage-chat-header-title';\n title.textContent = options.headerTitle ?? this.i18n.headerTitle ?? 'Gengage Asistan\\u0131';\n titleRow.appendChild(title);\n\n if (options.headerBadge) {\n const badge = document.createElement('span');\n badge.className = 'gengage-chat-header-badge';\n badge.textContent = options.headerBadge;\n titleRow.appendChild(badge);\n }\n headerInfo.appendChild(titleRow);\n\n const powered = document.createElement('a');\n powered.className = 'gengage-chat-header-powered';\n powered.href = 'https://gengage.ai/';\n powered.target = '_blank';\n powered.rel = 'noopener noreferrer';\n powered.innerHTML = `<svg viewBox=\"0 0 16 16\" fill=\"currentColor\"><path d=\"M8 1a7 7 0 110 14A7 7 0 018 1zm0 1.5a5.5 5.5 0 100 11 5.5 5.5 0 000-11zM7 4.5h2v4H7v-4zm0 5h2v2H7v-2z\"/></svg>Powered by Gengage`;\n headerInfo.appendChild(powered);\n\n headerLeft.appendChild(headerInfo);\n header.appendChild(headerLeft);\n\n const headerRight = document.createElement('div');\n headerRight.className = 'gengage-chat-header-right';\n\n // Cart link (optional — production shows cart icon → /sepetim)\n if (options.headerCartUrl) {\n const cartLink = document.createElement('a');\n cartLink.className = 'gengage-chat-header-btn';\n cartLink.href = options.headerCartUrl;\n cartLink.target = '_blank';\n cartLink.rel = 'noopener noreferrer';\n cartLink.setAttribute('aria-label', 'Sepetim');\n cartLink.innerHTML = `<svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"9\" cy=\"21\" r=\"1\"/><circle cx=\"20\" cy=\"21\" r=\"1\"/><path d=\"M1 1h4l2.68 13.39a2 2 0 0 0 2 1.61h9.72a2 2 0 0 0 2-1.61L23 6H6\"/></svg>`;\n headerRight.appendChild(cartLink);\n }\n\n // Favorites heart toggle (optional)\n if (options.headerFavoritesToggle) {\n const favBtn = document.createElement('button');\n favBtn.className = 'gengage-chat-header-btn';\n favBtn.type = 'button';\n favBtn.setAttribute('aria-label', 'Favorilerim');\n favBtn.innerHTML = `<svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z\"/></svg>`;\n favBtn.addEventListener('click', () => options.onFavoritesClick?.());\n headerRight.appendChild(favBtn);\n }\n\n const closeBtn = document.createElement('button');\n closeBtn.className = 'gengage-chat-close';\n closeBtn.type = 'button';\n closeBtn.setAttribute('aria-label', this.i18n.closeButton);\n closeBtn.innerHTML = `<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\"><line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/></svg>`;\n closeBtn.addEventListener('click', options.onClose);\n headerRight.appendChild(closeBtn);\n header.appendChild(headerRight);\n\n // Body: flex container for panel + conversation\n const body = document.createElement('div');\n body.className = 'gengage-chat-body';\n\n // Panel (hidden by default)\n this._panelEl = document.createElement('div');\n this._panelEl.className = 'gengage-chat-panel';\n\n // Panel top bar (navigation)\n this._panelTopBar = new PanelTopBar({\n onBack: () => options.onPanelBack?.(),\n onForward: () => options.onPanelForward?.(),\n });\n this._panelEl.appendChild(this._panelTopBar.getElement());\n\n body.appendChild(this._panelEl);\n\n // Divider between panel and conversation\n this._dividerEl = document.createElement('div');\n this._dividerEl.className = 'gengage-chat-panel-divider gengage-chat-panel-divider--hidden';\n this._dividerEl.setAttribute('role', 'separator');\n this._dividerEl.setAttribute('aria-label', 'Toggle panel');\n const chevron = document.createElement('button');\n chevron.className = 'gengage-chat-panel-divider-toggle';\n chevron.type = 'button';\n chevron.setAttribute('aria-label', 'Toggle panel');\n chevron.textContent = '\\u00BB'; // » (collapse right)\n chevron.addEventListener('click', () => {\n this.togglePanel();\n this._onPanelToggle?.();\n });\n this._dividerEl.appendChild(chevron);\n body.appendChild(this._dividerEl);\n\n // Conversation wrapper — header lives inside so it only spans chat width\n const conversation = document.createElement('div');\n conversation.className = 'gengage-chat-conversation';\n conversation.appendChild(header);\n\n // KVKK banner slot (inserted above messages)\n this._kvkkSlot = document.createElement('div');\n this._kvkkSlot.className = 'gengage-chat-kvkk-slot';\n conversation.appendChild(this._kvkkSlot);\n\n // Messages area\n this.messagesEl = document.createElement('div');\n this.messagesEl.className = 'gengage-chat-messages';\n this.messagesEl.setAttribute('role', 'log');\n this.messagesEl.setAttribute('aria-live', 'polite');\n this.messagesEl.setAttribute('aria-label', 'Chat messages');\n\n // Track user scroll position to avoid auto-scrolling when reading history\n this.messagesEl.addEventListener(\n 'scroll',\n () => {\n const { scrollTop, scrollHeight, clientHeight } = this.messagesEl;\n this._userScrolledUp = scrollHeight - scrollTop - clientHeight > 10;\n },\n { passive: true },\n );\n\n conversation.appendChild(this.messagesEl);\n\n // Thumbnails column (right edge of panel — quick-scroll shortcuts for search results)\n this._thumbnailsColumn = new ThumbnailsColumn({\n onThumbnailClick: (threadId) => options.onThumbnailClick?.(threadId),\n });\n this._panelEl.appendChild(this._thumbnailsColumn.getElement());\n\n // Suggestion pills row (between messages and input)\n this._pillsEl = document.createElement('div');\n this._pillsEl.className = 'gengage-chat-pills';\n this._pillsEl.setAttribute('role', 'toolbar');\n this._pillsEl.setAttribute('aria-label', 'Suggestions');\n this._pillsEl.style.display = 'none';\n\n const pillsScroll = document.createElement('div');\n pillsScroll.className = 'gengage-chat-pills-scroll';\n this._pillsEl.appendChild(pillsScroll);\n\n const pillsArrow = document.createElement('button');\n pillsArrow.className = 'gengage-chat-pills-arrow';\n pillsArrow.type = 'button';\n pillsArrow.setAttribute('aria-label', 'More suggestions');\n pillsArrow.textContent = '\\u203A'; // › single right-pointing angle\n pillsArrow.addEventListener('click', () => {\n pillsScroll.scrollBy({ left: 150, behavior: 'smooth' });\n });\n this._pillsEl.appendChild(pillsArrow);\n\n // Hide arrow when fully scrolled\n pillsScroll.addEventListener(\n 'scroll',\n () => {\n const atEnd = pillsScroll.scrollLeft + pillsScroll.clientWidth >= pillsScroll.scrollWidth - 4;\n pillsArrow.style.display = atEnd ? 'none' : '';\n },\n { passive: true },\n );\n\n conversation.appendChild(this._pillsEl);\n\n // Input-area chips (compact chips above input for search/info/review/similar)\n this._inputChipsEl = document.createElement('div');\n this._inputChipsEl.className = 'gengage-chat-input-chips';\n this._inputChipsEl.style.display = 'none';\n conversation.appendChild(this._inputChipsEl);\n\n // Input area\n const inputArea = document.createElement('div');\n inputArea.className = 'gengage-chat-input-area';\n\n this.inputEl = document.createElement('textarea');\n this.inputEl.className = 'gengage-chat-input';\n this.inputEl.rows = 1;\n this.inputEl.placeholder = this.i18n.inputPlaceholder;\n\n // Auto-expand on desktop as user types (capped at 120px)\n this.inputEl.addEventListener('input', () => {\n this.inputEl.style.height = 'auto';\n this.inputEl.style.height = `${Math.min(this.inputEl.scrollHeight, 120)}px`;\n });\n\n // Enter submits; Shift+Enter inserts newline on desktop only\n this.inputEl.addEventListener('keydown', (e) => {\n if (e.key === 'Enter') {\n const isMobile = window.innerWidth < 768;\n if (isMobile || !e.shiftKey) {\n e.preventDefault();\n this._submit();\n }\n // else: Shift+Enter on desktop → natural newline (no preventDefault)\n }\n });\n\n this.inputEl.addEventListener('paste', (e) => {\n const file = e.clipboardData?.files[0];\n if (file && file.type.startsWith('image/')) {\n e.preventDefault();\n if (this._onAttachment) {\n this._onAttachment(file);\n } else {\n this.stageAttachment(file);\n }\n }\n });\n\n // Hidden file input\n this._fileInput = document.createElement('input');\n this._fileInput.type = 'file';\n this._fileInput.accept = 'image/jpeg,image/png,image/webp';\n this._fileInput.style.display = 'none';\n this._fileInput.addEventListener('change', () => {\n const file = this._fileInput.files?.[0];\n if (file) {\n if (this._onAttachment) {\n this._onAttachment(file);\n } else {\n this.stageAttachment(file);\n }\n }\n this._fileInput.value = '';\n });\n\n // Attach button with camera SVG\n const attachBtn = document.createElement('button');\n attachBtn.className = 'gengage-chat-attach-btn';\n attachBtn.type = 'button';\n attachBtn.setAttribute('aria-label', this.i18n.attachImageButton);\n attachBtn.innerHTML = `<svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z\"/><circle cx=\"12\" cy=\"13\" r=\"4\"/></svg>`;\n attachBtn.addEventListener('click', () => this._fileInput.click());\n\n // Attachment preview strip (hidden by default)\n this._previewStrip = document.createElement('div');\n this._previewStrip.className = 'gengage-chat-attachment-preview gengage-chat-attachment-preview--hidden';\n const previewThumb = document.createElement('img');\n previewThumb.className = 'gengage-chat-attachment-preview-thumb';\n previewThumb.alt = '';\n this._previewName = document.createElement('span');\n this._previewName.className = 'gengage-chat-attachment-name';\n const removeBtn = document.createElement('button');\n removeBtn.className = 'gengage-chat-attachment-remove';\n removeBtn.type = 'button';\n removeBtn.setAttribute('aria-label', this.i18n.removeAttachmentButton);\n removeBtn.textContent = '\\u00D7'; // multiplication sign (x)\n removeBtn.addEventListener('click', () => this.clearAttachment());\n this._previewStrip.appendChild(previewThumb);\n this._previewStrip.appendChild(this._previewName);\n this._previewStrip.appendChild(removeBtn);\n\n this.sendBtn = document.createElement('button');\n this.sendBtn.className = 'gengage-chat-send';\n this.sendBtn.type = 'button';\n this.sendBtn.setAttribute('aria-label', this.i18n.sendButton);\n this.sendBtn.innerHTML = `<svg viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M2.01 21L23 12 2.01 3 2 10l15 2-15 2z\"/></svg>`;\n this.sendBtn.addEventListener('click', () => this._submit());\n\n // Drag-and-drop on input area\n inputArea.addEventListener('dragover', (e) => {\n e.preventDefault();\n inputArea.classList.add('gengage-chat-input-area--dragover');\n });\n inputArea.addEventListener('dragleave', () => {\n inputArea.classList.remove('gengage-chat-input-area--dragover');\n });\n inputArea.addEventListener('drop', (e) => {\n e.preventDefault();\n inputArea.classList.remove('gengage-chat-input-area--dragover');\n const file = e.dataTransfer?.files[0];\n if (file) {\n if (this._onAttachment) {\n this._onAttachment(file);\n } else {\n this.stageAttachment(file);\n }\n }\n });\n\n // Build pill container: [camera] [input] [send]\n const pill = document.createElement('div');\n pill.className = 'gengage-chat-input-pill';\n pill.appendChild(attachBtn);\n pill.appendChild(this.inputEl);\n pill.appendChild(this.sendBtn);\n\n inputArea.appendChild(this._previewStrip);\n inputArea.appendChild(this._fileInput);\n inputArea.appendChild(pill);\n conversation.appendChild(inputArea);\n\n body.appendChild(conversation);\n this.root.appendChild(body);\n\n // Footer\n const footer = document.createElement('div');\n footer.className = 'gengage-chat-footer';\n footer.textContent = this.i18n.poweredBy;\n this.root.appendChild(footer);\n\n // Escape key to close drawer\n this.root.addEventListener('keydown', (e) => {\n if (e.key === 'Escape') {\n options.onClose();\n }\n });\n\n this._trapFocus();\n\n container.appendChild(this.root);\n }\n\n addMessage(message: ChatMessage): void {\n const bubble = document.createElement('div');\n bubble.className = `gengage-chat-bubble gengage-chat-bubble--${message.role}`;\n bubble.dataset['messageId'] = message.id;\n if (message.threadId) {\n bubble.dataset['threadId'] = message.threadId;\n }\n\n if (this._firstBotMessageIds.has(message.id)) {\n bubble.classList.add('gengage-chat-bubble--first');\n }\n\n if (message.attachment) {\n const thumbEl = document.createElement('img');\n thumbEl.className = 'gengage-chat-attachment-thumb';\n thumbEl.src = URL.createObjectURL(message.attachment);\n thumbEl.alt = message.attachment.name;\n bubble.insertBefore(thumbEl, bubble.firstChild);\n }\n\n if (message.content) {\n const text = document.createElement('div');\n text.className = 'gengage-chat-bubble-text';\n if (message.role === 'assistant') {\n text.innerHTML = sanitizeHtml(message.content);\n // Intercept all links in bot HTML\n if (this._onLinkClick) {\n const links = text.querySelectorAll('a[href]');\n for (const link of links) {\n link.addEventListener('click', (e) => {\n e.preventDefault();\n const href = link.getAttribute('href');\n if (href) {\n this._onLinkClick?.(href);\n }\n });\n }\n }\n } else {\n text.textContent = message.content; // User messages: always safe textContent\n }\n bubble.appendChild(text);\n }\n\n // Add rollback button to user message bubbles\n if (message.role === 'user' && this._onRollback) {\n const rollbackBtn = document.createElement('button');\n rollbackBtn.className = 'gengage-chat-rollback-btn';\n rollbackBtn.type = 'button';\n rollbackBtn.setAttribute('aria-label', 'Rollback to this message');\n rollbackBtn.innerHTML = `<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"1 4 1 10 7 10\"/><path d=\"M3.51 15a9 9 0 1 0 2.13-9.36L1 10\"/></svg>`;\n rollbackBtn.addEventListener('click', (e) => {\n e.stopPropagation();\n this._onRollback?.(message.id);\n });\n bubble.appendChild(rollbackBtn);\n }\n\n this.messagesEl.appendChild(bubble);\n this._scrollToBottom(message.role === 'user');\n }\n\n showTypingIndicator(searchText?: string): void {\n this.removeTypingIndicator();\n const container = document.createElement('div');\n container.className = 'gengage-chat-typing';\n container.dataset['typing'] = 'true';\n\n if (this._thinkingSteps.length > 0) {\n // Render accumulated thinking steps\n this._renderThinkingStepsInto(container);\n } else {\n // Default 3-dot animation\n const indicator = document.createElement('div');\n indicator.className = 'gengage-chat-typing-dots';\n for (let i = 0; i < 3; i++) indicator.appendChild(document.createElement('span'));\n container.appendChild(indicator);\n if (searchText) {\n const sparkle = document.createElement('span');\n sparkle.className = 'gengage-chat-typing-sparkle';\n sparkle.textContent = '\\u2728'; // sparkle\n container.appendChild(sparkle);\n\n const text = document.createElement('span');\n text.className = 'gengage-chat-typing-text';\n text.textContent = searchText;\n container.appendChild(text);\n }\n }\n\n this.messagesEl.appendChild(container);\n this._scrollToBottom(true);\n }\n\n /** Accumulate a new thinking step (shown as a checklist in the typing indicator). */\n addThinkingStep(text: string): void {\n this._thinkingSteps.push(text);\n this._renderThinkingSteps();\n }\n\n removeTypingIndicator(): void {\n const existing = this.messagesEl.querySelector('.gengage-chat-typing');\n existing?.remove();\n this._thinkingSteps = [];\n }\n\n showError(message?: string): void {\n const errEl = document.createElement('div');\n errEl.className = 'gengage-chat-error';\n errEl.textContent = message ?? this.i18n.errorMessage;\n this.messagesEl.appendChild(errEl);\n this._scrollToBottom(true);\n }\n\n clearMessages(): void {\n this.messagesEl.innerHTML = '';\n }\n\n /** Replace suggestion pills. Pass empty array to hide. */\n setPills(\n pills: Array<{ label: string; onAction: () => void; icon?: string; image?: string; description?: string }>,\n ): void {\n const scroll = this._pillsEl.querySelector('.gengage-chat-pills-scroll');\n if (!scroll) return;\n while (scroll.firstChild) scroll.removeChild(scroll.firstChild);\n\n if (pills.length === 0) {\n this._pillsEl.style.display = 'none';\n return;\n }\n\n this._pillsEl.style.display = '';\n for (const pill of pills) {\n const btn = document.createElement('button');\n btn.className = pill.image ? 'gengage-chat-pill gengage-chat-pill--rich' : 'gengage-chat-pill';\n btn.type = 'button';\n\n if (pill.icon) {\n const svgHtml = SUGGESTED_ACTION_ICONS[pill.icon];\n if (svgHtml) {\n const iconSpan = document.createElement('span');\n iconSpan.className = 'gengage-chat-pill-icon';\n iconSpan.innerHTML = svgHtml;\n btn.appendChild(iconSpan);\n }\n }\n\n if (pill.image) {\n const img = document.createElement('img');\n img.className = 'gengage-chat-pill-img';\n img.src = pill.image;\n img.alt = '';\n btn.appendChild(img);\n }\n\n const textWrap = document.createElement('span');\n textWrap.className = 'gengage-chat-pill-text';\n textWrap.textContent = pill.label;\n btn.appendChild(textWrap);\n\n if (pill.description) {\n const desc = document.createElement('span');\n desc.className = 'gengage-chat-pill-desc';\n desc.textContent = pill.description;\n btn.appendChild(desc);\n }\n\n btn.addEventListener('click', () => pill.onAction());\n scroll.appendChild(btn);\n }\n\n // Show/hide arrow based on overflow\n const arrow = this._pillsEl.querySelector('.gengage-chat-pills-arrow') as HTMLElement | null;\n if (arrow) {\n requestAnimationFrame(() => {\n arrow.style.display = scroll.scrollWidth > scroll.clientWidth ? '' : 'none';\n });\n }\n }\n\n focusInput(): void {\n this.inputEl.focus();\n }\n\n showKvkkBanner(html: string, onDismiss: () => void): void {\n this._kvkkSlot.innerHTML = '';\n const banner = createKvkkBanner({ htmlContent: html, onDismiss });\n this._kvkkSlot.appendChild(banner);\n }\n\n hideKvkkBanner(): void {\n this._kvkkSlot.innerHTML = '';\n }\n\n getElement(): HTMLElement {\n return this.root;\n }\n\n /** Stage a file attachment for sending. Shows preview. */\n stageAttachment(file: File): void {\n this._pendingAttachment = file;\n this._previewName.textContent = file.name;\n const thumb = this._previewStrip.querySelector('.gengage-chat-attachment-preview-thumb') as HTMLImageElement;\n if (thumb) {\n thumb.src = URL.createObjectURL(file);\n }\n this._previewStrip.classList.remove('gengage-chat-attachment-preview--hidden');\n }\n\n /** Remove the staged attachment and hide preview. */\n clearAttachment(): void {\n const thumb = this._previewStrip.querySelector('.gengage-chat-attachment-preview-thumb') as HTMLImageElement;\n if (thumb?.src) {\n URL.revokeObjectURL(thumb.src);\n thumb.src = '';\n }\n this._pendingAttachment = null;\n this._previewStrip.classList.add('gengage-chat-attachment-preview--hidden');\n }\n\n /** Get the currently staged attachment file, or null. */\n getPendingAttachment(): File | null {\n return this._pendingAttachment;\n }\n\n /** Replace panel content and show the panel. */\n setPanelContent(el: HTMLElement): void {\n this._panelEl.innerHTML = '';\n this._panelEl.appendChild(this._panelTopBar.getElement());\n this._panelEl.appendChild(el);\n this._dividerEl.classList.remove('gengage-chat-panel-divider--hidden');\n if (!this._panelVisible) {\n this._panelVisible = true;\n this._panelEl.classList.add('gengage-chat-panel--visible');\n this.root.classList.add('gengage-chat-drawer--with-panel');\n }\n if (this._panelCollapsed) {\n this._panelEl.classList.add('gengage-chat-panel--collapsed');\n }\n }\n\n /** Append content to the panel without replacing existing content. */\n appendPanelContent(el: HTMLElement): void {\n this._panelEl.appendChild(el);\n this._dividerEl.classList.remove('gengage-chat-panel-divider--hidden');\n if (!this._panelVisible) {\n this._panelVisible = true;\n this._panelEl.classList.add('gengage-chat-panel--visible');\n this.root.classList.add('gengage-chat-drawer--with-panel');\n }\n }\n\n /** Return the panel element's content child (after topbar), or null. */\n getPanelContentElement(): HTMLElement | null {\n const children = this._panelEl.children;\n for (let i = 0; i < children.length; i++) {\n const child = children[i] as HTMLElement;\n if (\n child.classList.contains('gengage-chat-panel-topbar') ||\n child.classList.contains('gengage-chat-thumbnails-column')\n ) {\n continue;\n }\n return child;\n }\n return null;\n }\n\n /** Whether the panel is currently visible and has rendered content (beyond the topbar). */\n hasPanelContent(): boolean {\n // The topbar is always present; actual content starts at childElementCount > 1\n return this._panelVisible && this._panelEl.childElementCount > 1;\n }\n\n /** Whether panel currently shows loading skeleton blocks. */\n isPanelLoading(): boolean {\n return this._panelEl.querySelector('.gengage-chat-panel-skeleton') !== null;\n }\n\n /** Show loading skeleton in the panel. Variant depends on contentType hint. */\n showPanelLoading(contentType?: string): void {\n this._dividerEl.classList.remove('gengage-chat-panel-divider--hidden');\n this._panelEl.innerHTML = '';\n this._panelEl.appendChild(this._panelTopBar.getElement());\n const skeleton = document.createElement('div');\n skeleton.className = 'gengage-chat-panel-skeleton';\n\n switch (contentType) {\n case 'productDetails': {\n // Tall image placeholder + text lines\n const imgBlock = document.createElement('div');\n imgBlock.className = 'gengage-chat-panel-skeleton-block gengage-chat-panel-skeleton-block--image';\n skeleton.appendChild(imgBlock);\n for (let i = 0; i < 3; i++) {\n const line = document.createElement('div');\n line.className = 'gengage-chat-panel-skeleton-block gengage-chat-panel-skeleton-block--text';\n skeleton.appendChild(line);\n }\n break;\n }\n case 'productList':\n case 'groupList': {\n // 2x3 grid of small card placeholders\n const grid = document.createElement('div');\n grid.className = 'gengage-chat-panel-skeleton-grid';\n for (let i = 0; i < 6; i++) {\n const card = document.createElement('div');\n card.className = 'gengage-chat-panel-skeleton-block gengage-chat-panel-skeleton-block--card';\n grid.appendChild(card);\n }\n skeleton.appendChild(grid);\n break;\n }\n case 'comparisonTable': {\n // Table-like rows\n for (let i = 0; i < 4; i++) {\n const row = document.createElement('div');\n row.className = 'gengage-chat-panel-skeleton-block gengage-chat-panel-skeleton-block--row';\n skeleton.appendChild(row);\n }\n break;\n }\n default: {\n // Generic: 3 blocks (existing behavior)\n for (let i = 0; i < 3; i++) {\n const block = document.createElement('div');\n block.className = 'gengage-chat-panel-skeleton-block';\n skeleton.appendChild(block);\n }\n break;\n }\n }\n\n this._panelEl.appendChild(skeleton);\n if (!this._panelVisible) {\n this._panelVisible = true;\n this._panelEl.classList.add('gengage-chat-panel--visible');\n this.root.classList.add('gengage-chat-drawer--with-panel');\n }\n }\n\n /** Update the panel top bar navigation state. */\n updatePanelTopBar(canBack: boolean, canForward: boolean, title: string): void {\n this._panelTopBar.update(canBack, canForward, title);\n }\n\n /** Hide the panel and clear its content. In force-expanded mode, keeps panel visible. */\n clearPanel(): void {\n this._panelEl.innerHTML = '';\n this._panelEl.appendChild(this._panelTopBar.getElement());\n if (this._panelForceExpanded) {\n // Keep panel visible but empty in expanded mode\n return;\n }\n this._panelVisible = false;\n this._panelCollapsed = false;\n this._panelEl.classList.remove('gengage-chat-panel--visible', 'gengage-chat-panel--collapsed');\n this.root.classList.remove('gengage-chat-drawer--with-panel');\n this._dividerEl.classList.add('gengage-chat-panel-divider--hidden');\n }\n\n /** Force the panel to stay expanded (panelMode: 'expanded'). Hides the divider toggle. */\n setForceExpanded(): void {\n this._panelForceExpanded = true;\n this._panelCollapsed = false;\n this._panelEl.classList.remove('gengage-chat-panel--collapsed');\n // Show panel immediately even if empty\n if (!this._panelVisible) {\n this._panelVisible = true;\n this._panelEl.classList.add('gengage-chat-panel--visible');\n this.root.classList.add('gengage-chat-drawer--with-panel');\n }\n // Hide divider toggle — user cannot collapse\n this._dividerEl.classList.add('gengage-chat-panel-divider--hidden');\n }\n\n /** Toggle panel between collapsed and expanded. */\n togglePanel(): void {\n if (this._panelForceExpanded) return;\n this.setPanelCollapsed(!this._panelCollapsed);\n }\n\n /** Whether the panel is currently collapsed by the user. */\n isPanelCollapsed(): boolean {\n return this._panelCollapsed;\n }\n\n /** Programmatically set panel collapsed state. */\n setPanelCollapsed(collapsed: boolean): void {\n if (this._panelForceExpanded) return;\n this._panelCollapsed = collapsed;\n if (collapsed) {\n this._panelEl.classList.add('gengage-chat-panel--collapsed');\n } else {\n this._panelEl.classList.remove('gengage-chat-panel--collapsed');\n }\n const chevronBtn = this._dividerEl.querySelector('.gengage-chat-panel-divider-toggle');\n if (chevronBtn) {\n chevronBtn.textContent = collapsed ? '\\u00AB' : '\\u00BB'; // « (expand left) or » (collapse right)\n }\n }\n\n /** Save panel collapsed state to sessionStorage. */\n persistPanelState(accountId: string): void {\n try {\n const key = `gengage:panel:${accountId}`;\n if (this._panelCollapsed) {\n sessionStorage.setItem(key, 'collapsed');\n } else {\n sessionStorage.removeItem(key);\n }\n } catch {\n // sessionStorage may be unavailable in restricted environments\n }\n }\n\n /** Restore panel collapsed state from sessionStorage. */\n restorePanelState(accountId: string): void {\n try {\n const key = `gengage:panel:${accountId}`;\n if (sessionStorage.getItem(key) === 'collapsed') {\n this._panelCollapsed = true;\n }\n } catch {\n // sessionStorage may be unavailable in restricted environments\n }\n }\n\n /** Re-render thinking steps inside the existing typing indicator container. */\n private _renderThinkingSteps(): void {\n const existing = this.messagesEl.querySelector('[data-typing=\"true\"]') as HTMLElement | null;\n if (!existing) {\n // No typing indicator yet — create one with the steps\n this.showTypingIndicator();\n return;\n }\n // Clear and re-render\n existing.innerHTML = '';\n this._renderThinkingStepsInto(existing);\n this._scrollToBottom(false);\n }\n\n /** Render the accumulated thinking-step checklist into a container element. */\n private _renderThinkingStepsInto(container: HTMLElement): void {\n const list = document.createElement('div');\n list.className = 'gengage-chat-thinking-steps';\n\n for (let i = 0; i < this._thinkingSteps.length; i++) {\n const step = document.createElement('div');\n step.className = 'gengage-chat-thinking-step';\n\n const marker = document.createElement('span');\n marker.className = 'gengage-chat-thinking-step-marker';\n\n if (i < this._thinkingSteps.length - 1) {\n // Completed step\n marker.textContent = '\\u2713'; // ✓\n marker.classList.add('gengage-chat-thinking-step-marker--done');\n } else {\n // Current step (last one — still in progress)\n marker.textContent = '\\u25CF'; // ●\n marker.classList.add('gengage-chat-thinking-step-marker--active');\n }\n\n step.appendChild(marker);\n\n const text = document.createElement('span');\n text.className = 'gengage-chat-thinking-step-text';\n text.textContent = this._thinkingSteps[i]!;\n step.appendChild(text);\n\n list.appendChild(step);\n }\n\n container.appendChild(list);\n }\n\n private _trapFocus(): void {\n this.root.addEventListener('keydown', (e) => {\n if (e.key !== 'Tab') return;\n const focusable = this.root.querySelectorAll<HTMLElement>(\n 'button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])',\n );\n if (focusable.length === 0) return;\n const first = focusable[0];\n const last = focusable[focusable.length - 1];\n if (!first || !last) return;\n\n // Use getRootNode() to resolve activeElement inside Shadow DOM\n const rootNode = this.root.getRootNode();\n const active = (rootNode as ShadowRoot).activeElement ?? document.activeElement;\n\n if (e.shiftKey) {\n if (active === first) {\n e.preventDefault();\n last.focus();\n }\n } else {\n if (active === last) {\n e.preventDefault();\n first.focus();\n }\n }\n });\n }\n\n private _submit(): void {\n const text = this.inputEl.value.trim();\n const attachment = this._pendingAttachment;\n if (!text && !attachment) return;\n this.onSend(text, attachment ?? undefined);\n this.inputEl.value = '';\n this.inputEl.style.height = 'auto'; // Reset textarea height after submit\n this.clearAttachment();\n }\n\n /** Lock auto-scroll for 500ms after session history restore to prevent visual jump. */\n lockScrollForRestore(): void {\n this._scrollLockedUntil = Date.now() + 500;\n }\n\n /** Scroll to bottom only if user hasn't scrolled up. Force=true always scrolls. */\n private _scrollToBottom(force = false): void {\n if (!force && this._userScrolledUp) return;\n if (!force && Date.now() < this._scrollLockedUntil) return;\n requestAnimationFrame(() => {\n this.messagesEl.scrollTop = this.messagesEl.scrollHeight;\n this._userScrolledUp = false;\n });\n }\n\n /** Public method for typewriter ticks — scrolls only if user is near bottom. */\n scrollToBottomIfNeeded(): void {\n this._scrollToBottom(false);\n }\n\n /** Mark a message as the first bot message in its thread (for special styling). */\n markFirstBotMessage(messageId: string): void {\n this._firstBotMessageIds.add(messageId);\n const bubble = this.messagesEl.querySelector(`[data-message-id=\"${CSS.escape(messageId)}\"]`);\n if (bubble) {\n bubble.classList.add('gengage-chat-bubble--first');\n }\n }\n\n /** Scroll to the first message of the last thread (for restore targeting). */\n scrollToLastThread(): void {\n const allBubbles = this.messagesEl.querySelectorAll('[data-thread-id]');\n if (allBubbles.length === 0) {\n this._scrollToBottom(true);\n return;\n }\n const lastThreadId = allBubbles[allBubbles.length - 1]!.getAttribute('data-thread-id');\n if (!lastThreadId) {\n this._scrollToBottom(true);\n return;\n }\n const target = this.messagesEl.querySelector(`[data-thread-id=\"${CSS.escape(lastThreadId)}\"]`);\n if (target) {\n requestAnimationFrame(() => {\n target.scrollIntoView({ block: 'start', behavior: 'auto' });\n this._userScrolledUp = false;\n });\n } else {\n this._scrollToBottom(true);\n }\n }\n\n /** Set compact input-area chips (search/info/review shortcuts above input). */\n setInputAreaChips(chips: Array<{ label: string; onAction: () => void; icon?: string }>): void {\n this._inputChipsEl.innerHTML = '';\n if (chips.length === 0) {\n this._inputChipsEl.style.display = 'none';\n return;\n }\n this._inputChipsEl.style.display = '';\n for (const chip of chips) {\n const btn = document.createElement('button');\n btn.className = 'gengage-chat-input-chip';\n btn.type = 'button';\n\n // Icon (SVG from icon map)\n if (chip.icon) {\n const svgHtml = SUGGESTED_ACTION_ICONS[chip.icon];\n if (svgHtml) {\n const iconSpan = document.createElement('span');\n iconSpan.className = 'gengage-chat-input-chip-icon';\n iconSpan.innerHTML = svgHtml;\n btn.appendChild(iconSpan);\n }\n }\n\n const label = document.createElement('span');\n label.textContent = chip.label;\n btn.appendChild(label);\n\n btn.addEventListener('click', () => chip.onAction());\n this._inputChipsEl.appendChild(btn);\n }\n }\n\n /** Clear input-area chips. */\n clearInputAreaChips(): void {\n this._inputChipsEl.innerHTML = '';\n this._inputChipsEl.style.display = 'none';\n }\n\n setThumbnails(entries: ThumbnailEntry[]): void {\n this._thumbnailsColumn.setEntries(entries);\n if (entries.length > 0) {\n this._thumbnailsColumn.show();\n } else {\n this._thumbnailsColumn.hide();\n }\n }\n\n hideThumbnails(): void {\n this._thumbnailsColumn.hide();\n }\n}\n","export interface LauncherOptions {\n onClick: () => void;\n svgMarkup?: string;\n ariaLabel?: string;\n hideMobile?: boolean;\n mobileBreakpoint?: number;\n tooltip?: string;\n}\n\n/**\n * Result of createLauncher — the container wraps the button and exposes\n * content-area slots where the QNA widget or host page can inject engagement\n * actions (buying-hesitation questions, \"Find Similar\" buttons, etc.).\n */\nexport interface LauncherElements {\n /** Outer container — append this to the DOM. */\n container: HTMLElement;\n /** The clickable FAB button. */\n button: HTMLButtonElement;\n /** Slot above the button (primary QNA actions). */\n contentArea: HTMLElement;\n /** Slot below the button (secondary content). */\n contentAreaBottom: HTMLElement;\n}\n\nconst DEFAULT_SVG = `<svg width=\"28\" height=\"28\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect x=\"3\" y=\"7\" width=\"18\" height=\"13\" rx=\"3\" fill=\"currentColor\" opacity=\"0.15\"/>\n <rect x=\"3\" y=\"7\" width=\"18\" height=\"13\" rx=\"3\" stroke=\"currentColor\" stroke-width=\"1.5\"/>\n <circle cx=\"9\" cy=\"13\" r=\"1.5\" fill=\"currentColor\"/>\n <circle cx=\"15\" cy=\"13\" r=\"1.5\" fill=\"currentColor\"/>\n <path d=\"M9.5 17C10.3 17.6 11.1 18 12 18C12.9 18 13.7 17.6 14.5 17\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\"/>\n <path d=\"M12 7V4\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\"/>\n <circle cx=\"12\" cy=\"3\" r=\"1\" fill=\"currentColor\"/>\n <path d=\"M1 12V14\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\"/>\n <path d=\"M23 12V14\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\"/>\n</svg>`;\n\nexport function createLauncher(options: LauncherOptions): LauncherElements {\n // Container holds content areas + button\n const container = document.createElement('div');\n container.className = 'gengage-chat-launcher-container';\n\n // Content area above button (QNA actions, buying-hesitation questions)\n const contentArea = document.createElement('div');\n contentArea.className = 'gengage-chat-launcher-content-area';\n container.appendChild(contentArea);\n\n // The FAB button\n const button = document.createElement('button');\n button.className = 'gengage-chat-launcher';\n button.type = 'button';\n button.setAttribute('aria-label', options.ariaLabel ?? 'Open chat');\n button.innerHTML = options.svgMarkup ?? DEFAULT_SVG;\n\n if (options.tooltip !== undefined) {\n const tooltipEl = document.createElement('span');\n tooltipEl.className = 'gengage-chat-launcher-tooltip';\n tooltipEl.textContent = options.tooltip;\n button.appendChild(tooltipEl);\n }\n\n if (options.hideMobile) {\n container.dataset['hideMobile'] = '1';\n }\n if (options.mobileBreakpoint !== undefined) {\n container.dataset['mobileBreakpoint'] = String(options.mobileBreakpoint);\n }\n\n button.addEventListener('click', options.onClick);\n container.appendChild(button);\n\n // Content area below button (secondary content)\n const contentAreaBottom = document.createElement('div');\n contentAreaBottom.className = 'gengage-chat-launcher-content-area-bottom';\n container.appendChild(contentAreaBottom);\n\n return { container, button, contentArea, contentAreaBottom };\n}\n","export interface ProactivePopupOptions {\n message: string;\n onAccept: () => void;\n onDismiss: () => void;\n /** Auto-dismiss after this many ms (default: 15000). 0 = never. */\n autoDismissMs?: number;\n /** Accept button label (default: \"Sohbete Başla\"). */\n acceptLabel?: string;\n}\n\nexport function createProactivePopup(options: ProactivePopupOptions): HTMLElement {\n const popup = document.createElement('div');\n popup.className = 'gengage-chat-proactive';\n\n const messageEl = document.createElement('p');\n messageEl.className = 'gengage-chat-proactive-message';\n messageEl.textContent = options.message;\n popup.appendChild(messageEl);\n\n const actions = document.createElement('div');\n actions.className = 'gengage-chat-proactive-actions';\n\n const acceptBtn = document.createElement('button');\n acceptBtn.className = 'gengage-chat-proactive-accept';\n acceptBtn.type = 'button';\n acceptBtn.textContent = options.acceptLabel ?? 'Sohbete Başla';\n acceptBtn.addEventListener('click', () => {\n popup.remove();\n options.onAccept();\n });\n actions.appendChild(acceptBtn);\n\n const dismissBtn = document.createElement('button');\n dismissBtn.className = 'gengage-chat-proactive-dismiss';\n dismissBtn.type = 'button';\n dismissBtn.textContent = '\\u00D7';\n dismissBtn.setAttribute('aria-label', 'Kapat');\n dismissBtn.addEventListener('click', () => {\n popup.remove();\n options.onDismiss();\n });\n popup.appendChild(dismissBtn);\n\n popup.appendChild(actions);\n\n // Auto-dismiss\n const timeout = options.autoDismissMs ?? 15000;\n if (timeout > 0) {\n setTimeout(() => {\n if (popup.parentElement) {\n popup.remove();\n options.onDismiss();\n }\n }, timeout);\n }\n\n // Animate in\n requestAnimationFrame(() => popup.classList.add('gengage-chat-proactive--visible'));\n\n return popup;\n}\n","/**\n * Tracks user activity signals (page views, idle, scroll depth) for\n * engagement analytics and proactive-agent triggering.\n */\n\nexport interface ActivityEvent {\n type: 'pageview' | 'idle' | 'scroll' | 'focus' | 'blur';\n timestamp: number;\n data?: Record<string, unknown>;\n}\n\nexport interface ActivityTrackerOptions {\n /** Idle threshold in ms (default: 30000). */\n idleThresholdMs?: number;\n /** Scroll depth granularity in percent (default: 25). */\n scrollGranularity?: number;\n /** Callback when an activity event fires. */\n onActivity?: (event: ActivityEvent) => void;\n}\n\nexport class ActivityTracker {\n private _idleTimer: ReturnType<typeof setTimeout> | null = null;\n private _idleThreshold: number;\n private _scrollGranularity: number;\n private _maxScrollDepth = 0;\n private _lastReportedDepth = 0;\n private _onActivity: ((event: ActivityEvent) => void) | null;\n private _listeners: Array<[EventTarget, string, EventListener]> = [];\n private _destroyed = false;\n\n constructor(options: ActivityTrackerOptions = {}) {\n this._idleThreshold = options.idleThresholdMs ?? 30000;\n this._scrollGranularity = options.scrollGranularity ?? 25;\n this._onActivity = options.onActivity ?? null;\n this._setup();\n }\n\n private _setup(): void {\n this._emit({ type: 'pageview', timestamp: Date.now() });\n this._resetIdleTimer();\n\n this._listen(window, 'scroll', () => this._onScroll(), { passive: true });\n this._listen(window, 'mousemove', () => this._resetIdleTimer(), { passive: true });\n this._listen(window, 'keydown', () => this._resetIdleTimer(), { passive: true });\n this._listen(window, 'touchstart', () => this._resetIdleTimer(), { passive: true });\n this._listen(document, 'visibilitychange', () => this._onVisibility());\n }\n\n private _listen(target: EventTarget, event: string, handler: EventListener, options?: AddEventListenerOptions): void {\n target.addEventListener(event, handler, options);\n this._listeners.push([target, event, handler]);\n }\n\n private _resetIdleTimer(): void {\n if (this._idleTimer) clearTimeout(this._idleTimer);\n this._idleTimer = setTimeout(() => {\n this._emit({ type: 'idle', timestamp: Date.now() });\n }, this._idleThreshold);\n }\n\n private _onScroll(): void {\n const scrollTop = window.scrollY || document.documentElement.scrollTop;\n const docHeight = Math.max(document.documentElement.scrollHeight - window.innerHeight, 1);\n const depth = Math.min(100, Math.round((scrollTop / docHeight) * 100));\n\n if (depth > this._maxScrollDepth) {\n this._maxScrollDepth = depth;\n }\n\n const bucket = Math.floor(depth / this._scrollGranularity) * this._scrollGranularity;\n if (bucket > this._lastReportedDepth) {\n this._lastReportedDepth = bucket;\n this._emit({\n type: 'scroll',\n timestamp: Date.now(),\n data: { depth: bucket },\n });\n }\n\n this._resetIdleTimer();\n }\n\n private _onVisibility(): void {\n if (document.hidden) {\n this._emit({ type: 'blur', timestamp: Date.now() });\n if (this._idleTimer) clearTimeout(this._idleTimer);\n } else {\n this._emit({ type: 'focus', timestamp: Date.now() });\n this._resetIdleTimer();\n }\n }\n\n private _emit(event: ActivityEvent): void {\n if (this._destroyed) return;\n this._onActivity?.(event);\n }\n\n /** Current max scroll depth reached (0-100). */\n get maxScrollDepth(): number {\n return this._maxScrollDepth;\n }\n\n destroy(): void {\n this._destroyed = true;\n if (this._idleTimer) clearTimeout(this._idleTimer);\n for (const [target, event, handler] of this._listeners) {\n target.removeEventListener(event, handler);\n }\n this._listeners = [];\n }\n}\n","/**\n * ComparisonTable — renders a product comparison table with recommended pick,\n * attribute rows, highlights, and optional special cases.\n *\n * XSS safety: All text is set via textContent. Image URLs are validated\n * for safe protocols before being assigned to img.src.\n */\n\nimport { sanitizeHtml } from '../../common/safe-html.js';\n\nconst SAFE_URL_PROTOCOLS = ['http:', 'https:'];\n\n/** Fallback display names for common Turkish e-commerce product attributes. */\nconst CRITERIA_DISPLAY_NAMES: Record<string, string> = {\n screen_size: 'Ekran Boyutu',\n weight: 'Ağırlık',\n battery_capacity: 'Batarya Kapasitesi',\n battery_life: 'Batarya Ömrü',\n storage: 'Depolama',\n memory: 'Bellek',\n ram: 'RAM',\n processor: 'İşlemci',\n camera: 'Kamera',\n resolution: 'Çözünürlük',\n display_type: 'Ekran Tipi',\n refresh_rate: 'Yenileme Hızı',\n color: 'Renk',\n material: 'Malzeme',\n dimensions: 'Boyutlar',\n warranty: 'Garanti',\n connectivity: 'Bağlantı',\n water_resistance: 'Su Dayanıklılığı',\n operating_system: 'İşletim Sistemi',\n brand: 'Marka',\n model: 'Model',\n price: 'Fiyat',\n energy_class: 'Enerji Sınıfı',\n noise_level: 'Gürültü Seviyesi',\n capacity: 'Kapasite',\n power: 'Güç',\n voltage: 'Voltaj',\n width: 'Genişlik',\n height: 'Yükseklik',\n depth: 'Derinlik',\n};\n\n/**\n * Map a raw criteria field name to a human-readable label.\n * Uses the Turkish fallback map first, then falls back to a simple\n * formatting heuristic (replace underscores, capitalize first letter).\n */\nexport function formatCriteriaName(rawName: string): string {\n return CRITERIA_DISPLAY_NAMES[rawName] ?? rawName.replace(/_/g, ' ').replace(/^\\w/, (c) => c.toUpperCase());\n}\n\nfunction isSafeImageUrl(url: string): boolean {\n try {\n const parsed = new URL(url);\n return SAFE_URL_PROTOCOLS.includes(parsed.protocol);\n } catch {\n return false;\n }\n}\n\nexport interface ComparisonProduct {\n sku: string;\n name: string;\n price: string;\n imageUrl?: string | undefined;\n rating?: number | undefined;\n reviewCount?: number | undefined;\n}\n\nexport interface ComparisonAttribute {\n label: string;\n values: string[];\n}\n\nexport interface ComparisonTableOptions {\n recommended: ComparisonProduct;\n products: ComparisonProduct[];\n attributes: ComparisonAttribute[];\n highlights: string[];\n specialCases?: string[] | undefined;\n onProductClick: (sku: string) => void;\n onAddToCart?: ((sku: string) => void) | undefined;\n recommendedText?: string | undefined;\n winnerHits?: Record<string, { positive?: string[]; negative?: string[] }> | undefined;\n productActions?: Record<string, { title: string; type: string; payload?: unknown }> | undefined;\n keyDifferencesHtml?: string | undefined;\n}\n\nexport function renderComparisonTable(options: ComparisonTableOptions): HTMLElement {\n const { recommended, products, attributes, highlights, specialCases, onProductClick } = options;\n\n const container = document.createElement('div');\n container.className = 'gengage-chat-comparison';\n\n // Heading\n const heading = document.createElement('h3');\n heading.className = 'gengage-chat-comparison-heading';\n heading.textContent = 'KARŞILAŞTIRMA SONUÇLARI';\n container.appendChild(heading);\n\n // Recommended card\n if (recommended) {\n const recCard = document.createElement('div');\n recCard.className = 'gengage-chat-comparison-recommended';\n\n const recLabel = document.createElement('div');\n recLabel.className = 'gengage-chat-comparison-recommended-label';\n recLabel.textContent = 'Önerilen Seçim';\n recCard.appendChild(recLabel);\n\n const recBody = document.createElement('div');\n recBody.className = 'gengage-chat-comparison-recommended-body';\n\n if (recommended.imageUrl && isSafeImageUrl(recommended.imageUrl)) {\n const img = document.createElement('img');\n img.src = recommended.imageUrl;\n img.alt = recommended.name;\n img.loading = 'lazy';\n recBody.appendChild(img);\n }\n\n const info = document.createElement('div');\n info.className = 'gengage-chat-comparison-recommended-info';\n const title = document.createElement('div');\n title.className = 'gengage-chat-comparison-recommended-title';\n title.textContent = recommended.name;\n info.appendChild(title);\n const price = document.createElement('div');\n price.className = 'gengage-chat-comparison-recommended-price';\n price.textContent = recommended.price;\n info.appendChild(price);\n recBody.appendChild(info);\n\n recBody.addEventListener('click', () => {\n onProductClick(recommended.sku);\n });\n recBody.style.cursor = 'pointer';\n\n recCard.appendChild(recBody);\n\n // Highlights\n if (highlights.length > 0) {\n const hlSection = document.createElement('div');\n hlSection.className = 'gengage-chat-comparison-highlights';\n const hlLabel = document.createElement('div');\n hlLabel.className = 'gengage-chat-comparison-highlights-label';\n hlLabel.textContent = 'Öne Çıkan Özellikler';\n hlSection.appendChild(hlLabel);\n const ul = document.createElement('ul');\n for (const hl of highlights) {\n const li = document.createElement('li');\n li.textContent = hl;\n ul.appendChild(li);\n }\n hlSection.appendChild(ul);\n recCard.appendChild(hlSection);\n }\n\n // Recommended choice explanation\n if (options.recommendedText) {\n const recExplanation = document.createElement('div');\n recExplanation.className = 'gengage-chat-comparison-recommended-text';\n recExplanation.textContent = options.recommendedText;\n recCard.appendChild(recExplanation);\n }\n\n container.appendChild(recCard);\n }\n\n // Key Differences section\n if (options.keyDifferencesHtml) {\n const kdSection = document.createElement('div');\n kdSection.className = 'gengage-chat-comparison-key-differences';\n const kdHeading = document.createElement('h4');\n kdHeading.textContent = 'Temel Farklar';\n kdSection.appendChild(kdHeading);\n const kdContent = document.createElement('div');\n kdContent.className = 'gengage-chat-comparison-key-differences-content';\n kdContent.innerHTML = sanitizeHtml(formatKeyDifferences(options.keyDifferencesHtml));\n kdSection.appendChild(kdContent);\n container.appendChild(kdSection);\n }\n\n // Special cases (expandable)\n if (specialCases && specialCases.length > 0) {\n const special = document.createElement('details');\n special.className = 'gengage-chat-comparison-special';\n const summary = document.createElement('summary');\n summary.textContent = 'Özel Durumlar İçin';\n special.appendChild(summary);\n const list = document.createElement('ul');\n for (const sc of specialCases) {\n const li = document.createElement('li');\n li.textContent = sc;\n list.appendChild(li);\n }\n special.appendChild(list);\n container.appendChild(special);\n }\n\n // Comparison table\n if (products.length > 0 && attributes.length > 0) {\n const table = document.createElement('table');\n table.className = 'gengage-chat-comparison-table';\n\n // Header row: empty cell + product columns\n const thead = document.createElement('thead');\n const headerRow = document.createElement('tr');\n const emptyTh = document.createElement('th');\n headerRow.appendChild(emptyTh);\n for (const product of products) {\n const th = document.createElement('th');\n if (product.sku === recommended?.sku) {\n th.className = 'gengage-chat-comparison-selected';\n }\n if (product.imageUrl && isSafeImageUrl(product.imageUrl)) {\n const img = document.createElement('img');\n img.src = product.imageUrl;\n img.alt = product.name;\n img.loading = 'lazy';\n th.appendChild(img);\n }\n const name = document.createElement('div');\n name.textContent = product.name;\n th.appendChild(name);\n const prc = document.createElement('div');\n prc.className = 'gengage-chat-comparison-table-price';\n prc.textContent = product.price;\n th.appendChild(prc);\n headerRow.appendChild(th);\n }\n thead.appendChild(headerRow);\n table.appendChild(thead);\n\n // Attribute rows\n const tbody = document.createElement('tbody');\n for (const attr of attributes) {\n const row = document.createElement('tr');\n const labelTd = document.createElement('td');\n labelTd.className = 'gengage-chat-comparison-label';\n labelTd.textContent = formatCriteriaName(attr.label);\n row.appendChild(labelTd);\n for (let i = 0; i < attr.values.length; i++) {\n const td = document.createElement('td');\n if (products[i]?.sku === recommended?.sku) {\n td.className = 'gengage-chat-comparison-selected';\n }\n td.textContent = attr.values[i] ?? '';\n row.appendChild(td);\n }\n tbody.appendChild(row);\n }\n table.appendChild(tbody);\n container.appendChild(table);\n }\n\n // View product buttons\n if (options.productActions) {\n const btnRow = document.createElement('div');\n btnRow.className = 'gengage-chat-comparison-product-actions';\n for (const product of products) {\n const action = options.productActions[product.sku];\n if (action) {\n const btn = document.createElement('button');\n btn.className = 'gengage-chat-comparison-view-btn';\n btn.type = 'button';\n btn.textContent = product.name;\n btn.addEventListener('click', () => onProductClick(product.sku));\n btnRow.appendChild(btn);\n }\n }\n if (btnRow.childElementCount > 0) {\n container.appendChild(btnRow);\n }\n }\n\n return container;\n}\n\nfunction formatKeyDifferences(text: string): string {\n const lines = text.split('\\n').filter((l) => l.trim());\n if (lines.length <= 1) return text;\n return '<ul>' + lines.map((l) => `<li>${l.trim()}</li>`).join('') + '</ul>';\n}\n","/**\n * ReviewHighlights — renders review summary cards with filter tabs and sentiment tag pills.\n *\n * Production parity: filter tabs (Tümü/Olumlu/Olumsuz), sentiment pill summary,\n * and the existing per-review cards with tone coloring.\n *\n * All text is set via textContent — no innerHTML, no XSS surface.\n */\n\nimport type { UIElement } from '../../common/types.js';\n\ninterface ReviewItem {\n review_class?: string;\n review_text?: string;\n review_rating?: string | number;\n review_tag?: string;\n}\n\nexport function renderReviewHighlights(element: UIElement): HTMLElement {\n const container = document.createElement('div');\n container.className = 'gengage-chat-review-highlights';\n\n const reviews = element.props?.['reviews'];\n if (!Array.isArray(reviews) || reviews.length === 0) {\n const empty = document.createElement('div');\n empty.className = 'gengage-chat-review-empty';\n empty.textContent = 'Yorum özeti bulunamadı.';\n container.appendChild(empty);\n return container;\n }\n\n const items: ReviewItem[] = reviews.filter(\n (r): r is Record<string, unknown> => r !== null && typeof r === 'object',\n ) as ReviewItem[];\n\n // Count sentiments\n const counts = { all: items.length, positive: 0, negative: 0, neutral: 0 };\n for (const item of items) {\n if (item.review_class === 'positive') counts.positive++;\n else if (item.review_class === 'negative') counts.negative++;\n else counts.neutral++;\n }\n\n // Filter tabs\n const tabBar = document.createElement('div');\n tabBar.className = 'gengage-chat-review-tabs';\n\n const filters: Array<{ label: string; filter: string }> = [{ label: `Tümü (${counts.all})`, filter: 'all' }];\n if (counts.positive > 0) filters.push({ label: `Olumlu (${counts.positive})`, filter: 'positive' });\n if (counts.negative > 0) filters.push({ label: `Olumsuz (${counts.negative})`, filter: 'negative' });\n\n let activeFilter = 'all';\n\n const itemsContainer = document.createElement('div');\n itemsContainer.className = 'gengage-chat-review-items';\n\n function renderItems(): void {\n while (itemsContainer.firstChild) itemsContainer.removeChild(itemsContainer.firstChild);\n const filtered = activeFilter === 'all' ? items : items.filter((i) => i.review_class === activeFilter);\n for (const review of filtered) {\n const item = document.createElement('article');\n item.className = 'gengage-chat-review-item';\n const cls = review.review_class;\n if (cls === 'positive' || cls === 'negative' || cls === 'neutral') {\n item.dataset['tone'] = cls;\n }\n\n if (typeof review.review_tag === 'string' && review.review_tag.length > 0) {\n const tagEl = document.createElement('div');\n tagEl.className = 'gengage-chat-review-tag';\n tagEl.textContent = review.review_tag;\n item.appendChild(tagEl);\n }\n\n if (typeof review.review_text === 'string' && review.review_text.length > 0) {\n const textEl = document.createElement('div');\n textEl.className = 'gengage-chat-review-text';\n textEl.textContent = review.review_text;\n item.appendChild(textEl);\n }\n\n if (review.review_rating !== undefined && String(review.review_rating).length > 0) {\n const ratingEl = document.createElement('div');\n ratingEl.className = 'gengage-chat-review-rating';\n ratingEl.textContent = String(review.review_rating);\n item.appendChild(ratingEl);\n }\n\n itemsContainer.appendChild(item);\n }\n }\n\n for (const f of filters) {\n const tab = document.createElement('button');\n tab.className = 'gengage-chat-review-tab';\n tab.type = 'button';\n tab.textContent = f.label;\n if (f.filter === activeFilter) tab.classList.add('gengage-chat-review-tab--active');\n\n tab.addEventListener('click', () => {\n activeFilter = f.filter;\n for (const t of tabBar.querySelectorAll('.gengage-chat-review-tab')) {\n t.classList.toggle('gengage-chat-review-tab--active', t === tab);\n }\n renderItems();\n });\n tabBar.appendChild(tab);\n }\n\n container.appendChild(tabBar);\n\n // Sentiment tag pills (summary of unique tags with counts)\n const tagCounts = new Map<string, { count: number; sentiment: string }>();\n for (const item of items) {\n if (typeof item.review_tag === 'string' && item.review_tag.length > 0) {\n const existing = tagCounts.get(item.review_tag);\n if (existing) {\n existing.count++;\n } else {\n tagCounts.set(item.review_tag, { count: 1, sentiment: item.review_class ?? 'neutral' });\n }\n }\n }\n\n if (tagCounts.size > 0) {\n const pillsRow = document.createElement('div');\n pillsRow.className = 'gengage-chat-review-pills';\n for (const [tag, data] of tagCounts) {\n const pill = document.createElement('span');\n pill.className = 'gengage-chat-review-pill';\n pill.dataset['tone'] = data.sentiment;\n\n const icon = document.createElement('span');\n icon.className = 'gengage-chat-review-pill-icon';\n icon.textContent = data.sentiment === 'positive' ? '\\u2713' : data.sentiment === 'negative' ? '\\u2715' : '\\u25CF';\n pill.appendChild(icon);\n\n const tagText = document.createElement('span');\n tagText.textContent = tag;\n pill.appendChild(tagText);\n\n if (data.count > 1) {\n const badge = document.createElement('span');\n badge.className = 'gengage-chat-review-pill-count';\n badge.textContent = String(data.count);\n pill.appendChild(badge);\n }\n\n pillsRow.appendChild(pill);\n }\n container.appendChild(pillsRow);\n }\n\n renderItems();\n container.appendChild(itemsContainer);\n\n return container;\n}\n","/**\n * AI Top Picks renderer.\n *\n * Renders rich AI-curated product suggestion cards with:\n * - Winner card (vertical, primary border, badge, large image)\n * - Compact cards (horizontal, smaller)\n * - Sentiment label chips (green/red/gray)\n * - Expert quality scores, review quotes\n */\n\nimport type { UIElement, ActionPayload } from '../../common/types.js';\nimport type { ChatUISpecRenderContext } from '../types.js';\nimport { formatTurkishPrice } from './renderUISpec.js';\n\ninterface SentimentLabel {\n label: string;\n sentiment?: 'positive' | 'negative' | 'neutral';\n}\n\ninterface AITopPickItem {\n product: Record<string, unknown>;\n role?: string;\n reason?: string;\n labels?: SentimentLabel[];\n expertQualityScore?: number;\n reviewHighlight?: string;\n action?: ActionPayload;\n}\n\nconst ROLE_LABELS: Record<string, string> = {\n winner: 'roleWinner',\n best_value: 'roleBestValue',\n best_alternative: 'roleBestAlternative',\n};\n\nfunction getRoleLabel(role: string | undefined, i18n: ChatUISpecRenderContext['i18n']): string | null {\n if (!role || !i18n) return null;\n const key = ROLE_LABELS[role];\n if (!key) return role;\n return (i18n as Record<string, string>)[key] ?? role;\n}\n\nexport function renderAITopPicks(element: UIElement, ctx: ChatUISpecRenderContext): HTMLElement {\n const container = document.createElement('div');\n container.className = 'gengage-chat-ai-top-picks';\n\n const suggestions = (element.props?.['suggestions'] ?? []) as AITopPickItem[];\n if (suggestions.length === 0) return container;\n\n // Title\n const title = document.createElement('h3');\n title.className = 'gengage-chat-ai-top-picks-title';\n title.textContent = ctx.i18n?.aiTopPicksTitle ?? 'Top Picks';\n container.appendChild(title);\n\n const cardsWrap = document.createElement('div');\n cardsWrap.className = 'gengage-chat-ai-top-picks-cards';\n\n for (let i = 0; i < suggestions.length; i++) {\n const suggestion = suggestions[i]!;\n const isWinner = suggestion.role === 'winner' || i === 0;\n const card = isWinner ? renderTopPickCard(suggestion, ctx) : renderCompactCard(suggestion, ctx);\n cardsWrap.appendChild(card);\n }\n\n container.appendChild(cardsWrap);\n return container;\n}\n\nfunction renderTopPickCard(item: AITopPickItem, ctx: ChatUISpecRenderContext): HTMLElement {\n const card = document.createElement('div');\n card.className = 'gengage-chat-ai-toppick-card gengage-chat-ai-toppick-card--winner';\n\n // Badge\n const badge = document.createElement('span');\n badge.className = 'gengage-chat-ai-toppick-badge';\n badge.textContent = getRoleLabel(item.role, ctx.i18n) ?? ctx.i18n?.roleWinner ?? 'TOP MATCH';\n card.appendChild(badge);\n\n const product = item.product;\n\n // Discount badge\n const discountPercent = product['discountPercent'] as number | undefined;\n if (typeof discountPercent === 'number' && discountPercent > 0) {\n const discountBadge = document.createElement('span');\n discountBadge.className = 'gengage-chat-ai-toppick-discount-badge';\n discountBadge.textContent = `%${discountPercent}`;\n card.appendChild(discountBadge);\n }\n\n // Image\n const imageUrl = product['imageUrl'] as string | undefined;\n if (imageUrl) {\n const img = document.createElement('img');\n img.className = 'gengage-chat-ai-toppick-img';\n img.src = imageUrl;\n img.alt = (product['name'] as string) ?? '';\n card.appendChild(img);\n }\n\n // Body\n const body = document.createElement('div');\n body.className = 'gengage-chat-ai-toppick-body';\n\n const name = product['name'] as string | undefined;\n if (name) {\n const nameEl = document.createElement('div');\n nameEl.className = 'gengage-chat-ai-toppick-name';\n nameEl.textContent = name;\n body.appendChild(nameEl);\n }\n\n // Reason text\n if (item.reason) {\n const reasonEl = document.createElement('div');\n reasonEl.className = 'gengage-chat-ai-toppick-reason';\n reasonEl.textContent = item.reason;\n body.appendChild(reasonEl);\n }\n\n // Sentiment chips\n if (item.labels && item.labels.length > 0) {\n body.appendChild(renderSentimentChips(item.labels));\n }\n\n // Expert quality score\n if (typeof item.expertQualityScore === 'number') {\n const score = document.createElement('div');\n score.className = 'gengage-chat-ai-toppick-score';\n score.textContent = `${item.expertQualityScore}/10`;\n body.appendChild(score);\n }\n\n // Review highlight quote\n if (item.reviewHighlight) {\n const review = document.createElement('blockquote');\n review.className = 'gengage-chat-ai-toppick-review';\n review.textContent = item.reviewHighlight;\n body.appendChild(review);\n }\n\n // Price\n const price = product['price'] as string | undefined;\n const originalPrice = product['originalPrice'] as string | undefined;\n if (price) {\n const priceRow = document.createElement('div');\n priceRow.className = 'gengage-chat-ai-toppick-price';\n if (originalPrice && originalPrice !== price) {\n const orig = document.createElement('span');\n orig.className = 'gengage-chat-ai-toppick-original-price';\n orig.textContent = formatTurkishPrice(originalPrice);\n priceRow.appendChild(orig);\n priceRow.appendChild(document.createTextNode(' '));\n }\n const current = document.createElement('span');\n current.textContent = formatTurkishPrice(price);\n priceRow.appendChild(current);\n body.appendChild(priceRow);\n }\n\n card.appendChild(body);\n\n // CTA button\n if (item.action) {\n const sku = (product['sku'] as string) ?? null;\n\n // Spinner overlay (hidden by default)\n const spinner = document.createElement('div');\n spinner.className = 'gengage-chat-ai-toppick-spinner';\n spinner.style.display = sku && ctx.topPicksLoadingSku === sku ? '' : 'none';\n card.appendChild(spinner);\n\n const cta = document.createElement('button');\n cta.className = 'gengage-chat-ai-toppick-cta';\n cta.type = 'button';\n cta.textContent = ctx.i18n?.viewDetails ?? 'View Details';\n cta.addEventListener('click', () => {\n if (sku) spinner.style.display = '';\n ctx.onAction(item.action!);\n });\n card.appendChild(cta);\n }\n\n return card;\n}\n\nfunction renderCompactCard(item: AITopPickItem, ctx: ChatUISpecRenderContext): HTMLElement {\n const card = document.createElement('div');\n card.className = 'gengage-chat-ai-toppick-card gengage-chat-ai-toppick-card--compact';\n\n const product = item.product;\n\n // Discount badge\n const discountPercent = product['discountPercent'] as number | undefined;\n if (typeof discountPercent === 'number' && discountPercent > 0) {\n const discountBadge = document.createElement('span');\n discountBadge.className = 'gengage-chat-ai-toppick-discount-badge';\n discountBadge.textContent = `%${discountPercent}`;\n card.appendChild(discountBadge);\n }\n\n // Image\n const imageUrl = product['imageUrl'] as string | undefined;\n if (imageUrl) {\n const img = document.createElement('img');\n img.className = 'gengage-chat-ai-toppick-img';\n img.src = imageUrl;\n img.alt = (product['name'] as string) ?? '';\n card.appendChild(img);\n }\n\n // Body\n const body = document.createElement('div');\n body.className = 'gengage-chat-ai-toppick-body';\n\n // Role label\n const roleLabel = getRoleLabel(item.role, ctx.i18n);\n if (roleLabel) {\n const roleEl = document.createElement('div');\n roleEl.className = 'gengage-chat-ai-toppick-role';\n roleEl.textContent = roleLabel;\n body.appendChild(roleEl);\n }\n\n const name = product['name'] as string | undefined;\n if (name) {\n const nameEl = document.createElement('div');\n nameEl.className = 'gengage-chat-ai-toppick-name';\n nameEl.textContent = name;\n body.appendChild(nameEl);\n }\n\n // Reason text\n if (item.reason) {\n const reasonEl = document.createElement('div');\n reasonEl.className = 'gengage-chat-ai-toppick-reason';\n reasonEl.textContent = item.reason;\n body.appendChild(reasonEl);\n }\n\n // Sentiment chips\n if (item.labels && item.labels.length > 0) {\n body.appendChild(renderSentimentChips(item.labels));\n }\n\n // Price\n const price = product['price'] as string | undefined;\n if (price) {\n const priceEl = document.createElement('div');\n priceEl.className = 'gengage-chat-ai-toppick-price';\n priceEl.textContent = formatTurkishPrice(price);\n body.appendChild(priceEl);\n }\n\n card.appendChild(body);\n\n // CTA\n if (item.action) {\n const sku = (product['sku'] as string) ?? null;\n\n // Spinner overlay (hidden by default)\n const spinner = document.createElement('div');\n spinner.className = 'gengage-chat-ai-toppick-spinner';\n spinner.style.display = sku && ctx.topPicksLoadingSku === sku ? '' : 'none';\n card.appendChild(spinner);\n\n const cta = document.createElement('button');\n cta.className = 'gengage-chat-ai-toppick-cta';\n cta.type = 'button';\n cta.textContent = ctx.i18n?.viewDetails ?? 'View Details';\n cta.addEventListener('click', () => {\n if (sku) spinner.style.display = '';\n ctx.onAction(item.action!);\n });\n card.appendChild(cta);\n }\n\n return card;\n}\n\nfunction renderSentimentChips(labels: SentimentLabel[]): HTMLElement {\n const container = document.createElement('div');\n container.className = 'gengage-chat-ai-toppick-labels';\n for (const label of labels) {\n const chip = document.createElement('span');\n chip.className = 'gengage-chat-ai-toppick-label';\n chip.dataset['sentiment'] = label.sentiment ?? 'neutral';\n chip.textContent = label.label;\n container.appendChild(chip);\n }\n return container;\n}\n","/**\n * Grounding Review Card renderer.\n *\n * Renders a clickable card for review grounding data with title,\n * review count, and a CTA arrow. The entire card is clickable.\n *\n * XSS safety: All text is set via textContent. No innerHTML.\n */\n\nimport type { UIElement, ActionPayload } from '../../common/types.js';\nimport type { ChatUISpecRenderContext } from '../types.js';\n\nexport function renderGroundingReviewCard(element: UIElement, ctx: ChatUISpecRenderContext): HTMLElement {\n const container = document.createElement('div');\n container.className = 'gengage-chat-grounding-review';\n\n const props = element.props ?? {};\n const title = props['title'] as string | undefined;\n const reviewCount = props['reviewCount'] as string | undefined;\n const action = props['action'] as ActionPayload | undefined;\n const ctaLabel = ctx.i18n?.groundingReviewCta ?? 'Yorumları Oku';\n\n // Icon\n const icon = document.createElement('span');\n icon.className = 'gengage-chat-grounding-review-icon';\n icon.textContent = '\\u{1F4CB}'; // clipboard\n container.appendChild(icon);\n\n const body = document.createElement('div');\n body.className = 'gengage-chat-grounding-review-body';\n\n // Title\n const titleEl = document.createElement('div');\n titleEl.className = 'gengage-chat-grounding-review-title';\n titleEl.textContent = title ?? 'M\\u00fc\\u015fteri Yorumlar\\u0131';\n body.appendChild(titleEl);\n\n // Subtitle (review count)\n if (reviewCount) {\n const subtitle = document.createElement('div');\n subtitle.className = 'gengage-chat-grounding-review-subtitle';\n subtitle.textContent = `${reviewCount} yorum mevcut`;\n body.appendChild(subtitle);\n }\n\n container.appendChild(body);\n\n // CTA arrow\n const cta = document.createElement('span');\n cta.className = 'gengage-chat-grounding-review-cta';\n cta.textContent = `${ctaLabel} \\u2192`;\n container.appendChild(cta);\n\n // Make entire card clickable\n if (action) {\n container.style.cursor = 'pointer';\n container.addEventListener('click', () => ctx.onAction(action));\n }\n\n return container;\n}\n","/**\n * AI Grouping Cards renderer.\n *\n * Desktop: compact card with image, name, and labels.\n * Mobile: simple button list with arrow prefix (images hidden via CSS).\n *\n * XSS safety: All text is set via textContent. Image URLs are validated\n * for safe protocols. No innerHTML.\n */\n\nimport type { UIElement, ActionPayload } from '../../common/types.js';\nimport type { ChatUISpecRenderContext } from '../types.js';\n\nconst SAFE_URL_PROTOCOLS = ['http:', 'https:'];\n\nfunction isSafeImageUrl(url: string): boolean {\n try {\n return SAFE_URL_PROTOCOLS.includes(new URL(url).protocol);\n } catch {\n return false;\n }\n}\n\ninterface GroupingEntry {\n name: string;\n image?: string;\n description?: string;\n labels?: string[];\n action: ActionPayload;\n}\n\nexport function renderAIGroupingCards(element: UIElement, ctx: ChatUISpecRenderContext): HTMLElement {\n const container = document.createElement('div');\n container.className = 'gengage-chat-grouping-cards';\n\n const entries = (element.props?.['entries'] ?? []) as GroupingEntry[];\n if (entries.length === 0) return container;\n\n for (const entry of entries) {\n const card = document.createElement('div');\n card.className = 'gengage-chat-grouping-card';\n card.style.cursor = 'pointer';\n card.addEventListener('click', () => ctx.onAction(entry.action));\n\n // Image (20x20 on desktop, hidden on mobile via CSS)\n if (entry.image && isSafeImageUrl(entry.image)) {\n const img = document.createElement('img');\n img.className = 'gengage-chat-grouping-card-img';\n img.src = entry.image;\n img.alt = entry.name;\n img.width = 20;\n img.height = 20;\n card.appendChild(img);\n }\n\n const body = document.createElement('div');\n body.className = 'gengage-chat-grouping-card-body';\n\n const nameEl = document.createElement('span');\n nameEl.className = 'gengage-chat-grouping-card-name';\n nameEl.textContent = entry.name;\n body.appendChild(nameEl);\n\n if (entry.description) {\n const desc = document.createElement('span');\n desc.className = 'gengage-chat-grouping-card-desc';\n desc.textContent = entry.description;\n body.appendChild(desc);\n }\n\n if (entry.labels && entry.labels.length > 0) {\n const labelsEl = document.createElement('span');\n labelsEl.className = 'gengage-chat-grouping-card-labels';\n labelsEl.textContent = entry.labels.slice(0, 3).join(' \\u00B7 ');\n body.appendChild(labelsEl);\n }\n\n card.appendChild(body);\n\n // Mobile prefix arrow (shown via CSS only on mobile)\n const arrow = document.createElement('span');\n arrow.className = 'gengage-chat-grouping-card-arrow';\n arrow.textContent = '\\u21B3';\n card.insertBefore(arrow, card.firstChild);\n\n container.appendChild(card);\n }\n\n return container;\n}\n","/**\n * AI Suggested Search Cards renderer.\n *\n * Cards with image, short_name, detailed_user_message, and why_different.\n * Clicking a card dispatches the associated action.\n *\n * XSS safety: All text is set via textContent. Image URLs are validated\n * for safe protocols. No innerHTML.\n */\n\nimport type { UIElement, ActionPayload } from '../../common/types.js';\nimport type { ChatUISpecRenderContext } from '../types.js';\n\nconst SAFE_URL_PROTOCOLS = ['http:', 'https:'];\n\nfunction isSafeImageUrl(url: string): boolean {\n try {\n return SAFE_URL_PROTOCOLS.includes(new URL(url).protocol);\n } catch {\n return false;\n }\n}\n\ninterface SuggestedSearchEntry {\n shortName: string;\n detailedMessage?: string;\n whyDifferent?: string;\n image?: string;\n action: ActionPayload;\n}\n\nexport function renderAISuggestedSearchCards(element: UIElement, ctx: ChatUISpecRenderContext): HTMLElement {\n const container = document.createElement('div');\n container.className = 'gengage-chat-suggested-search-cards';\n\n const entries = (element.props?.['entries'] ?? []) as SuggestedSearchEntry[];\n if (entries.length === 0) return container;\n\n for (const entry of entries) {\n const card = document.createElement('div');\n card.className = 'gengage-chat-suggested-search-card';\n card.style.cursor = 'pointer';\n card.addEventListener('click', () => ctx.onAction(entry.action));\n\n // Image (40x40)\n if (entry.image && isSafeImageUrl(entry.image)) {\n const img = document.createElement('img');\n img.className = 'gengage-chat-suggested-search-card-img';\n img.src = entry.image;\n img.alt = entry.shortName;\n img.width = 40;\n img.height = 40;\n card.appendChild(img);\n }\n\n const body = document.createElement('div');\n body.className = 'gengage-chat-suggested-search-card-body';\n\n const nameEl = document.createElement('div');\n nameEl.className = 'gengage-chat-suggested-search-card-name';\n nameEl.textContent = entry.shortName;\n body.appendChild(nameEl);\n\n if (entry.detailedMessage) {\n const desc = document.createElement('div');\n desc.className = 'gengage-chat-suggested-search-card-desc';\n desc.textContent = entry.detailedMessage;\n body.appendChild(desc);\n }\n\n if (entry.whyDifferent) {\n const diff = document.createElement('div');\n diff.className = 'gengage-chat-suggested-search-card-diff';\n diff.textContent = entry.whyDifferent;\n body.appendChild(diff);\n }\n\n card.appendChild(body);\n container.appendChild(card);\n }\n\n return container;\n}\n","/**\n * Floating comparison button.\n *\n * Renders a fixed-position button at the bottom of the product grid wrapper\n * that appears when 2+ products are selected for comparison.\n * Click dispatches a `getComparisonTable` action with the selected SKUs.\n *\n * XSS safety: All text set via textContent.\n */\n\nimport type { ChatUISpecRenderContext } from '../types.js';\n\n/**\n * Creates a floating comparison button element.\n * Only meaningful when `selectedSkus.length >= 2`.\n *\n * @param selectedSkus - Array of selected product SKU strings\n * @param ctx - Render context with onAction and i18n\n * @returns The button element\n */\nexport function renderFloatingComparisonButton(selectedSkus: string[], ctx: ChatUISpecRenderContext): HTMLElement {\n const button = document.createElement('button');\n button.className = 'gengage-chat-comparison-floating-btn';\n button.type = 'button';\n\n const label = ctx.i18n?.compareSelected ?? 'Karşılaştır';\n button.textContent = `${label} (${selectedSkus.length})`;\n\n button.addEventListener('click', () => {\n ctx.onAction({\n title: label,\n type: 'getComparisonTable',\n payload: { sku_list: [...selectedSkus] },\n });\n });\n\n return button;\n}\n","/**\n * Renders a Pros & Cons list for a product.\n *\n * XSS safety: All text is set via textContent. No innerHTML.\n */\n\nexport function renderProsAndCons(element: { props?: Record<string, unknown> }): HTMLElement {\n const container = document.createElement('div');\n container.className = 'gengage-chat-pros-cons';\n\n const productName = element.props?.['productName'] as string | undefined;\n if (productName) {\n const heading = document.createElement('h4');\n heading.className = 'gengage-chat-pros-cons-heading';\n heading.textContent = productName;\n container.appendChild(heading);\n }\n\n const pros = element.props?.['pros'] as string[] | undefined;\n const cons = element.props?.['cons'] as string[] | undefined;\n\n if (pros && pros.length > 0) {\n const prosList = document.createElement('ul');\n prosList.className = 'gengage-chat-pros-cons-list';\n for (const pro of pros) {\n const li = document.createElement('li');\n li.className = 'gengage-chat-pros-cons-item';\n const icon = document.createElement('span');\n icon.className = 'gengage-chat-pros-cons-icon gengage-chat-pros-cons-icon--pro';\n icon.textContent = '\\u2713';\n li.appendChild(icon);\n const text = document.createElement('span');\n text.textContent = pro;\n li.appendChild(text);\n prosList.appendChild(li);\n }\n container.appendChild(prosList);\n }\n\n if (cons && cons.length > 0) {\n const consList = document.createElement('ul');\n consList.className = 'gengage-chat-pros-cons-list';\n for (const con of cons) {\n const li = document.createElement('li');\n li.className = 'gengage-chat-pros-cons-item';\n const icon = document.createElement('span');\n icon.className = 'gengage-chat-pros-cons-icon gengage-chat-pros-cons-icon--con';\n icon.textContent = '\\u2717';\n li.appendChild(icon);\n const text = document.createElement('span');\n text.textContent = con;\n li.appendChild(text);\n consList.appendChild(li);\n }\n container.appendChild(consList);\n }\n\n return container;\n}\n","/**\n * CategoriesContainer — renders grouped product lists with tab navigation\n * and optional filter tags.\n *\n * Backend sends `groupList` with `{ group_list: [{ group_name, product_list }], filter_tags }`.\n * The v1 adapter normalizes this into a CategoriesContainer UISpec element.\n *\n * XSS safety: All text is set via textContent. No innerHTML.\n */\n\nimport type { UIElement } from '../../common/types.js';\nimport type { ChatUISpecRenderContext } from '../types.js';\nimport type { NormalizedProduct } from '../../common/v1-protocol-adapter.js';\n\ninterface GroupData {\n groupName: string;\n products: NormalizedProduct[];\n}\n\ninterface FilterTagData {\n title: string;\n action?: { title: string; type: string; payload?: unknown };\n}\n\nexport function renderCategoriesContainer(element: UIElement, context: ChatUISpecRenderContext): HTMLElement {\n const groups = (element.props?.['groups'] as GroupData[] | undefined) ?? [];\n const filterTags = (element.props?.['filterTags'] as FilterTagData[] | undefined) ?? [];\n\n const container = document.createElement('div');\n container.className = 'gengage-chat-categories';\n\n if (groups.length === 0) return container;\n\n // Tab bar\n const tabBar = document.createElement('div');\n tabBar.className = 'gengage-chat-categories-tabs';\n\n const panels: HTMLElement[] = [];\n\n for (let i = 0; i < groups.length; i++) {\n const group = groups[i]!;\n\n // Tab button\n const tab = document.createElement('button');\n tab.className = 'gengage-chat-categories-tab';\n tab.type = 'button';\n if (i === 0) tab.classList.add('gengage-chat-categories-tab--active');\n tab.textContent = group.groupName;\n tab.addEventListener('click', () => {\n tabBar.querySelectorAll('.gengage-chat-categories-tab').forEach((t) => {\n t.classList.remove('gengage-chat-categories-tab--active');\n });\n tab.classList.add('gengage-chat-categories-tab--active');\n panels.forEach((p, pIdx) => {\n p.style.display = pIdx === i ? '' : 'none';\n });\n });\n tabBar.appendChild(tab);\n\n // Product grid panel\n const panel = document.createElement('div');\n panel.className = 'gengage-chat-categories-grid';\n if (i !== 0) panel.style.display = 'none';\n\n for (const product of group.products) {\n const card = renderCategoryProductCard(product, context);\n panel.appendChild(card);\n }\n\n panels.push(panel);\n }\n\n container.appendChild(tabBar);\n for (const panel of panels) container.appendChild(panel);\n\n // Filter tags\n if (filterTags.length > 0) {\n const tagsContainer = document.createElement('div');\n tagsContainer.className = 'gengage-chat-categories-filter-tags';\n\n for (const tag of filterTags) {\n const tagBtn = document.createElement('button');\n tagBtn.className = 'gengage-chat-categories-filter-tag';\n tagBtn.type = 'button';\n tagBtn.textContent = tag.title;\n if (tag.action) {\n tagBtn.addEventListener('click', () => {\n context.onAction(tag.action!);\n });\n }\n tagsContainer.appendChild(tagBtn);\n }\n\n container.appendChild(tagsContainer);\n }\n\n return container;\n}\n\nfunction renderCategoryProductCard(product: NormalizedProduct, ctx: ChatUISpecRenderContext): HTMLElement {\n const card = document.createElement('div');\n card.className = 'gengage-chat-product-card';\n\n if (product.imageUrl) {\n const img = document.createElement('img');\n img.className = 'gengage-chat-product-card-img';\n img.src = product.imageUrl;\n img.alt = product.name;\n card.appendChild(img);\n }\n\n const body = document.createElement('div');\n body.className = 'gengage-chat-product-card-body';\n\n const nameEl = document.createElement('div');\n nameEl.className = 'gengage-chat-product-card-name';\n nameEl.textContent = product.name;\n body.appendChild(nameEl);\n\n if (product.price) {\n const priceEl = document.createElement('div');\n priceEl.className = 'gengage-chat-product-card-price';\n priceEl.textContent = product.price;\n body.appendChild(priceEl);\n }\n\n card.appendChild(body);\n\n // Click → show product details\n if (ctx.onProductSelect) {\n card.style.cursor = 'pointer';\n card.addEventListener('click', () => {\n ctx.onProductSelect?.(product as unknown as Record<string, unknown>);\n });\n }\n\n return card;\n}\n","/**\n * Renders a json-render UISpec into DOM elements.\n *\n * XSS safety: All text is set via textContent. URLs are validated for safe protocols.\n * No innerHTML is used anywhere in this module.\n */\n\nimport type { UISpec, UIElement, ActionPayload } from '../../common/types.js';\nimport { renderUISpecWithRegistry } from '../../common/renderer/index.js';\nimport type { UISpecDomRegistry, UISpecDomUnknownRenderer } from '../../common/renderer/index.js';\nimport type { ChatUISpecRenderContext, ProductSortState } from '../types.js';\nimport { renderComparisonTable } from './ComparisonTable.js';\nimport type { ComparisonProduct, ComparisonAttribute } from './ComparisonTable.js';\nimport { renderReviewHighlights as renderReviewHighlightsComponent } from './ReviewHighlights.js';\nimport { renderAITopPicks } from './AITopPicks.js';\nimport { renderGroundingReviewCard } from './GroundingReviewCard.js';\nimport { renderAIGroupingCards } from './AIGroupingCards.js';\nimport { renderAISuggestedSearchCards } from './AISuggestedSearchCards.js';\nimport { renderFloatingComparisonButton } from './FloatingComparisonButton.js';\nimport { renderProsAndCons } from './ProsAndCons.js';\nimport { renderCategoriesContainer } from './CategoriesContainer.js';\n\nexport type UISpecRenderContext = ChatUISpecRenderContext;\n\nexport type ChatUISpecRegistry = UISpecDomRegistry<UISpecRenderContext>;\n\n/**\n * Formats a raw numeric price string into Turkish locale format.\n * Example: \"17990\" → \"17.990 TL\", \"17990.5\" → \"17.990,50 TL\"\n * Returns the input as-is if it's not a valid number.\n */\nexport function formatTurkishPrice(raw: string): string {\n const num = Number(raw);\n if (!Number.isFinite(num)) return raw;\n\n const fixed = num % 1 === 0 ? num.toFixed(0) : num.toFixed(2);\n const dotIdx = fixed.indexOf('.');\n const intPart = dotIdx === -1 ? fixed : fixed.slice(0, dotIdx);\n const decPart = dotIdx === -1 ? undefined : fixed.slice(dotIdx + 1);\n\n // Add dot thousands separators to integer part\n const withSeparators = intPart.replace(/\\B(?=(\\d{3})+(?!\\d))/g, '.');\n\n if (decPart !== undefined) {\n return `${withSeparators},${decPart} TL`;\n }\n return `${withSeparators} TL`;\n}\n\nconst SAFE_URL_PROTOCOLS = ['http:', 'https:', '/'];\n\nfunction isSafeUrl(url: string): boolean {\n if (url.startsWith('/')) return true;\n try {\n const parsed = new URL(url);\n return SAFE_URL_PROTOCOLS.includes(parsed.protocol);\n } catch {\n return false;\n }\n}\n\nfunction safeSetAttribute(el: HTMLElement, attr: string, value: string): void {\n if (attr === 'href' || attr === 'src') {\n if (!isSafeUrl(value)) return;\n }\n el.setAttribute(attr, value);\n}\n\nfunction isMobileViewport(): boolean {\n return window.innerWidth < 768;\n}\n\nconst DEFAULT_CHAT_UI_SPEC_REGISTRY: ChatUISpecRegistry = {\n ActionButtons: ({ element, context }) => renderActionButtons(element, context),\n ActionButton: ({ element, context }) => renderActionButton(element, context),\n ProductCard: ({ element, context }) => renderProductCard(element, context),\n ProductDetailsPanel: ({ element, context }) => renderProductDetailsPanel(element, context),\n ProductGrid: ({ element, spec, renderElement, context }) => renderProductGrid(element, spec, renderElement, context),\n ReviewHighlights: ({ element }) => renderReviewHighlightsComponent(element),\n ComparisonTable: ({ element, context }) => renderComparisonTableElement(element, context),\n AITopPicks: ({ element, context }) => renderAITopPicks(element, context),\n GroundingReviewCard: ({ element, context }) => renderGroundingReviewCard(element, context),\n AIGroupingCards: ({ element, context }) => renderAIGroupingCards(element, context),\n AISuggestedSearchCards: ({ element, context }) => renderAISuggestedSearchCards(element, context),\n ProsAndCons: ({ element }) => renderProsAndCons(element),\n CategoriesContainer: ({ element, context }) => renderCategoriesContainer(element, context),\n Divider: ({ element }) => renderDivider(element),\n};\n\nexport const defaultChatUnknownUISpecRenderer: UISpecDomUnknownRenderer<UISpecRenderContext> = ({\n element,\n renderElement,\n}) => {\n if (import.meta.env?.DEV) {\n console.warn(`[gengage] Unknown ui_spec component type: ${element.type}`);\n }\n if (!element.children || element.children.length === 0) {\n return null;\n }\n const wrapper = document.createElement('div');\n for (const childId of element.children) {\n const rendered = renderElement(childId);\n if (rendered) wrapper.appendChild(rendered);\n }\n return wrapper;\n};\n\nexport function createDefaultChatUISpecRegistry(): ChatUISpecRegistry {\n return { ...DEFAULT_CHAT_UI_SPEC_REGISTRY };\n}\n\nexport function renderUISpec(\n spec: UISpec,\n ctx: UISpecRenderContext,\n registry = DEFAULT_CHAT_UI_SPEC_REGISTRY,\n unknownRenderer: UISpecDomUnknownRenderer<UISpecRenderContext> = defaultChatUnknownUISpecRenderer,\n): HTMLElement {\n return renderUISpecWithRegistry({\n spec,\n context: ctx,\n registry,\n containerClassName: 'gengage-chat-uispec',\n unknownRenderer,\n });\n}\n\nfunction renderActionButtons(element: UIElement, ctx: UISpecRenderContext): HTMLElement {\n const container = document.createElement('div');\n container.className = 'gengage-chat-action-buttons';\n\n const buttons = element.props?.['buttons'] as Array<{ label: string; action: ActionPayload }> | undefined;\n\n if (buttons) {\n for (const btn of buttons) {\n const button = document.createElement('button');\n button.className = 'gengage-chat-action-btn';\n button.textContent = btn.label;\n button.addEventListener('click', () => ctx.onAction(btn.action));\n container.appendChild(button);\n }\n }\n\n return container;\n}\n\nfunction renderActionButton(element: UIElement, ctx: UISpecRenderContext): HTMLElement {\n const button = document.createElement('button');\n button.className = 'gengage-chat-action-btn';\n const label = element.props?.['label'];\n if (typeof label === 'string') button.textContent = label;\n const action = element.props?.['action'] as ActionPayload | undefined;\n if (action) {\n button.addEventListener('click', () => ctx.onAction(action));\n }\n return button;\n}\n\nfunction renderProductCard(element: UIElement, ctx: UISpecRenderContext): HTMLElement {\n const card = document.createElement('div');\n card.className = 'gengage-chat-product-card';\n\n // Product data may be nested under `product` prop (v1 adapter) or flat in props\n const product = (element.props?.['product'] ?? element.props) as Record<string, unknown> | undefined;\n if (!product) return card;\n\n // Make card clickable to show detail in panel\n if (ctx.onProductSelect) {\n card.style.cursor = 'pointer';\n card.addEventListener('click', (e) => {\n if ((e.target as HTMLElement).closest('.gengage-chat-product-card-atc')) return;\n if ((e.target as HTMLElement).closest('.gengage-chat-product-card-cta')) return;\n ctx.onProductSelect?.(product);\n });\n }\n\n const imageUrl = product['imageUrl'] as string | undefined;\n if (imageUrl && isSafeUrl(imageUrl)) {\n const imgWrapper = document.createElement('div');\n imgWrapper.className = 'gengage-chat-product-card-img-wrapper';\n\n const img = document.createElement('img');\n img.className = 'gengage-chat-product-card-img';\n safeSetAttribute(img, 'src', imageUrl);\n const name = product['name'] as string | undefined;\n if (name) img.alt = name;\n imgWrapper.appendChild(img);\n\n // Discount badge (top-left of image)\n const discountPercent = product['discountPercent'] as number | undefined;\n if (typeof discountPercent === 'number' && discountPercent > 0) {\n const badge = document.createElement('span');\n badge.className = 'gengage-chat-product-card-discount-badge';\n badge.textContent = `%${discountPercent}`;\n imgWrapper.appendChild(badge);\n }\n\n // \"Find Similar\" hover pill on image\n const findSimilarSku = product['sku'] as string | undefined;\n if (findSimilarSku) {\n const pill = document.createElement('button');\n pill.className = 'gengage-chat-find-similar-pill';\n pill.type = 'button';\n pill.textContent = ctx.i18n?.findSimilarLabel ?? 'Benzerlerini Bul';\n pill.addEventListener('click', (e) => {\n e.stopPropagation();\n ctx.onAction({\n title: ctx.i18n?.findSimilarLabel ?? 'Benzerlerini Bul',\n type: 'findSimilar',\n payload: { sku: findSimilarSku, ...(imageUrl ? { image_url: imageUrl } : {}) },\n });\n });\n imgWrapper.appendChild(pill);\n }\n\n // Favorite heart toggle\n const favSku = product['sku'] as string | undefined;\n if (favSku && ctx.onFavoriteToggle) {\n const heart = document.createElement('button');\n heart.className = 'gengage-chat-favorite-btn';\n heart.type = 'button';\n heart.setAttribute('aria-label', 'Favorilere ekle');\n const isFav = ctx.favoritedSkus?.has(favSku) ?? false;\n if (isFav) heart.classList.add('gengage-chat-favorite-btn--active');\n const svgFill = isFav ? 'currentColor' : 'none';\n heart.innerHTML = `<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"${svgFill}\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z\"/></svg>`;\n heart.addEventListener('click', (e) => {\n e.stopPropagation();\n heart.classList.toggle('gengage-chat-favorite-btn--active');\n const svg = heart.querySelector('svg');\n if (svg) {\n svg.setAttribute(\n 'fill',\n heart.classList.contains('gengage-chat-favorite-btn--active') ? 'currentColor' : 'none',\n );\n }\n ctx.onFavoriteToggle!(favSku, product);\n });\n imgWrapper.appendChild(heart);\n }\n\n card.appendChild(imgWrapper);\n }\n\n const body = document.createElement('div');\n body.className = 'gengage-chat-product-card-body';\n\n const brand = product['brand'] as string | undefined;\n if (brand) {\n const brandEl = document.createElement('div');\n brandEl.className = 'gengage-chat-product-card-brand';\n brandEl.textContent = brand;\n body.appendChild(brandEl);\n }\n\n const name = product['name'] as string | undefined;\n if (name) {\n const nameEl = document.createElement('div');\n nameEl.className = 'gengage-chat-product-card-name';\n nameEl.textContent = name;\n body.appendChild(nameEl);\n }\n\n const rating = product['rating'];\n const reviewCount = product['reviewCount'];\n if (typeof rating === 'number' && Number.isFinite(rating)) {\n const ratingRow = document.createElement('div');\n ratingRow.className = 'gengage-chat-product-card-rating';\n ratingRow.textContent = renderStarRating(rating);\n if (typeof reviewCount === 'number' && Number.isFinite(reviewCount)) {\n const count = document.createElement('span');\n count.className = 'gengage-chat-product-card-review-count';\n count.textContent = ` (${reviewCount})`;\n ratingRow.appendChild(count);\n }\n body.appendChild(ratingRow);\n }\n\n const price = product['price'] as string | undefined;\n const originalPrice = product['originalPrice'] as string | undefined;\n const priceAsync = product['price_async'] as boolean | undefined;\n\n if (priceAsync === true) {\n const priceRow = document.createElement('div');\n priceRow.className = 'gengage-chat-product-card-price';\n const skeleton = document.createElement('span');\n skeleton.className = 'gengage-chat-price-skeleton';\n priceRow.appendChild(skeleton);\n body.appendChild(priceRow);\n // Replace skeleton with actual price after delay\n setTimeout(() => {\n if (price) {\n skeleton.replaceWith(document.createTextNode(formatTurkishPrice(price)));\n } else {\n skeleton.remove();\n }\n }, 300);\n } else if (price) {\n const priceRow = document.createElement('div');\n priceRow.className = 'gengage-chat-product-card-price';\n if (originalPrice && originalPrice !== price) {\n const orig = document.createElement('span');\n orig.className = 'gengage-chat-product-card-original-price';\n orig.textContent = formatTurkishPrice(originalPrice);\n priceRow.appendChild(orig);\n priceRow.appendChild(document.createTextNode(' '));\n }\n const current = document.createElement('span');\n current.textContent = formatTurkishPrice(price);\n priceRow.appendChild(current);\n body.appendChild(priceRow);\n }\n\n // Stock indicator\n const inStock = product['inStock'];\n if (typeof inStock === 'boolean') {\n const stock = document.createElement('div');\n stock.className = `gengage-chat-product-card-stock ${inStock ? 'is-in-stock' : 'is-out-of-stock'}`;\n stock.textContent = inStock ? (ctx.i18n?.inStockLabel ?? 'Stokta') : (ctx.i18n?.outOfStockLabel ?? 'Tükendi');\n body.appendChild(stock);\n }\n\n // Promotion badges (e.g. \"Free Shipping\", \"Flash Sale\")\n const promotions = product['promotions'] as string[] | undefined;\n if (promotions && promotions.length > 0) {\n const promoBadges = document.createElement('div');\n promoBadges.className = 'gengage-chat-product-card-promos';\n for (const promo of promotions) {\n const badge = document.createElement('span');\n badge.className = 'gengage-chat-product-card-promo-badge';\n badge.textContent = promo;\n promoBadges.appendChild(badge);\n }\n body.appendChild(promoBadges);\n }\n\n card.appendChild(body);\n\n const url = product['url'] as string | undefined;\n const sku = product['sku'] as string | undefined;\n const action = element.props?.['action'] as ActionPayload | undefined;\n\n if (action) {\n const cta = document.createElement('button');\n cta.className = 'gengage-chat-product-card-cta';\n cta.type = 'button';\n cta.textContent = action.title || ctx.i18n?.productCtaLabel || 'Incele';\n cta.addEventListener('click', () => ctx.onAction(action));\n card.appendChild(cta);\n } else if (url && isSafeUrl(url)) {\n const cta = document.createElement('a');\n cta.className = 'gengage-chat-product-card-cta';\n safeSetAttribute(cta, 'href', url);\n safeSetAttribute(cta, 'target', '_blank');\n safeSetAttribute(cta, 'rel', 'noopener noreferrer');\n cta.textContent = ctx.i18n?.productCtaLabel ?? 'İncele';\n cta.addEventListener('click', (e) => {\n if (ctx.onProductClick && sku) {\n e.preventDefault();\n ctx.onProductClick({ sku, url });\n }\n });\n card.appendChild(cta);\n }\n\n // Add to cart icon-button (shown on search result cards when cartCode is available)\n const cartCode = product['cartCode'] as string | undefined;\n if (cartCode && sku) {\n const atcBtn = document.createElement('button');\n atcBtn.className = 'gengage-chat-product-card-atc';\n atcBtn.type = 'button';\n atcBtn.textContent = '\\uD83D\\uDED2'; // shopping cart emoji as icon\n atcBtn.title = 'Sepete Ekle';\n atcBtn.addEventListener('click', (e) => {\n e.stopPropagation();\n ctx.onAction({\n title: 'Sepete Ekle',\n type: 'addToCart',\n payload: { sku, cartCode, quantity: 1 },\n });\n });\n card.appendChild(atcBtn);\n }\n\n // Wrap with checkbox overlay when comparison select mode is active\n if (ctx.comparisonSelectMode && sku && ctx.onToggleComparisonSku) {\n const wrapper = document.createElement('div');\n wrapper.className = 'gengage-chat-comparison-select-wrapper';\n\n const checkbox = document.createElement('input');\n checkbox.type = 'checkbox';\n checkbox.className = 'gengage-chat-comparison-checkbox';\n checkbox.checked = ctx.comparisonSelectedSkus?.includes(sku) ?? false;\n checkbox.addEventListener('change', () => {\n ctx.onToggleComparisonSku?.(sku);\n });\n\n wrapper.appendChild(checkbox);\n wrapper.appendChild(card);\n return wrapper;\n }\n\n return card;\n}\n\nfunction renderStarRating(rating: number): string {\n const full = Math.floor(rating);\n const half = rating - full >= 0.5 ? 1 : 0;\n const empty = 5 - full - half;\n return '\\u2605'.repeat(full) + (half ? '\\u00BD' : '') + '\\u2606'.repeat(empty);\n}\n\nfunction renderProductDetailsPanel(element: UIElement, ctx: UISpecRenderContext): HTMLElement {\n const panel = document.createElement('article');\n panel.className = 'gengage-chat-product-details-panel';\n\n const product = (element.props?.['product'] ?? element.props) as Record<string, unknown> | undefined;\n if (!product) return panel;\n\n // Image gallery or single image\n const images = product['images'] as string[] | undefined;\n const imageUrl = product['imageUrl'] as string | undefined;\n\n const detailsSku = product['sku'] as string | undefined;\n\n if (images && images.length > 1) {\n // Gallery with thumbnails\n const media = document.createElement('div');\n media.className =\n 'gengage-chat-product-details-media gengage-chat-product-details-gallery gengage-chat-product-details-img-wrap';\n\n const mainImg = document.createElement('img');\n mainImg.className = 'gengage-chat-product-details-img';\n const firstSafe = images.find((u) => isSafeUrl(u));\n if (firstSafe) safeSetAttribute(mainImg, 'src', firstSafe);\n const name = product['name'] as string | undefined;\n if (name) mainImg.alt = name;\n media.appendChild(mainImg);\n\n const thumbStrip = document.createElement('div');\n thumbStrip.className = 'gengage-chat-product-gallery-thumbs';\n\n for (let i = 0; i < images.length; i++) {\n const imgUrl = images[i];\n if (!imgUrl || !isSafeUrl(imgUrl)) continue;\n const thumb = document.createElement('img');\n thumb.className = 'gengage-chat-product-gallery-thumb';\n if (i === 0) thumb.classList.add('gengage-chat-product-gallery-thumb--active');\n safeSetAttribute(thumb, 'src', imgUrl);\n thumb.alt = `${name ?? 'Product'} ${i + 1}`;\n thumb.width = 48;\n thumb.height = 48;\n thumb.addEventListener('click', () => {\n safeSetAttribute(mainImg, 'src', imgUrl);\n thumbStrip\n .querySelectorAll('.gengage-chat-product-gallery-thumb')\n .forEach((t) => t.classList.remove('gengage-chat-product-gallery-thumb--active'));\n thumb.classList.add('gengage-chat-product-gallery-thumb--active');\n });\n thumbStrip.appendChild(thumb);\n }\n\n // Touch swipe gesture for gallery navigation\n let touchStartX = 0;\n const SWIPE_THRESHOLD = 50;\n\n mainImg.addEventListener(\n 'touchstart',\n (e: TouchEvent) => {\n touchStartX = e.changedTouches[0]!.clientX;\n },\n { passive: true },\n );\n\n mainImg.addEventListener('touchend', (e: TouchEvent) => {\n const touchEndX = e.changedTouches[0]!.clientX;\n const diff = touchStartX - touchEndX;\n if (Math.abs(diff) < SWIPE_THRESHOLD) return;\n\n const thumbs = thumbStrip.querySelectorAll('.gengage-chat-product-gallery-thumb');\n const activeThumb = thumbStrip.querySelector('.gengage-chat-product-gallery-thumb--active');\n const currentIdx = activeThumb ? Array.from(thumbs).indexOf(activeThumb) : 0;\n\n const nextIdx =\n diff > 0\n ? Math.min(currentIdx + 1, thumbs.length - 1) // swipe left → next\n : Math.max(currentIdx - 1, 0); // swipe right → prev\n\n if (nextIdx !== currentIdx && thumbs[nextIdx]) {\n (thumbs[nextIdx] as HTMLElement).click();\n }\n });\n\n media.appendChild(thumbStrip);\n\n // \"Find Similar\" hover pill on gallery image\n if (detailsSku) {\n const pill = document.createElement('button');\n pill.className = 'gengage-chat-find-similar-pill';\n pill.type = 'button';\n pill.textContent = ctx.i18n?.findSimilarLabel ?? 'Benzerlerini Bul';\n pill.addEventListener('click', () => {\n ctx.onAction({\n title: ctx.i18n?.findSimilarLabel ?? 'Benzerlerini Bul',\n type: 'findSimilar',\n payload: { sku: detailsSku, ...(firstSafe ? { image_url: firstSafe } : {}) },\n });\n });\n media.appendChild(pill);\n }\n\n panel.appendChild(media);\n } else if (imageUrl && isSafeUrl(imageUrl)) {\n // Single image fallback\n const media = document.createElement('div');\n media.className = 'gengage-chat-product-details-media gengage-chat-product-details-img-wrap';\n const img = document.createElement('img');\n img.className = 'gengage-chat-product-details-img';\n safeSetAttribute(img, 'src', imageUrl);\n const name = product['name'] as string | undefined;\n if (name) img.alt = name;\n media.appendChild(img);\n\n // \"Find Similar\" hover pill on single image\n if (detailsSku) {\n const pill = document.createElement('button');\n pill.className = 'gengage-chat-find-similar-pill';\n pill.type = 'button';\n pill.textContent = ctx.i18n?.findSimilarLabel ?? 'Benzerlerini Bul';\n pill.addEventListener('click', () => {\n ctx.onAction({\n title: ctx.i18n?.findSimilarLabel ?? 'Benzerlerini Bul',\n type: 'findSimilar',\n payload: { sku: detailsSku, ...(imageUrl ? { image_url: imageUrl } : {}) },\n });\n });\n media.appendChild(pill);\n }\n\n panel.appendChild(media);\n }\n\n const content = document.createElement('div');\n content.className = 'gengage-chat-product-details-content';\n\n const name = product['name'] as string | undefined;\n if (name) {\n const title = document.createElement('h3');\n title.className = 'gengage-chat-product-details-title';\n title.textContent = name;\n content.appendChild(title);\n }\n\n const rating = product['rating'];\n const reviewCount = product['reviewCount'];\n if (typeof rating === 'number' && Number.isFinite(rating)) {\n const ratingRow = document.createElement('div');\n ratingRow.className = 'gengage-chat-product-details-rating';\n ratingRow.textContent = `\\u2605 ${rating.toFixed(1)}`;\n if (typeof reviewCount === 'number' && Number.isFinite(reviewCount)) {\n const count = document.createElement('span');\n count.className = 'gengage-chat-product-details-review-count';\n count.textContent = ` (${reviewCount})`;\n ratingRow.appendChild(count);\n }\n content.appendChild(ratingRow);\n }\n\n const price = product['price'] as string | undefined;\n const originalPrice = product['originalPrice'] as string | undefined;\n const priceAsync = product['price_async'] as boolean | undefined;\n\n if (priceAsync === true) {\n const priceRow = document.createElement('div');\n priceRow.className = 'gengage-chat-product-details-price';\n const skeleton = document.createElement('span');\n skeleton.className = 'gengage-chat-price-skeleton';\n priceRow.appendChild(skeleton);\n content.appendChild(priceRow);\n // Replace skeleton with actual price after delay\n setTimeout(() => {\n if (price) {\n const currentPrice = document.createElement('span');\n currentPrice.className = 'gengage-chat-product-details-current-price';\n currentPrice.textContent = formatTurkishPrice(price);\n skeleton.replaceWith(currentPrice);\n } else {\n skeleton.remove();\n }\n }, 300);\n } else if (price) {\n const priceRow = document.createElement('div');\n priceRow.className = 'gengage-chat-product-details-price';\n if (originalPrice && originalPrice !== price) {\n const oldPrice = document.createElement('span');\n oldPrice.className = 'gengage-chat-product-details-original-price';\n oldPrice.textContent = formatTurkishPrice(originalPrice);\n priceRow.appendChild(oldPrice);\n priceRow.appendChild(document.createTextNode(' '));\n }\n const currentPrice = document.createElement('span');\n currentPrice.className = 'gengage-chat-product-details-current-price';\n currentPrice.textContent = formatTurkishPrice(price);\n priceRow.appendChild(currentPrice);\n content.appendChild(priceRow);\n }\n\n const inStock = product['inStock'];\n if (typeof inStock === 'boolean') {\n const stock = document.createElement('div');\n stock.className = `gengage-chat-product-details-stock ${inStock ? 'is-in-stock' : 'is-out-of-stock'}`;\n stock.textContent = inStock ? 'Stokta var' : 'Stokta yok';\n content.appendChild(stock);\n }\n\n // Promotion badges (e.g. \"Free Shipping\", \"Flash Sale\")\n const promotions = product['promotions'] as string[] | undefined;\n if (promotions && promotions.length > 0) {\n const promoBadges = document.createElement('div');\n promoBadges.className = 'gengage-chat-product-details-promos';\n for (const promo of promotions) {\n const badge = document.createElement('span');\n badge.className = 'gengage-chat-product-details-promo-badge';\n badge.textContent = promo;\n promoBadges.appendChild(badge);\n }\n content.appendChild(promoBadges);\n }\n\n // Variant selector\n const variants = product['variants'] as Array<Record<string, unknown>> | undefined;\n if (variants && variants.length > 0) {\n const variantSection = document.createElement('div');\n variantSection.className = 'gengage-chat-product-variants';\n\n const variantLabel = document.createElement('div');\n variantLabel.className = 'gengage-chat-product-variants-label';\n variantLabel.textContent = ctx.i18n?.variantsLabel ?? 'Varyantlar';\n variantSection.appendChild(variantLabel);\n\n const variantList = document.createElement('div');\n variantList.className = 'gengage-chat-product-variants-list';\n\n for (const variant of variants) {\n const variantName = (variant['name'] as string | undefined) ?? (variant['variant_name'] as string | undefined);\n const variantSku = variant['sku'] as string | undefined;\n if (!variantName && !variantSku) continue;\n\n const btn = document.createElement('button');\n btn.className = 'gengage-chat-product-variant-btn';\n btn.type = 'button';\n\n const labelText = variantName ?? variantSku ?? '';\n const variantPrice = variant['price'] as number | string | undefined;\n if (variantPrice && String(variantPrice) !== String(price)) {\n btn.textContent = `${labelText} - ${formatTurkishPrice(String(variantPrice))}`;\n } else {\n btn.textContent = labelText;\n }\n\n if (variantSku) {\n btn.addEventListener('click', () => {\n ctx.onAction({\n title: labelText,\n type: 'launchVariant',\n payload: { sku: variantSku },\n });\n });\n }\n variantList.appendChild(btn);\n }\n\n variantSection.appendChild(variantList);\n content.appendChild(variantSection);\n }\n\n const sku = product['sku'] as string | undefined;\n const cartCode = product['cartCode'] as string | undefined;\n\n const actionRow = document.createElement('div');\n actionRow.className = 'gengage-chat-product-details-actions';\n\n const action = element.props?.['action'] as ActionPayload | undefined;\n if (action) {\n const actionBtn = document.createElement('button');\n actionBtn.className = 'gengage-chat-product-details-cta';\n actionBtn.type = 'button';\n actionBtn.textContent = action.title || ctx.i18n?.productCtaLabel || 'Incele';\n actionBtn.addEventListener('click', () => ctx.onAction(action));\n actionRow.appendChild(actionBtn);\n } else {\n const url = product['url'] as string | undefined;\n if (url && isSafeUrl(url)) {\n const cta = document.createElement('a');\n cta.className = 'gengage-chat-product-details-cta';\n safeSetAttribute(cta, 'href', url);\n safeSetAttribute(cta, 'target', '_blank');\n safeSetAttribute(cta, 'rel', 'noopener noreferrer');\n cta.textContent = ctx.i18n?.productCtaLabel ?? 'Incele';\n cta.addEventListener('click', (e) => {\n if (ctx.onProductClick && sku) {\n e.preventDefault();\n ctx.onProductClick({ sku, url });\n }\n });\n actionRow.appendChild(cta);\n }\n }\n\n // \"Sepete Ekle\" button — shown when the product has a cartCode\n if (cartCode && sku) {\n const atcBtn = document.createElement('button');\n atcBtn.className = 'gengage-chat-product-details-atc';\n atcBtn.type = 'button';\n atcBtn.textContent = 'Sepete Ekle';\n atcBtn.addEventListener('click', () => {\n ctx.onAction({\n title: 'Sepete Ekle',\n type: 'addToCart',\n payload: { sku, cartCode, quantity: 1 },\n });\n });\n actionRow.appendChild(atcBtn);\n }\n\n if (actionRow.childElementCount > 0) {\n content.appendChild(actionRow);\n }\n\n panel.appendChild(content);\n\n // Product detail tabs: \"Ürün Bilgileri\" / \"Teknik Özellikler\"\n const description = product['description'] as string | undefined;\n const specifications = product['specifications'] as\n | Record<string, string>\n | Array<{ key: string; value: string }>\n | undefined;\n if (description || specifications) {\n panel.appendChild(renderProductDetailTabs(description, specifications));\n }\n\n return panel;\n}\n\nfunction renderProductDetailTabs(\n description: string | undefined,\n specifications: Record<string, string> | Array<{ key: string; value: string }> | undefined,\n): HTMLElement {\n const container = document.createElement('div');\n container.className = 'gengage-chat-product-detail-tabs';\n\n const tabBar = document.createElement('div');\n tabBar.className = 'gengage-chat-product-detail-tab-bar';\n\n const tabPanels: HTMLElement[] = [];\n\n // \"Ürün Bilgileri\" tab\n if (description) {\n const tab = document.createElement('button');\n tab.className = 'gengage-chat-product-detail-tab gengage-chat-product-detail-tab--active';\n tab.type = 'button';\n tab.textContent = 'Ürün Bilgileri';\n tabBar.appendChild(tab);\n\n const panel = document.createElement('div');\n panel.className = 'gengage-chat-product-detail-tab-panel';\n panel.textContent = description;\n tabPanels.push(panel);\n }\n\n // \"Teknik Özellikler\" tab\n if (specifications) {\n const tab = document.createElement('button');\n tab.className = `gengage-chat-product-detail-tab${!description ? ' gengage-chat-product-detail-tab--active' : ''}`;\n tab.type = 'button';\n tab.textContent = 'Teknik Özellikler';\n tabBar.appendChild(tab);\n\n const panel = document.createElement('div');\n panel.className = 'gengage-chat-product-detail-tab-panel';\n if (!description) {\n // Show specs by default if no description\n } else {\n panel.style.display = 'none';\n }\n\n const table = document.createElement('table');\n table.className = 'gengage-chat-product-specs-table';\n const entries = Array.isArray(specifications)\n ? specifications\n : Object.entries(specifications).map(([key, value]) => ({ key, value }));\n for (const entry of entries) {\n const row = document.createElement('tr');\n const keyCell = document.createElement('td');\n keyCell.className = 'gengage-chat-product-specs-key';\n keyCell.textContent = entry.key;\n const valCell = document.createElement('td');\n valCell.className = 'gengage-chat-product-specs-value';\n valCell.textContent = entry.value;\n row.appendChild(keyCell);\n row.appendChild(valCell);\n table.appendChild(row);\n }\n panel.appendChild(table);\n tabPanels.push(panel);\n }\n\n // Wire up tab switching\n const tabs = tabBar.querySelectorAll('.gengage-chat-product-detail-tab');\n tabs.forEach((tabEl, idx) => {\n tabEl.addEventListener('click', () => {\n tabs.forEach((t) => t.classList.remove('gengage-chat-product-detail-tab--active'));\n tabEl.classList.add('gengage-chat-product-detail-tab--active');\n tabPanels.forEach((p, pIdx) => {\n p.style.display = pIdx === idx ? '' : 'none';\n });\n });\n });\n\n container.appendChild(tabBar);\n for (const p of tabPanels) container.appendChild(p);\n return container;\n}\n\nfunction getSortedChildIds(childIds: string[], spec: UISpec, sort?: ProductSortState): string[] {\n if (!sort || sort.type === 'related') return childIds;\n\n const withPrice = childIds.map((id) => {\n const el = spec.elements[id];\n const product = el?.props?.['product'] as Record<string, unknown> | undefined;\n const price = product ? Number(product['price']) : NaN;\n return { id, price: Number.isFinite(price) ? price : Infinity };\n });\n\n withPrice.sort((a, b) => {\n if (a.price === Infinity && b.price === Infinity) return 0;\n if (a.price === Infinity) return 1;\n if (b.price === Infinity) return -1;\n return sort.direction === 'desc' ? b.price - a.price : a.price - b.price;\n });\n\n return withPrice.map((x) => x.id);\n}\n\nfunction resortGrid(grid: HTMLElement, childIds: string[], spec: UISpec, sort: ProductSortState): void {\n const sorted = getSortedChildIds(childIds, spec, sort);\n // Build map from element ID data attribute to DOM element\n const childMap = new Map<string, HTMLElement>();\n for (const child of Array.from(grid.children) as HTMLElement[]) {\n const elId = child.dataset['elementId'];\n if (elId) childMap.set(elId, child);\n }\n\n for (const id of sorted) {\n const el = childMap.get(id);\n if (el) grid.appendChild(el);\n }\n}\n\nfunction renderProductGrid(\n element: UIElement,\n spec: UISpec,\n renderElement: (elementId: string) => HTMLElement | null,\n ctx?: UISpecRenderContext,\n): HTMLElement {\n const wrapper = document.createElement('div');\n wrapper.className = 'gengage-chat-product-grid-wrapper';\n\n const childIds = element.children ?? [];\n\n // Sort toolbar (only when >1 children and context has sort support)\n if (childIds.length > 1 && ctx?.onSortChange) {\n const toolbar = document.createElement('div');\n toolbar.className = 'gengage-chat-product-sort-toolbar';\n\n const sort = ctx.productSort ?? { type: 'related' as const };\n\n const buttons: Array<{ label: string; sortState: ProductSortState }> = [\n { label: ctx.i18n?.sortRelated ?? 'Önerilen', sortState: { type: 'related' } },\n { label: ctx.i18n?.sortPriceAsc ?? 'Fiyat ↑', sortState: { type: 'price', direction: 'asc' } },\n { label: ctx.i18n?.sortPriceDesc ?? 'Fiyat ↓', sortState: { type: 'price', direction: 'desc' } },\n ];\n\n for (const btn of buttons) {\n const button = document.createElement('button');\n button.className = 'gengage-chat-product-sort-btn';\n button.type = 'button';\n const isActive = sort.type === btn.sortState.type && sort.direction === btn.sortState.direction;\n if (isActive) button.classList.add('gengage-chat-product-sort-btn--active');\n button.textContent = btn.label;\n button.addEventListener('click', () => {\n ctx.onSortChange?.(btn.sortState);\n resortGrid(grid, childIds, spec, btn.sortState);\n toolbar\n .querySelectorAll('.gengage-chat-product-sort-btn')\n .forEach((b) => b.classList.remove('gengage-chat-product-sort-btn--active'));\n button.classList.add('gengage-chat-product-sort-btn--active');\n });\n toolbar.appendChild(button);\n }\n\n // Comparison toggle button (only if onToggleComparisonSku is provided)\n if (ctx.onToggleComparisonSku) {\n const separator = document.createElement('div');\n separator.className = 'gengage-chat-product-sort-separator';\n toolbar.appendChild(separator);\n\n const compareBtn = document.createElement('button');\n compareBtn.className = 'gengage-chat-comparison-toggle-btn';\n compareBtn.type = 'button';\n if (ctx.comparisonSelectMode) {\n compareBtn.classList.add('gengage-chat-comparison-toggle-btn--active');\n }\n compareBtn.textContent = ctx.i18n?.compareSelected ?? 'Karşılaştır';\n compareBtn.addEventListener('click', () => {\n // Toggle is handled by the parent — dispatched via onToggleComparisonSku with empty string\n // to signal mode toggle (convention: empty sku = toggle mode)\n ctx.onToggleComparisonSku?.('');\n });\n toolbar.appendChild(compareBtn);\n }\n\n wrapper.appendChild(toolbar);\n }\n\n const grid = document.createElement('div');\n grid.className = 'gengage-chat-product-grid';\n\n const sortedIds = getSortedChildIds(childIds, spec, ctx?.productSort);\n for (const childId of sortedIds) {\n if (!spec.elements[childId]) continue;\n const rendered = renderElement(childId);\n if (rendered) {\n rendered.dataset['elementId'] = childId;\n grid.appendChild(rendered);\n }\n }\n\n // Mobile variant: horizontal scroll\n if (isMobileViewport()) {\n grid.classList.add('gengage-chat-product-grid--mobile');\n }\n\n wrapper.appendChild(grid);\n\n // \"View More\" button (only when endOfList is not true)\n const endOfList = element.props?.['endOfList'] as boolean | undefined;\n if (endOfList !== true && childIds.length > 0) {\n const viewMoreBtn = document.createElement('button');\n viewMoreBtn.className = 'gengage-chat-product-grid-view-more';\n viewMoreBtn.type = 'button';\n viewMoreBtn.textContent = ctx?.i18n?.viewMoreLabel ?? 'Daha Fazla Göster';\n viewMoreBtn.addEventListener('click', () => {\n ctx?.onAction({ title: 'More', type: 'moreProductList', payload: {} });\n });\n wrapper.appendChild(viewMoreBtn);\n }\n\n // Floating comparison button (visible when 2+ products are selected)\n if (ctx?.comparisonSelectMode && ctx.comparisonSelectedSkus && ctx.comparisonSelectedSkus.length >= 2) {\n const floatingBtn = renderFloatingComparisonButton(ctx.comparisonSelectedSkus, ctx);\n wrapper.appendChild(floatingBtn);\n }\n\n return wrapper;\n}\n\nfunction renderComparisonTableElement(element: UIElement, ctx: UISpecRenderContext): HTMLElement {\n const props = element.props ?? {};\n const keyDifferencesHtml = props['keyDifferencesHtml'] as string | undefined;\n const recommended = props['recommended'] as ComparisonProduct | undefined;\n const products = (props['products'] as ComparisonProduct[] | undefined) ?? [];\n const attributes = (props['attributes'] as ComparisonAttribute[] | undefined) ?? [];\n const highlights = (props['highlights'] as string[] | undefined) ?? [];\n const specialCases = props['specialCases'] as string[] | undefined;\n const recommendedText = props['recommendedText'] as string | undefined;\n const winnerHits = props['winnerHits'] as Record<string, { positive?: string[]; negative?: string[] }> | undefined;\n const productActions = props['productActions'] as\n | Record<string, { title: string; type: string; payload?: unknown }>\n | undefined;\n\n if (!recommended) {\n const fallback = document.createElement('div');\n return fallback;\n }\n\n const options: import('./ComparisonTable.js').ComparisonTableOptions = {\n recommended,\n products,\n attributes,\n highlights,\n specialCases,\n onProductClick: (sku) => {\n ctx.onProductClick?.({ sku, url: '' });\n },\n };\n if (recommendedText !== undefined) options.recommendedText = recommendedText;\n if (winnerHits !== undefined) options.winnerHits = winnerHits;\n if (productActions !== undefined) options.productActions = productActions;\n if (keyDifferencesHtml !== undefined) options.keyDifferencesHtml = keyDifferencesHtml;\n\n const el = renderComparisonTable(options);\n\n // Mobile variant\n if (isMobileViewport()) {\n el.classList.add('gengage-chat-comparison--mobile');\n }\n\n return el;\n}\n\nfunction renderDivider(element: UIElement): HTMLElement {\n const hr = document.createElement('hr');\n hr.className = 'gengage-chat-divider';\n const label = element.props?.['label'] as string | undefined;\n if (label) {\n const wrapper = document.createElement('div');\n wrapper.className = 'gengage-chat-divider-wrapper';\n const labelEl = document.createElement('span');\n labelEl.className = 'gengage-chat-divider-label';\n labelEl.textContent = label;\n wrapper.appendChild(hr);\n wrapper.appendChild(labelEl);\n return wrapper;\n }\n return hr;\n}\n","/**\n * Block-by-block HTML typewriter effect.\n *\n * Parses sanitised HTML into top-level blocks and reveals them one at a time\n * with a configurable stagger delay. Respects prefers-reduced-motion.\n */\n\nexport interface TypewriterOptions {\n container: HTMLElement;\n html: string;\n /** Delay in ms between block reveals (default: 30). */\n delayMs?: number;\n /** Called after each block is revealed — useful for scroll tracking. */\n onTick?: () => void;\n /** Called when all blocks have been revealed. */\n onComplete?: () => void;\n}\n\nexport interface TypewriterHandle {\n /** Skip animation and show all content immediately. */\n complete(): void;\n /** Cancel animation, leave content as-is. */\n cancel(): void;\n readonly isRunning: boolean;\n}\n\nconst BLOCK_ELEMENTS = new Set([\n 'P',\n 'DIV',\n 'H1',\n 'H2',\n 'H3',\n 'H4',\n 'H5',\n 'H6',\n 'LI',\n 'UL',\n 'OL',\n 'BLOCKQUOTE',\n 'PRE',\n 'TABLE',\n 'SECTION',\n 'HR',\n 'FIGURE',\n 'FIGCAPTION',\n 'DL',\n 'DT',\n 'DD',\n]);\n\n/**\n * Split parsed DOM children into logical blocks for reveal animation.\n * Block-level elements each become their own block.\n * Adjacent inline/text nodes are grouped together.\n */\nfunction splitIntoBlocks(nodes: NodeList): Node[][] {\n const blocks: Node[][] = [];\n let currentInline: Node[] = [];\n\n for (const node of nodes) {\n if (node.nodeType === Node.ELEMENT_NODE && BLOCK_ELEMENTS.has((node as Element).tagName)) {\n // Flush any pending inline group\n if (currentInline.length > 0) {\n blocks.push(currentInline);\n currentInline = [];\n }\n blocks.push([node]);\n } else {\n currentInline.push(node);\n }\n }\n\n if (currentInline.length > 0) {\n blocks.push(currentInline);\n }\n\n return blocks;\n}\n\nfunction containsTable(nodes: Node[][]): boolean {\n for (const block of nodes) {\n for (const node of block) {\n if (\n node.nodeType === Node.ELEMENT_NODE &&\n ((node as Element).tagName === 'TABLE' || (node as Element).querySelector?.('table'))\n ) {\n return true;\n }\n }\n }\n return false;\n}\n\nfunction prefersReducedMotion(): boolean {\n if (typeof window === 'undefined' || typeof window.matchMedia !== 'function') return false;\n return window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n}\n\nexport function typewriteHtml(options: TypewriterOptions): TypewriterHandle {\n const { container, html, delayMs = 30, onTick, onComplete } = options;\n\n // Parse HTML into DOM nodes\n const template = document.createElement('template');\n template.innerHTML = html;\n const blocks = splitIntoBlocks(template.content.childNodes);\n\n // Skip animation for: reduced motion, single block, contains table, empty\n if (prefersReducedMotion() || blocks.length <= 1 || containsTable(blocks)) {\n container.innerHTML = html;\n onComplete?.();\n return { complete() {}, cancel() {}, isRunning: false };\n }\n\n // Clear container and start reveal\n container.innerHTML = '';\n let currentIndex = 0;\n let timerId: ReturnType<typeof setTimeout> | null = null;\n let running = true;\n\n function revealNext(): void {\n if (!running || currentIndex >= blocks.length) {\n running = false;\n onComplete?.();\n return;\n }\n\n const block = blocks[currentIndex]!;\n const wrapper = document.createElement('span');\n wrapper.className = 'gengage-chat-typewriter-block';\n for (const node of block) {\n wrapper.appendChild(node.cloneNode(true));\n }\n container.appendChild(wrapper);\n\n currentIndex++;\n onTick?.();\n\n if (currentIndex < blocks.length) {\n timerId = setTimeout(revealNext, delayMs);\n } else {\n running = false;\n onComplete?.();\n }\n }\n\n // Start the first reveal immediately\n revealNext();\n\n return {\n complete() {\n if (!running) return;\n if (timerId !== null) clearTimeout(timerId);\n running = false;\n container.innerHTML = html;\n onComplete?.();\n },\n cancel() {\n if (timerId !== null) clearTimeout(timerId);\n running = false;\n },\n get isRunning() {\n return running;\n },\n };\n}\n","/**\n * Product mention linker.\n *\n * After sanitiseHtml() renders bot text, this module walks text nodes and\n * wraps product name occurrences with clickable links that dispatch a\n * `launchSingleProduct` action.\n *\n * XSS safety: Uses DOM text-node manipulation only — no innerHTML.\n */\n\nexport interface ProductMention {\n sku: string;\n short_name: string;\n}\n\nexport interface ProductMentionLinkerOptions {\n container: HTMLElement;\n mentions: ProductMention[];\n onProductClick: (sku: string) => void;\n}\n\n/**\n * Walk text nodes in `container` and wrap occurrences of each mention's\n * `short_name` with a clickable `<a>` element.\n *\n * Only the first occurrence of each mention is linked to avoid visual clutter.\n */\nexport function linkProductMentions(options: ProductMentionLinkerOptions): void {\n const { container, mentions, onProductClick } = options;\n if (mentions.length === 0) return;\n\n // Build a map of lowercase short_name → mention for case-insensitive matching\n const mentionMap = new Map<string, ProductMention>();\n for (const m of mentions) {\n if (m.short_name.length === 0) continue;\n mentionMap.set(m.short_name.toLowerCase(), m);\n }\n\n if (mentionMap.size === 0) return;\n\n // Process one mention at a time, re-walking the tree each time\n // (DOM mutations invalidate the walker)\n for (const [lowerName, mention] of mentionMap) {\n const walker = document.createTreeWalker(container, NodeFilter.SHOW_TEXT);\n let node = walker.nextNode();\n let found = false;\n\n while (node && !found) {\n const text = node.textContent ?? '';\n const idx = text.toLowerCase().indexOf(lowerName);\n if (idx === -1) {\n node = walker.nextNode();\n continue;\n }\n\n const before = text.slice(0, idx);\n const match = text.slice(idx, idx + mention.short_name.length);\n const after = text.slice(idx + mention.short_name.length);\n\n const parent = node.parentNode;\n if (!parent) {\n node = walker.nextNode();\n continue;\n }\n\n const link = document.createElement('a');\n link.className = 'gengage-product-mention';\n link.textContent = match;\n link.href = '#';\n link.addEventListener('click', (e) => {\n e.preventDefault();\n onProductClick(mention.sku);\n });\n\n if (before) parent.insertBefore(document.createTextNode(before), node);\n parent.insertBefore(link, node);\n if (after) parent.insertBefore(document.createTextNode(after), node);\n parent.removeChild(node);\n\n found = true;\n }\n }\n}\n","/**\n * Classifies suggested actions into input-area chips vs message-flow pills.\n *\n * Input-area chips: compact shortcuts above the input field (search, info, review, similar).\n * Message-flow pills: larger interactive cards in the suggestion row.\n */\n\nconst INPUT_AREA_ICONS = new Set(['search', 'info', 'review', 'similar']);\nconst INPUT_AREA_TYPES = new Set([\n 'quickAnswer',\n 'reviewSummary',\n 'searchDiscovery',\n 'launchDiscovery',\n 'exploreTogetherV2',\n]);\n\nexport function isInputAreaAction(btn: { icon?: string; action?: { type?: string } }): boolean {\n if (btn.icon && INPUT_AREA_ICONS.has(btn.icon)) return true;\n if (btn.action?.type && INPUT_AREA_TYPES.has(btn.action.type)) return true;\n return false;\n}\n","/**\n * Floating card that suggests the user try comparison mode.\n *\n * Shows in the panel bottom-right when a ProductGrid is displayed and\n * comparison mode is not active.\n */\n\nconst SESSION_STORAGE_KEY = 'gengage_choice_prompter_dismissed';\n\nexport interface ChoicePrompterOptions {\n heading: string;\n suggestion: string;\n ctaLabel: string;\n onCtaClick: () => void;\n onDismiss?: () => void;\n}\n\nexport function createChoicePrompter(options: ChoicePrompterOptions): HTMLElement {\n const card = document.createElement('div');\n card.className = 'gengage-chat-choice-prompter';\n\n const headingEl = document.createElement('div');\n headingEl.className = 'gengage-chat-choice-prompter-heading';\n headingEl.textContent = options.heading;\n card.appendChild(headingEl);\n\n const suggestionEl = document.createElement('div');\n suggestionEl.className = 'gengage-chat-choice-prompter-suggestion';\n suggestionEl.textContent = options.suggestion;\n card.appendChild(suggestionEl);\n\n const cta = document.createElement('button');\n cta.type = 'button';\n cta.className = 'gengage-chat-choice-prompter-cta';\n cta.textContent = options.ctaLabel;\n cta.addEventListener('click', () => {\n markDismissed();\n card.remove();\n options.onCtaClick();\n });\n card.appendChild(cta);\n\n const dismiss = document.createElement('button');\n dismiss.type = 'button';\n dismiss.className = 'gengage-chat-choice-prompter-dismiss';\n dismiss.textContent = '\\u00D7'; // × close\n dismiss.setAttribute('aria-label', 'Dismiss');\n dismiss.addEventListener('click', () => {\n markDismissed();\n card.remove();\n options.onDismiss?.();\n });\n card.appendChild(dismiss);\n\n return card;\n}\n\nexport function isChoicePrompterDismissed(): boolean {\n try {\n return sessionStorage.getItem(SESSION_STORAGE_KEY) === '1';\n } catch {\n return false;\n }\n}\n\nfunction markDismissed(): void {\n try {\n sessionStorage.setItem(SESSION_STORAGE_KEY, '1');\n } catch {\n // sessionStorage unavailable — silently ignore\n }\n}\n","/**\n * IndexedDB persistence for chat sessions, backend context, and message payloads.\n *\n * Three stores:\n * - `sessions` — full session state (messages, thread cursors, timestamps)\n * - `context` — per-thread backend context snapshots (compound key)\n * - `payload` — message UISpec payloads (lean message pattern)\n *\n * All operations are best-effort: IndexedDB unavailability is non-fatal.\n */\n\nimport type { SerializableChatMessage } from '../chat/types.js';\nimport type { UISpec } from './types.js';\n\n// ---------------------------------------------------------------------------\n// Data shapes stored in each object store\n// ---------------------------------------------------------------------------\n\nexport interface SessionData {\n userId: string;\n appId: string;\n sessionId: string;\n messages: SerializableChatMessage[];\n currentThreadId: string | null;\n lastThreadId: string | null;\n createdAt: string;\n /** Thread IDs that produced panel content, in creation order. */\n panelThreads?: string[] | undefined;\n /** Product thumbnails for ThumbnailsColumn. */\n thumbnailEntries?: Array<{ sku: string; imageUrl: string; threadId: string }> | undefined;\n /** Serialized panel HTML keyed by bot message ID (for panel snapshot restore). */\n panelSnapshotHtml?: Record<string, string> | undefined;\n}\n\nexport interface ContextData {\n sessionId: string;\n threadId: string;\n context: Record<string, unknown>;\n}\n\nexport interface PayloadData {\n threadId: string;\n messageId: string;\n uiSpec: UISpec;\n}\n\nexport interface FavoriteData {\n userId: string;\n appId: string;\n sku: string;\n name?: string | undefined;\n imageUrl?: string | undefined;\n price?: string | undefined;\n savedAt: string;\n}\n\n// ---------------------------------------------------------------------------\n// GengageIndexedDB\n// ---------------------------------------------------------------------------\n\nconst DB_NAME = 'gengage_assistant';\nconst DB_VERSION = 3;\n\nconst STORE_SESSIONS = 'sessions';\nconst STORE_CONTEXT = 'context';\nconst STORE_PAYLOAD = 'payload';\nconst STORE_FAVORITES = 'favorites';\n\n/**\n * Wrap an IDBRequest in a Promise.\n */\nfunction requestToPromise<T>(request: IDBRequest<T>): Promise<T> {\n return new Promise((resolve, reject) => {\n request.onsuccess = () => resolve(request.result);\n request.onerror = () => reject(request.error);\n });\n}\n\n/**\n * Wrap an IDBTransaction completion in a Promise.\n */\nfunction transactionComplete(tx: IDBTransaction): Promise<void> {\n return new Promise((resolve, reject) => {\n tx.oncomplete = () => resolve();\n tx.onerror = () => reject(tx.error);\n tx.onabort = () => reject(tx.error ?? new DOMException('Transaction aborted'));\n });\n}\n\nexport class GengageIndexedDB {\n private _db: IDBDatabase | null = null;\n private _dbName: string;\n private _version: number;\n\n constructor(dbName: string = DB_NAME, version: number = DB_VERSION) {\n this._dbName = dbName;\n this._version = version;\n }\n\n // -------------------------------------------------------------------------\n // Lifecycle\n // -------------------------------------------------------------------------\n\n async open(): Promise<IDBDatabase> {\n if (this._db) return this._db;\n\n return new Promise((resolve, reject) => {\n const request = indexedDB.open(this._dbName, this._version);\n\n request.onupgradeneeded = (event) => {\n const db = request.result;\n const oldVersion = (event as IDBVersionChangeEvent).oldVersion;\n\n if (oldVersion < 1) {\n // Fresh install — create stores with v3 schema directly\n db.createObjectStore(STORE_SESSIONS, { keyPath: ['userId', 'appId', 'sessionId'] });\n db.createObjectStore(STORE_CONTEXT, { keyPath: ['sessionId', 'threadId'] });\n const payloadStore = db.createObjectStore(STORE_PAYLOAD, {\n keyPath: ['threadId', 'messageId'],\n });\n payloadStore.createIndex('threadId', 'threadId', { unique: false });\n db.createObjectStore(STORE_FAVORITES, { keyPath: ['userId', 'appId', 'sku'] });\n }\n\n if (oldVersion >= 1 && oldVersion < 2) {\n // Upgrade from v1 — drop old stores, recreate with new keys\n if (db.objectStoreNames.contains(STORE_SESSIONS)) db.deleteObjectStore(STORE_SESSIONS);\n if (db.objectStoreNames.contains(STORE_PAYLOAD)) db.deleteObjectStore(STORE_PAYLOAD);\n db.createObjectStore(STORE_SESSIONS, { keyPath: ['userId', 'appId', 'sessionId'] });\n const payloadStore = db.createObjectStore(STORE_PAYLOAD, {\n keyPath: ['threadId', 'messageId'],\n });\n payloadStore.createIndex('threadId', 'threadId', { unique: false });\n // Context store unchanged — keep existing data\n }\n\n if (oldVersion < 3) {\n if (!db.objectStoreNames.contains(STORE_FAVORITES)) {\n db.createObjectStore(STORE_FAVORITES, { keyPath: ['userId', 'appId', 'sku'] });\n }\n }\n };\n\n request.onsuccess = () => {\n this._db = request.result;\n resolve(this._db);\n };\n\n request.onerror = () => reject(request.error);\n });\n }\n\n close(): void {\n this._db?.close();\n this._db = null;\n }\n\n // -------------------------------------------------------------------------\n // Sessions\n // -------------------------------------------------------------------------\n\n async saveSession(data: SessionData): Promise<void> {\n const db = this._requireDb();\n const tx = db.transaction(STORE_SESSIONS, 'readwrite');\n tx.objectStore(STORE_SESSIONS).put(data);\n await transactionComplete(tx);\n }\n\n async loadSession(userId: string, appId: string, sessionId: string): Promise<SessionData | null> {\n const db = this._requireDb();\n const tx = db.transaction(STORE_SESSIONS, 'readonly');\n const result = await requestToPromise(tx.objectStore(STORE_SESSIONS).get([userId, appId, sessionId]));\n return (result as SessionData | undefined) ?? null;\n }\n\n // -------------------------------------------------------------------------\n // Context (compound key: [sessionId, threadId])\n // -------------------------------------------------------------------------\n\n async saveContext(data: ContextData): Promise<void> {\n const db = this._requireDb();\n const tx = db.transaction(STORE_CONTEXT, 'readwrite');\n tx.objectStore(STORE_CONTEXT).put(data);\n await transactionComplete(tx);\n }\n\n async loadContext(sessionId: string, threadId: string): Promise<ContextData | null> {\n const db = this._requireDb();\n const tx = db.transaction(STORE_CONTEXT, 'readonly');\n const result = await requestToPromise(tx.objectStore(STORE_CONTEXT).get([sessionId, threadId]));\n return (result as ContextData | undefined) ?? null;\n }\n\n /**\n * Delete all context entries for a session whose threadId is lexicographically\n * greater than the given threadId. Used during rollback to prune future branches.\n *\n * Thread IDs are UUIDv7 (lexicographically sortable by time), so string\n * comparison is sufficient.\n */\n async deleteContextsAfterThread(sessionId: string, threadId: string): Promise<void> {\n const db = this._requireDb();\n const tx = db.transaction(STORE_CONTEXT, 'readwrite');\n const store = tx.objectStore(STORE_CONTEXT);\n\n // Open cursor over all entries and filter by sessionId + threadId comparison\n const request = store.openCursor();\n\n await new Promise<void>((resolve, reject) => {\n request.onsuccess = () => {\n const cursor = request.result;\n if (!cursor) {\n resolve();\n return;\n }\n const entry = cursor.value as ContextData;\n if (entry.sessionId === sessionId && entry.threadId > threadId) {\n cursor.delete();\n }\n cursor.continue();\n };\n request.onerror = () => reject(request.error);\n });\n\n await transactionComplete(tx);\n }\n\n /**\n * Load the most recent context for a session (latest threadId).\n * Uses lexicographic ordering of UUIDv7 threadIds for chronological sort.\n */\n async loadLatestContext(sessionId: string): Promise<ContextData | null> {\n const db = this._requireDb();\n const tx = db.transaction(STORE_CONTEXT, 'readonly');\n const store = tx.objectStore(STORE_CONTEXT);\n\n // UUIDv7 thread IDs are ASCII hex+hyphens, so \\uffff is a safe upper bound\n const range = IDBKeyRange.bound([sessionId, ''], [sessionId, '\\uffff']);\n\n return new Promise((resolve, reject) => {\n const request = store.openCursor(range, 'prev');\n request.onsuccess = () => {\n const cursor = request.result;\n resolve(cursor ? (cursor.value as ContextData) : null);\n };\n request.onerror = () => reject(request.error);\n });\n }\n\n // -------------------------------------------------------------------------\n // Payload\n // -------------------------------------------------------------------------\n\n async savePayload(data: PayloadData): Promise<void> {\n const db = this._requireDb();\n const tx = db.transaction(STORE_PAYLOAD, 'readwrite');\n tx.objectStore(STORE_PAYLOAD).put(data);\n await transactionComplete(tx);\n }\n\n async loadPayload(threadId: string, messageId: string): Promise<PayloadData | null> {\n const db = this._requireDb();\n const tx = db.transaction(STORE_PAYLOAD, 'readonly');\n const result = await requestToPromise(tx.objectStore(STORE_PAYLOAD).get([threadId, messageId]));\n return (result as PayloadData | undefined) ?? null;\n }\n\n async loadPayloadsByThread(threadId: string): Promise<PayloadData[]> {\n const db = this._requireDb();\n const tx = db.transaction(STORE_PAYLOAD, 'readonly');\n const index = tx.objectStore(STORE_PAYLOAD).index('threadId');\n const results: PayloadData[] = [];\n\n return new Promise((resolve, reject) => {\n const request = index.openCursor(IDBKeyRange.only(threadId));\n request.onsuccess = () => {\n const cursor = request.result;\n if (!cursor) {\n resolve(results);\n return;\n }\n results.push(cursor.value as PayloadData);\n cursor.continue();\n };\n request.onerror = () => reject(request.error);\n });\n }\n\n // -------------------------------------------------------------------------\n // Favorites\n // -------------------------------------------------------------------------\n\n async saveFavorite(data: FavoriteData): Promise<void> {\n const db = this._requireDb();\n const tx = db.transaction(STORE_FAVORITES, 'readwrite');\n tx.objectStore(STORE_FAVORITES).put(data);\n await transactionComplete(tx);\n }\n\n async removeFavorite(userId: string, appId: string, sku: string): Promise<void> {\n const db = this._requireDb();\n const tx = db.transaction(STORE_FAVORITES, 'readwrite');\n tx.objectStore(STORE_FAVORITES).delete([userId, appId, sku]);\n await transactionComplete(tx);\n }\n\n async loadFavorites(userId: string, appId: string): Promise<FavoriteData[]> {\n const db = this._requireDb();\n const tx = db.transaction(STORE_FAVORITES, 'readonly');\n const all = await requestToPromise(tx.objectStore(STORE_FAVORITES).getAll());\n return (all as FavoriteData[]).filter((f) => f.userId === userId && f.appId === appId);\n }\n\n async isFavorite(userId: string, appId: string, sku: string): Promise<boolean> {\n const db = this._requireDb();\n const tx = db.transaction(STORE_FAVORITES, 'readonly');\n const result = await requestToPromise(tx.objectStore(STORE_FAVORITES).get([userId, appId, sku]));\n return result !== undefined;\n }\n\n // -------------------------------------------------------------------------\n // Internal\n // -------------------------------------------------------------------------\n\n private _requireDb(): IDBDatabase {\n if (!this._db) {\n throw new Error('GengageIndexedDB: database not open. Call open() first.');\n }\n return this._db;\n }\n}\n","/**\n * Extended Mode Manager — production lock-count system for panel extension.\n *\n * Controls whether the host page PDP area should be maximized or minimized\n * based on a combination of conditions: lock count, user visibility preference,\n * favorites mode, panel content type, and chat visibility.\n */\n\nexport type PanelContentType =\n | 'comparisonTable'\n | 'groupList'\n | 'productDetails'\n | 'productDetailsSimilars'\n | 'productList';\n\n/**\n * Base content types that always trigger panel extension.\n * `productDetails` is only added when `productDetailsInPanel` is true\n * (i.e. demo websites). Regular accounts show product details inline in ChatPane.\n */\nconst BASE_PANEL_CONTENT_TYPES: readonly PanelContentType[] = [\n 'comparisonTable',\n 'groupList',\n 'productDetailsSimilars',\n 'productList',\n];\n\nexport interface ExtendedModeManagerOptions {\n onChange: (extended: boolean) => void;\n /** Whether `productDetails` should trigger panel extension (default: false, true for demo sites). */\n productDetailsInPanel?: boolean;\n}\n\nexport class ExtendedModeManager {\n private _lockCount = 1; // starts locked\n private _hiddenByUser = false;\n private _lastPanelContentType: PanelContentType | null = null;\n private _chatShown = false;\n private _isFavoritesMode = false;\n private _lastExtended = false;\n private _onChange: (extended: boolean) => void;\n private _panelContentTypes: ReadonlySet<string>;\n\n constructor(options: ExtendedModeManagerOptions) {\n this._onChange = options.onChange;\n\n const types = new Set<string>(BASE_PANEL_CONTENT_TYPES);\n if (options.productDetailsInPanel) {\n types.add('productDetails');\n }\n this._panelContentTypes = types;\n }\n\n get isExtended(): boolean {\n return (\n this._lockCount === 0 &&\n !this._hiddenByUser &&\n !this._isFavoritesMode &&\n this._lastPanelContentType !== null &&\n this._panelContentTypes.has(this._lastPanelContentType) &&\n this._chatShown\n );\n }\n\n unlock(): void {\n if (this._lockCount > 0) {\n this._lockCount--;\n }\n this._checkStateChange();\n }\n\n lock(): void {\n this._lockCount++;\n this._checkStateChange();\n }\n\n setHiddenByUser(hidden: boolean): void {\n this._hiddenByUser = hidden;\n this._checkStateChange();\n }\n\n setChatShown(shown: boolean): void {\n this._chatShown = shown;\n this._checkStateChange();\n }\n\n setFavoritesMode(fav: boolean): void {\n this._isFavoritesMode = fav;\n this._checkStateChange();\n }\n\n setPanelContentType(type: PanelContentType | null): void {\n this._lastPanelContentType = type;\n this._checkStateChange();\n }\n\n private _checkStateChange(): void {\n const current = this.isExtended;\n if (current !== this._lastExtended) {\n this._lastExtended = current;\n this._onChange(current);\n }\n }\n}\n","/**\n * Chat widget — json-render catalog definition.\n *\n * This catalog describes all UI components the chat widget understands.\n * The backend streams `ui_spec` events whose element types must match names\n * defined here. Component implementations live in ./registry.tsx.\n *\n * HOW IT WORKS:\n * 1. Backend streams NDJSON events including `ui_spec` events.\n * 2. Each `ui_spec` event contains a `spec: UISpec` field.\n * 3. The `<ChatRenderer>` component feeds specs into json-render's `<Renderer>`.\n * 4. json-render looks up the element `type` in the registry and renders it.\n *\n * CUSTOMISING:\n * Fork this repo, edit ./registry.tsx to swap in your own components.\n * The catalog schema below stays the same — only the visual implementation changes.\n *\n * See: https://github.com/vercel-labs/json-render\n */\n\nimport { z } from 'zod';\n\n// ---------------------------------------------------------------------------\n// Component schemas (Zod)\n// ---------------------------------------------------------------------------\n\nexport const MessageBubbleSchema = z.object({\n role: z.enum(['user', 'assistant']),\n content: z.string(),\n timestamp: z.number().optional(),\n});\n\nexport const ProductCardSchema = z.object({\n sku: z.string(),\n name: z.string(),\n imageUrl: z.string().url().optional(),\n price: z.string().optional(),\n originalPrice: z.string().optional(),\n url: z.string().url(),\n /** Override CTA label (default: \"View product\") */\n ctaLabel: z.string().optional(),\n});\n\nexport const ActionButtonsSchema = z.object({\n buttons: z.array(\n z.object({\n label: z.string(),\n /** Opaque action payload forwarded to the backend when clicked. */\n action: z.object({\n title: z.string(),\n type: z.string(),\n payload: z.unknown().optional(),\n }),\n }),\n ),\n});\n\nexport const TypingIndicatorSchema = z.object({});\n\nexport const DividerSchema = z.object({\n label: z.string().optional(),\n});\n\nconst ComparisonProductSchema = z.object({\n sku: z.string(),\n name: z.string(),\n price: z.string(),\n imageUrl: z.string().optional(),\n rating: z.number().optional(),\n reviewCount: z.number().optional(),\n});\n\nexport const ComparisonTableSchema = z.object({\n recommended: ComparisonProductSchema,\n products: z.array(ComparisonProductSchema),\n attributes: z.array(\n z.object({\n label: z.string(),\n values: z.array(z.string()),\n }),\n ),\n highlights: z.array(z.string()),\n specialCases: z.array(z.string()).optional(),\n recommendedText: z.string().optional(),\n winnerHits: z\n .record(\n z.object({\n positive: z.array(z.string()).optional(),\n negative: z.array(z.string()).optional(),\n }),\n )\n .optional(),\n productActions: z\n .record(\n z.object({\n title: z.string(),\n type: z.string(),\n payload: z.unknown().optional(),\n }),\n )\n .optional(),\n});\n\nexport const SentimentLabelSchema = z.object({\n label: z.string(),\n sentiment: z.enum(['positive', 'negative', 'neutral']).optional(),\n});\n\nexport const AITopPickItemSchema = z.object({\n product: z.record(z.unknown()),\n role: z.string().optional(),\n reason: z.string().optional(),\n labels: z.array(SentimentLabelSchema).optional(),\n expertQualityScore: z.number().optional(),\n reviewHighlight: z.string().optional(),\n action: z\n .object({\n title: z.string(),\n type: z.string(),\n payload: z.unknown().optional(),\n })\n .optional(),\n});\n\nexport const AITopPicksSchema = z.object({\n suggestions: z.array(AITopPickItemSchema),\n});\n\nexport const GroundingReviewCardSchema = z.object({\n title: z.string().optional(),\n text: z.string().optional(),\n reviewCount: z.string().optional(),\n action: z.object({ title: z.string(), type: z.string(), payload: z.unknown().optional() }),\n});\n\nexport const AIGroupingCardsSchema = z.object({\n entries: z.array(\n z.object({\n name: z.string(),\n image: z.string().optional(),\n description: z.string().optional(),\n action: z.object({ title: z.string(), type: z.string(), payload: z.unknown().optional() }),\n }),\n ),\n});\n\nexport const AISuggestedSearchCardsSchema = z.object({\n entries: z.array(\n z.object({\n shortName: z.string(),\n detailedMessage: z.string().optional(),\n whyDifferent: z.string().optional(),\n image: z.string().optional(),\n action: z.object({ title: z.string(), type: z.string(), payload: z.unknown().optional() }),\n }),\n ),\n});\n\n// ---------------------------------------------------------------------------\n// Catalog definition\n//\n// When @json-render/core ships a stable defineCatalog() API, replace this\n// plain object with the official defineCatalog() call. For now the schema\n// map acts as both documentation and runtime validation.\n// ---------------------------------------------------------------------------\n\nexport const chatCatalog = {\n components: {\n MessageBubble: {\n schema: MessageBubbleSchema,\n description: 'A single chat message bubble for user or assistant turns.',\n },\n ProductCard: {\n schema: ProductCardSchema,\n description: 'A product card rendered inline in the chat stream.',\n },\n ActionButtons: {\n schema: ActionButtonsSchema,\n description: 'A horizontal row of quick-reply action buttons.',\n },\n TypingIndicator: {\n schema: TypingIndicatorSchema,\n description: 'An animated indicator shown while the assistant is typing.',\n },\n Divider: {\n schema: DividerSchema,\n description: 'A horizontal rule with an optional label.',\n },\n ComparisonTable: {\n schema: ComparisonTableSchema,\n description: 'A product comparison table with recommended pick, attribute rows, and highlights.',\n },\n AITopPicks: {\n schema: AITopPicksSchema,\n description: 'Rich AI-curated product suggestion cards with roles, sentiment labels, scores, and review quotes.',\n },\n GroundingReviewCard: {\n schema: GroundingReviewCardSchema,\n description: 'A card showing review grounding data with review count and CTA.',\n },\n AIGroupingCards: {\n schema: AIGroupingCardsSchema,\n description: 'Category grouping cards with images and labels for product discovery.',\n },\n AISuggestedSearchCards: {\n schema: AISuggestedSearchCardsSchema,\n description: 'Suggested search cards with images, descriptions, and differentiation.',\n },\n },\n} as const;\n\nexport type ChatCatalog = typeof chatCatalog;\nexport type ChatComponentName = keyof ChatCatalog['components'];\n","/**\n * Chat widget -- public entry point.\n *\n * Renders a floating launcher button + slide-in chat drawer inside Shadow DOM\n * for CSS isolation. Handles streaming NDJSON from the backend.\n */\n\nimport type { ActionPayload, PageContext, StreamEvent, StreamEventAction, UISpec } from '../common/types.js';\nimport type { ChatTransportConfig } from '../common/api-paths.js';\nimport type { ActionRouterOptions } from '../common/action-router.js';\nimport type { UISpecRenderHelpers } from '../common/renderer/index.js';\nimport type { BridgeMessage } from '../common/communication-bridge.js';\nimport type { BackendRequestMeta } from './api.js';\nimport { mergeUISpecRegistry } from '../common/renderer/index.js';\nimport { BaseWidget } from '../common/widget-base.js';\nimport { dispatch } from '../common/events.js';\nimport { uuidv7 } from '../common/uuidv7.js';\nimport { CommunicationBridge } from '../common/communication-bridge.js';\nimport { routeStreamAction } from '../common/action-router.js';\nimport {\n streamStartEvent,\n streamChunkEvent,\n streamDoneEvent,\n streamErrorEvent,\n streamUiSpecEvent,\n llmUsageEvent,\n meteringIncrementEvent,\n chatHistorySnapshotEvent,\n} from '../common/analytics-events.js';\nimport { sanitizeHtml } from '../common/safe-html.js';\nimport { validateImageFile } from './attachment-utils.js';\nimport { sendChatMessage, enrichActionPayload } from './api.js';\nimport { ChatDrawer } from './components/ChatDrawer.js';\nimport { createLauncher } from './components/Launcher.js';\nimport type { LauncherElements } from './components/Launcher.js';\nimport { createProactivePopup } from './components/ProactivePopup.js';\nimport { ActivityTracker } from '../common/activity-tracker.js';\nimport {\n renderUISpec,\n createDefaultChatUISpecRegistry,\n defaultChatUnknownUISpecRenderer,\n} from './components/renderUISpec.js';\nimport type { TypewriterHandle } from './components/typewriter.js';\nimport { typewriteHtml } from './components/typewriter.js';\nimport { linkProductMentions } from './components/productMentionLinker.js';\nimport { isInputAreaAction } from './components/actionClassifier.js';\nimport type { ThumbnailEntry } from './components/ThumbnailsColumn.js';\nimport { createChoicePrompter, isChoicePrompterDismissed } from './components/ChoicePrompter.js';\nimport type {\n ChatWidgetConfig,\n ChatMessage,\n ChatI18n,\n ChatUISpecRenderContext,\n ChatUISpecRegistry,\n ProductSortState,\n SerializableChatMessage,\n} from './types.js';\nimport { GengageIndexedDB } from '../common/indexed-db.js';\nimport { CHAT_I18N_TR, resolveChatLocale } from './locales/index.js';\nimport { ExtendedModeManager } from './extendedModeManager.js';\nimport type { PanelContentType } from './extendedModeManager.js';\n\nimport chatStyles from './components/chat.css?inline';\n\n// ---------------------------------------------------------------------------\n// KVKK notice caching\n// ---------------------------------------------------------------------------\nconst KVKK_STORAGE_KEY = 'gengage_kvkk_shown';\nconst KVKK_MARKERS = ['kvkk', 'kişisel veri', 'kisisel veri', '6698'];\n\nfunction containsKvkk(html: string): boolean {\n const lower = html.toLowerCase();\n return KVKK_MARKERS.some((m) => lower.includes(m));\n}\n\nfunction isKvkkShown(accountId: string): boolean {\n try {\n return localStorage.getItem(`${KVKK_STORAGE_KEY}_${accountId}`) === '1';\n } catch {\n return false;\n }\n}\n\nfunction markKvkkShown(accountId: string): void {\n try {\n localStorage.setItem(`${KVKK_STORAGE_KEY}_${accountId}`, '1');\n } catch {\n // localStorage unavailable — silently ignore\n }\n}\n\n/**\n * Strip the KVKK portion from bot HTML.\n * KVKK is typically wrapped in a `<div style=\"...\">` at the start.\n * We remove the first block-level element that contains a KVKK marker.\n */\nfunction stripKvkkBlock(html: string): string {\n const doc = new DOMParser().parseFromString(html, 'text/html');\n const body = doc.body;\n const children = Array.from(body.children);\n for (const child of children) {\n if (containsKvkk(child.textContent ?? '')) {\n child.remove();\n break; // Only strip the first KVKK block\n }\n }\n return body.innerHTML.trim();\n}\n\nfunction extractKvkkBlock(html: string): string | null {\n const doc = new DOMParser().parseFromString(html, 'text/html');\n for (const child of Array.from(doc.body.children)) {\n if (containsKvkk(child.textContent ?? '')) {\n return child.outerHTML;\n }\n }\n return null;\n}\n\nconst LOCALE_TO_LANGUAGE: Record<string, string> = {\n tr: 'TURKISH',\n en: 'ENGLISH',\n de: 'GERMAN',\n fr: 'FRENCH',\n};\n\nfunction localeToOutputLanguage(locale?: string): string {\n if (!locale) return 'TURKISH';\n return LOCALE_TO_LANGUAGE[locale.toLowerCase().slice(0, 2)] ?? 'TURKISH';\n}\n\nexport class GengageChat extends BaseWidget<ChatWidgetConfig> {\n private _shadow: ShadowRoot | null = null;\n private _rootEl: HTMLElement | null = null;\n private _launcher: LauncherElements | null = null;\n private _drawer: ChatDrawer | null = null;\n private _bridge: CommunicationBridge | null = null;\n private _activityTracker: ActivityTracker | null = null;\n private _proactiveShown = false;\n private _drawerVisible = false;\n private _messages: ChatMessage[] = [];\n private _currentBotText = '';\n private _currentMessageId = 0;\n private _abortController: AbortController | null = null;\n /** Current thread cursor — only messages with threadId <= this are visible. */\n private _currentThreadId: string | null = null;\n /** Most recent threadId ever created — used to detect branch points. */\n private _lastThreadId: string | null = null;\n /** Timestamp when the chat session was created (ISO 8601). */\n private _chatCreatedAt = '';\n /** Last backend-streamed context object — sent back with every request. */\n private _lastBackendContext: Record<string, unknown> | null = null;\n /** Panel content snapshots keyed by bot message ID for history navigation. */\n private _panelSnapshots = new Map<string, HTMLElement>();\n /** Component type for each panel snapshot (for topbar title restoration). */\n private _panelSnapshotTypes = new Map<string, string>();\n /** Currently active (highlighted) message ID in the chat pane. */\n private _activePanelMessageId: string | null = null;\n private _productSort: ProductSortState = { type: 'related' };\n private _comparisonSelectMode = false;\n private _comparisonSelectedSkus: string[] = [];\n private _thumbnailEntries: ThumbnailEntry[] = [];\n private _choicePrompterEl: HTMLElement | null = null;\n private _openState: 'full' | 'half' = 'full';\n private _mobileBreakpoint = 768;\n private _isMobileViewport = false;\n private _pdpLaunched = false;\n private _currentPanelType: string | null = null;\n private _i18n: ChatI18n = CHAT_I18N_TR;\n private _extendedModeManager: ExtendedModeManager | null = null;\n /** Thread IDs that have panel content, in order of creation. */\n private _panelThreads: string[] = [];\n /** Active typewriter animation handle — cancelled on new action or drawer close. */\n private _activeTypewriter: TypewriterHandle | null = null;\n /** IndexedDB persistence layer — null when unavailable. */\n private _indexedDB: GengageIndexedDB | null = null;\n /** Active request thread ID — guards against stale stream events from cancelled requests. */\n private _activeRequestThreadId: string | null = null;\n /** Accumulated SKU → product item map from outputText events. */\n private _skuToProductItem: Record<string, Record<string, unknown>> = {};\n /** Current conversation mode from the latest outputText event. */\n private _conversationMode: string | null = null;\n /** Whether initialization (including IDB restore) has completed. */\n private _initComplete = false;\n /** Queue of actions received before init completes. Max 10, FIFO discard. */\n private _pendingActions: Array<{\n action: ActionPayload;\n options?: { silent?: boolean; attachment?: File } | undefined;\n }> = [];\n /** Favorited product SKUs (loaded from IDB). */\n private _favoritedSkus: Set<string> = new Set();\n /** Supplemental context received from host via bridge (e.g. PDP detail context). */\n private _bridgeContext: Record<string, unknown> | null = null;\n /** Last cart quantity received from host via bridge. */\n private _cartQuantity: number | null = null;\n private _threadsWithFirstBot: Set<string> = new Set();\n\n protected async onInit(config: ChatWidgetConfig): Promise<void> {\n this._i18n = this._resolveI18n(config);\n this._chatCreatedAt = new Date().toISOString();\n\n // Create Shadow DOM for CSS isolation\n this._shadow = this.root.attachShadow({ mode: 'open' });\n\n // Inject styles\n const style = document.createElement('style');\n style.textContent = chatStyles;\n this._shadow.appendChild(style);\n\n // Create root container\n const rootEl = document.createElement('div');\n rootEl.className = 'gengage-chat-root';\n this._rootEl = rootEl;\n this._shadow.appendChild(rootEl);\n\n // Create launcher (floating variant only — inline/overlay are triggered programmatically)\n const variant = config.variant ?? 'floating';\n if (variant === 'floating') {\n const launcherOpts: import('./components/Launcher.js').LauncherOptions = {\n onClick: () => this.open(),\n ariaLabel: this._i18n.openButton,\n };\n if (config.launcherSvg !== undefined) launcherOpts.svgMarkup = config.launcherSvg;\n if (config.hideMobileLauncher !== undefined) launcherOpts.hideMobile = config.hideMobileLauncher;\n if (config.mobileBreakpoint !== undefined) launcherOpts.mobileBreakpoint = config.mobileBreakpoint;\n if (config.launcherTooltip !== undefined) launcherOpts.tooltip = config.launcherTooltip;\n this._launcher = createLauncher(launcherOpts);\n rootEl.appendChild(this._launcher.container);\n }\n\n // Overlay variant wraps drawer in a backdrop for full-screen modal\n if (variant === 'overlay') {\n rootEl.classList.add('gengage-chat--overlay');\n }\n\n // Create drawer (hidden initially for floating/overlay, visible for inline)\n const drawerContainer = document.createElement('div');\n rootEl.appendChild(drawerContainer);\n\n this._drawer = new ChatDrawer(drawerContainer, {\n i18n: this._i18n,\n onSend: (text, attachment) => this._sendMessage(text, attachment),\n onClose: () => this.close(),\n onAttachment: (file) => this._handleAttachment(file),\n onPanelToggle: () => {\n this._drawer?.persistPanelState(config.accountId);\n },\n onRollback: (messageId) => this._handleRollback(messageId),\n onPanelBack: () => this._navigatePanelBack(),\n onPanelForward: () => this._navigatePanelForward(),\n headerTitle: config.headerTitle,\n headerAvatarUrl: config.headerAvatarUrl,\n headerBadge: config.headerBadge,\n headerCartUrl: config.headerCartUrl,\n headerFavoritesToggle: config.headerFavoritesToggle,\n onFavoritesClick: config.onFavoritesClick,\n onThumbnailClick: (threadId) => this._rollbackToThread(threadId),\n onLinkClick: (url) => {\n this._saveSessionAndOpenURL(url);\n },\n });\n\n // Extended mode manager for host PDP maximize/minimize\n this._extendedModeManager = new ExtendedModeManager({\n onChange: (extended) => this._notifyPanelExtension(extended),\n productDetailsInPanel: config.isDemoWebsite ?? false,\n });\n\n // Hide drawer initially for floating/overlay variants\n if (variant !== 'inline') {\n this._drawer.getElement().classList.add('gengage-chat-drawer--hidden');\n }\n\n // Restore panel state from session\n this._drawer.restorePanelState(config.accountId);\n\n // Apply initial panelMode\n const panelMode = config.panelMode ?? 'auto';\n if (panelMode === 'collapsed') {\n this._drawer.setPanelCollapsed(true);\n } else if (panelMode === 'expanded') {\n this._drawer.setForceExpanded();\n }\n\n // Restore session if available\n const restoreSessionId = sessionStorage.getItem('gengage_restore_session_id');\n const restoreSku = sessionStorage.getItem('gengage_restore_sku');\n if (restoreSessionId && restoreSku) {\n sessionStorage.removeItem('gengage_restore_session_id');\n sessionStorage.removeItem('gengage_restore_sku');\n // Session restoration handled -- could auto-open in future\n }\n\n // IndexedDB persistence — best-effort, non-fatal\n try {\n this._indexedDB = new GengageIndexedDB();\n await this._indexedDB.open();\n await this._restoreFromIndexedDB();\n } catch {\n // IndexedDB unavailable — continue without persistence\n this._indexedDB = null;\n }\n\n // Register public API on window\n this._registerPublicAPI();\n\n // Apply mobileInitialState if configured\n if (config.mobileInitialState !== undefined) {\n this._openState = config.mobileInitialState;\n }\n this._mobileBreakpoint = config.mobileBreakpoint ?? 768;\n\n this._syncViewportState();\n const onResize = () => this._syncViewportState();\n window.addEventListener('resize', onResize, { passive: true });\n this.addCleanup(() => window.removeEventListener('resize', onResize));\n\n // iOS visualViewport keyboard handling\n if (window.visualViewport) {\n const onViewportResize = () => {\n if (!this._drawerVisible || !this._isMobileViewport) return;\n const el = this._drawer?.getElement();\n if (!el) return;\n const offset = window.innerHeight - (window.visualViewport?.height ?? window.innerHeight);\n el.style.setProperty('--gengage-keyboard-offset', `${Math.max(0, offset)}px`);\n };\n window.visualViewport.addEventListener('resize', onViewportResize);\n this.addCleanup(() => window.visualViewport?.removeEventListener('resize', onViewportResize));\n }\n\n // Inline variant starts visible\n if (variant === 'inline') {\n this._drawerVisible = true;\n this.isVisible = true;\n this._applyOpenStateClasses();\n }\n\n // Communication bridge for host ↔ widget messaging\n this._bridge = new CommunicationBridge({\n namespace: 'chat',\n onMessage: (msg) => this._handleBridgeMessage(msg),\n });\n\n // Activity tracker for engagement signals & proactive popup trigger\n this._activityTracker = new ActivityTracker({\n idleThresholdMs: config.proactiveDelayMs ?? 30000,\n onActivity: (event) => {\n if (event.type === 'idle' && !this._proactiveShown && !this._drawerVisible && config.proactiveMessage) {\n // Check scroll depth threshold (config is 0–1 fraction, tracker reports 0–100)\n const minDepth = config.proactiveMinScrollDepth ?? 0;\n if (minDepth > 0 && (this._activityTracker?.maxScrollDepth ?? 0) < minDepth * 100) {\n return;\n }\n // Check sessionStorage guard — don't re-trigger in same session\n try {\n if (sessionStorage.getItem('gengage_proactive_shown')) return;\n } catch {\n // sessionStorage unavailable (e.g. sandboxed iframe) — proceed\n }\n this._showProactivePopup(config.proactiveMessage);\n }\n },\n });\n this.addCleanup(() => this._activityTracker?.destroy());\n\n // Mark init complete and drain pending actions queue\n this._initComplete = true;\n for (const pending of this._pendingActions) {\n this._sendAction(pending.action, pending.options);\n }\n this._pendingActions = [];\n\n dispatch('gengage:chat:ready', {});\n config.onReady?.();\n }\n\n protected onUpdate(_context: Partial<PageContext>): void {\n // Forward context changes to pending messages if needed\n }\n\n protected onShow(): void {\n this._showDrawer();\n this.emit('open');\n dispatch('gengage:chat:open', { state: this._openState });\n this.config.onOpen?.();\n\n // Auto-launch PDP context on first open when SKU is available\n if (!this._pdpLaunched && this.config.pageContext?.sku) {\n this._pdpLaunched = true;\n this._sendAction(\n {\n title: '',\n type: 'launchSingleProduct',\n payload: { sku: this.config.pageContext.sku },\n },\n { silent: true },\n );\n }\n }\n\n protected onHide(): void {\n // Floating mode should only hide the drawer, not the launcher button.\n // BaseWidget.hide() toggles `root.style.display = 'none'`, so undo it here.\n if ((this.config.variant ?? 'floating') === 'floating') {\n this.root.style.display = '';\n }\n this._hideDrawer();\n this.emit('close');\n dispatch('gengage:chat:close', {});\n this.config.onClose?.();\n }\n\n protected onDestroy(): void {\n this._abortController?.abort();\n this._bridge?.destroy();\n this._bridge = null;\n this._extendedModeManager = null;\n this._indexedDB?.close();\n this._indexedDB = null;\n if (window.gengage) {\n delete window.gengage.chat;\n }\n if (this._shadow) {\n this._shadow.innerHTML = '';\n this._shadow = null;\n }\n this._rootEl = null;\n }\n\n // ---------------------------------------------------------------------------\n // Public API\n // ---------------------------------------------------------------------------\n\n open(options?: { state?: 'full' | 'half'; initialMessage?: string }): void {\n if (options?.state !== undefined) {\n this._openState = options.state;\n if (this._drawerVisible) {\n this._applyOpenStateClasses();\n }\n }\n this.show();\n if (options?.initialMessage !== undefined) {\n this._sendMessage(options.initialMessage);\n }\n }\n\n openWithAction(action: ActionPayload, options?: { sku?: string }): void {\n if (options?.sku !== undefined) {\n this.update({ sku: options.sku });\n }\n // Mark PDP as launched since we're sending an explicit action\n this._pdpLaunched = true;\n this.show();\n this._sendAction(action);\n }\n\n close(): void {\n this.hide();\n }\n\n saveSession(sessionId: string, sku: string): void {\n sessionStorage.setItem('gengage_restore_session_id', sessionId);\n sessionStorage.setItem('gengage_restore_sku', sku);\n }\n\n get isOpen(): boolean {\n return this._drawerVisible;\n }\n\n // ---------------------------------------------------------------------------\n // Private\n // ---------------------------------------------------------------------------\n\n private _handleBridgeMessage(msg: BridgeMessage): void {\n switch (msg.type) {\n case 'openChat':\n this.open();\n break;\n case 'closeChat':\n this.close();\n break;\n case 'startNewChatWithLauncherAction': {\n // Start a new chat with a preset launcher action\n const payload = msg.payload as Record<string, unknown> | undefined;\n const action = payload?.action;\n if (action && typeof action === 'object' && 'type' in (action as Record<string, unknown>)) {\n this._sendAction(action as ActionPayload, { silent: true });\n }\n this.open();\n break;\n }\n case 'startNewChatWithDetailContext': {\n // Start chat with product detail context (e.g., from PDP page)\n const ctx = msg.payload;\n if (ctx && typeof ctx === 'object') {\n this._bridgeContext = ctx as Record<string, unknown>;\n }\n this.open();\n break;\n }\n case 'launcherAction': {\n // Send action to active chat from external trigger\n const payload = msg.payload as Record<string, unknown> | undefined;\n const action = payload?.action;\n if (action && typeof action === 'object' && 'type' in (action as Record<string, unknown>)) {\n this._sendAction(action as ActionPayload);\n }\n break;\n }\n case 'scrollToBottom':\n this._drawer?.scrollToBottomIfNeeded();\n break;\n case 'addToCardHandler': {\n // Host notifies widget of add-to-cart result\n this._bridge?.send('addToCardResult', msg.payload);\n break;\n }\n case 'cartQuantityHandler': {\n // Host sends updated cart quantity\n const payload = msg.payload as Record<string, unknown> | undefined;\n if (payload && 'quantity' in payload && typeof payload.quantity === 'number') {\n this._cartQuantity = payload.quantity;\n }\n break;\n }\n case 'minimizeRequestedByUser':\n this._extendedModeManager?.setHiddenByUser(true);\n break;\n case 'bgColorChange': {\n // Host sends theme color update\n const payload = msg.payload as Record<string, unknown> | undefined;\n const color = payload?.color;\n if (typeof color === 'string' && this._shadow) {\n (this._shadow.host as HTMLElement).style.setProperty('--gengage-chat-bg', color);\n }\n break;\n }\n default:\n break;\n }\n }\n\n private _registerPublicAPI(): void {\n if (!window.gengage) window.gengage = {};\n window.gengage.chat = {\n open: (opts) => this.open(opts),\n openWithAction: (action, opts) => this.openWithAction(action, opts),\n close: () => this.close(),\n saveSession: (sid, sku) => this.saveSession(sid, sku),\n get isOpen() {\n return false;\n }, // Placeholder, overridden below\n on: (event, handler) => this.on(event, handler),\n trackCheckout: (type, data) => this.trackCheckout(type, data),\n flushMeteringSummary: (data) => this.flushMeteringSummary(data),\n };\n // Fix isOpen getter to reflect actual state\n Object.defineProperty(window.gengage.chat, 'isOpen', {\n get: () => this._drawerVisible,\n });\n }\n\n private _showDrawer(): void {\n if (this._drawerVisible) return;\n this._drawerVisible = true;\n const el = this._drawer?.getElement();\n if (el) {\n el.classList.remove('gengage-chat-drawer--hidden');\n }\n this._applyOpenStateClasses();\n if (!(this._isMobileViewport && this._openState === 'half')) {\n this._drawer?.focusInput();\n }\n this._extendedModeManager?.setChatShown(true);\n }\n\n private _showProactivePopup(message: string): void {\n if (this._proactiveShown || !this._rootEl) return;\n this._proactiveShown = true;\n\n // Persist across same-session page navigations\n try {\n sessionStorage.setItem('gengage_proactive_shown', '1');\n } catch {\n // sessionStorage unavailable — proceed without persistence\n }\n\n const popupOpts: import('./components/ProactivePopup.js').ProactivePopupOptions = {\n message,\n onAccept: () => this.open(),\n onDismiss: () => {\n /* no-op — popup auto-removes itself */\n },\n };\n if (this.config.proactiveAcceptLabel !== undefined) {\n popupOpts.acceptLabel = this.config.proactiveAcceptLabel;\n }\n const popup = createProactivePopup(popupOpts);\n this._rootEl.appendChild(popup);\n }\n\n private _hideDrawer(): void {\n if (!this._drawerVisible) return;\n this._activeTypewriter?.cancel();\n this._activeTypewriter = null;\n this._drawerVisible = false;\n const el = this._drawer?.getElement();\n if (el) {\n el.classList.add('gengage-chat-drawer--hidden');\n }\n this._applyOpenStateClasses();\n this._extendedModeManager?.setChatShown(false);\n }\n\n private _syncViewportState(): void {\n if (!this._rootEl) return;\n this._isMobileViewport = window.innerWidth <= this._mobileBreakpoint;\n this._rootEl.classList.toggle('gengage-chat-root--mobile', this._isMobileViewport);\n\n if (this._launcher) {\n const hideLauncher = this._isMobileViewport && this.config.hideMobileLauncher === true;\n this._launcher.container.classList.toggle('gengage-chat-launcher--hidden-mobile', hideLauncher);\n }\n\n this._applyOpenStateClasses();\n }\n\n private _applyOpenStateClasses(): void {\n if (!this._rootEl) return;\n const mobileHalf = this._drawerVisible && this._isMobileViewport && this._openState === 'half';\n const mobileFull = this._drawerVisible && this._isMobileViewport && this._openState === 'full';\n this._rootEl.classList.toggle('gengage-chat-root--open', this._drawerVisible);\n this._rootEl.classList.toggle('gengage-chat-root--mobile-half', mobileHalf);\n this._rootEl.classList.toggle('gengage-chat-root--mobile-full', mobileFull);\n }\n\n private _handleAttachment(file: File): void {\n const result = validateImageFile(file);\n if (!result.ok) {\n const message = result.reason === 'invalid_type' ? this._i18n.invalidFileType : this._i18n.fileTooLarge;\n dispatch('gengage:global:error', {\n message,\n source: 'chat' as const,\n });\n return;\n }\n this._drawer?.stageAttachment(file);\n }\n\n private _sendMessage(text: string, attachment?: File): void {\n const action: ActionPayload = {\n title: text,\n type: 'user_message',\n payload: text,\n };\n if (attachment !== undefined) {\n this._sendAction(action, { attachment });\n } else {\n this._sendAction(action);\n }\n }\n\n private _sendAction(action: ActionPayload, options?: { silent?: boolean; attachment?: File }): void {\n // Cancel any running typewriter animation\n this._activeTypewriter?.cancel();\n this._activeTypewriter = null;\n\n // Defer actions until init completes\n if (!this._initComplete) {\n if (this._pendingActions.length < 10) {\n this._pendingActions.push({ action, options });\n }\n return;\n }\n\n // Remove ChoicePrompter on new action\n this._choicePrompterEl?.remove();\n this._choicePrompterEl = null;\n\n // Branch deletion: if user is sending from a rewound position, prune future messages\n if (this._currentThreadId && this._lastThreadId && this._lastThreadId > this._currentThreadId) {\n const cutoff = this._currentThreadId;\n // Remove future messages from array\n const removed = this._messages.filter((m) => m.threadId !== undefined && m.threadId > cutoff);\n this._messages = this._messages.filter((m) => !m.threadId || m.threadId <= cutoff);\n // Remove their DOM nodes\n for (const msg of removed) {\n this._shadow?.querySelector(`[data-message-id=\"${msg.id}\"]`)?.remove();\n this._panelSnapshots.delete(msg.id);\n this._panelSnapshotTypes.delete(msg.id);\n }\n // Remove orphaned inline UISpec elements\n const orphanedUISpecs = this._shadow?.querySelectorAll(`[data-thread-id]`);\n orphanedUISpecs?.forEach((el) => {\n if (el instanceof HTMLElement && el.dataset['threadId'] && el.dataset['threadId'] > cutoff) {\n el.remove();\n }\n });\n }\n\n // Clear previous suggestion pills and input chips\n this._drawer?.setPills([]);\n this._drawer?.clearInputAreaChips();\n\n // Notify host that assistant is responding\n this._bridge?.send('isResponding', true);\n\n // Generate thread ID for this request-response cycle\n const threadId = uuidv7();\n this._currentThreadId = threadId;\n this._lastThreadId = threadId;\n this._activeRequestThreadId = threadId;\n\n // Add user message to UI (skip for silent/auto-launch actions)\n if (!options?.silent) {\n const userMsg = this._createMessage('user', typeof action.payload === 'string' ? action.payload : action.title);\n userMsg.threadId = threadId;\n if (options?.attachment !== undefined) {\n userMsg.attachment = options.attachment;\n }\n this._drawer?.addMessage(userMsg);\n this._messages.push(userMsg);\n }\n\n // Clear panel for new results (previous snapshot is already stored)\n this._drawer?.clearPanel();\n\n // Show typing indicator\n this._drawer?.showTypingIndicator();\n this._currentBotText = '';\n\n // Create bot message placeholder\n const botMsg = this._createMessage('assistant', '');\n botMsg.threadId = threadId;\n botMsg.status = 'streaming';\n // Note: silent flag only skips the USER message above — bot response is always rendered\n this._messages.push(botMsg);\n\n // Abort previous request\n this._abortController?.abort();\n\n const transport: ChatTransportConfig = {\n middlewareUrl: this.config.middlewareUrl,\n };\n if (options?.attachment !== undefined) {\n transport.attachment = options.attachment;\n }\n\n const visibleMessages = this._getVisibleMessages();\n const chatHistory = visibleMessages\n .filter((m) => m.content)\n .slice(-50)\n .map((m) => ({\n role: m.role === 'user' ? 'user' : 'model',\n content: m.content ?? '',\n }));\n\n // Build meta object for v1 backend\n const meta: BackendRequestMeta = {\n outputLanguage: localeToOutputLanguage(this.config.locale),\n parentUrl: window.location.href,\n windowWidth: String(window.innerWidth),\n windowHeight: String(window.innerHeight),\n selfUrl: '',\n id: this.config.session?.sessionId ?? '',\n userId: this.config.session?.userId ?? '',\n appId: this.config.accountId,\n threads: [],\n createdAt: this._chatCreatedAt,\n kvkkApproved: isKvkkShown(this.config.accountId),\n voiceEnabled: false,\n threadId,\n isControlGroup: false,\n isMobile: this._isMobileViewport,\n };\n if (this.config.session?.viewId !== undefined) {\n meta.viewId = this.config.session.viewId;\n }\n\n // Enrich action payload with fields the backend expects\n const enrichedAction = enrichActionPayload(action, {\n pageContext: this.config.pageContext,\n backendContext: this._lastBackendContext,\n isMobile: this._isMobileViewport,\n });\n\n const request: import('./api.js').ProcessActionRequest = {\n account_id: this.config.accountId,\n session_id: this.config.session?.sessionId ?? '',\n correlation_id: this.config.session?.sessionId ?? '',\n action: {\n title: enrichedAction.title,\n type: enrichedAction.type,\n },\n locale: this.config.locale ?? 'tr',\n meta,\n context: {\n messages: chatHistory,\n ...(this._lastBackendContext ?? {}),\n },\n };\n\n // Only set optional fields when values exist (exactOptionalPropertyTypes)\n if (this.config.session?.userId !== undefined) {\n request.user_id = this.config.session.userId;\n }\n if (this.config.session?.viewId !== undefined) {\n request.view_id = this.config.session.viewId;\n }\n if (enrichedAction.payload !== undefined) {\n request.action.payload = enrichedAction.payload;\n }\n if (this.config.pageContext?.sku !== undefined) {\n request.sku = this.config.pageContext.sku;\n }\n if (this.config.pageContext?.pageType !== undefined) {\n request.page_type = this.config.pageContext.pageType;\n }\n\n // Analytics tracking state for this request\n const requestId = crypto.randomUUID();\n const streamStart = Date.now();\n let chunkIndex = 0;\n let panelLoadingSeen = false;\n let panelContentReceived = false;\n\n this.track(\n streamStartEvent(this.analyticsContext(), {\n endpoint: 'process_action',\n request_id: requestId,\n widget: 'chat',\n }),\n );\n\n this._abortController = sendChatMessage(\n request,\n {\n onTextChunk: (content, isFinal, extra) => {\n if (threadId !== this._activeRequestThreadId) return;\n this._currentBotText += content;\n this._drawer?.removeTypingIndicator();\n\n // Store enrichment data from outputText for downstream rendering\n if (extra?.skuToProductItem) {\n this._skuToProductItem = { ...this._skuToProductItem, ...extra.skuToProductItem };\n }\n if (extra?.conversationMode) {\n this._conversationMode = extra.conversationMode;\n }\n\n this.track(\n streamChunkEvent(this.analyticsContext(), {\n request_id: requestId,\n chunk_index: chunkIndex++,\n widget: 'chat',\n }),\n );\n\n if (!this._drawer) return;\n\n // KVKK filtering: always strip KVKK block from display text.\n // Show banner on first encounter only.\n let displayText = this._currentBotText;\n if (isFinal && containsKvkk(displayText)) {\n const acctId = this.config.accountId;\n if (!isKvkkShown(acctId)) {\n const kvkkHtml = extractKvkkBlock(displayText);\n if (kvkkHtml) {\n this._drawer?.showKvkkBanner(kvkkHtml, () => {\n this._drawer?.hideKvkkBanner();\n });\n }\n markKvkkShown(acctId);\n }\n displayText = stripKvkkBlock(displayText);\n }\n\n // Check if we already have a bot bubble in the DOM (query by message ID, not :last-child)\n const existingBubble = this._shadow?.querySelector(\n `[data-message-id=\"${botMsg.id}\"] .gengage-chat-bubble-text`,\n );\n if (existingBubble) {\n existingBubble.innerHTML = sanitizeHtml(displayText);\n } else {\n botMsg.content = displayText;\n if (botMsg.role === 'assistant' && botMsg.threadId && !this._threadsWithFirstBot.has(botMsg.threadId)) {\n this._threadsWithFirstBot.add(botMsg.threadId);\n this._drawer.markFirstBotMessage(botMsg.id);\n }\n this._drawer.addMessage(botMsg);\n }\n\n if (isFinal) {\n botMsg.content = displayText;\n botMsg.status = 'done';\n\n // Apply typewriter animation to the final bot text\n const bubbleTextEl = this._shadow?.querySelector(\n `[data-message-id=\"${botMsg.id}\"] .gengage-chat-bubble-text`,\n ) as HTMLElement | null;\n if (bubbleTextEl) {\n this._activeTypewriter?.cancel();\n const mentions = extra?.productMentions;\n this._activeTypewriter = typewriteHtml({\n container: bubbleTextEl,\n html: sanitizeHtml(displayText),\n onTick: () => this._drawer?.scrollToBottomIfNeeded(),\n onComplete: () => {\n this._activeTypewriter = null;\n // Link product mentions after typewriter finishes\n if (mentions && mentions.length > 0 && bubbleTextEl) {\n linkProductMentions({\n container: bubbleTextEl,\n mentions,\n onProductClick: (sku) => {\n this._sendAction({\n title: mentions.find((m) => m.sku === sku)?.short_name ?? sku,\n type: 'launchSingleProduct',\n payload: { sku },\n });\n },\n });\n }\n },\n });\n }\n }\n },\n onUISpec: (spec, widget, panelHint) => {\n if (threadId !== this._activeRequestThreadId) return;\n if (widget !== 'chat') return;\n\n const rootElement = spec.elements[spec.root];\n const componentType = rootElement?.type ?? 'unknown';\n this.track(\n streamUiSpecEvent(this.analyticsContext(), {\n request_id: requestId,\n chunk_index: chunkIndex,\n component_type: componentType,\n widget: 'chat',\n }),\n );\n\n const renderContext = this._buildRenderContext();\n\n const panelSpec = panelHint === 'panel' ? this._toPanelSpec(spec) : spec;\n const shouldRenderInline =\n !botMsg.silent &&\n (panelHint !== 'panel' || componentType === 'ProductCard') &&\n componentType !== 'ActionButtons'; // ActionButtons render as bottom pills only\n\n if (panelHint === 'panel') {\n panelContentReceived = true;\n\n // productDetailsSimilars: append to existing ProductDetailsPanel instead of replacing\n // Never append to loading skeleton — always replace it\n if (\n rootElement?.props?.['similarsAppend'] === true &&\n this._currentPanelType === 'ProductDetailsPanel' &&\n this._drawer?.hasPanelContent() &&\n !this._drawer.isPanelLoading()\n ) {\n this._appendSimilarsToPanel(panelSpec, renderContext);\n } else if (\n componentType === 'ProductGrid' &&\n this._drawer?.hasPanelContent() &&\n !this._drawer.isPanelLoading()\n ) {\n // Append ProductGrid (similar products) below existing panel content\n this._drawer.appendPanelContent(this._renderUISpec(panelSpec, renderContext));\n } else {\n this._drawer?.setPanelContent(this._renderUISpec(panelSpec, renderContext));\n this._currentPanelType = componentType;\n }\n\n // Track panel thread and update topbar + extended mode\n if (botMsg.threadId && !this._panelThreads.includes(botMsg.threadId)) {\n this._panelThreads.push(botMsg.threadId);\n }\n // Use the primary panel type for title (don't let appended grids overwrite it)\n const titleType = this._currentPanelType ?? componentType;\n this._updatePanelTopBar(titleType);\n this._updateExtendedModeForPanel(componentType);\n }\n\n if (shouldRenderInline) {\n const messagesContainer = this._shadow?.querySelector('.gengage-chat-messages');\n if (messagesContainer) {\n const inline = this._renderUISpec(spec, renderContext);\n if (botMsg.threadId) {\n inline.dataset['threadId'] = botMsg.threadId;\n }\n messagesContainer.appendChild(inline);\n inline.scrollIntoView({ behavior: 'smooth', block: 'end' });\n }\n }\n\n // Track product thumbnails for ThumbnailsColumn\n if ((componentType === 'ProductGrid' || componentType === 'ProductCard') && botMsg.threadId) {\n const childIds = rootElement?.children ?? [];\n const products =\n componentType === 'ProductGrid'\n ? (childIds\n .map((id) => spec.elements[id]?.props?.['product'] as Record<string, unknown> | undefined)\n .filter(Boolean) as Record<string, unknown>[])\n : ([rootElement?.props?.['product'] as Record<string, unknown> | undefined].filter(Boolean) as Record<\n string,\n unknown\n >[]);\n\n for (const product of products) {\n const sku = product['sku'] as string | undefined;\n const imageUrl = product['imageUrl'] as string | undefined;\n if (sku && imageUrl) {\n this._thumbnailEntries.push({ sku, imageUrl, threadId: botMsg.threadId });\n }\n }\n this._drawer?.setThumbnails(this._thumbnailEntries);\n }\n\n // Send preview images to host for launcher thumbnails\n if (componentType === 'ProductGrid' || componentType === 'ProductDetailsPanel') {\n const previewProducts =\n componentType === 'ProductGrid'\n ? ((rootElement?.children ?? [])\n .map((id) => spec.elements[id]?.props?.['product'] as Record<string, unknown> | undefined)\n .filter(Boolean) as Record<string, unknown>[])\n : ([\n (rootElement?.props?.['product'] ?? rootElement?.props) as Record<string, unknown> | undefined,\n ].filter(Boolean) as Record<string, unknown>[]);\n const previewImageUrls = previewProducts\n .map((p) => p['imageUrl'] as string | undefined)\n .filter((url): url is string => typeof url === 'string')\n .slice(0, 5);\n if (previewImageUrls.length > 0) {\n this._bridge?.send('previewImages', { images: previewImageUrls });\n }\n }\n\n // Show ChoicePrompter when ProductGrid in panel and comparison mode is not active\n if (\n componentType === 'ProductGrid' &&\n panelHint === 'panel' &&\n !this._comparisonSelectMode &&\n !isChoicePrompterDismissed()\n ) {\n this._choicePrompterEl?.remove();\n this._choicePrompterEl = createChoicePrompter({\n heading: this._i18n.choicePrompterHeading,\n suggestion: this._i18n.choicePrompterSuggestion,\n ctaLabel: this._i18n.choicePrompterCta,\n onCtaClick: () => {\n this._comparisonSelectMode = true;\n this._choicePrompterEl = null;\n },\n onDismiss: () => {\n this._choicePrompterEl = null;\n },\n });\n // Append to panel element\n const panelEl = this._shadow?.querySelector('.gengage-chat-panel');\n panelEl?.appendChild(this._choicePrompterEl);\n }\n\n // Extract suggestion pills / input-area chips from ActionButtons UISpec\n if (componentType === 'ActionButtons') {\n const buttons = rootElement?.props?.['buttons'] as\n | Array<{\n label: string;\n action: ActionPayload;\n icon?: string;\n image?: string;\n description?: string;\n }>\n | undefined;\n if (buttons && buttons.length > 0) {\n const inputChips: Array<{ label: string; icon?: string | undefined; action: ActionPayload }> = [];\n const pillButtons: typeof buttons = [];\n\n for (const btn of buttons) {\n if (isInputAreaAction(btn)) {\n const chip: { label: string; icon?: string | undefined; action: ActionPayload } = {\n label: btn.label,\n action: btn.action,\n };\n if (btn.icon) chip.icon = btn.icon;\n inputChips.push(chip);\n } else {\n pillButtons.push(btn);\n }\n }\n\n if (inputChips.length > 0) {\n this._drawer?.setInputAreaChips(\n inputChips.map((chip) => ({\n label: chip.label,\n onAction: () => this._sendAction(chip.action),\n ...(chip.icon ? { icon: chip.icon } : {}),\n })),\n );\n }\n\n if (pillButtons.length > 0) {\n this._drawer?.setPills(\n pillButtons.map((btn) => {\n const pill: {\n label: string;\n onAction: () => void;\n icon?: string;\n image?: string;\n description?: string;\n } = {\n label: btn.label,\n onAction: () => this._sendAction(btn.action),\n };\n if (btn.icon) pill.icon = btn.icon;\n if (btn.image) pill.image = btn.image;\n if (btn.description) pill.description = btn.description;\n return pill;\n }),\n );\n }\n }\n }\n\n botMsg.uiSpec = spec;\n },\n onAction: (event: StreamEvent) => {\n if (threadId !== this._activeRequestThreadId) return;\n if (event.type === 'action') {\n const routerOpts: ActionRouterOptions = {};\n if (this.config.actionHandling?.unknownActionPolicy !== undefined) {\n routerOpts.unknownActionPolicy = this.config.actionHandling.unknownActionPolicy;\n }\n if (this.config.actionHandling?.allowScriptCall !== undefined) {\n routerOpts.allowScriptCall = this.config.actionHandling.allowScriptCall;\n }\n routeStreamAction(\n event as StreamEventAction,\n {\n openChat: () => this.open(),\n navigate: (params) => {\n this._bridge?.send('navigate', params);\n if (params.newTab) {\n window.open(params.url, '_blank', 'noopener,noreferrer');\n } else {\n window.location.href = params.url;\n }\n },\n saveSession: (params) => this.saveSession(params.sessionId, params.sku),\n addToCart: (params) => {\n dispatch('gengage:similar:add-to-cart', params);\n },\n scriptCall: (params) => {\n dispatch('gengage:chat:script-call', params);\n this.config.onScriptCall?.(params);\n },\n },\n routerOpts,\n );\n }\n },\n onMetadata: (event: StreamEvent) => {\n if (threadId !== this._activeRequestThreadId) return;\n if (event.type === 'metadata' && event.meta) {\n // Store backend context for sending with next request\n if (\n event.meta.panel !== undefined ||\n event.meta.messages !== undefined ||\n event.meta.message_id !== undefined\n ) {\n this._lastBackendContext = event.meta as Record<string, unknown>;\n }\n\n // Panel loading indicator\n if (event.meta.panelLoading) {\n panelLoadingSeen = true;\n panelContentReceived = false;\n const pendingType =\n typeof event.meta.panelPendingType === 'string' ? event.meta.panelPendingType : undefined;\n this._currentPanelType = null;\n this._drawer?.showPanelLoading(pendingType);\n // Set panel topbar title immediately so it's not an empty white bar\n if (pendingType) {\n this._updatePanelTopBarForLoading(pendingType);\n }\n }\n\n // Optional voice payload emitted by v1 backend when voiceEnabled is true.\n if (event.meta.voice) {\n dispatch('gengage:chat:voice', { payload: event.meta.voice });\n }\n\n if (event.meta.redirectTarget || event.meta.redirect) {\n dispatch('gengage:chat:redirect', {\n target: event.meta.redirectTarget ?? null,\n payload: event.meta.redirect ?? null,\n });\n }\n\n // Analyze animation — show panel loading skeleton with pulse\n if (event.meta.analyzeAnimation) {\n panelLoadingSeen = true;\n panelContentReceived = false;\n this._currentPanelType = null;\n this._drawer?.showPanelLoading();\n // Default to product details title during analyze\n this._updatePanelTopBarForLoading('productDetails');\n }\n\n // Thinking step messages — accumulate as checklist in typing indicator\n if (event.meta.loading && typeof event.meta.loadingText === 'string') {\n this._drawer?.addThinkingStep(event.meta.loadingText);\n this._bridge?.send('loadingMessage', { text: event.meta.loadingText });\n }\n\n // Forward visitor engagement data to host page\n if (event.meta.visitorDataResponse) {\n this._bridge?.send('engagingMessage', event.meta.visitorDataResponse);\n }\n\n // Forward form events to host via bridge (Otokoc-specific)\n if (event.meta.formType) {\n this._bridge?.send('glovOtokoc', {\n type: event.meta.formType,\n data: event.meta.formPayload,\n });\n }\n\n // Forward launcher content to host via bridge\n if (event.meta.launcherContent) {\n this._bridge?.send('launcherContent', event.meta.launcherContent);\n }\n\n dispatch('gengage:chat:metadata', { payload: event.meta });\n\n // Extract LLM usage from metadata if present\n const meta = event.meta;\n if (typeof meta.prompt_tokens === 'number' && typeof meta.completion_tokens === 'number') {\n this.track(\n llmUsageEvent(this.analyticsContext(), {\n model: event.model ?? 'unknown',\n prompt_tokens: meta.prompt_tokens as number,\n completion_tokens: meta.completion_tokens as number,\n total_tokens:\n (meta.total_tokens as number) ??\n (meta.prompt_tokens as number) + (meta.completion_tokens as number),\n }),\n );\n }\n }\n },\n onError: (err) => {\n // Skip error handling for aborted/superseded requests\n if (threadId !== this._activeRequestThreadId && this._activeRequestThreadId !== null) return;\n this._bridge?.send('isResponding', false);\n this._bridge?.send('loadingMessage', { text: null });\n this._drawer?.removeTypingIndicator();\n if (panelLoadingSeen && !panelContentReceived && this._drawer?.isPanelLoading()) {\n this._drawer.clearPanel();\n }\n panelLoadingSeen = false;\n panelContentReceived = false;\n dispatch('gengage:global:error', {\n source: 'chat',\n code: 'STREAM_ERROR',\n message: this._i18n.errorMessage,\n });\n this._drawer?.showError(err.message);\n botMsg.status = 'error';\n\n this.track(\n streamErrorEvent(this.analyticsContext(), {\n request_id: requestId,\n error_code: 'STREAM_ERROR',\n error_message: err.message,\n widget: 'chat',\n }),\n );\n },\n onDone: () => {\n // Skip cleanup for aborted/superseded requests\n if (threadId !== this._activeRequestThreadId && this._activeRequestThreadId !== null) return;\n this._activeRequestThreadId = null;\n this._bridge?.send('isResponding', false);\n this._bridge?.send('loadingMessage', { text: null });\n this._drawer?.removeTypingIndicator();\n if (panelLoadingSeen && !panelContentReceived && this._drawer?.isPanelLoading()) {\n this._drawer.clearPanel();\n }\n panelLoadingSeen = false;\n panelContentReceived = false;\n if (botMsg.status === 'streaming') {\n botMsg.status = 'done';\n }\n\n // Snapshot current panel content for this message's history\n this._snapshotPanelForMessage(botMsg.id);\n // Make the bot message bubble clickable to restore its panel state\n this._attachMessageClickHandler(botMsg.id);\n\n this.track(\n streamDoneEvent(this.analyticsContext(), {\n request_id: requestId,\n latency_ms: Date.now() - streamStart,\n chunk_count: chunkIndex,\n widget: 'chat',\n }),\n );\n\n this.track(\n meteringIncrementEvent(this.analyticsContext(), {\n meter_key: 'chat_request',\n quantity: 1,\n unit: 'request',\n }),\n );\n\n this.track(\n chatHistorySnapshotEvent(this.analyticsContext(), {\n message_count: this._messages.length,\n history_ref: this.config.session?.sessionId ?? '',\n redaction_level: 'none',\n }),\n );\n\n // Persist session to IndexedDB (fire-and-forget)\n this._persistToIndexedDB().catch(() => {\n /* non-fatal */\n });\n },\n },\n transport,\n );\n }\n\n /** Return messages visible at the current thread cursor. */\n private _getVisibleMessages(): ChatMessage[] {\n const msgs = this._messages.filter((m) => !m.silent);\n if (!this._currentThreadId) return msgs;\n const cutoff = this._currentThreadId;\n return msgs.filter((m) => !m.threadId || m.threadId <= cutoff);\n }\n\n /** Handle rollback-on-click from a user message bubble. */\n private _appendSimilarsToPanel(spec: UISpec, ctx: import('../chat/types.js').ChatUISpecRenderContext): void {\n if (!this._drawer) return;\n const panelEl = this._drawer.getPanelContentElement();\n if (!panelEl) return;\n const heading = document.createElement('h3');\n heading.className = 'gengage-chat-product-details-similars-heading';\n heading.textContent = this._i18n.similarProductsLabel ?? 'Benzer Ürünler';\n panelEl.appendChild(heading);\n const grid = this._renderUISpec(spec, ctx);\n grid.classList.add('gengage-chat-product-details-similars');\n panelEl.appendChild(grid);\n }\n\n private _handleRollback(messageId: string): void {\n const msg = this._messages.find((m) => m.id === messageId);\n if (!msg?.threadId) return;\n this._rollbackToThread(msg.threadId);\n }\n\n /** Rewind the conversation to the given thread. */\n private _rollbackToThread(threadId: string): void {\n this._currentThreadId = threadId;\n this._extendedModeManager?.setHiddenByUser(false);\n\n // Toggle visibility of messages after the cutoff\n for (const msg of this._messages) {\n const bubble = this._shadow?.querySelector(`[data-message-id=\"${msg.id}\"]`);\n if (!bubble) continue;\n if (msg.threadId && msg.threadId > threadId) {\n bubble.classList.add('gengage-chat-bubble--hidden');\n } else {\n bubble.classList.remove('gengage-chat-bubble--hidden');\n }\n }\n\n // Hide inline UISpec elements from future threads\n this._shadow?.querySelectorAll('[data-thread-id]').forEach((el) => {\n if (el instanceof HTMLElement && el.dataset['threadId'] && el.dataset['threadId'] > threadId) {\n el.classList.add('gengage-chat-bubble--hidden');\n } else if (el instanceof HTMLElement) {\n el.classList.remove('gengage-chat-bubble--hidden');\n }\n });\n\n // Restore panel snapshot from the target thread's bot message\n const targetBot = this._messages.find((m) => m.role === 'assistant' && m.threadId === threadId);\n const restored = targetBot ? this._restorePanelForMessage(targetBot.id) : false;\n if (!restored) {\n this._drawer?.clearPanel();\n }\n // Always update topbar navigation state for the new thread position\n const panelType = this._currentPanelType ?? '';\n this._updatePanelTopBar(panelType);\n\n // Clear suggestion pills (they belong to the latest thread)\n this._drawer?.setPills([]);\n\n // Load context from IndexedDB for the target thread so the next request\n // sends the correct historical context (not the latest one).\n if (this._indexedDB && this.config.session?.sessionId) {\n this._indexedDB\n .loadContext(this.config.session.sessionId, threadId)\n .then((ctx) => {\n if (ctx) this._lastBackendContext = ctx.context;\n })\n .catch(() => {\n /* non-fatal */\n });\n }\n\n // Prune future context entries from IndexedDB\n if (this._indexedDB && this.config.session?.sessionId) {\n this._indexedDB.deleteContextsAfterThread(this.config.session.sessionId, threadId).catch(() => {\n /* non-fatal */\n });\n }\n }\n\n // ---------------------------------------------------------------------------\n // IndexedDB persistence\n // ---------------------------------------------------------------------------\n\n /**\n * Persist current session state to IndexedDB.\n * Called after each stream completion (onDone). Non-fatal on failure.\n */\n private async _persistToIndexedDB(): Promise<void> {\n if (!this._indexedDB || !this.config.session?.sessionId) return;\n\n const serializableMessages: SerializableChatMessage[] = this._messages.map((m) => {\n const sm: SerializableChatMessage = {\n id: m.id,\n role: m.role,\n timestamp: m.timestamp,\n status: m.status === 'streaming' ? 'done' : m.status,\n };\n if (m.threadId !== undefined) sm.threadId = m.threadId;\n if (m.content !== undefined) sm.content = m.content;\n if (m.silent) sm.silent = true;\n return sm;\n });\n\n // Serialize panel snapshots to HTML strings (never persist loading skeletons)\n const panelSnapshotHtml: Record<string, string> = {};\n for (const [msgId, el] of this._panelSnapshots) {\n if (el.querySelector('.gengage-chat-panel-skeleton')) continue;\n panelSnapshotHtml[msgId] = el.innerHTML;\n }\n\n await this._indexedDB.saveSession({\n userId: this.config.session.userId ?? '',\n appId: this.config.accountId,\n sessionId: this.config.session.sessionId,\n messages: serializableMessages,\n currentThreadId: this._currentThreadId,\n lastThreadId: this._lastThreadId,\n createdAt: this._chatCreatedAt,\n panelThreads: this._panelThreads.length > 0 ? this._panelThreads : undefined,\n thumbnailEntries: this._thumbnailEntries.length > 0 ? this._thumbnailEntries : undefined,\n panelSnapshotHtml: Object.keys(panelSnapshotHtml).length > 0 ? panelSnapshotHtml : undefined,\n });\n\n // Save latest context snapshot for current thread\n if (this._lastBackendContext && this._currentThreadId) {\n await this._indexedDB.saveContext({\n sessionId: this.config.session.sessionId,\n threadId: this._currentThreadId,\n context: this._lastBackendContext,\n });\n }\n\n // Save UISpec payloads separately, then clear from in-memory messages\n for (const m of this._messages) {\n if (m.uiSpec && m.threadId) {\n await this._indexedDB.savePayload({\n threadId: m.threadId,\n messageId: m.id,\n uiSpec: m.uiSpec,\n });\n // Clear UISpec from in-memory message to free memory (lean pattern)\n delete m.uiSpec;\n }\n }\n\n // Set sessionStorage flag so restore works on re-open within same page session\n try {\n sessionStorage.setItem('gengage_restore_session_id', this.config.session.sessionId);\n } catch {\n // sessionStorage unavailable — silently ignore\n }\n }\n\n /**\n * Persist session to IndexedDB, then send openURLInNewTab bridge message.\n * Used by product clicks and bot HTML link clicks so the session can be\n * restored when the user returns from navigation.\n */\n private async _saveSessionAndOpenURL(url: string): Promise<void> {\n try {\n await this._persistToIndexedDB();\n } catch {\n // Non-fatal — still navigate\n }\n this._bridge?.send('openURLInNewTab', { url });\n }\n\n /**\n * Load a UISpec payload from IndexedDB with retry logic.\n * Returns null if not found or all retries fail.\n */\n private async _loadPayload(threadId: string, messageId: string): Promise<import('../common/types.js').UISpec | null> {\n if (!this._indexedDB) return null;\n\n for (let attempt = 0; attempt < 3; attempt++) {\n try {\n const payload = await this._indexedDB.loadPayload(threadId, messageId);\n if (payload) return payload.uiSpec;\n } catch {\n // Retry after delay\n }\n if (attempt < 2) {\n await new Promise((r) => setTimeout(r, 100));\n }\n }\n return null;\n }\n\n /**\n * Attempt to restore chat session from IndexedDB.\n * Always restores when IDB has session data for the current sessionId.\n * Best-effort — failures are silently ignored.\n */\n private async _restoreFromIndexedDB(): Promise<void> {\n if (!this._indexedDB) return;\n const sessionId = this.config.session?.sessionId;\n if (!sessionId) return;\n\n const userId = this.config.session?.userId ?? '';\n const appId = this.config.accountId;\n\n // Restore favorited SKUs from IDB\n try {\n const favs = await this._indexedDB.loadFavorites(userId, appId);\n for (const f of favs) this._favoritedSkus.add(f.sku);\n } catch {\n // Non-fatal — continue without favorites\n }\n\n const session = await this._indexedDB.loadSession(userId, appId, sessionId);\n if (!session || session.messages.length === 0) return;\n\n // Prevent duplicate auto-launch: session already has messages, so PDP launch already happened\n this._pdpLaunched = true;\n\n // Lock auto-scroll during restore to prevent visual jump\n this._drawer?.lockScrollForRestore();\n\n // Restore thread cursors and creation timestamp\n this._currentThreadId = session.currentThreadId;\n this._lastThreadId = session.lastThreadId;\n this._chatCreatedAt = session.createdAt;\n\n // Restore panel threads and thumbnail entries\n if (session.panelThreads) {\n this._panelThreads = session.panelThreads;\n }\n if (session.thumbnailEntries) {\n this._thumbnailEntries = session.thumbnailEntries;\n this._drawer?.setThumbnails(this._thumbnailEntries);\n }\n\n // Restore panel snapshots from serialized HTML\n if (session.panelSnapshotHtml) {\n for (const [msgId, html] of Object.entries(session.panelSnapshotHtml)) {\n const container = document.createElement('div');\n container.innerHTML = html;\n this._panelSnapshots.set(msgId, container);\n }\n }\n\n // Track highest message ID to avoid collisions with new messages\n let maxMsgNum = 0;\n\n // Replay messages into DOM\n for (const msg of session.messages) {\n const chatMsg: ChatMessage = {\n id: msg.id,\n role: msg.role,\n timestamp: msg.timestamp,\n status: msg.status,\n };\n if (msg.threadId !== undefined) chatMsg.threadId = msg.threadId;\n if (msg.content !== undefined) chatMsg.content = msg.content;\n if (msg.silent) chatMsg.silent = true;\n\n this._messages.push(chatMsg);\n\n // Skip silent messages from DOM rendering\n if (chatMsg.silent) continue;\n\n if (chatMsg.role === 'assistant' && chatMsg.threadId && !this._threadsWithFirstBot.has(chatMsg.threadId)) {\n this._threadsWithFirstBot.add(chatMsg.threadId);\n this._drawer?.markFirstBotMessage(chatMsg.id);\n }\n this._drawer?.addMessage(chatMsg);\n\n // Track message ID counter\n const idNum = parseInt(msg.id.replace('msg-', ''), 10);\n if (!isNaN(idNum) && idNum > maxMsgNum) maxMsgNum = idNum;\n\n // Re-render inline UISpec elements for bot messages (load from payload store)\n if (chatMsg.role === 'assistant' && chatMsg.threadId) {\n const uiSpec = await this._loadPayload(chatMsg.threadId, chatMsg.id);\n if (uiSpec) {\n chatMsg.uiSpec = uiSpec;\n this._restoreInlineUISpec(chatMsg);\n this._attachMessageClickHandler(chatMsg.id);\n // Clear after render to maintain lean pattern\n delete chatMsg.uiSpec;\n }\n }\n }\n\n // Advance message ID counter past restored messages\n if (maxMsgNum > this._currentMessageId) {\n this._currentMessageId = maxMsgNum;\n }\n\n // Restore backend context with fallback chain\n if (this._currentThreadId) {\n let ctx = await this._indexedDB.loadContext(sessionId, this._currentThreadId);\n if (!ctx) {\n ctx = await this._indexedDB.loadLatestContext(sessionId);\n }\n if (ctx) this._lastBackendContext = ctx.context;\n }\n\n // Restore panel for the current thread's latest bot message\n if (this._currentThreadId) {\n const panelBot = [...this._messages]\n .reverse()\n .find((m) => m.role === 'assistant' && m.threadId === this._currentThreadId && !m.silent);\n if (panelBot && this._panelSnapshots.has(panelBot.id)) {\n this._restorePanelForMessage(panelBot.id);\n }\n }\n\n // Apply thread visibility — hide messages from future threads\n if (this._currentThreadId) {\n const cutoff = this._currentThreadId;\n for (const msg of this._messages) {\n if (msg.threadId && msg.threadId > cutoff) {\n const bubble = this._shadow?.querySelector(`[data-message-id=\"${msg.id}\"]`);\n bubble?.classList.add('gengage-chat-bubble--hidden');\n }\n }\n this._shadow?.querySelectorAll('[data-thread-id]').forEach((el) => {\n if (el instanceof HTMLElement && el.dataset['threadId'] && el.dataset['threadId'] > cutoff) {\n el.classList.add('gengage-chat-bubble--hidden');\n }\n });\n }\n\n // Update panel topbar if we have panel threads\n if (this._panelThreads.length > 0 && this._currentThreadId) {\n const lastPanelThread = this._panelThreads[this._panelThreads.length - 1];\n if (lastPanelThread) {\n const lastPanelBot = [...this._messages]\n .reverse()\n .find((m) => m.role === 'assistant' && m.threadId === lastPanelThread);\n if (lastPanelBot?.threadId) {\n const uiSpec = await this._loadPayload(lastPanelBot.threadId, lastPanelBot.id);\n if (uiSpec) {\n const rootEl = uiSpec.elements[uiSpec.root];\n if (rootEl) {\n this._updatePanelTopBar(rootEl.type);\n }\n }\n }\n }\n }\n\n // After lockout expires, scroll to last thread boundary instead of absolute bottom\n setTimeout(() => {\n this._drawer?.scrollToLastThread();\n }, 550);\n }\n\n /**\n * Build a ChatUISpecRenderContext with all callbacks wired up.\n * Used both during streaming and during session restore.\n */\n private _buildRenderContext(): ChatUISpecRenderContext {\n const ctx: ChatUISpecRenderContext = {\n onAction: (action) => this._sendAction(action),\n onProductClick: (params) => {\n dispatch('gengage:similar:product-click', {\n sku: params.sku,\n url: params.url,\n sessionId: this.config.session?.sessionId ?? null,\n });\n this._saveSessionAndOpenURL(params.url);\n },\n onAddToCart: (params) => {\n dispatch('gengage:chat:add-to-cart', {\n ...params,\n sessionId: this.config.session?.sessionId ?? null,\n });\n this._bridge?.send('addToCart', params);\n },\n onProductSelect: (product) => {\n const detailSpec: import('../common/types.js').UISpec = {\n root: 'root',\n elements: {\n root: {\n type: 'ProductDetailsPanel',\n props: { product },\n },\n },\n };\n this._drawer?.setPanelContent(this._renderUISpec(detailSpec, ctx));\n },\n i18n: {\n productCtaLabel: this._i18n.productCtaLabel,\n aiTopPicksTitle: this._i18n.aiTopPicksTitle,\n roleWinner: this._i18n.roleWinner,\n roleBestValue: this._i18n.roleBestValue,\n roleBestAlternative: this._i18n.roleBestAlternative,\n viewDetails: this._i18n.viewDetails,\n groundingReviewCta: this._i18n.groundingReviewCta,\n variantsLabel: this._i18n.variantsLabel,\n sortRelated: this._i18n.sortRelated,\n sortPriceAsc: this._i18n.sortPriceAsc,\n sortPriceDesc: this._i18n.sortPriceDesc,\n compareSelected: this._i18n.compareSelected,\n panelTitleProductDetails: this._i18n.panelTitleProductDetails,\n panelTitleSimilarProducts: this._i18n.panelTitleSimilarProducts,\n panelTitleComparisonResults: this._i18n.panelTitleComparisonResults,\n panelTitleCategories: this._i18n.panelTitleCategories,\n inStockLabel: this._i18n.inStockLabel,\n outOfStockLabel: this._i18n.outOfStockLabel,\n findSimilarLabel: this._i18n.findSimilarLabel,\n viewMoreLabel: this._i18n.viewMoreLabel,\n similarProductsLabel: this._i18n.similarProductsLabel,\n },\n productSort: this._productSort,\n onSortChange: (sort) => {\n this._productSort = sort;\n },\n comparisonSelectMode: this._comparisonSelectMode,\n comparisonSelectedSkus: this._comparisonSelectedSkus,\n onToggleComparisonSku: (sku) => {\n if (sku === '') {\n this._comparisonSelectMode = !this._comparisonSelectMode;\n if (!this._comparisonSelectMode) {\n this._comparisonSelectedSkus = [];\n }\n } else {\n const idx = this._comparisonSelectedSkus.indexOf(sku);\n if (idx >= 0) {\n this._comparisonSelectedSkus = this._comparisonSelectedSkus.filter((s) => s !== sku);\n } else {\n this._comparisonSelectedSkus = [...this._comparisonSelectedSkus, sku];\n }\n }\n },\n favoritedSkus: this._favoritedSkus,\n onFavoriteToggle: (sku, product) => {\n void this._toggleFavorite(sku, product);\n },\n };\n return ctx;\n }\n\n private async _toggleFavorite(sku: string, product: Record<string, unknown>): Promise<void> {\n if (!this._indexedDB) return;\n const userId = this.config.session?.userId ?? '';\n const appId = this.config.accountId;\n if (this._favoritedSkus.has(sku)) {\n this._favoritedSkus.delete(sku);\n await this._indexedDB.removeFavorite(userId, appId, sku);\n } else {\n this._favoritedSkus.add(sku);\n await this._indexedDB.saveFavorite({\n userId,\n appId,\n sku,\n name: product['name'] as string | undefined,\n imageUrl: product['imageUrl'] as string | undefined,\n price: product['price'] as string | undefined,\n savedAt: new Date().toISOString(),\n });\n }\n }\n\n /**\n * Re-render inline UISpec elements for a restored bot message.\n * Inserts them into the messages container after the message bubble.\n */\n private _restoreInlineUISpec(chatMsg: ChatMessage): void {\n if (!chatMsg.uiSpec || !this._drawer) return;\n const spec = chatMsg.uiSpec;\n const rootElement = spec.elements[spec.root];\n if (!rootElement) return;\n\n const componentType = rootElement.type;\n\n // ActionButtons are rendered as pills/chips, not inline\n if (componentType === 'ActionButtons') return;\n\n // Panel-only components should not be rendered inline (except ProductCard)\n const panelHint = rootElement.props?.['panelHint'] as string | undefined;\n if (panelHint === 'panel' && componentType !== 'ProductCard') return;\n\n const renderContext = this._buildRenderContext();\n const messagesContainer = this._shadow?.querySelector('.gengage-chat-messages');\n if (!messagesContainer) return;\n\n const inline = this._renderUISpec(spec, renderContext);\n if (chatMsg.threadId) {\n inline.dataset['threadId'] = chatMsg.threadId;\n }\n messagesContainer.appendChild(inline);\n }\n\n private _createMessage(role: 'user' | 'assistant', content: string): ChatMessage {\n this._currentMessageId++;\n return {\n id: `msg-${this._currentMessageId}`,\n role,\n content,\n timestamp: Date.now(),\n status: 'done',\n };\n }\n\n private _resolveI18n(config: ChatWidgetConfig): ChatI18n {\n const base = resolveChatLocale(config.locale);\n return { ...base, ...config.i18n };\n }\n\n private _resolveUISpecRegistry(): ChatUISpecRegistry {\n const baseRegistry = createDefaultChatUISpecRegistry();\n return mergeUISpecRegistry(baseRegistry, this.config.renderer?.registry);\n }\n\n private _renderUISpec(spec: UISpec, context: ChatUISpecRenderContext): HTMLElement {\n const registry = this._resolveUISpecRegistry();\n const unknownRenderer = this.config.renderer?.unknownRenderer ?? defaultChatUnknownUISpecRenderer;\n const defaultRender = (inputSpec: UISpec, inputContext: ChatUISpecRenderContext) =>\n renderUISpec(inputSpec, inputContext, registry, unknownRenderer);\n\n const override = this.config.renderer?.renderUISpec;\n if (!override) return defaultRender(spec, context);\n\n const helpers: UISpecRenderHelpers<ChatUISpecRenderContext> = {\n registry,\n unknownRenderer,\n defaultRender,\n };\n return override(spec, context, helpers);\n }\n\n /**\n * Deep-clone the current panel content (excluding topbar/thumbnails) and store\n * it keyed by message ID. Called when a stream completes so panel content can\n * be restored later without duplicating the topbar.\n */\n private _snapshotPanelForMessage(messageId: string): void {\n if (!this._drawer?.hasPanelContent()) return;\n // Never snapshot loading skeleton — it must not be persisted or restored\n if (this._drawer.isPanelLoading()) return;\n const contentEl = this._drawer.getPanelContentElement();\n if (!contentEl) return;\n const clone = contentEl.cloneNode(true) as HTMLElement;\n this._panelSnapshots.set(messageId, clone);\n // Store the component type so topbar can be restored with the right title\n if (this._currentPanelType) {\n this._panelSnapshotTypes.set(messageId, this._currentPanelType);\n }\n }\n\n /**\n * Attach a click handler to a bot message bubble so clicking it restores\n * the panel content that was active when that message was received.\n */\n private _attachMessageClickHandler(messageId: string): void {\n const bubble = this._shadow?.querySelector(`[data-message-id=\"${messageId}\"]`);\n if (!bubble) return;\n (bubble as HTMLElement).style.cursor = 'pointer';\n bubble.addEventListener('click', () => this._restorePanelForMessage(messageId));\n }\n\n /**\n * Restore the panel content snapshot associated with a given message ID.\n * Highlights the active message and de-highlights the previous one.\n * Also restores the panel topbar title for the snapshot's component type.\n * Returns true if the snapshot was found and restored.\n */\n private _restorePanelForMessage(messageId: string): boolean {\n const snapshot = this._panelSnapshots.get(messageId);\n if (!snapshot) return false;\n\n // De-highlight previous active message\n if (this._activePanelMessageId) {\n const prev = this._shadow?.querySelector(`[data-message-id=\"${this._activePanelMessageId}\"]`);\n prev?.classList.remove('gengage-chat-bubble--active');\n }\n\n // Highlight the clicked message\n const current = this._shadow?.querySelector(`[data-message-id=\"${messageId}\"]`);\n current?.classList.add('gengage-chat-bubble--active');\n this._activePanelMessageId = messageId;\n\n // Restore panel content from snapshot clone\n this._drawer?.setPanelContent(snapshot.cloneNode(true) as HTMLElement);\n\n // Restore component type and topbar\n const snapshotType = this._panelSnapshotTypes.get(messageId);\n if (snapshotType) {\n this._currentPanelType = snapshotType;\n }\n return true;\n }\n\n /**\n * Send maximize-pdp / minify-pdp bridge messages with production-matching delays.\n * Called by the extended mode manager (Group H) when panel extension state changes.\n */\n private _notifyPanelExtension(extended: boolean): void {\n if (extended) {\n setTimeout(() => this._bridge?.send('maximize-pdp', {}), 350);\n } else {\n setTimeout(() => this._bridge?.send('minify-pdp', {}), 200);\n }\n }\n\n /**\n * Derive panel title from UISpec root element type using i18n strings.\n */\n private _panelTitleForComponent(componentType: string): string {\n switch (componentType) {\n case 'ProductDetailsPanel':\n return this._i18n.panelTitleProductDetails;\n case 'ProductGrid':\n return this._i18n.panelTitleSimilarProducts;\n case 'ComparisonTable':\n return this._i18n.panelTitleComparisonResults;\n case 'AIGroupingCards':\n return this._i18n.panelTitleCategories;\n default:\n return '';\n }\n }\n\n /**\n * Update the panel top bar navigation state and title.\n */\n private _updatePanelTopBar(componentType: string): void {\n if (!this._currentThreadId) return;\n const idx = this._panelThreads.indexOf(this._currentThreadId);\n const canBack = idx > 0;\n const canForward = idx >= 0 && idx < this._panelThreads.length - 1;\n const title = this._panelTitleForComponent(componentType);\n this._drawer?.updatePanelTopBar(canBack, canForward, title);\n }\n\n /**\n * Set panel topbar title during loading (before actual panel content arrives).\n * Maps backend pending types to the same i18n titles used for final content.\n */\n private _updatePanelTopBarForLoading(pendingType: string): void {\n const loadingTitleMap: Record<string, string> = {\n productDetails: this._i18n.panelTitleProductDetails,\n productList: this._i18n.panelTitleSimilarProducts,\n comparisonTable: this._i18n.panelTitleComparisonResults,\n groupList: this._i18n.panelTitleCategories,\n };\n const title = loadingTitleMap[pendingType] ?? '';\n if (title) {\n const idx = this._currentThreadId ? this._panelThreads.indexOf(this._currentThreadId) : -1;\n const canBack = idx > 0;\n const canForward = idx >= 0 && idx < this._panelThreads.length - 1;\n this._drawer?.updatePanelTopBar(canBack, canForward, title);\n }\n }\n\n /**\n * Map UISpec component types to PanelContentType for the extended mode manager.\n */\n private _updateExtendedModeForPanel(componentType: string): void {\n const mapping: Record<string, PanelContentType> = {\n ComparisonTable: 'comparisonTable',\n AIGroupingCards: 'groupList',\n ProductDetailsPanel: 'productDetails',\n ProductGrid: 'productList',\n };\n const panelType = mapping[componentType] ?? null;\n this._extendedModeManager?.setPanelContentType(panelType);\n }\n\n /** Navigate to the previous panel thread. */\n private _navigatePanelBack(): void {\n if (!this._currentThreadId) return;\n const idx = this._panelThreads.indexOf(this._currentThreadId);\n if (idx > 0) {\n const targetThread = this._panelThreads[idx - 1];\n if (targetThread) {\n this._rollbackToThread(targetThread);\n }\n }\n }\n\n /** Navigate to the next panel thread. */\n private _navigatePanelForward(): void {\n if (!this._currentThreadId) return;\n const idx = this._panelThreads.indexOf(this._currentThreadId);\n if (idx >= 0 && idx < this._panelThreads.length - 1) {\n const targetThread = this._panelThreads[idx + 1];\n if (targetThread) {\n this._rollbackToThread(targetThread);\n }\n }\n }\n\n /**\n * Panel route shaping:\n * - product details => expanded LHS panel (`ProductDetailsPanel`)\n * - all other panel-routed specs keep their original component types\n */\n private _toPanelSpec(spec: UISpec): UISpec {\n const root = spec.elements[spec.root];\n if (!root || root.type !== 'ProductCard') return spec;\n\n const panelRoot: import('../common/types.js').UIElement = {\n ...root,\n type: 'ProductDetailsPanel',\n };\n\n return {\n root: spec.root,\n elements: {\n ...spec.elements,\n [spec.root]: panelRoot,\n },\n };\n }\n}\n\n// ---------------------------------------------------------------------------\n// Convenience factory\n// ---------------------------------------------------------------------------\n\nexport function createChatWidget(): GengageChat {\n return new GengageChat();\n}\n\nexport type {\n ChatWidgetConfig,\n ChatMessage,\n ChatSession,\n ChatUIComponents,\n ChatI18n,\n ChatRendererConfig,\n ChatUISpecRenderContext,\n ChatUISpecRegistry,\n ProductSortState,\n SerializableChatMessage,\n} from './types.js';\nexport {\n renderUISpec,\n createDefaultChatUISpecRegistry,\n defaultChatUnknownUISpecRenderer,\n} from './components/renderUISpec.js';\nexport type { UISpecRenderContext } from './components/renderUISpec.js';\nexport { chatCatalog } from './catalog.js';\nexport type { ChatCatalog, ChatComponentName } from './catalog.js';\n"],"names":["uuidv7","now","bytes","hex","b","CommunicationBridge","options","event","type","payload","detail","handler","handlers","data","isValidBridgeData","msg","origin","obj","defaultLogger","routeStreamAction","action","logger","handleUnknownAction","newTab","defaultNavigate","isRecord","policy","url","value","ALLOWED_TAGS","DISALLOWED_TAGS","ALLOWED_ATTRS","hasJavascriptProtocol","sanitizeNode","node","parent","el","tag","children","child","globalAllowed","tagAllowed","attrs","attr","name","href","trimmed","src","sanitizeHtml","raw","body","ALLOWED_MIME_TYPES","MAX_FILE_SIZE","validateImageFile","file","enrichActionPayload","ctx","existing","merge","additions","result","key","ACTION_TYPE_MAP","buildRequestBody","request","rest","mappedType","sendChatMessage","callbacks","transport","buildChatEndpointUrl","controller","requestBody","useFormData","fetchInit","formData","response","consumeStream","normalized","adaptV1Event","err","CHAT_I18N_TR","CHAT_I18N_EN","normalizeLocale","locale","resolveChatLocale","createKvkkBanner","banner","content","dismiss","PanelTopBar","canBack","canForward","title","ThumbnailsColumn","entries","seen","unique","entry","thumb","img","SUGGESTED_ACTION_ICONS","DEFAULT_I18N","ChatDrawer","container","header","headerLeft","avatar","headerInfo","titleRow","badge","powered","headerRight","cartLink","favBtn","closeBtn","chevron","conversation","scrollTop","scrollHeight","clientHeight","threadId","pillsScroll","pillsArrow","atEnd","inputArea","e","attachBtn","previewThumb","removeBtn","pill","footer","message","bubble","thumbEl","text","links","link","rollbackBtn","searchText","indicator","i","sparkle","errEl","pills","scroll","btn","svgHtml","iconSpan","textWrap","desc","arrow","html","onDismiss","contentType","skeleton","imgBlock","line","grid","card","row","block","collapsed","chevronBtn","accountId","list","step","marker","focusable","first","last","active","attachment","force","messageId","allBubbles","lastThreadId","target","chips","chip","label","DEFAULT_SVG","createLauncher","contentArea","button","tooltipEl","contentAreaBottom","createProactivePopup","popup","messageEl","actions","acceptBtn","dismissBtn","timeout","ActivityTracker","docHeight","depth","bucket","SAFE_URL_PROTOCOLS","CRITERIA_DISPLAY_NAMES","formatCriteriaName","rawName","c","isSafeImageUrl","parsed","renderComparisonTable","recommended","products","attributes","highlights","specialCases","onProductClick","heading","recCard","recLabel","recBody","info","price","hlSection","hlLabel","ul","hl","li","recExplanation","kdSection","kdHeading","kdContent","formatKeyDifferences","special","summary","sc","table","thead","headerRow","emptyTh","product","th","prc","tbody","labelTd","td","btnRow","lines","l","renderReviewHighlights","element","reviews","empty","items","r","counts","item","tabBar","filters","activeFilter","itemsContainer","renderItems","filtered","review","cls","tagEl","textEl","ratingEl","f","tab","t","tagCounts","pillsRow","icon","tagText","ROLE_LABELS","getRoleLabel","role","i18n","renderAITopPicks","suggestions","cardsWrap","suggestion","renderTopPickCard","renderCompactCard","discountPercent","discountBadge","imageUrl","nameEl","reasonEl","renderSentimentChips","score","originalPrice","priceRow","orig","formatTurkishPrice","current","sku","spinner","cta","roleLabel","roleEl","priceEl","labels","renderGroundingReviewCard","props","reviewCount","ctaLabel","titleEl","subtitle","renderAIGroupingCards","labelsEl","renderAISuggestedSearchCards","diff","renderFloatingComparisonButton","selectedSkus","renderProsAndCons","productName","pros","cons","prosList","pro","consList","con","renderCategoriesContainer","context","groups","filterTags","panels","group","p","pIdx","panel","renderCategoryProductCard","tagsContainer","tagBtn","num","fixed","dotIdx","intPart","decPart","withSeparators","isSafeUrl","safeSetAttribute","isMobileViewport","DEFAULT_CHAT_UI_SPEC_REGISTRY","renderActionButtons","renderActionButton","renderProductCard","renderProductDetailsPanel","spec","renderElement","renderProductGrid","renderReviewHighlightsComponent","renderComparisonTableElement","renderDivider","defaultChatUnknownUISpecRenderer","wrapper","childId","rendered","createDefaultChatUISpecRegistry","renderUISpec","registry","unknownRenderer","renderUISpecWithRegistry","buttons","imgWrapper","findSimilarSku","favSku","heart","isFav","svgFill","svg","brand","brandEl","rating","ratingRow","renderStarRating","count","inStock","stock","promotions","promoBadges","promo","cartCode","atcBtn","checkbox","full","half","images","detailsSku","media","mainImg","firstSafe","u","thumbStrip","imgUrl","touchStartX","SWIPE_THRESHOLD","touchEndX","thumbs","activeThumb","currentIdx","nextIdx","currentPrice","oldPrice","variants","variantSection","variantLabel","variantList","variant","variantName","variantSku","labelText","variantPrice","actionRow","actionBtn","description","specifications","renderProductDetailTabs","tabPanels","keyCell","valCell","tabs","tabEl","idx","getSortedChildIds","childIds","sort","withPrice","id","a","x","resortGrid","sorted","childMap","elId","toolbar","separator","compareBtn","sortedIds","viewMoreBtn","floatingBtn","keyDifferencesHtml","recommendedText","winnerHits","productActions","hr","labelEl","BLOCK_ELEMENTS","splitIntoBlocks","nodes","blocks","currentInline","containsTable","prefersReducedMotion","typewriteHtml","delayMs","onTick","onComplete","template","currentIndex","timerId","running","revealNext","linkProductMentions","mentions","mentionMap","m","lowerName","mention","walker","found","before","match","after","INPUT_AREA_ICONS","INPUT_AREA_TYPES","isInputAreaAction","SESSION_STORAGE_KEY","createChoicePrompter","headingEl","suggestionEl","markDismissed","isChoicePrompterDismissed","DB_NAME","DB_VERSION","STORE_SESSIONS","STORE_CONTEXT","STORE_PAYLOAD","STORE_FAVORITES","requestToPromise","resolve","reject","transactionComplete","tx","GengageIndexedDB","dbName","version","db","oldVersion","userId","appId","sessionId","cursor","store","range","index","results","BASE_PANEL_CONTENT_TYPES","ExtendedModeManager","types","hidden","shown","fav","MessageBubbleSchema","z.object","z.enum","z.string","z.number","ProductCardSchema","ActionButtonsSchema","z.array","z.unknown","TypingIndicatorSchema","DividerSchema","ComparisonProductSchema","ComparisonTableSchema","z.record","SentimentLabelSchema","AITopPickItemSchema","AITopPicksSchema","GroundingReviewCardSchema","AIGroupingCardsSchema","AISuggestedSearchCardsSchema","chatCatalog","KVKK_STORAGE_KEY","KVKK_MARKERS","containsKvkk","lower","isKvkkShown","markKvkkShown","stripKvkkBlock","extractKvkkBlock","doc","LOCALE_TO_LANGUAGE","localeToOutputLanguage","GengageChat","BaseWidget","config","style","chatStyles","rootEl","launcherOpts","drawerContainer","extended","panelMode","restoreSessionId","restoreSku","onResize","onViewportResize","offset","minDepth","pending","dispatch","_context","color","opts","sid","popupOpts","hideLauncher","mobileHalf","mobileFull","cutoff","removed","userMsg","botMsg","chatHistory","meta","enrichedAction","requestId","streamStart","chunkIndex","panelLoadingSeen","panelContentReceived","streamStartEvent","isFinal","extra","streamChunkEvent","displayText","acctId","kvkkHtml","existingBubble","bubbleTextEl","widget","panelHint","rootElement","componentType","streamUiSpecEvent","renderContext","panelSpec","shouldRenderInline","titleType","messagesContainer","inline","previewImageUrls","inputChips","pillButtons","routerOpts","params","pendingType","llmUsageEvent","streamErrorEvent","streamDoneEvent","meteringIncrementEvent","chatHistorySnapshotEvent","msgs","panelEl","targetBot","panelType","serializableMessages","sm","panelSnapshotHtml","msgId","attempt","favs","session","maxMsgNum","chatMsg","idNum","uiSpec","panelBot","lastPanelThread","lastPanelBot","detailSpec","s","baseRegistry","mergeUISpecRegistry","defaultRender","inputSpec","inputContext","override","contentEl","clone","snapshot","snapshotType","targetThread","root","panelRoot","createChatWidget"],"mappings":"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"}
|