@nextclaw/agent-chat-ui 0.2.3 → 0.2.5
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 +12 -3
- package/dist/index.js +117 -26
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as react from 'react';
|
|
2
2
|
import { RefObject } from 'react';
|
|
3
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
3
4
|
|
|
4
5
|
type ChatTexts = {
|
|
5
6
|
slashLoadingLabel: string;
|
|
@@ -191,7 +192,15 @@ type ChatMessageListProps = {
|
|
|
191
192
|
className?: string;
|
|
192
193
|
};
|
|
193
194
|
|
|
194
|
-
|
|
195
|
+
type ChatInputBarHandle = {
|
|
196
|
+
insertFileToken: (tokenKey: string, label: string) => void;
|
|
197
|
+
insertFileTokens: (tokens: Array<{
|
|
198
|
+
tokenKey: string;
|
|
199
|
+
label: string;
|
|
200
|
+
}>) => void;
|
|
201
|
+
focusComposer: () => void;
|
|
202
|
+
};
|
|
203
|
+
declare const ChatInputBar: react.ForwardRefExoticComponent<ChatInputBarProps & react.RefAttributes<ChatInputBarHandle>>;
|
|
195
204
|
|
|
196
205
|
declare function ChatMessageList(props: ChatMessageListProps): react_jsx_runtime.JSX.Element;
|
|
197
206
|
|
|
@@ -255,4 +264,4 @@ declare function resolveChatComposerSlashTrigger(nodes: ChatComposerNode[], sele
|
|
|
255
264
|
end: number;
|
|
256
265
|
} | null;
|
|
257
266
|
|
|
258
|
-
export { type ChatComposerNode, type ChatComposerSelection, type ChatComposerTextNode, type ChatComposerTokenKind, type ChatComposerTokenNode, type ChatInlineHint, ChatInputBar, type ChatInputBarActionsProps, type ChatInputBarProps, type ChatInputBarToolbarProps, ChatMessageList, type ChatMessageListProps, type ChatMessagePartViewModel, type ChatMessageRole, type ChatMessageTexts, type ChatMessageViewModel, type ChatSelectedItem, type ChatSkillPickerOption, type ChatSkillPickerProps, type ChatSlashItem, type ChatSlashMenuProps, type ChatTexts, type ChatToolPartViewModel, type ChatToolbarAccessory, type ChatToolbarAccessoryIcon, type ChatToolbarIcon, type ChatToolbarSelect, type ChatToolbarSelectOption, copyText, createChatComposerNodesFromText, createChatComposerTextNode, createChatComposerTokenNode, createEmptyChatComposerNodes, extractChatComposerTokenKeys, normalizeChatComposerNodes, removeChatComposerTokenNodes, replaceChatComposerRange, resolveChatComposerSlashTrigger, serializeChatComposerDocument, serializeChatComposerPlainText, useActiveItemScroll, useCopyFeedback, useElementWidth, useStickyBottomScroll };
|
|
267
|
+
export { type ChatComposerNode, type ChatComposerSelection, type ChatComposerTextNode, type ChatComposerTokenKind, type ChatComposerTokenNode, type ChatInlineHint, ChatInputBar, type ChatInputBarActionsProps, type ChatInputBarHandle, type ChatInputBarProps, type ChatInputBarToolbarProps, ChatMessageList, type ChatMessageListProps, type ChatMessagePartViewModel, type ChatMessageRole, type ChatMessageTexts, type ChatMessageViewModel, type ChatSelectedItem, type ChatSkillPickerOption, type ChatSkillPickerProps, type ChatSlashItem, type ChatSlashMenuProps, type ChatTexts, type ChatToolPartViewModel, type ChatToolbarAccessory, type ChatToolbarAccessoryIcon, type ChatToolbarIcon, type ChatToolbarSelect, type ChatToolbarSelectOption, copyText, createChatComposerNodesFromText, createChatComposerTextNode, createChatComposerTokenNode, createEmptyChatComposerNodes, extractChatComposerTokenKeys, normalizeChatComposerNodes, removeChatComposerTokenNodes, replaceChatComposerRange, resolveChatComposerSlashTrigger, serializeChatComposerDocument, serializeChatComposerPlainText, useActiveItemScroll, useCopyFeedback, useElementWidth, useStickyBottomScroll };
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/components/chat/ui/chat-input-bar/chat-input-bar.tsx
|
|
2
|
-
import { useEffect as useEffect4, useMemo as useMemo3, useRef as useRef4, useState as useState4 } from "react";
|
|
2
|
+
import { forwardRef as forwardRef7, useEffect as useEffect4, useImperativeHandle as useImperativeHandle2, useMemo as useMemo3, useRef as useRef4, useState as useState4 } from "react";
|
|
3
3
|
|
|
4
4
|
// src/components/chat/ui/chat-input-bar/chat-slash-menu.tsx
|
|
5
5
|
import { useMemo, useRef as useRef2 } from "react";
|
|
@@ -1251,32 +1251,53 @@ var ChatComposerSurfaceRenderer = class {
|
|
|
1251
1251
|
element.dataset.composerTokenKind = node.tokenKind;
|
|
1252
1252
|
element.dataset.composerTokenKey = node.tokenKey;
|
|
1253
1253
|
element.dataset.composerLabel = node.label;
|
|
1254
|
-
element.
|
|
1254
|
+
element.title = node.label;
|
|
1255
|
+
element.className = this.buildTokenClassName(node.tokenKind, isSelected);
|
|
1256
|
+
element.append(this.createTokenIcon(node.tokenKind));
|
|
1257
|
+
const label = document.createElement("span");
|
|
1258
|
+
label.className = node.tokenKind === "file" ? "min-w-0 flex-1 truncate text-[12px] font-medium text-slate-700" : "truncate";
|
|
1259
|
+
label.textContent = node.label;
|
|
1260
|
+
element.append(label);
|
|
1261
|
+
return element;
|
|
1262
|
+
};
|
|
1263
|
+
this.buildTokenClassName = (tokenKind, isSelected) => {
|
|
1264
|
+
if (tokenKind === "file") {
|
|
1265
|
+
return [
|
|
1266
|
+
"mx-[2px]",
|
|
1267
|
+
"inline-flex",
|
|
1268
|
+
"h-7",
|
|
1269
|
+
"max-w-[min(100%,17rem)]",
|
|
1270
|
+
"items-center",
|
|
1271
|
+
"gap-1.5",
|
|
1272
|
+
"rounded-lg",
|
|
1273
|
+
"border",
|
|
1274
|
+
"px-2",
|
|
1275
|
+
"align-baseline",
|
|
1276
|
+
"transition-[border-color,background-color,box-shadow,color]",
|
|
1277
|
+
"duration-150",
|
|
1278
|
+
isSelected ? "border-slate-300 bg-slate-100 text-slate-800 shadow-[0_0_0_2px_rgba(148,163,184,0.14)]" : "border-slate-200/80 bg-slate-50 text-slate-700"
|
|
1279
|
+
].join(" ");
|
|
1280
|
+
}
|
|
1281
|
+
return [
|
|
1255
1282
|
"mx-[2px]",
|
|
1256
1283
|
"inline-flex",
|
|
1257
|
-
"h-
|
|
1284
|
+
"h-7",
|
|
1258
1285
|
"max-w-full",
|
|
1259
1286
|
"items-center",
|
|
1260
|
-
"gap-1",
|
|
1261
|
-
"rounded-
|
|
1287
|
+
"gap-1.5",
|
|
1288
|
+
"rounded-lg",
|
|
1262
1289
|
"border",
|
|
1263
|
-
"px-
|
|
1290
|
+
"px-2",
|
|
1264
1291
|
"align-baseline",
|
|
1265
1292
|
"text-[11px]",
|
|
1266
1293
|
"font-medium",
|
|
1267
1294
|
"transition",
|
|
1268
1295
|
isSelected ? "border-primary/30 bg-primary/18 text-primary" : "border-primary/12 bg-primary/8 text-primary"
|
|
1269
1296
|
].join(" ");
|
|
1270
|
-
element.append(this.createTokenIcon(node.tokenKind));
|
|
1271
|
-
const label = document.createElement("span");
|
|
1272
|
-
label.className = "truncate";
|
|
1273
|
-
label.textContent = node.label;
|
|
1274
|
-
element.append(label);
|
|
1275
|
-
return element;
|
|
1276
1297
|
};
|
|
1277
1298
|
this.createTokenIcon = (tokenKind) => {
|
|
1278
1299
|
const wrapper = document.createElement("span");
|
|
1279
|
-
wrapper.className = "inline-flex h-3 w-3 shrink-0 items-center justify-center text-primary/70";
|
|
1300
|
+
wrapper.className = tokenKind === "file" ? "inline-flex h-4.5 w-4.5 shrink-0 items-center justify-center rounded-md bg-white text-slate-500 ring-1 ring-black/5" : "inline-flex h-3.5 w-3.5 shrink-0 items-center justify-center text-primary/70";
|
|
1280
1301
|
wrapper.append(tokenKind === "file" ? this.createFileIcon() : this.createSkillIcon());
|
|
1281
1302
|
return wrapper;
|
|
1282
1303
|
};
|
|
@@ -1290,10 +1311,9 @@ var ChatComposerSurfaceRenderer = class {
|
|
|
1290
1311
|
};
|
|
1291
1312
|
this.createFileIcon = () => {
|
|
1292
1313
|
return this.createSvgIcon([
|
|
1293
|
-
{ tag: "path", attrs: { d: "
|
|
1294
|
-
{ tag: "path", attrs: { d: "
|
|
1295
|
-
{ tag: "path", attrs: { d: "
|
|
1296
|
-
{ tag: "path", attrs: { d: "M5.75 10.75h4.5" } }
|
|
1314
|
+
{ tag: "path", attrs: { d: "M3.25 4.25A1.5 1.5 0 0 1 4.75 2.75h6.5a1.5 1.5 0 0 1 1.5 1.5v7.5a1.5 1.5 0 0 1-1.5 1.5h-6.5a1.5 1.5 0 0 1-1.5-1.5v-7.5Z" } },
|
|
1315
|
+
{ tag: "path", attrs: { d: "m4.75 10 2.25-2.5 1.75 1.75 1.25-1.25 2 2" } },
|
|
1316
|
+
{ tag: "path", attrs: { d: "M9.75 6.25h.01" } }
|
|
1297
1317
|
]);
|
|
1298
1318
|
};
|
|
1299
1319
|
this.createSvgIcon = (children) => {
|
|
@@ -1463,8 +1483,8 @@ var ChatComposerViewController = class {
|
|
|
1463
1483
|
commitSnapshot(this.controller.insertText(text));
|
|
1464
1484
|
};
|
|
1465
1485
|
this.handleBlur = (params) => {
|
|
1466
|
-
const {
|
|
1467
|
-
|
|
1486
|
+
const { clearSelectedRange, onSlashQueryChange, onSlashOpenChange } = params;
|
|
1487
|
+
clearSelectedRange();
|
|
1468
1488
|
onSlashQueryChange?.(null);
|
|
1469
1489
|
onSlashOpenChange(false);
|
|
1470
1490
|
};
|
|
@@ -1510,6 +1530,20 @@ var ChatComposerRuntime = class {
|
|
|
1510
1530
|
},
|
|
1511
1531
|
insertFileToken: (tokenKey, label) => {
|
|
1512
1532
|
this.commitSnapshot(this.controller.insertFileToken(tokenKey, label));
|
|
1533
|
+
this.focusComposerSoon();
|
|
1534
|
+
},
|
|
1535
|
+
insertFileTokens: (tokens) => {
|
|
1536
|
+
let nextSnapshot = null;
|
|
1537
|
+
for (const token of tokens) {
|
|
1538
|
+
nextSnapshot = this.controller.insertFileToken(token.tokenKey, token.label);
|
|
1539
|
+
}
|
|
1540
|
+
if (nextSnapshot) {
|
|
1541
|
+
this.commitSnapshot(nextSnapshot);
|
|
1542
|
+
this.focusComposerSoon();
|
|
1543
|
+
}
|
|
1544
|
+
},
|
|
1545
|
+
focusComposer: () => {
|
|
1546
|
+
this.focusComposer();
|
|
1513
1547
|
},
|
|
1514
1548
|
syncSelectedSkills: (nextKeys, options) => {
|
|
1515
1549
|
this.viewController.syncSelectedSkills(nextKeys, options, this.commitSnapshot);
|
|
@@ -1603,7 +1637,7 @@ var ChatComposerRuntime = class {
|
|
|
1603
1637
|
const config = this.requireConfig();
|
|
1604
1638
|
this.isComposing = false;
|
|
1605
1639
|
this.viewController.handleBlur({
|
|
1606
|
-
|
|
1640
|
+
clearSelectedRange: this.clearSelectedRange,
|
|
1607
1641
|
onSlashQueryChange: config.onSlashQueryChange,
|
|
1608
1642
|
onSlashOpenChange: config.onSlashOpenChange
|
|
1609
1643
|
});
|
|
@@ -1613,6 +1647,10 @@ var ChatComposerRuntime = class {
|
|
|
1613
1647
|
this.selection = selection;
|
|
1614
1648
|
this.requestRender();
|
|
1615
1649
|
};
|
|
1650
|
+
this.clearSelectedRange = () => {
|
|
1651
|
+
this.selectedRange = null;
|
|
1652
|
+
this.requestRender();
|
|
1653
|
+
};
|
|
1616
1654
|
this.commitSnapshot = (nextSnapshot) => {
|
|
1617
1655
|
const config = this.requireConfig();
|
|
1618
1656
|
this.selection = nextSnapshot.selection;
|
|
@@ -1633,6 +1671,33 @@ var ChatComposerRuntime = class {
|
|
|
1633
1671
|
this.requestRender = () => {
|
|
1634
1672
|
this.requireConfig().requestRender();
|
|
1635
1673
|
};
|
|
1674
|
+
this.focusComposerSoon = () => {
|
|
1675
|
+
if (typeof requestAnimationFrame === "function") {
|
|
1676
|
+
requestAnimationFrame(() => this.focusComposer());
|
|
1677
|
+
return;
|
|
1678
|
+
}
|
|
1679
|
+
this.focusComposer();
|
|
1680
|
+
};
|
|
1681
|
+
this.focusComposer = () => {
|
|
1682
|
+
if (!this.rootElement) {
|
|
1683
|
+
return;
|
|
1684
|
+
}
|
|
1685
|
+
const targetSelection = this.selection;
|
|
1686
|
+
this.rootElement.focus();
|
|
1687
|
+
const restoreSelection2 = () => {
|
|
1688
|
+
if (!this.rootElement) {
|
|
1689
|
+
return;
|
|
1690
|
+
}
|
|
1691
|
+
this.selection = targetSelection;
|
|
1692
|
+
this.selectedRange = targetSelection;
|
|
1693
|
+
this.viewController.restoreSelectionIfFocused(this.rootElement, targetSelection);
|
|
1694
|
+
};
|
|
1695
|
+
if (typeof requestAnimationFrame === "function") {
|
|
1696
|
+
requestAnimationFrame(restoreSelection2);
|
|
1697
|
+
return;
|
|
1698
|
+
}
|
|
1699
|
+
restoreSelection2();
|
|
1700
|
+
};
|
|
1636
1701
|
this.requireConfig = () => {
|
|
1637
1702
|
if (!this.config) {
|
|
1638
1703
|
throw new Error("ChatComposerRuntime is not configured.");
|
|
@@ -1744,7 +1809,7 @@ function InputBarHint({ hint }) {
|
|
|
1744
1809
|
) : null
|
|
1745
1810
|
] }) });
|
|
1746
1811
|
}
|
|
1747
|
-
|
|
1812
|
+
var ChatInputBar = forwardRef7(function ChatInputBar2(props, ref) {
|
|
1748
1813
|
const composerRef = useRef4(null);
|
|
1749
1814
|
const [slashQuery, setSlashQuery] = useState4(null);
|
|
1750
1815
|
const [activeSlashIndex, setActiveSlashIndex] = useState4(0);
|
|
@@ -1784,6 +1849,11 @@ function ChatInputBar(props) {
|
|
|
1784
1849
|
}
|
|
1785
1850
|
};
|
|
1786
1851
|
}, [props.toolbar]);
|
|
1852
|
+
useImperativeHandle2(ref, () => ({
|
|
1853
|
+
insertFileToken: (tokenKey, label) => composerRef.current?.insertFileToken(tokenKey, label),
|
|
1854
|
+
insertFileTokens: (tokens) => composerRef.current?.insertFileTokens(tokens),
|
|
1855
|
+
focusComposer: () => composerRef.current?.focusComposer()
|
|
1856
|
+
}), []);
|
|
1787
1857
|
return /* @__PURE__ */ jsx11("div", { className: "border-t border-gray-200/80 bg-white p-4", children: /* @__PURE__ */ jsx11("div", { className: "mx-auto w-full max-w-[min(1120px,100%)]", children: /* @__PURE__ */ jsxs6("div", { className: "overflow-hidden rounded-2xl border border-gray-200 bg-white shadow-card", children: [
|
|
1788
1858
|
/* @__PURE__ */ jsxs6("div", { className: "relative", children: [
|
|
1789
1859
|
/* @__PURE__ */ jsx11(
|
|
@@ -1838,7 +1908,8 @@ function ChatInputBar(props) {
|
|
|
1838
1908
|
/* @__PURE__ */ jsx11(InputBarHint, { hint: props.hint }),
|
|
1839
1909
|
/* @__PURE__ */ jsx11(ChatInputBarToolbar, { ...toolbar })
|
|
1840
1910
|
] }) }) });
|
|
1841
|
-
}
|
|
1911
|
+
});
|
|
1912
|
+
ChatInputBar.displayName = "ChatInputBar";
|
|
1842
1913
|
|
|
1843
1914
|
// src/components/chat/ui/chat-message-list/chat-message-avatar.tsx
|
|
1844
1915
|
import { Bot, User, Wrench } from "lucide-react";
|
|
@@ -2119,10 +2190,30 @@ function ChatMessageMarkdown(props) {
|
|
|
2119
2190
|
import { jsx as jsx15, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
2120
2191
|
function ChatMessageFile({ file }) {
|
|
2121
2192
|
if (file.isImage && file.dataUrl) {
|
|
2122
|
-
return /* @__PURE__ */
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2193
|
+
return /* @__PURE__ */ jsx15(
|
|
2194
|
+
"img",
|
|
2195
|
+
{
|
|
2196
|
+
src: file.dataUrl,
|
|
2197
|
+
alt: file.label,
|
|
2198
|
+
className: "block max-h-80 max-w-full rounded-2xl object-contain"
|
|
2199
|
+
}
|
|
2200
|
+
);
|
|
2201
|
+
}
|
|
2202
|
+
if (file.dataUrl) {
|
|
2203
|
+
return /* @__PURE__ */ jsxs8(
|
|
2204
|
+
"a",
|
|
2205
|
+
{
|
|
2206
|
+
href: file.dataUrl,
|
|
2207
|
+
download: file.label,
|
|
2208
|
+
target: "_blank",
|
|
2209
|
+
rel: "noreferrer",
|
|
2210
|
+
className: "block rounded-2xl border border-black/8 bg-black/6 px-3 py-2 text-sm transition hover:bg-black/8",
|
|
2211
|
+
children: [
|
|
2212
|
+
/* @__PURE__ */ jsx15("div", { className: "font-medium", children: file.label }),
|
|
2213
|
+
/* @__PURE__ */ jsx15("div", { className: "text-xs opacity-75", children: file.mimeType })
|
|
2214
|
+
]
|
|
2215
|
+
}
|
|
2216
|
+
);
|
|
2126
2217
|
}
|
|
2127
2218
|
return /* @__PURE__ */ jsxs8("div", { className: "rounded-2xl border border-black/8 bg-black/6 px-3 py-2 text-sm", children: [
|
|
2128
2219
|
/* @__PURE__ */ jsx15("div", { className: "font-medium", children: file.label }),
|