@mieweb/ui 0.10.0-dev.7 → 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.
- package/dist/{chunk-XEPDIFEA.js → chunk-4A3W4TQF.js} +16 -3
- package/dist/chunk-4A3W4TQF.js.map +1 -0
- package/dist/{chunk-WNAA6CLE.cjs → chunk-AR7AKDM2.cjs} +2 -2
- package/dist/{chunk-WNAA6CLE.cjs.map → chunk-AR7AKDM2.cjs.map} +1 -1
- package/dist/{chunk-XCENM6ED.cjs → chunk-ASSDGS4F.cjs} +16 -3
- package/dist/chunk-ASSDGS4F.cjs.map +1 -0
- package/dist/{chunk-JHULS3EC.js → chunk-AWJBOND5.js} +2 -2
- package/dist/{chunk-JHULS3EC.js.map → chunk-AWJBOND5.js.map} +1 -1
- package/dist/chunk-BM35CACB.js +148 -0
- package/dist/chunk-BM35CACB.js.map +1 -0
- package/dist/{chunk-WIAQQNFU.cjs → chunk-FS4VZUFV.cjs} +31 -2
- package/dist/chunk-FS4VZUFV.cjs.map +1 -0
- package/dist/{chunk-22CYDCXA.js → chunk-HACNIFO3.js} +31 -3
- package/dist/chunk-HACNIFO3.js.map +1 -0
- package/dist/chunk-VPTASZ2O.cjs +171 -0
- package/dist/chunk-VPTASZ2O.cjs.map +1 -0
- package/dist/components/SuperChat/index.cjs +442 -267
- package/dist/components/SuperChat/index.cjs.map +1 -1
- package/dist/components/SuperChat/index.js +439 -264
- package/dist/components/SuperChat/index.js.map +1 -1
- package/dist/hooks/index.cjs +22 -13
- package/dist/hooks/index.d.cts +101 -1
- package/dist/hooks/index.d.ts +101 -1
- package/dist/hooks/index.js +2 -1
- package/dist/index.cjs +193 -70
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +146 -30
- package/dist/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/tailwind-preset.cjs +4 -4
- package/dist/tailwind-preset.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-22CYDCXA.js.map +0 -1
- package/dist/chunk-WIAQQNFU.cjs.map +0 -1
- package/dist/chunk-XCENM6ED.cjs.map +0 -1
- package/dist/chunk-XEPDIFEA.js.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-
|
|
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
|
|
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 =
|
|
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] =
|
|
476
|
-
const copiedTimer =
|
|
477
|
+
const [copied, setCopied] = React3.useState(false);
|
|
478
|
+
const copiedTimer = React3.useRef(
|
|
477
479
|
void 0
|
|
478
480
|
);
|
|
479
|
-
|
|
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] =
|
|
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,17 +574,13 @@ function FooterActionButton({
|
|
|
572
574
|
}
|
|
573
575
|
);
|
|
574
576
|
}
|
|
575
|
-
var MessageActionsBar =
|
|
577
|
+
var MessageActionsBar = React3.forwardRef(function MessageActionsBar2({ actions, isSelf }, ref) {
|
|
576
578
|
return /* @__PURE__ */ jsx(
|
|
577
579
|
"div",
|
|
578
580
|
{
|
|
579
581
|
ref,
|
|
580
582
|
"data-slot": "superchat-message-actions",
|
|
581
|
-
className: cn(
|
|
582
|
-
"flex items-center gap-0.5",
|
|
583
|
-
isSelf && "justify-end",
|
|
584
|
-
actionRevealClass
|
|
585
|
-
),
|
|
583
|
+
className: cn("flex flex-col items-center gap-0.5", actionRevealClass),
|
|
586
584
|
children: actions.map((action) => /* @__PURE__ */ jsx(FooterActionButton, { action, isSelf }, action.id))
|
|
587
585
|
}
|
|
588
586
|
);
|
|
@@ -592,7 +590,7 @@ function MessageOverflowMenu({
|
|
|
592
590
|
actions,
|
|
593
591
|
footerVisible
|
|
594
592
|
}) {
|
|
595
|
-
const [open, setOpen] =
|
|
593
|
+
const [open, setOpen] = React3.useState(false);
|
|
596
594
|
const select = (fn) => {
|
|
597
595
|
setOpen(false);
|
|
598
596
|
fn();
|
|
@@ -601,7 +599,7 @@ function MessageOverflowMenu({
|
|
|
601
599
|
"div",
|
|
602
600
|
{
|
|
603
601
|
className: cn(
|
|
604
|
-
"sticky bottom-2 shrink-0
|
|
602
|
+
"sticky bottom-2 mt-auto shrink-0 transition-opacity",
|
|
605
603
|
// Rich content (e.g. NITRO tables) layers internals up to z-50, so the
|
|
606
604
|
// open menu's stacking context must clear that.
|
|
607
605
|
open ? "z-[60]" : "z-10",
|
|
@@ -645,7 +643,7 @@ function MessageOverflowMenu({
|
|
|
645
643
|
}
|
|
646
644
|
);
|
|
647
645
|
}
|
|
648
|
-
var MessageRow =
|
|
646
|
+
var MessageRow = React3.memo(function MessageRow2({
|
|
649
647
|
message,
|
|
650
648
|
participant,
|
|
651
649
|
isSelf,
|
|
@@ -658,17 +656,18 @@ var MessageRow = React2.memo(function MessageRow2({
|
|
|
658
656
|
}) {
|
|
659
657
|
const streaming = message.status === "streaming";
|
|
660
658
|
const hasBody = !!message.text || (message.content?.length ?? 0) > 0;
|
|
661
|
-
const [isEditing, setIsEditing] =
|
|
662
|
-
const [draft, setDraft] =
|
|
663
|
-
const
|
|
664
|
-
const
|
|
665
|
-
const
|
|
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(() => {
|
|
666
665
|
const el = editRef.current;
|
|
667
666
|
if (!el) return;
|
|
668
667
|
el.style.height = "auto";
|
|
669
668
|
el.style.height = `${el.scrollHeight}px`;
|
|
670
669
|
}, []);
|
|
671
|
-
|
|
670
|
+
React3.useEffect(() => {
|
|
672
671
|
if (!isEditing) return;
|
|
673
672
|
const el = editRef.current;
|
|
674
673
|
if (!el) return;
|
|
@@ -689,16 +688,19 @@ ${block.text}
|
|
|
689
688
|
return "";
|
|
690
689
|
}).filter(Boolean).join("\n\n") ?? "";
|
|
691
690
|
const canCopy = !isEditing && (!!message.content?.length || typeof message.text === "string" && message.text.length > 0);
|
|
692
|
-
const
|
|
691
|
+
const showEditAction = canEdit && !isEditing;
|
|
692
|
+
const actionCount = (canCopy ? 1 : 0) + (showEditAction ? 1 : 0);
|
|
693
|
+
const hasActions = actionCount > 0;
|
|
694
|
+
const collapseToMenu = actionCount > 1;
|
|
693
695
|
const copy = useMessageCopy({
|
|
694
696
|
markdown: markdownSource,
|
|
695
697
|
getHtml: () => bubbleRef.current?.innerHTML ?? "",
|
|
696
698
|
getText: () => bubbleRef.current?.textContent ?? "",
|
|
697
699
|
defaultFormat: defaultCopyFormat
|
|
698
700
|
});
|
|
699
|
-
const actionsBarRef =
|
|
700
|
-
const [footerVisible, setFooterVisible] =
|
|
701
|
-
|
|
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]) => {
|
|
@@ -706,7 +708,7 @@ ${block.text}
|
|
|
706
708
|
});
|
|
707
709
|
observer.observe(el);
|
|
708
710
|
return () => observer.disconnect();
|
|
709
|
-
}, [hasActions]);
|
|
711
|
+
}, [hasActions, collapseToMenu]);
|
|
710
712
|
if (message.type === "system") {
|
|
711
713
|
return /* @__PURE__ */ jsx(
|
|
712
714
|
"div",
|
|
@@ -739,6 +741,12 @@ ${block.text}
|
|
|
739
741
|
const accentTextColor = accessibleAccentTextColor(accent);
|
|
740
742
|
const authorName = participant?.name ?? "Unknown";
|
|
741
743
|
const startEdit = () => {
|
|
744
|
+
const el = bubbleRef.current;
|
|
745
|
+
if (el) {
|
|
746
|
+
const cs = getComputedStyle(el);
|
|
747
|
+
const contentWidth = el.clientWidth - parseFloat(cs.paddingLeft) - parseFloat(cs.paddingRight);
|
|
748
|
+
setEditMinWidth(contentWidth > 0 ? contentWidth : void 0);
|
|
749
|
+
}
|
|
742
750
|
setDraft(message.text ?? "");
|
|
743
751
|
setIsEditing(true);
|
|
744
752
|
};
|
|
@@ -812,7 +820,7 @@ ${block.text}
|
|
|
812
820
|
}
|
|
813
821
|
}
|
|
814
822
|
] : [],
|
|
815
|
-
...
|
|
823
|
+
...showEditAction ? [
|
|
816
824
|
{
|
|
817
825
|
id: "edit",
|
|
818
826
|
label: "Edit message",
|
|
@@ -832,172 +840,191 @@ ${block.text}
|
|
|
832
840
|
isSelf ? "flex-row-reverse" : "flex-row"
|
|
833
841
|
),
|
|
834
842
|
children: [
|
|
835
|
-
/* @__PURE__ */
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
"
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
children: [
|
|
843
|
+
/* @__PURE__ */ jsxs(
|
|
844
|
+
"div",
|
|
845
|
+
{
|
|
846
|
+
"data-slot": "superchat-message-gutter",
|
|
847
|
+
className: "flex shrink-0 flex-col items-center gap-1",
|
|
848
|
+
children: [
|
|
849
|
+
/* @__PURE__ */ jsx(ParticipantAvatar, { participant }),
|
|
850
|
+
hasActions && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
843
851
|
/* @__PURE__ */ jsx(
|
|
844
|
-
"span",
|
|
845
|
-
{
|
|
846
|
-
className: "text-xs font-medium",
|
|
847
|
-
style: accentTextColor ? { color: accentTextColor } : void 0,
|
|
848
|
-
children: authorName
|
|
849
|
-
}
|
|
850
|
-
),
|
|
851
|
-
participant?.role && /* @__PURE__ */ jsx("span", { className: "text-[10px] text-neutral-500 dark:text-neutral-400", children: participant.role }),
|
|
852
|
-
/* @__PURE__ */ jsx("span", { className: "text-[10px] text-neutral-500 dark:text-neutral-400", children: formatTime(message.time) }),
|
|
853
|
-
message.editedAt && /* @__PURE__ */ jsx(
|
|
854
|
-
"span",
|
|
855
|
-
{
|
|
856
|
-
"data-slot": "superchat-edited-indicator",
|
|
857
|
-
className: "text-[10px] text-neutral-500 dark:text-neutral-400",
|
|
858
|
-
title: `Edited ${formatTime(message.editedAt)}`,
|
|
859
|
-
children: "(edited)"
|
|
860
|
-
}
|
|
861
|
-
)
|
|
862
|
-
]
|
|
863
|
-
}
|
|
864
|
-
),
|
|
865
|
-
/* @__PURE__ */ jsxs(
|
|
866
|
-
"div",
|
|
867
|
-
{
|
|
868
|
-
className: cn(
|
|
869
|
-
"flex items-center gap-1",
|
|
870
|
-
isSelf ? "flex-row-reverse" : "flex-row"
|
|
871
|
-
),
|
|
872
|
-
children: [
|
|
873
|
-
hasActions && /* @__PURE__ */ jsx(
|
|
874
852
|
MessageOverflowMenu,
|
|
875
853
|
{
|
|
876
854
|
isSelf,
|
|
877
855
|
actions,
|
|
878
|
-
footerVisible
|
|
856
|
+
footerVisible: collapseToMenu ? false : footerVisible
|
|
879
857
|
}
|
|
880
858
|
),
|
|
881
|
-
/* @__PURE__ */ jsx(
|
|
882
|
-
|
|
859
|
+
!collapseToMenu && /* @__PURE__ */ jsx(
|
|
860
|
+
MessageActionsBar,
|
|
883
861
|
{
|
|
884
|
-
ref:
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
862
|
+
ref: actionsBarRef,
|
|
863
|
+
actions,
|
|
864
|
+
isSelf
|
|
865
|
+
}
|
|
866
|
+
)
|
|
867
|
+
] })
|
|
868
|
+
]
|
|
869
|
+
}
|
|
870
|
+
),
|
|
871
|
+
/* @__PURE__ */ jsxs(
|
|
872
|
+
"div",
|
|
873
|
+
{
|
|
874
|
+
className: cn(
|
|
875
|
+
"flex min-w-0 flex-1 flex-col gap-1",
|
|
876
|
+
isSelf && "items-end"
|
|
877
|
+
),
|
|
878
|
+
children: [
|
|
879
|
+
/* @__PURE__ */ jsxs(
|
|
880
|
+
"div",
|
|
881
|
+
{
|
|
882
|
+
"data-slot": "superchat-message-meta",
|
|
883
|
+
className: "flex items-baseline gap-2",
|
|
884
|
+
children: [
|
|
885
|
+
/* @__PURE__ */ jsx(
|
|
886
|
+
"span",
|
|
891
887
|
{
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
children:
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
888
|
+
className: "text-xs font-medium",
|
|
889
|
+
style: accentTextColor ? { color: accentTextColor } : void 0,
|
|
890
|
+
children: authorName
|
|
891
|
+
}
|
|
892
|
+
),
|
|
893
|
+
participant?.role && /* @__PURE__ */ jsx("span", { className: "text-[10px] text-neutral-500 dark:text-neutral-400", children: participant.role }),
|
|
894
|
+
/* @__PURE__ */ jsx("span", { className: "text-[10px] text-neutral-500 dark:text-neutral-400", children: formatTime(message.time) }),
|
|
895
|
+
message.editedAt && /* @__PURE__ */ jsx(
|
|
896
|
+
"span",
|
|
897
|
+
{
|
|
898
|
+
"data-slot": "superchat-edited-indicator",
|
|
899
|
+
className: "text-[10px] text-neutral-500 dark:text-neutral-400",
|
|
900
|
+
title: `Edited ${formatTime(message.editedAt)}`,
|
|
901
|
+
children: "(edited)"
|
|
902
|
+
}
|
|
903
|
+
)
|
|
904
|
+
]
|
|
905
|
+
}
|
|
906
|
+
),
|
|
907
|
+
/* @__PURE__ */ jsx(
|
|
908
|
+
"div",
|
|
909
|
+
{
|
|
910
|
+
className: cn(
|
|
911
|
+
"flex w-full items-center gap-1",
|
|
912
|
+
isSelf ? "flex-row-reverse" : "flex-row"
|
|
913
|
+
),
|
|
914
|
+
children: /* @__PURE__ */ jsx(
|
|
915
|
+
ChatBubble,
|
|
916
|
+
{
|
|
917
|
+
ref: bubbleRef,
|
|
918
|
+
"data-slot": "superchat-bubble",
|
|
919
|
+
variant: isSelf ? "user" : "assistant",
|
|
920
|
+
hasError: message.status === "error",
|
|
921
|
+
className: "text-sm has-[[data-slot=superchat-nitro-table]]:w-full has-[[data-slot=superchat-nitro-table]]:max-w-full",
|
|
922
|
+
children: isEditing ? /* @__PURE__ */ jsxs(
|
|
923
|
+
"div",
|
|
924
|
+
{
|
|
925
|
+
"data-slot": "superchat-message-editor",
|
|
926
|
+
className: "flex w-80 max-w-full flex-col gap-2",
|
|
927
|
+
style: editMinWidth ? { minWidth: editMinWidth } : void 0,
|
|
928
|
+
children: [
|
|
920
929
|
/* @__PURE__ */ jsx(
|
|
921
|
-
"
|
|
930
|
+
"textarea",
|
|
922
931
|
{
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
932
|
+
value: draft,
|
|
933
|
+
ref: editRef,
|
|
934
|
+
rows: 2,
|
|
935
|
+
onChange: (e) => {
|
|
936
|
+
setDraft(e.target.value);
|
|
937
|
+
autosize();
|
|
938
|
+
},
|
|
939
|
+
onPaste: handleEditPaste,
|
|
940
|
+
onKeyDown: (e) => {
|
|
941
|
+
if (e.key === "Enter" && !e.shiftKey) {
|
|
942
|
+
e.preventDefault();
|
|
943
|
+
saveEdit();
|
|
944
|
+
} else if (e.key === "Escape") {
|
|
945
|
+
e.preventDefault();
|
|
946
|
+
cancelEdit();
|
|
947
|
+
}
|
|
948
|
+
},
|
|
949
|
+
"aria-label": "Edit message",
|
|
950
|
+
className: "focus:ring-primary-500 max-h-60 min-h-16 w-full resize-none rounded-lg border border-neutral-300 bg-white px-3 py-2 text-sm text-neutral-900 focus:ring-1 focus:outline-none dark:border-neutral-600 dark:bg-neutral-900 dark:text-white"
|
|
927
951
|
}
|
|
928
952
|
),
|
|
929
|
-
/* @__PURE__ */
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
className: "prose prose-sm dark:prose-invert max-w-none **:wrap-break-word",
|
|
952
|
-
children: renderText(block.text, {
|
|
953
|
-
messageId: message.id,
|
|
954
|
-
streaming,
|
|
955
|
-
role: participant?.kind === "human" ? "user" : "assistant"
|
|
956
|
-
})
|
|
957
|
-
},
|
|
958
|
-
i
|
|
959
|
-
);
|
|
953
|
+
/* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
|
|
954
|
+
/* @__PURE__ */ jsx(
|
|
955
|
+
"button",
|
|
956
|
+
{
|
|
957
|
+
type: "button",
|
|
958
|
+
onClick: cancelEdit,
|
|
959
|
+
className: "rounded-md px-2.5 py-1 text-xs font-medium text-neutral-200 hover:bg-white/10",
|
|
960
|
+
children: "Cancel"
|
|
961
|
+
}
|
|
962
|
+
),
|
|
963
|
+
/* @__PURE__ */ jsx(
|
|
964
|
+
"button",
|
|
965
|
+
{
|
|
966
|
+
type: "button",
|
|
967
|
+
onClick: saveEdit,
|
|
968
|
+
disabled: !draft.trim() || draft.trim() === message.text,
|
|
969
|
+
className: "rounded-md bg-white px-2.5 py-1 text-xs font-medium text-neutral-900 hover:bg-neutral-100 disabled:opacity-40",
|
|
970
|
+
children: "Save"
|
|
971
|
+
}
|
|
972
|
+
)
|
|
973
|
+
] })
|
|
974
|
+
]
|
|
960
975
|
}
|
|
961
|
-
|
|
962
|
-
|
|
976
|
+
) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
977
|
+
message.content?.map((block, i) => {
|
|
978
|
+
if (block.type === "tool_use" && block.toolCall) {
|
|
979
|
+
return /* @__PURE__ */ jsx(MCPToolCallDisplay, { toolCall: block.toolCall }, i);
|
|
980
|
+
}
|
|
981
|
+
if ((block.type === "text" || block.type === "thinking") && block.text) {
|
|
982
|
+
return /* @__PURE__ */ jsx(
|
|
983
|
+
"div",
|
|
984
|
+
{
|
|
985
|
+
className: "prose prose-sm dark:prose-invert max-w-none **:wrap-break-word",
|
|
986
|
+
children: renderText(block.text, {
|
|
987
|
+
messageId: message.id,
|
|
988
|
+
streaming,
|
|
989
|
+
role: participant?.kind === "human" ? "user" : "assistant"
|
|
990
|
+
})
|
|
991
|
+
},
|
|
992
|
+
i
|
|
993
|
+
);
|
|
994
|
+
}
|
|
995
|
+
if (block.type === "code" && block.text) {
|
|
996
|
+
const fenced = `\`\`\`${block.language ?? ""}
|
|
963
997
|
${block.text}
|
|
964
998
|
\`\`\``;
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
{
|
|
995
|
-
ref: actionsBarRef,
|
|
996
|
-
actions,
|
|
997
|
-
isSelf
|
|
998
|
-
}
|
|
999
|
-
)
|
|
1000
|
-
] })
|
|
999
|
+
return /* @__PURE__ */ jsx(
|
|
1000
|
+
"div",
|
|
1001
|
+
{
|
|
1002
|
+
className: "prose prose-sm dark:prose-invert max-w-none **:wrap-break-word",
|
|
1003
|
+
children: renderText(fenced, {
|
|
1004
|
+
messageId: message.id,
|
|
1005
|
+
streaming,
|
|
1006
|
+
role: participant?.kind === "human" ? "user" : "assistant"
|
|
1007
|
+
})
|
|
1008
|
+
},
|
|
1009
|
+
i
|
|
1010
|
+
);
|
|
1011
|
+
}
|
|
1012
|
+
return null;
|
|
1013
|
+
}),
|
|
1014
|
+
message.text && /* @__PURE__ */ jsx("div", { className: "prose prose-sm dark:prose-invert max-w-none **:wrap-break-word", children: renderText(message.text, {
|
|
1015
|
+
messageId: message.id,
|
|
1016
|
+
streaming,
|
|
1017
|
+
role: participant?.kind === "human" ? "user" : "assistant"
|
|
1018
|
+
}) }),
|
|
1019
|
+
streaming && !hasBody && /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx(AITypingIndicator, {}) })
|
|
1020
|
+
] })
|
|
1021
|
+
}
|
|
1022
|
+
)
|
|
1023
|
+
}
|
|
1024
|
+
)
|
|
1025
|
+
]
|
|
1026
|
+
}
|
|
1027
|
+
)
|
|
1001
1028
|
]
|
|
1002
1029
|
}
|
|
1003
1030
|
);
|
|
@@ -1024,32 +1051,23 @@ function VirtualThread({
|
|
|
1024
1051
|
editable,
|
|
1025
1052
|
onMessageEdited,
|
|
1026
1053
|
defaultCopyFormat,
|
|
1027
|
-
|
|
1028
|
-
|
|
1054
|
+
scrollRef,
|
|
1055
|
+
contentRef,
|
|
1029
1056
|
containerProps
|
|
1030
1057
|
}) {
|
|
1031
|
-
const parentRef = React2.useRef(null);
|
|
1032
1058
|
const virtualizer = useVirtualizer({
|
|
1033
1059
|
count: items.length,
|
|
1034
|
-
getScrollElement: () =>
|
|
1060
|
+
getScrollElement: () => scrollRef.current,
|
|
1035
1061
|
// Rough first guess; real heights are measured via measureElement.
|
|
1036
1062
|
estimateSize: () => 88,
|
|
1037
1063
|
overscan: 10,
|
|
1038
1064
|
getItemKey: (index) => items[index]?.id ?? index
|
|
1039
1065
|
});
|
|
1040
|
-
const count = items.length;
|
|
1041
|
-
React2.useEffect(() => {
|
|
1042
|
-
if (count === 0) return;
|
|
1043
|
-
if (order === "desc") {
|
|
1044
|
-
virtualizer.scrollToIndex(0, { align: "start" });
|
|
1045
|
-
} else {
|
|
1046
|
-
virtualizer.scrollToIndex(count - 1, { align: "end" });
|
|
1047
|
-
}
|
|
1048
|
-
}, [count, conversationId, order]);
|
|
1049
1066
|
const virtualItems = virtualizer.getVirtualItems();
|
|
1050
|
-
return /* @__PURE__ */ jsx("div", { ...containerProps, ref:
|
|
1067
|
+
return /* @__PURE__ */ jsx("div", { ...containerProps, ref: scrollRef, children: /* @__PURE__ */ jsx(
|
|
1051
1068
|
"div",
|
|
1052
1069
|
{
|
|
1070
|
+
ref: contentRef,
|
|
1053
1071
|
style: {
|
|
1054
1072
|
height: virtualizer.getTotalSize(),
|
|
1055
1073
|
position: "relative",
|
|
@@ -1110,38 +1128,180 @@ function SuperChat({
|
|
|
1110
1128
|
onReferenceClick,
|
|
1111
1129
|
onBack
|
|
1112
1130
|
}) {
|
|
1113
|
-
const headingId =
|
|
1114
|
-
|
|
1131
|
+
const headingId = React3.useId();
|
|
1132
|
+
React3.useEffect(() => {
|
|
1115
1133
|
notifyComposerMigrationOnce("SuperChat");
|
|
1116
1134
|
}, []);
|
|
1117
|
-
const renderText =
|
|
1135
|
+
const renderText = React3.useMemo(
|
|
1118
1136
|
() => renderTextContent ?? createMarkdownRenderer({
|
|
1119
1137
|
plugins: renderPlugins,
|
|
1120
1138
|
trusted: trustedContent
|
|
1121
1139
|
}),
|
|
1122
1140
|
[renderTextContent, renderPlugins, trustedContent]
|
|
1123
1141
|
);
|
|
1124
|
-
const
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
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(() => {
|
|
1132
1273
|
const map = /* @__PURE__ */ new Map();
|
|
1133
1274
|
conversation.participants.forEach((p) => map.set(p.id, p));
|
|
1134
1275
|
return map;
|
|
1135
1276
|
}, [conversation]);
|
|
1136
|
-
const orderedThread =
|
|
1277
|
+
const orderedThread = React3.useMemo(() => {
|
|
1137
1278
|
const sorted = [...conversation.thread].sort(byTime);
|
|
1138
1279
|
return order === "desc" ? sorted.reverse() : sorted;
|
|
1139
1280
|
}, [conversation, order]);
|
|
1140
|
-
const
|
|
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);
|
|
1141
1301
|
onMessageEditedRef.current = onMessageEdited;
|
|
1142
|
-
const conversationRef =
|
|
1302
|
+
const conversationRef = React3.useRef(conversation);
|
|
1143
1303
|
conversationRef.current = conversation;
|
|
1144
|
-
const handleMessageEdited =
|
|
1304
|
+
const handleMessageEdited = React3.useCallback(
|
|
1145
1305
|
(messageId, text) => {
|
|
1146
1306
|
onMessageEditedRef.current?.(messageId, text, {
|
|
1147
1307
|
conversation: conversationRef.current
|
|
@@ -1150,7 +1310,7 @@ function SuperChat({
|
|
|
1150
1310
|
[]
|
|
1151
1311
|
);
|
|
1152
1312
|
const editable = !readOnly && !!onMessageEdited;
|
|
1153
|
-
const mentionOptions =
|
|
1313
|
+
const mentionOptions = React3.useMemo(
|
|
1154
1314
|
() => conversation.participants.filter((p) => p.kind !== "system").map((p) => ({
|
|
1155
1315
|
id: p.id,
|
|
1156
1316
|
label: p.name,
|
|
@@ -1160,17 +1320,17 @@ function SuperChat({
|
|
|
1160
1320
|
})),
|
|
1161
1321
|
[conversation.participants]
|
|
1162
1322
|
);
|
|
1163
|
-
const composerAccept =
|
|
1323
|
+
const composerAccept = React3.useMemo(
|
|
1164
1324
|
() => acceptTokensFor(acceptedFileTypes),
|
|
1165
1325
|
[acceptedFileTypes]
|
|
1166
1326
|
);
|
|
1167
|
-
const [draft, setDraft] =
|
|
1168
|
-
const draftEpochRef =
|
|
1169
|
-
const handleDraftChange =
|
|
1327
|
+
const [draft, setDraft] = React3.useState("");
|
|
1328
|
+
const draftEpochRef = React3.useRef(0);
|
|
1329
|
+
const handleDraftChange = React3.useCallback((value) => {
|
|
1170
1330
|
draftEpochRef.current += 1;
|
|
1171
1331
|
setDraft(value);
|
|
1172
1332
|
}, []);
|
|
1173
|
-
const handleComposerSend =
|
|
1333
|
+
const handleComposerSend = React3.useCallback(
|
|
1174
1334
|
async (message) => {
|
|
1175
1335
|
const epoch = draftEpochRef.current;
|
|
1176
1336
|
try {
|
|
@@ -1266,55 +1426,69 @@ function SuperChat({
|
|
|
1266
1426
|
]
|
|
1267
1427
|
}
|
|
1268
1428
|
),
|
|
1269
|
-
|
|
1270
|
-
VirtualThread,
|
|
1271
|
-
{
|
|
1272
|
-
items: orderedThread,
|
|
1273
|
-
participantById,
|
|
1274
|
-
currentParticipantId,
|
|
1275
|
-
renderText,
|
|
1276
|
-
linkBuilder,
|
|
1277
|
-
onReferenceClick,
|
|
1278
|
-
editable,
|
|
1279
|
-
onMessageEdited: handleMessageEdited,
|
|
1280
|
-
defaultCopyFormat,
|
|
1281
|
-
order,
|
|
1282
|
-
conversationId: conversation.id,
|
|
1283
|
-
containerProps: {
|
|
1284
|
-
"data-slot": "superchat-thread",
|
|
1285
|
-
role: "log",
|
|
1286
|
-
"aria-label": "Messages",
|
|
1287
|
-
"aria-live": "polite",
|
|
1288
|
-
// Focusable so keyboard-only users can scroll the message history.
|
|
1289
|
-
tabIndex: 0,
|
|
1290
|
-
className: "flex-1 overflow-y-auto p-4"
|
|
1291
|
-
}
|
|
1292
|
-
}
|
|
1293
|
-
) : /* @__PURE__ */ jsx(
|
|
1429
|
+
/* @__PURE__ */ jsxs(
|
|
1294
1430
|
"div",
|
|
1295
1431
|
{
|
|
1296
|
-
"data-slot": "superchat-thread",
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
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
|
+
]
|
|
1318
1492
|
}
|
|
1319
1493
|
),
|
|
1320
1494
|
/* @__PURE__ */ jsx(
|
|
@@ -1324,6 +1498,7 @@ function SuperChat({
|
|
|
1324
1498
|
onValueChange: handleDraftChange,
|
|
1325
1499
|
onSend: handleComposerSend,
|
|
1326
1500
|
disabled: readOnly,
|
|
1501
|
+
className: "px-4 pb-4",
|
|
1327
1502
|
placeholder: readOnly ? "Read-only conversation" : "Type a message\u2026 use @ to address an agent",
|
|
1328
1503
|
mentionOptions,
|
|
1329
1504
|
allowAttachments: !readOnly,
|
|
@@ -1345,12 +1520,12 @@ function SuperChatConversations({
|
|
|
1345
1520
|
onConversationOpened,
|
|
1346
1521
|
onNewConversation
|
|
1347
1522
|
}) {
|
|
1348
|
-
const [internalActive, setInternalActive] =
|
|
1523
|
+
const [internalActive, setInternalActive] = React3.useState(
|
|
1349
1524
|
defaultActiveConversationId ?? conversations[0]?.id
|
|
1350
1525
|
);
|
|
1351
1526
|
const requestedId = activeConversationId ?? internalActive;
|
|
1352
1527
|
const activeId = conversations.some((c) => c.id === requestedId) ? requestedId : conversations[0]?.id;
|
|
1353
|
-
const sortedConversations =
|
|
1528
|
+
const sortedConversations = React3.useMemo(
|
|
1354
1529
|
() => [...conversations].sort((a, b) => lastActivityOf(b) - lastActivityOf(a)),
|
|
1355
1530
|
[conversations]
|
|
1356
1531
|
);
|
|
@@ -1439,13 +1614,13 @@ function SuperChatInbox({
|
|
|
1439
1614
|
onNewConversation,
|
|
1440
1615
|
onReferenceClick
|
|
1441
1616
|
}) {
|
|
1442
|
-
const [internalActive, setInternalActive] =
|
|
1617
|
+
const [internalActive, setInternalActive] = React3.useState(
|
|
1443
1618
|
defaultActiveConversationId ?? conversations[0]?.id
|
|
1444
1619
|
);
|
|
1445
1620
|
const requestedId = activeConversationId ?? internalActive;
|
|
1446
1621
|
const active = conversations.find((c) => c.id === requestedId) ?? conversations[0];
|
|
1447
1622
|
const activeId = active?.id;
|
|
1448
|
-
const [mobileView, setMobileView] =
|
|
1623
|
+
const [mobileView, setMobileView] = React3.useState("list");
|
|
1449
1624
|
const handleOpen = (c) => {
|
|
1450
1625
|
if (activeConversationId === void 0) setInternalActive(c.id);
|
|
1451
1626
|
setMobileView("chat");
|