@retrivora-ai/rag-engine 1.1.3 → 1.1.5
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/{chunk-JBZEUFW3.mjs → chunk-OCDCJUNE.mjs} +32 -31
- package/dist/handlers/index.js +32 -31
- package/dist/handlers/index.mjs +1 -1
- package/dist/index.js +223 -95
- package/dist/index.mjs +199 -71
- package/dist/server.js +32 -31
- package/dist/server.mjs +1 -1
- package/package.json +1 -1
- package/src/app/globals.css +9 -0
- package/src/components/MessageBubble.tsx +84 -1
- package/src/components/ProductCard.tsx +90 -0
- package/src/components/ProductCarousel.tsx +59 -0
- package/src/config/serverConfig.ts +5 -1
package/dist/index.mjs
CHANGED
|
@@ -7,11 +7,11 @@ import {
|
|
|
7
7
|
} from "./chunk-X4TOT24V.mjs";
|
|
8
8
|
|
|
9
9
|
// src/components/ChatWidget.tsx
|
|
10
|
-
import
|
|
10
|
+
import React8, { useState as useState4 } from "react";
|
|
11
11
|
import { MessageSquare, X as X2 } from "lucide-react";
|
|
12
12
|
|
|
13
13
|
// src/components/ChatWindow.tsx
|
|
14
|
-
import
|
|
14
|
+
import React7, { useState as useState3, useRef as useRef3, useEffect as useEffect3, useCallback as useCallback2 } from "react";
|
|
15
15
|
import {
|
|
16
16
|
Bot as Bot2,
|
|
17
17
|
Trash2,
|
|
@@ -25,8 +25,8 @@ import {
|
|
|
25
25
|
} from "lucide-react";
|
|
26
26
|
|
|
27
27
|
// src/components/MessageBubble.tsx
|
|
28
|
-
import
|
|
29
|
-
import { Bot, User, ChevronDown as ChevronDown2, ChevronRight } from "lucide-react";
|
|
28
|
+
import React4 from "react";
|
|
29
|
+
import { Bot, User, ChevronDown as ChevronDown2, ChevronRight as ChevronRight2 } from "lucide-react";
|
|
30
30
|
import ReactMarkdown from "react-markdown";
|
|
31
31
|
import remarkGfm from "remark-gfm";
|
|
32
32
|
|
|
@@ -53,6 +53,79 @@ function SourceCard({ source, index }) {
|
|
|
53
53
|
);
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
+
// src/components/ProductCarousel.tsx
|
|
57
|
+
import React3, { useRef } from "react";
|
|
58
|
+
import { ChevronLeft, ChevronRight } from "lucide-react";
|
|
59
|
+
|
|
60
|
+
// src/components/ProductCard.tsx
|
|
61
|
+
import React2 from "react";
|
|
62
|
+
import Image from "next/image";
|
|
63
|
+
import { ShoppingCart, ExternalLink } from "lucide-react";
|
|
64
|
+
function ProductCard({ product, primaryColor = "#6366f1" }) {
|
|
65
|
+
return /* @__PURE__ */ React2.createElement("div", { className: "flex-shrink-0 w-64 bg-white dark:bg-white/5 border border-slate-200 dark:border-white/10 rounded-xl overflow-hidden shadow-sm hover:shadow-md transition-all duration-300 group" }, /* @__PURE__ */ React2.createElement("div", { className: "relative h-40 w-full bg-slate-100 dark:bg-white/5 flex items-center justify-center overflow-hidden" }, product.image ? /* @__PURE__ */ React2.createElement(
|
|
66
|
+
Image,
|
|
67
|
+
{
|
|
68
|
+
src: product.image,
|
|
69
|
+
alt: product.name,
|
|
70
|
+
fill: true,
|
|
71
|
+
unoptimized: true,
|
|
72
|
+
className: "object-cover group-hover:scale-105 transition-transform duration-500"
|
|
73
|
+
}
|
|
74
|
+
) : /* @__PURE__ */ React2.createElement("div", { className: "text-slate-400 dark:text-white/20" }, /* @__PURE__ */ React2.createElement(ShoppingCart, { className: "w-12 h-12" })), product.brand && /* @__PURE__ */ React2.createElement("div", { className: "absolute top-2 left-2 px-2 py-1 bg-white/90 dark:bg-black/60 backdrop-blur-md rounded-md text-[10px] font-bold uppercase tracking-wider text-slate-700 dark:text-white/90 shadow-sm" }, product.brand)), /* @__PURE__ */ React2.createElement("div", { className: "p-4 flex flex-col gap-2" }, /* @__PURE__ */ React2.createElement("div", { className: "flex justify-between items-start gap-2" }, /* @__PURE__ */ React2.createElement("h3", { className: "text-sm font-semibold text-slate-800 dark:text-white/90 line-clamp-1" }, product.name), product.price && /* @__PURE__ */ React2.createElement("span", { className: "text-sm font-bold", style: { color: primaryColor } }, typeof product.price === "number" ? `$${product.price}` : product.price)), product.description && /* @__PURE__ */ React2.createElement("p", { className: "text-[11px] text-slate-500 dark:text-white/50 line-clamp-2 leading-relaxed" }, product.description), /* @__PURE__ */ React2.createElement("div", { className: "mt-2 flex gap-2" }, /* @__PURE__ */ React2.createElement(
|
|
75
|
+
"button",
|
|
76
|
+
{
|
|
77
|
+
className: "flex-1 py-2 px-3 rounded-lg text-[11px] font-medium text-white shadow-sm hover:opacity-90 transition-opacity flex items-center justify-center gap-1.5",
|
|
78
|
+
style: { background: primaryColor }
|
|
79
|
+
},
|
|
80
|
+
/* @__PURE__ */ React2.createElement(ShoppingCart, { className: "w-3 h-3" }),
|
|
81
|
+
"Add to Cart"
|
|
82
|
+
), product.link && /* @__PURE__ */ React2.createElement(
|
|
83
|
+
"a",
|
|
84
|
+
{
|
|
85
|
+
href: product.link,
|
|
86
|
+
target: "_blank",
|
|
87
|
+
rel: "noopener noreferrer",
|
|
88
|
+
className: "p-2 rounded-lg bg-slate-100 dark:bg-white/10 text-slate-600 dark:text-white/70 hover:bg-slate-200 dark:hover:bg-white/20 transition-colors"
|
|
89
|
+
},
|
|
90
|
+
/* @__PURE__ */ React2.createElement(ExternalLink, { className: "w-3.5 h-3.5" })
|
|
91
|
+
))));
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// src/components/ProductCarousel.tsx
|
|
95
|
+
function ProductCarousel({ products, primaryColor = "#6366f1" }) {
|
|
96
|
+
const scrollRef = useRef(null);
|
|
97
|
+
const scroll = (direction) => {
|
|
98
|
+
if (scrollRef.current) {
|
|
99
|
+
const scrollAmount = direction === "left" ? -280 : 280;
|
|
100
|
+
scrollRef.current.scrollBy({ left: scrollAmount, behavior: "smooth" });
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
if (!products || products.length === 0) return null;
|
|
104
|
+
return /* @__PURE__ */ React3.createElement("div", { className: "relative w-full my-4 group/carousel" }, /* @__PURE__ */ React3.createElement("div", { className: "absolute -left-3 top-1/2 -translate-y-1/2 z-10 opacity-0 group-hover/carousel:opacity-100 transition-opacity" }, /* @__PURE__ */ React3.createElement(
|
|
105
|
+
"button",
|
|
106
|
+
{
|
|
107
|
+
onClick: () => scroll("left"),
|
|
108
|
+
className: "p-1.5 rounded-full bg-white dark:bg-slate-800 shadow-lg border border-slate-200 dark:border-white/10 text-slate-600 dark:text-white/80 hover:text-indigo-500 dark:hover:text-indigo-400 transition-colors"
|
|
109
|
+
},
|
|
110
|
+
/* @__PURE__ */ React3.createElement(ChevronLeft, { className: "w-4 h-4" })
|
|
111
|
+
)), /* @__PURE__ */ React3.createElement("div", { className: "absolute -right-3 top-1/2 -translate-y-1/2 z-10 opacity-0 group-hover/carousel:opacity-100 transition-opacity" }, /* @__PURE__ */ React3.createElement(
|
|
112
|
+
"button",
|
|
113
|
+
{
|
|
114
|
+
onClick: () => scroll("right"),
|
|
115
|
+
className: "p-1.5 rounded-full bg-white dark:bg-slate-800 shadow-lg border border-slate-200 dark:border-white/10 text-slate-600 dark:text-white/80 hover:text-indigo-500 dark:hover:text-indigo-400 transition-colors"
|
|
116
|
+
},
|
|
117
|
+
/* @__PURE__ */ React3.createElement(ChevronRight, { className: "w-4 h-4" })
|
|
118
|
+
)), /* @__PURE__ */ React3.createElement(
|
|
119
|
+
"div",
|
|
120
|
+
{
|
|
121
|
+
ref: scrollRef,
|
|
122
|
+
className: "flex gap-4 overflow-x-auto pb-4 px-1 scrollbar-hide snap-x snap-mandatory",
|
|
123
|
+
style: { scrollbarWidth: "none", msOverflowStyle: "none" }
|
|
124
|
+
},
|
|
125
|
+
products.map((product) => /* @__PURE__ */ React3.createElement("div", { key: product.id, className: "snap-start" }, /* @__PURE__ */ React3.createElement(ProductCard, { product, primaryColor })))
|
|
126
|
+
));
|
|
127
|
+
}
|
|
128
|
+
|
|
56
129
|
// src/components/MessageBubble.tsx
|
|
57
130
|
function MessageBubble({
|
|
58
131
|
message,
|
|
@@ -62,37 +135,92 @@ function MessageBubble({
|
|
|
62
135
|
accentColor = "#8b5cf6"
|
|
63
136
|
}) {
|
|
64
137
|
const isUser = message.role === "user";
|
|
65
|
-
const [showSources, setShowSources] =
|
|
66
|
-
|
|
138
|
+
const [showSources, setShowSources] = React4.useState(false);
|
|
139
|
+
const resolveImage = (data) => {
|
|
140
|
+
if (!data) return void 0;
|
|
141
|
+
const singleFields = ["image", "img", "thumbnail"];
|
|
142
|
+
for (const field of singleFields) {
|
|
143
|
+
const val = data[field];
|
|
144
|
+
if (typeof val === "string" && val) return val;
|
|
145
|
+
}
|
|
146
|
+
if (Array.isArray(data.images) && data.images.length > 0) {
|
|
147
|
+
if (typeof data.images[0] === "string") return data.images[0];
|
|
148
|
+
}
|
|
149
|
+
return void 0;
|
|
150
|
+
};
|
|
151
|
+
const productsFromSources = React4.useMemo(() => {
|
|
152
|
+
if (isUser || !sources) return [];
|
|
153
|
+
return sources.filter((s) => {
|
|
154
|
+
const m = s.metadata || {};
|
|
155
|
+
return m.price || m.image || m.img || m.thumbnail || m.images || m.brand || m.type === "product";
|
|
156
|
+
}).map((s) => {
|
|
157
|
+
const m = s.metadata || {};
|
|
158
|
+
return {
|
|
159
|
+
id: s.id,
|
|
160
|
+
name: m.name || m.title || s.content.split("\n")[0] || "Unknown Product",
|
|
161
|
+
brand: m.brand,
|
|
162
|
+
price: m.price,
|
|
163
|
+
image: resolveImage(m),
|
|
164
|
+
link: m.link,
|
|
165
|
+
description: s.content
|
|
166
|
+
};
|
|
167
|
+
});
|
|
168
|
+
}, [sources, isUser]);
|
|
169
|
+
const { productsFromContent, cleanContent } = React4.useMemo(() => {
|
|
170
|
+
if (isUser) return { productsFromContent: [], cleanContent: message.content };
|
|
171
|
+
const jsonRegex = /```json\s*([\s\S]*?)\s*```/g;
|
|
172
|
+
const products = [];
|
|
173
|
+
let content = message.content;
|
|
174
|
+
if (content.includes('"type": "products"') || content.includes('"type":"products"')) {
|
|
175
|
+
const matches = Array.from(content.matchAll(jsonRegex));
|
|
176
|
+
for (const m of matches) {
|
|
177
|
+
try {
|
|
178
|
+
const data = JSON.parse(m[1]);
|
|
179
|
+
if (data.type === "products" && Array.isArray(data.items)) {
|
|
180
|
+
const formattedItems = data.items.map((item) => __spreadProps(__spreadValues({}, item), {
|
|
181
|
+
image: item.image || resolveImage(item)
|
|
182
|
+
}));
|
|
183
|
+
products.push(...formattedItems);
|
|
184
|
+
content = content.replace(m[0], "");
|
|
185
|
+
}
|
|
186
|
+
} catch (e) {
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
return { productsFromContent: products, cleanContent: content.trim() };
|
|
191
|
+
}, [message.content, isUser]);
|
|
192
|
+
const allProducts = [...productsFromSources, ...productsFromContent];
|
|
193
|
+
const hasProducts = allProducts.length > 0;
|
|
194
|
+
return /* @__PURE__ */ React4.createElement("div", { className: `flex gap-3 ${isUser ? "flex-row-reverse" : "flex-row"} items-start` }, /* @__PURE__ */ React4.createElement(
|
|
67
195
|
"div",
|
|
68
196
|
{
|
|
69
197
|
className: `flex-shrink-0 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"}`,
|
|
70
198
|
style: isUser ? { background: `linear-gradient(135deg, ${primaryColor}, ${accentColor})` } : {}
|
|
71
199
|
},
|
|
72
|
-
isUser ? /* @__PURE__ */
|
|
73
|
-
), /* @__PURE__ */
|
|
200
|
+
isUser ? /* @__PURE__ */ React4.createElement(User, { className: "w-4 h-4 text-white" }) : /* @__PURE__ */ React4.createElement(Bot, { className: "w-4 h-4" })
|
|
201
|
+
), /* @__PURE__ */ React4.createElement("div", { className: `flex flex-col gap-1 max-w-[75%] ${isUser ? "items-end" : "items-start"}` }, /* @__PURE__ */ React4.createElement(
|
|
74
202
|
"div",
|
|
75
203
|
{
|
|
76
204
|
className: `relative px-4 py-3 rounded-2xl text-sm 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"}`,
|
|
77
205
|
style: isUser ? { background: `linear-gradient(135deg, ${primaryColor}, ${accentColor})` } : {}
|
|
78
206
|
},
|
|
79
|
-
isStreaming && !message.content ? /* @__PURE__ */
|
|
80
|
-
), !isUser && sources && sources.length > 0 && /* @__PURE__ */
|
|
207
|
+
isStreaming && !message.content ? /* @__PURE__ */ React4.createElement("span", { className: "flex items-center gap-1 py-1" }, /* @__PURE__ */ React4.createElement("span", { className: "w-1.5 h-1.5 rounded-full bg-slate-400 dark:bg-white/60 animate-bounce [animation-delay:0ms]" }), /* @__PURE__ */ React4.createElement("span", { className: "w-1.5 h-1.5 rounded-full bg-slate-400 dark:bg-white/60 animate-bounce [animation-delay:150ms]" }), /* @__PURE__ */ React4.createElement("span", { className: "w-1.5 h-1.5 rounded-full bg-slate-400 dark:bg-white/60 animate-bounce [animation-delay:300ms]" })) : /* @__PURE__ */ React4.createElement("div", { className: `prose prose-sm max-w-none ${isUser ? "prose-invert" : "dark:prose-invert"}` }, /* @__PURE__ */ React4.createElement(ReactMarkdown, { remarkPlugins: [remarkGfm] }, cleanContent || message.content), hasProducts && /* @__PURE__ */ React4.createElement(ProductCarousel, { products: allProducts, primaryColor }), isStreaming && message.content && /* @__PURE__ */ React4.createElement("span", { className: "inline-block w-1.5 h-3.5 ml-1 bg-emerald-500 animate-pulse align-middle" }))
|
|
208
|
+
), !isUser && sources && sources.length > 0 && /* @__PURE__ */ React4.createElement("div", { className: "w-full" }, /* @__PURE__ */ React4.createElement(
|
|
81
209
|
"button",
|
|
82
210
|
{
|
|
83
211
|
onClick: () => setShowSources((s) => !s),
|
|
84
212
|
className: "text-[11px] text-indigo-400 hover:text-indigo-300 transition-colors flex items-center gap-1 mt-1"
|
|
85
213
|
},
|
|
86
|
-
showSources ? /* @__PURE__ */
|
|
214
|
+
showSources ? /* @__PURE__ */ React4.createElement(ChevronDown2, { className: "w-3 h-3" }) : /* @__PURE__ */ React4.createElement(ChevronRight2, { className: "w-3 h-3" }),
|
|
87
215
|
sources.length,
|
|
88
216
|
" source",
|
|
89
217
|
sources.length !== 1 ? "s" : "",
|
|
90
218
|
" used"
|
|
91
|
-
), showSources && /* @__PURE__ */
|
|
219
|
+
), showSources && /* @__PURE__ */ React4.createElement("div", { className: "mt-2 flex flex-col gap-2" }, sources.map((src, i) => /* @__PURE__ */ React4.createElement(SourceCard, { key: src.id, source: src, index: i }))))));
|
|
92
220
|
}
|
|
93
221
|
|
|
94
222
|
// src/components/ConfigProvider.tsx
|
|
95
|
-
import
|
|
223
|
+
import React5, { createContext, useContext } from "react";
|
|
96
224
|
var defaultConfig = {
|
|
97
225
|
projectId: "default",
|
|
98
226
|
ui: {
|
|
@@ -121,17 +249,17 @@ function ConfigProvider({
|
|
|
121
249
|
projectId: (config == null ? void 0 : config.projectId) || defaultConfig.projectId,
|
|
122
250
|
ui: mergeDefined(defaultConfig.ui, config == null ? void 0 : config.ui)
|
|
123
251
|
};
|
|
124
|
-
return /* @__PURE__ */
|
|
252
|
+
return /* @__PURE__ */ React5.createElement(ConfigContext.Provider, { value: merged }, children);
|
|
125
253
|
}
|
|
126
254
|
function useConfig() {
|
|
127
255
|
return useContext(ConfigContext);
|
|
128
256
|
}
|
|
129
257
|
|
|
130
258
|
// src/hooks/useRagChat.ts
|
|
131
|
-
import { useState as useState2, useCallback, useRef, useEffect as useEffect2 } from "react";
|
|
259
|
+
import { useState as useState2, useCallback, useRef as useRef2, useEffect as useEffect2 } from "react";
|
|
132
260
|
|
|
133
261
|
// src/hooks/useStoredMessages.ts
|
|
134
|
-
import * as
|
|
262
|
+
import * as React6 from "react";
|
|
135
263
|
function readStoredMessages(storageKey) {
|
|
136
264
|
if (typeof window === "undefined") {
|
|
137
265
|
return [];
|
|
@@ -148,8 +276,8 @@ function readStoredMessages(storageKey) {
|
|
|
148
276
|
}
|
|
149
277
|
}
|
|
150
278
|
function useStoredMessages(storageKey, persist) {
|
|
151
|
-
const [messages, setMessages] =
|
|
152
|
-
|
|
279
|
+
const [messages, setMessages] = React6.useState(() => persist ? readStoredMessages(storageKey) : []);
|
|
280
|
+
React6.useEffect(() => {
|
|
153
281
|
if (!persist || typeof window === "undefined") {
|
|
154
282
|
return;
|
|
155
283
|
}
|
|
@@ -191,8 +319,8 @@ function useRagChat(projectId, options = {}) {
|
|
|
191
319
|
const [messages, setMessages] = useStoredMessages(storageKey, persist);
|
|
192
320
|
const [isLoading, setIsLoading] = useState2(false);
|
|
193
321
|
const [error, setError] = useState2(null);
|
|
194
|
-
const lastInputRef =
|
|
195
|
-
const messagesRef =
|
|
322
|
+
const lastInputRef = useRef2("");
|
|
323
|
+
const messagesRef = useRef2(messages);
|
|
196
324
|
useEffect2(() => {
|
|
197
325
|
messagesRef.current = messages;
|
|
198
326
|
}, [messages]);
|
|
@@ -348,8 +476,8 @@ function ChatWindow({
|
|
|
348
476
|
const { ui, projectId } = useConfig();
|
|
349
477
|
const [input, setInput] = useState3("");
|
|
350
478
|
const [mounted, setMounted] = useState3(false);
|
|
351
|
-
const bottomRef =
|
|
352
|
-
const inputRef =
|
|
479
|
+
const bottomRef = useRef3(null);
|
|
480
|
+
const inputRef = useRef3(null);
|
|
353
481
|
const { messages, send, clear, isLoading, error } = useRagChat(projectId, {
|
|
354
482
|
namespace: projectId
|
|
355
483
|
});
|
|
@@ -384,83 +512,83 @@ function ChatWindow({
|
|
|
384
512
|
const isEmpty = messages.length === 0;
|
|
385
513
|
const currentRadius = BORDER_RADIUS_MAP[ui.borderRadius || "xl"];
|
|
386
514
|
const isGlass = ui.visualStyle !== "solid";
|
|
387
|
-
return /* @__PURE__ */
|
|
515
|
+
return /* @__PURE__ */ React7.createElement(
|
|
388
516
|
"div",
|
|
389
517
|
{
|
|
390
518
|
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}`,
|
|
391
519
|
style: __spreadValues({ "--primary": ui.primaryColor, "--accent": ui.accentColor }, style)
|
|
392
520
|
},
|
|
393
|
-
onResizeStart && /* @__PURE__ */
|
|
521
|
+
onResizeStart && /* @__PURE__ */ React7.createElement(
|
|
394
522
|
"div",
|
|
395
523
|
{
|
|
396
524
|
onMouseDown: onResizeStart,
|
|
397
525
|
className: "absolute top-0 left-0 w-6 h-6 cursor-nw-resize z-[100] group flex items-start justify-start p-1",
|
|
398
526
|
title: "Drag to resize"
|
|
399
527
|
},
|
|
400
|
-
/* @__PURE__ */
|
|
528
|
+
/* @__PURE__ */ React7.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]" })
|
|
401
529
|
),
|
|
402
|
-
/* @__PURE__ */
|
|
530
|
+
/* @__PURE__ */ React7.createElement(
|
|
403
531
|
"div",
|
|
404
532
|
{
|
|
405
533
|
className: "flex items-center justify-between px-5 py-4 border-b border-slate-200 dark:border-white/10",
|
|
406
534
|
style: { background: `linear-gradient(135deg, ${ui.primaryColor}15, ${ui.accentColor}10)` }
|
|
407
535
|
},
|
|
408
|
-
/* @__PURE__ */
|
|
536
|
+
/* @__PURE__ */ React7.createElement("div", { className: "flex items-center gap-3" }, ui.logoUrl ? (
|
|
409
537
|
// eslint-disable-next-line @next/next/no-img-element
|
|
410
|
-
/* @__PURE__ */
|
|
411
|
-
) : /* @__PURE__ */
|
|
538
|
+
/* @__PURE__ */ React7.createElement("img", { src: ui.logoUrl, alt: "logo", className: "w-8 h-8 rounded-lg object-cover" })
|
|
539
|
+
) : /* @__PURE__ */ React7.createElement(
|
|
412
540
|
"div",
|
|
413
541
|
{
|
|
414
542
|
className: `w-9 h-9 flex items-center justify-center shadow-md ${ui.borderRadius === "full" ? "rounded-full" : "rounded-xl"}`,
|
|
415
543
|
style: { background: `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` }
|
|
416
544
|
},
|
|
417
|
-
/* @__PURE__ */
|
|
418
|
-
), /* @__PURE__ */
|
|
419
|
-
/* @__PURE__ */
|
|
545
|
+
/* @__PURE__ */ React7.createElement(Bot2, { className: "w-5 h-5 text-white" })
|
|
546
|
+
), /* @__PURE__ */ React7.createElement("div", null, /* @__PURE__ */ React7.createElement("h2", { className: "text-slate-900 dark:text-white font-semibold text-sm leading-tight" }, ui.title), ui.poweredBy && /* @__PURE__ */ React7.createElement("p", { className: "text-slate-500 dark:text-white/40 text-[11px] leading-tight" }, `Powered by ${ui.poweredBy}`))),
|
|
547
|
+
/* @__PURE__ */ React7.createElement("div", { className: "flex items-center gap-1.5" }, /* @__PURE__ */ React7.createElement("span", { className: "flex items-center gap-1 text-[10px] text-emerald-500 dark:text-emerald-400 mr-2" }, /* @__PURE__ */ React7.createElement("span", { className: "w-1.5 h-1.5 rounded-full bg-emerald-500 dark:bg-emerald-400 animate-pulse" }), "Online"), /* @__PURE__ */ React7.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__ */ React7.createElement(
|
|
420
548
|
"button",
|
|
421
549
|
{
|
|
422
550
|
onClick: clearHistory,
|
|
423
551
|
title: "Clear conversation",
|
|
424
552
|
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"
|
|
425
553
|
},
|
|
426
|
-
/* @__PURE__ */
|
|
427
|
-
), isResized && onResetResize && /* @__PURE__ */
|
|
554
|
+
/* @__PURE__ */ React7.createElement(Trash2, { className: "w-3.5 h-3.5" })
|
|
555
|
+
), isResized && onResetResize && /* @__PURE__ */ React7.createElement(
|
|
428
556
|
"button",
|
|
429
557
|
{
|
|
430
558
|
onClick: onResetResize,
|
|
431
559
|
title: "Reset to default size",
|
|
432
560
|
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"
|
|
433
561
|
},
|
|
434
|
-
/* @__PURE__ */
|
|
435
|
-
), onMaximize && /* @__PURE__ */
|
|
562
|
+
/* @__PURE__ */ React7.createElement(RotateCcw, { className: "w-3.5 h-3.5" })
|
|
563
|
+
), onMaximize && /* @__PURE__ */ React7.createElement(
|
|
436
564
|
"button",
|
|
437
565
|
{
|
|
438
566
|
onClick: onMaximize,
|
|
439
567
|
title: isMaximized ? "Minimize" : "Maximize",
|
|
440
568
|
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"
|
|
441
569
|
},
|
|
442
|
-
isMaximized ? /* @__PURE__ */
|
|
443
|
-
), showClose && onClose && /* @__PURE__ */
|
|
570
|
+
isMaximized ? /* @__PURE__ */ React7.createElement(Minimize2, { className: "w-3.5 h-3.5" }) : /* @__PURE__ */ React7.createElement(Maximize2, { className: "w-3.5 h-3.5" })
|
|
571
|
+
), showClose && onClose && /* @__PURE__ */ React7.createElement(
|
|
444
572
|
"button",
|
|
445
573
|
{
|
|
446
574
|
onClick: onClose,
|
|
447
575
|
title: "Close chat",
|
|
448
576
|
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"
|
|
449
577
|
},
|
|
450
|
-
/* @__PURE__ */
|
|
578
|
+
/* @__PURE__ */ React7.createElement(X, { className: "w-4 h-4" })
|
|
451
579
|
)))
|
|
452
580
|
),
|
|
453
|
-
/* @__PURE__ */
|
|
581
|
+
/* @__PURE__ */ React7.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 ? (
|
|
454
582
|
/* Welcome state */
|
|
455
|
-
/* @__PURE__ */
|
|
583
|
+
/* @__PURE__ */ React7.createElement("div", { className: "h-full flex flex-col items-center justify-center text-center gap-4 px-6 py-12" }, /* @__PURE__ */ React7.createElement(
|
|
456
584
|
"div",
|
|
457
585
|
{
|
|
458
586
|
className: `w-16 h-16 flex items-center justify-center shadow-lg ${ui.borderRadius === "full" ? "rounded-full" : "rounded-2xl"}`,
|
|
459
587
|
style: { background: `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` }
|
|
460
588
|
},
|
|
461
|
-
/* @__PURE__ */
|
|
462
|
-
), /* @__PURE__ */
|
|
463
|
-
(suggestion) => /* @__PURE__ */
|
|
589
|
+
/* @__PURE__ */ React7.createElement(Sparkles, { className: "w-8 h-8 text-white" })
|
|
590
|
+
), /* @__PURE__ */ React7.createElement("div", null, /* @__PURE__ */ React7.createElement("p", { className: "text-slate-800 dark:text-white/80 font-medium leading-relaxed" }, ui.welcomeMessage), /* @__PURE__ */ React7.createElement("p", { className: "text-slate-500 dark:text-white/30 text-sm mt-2" }, "Ask a question to get started")), /* @__PURE__ */ React7.createElement("div", { className: "flex flex-wrap gap-2 justify-center mt-2" }, CHAT_SUGGESTIONS.map(
|
|
591
|
+
(suggestion) => /* @__PURE__ */ React7.createElement(
|
|
464
592
|
"button",
|
|
465
593
|
{
|
|
466
594
|
key: suggestion,
|
|
@@ -474,7 +602,7 @@ function ChatWindow({
|
|
|
474
602
|
suggestion
|
|
475
603
|
)
|
|
476
604
|
)))
|
|
477
|
-
) : messages.map((msg, index) => /* @__PURE__ */
|
|
605
|
+
) : messages.map((msg, index) => /* @__PURE__ */ React7.createElement(
|
|
478
606
|
MessageBubble,
|
|
479
607
|
{
|
|
480
608
|
key: msg.id,
|
|
@@ -484,7 +612,7 @@ function ChatWindow({
|
|
|
484
612
|
primaryColor: ui.primaryColor,
|
|
485
613
|
accentColor: ui.accentColor
|
|
486
614
|
}
|
|
487
|
-
)), isLoading && ((_a = messages[messages.length - 1]) == null ? void 0 : _a.role) !== "assistant" && /* @__PURE__ */
|
|
615
|
+
)), isLoading && ((_a = messages[messages.length - 1]) == null ? void 0 : _a.role) !== "assistant" && /* @__PURE__ */ React7.createElement(
|
|
488
616
|
MessageBubble,
|
|
489
617
|
{
|
|
490
618
|
message: { role: "assistant", content: "" },
|
|
@@ -492,8 +620,8 @@ function ChatWindow({
|
|
|
492
620
|
primaryColor: ui.primaryColor,
|
|
493
621
|
accentColor: ui.accentColor
|
|
494
622
|
}
|
|
495
|
-
), error && /* @__PURE__ */
|
|
496
|
-
/* @__PURE__ */
|
|
623
|
+
), error && /* @__PURE__ */ React7.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__ */ React7.createElement(TriangleAlert, { className: "w-4 h-4 flex-shrink-0" }), /* @__PURE__ */ React7.createElement("span", null, error)), /* @__PURE__ */ React7.createElement("div", { ref: bottomRef })),
|
|
624
|
+
/* @__PURE__ */ React7.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]"}` }, /* @__PURE__ */ React7.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__ */ React7.createElement(
|
|
497
625
|
"textarea",
|
|
498
626
|
{
|
|
499
627
|
ref: inputRef,
|
|
@@ -506,7 +634,7 @@ function ChatWindow({
|
|
|
506
634
|
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",
|
|
507
635
|
style: { scrollbarWidth: "none" }
|
|
508
636
|
}
|
|
509
|
-
), /* @__PURE__ */
|
|
637
|
+
), /* @__PURE__ */ React7.createElement(
|
|
510
638
|
"button",
|
|
511
639
|
{
|
|
512
640
|
onClick: sendMessage,
|
|
@@ -517,8 +645,8 @@ function ChatWindow({
|
|
|
517
645
|
// slate-400/20 for light mode disabled
|
|
518
646
|
}
|
|
519
647
|
},
|
|
520
|
-
/* @__PURE__ */
|
|
521
|
-
)), /* @__PURE__ */
|
|
648
|
+
/* @__PURE__ */ React7.createElement(ArrowUp, { className: "w-4 h-4 text-white" })
|
|
649
|
+
)), /* @__PURE__ */ React7.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"))
|
|
522
650
|
);
|
|
523
651
|
}
|
|
524
652
|
|
|
@@ -581,7 +709,7 @@ function ChatWidget({ position = "bottom-right" }) {
|
|
|
581
709
|
}
|
|
582
710
|
};
|
|
583
711
|
const isResized = dimensions.width !== DEFAULT_DIMENSIONS.width || dimensions.height !== DEFAULT_DIMENSIONS.height;
|
|
584
|
-
return /* @__PURE__ */
|
|
712
|
+
return /* @__PURE__ */ React8.createElement(React8.Fragment, null, /* @__PURE__ */ React8.createElement(
|
|
585
713
|
"div",
|
|
586
714
|
{
|
|
587
715
|
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"}`,
|
|
@@ -591,7 +719,7 @@ function ChatWidget({ position = "bottom-right" }) {
|
|
|
591
719
|
maxHeight: "calc(100vh - 6rem)"
|
|
592
720
|
}
|
|
593
721
|
},
|
|
594
|
-
/* @__PURE__ */
|
|
722
|
+
/* @__PURE__ */ React8.createElement(
|
|
595
723
|
ChatWindow,
|
|
596
724
|
{
|
|
597
725
|
className: "h-full relative z-10",
|
|
@@ -604,13 +732,13 @@ function ChatWidget({ position = "bottom-right" }) {
|
|
|
604
732
|
isMaximized
|
|
605
733
|
}
|
|
606
734
|
),
|
|
607
|
-
/* @__PURE__ */
|
|
735
|
+
/* @__PURE__ */ React8.createElement(
|
|
608
736
|
"div",
|
|
609
737
|
{
|
|
610
738
|
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"}`
|
|
611
739
|
}
|
|
612
740
|
)
|
|
613
|
-
), /* @__PURE__ */
|
|
741
|
+
), /* @__PURE__ */ React8.createElement(
|
|
614
742
|
"button",
|
|
615
743
|
{
|
|
616
744
|
onClick: isOpen ? () => setIsOpen(false) : handleOpen,
|
|
@@ -618,32 +746,32 @@ function ChatWidget({ position = "bottom-right" }) {
|
|
|
618
746
|
style: { background: `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` },
|
|
619
747
|
"aria-label": "Open chat"
|
|
620
748
|
},
|
|
621
|
-
/* @__PURE__ */
|
|
749
|
+
/* @__PURE__ */ React8.createElement(
|
|
622
750
|
"span",
|
|
623
751
|
{
|
|
624
752
|
className: "absolute inset-0 rounded-full animate-ping opacity-20",
|
|
625
753
|
style: { background: ui.primaryColor }
|
|
626
754
|
}
|
|
627
755
|
),
|
|
628
|
-
/* @__PURE__ */
|
|
756
|
+
/* @__PURE__ */ React8.createElement(
|
|
629
757
|
"span",
|
|
630
758
|
{
|
|
631
759
|
className: `transition-transform duration-300 ${isOpen ? "rotate-90 scale-90" : "rotate-0 scale-100"}`
|
|
632
760
|
},
|
|
633
|
-
isOpen ? /* @__PURE__ */
|
|
761
|
+
isOpen ? /* @__PURE__ */ React8.createElement(X2, { className: "w-6 h-6 text-white" }) : /* @__PURE__ */ React8.createElement(MessageSquare, { className: "w-6 h-6 text-white" })
|
|
634
762
|
),
|
|
635
|
-
hasUnread && !isOpen && /* @__PURE__ */
|
|
763
|
+
hasUnread && !isOpen && /* @__PURE__ */ React8.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")
|
|
636
764
|
));
|
|
637
765
|
}
|
|
638
766
|
|
|
639
767
|
// src/components/DocumentUpload.tsx
|
|
640
|
-
import
|
|
768
|
+
import React9, { useState as useState5, useRef as useRef4 } from "react";
|
|
641
769
|
import { Upload, File, X as X3, CheckCircle, AlertCircle, Loader2 } from "lucide-react";
|
|
642
770
|
function DocumentUpload({ namespace, onUploadComplete, className = "" }) {
|
|
643
771
|
const { ui } = useConfig();
|
|
644
772
|
const [fileStates, setFileStates] = useState5([]);
|
|
645
773
|
const [isDragging, setIsDragging] = useState5(false);
|
|
646
|
-
const fileInputRef =
|
|
774
|
+
const fileInputRef = useRef4(null);
|
|
647
775
|
const addFiles = (files) => {
|
|
648
776
|
const newStates = files.map((file) => ({ file, status: "idle" }));
|
|
649
777
|
setFileStates((prev) => [...prev, ...newStates]);
|
|
@@ -693,7 +821,7 @@ function DocumentUpload({ namespace, onUploadComplete, className = "" }) {
|
|
|
693
821
|
};
|
|
694
822
|
const isUploading = fileStates.some((s) => s.status === "uploading");
|
|
695
823
|
const hasIdle = fileStates.some((s) => s.status === "idle");
|
|
696
|
-
return /* @__PURE__ */
|
|
824
|
+
return /* @__PURE__ */ React9.createElement(
|
|
697
825
|
"div",
|
|
698
826
|
{
|
|
699
827
|
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}`,
|
|
@@ -701,14 +829,14 @@ function DocumentUpload({ namespace, onUploadComplete, className = "" }) {
|
|
|
701
829
|
onDragLeave,
|
|
702
830
|
onDrop
|
|
703
831
|
},
|
|
704
|
-
/* @__PURE__ */
|
|
832
|
+
/* @__PURE__ */ React9.createElement("div", { className: "flex flex-col items-center justify-center text-center" }, /* @__PURE__ */ React9.createElement(
|
|
705
833
|
"div",
|
|
706
834
|
{
|
|
707
835
|
className: "w-12 h-12 rounded-full flex items-center justify-center mb-4 shadow-sm",
|
|
708
836
|
style: { background: `linear-gradient(135deg, ${ui.primaryColor}20, ${ui.accentColor}20)` }
|
|
709
837
|
},
|
|
710
|
-
/* @__PURE__ */
|
|
711
|
-
), /* @__PURE__ */
|
|
838
|
+
/* @__PURE__ */ React9.createElement(Upload, { className: "w-6 h-6", style: { color: ui.primaryColor } })
|
|
839
|
+
), /* @__PURE__ */ React9.createElement("h3", { className: "text-slate-900 dark:text-white font-semibold mb-1" }, "Upload Documents"), /* @__PURE__ */ React9.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__ */ React9.createElement(
|
|
712
840
|
"button",
|
|
713
841
|
{
|
|
714
842
|
onClick: () => {
|
|
@@ -724,7 +852,7 @@ function DocumentUpload({ namespace, onUploadComplete, className = "" }) {
|
|
|
724
852
|
}
|
|
725
853
|
},
|
|
726
854
|
"Select Files"
|
|
727
|
-
), /* @__PURE__ */
|
|
855
|
+
), /* @__PURE__ */ React9.createElement(
|
|
728
856
|
"input",
|
|
729
857
|
{
|
|
730
858
|
ref: fileInputRef,
|
|
@@ -735,22 +863,22 @@ function DocumentUpload({ namespace, onUploadComplete, className = "" }) {
|
|
|
735
863
|
accept: ".pdf,.docx,.txt,.md,.json,.csv"
|
|
736
864
|
}
|
|
737
865
|
)),
|
|
738
|
-
fileStates.length > 0 && /* @__PURE__ */
|
|
866
|
+
fileStates.length > 0 && /* @__PURE__ */ React9.createElement("div", { className: "mt-8 space-y-3" }, fileStates.map((state, i) => /* @__PURE__ */ React9.createElement(
|
|
739
867
|
"div",
|
|
740
868
|
{
|
|
741
869
|
key: i,
|
|
742
870
|
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"
|
|
743
871
|
},
|
|
744
|
-
/* @__PURE__ */
|
|
745
|
-
/* @__PURE__ */
|
|
872
|
+
/* @__PURE__ */ React9.createElement("div", { className: "flex items-center gap-3 overflow-hidden" }, /* @__PURE__ */ React9.createElement("div", { className: "w-8 h-8 rounded-lg bg-white dark:bg-white/10 flex items-center justify-center shadow-sm" }, /* @__PURE__ */ React9.createElement(File, { className: "w-4 h-4 text-slate-400" })), /* @__PURE__ */ React9.createElement("div", { className: "truncate" }, /* @__PURE__ */ React9.createElement("p", { className: "text-xs font-medium text-slate-700 dark:text-white/80 truncate" }, state.file.name), /* @__PURE__ */ React9.createElement("p", { className: "text-[10px] text-slate-400" }, (state.file.size / 1024).toFixed(1), " KB"))),
|
|
873
|
+
/* @__PURE__ */ React9.createElement("div", { className: "flex items-center gap-2" }, state.status === "uploading" && /* @__PURE__ */ React9.createElement(Loader2, { className: "w-4 h-4 text-slate-400 animate-spin" }), state.status === "success" && /* @__PURE__ */ React9.createElement(CheckCircle, { className: "w-4 h-4 text-emerald-500" }), state.status === "error" && /* @__PURE__ */ React9.createElement("div", { title: state.error }, /* @__PURE__ */ React9.createElement(AlertCircle, { className: "w-4 h-4 text-rose-500" })), state.status !== "uploading" && /* @__PURE__ */ React9.createElement(
|
|
746
874
|
"button",
|
|
747
875
|
{
|
|
748
876
|
onClick: () => removeFile(i),
|
|
749
877
|
className: "p-1 rounded-md hover:bg-slate-200 dark:hover:bg-white/10 transition-colors"
|
|
750
878
|
},
|
|
751
|
-
/* @__PURE__ */
|
|
879
|
+
/* @__PURE__ */ React9.createElement(X3, { className: "w-3.5 h-3.5 text-slate-400" })
|
|
752
880
|
))
|
|
753
|
-
)), hasIdle && !isUploading && /* @__PURE__ */
|
|
881
|
+
)), hasIdle && !isUploading && /* @__PURE__ */ React9.createElement(
|
|
754
882
|
"button",
|
|
755
883
|
{
|
|
756
884
|
onClick: uploadFiles,
|