@djangocfg/ui-tools 2.1.367 → 2.1.369
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-DENECC2Q.mjs +5 -0
- package/dist/{ChatRoot-6U7633X3.mjs.map → ChatRoot-DENECC2Q.mjs.map} +1 -1
- package/dist/ChatRoot-PW6U3QVF.cjs +14 -0
- package/dist/{ChatRoot-HARTIAJ5.cjs.map → ChatRoot-PW6U3QVF.cjs.map} +1 -1
- package/dist/{chunk-OPKFKTIN.cjs → chunk-OD3P64QD.cjs} +150 -192
- package/dist/chunk-OD3P64QD.cjs.map +1 -0
- package/dist/{chunk-WGU5BEZX.mjs → chunk-YLIYXSUO.mjs} +152 -192
- package/dist/chunk-YLIYXSUO.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 +182 -20
- 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,6 +1,6 @@
|
|
|
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
6
|
import { useLocalStorage, useMediaQuery } from '@djangocfg/ui-core/hooks';
|
|
@@ -9,6 +9,7 @@ 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,14 +2144,36 @@ 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 virtuosoRef = useRef(null);
|
|
2158
|
+
useImperativeHandle(
|
|
2159
|
+
ref,
|
|
2160
|
+
() => ({
|
|
2161
|
+
scrollToBottom: /* @__PURE__ */ __name((smooth = false) => {
|
|
2162
|
+
virtuosoRef.current?.scrollToIndex({
|
|
2163
|
+
index: "LAST",
|
|
2164
|
+
behavior: smooth ? "smooth" : "auto",
|
|
2165
|
+
align: "end"
|
|
2166
|
+
});
|
|
2167
|
+
}, "scrollToBottom"),
|
|
2168
|
+
scrollToIndex: /* @__PURE__ */ __name((index, smooth = false) => {
|
|
2169
|
+
virtuosoRef.current?.scrollToIndex({
|
|
2170
|
+
index,
|
|
2171
|
+
behavior: smooth ? "smooth" : "auto"
|
|
2172
|
+
});
|
|
2173
|
+
}, "scrollToIndex")
|
|
2174
|
+
}),
|
|
2175
|
+
[]
|
|
2176
|
+
);
|
|
2252
2177
|
const defaultRenderItem = useCallback(
|
|
2253
2178
|
(m) => /* @__PURE__ */ jsx("div", { className: itemClassName, children: /* @__PURE__ */ jsx(
|
|
2254
2179
|
MessageBubble,
|
|
@@ -2258,24 +2183,73 @@ var MessageList = forwardRef(/* @__PURE__ */ __name(function MessageList2({
|
|
|
2258
2183
|
onRegenerate: ctx ? () => void ctx.regenerate(m.id) : void 0,
|
|
2259
2184
|
onDelete: ctx ? () => ctx.deleteMessage(m.id) : void 0
|
|
2260
2185
|
}
|
|
2261
|
-
) }
|
|
2186
|
+
) }),
|
|
2262
2187
|
[itemClassName, ctx]
|
|
2263
2188
|
);
|
|
2264
2189
|
const itemRenderer = renderItem ?? defaultRenderItem;
|
|
2265
|
-
|
|
2266
|
-
|
|
2190
|
+
const computeItemKey = useCallback((index, m) => m.id ?? index, []);
|
|
2191
|
+
const startReachedHandler = useMemo(() => {
|
|
2192
|
+
if (!onStartReached) return void 0;
|
|
2193
|
+
let inFlight = false;
|
|
2194
|
+
return () => {
|
|
2195
|
+
if (inFlight || isLoadingMore) return;
|
|
2196
|
+
inFlight = true;
|
|
2197
|
+
try {
|
|
2198
|
+
onStartReached();
|
|
2199
|
+
} finally {
|
|
2200
|
+
queueMicrotask(() => {
|
|
2201
|
+
inFlight = false;
|
|
2202
|
+
});
|
|
2203
|
+
}
|
|
2204
|
+
};
|
|
2205
|
+
}, [onStartReached, isLoadingMore]);
|
|
2206
|
+
if (messages.length === 0) {
|
|
2207
|
+
return /* @__PURE__ */ jsx(
|
|
2208
|
+
"div",
|
|
2209
|
+
{
|
|
2210
|
+
role: "log",
|
|
2211
|
+
"aria-live": "polite",
|
|
2212
|
+
"aria-atomic": "false",
|
|
2213
|
+
className: cn("flex-1 overflow-y-auto", className),
|
|
2214
|
+
children: renderEmpty?.() ?? null
|
|
2215
|
+
}
|
|
2216
|
+
);
|
|
2217
|
+
}
|
|
2218
|
+
if (noVirtualize) {
|
|
2219
|
+
return /* @__PURE__ */ jsxs(
|
|
2220
|
+
"div",
|
|
2221
|
+
{
|
|
2222
|
+
role: "log",
|
|
2223
|
+
"aria-live": "polite",
|
|
2224
|
+
"aria-atomic": "false",
|
|
2225
|
+
className: cn("flex-1 overflow-y-auto", className),
|
|
2226
|
+
children: [
|
|
2227
|
+
isLoadingMore ? /* @__PURE__ */ jsx("div", { className: "flex justify-center py-2", children: /* @__PURE__ */ jsx(Spinner, { className: "size-4 text-muted-foreground" }) }) : null,
|
|
2228
|
+
messages.map((m, i) => /* @__PURE__ */ jsx("div", { children: itemRenderer(m, i) }, m.id ?? i))
|
|
2229
|
+
]
|
|
2230
|
+
}
|
|
2231
|
+
);
|
|
2232
|
+
}
|
|
2233
|
+
return /* @__PURE__ */ jsx(
|
|
2234
|
+
Virtuoso,
|
|
2267
2235
|
{
|
|
2268
|
-
ref,
|
|
2236
|
+
ref: virtuosoRef,
|
|
2269
2237
|
role: "log",
|
|
2270
2238
|
"aria-live": "polite",
|
|
2271
2239
|
"aria-atomic": "false",
|
|
2272
|
-
className: cn("flex-1
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2240
|
+
className: cn("flex-1", className),
|
|
2241
|
+
data: messages,
|
|
2242
|
+
computeItemKey,
|
|
2243
|
+
itemContent: (index, m) => itemRenderer(m, index),
|
|
2244
|
+
defaultItemHeight,
|
|
2245
|
+
followOutput: (isAtBottom) => isAtBottom ? "auto" : false,
|
|
2246
|
+
atBottomStateChange: onAtBottomChange,
|
|
2247
|
+
alignToBottom: true,
|
|
2248
|
+
startReached: startReachedHandler,
|
|
2249
|
+
components: isLoadingMore ? {
|
|
2250
|
+
Header: /* @__PURE__ */ __name(() => /* @__PURE__ */ jsx("div", { className: "flex justify-center py-2", children: /* @__PURE__ */ jsx(Spinner, { className: "size-4 text-muted-foreground" }) }), "Header")
|
|
2251
|
+
} : void 0,
|
|
2252
|
+
increaseViewportBy: { top: 200, bottom: 400 }
|
|
2279
2253
|
}
|
|
2280
2254
|
);
|
|
2281
2255
|
}, "MessageList"));
|
|
@@ -2308,22 +2282,9 @@ function ChatRootShell({ className, listClassName, slots }) {
|
|
|
2308
2282
|
onSubmit: /* @__PURE__ */ __name((content, attachments) => chat.sendMessage(content, attachments), "onSubmit"),
|
|
2309
2283
|
disabled: chat.isStreaming
|
|
2310
2284
|
});
|
|
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
|
-
});
|
|
2285
|
+
const listRef = useRef(null);
|
|
2286
|
+
const [isAtBottom, setIsAtBottom] = useState(true);
|
|
2287
|
+
const handleStartReached = chat.hasMore && !chat.isLoadingMore ? () => void chat.loadMore() : void 0;
|
|
2327
2288
|
const greeting = chat.config.greeting ?? "How can I help?";
|
|
2328
2289
|
const description = chat.config.description;
|
|
2329
2290
|
const suggestions = chat.config.suggestions;
|
|
@@ -2368,20 +2329,19 @@ function ChatRootShell({ className, listClassName, slots }) {
|
|
|
2368
2329
|
/* @__PURE__ */ jsx(
|
|
2369
2330
|
MessageList,
|
|
2370
2331
|
{
|
|
2371
|
-
ref:
|
|
2372
|
-
topSentinelRef: topRef,
|
|
2373
|
-
bottomRef,
|
|
2332
|
+
ref: listRef,
|
|
2374
2333
|
renderItem,
|
|
2375
2334
|
renderEmpty: () => /* @__PURE__ */ jsx(Fragment, { children: emptyNode }),
|
|
2376
|
-
className: listClassName
|
|
2335
|
+
className: listClassName,
|
|
2336
|
+
onStartReached: handleStartReached,
|
|
2337
|
+
onAtBottomChange: setIsAtBottom
|
|
2377
2338
|
}
|
|
2378
2339
|
),
|
|
2379
2340
|
/* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute inset-x-0 bottom-2 flex justify-center", children: slots.jumpToLatest ?? /* @__PURE__ */ jsx(
|
|
2380
2341
|
JumpToLatest,
|
|
2381
2342
|
{
|
|
2382
|
-
visible: !
|
|
2383
|
-
|
|
2384
|
-
onClick: () => scroll.scrollToBottom(true)
|
|
2343
|
+
visible: !isAtBottom,
|
|
2344
|
+
onClick: () => listRef.current?.scrollToBottom(true)
|
|
2385
2345
|
}
|
|
2386
2346
|
) })
|
|
2387
2347
|
] }),
|
|
@@ -2409,6 +2369,6 @@ function copy2(text) {
|
|
|
2409
2369
|
}
|
|
2410
2370
|
__name(copy2, "copy");
|
|
2411
2371
|
|
|
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-
|
|
2372
|
+
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 };
|
|
2373
|
+
//# sourceMappingURL=chunk-YLIYXSUO.mjs.map
|
|
2374
|
+
//# sourceMappingURL=chunk-YLIYXSUO.mjs.map
|