@cloudbase/agent-react-ui 0.0.23
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/README.md +135 -0
- package/components.json +21 -0
- package/dist/index.css +4241 -0
- package/dist/index.css.map +1 -0
- package/dist/index.d.mts +59 -0
- package/dist/index.d.ts +59 -0
- package/dist/index.js +2169 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +2182 -0
- package/dist/index.mjs.map +1 -0
- package/example/.env.sample +2 -0
- package/example/App.tsx +368 -0
- package/example/app.css +1 -0
- package/example/index.html +12 -0
- package/example/main.tsx +9 -0
- package/example/vite.config.ts +34 -0
- package/package.json +75 -0
- package/postcss.config.cjs +3 -0
- package/src/components/ai-elements/agent.tsx +140 -0
- package/src/components/ai-elements/artifact.tsx +147 -0
- package/src/components/ai-elements/attachments.tsx +421 -0
- package/src/components/ai-elements/audio-player.tsx +228 -0
- package/src/components/ai-elements/canvas.tsx +22 -0
- package/src/components/ai-elements/chain-of-thought.tsx +228 -0
- package/src/components/ai-elements/checkpoint.tsx +71 -0
- package/src/components/ai-elements/code-block.tsx +532 -0
- package/src/components/ai-elements/commit.tsx +448 -0
- package/src/components/ai-elements/confirmation.tsx +176 -0
- package/src/components/ai-elements/connection.tsx +28 -0
- package/src/components/ai-elements/context.tsx +408 -0
- package/src/components/ai-elements/controls.tsx +18 -0
- package/src/components/ai-elements/conversation.tsx +100 -0
- package/src/components/ai-elements/edge.tsx +140 -0
- package/src/components/ai-elements/environment-variables.tsx +295 -0
- package/src/components/ai-elements/file-tree.tsx +258 -0
- package/src/components/ai-elements/image.tsx +24 -0
- package/src/components/ai-elements/inline-citation.tsx +287 -0
- package/src/components/ai-elements/message.tsx +336 -0
- package/src/components/ai-elements/mic-selector.tsx +370 -0
- package/src/components/ai-elements/model-selector.tsx +211 -0
- package/src/components/ai-elements/node.tsx +71 -0
- package/src/components/ai-elements/open-in-chat.tsx +365 -0
- package/src/components/ai-elements/package-info.tsx +233 -0
- package/src/components/ai-elements/panel.tsx +15 -0
- package/src/components/ai-elements/persona.tsx +270 -0
- package/src/components/ai-elements/plan.tsx +142 -0
- package/src/components/ai-elements/prompt-input.tsx +1263 -0
- package/src/components/ai-elements/queue.tsx +274 -0
- package/src/components/ai-elements/reasoning.tsx +193 -0
- package/src/components/ai-elements/sandbox.tsx +126 -0
- package/src/components/ai-elements/schema-display.tsx +458 -0
- package/src/components/ai-elements/shimmer.tsx +64 -0
- package/src/components/ai-elements/snippet.tsx +139 -0
- package/src/components/ai-elements/sources.tsx +77 -0
- package/src/components/ai-elements/speech-input.tsx +301 -0
- package/src/components/ai-elements/stack-trace.tsx +482 -0
- package/src/components/ai-elements/suggestion.tsx +53 -0
- package/src/components/ai-elements/task.tsx +87 -0
- package/src/components/ai-elements/terminal.tsx +261 -0
- package/src/components/ai-elements/test-results.tsx +485 -0
- package/src/components/ai-elements/tool.tsx +174 -0
- package/src/components/ai-elements/toolbar.tsx +16 -0
- package/src/components/ai-elements/transcription.tsx +124 -0
- package/src/components/ai-elements/voice-selector.tsx +479 -0
- package/src/components/ai-elements/web-preview.tsx +263 -0
- package/src/components/chat/Chat.tsx +178 -0
- package/src/components/chat/Input.tsx +98 -0
- package/src/components/chat/Message.tsx +276 -0
- package/src/components/chat/index.ts +2 -0
- package/src/components/index.ts +1 -0
- package/src/components/ui/accordion.tsx +64 -0
- package/src/components/ui/alert.tsx +66 -0
- package/src/components/ui/avatar.tsx +107 -0
- package/src/components/ui/badge.tsx +48 -0
- package/src/components/ui/button-group.tsx +83 -0
- package/src/components/ui/button.tsx +64 -0
- package/src/components/ui/card.tsx +92 -0
- package/src/components/ui/carousel.tsx +239 -0
- package/src/components/ui/collapsible.tsx +31 -0
- package/src/components/ui/command.tsx +184 -0
- package/src/components/ui/dialog.tsx +158 -0
- package/src/components/ui/dropdown-menu.tsx +257 -0
- package/src/components/ui/hover-card.tsx +42 -0
- package/src/components/ui/input-group.tsx +168 -0
- package/src/components/ui/input.tsx +21 -0
- package/src/components/ui/popover.tsx +87 -0
- package/src/components/ui/progress.tsx +31 -0
- package/src/components/ui/scroll-area.tsx +56 -0
- package/src/components/ui/select.tsx +190 -0
- package/src/components/ui/separator.tsx +28 -0
- package/src/components/ui/spinner.tsx +16 -0
- package/src/components/ui/switch.tsx +33 -0
- package/src/components/ui/tabs.tsx +91 -0
- package/src/components/ui/textarea.tsx +18 -0
- package/src/components/ui/tooltip.tsx +61 -0
- package/src/css/global.css +123 -0
- package/src/css/index.css +1 -0
- package/src/hooks/index.ts +1 -0
- package/src/hooks/use-copy-to-clipboard.ts +31 -0
- package/src/index.ts +4 -0
- package/src/lib/utils.ts +6 -0
- package/src/locales/context.ts +8 -0
- package/src/locales/hooks.ts +20 -0
- package/src/locales/index.ts +3 -0
- package/src/locales/langs/en.ts +17 -0
- package/src/locales/langs/index.ts +12 -0
- package/src/locales/langs/zh-cn.ts +18 -0
- package/tsconfig.json +21 -0
- package/tsup.config.ts +21 -0
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { Button } from "@/components/ui/button";
|
|
4
|
+
import { cn } from "@/lib/utils";
|
|
5
|
+
import Ansi from "ansi-to-react";
|
|
6
|
+
import { CheckIcon, CopyIcon, TerminalIcon, Trash2Icon } from "lucide-react";
|
|
7
|
+
import {
|
|
8
|
+
type ComponentProps,
|
|
9
|
+
createContext,
|
|
10
|
+
type HTMLAttributes,
|
|
11
|
+
useContext,
|
|
12
|
+
useEffect,
|
|
13
|
+
useRef,
|
|
14
|
+
useState,
|
|
15
|
+
} from "react";
|
|
16
|
+
import { Shimmer } from "./shimmer";
|
|
17
|
+
|
|
18
|
+
interface TerminalContextType {
|
|
19
|
+
output: string;
|
|
20
|
+
isStreaming: boolean;
|
|
21
|
+
autoScroll: boolean;
|
|
22
|
+
onClear?: () => void;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const TerminalContext = createContext<TerminalContextType>({
|
|
26
|
+
output: "",
|
|
27
|
+
isStreaming: false,
|
|
28
|
+
autoScroll: true,
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
export type TerminalProps = HTMLAttributes<HTMLDivElement> & {
|
|
32
|
+
output: string;
|
|
33
|
+
isStreaming?: boolean;
|
|
34
|
+
autoScroll?: boolean;
|
|
35
|
+
onClear?: () => void;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export const Terminal = ({
|
|
39
|
+
output,
|
|
40
|
+
isStreaming = false,
|
|
41
|
+
autoScroll = true,
|
|
42
|
+
onClear,
|
|
43
|
+
className,
|
|
44
|
+
children,
|
|
45
|
+
...props
|
|
46
|
+
}: TerminalProps) => (
|
|
47
|
+
<TerminalContext.Provider
|
|
48
|
+
value={{ output, isStreaming, autoScroll, onClear }}
|
|
49
|
+
>
|
|
50
|
+
<div
|
|
51
|
+
className={cn(
|
|
52
|
+
"flex flex-col overflow-hidden rounded-lg border bg-zinc-950 text-zinc-100",
|
|
53
|
+
className
|
|
54
|
+
)}
|
|
55
|
+
{...props}
|
|
56
|
+
>
|
|
57
|
+
{children ?? (
|
|
58
|
+
<>
|
|
59
|
+
<TerminalHeader>
|
|
60
|
+
<TerminalTitle />
|
|
61
|
+
<div className="flex items-center gap-1">
|
|
62
|
+
<TerminalStatus />
|
|
63
|
+
<TerminalActions>
|
|
64
|
+
<TerminalCopyButton />
|
|
65
|
+
{onClear && <TerminalClearButton />}
|
|
66
|
+
</TerminalActions>
|
|
67
|
+
</div>
|
|
68
|
+
</TerminalHeader>
|
|
69
|
+
<TerminalContent />
|
|
70
|
+
</>
|
|
71
|
+
)}
|
|
72
|
+
</div>
|
|
73
|
+
</TerminalContext.Provider>
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
export type TerminalHeaderProps = HTMLAttributes<HTMLDivElement>;
|
|
77
|
+
|
|
78
|
+
export const TerminalHeader = ({
|
|
79
|
+
className,
|
|
80
|
+
children,
|
|
81
|
+
...props
|
|
82
|
+
}: TerminalHeaderProps) => (
|
|
83
|
+
<div
|
|
84
|
+
className={cn(
|
|
85
|
+
"flex items-center justify-between border-zinc-800 border-b px-4 py-2",
|
|
86
|
+
className
|
|
87
|
+
)}
|
|
88
|
+
{...props}
|
|
89
|
+
>
|
|
90
|
+
{children}
|
|
91
|
+
</div>
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
export type TerminalTitleProps = HTMLAttributes<HTMLDivElement>;
|
|
95
|
+
|
|
96
|
+
export const TerminalTitle = ({
|
|
97
|
+
className,
|
|
98
|
+
children,
|
|
99
|
+
...props
|
|
100
|
+
}: TerminalTitleProps) => (
|
|
101
|
+
<div
|
|
102
|
+
className={cn("flex items-center gap-2 text-sm text-zinc-400", className)}
|
|
103
|
+
{...props}
|
|
104
|
+
>
|
|
105
|
+
<TerminalIcon className="size-4" />
|
|
106
|
+
{children ?? "Terminal"}
|
|
107
|
+
</div>
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
export type TerminalStatusProps = HTMLAttributes<HTMLDivElement>;
|
|
111
|
+
|
|
112
|
+
export const TerminalStatus = ({
|
|
113
|
+
className,
|
|
114
|
+
children,
|
|
115
|
+
...props
|
|
116
|
+
}: TerminalStatusProps) => {
|
|
117
|
+
const { isStreaming } = useContext(TerminalContext);
|
|
118
|
+
|
|
119
|
+
if (!isStreaming) {
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return (
|
|
124
|
+
<div
|
|
125
|
+
className={cn("flex items-center gap-2 text-xs text-zinc-400", className)}
|
|
126
|
+
{...props}
|
|
127
|
+
>
|
|
128
|
+
{children ?? <Shimmer className="w-16" />}
|
|
129
|
+
</div>
|
|
130
|
+
);
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
export type TerminalActionsProps = HTMLAttributes<HTMLDivElement>;
|
|
134
|
+
|
|
135
|
+
export const TerminalActions = ({
|
|
136
|
+
className,
|
|
137
|
+
children,
|
|
138
|
+
...props
|
|
139
|
+
}: TerminalActionsProps) => (
|
|
140
|
+
<div className={cn("flex items-center gap-1", className)} {...props}>
|
|
141
|
+
{children}
|
|
142
|
+
</div>
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
export type TerminalCopyButtonProps = ComponentProps<typeof Button> & {
|
|
146
|
+
onCopy?: () => void;
|
|
147
|
+
onError?: (error: Error) => void;
|
|
148
|
+
timeout?: number;
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
export const TerminalCopyButton = ({
|
|
152
|
+
onCopy,
|
|
153
|
+
onError,
|
|
154
|
+
timeout = 2000,
|
|
155
|
+
children,
|
|
156
|
+
className,
|
|
157
|
+
...props
|
|
158
|
+
}: TerminalCopyButtonProps) => {
|
|
159
|
+
const [isCopied, setIsCopied] = useState(false);
|
|
160
|
+
const { output } = useContext(TerminalContext);
|
|
161
|
+
|
|
162
|
+
const copyToClipboard = async () => {
|
|
163
|
+
if (typeof window === "undefined" || !navigator?.clipboard?.writeText) {
|
|
164
|
+
onError?.(new Error("Clipboard API not available"));
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
try {
|
|
169
|
+
await navigator.clipboard.writeText(output);
|
|
170
|
+
setIsCopied(true);
|
|
171
|
+
onCopy?.();
|
|
172
|
+
setTimeout(() => setIsCopied(false), timeout);
|
|
173
|
+
} catch (error) {
|
|
174
|
+
onError?.(error as Error);
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
const Icon = isCopied ? CheckIcon : CopyIcon;
|
|
179
|
+
|
|
180
|
+
return (
|
|
181
|
+
<Button
|
|
182
|
+
className={cn(
|
|
183
|
+
"size-7 shrink-0 text-zinc-400 hover:bg-zinc-800 hover:text-zinc-100",
|
|
184
|
+
className
|
|
185
|
+
)}
|
|
186
|
+
onClick={copyToClipboard}
|
|
187
|
+
size="icon"
|
|
188
|
+
variant="ghost"
|
|
189
|
+
{...props}
|
|
190
|
+
>
|
|
191
|
+
{children ?? <Icon size={14} />}
|
|
192
|
+
</Button>
|
|
193
|
+
);
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
export type TerminalClearButtonProps = ComponentProps<typeof Button>;
|
|
197
|
+
|
|
198
|
+
export const TerminalClearButton = ({
|
|
199
|
+
children,
|
|
200
|
+
className,
|
|
201
|
+
...props
|
|
202
|
+
}: TerminalClearButtonProps) => {
|
|
203
|
+
const { onClear } = useContext(TerminalContext);
|
|
204
|
+
|
|
205
|
+
if (!onClear) {
|
|
206
|
+
return null;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
return (
|
|
210
|
+
<Button
|
|
211
|
+
className={cn(
|
|
212
|
+
"size-7 shrink-0 text-zinc-400 hover:bg-zinc-800 hover:text-zinc-100",
|
|
213
|
+
className
|
|
214
|
+
)}
|
|
215
|
+
onClick={onClear}
|
|
216
|
+
size="icon"
|
|
217
|
+
variant="ghost"
|
|
218
|
+
{...props}
|
|
219
|
+
>
|
|
220
|
+
{children ?? <Trash2Icon size={14} />}
|
|
221
|
+
</Button>
|
|
222
|
+
);
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
export type TerminalContentProps = HTMLAttributes<HTMLDivElement>;
|
|
226
|
+
|
|
227
|
+
export const TerminalContent = ({
|
|
228
|
+
className,
|
|
229
|
+
children,
|
|
230
|
+
...props
|
|
231
|
+
}: TerminalContentProps) => {
|
|
232
|
+
const { output, isStreaming, autoScroll } = useContext(TerminalContext);
|
|
233
|
+
const containerRef = useRef<HTMLDivElement>(null);
|
|
234
|
+
|
|
235
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies: output triggers auto-scroll when new content arrives
|
|
236
|
+
useEffect(() => {
|
|
237
|
+
if (autoScroll && containerRef.current) {
|
|
238
|
+
containerRef.current.scrollTop = containerRef.current.scrollHeight;
|
|
239
|
+
}
|
|
240
|
+
}, [output, autoScroll]);
|
|
241
|
+
|
|
242
|
+
return (
|
|
243
|
+
<div
|
|
244
|
+
className={cn(
|
|
245
|
+
"max-h-96 overflow-auto p-4 font-mono text-sm leading-relaxed",
|
|
246
|
+
className
|
|
247
|
+
)}
|
|
248
|
+
ref={containerRef}
|
|
249
|
+
{...props}
|
|
250
|
+
>
|
|
251
|
+
{children ?? (
|
|
252
|
+
<pre className="whitespace-pre-wrap break-words">
|
|
253
|
+
<Ansi>{output}</Ansi>
|
|
254
|
+
{isStreaming && (
|
|
255
|
+
<span className="ml-0.5 inline-block h-4 w-2 animate-pulse bg-zinc-100" />
|
|
256
|
+
)}
|
|
257
|
+
</pre>
|
|
258
|
+
)}
|
|
259
|
+
</div>
|
|
260
|
+
);
|
|
261
|
+
};
|