aizek-chatbot 1.0.27 → 1.0.28
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.cjs +566 -99
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +475 -2
- package/dist/index.css.map +1 -1
- package/dist/index.mjs +565 -99
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -2
package/dist/index.mjs
CHANGED
|
@@ -2,8 +2,14 @@ import { useRef, useState, useEffect } from 'react';
|
|
|
2
2
|
import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
|
|
3
3
|
import ReactMarkdown from 'react-markdown';
|
|
4
4
|
import remarkGfm from 'remark-gfm';
|
|
5
|
+
import sanitizeHtml from 'sanitize-html';
|
|
5
6
|
|
|
6
|
-
// src/utils/
|
|
7
|
+
// src/utils/global.ts
|
|
8
|
+
var SESSION_TTL_MS = 60 * 60 * 1e3;
|
|
9
|
+
var MAX_SESSIONS = 3;
|
|
10
|
+
var DEVICE_KEY = "aizek_device_id_v1";
|
|
11
|
+
var ACTIVE_SESSION_KEY = "aizek_active_session_v1";
|
|
12
|
+
var LOCAL_SESSIONS_KEY = "aizek_sessions_v1";
|
|
7
13
|
function validateHeaders(headers, authConfig, opts = {}) {
|
|
8
14
|
if (headers && (!authConfig || Object.keys(authConfig).length === 0)) {
|
|
9
15
|
return {
|
|
@@ -32,6 +38,65 @@ function validateHeaders(headers, authConfig, opts = {}) {
|
|
|
32
38
|
const isValid = hasAllRequired && !hasExtraKeys && emptyValueKeys.length === 0;
|
|
33
39
|
return { isValid, missingKeys, extraKeys, emptyValueKeys };
|
|
34
40
|
}
|
|
41
|
+
function getOrCreateDeviceId() {
|
|
42
|
+
if (typeof window === "undefined") return "";
|
|
43
|
+
const existing = localStorage.getItem(DEVICE_KEY);
|
|
44
|
+
if (existing) return existing;
|
|
45
|
+
const id = crypto.randomUUID();
|
|
46
|
+
localStorage.setItem(DEVICE_KEY, id);
|
|
47
|
+
return id;
|
|
48
|
+
}
|
|
49
|
+
function now() {
|
|
50
|
+
return Date.now();
|
|
51
|
+
}
|
|
52
|
+
function readStoredSessions() {
|
|
53
|
+
try {
|
|
54
|
+
const raw = localStorage.getItem(LOCAL_SESSIONS_KEY);
|
|
55
|
+
const parsed = JSON.parse(raw ?? "[]");
|
|
56
|
+
if (!Array.isArray(parsed)) return [];
|
|
57
|
+
return parsed.filter((x) => x && typeof x.sessionId === "string" && typeof x.lastActive === "number").slice(0, MAX_SESSIONS);
|
|
58
|
+
} catch {
|
|
59
|
+
return [];
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
function writeStoredSessions(list) {
|
|
63
|
+
localStorage.setItem(LOCAL_SESSIONS_KEY, JSON.stringify(list.slice(0, MAX_SESSIONS)));
|
|
64
|
+
}
|
|
65
|
+
function purgeExpiredLocalSessions(setActiveSessionIdState) {
|
|
66
|
+
const list = readStoredSessions();
|
|
67
|
+
const filtered = list.filter((s) => now() - s.lastActive <= SESSION_TTL_MS);
|
|
68
|
+
if (filtered.length !== list.length) writeStoredSessions(filtered);
|
|
69
|
+
const active = getActiveSessionId();
|
|
70
|
+
if (active && !filtered.some((s) => s.sessionId === active)) {
|
|
71
|
+
setActiveSessionId(null);
|
|
72
|
+
setActiveSessionIdState(null);
|
|
73
|
+
}
|
|
74
|
+
return filtered;
|
|
75
|
+
}
|
|
76
|
+
function getActiveSessionId() {
|
|
77
|
+
return localStorage.getItem(ACTIVE_SESSION_KEY);
|
|
78
|
+
}
|
|
79
|
+
function setActiveSessionId(id) {
|
|
80
|
+
if (!id) localStorage.removeItem(ACTIVE_SESSION_KEY);
|
|
81
|
+
else localStorage.setItem(ACTIVE_SESSION_KEY, id);
|
|
82
|
+
}
|
|
83
|
+
function touchSession(sessionId) {
|
|
84
|
+
const list = readStoredSessions();
|
|
85
|
+
const next = list.map((s) => s.sessionId === sessionId ? { ...s, lastActive: now() } : s);
|
|
86
|
+
if (!next.some((s) => s.sessionId === sessionId)) next.unshift({ sessionId, lastActive: now() });
|
|
87
|
+
writeStoredSessions(next.slice(0, MAX_SESSIONS));
|
|
88
|
+
}
|
|
89
|
+
function upsertSessionsFromServer(serverSessionIds, setSessions) {
|
|
90
|
+
const local = readStoredSessions();
|
|
91
|
+
const map = new Map(local.map((s) => [s.sessionId, s.lastActive]));
|
|
92
|
+
const merged = serverSessionIds.slice(0, MAX_SESSIONS).map((sid) => ({
|
|
93
|
+
sessionId: sid,
|
|
94
|
+
lastActive: map.get(sid) ?? now()
|
|
95
|
+
}));
|
|
96
|
+
writeStoredSessions(merged);
|
|
97
|
+
setSessions(merged.map((x) => x.sessionId));
|
|
98
|
+
return merged;
|
|
99
|
+
}
|
|
35
100
|
var HeaderAlert = ({ headerValidation, showAlert, setShowAlert }) => {
|
|
36
101
|
if (!headerValidation || !showAlert) return null;
|
|
37
102
|
const { isValid, missingKeys, extraKeys, emptyValueKeys, warning } = headerValidation;
|
|
@@ -422,7 +487,17 @@ var extractUIJsonFromText = (text) => {
|
|
|
422
487
|
uiData
|
|
423
488
|
};
|
|
424
489
|
};
|
|
425
|
-
var AizekChatBot = ({
|
|
490
|
+
var AizekChatBot = ({
|
|
491
|
+
clientId,
|
|
492
|
+
headers,
|
|
493
|
+
onMounted,
|
|
494
|
+
onReady,
|
|
495
|
+
onOpen,
|
|
496
|
+
onClose,
|
|
497
|
+
onMessage,
|
|
498
|
+
onToolCall,
|
|
499
|
+
onDisconnect
|
|
500
|
+
}) => {
|
|
426
501
|
const messagesEndRef = useRef(null);
|
|
427
502
|
const [config, setConfig] = useState();
|
|
428
503
|
const [messages, setMessages] = useState([]);
|
|
@@ -431,77 +506,169 @@ var AizekChatBot = ({ clientId, headers, onMounted, onReady, onOpen, onClose, on
|
|
|
431
506
|
const [isOpen, setIsOpen] = useState(false);
|
|
432
507
|
const [headerValidation, setHeaderValidation] = useState(null);
|
|
433
508
|
const [showAlert, setShowAlert] = useState(true);
|
|
509
|
+
const [sessions, setSessions] = useState([]);
|
|
510
|
+
const [activeSessionId, setActiveSessionIdState] = useState(null);
|
|
511
|
+
const [activeTab, setActiveTab] = useState("home");
|
|
512
|
+
const [messageView, setMessageView] = useState("list");
|
|
434
513
|
const PROXY_BASE_URL = "https://proxy.aizek.ai/api";
|
|
514
|
+
const createNewSession = async () => {
|
|
515
|
+
const deviceId = getOrCreateDeviceId();
|
|
516
|
+
if (sessions.length >= MAX_SESSIONS) {
|
|
517
|
+
throw new Error(`You can open up to ${MAX_SESSIONS} sessions.`);
|
|
518
|
+
}
|
|
519
|
+
const res = await fetch(`${PROXY_BASE_URL}/aizek-sessions/new?clientId=${clientId}`, {
|
|
520
|
+
method: "POST",
|
|
521
|
+
headers: {
|
|
522
|
+
"Content-Type": "application/json",
|
|
523
|
+
"x-device-id": deviceId,
|
|
524
|
+
"x-alternate": JSON.stringify(headers)
|
|
525
|
+
}
|
|
526
|
+
});
|
|
527
|
+
const data = await res.json();
|
|
528
|
+
if (!data.success) throw new Error(data.message || "session create failed");
|
|
529
|
+
const sid = data.data.sessionId;
|
|
530
|
+
const updatedSessions = data.data.sessions ?? [sid];
|
|
531
|
+
upsertSessionsFromServer(updatedSessions, setSessions);
|
|
532
|
+
setActiveSessionIdState(sid);
|
|
533
|
+
setActiveSessionId(sid);
|
|
534
|
+
setActiveTab("messages");
|
|
535
|
+
setMessageView("detail");
|
|
536
|
+
touchSession(sid);
|
|
537
|
+
setMessages([]);
|
|
538
|
+
return sid;
|
|
539
|
+
};
|
|
435
540
|
const loadConfig = async () => {
|
|
436
541
|
try {
|
|
437
542
|
setIsConfigLoading(true);
|
|
543
|
+
const deviceId = getOrCreateDeviceId();
|
|
544
|
+
purgeExpiredLocalSessions(setActiveSessionIdState);
|
|
545
|
+
const localActive = getActiveSessionId();
|
|
438
546
|
const response = await fetch(`${PROXY_BASE_URL}/aizek-connect?clientId=${clientId}`, {
|
|
439
547
|
method: "POST",
|
|
440
548
|
headers: {
|
|
441
549
|
"Content-Type": "application/json",
|
|
550
|
+
"x-device-id": deviceId,
|
|
442
551
|
"x-alternate": JSON.stringify(headers)
|
|
443
|
-
}
|
|
444
|
-
credentials: "include"
|
|
552
|
+
}
|
|
445
553
|
});
|
|
446
554
|
const data = await response.json();
|
|
447
|
-
if (data.success) {
|
|
448
|
-
setIsOpen(data.data.widget_config.initial_open);
|
|
449
|
-
setConfig(data.data);
|
|
450
|
-
if (headers) {
|
|
451
|
-
const validationResult = validateHeaders(
|
|
452
|
-
headers,
|
|
453
|
-
data.data.auth_config,
|
|
454
|
-
{
|
|
455
|
-
allowExtra: false,
|
|
456
|
-
caseSensitive: true
|
|
457
|
-
}
|
|
458
|
-
);
|
|
459
|
-
setHeaderValidation(validationResult);
|
|
460
|
-
}
|
|
461
|
-
onReady?.({ config: { ...data.data } });
|
|
462
|
-
} else {
|
|
555
|
+
if (!data.success) {
|
|
463
556
|
setIsOpen(false);
|
|
557
|
+
return;
|
|
464
558
|
}
|
|
559
|
+
setIsOpen(!!data.data.widget_config.initial_open);
|
|
560
|
+
setConfig(data.data);
|
|
561
|
+
const serverSessions = data.data.sessions ?? [];
|
|
562
|
+
const merged = upsertSessionsFromServer(serverSessions, setSessions);
|
|
563
|
+
if (merged.length === 0) {
|
|
564
|
+
const newSid = await createNewSession();
|
|
565
|
+
setActiveSessionIdState(newSid);
|
|
566
|
+
setActiveSessionId(newSid);
|
|
567
|
+
return;
|
|
568
|
+
}
|
|
569
|
+
const mergedIds = merged.map((s) => s.sessionId);
|
|
570
|
+
const nextActive = (localActive && mergedIds.includes(localActive) ? localActive : null) ?? mergedIds[0] ?? null;
|
|
571
|
+
setActiveSessionIdState(nextActive);
|
|
572
|
+
setActiveSessionId(nextActive);
|
|
573
|
+
if (headers) {
|
|
574
|
+
const validationResult = validateHeaders(headers, data.data.auth_config, {
|
|
575
|
+
allowExtra: false,
|
|
576
|
+
caseSensitive: true
|
|
577
|
+
});
|
|
578
|
+
setHeaderValidation(validationResult);
|
|
579
|
+
}
|
|
580
|
+
onReady?.({ config: { ...data.data } });
|
|
465
581
|
} catch (error) {
|
|
466
582
|
console.error("Failed to load chat widget config:", error);
|
|
467
583
|
} finally {
|
|
468
584
|
setIsConfigLoading(false);
|
|
469
585
|
}
|
|
470
586
|
};
|
|
471
|
-
const
|
|
587
|
+
const getHistoryMessageBySessionId = async (sid) => {
|
|
472
588
|
try {
|
|
473
|
-
|
|
474
|
-
await fetch(`${PROXY_BASE_URL}/aizek-
|
|
475
|
-
method: "
|
|
589
|
+
const deviceId = getOrCreateDeviceId();
|
|
590
|
+
const response = await fetch(`${PROXY_BASE_URL}/aizek-messages`, {
|
|
591
|
+
method: "GET",
|
|
476
592
|
headers: {
|
|
477
593
|
"Content-Type": "application/json",
|
|
594
|
+
"x-device-id": deviceId,
|
|
595
|
+
"x-session-id": sid,
|
|
478
596
|
"x-alternate": JSON.stringify(headers)
|
|
479
|
-
}
|
|
480
|
-
credentials: "include"
|
|
597
|
+
}
|
|
481
598
|
});
|
|
482
|
-
|
|
599
|
+
const data = await response.json();
|
|
600
|
+
if (!data.success) {
|
|
601
|
+
throw new Error(data.message || "Failed to fetch messages");
|
|
602
|
+
}
|
|
603
|
+
const historyMessages = [];
|
|
604
|
+
if (data.data?.messages && Array.isArray(data.data.messages)) {
|
|
605
|
+
for (const msg of data.data.messages) {
|
|
606
|
+
let textContent = "";
|
|
607
|
+
let uiData = null;
|
|
608
|
+
if (typeof msg.content === "string") {
|
|
609
|
+
textContent = msg.content;
|
|
610
|
+
} else if (Array.isArray(msg.content)) {
|
|
611
|
+
const textParts = [];
|
|
612
|
+
for (const item of msg.content) {
|
|
613
|
+
if (item.type === "text" && item.text) {
|
|
614
|
+
textParts.push(item.text);
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
textContent = textParts.join("\n");
|
|
618
|
+
}
|
|
619
|
+
if (textContent) {
|
|
620
|
+
const extracted = extractUIJsonFromText(textContent);
|
|
621
|
+
textContent = extracted.cleanedText;
|
|
622
|
+
uiData = extracted.uiData;
|
|
623
|
+
}
|
|
624
|
+
if (textContent.trim() || uiData) {
|
|
625
|
+
historyMessages.push({
|
|
626
|
+
text: textContent.trim() || void 0,
|
|
627
|
+
ui: uiData,
|
|
628
|
+
role: msg.role === "user" ? "user" : msg.role === "assistant" ? "assistant" : "user",
|
|
629
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
630
|
+
});
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
return historyMessages;
|
|
483
635
|
} catch (error) {
|
|
484
|
-
console.error("
|
|
485
|
-
|
|
486
|
-
setIsConfigLoading(false);
|
|
636
|
+
console.error("Error fetching message history:", error);
|
|
637
|
+
return [];
|
|
487
638
|
}
|
|
488
639
|
};
|
|
489
640
|
useEffect(() => {
|
|
490
641
|
onMounted?.();
|
|
491
642
|
loadConfig();
|
|
492
|
-
return () => {
|
|
493
|
-
disconnect();
|
|
494
|
-
};
|
|
495
643
|
}, []);
|
|
496
644
|
useEffect(() => {
|
|
497
|
-
const
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
645
|
+
const t = setInterval(() => {
|
|
646
|
+
purgeExpiredLocalSessions(setActiveSessionIdState);
|
|
647
|
+
}, 1e3);
|
|
648
|
+
return () => clearInterval(t);
|
|
649
|
+
}, []);
|
|
650
|
+
useEffect(() => {
|
|
651
|
+
if (typeof config?.widget_config.initial_open === "boolean") {
|
|
652
|
+
const open = config.widget_config.initial_open;
|
|
653
|
+
setIsOpen(open);
|
|
654
|
+
if (open) onOpen?.();
|
|
655
|
+
else onClose?.();
|
|
656
|
+
}
|
|
501
657
|
}, [config?.widget_config.initial_open]);
|
|
502
658
|
useEffect(() => {
|
|
503
659
|
messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
|
|
504
660
|
}, [messages]);
|
|
661
|
+
useEffect(() => {
|
|
662
|
+
if (activeSessionId && !isConfigLoading) {
|
|
663
|
+
getHistoryMessageBySessionId(activeSessionId).then((historyMessages) => {
|
|
664
|
+
setMessages(historyMessages);
|
|
665
|
+
}).catch((error) => {
|
|
666
|
+
console.error("Failed to load message history:", error);
|
|
667
|
+
});
|
|
668
|
+
} else if (!activeSessionId) {
|
|
669
|
+
setMessages([]);
|
|
670
|
+
}
|
|
671
|
+
}, [activeSessionId, isConfigLoading]);
|
|
505
672
|
const addMessage = (payload) => {
|
|
506
673
|
const newMessage = {
|
|
507
674
|
text: payload.text,
|
|
@@ -516,24 +683,51 @@ var AizekChatBot = ({ clientId, headers, onMounted, onReady, onOpen, onClose, on
|
|
|
516
683
|
};
|
|
517
684
|
const sendMessage = async (message, approval) => {
|
|
518
685
|
if (!message.trim() || isLoading) return;
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
ui: void 0,
|
|
522
|
-
|
|
523
|
-
timestamp: /* @__PURE__ */ new Date()
|
|
524
|
-
};
|
|
525
|
-
setMessages((prev) => [...prev, newMessage]);
|
|
686
|
+
setMessages((prev) => [
|
|
687
|
+
...prev,
|
|
688
|
+
{ text: message, ui: void 0, role: approval ? "approval" : "user", timestamp: /* @__PURE__ */ new Date() }
|
|
689
|
+
]);
|
|
526
690
|
setIsLoading(true);
|
|
527
691
|
try {
|
|
692
|
+
const deviceId = getOrCreateDeviceId();
|
|
693
|
+
purgeExpiredLocalSessions(setActiveSessionIdState);
|
|
694
|
+
let sid = activeSessionId;
|
|
695
|
+
if (!sid) sid = await createNewSession();
|
|
528
696
|
const response = await fetch(`${PROXY_BASE_URL}/aizek-chat?clientId=${clientId}`, {
|
|
529
697
|
method: "POST",
|
|
530
698
|
headers: {
|
|
531
699
|
"Content-Type": "application/json",
|
|
700
|
+
"x-device-id": deviceId,
|
|
701
|
+
"x-session-id": sid,
|
|
532
702
|
"x-alternate": JSON.stringify(headers)
|
|
533
703
|
},
|
|
534
|
-
body: JSON.stringify({ message })
|
|
535
|
-
credentials: "include"
|
|
704
|
+
body: JSON.stringify({ message })
|
|
536
705
|
});
|
|
706
|
+
if (response.status === 401) {
|
|
707
|
+
const local = readStoredSessions().filter((s) => s.sessionId !== sid);
|
|
708
|
+
writeStoredSessions(local);
|
|
709
|
+
setSessions(local.map((x) => x.sessionId));
|
|
710
|
+
setActiveSessionId(null);
|
|
711
|
+
setActiveSessionIdState(null);
|
|
712
|
+
const newSid = await createNewSession();
|
|
713
|
+
const retry = await fetch(`${PROXY_BASE_URL}/aizek-chat?clientId=${clientId}`, {
|
|
714
|
+
method: "POST",
|
|
715
|
+
headers: {
|
|
716
|
+
"Content-Type": "application/json",
|
|
717
|
+
"x-device-id": deviceId,
|
|
718
|
+
"x-session-id": newSid,
|
|
719
|
+
"x-alternate": JSON.stringify(headers)
|
|
720
|
+
},
|
|
721
|
+
body: JSON.stringify({ message })
|
|
722
|
+
});
|
|
723
|
+
if (!retry.ok) throw new Error(`HTTP error ${retry.status}`);
|
|
724
|
+
const retryJson = await retry.json();
|
|
725
|
+
const text = JSON.stringify(retryJson.data);
|
|
726
|
+
const { cleanedText, uiData } = extractUIJsonFromText(text);
|
|
727
|
+
addMessage({ text: cleanedText, ui: uiData, role: "assistant" });
|
|
728
|
+
touchSession(newSid);
|
|
729
|
+
return;
|
|
730
|
+
}
|
|
537
731
|
if (!response.ok) {
|
|
538
732
|
throw new Error(`HTTP error ${response.status}`);
|
|
539
733
|
}
|
|
@@ -577,87 +771,359 @@ var AizekChatBot = ({ clientId, headers, onMounted, onReady, onOpen, onClose, on
|
|
|
577
771
|
}
|
|
578
772
|
}
|
|
579
773
|
}
|
|
774
|
+
touchSession(sid);
|
|
580
775
|
} catch (error) {
|
|
581
776
|
console.error("Error sending message:", error);
|
|
582
|
-
addMessage({ text: "
|
|
777
|
+
addMessage({ text: "Sorry, something went wrong. Please try again.", role: "assistant" });
|
|
583
778
|
} finally {
|
|
584
779
|
setIsLoading(false);
|
|
585
780
|
}
|
|
586
781
|
};
|
|
782
|
+
const disconnectActiveSession = async () => {
|
|
783
|
+
try {
|
|
784
|
+
const deviceId = getOrCreateDeviceId();
|
|
785
|
+
const sid = activeSessionId;
|
|
786
|
+
if (!sid) return;
|
|
787
|
+
await fetch(`${PROXY_BASE_URL}/aizek-disconnect?clientId=${clientId}`, {
|
|
788
|
+
method: "POST",
|
|
789
|
+
headers: {
|
|
790
|
+
"Content-Type": "application/json",
|
|
791
|
+
"x-device-id": deviceId,
|
|
792
|
+
"x-session-id": sid,
|
|
793
|
+
"x-alternate": JSON.stringify(headers)
|
|
794
|
+
},
|
|
795
|
+
body: JSON.stringify({ sessionId: sid })
|
|
796
|
+
});
|
|
797
|
+
const nextStored = readStoredSessions().filter((s) => s.sessionId !== sid);
|
|
798
|
+
writeStoredSessions(nextStored);
|
|
799
|
+
const nextSessions = nextStored.map((x) => x.sessionId);
|
|
800
|
+
setSessions(nextSessions);
|
|
801
|
+
const nextActive = nextSessions[0] ?? null;
|
|
802
|
+
setActiveSessionIdState(nextActive);
|
|
803
|
+
setActiveSessionId(nextActive);
|
|
804
|
+
setMessages([]);
|
|
805
|
+
onDisconnect?.();
|
|
806
|
+
} catch (e) {
|
|
807
|
+
console.error(e);
|
|
808
|
+
}
|
|
809
|
+
};
|
|
810
|
+
const handleSelectSession = (sid) => {
|
|
811
|
+
setActiveSessionIdState(sid);
|
|
812
|
+
setActiveSessionId(sid);
|
|
813
|
+
setActiveTab("messages");
|
|
814
|
+
setMessageView("detail");
|
|
815
|
+
};
|
|
816
|
+
const getSessionLabel = (sid) => {
|
|
817
|
+
const idx = sessions.indexOf(sid);
|
|
818
|
+
return idx >= 0 ? `Chat ${idx + 1}` : "Chat";
|
|
819
|
+
};
|
|
587
820
|
const toggleChat = () => {
|
|
588
821
|
const newIsOpen = !isOpen;
|
|
589
822
|
setIsOpen(newIsOpen);
|
|
590
823
|
if (newIsOpen) onOpen?.();
|
|
591
824
|
else onClose?.();
|
|
592
825
|
};
|
|
826
|
+
const clean = sanitizeHtml(config?.widget_config.welcome_message ?? "", {
|
|
827
|
+
allowedTags: ["b", "i", "em", "strong", "a", "p", "br"],
|
|
828
|
+
allowedAttributes: {
|
|
829
|
+
a: ["href", "target", "rel"]
|
|
830
|
+
}
|
|
831
|
+
});
|
|
593
832
|
return /* @__PURE__ */ jsx(Fragment, { children: isConfigLoading ? /* @__PURE__ */ jsx(
|
|
594
833
|
"button",
|
|
595
834
|
{
|
|
596
835
|
className: "floating-button bottom-right button-sizes medium loading-state",
|
|
597
836
|
style: { background: "#4f46e5" },
|
|
598
|
-
"aria-label": "
|
|
837
|
+
"aria-label": "Loading",
|
|
599
838
|
children: /* @__PURE__ */ jsx("div", { className: "loading-spinner" })
|
|
600
839
|
}
|
|
601
840
|
) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
602
841
|
isOpen && /* @__PURE__ */ jsx("div", { className: `overlay floating-chat-overlay ${isOpen ? "is-open" : ""}`, onClick: toggleChat }),
|
|
603
|
-
/* @__PURE__ */ jsx(
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
className: "logo-image"
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
842
|
+
/* @__PURE__ */ jsx(
|
|
843
|
+
"div",
|
|
844
|
+
{
|
|
845
|
+
className: `chat-container ${config?.widget_config.button_position} ${isOpen ? "is-open" : ""}`,
|
|
846
|
+
style: { width: config?.widget_config.chat_width, height: config?.widget_config.chat_height },
|
|
847
|
+
children: /* @__PURE__ */ jsxs("div", { className: "chatbot-container", children: [
|
|
848
|
+
/* @__PURE__ */ jsxs("div", { className: "header", style: { background: config?.widget_config.header_background }, children: [
|
|
849
|
+
/* @__PURE__ */ jsx("div", { className: "logo-container", children: config?.widget_config.company_logo ? config?.widget_config.company_logo.startsWith("http") || config?.widget_config.company_logo.startsWith("data:") ? /* @__PURE__ */ jsx("img", { src: config?.widget_config.company_logo, alt: "Company Logo", className: "logo-image" }) : /* @__PURE__ */ jsx("span", { className: "logo-text", children: config?.widget_config.company_logo }) : "\u{1F916}" }),
|
|
850
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
851
|
+
/* @__PURE__ */ jsx("h3", { className: "company-name", children: config?.widget_config.company_name }),
|
|
852
|
+
/* @__PURE__ */ jsx("p", { className: "status-text", children: isLoading ? "Typing..." : "Online" })
|
|
853
|
+
] })
|
|
854
|
+
] }),
|
|
855
|
+
/* @__PURE__ */ jsxs("div", { className: "chat-content", children: [
|
|
856
|
+
activeTab === "home" && /* @__PURE__ */ jsxs("div", { className: "home-panel", children: [
|
|
857
|
+
/* @__PURE__ */ jsx("p", { className: "eyebrow", children: "Welcome" }),
|
|
858
|
+
/* @__PURE__ */ jsx("h3", { className: "panel-title", children: config?.widget_config.company_name }),
|
|
859
|
+
/* @__PURE__ */ jsx("p", { className: "panel-subtitle", children: "Ask anything. We keep your history and respond instantly." }),
|
|
860
|
+
/* @__PURE__ */ jsxs("div", { className: "home-actions", children: [
|
|
861
|
+
/* @__PURE__ */ jsx(
|
|
862
|
+
"button",
|
|
863
|
+
{
|
|
864
|
+
className: "primary-button",
|
|
865
|
+
onClick: async () => {
|
|
866
|
+
try {
|
|
867
|
+
await createNewSession();
|
|
868
|
+
} catch (e) {
|
|
869
|
+
console.error(e);
|
|
870
|
+
}
|
|
871
|
+
},
|
|
872
|
+
disabled: isLoading || sessions.length >= MAX_SESSIONS,
|
|
873
|
+
children: "Start a new conversation"
|
|
874
|
+
}
|
|
875
|
+
),
|
|
876
|
+
/* @__PURE__ */ jsx(
|
|
877
|
+
"button",
|
|
878
|
+
{
|
|
879
|
+
className: "ghost-button",
|
|
880
|
+
onClick: () => {
|
|
881
|
+
setActiveTab("messages");
|
|
882
|
+
setMessageView("list");
|
|
883
|
+
},
|
|
884
|
+
children: "View conversations"
|
|
885
|
+
}
|
|
886
|
+
)
|
|
887
|
+
] })
|
|
888
|
+
] }),
|
|
889
|
+
activeTab === "messages" && /* @__PURE__ */ jsx(Fragment, { children: messageView === "list" ? /* @__PURE__ */ jsxs("div", { className: "conversation-list", children: [
|
|
890
|
+
/* @__PURE__ */ jsxs("div", { className: "list-header", children: [
|
|
891
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
892
|
+
/* @__PURE__ */ jsx("p", { className: "eyebrow", children: "Conversations" }),
|
|
893
|
+
/* @__PURE__ */ jsx("h4", { className: "panel-title", children: "Inbox" })
|
|
894
|
+
] }),
|
|
895
|
+
/* @__PURE__ */ jsx(
|
|
896
|
+
"button",
|
|
897
|
+
{
|
|
898
|
+
className: "session-new-button",
|
|
899
|
+
onClick: async () => {
|
|
900
|
+
try {
|
|
901
|
+
await createNewSession();
|
|
902
|
+
} catch (e) {
|
|
903
|
+
console.error(e);
|
|
904
|
+
}
|
|
905
|
+
},
|
|
906
|
+
disabled: sessions.length >= MAX_SESSIONS,
|
|
907
|
+
children: /* @__PURE__ */ jsx("span", { children: "+ New" })
|
|
908
|
+
}
|
|
909
|
+
)
|
|
910
|
+
] }),
|
|
911
|
+
sessions.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "empty-list", children: [
|
|
912
|
+
/* @__PURE__ */ jsx("div", { className: "empty-state-icon", children: "\u{1F4AC}" }),
|
|
913
|
+
/* @__PURE__ */ jsx("h4", { className: "empty-state-title", children: "No conversations yet" }),
|
|
914
|
+
/* @__PURE__ */ jsx("p", { className: "empty-state-description", children: "Start a new conversation to see it appear here." })
|
|
915
|
+
] }) : /* @__PURE__ */ jsx("div", { className: "conversation-items", children: sessions.map((sid) => /* @__PURE__ */ jsxs(
|
|
916
|
+
"button",
|
|
917
|
+
{
|
|
918
|
+
className: `conversation-item ${sid === activeSessionId ? "active" : ""}`,
|
|
919
|
+
onClick: () => handleSelectSession(sid),
|
|
920
|
+
children: [
|
|
921
|
+
/* @__PURE__ */ jsxs("div", { className: "conversation-meta", children: [
|
|
922
|
+
/* @__PURE__ */ jsx("p", { className: "conversation-title", children: getSessionLabel(sid) }),
|
|
923
|
+
/* @__PURE__ */ jsxs("p", { className: "conversation-sub", children: [
|
|
924
|
+
"Session ID: ",
|
|
925
|
+
sid.slice(0, 8),
|
|
926
|
+
"..."
|
|
927
|
+
] })
|
|
928
|
+
] }),
|
|
929
|
+
/* @__PURE__ */ jsx("span", { className: "conversation-pill", children: "Open" })
|
|
930
|
+
]
|
|
931
|
+
},
|
|
932
|
+
sid
|
|
933
|
+
)) })
|
|
934
|
+
] }) : /* @__PURE__ */ jsxs("div", { className: "conversation-detail", children: [
|
|
935
|
+
/* @__PURE__ */ jsxs("div", { className: "detail-header", children: [
|
|
936
|
+
/* @__PURE__ */ jsx("div", { className: "detail-header-left", children: /* @__PURE__ */ jsx("button", { className: "icon-button", onClick: () => setMessageView("list"), "aria-label": "Back", children: /* @__PURE__ */ jsx("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsx(
|
|
937
|
+
"path",
|
|
938
|
+
{
|
|
939
|
+
d: "M15 18l-6-6 6-6",
|
|
940
|
+
stroke: "currentColor",
|
|
941
|
+
strokeWidth: "2",
|
|
942
|
+
strokeLinecap: "round",
|
|
943
|
+
strokeLinejoin: "round"
|
|
944
|
+
}
|
|
945
|
+
) }) }) }),
|
|
946
|
+
/* @__PURE__ */ jsxs("div", { className: "detail-header-center", children: [
|
|
947
|
+
/* @__PURE__ */ jsx("div", { className: "detail-avatar", "aria-hidden": "true", children: /* @__PURE__ */ jsx("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsx(
|
|
948
|
+
"path",
|
|
949
|
+
{
|
|
950
|
+
d: "M12 3c-4.418 0-8 3.134-8 7 0 2.382 1.362 4.486 3.5 5.737V21l4.07-2.13c.14.008.283.013.43.013 4.418 0 8-3.134 8-7s-3.582-7-8-7z",
|
|
951
|
+
stroke: "currentColor",
|
|
952
|
+
strokeWidth: "2",
|
|
953
|
+
strokeLinejoin: "round"
|
|
954
|
+
}
|
|
955
|
+
) }) }),
|
|
956
|
+
/* @__PURE__ */ jsxs("div", { className: "detail-title", children: [
|
|
957
|
+
/* @__PURE__ */ jsxs("div", { className: "detail-title-row", children: [
|
|
958
|
+
/* @__PURE__ */ jsx("strong", { className: "detail-title-text", children: activeSessionId ? getSessionLabel(activeSessionId) : "Chat" }),
|
|
959
|
+
/* @__PURE__ */ jsx("span", { className: `status-dot ${isLoading ? "typing" : "online"}`, "aria-hidden": "true" })
|
|
960
|
+
] }),
|
|
961
|
+
/* @__PURE__ */ jsx("p", { className: "detail-subtitle", children: isLoading ? "Yaz\u0131yor\u2026" : "Online" })
|
|
962
|
+
] })
|
|
963
|
+
] }),
|
|
964
|
+
/* @__PURE__ */ jsxs("div", { className: "detail-header-right", children: [
|
|
965
|
+
/* @__PURE__ */ jsx(
|
|
966
|
+
"button",
|
|
967
|
+
{
|
|
968
|
+
className: "icon-button",
|
|
969
|
+
onClick: () => {
|
|
970
|
+
setActiveTab("info");
|
|
971
|
+
setMessageView("list");
|
|
972
|
+
},
|
|
973
|
+
"aria-label": "Bilgi",
|
|
974
|
+
children: /* @__PURE__ */ jsxs("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", children: [
|
|
975
|
+
/* @__PURE__ */ jsx(
|
|
976
|
+
"path",
|
|
977
|
+
{
|
|
978
|
+
d: "M12 17v-6",
|
|
979
|
+
stroke: "currentColor",
|
|
980
|
+
strokeWidth: "2",
|
|
981
|
+
strokeLinecap: "round"
|
|
982
|
+
}
|
|
983
|
+
),
|
|
984
|
+
/* @__PURE__ */ jsx(
|
|
985
|
+
"path",
|
|
986
|
+
{
|
|
987
|
+
d: "M12 8h.01",
|
|
988
|
+
stroke: "currentColor",
|
|
989
|
+
strokeWidth: "2.5",
|
|
990
|
+
strokeLinecap: "round"
|
|
991
|
+
}
|
|
992
|
+
),
|
|
993
|
+
/* @__PURE__ */ jsx(
|
|
994
|
+
"circle",
|
|
995
|
+
{
|
|
996
|
+
cx: "12",
|
|
997
|
+
cy: "12",
|
|
998
|
+
r: "9",
|
|
999
|
+
stroke: "currentColor",
|
|
1000
|
+
strokeWidth: "2"
|
|
1001
|
+
}
|
|
1002
|
+
)
|
|
1003
|
+
] })
|
|
1004
|
+
}
|
|
1005
|
+
),
|
|
1006
|
+
/* @__PURE__ */ jsx(
|
|
1007
|
+
"button",
|
|
1008
|
+
{
|
|
1009
|
+
className: "icon-button danger",
|
|
1010
|
+
onClick: disconnectActiveSession,
|
|
1011
|
+
disabled: !activeSessionId,
|
|
1012
|
+
"aria-label": "End conversation",
|
|
1013
|
+
children: /* @__PURE__ */ jsxs("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", children: [
|
|
1014
|
+
/* @__PURE__ */ jsx(
|
|
1015
|
+
"path",
|
|
1016
|
+
{
|
|
1017
|
+
d: "M3 6h18",
|
|
1018
|
+
stroke: "currentColor",
|
|
1019
|
+
strokeWidth: "2",
|
|
1020
|
+
strokeLinecap: "round"
|
|
1021
|
+
}
|
|
1022
|
+
),
|
|
1023
|
+
/* @__PURE__ */ jsx(
|
|
1024
|
+
"path",
|
|
1025
|
+
{
|
|
1026
|
+
d: "M8 6V4h8v2",
|
|
1027
|
+
stroke: "currentColor",
|
|
1028
|
+
strokeWidth: "2",
|
|
1029
|
+
strokeLinejoin: "round"
|
|
1030
|
+
}
|
|
1031
|
+
),
|
|
1032
|
+
/* @__PURE__ */ jsx(
|
|
1033
|
+
"path",
|
|
1034
|
+
{
|
|
1035
|
+
d: "M6 6l1 16h10l1-16",
|
|
1036
|
+
stroke: "currentColor",
|
|
1037
|
+
strokeWidth: "2",
|
|
1038
|
+
strokeLinejoin: "round"
|
|
1039
|
+
}
|
|
1040
|
+
)
|
|
1041
|
+
] })
|
|
1042
|
+
}
|
|
1043
|
+
)
|
|
1044
|
+
] })
|
|
1045
|
+
] }),
|
|
1046
|
+
/* @__PURE__ */ jsxs("div", { className: "messages-container", children: [
|
|
1047
|
+
/* @__PURE__ */ jsx(HeaderAlert, { headerValidation, setShowAlert, showAlert }),
|
|
1048
|
+
messages.length === 0 ? /* @__PURE__ */ jsx("div", { className: "empty-state", children: /* @__PURE__ */ jsx("span", { dangerouslySetInnerHTML: { __html: clean } }) }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1049
|
+
messages.map((message, index) => /* @__PURE__ */ jsx(MessageBubble, { message, onAction: sendMessage }, index)),
|
|
1050
|
+
config?.widget_config.show_typing_indicator && isLoading && /* @__PURE__ */ jsx(TypingDots, {})
|
|
1051
|
+
] }),
|
|
1052
|
+
/* @__PURE__ */ jsx("div", { ref: messagesEndRef })
|
|
1053
|
+
] }),
|
|
1054
|
+
/* @__PURE__ */ jsx(
|
|
1055
|
+
ChatInput,
|
|
1056
|
+
{
|
|
1057
|
+
handleSendMessage: sendMessage,
|
|
1058
|
+
isLoading,
|
|
1059
|
+
placeholder: config?.widget_config.placeholder ?? ""
|
|
1060
|
+
}
|
|
1061
|
+
)
|
|
1062
|
+
] }) }),
|
|
1063
|
+
activeTab === "info" && /* @__PURE__ */ jsxs("div", { className: "info-panel", children: [
|
|
1064
|
+
/* @__PURE__ */ jsx("p", { className: "eyebrow", children: "Info" }),
|
|
1065
|
+
/* @__PURE__ */ jsx("h4", { className: "panel-title", children: "Widget Details" }),
|
|
1066
|
+
/* @__PURE__ */ jsxs("ul", { className: "info-list", children: [
|
|
1067
|
+
/* @__PURE__ */ jsxs("li", { children: [
|
|
1068
|
+
/* @__PURE__ */ jsx("span", { children: "Company" }),
|
|
1069
|
+
/* @__PURE__ */ jsx("strong", { children: config?.widget_config.company_name })
|
|
1070
|
+
] }),
|
|
1071
|
+
/* @__PURE__ */ jsxs("li", { children: [
|
|
1072
|
+
/* @__PURE__ */ jsx("span", { children: "Status" }),
|
|
1073
|
+
/* @__PURE__ */ jsx("strong", { children: isLoading ? "Typing..." : "Online" })
|
|
1074
|
+
] }),
|
|
1075
|
+
/* @__PURE__ */ jsxs("li", { children: [
|
|
1076
|
+
/* @__PURE__ */ jsx("span", { children: "Conversations" }),
|
|
1077
|
+
/* @__PURE__ */ jsx("strong", { children: sessions.length })
|
|
1078
|
+
] })
|
|
1079
|
+
] })
|
|
1080
|
+
] })
|
|
1081
|
+
] }),
|
|
1082
|
+
/* @__PURE__ */ jsxs("div", { className: "bottom-nav", children: [
|
|
1083
|
+
/* @__PURE__ */ jsx(
|
|
1084
|
+
"button",
|
|
1085
|
+
{
|
|
1086
|
+
className: `nav-button ${activeTab === "home" ? "active" : ""}`,
|
|
1087
|
+
onClick: () => {
|
|
1088
|
+
setActiveTab("home");
|
|
1089
|
+
setMessageView("list");
|
|
1090
|
+
},
|
|
1091
|
+
children: "Home"
|
|
1092
|
+
}
|
|
1093
|
+
),
|
|
1094
|
+
/* @__PURE__ */ jsx(
|
|
1095
|
+
"button",
|
|
1096
|
+
{
|
|
1097
|
+
className: `nav-button ${activeTab === "messages" ? "active" : ""}`,
|
|
1098
|
+
onClick: () => {
|
|
1099
|
+
setActiveTab("messages");
|
|
1100
|
+
setMessageView("list");
|
|
1101
|
+
},
|
|
1102
|
+
children: "Messages"
|
|
1103
|
+
}
|
|
1104
|
+
),
|
|
1105
|
+
/* @__PURE__ */ jsx(
|
|
1106
|
+
"button",
|
|
1107
|
+
{
|
|
1108
|
+
className: `nav-button ${activeTab === "info" ? "active" : ""}`,
|
|
1109
|
+
onClick: () => {
|
|
1110
|
+
setActiveTab("info");
|
|
1111
|
+
setMessageView("list");
|
|
1112
|
+
},
|
|
1113
|
+
children: "Info"
|
|
1114
|
+
}
|
|
1115
|
+
)
|
|
1116
|
+
] })
|
|
616
1117
|
] })
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
/* @__PURE__ */ jsx(
|
|
620
|
-
HeaderAlert,
|
|
621
|
-
{
|
|
622
|
-
headerValidation,
|
|
623
|
-
setShowAlert,
|
|
624
|
-
showAlert
|
|
625
|
-
}
|
|
626
|
-
),
|
|
627
|
-
messages.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "empty-state", children: [
|
|
628
|
-
/* @__PURE__ */ jsx("div", { className: "empty-state-icon", children: "\u{1F4AC}" }),
|
|
629
|
-
/* @__PURE__ */ jsx("h4", { className: "empty-state-title", children: config?.widget_config.welcome_message }),
|
|
630
|
-
/* @__PURE__ */ jsx("p", { className: "empty-state-description", children: "A\u015Fa\u011F\u0131daki alana mesaj\u0131n\u0131z\u0131 yazarak ba\u015Flayabilirsiniz." })
|
|
631
|
-
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
632
|
-
messages.map((message, index) => /* @__PURE__ */ jsx(
|
|
633
|
-
MessageBubble,
|
|
634
|
-
{
|
|
635
|
-
message,
|
|
636
|
-
onAction: sendMessage
|
|
637
|
-
},
|
|
638
|
-
index
|
|
639
|
-
)),
|
|
640
|
-
config?.widget_config.show_typing_indicator && isLoading && /* @__PURE__ */ jsx(TypingDots, {})
|
|
641
|
-
] }),
|
|
642
|
-
/* @__PURE__ */ jsx("div", { ref: messagesEndRef })
|
|
643
|
-
] }),
|
|
644
|
-
/* @__PURE__ */ jsx(
|
|
645
|
-
ChatInput,
|
|
646
|
-
{
|
|
647
|
-
handleSendMessage: sendMessage,
|
|
648
|
-
isLoading,
|
|
649
|
-
placeholder: config?.widget_config.placeholder ?? ""
|
|
650
|
-
}
|
|
651
|
-
)
|
|
652
|
-
] }) }),
|
|
1118
|
+
}
|
|
1119
|
+
),
|
|
653
1120
|
/* @__PURE__ */ jsx(
|
|
654
1121
|
"button",
|
|
655
1122
|
{
|
|
656
1123
|
onClick: toggleChat,
|
|
657
1124
|
className: `floating-button ${config?.widget_config.button_position} button-sizes ${config?.widget_config.button_size} ${isOpen ? "is-open" : ""}`,
|
|
658
1125
|
style: { background: config?.widget_config.button_background },
|
|
659
|
-
|
|
660
|
-
children: isOpen ? /* @__PURE__ */ jsx("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsx("path", { d: "M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z" }) }) : /* @__PURE__ */ jsx("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsx("path", { d: "M20 2H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h4l4 4 4-4h4c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-2 12H6v-2h12v2zm0-3H6V9h12v2zm0-3H6V6h12v2z" }) })
|
|
1126
|
+
children: isOpen ? /* @__PURE__ */ jsx("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsx("path", { d: "M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z" }) }) : /* @__PURE__ */ jsx("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsx("path", { d: "M20 2H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h4l4 4 4-4h4c1.1 0-2 .9-2-2V4c0-1.1-.9-2-2-2zm-2 12H6v-2h12v2zm0-3H6V9h12v2zm0-3H6V6h12v2z" }) })
|
|
661
1127
|
}
|
|
662
1128
|
)
|
|
663
1129
|
] }) });
|