@nextclaw/agent-chat-ui 0.2.3 → 0.2.4
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 +107 -22
- 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,76 @@ 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-800" : "truncate";
|
|
1259
|
+
label.textContent = node.label;
|
|
1260
|
+
element.append(label);
|
|
1261
|
+
if (node.tokenKind === "file") {
|
|
1262
|
+
const badge = document.createElement("span");
|
|
1263
|
+
badge.className = [
|
|
1264
|
+
"hidden",
|
|
1265
|
+
"shrink-0",
|
|
1266
|
+
"rounded-md",
|
|
1267
|
+
"border",
|
|
1268
|
+
"border-sky-100",
|
|
1269
|
+
"bg-sky-50",
|
|
1270
|
+
"px-1.5",
|
|
1271
|
+
"py-0.5",
|
|
1272
|
+
"text-[9px]",
|
|
1273
|
+
"font-semibold",
|
|
1274
|
+
"uppercase",
|
|
1275
|
+
"tracking-[0.12em]",
|
|
1276
|
+
"text-sky-700",
|
|
1277
|
+
"sm:inline-flex"
|
|
1278
|
+
].join(" ");
|
|
1279
|
+
badge.textContent = this.resolveFileBadgeLabel(node.label);
|
|
1280
|
+
element.append(badge);
|
|
1281
|
+
}
|
|
1282
|
+
return element;
|
|
1283
|
+
};
|
|
1284
|
+
this.buildTokenClassName = (tokenKind, isSelected) => {
|
|
1285
|
+
if (tokenKind === "file") {
|
|
1286
|
+
return [
|
|
1287
|
+
"mx-[2px]",
|
|
1288
|
+
"inline-flex",
|
|
1289
|
+
"h-8",
|
|
1290
|
+
"max-w-[min(100%,19rem)]",
|
|
1291
|
+
"items-center",
|
|
1292
|
+
"gap-2",
|
|
1293
|
+
"rounded-xl",
|
|
1294
|
+
"border",
|
|
1295
|
+
"px-2",
|
|
1296
|
+
"pr-2.5",
|
|
1297
|
+
"align-baseline",
|
|
1298
|
+
"shadow-[0_1px_2px_rgba(15,23,42,0.06)]",
|
|
1299
|
+
"transition-[border-color,background-color,box-shadow,color]",
|
|
1300
|
+
"duration-150",
|
|
1301
|
+
isSelected ? "border-sky-300 bg-sky-50 text-slate-900 shadow-[0_0_0_3px_rgba(14,165,233,0.14)]" : "border-slate-200 bg-[linear-gradient(180deg,rgba(255,255,255,1),rgba(248,250,252,0.98))] text-slate-700"
|
|
1302
|
+
].join(" ");
|
|
1303
|
+
}
|
|
1304
|
+
return [
|
|
1255
1305
|
"mx-[2px]",
|
|
1256
1306
|
"inline-flex",
|
|
1257
|
-
"h-
|
|
1307
|
+
"h-7",
|
|
1258
1308
|
"max-w-full",
|
|
1259
1309
|
"items-center",
|
|
1260
|
-
"gap-1",
|
|
1261
|
-
"rounded-
|
|
1310
|
+
"gap-1.5",
|
|
1311
|
+
"rounded-lg",
|
|
1262
1312
|
"border",
|
|
1263
|
-
"px-
|
|
1313
|
+
"px-2",
|
|
1264
1314
|
"align-baseline",
|
|
1265
1315
|
"text-[11px]",
|
|
1266
1316
|
"font-medium",
|
|
1267
1317
|
"transition",
|
|
1268
1318
|
isSelected ? "border-primary/30 bg-primary/18 text-primary" : "border-primary/12 bg-primary/8 text-primary"
|
|
1269
1319
|
].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
1320
|
};
|
|
1277
1321
|
this.createTokenIcon = (tokenKind) => {
|
|
1278
1322
|
const wrapper = document.createElement("span");
|
|
1279
|
-
wrapper.className = "inline-flex h-3 w-3 shrink-0 items-center justify-center text-primary/70";
|
|
1323
|
+
wrapper.className = tokenKind === "file" ? "inline-flex h-5 w-5 shrink-0 items-center justify-center rounded-lg bg-sky-100 text-sky-700" : "inline-flex h-3.5 w-3.5 shrink-0 items-center justify-center text-primary/70";
|
|
1280
1324
|
wrapper.append(tokenKind === "file" ? this.createFileIcon() : this.createSkillIcon());
|
|
1281
1325
|
return wrapper;
|
|
1282
1326
|
};
|
|
@@ -1290,12 +1334,15 @@ var ChatComposerSurfaceRenderer = class {
|
|
|
1290
1334
|
};
|
|
1291
1335
|
this.createFileIcon = () => {
|
|
1292
1336
|
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" } }
|
|
1337
|
+
{ 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" } },
|
|
1338
|
+
{ tag: "path", attrs: { d: "m4.75 10 2.25-2.5 1.75 1.75 1.25-1.25 2 2" } },
|
|
1339
|
+
{ tag: "path", attrs: { d: "M9.75 6.25h.01" } }
|
|
1297
1340
|
]);
|
|
1298
1341
|
};
|
|
1342
|
+
this.resolveFileBadgeLabel = (label) => {
|
|
1343
|
+
const match = /\.([a-z0-9]+)$/i.exec(label.trim());
|
|
1344
|
+
return match?.[1]?.slice(0, 4).toUpperCase() || "IMG";
|
|
1345
|
+
};
|
|
1299
1346
|
this.createSvgIcon = (children) => {
|
|
1300
1347
|
const svg = document.createElementNS(SVG_NAMESPACE, "svg");
|
|
1301
1348
|
svg.setAttribute("viewBox", "0 0 16 16");
|
|
@@ -1463,8 +1510,8 @@ var ChatComposerViewController = class {
|
|
|
1463
1510
|
commitSnapshot(this.controller.insertText(text));
|
|
1464
1511
|
};
|
|
1465
1512
|
this.handleBlur = (params) => {
|
|
1466
|
-
const {
|
|
1467
|
-
|
|
1513
|
+
const { clearSelectedRange, onSlashQueryChange, onSlashOpenChange } = params;
|
|
1514
|
+
clearSelectedRange();
|
|
1468
1515
|
onSlashQueryChange?.(null);
|
|
1469
1516
|
onSlashOpenChange(false);
|
|
1470
1517
|
};
|
|
@@ -1510,6 +1557,20 @@ var ChatComposerRuntime = class {
|
|
|
1510
1557
|
},
|
|
1511
1558
|
insertFileToken: (tokenKey, label) => {
|
|
1512
1559
|
this.commitSnapshot(this.controller.insertFileToken(tokenKey, label));
|
|
1560
|
+
this.focusComposerSoon();
|
|
1561
|
+
},
|
|
1562
|
+
insertFileTokens: (tokens) => {
|
|
1563
|
+
let nextSnapshot = null;
|
|
1564
|
+
for (const token of tokens) {
|
|
1565
|
+
nextSnapshot = this.controller.insertFileToken(token.tokenKey, token.label);
|
|
1566
|
+
}
|
|
1567
|
+
if (nextSnapshot) {
|
|
1568
|
+
this.commitSnapshot(nextSnapshot);
|
|
1569
|
+
this.focusComposerSoon();
|
|
1570
|
+
}
|
|
1571
|
+
},
|
|
1572
|
+
focusComposer: () => {
|
|
1573
|
+
this.focusComposer();
|
|
1513
1574
|
},
|
|
1514
1575
|
syncSelectedSkills: (nextKeys, options) => {
|
|
1515
1576
|
this.viewController.syncSelectedSkills(nextKeys, options, this.commitSnapshot);
|
|
@@ -1603,7 +1664,7 @@ var ChatComposerRuntime = class {
|
|
|
1603
1664
|
const config = this.requireConfig();
|
|
1604
1665
|
this.isComposing = false;
|
|
1605
1666
|
this.viewController.handleBlur({
|
|
1606
|
-
|
|
1667
|
+
clearSelectedRange: this.clearSelectedRange,
|
|
1607
1668
|
onSlashQueryChange: config.onSlashQueryChange,
|
|
1608
1669
|
onSlashOpenChange: config.onSlashOpenChange
|
|
1609
1670
|
});
|
|
@@ -1613,6 +1674,10 @@ var ChatComposerRuntime = class {
|
|
|
1613
1674
|
this.selection = selection;
|
|
1614
1675
|
this.requestRender();
|
|
1615
1676
|
};
|
|
1677
|
+
this.clearSelectedRange = () => {
|
|
1678
|
+
this.selectedRange = null;
|
|
1679
|
+
this.requestRender();
|
|
1680
|
+
};
|
|
1616
1681
|
this.commitSnapshot = (nextSnapshot) => {
|
|
1617
1682
|
const config = this.requireConfig();
|
|
1618
1683
|
this.selection = nextSnapshot.selection;
|
|
@@ -1633,6 +1698,20 @@ var ChatComposerRuntime = class {
|
|
|
1633
1698
|
this.requestRender = () => {
|
|
1634
1699
|
this.requireConfig().requestRender();
|
|
1635
1700
|
};
|
|
1701
|
+
this.focusComposerSoon = () => {
|
|
1702
|
+
if (typeof requestAnimationFrame === "function") {
|
|
1703
|
+
requestAnimationFrame(() => this.focusComposer());
|
|
1704
|
+
return;
|
|
1705
|
+
}
|
|
1706
|
+
this.focusComposer();
|
|
1707
|
+
};
|
|
1708
|
+
this.focusComposer = () => {
|
|
1709
|
+
if (!this.rootElement) {
|
|
1710
|
+
return;
|
|
1711
|
+
}
|
|
1712
|
+
this.rootElement.focus();
|
|
1713
|
+
this.viewController.restoreSelectionIfFocused(this.rootElement, this.selection);
|
|
1714
|
+
};
|
|
1636
1715
|
this.requireConfig = () => {
|
|
1637
1716
|
if (!this.config) {
|
|
1638
1717
|
throw new Error("ChatComposerRuntime is not configured.");
|
|
@@ -1744,7 +1823,7 @@ function InputBarHint({ hint }) {
|
|
|
1744
1823
|
) : null
|
|
1745
1824
|
] }) });
|
|
1746
1825
|
}
|
|
1747
|
-
|
|
1826
|
+
var ChatInputBar = forwardRef7(function ChatInputBar2(props, ref) {
|
|
1748
1827
|
const composerRef = useRef4(null);
|
|
1749
1828
|
const [slashQuery, setSlashQuery] = useState4(null);
|
|
1750
1829
|
const [activeSlashIndex, setActiveSlashIndex] = useState4(0);
|
|
@@ -1784,6 +1863,11 @@ function ChatInputBar(props) {
|
|
|
1784
1863
|
}
|
|
1785
1864
|
};
|
|
1786
1865
|
}, [props.toolbar]);
|
|
1866
|
+
useImperativeHandle2(ref, () => ({
|
|
1867
|
+
insertFileToken: (tokenKey, label) => composerRef.current?.insertFileToken(tokenKey, label),
|
|
1868
|
+
insertFileTokens: (tokens) => composerRef.current?.insertFileTokens(tokens),
|
|
1869
|
+
focusComposer: () => composerRef.current?.focusComposer()
|
|
1870
|
+
}), []);
|
|
1787
1871
|
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
1872
|
/* @__PURE__ */ jsxs6("div", { className: "relative", children: [
|
|
1789
1873
|
/* @__PURE__ */ jsx11(
|
|
@@ -1838,7 +1922,8 @@ function ChatInputBar(props) {
|
|
|
1838
1922
|
/* @__PURE__ */ jsx11(InputBarHint, { hint: props.hint }),
|
|
1839
1923
|
/* @__PURE__ */ jsx11(ChatInputBarToolbar, { ...toolbar })
|
|
1840
1924
|
] }) }) });
|
|
1841
|
-
}
|
|
1925
|
+
});
|
|
1926
|
+
ChatInputBar.displayName = "ChatInputBar";
|
|
1842
1927
|
|
|
1843
1928
|
// src/components/chat/ui/chat-message-list/chat-message-avatar.tsx
|
|
1844
1929
|
import { Bot, User, Wrench } from "lucide-react";
|