@mieweb/ui 0.10.0-dev.8 → 0.10.0-dev.9

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.
Files changed (38) hide show
  1. package/dist/{chunk-7G3ZIYFY.js → chunk-4A3W4TQF.js} +15 -2
  2. package/dist/chunk-4A3W4TQF.js.map +1 -0
  3. package/dist/{chunk-WNAA6CLE.cjs → chunk-AR7AKDM2.cjs} +2 -2
  4. package/dist/{chunk-WNAA6CLE.cjs.map → chunk-AR7AKDM2.cjs.map} +1 -1
  5. package/dist/{chunk-EZSSESEU.cjs → chunk-ASSDGS4F.cjs} +15 -2
  6. package/dist/chunk-ASSDGS4F.cjs.map +1 -0
  7. package/dist/{chunk-JHULS3EC.js → chunk-AWJBOND5.js} +2 -2
  8. package/dist/{chunk-JHULS3EC.js.map → chunk-AWJBOND5.js.map} +1 -1
  9. package/dist/chunk-BM35CACB.js +148 -0
  10. package/dist/chunk-BM35CACB.js.map +1 -0
  11. package/dist/{chunk-WIAQQNFU.cjs → chunk-FS4VZUFV.cjs} +31 -2
  12. package/dist/chunk-FS4VZUFV.cjs.map +1 -0
  13. package/dist/{chunk-22CYDCXA.js → chunk-HACNIFO3.js} +31 -3
  14. package/dist/chunk-HACNIFO3.js.map +1 -0
  15. package/dist/chunk-VPTASZ2O.cjs +171 -0
  16. package/dist/chunk-VPTASZ2O.cjs.map +1 -0
  17. package/dist/components/SuperChat/index.cjs +261 -112
  18. package/dist/components/SuperChat/index.cjs.map +1 -1
  19. package/dist/components/SuperChat/index.js +255 -106
  20. package/dist/components/SuperChat/index.js.map +1 -1
  21. package/dist/hooks/index.cjs +22 -13
  22. package/dist/hooks/index.d.cts +101 -1
  23. package/dist/hooks/index.d.ts +101 -1
  24. package/dist/hooks/index.js +2 -1
  25. package/dist/index.cjs +193 -70
  26. package/dist/index.cjs.map +1 -1
  27. package/dist/index.d.cts +1 -1
  28. package/dist/index.d.ts +1 -1
  29. package/dist/index.js +146 -30
  30. package/dist/index.js.map +1 -1
  31. package/dist/styles.css +1 -1
  32. package/dist/tailwind-preset.cjs +4 -4
  33. package/dist/tailwind-preset.js +1 -1
  34. package/package.json +1 -1
  35. package/dist/chunk-22CYDCXA.js.map +0 -1
  36. package/dist/chunk-7G3ZIYFY.js.map +0 -1
  37. package/dist/chunk-EZSSESEU.cjs.map +0 -1
  38. package/dist/chunk-WIAQQNFU.cjs.map +0 -1
@@ -1,10 +1,11 @@
1
1
  import { TextRenderContext } from '../../chunk-I6CY5C6A.js';
2
2
  export { TextRenderContext, useTextRenderContext } from '../../chunk-I6CY5C6A.js';
3
- import { ChatBubble, MCPToolCallDisplay, AITypingIndicator, SparklesIcon, CloseIcon } from '../../chunk-22CYDCXA.js';
3
+ import { ChatBubble, MCPToolCallDisplay, AITypingIndicator, SparklesIcon, CloseIcon, JumpToBottomButton } from '../../chunk-HACNIFO3.js';
4
4
  import { notifyComposerMigrationOnce, ChatComposer } from '../../chunk-ACCAXVOG.js';
5
5
  import { Dropdown, DropdownSubmenu, DropdownItem } from '../../chunk-ZGRCSNPK.js';
6
6
  import { Avatar } from '../../chunk-HZ4MBUC3.js';
7
7
  import '../../chunk-IQ4KQJAO.js';
8
+ import { useStickToBottom, useStreamEndedBelowFold } from '../../chunk-BM35CACB.js';
8
9
  import '../../chunk-VVDE4CHU.js';
