@retrivora-ai/rag-engine 1.1.4 → 1.1.6
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/index.js +242 -95
- package/dist/index.mjs +218 -71
- package/package.json +1 -1
- package/src/app/globals.css +9 -0
- package/src/components/MessageBubble.tsx +87 -2
- package/src/components/ProductCard.tsx +90 -0
- package/src/components/ProductCarousel.tsx +69 -0
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,98 @@ 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-full bg-white dark:bg-white/5 border border-slate-200 dark:border-white/10 rounded-xl overflow-hidden shadow-sm hover:shadow-md transition-all duration-300 group" }, /* @__PURE__ */ 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 firstCard = scrollRef.current.firstElementChild;
|
|
100
|
+
if (firstCard) {
|
|
101
|
+
const cardWidth = firstCard.offsetWidth + 16;
|
|
102
|
+
const scrollAmount = direction === "left" ? -cardWidth : cardWidth;
|
|
103
|
+
scrollRef.current.scrollBy({ left: scrollAmount, behavior: "smooth" });
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
if (!products || products.length === 0) return null;
|
|
108
|
+
return /* @__PURE__ */ React3.createElement("div", { className: "relative w-full my-4 group/carousel" }, /* @__PURE__ */ React3.createElement("div", { className: "absolute -left-4 top-1/2 -translate-y-1/2 z-20 opacity-100 md:opacity-0 md:group-hover/carousel:opacity-100 transition-opacity" }, /* @__PURE__ */ React3.createElement(
|
|
109
|
+
"button",
|
|
110
|
+
{
|
|
111
|
+
onClick: (e) => {
|
|
112
|
+
e.stopPropagation();
|
|
113
|
+
scroll("left");
|
|
114
|
+
},
|
|
115
|
+
className: "p-2 rounded-full bg-white dark:bg-slate-800 shadow-xl border border-slate-200 dark:border-white/10 text-slate-600 dark:text-white/80 hover:text-indigo-500 dark:hover:text-indigo-400 transition-all hover:scale-110 active:scale-95",
|
|
116
|
+
"aria-label": "Scroll left"
|
|
117
|
+
},
|
|
118
|
+
/* @__PURE__ */ React3.createElement(ChevronLeft, { className: "w-5 h-5" })
|
|
119
|
+
)), /* @__PURE__ */ React3.createElement("div", { className: "absolute -right-4 top-1/2 -translate-y-1/2 z-20 opacity-100 md:opacity-0 md:group-hover/carousel:opacity-100 transition-opacity" }, /* @__PURE__ */ React3.createElement(
|
|
120
|
+
"button",
|
|
121
|
+
{
|
|
122
|
+
onClick: (e) => {
|
|
123
|
+
e.stopPropagation();
|
|
124
|
+
scroll("right");
|
|
125
|
+
},
|
|
126
|
+
className: "p-2 rounded-full bg-white dark:bg-slate-800 shadow-xl border border-slate-200 dark:border-white/10 text-slate-600 dark:text-white/80 hover:text-indigo-500 dark:hover:text-indigo-400 transition-all hover:scale-110 active:scale-95",
|
|
127
|
+
"aria-label": "Scroll right"
|
|
128
|
+
},
|
|
129
|
+
/* @__PURE__ */ React3.createElement(ChevronRight, { className: "w-5 h-5" })
|
|
130
|
+
)), /* @__PURE__ */ React3.createElement(
|
|
131
|
+
"div",
|
|
132
|
+
{
|
|
133
|
+
ref: scrollRef,
|
|
134
|
+
className: "flex gap-4 overflow-x-auto pb-4 px-1 scrollbar-hide snap-x snap-mandatory",
|
|
135
|
+
style: { scrollbarWidth: "none", msOverflowStyle: "none" }
|
|
136
|
+
},
|
|
137
|
+
products.map((product) => /* @__PURE__ */ React3.createElement(
|
|
138
|
+
"div",
|
|
139
|
+
{
|
|
140
|
+
key: product.id,
|
|
141
|
+
className: "snap-start flex-shrink-0 w-[85%] sm:w-[48%] md:w-[31%] min-w-[200px] max-w-[300px]"
|
|
142
|
+
},
|
|
143
|
+
/* @__PURE__ */ React3.createElement(ProductCard, { product, primaryColor })
|
|
144
|
+
))
|
|
145
|
+
));
|
|
146
|
+
}
|
|
147
|
+
|
|
56
148
|
// src/components/MessageBubble.tsx
|
|
57
149
|
function MessageBubble({
|
|
58
150
|
message,
|
|
@@ -62,37 +154,92 @@ function MessageBubble({
|
|
|
62
154
|
accentColor = "#8b5cf6"
|
|
63
155
|
}) {
|
|
64
156
|
const isUser = message.role === "user";
|
|
65
|
-
const [showSources, setShowSources] =
|
|
66
|
-
|
|
157
|
+
const [showSources, setShowSources] = React4.useState(false);
|
|
158
|
+
const resolveImage = (data) => {
|
|
159
|
+
if (!data) return void 0;
|
|
160
|
+
const singleFields = ["image", "img", "thumbnail"];
|
|
161
|
+
for (const field of singleFields) {
|
|
162
|
+
const val = data[field];
|
|
163
|
+
if (typeof val === "string" && val) return val;
|
|
164
|
+
}
|
|
165
|
+
if (Array.isArray(data.images) && data.images.length > 0) {
|
|
166
|
+
if (typeof data.images[0] === "string") return data.images[0];
|
|
167
|
+
}
|
|
168
|
+
return void 0;
|
|
169
|
+
};
|
|
170
|
+
const productsFromSources = React4.useMemo(() => {
|
|
171
|
+
if (isUser || !sources) return [];
|
|
172
|
+
return sources.filter((s) => {
|
|
173
|
+
const m = s.metadata || {};
|
|
174
|
+
return m.price || m.image || m.img || m.thumbnail || m.images || m.brand || m.type === "product";
|
|
175
|
+
}).map((s) => {
|
|
176
|
+
const m = s.metadata || {};
|
|
177
|
+
return {
|
|
178
|
+
id: s.id,
|
|
179
|
+
name: m.name || m.title || s.content.split("\n")[0] || "Unknown Product",
|
|
180
|
+
brand: m.brand,
|
|
181
|
+
price: m.price,
|
|
182
|
+
image: resolveImage(m),
|
|
183
|
+
link: m.link,
|
|
184
|
+
description: s.content
|
|
185
|
+
};
|
|
186
|
+
});
|
|
187
|
+
}, [sources, isUser]);
|
|
188
|
+
const { productsFromContent, cleanContent } = React4.useMemo(() => {
|
|
189
|
+
if (isUser) return { productsFromContent: [], cleanContent: message.content };
|
|
190
|
+
const jsonRegex = /```json\s*([\s\S]*?)\s*```/g;
|
|
191
|
+
const products = [];
|
|
192
|
+
let content = message.content;
|
|
193
|
+
if (content.includes('"type": "products"') || content.includes('"type":"products"')) {
|
|
194
|
+
const matches = Array.from(content.matchAll(jsonRegex));
|
|
195
|
+
for (const m of matches) {
|
|
196
|
+
try {
|
|
197
|
+
const data = JSON.parse(m[1]);
|
|
198
|
+
if (data.type === "products" && Array.isArray(data.items)) {
|
|
199
|
+
const formattedItems = data.items.map((item) => __spreadProps(__spreadValues({}, item), {
|
|
200
|
+
image: item.image || resolveImage(item)
|
|
201
|
+
}));
|
|
202
|
+
products.push(...formattedItems);
|
|
203
|
+
content = content.replace(m[0], "");
|
|
204
|
+
}
|
|
205
|
+
} catch (e) {
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
return { productsFromContent: products, cleanContent: content.trim() };
|
|
210
|
+
}, [message.content, isUser]);
|
|
211
|
+
const allProducts = [...productsFromSources, ...productsFromContent];
|
|
212
|
+
const hasProducts = allProducts.length > 0;
|
|
213
|
+
return /* @__PURE__ */ React4.createElement("div", { className: `flex gap-3 ${isUser ? "flex-row-reverse" : "flex-row"} items-start` }, /* @__PURE__ */ React4.createElement(
|
|
67
214
|
"div",
|
|
68
215
|
{
|
|
69
216
|
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
217
|
style: isUser ? { background: `linear-gradient(135deg, ${primaryColor}, ${accentColor})` } : {}
|
|
71
218
|
},
|
|
72
|
-
isUser ? /* @__PURE__ */
|
|
73
|
-
), /* @__PURE__ */
|
|
219
|
+
isUser ? /* @__PURE__ */ React4.createElement(User, { className: "w-4 h-4 text-white" }) : /* @__PURE__ */ React4.createElement(Bot, { className: "w-4 h-4" })
|
|
220
|
+
), /* @__PURE__ */ React4.createElement("div", { className: `flex flex-col gap-1 max-w-[90%] ${isUser ? "items-end" : "items-start"}` }, /* @__PURE__ */ React4.createElement(
|
|
74
221
|
"div",
|
|
75
222
|
{
|
|
76
223
|
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
224
|
style: isUser ? { background: `linear-gradient(135deg, ${primaryColor}, ${accentColor})` } : {}
|
|
78
225
|
},
|
|
79
|
-
isStreaming && !message.content ? /* @__PURE__ */
|
|
80
|
-
), !isUser && sources && sources.length > 0 && /* @__PURE__ */
|
|
226
|
+
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), 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" }))
|
|
227
|
+
), !isUser && hasProducts && /* @__PURE__ */ React4.createElement("div", { className: "w-full mt-1" }, /* @__PURE__ */ React4.createElement(ProductCarousel, { products: allProducts, primaryColor })), !isUser && sources && sources.length > 0 && /* @__PURE__ */ React4.createElement("div", { className: "w-full" }, /* @__PURE__ */ React4.createElement(
|
|
81
228
|
"button",
|
|
82
229
|
{
|
|
83
230
|
onClick: () => setShowSources((s) => !s),
|
|
84
231
|
className: "text-[11px] text-indigo-400 hover:text-indigo-300 transition-colors flex items-center gap-1 mt-1"
|
|
85
232
|
},
|
|
86
|
-
showSources ? /* @__PURE__ */
|
|
233
|
+
showSources ? /* @__PURE__ */ React4.createElement(ChevronDown2, { className: "w-3 h-3" }) : /* @__PURE__ */ React4.createElement(ChevronRight2, { className: "w-3 h-3" }),
|
|
87
234
|
sources.length,
|
|
88
235
|
" source",
|
|
89
236
|
sources.length !== 1 ? "s" : "",
|
|
90
237
|
" used"
|
|
91
|
-
), showSources && /* @__PURE__ */
|
|
238
|
+
), 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
239
|
}
|
|
93
240
|
|
|
94
241
|
// src/components/ConfigProvider.tsx
|
|
95
|
-
import
|
|
242
|
+
import React5, { createContext, useContext } from "react";
|
|
96
243
|
var defaultConfig = {
|
|
97
244
|
projectId: "default",
|
|
98
245
|
ui: {
|
|
@@ -121,17 +268,17 @@ function ConfigProvider({
|
|
|
121
268
|
projectId: (config == null ? void 0 : config.projectId) || defaultConfig.projectId,
|
|
122
269
|
ui: mergeDefined(defaultConfig.ui, config == null ? void 0 : config.ui)
|
|
123
270
|
};
|
|
124
|
-
return /* @__PURE__ */
|
|
271
|
+
return /* @__PURE__ */ React5.createElement(ConfigContext.Provider, { value: merged }, children);
|
|
125
272
|
}
|
|
126
273
|
function useConfig() {
|
|
127
274
|
return useContext(ConfigContext);
|
|
128
275
|
}
|
|
129
276
|
|
|
130
277
|
// src/hooks/useRagChat.ts
|
|
131
|
-
import { useState as useState2, useCallback, useRef, useEffect as useEffect2 } from "react";
|
|
278
|
+
import { useState as useState2, useCallback, useRef as useRef2, useEffect as useEffect2 } from "react";
|
|
132
279
|
|
|
133
280
|
// src/hooks/useStoredMessages.ts
|
|
134
|
-
import * as
|
|
281
|
+
import * as React6 from "react";
|
|
135
282
|
function readStoredMessages(storageKey) {
|
|
136
283
|
if (typeof window === "undefined") {
|
|
137
284
|
return [];
|
|
@@ -148,8 +295,8 @@ function readStoredMessages(storageKey) {
|
|
|
148
295
|
}
|
|
149
296
|
}
|
|
150
297
|
function useStoredMessages(storageKey, persist) {
|
|
151
|
-
const [messages, setMessages] =
|
|
152
|
-
|
|
298
|
+
const [messages, setMessages] = React6.useState(() => persist ? readStoredMessages(storageKey) : []);
|
|
299
|
+
React6.useEffect(() => {
|
|
153
300
|
if (!persist || typeof window === "undefined") {
|
|
154
301
|
return;
|
|
155
302
|
}
|
|
@@ -191,8 +338,8 @@ function useRagChat(projectId, options = {}) {
|
|
|
191
338
|
const [messages, setMessages] = useStoredMessages(storageKey, persist);
|
|
192
339
|
const [isLoading, setIsLoading] = useState2(false);
|
|
193
340
|
const [error, setError] = useState2(null);
|
|
194
|
-
const lastInputRef =
|
|
195
|
-
const messagesRef =
|
|
341
|
+
const lastInputRef = useRef2("");
|
|
342
|
+
const messagesRef = useRef2(messages);
|
|
196
343
|
useEffect2(() => {
|
|
197
344
|
messagesRef.current = messages;
|
|
198
345
|
}, [messages]);
|
|
@@ -348,8 +495,8 @@ function ChatWindow({
|
|
|
348
495
|
const { ui, projectId } = useConfig();
|
|
349
496
|
const [input, setInput] = useState3("");
|
|
350
497
|
const [mounted, setMounted] = useState3(false);
|
|
351
|
-
const bottomRef =
|
|
352
|
-
const inputRef =
|
|
498
|
+
const bottomRef = useRef3(null);
|
|
499
|
+
const inputRef = useRef3(null);
|
|
353
500
|
const { messages, send, clear, isLoading, error } = useRagChat(projectId, {
|
|
354
501
|
namespace: projectId
|
|
355
502
|
});
|
|
@@ -384,83 +531,83 @@ function ChatWindow({
|
|
|
384
531
|
const isEmpty = messages.length === 0;
|
|
385
532
|
const currentRadius = BORDER_RADIUS_MAP[ui.borderRadius || "xl"];
|
|
386
533
|
const isGlass = ui.visualStyle !== "solid";
|
|
387
|
-
return /* @__PURE__ */
|
|
534
|
+
return /* @__PURE__ */ React7.createElement(
|
|
388
535
|
"div",
|
|
389
536
|
{
|
|
390
537
|
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
538
|
style: __spreadValues({ "--primary": ui.primaryColor, "--accent": ui.accentColor }, style)
|
|
392
539
|
},
|
|
393
|
-
onResizeStart && /* @__PURE__ */
|
|
540
|
+
onResizeStart && /* @__PURE__ */ React7.createElement(
|
|
394
541
|
"div",
|
|
395
542
|
{
|
|
396
543
|
onMouseDown: onResizeStart,
|
|
397
544
|
className: "absolute top-0 left-0 w-6 h-6 cursor-nw-resize z-[100] group flex items-start justify-start p-1",
|
|
398
545
|
title: "Drag to resize"
|
|
399
546
|
},
|
|
400
|
-
/* @__PURE__ */
|
|
547
|
+
/* @__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
548
|
),
|
|
402
|
-
/* @__PURE__ */
|
|
549
|
+
/* @__PURE__ */ React7.createElement(
|
|
403
550
|
"div",
|
|
404
551
|
{
|
|
405
552
|
className: "flex items-center justify-between px-5 py-4 border-b border-slate-200 dark:border-white/10",
|
|
406
553
|
style: { background: `linear-gradient(135deg, ${ui.primaryColor}15, ${ui.accentColor}10)` }
|
|
407
554
|
},
|
|
408
|
-
/* @__PURE__ */
|
|
555
|
+
/* @__PURE__ */ React7.createElement("div", { className: "flex items-center gap-3" }, ui.logoUrl ? (
|
|
409
556
|
// eslint-disable-next-line @next/next/no-img-element
|
|
410
|
-
/* @__PURE__ */
|
|
411
|
-
) : /* @__PURE__ */
|
|
557
|
+
/* @__PURE__ */ React7.createElement("img", { src: ui.logoUrl, alt: "logo", className: "w-8 h-8 rounded-lg object-cover" })
|
|
558
|
+
) : /* @__PURE__ */ React7.createElement(
|
|
412
559
|
"div",
|
|
413
560
|
{
|
|
414
561
|
className: `w-9 h-9 flex items-center justify-center shadow-md ${ui.borderRadius === "full" ? "rounded-full" : "rounded-xl"}`,
|
|
415
562
|
style: { background: `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` }
|
|
416
563
|
},
|
|
417
|
-
/* @__PURE__ */
|
|
418
|
-
), /* @__PURE__ */
|
|
419
|
-
/* @__PURE__ */
|
|
564
|
+
/* @__PURE__ */ React7.createElement(Bot2, { className: "w-5 h-5 text-white" })
|
|
565
|
+
), /* @__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}`))),
|
|
566
|
+
/* @__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
567
|
"button",
|
|
421
568
|
{
|
|
422
569
|
onClick: clearHistory,
|
|
423
570
|
title: "Clear conversation",
|
|
424
571
|
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
572
|
},
|
|
426
|
-
/* @__PURE__ */
|
|
427
|
-
), isResized && onResetResize && /* @__PURE__ */
|
|
573
|
+
/* @__PURE__ */ React7.createElement(Trash2, { className: "w-3.5 h-3.5" })
|
|
574
|
+
), isResized && onResetResize && /* @__PURE__ */ React7.createElement(
|
|
428
575
|
"button",
|
|
429
576
|
{
|
|
430
577
|
onClick: onResetResize,
|
|
431
578
|
title: "Reset to default size",
|
|
432
579
|
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
580
|
},
|
|
434
|
-
/* @__PURE__ */
|
|
435
|
-
), onMaximize && /* @__PURE__ */
|
|
581
|
+
/* @__PURE__ */ React7.createElement(RotateCcw, { className: "w-3.5 h-3.5" })
|
|
582
|
+
), onMaximize && /* @__PURE__ */ React7.createElement(
|
|
436
583
|
"button",
|
|
437
584
|
{
|
|
438
585
|
onClick: onMaximize,
|
|
439
586
|
title: isMaximized ? "Minimize" : "Maximize",
|
|
440
587
|
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
588
|
},
|
|
442
|
-
isMaximized ? /* @__PURE__ */
|
|
443
|
-
), showClose && onClose && /* @__PURE__ */
|
|
589
|
+
isMaximized ? /* @__PURE__ */ React7.createElement(Minimize2, { className: "w-3.5 h-3.5" }) : /* @__PURE__ */ React7.createElement(Maximize2, { className: "w-3.5 h-3.5" })
|
|
590
|
+
), showClose && onClose && /* @__PURE__ */ React7.createElement(
|
|
444
591
|
"button",
|
|
445
592
|
{
|
|
446
593
|
onClick: onClose,
|
|
447
594
|
title: "Close chat",
|
|
448
595
|
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
596
|
},
|
|
450
|
-
/* @__PURE__ */
|
|
597
|
+
/* @__PURE__ */ React7.createElement(X, { className: "w-4 h-4" })
|
|
451
598
|
)))
|
|
452
599
|
),
|
|
453
|
-
/* @__PURE__ */
|
|
600
|
+
/* @__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
601
|
/* Welcome state */
|
|
455
|
-
/* @__PURE__ */
|
|
602
|
+
/* @__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
603
|
"div",
|
|
457
604
|
{
|
|
458
605
|
className: `w-16 h-16 flex items-center justify-center shadow-lg ${ui.borderRadius === "full" ? "rounded-full" : "rounded-2xl"}`,
|
|
459
606
|
style: { background: `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` }
|
|
460
607
|
},
|
|
461
|
-
/* @__PURE__ */
|
|
462
|
-
), /* @__PURE__ */
|
|
463
|
-
(suggestion) => /* @__PURE__ */
|
|
608
|
+
/* @__PURE__ */ React7.createElement(Sparkles, { className: "w-8 h-8 text-white" })
|
|
609
|
+
), /* @__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(
|
|
610
|
+
(suggestion) => /* @__PURE__ */ React7.createElement(
|
|
464
611
|
"button",
|
|
465
612
|
{
|
|
466
613
|
key: suggestion,
|
|
@@ -474,7 +621,7 @@ function ChatWindow({
|
|
|
474
621
|
suggestion
|
|
475
622
|
)
|
|
476
623
|
)))
|
|
477
|
-
) : messages.map((msg, index) => /* @__PURE__ */
|
|
624
|
+
) : messages.map((msg, index) => /* @__PURE__ */ React7.createElement(
|
|
478
625
|
MessageBubble,
|
|
479
626
|
{
|
|
480
627
|
key: msg.id,
|
|
@@ -484,7 +631,7 @@ function ChatWindow({
|
|
|
484
631
|
primaryColor: ui.primaryColor,
|
|
485
632
|
accentColor: ui.accentColor
|
|
486
633
|
}
|
|
487
|
-
)), isLoading && ((_a = messages[messages.length - 1]) == null ? void 0 : _a.role) !== "assistant" && /* @__PURE__ */
|
|
634
|
+
)), isLoading && ((_a = messages[messages.length - 1]) == null ? void 0 : _a.role) !== "assistant" && /* @__PURE__ */ React7.createElement(
|
|
488
635
|
MessageBubble,
|
|
489
636
|
{
|
|
490
637
|
message: { role: "assistant", content: "" },
|
|
@@ -492,8 +639,8 @@ function ChatWindow({
|
|
|
492
639
|
primaryColor: ui.primaryColor,
|
|
493
640
|
accentColor: ui.accentColor
|
|
494
641
|
}
|
|
495
|
-
), error && /* @__PURE__ */
|
|
496
|
-
/* @__PURE__ */
|
|
642
|
+
), 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 })),
|
|
643
|
+
/* @__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
644
|
"textarea",
|
|
498
645
|
{
|
|
499
646
|
ref: inputRef,
|
|
@@ -506,7 +653,7 @@ function ChatWindow({
|
|
|
506
653
|
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
654
|
style: { scrollbarWidth: "none" }
|
|
508
655
|
}
|
|
509
|
-
), /* @__PURE__ */
|
|
656
|
+
), /* @__PURE__ */ React7.createElement(
|
|
510
657
|
"button",
|
|
511
658
|
{
|
|
512
659
|
onClick: sendMessage,
|
|
@@ -517,8 +664,8 @@ function ChatWindow({
|
|
|
517
664
|
// slate-400/20 for light mode disabled
|
|
518
665
|
}
|
|
519
666
|
},
|
|
520
|
-
/* @__PURE__ */
|
|
521
|
-
)), /* @__PURE__ */
|
|
667
|
+
/* @__PURE__ */ React7.createElement(ArrowUp, { className: "w-4 h-4 text-white" })
|
|
668
|
+
)), /* @__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
669
|
);
|
|
523
670
|
}
|
|
524
671
|
|
|
@@ -581,7 +728,7 @@ function ChatWidget({ position = "bottom-right" }) {
|
|
|
581
728
|
}
|
|
582
729
|
};
|
|
583
730
|
const isResized = dimensions.width !== DEFAULT_DIMENSIONS.width || dimensions.height !== DEFAULT_DIMENSIONS.height;
|
|
584
|
-
return /* @__PURE__ */
|
|
731
|
+
return /* @__PURE__ */ React8.createElement(React8.Fragment, null, /* @__PURE__ */ React8.createElement(
|
|
585
732
|
"div",
|
|
586
733
|
{
|
|
587
734
|
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 +738,7 @@ function ChatWidget({ position = "bottom-right" }) {
|
|
|
591
738
|
maxHeight: "calc(100vh - 6rem)"
|
|
592
739
|
}
|
|
593
740
|
},
|
|
594
|
-
/* @__PURE__ */
|
|
741
|
+
/* @__PURE__ */ React8.createElement(
|
|
595
742
|
ChatWindow,
|
|
596
743
|
{
|
|
597
744
|
className: "h-full relative z-10",
|
|
@@ -604,13 +751,13 @@ function ChatWidget({ position = "bottom-right" }) {
|
|
|
604
751
|
isMaximized
|
|
605
752
|
}
|
|
606
753
|
),
|
|
607
|
-
/* @__PURE__ */
|
|
754
|
+
/* @__PURE__ */ React8.createElement(
|
|
608
755
|
"div",
|
|
609
756
|
{
|
|
610
757
|
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
758
|
}
|
|
612
759
|
)
|
|
613
|
-
), /* @__PURE__ */
|
|
760
|
+
), /* @__PURE__ */ React8.createElement(
|
|
614
761
|
"button",
|
|
615
762
|
{
|
|
616
763
|
onClick: isOpen ? () => setIsOpen(false) : handleOpen,
|
|
@@ -618,32 +765,32 @@ function ChatWidget({ position = "bottom-right" }) {
|
|
|
618
765
|
style: { background: `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` },
|
|
619
766
|
"aria-label": "Open chat"
|
|
620
767
|
},
|
|
621
|
-
/* @__PURE__ */
|
|
768
|
+
/* @__PURE__ */ React8.createElement(
|
|
622
769
|
"span",
|
|
623
770
|
{
|
|
624
771
|
className: "absolute inset-0 rounded-full animate-ping opacity-20",
|
|
625
772
|
style: { background: ui.primaryColor }
|
|
626
773
|
}
|
|
627
774
|
),
|
|
628
|
-
/* @__PURE__ */
|
|
775
|
+
/* @__PURE__ */ React8.createElement(
|
|
629
776
|
"span",
|
|
630
777
|
{
|
|
631
778
|
className: `transition-transform duration-300 ${isOpen ? "rotate-90 scale-90" : "rotate-0 scale-100"}`
|
|
632
779
|
},
|
|
633
|
-
isOpen ? /* @__PURE__ */
|
|
780
|
+
isOpen ? /* @__PURE__ */ React8.createElement(X2, { className: "w-6 h-6 text-white" }) : /* @__PURE__ */ React8.createElement(MessageSquare, { className: "w-6 h-6 text-white" })
|
|
634
781
|
),
|
|
635
|
-
hasUnread && !isOpen && /* @__PURE__ */
|
|
782
|
+
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
783
|
));
|
|
637
784
|
}
|
|
638
785
|
|
|
639
786
|
// src/components/DocumentUpload.tsx
|
|
640
|
-
import
|
|
787
|
+
import React9, { useState as useState5, useRef as useRef4 } from "react";
|
|
641
788
|
import { Upload, File, X as X3, CheckCircle, AlertCircle, Loader2 } from "lucide-react";
|
|
642
789
|
function DocumentUpload({ namespace, onUploadComplete, className = "" }) {
|
|
643
790
|
const { ui } = useConfig();
|
|
644
791
|
const [fileStates, setFileStates] = useState5([]);
|
|
645
792
|
const [isDragging, setIsDragging] = useState5(false);
|
|
646
|
-
const fileInputRef =
|
|
793
|
+
const fileInputRef = useRef4(null);
|
|
647
794
|
const addFiles = (files) => {
|
|
648
795
|
const newStates = files.map((file) => ({ file, status: "idle" }));
|
|
649
796
|
setFileStates((prev) => [...prev, ...newStates]);
|
|
@@ -693,7 +840,7 @@ function DocumentUpload({ namespace, onUploadComplete, className = "" }) {
|
|
|
693
840
|
};
|
|
694
841
|
const isUploading = fileStates.some((s) => s.status === "uploading");
|
|
695
842
|
const hasIdle = fileStates.some((s) => s.status === "idle");
|
|
696
|
-
return /* @__PURE__ */
|
|
843
|
+
return /* @__PURE__ */ React9.createElement(
|
|
697
844
|
"div",
|
|
698
845
|
{
|
|
699
846
|
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 +848,14 @@ function DocumentUpload({ namespace, onUploadComplete, className = "" }) {
|
|
|
701
848
|
onDragLeave,
|
|
702
849
|
onDrop
|
|
703
850
|
},
|
|
704
|
-
/* @__PURE__ */
|
|
851
|
+
/* @__PURE__ */ React9.createElement("div", { className: "flex flex-col items-center justify-center text-center" }, /* @__PURE__ */ React9.createElement(
|
|
705
852
|
"div",
|
|
706
853
|
{
|
|
707
854
|
className: "w-12 h-12 rounded-full flex items-center justify-center mb-4 shadow-sm",
|
|
708
855
|
style: { background: `linear-gradient(135deg, ${ui.primaryColor}20, ${ui.accentColor}20)` }
|
|
709
856
|
},
|
|
710
|
-
/* @__PURE__ */
|
|
711
|
-
), /* @__PURE__ */
|
|
857
|
+
/* @__PURE__ */ React9.createElement(Upload, { className: "w-6 h-6", style: { color: ui.primaryColor } })
|
|
858
|
+
), /* @__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
859
|
"button",
|
|
713
860
|
{
|
|
714
861
|
onClick: () => {
|
|
@@ -724,7 +871,7 @@ function DocumentUpload({ namespace, onUploadComplete, className = "" }) {
|
|
|
724
871
|
}
|
|
725
872
|
},
|
|
726
873
|
"Select Files"
|
|
727
|
-
), /* @__PURE__ */
|
|
874
|
+
), /* @__PURE__ */ React9.createElement(
|
|
728
875
|
"input",
|
|
729
876
|
{
|
|
730
877
|
ref: fileInputRef,
|
|
@@ -735,22 +882,22 @@ function DocumentUpload({ namespace, onUploadComplete, className = "" }) {
|
|
|
735
882
|
accept: ".pdf,.docx,.txt,.md,.json,.csv"
|
|
736
883
|
}
|
|
737
884
|
)),
|
|
738
|
-
fileStates.length > 0 && /* @__PURE__ */
|
|
885
|
+
fileStates.length > 0 && /* @__PURE__ */ React9.createElement("div", { className: "mt-8 space-y-3" }, fileStates.map((state, i) => /* @__PURE__ */ React9.createElement(
|
|
739
886
|
"div",
|
|
740
887
|
{
|
|
741
888
|
key: i,
|
|
742
889
|
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
890
|
},
|
|
744
|
-
/* @__PURE__ */
|
|
745
|
-
/* @__PURE__ */
|
|
891
|
+
/* @__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"))),
|
|
892
|
+
/* @__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
893
|
"button",
|
|
747
894
|
{
|
|
748
895
|
onClick: () => removeFile(i),
|
|
749
896
|
className: "p-1 rounded-md hover:bg-slate-200 dark:hover:bg-white/10 transition-colors"
|
|
750
897
|
},
|
|
751
|
-
/* @__PURE__ */
|
|
898
|
+
/* @__PURE__ */ React9.createElement(X3, { className: "w-3.5 h-3.5 text-slate-400" })
|
|
752
899
|
))
|
|
753
|
-
)), hasIdle && !isUploading && /* @__PURE__ */
|
|
900
|
+
)), hasIdle && !isUploading && /* @__PURE__ */ React9.createElement(
|
|
754
901
|
"button",
|
|
755
902
|
{
|
|
756
903
|
onClick: uploadFiles,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@retrivora-ai/rag-engine",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.6",
|
|
4
4
|
"description": "Retrivora AI is a plug-and-play AI engine for RAG chat experiences — generic vector DB + LLM provider, embeddable or standalone.",
|
|
5
5
|
"author": "Abhinav Alkuchi",
|
|
6
6
|
"license": "MIT",
|
package/src/app/globals.css
CHANGED
|
@@ -65,6 +65,15 @@ body {
|
|
|
65
65
|
background: rgba(255, 255, 255, 0.2);
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
+
.scrollbar-hide::-webkit-scrollbar {
|
|
69
|
+
display: none;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.scrollbar-hide {
|
|
73
|
+
-ms-overflow-style: none;
|
|
74
|
+
scrollbar-width: none;
|
|
75
|
+
}
|
|
76
|
+
|
|
68
77
|
/* ─── Prose Overrides (markdown in chat) ───────────────────── */
|
|
69
78
|
.prose-invert {
|
|
70
79
|
color: inherit;
|