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