9
10
  import '../../chunk-6NZXWKUE.js';
10
11
  import '../../chunk-3IMM2PM4.js';
@@ -12,11 +13,12 @@ import '../../chunk-62ZOA6PX.js';
12
13
  import '../../chunk-WSNMQQ4P.js';
13
14
  import '../../chunk-T4ME7QCT.js';
14
15
  import '../../chunk-BKSPDTX4.js';
16
+ import { usePrefersReducedMotion } from '../../chunk-HB7C7NB5.js';
15
17
  import { Badge } from '../../chunk-BMSG4NBH.js';
16
18
  import '../../chunk-XCP454Q6.js';
17
19
  import { cn } from '../../chunk-TQONQSJO.js';
18
20
  import '../../chunk-PX6F3LHL.js';
19
- import * as React2 from 'react';
21
+ import * as React3 from 'react';
20
22
  import Markdown, { defaultUrlTransform } from 'react-markdown';
21
23
  import remarkGfm from 'remark-gfm';
22
24
  import rehypeSanitize, { defaultSchema } from 'rehype-sanitize';
@@ -269,7 +271,7 @@ var transformUrl = (url, key, node) => {
269
271
  }
270
272
  return defaultUrlTransform(url);
271
273
  };
272
- var MarkdownContent = React2.memo(function MarkdownContent2({
274
+ var MarkdownContent = React3.memo(function MarkdownContent2({
273
275
  text,
274
276
  messageId,
275
277
  streaming,
@@ -472,11 +474,11 @@ function useMessageCopy({
472
474
  getText,
473
475
  defaultFormat
474
476
  }) {
475
- const [copied, setCopied] = React2.useState(false);
476
- const copiedTimer = React2.useRef(
477
+ const [copied, setCopied] = React3.useState(false);
478
+ const copiedTimer = React3.useRef(
477
479
  void 0
478
480
  );
479
- React2.useEffect(() => () => window.clearTimeout(copiedTimer.current), []);
481
+ React3.useEffect(() => () => window.clearTimeout(copiedTimer.current), []);
480
482
  const flash = () => {
481
483
  setCopied(true);
482
484
  window.clearTimeout(copiedTimer.current);
@@ -529,7 +531,7 @@ function FooterActionButton({
529
531
  action,
530
532
  isSelf
531
533
  }) {
532
- const [open, setOpen] = React2.useState(false);
534
+ const [open, setOpen] = React3.useState(false);
533
535
  const onClickCapture = action.submenu ? (e) => {
534
536
  if (e.metaKey || e.ctrlKey) {
535
537
  e.preventDefault();
@@ -572,7 +574,7 @@ function FooterActionButton({
572
574
  }
573
575
  );
574
576
  }
575
- var MessageActionsBar = React2.forwardRef(function MessageActionsBar2({ actions, isSelf }, ref) {
577
+ var MessageActionsBar = React3.forwardRef(function MessageActionsBar2({ actions, isSelf }, ref) {
576
578
  return /* @__PURE__ */ jsx(
577
579
  "div",
578
580
  {
@@ -588,7 +590,7 @@ function MessageOverflowMenu({
588
590
  actions,
589
591
  footerVisible
590
592
  }) {
591
- const [open, setOpen] = React2.useState(false);
593
+ const [open, setOpen] = React3.useState(false);
592
594
  const select = (fn) => {
593
595
  setOpen(false);
594
596
  fn();
@@ -641,7 +643,7 @@ function MessageOverflowMenu({
641
643
  }
642
644
  );
643
645
  }
644
- var MessageRow = React2.memo(function MessageRow2({
646
+ var MessageRow = React3.memo(function MessageRow2({
645
647
  message,
646
648
  participant,
647
649
  isSelf,
@@ -654,18 +656,18 @@ var MessageRow = React2.memo(function MessageRow2({
654
656
  }) {
655
657
  const streaming = message.status === "streaming";
656
658
  const hasBody = !!message.text || (message.content?.length ?? 0) > 0;
657
- const [isEditing, setIsEditing] = React2.useState(false);
658
- const [draft, setDraft] = React2.useState(message.text ?? "");
659
- const [editMinWidth, setEditMinWidth] = React2.useState();
660
- const editRef = React2.useRef(null);
661
- const bubbleRef = React2.useRef(null);
662
- const autosize = React2.useCallback(() => {
659
+ const [isEditing, setIsEditing] = React3.useState(false);
660
+ const [draft, setDraft] = React3.useState(message.text ?? "");
661
+ const [editMinWidth, setEditMinWidth] = React3.useState();
662
+ const editRef = React3.useRef(null);
663
+ const bubbleRef = React3.useRef(null);
664
+ const autosize = React3.useCallback(() => {
663
665
  const el = editRef.current;
664
666
  if (!el) return;
665
667
  el.style.height = "auto";
666
668
  el.style.height = `${el.scrollHeight}px`;
667
669
  }, []);
668
- React2.useEffect(() => {
670
+ React3.useEffect(() => {
669
671
  if (!isEditing) return;
670
672
  const el = editRef.current;
671
673
  if (!el) return;
@@ -696,9 +698,9 @@ ${block.text}
696
698
  getText: () => bubbleRef.current?.textContent ?? "",
697
699
  defaultFormat: defaultCopyFormat
698
700
  });
699
- const actionsBarRef = React2.useRef(null);
700
- const [footerVisible, setFooterVisible] = React2.useState(true);
701
- React2.useEffect(() => {
701
+ const actionsBarRef = React3.useRef(null);
702
+ const [footerVisible, setFooterVisible] = React3.useState(true);
703
+ React3.useEffect(() => {
702
704
  const el = actionsBarRef.current;
703
705
  if (!el || typeof globalThis.IntersectionObserver === "undefined") return;
704
706
  const observer = new globalThis.IntersectionObserver(([entry]) => {
@@ -1049,32 +1051,23 @@ function VirtualThread({
1049
1051
  editable,
1050
1052
  onMessageEdited,
1051
1053
  defaultCopyFormat,
1052
- order,
1053
- conversationId,
1054
+ scrollRef,
1055
+ contentRef,
1054
1056
  containerProps
1055
1057
  }) {
1056
- const parentRef = React2.useRef(null);
1057
1058
  const virtualizer = useVirtualizer({
1058
1059
  count: items.length,
1059
- getScrollElement: () => parentRef.current,
1060
+ getScrollElement: () => scrollRef.current,
1060
1061
  // Rough first guess; real heights are measured via measureElement.
1061
1062
  estimateSize: () => 88,
1062
1063
  overscan: 10,
1063
1064
  getItemKey: (index) => items[index]?.id ?? index
1064
1065
  });
1065
- const count = items.length;
1066
- React2.useEffect(() => {
1067
- if (count === 0) return;
1068
- if (order === "desc") {
1069
- virtualizer.scrollToIndex(0, { align: "start" });
1070
- } else {
1071
- virtualizer.scrollToIndex(count - 1, { align: "end" });
1072
- }
1073
- }, [count, conversationId, order]);
1074
1066
  const virtualItems = virtualizer.getVirtualItems();
1075
- return /* @__PURE__ */ jsx("div", { ...containerProps, ref: parentRef, children: /* @__PURE__ */ jsx(
1067
+ return /* @__PURE__ */ jsx("div", { ...containerProps, ref: scrollRef, children: /* @__PURE__ */ jsx(
1076
1068
  "div",
1077
1069
  {
1070
+ ref: contentRef,
1078
1071
  style: {
1079
1072
  height: virtualizer.getTotalSize(),
1080
1073
  position: "relative",
@@ -1135,38 +1128,180 @@ function SuperChat({
1135
1128
  onReferenceClick,
1136
1129
  onBack
1137
1130
  }) {
1138
- const headingId = React2.useId();
1139
- React2.useEffect(() => {
1131
+ const headingId = React3.useId();
1132
+ React3.useEffect(() => {
1140
1133
  notifyComposerMigrationOnce("SuperChat");
1141
1134
  }, []);
1142
- const renderText = React2.useMemo(
1135
+ const renderText = React3.useMemo(
1143
1136
  () => renderTextContent ?? createMarkdownRenderer({
1144
1137
  plugins: renderPlugins,
1145
1138
  trusted: trustedContent
1146
1139
  }),
1147
1140
  [renderTextContent, renderPlugins, trustedContent]
1148
1141
  );
1149
- const threadRef = React2.useRef(null);
1150
- React2.useEffect(() => {
1151
- if (virtualized) return;
1152
- const el = threadRef.current;
1153
- if (!el) return;
1154
- el.scrollTop = order === "desc" ? 0 : el.scrollHeight;
1155
- }, [conversation.thread.length, conversation.id, order, virtualized]);
1156
- const participantById = React2.useMemo(() => {
1142
+ const prefersReducedMotion = usePrefersReducedMotion();
1143
+ const {
1144
+ containerRef: threadRef,
1145
+ contentRef: threadContentRef,
1146
+ isAtBottom,
1147
+ scrollToBottom,
1148
+ anchorToTurnStart,
1149
+ followIfPinned,
1150
+ stopFollowing
1151
+ } = useStickToBottom({ disabled: order === "desc" });
1152
+ const [hasNewBelow, setHasNewBelow] = React3.useState(false);
1153
+ const [turnStartId, setTurnStartId] = React3.useState(null);
1154
+ const [turnMinHeight, setTurnMinHeight] = React3.useState();
1155
+ const anchoredTurnRef = React3.useRef(null);
1156
+ React3.useEffect(() => {
1157
+ setTurnStartId(null);
1158
+ anchoredTurnRef.current = null;
1159
+ if (order === "desc") {
1160
+ const el = threadRef.current;
1161
+ if (el) el.scrollTop = 0;
1162
+ } else {
1163
+ scrollToBottom("auto");
1164
+ }
1165
+ setHasNewBelow(false);
1166
+ }, [conversation.id, order]);
1167
+ const threadLength = conversation.thread.length;
1168
+ const prevThreadLengthRef = React3.useRef(threadLength);
1169
+ const prevMessageIdsRef = React3.useRef(
1170
+ new Set(conversation.thread.map((message) => message.id))
1171
+ );
1172
+ const policyConversationRef = React3.useRef(conversation.id);
1173
+ const policyBaselinedRef = React3.useRef(false);
1174
+ React3.useEffect(() => {
1175
+ if (!policyBaselinedRef.current || policyConversationRef.current !== conversation.id) {
1176
+ policyBaselinedRef.current = true;
1177
+ policyConversationRef.current = conversation.id;
1178
+ prevThreadLengthRef.current = threadLength;
1179
+ prevMessageIdsRef.current = new Set(
1180
+ conversation.thread.map((message) => message.id)
1181
+ );
1182
+ if (order !== "desc" && [...conversation.thread].sort(byTime).at(-1)?.status === "streaming") {
1183
+ stopFollowing();
1184
+ }
1185
+ return;
1186
+ }
1187
+ if (threadLength === prevThreadLengthRef.current) return;
1188
+ const grew = threadLength > prevThreadLengthRef.current;
1189
+ prevThreadLengthRef.current = threadLength;
1190
+ if (order === "desc") {
1191
+ const el = threadRef.current;
1192
+ if (el) el.scrollTop = 0;
1193
+ return;
1194
+ }
1195
+ const prevIds = prevMessageIdsRef.current;
1196
+ let turnStart;
1197
+ if (grew && currentParticipantId) {
1198
+ for (const message of [...conversation.thread].sort(byTime)) {
1199
+ if (!prevIds.has(message.id) && message.participantId === currentParticipantId) {
1200
+ turnStart = message.id;
1201
+ }
1202
+ }
1203
+ }
1204
+ if (turnStart) {
1205
+ if (virtualized) {
1206
+ scrollToBottom("auto");
1207
+ } else {
1208
+ setTurnStartId(turnStart);
1209
+ }
1210
+ } else if (grew) {
1211
+ const newest = [...conversation.thread].sort(byTime).at(-1);
1212
+ if (newest?.status === "streaming") {
1213
+ followIfPinned("auto");
1214
+ stopFollowing();
1215
+ } else if (!followIfPinned("auto")) {
1216
+ setHasNewBelow(true);
1217
+ }
1218
+ } else {
1219
+ followIfPinned("auto");
1220
+ }
1221
+ }, [threadLength, order, isAtBottom, conversation.id]);
1222
+ React3.useLayoutEffect(() => {
1223
+ if (!turnStartId || anchoredTurnRef.current === turnStartId) return;
1224
+ const container = threadRef.current;
1225
+ if (!container) return;
1226
+ const reserve = Math.max(0, container.clientHeight - 32);
1227
+ if (turnMinHeight !== reserve) {
1228
+ setTurnMinHeight(reserve);
1229
+ return;
1230
+ }
1231
+ const target = container.querySelector(
1232
+ '[data-slot="superchat-turn"]'
1233
+ );
1234
+ if (target) {
1235
+ anchorToTurnStart(target, prefersReducedMotion ? "auto" : "smooth");
1236
+ anchoredTurnRef.current = turnStartId;
1237
+ }
1238
+ }, [
1239
+ turnStartId,
1240
+ turnMinHeight,
1241
+ anchorToTurnStart,
1242
+ prefersReducedMotion,
1243
+ threadRef
1244
+ ]);
1245
+ React3.useEffect(() => {
1246
+ prevMessageIdsRef.current = new Set(
1247
+ conversation.thread.map((message) => message.id)
1248
+ );
1249
+ });
1250
+ React3.useEffect(() => {
1251
+ if (isAtBottom) setHasNewBelow(false);
1252
+ }, [isAtBottom]);
1253
+ const newestMessage = React3.useMemo(
1254
+ () => [...conversation.thread].sort(byTime).at(-1),
1255
+ [conversation]
1256
+ );
1257
+ const raiseNewBelow = React3.useCallback(() => {
1258
+ if (order !== "desc") setHasNewBelow(true);
1259
+ }, [order]);
1260
+ const resumeFollowing = React3.useCallback(() => {
1261
+ if (order !== "desc") scrollToBottom("auto");
1262
+ }, [order, scrollToBottom]);
1263
+ useStreamEndedBelowFold(
1264
+ newestMessage,
1265
+ isAtBottom,
1266
+ raiseNewBelow,
1267
+ resumeFollowing
1268
+ );
1269
+ const handleJumpToBottom = React3.useCallback(() => {
1270
+ scrollToBottom(prefersReducedMotion ? "auto" : "smooth");
1271
+ }, [scrollToBottom, prefersReducedMotion]);
1272
+ const participantById = React3.useMemo(() => {
1157
1273
  const map = /* @__PURE__ */ new Map();
1158
1274
  conversation.participants.forEach((p) => map.set(p.id, p));
1159
1275
  return map;
1160
1276
  }, [conversation]);
1161
- const orderedThread = React2.useMemo(() => {
1277
+ const orderedThread = React3.useMemo(() => {
1162
1278
  const sorted = [...conversation.thread].sort(byTime);
1163
1279
  return order === "desc" ? sorted.reverse() : sorted;
1164
1280
  }, [conversation, order]);
1165
- const onMessageEditedRef = React2.useRef(onMessageEdited);
1281
+ const turnIndex = React3.useMemo(
1282
+ () => turnStartId && order !== "desc" ? orderedThread.findIndex((message) => message.id === turnStartId) : -1,
1283
+ [orderedThread, turnStartId, order]
1284
+ );
1285
+ const renderMessageRow = (m) => /* @__PURE__ */ jsx(
1286
+ MessageRow,
1287
+ {
1288
+ message: m,
1289
+ participant: participantById.get(m.participantId),
1290
+ isSelf: !!currentParticipantId && m.participantId === currentParticipantId,
1291
+ renderText,
1292
+ linkBuilder,
1293
+ onReferenceClick,
1294
+ editable,
1295
+ onMessageEdited: handleMessageEdited,
1296
+ defaultCopyFormat
1297
+ },
1298
+ m.id
1299
+ );
1300
+ const onMessageEditedRef = React3.useRef(onMessageEdited);
1166
1301
  onMessageEditedRef.current = onMessageEdited;
1167
- const conversationRef = React2.useRef(conversation);
1302
+ const conversationRef = React3.useRef(conversation);
1168
1303
  conversationRef.current = conversation;
1169
- const handleMessageEdited = React2.useCallback(
1304
+ const handleMessageEdited = React3.useCallback(
1170
1305
  (messageId, text) => {
1171
1306
  onMessageEditedRef.current?.(messageId, text, {
1172
1307
  conversation: conversationRef.current
@@ -1175,7 +1310,7 @@ function SuperChat({
1175
1310
  []
1176
1311
  );
1177
1312
  const editable = !readOnly && !!onMessageEdited;
1178
- const mentionOptions = React2.useMemo(
1313
+ const mentionOptions = React3.useMemo(
1179
1314
  () => conversation.participants.filter((p) => p.kind !== "system").map((p) => ({
1180
1315
  id: p.id,
1181
1316
  label: p.name,
@@ -1185,17 +1320,17 @@ function SuperChat({
1185
1320
  })),
1186
1321
  [conversation.participants]
1187
1322
  );
1188
- const composerAccept = React2.useMemo(
1323
+ const composerAccept = React3.useMemo(
1189
1324
  () => acceptTokensFor(acceptedFileTypes),
1190
1325
  [acceptedFileTypes]
1191
1326
  );
1192
- const [draft, setDraft] = React2.useState("");
1193
- const draftEpochRef = React2.useRef(0);
1194
- const handleDraftChange = React2.useCallback((value) => {
1327
+ const [draft, setDraft] = React3.useState("");
1328
+ const draftEpochRef = React3.useRef(0);
1329
+ const handleDraftChange = React3.useCallback((value) => {
1195
1330
  draftEpochRef.current += 1;
1196
1331
  setDraft(value);
1197
1332
  }, []);
1198
- const handleComposerSend = React2.useCallback(
1333
+ const handleComposerSend = React3.useCallback(
1199
1334
  async (message) => {
1200
1335
  const epoch = draftEpochRef.current;
1201
1336
  try {
@@ -1291,55 +1426,69 @@ function SuperChat({
1291
1426
  ]
1292
1427
  }
1293
1428
  ),
1294
- virtualized ? /* @__PURE__ */ jsx(
1295
- VirtualThread,
1296
- {
1297
- items: orderedThread,
1298
- participantById,
1299
- currentParticipantId,
1300
- renderText,
1301
- linkBuilder,
1302
- onReferenceClick,
1303
- editable,
1304
- onMessageEdited: handleMessageEdited,
1305
- defaultCopyFormat,
1306
- order,
1307
- conversationId: conversation.id,
1308
- containerProps: {
1309
- "data-slot": "superchat-thread",
1310
- role: "log",
1311
- "aria-label": "Messages",
1312
- "aria-live": "polite",
1313
- // Focusable so keyboard-only users can scroll the message history.
1314
- tabIndex: 0,
1315
- className: "flex-1 overflow-y-auto p-4"
1316
- }
1317
- }
1318
- ) : /* @__PURE__ */ jsx(
1429
+ /* @__PURE__ */ jsxs(
1319
1430
  "div",
1320
1431
  {
1321
- "data-slot": "superchat-thread",
1322
- ref: threadRef,
1323
- role: "log",
1324
- "aria-label": "Messages",
1325
- "aria-live": "polite",
1326
- tabIndex: 0,
1327
- className: "flex-1 space-y-4 overflow-y-auto p-4",
1328
- children: orderedThread.map((m) => /* @__PURE__ */ jsx(
1329
- MessageRow,
1330
- {
1331
- message: m,
1332
- participant: participantById.get(m.participantId),
1333
- isSelf: !!currentParticipantId && m.participantId === currentParticipantId,
1334
- renderText,
1335
- linkBuilder,
1336
- onReferenceClick,
1337
- editable,
1338
- onMessageEdited: handleMessageEdited,
1339
- defaultCopyFormat
1340
- },
1341
- m.id
1342
- ))
1432
+ "data-slot": "superchat-thread-viewport",
1433
+ className: "relative flex min-h-0 flex-1 flex-col",
1434
+ children: [
1435
+ virtualized ? /* @__PURE__ */ jsx(
1436
+ VirtualThread,
1437
+ {
1438
+ items: orderedThread,
1439
+ participantById,
1440
+ currentParticipantId,
1441
+ renderText,
1442
+ linkBuilder,
1443
+ onReferenceClick,
1444
+ editable,
1445
+ onMessageEdited: handleMessageEdited,
1446
+ defaultCopyFormat,
1447
+ scrollRef: threadRef,
1448
+ contentRef: threadContentRef,
1449
+ containerProps: {
1450
+ "data-slot": "superchat-thread",
1451
+ role: "log",
1452
+ "aria-label": "Messages",
1453
+ "aria-live": "polite",
1454
+ // Focusable so keyboard-only users can scroll the message history.
1455
+ tabIndex: 0,
1456
+ className: "flex-1 overflow-y-auto p-4"
1457
+ }
1458
+ }
1459
+ ) : /* @__PURE__ */ jsx(
1460
+ "div",
1461
+ {
1462
+ "data-slot": "superchat-thread",
1463
+ ref: threadRef,
1464
+ role: "log",
1465
+ "aria-label": "Messages",
1466
+ "aria-live": "polite",
1467
+ tabIndex: 0,
1468
+ className: "flex-1 overflow-y-auto p-4",
1469
+ children: /* @__PURE__ */ jsxs("div", { ref: threadContentRef, className: "space-y-4", children: [
1470
+ (turnIndex === -1 ? orderedThread : orderedThread.slice(0, turnIndex)).map(renderMessageRow),
1471
+ turnIndex !== -1 && /* @__PURE__ */ jsx(
1472
+ "div",
1473
+ {
1474
+ "data-slot": "superchat-turn",
1475
+ className: "space-y-4",
1476
+ style: { minHeight: turnMinHeight },
1477
+ children: orderedThread.slice(turnIndex).map(renderMessageRow)
1478
+ }
1479
+ )
1480
+ ] })
1481
+ }
1482
+ ),
1483
+ order !== "desc" && !isAtBottom && /* @__PURE__ */ jsx(
1484
+ JumpToBottomButton,
1485
+ {
1486
+ dataSlot: "superchat-jump-to-bottom",
1487
+ hasNewMessages: hasNewBelow,
1488
+ onClick: handleJumpToBottom
1489
+ }
1490
+ )
1491
+ ]
1343
1492
  }
1344
1493
  ),
1345
1494
  /* @__PURE__ */ jsx(
@@ -1371,12 +1520,12 @@ function SuperChatConversations({
1371
1520
  onConversationOpened,
1372
1521
  onNewConversation
1373
1522
  }) {
1374
- const [internalActive, setInternalActive] = React2.useState(
1523
+ const [internalActive, setInternalActive] = React3.useState(
1375
1524
  defaultActiveConversationId ?? conversations[0]?.id
1376
1525
  );
1377
1526
  const requestedId = activeConversationId ?? internalActive;
1378
1527
  const activeId = conversations.some((c) => c.id === requestedId) ? requestedId : conversations[0]?.id;
1379
- const sortedConversations = React2.useMemo(
1528
+ const sortedConversations = React3.useMemo(
1380
1529
  () => [...conversations].sort((a, b) => lastActivityOf(b) - lastActivityOf(a)),
1381
1530
  [conversations]
1382
1531
  );
@@ -1465,13 +1614,13 @@ function SuperChatInbox({
1465
1614
  onNewConversation,
1466
1615
  onReferenceClick
1467
1616
  }) {
1468
- const [internalActive, setInternalActive] = React2.useState(
1617
+ const [internalActive, setInternalActive] = React3.useState(
1469
1618
  defaultActiveConversationId ?? conversations[0]?.id
1470
1619
  );
1471
1620
  const requestedId = activeConversationId ?? internalActive;
1472
1621
  const active = conversations.find((c) => c.id === requestedId) ?? conversations[0];
1473
1622
  const activeId = active?.id;
1474
- const [mobileView, setMobileView] = React2.useState("list");
1623
+ const [mobileView, setMobileView] = React3.useState("list");
1475
1624
  const handleOpen = (c) => {
1476
1625
  if (activeConversationId === void 0) setInternalActive(c.id);
1477
1626
  setMobileView("chat");