@gengage/assistant-fe 0.3.6 → 0.3.7

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.
Files changed (61) hide show
  1. package/dist/{chat-puIOIZga.cjs → chat-7RDofXq2.cjs} +2 -2
  2. package/dist/{chat-puIOIZga.cjs.map → chat-7RDofXq2.cjs.map} +1 -1
  3. package/dist/{chat-B8OppINI.js → chat-D_OIWCbN.js} +3 -3
  4. package/dist/{chat-B8OppINI.js.map → chat-D_OIWCbN.js.map} +1 -1
  5. package/dist/chat.cjs +1 -1
  6. package/dist/chat.iife.js.map +1 -1
  7. package/dist/chat.js +1 -1
  8. package/dist/common/events.d.ts.map +1 -1
  9. package/dist/{common-VO039pV2.js → common-Ceb-JCvj.js} +3 -3
  10. package/dist/{common-VO039pV2.js.map → common-Ceb-JCvj.js.map} +1 -1
  11. package/dist/{common-CEJUYizl.cjs → common-D1T9i8YW.cjs} +2 -2
  12. package/dist/{common-CEJUYizl.cjs.map → common-D1T9i8YW.cjs.map} +1 -1
  13. package/dist/common.cjs +1 -1
  14. package/dist/common.js +6 -6
  15. package/dist/{connection-warning-BXw7TANB.cjs → connection-warning-CAFljVhG.cjs} +2 -2
  16. package/dist/{connection-warning-BXw7TANB.cjs.map → connection-warning-CAFljVhG.cjs.map} +1 -1
  17. package/dist/{connection-warning-wrjf1GbE.js → connection-warning-KHArAYMR.js} +2 -2
  18. package/dist/{connection-warning-wrjf1GbE.js.map → connection-warning-KHArAYMR.js.map} +1 -1
  19. package/dist/ga-datalayer-Bc8ubVOe.cjs +48 -0
  20. package/dist/ga-datalayer-Bc8ubVOe.cjs.map +1 -0
  21. package/dist/{ga-datalayer-Dv8vn6TL.js → ga-datalayer-DmghxKMt.js} +111 -95
  22. package/dist/ga-datalayer-DmghxKMt.js.map +1 -0
  23. package/dist/index.cjs +1 -1
  24. package/dist/index.js +9 -9
  25. package/dist/{native-webview-C9KcNjOK.cjs → native-webview-BWSJqFL8.cjs} +2 -2
  26. package/dist/{native-webview-C9KcNjOK.cjs.map → native-webview-BWSJqFL8.cjs.map} +1 -1
  27. package/dist/{native-webview-DH9Cd8qX.js → native-webview-iVzu40B0.js} +7 -7
  28. package/dist/{native-webview-DH9Cd8qX.js.map → native-webview-iVzu40B0.js.map} +1 -1
  29. package/dist/native.cjs +1 -1
  30. package/dist/native.iife.js +14 -14
  31. package/dist/native.iife.js.map +1 -1
  32. package/dist/native.js +1 -1
  33. package/dist/{qna-C-_qwxhx.cjs → qna-BvHuFY5p.cjs} +2 -2
  34. package/dist/{qna-C-_qwxhx.cjs.map → qna-BvHuFY5p.cjs.map} +1 -1
  35. package/dist/{qna-DIjIo1cS.js → qna-uUsODJ3Y.js} +4 -4
  36. package/dist/{qna-DIjIo1cS.js.map → qna-uUsODJ3Y.js.map} +1 -1
  37. package/dist/qna.cjs +1 -1
  38. package/dist/qna.iife.js.map +1 -1
  39. package/dist/qna.js +1 -1
  40. package/dist/{schemas-01_sXoCv.js → schemas-Ct-HGOQp.js} +2 -2
  41. package/dist/{schemas-01_sXoCv.js.map → schemas-Ct-HGOQp.js.map} +1 -1
  42. package/dist/{schemas-D-jM96EO.cjs → schemas-qbR8squl.cjs} +2 -2
  43. package/dist/{schemas-D-jM96EO.cjs.map → schemas-qbR8squl.cjs.map} +1 -1
  44. package/dist/{simbut-CladS-u2.cjs → simbut-CcE7KVvO.cjs} +2 -2
  45. package/dist/{simbut-CladS-u2.cjs.map → simbut-CcE7KVvO.cjs.map} +1 -1
  46. package/dist/{simbut-B9bzHbOw.js → simbut-DiRfa6IR.js} +2 -2
  47. package/dist/{simbut-B9bzHbOw.js.map → simbut-DiRfa6IR.js.map} +1 -1
  48. package/dist/simbut.cjs +1 -1
  49. package/dist/simbut.iife.js.map +1 -1
  50. package/dist/simbut.js +1 -1
  51. package/dist/{simrel-81wZXFMk.js → simrel-BLo2xKLm.js} +4 -4
  52. package/dist/{simrel-81wZXFMk.js.map → simrel-BLo2xKLm.js.map} +1 -1
  53. package/dist/{simrel-BlNQ2EyH.cjs → simrel-D3M2Rcqm.cjs} +2 -2
  54. package/dist/{simrel-BlNQ2EyH.cjs.map → simrel-D3M2Rcqm.cjs.map} +1 -1
  55. package/dist/simrel.cjs +1 -1
  56. package/dist/simrel.iife.js.map +1 -1
  57. package/dist/simrel.js +1 -1
  58. package/package.json +1 -1
  59. package/dist/ga-datalayer-Dv8vn6TL.js.map +0 -1
  60. package/dist/ga-datalayer-boRrTCtO.cjs +0 -48
  61. package/dist/ga-datalayer-boRrTCtO.cjs.map +0 -1
package/dist/simrel.js CHANGED
@@ -1,2 +1,2 @@
1
- import { a as e, i as t, n, o as r, r as i, t as a } from "./simrel-81wZXFMk.js";
1
+ import { a as e, i as t, n, o as r, r as i, t as a } from "./simrel-BLo2xKLm.js";
2
2
  export { a as GengageSimRel, t as createDefaultSimRelUISpecRegistry, n as createSimRelWidget, e as defaultSimRelUnknownUISpecRenderer, r as renderSimRelUISpec, i as simRelCatalog };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gengage/assistant-fe",
3
- "version": "0.3.6",
3
+ "version": "0.3.7",
4
4
  "description": "Source-available frontend widgets for Gengage AI Assistant — chat, Q&A, and similar-products. Backend is SaaS (gengage.ai).",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "type": "module",
