@retrivora-ai/rag-engine 1.7.9 → 1.8.1
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/DocumentChunker-Dh9TvmGG.d.mts +45 -0
- package/dist/DocumentChunker-Dh9TvmGG.d.ts +45 -0
- package/dist/{index-wCRqMtdX.d.mts → ILLMProvider-BfRgI1Xh.d.mts} +59 -1
- package/dist/{index-wCRqMtdX.d.ts → ILLMProvider-BfRgI1Xh.d.ts} +59 -1
- package/dist/MultiTablePostgresProvider-YY7LPNJK.mjs +8 -0
- package/dist/{chunk-UHGYLTTY.mjs → chunk-BFYLQYQU.mjs} +846 -458
- package/dist/chunk-R3RGUMHE.mjs +218 -0
- package/dist/handlers/index.d.mts +2 -2
- package/dist/handlers/index.d.ts +2 -2
- package/dist/handlers/index.js +1033 -622
- package/dist/handlers/index.mjs +1 -1
- package/dist/{index-BDqz2_Yu.d.ts → index-1Z4GuYBi.d.ts} +7 -1
- package/dist/{index-DhsG2o5q.d.mts → index-BV0z5mb6.d.mts} +7 -1
- package/dist/index.d.mts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +507 -352
- package/dist/index.mjs +427 -253
- package/dist/server.d.mts +35 -5
- package/dist/server.d.ts +35 -5
- package/dist/server.js +1183 -795
- package/dist/server.mjs +163 -176
- package/package.json +4 -2
- package/src/app/page.tsx +1 -2
- package/src/components/DynamicChart.tsx +10 -35
- package/src/components/MessageBubble.tsx +223 -74
- package/src/components/ProductCard.tsx +2 -2
- package/src/components/VisualizationRenderer.tsx +347 -247
- package/src/config/RagConfig.ts +5 -0
- package/src/config/serverConfig.ts +3 -1
- package/src/core/Pipeline.ts +70 -209
- package/src/core/ProviderRegistry.ts +2 -2
- package/src/core/VectorPlugin.ts +9 -0
- package/src/handlers/index.ts +23 -7
- package/src/hooks/useRagChat.ts +2 -2
- package/src/llm/LLMFactory.ts +54 -2
- package/src/llm/providers/AnthropicProvider.ts +12 -8
- package/src/llm/providers/GeminiProvider.ts +188 -143
- package/src/llm/providers/OllamaProvider.ts +7 -3
- package/src/llm/providers/OpenAIProvider.ts +12 -8
- package/src/types/chat.ts +6 -0
- package/src/types/index.ts +81 -0
- package/src/utils/SchemaMapper.ts +129 -0
- package/src/utils/UITransformer.ts +524 -194
- package/dist/DocumentChunker-Bmscbh-X.d.ts +0 -93
- package/dist/DocumentChunker-DCuxrOdM.d.mts +0 -93
- package/dist/PostgreSQLProvider-BMOETDZA.mjs +0 -8
- package/dist/chunk-FLOSGE6A.mjs +0 -202
package/dist/index.js
CHANGED
|
@@ -71,18 +71,17 @@ __export(index_exports, {
|
|
|
71
71
|
module.exports = __toCommonJS(index_exports);
|
|
72
72
|
|
|
73
73
|
// src/components/ChatWidget.tsx
|
|
74
|
-
var
|
|
74
|
+
var import_react10 = __toESM(require("react"));
|
|
75
75
|
var import_lucide_react6 = require("lucide-react");
|
|
76
76
|
|
|
77
77
|
// src/components/ChatWindow.tsx
|
|
78
|
-
var
|
|
78
|
+
var import_react9 = __toESM(require("react"));
|
|
79
79
|
var import_lucide_react5 = require("lucide-react");
|
|
80
80
|
|
|
81
81
|
// src/components/MessageBubble.tsx
|
|
82
|
-
var
|
|
82
|
+
var import_react6 = __toESM(require("react"));
|
|
83
83
|
var import_lucide_react4 = require("lucide-react");
|
|
84
84
|
var import_react_markdown = __toESM(require("react-markdown"));
|
|
85
|
-
var import_remark_gfm = __toESM(require("remark-gfm"));
|
|
86
85
|
|
|
87
86
|
// src/components/SourceCard.tsx
|
|
88
87
|
var import_react = __toESM(require("react"));
|
|
@@ -304,37 +303,12 @@ function DynamicChart({
|
|
|
304
303
|
const finalXKey = String(resolvedXKey);
|
|
305
304
|
const finalDataKeys = resolvedDataKeys.map(String).filter((k) => k !== "undefined");
|
|
306
305
|
const pieDataKey = finalDataKeys[0] || "value";
|
|
307
|
-
const stockAwareColor = (entry, index) => {
|
|
308
|
-
var _a, _b, _c;
|
|
309
|
-
const stockStatus = String(
|
|
310
|
-
(_c = (_b = (_a = entry.stockStatus) != null ? _a : entry.status) != null ? _b : entry.availability) != null ? _c : ""
|
|
311
|
-
).toLowerCase();
|
|
312
|
-
const inStockCount = typeof entry.inStockCount === "number" ? entry.inStockCount : void 0;
|
|
313
|
-
const outOfStockCount = typeof entry.outOfStockCount === "number" ? entry.outOfStockCount : void 0;
|
|
314
|
-
const inStockFlag = entry.inStock;
|
|
315
|
-
if (stockStatus.includes("in stock")) return "#10b981";
|
|
316
|
-
if (stockStatus.includes("out of stock")) return "#f97316";
|
|
317
|
-
if (typeof inStockFlag === "string" && inStockFlag.toLowerCase() === "true") return "#10b981";
|
|
318
|
-
if (inStockFlag === 1) return "#10b981";
|
|
319
|
-
if (inStockFlag === 0) return "#f97316";
|
|
320
|
-
if (typeof inStockCount === "number" || typeof outOfStockCount === "number") {
|
|
321
|
-
const inCount = inStockCount != null ? inStockCount : 0;
|
|
322
|
-
const outCount = outOfStockCount != null ? outOfStockCount : 0;
|
|
323
|
-
if (inCount > outCount) return "#10b981";
|
|
324
|
-
if (outCount > inCount) return "#f97316";
|
|
325
|
-
}
|
|
326
|
-
return colors[index % colors.length];
|
|
327
|
-
};
|
|
328
306
|
const tooltipLabelMap = {
|
|
329
|
-
value: "
|
|
307
|
+
value: "Total Items",
|
|
330
308
|
count: "Count",
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
stockStatus: "Stock status",
|
|
335
|
-
category: "Category",
|
|
336
|
-
label: "Label",
|
|
337
|
-
name: "Name"
|
|
309
|
+
inStockCount: "In Stock",
|
|
310
|
+
outOfStockCount: "Out of Stock",
|
|
311
|
+
stockStatus: "Status"
|
|
338
312
|
};
|
|
339
313
|
const renderTooltip = (row, label) => {
|
|
340
314
|
var _a, _b;
|
|
@@ -343,6 +317,8 @@ function DynamicChart({
|
|
|
343
317
|
var _a2;
|
|
344
318
|
if (value === null || value === void 0 || key === finalXKey) return null;
|
|
345
319
|
if (typeof value === "object") return null;
|
|
320
|
+
const forbiddenKeys = ["fill", "color", "payload", "percent", "stroke", "inStock"];
|
|
321
|
+
if (forbiddenKeys.includes(key)) return null;
|
|
346
322
|
return /* @__PURE__ */ import_react4.default.createElement("div", { key, className: "flex items-center justify-between gap-3 text-slate-600 dark:text-white/70" }, /* @__PURE__ */ import_react4.default.createElement("span", null, (_a2 = tooltipLabelMap[key]) != null ? _a2 : key), /* @__PURE__ */ import_react4.default.createElement("span", { className: "font-medium text-slate-900 dark:text-white/90" }, String(value)));
|
|
347
323
|
}));
|
|
348
324
|
};
|
|
@@ -367,7 +343,7 @@ function DynamicChart({
|
|
|
367
343
|
label: false,
|
|
368
344
|
labelLine: false
|
|
369
345
|
},
|
|
370
|
-
sanitizedData.map((
|
|
346
|
+
sanitizedData.map((_entry, index) => /* @__PURE__ */ import_react4.default.createElement(import_recharts.Cell, { key: `cell-${index}`, fill: colors[index % colors.length] }))
|
|
371
347
|
), /* @__PURE__ */ import_react4.default.createElement(import_recharts.Tooltip, { content: (props) => renderTooltip(getTooltipRow(props.payload), typeof props.label === "string" ? props.label : void 0) }), showLegend && !isCompact && /* @__PURE__ */ import_react4.default.createElement(import_recharts.Legend, { wrapperStyle: { fontSize: 12 }, verticalAlign: "bottom" })))));
|
|
372
348
|
}
|
|
373
349
|
return /* @__PURE__ */ import_react4.default.createElement("div", { ref: containerRef, className: "w-full min-w-0 mt-4 mb-2 select-none overflow-hidden" }, /* @__PURE__ */ import_react4.default.createElement("div", { className: "w-full aspect-[4/3]" }, /* @__PURE__ */ import_react4.default.createElement(import_recharts.ResponsiveContainer, { width: "100%", height: "100%" }, type === "bar" ? /* @__PURE__ */ import_react4.default.createElement(import_recharts.BarChart, { data: sanitizedData, margin: chartMargin }, /* @__PURE__ */ import_react4.default.createElement(import_recharts.CartesianGrid, { strokeDasharray: "3 3", vertical: false, stroke: "#e2e8f0" }), /* @__PURE__ */ import_react4.default.createElement(import_recharts.XAxis, { dataKey: finalXKey, tick: axisTick, tickFormatter: truncateAxisLabel, tickLine: false, axisLine: { stroke: "#cbd5e1" }, interval: 0, minTickGap: isTiny ? 2 : isCompact ? 6 : 12 }), /* @__PURE__ */ import_react4.default.createElement(import_recharts.YAxis, { tick: axisTick, tickLine: false, axisLine: false }), /* @__PURE__ */ import_react4.default.createElement(import_recharts.Tooltip, { content: (props) => renderTooltip(getTooltipRow(props.payload), typeof props.label === "string" ? props.label : void 0), cursor: { fill: "#f1f5f9" } }), showLegend && /* @__PURE__ */ import_react4.default.createElement(import_recharts.Legend, { wrapperStyle: { fontSize: isCompact ? 10 : 12 } }), finalDataKeys.map((key, index) => /* @__PURE__ */ import_react4.default.createElement(
|
|
@@ -394,175 +370,232 @@ function DynamicChart({
|
|
|
394
370
|
}
|
|
395
371
|
|
|
396
372
|
// src/components/VisualizationRenderer.tsx
|
|
397
|
-
var
|
|
373
|
+
var import_react5 = __toESM(require("react"));
|
|
374
|
+
var import_recharts2 = require("recharts");
|
|
375
|
+
var CHART_COLORS = [
|
|
376
|
+
"#6366f1",
|
|
377
|
+
// indigo
|
|
378
|
+
"#10b981",
|
|
379
|
+
// emerald
|
|
380
|
+
"#f59e0b",
|
|
381
|
+
// amber
|
|
382
|
+
"#ef4444",
|
|
383
|
+
// red
|
|
384
|
+
"#8b5cf6",
|
|
385
|
+
// purple
|
|
386
|
+
"#ec4899",
|
|
387
|
+
// pink
|
|
388
|
+
"#06b6d4",
|
|
389
|
+
// cyan
|
|
390
|
+
"#f97316"
|
|
391
|
+
// orange
|
|
392
|
+
];
|
|
393
|
+
function getColor(index) {
|
|
394
|
+
return CHART_COLORS[index % CHART_COLORS.length];
|
|
395
|
+
}
|
|
396
|
+
function CustomTooltip({
|
|
397
|
+
active,
|
|
398
|
+
payload,
|
|
399
|
+
label
|
|
400
|
+
}) {
|
|
401
|
+
if (!active || !payload || payload.length === 0) return null;
|
|
402
|
+
return /* @__PURE__ */ import_react5.default.createElement("div", { className: "rounded-xl border border-slate-200 bg-white px-3 py-2 text-xs shadow-xl dark:border-white/10 dark:bg-slate-950" }, label && /* @__PURE__ */ import_react5.default.createElement("p", { className: "mb-2 font-semibold text-slate-800 dark:text-white/90" }, label), payload.map((entry, i) => /* @__PURE__ */ import_react5.default.createElement("div", { key: i, className: "flex items-center justify-between gap-3 text-slate-600 dark:text-white/70" }, /* @__PURE__ */ import_react5.default.createElement("span", { className: "flex items-center gap-1.5" }, entry.color && /* @__PURE__ */ import_react5.default.createElement(
|
|
403
|
+
"span",
|
|
404
|
+
{
|
|
405
|
+
className: "inline-block w-2 h-2 rounded-full flex-shrink-0",
|
|
406
|
+
style: { background: entry.color }
|
|
407
|
+
}
|
|
408
|
+
), entry.name), /* @__PURE__ */ import_react5.default.createElement("span", { className: "font-medium text-slate-900 dark:text-white/90" }, entry.value))));
|
|
409
|
+
}
|
|
398
410
|
function VisualizationRenderer({
|
|
399
411
|
data,
|
|
400
|
-
className = ""
|
|
412
|
+
className = "",
|
|
413
|
+
primaryColor,
|
|
414
|
+
onAddToCart
|
|
401
415
|
}) {
|
|
416
|
+
var _a;
|
|
402
417
|
if (!data) {
|
|
403
|
-
return /* @__PURE__ */
|
|
418
|
+
return /* @__PURE__ */ import_react5.default.createElement("div", { className: `p-4 text-gray-500 ${className}` }, "No data available for visualization");
|
|
404
419
|
}
|
|
405
|
-
return /* @__PURE__ */
|
|
420
|
+
return /* @__PURE__ */ import_react5.default.createElement("div", { className: `space-y-4 ${className}` }, /* @__PURE__ */ import_react5.default.createElement("div", { className: "space-y-1" }, /* @__PURE__ */ import_react5.default.createElement("h3", { className: "text-sm font-semibold text-slate-900 dark:text-white" }, data.title), data.description && data.description !== ((_a = data.data) == null ? void 0 : _a.content) && /* @__PURE__ */ import_react5.default.createElement("p", { className: "text-xs text-slate-500 dark:text-slate-400" }, data.description)), renderVisualization(data.type, data.data, onAddToCart, primaryColor));
|
|
406
421
|
}
|
|
407
|
-
function renderVisualization(type, data) {
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
+
function renderVisualization(type, data, onAddToCart, primaryColor) {
|
|
423
|
+
try {
|
|
424
|
+
switch (type) {
|
|
425
|
+
case "pie_chart":
|
|
426
|
+
return /* @__PURE__ */ import_react5.default.createElement(PieChartView, { data });
|
|
427
|
+
case "bar_chart":
|
|
428
|
+
return /* @__PURE__ */ import_react5.default.createElement(BarChartView, { data, primaryColor });
|
|
429
|
+
case "line_chart":
|
|
430
|
+
return /* @__PURE__ */ import_react5.default.createElement(LineChartView, { data, primaryColor });
|
|
431
|
+
case "radar_chart":
|
|
432
|
+
return /* @__PURE__ */ import_react5.default.createElement(RadarChartView, { data });
|
|
433
|
+
case "table":
|
|
434
|
+
return /* @__PURE__ */ import_react5.default.createElement(TableView, { data });
|
|
435
|
+
case "product_carousel":
|
|
436
|
+
case "carousel":
|
|
437
|
+
return /* @__PURE__ */ import_react5.default.createElement(CarouselView, { data, onAddToCart, primaryColor });
|
|
438
|
+
case "text":
|
|
439
|
+
default:
|
|
440
|
+
return /* @__PURE__ */ import_react5.default.createElement(TextView, { data });
|
|
441
|
+
}
|
|
442
|
+
} catch (error) {
|
|
443
|
+
console.warn("[VisualizationRenderer] Rendering failed, falling back to text:", error);
|
|
444
|
+
return /* @__PURE__ */ import_react5.default.createElement(TextView, { data: { content: "Unable to render the requested visualization." } });
|
|
422
445
|
}
|
|
423
446
|
}
|
|
424
|
-
function
|
|
425
|
-
if (!Array.isArray(data)) {
|
|
426
|
-
return /* @__PURE__ */
|
|
447
|
+
function PieChartView({ data }) {
|
|
448
|
+
if (!Array.isArray(data) || data.length === 0) {
|
|
449
|
+
return /* @__PURE__ */ import_react5.default.createElement("div", { className: "text-xs text-red-500" }, "Invalid pie chart data");
|
|
427
450
|
}
|
|
428
|
-
|
|
429
|
-
|
|
451
|
+
const chartData = data.map((item) => ({
|
|
452
|
+
name: item.label,
|
|
453
|
+
value: item.value
|
|
454
|
+
}));
|
|
455
|
+
return /* @__PURE__ */ import_react5.default.createElement("div", { className: "bg-white dark:bg-slate-900 rounded-xl border border-slate-200 dark:border-white/10 p-4 shadow-sm" }, /* @__PURE__ */ import_react5.default.createElement(import_recharts2.ResponsiveContainer, { width: "100%", height: 280 }, /* @__PURE__ */ import_react5.default.createElement(import_recharts2.PieChart, null, /* @__PURE__ */ import_react5.default.createElement(
|
|
456
|
+
import_recharts2.Pie,
|
|
430
457
|
{
|
|
431
|
-
|
|
432
|
-
|
|
458
|
+
data: chartData,
|
|
459
|
+
dataKey: "value",
|
|
460
|
+
nameKey: "name",
|
|
461
|
+
cx: "50%",
|
|
462
|
+
cy: "50%",
|
|
463
|
+
outerRadius: "68%",
|
|
464
|
+
label: false,
|
|
465
|
+
labelLine: false
|
|
433
466
|
},
|
|
434
|
-
/* @__PURE__ */
|
|
435
|
-
|
|
436
|
-
{
|
|
437
|
-
className: "w-3 h-3 rounded-full",
|
|
438
|
-
style: { backgroundColor: generateColor(idx) }
|
|
439
|
-
}
|
|
440
|
-
),
|
|
441
|
-
/* @__PURE__ */ React.createElement("span", { className: "text-sm font-medium text-gray-700 dark:text-gray-300" }, item.label, ": ", item.value),
|
|
442
|
-
item.inStock !== void 0 && /* @__PURE__ */ React.createElement(
|
|
443
|
-
"span",
|
|
444
|
-
{
|
|
445
|
-
className: `text-xs px-2 py-1 rounded ${item.inStock ? "bg-green-100 text-green-800" : "bg-red-100 text-red-800"}`
|
|
446
|
-
},
|
|
447
|
-
item.inStock ? "In Stock" : "Out of Stock"
|
|
448
|
-
)
|
|
449
|
-
))));
|
|
467
|
+
chartData.map((_entry, index) => /* @__PURE__ */ import_react5.default.createElement(import_recharts2.Cell, { key: `cell-${index}`, fill: getColor(index) }))
|
|
468
|
+
), /* @__PURE__ */ import_react5.default.createElement(import_recharts2.Tooltip, { content: /* @__PURE__ */ import_react5.default.createElement(CustomTooltip, null) }), /* @__PURE__ */ import_react5.default.createElement(import_recharts2.Legend, { wrapperStyle: { fontSize: 12 }, verticalAlign: "bottom" }))));
|
|
450
469
|
}
|
|
451
|
-
function
|
|
452
|
-
if (!Array.isArray(data)) {
|
|
453
|
-
return /* @__PURE__ */
|
|
470
|
+
function BarChartView({ data, primaryColor }) {
|
|
471
|
+
if (!Array.isArray(data) || data.length === 0) {
|
|
472
|
+
return /* @__PURE__ */ import_react5.default.createElement("div", { className: "text-xs text-red-500" }, "Invalid bar chart data");
|
|
454
473
|
}
|
|
455
|
-
|
|
456
|
-
|
|
474
|
+
const chartData = data.map((item) => __spreadValues(__spreadValues({
|
|
475
|
+
category: item.category,
|
|
476
|
+
value: item.value
|
|
477
|
+
}, item.inStockCount !== void 0 && { inStockCount: item.inStockCount }), item.outOfStockCount !== void 0 && { outOfStockCount: item.outOfStockCount }));
|
|
478
|
+
const barColor = primaryColor != null ? primaryColor : getColor(0);
|
|
479
|
+
const hasStock = chartData.some((d) => "inStockCount" in d);
|
|
480
|
+
return /* @__PURE__ */ import_react5.default.createElement("div", { className: "bg-white dark:bg-slate-900 rounded-xl border border-slate-200 dark:border-white/10 p-4 shadow-sm overflow-x-auto" }, /* @__PURE__ */ import_react5.default.createElement(import_recharts2.ResponsiveContainer, { width: "100%", height: 260 }, /* @__PURE__ */ import_react5.default.createElement(import_recharts2.BarChart, { data: chartData, margin: { top: 10, right: 10, left: -20, bottom: 0 } }, /* @__PURE__ */ import_react5.default.createElement(import_recharts2.CartesianGrid, { strokeDasharray: "3 3", vertical: false, stroke: "#e2e8f0" }), /* @__PURE__ */ import_react5.default.createElement(
|
|
481
|
+
import_recharts2.XAxis,
|
|
457
482
|
{
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
}
|
|
483
|
+
dataKey: "category",
|
|
484
|
+
tick: { fontSize: 11, fill: "#64748b" },
|
|
485
|
+
tickLine: false,
|
|
486
|
+
axisLine: { stroke: "#cbd5e1" }
|
|
463
487
|
}
|
|
464
|
-
)),
|
|
465
|
-
"span",
|
|
466
|
-
{
|
|
467
|
-
className: `text-xs px-2 py-1 rounded inline-block ${item.inStock ? "bg-green-100 text-green-800" : "bg-red-100 text-red-800"}`
|
|
468
|
-
},
|
|
469
|
-
item.inStock ? "In Stock" : "Out of Stock"
|
|
470
|
-
)))));
|
|
488
|
+
), /* @__PURE__ */ import_react5.default.createElement(import_recharts2.YAxis, { tick: { fontSize: 11, fill: "#64748b" }, tickLine: false, axisLine: false }), /* @__PURE__ */ import_react5.default.createElement(import_recharts2.Tooltip, { content: /* @__PURE__ */ import_react5.default.createElement(CustomTooltip, null), cursor: { fill: "#f1f5f9" } }), /* @__PURE__ */ import_react5.default.createElement(import_recharts2.Legend, { wrapperStyle: { fontSize: 12 } }), hasStock ? /* @__PURE__ */ import_react5.default.createElement(import_react5.default.Fragment, null, /* @__PURE__ */ import_react5.default.createElement(import_recharts2.Bar, { dataKey: "inStockCount", name: "In Stock", fill: getColor(1), radius: [4, 4, 0, 0] }), /* @__PURE__ */ import_react5.default.createElement(import_recharts2.Bar, { dataKey: "outOfStockCount", name: "Out of Stock", fill: getColor(3), radius: [4, 4, 0, 0] })) : /* @__PURE__ */ import_react5.default.createElement(import_recharts2.Bar, { dataKey: "value", name: "Value", fill: barColor, radius: [4, 4, 0, 0] }))));
|
|
471
489
|
}
|
|
472
|
-
function
|
|
473
|
-
if (!Array.isArray(data)) {
|
|
474
|
-
return /* @__PURE__ */
|
|
490
|
+
function LineChartView({ data, primaryColor }) {
|
|
491
|
+
if (!Array.isArray(data) || data.length === 0) {
|
|
492
|
+
return /* @__PURE__ */ import_react5.default.createElement("div", { className: "text-xs text-red-500" }, "Invalid line chart data");
|
|
475
493
|
}
|
|
476
|
-
|
|
477
|
-
|
|
494
|
+
const chartData = data.map((point) => {
|
|
495
|
+
var _a;
|
|
496
|
+
return {
|
|
497
|
+
label: String((_a = point.label) != null ? _a : point.timestamp),
|
|
498
|
+
value: Number(point.value)
|
|
499
|
+
};
|
|
500
|
+
});
|
|
501
|
+
const lineColor = primaryColor != null ? primaryColor : getColor(0);
|
|
502
|
+
return /* @__PURE__ */ import_react5.default.createElement("div", { className: "bg-white dark:bg-slate-900 rounded-xl border border-slate-200 dark:border-white/10 p-4 shadow-sm overflow-x-auto" }, /* @__PURE__ */ import_react5.default.createElement(import_recharts2.ResponsiveContainer, { width: "100%", height: 260 }, /* @__PURE__ */ import_react5.default.createElement(import_recharts2.LineChart, { data: chartData, margin: { top: 10, right: 10, left: -20, bottom: 0 } }, /* @__PURE__ */ import_react5.default.createElement(import_recharts2.CartesianGrid, { strokeDasharray: "3 3", vertical: false, stroke: "#e2e8f0" }), /* @__PURE__ */ import_react5.default.createElement(
|
|
503
|
+
import_recharts2.XAxis,
|
|
478
504
|
{
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
505
|
+
dataKey: "label",
|
|
506
|
+
tick: { fontSize: 11, fill: "#64748b" },
|
|
507
|
+
tickLine: false,
|
|
508
|
+
axisLine: { stroke: "#cbd5e1" }
|
|
509
|
+
}
|
|
510
|
+
), /* @__PURE__ */ import_react5.default.createElement(import_recharts2.YAxis, { tick: { fontSize: 11, fill: "#64748b" }, tickLine: false, axisLine: false }), /* @__PURE__ */ import_react5.default.createElement(import_recharts2.Tooltip, { content: /* @__PURE__ */ import_react5.default.createElement(CustomTooltip, null) }), /* @__PURE__ */ import_react5.default.createElement(
|
|
511
|
+
import_recharts2.Line,
|
|
512
|
+
{
|
|
513
|
+
type: "monotone",
|
|
514
|
+
dataKey: "value",
|
|
515
|
+
name: "Value",
|
|
516
|
+
stroke: lineColor,
|
|
517
|
+
strokeWidth: 2.5,
|
|
518
|
+
dot: { r: 3.5, strokeWidth: 2, fill: lineColor },
|
|
519
|
+
activeDot: { r: 5 }
|
|
520
|
+
}
|
|
484
521
|
))));
|
|
485
522
|
}
|
|
486
|
-
function
|
|
487
|
-
if (!data
|
|
488
|
-
return /* @__PURE__ */
|
|
523
|
+
function RadarChartView({ data }) {
|
|
524
|
+
if (!Array.isArray(data) || data.length === 0) {
|
|
525
|
+
return /* @__PURE__ */ import_react5.default.createElement("div", { className: "text-xs text-red-500" }, "Invalid radar chart data");
|
|
489
526
|
}
|
|
490
|
-
|
|
527
|
+
const productNames = Array.from(
|
|
528
|
+
new Set(data.flatMap((item) => Object.keys(item).filter((key) => key !== "attribute")))
|
|
529
|
+
);
|
|
530
|
+
return /* @__PURE__ */ import_react5.default.createElement("div", { className: "bg-white dark:bg-slate-900 rounded-xl border border-slate-200 dark:border-white/10 p-4 shadow-sm" }, /* @__PURE__ */ import_react5.default.createElement(import_recharts2.ResponsiveContainer, { width: "100%", height: 300 }, /* @__PURE__ */ import_react5.default.createElement(import_recharts2.RadarChart, { cx: "50%", cy: "50%", outerRadius: "80%", data }, /* @__PURE__ */ import_react5.default.createElement(import_recharts2.PolarGrid, { stroke: "#e2e8f0" }), /* @__PURE__ */ import_react5.default.createElement(import_recharts2.PolarAngleAxis, { dataKey: "attribute", tick: { fontSize: 11, fill: "#64748b" } }), /* @__PURE__ */ import_react5.default.createElement(import_recharts2.PolarRadiusAxis, { tick: { fontSize: 10, fill: "#64748b" } }), productNames.map((productName, index) => /* @__PURE__ */ import_react5.default.createElement(
|
|
531
|
+
import_recharts2.Radar,
|
|
532
|
+
{
|
|
533
|
+
key: productName,
|
|
534
|
+
name: productName,
|
|
535
|
+
dataKey: productName,
|
|
536
|
+
stroke: getColor(index),
|
|
537
|
+
fill: getColor(index),
|
|
538
|
+
fillOpacity: 0.4
|
|
539
|
+
}
|
|
540
|
+
)), /* @__PURE__ */ import_react5.default.createElement(import_recharts2.Tooltip, { content: /* @__PURE__ */ import_react5.default.createElement(CustomTooltip, null) }), /* @__PURE__ */ import_react5.default.createElement(import_recharts2.Legend, { wrapperStyle: { fontSize: 12 } }))));
|
|
541
|
+
}
|
|
542
|
+
function TableView({ data }) {
|
|
543
|
+
if (!(data == null ? void 0 : data.columns) || !(data == null ? void 0 : data.rows)) {
|
|
544
|
+
return /* @__PURE__ */ import_react5.default.createElement("div", { className: "text-xs text-red-500" }, "Invalid table data");
|
|
545
|
+
}
|
|
546
|
+
return /* @__PURE__ */ import_react5.default.createElement("div", { className: "bg-white dark:bg-slate-900 rounded-xl border border-slate-200 dark:border-white/10 shadow-sm overflow-hidden" }, /* @__PURE__ */ import_react5.default.createElement("div", { className: "overflow-x-auto" }, /* @__PURE__ */ import_react5.default.createElement("table", { className: "w-full text-sm border-collapse" }, /* @__PURE__ */ import_react5.default.createElement("thead", { className: "bg-slate-50 dark:bg-white/5 border-b border-slate-200 dark:border-white/10" }, /* @__PURE__ */ import_react5.default.createElement("tr", null, data.columns.map((col, idx) => /* @__PURE__ */ import_react5.default.createElement(
|
|
491
547
|
"th",
|
|
492
548
|
{
|
|
493
549
|
key: idx,
|
|
494
|
-
className: "px-4 py-
|
|
550
|
+
className: "px-4 py-3 text-left text-xs font-semibold text-slate-700 dark:text-white/90 whitespace-nowrap uppercase tracking-wider"
|
|
495
551
|
},
|
|
496
552
|
col
|
|
497
|
-
)))), /* @__PURE__ */
|
|
553
|
+
)))), /* @__PURE__ */ import_react5.default.createElement("tbody", { className: "divide-y divide-slate-100 dark:divide-white/5" }, data.rows.map((row, rowIdx) => /* @__PURE__ */ import_react5.default.createElement(
|
|
498
554
|
"tr",
|
|
499
555
|
{
|
|
500
556
|
key: rowIdx,
|
|
501
|
-
className: "hover:bg-
|
|
557
|
+
className: "hover:bg-slate-50/60 dark:hover:bg-white/5 transition-colors"
|
|
502
558
|
},
|
|
503
|
-
row.map((cell, cellIdx) => /* @__PURE__ */
|
|
559
|
+
row.map((cell, cellIdx) => /* @__PURE__ */ import_react5.default.createElement(
|
|
504
560
|
"td",
|
|
505
561
|
{
|
|
506
562
|
key: cellIdx,
|
|
507
|
-
className: "px-4 py-
|
|
563
|
+
className: "px-4 py-3 text-slate-600 dark:text-white/70 text-sm"
|
|
508
564
|
},
|
|
509
565
|
String(cell)
|
|
510
566
|
))
|
|
511
|
-
)))));
|
|
567
|
+
))))), /* @__PURE__ */ import_react5.default.createElement("div", { className: "px-4 py-2 bg-slate-50 dark:bg-white/5 border-t border-slate-100 dark:border-white/5" }, /* @__PURE__ */ import_react5.default.createElement("p", { className: "text-[11px] text-slate-400 dark:text-white/30" }, data.rows.length, " row", data.rows.length !== 1 ? "s" : "")));
|
|
512
568
|
}
|
|
513
|
-
function
|
|
569
|
+
function CarouselView({
|
|
570
|
+
data,
|
|
571
|
+
onAddToCart,
|
|
572
|
+
primaryColor
|
|
573
|
+
}) {
|
|
514
574
|
if (!Array.isArray(data)) {
|
|
515
|
-
return /* @__PURE__ */
|
|
575
|
+
return /* @__PURE__ */ import_react5.default.createElement("div", { className: "text-xs text-red-500" }, "Invalid carousel data");
|
|
516
576
|
}
|
|
517
|
-
|
|
518
|
-
|
|
577
|
+
const products = data.map((product) => ({
|
|
578
|
+
id: product.id,
|
|
579
|
+
name: product.name,
|
|
580
|
+
brand: product.brand,
|
|
581
|
+
price: product.price,
|
|
582
|
+
image: product.image,
|
|
583
|
+
link: typeof product.link === "string" ? product.link : void 0,
|
|
584
|
+
description: product.description,
|
|
585
|
+
inStock: product.inStock
|
|
586
|
+
}));
|
|
587
|
+
return /* @__PURE__ */ import_react5.default.createElement("div", { className: "w-full" }, /* @__PURE__ */ import_react5.default.createElement(
|
|
588
|
+
ProductCarousel,
|
|
519
589
|
{
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
{
|
|
526
|
-
src: product.image,
|
|
527
|
-
alt: product.name,
|
|
528
|
-
fill: true,
|
|
529
|
-
className: "object-cover",
|
|
530
|
-
sizes: "(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
|
|
531
|
-
}
|
|
532
|
-
)),
|
|
533
|
-
/* @__PURE__ */ React.createElement("div", { className: "p-4 space-y-2" }, /* @__PURE__ */ React.createElement("h4", { className: "font-semibold text-gray-900 dark:text-white line-clamp-2" }, product.name), product.brand && /* @__PURE__ */ React.createElement("p", { className: "text-xs text-gray-500 dark:text-gray-400" }, "Brand: ", product.brand), product.price && /* @__PURE__ */ React.createElement("p", { className: "text-lg font-bold text-gray-900 dark:text-white" }, "$", typeof product.price === "number" ? product.price.toFixed(2) : product.price), product.description && /* @__PURE__ */ React.createElement("p", { className: "text-sm text-gray-600 dark:text-gray-400 line-clamp-2" }, product.description), /* @__PURE__ */ React.createElement("div", { className: "flex gap-2 pt-2" }, /* @__PURE__ */ React.createElement(
|
|
534
|
-
"span",
|
|
535
|
-
{
|
|
536
|
-
className: `text-xs px-2 py-1 rounded flex-1 text-center ${product.inStock ? "bg-green-100 text-green-800" : "bg-red-100 text-red-800"}`
|
|
537
|
-
},
|
|
538
|
-
product.inStock ? "In Stock" : "Out of Stock"
|
|
539
|
-
)))
|
|
540
|
-
))));
|
|
541
|
-
}
|
|
542
|
-
function renderText(data) {
|
|
543
|
-
const content = (data == null ? void 0 : data.content) || String(data);
|
|
544
|
-
return /* @__PURE__ */ React.createElement("div", { className: "bg-white dark:bg-gray-800 p-4 rounded-lg shadow prose dark:prose-invert max-w-none" }, /* @__PURE__ */ React.createElement("p", { className: "text-gray-700 dark:text-gray-300 whitespace-pre-wrap" }, content));
|
|
590
|
+
products,
|
|
591
|
+
primaryColor: primaryColor != null ? primaryColor : "#6366f1",
|
|
592
|
+
onAddToCart: (p) => onAddToCart == null ? void 0 : onAddToCart(p)
|
|
593
|
+
}
|
|
594
|
+
));
|
|
545
595
|
}
|
|
546
|
-
function
|
|
547
|
-
const
|
|
548
|
-
|
|
549
|
-
// blue
|
|
550
|
-
"#10B981",
|
|
551
|
-
// green
|
|
552
|
-
"#F59E0B",
|
|
553
|
-
// amber
|
|
554
|
-
"#EF4444",
|
|
555
|
-
// red
|
|
556
|
-
"#8B5CF6",
|
|
557
|
-
// purple
|
|
558
|
-
"#EC4899",
|
|
559
|
-
// pink
|
|
560
|
-
"#06B6D4",
|
|
561
|
-
// cyan
|
|
562
|
-
"#F97316"
|
|
563
|
-
// orange
|
|
564
|
-
];
|
|
565
|
-
return colors[index % colors.length];
|
|
596
|
+
function TextView({ data }) {
|
|
597
|
+
const content = (data == null ? void 0 : data.content) || String(data != null ? data : "");
|
|
598
|
+
return /* @__PURE__ */ import_react5.default.createElement("div", { className: "bg-white dark:bg-slate-900 rounded-xl border border-slate-200 dark:border-white/10 p-4 shadow-sm" }, /* @__PURE__ */ import_react5.default.createElement("p", { className: "text-sm text-slate-700 dark:text-slate-300 whitespace-pre-wrap leading-relaxed" }, content));
|
|
566
599
|
}
|
|
567
600
|
|
|
568
601
|
// src/components/MessageBubble.tsx
|
|
@@ -646,41 +679,51 @@ function stripStructuredUiLabels(raw) {
|
|
|
646
679
|
);
|
|
647
680
|
}
|
|
648
681
|
function extractBareJsonObject(raw) {
|
|
649
|
-
|
|
682
|
+
let start = raw.indexOf("{");
|
|
650
683
|
if (start === -1) return null;
|
|
651
|
-
let
|
|
652
|
-
let
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
if (
|
|
673
|
-
|
|
684
|
+
let bestJson = null;
|
|
685
|
+
let maxLen = 0;
|
|
686
|
+
while (start !== -1) {
|
|
687
|
+
let depth = 0;
|
|
688
|
+
let inString = false;
|
|
689
|
+
let escape = false;
|
|
690
|
+
for (let i = start; i < raw.length; i += 1) {
|
|
691
|
+
const ch = raw[i];
|
|
692
|
+
if (escape) {
|
|
693
|
+
escape = false;
|
|
694
|
+
continue;
|
|
695
|
+
}
|
|
696
|
+
if (ch === "\\" && inString) {
|
|
697
|
+
escape = true;
|
|
698
|
+
continue;
|
|
699
|
+
}
|
|
700
|
+
if (ch === '"') {
|
|
701
|
+
inString = !inString;
|
|
702
|
+
continue;
|
|
703
|
+
}
|
|
704
|
+
if (inString) continue;
|
|
705
|
+
if (ch === "{") depth += 1;
|
|
706
|
+
else if (ch === "}") {
|
|
707
|
+
depth -= 1;
|
|
708
|
+
if (depth === 0) {
|
|
709
|
+
const candidate = raw.slice(start, i + 1);
|
|
710
|
+
if (candidate.length > maxLen) {
|
|
711
|
+
maxLen = candidate.length;
|
|
712
|
+
bestJson = candidate;
|
|
713
|
+
}
|
|
714
|
+
break;
|
|
715
|
+
}
|
|
674
716
|
}
|
|
675
717
|
}
|
|
718
|
+
start = raw.indexOf("{", start + 1);
|
|
676
719
|
}
|
|
677
|
-
return
|
|
720
|
+
return bestJson;
|
|
678
721
|
}
|
|
679
722
|
function extractStructuredPayload(raw) {
|
|
680
723
|
var _a, _b;
|
|
681
724
|
let working = raw;
|
|
682
725
|
const fenceRegex = /```(?:[a-z]+)?\s*([\s\S]*?)```/gi;
|
|
683
|
-
for (const match of raw.matchAll(fenceRegex)) {
|
|
726
|
+
for (const match of Array.from(raw.matchAll(fenceRegex))) {
|
|
684
727
|
const body = (_b = (_a = match[1]) == null ? void 0 : _a.trim()) != null ? _b : "";
|
|
685
728
|
if (!looksLikeStructuredPayload(body)) continue;
|
|
686
729
|
working = working.replace(match[0], "");
|
|
@@ -704,21 +747,30 @@ function extractStructuredPayload(raw) {
|
|
|
704
747
|
}
|
|
705
748
|
function isLikelyUiOnlyMessage(text) {
|
|
706
749
|
const trimmed = text.trim();
|
|
707
|
-
return trimmed.length === 0 || /^(chart data|table data|visualization|visual representation|product catalog|product recommendations|catalog summary)\s*:?\s*$/i.test(trimmed);
|
|
750
|
+
return trimmed.length === 0 || trimmed.length < 30 || /^(chart data|table data|visualization|visual representation|product catalog|product recommendations|catalog summary|availability|inventory status|details)\s*:?\s*$/i.test(trimmed);
|
|
708
751
|
}
|
|
709
752
|
function resolveImage(data) {
|
|
710
753
|
const isPlaceholder = (val) => typeof val === "string" && (val === "..." || val === "" || val.toLowerCase() === "null" || val.toLowerCase() === "undefined");
|
|
711
|
-
for (const key of ["image", "img", "thumbnail"]) {
|
|
754
|
+
for (const key of ["image", "img", "thumbnail", "images", "product_image", "Image", "Thumbnail"]) {
|
|
712
755
|
const v = data[key];
|
|
713
756
|
if (typeof v === "string" && v && !isPlaceholder(v)) return v;
|
|
714
|
-
|
|
715
|
-
if (Array.isArray(data.images) && typeof data.images[0] === "string" && !isPlaceholder(data.images[0])) {
|
|
716
|
-
return data.images[0];
|
|
757
|
+
if (Array.isArray(v) && typeof v[0] === "string" && v[0] && !isPlaceholder(v[0])) return v[0];
|
|
717
758
|
}
|
|
718
759
|
return void 0;
|
|
719
760
|
}
|
|
761
|
+
function getMetadataValue(meta, keys) {
|
|
762
|
+
const searchKeys = keys.map((k) => k.toLowerCase());
|
|
763
|
+
const metaKeys = Object.keys(meta);
|
|
764
|
+
const foundKey = metaKeys.find((k) => searchKeys.includes(k.toLowerCase()));
|
|
765
|
+
if (foundKey) return meta[foundKey];
|
|
766
|
+
const partialKey = metaKeys.find((k) => {
|
|
767
|
+
const kLow = k.toLowerCase();
|
|
768
|
+
return searchKeys.some((sk) => kLow.includes(sk) || sk.includes(kLow));
|
|
769
|
+
});
|
|
770
|
+
return partialKey ? meta[partialKey] : void 0;
|
|
771
|
+
}
|
|
720
772
|
function normaliseChild(children) {
|
|
721
|
-
if (typeof children === "object" && children !== null && !Array.isArray(children) && !
|
|
773
|
+
if (typeof children === "object" && children !== null && !Array.isArray(children) && !import_react6.default.isValidElement(children)) {
|
|
722
774
|
return JSON.stringify(children);
|
|
723
775
|
}
|
|
724
776
|
return children;
|
|
@@ -732,7 +784,7 @@ function formatColumnLabel(value) {
|
|
|
732
784
|
function DataTable({ config, viewportSize = "large" }) {
|
|
733
785
|
const isCompact = viewportSize === "compact";
|
|
734
786
|
const isMedium = viewportSize === "medium";
|
|
735
|
-
const columns =
|
|
787
|
+
const columns = import_react6.default.useMemo(() => {
|
|
736
788
|
const rowKeys = Array.from(
|
|
737
789
|
new Set(
|
|
738
790
|
config.data.flatMap((row) => Object.keys(row))
|
|
@@ -762,27 +814,27 @@ function DataTable({ config, viewportSize = "large" }) {
|
|
|
762
814
|
return rowKeys.map((key) => ({ label: formatColumnLabel(key), accessor: key }));
|
|
763
815
|
}, [config]);
|
|
764
816
|
if (!config.data.length || !columns.length) {
|
|
765
|
-
return /* @__PURE__ */
|
|
817
|
+
return /* @__PURE__ */ import_react6.default.createElement("p", { className: "text-xs text-slate-400 italic my-2" }, "No data to display.");
|
|
766
818
|
}
|
|
767
819
|
const formatCell = (val) => {
|
|
768
820
|
if (val === null || val === void 0) return "\u2014";
|
|
769
821
|
if (typeof val === "boolean") return val ? "\u2713" : "\u2717";
|
|
770
822
|
return String(val);
|
|
771
823
|
};
|
|
772
|
-
return /* @__PURE__ */
|
|
824
|
+
return /* @__PURE__ */ import_react6.default.createElement("div", { className: "my-4 rounded-xl border border-slate-200 dark:border-white/10 shadow-sm overflow-hidden" }, config.title && /* @__PURE__ */ import_react6.default.createElement("div", { className: "px-4 py-2.5 bg-slate-50 dark:bg-white/5 border-b border-slate-200 dark:border-white/10" }, /* @__PURE__ */ import_react6.default.createElement("p", { className: "text-xs font-semibold text-slate-600 dark:text-white/70 uppercase tracking-wide" }, config.title)), /* @__PURE__ */ import_react6.default.createElement("div", { className: "overflow-x-auto" }, /* @__PURE__ */ import_react6.default.createElement("table", { className: `w-full text-left border-collapse ${isCompact ? "min-w-[240px] text-xs" : isMedium ? "min-w-[280px] text-[13px]" : "min-w-[320px] text-sm"}` }, /* @__PURE__ */ import_react6.default.createElement("thead", { className: "bg-slate-50 dark:bg-white/5 border-b border-slate-200 dark:border-white/10" }, /* @__PURE__ */ import_react6.default.createElement("tr", null, columns.map((column) => /* @__PURE__ */ import_react6.default.createElement(
|
|
773
825
|
"th",
|
|
774
826
|
{
|
|
775
827
|
key: column.label,
|
|
776
828
|
className: `${isCompact ? "px-2.5 py-2" : "px-4 py-3"} font-semibold text-slate-700 dark:text-white/90 whitespace-nowrap`
|
|
777
829
|
},
|
|
778
830
|
column.label
|
|
779
|
-
)))), /* @__PURE__ */
|
|
831
|
+
)))), /* @__PURE__ */ import_react6.default.createElement("tbody", null, config.data.map((row, ri) => /* @__PURE__ */ import_react6.default.createElement(
|
|
780
832
|
"tr",
|
|
781
833
|
{
|
|
782
834
|
key: ri,
|
|
783
835
|
className: "border-b border-slate-100 dark:border-white/5 last:border-0 hover:bg-slate-50/60 dark:hover:bg-white/5 transition-colors"
|
|
784
836
|
},
|
|
785
|
-
columns.map((column) => /* @__PURE__ */
|
|
837
|
+
columns.map((column) => /* @__PURE__ */ import_react6.default.createElement(
|
|
786
838
|
"td",
|
|
787
839
|
{
|
|
788
840
|
key: column.label,
|
|
@@ -790,10 +842,17 @@ function DataTable({ config, viewportSize = "large" }) {
|
|
|
790
842
|
},
|
|
791
843
|
formatCell(row[column.accessor])
|
|
792
844
|
))
|
|
793
|
-
))))), /* @__PURE__ */
|
|
845
|
+
))))), /* @__PURE__ */ import_react6.default.createElement("div", { className: "px-4 py-2 bg-slate-50 dark:bg-white/5 border-t border-slate-100 dark:border-white/5" }, /* @__PURE__ */ import_react6.default.createElement("p", { className: "text-[11px] text-slate-400 dark:text-white/30" }, config.data.length, " row", config.data.length !== 1 ? "s" : "")));
|
|
794
846
|
}
|
|
795
847
|
function normalizeTabularRows(rows, columns) {
|
|
796
848
|
if (!Array.isArray(rows)) return [];
|
|
849
|
+
const SYNONYMS = {
|
|
850
|
+
name: ["product", "item", "title", "label", "heading", "product name", "item name"],
|
|
851
|
+
price: ["cost", "amount", "msrp", "price", "rate", "value", "price_usd"],
|
|
852
|
+
brand: ["manufacturer", "vendor", "make", "company", "brand_name", "supplier"],
|
|
853
|
+
image: ["imageUrl", "thumbnail", "img", "url", "photo", "picture", "media"],
|
|
854
|
+
stock: ["inventory", "quantity", "count", "availability", "stock_level", "in stock", "status"]
|
|
855
|
+
};
|
|
797
856
|
return rows.map((row) => {
|
|
798
857
|
if (Array.isArray(row)) {
|
|
799
858
|
const keys = Array.isArray(columns) && columns.length > 0 ? columns : row.map((_, index) => `column_${index + 1}`);
|
|
@@ -803,7 +862,36 @@ function normalizeTabularRows(rows, columns) {
|
|
|
803
862
|
}, {});
|
|
804
863
|
}
|
|
805
864
|
if (row && typeof row === "object") {
|
|
806
|
-
|
|
865
|
+
const result = __spreadValues({}, row);
|
|
866
|
+
if (Array.isArray(columns)) {
|
|
867
|
+
columns.forEach((col) => {
|
|
868
|
+
if (result[col] !== void 0) return;
|
|
869
|
+
const rowKeys = Object.keys(row);
|
|
870
|
+
const colLower = col.toLowerCase().replace(/_/g, " ");
|
|
871
|
+
const foundKey = rowKeys.find((rk) => {
|
|
872
|
+
const rkLower = rk.toLowerCase().replace(/_/g, " ");
|
|
873
|
+
return rkLower === colLower || rkLower.includes(colLower) || colLower.includes(rkLower);
|
|
874
|
+
});
|
|
875
|
+
if (foundKey) {
|
|
876
|
+
result[col] = row[foundKey];
|
|
877
|
+
return;
|
|
878
|
+
}
|
|
879
|
+
for (const [target, aliases] of Object.entries(SYNONYMS)) {
|
|
880
|
+
const isMatch = target === colLower || aliases.some((a) => colLower.includes(a) || a.includes(colLower));
|
|
881
|
+
if (isMatch) {
|
|
882
|
+
const mappedKey = rowKeys.find((rk) => {
|
|
883
|
+
const rkL = rk.toLowerCase();
|
|
884
|
+
return rkL === target || aliases.some((a) => rkL.includes(a) || a.includes(rkL));
|
|
885
|
+
});
|
|
886
|
+
if (mappedKey) {
|
|
887
|
+
result[col] = row[mappedKey];
|
|
888
|
+
break;
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
});
|
|
893
|
+
}
|
|
894
|
+
return result;
|
|
807
895
|
}
|
|
808
896
|
return { value: row };
|
|
809
897
|
}).filter((row) => Object.keys(row).length > 0);
|
|
@@ -823,7 +911,7 @@ function resolveStructuredRows(config) {
|
|
|
823
911
|
}
|
|
824
912
|
function UIDispatcher({ rawContent, primaryColor, accentColor, isStreaming, onAddToCart, viewportSize = "large" }) {
|
|
825
913
|
var _a;
|
|
826
|
-
const result =
|
|
914
|
+
const result = import_react6.default.useMemo(() => {
|
|
827
915
|
if (isStreaming) return { loading: true };
|
|
828
916
|
try {
|
|
829
917
|
const clean = rawContent.replace(/^```[a-z]*\s*/i, "").replace(/```\s*$/, "").trim();
|
|
@@ -846,12 +934,15 @@ function UIDispatcher({ rawContent, primaryColor, accentColor, isStreaming, onAd
|
|
|
846
934
|
config2.view = "chart";
|
|
847
935
|
config2.chartType = config2.chartType || "bar";
|
|
848
936
|
}
|
|
849
|
-
if (!config2.view) {
|
|
850
|
-
|
|
937
|
+
if (!config2.view || ["pie", "bar", "line", "pie_chart", "bar_chart", "line_chart"].includes(String(config2.view))) {
|
|
938
|
+
const viewStr = String(config2.view || "").toLowerCase();
|
|
939
|
+
if (viewStr.includes("carousel") || config2.type === "products" || Array.isArray(config2.items) || hasProductLikeData) {
|
|
851
940
|
config2.view = "carousel";
|
|
852
|
-
} else if (hasAggregationLikeData || typeof config2.type === "string" && ["pie", "bar", "line"].includes(config2.type) || typeof config2.chartType === "string" && ["pie", "bar", "line"].includes(config2.chartType)) {
|
|
941
|
+
} else if (viewStr.includes("chart") || viewStr.includes("pie") || viewStr.includes("bar") || viewStr.includes("line") || hasAggregationLikeData || typeof config2.type === "string" && ["pie", "bar", "line"].includes(config2.type) || typeof config2.chartType === "string" && ["pie", "bar", "line"].includes(config2.chartType)) {
|
|
853
942
|
config2.view = "chart";
|
|
854
|
-
config2.chartType = config2.chartType || config2.type || "bar";
|
|
943
|
+
config2.chartType = config2.chartType || viewStr.replace("_chart", "") || config2.type || "bar";
|
|
944
|
+
} else if (viewStr.includes("table")) {
|
|
945
|
+
config2.view = "table";
|
|
855
946
|
} else {
|
|
856
947
|
config2.view = "table";
|
|
857
948
|
}
|
|
@@ -865,10 +956,10 @@ function UIDispatcher({ rawContent, primaryColor, accentColor, isStreaming, onAd
|
|
|
865
956
|
}
|
|
866
957
|
}, [rawContent, isStreaming]);
|
|
867
958
|
if ("loading" in result) {
|
|
868
|
-
return /* @__PURE__ */
|
|
959
|
+
return /* @__PURE__ */ import_react6.default.createElement("div", { className: "my-4 p-8 bg-slate-50 dark:bg-white/5 rounded-xl border border-dashed border-slate-300 dark:border-white/10 flex flex-col items-center justify-center gap-3 animate-pulse" }, /* @__PURE__ */ import_react6.default.createElement("div", { className: "w-5 h-5 border-2 border-indigo-500 border-t-transparent rounded-full animate-spin" }), /* @__PURE__ */ import_react6.default.createElement("p", { className: "text-xs text-slate-500 font-medium italic" }, "Preparing view..."));
|
|
869
960
|
}
|
|
870
961
|
if ("error" in result) {
|
|
871
|
-
return /* @__PURE__ */
|
|
962
|
+
return /* @__PURE__ */ import_react6.default.createElement("pre", { className: "p-4 my-2 bg-slate-900 text-slate-100 rounded-lg text-[10px] overflow-auto max-h-40" }, /* @__PURE__ */ import_react6.default.createElement("code", null, rawContent));
|
|
872
963
|
}
|
|
873
964
|
const { config } = result;
|
|
874
965
|
const isCompact = viewportSize === "compact";
|
|
@@ -876,7 +967,7 @@ function UIDispatcher({ rawContent, primaryColor, accentColor, isStreaming, onAd
|
|
|
876
967
|
const hasDescription = typeof config.description === "string" && config.description.trim().length > 0;
|
|
877
968
|
switch (config.view) {
|
|
878
969
|
case "chart":
|
|
879
|
-
return /* @__PURE__ */
|
|
970
|
+
return /* @__PURE__ */ import_react6.default.createElement("div", { className: `${isCompact ? "my-4 p-3" : "my-6 p-4"} bg-white dark:bg-slate-900 rounded-2xl border border-slate-200 dark:border-white/10 shadow-sm overflow-hidden` }, config.title && /* @__PURE__ */ import_react6.default.createElement("h4", { className: `${isCompact ? "text-[11px] mb-3" : "text-xs mb-4"} font-semibold text-slate-500 px-2` }, config.title), hasDescription && /* @__PURE__ */ import_react6.default.createElement("p", { className: `px-2 ${isCompact ? "text-xs" : "text-sm"} text-slate-500 dark:text-white/60` }, config.description), /* @__PURE__ */ import_react6.default.createElement(
|
|
880
971
|
DynamicChart,
|
|
881
972
|
{
|
|
882
973
|
config: {
|
|
@@ -890,23 +981,23 @@ function UIDispatcher({ rawContent, primaryColor, accentColor, isStreaming, onAd
|
|
|
890
981
|
accentColor,
|
|
891
982
|
viewportSize
|
|
892
983
|
}
|
|
893
|
-
), hasInsights && /* @__PURE__ */
|
|
984
|
+
), hasInsights && /* @__PURE__ */ import_react6.default.createElement("div", { className: "mt-4 flex flex-wrap gap-2 px-2" }, (_a = config.insights) == null ? void 0 : _a.map((insight, i) => /* @__PURE__ */ import_react6.default.createElement(
|
|
894
985
|
"span",
|
|
895
986
|
{
|
|
896
|
-
key: insight
|
|
987
|
+
key: `insight-${i}`,
|
|
897
988
|
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`
|
|
898
989
|
},
|
|
899
|
-
insight
|
|
990
|
+
String(insight)
|
|
900
991
|
))));
|
|
901
992
|
case "carousel":
|
|
902
|
-
return /* @__PURE__ */
|
|
993
|
+
return /* @__PURE__ */ import_react6.default.createElement("div", { className: "my-4" }, config.title && /* @__PURE__ */ import_react6.default.createElement("h4", { className: `${isCompact ? "mb-1.5 text-[11px]" : "mb-2 text-xs"} font-semibold text-slate-500` }, config.title), hasDescription && /* @__PURE__ */ import_react6.default.createElement("p", { className: `mb-3 ${isCompact ? "text-xs" : "text-sm"} text-slate-500 dark:text-white/60` }, config.description), /* @__PURE__ */ import_react6.default.createElement(ProductCarousel, { products: config.data.map((item) => {
|
|
903
994
|
var _a2;
|
|
904
995
|
return __spreadProps(__spreadValues({}, item), {
|
|
905
996
|
image: (_a2 = item.image) != null ? _a2 : typeof resolveImage === "function" ? resolveImage(item) : void 0
|
|
906
997
|
});
|
|
907
998
|
}), primaryColor, onAddToCart }));
|
|
908
999
|
case "table":
|
|
909
|
-
return /* @__PURE__ */
|
|
1000
|
+
return /* @__PURE__ */ import_react6.default.createElement("div", { className: `${isCompact ? "my-3 p-3 max-h-[320px]" : "my-4 p-4 max-h-[400px]"} bg-white dark:bg-slate-900 rounded-xl border border-slate-200 dark:border-white/10 shadow-sm overflow-auto` }, config.title && /* @__PURE__ */ import_react6.default.createElement("h4", { className: `${isCompact ? "text-[11px]" : "text-xs"} font-semibold text-slate-500 mb-2` }, config.title), hasDescription && /* @__PURE__ */ import_react6.default.createElement("p", { className: `mb-3 ${isCompact ? "text-xs" : "text-sm"} text-slate-500 dark:text-white/60` }, config.description), /* @__PURE__ */ import_react6.default.createElement(DataTable, { config: {
|
|
910
1001
|
type: "table",
|
|
911
1002
|
title: config.title,
|
|
912
1003
|
description: config.description,
|
|
@@ -931,44 +1022,59 @@ function MessageBubble({
|
|
|
931
1022
|
const isUser = message.role === "user";
|
|
932
1023
|
const isCompact = viewportSize === "compact";
|
|
933
1024
|
const isMedium = viewportSize === "medium";
|
|
934
|
-
const [showSources, setShowSources] =
|
|
935
|
-
const
|
|
936
|
-
() => /```(?:ui|json|chart)\s*[\s\S]*?"?(?:view|type|data|products)"?\s*:\s*"?(?:carousel|products|table)"?/i.test(message.content) || /\{[\s\S]*?"?(?:view|type|data|products)"?\s*:\s*"?(?:carousel|products)"?[\s\S]*\}/i.test(message.content) && looksLikeStructuredPayload(message.content),
|
|
937
|
-
[message.content]
|
|
938
|
-
);
|
|
939
|
-
const structuredContent = import_react5.default.useMemo(
|
|
1025
|
+
const [showSources, setShowSources] = import_react6.default.useState(false);
|
|
1026
|
+
const structuredContent = import_react6.default.useMemo(
|
|
940
1027
|
() => isUser ? { payload: null, text: message.content } : extractStructuredPayload(message.content),
|
|
941
1028
|
[isUser, message.content]
|
|
942
1029
|
);
|
|
943
|
-
const
|
|
944
|
-
|
|
1030
|
+
const hasRichUI = import_react6.default.useMemo(() => {
|
|
1031
|
+
if (message.uiTransformation) {
|
|
1032
|
+
const type = message.uiTransformation.type;
|
|
1033
|
+
if (type && !["text", "table"].includes(type)) return true;
|
|
1034
|
+
}
|
|
1035
|
+
if (structuredContent.payload) {
|
|
1036
|
+
return /"?(?:view|type|chartType)"?\s*:\s*"?(?:chart|carousel|pie|bar|line|product_carousel)"?/i.test(structuredContent.payload);
|
|
1037
|
+
}
|
|
1038
|
+
return false;
|
|
1039
|
+
}, [message.uiTransformation, structuredContent.payload]);
|
|
1040
|
+
const shouldRenderStructuredOnly = !isUser && hasRichUI && isLikelyUiOnlyMessage(structuredContent.text);
|
|
1041
|
+
const productsFromSources = import_react6.default.useMemo(() => {
|
|
945
1042
|
if (isUser || !sources) return [];
|
|
946
1043
|
return sources.filter((s) => {
|
|
947
1044
|
var _a;
|
|
948
1045
|
const m = (_a = s.metadata) != null ? _a : {};
|
|
949
|
-
|
|
1046
|
+
const keys = Object.keys(m).map((k) => k.toLowerCase());
|
|
1047
|
+
const hasProductKey = keys.some(
|
|
1048
|
+
(k) => ["price", "image", "img", "thumbnail", "images", "brand", "product", "sku", "category", "model", "cost"].includes(k)
|
|
1049
|
+
);
|
|
1050
|
+
const hasPricePattern = /\$\s*\d+/.test(s.content);
|
|
1051
|
+
return hasProductKey || hasPricePattern || m.type === "product";
|
|
950
1052
|
}).map((s) => {
|
|
951
|
-
var _a, _b
|
|
1053
|
+
var _a, _b;
|
|
952
1054
|
const m = (_a = s.metadata) != null ? _a : {};
|
|
1055
|
+
const name = getMetadataValue(m, ["name", "product", "title", "label", "item"]);
|
|
1056
|
+
const brand = getMetadataValue(m, ["brand", "manufacturer", "vendor", "make"]);
|
|
1057
|
+
const price = getMetadataValue(m, ["price", "cost", "amount", "msrp", "rate"]);
|
|
953
1058
|
return {
|
|
954
1059
|
id: s.id,
|
|
955
|
-
name: (
|
|
956
|
-
brand
|
|
957
|
-
price
|
|
1060
|
+
name: (_b = name != null ? name : s.content.split("\n")[0]) != null ? _b : "Unknown Product",
|
|
1061
|
+
brand,
|
|
1062
|
+
price,
|
|
958
1063
|
image: resolveImage(m),
|
|
959
|
-
link: m
|
|
1064
|
+
link: getMetadataValue(m, ["link", "url", "product_url"]),
|
|
960
1065
|
description: s.content
|
|
961
1066
|
};
|
|
962
1067
|
});
|
|
963
1068
|
}, [sources, isUser]);
|
|
964
|
-
const { productsFromContent, cleanContent } =
|
|
1069
|
+
const { productsFromContent, cleanContent } = import_react6.default.useMemo(() => {
|
|
1070
|
+
var _a, _b;
|
|
965
1071
|
if (isUser) {
|
|
966
1072
|
return { productsFromContent: [], cleanContent: message.content };
|
|
967
1073
|
}
|
|
968
1074
|
const jsonRegex = /```(?:json|ui)?\s*([\s\S]*?)\s*```/g;
|
|
969
1075
|
const products = [];
|
|
970
1076
|
let content = structuredContent.text;
|
|
971
|
-
const payloadCandidates = [structuredContent.payload, ...content.matchAll(jsonRegex).map((match) => match[1])].filter(Boolean);
|
|
1077
|
+
const payloadCandidates = [structuredContent.payload, ...Array.from(content.matchAll(jsonRegex)).map((match) => match[1])].filter(Boolean);
|
|
972
1078
|
for (const candidate of payloadCandidates) {
|
|
973
1079
|
try {
|
|
974
1080
|
const data = JSON.parse(sanitizeJson(candidate));
|
|
@@ -976,9 +1082,9 @@ function MessageBubble({
|
|
|
976
1082
|
if ((data.type === "products" || data.view === "carousel" || data.view === "table" || Array.isArray(data.products)) && itemSet) {
|
|
977
1083
|
products.push(
|
|
978
1084
|
...itemSet.map((item) => {
|
|
979
|
-
var
|
|
1085
|
+
var _a2;
|
|
980
1086
|
return __spreadProps(__spreadValues({}, item), {
|
|
981
|
-
image: (
|
|
1087
|
+
image: (_a2 = item.image) != null ? _a2 : resolveImage(item)
|
|
982
1088
|
});
|
|
983
1089
|
})
|
|
984
1090
|
);
|
|
@@ -987,15 +1093,15 @@ function MessageBubble({
|
|
|
987
1093
|
}
|
|
988
1094
|
}
|
|
989
1095
|
if (content.includes('"type": "products"') || content.includes('"type":"products"')) {
|
|
990
|
-
for (const match of content.matchAll(jsonRegex)) {
|
|
1096
|
+
for (const match of Array.from(content.matchAll(jsonRegex))) {
|
|
991
1097
|
try {
|
|
992
1098
|
const data = JSON.parse(sanitizeJson(match[1]));
|
|
993
1099
|
if (data.type === "products" && Array.isArray(data.items)) {
|
|
994
1100
|
products.push(
|
|
995
1101
|
...data.items.map((item) => {
|
|
996
|
-
var
|
|
1102
|
+
var _a2;
|
|
997
1103
|
return __spreadProps(__spreadValues({}, item), {
|
|
998
|
-
image: (
|
|
1104
|
+
image: (_a2 = item.image) != null ? _a2 : resolveImage(item)
|
|
999
1105
|
});
|
|
1000
1106
|
})
|
|
1001
1107
|
);
|
|
@@ -1005,9 +1111,42 @@ function MessageBubble({
|
|
|
1005
1111
|
}
|
|
1006
1112
|
}
|
|
1007
1113
|
}
|
|
1114
|
+
const bulletRegex = /(?:[•*-]\s*)?([^•\n\-\$*–—\(]+?)(?:\s*\(?Price\s*[:\-–—]?\s*)?(?:\s*[:\-–—]\s*|\s+)\$?([\d,.]+)(?:\s*USD)?/gi;
|
|
1115
|
+
const matches = Array.from(content.matchAll(bulletRegex));
|
|
1116
|
+
if (matches.length >= 2) {
|
|
1117
|
+
const normalize = (s) => s.toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
1118
|
+
for (const match of matches) {
|
|
1119
|
+
let name = ((_a = match[1]) == null ? void 0 : _a.trim()) || "";
|
|
1120
|
+
name = name.replace(/\s*\(?Price\s*$/i, "").replace(/[:\-–—]\s*$/g, "").trim();
|
|
1121
|
+
let price = ((_b = match[2]) == null ? void 0 : _b.trim()) || "";
|
|
1122
|
+
price = price.replace(/[,\s]+$/, "").trim();
|
|
1123
|
+
if (name && price) {
|
|
1124
|
+
const newProduct = {
|
|
1125
|
+
id: `text-prod-${name}-${price}`,
|
|
1126
|
+
name,
|
|
1127
|
+
price: `$${price}`
|
|
1128
|
+
};
|
|
1129
|
+
const normName = normalize(name);
|
|
1130
|
+
const sourceMatch = productsFromSources.find((s) => {
|
|
1131
|
+
const sn = normalize(s.name);
|
|
1132
|
+
return sn.includes(normName) || normName.includes(sn);
|
|
1133
|
+
});
|
|
1134
|
+
if (sourceMatch) {
|
|
1135
|
+
newProduct.image = sourceMatch.image;
|
|
1136
|
+
newProduct.brand = sourceMatch.brand;
|
|
1137
|
+
newProduct.link = sourceMatch.link;
|
|
1138
|
+
newProduct.description = sourceMatch.description;
|
|
1139
|
+
}
|
|
1140
|
+
products.push(newProduct);
|
|
1141
|
+
content = content.replace(match[0], `
|
|
1142
|
+
**${name}** \u2014 $${price}`);
|
|
1143
|
+
}
|
|
1144
|
+
}
|
|
1145
|
+
content = content.replace(/\n{3,}/g, "\n\n").trim();
|
|
1146
|
+
}
|
|
1008
1147
|
return { productsFromContent: products, cleanContent: content.trim() };
|
|
1009
|
-
}, [message.content, isUser, structuredContent]);
|
|
1010
|
-
const allProducts =
|
|
1148
|
+
}, [message.content, isUser, structuredContent, productsFromSources]);
|
|
1149
|
+
const allProducts = import_react6.default.useMemo(() => {
|
|
1011
1150
|
if (productsFromContent.length > 0) return productsFromContent;
|
|
1012
1151
|
const seen = /* @__PURE__ */ new Set();
|
|
1013
1152
|
const contentLower = message.content.toLowerCase();
|
|
@@ -1023,7 +1162,7 @@ function MessageBubble({
|
|
|
1023
1162
|
return false;
|
|
1024
1163
|
});
|
|
1025
1164
|
}, [productsFromSources, productsFromContent, message.content]);
|
|
1026
|
-
const processedMarkdown =
|
|
1165
|
+
const processedMarkdown = import_react6.default.useMemo(() => {
|
|
1027
1166
|
let raw = structuredContent.payload ? structuredContent.text : cleanContent || message.content;
|
|
1028
1167
|
const hasStructuredUiBlock = Boolean(structuredContent.payload) || /```(?:ui|json|chart)\s*[\s\S]*?"(?:view|chartType|type|data|items|rows|products|results)"\s*:/i.test(raw);
|
|
1029
1168
|
raw = raw.replace(/([^\n])\n\|/g, "$1\n\n|").replace(/(\|[^\n]*\|)\n\n+(?=\|)/g, "$1\n");
|
|
@@ -1057,16 +1196,16 @@ ${match.trim()}
|
|
|
1057
1196
|
}
|
|
1058
1197
|
return raw;
|
|
1059
1198
|
}, [cleanContent, message.content, isStreaming, structuredContent]);
|
|
1060
|
-
const markdownComponents =
|
|
1199
|
+
const markdownComponents = import_react6.default.useMemo(
|
|
1061
1200
|
() => ({
|
|
1062
1201
|
// Wrap in not-prose so Tailwind Typography resets don't clobber our styles.
|
|
1063
1202
|
// prose applies display:block and padding:0 to table/th/td — not-prose opts out.
|
|
1064
1203
|
table: (_a) => {
|
|
1065
1204
|
var props = __objRest(_a, []);
|
|
1066
1205
|
if (isStreaming) {
|
|
1067
|
-
return /* @__PURE__ */
|
|
1206
|
+
return /* @__PURE__ */ import_react6.default.createElement("div", { className: "my-5 p-6 bg-slate-50 dark:bg-white/5 rounded-xl border border-dashed border-slate-300 dark:border-white/10 flex items-center justify-center gap-3 select-none" }, /* @__PURE__ */ import_react6.default.createElement("div", { className: "w-4 h-4 border-2 border-indigo-500 border-t-transparent rounded-full animate-spin" }), /* @__PURE__ */ import_react6.default.createElement("p", { className: "text-xs text-slate-500 font-medium italic animate-pulse" }, "Generating data table..."));
|
|
1068
1207
|
}
|
|
1069
|
-
return /* @__PURE__ */
|
|
1208
|
+
return /* @__PURE__ */ import_react6.default.createElement("div", { className: "not-prose overflow-hidden my-5 rounded-xl border border-slate-200 dark:border-white/10 shadow-sm bg-white dark:bg-slate-900/50" }, /* @__PURE__ */ import_react6.default.createElement("div", { className: "overflow-x-auto" }, /* @__PURE__ */ import_react6.default.createElement(
|
|
1070
1209
|
"table",
|
|
1071
1210
|
__spreadValues({
|
|
1072
1211
|
className: "!table w-full text-left border-collapse min-w-[400px] text-sm"
|
|
@@ -1075,7 +1214,7 @@ ${match.trim()}
|
|
|
1075
1214
|
},
|
|
1076
1215
|
thead: (_b) => {
|
|
1077
1216
|
var props = __objRest(_b, []);
|
|
1078
|
-
return /* @__PURE__ */
|
|
1217
|
+
return /* @__PURE__ */ import_react6.default.createElement(
|
|
1079
1218
|
"thead",
|
|
1080
1219
|
__spreadValues({
|
|
1081
1220
|
className: "!table-header-group bg-slate-50 dark:bg-white/5 border-b border-slate-200 dark:border-white/10"
|
|
@@ -1084,11 +1223,11 @@ ${match.trim()}
|
|
|
1084
1223
|
},
|
|
1085
1224
|
tbody: (_c) => {
|
|
1086
1225
|
var props = __objRest(_c, []);
|
|
1087
|
-
return /* @__PURE__ */
|
|
1226
|
+
return /* @__PURE__ */ import_react6.default.createElement("tbody", __spreadValues({ className: "!table-row-group divide-y divide-slate-100 dark:divide-white/5" }, props));
|
|
1088
1227
|
},
|
|
1089
1228
|
tr: (_d) => {
|
|
1090
1229
|
var props = __objRest(_d, []);
|
|
1091
|
-
return /* @__PURE__ */
|
|
1230
|
+
return /* @__PURE__ */ import_react6.default.createElement(
|
|
1092
1231
|
"tr",
|
|
1093
1232
|
__spreadValues({
|
|
1094
1233
|
className: "!table-row hover:bg-slate-50/70 dark:hover:bg-white/5 transition-colors"
|
|
@@ -1097,7 +1236,7 @@ ${match.trim()}
|
|
|
1097
1236
|
},
|
|
1098
1237
|
th: (_e) => {
|
|
1099
1238
|
var _f = _e, { children } = _f, props = __objRest(_f, ["children"]);
|
|
1100
|
-
return /* @__PURE__ */
|
|
1239
|
+
return /* @__PURE__ */ import_react6.default.createElement(
|
|
1101
1240
|
"th",
|
|
1102
1241
|
__spreadValues({
|
|
1103
1242
|
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"
|
|
@@ -1107,7 +1246,7 @@ ${match.trim()}
|
|
|
1107
1246
|
},
|
|
1108
1247
|
td: (_g) => {
|
|
1109
1248
|
var _h = _g, { children } = _h, props = __objRest(_h, ["children"]);
|
|
1110
|
-
return /* @__PURE__ */
|
|
1249
|
+
return /* @__PURE__ */ import_react6.default.createElement(
|
|
1111
1250
|
"td",
|
|
1112
1251
|
__spreadValues({
|
|
1113
1252
|
className: "!table-cell px-4 py-3 text-slate-600 dark:text-white/70 whitespace-nowrap text-sm"
|
|
@@ -1128,7 +1267,7 @@ ${match.trim()}
|
|
|
1128
1267
|
var _a;
|
|
1129
1268
|
const lang = (_a = /language-(\w+)/.exec(className != null ? className : "")) == null ? void 0 : _a[1];
|
|
1130
1269
|
if (!inline && (lang === "ui" || lang === "chart")) {
|
|
1131
|
-
return /* @__PURE__ */
|
|
1270
|
+
return /* @__PURE__ */ import_react6.default.createElement(
|
|
1132
1271
|
UIDispatcher,
|
|
1133
1272
|
{
|
|
1134
1273
|
rawContent: String(children != null ? children : "").trim(),
|
|
@@ -1143,7 +1282,7 @@ ${match.trim()}
|
|
|
1143
1282
|
if (!inline && lang === "json") {
|
|
1144
1283
|
const content = String(children != null ? children : "").trim();
|
|
1145
1284
|
if (looksLikeStructuredPayload(content)) {
|
|
1146
|
-
return /* @__PURE__ */
|
|
1285
|
+
return /* @__PURE__ */ import_react6.default.createElement(
|
|
1147
1286
|
UIDispatcher,
|
|
1148
1287
|
{
|
|
1149
1288
|
rawContent: content,
|
|
@@ -1159,7 +1298,7 @@ ${match.trim()}
|
|
|
1159
1298
|
if (!inline) {
|
|
1160
1299
|
const content = String(children != null ? children : "").trim();
|
|
1161
1300
|
if (looksLikeStructuredPayload(content)) {
|
|
1162
|
-
return /* @__PURE__ */
|
|
1301
|
+
return /* @__PURE__ */ import_react6.default.createElement(
|
|
1163
1302
|
UIDispatcher,
|
|
1164
1303
|
{
|
|
1165
1304
|
rawContent: content,
|
|
@@ -1173,27 +1312,27 @@ ${match.trim()}
|
|
|
1173
1312
|
}
|
|
1174
1313
|
}
|
|
1175
1314
|
if (!inline && lang === "table-loading") {
|
|
1176
|
-
return /* @__PURE__ */
|
|
1315
|
+
return /* @__PURE__ */ import_react6.default.createElement("div", { className: "my-5 p-6 bg-slate-50 dark:bg-white/5 rounded-xl border border-dashed border-slate-300 dark:border-white/10 flex items-center justify-center gap-3 select-none" }, /* @__PURE__ */ import_react6.default.createElement("div", { className: "w-4 h-4 border-2 border-indigo-500 border-t-transparent rounded-full animate-spin" }), /* @__PURE__ */ import_react6.default.createElement("p", { className: "text-xs text-slate-500 font-medium italic animate-pulse" }, "Generating data table..."));
|
|
1177
1316
|
}
|
|
1178
|
-
return /* @__PURE__ */
|
|
1317
|
+
return /* @__PURE__ */ import_react6.default.createElement("code", __spreadValues({ className }, props), typeof children === "string" || typeof children === "number" ? children : JSON.stringify(children));
|
|
1179
1318
|
}
|
|
1180
1319
|
}),
|
|
1181
1320
|
[primaryColor, accentColor, isStreaming, onAddToCart, viewportSize]
|
|
1182
1321
|
);
|
|
1183
|
-
return /* @__PURE__ */
|
|
1322
|
+
return /* @__PURE__ */ import_react6.default.createElement("div", { className: `flex ${isCompact ? "gap-2" : "gap-3"} ${isUser ? "flex-row-reverse" : "flex-row"} items-start` }, /* @__PURE__ */ import_react6.default.createElement(
|
|
1184
1323
|
"div",
|
|
1185
1324
|
{
|
|
1186
1325
|
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"}`,
|
|
1187
1326
|
style: isUser ? { background: `linear-gradient(135deg, ${primaryColor}, ${accentColor})` } : {}
|
|
1188
1327
|
},
|
|
1189
|
-
isUser ? /* @__PURE__ */
|
|
1190
|
-
), /* @__PURE__ */
|
|
1328
|
+
isUser ? /* @__PURE__ */ import_react6.default.createElement(import_lucide_react4.User, { className: `${isCompact ? "w-3.5 h-3.5" : "w-4 h-4"} text-white` }) : /* @__PURE__ */ import_react6.default.createElement(import_lucide_react4.Bot, { className: `${isCompact ? "w-3.5 h-3.5" : "w-4 h-4"}` })
|
|
1329
|
+
), /* @__PURE__ */ import_react6.default.createElement("div", { className: `flex flex-col gap-1 ${isCompact ? "max-w-[94%]" : isMedium ? "max-w-[92%]" : "max-w-[90%]"} ${isUser ? "items-end" : "items-start"}` }, /* @__PURE__ */ import_react6.default.createElement(
|
|
1191
1330
|
"div",
|
|
1192
1331
|
{
|
|
1193
1332
|
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"}`,
|
|
1194
1333
|
style: isUser ? { background: `linear-gradient(135deg, ${primaryColor}, ${accentColor})` } : {}
|
|
1195
1334
|
},
|
|
1196
|
-
isStreaming && !message.content ? /* @__PURE__ */
|
|
1335
|
+
isStreaming && !message.content ? /* @__PURE__ */ import_react6.default.createElement("span", { className: "flex items-center gap-1 py-1" }, /* @__PURE__ */ import_react6.default.createElement("span", { className: "w-1.5 h-1.5 rounded-full bg-slate-400 dark:bg-white/60 animate-bounce [animation-delay:0ms]" }), /* @__PURE__ */ import_react6.default.createElement("span", { className: "w-1.5 h-1.5 rounded-full bg-slate-400 dark:bg-white/60 animate-bounce [animation-delay:150ms]" }), /* @__PURE__ */ import_react6.default.createElement("span", { className: "w-1.5 h-1.5 rounded-full bg-slate-400 dark:bg-white/60 animate-bounce [animation-delay:300ms]" })) : /* @__PURE__ */ import_react6.default.createElement("div", { className: `prose ${isCompact ? "prose-xs" : "prose-sm"} max-w-none break-words ${isUser ? "prose-invert" : "dark:prose-invert"}` }, !isUser && structuredContent.payload && /* @__PURE__ */ import_react6.default.createElement(
|
|
1197
1336
|
UIDispatcher,
|
|
1198
1337
|
{
|
|
1199
1338
|
rawContent: structuredContent.payload,
|
|
@@ -1203,30 +1342,46 @@ ${match.trim()}
|
|
|
1203
1342
|
onAddToCart,
|
|
1204
1343
|
viewportSize
|
|
1205
1344
|
}
|
|
1206
|
-
), !shouldRenderStructuredOnly && /* @__PURE__ */
|
|
1207
|
-
),
|
|
1345
|
+
), !shouldRenderStructuredOnly && /* @__PURE__ */ import_react6.default.createElement(import_react_markdown.default, { components: markdownComponents }, processedMarkdown), isStreaming && message.content && /* @__PURE__ */ import_react6.default.createElement("span", { className: "inline-block w-1.5 h-3.5 ml-1 bg-emerald-500 animate-pulse align-middle" }))
|
|
1346
|
+
), (() => {
|
|
1347
|
+
var _a, _b;
|
|
1348
|
+
if (isUser || structuredContent.payload || !message.uiTransformation) return null;
|
|
1349
|
+
const ui = message.uiTransformation;
|
|
1350
|
+
const textContent = (_b = (_a = ui.data) == null ? void 0 : _a.content) != null ? _b : "";
|
|
1351
|
+
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());
|
|
1352
|
+
if (!shouldShow) return null;
|
|
1353
|
+
return /* @__PURE__ */ import_react6.default.createElement("div", { className: "w-full mt-3" }, /* @__PURE__ */ import_react6.default.createElement(
|
|
1354
|
+
VisualizationRenderer,
|
|
1355
|
+
{
|
|
1356
|
+
data: ui,
|
|
1357
|
+
primaryColor,
|
|
1358
|
+
onAddToCart,
|
|
1359
|
+
className: "rounded-3xl border border-slate-200/60 dark:border-white/10 bg-white/90 dark:bg-slate-900/80 p-4"
|
|
1360
|
+
}
|
|
1361
|
+
));
|
|
1362
|
+
})(), !isUser && !hasRichUI && allProducts.length > 0 && /* @__PURE__ */ import_react6.default.createElement("div", { className: "w-full mt-1" }, /* @__PURE__ */ import_react6.default.createElement(
|
|
1208
1363
|
ProductCarousel,
|
|
1209
1364
|
{
|
|
1210
1365
|
products: allProducts,
|
|
1211
1366
|
primaryColor,
|
|
1212
1367
|
onAddToCart
|
|
1213
1368
|
}
|
|
1214
|
-
)), !isUser && sources && sources.length > 0 && /* @__PURE__ */
|
|
1369
|
+
)), !isUser && sources && sources.length > 0 && /* @__PURE__ */ import_react6.default.createElement("div", { className: "w-full" }, /* @__PURE__ */ import_react6.default.createElement(
|
|
1215
1370
|
"button",
|
|
1216
1371
|
{
|
|
1217
1372
|
onClick: () => setShowSources((s) => !s),
|
|
1218
1373
|
className: "text-[11px] text-indigo-400 hover:text-indigo-300 transition-colors flex items-center gap-1 mt-1"
|
|
1219
1374
|
},
|
|
1220
|
-
showSources ? /* @__PURE__ */
|
|
1375
|
+
showSources ? /* @__PURE__ */ import_react6.default.createElement(import_lucide_react4.ChevronDown, { className: "w-3 h-3" }) : /* @__PURE__ */ import_react6.default.createElement(import_lucide_react4.ChevronRight, { className: "w-3 h-3" }),
|
|
1221
1376
|
sources.length,
|
|
1222
1377
|
" source",
|
|
1223
1378
|
sources.length !== 1 ? "s" : "",
|
|
1224
1379
|
" used"
|
|
1225
|
-
), showSources && /* @__PURE__ */
|
|
1380
|
+
), showSources && /* @__PURE__ */ import_react6.default.createElement("div", { className: "mt-2 flex flex-col gap-2" }, sources.map((src, i) => /* @__PURE__ */ import_react6.default.createElement(SourceCard, { key: src.id, source: src, index: i }))))));
|
|
1226
1381
|
}
|
|
1227
1382
|
|
|
1228
1383
|
// src/components/ConfigProvider.tsx
|
|
1229
|
-
var
|
|
1384
|
+
var import_react7 = __toESM(require("react"));
|
|
1230
1385
|
|
|
1231
1386
|
// src/utils/templateUtils.ts
|
|
1232
1387
|
function mergeDefined(base, override) {
|
|
@@ -1278,7 +1433,7 @@ var CHAT_SUGGESTIONS = [
|
|
|
1278
1433
|
];
|
|
1279
1434
|
|
|
1280
1435
|
// src/components/ConfigProvider.tsx
|
|
1281
|
-
var ConfigContext = (0,
|
|
1436
|
+
var ConfigContext = (0, import_react7.createContext)(DEFAULT_CONFIG);
|
|
1282
1437
|
function ConfigProvider({
|
|
1283
1438
|
config,
|
|
1284
1439
|
children
|
|
@@ -1287,14 +1442,14 @@ function ConfigProvider({
|
|
|
1287
1442
|
projectId: (config == null ? void 0 : config.projectId) || DEFAULT_CONFIG.projectId,
|
|
1288
1443
|
ui: mergeDefined(DEFAULT_CONFIG.ui, config == null ? void 0 : config.ui)
|
|
1289
1444
|
};
|
|
1290
|
-
return /* @__PURE__ */
|
|
1445
|
+
return /* @__PURE__ */ import_react7.default.createElement(ConfigContext.Provider, { value: merged }, children);
|
|
1291
1446
|
}
|
|
1292
1447
|
function useConfig() {
|
|
1293
|
-
return (0,
|
|
1448
|
+
return (0, import_react7.useContext)(ConfigContext);
|
|
1294
1449
|
}
|
|
1295
1450
|
|
|
1296
1451
|
// src/hooks/useRagChat.ts
|
|
1297
|
-
var
|
|
1452
|
+
var import_react8 = require("react");
|
|
1298
1453
|
|
|
1299
1454
|
// src/hooks/useStoredMessages.ts
|
|
1300
1455
|
var React8 = __toESM(require("react"));
|
|
@@ -1355,14 +1510,14 @@ function useRagChat(projectId, options = {}) {
|
|
|
1355
1510
|
} = options;
|
|
1356
1511
|
const storageKey = `rag_chat_${projectId}`;
|
|
1357
1512
|
const [messages, setMessages] = useStoredMessages(storageKey, persist);
|
|
1358
|
-
const [isLoading, setIsLoading] = (0,
|
|
1359
|
-
const [error, setError] = (0,
|
|
1360
|
-
const lastInputRef = (0,
|
|
1361
|
-
const messagesRef = (0,
|
|
1362
|
-
(0,
|
|
1513
|
+
const [isLoading, setIsLoading] = (0, import_react8.useState)(false);
|
|
1514
|
+
const [error, setError] = (0, import_react8.useState)(null);
|
|
1515
|
+
const lastInputRef = (0, import_react8.useRef)("");
|
|
1516
|
+
const messagesRef = (0, import_react8.useRef)(messages);
|
|
1517
|
+
(0, import_react8.useEffect)(() => {
|
|
1363
1518
|
messagesRef.current = messages;
|
|
1364
1519
|
}, [messages]);
|
|
1365
|
-
const sendMessage = (0,
|
|
1520
|
+
const sendMessage = (0, import_react8.useCallback)(
|
|
1366
1521
|
async (text, opts) => {
|
|
1367
1522
|
var _a, _b;
|
|
1368
1523
|
const trimmed = text.trim();
|
|
@@ -1422,7 +1577,7 @@ function useRagChat(projectId, options = {}) {
|
|
|
1422
1577
|
const complete = buffer.slice(0, lastBoundary + 2);
|
|
1423
1578
|
buffer = buffer.slice(lastBoundary + 2);
|
|
1424
1579
|
for (const frame of parseSseChunk(complete)) {
|
|
1425
|
-
if (frame.type === "text") {
|
|
1580
|
+
if (frame.type === "text" && frame.text) {
|
|
1426
1581
|
assistantContent += frame.text;
|
|
1427
1582
|
} else if (frame.type === "metadata") {
|
|
1428
1583
|
sources = (_a = frame.sources) != null ? _a : [];
|
|
@@ -1444,7 +1599,7 @@ function useRagChat(projectId, options = {}) {
|
|
|
1444
1599
|
}
|
|
1445
1600
|
if (buffer.trim()) {
|
|
1446
1601
|
for (const frame of parseSseChunk(buffer)) {
|
|
1447
|
-
if (frame.type === "text") assistantContent += frame.text;
|
|
1602
|
+
if (frame.type === "text" && frame.text) assistantContent += frame.text;
|
|
1448
1603
|
else if (frame.type === "metadata") sources = (_b = frame.sources) != null ? _b : [];
|
|
1449
1604
|
}
|
|
1450
1605
|
}
|
|
@@ -1467,12 +1622,12 @@ function useRagChat(projectId, options = {}) {
|
|
|
1467
1622
|
},
|
|
1468
1623
|
[apiUrl, isLoading, namespace, onError, onReply, projectId, setMessages]
|
|
1469
1624
|
);
|
|
1470
|
-
const clear = (0,
|
|
1625
|
+
const clear = (0, import_react8.useCallback)(() => {
|
|
1471
1626
|
setMessages([]);
|
|
1472
1627
|
setError(null);
|
|
1473
1628
|
if (persist) localStorage.removeItem(storageKey);
|
|
1474
1629
|
}, [persist, setMessages, storageKey]);
|
|
1475
|
-
const retry = (0,
|
|
1630
|
+
const retry = (0, import_react8.useCallback)(async () => {
|
|
1476
1631
|
if (lastInputRef.current) {
|
|
1477
1632
|
const latestMessage = messagesRef.current[messagesRef.current.length - 1];
|
|
1478
1633
|
await sendMessage(lastInputRef.current, {
|
|
@@ -1506,20 +1661,20 @@ function ChatWindow({
|
|
|
1506
1661
|
}) {
|
|
1507
1662
|
var _a;
|
|
1508
1663
|
const { ui, projectId } = useConfig();
|
|
1509
|
-
const [input, setInput] = (0,
|
|
1510
|
-
const [mounted, setMounted] = (0,
|
|
1511
|
-
const [viewportSize, setViewportSize] = (0,
|
|
1512
|
-
const windowRef = (0,
|
|
1513
|
-
const bottomRef = (0,
|
|
1514
|
-
const inputRef = (0,
|
|
1664
|
+
const [input, setInput] = (0, import_react9.useState)("");
|
|
1665
|
+
const [mounted, setMounted] = (0, import_react9.useState)(false);
|
|
1666
|
+
const [viewportSize, setViewportSize] = (0, import_react9.useState)("large");
|
|
1667
|
+
const windowRef = (0, import_react9.useRef)(null);
|
|
1668
|
+
const bottomRef = (0, import_react9.useRef)(null);
|
|
1669
|
+
const inputRef = (0, import_react9.useRef)(null);
|
|
1515
1670
|
const { messages, send, clear, isLoading, error } = useRagChat(projectId, {
|
|
1516
1671
|
namespace: projectId
|
|
1517
1672
|
});
|
|
1518
|
-
const [suggestions, setSuggestions] = (0,
|
|
1519
|
-
const [isSuggesting, setIsSuggesting] = (0,
|
|
1520
|
-
const [isListening, setIsListening] = (0,
|
|
1521
|
-
const recognitionRef = (0,
|
|
1522
|
-
(0,
|
|
1673
|
+
const [suggestions, setSuggestions] = (0, import_react9.useState)([]);
|
|
1674
|
+
const [isSuggesting, setIsSuggesting] = (0, import_react9.useState)(false);
|
|
1675
|
+
const [isListening, setIsListening] = (0, import_react9.useState)(false);
|
|
1676
|
+
const recognitionRef = (0, import_react9.useRef)(null);
|
|
1677
|
+
(0, import_react9.useEffect)(() => {
|
|
1523
1678
|
if (typeof window !== "undefined") {
|
|
1524
1679
|
const win = window;
|
|
1525
1680
|
const SpeechRecognition = win.SpeechRecognition || win.webkitSpeechRecognition;
|
|
@@ -1565,10 +1720,10 @@ function ChatWindow({
|
|
|
1565
1720
|
}
|
|
1566
1721
|
}
|
|
1567
1722
|
};
|
|
1568
|
-
(0,
|
|
1723
|
+
(0, import_react9.useEffect)(() => {
|
|
1569
1724
|
setMounted(true);
|
|
1570
1725
|
}, []);
|
|
1571
|
-
(0,
|
|
1726
|
+
(0, import_react9.useEffect)(() => {
|
|
1572
1727
|
const element = windowRef.current;
|
|
1573
1728
|
if (!element || typeof ResizeObserver === "undefined") return;
|
|
1574
1729
|
const resolveViewportSize = (width) => {
|
|
@@ -1584,13 +1739,13 @@ function ChatWindow({
|
|
|
1584
1739
|
observer.observe(element);
|
|
1585
1740
|
return () => observer.disconnect();
|
|
1586
1741
|
}, []);
|
|
1587
|
-
(0,
|
|
1742
|
+
(0, import_react9.useEffect)(() => {
|
|
1588
1743
|
var _a2;
|
|
1589
1744
|
if (messages.length > 0 || isLoading) {
|
|
1590
1745
|
(_a2 = bottomRef.current) == null ? void 0 : _a2.scrollIntoView({ behavior: "smooth" });
|
|
1591
1746
|
}
|
|
1592
1747
|
}, [messages, isLoading]);
|
|
1593
|
-
const sendMessage = (0,
|
|
1748
|
+
const sendMessage = (0, import_react9.useCallback)(async () => {
|
|
1594
1749
|
var _a2;
|
|
1595
1750
|
const text = input.trim();
|
|
1596
1751
|
if (!text || isLoading) return;
|
|
@@ -1620,7 +1775,7 @@ function ChatWindow({
|
|
|
1620
1775
|
const isEmpty = messages.length === 0;
|
|
1621
1776
|
const currentRadius = BORDER_RADIUS_MAP[ui.borderRadius || "xl"];
|
|
1622
1777
|
const isGlass = ui.visualStyle !== "solid";
|
|
1623
|
-
(0,
|
|
1778
|
+
(0, import_react9.useEffect)(() => {
|
|
1624
1779
|
if (input.trim().length < 3) {
|
|
1625
1780
|
return;
|
|
1626
1781
|
}
|
|
@@ -1644,84 +1799,84 @@ function ChatWindow({
|
|
|
1644
1799
|
}, 800);
|
|
1645
1800
|
return () => clearTimeout(timer);
|
|
1646
1801
|
}, [input, projectId]);
|
|
1647
|
-
return /* @__PURE__ */
|
|
1802
|
+
return /* @__PURE__ */ import_react9.default.createElement(
|
|
1648
1803
|
"div",
|
|
1649
1804
|
{
|
|
1650
1805
|
ref: windowRef,
|
|
1651
1806
|
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}`,
|
|
1652
1807
|
style: __spreadValues({ "--primary": ui.primaryColor, "--accent": ui.accentColor }, style)
|
|
1653
1808
|
},
|
|
1654
|
-
onResizeStart && /* @__PURE__ */
|
|
1809
|
+
onResizeStart && /* @__PURE__ */ import_react9.default.createElement(
|
|
1655
1810
|
"div",
|
|
1656
1811
|
{
|
|
1657
1812
|
onMouseDown: onResizeStart,
|
|
1658
1813
|
className: "absolute top-0 left-0 w-6 h-6 cursor-nw-resize z-[100] group flex items-start justify-start p-1",
|
|
1659
1814
|
title: "Drag to resize"
|
|
1660
1815
|
},
|
|
1661
|
-
/* @__PURE__ */
|
|
1816
|
+
/* @__PURE__ */ import_react9.default.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]" })
|
|
1662
1817
|
),
|
|
1663
|
-
/* @__PURE__ */
|
|
1818
|
+
/* @__PURE__ */ import_react9.default.createElement(
|
|
1664
1819
|
"div",
|
|
1665
1820
|
{
|
|
1666
1821
|
className: "flex items-center justify-between px-5 py-4 border-b border-slate-200 dark:border-white/10",
|
|
1667
1822
|
style: { background: `linear-gradient(135deg, ${ui.primaryColor}15, ${ui.accentColor}10)` }
|
|
1668
1823
|
},
|
|
1669
|
-
/* @__PURE__ */
|
|
1824
|
+
/* @__PURE__ */ import_react9.default.createElement("div", { className: "flex items-center gap-3" }, ui.logoUrl ? (
|
|
1670
1825
|
// eslint-disable-next-line @next/next/no-img-element
|
|
1671
|
-
/* @__PURE__ */
|
|
1672
|
-
) : /* @__PURE__ */
|
|
1826
|
+
/* @__PURE__ */ import_react9.default.createElement("img", { src: ui.logoUrl, alt: "logo", className: "w-8 h-8 rounded-lg object-cover" })
|
|
1827
|
+
) : /* @__PURE__ */ import_react9.default.createElement(
|
|
1673
1828
|
"div",
|
|
1674
1829
|
{
|
|
1675
1830
|
className: `w-9 h-9 flex items-center justify-center shadow-md ${ui.borderRadius === "full" ? "rounded-full" : "rounded-xl"}`,
|
|
1676
1831
|
style: { background: `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` }
|
|
1677
1832
|
},
|
|
1678
|
-
/* @__PURE__ */
|
|
1679
|
-
), /* @__PURE__ */
|
|
1680
|
-
/* @__PURE__ */
|
|
1833
|
+
/* @__PURE__ */ import_react9.default.createElement(import_lucide_react5.Bot, { className: "w-5 h-5 text-white" })
|
|
1834
|
+
), /* @__PURE__ */ import_react9.default.createElement("div", null, /* @__PURE__ */ import_react9.default.createElement("h2", { className: "text-slate-900 dark:text-white font-semibold text-sm leading-tight" }, ui.title), ui.poweredBy && /* @__PURE__ */ import_react9.default.createElement("p", { className: "text-slate-500 dark:text-white/40 text-[11px] leading-tight" }, `Powered by ${ui.poweredBy}`))),
|
|
1835
|
+
/* @__PURE__ */ import_react9.default.createElement("div", { className: "flex items-center gap-1.5" }, /* @__PURE__ */ import_react9.default.createElement("span", { className: "flex items-center gap-1 text-[10px] text-emerald-500 dark:text-emerald-400 mr-2" }, /* @__PURE__ */ import_react9.default.createElement("span", { className: "w-1.5 h-1.5 rounded-full bg-emerald-500 dark:bg-emerald-400 animate-pulse" }), "Online"), /* @__PURE__ */ import_react9.default.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__ */ import_react9.default.createElement(
|
|
1681
1836
|
"button",
|
|
1682
1837
|
{
|
|
1683
1838
|
onClick: clearHistory,
|
|
1684
1839
|
title: "Clear conversation",
|
|
1685
1840
|
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"
|
|
1686
1841
|
},
|
|
1687
|
-
/* @__PURE__ */
|
|
1688
|
-
), isResized && onResetResize && /* @__PURE__ */
|
|
1842
|
+
/* @__PURE__ */ import_react9.default.createElement(import_lucide_react5.Trash2, { className: "w-3.5 h-3.5" })
|
|
1843
|
+
), isResized && onResetResize && /* @__PURE__ */ import_react9.default.createElement(
|
|
1689
1844
|
"button",
|
|
1690
1845
|
{
|
|
1691
1846
|
onClick: onResetResize,
|
|
1692
1847
|
title: "Reset to default size",
|
|
1693
1848
|
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"
|
|
1694
1849
|
},
|
|
1695
|
-
/* @__PURE__ */
|
|
1696
|
-
), onMaximize && /* @__PURE__ */
|
|
1850
|
+
/* @__PURE__ */ import_react9.default.createElement(import_lucide_react5.RotateCcw, { className: "w-3.5 h-3.5" })
|
|
1851
|
+
), onMaximize && /* @__PURE__ */ import_react9.default.createElement(
|
|
1697
1852
|
"button",
|
|
1698
1853
|
{
|
|
1699
1854
|
onClick: onMaximize,
|
|
1700
1855
|
title: isMaximized ? "Minimize" : "Maximize",
|
|
1701
1856
|
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"
|
|
1702
1857
|
},
|
|
1703
|
-
isMaximized ? /* @__PURE__ */
|
|
1704
|
-
), showClose && onClose && /* @__PURE__ */
|
|
1858
|
+
isMaximized ? /* @__PURE__ */ import_react9.default.createElement(import_lucide_react5.Minimize2, { className: "w-3.5 h-3.5" }) : /* @__PURE__ */ import_react9.default.createElement(import_lucide_react5.Maximize2, { className: "w-3.5 h-3.5" })
|
|
1859
|
+
), showClose && onClose && /* @__PURE__ */ import_react9.default.createElement(
|
|
1705
1860
|
"button",
|
|
1706
1861
|
{
|
|
1707
1862
|
onClick: onClose,
|
|
1708
1863
|
title: "Close chat",
|
|
1709
1864
|
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"
|
|
1710
1865
|
},
|
|
1711
|
-
/* @__PURE__ */
|
|
1866
|
+
/* @__PURE__ */ import_react9.default.createElement(import_lucide_react5.X, { className: "w-4 h-4" })
|
|
1712
1867
|
)))
|
|
1713
1868
|
),
|
|
1714
|
-
/* @__PURE__ */
|
|
1869
|
+
/* @__PURE__ */ import_react9.default.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 ? (
|
|
1715
1870
|
/* Welcome state */
|
|
1716
|
-
/* @__PURE__ */
|
|
1871
|
+
/* @__PURE__ */ import_react9.default.createElement("div", { className: "h-full flex flex-col items-center justify-center text-center gap-4 px-6 py-12" }, /* @__PURE__ */ import_react9.default.createElement(
|
|
1717
1872
|
"div",
|
|
1718
1873
|
{
|
|
1719
1874
|
className: `w-16 h-16 flex items-center justify-center shadow-lg ${ui.borderRadius === "full" ? "rounded-full" : "rounded-2xl"}`,
|
|
1720
1875
|
style: { background: `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` }
|
|
1721
1876
|
},
|
|
1722
|
-
/* @__PURE__ */
|
|
1723
|
-
), /* @__PURE__ */
|
|
1724
|
-
(suggestion) => /* @__PURE__ */
|
|
1877
|
+
/* @__PURE__ */ import_react9.default.createElement(import_lucide_react5.Sparkles, { className: "w-8 h-8 text-white" })
|
|
1878
|
+
), /* @__PURE__ */ import_react9.default.createElement("div", null, /* @__PURE__ */ import_react9.default.createElement("p", { className: "text-slate-800 dark:text-white/80 font-medium leading-relaxed" }, ui.welcomeMessage), /* @__PURE__ */ import_react9.default.createElement("p", { className: "text-slate-500 dark:text-white/30 text-sm mt-2" }, "Ask a question to get started")), /* @__PURE__ */ import_react9.default.createElement("div", { className: "flex flex-wrap gap-2 justify-center mt-2" }, CHAT_SUGGESTIONS.map(
|
|
1879
|
+
(suggestion) => /* @__PURE__ */ import_react9.default.createElement(
|
|
1725
1880
|
"button",
|
|
1726
1881
|
{
|
|
1727
1882
|
key: suggestion,
|
|
@@ -1735,7 +1890,7 @@ function ChatWindow({
|
|
|
1735
1890
|
suggestion
|
|
1736
1891
|
)
|
|
1737
1892
|
)))
|
|
1738
|
-
) : messages.map((msg, index) => /* @__PURE__ */
|
|
1893
|
+
) : messages.map((msg, index) => /* @__PURE__ */ import_react9.default.createElement(
|
|
1739
1894
|
MessageBubble,
|
|
1740
1895
|
{
|
|
1741
1896
|
key: msg.id,
|
|
@@ -1747,7 +1902,7 @@ function ChatWindow({
|
|
|
1747
1902
|
onAddToCart,
|
|
1748
1903
|
viewportSize
|
|
1749
1904
|
}
|
|
1750
|
-
)), isLoading && ((_a = messages[messages.length - 1]) == null ? void 0 : _a.role) !== "assistant" && /* @__PURE__ */
|
|
1905
|
+
)), isLoading && ((_a = messages[messages.length - 1]) == null ? void 0 : _a.role) !== "assistant" && /* @__PURE__ */ import_react9.default.createElement(
|
|
1751
1906
|
MessageBubble,
|
|
1752
1907
|
{
|
|
1753
1908
|
message: { id: "loading", role: "assistant", content: "", createdAt: (/* @__PURE__ */ new Date()).toISOString() },
|
|
@@ -1757,8 +1912,8 @@ function ChatWindow({
|
|
|
1757
1912
|
onAddToCart,
|
|
1758
1913
|
viewportSize
|
|
1759
1914
|
}
|
|
1760
|
-
), error && /* @__PURE__ */
|
|
1761
|
-
/* @__PURE__ */
|
|
1915
|
+
), error && /* @__PURE__ */ import_react9.default.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__ */ import_react9.default.createElement(import_lucide_react5.TriangleAlert, { className: "w-4 h-4 flex-shrink-0" }), /* @__PURE__ */ import_react9.default.createElement("span", null, error)), /* @__PURE__ */ import_react9.default.createElement("div", { ref: bottomRef })),
|
|
1916
|
+
/* @__PURE__ */ import_react9.default.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__ */ import_react9.default.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__ */ import_react9.default.createElement(
|
|
1762
1917
|
"button",
|
|
1763
1918
|
{
|
|
1764
1919
|
key: suggestion,
|
|
@@ -1770,9 +1925,9 @@ function ChatWindow({
|
|
|
1770
1925
|
},
|
|
1771
1926
|
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"
|
|
1772
1927
|
},
|
|
1773
|
-
/* @__PURE__ */
|
|
1928
|
+
/* @__PURE__ */ import_react9.default.createElement(import_lucide_react5.Sparkles, { className: "w-3 h-3 text-amber-400" }),
|
|
1774
1929
|
suggestion
|
|
1775
|
-
)), isSuggesting && suggestions.length === 0 && /* @__PURE__ */
|
|
1930
|
+
)), isSuggesting && suggestions.length === 0 && /* @__PURE__ */ import_react9.default.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__ */ import_react9.default.createElement(import_lucide_react5.Sparkles, { className: "w-3 h-3" }), "Thinking...")), /* @__PURE__ */ import_react9.default.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__ */ import_react9.default.createElement(
|
|
1776
1931
|
"textarea",
|
|
1777
1932
|
{
|
|
1778
1933
|
ref: inputRef,
|
|
@@ -1791,7 +1946,7 @@ function ChatWindow({
|
|
|
1791
1946
|
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",
|
|
1792
1947
|
style: { scrollbarWidth: "none" }
|
|
1793
1948
|
}
|
|
1794
|
-
), ui.enableVoiceInput !== false && /* @__PURE__ */
|
|
1949
|
+
), ui.enableVoiceInput !== false && /* @__PURE__ */ import_react9.default.createElement(
|
|
1795
1950
|
"button",
|
|
1796
1951
|
{
|
|
1797
1952
|
type: "button",
|
|
@@ -1800,8 +1955,8 @@ function ChatWindow({
|
|
|
1800
1955
|
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"}`,
|
|
1801
1956
|
title: isListening ? "Stop listening" : "Start voice input"
|
|
1802
1957
|
},
|
|
1803
|
-
isListening ? /* @__PURE__ */
|
|
1804
|
-
), /* @__PURE__ */
|
|
1958
|
+
isListening ? /* @__PURE__ */ import_react9.default.createElement(import_lucide_react5.MicOff, { className: "w-4 h-4" }) : /* @__PURE__ */ import_react9.default.createElement(import_lucide_react5.Mic, { className: "w-4 h-4" })
|
|
1959
|
+
), /* @__PURE__ */ import_react9.default.createElement(
|
|
1805
1960
|
"button",
|
|
1806
1961
|
{
|
|
1807
1962
|
onClick: sendMessage,
|
|
@@ -1812,8 +1967,8 @@ function ChatWindow({
|
|
|
1812
1967
|
// slate-400/20 for light mode disabled
|
|
1813
1968
|
}
|
|
1814
1969
|
},
|
|
1815
|
-
/* @__PURE__ */
|
|
1816
|
-
)), /* @__PURE__ */
|
|
1970
|
+
/* @__PURE__ */ import_react9.default.createElement(import_lucide_react5.ArrowUp, { className: "w-4 h-4 text-white" })
|
|
1971
|
+
)), /* @__PURE__ */ import_react9.default.createElement("p", { className: "text-center text-[10px] text-slate-400 dark:text-white/20 mt-2" }, "Press Enter to send \xB7 Shift+Enter for new line"))
|
|
1817
1972
|
);
|
|
1818
1973
|
}
|
|
1819
1974
|
|
|
@@ -1821,12 +1976,12 @@ function ChatWindow({
|
|
|
1821
1976
|
var DEFAULT_DIMENSIONS = { width: 380, height: 600 };
|
|
1822
1977
|
function ChatWidget({ position = "bottom-right", onAddToCart }) {
|
|
1823
1978
|
const { ui } = useConfig();
|
|
1824
|
-
const [isOpen, setIsOpen] = (0,
|
|
1825
|
-
const [hasUnread, setHasUnread] = (0,
|
|
1826
|
-
const [dimensions, setDimensions] = (0,
|
|
1827
|
-
const [isResizing, setIsResizing] = (0,
|
|
1828
|
-
const [isMaximized, setIsMaximized] = (0,
|
|
1829
|
-
const [prevDimensions, setPrevDimensions] = (0,
|
|
1979
|
+
const [isOpen, setIsOpen] = (0, import_react10.useState)(false);
|
|
1980
|
+
const [hasUnread, setHasUnread] = (0, import_react10.useState)(false);
|
|
1981
|
+
const [dimensions, setDimensions] = (0, import_react10.useState)(DEFAULT_DIMENSIONS);
|
|
1982
|
+
const [isResizing, setIsResizing] = (0, import_react10.useState)(false);
|
|
1983
|
+
const [isMaximized, setIsMaximized] = (0, import_react10.useState)(false);
|
|
1984
|
+
const [prevDimensions, setPrevDimensions] = (0, import_react10.useState)(DEFAULT_DIMENSIONS);
|
|
1830
1985
|
if (ui.showWidget === false) return null;
|
|
1831
1986
|
const positionClass = position === "bottom-left" ? "bottom-6 left-6" : "bottom-6 right-6";
|
|
1832
1987
|
const windowPositionClass = position === "bottom-left" ? "bottom-20 left-6" : "bottom-20 right-6";
|
|
@@ -1876,7 +2031,7 @@ function ChatWidget({ position = "bottom-right", onAddToCart }) {
|
|
|
1876
2031
|
}
|
|
1877
2032
|
};
|
|
1878
2033
|
const isResized = dimensions.width !== DEFAULT_DIMENSIONS.width || dimensions.height !== DEFAULT_DIMENSIONS.height;
|
|
1879
|
-
return /* @__PURE__ */
|
|
2034
|
+
return /* @__PURE__ */ import_react10.default.createElement(import_react10.default.Fragment, null, /* @__PURE__ */ import_react10.default.createElement(
|
|
1880
2035
|
"div",
|
|
1881
2036
|
{
|
|
1882
2037
|
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"}`,
|
|
@@ -1886,7 +2041,7 @@ function ChatWidget({ position = "bottom-right", onAddToCart }) {
|
|
|
1886
2041
|
maxHeight: "calc(100vh - 6rem)"
|
|
1887
2042
|
}
|
|
1888
2043
|
},
|
|
1889
|
-
/* @__PURE__ */
|
|
2044
|
+
/* @__PURE__ */ import_react10.default.createElement(
|
|
1890
2045
|
ChatWindow,
|
|
1891
2046
|
{
|
|
1892
2047
|
className: "h-full relative z-10",
|
|
@@ -1900,13 +2055,13 @@ function ChatWidget({ position = "bottom-right", onAddToCart }) {
|
|
|
1900
2055
|
onAddToCart
|
|
1901
2056
|
}
|
|
1902
2057
|
),
|
|
1903
|
-
/* @__PURE__ */
|
|
2058
|
+
/* @__PURE__ */ import_react10.default.createElement(
|
|
1904
2059
|
"div",
|
|
1905
2060
|
{
|
|
1906
2061
|
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"}`
|
|
1907
2062
|
}
|
|
1908
2063
|
)
|
|
1909
|
-
), /* @__PURE__ */
|
|
2064
|
+
), /* @__PURE__ */ import_react10.default.createElement(
|
|
1910
2065
|
"button",
|
|
1911
2066
|
{
|
|
1912
2067
|
onClick: isOpen ? () => setIsOpen(false) : handleOpen,
|
|
@@ -1914,32 +2069,32 @@ function ChatWidget({ position = "bottom-right", onAddToCart }) {
|
|
|
1914
2069
|
style: { background: `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` },
|
|
1915
2070
|
"aria-label": "Open chat"
|
|
1916
2071
|
},
|
|
1917
|
-
/* @__PURE__ */
|
|
2072
|
+
/* @__PURE__ */ import_react10.default.createElement(
|
|
1918
2073
|
"span",
|
|
1919
2074
|
{
|
|
1920
2075
|
className: "absolute inset-0 rounded-full animate-ping opacity-20",
|
|
1921
2076
|
style: { background: ui.primaryColor }
|
|
1922
2077
|
}
|
|
1923
2078
|
),
|
|
1924
|
-
/* @__PURE__ */
|
|
2079
|
+
/* @__PURE__ */ import_react10.default.createElement(
|
|
1925
2080
|
"span",
|
|
1926
2081
|
{
|
|
1927
2082
|
className: `transition-transform duration-300 ${isOpen ? "rotate-90 scale-90" : "rotate-0 scale-100"}`
|
|
1928
2083
|
},
|
|
1929
|
-
isOpen ? /* @__PURE__ */
|
|
2084
|
+
isOpen ? /* @__PURE__ */ import_react10.default.createElement(import_lucide_react6.X, { className: "w-6 h-6 text-white" }) : /* @__PURE__ */ import_react10.default.createElement(import_lucide_react6.MessageSquare, { className: "w-6 h-6 text-white" })
|
|
1930
2085
|
),
|
|
1931
|
-
hasUnread && !isOpen && /* @__PURE__ */
|
|
2086
|
+
hasUnread && !isOpen && /* @__PURE__ */ import_react10.default.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")
|
|
1932
2087
|
));
|
|
1933
2088
|
}
|
|
1934
2089
|
|
|
1935
2090
|
// src/components/DocumentUpload.tsx
|
|
1936
|
-
var
|
|
2091
|
+
var import_react11 = __toESM(require("react"));
|
|
1937
2092
|
var import_lucide_react7 = require("lucide-react");
|
|
1938
2093
|
function DocumentUpload({ namespace, onUploadComplete, className = "" }) {
|
|
1939
2094
|
const { ui } = useConfig();
|
|
1940
|
-
const [fileStates, setFileStates] = (0,
|
|
1941
|
-
const [isDragging, setIsDragging] = (0,
|
|
1942
|
-
const fileInputRef = (0,
|
|
2095
|
+
const [fileStates, setFileStates] = (0, import_react11.useState)([]);
|
|
2096
|
+
const [isDragging, setIsDragging] = (0, import_react11.useState)(false);
|
|
2097
|
+
const fileInputRef = (0, import_react11.useRef)(null);
|
|
1943
2098
|
const addFiles = (files) => {
|
|
1944
2099
|
const newStates = files.map((file) => ({ file, status: "idle" }));
|
|
1945
2100
|
setFileStates((prev) => [...prev, ...newStates]);
|
|
@@ -1989,7 +2144,7 @@ function DocumentUpload({ namespace, onUploadComplete, className = "" }) {
|
|
|
1989
2144
|
};
|
|
1990
2145
|
const isUploading = fileStates.some((s) => s.status === "uploading");
|
|
1991
2146
|
const hasIdle = fileStates.some((s) => s.status === "idle");
|
|
1992
|
-
return /* @__PURE__ */
|
|
2147
|
+
return /* @__PURE__ */ import_react11.default.createElement(
|
|
1993
2148
|
"div",
|
|
1994
2149
|
{
|
|
1995
2150
|
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}`,
|
|
@@ -1997,14 +2152,14 @@ function DocumentUpload({ namespace, onUploadComplete, className = "" }) {
|
|
|
1997
2152
|
onDragLeave,
|
|
1998
2153
|
onDrop
|
|
1999
2154
|
},
|
|
2000
|
-
/* @__PURE__ */
|
|
2155
|
+
/* @__PURE__ */ import_react11.default.createElement("div", { className: "flex flex-col items-center justify-center text-center" }, /* @__PURE__ */ import_react11.default.createElement(
|
|
2001
2156
|
"div",
|
|
2002
2157
|
{
|
|
2003
2158
|
className: "w-12 h-12 rounded-full flex items-center justify-center mb-4 shadow-sm",
|
|
2004
2159
|
style: { background: `linear-gradient(135deg, ${ui.primaryColor}20, ${ui.accentColor}20)` }
|
|
2005
2160
|
},
|
|
2006
|
-
/* @__PURE__ */
|
|
2007
|
-
), /* @__PURE__ */
|
|
2161
|
+
/* @__PURE__ */ import_react11.default.createElement(import_lucide_react7.Upload, { className: "w-6 h-6", style: { color: ui.primaryColor } })
|
|
2162
|
+
), /* @__PURE__ */ import_react11.default.createElement("h3", { className: "text-slate-900 dark:text-white font-semibold mb-1" }, "Upload Documents"), /* @__PURE__ */ import_react11.default.createElement("p", { className: "text-slate-500 dark:text-white/40 text-sm mb-6 max-w-xs" }, "Drag and drop PDF, DOCX, TXT, or JSON files to train your AI on your own data."), /* @__PURE__ */ import_react11.default.createElement(
|
|
2008
2163
|
"button",
|
|
2009
2164
|
{
|
|
2010
2165
|
onClick: () => {
|
|
@@ -2020,7 +2175,7 @@ function DocumentUpload({ namespace, onUploadComplete, className = "" }) {
|
|
|
2020
2175
|
}
|
|
2021
2176
|
},
|
|
2022
2177
|
"Select Files"
|
|
2023
|
-
), /* @__PURE__ */
|
|
2178
|
+
), /* @__PURE__ */ import_react11.default.createElement(
|
|
2024
2179
|
"input",
|
|
2025
2180
|
{
|
|
2026
2181
|
ref: fileInputRef,
|
|
@@ -2031,22 +2186,22 @@ function DocumentUpload({ namespace, onUploadComplete, className = "" }) {
|
|
|
2031
2186
|
accept: ".pdf,.docx,.txt,.md,.json,.csv"
|
|
2032
2187
|
}
|
|
2033
2188
|
)),
|
|
2034
|
-
fileStates.length > 0 && /* @__PURE__ */
|
|
2189
|
+
fileStates.length > 0 && /* @__PURE__ */ import_react11.default.createElement("div", { className: "mt-8 space-y-3" }, fileStates.map((state, i) => /* @__PURE__ */ import_react11.default.createElement(
|
|
2035
2190
|
"div",
|
|
2036
2191
|
{
|
|
2037
2192
|
key: i,
|
|
2038
2193
|
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"
|
|
2039
2194
|
},
|
|
2040
|
-
/* @__PURE__ */
|
|
2041
|
-
/* @__PURE__ */
|
|
2195
|
+
/* @__PURE__ */ import_react11.default.createElement("div", { className: "flex items-center gap-3 overflow-hidden" }, /* @__PURE__ */ import_react11.default.createElement("div", { className: "w-8 h-8 rounded-lg bg-white dark:bg-white/10 flex items-center justify-center shadow-sm" }, /* @__PURE__ */ import_react11.default.createElement(import_lucide_react7.File, { className: "w-4 h-4 text-slate-400" })), /* @__PURE__ */ import_react11.default.createElement("div", { className: "truncate" }, /* @__PURE__ */ import_react11.default.createElement("p", { className: "text-xs font-medium text-slate-700 dark:text-white/80 truncate" }, state.file.name), /* @__PURE__ */ import_react11.default.createElement("p", { className: "text-[10px] text-slate-400" }, (state.file.size / 1024).toFixed(1), " KB"))),
|
|
2196
|
+
/* @__PURE__ */ import_react11.default.createElement("div", { className: "flex items-center gap-2" }, state.status === "uploading" && /* @__PURE__ */ import_react11.default.createElement(import_lucide_react7.Loader2, { className: "w-4 h-4 text-slate-400 animate-spin" }), state.status === "success" && /* @__PURE__ */ import_react11.default.createElement(import_lucide_react7.CheckCircle, { className: "w-4 h-4 text-emerald-500" }), state.status === "error" && /* @__PURE__ */ import_react11.default.createElement("div", { title: state.error }, /* @__PURE__ */ import_react11.default.createElement(import_lucide_react7.AlertCircle, { className: "w-4 h-4 text-rose-500" })), state.status !== "uploading" && /* @__PURE__ */ import_react11.default.createElement(
|
|
2042
2197
|
"button",
|
|
2043
2198
|
{
|
|
2044
2199
|
onClick: () => removeFile(i),
|
|
2045
2200
|
className: "p-1 rounded-md hover:bg-slate-200 dark:hover:bg-white/10 transition-colors"
|
|
2046
2201
|
},
|
|
2047
|
-
/* @__PURE__ */
|
|
2202
|
+
/* @__PURE__ */ import_react11.default.createElement(import_lucide_react7.X, { className: "w-3.5 h-3.5 text-slate-400" })
|
|
2048
2203
|
))
|
|
2049
|
-
)), hasIdle && !isUploading && /* @__PURE__ */
|
|
2204
|
+
)), hasIdle && !isUploading && /* @__PURE__ */ import_react11.default.createElement(
|
|
2050
2205
|
"button",
|
|
2051
2206
|
{
|
|
2052
2207
|
onClick: uploadFiles,
|