@gengage/assistant-fe 0.1.7 → 0.1.9

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 (134) hide show
  1. package/README.md +80 -282
  2. package/dist/assistant-fe.css +1 -1
  3. package/dist/chat/api.d.ts +1 -12
  4. package/dist/chat/api.d.ts.map +1 -1
  5. package/dist/chat/components/ChatDrawer.d.ts +15 -1
  6. package/dist/chat/components/ChatDrawer.d.ts.map +1 -1
  7. package/dist/chat/components/ChoicePrompter.d.ts +1 -0
  8. package/dist/chat/components/ChoicePrompter.d.ts.map +1 -1
  9. package/dist/chat/components/ComparisonTable.d.ts +5 -3
  10. package/dist/chat/components/ComparisonTable.d.ts.map +1 -1
  11. package/dist/chat/components/PanelTopBar.d.ts +2 -0
  12. package/dist/chat/components/PanelTopBar.d.ts.map +1 -1
  13. package/dist/chat/components/ProductSummaryCard.d.ts.map +1 -1
  14. package/dist/chat/components/ReviewHighlights.d.ts +3 -0
  15. package/dist/chat/components/ReviewHighlights.d.ts.map +1 -1
  16. package/dist/chat/components/renderUISpec.d.ts +0 -5
  17. package/dist/chat/components/renderUISpec.d.ts.map +1 -1
  18. package/dist/chat/index.d.ts +18 -9
  19. package/dist/chat/index.d.ts.map +1 -1
  20. package/dist/chat/locales/en.d.ts.map +1 -1
  21. package/dist/chat/locales/tr.d.ts.map +1 -1
  22. package/dist/chat/session-persistence.d.ts +3 -0
  23. package/dist/chat/session-persistence.d.ts.map +1 -1
  24. package/dist/chat/types.d.ts +23 -25
  25. package/dist/chat/types.d.ts.map +1 -1
  26. package/dist/chat.cjs +1 -1
  27. package/dist/chat.iife.js +24 -24
  28. package/dist/chat.iife.js.map +1 -1
  29. package/dist/chat.js +8 -9
  30. package/dist/chat.js.map +1 -1
  31. package/dist/common/action-router.d.ts.map +1 -1
  32. package/dist/common/activity-tracker.d.ts +1 -1
  33. package/dist/common/analytics.d.ts +12 -8
  34. package/dist/common/analytics.d.ts.map +1 -1
  35. package/dist/common/api-paths.d.ts +2 -5
  36. package/dist/common/api-paths.d.ts.map +1 -1
  37. package/dist/common/config-schema.d.ts.map +1 -1
  38. package/dist/common/debug.d.ts +14 -0
  39. package/dist/common/debug.d.ts.map +1 -0
  40. package/dist/common/events.d.ts.map +1 -1
  41. package/dist/common/index.d.ts +2 -2
  42. package/dist/common/index.d.ts.map +1 -1
  43. package/dist/common/overlay.d.ts +19 -0
  44. package/dist/common/overlay.d.ts.map +1 -1
  45. package/dist/common/{v1-protocol-adapter.d.ts → protocol-adapter.d.ts} +2 -2
  46. package/dist/common/protocol-adapter.d.ts.map +1 -0
  47. package/dist/common/quantity-stepper.d.ts +10 -10
  48. package/dist/common/quantity-stepper.d.ts.map +1 -1
  49. package/dist/common/safe-html.d.ts.map +1 -1
  50. package/dist/common/streaming.d.ts.map +1 -1
  51. package/dist/common/tts-player.d.ts +2 -0
  52. package/dist/common/tts-player.d.ts.map +1 -1
  53. package/dist/common/types.d.ts +1 -1
  54. package/dist/common/voice-input.d.ts +1 -0
  55. package/dist/common/voice-input.d.ts.map +1 -1
  56. package/dist/common/widget-base.d.ts.map +1 -1
  57. package/dist/common.cjs +1 -1
  58. package/dist/common.cjs.map +1 -1
  59. package/dist/common.js +173 -172
  60. package/dist/common.js.map +1 -1
  61. package/dist/index-BWPx4pM7.cjs +13 -0
  62. package/dist/index-BWPx4pM7.cjs.map +1 -0
  63. package/dist/index-CEt87kCd.js +4463 -0
  64. package/dist/index-CEt87kCd.js.map +1 -0
  65. package/dist/index-DL4CAkyL.cjs +2 -0
  66. package/dist/index-DL4CAkyL.cjs.map +1 -0
  67. package/dist/{index-BH-V2lWn.js → index-DR2uepzb.js} +108 -106
  68. package/dist/index-DR2uepzb.js.map +1 -0
  69. package/dist/index.cjs +1 -1
  70. package/dist/index.js +16 -16
  71. package/dist/native.cjs +1 -1
  72. package/dist/native.iife.js +18 -18
  73. package/dist/native.iife.js.map +1 -1
  74. package/dist/native.js +1 -1
  75. package/dist/qna/index.d.ts +19 -0
  76. package/dist/qna/index.d.ts.map +1 -1
  77. package/dist/qna/types.d.ts +2 -2
  78. package/dist/qna/types.d.ts.map +1 -1
  79. package/dist/qna.cjs +1 -1
  80. package/dist/qna.cjs.map +1 -1
  81. package/dist/qna.css +1 -1
  82. package/dist/qna.iife.js +7 -7
  83. package/dist/qna.iife.js.map +1 -1
  84. package/dist/qna.js +14 -14
  85. package/dist/qna.js.map +1 -1
  86. package/dist/quantity-stepper-C-nV4lwi.js +77 -0
  87. package/dist/quantity-stepper-C-nV4lwi.js.map +1 -0
  88. package/dist/quantity-stepper-CURMkwRF.cjs +2 -0
  89. package/dist/quantity-stepper-CURMkwRF.cjs.map +1 -0
  90. package/dist/{schemas-yF4IOEUi.js → schemas-DIhL3DkL.js} +1166 -947
  91. package/dist/schemas-DIhL3DkL.js.map +1 -0
  92. package/dist/schemas-Dsr0bbO_.cjs +86 -0
  93. package/dist/schemas-Dsr0bbO_.cjs.map +1 -0
  94. package/dist/simrel/api.d.ts +1 -1
  95. package/dist/simrel/api.d.ts.map +1 -1
  96. package/dist/simrel/components/GroupTabs.d.ts +1 -1
  97. package/dist/simrel/components/GroupTabs.d.ts.map +1 -1
  98. package/dist/simrel/components/ProductCard.d.ts +1 -1
  99. package/dist/simrel/components/ProductCard.d.ts.map +1 -1
  100. package/dist/simrel/components/ProductGrid.d.ts +1 -1
  101. package/dist/simrel/components/ProductGrid.d.ts.map +1 -1
  102. package/dist/simrel/index.d.ts +20 -1
  103. package/dist/simrel/index.d.ts.map +1 -1
  104. package/dist/simrel/locales/en.d.ts.map +1 -1
  105. package/dist/simrel/locales/tr.d.ts.map +1 -1
  106. package/dist/simrel/types.d.ts +1 -0
  107. package/dist/simrel/types.d.ts.map +1 -1
  108. package/dist/simrel.cjs +1 -1
  109. package/dist/simrel.cjs.map +1 -1
  110. package/dist/simrel.css +1 -1
  111. package/dist/simrel.iife.js +11 -11
  112. package/dist/simrel.iife.js.map +1 -1
  113. package/dist/simrel.js +123 -111
  114. package/dist/simrel.js.map +1 -1
  115. package/package.json +1 -1
  116. package/dist/chat/components/ProactivePopup.d.ts +0 -20
  117. package/dist/chat/components/ProactivePopup.d.ts.map +0 -1
  118. package/dist/chat/heartbeat.d.ts +0 -71
  119. package/dist/chat/heartbeat.d.ts.map +0 -1
  120. package/dist/common/v1-protocol-adapter.d.ts.map +0 -1
  121. package/dist/index-1yPxOqAw.cjs +0 -13
  122. package/dist/index-1yPxOqAw.cjs.map +0 -1
  123. package/dist/index-BH-V2lWn.js.map +0 -1
  124. package/dist/index-BelS6Vnv.cjs +0 -2
  125. package/dist/index-BelS6Vnv.cjs.map +0 -1
  126. package/dist/index-CERWfDdF.js +0 -4571
  127. package/dist/index-CERWfDdF.js.map +0 -1
  128. package/dist/quantity-stepper-B8kX8GbN.js +0 -209
  129. package/dist/quantity-stepper-B8kX8GbN.js.map +0 -1
  130. package/dist/quantity-stepper-UbAp53Ow.cjs +0 -2
  131. package/dist/quantity-stepper-UbAp53Ow.cjs.map +0 -1
  132. package/dist/schemas-DHzfUzwA.cjs +0 -86
  133. package/dist/schemas-DHzfUzwA.cjs.map +0 -1
  134. package/dist/schemas-yF4IOEUi.js.map +0 -1