@@ -1 +0,0 @@
1
- {"version":3,"file":"ga-datalayer-Dv8vn6TL.js","names":[],"sources":["../src/common/analytics-events.ts","../src/common/safe-html.ts","../src/common/events.ts","../src/common/context.ts","../src/common/ui-theme.ts","../src/common/theme-utils.ts","../src/common/global-error-toast.ts","../src/common/debug.ts","../src/common/widget-base.ts","../src/common/ga-datalayer.ts"],"sourcesContent":["import type { AnalyticsInput } from './analytics.js';\n\n// Context shared across all events in a page session\nexport interface AnalyticsContext {\n account_id: string;\n session_id: string;\n correlation_id: string;\n view_id?: string;\n user_id?: string;\n page_type?: string;\n sku?: string;\n ab_test_variant?: string;\n ab_test_experiment_id?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Stream Lifecycle\n// ---------------------------------------------------------------------------\n\nexport function streamStartEvent(\n ctx: AnalyticsContext,\n payload: {\n endpoint: string;\n request_id: string;\n widget?: 'chat' | 'qna' | 'simrel';\n },\n): AnalyticsInput {\n const event: AnalyticsInput = {\n event_name: 'stream.start',\n account_id: ctx.account_id,\n session_id: ctx.session_id,\n correlation_id: ctx.correlation_id,\n payload: {\n endpoint: payload.endpoint,\n request_id: payload.request_id,\n },\n };\n if (ctx.view_id !== undefined) event.view_id = ctx.view_id;\n if (ctx.user_id !== undefined) event.user_id = ctx.user_id;\n if (payload.widget !== undefined) event.widget = payload.widget;\n if (ctx.page_type !== undefined) event.page_type = ctx.page_type;\n if (ctx.sku !== undefined) event.sku = ctx.sku;\n return event;\n}\n\nexport function streamChunkEvent(\n ctx: AnalyticsContext,\n payload: {\n request_id: string;\n chunk_index: number;\n latency_ms?: number;\n widget?: 'chat' | 'qna' | 'simrel';\n },\n): AnalyticsInput {\n const eventPayload: Record<string, unknown> = {\n request_id: payload.request_id,\n chunk_index: payload.chunk_index,\n };\n if (payload.latency_ms !== undefined) eventPayload.latency_ms = payload.latency_ms;\n\n const event: AnalyticsInput = {\n event_name: 'stream.chunk',\n account_id: ctx.account_id,\n session_id: ctx.session_id,\n correlation_id: ctx.correlation_id,\n payload: eventPayload,\n };\n if (ctx.view_id !== undefined) event.view_id = ctx.view_id;\n if (ctx.user_id !== undefined) event.user_id = ctx.user_id;\n if (payload.widget !== undefined) event.widget = payload.widget;\n if (ctx.page_type !== undefined) event.page_type = ctx.page_type;\n if (ctx.sku !== undefined) event.sku = ctx.sku;\n return event;\n}\n\nexport function streamUiSpecEvent(\n ctx: AnalyticsContext,\n payload: {\n request_id: string;\n chunk_index: number;\n component_type: string;\n widget?: 'chat' | 'qna' | 'simrel';\n },\n): AnalyticsInput {\n const event: AnalyticsInput = {\n event_name: 'stream.ui_spec',\n account_id: ctx.account_id,\n session_id: ctx.session_id,\n correlation_id: ctx.correlation_id,\n payload: {\n request_id: payload.request_id,\n chunk_index: payload.chunk_index,\n component_type: payload.component_type,\n },\n };\n if (ctx.view_id !== undefined) event.view_id = ctx.view_id;\n if (ctx.user_id !== undefined) event.user_id = ctx.user_id;\n if (payload.widget !== undefined) event.widget = payload.widget;\n if (ctx.page_type !== undefined) event.page_type = ctx.page_type;\n if (ctx.sku !== undefined) event.sku = ctx.sku;\n return event;\n}\n\nexport function streamDoneEvent(\n ctx: AnalyticsContext,\n payload: {\n request_id: string;\n latency_ms: number;\n chunk_count: number;\n widget?: 'chat' | 'qna' | 'simrel';\n },\n): AnalyticsInput {\n const event: AnalyticsInput = {\n event_name: 'stream.done',\n account_id: ctx.account_id,\n session_id: ctx.session_id,\n correlation_id: ctx.correlation_id,\n payload: {\n request_id: payload.request_id,\n latency_ms: payload.latency_ms,\n chunk_count: payload.chunk_count,\n },\n };\n if (ctx.view_id !== undefined) event.view_id = ctx.view_id;\n if (ctx.user_id !== undefined) event.user_id = ctx.user_id;\n if (payload.widget !== undefined) event.widget = payload.widget;\n if (ctx.page_type !== undefined) event.page_type = ctx.page_type;\n if (ctx.sku !== undefined) event.sku = ctx.sku;\n return event;\n}\n\nexport function streamErrorEvent(\n ctx: AnalyticsContext,\n payload: {\n request_id: string;\n error_code: string;\n error_message: string;\n widget?: 'chat' | 'qna' | 'simrel';\n },\n): AnalyticsInput {\n const event: AnalyticsInput = {\n event_name: 'stream.error',\n account_id: ctx.account_id,\n session_id: ctx.session_id,\n correlation_id: ctx.correlation_id,\n payload: {\n request_id: payload.request_id,\n error_code: payload.error_code,\n error_message: payload.error_message,\n },\n };\n if (ctx.view_id !== undefined) event.view_id = ctx.view_id;\n if (ctx.user_id !== undefined) event.user_id = ctx.user_id;\n if (payload.widget !== undefined) event.widget = payload.widget;\n if (ctx.page_type !== undefined) event.page_type = ctx.page_type;\n if (ctx.sku !== undefined) event.sku = ctx.sku;\n return event;\n}\n\n// ---------------------------------------------------------------------------\n// LLM Usage\n// ---------------------------------------------------------------------------\n\nexport function llmUsageEvent(\n ctx: AnalyticsContext,\n payload: {\n model: string;\n prompt_tokens: number;\n completion_tokens: number;\n total_tokens: number;\n provider?: string;\n },\n): AnalyticsInput {\n const eventPayload: Record<string, unknown> = {\n model: payload.model,\n prompt_tokens: payload.prompt_tokens,\n completion_tokens: payload.completion_tokens,\n total_tokens: payload.total_tokens,\n };\n if (payload.provider !== undefined) eventPayload.provider = payload.provider;\n\n const event: AnalyticsInput = {\n event_name: 'llm.usage',\n account_id: ctx.account_id,\n session_id: ctx.session_id,\n correlation_id: ctx.correlation_id,\n payload: eventPayload,\n };\n if (ctx.view_id !== undefined) event.view_id = ctx.view_id;\n if (ctx.user_id !== undefined) event.user_id = ctx.user_id;\n if (ctx.page_type !== undefined) event.page_type = ctx.page_type;\n if (ctx.sku !== undefined) event.sku = ctx.sku;\n return event;\n}\n\n// ---------------------------------------------------------------------------\n// Metering\n// ---------------------------------------------------------------------------\n\nexport function meteringIncrementEvent(\n ctx: AnalyticsContext,\n payload: {\n meter_key: string;\n quantity: number;\n unit: string;\n },\n): AnalyticsInput {\n const event: AnalyticsInput = {\n event_name: 'metering.increment',\n account_id: ctx.account_id,\n session_id: ctx.session_id,\n correlation_id: ctx.correlation_id,\n payload: {\n meter_key: payload.meter_key,\n quantity: payload.quantity,\n unit: payload.unit,\n },\n };\n if (ctx.view_id !== undefined) event.view_id = ctx.view_id;\n if (ctx.user_id !== undefined) event.user_id = ctx.user_id;\n if (ctx.page_type !== undefined) event.page_type = ctx.page_type;\n if (ctx.sku !== undefined) event.sku = ctx.sku;\n return event;\n}\n\nexport function meteringSummaryEvent(\n ctx: AnalyticsContext,\n payload: {\n meter_key: string;\n quantity: number;\n unit: string;\n },\n): AnalyticsInput {\n const event: AnalyticsInput = {\n event_name: 'metering.summary',\n account_id: ctx.account_id,\n session_id: ctx.session_id,\n correlation_id: ctx.correlation_id,\n payload: {\n meter_key: payload.meter_key,\n quantity: payload.quantity,\n unit: payload.unit,\n },\n };\n if (ctx.view_id !== undefined) event.view_id = ctx.view_id;\n if (ctx.user_id !== undefined) event.user_id = ctx.user_id;\n if (ctx.page_type !== undefined) event.page_type = ctx.page_type;\n if (ctx.sku !== undefined) event.sku = ctx.sku;\n return event;\n}\n\n// ---------------------------------------------------------------------------\n// Chat and Widget Histories\n// ---------------------------------------------------------------------------\n\nexport function chatHistorySnapshotEvent(\n ctx: AnalyticsContext,\n payload: {\n message_count: number;\n history_ref: string;\n redaction_level: string;\n },\n): AnalyticsInput {\n const event: AnalyticsInput = {\n event_name: 'chat.history.snapshot',\n account_id: ctx.account_id,\n session_id: ctx.session_id,\n correlation_id: ctx.correlation_id,\n payload: {\n message_count: payload.message_count,\n history_ref: payload.history_ref,\n redaction_level: payload.redaction_level,\n },\n };\n if (ctx.view_id !== undefined) event.view_id = ctx.view_id;\n if (ctx.user_id !== undefined) event.user_id = ctx.user_id;\n if (ctx.page_type !== undefined) event.page_type = ctx.page_type;\n if (ctx.sku !== undefined) event.sku = ctx.sku;\n return event;\n}\n\nexport function widgetHistorySnapshotEvent(\n ctx: AnalyticsContext,\n payload: {\n message_count: number;\n history_ref: string;\n redaction_level: string;\n widget: 'chat' | 'qna' | 'simrel';\n },\n): AnalyticsInput {\n const event: AnalyticsInput = {\n event_name: 'widget.history.snapshot',\n account_id: ctx.account_id,\n session_id: ctx.session_id,\n correlation_id: ctx.correlation_id,\n widget: payload.widget,\n payload: {\n message_count: payload.message_count,\n history_ref: payload.history_ref,\n redaction_level: payload.redaction_level,\n },\n };\n if (ctx.view_id !== undefined) event.view_id = ctx.view_id;\n if (ctx.user_id !== undefined) event.user_id = ctx.user_id;\n if (ctx.page_type !== undefined) event.page_type = ctx.page_type;\n if (ctx.sku !== undefined) event.sku = ctx.sku;\n return event;\n}\n\n// ---------------------------------------------------------------------------\n// Commerce Attribution\n// ---------------------------------------------------------------------------\n\nexport function basketAddEvent(\n ctx: AnalyticsContext,\n payload: {\n attribution_source: 'chat' | 'qna' | 'simrel';\n attribution_action_id: string;\n cart_value: number;\n currency: string;\n line_items: number;\n sku: string;\n },\n): AnalyticsInput {\n const event: AnalyticsInput = {\n event_name: 'basket.add',\n account_id: ctx.account_id,\n session_id: ctx.session_id,\n correlation_id: ctx.correlation_id,\n widget: payload.attribution_source,\n payload: {\n attribution_source: payload.attribution_source,\n attribution_action_id: payload.attribution_action_id,\n cart_value: payload.cart_value,\n currency: payload.currency,\n line_items: payload.line_items,\n sku: payload.sku,\n },\n };\n if (ctx.view_id !== undefined) event.view_id = ctx.view_id;\n if (ctx.user_id !== undefined) event.user_id = ctx.user_id;\n if (ctx.page_type !== undefined) event.page_type = ctx.page_type;\n if (ctx.sku !== undefined) event.sku = ctx.sku;\n return event;\n}\n\nexport function checkoutStartEvent(\n ctx: AnalyticsContext,\n payload: {\n attribution_source: 'chat' | 'qna' | 'simrel';\n attribution_action_id: string;\n cart_value: number;\n currency: string;\n line_items: number;\n },\n): AnalyticsInput {\n const event: AnalyticsInput = {\n event_name: 'checkout.start',\n account_id: ctx.account_id,\n session_id: ctx.session_id,\n correlation_id: ctx.correlation_id,\n widget: payload.attribution_source,\n payload: {\n attribution_source: payload.attribution_source,\n attribution_action_id: payload.attribution_action_id,\n cart_value: payload.cart_value,\n currency: payload.currency,\n line_items: payload.line_items,\n },\n };\n if (ctx.view_id !== undefined) event.view_id = ctx.view_id;\n if (ctx.user_id !== undefined) event.user_id = ctx.user_id;\n if (ctx.page_type !== undefined) event.page_type = ctx.page_type;\n if (ctx.sku !== undefined) event.sku = ctx.sku;\n return event;\n}\n\nexport function checkoutCompleteEvent(\n ctx: AnalyticsContext,\n payload: {\n attribution_source: 'chat' | 'qna' | 'simrel';\n attribution_action_id: string;\n cart_value: number;\n currency: string;\n line_items: number;\n },\n): AnalyticsInput {\n const event: AnalyticsInput = {\n event_name: 'checkout.complete',\n account_id: ctx.account_id,\n session_id: ctx.session_id,\n correlation_id: ctx.correlation_id,\n widget: payload.attribution_source,\n payload: {\n attribution_source: payload.attribution_source,\n attribution_action_id: payload.attribution_action_id,\n cart_value: payload.cart_value,\n currency: payload.currency,\n line_items: payload.line_items,\n },\n };\n if (ctx.view_id !== undefined) event.view_id = ctx.view_id;\n if (ctx.user_id !== undefined) event.user_id = ctx.user_id;\n if (ctx.page_type !== undefined) event.page_type = ctx.page_type;\n if (ctx.sku !== undefined) event.sku = ctx.sku;\n return event;\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 'template',\n 'noscript',\n]);\n\n/**\n * Attributes allowed per-tag. `'*'` means any allowed tag.\n * The `style` attribute is further sanitized by `sanitizeCssStyle()` to\n * strip dangerous CSS values (url(), expression(), -moz-binding, etc.).\n */\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\n/** CSS properties considered safe in style attributes (layout + typography). */\nconst SAFE_CSS_PROPERTIES = new Set([\n 'color',\n 'background-color',\n 'font-size',\n 'font-weight',\n 'font-style',\n 'font-family',\n 'text-align',\n 'text-decoration',\n 'line-height',\n 'letter-spacing',\n 'margin',\n 'margin-top',\n 'margin-right',\n 'margin-bottom',\n 'margin-left',\n 'padding',\n 'padding-top',\n 'padding-right',\n 'padding-bottom',\n 'padding-left',\n 'border',\n 'border-top',\n 'border-right',\n 'border-bottom',\n 'border-left',\n 'border-radius',\n 'border-color',\n 'border-width',\n 'border-style',\n 'width',\n 'max-width',\n 'min-width',\n 'height',\n 'max-height',\n 'min-height',\n 'display',\n 'vertical-align',\n 'white-space',\n 'word-break',\n 'overflow',\n 'opacity',\n 'visibility',\n 'list-style',\n 'list-style-type',\n 'text-transform',\n 'text-indent',\n 'text-overflow',\n 'box-sizing',\n 'flex',\n 'flex-direction',\n 'flex-wrap',\n 'justify-content',\n 'align-items',\n 'gap',\n]);\n\n/** Patterns indicating dangerous CSS values that could execute code or load external resources. */\nconst DANGEROUS_CSS_VALUE = /url\\s*\\(|expression\\s*\\(|javascript\\s*:|\\bimport\\b|-moz-binding|behavior\\s*:/i;\n\n/**\n * Sanitize a CSS style attribute value.\n * Allowlists safe properties and rejects values containing dangerous patterns.\n * Returns empty string if nothing is safe.\n */\nfunction sanitizeCssStyle(raw: string): string {\n const safe: string[] = [];\n for (const decl of raw.split(';')) {\n const trimmed = decl.trim();\n if (!trimmed) continue;\n const colonIdx = trimmed.indexOf(':');\n if (colonIdx === -1) continue;\n const property = trimmed.slice(0, colonIdx).trim().toLowerCase();\n const value = trimmed.slice(colonIdx + 1).trim();\n if (!SAFE_CSS_PROPERTIES.has(property)) continue;\n if (DANGEROUS_CSS_VALUE.test(value)) continue;\n safe.push(trimmed);\n }\n return safe.join('; ');\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 // Sanitize CSS style values to prevent XSS via url(), expression(), etc.\n if (name === 'style') {\n const sanitized = sanitizeCssStyle(attr.value);\n if (sanitized) {\n el.setAttribute('style', sanitized);\n } else {\n el.removeAttribute('style');\n }\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 */\nconst SAFE_URL_PROTOCOLS = ['http:', 'https:'];\n\n/** Check if a URL uses a safe protocol (http or https). */\nexport function isSafeImageUrl(url: string): boolean {\n try {\n return SAFE_URL_PROTOCOLS.includes(new URL(url).protocol);\n } catch {\n return false;\n }\n}\n\n/**\n * Check if a URL is safe for use in href/src attributes.\n * Allows http:, https:, and relative paths (starting with `/`).\n */\nexport function isSafeUrl(url: string): boolean {\n // Allow relative paths but reject protocol-relative URLs (//evil.com/...)\n if (url.startsWith('/') && !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\n/**\n * Safely set an attribute on an element.\n * For `href` and `src` attributes, validates the URL against safe protocols.\n */\nexport function 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\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","/**\n * Cross-widget event bus utilities.\n *\n * All Gengage widgets communicate through window CustomEvents following\n * the naming convention: gengage:<widget>:<action>\n *\n * This creates a loosely-coupled event bus — widgets don't import each other,\n * host pages can intercept any event, and third-party analytics can hook in.\n */\n\nimport type { GengageEventDetailMap, GengageEventName } from './types.js';\nimport type { ActionPayload } from './types.js';\nimport { isSafeUrl } from './safe-html.js';\n\n/**\n * Dispatch a typed Gengage event on window.\n *\n * @example\n * dispatch('gengage:qna:action', { title: 'About shipping', type: 'query', payload: 'shipping' });\n */\nexport function dispatch<K extends GengageEventName>(name: K, detail: GengageEventDetailMap[K]): void {\n window.dispatchEvent(new CustomEvent(name, { detail, bubbles: false }));\n}\n\n/**\n * Listen for a typed Gengage event on window.\n * Returns an unsubscribe function.\n *\n * @example\n * const off = listen('gengage:qna:action', (detail) => {\n * window.gengage?.chat?.openWithAction(detail);\n * });\n * // Later:\n * off();\n */\nexport function listen<K extends GengageEventName>(\n name: K,\n handler: (detail: GengageEventDetailMap[K]) => void,\n): () => void {\n const listener = (e: Event) => {\n handler((e as CustomEvent<GengageEventDetailMap[K]>).detail);\n };\n window.addEventListener(name, listener);\n return () => window.removeEventListener(name, listener);\n}\n\nexport interface WireQNAToChatOptions {\n onChatUnavailable?: () => void;\n}\n\ninterface WireableChatAPI {\n open?: (options?: { state?: 'full' | 'half'; initialMessage?: string }) => void;\n openWithAction?: (action: ActionPayload) => void;\n sendMessage?: (text: string) => void;\n}\n\nfunction extractFreeTextActionMessage(action: ActionPayload): string | null {\n if (action.type !== 'user_message' && action.type !== 'inputText') return null;\n\n if (typeof action.payload === 'string' && action.payload.trim().length > 0) {\n return action.payload.trim();\n }\n\n if (typeof action.payload === 'object' && action.payload !== null) {\n const payloadObj = action.payload as Record<string, unknown>;\n if (typeof payloadObj.text === 'string') {\n const text = payloadObj.text.trim();\n if (text.length > 0) return text;\n }\n }\n\n if (typeof action.title === 'string' && action.title.trim().length > 0) {\n return action.title.trim();\n }\n\n return null;\n}\n\n/**\n * Convenience: wire QNA → Chat automatically.\n * Call this once after both widgets are initialised.\n *\n * Listens for 'gengage:qna:action' and forwards to window.gengage.chat.openWithAction().\n * Listens for 'gengage:qna:open-chat' and forwards to window.gengage.chat.open().\n *\n * If chat is not available at dispatch time, emits a one-time console.warn and\n * calls options.onChatUnavailable (every time) if provided.\n *\n * @returns unsubscribe function that removes both listeners.\n */\nexport function wireQNAToChat(options?: WireQNAToChatOptions): () => void {\n let warnedOnce = false;\n const pendingActions: ActionPayload[] = [];\n let pendingOpenCount = 0;\n let pollTimer: number | null = null;\n let pollStartedAt = 0;\n const pollIntervalMs = 100;\n const pollTimeoutMs = 5000;\n\n function getChat(): WireableChatAPI | null {\n return (window.gengage?.chat as WireableChatAPI | undefined) ?? null;\n }\n\n function notifyUnavailable(): void {\n if (!warnedOnce) {\n console.warn(\n '[gengage] QNA tried to open chat, but chat widget is not initialized. ' +\n 'Ensure GengageChat is initialized before calling wireQNAToChat().',\n );\n warnedOnce = true;\n }\n options?.onChatUnavailable?.();\n }\n\n function routeActionToChat(chat: WireableChatAPI, action: ActionPayload): void {\n const freeText = extractFreeTextActionMessage(action);\n if (freeText && chat.sendMessage) {\n chat.open?.();\n chat.sendMessage(freeText);\n return;\n }\n chat.openWithAction?.(action);\n }\n\n function clearPollTimer(): void {\n if (pollTimer !== null) {\n window.clearInterval(pollTimer);\n pollTimer = null;\n }\n }\n\n function flushPendingToChat(): boolean {\n const chat = getChat();\n if (!chat) return false;\n\n if (pendingOpenCount > 0) {\n chat.open?.();\n pendingOpenCount = 0;\n }\n\n if (pendingActions.length > 0) {\n const queued = pendingActions.splice(0, pendingActions.length);\n for (const action of queued) {\n routeActionToChat(chat, action);\n }\n }\n\n clearPollTimer();\n return true;\n }\n\n function ensurePollTimer(): void {\n if (pollTimer !== null) return;\n pollStartedAt = Date.now();\n pollTimer = window.setInterval(() => {\n if (flushPendingToChat()) return;\n if (Date.now() - pollStartedAt >= pollTimeoutMs) {\n pendingActions.length = 0;\n pendingOpenCount = 0;\n clearPollTimer();\n }\n }, pollIntervalMs);\n }\n\n const offAction = listen('gengage:qna:action', (action) => {\n const chat = getChat();\n if (chat) {\n routeActionToChat(chat, action);\n return;\n }\n\n notifyUnavailable();\n if (pendingActions.length >= 20) pendingActions.shift();\n pendingActions.push(action);\n ensurePollTimer();\n });\n\n const offOpen = listen('gengage:qna:open-chat', () => {\n const chat = getChat();\n if (chat) {\n chat.open?.();\n return;\n }\n\n notifyUnavailable();\n pendingOpenCount += 1;\n ensurePollTimer();\n });\n\n return () => {\n offAction();\n offOpen();\n pendingActions.length = 0;\n pendingOpenCount = 0;\n clearPollTimer();\n };\n}\n\n/**\n * Convenience: wire Similar Products → Chat for cross-page session continuity.\n * Call this once after both widgets are initialised.\n *\n * When the user navigates to a product page, the chat widget can restore\n * the conversation where it left off using saveSession().\n *\n * @returns unsubscribe function.\n */\nexport function wireSimilarToChat(): () => void {\n return listen('gengage:similar:product-click', ({ sku, url, sessionId }) => {\n if (sessionId) {\n window.gengage?.chat?.saveSession(sessionId, sku);\n }\n if (isSafeUrl(url)) {\n window.location.href = url;\n }\n });\n}\n","/**\n * Page context management.\n *\n * Best practice for passing page context to widgets:\n *\n * ## SSR / Static pages\n * Set window.gengage.pageContext before widget scripts load:\n *\n * <script>\n * window.gengage = {\n * pageContext: {\n * pageType: 'pdp',\n * sku: '{{ product.sku }}',\n * price: '{{ product.price }}',\n * categoryTree: {{ product.categories | json }},\n * }\n * };\n * </script>\n * <script src=\"https://cdn.gengage.ai/widgets/latest/chat.iife.js\"></script>\n *\n * ## CSR / SPA (React, Vue, Next.js, etc.)\n * Call widget.update() after each navigation:\n *\n * router.afterEach((to) => {\n * chatWidget.update({\n * pageType: to.meta.pageType,\n * sku: to.params.sku,\n * });\n * });\n *\n * ## Event-based (loosest coupling)\n * Dispatch 'gengage:context:update' from anywhere:\n *\n * window.dispatchEvent(new CustomEvent('gengage:context:update', {\n * detail: { pageType: 'pdp', sku: '12345' }\n * }));\n */\n\nimport type { PageContext, SessionContext } from './types.js';\n\n// ---------------------------------------------------------------------------\n// Session bootstrap\n// ---------------------------------------------------------------------------\n\n/**\n * Returns the shared session ID for this browser tab session.\n * Creates and persists it on first call.\n *\n * Call this once at page load and share the result with all widget configs:\n *\n * const sessionId = bootstrapSession();\n * chatWidget.init({ ..., session: { sessionId } });\n * qnaWidget.init({ ..., session: { sessionId } });\n */\nexport function bootstrapSession(): string {\n const existing = window.__gengageSessionId ?? sessionStorage.getItem('gengage_session_id') ?? null;\n\n const sessionId = existing ?? crypto.randomUUID();\n\n window.__gengageSessionId = sessionId;\n sessionStorage.setItem('gengage_session_id', sessionId);\n\n if (!window.gengage) window.gengage = {};\n window.gengage.sessionId = sessionId;\n\n return sessionId;\n}\n\n// ---------------------------------------------------------------------------\n// Page context resolution\n// ---------------------------------------------------------------------------\n\n/**\n * Reads the current page context from window.gengage.pageContext.\n * Returns null if not set.\n */\nexport function getWindowPageContext(): PageContext | null {\n return window.gengage?.pageContext ?? null;\n}\n\n/**\n * Merges a partial context update into the current window.gengage.pageContext.\n * Dispatches 'gengage:context:update' so all listening widgets update.\n */\nexport function updatePageContext(patch: Partial<PageContext>): void {\n if (!window.gengage) window.gengage = {};\n window.gengage.pageContext = {\n pageType: 'other',\n ...window.gengage.pageContext,\n ...patch,\n };\n\n window.dispatchEvent(new CustomEvent('gengage:context:update', { detail: patch }));\n}\n\n/**\n * Resolves the session context, bootstrapping if necessary.\n * Merges provided overrides with auto-generated session ID.\n */\nexport function resolveSession(overrides?: Partial<SessionContext>): SessionContext {\n const sessionId = overrides?.sessionId ?? bootstrapSession();\n return {\n sessionId,\n ...overrides,\n };\n}\n","import type { WidgetTheme } from './types.js';\n\n/**\n * Shared SDK-wide visual tokens.\n *\n * Applied to every widget root by default so account customizations only\n * override what they need.\n */\nexport const DEFAULT_WIDGET_THEME_TOKENS: WidgetTheme = {\n '--gengage-chat-offset': '20px',\n '--gengage-chat-launcher-size': '56px',\n '--gengage-chat-width': '400px',\n '--gengage-chat-shell-radius': '1rem' /* lg roundedness */,\n '--gengage-chat-header-height': '72px',\n '--gengage-chat-conversation-width': '396px',\n '--gengage-chat-panel-min-width': '320px',\n '--gengage-chat-panel-max-width': '1200px',\n '--gengage-chat-input-height': '48px',\n\n '--gengage-qna-pill-radius': '999px' /* roundedness-full */,\n '--gengage-qna-input-radius': '0.75rem' /* md roundedness */,\n\n '--gengage-simrel-card-radius': '0.75rem' /* md roundedness */,\n\n '--radius-control': '12px',\n '--radius-card': '16px',\n '--radius-panel': '24px',\n '--radius-pill': '999px',\n '--surface-card-muted': '#f8fafc',\n '--text-secondary': '#4b5563',\n '--text-muted': '#6b7280',\n '--border-default': 'rgba(17, 24, 39, 0.10)',\n};\n\nexport function withDefaultWidgetTheme(theme?: WidgetTheme): WidgetTheme {\n if (!theme) {\n return { ...DEFAULT_WIDGET_THEME_TOKENS };\n }\n return { ...DEFAULT_WIDGET_THEME_TOKENS, ...theme };\n}\n","import type { WidgetTheme } from './types.js';\n\n/**\n * Shared baseline tokens used by account customizations.\n *\n * These values come from historical Gengage host defaults and are\n * intentionally conservative so account themes can override only what differs.\n */\nexport const BASE_WIDGET_THEME: WidgetTheme = {\n /* ── Editorial Commerce Framework ────────────────────────────────────── */\n /* Primary: signature red; never use pure black for text — use on_surface */\n primaryColor: '#b7102a',\n primaryForeground: '#ffffff',\n backgroundColor: '#ffffff' /* surface-card */,\n foregroundColor: '#111827' /* text-primary */,\n borderRadius: '0.75rem' /* md roundedness */,\n fontFamily: '\"Plus Jakarta Sans\", -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif',\n fontSize: '14px',\n zIndex: '1000',\n\n '--glov-chatbot-width': '420px',\n '--glov-left-spacing': '260px',\n '--chatbot-padding': '16px',\n '--root-wrapper-background-color': '#f8f9fa' /* background token */,\n '--root-wrapper-border-color': '#edeeef' /* surface-container */,\n\n '--gengage-chat-width': '400px',\n '--gengage-chat-shell-radius': '1rem' /* lg roundedness */,\n '--gengage-chat-header-height': '72px',\n '--gengage-chat-conversation-width': '396px',\n '--gengage-chat-panel-min-width': '320px',\n '--gengage-chat-panel-max-width': '1200px',\n '--gengage-chat-input-height': '48px',\n '--gengage-qna-pill-radius': '999px' /* roundedness-full */,\n '--gengage-qna-input-radius': '0.75rem' /* md roundedness */,\n '--gengage-simrel-card-radius': '0.75rem' /* md roundedness */,\n\n '--client-primary': '#b7102a',\n '--client-primary-hover': 'color-mix(in srgb, #b7102a 88%, black 12%)',\n '--client-primary-active': 'color-mix(in srgb, #b7102a 78%, black 22%)',\n '--client-primary-subtle': 'color-mix(in srgb, #b7102a 12%, white)',\n '--client-primary-soft': 'color-mix(in srgb, #b7102a 20%, white)',\n '--client-on-primary': '#ffffff',\n '--client-focus-ring': 'color-mix(in srgb, #b7102a 32%, transparent)',\n\n '--surface-page': '#f6f7fb',\n '--surface-shell': '#10131a',\n '--surface-card': '#ffffff',\n '--surface-card-muted': '#f8fafc',\n '--surface-card-soft': '#f8fafc',\n '--surface-elevated': '#ffffff',\n '--surface-input': '#ffffff',\n '--surface-overlay': 'rgba(16, 19, 26, 0.52)',\n\n '--text-primary': '#111827',\n '--text-secondary': '#4b5563',\n '--text-muted': '#6b7280',\n '--text-inverse': '#f9fafb',\n\n '--border-subtle': 'rgba(17, 24, 39, 0.06)',\n '--border-default': 'rgba(17, 24, 39, 0.10)',\n '--border-strong': 'rgba(17, 24, 39, 0.18)',\n\n '--shadow-1': '0 1px 2px rgba(16, 24, 40, 0.04), 0 1px 3px rgba(16, 24, 40, 0.06)',\n '--shadow-2': '0 4px 12px rgba(16, 24, 40, 0.08)',\n '--shadow-3': '0 10px 24px rgba(16, 24, 40, 0.12)',\n\n '--radius-control': '12px',\n '--radius-card': '16px',\n '--radius-panel': '24px',\n '--radius-pill': '999px',\n\n '--success': '#16a34a',\n '--warning': '#d97706',\n '--error': '#dc2626',\n '--info': '#2563eb',\n '--rating': '#f5b301',\n\n '--ai-accent-start': '#0b24d6',\n '--ai-accent-end': '#f768f2',\n '--ai-accent-soft': 'linear-gradient(135deg, rgba(11, 36, 214, 0.08), rgba(247, 104, 242, 0.08))',\n};\n\n/**\n * Merge account overrides on top of the shared base theme.\n *\n * Account customization files should call this helper so shared defaults stay\n * centralized under src/common.\n */\nexport function withBaseTheme(overrides: WidgetTheme): WidgetTheme {\n return { ...BASE_WIDGET_THEME, ...overrides };\n}\n","import type { GengageEventDetailMap } from './types.js';\nimport { listen } from './events.js';\nimport { BASE_WIDGET_THEME } from './theme-utils.js';\n\nconst ROOT_ID = 'gengage-global-toast-root';\nconst STYLE_ID = 'gengage-global-toast-style';\nconst ROOT_VISIBLE_CLASS = 'gengage-global-toast-root--visible';\nconst DEFAULT_DURATION_MS = 4200;\nconst MIN_DURATION_MS = 1500;\nconst MAX_DURATION_MS = 15000;\nconst THEME_SYNC_VARS = [\n '--gengage-font-family',\n '--surface-card',\n '--text-primary',\n '--text-muted',\n '--border-default',\n '--radius-card',\n '--shadow-3',\n '--error',\n '--ds-toast-error-bg',\n '--ds-toast-error-border',\n '--ds-toast-error-accent',\n '--ds-toast-error-fg',\n '--ds-toast-error-shadow',\n] as const;\n\nlet listenerRegistered = false;\nlet dismissTimer: ReturnType<typeof setTimeout> | null = null;\n\nconst CONNECTIVITY_ERROR_PATTERNS = [\n /failed to fetch/i,\n /networkerror/i,\n /network request failed/i,\n /load failed/i,\n /err_network/i,\n /fetch failed/i,\n /network error/i,\n] as const;\n\nfunction isTurkishLocale(locale?: string): boolean {\n return typeof locale === 'string' && locale.toLowerCase().startsWith('tr');\n}\n\nexport function isLikelyConnectivityIssue(error?: unknown): boolean {\n if (typeof navigator !== 'undefined' && navigator.onLine === false) {\n return true;\n }\n\n const message = error instanceof Error ? error.message.trim() : '';\n if (!message) return false;\n\n return CONNECTIVITY_ERROR_PATTERNS.some((pattern) => pattern.test(message));\n}\n\nexport function getGlobalErrorMessage(locale?: string, error?: unknown): string {\n if (isLikelyConnectivityIssue(error)) {\n if (isTurkishLocale(locale)) {\n return 'Bağlantı sorunu oluştu. Lütfen tekrar deneyin.';\n }\n return 'Connection issue. Please try again.';\n }\n\n if (isTurkishLocale(locale)) {\n return 'Bir hata oluştu. Lütfen tekrar deneyin.';\n }\n return 'Something went wrong. Please try again.';\n}\n\nexport function registerGlobalErrorToastListener(): void {\n if (listenerRegistered || typeof window === 'undefined' || typeof document === 'undefined') {\n return;\n }\n\n listenerRegistered = true;\n listen('gengage:global:error', (detail) => {\n showGlobalErrorToast(detail);\n });\n}\n\nexport function showGlobalErrorToast(detail: GengageEventDetailMap['gengage:global:error']): void {\n if (typeof document === 'undefined') return;\n const message = detail.message.trim();\n if (!message) return;\n\n ensureStyles();\n const root = ensureRoot();\n syncRootThemeVars(root);\n root.innerHTML = '';\n\n const toast = document.createElement('section');\n toast.className = 'gengage-global-toast gengage-global-toast--error';\n toast.setAttribute('role', 'status');\n toast.setAttribute('aria-live', 'polite');\n\n const title = document.createElement('div');\n title.className = 'gengage-global-toast-title';\n title.textContent = sourceTitle(detail.source);\n\n const body = document.createElement('div');\n body.className = 'gengage-global-toast-message';\n body.textContent = message;\n\n toast.appendChild(title);\n toast.appendChild(body);\n root.appendChild(toast);\n root.classList.add(ROOT_VISIBLE_CLASS);\n\n if (dismissTimer) {\n clearTimeout(dismissTimer);\n dismissTimer = null;\n }\n\n if (detail.sticky === true) {\n return;\n }\n\n dismissTimer = setTimeout(() => {\n dismissGlobalErrorToast();\n }, clampDuration(detail.durationMs));\n}\n\nexport function dismissGlobalErrorToast(): void {\n if (typeof document === 'undefined') return;\n const root = document.getElementById(ROOT_ID);\n if (!root) return;\n\n root.classList.remove(ROOT_VISIBLE_CLASS);\n root.innerHTML = '';\n\n if (dismissTimer) {\n clearTimeout(dismissTimer);\n dismissTimer = null;\n }\n}\n\nfunction sourceTitle(source: GengageEventDetailMap['gengage:global:error']['source']): string {\n switch (source) {\n case 'chat':\n return 'Chat warning';\n case 'qna':\n return 'QnA warning';\n case 'simrel':\n return 'Widget warning';\n default:\n return 'Connection warning';\n }\n}\n\nfunction ensureRoot(): HTMLElement {\n const existing = document.getElementById(ROOT_ID);\n if (existing instanceof HTMLElement) return existing;\n\n const root = document.createElement('div');\n root.id = ROOT_ID;\n root.className = 'gengage-global-toast-root';\n document.body.appendChild(root);\n return root;\n}\n\nfunction syncRootThemeVars(root: HTMLElement): void {\n if (typeof document === 'undefined' || typeof window === 'undefined') return;\n const source = document.querySelector<HTMLElement>(\n '.gengage-chat-root, .gengage-qna-container, .gengage-simrel-container, .gengage-simbut-root',\n );\n if (!source) return;\n const computed = window.getComputedStyle(source);\n for (const name of THEME_SYNC_VARS) {\n const value = computed.getPropertyValue(name).trim();\n if (value) {\n root.style.setProperty(name, value);\n } else {\n root.style.removeProperty(name);\n }\n }\n}\n\nfunction clampDuration(durationMs?: number): number {\n if (typeof durationMs !== 'number' || !Number.isFinite(durationMs)) {\n return DEFAULT_DURATION_MS;\n }\n return Math.min(MAX_DURATION_MS, Math.max(MIN_DURATION_MS, Math.round(durationMs)));\n}\n\nfunction ensureStyles(): void {\n if (document.getElementById(STYLE_ID)) return;\n\n const style = document.createElement('style');\n style.id = STYLE_ID;\n const surfaceCard = BASE_WIDGET_THEME['--surface-card'] ?? BASE_WIDGET_THEME.backgroundColor ?? '#ffffff';\n const textPrimary = BASE_WIDGET_THEME['--text-primary'] ?? BASE_WIDGET_THEME.foregroundColor ?? '#111827';\n const borderDefault = BASE_WIDGET_THEME['--border-default'] ?? 'rgba(17, 24, 39, 0.10)';\n const error = BASE_WIDGET_THEME['--error'] ?? '#dc2626';\n const shadow3 = BASE_WIDGET_THEME['--shadow-3'] ?? '0 10px 24px rgba(16, 24, 40, 0.12)';\n const radiusCard = BASE_WIDGET_THEME['--radius-card'] ?? '16px';\n const textMuted = BASE_WIDGET_THEME['--text-muted'] ?? '#6b7280';\n style.textContent = `\n#${ROOT_ID} {\n position: fixed;\n top: 16px;\n right: 16px;\n z-index: 2147483646;\n pointer-events: none;\n}\n#${ROOT_ID}.${ROOT_VISIBLE_CLASS} {\n pointer-events: auto;\n}\n#${ROOT_ID} .gengage-global-toast {\n min-width: 260px;\n max-width: min(92vw, 420px);\n border-radius: var(--radius-card, ${radiusCard});\n border: 1px solid var(--ds-toast-error-border, color-mix(in srgb, var(--error, ${error}) 18%, var(--border-default, ${borderDefault})));\n border-left: 4px solid var(--ds-toast-error-accent, var(--error, ${error}));\n background: var(--ds-toast-error-bg, color-mix(in srgb, var(--error, ${error}) 5%, var(--surface-card, ${surfaceCard})));\n color: var(--ds-toast-error-fg, color-mix(in srgb, var(--error, ${error}) 22%, var(--text-primary, ${textPrimary})));\n box-shadow: var(--ds-toast-error-shadow, var(--shadow-3, ${shadow3}));\n padding: 10px 12px;\n font-family: var(--gengage-font-family, ${JSON.stringify(BASE_WIDGET_THEME.fontFamily ?? '-apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif')});\n font-size: 13px;\n line-height: 1.4;\n animation: gengage-global-toast-in 180ms ease-out forwards;\n}\n#${ROOT_ID} .gengage-global-toast-title {\n margin: 0 0 4px;\n font-size: 12px;\n font-weight: 700;\n color: var(--text-muted, ${textMuted});\n}\n#${ROOT_ID} .gengage-global-toast-message {\n margin: 0;\n font-weight: 500;\n}\n@keyframes gengage-global-toast-in {\n from {\n opacity: 0;\n transform: translateY(-8px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n`;\n document.head.appendChild(style);\n}\n","/**\n * Debug logging for integrators.\n *\n * Enable with: `localStorage.setItem('gengage:debug', '1')`\n * Disable with: `localStorage.removeItem('gengage:debug')`\n *\n * When disabled, all debug calls are no-ops with zero overhead\n * (the check is a single localStorage read cached per page load).\n */\n\nlet _enabled: boolean | null = null;\n\nfunction isEnabled(): boolean {\n if (_enabled !== null) return _enabled;\n try {\n _enabled = localStorage.getItem('gengage:debug') === '1';\n } catch {\n _enabled = false;\n }\n return _enabled;\n}\n\n/** Log a debug message (only when gengage:debug is enabled). */\nexport function debugLog(category: string, message: string, data?: unknown): void {\n if (!isEnabled()) return;\n const args: unknown[] = [`[gengage:${category}]`, message];\n if (data !== undefined) args.push(data);\n // eslint-disable-next-line no-console -- debug utility, gated by localStorage flag\n console.debug(...args);\n}\n\n/** Reset the cached enabled state (for testing). */\nexport function _resetDebugCache(): void {\n _enabled = null;\n}\n","/**\n * Abstract base class for all Gengage widgets.\n *\n * Provides:\n * - Lifecycle management (init → update → show/hide → destroy)\n * - Typed event emitter\n * - Theme application via CSS custom properties\n * - SPA context-update listener (gengage:context:update)\n * - Mount target resolution (selector string or HTMLElement)\n *\n * Subclasses must implement:\n * - protected onInit(config): Promise<void>\n * - protected onUpdate(context): void\n * - protected onShow(): void\n * - protected onHide(): void\n * - protected onDestroy(): void\n */\n\nimport type { BaseWidgetConfig, GengageWidget, PageContext, WidgetTheme } from './types.js';\nimport type { AnalyticsInput } from './analytics.js';\nimport type { AnalyticsContext } from './analytics-events.js';\nimport { checkoutStartEvent, checkoutCompleteEvent, meteringSummaryEvent } from './analytics-events.js';\nimport { listen } from './events.js';\nimport { resolveSession } from './context.js';\nimport { withDefaultWidgetTheme } from './ui-theme.js';\nimport { registerGlobalErrorToastListener } from './global-error-toast.js';\nimport { debugLog } from './debug.js';\n\ntype AnyHandler = (...args: unknown[]) => void;\n\nexport abstract class BaseWidget<\n TConfig extends BaseWidgetConfig = BaseWidgetConfig,\n> implements GengageWidget<TConfig> {\n protected config!: TConfig;\n protected root!: HTMLElement;\n protected isVisible = false;\n protected isInitialised = false;\n\n private readonly _handlers = new Map<string, Set<AnyHandler>>();\n private readonly _cleanups: Array<() => void> = [];\n private _ownsRoot = false;\n private _destroying = false;\n\n // ---------------------------------------------------------------------------\n // Public API\n // ---------------------------------------------------------------------------\n\n async init(config: TConfig): Promise<void> {\n if (this.isInitialised) {\n console.warn('[gengage] Widget already initialised. Call update() instead.');\n return;\n }\n\n const mergedTheme = withDefaultWidgetTheme(config.theme);\n\n this.config = {\n ...config,\n theme: mergedTheme,\n session: resolveSession(config.session),\n };\n\n this.root = this._resolveMount(config.mountTarget);\n this._applyTheme(mergedTheme);\n registerGlobalErrorToastListener();\n\n // Listen for context updates dispatched by the host page\n const off = listen('gengage:context:update', (patch) => this.update(patch));\n this._cleanups.push(off);\n\n debugLog('lifecycle', `${this.constructor.name}.init`, {\n accountId: config.accountId,\n sku: config.pageContext?.sku,\n });\n\n try {\n await this.onInit(this.config);\n } catch (err) {\n this.destroy();\n throw err;\n }\n if (this._destroying) return;\n this.isInitialised = true;\n debugLog('lifecycle', `${this.constructor.name} ready`);\n this.emit('ready');\n }\n\n update(context: Partial<PageContext>): void {\n if (!this.isInitialised) return;\n if (this.config.pageContext) {\n this.config = {\n ...this.config,\n pageContext: { ...this.config.pageContext, ...context },\n };\n } else if (context.pageType !== undefined) {\n // Only create a new pageContext when pageType is present (required field)\n this.config = { ...this.config, pageContext: context as PageContext };\n }\n this.onUpdate(context);\n this.emit('context-update', this.config.pageContext);\n }\n\n show(): void {\n if (this.isVisible) return;\n this.isVisible = true;\n this.root.style.display = '';\n this.onShow();\n this.emit('show');\n }\n\n hide(): void {\n if (!this.isVisible) return;\n this.isVisible = false;\n this.root.style.display = 'none';\n this.onHide();\n this.emit('hide');\n }\n\n destroy(): void {\n if (this._destroying) return;\n this._destroying = true;\n this.emit('destroy');\n this._cleanups.forEach((fn) => fn());\n this._cleanups.length = 0;\n this._handlers.clear();\n this.onDestroy();\n this.config.analyticsClient?.destroy();\n if (this._ownsRoot) {\n this.root.remove();\n } else {\n this.root.innerHTML = '';\n }\n this.isInitialised = false;\n }\n\n on(event: string, handler: AnyHandler): () => void {\n if (!this._handlers.has(event)) this._handlers.set(event, new Set());\n this._handlers.get(event)!.add(handler);\n return () => this._handlers.get(event)?.delete(handler);\n }\n\n /** Track a checkout start event. Called by host page to attribute checkout to widget interaction. */\n trackCheckout(\n type: 'start' | 'complete',\n data: {\n attribution_source: 'chat' | 'qna' | 'simrel';\n attribution_action_id: string;\n cart_value: number;\n currency: string;\n line_items: number;\n },\n ): void {\n const builder = type === 'start' ? checkoutStartEvent : checkoutCompleteEvent;\n this.track(builder(this.analyticsContext(), data));\n }\n\n /** Track a metering summary event. Called by host page for session-level aggregation. */\n flushMeteringSummary(data: { meter_key: string; quantity: number; unit: string }): void {\n this.track(meteringSummaryEvent(this.analyticsContext(), data));\n }\n\n // ---------------------------------------------------------------------------\n // Protected — subclasses implement these\n // ---------------------------------------------------------------------------\n\n protected abstract onInit(config: TConfig): Promise<void>;\n protected abstract onUpdate(context: Partial<PageContext>): void;\n protected abstract onShow(): void;\n protected abstract onHide(): void;\n protected abstract onDestroy(): void;\n\n // ---------------------------------------------------------------------------\n // Protected helpers\n // ---------------------------------------------------------------------------\n\n /** Emit a widget event to all registered handlers. */\n protected emit(event: string, ...args: unknown[]): void {\n this._handlers.get(event)?.forEach((h) => h(...args));\n }\n\n /** Register a cleanup function to run on destroy(). */\n protected addCleanup(fn: () => void): void {\n this._cleanups.push(fn);\n }\n\n /** Track an analytics event (no-op if analyticsClient is not configured). */\n protected track(input: AnalyticsInput): void {\n this.config.analyticsClient?.track(input);\n }\n\n /** Build the shared analytics context from widget config. */\n protected analyticsContext(): AnalyticsContext {\n const ctx: AnalyticsContext = {\n account_id: this.config.accountId,\n session_id: this.config.session?.sessionId ?? '',\n correlation_id: this.config.session?.sessionId ?? '',\n };\n if (this.config.session?.viewId !== undefined) ctx.view_id = this.config.session.viewId;\n if (this.config.session?.userId !== undefined) ctx.user_id = this.config.session.userId;\n if (this.config.pageContext?.pageType !== undefined) ctx.page_type = this.config.pageContext.pageType;\n if (this.config.pageContext?.sku !== undefined) ctx.sku = this.config.pageContext.sku;\n if (this.config.session?.abTestVariant !== undefined) ctx.ab_test_variant = this.config.session.abTestVariant;\n if (this.config.session?.abTestExperimentId !== undefined)\n ctx.ab_test_experiment_id = this.config.session.abTestExperimentId;\n return ctx;\n }\n\n // ---------------------------------------------------------------------------\n // Private helpers\n // ---------------------------------------------------------------------------\n\n private _resolveMount(target?: HTMLElement | string): HTMLElement {\n if (target instanceof HTMLElement) return target;\n if (typeof target === 'string') {\n const el = document.querySelector<HTMLElement>(target);\n if (!el) throw new Error(`[gengage] Mount target not found: \"${target}\"`);\n return el;\n }\n // Default: create a div prepended to body so the widget's launcher appears\n // near the start of the tab order rather than being buried at the very end\n // (which would force keyboard-only users to tab through the entire page).\n const div = document.createElement('div');\n div.dataset['gengageWidget'] = this.constructor.name.toLowerCase();\n document.body.insertBefore(div, document.body.firstChild);\n this._ownsRoot = true;\n return div;\n }\n\n private _applyTheme(theme?: WidgetTheme): void {\n if (!theme) return;\n for (const [key, value] of Object.entries(theme)) {\n if (value !== undefined) {\n const prop = key.startsWith('--') ? key : `--gengage-${toKebab(key)}`;\n this.root.style.setProperty(prop, value);\n }\n }\n }\n}\n\nfunction toKebab(str: string): string {\n return str.replace(/([A-Z])/g, '-$1').toLowerCase();\n}\n\n// ---------------------------------------------------------------------------\n// Chat widget public API (exposed on window.gengage.chat)\n// ---------------------------------------------------------------------------\n\nexport interface ChatPublicAPI {\n open(options?: { state?: 'full' | 'half'; initialMessage?: string }): void;\n openWithAction(action: import('./types.js').ActionPayload, options?: { sku?: string; state?: 'full' | 'half' }): void;\n /** Send a user message programmatically (same as typing + submit). */\n sendMessage(text: string): void;\n /** Send a backend action programmatically. */\n sendAction(action: import('./types.js').ActionPayload, options?: { silent?: boolean }): void;\n close(): void;\n saveSession(sessionId: string, sku: string): void;\n readonly isOpen: boolean;\n on(\n event: 'open' | 'close' | 'ready' | 'message' | 'error' | 'context-update' | 'destroy',\n handler: (...args: unknown[]) => void,\n ): () => void;\n trackCheckout(\n type: 'start' | 'complete',\n data: {\n attribution_source: 'chat' | 'qna' | 'simrel';\n attribution_action_id: string;\n cart_value: number;\n currency: string;\n line_items: number;\n },\n ): void;\n flushMeteringSummary(data: { meter_key: string; quantity: number; unit: string }): void;\n /**\n * Register a callback for a GA4 event name.\n * When the widget fires that event, the callback is invoked with the event detail.\n * Callbacks that return `false` or throw signal failure — the widget reacts accordingly\n * (e.g. showing an error message for add-to-cart failures).\n *\n * @returns unsubscribe function\n */\n addCallback(eventName: string, callback: (detail: Record<string, unknown>) => boolean | Promise<boolean>): () => void;\n}\n","/**\n * Google Analytics dataLayer integration.\n *\n * Pushes chat activity events to `window.dataLayer` when GA is available.\n * Falls back to `console.debug` when GA is not detected (useful for debugging).\n *\n * Event naming follows the GA4 recommended event pattern:\n * - All lowercase, hyphen-separated\n * - Prefixed with `gengage-` for easy filtering in GA dashboards\n *\n * Clients can build custom chat funnels in GA using these events.\n */\n\n// ---------------------------------------------------------------------------\n// GA dataLayer type augmentation\n// ---------------------------------------------------------------------------\n\ninterface DataLayerEvent {\n event: string;\n [key: string]: unknown;\n}\n\ndeclare global {\n interface Window {\n dataLayer?: DataLayerEvent[];\n }\n}\n\n// ---------------------------------------------------------------------------\n// GA detection\n// ---------------------------------------------------------------------------\n\nfunction isGAAvailable(): boolean {\n return typeof window !== 'undefined' && Array.isArray(window.dataLayer);\n}\n\n// ---------------------------------------------------------------------------\n// Core push function\n// ---------------------------------------------------------------------------\n\nfunction pushEvent(eventName: string, params?: Record<string, unknown>): void {\n const payload: DataLayerEvent = {\n event: eventName,\n ...params,\n };\n\n if (isGAAvailable()) {\n window.dataLayer!.push(payload);\n }\n // No fallback log — GA events are silently dropped when dataLayer is absent.\n}\n\n// ---------------------------------------------------------------------------\n// Typed event emitters\n// ---------------------------------------------------------------------------\n\n/** Widget icon/avatar displayed on page. */\nexport function trackInit(widget: string): void {\n pushEvent('gengage-on-init', { gengage_widget: widget });\n}\n\n/** Widget opened / shown to user. */\nexport function trackShow(widget: string): void {\n pushEvent('gengage-show', { gengage_widget: widget });\n}\n\n/** Widget closed / hidden. */\nexport function trackHide(widget: string): void {\n pushEvent('gengage-hide', { gengage_widget: widget });\n}\n\n/** User clicked a suggested question / action button. */\nexport function trackSuggestedQuestion(title: string, type: string): void {\n pushEvent('gengage-suggested-question', {\n gengage_question_title: title,\n gengage_action_type: type,\n });\n}\n\n/** User clicked \"Find Similar\" for a product. */\nexport function trackFindSimilars(sku: string): void {\n pushEvent('gengage-find-similars', { gengage_sku: sku });\n}\n\n/** User pre-selected a product for comparison. */\nexport function trackComparePreselection(sku: string): void {\n pushEvent('gengage-compare-preselection', { gengage_sku: sku });\n}\n\n/** User submitted the comparison (clicked \"Compare Selected\"). */\nexport function trackCompareSelected(skus: string[]): void {\n pushEvent('gengage-compare-selected', {\n gengage_skus: skus,\n gengage_product_count: skus.length,\n });\n}\n\n/** User cleared the comparison selection. */\nexport function trackCompareClear(): void {\n pushEvent('gengage-compare-clear');\n}\n\n/** Comparison results received and rendered. */\nexport function trackCompareReceived(productCount: number): void {\n pushEvent('gengage-compare-received', {\n gengage_product_count: productCount,\n });\n}\n\n/** User liked / favorited a product. */\nexport function trackLikeProduct(sku: string): void {\n pushEvent('gengage-like-product', { gengage_sku: sku });\n}\n\n/** User clicked the favorites/likes list button. */\nexport function trackLikeList(): void {\n pushEvent('gengage-like-list');\n}\n\n/** Product list / search results displayed. */\nexport function trackSearch(query?: string, resultCount?: number): void {\n pushEvent('gengage-search', {\n gengage_search_query: query,\n gengage_result_count: resultCount,\n });\n}\n\n/** User clicked on a product to view details. */\nexport function trackProductDetail(sku: string, name?: string): void {\n pushEvent('gengage-product-detail', {\n gengage_sku: sku,\n gengage_product_name: name,\n });\n}\n\n/** User added a product to cart from the widget. */\nexport function trackCartAdd(sku: string, quantity: number): void {\n pushEvent('gengage-cart-add', {\n gengage_sku: sku,\n gengage_quantity: quantity,\n });\n}\n\n/** User sent a chat message. */\nexport function trackMessageSent(): void {\n pushEvent('gengage-message-sent');\n}\n\n/** Assistant responded with text. */\nexport function trackMessageReceived(): void {\n pushEvent('gengage-message-received');\n}\n\n/** User started a new conversation. */\nexport function trackConversationStart(): void {\n pushEvent('gengage-conversation-start');\n}\n\n/** User used voice input. */\nexport function trackVoiceInput(): void {\n pushEvent('gengage-voice-input');\n}\n\n/** Widget or stream error occurred. */\nexport function trackError(widget: string, error: string): void {\n pushEvent('gengage-error', { gengage_widget: widget, gengage_error: error });\n}\n\n// ---------------------------------------------------------------------------\n// Batch wire-up: connect to the Gengage event bus\n// ---------------------------------------------------------------------------\n\n/**\n * Wire GA dataLayer tracking to the Gengage event bus.\n * Call once after widgets are initialized.\n *\n * @returns unsubscribe function that removes all listeners.\n */\nlet _gaWiredUnsub: (() => void) | null = null;\n\nexport function wireGADataLayer(): () => void {\n if (typeof window === 'undefined') return () => {};\n // Idempotency guard: return existing unsubscribe if already wired\n if (_gaWiredUnsub) return _gaWiredUnsub;\n\n const listeners: Array<() => void> = [];\n\n function on<T>(eventName: string, handler: (detail: T) => void): void {\n const listener = (e: Event) => handler((e as CustomEvent<T>).detail);\n window.addEventListener(eventName, listener);\n listeners.push(() => window.removeEventListener(eventName, listener));\n }\n\n // Chat lifecycle\n on<{ state?: string }>('gengage:chat:open', () => trackShow('chat'));\n on<Record<string, never>>('gengage:chat:close', () => trackHide('chat'));\n on<Record<string, never>>('gengage:chat:ready', () => trackInit('chat'));\n\n // Add to cart (from similar products widget — chat handles GA4 directly)\n on<{ sku: string; quantity: number; cartCode: string }>('gengage:similar:add-to-cart', ({ sku, quantity }) => {\n trackCartAdd(sku, quantity);\n });\n\n // Product click from similar products\n on<{ sku: string; url: string }>('gengage:similar:product-click', ({ sku }) => {\n trackProductDetail(sku);\n });\n\n // QNA action (suggested question click)\n on<{ title: string; type: string }>('gengage:qna:action', ({ title, type }) => {\n trackSuggestedQuestion(title, type);\n });\n\n // Voice input\n on<{ payload: unknown }>('gengage:chat:voice', () => trackVoiceInput());\n\n // QNA open chat\n on<Record<string, never>>('gengage:qna:open-chat', () => trackShow('chat'));\n\n // Error tracking\n on<{ source: string; message: string }>('gengage:global:error', ({ source, message }) => {\n trackError(source, message);\n });\n\n _gaWiredUnsub = () => {\n for (const unsub of listeners) unsub();\n listeners.length = 0;\n _gaWiredUnsub = null;\n };\n return _gaWiredUnsub;\n}\n"],"mappings":"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"}
@@ -1,48 +0,0 @@
1
- function e(e,t){let n={event_name:`stream.start`,account_id:e.account_id,session_id:e.session_id,correlation_id:e.correlation_id,payload:{endpoint:t.endpoint,request_id:t.request_id}};return e.view_id!==void 0&&(n.view_id=e.view_id),e.user_id!==void 0&&(n.user_id=e.user_id),t.widget!==void 0&&(n.widget=t.widget),e.page_type!==void 0&&(n.page_type=e.page_type),e.sku!==void 0&&(n.sku=e.sku),n}function t(e,t){let n={request_id:t.request_id,chunk_index:t.chunk_index};t.latency_ms!==void 0&&(n.latency_ms=t.latency_ms);let r={event_name:`stream.chunk`,account_id:e.account_id,session_id:e.session_id,correlation_id:e.correlation_id,payload:n};return e.view_id!==void 0&&(r.view_id=e.view_id),e.user_id!==void 0&&(r.user_id=e.user_id),t.widget!==void 0&&(r.widget=t.widget),e.page_type!==void 0&&(r.page_type=e.page_type),e.sku!==void 0&&(r.sku=e.sku),r}function n(e,t){let n={event_name:`stream.ui_spec`,account_id:e.account_id,session_id:e.session_id,correlation_id:e.correlation_id,payload:{request_id:t.request_id,chunk_index:t.chunk_index,component_type:t.component_type}};return e.view_id!==void 0&&(n.view_id=e.view_id),e.user_id!==void 0&&(n.user_id=e.user_id),t.widget!==void 0&&(n.widget=t.widget),e.page_type!==void 0&&(n.page_type=e.page_type),e.sku!==void 0&&(n.sku=e.sku),n}function r(e,t){let n={event_name:`stream.done`,account_id:e.account_id,session_id:e.session_id,correlation_id:e.correlation_id,payload:{request_id:t.request_id,latency_ms:t.latency_ms,chunk_count:t.chunk_count}};return e.view_id!==void 0&&(n.view_id=e.view_id),e.user_id!==void 0&&(n.user_id=e.user_id),t.widget!==void 0&&(n.widget=t.widget),e.page_type!==void 0&&(n.page_type=e.page_type),e.sku!==void 0&&(n.sku=e.sku),n}function i(e,t){let n={event_name:`stream.error`,account_id:e.account_id,session_id:e.session_id,correlation_id:e.correlation_id,payload:{request_id:t.request_id,error_code:t.error_code,error_message:t.error_message}};return e.view_id!==void 0&&(n.view_id=e.view_id),e.user_id!==void 0&&(n.user_id=e.user_id),t.widget!==void 0&&(n.widget=t.widget),e.page_type!==void 0&&(n.page_type=e.page_type),e.sku!==void 0&&(n.sku=e.sku),n}function a(e,t){let n={model:t.model,prompt_tokens:t.prompt_tokens,completion_tokens:t.completion_tokens,total_tokens:t.total_tokens};t.provider!==void 0&&(n.provider=t.provider);let r={event_name:`llm.usage`,account_id:e.account_id,session_id:e.session_id,correlation_id:e.correlation_id,payload:n};return e.view_id!==void 0&&(r.view_id=e.view_id),e.user_id!==void 0&&(r.user_id=e.user_id),e.page_type!==void 0&&(r.page_type=e.page_type),e.sku!==void 0&&(r.sku=e.sku),r}function o(e,t){let n={event_name:`metering.increment`,account_id:e.account_id,session_id:e.session_id,correlation_id:e.correlation_id,payload:{meter_key:t.meter_key,quantity:t.quantity,unit:t.unit}};return e.view_id!==void 0&&(n.view_id=e.view_id),e.user_id!==void 0&&(n.user_id=e.user_id),e.page_type!==void 0&&(n.page_type=e.page_type),e.sku!==void 0&&(n.sku=e.sku),n}function s(e,t){let n={event_name:`metering.summary`,account_id:e.account_id,session_id:e.session_id,correlation_id:e.correlation_id,payload:{meter_key:t.meter_key,quantity:t.quantity,unit:t.unit}};return e.view_id!==void 0&&(n.view_id=e.view_id),e.user_id!==void 0&&(n.user_id=e.user_id),e.page_type!==void 0&&(n.page_type=e.page_type),e.sku!==void 0&&(n.sku=e.sku),n}function c(e,t){let n={event_name:`chat.history.snapshot`,account_id:e.account_id,session_id:e.session_id,correlation_id:e.correlation_id,payload:{message_count:t.message_count,history_ref:t.history_ref,redaction_level:t.redaction_level}};return e.view_id!==void 0&&(n.view_id=e.view_id),e.user_id!==void 0&&(n.user_id=e.user_id),e.page_type!==void 0&&(n.page_type=e.page_type),e.sku!==void 0&&(n.sku=e.sku),n}function l(e,t){let n={event_name:`widget.history.snapshot`,account_id:e.account_id,session_id:e.session_id,correlation_id:e.correlation_id,widget:t.widget,payload:{message_count:t.message_count,history_ref:t.history_ref,redaction_level:t.redaction_level}};return e.view_id!==void 0&&(n.view_id=e.view_id),e.user_id!==void 0&&(n.user_id=e.user_id),e.page_type!==void 0&&(n.page_type=e.page_type),e.sku!==void 0&&(n.sku=e.sku),n}function u(e,t){let n={event_name:`basket.add`,account_id:e.account_id,session_id:e.session_id,correlation_id:e.correlation_id,widget:t.attribution_source,payload:{attribution_source:t.attribution_source,attribution_action_id:t.attribution_action_id,cart_value:t.cart_value,currency:t.currency,line_items:t.line_items,sku:t.sku}};return e.view_id!==void 0&&(n.view_id=e.view_id),e.user_id!==void 0&&(n.user_id=e.user_id),e.page_type!==void 0&&(n.page_type=e.page_type),e.sku!==void 0&&(n.sku=e.sku),n}function d(e,t){let n={event_name:`checkout.start`,account_id:e.account_id,session_id:e.session_id,correlation_id:e.correlation_id,widget:t.attribution_source,payload:{attribution_source:t.attribution_source,attribution_action_id:t.attribution_action_id,cart_value:t.cart_value,currency:t.currency,line_items:t.line_items}};return e.view_id!==void 0&&(n.view_id=e.view_id),e.user_id!==void 0&&(n.user_id=e.user_id),e.page_type!==void 0&&(n.page_type=e.page_type),e.sku!==void 0&&(n.sku=e.sku),n}function f(e,t){let n={event_name:`checkout.complete`,account_id:e.account_id,session_id:e.session_id,correlation_id:e.correlation_id,widget:t.attribution_source,payload:{attribution_source:t.attribution_source,attribution_action_id:t.attribution_action_id,cart_value:t.cart_value,currency:t.currency,line_items:t.line_items}};return e.view_id!==void 0&&(n.view_id=e.view_id),e.user_id!==void 0&&(n.user_id=e.user_id),e.page_type!==void 0&&(n.page_type=e.page_type),e.sku!==void 0&&(n.sku=e.sku),n}var p=new Set(`p.br.a.strong.b.em.i.u.ul.ol.li.h1.h2.h3.h4.h5.h6.span.div.table.thead.tbody.tr.th.td.hr.code.pre.blockquote.img.sup.sub`.split(`.`)),ee=new Set([`script`,`iframe`,`object`,`embed`,`form`,`input`,`textarea`,`select`,`button`,`style`,`link`,`meta`,`template`,`noscript`]),m={"*":new Set([`class`]),a:new Set([`href`,`target`,`rel`]),img:new Set([`src`,`alt`,`width`,`height`]),div:new Set([`style`]),span:new Set([`style`]),p:new Set([`style`])};function te(e){return/^\s*javascript\s*:/i.test(e)}var ne=new Set(`color.background-color.font-size.font-weight.font-style.font-family.text-align.text-decoration.line-height.letter-spacing.margin.margin-top.margin-right.margin-bottom.margin-left.padding.padding-top.padding-right.padding-bottom.padding-left.border.border-top.border-right.border-bottom.border-left.border-radius.border-color.border-width.border-style.width.max-width.min-width.height.max-height.min-height.display.vertical-align.white-space.word-break.overflow.opacity.visibility.list-style.list-style-type.text-transform.text-indent.text-overflow.box-sizing.flex.flex-direction.flex-wrap.justify-content.align-items.gap`.split(`.`)),h=/url\s*\(|expression\s*\(|javascript\s*:|\bimport\b|-moz-binding|behavior\s*:/i;function g(e){let t=[];for(let n of e.split(`;`)){let e=n.trim();if(!e)continue;let r=e.indexOf(`:`);if(r===-1)continue;let i=e.slice(0,r).trim().toLowerCase(),a=e.slice(r+1).trim();ne.has(i)&&(h.test(a)||t.push(e))}return t.join(`; `)}function _(e,t){if(e.nodeType===Node.TEXT_NODE)return;if(e.nodeType!==Node.ELEMENT_NODE){e.parentNode?.removeChild(e);return}let n=e,r=n.tagName.toLowerCase();if(ee.has(r)){n.parentNode?.removeChild(n);return}if(!p.has(r)){let e=Array.from(n.childNodes);for(let r of e)t.insertBefore(r,n);t.removeChild(n);for(let n of e)_(n,t);return}let i=m[`*`]??new Set,a=m[r]??new Set,o=Array.from(n.attributes);for(let e of o){let t=e.name.toLowerCase();if(!i.has(t)&&!a.has(t)){n.removeAttribute(e.name);continue}if(te(e.value)){n.removeAttribute(e.name);continue}if(t===`style`){let t=g(e.value);t?n.setAttribute(`style`,t):n.removeAttribute(`style`);continue}}if(r===`a`){let e=n.getAttribute(`href`);if(e!==null){let t=e.trim().toLowerCase();!t.startsWith(`http://`)&&!t.startsWith(`https://`)&&!t.startsWith(`mailto:`)&&n.removeAttribute(`href`)}n.setAttribute(`target`,`_blank`),n.setAttribute(`rel`,`noopener noreferrer`)}if(r===`img`){let e=n.getAttribute(`src`);e!==null&&(e.trim().toLowerCase().startsWith(`https://`)||n.removeAttribute(`src`))}let s=Array.from(n.childNodes);for(let e of s)_(e,n)}var v=[`http:`,`https:`];function re(e){try{return v.includes(new URL(e).protocol)}catch{return!1}}function y(e){if(e.startsWith(`/`)&&!e.startsWith(`//`))return!0;try{let t=new URL(e);return v.includes(t.protocol)}catch{return!1}}function ie(e,t,n){(t===`href`||t===`src`)&&!y(n)||e.setAttribute(t,n)}function ae(e){if(!e)return``;let t=new DOMParser().parseFromString(e,`text/html`).body,n=Array.from(t.childNodes);for(let e of n)_(e,t);return t.innerHTML}function oe(e,t){window.dispatchEvent(new CustomEvent(e,{detail:t,bubbles:!1}))}function b(e,t){let n=e=>{t(e.detail)};return window.addEventListener(e,n),()=>window.removeEventListener(e,n)}function x(e){if(e.type!==`user_message`&&e.type!==`inputText`)return null;if(typeof e.payload==`string`&&e.payload.trim().length>0)return e.payload.trim();if(typeof e.payload==`object`&&e.payload!==null){let t=e.payload;if(typeof t.text==`string`){let e=t.text.trim();if(e.length>0)return e}}return typeof e.title==`string`&&e.title.trim().length>0?e.title.trim():null}function S(e){let t=!1,n=[],r=0,i=null,a=0;function o(){return window.gengage?.chat??null}function s(){t||=(console.warn(`[gengage] QNA tried to open chat, but chat widget is not initialized. Ensure GengageChat is initialized before calling wireQNAToChat().`),!0),e?.onChatUnavailable?.()}function c(e,t){let n=x(t);if(n&&e.sendMessage){e.open?.(),e.sendMessage(n);return}e.openWithAction?.(t)}function l(){i!==null&&(window.clearInterval(i),i=null)}function u(){let e=o();if(!e)return!1;if(r>0&&(e.open?.(),r=0),n.length>0){let t=n.splice(0,n.length);for(let n of t)c(e,n)}return l(),!0}function d(){i===null&&(a=Date.now(),i=window.setInterval(()=>{u()||Date.now()-a>=5e3&&(n.length=0,r=0,l())},100))}let f=b(`gengage:qna:action`,e=>{let t=o();if(t){c(t,e);return}s(),n.length>=20&&n.shift(),n.push(e),d()}),p=b(`gengage:qna:open-chat`,()=>{let e=o();if(e){e.open?.();return}s(),r+=1,d()});return()=>{f(),p(),n.length=0,r=0,l()}}function C(){return b(`gengage:similar:product-click`,({sku:e,url:t,sessionId:n})=>{n&&window.gengage?.chat?.saveSession(n,e),y(t)&&(window.location.href=t)})}function w(){let e=window.__gengageSessionId??sessionStorage.getItem(`gengage_session_id`)??null??crypto.randomUUID();return window.__gengageSessionId=e,sessionStorage.setItem(`gengage_session_id`,e),window.gengage||(window.gengage={}),window.gengage.sessionId=e,e}function T(){return window.gengage?.pageContext??null}function E(e){window.gengage||(window.gengage={}),window.gengage.pageContext={pageType:`other`,...window.gengage.pageContext,...e},window.dispatchEvent(new CustomEvent(`gengage:context:update`,{detail:e}))}function D(e){return{sessionId:e?.sessionId??w(),...e}}var O={"--gengage-chat-offset":`20px`,"--gengage-chat-launcher-size":`56px`,"--gengage-chat-width":`400px`,"--gengage-chat-shell-radius":`1rem`,"--gengage-chat-header-height":`72px`,"--gengage-chat-conversation-width":`396px`,"--gengage-chat-panel-min-width":`320px`,"--gengage-chat-panel-max-width":`1200px`,"--gengage-chat-input-height":`48px`,"--gengage-qna-pill-radius":`999px`,"--gengage-qna-input-radius":`0.75rem`,"--gengage-simrel-card-radius":`0.75rem`,"--radius-control":`12px`,"--radius-card":`16px`,"--radius-panel":`24px`,"--radius-pill":`999px`,"--surface-card-muted":`#f8fafc`,"--text-secondary":`#4b5563`,"--text-muted":`#6b7280`,"--border-default":`rgba(17, 24, 39, 0.10)`};function k(e){return e?{...O,...e}:{...O}}var A={primaryColor:`#b7102a`,primaryForeground:`#ffffff`,backgroundColor:`#ffffff`,foregroundColor:`#111827`,borderRadius:`0.75rem`,fontFamily:`"Plus Jakarta Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif`,fontSize:`14px`,zIndex:`1000`,"--glov-chatbot-width":`420px`,"--glov-left-spacing":`260px`,"--chatbot-padding":`16px`,"--root-wrapper-background-color":`#f8f9fa`,"--root-wrapper-border-color":`#edeeef`,"--gengage-chat-width":`400px`,"--gengage-chat-shell-radius":`1rem`,"--gengage-chat-header-height":`72px`,"--gengage-chat-conversation-width":`396px`,"--gengage-chat-panel-min-width":`320px`,"--gengage-chat-panel-max-width":`1200px`,"--gengage-chat-input-height":`48px`,"--gengage-qna-pill-radius":`999px`,"--gengage-qna-input-radius":`0.75rem`,"--gengage-simrel-card-radius":`0.75rem`,"--client-primary":`#b7102a`,"--client-primary-hover":`color-mix(in srgb, #b7102a 88%, black 12%)`,"--client-primary-active":`color-mix(in srgb, #b7102a 78%, black 22%)`,"--client-primary-subtle":`color-mix(in srgb, #b7102a 12%, white)`,"--client-primary-soft":`color-mix(in srgb, #b7102a 20%, white)`,"--client-on-primary":`#ffffff`,"--client-focus-ring":`color-mix(in srgb, #b7102a 32%, transparent)`,"--surface-page":`#f6f7fb`,"--surface-shell":`#10131a`,"--surface-card":`#ffffff`,"--surface-card-muted":`#f8fafc`,"--surface-card-soft":`#f8fafc`,"--surface-elevated":`#ffffff`,"--surface-input":`#ffffff`,"--surface-overlay":`rgba(16, 19, 26, 0.52)`,"--text-primary":`#111827`,"--text-secondary":`#4b5563`,"--text-muted":`#6b7280`,"--text-inverse":`#f9fafb`,"--border-subtle":`rgba(17, 24, 39, 0.06)`,"--border-default":`rgba(17, 24, 39, 0.10)`,"--border-strong":`rgba(17, 24, 39, 0.18)`,"--shadow-1":`0 1px 2px rgba(16, 24, 40, 0.04), 0 1px 3px rgba(16, 24, 40, 0.06)`,"--shadow-2":`0 4px 12px rgba(16, 24, 40, 0.08)`,"--shadow-3":`0 10px 24px rgba(16, 24, 40, 0.12)`,"--radius-control":`12px`,"--radius-card":`16px`,"--radius-panel":`24px`,"--radius-pill":`999px`,"--success":`#16a34a`,"--warning":`#d97706`,"--error":`#dc2626`,"--info":`#2563eb`,"--rating":`#f5b301`,"--ai-accent-start":`#0b24d6`,"--ai-accent-end":`#f768f2`,"--ai-accent-soft":`linear-gradient(135deg, rgba(11, 36, 214, 0.08), rgba(247, 104, 242, 0.08))`};function se(e){return{...A,...e}}var j=`gengage-global-toast-root`,M=`gengage-global-toast-style`,N=`gengage-global-toast-root--visible`,ce=4200,le=1500,ue=15e3,de=[`--gengage-font-family`,`--surface-card`,`--text-primary`,`--text-muted`,`--border-default`,`--radius-card`,`--shadow-3`,`--error`,`--ds-toast-error-bg`,`--ds-toast-error-border`,`--ds-toast-error-accent`,`--ds-toast-error-fg`,`--ds-toast-error-shadow`],P=!1,F=null,I=[/failed to fetch/i,/networkerror/i,/network request failed/i,/load failed/i,/err_network/i,/fetch failed/i,/network error/i];function L(e){return typeof e==`string`&&e.toLowerCase().startsWith(`tr`)}function R(e){if(typeof navigator<`u`&&navigator.onLine===!1)return!0;let t=e instanceof Error?e.message.trim():``;return t?I.some(e=>e.test(t)):!1}function z(e,t){return R(t)?L(e)?`Bağlantı sorunu oluştu. Lütfen tekrar deneyin.`:`Connection issue. Please try again.`:L(e)?`Bir hata oluştu. Lütfen tekrar deneyin.`:`Something went wrong. Please try again.`}function B(){P||typeof window>`u`||typeof document>`u`||(P=!0,b(`gengage:global:error`,e=>{V(e)}))}function V(e){if(typeof document>`u`)return;let t=e.message.trim();if(!t)return;ge();let n=pe();me(n),n.innerHTML=``;let r=document.createElement(`section`);r.className=`gengage-global-toast gengage-global-toast--error`,r.setAttribute(`role`,`status`),r.setAttribute(`aria-live`,`polite`);let i=document.createElement(`div`);i.className=`gengage-global-toast-title`,i.textContent=fe(e.source);let a=document.createElement(`div`);a.className=`gengage-global-toast-message`,a.textContent=t,r.appendChild(i),r.appendChild(a),n.appendChild(r),n.classList.add(N),F&&=(clearTimeout(F),null),e.sticky!==!0&&(F=setTimeout(()=>{H()},he(e.durationMs)))}function H(){if(typeof document>`u`)return;let e=document.getElementById(j);e&&(e.classList.remove(N),e.innerHTML=``,F&&=(clearTimeout(F),null))}function fe(e){switch(e){case`chat`:return`Chat warning`;case`qna`:return`QnA warning`;case`simrel`:return`Widget warning`;default:return`Connection warning`}}function pe(){let e=document.getElementById(j);if(e instanceof HTMLElement)return e;let t=document.createElement(`div`);return t.id=j,t.className=`gengage-global-toast-root`,document.body.appendChild(t),t}function me(e){if(typeof document>`u`||typeof window>`u`)return;let t=document.querySelector(`.gengage-chat-root, .gengage-qna-container, .gengage-simrel-container, .gengage-simbut-root`);if(!t)return;let n=window.getComputedStyle(t);for(let t of de){let r=n.getPropertyValue(t).trim();r?e.style.setProperty(t,r):e.style.removeProperty(t)}}function he(e){return typeof e!=`number`||!Number.isFinite(e)?ce:Math.min(ue,Math.max(le,Math.round(e)))}function ge(){if(document.getElementById(M))return;let e=document.createElement(`style`);e.id=M;let t=A[`--surface-card`]??A.backgroundColor??`#ffffff`,n=A[`--text-primary`]??A.foregroundColor??`#111827`,r=A[`--border-default`]??`rgba(17, 24, 39, 0.10)`,i=A[`--error`]??`#dc2626`,a=A[`--shadow-3`]??`0 10px 24px rgba(16, 24, 40, 0.12)`,o=A[`--radius-card`]??`16px`,s=A[`--text-muted`]??`#6b7280`;e.textContent=`
2
- #${j} {
3
- position: fixed;
4
- top: 16px;
5
- right: 16px;
6
- z-index: 2147483646;
7
- pointer-events: none;
8
- }
9
- #${j}.${N} {
10
- pointer-events: auto;
11
- }
12
- #${j} .gengage-global-toast {
13
- min-width: 260px;
14
- max-width: min(92vw, 420px);
15
- border-radius: var(--radius-card, ${o});
16
- border: 1px solid var(--ds-toast-error-border, color-mix(in srgb, var(--error, ${i}) 18%, var(--border-default, ${r})));
17
- border-left: 4px solid var(--ds-toast-error-accent, var(--error, ${i}));
18
- background: var(--ds-toast-error-bg, color-mix(in srgb, var(--error, ${i}) 5%, var(--surface-card, ${t})));
19
- color: var(--ds-toast-error-fg, color-mix(in srgb, var(--error, ${i}) 22%, var(--text-primary, ${n})));
20
- box-shadow: var(--ds-toast-error-shadow, var(--shadow-3, ${a}));
21
- padding: 10px 12px;
22
- font-family: var(--gengage-font-family, ${JSON.stringify(A.fontFamily??`-apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif`)});
23
- font-size: 13px;
24
- line-height: 1.4;
25
- animation: gengage-global-toast-in 180ms ease-out forwards;
26
- }
27
- #${j} .gengage-global-toast-title {
28
- margin: 0 0 4px;
29
- font-size: 12px;
30
- font-weight: 700;
31
- color: var(--text-muted, ${s});
32
- }
33
- #${j} .gengage-global-toast-message {
34
- margin: 0;
35
- font-weight: 500;
36
- }
37
- @keyframes gengage-global-toast-in {
38
- from {
39
- opacity: 0;
40
- transform: translateY(-8px);
41
- }
42
- to {
43
- opacity: 1;
44
- transform: translateY(0);
45
- }
46
- }
47
- `,document.head.appendChild(e)}var U=null;function _e(){if(U!==null)return U;try{U=localStorage.getItem(`gengage:debug`)===`1`}catch{U=!1}return U}function W(e,t,n){if(!_e())return;let r=[`[gengage:${e}]`,t];n!==void 0&&r.push(n),console.debug(...r)}var ve=class{constructor(){this.isVisible=!1,this.isInitialised=!1,this._handlers=new Map,this._cleanups=[],this._ownsRoot=!1,this._destroying=!1}async init(e){if(this.isInitialised){console.warn(`[gengage] Widget already initialised. Call update() instead.`);return}let t=k(e.theme);this.config={...e,theme:t,session:D(e.session)},this.root=this._resolveMount(e.mountTarget),this._applyTheme(t),B();let n=b(`gengage:context:update`,e=>this.update(e));this._cleanups.push(n),W(`lifecycle`,`${this.constructor.name}.init`,{accountId:e.accountId,sku:e.pageContext?.sku});try{await this.onInit(this.config)}catch(e){throw this.destroy(),e}this._destroying||(this.isInitialised=!0,W(`lifecycle`,`${this.constructor.name} ready`),this.emit(`ready`))}update(e){this.isInitialised&&(this.config.pageContext?this.config={...this.config,pageContext:{...this.config.pageContext,...e}}:e.pageType!==void 0&&(this.config={...this.config,pageContext:e}),this.onUpdate(e),this.emit(`context-update`,this.config.pageContext))}show(){this.isVisible||(this.isVisible=!0,this.root.style.display=``,this.onShow(),this.emit(`show`))}hide(){this.isVisible&&(this.isVisible=!1,this.root.style.display=`none`,this.onHide(),this.emit(`hide`))}destroy(){this._destroying||(this._destroying=!0,this.emit(`destroy`),this._cleanups.forEach(e=>e()),this._cleanups.length=0,this._handlers.clear(),this.onDestroy(),this.config.analyticsClient?.destroy(),this._ownsRoot?this.root.remove():this.root.innerHTML=``,this.isInitialised=!1)}on(e,t){return this._handlers.has(e)||this._handlers.set(e,new Set),this._handlers.get(e).add(t),()=>this._handlers.get(e)?.delete(t)}trackCheckout(e,t){let n=e===`start`?d:f;this.track(n(this.analyticsContext(),t))}flushMeteringSummary(e){this.track(s(this.analyticsContext(),e))}emit(e,...t){this._handlers.get(e)?.forEach(e=>e(...t))}addCleanup(e){this._cleanups.push(e)}track(e){this.config.analyticsClient?.track(e)}analyticsContext(){let e={account_id:this.config.accountId,session_id:this.config.session?.sessionId??``,correlation_id:this.config.session?.sessionId??``};return this.config.session?.viewId!==void 0&&(e.view_id=this.config.session.viewId),this.config.session?.userId!==void 0&&(e.user_id=this.config.session.userId),this.config.pageContext?.pageType!==void 0&&(e.page_type=this.config.pageContext.pageType),this.config.pageContext?.sku!==void 0&&(e.sku=this.config.pageContext.sku),this.config.session?.abTestVariant!==void 0&&(e.ab_test_variant=this.config.session.abTestVariant),this.config.session?.abTestExperimentId!==void 0&&(e.ab_test_experiment_id=this.config.session.abTestExperimentId),e}_resolveMount(e){if(e instanceof HTMLElement)return e;if(typeof e==`string`){let t=document.querySelector(e);if(!t)throw Error(`[gengage] Mount target not found: "${e}"`);return t}let t=document.createElement(`div`);return t.dataset.gengageWidget=this.constructor.name.toLowerCase(),document.body.insertBefore(t,document.body.firstChild),this._ownsRoot=!0,t}_applyTheme(e){if(e){for(let[t,n]of Object.entries(e))if(n!==void 0){let e=t.startsWith(`--`)?t:`--gengage-${ye(t)}`;this.root.style.setProperty(e,n)}}}};function ye(e){return e.replace(/([A-Z])/g,`-$1`).toLowerCase()}function be(){return typeof window<`u`&&Array.isArray(window.dataLayer)}function G(e,t){let n={event:e,...t};be()&&window.dataLayer.push(n)}function K(e){G(`gengage-on-init`,{gengage_widget:e})}function q(e){G(`gengage-show`,{gengage_widget:e})}function xe(e){G(`gengage-hide`,{gengage_widget:e})}function J(e,t){G(`gengage-suggested-question`,{gengage_question_title:e,gengage_action_type:t})}function Se(e){G(`gengage-find-similars`,{gengage_sku:e})}function Ce(e){G(`gengage-compare-preselection`,{gengage_sku:e})}function we(e){G(`gengage-compare-selected`,{gengage_skus:e,gengage_product_count:e.length})}function Te(){G(`gengage-compare-clear`)}function Ee(e){G(`gengage-compare-received`,{gengage_product_count:e})}function De(e){G(`gengage-like-product`,{gengage_sku:e})}function Oe(){G(`gengage-like-list`)}function ke(e,t){G(`gengage-search`,{gengage_search_query:e,gengage_result_count:t})}function Y(e,t){G(`gengage-product-detail`,{gengage_sku:e,gengage_product_name:t})}function X(e,t){G(`gengage-cart-add`,{gengage_sku:e,gengage_quantity:t})}function Z(){G(`gengage-message-sent`)}function Ae(){G(`gengage-message-received`)}function je(){G(`gengage-conversation-start`)}function Q(){G(`gengage-voice-input`)}function Me(e,t){G(`gengage-error`,{gengage_widget:e,gengage_error:t})}var $=null;function Ne(){if(typeof window>`u`)return()=>{};if($)return $;let e=[];function t(t,n){let r=e=>n(e.detail);window.addEventListener(t,r),e.push(()=>window.removeEventListener(t,r))}return t(`gengage:chat:open`,()=>q(`chat`)),t(`gengage:chat:close`,()=>xe(`chat`)),t(`gengage:chat:ready`,()=>K(`chat`)),t(`gengage:similar:add-to-cart`,({sku:e,quantity:t})=>{X(e,t)}),t(`gengage:similar:product-click`,({sku:e})=>{Y(e)}),t(`gengage:qna:action`,({title:e,type:t})=>{J(e,t)}),t(`gengage:chat:voice`,()=>Q()),t(`gengage:qna:open-chat`,()=>q(`chat`)),t(`gengage:global:error`,({source:e,message:t})=>{Me(e,t)}),$=()=>{for(let t of e)t();e.length=0,$=null},$}Object.defineProperty(exports,`$`,{enumerable:!0,get:function(){return n}}),Object.defineProperty(exports,`A`,{enumerable:!0,get:function(){return w}}),Object.defineProperty(exports,`B`,{enumerable:!0,get:function(){return ie}}),Object.defineProperty(exports,`C`,{enumerable:!0,get:function(){return R}}),Object.defineProperty(exports,`D`,{enumerable:!0,get:function(){return se}}),Object.defineProperty(exports,`E`,{enumerable:!0,get:function(){return A}}),Object.defineProperty(exports,`F`,{enumerable:!0,get:function(){return b}}),Object.defineProperty(exports,`G`,{enumerable:!0,get:function(){return d}}),Object.defineProperty(exports,`H`,{enumerable:!0,get:function(){return u}}),Object.defineProperty(exports,`I`,{enumerable:!0,get:function(){return S}}),Object.defineProperty(exports,`J`,{enumerable:!0,get:function(){return s}}),Object.defineProperty(exports,`K`,{enumerable:!0,get:function(){return a}}),Object.defineProperty(exports,`L`,{enumerable:!0,get:function(){return C}}),Object.defineProperty(exports,`M`,{enumerable:!0,get:function(){return D}}),Object.defineProperty(exports,`N`,{enumerable:!0,get:function(){return E}}),Object.defineProperty(exports,`O`,{enumerable:!0,get:function(){return O}}),Object.defineProperty(exports,`P`,{enumerable:!0,get:function(){return oe}}),Object.defineProperty(exports,`Q`,{enumerable:!0,get:function(){return e}}),Object.defineProperty(exports,`R`,{enumerable:!0,get:function(){return re}}),Object.defineProperty(exports,`S`,{enumerable:!0,get:function(){return z}}),Object.defineProperty(exports,`T`,{enumerable:!0,get:function(){return V}}),Object.defineProperty(exports,`U`,{enumerable:!0,get:function(){return c}}),Object.defineProperty(exports,`V`,{enumerable:!0,get:function(){return ae}}),Object.defineProperty(exports,`W`,{enumerable:!0,get:function(){return f}}),Object.defineProperty(exports,`X`,{enumerable:!0,get:function(){return r}}),Object.defineProperty(exports,`Y`,{enumerable:!0,get:function(){return t}}),Object.defineProperty(exports,`Z`,{enumerable:!0,get:function(){return i}}),Object.defineProperty(exports,`_`,{enumerable:!0,get:function(){return Q}}),Object.defineProperty(exports,`a`,{enumerable:!0,get:function(){return we}}),Object.defineProperty(exports,`b`,{enumerable:!0,get:function(){return W}}),Object.defineProperty(exports,`c`,{enumerable:!0,get:function(){return K}}),Object.defineProperty(exports,`d`,{enumerable:!0,get:function(){return Ae}}),Object.defineProperty(exports,`et`,{enumerable:!0,get:function(){return l}}),Object.defineProperty(exports,`f`,{enumerable:!0,get:function(){return Z}}),Object.defineProperty(exports,`g`,{enumerable:!0,get:function(){return J}}),Object.defineProperty(exports,`h`,{enumerable:!0,get:function(){return q}}),Object.defineProperty(exports,`i`,{enumerable:!0,get:function(){return Ee}}),Object.defineProperty(exports,`j`,{enumerable:!0,get:function(){return T}}),Object.defineProperty(exports,`k`,{enumerable:!0,get:function(){return k}}),Object.defineProperty(exports,`l`,{enumerable:!0,get:function(){return Oe}}),Object.defineProperty(exports,`m`,{enumerable:!0,get:function(){return ke}}),Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return Te}}),Object.defineProperty(exports,`o`,{enumerable:!0,get:function(){return je}}),Object.defineProperty(exports,`p`,{enumerable:!0,get:function(){return Y}}),Object.defineProperty(exports,`q`,{enumerable:!0,get:function(){return o}}),Object.defineProperty(exports,`r`,{enumerable:!0,get:function(){return Ce}}),Object.defineProperty(exports,`s`,{enumerable:!0,get:function(){return Se}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return X}}),Object.defineProperty(exports,`u`,{enumerable:!0,get:function(){return De}}),Object.defineProperty(exports,`v`,{enumerable:!0,get:function(){return Ne}}),Object.defineProperty(exports,`w`,{enumerable:!0,get:function(){return B}}),Object.defineProperty(exports,`x`,{enumerable:!0,get:function(){return H}}),Object.defineProperty(exports,`y`,{enumerable:!0,get:function(){return ve}}),Object.defineProperty(exports,`z`,{enumerable:!0,get:function(){return y}});
48
- //# sourceMappingURL=ga-datalayer-boRrTCtO.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ga-datalayer-boRrTCtO.cjs","names":[],"sources":["../src/common/analytics-events.ts","../src/common/safe-html.ts","../src/common/events.ts","../src/common/context.ts","../src/common/ui-theme.ts","../src/common/theme-utils.ts","../src/common/global-error-toast.ts","../src/common/debug.ts","../src/common/widget-base.ts","../src/common/ga-datalayer.ts"],"sourcesContent":["import type { AnalyticsInput } from './analytics.js';\n\n// Context shared across all events in a page session\nexport interface AnalyticsContext {\n account_id: string;\n session_id: string;\n correlation_id: string;\n view_id?: string;\n user_id?: string;\n page_type?: string;\n sku?: string;\n ab_test_variant?: string;\n ab_test_experiment_id?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Stream Lifecycle\n// ---------------------------------------------------------------------------\n\nexport function streamStartEvent(\n ctx: AnalyticsContext,\n payload: {\n endpoint: string;\n request_id: string;\n widget?: 'chat' | 'qna' | 'simrel';\n },\n): AnalyticsInput {\n const event: AnalyticsInput = {\n event_name: 'stream.start',\n account_id: ctx.account_id,\n session_id: ctx.session_id,\n correlation_id: ctx.correlation_id,\n payload: {\n endpoint: payload.endpoint,\n request_id: payload.request_id,\n },\n };\n if (ctx.view_id !== undefined) event.view_id = ctx.view_id;\n if (ctx.user_id !== undefined) event.user_id = ctx.user_id;\n if (payload.widget !== undefined) event.widget = payload.widget;\n if (ctx.page_type !== undefined) event.page_type = ctx.page_type;\n if (ctx.sku !== undefined) event.sku = ctx.sku;\n return event;\n}\n\nexport function streamChunkEvent(\n ctx: AnalyticsContext,\n payload: {\n request_id: string;\n chunk_index: number;\n latency_ms?: number;\n widget?: 'chat' | 'qna' | 'simrel';\n },\n): AnalyticsInput {\n const eventPayload: Record<string, unknown> = {\n request_id: payload.request_id,\n chunk_index: payload.chunk_index,\n };\n if (payload.latency_ms !== undefined) eventPayload.latency_ms = payload.latency_ms;\n\n const event: AnalyticsInput = {\n event_name: 'stream.chunk',\n account_id: ctx.account_id,\n session_id: ctx.session_id,\n correlation_id: ctx.correlation_id,\n payload: eventPayload,\n };\n if (ctx.view_id !== undefined) event.view_id = ctx.view_id;\n if (ctx.user_id !== undefined) event.user_id = ctx.user_id;\n if (payload.widget !== undefined) event.widget = payload.widget;\n if (ctx.page_type !== undefined) event.page_type = ctx.page_type;\n if (ctx.sku !== undefined) event.sku = ctx.sku;\n return event;\n}\n\nexport function streamUiSpecEvent(\n ctx: AnalyticsContext,\n payload: {\n request_id: string;\n chunk_index: number;\n component_type: string;\n widget?: 'chat' | 'qna' | 'simrel';\n },\n): AnalyticsInput {\n const event: AnalyticsInput = {\n event_name: 'stream.ui_spec',\n account_id: ctx.account_id,\n session_id: ctx.session_id,\n correlation_id: ctx.correlation_id,\n payload: {\n request_id: payload.request_id,\n chunk_index: payload.chunk_index,\n component_type: payload.component_type,\n },\n };\n if (ctx.view_id !== undefined) event.view_id = ctx.view_id;\n if (ctx.user_id !== undefined) event.user_id = ctx.user_id;\n if (payload.widget !== undefined) event.widget = payload.widget;\n if (ctx.page_type !== undefined) event.page_type = ctx.page_type;\n if (ctx.sku !== undefined) event.sku = ctx.sku;\n return event;\n}\n\nexport function streamDoneEvent(\n ctx: AnalyticsContext,\n payload: {\n request_id: string;\n latency_ms: number;\n chunk_count: number;\n widget?: 'chat' | 'qna' | 'simrel';\n },\n): AnalyticsInput {\n const event: AnalyticsInput = {\n event_name: 'stream.done',\n account_id: ctx.account_id,\n session_id: ctx.session_id,\n correlation_id: ctx.correlation_id,\n payload: {\n request_id: payload.request_id,\n latency_ms: payload.latency_ms,\n chunk_count: payload.chunk_count,\n },\n };\n if (ctx.view_id !== undefined) event.view_id = ctx.view_id;\n if (ctx.user_id !== undefined) event.user_id = ctx.user_id;\n if (payload.widget !== undefined) event.widget = payload.widget;\n if (ctx.page_type !== undefined) event.page_type = ctx.page_type;\n if (ctx.sku !== undefined) event.sku = ctx.sku;\n return event;\n}\n\nexport function streamErrorEvent(\n ctx: AnalyticsContext,\n payload: {\n request_id: string;\n error_code: string;\n error_message: string;\n widget?: 'chat' | 'qna' | 'simrel';\n },\n): AnalyticsInput {\n const event: AnalyticsInput = {\n event_name: 'stream.error',\n account_id: ctx.account_id,\n session_id: ctx.session_id,\n correlation_id: ctx.correlation_id,\n payload: {\n request_id: payload.request_id,\n error_code: payload.error_code,\n error_message: payload.error_message,\n },\n };\n if (ctx.view_id !== undefined) event.view_id = ctx.view_id;\n if (ctx.user_id !== undefined) event.user_id = ctx.user_id;\n if (payload.widget !== undefined) event.widget = payload.widget;\n if (ctx.page_type !== undefined) event.page_type = ctx.page_type;\n if (ctx.sku !== undefined) event.sku = ctx.sku;\n return event;\n}\n\n// ---------------------------------------------------------------------------\n// LLM Usage\n// ---------------------------------------------------------------------------\n\nexport function llmUsageEvent(\n ctx: AnalyticsContext,\n payload: {\n model: string;\n prompt_tokens: number;\n completion_tokens: number;\n total_tokens: number;\n provider?: string;\n },\n): AnalyticsInput {\n const eventPayload: Record<string, unknown> = {\n model: payload.model,\n prompt_tokens: payload.prompt_tokens,\n completion_tokens: payload.completion_tokens,\n total_tokens: payload.total_tokens,\n };\n if (payload.provider !== undefined) eventPayload.provider = payload.provider;\n\n const event: AnalyticsInput = {\n event_name: 'llm.usage',\n account_id: ctx.account_id,\n session_id: ctx.session_id,\n correlation_id: ctx.correlation_id,\n payload: eventPayload,\n };\n if (ctx.view_id !== undefined) event.view_id = ctx.view_id;\n if (ctx.user_id !== undefined) event.user_id = ctx.user_id;\n if (ctx.page_type !== undefined) event.page_type = ctx.page_type;\n if (ctx.sku !== undefined) event.sku = ctx.sku;\n return event;\n}\n\n// ---------------------------------------------------------------------------\n// Metering\n// ---------------------------------------------------------------------------\n\nexport function meteringIncrementEvent(\n ctx: AnalyticsContext,\n payload: {\n meter_key: string;\n quantity: number;\n unit: string;\n },\n): AnalyticsInput {\n const event: AnalyticsInput = {\n event_name: 'metering.increment',\n account_id: ctx.account_id,\n session_id: ctx.session_id,\n correlation_id: ctx.correlation_id,\n payload: {\n meter_key: payload.meter_key,\n quantity: payload.quantity,\n unit: payload.unit,\n },\n };\n if (ctx.view_id !== undefined) event.view_id = ctx.view_id;\n if (ctx.user_id !== undefined) event.user_id = ctx.user_id;\n if (ctx.page_type !== undefined) event.page_type = ctx.page_type;\n if (ctx.sku !== undefined) event.sku = ctx.sku;\n return event;\n}\n\nexport function meteringSummaryEvent(\n ctx: AnalyticsContext,\n payload: {\n meter_key: string;\n quantity: number;\n unit: string;\n },\n): AnalyticsInput {\n const event: AnalyticsInput = {\n event_name: 'metering.summary',\n account_id: ctx.account_id,\n session_id: ctx.session_id,\n correlation_id: ctx.correlation_id,\n payload: {\n meter_key: payload.meter_key,\n quantity: payload.quantity,\n unit: payload.unit,\n },\n };\n if (ctx.view_id !== undefined) event.view_id = ctx.view_id;\n if (ctx.user_id !== undefined) event.user_id = ctx.user_id;\n if (ctx.page_type !== undefined) event.page_type = ctx.page_type;\n if (ctx.sku !== undefined) event.sku = ctx.sku;\n return event;\n}\n\n// ---------------------------------------------------------------------------\n// Chat and Widget Histories\n// ---------------------------------------------------------------------------\n\nexport function chatHistorySnapshotEvent(\n ctx: AnalyticsContext,\n payload: {\n message_count: number;\n history_ref: string;\n redaction_level: string;\n },\n): AnalyticsInput {\n const event: AnalyticsInput = {\n event_name: 'chat.history.snapshot',\n account_id: ctx.account_id,\n session_id: ctx.session_id,\n correlation_id: ctx.correlation_id,\n payload: {\n message_count: payload.message_count,\n history_ref: payload.history_ref,\n redaction_level: payload.redaction_level,\n },\n };\n if (ctx.view_id !== undefined) event.view_id = ctx.view_id;\n if (ctx.user_id !== undefined) event.user_id = ctx.user_id;\n if (ctx.page_type !== undefined) event.page_type = ctx.page_type;\n if (ctx.sku !== undefined) event.sku = ctx.sku;\n return event;\n}\n\nexport function widgetHistorySnapshotEvent(\n ctx: AnalyticsContext,\n payload: {\n message_count: number;\n history_ref: string;\n redaction_level: string;\n widget: 'chat' | 'qna' | 'simrel';\n },\n): AnalyticsInput {\n const event: AnalyticsInput = {\n event_name: 'widget.history.snapshot',\n account_id: ctx.account_id,\n session_id: ctx.session_id,\n correlation_id: ctx.correlation_id,\n widget: payload.widget,\n payload: {\n message_count: payload.message_count,\n history_ref: payload.history_ref,\n redaction_level: payload.redaction_level,\n },\n };\n if (ctx.view_id !== undefined) event.view_id = ctx.view_id;\n if (ctx.user_id !== undefined) event.user_id = ctx.user_id;\n if (ctx.page_type !== undefined) event.page_type = ctx.page_type;\n if (ctx.sku !== undefined) event.sku = ctx.sku;\n return event;\n}\n\n// ---------------------------------------------------------------------------\n// Commerce Attribution\n// ---------------------------------------------------------------------------\n\nexport function basketAddEvent(\n ctx: AnalyticsContext,\n payload: {\n attribution_source: 'chat' | 'qna' | 'simrel';\n attribution_action_id: string;\n cart_value: number;\n currency: string;\n line_items: number;\n sku: string;\n },\n): AnalyticsInput {\n const event: AnalyticsInput = {\n event_name: 'basket.add',\n account_id: ctx.account_id,\n session_id: ctx.session_id,\n correlation_id: ctx.correlation_id,\n widget: payload.attribution_source,\n payload: {\n attribution_source: payload.attribution_source,\n attribution_action_id: payload.attribution_action_id,\n cart_value: payload.cart_value,\n currency: payload.currency,\n line_items: payload.line_items,\n sku: payload.sku,\n },\n };\n if (ctx.view_id !== undefined) event.view_id = ctx.view_id;\n if (ctx.user_id !== undefined) event.user_id = ctx.user_id;\n if (ctx.page_type !== undefined) event.page_type = ctx.page_type;\n if (ctx.sku !== undefined) event.sku = ctx.sku;\n return event;\n}\n\nexport function checkoutStartEvent(\n ctx: AnalyticsContext,\n payload: {\n attribution_source: 'chat' | 'qna' | 'simrel';\n attribution_action_id: string;\n cart_value: number;\n currency: string;\n line_items: number;\n },\n): AnalyticsInput {\n const event: AnalyticsInput = {\n event_name: 'checkout.start',\n account_id: ctx.account_id,\n session_id: ctx.session_id,\n correlation_id: ctx.correlation_id,\n widget: payload.attribution_source,\n payload: {\n attribution_source: payload.attribution_source,\n attribution_action_id: payload.attribution_action_id,\n cart_value: payload.cart_value,\n currency: payload.currency,\n line_items: payload.line_items,\n },\n };\n if (ctx.view_id !== undefined) event.view_id = ctx.view_id;\n if (ctx.user_id !== undefined) event.user_id = ctx.user_id;\n if (ctx.page_type !== undefined) event.page_type = ctx.page_type;\n if (ctx.sku !== undefined) event.sku = ctx.sku;\n return event;\n}\n\nexport function checkoutCompleteEvent(\n ctx: AnalyticsContext,\n payload: {\n attribution_source: 'chat' | 'qna' | 'simrel';\n attribution_action_id: string;\n cart_value: number;\n currency: string;\n line_items: number;\n },\n): AnalyticsInput {\n const event: AnalyticsInput = {\n event_name: 'checkout.complete',\n account_id: ctx.account_id,\n session_id: ctx.session_id,\n correlation_id: ctx.correlation_id,\n widget: payload.attribution_source,\n payload: {\n attribution_source: payload.attribution_source,\n attribution_action_id: payload.attribution_action_id,\n cart_value: payload.cart_value,\n currency: payload.currency,\n line_items: payload.line_items,\n },\n };\n if (ctx.view_id !== undefined) event.view_id = ctx.view_id;\n if (ctx.user_id !== undefined) event.user_id = ctx.user_id;\n if (ctx.page_type !== undefined) event.page_type = ctx.page_type;\n if (ctx.sku !== undefined) event.sku = ctx.sku;\n return event;\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 'template',\n 'noscript',\n]);\n\n/**\n * Attributes allowed per-tag. `'*'` means any allowed tag.\n * The `style` attribute is further sanitized by `sanitizeCssStyle()` to\n * strip dangerous CSS values (url(), expression(), -moz-binding, etc.).\n */\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\n/** CSS properties considered safe in style attributes (layout + typography). */\nconst SAFE_CSS_PROPERTIES = new Set([\n 'color',\n 'background-color',\n 'font-size',\n 'font-weight',\n 'font-style',\n 'font-family',\n 'text-align',\n 'text-decoration',\n 'line-height',\n 'letter-spacing',\n 'margin',\n 'margin-top',\n 'margin-right',\n 'margin-bottom',\n 'margin-left',\n 'padding',\n 'padding-top',\n 'padding-right',\n 'padding-bottom',\n 'padding-left',\n 'border',\n 'border-top',\n 'border-right',\n 'border-bottom',\n 'border-left',\n 'border-radius',\n 'border-color',\n 'border-width',\n 'border-style',\n 'width',\n 'max-width',\n 'min-width',\n 'height',\n 'max-height',\n 'min-height',\n 'display',\n 'vertical-align',\n 'white-space',\n 'word-break',\n 'overflow',\n 'opacity',\n 'visibility',\n 'list-style',\n 'list-style-type',\n 'text-transform',\n 'text-indent',\n 'text-overflow',\n 'box-sizing',\n 'flex',\n 'flex-direction',\n 'flex-wrap',\n 'justify-content',\n 'align-items',\n 'gap',\n]);\n\n/** Patterns indicating dangerous CSS values that could execute code or load external resources. */\nconst DANGEROUS_CSS_VALUE = /url\\s*\\(|expression\\s*\\(|javascript\\s*:|\\bimport\\b|-moz-binding|behavior\\s*:/i;\n\n/**\n * Sanitize a CSS style attribute value.\n * Allowlists safe properties and rejects values containing dangerous patterns.\n * Returns empty string if nothing is safe.\n */\nfunction sanitizeCssStyle(raw: string): string {\n const safe: string[] = [];\n for (const decl of raw.split(';')) {\n const trimmed = decl.trim();\n if (!trimmed) continue;\n const colonIdx = trimmed.indexOf(':');\n if (colonIdx === -1) continue;\n const property = trimmed.slice(0, colonIdx).trim().toLowerCase();\n const value = trimmed.slice(colonIdx + 1).trim();\n if (!SAFE_CSS_PROPERTIES.has(property)) continue;\n if (DANGEROUS_CSS_VALUE.test(value)) continue;\n safe.push(trimmed);\n }\n return safe.join('; ');\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 // Sanitize CSS style values to prevent XSS via url(), expression(), etc.\n if (name === 'style') {\n const sanitized = sanitizeCssStyle(attr.value);\n if (sanitized) {\n el.setAttribute('style', sanitized);\n } else {\n el.removeAttribute('style');\n }\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 */\nconst SAFE_URL_PROTOCOLS = ['http:', 'https:'];\n\n/** Check if a URL uses a safe protocol (http or https). */\nexport function isSafeImageUrl(url: string): boolean {\n try {\n return SAFE_URL_PROTOCOLS.includes(new URL(url).protocol);\n } catch {\n return false;\n }\n}\n\n/**\n * Check if a URL is safe for use in href/src attributes.\n * Allows http:, https:, and relative paths (starting with `/`).\n */\nexport function isSafeUrl(url: string): boolean {\n // Allow relative paths but reject protocol-relative URLs (//evil.com/...)\n if (url.startsWith('/') && !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\n/**\n * Safely set an attribute on an element.\n * For `href` and `src` attributes, validates the URL against safe protocols.\n */\nexport function 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\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","/**\n * Cross-widget event bus utilities.\n *\n * All Gengage widgets communicate through window CustomEvents following\n * the naming convention: gengage:<widget>:<action>\n *\n * This creates a loosely-coupled event bus — widgets don't import each other,\n * host pages can intercept any event, and third-party analytics can hook in.\n */\n\nimport type { GengageEventDetailMap, GengageEventName } from './types.js';\nimport type { ActionPayload } from './types.js';\nimport { isSafeUrl } from './safe-html.js';\n\n/**\n * Dispatch a typed Gengage event on window.\n *\n * @example\n * dispatch('gengage:qna:action', { title: 'About shipping', type: 'query', payload: 'shipping' });\n */\nexport function dispatch<K extends GengageEventName>(name: K, detail: GengageEventDetailMap[K]): void {\n window.dispatchEvent(new CustomEvent(name, { detail, bubbles: false }));\n}\n\n/**\n * Listen for a typed Gengage event on window.\n * Returns an unsubscribe function.\n *\n * @example\n * const off = listen('gengage:qna:action', (detail) => {\n * window.gengage?.chat?.openWithAction(detail);\n * });\n * // Later:\n * off();\n */\nexport function listen<K extends GengageEventName>(\n name: K,\n handler: (detail: GengageEventDetailMap[K]) => void,\n): () => void {\n const listener = (e: Event) => {\n handler((e as CustomEvent<GengageEventDetailMap[K]>).detail);\n };\n window.addEventListener(name, listener);\n return () => window.removeEventListener(name, listener);\n}\n\nexport interface WireQNAToChatOptions {\n onChatUnavailable?: () => void;\n}\n\ninterface WireableChatAPI {\n open?: (options?: { state?: 'full' | 'half'; initialMessage?: string }) => void;\n openWithAction?: (action: ActionPayload) => void;\n sendMessage?: (text: string) => void;\n}\n\nfunction extractFreeTextActionMessage(action: ActionPayload): string | null {\n if (action.type !== 'user_message' && action.type !== 'inputText') return null;\n\n if (typeof action.payload === 'string' && action.payload.trim().length > 0) {\n return action.payload.trim();\n }\n\n if (typeof action.payload === 'object' && action.payload !== null) {\n const payloadObj = action.payload as Record<string, unknown>;\n if (typeof payloadObj.text === 'string') {\n const text = payloadObj.text.trim();\n if (text.length > 0) return text;\n }\n }\n\n if (typeof action.title === 'string' && action.title.trim().length > 0) {\n return action.title.trim();\n }\n\n return null;\n}\n\n/**\n * Convenience: wire QNA → Chat automatically.\n * Call this once after both widgets are initialised.\n *\n * Listens for 'gengage:qna:action' and forwards to window.gengage.chat.openWithAction().\n * Listens for 'gengage:qna:open-chat' and forwards to window.gengage.chat.open().\n *\n * If chat is not available at dispatch time, emits a one-time console.warn and\n * calls options.onChatUnavailable (every time) if provided.\n *\n * @returns unsubscribe function that removes both listeners.\n */\nexport function wireQNAToChat(options?: WireQNAToChatOptions): () => void {\n let warnedOnce = false;\n const pendingActions: ActionPayload[] = [];\n let pendingOpenCount = 0;\n let pollTimer: number | null = null;\n let pollStartedAt = 0;\n const pollIntervalMs = 100;\n const pollTimeoutMs = 5000;\n\n function getChat(): WireableChatAPI | null {\n return (window.gengage?.chat as WireableChatAPI | undefined) ?? null;\n }\n\n function notifyUnavailable(): void {\n if (!warnedOnce) {\n console.warn(\n '[gengage] QNA tried to open chat, but chat widget is not initialized. ' +\n 'Ensure GengageChat is initialized before calling wireQNAToChat().',\n );\n warnedOnce = true;\n }\n options?.onChatUnavailable?.();\n }\n\n function routeActionToChat(chat: WireableChatAPI, action: ActionPayload): void {\n const freeText = extractFreeTextActionMessage(action);\n if (freeText && chat.sendMessage) {\n chat.open?.();\n chat.sendMessage(freeText);\n return;\n }\n chat.openWithAction?.(action);\n }\n\n function clearPollTimer(): void {\n if (pollTimer !== null) {\n window.clearInterval(pollTimer);\n pollTimer = null;\n }\n }\n\n function flushPendingToChat(): boolean {\n const chat = getChat();\n if (!chat) return false;\n\n if (pendingOpenCount > 0) {\n chat.open?.();\n pendingOpenCount = 0;\n }\n\n if (pendingActions.length > 0) {\n const queued = pendingActions.splice(0, pendingActions.length);\n for (const action of queued) {\n routeActionToChat(chat, action);\n }\n }\n\n clearPollTimer();\n return true;\n }\n\n function ensurePollTimer(): void {\n if (pollTimer !== null) return;\n pollStartedAt = Date.now();\n pollTimer = window.setInterval(() => {\n if (flushPendingToChat()) return;\n if (Date.now() - pollStartedAt >= pollTimeoutMs) {\n pendingActions.length = 0;\n pendingOpenCount = 0;\n clearPollTimer();\n }\n }, pollIntervalMs);\n }\n\n const offAction = listen('gengage:qna:action', (action) => {\n const chat = getChat();\n if (chat) {\n routeActionToChat(chat, action);\n return;\n }\n\n notifyUnavailable();\n if (pendingActions.length >= 20) pendingActions.shift();\n pendingActions.push(action);\n ensurePollTimer();\n });\n\n const offOpen = listen('gengage:qna:open-chat', () => {\n const chat = getChat();\n if (chat) {\n chat.open?.();\n return;\n }\n\n notifyUnavailable();\n pendingOpenCount += 1;\n ensurePollTimer();\n });\n\n return () => {\n offAction();\n offOpen();\n pendingActions.length = 0;\n pendingOpenCount = 0;\n clearPollTimer();\n };\n}\n\n/**\n * Convenience: wire Similar Products → Chat for cross-page session continuity.\n * Call this once after both widgets are initialised.\n *\n * When the user navigates to a product page, the chat widget can restore\n * the conversation where it left off using saveSession().\n *\n * @returns unsubscribe function.\n */\nexport function wireSimilarToChat(): () => void {\n return listen('gengage:similar:product-click', ({ sku, url, sessionId }) => {\n if (sessionId) {\n window.gengage?.chat?.saveSession(sessionId, sku);\n }\n if (isSafeUrl(url)) {\n window.location.href = url;\n }\n });\n}\n","/**\n * Page context management.\n *\n * Best practice for passing page context to widgets:\n *\n * ## SSR / Static pages\n * Set window.gengage.pageContext before widget scripts load:\n *\n * <script>\n * window.gengage = {\n * pageContext: {\n * pageType: 'pdp',\n * sku: '{{ product.sku }}',\n * price: '{{ product.price }}',\n * categoryTree: {{ product.categories | json }},\n * }\n * };\n * </script>\n * <script src=\"https://cdn.gengage.ai/widgets/latest/chat.iife.js\"></script>\n *\n * ## CSR / SPA (React, Vue, Next.js, etc.)\n * Call widget.update() after each navigation:\n *\n * router.afterEach((to) => {\n * chatWidget.update({\n * pageType: to.meta.pageType,\n * sku: to.params.sku,\n * });\n * });\n *\n * ## Event-based (loosest coupling)\n * Dispatch 'gengage:context:update' from anywhere:\n *\n * window.dispatchEvent(new CustomEvent('gengage:context:update', {\n * detail: { pageType: 'pdp', sku: '12345' }\n * }));\n */\n\nimport type { PageContext, SessionContext } from './types.js';\n\n// ---------------------------------------------------------------------------\n// Session bootstrap\n// ---------------------------------------------------------------------------\n\n/**\n * Returns the shared session ID for this browser tab session.\n * Creates and persists it on first call.\n *\n * Call this once at page load and share the result with all widget configs:\n *\n * const sessionId = bootstrapSession();\n * chatWidget.init({ ..., session: { sessionId } });\n * qnaWidget.init({ ..., session: { sessionId } });\n */\nexport function bootstrapSession(): string {\n const existing = window.__gengageSessionId ?? sessionStorage.getItem('gengage_session_id') ?? null;\n\n const sessionId = existing ?? crypto.randomUUID();\n\n window.__gengageSessionId = sessionId;\n sessionStorage.setItem('gengage_session_id', sessionId);\n\n if (!window.gengage) window.gengage = {};\n window.gengage.sessionId = sessionId;\n\n return sessionId;\n}\n\n// ---------------------------------------------------------------------------\n// Page context resolution\n// ---------------------------------------------------------------------------\n\n/**\n * Reads the current page context from window.gengage.pageContext.\n * Returns null if not set.\n */\nexport function getWindowPageContext(): PageContext | null {\n return window.gengage?.pageContext ?? null;\n}\n\n/**\n * Merges a partial context update into the current window.gengage.pageContext.\n * Dispatches 'gengage:context:update' so all listening widgets update.\n */\nexport function updatePageContext(patch: Partial<PageContext>): void {\n if (!window.gengage) window.gengage = {};\n window.gengage.pageContext = {\n pageType: 'other',\n ...window.gengage.pageContext,\n ...patch,\n };\n\n window.dispatchEvent(new CustomEvent('gengage:context:update', { detail: patch }));\n}\n\n/**\n * Resolves the session context, bootstrapping if necessary.\n * Merges provided overrides with auto-generated session ID.\n */\nexport function resolveSession(overrides?: Partial<SessionContext>): SessionContext {\n const sessionId = overrides?.sessionId ?? bootstrapSession();\n return {\n sessionId,\n ...overrides,\n };\n}\n","import type { WidgetTheme } from './types.js';\n\n/**\n * Shared SDK-wide visual tokens.\n *\n * Applied to every widget root by default so account customizations only\n * override what they need.\n */\nexport const DEFAULT_WIDGET_THEME_TOKENS: WidgetTheme = {\n '--gengage-chat-offset': '20px',\n '--gengage-chat-launcher-size': '56px',\n '--gengage-chat-width': '400px',\n '--gengage-chat-shell-radius': '1rem' /* lg roundedness */,\n '--gengage-chat-header-height': '72px',\n '--gengage-chat-conversation-width': '396px',\n '--gengage-chat-panel-min-width': '320px',\n '--gengage-chat-panel-max-width': '1200px',\n '--gengage-chat-input-height': '48px',\n\n '--gengage-qna-pill-radius': '999px' /* roundedness-full */,\n '--gengage-qna-input-radius': '0.75rem' /* md roundedness */,\n\n '--gengage-simrel-card-radius': '0.75rem' /* md roundedness */,\n\n '--radius-control': '12px',\n '--radius-card': '16px',\n '--radius-panel': '24px',\n '--radius-pill': '999px',\n '--surface-card-muted': '#f8fafc',\n '--text-secondary': '#4b5563',\n '--text-muted': '#6b7280',\n '--border-default': 'rgba(17, 24, 39, 0.10)',\n};\n\nexport function withDefaultWidgetTheme(theme?: WidgetTheme): WidgetTheme {\n if (!theme) {\n return { ...DEFAULT_WIDGET_THEME_TOKENS };\n }\n return { ...DEFAULT_WIDGET_THEME_TOKENS, ...theme };\n}\n","import type { WidgetTheme } from './types.js';\n\n/**\n * Shared baseline tokens used by account customizations.\n *\n * These values come from historical Gengage host defaults and are\n * intentionally conservative so account themes can override only what differs.\n */\nexport const BASE_WIDGET_THEME: WidgetTheme = {\n /* ── Editorial Commerce Framework ────────────────────────────────────── */\n /* Primary: signature red; never use pure black for text — use on_surface */\n primaryColor: '#b7102a',\n primaryForeground: '#ffffff',\n backgroundColor: '#ffffff' /* surface-card */,\n foregroundColor: '#111827' /* text-primary */,\n borderRadius: '0.75rem' /* md roundedness */,\n fontFamily: '\"Plus Jakarta Sans\", -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif',\n fontSize: '14px',\n zIndex: '1000',\n\n '--glov-chatbot-width': '420px',\n '--glov-left-spacing': '260px',\n '--chatbot-padding': '16px',\n '--root-wrapper-background-color': '#f8f9fa' /* background token */,\n '--root-wrapper-border-color': '#edeeef' /* surface-container */,\n\n '--gengage-chat-width': '400px',\n '--gengage-chat-shell-radius': '1rem' /* lg roundedness */,\n '--gengage-chat-header-height': '72px',\n '--gengage-chat-conversation-width': '396px',\n '--gengage-chat-panel-min-width': '320px',\n '--gengage-chat-panel-max-width': '1200px',\n '--gengage-chat-input-height': '48px',\n '--gengage-qna-pill-radius': '999px' /* roundedness-full */,\n '--gengage-qna-input-radius': '0.75rem' /* md roundedness */,\n '--gengage-simrel-card-radius': '0.75rem' /* md roundedness */,\n\n '--client-primary': '#b7102a',\n '--client-primary-hover': 'color-mix(in srgb, #b7102a 88%, black 12%)',\n '--client-primary-active': 'color-mix(in srgb, #b7102a 78%, black 22%)',\n '--client-primary-subtle': 'color-mix(in srgb, #b7102a 12%, white)',\n '--client-primary-soft': 'color-mix(in srgb, #b7102a 20%, white)',\n '--client-on-primary': '#ffffff',\n '--client-focus-ring': 'color-mix(in srgb, #b7102a 32%, transparent)',\n\n '--surface-page': '#f6f7fb',\n '--surface-shell': '#10131a',\n '--surface-card': '#ffffff',\n '--surface-card-muted': '#f8fafc',\n '--surface-card-soft': '#f8fafc',\n '--surface-elevated': '#ffffff',\n '--surface-input': '#ffffff',\n '--surface-overlay': 'rgba(16, 19, 26, 0.52)',\n\n '--text-primary': '#111827',\n '--text-secondary': '#4b5563',\n '--text-muted': '#6b7280',\n '--text-inverse': '#f9fafb',\n\n '--border-subtle': 'rgba(17, 24, 39, 0.06)',\n '--border-default': 'rgba(17, 24, 39, 0.10)',\n '--border-strong': 'rgba(17, 24, 39, 0.18)',\n\n '--shadow-1': '0 1px 2px rgba(16, 24, 40, 0.04), 0 1px 3px rgba(16, 24, 40, 0.06)',\n '--shadow-2': '0 4px 12px rgba(16, 24, 40, 0.08)',\n '--shadow-3': '0 10px 24px rgba(16, 24, 40, 0.12)',\n\n '--radius-control': '12px',\n '--radius-card': '16px',\n '--radius-panel': '24px',\n '--radius-pill': '999px',\n\n '--success': '#16a34a',\n '--warning': '#d97706',\n '--error': '#dc2626',\n '--info': '#2563eb',\n '--rating': '#f5b301',\n\n '--ai-accent-start': '#0b24d6',\n '--ai-accent-end': '#f768f2',\n '--ai-accent-soft': 'linear-gradient(135deg, rgba(11, 36, 214, 0.08), rgba(247, 104, 242, 0.08))',\n};\n\n/**\n * Merge account overrides on top of the shared base theme.\n *\n * Account customization files should call this helper so shared defaults stay\n * centralized under src/common.\n */\nexport function withBaseTheme(overrides: WidgetTheme): WidgetTheme {\n return { ...BASE_WIDGET_THEME, ...overrides };\n}\n","import type { GengageEventDetailMap } from './types.js';\nimport { listen } from './events.js';\nimport { BASE_WIDGET_THEME } from './theme-utils.js';\n\nconst ROOT_ID = 'gengage-global-toast-root';\nconst STYLE_ID = 'gengage-global-toast-style';\nconst ROOT_VISIBLE_CLASS = 'gengage-global-toast-root--visible';\nconst DEFAULT_DURATION_MS = 4200;\nconst MIN_DURATION_MS = 1500;\nconst MAX_DURATION_MS = 15000;\nconst THEME_SYNC_VARS = [\n '--gengage-font-family',\n '--surface-card',\n '--text-primary',\n '--text-muted',\n '--border-default',\n '--radius-card',\n '--shadow-3',\n '--error',\n '--ds-toast-error-bg',\n '--ds-toast-error-border',\n '--ds-toast-error-accent',\n '--ds-toast-error-fg',\n '--ds-toast-error-shadow',\n] as const;\n\nlet listenerRegistered = false;\nlet dismissTimer: ReturnType<typeof setTimeout> | null = null;\n\nconst CONNECTIVITY_ERROR_PATTERNS = [\n /failed to fetch/i,\n /networkerror/i,\n /network request failed/i,\n /load failed/i,\n /err_network/i,\n /fetch failed/i,\n /network error/i,\n] as const;\n\nfunction isTurkishLocale(locale?: string): boolean {\n return typeof locale === 'string' && locale.toLowerCase().startsWith('tr');\n}\n\nexport function isLikelyConnectivityIssue(error?: unknown): boolean {\n if (typeof navigator !== 'undefined' && navigator.onLine === false) {\n return true;\n }\n\n const message = error instanceof Error ? error.message.trim() : '';\n if (!message) return false;\n\n return CONNECTIVITY_ERROR_PATTERNS.some((pattern) => pattern.test(message));\n}\n\nexport function getGlobalErrorMessage(locale?: string, error?: unknown): string {\n if (isLikelyConnectivityIssue(error)) {\n if (isTurkishLocale(locale)) {\n return 'Bağlantı sorunu oluştu. Lütfen tekrar deneyin.';\n }\n return 'Connection issue. Please try again.';\n }\n\n if (isTurkishLocale(locale)) {\n return 'Bir hata oluştu. Lütfen tekrar deneyin.';\n }\n return 'Something went wrong. Please try again.';\n}\n\nexport function registerGlobalErrorToastListener(): void {\n if (listenerRegistered || typeof window === 'undefined' || typeof document === 'undefined') {\n return;\n }\n\n listenerRegistered = true;\n listen('gengage:global:error', (detail) => {\n showGlobalErrorToast(detail);\n });\n}\n\nexport function showGlobalErrorToast(detail: GengageEventDetailMap['gengage:global:error']): void {\n if (typeof document === 'undefined') return;\n const message = detail.message.trim();\n if (!message) return;\n\n ensureStyles();\n const root = ensureRoot();\n syncRootThemeVars(root);\n root.innerHTML = '';\n\n const toast = document.createElement('section');\n toast.className = 'gengage-global-toast gengage-global-toast--error';\n toast.setAttribute('role', 'status');\n toast.setAttribute('aria-live', 'polite');\n\n const title = document.createElement('div');\n title.className = 'gengage-global-toast-title';\n title.textContent = sourceTitle(detail.source);\n\n const body = document.createElement('div');\n body.className = 'gengage-global-toast-message';\n body.textContent = message;\n\n toast.appendChild(title);\n toast.appendChild(body);\n root.appendChild(toast);\n root.classList.add(ROOT_VISIBLE_CLASS);\n\n if (dismissTimer) {\n clearTimeout(dismissTimer);\n dismissTimer = null;\n }\n\n if (detail.sticky === true) {\n return;\n }\n\n dismissTimer = setTimeout(() => {\n dismissGlobalErrorToast();\n }, clampDuration(detail.durationMs));\n}\n\nexport function dismissGlobalErrorToast(): void {\n if (typeof document === 'undefined') return;\n const root = document.getElementById(ROOT_ID);\n if (!root) return;\n\n root.classList.remove(ROOT_VISIBLE_CLASS);\n root.innerHTML = '';\n\n if (dismissTimer) {\n clearTimeout(dismissTimer);\n dismissTimer = null;\n }\n}\n\nfunction sourceTitle(source: GengageEventDetailMap['gengage:global:error']['source']): string {\n switch (source) {\n case 'chat':\n return 'Chat warning';\n case 'qna':\n return 'QnA warning';\n case 'simrel':\n return 'Widget warning';\n default:\n return 'Connection warning';\n }\n}\n\nfunction ensureRoot(): HTMLElement {\n const existing = document.getElementById(ROOT_ID);\n if (existing instanceof HTMLElement) return existing;\n\n const root = document.createElement('div');\n root.id = ROOT_ID;\n root.className = 'gengage-global-toast-root';\n document.body.appendChild(root);\n return root;\n}\n\nfunction syncRootThemeVars(root: HTMLElement): void {\n if (typeof document === 'undefined' || typeof window === 'undefined') return;\n const source = document.querySelector<HTMLElement>(\n '.gengage-chat-root, .gengage-qna-container, .gengage-simrel-container, .gengage-simbut-root',\n );\n if (!source) return;\n const computed = window.getComputedStyle(source);\n for (const name of THEME_SYNC_VARS) {\n const value = computed.getPropertyValue(name).trim();\n if (value) {\n root.style.setProperty(name, value);\n } else {\n root.style.removeProperty(name);\n }\n }\n}\n\nfunction clampDuration(durationMs?: number): number {\n if (typeof durationMs !== 'number' || !Number.isFinite(durationMs)) {\n return DEFAULT_DURATION_MS;\n }\n return Math.min(MAX_DURATION_MS, Math.max(MIN_DURATION_MS, Math.round(durationMs)));\n}\n\nfunction ensureStyles(): void {\n if (document.getElementById(STYLE_ID)) return;\n\n const style = document.createElement('style');\n style.id = STYLE_ID;\n const surfaceCard = BASE_WIDGET_THEME['--surface-card'] ?? BASE_WIDGET_THEME.backgroundColor ?? '#ffffff';\n const textPrimary = BASE_WIDGET_THEME['--text-primary'] ?? BASE_WIDGET_THEME.foregroundColor ?? '#111827';\n const borderDefault = BASE_WIDGET_THEME['--border-default'] ?? 'rgba(17, 24, 39, 0.10)';\n const error = BASE_WIDGET_THEME['--error'] ?? '#dc2626';\n const shadow3 = BASE_WIDGET_THEME['--shadow-3'] ?? '0 10px 24px rgba(16, 24, 40, 0.12)';\n const radiusCard = BASE_WIDGET_THEME['--radius-card'] ?? '16px';\n const textMuted = BASE_WIDGET_THEME['--text-muted'] ?? '#6b7280';\n style.textContent = `\n#${ROOT_ID} {\n position: fixed;\n top: 16px;\n right: 16px;\n z-index: 2147483646;\n pointer-events: none;\n}\n#${ROOT_ID}.${ROOT_VISIBLE_CLASS} {\n pointer-events: auto;\n}\n#${ROOT_ID} .gengage-global-toast {\n min-width: 260px;\n max-width: min(92vw, 420px);\n border-radius: var(--radius-card, ${radiusCard});\n border: 1px solid var(--ds-toast-error-border, color-mix(in srgb, var(--error, ${error}) 18%, var(--border-default, ${borderDefault})));\n border-left: 4px solid var(--ds-toast-error-accent, var(--error, ${error}));\n background: var(--ds-toast-error-bg, color-mix(in srgb, var(--error, ${error}) 5%, var(--surface-card, ${surfaceCard})));\n color: var(--ds-toast-error-fg, color-mix(in srgb, var(--error, ${error}) 22%, var(--text-primary, ${textPrimary})));\n box-shadow: var(--ds-toast-error-shadow, var(--shadow-3, ${shadow3}));\n padding: 10px 12px;\n font-family: var(--gengage-font-family, ${JSON.stringify(BASE_WIDGET_THEME.fontFamily ?? '-apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif')});\n font-size: 13px;\n line-height: 1.4;\n animation: gengage-global-toast-in 180ms ease-out forwards;\n}\n#${ROOT_ID} .gengage-global-toast-title {\n margin: 0 0 4px;\n font-size: 12px;\n font-weight: 700;\n color: var(--text-muted, ${textMuted});\n}\n#${ROOT_ID} .gengage-global-toast-message {\n margin: 0;\n font-weight: 500;\n}\n@keyframes gengage-global-toast-in {\n from {\n opacity: 0;\n transform: translateY(-8px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n`;\n document.head.appendChild(style);\n}\n","/**\n * Debug logging for integrators.\n *\n * Enable with: `localStorage.setItem('gengage:debug', '1')`\n * Disable with: `localStorage.removeItem('gengage:debug')`\n *\n * When disabled, all debug calls are no-ops with zero overhead\n * (the check is a single localStorage read cached per page load).\n */\n\nlet _enabled: boolean | null = null;\n\nfunction isEnabled(): boolean {\n if (_enabled !== null) return _enabled;\n try {\n _enabled = localStorage.getItem('gengage:debug') === '1';\n } catch {\n _enabled = false;\n }\n return _enabled;\n}\n\n/** Log a debug message (only when gengage:debug is enabled). */\nexport function debugLog(category: string, message: string, data?: unknown): void {\n if (!isEnabled()) return;\n const args: unknown[] = [`[gengage:${category}]`, message];\n if (data !== undefined) args.push(data);\n // eslint-disable-next-line no-console -- debug utility, gated by localStorage flag\n console.debug(...args);\n}\n\n/** Reset the cached enabled state (for testing). */\nexport function _resetDebugCache(): void {\n _enabled = null;\n}\n","/**\n * Abstract base class for all Gengage widgets.\n *\n * Provides:\n * - Lifecycle management (init → update → show/hide → destroy)\n * - Typed event emitter\n * - Theme application via CSS custom properties\n * - SPA context-update listener (gengage:context:update)\n * - Mount target resolution (selector string or HTMLElement)\n *\n * Subclasses must implement:\n * - protected onInit(config): Promise<void>\n * - protected onUpdate(context): void\n * - protected onShow(): void\n * - protected onHide(): void\n * - protected onDestroy(): void\n */\n\nimport type { BaseWidgetConfig, GengageWidget, PageContext, WidgetTheme } from './types.js';\nimport type { AnalyticsInput } from './analytics.js';\nimport type { AnalyticsContext } from './analytics-events.js';\nimport { checkoutStartEvent, checkoutCompleteEvent, meteringSummaryEvent } from './analytics-events.js';\nimport { listen } from './events.js';\nimport { resolveSession } from './context.js';\nimport { withDefaultWidgetTheme } from './ui-theme.js';\nimport { registerGlobalErrorToastListener } from './global-error-toast.js';\nimport { debugLog } from './debug.js';\n\ntype AnyHandler = (...args: unknown[]) => void;\n\nexport abstract class BaseWidget<\n TConfig extends BaseWidgetConfig = BaseWidgetConfig,\n> implements GengageWidget<TConfig> {\n protected config!: TConfig;\n protected root!: HTMLElement;\n protected isVisible = false;\n protected isInitialised = false;\n\n private readonly _handlers = new Map<string, Set<AnyHandler>>();\n private readonly _cleanups: Array<() => void> = [];\n private _ownsRoot = false;\n private _destroying = false;\n\n // ---------------------------------------------------------------------------\n // Public API\n // ---------------------------------------------------------------------------\n\n async init(config: TConfig): Promise<void> {\n if (this.isInitialised) {\n console.warn('[gengage] Widget already initialised. Call update() instead.');\n return;\n }\n\n const mergedTheme = withDefaultWidgetTheme(config.theme);\n\n this.config = {\n ...config,\n theme: mergedTheme,\n session: resolveSession(config.session),\n };\n\n this.root = this._resolveMount(config.mountTarget);\n this._applyTheme(mergedTheme);\n registerGlobalErrorToastListener();\n\n // Listen for context updates dispatched by the host page\n const off = listen('gengage:context:update', (patch) => this.update(patch));\n this._cleanups.push(off);\n\n debugLog('lifecycle', `${this.constructor.name}.init`, {\n accountId: config.accountId,\n sku: config.pageContext?.sku,\n });\n\n try {\n await this.onInit(this.config);\n } catch (err) {\n this.destroy();\n throw err;\n }\n if (this._destroying) return;\n this.isInitialised = true;\n debugLog('lifecycle', `${this.constructor.name} ready`);\n this.emit('ready');\n }\n\n update(context: Partial<PageContext>): void {\n if (!this.isInitialised) return;\n if (this.config.pageContext) {\n this.config = {\n ...this.config,\n pageContext: { ...this.config.pageContext, ...context },\n };\n } else if (context.pageType !== undefined) {\n // Only create a new pageContext when pageType is present (required field)\n this.config = { ...this.config, pageContext: context as PageContext };\n }\n this.onUpdate(context);\n this.emit('context-update', this.config.pageContext);\n }\n\n show(): void {\n if (this.isVisible) return;\n this.isVisible = true;\n this.root.style.display = '';\n this.onShow();\n this.emit('show');\n }\n\n hide(): void {\n if (!this.isVisible) return;\n this.isVisible = false;\n this.root.style.display = 'none';\n this.onHide();\n this.emit('hide');\n }\n\n destroy(): void {\n if (this._destroying) return;\n this._destroying = true;\n this.emit('destroy');\n this._cleanups.forEach((fn) => fn());\n this._cleanups.length = 0;\n this._handlers.clear();\n this.onDestroy();\n this.config.analyticsClient?.destroy();\n if (this._ownsRoot) {\n this.root.remove();\n } else {\n this.root.innerHTML = '';\n }\n this.isInitialised = false;\n }\n\n on(event: string, handler: AnyHandler): () => void {\n if (!this._handlers.has(event)) this._handlers.set(event, new Set());\n this._handlers.get(event)!.add(handler);\n return () => this._handlers.get(event)?.delete(handler);\n }\n\n /** Track a checkout start event. Called by host page to attribute checkout to widget interaction. */\n trackCheckout(\n type: 'start' | 'complete',\n data: {\n attribution_source: 'chat' | 'qna' | 'simrel';\n attribution_action_id: string;\n cart_value: number;\n currency: string;\n line_items: number;\n },\n ): void {\n const builder = type === 'start' ? checkoutStartEvent : checkoutCompleteEvent;\n this.track(builder(this.analyticsContext(), data));\n }\n\n /** Track a metering summary event. Called by host page for session-level aggregation. */\n flushMeteringSummary(data: { meter_key: string; quantity: number; unit: string }): void {\n this.track(meteringSummaryEvent(this.analyticsContext(), data));\n }\n\n // ---------------------------------------------------------------------------\n // Protected — subclasses implement these\n // ---------------------------------------------------------------------------\n\n protected abstract onInit(config: TConfig): Promise<void>;\n protected abstract onUpdate(context: Partial<PageContext>): void;\n protected abstract onShow(): void;\n protected abstract onHide(): void;\n protected abstract onDestroy(): void;\n\n // ---------------------------------------------------------------------------\n // Protected helpers\n // ---------------------------------------------------------------------------\n\n /** Emit a widget event to all registered handlers. */\n protected emit(event: string, ...args: unknown[]): void {\n this._handlers.get(event)?.forEach((h) => h(...args));\n }\n\n /** Register a cleanup function to run on destroy(). */\n protected addCleanup(fn: () => void): void {\n this._cleanups.push(fn);\n }\n\n /** Track an analytics event (no-op if analyticsClient is not configured). */\n protected track(input: AnalyticsInput): void {\n this.config.analyticsClient?.track(input);\n }\n\n /** Build the shared analytics context from widget config. */\n protected analyticsContext(): AnalyticsContext {\n const ctx: AnalyticsContext = {\n account_id: this.config.accountId,\n session_id: this.config.session?.sessionId ?? '',\n correlation_id: this.config.session?.sessionId ?? '',\n };\n if (this.config.session?.viewId !== undefined) ctx.view_id = this.config.session.viewId;\n if (this.config.session?.userId !== undefined) ctx.user_id = this.config.session.userId;\n if (this.config.pageContext?.pageType !== undefined) ctx.page_type = this.config.pageContext.pageType;\n if (this.config.pageContext?.sku !== undefined) ctx.sku = this.config.pageContext.sku;\n if (this.config.session?.abTestVariant !== undefined) ctx.ab_test_variant = this.config.session.abTestVariant;\n if (this.config.session?.abTestExperimentId !== undefined)\n ctx.ab_test_experiment_id = this.config.session.abTestExperimentId;\n return ctx;\n }\n\n // ---------------------------------------------------------------------------\n // Private helpers\n // ---------------------------------------------------------------------------\n\n private _resolveMount(target?: HTMLElement | string): HTMLElement {\n if (target instanceof HTMLElement) return target;\n if (typeof target === 'string') {\n const el = document.querySelector<HTMLElement>(target);\n if (!el) throw new Error(`[gengage] Mount target not found: \"${target}\"`);\n return el;\n }\n // Default: create a div prepended to body so the widget's launcher appears\n // near the start of the tab order rather than being buried at the very end\n // (which would force keyboard-only users to tab through the entire page).\n const div = document.createElement('div');\n div.dataset['gengageWidget'] = this.constructor.name.toLowerCase();\n document.body.insertBefore(div, document.body.firstChild);\n this._ownsRoot = true;\n return div;\n }\n\n private _applyTheme(theme?: WidgetTheme): void {\n if (!theme) return;\n for (const [key, value] of Object.entries(theme)) {\n if (value !== undefined) {\n const prop = key.startsWith('--') ? key : `--gengage-${toKebab(key)}`;\n this.root.style.setProperty(prop, value);\n }\n }\n }\n}\n\nfunction toKebab(str: string): string {\n return str.replace(/([A-Z])/g, '-$1').toLowerCase();\n}\n\n// ---------------------------------------------------------------------------\n// Chat widget public API (exposed on window.gengage.chat)\n// ---------------------------------------------------------------------------\n\nexport interface ChatPublicAPI {\n open(options?: { state?: 'full' | 'half'; initialMessage?: string }): void;\n openWithAction(action: import('./types.js').ActionPayload, options?: { sku?: string; state?: 'full' | 'half' }): void;\n /** Send a user message programmatically (same as typing + submit). */\n sendMessage(text: string): void;\n /** Send a backend action programmatically. */\n sendAction(action: import('./types.js').ActionPayload, options?: { silent?: boolean }): void;\n close(): void;\n saveSession(sessionId: string, sku: string): void;\n readonly isOpen: boolean;\n on(\n event: 'open' | 'close' | 'ready' | 'message' | 'error' | 'context-update' | 'destroy',\n handler: (...args: unknown[]) => void,\n ): () => void;\n trackCheckout(\n type: 'start' | 'complete',\n data: {\n attribution_source: 'chat' | 'qna' | 'simrel';\n attribution_action_id: string;\n cart_value: number;\n currency: string;\n line_items: number;\n },\n ): void;\n flushMeteringSummary(data: { meter_key: string; quantity: number; unit: string }): void;\n /**\n * Register a callback for a GA4 event name.\n * When the widget fires that event, the callback is invoked with the event detail.\n * Callbacks that return `false` or throw signal failure — the widget reacts accordingly\n * (e.g. showing an error message for add-to-cart failures).\n *\n * @returns unsubscribe function\n */\n addCallback(eventName: string, callback: (detail: Record<string, unknown>) => boolean | Promise<boolean>): () => void;\n}\n","/**\n * Google Analytics dataLayer integration.\n *\n * Pushes chat activity events to `window.dataLayer` when GA is available.\n * Falls back to `console.debug` when GA is not detected (useful for debugging).\n *\n * Event naming follows the GA4 recommended event pattern:\n * - All lowercase, hyphen-separated\n * - Prefixed with `gengage-` for easy filtering in GA dashboards\n *\n * Clients can build custom chat funnels in GA using these events.\n */\n\n// ---------------------------------------------------------------------------\n// GA dataLayer type augmentation\n// ---------------------------------------------------------------------------\n\ninterface DataLayerEvent {\n event: string;\n [key: string]: unknown;\n}\n\ndeclare global {\n interface Window {\n dataLayer?: DataLayerEvent[];\n }\n}\n\n// ---------------------------------------------------------------------------\n// GA detection\n// ---------------------------------------------------------------------------\n\nfunction isGAAvailable(): boolean {\n return typeof window !== 'undefined' && Array.isArray(window.dataLayer);\n}\n\n// ---------------------------------------------------------------------------\n// Core push function\n// ---------------------------------------------------------------------------\n\nfunction pushEvent(eventName: string, params?: Record<string, unknown>): void {\n const payload: DataLayerEvent = {\n event: eventName,\n ...params,\n };\n\n if (isGAAvailable()) {\n window.dataLayer!.push(payload);\n }\n // No fallback log — GA events are silently dropped when dataLayer is absent.\n}\n\n// ---------------------------------------------------------------------------\n// Typed event emitters\n// ---------------------------------------------------------------------------\n\n/** Widget icon/avatar displayed on page. */\nexport function trackInit(widget: string): void {\n pushEvent('gengage-on-init', { gengage_widget: widget });\n}\n\n/** Widget opened / shown to user. */\nexport function trackShow(widget: string): void {\n pushEvent('gengage-show', { gengage_widget: widget });\n}\n\n/** Widget closed / hidden. */\nexport function trackHide(widget: string): void {\n pushEvent('gengage-hide', { gengage_widget: widget });\n}\n\n/** User clicked a suggested question / action button. */\nexport function trackSuggestedQuestion(title: string, type: string): void {\n pushEvent('gengage-suggested-question', {\n gengage_question_title: title,\n gengage_action_type: type,\n });\n}\n\n/** User clicked \"Find Similar\" for a product. */\nexport function trackFindSimilars(sku: string): void {\n pushEvent('gengage-find-similars', { gengage_sku: sku });\n}\n\n/** User pre-selected a product for comparison. */\nexport function trackComparePreselection(sku: string): void {\n pushEvent('gengage-compare-preselection', { gengage_sku: sku });\n}\n\n/** User submitted the comparison (clicked \"Compare Selected\"). */\nexport function trackCompareSelected(skus: string[]): void {\n pushEvent('gengage-compare-selected', {\n gengage_skus: skus,\n gengage_product_count: skus.length,\n });\n}\n\n/** User cleared the comparison selection. */\nexport function trackCompareClear(): void {\n pushEvent('gengage-compare-clear');\n}\n\n/** Comparison results received and rendered. */\nexport function trackCompareReceived(productCount: number): void {\n pushEvent('gengage-compare-received', {\n gengage_product_count: productCount,\n });\n}\n\n/** User liked / favorited a product. */\nexport function trackLikeProduct(sku: string): void {\n pushEvent('gengage-like-product', { gengage_sku: sku });\n}\n\n/** User clicked the favorites/likes list button. */\nexport function trackLikeList(): void {\n pushEvent('gengage-like-list');\n}\n\n/** Product list / search results displayed. */\nexport function trackSearch(query?: string, resultCount?: number): void {\n pushEvent('gengage-search', {\n gengage_search_query: query,\n gengage_result_count: resultCount,\n });\n}\n\n/** User clicked on a product to view details. */\nexport function trackProductDetail(sku: string, name?: string): void {\n pushEvent('gengage-product-detail', {\n gengage_sku: sku,\n gengage_product_name: name,\n });\n}\n\n/** User added a product to cart from the widget. */\nexport function trackCartAdd(sku: string, quantity: number): void {\n pushEvent('gengage-cart-add', {\n gengage_sku: sku,\n gengage_quantity: quantity,\n });\n}\n\n/** User sent a chat message. */\nexport function trackMessageSent(): void {\n pushEvent('gengage-message-sent');\n}\n\n/** Assistant responded with text. */\nexport function trackMessageReceived(): void {\n pushEvent('gengage-message-received');\n}\n\n/** User started a new conversation. */\nexport function trackConversationStart(): void {\n pushEvent('gengage-conversation-start');\n}\n\n/** User used voice input. */\nexport function trackVoiceInput(): void {\n pushEvent('gengage-voice-input');\n}\n\n/** Widget or stream error occurred. */\nexport function trackError(widget: string, error: string): void {\n pushEvent('gengage-error', { gengage_widget: widget, gengage_error: error });\n}\n\n// ---------------------------------------------------------------------------\n// Batch wire-up: connect to the Gengage event bus\n// ---------------------------------------------------------------------------\n\n/**\n * Wire GA dataLayer tracking to the Gengage event bus.\n * Call once after widgets are initialized.\n *\n * @returns unsubscribe function that removes all listeners.\n */\nlet _gaWiredUnsub: (() => void) | null = null;\n\nexport function wireGADataLayer(): () => void {\n if (typeof window === 'undefined') return () => {};\n // Idempotency guard: return existing unsubscribe if already wired\n if (_gaWiredUnsub) return _gaWiredUnsub;\n\n const listeners: Array<() => void> = [];\n\n function on<T>(eventName: string, handler: (detail: T) => void): void {\n const listener = (e: Event) => handler((e as CustomEvent<T>).detail);\n window.addEventListener(eventName, listener);\n listeners.push(() => window.removeEventListener(eventName, listener));\n }\n\n // Chat lifecycle\n on<{ state?: string }>('gengage:chat:open', () => trackShow('chat'));\n on<Record<string, never>>('gengage:chat:close', () => trackHide('chat'));\n on<Record<string, never>>('gengage:chat:ready', () => trackInit('chat'));\n\n // Add to cart (from similar products widget — chat handles GA4 directly)\n on<{ sku: string; quantity: number; cartCode: string }>('gengage:similar:add-to-cart', ({ sku, quantity }) => {\n trackCartAdd(sku, quantity);\n });\n\n // Product click from similar products\n on<{ sku: string; url: string }>('gengage:similar:product-click', ({ sku }) => {\n trackProductDetail(sku);\n });\n\n // QNA action (suggested question click)\n on<{ title: string; type: string }>('gengage:qna:action', ({ title, type }) => {\n trackSuggestedQuestion(title, type);\n });\n\n // Voice input\n on<{ payload: unknown }>('gengage:chat:voice', () => trackVoiceInput());\n\n // QNA open chat\n on<Record<string, never>>('gengage:qna:open-chat', () => trackShow('chat'));\n\n // Error tracking\n on<{ source: string; message: string }>('gengage:global:error', ({ source, message }) => {\n trackError(source, message);\n });\n\n _gaWiredUnsub = () => {\n for (const unsub of listeners) unsub();\n listeners.length = 0;\n _gaWiredUnsub = null;\n };\n return _gaWiredUnsub;\n}\n"],"mappings":"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"}