@nextclaw/agent-chat-ui 0.3.16 → 0.3.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +1 -0
- package/dist/index.js +72 -17
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -146,6 +146,7 @@ type ChatSlashMenuProps = {
|
|
|
146
146
|
texts: Pick<ChatTexts, "slashLoadingLabel" | "slashSectionLabel" | "slashEmptyLabel" | "slashHintLabel" | "slashSkillHintLabel">;
|
|
147
147
|
onSelectItem: (item: ChatSlashItem) => void;
|
|
148
148
|
onOpenChange: (open: boolean) => void;
|
|
149
|
+
onDetailsPointerDown?: () => void;
|
|
149
150
|
onSetActiveIndex: (index: number) => void;
|
|
150
151
|
};
|
|
151
152
|
type ChatInputBarProps = {
|
package/dist/index.js
CHANGED
|
@@ -208,7 +208,7 @@ function ChatSlashMenu(props) {
|
|
|
208
208
|
const { Popover, PopoverAnchor, PopoverContent } = ChatUiPrimitives;
|
|
209
209
|
const { elementRef: anchorRef, width: panelWidth } = useElementWidth();
|
|
210
210
|
const listRef = useRef(null);
|
|
211
|
-
const { isOpen, isLoading, items, activeIndex, activeItem, texts, onSelectItem, onOpenChange, onSetActiveIndex } = props;
|
|
211
|
+
const { isOpen, isLoading, items, activeIndex, activeItem, texts, onSelectItem, onOpenChange, onDetailsPointerDown, onSetActiveIndex } = props;
|
|
212
212
|
const resolvedWidth = useMemo(() => {
|
|
213
213
|
if (!panelWidth) return;
|
|
214
214
|
return Math.min(panelWidth > SLASH_PANEL_DESKTOP_MIN_WIDTH ? panelWidth * SLASH_PANEL_DESKTOP_SHRINK_RATIO : panelWidth, SLASH_PANEL_MAX_WIDTH);
|
|
@@ -276,6 +276,7 @@ function ChatSlashMenu(props) {
|
|
|
276
276
|
})] })
|
|
277
277
|
}), /* @__PURE__ */ jsx("div", {
|
|
278
278
|
className: "min-w-0 p-2.5",
|
|
279
|
+
onPointerDown: onDetailsPointerDown,
|
|
279
280
|
children: activeItem ? /* @__PURE__ */ jsxs("div", {
|
|
280
281
|
className: "space-y-3",
|
|
281
282
|
children: [
|
|
@@ -630,13 +631,11 @@ function ChatInputBarSkillPicker(props) {
|
|
|
630
631
|
visibleIndex += 1;
|
|
631
632
|
const isSelected = selectedSet.has(option.key);
|
|
632
633
|
const isActive = index === activeIndex;
|
|
633
|
-
return /* @__PURE__ */ jsxs("
|
|
634
|
-
type: "button",
|
|
634
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
635
635
|
id: `${listId}-option-${index}`,
|
|
636
636
|
role: "option",
|
|
637
637
|
"aria-selected": isSelected,
|
|
638
638
|
"data-skill-index": index,
|
|
639
|
-
onClick: () => onToggleOption(option.key),
|
|
640
639
|
onMouseEnter: () => setActiveIndex(index),
|
|
641
640
|
className: `flex w-full items-center gap-3 px-4 py-2.5 text-left transition-colors ${isActive ? "bg-gray-50" : "hover:bg-gray-50"}`,
|
|
642
641
|
children: [
|
|
@@ -645,7 +644,7 @@ function ChatInputBarSkillPicker(props) {
|
|
|
645
644
|
children: /* @__PURE__ */ jsx(Puzzle, { className: "h-4 w-4" })
|
|
646
645
|
}),
|
|
647
646
|
/* @__PURE__ */ jsxs("div", {
|
|
648
|
-
className: "min-w-0 flex-1",
|
|
647
|
+
className: "min-w-0 flex-1 select-text",
|
|
649
648
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
650
649
|
className: "flex items-center gap-1.5",
|
|
651
650
|
children: [/* @__PURE__ */ jsx("span", {
|
|
@@ -662,7 +661,10 @@ function ChatInputBarSkillPicker(props) {
|
|
|
662
661
|
}),
|
|
663
662
|
/* @__PURE__ */ jsx("div", {
|
|
664
663
|
className: "ml-3 shrink-0",
|
|
665
|
-
children: /* @__PURE__ */ jsx("
|
|
664
|
+
children: /* @__PURE__ */ jsx("button", {
|
|
665
|
+
type: "button",
|
|
666
|
+
"aria-label": `${isSelected ? "Remove" : "Add"} ${option.label}`,
|
|
667
|
+
onClick: () => onToggleOption(option.key),
|
|
666
668
|
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-gray-300 bg-white",
|
|
667
669
|
children: isSelected ? /* @__PURE__ */ jsx(Check, { className: "h-3 w-3" }) : null
|
|
668
670
|
})
|
|
@@ -1879,21 +1881,19 @@ function InputBarHint({ hint }) {
|
|
|
1879
1881
|
}
|
|
1880
1882
|
const ChatInputBar = forwardRef(function ChatInputBar(props, ref) {
|
|
1881
1883
|
const composerRef = useRef(null);
|
|
1882
|
-
const
|
|
1884
|
+
const isSlashMenuInteractionRef = useRef(false);
|
|
1883
1885
|
const [activeSlashIndex, setActiveSlashIndex] = useState(0);
|
|
1884
1886
|
const [activeSlashTriggerStart, setActiveSlashTriggerStart] = useState(null);
|
|
1885
1887
|
const [dismissedSlashTriggerStart, setDismissedSlashTriggerStart] = useState(null);
|
|
1886
1888
|
const isSlashPanelOpen = activeSlashTriggerStart !== null && dismissedSlashTriggerStart !== activeSlashTriggerStart;
|
|
1887
1889
|
const activeSlashItem = props.slashMenu.items[activeSlashIndex] ?? null;
|
|
1890
|
+
const dismissSlashTrigger = () => activeSlashTriggerStart !== null && !isSlashMenuInteractionRef.current ? setDismissedSlashTriggerStart(activeSlashTriggerStart) : void 0;
|
|
1888
1891
|
useEffect(() => {
|
|
1889
1892
|
setActiveSlashIndex((current) => {
|
|
1890
1893
|
if (props.slashMenu.items.length === 0) return 0;
|
|
1891
1894
|
return Math.min(current, props.slashMenu.items.length - 1);
|
|
1892
1895
|
});
|
|
1893
1896
|
}, [props.slashMenu.items.length]);
|
|
1894
|
-
useEffect(() => {
|
|
1895
|
-
if (slashQuery !== null) setActiveSlashIndex(0);
|
|
1896
|
-
}, [slashQuery]);
|
|
1897
1897
|
useEffect(() => {
|
|
1898
1898
|
if (activeSlashTriggerStart === null && dismissedSlashTriggerStart !== null) setDismissedSlashTriggerStart(null);
|
|
1899
1899
|
}, [activeSlashTriggerStart, dismissedSlashTriggerStart]);
|
|
@@ -1936,14 +1936,15 @@ const ChatInputBar = forwardRef(function ChatInputBar(props, ref) {
|
|
|
1936
1936
|
onNodesChange: props.composer.onNodesChange,
|
|
1937
1937
|
onFilesAdd: props.composer.onFilesAdd,
|
|
1938
1938
|
onSlashQueryChange: (query) => {
|
|
1939
|
-
|
|
1939
|
+
if (query === null && isSlashMenuInteractionRef.current) return;
|
|
1940
|
+
if (query !== null) setActiveSlashIndex(0);
|
|
1940
1941
|
props.composer.onSlashQueryChange?.(query);
|
|
1941
1942
|
},
|
|
1942
1943
|
onSlashTriggerChange: (trigger) => {
|
|
1943
1944
|
setActiveSlashTriggerStart(trigger?.start ?? null);
|
|
1944
1945
|
},
|
|
1945
1946
|
onSlashOpenChange: (open) => {
|
|
1946
|
-
if (!open
|
|
1947
|
+
if (!open) dismissSlashTrigger();
|
|
1947
1948
|
},
|
|
1948
1949
|
onSlashActiveIndexChange: setActiveSlashIndex
|
|
1949
1950
|
}), /* @__PURE__ */ jsx(ChatSlashMenu, {
|
|
@@ -1958,7 +1959,13 @@ const ChatInputBar = forwardRef(function ChatInputBar(props, ref) {
|
|
|
1958
1959
|
composerRef.current?.insertSlashItem(item);
|
|
1959
1960
|
},
|
|
1960
1961
|
onOpenChange: (open) => {
|
|
1961
|
-
if (!open
|
|
1962
|
+
if (!open) dismissSlashTrigger();
|
|
1963
|
+
},
|
|
1964
|
+
onDetailsPointerDown: () => {
|
|
1965
|
+
isSlashMenuInteractionRef.current = true;
|
|
1966
|
+
requestAnimationFrame(() => {
|
|
1967
|
+
isSlashMenuInteractionRef.current = false;
|
|
1968
|
+
});
|
|
1962
1969
|
},
|
|
1963
1970
|
onSetActiveIndex: setActiveSlashIndex
|
|
1964
1971
|
})]
|
|
@@ -3785,6 +3792,48 @@ function ChatMessageActionCopy({ message, texts }) {
|
|
|
3785
3792
|
//#endregion
|
|
3786
3793
|
//#region src/components/chat/ui/chat-message-list/chat-message-list.tsx
|
|
3787
3794
|
const INVISIBLE_ONLY_TEXT_PATTERN = /\u200B|\u200C|\u200D|\u2060|\uFEFF/g;
|
|
3795
|
+
const TYPING_TEXT_SHEEN_CSS = `
|
|
3796
|
+
@keyframes nextclaw-chat-typing-text-sheen {
|
|
3797
|
+
0% {
|
|
3798
|
+
background-position: 160% 0;
|
|
3799
|
+
}
|
|
3800
|
+
64% {
|
|
3801
|
+
background-position: -60% 0;
|
|
3802
|
+
}
|
|
3803
|
+
100% {
|
|
3804
|
+
background-position: -60% 0;
|
|
3805
|
+
}
|
|
3806
|
+
}
|
|
3807
|
+
|
|
3808
|
+
.nextclaw-chat-typing-indicator__text {
|
|
3809
|
+
background-image: linear-gradient(
|
|
3810
|
+
100deg,
|
|
3811
|
+
#6b7280 0%,
|
|
3812
|
+
#6b7280 34%,
|
|
3813
|
+
#a6adba 43%,
|
|
3814
|
+
#f8fafc 50%,
|
|
3815
|
+
#a6adba 57%,
|
|
3816
|
+
#6b7280 66%,
|
|
3817
|
+
#6b7280 100%
|
|
3818
|
+
);
|
|
3819
|
+
background-size: 240% 100%;
|
|
3820
|
+
background-position: 160% 0;
|
|
3821
|
+
-webkit-background-clip: text;
|
|
3822
|
+
background-clip: text;
|
|
3823
|
+
color: transparent;
|
|
3824
|
+
-webkit-text-fill-color: transparent;
|
|
3825
|
+
animation: nextclaw-chat-typing-text-sheen 4.2s cubic-bezier(0.4, 0, 0.2, 1) infinite;
|
|
3826
|
+
}
|
|
3827
|
+
|
|
3828
|
+
@media (prefers-reduced-motion: reduce) {
|
|
3829
|
+
.nextclaw-chat-typing-indicator__text {
|
|
3830
|
+
animation: none;
|
|
3831
|
+
background-image: none;
|
|
3832
|
+
color: #6b7280;
|
|
3833
|
+
-webkit-text-fill-color: currentColor;
|
|
3834
|
+
}
|
|
3835
|
+
}
|
|
3836
|
+
`;
|
|
3788
3837
|
function hasRenderableText(value) {
|
|
3789
3838
|
const trimmed = value.trim();
|
|
3790
3839
|
if (!trimmed) return false;
|
|
@@ -3809,6 +3858,15 @@ function ChatMessageTypingFooter() {
|
|
|
3809
3858
|
})
|
|
3810
3859
|
});
|
|
3811
3860
|
}
|
|
3861
|
+
function ChatTypingIndicator({ label }) {
|
|
3862
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
3863
|
+
className: "rounded-2xl border border-gray-200 bg-white px-4 py-3 text-sm text-gray-500 shadow-sm",
|
|
3864
|
+
children: [/* @__PURE__ */ jsx("style", { children: TYPING_TEXT_SHEEN_CSS }), /* @__PURE__ */ jsx("span", {
|
|
3865
|
+
className: "nextclaw-chat-typing-indicator__text",
|
|
3866
|
+
children: label
|
|
3867
|
+
})]
|
|
3868
|
+
});
|
|
3869
|
+
}
|
|
3812
3870
|
function ChatMessageList(props) {
|
|
3813
3871
|
const visibleMessages = props.messages.filter(hasRenderableMessageContent);
|
|
3814
3872
|
const hasRenderableAssistantDraft = visibleMessages.some((message) => message.role === "assistant" && (message.status === "streaming" || message.status === "pending"));
|
|
@@ -3846,10 +3904,7 @@ function ChatMessageList(props) {
|
|
|
3846
3904
|
}, message.id);
|
|
3847
3905
|
}), props.isSending && !hasRenderableAssistantDraft ? /* @__PURE__ */ jsxs("div", {
|
|
3848
3906
|
className: "flex justify-start gap-3",
|
|
3849
|
-
children: [/* @__PURE__ */ jsx(ChatMessageAvatar, { role: "assistant" }), /* @__PURE__ */ jsx(
|
|
3850
|
-
className: "rounded-2xl border border-gray-200 bg-white px-4 py-3 text-sm text-gray-500 shadow-sm",
|
|
3851
|
-
children: props.texts.typingLabel
|
|
3852
|
-
})]
|
|
3907
|
+
children: [/* @__PURE__ */ jsx(ChatMessageAvatar, { role: "assistant" }), /* @__PURE__ */ jsx(ChatTypingIndicator, { label: props.texts.typingLabel })]
|
|
3853
3908
|
}) : null]
|
|
3854
3909
|
});
|
|
3855
3910
|
}
|