@nextclaw/agent-chat-ui 0.5.0 → 0.5.1-beta.1
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/index.d.ts +48 -14
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +466 -240
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -5,7 +5,7 @@ import { twMerge } from "tailwind-merge";
|
|
|
5
5
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
6
6
|
import * as PopoverPrimitive from "@radix-ui/react-popover";
|
|
7
7
|
import * as SelectPrimitive from "@radix-ui/react-select";
|
|
8
|
-
import { AlertTriangle, ArrowUp, ArrowUpRight, Bot, Brain, BrainCircuit, Check, ChevronDown, ChevronRight, ChevronUp, Code2, Copy, ExternalLink, Eye, File, FileArchive, FileAudio2, FileCode2, FileImage, FileJson2, FileSpreadsheet, FileText, FileVideo2, Globe, Loader2, Minus, Paperclip, Puzzle, Search, Sparkles, Terminal, User, Wrench } from "lucide-react";
|
|
8
|
+
import { AlertTriangle, ArrowUp, ArrowUpRight, Bot, Brain, BrainCircuit, Check, ChevronDown, ChevronRight, ChevronUp, Code2, Copy, ExternalLink, Eye, File, FileArchive, FileAudio2, FileCode2, FileImage, FileJson2, FileSpreadsheet, FileText, FileVideo2, Globe, Loader2, Minus, Paperclip, Puzzle, Search, Sparkles, Star, Terminal, User, Wrench } from "lucide-react";
|
|
9
9
|
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
|
|
10
10
|
import { cva } from "class-variance-authority";
|
|
11
11
|
import { ContentEditable } from "@lexical/react/LexicalContentEditable";
|
|
@@ -89,14 +89,24 @@ const ChatInput = React.forwardRef(({ className, type, ...props }, ref) => /* @_
|
|
|
89
89
|
ChatInput.displayName = "ChatInput";
|
|
90
90
|
//#endregion
|
|
91
91
|
//#region src/components/chat/default-skin/popover.tsx
|
|
92
|
+
const CHAT_FLOATING_CONTENT_AVAILABLE_HEIGHT_GAP = "2rem";
|
|
93
|
+
function createChatPopoverAvailableHeightLimit(limit) {
|
|
94
|
+
return `min(${limit}, max(0px, calc(var(--radix-popover-content-available-height, 100vh) - ${CHAT_FLOATING_CONTENT_AVAILABLE_HEIGHT_GAP})))`;
|
|
95
|
+
}
|
|
96
|
+
const CHAT_POPOVER_CONTENT_MAX_HEIGHT = createChatPopoverAvailableHeightLimit("24rem");
|
|
92
97
|
const ChatPopover = PopoverPrimitive.Root;
|
|
93
98
|
const ChatPopoverTrigger = PopoverPrimitive.Trigger;
|
|
94
99
|
const ChatPopoverAnchor = PopoverPrimitive.Anchor;
|
|
95
|
-
const ChatPopoverContent = React.forwardRef(({ className, sideOffset = 8, align = "start", ...props }, ref) => /* @__PURE__ */ jsx(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx(PopoverPrimitive.Content, {
|
|
100
|
+
const ChatPopoverContent = React.forwardRef(({ className, sideOffset = 8, align = "start", collisionPadding = 12, style, ...props }, ref) => /* @__PURE__ */ jsx(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx(PopoverPrimitive.Content, {
|
|
96
101
|
ref,
|
|
97
102
|
sideOffset,
|
|
98
103
|
align,
|
|
99
|
-
|
|
104
|
+
collisionPadding,
|
|
105
|
+
className: cn("z-[var(--z-popover,50)] w-72 overflow-x-hidden overflow-y-auto rounded-2xl border border-gray-200/50 bg-white p-4 shadow-lg animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2", className),
|
|
106
|
+
style: {
|
|
107
|
+
maxHeight: CHAT_POPOVER_CONTENT_MAX_HEIGHT,
|
|
108
|
+
...style
|
|
109
|
+
},
|
|
100
110
|
...props
|
|
101
111
|
}) }));
|
|
102
112
|
ChatPopoverContent.displayName = PopoverPrimitive.Content.displayName;
|
|
@@ -105,6 +115,11 @@ ChatPopoverContent.displayName = PopoverPrimitive.Content.displayName;
|
|
|
105
115
|
const ChatSelect = SelectPrimitive.Root;
|
|
106
116
|
const ChatSelectGroup = SelectPrimitive.Group;
|
|
107
117
|
const ChatSelectValue = SelectPrimitive.Value;
|
|
118
|
+
const CHAT_SELECT_CONTENT_AVAILABLE_HEIGHT_GAP = "2rem";
|
|
119
|
+
function createChatSelectAvailableHeightLimit(limit) {
|
|
120
|
+
return `min(${limit}, max(0px, calc(var(--radix-select-content-available-height, 100vh) - ${CHAT_SELECT_CONTENT_AVAILABLE_HEIGHT_GAP})))`;
|
|
121
|
+
}
|
|
122
|
+
const CHAT_SELECT_CONTENT_MAX_HEIGHT = createChatSelectAvailableHeightLimit("24rem");
|
|
108
123
|
const ChatSelectTrigger = React.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(SelectPrimitive.Trigger, {
|
|
109
124
|
ref,
|
|
110
125
|
className: cn("flex h-9 w-full items-center justify-between whitespace-nowrap rounded-xl border border-gray-200/80 bg-white px-3 py-2 text-sm shadow-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-primary/40 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1", className),
|
|
@@ -129,15 +144,20 @@ const ChatSelectScrollDownButton = React.forwardRef(({ className, ...props }, re
|
|
|
129
144
|
children: /* @__PURE__ */ jsx(ChevronDown, { className: "h-4 w-4" })
|
|
130
145
|
}));
|
|
131
146
|
ChatSelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName;
|
|
132
|
-
const ChatSelectContent = React.forwardRef(({ className, children, position = "popper", ...props }, ref) => /* @__PURE__ */ jsx(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsxs(SelectPrimitive.Content, {
|
|
147
|
+
const ChatSelectContent = React.forwardRef(({ className, children, collisionPadding = 12, position = "popper", style, viewportClassName, ...props }, ref) => /* @__PURE__ */ jsx(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsxs(SelectPrimitive.Content, {
|
|
133
148
|
ref,
|
|
134
|
-
className: cn("relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md bg-white text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2", position === "popper" && "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1", className),
|
|
149
|
+
className: cn("relative z-50 flex max-h-96 min-w-[8rem] flex-col overflow-hidden rounded-md bg-white text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2", position === "popper" && "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1", className),
|
|
150
|
+
collisionPadding,
|
|
135
151
|
position,
|
|
152
|
+
style: {
|
|
153
|
+
maxHeight: CHAT_SELECT_CONTENT_MAX_HEIGHT,
|
|
154
|
+
...style
|
|
155
|
+
},
|
|
136
156
|
...props,
|
|
137
157
|
children: [
|
|
138
158
|
/* @__PURE__ */ jsx(ChatSelectScrollUpButton, {}),
|
|
139
159
|
/* @__PURE__ */ jsx(SelectPrimitive.Viewport, {
|
|
140
|
-
className: cn("p-1", position === "popper" && "
|
|
160
|
+
className: cn("min-h-0 flex-1 overflow-y-auto overscroll-contain p-1", position === "popper" && "w-full min-w-[var(--radix-select-trigger-width)]", viewportClassName),
|
|
141
161
|
children
|
|
142
162
|
}),
|
|
143
163
|
/* @__PURE__ */ jsx(ChatSelectScrollDownButton, {})
|
|
@@ -204,6 +224,8 @@ const ChatUiPrimitives = {
|
|
|
204
224
|
const SLASH_PANEL_MAX_WIDTH = 680;
|
|
205
225
|
const SLASH_PANEL_DESKTOP_SHRINK_RATIO = .82;
|
|
206
226
|
const SLASH_PANEL_DESKTOP_MIN_WIDTH = 560;
|
|
227
|
+
const SLASH_PANEL_MAX_HEIGHT = createChatPopoverAvailableHeightLimit("24rem");
|
|
228
|
+
const SLASH_PANEL_MIN_HEIGHT = createChatPopoverAvailableHeightLimit("240px");
|
|
207
229
|
function ChatSlashMenu(props) {
|
|
208
230
|
const { Popover, PopoverAnchor, PopoverContent } = ChatUiPrimitives;
|
|
209
231
|
const { elementRef: anchorRef, width: panelWidth } = useElementWidth();
|
|
@@ -233,16 +255,20 @@ function ChatSlashMenu(props) {
|
|
|
233
255
|
side: "top",
|
|
234
256
|
align: "start",
|
|
235
257
|
sideOffset: 10,
|
|
236
|
-
className: "z-[70] max-w-[calc(100vw-1.5rem)] overflow-hidden rounded-2xl border border-gray-200 bg-white/95 p-0 shadow-2xl backdrop-blur-md",
|
|
258
|
+
className: "z-[70] flex max-w-[calc(100vw-1.5rem)] flex-col overflow-hidden rounded-2xl border border-gray-200 bg-white/95 p-0 shadow-2xl backdrop-blur-md",
|
|
237
259
|
onOpenAutoFocus: (event) => event.preventDefault(),
|
|
238
|
-
style:
|
|
260
|
+
style: {
|
|
261
|
+
maxHeight: SLASH_PANEL_MAX_HEIGHT,
|
|
262
|
+
width: resolvedWidth ? `${resolvedWidth}px` : void 0
|
|
263
|
+
},
|
|
239
264
|
children: /* @__PURE__ */ jsxs("div", {
|
|
240
|
-
className: "grid min-h-
|
|
265
|
+
className: "grid min-h-0 flex-1 grid-cols-[minmax(220px,300px)_minmax(0,1fr)]",
|
|
266
|
+
style: { minHeight: SLASH_PANEL_MIN_HEIGHT },
|
|
241
267
|
children: [/* @__PURE__ */ jsx("div", {
|
|
242
268
|
ref: listRef,
|
|
243
269
|
role: "listbox",
|
|
244
270
|
"aria-label": texts.slashSectionLabel,
|
|
245
|
-
className: "custom-scrollbar
|
|
271
|
+
className: "custom-scrollbar min-h-0 overflow-y-auto overscroll-contain border-r border-gray-200 p-2.5",
|
|
246
272
|
children: isLoading ? /* @__PURE__ */ jsx("div", {
|
|
247
273
|
className: "p-2 text-xs text-gray-500",
|
|
248
274
|
children: texts.slashLoadingLabel
|
|
@@ -275,7 +301,7 @@ function ChatSlashMenu(props) {
|
|
|
275
301
|
})
|
|
276
302
|
})] })
|
|
277
303
|
}), /* @__PURE__ */ jsx("div", {
|
|
278
|
-
className: "min-w-0 p-2.5",
|
|
304
|
+
className: "custom-scrollbar min-h-0 min-w-0 overflow-y-auto overscroll-contain p-2.5",
|
|
279
305
|
onPointerDown: onDetailsPointerDown,
|
|
280
306
|
children: activeItem ? /* @__PURE__ */ jsxs("div", {
|
|
281
307
|
className: "space-y-3",
|
|
@@ -494,6 +520,7 @@ function filterOptions(options, query) {
|
|
|
494
520
|
].filter((value) => typeof value === "string" && value.trim().length > 0).join(" ").toLowerCase().includes(keyword);
|
|
495
521
|
});
|
|
496
522
|
}
|
|
523
|
+
const SKILL_PICKER_MAX_HEIGHT = createChatPopoverAvailableHeightLimit("24rem");
|
|
497
524
|
function ChatInputBarSkillPicker(props) {
|
|
498
525
|
const { Input, Popover, PopoverContent, PopoverTrigger } = ChatUiPrimitives;
|
|
499
526
|
const { picker } = props;
|
|
@@ -580,10 +607,11 @@ function ChatInputBarSkillPicker(props) {
|
|
|
580
607
|
}), /* @__PURE__ */ jsxs(PopoverContent, {
|
|
581
608
|
side: "top",
|
|
582
609
|
align: "start",
|
|
583
|
-
className: "w-[360px] p-0",
|
|
610
|
+
className: "flex w-[min(360px,calc(100vw-1rem))] flex-col overflow-hidden p-0",
|
|
611
|
+
style: { maxHeight: SKILL_PICKER_MAX_HEIGHT },
|
|
584
612
|
children: [
|
|
585
613
|
/* @__PURE__ */ jsxs("div", {
|
|
586
|
-
className: "space-y-2 border-b border-gray-100 px-4 py-3",
|
|
614
|
+
className: "shrink-0 space-y-2 border-b border-gray-100 px-4 py-3",
|
|
587
615
|
children: [/* @__PURE__ */ jsx("div", {
|
|
588
616
|
className: "text-sm font-semibold text-gray-900",
|
|
589
617
|
children: picker.title
|
|
@@ -608,7 +636,7 @@ function ChatInputBarSkillPicker(props) {
|
|
|
608
636
|
id: listId,
|
|
609
637
|
role: "listbox",
|
|
610
638
|
"aria-multiselectable": "true",
|
|
611
|
-
className: "custom-scrollbar
|
|
639
|
+
className: "custom-scrollbar min-h-0 flex-1 overflow-y-auto overscroll-contain",
|
|
612
640
|
children: picker.isLoading ? /* @__PURE__ */ jsx("div", {
|
|
613
641
|
className: "p-4 text-xs text-gray-500",
|
|
614
642
|
children: picker.loadingLabel
|
|
@@ -676,7 +704,7 @@ function ChatInputBarSkillPicker(props) {
|
|
|
676
704
|
})
|
|
677
705
|
}),
|
|
678
706
|
picker.manageHref && picker.manageLabel ? /* @__PURE__ */ jsx("div", {
|
|
679
|
-
className: "border-t border-gray-100 px-4 py-2.5",
|
|
707
|
+
className: "shrink-0 border-t border-gray-100 px-4 py-2.5",
|
|
680
708
|
children: /* @__PURE__ */ jsxs("a", {
|
|
681
709
|
href: picker.manageHref,
|
|
682
710
|
className: "inline-flex items-center gap-1.5 text-xs font-medium text-primary transition-colors hover:text-primary/80",
|
|
@@ -704,17 +732,173 @@ const CONTENT_WIDTH_BY_KEY = {
|
|
|
704
732
|
"session-type": "w-[220px]",
|
|
705
733
|
thinking: "w-[180px]"
|
|
706
734
|
};
|
|
735
|
+
const TOOLBAR_POPOVER_MAX_HEIGHT = createChatPopoverAvailableHeightLimit("18rem");
|
|
736
|
+
const TOOLBAR_SELECT_MAX_HEIGHT = createChatSelectAvailableHeightLimit("18rem");
|
|
707
737
|
function resolveMobileSelectedLabel(item) {
|
|
708
738
|
return item.key === "model" && item.selectedLabel ? item.selectedLabel.split("/").slice(1).join("/").trim() || item.selectedLabel : item.selectedLabel;
|
|
709
739
|
}
|
|
710
|
-
function
|
|
711
|
-
|
|
712
|
-
const groups = item.groups?.filter((group) => group.options.length > 0) ?? (item.options.length > 0 ? [{
|
|
740
|
+
function buildSelectGroups(item) {
|
|
741
|
+
return item.groups?.filter((group) => group.options.length > 0) ?? (item.options.length > 0 ? [{
|
|
713
742
|
key: `${item.key}-default`,
|
|
714
743
|
options: item.options
|
|
715
744
|
}] : []);
|
|
716
|
-
|
|
745
|
+
}
|
|
746
|
+
function ToolbarSelectTriggerContent({ item }) {
|
|
717
747
|
const mobileSelectedLabel = resolveMobileSelectedLabel(item);
|
|
748
|
+
if (item.selectedLabel) return /* @__PURE__ */ jsxs("div", {
|
|
749
|
+
className: "flex min-w-0 items-center gap-2 text-left",
|
|
750
|
+
children: [
|
|
751
|
+
/* @__PURE__ */ jsx(ToolbarIcon, { icon: item.icon }),
|
|
752
|
+
/* @__PURE__ */ jsx("span", {
|
|
753
|
+
className: "nextclaw-chat-toolbar-mobile-label truncate text-xs font-semibold text-gray-700 sm:hidden [@container_nextclaw-chat-input-bar_(max-width:440px)]:hidden",
|
|
754
|
+
children: mobileSelectedLabel
|
|
755
|
+
}),
|
|
756
|
+
/* @__PURE__ */ jsx("span", {
|
|
757
|
+
className: "nextclaw-chat-toolbar-label hidden truncate text-xs font-semibold text-gray-700 sm:inline [@container_nextclaw-chat-input-bar_(max-width:440px)]:hidden",
|
|
758
|
+
children: item.selectedLabel
|
|
759
|
+
})
|
|
760
|
+
]
|
|
761
|
+
});
|
|
762
|
+
if (item.loading) return /* @__PURE__ */ jsx("div", { className: "h-3 w-24 animate-pulse rounded bg-gray-200" });
|
|
763
|
+
return /* @__PURE__ */ jsx("span", {
|
|
764
|
+
className: "truncate",
|
|
765
|
+
children: item.placeholder
|
|
766
|
+
});
|
|
767
|
+
}
|
|
768
|
+
function ToolbarSelectOptionContent({ option }) {
|
|
769
|
+
return option.description ? /* @__PURE__ */ jsxs("div", {
|
|
770
|
+
className: "flex min-w-0 flex-col gap-0.5",
|
|
771
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
772
|
+
className: "truncate text-xs font-semibold text-gray-800",
|
|
773
|
+
children: option.label
|
|
774
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
775
|
+
className: "truncate text-[11px] text-gray-500",
|
|
776
|
+
children: option.description
|
|
777
|
+
})]
|
|
778
|
+
}) : /* @__PURE__ */ jsx("span", {
|
|
779
|
+
className: "truncate text-xs font-semibold text-gray-800",
|
|
780
|
+
children: option.label
|
|
781
|
+
});
|
|
782
|
+
}
|
|
783
|
+
function ToolbarSearchableSelect({ item }) {
|
|
784
|
+
const { Input, Popover, PopoverContent, PopoverTrigger, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } = ChatUiPrimitives;
|
|
785
|
+
const [open, setOpen] = useState(false);
|
|
786
|
+
const [query, setQuery] = useState("");
|
|
787
|
+
const groups = buildSelectGroups(item);
|
|
788
|
+
const filteredGroups = useMemo(() => {
|
|
789
|
+
const normalizedQuery = query.trim().toLowerCase();
|
|
790
|
+
if (!normalizedQuery) return groups;
|
|
791
|
+
return groups.map((group) => ({
|
|
792
|
+
...group,
|
|
793
|
+
options: group.options.filter((option) => [
|
|
794
|
+
option.label,
|
|
795
|
+
option.value,
|
|
796
|
+
option.description
|
|
797
|
+
].filter((value) => Boolean(value)).some((value) => value.toLowerCase().includes(normalizedQuery)))
|
|
798
|
+
})).filter((group) => group.options.length > 0);
|
|
799
|
+
}, [groups, query]);
|
|
800
|
+
const hasOptions = groups.some((group) => group.options.length > 0);
|
|
801
|
+
const hasFilteredOptions = filteredGroups.some((group) => group.options.length > 0);
|
|
802
|
+
const action = item.optionAction;
|
|
803
|
+
const activeValues = new Set(action?.activeValues ?? []);
|
|
804
|
+
return /* @__PURE__ */ jsxs(Popover, {
|
|
805
|
+
open,
|
|
806
|
+
onOpenChange: setOpen,
|
|
807
|
+
children: [/* @__PURE__ */ jsx(PopoverTrigger, {
|
|
808
|
+
asChild: true,
|
|
809
|
+
children: /* @__PURE__ */ jsxs("button", {
|
|
810
|
+
type: "button",
|
|
811
|
+
"aria-label": item.selectedLabel ? `${item.placeholder}: ${item.selectedLabel}` : item.placeholder,
|
|
812
|
+
disabled: item.disabled,
|
|
813
|
+
className: `nextclaw-chat-toolbar-select-trigger inline-flex h-8 w-auto items-center justify-between rounded-lg border-0 bg-transparent px-2 text-xs font-medium text-gray-600 shadow-none hover:bg-gray-100 focus:outline-none focus:ring-0 disabled:cursor-not-allowed disabled:opacity-50 sm:px-3 [@container_nextclaw-chat-input-bar_(max-width:440px)]:!basis-8 [@container_nextclaw-chat-input-bar_(max-width:440px)]:!justify-center [@container_nextclaw-chat-input-bar_(max-width:440px)]:!max-w-8 [@container_nextclaw-chat-input-bar_(max-width:440px)]:!min-w-8 [@container_nextclaw-chat-input-bar_(max-width:440px)]:!px-0 ${TRIGGER_WIDTH_BY_KEY[item.key] ?? ""}`,
|
|
814
|
+
children: [/* @__PURE__ */ jsx(ToolbarSelectTriggerContent, { item }), /* @__PURE__ */ jsx(ChevronDown, { className: "ml-1 h-3.5 w-3.5 shrink-0 text-gray-400 [@container_nextclaw-chat-input-bar_(max-width:440px)]:hidden" })]
|
|
815
|
+
})
|
|
816
|
+
}), /* @__PURE__ */ jsxs(PopoverContent, {
|
|
817
|
+
className: `flex flex-col overflow-hidden p-2 ${CONTENT_WIDTH_BY_KEY[item.key] ?? ""}`,
|
|
818
|
+
style: { maxHeight: TOOLBAR_POPOVER_MAX_HEIGHT },
|
|
819
|
+
children: [
|
|
820
|
+
/* @__PURE__ */ jsxs("div", {
|
|
821
|
+
className: "relative mb-2 shrink-0",
|
|
822
|
+
children: [/* @__PURE__ */ jsx(Search, { className: "pointer-events-none absolute left-2.5 top-1/2 h-3.5 w-3.5 -translate-y-1/2 text-gray-400" }), /* @__PURE__ */ jsx(Input, {
|
|
823
|
+
value: query,
|
|
824
|
+
onChange: (event) => setQuery(event.currentTarget.value),
|
|
825
|
+
placeholder: item.search?.placeholder ?? item.placeholder,
|
|
826
|
+
className: "h-8 rounded-lg pl-8 text-xs"
|
|
827
|
+
})]
|
|
828
|
+
}),
|
|
829
|
+
!hasOptions ? item.loading ? /* @__PURE__ */ jsxs("div", {
|
|
830
|
+
className: "space-y-2 px-2 py-1",
|
|
831
|
+
children: [
|
|
832
|
+
/* @__PURE__ */ jsx("div", { className: "h-3 w-36 animate-pulse rounded bg-gray-200" }),
|
|
833
|
+
/* @__PURE__ */ jsx("div", { className: "h-3 w-28 animate-pulse rounded bg-gray-200" }),
|
|
834
|
+
/* @__PURE__ */ jsx("div", { className: "h-3 w-32 animate-pulse rounded bg-gray-200" })
|
|
835
|
+
]
|
|
836
|
+
}) : item.emptyLabel ? /* @__PURE__ */ jsx("div", {
|
|
837
|
+
className: "px-2 py-1 text-xs text-gray-500",
|
|
838
|
+
children: item.emptyLabel
|
|
839
|
+
}) : null : null,
|
|
840
|
+
hasOptions && !hasFilteredOptions ? /* @__PURE__ */ jsx("div", {
|
|
841
|
+
className: "px-2 py-1 text-xs text-gray-500",
|
|
842
|
+
children: item.search?.emptyLabel ?? item.emptyLabel
|
|
843
|
+
}) : null,
|
|
844
|
+
/* @__PURE__ */ jsx("div", {
|
|
845
|
+
className: "min-h-0 flex-1 overflow-y-auto overscroll-contain",
|
|
846
|
+
children: filteredGroups.map((group, groupIndex) => /* @__PURE__ */ jsxs("div", {
|
|
847
|
+
className: groupIndex > 0 ? "border-t border-gray-100 pt-1" : void 0,
|
|
848
|
+
children: [group.label ? /* @__PURE__ */ jsx("div", {
|
|
849
|
+
className: "px-2 py-1 text-[11px] font-semibold uppercase tracking-[0.08em] text-gray-500",
|
|
850
|
+
children: group.label
|
|
851
|
+
}) : null, group.options.map((option) => {
|
|
852
|
+
const isSelected = item.value === option.value;
|
|
853
|
+
const isActive = activeValues.has(option.value);
|
|
854
|
+
const actionLabel = isActive ? action?.activeLabel : action?.inactiveLabel;
|
|
855
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
856
|
+
className: "group flex items-center gap-1 rounded-md hover:bg-gray-100",
|
|
857
|
+
children: [/* @__PURE__ */ jsxs("button", {
|
|
858
|
+
type: "button",
|
|
859
|
+
className: "flex min-w-0 flex-1 items-center gap-2 rounded-md px-2 py-2 text-left",
|
|
860
|
+
onClick: () => {
|
|
861
|
+
item.onValueChange(option.value);
|
|
862
|
+
setOpen(false);
|
|
863
|
+
setQuery("");
|
|
864
|
+
},
|
|
865
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
866
|
+
className: "min-w-0 flex-1",
|
|
867
|
+
children: /* @__PURE__ */ jsx(ToolbarSelectOptionContent, { option })
|
|
868
|
+
}), isSelected ? /* @__PURE__ */ jsx(Check, { className: "h-4 w-4 shrink-0 text-primary" }) : null]
|
|
869
|
+
}), action && actionLabel ? /* @__PURE__ */ jsx(TooltipProvider, { children: /* @__PURE__ */ jsxs(Tooltip, { children: [/* @__PURE__ */ jsx(TooltipTrigger, {
|
|
870
|
+
asChild: true,
|
|
871
|
+
children: /* @__PURE__ */ jsx("button", {
|
|
872
|
+
type: "button",
|
|
873
|
+
"aria-label": actionLabel,
|
|
874
|
+
"aria-pressed": isActive,
|
|
875
|
+
className: "mr-1 inline-flex h-7 w-7 shrink-0 items-center justify-center rounded-md text-gray-400 transition-colors hover:bg-white hover:text-amber-500 focus:outline-none focus:ring-1 focus:ring-primary/40",
|
|
876
|
+
onClick: (event) => {
|
|
877
|
+
event.stopPropagation();
|
|
878
|
+
action.onToggle(option.value, !isActive);
|
|
879
|
+
},
|
|
880
|
+
children: /* @__PURE__ */ jsx(Star, { className: `h-3.5 w-3.5 ${isActive ? "fill-amber-400 text-amber-500" : ""}` })
|
|
881
|
+
})
|
|
882
|
+
}), /* @__PURE__ */ jsx(TooltipContent, {
|
|
883
|
+
side: "left",
|
|
884
|
+
children: /* @__PURE__ */ jsx("p", {
|
|
885
|
+
className: "text-xs",
|
|
886
|
+
children: actionLabel
|
|
887
|
+
})
|
|
888
|
+
})] }) }) : null]
|
|
889
|
+
}, option.value);
|
|
890
|
+
})]
|
|
891
|
+
}, group.key))
|
|
892
|
+
})
|
|
893
|
+
]
|
|
894
|
+
})]
|
|
895
|
+
});
|
|
896
|
+
}
|
|
897
|
+
function ToolbarSelect({ item }) {
|
|
898
|
+
if (item.search) return /* @__PURE__ */ jsx(ToolbarSearchableSelect, { item });
|
|
899
|
+
const { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectSeparator, SelectTrigger, SelectValue } = ChatUiPrimitives;
|
|
900
|
+
const groups = buildSelectGroups(item);
|
|
901
|
+
const hasOptions = groups.some((group) => group.options.length > 0);
|
|
718
902
|
return /* @__PURE__ */ jsxs(Select, {
|
|
719
903
|
value: item.value,
|
|
720
904
|
onValueChange: item.onValueChange,
|
|
@@ -723,22 +907,10 @@ function ToolbarSelect({ item }) {
|
|
|
723
907
|
"aria-label": item.selectedLabel ? `${item.placeholder}: ${item.selectedLabel}` : item.placeholder,
|
|
724
908
|
title: item.selectedLabel,
|
|
725
909
|
className: `nextclaw-chat-toolbar-select-trigger h-8 w-auto rounded-lg border-0 bg-transparent px-2 text-xs font-medium text-gray-600 shadow-none hover:bg-gray-100 focus:ring-0 sm:px-3 [@container_nextclaw-chat-input-bar_(max-width:440px)]:!basis-8 [@container_nextclaw-chat-input-bar_(max-width:440px)]:!justify-center [@container_nextclaw-chat-input-bar_(max-width:440px)]:!max-w-8 [@container_nextclaw-chat-input-bar_(max-width:440px)]:!min-w-8 [@container_nextclaw-chat-input-bar_(max-width:440px)]:!px-0 ${TRIGGER_WIDTH_BY_KEY[item.key] ?? ""}`,
|
|
726
|
-
children: item.selectedLabel ? /* @__PURE__ */
|
|
727
|
-
className: "flex min-w-0 items-center gap-2 text-left",
|
|
728
|
-
children: [
|
|
729
|
-
/* @__PURE__ */ jsx(ToolbarIcon, { icon: item.icon }),
|
|
730
|
-
/* @__PURE__ */ jsx("span", {
|
|
731
|
-
className: "nextclaw-chat-toolbar-mobile-label truncate text-xs font-semibold text-gray-700 sm:hidden [@container_nextclaw-chat-input-bar_(max-width:440px)]:hidden",
|
|
732
|
-
children: mobileSelectedLabel
|
|
733
|
-
}),
|
|
734
|
-
/* @__PURE__ */ jsx("span", {
|
|
735
|
-
className: "nextclaw-chat-toolbar-label hidden truncate text-xs font-semibold text-gray-700 sm:inline [@container_nextclaw-chat-input-bar_(max-width:440px)]:hidden",
|
|
736
|
-
children: item.selectedLabel
|
|
737
|
-
})
|
|
738
|
-
]
|
|
739
|
-
}) : item.loading ? /* @__PURE__ */ jsx("div", { className: "h-3 w-24 animate-pulse rounded bg-gray-200" }) : /* @__PURE__ */ jsx(SelectValue, { placeholder: item.placeholder })
|
|
910
|
+
children: item.selectedLabel || item.loading ? /* @__PURE__ */ jsx(ToolbarSelectTriggerContent, { item }) : /* @__PURE__ */ jsx(SelectValue, { placeholder: item.placeholder })
|
|
740
911
|
}), /* @__PURE__ */ jsxs(SelectContent, {
|
|
741
912
|
className: CONTENT_WIDTH_BY_KEY[item.key] ?? "",
|
|
913
|
+
style: { maxHeight: TOOLBAR_SELECT_MAX_HEIGHT },
|
|
742
914
|
children: [!hasOptions ? item.loading ? /* @__PURE__ */ jsxs("div", {
|
|
743
915
|
className: "space-y-2 px-3 py-2",
|
|
744
916
|
children: [
|
|
@@ -752,19 +924,7 @@ function ToolbarSelect({ item }) {
|
|
|
752
924
|
}) : null : null, groups.map((group, groupIndex) => /* @__PURE__ */ jsxs("div", { children: [groupIndex > 0 ? /* @__PURE__ */ jsx(SelectSeparator, {}) : null, /* @__PURE__ */ jsxs(SelectGroup, { children: [group.label ? /* @__PURE__ */ jsx(SelectLabel, { children: group.label }) : null, group.options.map((option) => /* @__PURE__ */ jsx(SelectItem, {
|
|
753
925
|
value: option.value,
|
|
754
926
|
className: "py-2",
|
|
755
|
-
children:
|
|
756
|
-
className: "flex min-w-0 flex-col gap-0.5",
|
|
757
|
-
children: [/* @__PURE__ */ jsx("span", {
|
|
758
|
-
className: "truncate text-xs font-semibold text-gray-800",
|
|
759
|
-
children: option.label
|
|
760
|
-
}), /* @__PURE__ */ jsx("span", {
|
|
761
|
-
className: "truncate text-[11px] text-gray-500",
|
|
762
|
-
children: option.description
|
|
763
|
-
})]
|
|
764
|
-
}) : /* @__PURE__ */ jsx("span", {
|
|
765
|
-
className: "truncate text-xs font-semibold text-gray-800",
|
|
766
|
-
children: option.label
|
|
767
|
-
})
|
|
927
|
+
children: /* @__PURE__ */ jsx(ToolbarSelectOptionContent, { option })
|
|
768
928
|
}, option.value))] })] }, group.key))]
|
|
769
929
|
})]
|
|
770
930
|
});
|
|
@@ -991,10 +1151,10 @@ function buildTokenClassName(tokenKind) {
|
|
|
991
1151
|
"transition"
|
|
992
1152
|
].join(" ");
|
|
993
1153
|
}
|
|
994
|
-
function ChatComposerTokenChip(
|
|
1154
|
+
function ChatComposerTokenChip({ label, tokenKind }) {
|
|
995
1155
|
return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("span", {
|
|
996
|
-
className:
|
|
997
|
-
children:
|
|
1156
|
+
className: tokenKind === "file" ? "inline-flex h-4.5 w-4.5 shrink-0 items-center justify-center rounded-md bg-white text-slate-500 ring-1 ring-black/5" : "inline-flex h-3.5 w-3.5 shrink-0 items-center justify-center text-primary/70",
|
|
1157
|
+
children: tokenKind === "file" ? /* @__PURE__ */ jsxs("svg", {
|
|
998
1158
|
viewBox: "0 0 16 16",
|
|
999
1159
|
fill: "none",
|
|
1000
1160
|
stroke: "currentColor",
|
|
@@ -1025,8 +1185,8 @@ function ChatComposerTokenChip(props) {
|
|
|
1025
1185
|
]
|
|
1026
1186
|
})
|
|
1027
1187
|
}), /* @__PURE__ */ jsx("span", {
|
|
1028
|
-
className:
|
|
1029
|
-
children:
|
|
1188
|
+
className: tokenKind === "file" ? "min-w-0 flex-1 truncate text-[12px] font-medium text-slate-700" : "truncate",
|
|
1189
|
+
children: label
|
|
1030
1190
|
})] });
|
|
1031
1191
|
}
|
|
1032
1192
|
var ChatComposerTokenNode = class ChatComposerTokenNode extends DecoratorNode {
|
|
@@ -1514,8 +1674,8 @@ var LexicalComposerHandleOwner = class {
|
|
|
1514
1674
|
this.focusComposer = () => {
|
|
1515
1675
|
this.params.focusComposer();
|
|
1516
1676
|
};
|
|
1517
|
-
this.focusComposerAtEnd = () => {
|
|
1518
|
-
this.params.focusComposerAtEnd();
|
|
1677
|
+
this.focusComposerAtEnd = (nodes) => {
|
|
1678
|
+
this.params.focusComposerAtEnd(nodes);
|
|
1519
1679
|
};
|
|
1520
1680
|
this.syncSelectedSkills = (nextKeys, options) => {
|
|
1521
1681
|
this.params.publishSnapshot(syncSelectedSkillsIntoChatComposer({
|
|
@@ -1703,7 +1863,10 @@ function ChatComposerBindingsPlugin({ disabled, editorRef, editorSignatureRef, i
|
|
|
1703
1863
|
}
|
|
1704
1864
|
//#endregion
|
|
1705
1865
|
//#region src/components/chat/ui/chat-input-bar/lexical/chat-input-bar-tokenized-composer.tsx
|
|
1706
|
-
|
|
1866
|
+
function getChatComposerDocumentLength(nodes) {
|
|
1867
|
+
return nodes.reduce((cursor, node) => cursor + (node.type === "text" ? node.text.length : 1), 0);
|
|
1868
|
+
}
|
|
1869
|
+
const ChatInputBarTokenizedComposer = forwardRef(function ChatInputBarTokenizedComposer({ actions, activeSlashIndex, disabled, nodes, onFilesAdd, onNodesChange, onSlashActiveIndexChange, onSlashItemSelect, onSlashOpenChange, onSlashQueryChange, onSlashTriggerChange, placeholder, slashItems }, ref) {
|
|
1707
1870
|
const editorRef = useRef(null);
|
|
1708
1871
|
const selectionRef = useRef(null);
|
|
1709
1872
|
const pendingSelectionRef = useRef(null);
|
|
@@ -1712,23 +1875,27 @@ const ChatInputBarTokenizedComposer = forwardRef(function ChatInputBarTokenizedC
|
|
|
1712
1875
|
const isApplyingExternalUpdateRef = useRef(false);
|
|
1713
1876
|
const editorSignatureRef = useRef("");
|
|
1714
1877
|
const lastPublishedSignatureRef = useRef("");
|
|
1715
|
-
const syncSlashState = (nodes, selection) => {
|
|
1878
|
+
const syncSlashState = useCallback((nodes, selection) => {
|
|
1716
1879
|
const trigger = resolveChatComposerSlashTrigger(nodes, selection);
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
}
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1880
|
+
onSlashTriggerChange?.(trigger);
|
|
1881
|
+
onSlashQueryChange?.(trigger?.query ?? null);
|
|
1882
|
+
onSlashOpenChange(trigger !== null);
|
|
1883
|
+
}, [
|
|
1884
|
+
onSlashOpenChange,
|
|
1885
|
+
onSlashQueryChange,
|
|
1886
|
+
onSlashTriggerChange
|
|
1887
|
+
]);
|
|
1888
|
+
const readCurrentNodes = useCallback(() => {
|
|
1889
|
+
return nodes;
|
|
1890
|
+
}, [nodes]);
|
|
1891
|
+
const readCurrentSelection = useCallback(() => {
|
|
1725
1892
|
if (selectionRef.current) return selectionRef.current;
|
|
1726
1893
|
if (!editorRef.current) return null;
|
|
1727
1894
|
const snapshot = readChatComposerSnapshotFromEditorState(editorRef.current.getEditorState());
|
|
1728
1895
|
selectionRef.current = snapshot.selection;
|
|
1729
1896
|
return snapshot.selection;
|
|
1730
|
-
};
|
|
1731
|
-
const publishSnapshot = (snapshot, options) => {
|
|
1897
|
+
}, []);
|
|
1898
|
+
const publishSnapshot = useCallback((snapshot, options) => {
|
|
1732
1899
|
selectionRef.current = snapshot.selection;
|
|
1733
1900
|
pendingSelectionRef.current = snapshot.selection;
|
|
1734
1901
|
if (options?.focusAfterSync) shouldFocusAfterSyncRef.current = true;
|
|
@@ -1736,46 +1903,64 @@ const ChatInputBarTokenizedComposer = forwardRef(function ChatInputBarTokenizedC
|
|
|
1736
1903
|
syncSlashState(snapshot.nodes, snapshot.selection);
|
|
1737
1904
|
if (options?.forcePublish || signature !== lastPublishedSignatureRef.current) {
|
|
1738
1905
|
lastPublishedSignatureRef.current = signature;
|
|
1739
|
-
|
|
1906
|
+
onNodesChange(snapshot.nodes);
|
|
1740
1907
|
}
|
|
1741
|
-
};
|
|
1742
|
-
const focusComposer = () => {
|
|
1908
|
+
}, [onNodesChange, syncSlashState]);
|
|
1909
|
+
const focusComposer = useCallback(() => {
|
|
1743
1910
|
const editor = editorRef.current;
|
|
1744
1911
|
if (!editor) return;
|
|
1745
1912
|
editor.getRootElement()?.focus({ preventScroll: true });
|
|
1746
1913
|
const targetSelection = selectionRef.current;
|
|
1747
1914
|
if (targetSelection) syncLexicalSelectionFromChatComposerSelection(editor, targetSelection);
|
|
1748
1915
|
editor.focus();
|
|
1749
|
-
};
|
|
1750
|
-
const focusComposerAtEnd = () => {
|
|
1916
|
+
}, []);
|
|
1917
|
+
const focusComposerAtEnd = useCallback((nodes) => {
|
|
1751
1918
|
const editor = editorRef.current;
|
|
1752
1919
|
if (!editor) return;
|
|
1753
|
-
const end = readChatComposerSnapshotFromEditorState(editor.getEditorState()).nodes
|
|
1920
|
+
const end = getChatComposerDocumentLength(nodes ?? readChatComposerSnapshotFromEditorState(editor.getEditorState()).nodes);
|
|
1754
1921
|
const targetSelection = {
|
|
1755
1922
|
start: end,
|
|
1756
1923
|
end
|
|
1757
1924
|
};
|
|
1758
1925
|
selectionRef.current = targetSelection;
|
|
1926
|
+
pendingSelectionRef.current = targetSelection;
|
|
1759
1927
|
editor.getRootElement()?.focus({ preventScroll: true });
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1928
|
+
if (nodes) {
|
|
1929
|
+
isApplyingExternalUpdateRef.current = true;
|
|
1930
|
+
const signature = getChatComposerNodesSignature(nodes);
|
|
1931
|
+
syncLexicalEditorFromChatComposerState(editor, nodes, targetSelection);
|
|
1932
|
+
editorSignatureRef.current = signature;
|
|
1933
|
+
lastPublishedSignatureRef.current = signature;
|
|
1934
|
+
requestAnimationFrame(() => {
|
|
1935
|
+
isApplyingExternalUpdateRef.current = false;
|
|
1936
|
+
});
|
|
1937
|
+
} else syncLexicalSelectionFromChatComposerSelection(editor, targetSelection);
|
|
1938
|
+
editor.focus(() => {
|
|
1939
|
+
syncLexicalSelectionFromChatComposerSelection(editor, targetSelection);
|
|
1940
|
+
});
|
|
1941
|
+
}, []);
|
|
1942
|
+
const readComposerSnapshot = useCallback(() => ({
|
|
1764
1943
|
nodes: readCurrentNodes(),
|
|
1765
1944
|
selection: readCurrentSelection()
|
|
1766
|
-
});
|
|
1945
|
+
}), [readCurrentNodes, readCurrentSelection]);
|
|
1767
1946
|
useImperativeHandle(ref, () => createLexicalComposerHandle({
|
|
1768
1947
|
focusComposer,
|
|
1769
1948
|
focusComposerAtEnd,
|
|
1770
|
-
onSlashItemSelect
|
|
1949
|
+
onSlashItemSelect,
|
|
1771
1950
|
optionsReader: readComposerSnapshot,
|
|
1772
1951
|
publishSnapshot
|
|
1773
|
-
}), [
|
|
1952
|
+
}), [
|
|
1953
|
+
focusComposer,
|
|
1954
|
+
focusComposerAtEnd,
|
|
1955
|
+
onSlashItemSelect,
|
|
1956
|
+
publishSnapshot,
|
|
1957
|
+
readComposerSnapshot
|
|
1958
|
+
]);
|
|
1774
1959
|
return /* @__PURE__ */ jsxs(LexicalComposer, {
|
|
1775
1960
|
initialConfig: useMemo(() => ({
|
|
1776
|
-
editable: !
|
|
1961
|
+
editable: !disabled,
|
|
1777
1962
|
editorState: () => {
|
|
1778
|
-
writeChatComposerStateToLexicalRoot(
|
|
1963
|
+
writeChatComposerStateToLexicalRoot(nodes, null);
|
|
1779
1964
|
},
|
|
1780
1965
|
namespace: "NextClawChatComposerLexical",
|
|
1781
1966
|
nodes: [ChatComposerTokenNode],
|
|
@@ -1783,7 +1968,7 @@ const ChatInputBarTokenizedComposer = forwardRef(function ChatInputBarTokenizedC
|
|
|
1783
1968
|
throw error;
|
|
1784
1969
|
},
|
|
1785
1970
|
theme: {}
|
|
1786
|
-
}), [
|
|
1971
|
+
}), [disabled, nodes]),
|
|
1787
1972
|
children: [
|
|
1788
1973
|
/* @__PURE__ */ jsx("div", {
|
|
1789
1974
|
className: "px-3 py-2 sm:px-4 sm:py-2.5",
|
|
@@ -1794,7 +1979,7 @@ const ChatInputBarTokenizedComposer = forwardRef(function ChatInputBarTokenizedC
|
|
|
1794
1979
|
className: "min-h-7 max-h-[188px] w-full overflow-y-auto whitespace-pre-wrap break-words bg-transparent py-0.5 text-sm leading-6 text-gray-800 outline-none",
|
|
1795
1980
|
onBeforeInput: (event) => {
|
|
1796
1981
|
handleLexicalComposerBeforeInput({
|
|
1797
|
-
disabled
|
|
1982
|
+
disabled,
|
|
1798
1983
|
event,
|
|
1799
1984
|
isComposing: isComposingRef.current,
|
|
1800
1985
|
publishSnapshot,
|
|
@@ -1819,15 +2004,15 @@ const ChatInputBarTokenizedComposer = forwardRef(function ChatInputBarTokenizedC
|
|
|
1819
2004
|
},
|
|
1820
2005
|
onPaste: (event) => {
|
|
1821
2006
|
const files = Array.from(event.clipboardData.files ?? []);
|
|
1822
|
-
if (files.length > 0 &&
|
|
2007
|
+
if (files.length > 0 && onFilesAdd) {
|
|
1823
2008
|
event.preventDefault();
|
|
1824
|
-
|
|
2009
|
+
onFilesAdd(files);
|
|
1825
2010
|
}
|
|
1826
2011
|
}
|
|
1827
2012
|
}),
|
|
1828
2013
|
placeholder: /* @__PURE__ */ jsx("div", {
|
|
1829
2014
|
className: "pointer-events-none absolute left-3 top-2 select-none text-sm leading-6 text-gray-400 sm:left-4 sm:top-2.5",
|
|
1830
|
-
children:
|
|
2015
|
+
children: placeholder
|
|
1831
2016
|
}),
|
|
1832
2017
|
ErrorBoundary: LexicalErrorBoundary
|
|
1833
2018
|
})
|
|
@@ -1835,16 +2020,16 @@ const ChatInputBarTokenizedComposer = forwardRef(function ChatInputBarTokenizedC
|
|
|
1835
2020
|
}),
|
|
1836
2021
|
/* @__PURE__ */ jsx(EditorRefPlugin, { editorRef }),
|
|
1837
2022
|
/* @__PURE__ */ jsx(ChatComposerBindingsPlugin, {
|
|
1838
|
-
disabled
|
|
2023
|
+
disabled,
|
|
1839
2024
|
editorRef,
|
|
1840
2025
|
editorSignatureRef,
|
|
1841
2026
|
isApplyingExternalUpdateRef,
|
|
1842
2027
|
isComposingRef,
|
|
1843
2028
|
lastPublishedSignatureRef,
|
|
1844
|
-
nodes
|
|
2029
|
+
nodes,
|
|
1845
2030
|
onBlur: () => {
|
|
1846
|
-
|
|
1847
|
-
|
|
2031
|
+
onSlashQueryChange?.(null);
|
|
2032
|
+
onSlashOpenChange(false);
|
|
1848
2033
|
},
|
|
1849
2034
|
onKeyDown: (event) => {
|
|
1850
2035
|
const editor = editorRef.current;
|
|
@@ -1852,19 +2037,19 @@ const ChatInputBarTokenizedComposer = forwardRef(function ChatInputBarTokenizedC
|
|
|
1852
2037
|
const snapshot = readChatComposerSnapshotFromEditorState(editor.getEditorState());
|
|
1853
2038
|
selectionRef.current = snapshot.selection;
|
|
1854
2039
|
return handleLexicalComposerKeyboardCommand({
|
|
1855
|
-
actions
|
|
1856
|
-
activeSlashIndex
|
|
2040
|
+
actions,
|
|
2041
|
+
activeSlashIndex,
|
|
1857
2042
|
nativeEvent: event,
|
|
1858
|
-
onSlashActiveIndexChange
|
|
1859
|
-
onSlashItemSelect
|
|
1860
|
-
onSlashOpenChange
|
|
1861
|
-
onSlashQueryChange
|
|
2043
|
+
onSlashActiveIndexChange,
|
|
2044
|
+
onSlashItemSelect,
|
|
2045
|
+
onSlashOpenChange,
|
|
2046
|
+
onSlashQueryChange,
|
|
1862
2047
|
publishSnapshot,
|
|
1863
|
-
slashItems
|
|
2048
|
+
slashItems,
|
|
1864
2049
|
snapshot
|
|
1865
2050
|
});
|
|
1866
2051
|
},
|
|
1867
|
-
onNodesChange
|
|
2052
|
+
onNodesChange,
|
|
1868
2053
|
pendingSelectionRef,
|
|
1869
2054
|
selectionRef,
|
|
1870
2055
|
shouldFocusAfterSyncRef,
|
|
@@ -1898,45 +2083,37 @@ function InputBarHint({ hint }) {
|
|
|
1898
2083
|
})
|
|
1899
2084
|
});
|
|
1900
2085
|
}
|
|
1901
|
-
const ChatInputBar = forwardRef(function ChatInputBar(
|
|
2086
|
+
const ChatInputBar = forwardRef(function ChatInputBar({ composer, hint, slashMenu, surface, toolbar: toolbarProps }, ref) {
|
|
1902
2087
|
const composerRef = useRef(null);
|
|
1903
2088
|
const isSlashMenuInteractionRef = useRef(false);
|
|
1904
2089
|
const [activeSlashIndex, setActiveSlashIndex] = useState(0);
|
|
1905
2090
|
const [activeSlashTriggerStart, setActiveSlashTriggerStart] = useState(null);
|
|
1906
2091
|
const [dismissedSlashTriggerStart, setDismissedSlashTriggerStart] = useState(null);
|
|
1907
2092
|
const isSlashPanelOpen = activeSlashTriggerStart !== null && dismissedSlashTriggerStart !== activeSlashTriggerStart;
|
|
1908
|
-
const
|
|
2093
|
+
const activeSlashIndexInRange = slashMenu.items.length === 0 ? 0 : Math.min(activeSlashIndex, slashMenu.items.length - 1);
|
|
2094
|
+
const activeSlashItem = slashMenu.items[activeSlashIndexInRange] ?? null;
|
|
1909
2095
|
const dismissSlashTrigger = () => activeSlashTriggerStart !== null && !isSlashMenuInteractionRef.current ? setDismissedSlashTriggerStart(activeSlashTriggerStart) : void 0;
|
|
1910
|
-
useEffect(() => {
|
|
1911
|
-
setActiveSlashIndex((current) => {
|
|
1912
|
-
if (props.slashMenu.items.length === 0) return 0;
|
|
1913
|
-
return Math.min(current, props.slashMenu.items.length - 1);
|
|
1914
|
-
});
|
|
1915
|
-
}, [props.slashMenu.items.length]);
|
|
1916
|
-
useEffect(() => {
|
|
1917
|
-
if (activeSlashTriggerStart === null && dismissedSlashTriggerStart !== null) setDismissedSlashTriggerStart(null);
|
|
1918
|
-
}, [activeSlashTriggerStart, dismissedSlashTriggerStart]);
|
|
1919
2096
|
const toolbar = useMemo(() => {
|
|
1920
|
-
if (!
|
|
2097
|
+
if (!toolbarProps.skillPicker) return toolbarProps;
|
|
1921
2098
|
return {
|
|
1922
|
-
...
|
|
2099
|
+
...toolbarProps,
|
|
1923
2100
|
skillPicker: {
|
|
1924
|
-
...
|
|
2101
|
+
...toolbarProps.skillPicker,
|
|
1925
2102
|
onSelectedKeysChange: (nextKeys) => {
|
|
1926
|
-
composerRef.current?.syncSelectedSkills(nextKeys,
|
|
1927
|
-
|
|
2103
|
+
composerRef.current?.syncSelectedSkills(nextKeys, toolbarProps.skillPicker?.options ?? []);
|
|
2104
|
+
toolbarProps.skillPicker?.onSelectedKeysChange(nextKeys);
|
|
1928
2105
|
}
|
|
1929
2106
|
}
|
|
1930
2107
|
};
|
|
1931
|
-
}, [
|
|
2108
|
+
}, [toolbarProps]);
|
|
1932
2109
|
useImperativeHandle(ref, () => ({
|
|
1933
2110
|
insertFileToken: (tokenKey, label) => composerRef.current?.insertFileToken(tokenKey, label),
|
|
1934
2111
|
insertFileTokens: (tokens) => composerRef.current?.insertFileTokens(tokens),
|
|
1935
2112
|
focusComposer: () => composerRef.current?.focusComposer(),
|
|
1936
|
-
focusComposerAtEnd: () => composerRef.current?.focusComposerAtEnd()
|
|
2113
|
+
focusComposerAtEnd: (nodes) => composerRef.current?.focusComposerAtEnd(nodes)
|
|
1937
2114
|
}), []);
|
|
1938
2115
|
return /* @__PURE__ */ jsx("div", {
|
|
1939
|
-
className: "border-t border-gray-200/80 bg-white px-3 py-3 sm:px-4 sm:py-4",
|
|
2116
|
+
className: surface === "embedded" ? "bg-transparent px-0 py-0" : "border-t border-gray-200/80 bg-white px-3 py-3 sm:px-4 sm:py-4",
|
|
1940
2117
|
children: /* @__PURE__ */ jsx("div", {
|
|
1941
2118
|
className: "nextclaw-chat-input-bar-shell mx-auto w-full max-w-[min(1120px,100%)] [container:nextclaw-chat-input-bar/inline-size]",
|
|
1942
2119
|
children: /* @__PURE__ */ jsxs("div", {
|
|
@@ -1946,22 +2123,24 @@ const ChatInputBar = forwardRef(function ChatInputBar(props, ref) {
|
|
|
1946
2123
|
className: "relative",
|
|
1947
2124
|
children: [/* @__PURE__ */ jsx(ChatInputBarTokenizedComposer, {
|
|
1948
2125
|
ref: composerRef,
|
|
1949
|
-
nodes:
|
|
1950
|
-
placeholder:
|
|
1951
|
-
disabled:
|
|
1952
|
-
slashItems:
|
|
1953
|
-
onSlashItemSelect:
|
|
1954
|
-
actions:
|
|
1955
|
-
activeSlashIndex,
|
|
1956
|
-
onNodesChange:
|
|
1957
|
-
onFilesAdd:
|
|
2126
|
+
nodes: composer.nodes,
|
|
2127
|
+
placeholder: composer.placeholder,
|
|
2128
|
+
disabled: composer.disabled,
|
|
2129
|
+
slashItems: slashMenu.items,
|
|
2130
|
+
onSlashItemSelect: slashMenu.onSelectItem,
|
|
2131
|
+
actions: toolbarProps.actions,
|
|
2132
|
+
activeSlashIndex: activeSlashIndexInRange,
|
|
2133
|
+
onNodesChange: composer.onNodesChange,
|
|
2134
|
+
onFilesAdd: composer.onFilesAdd,
|
|
1958
2135
|
onSlashQueryChange: (query) => {
|
|
1959
2136
|
if (query === null && isSlashMenuInteractionRef.current) return;
|
|
1960
2137
|
if (query !== null) setActiveSlashIndex(0);
|
|
1961
|
-
|
|
2138
|
+
composer.onSlashQueryChange?.(query);
|
|
1962
2139
|
},
|
|
1963
2140
|
onSlashTriggerChange: (trigger) => {
|
|
1964
|
-
|
|
2141
|
+
const nextTriggerStart = trigger?.start ?? null;
|
|
2142
|
+
setActiveSlashTriggerStart(nextTriggerStart);
|
|
2143
|
+
if (nextTriggerStart === null) setDismissedSlashTriggerStart(null);
|
|
1965
2144
|
},
|
|
1966
2145
|
onSlashOpenChange: (open) => {
|
|
1967
2146
|
if (!open) dismissSlashTrigger();
|
|
@@ -1969,11 +2148,11 @@ const ChatInputBar = forwardRef(function ChatInputBar(props, ref) {
|
|
|
1969
2148
|
onSlashActiveIndexChange: setActiveSlashIndex
|
|
1970
2149
|
}), /* @__PURE__ */ jsx(ChatSlashMenu, {
|
|
1971
2150
|
isOpen: isSlashPanelOpen,
|
|
1972
|
-
isLoading:
|
|
1973
|
-
items:
|
|
1974
|
-
activeIndex:
|
|
2151
|
+
isLoading: slashMenu.isLoading,
|
|
2152
|
+
items: slashMenu.items,
|
|
2153
|
+
activeIndex: activeSlashIndexInRange,
|
|
1975
2154
|
activeItem: activeSlashItem,
|
|
1976
|
-
texts:
|
|
2155
|
+
texts: slashMenu.texts,
|
|
1977
2156
|
onSelectItem: (item) => {
|
|
1978
2157
|
setDismissedSlashTriggerStart(null);
|
|
1979
2158
|
composerRef.current?.insertSlashItem(item);
|
|
@@ -1990,7 +2169,7 @@ const ChatInputBar = forwardRef(function ChatInputBar(props, ref) {
|
|
|
1990
2169
|
onSetActiveIndex: setActiveSlashIndex
|
|
1991
2170
|
})]
|
|
1992
2171
|
}),
|
|
1993
|
-
/* @__PURE__ */ jsx(InputBarHint, { hint
|
|
2172
|
+
/* @__PURE__ */ jsx(InputBarHint, { hint }),
|
|
1994
2173
|
/* @__PURE__ */ jsx(ChatInputBarToolbar, { ...toolbar })
|
|
1995
2174
|
]
|
|
1996
2175
|
})
|
|
@@ -2021,7 +2200,7 @@ function ChatMessageAvatar({ role }) {
|
|
|
2021
2200
|
});
|
|
2022
2201
|
}
|
|
2023
2202
|
//#endregion
|
|
2024
|
-
//#region src/components/chat/utils/copy-text.ts
|
|
2203
|
+
//#region src/components/chat/utils/copy-text.utils.ts
|
|
2025
2204
|
function canUseClipboardApi() {
|
|
2026
2205
|
return typeof navigator !== "undefined" && typeof navigator.clipboard?.writeText === "function";
|
|
2027
2206
|
}
|
|
@@ -2032,48 +2211,75 @@ function restoreSelection(ranges) {
|
|
|
2032
2211
|
selection.removeAllRanges();
|
|
2033
2212
|
ranges.forEach((range) => selection.addRange(range));
|
|
2034
2213
|
}
|
|
2035
|
-
function
|
|
2036
|
-
if (typeof document === "undefined" || !document.body) return false;
|
|
2214
|
+
function snapshotCopyContext() {
|
|
2037
2215
|
const activeElement = document.activeElement instanceof HTMLElement ? document.activeElement : null;
|
|
2038
2216
|
const activeInput = activeElement instanceof HTMLInputElement || activeElement instanceof HTMLTextAreaElement ? activeElement : null;
|
|
2039
|
-
const
|
|
2217
|
+
const activeInputSelection = activeInput ? {
|
|
2218
|
+
input: activeInput,
|
|
2040
2219
|
start: activeInput.selectionStart,
|
|
2041
2220
|
end: activeInput.selectionEnd
|
|
2042
2221
|
} : null;
|
|
2043
2222
|
const selection = document.getSelection();
|
|
2044
|
-
|
|
2223
|
+
return {
|
|
2224
|
+
activeElement,
|
|
2225
|
+
activeInputSelection,
|
|
2226
|
+
ranges: selection ? Array.from({ length: selection.rangeCount }, (_, index) => selection.getRangeAt(index).cloneRange()) : []
|
|
2227
|
+
};
|
|
2228
|
+
}
|
|
2229
|
+
function createCopyTextarea(text) {
|
|
2045
2230
|
const textarea = document.createElement("textarea");
|
|
2046
2231
|
textarea.value = text;
|
|
2047
2232
|
textarea.setAttribute("readonly", "");
|
|
2048
2233
|
textarea.setAttribute("aria-hidden", "true");
|
|
2049
|
-
textarea.style
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2234
|
+
Object.assign(textarea.style, {
|
|
2235
|
+
fontSize: "12pt",
|
|
2236
|
+
left: "-9999px",
|
|
2237
|
+
opacity: "0",
|
|
2238
|
+
pointerEvents: "none",
|
|
2239
|
+
position: "fixed",
|
|
2240
|
+
top: "0"
|
|
2241
|
+
});
|
|
2242
|
+
return textarea;
|
|
2243
|
+
}
|
|
2244
|
+
function focusWithoutScroll(element) {
|
|
2056
2245
|
try {
|
|
2057
|
-
|
|
2246
|
+
element.focus({ preventScroll: true });
|
|
2058
2247
|
} catch {
|
|
2059
|
-
|
|
2248
|
+
element.focus();
|
|
2060
2249
|
}
|
|
2250
|
+
}
|
|
2251
|
+
function selectTextarea(textarea) {
|
|
2252
|
+
focusWithoutScroll(textarea);
|
|
2061
2253
|
textarea.select();
|
|
2062
2254
|
textarea.setSelectionRange(0, textarea.value.length);
|
|
2063
|
-
|
|
2255
|
+
}
|
|
2256
|
+
function runCopyCommand() {
|
|
2064
2257
|
try {
|
|
2065
|
-
|
|
2258
|
+
return typeof document.execCommand === "function" && document.execCommand("copy");
|
|
2066
2259
|
} catch {
|
|
2067
|
-
|
|
2260
|
+
return false;
|
|
2068
2261
|
}
|
|
2262
|
+
}
|
|
2263
|
+
function restoreInputSelection(snapshot) {
|
|
2264
|
+
if (!snapshot.activeInputSelection) return false;
|
|
2265
|
+
const { input, start, end } = snapshot.activeInputSelection;
|
|
2266
|
+
if (start === null || end === null) return false;
|
|
2267
|
+
input.setSelectionRange(start, end);
|
|
2268
|
+
return true;
|
|
2269
|
+
}
|
|
2270
|
+
function restoreCopyContext(snapshot) {
|
|
2271
|
+
if (snapshot.activeElement) focusWithoutScroll(snapshot.activeElement);
|
|
2272
|
+
if (!restoreInputSelection(snapshot)) restoreSelection(snapshot.ranges);
|
|
2273
|
+
}
|
|
2274
|
+
function fallbackCopyText(text) {
|
|
2275
|
+
if (typeof document === "undefined" || !document.body) return false;
|
|
2276
|
+
const snapshot = snapshotCopyContext();
|
|
2277
|
+
const textarea = createCopyTextarea(text);
|
|
2278
|
+
document.body.appendChild(textarea);
|
|
2279
|
+
selectTextarea(textarea);
|
|
2280
|
+
const copied = runCopyCommand();
|
|
2069
2281
|
textarea.remove();
|
|
2070
|
-
|
|
2071
|
-
activeElement.focus({ preventScroll: true });
|
|
2072
|
-
} catch {
|
|
2073
|
-
activeElement.focus();
|
|
2074
|
-
}
|
|
2075
|
-
if (activeInput && activeSelection) activeInput.setSelectionRange(activeSelection.start, activeSelection.end);
|
|
2076
|
-
else restoreSelection(ranges);
|
|
2282
|
+
restoreCopyContext(snapshot);
|
|
2077
2283
|
return copied;
|
|
2078
2284
|
}
|
|
2079
2285
|
async function copyText(text) {
|
|
@@ -3713,6 +3919,20 @@ function GenericToolCard({ card, onToolAction, renderToolAgent }) {
|
|
|
3713
3919
|
})] });
|
|
3714
3920
|
}
|
|
3715
3921
|
//#endregion
|
|
3922
|
+
//#region src/components/chat/ui/chat-message-list/tool-card/tool-card-panel-app.tsx
|
|
3923
|
+
function PanelAppInlineToolCard({ card, onToolAction, renderPanelAppCard }) {
|
|
3924
|
+
const { panelApp } = card;
|
|
3925
|
+
if (!panelApp) return /* @__PURE__ */ jsx(GenericToolCard, {
|
|
3926
|
+
card,
|
|
3927
|
+
onToolAction
|
|
3928
|
+
});
|
|
3929
|
+
if (renderPanelAppCard) return renderPanelAppCard(panelApp);
|
|
3930
|
+
return /* @__PURE__ */ jsx(GenericToolCard, {
|
|
3931
|
+
card,
|
|
3932
|
+
onToolAction
|
|
3933
|
+
});
|
|
3934
|
+
}
|
|
3935
|
+
//#endregion
|
|
3716
3936
|
//#region src/components/chat/ui/chat-message-list/chat-tool-card.tsx
|
|
3717
3937
|
function isTerminalTool(name) {
|
|
3718
3938
|
const lowered = name.toLowerCase();
|
|
@@ -3726,7 +3946,12 @@ function isSearchTool(name) {
|
|
|
3726
3946
|
const lowered = name.toLowerCase();
|
|
3727
3947
|
return lowered === "grep_search" || lowered === "find_files" || lowered.includes("search");
|
|
3728
3948
|
}
|
|
3729
|
-
function ChatToolCard({ card, onToolAction, onFileOpen, renderToolAgent }) {
|
|
3949
|
+
function ChatToolCard({ card, onToolAction, onFileOpen, renderToolAgent, renderPanelAppCard }) {
|
|
3950
|
+
if (card.panelApp) return /* @__PURE__ */ jsx(PanelAppInlineToolCard, {
|
|
3951
|
+
card,
|
|
3952
|
+
onToolAction,
|
|
3953
|
+
renderPanelAppCard
|
|
3954
|
+
});
|
|
3730
3955
|
if (isTerminalTool(card.toolName)) return /* @__PURE__ */ jsx(TerminalExecutionView, { card });
|
|
3731
3956
|
if (isFileEditTool(card.toolName)) return /* @__PURE__ */ jsx(FileOperationView, {
|
|
3732
3957
|
card,
|
|
@@ -3740,27 +3965,8 @@ function ChatToolCard({ card, onToolAction, onFileOpen, renderToolAgent }) {
|
|
|
3740
3965
|
});
|
|
3741
3966
|
}
|
|
3742
3967
|
//#endregion
|
|
3743
|
-
//#region src/components/chat/ui/chat-message-list/chat-unknown-part.tsx
|
|
3744
|
-
function ChatUnknownPart(props) {
|
|
3745
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
3746
|
-
className: "rounded-lg border border-gray-200 bg-gray-50 px-2.5 py-2 text-xs text-gray-600",
|
|
3747
|
-
children: [/* @__PURE__ */ jsxs("div", {
|
|
3748
|
-
className: "font-semibold text-gray-700",
|
|
3749
|
-
children: [
|
|
3750
|
-
props.label,
|
|
3751
|
-
": ",
|
|
3752
|
-
props.rawType
|
|
3753
|
-
]
|
|
3754
|
-
}), props.text ? /* @__PURE__ */ jsx("pre", {
|
|
3755
|
-
className: "mt-1 whitespace-pre-wrap break-words text-[11px] text-gray-500",
|
|
3756
|
-
children: props.text
|
|
3757
|
-
}) : null]
|
|
3758
|
-
});
|
|
3759
|
-
}
|
|
3760
|
-
//#endregion
|
|
3761
3968
|
//#region src/components/chat/ui/chat-message-list/chat-message.tsx
|
|
3762
|
-
const ChatMessage = memo(function ChatMessage(
|
|
3763
|
-
const { message, texts, onToolAction, onFileOpen, renderToolAgent } = props;
|
|
3969
|
+
const ChatMessage = memo(function ChatMessage({ message, texts, onToolAction, onFileOpen, renderToolAgent, renderPanelAppCard }) {
|
|
3764
3970
|
const { role } = message;
|
|
3765
3971
|
const isUser = role === "user";
|
|
3766
3972
|
const isMessageInProgress = message.status === "pending" || message.status === "streaming";
|
|
@@ -3770,61 +3976,77 @@ const ChatMessage = memo(function ChatMessage(props) {
|
|
|
3770
3976
|
className: "space-y-2",
|
|
3771
3977
|
children: message.parts.map((part, index) => {
|
|
3772
3978
|
const { type } = part;
|
|
3773
|
-
if (type === "markdown")
|
|
3774
|
-
text
|
|
3775
|
-
|
|
3776
|
-
|
|
3777
|
-
|
|
3778
|
-
|
|
3779
|
-
|
|
3780
|
-
|
|
3781
|
-
|
|
3782
|
-
|
|
3783
|
-
|
|
3784
|
-
|
|
3785
|
-
|
|
3786
|
-
|
|
3787
|
-
|
|
3788
|
-
|
|
3789
|
-
|
|
3790
|
-
}
|
|
3791
|
-
if (type === "
|
|
3792
|
-
|
|
3793
|
-
|
|
3794
|
-
|
|
3795
|
-
|
|
3796
|
-
|
|
3797
|
-
|
|
3798
|
-
})
|
|
3799
|
-
}
|
|
3800
|
-
if (type === "
|
|
3801
|
-
|
|
3802
|
-
|
|
3803
|
-
|
|
3804
|
-
|
|
3805
|
-
|
|
3806
|
-
|
|
3807
|
-
|
|
3808
|
-
|
|
3809
|
-
|
|
3979
|
+
if (type === "markdown") {
|
|
3980
|
+
const { text } = part;
|
|
3981
|
+
return /* @__PURE__ */ jsx(ChatMessageMarkdown, {
|
|
3982
|
+
text,
|
|
3983
|
+
role,
|
|
3984
|
+
texts,
|
|
3985
|
+
onFileOpen
|
|
3986
|
+
}, `markdown-${index}`);
|
|
3987
|
+
}
|
|
3988
|
+
if (type === "inline-content") {
|
|
3989
|
+
const { segments } = part;
|
|
3990
|
+
return /* @__PURE__ */ jsx(ChatMessageInlineContent, {
|
|
3991
|
+
segments,
|
|
3992
|
+
role,
|
|
3993
|
+
texts,
|
|
3994
|
+
onFileOpen
|
|
3995
|
+
}, `inline-content-${index}`);
|
|
3996
|
+
}
|
|
3997
|
+
if (type === "reasoning") {
|
|
3998
|
+
const { label, text } = part;
|
|
3999
|
+
return /* @__PURE__ */ jsx(ChatReasoningBlock, {
|
|
4000
|
+
label,
|
|
4001
|
+
text,
|
|
4002
|
+
isUser,
|
|
4003
|
+
isInProgress: isMessageInProgress && index === message.parts.length - 1
|
|
4004
|
+
}, `reasoning-${index}`);
|
|
4005
|
+
}
|
|
4006
|
+
if (type === "tool-card") {
|
|
4007
|
+
const { card } = part;
|
|
4008
|
+
return /* @__PURE__ */ jsx("div", {
|
|
4009
|
+
className: "mt-0.5",
|
|
4010
|
+
children: /* @__PURE__ */ jsx(ChatToolCard, {
|
|
4011
|
+
card,
|
|
4012
|
+
onToolAction,
|
|
4013
|
+
onFileOpen,
|
|
4014
|
+
renderToolAgent,
|
|
4015
|
+
renderPanelAppCard
|
|
4016
|
+
})
|
|
4017
|
+
}, `tool-${index}`);
|
|
4018
|
+
}
|
|
4019
|
+
if (type === "file") {
|
|
4020
|
+
const { file } = part;
|
|
4021
|
+
return /* @__PURE__ */ jsx(ChatMessageFile, {
|
|
4022
|
+
file,
|
|
4023
|
+
isUser,
|
|
4024
|
+
texts
|
|
4025
|
+
}, `file-${index}`);
|
|
4026
|
+
}
|
|
4027
|
+
if (type === "unknown") {
|
|
4028
|
+
const { label, rawType, text } = part;
|
|
4029
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
4030
|
+
className: "rounded-lg border border-gray-200 bg-gray-50 px-2.5 py-2 text-xs text-gray-600",
|
|
4031
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
4032
|
+
className: "font-semibold text-gray-700",
|
|
4033
|
+
children: [
|
|
4034
|
+
label,
|
|
4035
|
+
": ",
|
|
4036
|
+
rawType
|
|
4037
|
+
]
|
|
4038
|
+
}), text ? /* @__PURE__ */ jsx("pre", {
|
|
4039
|
+
className: "mt-1 whitespace-pre-wrap break-words text-[11px] text-gray-500",
|
|
4040
|
+
children: text
|
|
4041
|
+
}) : null]
|
|
4042
|
+
}, `unknown-${index}`);
|
|
4043
|
+
}
|
|
3810
4044
|
return null;
|
|
3811
4045
|
})
|
|
3812
4046
|
})
|
|
3813
4047
|
});
|
|
3814
4048
|
});
|
|
3815
4049
|
//#endregion
|
|
3816
|
-
//#region src/components/chat/ui/chat-message-list/chat-message-meta.tsx
|
|
3817
|
-
function ChatMessageMeta(props) {
|
|
3818
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
3819
|
-
className: cn("px-1 text-[11px] leading-4 text-gray-400", props.isUser ? "text-right" : "text-left"),
|
|
3820
|
-
children: [
|
|
3821
|
-
props.roleLabel,
|
|
3822
|
-
" · ",
|
|
3823
|
-
props.timestampLabel
|
|
3824
|
-
]
|
|
3825
|
-
});
|
|
3826
|
-
}
|
|
3827
|
-
//#endregion
|
|
3828
4050
|
//#region src/components/chat/ui/chat-message-list/chat-message-action-copy.tsx
|
|
3829
4051
|
function ChatMessageActionCopy({ message, texts }) {
|
|
3830
4052
|
const messageText = useMemo(() => {
|
|
@@ -3920,11 +4142,11 @@ function ChatTypingIndicator({ label }) {
|
|
|
3920
4142
|
})]
|
|
3921
4143
|
});
|
|
3922
4144
|
}
|
|
3923
|
-
function ChatMessageList(
|
|
3924
|
-
const visibleMessages =
|
|
4145
|
+
function ChatMessageList({ className, isSending, messages, onFileOpen, onToolAction, renderPanelAppCard, renderToolAgent, texts }) {
|
|
4146
|
+
const visibleMessages = messages.filter(hasRenderableMessageContent);
|
|
3925
4147
|
const hasRenderableAssistantDraft = visibleMessages.some((message) => message.role === "assistant" && (message.status === "streaming" || message.status === "pending"));
|
|
3926
4148
|
return /* @__PURE__ */ jsxs("div", {
|
|
3927
|
-
className: cn("space-y-5",
|
|
4149
|
+
className: cn("space-y-5", className),
|
|
3928
4150
|
children: [visibleMessages.map((message) => {
|
|
3929
4151
|
const isUser = message.role === "user";
|
|
3930
4152
|
const isGenerating = !isUser && (message.status === "streaming" || message.status === "pending");
|
|
@@ -3936,28 +4158,32 @@ function ChatMessageList(props) {
|
|
|
3936
4158
|
className: cn("w-fit max-w-[92%] space-y-2", isUser && "flex flex-col items-end"),
|
|
3937
4159
|
children: [/* @__PURE__ */ jsx(ChatMessage, {
|
|
3938
4160
|
message,
|
|
3939
|
-
texts
|
|
3940
|
-
onToolAction
|
|
3941
|
-
onFileOpen
|
|
3942
|
-
renderToolAgent
|
|
4161
|
+
texts,
|
|
4162
|
+
onToolAction,
|
|
4163
|
+
onFileOpen,
|
|
4164
|
+
renderToolAgent,
|
|
4165
|
+
renderPanelAppCard
|
|
3943
4166
|
}), /* @__PURE__ */ jsx("div", {
|
|
3944
4167
|
className: cn("flex items-center gap-2", isUser && "justify-end"),
|
|
3945
|
-
children: isGenerating ? /* @__PURE__ */ jsx(ChatMessageTypingFooter, {}) : /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */
|
|
3946
|
-
|
|
3947
|
-
|
|
3948
|
-
|
|
4168
|
+
children: isGenerating ? /* @__PURE__ */ jsx(ChatMessageTypingFooter, {}) : /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("div", {
|
|
4169
|
+
className: cn("px-1 text-[11px] leading-4 text-gray-400", isUser ? "text-right" : "text-left"),
|
|
4170
|
+
children: [
|
|
4171
|
+
message.roleLabel,
|
|
4172
|
+
" · ",
|
|
4173
|
+
message.timestampLabel
|
|
4174
|
+
]
|
|
3949
4175
|
}), !isUser ? /* @__PURE__ */ jsx(ChatMessageActionCopy, {
|
|
3950
4176
|
message,
|
|
3951
|
-
texts
|
|
4177
|
+
texts
|
|
3952
4178
|
}) : null] })
|
|
3953
4179
|
})]
|
|
3954
4180
|
}),
|
|
3955
4181
|
isUser ? /* @__PURE__ */ jsx(ChatMessageAvatar, { role: message.role }) : null
|
|
3956
4182
|
]
|
|
3957
4183
|
}, message.id);
|
|
3958
|
-
}),
|
|
4184
|
+
}), isSending && !hasRenderableAssistantDraft ? /* @__PURE__ */ jsxs("div", {
|
|
3959
4185
|
className: "flex justify-start gap-3",
|
|
3960
|
-
children: [/* @__PURE__ */ jsx(ChatMessageAvatar, { role: "assistant" }), /* @__PURE__ */ jsx(ChatTypingIndicator, { label:
|
|
4186
|
+
children: [/* @__PURE__ */ jsx(ChatMessageAvatar, { role: "assistant" }), /* @__PURE__ */ jsx(ChatTypingIndicator, { label: texts.typingLabel })]
|
|
3961
4187
|
}) : null]
|
|
3962
4188
|
});
|
|
3963
4189
|
}
|