@copilotz/chat-ui 0.8.5 → 0.8.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +589 -236
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +34 -1
- package/dist/index.d.ts +34 -1
- package/dist/index.js +614 -259
- package/dist/index.js.map +1 -1
- package/dist/styles.css +25 -0
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -118,6 +118,15 @@ var defaultChatConfig = {
|
|
|
118
118
|
renameThread: "Rename",
|
|
119
119
|
archiveThread: "Archive",
|
|
120
120
|
unarchiveThread: "Unarchive",
|
|
121
|
+
manageTags: "Manage tags",
|
|
122
|
+
tags: "Tags",
|
|
123
|
+
addTag: "Add tag",
|
|
124
|
+
removeTag: "Remove tag",
|
|
125
|
+
tagNamePlaceholder: "Tag name",
|
|
126
|
+
untagged: "Untagged",
|
|
127
|
+
groupBy: "Group by",
|
|
128
|
+
groupByDate: "Date",
|
|
129
|
+
groupByTag: "Tag",
|
|
121
130
|
today: "Today",
|
|
122
131
|
yesterday: "Yesterday",
|
|
123
132
|
createNewThread: "Create New Conversation",
|
|
@@ -151,6 +160,13 @@ var defaultChatConfig = {
|
|
|
151
160
|
enableRegeneration: true,
|
|
152
161
|
showActivity: true,
|
|
153
162
|
showActivityDetails: true,
|
|
163
|
+
threadTags: {
|
|
164
|
+
enabled: false,
|
|
165
|
+
groupingEnabled: true,
|
|
166
|
+
defaultGroupBy: "date",
|
|
167
|
+
allowCreate: true,
|
|
168
|
+
allowDrag: true
|
|
169
|
+
},
|
|
154
170
|
maxAttachments: 4,
|
|
155
171
|
maxFileSize: 10 * 1024 * 1024
|
|
156
172
|
// 10MB
|
|
@@ -183,7 +199,8 @@ var defaultChatConfig = {
|
|
|
183
199
|
createProvider: void 0
|
|
184
200
|
},
|
|
185
201
|
customComponent: {},
|
|
186
|
-
headerActions: null
|
|
202
|
+
headerActions: null,
|
|
203
|
+
headerMenuItems: []
|
|
187
204
|
};
|
|
188
205
|
function mergeConfig(_baseConfig, userConfig) {
|
|
189
206
|
if (!userConfig) return defaultChatConfig;
|
|
@@ -217,7 +234,8 @@ function mergeConfig(_baseConfig, userConfig) {
|
|
|
217
234
|
...userConfig.agentSelector
|
|
218
235
|
},
|
|
219
236
|
customComponent: userConfig.customComponent || defaultChatConfig.customComponent,
|
|
220
|
-
headerActions: userConfig.headerActions || defaultChatConfig.headerActions
|
|
237
|
+
headerActions: userConfig.headerActions || defaultChatConfig.headerActions,
|
|
238
|
+
headerMenuItems: userConfig.headerMenuItems || defaultChatConfig.headerMenuItems
|
|
221
239
|
};
|
|
222
240
|
}
|
|
223
241
|
|
|
@@ -2442,6 +2460,37 @@ var ThreadInitialsIcon = ({ title }) => {
|
|
|
2442
2460
|
const initials = title?.split(" ").map((n) => n[0]).slice(0, 2).join("").toUpperCase() || "?";
|
|
2443
2461
|
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "flex shrink-0 items-center justify-center rounded bg-muted text-[10px] font-medium", children: initials });
|
|
2444
2462
|
};
|
|
2463
|
+
function slugTagName(name) {
|
|
2464
|
+
const slug = name.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 48);
|
|
2465
|
+
return slug || "tag";
|
|
2466
|
+
}
|
|
2467
|
+
function createThreadTag(name) {
|
|
2468
|
+
return {
|
|
2469
|
+
id: `tag_${slugTagName(name)}`,
|
|
2470
|
+
name: name.trim()
|
|
2471
|
+
};
|
|
2472
|
+
}
|
|
2473
|
+
function mergeThreadTags(tags, tag) {
|
|
2474
|
+
const nameKey = tag.name.trim().toLowerCase();
|
|
2475
|
+
if (!nameKey) return tags;
|
|
2476
|
+
if (tags.some(
|
|
2477
|
+
(existing) => existing.id === tag.id || existing.name.trim().toLowerCase() === nameKey
|
|
2478
|
+
)) {
|
|
2479
|
+
return tags;
|
|
2480
|
+
}
|
|
2481
|
+
return [...tags, tag];
|
|
2482
|
+
}
|
|
2483
|
+
function collectThreadTags(threads) {
|
|
2484
|
+
const tags = [];
|
|
2485
|
+
for (const thread of threads) {
|
|
2486
|
+
for (const tag of thread.tags ?? []) {
|
|
2487
|
+
if (!tags.some((existing) => existing.id === tag.id)) {
|
|
2488
|
+
tags.push(tag);
|
|
2489
|
+
}
|
|
2490
|
+
}
|
|
2491
|
+
}
|
|
2492
|
+
return tags.sort((a, b) => a.name.localeCompare(b.name));
|
|
2493
|
+
}
|
|
2445
2494
|
var Sidebar2 = ({
|
|
2446
2495
|
threads,
|
|
2447
2496
|
currentThreadId,
|
|
@@ -2451,6 +2500,7 @@ var Sidebar2 = ({
|
|
|
2451
2500
|
onRenameThread,
|
|
2452
2501
|
onDeleteThread,
|
|
2453
2502
|
onArchiveThread,
|
|
2503
|
+
onUpdateThreadTags,
|
|
2454
2504
|
// User menu props
|
|
2455
2505
|
user,
|
|
2456
2506
|
userMenuCallbacks,
|
|
@@ -2465,7 +2515,20 @@ var Sidebar2 = ({
|
|
|
2465
2515
|
const [deleteThreadId, setDeleteThreadId] = (0, import_react4.useState)(null);
|
|
2466
2516
|
const [editingThreadId, setEditingThreadId] = (0, import_react4.useState)(null);
|
|
2467
2517
|
const [editTitle, setEditTitle] = (0, import_react4.useState)("");
|
|
2518
|
+
const [tagDialogThreadId, setTagDialogThreadId] = (0, import_react4.useState)(
|
|
2519
|
+
null
|
|
2520
|
+
);
|
|
2521
|
+
const [newTagName, setNewTagName] = (0, import_react4.useState)("");
|
|
2522
|
+
const [draggingThreadId, setDraggingThreadId] = (0, import_react4.useState)(null);
|
|
2523
|
+
const [dragOverTagId, setDragOverTagId] = (0, import_react4.useState)(null);
|
|
2468
2524
|
const inputRef = (0, import_react4.useRef)(null);
|
|
2525
|
+
const threadTagsConfig = config.features?.threadTags;
|
|
2526
|
+
const tagsEnabled = !!threadTagsConfig?.enabled;
|
|
2527
|
+
const canUpdateTags = tagsEnabled && !!onUpdateThreadTags;
|
|
2528
|
+
const canDragTags = canUpdateTags && threadTagsConfig?.allowDrag !== false;
|
|
2529
|
+
const [groupBy, setGroupBy] = (0, import_react4.useState)(
|
|
2530
|
+
threadTagsConfig?.defaultGroupBy === "tag" ? "tag" : "date"
|
|
2531
|
+
);
|
|
2469
2532
|
const { setOpen } = useSidebar();
|
|
2470
2533
|
(0, import_react4.useEffect)(() => {
|
|
2471
2534
|
if (editingThreadId && inputRef.current) {
|
|
@@ -2475,38 +2538,98 @@ var Sidebar2 = ({
|
|
|
2475
2538
|
}, [editingThreadId]);
|
|
2476
2539
|
const filteredThreads = threads.filter((thread) => {
|
|
2477
2540
|
const title = (thread.title ?? "").toString();
|
|
2478
|
-
const matchesSearch = title.toLowerCase().includes(
|
|
2479
|
-
searchQuery.toLowerCase()
|
|
2480
|
-
);
|
|
2541
|
+
const matchesSearch = title.toLowerCase().includes(searchQuery.toLowerCase());
|
|
2481
2542
|
const matchesArchiveFilter = showArchived || !thread.isArchived;
|
|
2482
2543
|
return matchesSearch && matchesArchiveFilter;
|
|
2483
2544
|
});
|
|
2484
|
-
const
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2545
|
+
const allTags = (0, import_react4.useMemo)(() => collectThreadTags(threads), [threads]);
|
|
2546
|
+
const threadGroups = (0, import_react4.useMemo)(() => {
|
|
2547
|
+
if (tagsEnabled && groupBy === "tag") {
|
|
2548
|
+
const groups2 = allTags.map((tag) => ({
|
|
2549
|
+
key: tag.id,
|
|
2550
|
+
label: tag.name,
|
|
2551
|
+
tag,
|
|
2552
|
+
threads: filteredThreads.filter(
|
|
2553
|
+
(thread) => (thread.tags ?? []).some((threadTag) => threadTag.id === tag.id)
|
|
2554
|
+
)
|
|
2555
|
+
})).filter((group) => group.threads.length > 0);
|
|
2556
|
+
const untagged = filteredThreads.filter(
|
|
2557
|
+
(thread) => (thread.tags ?? []).length === 0
|
|
2558
|
+
);
|
|
2559
|
+
if (untagged.length > 0) {
|
|
2560
|
+
groups2.push({
|
|
2561
|
+
key: "untagged",
|
|
2562
|
+
label: config.labels?.untagged || "Untagged",
|
|
2563
|
+
threads: untagged
|
|
2564
|
+
});
|
|
2565
|
+
}
|
|
2566
|
+
return groups2;
|
|
2567
|
+
}
|
|
2568
|
+
const groups = [];
|
|
2569
|
+
const groupMap = /* @__PURE__ */ new Map();
|
|
2570
|
+
for (const thread of filteredThreads) {
|
|
2571
|
+
const date = new Date(thread.updatedAt);
|
|
2572
|
+
const today = /* @__PURE__ */ new Date();
|
|
2573
|
+
const yesterday = new Date(today.getTime() - 24 * 60 * 60 * 1e3);
|
|
2574
|
+
let groupKey;
|
|
2575
|
+
if (date.toDateString() === today.toDateString()) {
|
|
2576
|
+
groupKey = config.labels?.today || "Today";
|
|
2577
|
+
} else if (date.toDateString() === yesterday.toDateString()) {
|
|
2578
|
+
groupKey = config.labels?.yesterday || "Yesterday";
|
|
2579
|
+
} else {
|
|
2580
|
+
groupKey = date.toLocaleDateString("en-US", {
|
|
2581
|
+
weekday: "long",
|
|
2582
|
+
day: "2-digit",
|
|
2583
|
+
month: "long"
|
|
2584
|
+
});
|
|
2585
|
+
}
|
|
2586
|
+
const existing = groupMap.get(groupKey);
|
|
2587
|
+
if (existing) {
|
|
2588
|
+
existing.threads.push(thread);
|
|
2589
|
+
} else {
|
|
2590
|
+
const group = { key: groupKey, label: groupKey, threads: [thread] };
|
|
2591
|
+
groupMap.set(groupKey, group);
|
|
2592
|
+
groups.push(group);
|
|
2593
|
+
}
|
|
2502
2594
|
}
|
|
2503
|
-
groups[groupKey].push(thread);
|
|
2504
2595
|
return groups;
|
|
2505
|
-
},
|
|
2596
|
+
}, [
|
|
2597
|
+
allTags,
|
|
2598
|
+
config.labels?.today,
|
|
2599
|
+
config.labels?.untagged,
|
|
2600
|
+
config.labels?.yesterday,
|
|
2601
|
+
filteredThreads,
|
|
2602
|
+
groupBy,
|
|
2603
|
+
tagsEnabled
|
|
2604
|
+
]);
|
|
2605
|
+
const tagDialogThread = tagDialogThreadId ? threads.find((thread) => thread.id === tagDialogThreadId) ?? null : null;
|
|
2506
2606
|
const handleDeleteThread = (threadId) => {
|
|
2507
2607
|
onDeleteThread?.(threadId);
|
|
2508
2608
|
setDeleteThreadId(null);
|
|
2509
2609
|
};
|
|
2610
|
+
const updateThreadTags = (thread, tags) => {
|
|
2611
|
+
onUpdateThreadTags?.(thread.id, tags);
|
|
2612
|
+
};
|
|
2613
|
+
const addTagToThread = (thread, tag) => {
|
|
2614
|
+
updateThreadTags(thread, mergeThreadTags(thread.tags ?? [], tag));
|
|
2615
|
+
};
|
|
2616
|
+
const removeTagFromThread = (thread, tagId) => {
|
|
2617
|
+
updateThreadTags(
|
|
2618
|
+
thread,
|
|
2619
|
+
(thread.tags ?? []).filter((tag) => tag.id !== tagId)
|
|
2620
|
+
);
|
|
2621
|
+
};
|
|
2622
|
+
const handleCreateTag = () => {
|
|
2623
|
+
if (!tagDialogThread || !newTagName.trim()) return;
|
|
2624
|
+
addTagToThread(tagDialogThread, createThreadTag(newTagName));
|
|
2625
|
+
setNewTagName("");
|
|
2626
|
+
};
|
|
2627
|
+
const handleDropOnTag = (tag) => {
|
|
2628
|
+
const thread = draggingThreadId ? threads.find((candidate) => candidate.id === draggingThreadId) : null;
|
|
2629
|
+
if (thread) addTagToThread(thread, tag);
|
|
2630
|
+
setDraggingThreadId(null);
|
|
2631
|
+
setDragOverTagId(null);
|
|
2632
|
+
};
|
|
2510
2633
|
const startEditing = (thread) => {
|
|
2511
2634
|
setEditingThreadId(thread.id);
|
|
2512
2635
|
setEditTitle(thread.title || "");
|
|
@@ -2594,92 +2717,175 @@ var Sidebar2 = ({
|
|
|
2594
2717
|
]
|
|
2595
2718
|
}
|
|
2596
2719
|
) }),
|
|
2597
|
-
|
|
2598
|
-
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("
|
|
2599
|
-
/* @__PURE__ */ (0, import_jsx_runtime18.
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(SidebarGroupContent, { children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(SidebarMenu, { children: groupThreads.map((thread) => /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(SidebarMenuItem, { children: [
|
|
2603
|
-
editingThreadId === thread.id ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "flex items-center gap-1 px-2 py-1", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
2604
|
-
Input,
|
|
2720
|
+
tagsEnabled && threadTagsConfig?.groupingEnabled !== false && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "px-4 py-2 group-data-[collapsible=icon]:hidden", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex items-center justify-between rounded-md border border-sidebar-border bg-sidebar-accent/40 p-1", children: [
|
|
2721
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "px-2 text-[11px] text-muted-foreground", children: config.labels?.groupBy || "Group by" }),
|
|
2722
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex gap-1", children: [
|
|
2723
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
2724
|
+
Button,
|
|
2605
2725
|
{
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
saveEdit();
|
|
2612
|
-
}
|
|
2613
|
-
if (e.key === "Escape") {
|
|
2614
|
-
cancelEdit();
|
|
2615
|
-
}
|
|
2616
|
-
},
|
|
2617
|
-
onBlur: saveEdit,
|
|
2618
|
-
className: "h-7 text-sm"
|
|
2726
|
+
variant: groupBy === "date" ? "secondary" : "ghost",
|
|
2727
|
+
size: "sm",
|
|
2728
|
+
onClick: () => setGroupBy("date"),
|
|
2729
|
+
className: "h-6 px-2 text-xs",
|
|
2730
|
+
children: config.labels?.groupByDate || "Date"
|
|
2619
2731
|
}
|
|
2620
|
-
)
|
|
2621
|
-
|
|
2732
|
+
),
|
|
2733
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
2734
|
+
Button,
|
|
2622
2735
|
{
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "flex flex-col items-start gap-0.5 flex-1 min-w-0 group-data-[collapsible=icon]:hidden", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "truncate w-full", children: thread.title || "New Chat" }) }),
|
|
2629
|
-
thread.isArchived && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react8.Archive, { className: "ml-auto h-3 w-3 opacity-50 group-data-[collapsible=icon]:hidden" })
|
|
2630
|
-
]
|
|
2736
|
+
variant: groupBy === "tag" ? "secondary" : "ghost",
|
|
2737
|
+
size: "sm",
|
|
2738
|
+
onClick: () => setGroupBy("tag"),
|
|
2739
|
+
className: "h-6 px-2 text-xs",
|
|
2740
|
+
children: config.labels?.groupByTag || "Tag"
|
|
2631
2741
|
}
|
|
2632
|
-
)
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
2742
|
+
)
|
|
2743
|
+
] })
|
|
2744
|
+
] }) }),
|
|
2745
|
+
threadGroups.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "px-4 py-8 text-center text-muted-foreground group-data-[collapsible=icon]:hidden", children: [
|
|
2746
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "mx-auto h-8 w-8 mb-2 flex items-center justify-center rounded-full bg-muted/50", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react8.Plus, { className: "h-4 w-4 opacity-50" }) }),
|
|
2747
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("p", { className: "text-xs", children: searchQuery ? config.labels?.noThreadsFound || "No conversations found" : config.labels?.noThreadsYet || "No conversations yet" })
|
|
2748
|
+
] }) : threadGroups.map((group) => /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
|
|
2749
|
+
SidebarGroup,
|
|
2750
|
+
{
|
|
2751
|
+
className: "mt-2",
|
|
2752
|
+
onDragOver: (event) => {
|
|
2753
|
+
if (!canDragTags || !group.tag) return;
|
|
2754
|
+
event.preventDefault();
|
|
2755
|
+
setDragOverTagId(group.tag.id);
|
|
2756
|
+
},
|
|
2757
|
+
onDragLeave: () => {
|
|
2758
|
+
if (dragOverTagId === group.tag?.id) setDragOverTagId(null);
|
|
2759
|
+
},
|
|
2760
|
+
onDrop: (event) => {
|
|
2761
|
+
if (!canDragTags || !group.tag) return;
|
|
2762
|
+
event.preventDefault();
|
|
2763
|
+
handleDropOnTag(group.tag);
|
|
2764
|
+
},
|
|
2765
|
+
children: [
|
|
2638
2766
|
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
|
|
2639
|
-
|
|
2767
|
+
SidebarGroupLabel,
|
|
2640
2768
|
{
|
|
2641
|
-
className: "
|
|
2642
|
-
side: "right",
|
|
2643
|
-
align: "start",
|
|
2769
|
+
className: `group-data-[collapsible=icon]:hidden ${dragOverTagId === group.tag?.id ? "rounded-md bg-sidebar-accent text-sidebar-accent-foreground" : ""}`,
|
|
2644
2770
|
children: [
|
|
2645
|
-
/* @__PURE__ */ (0, import_jsx_runtime18.
|
|
2646
|
-
|
|
2647
|
-
{
|
|
2648
|
-
onClick: () => startEditing(thread),
|
|
2649
|
-
children: [
|
|
2650
|
-
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react8.Edit2, { className: "mr-2 h-4 w-4" }),
|
|
2651
|
-
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { children: config.labels?.renameThread || "Rename" })
|
|
2652
|
-
]
|
|
2653
|
-
}
|
|
2654
|
-
),
|
|
2655
|
-
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
|
|
2656
|
-
DropdownMenuItem,
|
|
2657
|
-
{
|
|
2658
|
-
onClick: () => onArchiveThread?.(thread.id),
|
|
2659
|
-
children: [
|
|
2660
|
-
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react8.Archive, { className: "mr-2 h-4 w-4" }),
|
|
2661
|
-
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { children: thread.isArchived ? config.labels?.unarchiveThread || "Unarchive" : config.labels?.archiveThread || "Archive" })
|
|
2662
|
-
]
|
|
2663
|
-
}
|
|
2664
|
-
),
|
|
2665
|
-
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(DropdownMenuSeparator, {}),
|
|
2666
|
-
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
|
|
2667
|
-
DropdownMenuItem,
|
|
2668
|
-
{
|
|
2669
|
-
onClick: () => setDeleteThreadId(thread.id),
|
|
2670
|
-
className: "text-destructive focus:text-destructive",
|
|
2671
|
-
children: [
|
|
2672
|
-
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react8.Trash2, { className: "mr-2 h-4 w-4" }),
|
|
2673
|
-
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { children: config.labels?.deleteThread || "Delete" })
|
|
2674
|
-
]
|
|
2675
|
-
}
|
|
2676
|
-
)
|
|
2771
|
+
group.tag && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react8.Tag, { className: "mr-1 h-3 w-3" }),
|
|
2772
|
+
group.label
|
|
2677
2773
|
]
|
|
2678
2774
|
}
|
|
2679
|
-
)
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
|
|
2775
|
+
),
|
|
2776
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(SidebarGroupContent, { children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(SidebarMenu, { children: group.threads.map((thread) => /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(SidebarMenuItem, { children: [
|
|
2777
|
+
editingThreadId === thread.id ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "flex items-center gap-1 px-2 py-1", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
2778
|
+
Input,
|
|
2779
|
+
{
|
|
2780
|
+
ref: inputRef,
|
|
2781
|
+
value: editTitle,
|
|
2782
|
+
onChange: (e) => setEditTitle(e.target.value),
|
|
2783
|
+
onKeyDown: (e) => {
|
|
2784
|
+
if (e.key === "Enter") {
|
|
2785
|
+
saveEdit();
|
|
2786
|
+
}
|
|
2787
|
+
if (e.key === "Escape") {
|
|
2788
|
+
cancelEdit();
|
|
2789
|
+
}
|
|
2790
|
+
},
|
|
2791
|
+
onBlur: saveEdit,
|
|
2792
|
+
className: "h-7 text-sm"
|
|
2793
|
+
}
|
|
2794
|
+
) }) : /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
|
|
2795
|
+
SidebarMenuButton,
|
|
2796
|
+
{
|
|
2797
|
+
isActive: currentThreadId === thread.id,
|
|
2798
|
+
onClick: () => onSelectThread?.(thread.id),
|
|
2799
|
+
tooltip: thread.title,
|
|
2800
|
+
draggable: canDragTags,
|
|
2801
|
+
onDragStart: () => setDraggingThreadId(thread.id),
|
|
2802
|
+
onDragEnd: () => {
|
|
2803
|
+
setDraggingThreadId(null);
|
|
2804
|
+
setDragOverTagId(null);
|
|
2805
|
+
},
|
|
2806
|
+
children: [
|
|
2807
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(ThreadInitialsIcon, { title: thread.title || "?" }),
|
|
2808
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex flex-col items-start gap-0.5 flex-1 min-w-0 group-data-[collapsible=icon]:hidden", children: [
|
|
2809
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "truncate w-full", children: thread.title || "New Chat" }),
|
|
2810
|
+
tagsEnabled && (thread.tags ?? []).length > 0 && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "flex max-w-full flex-wrap gap-1", children: (thread.tags ?? []).slice(0, 2).map((tag) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
2811
|
+
"span",
|
|
2812
|
+
{
|
|
2813
|
+
className: "max-w-20 truncate rounded bg-sidebar-accent px-1.5 py-0.5 text-[10px] text-muted-foreground",
|
|
2814
|
+
children: tag.name
|
|
2815
|
+
},
|
|
2816
|
+
tag.id
|
|
2817
|
+
)) })
|
|
2818
|
+
] }),
|
|
2819
|
+
thread.isArchived && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react8.Archive, { className: "ml-auto h-3 w-3 opacity-50 group-data-[collapsible=icon]:hidden" })
|
|
2820
|
+
]
|
|
2821
|
+
}
|
|
2822
|
+
),
|
|
2823
|
+
!editingThreadId && /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(DropdownMenu, { children: [
|
|
2824
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(SidebarMenuAction, { showOnHover: true, children: [
|
|
2825
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react8.MoreHorizontal, {}),
|
|
2826
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "sr-only", children: "More" })
|
|
2827
|
+
] }) }),
|
|
2828
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
|
|
2829
|
+
DropdownMenuContent,
|
|
2830
|
+
{
|
|
2831
|
+
className: "w-48",
|
|
2832
|
+
side: "right",
|
|
2833
|
+
align: "start",
|
|
2834
|
+
children: [
|
|
2835
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
|
|
2836
|
+
DropdownMenuItem,
|
|
2837
|
+
{
|
|
2838
|
+
onClick: () => startEditing(thread),
|
|
2839
|
+
children: [
|
|
2840
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react8.Edit2, { className: "mr-2 h-4 w-4" }),
|
|
2841
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { children: config.labels?.renameThread || "Rename" })
|
|
2842
|
+
]
|
|
2843
|
+
}
|
|
2844
|
+
),
|
|
2845
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
|
|
2846
|
+
DropdownMenuItem,
|
|
2847
|
+
{
|
|
2848
|
+
onClick: () => onArchiveThread?.(thread.id),
|
|
2849
|
+
children: [
|
|
2850
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react8.Archive, { className: "mr-2 h-4 w-4" }),
|
|
2851
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { children: thread.isArchived ? config.labels?.unarchiveThread || "Unarchive" : config.labels?.archiveThread || "Archive" })
|
|
2852
|
+
]
|
|
2853
|
+
}
|
|
2854
|
+
),
|
|
2855
|
+
canUpdateTags && /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
|
|
2856
|
+
DropdownMenuItem,
|
|
2857
|
+
{
|
|
2858
|
+
onClick: () => {
|
|
2859
|
+
setTagDialogThreadId(thread.id);
|
|
2860
|
+
setNewTagName("");
|
|
2861
|
+
},
|
|
2862
|
+
children: [
|
|
2863
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react8.Tag, { className: "mr-2 h-4 w-4" }),
|
|
2864
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { children: config.labels?.manageTags || "Manage tags" })
|
|
2865
|
+
]
|
|
2866
|
+
}
|
|
2867
|
+
),
|
|
2868
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(DropdownMenuSeparator, {}),
|
|
2869
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
|
|
2870
|
+
DropdownMenuItem,
|
|
2871
|
+
{
|
|
2872
|
+
onClick: () => setDeleteThreadId(thread.id),
|
|
2873
|
+
className: "text-destructive focus:text-destructive",
|
|
2874
|
+
children: [
|
|
2875
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react8.Trash2, { className: "mr-2 h-4 w-4" }),
|
|
2876
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { children: config.labels?.deleteThread || "Delete" })
|
|
2877
|
+
]
|
|
2878
|
+
}
|
|
2879
|
+
)
|
|
2880
|
+
]
|
|
2881
|
+
}
|
|
2882
|
+
)
|
|
2883
|
+
] })
|
|
2884
|
+
] }, thread.id)) }) })
|
|
2885
|
+
]
|
|
2886
|
+
},
|
|
2887
|
+
group.key
|
|
2888
|
+
))
|
|
2683
2889
|
] }),
|
|
2684
2890
|
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(SidebarFooter, { children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
2685
2891
|
UserMenu,
|
|
@@ -2694,6 +2900,94 @@ var Sidebar2 = ({
|
|
|
2694
2900
|
}
|
|
2695
2901
|
) }),
|
|
2696
2902
|
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(SidebarRail, {}),
|
|
2903
|
+
tagDialogThread && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
2904
|
+
Dialog,
|
|
2905
|
+
{
|
|
2906
|
+
open: !!tagDialogThread,
|
|
2907
|
+
onOpenChange: (open) => {
|
|
2908
|
+
if (!open) {
|
|
2909
|
+
setTagDialogThreadId(null);
|
|
2910
|
+
setNewTagName("");
|
|
2911
|
+
}
|
|
2912
|
+
},
|
|
2913
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(DialogContent, { children: [
|
|
2914
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(DialogHeader, { children: [
|
|
2915
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(DialogTitle, { children: config.labels?.manageTags || "Manage tags" }),
|
|
2916
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(DialogDescription, { children: tagDialogThread.title || "New Chat" })
|
|
2917
|
+
] }),
|
|
2918
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "space-y-4", children: [
|
|
2919
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "space-y-2", children: [
|
|
2920
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "text-sm font-medium", children: config.labels?.tags || "Tags" }),
|
|
2921
|
+
(tagDialogThread.tags ?? []).length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("p", { className: "text-sm text-muted-foreground", children: config.labels?.untagged || "Untagged" }) : /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "flex flex-wrap gap-2", children: (tagDialogThread.tags ?? []).map((tag) => /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
|
|
2922
|
+
"span",
|
|
2923
|
+
{
|
|
2924
|
+
className: "inline-flex items-center gap-1 rounded-md bg-muted px-2 py-1 text-sm",
|
|
2925
|
+
children: [
|
|
2926
|
+
tag.name,
|
|
2927
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
2928
|
+
"button",
|
|
2929
|
+
{
|
|
2930
|
+
type: "button",
|
|
2931
|
+
className: "rounded hover:bg-background",
|
|
2932
|
+
onClick: () => removeTagFromThread(tagDialogThread, tag.id),
|
|
2933
|
+
"aria-label": config.labels?.removeTag || "Remove tag",
|
|
2934
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react8.X, { className: "h-3 w-3" })
|
|
2935
|
+
}
|
|
2936
|
+
)
|
|
2937
|
+
]
|
|
2938
|
+
},
|
|
2939
|
+
tag.id
|
|
2940
|
+
)) })
|
|
2941
|
+
] }),
|
|
2942
|
+
allTags.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "space-y-2", children: [
|
|
2943
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "text-sm font-medium", children: config.labels?.addTag || "Add tag" }),
|
|
2944
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "flex flex-wrap gap-2", children: allTags.map((tag) => {
|
|
2945
|
+
const assigned = (tagDialogThread.tags ?? []).some(
|
|
2946
|
+
(threadTag) => threadTag.id === tag.id
|
|
2947
|
+
);
|
|
2948
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
2949
|
+
Button,
|
|
2950
|
+
{
|
|
2951
|
+
type: "button",
|
|
2952
|
+
variant: assigned ? "secondary" : "outline",
|
|
2953
|
+
size: "sm",
|
|
2954
|
+
disabled: assigned,
|
|
2955
|
+
onClick: () => addTagToThread(tagDialogThread, tag),
|
|
2956
|
+
children: tag.name
|
|
2957
|
+
},
|
|
2958
|
+
tag.id
|
|
2959
|
+
);
|
|
2960
|
+
}) })
|
|
2961
|
+
] }),
|
|
2962
|
+
threadTagsConfig?.allowCreate !== false && /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex gap-2", children: [
|
|
2963
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
2964
|
+
Input,
|
|
2965
|
+
{
|
|
2966
|
+
value: newTagName,
|
|
2967
|
+
onChange: (event) => setNewTagName(event.target.value),
|
|
2968
|
+
placeholder: config.labels?.tagNamePlaceholder || "Tag name",
|
|
2969
|
+
onKeyDown: (event) => {
|
|
2970
|
+
if (event.key === "Enter") {
|
|
2971
|
+
event.preventDefault();
|
|
2972
|
+
handleCreateTag();
|
|
2973
|
+
}
|
|
2974
|
+
}
|
|
2975
|
+
}
|
|
2976
|
+
),
|
|
2977
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
2978
|
+
Button,
|
|
2979
|
+
{
|
|
2980
|
+
type: "button",
|
|
2981
|
+
onClick: handleCreateTag,
|
|
2982
|
+
disabled: !newTagName.trim(),
|
|
2983
|
+
children: config.labels?.addTag || "Add tag"
|
|
2984
|
+
}
|
|
2985
|
+
)
|
|
2986
|
+
] })
|
|
2987
|
+
] })
|
|
2988
|
+
] })
|
|
2989
|
+
}
|
|
2990
|
+
),
|
|
2697
2991
|
deleteThreadId && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
2698
2992
|
AlertDialog,
|
|
2699
2993
|
{
|
|
@@ -3154,6 +3448,20 @@ var ChatHeader = ({
|
|
|
3154
3448
|
] }),
|
|
3155
3449
|
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(DropdownMenuSeparator, {})
|
|
3156
3450
|
] }),
|
|
3451
|
+
config.headerMenuItems?.map((item) => /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
3452
|
+
DropdownMenuItem,
|
|
3453
|
+
{
|
|
3454
|
+
onClick: item.onSelect,
|
|
3455
|
+
disabled: item.disabled,
|
|
3456
|
+
variant: item.variant,
|
|
3457
|
+
children: [
|
|
3458
|
+
item.icon ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "h-4 w-4 mr-2 flex items-center justify-center", children: item.icon }) : null,
|
|
3459
|
+
item.label
|
|
3460
|
+
]
|
|
3461
|
+
},
|
|
3462
|
+
item.id
|
|
3463
|
+
)),
|
|
3464
|
+
config.headerMenuItems && config.headerMenuItems.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(DropdownMenuSeparator, {}),
|
|
3157
3465
|
onExportData && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(DropdownMenuItem, { onClick: onExportData, children: [
|
|
3158
3466
|
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react10.Download, { className: "h-4 w-4 mr-2" }),
|
|
3159
3467
|
config.labels?.exportData || "Export Data"
|
|
@@ -5391,9 +5699,10 @@ var ChatUI = ({
|
|
|
5391
5699
|
}, [attachments]);
|
|
5392
5700
|
const [isCustomMounted, setIsCustomMounted] = (0, import_react10.useState)(false);
|
|
5393
5701
|
const [isCustomVisible, setIsCustomVisible] = (0, import_react10.useState)(false);
|
|
5394
|
-
const groupedMessages = (0, import_react10.useMemo)(
|
|
5395
|
-
messages
|
|
5396
|
-
|
|
5702
|
+
const groupedMessages = (0, import_react10.useMemo)(
|
|
5703
|
+
() => groupMessagesForRender(messages),
|
|
5704
|
+
[messages]
|
|
5705
|
+
);
|
|
5397
5706
|
const virtualizer = (0, import_react_virtual.useVirtualizer)({
|
|
5398
5707
|
count: groupedMessages.length,
|
|
5399
5708
|
getScrollElement: () => scrollAreaRef.current,
|
|
@@ -5519,7 +5828,8 @@ var ChatUI = ({
|
|
|
5519
5828
|
});
|
|
5520
5829
|
}, [groupedMessages, isLoadingOlderMessages, virtualizer]);
|
|
5521
5830
|
const requestOlderMessages = (0, import_react10.useCallback)(() => {
|
|
5522
|
-
if (!onLoadOlderMessages || !hasMoreMessagesBefore || isLoadingOlderMessages)
|
|
5831
|
+
if (!onLoadOlderMessages || !hasMoreMessagesBefore || isLoadingOlderMessages)
|
|
5832
|
+
return;
|
|
5523
5833
|
const viewport = scrollAreaRef.current;
|
|
5524
5834
|
prependSnapshotRef.current = viewport ? {
|
|
5525
5835
|
scrollHeight: viewport.scrollHeight,
|
|
@@ -5551,55 +5861,68 @@ var ChatUI = ({
|
|
|
5551
5861
|
return next;
|
|
5552
5862
|
});
|
|
5553
5863
|
}, [groupedMessages]);
|
|
5554
|
-
const handleScroll = (0, import_react10.useCallback)(
|
|
5555
|
-
|
|
5556
|
-
|
|
5557
|
-
|
|
5558
|
-
|
|
5559
|
-
|
|
5560
|
-
|
|
5561
|
-
|
|
5562
|
-
|
|
5563
|
-
|
|
5564
|
-
|
|
5565
|
-
|
|
5566
|
-
|
|
5567
|
-
|
|
5568
|
-
|
|
5569
|
-
|
|
5570
|
-
|
|
5571
|
-
|
|
5572
|
-
|
|
5573
|
-
|
|
5574
|
-
|
|
5575
|
-
|
|
5576
|
-
|
|
5577
|
-
|
|
5578
|
-
|
|
5579
|
-
|
|
5580
|
-
|
|
5581
|
-
|
|
5582
|
-
|
|
5583
|
-
|
|
5584
|
-
|
|
5585
|
-
|
|
5586
|
-
|
|
5587
|
-
|
|
5588
|
-
|
|
5589
|
-
|
|
5590
|
-
|
|
5591
|
-
|
|
5592
|
-
|
|
5593
|
-
|
|
5594
|
-
|
|
5595
|
-
|
|
5596
|
-
|
|
5597
|
-
|
|
5598
|
-
|
|
5599
|
-
|
|
5600
|
-
|
|
5601
|
-
|
|
5602
|
-
|
|
5864
|
+
const handleScroll = (0, import_react10.useCallback)(
|
|
5865
|
+
(e) => {
|
|
5866
|
+
const { scrollTop, scrollHeight, clientHeight } = e.currentTarget;
|
|
5867
|
+
const isAtBottom = scrollHeight - scrollTop - clientHeight < 50;
|
|
5868
|
+
const isNearTop = scrollTop < 120;
|
|
5869
|
+
if (isNearTop && hasMoreMessagesBefore && !isLoadingOlderMessages) {
|
|
5870
|
+
requestOlderMessages();
|
|
5871
|
+
}
|
|
5872
|
+
setState((prev) => {
|
|
5873
|
+
if (prev.isAtBottom === isAtBottom) return prev;
|
|
5874
|
+
return { ...prev, isAtBottom };
|
|
5875
|
+
});
|
|
5876
|
+
},
|
|
5877
|
+
[hasMoreMessagesBefore, isLoadingOlderMessages, requestOlderMessages]
|
|
5878
|
+
);
|
|
5879
|
+
const handleSendMessage = (0, import_react10.useCallback)(
|
|
5880
|
+
(content, messageAttachments = []) => {
|
|
5881
|
+
if (!content.trim() && messageAttachments.length === 0) return;
|
|
5882
|
+
callbacks.onSendMessage?.(
|
|
5883
|
+
content,
|
|
5884
|
+
messageAttachments,
|
|
5885
|
+
createStateCallback()
|
|
5886
|
+
);
|
|
5887
|
+
if (initialInputApplied.current && !initialInputConsumedRef.current) {
|
|
5888
|
+
initialInputConsumedRef.current = true;
|
|
5889
|
+
onInitialInputConsumed?.();
|
|
5890
|
+
}
|
|
5891
|
+
setInputValue("");
|
|
5892
|
+
setAttachments([]);
|
|
5893
|
+
},
|
|
5894
|
+
[callbacks, createStateCallback, onInitialInputConsumed]
|
|
5895
|
+
);
|
|
5896
|
+
const handleMessageAction = (0, import_react10.useCallback)(
|
|
5897
|
+
(event) => {
|
|
5898
|
+
const { action, messageId, content } = event;
|
|
5899
|
+
switch (action) {
|
|
5900
|
+
case "copy":
|
|
5901
|
+
callbacks.onCopyMessage?.(
|
|
5902
|
+
messageId,
|
|
5903
|
+
content || "",
|
|
5904
|
+
createStateCallback()
|
|
5905
|
+
);
|
|
5906
|
+
break;
|
|
5907
|
+
case "edit":
|
|
5908
|
+
if (content) {
|
|
5909
|
+
callbacks.onEditMessage?.(
|
|
5910
|
+
messageId,
|
|
5911
|
+
content,
|
|
5912
|
+
createStateCallback()
|
|
5913
|
+
);
|
|
5914
|
+
}
|
|
5915
|
+
break;
|
|
5916
|
+
case "regenerate":
|
|
5917
|
+
callbacks.onRegenerateMessage?.(messageId, createStateCallback());
|
|
5918
|
+
break;
|
|
5919
|
+
case "delete":
|
|
5920
|
+
callbacks.onDeleteMessage?.(messageId, createStateCallback());
|
|
5921
|
+
break;
|
|
5922
|
+
}
|
|
5923
|
+
},
|
|
5924
|
+
[callbacks, createStateCallback]
|
|
5925
|
+
);
|
|
5603
5926
|
const handleToggleMessageExpansion = (0, import_react10.useCallback)((messageId) => {
|
|
5604
5927
|
setExpandedMessageIds((prev) => {
|
|
5605
5928
|
if (prev[messageId]) {
|
|
@@ -5613,51 +5936,79 @@ var ChatUI = ({
|
|
|
5613
5936
|
};
|
|
5614
5937
|
});
|
|
5615
5938
|
}, []);
|
|
5616
|
-
const handleCreateThread = (0, import_react10.useCallback)(
|
|
5617
|
-
|
|
5618
|
-
|
|
5619
|
-
|
|
5620
|
-
callbacks
|
|
5621
|
-
|
|
5939
|
+
const handleCreateThread = (0, import_react10.useCallback)(
|
|
5940
|
+
(title) => {
|
|
5941
|
+
callbacks.onCreateThread?.(title, createStateCallback());
|
|
5942
|
+
},
|
|
5943
|
+
[callbacks, createStateCallback]
|
|
5944
|
+
);
|
|
5945
|
+
const handleSelectThread = (0, import_react10.useCallback)(
|
|
5946
|
+
(threadId) => {
|
|
5947
|
+
callbacks.onSelectThread?.(threadId, createStateCallback());
|
|
5948
|
+
},
|
|
5949
|
+
[callbacks, createStateCallback]
|
|
5950
|
+
);
|
|
5622
5951
|
const handleRenameThread = (0, import_react10.useCallback)(
|
|
5623
5952
|
(threadId, newTitle) => {
|
|
5624
5953
|
callbacks.onRenameThread?.(threadId, newTitle, createStateCallback());
|
|
5625
5954
|
},
|
|
5626
5955
|
[callbacks, createStateCallback]
|
|
5627
5956
|
);
|
|
5628
|
-
const handleDeleteThread = (0, import_react10.useCallback)(
|
|
5629
|
-
|
|
5630
|
-
|
|
5631
|
-
|
|
5632
|
-
callbacks
|
|
5633
|
-
|
|
5957
|
+
const handleDeleteThread = (0, import_react10.useCallback)(
|
|
5958
|
+
(threadId) => {
|
|
5959
|
+
callbacks.onDeleteThread?.(threadId, createStateCallback());
|
|
5960
|
+
},
|
|
5961
|
+
[callbacks, createStateCallback]
|
|
5962
|
+
);
|
|
5963
|
+
const handleArchiveThread = (0, import_react10.useCallback)(
|
|
5964
|
+
(threadId) => {
|
|
5965
|
+
callbacks.onArchiveThread?.(threadId, createStateCallback());
|
|
5966
|
+
},
|
|
5967
|
+
[callbacks, createStateCallback]
|
|
5968
|
+
);
|
|
5969
|
+
const handleUpdateThreadTags = (0, import_react10.useCallback)(
|
|
5970
|
+
(threadId, tags) => {
|
|
5971
|
+
callbacks.onUpdateThreadTags?.(
|
|
5972
|
+
threadId,
|
|
5973
|
+
tags ?? [],
|
|
5974
|
+
createStateCallback()
|
|
5975
|
+
);
|
|
5976
|
+
},
|
|
5977
|
+
[callbacks, createStateCallback]
|
|
5978
|
+
);
|
|
5634
5979
|
const closeSidebar = (0, import_react10.useCallback)(() => {
|
|
5635
5980
|
setState((prev) => ({ ...prev, showSidebar: false }));
|
|
5636
5981
|
}, []);
|
|
5637
5982
|
const handleCustomComponentToggle = (0, import_react10.useCallback)(() => {
|
|
5638
5983
|
setState((prev) => ({ ...prev, showSidebar: !prev.showSidebar }));
|
|
5639
5984
|
}, []);
|
|
5640
|
-
const sidebarUser = (0, import_react10.useMemo)(
|
|
5641
|
-
|
|
5642
|
-
|
|
5643
|
-
|
|
5644
|
-
|
|
5645
|
-
|
|
5985
|
+
const sidebarUser = (0, import_react10.useMemo)(
|
|
5986
|
+
() => user ? {
|
|
5987
|
+
id: user.id,
|
|
5988
|
+
name: user.name,
|
|
5989
|
+
email: user.email,
|
|
5990
|
+
avatar: user.avatar
|
|
5991
|
+
} : null,
|
|
5992
|
+
[user?.id, user?.name, user?.email, user?.avatar]
|
|
5993
|
+
);
|
|
5646
5994
|
const handleViewProfile = (0, import_react10.useCallback)(() => {
|
|
5647
5995
|
setIsUserProfileOpen(true);
|
|
5648
5996
|
callbacks.onViewProfile?.();
|
|
5649
5997
|
}, [callbacks.onViewProfile]);
|
|
5650
|
-
const sidebarUserMenuCallbacks = (0, import_react10.useMemo)(
|
|
5651
|
-
|
|
5652
|
-
|
|
5653
|
-
|
|
5654
|
-
|
|
5655
|
-
|
|
5656
|
-
|
|
5657
|
-
|
|
5658
|
-
|
|
5659
|
-
|
|
5660
|
-
|
|
5998
|
+
const sidebarUserMenuCallbacks = (0, import_react10.useMemo)(
|
|
5999
|
+
() => ({
|
|
6000
|
+
onViewProfile: handleViewProfile,
|
|
6001
|
+
onOpenSettings: callbacks.onOpenSettings,
|
|
6002
|
+
onThemeChange: callbacks.onThemeChange,
|
|
6003
|
+
onLogout: callbacks.onLogout
|
|
6004
|
+
}),
|
|
6005
|
+
[
|
|
6006
|
+
handleViewProfile,
|
|
6007
|
+
callbacks.onOpenSettings,
|
|
6008
|
+
callbacks.onThemeChange,
|
|
6009
|
+
callbacks.onLogout
|
|
6010
|
+
]
|
|
6011
|
+
);
|
|
5661
6012
|
const renderCustomComponent = (0, import_react10.useCallback)(() => {
|
|
5662
6013
|
const component = config?.customComponent?.component;
|
|
5663
6014
|
if (!component) return null;
|
|
@@ -5738,55 +6089,58 @@ var ChatUI = ({
|
|
|
5738
6089
|
);
|
|
5739
6090
|
}) });
|
|
5740
6091
|
const isMultiAgentMode = config.agentSelector?.mode === "multi";
|
|
5741
|
-
const messageProps = (0, import_react10.useMemo)(
|
|
5742
|
-
|
|
5743
|
-
|
|
5744
|
-
|
|
5745
|
-
|
|
5746
|
-
|
|
5747
|
-
|
|
5748
|
-
|
|
5749
|
-
|
|
5750
|
-
|
|
5751
|
-
|
|
5752
|
-
|
|
5753
|
-
|
|
5754
|
-
|
|
5755
|
-
|
|
5756
|
-
|
|
5757
|
-
|
|
5758
|
-
|
|
5759
|
-
|
|
5760
|
-
|
|
5761
|
-
|
|
5762
|
-
|
|
5763
|
-
|
|
5764
|
-
|
|
5765
|
-
|
|
5766
|
-
|
|
5767
|
-
|
|
5768
|
-
|
|
5769
|
-
|
|
5770
|
-
|
|
5771
|
-
|
|
5772
|
-
|
|
5773
|
-
|
|
5774
|
-
|
|
5775
|
-
|
|
5776
|
-
|
|
5777
|
-
|
|
5778
|
-
|
|
5779
|
-
|
|
5780
|
-
|
|
5781
|
-
|
|
5782
|
-
|
|
5783
|
-
|
|
5784
|
-
|
|
5785
|
-
|
|
5786
|
-
|
|
5787
|
-
|
|
5788
|
-
|
|
5789
|
-
|
|
6092
|
+
const messageProps = (0, import_react10.useMemo)(
|
|
6093
|
+
() => ({
|
|
6094
|
+
userAvatar: user?.avatar,
|
|
6095
|
+
userName: user?.name,
|
|
6096
|
+
assistantAvatar: assistant?.avatar,
|
|
6097
|
+
assistantName: assistant?.name,
|
|
6098
|
+
showTimestamp: config.ui.showTimestamps,
|
|
6099
|
+
showAvatar: config.ui.showAvatars,
|
|
6100
|
+
enableCopy: config.features.enableMessageCopy,
|
|
6101
|
+
enableEdit: config.features.enableMessageEditing,
|
|
6102
|
+
enableRegenerate: config.features.enableRegeneration,
|
|
6103
|
+
showActivity: config.features.showActivity,
|
|
6104
|
+
showActivityDetails: config.features.showActivityDetails,
|
|
6105
|
+
compactMode: config.ui.compactMode,
|
|
6106
|
+
onAction: handleMessageAction,
|
|
6107
|
+
labels: config.labels,
|
|
6108
|
+
showMoreLabel: config.labels.showMoreMessage,
|
|
6109
|
+
showLessLabel: config.labels.showLessMessage,
|
|
6110
|
+
collapseLongMessages: config.ui.collapseLongMessages,
|
|
6111
|
+
collapseLongMessagesForUserOnly: config.ui.collapseLongMessagesForUserOnly,
|
|
6112
|
+
longMessagePreviewChars: config.ui.longMessagePreviewChars,
|
|
6113
|
+
longMessageChunkChars: config.ui.longMessageChunkChars,
|
|
6114
|
+
renderUserMarkdown: config.ui.renderUserMarkdown,
|
|
6115
|
+
markdown: config.markdown,
|
|
6116
|
+
onToggleExpanded: handleToggleMessageExpansion
|
|
6117
|
+
}),
|
|
6118
|
+
[
|
|
6119
|
+
user?.avatar,
|
|
6120
|
+
user?.name,
|
|
6121
|
+
assistant?.avatar,
|
|
6122
|
+
assistant?.name,
|
|
6123
|
+
config.ui.showTimestamps,
|
|
6124
|
+
config.ui.showAvatars,
|
|
6125
|
+
config.ui.compactMode,
|
|
6126
|
+
config.features.enableMessageCopy,
|
|
6127
|
+
config.features.enableMessageEditing,
|
|
6128
|
+
config.features.enableRegeneration,
|
|
6129
|
+
config.features.showActivity,
|
|
6130
|
+
config.features.showActivityDetails,
|
|
6131
|
+
config.labels,
|
|
6132
|
+
config.labels.showMoreMessage,
|
|
6133
|
+
config.labels.showLessMessage,
|
|
6134
|
+
config.ui.collapseLongMessages,
|
|
6135
|
+
config.ui.collapseLongMessagesForUserOnly,
|
|
6136
|
+
config.ui.longMessagePreviewChars,
|
|
6137
|
+
config.ui.longMessageChunkChars,
|
|
6138
|
+
config.ui.renderUserMarkdown,
|
|
6139
|
+
config.markdown,
|
|
6140
|
+
handleMessageAction,
|
|
6141
|
+
handleToggleMessageExpansion
|
|
6142
|
+
]
|
|
6143
|
+
);
|
|
5790
6144
|
const shouldShowAgentSelector = Boolean(
|
|
5791
6145
|
config.agentSelector?.enabled && agentOptions.length > 0 && (!config.agentSelector?.hideIfSingle || agentOptions.length > 1) && (isMultiAgentMode ? onParticipantsChange : onSelectAgent)
|
|
5792
6146
|
);
|
|
@@ -5806,6 +6160,7 @@ var ChatUI = ({
|
|
|
5806
6160
|
onRenameThread: handleRenameThread,
|
|
5807
6161
|
onDeleteThread: handleDeleteThread,
|
|
5808
6162
|
onArchiveThread: handleArchiveThread,
|
|
6163
|
+
onUpdateThreadTags: handleUpdateThreadTags,
|
|
5809
6164
|
user: sidebarUser,
|
|
5810
6165
|
userMenuCallbacks: sidebarUserMenuCallbacks,
|
|
5811
6166
|
currentTheme: config.ui.theme === "auto" ? "system" : config.ui.theme,
|
|
@@ -5819,9 +6174,7 @@ var ChatUI = ({
|
|
|
5819
6174
|
ChatHeader,
|
|
5820
6175
|
{
|
|
5821
6176
|
config,
|
|
5822
|
-
currentThreadTitle: threads.find(
|
|
5823
|
-
(t) => t.id === state.selectedThreadId
|
|
5824
|
-
)?.title,
|
|
6177
|
+
currentThreadTitle: threads.find((t) => t.id === state.selectedThreadId)?.title,
|
|
5825
6178
|
isMobile,
|
|
5826
6179
|
onCustomComponentToggle: handleCustomComponentToggle,
|
|
5827
6180
|
onNewThread: handleCreateThread,
|