package/README.md CHANGED
@@ -1,354 +1,155 @@
1
- # gengage-assistant-fe
1
+ # Gengage AI Assistant — Frontend SDK
2
2
 
3
- Source-available frontend widgets for the **Gengage AI Assistant** — embeddable chat,
4
- contextual Q&A buttons, and a similar-products grid.
3
+ [![npm](https://img.shields.io/npm/v/@gengage/assistant-fe)](https://www.npmjs.com/package/@gengage/assistant-fe)
4
+ [![tests](https://img.shields.io/badge/tests-1056%20passing-brightgreen)]()
5
+ [![license](https://img.shields.io/badge/license-source--available-blue)](LICENSE)
5
6
 
6
- > **Note:** This repo contains UI and client-side logic only.
7
- > Backend services are proprietary and require a [gengage.ai](https://gengage.ai) subscription.
8
- > Use/deployment is intended for Registered Gengage customers connecting to their Gengage backend.
7
+ Embeddable AI shopping assistant widgets for e-commerce — **chat**, **contextual Q&A**, and **similar products** — built with vanilla TypeScript, zero framework dependencies.
9
8
 
10
- > **Legal:** See [LEGAL.md](./LEGAL.md) and [TRADEMARKS.md](./TRADEMARKS.md) for
11
- > service-access restrictions, branding disclaimers, and license boundaries.
9
+ > Backend services require a [gengage.ai](https://gengage.ai) subscription.
10
+ > See [LEGAL.md](./LEGAL.md) and [TRADEMARKS.md](./TRADEMARKS.md).
12
11
 
13
12
  ---
14
13
 
15
- ## Widgets
16
-
17
- | Widget | Import path | Description |
18
- |--------|------------|-------------|
19
- | **Chat** | `@gengage/assistant-fe/chat` | Floating AI chat drawer with streaming responses |
20
- | **QNA** | `@gengage/assistant-fe/qna` | Contextual action buttons for product pages |
21
- | **SimRel** | `@gengage/assistant-fe/simrel` | Similar / related product grid |
22
- | **Native Bridge** | `@gengage/assistant-fe/native` | Android/iOS WebView bridge + native-ready overlay bootstrap |
14
+ ## Choose Your Integration
23
15
 
24
- > **`middlewareUrl` is required.** Set it in your initialization script to point to your
25
- > Gengage backend. The SDK has no built-in default — you must always provide it explicitly.
26
-
27
- ---
28
-
29
- ## Quick Start (CDN embed)
16
+ ### CDN Script Tag (fastest)
30
17
 
31
18
  ```html
19
+ <script src="https://unpkg.com/@gengage/assistant-fe/dist/gengage-assistant.iife.js"></script>
32
20
  <script>
33
- window.__gengageSessionId =
34
- sessionStorage.getItem('gengage_session_id') ?? crypto.randomUUID();
35
- sessionStorage.setItem('gengage_session_id', window.__gengageSessionId);
36
- </script>
37
- <script src="https://cdn.gengage.ai/widgets/latest/chat.iife.js"></script>
38
- <script>
39
- const chat = new GengageChat();
40
- chat.init({
21
+ GengageAssistant.initFromConfig({
22
+ version: '1',
41
23
  accountId: 'YOUR_ACCOUNT_ID',
42
- middlewareUrl: 'https://YOUR_MIDDLEWARE_URL',
43
- session: { sessionId: window.__gengageSessionId },
44
- theme: { primaryColor: '#3b82f6' },
24
+ middlewareUrl: 'https://YOUR_BACKEND_URL',
45
25
  });
46
26
  </script>
47
27
  ```
48
28
 
49
- ## Quick Start (ES module)
29
+ ### npm / ES Module
50
30
 
51
31
  ```bash
52
32
  npm install @gengage/assistant-fe
53
33
  ```
54
34
 
55
35
  ```ts
56
- import { GengageChat, GengageQNA, GengageSimRel, bootstrapSession, wireQNAToChat } from '@gengage/assistant-fe';
57
-
58
- const sessionId = bootstrapSession();
36
+ import { GengageChat, bootstrapSession } from '@gengage/assistant-fe';
59
37
 
60
38
  const chat = new GengageChat();
61
- await chat.init({ accountId: 'mystore', session: { sessionId } });
62
-
63
- // On PDP pages — mount QNA buttons and similar products
64
- const qna = new GengageQNA();
65
- await qna.init({
39
+ await chat.init({
66
40
  accountId: 'mystore',
67
- mountTarget: '#qna-section',
68
- pageContext: { pageType: 'pdp', sku: currentSku },
69
- session: { sessionId },
41
+ middlewareUrl: 'https://YOUR_BACKEND_URL',
42
+ session: { sessionId: bootstrapSession() },
70
43
  });
71
-
72
- const simrel = new GengageSimRel();
73
- await simrel.init({
74
- accountId: 'mystore',
75
- sku: currentSku,
76
- mountTarget: '#similar-section',
77
- session: { sessionId },
78
- onAddToCart: ({ sku }) => myCart.add(sku),
79
- });
80
-
81
- wireQNAToChat(); // auto-wires QNA button clicks → chat.openWithAction()
82
44
  ```
83
45
 
84
- ## GTM / Overlay Bootstrap (idempotent, no iframe)
46
+ ### Google Tag Manager
85
47
 
86
48
  ```html
87
49
  <script type="module">
88
50
  import { initOverlayWidgets } from 'https://cdn.jsdelivr.net/npm/@gengage/assistant-fe/dist/index.js';
89
51
 
90
52
  await initOverlayWidgets({
91
- accountId: 'koctascomtr',
92
- middlewareUrl: '<ASSISTANT-BACKEND-URL>',
53
+ accountId: 'YOUR_ACCOUNT_ID',
54
+ middlewareUrl: 'https://YOUR_BACKEND_URL',
93
55
  sku: window.productSku,
94
56
  pageContext: { pageType: 'pdp' },
95
- chat: {
96
- variant: 'floating',
97
- mobileBreakpoint: 992,
98
- mobileInitialState: 'half',
99
- },
100
- qna: {
101
- mountTarget: '#koctas-qna-section',
102
- },
103
- simrel: {
104
- mountTarget: '#koctas-similar-products',
105
- },
57
+ chat: { variant: 'floating' },
58
+ qna: { mountTarget: '#qna-section' },
59
+ simrel: { mountTarget: '#similar-products' },
106
60
  });
107
61
  </script>
108
62
  ```
109
63
 
110
- `initOverlayWidgets()` is safe to call multiple times from GTM; it de-duplicates by idempotency key.
111
-
112
- ## Native WebView SDK (Android / iOS)
113
-
114
- Use the native helper package to bridge widget events with:
115
- - iOS WKWebView (`webkit.messageHandlers`)
116
- - Android `JavascriptInterface` (`window.GengageNative.postMessage`)
117
- - React Native WebView (`window.ReactNativeWebView.postMessage`)
64
+ ### Mobile WebView (Android / iOS / React Native)
118
65
 
119
66
  ```ts
120
67
  import { initNativeOverlayWidgets, applyNativeSession } from '@gengage/assistant-fe/native';
121
68
 
122
- applyNativeSession({
123
- sessionId: 'native-session-id',
124
- userId: 'native-user-id',
125
- });
69
+ applyNativeSession({ sessionId: 'native-session-id', userId: 'native-user-id' });
126
70
 
127
71
  const { controller, bridge } = await initNativeOverlayWidgets({
128
- accountId: 'yatasbeddingcomtr',
129
- middlewareUrl: 'https://YOUR_MIDDLEWARE_URL',
130
- locale: 'tr',
131
- pageContext: { pageType: 'pdp', sku: '1066800' },
132
- chat: {
133
- variant: 'floating',
134
- mobileInitialState: 'full',
135
- },
136
- qna: { mountTarget: '#gengage-qna' },
137
- simrel: { mountTarget: '#gengage-simrel' },
72
+ accountId: 'YOUR_ACCOUNT_ID',
73
+ middlewareUrl: 'https://YOUR_BACKEND_URL',
74
+ pageContext: { pageType: 'pdp', sku: '12345' },
75
+ chat: { variant: 'floating', mobileInitialState: 'full' },
138
76
  });
139
-
140
- // Optional manual command from JS side:
141
- bridge.receive({ type: 'openChat', payload: { state: 'full' } });
142
- ```
143
-
144
- Inbound native commands supported by `bridge.receive(...)`:
145
- `openChat`, `closeChat`, `updateContext`, `updateSku`, `setSession`, `destroy`.
146
-
147
- Mobile SDK defaults (out-of-box):
148
- - Commands received before overlay init are queued and replayed after controller is ready.
149
- - `onAddToCart` and `onProductNavigate` auto-forward to native bridge messages if not provided.
150
- - QNA/SimRel are auto-disabled when no mount exists (no noisy mount warnings).
151
- - If QNA/SimRel are explicitly enabled but mount is missing, a default mount is auto-created.
152
-
153
- Supported shorthand command envelopes:
154
-
155
- ```ts
156
- bridge.receive('openChat');
157
- bridge.receive({ command: 'updateSku', data: '1066800' } as unknown as { type: string });
158
- bridge.receive({ action: 'setSession', sessionId: 's1', userId: 'u1' } as unknown as { type: string });
159
77
  ```
160
78
 
161
- ### React Native (`react-native-webview`) host example
162
-
163
- ```tsx
164
- import React, { useMemo } from 'react';
165
- import { WebView } from 'react-native-webview';
166
-
167
- const NATIVE_HTML = `
168
- <!doctype html>
169
- <html>
170
- <body>
171
- <div id="gengage-qna"></div>
172
- <div id="gengage-simrel"></div>
173
- <script type="module">
174
- import { initNativeOverlayWidgets } from 'https://cdn.jsdelivr.net/npm/@gengage/assistant-fe/dist/native.js';
175
- await initNativeOverlayWidgets({
176
- accountId: 'yatasbeddingcomtr',
177
- middlewareUrl: 'https://YOUR_MIDDLEWARE_URL',
178
- pageContext: { pageType: 'pdp', sku: '1066800' },
179
- });
180
- </script>
181
- </body>
182
- </html>`;
183
-
184
- export function GengageNativeOverlay() {
185
- const injectedJavaScript = useMemo(
186
- () =>
187
- `window.gengageNative && window.gengageNative.receive(${JSON.stringify({
188
- type: 'setSession',
189
- payload: { sessionId: 'native-session-id', userId: 'native-user-id' },
190
- })}); true;`,
191
- [],
192
- );
193
-
194
- return (
195
- <WebView
196
- originWhitelist={['*']}
197
- source={{ html: NATIVE_HTML }}
198
- injectedJavaScript={injectedJavaScript}
199
- onMessage={(event) => {
200
- // event.nativeEvent.data is JSON from window.ReactNativeWebView.postMessage(...)
201
- const message = JSON.parse(event.nativeEvent.data);
202
- console.log('gengage-native-event', message);
203
- }}
204
- />
205
- );
206
- }
207
- ```
79
+ See [docs/native-mobile-sdk.md](docs/native-mobile-sdk.md) for iOS WKWebView, Android WebView, and React Native examples.
208
80
 
209
81
  ---
210
82
 
211
- ## Repository Structure
83
+ ## Widgets
212
84
 
213
- ```
214
- gengage-assistant-fe/
215
- ├── src/
216
- │ ├── common/ # Shared types, NDJSON stream parser, event bus, BaseWidget
217
- │ ├── chat/ # Chat widget
218
- │ │ ├── catalog.ts # json-render component schemas (Zod)
219
- │ │ ├── types.ts # Config interface + domain types
220
- │ │ ├── index.ts # Public class GengageChat
221
- │ │ └── components/ # Vanilla TS renderers (ChatDrawer, AITopPicks, etc.)
222
- │ ├── qna/ # QNA widget (same structure)
223
- │ ├── simrel/ # Similar Products widget (same structure)
224
- │ ├── native/ # Native WebView bridge helper exports
225
- │ └── index.ts # Barrel export
226
- ├── demos/
227
- │ ├── koctascomtr/ # Koçtaş branded PDP (inline config)
228
- │ ├── arcelikcomtr/ # Arçelik branded PDP
229
- │ ├── n11com/ # N11 branded PDP
230
- │ ├── yatasbeddingcomtr/ # Yataş Bedding branded PDP
231
- │ ├── hepsiburadacom/ # Hepsiburada branded PDP
232
- │ ├── vanilla-script/ # IIFE script tags, no bundler
233
- │ ├── vanilla-esm/ # ESM import, Vite-served
234
- │ ├── react/ # React CDN + IIFE bundles
235
- │ ├── nextjs/ # Next.js integration guide
236
- │ └── native/ # Mobile WebView overlay
237
- ├── catalog/ # Visual component catalog (no backend needed)
238
- │ ├── index.html # SPA shell
239
- │ ├── vite.config.ts # Resolves @gengage/assistant-fe → dist/
240
- │ └── src/ # Router, layout, mock data, sections
241
- ├── scripts/
242
- │ └── dev.ts # Dev server entry point (npm run dev)
243
- ├── docs/
244
- │ ├── architecture.md # System design and data flows
245
- │ ├── wire-protocol.md # Backend ↔ frontend NDJSON contract
246
- │ ├── config-files.md # File-based account configuration contract
247
- │ └── analytics-contract.md # Analytics + attribution event contract
248
- └── tests/ # Vitest unit tests + Playwright E2E
249
- ```
85
+ | Widget | Import | What it does |
86
+ |--------|--------|-------------|
87
+ | **Chat** | `@gengage/assistant-fe/chat` | Floating AI drawer with streaming responses, product cards, comparison tables |
88
+ | **QNA** | `@gengage/assistant-fe/qna` | Contextual action buttons for product pages |
89
+ | **SimRel** | `@gengage/assistant-fe/simrel` | AI-powered similar/related product grid |
90
+ | **Native** | `@gengage/assistant-fe/native` | Android/iOS WebView bridge + overlay bootstrap |
250
91
 
251
92
  ---
252
93
 
253
- ## npm Scripts
254
-
255
- | Command | Description |
256
- |---------|-------------|
257
- | `npm run dev -- <accountId> <sku>` | Start local dev server in PDP mode for an account + SKU |
258
- | `npm run kill` | Kill zombie listeners on ports 3000-3010 |
259
- | `npm run prerequisites:check` | Validate kickoff prerequisites (docs/config/schema/action routing) |
260
- | `npm run dev -- koctascomtr --sku=1000465056` | Example: Koçtaş PDP with SKU 1000465056 |
261
- | `npm run dev -- n11com --sku=ABC123 --port=3005` | Custom port |
262
- | `npm run build` | Build all widgets to `dist/` |
263
- | `npm run typecheck` | TypeScript strict check (no emit) |
264
- | `npm run lint` | ESLint `src/` |
265
- | `npm run test` | Vitest unit tests |
266
- | `npm run test:e2e` | Playwright smoke tests |
267
- | `npm run catalog` | Visual component catalog at `http://localhost:3002` |
268
- | `npm run docs:dev` | VitePress docs server |
269
-
270
- ### `npm run dev` — Local Widget Test Server
271
-
272
- The dev server spins up an account-aware PDP host shell with all three widgets initialised
273
- for the given account and SKU. Every invocation generates fresh UUIDs printed to the console:
274
-
275
- Current focus is PDP mode (`product details`) with a concrete SKU.
276
- PLP mode (`category / sku-list`) is planned and will be added as a separate harness flow.
94
+ ## Customization
277
95
 
278
- ```
279
- ── Gengage Dev Server ──────────────────────────────
280
- Account: koctascomtr
281
- SKU: 1234567
282
- Page type: pdp
283
- Session ID: 550e8400-e29b-41d4-a716-446655440000
284
- User ID: 6ba7b810-9dad-11d1-80b4-00c04fd430c8
285
- View ID: 6ba7b811-9dad-11d1-80b4-00c04fd430c8
286
- URL: http://localhost:3000
287
- ────────────────────────────────────────────────────
96
+ **Theme tokens** — no fork required:
97
+ ```ts
98
+ chat.init({
99
+ theme: { primaryColor: '#f27a1a', headerBg: '#1a1a2e' },
100
+ });
288
101
  ```
289
102
 
290
- The page shows:
291
- - A dev info banner with all context values
292
- - A realistic PDP scaffold (gallery, summary, tabs, recommendation rails)
293
- - The QNA widget mounted at the account's expected selector (for example `#koctas-qna-section`, `#arcelik-qna-section`, `#n11-qna-section`)
294
- - The SimRel widget mounted at the account's expected selector (for example `#koctas-similar-products`, `#arcelik-similar-products`, `#n11-similar-products`)
295
- - The Chat floating launcher
103
+ **Component overrides** — swap any UI component via the json-render registry.
296
104
 
297
- HMR is active editing `src/` files updates the page without a full reload.
105
+ **Full fork**replace `src/chat/components/` entirely; keep `catalog.ts` + `index.ts`.
298
106
 
299
- > The dev server serves the account's demo page from `demos/<accountId>/index.html`,
300
- > generating fresh session/user/view IDs on each start.
107
+ See [CUSTOMIZATION-GUIDE.md](CUSTOMIZATION-GUIDE.md) for the full playbook.
301
108
 
302
- ### Component Catalog (`npm run catalog`)
109
+ ---
303
110
 
304
- A visual catalog that renders every component with mock data — no backend needed.
305
- Imports from `dist/` (validates the npm package as consumers would see it).
111
+ ## Development
306
112
 
307
113
  ```bash
308
- npm run build && npm run catalog # Build first, then serve at :3002
114
+ npm install
115
+ npm run dev -- koctascomtr --sku=1000465056 # Local dev server with HMR
116
+ npm run typecheck # TypeScript strict check
117
+ npm run test # 1056 unit tests
118
+ npm run build # Build to dist/
119
+ npm run catalog # Visual component catalog at :3002
309
120
  ```
310
121
 
311
- Open `http://localhost:3002` to see:
312
-
313
- - **25+ components** grouped by widget (Chat, QNA, SimRel) in realistic frames
314
- - **Global theme selector** — switch between 12 merchant color presets (Koçtaş, n11, Hepsiburada, Trendyol, etc.)
315
- - **Chat components** shown inside a chat-drawer frame (dark header, avatar, message area)
316
- - **QNA components** shown inside a PDP-like frame (product title, price)
317
- - **SimRel components** shown inside a product section frame ("Benzer Ürünler" header)
318
- - **Full Widgets** section with mock fetch backend (NDJSON interception)
319
- - **Theme Comparison** — same component rendered across all 12 merchant themes
320
- - **Responsive Preview** — mobile / tablet / desktop viewport frames
321
-
322
- The catalog lives in `catalog/` and is excluded from npm publish (`files: ["dist/"]`).
323
-
324
122
  ---
325
123
 
326
- ## Customization
327
-
328
- Three levels — no fork required for themes, fork required for components:
329
-
330
- 1. **Theme tokens** — pass a `theme` object to `init()` (CSS custom properties)
331
- 2. **Component overrides** — replace entries in `components/registry.tsx`
332
- 3. **Full replacement** — replace all of `components/` (keep `catalog.ts` + `index.ts`)
333
-
334
- See [CUSTOMIZATION-GUIDE.md](CUSTOMIZATION-GUIDE.md) for details, examples, and fork/customize/deploy guidance.
124
+ ## Documentation
335
125
 
336
- Reference account implementations are in `demos/`. Koçtaş (`demos/koctascomtr/`)
337
- is the fully-wired reference. Copy it as a starting point for a new account.
126
+ | Doc | Description |
127
+ |-----|-------------|
128
+ | [Architecture](docs/architecture.md) | System design, widget lifecycle, data flows |
129
+ | [Wire Protocol](docs/wire-protocol.md) | Backend NDJSON streaming contract |
130
+ | [Customization](docs/customization.md) | CSS tokens, component overrides, XSS rules |
131
+ | [GTM Quickstart](docs/gtm-quickstart.md) | Copy-paste GTM embedding patterns |
132
+ | [Security](docs/security-production.md) | Production CSP, postMessage origins, sanitization |
133
+ | [Analytics](docs/analytics-contract.md) | Event taxonomy and attribution |
134
+ | [Mobile SDK](docs/native-mobile-sdk.md) | Android/iOS/React Native integration |
135
+ | [New Account](docs/new-account-guide.md) | Adding a new merchant demo |
338
136
 
339
137
  ---
340
138
 
341
- ## Documentation
139
+ ## Project Structure
342
140
 
343
- | Doc | Description |
344
- |-----|-------------|
345
- | [docs/architecture.md](docs/architecture.md) | System design, data flows, json-render integration |
346
- | [docs/wire-protocol.md](docs/wire-protocol.md) | Backend frontend NDJSON contract |
347
- | [docs/config-files.md](docs/config-files.md) | File-driven self-service account configuration |
348
- | [docs/analytics-contract.md](docs/analytics-contract.md) | Stream/token/metering/history/checkout analytics contract |
349
- | [docs/native-mobile-sdk.md](docs/native-mobile-sdk.md) | Android/iOS/React Native WebView integration guide |
350
- | [CUSTOMIZATION-GUIDE.md](CUSTOMIZATION-GUIDE.md) | Fork/customize/deploy playbook for integrators and coding agents |
351
- | [CONTRIBUTION-GUIDE.md](CONTRIBUTION-GUIDE.md) | SDK/core development guide for contributors and coding agents |
141
+ ```
142
+ src/
143
+ common/ # Shared: types, NDJSON parser, event bus, sanitizer, utilities
144
+ chat/ # Chat widget (GengageChat class + components)
145
+ qna/ # QNA widget (GengageQNA class + components)
146
+ simrel/ # Similar products widget (GengageSimRel class + components)
147
+ native/ # Native WebView bridge exports
148
+ demos/ # 12 merchant-branded demo pages
149
+ catalog/ # Visual component catalog (mock data, no backend)
150
+ docs/ # Architecture, wire protocol, customization, analytics
151
+ tests/ # Vitest unit tests + Playwright E2E
152
+ ```
352
153
 
353
154
  ---
354
155
 
@@ -356,7 +157,4 @@ is the fully-wired reference. Copy it as a starting point for a new account.
356
157
 
357
158
  Licensed under the **GENGAGE FRONTEND SOURCE-AVAILABLE LICENSE v1.0** — see [LICENSE](LICENSE).
358
159
 
359
- Backend services are proprietary and require a separate [gengage.ai](https://gengage.ai) subscription.
360
- They are not covered by this license.
361
-
362
- For trademark and account-design disclaimers, see [TRADEMARKS.md](./TRADEMARKS.md).
160
+ Backend services are proprietary and require a [gengage.ai](https://gengage.ai) subscription.
@@ -1 +1 @@
1
- .gengage-qna-container{font-family:var(--gengage-font-family, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif);font-size:var(--gengage-font-size, 14px);color:var(--gengage-foreground-color, #333)}.gengage-qna-uispec>*{animation:gengage-qna-enter .15s cubic-bezier(.2,.72,.2,1) both}@keyframes gengage-qna-enter{0%{opacity:0;transform:translateY(4px) scale(.995)}to{opacity:1;transform:translateY(0) scale(1)}}.gengage-qna-buttons{display:flex;flex-wrap:wrap;gap:8px;padding:8px 0 12px}.gengage-qna-button{display:inline-flex;align-items:center;justify-content:center;min-height:40px;padding:8px 14px;border:none;border-radius:var(--gengage-qna-pill-radius, 999px);background:var(--gengage-primary-color, #3b82f6);color:var(--gengage-primary-foreground, #fff);font-size:13px;font-weight:600;font-family:inherit;cursor:pointer;transition:filter .14s ease,transform .12s ease;text-align:left;line-height:1.25}.gengage-qna-button:hover{filter:brightness(1.06);transform:translateY(-1px)}.gengage-qna-button:active{transform:translateY(1px) scale(.988)}.gengage-qna-button:focus-visible{outline:2px solid var(--gengage-primary-color, #3b82f6);outline-offset:2px}.gengage-qna-cta{display:inline-flex;align-items:center;min-height:40px;padding:8px 14px;border:1px dashed color-mix(in srgb,var(--gengage-primary-color, #3b82f6) 65%,#cbd5e1 35%);border-radius:var(--gengage-qna-pill-radius, 999px);background:transparent;color:var(--gengage-primary-color, #3b82f6);font-size:13px;font-weight:600;font-family:inherit;cursor:pointer;opacity:.92;transition:opacity .12s ease,transform .12s ease;white-space:nowrap}.gengage-qna-cta:hover{opacity:1;transform:translateY(-1px)}.gengage-qna-input-wrapper{display:flex;gap:8px;padding:6px 0 2px;align-items:center}.gengage-qna-input{flex:1;min-width:0;height:48px;padding:0 14px 0 40px;border:1px solid #d5dbe7;border-radius:var(--gengage-qna-input-radius, 14px);font-size:15px;font-family:inherit;outline:none;background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='18' height='18' viewBox='0 0 24 24' fill='none' stroke='%239ca3af' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='8'/%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'/%3E%3C/svg%3E") 14px center no-repeat;transition:border-color .14s ease,box-shadow .14s ease}.gengage-qna-input::placeholder{transition:opacity .18s ease}.gengage-qna-input--fade::placeholder{opacity:0}.gengage-qna-input:focus{border-color:var(--gengage-primary-color, #3b82f6);box-shadow:0 0 0 3px color-mix(in srgb,var(--gengage-primary-color, #3b82f6) 18%,transparent)}.gengage-qna-send{min-width:60px;height:48px;padding:0 16px;border:1px dashed color-mix(in srgb,var(--gengage-primary-color, #3b82f6) 65%,#cbd5e1 35%);border-radius:var(--gengage-qna-pill-radius, 999px);background:transparent;color:var(--gengage-primary-color, #3b82f6);font-size:13px;font-weight:600;font-family:inherit;cursor:pointer;opacity:.92;transition:opacity .12s ease,transform .12s ease;white-space:nowrap}.gengage-qna-send:hover{opacity:1;transform:translateY(-1px)}.gengage-qna-send:active{transform:translateY(1px)}.gengage-qna-heading{font-size:1.04em;font-weight:700;margin:0 0 6px;color:var(--gengage-foreground-color, #333)}.gengage-qna-loading{display:flex;gap:4px;padding:12px 0}.gengage-qna-loading-dot{width:7px;height:7px;border-radius:50%;background:var(--gengage-primary-color, #3b82f6);opacity:.4;animation:gengage-qna-pulse 1.4s infinite ease-in-out both}.gengage-qna-loading-dot:nth-child(1){animation-delay:0s}.gengage-qna-loading-dot:nth-child(2){animation-delay:.16s}.gengage-qna-loading-dot:nth-child(3){animation-delay:.32s}@keyframes gengage-qna-pulse{0%,80%,to{opacity:.4;transform:scale(.8)}40%{opacity:1;transform:scale(1)}}@media(max-width:768px){.gengage-qna-buttons{gap:10px;padding:10px 0 14px}.gengage-qna-button,.gengage-qna-cta{min-height:44px;padding:10px 16px;font-size:14px;line-height:1.2}.gengage-qna-input-wrapper{flex-direction:column;gap:10px}.gengage-qna-input{width:100%;height:52px;padding-left:42px;font-size:16px}.gengage-qna-send{width:100%;min-height:48px;font-size:14px}}@media(prefers-reduced-motion:reduce){.gengage-qna-uispec>*,.gengage-qna-button,.gengage-qna-cta,.gengage-qna-send{animation:none!important;transition:none!important;transform:none!important}}.gengage-simrel-container{font-family:var(--gengage-font-family, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif);font-size:var(--gengage-font-size, 14px);color:var(--gengage-foreground-color, #333);--_gengage-border-color: var(--gengage-border-color, #e5e7eb);--_gengage-discount-color: var(--gengage-discount-color, #ef4444);--_gengage-text-secondary: var(--gengage-text-secondary, #6b7280)}.gengage-simrel-uispec>*{animation:gengage-simrel-enter .2s cubic-bezier(.2,.72,.2,1) both}@keyframes gengage-simrel-enter{0%{opacity:0;transform:translateY(8px) scale(.99)}to{opacity:1;transform:translateY(0) scale(1)}}.gengage-simrel-grid{display:grid;grid-template-columns:repeat(var(--gengage-simrel-columns, 4),minmax(0,1fr));gap:14px;padding:10px 0 16px}@media(max-width:992px){.gengage-simrel-grid{grid-template-columns:repeat(3,1fr)}}@media(max-width:768px){.gengage-simrel-grid{grid-template-columns:repeat(2,1fr);gap:12px}}.gengage-simrel-card{display:flex;flex-direction:column;position:relative;border:1px solid #eee;border-radius:var(--gengage-simrel-card-radius, 16px);overflow:hidden;background:var(--gengage-background-color, #fff);cursor:pointer;transition:box-shadow .2s ease,transform .1s ease;box-shadow:0 2px 8px #0000000f}.gengage-simrel-grid .gengage-simrel-card.gengage-chat-product-card{width:100%;min-width:0;max-width:none}.gengage-simrel-card:hover{box-shadow:0 4px 16px #0000001f;transform:translateY(-2px)}.gengage-simrel-card-image{position:relative;aspect-ratio:1;overflow:hidden;background:#fff}.gengage-simrel-card-image img{width:100%;height:100%;object-fit:contain;padding:8px;box-sizing:border-box}.gengage-simrel-badge{position:absolute;top:8px;left:8px;padding:2px 8px;border-radius:4px;background:var(--_gengage-discount-color);color:#fff;font-size:12px;font-weight:600}.gengage-simrel-card-info{flex:1;padding:8px 10px 10px;display:flex;flex-direction:column;gap:4px;text-align:center}.gengage-simrel-card-brand{font-size:10px;color:#666}.gengage-simrel-card-name{font-size:13px;font-weight:600;color:#1f2937;line-height:1.35;display:-webkit-box;-webkit-line-clamp:2;line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;text-overflow:ellipsis;min-height:0}.gengage-simrel-card-rating{font-size:12px;color:#f59e0b}.gengage-simrel-card-review-count{color:#9ca3af}.gengage-simrel-card-price{margin-top:auto;padding-top:4px;display:flex;align-items:baseline;justify-content:center;gap:4px}.gengage-simrel-card-price-original{text-decoration:line-through;color:#64748b;font-weight:400;font-size:12px}.gengage-simrel-card-price-current{font-size:16px;font-weight:800;color:#0f172a}.gengage-simrel-card-cta{width:100%;min-height:40px;border:none;border-top:1px solid #f1f5f9;border-radius:0;background:transparent;font-family:inherit;cursor:pointer}.gengage-simrel-container .gengage-simrel-atc{display:flex;width:100%;border-top:1px solid var(--_gengage-border-color);border-left:none;border-right:none;border-bottom:none;border-radius:0;background:transparent}.gengage-simrel-container .gengage-simrel-atc.gengage-qty-stepper{gap:0;overflow:hidden;border-radius:0;border-top:1px solid #f1f5f9;border-left:none;border-right:none;border-bottom:none}.gengage-simrel-container .gengage-simrel-atc .gengage-qty-btn{width:32px;height:36px;color:#64748b;font-size:14px}.gengage-simrel-container .gengage-simrel-atc .gengage-qty-btn:hover:not(:disabled){background:#f1f5f9}.gengage-simrel-container .gengage-simrel-atc .gengage-qty-value{min-width:24px;font-size:13px;color:#334155}.gengage-simrel-container .gengage-simrel-atc .gengage-qty-submit{flex:1;border-left:1px solid var(--_gengage-border-color);background:transparent;color:var(--gengage-primary-color, #3b82f6);font-weight:700;font-size:12px;font-family:inherit;letter-spacing:.01em;padding:8px 10px;border-radius:0;transition:color .15s ease,background .15s ease}.gengage-simrel-container .gengage-simrel-atc .gengage-qty-submit:hover{color:var(--gengage-primary-color, #0b24d6);background:#f8fafc}.gengage-simrel-quick-actions{display:flex;flex-wrap:wrap;gap:8px;padding:6px 12px 12px}.gengage-simrel-quick-action{border:1px solid #d2d8e3;background:#f8fafc;color:#334155;border-radius:999px;min-height:40px;padding:8px 10px;font-size:12px;font-weight:600;cursor:pointer;transition:transform .12s ease,box-shadow .12s ease,border-color .12s ease}.gengage-simrel-quick-action:hover{border-color:var(--gengage-primary-color, #3b82f6);color:var(--gengage-primary-color, #3b82f6);box-shadow:0 6px 14px #0f172a1f;transform:translateY(-1px)}.gengage-simrel-empty{grid-column:1 / -1;text-align:center;padding:40px 20px;color:var(--_gengage-text-secondary)}.gengage-simrel-tabs{display:flex;gap:4px;border-bottom:2px solid var(--_gengage-border-color);margin-bottom:16px;overflow-x:auto}.gengage-simrel-tab{min-height:40px;padding:10px 14px;border:none;background:transparent;color:var(--_gengage-text-secondary);font-size:inherit;font-family:inherit;cursor:pointer;white-space:nowrap;border-bottom:2px solid transparent;margin-bottom:-2px;transition:color .2s,border-color .2s}.gengage-simrel-tab:hover{color:var(--gengage-primary-color, #3b82f6)}.gengage-simrel-tab--active{color:var(--gengage-primary-color, #3b82f6);border-bottom-color:var(--gengage-primary-color, #3b82f6);font-weight:600}.gengage-simrel-loading{display:flex;justify-content:center;padding:40px}.gengage-simrel-spinner{width:32px;height:32px;border:3px solid var(--_gengage-border-color);border-top-color:var(--gengage-primary-color, #3b82f6);border-radius:50%;animation:gengage-simrel-spin .7s linear infinite}@keyframes gengage-simrel-spin{to{transform:rotate(360deg)}}@media(max-width:768px){.gengage-simrel-grid{gap:10px;padding-top:8px}.gengage-simrel-card-cta,.gengage-simrel-quick-action,.gengage-simrel-tab{min-height:44px}.gengage-simrel-container .gengage-simrel-atc .gengage-qty-btn{width:44px;height:44px;font-size:16px}.gengage-simrel-container .gengage-simrel-atc .gengage-qty-submit{min-height:44px;flex-basis:auto;border-left:1px solid var(--_gengage-border-color);border-top:none}}.gengage-simrel-card:focus-visible,.gengage-simrel-tab:focus-visible,.gengage-simrel-quick-action:focus-visible,.gengage-simrel-atc .gengage-qty-btn:focus-visible,.gengage-simrel-atc .gengage-qty-submit:focus-visible{outline:2px solid var(--gengage-primary-color, #3b82f6);outline-offset:2px}@media(prefers-reduced-motion:reduce){.gengage-simrel-uispec>*,.gengage-simrel-card,.gengage-simrel-card-image img,.gengage-simrel-quick-action,.gengage-simrel-spinner{animation:none!important;transition:none!important;transform:none!important}}
1
+ .gengage-qna-container{font-family:var(--gengage-font-family, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif);font-size:var(--gengage-font-size, 14px);color:var(--gengage-foreground-color, #333);--_gengage-border-color: var(--gengage-border-color, #e5e7eb)}.gengage-qna-uispec>*{animation:gengage-qna-enter .15s cubic-bezier(.2,.72,.2,1) both}@keyframes gengage-qna-enter{0%{opacity:0;transform:translateY(4px) scale(.995)}to{opacity:1;transform:translateY(0) scale(1)}}.gengage-qna-buttons{display:flex;flex-wrap:wrap;gap:8px;padding:8px 0 12px}.gengage-qna-button{display:inline-flex;align-items:center;justify-content:center;min-height:40px;padding:8px 14px;border:none;border-radius:var(--gengage-qna-pill-radius, 999px);background:var(--gengage-primary-color, #3b82f6);color:var(--gengage-primary-foreground, #fff);font-size:13px;font-weight:600;font-family:inherit;cursor:pointer;transition:filter .14s ease,transform .12s ease;text-align:left;line-height:1.25}.gengage-qna-button:hover{filter:brightness(1.06);transform:translateY(-1px)}.gengage-qna-button:active{transform:translateY(1px) scale(.988)}.gengage-qna-button:focus-visible{outline:2px solid var(--gengage-primary-color, #3b82f6);outline-offset:2px}.gengage-qna-cta{display:inline-flex;align-items:center;min-height:40px;padding:8px 14px;border:1px dashed color-mix(in srgb,var(--gengage-primary-color, #3b82f6) 65%,#cbd5e1 35%);border-radius:var(--gengage-qna-pill-radius, 999px);background:transparent;color:var(--gengage-primary-color, #3b82f6);font-size:13px;font-weight:600;font-family:inherit;cursor:pointer;opacity:.92;transition:opacity .12s ease,transform .12s ease;white-space:nowrap}.gengage-qna-cta:hover{opacity:1;transform:translateY(-1px)}.gengage-qna-cta:focus-visible{outline:2px solid var(--gengage-primary-color, #3b82f6);outline-offset:2px}.gengage-qna-input-wrapper{display:flex;gap:8px;padding:6px 0 2px;align-items:center}.gengage-qna-input{flex:1;min-width:0;height:48px;padding:0 14px 0 40px;border:1px solid var(--_gengage-border-color);border-radius:var(--gengage-qna-input-radius, 14px);font-size:15px;font-family:inherit;outline:none;background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='18' height='18' viewBox='0 0 24 24' fill='none' stroke='%239ca3af' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='8'/%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'/%3E%3C/svg%3E") 14px center no-repeat;transition:border-color .14s ease,box-shadow .14s ease}.gengage-qna-input::placeholder{transition:opacity .18s ease}.gengage-qna-input--fade::placeholder{opacity:0}.gengage-qna-input:focus{border-color:var(--gengage-primary-color, #3b82f6);box-shadow:0 0 0 3px color-mix(in srgb,var(--gengage-primary-color, #3b82f6) 18%,transparent)}.gengage-qna-send{min-width:60px;height:48px;padding:0 16px;border:1px dashed color-mix(in srgb,var(--gengage-primary-color, #3b82f6) 65%,#cbd5e1 35%);border-radius:var(--gengage-qna-pill-radius, 999px);background:transparent;color:var(--gengage-primary-color, #3b82f6);font-size:13px;font-weight:600;font-family:inherit;cursor:pointer;opacity:.92;transition:opacity .12s ease,transform .12s ease;white-space:nowrap}.gengage-qna-send:hover{opacity:1;transform:translateY(-1px)}.gengage-qna-send:focus-visible{outline:2px solid var(--gengage-primary-color, #3b82f6);outline-offset:2px}.gengage-qna-send:active{transform:translateY(1px)}.gengage-qna-heading{font-size:1.04em;font-weight:700;margin:0 0 6px;color:var(--gengage-foreground-color, #333)}.gengage-qna-loading{display:flex;gap:4px;padding:12px 0}.gengage-qna-loading-dot{width:7px;height:7px;border-radius:50%;background:var(--gengage-primary-color, #3b82f6);opacity:.4;animation:gengage-qna-pulse 1.4s infinite ease-in-out both}.gengage-qna-loading-dot:nth-child(1){animation-delay:0s}.gengage-qna-loading-dot:nth-child(2){animation-delay:.16s}.gengage-qna-loading-dot:nth-child(3){animation-delay:.32s}@keyframes gengage-qna-pulse{0%,80%,to{opacity:.4;transform:scale(.8)}40%{opacity:1;transform:scale(1)}}@media(max-width:768px){.gengage-qna-buttons{gap:10px;padding:10px 0 14px}.gengage-qna-button,.gengage-qna-cta{min-height:44px;padding:10px 16px;font-size:14px;line-height:1.2}.gengage-qna-input-wrapper{flex-direction:column;gap:10px}.gengage-qna-input{width:100%;height:52px;padding-left:42px;font-size:16px}.gengage-qna-send{width:100%;min-height:48px;font-size:14px}}@media(prefers-reduced-motion:reduce){.gengage-qna-uispec>*,.gengage-qna-button,.gengage-qna-cta,.gengage-qna-send{animation:none!important;transition:none!important;transform:none!important}}.gengage-simrel-container{font-family:var(--gengage-font-family, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif);font-size:var(--gengage-font-size, 14px);color:var(--gengage-foreground-color, #333);--_gengage-border-color: var(--gengage-border-color, #e5e7eb);--_gengage-discount-color: var(--gengage-discount-color, #ef4444);--_gengage-text-primary: var(--gengage-text-primary, #1f2937);--_gengage-text-secondary: var(--gengage-text-secondary, #6b7280);--_gengage-surface-muted: var(--gengage-surface-muted, #f8fafc);--_gengage-rating-color: var(--gengage-rating-color, #d97706)}.gengage-simrel-uispec>*{animation:gengage-simrel-enter .2s cubic-bezier(.2,.72,.2,1) both}@keyframes gengage-simrel-enter{0%{opacity:0;transform:translateY(8px) scale(.99)}to{opacity:1;transform:translateY(0) scale(1)}}.gengage-simrel-grid{display:grid;grid-template-columns:repeat(var(--gengage-simrel-columns, 4),minmax(0,1fr));gap:14px;padding:10px 0 16px}@media(max-width:992px){.gengage-simrel-grid{grid-template-columns:repeat(3,1fr)}}@media(max-width:768px){.gengage-simrel-grid{grid-template-columns:repeat(2,1fr);gap:12px}}.gengage-simrel-card{display:flex;flex-direction:column;position:relative;border:1px solid var(--_gengage-border-color);border-radius:var(--gengage-simrel-card-radius, 16px);overflow:hidden;background:var(--gengage-background-color, #fff);cursor:pointer;transition:box-shadow .2s ease,transform .1s ease;box-shadow:0 2px 8px #0000000f}.gengage-simrel-grid .gengage-simrel-card.gengage-chat-product-card{width:100%;min-width:0;max-width:none}.gengage-simrel-card:hover{box-shadow:0 4px 16px #0000001f;transform:translateY(-2px)}.gengage-simrel-card-image{position:relative;aspect-ratio:1;overflow:hidden;background:#fff}.gengage-simrel-card-image img{width:100%;height:100%;object-fit:contain;padding:8px;box-sizing:border-box}.gengage-simrel-badge{position:absolute;top:8px;left:8px;padding:2px 8px;border-radius:4px;background:var(--_gengage-discount-color);color:#fff;font-size:12px;font-weight:600}.gengage-simrel-card-info{flex:1;padding:8px 10px 10px;display:flex;flex-direction:column;gap:4px;text-align:center}.gengage-simrel-card-brand{font-size:10px;color:var(--_gengage-text-secondary)}.gengage-simrel-card-name{font-size:13px;font-weight:600;color:var(--_gengage-text-primary);line-height:1.35;display:-webkit-box;-webkit-line-clamp:2;line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;text-overflow:ellipsis;min-height:0}.gengage-simrel-card-rating{font-size:12px;color:var(--_gengage-rating-color)}.gengage-simrel-card-review-count{color:var(--_gengage-text-secondary)}.gengage-simrel-card-price{margin-top:auto;padding-top:4px;display:flex;align-items:baseline;justify-content:center;gap:4px}.gengage-simrel-card-price-original{text-decoration:line-through;color:var(--_gengage-text-secondary);font-weight:400;font-size:12px}.gengage-simrel-card-price-current{font-size:16px;font-weight:800;color:var(--_gengage-text-primary)}.gengage-simrel-card-cta{width:100%;min-height:40px;border:none;border-top:1px solid var(--_gengage-surface-muted);border-radius:0;background:transparent;font-family:inherit;cursor:pointer}.gengage-simrel-container .gengage-simrel-atc{display:flex;width:100%;border-top:1px solid var(--_gengage-border-color);border-left:none;border-right:none;border-bottom:none;border-radius:0;background:transparent}.gengage-simrel-container .gengage-simrel-atc.gengage-qty-stepper{gap:0;overflow:hidden;border-radius:0;border-top:1px solid var(--_gengage-surface-muted);border-left:none;border-right:none;border-bottom:none}.gengage-simrel-container .gengage-simrel-atc .gengage-qty-btn{width:32px;height:36px;color:var(--_gengage-text-secondary);font-size:14px}.gengage-simrel-container .gengage-simrel-atc .gengage-qty-btn:hover:not(:disabled){background:var(--_gengage-surface-muted)}.gengage-simrel-container .gengage-simrel-atc .gengage-qty-value{min-width:24px;font-size:13px;color:var(--_gengage-text-primary)}.gengage-simrel-container .gengage-simrel-atc .gengage-qty-submit{flex:1;border-left:1px solid var(--_gengage-border-color);background:transparent;color:var(--gengage-primary-color, #3b82f6);font-weight:700;font-size:12px;font-family:inherit;letter-spacing:.01em;padding:8px 10px;border-radius:0;transition:color .15s ease,background .15s ease}.gengage-simrel-container .gengage-simrel-atc .gengage-qty-submit:hover{color:var(--gengage-primary-color, #0b24d6);background:var(--_gengage-surface-muted)}.gengage-simrel-quick-actions{display:flex;flex-wrap:wrap;gap:8px;padding:6px 12px 12px}.gengage-simrel-quick-action{border:1px solid var(--_gengage-border-color);background:var(--_gengage-surface-muted);color:var(--_gengage-text-primary);border-radius:999px;min-height:40px;padding:8px 10px;font-size:12px;font-weight:600;cursor:pointer;transition:transform .12s ease,box-shadow .12s ease,border-color .12s ease}.gengage-simrel-quick-action:hover{border-color:var(--gengage-primary-color, #3b82f6);color:var(--gengage-primary-color, #3b82f6);box-shadow:0 6px 14px #0f172a1f;transform:translateY(-1px)}.gengage-simrel-empty{grid-column:1 / -1;text-align:center;padding:40px 20px;color:var(--_gengage-text-secondary)}.gengage-simrel-tabs{display:flex;gap:4px;border-bottom:2px solid var(--_gengage-border-color);margin-bottom:16px;overflow-x:auto}.gengage-simrel-tab{min-height:40px;padding:10px 14px;border:none;background:transparent;color:var(--_gengage-text-secondary);font-size:inherit;font-family:inherit;cursor:pointer;white-space:nowrap;border-bottom:2px solid transparent;margin-bottom:-2px;transition:color .2s,border-color .2s}.gengage-simrel-tab:hover{color:var(--gengage-primary-color, #3b82f6)}.gengage-simrel-tab--active{color:var(--gengage-primary-color, #3b82f6);border-bottom-color:var(--gengage-primary-color, #3b82f6);font-weight:600}.gengage-simrel-loading{display:flex;justify-content:center;padding:40px}.gengage-simrel-spinner{width:32px;height:32px;border:3px solid var(--_gengage-border-color);border-top-color:var(--gengage-primary-color, #3b82f6);border-radius:50%;animation:gengage-simrel-spin .7s linear infinite}@keyframes gengage-simrel-spin{to{transform:rotate(360deg)}}@media(max-width:768px){.gengage-simrel-grid{gap:10px;padding-top:8px}.gengage-simrel-card-cta,.gengage-simrel-quick-action,.gengage-simrel-tab{min-height:44px}.gengage-simrel-container .gengage-simrel-atc .gengage-qty-btn{width:44px;height:44px;font-size:16px}.gengage-simrel-container .gengage-simrel-atc .gengage-qty-submit{min-height:44px;flex-basis:auto;border-left:1px solid var(--_gengage-border-color);border-top:none}}.gengage-simrel-card:focus-visible,.gengage-simrel-tab:focus-visible,.gengage-simrel-quick-action:focus-visible,.gengage-simrel-atc .gengage-qty-btn:focus-visible,.gengage-simrel-atc .gengage-qty-submit:focus-visible{outline:2px solid var(--gengage-primary-color, #3b82f6);outline-offset:2px}@media(prefers-reduced-motion:reduce){.gengage-simrel-uispec>*,.gengage-simrel-card,.gengage-simrel-card-image img,.gengage-simrel-quick-action,.gengage-simrel-spinner{animation:none!important;transition:none!important;transform:none!important}}
@@ -55,7 +55,7 @@ export interface ActionEnrichmentContext {
55
55
  isMobile?: boolean | undefined;
56
56
  }
57
57
  /**
58
- * Enriches action payloads with fields the v1 backend expects.
58
+ * Enriches action payloads with fields the backend expects.
59
59
  * Only adds fields that are not already present in the payload.
60
60
  */
61
61
  export declare function enrichActionPayload(action: {
@@ -83,15 +83,4 @@ export interface StreamCallbacks {
83
83
  onDone: () => void;
84
84
  }
85
85
  export declare function sendChatMessage(request: ProcessActionRequest, callbacks: StreamCallbacks, transport: ChatTransportConfig): AbortController;
86
- export declare function fetchProactiveAction(request: {
87
- account_id: string;
88
- sku?: string;
89
- page_type?: string;
90
- output_language?: string;
91
- mode?: string;
92
- }, transport: ChatTransportConfig): Promise<{
93
- title?: string;
94
- question?: string;
95
- actions?: unknown[];
96
- } | null>;
97
86
  //# sourceMappingURL=api.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/chat/api.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/chat/api.ts"],"names":[],"mappings":"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"}
@@ -64,12 +64,21 @@ export declare class ChatDrawer {
64
64
  private _voiceEnabled;
65
65
  private _voiceLang;
66
66
  private _ignoreNextDividerClick;
67
+ private readonly _cleanups;
68
+ private _focusTrapHandler;
69
+ private _previouslyFocusedElement;
70
+ private _stillWorkingTimer;
67
71
  constructor(container: HTMLElement, options: ChatDrawerOptions);
68
72
  addMessage(message: ChatMessage): void;
69
73
  showTypingIndicator(searchText?: string): void;
70
74
  /** Accumulate a new thinking step (shown as a checklist in the typing indicator). */
71
75
  addThinkingStep(text: string): void;
72
76
  removeTypingIndicator(): void;
77
+ private _clearStillWorkingTimer;
78
+ /** Show a "Stop generating" button below the typing indicator. */
79
+ showStopButton(onStop: () => void): void;
80
+ /** Remove the stop-generating button if present. */
81
+ hideStopButton(): void;
73
82
  showError(message?: string, onRetry?: () => void): void;
74
83
  clearMessages(): void;
75
84
  /** Replace suggestion pills. Pass empty array to hide. */
@@ -132,7 +141,6 @@ export declare class ChatDrawer {
132
141
  private _renderThinkingSteps;
133
142
  /** Render the accumulated thinking-step checklist into a container element. */
134
143
  private _renderThinkingStepsInto;
135
- private _trapFocus;
136
144
  private _submit;
137
145
  private _toggleVoice;
138
146
  /** Lock auto-scroll for 500ms after session history restore to prevent visual jump. */
@@ -157,5 +165,11 @@ export declare class ChatDrawer {
157
165
  clearInputAreaChips(): void;
158
166
  setThumbnails(entries: ThumbnailEntry[]): void;
159
167
  hideThumbnails(): void;
168
+ /** Activate focus trap — Tab/Shift+Tab cycles within the drawer. */
169
+ trapFocus(): void;
170
+ /** Release the focus trap and restore previously focused element. */
171
+ releaseFocus(): void;
172
+ /** Clean up event listeners and child resources (VoiceInput, timers). */
173
+ destroy(): void;
160
174
  }
161
175
  //# sourceMappingURL=ChatDrawer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ChatDrawer.d.ts","sourceRoot":"","sources":["../../../src/chat/components/ChatDrawer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ChatDrawer.d.ts","sourceRoot":"","sources":["../../../src/chat/components/ChatDrawer.ts"],"names":[],"mappings":"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"}
@@ -10,6 +10,7 @@ export interface ChoicePrompterOptions {
10
10
  ctaLabel: string;
11
11
  onCtaClick: () => void;
12
12
  onDismiss?: () => void;
13
+ dismissAriaLabel?: string;
13
14
  }
14
15
  export declare function createChoicePrompter(options: ChoicePrompterOptions): HTMLElement;
15
16
  export declare function isChoicePrompterDismissed(): boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"ChoicePrompter.d.ts","sourceRoot":"","sources":["../../../src/chat/components/ChoicePrompter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;CACxB;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,qBAAqB,GAAG,WAAW,CAsChF;AAED,wBAAgB,yBAAyB,IAAI,OAAO,CAMnD"}
1
+ {"version":3,"file":"ChoicePrompter.d.ts","sourceRoot":"","sources":["../../../src/chat/components/ChoicePrompter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,qBAAqB,GAAG,WAAW,CAsChF;AAED,wBAAgB,yBAAyB,IAAI,OAAO,CAMnD"}
@@ -1,10 +1,10 @@
1
1
  import { PriceFormatConfig } from '../../common/price-formatter.js';
2
2
  /**
3
3
  * Map a raw criteria field name to a human-readable label.
4
- * Uses the Turkish fallback map first, then falls back to a simple
5
- * formatting heuristic (replace underscores, capitalize first letter).
4
+ * Checks locale-specific `criteriaLabels` first (from i18n), then the
5
+ * built-in fallback map, then applies a formatting heuristic.
6
6
  */
7
- export declare function formatCriteriaName(rawName: string): string;
7
+ export declare function formatCriteriaName(rawName: string, criteriaLabels?: Record<string, string>): string;
8
8
  export interface ComparisonProduct {
9
9
  sku: string;
10
10
  name: string;
@@ -24,6 +24,8 @@ export interface ComparisonTableI18n {
24
24
  keyDifferencesLabel?: string;
25
25
  specialCasesLabel?: string;
26
26
  addToCartButton?: string;
27
+ /** Locale-specific attribute display names (e.g., { screen_size: 'Screen Size' }). */
28
+ criteriaLabels?: Record<string, string>;
27
29
  }
28
30
  export interface ComparisonTableOptions {
29
31
  recommended: ComparisonProduct;