@mcp-b/react-components 0.2.2 → 0.4.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/attachment-preview-ChtC3HiU.js +25 -0
- package/dist/components/Activity.js +1 -1
- package/dist/components/AgentChat.d.ts +56 -9
- package/dist/components/AgentChat.js +146 -47
- package/dist/components/AgentConnection.js +3 -3
- 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/Context.d.ts +28 -27
- package/dist/components/Context.js +48 -47
- 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 +17 -2
- package/dist/components/Message.js +36 -2
- package/dist/components/ModelSelector.js +1 -1
- package/dist/components/NavigationMenu.js +1 -1
- package/dist/components/PricingPage.js +2 -2
- package/dist/components/PromptInput.d.ts +143 -10
- package/dist/components/PromptInput.js +318 -5
- 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/Suggestion.d.ts +43 -0
- package/dist/components/Suggestion.js +39 -0
- 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 +207 -0
- package/dist/components/ThinkChat.js +798 -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/agent-chat.css +19 -0
- package/dist/styles/attachment-preview.css +21 -0
- package/dist/styles/context.css +9 -17
- package/dist/styles/index.css +2 -0
- package/dist/styles/message.css +48 -0
- package/dist/styles/prompt-input.css +321 -0
- package/dist/styles/suggestions.css +21 -0
- package/package.json +26 -3
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CollapsiblePanel, CollapsibleRoot, CollapsibleTrigger } from "./Collapsible.js";
|
|
2
2
|
import { t as cx } from "../class-names-9UtZwb0J.js";
|
|
3
|
-
import {
|
|
3
|
+
import { A as SpinnerIcon, d as DotIcon, l as ChevronRightIcon, o as CheckIcon } from "../icons-DQC4Zw5R.js";
|
|
4
4
|
import "react";
|
|
5
5
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
6
|
//#region src/components/ChainOfThought.tsx
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as CodeBlockCopyButton, c as CodeBlockLanguageSelector, d as CodeBlockLanguageSelectorTrigger, f as CodeBlockLanguageSelectorValue, h as CODE_BLOCK_LANGUAGES, i as CodeBlockContent, l as CodeBlockLanguageSelectorContent, m as highlightCode, n as CodeBlockActions, o as CodeBlockFilename, p as CodeBlockTitle, r as CodeBlockContainer, s as CodeBlockHeader, t as CodeBlock, u as CodeBlockLanguageSelectorItem } from "../CodeBlock-
|
|
1
|
+
import { a as CodeBlockCopyButton, c as CodeBlockLanguageSelector, d as CodeBlockLanguageSelectorTrigger, f as CodeBlockLanguageSelectorValue, h as CODE_BLOCK_LANGUAGES, i as CodeBlockContent, l as CodeBlockLanguageSelectorContent, m as highlightCode, n as CodeBlockActions, o as CodeBlockFilename, p as CodeBlockTitle, r as CodeBlockContainer, s as CodeBlockHeader, t as CodeBlock, u as CodeBlockLanguageSelectorItem } from "../CodeBlock-C2Xjxu9M.js";
|
|
2
2
|
export { CODE_BLOCK_LANGUAGES, CodeBlock, CodeBlockActions, CodeBlockContainer, CodeBlockContent, CodeBlockCopyButton, CodeBlockFilename, CodeBlockHeader, CodeBlockLanguageSelector, CodeBlockLanguageSelectorContent, CodeBlockLanguageSelectorItem, CodeBlockLanguageSelectorTrigger, CodeBlockLanguageSelectorValue, CodeBlockTitle, highlightCode };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CollapsiblePanel, CollapsibleRoot, CollapsibleTrigger } from "./Collapsible.js";
|
|
2
2
|
import { t as cx } from "../class-names-9UtZwb0J.js";
|
|
3
|
-
import { h as FileIcon, l as ChevronRightIcon, o as CheckIcon, u as CopyIcon } from "../icons-
|
|
3
|
+
import { h as FileIcon, l as ChevronRightIcon, o as CheckIcon, u as CopyIcon } from "../icons-DQC4Zw5R.js";
|
|
4
4
|
import { Button } from "./Button.js";
|
|
5
5
|
import { Tooltip, TooltipPopup, TooltipPortal, TooltipPositioner, TooltipTrigger } from "./Tooltip.js";
|
|
6
6
|
import { Badge } from "./Badge.js";
|
|
@@ -1,31 +1,21 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { PopoverProps } from "./Popover.js";
|
|
1
|
+
import { PopoverPositionerProps, PopoverProps } from "./Popover.js";
|
|
3
2
|
import * as React from "react";
|
|
3
|
+
import { LanguageModelUsage, UIMessage } from "ai";
|
|
4
4
|
|
|
5
5
|
//#region src/components/Context.d.ts
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
input?: number;
|
|
13
|
-
inputTokens?: number;
|
|
14
|
-
output?: number;
|
|
15
|
-
outputTokens?: number;
|
|
16
|
-
reasoning?: number;
|
|
17
|
-
reasoningTokens?: number;
|
|
18
|
-
cache?: number;
|
|
19
|
-
cachedInputTokens?: number;
|
|
20
|
-
categories?: ContextUsageCategory[];
|
|
21
|
-
}
|
|
6
|
+
/**
|
|
7
|
+
* The AI SDK's `LanguageModelUsage`, taken whole. `Partial` only relaxes the
|
|
8
|
+
* required-but-`undefined`able keys for fixtures/JSX literals — key names and
|
|
9
|
+
* meanings are upstream's.
|
|
10
|
+
*/
|
|
11
|
+
type ContextTokenUsage = Partial<LanguageModelUsage>;
|
|
22
12
|
interface ContextProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
23
13
|
/** Tokens currently used. */
|
|
24
14
|
usedTokens: number;
|
|
25
15
|
/** Maximum context window size. */
|
|
26
16
|
maxTokens: number;
|
|
27
17
|
/** Optional usage breakdown. */
|
|
28
|
-
usage?:
|
|
18
|
+
usage?: ContextTokenUsage;
|
|
29
19
|
/** Optional model identifier shown in the header. */
|
|
30
20
|
modelId?: string;
|
|
31
21
|
/** Optional total cost in USD. */
|
|
@@ -36,8 +26,8 @@ interface ContextProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
|
36
26
|
}
|
|
37
27
|
/**
|
|
38
28
|
* Displays token / context usage with a hover card breakdown. The trigger is
|
|
39
|
-
* a
|
|
40
|
-
*
|
|
29
|
+
* a bare progress ring; clicking it opens a popover (upward by default) with
|
|
30
|
+
* category rows and total cost.
|
|
41
31
|
*
|
|
42
32
|
* @example
|
|
43
33
|
* ```tsx
|
|
@@ -45,7 +35,7 @@ interface ContextProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
|
45
35
|
* usedTokens={42_300}
|
|
46
36
|
* maxTokens={200_000}
|
|
47
37
|
* modelId="claude-opus-4-6"
|
|
48
|
-
* usage={{
|
|
38
|
+
* usage={{ inputTokens: 30000, outputTokens: 12300 }}
|
|
49
39
|
* totalCostUsd={0.42}
|
|
50
40
|
* >
|
|
51
41
|
* <ContextTrigger />
|
|
@@ -73,17 +63,19 @@ declare function Context({
|
|
|
73
63
|
}: ContextProps & {
|
|
74
64
|
ref?: React.Ref<HTMLDivElement>;
|
|
75
65
|
}): React.JSX.Element;
|
|
76
|
-
interface ContextTriggerProps extends
|
|
77
|
-
className?: string;
|
|
78
|
-
}
|
|
66
|
+
interface ContextTriggerProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {}
|
|
79
67
|
declare function ContextTrigger({
|
|
80
68
|
className,
|
|
81
69
|
children,
|
|
82
70
|
...props
|
|
83
71
|
}: ContextTriggerProps): React.JSX.Element;
|
|
84
|
-
interface ContextContentProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
72
|
+
interface ContextContentProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
73
|
+
/** The trigger usually sits in a composer at the bottom, so default "top". */
|
|
74
|
+
side?: PopoverPositionerProps["side"];
|
|
75
|
+
}
|
|
85
76
|
declare function ContextContent({
|
|
86
77
|
className,
|
|
78
|
+
side,
|
|
87
79
|
children,
|
|
88
80
|
...props
|
|
89
81
|
}: ContextContentProps): React.JSX.Element;
|
|
@@ -125,5 +117,14 @@ declare function ContextInputUsage(props: ContextInputUsageProps): React.JSX.Ele
|
|
|
125
117
|
declare function ContextOutputUsage(props: ContextOutputUsageProps): React.JSX.Element;
|
|
126
118
|
declare function ContextReasoningUsage(props: ContextReasoningUsageProps): React.JSX.Element;
|
|
127
119
|
declare function ContextCacheUsage(props: ContextCacheUsageProps): React.JSX.Element;
|
|
120
|
+
/**
|
|
121
|
+
* Latest `metadata.usage` in a transcript — the AI SDK convention for token
|
|
122
|
+
* accounting (`toUIMessageStreamResponse({ messageMetadata })`), which Think
|
|
123
|
+
* merges into `message.metadata` as turns finish. Structural: any message
|
|
124
|
+
* whose metadata carries a `usage` object qualifies.
|
|
125
|
+
*/
|
|
126
|
+
declare function getContextUsage(messages: readonly UIMessage[]): LanguageModelUsage | undefined;
|
|
127
|
+
/** Tokens occupying the context window: `totalTokens`, or input + output. */
|
|
128
|
+
declare function getContextUsedTokens(usage: LanguageModelUsage | undefined): number;
|
|
128
129
|
//#endregion
|
|
129
|
-
export { Context, ContextCacheUsage, ContextCacheUsageProps, ContextContent, ContextContentBody, ContextContentBodyProps, ContextContentFooter, ContextContentFooterProps, ContextContentHeader, ContextContentHeaderProps, ContextContentProps, ContextInputUsage, ContextInputUsageProps, ContextOutputUsage, ContextOutputUsageProps, ContextProps, ContextReasoningUsage, ContextReasoningUsageProps, ContextTrigger, ContextTriggerProps,
|
|
130
|
+
export { Context, ContextCacheUsage, ContextCacheUsageProps, ContextContent, ContextContentBody, ContextContentBodyProps, ContextContentFooter, ContextContentFooterProps, ContextContentHeader, ContextContentHeaderProps, ContextContentProps, ContextInputUsage, ContextInputUsageProps, ContextOutputUsage, ContextOutputUsageProps, ContextProps, ContextReasoningUsage, ContextReasoningUsageProps, ContextTokenUsage, ContextTrigger, ContextTriggerProps, ContextUsageRowProps, getContextUsage, getContextUsedTokens };
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { t as cx } from "../class-names-9UtZwb0J.js";
|
|
2
|
-
import { Button } from "./Button.js";
|
|
3
2
|
import { Popover } from "./Popover.js";
|
|
4
3
|
import { Separator } from "./Separator.js";
|
|
5
4
|
import * as React from "react";
|
|
@@ -13,8 +12,8 @@ function useContextContext() {
|
|
|
13
12
|
}
|
|
14
13
|
/**
|
|
15
14
|
* Displays token / context usage with a hover card breakdown. The trigger is
|
|
16
|
-
* a
|
|
17
|
-
*
|
|
15
|
+
* a bare progress ring; clicking it opens a popover (upward by default) with
|
|
16
|
+
* category rows and total cost.
|
|
18
17
|
*
|
|
19
18
|
* @example
|
|
20
19
|
* ```tsx
|
|
@@ -22,7 +21,7 @@ function useContextContext() {
|
|
|
22
21
|
* usedTokens={42_300}
|
|
23
22
|
* maxTokens={200_000}
|
|
24
23
|
* modelId="claude-opus-4-6"
|
|
25
|
-
* usage={{
|
|
24
|
+
* usage={{ inputTokens: 30000, outputTokens: 12300 }}
|
|
26
25
|
* totalCostUsd={0.42}
|
|
27
26
|
* >
|
|
28
27
|
* <ContextTrigger />
|
|
@@ -68,33 +67,26 @@ function ContextTrigger({ className, children, ...props }) {
|
|
|
68
67
|
const percent = maxTokens > 0 ? usedTokens / maxTokens * 100 : 0;
|
|
69
68
|
if (React.isValidElement(children)) return /* @__PURE__ */ jsx(Popover.Trigger, { render: children });
|
|
70
69
|
if (children) return /* @__PURE__ */ jsx(Popover.Trigger, { children });
|
|
71
|
-
return /* @__PURE__ */ jsx(Popover.Trigger, {
|
|
72
|
-
variant: "ghost",
|
|
73
|
-
color: "neutral",
|
|
74
|
-
size: "sm",
|
|
70
|
+
return /* @__PURE__ */ jsx(Popover.Trigger, {
|
|
75
71
|
className: cx("context__trigger", className),
|
|
76
72
|
"aria-label": `Context usage: ${percent.toFixed(0)}%`,
|
|
77
73
|
...props,
|
|
78
|
-
children:
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
stroke: 2.5
|
|
85
|
-
})
|
|
86
|
-
}), /* @__PURE__ */ jsxs("span", {
|
|
87
|
-
className: "context__trigger-label",
|
|
88
|
-
children: [percent.toFixed(0), "%"]
|
|
89
|
-
})]
|
|
90
|
-
}) });
|
|
74
|
+
children: /* @__PURE__ */ jsx(ProgressRing, {
|
|
75
|
+
percent,
|
|
76
|
+
size: 16,
|
|
77
|
+
stroke: 2.5
|
|
78
|
+
})
|
|
79
|
+
});
|
|
91
80
|
}
|
|
92
|
-
function ContextContent({ className, children, ...props }) {
|
|
93
|
-
return /* @__PURE__ */ jsx(Popover.Portal, { children: /* @__PURE__ */ jsx(Popover.Positioner, {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
81
|
+
function ContextContent({ className, side = "top", children, ...props }) {
|
|
82
|
+
return /* @__PURE__ */ jsx(Popover.Portal, { children: /* @__PURE__ */ jsx(Popover.Positioner, {
|
|
83
|
+
side,
|
|
84
|
+
children: /* @__PURE__ */ jsx(Popover.Popup, {
|
|
85
|
+
className: cx("context__content", className),
|
|
86
|
+
...props,
|
|
87
|
+
children
|
|
88
|
+
})
|
|
89
|
+
}) });
|
|
98
90
|
}
|
|
99
91
|
function ContextContentHeader({ className, children, ref, ...props }) {
|
|
100
92
|
const { usedTokens, maxTokens, modelId } = useContextContext();
|
|
@@ -173,7 +165,6 @@ function ContextContentBody({ className, children, ref, ...props }) {
|
|
|
173
165
|
label: "Cache",
|
|
174
166
|
tokens: cacheTokens
|
|
175
167
|
});
|
|
176
|
-
if (usage?.categories) rows.push(...usage.categories);
|
|
177
168
|
return /* @__PURE__ */ jsxs("div", {
|
|
178
169
|
ref,
|
|
179
170
|
className: cx("context__body", className),
|
|
@@ -182,20 +173,13 @@ function ContextContentBody({ className, children, ref, ...props }) {
|
|
|
182
173
|
className: "context__rows",
|
|
183
174
|
children: rows.map((row) => /* @__PURE__ */ jsxs("li", {
|
|
184
175
|
className: "context__row",
|
|
185
|
-
children: [
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
children: row.tokens.toLocaleString()
|
|
193
|
-
}),
|
|
194
|
-
row.costUsd !== void 0 ? /* @__PURE__ */ jsxs("span", {
|
|
195
|
-
className: "context__row-cost",
|
|
196
|
-
children: ["$", row.costUsd.toFixed(4)]
|
|
197
|
-
}) : null
|
|
198
|
-
]
|
|
176
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
177
|
+
className: "context__row-label",
|
|
178
|
+
children: row.label
|
|
179
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
180
|
+
className: "context__row-value",
|
|
181
|
+
children: row.tokens.toLocaleString()
|
|
182
|
+
})]
|
|
199
183
|
}, row.label))
|
|
200
184
|
})]
|
|
201
185
|
});
|
|
@@ -269,10 +253,27 @@ function ContextUsageRow({ className, children, label, usageKey, defaultLabel, r
|
|
|
269
253
|
}
|
|
270
254
|
function getUsageTokens(usage, key) {
|
|
271
255
|
if (!usage) return void 0;
|
|
272
|
-
if (key === "input") return usage.
|
|
273
|
-
if (key === "output") return usage.
|
|
274
|
-
if (key === "reasoning") return usage.
|
|
275
|
-
return usage.
|
|
256
|
+
if (key === "input") return usage.inputTokens;
|
|
257
|
+
if (key === "output") return usage.outputTokens;
|
|
258
|
+
if (key === "reasoning") return usage.outputTokenDetails?.reasoningTokens ?? usage.reasoningTokens;
|
|
259
|
+
return usage.inputTokenDetails?.cacheReadTokens ?? usage.cachedInputTokens;
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Latest `metadata.usage` in a transcript — the AI SDK convention for token
|
|
263
|
+
* accounting (`toUIMessageStreamResponse({ messageMetadata })`), which Think
|
|
264
|
+
* merges into `message.metadata` as turns finish. Structural: any message
|
|
265
|
+
* whose metadata carries a `usage` object qualifies.
|
|
266
|
+
*/
|
|
267
|
+
function getContextUsage(messages) {
|
|
268
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
269
|
+
const usage = messages[i].metadata?.usage;
|
|
270
|
+
if (usage && typeof usage === "object") return usage;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
/** Tokens occupying the context window: `totalTokens`, or input + output. */
|
|
274
|
+
function getContextUsedTokens(usage) {
|
|
275
|
+
if (!usage) return 0;
|
|
276
|
+
return usage.totalTokens ?? (usage.inputTokens ?? 0) + (usage.outputTokens ?? 0);
|
|
276
277
|
}
|
|
277
278
|
function ProgressRing({ percent, size, stroke }) {
|
|
278
279
|
const radius = (size - stroke) / 2;
|
|
@@ -306,4 +307,4 @@ function ProgressRing({ percent, size, stroke }) {
|
|
|
306
307
|
});
|
|
307
308
|
}
|
|
308
309
|
//#endregion
|
|
309
|
-
export { Context, ContextCacheUsage, ContextContent, ContextContentBody, ContextContentFooter, ContextContentHeader, ContextInputUsage, ContextOutputUsage, ContextReasoningUsage, ContextTrigger };
|
|
310
|
+
export { Context, ContextCacheUsage, ContextContent, ContextContentBody, ContextContentFooter, ContextContentHeader, ContextInputUsage, ContextOutputUsage, ContextReasoningUsage, ContextTrigger, getContextUsage, getContextUsedTokens };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { d as DotIcon, l as ChevronRightIcon, o as CheckIcon } from "../icons-
|
|
1
|
+
import { d as DotIcon, l as ChevronRightIcon, o as CheckIcon } from "../icons-DQC4Zw5R.js";
|
|
2
2
|
import "react";
|
|
3
3
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
4
|
import { ContextMenu as ContextMenu$1 } from "@base-ui/react/context-menu";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as cx } from "../class-names-9UtZwb0J.js";
|
|
2
|
-
import { f as DownloadIcon, t as ArrowDownIcon } from "../icons-
|
|
2
|
+
import { f as DownloadIcon, t as ArrowDownIcon } from "../icons-DQC4Zw5R.js";
|
|
3
3
|
import { Button } from "./Button.js";
|
|
4
4
|
import { useStickToBottom } from "./useStickToBottom.js";
|
|
5
5
|
import * as React from "react";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as cx } from "../class-names-9UtZwb0J.js";
|
|
2
|
-
import { m as EyeOffIcon, o as CheckIcon, p as EyeIcon, u as CopyIcon } from "../icons-
|
|
2
|
+
import { m as EyeOffIcon, o as CheckIcon, p as EyeIcon, u as CopyIcon } from "../icons-DQC4Zw5R.js";
|
|
3
3
|
import { Button } from "./Button.js";
|
|
4
4
|
import { Tooltip, TooltipPopup, TooltipPortal, TooltipPositioner, TooltipTrigger } from "./Tooltip.js";
|
|
5
5
|
import { Badge } from "./Badge.js";
|
|
@@ -1,310 +1,2 @@
|
|
|
1
|
-
import { t as
|
|
2
|
-
import { _ as FolderOpenIcon, g as FolderIcon, h as FileIcon, l as ChevronRightIcon } from "../icons-Bf7JMKk-.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
|
|
1
|
+
import { a as FileTreeIcon, i as FileTreeFolder, n as FileTreeActions, o as FileTreeName, r as FileTreeFile, t as FileTree } from "../FileTree-D0c9Yj9U.js";
|
|
310
2
|
export { FileTree, FileTreeActions, FileTreeFile, FileTreeFolder, FileTreeIcon, FileTreeName };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { d as DotIcon, l as ChevronRightIcon, o as CheckIcon } from "../icons-
|
|
1
|
+
import { d as DotIcon, l as ChevronRightIcon, o as CheckIcon } from "../icons-DQC4Zw5R.js";
|
|
2
2
|
import "react";
|
|
3
3
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
4
|
import { Menu } from "@base-ui/react/menu";
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { r as ButtonProps } from "../Button-Ct5I6aTu.js";
|
|
2
2
|
import * as React from "react";
|
|
3
|
+
import { FileUIPart, UIMessage } from "ai";
|
|
3
4
|
import { StreamdownProps } from "streamdown";
|
|
4
5
|
|
|
5
6
|
//#region src/components/Message.d.ts
|
|
6
|
-
type MessageRole = "
|
|
7
|
+
type MessageRole = UIMessage["role"] | (string & {});
|
|
7
8
|
interface MessageProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
8
9
|
/**
|
|
9
10
|
* The originating role of the message. Controls alignment and styling via
|
|
@@ -59,6 +60,20 @@ declare const MessageResponse: React.MemoExoticComponent<({
|
|
|
59
60
|
className,
|
|
60
61
|
...props
|
|
61
62
|
}: MessageResponseProps) => React.JSX.Element>;
|
|
63
|
+
interface MessageAttachmentProps extends Omit<React.HTMLAttributes<HTMLElement>, "part"> {
|
|
64
|
+
/** The AI SDK `file` part, taken whole. */
|
|
65
|
+
part: FileUIPart;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* A `file` part inside a message: images render inline (click to zoom),
|
|
69
|
+
* anything else becomes a download chip. Covers both directions — files the
|
|
70
|
+
* user attached and files the agent emitted.
|
|
71
|
+
*/
|
|
72
|
+
declare function MessageAttachment({
|
|
73
|
+
part,
|
|
74
|
+
className,
|
|
75
|
+
...props
|
|
76
|
+
}: MessageAttachmentProps): React.JSX.Element;
|
|
62
77
|
interface MessageActionsProps extends React.HTMLAttributes<HTMLDivElement> {}
|
|
63
78
|
/**
|
|
64
79
|
* Horizontal list of action buttons (copy, retry, thumbs-up, etc.) shown
|
|
@@ -213,4 +228,4 @@ declare function MessageBranchPage({
|
|
|
213
228
|
ref?: React.Ref<HTMLSpanElement>;
|
|
214
229
|
}): React.JSX.Element;
|
|
215
230
|
//#endregion
|
|
216
|
-
export { Message, MessageAction, MessageActionProps, MessageActions, MessageActionsProps, MessageBranch, MessageBranchContent, MessageBranchContentProps, MessageBranchNext, MessageBranchNextProps, MessageBranchPage, MessageBranchPageProps, MessageBranchPrevious, MessageBranchPreviousProps, MessageBranchProps, MessageBranchSelector, MessageBranchSelectorProps, MessageContent, MessageContentProps, MessageProps, MessageResponse, MessageResponseProps, MessageRole, MessageToolbar, MessageToolbarProps };
|
|
231
|
+
export { Message, MessageAction, MessageActionProps, MessageActions, MessageActionsProps, MessageAttachment, MessageAttachmentProps, MessageBranch, MessageBranchContent, MessageBranchContentProps, MessageBranchNext, MessageBranchNextProps, MessageBranchPage, MessageBranchPageProps, MessageBranchPrevious, MessageBranchPreviousProps, MessageBranchProps, MessageBranchSelector, MessageBranchSelectorProps, MessageContent, MessageContentProps, MessageProps, MessageResponse, MessageResponseProps, MessageRole, MessageToolbar, MessageToolbarProps };
|