@tangle-network/sandbox-ui 0.6.1 → 0.8.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/auth.d.ts +10 -6
- package/dist/auth.js +3 -3
- package/dist/{chat-container-Cg-GwyiK.d.ts → chat-container-f4yEs6KN.d.ts} +9 -1
- package/dist/chat.d.ts +12 -2
- package/dist/chat.js +10 -10
- package/dist/{chunk-TSE423UF.js → chunk-2QZ6G7NM.js} +6 -6
- package/dist/{chunk-WBQ7VULC.js → chunk-34A66VBG.js} +7 -7
- package/dist/{chunk-JP725R4W.js → chunk-34I7UFSX.js} +2 -2
- package/dist/{chunk-YS66Q3RC.js → chunk-3CJ2SOEI.js} +2 -2
- package/dist/{chunk-CNWVHQFY.js → chunk-54SQQMMM.js} +6 -24
- package/dist/{chunk-DLCFZDGX.js → chunk-5UM2XMEJ.js} +39 -14
- package/dist/{chunk-YYGECNZZ.js → chunk-66EZOYZR.js} +3 -3
- package/dist/chunk-7U2Z23NE.js +49 -0
- package/dist/{chunk-RKXIRRKQ.js → chunk-BUOQTBTO.js} +70 -66
- package/dist/{chunk-DCPYTL4W.js → chunk-D4CZWJCD.js} +72 -148
- package/dist/{chunk-MXRQ4MJE.js → chunk-DXMIEK4K.js} +34 -23
- package/dist/{chunk-ZMWWE5RF.js → chunk-EXSOPXIY.js} +141 -123
- package/dist/{chunk-GW4GRAWJ.js → chunk-GSZA3TSY.js} +18 -12
- package/dist/{chunk-W4LM3QYZ.js → chunk-HB5Y37YU.js} +8 -8
- package/dist/{chunk-E2XT3G52.js → chunk-HFMAXUHV.js} +136 -137
- package/dist/{chunk-BRBTD7RH.js → chunk-MA7YKRUP.js} +28 -18
- package/dist/{chunk-MJUDMVRU.js → chunk-MT5FJ3ZT.js} +17 -17
- package/dist/chunk-OKLQVY3Y.js +139 -0
- package/dist/{chunk-KH5UDAJ2.js → chunk-QDH5GEGY.js} +58 -54
- package/dist/{chunk-33W2TLUL.js → chunk-QID2OOMG.js} +12 -3
- package/dist/{chunk-FJSVPBKY.js → chunk-S7OXQTST.js} +17 -3
- package/dist/chunk-T7HMZEVO.js +216 -0
- package/dist/{chunk-FNYJFCGU.js → chunk-U6QTHMY6.js} +145 -256
- package/dist/{chunk-565V6JTN.js → chunk-UXQMIR3D.js} +60 -99
- package/dist/{chunk-XTPAWK7L.js → chunk-VOUV7GGB.js} +25 -47
- package/dist/{chunk-OVNLOE3Y.js → chunk-WXK43R62.js} +41 -41
- package/dist/{chunk-6V4XVKFY.js → chunk-XXDFEF72.js} +340 -335
- package/dist/{chunk-TDYQBLL5.js → chunk-ZMNSRDMH.js} +6 -6
- package/dist/dashboard.d.ts +135 -3
- package/dist/dashboard.js +848 -8
- package/dist/{document-editor-pane-DWWUTTTZ.js → document-editor-pane-TLPVRBBU.js} +3 -3
- package/dist/editor.d.ts +9 -8
- package/dist/editor.js +3 -3
- package/dist/files.js +3 -3
- package/dist/globals.css +5304 -68
- package/dist/hooks.d.ts +1 -1
- package/dist/hooks.js +7 -7
- package/dist/index.d.ts +4 -4
- package/dist/index.js +28 -28
- package/dist/markdown.js +1 -1
- package/dist/openui.js +5 -5
- package/dist/pages.d.ts +47 -3
- package/dist/pages.js +911 -357
- package/dist/primitives.d.ts +5 -2
- package/dist/primitives.js +10 -10
- package/dist/run.js +4 -4
- package/dist/sdk-hooks.d.ts +2 -3
- package/dist/sdk-hooks.js +5 -5
- package/dist/styles.css +5304 -68
- package/dist/template-card-BAtvcAkU.d.ts +18 -0
- package/dist/terminal.d.ts +3 -1
- package/dist/terminal.js +66 -32
- package/dist/tokens.css +701 -40
- package/dist/{usage-chart-XCoB_7Xu.d.ts → usage-chart-SSiOgeQI.d.ts} +3 -1
- package/dist/{use-pty-session-COzVkhtc.d.ts → use-pty-session-0AOuwXgq.d.ts} +2 -0
- package/dist/{index-BT_-ecpc.d.ts → variant-list-C8wx2TqF.d.ts} +17 -8
- package/dist/workspace.d.ts +1 -1
- package/dist/workspace.js +13 -13
- package/package.json +3 -1
- package/tailwind.config.cjs +3 -2
- package/dist/chunk-3HW53XTH.js +0 -228
- package/dist/chunk-OKCIKTXQ.js +0 -63
package/dist/auth.d.ts
CHANGED
|
@@ -54,17 +54,21 @@ interface AuthHeaderProps {
|
|
|
54
54
|
declare function AuthHeader({ user, loading, variant, apiBaseUrl, menuLinks, className, }: AuthHeaderProps): react_jsx_runtime.JSX.Element;
|
|
55
55
|
|
|
56
56
|
interface LoginLayoutProps {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
57
|
+
title?: React.ReactNode;
|
|
58
|
+
subtitle?: React.ReactNode;
|
|
59
|
+
brandIcon?: React.ReactNode;
|
|
60
|
+
children: React.ReactNode;
|
|
61
|
+
className?: string;
|
|
62
|
+
/** (Deprecated) terminal lines from legacy layout, kept for backwards compatibility */
|
|
60
63
|
terminalLines?: string[];
|
|
64
|
+
/** (Deprecated) tagline, kept for backwards compatibility */
|
|
65
|
+
tagline?: React.ReactNode;
|
|
66
|
+
/** (Deprecated) footerLinks, kept for backwards compatibility */
|
|
61
67
|
footerLinks?: {
|
|
62
68
|
label: string;
|
|
63
69
|
href: string;
|
|
64
70
|
}[];
|
|
65
|
-
children: React.ReactNode;
|
|
66
|
-
className?: string;
|
|
67
71
|
}
|
|
68
|
-
declare function LoginLayout({
|
|
72
|
+
declare function LoginLayout({ title, subtitle, brandIcon, children, className, }: LoginLayoutProps): react_jsx_runtime.JSX.Element;
|
|
69
73
|
|
|
70
74
|
export { AuthHeader, type AuthHeaderProps, GitHubLoginButton, type GitHubLoginButtonProps, LoginLayout, type LoginLayoutProps, type SessionUser, UserMenu, type UserMenuProps };
|
package/dist/auth.js
CHANGED
|
@@ -3,9 +3,9 @@ import {
|
|
|
3
3
|
GitHubLoginButton,
|
|
4
4
|
LoginLayout,
|
|
5
5
|
UserMenu
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
8
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-VOUV7GGB.js";
|
|
7
|
+
import "./chunk-34A66VBG.js";
|
|
8
|
+
import "./chunk-2QZ6G7NM.js";
|
|
9
9
|
import "./chunk-RQHJBTEU.js";
|
|
10
10
|
export {
|
|
11
11
|
AuthHeader,
|
|
@@ -50,8 +50,16 @@ interface ChatInputProps {
|
|
|
50
50
|
/** Drop zone overlay description */
|
|
51
51
|
dropDescription?: string;
|
|
52
52
|
className?: string;
|
|
53
|
+
/** Label above the input. Set to null to hide. Default: "Agent Command Deck" */
|
|
54
|
+
inputLabel?: string | null;
|
|
55
|
+
/** Status text shown when idle. Set to null to hide. Default: "Ready for next instruction" */
|
|
56
|
+
idleStatus?: string | null;
|
|
57
|
+
/** Status text shown when streaming. Set to null to hide. Default: "Streaming response" */
|
|
58
|
+
streamingStatus?: string | null;
|
|
59
|
+
/** Hide the Cmd+L focus shortcut hint */
|
|
60
|
+
hideShortcutHint?: boolean;
|
|
53
61
|
}
|
|
54
|
-
declare function ChatInput({ onSend, onCancel, isStreaming, disabled, placeholder, modelLabel, onModelClick, pendingFiles, onRemoveFile, onAttach, onAttachFolder, accept, dropTitle, dropDescription, className, }: ChatInputProps): react_jsx_runtime.JSX.Element;
|
|
62
|
+
declare function ChatInput({ onSend, onCancel, isStreaming, disabled, placeholder, modelLabel, onModelClick, pendingFiles, onRemoveFile, onAttach, onAttachFolder, accept, dropTitle, dropDescription, className, inputLabel, idleStatus, streamingStatus, hideShortcutHint, }: ChatInputProps): react_jsx_runtime.JSX.Element;
|
|
55
63
|
|
|
56
64
|
interface ChatContainerProps {
|
|
57
65
|
messages: SessionMessage[];
|
package/dist/chat.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { C as ChatContainer, a as ChatContainerProps, b as ChatInput, c as ChatInputProps, P as PendingFile } from './chat-container-
|
|
1
|
+
export { C as ChatContainer, a as ChatContainerProps, b as ChatInput, c as ChatInputProps, P as PendingFile } from './chat-container-f4yEs6KN.js';
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
import { ReactNode } from 'react';
|
|
4
4
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
@@ -20,8 +20,18 @@ interface ChatMessageProps {
|
|
|
20
20
|
/** Timestamp */
|
|
21
21
|
timestamp?: Date;
|
|
22
22
|
className?: string;
|
|
23
|
+
/** Custom user label. Default: "You" */
|
|
24
|
+
userLabel?: string;
|
|
25
|
+
/** Custom assistant label. Default: "Agent" */
|
|
26
|
+
assistantLabel?: string;
|
|
27
|
+
/** Hide the role label row entirely */
|
|
28
|
+
hideRoleLabel?: boolean;
|
|
29
|
+
/** Hide the avatar icon */
|
|
30
|
+
hideAvatar?: boolean;
|
|
31
|
+
/** Custom avatar element (replaces default User/Bot icon) */
|
|
32
|
+
avatar?: ReactNode;
|
|
23
33
|
}
|
|
24
|
-
declare function ChatMessage({ role, content, toolCalls, isStreaming, timestamp, className, }: ChatMessageProps): react_jsx_runtime.JSX.Element;
|
|
34
|
+
declare function ChatMessage({ role, content, toolCalls, isStreaming, timestamp, className, userLabel, assistantLabel, hideRoleLabel, hideAvatar, avatar, }: ChatMessageProps): react_jsx_runtime.JSX.Element;
|
|
25
35
|
|
|
26
36
|
interface MessageListProps {
|
|
27
37
|
groups: GroupedMessage[];
|
package/dist/chat.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ChatMessage
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-GSZA3TSY.js";
|
|
4
4
|
import {
|
|
5
5
|
AgentTimeline,
|
|
6
6
|
ChatContainer,
|
|
@@ -8,17 +8,17 @@ import {
|
|
|
8
8
|
MessageList,
|
|
9
9
|
ThinkingIndicator,
|
|
10
10
|
UserMessage
|
|
11
|
-
} from "./chunk-
|
|
12
|
-
import "./chunk-
|
|
13
|
-
import "./chunk-
|
|
11
|
+
} from "./chunk-BUOQTBTO.js";
|
|
12
|
+
import "./chunk-54SQQMMM.js";
|
|
13
|
+
import "./chunk-EXSOPXIY.js";
|
|
14
14
|
import "./chunk-HRMUF35V.js";
|
|
15
|
-
import "./chunk-
|
|
15
|
+
import "./chunk-MT5FJ3ZT.js";
|
|
16
16
|
import "./chunk-BX6AQMUS.js";
|
|
17
|
-
import "./chunk-
|
|
18
|
-
import "./chunk-
|
|
19
|
-
import "./chunk-
|
|
20
|
-
import "./chunk-
|
|
21
|
-
import "./chunk-
|
|
17
|
+
import "./chunk-WXK43R62.js";
|
|
18
|
+
import "./chunk-34I7UFSX.js";
|
|
19
|
+
import "./chunk-T7HMZEVO.js";
|
|
20
|
+
import "./chunk-ZMNSRDMH.js";
|
|
21
|
+
import "./chunk-2QZ6G7NM.js";
|
|
22
22
|
import "./chunk-RQHJBTEU.js";
|
|
23
23
|
export {
|
|
24
24
|
AgentTimeline,
|
|
@@ -12,13 +12,13 @@ var buttonVariants = cva(
|
|
|
12
12
|
{
|
|
13
13
|
variants: {
|
|
14
14
|
variant: {
|
|
15
|
-
default: "bg-
|
|
16
|
-
destructive: "bg-destructive/
|
|
17
|
-
outline: "border border-
|
|
18
|
-
secondary: "bg-
|
|
19
|
-
ghost: "hover:bg-
|
|
15
|
+
default: "bg-primary/20 border border-primary/30 text-primary hover:text-primary-foreground shadow-[var(--shadow-accent)] hover:bg-primary hover:shadow-[var(--shadow-glow)] active:scale-[0.97] duration-[var(--transition-fast)]",
|
|
16
|
+
destructive: "bg-destructive/10 border border-destructive/30 text-destructive hover:text-destructive-foreground hover:bg-destructive/80 active:scale-[0.97] duration-[var(--transition-fast)]",
|
|
17
|
+
outline: "border border-border bg-card/50 backdrop-blur-xl hover:bg-muted hover:border-primary/20 active:scale-[0.97] duration-[var(--transition-fast)] text-foreground shadow-sm",
|
|
18
|
+
secondary: "bg-muted/50 border border-border text-foreground backdrop-blur-xl hover:bg-muted active:scale-[0.97] duration-[var(--transition-fast)] shadow-sm",
|
|
19
|
+
ghost: "hover:bg-muted hover:text-foreground duration-[var(--transition-fast)] text-muted-foreground border border-transparent",
|
|
20
20
|
link: "text-primary underline-offset-4 hover:underline",
|
|
21
|
-
sandbox: "bg-[image:var(--accent-gradient-strong)] text-white shadow-[var(--shadow-accent)] hover:brightness-110 active:scale-[0.97] duration-[var(--transition-fast)]"
|
|
21
|
+
sandbox: "bg-[image:var(--accent-gradient-strong)] text-white shadow-[var(--shadow-accent)] backdrop-blur-2xl border border-[var(--border-accent)] hover:brightness-110 active:scale-[0.97] duration-[var(--transition-fast)]"
|
|
22
22
|
},
|
|
23
23
|
size: {
|
|
24
24
|
default: "h-[var(--control-height)] px-4 py-2",
|
|
@@ -57,7 +57,7 @@ var DropdownMenuSubTrigger = React2.forwardRef(({ className, inset, children, ..
|
|
|
57
57
|
ref,
|
|
58
58
|
className: cn(
|
|
59
59
|
"flex cursor-default select-none items-center rounded-md px-2 py-1.5 text-sm outline-none",
|
|
60
|
-
"focus:bg-accent data-[state=open]:bg-
|
|
60
|
+
"focus:bg-accent data-[state=open]:bg-muted/50",
|
|
61
61
|
inset && "pl-8",
|
|
62
62
|
className
|
|
63
63
|
),
|
|
@@ -74,7 +74,7 @@ var DropdownMenuSubContent = React2.forwardRef(({ className, ...props }, ref) =>
|
|
|
74
74
|
{
|
|
75
75
|
ref,
|
|
76
76
|
className: cn(
|
|
77
|
-
"z-50 min-w-[8rem] overflow-hidden rounded-xl border border-
|
|
77
|
+
"z-50 min-w-[8rem] overflow-hidden rounded-xl border border-border bg-card p-1 text-foreground shadow-[var(--shadow-card)]",
|
|
78
78
|
"data-[state=closed]:animate-out data-[state=open]:animate-in",
|
|
79
79
|
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
80
80
|
"data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
|
|
@@ -92,7 +92,7 @@ var DropdownMenuContent = React2.forwardRef(({ className, sideOffset = 4, ...pro
|
|
|
92
92
|
ref,
|
|
93
93
|
sideOffset,
|
|
94
94
|
className: cn(
|
|
95
|
-
"z-50 min-w-[8rem] overflow-hidden rounded-xl border border-
|
|
95
|
+
"z-50 min-w-[8rem] overflow-hidden rounded-xl border border-border bg-card p-1 text-foreground shadow-[var(--shadow-card)]",
|
|
96
96
|
"data-[state=closed]:animate-out data-[state=open]:animate-in",
|
|
97
97
|
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
98
98
|
"data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
|
|
@@ -110,7 +110,7 @@ var DropdownMenuItem = React2.forwardRef(({ className, inset, ...props }, ref) =
|
|
|
110
110
|
ref,
|
|
111
111
|
className: cn(
|
|
112
112
|
"relative flex cursor-pointer select-none items-center rounded-md px-2 py-1.5 text-sm outline-none transition-colors",
|
|
113
|
-
"focus:bg-
|
|
113
|
+
"focus:bg-muted/50 focus:text-foreground",
|
|
114
114
|
"data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
|
115
115
|
inset && "pl-8",
|
|
116
116
|
className
|
|
@@ -125,7 +125,7 @@ var DropdownMenuCheckboxItem = React2.forwardRef(({ className, children, checked
|
|
|
125
125
|
ref,
|
|
126
126
|
className: cn(
|
|
127
127
|
"relative flex cursor-pointer select-none items-center rounded-md py-1.5 pr-2 pl-8 text-sm outline-none transition-colors",
|
|
128
|
-
"focus:bg-
|
|
128
|
+
"focus:bg-muted/50 focus:text-foreground",
|
|
129
129
|
"data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
|
130
130
|
className
|
|
131
131
|
),
|
|
@@ -144,7 +144,7 @@ var DropdownMenuRadioItem = React2.forwardRef(({ className, children, ...props }
|
|
|
144
144
|
ref,
|
|
145
145
|
className: cn(
|
|
146
146
|
"relative flex cursor-pointer select-none items-center rounded-md py-1.5 pr-2 pl-8 text-sm outline-none transition-colors",
|
|
147
|
-
"focus:bg-
|
|
147
|
+
"focus:bg-muted/50 focus:text-foreground",
|
|
148
148
|
"data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
|
149
149
|
className
|
|
150
150
|
),
|
|
@@ -173,7 +173,7 @@ var DropdownMenuSeparator = React2.forwardRef(({ className, ...props }, ref) =>
|
|
|
173
173
|
DropdownMenuPrimitive.Separator,
|
|
174
174
|
{
|
|
175
175
|
ref,
|
|
176
|
-
className: cn("-mx-1 my-1 h-px bg-
|
|
176
|
+
className: cn("-mx-1 my-1 h-px bg-border", className),
|
|
177
177
|
...props
|
|
178
178
|
}
|
|
179
179
|
));
|
|
@@ -30,7 +30,7 @@ var TableFooter = React.forwardRef(({ className, ...props }, ref) => /* @__PURE_
|
|
|
30
30
|
{
|
|
31
31
|
ref,
|
|
32
32
|
className: cn(
|
|
33
|
-
"border-t bg-
|
|
33
|
+
"border-t bg-card font-medium [&>tr]:last:border-b-0",
|
|
34
34
|
className
|
|
35
35
|
),
|
|
36
36
|
...props
|
|
@@ -42,7 +42,7 @@ var TableRow = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ *
|
|
|
42
42
|
{
|
|
43
43
|
ref,
|
|
44
44
|
className: cn(
|
|
45
|
-
"border-border border-b transition-colors hover:bg-
|
|
45
|
+
"border-border border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted/50",
|
|
46
46
|
className
|
|
47
47
|
),
|
|
48
48
|
...props
|
|
@@ -16,7 +16,7 @@ var DialogOverlay = React.forwardRef(({ className, ...props }, ref) => /* @__PUR
|
|
|
16
16
|
{
|
|
17
17
|
ref,
|
|
18
18
|
className: cn(
|
|
19
|
-
"fixed inset-0 z-50 bg-black/
|
|
19
|
+
"fixed inset-0 z-50 bg-black/80 backdrop-blur-sm",
|
|
20
20
|
"data-[state=closed]:animate-out data-[state=open]:animate-in",
|
|
21
21
|
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
22
22
|
className
|
|
@@ -38,7 +38,7 @@ var DialogContent = React.forwardRef(({ className, children, variant = "default"
|
|
|
38
38
|
ref,
|
|
39
39
|
className: cn(
|
|
40
40
|
"fixed top-[50%] left-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%]",
|
|
41
|
-
"gap-4 rounded-
|
|
41
|
+
"gap-4 rounded-2xl border bg-card/95 backdrop-blur-xl p-6 shadow-2xl duration-200",
|
|
42
42
|
"data-[state=closed]:animate-out data-[state=open]:animate-in",
|
|
43
43
|
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
44
44
|
"data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
|
|
@@ -91,26 +91,9 @@ function useRunGroups({
|
|
|
91
91
|
}
|
|
92
92
|
|
|
93
93
|
// src/hooks/use-run-collapse-state.ts
|
|
94
|
-
import { useCallback,
|
|
95
|
-
var AUTO_COLLAPSE_DELAY = 1e3;
|
|
94
|
+
import { useCallback, useState } from "react";
|
|
96
95
|
function useRunCollapseState(runs) {
|
|
97
96
|
const [collapsedMap, setCollapsedMap] = useState({});
|
|
98
|
-
const userOverrides = useRef(/* @__PURE__ */ new Set());
|
|
99
|
-
const completedRuns = useRef(/* @__PURE__ */ new Set());
|
|
100
|
-
useEffect(() => {
|
|
101
|
-
const timers = [];
|
|
102
|
-
for (const run of runs) {
|
|
103
|
-
if (run.isComplete && !completedRuns.current.has(run.id)) {
|
|
104
|
-
completedRuns.current.add(run.id);
|
|
105
|
-
if (userOverrides.current.has(run.id)) continue;
|
|
106
|
-
const timer = setTimeout(() => {
|
|
107
|
-
setCollapsedMap((prev) => ({ ...prev, [run.id]: true }));
|
|
108
|
-
}, AUTO_COLLAPSE_DELAY);
|
|
109
|
-
timers.push(timer);
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
return () => timers.forEach(clearTimeout);
|
|
113
|
-
}, [runs]);
|
|
114
97
|
const isCollapsed = useCallback(
|
|
115
98
|
(runId) => {
|
|
116
99
|
return collapsedMap[runId] ?? false;
|
|
@@ -118,7 +101,6 @@ function useRunCollapseState(runs) {
|
|
|
118
101
|
[collapsedMap]
|
|
119
102
|
);
|
|
120
103
|
const toggleCollapse = useCallback((runId) => {
|
|
121
|
-
userOverrides.current.add(runId);
|
|
122
104
|
setCollapsedMap((prev) => ({ ...prev, [runId]: !prev[runId] }));
|
|
123
105
|
}, []);
|
|
124
106
|
return { isCollapsed, toggleCollapse };
|
|
@@ -127,20 +109,20 @@ function useRunCollapseState(runs) {
|
|
|
127
109
|
// src/hooks/use-auto-scroll.ts
|
|
128
110
|
import {
|
|
129
111
|
useCallback as useCallback2,
|
|
130
|
-
useEffect
|
|
131
|
-
useRef
|
|
112
|
+
useEffect,
|
|
113
|
+
useRef,
|
|
132
114
|
useState as useState2
|
|
133
115
|
} from "react";
|
|
134
116
|
var BOTTOM_THRESHOLD = 40;
|
|
135
117
|
function useAutoScroll(containerRef, deps = []) {
|
|
136
118
|
const [isAtBottom, setIsAtBottom] = useState2(true);
|
|
137
|
-
const userScrolledUp =
|
|
119
|
+
const userScrolledUp = useRef(false);
|
|
138
120
|
const checkBottom = useCallback2(() => {
|
|
139
121
|
const el = containerRef.current;
|
|
140
122
|
if (!el) return true;
|
|
141
123
|
return el.scrollHeight - el.scrollTop - el.clientHeight < BOTTOM_THRESHOLD;
|
|
142
124
|
}, [containerRef]);
|
|
143
|
-
|
|
125
|
+
useEffect(() => {
|
|
144
126
|
const el = containerRef.current;
|
|
145
127
|
if (!el) return;
|
|
146
128
|
const onScroll = () => {
|
|
@@ -151,7 +133,7 @@ function useAutoScroll(containerRef, deps = []) {
|
|
|
151
133
|
el.addEventListener("scroll", onScroll, { passive: true });
|
|
152
134
|
return () => el.removeEventListener("scroll", onScroll);
|
|
153
135
|
}, [containerRef, checkBottom]);
|
|
154
|
-
|
|
136
|
+
useEffect(() => {
|
|
155
137
|
if (userScrolledUp.current) return;
|
|
156
138
|
const el = containerRef.current;
|
|
157
139
|
if (!el) return;
|
|
@@ -9,7 +9,6 @@ function usePtySession({ apiUrl, token, onData }) {
|
|
|
9
9
|
const retryCountRef = useRef(0);
|
|
10
10
|
const mountedRef = useRef(true);
|
|
11
11
|
const onDataRef = useRef(onData);
|
|
12
|
-
onDataRef.current = onData;
|
|
13
12
|
const connectStreamRef = useRef(null);
|
|
14
13
|
const abortStream = useCallback(() => {
|
|
15
14
|
if (retryTimerRef.current) {
|
|
@@ -117,6 +116,7 @@ function usePtySession({ apiUrl, token, onData }) {
|
|
|
117
116
|
}
|
|
118
117
|
}
|
|
119
118
|
}, [apiUrl, token, abortStream]);
|
|
119
|
+
onDataRef.current = onData;
|
|
120
120
|
connectStreamRef.current = connectStream;
|
|
121
121
|
const connect = useCallback(async () => {
|
|
122
122
|
cleanup();
|
|
@@ -149,21 +149,46 @@ function usePtySession({ apiUrl, token, onData }) {
|
|
|
149
149
|
}
|
|
150
150
|
}
|
|
151
151
|
}, [apiUrl, token, cleanup, connectStream]);
|
|
152
|
+
const resizeTerminal = useCallback(async (cols, rows) => {
|
|
153
|
+
const sid = sessionIdRef.current;
|
|
154
|
+
if (!sid || cols <= 0 || rows <= 0) return;
|
|
155
|
+
try {
|
|
156
|
+
const res = await fetch(`${apiUrl}/terminals/${sid}`, {
|
|
157
|
+
method: "PATCH",
|
|
158
|
+
headers: {
|
|
159
|
+
Authorization: `Bearer ${token}`,
|
|
160
|
+
"Content-Type": "application/json"
|
|
161
|
+
},
|
|
162
|
+
credentials: "include",
|
|
163
|
+
body: JSON.stringify({ cols, rows })
|
|
164
|
+
});
|
|
165
|
+
if (!res.ok) {
|
|
166
|
+
console.error("Failed to resize terminal:", res.status);
|
|
167
|
+
}
|
|
168
|
+
} catch (err) {
|
|
169
|
+
console.error("Failed to resize terminal", err);
|
|
170
|
+
}
|
|
171
|
+
}, [apiUrl, token]);
|
|
152
172
|
const sendCommand = useCallback(async (command) => {
|
|
153
173
|
const sid = sessionIdRef.current;
|
|
154
174
|
if (!sid) return;
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
175
|
+
try {
|
|
176
|
+
const res = await fetch(`${apiUrl}/terminals/${sid}/input`, {
|
|
177
|
+
method: "POST",
|
|
178
|
+
headers: {
|
|
179
|
+
Authorization: `Bearer ${token}`,
|
|
180
|
+
"Content-Type": "application/json"
|
|
181
|
+
},
|
|
182
|
+
credentials: "include",
|
|
183
|
+
body: JSON.stringify({ data: command })
|
|
184
|
+
});
|
|
185
|
+
if (!res.ok) {
|
|
186
|
+
const text = await res.text();
|
|
187
|
+
throw new Error(text || `Input failed: ${res.status}`);
|
|
188
|
+
}
|
|
189
|
+
} catch (err) {
|
|
190
|
+
console.error("Failed to send command", err);
|
|
191
|
+
throw err;
|
|
167
192
|
}
|
|
168
193
|
}, [apiUrl, token]);
|
|
169
194
|
useEffect(() => {
|
|
@@ -174,7 +199,7 @@ function usePtySession({ apiUrl, token, onData }) {
|
|
|
174
199
|
cleanup();
|
|
175
200
|
};
|
|
176
201
|
}, [connect, cleanup]);
|
|
177
|
-
return { isConnected, error, sendCommand, reconnect: connect };
|
|
202
|
+
return { isConnected, error, sendCommand, resizeTerminal, reconnect: connect };
|
|
178
203
|
}
|
|
179
204
|
|
|
180
205
|
export {
|
|
@@ -52,7 +52,7 @@ function Skeleton({
|
|
|
52
52
|
return /* @__PURE__ */ jsx2(
|
|
53
53
|
"div",
|
|
54
54
|
{
|
|
55
|
-
className: cn("animate-pulse rounded-lg bg-
|
|
55
|
+
className: cn("animate-pulse rounded-lg bg-muted/50", className),
|
|
56
56
|
...props
|
|
57
57
|
}
|
|
58
58
|
);
|
|
@@ -62,7 +62,7 @@ function SkeletonCard({ className }) {
|
|
|
62
62
|
"div",
|
|
63
63
|
{
|
|
64
64
|
className: cn(
|
|
65
|
-
"space-y-4 rounded-xl border border-
|
|
65
|
+
"space-y-4 rounded-xl border border-border bg-card p-6",
|
|
66
66
|
className
|
|
67
67
|
),
|
|
68
68
|
children: [
|
|
@@ -79,7 +79,7 @@ function SkeletonCard({ className }) {
|
|
|
79
79
|
}
|
|
80
80
|
function SkeletonTable({ rows = 5 }) {
|
|
81
81
|
return /* @__PURE__ */ jsxs2("div", { className: "space-y-3", children: [
|
|
82
|
-
/* @__PURE__ */ jsxs2("div", { className: "flex gap-4 border-
|
|
82
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex gap-4 border-border border-b pb-2", children: [
|
|
83
83
|
/* @__PURE__ */ jsx2(Skeleton, { className: "h-4 w-1/4" }),
|
|
84
84
|
/* @__PURE__ */ jsx2(Skeleton, { className: "h-4 w-1/4" }),
|
|
85
85
|
/* @__PURE__ */ jsx2(Skeleton, { className: "h-4 w-1/4" }),
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import {
|
|
2
|
+
cn
|
|
3
|
+
} from "./chunk-RQHJBTEU.js";
|
|
4
|
+
|
|
5
|
+
// src/dashboard/template-card.tsx
|
|
6
|
+
import { ArrowRight } from "lucide-react";
|
|
7
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
+
function TemplateCard({ template, onUseTemplate, className }) {
|
|
9
|
+
return /* @__PURE__ */ jsxs(
|
|
10
|
+
"div",
|
|
11
|
+
{
|
|
12
|
+
className: cn(
|
|
13
|
+
"group relative flex flex-col justify-between rounded-2xl border border-border bg-card p-6 transition-all hover:border-primary/30 hover:shadow-md",
|
|
14
|
+
className
|
|
15
|
+
),
|
|
16
|
+
children: [
|
|
17
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
18
|
+
/* @__PURE__ */ jsx("div", { className: "mb-4 flex h-12 w-12 items-center justify-center rounded-xl bg-muted border border-border", children: template.icon ?? /* @__PURE__ */ jsx("span", { className: "text-lg font-bold text-primary", children: template.name.charAt(0).toUpperCase() }) }),
|
|
19
|
+
/* @__PURE__ */ jsx("h3", { className: "mb-1 text-base font-bold text-foreground", children: template.name }),
|
|
20
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground leading-relaxed line-clamp-2", children: template.description }),
|
|
21
|
+
template.tags && template.tags.length > 0 && /* @__PURE__ */ jsx("div", { className: "mt-3 flex flex-wrap gap-1.5", children: template.tags.map((tag, i) => /* @__PURE__ */ jsx(
|
|
22
|
+
"span",
|
|
23
|
+
{
|
|
24
|
+
className: "rounded-full bg-muted px-2 py-0.5 text-[10px] font-medium text-muted-foreground",
|
|
25
|
+
children: tag
|
|
26
|
+
},
|
|
27
|
+
`${tag}-${i}`
|
|
28
|
+
)) })
|
|
29
|
+
] }),
|
|
30
|
+
/* @__PURE__ */ jsxs(
|
|
31
|
+
"button",
|
|
32
|
+
{
|
|
33
|
+
type: "button",
|
|
34
|
+
onClick: () => onUseTemplate(template.id),
|
|
35
|
+
className: "mt-5 inline-flex w-full items-center justify-center gap-2 rounded-xl bg-primary/10 border border-primary/20 px-4 py-2.5 text-sm font-bold text-primary transition-colors hover:bg-primary hover:text-primary-foreground active:scale-[0.98]",
|
|
36
|
+
children: [
|
|
37
|
+
"Use Template",
|
|
38
|
+
/* @__PURE__ */ jsx(ArrowRight, { className: "h-4 w-4 transition-transform group-hover:translate-x-0.5" })
|
|
39
|
+
]
|
|
40
|
+
}
|
|
41
|
+
)
|
|
42
|
+
]
|
|
43
|
+
}
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export {
|
|
48
|
+
TemplateCard
|
|
49
|
+
};
|