@retrivora-ai/rag-engine 1.8.2 → 1.8.4

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 (49) hide show
  1. package/dist/handlers/index.js +142 -16
  2. package/dist/handlers/index.mjs +5848 -17
  3. package/dist/index.css +3162 -0
  4. package/dist/index.d.mts +9 -15
  5. package/dist/index.d.ts +9 -15
  6. package/dist/index.js +1355 -919
  7. package/dist/index.mjs +1437 -896
  8. package/dist/server.d.mts +6 -0
  9. package/dist/server.d.ts +6 -0
  10. package/dist/server.js +171 -17
  11. package/dist/server.mjs +5923 -68
  12. package/package.json +8 -6
  13. package/src/app/globals.css +35 -11
  14. package/src/components/ChatWidget.tsx +0 -1
  15. package/src/components/MarkdownComponents.tsx +3 -0
  16. package/src/components/MessageBubble.tsx +3 -2
  17. package/src/components/ObservabilityPanel.tsx +1 -1
  18. package/src/components/UIDispatcher.tsx +0 -3
  19. package/src/config/ConfigBuilder.ts +38 -1
  20. package/src/core/LangChainAgent.ts +1 -4
  21. package/src/core/Pipeline.ts +31 -18
  22. package/src/core/QueryProcessor.ts +65 -0
  23. package/src/rag/Reranker.ts +99 -6
  24. package/src/tailwind.css +2 -0
  25. package/src/utils/ProductExtractor.ts +3 -3
  26. package/dist/ChromaDBProvider-MIDOR4FW.mjs +0 -8
  27. package/dist/MilvusProvider-U7SKC27V.mjs +0 -8
  28. package/dist/MongoDBProvider-YNKC7EJ6.mjs +0 -8
  29. package/dist/MultiTablePostgresProvider-ZLGSKTJR.mjs +0 -8
  30. package/dist/PineconeProvider-QZNRKTN2.mjs +0 -8
  31. package/dist/QdrantProvider-RLJTNGPY.mjs +0 -8
  32. package/dist/RedisProvider-SR65SCKV.mjs +0 -8
  33. package/dist/SimpleGraphProvider-SLOXO4M7.mjs +0 -62
  34. package/dist/UniversalVectorProvider-IN67OS56.mjs +0 -9
  35. package/dist/WeaviateProvider-5FWDFITI.mjs +0 -8
  36. package/dist/chunk-5AJ4XHLW.mjs +0 -201
  37. package/dist/chunk-5YGUXK7Z.mjs +0 -80
  38. package/dist/chunk-CFVEZTBJ.mjs +0 -102
  39. package/dist/chunk-ICKRMZQK.mjs +0 -76
  40. package/dist/chunk-IMP6FUCY.mjs +0 -30
  41. package/dist/chunk-LR3VMDVK.mjs +0 -157
  42. package/dist/chunk-LZVVLSDN.mjs +0 -4077
  43. package/dist/chunk-M6JSPGAR.mjs +0 -117
  44. package/dist/chunk-OZFBG4BA.mjs +0 -291
  45. package/dist/chunk-PSFPZXHX.mjs +0 -245
  46. package/dist/chunk-U55XRW3U.mjs +0 -96
  47. package/dist/chunk-VUQJVIJT.mjs +0 -148
  48. package/dist/chunk-X4TOT24V.mjs +0 -89
  49. package/dist/chunk-YLTMFW4M.mjs +0 -49
package/dist/index.mjs CHANGED
@@ -1,22 +1,41 @@
1
- import {
2
- addSynonyms,
3
- resolveMetadataValue
4
- } from "./chunk-ICKRMZQK.mjs";
5
- import {
6
- mergeDefined
7
- } from "./chunk-YLTMFW4M.mjs";
8
- import {
9
- __objRest,
10
- __spreadProps,
11
- __spreadValues
12
- } from "./chunk-X4TOT24V.mjs";
1
+ var __defProp = Object.defineProperty;
2
+ var __defProps = Object.defineProperties;
3
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
4
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
7
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
8
+ var __spreadValues = (a, b) => {
9
+ for (var prop in b || (b = {}))
10
+ if (__hasOwnProp.call(b, prop))
11
+ __defNormalProp(a, prop, b[prop]);
12
+ if (__getOwnPropSymbols)
13
+ for (var prop of __getOwnPropSymbols(b)) {
14
+ if (__propIsEnum.call(b, prop))
15
+ __defNormalProp(a, prop, b[prop]);
16
+ }
17
+ return a;
18
+ };
19
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
20
+ var __objRest = (source, exclude) => {
21
+ var target = {};
22
+ for (var prop in source)
23
+ if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
24
+ target[prop] = source[prop];
25
+ if (source != null && __getOwnPropSymbols)
26
+ for (var prop of __getOwnPropSymbols(source)) {
27
+ if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
28
+ target[prop] = source[prop];
29
+ }
30
+ return target;
31
+ };
13
32
 
14
33
  // src/components/ChatWidget.tsx
15
- import React15, { useState as useState6 } from "react";
34
+ import { useState as useState6 } from "react";
16
35
  import { MessageSquare, X as X3 } from "lucide-react";
17
36
 
18
37
  // src/components/ChatWindow.tsx
19
- import React14, { useState as useState5, useRef as useRef4, useEffect as useEffect4, useCallback as useCallback2 } from "react";
38
+ import { useState as useState5, useRef as useRef4, useEffect as useEffect4, useCallback as useCallback2 } from "react";
20
39
  import {
21
40
  Bot as Bot2,
22
41
  Trash2,
@@ -33,11 +52,25 @@ import {
33
52
  } from "lucide-react";
34
53
 
35
54
  // src/components/DocumentUpload.tsx
36
- import React2, { useState, useRef } from "react";
55
+ import { useState, useRef } from "react";
37
56
  import { Upload, File, X, CheckCircle, AlertCircle, Loader2 } from "lucide-react";
38
57
 
39
58
  // src/components/ConfigProvider.tsx
40
- import React, { createContext, useContext } from "react";
59
+ import { createContext, useContext } from "react";
60
+
61
+ // src/utils/templateUtils.ts
62
+ function mergeDefined(base, override) {
63
+ const merged = __spreadValues({}, base || {});
64
+ if (!override) {
65
+ return merged;
66
+ }
67
+ for (const [key, value] of Object.entries(override)) {
68
+ if (value !== void 0 && value !== null && value !== "") {
69
+ merged[key] = value;
70
+ }
71
+ }
72
+ return merged;
73
+ }
41
74
 
42
75
  // src/config/uiConstants.ts
43
76
  var DEFAULT_CONFIG = {
@@ -75,6 +108,7 @@ var CHAT_SUGGESTIONS = [
75
108
  ];
76
109
 
77
110
  // src/components/ConfigProvider.tsx
111
+ import { jsx } from "react/jsx-runtime";
78
112
  var ConfigContext = createContext(DEFAULT_CONFIG);
79
113
  function ConfigProvider({
80
114
  config,
@@ -85,13 +119,14 @@ function ConfigProvider({
85
119
  ui: mergeDefined(DEFAULT_CONFIG.ui, config == null ? void 0 : config.ui),
86
120
  embedding: config == null ? void 0 : config.embedding
87
121
  };
88
- return /* @__PURE__ */ React.createElement(ConfigContext.Provider, { value: merged }, children);
122
+ return /* @__PURE__ */ jsx(ConfigContext.Provider, { value: merged, children });
89
123
  }
90
124
  function useConfig() {
91
125
  return useContext(ConfigContext);
92
126
  }
93
127
 
94
128
  // src/components/DocumentUpload.tsx
129
+ import { jsx as jsx2, jsxs } from "react/jsx-runtime";
95
130
  function DocumentUpload({ namespace, onUploadComplete, className = "" }) {
96
131
  var _a;
97
132
  const { ui, embedding } = useConfig();
@@ -162,92 +197,129 @@ function DocumentUpload({ namespace, onUploadComplete, className = "" }) {
162
197
  };
163
198
  const isUploading = fileStates.some((s) => s.status === "uploading");
164
199
  const hasIdle = fileStates.some((s) => s.status === "idle");
165
- return /* @__PURE__ */ React2.createElement(
200
+ return /* @__PURE__ */ jsxs(
166
201
  "div",
167
202
  {
168
203
  className: `p-6 border-2 border-dashed transition-all duration-300 rounded-2xl ${isDragging ? "border-emerald-500 bg-emerald-50/50 dark:bg-emerald-500/5" : "border-slate-200 dark:border-white/10 bg-white dark:bg-white/5"} ${className}`,
169
204
  onDragOver,
170
205
  onDragLeave,
171
- onDrop
172
- },
173
- /* @__PURE__ */ React2.createElement("div", { className: "flex flex-col items-center justify-center text-center" }, /* @__PURE__ */ React2.createElement(
174
- "div",
175
- {
176
- className: "w-12 h-12 rounded-full flex items-center justify-center mb-4 shadow-sm",
177
- style: { background: `linear-gradient(135deg, ${ui.primaryColor}20, ${ui.accentColor}20)` }
178
- },
179
- /* @__PURE__ */ React2.createElement(Upload, { className: "w-6 h-6", style: { color: ui.primaryColor } })
180
- ), /* @__PURE__ */ React2.createElement("h3", { className: "text-slate-900 dark:text-white font-semibold mb-1" }, "Upload Documents"), /* @__PURE__ */ React2.createElement("p", { className: "text-slate-500 dark:text-white/40 text-sm mb-6 max-w-xs" }, "Drag and drop PDF, DOCX, TXT, or JSON files to train your AI on your own data."), /* @__PURE__ */ React2.createElement(
181
- "button",
182
- {
183
- onClick: () => {
184
- var _a2;
185
- return (_a2 = fileInputRef.current) == null ? void 0 : _a2.click();
186
- },
187
- disabled: isUploading,
188
- className: "px-4 py-2 rounded-lg text-sm font-medium transition-all hover:scale-105 active:scale-95 disabled:opacity-50",
189
- style: {
190
- backgroundColor: `${ui.primaryColor}15`,
191
- color: ui.primaryColor,
192
- border: `1px solid ${ui.primaryColor}30`
193
- }
194
- },
195
- "Select Files"
196
- ), /* @__PURE__ */ React2.createElement(
197
- "input",
198
- {
199
- ref: fileInputRef,
200
- type: "file",
201
- multiple: true,
202
- onChange: onFileSelect,
203
- className: "hidden",
204
- accept: ".pdf,.docx,.txt,.md,.json,.csv"
205
- }
206
- ), /* @__PURE__ */ React2.createElement("div", { className: "mt-6 flex flex-col items-center gap-2 text-sm" }, /* @__PURE__ */ React2.createElement("label", { className: "text-slate-600 dark:text-white/60 font-medium" }, "Embedding Dimension"), isChangeable ? /* @__PURE__ */ React2.createElement(
207
- "select",
208
- {
209
- value: dimension,
210
- onChange: (e) => setDimension(Number(e.target.value)),
211
- disabled: isUploading,
212
- className: "px-3 py-1.5 rounded-lg bg-slate-50 dark:bg-white/5 border border-slate-200 dark:border-white/10 text-slate-800 dark:text-white/90 outline-none focus:border-emerald-500 transition-colors"
213
- },
214
- availableDimensions.map((dim) => /* @__PURE__ */ React2.createElement("option", { key: dim, value: dim, className: "bg-white dark:bg-slate-900" }, dim))
215
- ) : /* @__PURE__ */ React2.createElement("div", { className: "px-3 py-1.5 rounded-lg bg-slate-100 dark:bg-white/10 border border-slate-200 dark:border-white/10 text-slate-500 dark:text-white/50 cursor-not-allowed text-xs" }, dimension, " (Fixed for ", currentModel, ")"))),
216
- fileStates.length > 0 && /* @__PURE__ */ React2.createElement("div", { className: "mt-8 space-y-3" }, fileStates.map((state, i) => /* @__PURE__ */ React2.createElement(
217
- "div",
218
- {
219
- key: i,
220
- className: "flex items-center justify-between p-3 rounded-xl bg-slate-50 dark:bg-white/5 border border-slate-100 dark:border-white/10"
221
- },
222
- /* @__PURE__ */ React2.createElement("div", { className: "flex items-center gap-3 overflow-hidden" }, /* @__PURE__ */ React2.createElement("div", { className: "w-8 h-8 rounded-lg bg-white dark:bg-white/10 flex items-center justify-center shadow-sm" }, /* @__PURE__ */ React2.createElement(File, { className: "w-4 h-4 text-slate-400" })), /* @__PURE__ */ React2.createElement("div", { className: "truncate" }, /* @__PURE__ */ React2.createElement("p", { className: "text-xs font-medium text-slate-700 dark:text-white/80 truncate" }, state.file.name), /* @__PURE__ */ React2.createElement("p", { className: "text-[10px] text-slate-400" }, (state.file.size / 1024).toFixed(1), " KB"))),
223
- /* @__PURE__ */ React2.createElement("div", { className: "flex items-center gap-2" }, state.status === "uploading" && /* @__PURE__ */ React2.createElement(Loader2, { className: "w-4 h-4 text-slate-400 animate-spin" }), state.status === "success" && /* @__PURE__ */ React2.createElement(CheckCircle, { className: "w-4 h-4 text-emerald-500" }), state.status === "error" && /* @__PURE__ */ React2.createElement("div", { title: state.error }, /* @__PURE__ */ React2.createElement(AlertCircle, { className: "w-4 h-4 text-rose-500" })), state.status !== "uploading" && /* @__PURE__ */ React2.createElement(
224
- "button",
225
- {
226
- onClick: () => removeFile(i),
227
- className: "p-1 rounded-md hover:bg-slate-200 dark:hover:bg-white/10 transition-colors"
228
- },
229
- /* @__PURE__ */ React2.createElement(X, { className: "w-3.5 h-3.5 text-slate-400" })
230
- ))
231
- )), hasIdle && !isUploading && /* @__PURE__ */ React2.createElement(
232
- "button",
233
- {
234
- onClick: uploadFiles,
235
- className: "w-full mt-4 py-2.5 rounded-xl text-sm font-semibold text-white shadow-lg transition-all hover:scale-[1.02] active:scale-[0.98]",
236
- style: { background: `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` }
237
- },
238
- "Start Upload"
239
- ))
206
+ onDrop,
207
+ children: [
208
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center text-center", children: [
209
+ /* @__PURE__ */ jsx2(
210
+ "div",
211
+ {
212
+ className: "w-12 h-12 rounded-full flex items-center justify-center mb-4 shadow-sm",
213
+ style: { background: `linear-gradient(135deg, ${ui.primaryColor}20, ${ui.accentColor}20)` },
214
+ children: /* @__PURE__ */ jsx2(Upload, { className: "w-6 h-6", style: { color: ui.primaryColor } })
215
+ }
216
+ ),
217
+ /* @__PURE__ */ jsx2("h3", { className: "text-slate-900 dark:text-white font-semibold mb-1", children: "Upload Documents" }),
218
+ /* @__PURE__ */ jsx2("p", { className: "text-slate-500 dark:text-white/40 text-sm mb-6 max-w-xs", children: "Drag and drop PDF, DOCX, TXT, or JSON files to train your AI on your own data." }),
219
+ /* @__PURE__ */ jsx2(
220
+ "button",
221
+ {
222
+ onClick: () => {
223
+ var _a2;
224
+ return (_a2 = fileInputRef.current) == null ? void 0 : _a2.click();
225
+ },
226
+ disabled: isUploading,
227
+ className: "px-4 py-2 rounded-lg text-sm font-medium transition-all hover:scale-105 active:scale-95 disabled:opacity-50",
228
+ style: {
229
+ backgroundColor: `${ui.primaryColor}15`,
230
+ color: ui.primaryColor,
231
+ border: `1px solid ${ui.primaryColor}30`
232
+ },
233
+ children: "Select Files"
234
+ }
235
+ ),
236
+ /* @__PURE__ */ jsx2(
237
+ "input",
238
+ {
239
+ ref: fileInputRef,
240
+ type: "file",
241
+ multiple: true,
242
+ onChange: onFileSelect,
243
+ className: "hidden",
244
+ accept: ".pdf,.docx,.txt,.md,.json,.csv"
245
+ }
246
+ ),
247
+ /* @__PURE__ */ jsxs("div", { className: "mt-6 flex flex-col items-center gap-2 text-sm", children: [
248
+ /* @__PURE__ */ jsx2("label", { className: "text-slate-600 dark:text-white/60 font-medium", children: "Embedding Dimension" }),
249
+ isChangeable ? /* @__PURE__ */ jsx2(
250
+ "select",
251
+ {
252
+ value: dimension,
253
+ onChange: (e) => setDimension(Number(e.target.value)),
254
+ disabled: isUploading,
255
+ className: "px-3 py-1.5 rounded-lg bg-slate-50 dark:bg-white/5 border border-slate-200 dark:border-white/10 text-slate-800 dark:text-white/90 outline-none focus:border-emerald-500 transition-colors",
256
+ children: availableDimensions.map((dim) => /* @__PURE__ */ jsx2("option", { value: dim, className: "bg-white dark:bg-slate-900", children: dim }, dim))
257
+ }
258
+ ) : /* @__PURE__ */ jsxs("div", { className: "px-3 py-1.5 rounded-lg bg-slate-100 dark:bg-white/10 border border-slate-200 dark:border-white/10 text-slate-500 dark:text-white/50 cursor-not-allowed text-xs", children: [
259
+ dimension,
260
+ " (Fixed for ",
261
+ currentModel,
262
+ ")"
263
+ ] })
264
+ ] })
265
+ ] }),
266
+ fileStates.length > 0 && /* @__PURE__ */ jsxs("div", { className: "mt-8 space-y-3", children: [
267
+ fileStates.map((state, i) => /* @__PURE__ */ jsxs(
268
+ "div",
269
+ {
270
+ className: "flex items-center justify-between p-3 rounded-xl bg-slate-50 dark:bg-white/5 border border-slate-100 dark:border-white/10",
271
+ children: [
272
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 overflow-hidden", children: [
273
+ /* @__PURE__ */ jsx2("div", { className: "w-8 h-8 rounded-lg bg-white dark:bg-white/10 flex items-center justify-center shadow-sm", children: /* @__PURE__ */ jsx2(File, { className: "w-4 h-4 text-slate-400" }) }),
274
+ /* @__PURE__ */ jsxs("div", { className: "truncate", children: [
275
+ /* @__PURE__ */ jsx2("p", { className: "text-xs font-medium text-slate-700 dark:text-white/80 truncate", children: state.file.name }),
276
+ /* @__PURE__ */ jsxs("p", { className: "text-[10px] text-slate-400", children: [
277
+ (state.file.size / 1024).toFixed(1),
278
+ " KB"
279
+ ] })
280
+ ] })
281
+ ] }),
282
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
283
+ state.status === "uploading" && /* @__PURE__ */ jsx2(Loader2, { className: "w-4 h-4 text-slate-400 animate-spin" }),
284
+ state.status === "success" && /* @__PURE__ */ jsx2(CheckCircle, { className: "w-4 h-4 text-emerald-500" }),
285
+ state.status === "error" && /* @__PURE__ */ jsx2("div", { title: state.error, children: /* @__PURE__ */ jsx2(AlertCircle, { className: "w-4 h-4 text-rose-500" }) }),
286
+ state.status !== "uploading" && /* @__PURE__ */ jsx2(
287
+ "button",
288
+ {
289
+ onClick: () => removeFile(i),
290
+ className: "p-1 rounded-md hover:bg-slate-200 dark:hover:bg-white/10 transition-colors",
291
+ children: /* @__PURE__ */ jsx2(X, { className: "w-3.5 h-3.5 text-slate-400" })
292
+ }
293
+ )
294
+ ] })
295
+ ]
296
+ },
297
+ i
298
+ )),
299
+ hasIdle && !isUploading && /* @__PURE__ */ jsx2(
300
+ "button",
301
+ {
302
+ onClick: uploadFiles,
303
+ className: "w-full mt-4 py-2.5 rounded-xl text-sm font-semibold text-white shadow-lg transition-all hover:scale-[1.02] active:scale-[0.98]",
304
+ style: { background: `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` },
305
+ children: "Start Upload"
306
+ }
307
+ )
308
+ ] })
309
+ ]
310
+ }
240
311
  );
241
312
  }
242
313
 
243
314
  // src/components/MessageBubble.tsx
244
- import React12 from "react";
315
+ import React9 from "react";
245
316
  import { Bot, User, ChevronDown as ChevronDown3, ChevronRight as ChevronRight3, Activity } from "lucide-react";
246
317
  import ReactMarkdown from "react-markdown";
247
318
 
248
319
  // src/components/SourceCard.tsx
249
320
  import React3 from "react";
250
321
  import { ChevronDown, ChevronUp } from "lucide-react";
322
+ import { Fragment, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
251
323
  function SourceCard({ source, index }) {
252
324
  var _a, _b;
253
325
  const [expanded, setExpanded] = React3.useState(false);
@@ -256,58 +328,94 @@ function SourceCard({ source, index }) {
256
328
  const scoreBg = source.score >= 0.8 ? "bg-emerald-50 border-emerald-100 dark:bg-emerald-400/10 dark:border-emerald-400/20" : source.score >= 0.6 ? "bg-amber-50 border-amber-100 dark:bg-amber-400/10 dark:border-amber-400/20" : "bg-rose-50 border-rose-100 dark:bg-rose-400/10 dark:border-rose-400/20";
257
329
  const preview = source.content.slice(0, 120);
258
330
  const hasMore = source.content.length > 120;
259
- return /* @__PURE__ */ React3.createElement(
331
+ return /* @__PURE__ */ jsxs2(
260
332
  "div",
261
333
  {
262
334
  className: `rounded-xl border backdrop-blur-sm p-3 transition-all duration-200 hover:scale-[1.01] cursor-pointer ${scoreBg}`,
263
- onClick: () => setExpanded((e) => !e)
264
- },
265
- /* @__PURE__ */ React3.createElement("div", { className: "flex items-start justify-between gap-2" }, /* @__PURE__ */ React3.createElement("div", { className: "flex items-center gap-2 min-w-0" }, /* @__PURE__ */ React3.createElement("span", { className: "flex-shrink-0 w-5 h-5 rounded-full bg-slate-200 dark:bg-white/10 flex items-center justify-center text-[10px] font-bold text-slate-500 dark:text-white/60" }, index + 1), /* @__PURE__ */ React3.createElement("span", { className: "text-xs text-slate-500 dark:text-white/50 truncate font-mono" }, (_b = (_a = source.metadata) == null ? void 0 : _a.docId) != null ? _b : source.id)), /* @__PURE__ */ React3.createElement("span", { className: `flex-shrink-0 text-xs font-semibold ${scoreColor} tabular-nums` }, scorePercent, "%")),
266
- /* @__PURE__ */ React3.createElement("p", { className: "mt-2 text-xs text-slate-600 dark:text-white/70 leading-relaxed" }, expanded ? source.content : `${preview}${hasMore && !expanded ? "\u2026" : ""}`),
267
- hasMore && /* @__PURE__ */ React3.createElement("button", { className: "mt-1 text-[10px] text-indigo-400 hover:text-indigo-300 transition-colors flex items-center gap-0.5" }, expanded ? /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement(ChevronUp, { className: "w-3 h-3" }), " Show less") : /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement(ChevronDown, { className: "w-3 h-3" }), " Show more"))
335
+ onClick: () => setExpanded((e) => !e),
336
+ children: [
337
+ /* @__PURE__ */ jsxs2("div", { className: "flex items-start justify-between gap-2", children: [
338
+ /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-2 min-w-0", children: [
339
+ /* @__PURE__ */ jsx3("span", { className: "flex-shrink-0 w-5 h-5 rounded-full bg-slate-200 dark:bg-white/10 flex items-center justify-center text-[10px] font-bold text-slate-500 dark:text-white/60", children: index + 1 }),
340
+ /* @__PURE__ */ jsx3("span", { className: "text-xs text-slate-500 dark:text-white/50 truncate font-mono", children: (_b = (_a = source.metadata) == null ? void 0 : _a.docId) != null ? _b : source.id })
341
+ ] }),
342
+ /* @__PURE__ */ jsxs2("span", { className: `flex-shrink-0 text-xs font-semibold ${scoreColor} tabular-nums`, children: [
343
+ scorePercent,
344
+ "%"
345
+ ] })
346
+ ] }),
347
+ /* @__PURE__ */ jsx3("p", { className: "mt-2 text-xs text-slate-600 dark:text-white/70 leading-relaxed", children: expanded ? source.content : `${preview}${hasMore && !expanded ? "\u2026" : ""}` }),
348
+ hasMore && /* @__PURE__ */ jsx3("button", { className: "mt-1 text-[10px] text-indigo-400 hover:text-indigo-300 transition-colors flex items-center gap-0.5", children: expanded ? /* @__PURE__ */ jsxs2(Fragment, { children: [
349
+ /* @__PURE__ */ jsx3(ChevronUp, { className: "w-3 h-3" }),
350
+ " Show less"
351
+ ] }) : /* @__PURE__ */ jsxs2(Fragment, { children: [
352
+ /* @__PURE__ */ jsx3(ChevronDown, { className: "w-3 h-3" }),
353
+ " Show more"
354
+ ] }) })
355
+ ]
356
+ }
268
357
  );
269
358
  }
270
359
 
271
360
  // src/components/ProductCarousel.tsx
272
- import React5, { useRef as useRef2, useState as useState2, useEffect } from "react";
361
+ import { useRef as useRef2, useState as useState2, useEffect } from "react";
273
362
  import { ChevronLeft, ChevronRight } from "lucide-react";
274
363
 
275
364
  // src/components/ProductCard.tsx
276
- import React4 from "react";
277
365
  import Image from "next/image";
278
366
  import { ShoppingCart, ExternalLink } from "lucide-react";
