@nextclaw/agent-chat-ui 0.5.2 → 0.5.3
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.js +498 -472
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -10,7 +10,6 @@ import * as TooltipPrimitive from "@radix-ui/react-tooltip";
|
|
|
10
10
|
import { cva } from "class-variance-authority";
|
|
11
11
|
import { ContentEditable } from "@lexical/react/LexicalContentEditable";
|
|
12
12
|
import { LexicalComposer } from "@lexical/react/LexicalComposer";
|
|
13
|
-
import { EditorRefPlugin } from "@lexical/react/LexicalEditorRefPlugin";
|
|
14
13
|
import { LexicalErrorBoundary } from "@lexical/react/LexicalErrorBoundary";
|
|
15
14
|
import { PlainTextPlugin } from "@lexical/react/LexicalPlainTextPlugin";
|
|
16
15
|
import { $applyNodeReplacement, $createLineBreakNode, $createParagraphNode, $createRangeSelection, $createTextNode, $getRoot, $getSelection, $isElementNode, $isRangeSelection, $isTextNode, $setSelection, BLUR_COMMAND, COMMAND_PRIORITY_EDITOR, COMMAND_PRIORITY_HIGH, DecoratorNode, KEY_DOWN_COMMAND, SELECTION_CHANGE_COMMAND, mergeRegister } from "lexical";
|
|
@@ -256,7 +255,7 @@ function cn(...inputs) {
|
|
|
256
255
|
//#region src/components/chat/default-skin/input.tsx
|
|
257
256
|
const ChatInput = React.forwardRef(({ className, type, ...props }, ref) => /* @__PURE__ */ jsx("input", {
|
|
258
257
|
type,
|
|
259
|
-
className: cn("flex h-9 w-full rounded-xl border border-
|
|
258
|
+
className: cn("flex h-9 w-full rounded-xl border border-border bg-card px-3.5 py-2 text-sm text-foreground file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground/55 placeholder:font-normal focus:outline-none focus:ring-1 focus:ring-primary/40 focus:border-primary/40 transition-colors disabled:cursor-not-allowed disabled:opacity-50", className),
|
|
260
259
|
ref,
|
|
261
260
|
...props
|
|
262
261
|
}));
|
|
@@ -276,7 +275,7 @@ const ChatPopoverContent = React.forwardRef(({ className, sideOffset = 8, align
|
|
|
276
275
|
sideOffset,
|
|
277
276
|
align,
|
|
278
277
|
collisionPadding,
|
|
279
|
-
className: cn("z-[var(--z-popover,50)] w-72 overflow-x-hidden overflow-y-auto rounded-2xl border border-
|
|
278
|
+
className: cn("z-[var(--z-popover,50)] w-72 overflow-x-hidden overflow-y-auto rounded-2xl border border-border bg-popover p-4 text-popover-foreground 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=top]:slide-in-from-bottom-2 data-[side=right]:slide-in-from-left-2", className),
|
|
280
279
|
style: {
|
|
281
280
|
maxHeight: CHAT_POPOVER_CONTENT_MAX_HEIGHT,
|
|
282
281
|
...style
|
|
@@ -296,7 +295,7 @@ function createChatSelectAvailableHeightLimit(limit) {
|
|
|
296
295
|
const CHAT_SELECT_CONTENT_MAX_HEIGHT = createChatSelectAvailableHeightLimit("24rem");
|
|
297
296
|
const ChatSelectTrigger = React.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(SelectPrimitive.Trigger, {
|
|
298
297
|
ref,
|
|
299
|
-
className: cn("flex h-9 w-full items-center justify-between whitespace-nowrap rounded-xl border border-
|
|
298
|
+
className: cn("flex h-9 w-full items-center justify-between whitespace-nowrap rounded-xl border border-border bg-card px-3 py-2 text-sm text-foreground 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),
|
|
300
299
|
...props,
|
|
301
300
|
children: [children, /* @__PURE__ */ jsx(SelectPrimitive.Icon, {
|
|
302
301
|
asChild: true,
|
|
@@ -320,7 +319,7 @@ const ChatSelectScrollDownButton = React.forwardRef(({ className, ...props }, re
|
|
|
320
319
|
ChatSelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName;
|
|
321
320
|
const ChatSelectContent = React.forwardRef(({ className, children, collisionPadding = 12, position = "popper", style, viewportClassName, ...props }, ref) => /* @__PURE__ */ jsx(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsxs(SelectPrimitive.Content, {
|
|
322
321
|
ref,
|
|
323
|
-
className: cn("relative z-50 flex max-h-96 min-w-[8rem] flex-col overflow-hidden rounded-md bg-
|
|
322
|
+
className: cn("relative z-50 flex max-h-96 min-w-[8rem] flex-col overflow-hidden rounded-md border border-border bg-popover 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),
|
|
324
323
|
collisionPadding,
|
|
325
324
|
position,
|
|
326
325
|
style: {
|
|
@@ -340,13 +339,13 @@ const ChatSelectContent = React.forwardRef(({ className, children, collisionPadd
|
|
|
340
339
|
ChatSelectContent.displayName = SelectPrimitive.Content.displayName;
|
|
341
340
|
const ChatSelectLabel = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(SelectPrimitive.Label, {
|
|
342
341
|
ref,
|
|
343
|
-
className: cn("px-2 py-1 text-[11px] font-semibold uppercase tracking-[0.08em] text-
|
|
342
|
+
className: cn("px-2 py-1 text-[11px] font-semibold uppercase tracking-[0.08em] text-muted-foreground", className),
|
|
344
343
|
...props
|
|
345
344
|
}));
|
|
346
345
|
ChatSelectLabel.displayName = SelectPrimitive.Label.displayName;
|
|
347
346
|
const ChatSelectItem = React.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(SelectPrimitive.Item, {
|
|
348
347
|
ref,
|
|
349
|
-
className: cn("relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-2 pr-8 text-sm outline-none focus:bg-
|
|
348
|
+
className: cn("relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-2 pr-8 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 hover:bg-accent hover:text-accent-foreground", className),
|
|
350
349
|
...props,
|
|
351
350
|
children: [/* @__PURE__ */ jsx("span", {
|
|
352
351
|
className: "absolute right-2 flex h-3.5 w-3.5 items-center justify-center",
|
|
@@ -356,7 +355,7 @@ const ChatSelectItem = React.forwardRef(({ className, children, ...props }, ref)
|
|
|
356
355
|
ChatSelectItem.displayName = SelectPrimitive.Item.displayName;
|
|
357
356
|
const ChatSelectSeparator = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(SelectPrimitive.Separator, {
|
|
358
357
|
ref,
|
|
359
|
-
className: cn("-mx-1 my-1 h-px bg-
|
|
358
|
+
className: cn("-mx-1 my-1 h-px bg-border", className),
|
|
360
359
|
...props
|
|
361
360
|
}));
|
|
362
361
|
ChatSelectSeparator.displayName = SelectPrimitive.Separator.displayName;
|
|
@@ -652,12 +651,12 @@ const buttonVariants = cva("inline-flex items-center justify-center whitespace-n
|
|
|
652
651
|
variant: {
|
|
653
652
|
default: "bg-primary text-primary-foreground hover:bg-primary-600 active:bg-primary-700 shadow-sm",
|
|
654
653
|
destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
|
|
655
|
-
outline: "border border-
|
|
656
|
-
secondary: "bg-
|
|
657
|
-
ghost: "hover:bg-
|
|
654
|
+
outline: "border border-border bg-card text-muted-foreground hover:bg-accent hover:text-accent-foreground",
|
|
655
|
+
secondary: "bg-muted text-foreground hover:bg-accent hover:text-accent-foreground",
|
|
656
|
+
ghost: "text-muted-foreground hover:bg-accent hover:text-accent-foreground",
|
|
658
657
|
link: "text-primary underline-offset-4 hover:underline",
|
|
659
658
|
primary: "bg-primary text-primary-foreground hover:bg-primary-600 active:bg-primary-700 shadow-sm",
|
|
660
|
-
subtle: "bg-
|
|
659
|
+
subtle: "bg-muted text-muted-foreground hover:bg-accent hover:text-accent-foreground",
|
|
661
660
|
"primary-outline": "border border-primary/30 text-primary hover:bg-primary hover:text-primary-foreground"
|
|
662
661
|
},
|
|
663
662
|
size: {
|
|
@@ -695,30 +694,30 @@ function StopIcon() {
|
|
|
695
694
|
return /* @__PURE__ */ jsx("span", {
|
|
696
695
|
"aria-hidden": "true",
|
|
697
696
|
"data-testid": "chat-stop-icon",
|
|
698
|
-
className: "block h-3 w-3 rounded-[2px] bg-
|
|
697
|
+
className: "block h-3 w-3 rounded-[2px] bg-foreground shadow-[inset_0_0_0_1px_hsl(var(--border))]"
|
|
699
698
|
});
|
|
700
699
|
}
|
|
701
700
|
function ContextWindowIndicator({ contextWindow }) {
|
|
702
701
|
const { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } = ChatUiPrimitives;
|
|
703
702
|
const clampedRatio = Math.max(0, Math.min(1, contextWindow.ratio));
|
|
704
703
|
const angle = Math.round(clampedRatio * 360);
|
|
705
|
-
const ringColor = "
|
|
704
|
+
const ringColor = "hsl(var(--muted-foreground))";
|
|
706
705
|
return /* @__PURE__ */ jsx(TooltipProvider, {
|
|
707
706
|
delayDuration: 0,
|
|
708
707
|
children: /* @__PURE__ */ jsxs(Tooltip, { children: [/* @__PURE__ */ jsx(TooltipTrigger, {
|
|
709
708
|
asChild: true,
|
|
710
709
|
children: /* @__PURE__ */ jsxs("button", {
|
|
711
710
|
type: "button",
|
|
712
|
-
className: "relative inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-lg text-
|
|
711
|
+
className: "relative inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-lg text-muted-foreground transition-colors hover:bg-accent hover:text-accent-foreground",
|
|
713
712
|
"aria-label": contextWindow.label,
|
|
714
713
|
title: contextWindow.label,
|
|
715
714
|
children: [/* @__PURE__ */ jsx("span", {
|
|
716
715
|
"aria-hidden": "true",
|
|
717
716
|
className: "absolute inset-[7px] rounded-full",
|
|
718
|
-
style: { background: `conic-gradient(${ringColor} ${angle}deg,
|
|
717
|
+
style: { background: `conic-gradient(${ringColor} ${angle}deg, hsl(var(--border)) 0deg)` }
|
|
719
718
|
}), /* @__PURE__ */ jsx("span", {
|
|
720
719
|
"aria-hidden": "true",
|
|
721
|
-
className: "absolute inset-[10px] rounded-full bg-
|
|
720
|
+
className: "absolute inset-[10px] rounded-full bg-card"
|
|
722
721
|
})]
|
|
723
722
|
})
|
|
724
723
|
}), /* @__PURE__ */ jsx(TooltipContent, {
|
|
@@ -727,12 +726,12 @@ function ContextWindowIndicator({ contextWindow }) {
|
|
|
727
726
|
children: /* @__PURE__ */ jsxs("div", {
|
|
728
727
|
className: "space-y-1.5 text-xs",
|
|
729
728
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
730
|
-
className: "flex items-center justify-between gap-5 font-semibold text-
|
|
729
|
+
className: "flex items-center justify-between gap-5 font-semibold text-foreground",
|
|
731
730
|
children: [/* @__PURE__ */ jsx("span", { children: contextWindow.label }), /* @__PURE__ */ jsx("span", { children: contextWindow.percentLabel })]
|
|
732
731
|
}), contextWindow.details.map((detail) => /* @__PURE__ */ jsxs("div", {
|
|
733
|
-
className: "flex items-center justify-between gap-5 text-
|
|
732
|
+
className: "flex items-center justify-between gap-5 text-muted-foreground",
|
|
734
733
|
children: [/* @__PURE__ */ jsx("span", { children: detail.label }), /* @__PURE__ */ jsx("span", {
|
|
735
|
-
className: "font-medium text-
|
|
734
|
+
className: "font-medium text-foreground",
|
|
736
735
|
children: detail.value
|
|
737
736
|
})]
|
|
738
737
|
}, detail.label))]
|
|
@@ -895,7 +894,7 @@ function ChatInputBarSkillPicker(props) {
|
|
|
895
894
|
type: "button",
|
|
896
895
|
"aria-haspopup": "listbox",
|
|
897
896
|
"aria-label": picker.title,
|
|
898
|
-
className: "relative inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-lg px-0 text-xs font-medium text-
|
|
897
|
+
className: "relative inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-lg px-0 text-xs font-medium text-muted-foreground transition-colors hover:bg-accent hover:text-accent-foreground sm:w-auto sm:gap-1.5 sm:px-3",
|
|
899
898
|
children: [
|
|
900
899
|
/* @__PURE__ */ jsx(BrainCircuit, { className: "h-4 w-4" }),
|
|
901
900
|
/* @__PURE__ */ jsx("span", {
|
|
@@ -915,13 +914,13 @@ function ChatInputBarSkillPicker(props) {
|
|
|
915
914
|
style: { maxHeight: SKILL_PICKER_MAX_HEIGHT },
|
|
916
915
|
children: [
|
|
917
916
|
/* @__PURE__ */ jsxs("div", {
|
|
918
|
-
className: "shrink-0 space-y-2 border-b border-
|
|
917
|
+
className: "shrink-0 space-y-2 border-b border-border px-4 py-3",
|
|
919
918
|
children: [/* @__PURE__ */ jsx("div", {
|
|
920
|
-
className: "text-sm font-semibold text-
|
|
919
|
+
className: "text-sm font-semibold text-foreground",
|
|
921
920
|
children: picker.title
|
|
922
921
|
}), /* @__PURE__ */ jsxs("div", {
|
|
923
922
|
className: "relative",
|
|
924
|
-
children: [/* @__PURE__ */ jsx(Search, { className: "pointer-events-none absolute left-3 top-2.5 h-3.5 w-3.5 text-
|
|
923
|
+
children: [/* @__PURE__ */ jsx(Search, { className: "pointer-events-none absolute left-3 top-2.5 h-3.5 w-3.5 text-muted-foreground/70" }), /* @__PURE__ */ jsx(Input, {
|
|
925
924
|
value: query,
|
|
926
925
|
onChange: (event) => setQuery(event.target.value),
|
|
927
926
|
onKeyDown: onSearchKeyDown,
|
|
@@ -942,10 +941,10 @@ function ChatInputBarSkillPicker(props) {
|
|
|
942
941
|
"aria-multiselectable": "true",
|
|
943
942
|
className: "custom-scrollbar min-h-0 flex-1 overflow-y-auto overscroll-contain",
|
|
944
943
|
children: picker.isLoading ? /* @__PURE__ */ jsx("div", {
|
|
945
|
-
className: "p-4 text-xs text-
|
|
944
|
+
className: "p-4 text-xs text-muted-foreground",
|
|
946
945
|
children: picker.loadingLabel
|
|
947
946
|
}) : visibleOptions.length === 0 ? /* @__PURE__ */ jsx("div", {
|
|
948
|
-
className: "p-4 text-center text-xs text-
|
|
947
|
+
className: "p-4 text-center text-xs text-muted-foreground",
|
|
949
948
|
children: picker.emptyLabel
|
|
950
949
|
}) : /* @__PURE__ */ jsx("div", {
|
|
951
950
|
className: "py-1",
|
|
@@ -956,7 +955,7 @@ function ChatInputBarSkillPicker(props) {
|
|
|
956
955
|
}];
|
|
957
956
|
let visibleIndex = 0;
|
|
958
957
|
return groups.map((group) => /* @__PURE__ */ jsxs("div", { children: [group.label ? /* @__PURE__ */ jsx("div", {
|
|
959
|
-
className: "px-4 pb-1 pt-2 text-[11px] font-semibold uppercase tracking-wide text-
|
|
958
|
+
className: "px-4 pb-1 pt-2 text-[11px] font-semibold uppercase tracking-wide text-muted-foreground",
|
|
960
959
|
children: group.label
|
|
961
960
|
}) : null, group.options.map((option) => {
|
|
962
961
|
const index = visibleIndex;
|
|
@@ -969,10 +968,10 @@ function ChatInputBarSkillPicker(props) {
|
|
|
969
968
|
"aria-selected": isSelected,
|
|
970
969
|
"data-skill-index": index,
|
|
971
970
|
onMouseEnter: () => setActiveIndex(index),
|
|
972
|
-
className: `flex w-full items-center gap-3 px-4 py-2.5 text-left transition-colors ${isActive ? "bg-
|
|
971
|
+
className: `flex w-full items-center gap-3 px-4 py-2.5 text-left transition-colors ${isActive ? "bg-accent" : "hover:bg-accent"}`,
|
|
973
972
|
children: [
|
|
974
973
|
/* @__PURE__ */ jsx("div", {
|
|
975
|
-
className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-
|
|
974
|
+
className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-muted text-muted-foreground",
|
|
976
975
|
children: /* @__PURE__ */ jsx(Puzzle, { className: "h-4 w-4" })
|
|
977
976
|
}),
|
|
978
977
|
/* @__PURE__ */ jsxs("div", {
|
|
@@ -980,14 +979,14 @@ function ChatInputBarSkillPicker(props) {
|
|
|
980
979
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
981
980
|
className: "flex items-center gap-1.5",
|
|
982
981
|
children: [/* @__PURE__ */ jsx("span", {
|
|
983
|
-
className: "truncate text-sm text-
|
|
982
|
+
className: "truncate text-sm text-foreground",
|
|
984
983
|
children: option.label
|
|
985
984
|
}), option.badgeLabel ? /* @__PURE__ */ jsx("span", {
|
|
986
985
|
className: "shrink-0 rounded-full bg-primary/10 px-1.5 py-0.5 text-[10px] font-medium text-primary",
|
|
987
986
|
children: option.badgeLabel
|
|
988
987
|
}) : null]
|
|
989
988
|
}), /* @__PURE__ */ jsx("div", {
|
|
990
|
-
className: "mt-0.5 truncate text-xs text-
|
|
989
|
+
className: "mt-0.5 truncate text-xs text-muted-foreground",
|
|
991
990
|
children: option.description || option.key
|
|
992
991
|
})]
|
|
993
992
|
}),
|
|
@@ -997,7 +996,7 @@ function ChatInputBarSkillPicker(props) {
|
|
|
997
996
|
type: "button",
|
|
998
997
|
"aria-label": `${isSelected ? "Remove" : "Add"} ${option.label}`,
|
|
999
998
|
onClick: () => onToggleOption(option.key),
|
|
1000
|
-
className: isSelected ? "inline-flex h-5 w-5 items-center justify-center rounded-full bg-primary text-white" : "inline-flex h-5 w-5 items-center justify-center rounded-full border border-
|
|
999
|
+
className: isSelected ? "inline-flex h-5 w-5 items-center justify-center rounded-full bg-primary text-white" : "inline-flex h-5 w-5 items-center justify-center rounded-full border border-border bg-card",
|
|
1001
1000
|
children: isSelected ? /* @__PURE__ */ jsx(Check, { className: "h-3 w-3" }) : null
|
|
1002
1001
|
})
|
|
1003
1002
|
})
|
|
@@ -1008,7 +1007,7 @@ function ChatInputBarSkillPicker(props) {
|
|
|
1008
1007
|
})
|
|
1009
1008
|
}),
|
|
1010
1009
|
picker.manageHref && picker.manageLabel ? /* @__PURE__ */ jsx("div", {
|
|
1011
|
-
className: "shrink-0 border-t border-
|
|
1010
|
+
className: "shrink-0 border-t border-border px-4 py-2.5",
|
|
1012
1011
|
children: /* @__PURE__ */ jsxs("a", {
|
|
1013
1012
|
href: picker.manageHref,
|
|
1014
1013
|
className: "inline-flex items-center gap-1.5 text-xs font-medium text-primary transition-colors hover:text-primary/80",
|
|
@@ -1021,7 +1020,7 @@ function ChatInputBarSkillPicker(props) {
|
|
|
1021
1020
|
//#endregion
|
|
1022
1021
|
//#region src/components/chat/ui/chat-input-bar/chat-input-bar-toolbar.tsx
|
|
1023
1022
|
function ToolbarIcon({ icon }) {
|
|
1024
|
-
return icon === "sparkles" ? /* @__PURE__ */ jsx(Sparkles, { className: "h-3.5 w-3.5 shrink-0 text-primary" }) : icon === "brain" ? /* @__PURE__ */ jsx(Brain, { className: "h-3.5 w-3.5 shrink-0 text-
|
|
1023
|
+
return icon === "sparkles" ? /* @__PURE__ */ jsx(Sparkles, { className: "h-3.5 w-3.5 shrink-0 text-primary" }) : icon === "brain" ? /* @__PURE__ */ jsx(Brain, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground" }) : null;
|
|
1025
1024
|
}
|
|
1026
1025
|
function AccessoryIcon({ icon }) {
|
|
1027
1026
|
return icon === "paperclip" ? /* @__PURE__ */ jsx(Paperclip, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx(ToolbarIcon, { icon });
|
|
@@ -1054,16 +1053,16 @@ function ToolbarSelectTriggerContent({ item }) {
|
|
|
1054
1053
|
children: [
|
|
1055
1054
|
/* @__PURE__ */ jsx(ToolbarIcon, { icon: item.icon }),
|
|
1056
1055
|
/* @__PURE__ */ jsx("span", {
|
|
1057
|
-
className: "nextclaw-chat-toolbar-mobile-label truncate text-xs font-semibold text-
|
|
1056
|
+
className: "nextclaw-chat-toolbar-mobile-label truncate text-xs font-semibold text-foreground sm:hidden [@container_nextclaw-chat-input-bar_(max-width:440px)]:hidden",
|
|
1058
1057
|
children: mobileSelectedLabel
|
|
1059
1058
|
}),
|
|
1060
1059
|
/* @__PURE__ */ jsx("span", {
|
|
1061
|
-
className: "nextclaw-chat-toolbar-label hidden truncate text-xs font-semibold text-
|
|
1060
|
+
className: "nextclaw-chat-toolbar-label hidden truncate text-xs font-semibold text-foreground sm:inline [@container_nextclaw-chat-input-bar_(max-width:440px)]:hidden",
|
|
1062
1061
|
children: item.selectedLabel
|
|
1063
1062
|
})
|
|
1064
1063
|
]
|
|
1065
1064
|
});
|
|
1066
|
-
if (item.loading) return /* @__PURE__ */ jsx("div", { className: "h-3 w-24 animate-pulse rounded bg-
|
|
1065
|
+
if (item.loading) return /* @__PURE__ */ jsx("div", { className: "h-3 w-24 animate-pulse rounded bg-muted" });
|
|
1067
1066
|
return /* @__PURE__ */ jsx("span", {
|
|
1068
1067
|
className: "truncate",
|
|
1069
1068
|
children: item.placeholder
|
|
@@ -1073,14 +1072,14 @@ function ToolbarSelectOptionContent({ option }) {
|
|
|
1073
1072
|
return option.description ? /* @__PURE__ */ jsxs("div", {
|
|
1074
1073
|
className: "flex min-w-0 flex-col gap-0.5",
|
|
1075
1074
|
children: [/* @__PURE__ */ jsx("span", {
|
|
1076
|
-
className: "truncate text-xs font-semibold text-
|
|
1075
|
+
className: "truncate text-xs font-semibold text-foreground",
|
|
1077
1076
|
children: option.label
|
|
1078
1077
|
}), /* @__PURE__ */ jsx("span", {
|
|
1079
|
-
className: "truncate text-[11px] text-
|
|
1078
|
+
className: "truncate text-[11px] text-muted-foreground",
|
|
1080
1079
|
children: option.description
|
|
1081
1080
|
})]
|
|
1082
1081
|
}) : /* @__PURE__ */ jsx("span", {
|
|
1083
|
-
className: "truncate text-xs font-semibold text-
|
|
1082
|
+
className: "truncate text-xs font-semibold text-foreground",
|
|
1084
1083
|
children: option.label
|
|
1085
1084
|
});
|
|
1086
1085
|
}
|
|
@@ -1114,8 +1113,8 @@ function ToolbarSearchableSelect({ item }) {
|
|
|
1114
1113
|
type: "button",
|
|
1115
1114
|
"aria-label": item.selectedLabel ? `${item.placeholder}: ${item.selectedLabel}` : item.placeholder,
|
|
1116
1115
|
disabled: item.disabled,
|
|
1117
|
-
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-
|
|
1118
|
-
children: [/* @__PURE__ */ jsx(ToolbarSelectTriggerContent, { item }), /* @__PURE__ */ jsx(ChevronDown, { className: "ml-1 h-3.5 w-3.5 shrink-0 text-
|
|
1116
|
+
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-muted-foreground shadow-none hover:bg-accent hover:text-accent-foreground 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] ?? ""}`,
|
|
1117
|
+
children: [/* @__PURE__ */ jsx(ToolbarSelectTriggerContent, { item }), /* @__PURE__ */ jsx(ChevronDown, { className: "ml-1 h-3.5 w-3.5 shrink-0 text-muted-foreground/70 [@container_nextclaw-chat-input-bar_(max-width:440px)]:hidden" })]
|
|
1119
1118
|
})
|
|
1120
1119
|
}), /* @__PURE__ */ jsxs(PopoverContent, {
|
|
1121
1120
|
className: `flex flex-col overflow-hidden p-2 ${CONTENT_WIDTH_BY_KEY[item.key] ?? ""}`,
|
|
@@ -1123,7 +1122,7 @@ function ToolbarSearchableSelect({ item }) {
|
|
|
1123
1122
|
children: [
|
|
1124
1123
|
/* @__PURE__ */ jsxs("div", {
|
|
1125
1124
|
className: "relative mb-2 shrink-0",
|
|
1126
|
-
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-
|
|
1125
|
+
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-muted-foreground/70" }), /* @__PURE__ */ jsx(Input, {
|
|
1127
1126
|
value: query,
|
|
1128
1127
|
onChange: (event) => setQuery(event.currentTarget.value),
|
|
1129
1128
|
placeholder: item.search?.placeholder ?? item.placeholder,
|
|
@@ -1133,31 +1132,31 @@ function ToolbarSearchableSelect({ item }) {
|
|
|
1133
1132
|
!hasOptions ? item.loading ? /* @__PURE__ */ jsxs("div", {
|
|
1134
1133
|
className: "space-y-2 px-2 py-1",
|
|
1135
1134
|
children: [
|
|
1136
|
-
/* @__PURE__ */ jsx("div", { className: "h-3 w-36 animate-pulse rounded bg-
|
|
1137
|
-
/* @__PURE__ */ jsx("div", { className: "h-3 w-28 animate-pulse rounded bg-
|
|
1138
|
-
/* @__PURE__ */ jsx("div", { className: "h-3 w-32 animate-pulse rounded bg-
|
|
1135
|
+
/* @__PURE__ */ jsx("div", { className: "h-3 w-36 animate-pulse rounded bg-muted" }),
|
|
1136
|
+
/* @__PURE__ */ jsx("div", { className: "h-3 w-28 animate-pulse rounded bg-muted" }),
|
|
1137
|
+
/* @__PURE__ */ jsx("div", { className: "h-3 w-32 animate-pulse rounded bg-muted" })
|
|
1139
1138
|
]
|
|
1140
1139
|
}) : item.emptyLabel ? /* @__PURE__ */ jsx("div", {
|
|
1141
|
-
className: "px-2 py-1 text-xs text-
|
|
1140
|
+
className: "px-2 py-1 text-xs text-muted-foreground",
|
|
1142
1141
|
children: item.emptyLabel
|
|
1143
1142
|
}) : null : null,
|
|
1144
1143
|
hasOptions && !hasFilteredOptions ? /* @__PURE__ */ jsx("div", {
|
|
1145
|
-
className: "px-2 py-1 text-xs text-
|
|
1144
|
+
className: "px-2 py-1 text-xs text-muted-foreground",
|
|
1146
1145
|
children: item.search?.emptyLabel ?? item.emptyLabel
|
|
1147
1146
|
}) : null,
|
|
1148
1147
|
/* @__PURE__ */ jsx("div", {
|
|
1149
1148
|
className: "min-h-0 flex-1 overflow-y-auto overscroll-contain",
|
|
1150
1149
|
children: filteredGroups.map((group, groupIndex) => /* @__PURE__ */ jsxs("div", {
|
|
1151
|
-
className: groupIndex > 0 ? "border-t border-
|
|
1150
|
+
className: groupIndex > 0 ? "border-t border-border pt-1" : void 0,
|
|
1152
1151
|
children: [group.label ? /* @__PURE__ */ jsx("div", {
|
|
1153
|
-
className: "px-2 py-1 text-[11px] font-semibold uppercase tracking-[0.08em] text-
|
|
1152
|
+
className: "px-2 py-1 text-[11px] font-semibold uppercase tracking-[0.08em] text-muted-foreground",
|
|
1154
1153
|
children: group.label
|
|
1155
1154
|
}) : null, group.options.map((option) => {
|
|
1156
1155
|
const isSelected = item.value === option.value;
|
|
1157
1156
|
const isActive = activeValues.has(option.value);
|
|
1158
1157
|
const actionLabel = isActive ? action?.activeLabel : action?.inactiveLabel;
|
|
1159
1158
|
return /* @__PURE__ */ jsxs("div", {
|
|
1160
|
-
className: "group flex items-center gap-1 rounded-md hover:bg-
|
|
1159
|
+
className: "group flex items-center gap-1 rounded-md hover:bg-accent",
|
|
1161
1160
|
children: [/* @__PURE__ */ jsxs("button", {
|
|
1162
1161
|
type: "button",
|
|
1163
1162
|
className: "flex min-w-0 flex-1 items-center gap-2 rounded-md px-2 py-2 text-left",
|
|
@@ -1176,7 +1175,7 @@ function ToolbarSearchableSelect({ item }) {
|
|
|
1176
1175
|
type: "button",
|
|
1177
1176
|
"aria-label": actionLabel,
|
|
1178
1177
|
"aria-pressed": isActive,
|
|
1179
|
-
className: "mr-1 inline-flex h-7 w-7 shrink-0 items-center justify-center rounded-md text-
|
|
1178
|
+
className: "mr-1 inline-flex h-7 w-7 shrink-0 items-center justify-center rounded-md text-muted-foreground/70 transition-colors hover:bg-card hover:text-amber-500 focus:outline-none focus:ring-1 focus:ring-primary/40",
|
|
1180
1179
|
onClick: (event) => {
|
|
1181
1180
|
event.stopPropagation();
|
|
1182
1181
|
action.onToggle(option.value, !isActive);
|
|
@@ -1210,7 +1209,7 @@ function ToolbarSelect({ item }) {
|
|
|
1210
1209
|
children: [/* @__PURE__ */ jsx(SelectTrigger, {
|
|
1211
1210
|
"aria-label": item.selectedLabel ? `${item.placeholder}: ${item.selectedLabel}` : item.placeholder,
|
|
1212
1211
|
title: item.selectedLabel,
|
|
1213
|
-
className: `nextclaw-chat-toolbar-select-trigger h-8 w-auto rounded-lg border-0 bg-transparent px-2 text-xs font-medium text-
|
|
1212
|
+
className: `nextclaw-chat-toolbar-select-trigger h-8 w-auto rounded-lg border-0 bg-transparent px-2 text-xs font-medium text-muted-foreground shadow-none hover:bg-accent hover:text-accent-foreground 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] ?? ""}`,
|
|
1214
1213
|
children: item.selectedLabel || item.loading ? /* @__PURE__ */ jsx(ToolbarSelectTriggerContent, { item }) : /* @__PURE__ */ jsx(SelectValue, { placeholder: item.placeholder })
|
|
1215
1214
|
}), /* @__PURE__ */ jsxs(SelectContent, {
|
|
1216
1215
|
className: CONTENT_WIDTH_BY_KEY[item.key] ?? "",
|
|
@@ -1218,12 +1217,12 @@ function ToolbarSelect({ item }) {
|
|
|
1218
1217
|
children: [!hasOptions ? item.loading ? /* @__PURE__ */ jsxs("div", {
|
|
1219
1218
|
className: "space-y-2 px-3 py-2",
|
|
1220
1219
|
children: [
|
|
1221
|
-
/* @__PURE__ */ jsx("div", { className: "h-3 w-36 animate-pulse rounded bg-
|
|
1222
|
-
/* @__PURE__ */ jsx("div", { className: "h-3 w-28 animate-pulse rounded bg-
|
|
1223
|
-
/* @__PURE__ */ jsx("div", { className: "h-3 w-32 animate-pulse rounded bg-
|
|
1220
|
+
/* @__PURE__ */ jsx("div", { className: "h-3 w-36 animate-pulse rounded bg-muted" }),
|
|
1221
|
+
/* @__PURE__ */ jsx("div", { className: "h-3 w-28 animate-pulse rounded bg-muted" }),
|
|
1222
|
+
/* @__PURE__ */ jsx("div", { className: "h-3 w-32 animate-pulse rounded bg-muted" })
|
|
1224
1223
|
]
|
|
1225
1224
|
}) : item.emptyLabel ? /* @__PURE__ */ jsx("div", {
|
|
1226
|
-
className: "px-3 py-2 text-xs text-
|
|
1225
|
+
className: "px-3 py-2 text-xs text-muted-foreground",
|
|
1227
1226
|
children: item.emptyLabel
|
|
1228
1227
|
}) : 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, {
|
|
1229
1228
|
value: option.value,
|
|
@@ -1245,7 +1244,7 @@ function ChatInputBarToolbar({ actions, accessories, selects, skillPicker }) {
|
|
|
1245
1244
|
accessories?.map((item) => {
|
|
1246
1245
|
const button = /* @__PURE__ */ jsxs("button", {
|
|
1247
1246
|
type: "button",
|
|
1248
|
-
className: `inline-flex items-center rounded-lg py-1.5 text-xs font-medium text-
|
|
1247
|
+
className: `inline-flex items-center rounded-lg py-1.5 text-xs font-medium text-muted-foreground transition-colors hover:bg-accent hover:text-accent-foreground disabled:cursor-not-allowed disabled:text-muted-foreground/50 ${item.iconOnly ? "h-8 w-8 justify-center px-0" : "gap-1.5 px-3"}`,
|
|
1249
1248
|
onClick: item.onClick,
|
|
1250
1249
|
disabled: item.disabled,
|
|
1251
1250
|
"aria-label": item.label,
|
|
@@ -1699,7 +1698,7 @@ function insertInputSurfaceItemIntoChatComposer(params) {
|
|
|
1699
1698
|
});
|
|
1700
1699
|
}
|
|
1701
1700
|
function getChatComposerNodesSignature(nodes) {
|
|
1702
|
-
return nodes.map((node) => node.type === "text" ? `text:${node.
|
|
1701
|
+
return nodes.map((node) => node.type === "text" ? `text:${node.text}` : `token:${node.tokenKind}:${node.tokenKey}:${node.label}`).join("");
|
|
1703
1702
|
}
|
|
1704
1703
|
function replaceChatComposerSelectionWithText(params) {
|
|
1705
1704
|
const { nodes, selection, text } = params;
|
|
@@ -1800,66 +1799,6 @@ function resolveLexicalComposerKeyboardAction(params) {
|
|
|
1800
1799
|
};
|
|
1801
1800
|
return { type: "noop" };
|
|
1802
1801
|
}
|
|
1803
|
-
var LexicalComposerHandleOwner = class {
|
|
1804
|
-
constructor(params) {
|
|
1805
|
-
this.params = params;
|
|
1806
|
-
this.insertInputSurfaceItem = (item, triggerSpecs = [CHAT_INPUT_SURFACE_SLASH_TRIGGER_SPEC]) => {
|
|
1807
|
-
this.params.onInputSurfaceItemSelect?.(item);
|
|
1808
|
-
this.params.publishSnapshot(insertInputSurfaceItemIntoChatComposer({
|
|
1809
|
-
item,
|
|
1810
|
-
nodes: this.params.optionsReader().nodes,
|
|
1811
|
-
selection: this.params.optionsReader().selection,
|
|
1812
|
-
triggerSpecs
|
|
1813
|
-
}), { focusAfterSync: true });
|
|
1814
|
-
};
|
|
1815
|
-
this.insertSlashItem = (item) => {
|
|
1816
|
-
this.insertInputSurfaceItem(item);
|
|
1817
|
-
};
|
|
1818
|
-
this.insertFileToken = (tokenKey, label) => {
|
|
1819
|
-
this.params.publishSnapshot(insertFileTokenIntoChatComposer({
|
|
1820
|
-
label,
|
|
1821
|
-
nodes: this.params.optionsReader().nodes,
|
|
1822
|
-
selection: this.params.optionsReader().selection,
|
|
1823
|
-
tokenKey
|
|
1824
|
-
}), { focusAfterSync: true });
|
|
1825
|
-
};
|
|
1826
|
-
this.insertFileTokens = (tokens) => {
|
|
1827
|
-
let nextNodes = this.params.optionsReader().nodes;
|
|
1828
|
-
let nextSelection = this.params.optionsReader().selection;
|
|
1829
|
-
for (const token of tokens) {
|
|
1830
|
-
const snapshot = insertFileTokenIntoChatComposer({
|
|
1831
|
-
label: token.label,
|
|
1832
|
-
nodes: nextNodes,
|
|
1833
|
-
selection: nextSelection,
|
|
1834
|
-
tokenKey: token.tokenKey
|
|
1835
|
-
});
|
|
1836
|
-
nextNodes = snapshot.nodes;
|
|
1837
|
-
nextSelection = snapshot.selection;
|
|
1838
|
-
}
|
|
1839
|
-
this.params.publishSnapshot({
|
|
1840
|
-
nodes: nextNodes,
|
|
1841
|
-
selection: nextSelection
|
|
1842
|
-
}, { focusAfterSync: true });
|
|
1843
|
-
};
|
|
1844
|
-
this.focusComposer = () => {
|
|
1845
|
-
this.params.focusComposer();
|
|
1846
|
-
};
|
|
1847
|
-
this.focusComposerAtEnd = (nodes) => {
|
|
1848
|
-
this.params.focusComposerAtEnd(nodes);
|
|
1849
|
-
};
|
|
1850
|
-
this.syncSelectedSkills = (nextKeys, options) => {
|
|
1851
|
-
this.params.publishSnapshot(syncSelectedSkillsIntoChatComposer({
|
|
1852
|
-
nextKeys,
|
|
1853
|
-
nodes: this.params.optionsReader().nodes,
|
|
1854
|
-
options,
|
|
1855
|
-
selection: this.params.optionsReader().selection
|
|
1856
|
-
}), { focusAfterSync: true });
|
|
1857
|
-
};
|
|
1858
|
-
}
|
|
1859
|
-
};
|
|
1860
|
-
function createLexicalComposerHandle(params) {
|
|
1861
|
-
return new LexicalComposerHandleOwner(params);
|
|
1862
|
-
}
|
|
1863
1802
|
function getChatComposerContentSignature(nodes) {
|
|
1864
1803
|
return JSON.stringify(nodes.map((node) => node.type === "text" ? {
|
|
1865
1804
|
text: node.text,
|
|
@@ -1887,12 +1826,13 @@ function handleLexicalComposerBeforeInput(params) {
|
|
|
1887
1826
|
} });
|
|
1888
1827
|
}
|
|
1889
1828
|
function handleLexicalComposerCompositionEnd(params) {
|
|
1890
|
-
const { data, fallbackSnapshot, publishSnapshot, snapshotReader } = params;
|
|
1829
|
+
const { compositionStartSnapshot, data, fallbackSnapshot, publishSnapshot, snapshotReader } = params;
|
|
1891
1830
|
const currentSnapshot = snapshotReader();
|
|
1892
1831
|
const editorSnapshot = fallbackSnapshot();
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1832
|
+
const baseSnapshot = compositionStartSnapshot ?? currentSnapshot;
|
|
1833
|
+
publishSnapshot(getChatComposerContentSignature(editorSnapshot.nodes) !== getChatComposerContentSignature(baseSnapshot.nodes) ? editorSnapshot : data.length > 0 ? replaceChatComposerSelectionWithText({
|
|
1834
|
+
nodes: baseSnapshot.nodes,
|
|
1835
|
+
selection: baseSnapshot.selection,
|
|
1896
1836
|
text: data
|
|
1897
1837
|
}) : editorSnapshot, {
|
|
1898
1838
|
forcePublish: true,
|
|
@@ -1941,182 +1881,314 @@ function handleLexicalComposerKeyboardCommand(params) {
|
|
|
1941
1881
|
}
|
|
1942
1882
|
}
|
|
1943
1883
|
//#endregion
|
|
1884
|
+
//#region src/components/chat/ui/chat-input-bar/lexical/owners/chat-composer-lexical-owner.ts
|
|
1885
|
+
function createMutableRef(value) {
|
|
1886
|
+
return { current: value };
|
|
1887
|
+
}
|
|
1888
|
+
function getChatComposerDocumentLength(nodes) {
|
|
1889
|
+
return nodes.reduce((cursor, node) => cursor + (node.type === "text" ? node.text.length : 1), 0);
|
|
1890
|
+
}
|
|
1891
|
+
var ChatComposerLexicalOwner = class {
|
|
1892
|
+
constructor() {
|
|
1893
|
+
this.isApplyingExternalUpdateRef = createMutableRef(false);
|
|
1894
|
+
this.isComposingRef = createMutableRef(false);
|
|
1895
|
+
this.pendingOwnerSignatureRef = createMutableRef(null);
|
|
1896
|
+
this.pendingSelectionRef = createMutableRef(null);
|
|
1897
|
+
this.selectionRef = createMutableRef(null);
|
|
1898
|
+
this.shouldFocusAfterSyncRef = createMutableRef(false);
|
|
1899
|
+
this.compositionStartSnapshotRef = createMutableRef(null);
|
|
1900
|
+
this.editorSignatureRef = createMutableRef("");
|
|
1901
|
+
this.lastPublishedSignatureRef = createMutableRef("");
|
|
1902
|
+
this.pendingInputSurfaceReasonRef = createMutableRef(null);
|
|
1903
|
+
this.editor = null;
|
|
1904
|
+
this.runtime = null;
|
|
1905
|
+
this.configureRuntime = (runtime) => {
|
|
1906
|
+
this.runtime = runtime;
|
|
1907
|
+
};
|
|
1908
|
+
this.bindEditor = (editor) => {
|
|
1909
|
+
this.editor = editor;
|
|
1910
|
+
return () => {
|
|
1911
|
+
if (this.editor === editor) this.editor = null;
|
|
1912
|
+
};
|
|
1913
|
+
};
|
|
1914
|
+
this.registerEditorListeners = (editor) => {
|
|
1915
|
+
return mergeRegister(editor.registerUpdateListener(({ editorState }) => {
|
|
1916
|
+
const runtime = this.getRuntime();
|
|
1917
|
+
this.handleEditorUpdate(editorState, runtime.callbacks);
|
|
1918
|
+
}), editor.registerCommand(SELECTION_CHANGE_COMMAND, () => {
|
|
1919
|
+
const runtime = this.getRuntime();
|
|
1920
|
+
this.handleSelectionChange(editor, runtime.callbacks);
|
|
1921
|
+
return false;
|
|
1922
|
+
}, COMMAND_PRIORITY_EDITOR), editor.registerCommand(BLUR_COMMAND, () => {
|
|
1923
|
+
this.getRuntime().callbacks.onInputSurfaceOpenChange?.(false);
|
|
1924
|
+
return false;
|
|
1925
|
+
}, COMMAND_PRIORITY_EDITOR), editor.registerCommand(KEY_DOWN_COMMAND, (event) => {
|
|
1926
|
+
const runtime = this.getRuntime();
|
|
1927
|
+
return this.handleKeyDown({
|
|
1928
|
+
actions: runtime.actions,
|
|
1929
|
+
callbacks: runtime.callbacks,
|
|
1930
|
+
event,
|
|
1931
|
+
fallbackNodes: runtime.fallbackNodes
|
|
1932
|
+
});
|
|
1933
|
+
}, COMMAND_PRIORITY_HIGH));
|
|
1934
|
+
};
|
|
1935
|
+
this.syncExternalState = (editor, nodes) => {
|
|
1936
|
+
if (this.isComposingRef.current) return;
|
|
1937
|
+
const nextSignature = getChatComposerNodesSignature(nodes);
|
|
1938
|
+
const pendingSelection = this.pendingSelectionRef.current;
|
|
1939
|
+
const pendingOwnerSignature = this.pendingOwnerSignatureRef.current;
|
|
1940
|
+
if (pendingOwnerSignature) {
|
|
1941
|
+
if (nextSignature === pendingOwnerSignature) this.pendingOwnerSignatureRef.current = null;
|
|
1942
|
+
else if (nextSignature !== this.editorSignatureRef.current) return;
|
|
1943
|
+
}
|
|
1944
|
+
const shouldSyncDocument = nextSignature !== this.editorSignatureRef.current;
|
|
1945
|
+
if (!shouldSyncDocument && !pendingSelection) return;
|
|
1946
|
+
this.startApplyingExternalUpdate();
|
|
1947
|
+
if (shouldSyncDocument) {
|
|
1948
|
+
syncLexicalEditorFromChatComposerState(editor, nodes, pendingSelection);
|
|
1949
|
+
this.editorSignatureRef.current = nextSignature;
|
|
1950
|
+
this.lastPublishedSignatureRef.current = nextSignature;
|
|
1951
|
+
} else if (pendingSelection) syncLexicalSelectionFromChatComposerSelection(editor, pendingSelection);
|
|
1952
|
+
if (pendingSelection) {
|
|
1953
|
+
this.selectionRef.current = pendingSelection;
|
|
1954
|
+
this.pendingSelectionRef.current = null;
|
|
1955
|
+
}
|
|
1956
|
+
if (this.shouldFocusAfterSyncRef.current) {
|
|
1957
|
+
this.shouldFocusAfterSyncRef.current = false;
|
|
1958
|
+
const targetSelection = this.selectionRef.current;
|
|
1959
|
+
editor.focus(() => {
|
|
1960
|
+
if (targetSelection) syncLexicalSelectionFromChatComposerSelection(editor, targetSelection);
|
|
1961
|
+
});
|
|
1962
|
+
}
|
|
1963
|
+
};
|
|
1964
|
+
this.publishSnapshot = (snapshot, callbacks, options) => {
|
|
1965
|
+
this.selectionRef.current = snapshot.selection;
|
|
1966
|
+
this.pendingSelectionRef.current = snapshot.selection;
|
|
1967
|
+
if (options?.focusAfterSync) this.shouldFocusAfterSyncRef.current = true;
|
|
1968
|
+
const signature = getChatComposerNodesSignature(snapshot.nodes);
|
|
1969
|
+
const { editor } = this;
|
|
1970
|
+
this.pendingOwnerSignatureRef.current = signature;
|
|
1971
|
+
if (editor) {
|
|
1972
|
+
this.startApplyingExternalUpdate();
|
|
1973
|
+
syncLexicalEditorFromChatComposerState(editor, snapshot.nodes, snapshot.selection);
|
|
1974
|
+
this.editorSignatureRef.current = signature;
|
|
1975
|
+
}
|
|
1976
|
+
callbacks.onInputSurfaceSnapshotChange?.(snapshot.nodes, snapshot.selection, options?.inputSurfaceReason ?? { type: "programmatic" });
|
|
1977
|
+
if (options?.forcePublish || signature !== this.lastPublishedSignatureRef.current) {
|
|
1978
|
+
this.lastPublishedSignatureRef.current = signature;
|
|
1979
|
+
callbacks.onNodesChange(snapshot.nodes);
|
|
1980
|
+
}
|
|
1981
|
+
};
|
|
1982
|
+
this.focusComposer = () => {
|
|
1983
|
+
const { editor } = this;
|
|
1984
|
+
if (!editor) return;
|
|
1985
|
+
editor.getRootElement()?.focus({ preventScroll: true });
|
|
1986
|
+
const targetSelection = this.selectionRef.current;
|
|
1987
|
+
if (targetSelection) syncLexicalSelectionFromChatComposerSelection(editor, targetSelection);
|
|
1988
|
+
editor.focus();
|
|
1989
|
+
};
|
|
1990
|
+
this.focusComposerAtEnd = (nodes) => {
|
|
1991
|
+
const { editor } = this;
|
|
1992
|
+
if (!editor) return;
|
|
1993
|
+
const end = getChatComposerDocumentLength(nodes ?? readChatComposerSnapshotFromEditorState(editor.getEditorState()).nodes);
|
|
1994
|
+
const targetSelection = {
|
|
1995
|
+
start: end,
|
|
1996
|
+
end
|
|
1997
|
+
};
|
|
1998
|
+
this.selectionRef.current = targetSelection;
|
|
1999
|
+
this.pendingSelectionRef.current = targetSelection;
|
|
2000
|
+
editor.getRootElement()?.focus({ preventScroll: true });
|
|
2001
|
+
if (nodes) {
|
|
2002
|
+
this.startApplyingExternalUpdate();
|
|
2003
|
+
const signature = getChatComposerNodesSignature(nodes);
|
|
2004
|
+
syncLexicalEditorFromChatComposerState(editor, nodes, targetSelection);
|
|
2005
|
+
this.editorSignatureRef.current = signature;
|
|
2006
|
+
this.lastPublishedSignatureRef.current = signature;
|
|
2007
|
+
} else syncLexicalSelectionFromChatComposerSelection(editor, targetSelection);
|
|
2008
|
+
editor.focus(() => {
|
|
2009
|
+
syncLexicalSelectionFromChatComposerSelection(editor, targetSelection);
|
|
2010
|
+
});
|
|
2011
|
+
};
|
|
2012
|
+
this.readComposerSnapshot = (fallbackNodes) => {
|
|
2013
|
+
const { editor } = this;
|
|
2014
|
+
if (!editor) return {
|
|
2015
|
+
nodes: fallbackNodes,
|
|
2016
|
+
selection: this.selectionRef.current
|
|
2017
|
+
};
|
|
2018
|
+
const snapshot = readChatComposerSnapshotFromEditorState(editor.getEditorState());
|
|
2019
|
+
this.selectionRef.current = snapshot.selection;
|
|
2020
|
+
return snapshot;
|
|
2021
|
+
};
|
|
2022
|
+
this.createHandle = () => {
|
|
2023
|
+
const insertInputSurfaceItem = (item, triggerSpecs = [CHAT_INPUT_SURFACE_SLASH_TRIGGER_SPEC]) => {
|
|
2024
|
+
const { callbacks } = this.getRuntime();
|
|
2025
|
+
callbacks.onInputSurfaceItemSelect?.(item);
|
|
2026
|
+
this.publishRuntimeSnapshot((snapshot) => insertInputSurfaceItemIntoChatComposer({
|
|
2027
|
+
item,
|
|
2028
|
+
nodes: snapshot.nodes,
|
|
2029
|
+
selection: snapshot.selection,
|
|
2030
|
+
triggerSpecs
|
|
2031
|
+
}), { focusAfterSync: true });
|
|
2032
|
+
};
|
|
2033
|
+
return {
|
|
2034
|
+
insertInputSurfaceItem,
|
|
2035
|
+
insertSlashItem: (item) => {
|
|
2036
|
+
insertInputSurfaceItem(item);
|
|
2037
|
+
},
|
|
2038
|
+
insertFileToken: (tokenKey, label) => {
|
|
2039
|
+
this.publishRuntimeSnapshot((snapshot) => insertFileTokenIntoChatComposer({
|
|
2040
|
+
label,
|
|
2041
|
+
nodes: snapshot.nodes,
|
|
2042
|
+
selection: snapshot.selection,
|
|
2043
|
+
tokenKey
|
|
2044
|
+
}), { focusAfterSync: true });
|
|
2045
|
+
},
|
|
2046
|
+
insertFileTokens: (tokens) => {
|
|
2047
|
+
this.publishRuntimeSnapshot((snapshot) => tokens.reduce((nextSnapshot, token) => insertFileTokenIntoChatComposer({
|
|
2048
|
+
label: token.label,
|
|
2049
|
+
nodes: nextSnapshot.nodes,
|
|
2050
|
+
selection: nextSnapshot.selection,
|
|
2051
|
+
tokenKey: token.tokenKey
|
|
2052
|
+
}), snapshot), { focusAfterSync: true });
|
|
2053
|
+
},
|
|
2054
|
+
focusComposer: this.focusComposer,
|
|
2055
|
+
focusComposerAtEnd: this.focusComposerAtEnd,
|
|
2056
|
+
syncSelectedSkills: (nextKeys, options) => {
|
|
2057
|
+
this.publishRuntimeSnapshot((snapshot) => syncSelectedSkillsIntoChatComposer({
|
|
2058
|
+
nextKeys,
|
|
2059
|
+
nodes: snapshot.nodes,
|
|
2060
|
+
options,
|
|
2061
|
+
selection: snapshot.selection
|
|
2062
|
+
}), { focusAfterSync: true });
|
|
2063
|
+
}
|
|
2064
|
+
};
|
|
2065
|
+
};
|
|
2066
|
+
this.handleBeforeInput = (params) => {
|
|
2067
|
+
const { disabled, event } = params;
|
|
2068
|
+
const { callbacks, fallbackNodes } = this.getRuntime();
|
|
2069
|
+
handleLexicalComposerBeforeInput({
|
|
2070
|
+
disabled,
|
|
2071
|
+
event,
|
|
2072
|
+
isComposing: this.isComposingRef.current,
|
|
2073
|
+
publishSnapshot: (snapshot, options) => this.publishSnapshot(snapshot, callbacks, options),
|
|
2074
|
+
snapshotReader: () => this.readComposerSnapshot(fallbackNodes)
|
|
2075
|
+
});
|
|
2076
|
+
};
|
|
2077
|
+
this.handleCompositionStart = () => {
|
|
2078
|
+
const { fallbackNodes } = this.getRuntime();
|
|
2079
|
+
this.compositionStartSnapshotRef.current = this.readComposerSnapshot(fallbackNodes);
|
|
2080
|
+
this.isComposingRef.current = true;
|
|
2081
|
+
};
|
|
2082
|
+
this.handleCompositionEnd = (params) => {
|
|
2083
|
+
const { data } = params;
|
|
2084
|
+
const { callbacks, fallbackNodes } = this.getRuntime();
|
|
2085
|
+
this.isComposingRef.current = false;
|
|
2086
|
+
handleLexicalComposerCompositionEnd({
|
|
2087
|
+
compositionStartSnapshot: this.compositionStartSnapshotRef.current,
|
|
2088
|
+
data,
|
|
2089
|
+
fallbackSnapshot: () => this.readComposerSnapshot(fallbackNodes),
|
|
2090
|
+
publishSnapshot: (snapshot, options) => this.publishSnapshot(snapshot, callbacks, options),
|
|
2091
|
+
snapshotReader: () => this.readComposerSnapshot(fallbackNodes)
|
|
2092
|
+
});
|
|
2093
|
+
this.compositionStartSnapshotRef.current = null;
|
|
2094
|
+
};
|
|
2095
|
+
this.handleKeyDown = (params) => {
|
|
2096
|
+
const { actions, callbacks, event, fallbackNodes } = params;
|
|
2097
|
+
if (event.key.length === 1 && !event.isComposing && !event.altKey && !event.ctrlKey && !event.metaKey) this.pendingInputSurfaceReasonRef.current = {
|
|
2098
|
+
type: "insert-text",
|
|
2099
|
+
text: event.key
|
|
2100
|
+
};
|
|
2101
|
+
const snapshot = this.readComposerSnapshot(fallbackNodes);
|
|
2102
|
+
if (callbacks.onInputSurfaceKeyDown?.(event)) return true;
|
|
2103
|
+
return handleLexicalComposerKeyboardCommand({
|
|
2104
|
+
actions,
|
|
2105
|
+
nativeEvent: event,
|
|
2106
|
+
publishSnapshot: (nextSnapshot, options) => this.publishSnapshot(nextSnapshot, callbacks, options),
|
|
2107
|
+
snapshot
|
|
2108
|
+
});
|
|
2109
|
+
};
|
|
2110
|
+
this.handleEditorUpdate = (editorState, callbacks) => {
|
|
2111
|
+
const snapshot = readChatComposerSnapshotFromEditorState(editorState);
|
|
2112
|
+
const signature = getChatComposerNodesSignature(snapshot.nodes);
|
|
2113
|
+
this.editorSignatureRef.current = signature;
|
|
2114
|
+
if (this.isApplyingExternalUpdateRef.current || this.isComposingRef.current) return;
|
|
2115
|
+
this.selectionRef.current = snapshot.selection;
|
|
2116
|
+
callbacks.onInputSurfaceSnapshotChange?.(snapshot.nodes, snapshot.selection, this.consumeInputSurfaceReason() ?? { type: "sync" });
|
|
2117
|
+
if (signature === this.lastPublishedSignatureRef.current) return;
|
|
2118
|
+
this.lastPublishedSignatureRef.current = signature;
|
|
2119
|
+
callbacks.onNodesChange(snapshot.nodes);
|
|
2120
|
+
};
|
|
2121
|
+
this.handleSelectionChange = (editor, callbacks) => {
|
|
2122
|
+
const snapshot = readChatComposerSnapshotFromEditorState(editor.getEditorState());
|
|
2123
|
+
if (this.isComposingRef.current) return;
|
|
2124
|
+
this.selectionRef.current = snapshot.selection;
|
|
2125
|
+
callbacks.onInputSurfaceSnapshotChange?.(snapshot.nodes, snapshot.selection, { type: "selection" });
|
|
2126
|
+
};
|
|
2127
|
+
this.consumeInputSurfaceReason = () => {
|
|
2128
|
+
const reason = this.pendingInputSurfaceReasonRef.current;
|
|
2129
|
+
this.pendingInputSurfaceReasonRef.current = null;
|
|
2130
|
+
return reason;
|
|
2131
|
+
};
|
|
2132
|
+
this.publishRuntimeSnapshot = (createSnapshot, options) => {
|
|
2133
|
+
const { callbacks, fallbackNodes } = this.getRuntime();
|
|
2134
|
+
this.publishSnapshot(createSnapshot(this.readComposerSnapshot(fallbackNodes)), callbacks, options);
|
|
2135
|
+
};
|
|
2136
|
+
this.startApplyingExternalUpdate = () => {
|
|
2137
|
+
this.isApplyingExternalUpdateRef.current = true;
|
|
2138
|
+
requestAnimationFrame(() => {
|
|
2139
|
+
this.isApplyingExternalUpdateRef.current = false;
|
|
2140
|
+
});
|
|
2141
|
+
};
|
|
2142
|
+
this.getRuntime = () => {
|
|
2143
|
+
if (!this.runtime) throw new Error("ChatComposerLexicalOwner runtime has not been configured.");
|
|
2144
|
+
return this.runtime;
|
|
2145
|
+
};
|
|
2146
|
+
}
|
|
2147
|
+
};
|
|
2148
|
+
//#endregion
|
|
1944
2149
|
//#region src/components/chat/ui/chat-input-bar/lexical/chat-composer-plugins.tsx
|
|
1945
|
-
function ChatComposerBindingsPlugin({ disabled,
|
|
2150
|
+
function ChatComposerBindingsPlugin({ disabled, nodes, owner }) {
|
|
1946
2151
|
const [editor] = useLexicalComposerContext();
|
|
1947
2152
|
useLayoutEffect(() => {
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
if (editorRef.current === editor) editorRef.current = null;
|
|
1951
|
-
};
|
|
1952
|
-
}, [editor, editorRef]);
|
|
2153
|
+
return owner.bindEditor(editor);
|
|
2154
|
+
}, [editor, owner]);
|
|
1953
2155
|
useLayoutEffect(() => {
|
|
1954
2156
|
editor.setEditable(!disabled);
|
|
1955
|
-
|
|
1956
|
-
useLayoutEffect(() => {
|
|
1957
|
-
const nextSignature = getChatComposerNodesSignature(nodes);
|
|
1958
|
-
const pendingSelection = pendingSelectionRef.current;
|
|
1959
|
-
const shouldSyncDocument = nextSignature !== editorSignatureRef.current;
|
|
1960
|
-
if (!shouldSyncDocument && !pendingSelection) return;
|
|
1961
|
-
isApplyingExternalUpdateRef.current = true;
|
|
1962
|
-
if (shouldSyncDocument) {
|
|
1963
|
-
syncLexicalEditorFromChatComposerState(editor, nodes, pendingSelection);
|
|
1964
|
-
editorSignatureRef.current = nextSignature;
|
|
1965
|
-
lastPublishedSignatureRef.current = nextSignature;
|
|
1966
|
-
} else if (pendingSelection) syncLexicalSelectionFromChatComposerSelection(editor, pendingSelection);
|
|
1967
|
-
if (pendingSelection) {
|
|
1968
|
-
selectionRef.current = pendingSelection;
|
|
1969
|
-
pendingSelectionRef.current = null;
|
|
1970
|
-
}
|
|
1971
|
-
if (shouldFocusAfterSyncRef.current) {
|
|
1972
|
-
shouldFocusAfterSyncRef.current = false;
|
|
1973
|
-
const targetSelection = selectionRef.current;
|
|
1974
|
-
editor.focus(() => {
|
|
1975
|
-
if (targetSelection) syncLexicalSelectionFromChatComposerSelection(editor, targetSelection);
|
|
1976
|
-
});
|
|
1977
|
-
}
|
|
1978
|
-
requestAnimationFrame(() => {
|
|
1979
|
-
isApplyingExternalUpdateRef.current = false;
|
|
1980
|
-
});
|
|
2157
|
+
owner.syncExternalState(editor, nodes);
|
|
1981
2158
|
}, [
|
|
2159
|
+
disabled,
|
|
1982
2160
|
editor,
|
|
1983
|
-
editorSignatureRef,
|
|
1984
|
-
isApplyingExternalUpdateRef,
|
|
1985
|
-
lastPublishedSignatureRef,
|
|
1986
2161
|
nodes,
|
|
1987
|
-
|
|
1988
|
-
selectionRef,
|
|
1989
|
-
shouldFocusAfterSyncRef
|
|
2162
|
+
owner
|
|
1990
2163
|
]);
|
|
1991
2164
|
useEffect(() => {
|
|
1992
|
-
return
|
|
1993
|
-
|
|
1994
|
-
const signature = getChatComposerNodesSignature(snapshot.nodes);
|
|
1995
|
-
selectionRef.current = snapshot.selection;
|
|
1996
|
-
editorSignatureRef.current = signature;
|
|
1997
|
-
if (isApplyingExternalUpdateRef.current || isComposingRef.current) return;
|
|
1998
|
-
syncInputSurfaceSnapshot(snapshot.nodes, snapshot.selection, consumeInputSurfaceReason() ?? { type: "sync" });
|
|
1999
|
-
if (signature === lastPublishedSignatureRef.current) return;
|
|
2000
|
-
lastPublishedSignatureRef.current = signature;
|
|
2001
|
-
onNodesChange(snapshot.nodes);
|
|
2002
|
-
}), editor.registerCommand(SELECTION_CHANGE_COMMAND, () => {
|
|
2003
|
-
const snapshot = readChatComposerSnapshotFromEditorState(editor.getEditorState());
|
|
2004
|
-
selectionRef.current = snapshot.selection;
|
|
2005
|
-
if (!isComposingRef.current) syncInputSurfaceSnapshot(snapshot.nodes, snapshot.selection, { type: "selection" });
|
|
2006
|
-
return false;
|
|
2007
|
-
}, COMMAND_PRIORITY_EDITOR), editor.registerCommand(BLUR_COMMAND, () => {
|
|
2008
|
-
onBlur();
|
|
2009
|
-
return false;
|
|
2010
|
-
}, COMMAND_PRIORITY_EDITOR), editor.registerCommand(KEY_DOWN_COMMAND, (event) => onKeyDown(event), COMMAND_PRIORITY_HIGH));
|
|
2011
|
-
}, [
|
|
2012
|
-
editor,
|
|
2013
|
-
editorSignatureRef,
|
|
2014
|
-
isApplyingExternalUpdateRef,
|
|
2015
|
-
isComposingRef,
|
|
2016
|
-
lastPublishedSignatureRef,
|
|
2017
|
-
onBlur,
|
|
2018
|
-
consumeInputSurfaceReason,
|
|
2019
|
-
onKeyDown,
|
|
2020
|
-
onNodesChange,
|
|
2021
|
-
selectionRef,
|
|
2022
|
-
syncInputSurfaceSnapshot
|
|
2023
|
-
]);
|
|
2165
|
+
return owner.registerEditorListeners(editor);
|
|
2166
|
+
}, [editor, owner]);
|
|
2024
2167
|
return null;
|
|
2025
2168
|
}
|
|
2026
2169
|
//#endregion
|
|
2027
2170
|
//#region src/components/chat/ui/chat-input-bar/lexical/chat-input-bar-tokenized-composer.tsx
|
|
2028
|
-
function getChatComposerDocumentLength(nodes) {
|
|
2029
|
-
return nodes.reduce((cursor, node) => cursor + (node.type === "text" ? node.text.length : 1), 0);
|
|
2030
|
-
}
|
|
2031
2171
|
const ChatInputBarTokenizedComposer = forwardRef(function ChatInputBarTokenizedComposer({ actions, disabled, nodes, onFilesAdd, onInputSurfaceItemSelect, onInputSurfaceKeyDown, onInputSurfaceOpenChange, onInputSurfaceSnapshotChange, onNodesChange, placeholder }, ref) {
|
|
2032
|
-
const
|
|
2033
|
-
const
|
|
2034
|
-
const pendingSelectionRef = useRef(null);
|
|
2035
|
-
const shouldFocusAfterSyncRef = useRef(false);
|
|
2036
|
-
const isComposingRef = useRef(false);
|
|
2037
|
-
const isApplyingExternalUpdateRef = useRef(false);
|
|
2038
|
-
const pendingInputSurfaceReasonRef = useRef(null);
|
|
2039
|
-
const editorSignatureRef = useRef("");
|
|
2040
|
-
const lastPublishedSignatureRef = useRef("");
|
|
2041
|
-
const syncInputSurfaceSnapshot = useCallback((nodes, selection, reason) => {
|
|
2042
|
-
onInputSurfaceSnapshotChange?.(nodes, selection, reason);
|
|
2043
|
-
}, [onInputSurfaceSnapshotChange]);
|
|
2044
|
-
const readCurrentNodes = useCallback(() => {
|
|
2045
|
-
return nodes;
|
|
2046
|
-
}, [nodes]);
|
|
2047
|
-
const readCurrentSelection = useCallback(() => {
|
|
2048
|
-
if (selectionRef.current) return selectionRef.current;
|
|
2049
|
-
if (!editorRef.current) return null;
|
|
2050
|
-
const snapshot = readChatComposerSnapshotFromEditorState(editorRef.current.getEditorState());
|
|
2051
|
-
selectionRef.current = snapshot.selection;
|
|
2052
|
-
return snapshot.selection;
|
|
2053
|
-
}, []);
|
|
2054
|
-
const publishSnapshot = useCallback((snapshot, options) => {
|
|
2055
|
-
selectionRef.current = snapshot.selection;
|
|
2056
|
-
pendingSelectionRef.current = snapshot.selection;
|
|
2057
|
-
if (options?.focusAfterSync) shouldFocusAfterSyncRef.current = true;
|
|
2058
|
-
const signature = getChatComposerNodesSignature(snapshot.nodes);
|
|
2059
|
-
syncInputSurfaceSnapshot(snapshot.nodes, snapshot.selection, options?.inputSurfaceReason ?? { type: "programmatic" });
|
|
2060
|
-
if (options?.forcePublish || signature !== lastPublishedSignatureRef.current) {
|
|
2061
|
-
lastPublishedSignatureRef.current = signature;
|
|
2062
|
-
onNodesChange(snapshot.nodes);
|
|
2063
|
-
}
|
|
2064
|
-
}, [onNodesChange, syncInputSurfaceSnapshot]);
|
|
2065
|
-
const focusComposer = useCallback(() => {
|
|
2066
|
-
const editor = editorRef.current;
|
|
2067
|
-
if (!editor) return;
|
|
2068
|
-
editor.getRootElement()?.focus({ preventScroll: true });
|
|
2069
|
-
const targetSelection = selectionRef.current;
|
|
2070
|
-
if (targetSelection) syncLexicalSelectionFromChatComposerSelection(editor, targetSelection);
|
|
2071
|
-
editor.focus();
|
|
2072
|
-
}, []);
|
|
2073
|
-
const focusComposerAtEnd = useCallback((nodes) => {
|
|
2074
|
-
const editor = editorRef.current;
|
|
2075
|
-
if (!editor) return;
|
|
2076
|
-
const end = getChatComposerDocumentLength(nodes ?? readChatComposerSnapshotFromEditorState(editor.getEditorState()).nodes);
|
|
2077
|
-
const targetSelection = {
|
|
2078
|
-
start: end,
|
|
2079
|
-
end
|
|
2080
|
-
};
|
|
2081
|
-
selectionRef.current = targetSelection;
|
|
2082
|
-
pendingSelectionRef.current = targetSelection;
|
|
2083
|
-
editor.getRootElement()?.focus({ preventScroll: true });
|
|
2084
|
-
if (nodes) {
|
|
2085
|
-
isApplyingExternalUpdateRef.current = true;
|
|
2086
|
-
const signature = getChatComposerNodesSignature(nodes);
|
|
2087
|
-
syncLexicalEditorFromChatComposerState(editor, nodes, targetSelection);
|
|
2088
|
-
editorSignatureRef.current = signature;
|
|
2089
|
-
lastPublishedSignatureRef.current = signature;
|
|
2090
|
-
requestAnimationFrame(() => {
|
|
2091
|
-
isApplyingExternalUpdateRef.current = false;
|
|
2092
|
-
});
|
|
2093
|
-
} else syncLexicalSelectionFromChatComposerSelection(editor, targetSelection);
|
|
2094
|
-
editor.focus(() => {
|
|
2095
|
-
syncLexicalSelectionFromChatComposerSelection(editor, targetSelection);
|
|
2096
|
-
});
|
|
2097
|
-
}, []);
|
|
2098
|
-
const readComposerSnapshot = useCallback(() => ({
|
|
2099
|
-
nodes: readCurrentNodes(),
|
|
2100
|
-
selection: readCurrentSelection()
|
|
2101
|
-
}), [readCurrentNodes, readCurrentSelection]);
|
|
2102
|
-
const consumeInputSurfaceReason = useCallback(() => {
|
|
2103
|
-
const reason = pendingInputSurfaceReasonRef.current;
|
|
2104
|
-
pendingInputSurfaceReasonRef.current = null;
|
|
2105
|
-
return reason;
|
|
2106
|
-
}, []);
|
|
2107
|
-
useImperativeHandle(ref, () => createLexicalComposerHandle({
|
|
2108
|
-
focusComposer,
|
|
2109
|
-
focusComposerAtEnd,
|
|
2172
|
+
const [owner] = useState(() => new ChatComposerLexicalOwner());
|
|
2173
|
+
const ownerCallbacks = useMemo(() => ({
|
|
2110
2174
|
onInputSurfaceItemSelect,
|
|
2111
|
-
|
|
2112
|
-
|
|
2175
|
+
onInputSurfaceKeyDown,
|
|
2176
|
+
onInputSurfaceOpenChange,
|
|
2177
|
+
onInputSurfaceSnapshotChange,
|
|
2178
|
+
onNodesChange
|
|
2113
2179
|
}), [
|
|
2114
|
-
focusComposer,
|
|
2115
|
-
focusComposerAtEnd,
|
|
2116
2180
|
onInputSurfaceItemSelect,
|
|
2117
|
-
|
|
2118
|
-
|
|
2181
|
+
onInputSurfaceKeyDown,
|
|
2182
|
+
onInputSurfaceOpenChange,
|
|
2183
|
+
onInputSurfaceSnapshotChange,
|
|
2184
|
+
onNodesChange
|
|
2119
2185
|
]);
|
|
2186
|
+
owner.configureRuntime({
|
|
2187
|
+
actions,
|
|
2188
|
+
callbacks: ownerCallbacks,
|
|
2189
|
+
fallbackNodes: nodes
|
|
2190
|
+
});
|
|
2191
|
+
useImperativeHandle(ref, () => owner.createHandle(), [owner]);
|
|
2120
2192
|
return /* @__PURE__ */ jsxs(LexicalComposer, {
|
|
2121
2193
|
initialConfig: useMemo(() => ({
|
|
2122
2194
|
editable: !disabled,
|
|
@@ -2130,92 +2202,46 @@ const ChatInputBarTokenizedComposer = forwardRef(function ChatInputBarTokenizedC
|
|
|
2130
2202
|
},
|
|
2131
2203
|
theme: {}
|
|
2132
2204
|
}), [disabled, nodes]),
|
|
2133
|
-
children: [
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
},
|
|
2159
|
-
publishSnapshot,
|
|
2160
|
-
snapshotReader: readComposerSnapshot
|
|
2161
|
-
});
|
|
2162
|
-
},
|
|
2163
|
-
onCompositionStart: () => {
|
|
2164
|
-
isComposingRef.current = true;
|
|
2165
|
-
},
|
|
2166
|
-
onPaste: (event) => {
|
|
2167
|
-
const files = Array.from(event.clipboardData.files ?? []);
|
|
2168
|
-
if (files.length > 0 && onFilesAdd) {
|
|
2169
|
-
event.preventDefault();
|
|
2170
|
-
onFilesAdd(files);
|
|
2171
|
-
}
|
|
2205
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
2206
|
+
className: "px-3 py-2 sm:px-4 sm:py-2.5",
|
|
2207
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
2208
|
+
className: "min-h-11 sm:min-h-[60px]",
|
|
2209
|
+
children: /* @__PURE__ */ jsx(PlainTextPlugin, {
|
|
2210
|
+
contentEditable: /* @__PURE__ */ jsx(ContentEditable, {
|
|
2211
|
+
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-foreground outline-none",
|
|
2212
|
+
onBeforeInput: (event) => {
|
|
2213
|
+
owner.handleBeforeInput({
|
|
2214
|
+
disabled,
|
|
2215
|
+
event
|
|
2216
|
+
});
|
|
2217
|
+
},
|
|
2218
|
+
onCompositionEnd: (event) => {
|
|
2219
|
+
const nativeEvent = event.nativeEvent;
|
|
2220
|
+
owner.handleCompositionEnd({ data: typeof nativeEvent.data === "string" ? nativeEvent.data : "" });
|
|
2221
|
+
},
|
|
2222
|
+
onCompositionStart: () => {
|
|
2223
|
+
owner.handleCompositionStart();
|
|
2224
|
+
},
|
|
2225
|
+
onPaste: (event) => {
|
|
2226
|
+
const files = Array.from(event.clipboardData.files ?? []);
|
|
2227
|
+
if (files.length > 0 && onFilesAdd) {
|
|
2228
|
+
event.preventDefault();
|
|
2229
|
+
onFilesAdd(files);
|
|
2172
2230
|
}
|
|
2173
|
-
}
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2231
|
+
}
|
|
2232
|
+
}),
|
|
2233
|
+
placeholder: /* @__PURE__ */ jsx("div", {
|
|
2234
|
+
className: "pointer-events-none absolute left-3 top-2 select-none text-sm leading-6 text-muted-foreground/60 sm:left-4 sm:top-2.5",
|
|
2235
|
+
children: placeholder
|
|
2236
|
+
}),
|
|
2237
|
+
ErrorBoundary: LexicalErrorBoundary
|
|
2180
2238
|
})
|
|
2181
|
-
}),
|
|
2182
|
-
/* @__PURE__ */ jsx(EditorRefPlugin, { editorRef }),
|
|
2183
|
-
/* @__PURE__ */ jsx(ChatComposerBindingsPlugin, {
|
|
2184
|
-
disabled,
|
|
2185
|
-
editorRef,
|
|
2186
|
-
editorSignatureRef,
|
|
2187
|
-
isApplyingExternalUpdateRef,
|
|
2188
|
-
isComposingRef,
|
|
2189
|
-
lastPublishedSignatureRef,
|
|
2190
|
-
nodes,
|
|
2191
|
-
onBlur: () => {
|
|
2192
|
-
onInputSurfaceOpenChange?.(false);
|
|
2193
|
-
},
|
|
2194
|
-
consumeInputSurfaceReason,
|
|
2195
|
-
onKeyDown: (event) => {
|
|
2196
|
-
if (event.key.length === 1 && !event.isComposing && !event.altKey && !event.ctrlKey && !event.metaKey) pendingInputSurfaceReasonRef.current = {
|
|
2197
|
-
type: "insert-text",
|
|
2198
|
-
text: event.key
|
|
2199
|
-
};
|
|
2200
|
-
const editor = editorRef.current;
|
|
2201
|
-
if (!editor) return false;
|
|
2202
|
-
const snapshot = readChatComposerSnapshotFromEditorState(editor.getEditorState());
|
|
2203
|
-
selectionRef.current = snapshot.selection;
|
|
2204
|
-
if (onInputSurfaceKeyDown?.(event)) return true;
|
|
2205
|
-
return handleLexicalComposerKeyboardCommand({
|
|
2206
|
-
actions,
|
|
2207
|
-
nativeEvent: event,
|
|
2208
|
-
publishSnapshot,
|
|
2209
|
-
snapshot
|
|
2210
|
-
});
|
|
2211
|
-
},
|
|
2212
|
-
onNodesChange,
|
|
2213
|
-
pendingSelectionRef,
|
|
2214
|
-
selectionRef,
|
|
2215
|
-
shouldFocusAfterSyncRef,
|
|
2216
|
-
syncInputSurfaceSnapshot
|
|
2217
2239
|
})
|
|
2218
|
-
|
|
2240
|
+
}), /* @__PURE__ */ jsx(ChatComposerBindingsPlugin, {
|
|
2241
|
+
disabled,
|
|
2242
|
+
nodes,
|
|
2243
|
+
owner
|
|
2244
|
+
})]
|
|
2219
2245
|
});
|
|
2220
2246
|
});
|
|
2221
2247
|
ChatInputBarTokenizedComposer.displayName = "LexicalChatInputBarTokenizedComposer";
|
|
@@ -2226,14 +2252,14 @@ function InputBarHint({ hint }) {
|
|
|
2226
2252
|
if (hint.loading) return /* @__PURE__ */ jsx("div", {
|
|
2227
2253
|
className: "px-4 pb-2",
|
|
2228
2254
|
children: /* @__PURE__ */ jsxs("div", {
|
|
2229
|
-
className: "inline-flex items-center gap-2 rounded-lg border border-
|
|
2230
|
-
children: [/* @__PURE__ */ jsx("span", { className: "h-3 w-28 animate-pulse rounded bg-
|
|
2255
|
+
className: "inline-flex items-center gap-2 rounded-lg border border-border bg-muted px-3 py-2",
|
|
2256
|
+
children: [/* @__PURE__ */ jsx("span", { className: "h-3 w-28 animate-pulse rounded bg-muted-foreground/20" }), /* @__PURE__ */ jsx("span", { className: "h-3 w-16 animate-pulse rounded bg-muted-foreground/20" })]
|
|
2231
2257
|
})
|
|
2232
2258
|
});
|
|
2233
2259
|
return /* @__PURE__ */ jsx("div", {
|
|
2234
2260
|
className: "px-4 pb-2",
|
|
2235
2261
|
children: /* @__PURE__ */ jsxs("div", {
|
|
2236
|
-
className: `inline-flex items-center gap-2 rounded-lg px-3 py-1.5 text-xs ${hint.tone === "warning" ? "border-amber-200 bg-amber-50 text-amber-800" : "border-
|
|
2262
|
+
className: `inline-flex items-center gap-2 rounded-lg px-3 py-1.5 text-xs ${hint.tone === "warning" ? "border-amber-200 bg-amber-50 text-amber-800" : "border-border bg-muted text-muted-foreground"}`,
|
|
2237
2263
|
children: [hint.text ? /* @__PURE__ */ jsx("span", { children: hint.text }) : null, hint.actionLabel && hint.onAction ? /* @__PURE__ */ jsx("button", {
|
|
2238
2264
|
type: "button",
|
|
2239
2265
|
onClick: hint.onAction,
|
|
@@ -2277,11 +2303,11 @@ const ChatInputBar = forwardRef(function ChatInputBar({ composer, hint, inputSur
|
|
|
2277
2303
|
focusComposerAtEnd: (nodes) => composerRef.current?.focusComposerAtEnd(nodes)
|
|
2278
2304
|
}), []);
|
|
2279
2305
|
return /* @__PURE__ */ jsx("div", {
|
|
2280
|
-
className: surface === "embedded" ? "bg-transparent px-0 py-0" : "
|
|
2306
|
+
className: surface === "embedded" ? "bg-transparent px-0 py-0" : "bg-background px-3 pb-3 pt-2 sm:px-4 sm:pb-4 sm:pt-2",
|
|
2281
2307
|
children: /* @__PURE__ */ jsx("div", {
|
|
2282
2308
|
className: "nextclaw-chat-input-bar-shell mx-auto w-full max-w-[min(1120px,100%)] [container:nextclaw-chat-input-bar/inline-size]",
|
|
2283
2309
|
children: /* @__PURE__ */ jsxs("div", {
|
|
2284
|
-
className: "overflow-hidden rounded-2xl border border-
|
|
2310
|
+
className: "overflow-hidden rounded-2xl border border-border bg-card shadow-card",
|
|
2285
2311
|
children: [
|
|
2286
2312
|
/* @__PURE__ */ jsx("div", {
|
|
2287
2313
|
className: "relative",
|
|
@@ -2318,19 +2344,19 @@ ChatInputBar.displayName = "ChatInputBar";
|
|
|
2318
2344
|
function ChatMessageAvatar({ role }) {
|
|
2319
2345
|
if (role === "user") return /* @__PURE__ */ jsx("div", {
|
|
2320
2346
|
"data-testid": "chat-message-avatar-user",
|
|
2321
|
-
className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-primary text-
|
|
2347
|
+
className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-primary text-primary-foreground shadow-sm",
|
|
2322
2348
|
children: /* @__PURE__ */ jsx(User, { className: "h-4 w-4" })
|
|
2323
2349
|
});
|
|
2324
2350
|
if (role === "tool") return /* @__PURE__ */ jsx("div", {
|
|
2325
2351
|
"data-testid": "chat-message-avatar-tool",
|
|
2326
|
-
className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-
|
|
2352
|
+
className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-accent text-accent-foreground shadow-sm ring-1 ring-border",
|
|
2327
2353
|
children: /* @__PURE__ */ jsx(Wrench, { className: "h-4 w-4" })
|
|
2328
2354
|
});
|
|
2329
2355
|
return /* @__PURE__ */ jsx("div", {
|
|
2330
2356
|
"data-testid": "chat-message-avatar-assistant",
|
|
2331
|
-
className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-
|
|
2357
|
+
className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-muted text-foreground shadow-sm ring-1 ring-border",
|
|
2332
2358
|
children: /* @__PURE__ */ jsx(Bot, {
|
|
2333
|
-
className: "h-[18px] w-[18px] text-
|
|
2359
|
+
className: "h-[18px] w-[18px] text-current",
|
|
2334
2360
|
strokeWidth: 2.5
|
|
2335
2361
|
})
|
|
2336
2362
|
});
|
|
@@ -2343,14 +2369,14 @@ function resolveInlineTokenTone(kind) {
|
|
|
2343
2369
|
return "default";
|
|
2344
2370
|
}
|
|
2345
2371
|
function resolveInlineTokenBadgeClassName(tone, isUser) {
|
|
2346
|
-
if (tone === "skill") return isUser ? "border-
|
|
2347
|
-
if (tone === "panel_app") return isUser ? "border-
|
|
2348
|
-
return isUser ? "border-
|
|
2372
|
+
if (tone === "skill") return isUser ? "border-primary-foreground/30 bg-primary-foreground/18 text-primary-foreground" : "border-border bg-accent text-accent-foreground";
|
|
2373
|
+
if (tone === "panel_app") return isUser ? "border-primary-foreground/30 bg-primary-foreground/18 text-primary-foreground" : "border-border bg-accent text-accent-foreground";
|
|
2374
|
+
return isUser ? "border-primary-foreground/30 bg-primary-foreground/18 text-primary-foreground" : "border-border bg-muted text-muted-foreground";
|
|
2349
2375
|
}
|
|
2350
2376
|
function resolveInlineTokenIconClassName(tone, isUser) {
|
|
2351
|
-
if (tone === "skill") return isUser ? "text-
|
|
2352
|
-
if (tone === "panel_app") return isUser ? "text-
|
|
2353
|
-
return isUser ? "text-
|
|
2377
|
+
if (tone === "skill") return isUser ? "text-primary-foreground/70" : "text-muted-foreground";
|
|
2378
|
+
if (tone === "panel_app") return isUser ? "text-primary-foreground/70" : "text-muted-foreground";
|
|
2379
|
+
return isUser ? "text-primary-foreground/70" : "text-muted-foreground";
|
|
2354
2380
|
}
|
|
2355
2381
|
function renderInlineTokenIcon(tone) {
|
|
2356
2382
|
return tone === "panel_app" ? /* @__PURE__ */ jsx(AppWindow, {
|
|
@@ -2929,16 +2955,16 @@ function ChatMessageMarkdown({ text, role, texts, inline = false, inlineTokens,
|
|
|
2929
2955
|
//#endregion
|
|
2930
2956
|
//#region src/components/chat/ui/chat-message-list/chat-message-file/meta.ts
|
|
2931
2957
|
const FILE_CATEGORY_TILE_CLASSES = {
|
|
2932
|
-
archive: "border-
|
|
2933
|
-
audio: "border-
|
|
2934
|
-
code: "border-
|
|
2935
|
-
data: "border-
|
|
2936
|
-
document: "border-
|
|
2937
|
-
generic: "border-
|
|
2938
|
-
image: "border-
|
|
2939
|
-
pdf: "border-
|
|
2940
|
-
sheet: "border-
|
|
2941
|
-
video: "border-
|
|
2958
|
+
archive: "border-border bg-muted text-muted-foreground",
|
|
2959
|
+
audio: "border-border bg-muted text-muted-foreground",
|
|
2960
|
+
code: "border-border bg-muted text-muted-foreground",
|
|
2961
|
+
data: "border-border bg-muted text-muted-foreground",
|
|
2962
|
+
document: "border-border bg-muted text-muted-foreground",
|
|
2963
|
+
generic: "border-border bg-muted text-muted-foreground",
|
|
2964
|
+
image: "border-border bg-muted text-muted-foreground",
|
|
2965
|
+
pdf: "border-border bg-muted text-muted-foreground",
|
|
2966
|
+
sheet: "border-border bg-muted text-muted-foreground",
|
|
2967
|
+
video: "border-border bg-muted text-muted-foreground"
|
|
2942
2968
|
};
|
|
2943
2969
|
const CODE_EXTENSIONS = new Set([
|
|
2944
2970
|
"c",
|
|
@@ -3148,13 +3174,13 @@ function readFileCategoryLabel(category, texts) {
|
|
|
3148
3174
|
}
|
|
3149
3175
|
function renderMetaLine(categoryLabel, sizeLabel, isUser) {
|
|
3150
3176
|
return /* @__PURE__ */ jsx("div", {
|
|
3151
|
-
className: cn("mt-1 text-xs leading-5", isUser ? "text-
|
|
3177
|
+
className: cn("mt-1 text-xs leading-5", isUser ? "text-primary-foreground/70" : "text-muted-foreground"),
|
|
3152
3178
|
children: sizeLabel ? `${categoryLabel} · ${sizeLabel}` : categoryLabel
|
|
3153
3179
|
});
|
|
3154
3180
|
}
|
|
3155
3181
|
function renderActionPill(label, isUser, isInteractive) {
|
|
3156
3182
|
return /* @__PURE__ */ jsx("span", {
|
|
3157
|
-
className: cn("inline-flex items-center rounded-full border px-2.5 py-1 text-[11px] font-medium", isInteractive ? isUser ? "border-
|
|
3183
|
+
className: cn("inline-flex items-center rounded-full border px-2.5 py-1 text-[11px] font-medium", isInteractive ? isUser ? "border-primary-foreground/14 bg-primary-foreground/12 text-primary-foreground" : "border-border bg-card text-foreground" : isUser ? "border-primary-foreground/10 bg-primary-foreground/6 text-primary-foreground/62" : "border-border bg-muted text-muted-foreground"),
|
|
3158
3184
|
children: label
|
|
3159
3185
|
});
|
|
3160
3186
|
}
|
|
@@ -3163,16 +3189,16 @@ function renderActionLink(label, href, isUser) {
|
|
|
3163
3189
|
href,
|
|
3164
3190
|
target: "_blank",
|
|
3165
3191
|
rel: "noreferrer",
|
|
3166
|
-
className: cn("inline-flex items-center rounded-full border px-2.5 py-1 text-[11px] font-medium transition duration-200", isUser ? "border-
|
|
3192
|
+
className: cn("inline-flex items-center rounded-full border px-2.5 py-1 text-[11px] font-medium transition duration-200", isUser ? "border-primary-foreground/14 bg-primary-foreground/12 text-primary-foreground hover:border-primary-foreground/20 hover:bg-primary-foreground/16" : "border-border bg-card text-foreground hover:border-border-hover hover:bg-accent"),
|
|
3167
3193
|
children: label
|
|
3168
3194
|
});
|
|
3169
3195
|
}
|
|
3170
3196
|
function FileCategoryGlyph({ category, isUser }) {
|
|
3171
3197
|
const Icon = FILE_CATEGORY_ICONS[category];
|
|
3172
3198
|
return /* @__PURE__ */ jsx("div", {
|
|
3173
|
-
className: cn("flex h-14 w-14 shrink-0 items-center justify-center rounded-[1rem] border", isUser ? "border-
|
|
3199
|
+
className: cn("flex h-14 w-14 shrink-0 items-center justify-center rounded-[1rem] border", isUser ? "border-primary-foreground/12 bg-primary-foreground/10 text-primary-foreground" : FILE_CATEGORY_TILE_CLASSES[category]),
|
|
3174
3200
|
children: /* @__PURE__ */ jsx(Icon, {
|
|
3175
|
-
className: cn("h-7 w-7", isUser ? "text-
|
|
3201
|
+
className: cn("h-7 w-7", isUser ? "text-primary-foreground/92" : "text-current"),
|
|
3176
3202
|
strokeWidth: 2.2
|
|
3177
3203
|
})
|
|
3178
3204
|
});
|
|
@@ -3186,7 +3212,7 @@ function renderImagePreview(params) {
|
|
|
3186
3212
|
rel: "noreferrer",
|
|
3187
3213
|
className: "group block",
|
|
3188
3214
|
children: /* @__PURE__ */ jsxs("div", {
|
|
3189
|
-
className: cn("relative overflow-hidden rounded-[1rem]", isUser ? "ring-1 ring-
|
|
3215
|
+
className: cn("relative overflow-hidden rounded-[1rem]", isUser ? "ring-1 ring-primary-foreground/10" : "bg-muted ring-1 ring-border"),
|
|
3190
3216
|
children: [/* @__PURE__ */ jsx("img", {
|
|
3191
3217
|
src: file.dataUrl,
|
|
3192
3218
|
alt: file.label,
|
|
@@ -3194,10 +3220,10 @@ function renderImagePreview(params) {
|
|
|
3194
3220
|
}), /* @__PURE__ */ jsxs("div", {
|
|
3195
3221
|
className: "pointer-events-none absolute right-3 top-3 flex items-center gap-2",
|
|
3196
3222
|
children: [/* @__PURE__ */ jsx("span", {
|
|
3197
|
-
className: cn("inline-flex items-center rounded-full px-2 py-1 text-[10px] font-semibold tracking-[0.18em] text-white backdrop-blur-sm", isUser ? "bg-
|
|
3223
|
+
className: cn("inline-flex items-center rounded-full px-2 py-1 text-[10px] font-semibold tracking-[0.18em] text-white backdrop-blur-sm", isUser ? "bg-black/36" : "bg-black/58"),
|
|
3198
3224
|
children: categoryLabel
|
|
3199
3225
|
}), sizeLabel ? /* @__PURE__ */ jsx("span", {
|
|
3200
|
-
className: cn("inline-flex items-center rounded-full px-2 py-1 text-[10px] font-medium text-white/92 backdrop-blur-sm", isUser ? "bg-
|
|
3226
|
+
className: cn("inline-flex items-center rounded-full px-2 py-1 text-[10px] font-medium text-white/92 backdrop-blur-sm", isUser ? "bg-black/28" : "bg-black/46"),
|
|
3201
3227
|
children: sizeLabel
|
|
3202
3228
|
}) : null]
|
|
3203
3229
|
})]
|
|
@@ -3251,7 +3277,7 @@ function renderInlineMediaCard(params) {
|
|
|
3251
3277
|
...mediaMimeType ? { type: mediaMimeType } : {}
|
|
3252
3278
|
})
|
|
3253
3279
|
}) : /* @__PURE__ */ jsx("div", {
|
|
3254
|
-
className: cn("overflow-hidden rounded-[1rem] border", isUser ? "border-
|
|
3280
|
+
className: cn("overflow-hidden rounded-[1rem] border", isUser ? "border-primary-foreground/10 bg-black/26" : "border-border bg-muted"),
|
|
3255
3281
|
children: /* @__PURE__ */ jsx("video", {
|
|
3256
3282
|
controls: true,
|
|
3257
3283
|
preload: "metadata",
|
|
@@ -3275,7 +3301,7 @@ function ChatMessageFile({ file, isUser = false, texts }) {
|
|
|
3275
3301
|
const isInteractive = Boolean(file.dataUrl);
|
|
3276
3302
|
const actionLabel = isInteractive ? texts?.attachmentOpenLabel ?? "Open" : texts?.attachmentAttachedLabel ?? "Attached";
|
|
3277
3303
|
const categoryLabel = readFileCategoryLabel(category, texts);
|
|
3278
|
-
const shellClasses = cn("block overflow-hidden rounded-[1.25rem] border transition duration-200", isUser ? "border-
|
|
3304
|
+
const shellClasses = cn("block overflow-hidden rounded-[1.25rem] border transition duration-200", isUser ? "border-primary-foreground/12 bg-primary-foreground/10 text-primary-foreground" : "border-border bg-card text-card-foreground", isInteractive && (isUser ? "hover:border-primary-foreground/18 hover:bg-primary-foreground/13" : "hover:border-border-hover hover:bg-accent"));
|
|
3279
3305
|
if (renderAsImage) return renderImagePreview({
|
|
3280
3306
|
file,
|
|
3281
3307
|
categoryLabel,
|
|
@@ -3431,14 +3457,14 @@ function ChatReasoningBlock({ label, text, isUser, isInProgress }) {
|
|
|
3431
3457
|
className: "mt-2",
|
|
3432
3458
|
open: isOpen,
|
|
3433
3459
|
children: [/* @__PURE__ */ jsx("summary", {
|
|
3434
|
-
className: cn("cursor-pointer text-xs", isUser ? "text-primary-100" : "text-
|
|
3460
|
+
className: cn("cursor-pointer text-xs", isUser ? "text-primary-100" : "text-muted-foreground"),
|
|
3435
3461
|
onClick: onSummaryClick,
|
|
3436
3462
|
children: displayLabel
|
|
3437
3463
|
}), /* @__PURE__ */ jsx("div", {
|
|
3438
3464
|
ref: scrollRef,
|
|
3439
3465
|
onScroll,
|
|
3440
3466
|
"data-reasoning-scroll": "true",
|
|
3441
|
-
className: cn("mt-2 w-fit max-w-[500px] max-h-56 overflow-y-auto rounded-lg custom-scrollbar
|
|
3467
|
+
className: cn("mt-2 w-fit max-w-[500px] max-h-56 overflow-y-auto rounded-lg custom-scrollbar", isUser ? "bg-primary/70" : "bg-muted"),
|
|
3442
3468
|
children: /* @__PURE__ */ jsx("pre", {
|
|
3443
3469
|
className: "min-w-0 whitespace-pre-wrap break-all p-2 text-[11px]",
|
|
3444
3470
|
children: text
|
|
@@ -3450,13 +3476,13 @@ function ChatReasoningBlock({ label, text, isUser, isInProgress }) {
|
|
|
3450
3476
|
//#region src/components/chat/ui/chat-message-list/tool-card/tool-card-root.tsx
|
|
3451
3477
|
function ToolCardRoot({ children, className }) {
|
|
3452
3478
|
return /* @__PURE__ */ jsx("div", {
|
|
3453
|
-
className: cn("my-2 rounded-lg border border-
|
|
3479
|
+
className: cn("my-2 rounded-lg border border-border bg-card shadow-sm overflow-hidden text-[12px] text-card-foreground", "w-[280px] sm:w-[360px] md:w-[480px] min-w-full max-w-full transition-all flex flex-col", className),
|
|
3454
3480
|
children
|
|
3455
3481
|
});
|
|
3456
3482
|
}
|
|
3457
3483
|
function ToolCardContent({ children, className }) {
|
|
3458
3484
|
return /* @__PURE__ */ jsx("div", {
|
|
3459
|
-
className: cn("border-t border-
|
|
3485
|
+
className: cn("border-t border-border bg-muted/35 px-3 pt-1 pb-2 w-full overflow-hidden", className),
|
|
3460
3486
|
children
|
|
3461
3487
|
});
|
|
3462
3488
|
}
|
|
@@ -3464,22 +3490,22 @@ function ToolCardContent({ children, className }) {
|
|
|
3464
3490
|
//#region src/components/chat/ui/chat-message-list/tool-card/tool-card-status.tsx
|
|
3465
3491
|
const STATUS_STYLES = {
|
|
3466
3492
|
running: {
|
|
3467
|
-
text: "text-
|
|
3493
|
+
text: "text-primary/70",
|
|
3468
3494
|
icon: Loader2,
|
|
3469
3495
|
spin: true
|
|
3470
3496
|
},
|
|
3471
3497
|
success: {
|
|
3472
|
-
text: "text-
|
|
3498
|
+
text: "text-primary/70",
|
|
3473
3499
|
icon: Check,
|
|
3474
3500
|
spin: false
|
|
3475
3501
|
},
|
|
3476
3502
|
error: {
|
|
3477
|
-
text: "text-
|
|
3503
|
+
text: "text-destructive",
|
|
3478
3504
|
icon: AlertTriangle,
|
|
3479
3505
|
spin: false
|
|
3480
3506
|
},
|
|
3481
3507
|
cancelled: {
|
|
3482
|
-
text: "text-
|
|
3508
|
+
text: "text-muted-foreground",
|
|
3483
3509
|
icon: Minus,
|
|
3484
3510
|
spin: false
|
|
3485
3511
|
}
|
|
@@ -3501,12 +3527,12 @@ function resolveToolCardActionView(action) {
|
|
|
3501
3527
|
if (action.kind === "show-content") return {
|
|
3502
3528
|
icon: Eye,
|
|
3503
3529
|
label: action.label,
|
|
3504
|
-
toneClassName: "border-
|
|
3530
|
+
toneClassName: "border-border bg-card text-foreground hover:bg-accent hover:text-accent-foreground focus-visible:ring-primary/35"
|
|
3505
3531
|
};
|
|
3506
3532
|
return {
|
|
3507
3533
|
icon: ArrowUpRight,
|
|
3508
3534
|
label: action.label ?? (action.sessionKind === "child" ? "Open child session" : "Open session"),
|
|
3509
|
-
toneClassName: "border-
|
|
3535
|
+
toneClassName: "border-border bg-card text-foreground hover:bg-accent hover:text-accent-foreground focus-visible:ring-primary/35"
|
|
3510
3536
|
};
|
|
3511
3537
|
}
|
|
3512
3538
|
function ToolCardActionButton({ action, onAction }) {
|
|
@@ -3542,12 +3568,12 @@ function ToolCardActionButton({ action, onAction }) {
|
|
|
3542
3568
|
function ToolCardHeader({ card, icon: Icon, expanded, canExpand, hideSummary = false, actionSlot, onToggle }) {
|
|
3543
3569
|
const summaryPart = hideSummary ? "" : card.summary?.replace(/^(command|path|args|query|input):\s*/i, "") ?? "";
|
|
3544
3570
|
return /* @__PURE__ */ jsxs("div", {
|
|
3545
|
-
className: cn("flex items-center gap-3 px-3 py-2.5 transition-colors bg-transparent", canExpand ? "cursor-pointer hover:bg-
|
|
3571
|
+
className: cn("flex items-center gap-3 px-3 py-2.5 transition-colors bg-transparent", canExpand ? "cursor-pointer hover:bg-accent/70" : ""),
|
|
3546
3572
|
onClick: onToggle,
|
|
3547
3573
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
3548
|
-
className: "flex min-w-0 flex-1 items-center gap-2 overflow-hidden font-mono text-
|
|
3574
|
+
className: "flex min-w-0 flex-1 items-center gap-2 overflow-hidden font-mono text-foreground",
|
|
3549
3575
|
children: [/* @__PURE__ */ jsx(Icon, {
|
|
3550
|
-
className: "h-4 w-4 text-
|
|
3576
|
+
className: "h-4 w-4 text-primary/70 shrink-0",
|
|
3551
3577
|
strokeWidth: 3
|
|
3552
3578
|
}), /* @__PURE__ */ jsxs("div", {
|
|
3553
3579
|
className: "flex min-w-0 flex-1 items-center gap-1.5 overflow-hidden",
|
|
@@ -3555,10 +3581,10 @@ function ToolCardHeader({ card, icon: Icon, expanded, canExpand, hideSummary = f
|
|
|
3555
3581
|
className: "font-bold shrink-0 tracking-tight",
|
|
3556
3582
|
children: card.toolName
|
|
3557
3583
|
}), summaryPart && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("span", {
|
|
3558
|
-
className: "text-
|
|
3584
|
+
className: "text-muted-foreground/45 font-bold select-none shrink-0",
|
|
3559
3585
|
children: "›"
|
|
3560
3586
|
}), /* @__PURE__ */ jsx("span", {
|
|
3561
|
-
className: "block min-w-0 flex-1 truncate font-normal",
|
|
3587
|
+
className: "block min-w-0 flex-1 truncate font-normal text-muted-foreground",
|
|
3562
3588
|
title: summaryPart,
|
|
3563
3589
|
children: summaryPart
|
|
3564
3590
|
})] })]
|
|
@@ -3569,10 +3595,10 @@ function ToolCardHeader({ card, icon: Icon, expanded, canExpand, hideSummary = f
|
|
|
3569
3595
|
actionSlot,
|
|
3570
3596
|
/* @__PURE__ */ jsx(ToolStatusLabel, { card }),
|
|
3571
3597
|
canExpand && (expanded ? /* @__PURE__ */ jsx(ChevronDown, {
|
|
3572
|
-
className: "h-4 w-4 text-
|
|
3598
|
+
className: "h-4 w-4 text-muted-foreground",
|
|
3573
3599
|
strokeWidth: 3
|
|
3574
3600
|
}) : /* @__PURE__ */ jsx(ChevronRight, {
|
|
3575
|
-
className: "h-4 w-4 text-
|
|
3601
|
+
className: "h-4 w-4 text-muted-foreground",
|
|
3576
3602
|
strokeWidth: 3
|
|
3577
3603
|
}))
|
|
3578
3604
|
]
|
|
@@ -3616,12 +3642,12 @@ function readCodeColumnWidth(block) {
|
|
|
3616
3642
|
function getLineNumberTone(line) {
|
|
3617
3643
|
if (line.kind === "remove") return "border-r border-rose-200 bg-rose-50 text-rose-700";
|
|
3618
3644
|
if (line.kind === "add") return "border-r border-emerald-200 bg-emerald-50 text-emerald-700";
|
|
3619
|
-
return "border-r border-
|
|
3645
|
+
return "border-r border-border bg-muted text-muted-foreground";
|
|
3620
3646
|
}
|
|
3621
3647
|
function getCodeRowTone(line) {
|
|
3622
3648
|
if (line.kind === "remove") return "bg-rose-50 text-rose-950";
|
|
3623
3649
|
if (line.kind === "add") return "bg-emerald-50 text-emerald-950";
|
|
3624
|
-
return "bg-
|
|
3650
|
+
return "bg-card text-foreground";
|
|
3625
3651
|
}
|
|
3626
3652
|
function FileOperationLineNumberCell({ layout, line, lineNumberColumnWidth }) {
|
|
3627
3653
|
return /* @__PURE__ */ jsx("span", {
|
|
@@ -3659,7 +3685,7 @@ function FileOperationWorkspaceSurface({ block }) {
|
|
|
3659
3685
|
return /* @__PURE__ */ jsxs("div", {
|
|
3660
3686
|
"data-file-code-surface": "true",
|
|
3661
3687
|
"data-file-code-surface-layout": "workspace",
|
|
3662
|
-
className: "flex h-full min-h-full min-w-full bg-
|
|
3688
|
+
className: "flex h-full min-h-full min-w-full bg-card",
|
|
3663
3689
|
children: [showLineNumbers ? /* @__PURE__ */ jsxs("div", {
|
|
3664
3690
|
"data-file-code-gutter": "true",
|
|
3665
3691
|
style: {
|
|
@@ -3671,10 +3697,10 @@ function FileOperationWorkspaceSurface({ block }) {
|
|
|
3671
3697
|
layout: "workspace",
|
|
3672
3698
|
line,
|
|
3673
3699
|
lineNumberColumnWidth
|
|
3674
|
-
}, readLineKey("gutter", line, index))), /* @__PURE__ */ jsx("div", { className: "min-h-0 flex-1 border-r border-
|
|
3700
|
+
}, readLineKey("gutter", line, index))), /* @__PURE__ */ jsx("div", { className: "min-h-0 flex-1 border-r border-border bg-muted" })]
|
|
3675
3701
|
}) : null, /* @__PURE__ */ jsxs("div", {
|
|
3676
3702
|
"data-file-code-canvas": "true",
|
|
3677
|
-
className: "flex h-full min-h-full min-w-0 flex-1 flex-col bg-
|
|
3703
|
+
className: "flex h-full min-h-full min-w-0 flex-1 flex-col bg-card",
|
|
3678
3704
|
children: [/* @__PURE__ */ jsx("div", {
|
|
3679
3705
|
"data-file-code-stack": "true",
|
|
3680
3706
|
className: "min-w-full",
|
|
@@ -3684,7 +3710,7 @@ function FileOperationWorkspaceSurface({ block }) {
|
|
|
3684
3710
|
className: FILE_ROW_CLASS_NAME,
|
|
3685
3711
|
children: /* @__PURE__ */ jsx(FileOperationCodeCell, { line })
|
|
3686
3712
|
}, readLineKey("code", line, index)))
|
|
3687
|
-
}), /* @__PURE__ */ jsx("div", { className: "min-h-0 flex-1 bg-
|
|
3713
|
+
}), /* @__PURE__ */ jsx("div", { className: "min-h-0 flex-1 bg-card" })]
|
|
3688
3714
|
})]
|
|
3689
3715
|
});
|
|
3690
3716
|
}
|
|
@@ -3697,7 +3723,7 @@ function FileOperationCodeSurface({ block, layout = "compact" }) {
|
|
|
3697
3723
|
return /* @__PURE__ */ jsx("div", {
|
|
3698
3724
|
"data-file-code-surface": "true",
|
|
3699
3725
|
"data-file-code-surface-layout": "compact",
|
|
3700
|
-
className: "overflow-x-auto custom-scrollbar
|
|
3726
|
+
className: "overflow-x-auto custom-scrollbar bg-card",
|
|
3701
3727
|
children: /* @__PURE__ */ jsx("div", {
|
|
3702
3728
|
"data-file-code-stack": "true",
|
|
3703
3729
|
className: "min-w-full",
|
|
@@ -3733,7 +3759,7 @@ function readFileOperationContentVersion(block) {
|
|
|
3733
3759
|
function getCaptionTone(part) {
|
|
3734
3760
|
if (/^\+\d+$/.test(part)) return "text-emerald-700";
|
|
3735
3761
|
if (/^-\d+$/.test(part)) return "text-rose-700";
|
|
3736
|
-
return "text-
|
|
3762
|
+
return "text-muted-foreground";
|
|
3737
3763
|
}
|
|
3738
3764
|
function renderCaption(caption) {
|
|
3739
3765
|
const parts = caption.split("·").map((part) => part.trim()).filter((part) => /^\+\d+$/.test(part) || /^-\d+$/.test(part));
|
|
@@ -3741,7 +3767,7 @@ function renderCaption(caption) {
|
|
|
3741
3767
|
return /* @__PURE__ */ jsx("div", {
|
|
3742
3768
|
className: "flex shrink-0 items-center gap-x-1 whitespace-nowrap text-[10px] font-medium uppercase tracking-[0.08em]",
|
|
3743
3769
|
children: parts.map((part, index) => /* @__PURE__ */ jsxs(Fragment, { children: [index > 0 ? /* @__PURE__ */ jsx("span", {
|
|
3744
|
-
className: "text-
|
|
3770
|
+
className: "text-muted-foreground/45",
|
|
3745
3771
|
children: "·"
|
|
3746
3772
|
}) : null, /* @__PURE__ */ jsx("span", {
|
|
3747
3773
|
className: cn(getCaptionTone(part)),
|
|
@@ -3777,7 +3803,7 @@ function StickyFileOperationScrollArea({ children, contentVersion, resetKey, cla
|
|
|
3777
3803
|
ref: scrollRef,
|
|
3778
3804
|
onScroll,
|
|
3779
3805
|
"data-file-scroll-kind": scrollKind,
|
|
3780
|
-
className: cn("overflow-y-auto bg-
|
|
3806
|
+
className: cn("overflow-y-auto bg-card custom-scrollbar", className),
|
|
3781
3807
|
children
|
|
3782
3808
|
});
|
|
3783
3809
|
}
|
|
@@ -3790,10 +3816,10 @@ function FileOperationBlock({ block, showPathRow, isFirst, onFileOpen }) {
|
|
|
3790
3816
|
onFileOpen(buildFileOpenAction(block));
|
|
3791
3817
|
};
|
|
3792
3818
|
return /* @__PURE__ */ jsxs("section", {
|
|
3793
|
-
className: cn("overflow-hidden bg-
|
|
3819
|
+
className: cn("overflow-hidden bg-card", !isFirst && "border-t border-border"),
|
|
3794
3820
|
children: [
|
|
3795
3821
|
showMetaRow ? /* @__PURE__ */ jsxs("div", {
|
|
3796
|
-
className: cn("flex items-center justify-between gap-4 border-b border-
|
|
3822
|
+
className: cn("flex items-center justify-between gap-4 border-b border-border px-4 text-muted-foreground", showPathRow ? "py-2" : "py-1.5"),
|
|
3797
3823
|
children: [/* @__PURE__ */ jsx("div", {
|
|
3798
3824
|
className: "min-w-0 flex-1",
|
|
3799
3825
|
children: showPathRow ? /* @__PURE__ */ jsx(TooltipProvider, {
|
|
@@ -3803,7 +3829,7 @@ function FileOperationBlock({ block, showPathRow, isFirst, onFileOpen }) {
|
|
|
3803
3829
|
children: /* @__PURE__ */ jsx("button", {
|
|
3804
3830
|
type: "button",
|
|
3805
3831
|
onClick: handlePathClick,
|
|
3806
|
-
className: cn("w-full truncate whitespace-nowrap text-left font-mono text-[12px] font-medium text-
|
|
3832
|
+
className: cn("w-full truncate whitespace-nowrap text-left font-mono text-[12px] font-medium text-foreground", onFileOpen && "transition-colors hover:text-primary hover:underline"),
|
|
3807
3833
|
title: block.path,
|
|
3808
3834
|
children: block.path
|
|
3809
3835
|
})
|
|
@@ -3827,15 +3853,15 @@ function FileOperationBlock({ block, showPathRow, isFirst, onFileOpen }) {
|
|
|
3827
3853
|
className: "max-h-72",
|
|
3828
3854
|
scrollKind: "raw",
|
|
3829
3855
|
children: /* @__PURE__ */ jsx("div", {
|
|
3830
|
-
className: "overflow-x-auto custom-scrollbar
|
|
3856
|
+
className: "overflow-x-auto custom-scrollbar",
|
|
3831
3857
|
children: /* @__PURE__ */ jsx("pre", {
|
|
3832
|
-
className: "min-w-max whitespace-pre bg-
|
|
3858
|
+
className: "min-w-max whitespace-pre bg-card px-4 py-2 font-mono text-[11px] leading-5 text-foreground",
|
|
3833
3859
|
children: block.rawText
|
|
3834
3860
|
})
|
|
3835
3861
|
})
|
|
3836
3862
|
}) : null,
|
|
3837
3863
|
block.truncated && !previewBlock ? /* @__PURE__ */ jsx("div", {
|
|
3838
|
-
className: "border-t border-
|
|
3864
|
+
className: "border-t border-border bg-muted px-4 py-2 text-[10px] text-muted-foreground",
|
|
3839
3865
|
children: "Showing a shortened diff preview."
|
|
3840
3866
|
}) : null
|
|
3841
3867
|
]
|
|
@@ -3846,7 +3872,7 @@ function ToolCardFileOperationContent({ card, className, onFileOpen }) {
|
|
|
3846
3872
|
const output = card.output?.trim() ?? "";
|
|
3847
3873
|
if (blocks.length === 0 && !output) return null;
|
|
3848
3874
|
return /* @__PURE__ */ jsxs("div", {
|
|
3849
|
-
className: cn("overflow-hidden bg-
|
|
3875
|
+
className: cn("overflow-hidden bg-card", className),
|
|
3850
3876
|
children: [blocks.map((block, index) => {
|
|
3851
3877
|
return /* @__PURE__ */ jsx(FileOperationBlock, {
|
|
3852
3878
|
block,
|
|
@@ -3857,12 +3883,12 @@ function ToolCardFileOperationContent({ card, className, onFileOpen }) {
|
|
|
3857
3883
|
}), output ? /* @__PURE__ */ jsx(StickyFileOperationScrollArea, {
|
|
3858
3884
|
resetKey: `output:${card.toolName}:${card.summary ?? "none"}`,
|
|
3859
3885
|
contentVersion: output,
|
|
3860
|
-
className: cn("max-h-56", blocks.length > 0 && "border-t border-
|
|
3886
|
+
className: cn("max-h-56", blocks.length > 0 && "border-t border-border"),
|
|
3861
3887
|
scrollKind: "output",
|
|
3862
3888
|
children: /* @__PURE__ */ jsx("div", {
|
|
3863
|
-
className: "overflow-x-auto custom-scrollbar
|
|
3889
|
+
className: "overflow-x-auto custom-scrollbar",
|
|
3864
3890
|
children: /* @__PURE__ */ jsx("pre", {
|
|
3865
|
-
className: "min-w-max whitespace-pre bg-
|
|
3891
|
+
className: "min-w-max whitespace-pre bg-card px-4 py-2 font-mono text-[11px] leading-5 text-foreground",
|
|
3866
3892
|
children: output
|
|
3867
3893
|
})
|
|
3868
3894
|
})
|
|
@@ -3978,16 +4004,16 @@ function useToolCardExpandedState({ canExpand, isRunning, autoExpandWhileRunning
|
|
|
3978
4004
|
function GenericToolSection({ label, tone, children }) {
|
|
3979
4005
|
const style = {
|
|
3980
4006
|
input: {
|
|
3981
|
-
shell: "border-
|
|
3982
|
-
header: "border-
|
|
3983
|
-
dot: "bg-
|
|
3984
|
-
body: "text-
|
|
4007
|
+
shell: "border-border bg-card",
|
|
4008
|
+
header: "border-border bg-muted/55 text-muted-foreground",
|
|
4009
|
+
dot: "bg-muted-foreground/60",
|
|
4010
|
+
body: "text-foreground"
|
|
3985
4011
|
},
|
|
3986
4012
|
output: {
|
|
3987
|
-
shell: "border-
|
|
3988
|
-
header: "border-
|
|
3989
|
-
dot: "bg-
|
|
3990
|
-
body: "text-
|
|
4013
|
+
shell: "border-border bg-card",
|
|
4014
|
+
header: "border-border bg-muted/55 text-muted-foreground",
|
|
4015
|
+
dot: "bg-primary/70",
|
|
4016
|
+
body: "text-foreground"
|
|
3991
4017
|
},
|
|
3992
4018
|
error: {
|
|
3993
4019
|
shell: "border-rose-200/80 bg-rose-50/85",
|
|
@@ -4004,7 +4030,7 @@ function GenericToolSection({ label, tone, children }) {
|
|
|
4004
4030
|
}), /* @__PURE__ */ jsx("div", {
|
|
4005
4031
|
className: "w-full overflow-hidden",
|
|
4006
4032
|
children: /* @__PURE__ */ jsx("pre", {
|
|
4007
|
-
className: cn("w-full max-w-full min-w-0 max-h-64 overflow-x-auto overflow-y-auto px-3 py-2.5 font-mono text-[12px] leading-relaxed whitespace-pre custom-scrollbar
|
|
4033
|
+
className: cn("w-full max-w-full min-w-0 max-h-64 overflow-x-auto overflow-y-auto px-3 py-2.5 font-mono text-[12px] leading-relaxed whitespace-pre custom-scrollbar", style.body),
|
|
4008
4034
|
children
|
|
4009
4035
|
})
|
|
4010
4036
|
})]
|
|
@@ -4029,23 +4055,23 @@ function TerminalExecutionView({ card }) {
|
|
|
4029
4055
|
canExpand: output.trim().length > 0 || isRunning,
|
|
4030
4056
|
onToggle
|
|
4031
4057
|
}), expanded && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("div", {
|
|
4032
|
-
className: "px-3 pb-2 font-mono w-full max-h-48 overflow-y-auto custom-scrollbar
|
|
4058
|
+
className: "px-3 pb-2 font-mono w-full max-h-48 overflow-y-auto custom-scrollbar min-h-0 text-[12px]",
|
|
4033
4059
|
children: /* @__PURE__ */ jsxs("div", {
|
|
4034
4060
|
className: "flex items-start gap-2 leading-relaxed",
|
|
4035
4061
|
children: [/* @__PURE__ */ jsx("span", {
|
|
4036
|
-
className: "text-
|
|
4062
|
+
className: "text-primary/55 font-medium shrink-0 select-none mt-[1px]",
|
|
4037
4063
|
children: "$"
|
|
4038
4064
|
}), /* @__PURE__ */ jsx("div", {
|
|
4039
4065
|
className: "flex-1 min-w-0",
|
|
4040
4066
|
children: commandPart ? /* @__PURE__ */ jsxs("div", {
|
|
4041
|
-
className: "text-
|
|
4042
|
-
children: [commandPart, isRunning && !output && /* @__PURE__ */ jsx("span", { className: "inline-block w-1.5 h-3 ml-1 bg-
|
|
4043
|
-
}) : /* @__PURE__ */ jsx("div", { className: "h-3 w-32 bg-
|
|
4067
|
+
className: "text-foreground break-words whitespace-pre-wrap tracking-tight font-medium inline-block",
|
|
4068
|
+
children: [commandPart, isRunning && !output && /* @__PURE__ */ jsx("span", { className: "inline-block w-1.5 h-3 ml-1 bg-primary/60 animate-pulse align-middle" })]
|
|
4069
|
+
}) : /* @__PURE__ */ jsx("div", { className: "h-3 w-32 bg-muted rounded animate-pulse mt-2" })
|
|
4044
4070
|
})]
|
|
4045
4071
|
})
|
|
4046
4072
|
}), output && /* @__PURE__ */ jsx(ToolCardContent, { children: /* @__PURE__ */ jsxs("pre", {
|
|
4047
|
-
className: "font-mono text-[12px] text-
|
|
4048
|
-
children: [output, isRunning && /* @__PURE__ */ jsx("span", { className: "inline-block w-1.5 h-3 ml-1 bg-
|
|
4073
|
+
className: "font-mono text-[12px] text-muted-foreground whitespace-pre-wrap break-all w-full max-w-full max-h-64 overflow-y-auto overflow-x-hidden min-w-0 custom-scrollbar leading-relaxed px-0",
|
|
4074
|
+
children: [output, isRunning && /* @__PURE__ */ jsx("span", { className: "inline-block w-1.5 h-3 ml-1 bg-primary/60 animate-pulse align-middle" })]
|
|
4049
4075
|
}) })] })] });
|
|
4050
4076
|
}
|
|
4051
4077
|
function FileOperationView({ card, onFileOpen }) {
|
|
@@ -4075,7 +4101,7 @@ function FileOperationView({ card, onFileOpen }) {
|
|
|
4075
4101
|
hideSummary: expanded && hasStructuredPreview,
|
|
4076
4102
|
onToggle
|
|
4077
4103
|
}), expanded && hasContent && /* @__PURE__ */ jsx(ToolCardContent, {
|
|
4078
|
-
className: "border-t border-
|
|
4104
|
+
className: "border-t border-border bg-transparent px-0 pt-0 pb-0",
|
|
4079
4105
|
children: /* @__PURE__ */ jsx(ToolCardFileOperationContent, {
|
|
4080
4106
|
card,
|
|
4081
4107
|
onFileOpen
|
|
@@ -4098,7 +4124,7 @@ function SearchSnippetView({ card }) {
|
|
|
4098
4124
|
canExpand: !!output || isRunning,
|
|
4099
4125
|
onToggle
|
|
4100
4126
|
}), expanded && output && /* @__PURE__ */ jsx(ToolCardContent, { children: /* @__PURE__ */ jsx("pre", {
|
|
4101
|
-
className: "font-mono text-[12px] text-
|
|
4127
|
+
className: "font-mono text-[12px] text-muted-foreground whitespace-pre-wrap break-all w-full max-w-full max-h-64 overflow-y-auto overflow-x-hidden min-w-0 custom-scrollbar leading-relaxed",
|
|
4102
4128
|
children: output
|
|
4103
4129
|
}) })] });
|
|
4104
4130
|
}
|
|
@@ -4197,7 +4223,7 @@ const ChatMessage = memo(function ChatMessage({ message, texts, onToolAction, on
|
|
|
4197
4223
|
const isUser = role === "user";
|
|
4198
4224
|
const isMessageInProgress = message.status === "pending" || message.status === "streaming";
|
|
4199
4225
|
return /* @__PURE__ */ jsx("div", {
|
|
4200
|
-
className: cn("inline-block w-fit max-w-full rounded-2xl border px-4 shadow-sm", isUser ? "border-primary bg-primary py-3 text-
|
|
4226
|
+
className: cn("inline-block w-fit max-w-full rounded-2xl border px-4 shadow-sm", isUser ? "border-primary bg-primary py-3 text-primary-foreground" : role === "assistant" ? "border-border bg-card pb-3 pt-4 text-card-foreground" : "border-border bg-muted/45 py-3 text-foreground"),
|
|
4201
4227
|
children: /* @__PURE__ */ jsx("div", {
|
|
4202
4228
|
className: "space-y-2",
|
|
4203
4229
|
children: message.parts.map((part, index) => {
|
|
@@ -4245,16 +4271,16 @@ const ChatMessage = memo(function ChatMessage({ message, texts, onToolAction, on
|
|
|
4245
4271
|
if (type === "unknown") {
|
|
4246
4272
|
const { label, rawType, text } = part;
|
|
4247
4273
|
return /* @__PURE__ */ jsxs("div", {
|
|
4248
|
-
className: "rounded-lg border border-
|
|
4274
|
+
className: "rounded-lg border border-border bg-muted/60 px-2.5 py-2 text-xs text-muted-foreground",
|
|
4249
4275
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
4250
|
-
className: "font-semibold text-
|
|
4276
|
+
className: "font-semibold text-foreground",
|
|
4251
4277
|
children: [
|
|
4252
4278
|
label,
|
|
4253
4279
|
": ",
|
|
4254
4280
|
rawType
|
|
4255
4281
|
]
|
|
4256
4282
|
}), text ? /* @__PURE__ */ jsx("pre", {
|
|
4257
|
-
className: "mt-1 whitespace-pre-wrap break-words text-[11px] text-
|
|
4283
|
+
className: "mt-1 whitespace-pre-wrap break-words text-[11px] text-muted-foreground",
|
|
4258
4284
|
children: text
|
|
4259
4285
|
}) : null]
|
|
4260
4286
|
}, `unknown-${index}`);
|
|
@@ -4279,7 +4305,7 @@ function ChatMessageActionCopy({ message, texts }) {
|
|
|
4279
4305
|
return /* @__PURE__ */ jsx("button", {
|
|
4280
4306
|
type: "button",
|
|
4281
4307
|
onClick: () => void copy(),
|
|
4282
|
-
className: "text-
|
|
4308
|
+
className: "text-muted-foreground hover:text-foreground transition-colors p-1 rounded-md hover:bg-accent flex items-center justify-center",
|
|
4283
4309
|
"aria-label": copied ? texts.copiedMessageLabel : texts.copyMessageLabel,
|
|
4284
4310
|
title: copied ? texts.copiedMessageLabel : texts.copyMessageLabel,
|
|
4285
4311
|
children: copied ? /* @__PURE__ */ jsx(Check, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ jsx(Copy, { className: "h-3.5 w-3.5" })
|
|
@@ -4301,13 +4327,13 @@ const TYPING_TEXT_SHEEN_CSS = `
|
|
|
4301
4327
|
.nextclaw-chat-typing-indicator__text {
|
|
4302
4328
|
background-image: linear-gradient(
|
|
4303
4329
|
100deg,
|
|
4304
|
-
|
|
4305
|
-
|
|
4306
|
-
|
|
4307
|
-
|
|
4308
|
-
|
|
4309
|
-
|
|
4310
|
-
|
|
4330
|
+
hsl(var(--muted-foreground)) 0%,
|
|
4331
|
+
hsl(var(--muted-foreground)) 34%,
|
|
4332
|
+
hsl(var(--foreground-tertiary)) 43%,
|
|
4333
|
+
hsl(var(--foreground-muted)) 50%,
|
|
4334
|
+
hsl(var(--foreground-tertiary)) 57%,
|
|
4335
|
+
hsl(var(--muted-foreground)) 66%,
|
|
4336
|
+
hsl(var(--muted-foreground)) 100%
|
|
4311
4337
|
);
|
|
4312
4338
|
background-size: 240% 100%;
|
|
4313
4339
|
background-position: 160% 0;
|
|
@@ -4322,7 +4348,7 @@ const TYPING_TEXT_SHEEN_CSS = `
|
|
|
4322
4348
|
.nextclaw-chat-typing-indicator__text {
|
|
4323
4349
|
animation: none;
|
|
4324
4350
|
background-image: none;
|
|
4325
|
-
color:
|
|
4351
|
+
color: hsl(var(--muted-foreground));
|
|
4326
4352
|
-webkit-text-fill-color: currentColor;
|
|
4327
4353
|
}
|
|
4328
4354
|
}
|
|
@@ -4340,20 +4366,20 @@ function hasRenderableMessageContent(message) {
|
|
|
4340
4366
|
}
|
|
4341
4367
|
function ChatMessageTypingFooter() {
|
|
4342
4368
|
return /* @__PURE__ */ jsx("div", {
|
|
4343
|
-
className: "flex items-center gap-2 px-1 py-0.5 text-[11px] text-
|
|
4369
|
+
className: "flex items-center gap-2 px-1 py-0.5 text-[11px] text-muted-foreground",
|
|
4344
4370
|
children: /* @__PURE__ */ jsxs("div", {
|
|
4345
4371
|
className: "flex space-x-1 items-center h-full",
|
|
4346
4372
|
children: [
|
|
4347
|
-
/* @__PURE__ */ jsx("div", { className: "h-1.5 w-1.5 rounded-full bg-
|
|
4348
|
-
/* @__PURE__ */ jsx("div", { className: "h-1.5 w-1.5 rounded-full bg-
|
|
4349
|
-
/* @__PURE__ */ jsx("div", { className: "h-1.5 w-1.5 rounded-full bg-
|
|
4373
|
+
/* @__PURE__ */ jsx("div", { className: "h-1.5 w-1.5 rounded-full bg-muted-foreground animate-pulse" }),
|
|
4374
|
+
/* @__PURE__ */ jsx("div", { className: "h-1.5 w-1.5 rounded-full bg-muted-foreground animate-pulse [animation-delay:200ms]" }),
|
|
4375
|
+
/* @__PURE__ */ jsx("div", { className: "h-1.5 w-1.5 rounded-full bg-muted-foreground animate-pulse [animation-delay:400ms]" })
|
|
4350
4376
|
]
|
|
4351
4377
|
})
|
|
4352
4378
|
});
|
|
4353
4379
|
}
|
|
4354
4380
|
function ChatTypingIndicator({ label }) {
|
|
4355
4381
|
return /* @__PURE__ */ jsxs("div", {
|
|
4356
|
-
className: "rounded-2xl border border-
|
|
4382
|
+
className: "rounded-2xl border border-border bg-card px-4 py-3 text-sm text-muted-foreground shadow-sm",
|
|
4357
4383
|
children: [/* @__PURE__ */ jsx("style", { children: TYPING_TEXT_SHEEN_CSS }), /* @__PURE__ */ jsx("span", {
|
|
4358
4384
|
className: "nextclaw-chat-typing-indicator__text",
|
|
4359
4385
|
children: label
|
|
@@ -4384,7 +4410,7 @@ function ChatMessageList({ className, isSending, messages, onFileOpen, onToolAct
|
|
|
4384
4410
|
}), /* @__PURE__ */ jsx("div", {
|
|
4385
4411
|
className: cn("flex items-center gap-2", isUser && "justify-end"),
|
|
4386
4412
|
children: isGenerating ? /* @__PURE__ */ jsx(ChatMessageTypingFooter, {}) : /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("div", {
|
|
4387
|
-
className: cn("px-1 text-[11px] leading-4 text-
|
|
4413
|
+
className: cn("px-1 text-[11px] leading-4 text-muted-foreground", isUser ? "text-right" : "text-left"),
|
|
4388
4414
|
children: [
|
|
4389
4415
|
message.roleLabel,
|
|
4390
4416
|
" · ",
|