@djangocfg/ui-tools 2.1.368 → 2.1.371
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/ChatRoot-DYMCNGOB.mjs +5 -0
- package/dist/{ChatRoot-6U7633X3.mjs.map → ChatRoot-DYMCNGOB.mjs.map} +1 -1
- package/dist/ChatRoot-HOQ37WRE.cjs +14 -0
- package/dist/{ChatRoot-HARTIAJ5.cjs.map → ChatRoot-HOQ37WRE.cjs.map} +1 -1
- package/dist/{chunk-OPKFKTIN.cjs → chunk-2SKR4U5S.cjs} +160 -203
- package/dist/chunk-2SKR4U5S.cjs.map +1 -0
- package/dist/{chunk-WGU5BEZX.mjs → chunk-MVAT6OPZ.mjs} +163 -204
- package/dist/chunk-MVAT6OPZ.mjs.map +1 -0
- package/dist/index.cjs +181 -55
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +113 -4
- package/dist/index.d.ts +113 -4
- package/dist/index.mjs +136 -4
- package/dist/index.mjs.map +1 -1
- package/package.json +7 -6
- package/src/tools/Chat/README.md +22 -1
- package/src/tools/Chat/components/ChatRoot.tsx +15 -28
- package/src/tools/Chat/components/MessageBubble.tsx +37 -9
- package/src/tools/Chat/components/MessageList.tsx +203 -27
- package/src/tools/Chat/components/index.ts +5 -1
- package/src/tools/Chat/context/ChatProvider.tsx +8 -0
- package/src/tools/Chat/hooks/useChat.ts +24 -3
- package/src/tools/Chat/hooks/useChatComposer.ts +39 -1
- package/src/tools/Chat/hooks/useChatScroll.ts +13 -0
- package/src/tools/Chat/index.ts +1 -0
- package/src/tools/Chat/types.ts +6 -0
- package/dist/ChatRoot-6U7633X3.mjs +0 -5
- package/dist/ChatRoot-HARTIAJ5.cjs +0 -14
- package/dist/chunk-OPKFKTIN.cjs.map +0 -1
- package/dist/chunk-WGU5BEZX.mjs.map +0 -1
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import { MarkdownMessage } from './chunk-NWUT327A.mjs';
|
|
2
2
|
import { __name } from './chunk-N2XQF2OL.mjs';
|
|
3
|
-
import { createContext, forwardRef, memo, useCallback,
|
|
3
|
+
import { createContext, forwardRef, memo, useRef, useImperativeHandle, useCallback, useMemo, useReducer, useEffect, useState, useSyncExternalStore, useContext } from 'react';
|
|
4
4
|
import { cn, isDev } from '@djangocfg/ui-core/lib';
|
|
5
5
|
import { consola } from 'consola';
|
|
6
|
-
import { useLocalStorage, useMediaQuery } from '@djangocfg/ui-core/hooks';
|
|
6
|
+
import { useCopy, useLocalStorage, useMediaQuery } from '@djangocfg/ui-core/hooks';
|
|
7
7
|
import { create } from 'zustand';
|
|
8
8
|
import { persist, createJSONStorage } from 'zustand/middleware';
|
|
9
9
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
10
10
|
import { Paperclip, Square, Send, File, X, Sparkles, AlertCircle, RefreshCw, ArrowDown, ExternalLink, ChevronDown, ChevronRight, Loader2, Copy, Pencil, Trash } from 'lucide-react';
|
|
11
11
|
import { Button, Textarea, Spinner, Avatar, AvatarImage, AvatarFallback } from '@djangocfg/ui-core/components';
|
|
12
|
+
import { Virtuoso } from 'react-virtuoso';
|
|
12
13
|
|
|
13
14
|
// src/tools/Chat/types.ts
|
|
14
15
|
var DEFAULT_LABELS = {
|
|
@@ -692,13 +693,21 @@ function useChat(config) {
|
|
|
692
693
|
};
|
|
693
694
|
dispatch({ type: "MESSAGE_USER_ADD", message: userMsg });
|
|
694
695
|
config.onMessageSent?.(userMsg);
|
|
696
|
+
let outbound = content;
|
|
697
|
+
if (config.onBeforeSend) {
|
|
698
|
+
try {
|
|
699
|
+
outbound = await config.onBeforeSend(content);
|
|
700
|
+
} catch (err) {
|
|
701
|
+
log.error.error("onBeforeSend threw \u2014 falling back to original content", err);
|
|
702
|
+
}
|
|
703
|
+
}
|
|
695
704
|
if (streaming) {
|
|
696
|
-
await consumeStream(sessionId,
|
|
705
|
+
await consumeStream(sessionId, outbound, attachments);
|
|
697
706
|
} else {
|
|
698
|
-
await consumeBuffered(sessionId,
|
|
707
|
+
await consumeBuffered(sessionId, outbound, attachments);
|
|
699
708
|
}
|
|
700
709
|
},
|
|
701
|
-
[streaming, consumeStream, consumeBuffered, config, awaitSession]
|
|
710
|
+
[streaming, consumeStream, consumeBuffered, config, awaitSession, log]
|
|
702
711
|
);
|
|
703
712
|
const cancelStream = useCallback(() => {
|
|
704
713
|
abortRef.current?.abort();
|
|
@@ -1198,6 +1207,7 @@ function ChatProvider({
|
|
|
1198
1207
|
streaming,
|
|
1199
1208
|
audio,
|
|
1200
1209
|
debug,
|
|
1210
|
+
onBeforeSend,
|
|
1201
1211
|
children
|
|
1202
1212
|
}) {
|
|
1203
1213
|
const audioApi = useChatAudio(audio ?? {});
|
|
@@ -1221,7 +1231,8 @@ function ChatProvider({
|
|
|
1221
1231
|
onMessageSent,
|
|
1222
1232
|
onMessageEnd,
|
|
1223
1233
|
onStreamStart,
|
|
1224
|
-
onError
|
|
1234
|
+
onError,
|
|
1235
|
+
onBeforeSend
|
|
1225
1236
|
});
|
|
1226
1237
|
const layout = useChatLayout({ defaultMode: "embedded" });
|
|
1227
1238
|
const rootRef = useRef(null);
|
|
@@ -1277,9 +1288,28 @@ function useChatComposer(options) {
|
|
|
1277
1288
|
disabled = false,
|
|
1278
1289
|
submitOn = "enter",
|
|
1279
1290
|
history = { enabled: true, size: LIMITS.composerHistorySize },
|
|
1280
|
-
onPasteFiles
|
|
1291
|
+
onPasteFiles,
|
|
1292
|
+
persistKey
|
|
1281
1293
|
} = options;
|
|
1282
|
-
const
|
|
1294
|
+
const initialFromStorage = (() => {
|
|
1295
|
+
if (!persistKey || typeof window === "undefined") return initialValue;
|
|
1296
|
+
try {
|
|
1297
|
+
const stored = window.sessionStorage.getItem(`chat:draft:${persistKey}`);
|
|
1298
|
+
return stored && stored.length > 0 ? stored : initialValue;
|
|
1299
|
+
} catch {
|
|
1300
|
+
return initialValue;
|
|
1301
|
+
}
|
|
1302
|
+
})();
|
|
1303
|
+
const [value, setValueState] = useState(initialFromStorage);
|
|
1304
|
+
useEffect(() => {
|
|
1305
|
+
if (!persistKey || typeof window === "undefined") return;
|
|
1306
|
+
try {
|
|
1307
|
+
const k = `chat:draft:${persistKey}`;
|
|
1308
|
+
if (value.length > 0) window.sessionStorage.setItem(k, value);
|
|
1309
|
+
else window.sessionStorage.removeItem(k);
|
|
1310
|
+
} catch {
|
|
1311
|
+
}
|
|
1312
|
+
}, [value, persistKey]);
|
|
1283
1313
|
const [attachments, setAttachments] = useState([]);
|
|
1284
1314
|
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
1285
1315
|
const textareaRef = useRef(null);
|
|
@@ -1424,138 +1454,6 @@ function useChatComposer(options) {
|
|
|
1424
1454
|
};
|
|
1425
1455
|
}
|
|
1426
1456
|
__name(useChatComposer, "useChatComposer");
|
|
1427
|
-
function useChatScroll(options) {
|
|
1428
|
-
const {
|
|
1429
|
-
containerRef,
|
|
1430
|
-
bottomRef,
|
|
1431
|
-
isStreaming = false,
|
|
1432
|
-
bottomThresholdPx = 80,
|
|
1433
|
-
messagesCount = 0
|
|
1434
|
-
} = options;
|
|
1435
|
-
const [isAtBottom, setIsAtBottom] = useState(true);
|
|
1436
|
-
const [unreadCount, setUnreadCount] = useState(0);
|
|
1437
|
-
const lastCountRef = useRef(messagesCount);
|
|
1438
|
-
const stickyRef = useRef(true);
|
|
1439
|
-
const wasStreamingRef = useRef(isStreaming);
|
|
1440
|
-
const scrollToBottom = useCallback(
|
|
1441
|
-
(smooth = false) => {
|
|
1442
|
-
const el = containerRef.current;
|
|
1443
|
-
if (!el) return;
|
|
1444
|
-
el.scrollTo({
|
|
1445
|
-
top: el.scrollHeight,
|
|
1446
|
-
behavior: smooth ? "smooth" : "auto"
|
|
1447
|
-
});
|
|
1448
|
-
stickyRef.current = true;
|
|
1449
|
-
setIsAtBottom(true);
|
|
1450
|
-
setUnreadCount(0);
|
|
1451
|
-
},
|
|
1452
|
-
[containerRef]
|
|
1453
|
-
);
|
|
1454
|
-
const resetUnread = useCallback(() => setUnreadCount(0), []);
|
|
1455
|
-
useEffect(() => {
|
|
1456
|
-
const el = containerRef.current;
|
|
1457
|
-
if (!el) return;
|
|
1458
|
-
const onScroll = /* @__PURE__ */ __name(() => {
|
|
1459
|
-
const distance = el.scrollHeight - el.scrollTop - el.clientHeight;
|
|
1460
|
-
const atBottom = distance <= bottomThresholdPx;
|
|
1461
|
-
stickyRef.current = atBottom;
|
|
1462
|
-
setIsAtBottom(atBottom);
|
|
1463
|
-
if (atBottom) setUnreadCount(0);
|
|
1464
|
-
}, "onScroll");
|
|
1465
|
-
onScroll();
|
|
1466
|
-
el.addEventListener("scroll", onScroll, { passive: true });
|
|
1467
|
-
return () => {
|
|
1468
|
-
el.removeEventListener("scroll", onScroll);
|
|
1469
|
-
};
|
|
1470
|
-
}, [containerRef, bottomThresholdPx]);
|
|
1471
|
-
useEffect(() => {
|
|
1472
|
-
const el = containerRef.current;
|
|
1473
|
-
if (!el) return;
|
|
1474
|
-
if (isStreaming) {
|
|
1475
|
-
wasStreamingRef.current = true;
|
|
1476
|
-
if (!stickyRef.current) return;
|
|
1477
|
-
let raf = 0;
|
|
1478
|
-
const tick = /* @__PURE__ */ __name(() => {
|
|
1479
|
-
if (!stickyRef.current) return;
|
|
1480
|
-
el.scrollTop = el.scrollHeight;
|
|
1481
|
-
raf = requestAnimationFrame(tick);
|
|
1482
|
-
}, "tick");
|
|
1483
|
-
raf = requestAnimationFrame(tick);
|
|
1484
|
-
return () => cancelAnimationFrame(raf);
|
|
1485
|
-
}
|
|
1486
|
-
if (wasStreamingRef.current && stickyRef.current) {
|
|
1487
|
-
wasStreamingRef.current = false;
|
|
1488
|
-
let raf1 = 0;
|
|
1489
|
-
let raf2 = 0;
|
|
1490
|
-
raf1 = requestAnimationFrame(() => {
|
|
1491
|
-
el.scrollTop = el.scrollHeight;
|
|
1492
|
-
raf2 = requestAnimationFrame(() => {
|
|
1493
|
-
el.scrollTop = el.scrollHeight;
|
|
1494
|
-
});
|
|
1495
|
-
});
|
|
1496
|
-
return () => {
|
|
1497
|
-
cancelAnimationFrame(raf1);
|
|
1498
|
-
cancelAnimationFrame(raf2);
|
|
1499
|
-
};
|
|
1500
|
-
}
|
|
1501
|
-
wasStreamingRef.current = false;
|
|
1502
|
-
return;
|
|
1503
|
-
}, [containerRef, isStreaming]);
|
|
1504
|
-
useEffect(() => {
|
|
1505
|
-
if (messagesCount > lastCountRef.current) {
|
|
1506
|
-
if (stickyRef.current) {
|
|
1507
|
-
const el = containerRef.current;
|
|
1508
|
-
if (el) el.scrollTop = el.scrollHeight;
|
|
1509
|
-
} else {
|
|
1510
|
-
setUnreadCount((n) => n + (messagesCount - lastCountRef.current));
|
|
1511
|
-
}
|
|
1512
|
-
}
|
|
1513
|
-
lastCountRef.current = messagesCount;
|
|
1514
|
-
}, [containerRef, messagesCount]);
|
|
1515
|
-
useEffect(() => {
|
|
1516
|
-
}, [bottomRef]);
|
|
1517
|
-
return { isAtBottom, unreadCount, scrollToBottom, resetUnread };
|
|
1518
|
-
}
|
|
1519
|
-
__name(useChatScroll, "useChatScroll");
|
|
1520
|
-
function useChatHistory(options) {
|
|
1521
|
-
const { enabled = true, containerRef, topSentinelRef, hasMore, isLoadingMore, loadMore } = options;
|
|
1522
|
-
const heightBeforeRef = useRef(null);
|
|
1523
|
-
useEffect(() => {
|
|
1524
|
-
if (heightBeforeRef.current == null) return;
|
|
1525
|
-
const el = containerRef.current;
|
|
1526
|
-
if (!el) {
|
|
1527
|
-
heightBeforeRef.current = null;
|
|
1528
|
-
return;
|
|
1529
|
-
}
|
|
1530
|
-
if (!isLoadingMore) {
|
|
1531
|
-
const delta = el.scrollHeight - heightBeforeRef.current;
|
|
1532
|
-
if (delta > 0) {
|
|
1533
|
-
el.scrollTop += delta;
|
|
1534
|
-
}
|
|
1535
|
-
heightBeforeRef.current = null;
|
|
1536
|
-
}
|
|
1537
|
-
}, [containerRef, isLoadingMore]);
|
|
1538
|
-
useEffect(() => {
|
|
1539
|
-
if (!enabled || !hasMore) return;
|
|
1540
|
-
const sentinel = topSentinelRef.current;
|
|
1541
|
-
const root = containerRef.current;
|
|
1542
|
-
if (!sentinel || !root) return;
|
|
1543
|
-
const observer = new IntersectionObserver(
|
|
1544
|
-
(entries) => {
|
|
1545
|
-
const entry = entries[0];
|
|
1546
|
-
if (!entry?.isIntersecting) return;
|
|
1547
|
-
if (isLoadingMore) return;
|
|
1548
|
-
const el = containerRef.current;
|
|
1549
|
-
if (el) heightBeforeRef.current = el.scrollHeight;
|
|
1550
|
-
void loadMore();
|
|
1551
|
-
},
|
|
1552
|
-
{ root, threshold: 0, rootMargin: "200px 0px 0px 0px" }
|
|
1553
|
-
);
|
|
1554
|
-
observer.observe(sentinel);
|
|
1555
|
-
return () => observer.disconnect();
|
|
1556
|
-
}, [enabled, hasMore, isLoadingMore, containerRef, topSentinelRef, loadMore]);
|
|
1557
|
-
}
|
|
1558
|
-
__name(useChatHistory, "useChatHistory");
|
|
1559
1457
|
function AttachmentsGrid({
|
|
1560
1458
|
attachments,
|
|
1561
1459
|
maxVisible,
|
|
@@ -2135,7 +2033,9 @@ var MessageBubbleInner = /* @__PURE__ */ __name(({
|
|
|
2135
2033
|
onCopy,
|
|
2136
2034
|
onRegenerate,
|
|
2137
2035
|
onEdit,
|
|
2138
|
-
onDelete
|
|
2036
|
+
onDelete,
|
|
2037
|
+
messageActionsExtra,
|
|
2038
|
+
streamingIndicator
|
|
2139
2039
|
}) => {
|
|
2140
2040
|
const isUser = isUserProp ?? message.role === "user";
|
|
2141
2041
|
const isStreaming = !!message.isStreaming;
|
|
@@ -2198,7 +2098,7 @@ var MessageBubbleInner = /* @__PURE__ */ __name(({
|
|
|
2198
2098
|
isUser ? "bg-primary text-primary-foreground rounded-tr-md" : isErr ? "bg-destructive/10 text-destructive rounded-tl-md border border-destructive/30" : "bg-muted text-foreground rounded-tl-md"
|
|
2199
2099
|
),
|
|
2200
2100
|
children: [
|
|
2201
|
-
isStreaming && message.toolActivity ? /* @__PURE__ */ jsx("div", { className: "mb-1.5", children: /* @__PURE__ */ jsx(StreamingIndicator, { label: message.toolActivity }) }) : null,
|
|
2101
|
+
isStreaming && message.toolActivity ? /* @__PURE__ */ jsx("div", { className: "mb-1.5", children: streamingIndicator ? streamingIndicator(message) : /* @__PURE__ */ jsx(StreamingIndicator, { label: message.toolActivity }) }) : null,
|
|
2202
2102
|
message.content || !isStreaming ? /* @__PURE__ */ jsx(
|
|
2203
2103
|
MarkdownMessage,
|
|
2204
2104
|
{
|
|
@@ -2207,22 +2107,25 @@ var MessageBubbleInner = /* @__PURE__ */ __name(({
|
|
|
2207
2107
|
isCompact,
|
|
2208
2108
|
plainText: isStreaming
|
|
2209
2109
|
}
|
|
2210
|
-
) : /* @__PURE__ */ jsx(StreamingIndicator, {})
|
|
2110
|
+
) : streamingIndicator ? streamingIndicator(message) : /* @__PURE__ */ jsx(StreamingIndicator, {})
|
|
2211
2111
|
]
|
|
2212
2112
|
}
|
|
2213
2113
|
),
|
|
2214
2114
|
message.toolCalls?.length ? toolCallsRenderer ? toolCallsRenderer(message.toolCalls) : /* @__PURE__ */ jsx(ToolCalls, { calls: message.toolCalls, ...toolCallsProps }) : null,
|
|
2215
2115
|
message.sources?.length && !isStreaming ? sourcesRenderer ? sourcesRenderer(message.sources) : /* @__PURE__ */ jsx(Sources, { sources: message.sources }) : null,
|
|
2216
|
-
showActions && !isStreaming ? /* @__PURE__ */
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2116
|
+
showActions && !isStreaming ? /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-0.5", children: [
|
|
2117
|
+
/* @__PURE__ */ jsx(
|
|
2118
|
+
MessageActions,
|
|
2119
|
+
{
|
|
2120
|
+
role: message.role,
|
|
2121
|
+
onCopy,
|
|
2122
|
+
onRegenerate,
|
|
2123
|
+
onEdit,
|
|
2124
|
+
onDelete
|
|
2125
|
+
}
|
|
2126
|
+
),
|
|
2127
|
+
messageActionsExtra ? messageActionsExtra(message) : null
|
|
2128
|
+
] }) : null,
|
|
2226
2129
|
showTimestamp ? /* @__PURE__ */ jsx("div", { className: "mt-1 text-[10px] text-muted-foreground", children: new Date(message.createdAt).toLocaleTimeString() }) : null,
|
|
2227
2130
|
afterContent
|
|
2228
2131
|
] })
|
|
@@ -2241,50 +2144,120 @@ var MessageList = forwardRef(/* @__PURE__ */ __name(function MessageList2({
|
|
|
2241
2144
|
renderItem,
|
|
2242
2145
|
renderEmpty,
|
|
2243
2146
|
isLoadingMore: isLoadingMoreProp,
|
|
2244
|
-
|
|
2245
|
-
bottomRef,
|
|
2147
|
+
onStartReached,
|
|
2246
2148
|
className,
|
|
2247
|
-
itemClassName
|
|
2149
|
+
itemClassName,
|
|
2150
|
+
noVirtualize = false,
|
|
2151
|
+
defaultItemHeight = 120,
|
|
2152
|
+
onAtBottomChange
|
|
2248
2153
|
}, ref) {
|
|
2249
2154
|
const ctx = useChatContextOptional();
|
|
2250
2155
|
const messages = messagesProp ?? ctx?.messages ?? [];
|
|
2251
2156
|
const isLoadingMore = isLoadingMoreProp ?? ctx?.isLoadingMore ?? false;
|
|
2157
|
+
const { copyToClipboard } = useCopy();
|
|
2158
|
+
const virtuosoRef = useRef(null);
|
|
2159
|
+
useImperativeHandle(
|
|
2160
|
+
ref,
|
|
2161
|
+
() => ({
|
|
2162
|
+
scrollToBottom: /* @__PURE__ */ __name((smooth = false) => {
|
|
2163
|
+
virtuosoRef.current?.scrollToIndex({
|
|
2164
|
+
index: "LAST",
|
|
2165
|
+
behavior: smooth ? "smooth" : "auto",
|
|
2166
|
+
align: "end"
|
|
2167
|
+
});
|
|
2168
|
+
}, "scrollToBottom"),
|
|
2169
|
+
scrollToIndex: /* @__PURE__ */ __name((index, smooth = false) => {
|
|
2170
|
+
virtuosoRef.current?.scrollToIndex({
|
|
2171
|
+
index,
|
|
2172
|
+
behavior: smooth ? "smooth" : "auto"
|
|
2173
|
+
});
|
|
2174
|
+
}, "scrollToIndex")
|
|
2175
|
+
}),
|
|
2176
|
+
[]
|
|
2177
|
+
);
|
|
2252
2178
|
const defaultRenderItem = useCallback(
|
|
2253
2179
|
(m) => /* @__PURE__ */ jsx("div", { className: itemClassName, children: /* @__PURE__ */ jsx(
|
|
2254
2180
|
MessageBubble,
|
|
2255
2181
|
{
|
|
2256
2182
|
message: m,
|
|
2257
|
-
onCopy: () =>
|
|
2183
|
+
onCopy: () => void copyToClipboard(m.content),
|
|
2258
2184
|
onRegenerate: ctx ? () => void ctx.regenerate(m.id) : void 0,
|
|
2259
2185
|
onDelete: ctx ? () => ctx.deleteMessage(m.id) : void 0
|
|
2260
2186
|
}
|
|
2261
|
-
) }
|
|
2262
|
-
[itemClassName, ctx]
|
|
2187
|
+
) }),
|
|
2188
|
+
[itemClassName, ctx, copyToClipboard]
|
|
2263
2189
|
);
|
|
2264
2190
|
const itemRenderer = renderItem ?? defaultRenderItem;
|
|
2265
|
-
|
|
2266
|
-
|
|
2191
|
+
const computeItemKey = useCallback(
|
|
2192
|
+
(index, m) => m?.id ?? index,
|
|
2193
|
+
[]
|
|
2194
|
+
);
|
|
2195
|
+
const startReachedHandler = useMemo(() => {
|
|
2196
|
+
if (!onStartReached) return void 0;
|
|
2197
|
+
let inFlight = false;
|
|
2198
|
+
return () => {
|
|
2199
|
+
if (inFlight || isLoadingMore) return;
|
|
2200
|
+
inFlight = true;
|
|
2201
|
+
try {
|
|
2202
|
+
onStartReached();
|
|
2203
|
+
} finally {
|
|
2204
|
+
queueMicrotask(() => {
|
|
2205
|
+
inFlight = false;
|
|
2206
|
+
});
|
|
2207
|
+
}
|
|
2208
|
+
};
|
|
2209
|
+
}, [onStartReached, isLoadingMore]);
|
|
2210
|
+
if (messages.length === 0) {
|
|
2211
|
+
return /* @__PURE__ */ jsx(
|
|
2212
|
+
"div",
|
|
2213
|
+
{
|
|
2214
|
+
role: "log",
|
|
2215
|
+
"aria-live": "polite",
|
|
2216
|
+
"aria-atomic": "false",
|
|
2217
|
+
className: cn("flex-1 overflow-y-auto", className),
|
|
2218
|
+
children: renderEmpty?.() ?? null
|
|
2219
|
+
}
|
|
2220
|
+
);
|
|
2221
|
+
}
|
|
2222
|
+
if (noVirtualize) {
|
|
2223
|
+
return /* @__PURE__ */ jsxs(
|
|
2224
|
+
"div",
|
|
2225
|
+
{
|
|
2226
|
+
role: "log",
|
|
2227
|
+
"aria-live": "polite",
|
|
2228
|
+
"aria-atomic": "false",
|
|
2229
|
+
className: cn("flex-1 overflow-y-auto", className),
|
|
2230
|
+
children: [
|
|
2231
|
+
isLoadingMore ? /* @__PURE__ */ jsx("div", { className: "flex justify-center py-2", children: /* @__PURE__ */ jsx(Spinner, { className: "size-4 text-muted-foreground" }) }) : null,
|
|
2232
|
+
messages.map((m, i) => /* @__PURE__ */ jsx("div", { children: itemRenderer(m, i) }, m.id ?? i))
|
|
2233
|
+
]
|
|
2234
|
+
}
|
|
2235
|
+
);
|
|
2236
|
+
}
|
|
2237
|
+
return /* @__PURE__ */ jsx(
|
|
2238
|
+
Virtuoso,
|
|
2267
2239
|
{
|
|
2268
|
-
ref,
|
|
2240
|
+
ref: virtuosoRef,
|
|
2269
2241
|
role: "log",
|
|
2270
2242
|
"aria-live": "polite",
|
|
2271
2243
|
"aria-atomic": "false",
|
|
2272
|
-
className: cn("flex-1
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2244
|
+
className: cn("flex-1", className),
|
|
2245
|
+
data: messages,
|
|
2246
|
+
computeItemKey,
|
|
2247
|
+
itemContent: (index, m) => m ? itemRenderer(m, index) : null,
|
|
2248
|
+
defaultItemHeight,
|
|
2249
|
+
followOutput: (isAtBottom) => isAtBottom ? "auto" : false,
|
|
2250
|
+
atBottomStateChange: onAtBottomChange,
|
|
2251
|
+
alignToBottom: true,
|
|
2252
|
+
startReached: startReachedHandler,
|
|
2253
|
+
components: isLoadingMore ? {
|
|
2254
|
+
Header: /* @__PURE__ */ __name(() => /* @__PURE__ */ jsx("div", { className: "flex justify-center py-2", children: /* @__PURE__ */ jsx(Spinner, { className: "size-4 text-muted-foreground" }) }), "Header")
|
|
2255
|
+
} : EMPTY_COMPONENTS,
|
|
2256
|
+
increaseViewportBy: { top: 200, bottom: 400 }
|
|
2279
2257
|
}
|
|
2280
2258
|
);
|
|
2281
2259
|
}, "MessageList"));
|
|
2282
|
-
|
|
2283
|
-
if (typeof navigator !== "undefined" && navigator.clipboard) {
|
|
2284
|
-
void navigator.clipboard.writeText(text);
|
|
2285
|
-
}
|
|
2286
|
-
}
|
|
2287
|
-
__name(copy, "copy");
|
|
2260
|
+
var EMPTY_COMPONENTS = {};
|
|
2288
2261
|
function ChatRoot(props) {
|
|
2289
2262
|
const { transport, config, initialSessionId, autoCreateSession, streaming, audio, debug, className, listClassName, ...slots } = props;
|
|
2290
2263
|
return /* @__PURE__ */ jsx(
|
|
@@ -2308,22 +2281,9 @@ function ChatRootShell({ className, listClassName, slots }) {
|
|
|
2308
2281
|
onSubmit: /* @__PURE__ */ __name((content, attachments) => chat.sendMessage(content, attachments), "onSubmit"),
|
|
2309
2282
|
disabled: chat.isStreaming
|
|
2310
2283
|
});
|
|
2311
|
-
const
|
|
2312
|
-
const
|
|
2313
|
-
const
|
|
2314
|
-
const scroll = useChatScroll({
|
|
2315
|
-
containerRef,
|
|
2316
|
-
bottomRef,
|
|
2317
|
-
isStreaming: chat.isStreaming,
|
|
2318
|
-
messagesCount: chat.messages.length
|
|
2319
|
-
});
|
|
2320
|
-
useChatHistory({
|
|
2321
|
-
containerRef,
|
|
2322
|
-
topSentinelRef: topRef,
|
|
2323
|
-
hasMore: chat.hasMore,
|
|
2324
|
-
isLoadingMore: chat.isLoadingMore,
|
|
2325
|
-
loadMore: chat.loadMore
|
|
2326
|
-
});
|
|
2284
|
+
const listRef = useRef(null);
|
|
2285
|
+
const [isAtBottom, setIsAtBottom] = useState(true);
|
|
2286
|
+
const handleStartReached = chat.hasMore && !chat.isLoadingMore ? () => void chat.loadMore() : void 0;
|
|
2327
2287
|
const greeting = chat.config.greeting ?? "How can I help?";
|
|
2328
2288
|
const description = chat.config.description;
|
|
2329
2289
|
const suggestions = chat.config.suggestions;
|
|
@@ -2347,7 +2307,7 @@ function ChatRootShell({ className, listClassName, slots }) {
|
|
|
2347
2307
|
toolCallsProps: slots.toolCallsProps,
|
|
2348
2308
|
attachmentRenderers: slots.attachmentRenderers,
|
|
2349
2309
|
onAttachmentOpen: slots.onAttachmentOpen,
|
|
2350
|
-
onCopy: () =>
|
|
2310
|
+
onCopy: () => copy(m.content),
|
|
2351
2311
|
onRegenerate: () => void chat.regenerate(m.id),
|
|
2352
2312
|
onDelete: () => chat.deleteMessage(m.id)
|
|
2353
2313
|
},
|
|
@@ -2368,20 +2328,19 @@ function ChatRootShell({ className, listClassName, slots }) {
|
|
|
2368
2328
|
/* @__PURE__ */ jsx(
|
|
2369
2329
|
MessageList,
|
|
2370
2330
|
{
|
|
2371
|
-
ref:
|
|
2372
|
-
topSentinelRef: topRef,
|
|
2373
|
-
bottomRef,
|
|
2331
|
+
ref: listRef,
|
|
2374
2332
|
renderItem,
|
|
2375
2333
|
renderEmpty: () => /* @__PURE__ */ jsx(Fragment, { children: emptyNode }),
|
|
2376
|
-
className: listClassName
|
|
2334
|
+
className: listClassName,
|
|
2335
|
+
onStartReached: handleStartReached,
|
|
2336
|
+
onAtBottomChange: setIsAtBottom
|
|
2377
2337
|
}
|
|
2378
2338
|
),
|
|
2379
2339
|
/* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute inset-x-0 bottom-2 flex justify-center", children: slots.jumpToLatest ?? /* @__PURE__ */ jsx(
|
|
2380
2340
|
JumpToLatest,
|
|
2381
2341
|
{
|
|
2382
|
-
visible: !
|
|
2383
|
-
|
|
2384
|
-
onClick: () => scroll.scrollToBottom(true)
|
|
2342
|
+
visible: !isAtBottom,
|
|
2343
|
+
onClick: () => listRef.current?.scrollToBottom(true)
|
|
2385
2344
|
}
|
|
2386
2345
|
) })
|
|
2387
2346
|
] }),
|
|
@@ -2402,13 +2361,13 @@ function ChatRootShell({ className, listClassName, slots }) {
|
|
|
2402
2361
|
] });
|
|
2403
2362
|
}
|
|
2404
2363
|
__name(ChatRootShell, "ChatRootShell");
|
|
2405
|
-
function
|
|
2364
|
+
function copy(text) {
|
|
2406
2365
|
if (typeof navigator !== "undefined" && navigator.clipboard) {
|
|
2407
2366
|
void navigator.clipboard.writeText(text);
|
|
2408
2367
|
}
|
|
2409
2368
|
}
|
|
2410
|
-
__name(
|
|
2369
|
+
__name(copy, "copy");
|
|
2411
2370
|
|
|
2412
|
-
export { Attachments, AttachmentsGrid, AttachmentsList, CHAT_EVENT_NAME, CSS_VARS, ChatProvider, ChatRoot, Composer, DEFAULT_LABELS, DEFAULT_SIDEBAR, DEFAULT_Z_INDEX, EmptyState, ErrorBanner, HOTKEYS, JumpToLatest, LIMITS, MessageActions, MessageBubble, MessageList, STORAGE_KEYS, Sources, StreamingIndicator, ToolCalls, createId, createTokenBuffer, deriveInitials, getChatLogger, initialState, reducer, resolvePersona, useChat, useChatAudio, useChatAudioPrefs, useChatComposer, useChatContext, useChatContextOptional,
|
|
2413
|
-
//# sourceMappingURL=chunk-
|
|
2414
|
-
//# sourceMappingURL=chunk-
|
|
2371
|
+
export { Attachments, AttachmentsGrid, AttachmentsList, CHAT_EVENT_NAME, CSS_VARS, ChatProvider, ChatRoot, Composer, DEFAULT_LABELS, DEFAULT_SIDEBAR, DEFAULT_Z_INDEX, EmptyState, ErrorBanner, HOTKEYS, JumpToLatest, LIMITS, MessageActions, MessageBubble, MessageList, STORAGE_KEYS, Sources, StreamingIndicator, ToolCalls, createId, createTokenBuffer, deriveInitials, getChatLogger, initialState, reducer, resolvePersona, useChat, useChatAudio, useChatAudioPrefs, useChatComposer, useChatContext, useChatContextOptional, useChatLayout };
|
|
2372
|
+
//# sourceMappingURL=chunk-MVAT6OPZ.mjs.map
|
|
2373
|
+
//# sourceMappingURL=chunk-MVAT6OPZ.mjs.map
|