367
+ import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
279
368
  function ProductCard({ product, primaryColor = "#6366f1", onAddToCart }) {
280
- return /* @__PURE__ */ React4.createElement("div", { className: "flex-shrink-0 w-full bg-white dark:bg-white/5 border border-slate-200 dark:border-white/10 rounded-xl overflow-hidden shadow-sm hover:shadow-md transition-all duration-300 group" }, /* @__PURE__ */ React4.createElement("div", { className: "relative h-40 w-full bg-slate-100 dark:bg-white/5 flex items-center justify-center overflow-hidden" }, product.image ? /* @__PURE__ */ React4.createElement(
281
- Image,
282
- {
283
- src: product.image,
284
- alt: product.name,
285
- fill: true,
286
- unoptimized: true,
287
- className: "object-cover group-hover:scale-105 transition-transform duration-500"
288
- }
289
- ) : /* @__PURE__ */ React4.createElement("div", { className: "text-slate-400 dark:text-white/20" }, /* @__PURE__ */ React4.createElement(ShoppingCart, { className: "w-12 h-12" })), product.brand && /* @__PURE__ */ React4.createElement("div", { className: "absolute top-2 left-2 px-2 py-1 bg-white/90 dark:bg-black/60 backdrop-blur-md rounded-md text-[10px] font-bold uppercase tracking-wider text-slate-700 dark:text-white/90 shadow-sm" }, product.brand)), /* @__PURE__ */ React4.createElement("div", { className: "p-4 flex flex-col gap-2" }, /* @__PURE__ */ React4.createElement("div", { className: "flex justify-between items-start gap-2" }, /* @__PURE__ */ React4.createElement("h3", { className: "text-sm font-semibold text-slate-800 dark:text-white/90 line-clamp-1" }, product.name), product.price && /* @__PURE__ */ React4.createElement("span", { className: "text-sm font-bold", style: { color: primaryColor } }, typeof product.price === "number" ? `$${product.price}` : String(product.price).match(/^[\d.]/) ? `$${product.price}` : product.price)), product.description && /* @__PURE__ */ React4.createElement("p", { className: "text-[11px] text-slate-500 dark:text-white/50 line-clamp-2 leading-relaxed" }, product.description), /* @__PURE__ */ React4.createElement("div", { className: "mt-2 flex gap-2" }, /* @__PURE__ */ React4.createElement(
290
- "button",
291
- {
292
- onClick: () => onAddToCart == null ? void 0 : onAddToCart(product),
293
- className: "flex-1 py-2 px-3 rounded-lg text-[11px] font-medium text-white shadow-sm hover:opacity-90 transition-opacity flex items-center justify-center gap-1.5",
294
- style: { background: primaryColor }
295
- },
296
- /* @__PURE__ */ React4.createElement(ShoppingCart, { className: "w-3 h-3" }),
297
- "Add to Cart"
298
- ), product.link && /* @__PURE__ */ React4.createElement(
299
- "a",
300
- {
301
- href: product.link,
302
- target: "_blank",
303
- rel: "noopener noreferrer",
304
- className: "p-2 rounded-lg bg-slate-100 dark:bg-white/10 text-slate-600 dark:text-white/70 hover:bg-slate-200 dark:hover:bg-white/20 transition-colors"
305
- },
306
- /* @__PURE__ */ React4.createElement(ExternalLink, { className: "w-3.5 h-3.5" })
307
- ))));
369
+ return /* @__PURE__ */ jsxs3("div", { className: "flex-shrink-0 w-full bg-white dark:bg-white/5 border border-slate-200 dark:border-white/10 rounded-xl overflow-hidden shadow-sm hover:shadow-md transition-all duration-300 group", children: [
370
+ /* @__PURE__ */ jsxs3("div", { className: "relative h-40 w-full bg-slate-100 dark:bg-white/5 flex items-center justify-center overflow-hidden", children: [
371
+ product.image ? /* @__PURE__ */ jsx4(
372
+ Image,
373
+ {
374
+ src: product.image,
375
+ alt: product.name,
376
+ fill: true,
377
+ unoptimized: true,
378
+ className: "object-cover group-hover:scale-105 transition-transform duration-500"
379
+ }
380
+ ) : /* @__PURE__ */ jsx4("div", { className: "text-slate-400 dark:text-white/20", children: /* @__PURE__ */ jsx4(ShoppingCart, { className: "w-12 h-12" }) }),
381
+ product.brand && /* @__PURE__ */ jsx4("div", { className: "absolute top-2 left-2 px-2 py-1 bg-white/90 dark:bg-black/60 backdrop-blur-md rounded-md text-[10px] font-bold uppercase tracking-wider text-slate-700 dark:text-white/90 shadow-sm", children: product.brand })
382
+ ] }),
383
+ /* @__PURE__ */ jsxs3("div", { className: "p-4 flex flex-col gap-2", children: [
384
+ /* @__PURE__ */ jsxs3("div", { className: "flex justify-between items-start gap-2", children: [
385
+ /* @__PURE__ */ jsx4("h3", { className: "text-sm font-semibold text-slate-800 dark:text-white/90 line-clamp-1", children: product.name }),
386
+ product.price && /* @__PURE__ */ jsx4("span", { className: "text-sm font-bold", style: { color: primaryColor }, children: typeof product.price === "number" ? `$${product.price}` : String(product.price).match(/^[\d.]/) ? `$${product.price}` : product.price })
387
+ ] }),
388
+ product.description && /* @__PURE__ */ jsx4("p", { className: "text-[11px] text-slate-500 dark:text-white/50 line-clamp-2 leading-relaxed", children: product.description }),
389
+ /* @__PURE__ */ jsxs3("div", { className: "mt-2 flex gap-2", children: [
390
+ /* @__PURE__ */ jsxs3(
391
+ "button",
392
+ {
393
+ onClick: () => onAddToCart == null ? void 0 : onAddToCart(product),
394
+ className: "flex-1 py-2 px-3 rounded-lg text-[11px] font-medium text-white shadow-sm hover:opacity-90 transition-opacity flex items-center justify-center gap-1.5",
395
+ style: { background: primaryColor },
396
+ children: [
397
+ /* @__PURE__ */ jsx4(ShoppingCart, { className: "w-3 h-3" }),
398
+ "Add to Cart"
399
+ ]
400
+ }
401
+ ),
402
+ product.link && /* @__PURE__ */ jsx4(
403
+ "a",
404
+ {
405
+ href: product.link,
406
+ target: "_blank",
407
+ rel: "noopener noreferrer",
408
+ className: "p-2 rounded-lg bg-slate-100 dark:bg-white/10 text-slate-600 dark:text-white/70 hover:bg-slate-200 dark:hover:bg-white/20 transition-colors",
409
+ children: /* @__PURE__ */ jsx4(ExternalLink, { className: "w-3.5 h-3.5" })
410
+ }
411
+ )
412
+ ] })
413
+ ] })
414
+ ] });
308
415
  }
309
416
 
310
417
  // src/components/ProductCarousel.tsx
418
+ import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
311
419
  function ProductCarousel({ products, primaryColor = "#6366f1", onAddToCart }) {
312
420
  const scrollRef = useRef2(null);
313
421
  const [canScroll, setCanScroll] = useState2(false);
@@ -335,50 +443,55 @@ function ProductCarousel({ products, primaryColor = "#6366f1", onAddToCart }) {
335
443
  };
336
444
  if (!products || products.length === 0) return null;
337
445
  if (products.length === 1) {
338
- return /* @__PURE__ */ React5.createElement("div", { className: "my-4 w-[min(88%,18rem)] min-w-0 max-w-full animate-fade-in-up" }, /* @__PURE__ */ React5.createElement(ProductCard, { product: products[0], primaryColor, onAddToCart }));
446
+ return /* @__PURE__ */ jsx5("div", { className: "my-4 w-[min(88%,18rem)] min-w-0 max-w-full animate-fade-in-up", children: /* @__PURE__ */ jsx5(ProductCard, { product: products[0], primaryColor, onAddToCart }) });
339
447
  }
340
- return /* @__PURE__ */ React5.createElement("div", { className: "relative w-full my-4 group/carousel animate-fade-in-up" }, canScroll && /* @__PURE__ */ React5.createElement(React5.Fragment, null, /* @__PURE__ */ React5.createElement("div", { className: "absolute -left-4 top-1/2 -translate-y-1/2 z-20 opacity-100 md:opacity-0 md:group-hover/carousel:opacity-100 transition-opacity" }, /* @__PURE__ */ React5.createElement(
341
- "button",
342
- {
343
- onClick: (e) => {
344
- e.stopPropagation();
345
- scroll("left");
346
- },
347
- className: "p-2 rounded-full bg-white dark:bg-slate-800 shadow-xl border border-slate-200 dark:border-white/10 text-slate-600 dark:text-white/80 hover:text-indigo-500 dark:hover:text-indigo-400 transition-all hover:scale-110 active:scale-95",
348
- "aria-label": "Scroll left"
349
- },
350
- /* @__PURE__ */ React5.createElement(ChevronLeft, { className: "w-5 h-5" })
351
- )), /* @__PURE__ */ React5.createElement("div", { className: "absolute -right-4 top-1/2 -translate-y-1/2 z-20 opacity-100 md:opacity-0 md:group-hover/carousel:opacity-100 transition-opacity" }, /* @__PURE__ */ React5.createElement(
352
- "button",
353
- {
354
- onClick: (e) => {
355
- e.stopPropagation();
356
- scroll("right");
357
- },
358
- className: "p-2 rounded-full bg-white dark:bg-slate-800 shadow-xl border border-slate-200 dark:border-white/10 text-slate-600 dark:text-white/80 hover:text-indigo-500 dark:hover:text-indigo-400 transition-all hover:scale-110 active:scale-95",
359
- "aria-label": "Scroll right"
360
- },
361
- /* @__PURE__ */ React5.createElement(ChevronRight, { className: "w-5 h-5" })
362
- ))), /* @__PURE__ */ React5.createElement(
363
- "div",
364
- {
365
- ref: scrollRef,
366
- className: "flex gap-4 overflow-x-auto pb-4 px-1 scrollbar-hide snap-x snap-mandatory",
367
- style: { scrollbarWidth: "none", msOverflowStyle: "none" }
368
- },
369
- products.map((product) => /* @__PURE__ */ React5.createElement(
448
+ return /* @__PURE__ */ jsxs4("div", { className: "relative w-full my-4 group/carousel animate-fade-in-up", children: [
449
+ canScroll && /* @__PURE__ */ jsxs4(Fragment2, { children: [
450
+ /* @__PURE__ */ jsx5("div", { className: "absolute -left-4 top-1/2 -translate-y-1/2 z-20 opacity-100 md:opacity-0 md:group-hover/carousel:opacity-100 transition-opacity", children: /* @__PURE__ */ jsx5(
451
+ "button",
452
+ {
453
+ onClick: (e) => {
454
+ e.stopPropagation();
455
+ scroll("left");
456
+ },
457
+ className: "p-2 rounded-full bg-white dark:bg-slate-800 shadow-xl border border-slate-200 dark:border-white/10 text-slate-600 dark:text-white/80 hover:text-indigo-500 dark:hover:text-indigo-400 transition-all hover:scale-110 active:scale-95",
458
+ "aria-label": "Scroll left",
459
+ children: /* @__PURE__ */ jsx5(ChevronLeft, { className: "w-5 h-5" })
460
+ }
461
+ ) }),
462
+ /* @__PURE__ */ jsx5("div", { className: "absolute -right-4 top-1/2 -translate-y-1/2 z-20 opacity-100 md:opacity-0 md:group-hover/carousel:opacity-100 transition-opacity", children: /* @__PURE__ */ jsx5(
463
+ "button",
464
+ {
465
+ onClick: (e) => {
466
+ e.stopPropagation();
467
+ scroll("right");
468
+ },
469
+ className: "p-2 rounded-full bg-white dark:bg-slate-800 shadow-xl border border-slate-200 dark:border-white/10 text-slate-600 dark:text-white/80 hover:text-indigo-500 dark:hover:text-indigo-400 transition-all hover:scale-110 active:scale-95",
470
+ "aria-label": "Scroll right",
471
+ children: /* @__PURE__ */ jsx5(ChevronRight, { className: "w-5 h-5" })
472
+ }
473
+ ) })
474
+ ] }),
475
+ /* @__PURE__ */ jsx5(
370
476
  "div",
371
477
  {
372
- key: product.id,
373
- className: "snap-start flex-shrink-0 w-[min(88%,18rem)] min-w-[11rem] max-w-full"
374
- },
375
- /* @__PURE__ */ React5.createElement(ProductCard, { product, primaryColor, onAddToCart })
376
- ))
377
- ));
478
+ ref: scrollRef,
479
+ className: "flex gap-4 overflow-x-auto pb-4 px-1 scrollbar-hide snap-x snap-mandatory",
480
+ style: { scrollbarWidth: "none", msOverflowStyle: "none" },
481
+ children: products.map((product) => /* @__PURE__ */ jsx5(
482
+ "div",
483
+ {
484
+ className: "snap-start flex-shrink-0 w-[min(88%,18rem)] min-w-[11rem] max-w-full",
485
+ children: /* @__PURE__ */ jsx5(ProductCard, { product, primaryColor, onAddToCart })
486
+ },
487
+ product.id
488
+ ))
489
+ }
490
+ )
491
+ ] });
378
492
  }
379
493
 
380
494
  // src/components/VisualizationRenderer.tsx
