@mnexium/chat-react 1.0.0

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.mjs ADDED
@@ -0,0 +1,589 @@
1
+ "use client";
2
+
3
+ // src/client/MnexiumChat.tsx
4
+ import { useState, useEffect, useRef, useCallback } from "react";
5
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
6
+ var themes = {
7
+ dark: {
8
+ bg: "#1a1a1a",
9
+ bgSecondary: "#2a2a2a",
10
+ border: "#333",
11
+ text: "#fff",
12
+ textSecondary: "#e5e5e5",
13
+ textMuted: "#888",
14
+ inputBg: "#2a2a2a",
15
+ inputBorder: "#444",
16
+ codeBg: "#374151",
17
+ codeBlockBg: "#1f2937"
18
+ },
19
+ light: {
20
+ bg: "#ffffff",
21
+ bgSecondary: "#f3f4f6",
22
+ border: "#e5e7eb",
23
+ text: "#111827",
24
+ textSecondary: "#374151",
25
+ textMuted: "#6b7280",
26
+ inputBg: "#f9fafb",
27
+ inputBorder: "#d1d5db",
28
+ codeBg: "#e5e7eb",
29
+ codeBlockBg: "#f3f4f6"
30
+ }
31
+ };
32
+ function generateId() {
33
+ return Math.random().toString(36).substring(2, 15);
34
+ }
35
+ function renderMarkdown(text, themeColors) {
36
+ if (!text) return null;
37
+ const lines = text.split("\n");
38
+ const elements = [];
39
+ let inCodeBlock = false;
40
+ let codeContent = [];
41
+ const processInline = (line) => {
42
+ const parts = [];
43
+ let remaining = line;
44
+ let key = 0;
45
+ while (remaining.length > 0) {
46
+ const codeMatch = remaining.match(/`([^`]+)`/);
47
+ const boldMatch = remaining.match(/\*\*([^*]+)\*\*/);
48
+ const italicMatch = remaining.match(/\*([^*]+)\*/);
49
+ const matches = [
50
+ codeMatch ? { type: "code", match: codeMatch, index: codeMatch.index } : null,
51
+ boldMatch ? { type: "bold", match: boldMatch, index: boldMatch.index } : null,
52
+ italicMatch ? { type: "italic", match: italicMatch, index: italicMatch.index } : null
53
+ ].filter(Boolean).sort((a, b) => a.index - b.index);
54
+ if (matches.length === 0) {
55
+ parts.push(remaining);
56
+ break;
57
+ }
58
+ const first = matches[0];
59
+ if (first.index > 0) {
60
+ parts.push(remaining.substring(0, first.index));
61
+ }
62
+ if (first.type === "code") {
63
+ parts.push(
64
+ /* @__PURE__ */ jsx("code", { style: { backgroundColor: themeColors.codeBg, padding: "2px 6px", borderRadius: "4px", fontSize: "13px" }, children: first.match[1] }, key++)
65
+ );
66
+ } else if (first.type === "bold") {
67
+ parts.push(/* @__PURE__ */ jsx("strong", { children: first.match[1] }, key++));
68
+ } else if (first.type === "italic") {
69
+ parts.push(/* @__PURE__ */ jsx("em", { children: first.match[1] }, key++));
70
+ }
71
+ remaining = remaining.substring(first.index + first.match[0].length);
72
+ }
73
+ return parts.length === 1 ? parts[0] : parts;
74
+ };
75
+ for (let i = 0; i < lines.length; i++) {
76
+ const line = lines[i];
77
+ if (line.startsWith("```")) {
78
+ if (!inCodeBlock) {
79
+ inCodeBlock = true;
80
+ codeContent = [];
81
+ } else {
82
+ elements.push(
83
+ /* @__PURE__ */ jsx("pre", { style: { backgroundColor: themeColors.codeBlockBg, padding: "12px", borderRadius: "8px", overflow: "auto", fontSize: "13px", margin: "8px 0" }, children: /* @__PURE__ */ jsx("code", { children: codeContent.join("\n") }) }, i)
84
+ );
85
+ inCodeBlock = false;
86
+ }
87
+ continue;
88
+ }
89
+ if (inCodeBlock) {
90
+ codeContent.push(line);
91
+ continue;
92
+ }
93
+ if (line.startsWith("### ")) {
94
+ elements.push(/* @__PURE__ */ jsx("h4", { style: { margin: "12px 0 8px", fontSize: "14px", fontWeight: 600 }, children: processInline(line.slice(4)) }, i));
95
+ } else if (line.startsWith("## ")) {
96
+ elements.push(/* @__PURE__ */ jsx("h3", { style: { margin: "12px 0 8px", fontSize: "15px", fontWeight: 600 }, children: processInline(line.slice(3)) }, i));
97
+ } else if (line.startsWith("# ")) {
98
+ elements.push(/* @__PURE__ */ jsx("h2", { style: { margin: "12px 0 8px", fontSize: "16px", fontWeight: 600 }, children: processInline(line.slice(2)) }, i));
99
+ } else if (line.startsWith("- ") || line.startsWith("* ")) {
100
+ elements.push(/* @__PURE__ */ jsx("li", { style: { marginLeft: "16px", listStyleType: "disc" }, children: processInline(line.slice(2)) }, i));
101
+ } else if (/^\d+\.\s/.test(line)) {
102
+ const content = line.replace(/^\d+\.\s/, "");
103
+ elements.push(/* @__PURE__ */ jsx("li", { style: { marginLeft: "16px", listStyleType: "decimal" }, children: processInline(content) }, i));
104
+ } else if (line.trim() === "") {
105
+ elements.push(/* @__PURE__ */ jsx("br", {}, i));
106
+ } else {
107
+ elements.push(/* @__PURE__ */ jsx("p", { style: { margin: "4px 0" }, children: processInline(line) }, i));
108
+ }
109
+ }
110
+ if (inCodeBlock && codeContent.length > 0) {
111
+ elements.push(
112
+ /* @__PURE__ */ jsx("pre", { style: { backgroundColor: themeColors.codeBlockBg, padding: "12px", borderRadius: "8px", overflow: "auto", fontSize: "13px", margin: "8px 0" }, children: /* @__PURE__ */ jsx("code", { children: codeContent.join("\n") }) }, "final-code")
113
+ );
114
+ }
115
+ return /* @__PURE__ */ jsx("div", { children: elements });
116
+ }
117
+ function MnexiumChat({
118
+ endpoint = "/api/mnx",
119
+ placeholder = "Type a message...",
120
+ title = "Ask AI",
121
+ buttonLabel = "Ask AI",
122
+ position = "bottom-right",
123
+ primaryColor = "#facc15",
124
+ defaultOpen = false,
125
+ logo,
126
+ theme = "dark",
127
+ welcomeIcon = "\u{1F44B}",
128
+ welcomeMessage = "How can I help you today?",
129
+ history = false,
130
+ eagerInit = true
131
+ }) {
132
+ const t = themes[theme];
133
+ const [isOpen, setIsOpen] = useState(defaultOpen);
134
+ const [messages, setMessages] = useState([]);
135
+ const [input, setInput] = useState("");
136
+ const [isLoading, setIsLoading] = useState(false);
137
+ const [isStreaming, setIsStreaming] = useState(false);
138
+ const [isInitialized, setIsInitialized] = useState(false);
139
+ const [error, setError] = useState(null);
140
+ const messagesEndRef = useRef(null);
141
+ const inputRef = useRef(null);
142
+ const scrollToBottom = useCallback(() => {
143
+ messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
144
+ }, []);
145
+ useEffect(() => {
146
+ scrollToBottom();
147
+ }, [messages, scrollToBottom]);
148
+ useEffect(() => {
149
+ if (isOpen && inputRef.current) {
150
+ inputRef.current.focus();
151
+ }
152
+ }, [isOpen]);
153
+ useEffect(() => {
154
+ if (!eagerInit && !isOpen) return;
155
+ const bootstrap = async () => {
156
+ if (isInitialized) return;
157
+ try {
158
+ const res = await fetch(`${endpoint}/bootstrap`);
159
+ if (!res.ok) throw new Error("Failed to bootstrap");
160
+ const data = await res.json();
161
+ if (history && data.chat_id) {
162
+ try {
163
+ const historyRes = await fetch(`${endpoint}/conversations/${data.chat_id}`);
164
+ if (historyRes.ok) {
165
+ const historyData = await historyRes.json();
166
+ if (historyData.messages && Array.isArray(historyData.messages)) {
167
+ setMessages(historyData.messages.map((m) => ({
168
+ id: generateId(),
169
+ role: m.role,
170
+ content: m.content,
171
+ timestamp: /* @__PURE__ */ new Date()
172
+ })));
173
+ }
174
+ }
175
+ } catch {
176
+ }
177
+ }
178
+ setIsInitialized(true);
179
+ } catch (err) {
180
+ setError("Failed to initialize chat");
181
+ console.error("Bootstrap error:", err);
182
+ }
183
+ };
184
+ bootstrap();
185
+ }, [endpoint, isOpen, isInitialized, history, eagerInit]);
186
+ const sendMessage = async () => {
187
+ if (!input.trim() || isLoading || isStreaming) return;
188
+ const userMessage = {
189
+ id: generateId(),
190
+ role: "user",
191
+ content: input.trim(),
192
+ timestamp: /* @__PURE__ */ new Date()
193
+ };
194
+ setMessages((prev) => [...prev, userMessage]);
195
+ setInput("");
196
+ setIsLoading(true);
197
+ setError(null);
198
+ const assistantMessageId = generateId();
199
+ try {
200
+ const res = await fetch(`${endpoint}/chat`, {
201
+ method: "POST",
202
+ headers: { "Content-Type": "application/json" },
203
+ body: JSON.stringify({ message: userMessage.content })
204
+ });
205
+ if (!res.ok) throw new Error("Failed to send message");
206
+ if (!res.body) throw new Error("No response body");
207
+ setIsLoading(false);
208
+ setIsStreaming(true);
209
+ const assistantMessage = {
210
+ id: assistantMessageId,
211
+ role: "assistant",
212
+ content: "",
213
+ timestamp: /* @__PURE__ */ new Date()
214
+ };
215
+ setMessages((prev) => [...prev, assistantMessage]);
216
+ const reader = res.body.getReader();
217
+ const decoder = new TextDecoder();
218
+ let buffer = "";
219
+ while (true) {
220
+ const { done, value } = await reader.read();
221
+ if (done) break;
222
+ buffer += decoder.decode(value, { stream: true });
223
+ const lines = buffer.split("\n");
224
+ buffer = lines.pop() || "";
225
+ for (const line of lines) {
226
+ if (line.startsWith("data: ")) {
227
+ const data = line.slice(6);
228
+ if (data === "[DONE]") continue;
229
+ try {
230
+ const parsed = JSON.parse(data);
231
+ const content = parsed.choices?.[0]?.delta?.content;
232
+ if (content) {
233
+ setMessages(
234
+ (prev) => prev.map(
235
+ (m) => m.id === assistantMessageId ? { ...m, content: m.content + content } : m
236
+ )
237
+ );
238
+ }
239
+ } catch {
240
+ }
241
+ }
242
+ }
243
+ }
244
+ if (buffer.startsWith("data: ")) {
245
+ const data = buffer.slice(6);
246
+ if (data !== "[DONE]") {
247
+ try {
248
+ const parsed = JSON.parse(data);
249
+ const content = parsed.choices?.[0]?.delta?.content;
250
+ if (content) {
251
+ setMessages(
252
+ (prev) => prev.map(
253
+ (m) => m.id === assistantMessageId ? { ...m, content: m.content + content } : m
254
+ )
255
+ );
256
+ }
257
+ } catch {
258
+ }
259
+ }
260
+ }
261
+ } catch (err) {
262
+ setError("Failed to send message");
263
+ console.error("Chat error:", err);
264
+ setMessages((prev) => prev.filter((m) => m.id !== assistantMessageId));
265
+ } finally {
266
+ setIsLoading(false);
267
+ setIsStreaming(false);
268
+ requestAnimationFrame(() => {
269
+ inputRef.current?.focus();
270
+ });
271
+ }
272
+ };
273
+ const handleKeyDown = (e) => {
274
+ if (e.key === "Enter" && !e.shiftKey) {
275
+ e.preventDefault();
276
+ sendMessage();
277
+ }
278
+ };
279
+ const startNewChat = async () => {
280
+ try {
281
+ const res = await fetch(`${endpoint}/new-chat`, { method: "POST" });
282
+ if (res.ok) {
283
+ setMessages([]);
284
+ }
285
+ } catch {
286
+ setMessages([]);
287
+ }
288
+ };
289
+ const positionStyles = position === "bottom-right" ? { right: "20px", bottom: "20px" } : { left: "20px", bottom: "20px" };
290
+ const chatPositionStyles = position === "bottom-right" ? { right: "0", bottom: "60px" } : { left: "0", bottom: "60px" };
291
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
292
+ /* @__PURE__ */ jsx("style", { children: `
293
+ @keyframes mnx-typing {
294
+ 0%, 80%, 100% { transform: scale(0.8); opacity: 0.5; }
295
+ 40% { transform: scale(1); opacity: 1; }
296
+ }
297
+ @keyframes mnx-fade-in {
298
+ from { opacity: 0; transform: translateY(10px) scale(0.95); }
299
+ to { opacity: 1; transform: translateY(0) scale(1); }
300
+ }
301
+ @keyframes mnx-fade-out {
302
+ from { opacity: 1; transform: translateY(0) scale(1); }
303
+ to { opacity: 0; transform: translateY(10px) scale(0.95); }
304
+ }
305
+ @keyframes mnx-pulse {
306
+ 0% { box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); }
307
+ 50% { box-shadow: 0 4px 20px rgba(0, 0, 0, 0.4); }
308
+ 100% { box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); }
309
+ }
310
+ .mnx-typing-dot:nth-child(1) { animation-delay: 0s; }
311
+ .mnx-typing-dot:nth-child(2) { animation-delay: 0.2s; }
312
+ .mnx-typing-dot:nth-child(3) { animation-delay: 0.4s; }
313
+ .mnx-btn-icon {
314
+ transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
315
+ }
316
+ .mnx-btn-icon.open {
317
+ transform: rotate(45deg);
318
+ }
319
+ ` }),
320
+ /* @__PURE__ */ jsxs("div", { style: {
321
+ position: "fixed",
322
+ zIndex: 9999,
323
+ fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
324
+ ...positionStyles
325
+ }, children: [
326
+ isOpen && /* @__PURE__ */ jsxs("div", { style: {
327
+ position: "absolute",
328
+ ...chatPositionStyles,
329
+ width: "380px",
330
+ height: "500px",
331
+ backgroundColor: theme === "dark" ? "rgba(26, 26, 26, 0.9)" : "rgba(255, 255, 255, 0.9)",
332
+ backdropFilter: "blur(8px) saturate(180%)",
333
+ WebkitBackdropFilter: "blur(16px) saturate(180%)",
334
+ borderRadius: "16px",
335
+ border: `1px solid ${primaryColor}33`,
336
+ boxShadow: theme === "dark" ? "0 25px 50px -12px rgba(0, 0, 0, 0.5)" : "0 25px 50px -12px rgba(0, 0, 0, 0.15)",
337
+ display: "flex",
338
+ flexDirection: "column",
339
+ overflow: "hidden",
340
+ animation: "mnx-fade-in 0.2s ease-out",
341
+ transform: "translateZ(0)",
342
+ isolation: "isolate"
343
+ }, children: [
344
+ /* @__PURE__ */ jsxs("div", { style: {
345
+ display: "flex",
346
+ alignItems: "center",
347
+ justifyContent: "space-between",
348
+ padding: "8px 8px",
349
+ borderBottom: `1px solid ${t.border}`,
350
+ backgroundColor: theme === "dark" ? "rgba(26, 26, 26, 0.7)" : "rgba(255, 255, 255, 0.7)"
351
+ }, children: [
352
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: "10px" }, children: [
353
+ /* @__PURE__ */ jsx("div", { style: {
354
+ width: "32px",
355
+ height: "32px",
356
+ backgroundColor: primaryColor,
357
+ borderRadius: "8px",
358
+ display: "flex",
359
+ alignItems: "center",
360
+ justifyContent: "center",
361
+ overflow: "hidden"
362
+ }, children: logo ? /* @__PURE__ */ jsx("img", { src: logo, alt: "", style: { width: "100%", height: "100%", objectFit: "cover" } }) : /* @__PURE__ */ jsxs("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "#000", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
363
+ /* @__PURE__ */ jsx("path", { d: "M12 2L2 7l10 5 10-5-10-5z" }),
364
+ /* @__PURE__ */ jsx("path", { d: "M2 17l10 5 10-5" }),
365
+ /* @__PURE__ */ jsx("path", { d: "M2 12l10 5 10-5" })
366
+ ] }) }),
367
+ /* @__PURE__ */ jsx("span", { style: { color: t.text, fontWeight: 600, fontSize: "15px" }, children: title })
368
+ ] }),
369
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: "4px" }, children: [
370
+ /* @__PURE__ */ jsx(
371
+ "button",
372
+ {
373
+ onClick: startNewChat,
374
+ style: {
375
+ background: "none",
376
+ border: "none",
377
+ color: t.textMuted,
378
+ cursor: "pointer",
379
+ padding: "6px",
380
+ borderRadius: "6px",
381
+ display: "flex",
382
+ alignItems: "center",
383
+ justifyContent: "center"
384
+ },
385
+ title: "New chat",
386
+ children: /* @__PURE__ */ jsxs("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
387
+ /* @__PURE__ */ jsx("line", { x1: "12", y1: "5", x2: "12", y2: "19" }),
388
+ /* @__PURE__ */ jsx("line", { x1: "5", y1: "12", x2: "19", y2: "12" })
389
+ ] })
390
+ }
391
+ ),
392
+ /* @__PURE__ */ jsx(
393
+ "button",
394
+ {
395
+ onClick: () => setIsOpen(false),
396
+ style: {
397
+ background: "none",
398
+ border: "none",
399
+ color: t.textMuted,
400
+ cursor: "pointer",
401
+ padding: "4px",
402
+ display: "flex",
403
+ alignItems: "center",
404
+ justifyContent: "center"
405
+ },
406
+ children: /* @__PURE__ */ jsxs("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
407
+ /* @__PURE__ */ jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
408
+ /* @__PURE__ */ jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
409
+ ] })
410
+ }
411
+ )
412
+ ] })
413
+ ] }),
414
+ /* @__PURE__ */ jsxs("div", { style: {
415
+ flex: 1,
416
+ overflowY: "auto",
417
+ padding: "8px 8px",
418
+ display: "flex",
419
+ flexDirection: "column",
420
+ gap: "12px"
421
+ }, children: [
422
+ !isInitialized && !error && /* @__PURE__ */ jsx("div", { style: { display: "flex", alignItems: "center", justifyContent: "center", height: "100%", color: t.textMuted }, children: "Initializing..." }),
423
+ error && /* @__PURE__ */ jsx("div", { style: { display: "flex", alignItems: "center", justifyContent: "center", height: "100%", color: "#ef4444" }, children: error }),
424
+ isInitialized && messages.length === 0 && !error && /* @__PURE__ */ jsx("div", { style: { display: "flex", alignItems: "center", justifyContent: "center", height: "100%", color: t.textMuted, textAlign: "center" }, children: /* @__PURE__ */ jsxs("div", { children: [
425
+ /* @__PURE__ */ jsx("div", { style: { fontSize: "24px", marginBottom: "8px" }, children: welcomeIcon }),
426
+ /* @__PURE__ */ jsx("div", { children: welcomeMessage })
427
+ ] }) }),
428
+ messages.map((message) => /* @__PURE__ */ jsx(
429
+ "div",
430
+ {
431
+ style: {
432
+ maxWidth: "85%",
433
+ padding: "10px 14px",
434
+ borderRadius: "12px",
435
+ fontSize: "14px",
436
+ lineHeight: 1.5,
437
+ wordBreak: "break-word",
438
+ ...message.role === "user" ? {
439
+ alignSelf: "flex-end",
440
+ backgroundColor: `${primaryColor}cc`,
441
+ color: "#000",
442
+ borderBottomRightRadius: "4px"
443
+ } : {
444
+ alignSelf: "flex-start",
445
+ backgroundColor: theme === "dark" ? "rgba(42, 42, 42, 0.7)" : "rgba(243, 244, 246, 0.7)",
446
+ color: t.textSecondary,
447
+ borderBottomLeftRadius: "4px"
448
+ }
449
+ },
450
+ children: message.role === "assistant" ? renderMarkdown(message.content, { codeBg: t.codeBg, codeBlockBg: t.codeBlockBg }) : message.content
451
+ },
452
+ message.id
453
+ )),
454
+ isLoading && /* @__PURE__ */ jsxs("div", { style: {
455
+ display: "flex",
456
+ gap: "4px",
457
+ padding: "10px 14px",
458
+ alignSelf: "flex-start",
459
+ backgroundColor: theme === "dark" ? "rgba(42, 42, 42, 0.7)" : "rgba(243, 244, 246, 0.7)",
460
+ borderRadius: "12px",
461
+ borderBottomLeftRadius: "4px"
462
+ }, children: [
463
+ /* @__PURE__ */ jsx("div", { className: "mnx-typing-dot", style: { width: "6px", height: "6px", backgroundColor: t.textMuted, borderRadius: "50%", animation: "mnx-typing 1.4s infinite ease-in-out" } }),
464
+ /* @__PURE__ */ jsx("div", { className: "mnx-typing-dot", style: { width: "6px", height: "6px", backgroundColor: t.textMuted, borderRadius: "50%", animation: "mnx-typing 1.4s infinite ease-in-out" } }),
465
+ /* @__PURE__ */ jsx("div", { className: "mnx-typing-dot", style: { width: "6px", height: "6px", backgroundColor: t.textMuted, borderRadius: "50%", animation: "mnx-typing 1.4s infinite ease-in-out" } })
466
+ ] }),
467
+ /* @__PURE__ */ jsx("div", { ref: messagesEndRef })
468
+ ] }),
469
+ /* @__PURE__ */ jsxs("div", { style: {
470
+ display: "flex",
471
+ gap: "8px",
472
+ padding: "8px 8px",
473
+ borderTop: `1px solid ${t.border}`,
474
+ backgroundColor: theme === "dark" ? "rgba(26, 26, 26, 0.5)" : "rgba(255, 255, 255, 0.5)"
475
+ }, children: [
476
+ /* @__PURE__ */ jsx(
477
+ "input",
478
+ {
479
+ ref: inputRef,
480
+ type: "text",
481
+ value: input,
482
+ onChange: (e) => setInput(e.target.value),
483
+ onKeyDown: handleKeyDown,
484
+ placeholder,
485
+ disabled: !isInitialized || isLoading || isStreaming,
486
+ style: {
487
+ flex: 1,
488
+ padding: "10px 14px",
489
+ backgroundColor: theme === "dark" ? "rgba(42, 42, 42, 0.6)" : "rgba(249, 250, 251, 0.6)",
490
+ border: "none",
491
+ borderRadius: "8px",
492
+ fontSize: "14px",
493
+ color: t.text,
494
+ outline: "none",
495
+ transition: "box-shadow 0.15s ease"
496
+ },
497
+ onFocus: (e) => {
498
+ e.currentTarget.style.boxShadow = `0 0 0 2px ${primaryColor}`;
499
+ },
500
+ onBlur: (e) => {
501
+ e.currentTarget.style.boxShadow = "none";
502
+ }
503
+ }
504
+ ),
505
+ /* @__PURE__ */ jsx(
506
+ "button",
507
+ {
508
+ onClick: sendMessage,
509
+ disabled: !isInitialized || !input.trim() || isLoading || isStreaming,
510
+ style: {
511
+ padding: "10px 16px",
512
+ backgroundColor: !isInitialized || !input.trim() || isLoading || isStreaming ? t.inputBorder : primaryColor,
513
+ color: "#000",
514
+ border: "none",
515
+ borderRadius: "8px",
516
+ fontSize: "14px",
517
+ fontWeight: 500,
518
+ cursor: !isInitialized || !input.trim() || isLoading || isStreaming ? "not-allowed" : "pointer",
519
+ display: "flex",
520
+ alignItems: "center",
521
+ justifyContent: "center"
522
+ },
523
+ children: /* @__PURE__ */ jsxs("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
524
+ /* @__PURE__ */ jsx("line", { x1: "22", y1: "2", x2: "11", y2: "13" }),
525
+ /* @__PURE__ */ jsx("polygon", { points: "22 2 15 22 11 13 2 9 22 2" })
526
+ ] })
527
+ }
528
+ )
529
+ ] })
530
+ ] }),
531
+ /* @__PURE__ */ jsxs(
532
+ "button",
533
+ {
534
+ onClick: () => setIsOpen(!isOpen),
535
+ style: {
536
+ display: "flex",
537
+ alignItems: "center",
538
+ gap: "8px",
539
+ padding: "12px 16px",
540
+ backgroundColor: primaryColor,
541
+ color: "#000",
542
+ border: "none",
543
+ borderRadius: "12px",
544
+ fontSize: "14px",
545
+ fontWeight: 600,
546
+ cursor: "pointer",
547
+ boxShadow: "0 4px 12px rgba(0, 0, 0, 0.3)",
548
+ transition: "all 0.3s cubic-bezier(0.4, 0, 0.2, 1)"
549
+ },
550
+ onMouseEnter: (e) => {
551
+ e.currentTarget.style.transform = "scale(1.05)";
552
+ e.currentTarget.style.boxShadow = "0 6px 20px rgba(0, 0, 0, 0.4)";
553
+ },
554
+ onMouseLeave: (e) => {
555
+ e.currentTarget.style.transform = "scale(1)";
556
+ e.currentTarget.style.boxShadow = "0 4px 12px rgba(0, 0, 0, 0.3)";
557
+ },
558
+ children: [
559
+ /* @__PURE__ */ jsx(
560
+ "span",
561
+ {
562
+ className: `mnx-btn-icon ${isOpen ? "open" : ""}`,
563
+ style: { display: "flex", alignItems: "center", justifyContent: "center" },
564
+ children: isOpen ? /* @__PURE__ */ jsxs("svg", { width: "28", height: "28", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
565
+ /* @__PURE__ */ jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
566
+ /* @__PURE__ */ jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
567
+ ] }) : logo ? /* @__PURE__ */ jsx("img", { src: logo, alt: "", style: { height: "28px", width: "auto", objectFit: "contain" } }) : /* @__PURE__ */ jsxs("svg", { width: "28", height: "28", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
568
+ /* @__PURE__ */ jsx("path", { d: "M12 2L2 7l10 5 10-5-10-5z" }),
569
+ /* @__PURE__ */ jsx("path", { d: "M2 17l10 5 10-5" }),
570
+ /* @__PURE__ */ jsx("path", { d: "M2 12l10 5 10-5" })
571
+ ] })
572
+ }
573
+ ),
574
+ /* @__PURE__ */ jsx("span", { style: {
575
+ transition: "opacity 0.2s, width 0.3s",
576
+ overflow: "hidden",
577
+ whiteSpace: "nowrap"
578
+ }, children: isOpen ? "Close" : buttonLabel })
579
+ ]
580
+ }
581
+ )
582
+ ] })
583
+ ] });
584
+ }
585
+ export {
586
+ MnexiumChat,
587
+ MnexiumChat as default
588
+ };
589
+ //# sourceMappingURL=index.mjs.map