@tangle-network/sandbox-ui 0.22.0 → 0.23.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/auth.js +1 -3
- package/dist/{chunk-UHFJXO24.js → chunk-7ZA5SEK3.js} +177 -1
- package/dist/{chunk-ZNYEJERQ.js → chunk-CB3KBKYN.js} +864 -658
- package/dist/{chunk-R3ZMMCT3.js → chunk-IOB2PW5Z.js} +13 -5
- package/dist/dashboard.d.ts +159 -5
- package/dist/dashboard.js +8 -3
- package/dist/globals.css +10 -92
- package/dist/index.d.ts +1 -1
- package/dist/index.js +11 -7
- package/dist/pages.js +1 -2
- package/dist/primitives.js +3 -5
- package/dist/styles.css +10 -92
- package/package.json +17 -17
- package/dist/assets.d.ts +0 -81
- package/dist/assets.js +0 -935
- package/dist/chunk-SM7IJY4I.js +0 -178
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
|
-
Button
|
|
3
|
-
} from "./chunk-SM7IJY4I.js";
|
|
4
|
-
import {
|
|
2
|
+
Button,
|
|
5
3
|
Logo
|
|
6
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-7ZA5SEK3.js";
|
|
7
5
|
import {
|
|
8
6
|
cn
|
|
9
7
|
} from "./chunk-EI44GEQ5.js";
|
|
10
8
|
|
|
11
9
|
// src/dashboard/app-sidebar.tsx
|
|
10
|
+
import * as React2 from "react";
|
|
12
11
|
import { Avatar, AvatarFallback, AvatarImage } from "@tangle-network/ui/primitives";
|
|
13
12
|
import {
|
|
14
13
|
DropdownMenu,
|
|
@@ -29,6 +28,7 @@ var SIDEBAR_RAIL_WIDTH = 64;
|
|
|
29
28
|
var SIDEBAR_PANEL_WIDTH = 260;
|
|
30
29
|
var SIDEBAR_TOTAL_WIDTH = SIDEBAR_RAIL_WIDTH + SIDEBAR_PANEL_WIDTH;
|
|
31
30
|
var SIDEBAR_MOBILE_WIDTH = 256;
|
|
31
|
+
var SIDEBAR_RAIL_LABELED_WIDTH = 224;
|
|
32
32
|
var SidebarContext = React.createContext(null);
|
|
33
33
|
function readStorage(key, fallback) {
|
|
34
34
|
if (typeof window === "undefined") return fallback;
|
|
@@ -49,49 +49,44 @@ function SidebarProvider({
|
|
|
49
49
|
defaultPanelOpen = true,
|
|
50
50
|
defaultMode = "projects",
|
|
51
51
|
hasPanels = true,
|
|
52
|
+
railWidth = SIDEBAR_RAIL_WIDTH,
|
|
53
|
+
panelOpen: controlledPanelOpen,
|
|
54
|
+
onPanelOpenChange,
|
|
52
55
|
children
|
|
53
56
|
}) {
|
|
54
|
-
const
|
|
55
|
-
|
|
57
|
+
const isControlled = controlledPanelOpen !== void 0;
|
|
58
|
+
const [uncontrolledPanelOpen, setUncontrolledPanelOpen] = React.useState(
|
|
59
|
+
() => isControlled ? controlledPanelOpen : readStorage(PANEL_OPEN_KEY, String(defaultPanelOpen)) === "true"
|
|
56
60
|
);
|
|
61
|
+
const panelOpen = isControlled ? controlledPanelOpen : uncontrolledPanelOpen;
|
|
57
62
|
const [mode, setModeState] = React.useState(
|
|
58
|
-
() => readStorage(SIDEBAR_MODE_KEY, defaultMode)
|
|
63
|
+
() => isControlled ? defaultMode : readStorage(SIDEBAR_MODE_KEY, defaultMode)
|
|
59
64
|
);
|
|
60
65
|
const [hidden, setHidden] = React.useState(false);
|
|
61
66
|
const setPanelOpen = React.useCallback((open) => {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
67
|
+
if (!isControlled) {
|
|
68
|
+
setUncontrolledPanelOpen(open);
|
|
69
|
+
writeStorage(PANEL_OPEN_KEY, String(open));
|
|
70
|
+
}
|
|
71
|
+
onPanelOpenChange?.(open);
|
|
72
|
+
}, [isControlled, onPanelOpenChange]);
|
|
65
73
|
const togglePanel = React.useCallback(() => {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
writeStorage(PANEL_OPEN_KEY, String(next));
|
|
69
|
-
return next;
|
|
70
|
-
});
|
|
71
|
-
}, []);
|
|
74
|
+
setPanelOpen(!panelOpen);
|
|
75
|
+
}, [setPanelOpen, panelOpen]);
|
|
72
76
|
const setMode = React.useCallback((m) => {
|
|
73
77
|
setModeState(m);
|
|
74
|
-
writeStorage(SIDEBAR_MODE_KEY, m);
|
|
75
|
-
}, []);
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
setPanelOpenState(() => {
|
|
87
|
-
writeStorage(PANEL_OPEN_KEY, "true");
|
|
88
|
-
return true;
|
|
89
|
-
});
|
|
90
|
-
writeStorage(SIDEBAR_MODE_KEY, m);
|
|
91
|
-
return m;
|
|
92
|
-
});
|
|
93
|
-
}, []);
|
|
94
|
-
const contentMargin = hidden ? 0 : panelOpen && hasPanels ? SIDEBAR_TOTAL_WIDTH : SIDEBAR_RAIL_WIDTH;
|
|
78
|
+
if (!isControlled) writeStorage(SIDEBAR_MODE_KEY, m);
|
|
79
|
+
}, [isControlled]);
|
|
80
|
+
const switchMode = React.useCallback((m) => {
|
|
81
|
+
if (mode === m) {
|
|
82
|
+
setPanelOpen(!panelOpen);
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
setModeState(m);
|
|
86
|
+
if (!isControlled) writeStorage(SIDEBAR_MODE_KEY, m);
|
|
87
|
+
setPanelOpen(true);
|
|
88
|
+
}, [mode, panelOpen, isControlled, setPanelOpen]);
|
|
89
|
+
const contentMargin = hidden ? 0 : panelOpen && hasPanels ? railWidth + SIDEBAR_PANEL_WIDTH : railWidth;
|
|
95
90
|
const value = React.useMemo(
|
|
96
91
|
() => ({
|
|
97
92
|
panelOpen,
|
|
@@ -99,13 +94,14 @@ function SidebarProvider({
|
|
|
99
94
|
togglePanel,
|
|
100
95
|
mode,
|
|
101
96
|
setMode,
|
|
102
|
-
switchMode
|
|
97
|
+
switchMode,
|
|
103
98
|
hidden,
|
|
104
99
|
setHidden,
|
|
105
100
|
contentMargin,
|
|
106
|
-
hasPanels
|
|
101
|
+
hasPanels,
|
|
102
|
+
railWidth
|
|
107
103
|
}),
|
|
108
|
-
[panelOpen, setPanelOpen, togglePanel, mode, setMode,
|
|
104
|
+
[panelOpen, setPanelOpen, togglePanel, mode, setMode, switchMode, hidden, setHidden, contentMargin, hasPanels, railWidth]
|
|
109
105
|
);
|
|
110
106
|
return /* @__PURE__ */ jsx(SidebarContext.Provider, { value, children });
|
|
111
107
|
}
|
|
@@ -147,7 +143,7 @@ function LogOutIcon({ className }) {
|
|
|
147
143
|
] });
|
|
148
144
|
}
|
|
149
145
|
function Sidebar({ children, className, style }) {
|
|
150
|
-
const { panelOpen, hidden, hasPanels } = useSidebar();
|
|
146
|
+
const { panelOpen, hidden, hasPanels, railWidth } = useSidebar();
|
|
151
147
|
return /* @__PURE__ */ jsx2(
|
|
152
148
|
"div",
|
|
153
149
|
{
|
|
@@ -157,20 +153,22 @@ function Sidebar({ children, className, style }) {
|
|
|
157
153
|
hidden && "-translate-x-full",
|
|
158
154
|
className
|
|
159
155
|
),
|
|
160
|
-
style: { width: panelOpen && hasPanels ?
|
|
156
|
+
style: { width: panelOpen && hasPanels ? railWidth + SIDEBAR_PANEL_WIDTH : railWidth, ...style },
|
|
161
157
|
children
|
|
162
158
|
}
|
|
163
159
|
);
|
|
164
160
|
}
|
|
165
161
|
function SidebarRail({ children, className, wide = false }) {
|
|
162
|
+
const { railWidth } = useSidebar();
|
|
166
163
|
return /* @__PURE__ */ jsx2(
|
|
167
164
|
"div",
|
|
168
165
|
{
|
|
169
166
|
className: cn(
|
|
170
167
|
"flex flex-col h-full shrink-0 bg-transparent",
|
|
171
|
-
wide
|
|
168
|
+
wide && "w-full",
|
|
172
169
|
className
|
|
173
170
|
),
|
|
171
|
+
style: wide ? void 0 : { width: railWidth },
|
|
174
172
|
children
|
|
175
173
|
}
|
|
176
174
|
);
|
|
@@ -187,30 +185,31 @@ function SidebarRailFooter({ children, className }) {
|
|
|
187
185
|
function RailSeparator({ className }) {
|
|
188
186
|
return /* @__PURE__ */ jsx2("div", { className: cn("my-2 h-px w-10 bg-[var(--md3-outline-variant)]", className) });
|
|
189
187
|
}
|
|
190
|
-
function RailButton({ icon: Icon, label, isActive, badge, onClick, className, showLabel }) {
|
|
191
|
-
|
|
192
|
-
"
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
"hover:bg-[var(--accent-surface-soft)] hover:text-[var(--accent-text)]",
|
|
201
|
-
"active:scale-95",
|
|
202
|
-
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary",
|
|
203
|
-
isActive && "bg-[var(--accent-surface-strong)] text-[var(--accent-text)]",
|
|
204
|
-
!isActive && "text-muted-foreground",
|
|
205
|
-
className
|
|
206
|
-
),
|
|
207
|
-
children: [
|
|
208
|
-
/* @__PURE__ */ jsx2(Icon, { className: "h-5 w-5 shrink-0" }),
|
|
209
|
-
showLabel && /* @__PURE__ */ jsx2("span", { className: "text-sm font-medium", children: label }),
|
|
210
|
-
badge !== void 0 && badge > 0 && /* @__PURE__ */ jsx2("span", { className: "absolute -top-1 -right-1 flex h-4 min-w-4 items-center justify-center rounded-full bg-primary text-[9px] font-bold text-[var(--md3-on-primary)] px-1 shadow-sm", children: badge > 99 ? "99+" : badge })
|
|
211
|
-
]
|
|
212
|
-
}
|
|
188
|
+
function RailButton({ icon: Icon, label, isActive, badge, onClick, className, showLabel, asChild, children }) {
|
|
189
|
+
const classes = cn(
|
|
190
|
+
"group relative flex items-center justify-center rounded-xl transition-all duration-200",
|
|
191
|
+
showLabel ? "w-full justify-start px-3 h-11 gap-3" : "w-11 h-11 justify-center",
|
|
192
|
+
"hover:bg-[var(--accent-surface-soft)] hover:text-[var(--accent-text)]",
|
|
193
|
+
"active:scale-95",
|
|
194
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary",
|
|
195
|
+
isActive && "bg-[var(--accent-surface-strong)] text-[var(--accent-text)]",
|
|
196
|
+
!isActive && "text-muted-foreground",
|
|
197
|
+
className
|
|
213
198
|
);
|
|
199
|
+
const content = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
200
|
+
/* @__PURE__ */ jsx2(Icon, { className: "h-5 w-5 shrink-0" }),
|
|
201
|
+
showLabel && /* @__PURE__ */ jsx2("span", { className: "text-sm font-medium", children: label }),
|
|
202
|
+
badge !== void 0 && badge > 0 && /* @__PURE__ */ jsx2("span", { className: "absolute -top-1 -right-1 flex h-4 min-w-4 items-center justify-center rounded-full bg-primary text-[9px] font-bold text-[var(--md3-on-primary)] px-1 shadow-sm", children: badge > 99 ? "99+" : badge })
|
|
203
|
+
] });
|
|
204
|
+
if (asChild && React2.isValidElement(children)) {
|
|
205
|
+
const child = children;
|
|
206
|
+
return React2.cloneElement(
|
|
207
|
+
child,
|
|
208
|
+
{ className: cn(classes, child.props.className), title: child.props.title ?? label },
|
|
209
|
+
content
|
|
210
|
+
);
|
|
211
|
+
}
|
|
212
|
+
return /* @__PURE__ */ jsx2("button", { type: "button", onClick, title: label, className: classes, children: content });
|
|
214
213
|
}
|
|
215
214
|
function RailModeButton({ mode, icon, label, badge, className, showLabel }) {
|
|
216
215
|
const { panelOpen, mode: currentMode, switchMode } = useSidebar();
|
|
@@ -269,24 +268,35 @@ function ProfileAvatar({
|
|
|
269
268
|
settingsHref = "/dashboard/settings",
|
|
270
269
|
children,
|
|
271
270
|
className,
|
|
271
|
+
showDetails = false,
|
|
272
272
|
LinkComponent
|
|
273
273
|
}) {
|
|
274
274
|
const Link = LinkComponent ?? DefaultLink;
|
|
275
275
|
return /* @__PURE__ */ jsxs(DropdownMenu, { children: [
|
|
276
|
-
/* @__PURE__ */ jsx2(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */
|
|
276
|
+
/* @__PURE__ */ jsx2(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
|
|
277
277
|
"button",
|
|
278
278
|
{
|
|
279
279
|
type: "button",
|
|
280
280
|
className: cn(
|
|
281
|
-
"flex items-center
|
|
281
|
+
"flex items-center rounded-lg transition-colors hover:bg-[var(--accent-surface-soft)]",
|
|
282
282
|
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary",
|
|
283
|
+
showDetails ? "w-full gap-2.5 px-3 py-2 text-left" : "justify-center w-12 h-12",
|
|
283
284
|
className
|
|
284
285
|
),
|
|
285
286
|
"aria-label": "User menu",
|
|
286
|
-
children:
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
287
|
+
children: [
|
|
288
|
+
isLoading ? /* @__PURE__ */ jsx2(Skeleton, { className: "h-7 w-7 shrink-0 rounded-full" }) : /* @__PURE__ */ jsxs(Avatar, { className: "h-7 w-7 shrink-0", children: [
|
|
289
|
+
user?.avatarUrl && /* @__PURE__ */ jsx2(AvatarImage, { src: user.avatarUrl, alt: "" }),
|
|
290
|
+
/* @__PURE__ */ jsx2(AvatarFallback, { className: "text-[10px] bg-violet-500/20 text-violet-300", children: getInitials(user?.name, user?.email) })
|
|
291
|
+
] }),
|
|
292
|
+
showDetails && /* @__PURE__ */ jsx2("div", { className: "min-w-0 flex-1", children: isLoading ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
293
|
+
/* @__PURE__ */ jsx2(Skeleton, { className: "mb-1 h-3.5 w-20" }),
|
|
294
|
+
/* @__PURE__ */ jsx2(Skeleton, { className: "h-3 w-28" })
|
|
295
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
296
|
+
/* @__PURE__ */ jsx2("p", { className: "truncate text-sm font-medium text-foreground", children: user?.name ?? user?.email ?? "Not signed in" }),
|
|
297
|
+
user?.email && user?.name && /* @__PURE__ */ jsx2("p", { className: "truncate text-xs text-muted-foreground", children: user.email })
|
|
298
|
+
] }) })
|
|
299
|
+
]
|
|
290
300
|
}
|
|
291
301
|
) }),
|
|
292
302
|
/* @__PURE__ */ jsxs(DropdownMenuContent, { side: "right", align: "end", sideOffset: 8, className: "w-72", children: [
|
|
@@ -328,7 +338,7 @@ function ProfileAvatar({
|
|
|
328
338
|
}
|
|
329
339
|
|
|
330
340
|
// src/dashboard/credit-balance.tsx
|
|
331
|
-
import * as
|
|
341
|
+
import * as React3 from "react";
|
|
332
342
|
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
333
343
|
function CreditBalance({
|
|
334
344
|
amount,
|
|
@@ -337,7 +347,7 @@ function CreditBalance({
|
|
|
337
347
|
quickAmounts = [10, 25, 100],
|
|
338
348
|
className
|
|
339
349
|
}) {
|
|
340
|
-
const [topUpValue, setTopUpValue] =
|
|
350
|
+
const [topUpValue, setTopUpValue] = React3.useState("50.00");
|
|
341
351
|
return /* @__PURE__ */ jsxs2(
|
|
342
352
|
"div",
|
|
343
353
|
{
|
|
@@ -498,9 +508,10 @@ function getBarColor(percent) {
|
|
|
498
508
|
if (percent >= 70) return "bg-[var(--surface-warning-text)]";
|
|
499
509
|
return "bg-primary";
|
|
500
510
|
}
|
|
501
|
-
function ResourceMeter({ label, value, max = 100, unit, icon, className }) {
|
|
502
|
-
const percent = max > 0 ? Math.min(value / max * 100, 100) : 0;
|
|
511
|
+
function ResourceMeter({ label, value, max = 100, unit, valueLabel, icon, className }) {
|
|
512
|
+
const percent = max > 0 ? Math.max(0, Math.min(value / max * 100, 100)) : 0;
|
|
503
513
|
const barColor = getBarColor(percent);
|
|
514
|
+
const readout = valueLabel ?? (unit ? `${value}${unit}/${max}${unit}` : `${Math.round(percent)}%`);
|
|
504
515
|
return /* @__PURE__ */ jsxs5("div", { className: cn("flex items-center gap-3", className), children: [
|
|
505
516
|
/* @__PURE__ */ jsxs5("span", { className: "flex shrink-0 items-center gap-1 text-[10px] font-mono text-muted-foreground uppercase tracking-wide", children: [
|
|
506
517
|
icon,
|
|
@@ -513,10 +524,94 @@ function ResourceMeter({ label, value, max = 100, unit, icon, className }) {
|
|
|
513
524
|
style: { width: `${percent}%` }
|
|
514
525
|
}
|
|
515
526
|
) }),
|
|
516
|
-
/* @__PURE__ */ jsx6("span", { className: "shrink-0 text-[10px] font-mono tabular-nums text-muted-foreground", children:
|
|
527
|
+
/* @__PURE__ */ jsx6("span", { className: "shrink-0 text-[10px] font-mono tabular-nums text-muted-foreground", children: readout })
|
|
517
528
|
] });
|
|
518
529
|
}
|
|
519
530
|
|
|
531
|
+
// src/dashboard/resource-snapshot.tsx
|
|
532
|
+
import { Skeleton as Skeleton2 } from "@tangle-network/ui/primitives";
|
|
533
|
+
import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
534
|
+
function ResourceSnapshot({
|
|
535
|
+
title = "Resources",
|
|
536
|
+
action,
|
|
537
|
+
items,
|
|
538
|
+
loading = false,
|
|
539
|
+
error = null,
|
|
540
|
+
className
|
|
541
|
+
}) {
|
|
542
|
+
const rowCount = items.length > 0 ? items.length : 3;
|
|
543
|
+
return /* @__PURE__ */ jsxs6(
|
|
544
|
+
"div",
|
|
545
|
+
{
|
|
546
|
+
className: cn(
|
|
547
|
+
"flex flex-col rounded-lg border border-border bg-card p-6",
|
|
548
|
+
className
|
|
549
|
+
),
|
|
550
|
+
children: [
|
|
551
|
+
/* @__PURE__ */ jsxs6("div", { className: "mb-4 flex items-center justify-between gap-2", children: [
|
|
552
|
+
/* @__PURE__ */ jsx7("h3", { className: "font-display font-semibold text-foreground text-sm", children: title }),
|
|
553
|
+
action
|
|
554
|
+
] }),
|
|
555
|
+
error ? /* @__PURE__ */ jsx7("p", { className: "text-[var(--surface-danger-text)] text-xs", children: error }) : loading ? /* @__PURE__ */ jsx7("div", { className: "space-y-3", children: Array.from({ length: rowCount }).map((_, i) => /* @__PURE__ */ jsx7(Skeleton2, { className: "h-4 w-full" }, i)) }) : /* @__PURE__ */ jsx7("div", { className: "space-y-3", children: items.map((item, idx) => /* @__PURE__ */ jsx7(
|
|
556
|
+
ResourceMeter,
|
|
557
|
+
{
|
|
558
|
+
label: item.label,
|
|
559
|
+
value: item.value,
|
|
560
|
+
max: item.max,
|
|
561
|
+
unit: item.unit,
|
|
562
|
+
valueLabel: item.valueLabel,
|
|
563
|
+
icon: item.icon
|
|
564
|
+
},
|
|
565
|
+
item.id ?? `${item.label}-${idx}`
|
|
566
|
+
)) })
|
|
567
|
+
]
|
|
568
|
+
}
|
|
569
|
+
);
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
// src/dashboard/activity-feed.tsx
|
|
573
|
+
import * as React4 from "react";
|
|
574
|
+
import { Skeleton as Skeleton3 } from "@tangle-network/ui/primitives";
|
|
575
|
+
import { timeAgo } from "@tangle-network/ui/utils";
|
|
576
|
+
import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
577
|
+
function ActivityFeed({
|
|
578
|
+
title = "Recent activity",
|
|
579
|
+
action,
|
|
580
|
+
items,
|
|
581
|
+
loading = false,
|
|
582
|
+
maxItems = 6,
|
|
583
|
+
emptyLabel = "No recent activity",
|
|
584
|
+
className
|
|
585
|
+
}) {
|
|
586
|
+
const sorted = React4.useMemo(
|
|
587
|
+
() => [...items].sort((a, b) => (b.timestamp ?? 0) - (a.timestamp ?? 0)).slice(0, maxItems),
|
|
588
|
+
[items, maxItems]
|
|
589
|
+
);
|
|
590
|
+
return /* @__PURE__ */ jsxs7(
|
|
591
|
+
"div",
|
|
592
|
+
{
|
|
593
|
+
className: cn(
|
|
594
|
+
"flex flex-col rounded-lg border border-border bg-card p-6",
|
|
595
|
+
className
|
|
596
|
+
),
|
|
597
|
+
children: [
|
|
598
|
+
/* @__PURE__ */ jsxs7("div", { className: "mb-4 flex items-center justify-between gap-2", children: [
|
|
599
|
+
/* @__PURE__ */ jsx8("h3", { className: "font-display font-semibold text-foreground text-sm", children: title }),
|
|
600
|
+
action
|
|
601
|
+
] }),
|
|
602
|
+
loading ? /* @__PURE__ */ jsx8("div", { className: "space-y-3", children: Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ jsx8(Skeleton3, { className: "h-9 w-full" }, i)) }) : sorted.length === 0 ? /* @__PURE__ */ jsx8("p", { className: "text-muted-foreground text-sm", children: emptyLabel }) : /* @__PURE__ */ jsx8("ul", { className: "space-y-3", children: sorted.map((item) => /* @__PURE__ */ jsxs7("li", { className: "flex items-start gap-3", children: [
|
|
603
|
+
item.icon && /* @__PURE__ */ jsx8("span", { className: "mt-0.5 shrink-0 text-muted-foreground", children: item.icon }),
|
|
604
|
+
/* @__PURE__ */ jsxs7("div", { className: "min-w-0 flex-1", children: [
|
|
605
|
+
/* @__PURE__ */ jsx8("p", { className: "truncate font-medium text-foreground text-sm", children: item.title }),
|
|
606
|
+
item.detail && /* @__PURE__ */ jsx8("p", { className: "truncate text-muted-foreground text-xs", children: item.detail })
|
|
607
|
+
] }),
|
|
608
|
+
item.timestamp != null && /* @__PURE__ */ jsx8("span", { className: "shrink-0 text-muted-foreground text-xs tabular-nums", children: timeAgo(item.timestamp) })
|
|
609
|
+
] }, item.id)) })
|
|
610
|
+
]
|
|
611
|
+
}
|
|
612
|
+
);
|
|
613
|
+
}
|
|
614
|
+
|
|
520
615
|
// src/dashboard/sandbox-card.tsx
|
|
521
616
|
import {
|
|
522
617
|
DropdownMenu as DropdownMenu2,
|
|
@@ -541,7 +636,7 @@ import {
|
|
|
541
636
|
Plus,
|
|
542
637
|
Users
|
|
543
638
|
} from "lucide-react";
|
|
544
|
-
import { Fragment as Fragment3, jsx as
|
|
639
|
+
import { Fragment as Fragment3, jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
545
640
|
function canAdminSandbox(sandbox) {
|
|
546
641
|
if (!sandbox.team) return true;
|
|
547
642
|
return sandbox.team.role === "owner" || sandbox.team.role === "admin";
|
|
@@ -564,115 +659,115 @@ function SandboxCard({
|
|
|
564
659
|
const isRunning = sandbox.status === "running";
|
|
565
660
|
const isTransitioning = sandbox.status === "provisioning" || sandbox.status === "creating";
|
|
566
661
|
const isStopped = !isRunning && !isTransitioning;
|
|
567
|
-
return /* @__PURE__ */
|
|
662
|
+
return /* @__PURE__ */ jsxs8("div", { className: cn(
|
|
568
663
|
"group relative flex flex-col justify-between overflow-hidden rounded-lg border bg-card p-5 transition-colors",
|
|
569
664
|
isRunning ? "border-[var(--status-running)]/30" : "border-border",
|
|
570
665
|
"hover:border-foreground/15",
|
|
571
666
|
className
|
|
572
667
|
), children: [
|
|
573
|
-
/* @__PURE__ */
|
|
574
|
-
/* @__PURE__ */
|
|
575
|
-
/* @__PURE__ */
|
|
576
|
-
/* @__PURE__ */
|
|
668
|
+
/* @__PURE__ */ jsxs8("div", { className: "flex items-start justify-between", children: [
|
|
669
|
+
/* @__PURE__ */ jsxs8("div", { children: [
|
|
670
|
+
/* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-2", children: [
|
|
671
|
+
/* @__PURE__ */ jsxs8("h3", { className: "flex items-center gap-2 text-sm font-bold text-foreground", children: [
|
|
577
672
|
sandbox.name,
|
|
578
|
-
isRunning && /* @__PURE__ */
|
|
579
|
-
/* @__PURE__ */
|
|
580
|
-
/* @__PURE__ */
|
|
673
|
+
isRunning && /* @__PURE__ */ jsxs8("span", { className: "relative flex h-2 w-2", children: [
|
|
674
|
+
/* @__PURE__ */ jsx9("span", { className: "absolute inline-flex h-full w-full animate-pulse rounded-full bg-[var(--status-running)] opacity-75" }),
|
|
675
|
+
/* @__PURE__ */ jsx9("span", { className: "relative inline-flex h-1.5 w-1.5 rounded-full bg-[var(--status-running)]" })
|
|
581
676
|
] })
|
|
582
677
|
] }),
|
|
583
|
-
sandbox.team && /* @__PURE__ */
|
|
678
|
+
sandbox.team && /* @__PURE__ */ jsxs8(
|
|
584
679
|
"span",
|
|
585
680
|
{
|
|
586
681
|
className: "inline-flex items-center gap-1 rounded-full bg-[var(--accent-surface-soft)] px-2 py-0.5 text-[10px] font-semibold text-[var(--accent-text)]",
|
|
587
682
|
title: `Shared with ${sandbox.team.name ?? "Team"} \xB7 ${sandbox.team.role}`,
|
|
588
683
|
children: [
|
|
589
|
-
/* @__PURE__ */
|
|
684
|
+
/* @__PURE__ */ jsx9(Users, { className: "h-3 w-3", "aria-hidden": "true" }),
|
|
590
685
|
sandbox.team.name ?? "Team"
|
|
591
686
|
]
|
|
592
687
|
}
|
|
593
688
|
)
|
|
594
689
|
] }),
|
|
595
|
-
/* @__PURE__ */
|
|
690
|
+
/* @__PURE__ */ jsxs8("p", { className: "mt-0.5 font-mono text-[10px] tracking-wider text-muted-foreground uppercase", children: [
|
|
596
691
|
sandbox.nodeId || "Unknown Node",
|
|
597
|
-
sandbox.team && /* @__PURE__ */
|
|
692
|
+
sandbox.team && /* @__PURE__ */ jsxs8("span", { className: "ml-2 normal-case tracking-normal", children: [
|
|
598
693
|
"\xB7 your role: ",
|
|
599
694
|
sandbox.team.role
|
|
600
695
|
] })
|
|
601
696
|
] })
|
|
602
697
|
] }),
|
|
603
|
-
/* @__PURE__ */
|
|
604
|
-
/* @__PURE__ */
|
|
698
|
+
/* @__PURE__ */ jsxs8(DropdownMenu2, { children: [
|
|
699
|
+
/* @__PURE__ */ jsx9(DropdownMenuTrigger2, { asChild: true, children: /* @__PURE__ */ jsx9(
|
|
605
700
|
"button",
|
|
606
701
|
{
|
|
607
702
|
type: "button",
|
|
608
703
|
className: "rounded-md p-1.5 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground outline-none",
|
|
609
704
|
"aria-label": "Sandbox options",
|
|
610
|
-
children: /* @__PURE__ */
|
|
705
|
+
children: /* @__PURE__ */ jsx9(MoreVertical, { className: "h-4 w-4" })
|
|
611
706
|
}
|
|
612
707
|
) }),
|
|
613
|
-
/* @__PURE__ */
|
|
614
|
-
isRunning && /* @__PURE__ */
|
|
615
|
-
onStop && /* @__PURE__ */
|
|
616
|
-
/* @__PURE__ */
|
|
708
|
+
/* @__PURE__ */ jsxs8(DropdownMenuContent2, { align: "end", className: "min-w-[180px]", children: [
|
|
709
|
+
isRunning && /* @__PURE__ */ jsxs8(Fragment3, { children: [
|
|
710
|
+
onStop && /* @__PURE__ */ jsxs8(DropdownMenuItem2, { onClick: () => onStop(sandbox.id), children: [
|
|
711
|
+
/* @__PURE__ */ jsx9(PowerOff, { className: "mr-2 h-4 w-4" }),
|
|
617
712
|
" Stop Sandbox"
|
|
618
713
|
] }),
|
|
619
|
-
onKeepAlive && /* @__PURE__ */
|
|
620
|
-
/* @__PURE__ */
|
|
714
|
+
onKeepAlive && /* @__PURE__ */ jsxs8(DropdownMenuItem2, { onClick: () => onKeepAlive(sandbox.id), children: [
|
|
715
|
+
/* @__PURE__ */ jsx9(Clock, { className: "mr-2 h-4 w-4" }),
|
|
621
716
|
" Keep Alive"
|
|
622
717
|
] }),
|
|
623
|
-
(onStop || onKeepAlive) && /* @__PURE__ */
|
|
624
|
-
onUsage && /* @__PURE__ */
|
|
625
|
-
/* @__PURE__ */
|
|
718
|
+
(onStop || onKeepAlive) && /* @__PURE__ */ jsx9(DropdownMenuSeparator2, {}),
|
|
719
|
+
onUsage && /* @__PURE__ */ jsxs8(DropdownMenuItem2, { onClick: () => onUsage(sandbox.id), children: [
|
|
720
|
+
/* @__PURE__ */ jsx9(BarChart2, { className: "mr-2 h-4 w-4" }),
|
|
626
721
|
" View Usage"
|
|
627
722
|
] }),
|
|
628
|
-
onHealth && /* @__PURE__ */
|
|
629
|
-
/* @__PURE__ */
|
|
723
|
+
onHealth && /* @__PURE__ */ jsxs8(DropdownMenuItem2, { onClick: () => onHealth(sandbox.id), children: [
|
|
724
|
+
/* @__PURE__ */ jsx9(Activity, { className: "mr-2 h-4 w-4" }),
|
|
630
725
|
" Health Check"
|
|
631
726
|
] }),
|
|
632
|
-
(onUsage || onHealth) && /* @__PURE__ */
|
|
633
|
-
onFork && /* @__PURE__ */
|
|
634
|
-
/* @__PURE__ */
|
|
635
|
-
/* @__PURE__ */
|
|
727
|
+
(onUsage || onHealth) && /* @__PURE__ */ jsx9(DropdownMenuSeparator2, {}),
|
|
728
|
+
onFork && /* @__PURE__ */ jsxs8(Fragment3, { children: [
|
|
729
|
+
/* @__PURE__ */ jsxs8(DropdownMenuItem2, { onClick: () => onFork(sandbox.id), children: [
|
|
730
|
+
/* @__PURE__ */ jsx9(Copy, { className: "mr-2 h-4 w-4" }),
|
|
636
731
|
" Fork Sandbox"
|
|
637
732
|
] }),
|
|
638
|
-
/* @__PURE__ */
|
|
733
|
+
/* @__PURE__ */ jsx9(DropdownMenuSeparator2, {})
|
|
639
734
|
] })
|
|
640
735
|
] }),
|
|
641
|
-
isStopped && /* @__PURE__ */
|
|
642
|
-
onResume && /* @__PURE__ */
|
|
643
|
-
/* @__PURE__ */
|
|
736
|
+
isStopped && /* @__PURE__ */ jsxs8(Fragment3, { children: [
|
|
737
|
+
onResume && /* @__PURE__ */ jsxs8(DropdownMenuItem2, { onClick: () => onResume(sandbox.id), children: [
|
|
738
|
+
/* @__PURE__ */ jsx9(Power, { className: "mr-2 h-4 w-4" }),
|
|
644
739
|
" Resume Sandbox"
|
|
645
740
|
] }),
|
|
646
|
-
onFork && /* @__PURE__ */
|
|
647
|
-
/* @__PURE__ */
|
|
741
|
+
onFork && /* @__PURE__ */ jsxs8(DropdownMenuItem2, { onClick: () => onFork(sandbox.id), children: [
|
|
742
|
+
/* @__PURE__ */ jsx9(Copy, { className: "mr-2 h-4 w-4" }),
|
|
648
743
|
" Fork Sandbox"
|
|
649
744
|
] }),
|
|
650
|
-
(onResume || onFork) && /* @__PURE__ */
|
|
745
|
+
(onResume || onFork) && /* @__PURE__ */ jsx9(DropdownMenuSeparator2, {})
|
|
651
746
|
] }),
|
|
652
|
-
onDelete && canAdminSandbox(sandbox) && /* @__PURE__ */
|
|
653
|
-
/* @__PURE__ */
|
|
747
|
+
onDelete && canAdminSandbox(sandbox) && /* @__PURE__ */ jsxs8(DropdownMenuItem2, { className: "text-destructive focus:bg-destructive/10 focus:text-destructive", onClick: () => onDelete(sandbox.id), children: [
|
|
748
|
+
/* @__PURE__ */ jsx9(Trash2, { className: "mr-2 h-4 w-4" }),
|
|
654
749
|
" Delete Sandbox"
|
|
655
750
|
] })
|
|
656
751
|
] })
|
|
657
752
|
] })
|
|
658
753
|
] }),
|
|
659
|
-
/* @__PURE__ */
|
|
660
|
-
/* @__PURE__ */
|
|
661
|
-
/* @__PURE__ */
|
|
662
|
-
/* @__PURE__ */
|
|
663
|
-
/* @__PURE__ */
|
|
664
|
-
/* @__PURE__ */
|
|
754
|
+
/* @__PURE__ */ jsxs8("div", { className: "my-4", children: [
|
|
755
|
+
/* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-3 rounded-md border border-border bg-muted/30 p-3", children: [
|
|
756
|
+
/* @__PURE__ */ jsx9("div", { className: cn("flex h-10 w-10 items-center justify-center rounded-md", isRunning ? "bg-[var(--surface-success-bg)]" : "bg-muted"), children: sandbox.imageIcon ? sandbox.imageIcon : sandbox.image?.includes("node") ? /* @__PURE__ */ jsx9(Code2, { className: cn("h-5 w-5", isRunning ? "text-[var(--surface-success-text)]" : "text-muted-foreground") }) : /* @__PURE__ */ jsx9(Terminal, { className: cn("h-5 w-5", isRunning ? "text-[var(--surface-success-text)]" : "text-muted-foreground") }) }),
|
|
757
|
+
/* @__PURE__ */ jsxs8("div", { className: "flex flex-col", children: [
|
|
758
|
+
/* @__PURE__ */ jsx9("span", { className: "text-[10px] text-muted-foreground uppercase tracking-widest font-bold", children: "Environment" }),
|
|
759
|
+
/* @__PURE__ */ jsx9("span", { className: "text-xs font-medium text-foreground font-mono mt-0.5", children: sandbox.image || "Universal" })
|
|
665
760
|
] })
|
|
666
761
|
] }),
|
|
667
|
-
isTransitioning && /* @__PURE__ */
|
|
668
|
-
/* @__PURE__ */
|
|
669
|
-
/* @__PURE__ */
|
|
670
|
-
/* @__PURE__ */
|
|
762
|
+
isTransitioning && /* @__PURE__ */ jsxs8("div", { className: "mt-3", children: [
|
|
763
|
+
/* @__PURE__ */ jsxs8("div", { className: "flex justify-between text-xs text-muted-foreground font-medium mb-1", children: [
|
|
764
|
+
/* @__PURE__ */ jsx9("span", { children: sandbox.provisioningMessage || "Starting..." }),
|
|
765
|
+
/* @__PURE__ */ jsxs8("span", { children: [
|
|
671
766
|
sandbox.provisioningPercent || 0,
|
|
672
767
|
"%"
|
|
673
768
|
] })
|
|
674
769
|
] }),
|
|
675
|
-
/* @__PURE__ */
|
|
770
|
+
/* @__PURE__ */ jsx9("div", { className: "h-1 w-full overflow-hidden rounded-full bg-muted", children: /* @__PURE__ */ jsx9(
|
|
676
771
|
"div",
|
|
677
772
|
{
|
|
678
773
|
className: "h-full bg-primary transition-all duration-500 rounded-full",
|
|
@@ -681,18 +776,18 @@ function SandboxCard({
|
|
|
681
776
|
) })
|
|
682
777
|
] })
|
|
683
778
|
] }),
|
|
684
|
-
/* @__PURE__ */
|
|
779
|
+
/* @__PURE__ */ jsx9("div", { className: "border-t border-border pt-3", children: isRunning ? /* @__PURE__ */ jsxs8(
|
|
685
780
|
"button",
|
|
686
781
|
{
|
|
687
782
|
type: "button",
|
|
688
783
|
onClick: () => onOpenIDE?.(sandbox.id),
|
|
689
784
|
className: "flex w-full items-center justify-center gap-2 rounded-md bg-[var(--btn-primary-bg)] px-4 py-2 text-sm font-semibold text-[var(--btn-primary-text)] transition-colors hover:bg-[var(--btn-primary-hover)] active:scale-[0.97]",
|
|
690
785
|
children: [
|
|
691
|
-
/* @__PURE__ */
|
|
786
|
+
/* @__PURE__ */ jsx9(Network, { className: "h-4 w-4" }),
|
|
692
787
|
"Connect Session"
|
|
693
788
|
]
|
|
694
789
|
}
|
|
695
|
-
) : /* @__PURE__ */
|
|
790
|
+
) : /* @__PURE__ */ jsxs8(
|
|
696
791
|
"button",
|
|
697
792
|
{
|
|
698
793
|
type: "button",
|
|
@@ -703,7 +798,7 @@ function SandboxCard({
|
|
|
703
798
|
isTransitioning ? "bg-muted text-muted-foreground cursor-not-allowed border-border" : "bg-card text-foreground hover:bg-muted border-border active:scale-[0.97]"
|
|
704
799
|
),
|
|
705
800
|
children: [
|
|
706
|
-
/* @__PURE__ */
|
|
801
|
+
/* @__PURE__ */ jsx9(Play, { className: "h-4 w-4" }),
|
|
707
802
|
isTransitioning ? "Starting..." : "Wake Sandbox"
|
|
708
803
|
]
|
|
709
804
|
}
|
|
@@ -711,7 +806,7 @@ function SandboxCard({
|
|
|
711
806
|
] });
|
|
712
807
|
}
|
|
713
808
|
function NewSandboxCard({ onClick, className }) {
|
|
714
|
-
return /* @__PURE__ */
|
|
809
|
+
return /* @__PURE__ */ jsxs8(
|
|
715
810
|
"button",
|
|
716
811
|
{
|
|
717
812
|
type: "button",
|
|
@@ -721,16 +816,16 @@ function NewSandboxCard({ onClick, className }) {
|
|
|
721
816
|
className
|
|
722
817
|
),
|
|
723
818
|
children: [
|
|
724
|
-
/* @__PURE__ */
|
|
725
|
-
/* @__PURE__ */
|
|
726
|
-
/* @__PURE__ */
|
|
819
|
+
/* @__PURE__ */ jsx9("div", { className: "flex h-12 w-12 items-center justify-center rounded-lg bg-muted text-muted-foreground", children: /* @__PURE__ */ jsx9(Plus, { className: "h-6 w-6" }) }),
|
|
820
|
+
/* @__PURE__ */ jsx9("span", { className: "mt-4 text-sm font-semibold text-foreground", children: "New Sandbox" }),
|
|
821
|
+
/* @__PURE__ */ jsx9("span", { className: "mt-1 text-xs text-muted-foreground", children: "Deploy a new isolated environment" })
|
|
727
822
|
]
|
|
728
823
|
}
|
|
729
824
|
);
|
|
730
825
|
}
|
|
731
826
|
|
|
732
827
|
// src/dashboard/sandbox-table.tsx
|
|
733
|
-
import * as
|
|
828
|
+
import * as React5 from "react";
|
|
734
829
|
import {
|
|
735
830
|
Activity as Activity2,
|
|
736
831
|
BarChart2 as BarChart22,
|
|
@@ -757,7 +852,7 @@ import {
|
|
|
757
852
|
DropdownMenuSeparator as DropdownMenuSeparator3,
|
|
758
853
|
DropdownMenuTrigger as DropdownMenuTrigger3
|
|
759
854
|
} from "@tangle-network/ui/primitives";
|
|
760
|
-
import { Fragment as Fragment5, jsx as
|
|
855
|
+
import { Fragment as Fragment5, jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
761
856
|
var statusColors = {
|
|
762
857
|
running: { dot: "bg-[var(--code-success)] animate-pulse", text: "text-[var(--code-success)]", bar: "bg-[var(--code-success)]" },
|
|
763
858
|
hibernating: { dot: "bg-muted-foreground", text: "text-muted-foreground", bar: "bg-muted-foreground" },
|
|
@@ -771,15 +866,15 @@ function isResumable(status) {
|
|
|
771
866
|
return status !== "running" && status !== "provisioning" && status !== "creating";
|
|
772
867
|
}
|
|
773
868
|
function MiniMeter({ label, percent, className }) {
|
|
774
|
-
return /* @__PURE__ */
|
|
775
|
-
/* @__PURE__ */
|
|
776
|
-
/* @__PURE__ */
|
|
777
|
-
/* @__PURE__ */
|
|
869
|
+
return /* @__PURE__ */ jsxs9("div", { className: cn("space-y-1", className), children: [
|
|
870
|
+
/* @__PURE__ */ jsxs9("div", { className: "flex justify-between text-[10px] font-mono text-muted-foreground", children: [
|
|
871
|
+
/* @__PURE__ */ jsx10("span", { className: "font-bold", children: label }),
|
|
872
|
+
/* @__PURE__ */ jsxs9("span", { className: "text-primary", children: [
|
|
778
873
|
percent,
|
|
779
874
|
"%"
|
|
780
875
|
] })
|
|
781
876
|
] }),
|
|
782
|
-
/* @__PURE__ */
|
|
877
|
+
/* @__PURE__ */ jsx10("div", { className: "h-1.5 w-full bg-background rounded-full overflow-hidden", children: /* @__PURE__ */ jsx10("div", { className: "h-full bg-primary rounded-full", style: { width: `${percent}%` } }) })
|
|
783
878
|
] });
|
|
784
879
|
}
|
|
785
880
|
function SandboxTable({
|
|
@@ -818,17 +913,17 @@ function SandboxTable({
|
|
|
818
913
|
const handler = resolveResumeHandler(sb.status);
|
|
819
914
|
return handler ? () => handler(sb.id) : void 0;
|
|
820
915
|
};
|
|
821
|
-
return /* @__PURE__ */
|
|
822
|
-
/* @__PURE__ */
|
|
823
|
-
/* @__PURE__ */
|
|
824
|
-
/* @__PURE__ */
|
|
825
|
-
/* @__PURE__ */
|
|
826
|
-
hasTeamSandboxes && /* @__PURE__ */
|
|
827
|
-
/* @__PURE__ */
|
|
828
|
-
/* @__PURE__ */
|
|
829
|
-
/* @__PURE__ */
|
|
916
|
+
return /* @__PURE__ */ jsxs9("div", { className: cn("w-full", className), children: [
|
|
917
|
+
/* @__PURE__ */ jsx10("div", { className: "w-full bg-card rounded-2xl overflow-hidden border border-border", children: /* @__PURE__ */ jsx10("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxs9("table", { className: "w-full text-left border-collapse", children: [
|
|
918
|
+
/* @__PURE__ */ jsx10("thead", { children: /* @__PURE__ */ jsxs9("tr", { className: "bg-background border-b border-border", children: [
|
|
919
|
+
/* @__PURE__ */ jsx10("th", { className: "px-6 py-4 text-xs font-semibold text-muted-foreground uppercase tracking-wider", children: "Status" }),
|
|
920
|
+
/* @__PURE__ */ jsx10("th", { className: "px-6 py-4 text-xs font-semibold text-muted-foreground uppercase tracking-wider", children: "Sandbox Name" }),
|
|
921
|
+
hasTeamSandboxes && /* @__PURE__ */ jsx10("th", { className: "px-6 py-4 text-xs font-semibold text-muted-foreground uppercase tracking-wider", children: "Scope" }),
|
|
922
|
+
/* @__PURE__ */ jsx10("th", { className: "px-6 py-4 text-xs font-semibold text-muted-foreground uppercase tracking-wider", children: "Environment" }),
|
|
923
|
+
/* @__PURE__ */ jsx10("th", { className: "px-6 py-4 text-xs font-semibold text-muted-foreground uppercase tracking-wider", children: "Resources" }),
|
|
924
|
+
/* @__PURE__ */ jsx10("th", { className: "px-6 py-4 text-xs font-semibold text-muted-foreground uppercase tracking-wider text-right", children: "Actions" })
|
|
830
925
|
] }) }),
|
|
831
|
-
/* @__PURE__ */
|
|
926
|
+
/* @__PURE__ */ jsx10("tbody", { className: "divide-y divide-border", children: sandboxes.map((sb) => {
|
|
832
927
|
const sc = statusColors[sb.status] ?? statusColors.stopped;
|
|
833
928
|
const isActive = sb.status === "running";
|
|
834
929
|
const isHibernating = sb.status === "hibernating";
|
|
@@ -850,7 +945,7 @@ function SandboxTable({
|
|
|
850
945
|
// IDE, Delete, …), which keep their native
|
|
851
946
|
// semantics. Mouse users get the click-anywhere
|
|
852
947
|
// affordance; nobody loses access.
|
|
853
|
-
/* @__PURE__ */
|
|
948
|
+
/* @__PURE__ */ jsxs9(
|
|
854
949
|
"tr",
|
|
855
950
|
{
|
|
856
951
|
className: cn(
|
|
@@ -859,69 +954,69 @@ function SandboxTable({
|
|
|
859
954
|
),
|
|
860
955
|
onClick: onRowClick,
|
|
861
956
|
children: [
|
|
862
|
-
/* @__PURE__ */
|
|
863
|
-
/* @__PURE__ */
|
|
864
|
-
/* @__PURE__ */
|
|
957
|
+
/* @__PURE__ */ jsx10("td", { className: "px-6 py-5 whitespace-nowrap", children: /* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-2", children: [
|
|
958
|
+
/* @__PURE__ */ jsx10("span", { className: cn("flex h-2.5 w-2.5 rounded-full", sc.dot) }),
|
|
959
|
+
/* @__PURE__ */ jsx10("span", { className: cn("text-xs font-bold uppercase tracking-wide", sc.text), children: sb.status.charAt(0).toUpperCase() + sb.status.slice(1) })
|
|
865
960
|
] }) }),
|
|
866
|
-
/* @__PURE__ */
|
|
867
|
-
/* @__PURE__ */
|
|
868
|
-
sb.nodeId && /* @__PURE__ */
|
|
961
|
+
/* @__PURE__ */ jsx10("td", { className: "px-6 py-5", children: /* @__PURE__ */ jsxs9("div", { className: "flex flex-col", children: [
|
|
962
|
+
/* @__PURE__ */ jsx10("span", { className: "text-sm font-bold text-foreground group-hover:text-primary transition-colors", children: sb.name }),
|
|
963
|
+
sb.nodeId && /* @__PURE__ */ jsx10("span", { className: "text-[10px] font-mono text-muted-foreground", children: sb.nodeId })
|
|
869
964
|
] }) }),
|
|
870
|
-
hasTeamSandboxes && /* @__PURE__ */
|
|
965
|
+
hasTeamSandboxes && /* @__PURE__ */ jsx10("td", { className: "px-6 py-5", children: sb.team ? /* @__PURE__ */ jsxs9(
|
|
871
966
|
"div",
|
|
872
967
|
{
|
|
873
968
|
className: "inline-flex items-center gap-1.5 rounded-full bg-[var(--accent-surface-soft)] px-2.5 py-1 text-[11px] font-semibold text-[var(--accent-text)]",
|
|
874
969
|
title: `Shared with ${sb.team.name ?? "Team"} \xB7 ${sb.team.role}`,
|
|
875
970
|
children: [
|
|
876
|
-
/* @__PURE__ */
|
|
877
|
-
/* @__PURE__ */
|
|
878
|
-
/* @__PURE__ */
|
|
971
|
+
/* @__PURE__ */ jsx10(Users2, { className: "h-3 w-3", "aria-hidden": "true" }),
|
|
972
|
+
/* @__PURE__ */ jsx10("span", { children: sb.team.name ?? "Team" }),
|
|
973
|
+
/* @__PURE__ */ jsxs9("span", { className: "font-normal text-muted-foreground", children: [
|
|
879
974
|
"\xB7 ",
|
|
880
975
|
sb.team.role
|
|
881
976
|
] })
|
|
882
977
|
]
|
|
883
978
|
}
|
|
884
|
-
) : /* @__PURE__ */
|
|
979
|
+
) : /* @__PURE__ */ jsxs9(
|
|
885
980
|
"div",
|
|
886
981
|
{
|
|
887
982
|
className: "inline-flex items-center gap-1.5 rounded-full bg-muted px-2.5 py-1 text-[11px] font-medium text-muted-foreground",
|
|
888
983
|
title: "Personal sandbox",
|
|
889
984
|
children: [
|
|
890
|
-
/* @__PURE__ */
|
|
985
|
+
/* @__PURE__ */ jsx10(User, { className: "h-3 w-3", "aria-hidden": "true" }),
|
|
891
986
|
"Personal"
|
|
892
987
|
]
|
|
893
988
|
}
|
|
894
989
|
) }),
|
|
895
|
-
/* @__PURE__ */
|
|
896
|
-
sb.imageIcon && /* @__PURE__ */
|
|
897
|
-
sb.image && /* @__PURE__ */
|
|
990
|
+
/* @__PURE__ */ jsx10("td", { className: "px-6 py-5", children: /* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-3", children: [
|
|
991
|
+
sb.imageIcon && /* @__PURE__ */ jsx10("div", { className: "w-8 h-8 rounded-lg bg-muted/50 flex items-center justify-center", children: sb.imageIcon }),
|
|
992
|
+
sb.image && /* @__PURE__ */ jsx10("span", { className: "text-xs font-bold text-foreground", children: sb.image })
|
|
898
993
|
] }) }),
|
|
899
|
-
/* @__PURE__ */
|
|
900
|
-
/* @__PURE__ */
|
|
901
|
-
/* @__PURE__ */
|
|
902
|
-
] }) : isProvisioning ? /* @__PURE__ */
|
|
903
|
-
/* @__PURE__ */
|
|
994
|
+
/* @__PURE__ */ jsx10("td", { className: "px-6 py-5", children: isActive ? /* @__PURE__ */ jsxs9("div", { className: "space-y-3 w-48", children: [
|
|
995
|
+
/* @__PURE__ */ jsx10(MiniMeter, { label: "CPU", percent: sb.cpuPercent ?? 0 }),
|
|
996
|
+
/* @__PURE__ */ jsx10(MiniMeter, { label: "RAM", percent: sb.ramTotal ? Math.round((sb.ramUsed ?? 0) / sb.ramTotal * 100) : 0 })
|
|
997
|
+
] }) : isProvisioning ? /* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-2 text-primary italic text-[10px] font-bold", children: [
|
|
998
|
+
/* @__PURE__ */ jsx10(RefreshCw, { className: "h-3.5 w-3.5 animate-spin" }),
|
|
904
999
|
sb.provisioningMessage ?? "Allocating nodes..."
|
|
905
|
-
] }) : isHibernating ? /* @__PURE__ */
|
|
906
|
-
/* @__PURE__ */
|
|
907
|
-
/* @__PURE__ */
|
|
1000
|
+
] }) : isHibernating ? /* @__PURE__ */ jsxs9("div", { className: "space-y-3 w-48 opacity-30", children: [
|
|
1001
|
+
/* @__PURE__ */ jsx10(MiniMeter, { label: "CPU", percent: 0 }),
|
|
1002
|
+
/* @__PURE__ */ jsx10(MiniMeter, { label: "RAM", percent: 0 })
|
|
908
1003
|
] }) : null }),
|
|
909
|
-
/* @__PURE__ */
|
|
910
|
-
isActive && /* @__PURE__ */
|
|
911
|
-
/* @__PURE__ */
|
|
1004
|
+
/* @__PURE__ */ jsx10("td", { className: "px-6 py-5 text-right", children: /* @__PURE__ */ jsxs9("div", { className: "flex items-center justify-end gap-1", children: [
|
|
1005
|
+
isActive && /* @__PURE__ */ jsxs9(Fragment5, { children: [
|
|
1006
|
+
/* @__PURE__ */ jsx10("button", { type: "button", onClick: (e) => {
|
|
912
1007
|
stopRowClick(e);
|
|
913
1008
|
onOpenIDE?.(sb.id);
|
|
914
|
-
}, className: "p-2 rounded-lg hover:bg-muted text-muted-foreground hover:text-foreground transition-all active:scale-90", title: "Open IDE", children: /* @__PURE__ */
|
|
915
|
-
/* @__PURE__ */
|
|
1009
|
+
}, className: "p-2 rounded-lg hover:bg-muted text-muted-foreground hover:text-foreground transition-all active:scale-90", title: "Open IDE", children: /* @__PURE__ */ jsx10(Code22, { className: "h-4 w-4" }) }),
|
|
1010
|
+
/* @__PURE__ */ jsx10("button", { type: "button", onClick: (e) => {
|
|
916
1011
|
stopRowClick(e);
|
|
917
1012
|
onOpenTerminal?.(sb.id);
|
|
918
|
-
}, className: "p-2 rounded-lg hover:bg-muted text-muted-foreground hover:text-foreground transition-all active:scale-90", title: "Terminal", children: /* @__PURE__ */
|
|
919
|
-
/* @__PURE__ */
|
|
1013
|
+
}, className: "p-2 rounded-lg hover:bg-muted text-muted-foreground hover:text-foreground transition-all active:scale-90", title: "Terminal", children: /* @__PURE__ */ jsx10(Terminal2, { className: "h-4 w-4" }) }),
|
|
1014
|
+
/* @__PURE__ */ jsx10("button", { type: "button", onClick: (e) => {
|
|
920
1015
|
stopRowClick(e);
|
|
921
1016
|
onSSH?.(sb.id);
|
|
922
|
-
}, className: "p-2 rounded-lg hover:bg-muted text-muted-foreground hover:text-foreground transition-all active:scale-90", title: "SSH", children: /* @__PURE__ */
|
|
1017
|
+
}, className: "p-2 rounded-lg hover:bg-muted text-muted-foreground hover:text-foreground transition-all active:scale-90", title: "SSH", children: /* @__PURE__ */ jsx10(Key, { className: "h-4 w-4" }) })
|
|
923
1018
|
] }),
|
|
924
|
-
resumeHandler && /* @__PURE__ */
|
|
1019
|
+
resumeHandler && /* @__PURE__ */ jsxs9(
|
|
925
1020
|
"button",
|
|
926
1021
|
{
|
|
927
1022
|
type: "button",
|
|
@@ -932,7 +1027,7 @@ function SandboxTable({
|
|
|
932
1027
|
className: "inline-flex items-center gap-1.5 px-3 py-1.5 rounded-lg border border-border text-primary text-[10px] font-bold uppercase tracking-wider hover:bg-[var(--accent-surface-soft)] active:scale-95 transition-all",
|
|
933
1028
|
title: resumeLabel,
|
|
934
1029
|
children: [
|
|
935
|
-
/* @__PURE__ */
|
|
1030
|
+
/* @__PURE__ */ jsx10(Play2, { className: "h-3 w-3" }),
|
|
936
1031
|
resumeLabel
|
|
937
1032
|
]
|
|
938
1033
|
}
|
|
@@ -946,55 +1041,55 @@ function SandboxTable({
|
|
|
946
1041
|
if (isActive) {
|
|
947
1042
|
const lifecycle = [];
|
|
948
1043
|
if (onStop) lifecycle.push(
|
|
949
|
-
/* @__PURE__ */
|
|
950
|
-
/* @__PURE__ */
|
|
1044
|
+
/* @__PURE__ */ jsxs9(DropdownMenuItem3, { onClick: runItem(onStop), children: [
|
|
1045
|
+
/* @__PURE__ */ jsx10(PowerOff2, { className: "mr-2 h-4 w-4" }),
|
|
951
1046
|
" Stop Sandbox"
|
|
952
1047
|
] }, "stop")
|
|
953
1048
|
);
|
|
954
1049
|
if (onKeepAlive) lifecycle.push(
|
|
955
|
-
/* @__PURE__ */
|
|
956
|
-
/* @__PURE__ */
|
|
1050
|
+
/* @__PURE__ */ jsxs9(DropdownMenuItem3, { onClick: runItem(onKeepAlive), children: [
|
|
1051
|
+
/* @__PURE__ */ jsx10(Clock2, { className: "mr-2 h-4 w-4" }),
|
|
957
1052
|
" Keep Alive"
|
|
958
1053
|
] }, "keep-alive")
|
|
959
1054
|
);
|
|
960
1055
|
if (lifecycle.length) overflowSections.push(lifecycle);
|
|
961
1056
|
const observability = [];
|
|
962
1057
|
if (onUsage) observability.push(
|
|
963
|
-
/* @__PURE__ */
|
|
964
|
-
/* @__PURE__ */
|
|
1058
|
+
/* @__PURE__ */ jsxs9(DropdownMenuItem3, { onClick: runItem(onUsage), children: [
|
|
1059
|
+
/* @__PURE__ */ jsx10(BarChart22, { className: "mr-2 h-4 w-4" }),
|
|
965
1060
|
" View Usage"
|
|
966
1061
|
] }, "usage")
|
|
967
1062
|
);
|
|
968
1063
|
if (onHealth) observability.push(
|
|
969
|
-
/* @__PURE__ */
|
|
970
|
-
/* @__PURE__ */
|
|
1064
|
+
/* @__PURE__ */ jsxs9(DropdownMenuItem3, { onClick: runItem(onHealth), children: [
|
|
1065
|
+
/* @__PURE__ */ jsx10(Activity2, { className: "mr-2 h-4 w-4" }),
|
|
971
1066
|
" Health Check"
|
|
972
1067
|
] }, "health")
|
|
973
1068
|
);
|
|
974
1069
|
if (observability.length) overflowSections.push(observability);
|
|
975
1070
|
if (onFork) overflowSections.push([
|
|
976
|
-
/* @__PURE__ */
|
|
977
|
-
/* @__PURE__ */
|
|
1071
|
+
/* @__PURE__ */ jsxs9(DropdownMenuItem3, { onClick: runItem(onFork), children: [
|
|
1072
|
+
/* @__PURE__ */ jsx10(Copy2, { className: "mr-2 h-4 w-4" }),
|
|
978
1073
|
" Fork Sandbox"
|
|
979
1074
|
] }, "fork")
|
|
980
1075
|
]);
|
|
981
1076
|
} else if (isResumable(sb.status)) {
|
|
982
1077
|
if (onFork) overflowSections.push([
|
|
983
|
-
/* @__PURE__ */
|
|
984
|
-
/* @__PURE__ */
|
|
1078
|
+
/* @__PURE__ */ jsxs9(DropdownMenuItem3, { onClick: runItem(onFork), children: [
|
|
1079
|
+
/* @__PURE__ */ jsx10(Copy2, { className: "mr-2 h-4 w-4" }),
|
|
985
1080
|
" Fork Sandbox"
|
|
986
1081
|
] }, "fork")
|
|
987
1082
|
]);
|
|
988
1083
|
}
|
|
989
1084
|
if (onMore) overflowSections.push([
|
|
990
|
-
/* @__PURE__ */
|
|
991
|
-
/* @__PURE__ */
|
|
1085
|
+
/* @__PURE__ */ jsxs9(DropdownMenuItem3, { onClick: runItem(onMore), children: [
|
|
1086
|
+
/* @__PURE__ */ jsx10(ExternalLink, { className: "mr-2 h-4 w-4" }),
|
|
992
1087
|
" View Details"
|
|
993
1088
|
] }, "view-details")
|
|
994
1089
|
]);
|
|
995
1090
|
if (overflowSections.length === 0) return null;
|
|
996
|
-
return /* @__PURE__ */
|
|
997
|
-
/* @__PURE__ */
|
|
1091
|
+
return /* @__PURE__ */ jsxs9(DropdownMenu3, { children: [
|
|
1092
|
+
/* @__PURE__ */ jsx10(DropdownMenuTrigger3, { asChild: true, children: /* @__PURE__ */ jsx10(
|
|
998
1093
|
"button",
|
|
999
1094
|
{
|
|
1000
1095
|
type: "button",
|
|
@@ -1002,19 +1097,19 @@ function SandboxTable({
|
|
|
1002
1097
|
className: "p-2 rounded-lg hover:bg-muted text-muted-foreground hover:text-foreground transition-all active:scale-90 outline-none",
|
|
1003
1098
|
"aria-label": "More actions",
|
|
1004
1099
|
title: "More actions",
|
|
1005
|
-
children: /* @__PURE__ */
|
|
1100
|
+
children: /* @__PURE__ */ jsx10(MoreVertical2, { className: "h-4 w-4" })
|
|
1006
1101
|
}
|
|
1007
1102
|
) }),
|
|
1008
|
-
/* @__PURE__ */
|
|
1009
|
-
sectionIdx > 0 && /* @__PURE__ */
|
|
1103
|
+
/* @__PURE__ */ jsx10(DropdownMenuContent3, { align: "end", className: "min-w-[180px]", children: overflowSections.map((section, sectionIdx) => /* @__PURE__ */ jsxs9(React5.Fragment, { children: [
|
|
1104
|
+
sectionIdx > 0 && /* @__PURE__ */ jsx10(DropdownMenuSeparator3, {}),
|
|
1010
1105
|
section
|
|
1011
1106
|
] }, sectionIdx)) })
|
|
1012
1107
|
] });
|
|
1013
1108
|
})(),
|
|
1014
|
-
onDelete && canAdminSandbox(sb) && /* @__PURE__ */
|
|
1109
|
+
onDelete && canAdminSandbox(sb) && /* @__PURE__ */ jsx10("button", { type: "button", onClick: (e) => {
|
|
1015
1110
|
stopRowClick(e);
|
|
1016
1111
|
onDelete(sb.id);
|
|
1017
|
-
}, className: "p-2 rounded-lg hover:bg-[var(--surface-danger-bg)] text-muted-foreground hover:text-[var(--surface-danger-text)] transition-all active:scale-90", title: "Delete", children: /* @__PURE__ */
|
|
1112
|
+
}, className: "p-2 rounded-lg hover:bg-[var(--surface-danger-bg)] text-muted-foreground hover:text-[var(--surface-danger-text)] transition-all active:scale-90", title: "Delete", children: /* @__PURE__ */ jsx10(Trash22, { className: "h-4 w-4" }) })
|
|
1018
1113
|
] }) })
|
|
1019
1114
|
]
|
|
1020
1115
|
},
|
|
@@ -1023,17 +1118,17 @@ function SandboxTable({
|
|
|
1023
1118
|
);
|
|
1024
1119
|
}) })
|
|
1025
1120
|
] }) }) }),
|
|
1026
|
-
totalPages > 1 && /* @__PURE__ */
|
|
1027
|
-
/* @__PURE__ */
|
|
1121
|
+
totalPages > 1 && /* @__PURE__ */ jsxs9("div", { className: "mt-6 flex flex-col md:flex-row justify-between items-center text-muted-foreground text-xs font-medium gap-4", children: [
|
|
1122
|
+
/* @__PURE__ */ jsxs9("p", { children: [
|
|
1028
1123
|
"Showing ",
|
|
1029
1124
|
sandboxes.length,
|
|
1030
1125
|
" of ",
|
|
1031
1126
|
totalCount,
|
|
1032
1127
|
" active sandboxes"
|
|
1033
1128
|
] }),
|
|
1034
|
-
/* @__PURE__ */
|
|
1035
|
-
/* @__PURE__ */
|
|
1036
|
-
Array.from({ length: Math.min(totalPages, 5) }, (_, i) => i + 1).map((p) => /* @__PURE__ */
|
|
1129
|
+
/* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-2", children: [
|
|
1130
|
+
/* @__PURE__ */ jsx10("button", { type: "button", onClick: () => onPageChange?.(page - 1), disabled: page <= 1, className: "p-2 rounded-lg border border-border hover:bg-muted/50 transition-colors disabled:opacity-30", children: /* @__PURE__ */ jsx10(ChevronLeft, { className: "h-4 w-4" }) }),
|
|
1131
|
+
Array.from({ length: Math.min(totalPages, 5) }, (_, i) => i + 1).map((p) => /* @__PURE__ */ jsx10(
|
|
1037
1132
|
"button",
|
|
1038
1133
|
{
|
|
1039
1134
|
type: "button",
|
|
@@ -1046,7 +1141,7 @@ function SandboxTable({
|
|
|
1046
1141
|
},
|
|
1047
1142
|
p
|
|
1048
1143
|
)),
|
|
1049
|
-
/* @__PURE__ */
|
|
1144
|
+
/* @__PURE__ */ jsx10("button", { type: "button", onClick: () => onPageChange?.(page + 1), disabled: page >= totalPages, className: "p-2 rounded-lg border border-border hover:bg-muted/50 transition-colors disabled:opacity-30", children: /* @__PURE__ */ jsx10(ChevronRight, { className: "h-4 w-4" }) })
|
|
1050
1145
|
] })
|
|
1051
1146
|
] })
|
|
1052
1147
|
] });
|
|
@@ -1054,51 +1149,51 @@ function SandboxTable({
|
|
|
1054
1149
|
|
|
1055
1150
|
// src/dashboard/invoice-table.tsx
|
|
1056
1151
|
import { Download, FileText } from "lucide-react";
|
|
1057
|
-
import { jsx as
|
|
1152
|
+
import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1058
1153
|
var statusStyle = {
|
|
1059
1154
|
paid: "bg-[var(--accent-surface-soft)] text-primary border border-border",
|
|
1060
1155
|
pending: "bg-[var(--surface-warning-bg)] text-[var(--surface-warning-text)] border border-[var(--surface-warning-border)]",
|
|
1061
1156
|
failed: "bg-[var(--surface-danger-bg)] text-[var(--surface-danger-text)] border border-[var(--surface-danger-border)]"
|
|
1062
1157
|
};
|
|
1063
1158
|
function InvoiceTable({ invoices, onExportAll, onLoadMore, onViewInvoice, hasMore, className }) {
|
|
1064
|
-
return /* @__PURE__ */
|
|
1065
|
-
/* @__PURE__ */
|
|
1066
|
-
/* @__PURE__ */
|
|
1067
|
-
onExportAll && /* @__PURE__ */
|
|
1068
|
-
/* @__PURE__ */
|
|
1159
|
+
return /* @__PURE__ */ jsxs10("section", { className, children: [
|
|
1160
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex justify-between items-center mb-6 px-2", children: [
|
|
1161
|
+
/* @__PURE__ */ jsx11("h2", { className: "text-2xl font-bold text-foreground tracking-tight", children: "Invoice History" }),
|
|
1162
|
+
onExportAll && /* @__PURE__ */ jsxs10("button", { type: "button", onClick: onExportAll, className: "text-[10px] font-mono text-primary uppercase tracking-widest flex items-center gap-2 hover:underline", children: [
|
|
1163
|
+
/* @__PURE__ */ jsx11(Download, { className: "h-3.5 w-3.5" }),
|
|
1069
1164
|
"Export All"
|
|
1070
1165
|
] })
|
|
1071
1166
|
] }),
|
|
1072
|
-
/* @__PURE__ */
|
|
1073
|
-
/* @__PURE__ */
|
|
1074
|
-
/* @__PURE__ */
|
|
1075
|
-
/* @__PURE__ */
|
|
1076
|
-
/* @__PURE__ */
|
|
1077
|
-
/* @__PURE__ */
|
|
1078
|
-
/* @__PURE__ */
|
|
1167
|
+
/* @__PURE__ */ jsx11("div", { className: "bg-card rounded-xl overflow-hidden border border-border", children: /* @__PURE__ */ jsxs10("table", { className: "w-full text-left border-collapse", children: [
|
|
1168
|
+
/* @__PURE__ */ jsx11("thead", { children: /* @__PURE__ */ jsxs10("tr", { className: "bg-background border-b border-border", children: [
|
|
1169
|
+
/* @__PURE__ */ jsx11("th", { className: "px-6 py-4 font-mono text-[10px] text-muted-foreground uppercase tracking-widest", children: "Invoice ID" }),
|
|
1170
|
+
/* @__PURE__ */ jsx11("th", { className: "px-6 py-4 font-mono text-[10px] text-muted-foreground uppercase tracking-widest", children: "Date" }),
|
|
1171
|
+
/* @__PURE__ */ jsx11("th", { className: "px-6 py-4 font-mono text-[10px] text-muted-foreground uppercase tracking-widest", children: "Amount" }),
|
|
1172
|
+
/* @__PURE__ */ jsx11("th", { className: "px-6 py-4 font-mono text-[10px] text-muted-foreground uppercase tracking-widest", children: "Status" }),
|
|
1173
|
+
/* @__PURE__ */ jsx11("th", { className: "px-6 py-4 font-mono text-[10px] text-muted-foreground uppercase tracking-widest text-right", children: "Action" })
|
|
1079
1174
|
] }) }),
|
|
1080
|
-
/* @__PURE__ */
|
|
1081
|
-
/* @__PURE__ */
|
|
1082
|
-
/* @__PURE__ */
|
|
1083
|
-
/* @__PURE__ */
|
|
1175
|
+
/* @__PURE__ */ jsx11("tbody", { className: "divide-y divide-border", children: invoices.map((inv) => /* @__PURE__ */ jsxs10("tr", { className: "hover:bg-muted/50 transition-colors", children: [
|
|
1176
|
+
/* @__PURE__ */ jsx11("td", { className: "px-6 py-5 font-mono text-xs text-foreground", children: inv.id }),
|
|
1177
|
+
/* @__PURE__ */ jsx11("td", { className: "px-6 py-5 text-sm text-foreground", children: inv.date }),
|
|
1178
|
+
/* @__PURE__ */ jsxs10("td", { className: "px-6 py-5 text-sm font-bold text-foreground", children: [
|
|
1084
1179
|
"$",
|
|
1085
1180
|
inv.amount.toFixed(2)
|
|
1086
1181
|
] }),
|
|
1087
|
-
/* @__PURE__ */
|
|
1088
|
-
/* @__PURE__ */
|
|
1182
|
+
/* @__PURE__ */ jsx11("td", { className: "px-6 py-5", children: /* @__PURE__ */ jsx11("span", { className: cn("px-2 py-1 text-[10px] font-mono rounded uppercase", statusStyle[inv.status] ?? statusStyle.paid), children: inv.status }) }),
|
|
1183
|
+
/* @__PURE__ */ jsx11("td", { className: "px-6 py-5 text-right", children: /* @__PURE__ */ jsx11("button", { type: "button", onClick: () => onViewInvoice?.(inv.id), className: "text-muted-foreground hover:text-foreground transition-colors", children: /* @__PURE__ */ jsx11(FileText, { className: "h-4 w-4" }) }) })
|
|
1089
1184
|
] }, inv.id)) })
|
|
1090
1185
|
] }) }),
|
|
1091
|
-
hasMore && onLoadMore && /* @__PURE__ */
|
|
1186
|
+
hasMore && onLoadMore && /* @__PURE__ */ jsx11("div", { className: "mt-6 flex justify-center", children: /* @__PURE__ */ jsx11("button", { type: "button", onClick: onLoadMore, className: "px-8 py-2 text-[10px] font-mono text-muted-foreground border border-border rounded-full hover:bg-muted/50 transition-colors uppercase tracking-widest", children: "Load More History" }) })
|
|
1092
1187
|
] });
|
|
1093
1188
|
}
|
|
1094
1189
|
|
|
1095
1190
|
// src/dashboard/plan-cards.tsx
|
|
1096
1191
|
import { Check } from "lucide-react";
|
|
1097
|
-
import { jsx as
|
|
1192
|
+
import { jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
1098
1193
|
function PlanCards({ plans, className }) {
|
|
1099
|
-
return /* @__PURE__ */
|
|
1100
|
-
/* @__PURE__ */
|
|
1101
|
-
/* @__PURE__ */
|
|
1194
|
+
return /* @__PURE__ */ jsxs11("section", { className, children: [
|
|
1195
|
+
/* @__PURE__ */ jsx12("h2", { className: "text-2xl font-bold text-foreground tracking-tight mb-5 px-2", children: "Subscription Plans" }),
|
|
1196
|
+
/* @__PURE__ */ jsx12("div", { className: "grid grid-cols-1 md:grid-cols-3 gap-6", children: plans.map((plan) => /* @__PURE__ */ jsxs11(
|
|
1102
1197
|
"div",
|
|
1103
1198
|
{
|
|
1104
1199
|
className: cn(
|
|
@@ -1106,23 +1201,23 @@ function PlanCards({ plans, className }) {
|
|
|
1106
1201
|
plan.popular ? "bg-muted/50 border-border" : "bg-card border-border hover:bg-muted/50 hover:border-primary/20"
|
|
1107
1202
|
),
|
|
1108
1203
|
children: [
|
|
1109
|
-
plan.popular && /* @__PURE__ */
|
|
1110
|
-
/* @__PURE__ */
|
|
1111
|
-
/* @__PURE__ */
|
|
1112
|
-
/* @__PURE__ */
|
|
1204
|
+
plan.popular && /* @__PURE__ */ jsx12("div", { className: "absolute top-0 right-0 bg-[var(--accent-surface-soft)] border-l border-b border-border px-4 py-1 text-[10px] font-bold text-[var(--accent-text)] uppercase tracking-widest rounded-bl-lg", children: "Popular" }),
|
|
1205
|
+
/* @__PURE__ */ jsxs11("div", { className: "mb-4", children: [
|
|
1206
|
+
/* @__PURE__ */ jsx12("div", { className: cn("text-xs font-mono uppercase tracking-widest mb-2", plan.popular ? "text-primary" : "text-muted-foreground"), children: plan.name }),
|
|
1207
|
+
/* @__PURE__ */ jsxs11("div", { className: "text-3xl font-bold text-foreground", children: [
|
|
1113
1208
|
"$",
|
|
1114
1209
|
plan.price,
|
|
1115
|
-
/* @__PURE__ */
|
|
1210
|
+
/* @__PURE__ */ jsxs11("span", { className: "text-sm font-normal text-muted-foreground tracking-normal", children: [
|
|
1116
1211
|
"/",
|
|
1117
1212
|
plan.period ?? "mo"
|
|
1118
1213
|
] })
|
|
1119
1214
|
] })
|
|
1120
1215
|
] }),
|
|
1121
|
-
/* @__PURE__ */
|
|
1122
|
-
/* @__PURE__ */
|
|
1216
|
+
/* @__PURE__ */ jsx12("ul", { className: "space-y-2 mb-5 text-sm text-muted-foreground", children: plan.features.map((f, i) => /* @__PURE__ */ jsxs11("li", { className: "flex items-center gap-2", children: [
|
|
1217
|
+
/* @__PURE__ */ jsx12(Check, { className: "h-3.5 w-3.5 text-primary shrink-0" }),
|
|
1123
1218
|
f.text
|
|
1124
1219
|
] }, i)) }),
|
|
1125
|
-
/* @__PURE__ */
|
|
1220
|
+
/* @__PURE__ */ jsx12(
|
|
1126
1221
|
"button",
|
|
1127
1222
|
{
|
|
1128
1223
|
type: "button",
|
|
@@ -1142,29 +1237,29 @@ function PlanCards({ plans, className }) {
|
|
|
1142
1237
|
}
|
|
1143
1238
|
|
|
1144
1239
|
// src/dashboard/dashboard-layout.tsx
|
|
1145
|
-
import * as
|
|
1240
|
+
import * as React6 from "react";
|
|
1146
1241
|
import { Plus as Plus2, Bell } from "lucide-react";
|
|
1147
|
-
import { Fragment as Fragment7, jsx as
|
|
1242
|
+
import { Fragment as Fragment7, jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
1148
1243
|
function SettingsIconSmall({ className }) {
|
|
1149
|
-
return /* @__PURE__ */
|
|
1150
|
-
/* @__PURE__ */
|
|
1151
|
-
/* @__PURE__ */
|
|
1152
|
-
/* @__PURE__ */
|
|
1244
|
+
return /* @__PURE__ */ jsxs12("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, children: [
|
|
1245
|
+
/* @__PURE__ */ jsx13("title", { children: "Settings" }),
|
|
1246
|
+
/* @__PURE__ */ jsx13("path", { d: "M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z" }),
|
|
1247
|
+
/* @__PURE__ */ jsx13("circle", { cx: "12", cy: "12", r: "3" })
|
|
1153
1248
|
] });
|
|
1154
1249
|
}
|
|
1155
1250
|
function MenuIcon({ className }) {
|
|
1156
|
-
return /* @__PURE__ */
|
|
1157
|
-
/* @__PURE__ */
|
|
1158
|
-
/* @__PURE__ */
|
|
1159
|
-
/* @__PURE__ */
|
|
1160
|
-
/* @__PURE__ */
|
|
1251
|
+
return /* @__PURE__ */ jsxs12("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, children: [
|
|
1252
|
+
/* @__PURE__ */ jsx13("title", { children: "Menu icon" }),
|
|
1253
|
+
/* @__PURE__ */ jsx13("line", { x1: "4", x2: "20", y1: "12", y2: "12" }),
|
|
1254
|
+
/* @__PURE__ */ jsx13("line", { x1: "4", x2: "20", y1: "6", y2: "6" }),
|
|
1255
|
+
/* @__PURE__ */ jsx13("line", { x1: "4", x2: "20", y1: "18", y2: "18" })
|
|
1161
1256
|
] });
|
|
1162
1257
|
}
|
|
1163
1258
|
function XIcon({ className }) {
|
|
1164
|
-
return /* @__PURE__ */
|
|
1165
|
-
/* @__PURE__ */
|
|
1166
|
-
/* @__PURE__ */
|
|
1167
|
-
/* @__PURE__ */
|
|
1259
|
+
return /* @__PURE__ */ jsxs12("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, children: [
|
|
1260
|
+
/* @__PURE__ */ jsx13("title", { children: "Close icon" }),
|
|
1261
|
+
/* @__PURE__ */ jsx13("path", { d: "M18 6 6 18" }),
|
|
1262
|
+
/* @__PURE__ */ jsx13("path", { d: "m6 6 12 12" })
|
|
1168
1263
|
] });
|
|
1169
1264
|
}
|
|
1170
1265
|
function formatNotifDate(raw) {
|
|
@@ -1178,7 +1273,7 @@ function DefaultLink2({
|
|
|
1178
1273
|
children,
|
|
1179
1274
|
...rest
|
|
1180
1275
|
}) {
|
|
1181
|
-
return /* @__PURE__ */
|
|
1276
|
+
return /* @__PURE__ */ jsx13("a", { href: href ?? to, className, ...rest, children });
|
|
1182
1277
|
}
|
|
1183
1278
|
function DashboardLayoutInner({
|
|
1184
1279
|
children,
|
|
@@ -1205,10 +1300,10 @@ function DashboardLayoutInner({
|
|
|
1205
1300
|
notifications: notifData
|
|
1206
1301
|
}) {
|
|
1207
1302
|
const Link = LinkComponent;
|
|
1208
|
-
const [mobileMenuOpen, setMobileMenuOpen] =
|
|
1209
|
-
const [notificationsOpen, setNotificationsOpen] =
|
|
1210
|
-
const notifRef =
|
|
1211
|
-
|
|
1303
|
+
const [mobileMenuOpen, setMobileMenuOpen] = React6.useState(false);
|
|
1304
|
+
const [notificationsOpen, setNotificationsOpen] = React6.useState(false);
|
|
1305
|
+
const notifRef = React6.useRef(null);
|
|
1306
|
+
React6.useEffect(() => {
|
|
1212
1307
|
if (!notificationsOpen) return;
|
|
1213
1308
|
const handler = (e) => {
|
|
1214
1309
|
if (notifRef.current && !notifRef.current.contains(e.target)) {
|
|
@@ -1226,23 +1321,23 @@ function DashboardLayoutInner({
|
|
|
1226
1321
|
};
|
|
1227
1322
|
}, [notificationsOpen]);
|
|
1228
1323
|
const { contentMargin, hidden, mode, hasPanels, panelOpen } = useSidebar();
|
|
1229
|
-
const modeSet =
|
|
1230
|
-
const sidebarUser =
|
|
1324
|
+
const modeSet = React6.useMemo(() => new Set(modeItems), [modeItems]);
|
|
1325
|
+
const sidebarUser = React6.useMemo(
|
|
1231
1326
|
() => user ? { email: user.email, name: user.name, tier: user.tier, avatarUrl: user.avatarUrl } : void 0,
|
|
1232
1327
|
[user?.email, user?.name, user?.tier, user?.avatarUrl]
|
|
1233
1328
|
);
|
|
1234
1329
|
const activePanel = panels.find((p) => p.mode === mode);
|
|
1235
|
-
const buildSidebarContent =
|
|
1236
|
-
(showLabels) => /* @__PURE__ */
|
|
1237
|
-
/* @__PURE__ */
|
|
1238
|
-
/* @__PURE__ */
|
|
1239
|
-
/* @__PURE__ */
|
|
1330
|
+
const buildSidebarContent = React6.useCallback(
|
|
1331
|
+
(showLabels) => /* @__PURE__ */ jsxs12(Fragment7, { children: [
|
|
1332
|
+
/* @__PURE__ */ jsxs12(SidebarRail, { wide: showLabels, children: [
|
|
1333
|
+
/* @__PURE__ */ jsx13(SidebarRailHeader, { children: /* @__PURE__ */ jsx13(Link, { href: "/", to: "/", className: "p-1 rounded-md transition-colors hover:bg-muted/50", children: /* @__PURE__ */ jsx13(Logo, { variant, size: "sm", iconOnly: true }) }) }),
|
|
1334
|
+
/* @__PURE__ */ jsx13(SidebarRailNav, { children: navItems.map((item, i) => {
|
|
1240
1335
|
const isMode = modeSet.has(item.id);
|
|
1241
1336
|
const prevIsMode = i > 0 && modeSet.has(navItems[i - 1].id);
|
|
1242
1337
|
const showSep = i > 0 && isMode && !prevIsMode;
|
|
1243
|
-
return /* @__PURE__ */
|
|
1244
|
-
showSep && /* @__PURE__ */
|
|
1245
|
-
isMode ? /* @__PURE__ */
|
|
1338
|
+
return /* @__PURE__ */ jsxs12(React6.Fragment, { children: [
|
|
1339
|
+
showSep && /* @__PURE__ */ jsx13(RailSeparator, {}),
|
|
1340
|
+
isMode ? /* @__PURE__ */ jsx13(
|
|
1246
1341
|
RailModeButton,
|
|
1247
1342
|
{
|
|
1248
1343
|
mode: item.id,
|
|
@@ -1251,7 +1346,7 @@ function DashboardLayoutInner({
|
|
|
1251
1346
|
badge: item.badge,
|
|
1252
1347
|
showLabel: showLabels
|
|
1253
1348
|
}
|
|
1254
|
-
) : /* @__PURE__ */
|
|
1349
|
+
) : /* @__PURE__ */ jsx13(Link, { href: item.href, to: item.href, children: /* @__PURE__ */ jsx13(
|
|
1255
1350
|
RailButton,
|
|
1256
1351
|
{
|
|
1257
1352
|
icon: item.icon,
|
|
@@ -1262,11 +1357,11 @@ function DashboardLayoutInner({
|
|
|
1262
1357
|
) })
|
|
1263
1358
|
] }, item.id);
|
|
1264
1359
|
}) }),
|
|
1265
|
-
/* @__PURE__ */
|
|
1266
|
-
onSettingsClick ? /* @__PURE__ */
|
|
1360
|
+
/* @__PURE__ */ jsxs12(SidebarRailFooter, { children: [
|
|
1361
|
+
onSettingsClick ? /* @__PURE__ */ jsx13(RailButton, { icon: SettingsIconSmall, label: "Settings", onClick: onSettingsClick, showLabel: showLabels }) : /* @__PURE__ */ jsx13(Link, { href: settingsHref, to: settingsHref, children: /* @__PURE__ */ jsx13(RailButton, { icon: SettingsIconSmall, label: "Settings", showLabel: showLabels }) }),
|
|
1267
1362
|
railFooter,
|
|
1268
|
-
/* @__PURE__ */
|
|
1269
|
-
/* @__PURE__ */
|
|
1363
|
+
/* @__PURE__ */ jsx13(RailSeparator, {}),
|
|
1364
|
+
/* @__PURE__ */ jsx13(
|
|
1270
1365
|
ProfileAvatar,
|
|
1271
1366
|
{
|
|
1272
1367
|
user: sidebarUser,
|
|
@@ -1280,9 +1375,9 @@ function DashboardLayoutInner({
|
|
|
1280
1375
|
)
|
|
1281
1376
|
] })
|
|
1282
1377
|
] }),
|
|
1283
|
-
panels.length > 0 && /* @__PURE__ */
|
|
1284
|
-
/* @__PURE__ */
|
|
1285
|
-
/* @__PURE__ */
|
|
1378
|
+
panels.length > 0 && /* @__PURE__ */ jsxs12(SidebarPanel, { children: [
|
|
1379
|
+
/* @__PURE__ */ jsx13(SidebarPanelHeader, { title: activePanel?.title ?? mode }),
|
|
1380
|
+
/* @__PURE__ */ jsx13(SidebarPanelContent, { children: activePanel?.content })
|
|
1286
1381
|
] })
|
|
1287
1382
|
] }),
|
|
1288
1383
|
// biome-ignore lint/correctness/useExhaustiveDependencies: intentional — only the inputs that actually affect the sidebar tree
|
|
@@ -1305,10 +1400,10 @@ function DashboardLayoutInner({
|
|
|
1305
1400
|
mode
|
|
1306
1401
|
]
|
|
1307
1402
|
);
|
|
1308
|
-
const sidebarContent =
|
|
1309
|
-
const mobileSidebarContent =
|
|
1310
|
-
return /* @__PURE__ */
|
|
1311
|
-
/* @__PURE__ */
|
|
1403
|
+
const sidebarContent = React6.useMemo(() => buildSidebarContent(false), [buildSidebarContent]);
|
|
1404
|
+
const mobileSidebarContent = React6.useMemo(() => buildSidebarContent(true), [buildSidebarContent]);
|
|
1405
|
+
return /* @__PURE__ */ jsxs12("div", { className: cn("min-h-screen bg-background text-foreground", className), children: [
|
|
1406
|
+
/* @__PURE__ */ jsxs12(
|
|
1312
1407
|
"nav",
|
|
1313
1408
|
{
|
|
1314
1409
|
className: "fixed top-0 z-50 bg-card border-b border-border flex justify-between items-center px-8 h-14 font-sans text-[13px] tracking-tight transition-[left,width] duration-200 ease-in-out",
|
|
@@ -1317,9 +1412,9 @@ function DashboardLayoutInner({
|
|
|
1317
1412
|
width: hidden ? "100%" : `calc(100% - ${contentMargin}px)`
|
|
1318
1413
|
},
|
|
1319
1414
|
children: [
|
|
1320
|
-
/* @__PURE__ */
|
|
1321
|
-
/* @__PURE__ */
|
|
1322
|
-
topNavLinks && topNavLinks.length > 0 && /* @__PURE__ */
|
|
1415
|
+
/* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-8", children: [
|
|
1416
|
+
/* @__PURE__ */ jsx13(Link, { href: "/", to: "/", className: "lg:hidden flex items-center p-1 rounded-md hover:bg-muted/50 transition-colors", children: /* @__PURE__ */ jsx13(Logo, { variant, size: "sm", iconOnly: true }) }),
|
|
1417
|
+
topNavLinks && topNavLinks.length > 0 && /* @__PURE__ */ jsx13("div", { className: "hidden md:flex gap-6", children: topNavLinks.map((link) => /* @__PURE__ */ jsx13(
|
|
1323
1418
|
Link,
|
|
1324
1419
|
{
|
|
1325
1420
|
href: link.href,
|
|
@@ -1333,21 +1428,21 @@ function DashboardLayoutInner({
|
|
|
1333
1428
|
link.href
|
|
1334
1429
|
)) })
|
|
1335
1430
|
] }),
|
|
1336
|
-
/* @__PURE__ */
|
|
1337
|
-
onNewSandbox && /* @__PURE__ */
|
|
1431
|
+
/* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-4", children: [
|
|
1432
|
+
onNewSandbox && /* @__PURE__ */ jsxs12(
|
|
1338
1433
|
"button",
|
|
1339
1434
|
{
|
|
1340
1435
|
type: "button",
|
|
1341
1436
|
onClick: onNewSandbox,
|
|
1342
1437
|
className: "hidden md:flex items-center gap-2 bg-[var(--btn-primary-bg)] border border-[var(--border-accent)] text-[var(--btn-primary-text)] px-4 py-2 rounded-lg font-bold hover:bg-[var(--btn-primary-hover)] transition-all active:scale-95 text-xs",
|
|
1343
1438
|
children: [
|
|
1344
|
-
/* @__PURE__ */
|
|
1439
|
+
/* @__PURE__ */ jsx13(Plus2, { className: "h-3.5 w-3.5" }),
|
|
1345
1440
|
"New Sandbox"
|
|
1346
1441
|
]
|
|
1347
1442
|
}
|
|
1348
1443
|
),
|
|
1349
|
-
/* @__PURE__ */
|
|
1350
|
-
/* @__PURE__ */
|
|
1444
|
+
/* @__PURE__ */ jsxs12("div", { className: "relative", ref: notifRef, children: [
|
|
1445
|
+
/* @__PURE__ */ jsxs12(
|
|
1351
1446
|
"button",
|
|
1352
1447
|
{
|
|
1353
1448
|
type: "button",
|
|
@@ -1356,15 +1451,15 @@ function DashboardLayoutInner({
|
|
|
1356
1451
|
"aria-label": "Notifications",
|
|
1357
1452
|
"aria-expanded": notificationsOpen,
|
|
1358
1453
|
children: [
|
|
1359
|
-
/* @__PURE__ */
|
|
1360
|
-
(notifData?.unreadCount ?? 0) > 0 && /* @__PURE__ */
|
|
1454
|
+
/* @__PURE__ */ jsx13(Bell, { className: "h-4 w-4" }),
|
|
1455
|
+
(notifData?.unreadCount ?? 0) > 0 && /* @__PURE__ */ jsx13("span", { className: "absolute top-1 right-1 h-2 w-2 rounded-full bg-destructive" })
|
|
1361
1456
|
]
|
|
1362
1457
|
}
|
|
1363
1458
|
),
|
|
1364
|
-
notificationsOpen && /* @__PURE__ */
|
|
1365
|
-
/* @__PURE__ */
|
|
1366
|
-
/* @__PURE__ */
|
|
1367
|
-
(notifData?.unreadCount ?? 0) > 0 && notifData?.onMarkAllRead && /* @__PURE__ */
|
|
1459
|
+
notificationsOpen && /* @__PURE__ */ jsxs12("div", { className: "absolute right-0 top-full mt-2 w-80 rounded-lg border border-border bg-card shadow-lg z-50", children: [
|
|
1460
|
+
/* @__PURE__ */ jsxs12("div", { className: "flex items-center justify-between border-b border-border px-4 py-3", children: [
|
|
1461
|
+
/* @__PURE__ */ jsx13("p", { className: "font-bold text-foreground text-sm", children: "Notifications" }),
|
|
1462
|
+
(notifData?.unreadCount ?? 0) > 0 && notifData?.onMarkAllRead && /* @__PURE__ */ jsx13(
|
|
1368
1463
|
"button",
|
|
1369
1464
|
{
|
|
1370
1465
|
type: "button",
|
|
@@ -1376,11 +1471,11 @@ function DashboardLayoutInner({
|
|
|
1376
1471
|
}
|
|
1377
1472
|
)
|
|
1378
1473
|
] }),
|
|
1379
|
-
!notifData?.items || notifData.items.length === 0 ? /* @__PURE__ */
|
|
1380
|
-
/* @__PURE__ */
|
|
1381
|
-
/* @__PURE__ */
|
|
1382
|
-
/* @__PURE__ */
|
|
1383
|
-
] }) : /* @__PURE__ */
|
|
1474
|
+
!notifData?.items || notifData.items.length === 0 ? /* @__PURE__ */ jsxs12("div", { className: "flex flex-col items-center justify-center px-4 py-8 text-center", children: [
|
|
1475
|
+
/* @__PURE__ */ jsx13(Bell, { className: "h-8 w-8 text-muted-foreground/40 mb-2" }),
|
|
1476
|
+
/* @__PURE__ */ jsx13("p", { className: "text-muted-foreground text-sm", children: "No notifications yet" }),
|
|
1477
|
+
/* @__PURE__ */ jsx13("p", { className: "text-muted-foreground/60 text-xs mt-1", children: "We'll notify you about important updates" })
|
|
1478
|
+
] }) : /* @__PURE__ */ jsx13("div", { className: "max-h-80 overflow-y-auto", children: notifData.items.map((n) => /* @__PURE__ */ jsxs12(
|
|
1384
1479
|
"button",
|
|
1385
1480
|
{
|
|
1386
1481
|
type: "button",
|
|
@@ -1392,9 +1487,9 @@ function DashboardLayoutInner({
|
|
|
1392
1487
|
if (!n.read) notifData.onMarkRead?.(n.id);
|
|
1393
1488
|
},
|
|
1394
1489
|
children: [
|
|
1395
|
-
/* @__PURE__ */
|
|
1396
|
-
/* @__PURE__ */
|
|
1397
|
-
/* @__PURE__ */
|
|
1490
|
+
/* @__PURE__ */ jsx13("p", { className: cn("text-sm", !n.read ? "font-semibold text-foreground" : "text-muted-foreground"), children: n.title }),
|
|
1491
|
+
/* @__PURE__ */ jsx13("p", { className: "text-xs text-muted-foreground mt-0.5 line-clamp-2", children: n.message }),
|
|
1492
|
+
/* @__PURE__ */ jsx13("p", { className: "text-[10px] text-muted-foreground/50 mt-1", children: formatNotifDate(n.createdAt) })
|
|
1398
1493
|
]
|
|
1399
1494
|
},
|
|
1400
1495
|
n.id
|
|
@@ -1402,7 +1497,7 @@ function DashboardLayoutInner({
|
|
|
1402
1497
|
] })
|
|
1403
1498
|
] })
|
|
1404
1499
|
] }),
|
|
1405
|
-
/* @__PURE__ */
|
|
1500
|
+
/* @__PURE__ */ jsx13(
|
|
1406
1501
|
"button",
|
|
1407
1502
|
{
|
|
1408
1503
|
type: "button",
|
|
@@ -1410,14 +1505,14 @@ function DashboardLayoutInner({
|
|
|
1410
1505
|
className: "rounded-md p-2 hover:bg-muted/50 lg:hidden",
|
|
1411
1506
|
"aria-label": mobileMenuOpen ? "Close menu" : "Open menu",
|
|
1412
1507
|
"aria-expanded": mobileMenuOpen,
|
|
1413
|
-
children: mobileMenuOpen ? /* @__PURE__ */
|
|
1508
|
+
children: mobileMenuOpen ? /* @__PURE__ */ jsx13(XIcon, { className: "h-6 w-6" }) : /* @__PURE__ */ jsx13(MenuIcon, { className: "h-6 w-6" })
|
|
1414
1509
|
}
|
|
1415
1510
|
)
|
|
1416
1511
|
]
|
|
1417
1512
|
}
|
|
1418
1513
|
),
|
|
1419
|
-
mobileMenuOpen && /* @__PURE__ */
|
|
1420
|
-
/* @__PURE__ */
|
|
1514
|
+
mobileMenuOpen && /* @__PURE__ */ jsx13("div", { className: "fixed inset-0 z-30 bg-black/50 lg:hidden", onClick: () => setMobileMenuOpen(false), "aria-hidden": "true" }),
|
|
1515
|
+
/* @__PURE__ */ jsx13(
|
|
1421
1516
|
"aside",
|
|
1422
1517
|
{
|
|
1423
1518
|
className: cn(
|
|
@@ -1430,13 +1525,121 @@ function DashboardLayoutInner({
|
|
|
1430
1525
|
children: mobileSidebarContent
|
|
1431
1526
|
}
|
|
1432
1527
|
),
|
|
1433
|
-
/* @__PURE__ */
|
|
1434
|
-
/* @__PURE__ */
|
|
1528
|
+
/* @__PURE__ */ jsx13(Sidebar, { className: cn("hidden lg:flex", sidebarClassName), children: sidebarContent }),
|
|
1529
|
+
/* @__PURE__ */ jsx13(SidebarContent, { className: cn("pt-16 px-6 pb-8 lg:px-8 bg-background", contentClassName), children }),
|
|
1435
1530
|
footer
|
|
1436
1531
|
] });
|
|
1437
1532
|
}
|
|
1438
1533
|
function DashboardLayout({ defaultPanelOpen, defaultMode, ...props }) {
|
|
1439
|
-
return /* @__PURE__ */
|
|
1534
|
+
return /* @__PURE__ */ jsx13(SidebarProvider, { defaultPanelOpen, defaultMode, hasPanels: (props.panels?.length ?? 0) > 0, children: /* @__PURE__ */ jsx13(DashboardLayoutInner, { defaultPanelOpen, defaultMode, ...props }) });
|
|
1535
|
+
}
|
|
1536
|
+
|
|
1537
|
+
// src/dashboard/sidebar-layout.tsx
|
|
1538
|
+
import { jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
1539
|
+
var HIDE_BELOW_CLASS = {
|
|
1540
|
+
md: "max-md:hidden",
|
|
1541
|
+
lg: "max-lg:hidden"
|
|
1542
|
+
};
|
|
1543
|
+
function DefaultLink3({
|
|
1544
|
+
href,
|
|
1545
|
+
to,
|
|
1546
|
+
className,
|
|
1547
|
+
children,
|
|
1548
|
+
...rest
|
|
1549
|
+
}) {
|
|
1550
|
+
return /* @__PURE__ */ jsx14("a", { href: href ?? to, className, ...rest, children });
|
|
1551
|
+
}
|
|
1552
|
+
function SidebarLayoutInner({
|
|
1553
|
+
children,
|
|
1554
|
+
navItems,
|
|
1555
|
+
activeId,
|
|
1556
|
+
panel,
|
|
1557
|
+
logo,
|
|
1558
|
+
logoHref,
|
|
1559
|
+
user,
|
|
1560
|
+
isLoading = false,
|
|
1561
|
+
onLogout,
|
|
1562
|
+
onSettingsClick,
|
|
1563
|
+
settingsHref,
|
|
1564
|
+
profileMenuItems,
|
|
1565
|
+
railFooter,
|
|
1566
|
+
LinkComponent,
|
|
1567
|
+
hideBelow,
|
|
1568
|
+
railLabels = false,
|
|
1569
|
+
closePanelOnNavigate = false,
|
|
1570
|
+
className,
|
|
1571
|
+
sidebarClassName,
|
|
1572
|
+
contentClassName
|
|
1573
|
+
}) {
|
|
1574
|
+
const Link = LinkComponent ?? DefaultLink3;
|
|
1575
|
+
const { panelOpen, togglePanel, setPanelOpen } = useSidebar();
|
|
1576
|
+
const handleNavClick = closePanelOnNavigate && panelOpen ? () => setPanelOpen(false) : void 0;
|
|
1577
|
+
const hasProfile = user !== void 0 || onLogout !== void 0 || onSettingsClick !== void 0;
|
|
1578
|
+
return /* @__PURE__ */ jsxs13("div", { className: cn("min-h-screen bg-background text-foreground", className), children: [
|
|
1579
|
+
/* @__PURE__ */ jsx14("div", { className: cn(hideBelow && HIDE_BELOW_CLASS[hideBelow]), children: /* @__PURE__ */ jsxs13(Sidebar, { className: sidebarClassName, children: [
|
|
1580
|
+
/* @__PURE__ */ jsxs13(SidebarRail, { children: [
|
|
1581
|
+
logo !== void 0 && /* @__PURE__ */ jsx14(SidebarRailHeader, { className: railLabels ? "justify-start px-4" : void 0, children: /* @__PURE__ */ jsx14(
|
|
1582
|
+
Link,
|
|
1583
|
+
{
|
|
1584
|
+
href: logoHref,
|
|
1585
|
+
to: logoHref,
|
|
1586
|
+
className: "flex items-center justify-center rounded-lg p-1 transition-colors hover:bg-muted/50",
|
|
1587
|
+
children: logo
|
|
1588
|
+
}
|
|
1589
|
+
) }),
|
|
1590
|
+
/* @__PURE__ */ jsx14(SidebarRailNav, { className: railLabels ? "px-2" : void 0, children: navItems.map(
|
|
1591
|
+
(item) => item.togglesPanel ? /* @__PURE__ */ jsx14(
|
|
1592
|
+
RailButton,
|
|
1593
|
+
{
|
|
1594
|
+
icon: item.icon,
|
|
1595
|
+
label: item.label,
|
|
1596
|
+
badge: item.badge,
|
|
1597
|
+
isActive: panelOpen,
|
|
1598
|
+
onClick: togglePanel,
|
|
1599
|
+
showLabel: railLabels
|
|
1600
|
+
},
|
|
1601
|
+
item.id
|
|
1602
|
+
) : /* @__PURE__ */ jsx14(RailButton, { icon: item.icon, label: item.label, badge: item.badge, isActive: activeId === item.id, showLabel: railLabels, asChild: true, children: /* @__PURE__ */ jsx14(Link, { href: item.href, to: item.href, onClick: handleNavClick }) }, item.id)
|
|
1603
|
+
) }),
|
|
1604
|
+
(railFooter !== void 0 || hasProfile) && /* @__PURE__ */ jsxs13(SidebarRailFooter, { className: cn("border-t border-border pt-2", railLabels && "items-stretch px-2"), children: [
|
|
1605
|
+
railFooter,
|
|
1606
|
+
hasProfile && /* @__PURE__ */ jsx14(
|
|
1607
|
+
ProfileAvatar,
|
|
1608
|
+
{
|
|
1609
|
+
user: user ?? void 0,
|
|
1610
|
+
isLoading,
|
|
1611
|
+
onLogout,
|
|
1612
|
+
onSettingsClick,
|
|
1613
|
+
settingsHref,
|
|
1614
|
+
showDetails: railLabels,
|
|
1615
|
+
LinkComponent: Link,
|
|
1616
|
+
children: profileMenuItems
|
|
1617
|
+
}
|
|
1618
|
+
)
|
|
1619
|
+
] })
|
|
1620
|
+
] }),
|
|
1621
|
+
panel != null && /* @__PURE__ */ jsx14(SidebarPanel, { children: panel })
|
|
1622
|
+
] }) }),
|
|
1623
|
+
/* @__PURE__ */ jsx14(SidebarContent, { className: contentClassName, children })
|
|
1624
|
+
] });
|
|
1625
|
+
}
|
|
1626
|
+
function SidebarLayout({
|
|
1627
|
+
panelOpen,
|
|
1628
|
+
onPanelOpenChange,
|
|
1629
|
+
defaultPanelOpen,
|
|
1630
|
+
...props
|
|
1631
|
+
}) {
|
|
1632
|
+
return /* @__PURE__ */ jsx14(
|
|
1633
|
+
SidebarProvider,
|
|
1634
|
+
{
|
|
1635
|
+
panelOpen,
|
|
1636
|
+
onPanelOpenChange,
|
|
1637
|
+
defaultPanelOpen,
|
|
1638
|
+
hasPanels: props.panel != null,
|
|
1639
|
+
railWidth: props.railLabels ? SIDEBAR_RAIL_LABELED_WIDTH : void 0,
|
|
1640
|
+
children: /* @__PURE__ */ jsx14(SidebarLayoutInner, { ...props })
|
|
1641
|
+
}
|
|
1642
|
+
);
|
|
1440
1643
|
}
|
|
1441
1644
|
|
|
1442
1645
|
// src/dashboard/profile-selector.tsx
|
|
@@ -1451,7 +1654,7 @@ import {
|
|
|
1451
1654
|
DropdownMenuSeparator as DropdownMenuSeparator4,
|
|
1452
1655
|
DropdownMenuTrigger as DropdownMenuTrigger4
|
|
1453
1656
|
} from "@tangle-network/ui/primitives";
|
|
1454
|
-
import { Fragment as Fragment8, jsx as
|
|
1657
|
+
import { Fragment as Fragment8, jsx as jsx15, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
1455
1658
|
function ProfileSelector({
|
|
1456
1659
|
profiles,
|
|
1457
1660
|
selectedId,
|
|
@@ -1466,77 +1669,77 @@ function ProfileSelector({
|
|
|
1466
1669
|
const selected = profiles.find((p) => p.id === selectedId);
|
|
1467
1670
|
const builtinProfiles = profiles.filter((p) => p.is_builtin);
|
|
1468
1671
|
const customProfiles = profiles.filter((p) => !p.is_builtin);
|
|
1469
|
-
return /* @__PURE__ */
|
|
1470
|
-
label && /* @__PURE__ */
|
|
1471
|
-
/* @__PURE__ */
|
|
1472
|
-
/* @__PURE__ */
|
|
1473
|
-
/* @__PURE__ */
|
|
1474
|
-
/* @__PURE__ */
|
|
1672
|
+
return /* @__PURE__ */ jsxs14("div", { className, children: [
|
|
1673
|
+
label && /* @__PURE__ */ jsx15("label", { className: "mb-2 block font-medium text-sm", children: label }),
|
|
1674
|
+
/* @__PURE__ */ jsxs14(DropdownMenu4, { children: [
|
|
1675
|
+
/* @__PURE__ */ jsx15(DropdownMenuTrigger4, { asChild: true, children: /* @__PURE__ */ jsxs14(Button2, { variant: "outline", className: "w-full justify-between", children: [
|
|
1676
|
+
/* @__PURE__ */ jsx15("span", { className: "truncate", children: selected ? selected.name : placeholder }),
|
|
1677
|
+
/* @__PURE__ */ jsx15(ChevronDown, { className: "ml-2 h-4 w-4 shrink-0 opacity-50" })
|
|
1475
1678
|
] }) }),
|
|
1476
|
-
/* @__PURE__ */
|
|
1477
|
-
/* @__PURE__ */
|
|
1679
|
+
/* @__PURE__ */ jsxs14(DropdownMenuContent4, { className: "w-[300px]", align: "start", children: [
|
|
1680
|
+
/* @__PURE__ */ jsxs14(
|
|
1478
1681
|
DropdownMenuItem4,
|
|
1479
1682
|
{
|
|
1480
1683
|
onClick: () => onSelect(null),
|
|
1481
1684
|
className: "flex items-center justify-between",
|
|
1482
1685
|
children: [
|
|
1483
|
-
/* @__PURE__ */
|
|
1484
|
-
!selectedId && /* @__PURE__ */
|
|
1686
|
+
/* @__PURE__ */ jsx15("span", { children: placeholder }),
|
|
1687
|
+
!selectedId && /* @__PURE__ */ jsx15(Check2, { className: "h-4 w-4 text-[var(--surface-success-text)]" })
|
|
1485
1688
|
]
|
|
1486
1689
|
}
|
|
1487
1690
|
),
|
|
1488
|
-
builtinProfiles.length > 0 && /* @__PURE__ */
|
|
1489
|
-
/* @__PURE__ */
|
|
1490
|
-
/* @__PURE__ */
|
|
1491
|
-
builtinProfiles.map((profile) => /* @__PURE__ */
|
|
1691
|
+
builtinProfiles.length > 0 && /* @__PURE__ */ jsxs14(Fragment8, { children: [
|
|
1692
|
+
/* @__PURE__ */ jsx15(DropdownMenuSeparator4, {}),
|
|
1693
|
+
/* @__PURE__ */ jsx15(DropdownMenuLabel2, { children: "Built-in Profiles" }),
|
|
1694
|
+
builtinProfiles.map((profile) => /* @__PURE__ */ jsxs14(
|
|
1492
1695
|
DropdownMenuItem4,
|
|
1493
1696
|
{
|
|
1494
1697
|
onClick: () => onSelect(profile),
|
|
1495
1698
|
className: "flex flex-col items-start gap-1",
|
|
1496
1699
|
children: [
|
|
1497
|
-
/* @__PURE__ */
|
|
1498
|
-
/* @__PURE__ */
|
|
1499
|
-
/* @__PURE__ */
|
|
1500
|
-
profile.extends && /* @__PURE__ */
|
|
1700
|
+
/* @__PURE__ */ jsxs14("div", { className: "flex w-full items-center justify-between", children: [
|
|
1701
|
+
/* @__PURE__ */ jsxs14("div", { className: "flex items-center gap-2", children: [
|
|
1702
|
+
/* @__PURE__ */ jsx15("span", { className: "font-medium", children: profile.name }),
|
|
1703
|
+
profile.extends && /* @__PURE__ */ jsxs14(Badge, { variant: "secondary", className: "border-0 text-xs", children: [
|
|
1501
1704
|
"extends ",
|
|
1502
1705
|
profile.extends
|
|
1503
1706
|
] })
|
|
1504
1707
|
] }),
|
|
1505
|
-
selectedId === profile.id && /* @__PURE__ */
|
|
1708
|
+
selectedId === profile.id && /* @__PURE__ */ jsx15(Check2, { className: "h-4 w-4 text-[var(--surface-success-text)]" })
|
|
1506
1709
|
] }),
|
|
1507
|
-
profile.description && /* @__PURE__ */
|
|
1710
|
+
profile.description && /* @__PURE__ */ jsx15("span", { className: "line-clamp-1 text-muted-foreground text-xs", children: profile.description })
|
|
1508
1711
|
]
|
|
1509
1712
|
},
|
|
1510
1713
|
profile.id
|
|
1511
1714
|
))
|
|
1512
1715
|
] }),
|
|
1513
|
-
customProfiles.length > 0 && /* @__PURE__ */
|
|
1514
|
-
/* @__PURE__ */
|
|
1515
|
-
/* @__PURE__ */
|
|
1516
|
-
customProfiles.map((profile) => /* @__PURE__ */
|
|
1716
|
+
customProfiles.length > 0 && /* @__PURE__ */ jsxs14(Fragment8, { children: [
|
|
1717
|
+
/* @__PURE__ */ jsx15(DropdownMenuSeparator4, {}),
|
|
1718
|
+
/* @__PURE__ */ jsx15(DropdownMenuLabel2, { children: "Custom Profiles" }),
|
|
1719
|
+
customProfiles.map((profile) => /* @__PURE__ */ jsxs14(
|
|
1517
1720
|
DropdownMenuItem4,
|
|
1518
1721
|
{
|
|
1519
1722
|
onClick: () => onSelect(profile),
|
|
1520
1723
|
className: "flex flex-col items-start gap-1",
|
|
1521
1724
|
children: [
|
|
1522
|
-
/* @__PURE__ */
|
|
1523
|
-
/* @__PURE__ */
|
|
1524
|
-
/* @__PURE__ */
|
|
1525
|
-
profile.model && /* @__PURE__ */
|
|
1725
|
+
/* @__PURE__ */ jsxs14("div", { className: "flex w-full items-center justify-between", children: [
|
|
1726
|
+
/* @__PURE__ */ jsxs14("div", { className: "flex items-center gap-2", children: [
|
|
1727
|
+
/* @__PURE__ */ jsx15("span", { className: "font-medium", children: profile.name }),
|
|
1728
|
+
profile.model && /* @__PURE__ */ jsx15(Badge, { variant: "secondary", className: "border-0 text-xs", children: profile.model.split("/").pop() })
|
|
1526
1729
|
] }),
|
|
1527
|
-
selectedId === profile.id && /* @__PURE__ */
|
|
1730
|
+
selectedId === profile.id && /* @__PURE__ */ jsx15(Check2, { className: "h-4 w-4 text-[var(--surface-success-text)]" })
|
|
1528
1731
|
] }),
|
|
1529
|
-
profile.description && /* @__PURE__ */
|
|
1530
|
-
showMetrics && profile.metrics && profile.metrics.total_runs > 0 && /* @__PURE__ */
|
|
1531
|
-
/* @__PURE__ */
|
|
1732
|
+
profile.description && /* @__PURE__ */ jsx15("span", { className: "line-clamp-1 text-muted-foreground text-xs", children: profile.description }),
|
|
1733
|
+
showMetrics && profile.metrics && profile.metrics.total_runs > 0 && /* @__PURE__ */ jsxs14("div", { className: "flex gap-3 text-muted-foreground text-xs", children: [
|
|
1734
|
+
/* @__PURE__ */ jsxs14("span", { children: [
|
|
1532
1735
|
profile.metrics.total_runs,
|
|
1533
1736
|
" runs"
|
|
1534
1737
|
] }),
|
|
1535
|
-
/* @__PURE__ */
|
|
1738
|
+
/* @__PURE__ */ jsxs14("span", { children: [
|
|
1536
1739
|
profile.metrics.success_rate.toFixed(0),
|
|
1537
1740
|
"% success"
|
|
1538
1741
|
] }),
|
|
1539
|
-
/* @__PURE__ */
|
|
1742
|
+
/* @__PURE__ */ jsxs14("span", { children: [
|
|
1540
1743
|
"~",
|
|
1541
1744
|
(profile.metrics.avg_duration_ms / 1e3).toFixed(1),
|
|
1542
1745
|
"s avg"
|
|
@@ -1547,26 +1750,26 @@ function ProfileSelector({
|
|
|
1547
1750
|
profile.id
|
|
1548
1751
|
))
|
|
1549
1752
|
] }),
|
|
1550
|
-
(onCreateClick || onManageClick) && /* @__PURE__ */
|
|
1551
|
-
/* @__PURE__ */
|
|
1552
|
-
onCreateClick && /* @__PURE__ */
|
|
1753
|
+
(onCreateClick || onManageClick) && /* @__PURE__ */ jsxs14(Fragment8, { children: [
|
|
1754
|
+
/* @__PURE__ */ jsx15(DropdownMenuSeparator4, {}),
|
|
1755
|
+
onCreateClick && /* @__PURE__ */ jsxs14(
|
|
1553
1756
|
DropdownMenuItem4,
|
|
1554
1757
|
{
|
|
1555
1758
|
onClick: onCreateClick,
|
|
1556
1759
|
className: "text-[var(--surface-info-text)]",
|
|
1557
1760
|
children: [
|
|
1558
|
-
/* @__PURE__ */
|
|
1761
|
+
/* @__PURE__ */ jsx15(Plus3, { className: "mr-2 h-4 w-4" }),
|
|
1559
1762
|
"Create New Profile"
|
|
1560
1763
|
]
|
|
1561
1764
|
}
|
|
1562
1765
|
),
|
|
1563
|
-
onManageClick && /* @__PURE__ */
|
|
1766
|
+
onManageClick && /* @__PURE__ */ jsxs14(
|
|
1564
1767
|
DropdownMenuItem4,
|
|
1565
1768
|
{
|
|
1566
1769
|
onClick: onManageClick,
|
|
1567
1770
|
className: "text-muted-foreground",
|
|
1568
1771
|
children: [
|
|
1569
|
-
/* @__PURE__ */
|
|
1772
|
+
/* @__PURE__ */ jsx15(Settings, { className: "mr-2 h-4 w-4" }),
|
|
1570
1773
|
"Manage Profiles"
|
|
1571
1774
|
]
|
|
1572
1775
|
}
|
|
@@ -1592,26 +1795,26 @@ function ProfileComparison({
|
|
|
1592
1795
|
const fastestProfile = profilesWithMetrics.reduce(
|
|
1593
1796
|
(best, p) => (p.metrics?.avg_duration_ms ?? Number.POSITIVE_INFINITY) < (best.metrics?.avg_duration_ms ?? Number.POSITIVE_INFINITY) ? p : best
|
|
1594
1797
|
);
|
|
1595
|
-
return /* @__PURE__ */
|
|
1596
|
-
/* @__PURE__ */
|
|
1597
|
-
/* @__PURE__ */
|
|
1798
|
+
return /* @__PURE__ */ jsxs14("div", { className: `rounded-lg border border-border p-4 ${className ?? ""}`, children: [
|
|
1799
|
+
/* @__PURE__ */ jsx15("h4", { className: "mb-3 font-medium text-sm", children: "Profile Performance" }),
|
|
1800
|
+
/* @__PURE__ */ jsx15("div", { className: "space-y-3", children: profilesWithMetrics.map((profile) => {
|
|
1598
1801
|
const isBestSuccess = profile.id === bestSuccess.id;
|
|
1599
1802
|
const isFastest = profile.id === fastestProfile.id;
|
|
1600
|
-
return /* @__PURE__ */
|
|
1803
|
+
return /* @__PURE__ */ jsxs14(
|
|
1601
1804
|
"div",
|
|
1602
1805
|
{
|
|
1603
1806
|
className: "flex items-center justify-between gap-4",
|
|
1604
1807
|
children: [
|
|
1605
|
-
/* @__PURE__ */
|
|
1606
|
-
/* @__PURE__ */
|
|
1607
|
-
isBestSuccess && /* @__PURE__ */
|
|
1608
|
-
isFastest && !isBestSuccess && /* @__PURE__ */
|
|
1808
|
+
/* @__PURE__ */ jsxs14("div", { className: "flex items-center gap-2", children: [
|
|
1809
|
+
/* @__PURE__ */ jsx15("span", { className: "font-medium", children: profile.name }),
|
|
1810
|
+
isBestSuccess && /* @__PURE__ */ jsx15(Badge, { className: "border border-[var(--surface-success-border)] bg-[var(--surface-success-bg)] text-[var(--surface-success-text)] text-xs", children: "Best Success" }),
|
|
1811
|
+
isFastest && !isBestSuccess && /* @__PURE__ */ jsx15(Badge, { className: "border border-[var(--surface-info-border)] bg-[var(--surface-info-bg)] text-[var(--surface-info-text)] text-xs", children: "Fastest" })
|
|
1609
1812
|
] }),
|
|
1610
|
-
/* @__PURE__ */
|
|
1611
|
-
/* @__PURE__ */
|
|
1612
|
-
/* @__PURE__ */
|
|
1813
|
+
/* @__PURE__ */ jsxs14("div", { className: "flex items-center gap-4 text-sm", children: [
|
|
1814
|
+
/* @__PURE__ */ jsxs14("span", { children: [
|
|
1815
|
+
/* @__PURE__ */ jsx15("span", { className: "text-muted-foreground", children: "Success:" }),
|
|
1613
1816
|
" ",
|
|
1614
|
-
/* @__PURE__ */
|
|
1817
|
+
/* @__PURE__ */ jsxs14(
|
|
1615
1818
|
"span",
|
|
1616
1819
|
{
|
|
1617
1820
|
className: (profile.metrics?.success_rate ?? 0) >= 80 ? "text-[var(--surface-success-text)]" : (profile.metrics?.success_rate ?? 0) >= 50 ? "text-[var(--surface-warning-text)]" : "text-[var(--surface-danger-text)]",
|
|
@@ -1622,13 +1825,13 @@ function ProfileComparison({
|
|
|
1622
1825
|
}
|
|
1623
1826
|
)
|
|
1624
1827
|
] }),
|
|
1625
|
-
/* @__PURE__ */
|
|
1626
|
-
/* @__PURE__ */
|
|
1828
|
+
/* @__PURE__ */ jsxs14("span", { children: [
|
|
1829
|
+
/* @__PURE__ */ jsx15("span", { className: "text-muted-foreground", children: "Avg:" }),
|
|
1627
1830
|
" ",
|
|
1628
1831
|
((profile.metrics?.avg_duration_ms ?? 0) / 1e3).toFixed(1),
|
|
1629
1832
|
"s"
|
|
1630
1833
|
] }),
|
|
1631
|
-
/* @__PURE__ */
|
|
1834
|
+
/* @__PURE__ */ jsxs14("span", { className: "text-muted-foreground", children: [
|
|
1632
1835
|
profile.metrics?.total_runs,
|
|
1633
1836
|
" runs"
|
|
1634
1837
|
] })
|
|
@@ -1642,8 +1845,8 @@ function ProfileComparison({
|
|
|
1642
1845
|
}
|
|
1643
1846
|
|
|
1644
1847
|
// src/dashboard/metric-area-chart.tsx
|
|
1645
|
-
import * as
|
|
1646
|
-
import { jsx as
|
|
1848
|
+
import * as React7 from "react";
|
|
1849
|
+
import { jsx as jsx16, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
1647
1850
|
var TONE_VARS = {
|
|
1648
1851
|
primary: "var(--brand-primary, hsl(var(--primary)))",
|
|
1649
1852
|
success: "var(--status-running, #22c55e)",
|
|
@@ -1689,7 +1892,7 @@ function MetricAreaChart({
|
|
|
1689
1892
|
emptyState,
|
|
1690
1893
|
className
|
|
1691
1894
|
}) {
|
|
1692
|
-
const gradientId =
|
|
1895
|
+
const gradientId = React7.useId();
|
|
1693
1896
|
const width = 400;
|
|
1694
1897
|
const values = points.map((p) => p.value).filter((v) => v !== null);
|
|
1695
1898
|
const latest = values.length > 0 ? values[values.length - 1] : null;
|
|
@@ -1697,7 +1900,7 @@ function MetricAreaChart({
|
|
|
1697
1900
|
const yMax = maxValue ?? (observedMax > 0 ? observedMax * 1.1 : 1);
|
|
1698
1901
|
const segments = buildSegments(points, width, height, yMax);
|
|
1699
1902
|
const color = TONE_VARS[tone];
|
|
1700
|
-
return /* @__PURE__ */
|
|
1903
|
+
return /* @__PURE__ */ jsxs15(
|
|
1701
1904
|
"div",
|
|
1702
1905
|
{
|
|
1703
1906
|
className: cn(
|
|
@@ -1706,21 +1909,21 @@ function MetricAreaChart({
|
|
|
1706
1909
|
),
|
|
1707
1910
|
"data-testid": `metric-chart-${label.toLowerCase().replace(/\s+/g, "-")}`,
|
|
1708
1911
|
children: [
|
|
1709
|
-
/* @__PURE__ */
|
|
1710
|
-
/* @__PURE__ */
|
|
1711
|
-
/* @__PURE__ */
|
|
1712
|
-
/* @__PURE__ */
|
|
1713
|
-
detail && /* @__PURE__ */
|
|
1912
|
+
/* @__PURE__ */ jsxs15("div", { className: "flex items-baseline justify-between gap-3", children: [
|
|
1913
|
+
/* @__PURE__ */ jsx16("p", { className: "font-medium text-muted-foreground text-xs uppercase tracking-[0.12em]", children: label }),
|
|
1914
|
+
/* @__PURE__ */ jsxs15("div", { className: "text-right", children: [
|
|
1915
|
+
/* @__PURE__ */ jsx16("span", { className: "font-semibold text-foreground text-xl tabular-nums tracking-tight", children: latest === null ? "\u2014" : formatValue(latest) }),
|
|
1916
|
+
detail && /* @__PURE__ */ jsx16("span", { className: "ml-1.5 text-muted-foreground text-xs", children: detail })
|
|
1714
1917
|
] })
|
|
1715
1918
|
] }),
|
|
1716
|
-
/* @__PURE__ */
|
|
1919
|
+
/* @__PURE__ */ jsx16("div", { className: "mt-3", children: values.length === 0 ? /* @__PURE__ */ jsx16(
|
|
1717
1920
|
"div",
|
|
1718
1921
|
{
|
|
1719
1922
|
className: "flex items-center justify-center text-muted-foreground text-xs",
|
|
1720
1923
|
style: { height },
|
|
1721
1924
|
children: emptyState ?? "Waiting for samples\u2026"
|
|
1722
1925
|
}
|
|
1723
|
-
) : /* @__PURE__ */
|
|
1926
|
+
) : /* @__PURE__ */ jsxs15(
|
|
1724
1927
|
"svg",
|
|
1725
1928
|
{
|
|
1726
1929
|
viewBox: `0 0 ${width} ${height}`,
|
|
@@ -1730,7 +1933,7 @@ function MetricAreaChart({
|
|
|
1730
1933
|
role: "img",
|
|
1731
1934
|
"aria-label": `${label} chart`,
|
|
1732
1935
|
children: [
|
|
1733
|
-
[0.25, 0.5, 0.75].map((fraction) => /* @__PURE__ */
|
|
1936
|
+
[0.25, 0.5, 0.75].map((fraction) => /* @__PURE__ */ jsx16(
|
|
1734
1937
|
"line",
|
|
1735
1938
|
{
|
|
1736
1939
|
x1: 0,
|
|
@@ -1745,13 +1948,13 @@ function MetricAreaChart({
|
|
|
1745
1948
|
},
|
|
1746
1949
|
fraction
|
|
1747
1950
|
)),
|
|
1748
|
-
/* @__PURE__ */
|
|
1749
|
-
/* @__PURE__ */
|
|
1750
|
-
/* @__PURE__ */
|
|
1951
|
+
/* @__PURE__ */ jsx16("defs", { children: /* @__PURE__ */ jsxs15("linearGradient", { id: gradientId, x1: "0", y1: "0", x2: "0", y2: "1", children: [
|
|
1952
|
+
/* @__PURE__ */ jsx16("stop", { offset: "0%", stopColor: color, stopOpacity: 0.28 }),
|
|
1953
|
+
/* @__PURE__ */ jsx16("stop", { offset: "100%", stopColor: color, stopOpacity: 0.02 })
|
|
1751
1954
|
] }) }),
|
|
1752
|
-
segments.map((segment) => /* @__PURE__ */
|
|
1753
|
-
/* @__PURE__ */
|
|
1754
|
-
/* @__PURE__ */
|
|
1955
|
+
segments.map((segment) => /* @__PURE__ */ jsxs15(React7.Fragment, { children: [
|
|
1956
|
+
/* @__PURE__ */ jsx16("path", { d: segment.area, fill: `url(#${gradientId})` }),
|
|
1957
|
+
/* @__PURE__ */ jsx16(
|
|
1755
1958
|
"path",
|
|
1756
1959
|
{
|
|
1757
1960
|
d: segment.path,
|
|
@@ -1767,9 +1970,9 @@ function MetricAreaChart({
|
|
|
1767
1970
|
]
|
|
1768
1971
|
}
|
|
1769
1972
|
) }),
|
|
1770
|
-
/* @__PURE__ */
|
|
1771
|
-
/* @__PURE__ */
|
|
1772
|
-
/* @__PURE__ */
|
|
1973
|
+
/* @__PURE__ */ jsxs15("div", { className: "mt-1.5 flex justify-between text-[10px] text-muted-foreground tabular-nums", children: [
|
|
1974
|
+
/* @__PURE__ */ jsx16("span", { children: values.length > 0 ? formatValue(0) : "" }),
|
|
1975
|
+
/* @__PURE__ */ jsx16("span", { children: values.length > 0 ? formatValue(yMax) : "" })
|
|
1773
1976
|
] })
|
|
1774
1977
|
]
|
|
1775
1978
|
}
|
|
@@ -1789,7 +1992,7 @@ import {
|
|
|
1789
1992
|
} from "lucide-react";
|
|
1790
1993
|
import { Button as Button3 } from "@tangle-network/ui/primitives";
|
|
1791
1994
|
import { Badge as Badge2 } from "@tangle-network/ui/primitives";
|
|
1792
|
-
import { Fragment as Fragment10, jsx as
|
|
1995
|
+
import { Fragment as Fragment10, jsx as jsx17, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
1793
1996
|
var statusConfig = {
|
|
1794
1997
|
pending: {
|
|
1795
1998
|
icon: Clock3,
|
|
@@ -1873,19 +2076,19 @@ function VariantList({
|
|
|
1873
2076
|
isActioning,
|
|
1874
2077
|
className
|
|
1875
2078
|
}) {
|
|
1876
|
-
return /* @__PURE__ */
|
|
2079
|
+
return /* @__PURE__ */ jsx17("div", { className: `space-y-2 ${className || ""}`, children: variants.map((variant) => {
|
|
1877
2080
|
const status = statusConfig[variant.status];
|
|
1878
2081
|
const StatusIcon = status.icon;
|
|
1879
2082
|
const isSelected = variant.id === selectedId;
|
|
1880
|
-
return /* @__PURE__ */
|
|
2083
|
+
return /* @__PURE__ */ jsxs16(
|
|
1881
2084
|
"div",
|
|
1882
2085
|
{
|
|
1883
2086
|
className: `cursor-pointer rounded-lg border px-3 py-2.5 transition-colors ${isSelected ? "border-primary/30 bg-[var(--accent-surface-soft)]" : "border-border bg-card hover:border-primary/20 hover:bg-muted/50"}`,
|
|
1884
2087
|
onClick: () => onSelect?.(variant.id),
|
|
1885
2088
|
children: [
|
|
1886
|
-
/* @__PURE__ */
|
|
1887
|
-
/* @__PURE__ */
|
|
1888
|
-
/* @__PURE__ */
|
|
2089
|
+
/* @__PURE__ */ jsxs16("div", { className: "flex items-center gap-2", children: [
|
|
2090
|
+
/* @__PURE__ */ jsxs16(Badge2, { className: `shrink-0 ${status.bg} ${status.border} ${status.color}`, children: [
|
|
2091
|
+
/* @__PURE__ */ jsx17(
|
|
1889
2092
|
StatusIcon,
|
|
1890
2093
|
{
|
|
1891
2094
|
className: `mr-1 h-3 w-3 ${status.animate ? "animate-spin" : ""}`
|
|
@@ -1893,27 +2096,27 @@ function VariantList({
|
|
|
1893
2096
|
),
|
|
1894
2097
|
status.label
|
|
1895
2098
|
] }),
|
|
1896
|
-
/* @__PURE__ */
|
|
1897
|
-
variant.sublabel && /* @__PURE__ */
|
|
2099
|
+
/* @__PURE__ */ jsx17("span", { className: "truncate text-sm font-medium text-foreground", children: variant.label }),
|
|
2100
|
+
variant.sublabel && /* @__PURE__ */ jsxs16("span", { className: "shrink-0 text-xs text-muted-foreground", children: [
|
|
1898
2101
|
"(",
|
|
1899
2102
|
variant.sublabel,
|
|
1900
2103
|
")"
|
|
1901
2104
|
] }),
|
|
1902
|
-
variant.durationMs && /* @__PURE__ */
|
|
1903
|
-
/* @__PURE__ */
|
|
2105
|
+
variant.durationMs && /* @__PURE__ */ jsxs16("span", { className: "flex shrink-0 items-center gap-1 text-xs text-muted-foreground", children: [
|
|
2106
|
+
/* @__PURE__ */ jsx17(Timer, { className: "h-3 w-3" }),
|
|
1904
2107
|
(variant.durationMs / 1e3).toFixed(1),
|
|
1905
2108
|
"s"
|
|
1906
2109
|
] }),
|
|
1907
|
-
/* @__PURE__ */
|
|
1908
|
-
variant.outcome && /* @__PURE__ */
|
|
2110
|
+
/* @__PURE__ */ jsxs16("div", { className: "ml-auto flex shrink-0 items-center gap-1.5", children: [
|
|
2111
|
+
variant.outcome && /* @__PURE__ */ jsx17(
|
|
1909
2112
|
Badge2,
|
|
1910
2113
|
{
|
|
1911
2114
|
className: `${outcomeConfig[variant.outcome].bg} ${outcomeConfig[variant.outcome].border} ${outcomeConfig[variant.outcome].color}`,
|
|
1912
2115
|
children: outcomeConfig[variant.outcome].label
|
|
1913
2116
|
}
|
|
1914
2117
|
),
|
|
1915
|
-
variant.status === "completed" && variant.outcome === "pending_review" && onAccept && onReject && /* @__PURE__ */
|
|
1916
|
-
/* @__PURE__ */
|
|
2118
|
+
variant.status === "completed" && variant.outcome === "pending_review" && onAccept && onReject && /* @__PURE__ */ jsxs16(Fragment10, { children: [
|
|
2119
|
+
/* @__PURE__ */ jsxs16(
|
|
1917
2120
|
Button3,
|
|
1918
2121
|
{
|
|
1919
2122
|
variant: "outline",
|
|
@@ -1925,12 +2128,12 @@ function VariantList({
|
|
|
1925
2128
|
},
|
|
1926
2129
|
disabled: isActioning === variant.id,
|
|
1927
2130
|
children: [
|
|
1928
|
-
/* @__PURE__ */
|
|
2131
|
+
/* @__PURE__ */ jsx17(Check3, { className: "mr-1 h-3 w-3" }),
|
|
1929
2132
|
"Accept"
|
|
1930
2133
|
]
|
|
1931
2134
|
}
|
|
1932
2135
|
),
|
|
1933
|
-
/* @__PURE__ */
|
|
2136
|
+
/* @__PURE__ */ jsxs16(
|
|
1934
2137
|
Button3,
|
|
1935
2138
|
{
|
|
1936
2139
|
variant: "outline",
|
|
@@ -1942,13 +2145,13 @@ function VariantList({
|
|
|
1942
2145
|
},
|
|
1943
2146
|
disabled: isActioning === variant.id,
|
|
1944
2147
|
children: [
|
|
1945
|
-
/* @__PURE__ */
|
|
2148
|
+
/* @__PURE__ */ jsx17(X, { className: "mr-1 h-3 w-3" }),
|
|
1946
2149
|
"Reject"
|
|
1947
2150
|
]
|
|
1948
2151
|
}
|
|
1949
2152
|
)
|
|
1950
2153
|
] }),
|
|
1951
|
-
variant.detailsUrl && /* @__PURE__ */
|
|
2154
|
+
variant.detailsUrl && /* @__PURE__ */ jsx17(
|
|
1952
2155
|
Button3,
|
|
1953
2156
|
{
|
|
1954
2157
|
variant: "ghost",
|
|
@@ -1958,13 +2161,13 @@ function VariantList({
|
|
|
1958
2161
|
e.stopPropagation();
|
|
1959
2162
|
window.open(variant.detailsUrl, "_blank");
|
|
1960
2163
|
},
|
|
1961
|
-
children: /* @__PURE__ */
|
|
2164
|
+
children: /* @__PURE__ */ jsx17(ExternalLink2, { className: "h-3.5 w-3.5" })
|
|
1962
2165
|
}
|
|
1963
2166
|
)
|
|
1964
2167
|
] })
|
|
1965
2168
|
] }),
|
|
1966
|
-
variant.error && /* @__PURE__ */
|
|
1967
|
-
variant.summary && /* @__PURE__ */
|
|
2169
|
+
variant.error && /* @__PURE__ */ jsx17("p", { className: "mt-1.5 text-xs text-[var(--surface-danger-text)]", children: variant.error }),
|
|
2170
|
+
variant.summary && /* @__PURE__ */ jsx17("p", { className: "mt-1.5 line-clamp-2 text-xs text-muted-foreground", children: variant.summary })
|
|
1968
2171
|
]
|
|
1969
2172
|
},
|
|
1970
2173
|
variant.id
|
|
@@ -1975,7 +2178,7 @@ function VariantList({
|
|
|
1975
2178
|
// src/dashboard/system-logs.tsx
|
|
1976
2179
|
import { Terminal as Terminal3 } from "lucide-react";
|
|
1977
2180
|
import { useEffect as useEffect2, useRef as useRef2, useState as useState4 } from "react";
|
|
1978
|
-
import { jsx as
|
|
2181
|
+
import { jsx as jsx18, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
1979
2182
|
function SystemLogsViewer({ apiUrl, token, className }) {
|
|
1980
2183
|
const [logs, setLogs] = useState4([]);
|
|
1981
2184
|
const [error, setError] = useState4(null);
|
|
@@ -2028,18 +2231,18 @@ function SystemLogsViewer({ apiUrl, token, className }) {
|
|
|
2028
2231
|
const isAtBottom = scrollHeight - scrollTop - clientHeight < 20;
|
|
2029
2232
|
setIsFollowing((prev) => prev === isAtBottom ? prev : isAtBottom);
|
|
2030
2233
|
};
|
|
2031
|
-
return /* @__PURE__ */
|
|
2032
|
-
/* @__PURE__ */
|
|
2033
|
-
/* @__PURE__ */
|
|
2034
|
-
/* @__PURE__ */
|
|
2035
|
-
/* @__PURE__ */
|
|
2234
|
+
return /* @__PURE__ */ jsxs17("div", { className: cn("flex flex-col h-full bg-background text-foreground font-mono text-sm leading-relaxed overflow-hidden rounded-lg border border-border", className), children: [
|
|
2235
|
+
/* @__PURE__ */ jsxs17("div", { className: "flex-none flex items-center justify-between border-b border-border bg-muted/50 backdrop-blur-md px-4 py-2", children: [
|
|
2236
|
+
/* @__PURE__ */ jsxs17("div", { className: "flex items-center gap-2", children: [
|
|
2237
|
+
/* @__PURE__ */ jsx18(Terminal3, { className: "h-4 w-4 text-primary animate-pulse" }),
|
|
2238
|
+
/* @__PURE__ */ jsx18("span", { className: "font-bold text-xs uppercase tracking-widest text-muted-foreground", children: "System Traces" })
|
|
2036
2239
|
] }),
|
|
2037
|
-
/* @__PURE__ */
|
|
2038
|
-
error && /* @__PURE__ */
|
|
2039
|
-
/* @__PURE__ */
|
|
2240
|
+
/* @__PURE__ */ jsxs17("div", { className: "flex items-center gap-3", children: [
|
|
2241
|
+
error && /* @__PURE__ */ jsxs17("span", { className: "text-destructive text-xs flex items-center gap-1", children: [
|
|
2242
|
+
/* @__PURE__ */ jsx18("span", { className: "w-2 h-2 rounded-full bg-destructive animate-ping" }),
|
|
2040
2243
|
" Error fetching logs"
|
|
2041
2244
|
] }),
|
|
2042
|
-
/* @__PURE__ */
|
|
2245
|
+
/* @__PURE__ */ jsx18(
|
|
2043
2246
|
"button",
|
|
2044
2247
|
{
|
|
2045
2248
|
onClick: () => {
|
|
@@ -2054,29 +2257,29 @@ function SystemLogsViewer({ apiUrl, token, className }) {
|
|
|
2054
2257
|
)
|
|
2055
2258
|
] })
|
|
2056
2259
|
] }),
|
|
2057
|
-
/* @__PURE__ */
|
|
2260
|
+
/* @__PURE__ */ jsx18(
|
|
2058
2261
|
"div",
|
|
2059
2262
|
{
|
|
2060
2263
|
ref: scrollRef,
|
|
2061
2264
|
onScroll: handleScroll,
|
|
2062
2265
|
className: "flex-1 overflow-y-auto p-4 space-y-1",
|
|
2063
|
-
children: logs.length === 0 && !error ? /* @__PURE__ */
|
|
2064
|
-
/* @__PURE__ */
|
|
2266
|
+
children: logs.length === 0 && !error ? /* @__PURE__ */ jsx18("div", { className: "flex h-full items-center justify-center text-muted-foreground italic", children: "Waiting for orchestrator logs..." }) : logs.map((log, i) => /* @__PURE__ */ jsxs17("div", { className: "break-words", children: [
|
|
2267
|
+
/* @__PURE__ */ jsxs17("span", { className: "text-muted-foreground mr-3 select-none", children: [
|
|
2065
2268
|
"[",
|
|
2066
2269
|
log.timestamp || i.toString().padStart(4, "0"),
|
|
2067
2270
|
"]"
|
|
2068
2271
|
] }),
|
|
2069
|
-
/* @__PURE__ */
|
|
2272
|
+
/* @__PURE__ */ jsxs17("span", { className: "text-primary/70 mr-2", children: [
|
|
2070
2273
|
"[",
|
|
2071
2274
|
log.level,
|
|
2072
2275
|
"]"
|
|
2073
2276
|
] }),
|
|
2074
|
-
/* @__PURE__ */
|
|
2277
|
+
/* @__PURE__ */ jsxs17("span", { className: "text-muted-foreground mr-2", children: [
|
|
2075
2278
|
"[",
|
|
2076
2279
|
log.scope,
|
|
2077
2280
|
"]"
|
|
2078
2281
|
] }),
|
|
2079
|
-
/* @__PURE__ */
|
|
2282
|
+
/* @__PURE__ */ jsx18("span", { className: log.level.toUpperCase() === "ERROR" || log.message.toLowerCase().includes("failed") ? "text-destructive" : log.level.toUpperCase() === "WARN" ? "text-warning" : "text-foreground", children: log.message })
|
|
2080
2283
|
] }, `${log.timestamp}-${log.scope}-${i}`))
|
|
2081
2284
|
}
|
|
2082
2285
|
)
|
|
@@ -2086,51 +2289,51 @@ function SystemLogsViewer({ apiUrl, token, className }) {
|
|
|
2086
2289
|
// src/dashboard/usage-summary.tsx
|
|
2087
2290
|
import { Clock as Clock4, Layers, MessageSquare, DollarSign } from "lucide-react";
|
|
2088
2291
|
import { StatCard } from "@tangle-network/ui/primitives";
|
|
2089
|
-
import { Skeleton as
|
|
2090
|
-
import { jsx as
|
|
2292
|
+
import { Skeleton as Skeleton4 } from "@tangle-network/ui/primitives";
|
|
2293
|
+
import { jsx as jsx19, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
2091
2294
|
function UsageSummary({ data, loading = false, className }) {
|
|
2092
2295
|
if (loading || !data) {
|
|
2093
|
-
return /* @__PURE__ */
|
|
2296
|
+
return /* @__PURE__ */ jsx19("div", { className: cn("grid grid-cols-2 gap-4 lg:grid-cols-4", className), children: Array.from({ length: 4 }).map((_, i) => /* @__PURE__ */ jsx19(Skeleton4, { className: "h-28 rounded-xl" }, i)) });
|
|
2094
2297
|
}
|
|
2095
|
-
return /* @__PURE__ */
|
|
2096
|
-
/* @__PURE__ */
|
|
2298
|
+
return /* @__PURE__ */ jsxs18("div", { className: cn("grid grid-cols-2 gap-4 lg:grid-cols-4", className), children: [
|
|
2299
|
+
/* @__PURE__ */ jsx19(
|
|
2097
2300
|
StatCard,
|
|
2098
2301
|
{
|
|
2099
2302
|
variant: "sandbox",
|
|
2100
2303
|
title: "Compute Hours",
|
|
2101
2304
|
value: data.computeHours.toFixed(1),
|
|
2102
2305
|
subtitle: "This billing period",
|
|
2103
|
-
icon: /* @__PURE__ */
|
|
2306
|
+
icon: /* @__PURE__ */ jsx19(Clock4, { className: "h-5 w-5" })
|
|
2104
2307
|
}
|
|
2105
2308
|
),
|
|
2106
|
-
/* @__PURE__ */
|
|
2309
|
+
/* @__PURE__ */ jsx19(
|
|
2107
2310
|
StatCard,
|
|
2108
2311
|
{
|
|
2109
2312
|
variant: "sandbox",
|
|
2110
2313
|
title: "Active Sessions",
|
|
2111
2314
|
value: data.activeSessions,
|
|
2112
2315
|
subtitle: "Currently running",
|
|
2113
|
-
icon: /* @__PURE__ */
|
|
2316
|
+
icon: /* @__PURE__ */ jsx19(Layers, { className: "h-5 w-5" })
|
|
2114
2317
|
}
|
|
2115
2318
|
),
|
|
2116
|
-
/* @__PURE__ */
|
|
2319
|
+
/* @__PURE__ */ jsx19(
|
|
2117
2320
|
StatCard,
|
|
2118
2321
|
{
|
|
2119
2322
|
variant: "sandbox",
|
|
2120
2323
|
title: "Messages Sent",
|
|
2121
2324
|
value: data.messagesSent.toLocaleString(),
|
|
2122
2325
|
subtitle: "Agent interactions",
|
|
2123
|
-
icon: /* @__PURE__ */
|
|
2326
|
+
icon: /* @__PURE__ */ jsx19(MessageSquare, { className: "h-5 w-5" })
|
|
2124
2327
|
}
|
|
2125
2328
|
),
|
|
2126
|
-
/* @__PURE__ */
|
|
2329
|
+
/* @__PURE__ */ jsx19(
|
|
2127
2330
|
StatCard,
|
|
2128
2331
|
{
|
|
2129
2332
|
variant: "sandbox",
|
|
2130
2333
|
title: "Estimated Cost",
|
|
2131
2334
|
value: `$${data.estimatedCost.toFixed(2)}`,
|
|
2132
2335
|
subtitle: "This billing period",
|
|
2133
|
-
icon: /* @__PURE__ */
|
|
2336
|
+
icon: /* @__PURE__ */ jsx19(DollarSign, { className: "h-5 w-5" })
|
|
2134
2337
|
}
|
|
2135
2338
|
)
|
|
2136
2339
|
] });
|
|
@@ -2138,66 +2341,66 @@ function UsageSummary({ data, loading = false, className }) {
|
|
|
2138
2341
|
|
|
2139
2342
|
// src/dashboard/git-panel.tsx
|
|
2140
2343
|
import { GitBranch, GitCommit, FileEdit, FilePlus, File } from "lucide-react";
|
|
2141
|
-
import { jsx as
|
|
2344
|
+
import { jsx as jsx20, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
2142
2345
|
function GitPanel({ status, log, loading = false, onRefresh, className }) {
|
|
2143
2346
|
if (loading) {
|
|
2144
|
-
return /* @__PURE__ */
|
|
2145
|
-
/* @__PURE__ */
|
|
2347
|
+
return /* @__PURE__ */ jsx20("div", { className: cn("rounded-lg border border-border bg-card p-5", className), children: /* @__PURE__ */ jsxs19("div", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: [
|
|
2348
|
+
/* @__PURE__ */ jsx20("div", { className: "h-4 w-4 animate-spin rounded-full border-2 border-primary border-t-transparent" }),
|
|
2146
2349
|
"Loading git info..."
|
|
2147
2350
|
] }) });
|
|
2148
2351
|
}
|
|
2149
2352
|
if (!status) {
|
|
2150
|
-
return /* @__PURE__ */
|
|
2151
|
-
/* @__PURE__ */
|
|
2353
|
+
return /* @__PURE__ */ jsx20("div", { className: cn("rounded-lg border border-border bg-card p-5", className), children: /* @__PURE__ */ jsxs19("div", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: [
|
|
2354
|
+
/* @__PURE__ */ jsx20(GitBranch, { className: "h-4 w-4" }),
|
|
2152
2355
|
"No git repository detected"
|
|
2153
2356
|
] }) });
|
|
2154
2357
|
}
|
|
2155
2358
|
const changedCount = status.staged.length + status.modified.length + status.untracked.length;
|
|
2156
|
-
return /* @__PURE__ */
|
|
2157
|
-
/* @__PURE__ */
|
|
2158
|
-
/* @__PURE__ */
|
|
2159
|
-
/* @__PURE__ */
|
|
2160
|
-
/* @__PURE__ */
|
|
2161
|
-
status.isDirty && /* @__PURE__ */
|
|
2359
|
+
return /* @__PURE__ */ jsxs19("div", { className: cn("rounded-lg border border-border bg-card overflow-hidden", className), children: [
|
|
2360
|
+
/* @__PURE__ */ jsxs19("div", { className: "flex items-center justify-between border-b border-border bg-muted/30 px-4 py-3", children: [
|
|
2361
|
+
/* @__PURE__ */ jsxs19("div", { className: "flex items-center gap-2", children: [
|
|
2362
|
+
/* @__PURE__ */ jsx20(GitBranch, { className: "h-4 w-4 text-primary" }),
|
|
2363
|
+
/* @__PURE__ */ jsx20("span", { className: "text-sm font-bold text-foreground", children: status.branch }),
|
|
2364
|
+
status.isDirty && /* @__PURE__ */ jsxs19("span", { className: "rounded-full bg-[var(--surface-warning-bg)] px-1.5 py-0.5 text-[10px] font-bold text-[var(--surface-warning-text)]", children: [
|
|
2162
2365
|
changedCount,
|
|
2163
2366
|
" change",
|
|
2164
2367
|
changedCount !== 1 ? "s" : ""
|
|
2165
2368
|
] })
|
|
2166
2369
|
] }),
|
|
2167
|
-
onRefresh && /* @__PURE__ */
|
|
2370
|
+
onRefresh && /* @__PURE__ */ jsx20("button", { type: "button", onClick: onRefresh, className: "text-xs text-muted-foreground hover:text-foreground transition-colors", children: "Refresh" })
|
|
2168
2371
|
] }),
|
|
2169
|
-
changedCount > 0 && /* @__PURE__ */
|
|
2170
|
-
status.staged.map((f) => /* @__PURE__ */
|
|
2171
|
-
/* @__PURE__ */
|
|
2172
|
-
/* @__PURE__ */
|
|
2173
|
-
/* @__PURE__ */
|
|
2372
|
+
changedCount > 0 && /* @__PURE__ */ jsx20("div", { className: "border-b border-border px-4 py-3", children: /* @__PURE__ */ jsxs19("div", { className: "space-y-1.5", children: [
|
|
2373
|
+
status.staged.map((f) => /* @__PURE__ */ jsxs19("div", { className: "flex items-center gap-2 text-xs", children: [
|
|
2374
|
+
/* @__PURE__ */ jsx20(FilePlus, { className: "h-3 w-3 text-[var(--surface-success-text)]" }),
|
|
2375
|
+
/* @__PURE__ */ jsx20("span", { className: "font-mono text-foreground truncate", children: f }),
|
|
2376
|
+
/* @__PURE__ */ jsx20("span", { className: "text-[var(--surface-success-text)] text-[10px] font-bold ml-auto", children: "STAGED" })
|
|
2174
2377
|
] }, `s-${f}`)),
|
|
2175
|
-
status.modified.map((f) => /* @__PURE__ */
|
|
2176
|
-
/* @__PURE__ */
|
|
2177
|
-
/* @__PURE__ */
|
|
2378
|
+
status.modified.map((f) => /* @__PURE__ */ jsxs19("div", { className: "flex items-center gap-2 text-xs", children: [
|
|
2379
|
+
/* @__PURE__ */ jsx20(FileEdit, { className: "h-3 w-3 text-[var(--surface-warning-text)]" }),
|
|
2380
|
+
/* @__PURE__ */ jsx20("span", { className: "font-mono text-foreground truncate", children: f })
|
|
2178
2381
|
] }, `m-${f}`)),
|
|
2179
|
-
status.untracked.map((f) => /* @__PURE__ */
|
|
2180
|
-
/* @__PURE__ */
|
|
2181
|
-
/* @__PURE__ */
|
|
2382
|
+
status.untracked.map((f) => /* @__PURE__ */ jsxs19("div", { className: "flex items-center gap-2 text-xs", children: [
|
|
2383
|
+
/* @__PURE__ */ jsx20(File, { className: "h-3 w-3 text-muted-foreground" }),
|
|
2384
|
+
/* @__PURE__ */ jsx20("span", { className: "font-mono text-muted-foreground truncate", children: f })
|
|
2182
2385
|
] }, `u-${f}`))
|
|
2183
2386
|
] }) }),
|
|
2184
|
-
log.length > 0 && /* @__PURE__ */
|
|
2185
|
-
/* @__PURE__ */
|
|
2186
|
-
/* @__PURE__ */
|
|
2187
|
-
/* @__PURE__ */
|
|
2188
|
-
/* @__PURE__ */
|
|
2189
|
-
/* @__PURE__ */
|
|
2190
|
-
/* @__PURE__ */
|
|
2387
|
+
log.length > 0 && /* @__PURE__ */ jsxs19("div", { className: "px-4 py-3", children: [
|
|
2388
|
+
/* @__PURE__ */ jsx20("div", { className: "mb-2 text-[10px] font-bold uppercase tracking-widest text-muted-foreground", children: "Recent Commits" }),
|
|
2389
|
+
/* @__PURE__ */ jsx20("div", { className: "space-y-2", children: log.slice(0, 5).map((commit) => /* @__PURE__ */ jsxs19("div", { className: "flex items-start gap-2 text-xs", children: [
|
|
2390
|
+
/* @__PURE__ */ jsx20(GitCommit, { className: "h-3 w-3 text-muted-foreground mt-0.5 shrink-0" }),
|
|
2391
|
+
/* @__PURE__ */ jsxs19("div", { className: "min-w-0", children: [
|
|
2392
|
+
/* @__PURE__ */ jsx20("span", { className: "font-mono text-primary mr-1.5", children: commit.shortSha }),
|
|
2393
|
+
/* @__PURE__ */ jsx20("span", { className: "text-foreground", children: commit.message })
|
|
2191
2394
|
] })
|
|
2192
2395
|
] }, commit.shortSha)) })
|
|
2193
2396
|
] }),
|
|
2194
|
-
(status.ahead > 0 || status.behind > 0) && /* @__PURE__ */
|
|
2195
|
-
status.ahead > 0 && /* @__PURE__ */
|
|
2397
|
+
(status.ahead > 0 || status.behind > 0) && /* @__PURE__ */ jsxs19("div", { className: "border-t border-border px-4 py-2 flex items-center gap-3 text-xs text-muted-foreground", children: [
|
|
2398
|
+
status.ahead > 0 && /* @__PURE__ */ jsxs19("span", { children: [
|
|
2196
2399
|
"\u2191 ",
|
|
2197
2400
|
status.ahead,
|
|
2198
2401
|
" ahead"
|
|
2199
2402
|
] }),
|
|
2200
|
-
status.behind > 0 && /* @__PURE__ */
|
|
2403
|
+
status.behind > 0 && /* @__PURE__ */ jsxs19("span", { children: [
|
|
2201
2404
|
"\u2193 ",
|
|
2202
2405
|
status.behind,
|
|
2203
2406
|
" behind"
|
|
@@ -2207,14 +2410,14 @@ function GitPanel({ status, log, loading = false, onRefresh, className }) {
|
|
|
2207
2410
|
}
|
|
2208
2411
|
|
|
2209
2412
|
// src/dashboard/ports-list.tsx
|
|
2210
|
-
import * as
|
|
2413
|
+
import * as React9 from "react";
|
|
2211
2414
|
import { Copy as Copy3, Check as Check4, Globe, Plus as Plus4, Trash2 as Trash23 } from "lucide-react";
|
|
2212
|
-
import { jsx as
|
|
2415
|
+
import { jsx as jsx21, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
2213
2416
|
function PortsList({ ports, onExposePort, onRemovePort, isExposing = false, className }) {
|
|
2214
|
-
const [newPort, setNewPort] =
|
|
2215
|
-
const [copiedPort, setCopiedPort] =
|
|
2216
|
-
const copyTimerRef =
|
|
2217
|
-
|
|
2417
|
+
const [newPort, setNewPort] = React9.useState("");
|
|
2418
|
+
const [copiedPort, setCopiedPort] = React9.useState(null);
|
|
2419
|
+
const copyTimerRef = React9.useRef(null);
|
|
2420
|
+
React9.useEffect(() => {
|
|
2218
2421
|
return () => {
|
|
2219
2422
|
if (copyTimerRef.current) clearTimeout(copyTimerRef.current);
|
|
2220
2423
|
};
|
|
@@ -2236,48 +2439,48 @@ function PortsList({ ports, onExposePort, onRemovePort, isExposing = false, clas
|
|
|
2236
2439
|
setNewPort("");
|
|
2237
2440
|
}
|
|
2238
2441
|
};
|
|
2239
|
-
return /* @__PURE__ */
|
|
2240
|
-
ports.length > 0 ? /* @__PURE__ */
|
|
2241
|
-
/* @__PURE__ */
|
|
2242
|
-
/* @__PURE__ */
|
|
2243
|
-
/* @__PURE__ */
|
|
2244
|
-
/* @__PURE__ */
|
|
2245
|
-
/* @__PURE__ */
|
|
2442
|
+
return /* @__PURE__ */ jsxs20("div", { className: cn("space-y-4", className), children: [
|
|
2443
|
+
ports.length > 0 ? /* @__PURE__ */ jsx21("div", { className: "rounded-lg border border-border overflow-hidden", children: /* @__PURE__ */ jsxs20("table", { className: "w-full text-sm", children: [
|
|
2444
|
+
/* @__PURE__ */ jsx21("thead", { className: "bg-muted/30 border-b border-border", children: /* @__PURE__ */ jsxs20("tr", { children: [
|
|
2445
|
+
/* @__PURE__ */ jsx21("th", { className: "px-4 py-2.5 text-left text-xs font-medium text-muted-foreground", children: "Port" }),
|
|
2446
|
+
/* @__PURE__ */ jsx21("th", { className: "px-4 py-2.5 text-left text-xs font-medium text-muted-foreground", children: "Public URL" }),
|
|
2447
|
+
/* @__PURE__ */ jsx21("th", { className: "px-4 py-2.5 text-left text-xs font-medium text-muted-foreground", children: "Status" }),
|
|
2448
|
+
/* @__PURE__ */ jsx21("th", { className: "px-4 py-2.5 text-right text-xs font-medium text-muted-foreground w-20" })
|
|
2246
2449
|
] }) }),
|
|
2247
|
-
/* @__PURE__ */
|
|
2248
|
-
/* @__PURE__ */
|
|
2249
|
-
/* @__PURE__ */
|
|
2450
|
+
/* @__PURE__ */ jsx21("tbody", { className: "divide-y divide-border", children: ports.map((p) => /* @__PURE__ */ jsxs20("tr", { children: [
|
|
2451
|
+
/* @__PURE__ */ jsx21("td", { className: "px-4 py-3 font-mono text-xs text-foreground", children: p.port }),
|
|
2452
|
+
/* @__PURE__ */ jsx21("td", { className: "px-4 py-3", children: /* @__PURE__ */ jsxs20(
|
|
2250
2453
|
"button",
|
|
2251
2454
|
{
|
|
2252
2455
|
type: "button",
|
|
2253
2456
|
onClick: () => handleCopy(p.url, p.port),
|
|
2254
2457
|
className: "flex items-center gap-2 font-mono text-xs text-primary hover:underline cursor-pointer group",
|
|
2255
2458
|
children: [
|
|
2256
|
-
/* @__PURE__ */
|
|
2257
|
-
copiedPort === p.port ? /* @__PURE__ */
|
|
2459
|
+
/* @__PURE__ */ jsx21("span", { className: "truncate max-w-[300px]", children: p.url }),
|
|
2460
|
+
copiedPort === p.port ? /* @__PURE__ */ jsx21(Check4, { className: "h-3 w-3 text-[var(--surface-success-text)] shrink-0" }) : /* @__PURE__ */ jsx21(Copy3, { className: "h-3 w-3 opacity-0 group-hover:opacity-100 transition-opacity shrink-0" })
|
|
2258
2461
|
]
|
|
2259
2462
|
}
|
|
2260
2463
|
) }),
|
|
2261
|
-
/* @__PURE__ */
|
|
2464
|
+
/* @__PURE__ */ jsx21("td", { className: "px-4 py-3", children: /* @__PURE__ */ jsx21("span", { className: cn(
|
|
2262
2465
|
"inline-flex items-center gap-1.5 rounded-full px-2 py-0.5 text-[10px] font-bold uppercase tracking-wider",
|
|
2263
2466
|
p.status === "active" ? "bg-[var(--surface-success-bg)] text-[var(--surface-success-text)]" : "bg-[var(--surface-warning-bg)] text-[var(--surface-warning-text)]"
|
|
2264
2467
|
), children: p.status }) }),
|
|
2265
|
-
/* @__PURE__ */
|
|
2468
|
+
/* @__PURE__ */ jsx21("td", { className: "px-4 py-3 text-right", children: onRemovePort && /* @__PURE__ */ jsx21(
|
|
2266
2469
|
"button",
|
|
2267
2470
|
{
|
|
2268
2471
|
type: "button",
|
|
2269
2472
|
onClick: () => onRemovePort(p.port),
|
|
2270
2473
|
className: "p-1 text-muted-foreground hover:text-destructive transition-colors rounded",
|
|
2271
|
-
children: /* @__PURE__ */
|
|
2474
|
+
children: /* @__PURE__ */ jsx21(Trash23, { className: "h-3.5 w-3.5" })
|
|
2272
2475
|
}
|
|
2273
2476
|
) })
|
|
2274
2477
|
] }, p.port)) })
|
|
2275
|
-
] }) }) : /* @__PURE__ */
|
|
2276
|
-
/* @__PURE__ */
|
|
2277
|
-
/* @__PURE__ */
|
|
2478
|
+
] }) }) : /* @__PURE__ */ jsxs20("div", { className: "rounded-lg border border-border bg-muted/20 p-6 text-center", children: [
|
|
2479
|
+
/* @__PURE__ */ jsx21(Globe, { className: "mx-auto h-8 w-8 text-muted-foreground mb-2" }),
|
|
2480
|
+
/* @__PURE__ */ jsx21("p", { className: "text-sm text-muted-foreground", children: "No ports exposed yet" })
|
|
2278
2481
|
] }),
|
|
2279
|
-
/* @__PURE__ */
|
|
2280
|
-
/* @__PURE__ */
|
|
2482
|
+
/* @__PURE__ */ jsxs20("div", { className: "flex items-center gap-3", children: [
|
|
2483
|
+
/* @__PURE__ */ jsx21(
|
|
2281
2484
|
"input",
|
|
2282
2485
|
{
|
|
2283
2486
|
type: "number",
|
|
@@ -2290,7 +2493,7 @@ function PortsList({ ports, onExposePort, onRemovePort, isExposing = false, clas
|
|
|
2290
2493
|
className: "flex-1 rounded-lg border border-border bg-background px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring"
|
|
2291
2494
|
}
|
|
2292
2495
|
),
|
|
2293
|
-
/* @__PURE__ */
|
|
2496
|
+
/* @__PURE__ */ jsxs20(
|
|
2294
2497
|
"button",
|
|
2295
2498
|
{
|
|
2296
2499
|
type: "button",
|
|
@@ -2298,7 +2501,7 @@ function PortsList({ ports, onExposePort, onRemovePort, isExposing = false, clas
|
|
|
2298
2501
|
disabled: !newPort || isExposing,
|
|
2299
2502
|
className: "inline-flex items-center gap-2 rounded-lg bg-primary/20 border border-primary/30 px-4 py-2 text-sm font-medium text-primary hover:bg-primary hover:text-primary-foreground transition-colors disabled:opacity-50",
|
|
2300
2503
|
children: [
|
|
2301
|
-
/* @__PURE__ */
|
|
2504
|
+
/* @__PURE__ */ jsx21(Plus4, { className: "h-4 w-4" }),
|
|
2302
2505
|
"Expose"
|
|
2303
2506
|
]
|
|
2304
2507
|
}
|
|
@@ -2308,9 +2511,9 @@ function PortsList({ ports, onExposePort, onRemovePort, isExposing = false, clas
|
|
|
2308
2511
|
}
|
|
2309
2512
|
|
|
2310
2513
|
// src/dashboard/process-list.tsx
|
|
2311
|
-
import * as
|
|
2514
|
+
import * as React10 from "react";
|
|
2312
2515
|
import { Activity as Activity3, Plus as Plus5, Skull, Terminal as Terminal4 } from "lucide-react";
|
|
2313
|
-
import { jsx as
|
|
2516
|
+
import { jsx as jsx22, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
2314
2517
|
function formatUptime(startedAt) {
|
|
2315
2518
|
if (!startedAt) return "-";
|
|
2316
2519
|
const ms = Date.now() - new Date(startedAt).getTime();
|
|
@@ -2320,7 +2523,7 @@ function formatUptime(startedAt) {
|
|
|
2320
2523
|
return `${Math.floor(ms / 36e5)}h ${Math.floor(ms % 36e5 / 6e4)}m`;
|
|
2321
2524
|
}
|
|
2322
2525
|
function ProcessList({ processes, onSpawn, onKill, loading = false, className }) {
|
|
2323
|
-
const [newCommand, setNewCommand] =
|
|
2526
|
+
const [newCommand, setNewCommand] = React10.useState("");
|
|
2324
2527
|
const handleSpawn = () => {
|
|
2325
2528
|
const cmd = newCommand.trim();
|
|
2326
2529
|
if (cmd) {
|
|
@@ -2328,43 +2531,43 @@ function ProcessList({ processes, onSpawn, onKill, loading = false, className })
|
|
|
2328
2531
|
setNewCommand("");
|
|
2329
2532
|
}
|
|
2330
2533
|
};
|
|
2331
|
-
return /* @__PURE__ */
|
|
2332
|
-
loading ? /* @__PURE__ */
|
|
2333
|
-
/* @__PURE__ */
|
|
2334
|
-
/* @__PURE__ */
|
|
2335
|
-
] }) : processes.length > 0 ? /* @__PURE__ */
|
|
2336
|
-
/* @__PURE__ */
|
|
2337
|
-
/* @__PURE__ */
|
|
2338
|
-
/* @__PURE__ */
|
|
2339
|
-
/* @__PURE__ */
|
|
2340
|
-
/* @__PURE__ */
|
|
2341
|
-
/* @__PURE__ */
|
|
2534
|
+
return /* @__PURE__ */ jsxs21("div", { className: cn("space-y-4", className), children: [
|
|
2535
|
+
loading ? /* @__PURE__ */ jsxs21("div", { className: "rounded-lg border border-border bg-muted/20 p-6 text-center", children: [
|
|
2536
|
+
/* @__PURE__ */ jsx22(Activity3, { className: "mx-auto h-6 w-6 text-muted-foreground animate-spin mb-2" }),
|
|
2537
|
+
/* @__PURE__ */ jsx22("p", { className: "text-sm text-muted-foreground", children: "Loading processes..." })
|
|
2538
|
+
] }) : processes.length > 0 ? /* @__PURE__ */ jsx22("div", { className: "rounded-lg border border-border overflow-hidden", children: /* @__PURE__ */ jsxs21("table", { className: "w-full text-sm", children: [
|
|
2539
|
+
/* @__PURE__ */ jsx22("thead", { className: "bg-muted/30 border-b border-border", children: /* @__PURE__ */ jsxs21("tr", { children: [
|
|
2540
|
+
/* @__PURE__ */ jsx22("th", { className: "px-4 py-2.5 text-left text-xs font-medium text-muted-foreground", children: "PID" }),
|
|
2541
|
+
/* @__PURE__ */ jsx22("th", { className: "px-4 py-2.5 text-left text-xs font-medium text-muted-foreground", children: "Command" }),
|
|
2542
|
+
/* @__PURE__ */ jsx22("th", { className: "px-4 py-2.5 text-left text-xs font-medium text-muted-foreground", children: "Status" }),
|
|
2543
|
+
/* @__PURE__ */ jsx22("th", { className: "px-4 py-2.5 text-left text-xs font-medium text-muted-foreground", children: "Uptime" }),
|
|
2544
|
+
/* @__PURE__ */ jsx22("th", { className: "px-4 py-2.5 text-right text-xs font-medium text-muted-foreground w-20" })
|
|
2342
2545
|
] }) }),
|
|
2343
|
-
/* @__PURE__ */
|
|
2344
|
-
/* @__PURE__ */
|
|
2345
|
-
/* @__PURE__ */
|
|
2346
|
-
/* @__PURE__ */
|
|
2546
|
+
/* @__PURE__ */ jsx22("tbody", { className: "divide-y divide-border", children: processes.map((p) => /* @__PURE__ */ jsxs21("tr", { children: [
|
|
2547
|
+
/* @__PURE__ */ jsx22("td", { className: "px-4 py-3 font-mono text-xs text-foreground", children: p.pid }),
|
|
2548
|
+
/* @__PURE__ */ jsx22("td", { className: "px-4 py-3 font-mono text-xs text-foreground truncate max-w-[250px]", children: p.command }),
|
|
2549
|
+
/* @__PURE__ */ jsx22("td", { className: "px-4 py-3", children: /* @__PURE__ */ jsx22("span", { className: cn(
|
|
2347
2550
|
"inline-flex items-center gap-1.5 rounded-full px-2 py-0.5 text-[10px] font-bold uppercase tracking-wider",
|
|
2348
2551
|
p.running ? "bg-[var(--surface-success-bg)] text-[var(--surface-success-text)]" : "bg-muted text-muted-foreground"
|
|
2349
2552
|
), children: p.running ? "running" : `exited (${p.exitCode ?? "?"})` }) }),
|
|
2350
|
-
/* @__PURE__ */
|
|
2351
|
-
/* @__PURE__ */
|
|
2553
|
+
/* @__PURE__ */ jsx22("td", { className: "px-4 py-3 font-mono text-xs text-muted-foreground", children: formatUptime(p.startedAt) }),
|
|
2554
|
+
/* @__PURE__ */ jsx22("td", { className: "px-4 py-3 text-right", children: p.running && /* @__PURE__ */ jsx22(
|
|
2352
2555
|
"button",
|
|
2353
2556
|
{
|
|
2354
2557
|
type: "button",
|
|
2355
2558
|
onClick: () => onKill(p.pid),
|
|
2356
2559
|
className: "p-1 text-muted-foreground hover:text-destructive transition-colors rounded",
|
|
2357
2560
|
title: "Kill process",
|
|
2358
|
-
children: /* @__PURE__ */
|
|
2561
|
+
children: /* @__PURE__ */ jsx22(Skull, { className: "h-3.5 w-3.5" })
|
|
2359
2562
|
}
|
|
2360
2563
|
) })
|
|
2361
2564
|
] }, `${p.pid}-${p.startedAt ?? p.command}`)) })
|
|
2362
|
-
] }) }) : /* @__PURE__ */
|
|
2363
|
-
/* @__PURE__ */
|
|
2364
|
-
/* @__PURE__ */
|
|
2565
|
+
] }) }) : /* @__PURE__ */ jsxs21("div", { className: "rounded-lg border border-border bg-muted/20 p-6 text-center", children: [
|
|
2566
|
+
/* @__PURE__ */ jsx22(Terminal4, { className: "mx-auto h-8 w-8 text-muted-foreground mb-2" }),
|
|
2567
|
+
/* @__PURE__ */ jsx22("p", { className: "text-sm text-muted-foreground", children: "No processes running" })
|
|
2365
2568
|
] }),
|
|
2366
|
-
/* @__PURE__ */
|
|
2367
|
-
/* @__PURE__ */
|
|
2569
|
+
/* @__PURE__ */ jsxs21("div", { className: "flex items-center gap-3", children: [
|
|
2570
|
+
/* @__PURE__ */ jsx22(
|
|
2368
2571
|
"input",
|
|
2369
2572
|
{
|
|
2370
2573
|
type: "text",
|
|
@@ -2375,7 +2578,7 @@ function ProcessList({ processes, onSpawn, onKill, loading = false, className })
|
|
|
2375
2578
|
className: "flex-1 rounded-lg border border-border bg-background px-3 py-2 text-sm font-mono text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring"
|
|
2376
2579
|
}
|
|
2377
2580
|
),
|
|
2378
|
-
/* @__PURE__ */
|
|
2581
|
+
/* @__PURE__ */ jsxs21(
|
|
2379
2582
|
"button",
|
|
2380
2583
|
{
|
|
2381
2584
|
type: "button",
|
|
@@ -2383,7 +2586,7 @@ function ProcessList({ processes, onSpawn, onKill, loading = false, className })
|
|
|
2383
2586
|
disabled: !newCommand.trim(),
|
|
2384
2587
|
className: "inline-flex items-center gap-2 rounded-lg bg-primary/20 border border-primary/30 px-4 py-2 text-sm font-medium text-primary hover:bg-primary hover:text-primary-foreground transition-colors disabled:opacity-50",
|
|
2385
2588
|
children: [
|
|
2386
|
-
/* @__PURE__ */
|
|
2589
|
+
/* @__PURE__ */ jsx22(Plus5, { className: "h-4 w-4" }),
|
|
2387
2590
|
"Spawn"
|
|
2388
2591
|
]
|
|
2389
2592
|
}
|
|
@@ -2393,11 +2596,11 @@ function ProcessList({ processes, onSpawn, onKill, loading = false, className })
|
|
|
2393
2596
|
}
|
|
2394
2597
|
|
|
2395
2598
|
// src/dashboard/network-config.tsx
|
|
2396
|
-
import * as
|
|
2599
|
+
import * as React11 from "react";
|
|
2397
2600
|
import { Network as Network2, Plus as Plus6, Trash2 as Trash24, ShieldAlert } from "lucide-react";
|
|
2398
|
-
import { jsx as
|
|
2601
|
+
import { jsx as jsx23, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
2399
2602
|
function NetworkConfig({ config, onUpdate, loading = false, className }) {
|
|
2400
|
-
const [newCidr, setNewCidr] =
|
|
2603
|
+
const [newCidr, setNewCidr] = React11.useState("");
|
|
2401
2604
|
const isValidCidr = (value) => {
|
|
2402
2605
|
const match = value.match(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\/(\d{1,2})$/);
|
|
2403
2606
|
if (!match) return false;
|
|
@@ -2418,21 +2621,21 @@ function NetworkConfig({ config, onUpdate, loading = false, className }) {
|
|
|
2418
2621
|
}
|
|
2419
2622
|
};
|
|
2420
2623
|
if (loading || !config) {
|
|
2421
|
-
return /* @__PURE__ */
|
|
2422
|
-
/* @__PURE__ */
|
|
2423
|
-
/* @__PURE__ */
|
|
2624
|
+
return /* @__PURE__ */ jsxs22("div", { className: cn("rounded-lg border border-border bg-muted/20 p-6 text-center", className), children: [
|
|
2625
|
+
/* @__PURE__ */ jsx23(Network2, { className: "mx-auto h-6 w-6 text-muted-foreground animate-pulse mb-2" }),
|
|
2626
|
+
/* @__PURE__ */ jsx23("p", { className: "text-sm text-muted-foreground", children: "Loading network configuration..." })
|
|
2424
2627
|
] });
|
|
2425
2628
|
}
|
|
2426
|
-
return /* @__PURE__ */
|
|
2427
|
-
/* @__PURE__ */
|
|
2428
|
-
/* @__PURE__ */
|
|
2429
|
-
/* @__PURE__ */
|
|
2430
|
-
/* @__PURE__ */
|
|
2431
|
-
/* @__PURE__ */
|
|
2432
|
-
/* @__PURE__ */
|
|
2629
|
+
return /* @__PURE__ */ jsxs22("div", { className: cn("space-y-4", className), children: [
|
|
2630
|
+
/* @__PURE__ */ jsxs22("div", { className: "flex items-center justify-between rounded-lg border border-border bg-card px-4 py-3", children: [
|
|
2631
|
+
/* @__PURE__ */ jsxs22("div", { className: "flex items-center gap-3", children: [
|
|
2632
|
+
/* @__PURE__ */ jsx23(ShieldAlert, { className: "h-4 w-4 text-muted-foreground" }),
|
|
2633
|
+
/* @__PURE__ */ jsxs22("div", { children: [
|
|
2634
|
+
/* @__PURE__ */ jsx23("p", { className: "text-sm font-medium text-foreground", children: "Block Outbound Traffic" }),
|
|
2635
|
+
/* @__PURE__ */ jsx23("p", { className: "text-xs text-muted-foreground", children: "Prevent the sandbox from making external network requests" })
|
|
2433
2636
|
] })
|
|
2434
2637
|
] }),
|
|
2435
|
-
/* @__PURE__ */
|
|
2638
|
+
/* @__PURE__ */ jsx23(
|
|
2436
2639
|
"button",
|
|
2437
2640
|
{
|
|
2438
2641
|
type: "button",
|
|
@@ -2444,7 +2647,7 @@ function NetworkConfig({ config, onUpdate, loading = false, className }) {
|
|
|
2444
2647
|
"relative inline-flex h-6 w-11 items-center rounded-full transition-colors",
|
|
2445
2648
|
config.blockOutbound ? "bg-destructive" : "bg-muted"
|
|
2446
2649
|
),
|
|
2447
|
-
children: /* @__PURE__ */
|
|
2650
|
+
children: /* @__PURE__ */ jsx23(
|
|
2448
2651
|
"span",
|
|
2449
2652
|
{
|
|
2450
2653
|
className: cn(
|
|
@@ -2456,22 +2659,22 @@ function NetworkConfig({ config, onUpdate, loading = false, className }) {
|
|
|
2456
2659
|
}
|
|
2457
2660
|
)
|
|
2458
2661
|
] }),
|
|
2459
|
-
/* @__PURE__ */
|
|
2460
|
-
/* @__PURE__ */
|
|
2461
|
-
config.allowList.length > 0 ? /* @__PURE__ */
|
|
2462
|
-
/* @__PURE__ */
|
|
2463
|
-
/* @__PURE__ */
|
|
2662
|
+
/* @__PURE__ */ jsxs22("div", { children: [
|
|
2663
|
+
/* @__PURE__ */ jsx23("h4", { className: "text-xs font-medium text-muted-foreground mb-2 uppercase tracking-wider", children: "Allowlist (CIDR)" }),
|
|
2664
|
+
config.allowList.length > 0 ? /* @__PURE__ */ jsx23("div", { className: "space-y-1.5 mb-3", children: config.allowList.map((cidr) => /* @__PURE__ */ jsxs22("div", { className: "flex items-center justify-between rounded border border-border bg-muted/20 px-3 py-2", children: [
|
|
2665
|
+
/* @__PURE__ */ jsx23("span", { className: "font-mono text-xs text-foreground", children: cidr }),
|
|
2666
|
+
/* @__PURE__ */ jsx23(
|
|
2464
2667
|
"button",
|
|
2465
2668
|
{
|
|
2466
2669
|
type: "button",
|
|
2467
2670
|
onClick: () => handleRemoveCidr(cidr),
|
|
2468
2671
|
className: "p-1 text-muted-foreground hover:text-destructive transition-colors rounded",
|
|
2469
|
-
children: /* @__PURE__ */
|
|
2672
|
+
children: /* @__PURE__ */ jsx23(Trash24, { className: "h-3 w-3" })
|
|
2470
2673
|
}
|
|
2471
2674
|
)
|
|
2472
|
-
] }, cidr)) }) : /* @__PURE__ */
|
|
2473
|
-
/* @__PURE__ */
|
|
2474
|
-
/* @__PURE__ */
|
|
2675
|
+
] }, cidr)) }) : /* @__PURE__ */ jsx23("p", { className: "text-xs text-muted-foreground mb-3", children: "No CIDR rules configured. All traffic is allowed." }),
|
|
2676
|
+
/* @__PURE__ */ jsxs22("div", { className: "flex items-center gap-3", children: [
|
|
2677
|
+
/* @__PURE__ */ jsx23(
|
|
2475
2678
|
"input",
|
|
2476
2679
|
{
|
|
2477
2680
|
type: "text",
|
|
@@ -2482,7 +2685,7 @@ function NetworkConfig({ config, onUpdate, loading = false, className }) {
|
|
|
2482
2685
|
className: "flex-1 rounded-lg border border-border bg-background px-3 py-2 text-sm font-mono text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring"
|
|
2483
2686
|
}
|
|
2484
2687
|
),
|
|
2485
|
-
/* @__PURE__ */
|
|
2688
|
+
/* @__PURE__ */ jsxs22(
|
|
2486
2689
|
"button",
|
|
2487
2690
|
{
|
|
2488
2691
|
type: "button",
|
|
@@ -2490,7 +2693,7 @@ function NetworkConfig({ config, onUpdate, loading = false, className }) {
|
|
|
2490
2693
|
disabled: !newCidr.trim(),
|
|
2491
2694
|
className: "inline-flex items-center gap-2 rounded-lg bg-primary/20 border border-primary/30 px-4 py-2 text-sm font-medium text-primary hover:bg-primary hover:text-primary-foreground transition-colors disabled:opacity-50",
|
|
2492
2695
|
children: [
|
|
2493
|
-
/* @__PURE__ */
|
|
2696
|
+
/* @__PURE__ */ jsx23(Plus6, { className: "h-4 w-4" }),
|
|
2494
2697
|
"Add"
|
|
2495
2698
|
]
|
|
2496
2699
|
}
|
|
@@ -2501,9 +2704,9 @@ function NetworkConfig({ config, onUpdate, loading = false, className }) {
|
|
|
2501
2704
|
}
|
|
2502
2705
|
|
|
2503
2706
|
// src/dashboard/backend-config.tsx
|
|
2504
|
-
import * as
|
|
2707
|
+
import * as React12 from "react";
|
|
2505
2708
|
import { Bot, Plus as Plus7, RefreshCw as RefreshCw2, Trash2 as Trash25, Server, Wrench } from "lucide-react";
|
|
2506
|
-
import { Fragment as Fragment11, jsx as
|
|
2709
|
+
import { Fragment as Fragment11, jsx as jsx24, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
2507
2710
|
function BackendConfig({
|
|
2508
2711
|
status,
|
|
2509
2712
|
mcpServers,
|
|
@@ -2513,10 +2716,10 @@ function BackendConfig({
|
|
|
2513
2716
|
loading = false,
|
|
2514
2717
|
className
|
|
2515
2718
|
}) {
|
|
2516
|
-
const [showAddMcp, setShowAddMcp] =
|
|
2517
|
-
const [mcpName, setMcpName] =
|
|
2518
|
-
const [mcpCommand, setMcpCommand] =
|
|
2519
|
-
const [mcpArgs, setMcpArgs] =
|
|
2719
|
+
const [showAddMcp, setShowAddMcp] = React12.useState(false);
|
|
2720
|
+
const [mcpName, setMcpName] = React12.useState("");
|
|
2721
|
+
const [mcpCommand, setMcpCommand] = React12.useState("");
|
|
2722
|
+
const [mcpArgs, setMcpArgs] = React12.useState("");
|
|
2520
2723
|
const handleAddMcp = () => {
|
|
2521
2724
|
const name = mcpName.trim();
|
|
2522
2725
|
const command = mcpCommand.trim();
|
|
@@ -2533,91 +2736,91 @@ function BackendConfig({
|
|
|
2533
2736
|
}
|
|
2534
2737
|
};
|
|
2535
2738
|
if (loading || !status) {
|
|
2536
|
-
return /* @__PURE__ */
|
|
2537
|
-
/* @__PURE__ */
|
|
2538
|
-
/* @__PURE__ */
|
|
2739
|
+
return /* @__PURE__ */ jsxs23("div", { className: cn("rounded-lg border border-border bg-muted/20 p-6 text-center", className), children: [
|
|
2740
|
+
/* @__PURE__ */ jsx24(Bot, { className: "mx-auto h-6 w-6 text-muted-foreground animate-pulse mb-2" }),
|
|
2741
|
+
/* @__PURE__ */ jsx24("p", { className: "text-sm text-muted-foreground", children: "Loading backend status..." })
|
|
2539
2742
|
] });
|
|
2540
2743
|
}
|
|
2541
|
-
return /* @__PURE__ */
|
|
2542
|
-
/* @__PURE__ */
|
|
2543
|
-
/* @__PURE__ */
|
|
2544
|
-
/* @__PURE__ */
|
|
2545
|
-
/* @__PURE__ */
|
|
2744
|
+
return /* @__PURE__ */ jsxs23("div", { className: cn("space-y-4", className), children: [
|
|
2745
|
+
/* @__PURE__ */ jsxs23("div", { className: "rounded-lg border border-border bg-card overflow-hidden", children: [
|
|
2746
|
+
/* @__PURE__ */ jsxs23("div", { className: "px-4 py-3 border-b border-border bg-muted/30 flex items-center justify-between", children: [
|
|
2747
|
+
/* @__PURE__ */ jsx24("h4", { className: "text-xs font-medium text-muted-foreground uppercase tracking-wider", children: "Agent Status" }),
|
|
2748
|
+
/* @__PURE__ */ jsxs23(
|
|
2546
2749
|
"button",
|
|
2547
2750
|
{
|
|
2548
2751
|
type: "button",
|
|
2549
2752
|
onClick: onRestart,
|
|
2550
2753
|
className: "inline-flex items-center gap-1.5 rounded-md bg-muted px-2.5 py-1 text-xs font-medium text-foreground hover:bg-muted/80 transition-colors border border-border",
|
|
2551
2754
|
children: [
|
|
2552
|
-
/* @__PURE__ */
|
|
2755
|
+
/* @__PURE__ */ jsx24(RefreshCw2, { className: "h-3 w-3" }),
|
|
2553
2756
|
"Restart"
|
|
2554
2757
|
]
|
|
2555
2758
|
}
|
|
2556
2759
|
)
|
|
2557
2760
|
] }),
|
|
2558
|
-
/* @__PURE__ */
|
|
2559
|
-
/* @__PURE__ */
|
|
2560
|
-
/* @__PURE__ */
|
|
2761
|
+
/* @__PURE__ */ jsx24("div", { className: "p-4", children: /* @__PURE__ */ jsxs23("dl", { className: "grid grid-cols-[100px_1fr] gap-y-3 text-sm", children: [
|
|
2762
|
+
/* @__PURE__ */ jsx24("dt", { className: "text-muted-foreground", children: "Status" }),
|
|
2763
|
+
/* @__PURE__ */ jsx24("dd", { children: /* @__PURE__ */ jsx24("span", { className: cn(
|
|
2561
2764
|
"inline-flex items-center gap-1.5 rounded-full px-2 py-0.5 text-[10px] font-bold uppercase tracking-wider",
|
|
2562
2765
|
status.running ? "bg-[var(--surface-success-bg)] text-[var(--surface-success-text)]" : "bg-destructive/10 text-destructive"
|
|
2563
2766
|
), children: status.running ? "Running" : "Stopped" }) }),
|
|
2564
|
-
/* @__PURE__ */
|
|
2565
|
-
/* @__PURE__ */
|
|
2566
|
-
status.provider && /* @__PURE__ */
|
|
2567
|
-
/* @__PURE__ */
|
|
2568
|
-
/* @__PURE__ */
|
|
2767
|
+
/* @__PURE__ */ jsx24("dt", { className: "text-muted-foreground", children: "Model" }),
|
|
2768
|
+
/* @__PURE__ */ jsx24("dd", { className: "font-mono text-xs", children: status.model ?? "Default" }),
|
|
2769
|
+
status.provider && /* @__PURE__ */ jsxs23(Fragment11, { children: [
|
|
2770
|
+
/* @__PURE__ */ jsx24("dt", { className: "text-muted-foreground", children: "Provider" }),
|
|
2771
|
+
/* @__PURE__ */ jsx24("dd", { className: "font-mono text-xs", children: status.provider })
|
|
2569
2772
|
] })
|
|
2570
2773
|
] }) })
|
|
2571
2774
|
] }),
|
|
2572
|
-
/* @__PURE__ */
|
|
2573
|
-
/* @__PURE__ */
|
|
2574
|
-
/* @__PURE__ */
|
|
2575
|
-
/* @__PURE__ */
|
|
2775
|
+
/* @__PURE__ */ jsxs23("div", { className: "rounded-lg border border-border bg-card overflow-hidden", children: [
|
|
2776
|
+
/* @__PURE__ */ jsxs23("div", { className: "px-4 py-3 border-b border-border bg-muted/30 flex items-center justify-between", children: [
|
|
2777
|
+
/* @__PURE__ */ jsxs23("h4", { className: "text-xs font-medium text-muted-foreground uppercase tracking-wider flex items-center gap-2", children: [
|
|
2778
|
+
/* @__PURE__ */ jsx24(Wrench, { className: "h-3.5 w-3.5" }),
|
|
2576
2779
|
"MCP Servers"
|
|
2577
2780
|
] }),
|
|
2578
|
-
/* @__PURE__ */
|
|
2781
|
+
/* @__PURE__ */ jsxs23(
|
|
2579
2782
|
"button",
|
|
2580
2783
|
{
|
|
2581
2784
|
type: "button",
|
|
2582
2785
|
onClick: () => setShowAddMcp(!showAddMcp),
|
|
2583
2786
|
className: "inline-flex items-center gap-1.5 rounded-md bg-primary/20 border border-primary/30 px-2.5 py-1 text-xs font-medium text-primary hover:bg-primary hover:text-primary-foreground transition-colors",
|
|
2584
2787
|
children: [
|
|
2585
|
-
/* @__PURE__ */
|
|
2788
|
+
/* @__PURE__ */ jsx24(Plus7, { className: "h-3 w-3" }),
|
|
2586
2789
|
"Add"
|
|
2587
2790
|
]
|
|
2588
2791
|
}
|
|
2589
2792
|
)
|
|
2590
2793
|
] }),
|
|
2591
|
-
mcpServers.length > 0 ? /* @__PURE__ */
|
|
2592
|
-
/* @__PURE__ */
|
|
2593
|
-
/* @__PURE__ */
|
|
2594
|
-
/* @__PURE__ */
|
|
2595
|
-
/* @__PURE__ */
|
|
2596
|
-
/* @__PURE__ */
|
|
2794
|
+
mcpServers.length > 0 ? /* @__PURE__ */ jsx24("div", { className: "divide-y divide-border", children: mcpServers.map((s) => /* @__PURE__ */ jsxs23("div", { className: "flex items-center justify-between px-4 py-3", children: [
|
|
2795
|
+
/* @__PURE__ */ jsxs23("div", { className: "flex items-center gap-3 min-w-0", children: [
|
|
2796
|
+
/* @__PURE__ */ jsx24(Server, { className: "h-3.5 w-3.5 text-muted-foreground shrink-0" }),
|
|
2797
|
+
/* @__PURE__ */ jsxs23("div", { className: "min-w-0", children: [
|
|
2798
|
+
/* @__PURE__ */ jsx24("p", { className: "text-sm font-medium text-foreground truncate", children: s.name }),
|
|
2799
|
+
/* @__PURE__ */ jsxs23("p", { className: "text-xs font-mono text-muted-foreground truncate", children: [
|
|
2597
2800
|
s.command,
|
|
2598
2801
|
" ",
|
|
2599
2802
|
s.args?.join(" ") ?? ""
|
|
2600
2803
|
] })
|
|
2601
2804
|
] })
|
|
2602
2805
|
] }),
|
|
2603
|
-
/* @__PURE__ */
|
|
2604
|
-
s.status && /* @__PURE__ */
|
|
2806
|
+
/* @__PURE__ */ jsxs23("div", { className: "flex items-center gap-2 shrink-0", children: [
|
|
2807
|
+
s.status && /* @__PURE__ */ jsx24("span", { className: cn(
|
|
2605
2808
|
"inline-flex items-center rounded-full px-1.5 py-0.5 text-[9px] font-bold uppercase",
|
|
2606
2809
|
s.status === "running" ? "bg-[var(--surface-success-bg)] text-[var(--surface-success-text)]" : s.status === "error" ? "bg-destructive/10 text-destructive" : "bg-muted text-muted-foreground"
|
|
2607
2810
|
), children: s.status }),
|
|
2608
|
-
/* @__PURE__ */
|
|
2811
|
+
/* @__PURE__ */ jsx24(
|
|
2609
2812
|
"button",
|
|
2610
2813
|
{
|
|
2611
2814
|
type: "button",
|
|
2612
2815
|
onClick: () => onRemoveMcp(s.name),
|
|
2613
2816
|
className: "p-1 text-muted-foreground hover:text-destructive transition-colors rounded",
|
|
2614
|
-
children: /* @__PURE__ */
|
|
2817
|
+
children: /* @__PURE__ */ jsx24(Trash25, { className: "h-3.5 w-3.5" })
|
|
2615
2818
|
}
|
|
2616
2819
|
)
|
|
2617
2820
|
] })
|
|
2618
|
-
] }, s.name)) }) : /* @__PURE__ */
|
|
2619
|
-
showAddMcp && /* @__PURE__ */
|
|
2620
|
-
/* @__PURE__ */
|
|
2821
|
+
] }, s.name)) }) : /* @__PURE__ */ jsx24("div", { className: "p-4 text-center", children: /* @__PURE__ */ jsx24("p", { className: "text-xs text-muted-foreground", children: "No MCP servers configured" }) }),
|
|
2822
|
+
showAddMcp && /* @__PURE__ */ jsxs23("div", { className: "p-4 border-t border-border bg-muted/10 space-y-2", children: [
|
|
2823
|
+
/* @__PURE__ */ jsx24(
|
|
2621
2824
|
"input",
|
|
2622
2825
|
{
|
|
2623
2826
|
type: "text",
|
|
@@ -2627,7 +2830,7 @@ function BackendConfig({
|
|
|
2627
2830
|
className: "w-full rounded-lg border border-border bg-background px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring"
|
|
2628
2831
|
}
|
|
2629
2832
|
),
|
|
2630
|
-
/* @__PURE__ */
|
|
2833
|
+
/* @__PURE__ */ jsx24(
|
|
2631
2834
|
"input",
|
|
2632
2835
|
{
|
|
2633
2836
|
type: "text",
|
|
@@ -2637,7 +2840,7 @@ function BackendConfig({
|
|
|
2637
2840
|
className: "w-full rounded-lg border border-border bg-background px-3 py-2 text-sm font-mono text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring"
|
|
2638
2841
|
}
|
|
2639
2842
|
),
|
|
2640
|
-
/* @__PURE__ */
|
|
2843
|
+
/* @__PURE__ */ jsx24(
|
|
2641
2844
|
"input",
|
|
2642
2845
|
{
|
|
2643
2846
|
type: "text",
|
|
@@ -2647,8 +2850,8 @@ function BackendConfig({
|
|
|
2647
2850
|
className: "w-full rounded-lg border border-border bg-background px-3 py-2 text-sm font-mono text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring"
|
|
2648
2851
|
}
|
|
2649
2852
|
),
|
|
2650
|
-
/* @__PURE__ */
|
|
2651
|
-
/* @__PURE__ */
|
|
2853
|
+
/* @__PURE__ */ jsxs23("div", { className: "flex justify-end gap-2 pt-1", children: [
|
|
2854
|
+
/* @__PURE__ */ jsx24(
|
|
2652
2855
|
"button",
|
|
2653
2856
|
{
|
|
2654
2857
|
type: "button",
|
|
@@ -2657,7 +2860,7 @@ function BackendConfig({
|
|
|
2657
2860
|
children: "Cancel"
|
|
2658
2861
|
}
|
|
2659
2862
|
),
|
|
2660
|
-
/* @__PURE__ */
|
|
2863
|
+
/* @__PURE__ */ jsx24(
|
|
2661
2864
|
"button",
|
|
2662
2865
|
{
|
|
2663
2866
|
type: "button",
|
|
@@ -2674,9 +2877,9 @@ function BackendConfig({
|
|
|
2674
2877
|
}
|
|
2675
2878
|
|
|
2676
2879
|
// src/dashboard/snapshot-list.tsx
|
|
2677
|
-
import * as
|
|
2880
|
+
import * as React13 from "react";
|
|
2678
2881
|
import { Camera, Clock as Clock5, HardDrive, Plus as Plus8, RotateCcw } from "lucide-react";
|
|
2679
|
-
import { jsx as
|
|
2882
|
+
import { jsx as jsx25, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
2680
2883
|
function formatBytes(bytes) {
|
|
2681
2884
|
if (bytes == null || bytes < 0) return "-";
|
|
2682
2885
|
if (bytes === 0) return "0 B";
|
|
@@ -2691,33 +2894,33 @@ function formatDate(dateStr) {
|
|
|
2691
2894
|
return d.toLocaleDateString(void 0, { month: "short", day: "numeric", hour: "2-digit", minute: "2-digit" });
|
|
2692
2895
|
}
|
|
2693
2896
|
function SnapshotList({ snapshots, onCreate, onRestore, onSaveAsTemplate, loading = false, className }) {
|
|
2694
|
-
const [showCreate, setShowCreate] =
|
|
2695
|
-
const [tags, setTags] =
|
|
2897
|
+
const [showCreate, setShowCreate] = React13.useState(false);
|
|
2898
|
+
const [tags, setTags] = React13.useState("");
|
|
2696
2899
|
const handleCreate = () => {
|
|
2697
2900
|
const tagList = tags.trim() ? tags.trim().split(",").map((t) => t.trim()).filter(Boolean) : void 0;
|
|
2698
2901
|
onCreate(tagList);
|
|
2699
2902
|
setTags("");
|
|
2700
2903
|
setShowCreate(false);
|
|
2701
2904
|
};
|
|
2702
|
-
return /* @__PURE__ */
|
|
2703
|
-
/* @__PURE__ */
|
|
2704
|
-
/* @__PURE__ */
|
|
2705
|
-
/* @__PURE__ */
|
|
2905
|
+
return /* @__PURE__ */ jsxs24("div", { className: cn("space-y-4", className), children: [
|
|
2906
|
+
/* @__PURE__ */ jsxs24("div", { className: "flex items-center justify-between", children: [
|
|
2907
|
+
/* @__PURE__ */ jsx25("h3", { className: "text-sm font-bold text-foreground", children: "Snapshots" }),
|
|
2908
|
+
/* @__PURE__ */ jsxs24(
|
|
2706
2909
|
"button",
|
|
2707
2910
|
{
|
|
2708
2911
|
type: "button",
|
|
2709
2912
|
onClick: () => setShowCreate(!showCreate),
|
|
2710
2913
|
className: "inline-flex items-center gap-1.5 rounded-lg bg-primary/20 border border-primary/30 px-3 py-1.5 text-xs font-medium text-primary hover:bg-primary hover:text-primary-foreground transition-colors",
|
|
2711
2914
|
children: [
|
|
2712
|
-
/* @__PURE__ */
|
|
2915
|
+
/* @__PURE__ */ jsx25(Plus8, { className: "h-3.5 w-3.5" }),
|
|
2713
2916
|
"Create Snapshot"
|
|
2714
2917
|
]
|
|
2715
2918
|
}
|
|
2716
2919
|
)
|
|
2717
2920
|
] }),
|
|
2718
|
-
showCreate && /* @__PURE__ */
|
|
2719
|
-
/* @__PURE__ */
|
|
2720
|
-
/* @__PURE__ */
|
|
2921
|
+
showCreate && /* @__PURE__ */ jsxs24("div", { className: "rounded-lg border border-primary/20 bg-primary/5 p-4 space-y-3", children: [
|
|
2922
|
+
/* @__PURE__ */ jsx25("p", { className: "text-sm text-foreground font-medium", children: "Create a new snapshot of the current sandbox state." }),
|
|
2923
|
+
/* @__PURE__ */ jsx25(
|
|
2721
2924
|
"input",
|
|
2722
2925
|
{
|
|
2723
2926
|
type: "text",
|
|
@@ -2728,8 +2931,8 @@ function SnapshotList({ snapshots, onCreate, onRestore, onSaveAsTemplate, loadin
|
|
|
2728
2931
|
className: "w-full rounded-lg border border-border bg-background px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring"
|
|
2729
2932
|
}
|
|
2730
2933
|
),
|
|
2731
|
-
/* @__PURE__ */
|
|
2732
|
-
/* @__PURE__ */
|
|
2934
|
+
/* @__PURE__ */ jsxs24("div", { className: "flex justify-end gap-2", children: [
|
|
2935
|
+
/* @__PURE__ */ jsx25(
|
|
2733
2936
|
"button",
|
|
2734
2937
|
{
|
|
2735
2938
|
type: "button",
|
|
@@ -2738,44 +2941,44 @@ function SnapshotList({ snapshots, onCreate, onRestore, onSaveAsTemplate, loadin
|
|
|
2738
2941
|
children: "Cancel"
|
|
2739
2942
|
}
|
|
2740
2943
|
),
|
|
2741
|
-
/* @__PURE__ */
|
|
2944
|
+
/* @__PURE__ */ jsxs24(
|
|
2742
2945
|
"button",
|
|
2743
2946
|
{
|
|
2744
2947
|
type: "button",
|
|
2745
2948
|
onClick: handleCreate,
|
|
2746
2949
|
className: "rounded-md bg-primary px-3 py-1.5 text-xs font-medium text-primary-foreground hover:bg-primary/90 transition-colors",
|
|
2747
2950
|
children: [
|
|
2748
|
-
/* @__PURE__ */
|
|
2951
|
+
/* @__PURE__ */ jsx25(Camera, { className: "h-3 w-3 mr-1.5 inline" }),
|
|
2749
2952
|
"Create"
|
|
2750
2953
|
]
|
|
2751
2954
|
}
|
|
2752
2955
|
)
|
|
2753
2956
|
] })
|
|
2754
2957
|
] }),
|
|
2755
|
-
loading ? /* @__PURE__ */
|
|
2756
|
-
/* @__PURE__ */
|
|
2757
|
-
/* @__PURE__ */
|
|
2758
|
-
] }) : snapshots.length > 0 ? /* @__PURE__ */
|
|
2759
|
-
/* @__PURE__ */
|
|
2760
|
-
/* @__PURE__ */
|
|
2761
|
-
/* @__PURE__ */
|
|
2762
|
-
/* @__PURE__ */
|
|
2763
|
-
/* @__PURE__ */
|
|
2764
|
-
/* @__PURE__ */
|
|
2958
|
+
loading ? /* @__PURE__ */ jsxs24("div", { className: "rounded-lg border border-border bg-muted/20 p-6 text-center", children: [
|
|
2959
|
+
/* @__PURE__ */ jsx25(Camera, { className: "mx-auto h-6 w-6 text-muted-foreground animate-pulse mb-2" }),
|
|
2960
|
+
/* @__PURE__ */ jsx25("p", { className: "text-sm text-muted-foreground", children: "Loading snapshots..." })
|
|
2961
|
+
] }) : snapshots.length > 0 ? /* @__PURE__ */ jsx25("div", { className: "rounded-lg border border-border overflow-hidden", children: /* @__PURE__ */ jsxs24("table", { className: "w-full text-sm", children: [
|
|
2962
|
+
/* @__PURE__ */ jsx25("thead", { className: "bg-muted/30 border-b border-border", children: /* @__PURE__ */ jsxs24("tr", { children: [
|
|
2963
|
+
/* @__PURE__ */ jsx25("th", { className: "px-4 py-2.5 text-left text-xs font-medium text-muted-foreground", children: "ID" }),
|
|
2964
|
+
/* @__PURE__ */ jsx25("th", { className: "px-4 py-2.5 text-left text-xs font-medium text-muted-foreground", children: "Created" }),
|
|
2965
|
+
/* @__PURE__ */ jsx25("th", { className: "px-4 py-2.5 text-left text-xs font-medium text-muted-foreground", children: "Size" }),
|
|
2966
|
+
/* @__PURE__ */ jsx25("th", { className: "px-4 py-2.5 text-left text-xs font-medium text-muted-foreground", children: "Tags" }),
|
|
2967
|
+
/* @__PURE__ */ jsx25("th", { className: "px-4 py-2.5 text-right text-xs font-medium text-muted-foreground w-24" })
|
|
2765
2968
|
] }) }),
|
|
2766
|
-
/* @__PURE__ */
|
|
2767
|
-
/* @__PURE__ */
|
|
2768
|
-
/* @__PURE__ */
|
|
2769
|
-
/* @__PURE__ */
|
|
2969
|
+
/* @__PURE__ */ jsx25("tbody", { className: "divide-y divide-border", children: snapshots.map((s) => /* @__PURE__ */ jsxs24("tr", { children: [
|
|
2970
|
+
/* @__PURE__ */ jsx25("td", { className: "px-4 py-3 font-mono text-xs text-foreground", children: s.id.slice(0, 12) }),
|
|
2971
|
+
/* @__PURE__ */ jsx25("td", { className: "px-4 py-3 text-xs text-muted-foreground", children: /* @__PURE__ */ jsxs24("span", { className: "inline-flex items-center gap-1.5", children: [
|
|
2972
|
+
/* @__PURE__ */ jsx25(Clock5, { className: "h-3 w-3" }),
|
|
2770
2973
|
formatDate(s.createdAt)
|
|
2771
2974
|
] }) }),
|
|
2772
|
-
/* @__PURE__ */
|
|
2773
|
-
/* @__PURE__ */
|
|
2975
|
+
/* @__PURE__ */ jsx25("td", { className: "px-4 py-3 text-xs text-muted-foreground", children: /* @__PURE__ */ jsxs24("span", { className: "inline-flex items-center gap-1.5", children: [
|
|
2976
|
+
/* @__PURE__ */ jsx25(HardDrive, { className: "h-3 w-3" }),
|
|
2774
2977
|
formatBytes(s.sizeBytes)
|
|
2775
2978
|
] }) }),
|
|
2776
|
-
/* @__PURE__ */
|
|
2777
|
-
/* @__PURE__ */
|
|
2778
|
-
/* @__PURE__ */
|
|
2979
|
+
/* @__PURE__ */ jsx25("td", { className: "px-4 py-3", children: s.tags?.length ? /* @__PURE__ */ jsx25("div", { className: "flex items-center gap-1 flex-wrap", children: s.tags.map((tag) => /* @__PURE__ */ jsx25("span", { className: "rounded-full bg-muted px-2 py-0.5 text-[10px] font-medium text-muted-foreground border border-border", children: tag }, tag)) }) : /* @__PURE__ */ jsx25("span", { className: "text-xs text-muted-foreground", children: "-" }) }),
|
|
2980
|
+
/* @__PURE__ */ jsx25("td", { className: "px-4 py-3 text-right", children: /* @__PURE__ */ jsxs24("div", { className: "flex items-center justify-end gap-2", children: [
|
|
2981
|
+
/* @__PURE__ */ jsxs24(
|
|
2779
2982
|
"button",
|
|
2780
2983
|
{
|
|
2781
2984
|
type: "button",
|
|
@@ -2783,12 +2986,12 @@ function SnapshotList({ snapshots, onCreate, onRestore, onSaveAsTemplate, loadin
|
|
|
2783
2986
|
className: "inline-flex items-center gap-1.5 rounded-md bg-muted px-2.5 py-1 text-xs font-medium text-foreground hover:bg-muted/80 transition-colors border border-border",
|
|
2784
2987
|
title: "Restore to new sandbox",
|
|
2785
2988
|
children: [
|
|
2786
|
-
/* @__PURE__ */
|
|
2989
|
+
/* @__PURE__ */ jsx25(RotateCcw, { className: "h-3 w-3" }),
|
|
2787
2990
|
"Restore"
|
|
2788
2991
|
]
|
|
2789
2992
|
}
|
|
2790
2993
|
),
|
|
2791
|
-
onSaveAsTemplate && /* @__PURE__ */
|
|
2994
|
+
onSaveAsTemplate && /* @__PURE__ */ jsx25(
|
|
2792
2995
|
"button",
|
|
2793
2996
|
{
|
|
2794
2997
|
type: "button",
|
|
@@ -2800,16 +3003,16 @@ function SnapshotList({ snapshots, onCreate, onRestore, onSaveAsTemplate, loadin
|
|
|
2800
3003
|
)
|
|
2801
3004
|
] }) })
|
|
2802
3005
|
] }, s.id)) })
|
|
2803
|
-
] }) }) : /* @__PURE__ */
|
|
2804
|
-
/* @__PURE__ */
|
|
2805
|
-
/* @__PURE__ */
|
|
2806
|
-
/* @__PURE__ */
|
|
3006
|
+
] }) }) : /* @__PURE__ */ jsxs24("div", { className: "rounded-lg border border-border bg-muted/20 p-6 text-center", children: [
|
|
3007
|
+
/* @__PURE__ */ jsx25(Camera, { className: "mx-auto h-8 w-8 text-muted-foreground mb-2" }),
|
|
3008
|
+
/* @__PURE__ */ jsx25("p", { className: "text-sm text-muted-foreground", children: "No snapshots yet" }),
|
|
3009
|
+
/* @__PURE__ */ jsx25("p", { className: "text-xs text-muted-foreground mt-1", children: "Create a snapshot to save the current state of your sandbox." })
|
|
2807
3010
|
] })
|
|
2808
3011
|
] });
|
|
2809
3012
|
}
|
|
2810
3013
|
|
|
2811
3014
|
// src/dashboard/promo-banner.tsx
|
|
2812
|
-
import { Fragment as Fragment12, jsx as
|
|
3015
|
+
import { Fragment as Fragment12, jsx as jsx26, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
2813
3016
|
function PromoBanner({
|
|
2814
3017
|
title,
|
|
2815
3018
|
description,
|
|
@@ -2824,21 +3027,21 @@ function PromoBanner({
|
|
|
2824
3027
|
"mt-6 inline-flex items-center gap-2 rounded-md border border-white/20 bg-[var(--btn-primary-bg)] px-4 py-2 text-sm font-medium text-[var(--btn-primary-text)] transition-colors",
|
|
2825
3028
|
disabled ? "opacity-50 cursor-not-allowed" : "hover:bg-[var(--btn-primary-hover)]"
|
|
2826
3029
|
);
|
|
2827
|
-
const buttonContent = /* @__PURE__ */
|
|
3030
|
+
const buttonContent = /* @__PURE__ */ jsxs25(Fragment12, { children: [
|
|
2828
3031
|
buttonLabel,
|
|
2829
|
-
/* @__PURE__ */
|
|
2830
|
-
/* @__PURE__ */
|
|
2831
|
-
/* @__PURE__ */
|
|
3032
|
+
/* @__PURE__ */ jsxs25("svg", { "aria-hidden": "true", xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "h-4 w-4", children: [
|
|
3033
|
+
/* @__PURE__ */ jsx26("path", { d: "M5 12h14" }),
|
|
3034
|
+
/* @__PURE__ */ jsx26("path", { d: "m12 5 7 7-7 7" })
|
|
2832
3035
|
] })
|
|
2833
3036
|
] });
|
|
2834
|
-
return /* @__PURE__ */
|
|
2835
|
-
/* @__PURE__ */
|
|
2836
|
-
/* @__PURE__ */
|
|
2837
|
-
/* @__PURE__ */
|
|
2838
|
-
href && !disabled ? /* @__PURE__ */
|
|
3037
|
+
return /* @__PURE__ */ jsxs25("div", { className: cn("relative overflow-hidden rounded-xl bg-[var(--brand-strong)] p-8 md:flex md:items-center md:justify-between", className), children: [
|
|
3038
|
+
/* @__PURE__ */ jsxs25("div", { className: "relative z-10", children: [
|
|
3039
|
+
/* @__PURE__ */ jsx26("h3", { className: "text-xl font-bold text-[var(--brand-strong-text)]", children: title }),
|
|
3040
|
+
/* @__PURE__ */ jsx26("p", { className: "mt-2 max-w-md text-sm text-[var(--brand-strong-text-muted)]", children: description }),
|
|
3041
|
+
href && !disabled ? /* @__PURE__ */ jsx26("a", { href, target: "_blank", rel: "noopener noreferrer", onClick, className: buttonClasses, children: buttonContent }) : /* @__PURE__ */ jsx26("button", { type: "button", onClick, disabled, className: buttonClasses, children: buttonContent })
|
|
2839
3042
|
] }),
|
|
2840
|
-
icon && /* @__PURE__ */
|
|
2841
|
-
/* @__PURE__ */
|
|
3043
|
+
icon && /* @__PURE__ */ jsx26("div", { className: "relative z-10 mt-6 flex items-center md:mt-0", children: /* @__PURE__ */ jsx26("div", { className: "flex h-16 w-16 items-center justify-center rounded-2xl border border-white/10 bg-white/10", children: icon }) }),
|
|
3044
|
+
/* @__PURE__ */ jsx26("div", { className: "pointer-events-none absolute inset-y-0 right-0 w-1/3 bg-gradient-to-l from-white/5 to-transparent" })
|
|
2842
3045
|
] });
|
|
2843
3046
|
}
|
|
2844
3047
|
|
|
@@ -2868,6 +3071,8 @@ export {
|
|
|
2868
3071
|
OutOfCreditsModal,
|
|
2869
3072
|
ClusterStatusBar,
|
|
2870
3073
|
ResourceMeter,
|
|
3074
|
+
ResourceSnapshot,
|
|
3075
|
+
ActivityFeed,
|
|
2871
3076
|
canAdminSandbox,
|
|
2872
3077
|
SandboxCard,
|
|
2873
3078
|
NewSandboxCard,
|
|
@@ -2875,6 +3080,7 @@ export {
|
|
|
2875
3080
|
InvoiceTable,
|
|
2876
3081
|
PlanCards,
|
|
2877
3082
|
DashboardLayout,
|
|
3083
|
+
SidebarLayout,
|
|
2878
3084
|
ProfileSelector,
|
|
2879
3085
|
ProfileComparison,
|
|
2880
3086
|
MetricAreaChart,
|