@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 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"ChatRoot-
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"ChatRoot-DYMCNGOB.mjs"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunk2SKR4U5S_cjs = require('./chunk-2SKR4U5S.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 chunk2SKR4U5S_cjs.ChatRoot; }
|
|
12
|
+
});
|
|
13
|
+
//# sourceMappingURL=ChatRoot-HOQ37WRE.cjs.map
|
|
14
|
+
//# sourceMappingURL=ChatRoot-HOQ37WRE.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"ChatRoot-
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"ChatRoot-HOQ37WRE.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,50 +2146,120 @@ 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 { copyToClipboard } = hooks.useCopy();
|
|
2160
|
+
const virtuosoRef = react.useRef(null);
|
|
2161
|
+
react.useImperativeHandle(
|
|
2162
|
+
ref,
|
|
2163
|
+
() => ({
|
|
2164
|
+
scrollToBottom: /* @__PURE__ */ chunkOLISEQHS_cjs.__name((smooth = false) => {
|
|
2165
|
+
virtuosoRef.current?.scrollToIndex({
|
|
2166
|
+
index: "LAST",
|
|
2167
|
+
behavior: smooth ? "smooth" : "auto",
|
|
2168
|
+
align: "end"
|
|
2169
|
+
});
|
|
2170
|
+
}, "scrollToBottom"),
|
|
2171
|
+
scrollToIndex: /* @__PURE__ */ chunkOLISEQHS_cjs.__name((index, smooth = false) => {
|
|
2172
|
+
virtuosoRef.current?.scrollToIndex({
|
|
2173
|
+
index,
|
|
2174
|
+
behavior: smooth ? "smooth" : "auto"
|
|
2175
|
+
});
|
|
2176
|
+
}, "scrollToIndex")
|
|
2177
|
+
}),
|
|
2178
|
+
[]
|
|
2179
|
+
);
|
|
2254
2180
|
const defaultRenderItem = react.useCallback(
|
|
2255
2181
|
(m) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: itemClassName, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2256
2182
|
MessageBubble,
|
|
2257
2183
|
{
|
|
2258
2184
|
message: m,
|
|
2259
|
-
onCopy: () =>
|
|
2185
|
+
onCopy: () => void copyToClipboard(m.content),
|
|
2260
2186
|
onRegenerate: ctx ? () => void ctx.regenerate(m.id) : void 0,
|
|
2261
2187
|
onDelete: ctx ? () => ctx.deleteMessage(m.id) : void 0
|
|
2262
2188
|
}
|
|
2263
|
-
) }
|
|
2264
|
-
[itemClassName, ctx]
|
|
2189
|
+
) }),
|
|
2190
|
+
[itemClassName, ctx, copyToClipboard]
|
|
2265
2191
|
);
|
|
2266
2192
|
const itemRenderer = renderItem ?? defaultRenderItem;
|
|
2267
|
-
|
|
2268
|
-
|
|
2193
|
+
const computeItemKey = react.useCallback(
|
|
2194
|
+
(index, m) => m?.id ?? index,
|
|
2195
|
+
[]
|
|
2196
|
+
);
|
|
2197
|
+
const startReachedHandler = react.useMemo(() => {
|
|
2198
|
+
if (!onStartReached) return void 0;
|
|
2199
|
+
let inFlight = false;
|
|
2200
|
+
return () => {
|
|
2201
|
+
if (inFlight || isLoadingMore) return;
|
|
2202
|
+
inFlight = true;
|
|
2203
|
+
try {
|
|
2204
|
+
onStartReached();
|
|
2205
|
+
} finally {
|
|
2206
|
+
queueMicrotask(() => {
|
|
2207
|
+
inFlight = false;
|
|
2208
|
+
});
|
|
2209
|
+
}
|
|
2210
|
+
};
|
|
2211
|
+
}, [onStartReached, isLoadingMore]);
|
|
2212
|
+
if (messages.length === 0) {
|
|
2213
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2214
|
+
"div",
|
|
2215
|
+
{
|
|
2216
|
+
role: "log",
|
|
2217
|
+
"aria-live": "polite",
|
|
2218
|
+
"aria-atomic": "false",
|
|
2219
|
+
className: lib.cn("flex-1 overflow-y-auto", className),
|
|
2220
|
+
children: renderEmpty?.() ?? null
|
|
2221
|
+
}
|
|
2222
|
+
);
|
|
2223
|
+
}
|
|
2224
|
+
if (noVirtualize) {
|
|
2225
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2226
|
+
"div",
|
|
2227
|
+
{
|
|
2228
|
+
role: "log",
|
|
2229
|
+
"aria-live": "polite",
|
|
2230
|
+
"aria-atomic": "false",
|
|
2231
|
+
className: lib.cn("flex-1 overflow-y-auto", className),
|
|
2232
|
+
children: [
|
|
2233
|
+
isLoadingMore ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center py-2", children: /* @__PURE__ */ jsxRuntime.jsx(components.Spinner, { className: "size-4 text-muted-foreground" }) }) : null,
|
|
2234
|
+
messages.map((m, i) => /* @__PURE__ */ jsxRuntime.jsx("div", { children: itemRenderer(m, i) }, m.id ?? i))
|
|
2235
|
+
]
|
|
2236
|
+
}
|
|
2237
|
+
);
|
|
2238
|
+
}
|
|
2239
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2240
|
+
reactVirtuoso.Virtuoso,
|
|
2269
2241
|
{
|
|
2270
|
-
ref,
|
|
2242
|
+
ref: virtuosoRef,
|
|
2271
2243
|
role: "log",
|
|
2272
2244
|
"aria-live": "polite",
|
|
2273
2245
|
"aria-atomic": "false",
|
|
2274
|
-
className: lib.cn("flex-1
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2246
|
+
className: lib.cn("flex-1", className),
|
|
2247
|
+
data: messages,
|
|
2248
|
+
computeItemKey,
|
|
2249
|
+
itemContent: (index, m) => m ? itemRenderer(m, index) : null,
|
|
2250
|
+
defaultItemHeight,
|
|
2251
|
+
followOutput: (isAtBottom) => isAtBottom ? "auto" : false,
|
|
2252
|
+
atBottomStateChange: onAtBottomChange,
|
|
2253
|
+
alignToBottom: true,
|
|
2254
|
+
startReached: startReachedHandler,
|
|
2255
|
+
components: isLoadingMore ? {
|
|
2256
|
+
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")
|
|
2257
|
+
} : EMPTY_COMPONENTS,
|
|
2258
|
+
increaseViewportBy: { top: 200, bottom: 400 }
|
|
2281
2259
|
}
|
|
2282
2260
|
);
|
|
2283
2261
|
}, "MessageList"));
|
|
2284
|
-
|
|
2285
|
-
if (typeof navigator !== "undefined" && navigator.clipboard) {
|
|
2286
|
-
void navigator.clipboard.writeText(text);
|
|
2287
|
-
}
|
|
2288
|
-
}
|
|
2289
|
-
chunkOLISEQHS_cjs.__name(copy, "copy");
|
|
2262
|
+
var EMPTY_COMPONENTS = {};
|
|
2290
2263
|
function ChatRoot(props) {
|
|
2291
2264
|
const { transport, config, initialSessionId, autoCreateSession, streaming, audio, debug, className, listClassName, ...slots } = props;
|
|
2292
2265
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -2310,22 +2283,9 @@ function ChatRootShell({ className, listClassName, slots }) {
|
|
|
2310
2283
|
onSubmit: /* @__PURE__ */ chunkOLISEQHS_cjs.__name((content, attachments) => chat.sendMessage(content, attachments), "onSubmit"),
|
|
2311
2284
|
disabled: chat.isStreaming
|
|
2312
2285
|
});
|
|
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
|
-
});
|
|
2286
|
+
const listRef = react.useRef(null);
|
|
2287
|
+
const [isAtBottom, setIsAtBottom] = react.useState(true);
|
|
2288
|
+
const handleStartReached = chat.hasMore && !chat.isLoadingMore ? () => void chat.loadMore() : void 0;
|
|
2329
2289
|
const greeting = chat.config.greeting ?? "How can I help?";
|
|
2330
2290
|
const description = chat.config.description;
|
|
2331
2291
|
const suggestions = chat.config.suggestions;
|
|
@@ -2349,7 +2309,7 @@ function ChatRootShell({ className, listClassName, slots }) {
|
|
|
2349
2309
|
toolCallsProps: slots.toolCallsProps,
|
|
2350
2310
|
attachmentRenderers: slots.attachmentRenderers,
|
|
2351
2311
|
onAttachmentOpen: slots.onAttachmentOpen,
|
|
2352
|
-
onCopy: () =>
|
|
2312
|
+
onCopy: () => copy(m.content),
|
|
2353
2313
|
onRegenerate: () => void chat.regenerate(m.id),
|
|
2354
2314
|
onDelete: () => chat.deleteMessage(m.id)
|
|
2355
2315
|
},
|
|
@@ -2370,20 +2330,19 @@ function ChatRootShell({ className, listClassName, slots }) {
|
|
|
2370
2330
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2371
2331
|
MessageList,
|
|
2372
2332
|
{
|
|
2373
|
-
ref:
|
|
2374
|
-
topSentinelRef: topRef,
|
|
2375
|
-
bottomRef,
|
|
2333
|
+
ref: listRef,
|
|
2376
2334
|
renderItem,
|
|
2377
2335
|
renderEmpty: () => /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: emptyNode }),
|
|
2378
|
-
className: listClassName
|
|
2336
|
+
className: listClassName,
|
|
2337
|
+
onStartReached: handleStartReached,
|
|
2338
|
+
onAtBottomChange: setIsAtBottom
|
|
2379
2339
|
}
|
|
2380
2340
|
),
|
|
2381
2341
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pointer-events-none absolute inset-x-0 bottom-2 flex justify-center", children: slots.jumpToLatest ?? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2382
2342
|
JumpToLatest,
|
|
2383
2343
|
{
|
|
2384
|
-
visible: !
|
|
2385
|
-
|
|
2386
|
-
onClick: () => scroll.scrollToBottom(true)
|
|
2344
|
+
visible: !isAtBottom,
|
|
2345
|
+
onClick: () => listRef.current?.scrollToBottom(true)
|
|
2387
2346
|
}
|
|
2388
2347
|
) })
|
|
2389
2348
|
] }),
|
|
@@ -2404,12 +2363,12 @@ function ChatRootShell({ className, listClassName, slots }) {
|
|
|
2404
2363
|
] });
|
|
2405
2364
|
}
|
|
2406
2365
|
chunkOLISEQHS_cjs.__name(ChatRootShell, "ChatRootShell");
|
|
2407
|
-
function
|
|
2366
|
+
function copy(text) {
|
|
2408
2367
|
if (typeof navigator !== "undefined" && navigator.clipboard) {
|
|
2409
2368
|
void navigator.clipboard.writeText(text);
|
|
2410
2369
|
}
|
|
2411
2370
|
}
|
|
2412
|
-
chunkOLISEQHS_cjs.__name(
|
|
2371
|
+
chunkOLISEQHS_cjs.__name(copy, "copy");
|
|
2413
2372
|
|
|
2414
2373
|
exports.Attachments = Attachments;
|
|
2415
2374
|
exports.AttachmentsGrid = AttachmentsGrid;
|
|
@@ -2447,8 +2406,6 @@ exports.useChatAudioPrefs = useChatAudioPrefs;
|
|
|
2447
2406
|
exports.useChatComposer = useChatComposer;
|
|
2448
2407
|
exports.useChatContext = useChatContext;
|
|
2449
2408
|
exports.useChatContextOptional = useChatContextOptional;
|
|
2450
|
-
exports.useChatHistory = useChatHistory;
|
|
2451
2409
|
exports.useChatLayout = useChatLayout;
|
|
2452
|
-
|
|
2453
|
-
//# sourceMappingURL=chunk-
|
|
2454
|
-
//# sourceMappingURL=chunk-OPKFKTIN.cjs.map
|
|
2410
|
+
//# sourceMappingURL=chunk-2SKR4U5S.cjs.map
|
|
2411
|
+
//# sourceMappingURL=chunk-2SKR4U5S.cjs.map
|