@mcp-b/react-components 0.2.2 → 0.3.0
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/{CodeBlock-BrCoypnc.js → CodeBlock-C2Xjxu9M.js} +1 -1
- package/dist/FileTree-D0c9Yj9U.js +310 -0
- package/dist/PromptInput-Dzn-fOPc.d.ts +444 -0
- package/dist/components/Activity.js +1 -1
- package/dist/components/AgentChat.d.ts +19 -9
- package/dist/components/AgentChat.js +27 -24
- package/dist/components/AgentConnection.js +2 -2
- package/dist/components/Artifact.js +1 -1
- package/dist/components/BrowserLiveView.d.ts +47 -0
- package/dist/components/BrowserLiveView.js +135 -0
- package/dist/components/BrowserReplay.d.ts +40 -0
- package/dist/components/BrowserReplay.js +187 -0
- package/dist/components/ChainOfThought.d.ts +1 -1
- package/dist/components/ChainOfThought.js +1 -1
- package/dist/components/CodeBlock.js +1 -1
- package/dist/components/Commit.js +1 -1
- package/dist/components/ContextMenu.js +1 -1
- package/dist/components/Conversation.js +1 -1
- package/dist/components/Dialog.js +1 -1
- package/dist/components/EnvironmentVariables.js +1 -1
- package/dist/components/FileTree.js +1 -309
- package/dist/components/Menubar.js +1 -1
- package/dist/components/Message.d.ts +2 -1
- package/dist/components/Message.js +1 -1
- package/dist/components/ModelSelector.js +1 -1
- package/dist/components/NavigationMenu.js +1 -1
- package/dist/components/PricingPage.js +1 -1
- package/dist/components/PromptInput.d.ts +2 -399
- package/dist/components/PromptInput.js +177 -2
- package/dist/components/Queue.js +1 -1
- package/dist/components/Reasoning.js +1 -1
- package/dist/components/Select.js +1 -1
- package/dist/components/Sources.js +1 -1
- package/dist/components/Stepper.js +1 -1
- package/dist/components/Task.js +1 -1
- package/dist/components/Terminal.js +2 -2
- package/dist/components/TestResults.js +1 -1
- package/dist/components/ThinkChat.d.ts +186 -0
- package/dist/components/ThinkChat.js +730 -0
- package/dist/components/Tool.d.ts +32 -28
- package/dist/components/Tool.js +29 -16
- package/dist/components/WebPreview.js +1 -1
- package/dist/components/WorkspaceExplorer.d.ts +102 -0
- package/dist/components/WorkspaceExplorer.js +352 -0
- package/dist/components/icons.d.ts +2 -2
- package/dist/components/icons.js +2 -2
- package/dist/{copy-button-DAPlB8Z0.js → copy-button-Dd6DEhOm.js} +1 -1
- package/dist/{icons-Bf7JMKk-.js → icons-DQC4Zw5R.js} +5 -1
- package/dist/{icons-BklFyZbx.d.ts → icons-ctdVxng0.d.ts} +2 -1
- package/dist/styles/prompt-input.css +149 -0
- package/package.json +26 -3
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { t as cx } from "./class-names-9UtZwb0J.js";
|
|
2
2
|
import { Select, SelectContent, SelectItem, SelectList, SelectTrigger, SelectValue } from "./components/Select.js";
|
|
3
|
-
import { t as CopyButton } from "./copy-button-
|
|
3
|
+
import { t as CopyButton } from "./copy-button-Dd6DEhOm.js";
|
|
4
4
|
import * as React from "react";
|
|
5
5
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
6
6
|
import { createHighlighter } from "shiki";
|
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
import { t as cx } from "./class-names-9UtZwb0J.js";
|
|
2
|
+
import { _ as FolderOpenIcon, g as FolderIcon, h as FileIcon, l as ChevronRightIcon } from "./icons-DQC4Zw5R.js";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
//#region src/components/_internal/use-file-tree-nav.ts
|
|
6
|
+
const FileTreeContext = React.createContext(null);
|
|
7
|
+
function useFileTreeContext() {
|
|
8
|
+
const ctx = React.useContext(FileTreeContext);
|
|
9
|
+
if (!ctx) throw new Error("FileTree subcomponents must be used inside <FileTree>.");
|
|
10
|
+
return ctx;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Builds a FileTreeContextValue that tracks registered nodes and dispatches
|
|
14
|
+
* keyboard navigation per the WAI-ARIA Tree Pattern.
|
|
15
|
+
*
|
|
16
|
+
* Call `register` from every FileTreeFolder/FileTreeFile during render. The
|
|
17
|
+
* hook resets its internal list on each render pass so removed nodes don't
|
|
18
|
+
* leave stale entries.
|
|
19
|
+
*/
|
|
20
|
+
function useFileTreeNav({ expanded, selectedPath, onSelect, onExpandedChange }) {
|
|
21
|
+
const [focusedPath, setFocusedPath] = React.useState(null);
|
|
22
|
+
const nodesRef = React.useRef([]);
|
|
23
|
+
nodesRef.current = [];
|
|
24
|
+
const register = React.useCallback((path, kind, parentExpanded) => {
|
|
25
|
+
nodesRef.current.push({
|
|
26
|
+
path,
|
|
27
|
+
kind,
|
|
28
|
+
visible: parentExpanded
|
|
29
|
+
});
|
|
30
|
+
}, []);
|
|
31
|
+
const visibleNodes = () => nodesRef.current.filter((n) => n.visible);
|
|
32
|
+
const moveFocus = React.useCallback((direction, from) => {
|
|
33
|
+
const visible = visibleNodes();
|
|
34
|
+
const idx = visible.findIndex((n) => n.path === from);
|
|
35
|
+
if (idx < 0) return;
|
|
36
|
+
const next = visible[Math.max(0, Math.min(visible.length - 1, idx + direction))];
|
|
37
|
+
if (next) setFocusedPath(next.path);
|
|
38
|
+
}, []);
|
|
39
|
+
const focusFirstVisibleNode = React.useCallback(() => {
|
|
40
|
+
const first = visibleNodes()[0];
|
|
41
|
+
if (first) setFocusedPath(first.path);
|
|
42
|
+
}, []);
|
|
43
|
+
const focusLastVisibleNode = React.useCallback(() => {
|
|
44
|
+
const visible = visibleNodes();
|
|
45
|
+
const last = visible[visible.length - 1];
|
|
46
|
+
if (last) setFocusedPath(last.path);
|
|
47
|
+
}, []);
|
|
48
|
+
const setFolderExpanded = React.useCallback((path, nextExpanded) => {
|
|
49
|
+
const next = new Set(expanded);
|
|
50
|
+
if (nextExpanded) next.add(path);
|
|
51
|
+
else next.delete(path);
|
|
52
|
+
onExpandedChange(next);
|
|
53
|
+
}, [expanded, onExpandedChange]);
|
|
54
|
+
const toggleFolderExpanded = React.useCallback((path) => {
|
|
55
|
+
setFolderExpanded(path, !expanded.has(path));
|
|
56
|
+
}, [expanded, setFolderExpanded]);
|
|
57
|
+
const keyHandlers = React.useMemo(() => ({
|
|
58
|
+
ArrowDown(path) {
|
|
59
|
+
moveFocus(1, path);
|
|
60
|
+
},
|
|
61
|
+
ArrowUp(path) {
|
|
62
|
+
moveFocus(-1, path);
|
|
63
|
+
},
|
|
64
|
+
ArrowRight(path, kind) {
|
|
65
|
+
if (!(kind === "folder")) return;
|
|
66
|
+
if (expanded.has(path)) moveFocus(1, path);
|
|
67
|
+
else setFolderExpanded(path, true);
|
|
68
|
+
},
|
|
69
|
+
ArrowLeft(path, kind) {
|
|
70
|
+
if (kind === "folder" && expanded.has(path)) setFolderExpanded(path, false);
|
|
71
|
+
},
|
|
72
|
+
Enter(path, kind) {
|
|
73
|
+
if (kind === "folder") {
|
|
74
|
+
onSelect(path);
|
|
75
|
+
toggleFolderExpanded(path);
|
|
76
|
+
} else onSelect(path);
|
|
77
|
+
},
|
|
78
|
+
" "(path, kind) {
|
|
79
|
+
if (kind === "folder") {
|
|
80
|
+
onSelect(path);
|
|
81
|
+
toggleFolderExpanded(path);
|
|
82
|
+
} else onSelect(path);
|
|
83
|
+
},
|
|
84
|
+
Home() {
|
|
85
|
+
focusFirstVisibleNode();
|
|
86
|
+
},
|
|
87
|
+
End() {
|
|
88
|
+
focusLastVisibleNode();
|
|
89
|
+
}
|
|
90
|
+
}), [
|
|
91
|
+
expanded,
|
|
92
|
+
focusFirstVisibleNode,
|
|
93
|
+
focusLastVisibleNode,
|
|
94
|
+
moveFocus,
|
|
95
|
+
onSelect,
|
|
96
|
+
setFolderExpanded,
|
|
97
|
+
toggleFolderExpanded
|
|
98
|
+
]);
|
|
99
|
+
const handleKeyDown = React.useCallback((event, path, kind) => {
|
|
100
|
+
const keyHandler = keyHandlers[event.key];
|
|
101
|
+
if (!keyHandler) return;
|
|
102
|
+
event.preventDefault();
|
|
103
|
+
keyHandler(path, kind);
|
|
104
|
+
}, [keyHandlers]);
|
|
105
|
+
return {
|
|
106
|
+
focusedPath,
|
|
107
|
+
selectedPath,
|
|
108
|
+
expanded,
|
|
109
|
+
onFocus: React.useCallback((path) => {
|
|
110
|
+
setFocusedPath(path);
|
|
111
|
+
}, []),
|
|
112
|
+
onSelect,
|
|
113
|
+
onExpandedChange: React.useCallback((path, next) => {
|
|
114
|
+
setFolderExpanded(path, next);
|
|
115
|
+
}, [setFolderExpanded]),
|
|
116
|
+
register,
|
|
117
|
+
handleKeyDown
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
//#endregion
|
|
121
|
+
//#region src/components/FileTree.tsx
|
|
122
|
+
/**
|
|
123
|
+
* A keyboard-accessible hierarchical file browser. Compose with
|
|
124
|
+
* FileTreeFolder and FileTreeFile children.
|
|
125
|
+
*
|
|
126
|
+
* Keyboard: ↑/↓ move focus, →/← expand/collapse folders, Enter/Space
|
|
127
|
+
* selects files and selects/toggles folders, Home/End jump to first/last node.
|
|
128
|
+
*
|
|
129
|
+
* @example
|
|
130
|
+
* ```tsx
|
|
131
|
+
* <FileTree defaultExpanded={new Set(["src"])}>
|
|
132
|
+
* <FileTreeFolder path="src" name="src">
|
|
133
|
+
* <FileTreeFile path="src/index.ts" name="index.ts" />
|
|
134
|
+
* <FileTreeFolder path="src/lib" name="lib">
|
|
135
|
+
* <FileTreeFile path="src/lib/utils.ts" name="utils.ts" />
|
|
136
|
+
* </FileTreeFolder>
|
|
137
|
+
* </FileTreeFolder>
|
|
138
|
+
* </FileTree>
|
|
139
|
+
* ```
|
|
140
|
+
*/
|
|
141
|
+
function FileTree({ className, "aria-label": ariaLabel = "File tree", expanded, defaultExpanded, selectedPath = null, onSelect, onExpandedChange, children, ref, ...props }) {
|
|
142
|
+
const [internalExpanded, setInternalExpanded] = React.useState(() => defaultExpanded ?? /* @__PURE__ */ new Set());
|
|
143
|
+
const isControlled = expanded !== void 0;
|
|
144
|
+
const currentExpanded = isControlled ? expanded : internalExpanded;
|
|
145
|
+
const handleExpandedChange = React.useCallback((next) => {
|
|
146
|
+
if (!isControlled) setInternalExpanded(next);
|
|
147
|
+
onExpandedChange?.(next);
|
|
148
|
+
}, [isControlled, onExpandedChange]);
|
|
149
|
+
const ctx = useFileTreeNav({
|
|
150
|
+
expanded: currentExpanded,
|
|
151
|
+
selectedPath,
|
|
152
|
+
onSelect: React.useCallback((path) => {
|
|
153
|
+
onSelect?.(path);
|
|
154
|
+
}, [onSelect]),
|
|
155
|
+
onExpandedChange: handleExpandedChange
|
|
156
|
+
});
|
|
157
|
+
return /* @__PURE__ */ jsx(FileTreeContext.Provider, {
|
|
158
|
+
value: ctx,
|
|
159
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
160
|
+
ref,
|
|
161
|
+
className: cx("file-tree", className),
|
|
162
|
+
...props,
|
|
163
|
+
children: /* @__PURE__ */ jsx("ul", {
|
|
164
|
+
className: "file-tree__list",
|
|
165
|
+
role: "tree",
|
|
166
|
+
"aria-label": ariaLabel,
|
|
167
|
+
tabIndex: 0,
|
|
168
|
+
children
|
|
169
|
+
})
|
|
170
|
+
})
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
function renderNestedFileTreeChild(child, level) {
|
|
174
|
+
if (React.isValidElement(child) && (child.type === FileTreeFolder || child.type === FileTreeFile)) return React.cloneElement(child, { level: level + 1 });
|
|
175
|
+
return child;
|
|
176
|
+
}
|
|
177
|
+
function dataFlag(enabled) {
|
|
178
|
+
return enabled ? "" : void 0;
|
|
179
|
+
}
|
|
180
|
+
function getFileTreeNodeTabIndex(focusedPath, path, level) {
|
|
181
|
+
return focusedPath === path || !focusedPath && level === 0 ? 0 : -1;
|
|
182
|
+
}
|
|
183
|
+
function getFileTreeNodeIndent(level, offset) {
|
|
184
|
+
return `${level * 1.125 + offset}rem`;
|
|
185
|
+
}
|
|
186
|
+
function FileTreeFolder({ className, path, name, level = 0, children, ref, ...props }) {
|
|
187
|
+
const { expanded, focusedPath, selectedPath, onFocus, onSelect, register, handleKeyDown, onExpandedChange } = useFileTreeContext();
|
|
188
|
+
const isExpanded = expanded.has(path);
|
|
189
|
+
const isFocused = focusedPath === path;
|
|
190
|
+
const isSelected = selectedPath === path;
|
|
191
|
+
register(path, "folder", true);
|
|
192
|
+
const toggle = React.useCallback(() => {
|
|
193
|
+
onExpandedChange(path, !isExpanded);
|
|
194
|
+
}, [
|
|
195
|
+
isExpanded,
|
|
196
|
+
onExpandedChange,
|
|
197
|
+
path
|
|
198
|
+
]);
|
|
199
|
+
const handleClick = React.useCallback(() => {
|
|
200
|
+
onSelect(path);
|
|
201
|
+
toggle();
|
|
202
|
+
}, [
|
|
203
|
+
onSelect,
|
|
204
|
+
path,
|
|
205
|
+
toggle
|
|
206
|
+
]);
|
|
207
|
+
return /* @__PURE__ */ jsxs("li", {
|
|
208
|
+
ref,
|
|
209
|
+
role: "treeitem",
|
|
210
|
+
"aria-expanded": isExpanded,
|
|
211
|
+
"aria-selected": isSelected,
|
|
212
|
+
className: cx("file-tree__folder", className),
|
|
213
|
+
...props,
|
|
214
|
+
children: [/* @__PURE__ */ jsxs("button", {
|
|
215
|
+
type: "button",
|
|
216
|
+
className: "file-tree__node file-tree__node--folder",
|
|
217
|
+
"data-focused": dataFlag(isFocused),
|
|
218
|
+
"data-selected": dataFlag(isSelected),
|
|
219
|
+
tabIndex: getFileTreeNodeTabIndex(focusedPath, path, level),
|
|
220
|
+
onClick: handleClick,
|
|
221
|
+
onFocus: () => onFocus(path),
|
|
222
|
+
onKeyDown: (e) => handleKeyDown(e, path, "folder"),
|
|
223
|
+
style: { paddingInlineStart: getFileTreeNodeIndent(level, .5) },
|
|
224
|
+
children: [
|
|
225
|
+
/* @__PURE__ */ jsx("span", {
|
|
226
|
+
className: cx("file-tree__chevron", isExpanded && "file-tree__chevron--expanded"),
|
|
227
|
+
"aria-hidden": "true",
|
|
228
|
+
children: /* @__PURE__ */ jsx(ChevronRightIcon, {})
|
|
229
|
+
}),
|
|
230
|
+
/* @__PURE__ */ jsx("span", {
|
|
231
|
+
className: "file-tree__icon",
|
|
232
|
+
"aria-hidden": "true",
|
|
233
|
+
children: isExpanded ? /* @__PURE__ */ jsx(FolderOpenIcon, {}) : /* @__PURE__ */ jsx(FolderIcon, {})
|
|
234
|
+
}),
|
|
235
|
+
/* @__PURE__ */ jsx("span", {
|
|
236
|
+
className: "file-tree__name",
|
|
237
|
+
children: name
|
|
238
|
+
})
|
|
239
|
+
]
|
|
240
|
+
}), isExpanded ? /* @__PURE__ */ jsx("ul", {
|
|
241
|
+
className: "file-tree__list",
|
|
242
|
+
role: "group",
|
|
243
|
+
children: React.Children.map(children, (child) => renderNestedFileTreeChild(child, level))
|
|
244
|
+
}) : null]
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
function FileTreeFile({ className, path, name, icon, level = 0, ref, ...props }) {
|
|
248
|
+
const { selectedPath, focusedPath, onFocus, onSelect, register, handleKeyDown } = useFileTreeContext();
|
|
249
|
+
const isSelected = selectedPath === path;
|
|
250
|
+
const isFocused = focusedPath === path;
|
|
251
|
+
register(path, "file", true);
|
|
252
|
+
return /* @__PURE__ */ jsx("li", {
|
|
253
|
+
ref,
|
|
254
|
+
role: "treeitem",
|
|
255
|
+
"aria-selected": isSelected,
|
|
256
|
+
className: cx("file-tree__file", className),
|
|
257
|
+
...props,
|
|
258
|
+
children: /* @__PURE__ */ jsxs("button", {
|
|
259
|
+
type: "button",
|
|
260
|
+
className: "file-tree__node file-tree__node--file",
|
|
261
|
+
"data-selected": dataFlag(isSelected),
|
|
262
|
+
"data-focused": dataFlag(isFocused),
|
|
263
|
+
tabIndex: getFileTreeNodeTabIndex(focusedPath, path, level),
|
|
264
|
+
onClick: () => onSelect(path),
|
|
265
|
+
onFocus: () => onFocus(path),
|
|
266
|
+
onKeyDown: (e) => handleKeyDown(e, path, "file"),
|
|
267
|
+
style: { paddingInlineStart: getFileTreeNodeIndent(level, 1.5) },
|
|
268
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
269
|
+
className: "file-tree__icon",
|
|
270
|
+
"aria-hidden": "true",
|
|
271
|
+
children: icon ?? /* @__PURE__ */ jsx(FileIcon, {})
|
|
272
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
273
|
+
className: "file-tree__name",
|
|
274
|
+
children: name
|
|
275
|
+
})]
|
|
276
|
+
})
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
function FileTreeIcon({ className, children, ref, ...props }) {
|
|
280
|
+
return /* @__PURE__ */ jsx("span", {
|
|
281
|
+
ref,
|
|
282
|
+
className: cx("file-tree__icon", className),
|
|
283
|
+
"aria-hidden": "true",
|
|
284
|
+
...props,
|
|
285
|
+
children
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
function FileTreeName({ className, children, ref, ...props }) {
|
|
289
|
+
return /* @__PURE__ */ jsx("span", {
|
|
290
|
+
ref,
|
|
291
|
+
className: cx("file-tree__name", className),
|
|
292
|
+
...props,
|
|
293
|
+
children
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
function FileTreeActions({ className, children, onClick, ref, ...props }) {
|
|
297
|
+
const handleClick = React.useCallback((e) => {
|
|
298
|
+
e.stopPropagation();
|
|
299
|
+
onClick?.(e);
|
|
300
|
+
}, [onClick]);
|
|
301
|
+
return /* @__PURE__ */ jsx("div", {
|
|
302
|
+
ref,
|
|
303
|
+
className: cx("file-tree__actions", className),
|
|
304
|
+
onClick: handleClick,
|
|
305
|
+
...props,
|
|
306
|
+
children
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
//#endregion
|
|
310
|
+
export { FileTreeIcon as a, FileTreeFolder as i, FileTreeActions as n, FileTreeName as o, FileTreeFile as r, FileTree as t };
|