381
- import React7 from "react";
382
495
  import {
383
496
  PieChart as PieChart2,
384
497
  Pie as Pie2,
@@ -401,7 +514,7 @@ import {
401
514
  } from "recharts";
402
515
 
403
516
  // src/components/DynamicChart.tsx
404
- import React6 from "react";
517
+ import React5 from "react";
405
518
  import {
406
519
  BarChart,
407
520
  Bar,
@@ -417,6 +530,7 @@ import {
417
530
  Legend,
418
531
  ResponsiveContainer
419
532
  } from "recharts";
533
+ import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
420
534
  var CHART_COLORS = ["#6366f1", "#10b981", "#f59e0b", "#ef4444", "#8b5cf6", "#ec4899"];
421
535
  function DynamicChart({
422
536
  config,
@@ -427,9 +541,9 @@ function DynamicChart({
427
541
  }) {
428
542
  const { type, data } = config;
429
543
  const colors = config.colors || [primaryColor, accentColor, ...CHART_COLORS];
430
- const containerRef = React6.useRef(null);
431
- const [containerWidth, setContainerWidth] = React6.useState(0);
432
- React6.useEffect(() => {
544
+ const containerRef = React5.useRef(null);
545
+ const [containerWidth, setContainerWidth] = React5.useState(0);
546
+ React5.useEffect(() => {
433
547
  const element = containerRef.current;
434
548
  if (!element || typeof ResizeObserver === "undefined") return;
435
549
  const updateWidth = (width) => {
@@ -455,7 +569,7 @@ function DynamicChart({
455
569
  return text.length > maxLength ? `${text.slice(0, maxLength)}\u2026` : text;
456
570
  };
457
571
  const chartMargin = isTiny ? { top: 8, right: 4, left: -28, bottom: 0 } : isCompact ? { top: 10, right: 6, left: -24, bottom: 0 } : { top: 10, right: 10, left: -20, bottom: 0 };
458
- const sanitizedData = React6.useMemo(() => {
572
+ const sanitizedData = React5.useMemo(() => {
459
573
  if (!data) return [];
460
574
  return data.map((item) => {
461
575
  const newItem = {};
@@ -489,17 +603,17 @@ function DynamicChart({
489
603
  }, [data]);
490
604
  if (isStreaming) {
491
605
  const bars = type === "pie" ? 6 : 5;
492
- return /* @__PURE__ */ React6.createElement("div", { className: "w-full mt-4 mb-2 animate-pulse" }, type === "pie" ? /* @__PURE__ */ React6.createElement("div", { className: "mx-auto w-40 h-40 rounded-full bg-slate-100 dark:bg-white/10" }) : /* @__PURE__ */ React6.createElement("div", { className: "flex items-end gap-2 h-32 px-2" }, Array.from({ length: bars }).map((_, i) => /* @__PURE__ */ React6.createElement(
606
+ return /* @__PURE__ */ jsx6("div", { className: "w-full mt-4 mb-2 animate-pulse", children: type === "pie" ? /* @__PURE__ */ jsx6("div", { className: "mx-auto w-40 h-40 rounded-full bg-slate-100 dark:bg-white/10" }) : /* @__PURE__ */ jsx6("div", { className: "flex items-end gap-2 h-32 px-2", children: Array.from({ length: bars }).map((_, i) => /* @__PURE__ */ jsx6(
493
607
  "div",
494
608
  {
495
- key: i,
496
609
  className: "flex-1 rounded-t-md bg-slate-100 dark:bg-white/10",
497
610
  style: { height: `${40 + i % 3 * 25}%` }
498
- }
499
- ))));
611
+ },
612
+ i
613
+ )) }) });
500
614
  }
501
615
  if (!data || data.length === 0) {
502
- return /* @__PURE__ */ React6.createElement("div", { className: "p-4 text-sm text-slate-500" }, "No data available for chart.");
616
+ return /* @__PURE__ */ jsx6("div", { className: "p-4 text-sm text-slate-500", children: "No data available for chart." });
503
617
  }
504
618
  const firstItem = sanitizedData[0];
505
619
  const allKeys = Object.keys(firstItem);
@@ -524,14 +638,20 @@ function DynamicChart({
524
638
  const renderTooltip = (row, label) => {
525
639
  var _a, _b;
526
640
  if (!row) return null;
527
- return /* @__PURE__ */ React6.createElement("div", { className: "rounded-xl border border-slate-200 bg-white px-3 py-2 text-xs shadow-xl dark:border-white/10 dark:bg-slate-950" }, /* @__PURE__ */ React6.createElement("p", { className: "mb-2 font-semibold text-slate-800 dark:text-white/90" }, String((_b = (_a = row[finalXKey]) != null ? _a : label) != null ? _b : "Details")), Object.entries(row).map(([key, value]) => {
528
- var _a2;
529
- if (value === null || value === void 0 || key === finalXKey) return null;
530
- if (typeof value === "object") return null;
531
- const forbiddenKeys = ["fill", "color", "payload", "percent", "stroke", "inStock"];
532
- if (forbiddenKeys.includes(key)) return null;
533
- return /* @__PURE__ */ React6.createElement("div", { key, className: "flex items-center justify-between gap-3 text-slate-600 dark:text-white/70" }, /* @__PURE__ */ React6.createElement("span", null, (_a2 = tooltipLabelMap[key]) != null ? _a2 : key), /* @__PURE__ */ React6.createElement("span", { className: "font-medium text-slate-900 dark:text-white/90" }, String(value)));
534
- }));
641
+ return /* @__PURE__ */ jsxs5("div", { className: "rounded-xl border border-slate-200 bg-white px-3 py-2 text-xs shadow-xl dark:border-white/10 dark:bg-slate-950", children: [
642
+ /* @__PURE__ */ jsx6("p", { className: "mb-2 font-semibold text-slate-800 dark:text-white/90", children: String((_b = (_a = row[finalXKey]) != null ? _a : label) != null ? _b : "Details") }),
643
+ Object.entries(row).map(([key, value]) => {
644
+ var _a2;
645
+ if (value === null || value === void 0 || key === finalXKey) return null;
646
+ if (typeof value === "object") return null;
647
+ const forbiddenKeys = ["fill", "color", "payload", "percent", "stroke", "inStock"];
648
+ if (forbiddenKeys.includes(key)) return null;
649
+ return /* @__PURE__ */ jsxs5("div", { className: "flex items-center justify-between gap-3 text-slate-600 dark:text-white/70", children: [
650
+ /* @__PURE__ */ jsx6("span", { children: (_a2 = tooltipLabelMap[key]) != null ? _a2 : key }),
651
+ /* @__PURE__ */ jsx6("span", { className: "font-medium text-slate-900 dark:text-white/90", children: String(value) })
652
+ ] }, key);
653
+ })
654
+ ] });
535
655
  };
536
656
  const getTooltipRow = (payload) => {
537
657
  if (!Array.isArray(payload) || payload.length === 0) return null;
@@ -542,45 +662,64 @@ function DynamicChart({
542
662
  return row;
543
663
  };
544
664
  if (type === "pie") {
545
- return /* @__PURE__ */ React6.createElement("div", { ref: containerRef, className: "w-full min-w-0 mt-4 mb-2 select-none overflow-hidden" }, /* @__PURE__ */ React6.createElement("div", { className: "mx-auto w-full max-w-full aspect-square" }, /* @__PURE__ */ React6.createElement(ResponsiveContainer, { width: "100%", height: "100%" }, /* @__PURE__ */ React6.createElement(PieChart, null, /* @__PURE__ */ React6.createElement(
546
- Pie,
665
+ return /* @__PURE__ */ jsx6("div", { ref: containerRef, className: "w-full min-w-0 mt-4 mb-2 select-none overflow-hidden", children: /* @__PURE__ */ jsx6("div", { className: "mx-auto w-full max-w-full aspect-square", children: /* @__PURE__ */ jsx6(ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxs5(PieChart, { children: [
666
+ /* @__PURE__ */ jsx6(
667
+ Pie,
668
+ {
669
+ data: sanitizedData,
670
+ dataKey: pieDataKey,
671
+ nameKey: finalXKey,
672
+ cx: "50%",
673
+ cy: "50%",
674
+ outerRadius: pieOuterRadius,
675
+ label: false,
676
+ labelLine: false,
677
+ children: sanitizedData.map((_entry, index) => /* @__PURE__ */ jsx6(Cell, { fill: colors[index % colors.length] }, `cell-${index}`))
678
+ }
679
+ ),
680
+ /* @__PURE__ */ jsx6(Tooltip, { content: (props) => renderTooltip(getTooltipRow(props.payload), typeof props.label === "string" ? props.label : void 0) }),
681
+ showLegend && !isCompact && /* @__PURE__ */ jsx6(Legend, { wrapperStyle: { fontSize: 12 }, verticalAlign: "bottom" })
682
+ ] }) }) }) });
683
+ }
684
+ return /* @__PURE__ */ jsx6("div", { ref: containerRef, className: "w-full min-w-0 mt-4 mb-2 select-none overflow-hidden", children: /* @__PURE__ */ jsx6("div", { className: "w-full aspect-[4/3]", children: /* @__PURE__ */ jsx6(ResponsiveContainer, { width: "100%", height: "100%", children: type === "bar" ? /* @__PURE__ */ jsxs5(BarChart, { data: sanitizedData, margin: chartMargin, children: [
685
+ /* @__PURE__ */ jsx6(CartesianGrid, { strokeDasharray: "3 3", vertical: false, stroke: "#e2e8f0" }),
686
+ /* @__PURE__ */ jsx6(XAxis, { dataKey: finalXKey, tick: axisTick, tickFormatter: truncateAxisLabel, tickLine: false, axisLine: { stroke: "#cbd5e1" }, interval: 0, minTickGap: isTiny ? 2 : isCompact ? 6 : 12 }),
687
+ /* @__PURE__ */ jsx6(YAxis, { tick: axisTick, tickLine: false, axisLine: false }),
688
+ /* @__PURE__ */ jsx6(Tooltip, { content: (props) => renderTooltip(getTooltipRow(props.payload), typeof props.label === "string" ? props.label : void 0), cursor: { fill: "#f1f5f9" } }),
689
+ showLegend && /* @__PURE__ */ jsx6(Legend, { wrapperStyle: { fontSize: isCompact ? 10 : 12 } }),
690
+ finalDataKeys.map((key, index) => /* @__PURE__ */ jsx6(
691
+ Bar,
547
692
  {
548
- data: sanitizedData,
549
- dataKey: pieDataKey,
550
- nameKey: finalXKey,
551
- cx: "50%",
552
- cy: "50%",
553
- outerRadius: pieOuterRadius,
554
- label: false,
555
- labelLine: false
693
+ dataKey: key,
694
+ fill: colors[index % colors.length],
695
+ radius: [4, 4, 0, 0],
696
+ barSize: isTiny ? Math.max(10, 28 / data.length) : isCompact ? Math.max(14, 42 / data.length) : Math.max(20, 60 / data.length)
556
697
  },
557
- sanitizedData.map((_entry, index) => /* @__PURE__ */ React6.createElement(Cell, { key: `cell-${index}`, fill: colors[index % colors.length] }))
558
- ), /* @__PURE__ */ React6.createElement(Tooltip, { content: (props) => renderTooltip(getTooltipRow(props.payload), typeof props.label === "string" ? props.label : void 0) }), showLegend && !isCompact && /* @__PURE__ */ React6.createElement(Legend, { wrapperStyle: { fontSize: 12 }, verticalAlign: "bottom" })))));
559
- }
560
- return /* @__PURE__ */ React6.createElement("div", { ref: containerRef, className: "w-full min-w-0 mt-4 mb-2 select-none overflow-hidden" }, /* @__PURE__ */ React6.createElement("div", { className: "w-full aspect-[4/3]" }, /* @__PURE__ */ React6.createElement(ResponsiveContainer, { width: "100%", height: "100%" }, type === "bar" ? /* @__PURE__ */ React6.createElement(BarChart, { data: sanitizedData, margin: chartMargin }, /* @__PURE__ */ React6.createElement(CartesianGrid, { strokeDasharray: "3 3", vertical: false, stroke: "#e2e8f0" }), /* @__PURE__ */ React6.createElement(XAxis, { dataKey: finalXKey, tick: axisTick, tickFormatter: truncateAxisLabel, tickLine: false, axisLine: { stroke: "#cbd5e1" }, interval: 0, minTickGap: isTiny ? 2 : isCompact ? 6 : 12 }), /* @__PURE__ */ React6.createElement(YAxis, { tick: axisTick, tickLine: false, axisLine: false }), /* @__PURE__ */ React6.createElement(Tooltip, { content: (props) => renderTooltip(getTooltipRow(props.payload), typeof props.label === "string" ? props.label : void 0), cursor: { fill: "#f1f5f9" } }), showLegend && /* @__PURE__ */ React6.createElement(Legend, { wrapperStyle: { fontSize: isCompact ? 10 : 12 } }), finalDataKeys.map((key, index) => /* @__PURE__ */ React6.createElement(
561
- Bar,
562
- {
563
- key,
564
- dataKey: key,
565
- fill: colors[index % colors.length],
566
- radius: [4, 4, 0, 0],
567
- barSize: isTiny ? Math.max(10, 28 / data.length) : isCompact ? Math.max(14, 42 / data.length) : Math.max(20, 60 / data.length)
568
- }
569
- ))) : /* @__PURE__ */ React6.createElement(LineChart, { data: sanitizedData, margin: chartMargin }, /* @__PURE__ */ React6.createElement(CartesianGrid, { strokeDasharray: "3 3", vertical: false, stroke: "#e2e8f0" }), /* @__PURE__ */ React6.createElement(XAxis, { dataKey: finalXKey, tick: axisTick, tickFormatter: truncateAxisLabel, tickLine: false, axisLine: { stroke: "#cbd5e1" }, interval: 0, minTickGap: isTiny ? 2 : isCompact ? 6 : 12 }), /* @__PURE__ */ React6.createElement(YAxis, { tick: axisTick, tickLine: false, axisLine: false }), /* @__PURE__ */ React6.createElement(Tooltip, { content: (props) => renderTooltip(getTooltipRow(props.payload), typeof props.label === "string" ? props.label : void 0) }), showLegend && /* @__PURE__ */ React6.createElement(Legend, { wrapperStyle: { fontSize: isCompact ? 10 : 12 } }), finalDataKeys.map((key, index) => /* @__PURE__ */ React6.createElement(
570
- Line,
571
- {
572
- key,
573
- type: "monotone",
574
- dataKey: key,
575
- stroke: colors[index % colors.length],
576
- strokeWidth: isTiny ? 1.75 : isCompact ? 2 : 3,
577
- dot: { r: isTiny ? 2.5 : isCompact ? 3 : 4, strokeWidth: 2 },
578
- activeDot: { r: isTiny ? 4 : isCompact ? 5 : 6 }
579
- }
580
- ))))));
698
+ key
699
+ ))
700
+ ] }) : /* @__PURE__ */ jsxs5(LineChart, { data: sanitizedData, margin: chartMargin, children: [
701
+ /* @__PURE__ */ jsx6(CartesianGrid, { strokeDasharray: "3 3", vertical: false, stroke: "#e2e8f0" }),
702
+ /* @__PURE__ */ jsx6(XAxis, { dataKey: finalXKey, tick: axisTick, tickFormatter: truncateAxisLabel, tickLine: false, axisLine: { stroke: "#cbd5e1" }, interval: 0, minTickGap: isTiny ? 2 : isCompact ? 6 : 12 }),
703
+ /* @__PURE__ */ jsx6(YAxis, { tick: axisTick, tickLine: false, axisLine: false }),
704
+ /* @__PURE__ */ jsx6(Tooltip, { content: (props) => renderTooltip(getTooltipRow(props.payload), typeof props.label === "string" ? props.label : void 0) }),
705
+ showLegend && /* @__PURE__ */ jsx6(Legend, { wrapperStyle: { fontSize: isCompact ? 10 : 12 } }),
706
+ finalDataKeys.map((key, index) => /* @__PURE__ */ jsx6(
707
+ Line,
708
+ {
709
+ type: "monotone",
710
+ dataKey: key,
711
+ stroke: colors[index % colors.length],
712
+ strokeWidth: isTiny ? 1.75 : isCompact ? 2 : 3,
713
+ dot: { r: isTiny ? 2.5 : isCompact ? 3 : 4, strokeWidth: 2 },
714
+ activeDot: { r: isTiny ? 4 : isCompact ? 5 : 6 }
715
+ },
716
+ key
717
+ ))
718
+ ] }) }) }) });
581
719
  }
582
720
 
583
721
  // src/components/VisualizationRenderer.tsx
722
+ import { Fragment as Fragment3, jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
584
723
  function getColor(index) {
585
724
  return CHART_COLORS[index % CHART_COLORS.length];
586
725
  }
@@ -590,13 +729,22 @@ function CustomTooltip({
590
729
  label
591
730
  }) {
592
731
  if (!active || !payload || payload.length === 0) return null;
593
- return /* @__PURE__ */ React7.createElement("div", { className: "rounded-xl border border-slate-200 bg-white px-3 py-2 text-xs shadow-xl dark:border-white/10 dark:bg-slate-950" }, label && /* @__PURE__ */ React7.createElement("p", { className: "mb-2 font-semibold text-slate-800 dark:text-white/90" }, label), payload.map((entry, i) => /* @__PURE__ */ React7.createElement("div", { key: i, className: "flex items-center justify-between gap-3 text-slate-600 dark:text-white/70" }, /* @__PURE__ */ React7.createElement("span", { className: "flex items-center gap-1.5" }, entry.color && /* @__PURE__ */ React7.createElement(
594
- "span",
595
- {
596
- className: "inline-block w-2 h-2 rounded-full flex-shrink-0",
597
- style: { background: entry.color }
598
- }
599
- ), entry.name), /* @__PURE__ */ React7.createElement("span", { className: "font-medium text-slate-900 dark:text-white/90" }, entry.value))));
732
+ return /* @__PURE__ */ jsxs6("div", { className: "rounded-xl border border-slate-200 bg-white px-3 py-2 text-xs shadow-xl dark:border-white/10 dark:bg-slate-950", children: [
733
+ label && /* @__PURE__ */ jsx7("p", { className: "mb-2 font-semibold text-slate-800 dark:text-white/90", children: label }),
734
+ payload.map((entry, i) => /* @__PURE__ */ jsxs6("div", { className: "flex items-center justify-between gap-3 text-slate-600 dark:text-white/70", children: [
735
+ /* @__PURE__ */ jsxs6("span", { className: "flex items-center gap-1.5", children: [
736
+ entry.color && /* @__PURE__ */ jsx7(
737
+ "span",
738
+ {
739
+ className: "inline-block w-2 h-2 rounded-full flex-shrink-0",
740
+ style: { background: entry.color }
741
+ }
742
+ ),
743
+ entry.name
744
+ ] }),
745
+ /* @__PURE__ */ jsx7("span", { className: "font-medium text-slate-900 dark:text-white/90", children: entry.value })
746
+ ] }, i))
747
+ ] });
600
748
  }
601
749
  function VisualizationRenderer({
602
750
  data,
@@ -607,72 +755,86 @@ function VisualizationRenderer({
607
755
  }) {
608
756
  var _a;
609
757
  if (!data) {
610
- return /* @__PURE__ */ React7.createElement("div", { className: `p-4 text-gray-500 ${className}` }, "No data available for visualization");
758
+ return /* @__PURE__ */ jsx7("div", { className: `p-4 text-gray-500 ${className}`, children: "No data available for visualization" });
611
759
  }
612
- return /* @__PURE__ */ React7.createElement("div", { className: `space-y-4 ${className}` }, /* @__PURE__ */ React7.createElement("div", { className: "space-y-1" }, /* @__PURE__ */ React7.createElement("h3", { className: "text-sm font-semibold text-slate-900 dark:text-white" }, data.title), data.description && data.description !== ((_a = data.data) == null ? void 0 : _a.content) && /* @__PURE__ */ React7.createElement("p", { className: "text-xs text-slate-500 dark:text-slate-400" }, data.description)), renderVisualization(data.type, data.data, onAddToCart, primaryColor, isStreaming));
760
+ return /* @__PURE__ */ jsxs6("div", { className: `space-y-4 ${className}`, children: [
761
+ /* @__PURE__ */ jsxs6("div", { className: "space-y-1", children: [
762
+ /* @__PURE__ */ jsx7("h3", { className: "text-sm font-semibold text-slate-900 dark:text-white", children: data.title }),
763
+ data.description && data.description !== ((_a = data.data) == null ? void 0 : _a.content) && /* @__PURE__ */ jsx7("p", { className: "text-xs text-slate-500 dark:text-slate-400", children: data.description })
764
+ ] }),
765
+ renderVisualization(data.type, data.data, onAddToCart, primaryColor, isStreaming)
766
+ ] });
613
767
  }
614
768
  function renderVisualization(type, data, onAddToCart, primaryColor, isStreaming) {
615
769
  try {
616
770
  switch (type) {
617
771
  case "pie_chart":
618
- return /* @__PURE__ */ React7.createElement(PieChartView, { data, isStreaming });
772
+ return /* @__PURE__ */ jsx7(PieChartView, { data, isStreaming });
619
773
  case "bar_chart":
620
- return /* @__PURE__ */ React7.createElement(BarChartView, { data, primaryColor, isStreaming });
774
+ return /* @__PURE__ */ jsx7(BarChartView, { data, primaryColor, isStreaming });
621
775
  case "line_chart":
622
- return /* @__PURE__ */ React7.createElement(LineChartView, { data, primaryColor, isStreaming });
776
+ return /* @__PURE__ */ jsx7(LineChartView, { data, primaryColor, isStreaming });
623
777
  case "radar_chart":
624
- return /* @__PURE__ */ React7.createElement(RadarChartView, { data, isStreaming });
778
+ return /* @__PURE__ */ jsx7(RadarChartView, { data, isStreaming });
625
779
  case "table":
626
- return /* @__PURE__ */ React7.createElement(TableView, { data, isStreaming });
780
+ return /* @__PURE__ */ jsx7(TableView, { data, isStreaming });
627
781
  case "product_carousel":
628
782
  case "carousel":
629
- return /* @__PURE__ */ React7.createElement(CarouselView, { data, onAddToCart, primaryColor });
783
+ return /* @__PURE__ */ jsx7(CarouselView, { data, onAddToCart, primaryColor });
630
784
  case "text":
631
785
  default:
632
- return /* @__PURE__ */ React7.createElement(TextView, { data });
786
+ return /* @__PURE__ */ jsx7(TextView, { data });
633
787
  }
634
788
  } catch (error) {
635
789
  console.warn("[VisualizationRenderer] Rendering failed, falling back to text:", error);
636
- return /* @__PURE__ */ React7.createElement(TextView, { data: { content: "Unable to render the requested visualization." } });
790
+ return /* @__PURE__ */ jsx7(TextView, { data: { content: "Unable to render the requested visualization." } });
637
791
  }
638
792
  }
639
793
  function ChartSkeleton({ type }) {
640
794
  if (type === "pie") {
641
- return /* @__PURE__ */ React7.createElement("div", { className: "w-full mt-4 mb-2 animate-pulse" }, /* @__PURE__ */ React7.createElement("div", { className: "mx-auto w-40 h-40 rounded-full bg-slate-100 dark:bg-white/10" }));
795
+ return /* @__PURE__ */ jsx7("div", { className: "w-full mt-4 mb-2 animate-pulse", children: /* @__PURE__ */ jsx7("div", { className: "mx-auto w-40 h-40 rounded-full bg-slate-100 dark:bg-white/10" }) });
642
796
  }
643
797
  if (type === "table") {
644
- return /* @__PURE__ */ React7.createElement("div", { className: "w-full mt-4 mb-2 animate-pulse space-y-2" }, /* @__PURE__ */ React7.createElement("div", { className: "h-8 bg-slate-100 dark:bg-white/10 rounded" }), /* @__PURE__ */ React7.createElement("div", { className: "h-8 bg-slate-100 dark:bg-white/10 rounded" }), /* @__PURE__ */ React7.createElement("div", { className: "h-8 bg-slate-100 dark:bg-white/10 rounded" }));
798
+ return /* @__PURE__ */ jsxs6("div", { className: "w-full mt-4 mb-2 animate-pulse space-y-2", children: [
799
+ /* @__PURE__ */ jsx7("div", { className: "h-8 bg-slate-100 dark:bg-white/10 rounded" }),
800
+ /* @__PURE__ */ jsx7("div", { className: "h-8 bg-slate-100 dark:bg-white/10 rounded" }),
801
+ /* @__PURE__ */ jsx7("div", { className: "h-8 bg-slate-100 dark:bg-white/10 rounded" })
802
+ ] });
645
803
  }
646
- return /* @__PURE__ */ React7.createElement("div", { className: "w-full mt-4 mb-2 animate-pulse flex items-end gap-2 h-32 px-2" }, Array.from({ length: 5 }).map((_, i) => /* @__PURE__ */ React7.createElement("div", { key: i, className: "flex-1 rounded-t-md bg-slate-100 dark:bg-white/10", style: { height: `${40 + i % 3 * 25}%` } })));
804
+ return /* @__PURE__ */ jsx7("div", { className: "w-full mt-4 mb-2 animate-pulse flex items-end gap-2 h-32 px-2", children: Array.from({ length: 5 }).map((_, i) => /* @__PURE__ */ jsx7("div", { className: "flex-1 rounded-t-md bg-slate-100 dark:bg-white/10", style: { height: `${40 + i % 3 * 25}%` } }, i)) });
647
805
  }
648
806
  function PieChartView({ data, isStreaming }) {
649
- if (isStreaming) return /* @__PURE__ */ React7.createElement(ChartSkeleton, { type: "pie" });
807
+ if (isStreaming) return /* @__PURE__ */ jsx7(ChartSkeleton, { type: "pie" });
650
808
  if (!Array.isArray(data) || data.length === 0) {
651
- return /* @__PURE__ */ React7.createElement("div", { className: "text-xs text-red-500" }, "Invalid pie chart data");
809
+ return /* @__PURE__ */ jsx7("div", { className: "text-xs text-red-500", children: "Invalid pie chart data" });
652
810
  }
653
811
  const chartData = data.map((item) => ({
654
812
  name: item.label,
655
813
  value: item.value
656
814
  }));
657
- return /* @__PURE__ */ React7.createElement("div", { className: "bg-white dark:bg-slate-900 rounded-xl border border-slate-200 dark:border-white/10 p-4 shadow-sm" }, /* @__PURE__ */ React7.createElement(ResponsiveContainer2, { width: "100%", height: 280 }, /* @__PURE__ */ React7.createElement(PieChart2, null, /* @__PURE__ */ React7.createElement(
658
- Pie2,
659
- {
660
- data: chartData,
661
- dataKey: "value",
662
- nameKey: "name",
663
- cx: "50%",
664
- cy: "50%",
665
- outerRadius: "68%",
666
- label: false,
667
- labelLine: false
668
- },
669
- chartData.map((_entry, index) => /* @__PURE__ */ React7.createElement(Cell2, { key: `cell-${index}`, fill: getColor(index) }))
670
- ), /* @__PURE__ */ React7.createElement(Tooltip2, { content: /* @__PURE__ */ React7.createElement(CustomTooltip, null) }), /* @__PURE__ */ React7.createElement(Legend2, { wrapperStyle: { fontSize: 12 }, verticalAlign: "bottom" }))));
815
+ return /* @__PURE__ */ jsx7("div", { className: "bg-white dark:bg-slate-900 rounded-xl border border-slate-200 dark:border-white/10 p-4 shadow-sm", children: /* @__PURE__ */ jsx7(ResponsiveContainer2, { width: "100%", height: 280, children: /* @__PURE__ */ jsxs6(PieChart2, { children: [
816
+ /* @__PURE__ */ jsx7(
817
+ Pie2,
818
+ {
819
+ data: chartData,
820
+ dataKey: "value",
821
+ nameKey: "name",
822
+ cx: "50%",
823
+ cy: "50%",
824
+ outerRadius: "68%",
825
+ label: false,
826
+ labelLine: false,
827
+ children: chartData.map((_entry, index) => /* @__PURE__ */ jsx7(Cell2, { fill: getColor(index) }, `cell-${index}`))
828
+ }
829
+ ),
830
+ /* @__PURE__ */ jsx7(Tooltip2, { content: /* @__PURE__ */ jsx7(CustomTooltip, {}) }),
831
+ /* @__PURE__ */ jsx7(Legend2, { wrapperStyle: { fontSize: 12 }, verticalAlign: "bottom" })
832
+ ] }) }) });
671
833
  }
672
834
  function BarChartView({ data, primaryColor, isStreaming }) {
673
- if (isStreaming) return /* @__PURE__ */ React7.createElement(ChartSkeleton, { type: "bar" });
835
+ if (isStreaming) return /* @__PURE__ */ jsx7(ChartSkeleton, { type: "bar" });
674
836
  if (!Array.isArray(data) || data.length === 0) {
675
- return /* @__PURE__ */ React7.createElement("div", { className: "text-xs text-red-500" }, "Invalid bar chart data");
837
+ return /* @__PURE__ */ jsx7("div", { className: "text-xs text-red-500", children: "Invalid bar chart data" });
676
838
  }
677
839
  const chartData = data.map((item) => __spreadValues(__spreadValues({
678
840
  category: item.category,
@@ -680,20 +842,30 @@ function BarChartView({ data, primaryColor, isStreaming }) {
680
842
  }, item.inStockCount !== void 0 && { inStockCount: item.inStockCount }), item.outOfStockCount !== void 0 && { outOfStockCount: item.outOfStockCount }));
681
843
  const barColor = primaryColor != null ? primaryColor : getColor(0);
682
844
  const hasStock = chartData.some((d) => "inStockCount" in d);
683
- return /* @__PURE__ */ React7.createElement("div", { className: "bg-white dark:bg-slate-900 rounded-xl border border-slate-200 dark:border-white/10 p-4 shadow-sm overflow-x-auto" }, /* @__PURE__ */ React7.createElement(ResponsiveContainer2, { width: "100%", height: 260 }, /* @__PURE__ */ React7.createElement(BarChart2, { data: chartData, margin: { top: 10, right: 10, left: -20, bottom: 0 } }, /* @__PURE__ */ React7.createElement(CartesianGrid2, { strokeDasharray: "3 3", vertical: false, stroke: "#e2e8f0" }), /* @__PURE__ */ React7.createElement(
684
- XAxis2,
685
- {
686
- dataKey: "category",
687
- tick: { fontSize: 11, fill: "#64748b" },
688
- tickLine: false,
689
- axisLine: { stroke: "#cbd5e1" }
690
- }
691
- ), /* @__PURE__ */ React7.createElement(YAxis2, { tick: { fontSize: 11, fill: "#64748b" }, tickLine: false, axisLine: false }), /* @__PURE__ */ React7.createElement(Tooltip2, { content: /* @__PURE__ */ React7.createElement(CustomTooltip, null), cursor: { fill: "#f1f5f9" } }), /* @__PURE__ */ React7.createElement(Legend2, { wrapperStyle: { fontSize: 12 } }), hasStock ? /* @__PURE__ */ React7.createElement(React7.Fragment, null, /* @__PURE__ */ React7.createElement(Bar2, { dataKey: "inStockCount", name: "In Stock", fill: getColor(1), radius: [4, 4, 0, 0] }), /* @__PURE__ */ React7.createElement(Bar2, { dataKey: "outOfStockCount", name: "Out of Stock", fill: getColor(3), radius: [4, 4, 0, 0] })) : /* @__PURE__ */ React7.createElement(Bar2, { dataKey: "value", name: "Value", fill: barColor, radius: [4, 4, 0, 0] }))));
845
+ return /* @__PURE__ */ jsx7("div", { className: "bg-white dark:bg-slate-900 rounded-xl border border-slate-200 dark:border-white/10 p-4 shadow-sm overflow-x-auto", children: /* @__PURE__ */ jsx7(ResponsiveContainer2, { width: "100%", height: 260, children: /* @__PURE__ */ jsxs6(BarChart2, { data: chartData, margin: { top: 10, right: 10, left: -20, bottom: 0 }, children: [
846
+ /* @__PURE__ */ jsx7(CartesianGrid2, { strokeDasharray: "3 3", vertical: false, stroke: "#e2e8f0" }),
847
+ /* @__PURE__ */ jsx7(
848
+ XAxis2,
849
+ {
850
+ dataKey: "category",
851
+ tick: { fontSize: 11, fill: "#64748b" },
852
+ tickLine: false,
853
+ axisLine: { stroke: "#cbd5e1" }
854
+ }
855
+ ),
856
+ /* @__PURE__ */ jsx7(YAxis2, { tick: { fontSize: 11, fill: "#64748b" }, tickLine: false, axisLine: false }),
857
+ /* @__PURE__ */ jsx7(Tooltip2, { content: /* @__PURE__ */ jsx7(CustomTooltip, {}), cursor: { fill: "#f1f5f9" } }),
858
+ /* @__PURE__ */ jsx7(Legend2, { wrapperStyle: { fontSize: 12 } }),
859
+ hasStock ? /* @__PURE__ */ jsxs6(Fragment3, { children: [
860
+ /* @__PURE__ */ jsx7(Bar2, { dataKey: "inStockCount", name: "In Stock", fill: getColor(1), radius: [4, 4, 0, 0] }),
861
+ /* @__PURE__ */ jsx7(Bar2, { dataKey: "outOfStockCount", name: "Out of Stock", fill: getColor(3), radius: [4, 4, 0, 0] })
862
+ ] }) : /* @__PURE__ */ jsx7(Bar2, { dataKey: "value", name: "Value", fill: barColor, radius: [4, 4, 0, 0] })
863
+ ] }) }) });
692
864
  }
693
865
  function LineChartView({ data, primaryColor, isStreaming }) {
694
- if (isStreaming) return /* @__PURE__ */ React7.createElement(ChartSkeleton, { type: "bar" });
866
+ if (isStreaming) return /* @__PURE__ */ jsx7(ChartSkeleton, { type: "bar" });
695
867
  if (!Array.isArray(data) || data.length === 0) {
696
- return /* @__PURE__ */ React7.createElement("div", { className: "text-xs text-red-500" }, "Invalid line chart data");
868
+ return /* @__PURE__ */ jsx7("div", { className: "text-xs text-red-500", children: "Invalid line chart data" });
697
869
  }
698
870
  const chartData = data.map((point) => {
699
871
  var _a;
@@ -703,74 +875,97 @@ function LineChartView({ data, primaryColor, isStreaming }) {
703
875
  };
704
876
  });
705
877
  const lineColor = primaryColor != null ? primaryColor : getColor(0);
706
- return /* @__PURE__ */ React7.createElement("div", { className: "bg-white dark:bg-slate-900 rounded-xl border border-slate-200 dark:border-white/10 p-4 shadow-sm overflow-x-auto" }, /* @__PURE__ */ React7.createElement(ResponsiveContainer2, { width: "100%", height: 260 }, /* @__PURE__ */ React7.createElement(LineChart2, { data: chartData, margin: { top: 10, right: 10, left: -20, bottom: 0 } }, /* @__PURE__ */ React7.createElement(CartesianGrid2, { strokeDasharray: "3 3", vertical: false, stroke: "#e2e8f0" }), /* @__PURE__ */ React7.createElement(
707
- XAxis2,
708
- {
709
- dataKey: "label",
710
- tick: { fontSize: 11, fill: "#64748b" },
711
- tickLine: false,
712
- axisLine: { stroke: "#cbd5e1" }
713
- }
714
- ), /* @__PURE__ */ React7.createElement(YAxis2, { tick: { fontSize: 11, fill: "#64748b" }, tickLine: false, axisLine: false }), /* @__PURE__ */ React7.createElement(Tooltip2, { content: /* @__PURE__ */ React7.createElement(CustomTooltip, null) }), /* @__PURE__ */ React7.createElement(
715
- Line2,
716
- {
717
- type: "monotone",
718
- dataKey: "value",
719
- name: "Value",
720
- stroke: lineColor,
721
- strokeWidth: 2.5,
722
- dot: { r: 3.5, strokeWidth: 2, fill: lineColor },
723
- activeDot: { r: 5 }
724
- }
725
- ))));
878
+ return /* @__PURE__ */ jsx7("div", { className: "bg-white dark:bg-slate-900 rounded-xl border border-slate-200 dark:border-white/10 p-4 shadow-sm overflow-x-auto", children: /* @__PURE__ */ jsx7(ResponsiveContainer2, { width: "100%", height: 260, children: /* @__PURE__ */ jsxs6(LineChart2, { data: chartData, margin: { top: 10, right: 10, left: -20, bottom: 0 }, children: [
879
+ /* @__PURE__ */ jsx7(CartesianGrid2, { strokeDasharray: "3 3", vertical: false, stroke: "#e2e8f0" }),
880
+ /* @__PURE__ */ jsx7(
881
+ XAxis2,
882
+ {
883
+ dataKey: "label",
884
+ tick: { fontSize: 11, fill: "#64748b" },
885
+ tickLine: false,
886
+ axisLine: { stroke: "#cbd5e1" }
887
+ }
888
+ ),
889
+ /* @__PURE__ */ jsx7(YAxis2, { tick: { fontSize: 11, fill: "#64748b" }, tickLine: false, axisLine: false }),
890
+ /* @__PURE__ */ jsx7(Tooltip2, { content: /* @__PURE__ */ jsx7(CustomTooltip, {}) }),
891
+ /* @__PURE__ */ jsx7(
892
+ Line2,
893
+ {
894
+ type: "monotone",
895
+ dataKey: "value",
896
+ name: "Value",
897
+ stroke: lineColor,
898
+ strokeWidth: 2.5,
899
+ dot: { r: 3.5, strokeWidth: 2, fill: lineColor },
900
+ activeDot: { r: 5 }
901
+ }
902
+ )
903
+ ] }) }) });
726
904
  }
727
905
  function RadarChartView({ data, isStreaming }) {
728
- if (isStreaming) return /* @__PURE__ */ React7.createElement(ChartSkeleton, { type: "pie" });
906
+ if (isStreaming) return /* @__PURE__ */ jsx7(ChartSkeleton, { type: "pie" });
729
907
  if (!Array.isArray(data) || data.length === 0) {
730
- return /* @__PURE__ */ React7.createElement("div", { className: "text-xs text-red-500" }, "Invalid radar chart data");
908
+ return /* @__PURE__ */ jsx7("div", { className: "text-xs text-red-500", children: "Invalid radar chart data" });
731
909
  }
732
910
  const productNames = Array.from(
733
911
  new Set(data.flatMap((item) => Object.keys(item).filter((key) => key !== "attribute")))
734
912
  );
735
- return /* @__PURE__ */ React7.createElement("div", { className: "bg-white dark:bg-slate-900 rounded-xl border border-slate-200 dark:border-white/10 p-4 shadow-sm" }, /* @__PURE__ */ React7.createElement(ResponsiveContainer2, { width: "100%", height: 300 }, /* @__PURE__ */ React7.createElement(RadarChart, { cx: "50%", cy: "50%", outerRadius: "80%", data }, /* @__PURE__ */ React7.createElement(PolarGrid, { stroke: "#e2e8f0" }), /* @__PURE__ */ React7.createElement(PolarAngleAxis, { dataKey: "attribute", tick: { fontSize: 11, fill: "#64748b" } }), /* @__PURE__ */ React7.createElement(PolarRadiusAxis, { tick: { fontSize: 10, fill: "#64748b" } }), productNames.map((productName, index) => /* @__PURE__ */ React7.createElement(
736
- Radar,
737
- {
738
- key: productName,
739
- name: productName,
740
- dataKey: productName,
741
- stroke: getColor(index),
742
- fill: getColor(index),
743
- fillOpacity: 0.4
744
- }
745
- )), /* @__PURE__ */ React7.createElement(Tooltip2, { content: /* @__PURE__ */ React7.createElement(CustomTooltip, null) }), /* @__PURE__ */ React7.createElement(Legend2, { wrapperStyle: { fontSize: 12 } }))));
913
+ return /* @__PURE__ */ jsx7("div", { className: "bg-white dark:bg-slate-900 rounded-xl border border-slate-200 dark:border-white/10 p-4 shadow-sm", children: /* @__PURE__ */ jsx7(ResponsiveContainer2, { width: "100%", height: 300, children: /* @__PURE__ */ jsxs6(RadarChart, { cx: "50%", cy: "50%", outerRadius: "80%", data, children: [
914
+ /* @__PURE__ */ jsx7(PolarGrid, { stroke: "#e2e8f0" }),
915
+ /* @__PURE__ */ jsx7(PolarAngleAxis, { dataKey: "attribute", tick: { fontSize: 11, fill: "#64748b" } }),
916
+ /* @__PURE__ */ jsx7(PolarRadiusAxis, { tick: { fontSize: 10, fill: "#64748b" } }),
917
+ productNames.map((productName, index) => /* @__PURE__ */ jsx7(
918
+ Radar,
919
+ {
920
+ name: productName,
921
+ dataKey: productName,
922
+ stroke: getColor(index),
923
+ fill: getColor(index),
924
+ fillOpacity: 0.4
925
+ },
926
+ productName
927
+ )),
928
+ /* @__PURE__ */ jsx7(Tooltip2, { content: /* @__PURE__ */ jsx7(CustomTooltip, {}) }),
929
+ /* @__PURE__ */ jsx7(Legend2, { wrapperStyle: { fontSize: 12 } })
930
+ ] }) }) });
746
931
  }
747
932
  function TableView({ data, isStreaming }) {
748
- if (isStreaming) return /* @__PURE__ */ React7.createElement(ChartSkeleton, { type: "table" });
933
+ if (isStreaming) return /* @__PURE__ */ jsx7(ChartSkeleton, { type: "table" });
749
934
  if (!(data == null ? void 0 : data.columns) || !(data == null ? void 0 : data.rows)) {
750
- return /* @__PURE__ */ React7.createElement("div", { className: "text-xs text-red-500" }, "Invalid table data");
935
+ return /* @__PURE__ */ jsx7("div", { className: "text-xs text-red-500", children: "Invalid table data" });
751
936
  }
752
- return /* @__PURE__ */ React7.createElement("div", { className: "bg-white dark:bg-slate-900 rounded-xl border border-slate-200 dark:border-white/10 shadow-sm overflow-hidden" }, /* @__PURE__ */ React7.createElement("div", { className: "overflow-x-auto" }, /* @__PURE__ */ React7.createElement("table", { className: "w-full text-sm border-collapse" }, /* @__PURE__ */ React7.createElement("thead", { className: "bg-slate-50 dark:bg-white/5 border-b border-slate-200 dark:border-white/10" }, /* @__PURE__ */ React7.createElement("tr", null, data.columns.map((col, idx) => /* @__PURE__ */ React7.createElement(
753
- "th",
754
- {
755
- key: idx,
756
- className: "px-4 py-3 text-left text-xs font-semibold text-slate-700 dark:text-white/90 whitespace-nowrap uppercase tracking-wider"
757
- },
758
- col
759
- )))), /* @__PURE__ */ React7.createElement("tbody", { className: "divide-y divide-slate-100 dark:divide-white/5" }, data.rows.map((row, rowIdx) => /* @__PURE__ */ React7.createElement(
760
- "tr",
761
- {
762
- key: rowIdx,
763
- className: "hover:bg-slate-50/60 dark:hover:bg-white/5 transition-colors"
764
- },
765
- row.map((cell, cellIdx) => /* @__PURE__ */ React7.createElement(
766
- "td",
767
- {
768
- key: cellIdx,
769
- className: "px-4 py-3 text-slate-600 dark:text-white/70 text-sm"
770
- },
771
- String(cell)
772
- ))
773
- ))))), /* @__PURE__ */ React7.createElement("div", { className: "px-4 py-2 bg-slate-50 dark:bg-white/5 border-t border-slate-100 dark:border-white/5" }, /* @__PURE__ */ React7.createElement("p", { className: "text-[11px] text-slate-400 dark:text-white/30" }, data.rows.length, " row", data.rows.length !== 1 ? "s" : "")));
937
+ return /* @__PURE__ */ jsxs6("div", { className: "bg-white dark:bg-slate-900 rounded-xl border border-slate-200 dark:border-white/10 shadow-sm overflow-hidden", children: [
938
+ /* @__PURE__ */ jsx7("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxs6("table", { className: "w-full text-sm border-collapse", children: [
939
+ /* @__PURE__ */ jsx7("thead", { className: "bg-slate-50 dark:bg-white/5 border-b border-slate-200 dark:border-white/10", children: /* @__PURE__ */ jsx7("tr", { children: data.columns.map((col, idx) => /* @__PURE__ */ jsx7(
940
+ "th",
941
+ {
942
+ className: "px-4 py-3 text-left text-xs font-semibold text-slate-700 dark:text-white/90 whitespace-nowrap uppercase tracking-wider",
943
+ children: col
944
+ },
945
+ idx
946
+ )) }) }),
947
+ /* @__PURE__ */ jsx7("tbody", { className: "divide-y divide-slate-100 dark:divide-white/5", children: data.rows.map((row, rowIdx) => /* @__PURE__ */ jsx7(
948
+ "tr",
949
+ {
950
+ className: "hover:bg-slate-50/60 dark:hover:bg-white/5 transition-colors",
951
+ children: row.map((cell, cellIdx) => /* @__PURE__ */ jsx7(
952
+ "td",
953
+ {
954
+ className: "px-4 py-3 text-slate-600 dark:text-white/70 text-sm",
955
+ children: String(cell)
956
+ },
957
+ cellIdx
958
+ ))
959
+ },
960
+ rowIdx
961
+ )) })
962
+ ] }) }),
963
+ /* @__PURE__ */ jsx7("div", { className: "px-4 py-2 bg-slate-50 dark:bg-white/5 border-t border-slate-100 dark:border-white/5", children: /* @__PURE__ */ jsxs6("p", { className: "text-[11px] text-slate-400 dark:text-white/30", children: [
964
+ data.rows.length,
965
+ " row",
966
+ data.rows.length !== 1 ? "s" : ""
967
+ ] }) })
968
+ ] });
774
969
  }
775
970
  function CarouselView({
776
971
  data,
@@ -778,7 +973,7 @@ function CarouselView({
778
973
  primaryColor
779
974
  }) {
780
975
  if (!Array.isArray(data)) {
781
- return /* @__PURE__ */ React7.createElement("div", { className: "text-xs text-red-500" }, "Invalid carousel data");
976
+ return /* @__PURE__ */ jsx7("div", { className: "text-xs text-red-500", children: "Invalid carousel data" });
782
977
  }
783
978
  const products = data.map((product) => ({
784
979
  id: product.id,
@@ -790,22 +985,22 @@ function CarouselView({
790
985
  description: product.description,
791
986
  inStock: product.inStock
792
987
  }));
793
- return /* @__PURE__ */ React7.createElement("div", { className: "w-full" }, /* @__PURE__ */ React7.createElement(
988
+ return /* @__PURE__ */ jsx7("div", { className: "w-full", children: /* @__PURE__ */ jsx7(
794
989
  ProductCarousel,
795
990
  {
796
991
  products,
797
992
  primaryColor: primaryColor != null ? primaryColor : "#6366f1",
798
993
  onAddToCart: (p) => onAddToCart == null ? void 0 : onAddToCart(p)
799
994
  }
800
- ));
995
+ ) });
801
996
  }
802
997
  function TextView({ data }) {
803
998
  const content = (data == null ? void 0 : data.content) || String(data != null ? data : "");
804
- return /* @__PURE__ */ React7.createElement("div", { className: "bg-white dark:bg-slate-900 rounded-xl border border-slate-200 dark:border-white/10 p-4 shadow-sm" }, /* @__PURE__ */ React7.createElement("p", { className: "text-sm text-slate-700 dark:text-slate-300 whitespace-pre-wrap leading-relaxed" }, content));
999
+ return /* @__PURE__ */ jsx7("div", { className: "bg-white dark:bg-slate-900 rounded-xl border border-slate-200 dark:border-white/10 p-4 shadow-sm", children: /* @__PURE__ */ jsx7("p", { className: "text-sm text-slate-700 dark:text-slate-300 whitespace-pre-wrap leading-relaxed", children: content }) });
805
1000
  }
806
1001
 
807
1002
  // src/components/ObservabilityPanel.tsx
808
- import React8 from "react";
1003
+ import React6 from "react";
809
1004
  import {
810
1005
  Clock,
811
1006
  Cpu,
@@ -818,6 +1013,7 @@ import {
818
1013
  CheckCircle as CheckCircle2,
819
1014
  AlertCircle as AlertCircle2
820
1015
  } from "lucide-react";
1016
+ import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
821
1017
  function fmtMs(ms) {
822
1018
  return ms >= 1e3 ? `${(ms / 1e3).toFixed(2)}s` : `${Math.round(ms)}ms`;
823
1019
  }
@@ -827,25 +1023,55 @@ function fmtTokens(n) {
827
1023
  function ScoreBadge({ score }) {
828
1024
  const pct = Math.round(score * 100);
829
1025
  const color = pct <= 20 ? "text-emerald-600 bg-emerald-50 border-emerald-200 dark:text-emerald-400 dark:bg-emerald-500/10 dark:border-emerald-500/20" : pct <= 50 ? "text-amber-600 bg-amber-50 border-amber-200 dark:text-amber-400 dark:bg-amber-500/10 dark:border-amber-500/20" : "text-red-600 bg-red-50 border-red-200 dark:text-red-400 dark:bg-red-500/10 dark:border-red-500/20";
830
- return /* @__PURE__ */ React8.createElement("span", { className: `inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-[11px] font-semibold border ${color}` }, pct <= 20 ? /* @__PURE__ */ React8.createElement(CheckCircle2, { className: "w-3 h-3" }) : /* @__PURE__ */ React8.createElement(AlertCircle2, { className: "w-3 h-3" }), pct, "% hallucination risk");
1026
+ return /* @__PURE__ */ jsxs7("span", { className: `inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-[11px] font-semibold border ${color}`, children: [
1027
+ pct <= 20 ? /* @__PURE__ */ jsx8(CheckCircle2, { className: "w-3 h-3" }) : /* @__PURE__ */ jsx8(AlertCircle2, { className: "w-3 h-3" }),
1028
+ pct,
1029
+ "% hallucination risk"
1030
+ ] });
831
1031
  }
832
1032
  function RetrievalTab({ trace }) {
833
- return /* @__PURE__ */ React8.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React8.createElement("p", { className: "text-[11px] text-slate-500 dark:text-white/40" }, trace.chunks.length, " chunk", trace.chunks.length !== 1 ? "s" : "", " retrieved", trace.rewrittenQuery && /* @__PURE__ */ React8.createElement("span", { className: "ml-2 italic" }, "(query rewritten: ", /* @__PURE__ */ React8.createElement("em", { className: "text-indigo-500" }, trace.rewrittenQuery), ")")), /* @__PURE__ */ React8.createElement("div", { className: "space-y-1.5 max-h-56 overflow-y-auto pr-1 custom-scrollbar" }, trace.chunks.map((chunk, i) => /* @__PURE__ */ React8.createElement(
834
- "div",
835
- {
836
- key: String(chunk.id),
837
- className: "rounded-lg border border-slate-100 dark:border-white/8 bg-slate-50 dark:bg-white/3 p-2.5"
838
- },
839
- /* @__PURE__ */ React8.createElement("div", { className: "flex items-center justify-between mb-1" }, /* @__PURE__ */ React8.createElement("span", { className: "text-[10px] font-mono text-slate-400 dark:text-white/30" }, "[", i + 1, "] ", String(chunk.id).slice(0, 20)), /* @__PURE__ */ React8.createElement("span", { className: "text-[10px] font-semibold text-indigo-600 dark:text-indigo-400" }, "score: ", chunk.score.toFixed(3))),
840
- /* @__PURE__ */ React8.createElement("div", { className: "h-1 rounded-full bg-slate-200 dark:bg-white/10 mb-2 overflow-hidden" }, /* @__PURE__ */ React8.createElement(
1033
+ return /* @__PURE__ */ jsxs7("div", { className: "space-y-2", children: [
1034
+ /* @__PURE__ */ jsxs7("p", { className: "text-[11px] text-slate-500 dark:text-white/40", children: [
1035
+ trace.chunks.length,
1036
+ " chunk",
1037
+ trace.chunks.length !== 1 ? "s" : "",
1038
+ " retrieved",
1039
+ trace.rewrittenQuery && /* @__PURE__ */ jsxs7("span", { className: "ml-2 italic", children: [
1040
+ "(query rewritten: ",
1041
+ /* @__PURE__ */ jsx8("em", { className: "text-indigo-500", children: trace.rewrittenQuery }),
1042
+ ")"
1043
+ ] })
1044
+ ] }),
1045
+ /* @__PURE__ */ jsx8("div", { className: "space-y-1.5 max-h-56 overflow-y-auto pr-1 custom-scrollbar", children: trace.chunks.map((chunk, i) => /* @__PURE__ */ jsxs7(
841
1046
  "div",
842
1047
  {
843
- className: "h-full rounded-full bg-indigo-500 dark:bg-indigo-400 transition-all",
844
- style: { width: `${Math.min(100, chunk.score * 100)}%` }
845
- }
846
- )),
847
- /* @__PURE__ */ React8.createElement("p", { className: "text-[11px] text-slate-600 dark:text-white/60 line-clamp-2 leading-relaxed" }, chunk.content)
848
- ))));
1048
+ className: "rounded-lg border border-slate-100 dark:border-white/8 bg-slate-50 dark:bg-white/3 p-2.5",
1049
+ children: [
1050
+ /* @__PURE__ */ jsxs7("div", { className: "flex items-center justify-between mb-1", children: [
1051
+ /* @__PURE__ */ jsxs7("span", { className: "text-[10px] font-mono text-slate-400 dark:text-white/30", children: [
1052
+ "[",
1053
+ i + 1,
1054
+ "] ",
1055
+ String(chunk.id).slice(0, 20)
1056
+ ] }),
1057
+ /* @__PURE__ */ jsxs7("span", { className: "text-[10px] font-semibold text-indigo-600 dark:text-indigo-400", children: [
1058
+ "score: ",
1059
+ chunk.score.toFixed(3)
1060
+ ] })
1061
+ ] }),
1062
+ /* @__PURE__ */ jsx8("div", { className: "h-1 rounded-full bg-slate-200 dark:bg-white/10 mb-2 overflow-hidden", children: /* @__PURE__ */ jsx8(
1063
+ "div",
1064
+ {
1065
+ className: "h-full rounded-full bg-indigo-500 dark:bg-indigo-400 transition-all",
1066
+ style: { width: `${Math.min(100, chunk.score * 100)}%` }
1067
+ }
1068
+ ) }),
1069
+ /* @__PURE__ */ jsx8("p", { className: "text-[11px] text-slate-600 dark:text-white/60 line-clamp-2 leading-relaxed", children: chunk.content })
1070
+ ]
1071
+ },
1072
+ String(chunk.id)
1073
+ )) })
1074
+ ] });
849
1075
  }
850
1076
  function LatencyTab({ trace }) {
851
1077
  const { latency } = trace;
@@ -856,73 +1082,153 @@ function LatencyTab({ trace }) {
856
1082
  { label: "Generate", ms: latency.generateMs, color: "#8b5cf6" }
857
1083
  ];
858
1084
  const maxMs = Math.max(...bars.map((b) => b.ms), 1);
859
- return /* @__PURE__ */ React8.createElement("div", { className: "space-y-3" }, /* @__PURE__ */ React8.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ React8.createElement("span", { className: "text-[11px] text-slate-500 dark:text-white/40" }, "Pipeline stages"), /* @__PURE__ */ React8.createElement("span", { className: "text-[11px] font-semibold text-slate-700 dark:text-white/70" }, "Total: ", fmtMs(latency.totalMs))), /* @__PURE__ */ React8.createElement("div", { className: "space-y-2" }, bars.map((bar) => /* @__PURE__ */ React8.createElement("div", { key: bar.label, className: "space-y-0.5" }, /* @__PURE__ */ React8.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ React8.createElement("span", { className: "text-[11px] text-slate-600 dark:text-white/60" }, bar.label), /* @__PURE__ */ React8.createElement("span", { className: "text-[11px] font-mono text-slate-500 dark:text-white/40" }, fmtMs(bar.ms))), /* @__PURE__ */ React8.createElement("div", { className: "h-2 rounded-full bg-slate-100 dark:bg-white/8 overflow-hidden" }, /* @__PURE__ */ React8.createElement(
860
- "div",
861
- {
862
- className: "h-full rounded-full transition-all duration-700",
863
- style: {
864
- width: `${bar.ms / maxMs * 100}%`,
865
- background: bar.color,
866
- opacity: 0.85
867
- }
868
- }
869
- ))))));
1085
+ return /* @__PURE__ */ jsxs7("div", { className: "space-y-3", children: [
1086
+ /* @__PURE__ */ jsxs7("div", { className: "flex items-center justify-between", children: [
1087
+ /* @__PURE__ */ jsx8("span", { className: "text-[11px] text-slate-500 dark:text-white/40", children: "Pipeline stages" }),
1088
+ /* @__PURE__ */ jsxs7("span", { className: "text-[11px] font-semibold text-slate-700 dark:text-white/70", children: [
1089
+ "Total: ",
1090
+ fmtMs(latency.totalMs)
1091
+ ] })
1092
+ ] }),
1093
+ /* @__PURE__ */ jsx8("div", { className: "space-y-2", children: bars.map((bar) => /* @__PURE__ */ jsxs7("div", { className: "space-y-0.5", children: [
1094
+ /* @__PURE__ */ jsxs7("div", { className: "flex items-center justify-between", children: [
1095
+ /* @__PURE__ */ jsx8("span", { className: "text-[11px] text-slate-600 dark:text-white/60", children: bar.label }),
1096
+ /* @__PURE__ */ jsx8("span", { className: "text-[11px] font-mono text-slate-500 dark:text-white/40", children: fmtMs(bar.ms) })
1097
+ ] }),
1098
+ /* @__PURE__ */ jsx8("div", { className: "h-2 rounded-full bg-slate-100 dark:bg-white/8 overflow-hidden", children: /* @__PURE__ */ jsx8(
1099
+ "div",
1100
+ {
1101
+ className: "h-full rounded-full transition-all duration-700",
1102
+ style: {
1103
+ width: `${bar.ms / maxMs * 100}%`,
1104
+ background: bar.color,
1105
+ opacity: 0.85
1106
+ }
1107
+ }
1108
+ ) })
1109
+ ] }, bar.label)) })
1110
+ ] });
870
1111
  }
871
1112
  function TokensTab({ trace }) {
872
1113
  const { tokens } = trace;
873
1114
  if (!tokens) {
874
- return /* @__PURE__ */ React8.createElement("p", { className: "text-[11px] text-slate-400 dark:text-white/30 italic" }, "Token data not available.");
1115
+ return /* @__PURE__ */ jsx8("p", { className: "text-[11px] text-slate-400 dark:text-white/30 italic", children: "Token data not available." });
875
1116
  }
876
1117
  const stats = [
877
1118
  { label: "Prompt Tokens", value: fmtTokens(tokens.promptTokens), color: "text-indigo-600 dark:text-indigo-400" },
878
1119
  { label: "Completion Tokens", value: fmtTokens(tokens.completionTokens), color: "text-emerald-600 dark:text-emerald-400" },
879
1120
  { label: "Total Tokens", value: fmtTokens(tokens.totalTokens), color: "text-slate-700 dark:text-white/80" }
880
1121
  ];
881
- return /* @__PURE__ */ React8.createElement("div", { className: "space-y-3" }, /* @__PURE__ */ React8.createElement("div", { className: "grid grid-cols-3 gap-2" }, stats.map((s) => /* @__PURE__ */ React8.createElement("div", { key: s.label, className: "rounded-lg border border-slate-100 dark:border-white/8 bg-slate-50 dark:bg-white/3 p-2.5 text-center" }, /* @__PURE__ */ React8.createElement("p", { className: `text-lg font-bold ${s.color}` }, s.value), /* @__PURE__ */ React8.createElement("p", { className: "text-[10px] text-slate-400 dark:text-white/30 mt-0.5" }, s.label)))), tokens.estimatedCostUsd != null && /* @__PURE__ */ React8.createElement("div", { className: "flex items-center justify-between rounded-lg border border-emerald-100 dark:border-emerald-500/20 bg-emerald-50 dark:bg-emerald-500/10 px-3 py-2" }, /* @__PURE__ */ React8.createElement("span", { className: "text-[11px] text-emerald-700 dark:text-emerald-400 font-medium" }, "Estimated Cost"), /* @__PURE__ */ React8.createElement("span", { className: "text-[11px] font-bold text-emerald-700 dark:text-emerald-400" }, "$", tokens.estimatedCostUsd < 1e-4 ? tokens.estimatedCostUsd.toExponential(2) : tokens.estimatedCostUsd.toFixed(5), " USD")), /* @__PURE__ */ React8.createElement("div", { className: "h-2 rounded-full overflow-hidden flex" }, /* @__PURE__ */ React8.createElement(
882
- "div",
883
- {
884
- className: "h-full bg-indigo-500 dark:bg-indigo-400",
885
- style: { width: `${tokens.promptTokens / tokens.totalTokens * 100}%` },
886
- title: "Prompt tokens"
887
- }
888
- ), /* @__PURE__ */ React8.createElement(
889
- "div",
890
- {
891
- className: "h-full bg-emerald-500 dark:bg-emerald-400",
892
- style: { width: `${tokens.completionTokens / tokens.totalTokens * 100}%` },
893
- title: "Completion tokens"
894
- }
895
- )), /* @__PURE__ */ React8.createElement("div", { className: "flex gap-3 text-[10px] text-slate-400 dark:text-white/30" }, /* @__PURE__ */ React8.createElement("span", { className: "flex items-center gap-1" }, /* @__PURE__ */ React8.createElement("span", { className: "inline-block w-2 h-2 rounded-full bg-indigo-500" }), " Prompt"), /* @__PURE__ */ React8.createElement("span", { className: "flex items-center gap-1" }, /* @__PURE__ */ React8.createElement("span", { className: "inline-block w-2 h-2 rounded-full bg-emerald-500" }), " Completion")));
1122
+ return /* @__PURE__ */ jsxs7("div", { className: "space-y-3", children: [
1123
+ /* @__PURE__ */ jsx8("div", { className: "grid grid-cols-3 gap-2", children: stats.map((s) => /* @__PURE__ */ jsxs7("div", { className: "rounded-lg border border-slate-100 dark:border-white/8 bg-slate-50 dark:bg-white/3 p-2.5 text-center", children: [
1124
+ /* @__PURE__ */ jsx8("p", { className: `text-lg font-bold ${s.color}`, children: s.value }),
1125
+ /* @__PURE__ */ jsx8("p", { className: "text-[10px] text-slate-400 dark:text-white/30 mt-0.5", children: s.label })
1126
+ ] }, s.label)) }),
1127
+ tokens.estimatedCostUsd != null && /* @__PURE__ */ jsxs7("div", { className: "flex items-center justify-between rounded-lg border border-emerald-100 dark:border-emerald-500/20 bg-emerald-50 dark:bg-emerald-500/10 px-3 py-2", children: [
1128
+ /* @__PURE__ */ jsx8("span", { className: "text-[11px] text-emerald-700 dark:text-emerald-400 font-medium", children: "Estimated Cost" }),
1129
+ /* @__PURE__ */ jsxs7("span", { className: "text-[11px] font-bold text-emerald-700 dark:text-emerald-400", children: [
1130
+ "$",
1131
+ tokens.estimatedCostUsd < 1e-4 ? tokens.estimatedCostUsd.toExponential(2) : tokens.estimatedCostUsd.toFixed(5),
1132
+ " USD"
1133
+ ] })
1134
+ ] }),
1135
+ /* @__PURE__ */ jsxs7("div", { className: "h-2 rounded-full overflow-hidden flex", children: [
1136
+ /* @__PURE__ */ jsx8(
1137
+ "div",
1138
+ {
1139
+ className: "h-full bg-indigo-500 dark:bg-indigo-400",
1140
+ style: { width: `${tokens.promptTokens / tokens.totalTokens * 100}%` },
1141
+ title: "Prompt tokens"
1142
+ }
1143
+ ),
1144
+ /* @__PURE__ */ jsx8(
1145
+ "div",
1146
+ {
1147
+ className: "h-full bg-emerald-500 dark:bg-emerald-400",
1148
+ style: { width: `${tokens.completionTokens / tokens.totalTokens * 100}%` },
1149
+ title: "Completion tokens"
1150
+ }
1151
+ )
1152
+ ] }),
1153
+ /* @__PURE__ */ jsxs7("div", { className: "flex gap-3 text-[10px] text-slate-400 dark:text-white/30", children: [
1154
+ /* @__PURE__ */ jsxs7("span", { className: "flex items-center gap-1", children: [
1155
+ /* @__PURE__ */ jsx8("span", { className: "inline-block w-2 h-2 rounded-full bg-indigo-500" }),
1156
+ " Prompt"
1157
+ ] }),
1158
+ /* @__PURE__ */ jsxs7("span", { className: "flex items-center gap-1", children: [
1159
+ /* @__PURE__ */ jsx8("span", { className: "inline-block w-2 h-2 rounded-full bg-emerald-500" }),
1160
+ " Completion"
1161
+ ] })
1162
+ ] })
1163
+ ] });
896
1164
  }
897
1165
  function HallucinationTab({ trace }) {
898
1166
  if (trace.hallucinationScore == null) {
899
- return /* @__PURE__ */ React8.createElement("p", { className: "text-[11px] text-slate-400 dark:text-white/30 italic" }, "Hallucination scoring not available for this response.");
1167
+ return /* @__PURE__ */ jsx8("p", { className: "text-[11px] text-slate-400 dark:text-white/30 italic", children: "Hallucination scoring not available for this response." });
900
1168
  }
901
1169
  const score = trace.hallucinationScore;
902
1170
  const pct = Math.round(score * 100);
903
1171
  const barColor = pct <= 20 ? "#10b981" : pct <= 50 ? "#f59e0b" : "#ef4444";
904
- return /* @__PURE__ */ React8.createElement("div", { className: "space-y-3" }, /* @__PURE__ */ React8.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ React8.createElement(ScoreBadge, { score }), /* @__PURE__ */ React8.createElement("span", { className: "text-[11px] font-mono text-slate-500 dark:text-white/40" }, pct, "/100")), /* @__PURE__ */ React8.createElement("div", { className: "h-3 rounded-full bg-slate-100 dark:bg-white/8 overflow-hidden" }, /* @__PURE__ */ React8.createElement(
905
- "div",
906
- {
907
- className: "h-full rounded-full transition-all duration-700",
908
- style: { width: `${pct}%`, background: barColor }
909
- }
910
- )), trace.hallucinationReason && /* @__PURE__ */ React8.createElement("div", { className: "rounded-lg border border-slate-100 dark:border-white/8 bg-slate-50 dark:bg-white/3 p-2.5" }, /* @__PURE__ */ React8.createElement("p", { className: "text-[11px] text-slate-500 dark:text-white/40 font-medium mb-0.5" }, "AI self-assessment"), /* @__PURE__ */ React8.createElement("p", { className: "text-[11px] text-slate-700 dark:text-white/70 leading-relaxed" }, trace.hallucinationReason)), /* @__PURE__ */ React8.createElement("div", { className: "flex gap-2 text-[10px] text-slate-400 dark:text-white/30" }, /* @__PURE__ */ React8.createElement("span", { className: "flex items-center gap-1" }, /* @__PURE__ */ React8.createElement("span", { className: "inline-block w-2 h-2 rounded-full bg-emerald-500" }), " 0\u201320%: Grounded"), /* @__PURE__ */ React8.createElement("span", { className: "flex items-center gap-1" }, /* @__PURE__ */ React8.createElement("span", { className: "inline-block w-2 h-2 rounded-full bg-amber-500" }), " 21\u201350%: Uncertain"), /* @__PURE__ */ React8.createElement("span", { className: "flex items-center gap-1" }, /* @__PURE__ */ React8.createElement("span", { className: "inline-block w-2 h-2 rounded-full bg-red-500" }), " 51\u2013100%: Risk")));
1172
+ return /* @__PURE__ */ jsxs7("div", { className: "space-y-3", children: [
1173
+ /* @__PURE__ */ jsxs7("div", { className: "flex items-center justify-between", children: [
1174
+ /* @__PURE__ */ jsx8(ScoreBadge, { score }),
1175
+ /* @__PURE__ */ jsxs7("span", { className: "text-[11px] font-mono text-slate-500 dark:text-white/40", children: [
1176
+ pct,
1177
+ "/100"
1178
+ ] })
1179
+ ] }),
1180
+ /* @__PURE__ */ jsx8("div", { className: "h-3 rounded-full bg-slate-100 dark:bg-white/8 overflow-hidden", children: /* @__PURE__ */ jsx8(
1181
+ "div",
1182
+ {
1183
+ className: "h-full rounded-full transition-all duration-700",
1184
+ style: { width: `${pct}%`, background: barColor }
1185
+ }
1186
+ ) }),
1187
+ trace.hallucinationReason && /* @__PURE__ */ jsxs7("div", { className: "rounded-lg border border-slate-100 dark:border-white/8 bg-slate-50 dark:bg-white/3 p-2.5", children: [
1188
+ /* @__PURE__ */ jsx8("p", { className: "text-[11px] text-slate-500 dark:text-white/40 font-medium mb-0.5", children: "AI self-assessment" }),
1189
+ /* @__PURE__ */ jsx8("p", { className: "text-[11px] text-slate-700 dark:text-white/70 leading-relaxed", children: trace.hallucinationReason })
1190
+ ] }),
1191
+ /* @__PURE__ */ jsxs7("div", { className: "flex gap-2 text-[10px] text-slate-400 dark:text-white/30", children: [
1192
+ /* @__PURE__ */ jsxs7("span", { className: "flex items-center gap-1", children: [
1193
+ /* @__PURE__ */ jsx8("span", { className: "inline-block w-2 h-2 rounded-full bg-emerald-500" }),
1194
+ " 0\u201320%: Grounded"
1195
+ ] }),
1196
+ /* @__PURE__ */ jsxs7("span", { className: "flex items-center gap-1", children: [
1197
+ /* @__PURE__ */ jsx8("span", { className: "inline-block w-2 h-2 rounded-full bg-amber-500" }),
1198
+ " 21\u201350%: Uncertain"
1199
+ ] }),
1200
+ /* @__PURE__ */ jsxs7("span", { className: "flex items-center gap-1", children: [
1201
+ /* @__PURE__ */ jsx8("span", { className: "inline-block w-2 h-2 rounded-full bg-red-500" }),
1202
+ " 51\u2013100%: Risk"
1203
+ ] })
1204
+ ] })
1205
+ ] });
911
1206
  }
912
1207
  function PromptTab({ trace }) {
913
- const [showSystem, setShowSystem] = React8.useState(false);
914
- return /* @__PURE__ */ React8.createElement("div", { className: "space-y-3" }, /* @__PURE__ */ React8.createElement("div", null, /* @__PURE__ */ React8.createElement(
915
- "button",
916
- {
917
- onClick: () => setShowSystem((s) => !s),
918
- className: "flex items-center gap-1.5 text-[11px] font-semibold text-slate-600 dark:text-white/60 hover:text-slate-900 dark:hover:text-white/80 transition-colors mb-1.5"
919
- },
920
- showSystem ? /* @__PURE__ */ React8.createElement(ChevronDown2, { className: "w-3 h-3" }) : /* @__PURE__ */ React8.createElement(ChevronRight2, { className: "w-3 h-3" }),
921
- "System Prompt"
922
- ), showSystem && /* @__PURE__ */ React8.createElement("pre", { className: "text-[10px] font-mono text-slate-600 dark:text-white/60 bg-slate-900 dark:bg-black/30 rounded-lg p-3 overflow-auto max-h-40 whitespace-pre-wrap leading-relaxed" }, trace.systemPrompt || "(empty)")), /* @__PURE__ */ React8.createElement("div", null, /* @__PURE__ */ React8.createElement("p", { className: "text-[11px] font-semibold text-slate-600 dark:text-white/60 mb-1.5" }, "User Prompt"), /* @__PURE__ */ React8.createElement("pre", { className: "text-[10px] font-mono text-slate-600 dark:text-white/60 bg-slate-900 dark:bg-black/30 rounded-lg p-3 overflow-auto max-h-40 whitespace-pre-wrap leading-relaxed" }, trace.userPrompt)));
1208
+ const [showSystem, setShowSystem] = React6.useState(false);
1209
+ return /* @__PURE__ */ jsxs7("div", { className: "space-y-3", children: [
1210
+ /* @__PURE__ */ jsxs7("div", { children: [
1211
+ /* @__PURE__ */ jsxs7(
1212
+ "button",
1213
+ {
1214
+ onClick: () => setShowSystem((s) => !s),
1215
+ className: "flex items-center gap-1.5 text-[11px] font-semibold text-slate-600 dark:text-white/60 hover:text-slate-900 dark:hover:text-white/80 transition-colors mb-1.5",
1216
+ children: [
1217
+ showSystem ? /* @__PURE__ */ jsx8(ChevronDown2, { className: "w-3 h-3" }) : /* @__PURE__ */ jsx8(ChevronRight2, { className: "w-3 h-3" }),
1218
+ "System Prompt"
1219
+ ]
1220
+ }
1221
+ ),
1222
+ showSystem && /* @__PURE__ */ jsx8("pre", { className: "text-[10px] font-mono text-slate-600 dark:text-white/60 bg-slate-900 dark:bg-black/30 rounded-lg p-3 overflow-auto max-h-40 whitespace-pre-wrap leading-relaxed", children: trace.systemPrompt || "(empty)" })
1223
+ ] }),
1224
+ /* @__PURE__ */ jsxs7("div", { children: [
1225
+ /* @__PURE__ */ jsx8("p", { className: "text-[11px] font-semibold text-slate-600 dark:text-white/60 mb-1.5", children: "User Prompt" }),
1226
+ /* @__PURE__ */ jsx8("pre", { className: "text-[10px] font-mono text-slate-600 dark:text-white/60 bg-slate-900 dark:bg-black/30 rounded-lg p-3 overflow-auto max-h-40 whitespace-pre-wrap leading-relaxed", children: trace.userPrompt })
1227
+ ] })
1228
+ ] });
923
1229
  }
924
1230
  function ChunksTab({ trace }) {
925
- const [expanded, setExpanded] = React8.useState(/* @__PURE__ */ new Set());
1231
+ const [expanded, setExpanded] = React6.useState(/* @__PURE__ */ new Set());
926
1232
  const toggle = (i) => setExpanded((prev) => {
927
1233
  const next = new Set(prev);
928
1234
  if (next.has(i)) {
@@ -932,74 +1238,111 @@ function ChunksTab({ trace }) {
932
1238
  }
933
1239
  return next;
934
1240
  });
935
- return /* @__PURE__ */ React8.createElement("div", { className: "space-y-1.5 max-h-64 overflow-y-auto pr-1 custom-scrollbar" }, trace.chunks.map((chunk, i) => {
1241
+ return /* @__PURE__ */ jsx8("div", { className: "space-y-1.5 max-h-64 overflow-y-auto pr-1 custom-scrollbar", children: trace.chunks.map((chunk, i) => {
936
1242
  const isOpen = expanded.has(i);
937
- return /* @__PURE__ */ React8.createElement(
1243
+ return /* @__PURE__ */ jsxs7(
938
1244
  "div",
939
1245
  {
940
- key: String(chunk.id),
941
- className: "rounded-lg border border-slate-100 dark:border-white/8 bg-slate-50 dark:bg-white/3 overflow-hidden"
1246
+ className: "rounded-lg border border-slate-100 dark:border-white/8 bg-slate-50 dark:bg-white/3 overflow-hidden",
1247
+ children: [
1248
+ /* @__PURE__ */ jsxs7(
1249
+ "button",
1250
+ {
1251
+ onClick: () => toggle(i),
1252
+ className: "w-full flex items-center justify-between px-3 py-2 text-left hover:bg-slate-100 dark:hover:bg-white/5 transition-colors",
1253
+ children: [
1254
+ /* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-2", children: [
1255
+ isOpen ? /* @__PURE__ */ jsx8(ChevronDown2, { className: "w-3 h-3 text-slate-400" }) : /* @__PURE__ */ jsx8(ChevronRight2, { className: "w-3 h-3 text-slate-400" }),
1256
+ /* @__PURE__ */ jsxs7("span", { className: "text-[11px] font-medium text-slate-700 dark:text-white/70", children: [
1257
+ "Chunk ",
1258
+ i + 1
1259
+ ] }),
1260
+ /* @__PURE__ */ jsx8("span", { className: "text-[10px] font-mono text-slate-400 dark:text-white/30", children: String(chunk.id).slice(0, 16) })
1261
+ ] }),
1262
+ /* @__PURE__ */ jsx8("span", { className: "text-[10px] font-semibold text-indigo-600 dark:text-indigo-400", children: chunk.score.toFixed(3) })
1263
+ ]
1264
+ }
1265
+ ),
1266
+ isOpen && /* @__PURE__ */ jsxs7("div", { className: "px-3 pb-3 space-y-2 border-t border-slate-100 dark:border-white/5 pt-2", children: [
1267
+ /* @__PURE__ */ jsxs7("div", { children: [
1268
+ /* @__PURE__ */ jsx8("p", { className: "text-[10px] text-slate-400 dark:text-white/30 font-semibold uppercase tracking-wider mb-1", children: "Content" }),
1269
+ /* @__PURE__ */ jsx8("p", { className: "text-[11px] text-slate-600 dark:text-white/60 leading-relaxed whitespace-pre-wrap", children: chunk.content })
1270
+ ] }),
1271
+ Object.keys(chunk.metadata).length > 0 && /* @__PURE__ */ jsxs7("div", { children: [
1272
+ /* @__PURE__ */ jsx8("p", { className: "text-[10px] text-slate-400 dark:text-white/30 font-semibold uppercase tracking-wider mb-1", children: "Metadata" }),
1273
+ /* @__PURE__ */ jsx8("pre", { className: "text-[10px] font-mono text-slate-500 dark:text-white/40 bg-slate-900 dark:bg-black/30 rounded-md p-2 overflow-auto max-h-24", children: JSON.stringify(chunk.metadata, null, 2) })
1274
+ ] })
1275
+ ] })
1276
+ ]
942
1277
  },
943
- /* @__PURE__ */ React8.createElement(
944
- "button",
945
- {
946
- onClick: () => toggle(i),
947
- className: "w-full flex items-center justify-between px-3 py-2 text-left hover:bg-slate-100 dark:hover:bg-white/5 transition-colors"
948
- },
949
- /* @__PURE__ */ React8.createElement("div", { className: "flex items-center gap-2" }, isOpen ? /* @__PURE__ */ React8.createElement(ChevronDown2, { className: "w-3 h-3 text-slate-400" }) : /* @__PURE__ */ React8.createElement(ChevronRight2, { className: "w-3 h-3 text-slate-400" }), /* @__PURE__ */ React8.createElement("span", { className: "text-[11px] font-medium text-slate-700 dark:text-white/70" }, "Chunk ", i + 1), /* @__PURE__ */ React8.createElement("span", { className: "text-[10px] font-mono text-slate-400 dark:text-white/30" }, String(chunk.id).slice(0, 16))),
950
- /* @__PURE__ */ React8.createElement("span", { className: "text-[10px] font-semibold text-indigo-600 dark:text-indigo-400" }, chunk.score.toFixed(3))
951
- ),
952
- isOpen && /* @__PURE__ */ React8.createElement("div", { className: "px-3 pb-3 space-y-2 border-t border-slate-100 dark:border-white/5 pt-2" }, /* @__PURE__ */ React8.createElement("div", null, /* @__PURE__ */ React8.createElement("p", { className: "text-[10px] text-slate-400 dark:text-white/30 font-semibold uppercase tracking-wider mb-1" }, "Content"), /* @__PURE__ */ React8.createElement("p", { className: "text-[11px] text-slate-600 dark:text-white/60 leading-relaxed whitespace-pre-wrap" }, chunk.content)), Object.keys(chunk.metadata).length > 0 && /* @__PURE__ */ React8.createElement("div", null, /* @__PURE__ */ React8.createElement("p", { className: "text-[10px] text-slate-400 dark:text-white/30 font-semibold uppercase tracking-wider mb-1" }, "Metadata"), /* @__PURE__ */ React8.createElement("pre", { className: "text-[10px] font-mono text-slate-500 dark:text-white/40 bg-slate-900 dark:bg-black/30 rounded-md p-2 overflow-auto max-h-24" }, JSON.stringify(chunk.metadata, null, 2))))
1278
+ String(chunk.id)
953
1279
  );
954
- }));
1280
+ }) });
955
1281
  }
956
1282
  var TABS = [
957
- { id: "retrieval", label: "Retrieval", icon: /* @__PURE__ */ React8.createElement(Layers, { className: "w-3 h-3" }) },
958
- { id: "latency", label: "Latency", icon: /* @__PURE__ */ React8.createElement(Clock, { className: "w-3 h-3" }) },
959
- { id: "tokens", label: "Tokens", icon: /* @__PURE__ */ React8.createElement(Cpu, { className: "w-3 h-3" }) },
960
- { id: "hallucination", label: "Grounding", icon: /* @__PURE__ */ React8.createElement(AlertTriangle, { className: "w-3 h-3" }) },
961
- { id: "prompt", label: "Prompt", icon: /* @__PURE__ */ React8.createElement(FileText, { className: "w-3 h-3" }) },
962
- { id: "chunks", label: "Chunks", icon: /* @__PURE__ */ React8.createElement(Zap, { className: "w-3 h-3" }) }
1283
+ { id: "retrieval", label: "Retrieval", icon: /* @__PURE__ */ jsx8(Layers, { className: "w-3 h-3" }) },
1284
+ { id: "latency", label: "Latency", icon: /* @__PURE__ */ jsx8(Clock, { className: "w-3 h-3" }) },
1285
+ { id: "tokens", label: "Tokens", icon: /* @__PURE__ */ jsx8(Cpu, { className: "w-3 h-3" }) },
1286
+ { id: "hallucination", label: "Grounding", icon: /* @__PURE__ */ jsx8(AlertTriangle, { className: "w-3 h-3" }) },
1287
+ { id: "prompt", label: "Prompt", icon: /* @__PURE__ */ jsx8(FileText, { className: "w-3 h-3" }) },
1288
+ { id: "chunks", label: "Chunks", icon: /* @__PURE__ */ jsx8(Zap, { className: "w-3 h-3" }) }
963
1289
  ];
964
1290
  function ObservabilityPanel({ trace, primaryColor = "#6366f1" }) {
965
- const [activeTab, setActiveTab] = React8.useState("retrieval");
966
- return /* @__PURE__ */ React8.createElement("div", { className: "mt-2 w-full rounded-xl border border-slate-200 dark:border-white/8 bg-white dark:bg-slate-900/60 shadow-sm overflow-hidden text-[12px]" }, /* @__PURE__ */ React8.createElement(
967
- "div",
968
- {
969
- className: "flex items-center gap-2 px-3 py-2 border-b border-slate-100 dark:border-white/8",
970
- style: { background: `${primaryColor}08` }
971
- },
972
- /* @__PURE__ */ React8.createElement(
973
- "span",
1291
+ const [activeTab, setActiveTab] = React6.useState("retrieval");
1292
+ return /* @__PURE__ */ jsxs7("div", { className: "mt-2 w-[500px] max-w-full rounded-xl border border-slate-200 dark:border-white/8 bg-white dark:bg-slate-900/60 shadow-sm overflow-hidden text-[12px]", children: [
1293
+ /* @__PURE__ */ jsxs7(
1294
+ "div",
974
1295
  {
975
- className: "inline-flex items-center gap-1 text-[10px] font-bold uppercase tracking-wider",
976
- style: { color: primaryColor }
977
- },
978
- /* @__PURE__ */ React8.createElement(Zap, { className: "w-3 h-3" }),
979
- "Observability Trace"
1296
+ className: "flex items-center gap-2 px-3 py-2 border-b border-slate-100 dark:border-white/8",
1297
+ style: { background: `${primaryColor}08` },
1298
+ children: [
1299
+ /* @__PURE__ */ jsxs7(
1300
+ "span",
1301
+ {
1302
+ className: "inline-flex items-center gap-1 text-[10px] font-bold uppercase tracking-wider",
1303
+ style: { color: primaryColor },
1304
+ children: [
1305
+ /* @__PURE__ */ jsx8(Zap, { className: "w-3 h-3" }),
1306
+ "Observability Trace"
1307
+ ]
1308
+ }
1309
+ ),
1310
+ /* @__PURE__ */ jsx8("span", { className: "text-[10px] text-slate-400 dark:text-white/30 ml-auto font-mono", children: trace.requestId })
1311
+ ]
1312
+ }
980
1313
  ),
981
- /* @__PURE__ */ React8.createElement("span", { className: "text-[10px] text-slate-400 dark:text-white/30 ml-auto font-mono" }, trace.requestId)
982
- ), /* @__PURE__ */ React8.createElement("div", { className: "flex border-b border-slate-100 dark:border-white/8 overflow-x-auto" }, TABS.map((tab) => /* @__PURE__ */ React8.createElement(
983
- "button",
984
- {
985
- key: tab.id,
986
- onClick: () => setActiveTab(tab.id),
987
- className: `flex items-center gap-1.5 px-3 py-2 text-[10px] font-semibold whitespace-nowrap transition-colors border-b-2 ${activeTab === tab.id ? "border-b-2 text-indigo-600 dark:text-indigo-400" : "border-transparent text-slate-400 dark:text-white/30 hover:text-slate-600 dark:hover:text-white/60"}`,
988
- style: activeTab === tab.id ? { borderBottomColor: primaryColor, color: primaryColor } : {}
989
- },
990
- tab.icon,
991
- tab.label
992
- ))), /* @__PURE__ */ React8.createElement("div", { className: "p-3" }, activeTab === "retrieval" && /* @__PURE__ */ React8.createElement(RetrievalTab, { trace }), activeTab === "latency" && /* @__PURE__ */ React8.createElement(LatencyTab, { trace }), activeTab === "tokens" && /* @__PURE__ */ React8.createElement(TokensTab, { trace }), activeTab === "hallucination" && /* @__PURE__ */ React8.createElement(HallucinationTab, { trace }), activeTab === "prompt" && /* @__PURE__ */ React8.createElement(PromptTab, { trace }), activeTab === "chunks" && /* @__PURE__ */ React8.createElement(ChunksTab, { trace })));
1314
+ /* @__PURE__ */ jsx8("div", { className: "flex border-b border-slate-100 dark:border-white/8 overflow-x-auto", children: TABS.map((tab) => /* @__PURE__ */ jsxs7(
1315
+ "button",
1316
+ {
1317
+ onClick: () => setActiveTab(tab.id),
1318
+ className: `flex items-center gap-1.5 px-3 py-2 text-[10px] font-semibold whitespace-nowrap transition-colors border-b-2 ${activeTab === tab.id ? "border-b-2 text-indigo-600 dark:text-indigo-400" : "border-transparent text-slate-400 dark:text-white/30 hover:text-slate-600 dark:hover:text-white/60"}`,
1319
+ style: activeTab === tab.id ? { borderBottomColor: primaryColor, color: primaryColor } : {},
1320
+ children: [
1321
+ tab.icon,
1322
+ tab.label
1323
+ ]
1324
+ },
1325
+ tab.id
1326
+ )) }),
1327
+ /* @__PURE__ */ jsxs7("div", { className: "p-3", children: [
1328
+ activeTab === "retrieval" && /* @__PURE__ */ jsx8(RetrievalTab, { trace }),
1329
+ activeTab === "latency" && /* @__PURE__ */ jsx8(LatencyTab, { trace }),
1330
+ activeTab === "tokens" && /* @__PURE__ */ jsx8(TokensTab, { trace }),
1331
+ activeTab === "hallucination" && /* @__PURE__ */ jsx8(HallucinationTab, { trace }),
1332
+ activeTab === "prompt" && /* @__PURE__ */ jsx8(PromptTab, { trace }),
1333
+ activeTab === "chunks" && /* @__PURE__ */ jsx8(ChunksTab, { trace })
1334
+ ] })
1335
+ ] });
993
1336
  }
994
1337
 
995
1338
  // src/components/HourglassLoader.tsx
996
- import React9 from "react";
1339
+ import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
997
1340
  var HourglassLoader = ({
998
1341
  size = 16,
999
1342
  primaryColor = "#10b981",
1000
1343
  glow = false
1001
1344
  }) => {
1002
- return /* @__PURE__ */ React9.createElement(
1345
+ return /* @__PURE__ */ jsx9(
1003
1346
  "svg",
1004
1347
  {
1005
1348
  xmlns: "http://www.w3.org/2000/svg",
@@ -1010,62 +1353,140 @@ var HourglassLoader = ({
1010
1353
  height: size,
1011
1354
  background: "transparent",
1012
1355
  filter: glow ? `drop-shadow(0 0 4px ${primaryColor})` : "none"
1013
- }
1014
- },
1015
- /* @__PURE__ */ React9.createElement("g", null, /* @__PURE__ */ React9.createElement(
1016
- "animateTransform",
1017
- {
1018
- attributeName: "transform",
1019
- type: "rotate",
1020
- calcMode: "spline",
1021
- values: "0 50 50; 0 50 50; 180 50 50",
1022
- keyTimes: "0; 0.8; 1",
1023
- keySplines: "0 0 1 1; 0.4 0 0.2 1",
1024
- dur: "2s",
1025
- repeatCount: "indefinite"
1026
- }
1027
- ), /* @__PURE__ */ React9.createElement(
1028
- "path",
1029
- {
1030
- d: "M 25 15 L 75 15 L 75 20 L 55 50 L 75 80 L 75 85 L 25 85 L 25 80 L 45 50 L 25 20 Z",
1031
- fill: "none",
1032
- stroke: primaryColor,
1033
- strokeWidth: "5",
1034
- strokeLinejoin: "round",
1035
- strokeLinecap: "round"
1036
- }
1037
- ), /* @__PURE__ */ React9.createElement("path", { fill: primaryColor }, /* @__PURE__ */ React9.createElement(
1038
- "animate",
1039
- {
1040
- attributeName: "d",
1041
- values: "M 30 20 L 70 20 L 50 50 L 50 50 Z; M 50 50 L 50 50 L 50 50 L 50 50 Z; M 50 50 L 50 50 L 50 50 L 50 50 Z",
1042
- keyTimes: "0; 0.8; 1",
1043
- dur: "2s",
1044
- repeatCount: "indefinite"
1045
- }
1046
- )), /* @__PURE__ */ React9.createElement("path", { fill: primaryColor }, /* @__PURE__ */ React9.createElement(
1047
- "animate",
1048
- {
1049
- attributeName: "d",
1050
- values: "M 30 80 L 70 80 L 70 80 L 30 80 Z; M 30 80 L 70 80 L 50 50 L 50 50 Z; M 30 80 L 70 80 L 50 50 L 50 50 Z",
1051
- keyTimes: "0; 0.8; 1",
1052
- dur: "2s",
1053
- repeatCount: "indefinite"
1054
- }
1055
- )), /* @__PURE__ */ React9.createElement("line", { x1: "50", y1: "50", x2: "50", y2: "80", stroke: primaryColor, strokeWidth: "3" }, /* @__PURE__ */ React9.createElement(
1056
- "animate",
1057
- {
1058
- attributeName: "opacity",
1059
- values: "0; 1; 1; 0; 0",
1060
- keyTimes: "0; 0.1; 0.7; 0.8; 1",
1061
- dur: "2s",
1062
- repeatCount: "indefinite"
1063
- }
1064
- )))
1356
+ },
1357
+ children: /* @__PURE__ */ jsxs8("g", { children: [
1358
+ /* @__PURE__ */ jsx9(
1359
+ "animateTransform",
1360
+ {
1361
+ attributeName: "transform",
1362
+ type: "rotate",
1363
+ calcMode: "spline",
1364
+ values: "0 50 50; 0 50 50; 180 50 50",
1365
+ keyTimes: "0; 0.8; 1",
1366
+ keySplines: "0 0 1 1; 0.4 0 0.2 1",
1367
+ dur: "2s",
1368
+ repeatCount: "indefinite"
1369
+ }
1370
+ ),
1371
+ /* @__PURE__ */ jsx9(
1372
+ "path",
1373
+ {
1374
+ d: "M 25 15 L 75 15 L 75 20 L 55 50 L 75 80 L 75 85 L 25 85 L 25 80 L 45 50 L 25 20 Z",
1375
+ fill: "none",
1376
+ stroke: primaryColor,
1377
+ strokeWidth: "5",
1378
+ strokeLinejoin: "round",
1379
+ strokeLinecap: "round"
1380
+ }
1381
+ ),
1382
+ /* @__PURE__ */ jsx9("path", { fill: primaryColor, children: /* @__PURE__ */ jsx9(
1383
+ "animate",
1384
+ {
1385
+ attributeName: "d",
1386
+ values: "M 30 20 L 70 20 L 50 50 L 50 50 Z; M 50 50 L 50 50 L 50 50 L 50 50 Z; M 50 50 L 50 50 L 50 50 L 50 50 Z",
1387
+ keyTimes: "0; 0.8; 1",
1388
+ dur: "2s",
1389
+ repeatCount: "indefinite"
1390
+ }
1391
+ ) }),
1392
+ /* @__PURE__ */ jsx9("path", { fill: primaryColor, children: /* @__PURE__ */ jsx9(
1393
+ "animate",
1394
+ {
1395
+ attributeName: "d",
1396
+ values: "M 30 80 L 70 80 L 70 80 L 30 80 Z; M 30 80 L 70 80 L 50 50 L 50 50 Z; M 30 80 L 70 80 L 50 50 L 50 50 Z",
1397
+ keyTimes: "0; 0.8; 1",
1398
+ dur: "2s",
1399
+ repeatCount: "indefinite"
1400
+ }
1401
+ ) }),
1402
+ /* @__PURE__ */ jsx9("line", { x1: "50", y1: "50", x2: "50", y2: "80", stroke: primaryColor, strokeWidth: "3", children: /* @__PURE__ */ jsx9(
1403
+ "animate",
1404
+ {
1405
+ attributeName: "opacity",
1406
+ values: "0; 1; 1; 0; 0",
1407
+ keyTimes: "0; 0.1; 0.7; 0.8; 1",
1408
+ dur: "2s",
1409
+ repeatCount: "indefinite"
1410
+ }
1411
+ ) })
1412
+ ] })
1413
+ }
1065
1414
  );
1066
1415
  };
1067
1416
  var HourglassLoader_default = HourglassLoader;
1068
1417
 
1418
+ // src/utils/synonyms.ts
1419
+ var FIELD_SYNONYMS = {
1420
+ name: ["product", "item", "title", "label", "heading", "subject", "product name", "item name"],
1421
+ price: ["cost", "amount", "msrp", "price", "rate", "value", "price_usd"],
1422
+ brand: ["manufacturer", "vendor", "make", "company", "brand_name", "supplier"],
1423
+ image: [
1424
+ "imageUrl",
1425
+ "thumbnail",
1426
+ "img",
1427
+ "url",
1428
+ "photo",
1429
+ "picture",
1430
+ "media",
1431
+ "image_url",
1432
+ "main_image",
1433
+ "product_image",
1434
+ "thumb"
1435
+ ],
1436
+ stock: [
1437
+ "inventory",
1438
+ "quantity",
1439
+ "count",
1440
+ "availability",
1441
+ "stock_level",
1442
+ "inStock",
1443
+ "is_available",
1444
+ "in stock",
1445
+ "status"
1446
+ ],
1447
+ description: ["summary", "content", "body", "text", "info", "details"],
1448
+ link: ["url", "href", "product_url", "page_url", "link"]
1449
+ };
1450
+ function addSynonyms(customSynonyms) {
1451
+ for (const [key, aliases] of Object.entries(customSynonyms)) {
1452
+ if (!FIELD_SYNONYMS[key]) {
1453
+ FIELD_SYNONYMS[key] = [];
1454
+ }
1455
+ const existing = new Set(FIELD_SYNONYMS[key].map((s) => s.toLowerCase()));
1456
+ for (const alias of aliases) {
1457
+ if (!existing.has(alias.toLowerCase())) {
1458
+ FIELD_SYNONYMS[key].push(alias);
1459
+ existing.add(alias.toLowerCase());
1460
+ }
1461
+ }
1462
+ }
1463
+ }
1464
+ function resolveMetadataValue(meta, uiKey) {
1465
+ var _a;
1466
+ const synonyms = (_a = FIELD_SYNONYMS[uiKey]) != null ? _a : [];
1467
+ const keys = Object.keys(meta);
1468
+ const systemKeys = ["namespace", "filename", "filesize", "filetype", "docid", "uploadedat", "dimension", "chunkindex"];
1469
+ let match = keys.find((k) => k.toLowerCase() === uiKey.toLowerCase());
1470
+ if (match !== void 0) return meta[match];
1471
+ match = keys.find((k) => synonyms.map((s) => s.toLowerCase()).includes(k.toLowerCase()));
1472
+ if (match !== void 0) return meta[match];
1473
+ const isBlacklisted = (kl) => {
1474
+ return systemKeys.includes(kl) || kl.startsWith("option1") || kl.startsWith("option2") || kl.startsWith("option3");
1475
+ };
1476
+ match = keys.find((k) => {
1477
+ const kl = k.toLowerCase();
1478
+ if (isBlacklisted(kl)) return false;
1479
+ return kl.includes(uiKey.toLowerCase());
1480
+ });
1481
+ if (match !== void 0) return meta[match];
1482
+ match = keys.find((k) => {
1483
+ const kl = k.toLowerCase();
1484
+ if (isBlacklisted(kl)) return false;
1485
+ return synonyms.some((sk) => kl.includes(sk.toLowerCase()) || sk.toLowerCase().includes(kl));
1486
+ });
1487
+ return match !== void 0 ? meta[match] : void 0;
1488
+ }
1489
+
1069
1490
  // src/utils/ProductExtractor.ts
1070
1491
  function sanitizeJson(raw) {
1071
1492
  let s = raw.trim();
@@ -1242,7 +1663,6 @@ function extractProductsFromSources(sources, isUser) {
1242
1663
  const brand = resolveMetadataValue(m, "brand");
1243
1664
  const price = resolveMetadataValue(m, "price");
1244
1665
  const description = resolveMetadataValue(m, "description");
1245
- console.log("\u{1F680} ~ extractProductsFromSources ~ description:", s);
1246
1666
  return {
1247
1667
  id: s.id,
1248
1668
  name: (_b = name != null ? name : s.content.split("\n")[0]) != null ? _b : "Unknown Product",
@@ -1255,7 +1675,7 @@ function extractProductsFromSources(sources, isUser) {
1255
1675
  };
1256
1676
  });
1257
1677
  }
1258
- function extractProductsFromContent(content, payloadText, payloadCandidates, productsFromSources) {
1678
+ function extractProductsFromContent(content, payloadText, payloadCandidates, productsFromSources, isStreaming = false) {
1259
1679
  var _a, _b;
1260
1680
  const jsonRegex = /```(?:json|ui)?\s*([\s\S]*?)\s*```/g;
1261
1681
  const products = [];
@@ -1298,7 +1718,7 @@ function extractProductsFromContent(content, payloadText, payloadCandidates, pro
1298
1718
  }
1299
1719
  const bulletRegex = /^[ \t]*(?:[•*-]|\d+\.)\s+(?:\*\*)?([^\n\-\$–—\(]+?)(?:\*\*)?(?:\s*\(?Price\s*[:\-–—]?\s*)?(?:\s*[:\-–—]\s*|\s+)\$?([\d,.]+)(?:\s*USD)?/gim;
1300
1720
  const matches = Array.from(cleanContent.matchAll(bulletRegex));
1301
- if (matches.length >= 2) {
1721
+ if (!isStreaming && matches.length >= 2) {
1302
1722
  const normalize = (s) => s.toLowerCase().replace(/[^a-z0-9]/g, "");
1303
1723
  for (const match of matches) {
1304
1724
  let name = ((_a = match[1]) == null ? void 0 : _a.trim()) || "";
@@ -1350,10 +1770,11 @@ function deduplicateProducts(productsFromSources, productsFromContent, messageCo
1350
1770
  }
1351
1771
 
1352
1772
  // src/components/MarkdownComponents.tsx
1353
- import React11 from "react";
1773
+ import React8 from "react";
1354
1774
 
1355
1775
  // src/components/UIDispatcher.tsx
1356
- import React10 from "react";
1776
+ import React7 from "react";
1777
+ import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
1357
1778
  function normalizeTabularRows(rows, columns) {
1358
1779
  if (!Array.isArray(rows)) return [];
1359
1780
  const SYNONYMS = {
@@ -1421,7 +1842,7 @@ function resolveStructuredRows(config) {
1421
1842
  }
1422
1843
  function UIDispatcher({ rawContent, primaryColor, accentColor, isStreaming, onAddToCart, viewportSize = "large" }) {
1423
1844
  var _a;
1424
- const result = React10.useMemo(() => {
1845
+ const result = React7.useMemo(() => {
1425
1846
  try {
1426
1847
  const clean = rawContent.replace(/^```[a-z]*\s*/i, "").replace(/```\s*$/, "").trim();
1427
1848
  const parsed = JSON.parse(sanitizeJson(extractLikelyJsonBlock(clean)));
@@ -1466,72 +1887,87 @@ function UIDispatcher({ rawContent, primaryColor, accentColor, isStreaming, onAd
1466
1887
  }
1467
1888
  }, [rawContent, isStreaming]);
1468
1889
  if ("loading" in result) {
1469
- return /* @__PURE__ */ React10.createElement("div", { className: "my-4 p-8 bg-slate-50 dark:bg-white/5 rounded-xl border border-dashed border-slate-300 dark:border-white/10 flex flex-col items-center justify-center gap-3 animate-pulse" }, /* @__PURE__ */ React10.createElement("div", { className: "w-5 h-5 border-2 border-indigo-500 border-t-transparent rounded-full animate-spin" }), /* @__PURE__ */ React10.createElement("p", { className: "text-xs text-slate-500 font-medium italic" }, "Preparing view..."));
1890
+ return /* @__PURE__ */ jsxs9("div", { className: "my-4 p-8 bg-slate-50 dark:bg-white/5 rounded-xl border border-dashed border-slate-300 dark:border-white/10 flex flex-col items-center justify-center gap-3 animate-pulse", children: [
1891
+ /* @__PURE__ */ jsx10("div", { className: "w-5 h-5 border-2 border-indigo-500 border-t-transparent rounded-full animate-spin" }),
1892
+ /* @__PURE__ */ jsx10("p", { className: "text-xs text-slate-500 font-medium italic", children: "Preparing view..." })
1893
+ ] });
1470
1894
  }
1471
1895
  if ("error" in result) {
1472
- return /* @__PURE__ */ React10.createElement("pre", { className: "p-4 my-2 bg-slate-900 text-slate-100 rounded-lg text-[10px] overflow-auto max-h-40" }, /* @__PURE__ */ React10.createElement("code", null, rawContent));
1896
+ return /* @__PURE__ */ jsx10("pre", { className: "p-4 my-2 bg-slate-900 text-slate-100 rounded-lg text-[10px] overflow-auto max-h-40", children: /* @__PURE__ */ jsx10("code", { children: rawContent }) });
1473
1897
  }
1474
1898
  const { config } = result;
1475
1899
  const isCompact = viewportSize === "compact";
1476
1900
  const hasInsights = Array.isArray(config.insights) && config.insights.length > 0;
1477
1901
  const hasDescription = typeof config.description === "string" && config.description.trim().length > 0;
1478
- console.log("\u{1F680} ~ UIDispatcher ~ description:", config.description);
1479
- console.log("\u{1F680} ~ UIDispatcher ~ hasDescription:", hasDescription);
1480
1902
  switch (config.view) {
1481
1903
  case "chart":
1482
- return /* @__PURE__ */ React10.createElement("div", { className: `${isCompact ? "my-4 p-3" : "my-6 p-4"} bg-white dark:bg-slate-900 rounded-2xl border border-slate-200 dark:border-white/10 shadow-sm overflow-hidden` }, config.title && /* @__PURE__ */ React10.createElement("h4", { className: `${isCompact ? "text-[11px] mb-3" : "text-xs mb-4"} font-semibold text-slate-500 px-2` }, config.title), hasDescription && /* @__PURE__ */ React10.createElement("p", { className: `px-2 ${isCompact ? "text-xs" : "text-sm"} text-slate-500 dark:text-white/60` }, config.description), /* @__PURE__ */ React10.createElement(
1483
- DynamicChart,
1484
- {
1485
- config: {
1486
- type: config.chartType || "bar",
1487
- data: config.data,
1488
- xAxisKey: config.xAxisKey,
1489
- dataKeys: config.dataKeys,
1490
- colors: config.colors
1904
+ return /* @__PURE__ */ jsxs9("div", { className: `${isCompact ? "my-4 p-3" : "my-6 p-4"} bg-white dark:bg-slate-900 rounded-2xl border border-slate-200 dark:border-white/10 shadow-sm overflow-hidden`, children: [
1905
+ config.title && /* @__PURE__ */ jsx10("h4", { className: `${isCompact ? "text-[11px] mb-3" : "text-xs mb-4"} font-semibold text-slate-500 px-2`, children: config.title }),
1906
+ hasDescription && /* @__PURE__ */ jsx10("p", { className: `px-2 ${isCompact ? "text-xs" : "text-sm"} text-slate-500 dark:text-white/60`, children: config.description }),
1907
+ /* @__PURE__ */ jsx10(
1908
+ DynamicChart,
1909
+ {
1910
+ config: {
1911
+ type: config.chartType || "bar",
1912
+ data: config.data,
1913
+ xAxisKey: config.xAxisKey,
1914
+ dataKeys: config.dataKeys,
1915
+ colors: config.colors
1916
+ },
1917
+ primaryColor,
1918
+ accentColor,
1919
+ viewportSize,
1920
+ isStreaming
1921
+ }
1922
+ ),
1923
+ hasInsights && /* @__PURE__ */ jsx10("div", { className: "mt-4 flex flex-wrap gap-2 px-2", children: (_a = config.insights) == null ? void 0 : _a.map((insight, i) => /* @__PURE__ */ jsx10(
1924
+ "span",
1925
+ {
1926
+ className: `rounded-full border border-emerald-200 bg-emerald-50 ${isCompact ? "px-2.5 py-1 text-[10px]" : "px-3 py-1 text-[11px]"} font-medium text-emerald-700 dark:border-emerald-500/20 dark:bg-emerald-500/10 dark:text-emerald-300`,
1927
+ children: String(insight)
1491
1928
  },
1492
- primaryColor,
1493
- accentColor,
1494
- viewportSize,
1495
- isStreaming
1496
- }
1497
- ), hasInsights && /* @__PURE__ */ React10.createElement("div", { className: "mt-4 flex flex-wrap gap-2 px-2" }, (_a = config.insights) == null ? void 0 : _a.map((insight, i) => /* @__PURE__ */ React10.createElement(
1498
- "span",
1499
- {
1500
- key: `insight-${i}`,
1501
- className: `rounded-full border border-emerald-200 bg-emerald-50 ${isCompact ? "px-2.5 py-1 text-[10px]" : "px-3 py-1 text-[11px]"} font-medium text-emerald-700 dark:border-emerald-500/20 dark:bg-emerald-500/10 dark:text-emerald-300`
1502
- },
1503
- String(insight)
1504
- ))));
1929
+ `insight-${i}`
1930
+ )) })
1931
+ ] });
1505
1932
  case "carousel":
1506
- return /* @__PURE__ */ React10.createElement("div", { className: "my-4" }, config.title && /* @__PURE__ */ React10.createElement("h4", { className: `${isCompact ? "mb-1.5 text-[11px]" : "mb-2 text-xs"} font-semibold text-slate-500` }, config.title), hasDescription && /* @__PURE__ */ React10.createElement("p", { className: `mb-3 ${isCompact ? "text-xs" : "text-sm"} text-slate-500 dark:text-white/60` }, config.description), /* @__PURE__ */ React10.createElement(ProductCarousel, { products: config.data.map((item) => {
1507
- var _a2;
1508
- return __spreadProps(__spreadValues({}, item), {
1509
- image: (_a2 = item.image) != null ? _a2 : typeof resolveImage === "function" ? resolveImage(item) : void 0
1510
- });
1511
- }), primaryColor, onAddToCart }));
1933
+ return /* @__PURE__ */ jsxs9("div", { className: "my-4", children: [
1934
+ config.title && /* @__PURE__ */ jsx10("h4", { className: `${isCompact ? "mb-1.5 text-[11px]" : "mb-2 text-xs"} font-semibold text-slate-500`, children: config.title }),
1935
+ hasDescription && /* @__PURE__ */ jsx10("p", { className: `mb-3 ${isCompact ? "text-xs" : "text-sm"} text-slate-500 dark:text-white/60`, children: config.description }),
1936
+ /* @__PURE__ */ jsx10(ProductCarousel, { products: config.data.map((item) => {
1937
+ var _a2;
1938
+ return __spreadProps(__spreadValues({}, item), {
1939
+ image: (_a2 = item.image) != null ? _a2 : typeof resolveImage === "function" ? resolveImage(item) : void 0
1940
+ });
1941
+ }), primaryColor, onAddToCart })
1942
+ ] });
1512
1943
  case "table":
1513
- return /* @__PURE__ */ React10.createElement("div", { className: `${isCompact ? "my-3 p-3 max-h-[320px]" : "my-4 p-4 max-h-[400px]"} bg-white dark:bg-slate-900 rounded-xl border border-slate-200 dark:border-white/10 shadow-sm overflow-auto` }, config.title && /* @__PURE__ */ React10.createElement("h4", { className: `${isCompact ? "text-[11px]" : "text-xs"} font-semibold text-slate-500 mb-2` }, config.title), hasDescription && /* @__PURE__ */ React10.createElement("p", { className: `mb-3 ${isCompact ? "text-xs" : "text-sm"} text-slate-500 dark:text-white/60` }, config.description), /* @__PURE__ */ React10.createElement(
1514
- VisualizationRenderer,
1515
- {
1516
- data: {
1517
- type: "table",
1518
- title: config.title || "",
1519
- description: config.description,
1944
+ return /* @__PURE__ */ jsxs9("div", { className: `${isCompact ? "my-3 p-3 max-h-[320px]" : "my-4 p-4 max-h-[400px]"} bg-white dark:bg-slate-900 rounded-xl border border-slate-200 dark:border-white/10 shadow-sm overflow-auto`, children: [
1945
+ config.title && /* @__PURE__ */ jsx10("h4", { className: `${isCompact ? "text-[11px]" : "text-xs"} font-semibold text-slate-500 mb-2`, children: config.title }),
1946
+ hasDescription && /* @__PURE__ */ jsx10("p", { className: `mb-3 ${isCompact ? "text-xs" : "text-sm"} text-slate-500 dark:text-white/60`, children: config.description }),
1947
+ /* @__PURE__ */ jsx10(
1948
+ VisualizationRenderer,
1949
+ {
1520
1950
  data: {
1521
- columns: config.columns || Object.keys(config.data[0] || {}),
1522
- rows: config.data.map((row) => Object.values(row))
1523
- }
1524
- },
1525
- primaryColor,
1526
- isStreaming
1527
- }
1528
- ));
1951
+ type: "table",
1952
+ title: config.title || "",
1953
+ description: config.description,
1954
+ data: {
1955
+ columns: config.columns || Object.keys(config.data[0] || {}),
1956
+ rows: config.data.map((row) => Object.values(row))
1957
+ }
1958
+ },
1959
+ primaryColor,
1960
+ isStreaming
1961
+ }
1962
+ )
1963
+ ] });
1529
1964
  default:
1530
1965
  return null;
1531
1966
  }
1532
1967
  }
1533
1968
 
1534
1969
  // src/components/MarkdownComponents.tsx
1970
+ import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
1535
1971
  function createMarkdownComponents({
1536
1972
  primaryColor,
1537
1973
  accentColor,
@@ -1540,66 +1976,75 @@ function createMarkdownComponents({
1540
1976
  viewportSize
1541
1977
  }) {
1542
1978
  return {
1543
- table: (_a) => {
1979
+ p: (_a) => {
1544
1980
  var props = __objRest(_a, []);
1981
+ return /* @__PURE__ */ jsx11("p", __spreadValues({ className: "whitespace-pre-line" }, props));
1982
+ },
1983
+ table: (_b) => {
1984
+ var props = __objRest(_b, []);
1545
1985
  if (isStreaming) {
1546
- return /* @__PURE__ */ React11.createElement("div", { className: "my-5 p-6 bg-slate-50 dark:bg-white/5 rounded-xl border border-dashed border-slate-300 dark:border-white/10 flex items-center justify-center gap-3 select-none" }, /* @__PURE__ */ React11.createElement("div", { className: "w-4 h-4 border-2 border-indigo-500 border-t-transparent rounded-full animate-spin" }), /* @__PURE__ */ React11.createElement("p", { className: "text-xs text-slate-500 font-medium italic animate-pulse" }, "Generating data table..."));
1986
+ return /* @__PURE__ */ jsxs10("div", { className: "my-5 p-6 bg-slate-50 dark:bg-white/5 rounded-xl border border-dashed border-slate-300 dark:border-white/10 flex items-center justify-center gap-3 select-none", children: [
1987
+ /* @__PURE__ */ jsx11("div", { className: "w-4 h-4 border-2 border-indigo-500 border-t-transparent rounded-full animate-spin" }),
1988
+ /* @__PURE__ */ jsx11("p", { className: "text-xs text-slate-500 font-medium italic animate-pulse", children: "Generating data table..." })
1989
+ ] });
1547
1990
  }
1548
- return /* @__PURE__ */ React11.createElement("div", { className: "not-prose overflow-hidden my-5 rounded-xl border border-slate-200 dark:border-white/10 shadow-sm bg-white dark:bg-slate-900/50" }, /* @__PURE__ */ React11.createElement("div", { className: "overflow-x-auto" }, /* @__PURE__ */ React11.createElement(
1991
+ return /* @__PURE__ */ jsx11("div", { className: "not-prose overflow-hidden my-5 rounded-xl border border-slate-200 dark:border-white/10 shadow-sm bg-white dark:bg-slate-900/50", children: /* @__PURE__ */ jsx11("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsx11(
1549
1992
  "table",
1550
1993
  __spreadValues({
1551
1994
  className: "!table w-full text-left border-collapse min-w-[400px] text-sm"
1552
1995
  }, props)
1553
- )));
1996
+ ) }) });
1554
1997
  },
1555
- thead: (_b) => {
1556
- var props = __objRest(_b, []);
1557
- return /* @__PURE__ */ React11.createElement(
1998
+ thead: (_c) => {
1999
+ var props = __objRest(_c, []);
2000
+ return /* @__PURE__ */ jsx11(
1558
2001
  "thead",
1559
2002
  __spreadValues({
1560
2003
  className: "!table-header-group bg-slate-50 dark:bg-white/5 border-b border-slate-200 dark:border-white/10"
1561
2004
  }, props)
1562
2005
  );
1563
2006
  },
1564
- tbody: (_c) => {
1565
- var props = __objRest(_c, []);
1566
- return /* @__PURE__ */ React11.createElement("tbody", __spreadValues({ className: "!table-row-group divide-y divide-slate-100 dark:divide-white/5" }, props));
1567
- },
1568
- tr: (_d) => {
2007
+ tbody: (_d) => {
1569
2008
  var props = __objRest(_d, []);
1570
- return /* @__PURE__ */ React11.createElement(
2009
+ return /* @__PURE__ */ jsx11("tbody", __spreadValues({ className: "!table-row-group divide-y divide-slate-100 dark:divide-white/5" }, props));
2010
+ },
2011
+ tr: (_e) => {
2012
+ var props = __objRest(_e, []);
2013
+ return /* @__PURE__ */ jsx11(
1571
2014
  "tr",
1572
2015
  __spreadValues({
1573
2016
  className: "!table-row hover:bg-slate-50/70 dark:hover:bg-white/5 transition-colors"
1574
2017
  }, props)
1575
2018
  );
1576
2019
  },
1577
- th: (_e) => {
1578
- var _f = _e, { children } = _f, props = __objRest(_f, ["children"]);
1579
- return /* @__PURE__ */ React11.createElement(
2020
+ th: (_f) => {
2021
+ var _g = _f, { children } = _g, props = __objRest(_g, ["children"]);
2022
+ return /* @__PURE__ */ jsx11(
1580
2023
  "th",
1581
- __spreadValues({
2024
+ __spreadProps(__spreadValues({
1582
2025
  className: "!table-cell px-4 py-3 font-bold text-slate-700 dark:text-white/90 whitespace-nowrap text-[11px] uppercase tracking-wider text-left"
1583
- }, props),
1584
- normaliseChild(children)
2026
+ }, props), {
2027
+ children: normaliseChild(children)
2028
+ })
1585
2029
  );
1586
2030
  },
1587
- td: (_g) => {
1588
- var _h = _g, { children } = _h, props = __objRest(_h, ["children"]);
1589
- return /* @__PURE__ */ React11.createElement(
2031
+ td: (_h) => {
2032
+ var _i = _h, { children } = _i, props = __objRest(_i, ["children"]);
2033
+ return /* @__PURE__ */ jsx11(
1590
2034
  "td",
1591
- __spreadValues({
2035
+ __spreadProps(__spreadValues({
1592
2036
  className: "!table-cell px-4 py-3 text-slate-600 dark:text-white/70 whitespace-nowrap text-sm"
1593
- }, props),
1594
- normaliseChild(children)
2037
+ }, props), {
2038
+ children: normaliseChild(children)
2039
+ })
1595
2040
  );
1596
2041
  },
1597
- code(_i) {
1598
- var _j = _i, {
2042
+ code(_j) {
2043
+ var _k = _j, {
1599
2044
  inline,
1600
2045
  className,
1601
2046
  children
1602
- } = _j, props = __objRest(_j, [
2047
+ } = _k, props = __objRest(_k, [
1603
2048
  "inline",
1604
2049
  "className",
1605
2050
  "children"
@@ -1608,7 +2053,7 @@ function createMarkdownComponents({
1608
2053
  const lang = (_a = /language-(\w+)/.exec(className != null ? className : "")) == null ? void 0 : _a[1];
1609
2054
  if (!inline && (lang === "ui" || lang === "chart" || lang === "json")) {
1610
2055
  const content = String(children != null ? children : "").trim();
1611
- return /* @__PURE__ */ React11.createElement(
2056
+ return /* @__PURE__ */ jsx11(
1612
2057
  UIDispatcher,
1613
2058
  {
1614
2059
  rawContent: content,
@@ -1623,7 +2068,7 @@ function createMarkdownComponents({
1623
2068
  if (!inline) {
1624
2069
  const content = String(children != null ? children : "").trim();
1625
2070
  if (content.startsWith("{") && content.endsWith("}")) {
1626
- return /* @__PURE__ */ React11.createElement(
2071
+ return /* @__PURE__ */ jsx11(
1627
2072
  UIDispatcher,
1628
2073
  {
1629
2074
  rawContent: content,
@@ -1636,18 +2081,19 @@ function createMarkdownComponents({
1636
2081
  );
1637
2082
  }
1638
2083
  }
1639
- return /* @__PURE__ */ React11.createElement("code", __spreadValues({ className }, props), typeof children === "string" || typeof children === "number" ? children : JSON.stringify(children));
2084
+ return /* @__PURE__ */ jsx11("code", __spreadProps(__spreadValues({ className }, props), { children: typeof children === "string" || typeof children === "number" ? children : JSON.stringify(children) }));
1640
2085
  }
1641
2086
  };
1642
2087
  }
1643
2088
  function normaliseChild(children) {
1644
- if (typeof children === "object" && children !== null && !Array.isArray(children) && !React11.isValidElement(children)) {
2089
+ if (typeof children === "object" && children !== null && !Array.isArray(children) && !React8.isValidElement(children)) {
1645
2090
  return JSON.stringify(children);
1646
2091
  }
1647
2092
  return children;
1648
2093
  }
1649
2094
 
1650
2095
  // src/components/MessageBubble.tsx
2096
+ import { jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
1651
2097
  function MessageBubble({
1652
2098
  message,
1653
2099
  sources,
@@ -1660,13 +2106,13 @@ function MessageBubble({
1660
2106
  const isUser = message.role === "user";
1661
2107
  const isCompact = viewportSize === "compact";
1662
2108
  const isMedium = viewportSize === "medium";
1663
- const [showSources, setShowSources] = React12.useState(false);
1664
- const [showTrace, setShowTrace] = React12.useState(false);
1665
- const structuredContent = React12.useMemo(
2109
+ const [showSources, setShowSources] = React9.useState(false);
2110
+ const [showTrace, setShowTrace] = React9.useState(false);
2111
+ const structuredContent = React9.useMemo(
1666
2112
  () => isUser ? { payload: null, text: message.content } : extractStructuredPayload(message.content),
1667
2113
  [isUser, message.content]
1668
2114
  );
1669
- const hasRichUI = React12.useMemo(() => {
2115
+ const hasRichUI = React9.useMemo(() => {
1670
2116
  if (message.uiTransformation) {
1671
2117
  const type = message.uiTransformation.type;
1672
2118
  if (type && !["text", "table"].includes(type)) return true;
@@ -1677,10 +2123,10 @@ function MessageBubble({
1677
2123
  return false;
1678
2124
  }, [message.uiTransformation, structuredContent.payload]);
1679
2125
  const shouldRenderStructuredOnly = !isUser && hasRichUI && isLikelyUiOnlyMessage(structuredContent.text);
1680
- const productsFromSources = React12.useMemo(() => {
2126
+ const productsFromSources = React9.useMemo(() => {
1681
2127
  return extractProductsFromSources(sources, isUser);
1682
2128
  }, [sources, isUser]);
1683
- const { productsFromContent, cleanContent } = React12.useMemo(() => {
2129
+ const { productsFromContent, cleanContent } = React9.useMemo(() => {
1684
2130
  if (isUser) {
1685
2131
  return { productsFromContent: [], cleanContent: message.content };
1686
2132
  }
@@ -1692,13 +2138,14 @@ function MessageBubble({
1692
2138
  message.content,
1693
2139
  structuredContent.text,
1694
2140
  payloadCandidates,
1695
- productsFromSources
2141
+ productsFromSources,
2142
+ isStreaming
1696
2143
  );
1697
- }, [message.content, isUser, structuredContent, productsFromSources]);
1698
- const allProducts = React12.useMemo(() => {
2144
+ }, [message.content, isUser, structuredContent, productsFromSources, isStreaming]);
2145
+ const allProducts = React9.useMemo(() => {
1699
2146
  return deduplicateProducts(productsFromSources, productsFromContent, message.content);
1700
2147
  }, [productsFromSources, productsFromContent, message.content]);
1701
- const processedMarkdown = React12.useMemo(() => {
2148
+ const processedMarkdown = React9.useMemo(() => {
1702
2149
  let raw = structuredContent.payload ? structuredContent.text : cleanContent || message.content;
1703
2150
  const hasStructuredUiBlock = Boolean(structuredContent.payload) || /```(?:ui|json|chart)\s*[\s\S]*?"(?:view|chartType|type|data|items|rows|products|results)"\s*:/i.test(raw);
1704
2151
  raw = raw.replace(/([^\n])\n\|/g, "$1\n\n|").replace(/(\|[^\n]*\|)\n\n+(?=\|)/g, "$1\n");
@@ -1721,93 +2168,123 @@ ${match.trim()}
1721
2168
  }
1722
2169
  return raw;
1723
2170
  }, [cleanContent, message.content, isStreaming, structuredContent]);
1724
- const markdownComponents = React12.useMemo(
2171
+ const markdownComponents = React9.useMemo(
1725
2172
  () => createMarkdownComponents({ primaryColor, accentColor, isStreaming, onAddToCart, viewportSize }),
1726
2173
  [primaryColor, accentColor, isStreaming, onAddToCart, viewportSize]
1727
2174
  );
1728
- return /* @__PURE__ */ React12.createElement("div", { className: `flex ${isCompact ? "gap-2" : "gap-3"} ${isUser ? "flex-row-reverse" : "flex-row"} items-start` }, /* @__PURE__ */ React12.createElement(
1729
- "div",
1730
- {
1731
- className: `flex-shrink-0 ${isCompact ? "w-7 h-7" : "w-8 h-8"} rounded-full flex items-center justify-center shadow-lg ${isUser ? "text-white" : "bg-slate-100 dark:bg-white/10 text-slate-700 dark:text-white/80"}`,
1732
- style: isUser ? { background: `linear-gradient(135deg, ${primaryColor}, ${accentColor})` } : {}
1733
- },
1734
- isUser ? /* @__PURE__ */ React12.createElement(User, { className: `${isCompact ? "w-3.5 h-3.5" : "w-4 h-4"} text-white` }) : /* @__PURE__ */ React12.createElement(Bot, { className: `${isCompact ? "w-3.5 h-3.5" : "w-4 h-4"}` })
1735
- ), /* @__PURE__ */ React12.createElement("div", { className: `flex flex-col gap-1 min-w-0 ${isCompact ? "max-w-[94%]" : isMedium ? "max-w-[92%]" : "max-w-[90%]"} ${isUser ? "items-end" : "items-start"}` }, /* @__PURE__ */ React12.createElement(
1736
- "div",
1737
- {
1738
- className: `relative ${isCompact ? "px-3 py-2.5 text-[13px]" : "px-4 py-3 text-sm"} rounded-2xl leading-relaxed shadow-sm dark:shadow-lg ${isUser ? "text-white rounded-tr-sm" : "bg-white dark:bg-white/5 border border-slate-200 dark:border-white/10 text-slate-800 dark:text-white/90 rounded-tl-sm"}`,
1739
- style: isUser ? { background: `linear-gradient(135deg, ${primaryColor}, ${accentColor})` } : {}
1740
- },
1741
- isStreaming && !message.content ? /* @__PURE__ */ React12.createElement("span", { className: "flex items-center gap-1 py-1" }, /* @__PURE__ */ React12.createElement("span", { className: "w-1.5 h-1.5 rounded-full bg-slate-400 dark:bg-white/60 animate-bounce [animation-delay:0ms]" }), /* @__PURE__ */ React12.createElement("span", { className: "w-1.5 h-1.5 rounded-full bg-slate-400 dark:bg-white/60 animate-bounce [animation-delay:150ms]" }), /* @__PURE__ */ React12.createElement("span", { className: "w-1.5 h-1.5 rounded-full bg-slate-400 dark:bg-white/60 animate-bounce [animation-delay:300ms]" })) : /* @__PURE__ */ React12.createElement("div", { className: `prose ${isCompact ? "prose-xs" : "prose-sm"} max-w-none break-words ${isUser ? "prose-invert" : "dark:prose-invert"}` }, !isUser && structuredContent.payload && /* @__PURE__ */ React12.createElement(
1742
- UIDispatcher,
1743
- {
1744
- rawContent: structuredContent.payload,
1745
- primaryColor,
1746
- accentColor,
1747
- isStreaming,
1748
- onAddToCart,
1749
- viewportSize
1750
- }
1751
- ), !shouldRenderStructuredOnly && /* @__PURE__ */ React12.createElement(ReactMarkdown, { components: markdownComponents }, processedMarkdown), isStreaming && /* @__PURE__ */ React12.createElement("span", { className: "inline-flex items-center gap-1.5 ml-2 text-emerald-500 animate-pulse align-middle text-xs font-medium" }, /* @__PURE__ */ React12.createElement(
1752
- HourglassLoader_default,
1753
- {
1754
- size: 18,
1755
- primaryColor,
1756
- accentColor,
1757
- glow: false
1758
- }
1759
- ), "Thinking..."))
1760
- ), (() => {
1761
- var _a, _b;
1762
- if (isUser || structuredContent.payload || !message.uiTransformation) return null;
1763
- const ui = message.uiTransformation;
1764
- const textContent = (_b = (_a = ui.data) == null ? void 0 : _a.content) != null ? _b : "";
1765
- const shouldShow = ui.type === "table" && allProducts.length === 0 || !["text", "table"].includes(ui.type) || ui.type === "text" && !hasRichUI && allProducts.length === 0 && textContent && !processedMarkdown.toLowerCase().includes(textContent.trim().toLowerCase());
1766
- if (!shouldShow) return null;
1767
- return /* @__PURE__ */ React12.createElement("div", { className: "w-full mt-3" }, /* @__PURE__ */ React12.createElement(
1768
- VisualizationRenderer,
2175
+ return /* @__PURE__ */ jsxs11("div", { className: `flex ${isCompact ? "gap-2" : "gap-3"} ${isUser ? "flex-row-reverse" : "flex-row"} items-start`, children: [
2176
+ /* @__PURE__ */ jsx12(
2177
+ "div",
1769
2178
  {
1770
- data: ui,
1771
- primaryColor,
1772
- onAddToCart,
1773
- className: "rounded-3xl border border-slate-200/60 dark:border-white/10 bg-white/90 dark:bg-slate-900/80 p-4",
1774
- isStreaming
2179
+ className: `flex-shrink-0 ${isCompact ? "w-7 h-7" : "w-8 h-8"} rounded-full flex items-center justify-center shadow-lg ${isUser ? "text-white" : "bg-slate-100 dark:bg-white/10 text-slate-700 dark:text-white/80"}`,
2180
+ style: isUser ? { background: `linear-gradient(135deg, ${primaryColor}, ${accentColor})` } : {},
2181
+ children: isUser ? /* @__PURE__ */ jsx12(User, { className: `${isCompact ? "w-3.5 h-3.5" : "w-4 h-4"} text-white` }) : /* @__PURE__ */ jsx12(Bot, { className: `${isCompact ? "w-3.5 h-3.5" : "w-4 h-4"}` })
1775
2182
  }
1776
- ));
1777
- })(), !isUser && !hasRichUI && allProducts.length > 0 && /* @__PURE__ */ React12.createElement("div", { className: "w-full mt-1" }, /* @__PURE__ */ React12.createElement(
1778
- ProductCarousel,
1779
- {
1780
- products: allProducts,
1781
- primaryColor,
1782
- onAddToCart
1783
- }
1784
- )), !isUser && /* @__PURE__ */ React12.createElement("div", { className: "flex items-center gap-4 mt-1 w-full flex-wrap" }, sources && sources.length > 0 && /* @__PURE__ */ React12.createElement(
1785
- "button",
1786
- {
1787
- onClick: () => setShowSources((s) => !s),
1788
- className: "text-[11px] text-indigo-400 hover:text-indigo-300 transition-colors flex items-center gap-1"
1789
- },
1790
- showSources ? /* @__PURE__ */ React12.createElement(ChevronDown3, { className: "w-3 h-3" }) : /* @__PURE__ */ React12.createElement(ChevronRight3, { className: "w-3 h-3" }),
1791
- sources.length,
1792
- " source",
1793
- sources.length !== 1 ? "s" : "",
1794
- " used"
1795
- ), message.trace && /* @__PURE__ */ React12.createElement(
1796
- "button",
1797
- {
1798
- onClick: () => setShowTrace((t) => !t),
1799
- className: "text-[11px] text-emerald-500 hover:text-emerald-400 transition-colors flex items-center gap-1"
1800
- },
1801
- /* @__PURE__ */ React12.createElement(Activity, { className: "w-3 h-3" }),
1802
- showTrace ? "Hide Trace" : "Trace"
1803
- )), /* @__PURE__ */ React12.createElement("div", { className: "w-full flex flex-col gap-2 min-w-0" }, showSources && sources && sources.length > 0 && /* @__PURE__ */ React12.createElement("div", { className: "mt-1 flex flex-col gap-2" }, sources.map((src, i) => /* @__PURE__ */ React12.createElement(SourceCard, { key: src.id, source: src, index: i }))), showTrace && message.trace && /* @__PURE__ */ React12.createElement(ObservabilityPanel, { trace: message.trace, primaryColor }))));
2183
+ ),
2184
+ /* @__PURE__ */ jsxs11("div", { className: `flex flex-col gap-1 min-w-0 ${isCompact ? "max-w-[94%]" : isMedium ? "max-w-[92%]" : "max-w-[90%]"} ${isUser ? "items-end" : "items-start"}`, children: [
2185
+ /* @__PURE__ */ jsx12(
2186
+ "div",
2187
+ {
2188
+ className: `relative ${isCompact ? "px-3 py-2.5 text-[13px]" : "px-4 py-3 text-sm"} rounded-2xl leading-relaxed shadow-sm dark:shadow-lg ${isUser ? "text-white rounded-tr-sm" : "bg-white dark:bg-white/5 border border-slate-200 dark:border-white/10 text-slate-800 dark:text-white/90 rounded-tl-sm"}`,
2189
+ style: isUser ? { background: `linear-gradient(135deg, ${primaryColor}, ${accentColor})` } : {},
2190
+ children: isStreaming && !message.content ? /* @__PURE__ */ jsxs11("span", { className: "flex items-center gap-1 py-1", children: [
2191
+ /* @__PURE__ */ jsx12("span", { className: "w-1.5 h-1.5 rounded-full bg-slate-400 dark:bg-white/60 animate-bounce [animation-delay:0ms]" }),
2192
+ /* @__PURE__ */ jsx12("span", { className: "w-1.5 h-1.5 rounded-full bg-slate-400 dark:bg-white/60 animate-bounce [animation-delay:150ms]" }),
2193
+ /* @__PURE__ */ jsx12("span", { className: "w-1.5 h-1.5 rounded-full bg-slate-400 dark:bg-white/60 animate-bounce [animation-delay:300ms]" })
2194
+ ] }) : /* @__PURE__ */ jsxs11("div", { className: `prose ${isCompact ? "prose-xs" : "prose-sm"} max-w-none break-words ${isUser ? "prose-invert" : "dark:prose-invert"}`, children: [
2195
+ !isUser && structuredContent.payload && /* @__PURE__ */ jsx12(
2196
+ UIDispatcher,
2197
+ {
2198
+ rawContent: structuredContent.payload,
2199
+ primaryColor,
2200
+ accentColor,
2201
+ isStreaming,
2202
+ onAddToCart,
2203
+ viewportSize
2204
+ }
2205
+ ),
2206
+ !shouldRenderStructuredOnly && /* @__PURE__ */ jsx12(ReactMarkdown, { components: markdownComponents, children: processedMarkdown }),
2207
+ isStreaming && /* @__PURE__ */ jsxs11("span", { className: "inline-flex items-center gap-1.5 ml-2 text-emerald-500 animate-pulse align-middle text-xs font-medium", children: [
2208
+ /* @__PURE__ */ jsx12(
2209
+ HourglassLoader_default,
2210
+ {
2211
+ size: 18,
2212
+ primaryColor,
2213
+ accentColor,
2214
+ glow: false
2215
+ }
2216
+ ),
2217
+ "Thinking..."
2218
+ ] })
2219
+ ] })
2220
+ }
2221
+ ),
2222
+ (() => {
2223
+ var _a, _b;
2224
+ if (isUser || structuredContent.payload || !message.uiTransformation) return null;
2225
+ const ui = message.uiTransformation;
2226
+ const textContent = (_b = (_a = ui.data) == null ? void 0 : _a.content) != null ? _b : "";
2227
+ const shouldShow = ui.type === "table" && allProducts.length === 0 || !["text", "table"].includes(ui.type) || ui.type === "text" && !hasRichUI && allProducts.length === 0 && textContent && !processedMarkdown.toLowerCase().includes(textContent.trim().toLowerCase());
2228
+ if (!shouldShow) return null;
2229
+ return /* @__PURE__ */ jsx12("div", { className: "w-full mt-3", children: /* @__PURE__ */ jsx12(
2230
+ VisualizationRenderer,
2231
+ {
2232
+ data: ui,
2233
+ primaryColor,
2234
+ onAddToCart,
2235
+ className: "rounded-3xl border border-slate-200/60 dark:border-white/10 bg-white/90 dark:bg-slate-900/80 p-4",
2236
+ isStreaming
2237
+ }
2238
+ ) });
2239
+ })(),
2240
+ !isUser && !hasRichUI && allProducts.length > 0 && /* @__PURE__ */ jsx12("div", { className: "w-full mt-1", children: /* @__PURE__ */ jsx12(
2241
+ ProductCarousel,
2242
+ {
2243
+ products: allProducts,
2244
+ primaryColor,
2245
+ onAddToCart
2246
+ }
2247
+ ) }),
2248
+ !isUser && /* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-4 mt-1 w-full flex-wrap", children: [
2249
+ sources && sources.length > 0 && /* @__PURE__ */ jsxs11(
2250
+ "button",
2251
+ {
2252
+ onClick: () => setShowSources((s) => !s),
2253
+ className: "text-[11px] text-indigo-400 hover:text-indigo-300 transition-colors flex items-center gap-1",
2254
+ children: [
2255
+ showSources ? /* @__PURE__ */ jsx12(ChevronDown3, { className: "w-3 h-3" }) : /* @__PURE__ */ jsx12(ChevronRight3, { className: "w-3 h-3" }),
2256
+ sources.length,
2257
+ " source",
2258
+ sources.length !== 1 ? "s" : "",
2259
+ " used"
2260
+ ]
2261
+ }
2262
+ ),
2263
+ message.trace && /* @__PURE__ */ jsxs11(
2264
+ "button",
2265
+ {
2266
+ onClick: () => setShowTrace((t) => !t),
2267
+ className: "text-[11px] text-emerald-500 hover:text-emerald-400 transition-colors flex items-center gap-1",
2268
+ children: [
2269
+ /* @__PURE__ */ jsx12(Activity, { className: "w-3 h-3" }),
2270
+ showTrace ? "Hide Trace" : "Trace"
2271
+ ]
2272
+ }
2273
+ )
2274
+ ] }),
2275
+ /* @__PURE__ */ jsxs11("div", { className: "w-full flex flex-col gap-2 min-w-0", children: [
2276
+ showSources && sources && sources.length > 0 && /* @__PURE__ */ jsx12("div", { className: "mt-1 flex flex-col gap-2", children: sources.map((src, i) => /* @__PURE__ */ jsx12(SourceCard, { source: src, index: i }, src.id)) }),
2277
+ showTrace && message.trace && /* @__PURE__ */ jsx12(ObservabilityPanel, { trace: message.trace, primaryColor })
2278
+ ] })
2279
+ ] })
2280
+ ] });
1804
2281
  }
1805
2282
 
1806
2283
  // src/hooks/useRagChat.ts
1807
2284
  import { useState as useState4, useCallback, useRef as useRef3, useEffect as useEffect3 } from "react";
1808
2285
 
1809
2286
  // src/hooks/useStoredMessages.ts
1810
- import * as React13 from "react";
2287
+ import * as React10 from "react";
1811
2288
  function readStoredMessages(storageKey) {
1812
2289
  if (typeof window === "undefined") {
1813
2290
  return [];
@@ -1824,8 +2301,8 @@ function readStoredMessages(storageKey) {
1824
2301
  }
1825
2302
  }
1826
2303
  function useStoredMessages(storageKey, persist) {
1827
- const [messages, setMessages] = React13.useState(() => persist ? readStoredMessages(storageKey) : []);
1828
- React13.useEffect(() => {
2304
+ const [messages, setMessages] = React10.useState(() => persist ? readStoredMessages(storageKey) : []);
2305
+ React10.useEffect(() => {
1829
2306
  if (!persist || typeof window === "undefined") {
1830
2307
  return;
1831
2308
  }
@@ -2010,6 +2487,7 @@ function useRagChat(projectId, options = {}) {
2010
2487
  }
2011
2488
 
2012
2489
  // src/components/ChatWindow.tsx
2490
+ import { jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
2013
2491
  function ChatWindow({
2014
2492
  className = "",
2015
2493
  style,
@@ -2163,203 +2641,260 @@ function ChatWindow({
2163
2641
  }, 800);
2164
2642
  return () => clearTimeout(timer);
2165
2643
  }, [input, projectId]);
2166
- return /* @__PURE__ */ React14.createElement(
2644
+ return /* @__PURE__ */ jsxs12(
2167
2645
  "div",
2168
2646
  {
2169
2647
  ref: windowRef,
2170
2648
  className: `relative flex flex-col border border-slate-200 dark:border-white/10 shadow-2xl transition-all duration-300 ${currentRadius} ${isGlass ? "bg-white/90 dark:bg-[#0f0f1a]/90 backdrop-blur-xl" : "bg-white dark:bg-[#0f0f1a]"} ${className}`,
2171
- style: __spreadValues({ "--primary": ui.primaryColor, "--accent": ui.accentColor }, style)
2172
- },
2173
- onResizeStart && /* @__PURE__ */ React14.createElement(
2174
- "div",
2175
- {
2176
- onMouseDown: onResizeStart,
2177
- className: "absolute top-0 left-0 w-6 h-6 cursor-nw-resize z-[100] group flex items-start justify-start p-1",
2178
- title: "Drag to resize"
2179
- },
2180
- /* @__PURE__ */ React14.createElement("div", { className: "w-2.5 h-2.5 border-t-2 border-l-2 border-slate-300 dark:border-white/20 group-hover:border-slate-500 dark:group-hover:border-white/50 transition-colors rounded-tl-[2px]" })
2181
- ),
2182
- /* @__PURE__ */ React14.createElement(
2183
- "div",
2184
- {
2185
- className: "flex items-center justify-between px-5 py-4 border-b border-slate-200 dark:border-white/10",
2186
- style: { background: `linear-gradient(135deg, ${ui.primaryColor}15, ${ui.accentColor}10)` }
2187
- },
2188
- /* @__PURE__ */ React14.createElement("div", { className: "flex items-center gap-3" }, ui.logoUrl ? (
2189
- // eslint-disable-next-line @next/next/no-img-element
2190
- /* @__PURE__ */ React14.createElement("img", { src: ui.logoUrl, alt: "logo", className: "w-8 h-8 rounded-lg object-cover" })
2191
- ) : /* @__PURE__ */ React14.createElement(
2192
- "div",
2193
- {
2194
- className: `w-9 h-9 flex items-center justify-center shadow-md ${ui.borderRadius === "full" ? "rounded-full" : "rounded-xl"}`,
2195
- style: { background: `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` }
2196
- },
2197
- /* @__PURE__ */ React14.createElement(Bot2, { className: "w-5 h-5 text-white" })
2198
- ), /* @__PURE__ */ React14.createElement("div", null, /* @__PURE__ */ React14.createElement("h2", { className: "text-slate-900 dark:text-white font-semibold text-sm leading-tight" }, ui.title), ui.poweredBy && /* @__PURE__ */ React14.createElement("p", { className: "text-slate-500 dark:text-white/40 text-[11px] leading-tight" }, `Powered by ${ui.poweredBy}`))),
2199
- /* @__PURE__ */ React14.createElement("div", { className: "flex items-center gap-1.5" }, /* @__PURE__ */ React14.createElement("span", { className: "flex items-center gap-1 text-[10px] text-emerald-500 dark:text-emerald-400 mr-2" }, /* @__PURE__ */ React14.createElement("span", { className: "w-1.5 h-1.5 rounded-full bg-emerald-500 dark:bg-emerald-400 animate-pulse" }), "Online"), /* @__PURE__ */ React14.createElement("div", { className: "flex items-center bg-slate-100/50 dark:bg-white/5 rounded-lg p-0.5 border border-slate-200/50 dark:border-white/5" }, mounted && messages.length > 0 && /* @__PURE__ */ React14.createElement(
2200
- "button",
2201
- {
2202
- onClick: clearHistory,
2203
- title: "Clear conversation",
2204
- className: "w-7 h-7 rounded-md flex items-center justify-center text-slate-400 hover:text-rose-500 dark:text-white/40 dark:hover:text-rose-400 hover:bg-white dark:hover:bg-white/10 transition-all cursor-pointer"
2205
- },
2206
- /* @__PURE__ */ React14.createElement(Trash2, { className: "w-3.5 h-3.5" })
2207
- ), isResized && onResetResize && /* @__PURE__ */ React14.createElement(
2208
- "button",
2209
- {
2210
- onClick: onResetResize,
2211
- title: "Reset to default size",
2212
- className: "w-7 h-7 rounded-md flex items-center justify-center text-slate-400 hover:text-blue-500 dark:text-white/40 dark:hover:text-blue-400 hover:bg-white dark:hover:bg-white/10 transition-all cursor-pointer"
2213
- },
2214
- /* @__PURE__ */ React14.createElement(RotateCcw, { className: "w-3.5 h-3.5" })
2215
- ), onMaximize && /* @__PURE__ */ React14.createElement(
2216
- "button",
2217
- {
2218
- onClick: onMaximize,
2219
- title: isMaximized ? "Minimize" : "Maximize",
2220
- className: "w-7 h-7 rounded-md flex items-center justify-center text-slate-400 hover:text-blue-500 dark:text-white/40 dark:hover:text-blue-400 hover:bg-white dark:hover:bg-white/10 transition-all cursor-pointer"
2221
- },
2222
- isMaximized ? /* @__PURE__ */ React14.createElement(Minimize2, { className: "w-3.5 h-3.5" }) : /* @__PURE__ */ React14.createElement(Maximize2, { className: "w-3.5 h-3.5" })
2223
- ), showClose && onClose && /* @__PURE__ */ React14.createElement(
2224
- "button",
2225
- {
2226
- onClick: onClose,
2227
- title: "Close chat",
2228
- className: "w-7 h-7 rounded-md flex items-center justify-center text-slate-400 hover:text-slate-600 dark:text-white/40 dark:hover:text-white/70 hover:bg-white dark:hover:bg-white/10 transition-all cursor-pointer"
2229
- },
2230
- /* @__PURE__ */ React14.createElement(X2, { className: "w-4 h-4" })
2231
- )))
2232
- ),
2233
- /* @__PURE__ */ React14.createElement("div", { className: "flex-1 overflow-y-auto px-4 py-4 space-y-5 scrollbar-thin scrollbar-thumb-slate-200 dark:scrollbar-thumb-white/10 scrollbar-track-transparent min-h-0 bg-slate-50 dark:bg-transparent" }, !mounted || isEmpty ? (
2234
- /* Welcome state */
2235
- /* @__PURE__ */ React14.createElement("div", { className: "h-full flex flex-col items-center justify-center text-center gap-4 px-6 py-12" }, /* @__PURE__ */ React14.createElement(
2236
- "div",
2237
- {
2238
- className: `w-16 h-16 flex items-center justify-center shadow-lg ${ui.borderRadius === "full" ? "rounded-full" : "rounded-2xl"}`,
2239
- style: { background: `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` }
2240
- },
2241
- /* @__PURE__ */ React14.createElement(Sparkles, { className: "w-8 h-8 text-white" })
2242
- ), /* @__PURE__ */ React14.createElement("div", null, /* @__PURE__ */ React14.createElement("p", { className: "text-slate-800 dark:text-white/80 font-medium leading-relaxed" }, ui.welcomeMessage), /* @__PURE__ */ React14.createElement("p", { className: "text-slate-500 dark:text-white/30 text-sm mt-2" }, "Ask a question to get started")), /* @__PURE__ */ React14.createElement("div", { className: "flex flex-wrap gap-2 justify-center mt-2" }, CHAT_SUGGESTIONS.map(
2243
- (suggestion) => /* @__PURE__ */ React14.createElement(
2244
- "button",
2649
+ style: __spreadValues({ "--primary": ui.primaryColor, "--accent": ui.accentColor }, style),
2650
+ children: [
2651
+ onResizeStart && /* @__PURE__ */ jsx13(
2652
+ "div",
2245
2653
  {
2246
- key: suggestion,
2247
- onClick: () => {
2248
- var _a2;
2249
- setInput(suggestion);
2250
- (_a2 = inputRef.current) == null ? void 0 : _a2.focus();
2251
- },
2252
- className: "px-3 py-1.5 rounded-full text-xs border border-slate-200 dark:border-white/10 text-slate-600 dark:text-white/50 hover:text-slate-900 dark:hover:text-white/80 hover:border-slate-300 dark:hover:border-white/20 hover:bg-slate-100 dark:hover:bg-white/5 transition-all"
2253
- },
2254
- suggestion
2255
- )
2256
- )))
2257
- ) : messages.map((msg, index) => /* @__PURE__ */ React14.createElement(
2258
- MessageBubble,
2259
- {
2260
- key: msg.id,
2261
- message: msg,
2262
- sources: msg.sources,
2263
- isStreaming: isLoading && index === messages.length - 1 && msg.role === "assistant",
2264
- primaryColor: ui.primaryColor,
2265
- accentColor: ui.accentColor,
2266
- onAddToCart,
2267
- viewportSize
2268
- }
2269
- )), isLoading && ((_a = messages[messages.length - 1]) == null ? void 0 : _a.role) !== "assistant" && /* @__PURE__ */ React14.createElement(
2270
- MessageBubble,
2271
- {
2272
- message: { id: "loading", role: "assistant", content: "", createdAt: (/* @__PURE__ */ new Date()).toISOString() },
2273
- isStreaming: true,
2274
- primaryColor: ui.primaryColor,
2275
- accentColor: ui.accentColor,
2276
- onAddToCart,
2277
- viewportSize
2278
- }
2279
- ), error && /* @__PURE__ */ React14.createElement("div", { className: "flex items-center gap-2 text-rose-500 dark:text-rose-400 text-sm bg-rose-50 dark:bg-rose-400/10 border border-rose-200 dark:border-rose-400/20 rounded-xl px-4 py-3" }, /* @__PURE__ */ React14.createElement(TriangleAlert, { className: "w-4 h-4 flex-shrink-0" }), /* @__PURE__ */ React14.createElement("span", null, error)), /* @__PURE__ */ React14.createElement("div", { ref: bottomRef })),
2280
- isUploadModalOpen && /* @__PURE__ */ React14.createElement("div", { className: "absolute inset-0 z-50 flex items-center justify-center p-4 bg-slate-900/50 backdrop-blur-sm rounded-inherit" }, /* @__PURE__ */ React14.createElement("div", { className: "relative w-full max-w-md bg-white dark:bg-[#0f0f1a] rounded-2xl shadow-2xl overflow-hidden animate-in zoom-in-95 duration-200" }, /* @__PURE__ */ React14.createElement(
2281
- "button",
2282
- {
2283
- onClick: () => setIsUploadModalOpen(false),
2284
- className: "absolute top-4 right-4 p-1.5 rounded-lg text-slate-400 hover:text-slate-600 hover:bg-slate-100 dark:hover:text-white/80 dark:hover:bg-white/10 transition-colors z-10"
2285
- },
2286
- /* @__PURE__ */ React14.createElement(X2, { className: "w-5 h-5" })
2287
- ), /* @__PURE__ */ React14.createElement(
2288
- DocumentUpload,
2289
- {
2290
- namespace: projectId,
2291
- onUploadComplete: () => setIsUploadModalOpen(false)
2292
- }
2293
- ))),
2294
- /* @__PURE__ */ React14.createElement("div", { className: `px-4 pb-4 pt-2 border-t border-slate-200 dark:border-white/10 ${isGlass ? "bg-transparent" : "bg-white dark:bg-[#0f0f1a]"}` }, (suggestions.length > 0 || isSuggesting) && !isLoading && /* @__PURE__ */ React14.createElement("div", { className: "mb-3 flex flex-wrap gap-2 animate-in fade-in slide-in-from-bottom-2 duration-300" }, suggestions.map((suggestion) => /* @__PURE__ */ React14.createElement(
2295
- "button",
2296
- {
2297
- key: suggestion,
2298
- onClick: () => {
2299
- var _a2;
2300
- setInput(suggestion);
2301
- setSuggestions([]);
2302
- (_a2 = inputRef.current) == null ? void 0 : _a2.focus();
2303
- },
2304
- className: "flex items-center gap-1.5 px-3 py-1.5 rounded-xl text-[11px] font-medium bg-white dark:bg-white/5 border border-slate-200 dark:border-white/10 text-slate-600 dark:text-white/60 hover:text-slate-900 dark:hover:text-white/90 hover:border-slate-300 dark:hover:border-white/20 transition-all shadow-sm cursor-pointer group"
2305
- },
2306
- /* @__PURE__ */ React14.createElement(Sparkles, { className: "w-3 h-3 text-amber-400" }),
2307
- suggestion
2308
- )), isSuggesting && suggestions.length === 0 && /* @__PURE__ */ React14.createElement("div", { className: "flex items-center gap-1.5 px-3 py-1.5 rounded-xl text-[11px] font-medium text-slate-400 dark:text-white/30 animate-pulse" }, /* @__PURE__ */ React14.createElement(Sparkles, { className: "w-3 h-3" }), "Thinking...")), /* @__PURE__ */ React14.createElement("div", { className: `flex items-end gap-2 bg-slate-50 dark:bg-white/5 border border-slate-200 dark:border-white/10 p-2 focus-within:border-slate-300 dark:focus-within:border-white/20 transition-all ${ui.borderRadius === "full" ? "rounded-3xl" : "rounded-2xl"}` }, /* @__PURE__ */ React14.createElement(
2309
- "textarea",
2310
- {
2311
- ref: inputRef,
2312
- value: input,
2313
- onChange: (e) => {
2314
- const val = e.target.value;
2315
- setInput(val);
2316
- if (val.trim().length < 3) {
2317
- setSuggestions([]);
2654
+ onMouseDown: onResizeStart,
2655
+ className: "absolute top-0 left-0 w-6 h-6 cursor-nw-resize z-[100] group flex items-start justify-start p-1",
2656
+ title: "Drag to resize",
2657
+ children: /* @__PURE__ */ jsx13("div", { className: "w-2.5 h-2.5 border-t-2 border-l-2 border-slate-300 dark:border-white/20 group-hover:border-slate-500 dark:group-hover:border-white/50 transition-colors rounded-tl-[2px]" })
2318
2658
  }
2319
- },
2320
- onKeyDown: handleKeyDown,
2321
- placeholder: ui.placeholder,
2322
- rows: 1,
2323
- disabled: isLoading,
2324
- className: "flex-1 bg-transparent text-slate-900 dark:text-white/90 placeholder-slate-400 dark:placeholder-white/30 text-sm resize-none outline-none py-1.5 px-2 max-h-32 leading-relaxed disabled:opacity-50",
2325
- style: { scrollbarWidth: "none" }
2326
- }
2327
- ), ui.enableVoiceInput !== false && /* @__PURE__ */ React14.createElement(
2328
- "button",
2329
- {
2330
- type: "button",
2331
- onClick: toggleListening,
2332
- disabled: isLoading,
2333
- className: `flex-shrink-0 w-9 h-9 rounded-xl flex items-center justify-center transition-all hover:scale-105 active:scale-95 disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:scale-100 disabled:active:scale-100 ${isListening ? "bg-rose-500 text-white animate-pulse shadow-md shadow-rose-500/20" : "text-slate-400 dark:text-white/40 hover:bg-slate-200 dark:hover:bg-white/10"}`,
2334
- title: isListening ? "Stop listening" : "Start voice input"
2335
- },
2336
- isListening ? /* @__PURE__ */ React14.createElement(MicOff, { className: "w-4 h-4" }) : /* @__PURE__ */ React14.createElement(Mic, { className: "w-4 h-4" })
2337
- ), ui.allowUpload !== false && /* @__PURE__ */ React14.createElement(
2338
- "button",
2339
- {
2340
- type: "button",
2341
- onClick: () => setIsUploadModalOpen(true),
2342
- className: "flex-shrink-0 w-9 h-9 rounded-xl flex items-center justify-center transition-all hover:scale-105 active:scale-95 text-slate-400 dark:text-white/40 hover:bg-slate-200 dark:hover:bg-white/10",
2343
- title: "Upload Document"
2344
- },
2345
- /* @__PURE__ */ React14.createElement(Paperclip, { className: "w-4 h-4" })
2346
- ), /* @__PURE__ */ React14.createElement(
2347
- "button",
2348
- {
2349
- onClick: sendMessage,
2350
- disabled: !input.trim() || isLoading,
2351
- className: "flex-shrink-0 w-9 h-9 rounded-xl flex items-center justify-center transition-all disabled:opacity-30 disabled:cursor-not-allowed hover:scale-105 active:scale-95 shadow-md",
2352
- style: {
2353
- background: input.trim() && !isLoading ? `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` : "rgba(148, 163, 184, 0.2)"
2354
- // slate-400/20 for light mode disabled
2355
- }
2356
- },
2357
- /* @__PURE__ */ React14.createElement(ArrowUp, { className: "w-4 h-4 text-white" })
2358
- )), /* @__PURE__ */ React14.createElement("p", { className: "text-center text-[10px] text-slate-400 dark:text-white/20 mt-2" }, "Press Enter to send \xB7 Shift+Enter for new line"))
2659
+ ),
2660
+ /* @__PURE__ */ jsxs12(
2661
+ "div",
2662
+ {
2663
+ className: "flex items-center justify-between px-5 py-4 border-b border-slate-200 dark:border-white/10",
2664
+ style: { background: `linear-gradient(135deg, ${ui.primaryColor}15, ${ui.accentColor}10)` },
2665
+ children: [
2666
+ /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-3", children: [
2667
+ ui.logoUrl ? (
2668
+ // eslint-disable-next-line @next/next/no-img-element
2669
+ /* @__PURE__ */ jsx13("img", { src: ui.logoUrl, alt: "logo", className: "w-8 h-8 rounded-lg object-cover" })
2670
+ ) : /* @__PURE__ */ jsx13(
2671
+ "div",
2672
+ {
2673
+ className: `w-9 h-9 flex items-center justify-center shadow-md ${ui.borderRadius === "full" ? "rounded-full" : "rounded-xl"}`,
2674
+ style: { background: `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` },
2675
+ children: /* @__PURE__ */ jsx13(Bot2, { className: "w-5 h-5 text-white" })
2676
+ }
2677
+ ),
2678
+ /* @__PURE__ */ jsxs12("div", { children: [
2679
+ /* @__PURE__ */ jsx13("h2", { className: "text-slate-900 dark:text-white font-semibold text-sm leading-tight", children: ui.title }),
2680
+ ui.poweredBy && /* @__PURE__ */ jsx13("p", { className: "text-slate-500 dark:text-white/40 text-[11px] leading-tight", children: `Powered by ${ui.poweredBy}` })
2681
+ ] })
2682
+ ] }),
2683
+ /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-1.5", children: [
2684
+ /* @__PURE__ */ jsxs12("span", { className: "flex items-center gap-1 text-[10px] text-emerald-500 dark:text-emerald-400 mr-2", children: [
2685
+ /* @__PURE__ */ jsx13("span", { className: "w-1.5 h-1.5 rounded-full bg-emerald-500 dark:bg-emerald-400 animate-pulse" }),
2686
+ "Online"
2687
+ ] }),
2688
+ /* @__PURE__ */ jsxs12("div", { className: "flex items-center bg-slate-100/50 dark:bg-white/5 rounded-lg p-0.5 border border-slate-200/50 dark:border-white/5", children: [
2689
+ mounted && messages.length > 0 && /* @__PURE__ */ jsx13(
2690
+ "button",
2691
+ {
2692
+ onClick: clearHistory,
2693
+ title: "Clear conversation",
2694
+ className: "w-7 h-7 rounded-md flex items-center justify-center text-slate-400 hover:text-rose-500 dark:text-white/40 dark:hover:text-rose-400 hover:bg-white dark:hover:bg-white/10 transition-all cursor-pointer",
2695
+ children: /* @__PURE__ */ jsx13(Trash2, { className: "w-3.5 h-3.5" })
2696
+ }
2697
+ ),
2698
+ isResized && onResetResize && /* @__PURE__ */ jsx13(
2699
+ "button",
2700
+ {
2701
+ onClick: onResetResize,
2702
+ title: "Reset to default size",
2703
+ className: "w-7 h-7 rounded-md flex items-center justify-center text-slate-400 hover:text-blue-500 dark:text-white/40 dark:hover:text-blue-400 hover:bg-white dark:hover:bg-white/10 transition-all cursor-pointer",
2704
+ children: /* @__PURE__ */ jsx13(RotateCcw, { className: "w-3.5 h-3.5" })
2705
+ }
2706
+ ),
2707
+ onMaximize && /* @__PURE__ */ jsx13(
2708
+ "button",
2709
+ {
2710
+ onClick: onMaximize,
2711
+ title: isMaximized ? "Minimize" : "Maximize",
2712
+ className: "w-7 h-7 rounded-md flex items-center justify-center text-slate-400 hover:text-blue-500 dark:text-white/40 dark:hover:text-blue-400 hover:bg-white dark:hover:bg-white/10 transition-all cursor-pointer",
2713
+ children: isMaximized ? /* @__PURE__ */ jsx13(Minimize2, { className: "w-3.5 h-3.5" }) : /* @__PURE__ */ jsx13(Maximize2, { className: "w-3.5 h-3.5" })
2714
+ }
2715
+ ),
2716
+ showClose && onClose && /* @__PURE__ */ jsx13(
2717
+ "button",
2718
+ {
2719
+ onClick: onClose,
2720
+ title: "Close chat",
2721
+ className: "w-7 h-7 rounded-md flex items-center justify-center text-slate-400 hover:text-slate-600 dark:text-white/40 dark:hover:text-white/70 hover:bg-white dark:hover:bg-white/10 transition-all cursor-pointer",
2722
+ children: /* @__PURE__ */ jsx13(X2, { className: "w-4 h-4" })
2723
+ }
2724
+ )
2725
+ ] })
2726
+ ] })
2727
+ ]
2728
+ }
2729
+ ),
2730
+ /* @__PURE__ */ jsxs12("div", { className: "flex-1 overflow-y-auto px-4 py-4 space-y-5 scrollbar-thin scrollbar-thumb-slate-200 dark:scrollbar-thumb-white/10 scrollbar-track-transparent min-h-0 bg-slate-50 dark:bg-transparent", children: [
2731
+ !mounted || isEmpty ? (
2732
+ /* Welcome state */
2733
+ /* @__PURE__ */ jsxs12("div", { className: "h-full flex flex-col items-center justify-center text-center gap-4 px-6 py-12", children: [
2734
+ /* @__PURE__ */ jsx13(
2735
+ "div",
2736
+ {
2737
+ className: `w-16 h-16 flex items-center justify-center shadow-lg ${ui.borderRadius === "full" ? "rounded-full" : "rounded-2xl"}`,
2738
+ style: { background: `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` },
2739
+ children: /* @__PURE__ */ jsx13(Sparkles, { className: "w-8 h-8 text-white" })
2740
+ }
2741
+ ),
2742
+ /* @__PURE__ */ jsxs12("div", { children: [
2743
+ /* @__PURE__ */ jsx13("p", { className: "text-slate-800 dark:text-white/80 font-medium leading-relaxed", children: ui.welcomeMessage }),
2744
+ /* @__PURE__ */ jsx13("p", { className: "text-slate-500 dark:text-white/30 text-sm mt-2", children: "Ask a question to get started" })
2745
+ ] }),
2746
+ /* @__PURE__ */ jsx13("div", { className: "flex flex-wrap gap-2 justify-center mt-2", children: CHAT_SUGGESTIONS.map(
2747
+ (suggestion) => /* @__PURE__ */ jsx13(
2748
+ "button",
2749
+ {
2750
+ onClick: () => {
2751
+ var _a2;
2752
+ setInput(suggestion);
2753
+ (_a2 = inputRef.current) == null ? void 0 : _a2.focus();
2754
+ },
2755
+ className: "px-3 py-1.5 rounded-full text-xs border border-slate-200 dark:border-white/10 text-slate-600 dark:text-white/50 hover:text-slate-900 dark:hover:text-white/80 hover:border-slate-300 dark:hover:border-white/20 hover:bg-slate-100 dark:hover:bg-white/5 transition-all",
2756
+ children: suggestion
2757
+ },
2758
+ suggestion
2759
+ )
2760
+ ) })
2761
+ ] })
2762
+ ) : messages.map((msg, index) => /* @__PURE__ */ jsx13(
2763
+ MessageBubble,
2764
+ {
2765
+ message: msg,
2766
+ sources: msg.sources,
2767
+ isStreaming: isLoading && index === messages.length - 1 && msg.role === "assistant",
2768
+ primaryColor: ui.primaryColor,
2769
+ accentColor: ui.accentColor,
2770
+ onAddToCart,
2771
+ viewportSize
2772
+ },
2773
+ msg.id
2774
+ )),
2775
+ isLoading && ((_a = messages[messages.length - 1]) == null ? void 0 : _a.role) !== "assistant" && /* @__PURE__ */ jsx13(
2776
+ MessageBubble,
2777
+ {
2778
+ message: { id: "loading", role: "assistant", content: "", createdAt: (/* @__PURE__ */ new Date()).toISOString() },
2779
+ isStreaming: true,
2780
+ primaryColor: ui.primaryColor,
2781
+ accentColor: ui.accentColor,
2782
+ onAddToCart,
2783
+ viewportSize
2784
+ }
2785
+ ),
2786
+ error && /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-2 text-rose-500 dark:text-rose-400 text-sm bg-rose-50 dark:bg-rose-400/10 border border-rose-200 dark:border-rose-400/20 rounded-xl px-4 py-3", children: [
2787
+ /* @__PURE__ */ jsx13(TriangleAlert, { className: "w-4 h-4 flex-shrink-0" }),
2788
+ /* @__PURE__ */ jsx13("span", { children: error })
2789
+ ] }),
2790
+ /* @__PURE__ */ jsx13("div", { ref: bottomRef })
2791
+ ] }),
2792
+ isUploadModalOpen && /* @__PURE__ */ jsx13("div", { className: "absolute inset-0 z-50 flex items-center justify-center p-4 bg-slate-900/50 backdrop-blur-sm rounded-inherit", children: /* @__PURE__ */ jsxs12("div", { className: "relative w-full max-w-md bg-white dark:bg-[#0f0f1a] rounded-2xl shadow-2xl overflow-hidden animate-in zoom-in-95 duration-200", children: [
2793
+ /* @__PURE__ */ jsx13(
2794
+ "button",
2795
+ {
2796
+ onClick: () => setIsUploadModalOpen(false),
2797
+ className: "absolute top-4 right-4 p-1.5 rounded-lg text-slate-400 hover:text-slate-600 hover:bg-slate-100 dark:hover:text-white/80 dark:hover:bg-white/10 transition-colors z-10",
2798
+ children: /* @__PURE__ */ jsx13(X2, { className: "w-5 h-5" })
2799
+ }
2800
+ ),
2801
+ /* @__PURE__ */ jsx13(
2802
+ DocumentUpload,
2803
+ {
2804
+ namespace: projectId,
2805
+ onUploadComplete: () => setIsUploadModalOpen(false)
2806
+ }
2807
+ )
2808
+ ] }) }),
2809
+ /* @__PURE__ */ jsxs12("div", { className: `px-4 pb-4 pt-2 border-t border-slate-200 dark:border-white/10 ${isGlass ? "bg-transparent" : "bg-white dark:bg-[#0f0f1a]"}`, children: [
2810
+ (suggestions.length > 0 || isSuggesting) && !isLoading && /* @__PURE__ */ jsxs12("div", { className: "mb-3 flex flex-wrap gap-2 animate-in fade-in slide-in-from-bottom-2 duration-300", children: [
2811
+ suggestions.map((suggestion) => /* @__PURE__ */ jsxs12(
2812
+ "button",
2813
+ {
2814
+ onClick: () => {
2815
+ var _a2;
2816
+ setInput(suggestion);
2817
+ setSuggestions([]);
2818
+ (_a2 = inputRef.current) == null ? void 0 : _a2.focus();
2819
+ },
2820
+ className: "flex items-center gap-1.5 px-3 py-1.5 rounded-xl text-[11px] font-medium bg-white dark:bg-white/5 border border-slate-200 dark:border-white/10 text-slate-600 dark:text-white/60 hover:text-slate-900 dark:hover:text-white/90 hover:border-slate-300 dark:hover:border-white/20 transition-all shadow-sm cursor-pointer group",
2821
+ children: [
2822
+ /* @__PURE__ */ jsx13(Sparkles, { className: "w-3 h-3 text-amber-400" }),
2823
+ suggestion
2824
+ ]
2825
+ },
2826
+ suggestion
2827
+ )),
2828
+ isSuggesting && suggestions.length === 0 && /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-1.5 px-3 py-1.5 rounded-xl text-[11px] font-medium text-slate-400 dark:text-white/30 animate-pulse", children: [
2829
+ /* @__PURE__ */ jsx13(Sparkles, { className: "w-3 h-3" }),
2830
+ "Thinking..."
2831
+ ] })
2832
+ ] }),
2833
+ /* @__PURE__ */ jsxs12("div", { className: `flex items-end gap-2 bg-slate-50 dark:bg-white/5 border border-slate-200 dark:border-white/10 p-2 focus-within:border-slate-300 dark:focus-within:border-white/20 transition-all ${ui.borderRadius === "full" ? "rounded-3xl" : "rounded-2xl"}`, children: [
2834
+ /* @__PURE__ */ jsx13(
2835
+ "textarea",
2836
+ {
2837
+ ref: inputRef,
2838
+ value: input,
2839
+ onChange: (e) => {
2840
+ const val = e.target.value;
2841
+ setInput(val);
2842
+ if (val.trim().length < 3) {
2843
+ setSuggestions([]);
2844
+ }
2845
+ },
2846
+ onKeyDown: handleKeyDown,
2847
+ placeholder: ui.placeholder,
2848
+ rows: 1,
2849
+ disabled: isLoading,
2850
+ className: "flex-1 bg-transparent text-slate-900 dark:text-white/90 placeholder-slate-400 dark:placeholder-white/30 text-sm resize-none outline-none py-1.5 px-2 max-h-32 leading-relaxed disabled:opacity-50",
2851
+ style: { scrollbarWidth: "none" }
2852
+ }
2853
+ ),
2854
+ ui.enableVoiceInput !== false && /* @__PURE__ */ jsx13(
2855
+ "button",
2856
+ {
2857
+ type: "button",
2858
+ onClick: toggleListening,
2859
+ disabled: isLoading,
2860
+ className: `flex-shrink-0 w-9 h-9 rounded-xl flex items-center justify-center transition-all hover:scale-105 active:scale-95 disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:scale-100 disabled:active:scale-100 ${isListening ? "bg-rose-500 text-white animate-pulse shadow-md shadow-rose-500/20" : "text-slate-400 dark:text-white/40 hover:bg-slate-200 dark:hover:bg-white/10"}`,
2861
+ title: isListening ? "Stop listening" : "Start voice input",
2862
+ children: isListening ? /* @__PURE__ */ jsx13(MicOff, { className: "w-4 h-4" }) : /* @__PURE__ */ jsx13(Mic, { className: "w-4 h-4" })
2863
+ }
2864
+ ),
2865
+ ui.allowUpload !== false && /* @__PURE__ */ jsx13(
2866
+ "button",
2867
+ {
2868
+ type: "button",
2869
+ onClick: () => setIsUploadModalOpen(true),
2870
+ className: "flex-shrink-0 w-9 h-9 rounded-xl flex items-center justify-center transition-all hover:scale-105 active:scale-95 text-slate-400 dark:text-white/40 hover:bg-slate-200 dark:hover:bg-white/10",
2871
+ title: "Upload Document",
2872
+ children: /* @__PURE__ */ jsx13(Paperclip, { className: "w-4 h-4" })
2873
+ }
2874
+ ),
2875
+ /* @__PURE__ */ jsx13(
2876
+ "button",
2877
+ {
2878
+ onClick: sendMessage,
2879
+ disabled: !input.trim() || isLoading,
2880
+ className: "flex-shrink-0 w-9 h-9 rounded-xl flex items-center justify-center transition-all disabled:opacity-30 disabled:cursor-not-allowed hover:scale-105 active:scale-95 shadow-md",
2881
+ style: {
2882
+ background: input.trim() && !isLoading ? `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` : "rgba(148, 163, 184, 0.2)"
2883
+ // slate-400/20 for light mode disabled
2884
+ },
2885
+ children: /* @__PURE__ */ jsx13(ArrowUp, { className: "w-4 h-4 text-white" })
2886
+ }
2887
+ )
2888
+ ] }),
2889
+ /* @__PURE__ */ jsx13("p", { className: "text-center text-[10px] text-slate-400 dark:text-white/20 mt-2", children: "Press Enter to send \xB7 Shift+Enter for new line" })
2890
+ ] })
2891
+ ]
2892
+ }
2359
2893
  );
2360
2894
  }
2361
2895
 
2362
2896
  // src/components/ChatWidget.tsx
2897
+ import { Fragment as Fragment4, jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
2363
2898
  var DEFAULT_DIMENSIONS = { width: 380, height: 600 };
2364
2899
  function ChatWidget({ position = "bottom-right", onAddToCart }) {
2365
2900
  const { ui } = useConfig();
@@ -2373,7 +2908,6 @@ function ChatWidget({ position = "bottom-right", onAddToCart }) {
2373
2908
  const positionClass = position === "bottom-left" ? "bottom-6 left-6" : "bottom-6 right-6";
2374
2909
  const windowPositionClass = position === "bottom-left" ? "bottom-20 left-6" : "bottom-20 right-6";
2375
2910
  const handleOpen = () => {
2376
- console.log("ChatWidget: Opening...");
2377
2911
  setIsOpen(true);
2378
2912
  setHasUnread(false);
2379
2913
  };
@@ -2418,60 +2952,67 @@ function ChatWidget({ position = "bottom-right", onAddToCart }) {
2418
2952
  }
2419
2953
  };
2420
2954
  const isResized = dimensions.width !== DEFAULT_DIMENSIONS.width || dimensions.height !== DEFAULT_DIMENSIONS.height;
2421
- return /* @__PURE__ */ React15.createElement(React15.Fragment, null, /* @__PURE__ */ React15.createElement(
2422
- "div",
2423
- {
2424
- className: `fixed z-[9998] max-w-[calc(100vw-3rem)] ease-in-out ${windowPositionClass} ${isOpen ? "opacity-100 translate-y-0 pointer-events-auto" : "opacity-0 translate-y-4 pointer-events-none"} ${isResizing ? "" : "transition-all duration-300"}`,
2425
- style: {
2426
- width: `${dimensions.width}px`,
2427
- height: `${dimensions.height}px`,
2428
- maxHeight: "calc(100vh - 6rem)"
2429
- }
2430
- },
2431
- /* @__PURE__ */ React15.createElement(
2432
- ChatWindow,
2955
+ return /* @__PURE__ */ jsxs13(Fragment4, { children: [
2956
+ /* @__PURE__ */ jsxs13(
2957
+ "div",
2433
2958
  {
2434
- className: "h-full relative z-10",
2435
- showClose: true,
2436
- onClose: () => setIsOpen(false),
2437
- onResizeStart: ui.allowResize !== false ? handleResizeStart : void 0,
2438
- onResetResize: ui.allowResize !== false ? handleResetResize : void 0,
2439
- isResized,
2440
- onMaximize: ui.allowResize !== false ? handleMaximize : void 0,
2441
- isMaximized,
2442
- onAddToCart
2959
+ className: `fixed z-[9998] max-w-[calc(100vw-3rem)] ease-in-out ${windowPositionClass} ${isOpen ? "opacity-100 translate-y-0 pointer-events-auto" : "opacity-0 translate-y-4 pointer-events-none"} ${isResizing ? "" : "transition-all duration-300"}`,
2960
+ style: {
2961
+ width: `${dimensions.width}px`,
2962
+ height: `${dimensions.height}px`,
2963
+ maxHeight: "calc(100vh - 6rem)"
2964
+ },
2965
+ children: [
2966
+ /* @__PURE__ */ jsx14(
2967
+ ChatWindow,
2968
+ {
2969
+ className: "h-full relative z-10",
2970
+ showClose: true,
2971
+ onClose: () => setIsOpen(false),
2972
+ onResizeStart: ui.allowResize !== false ? handleResizeStart : void 0,
2973
+ onResetResize: ui.allowResize !== false ? handleResetResize : void 0,
2974
+ isResized,
2975
+ onMaximize: ui.allowResize !== false ? handleMaximize : void 0,
2976
+ isMaximized,
2977
+ onAddToCart
2978
+ }
2979
+ ),
2980
+ /* @__PURE__ */ jsx14(
2981
+ "div",
2982
+ {
2983
+ className: `absolute -bottom-1.5 w-4 h-4 rotate-45 border-r border-b border-slate-200 dark:border-white/10 z-0 ${ui.visualStyle === "solid" ? "bg-white dark:bg-[#0f0f1a]" : "bg-white/90 dark:bg-[#0f0f1a]/90 backdrop-blur-xl"} ${position === "bottom-left" ? "left-5" : "right-5"}`
2984
+ }
2985
+ )
2986
+ ]
2443
2987
  }
2444
2988
  ),
2445
- /* @__PURE__ */ React15.createElement(
2446
- "div",
2989
+ /* @__PURE__ */ jsxs13(
2990
+ "button",
2447
2991
  {
2448
- className: `absolute -bottom-1.5 w-4 h-4 rotate-45 border-r border-b border-slate-200 dark:border-white/10 z-0 ${ui.visualStyle === "solid" ? "bg-white dark:bg-[#0f0f1a]" : "bg-white/90 dark:bg-[#0f0f1a]/90 backdrop-blur-xl"} ${position === "bottom-left" ? "left-5" : "right-5"}`
2992
+ onClick: isOpen ? () => setIsOpen(false) : handleOpen,
2993
+ className: `fixed z-[9999] w-14 h-14 shadow-2xl flex items-center justify-center transition-all duration-300 cursor-pointer hover:scale-110 active:scale-95 ${ui.borderRadius === "full" ? "rounded-full" : "rounded-2xl"} ${positionClass}`,
2994
+ style: { background: `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` },
2995
+ "aria-label": "Open chat",
2996
+ children: [
2997
+ /* @__PURE__ */ jsx14(
2998
+ "span",
2999
+ {
3000
+ className: "absolute inset-0 rounded-full animate-ping opacity-20",
3001
+ style: { background: ui.primaryColor }
3002
+ }
3003
+ ),
3004
+ /* @__PURE__ */ jsx14(
3005
+ "span",
3006
+ {
3007
+ className: `transition-transform duration-300 ${isOpen ? "rotate-90 scale-90" : "rotate-0 scale-100"}`,
3008
+ children: isOpen ? /* @__PURE__ */ jsx14(X3, { className: "w-6 h-6 text-white" }) : /* @__PURE__ */ jsx14(MessageSquare, { className: "w-6 h-6 text-white" })
3009
+ }
3010
+ ),
3011
+ hasUnread && !isOpen && /* @__PURE__ */ jsx14("span", { className: "absolute top-0 right-0 w-4 h-4 bg-rose-500 rounded-full border-2 border-white flex items-center justify-center text-[9px] font-bold text-white", children: "1" })
3012
+ ]
2449
3013
  }
2450
3014
  )
2451
- ), /* @__PURE__ */ React15.createElement(
2452
- "button",
2453
- {
2454
- onClick: isOpen ? () => setIsOpen(false) : handleOpen,
2455
- className: `fixed z-[9999] w-14 h-14 shadow-2xl flex items-center justify-center transition-all duration-300 cursor-pointer hover:scale-110 active:scale-95 ${ui.borderRadius === "full" ? "rounded-full" : "rounded-2xl"} ${positionClass}`,
2456
- style: { background: `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` },
2457
- "aria-label": "Open chat"
2458
- },
2459
- /* @__PURE__ */ React15.createElement(
2460
- "span",
2461
- {
2462
- className: "absolute inset-0 rounded-full animate-ping opacity-20",
2463
- style: { background: ui.primaryColor }
2464
- }
2465
- ),
2466
- /* @__PURE__ */ React15.createElement(
2467
- "span",
2468
- {
2469
- className: `transition-transform duration-300 ${isOpen ? "rotate-90 scale-90" : "rotate-0 scale-100"}`
2470
- },
2471
- isOpen ? /* @__PURE__ */ React15.createElement(X3, { className: "w-6 h-6 text-white" }) : /* @__PURE__ */ React15.createElement(MessageSquare, { className: "w-6 h-6 text-white" })
2472
- ),
2473
- hasUnread && !isOpen && /* @__PURE__ */ React15.createElement("span", { className: "absolute top-0 right-0 w-4 h-4 bg-rose-500 rounded-full border-2 border-white flex items-center justify-center text-[9px] font-bold text-white" }, "1")
2474
- ));
3015
+ ] });
2475
3016
  }
2476
3017
  export {
2477
3018
  ChatWidget,