@agent-platform/ui 0.0.3 → 0.0.6
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/components/agent/agent-input.js +2 -1
- package/dist/components/agent/agent-popup-widget.js +1 -1
- package/dist/components/agent/index.d.ts +3 -3
- package/dist/components/agent/index.js +1 -1
- package/dist/components/agent/message/markdown.js +9 -9
- package/dist/components/agent/message/message-item.d.ts +1 -1
- package/dist/components/agent/message/message-item.js +1 -1
- package/dist/components/agent/message/message-list.js +3 -2
- package/dist/components/agent/message/message-loading.js +5 -5
- package/dist/components/agent/message/tool-call-card.js +1 -1
- package/dist/components/agent/provider/runtime-config.js +11 -4
- package/dist/components/agent/provider/types.d.ts +1 -0
- package/dist/components/agent/provider/use-agent-chat.js +39 -8
- package/dist/components/ui/badge.d.ts +1 -1
- package/dist/components/ui/button.d.ts +4 -4
- package/dist/components/ui/button.js +20 -20
- package/dist/components/ui/textarea.d.ts +3 -0
- package/dist/components/ui/textarea.js +6 -0
- package/dist/styles/globals.css +10 -8
- package/package.json +1 -1
|
@@ -4,6 +4,7 @@ import { Paperclip, PaperPlaneTilt } from '@phosphor-icons/react/dist/ssr';
|
|
|
4
4
|
import { useCallback, useRef, useState } from 'react';
|
|
5
5
|
import { cn } from '../../lib/utils';
|
|
6
6
|
import { Button } from '../ui/button';
|
|
7
|
+
import { Textarea } from '../ui/textarea';
|
|
7
8
|
function AgentInput({ value: controlledValue, onChange, onSend, onAttach, placeholder = 'AIに相談してみましょう', disabled = false, isLoading = false, className, }) {
|
|
8
9
|
const [uncontrolledValue, setUncontrolledValue] = useState('');
|
|
9
10
|
const textareaRef = useRef(null);
|
|
@@ -45,6 +46,6 @@ function AgentInput({ value: controlledValue, onChange, onSend, onAttach, placeh
|
|
|
45
46
|
}
|
|
46
47
|
}, [handleSend]);
|
|
47
48
|
const canSend = value.trim().length > 0 && !disabled && !isLoading;
|
|
48
|
-
return (_jsx("div", { "data-slot": "agent-input", className: cn('w-full border-t border-border bg-muted px-3 pb-3 pt-2', className), children: _jsxs("div", { className: "flex items-end gap-2 rounded-lg border border-border bg-background
|
|
49
|
+
return (_jsx("div", { "data-slot": "agent-input", className: cn('w-full border-t border-border bg-muted px-3 pb-3 pt-2', className), children: _jsxs("div", { className: "flex items-end gap-1 p-2 rounded-lg border border-border bg-background transition-colors", children: [_jsx(Button, { type: "button", variant: "ghost", size: "icon-sm", onClick: onAttach, disabled: disabled, "aria-label": "\u30D5\u30A1\u30A4\u30EB\u3092\u6DFB\u4ED8", className: "mb-0.5 text-muted-foreground hover:text-foreground", children: _jsx(Paperclip, { className: "size-4", weight: "bold" }) }), _jsx(Textarea, { ref: textareaRef, value: value, onChange: handleChange, onKeyDown: handleKeyDown, placeholder: placeholder, disabled: disabled, rows: 1, className: "border-none p-1 resize-none min-h-8 focus-visible:ring-0 focus-visible:border-0 bg-transparent" }), _jsx(Button, { type: "button", size: "icon-sm", onClick: handleSend, disabled: !canSend, "aria-label": "\u9001\u4FE1 (\u2318+Enter)", children: _jsx(PaperPlaneTilt, { className: "size-5", weight: "fill" }) })] }) }));
|
|
49
50
|
}
|
|
50
51
|
export { AgentInput };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useEffect, useMemo, useState } from 'react';
|
|
4
|
-
import { Button } from '../ui/button';
|
|
5
4
|
import { cn } from '../../lib/utils';
|
|
5
|
+
import { Button } from '../ui/button';
|
|
6
6
|
import { AgentContainer } from './agent-container';
|
|
7
7
|
import { AgentProvider } from './provider';
|
|
8
8
|
const DEFAULT_OFFSET = '1.5rem';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { AgentScreen } from './agent-screen';
|
|
2
|
-
export type { AgentScreenProps } from './agent-screen';
|
|
3
|
-
export { AgentPopupWidget } from './agent-popup-widget';
|
|
4
1
|
export type { AgentPopupWidgetProps } from './agent-popup-widget';
|
|
2
|
+
export { AgentPopupWidget } from './agent-popup-widget';
|
|
3
|
+
export type { AgentScreenProps } from './agent-screen';
|
|
4
|
+
export { AgentScreen } from './agent-screen';
|
|
5
5
|
export type { AgentHomeCardProps } from './types';
|
|
@@ -43,21 +43,21 @@ const components = {
|
|
|
43
43
|
if (className) {
|
|
44
44
|
return _jsx("code", { className: cn('text-xs', className), children: children });
|
|
45
45
|
}
|
|
46
|
-
return
|
|
46
|
+
return _jsx("code", { className: "bg-background/50 px-1 py-0.5 rounded text-xs", children: children });
|
|
47
47
|
},
|
|
48
48
|
a: ({ href, children }) => (_jsx("a", { href: href, target: "_blank", rel: "noopener noreferrer", className: "text-primary underline hover:text-primary/80", children: children })),
|
|
49
|
-
ul: ({ children }) =>
|
|
50
|
-
ol: ({ children }) =>
|
|
49
|
+
ul: ({ children }) => _jsx("ul", { className: "list-disc list-inside pl-3 my-1", children: children }),
|
|
50
|
+
ol: ({ children }) => _jsx("ol", { className: "list-decimal list-inside pl-3 my-1", children: children }),
|
|
51
51
|
li: ({ children }) => _jsx("li", { className: "leading-relaxed", children: children }),
|
|
52
|
-
p: ({ children }) => _jsx("p", { className: "
|
|
53
|
-
h1: ({ children }) =>
|
|
54
|
-
h2: ({ children }) =>
|
|
55
|
-
h3: ({ children }) =>
|
|
52
|
+
p: ({ children }) => _jsx("p", { className: "first:mt-0 last:mb-0", children: children }),
|
|
53
|
+
h1: ({ children }) => _jsx("h1", { className: "text-base font-bold mt-3 mb-1 first:mt-0", children: children }),
|
|
54
|
+
h2: ({ children }) => _jsx("h2", { className: "text-sm font-bold mt-2.5 mb-1 first:mt-0", children: children }),
|
|
55
|
+
h3: ({ children }) => _jsx("h3", { className: "text-sm font-semibold mt-2 mb-1 first:mt-0", children: children }),
|
|
56
56
|
blockquote: ({ children }) => (_jsx("blockquote", { className: "border-l-2 border-border pl-3 my-1.5 text-muted-foreground italic", children: children })),
|
|
57
57
|
table: ({ children }) => (_jsx("div", { className: "overflow-x-auto my-1.5", children: _jsx("table", { className: "min-w-full border-collapse border border-border text-xs", children: children }) })),
|
|
58
|
-
thead: ({ children }) =>
|
|
58
|
+
thead: ({ children }) => _jsx("thead", { className: "bg-muted/50", children: children }),
|
|
59
59
|
th: ({ children }) => (_jsx("th", { className: "border border-border px-2 py-1.5 text-left font-semibold", children: children })),
|
|
60
|
-
td: ({ children }) =>
|
|
60
|
+
td: ({ children }) => _jsx("td", { className: "border border-border px-2 py-1.5", children: children }),
|
|
61
61
|
hr: () => _jsx("hr", { className: "my-3 border-border" }),
|
|
62
62
|
};
|
|
63
63
|
export function Markdown({ content, className }) {
|
|
@@ -4,4 +4,4 @@ export interface MessageItemProps {
|
|
|
4
4
|
pendingToolCalls: ToolCallState[];
|
|
5
5
|
toolNameLabels?: Record<string, string>;
|
|
6
6
|
}
|
|
7
|
-
export declare function MessageItem({ message, pendingToolCalls, toolNameLabels
|
|
7
|
+
export declare function MessageItem({ message, pendingToolCalls, toolNameLabels }: MessageItemProps): import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -3,7 +3,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import { cn } from '../../../lib/utils';
|
|
4
4
|
import { Markdown } from './markdown';
|
|
5
5
|
import { ToolCallCard } from './tool-call-card';
|
|
6
|
-
export function MessageItem({ message, pendingToolCalls, toolNameLabels
|
|
6
|
+
export function MessageItem({ message, pendingToolCalls, toolNameLabels }) {
|
|
7
7
|
const isUser = message.role === 'user';
|
|
8
8
|
// メッセージからテキストを抽出
|
|
9
9
|
const textContent = message.content
|
|
@@ -8,7 +8,7 @@ export function MessageList({ messages, pendingToolCalls, toolNameLabels, isLoad
|
|
|
8
8
|
// 新しいメッセージが追加されたら自動スクロール
|
|
9
9
|
useEffect(() => {
|
|
10
10
|
bottomRef.current?.scrollIntoView({ behavior: 'smooth' });
|
|
11
|
-
}, [
|
|
11
|
+
}, []);
|
|
12
12
|
if (messages.length === 0 && !isLoading) {
|
|
13
13
|
return null;
|
|
14
14
|
}
|
|
@@ -19,6 +19,7 @@ export function MessageList({ messages, pendingToolCalls, toolNameLabels, isLoad
|
|
|
19
19
|
// Show loading indicator when:
|
|
20
20
|
// 1. isLoading is true AND
|
|
21
21
|
// 2. No messages yet OR last message is from user OR last assistant has no content
|
|
22
|
-
const showLoadingIndicator = isLoading &&
|
|
22
|
+
const showLoadingIndicator = isLoading &&
|
|
23
|
+
(messages.length === 0 || lastMessage?.role === 'user' || !lastAssistantHasContent);
|
|
23
24
|
return (_jsxs("div", { className: "flex flex-col gap-3 p-3", children: [messages.map((message) => (_jsx(MessageItem, { message: message, pendingToolCalls: pendingToolCalls, toolNameLabels: toolNameLabels }, message.id))), showLoadingIndicator && _jsx(MessageLoading, {}), _jsx("div", { ref: bottomRef })] }));
|
|
24
25
|
}
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { cn } from '../../../lib/utils';
|
|
4
|
-
/** Reusable
|
|
5
|
-
function
|
|
6
|
-
return (_jsxs("span", { className: "flex gap-
|
|
4
|
+
/** Reusable loading dots animation */
|
|
5
|
+
function LoadingDots() {
|
|
6
|
+
return (_jsxs("span", { className: "flex gap-0.5", "aria-hidden": "true", children: [_jsx("span", { className: "h-0.5 w-0.5 animate-dot-fade rounded-full bg-muted-foreground/50 [animation-delay:0ms]" }), _jsx("span", { className: "h-0.5 w-0.5 animate-dot-fade rounded-full bg-muted-foreground/50 [animation-delay:150ms]" }), _jsx("span", { className: "h-0.5 w-0.5 animate-dot-fade rounded-full bg-muted-foreground/50 [animation-delay:300ms]" })] }));
|
|
7
7
|
}
|
|
8
8
|
export function MessageLoading({ className }) {
|
|
9
|
-
return (_jsx("
|
|
9
|
+
return (_jsx("output", { className: cn('flex justify-start', className), "aria-label": "AI\u5FDC\u7B54\u3092\u5F85\u6A5F\u4E2D", children: _jsx("div", { className: "max-w-xl", children: _jsx("div", { className: "rounded-lg border border-border bg-card px-3 py-2", children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "text-sm text-muted-foreground", children: "\u8003\u3048\u4E2D" }), _jsx(LoadingDots, {})] }) }) }) }));
|
|
10
10
|
}
|
|
11
11
|
/**
|
|
12
12
|
* Compact loading indicator for inline use (e.g., inside MessageItem during streaming)
|
|
13
13
|
*/
|
|
14
14
|
export function ThinkingDots({ className }) {
|
|
15
|
-
return (
|
|
15
|
+
return (_jsx("output", { className: cn('flex items-center gap-2', className), "aria-label": "\u8003\u3048\u4E2D", children: _jsx(LoadingDots, {}) }));
|
|
16
16
|
}
|
|
@@ -21,5 +21,5 @@ export function ToolCallCard({ toolCallState, toolNameLabels = {}, statusLabels,
|
|
|
21
21
|
? { ...defaultStatusLabels, ...statusLabels }
|
|
22
22
|
: defaultStatusLabels;
|
|
23
23
|
const statusLabel = mergedStatusLabels[status];
|
|
24
|
-
return (_jsxs("div", { className: "rounded-md border border-border bg-card p-2", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "text-xs font-medium text-foreground", children: toolLabel }), _jsx("span", { className: cn('rounded-full px-1.5 py-0.5 text-[10px]', statusColors[status]), children: statusLabel })] }), status === 'executing' && (_jsx("div", { className: "h-4 w-4 animate-spin rounded-full border-2 border-primary border-t-transparent" })), status === 'completed' &&
|
|
24
|
+
return (_jsxs("div", { className: "rounded-md border border-border bg-card p-2", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "text-xs font-medium text-foreground", children: toolLabel }), _jsx("span", { className: cn('rounded-full px-1.5 py-0.5 text-[10px]', statusColors[status]), children: statusLabel })] }), status === 'executing' && (_jsx("div", { className: "h-4 w-4 animate-spin rounded-full border-2 border-primary border-t-transparent" })), status === 'completed' && _jsx(CheckCircle, { className: "size-4 text-green-600", weight: "fill" }), status === 'error' && _jsx(XCircle, { className: "size-4 text-destructive", weight: "fill" })] }), _jsxs("details", { className: "mt-2", children: [_jsx("summary", { className: "cursor-pointer text-xs text-muted-foreground", children: parametersLabel }), _jsx("pre", { className: "mt-1 overflow-x-auto rounded bg-muted p-2 text-xs text-muted-foreground", children: JSON.stringify(toolCall.input, null, 2) })] }), status === 'completed' && result !== undefined && (_jsxs("details", { className: "mt-2", children: [_jsx("summary", { className: "cursor-pointer text-xs text-green-800 dark:text-green-400", children: resultLabel }), _jsx("pre", { className: "mt-1 max-h-40 overflow-auto rounded bg-green-50 p-2 text-xs text-muted-foreground dark:bg-green-950", children: typeof result === 'string' ? result : JSON.stringify(result, null, 2) })] })), status === 'error' && error && (_jsx("div", { className: "mt-2 rounded bg-destructive/10 p-2 text-xs text-destructive", children: error }))] }));
|
|
25
25
|
}
|
|
@@ -1,8 +1,15 @@
|
|
|
1
|
-
const
|
|
2
|
-
const
|
|
1
|
+
const isDevelopment = process.env.NODE_ENV === 'development';
|
|
2
|
+
const PRODUCTION_AGENT_ENDPOINT = 'https://agent-server-prod--agent-platform-dev-8e3ae.asia-east1.hosted.app/api/agent';
|
|
3
|
+
const DEVELOPMENT_AGENT_ENDPOINT = 'http://localhost:3002/api/agent';
|
|
4
|
+
const FIXED_API_BASE_URL = isDevelopment
|
|
5
|
+
? 'http://localhost:3001/api'
|
|
6
|
+
: 'https://demo-scout-api-prod--agent-platform-dev-8e3ae.asia-east1.hosted.app/api';
|
|
7
|
+
function normalizeUrl(url) {
|
|
8
|
+
return url.replace(/\/$/, '');
|
|
9
|
+
}
|
|
3
10
|
export function resolveAgentRuntimeConfig() {
|
|
4
11
|
return {
|
|
5
|
-
endpoint:
|
|
6
|
-
apiBaseUrl: FIXED_API_BASE_URL,
|
|
12
|
+
endpoint: normalizeUrl(isDevelopment ? DEVELOPMENT_AGENT_ENDPOINT : PRODUCTION_AGENT_ENDPOINT),
|
|
13
|
+
apiBaseUrl: normalizeUrl(FIXED_API_BASE_URL),
|
|
7
14
|
};
|
|
8
15
|
}
|
|
@@ -25,6 +25,7 @@ export type AgentHeadersProvider = () => Record<string, string> | Promise<Record
|
|
|
25
25
|
*/
|
|
26
26
|
export interface AgentProviderConfig {
|
|
27
27
|
agentId?: string;
|
|
28
|
+
/** 通信先URLは packages/ui 内部のruntime-configで解決される */
|
|
28
29
|
/**
|
|
29
30
|
* @deprecated 旧実装との後方互換用。
|
|
30
31
|
* executeOn: 'client' のツールをブラウザ側で実行するコールバック
|
|
@@ -3,6 +3,29 @@ import { useCallback, useRef, useState } from 'react';
|
|
|
3
3
|
import { parseSSEBuffer } from './parse-sse-buffer';
|
|
4
4
|
/** クライアントツール自動継続の最大回数 */
|
|
5
5
|
const MAX_CONTINUE_ROUNDS = 10;
|
|
6
|
+
function isLikelyJwtToken(token) {
|
|
7
|
+
const normalized = token.startsWith('Bearer ') ? token.slice(7) : token;
|
|
8
|
+
return normalized.split('.').length === 3;
|
|
9
|
+
}
|
|
10
|
+
function normalizeErrorMessage(error) {
|
|
11
|
+
if (typeof error === 'string' && error.trim().length > 0)
|
|
12
|
+
return error;
|
|
13
|
+
if (typeof error === 'object' &&
|
|
14
|
+
error !== null &&
|
|
15
|
+
'message' in error &&
|
|
16
|
+
typeof error.message === 'string') {
|
|
17
|
+
return error.message;
|
|
18
|
+
}
|
|
19
|
+
if (error !== undefined) {
|
|
20
|
+
try {
|
|
21
|
+
return JSON.stringify(error);
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return String(error);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return 'Unknown error';
|
|
28
|
+
}
|
|
6
29
|
// --- イベントハンドラ ---
|
|
7
30
|
function handleTextDelta(text, accumulatedText, toolCalls, assistantMessageId, setMessages) {
|
|
8
31
|
const newText = accumulatedText + text;
|
|
@@ -55,7 +78,7 @@ function handleToolResult(tr, serverResolvedToolIds, setPendingToolCalls) {
|
|
|
55
78
|
...state,
|
|
56
79
|
status: tr.isError ? 'error' : 'completed',
|
|
57
80
|
result: tr.result,
|
|
58
|
-
error: tr.isError ?
|
|
81
|
+
error: tr.isError ? normalizeErrorMessage(tr.result) : undefined,
|
|
59
82
|
});
|
|
60
83
|
}
|
|
61
84
|
return newMap;
|
|
@@ -67,7 +90,12 @@ function handleFinish(assistantMessageId, setMessages) {
|
|
|
67
90
|
const idx = updated.findIndex((m) => m.id === assistantMessageId);
|
|
68
91
|
const existing = idx >= 0 ? updated[idx] : undefined;
|
|
69
92
|
if (existing) {
|
|
70
|
-
updated[idx] = {
|
|
93
|
+
updated[idx] = {
|
|
94
|
+
id: existing.id,
|
|
95
|
+
role: existing.role,
|
|
96
|
+
content: existing.content,
|
|
97
|
+
isStreaming: false,
|
|
98
|
+
};
|
|
71
99
|
}
|
|
72
100
|
return updated;
|
|
73
101
|
});
|
|
@@ -173,6 +201,7 @@ export function useAgentChatInternal(options) {
|
|
|
173
201
|
const buildAgentHeaders = useCallback(async () => {
|
|
174
202
|
const headers = { 'Content-Type': 'application/json' };
|
|
175
203
|
const token = getAuthToken ? await getAuthToken() : authToken;
|
|
204
|
+
console.log('[buildAgentHeaders] Building headers for agent request: ', token ? 'with auth' : 'no auth');
|
|
176
205
|
if (token) {
|
|
177
206
|
headers['Authorization'] = token.startsWith('Bearer ') ? token : `Bearer ${token}`;
|
|
178
207
|
}
|
|
@@ -186,7 +215,8 @@ export function useAgentChatInternal(options) {
|
|
|
186
215
|
}
|
|
187
216
|
return headers;
|
|
188
217
|
}, [authToken, getAuthToken, getAgentHeaders]);
|
|
189
|
-
const handleError = useCallback((
|
|
218
|
+
const handleError = useCallback((errorInput) => {
|
|
219
|
+
const errorMessage = normalizeErrorMessage(errorInput);
|
|
190
220
|
setError(errorMessage);
|
|
191
221
|
onError?.(errorMessage);
|
|
192
222
|
}, [onError]);
|
|
@@ -255,7 +285,9 @@ export function useAgentChatInternal(options) {
|
|
|
255
285
|
const toolApiHeaders = {};
|
|
256
286
|
if (!disableToolApiAuthHeader) {
|
|
257
287
|
const token = getAuthToken ? await getAuthToken() : authToken;
|
|
258
|
-
|
|
288
|
+
// Tool APIはcredentials: 'include'でCookie送信されるため、
|
|
289
|
+
// 非JWT(例: ANON_KEY)はAuthorizationヘッダーに載せずCookie認証を優先する。
|
|
290
|
+
if (token && isLikelyJwtToken(token)) {
|
|
259
291
|
toolApiHeaders['Authorization'] = token.startsWith('Bearer ') ? token : `Bearer ${token}`;
|
|
260
292
|
}
|
|
261
293
|
}
|
|
@@ -297,7 +329,7 @@ export function useAgentChatInternal(options) {
|
|
|
297
329
|
toolCall: tc,
|
|
298
330
|
status: isError ? 'error' : 'completed',
|
|
299
331
|
result: result.output,
|
|
300
|
-
error: isError ?
|
|
332
|
+
error: isError ? normalizeErrorMessage(result.output) : undefined,
|
|
301
333
|
});
|
|
302
334
|
return newMap;
|
|
303
335
|
});
|
|
@@ -403,8 +435,7 @@ export function useAgentChatInternal(options) {
|
|
|
403
435
|
catch (e) {
|
|
404
436
|
if (e instanceof Error && e.name === 'AbortError')
|
|
405
437
|
return;
|
|
406
|
-
|
|
407
|
-
handleError(errorMessage);
|
|
438
|
+
handleError(e);
|
|
408
439
|
}
|
|
409
440
|
finally {
|
|
410
441
|
setIsLoading(false);
|
|
@@ -433,7 +464,7 @@ export function useAgentChatInternal(options) {
|
|
|
433
464
|
})) || []);
|
|
434
465
|
}
|
|
435
466
|
catch (e) {
|
|
436
|
-
setError(e
|
|
467
|
+
setError(normalizeErrorMessage(e));
|
|
437
468
|
}
|
|
438
469
|
finally {
|
|
439
470
|
setIsLoading(false);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import { type VariantProps } from "class-variance-authority";
|
|
3
3
|
declare const badgeVariants: (props?: ({
|
|
4
|
-
variant?: "
|
|
4
|
+
variant?: "default" | "destructive" | "outline" | "secondary" | "ghost" | "link" | null | undefined;
|
|
5
5
|
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
6
6
|
declare function Badge({ className, variant, asChild, ...props }: React.ComponentProps<"span"> & VariantProps<typeof badgeVariants> & {
|
|
7
7
|
asChild?: boolean;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import { type VariantProps } from 'class-variance-authority';
|
|
2
|
+
import type * as React from 'react';
|
|
3
3
|
declare const buttonVariants: (props?: ({
|
|
4
|
-
variant?: "
|
|
4
|
+
variant?: "default" | "destructive" | "outline" | "secondary" | "ghost" | "link" | null | undefined;
|
|
5
5
|
size?: "default" | "xs" | "sm" | "lg" | "icon" | "icon-xs" | "icon-sm" | "icon-lg" | null | undefined;
|
|
6
6
|
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
7
|
-
declare function Button({ className, variant, size, asChild, ...props }: React.ComponentProps<
|
|
7
|
+
declare function Button({ className, variant, size, asChild, ...props }: React.ComponentProps<'button'> & VariantProps<typeof buttonVariants> & {
|
|
8
8
|
asChild?: boolean;
|
|
9
9
|
}): import("react/jsx-runtime").JSX.Element;
|
|
10
10
|
export { Button, buttonVariants };
|
|
@@ -1,35 +1,35 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { cva } from
|
|
3
|
-
import { Slot } from
|
|
4
|
-
import { cn } from
|
|
2
|
+
import { cva } from 'class-variance-authority';
|
|
3
|
+
import { Slot } from 'radix-ui';
|
|
4
|
+
import { cn } from '../../lib/utils';
|
|
5
5
|
const buttonVariants = cva("inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", {
|
|
6
6
|
variants: {
|
|
7
7
|
variant: {
|
|
8
|
-
default:
|
|
9
|
-
destructive:
|
|
10
|
-
outline:
|
|
11
|
-
secondary:
|
|
12
|
-
ghost:
|
|
13
|
-
link:
|
|
8
|
+
default: 'bg-primary text-primary-foreground hover:bg-primary/90',
|
|
9
|
+
destructive: 'bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60',
|
|
10
|
+
outline: 'border bg-background hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50',
|
|
11
|
+
secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80',
|
|
12
|
+
ghost: 'hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50',
|
|
13
|
+
link: 'text-primary underline-offset-4 hover:underline',
|
|
14
14
|
},
|
|
15
15
|
size: {
|
|
16
|
-
default:
|
|
16
|
+
default: 'h-10 px-4 py-2 has-[>svg]:px-3',
|
|
17
17
|
xs: "h-6 gap-1 rounded-md px-2 text-xs has-[>svg]:px-1.5 [&_svg:not([class*='size-'])]:size-3",
|
|
18
|
-
sm:
|
|
19
|
-
lg:
|
|
20
|
-
icon:
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
18
|
+
sm: 'h-9 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5',
|
|
19
|
+
lg: 'h-11 rounded-md px-6 has-[>svg]:px-4',
|
|
20
|
+
icon: 'size-10',
|
|
21
|
+
'icon-xs': "size-6 rounded-md [&_svg:not([class*='size-'])]:size-3",
|
|
22
|
+
'icon-sm': "size-8 rounded-md [&_svg:not([class*='size-'])]:size-4",
|
|
23
|
+
'icon-lg': "size-10 rounded-md [&_svg:not([class*='size-'])]:size-5",
|
|
24
24
|
},
|
|
25
25
|
},
|
|
26
26
|
defaultVariants: {
|
|
27
|
-
variant:
|
|
28
|
-
size:
|
|
27
|
+
variant: 'default',
|
|
28
|
+
size: 'default',
|
|
29
29
|
},
|
|
30
30
|
});
|
|
31
|
-
function Button({ className, variant =
|
|
32
|
-
const Comp = asChild ? Slot.Root :
|
|
31
|
+
function Button({ className, variant = 'default', size = 'default', asChild = false, ...props }) {
|
|
32
|
+
const Comp = asChild ? Slot.Root : 'button';
|
|
33
33
|
return (_jsx(Comp, { "data-slot": "button", "data-variant": variant, "data-size": size, className: cn(buttonVariants({ variant, size, className })), ...props }));
|
|
34
34
|
}
|
|
35
35
|
export { Button, buttonVariants };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { cn } from '@/lib/utils';
|
|
3
|
+
function Textarea({ className, ...props }) {
|
|
4
|
+
return (_jsx("textarea", { "data-slot": "textarea", className: cn('border-input placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 flex field-sizing-content min-h-16 w-full rounded-md border bg-transparent px-3 py-2 text-base outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 md:text-sm', className), ...props }));
|
|
5
|
+
}
|
|
6
|
+
export { Textarea };
|
package/dist/styles/globals.css
CHANGED
|
@@ -132,23 +132,25 @@
|
|
|
132
132
|
|
|
133
133
|
/* Custom animations for agent loading states */
|
|
134
134
|
@layer utilities {
|
|
135
|
-
@keyframes
|
|
136
|
-
0
|
|
137
|
-
|
|
138
|
-
}
|
|
135
|
+
@keyframes dot-fade {
|
|
136
|
+
0%,
|
|
137
|
+
80%,
|
|
139
138
|
100% {
|
|
140
|
-
|
|
139
|
+
opacity: 0.35;
|
|
140
|
+
}
|
|
141
|
+
40% {
|
|
142
|
+
opacity: 1;
|
|
141
143
|
}
|
|
142
144
|
}
|
|
143
145
|
|
|
144
|
-
.animate-
|
|
145
|
-
animation:
|
|
146
|
+
.animate-dot-fade {
|
|
147
|
+
animation: dot-fade 1.2s ease-in-out infinite;
|
|
146
148
|
}
|
|
147
149
|
}
|
|
148
150
|
|
|
149
151
|
/* Respect reduced motion preferences */
|
|
150
152
|
@media (prefers-reduced-motion: reduce) {
|
|
151
|
-
.animate-
|
|
153
|
+
.animate-dot-fade,
|
|
152
154
|
.animate-ping,
|
|
153
155
|
.animate-pulse,
|
|
154
156
|
.animate-bounce {
|