@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 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"ChatRoot-
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"ChatRoot-DENECC2Q.mjs"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkOD3P64QD_cjs = require('./chunk-OD3P64QD.cjs');
|
|
4
|
+
require('./chunk-XACCHZH2.cjs');
|
|
5
|
+
require('./chunk-OLISEQHS.cjs');
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
Object.defineProperty(exports, "ChatRoot", {
|
|
10
|
+
enumerable: true,
|
|
11
|
+
get: function () { return chunkOD3P64QD_cjs.ChatRoot; }
|
|
12
|
+
});
|
|
13
|
+
//# sourceMappingURL=ChatRoot-PW6U3QVF.cjs.map
|
|
14
|
+
//# sourceMappingURL=ChatRoot-PW6U3QVF.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"ChatRoot-
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"ChatRoot-PW6U3QVF.cjs"}
|
|
@@ -11,6 +11,7 @@ var middleware = require('zustand/middleware');
|
|
|
11
11
|
var jsxRuntime = require('react/jsx-runtime');
|
|
12
12
|
var lucideReact = require('lucide-react');
|
|
13
13
|
var components = require('@djangocfg/ui-core/components');
|
|
14
|
+
var reactVirtuoso = require('react-virtuoso');
|
|
14
15
|
|
|
15
16
|
// src/tools/Chat/types.ts
|
|
16
17
|
var DEFAULT_LABELS = {
|
|
@@ -694,13 +695,21 @@ function useChat(config) {
|
|
|
694
695
|
};
|
|
695
696
|
dispatch({ type: "MESSAGE_USER_ADD", message: userMsg });
|
|
696
697
|
config.onMessageSent?.(userMsg);
|
|
698
|
+
let outbound = content;
|
|
699
|
+
if (config.onBeforeSend) {
|
|
700
|
+
try {
|
|
701
|
+
outbound = await config.onBeforeSend(content);
|
|
702
|
+
} catch (err) {
|
|
703
|
+
log.error.error("onBeforeSend threw \u2014 falling back to original content", err);
|
|
704
|
+
}
|
|
705
|
+
}
|
|
697
706
|
if (streaming) {
|
|
698
|
-
await consumeStream(sessionId,
|
|
707
|
+
await consumeStream(sessionId, outbound, attachments);
|
|
699
708
|
} else {
|
|
700
|
-
await consumeBuffered(sessionId,
|
|
709
|
+
await consumeBuffered(sessionId, outbound, attachments);
|
|
701
710
|
}
|
|
702
711
|
},
|
|
703
|
-
[streaming, consumeStream, consumeBuffered, config, awaitSession]
|
|
712
|
+
[streaming, consumeStream, consumeBuffered, config, awaitSession, log]
|
|
704
713
|
);
|
|
705
714
|
const cancelStream = react.useCallback(() => {
|
|
706
715
|
abortRef.current?.abort();
|
|
@@ -1200,6 +1209,7 @@ function ChatProvider({
|
|
|
1200
1209
|
streaming,
|
|
1201
1210
|
audio,
|
|
1202
1211
|
debug,
|
|
1212
|
+
onBeforeSend,
|
|
1203
1213
|
children
|
|
1204
1214
|
}) {
|
|
1205
1215
|
const audioApi = useChatAudio(audio ?? {});
|
|
@@ -1223,7 +1233,8 @@ function ChatProvider({
|
|
|
1223
1233
|
onMessageSent,
|
|
1224
1234
|
onMessageEnd,
|
|
1225
1235
|
onStreamStart,
|
|
1226
|
-
onError
|
|
1236
|
+
onError,
|
|
1237
|
+
onBeforeSend
|
|
1227
1238
|
});
|
|
1228
1239
|
const layout = useChatLayout({ defaultMode: "embedded" });
|
|
1229
1240
|
const rootRef = react.useRef(null);
|
|
@@ -1279,9 +1290,28 @@ function useChatComposer(options) {
|
|
|
1279
1290
|
disabled = false,
|
|
1280
1291
|
submitOn = "enter",
|
|
1281
1292
|
history = { enabled: true, size: LIMITS.composerHistorySize },
|
|
1282
|
-
onPasteFiles
|
|
1293
|
+
onPasteFiles,
|
|
1294
|
+
persistKey
|
|
1283
1295
|
} = options;
|
|
1284
|
-
const
|
|
1296
|
+
const initialFromStorage = (() => {
|
|
1297
|
+
if (!persistKey || typeof window === "undefined") return initialValue;
|
|
1298
|
+
try {
|
|
1299
|
+
const stored = window.sessionStorage.getItem(`chat:draft:${persistKey}`);
|
|
1300
|
+
return stored && stored.length > 0 ? stored : initialValue;
|
|
1301
|
+
} catch {
|
|
1302
|
+
return initialValue;
|
|
1303
|
+
}
|
|
1304
|
+
})();
|
|
1305
|
+
const [value, setValueState] = react.useState(initialFromStorage);
|
|
1306
|
+
react.useEffect(() => {
|
|
1307
|
+
if (!persistKey || typeof window === "undefined") return;
|
|
1308
|
+
try {
|
|
1309
|
+
const k = `chat:draft:${persistKey}`;
|
|
1310
|
+
if (value.length > 0) window.sessionStorage.setItem(k, value);
|
|
1311
|
+
else window.sessionStorage.removeItem(k);
|
|
1312
|
+
} catch {
|
|
1313
|
+
}
|
|
1314
|
+
}, [value, persistKey]);
|
|
1285
1315
|
const [attachments, setAttachments] = react.useState([]);
|
|
1286
1316
|
const [isSubmitting, setIsSubmitting] = react.useState(false);
|
|
1287
1317
|
const textareaRef = react.useRef(null);
|
|
@@ -1426,138 +1456,6 @@ function useChatComposer(options) {
|
|
|
1426
1456
|
};
|
|
1427
1457
|
}
|
|
1428
1458
|
chunkOLISEQHS_cjs.__name(useChatComposer, "useChatComposer");
|
|
1429
|
-
function useChatScroll(options) {
|
|
1430
|
-
const {
|
|
1431
|
-
containerRef,
|
|
1432
|
-
bottomRef,
|
|
1433
|
-
isStreaming = false,
|
|
1434
|
-
bottomThresholdPx = 80,
|
|
1435
|
-
messagesCount = 0
|
|
1436
|
-
} = options;
|
|
1437
|
-
const [isAtBottom, setIsAtBottom] = react.useState(true);
|
|
1438
|
-
const [unreadCount, setUnreadCount] = react.useState(0);
|
|
1439
|
-
const lastCountRef = react.useRef(messagesCount);
|
|
1440
|
-
const stickyRef = react.useRef(true);
|
|
1441
|
-
const wasStreamingRef = react.useRef(isStreaming);
|
|
1442
|
-
const scrollToBottom = react.useCallback(
|
|
1443
|
-
(smooth = false) => {
|
|
1444
|
-
const el = containerRef.current;
|
|
1445
|
-
if (!el) return;
|
|
1446
|
-
el.scrollTo({
|
|
1447
|
-
top: el.scrollHeight,
|
|
1448
|
-
behavior: smooth ? "smooth" : "auto"
|
|
1449
|
-
});
|
|
1450
|
-
stickyRef.current = true;
|
|
1451
|
-
setIsAtBottom(true);
|
|
1452
|
-
setUnreadCount(0);
|
|
1453
|
-
},
|
|
1454
|
-
[containerRef]
|
|
1455
|
-
);
|
|
1456
|
-
const resetUnread = react.useCallback(() => setUnreadCount(0), []);
|
|
1457
|
-
react.useEffect(() => {
|
|
1458
|
-
const el = containerRef.current;
|
|
1459
|
-
if (!el) return;
|
|
1460
|
-
const onScroll = /* @__PURE__ */ chunkOLISEQHS_cjs.__name(() => {
|
|
1461
|
-
const distance = el.scrollHeight - el.scrollTop - el.clientHeight;
|
|
1462
|
-
const atBottom = distance <= bottomThresholdPx;
|
|
1463
|
-
stickyRef.current = atBottom;
|
|
1464
|
-
setIsAtBottom(atBottom);
|
|
1465
|
-
if (atBottom) setUnreadCount(0);
|
|
1466
|
-
}, "onScroll");
|
|
1467
|
-
onScroll();
|
|
1468
|
-
el.addEventListener("scroll", onScroll, { passive: true });
|
|
1469
|
-
return () => {
|
|
1470
|
-
el.removeEventListener("scroll", onScroll);
|
|
1471
|
-
};
|
|
1472
|
-
}, [containerRef, bottomThresholdPx]);
|
|
1473
|
-
react.useEffect(() => {
|
|
1474
|
-
const el = containerRef.current;
|
|
1475
|
-
if (!el) return;
|
|
1476
|
-
if (isStreaming) {
|
|
1477
|
-
wasStreamingRef.current = true;
|
|
1478
|
-
if (!stickyRef.current) return;
|
|
1479
|
-
let raf = 0;
|
|
1480
|
-
const tick = /* @__PURE__ */ chunkOLISEQHS_cjs.__name(() => {
|
|
1481
|
-
if (!stickyRef.current) return;
|
|
1482
|
-
el.scrollTop = el.scrollHeight;
|
|
1483
|
-
raf = requestAnimationFrame(tick);
|
|
1484
|
-
}, "tick");
|
|
1485
|
-
raf = requestAnimationFrame(tick);
|
|
1486
|
-
return () => cancelAnimationFrame(raf);
|
|
1487
|
-
}
|
|
1488
|
-
if (wasStreamingRef.current && stickyRef.current) {
|
|
1489
|
-
wasStreamingRef.current = false;
|
|
1490
|
-
let raf1 = 0;
|
|
1491
|
-
let raf2 = 0;
|
|
1492
|
-
raf1 = requestAnimationFrame(() => {
|
|
1493
|
-
el.scrollTop = el.scrollHeight;
|
|
1494
|
-
raf2 = requestAnimationFrame(() => {
|
|
1495
|
-
el.scrollTop = el.scrollHeight;
|
|
1496
|
-
});
|
|
1497
|
-
});
|
|
1498
|
-
return () => {
|
|
1499
|
-
cancelAnimationFrame(raf1);
|
|
1500
|
-
cancelAnimationFrame(raf2);
|
|
1501
|
-
};
|
|
1502
|
-
}
|
|
1503
|
-
wasStreamingRef.current = false;
|
|
1504
|
-
return;
|
|
1505
|
-
}, [containerRef, isStreaming]);
|
|
1506
|
-
react.useEffect(() => {
|
|
1507
|
-
if (messagesCount > lastCountRef.current) {
|
|
1508
|
-
if (stickyRef.current) {
|
|
1509
|
-
const el = containerRef.current;
|
|
1510
|
-
if (el) el.scrollTop = el.scrollHeight;
|
|
1511
|
-
} else {
|
|
1512
|
-
setUnreadCount((n) => n + (messagesCount - lastCountRef.current));
|
|
1513
|
-
}
|
|
1514
|
-
}
|
|
1515
|
-
lastCountRef.current = messagesCount;
|
|
1516
|
-
}, [containerRef, messagesCount]);
|
|
1517
|
-
react.useEffect(() => {
|
|
1518
|
-
}, [bottomRef]);
|
|
1519
|
-
return { isAtBottom, unreadCount, scrollToBottom, resetUnread };
|
|
1520
|
-
}
|
|
1521
|
-
chunkOLISEQHS_cjs.__name(useChatScroll, "useChatScroll");
|
|
1522
|
-
function useChatHistory(options) {
|
|
1523
|
-
const { enabled = true, containerRef, topSentinelRef, hasMore, isLoadingMore, loadMore } = options;
|
|
1524
|
-
const heightBeforeRef = react.useRef(null);
|
|
1525
|
-
react.useEffect(() => {
|
|
1526
|
-
if (heightBeforeRef.current == null) return;
|
|
1527
|
-
const el = containerRef.current;
|
|
1528
|
-
if (!el) {
|
|
1529
|
-
heightBeforeRef.current = null;
|
|
1530
|
-
return;
|
|
1531
|
-
}
|
|
1532
|
-
if (!isLoadingMore) {
|
|
1533
|
-
const delta = el.scrollHeight - heightBeforeRef.current;
|
|
1534
|
-
if (delta > 0) {
|
|
1535
|
-
el.scrollTop += delta;
|
|
1536
|
-
}
|
|
1537
|
-
heightBeforeRef.current = null;
|
|
1538
|
-
}
|
|
1539
|
-
}, [containerRef, isLoadingMore]);
|
|
1540
|
-
react.useEffect(() => {
|
|
1541
|
-
if (!enabled || !hasMore) return;
|
|
1542
|
-
const sentinel = topSentinelRef.current;
|
|
1543
|
-
const root = containerRef.current;
|
|
1544
|
-
if (!sentinel || !root) return;
|
|
1545
|
-
const observer = new IntersectionObserver(
|
|
1546
|
-
(entries) => {
|
|
1547
|
-
const entry = entries[0];
|
|
1548
|
-
if (!entry?.isIntersecting) return;
|
|
1549
|
-
if (isLoadingMore) return;
|
|
1550
|
-
const el = containerRef.current;
|
|
1551
|
-
if (el) heightBeforeRef.current = el.scrollHeight;
|
|
1552
|
-
void loadMore();
|
|
1553
|
-
},
|
|
1554
|
-
{ root, threshold: 0, rootMargin: "200px 0px 0px 0px" }
|
|
1555
|
-
);
|
|
1556
|
-
observer.observe(sentinel);
|
|
1557
|
-
return () => observer.disconnect();
|
|
1558
|
-
}, [enabled, hasMore, isLoadingMore, containerRef, topSentinelRef, loadMore]);
|
|
1559
|
-
}
|
|
1560
|
-
chunkOLISEQHS_cjs.__name(useChatHistory, "useChatHistory");
|
|
1561
1459
|
function AttachmentsGrid({
|
|
1562
1460
|
attachments,
|
|
1563
1461
|
maxVisible,
|
|
@@ -2137,7 +2035,9 @@ var MessageBubbleInner = /* @__PURE__ */ chunkOLISEQHS_cjs.__name(({
|
|
|
2137
2035
|
onCopy,
|
|
2138
2036
|
onRegenerate,
|
|
2139
2037
|
onEdit,
|
|
2140
|
-
onDelete
|
|
2038
|
+
onDelete,
|
|
2039
|
+
messageActionsExtra,
|
|
2040
|
+
streamingIndicator
|
|
2141
2041
|
}) => {
|
|
2142
2042
|
const isUser = isUserProp ?? message.role === "user";
|
|
2143
2043
|
const isStreaming = !!message.isStreaming;
|
|
@@ -2200,7 +2100,7 @@ var MessageBubbleInner = /* @__PURE__ */ chunkOLISEQHS_cjs.__name(({
|
|
|
2200
2100
|
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"
|
|
2201
2101
|
),
|
|
2202
2102
|
children: [
|
|
2203
|
-
isStreaming && message.toolActivity ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-1.5", children: /* @__PURE__ */ jsxRuntime.jsx(StreamingIndicator, { label: message.toolActivity }) }) : null,
|
|
2103
|
+
isStreaming && message.toolActivity ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-1.5", children: streamingIndicator ? streamingIndicator(message) : /* @__PURE__ */ jsxRuntime.jsx(StreamingIndicator, { label: message.toolActivity }) }) : null,
|
|
2204
2104
|
message.content || !isStreaming ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2205
2105
|
chunkXACCHZH2_cjs.MarkdownMessage,
|
|
2206
2106
|
{
|
|
@@ -2209,22 +2109,25 @@ var MessageBubbleInner = /* @__PURE__ */ chunkOLISEQHS_cjs.__name(({
|
|
|
2209
2109
|
isCompact,
|
|
2210
2110
|
plainText: isStreaming
|
|
2211
2111
|
}
|
|
2212
|
-
) : /* @__PURE__ */ jsxRuntime.jsx(StreamingIndicator, {})
|
|
2112
|
+
) : streamingIndicator ? streamingIndicator(message) : /* @__PURE__ */ jsxRuntime.jsx(StreamingIndicator, {})
|
|
2213
2113
|
]
|
|
2214
2114
|
}
|
|
2215
2115
|
),
|
|
2216
2116
|
message.toolCalls?.length ? toolCallsRenderer ? toolCallsRenderer(message.toolCalls) : /* @__PURE__ */ jsxRuntime.jsx(ToolCalls, { calls: message.toolCalls, ...toolCallsProps }) : null,
|
|
2217
2117
|
message.sources?.length && !isStreaming ? sourcesRenderer ? sourcesRenderer(message.sources) : /* @__PURE__ */ jsxRuntime.jsx(Sources, { sources: message.sources }) : null,
|
|
2218
|
-
showActions && !isStreaming ? /* @__PURE__ */ jsxRuntime.
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2118
|
+
showActions && !isStreaming ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-0.5", children: [
|
|
2119
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2120
|
+
MessageActions,
|
|
2121
|
+
{
|
|
2122
|
+
role: message.role,
|
|
2123
|
+
onCopy,
|
|
2124
|
+
onRegenerate,
|
|
2125
|
+
onEdit,
|
|
2126
|
+
onDelete
|
|
2127
|
+
}
|
|
2128
|
+
),
|
|
2129
|
+
messageActionsExtra ? messageActionsExtra(message) : null
|
|
2130
|
+
] }) : null,
|
|
2228
2131
|
showTimestamp ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 text-[10px] text-muted-foreground", children: new Date(message.createdAt).toLocaleTimeString() }) : null,
|
|
2229
2132
|
afterContent
|
|
2230
2133
|
] })
|
|
@@ -2243,14 +2146,36 @@ var MessageList = react.forwardRef(/* @__PURE__ */ chunkOLISEQHS_cjs.__name(func
|
|
|
2243
2146
|
renderItem,
|
|
2244
2147
|
renderEmpty,
|
|
2245
2148
|
isLoadingMore: isLoadingMoreProp,
|
|
2246
|
-
|
|
2247
|
-
bottomRef,
|
|
2149
|
+
onStartReached,
|
|
2248
2150
|
className,
|
|
2249
|
-
itemClassName
|
|
2151
|
+
itemClassName,
|
|
2152
|
+
noVirtualize = false,
|
|
2153
|
+
defaultItemHeight = 120,
|
|
2154
|
+
onAtBottomChange
|
|
2250
2155
|
}, ref) {
|
|
2251
2156
|
const ctx = useChatContextOptional();
|
|
2252
2157
|
const messages = messagesProp ?? ctx?.messages ?? [];
|
|
2253
2158
|
const isLoadingMore = isLoadingMoreProp ?? ctx?.isLoadingMore ?? false;
|
|
2159
|
+
const virtuosoRef = react.useRef(null);
|
|
2160
|
+
react.useImperativeHandle(
|
|
2161
|
+
ref,
|
|
2162
|
+
() => ({
|
|
2163
|
+
scrollToBottom: /* @__PURE__ */ chunkOLISEQHS_cjs.__name((smooth = false) => {
|
|
2164
|
+
virtuosoRef.current?.scrollToIndex({
|
|
2165
|
+
index: "LAST",
|
|
2166
|
+
behavior: smooth ? "smooth" : "auto",
|
|
2167
|
+
align: "end"
|
|
2168
|
+
});
|
|
2169
|
+
}, "scrollToBottom"),
|
|
2170
|
+
scrollToIndex: /* @__PURE__ */ chunkOLISEQHS_cjs.__name((index, smooth = false) => {
|
|
2171
|
+
virtuosoRef.current?.scrollToIndex({
|
|
2172
|
+
index,
|
|
2173
|
+
behavior: smooth ? "smooth" : "auto"
|
|
2174
|
+
});
|
|
2175
|
+
}, "scrollToIndex")
|
|
2176
|
+
}),
|
|
2177
|
+
[]
|
|
2178
|
+
);
|
|
2254
2179
|
const defaultRenderItem = react.useCallback(
|
|
2255
2180
|
(m) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: itemClassName, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2256
2181
|
MessageBubble,
|
|
@@ -2260,24 +2185,73 @@ var MessageList = react.forwardRef(/* @__PURE__ */ chunkOLISEQHS_cjs.__name(func
|
|
|
2260
2185
|
onRegenerate: ctx ? () => void ctx.regenerate(m.id) : void 0,
|
|
2261
2186
|
onDelete: ctx ? () => ctx.deleteMessage(m.id) : void 0
|
|
2262
2187
|
}
|
|
2263
|
-
) }
|
|
2188
|
+
) }),
|
|
2264
2189
|
[itemClassName, ctx]
|
|
2265
2190
|
);
|
|
2266
2191
|
const itemRenderer = renderItem ?? defaultRenderItem;
|
|
2267
|
-
|
|
2268
|
-
|
|
2192
|
+
const computeItemKey = react.useCallback((index, m) => m.id ?? index, []);
|
|
2193
|
+
const startReachedHandler = react.useMemo(() => {
|
|
2194
|
+
if (!onStartReached) return void 0;
|
|
2195
|
+
let inFlight = false;
|
|
2196
|
+
return () => {
|
|
2197
|
+
if (inFlight || isLoadingMore) return;
|
|
2198
|
+
inFlight = true;
|
|
2199
|
+
try {
|
|
2200
|
+
onStartReached();
|
|
2201
|
+
} finally {
|
|
2202
|
+
queueMicrotask(() => {
|
|
2203
|
+
inFlight = false;
|
|
2204
|
+
});
|
|
2205
|
+
}
|
|
2206
|
+
};
|
|
2207
|
+
}, [onStartReached, isLoadingMore]);
|
|
2208
|
+
if (messages.length === 0) {
|
|
2209
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2210
|
+
"div",
|
|
2211
|
+
{
|
|
2212
|
+
role: "log",
|
|
2213
|
+
"aria-live": "polite",
|
|
2214
|
+
"aria-atomic": "false",
|
|
2215
|
+
className: lib.cn("flex-1 overflow-y-auto", className),
|
|
2216
|
+
children: renderEmpty?.() ?? null
|
|
2217
|
+
}
|
|
2218
|
+
);
|
|
2219
|
+
}
|
|
2220
|
+
if (noVirtualize) {
|
|
2221
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2222
|
+
"div",
|
|
2223
|
+
{
|
|
2224
|
+
role: "log",
|
|
2225
|
+
"aria-live": "polite",
|
|
2226
|
+
"aria-atomic": "false",
|
|
2227
|
+
className: lib.cn("flex-1 overflow-y-auto", className),
|
|
2228
|
+
children: [
|
|
2229
|
+
isLoadingMore ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center py-2", children: /* @__PURE__ */ jsxRuntime.jsx(components.Spinner, { className: "size-4 text-muted-foreground" }) }) : null,
|
|
2230
|
+
messages.map((m, i) => /* @__PURE__ */ jsxRuntime.jsx("div", { children: itemRenderer(m, i) }, m.id ?? i))
|
|
2231
|
+
]
|
|
2232
|
+
}
|
|
2233
|
+
);
|
|
2234
|
+
}
|
|
2235
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2236
|
+
reactVirtuoso.Virtuoso,
|
|
2269
2237
|
{
|
|
2270
|
-
ref,
|
|
2238
|
+
ref: virtuosoRef,
|
|
2271
2239
|
role: "log",
|
|
2272
2240
|
"aria-live": "polite",
|
|
2273
2241
|
"aria-atomic": "false",
|
|
2274
|
-
className: lib.cn("flex-1
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2242
|
+
className: lib.cn("flex-1", className),
|
|
2243
|
+
data: messages,
|
|
2244
|
+
computeItemKey,
|
|
2245
|
+
itemContent: (index, m) => itemRenderer(m, index),
|
|
2246
|
+
defaultItemHeight,
|
|
2247
|
+
followOutput: (isAtBottom) => isAtBottom ? "auto" : false,
|
|
2248
|
+
atBottomStateChange: onAtBottomChange,
|
|
2249
|
+
alignToBottom: true,
|
|
2250
|
+
startReached: startReachedHandler,
|
|
2251
|
+
components: isLoadingMore ? {
|
|
2252
|
+
Header: /* @__PURE__ */ chunkOLISEQHS_cjs.__name(() => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center py-2", children: /* @__PURE__ */ jsxRuntime.jsx(components.Spinner, { className: "size-4 text-muted-foreground" }) }), "Header")
|
|
2253
|
+
} : void 0,
|
|
2254
|
+
increaseViewportBy: { top: 200, bottom: 400 }
|
|
2281
2255
|
}
|
|
2282
2256
|
);
|
|
2283
2257
|
}, "MessageList"));
|
|
@@ -2310,22 +2284,9 @@ function ChatRootShell({ className, listClassName, slots }) {
|
|
|
2310
2284
|
onSubmit: /* @__PURE__ */ chunkOLISEQHS_cjs.__name((content, attachments) => chat.sendMessage(content, attachments), "onSubmit"),
|
|
2311
2285
|
disabled: chat.isStreaming
|
|
2312
2286
|
});
|
|
2313
|
-
const
|
|
2314
|
-
const
|
|
2315
|
-
const
|
|
2316
|
-
const scroll = useChatScroll({
|
|
2317
|
-
containerRef,
|
|
2318
|
-
bottomRef,
|
|
2319
|
-
isStreaming: chat.isStreaming,
|
|
2320
|
-
messagesCount: chat.messages.length
|
|
2321
|
-
});
|
|
2322
|
-
useChatHistory({
|
|
2323
|
-
containerRef,
|
|
2324
|
-
topSentinelRef: topRef,
|
|
2325
|
-
hasMore: chat.hasMore,
|
|
2326
|
-
isLoadingMore: chat.isLoadingMore,
|
|
2327
|
-
loadMore: chat.loadMore
|
|
2328
|
-
});
|
|
2287
|
+
const listRef = react.useRef(null);
|
|
2288
|
+
const [isAtBottom, setIsAtBottom] = react.useState(true);
|
|
2289
|
+
const handleStartReached = chat.hasMore && !chat.isLoadingMore ? () => void chat.loadMore() : void 0;
|
|
2329
2290
|
const greeting = chat.config.greeting ?? "How can I help?";
|
|
2330
2291
|
const description = chat.config.description;
|
|
2331
2292
|
const suggestions = chat.config.suggestions;
|
|
@@ -2370,20 +2331,19 @@ function ChatRootShell({ className, listClassName, slots }) {
|
|
|
2370
2331
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2371
2332
|
MessageList,
|
|
2372
2333
|
{
|
|
2373
|
-
ref:
|
|
2374
|
-
topSentinelRef: topRef,
|
|
2375
|
-
bottomRef,
|
|
2334
|
+
ref: listRef,
|
|
2376
2335
|
renderItem,
|
|
2377
2336
|
renderEmpty: () => /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: emptyNode }),
|
|
2378
|
-
className: listClassName
|
|
2337
|
+
className: listClassName,
|
|
2338
|
+
onStartReached: handleStartReached,
|
|
2339
|
+
onAtBottomChange: setIsAtBottom
|
|
2379
2340
|
}
|
|
2380
2341
|
),
|
|
2381
2342
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pointer-events-none absolute inset-x-0 bottom-2 flex justify-center", children: slots.jumpToLatest ?? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2382
2343
|
JumpToLatest,
|
|
2383
2344
|
{
|
|
2384
|
-
visible: !
|
|
2385
|
-
|
|
2386
|
-
onClick: () => scroll.scrollToBottom(true)
|
|
2345
|
+
visible: !isAtBottom,
|
|
2346
|
+
onClick: () => listRef.current?.scrollToBottom(true)
|
|
2387
2347
|
}
|
|
2388
2348
|
) })
|
|
2389
2349
|
] }),
|
|
@@ -2447,8 +2407,6 @@ exports.useChatAudioPrefs = useChatAudioPrefs;
|
|
|
2447
2407
|
exports.useChatComposer = useChatComposer;
|
|
2448
2408
|
exports.useChatContext = useChatContext;
|
|
2449
2409
|
exports.useChatContextOptional = useChatContextOptional;
|
|
2450
|
-
exports.useChatHistory = useChatHistory;
|
|
2451
2410
|
exports.useChatLayout = useChatLayout;
|
|
2452
|
-
|
|
2453
|
-
//# sourceMappingURL=chunk-
|
|
2454
|
-
//# sourceMappingURL=chunk-OPKFKTIN.cjs.map
|
|
2411
|
+
//# sourceMappingURL=chunk-OD3P64QD.cjs.map
|
|
2412
|
+
//# sourceMappingURL=chunk-OD3P64QD.cjs.map
|