@retrivora-ai/rag-engine 1.8.2 → 1.8.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/handlers/index.js +142 -16
- package/dist/handlers/index.mjs +5848 -17
- package/dist/index.d.mts +9 -15
- package/dist/index.d.ts +9 -15
- package/dist/index.js +1355 -919
- package/dist/index.mjs +1437 -896
- package/dist/server.d.mts +6 -0
- package/dist/server.d.ts +6 -0
- package/dist/server.js +171 -17
- package/dist/server.mjs +5923 -68
- package/package.json +6 -6
- package/src/app/globals.css +35 -11
- package/src/components/ChatWidget.tsx +0 -1
- package/src/components/MarkdownComponents.tsx +3 -0
- package/src/components/MessageBubble.tsx +3 -2
- package/src/components/ObservabilityPanel.tsx +1 -1
- package/src/components/UIDispatcher.tsx +0 -3
- package/src/config/ConfigBuilder.ts +38 -1
- package/src/core/LangChainAgent.ts +1 -4
- package/src/core/Pipeline.ts +31 -18
- package/src/core/QueryProcessor.ts +65 -0
- package/src/rag/Reranker.ts +99 -6
- package/src/utils/ProductExtractor.ts +3 -3
- package/dist/ChromaDBProvider-MIDOR4FW.mjs +0 -8
- package/dist/MilvusProvider-U7SKC27V.mjs +0 -8
- package/dist/MongoDBProvider-YNKC7EJ6.mjs +0 -8
- package/dist/MultiTablePostgresProvider-ZLGSKTJR.mjs +0 -8
- package/dist/PineconeProvider-QZNRKTN2.mjs +0 -8
- package/dist/QdrantProvider-RLJTNGPY.mjs +0 -8
- package/dist/RedisProvider-SR65SCKV.mjs +0 -8
- package/dist/SimpleGraphProvider-SLOXO4M7.mjs +0 -62
- package/dist/UniversalVectorProvider-IN67OS56.mjs +0 -9
- package/dist/WeaviateProvider-5FWDFITI.mjs +0 -8
- package/dist/chunk-5AJ4XHLW.mjs +0 -201
- package/dist/chunk-5YGUXK7Z.mjs +0 -80
- package/dist/chunk-CFVEZTBJ.mjs +0 -102
- package/dist/chunk-ICKRMZQK.mjs +0 -76
- package/dist/chunk-IMP6FUCY.mjs +0 -30
- package/dist/chunk-LR3VMDVK.mjs +0 -157
- package/dist/chunk-LZVVLSDN.mjs +0 -4077
- package/dist/chunk-M6JSPGAR.mjs +0 -117
- package/dist/chunk-OZFBG4BA.mjs +0 -291
- package/dist/chunk-PSFPZXHX.mjs +0 -245
- package/dist/chunk-U55XRW3U.mjs +0 -96
- package/dist/chunk-VUQJVIJT.mjs +0 -148
- package/dist/chunk-X4TOT24V.mjs +0 -89
- package/dist/chunk-YLTMFW4M.mjs +0 -49
package/dist/index.mjs
CHANGED
|
@@ -1,22 +1,41 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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__ */
|
|
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__ */
|
|
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
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
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
|
|
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__ */
|
|
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
|
-
|
|
266
|
-
|
|
267
|
-
|
|
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
|
|
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__ */
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
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__ */
|
|
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__ */
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
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
|
-
|
|
373
|
-
className: "
|
|
374
|
-
|
|
375
|
-
|
|
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
|
|
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 =
|
|
431
|
-
const [containerWidth, setContainerWidth] =
|
|
432
|
-
|
|
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 =
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
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__ */
|
|
546
|
-
|
|
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
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
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
|
-
|
|
558
|
-
)
|
|
559
|
-
}
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
{
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
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__ */
|
|
594
|
-
"
|
|
595
|
-
{
|
|
596
|
-
className: "
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
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__ */
|
|
758
|
+
return /* @__PURE__ */ jsx7("div", { className: `p-4 text-gray-500 ${className}`, children: "No data available for visualization" });
|
|
611
759
|
}
|
|
612
|
-
return /* @__PURE__ */
|
|
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__ */
|
|
772
|
+
return /* @__PURE__ */ jsx7(PieChartView, { data, isStreaming });
|
|
619
773
|
case "bar_chart":
|
|
620
|
-
return /* @__PURE__ */
|
|
774
|
+
return /* @__PURE__ */ jsx7(BarChartView, { data, primaryColor, isStreaming });
|
|
621
775
|
case "line_chart":
|
|
622
|
-
return /* @__PURE__ */
|
|
776
|
+
return /* @__PURE__ */ jsx7(LineChartView, { data, primaryColor, isStreaming });
|
|
623
777
|
case "radar_chart":
|
|
624
|
-
return /* @__PURE__ */
|
|
778
|
+
return /* @__PURE__ */ jsx7(RadarChartView, { data, isStreaming });
|
|
625
779
|
case "table":
|
|
626
|
-
return /* @__PURE__ */
|
|
780
|
+
return /* @__PURE__ */ jsx7(TableView, { data, isStreaming });
|
|
627
781
|
case "product_carousel":
|
|
628
782
|
case "carousel":
|
|
629
|
-
return /* @__PURE__ */
|
|
783
|
+
return /* @__PURE__ */ jsx7(CarouselView, { data, onAddToCart, primaryColor });
|
|
630
784
|
case "text":
|
|
631
785
|
default:
|
|
632
|
-
return /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
807
|
+
if (isStreaming) return /* @__PURE__ */ jsx7(ChartSkeleton, { type: "pie" });
|
|
650
808
|
if (!Array.isArray(data) || data.length === 0) {
|
|
651
|
-
return /* @__PURE__ */
|
|
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__ */
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
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__ */
|
|
835
|
+
if (isStreaming) return /* @__PURE__ */ jsx7(ChartSkeleton, { type: "bar" });
|
|
674
836
|
if (!Array.isArray(data) || data.length === 0) {
|
|
675
|
-
return /* @__PURE__ */
|
|
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__ */
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
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__ */
|
|
866
|
+
if (isStreaming) return /* @__PURE__ */ jsx7(ChartSkeleton, { type: "bar" });
|
|
695
867
|
if (!Array.isArray(data) || data.length === 0) {
|
|
696
|
-
return /* @__PURE__ */
|
|
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__ */
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
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__ */
|
|
906
|
+
if (isStreaming) return /* @__PURE__ */ jsx7(ChartSkeleton, { type: "pie" });
|
|
729
907
|
if (!Array.isArray(data) || data.length === 0) {
|
|
730
|
-
return /* @__PURE__ */
|
|
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__ */
|
|
736
|
-
|
|
737
|
-
{
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
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__ */
|
|
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__ */
|
|
935
|
+
return /* @__PURE__ */ jsx7("div", { className: "text-xs text-red-500", children: "Invalid table data" });
|
|
751
936
|
}
|
|
752
|
-
return /* @__PURE__ */
|
|
753
|
-
"
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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
|
|
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__ */
|
|
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__ */
|
|
834
|
-
"
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
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: "
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
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__ */
|
|
860
|
-
"div",
|
|
861
|
-
|
|
862
|
-
className: "
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
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__ */
|
|
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__ */
|
|
882
|
-
"div",
|
|
883
|
-
|
|
884
|
-
className: "
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
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__ */
|
|
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__ */
|
|
905
|
-
"div",
|
|
906
|
-
|
|
907
|
-
className: "
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
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] =
|
|
914
|
-
return /* @__PURE__ */
|
|
915
|
-
"
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
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] =
|
|
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__ */
|
|
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__ */
|
|
1243
|
+
return /* @__PURE__ */ jsxs7(
|
|
938
1244
|
"div",
|
|
939
1245
|
{
|
|
940
|
-
|
|
941
|
-
|
|
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
|
-
|
|
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__ */
|
|
958
|
-
{ id: "latency", label: "Latency", icon: /* @__PURE__ */
|
|
959
|
-
{ id: "tokens", label: "Tokens", icon: /* @__PURE__ */
|
|
960
|
-
{ id: "hallucination", label: "Grounding", icon: /* @__PURE__ */
|
|
961
|
-
{ id: "prompt", label: "Prompt", icon: /* @__PURE__ */
|
|
962
|
-
{ id: "chunks", label: "Chunks", icon: /* @__PURE__ */
|
|
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] =
|
|
966
|
-
return /* @__PURE__ */
|
|
967
|
-
|
|
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: "
|
|
976
|
-
style: {
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
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__ */
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
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
|
|
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__ */
|
|
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
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
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
|
|
1773
|
+
import React8 from "react";
|
|
1354
1774
|
|
|
1355
1775
|
// src/components/UIDispatcher.tsx
|
|
1356
|
-
import
|
|
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 =
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
1483
|
-
|
|
1484
|
-
{
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
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
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
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__ */
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
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__ */
|
|
1514
|
-
|
|
1515
|
-
{
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
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
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
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
|
-
|
|
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__ */
|
|
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__ */
|
|
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: (
|
|
1556
|
-
var props = __objRest(
|
|
1557
|
-
return /* @__PURE__ */
|
|
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: (
|
|
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__ */
|
|
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: (
|
|
1578
|
-
var
|
|
1579
|
-
return /* @__PURE__ */
|
|
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
|
-
|
|
2026
|
+
}, props), {
|
|
2027
|
+
children: normaliseChild(children)
|
|
2028
|
+
})
|
|
1585
2029
|
);
|
|
1586
2030
|
},
|
|
1587
|
-
td: (
|
|
1588
|
-
var
|
|
1589
|
-
return /* @__PURE__ */
|
|
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
|
-
|
|
2037
|
+
}, props), {
|
|
2038
|
+
children: normaliseChild(children)
|
|
2039
|
+
})
|
|
1595
2040
|
);
|
|
1596
2041
|
},
|
|
1597
|
-
code(
|
|
1598
|
-
var
|
|
2042
|
+
code(_j) {
|
|
2043
|
+
var _k = _j, {
|
|
1599
2044
|
inline,
|
|
1600
2045
|
className,
|
|
1601
2046
|
children
|
|
1602
|
-
} =
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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) && !
|
|
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] =
|
|
1664
|
-
const [showTrace, setShowTrace] =
|
|
1665
|
-
const structuredContent =
|
|
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 =
|
|
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 =
|
|
2126
|
+
const productsFromSources = React9.useMemo(() => {
|
|
1681
2127
|
return extractProductsFromSources(sources, isUser);
|
|
1682
2128
|
}, [sources, isUser]);
|
|
1683
|
-
const { productsFromContent, cleanContent } =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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__ */
|
|
1729
|
-
|
|
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
|
-
|
|
1771
|
-
primaryColor,
|
|
1772
|
-
|
|
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
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
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
|
|
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] =
|
|
1828
|
-
|
|
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__ */
|
|
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
|
-
|
|
2174
|
-
|
|
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
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
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
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
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__ */
|
|
2422
|
-
|
|
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: "
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
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__ */
|
|
2446
|
-
"
|
|
2989
|
+
/* @__PURE__ */ jsxs13(
|
|
2990
|
+
"button",
|
|
2447
2991
|
{
|
|
2448
|
-
|
|
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
|
-
)
|
|
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,
|