@tangle-network/sandbox-ui 0.30.0 → 0.32.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/chat.js +3 -3
- package/dist/{chunk-DNZ4DTNA.js → chunk-2XNT74ZX.js} +2 -2
- package/dist/{chunk-AUFV7766.js → chunk-6NDOA4SB.js} +11 -8
- package/dist/{chunk-YPBFIETY.js → chunk-CI6RWXWY.js} +831 -734
- package/dist/{chunk-BJFWPP5T.js → chunk-E267TDZP.js} +12 -12
- package/dist/{chunk-ELGN7DPS.js → chunk-JC7GMQK7.js} +1 -1
- package/dist/{chunk-6NQBODYV.js → chunk-NMR2CTGP.js} +6 -6
- package/dist/dashboard.d.ts +92 -7
- package/dist/dashboard.js +12 -4
- package/dist/globals.css +90 -55
- package/dist/index.d.ts +1 -1
- package/dist/index.js +14 -6
- package/dist/pages.js +14 -14
- package/dist/styles.css +90 -55
- package/dist/workspace.js +1 -1
- package/package.json +1 -1
|
@@ -23,6 +23,7 @@ import { Skeleton, useTheme } from "@tangle-network/ui/primitives";
|
|
|
23
23
|
import * as React from "react";
|
|
24
24
|
import { jsx } from "react/jsx-runtime";
|
|
25
25
|
var PANEL_OPEN_KEY = "sandbox-sidebar-panel-open";
|
|
26
|
+
var RAIL_COLLAPSED_KEY = "sandbox-sidebar-rail-collapsed";
|
|
26
27
|
var SIDEBAR_MODE_KEY = "sandbox-sidebar-mode";
|
|
27
28
|
var SIDEBAR_RAIL_WIDTH = 56;
|
|
28
29
|
var SIDEBAR_PANEL_WIDTH = 268;
|
|
@@ -49,9 +50,12 @@ function SidebarProvider({
|
|
|
49
50
|
defaultPanelOpen = true,
|
|
50
51
|
defaultMode = "projects",
|
|
51
52
|
hasPanels = true,
|
|
52
|
-
|
|
53
|
+
labeledRail = false,
|
|
53
54
|
panelOpen: controlledPanelOpen,
|
|
54
55
|
onPanelOpenChange,
|
|
56
|
+
railCollapsed: controlledRailCollapsed,
|
|
57
|
+
onRailCollapsedChange,
|
|
58
|
+
defaultRailCollapsed = false,
|
|
55
59
|
children
|
|
56
60
|
}) {
|
|
57
61
|
const isControlled = controlledPanelOpen !== void 0;
|
|
@@ -59,6 +63,11 @@ function SidebarProvider({
|
|
|
59
63
|
() => isControlled ? controlledPanelOpen : readStorage(PANEL_OPEN_KEY, String(defaultPanelOpen)) === "true"
|
|
60
64
|
);
|
|
61
65
|
const panelOpen = isControlled ? controlledPanelOpen : uncontrolledPanelOpen;
|
|
66
|
+
const isRailControlled = controlledRailCollapsed !== void 0;
|
|
67
|
+
const [uncontrolledRailCollapsed, setUncontrolledRailCollapsed] = React.useState(
|
|
68
|
+
() => isRailControlled ? controlledRailCollapsed : readStorage(RAIL_COLLAPSED_KEY, String(defaultRailCollapsed)) === "true"
|
|
69
|
+
);
|
|
70
|
+
const railCollapsed = isRailControlled ? controlledRailCollapsed : uncontrolledRailCollapsed;
|
|
62
71
|
const [mode, setModeState] = React.useState(
|
|
63
72
|
() => isControlled ? defaultMode : readStorage(SIDEBAR_MODE_KEY, defaultMode)
|
|
64
73
|
);
|
|
@@ -73,6 +82,16 @@ function SidebarProvider({
|
|
|
73
82
|
const togglePanel = React.useCallback(() => {
|
|
74
83
|
setPanelOpen(!panelOpen);
|
|
75
84
|
}, [setPanelOpen, panelOpen]);
|
|
85
|
+
const setRailCollapsed = React.useCallback((collapsed) => {
|
|
86
|
+
if (!isRailControlled) {
|
|
87
|
+
setUncontrolledRailCollapsed(collapsed);
|
|
88
|
+
writeStorage(RAIL_COLLAPSED_KEY, String(collapsed));
|
|
89
|
+
}
|
|
90
|
+
onRailCollapsedChange?.(collapsed);
|
|
91
|
+
}, [isRailControlled, onRailCollapsedChange]);
|
|
92
|
+
const toggleRail = React.useCallback(() => {
|
|
93
|
+
setRailCollapsed(!railCollapsed);
|
|
94
|
+
}, [setRailCollapsed, railCollapsed]);
|
|
76
95
|
const setMode = React.useCallback((m) => {
|
|
77
96
|
setModeState(m);
|
|
78
97
|
if (!isControlled) writeStorage(SIDEBAR_MODE_KEY, m);
|
|
@@ -86,6 +105,7 @@ function SidebarProvider({
|
|
|
86
105
|
if (!isControlled) writeStorage(SIDEBAR_MODE_KEY, m);
|
|
87
106
|
setPanelOpen(true);
|
|
88
107
|
}, [mode, panelOpen, isControlled, setPanelOpen]);
|
|
108
|
+
const railWidth = labeledRail && !railCollapsed ? SIDEBAR_RAIL_LABELED_WIDTH : SIDEBAR_RAIL_WIDTH;
|
|
89
109
|
const contentMargin = hidden ? 0 : panelOpen && hasPanels ? railWidth + SIDEBAR_PANEL_WIDTH : railWidth;
|
|
90
110
|
const value = React.useMemo(
|
|
91
111
|
() => ({
|
|
@@ -99,9 +119,12 @@ function SidebarProvider({
|
|
|
99
119
|
setHidden,
|
|
100
120
|
contentMargin,
|
|
101
121
|
hasPanels,
|
|
122
|
+
railCollapsed,
|
|
123
|
+
setRailCollapsed,
|
|
124
|
+
toggleRail,
|
|
102
125
|
railWidth
|
|
103
126
|
}),
|
|
104
|
-
[panelOpen, setPanelOpen, togglePanel, mode, setMode, switchMode, hidden, setHidden, contentMargin, hasPanels, railWidth]
|
|
127
|
+
[panelOpen, setPanelOpen, togglePanel, mode, setMode, switchMode, hidden, setHidden, contentMargin, hasPanels, railCollapsed, setRailCollapsed, toggleRail, railWidth]
|
|
105
128
|
);
|
|
106
129
|
return /* @__PURE__ */ jsx(SidebarContext.Provider, { value, children });
|
|
107
130
|
}
|
|
@@ -111,8 +134,32 @@ function useSidebar() {
|
|
|
111
134
|
return ctx;
|
|
112
135
|
}
|
|
113
136
|
|
|
114
|
-
// src/dashboard/
|
|
137
|
+
// src/dashboard/rail-tooltip.tsx
|
|
115
138
|
import { Fragment, jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
139
|
+
function RailTooltip({ label, children, disabled, className }) {
|
|
140
|
+
if (disabled) return /* @__PURE__ */ jsx2(Fragment, { children });
|
|
141
|
+
return /* @__PURE__ */ jsxs("span", { className: cn("group/tip relative flex", className), children: [
|
|
142
|
+
children,
|
|
143
|
+
/* @__PURE__ */ jsx2(
|
|
144
|
+
"span",
|
|
145
|
+
{
|
|
146
|
+
role: "tooltip",
|
|
147
|
+
"aria-hidden": "true",
|
|
148
|
+
className: cn(
|
|
149
|
+
"pointer-events-none absolute left-full top-1/2 z-50 ml-2 -translate-y-1/2 translate-x-1 whitespace-nowrap",
|
|
150
|
+
"rounded-md border border-border bg-popover px-2 py-1 text-xs font-medium text-popover-foreground",
|
|
151
|
+
"opacity-0 shadow-[var(--shadow-dropdown)] transition-[opacity,transform] duration-150 ease-out",
|
|
152
|
+
"group-hover/tip:translate-x-0 group-hover/tip:opacity-100 group-hover/tip:delay-300",
|
|
153
|
+
"group-focus-within/tip:translate-x-0 group-focus-within/tip:opacity-100"
|
|
154
|
+
),
|
|
155
|
+
children: label
|
|
156
|
+
}
|
|
157
|
+
)
|
|
158
|
+
] });
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// src/dashboard/app-sidebar.tsx
|
|
162
|
+
import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
116
163
|
function DefaultLink({
|
|
117
164
|
href,
|
|
118
165
|
to,
|
|
@@ -120,7 +167,7 @@ function DefaultLink({
|
|
|
120
167
|
children,
|
|
121
168
|
...rest
|
|
122
169
|
}) {
|
|
123
|
-
return /* @__PURE__ */
|
|
170
|
+
return /* @__PURE__ */ jsx3("a", { href: href ?? to, className, ...rest, children });
|
|
124
171
|
}
|
|
125
172
|
function getInitials(name, email) {
|
|
126
173
|
if (name) return name.split(" ").map((w) => w[0]).filter(Boolean).slice(0, 2).join("").toUpperCase();
|
|
@@ -128,31 +175,31 @@ function getInitials(name, email) {
|
|
|
128
175
|
return "?";
|
|
129
176
|
}
|
|
130
177
|
function SettingsIcon({ className }) {
|
|
131
|
-
return /* @__PURE__ */
|
|
132
|
-
/* @__PURE__ */
|
|
133
|
-
/* @__PURE__ */
|
|
134
|
-
/* @__PURE__ */
|
|
178
|
+
return /* @__PURE__ */ jsxs2("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: [
|
|
179
|
+
/* @__PURE__ */ jsx3("title", { children: "Settings icon" }),
|
|
180
|
+
/* @__PURE__ */ jsx3("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" }),
|
|
181
|
+
/* @__PURE__ */ jsx3("circle", { cx: "12", cy: "12", r: "3" })
|
|
135
182
|
] });
|
|
136
183
|
}
|
|
137
184
|
function LogOutIcon({ className }) {
|
|
138
|
-
return /* @__PURE__ */
|
|
139
|
-
/* @__PURE__ */
|
|
140
|
-
/* @__PURE__ */
|
|
141
|
-
/* @__PURE__ */
|
|
142
|
-
/* @__PURE__ */
|
|
185
|
+
return /* @__PURE__ */ jsxs2("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: [
|
|
186
|
+
/* @__PURE__ */ jsx3("title", { children: "Log out icon" }),
|
|
187
|
+
/* @__PURE__ */ jsx3("path", { d: "M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4" }),
|
|
188
|
+
/* @__PURE__ */ jsx3("polyline", { points: "16,17 21,12 16,7" }),
|
|
189
|
+
/* @__PURE__ */ jsx3("line", { x1: "21", x2: "9", y1: "12", y2: "12" })
|
|
143
190
|
] });
|
|
144
191
|
}
|
|
145
192
|
function SunIcon({ className }) {
|
|
146
|
-
return /* @__PURE__ */
|
|
147
|
-
/* @__PURE__ */
|
|
148
|
-
/* @__PURE__ */
|
|
149
|
-
/* @__PURE__ */
|
|
193
|
+
return /* @__PURE__ */ jsxs2("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: [
|
|
194
|
+
/* @__PURE__ */ jsx3("title", { children: "Light mode icon" }),
|
|
195
|
+
/* @__PURE__ */ jsx3("circle", { cx: "12", cy: "12", r: "4" }),
|
|
196
|
+
/* @__PURE__ */ jsx3("path", { d: "M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41" })
|
|
150
197
|
] });
|
|
151
198
|
}
|
|
152
199
|
function MoonIcon({ className }) {
|
|
153
|
-
return /* @__PURE__ */
|
|
154
|
-
/* @__PURE__ */
|
|
155
|
-
/* @__PURE__ */
|
|
200
|
+
return /* @__PURE__ */ jsxs2("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: [
|
|
201
|
+
/* @__PURE__ */ jsx3("title", { children: "Dark mode icon" }),
|
|
202
|
+
/* @__PURE__ */ jsx3("path", { d: "M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z" })
|
|
156
203
|
] });
|
|
157
204
|
}
|
|
158
205
|
function RailThemeToggle({ className }) {
|
|
@@ -160,7 +207,7 @@ function RailThemeToggle({ className }) {
|
|
|
160
207
|
const [mounted, setMounted] = React2.useState(false);
|
|
161
208
|
React2.useEffect(() => setMounted(true), []);
|
|
162
209
|
const isDark = mounted && (theme === "dark" || theme === "system" && typeof window !== "undefined" && window.matchMedia("(prefers-color-scheme: dark)").matches);
|
|
163
|
-
return /* @__PURE__ */
|
|
210
|
+
return /* @__PURE__ */ jsx3(
|
|
164
211
|
"button",
|
|
165
212
|
{
|
|
166
213
|
type: "button",
|
|
@@ -170,16 +217,52 @@ function RailThemeToggle({ className }) {
|
|
|
170
217
|
className: cn(
|
|
171
218
|
"flex h-9 w-9 shrink-0 items-center justify-center rounded-md text-muted-foreground transition-colors",
|
|
172
219
|
"hover:bg-[var(--accent-surface-soft)] hover:text-foreground",
|
|
173
|
-
"focus-visible:outline-none focus-visible:ring-
|
|
220
|
+
"focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
174
221
|
className
|
|
175
222
|
),
|
|
176
|
-
children: isDark ? /* @__PURE__ */
|
|
223
|
+
children: isDark ? /* @__PURE__ */ jsx3(SunIcon, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx3(MoonIcon, { className: "h-4 w-4" })
|
|
177
224
|
}
|
|
178
225
|
);
|
|
179
226
|
}
|
|
227
|
+
function ChevronsLeftIcon({ className }) {
|
|
228
|
+
return /* @__PURE__ */ jsxs2("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: [
|
|
229
|
+
/* @__PURE__ */ jsx3("title", { children: "Collapse sidebar" }),
|
|
230
|
+
/* @__PURE__ */ jsx3("path", { d: "m11 17-5-5 5-5M18 17l-5-5 5-5" })
|
|
231
|
+
] });
|
|
232
|
+
}
|
|
233
|
+
function ChevronsRightIcon({ className }) {
|
|
234
|
+
return /* @__PURE__ */ jsxs2("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: [
|
|
235
|
+
/* @__PURE__ */ jsx3("title", { children: "Expand sidebar" }),
|
|
236
|
+
/* @__PURE__ */ jsx3("path", { d: "m6 17 5-5-5-5M13 17l5-5-5-5" })
|
|
237
|
+
] });
|
|
238
|
+
}
|
|
239
|
+
function RailCollapseToggle({ collapsed, showLabel, onToggle, className }) {
|
|
240
|
+
const label = collapsed ? "Expand sidebar" : "Collapse sidebar";
|
|
241
|
+
const Icon = collapsed ? ChevronsRightIcon : ChevronsLeftIcon;
|
|
242
|
+
return /* @__PURE__ */ jsx3(RailTooltip, { label, disabled: showLabel, className: showLabel ? "w-full" : void 0, children: /* @__PURE__ */ jsxs2(
|
|
243
|
+
"button",
|
|
244
|
+
{
|
|
245
|
+
type: "button",
|
|
246
|
+
onClick: onToggle,
|
|
247
|
+
"aria-label": label,
|
|
248
|
+
"aria-pressed": collapsed,
|
|
249
|
+
className: cn(
|
|
250
|
+
"flex shrink-0 items-center rounded-md text-muted-foreground transition-colors",
|
|
251
|
+
showLabel ? "h-9 w-full justify-start gap-2.5 px-2.5" : "h-9 w-9 justify-center",
|
|
252
|
+
"hover:bg-[var(--accent-surface-soft)] hover:text-foreground",
|
|
253
|
+
"focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
254
|
+
className
|
|
255
|
+
),
|
|
256
|
+
children: [
|
|
257
|
+
/* @__PURE__ */ jsx3(Icon, { className: "h-[17px] w-[17px] shrink-0" }),
|
|
258
|
+
showLabel && /* @__PURE__ */ jsx3("span", { className: "text-[13.5px] font-medium", children: label })
|
|
259
|
+
]
|
|
260
|
+
}
|
|
261
|
+
) });
|
|
262
|
+
}
|
|
180
263
|
function Sidebar({ children, className, style }) {
|
|
181
264
|
const { panelOpen, hidden, hasPanels, railWidth } = useSidebar();
|
|
182
|
-
return /* @__PURE__ */
|
|
265
|
+
return /* @__PURE__ */ jsx3(
|
|
183
266
|
"div",
|
|
184
267
|
{
|
|
185
268
|
"data-sidebar": "true",
|
|
@@ -195,7 +278,7 @@ function Sidebar({ children, className, style }) {
|
|
|
195
278
|
}
|
|
196
279
|
function SidebarRail({ children, className, wide = false }) {
|
|
197
280
|
const { railWidth } = useSidebar();
|
|
198
|
-
return /* @__PURE__ */
|
|
281
|
+
return /* @__PURE__ */ jsx3(
|
|
199
282
|
"div",
|
|
200
283
|
{
|
|
201
284
|
className: cn(
|
|
@@ -209,42 +292,44 @@ function SidebarRail({ children, className, wide = false }) {
|
|
|
209
292
|
);
|
|
210
293
|
}
|
|
211
294
|
function SidebarRailHeader({ children, className }) {
|
|
212
|
-
return /* @__PURE__ */
|
|
295
|
+
return /* @__PURE__ */ jsx3("div", { className: cn("flex h-14 shrink-0 items-center justify-center border-b border-border", className), children });
|
|
213
296
|
}
|
|
214
297
|
function SidebarRailNav({ children, className }) {
|
|
215
|
-
return /* @__PURE__ */
|
|
298
|
+
return /* @__PURE__ */ jsx3("nav", { className: cn("flex flex-col items-center gap-1 py-3 flex-1 min-h-0 overflow-y-auto", className), children });
|
|
216
299
|
}
|
|
217
300
|
function SidebarRailFooter({ children, className }) {
|
|
218
|
-
return /* @__PURE__ */
|
|
301
|
+
return /* @__PURE__ */ jsx3("div", { className: cn("flex flex-col items-center gap-1 pb-3 shrink-0", className), children });
|
|
219
302
|
}
|
|
220
303
|
function RailSeparator({ className }) {
|
|
221
|
-
return /* @__PURE__ */
|
|
304
|
+
return /* @__PURE__ */ jsx3("div", { className: cn("my-2 h-px w-10 bg-[var(--md3-outline-variant)]", className) });
|
|
222
305
|
}
|
|
223
306
|
function RailButton({ icon: Icon, label, isActive, badge, onClick, className, showLabel, asChild, children }) {
|
|
224
307
|
const classes = cn(
|
|
225
|
-
"
|
|
308
|
+
"relative flex shrink-0 items-center justify-center rounded-md transition-colors duration-150",
|
|
226
309
|
showLabel ? "w-full justify-start px-2.5 h-9 gap-2.5" : "w-9 h-9 justify-center",
|
|
227
|
-
|
|
228
|
-
"
|
|
229
|
-
"
|
|
230
|
-
isActive && "bg-[var(--accent-surface-strong)] text-[var(--accent-text)]",
|
|
231
|
-
!isActive && "text-muted-foreground",
|
|
310
|
+
// Quiet press feedback via color only — no scale on the full-width row.
|
|
311
|
+
"focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
312
|
+
isActive ? "bg-[var(--accent-surface-strong)] text-[var(--accent-text)]" : "text-muted-foreground hover:bg-[var(--accent-surface-soft)] hover:text-foreground",
|
|
232
313
|
className
|
|
233
314
|
);
|
|
234
|
-
const
|
|
235
|
-
/* @__PURE__ */
|
|
236
|
-
|
|
237
|
-
|
|
315
|
+
const iconWithBadge = /* @__PURE__ */ jsxs2("span", { className: "relative flex shrink-0 items-center justify-center", children: [
|
|
316
|
+
/* @__PURE__ */ jsx3(Icon, { className: "h-[17px] w-[17px] shrink-0" }),
|
|
317
|
+
badge !== void 0 && badge > 0 && /* @__PURE__ */ jsx3("span", { className: "absolute -top-1.5 -right-1.5 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", children: badge > 99 ? "99+" : badge })
|
|
318
|
+
] });
|
|
319
|
+
const content = /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
320
|
+
iconWithBadge,
|
|
321
|
+
showLabel && /* @__PURE__ */ jsx3("span", { className: "text-[13.5px] font-medium", children: label })
|
|
238
322
|
] });
|
|
239
323
|
if (asChild && React2.isValidElement(children)) {
|
|
240
324
|
const child = children;
|
|
241
|
-
|
|
325
|
+
const merged = React2.cloneElement(
|
|
242
326
|
child,
|
|
243
|
-
{ className: cn(classes, child.props.className),
|
|
327
|
+
{ className: cn(classes, child.props.className), "aria-label": child.props["aria-label"] ?? label },
|
|
244
328
|
content
|
|
245
329
|
);
|
|
330
|
+
return /* @__PURE__ */ jsx3(RailTooltip, { label, disabled: showLabel, className: showLabel ? "w-full" : void 0, children: merged });
|
|
246
331
|
}
|
|
247
|
-
return /* @__PURE__ */
|
|
332
|
+
return /* @__PURE__ */ jsx3(RailTooltip, { label, disabled: showLabel, className: showLabel ? "w-full" : void 0, children: /* @__PURE__ */ jsx3("button", { type: "button", onClick, "aria-label": label, className: classes, children: content }) });
|
|
248
333
|
}
|
|
249
334
|
function RailFlyout({
|
|
250
335
|
icon: Icon,
|
|
@@ -272,28 +357,28 @@ function RailFlyout({
|
|
|
272
357
|
document.removeEventListener("keydown", onKey);
|
|
273
358
|
};
|
|
274
359
|
}, [open]);
|
|
360
|
+
const active = isActive || open;
|
|
275
361
|
const triggerClasses = cn(
|
|
276
|
-
"
|
|
362
|
+
"relative flex shrink-0 items-center rounded-md transition-colors duration-150",
|
|
277
363
|
showLabel ? "w-full justify-start px-2.5 h-9 gap-2.5" : "w-9 h-9 justify-center",
|
|
278
|
-
"
|
|
279
|
-
"
|
|
280
|
-
isActive || open ? "bg-[var(--accent-surface-strong)] text-[var(--accent-text)]" : "text-muted-foreground",
|
|
364
|
+
"focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
365
|
+
active ? "bg-[var(--accent-surface-strong)] text-[var(--accent-text)]" : "text-muted-foreground hover:bg-[var(--accent-surface-soft)] hover:text-foreground",
|
|
281
366
|
className
|
|
282
367
|
);
|
|
283
|
-
return /* @__PURE__ */
|
|
284
|
-
/* @__PURE__ */
|
|
368
|
+
return /* @__PURE__ */ jsxs2("div", { ref, className: cn("relative", showLabel && "w-full"), children: [
|
|
369
|
+
/* @__PURE__ */ jsx3(RailTooltip, { label, disabled: showLabel || open, className: showLabel ? "w-full" : void 0, children: /* @__PURE__ */ jsxs2(
|
|
285
370
|
"button",
|
|
286
371
|
{
|
|
287
372
|
type: "button",
|
|
288
|
-
|
|
373
|
+
"aria-label": label,
|
|
289
374
|
"aria-haspopup": "menu",
|
|
290
375
|
"aria-expanded": open,
|
|
291
376
|
onClick: () => setOpen((v) => !v),
|
|
292
377
|
className: triggerClasses,
|
|
293
378
|
children: [
|
|
294
|
-
/* @__PURE__ */
|
|
295
|
-
showLabel && /* @__PURE__ */
|
|
296
|
-
showLabel && /* @__PURE__ */
|
|
379
|
+
/* @__PURE__ */ jsx3(Icon, { className: "h-[17px] w-[17px] shrink-0" }),
|
|
380
|
+
showLabel && /* @__PURE__ */ jsx3("span", { className: "text-sm font-medium", children: label }),
|
|
381
|
+
showLabel && /* @__PURE__ */ jsx3(
|
|
297
382
|
ChevronRightIcon,
|
|
298
383
|
{
|
|
299
384
|
className: cn(
|
|
@@ -304,11 +389,11 @@ function RailFlyout({
|
|
|
304
389
|
)
|
|
305
390
|
]
|
|
306
391
|
}
|
|
307
|
-
),
|
|
392
|
+
) }),
|
|
308
393
|
open && // Anchored to the right edge of the rail item; full-height-independent
|
|
309
394
|
// floating card. `onClickCapture` closes after a child link/button fires
|
|
310
395
|
// so selecting a sub-surface dismisses the flyout.
|
|
311
|
-
/* @__PURE__ */
|
|
396
|
+
/* @__PURE__ */ jsxs2(
|
|
312
397
|
"div",
|
|
313
398
|
{
|
|
314
399
|
role: "menu",
|
|
@@ -317,11 +402,11 @@ function RailFlyout({
|
|
|
317
402
|
if (el.closest("a,button")) setOpen(false);
|
|
318
403
|
},
|
|
319
404
|
className: cn(
|
|
320
|
-
"absolute top-0 z-50 min-w-[12rem] rounded-md border border-border bg-popover p-1.5 shadow-dropdown",
|
|
405
|
+
"absolute top-0 z-50 min-w-[12rem] rounded-md border border-border bg-popover p-1.5 shadow-[var(--shadow-dropdown)]",
|
|
321
406
|
showLabel ? "left-full ml-2" : "left-full ml-2"
|
|
322
407
|
),
|
|
323
408
|
children: [
|
|
324
|
-
/* @__PURE__ */
|
|
409
|
+
/* @__PURE__ */ jsx3("p", { className: "px-2 pb-1 pt-1 text-[10px] font-semibold uppercase tracking-wider text-muted-foreground/70 select-none", children: title ?? label }),
|
|
325
410
|
children
|
|
326
411
|
]
|
|
327
412
|
}
|
|
@@ -329,14 +414,14 @@ function RailFlyout({
|
|
|
329
414
|
] });
|
|
330
415
|
}
|
|
331
416
|
function ChevronRightIcon({ className }) {
|
|
332
|
-
return /* @__PURE__ */
|
|
333
|
-
/* @__PURE__ */
|
|
334
|
-
/* @__PURE__ */
|
|
417
|
+
return /* @__PURE__ */ jsxs2("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: [
|
|
418
|
+
/* @__PURE__ */ jsx3("title", { children: "Expand" }),
|
|
419
|
+
/* @__PURE__ */ jsx3("path", { d: "m9 18 6-6-6-6" })
|
|
335
420
|
] });
|
|
336
421
|
}
|
|
337
422
|
function RailModeButton({ mode, icon, label, badge, className, showLabel }) {
|
|
338
423
|
const { panelOpen, mode: currentMode, switchMode } = useSidebar();
|
|
339
|
-
return /* @__PURE__ */
|
|
424
|
+
return /* @__PURE__ */ jsx3(
|
|
340
425
|
RailButton,
|
|
341
426
|
{
|
|
342
427
|
icon,
|
|
@@ -351,7 +436,7 @@ function RailModeButton({ mode, icon, label, badge, className, showLabel }) {
|
|
|
351
436
|
}
|
|
352
437
|
function SidebarPanel({ children, className }) {
|
|
353
438
|
const { panelOpen } = useSidebar();
|
|
354
|
-
return /* @__PURE__ */
|
|
439
|
+
return /* @__PURE__ */ jsx3(
|
|
355
440
|
"div",
|
|
356
441
|
{
|
|
357
442
|
className: cn(
|
|
@@ -359,19 +444,19 @@ function SidebarPanel({ children, className }) {
|
|
|
359
444
|
panelOpen ? "w-[268px] opacity-100" : "w-0 opacity-0 pointer-events-none",
|
|
360
445
|
className
|
|
361
446
|
),
|
|
362
|
-
children: /* @__PURE__ */
|
|
447
|
+
children: /* @__PURE__ */ jsx3("div", { className: "flex flex-col h-full w-[268px]", children })
|
|
363
448
|
}
|
|
364
449
|
);
|
|
365
450
|
}
|
|
366
451
|
function SidebarPanelHeader({ children, title, className }) {
|
|
367
|
-
return /* @__PURE__ */
|
|
452
|
+
return /* @__PURE__ */ jsx3("div", { className: cn("flex h-14 items-center px-4 border-b border-border shrink-0", className), children: children ?? /* @__PURE__ */ jsx3("h2", { className: "text-sm font-semibold text-foreground", children: title }) });
|
|
368
453
|
}
|
|
369
454
|
function SidebarPanelContent({ children, className }) {
|
|
370
|
-
return /* @__PURE__ */
|
|
455
|
+
return /* @__PURE__ */ jsx3("div", { className: cn("flex-1 overflow-y-auto px-2 py-2", className), children });
|
|
371
456
|
}
|
|
372
457
|
function SidebarContent({ children, className }) {
|
|
373
458
|
const { contentMargin } = useSidebar();
|
|
374
|
-
return /* @__PURE__ */
|
|
459
|
+
return /* @__PURE__ */ jsx3(
|
|
375
460
|
"main",
|
|
376
461
|
{
|
|
377
462
|
className: cn(
|
|
@@ -395,58 +480,58 @@ function ProfileAvatar({
|
|
|
395
480
|
LinkComponent
|
|
396
481
|
}) {
|
|
397
482
|
const Link = LinkComponent ?? DefaultLink;
|
|
398
|
-
return /* @__PURE__ */
|
|
399
|
-
/* @__PURE__ */
|
|
483
|
+
return /* @__PURE__ */ jsxs2(DropdownMenu, { children: [
|
|
484
|
+
/* @__PURE__ */ jsx3(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs2(
|
|
400
485
|
"button",
|
|
401
486
|
{
|
|
402
487
|
type: "button",
|
|
403
488
|
className: cn(
|
|
404
489
|
"flex items-center rounded-lg transition-colors hover:bg-[var(--accent-surface-soft)]",
|
|
405
|
-
"focus-visible:outline-none focus-visible:ring-
|
|
490
|
+
"focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
406
491
|
showDetails ? "w-full gap-2.5 px-3 py-2 text-left" : "justify-center w-12 h-12",
|
|
407
492
|
className
|
|
408
493
|
),
|
|
409
494
|
"aria-label": "User menu",
|
|
410
495
|
children: [
|
|
411
|
-
isLoading ? /* @__PURE__ */
|
|
412
|
-
user?.avatarUrl && /* @__PURE__ */
|
|
413
|
-
/* @__PURE__ */
|
|
496
|
+
isLoading ? /* @__PURE__ */ jsx3(Skeleton, { className: "h-7 w-7 shrink-0 rounded-full" }) : /* @__PURE__ */ jsxs2(Avatar, { className: "h-7 w-7 shrink-0", children: [
|
|
497
|
+
user?.avatarUrl && /* @__PURE__ */ jsx3(AvatarImage, { src: user.avatarUrl, alt: "" }),
|
|
498
|
+
/* @__PURE__ */ jsx3(AvatarFallback, { className: "text-[10px] bg-violet-500/20 text-violet-300", children: getInitials(user?.name, user?.email) })
|
|
414
499
|
] }),
|
|
415
|
-
showDetails && /* @__PURE__ */
|
|
500
|
+
showDetails && /* @__PURE__ */ jsx3("div", { className: "min-w-0 flex-1", children: isLoading ? /* @__PURE__ */ jsx3(Skeleton, { className: "h-3.5 w-24" }) : /* @__PURE__ */ jsx3("p", { className: "truncate text-sm font-medium text-foreground", children: user?.name ?? user?.email ?? "Not signed in" }) })
|
|
416
501
|
]
|
|
417
502
|
}
|
|
418
503
|
) }),
|
|
419
|
-
/* @__PURE__ */
|
|
420
|
-
/* @__PURE__ */
|
|
421
|
-
/* @__PURE__ */
|
|
422
|
-
user?.avatarUrl && /* @__PURE__ */
|
|
423
|
-
/* @__PURE__ */
|
|
504
|
+
/* @__PURE__ */ jsxs2(DropdownMenuContent, { side: "right", align: "end", sideOffset: 8, className: "w-72", children: [
|
|
505
|
+
/* @__PURE__ */ jsx3(DropdownMenuLabel, { className: "p-0 font-normal", children: /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-3 px-2 py-3", children: [
|
|
506
|
+
/* @__PURE__ */ jsxs2(Avatar, { className: "h-12 w-12 shrink-0", children: [
|
|
507
|
+
user?.avatarUrl && /* @__PURE__ */ jsx3(AvatarImage, { src: user.avatarUrl, alt: "" }),
|
|
508
|
+
/* @__PURE__ */ jsx3(AvatarFallback, { className: "text-sm bg-[var(--surface-violet-bg)] text-[var(--surface-violet-text)]", children: getInitials(user?.name, user?.email) })
|
|
424
509
|
] }),
|
|
425
|
-
/* @__PURE__ */
|
|
426
|
-
/* @__PURE__ */
|
|
427
|
-
/* @__PURE__ */
|
|
428
|
-
] }) : /* @__PURE__ */
|
|
429
|
-
/* @__PURE__ */
|
|
430
|
-
user?.email && user?.name && /* @__PURE__ */
|
|
431
|
-
user?.tier && /* @__PURE__ */
|
|
510
|
+
/* @__PURE__ */ jsx3("div", { className: "min-w-0 flex-1", children: isLoading ? /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
511
|
+
/* @__PURE__ */ jsx3(Skeleton, { className: "h-4 w-24 mb-1" }),
|
|
512
|
+
/* @__PURE__ */ jsx3(Skeleton, { className: "h-3 w-32" })
|
|
513
|
+
] }) : /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
514
|
+
/* @__PURE__ */ jsx3("p", { className: "text-sm font-semibold truncate", children: user?.name ?? user?.email ?? "Not logged in" }),
|
|
515
|
+
user?.email && user?.name && /* @__PURE__ */ jsx3("p", { className: "text-xs text-muted-foreground truncate", children: user.email }),
|
|
516
|
+
user?.tier && /* @__PURE__ */ jsxs2("p", { className: "text-xs text-muted-foreground capitalize", children: [
|
|
432
517
|
user.tier,
|
|
433
518
|
" Plan"
|
|
434
519
|
] })
|
|
435
520
|
] }) })
|
|
436
521
|
] }) }),
|
|
437
|
-
/* @__PURE__ */
|
|
522
|
+
/* @__PURE__ */ jsx3(DropdownMenuSeparator, {}),
|
|
438
523
|
children,
|
|
439
|
-
onSettingsClick ? /* @__PURE__ */
|
|
440
|
-
/* @__PURE__ */
|
|
524
|
+
onSettingsClick ? /* @__PURE__ */ jsxs2(DropdownMenuItem, { onClick: onSettingsClick, children: [
|
|
525
|
+
/* @__PURE__ */ jsx3(SettingsIcon, { className: "mr-2 h-4 w-4", "aria-hidden": "true" }),
|
|
441
526
|
"Settings"
|
|
442
|
-
] }) : /* @__PURE__ */
|
|
443
|
-
/* @__PURE__ */
|
|
527
|
+
] }) : /* @__PURE__ */ jsx3(DropdownMenuItem, { asChild: true, children: /* @__PURE__ */ jsxs2(Link, { href: settingsHref, to: settingsHref, className: "flex items-center", children: [
|
|
528
|
+
/* @__PURE__ */ jsx3(SettingsIcon, { className: "mr-2 h-4 w-4", "aria-hidden": "true" }),
|
|
444
529
|
"Settings"
|
|
445
530
|
] }) }),
|
|
446
|
-
onLogout && /* @__PURE__ */
|
|
447
|
-
/* @__PURE__ */
|
|
448
|
-
/* @__PURE__ */
|
|
449
|
-
/* @__PURE__ */
|
|
531
|
+
onLogout && /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
532
|
+
/* @__PURE__ */ jsx3(DropdownMenuSeparator, {}),
|
|
533
|
+
/* @__PURE__ */ jsxs2(DropdownMenuItem, { className: "text-[var(--surface-danger-text)]", onClick: onLogout, children: [
|
|
534
|
+
/* @__PURE__ */ jsx3(LogOutIcon, { className: "mr-2 h-4 w-4", "aria-hidden": "true" }),
|
|
450
535
|
"Sign Out"
|
|
451
536
|
] })
|
|
452
537
|
] })
|
|
@@ -456,7 +541,7 @@ function ProfileAvatar({
|
|
|
456
541
|
|
|
457
542
|
// src/dashboard/credit-balance.tsx
|
|
458
543
|
import * as React3 from "react";
|
|
459
|
-
import { jsx as
|
|
544
|
+
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
460
545
|
function CreditBalance({
|
|
461
546
|
amount,
|
|
462
547
|
description = "Credits are automatically deducted based on hourly Sandbox usage and Agent operations.",
|
|
@@ -465,7 +550,7 @@ function CreditBalance({
|
|
|
465
550
|
className
|
|
466
551
|
}) {
|
|
467
552
|
const [topUpValue, setTopUpValue] = React3.useState("50.00");
|
|
468
|
-
return /* @__PURE__ */
|
|
553
|
+
return /* @__PURE__ */ jsxs3(
|
|
469
554
|
"div",
|
|
470
555
|
{
|
|
471
556
|
className: cn(
|
|
@@ -473,17 +558,17 @@ function CreditBalance({
|
|
|
473
558
|
className
|
|
474
559
|
),
|
|
475
560
|
children: [
|
|
476
|
-
/* @__PURE__ */
|
|
477
|
-
/* @__PURE__ */
|
|
478
|
-
/* @__PURE__ */
|
|
561
|
+
/* @__PURE__ */ jsxs3("div", { children: [
|
|
562
|
+
/* @__PURE__ */ jsx4("h3", { className: "text-sm font-semibold text-muted-foreground uppercase tracking-widest mb-2", children: "Available Credits" }),
|
|
563
|
+
/* @__PURE__ */ jsxs3("div", { className: "text-4xl font-extrabold text-primary tracking-tighter mb-2", children: [
|
|
479
564
|
"$",
|
|
480
565
|
amount.toFixed(2)
|
|
481
566
|
] }),
|
|
482
|
-
/* @__PURE__ */
|
|
567
|
+
/* @__PURE__ */ jsx4("p", { className: "text-sm text-muted-foreground leading-relaxed", children: description })
|
|
483
568
|
] }),
|
|
484
|
-
onTopUp && /* @__PURE__ */
|
|
485
|
-
/* @__PURE__ */
|
|
486
|
-
/* @__PURE__ */
|
|
569
|
+
onTopUp && /* @__PURE__ */ jsxs3("div", { className: "space-y-2.5 mt-5", children: [
|
|
570
|
+
/* @__PURE__ */ jsxs3("div", { className: "bg-card border border-border p-1 rounded-lg flex items-center", children: [
|
|
571
|
+
/* @__PURE__ */ jsx4(
|
|
487
572
|
"input",
|
|
488
573
|
{
|
|
489
574
|
type: "text",
|
|
@@ -495,7 +580,7 @@ function CreditBalance({
|
|
|
495
580
|
className: "bg-transparent border-none text-foreground font-mono text-lg w-full focus:ring-0 px-4 outline-none"
|
|
496
581
|
}
|
|
497
582
|
),
|
|
498
|
-
/* @__PURE__ */
|
|
583
|
+
/* @__PURE__ */ jsx4(
|
|
499
584
|
"button",
|
|
500
585
|
{
|
|
501
586
|
type: "button",
|
|
@@ -509,7 +594,7 @@ function CreditBalance({
|
|
|
509
594
|
}
|
|
510
595
|
)
|
|
511
596
|
] }),
|
|
512
|
-
/* @__PURE__ */
|
|
597
|
+
/* @__PURE__ */ jsx4("div", { className: "flex justify-between gap-2", children: quickAmounts.filter((qa) => Number.isFinite(qa) && qa > 0).map((qa) => /* @__PURE__ */ jsxs3(
|
|
513
598
|
"button",
|
|
514
599
|
{
|
|
515
600
|
type: "button",
|
|
@@ -533,7 +618,7 @@ function CreditBalance({
|
|
|
533
618
|
}
|
|
534
619
|
|
|
535
620
|
// src/dashboard/out-of-credits.tsx
|
|
536
|
-
import { jsx as
|
|
621
|
+
import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
537
622
|
var INSUFFICIENT_BALANCE_CODE = "insufficient_balance";
|
|
538
623
|
function parseInsufficientBalance(payload, opts = {}) {
|
|
539
624
|
if (!payload || typeof payload !== "object") return null;
|
|
@@ -556,7 +641,7 @@ function OutOfCreditsModal({
|
|
|
556
641
|
className
|
|
557
642
|
}) {
|
|
558
643
|
if (!balance) return null;
|
|
559
|
-
return /* @__PURE__ */
|
|
644
|
+
return /* @__PURE__ */ jsx5(
|
|
560
645
|
"div",
|
|
561
646
|
{
|
|
562
647
|
role: "dialog",
|
|
@@ -564,27 +649,27 @@ function OutOfCreditsModal({
|
|
|
564
649
|
"aria-label": "Out of credits",
|
|
565
650
|
className: "fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4",
|
|
566
651
|
onClick: onClose,
|
|
567
|
-
children: /* @__PURE__ */
|
|
652
|
+
children: /* @__PURE__ */ jsxs4(
|
|
568
653
|
"div",
|
|
569
654
|
{
|
|
570
655
|
className: cn(
|
|
571
|
-
"bg-card border border-border rounded-xl p-6 max-w-md w-full shadow-
|
|
656
|
+
"bg-card border border-border rounded-xl p-6 max-w-md w-full shadow-[var(--shadow-dropdown)]",
|
|
572
657
|
className
|
|
573
658
|
),
|
|
574
659
|
onClick: (e) => e.stopPropagation(),
|
|
575
660
|
children: [
|
|
576
|
-
/* @__PURE__ */
|
|
577
|
-
/* @__PURE__ */
|
|
661
|
+
/* @__PURE__ */ jsx5("h3", { className: "text-lg font-bold text-foreground mb-1", children: "You're out of credits" }),
|
|
662
|
+
/* @__PURE__ */ jsxs4("p", { className: "text-sm text-muted-foreground leading-relaxed mb-4", children: [
|
|
578
663
|
balance.message ?? "Add credits or start a subscription to keep going. Usage is billed to your Tangle account.",
|
|
579
|
-
typeof balance.remainingBalanceUsd === "number" && /* @__PURE__ */
|
|
664
|
+
typeof balance.remainingBalanceUsd === "number" && /* @__PURE__ */ jsxs4("span", { className: "block mt-1", children: [
|
|
580
665
|
"Balance: $",
|
|
581
666
|
balance.remainingBalanceUsd.toFixed(2),
|
|
582
667
|
balance.plan ? ` \xB7 ${balance.plan} plan` : ""
|
|
583
668
|
] })
|
|
584
669
|
] }),
|
|
585
|
-
/* @__PURE__ */
|
|
586
|
-
onClose && /* @__PURE__ */
|
|
587
|
-
/* @__PURE__ */
|
|
670
|
+
/* @__PURE__ */ jsxs4("div", { className: "flex gap-2 justify-end", children: [
|
|
671
|
+
onClose && /* @__PURE__ */ jsx5(Button, { variant: "outline", onClick: onClose, children: "Not now" }),
|
|
672
|
+
/* @__PURE__ */ jsx5(Button, { asChild: true, children: /* @__PURE__ */ jsx5("a", { href: balance.manageUrl, target: "_blank", rel: "noopener noreferrer", children: ctaLabel }) })
|
|
588
673
|
] })
|
|
589
674
|
]
|
|
590
675
|
}
|
|
@@ -594,32 +679,32 @@ function OutOfCreditsModal({
|
|
|
594
679
|
}
|
|
595
680
|
|
|
596
681
|
// src/dashboard/cluster-status-bar.tsx
|
|
597
|
-
import { Fragment as
|
|
682
|
+
import { Fragment as Fragment3, jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
598
683
|
function ClusterStatusBar({ items, latency, className }) {
|
|
599
684
|
if (!items?.length) return null;
|
|
600
|
-
return /* @__PURE__ */
|
|
601
|
-
/* @__PURE__ */
|
|
602
|
-
/* @__PURE__ */
|
|
603
|
-
/* @__PURE__ */
|
|
604
|
-
/* @__PURE__ */
|
|
605
|
-
/* @__PURE__ */
|
|
685
|
+
return /* @__PURE__ */ jsx6("div", { className: cn("fixed bottom-6 left-1/2 -translate-x-1/2 z-40 w-max max-w-[90vw] animate-in slide-in-from-bottom flex justify-center", className), children: /* @__PURE__ */ jsxs5("div", { className: "overflow-hidden rounded-full border border-border bg-card px-6 py-3 flex flex-wrap sm:flex-nowrap items-center justify-between gap-8 shadow-sm", children: [
|
|
686
|
+
/* @__PURE__ */ jsx6("div", { className: "flex items-center gap-6", children: items.map((item, i) => /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-2", children: [
|
|
687
|
+
/* @__PURE__ */ jsx6("span", { className: "text-[var(--md3-primary)] [&_svg]:h-[18px] [&_svg]:w-[18px]", children: item.icon }),
|
|
688
|
+
/* @__PURE__ */ jsxs5("div", { className: "flex flex-col", children: [
|
|
689
|
+
/* @__PURE__ */ jsx6("span", { className: "text-[10px] text-[var(--md3-on-surface-variant)] uppercase tracking-wider font-bold", children: item.label }),
|
|
690
|
+
/* @__PURE__ */ jsx6("span", { className: cn("text-xs font-bold text-foreground", item.valueClass), children: item.value })
|
|
606
691
|
] })
|
|
607
692
|
] }, i)) }),
|
|
608
|
-
latency && /* @__PURE__ */
|
|
609
|
-
/* @__PURE__ */
|
|
610
|
-
/* @__PURE__ */
|
|
611
|
-
/* @__PURE__ */
|
|
612
|
-
/* @__PURE__ */
|
|
613
|
-
/* @__PURE__ */
|
|
693
|
+
latency && /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
694
|
+
/* @__PURE__ */ jsx6("div", { className: "h-6 w-px bg-border" }),
|
|
695
|
+
/* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-3", children: [
|
|
696
|
+
/* @__PURE__ */ jsxs5("div", { className: "relative flex h-2.5 w-2.5 items-center justify-center", children: [
|
|
697
|
+
/* @__PURE__ */ jsx6("span", { className: "absolute inline-flex h-full w-full animate-ping rounded-full bg-green-400 opacity-75" }),
|
|
698
|
+
/* @__PURE__ */ jsx6("span", { className: "relative inline-flex h-2 w-2 rounded-full bg-green-500" })
|
|
614
699
|
] }),
|
|
615
|
-
/* @__PURE__ */
|
|
700
|
+
/* @__PURE__ */ jsx6("span", { className: "text-xs font-mono text-green-400 font-bold", children: latency })
|
|
616
701
|
] })
|
|
617
702
|
] })
|
|
618
703
|
] }) });
|
|
619
704
|
}
|
|
620
705
|
|
|
621
706
|
// src/dashboard/resource-meter.tsx
|
|
622
|
-
import { jsx as
|
|
707
|
+
import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
623
708
|
function getBarColor(percent) {
|
|
624
709
|
if (percent >= 90) return "bg-[var(--code-error)]";
|
|
625
710
|
if (percent >= 70) return "bg-[var(--surface-warning-text)]";
|
|
@@ -629,25 +714,25 @@ function ResourceMeter({ label, value, max = 100, unit, valueLabel, icon, classN
|
|
|
629
714
|
const percent = max > 0 ? Math.max(0, Math.min(value / max * 100, 100)) : 0;
|
|
630
715
|
const barColor = getBarColor(percent);
|
|
631
716
|
const readout = valueLabel ?? (unit ? `${value}${unit}/${max}${unit}` : `${Math.round(percent)}%`);
|
|
632
|
-
return /* @__PURE__ */
|
|
633
|
-
/* @__PURE__ */
|
|
717
|
+
return /* @__PURE__ */ jsxs6("div", { className: cn("flex items-center gap-3", className), children: [
|
|
718
|
+
/* @__PURE__ */ jsxs6("span", { className: "flex shrink-0 items-center gap-1 text-[10px] font-mono text-muted-foreground uppercase tracking-wide", children: [
|
|
634
719
|
icon,
|
|
635
720
|
label
|
|
636
721
|
] }),
|
|
637
|
-
/* @__PURE__ */
|
|
722
|
+
/* @__PURE__ */ jsx7("div", { className: "h-1.5 min-w-0 flex-1 bg-card rounded-full overflow-hidden", children: /* @__PURE__ */ jsx7(
|
|
638
723
|
"div",
|
|
639
724
|
{
|
|
640
725
|
className: cn("h-full rounded-full transition-all duration-500", barColor),
|
|
641
726
|
style: { width: `${percent}%` }
|
|
642
727
|
}
|
|
643
728
|
) }),
|
|
644
|
-
/* @__PURE__ */
|
|
729
|
+
/* @__PURE__ */ jsx7("span", { className: "shrink-0 text-[10px] font-mono tabular-nums text-muted-foreground", children: readout })
|
|
645
730
|
] });
|
|
646
731
|
}
|
|
647
732
|
|
|
648
733
|
// src/dashboard/resource-snapshot.tsx
|
|
649
734
|
import { Skeleton as Skeleton2 } from "@tangle-network/ui/primitives";
|
|
650
|
-
import { jsx as
|
|
735
|
+
import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
651
736
|
function ResourceSnapshot({
|
|
652
737
|
title = "Resources",
|
|
653
738
|
action,
|
|
@@ -657,7 +742,7 @@ function ResourceSnapshot({
|
|
|
657
742
|
className
|
|
658
743
|
}) {
|
|
659
744
|
const rowCount = items.length > 0 ? items.length : 3;
|
|
660
|
-
return /* @__PURE__ */
|
|
745
|
+
return /* @__PURE__ */ jsxs7(
|
|
661
746
|
"div",
|
|
662
747
|
{
|
|
663
748
|
className: cn(
|
|
@@ -665,11 +750,11 @@ function ResourceSnapshot({
|
|
|
665
750
|
className
|
|
666
751
|
),
|
|
667
752
|
children: [
|
|
668
|
-
/* @__PURE__ */
|
|
669
|
-
/* @__PURE__ */
|
|
753
|
+
/* @__PURE__ */ jsxs7("div", { className: "mb-4 flex items-center justify-between gap-2", children: [
|
|
754
|
+
/* @__PURE__ */ jsx8("h3", { className: "font-display font-semibold text-foreground text-sm", children: title }),
|
|
670
755
|
action
|
|
671
756
|
] }),
|
|
672
|
-
error ? /* @__PURE__ */
|
|
757
|
+
error ? /* @__PURE__ */ jsx8("p", { className: "text-[var(--surface-danger-text)] text-xs", children: error }) : loading ? /* @__PURE__ */ jsx8("div", { className: "space-y-3", children: Array.from({ length: rowCount }).map((_, i) => /* @__PURE__ */ jsx8(Skeleton2, { className: "h-4 w-full" }, i)) }) : /* @__PURE__ */ jsx8("div", { className: "space-y-3", children: items.map((item, idx) => /* @__PURE__ */ jsx8(
|
|
673
758
|
ResourceMeter,
|
|
674
759
|
{
|
|
675
760
|
label: item.label,
|
|
@@ -690,7 +775,7 @@ function ResourceSnapshot({
|
|
|
690
775
|
import * as React4 from "react";
|
|
691
776
|
import { Skeleton as Skeleton3 } from "@tangle-network/ui/primitives";
|
|
692
777
|
import { timeAgo } from "@tangle-network/ui/utils";
|
|
693
|
-
import { jsx as
|
|
778
|
+
import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
694
779
|
function ActivityFeed({
|
|
695
780
|
title = "Recent activity",
|
|
696
781
|
action,
|
|
@@ -704,7 +789,7 @@ function ActivityFeed({
|
|
|
704
789
|
() => [...items].sort((a, b) => (b.timestamp ?? 0) - (a.timestamp ?? 0)).slice(0, maxItems),
|
|
705
790
|
[items, maxItems]
|
|
706
791
|
);
|
|
707
|
-
return /* @__PURE__ */
|
|
792
|
+
return /* @__PURE__ */ jsxs8(
|
|
708
793
|
"div",
|
|
709
794
|
{
|
|
710
795
|
className: cn(
|
|
@@ -712,17 +797,17 @@ function ActivityFeed({
|
|
|
712
797
|
className
|
|
713
798
|
),
|
|
714
799
|
children: [
|
|
715
|
-
/* @__PURE__ */
|
|
716
|
-
/* @__PURE__ */
|
|
800
|
+
/* @__PURE__ */ jsxs8("div", { className: "mb-4 flex items-center justify-between gap-2", children: [
|
|
801
|
+
/* @__PURE__ */ jsx9("h3", { className: "font-display font-semibold text-foreground text-sm", children: title }),
|
|
717
802
|
action
|
|
718
803
|
] }),
|
|
719
|
-
loading ? /* @__PURE__ */
|
|
720
|
-
item.icon && /* @__PURE__ */
|
|
721
|
-
/* @__PURE__ */
|
|
722
|
-
/* @__PURE__ */
|
|
723
|
-
item.detail && /* @__PURE__ */
|
|
804
|
+
loading ? /* @__PURE__ */ jsx9("div", { className: "space-y-3", children: Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ jsx9(Skeleton3, { className: "h-9 w-full" }, i)) }) : sorted.length === 0 ? /* @__PURE__ */ jsx9("p", { className: "text-muted-foreground text-sm", children: emptyLabel }) : /* @__PURE__ */ jsx9("ul", { className: "space-y-3", children: sorted.map((item) => /* @__PURE__ */ jsxs8("li", { className: "flex items-start gap-3", children: [
|
|
805
|
+
item.icon && /* @__PURE__ */ jsx9("span", { className: "mt-0.5 shrink-0 text-muted-foreground", children: item.icon }),
|
|
806
|
+
/* @__PURE__ */ jsxs8("div", { className: "min-w-0 flex-1", children: [
|
|
807
|
+
/* @__PURE__ */ jsx9("p", { className: "truncate font-medium text-foreground text-sm", children: item.title }),
|
|
808
|
+
item.detail && /* @__PURE__ */ jsx9("p", { className: "truncate text-muted-foreground text-xs", children: item.detail })
|
|
724
809
|
] }),
|
|
725
|
-
item.timestamp != null && /* @__PURE__ */
|
|
810
|
+
item.timestamp != null && /* @__PURE__ */ jsx9("span", { className: "shrink-0 text-muted-foreground text-xs tabular-nums", children: timeAgo(item.timestamp) })
|
|
726
811
|
] }, item.id)) })
|
|
727
812
|
]
|
|
728
813
|
}
|
|
@@ -753,7 +838,7 @@ import {
|
|
|
753
838
|
Plus,
|
|
754
839
|
Users
|
|
755
840
|
} from "lucide-react";
|
|
756
|
-
import { Fragment as
|
|
841
|
+
import { Fragment as Fragment4, jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
757
842
|
function canAdminSandbox(sandbox) {
|
|
758
843
|
if (!sandbox.team) return true;
|
|
759
844
|
return sandbox.team.role === "owner" || sandbox.team.role === "admin";
|
|
@@ -776,115 +861,115 @@ function SandboxCard({
|
|
|
776
861
|
const isRunning = sandbox.status === "running";
|
|
777
862
|
const isTransitioning = sandbox.status === "provisioning" || sandbox.status === "creating";
|
|
778
863
|
const isStopped = !isRunning && !isTransitioning;
|
|
779
|
-
return /* @__PURE__ */
|
|
864
|
+
return /* @__PURE__ */ jsxs9("div", { className: cn(
|
|
780
865
|
"group relative flex flex-col justify-between overflow-hidden rounded-lg border bg-card p-5 transition-colors",
|
|
781
866
|
isRunning ? "border-[var(--status-running)]/30" : "border-border",
|
|
782
867
|
"hover:border-foreground/15",
|
|
783
868
|
className
|
|
784
869
|
), children: [
|
|
785
|
-
/* @__PURE__ */
|
|
786
|
-
/* @__PURE__ */
|
|
787
|
-
/* @__PURE__ */
|
|
788
|
-
/* @__PURE__ */
|
|
870
|
+
/* @__PURE__ */ jsxs9("div", { className: "flex items-start justify-between", children: [
|
|
871
|
+
/* @__PURE__ */ jsxs9("div", { children: [
|
|
872
|
+
/* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-2", children: [
|
|
873
|
+
/* @__PURE__ */ jsxs9("h3", { className: "flex items-center gap-2 text-sm font-bold text-foreground", children: [
|
|
789
874
|
sandbox.name,
|
|
790
|
-
isRunning && /* @__PURE__ */
|
|
791
|
-
/* @__PURE__ */
|
|
792
|
-
/* @__PURE__ */
|
|
875
|
+
isRunning && /* @__PURE__ */ jsxs9("span", { className: "relative flex h-2 w-2", children: [
|
|
876
|
+
/* @__PURE__ */ jsx10("span", { className: "absolute inline-flex h-full w-full animate-pulse rounded-full bg-[var(--status-running)] opacity-75" }),
|
|
877
|
+
/* @__PURE__ */ jsx10("span", { className: "relative inline-flex h-1.5 w-1.5 rounded-full bg-[var(--status-running)]" })
|
|
793
878
|
] })
|
|
794
879
|
] }),
|
|
795
|
-
sandbox.team && /* @__PURE__ */
|
|
880
|
+
sandbox.team && /* @__PURE__ */ jsxs9(
|
|
796
881
|
"span",
|
|
797
882
|
{
|
|
798
883
|
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)]",
|
|
799
884
|
title: `Shared with ${sandbox.team.name ?? "Team"} \xB7 ${sandbox.team.role}`,
|
|
800
885
|
children: [
|
|
801
|
-
/* @__PURE__ */
|
|
886
|
+
/* @__PURE__ */ jsx10(Users, { className: "h-3 w-3", "aria-hidden": "true" }),
|
|
802
887
|
sandbox.team.name ?? "Team"
|
|
803
888
|
]
|
|
804
889
|
}
|
|
805
890
|
)
|
|
806
891
|
] }),
|
|
807
|
-
/* @__PURE__ */
|
|
892
|
+
/* @__PURE__ */ jsxs9("p", { className: "mt-0.5 font-mono text-[10px] tracking-wider text-muted-foreground uppercase", children: [
|
|
808
893
|
sandbox.nodeId || "Unknown Node",
|
|
809
|
-
sandbox.team && /* @__PURE__ */
|
|
894
|
+
sandbox.team && /* @__PURE__ */ jsxs9("span", { className: "ml-2 normal-case tracking-normal", children: [
|
|
810
895
|
"\xB7 your role: ",
|
|
811
896
|
sandbox.team.role
|
|
812
897
|
] })
|
|
813
898
|
] })
|
|
814
899
|
] }),
|
|
815
|
-
/* @__PURE__ */
|
|
816
|
-
/* @__PURE__ */
|
|
900
|
+
/* @__PURE__ */ jsxs9(DropdownMenu2, { children: [
|
|
901
|
+
/* @__PURE__ */ jsx10(DropdownMenuTrigger2, { asChild: true, children: /* @__PURE__ */ jsx10(
|
|
817
902
|
"button",
|
|
818
903
|
{
|
|
819
904
|
type: "button",
|
|
820
905
|
className: "rounded-md p-1.5 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground outline-none",
|
|
821
906
|
"aria-label": "Sandbox options",
|
|
822
|
-
children: /* @__PURE__ */
|
|
907
|
+
children: /* @__PURE__ */ jsx10(MoreVertical, { className: "h-4 w-4" })
|
|
823
908
|
}
|
|
824
909
|
) }),
|
|
825
|
-
/* @__PURE__ */
|
|
826
|
-
isRunning && /* @__PURE__ */
|
|
827
|
-
onStop && /* @__PURE__ */
|
|
828
|
-
/* @__PURE__ */
|
|
910
|
+
/* @__PURE__ */ jsxs9(DropdownMenuContent2, { align: "end", className: "min-w-[180px]", children: [
|
|
911
|
+
isRunning && /* @__PURE__ */ jsxs9(Fragment4, { children: [
|
|
912
|
+
onStop && /* @__PURE__ */ jsxs9(DropdownMenuItem2, { onClick: () => onStop(sandbox.id), children: [
|
|
913
|
+
/* @__PURE__ */ jsx10(PowerOff, { className: "mr-2 h-4 w-4" }),
|
|
829
914
|
" Stop Sandbox"
|
|
830
915
|
] }),
|
|
831
|
-
onKeepAlive && /* @__PURE__ */
|
|
832
|
-
/* @__PURE__ */
|
|
916
|
+
onKeepAlive && /* @__PURE__ */ jsxs9(DropdownMenuItem2, { onClick: () => onKeepAlive(sandbox.id), children: [
|
|
917
|
+
/* @__PURE__ */ jsx10(Clock, { className: "mr-2 h-4 w-4" }),
|
|
833
918
|
" Keep Alive"
|
|
834
919
|
] }),
|
|
835
|
-
(onStop || onKeepAlive) && /* @__PURE__ */
|
|
836
|
-
onUsage && /* @__PURE__ */
|
|
837
|
-
/* @__PURE__ */
|
|
920
|
+
(onStop || onKeepAlive) && /* @__PURE__ */ jsx10(DropdownMenuSeparator2, {}),
|
|
921
|
+
onUsage && /* @__PURE__ */ jsxs9(DropdownMenuItem2, { onClick: () => onUsage(sandbox.id), children: [
|
|
922
|
+
/* @__PURE__ */ jsx10(BarChart2, { className: "mr-2 h-4 w-4" }),
|
|
838
923
|
" View Usage"
|
|
839
924
|
] }),
|
|
840
|
-
onHealth && /* @__PURE__ */
|
|
841
|
-
/* @__PURE__ */
|
|
925
|
+
onHealth && /* @__PURE__ */ jsxs9(DropdownMenuItem2, { onClick: () => onHealth(sandbox.id), children: [
|
|
926
|
+
/* @__PURE__ */ jsx10(Activity, { className: "mr-2 h-4 w-4" }),
|
|
842
927
|
" Health Check"
|
|
843
928
|
] }),
|
|
844
|
-
(onUsage || onHealth) && /* @__PURE__ */
|
|
845
|
-
onFork && /* @__PURE__ */
|
|
846
|
-
/* @__PURE__ */
|
|
847
|
-
/* @__PURE__ */
|
|
929
|
+
(onUsage || onHealth) && /* @__PURE__ */ jsx10(DropdownMenuSeparator2, {}),
|
|
930
|
+
onFork && /* @__PURE__ */ jsxs9(Fragment4, { children: [
|
|
931
|
+
/* @__PURE__ */ jsxs9(DropdownMenuItem2, { onClick: () => onFork(sandbox.id), children: [
|
|
932
|
+
/* @__PURE__ */ jsx10(Copy, { className: "mr-2 h-4 w-4" }),
|
|
848
933
|
" Fork Sandbox"
|
|
849
934
|
] }),
|
|
850
|
-
/* @__PURE__ */
|
|
935
|
+
/* @__PURE__ */ jsx10(DropdownMenuSeparator2, {})
|
|
851
936
|
] })
|
|
852
937
|
] }),
|
|
853
|
-
isStopped && /* @__PURE__ */
|
|
854
|
-
onResume && /* @__PURE__ */
|
|
855
|
-
/* @__PURE__ */
|
|
938
|
+
isStopped && /* @__PURE__ */ jsxs9(Fragment4, { children: [
|
|
939
|
+
onResume && /* @__PURE__ */ jsxs9(DropdownMenuItem2, { onClick: () => onResume(sandbox.id), children: [
|
|
940
|
+
/* @__PURE__ */ jsx10(Power, { className: "mr-2 h-4 w-4" }),
|
|
856
941
|
" Resume Sandbox"
|
|
857
942
|
] }),
|
|
858
|
-
onFork && /* @__PURE__ */
|
|
859
|
-
/* @__PURE__ */
|
|
943
|
+
onFork && /* @__PURE__ */ jsxs9(DropdownMenuItem2, { onClick: () => onFork(sandbox.id), children: [
|
|
944
|
+
/* @__PURE__ */ jsx10(Copy, { className: "mr-2 h-4 w-4" }),
|
|
860
945
|
" Fork Sandbox"
|
|
861
946
|
] }),
|
|
862
|
-
(onResume || onFork) && /* @__PURE__ */
|
|
947
|
+
(onResume || onFork) && /* @__PURE__ */ jsx10(DropdownMenuSeparator2, {})
|
|
863
948
|
] }),
|
|
864
|
-
onDelete && canAdminSandbox(sandbox) && /* @__PURE__ */
|
|
865
|
-
/* @__PURE__ */
|
|
949
|
+
onDelete && canAdminSandbox(sandbox) && /* @__PURE__ */ jsxs9(DropdownMenuItem2, { className: "text-destructive focus:bg-destructive/10 focus:text-destructive", onClick: () => onDelete(sandbox.id), children: [
|
|
950
|
+
/* @__PURE__ */ jsx10(Trash2, { className: "mr-2 h-4 w-4" }),
|
|
866
951
|
" Delete Sandbox"
|
|
867
952
|
] })
|
|
868
953
|
] })
|
|
869
954
|
] })
|
|
870
955
|
] }),
|
|
871
|
-
/* @__PURE__ */
|
|
872
|
-
/* @__PURE__ */
|
|
873
|
-
/* @__PURE__ */
|
|
874
|
-
/* @__PURE__ */
|
|
875
|
-
/* @__PURE__ */
|
|
876
|
-
/* @__PURE__ */
|
|
956
|
+
/* @__PURE__ */ jsxs9("div", { className: "my-4", children: [
|
|
957
|
+
/* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-3 rounded-md border border-border bg-muted/30 p-3", children: [
|
|
958
|
+
/* @__PURE__ */ jsx10("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__ */ jsx10(Code2, { className: cn("h-5 w-5", isRunning ? "text-[var(--surface-success-text)]" : "text-muted-foreground") }) : /* @__PURE__ */ jsx10(Terminal, { className: cn("h-5 w-5", isRunning ? "text-[var(--surface-success-text)]" : "text-muted-foreground") }) }),
|
|
959
|
+
/* @__PURE__ */ jsxs9("div", { className: "flex flex-col", children: [
|
|
960
|
+
/* @__PURE__ */ jsx10("span", { className: "text-[10px] text-muted-foreground uppercase tracking-widest font-bold", children: "Environment" }),
|
|
961
|
+
/* @__PURE__ */ jsx10("span", { className: "text-xs font-medium text-foreground font-mono mt-0.5", children: sandbox.image || "Universal" })
|
|
877
962
|
] })
|
|
878
963
|
] }),
|
|
879
|
-
isTransitioning && /* @__PURE__ */
|
|
880
|
-
/* @__PURE__ */
|
|
881
|
-
/* @__PURE__ */
|
|
882
|
-
/* @__PURE__ */
|
|
964
|
+
isTransitioning && /* @__PURE__ */ jsxs9("div", { className: "mt-3", children: [
|
|
965
|
+
/* @__PURE__ */ jsxs9("div", { className: "flex justify-between text-xs text-muted-foreground font-medium mb-1", children: [
|
|
966
|
+
/* @__PURE__ */ jsx10("span", { children: sandbox.provisioningMessage || "Starting..." }),
|
|
967
|
+
/* @__PURE__ */ jsxs9("span", { children: [
|
|
883
968
|
sandbox.provisioningPercent || 0,
|
|
884
969
|
"%"
|
|
885
970
|
] })
|
|
886
971
|
] }),
|
|
887
|
-
/* @__PURE__ */
|
|
972
|
+
/* @__PURE__ */ jsx10("div", { className: "h-1 w-full overflow-hidden rounded-full bg-muted", children: /* @__PURE__ */ jsx10(
|
|
888
973
|
"div",
|
|
889
974
|
{
|
|
890
975
|
className: "h-full bg-primary transition-all duration-500 rounded-full",
|
|
@@ -893,18 +978,18 @@ function SandboxCard({
|
|
|
893
978
|
) })
|
|
894
979
|
] })
|
|
895
980
|
] }),
|
|
896
|
-
/* @__PURE__ */
|
|
981
|
+
/* @__PURE__ */ jsx10("div", { className: "border-t border-border pt-3", children: isRunning ? /* @__PURE__ */ jsxs9(
|
|
897
982
|
"button",
|
|
898
983
|
{
|
|
899
984
|
type: "button",
|
|
900
985
|
onClick: () => onOpenIDE?.(sandbox.id),
|
|
901
986
|
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]",
|
|
902
987
|
children: [
|
|
903
|
-
/* @__PURE__ */
|
|
988
|
+
/* @__PURE__ */ jsx10(Network, { className: "h-4 w-4" }),
|
|
904
989
|
"Connect Session"
|
|
905
990
|
]
|
|
906
991
|
}
|
|
907
|
-
) : /* @__PURE__ */
|
|
992
|
+
) : /* @__PURE__ */ jsxs9(
|
|
908
993
|
"button",
|
|
909
994
|
{
|
|
910
995
|
type: "button",
|
|
@@ -915,7 +1000,7 @@ function SandboxCard({
|
|
|
915
1000
|
isTransitioning ? "bg-muted text-muted-foreground cursor-not-allowed border-border" : "bg-card text-foreground hover:bg-muted border-border active:scale-[0.97]"
|
|
916
1001
|
),
|
|
917
1002
|
children: [
|
|
918
|
-
/* @__PURE__ */
|
|
1003
|
+
/* @__PURE__ */ jsx10(Play, { className: "h-4 w-4" }),
|
|
919
1004
|
isTransitioning ? "Starting..." : "Wake Sandbox"
|
|
920
1005
|
]
|
|
921
1006
|
}
|
|
@@ -923,7 +1008,7 @@ function SandboxCard({
|
|
|
923
1008
|
] });
|
|
924
1009
|
}
|
|
925
1010
|
function NewSandboxCard({ onClick, className }) {
|
|
926
|
-
return /* @__PURE__ */
|
|
1011
|
+
return /* @__PURE__ */ jsxs9(
|
|
927
1012
|
"button",
|
|
928
1013
|
{
|
|
929
1014
|
type: "button",
|
|
@@ -933,9 +1018,9 @@ function NewSandboxCard({ onClick, className }) {
|
|
|
933
1018
|
className
|
|
934
1019
|
),
|
|
935
1020
|
children: [
|
|
936
|
-
/* @__PURE__ */
|
|
937
|
-
/* @__PURE__ */
|
|
938
|
-
/* @__PURE__ */
|
|
1021
|
+
/* @__PURE__ */ jsx10("div", { className: "flex h-12 w-12 items-center justify-center rounded-lg bg-muted text-muted-foreground", children: /* @__PURE__ */ jsx10(Plus, { className: "h-6 w-6" }) }),
|
|
1022
|
+
/* @__PURE__ */ jsx10("span", { className: "mt-4 text-sm font-semibold text-foreground", children: "New Sandbox" }),
|
|
1023
|
+
/* @__PURE__ */ jsx10("span", { className: "mt-1 text-xs text-muted-foreground", children: "Deploy a new isolated environment" })
|
|
939
1024
|
]
|
|
940
1025
|
}
|
|
941
1026
|
);
|
|
@@ -969,7 +1054,7 @@ import {
|
|
|
969
1054
|
DropdownMenuSeparator as DropdownMenuSeparator3,
|
|
970
1055
|
DropdownMenuTrigger as DropdownMenuTrigger3
|
|
971
1056
|
} from "@tangle-network/ui/primitives";
|
|
972
|
-
import { Fragment as
|
|
1057
|
+
import { Fragment as Fragment6, jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
973
1058
|
var statusColors = {
|
|
974
1059
|
running: { dot: "bg-[var(--code-success)] animate-pulse", text: "text-[var(--code-success)]", bar: "bg-[var(--code-success)]" },
|
|
975
1060
|
hibernating: { dot: "bg-muted-foreground", text: "text-muted-foreground", bar: "bg-muted-foreground" },
|
|
@@ -983,15 +1068,15 @@ function isResumable(status) {
|
|
|
983
1068
|
return status !== "running" && status !== "provisioning" && status !== "creating";
|
|
984
1069
|
}
|
|
985
1070
|
function MiniMeter({ label, percent, className }) {
|
|
986
|
-
return /* @__PURE__ */
|
|
987
|
-
/* @__PURE__ */
|
|
988
|
-
/* @__PURE__ */
|
|
989
|
-
/* @__PURE__ */
|
|
1071
|
+
return /* @__PURE__ */ jsxs10("div", { className: cn("space-y-1", className), children: [
|
|
1072
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex justify-between text-[10px] font-mono text-muted-foreground", children: [
|
|
1073
|
+
/* @__PURE__ */ jsx11("span", { className: "font-bold", children: label }),
|
|
1074
|
+
/* @__PURE__ */ jsxs10("span", { className: "text-primary", children: [
|
|
990
1075
|
percent,
|
|
991
1076
|
"%"
|
|
992
1077
|
] })
|
|
993
1078
|
] }),
|
|
994
|
-
/* @__PURE__ */
|
|
1079
|
+
/* @__PURE__ */ jsx11("div", { className: "h-1.5 w-full bg-background rounded-full overflow-hidden", children: /* @__PURE__ */ jsx11("div", { className: "h-full bg-primary rounded-full", style: { width: `${percent}%` } }) })
|
|
995
1080
|
] });
|
|
996
1081
|
}
|
|
997
1082
|
function SandboxTable({
|
|
@@ -1030,17 +1115,17 @@ function SandboxTable({
|
|
|
1030
1115
|
const handler = resolveResumeHandler(sb.status);
|
|
1031
1116
|
return handler ? () => handler(sb.id) : void 0;
|
|
1032
1117
|
};
|
|
1033
|
-
return /* @__PURE__ */
|
|
1034
|
-
/* @__PURE__ */
|
|
1035
|
-
/* @__PURE__ */
|
|
1036
|
-
/* @__PURE__ */
|
|
1037
|
-
/* @__PURE__ */
|
|
1038
|
-
hasTeamSandboxes && /* @__PURE__ */
|
|
1039
|
-
/* @__PURE__ */
|
|
1040
|
-
/* @__PURE__ */
|
|
1041
|
-
/* @__PURE__ */
|
|
1118
|
+
return /* @__PURE__ */ jsxs10("div", { className: cn("w-full", className), children: [
|
|
1119
|
+
/* @__PURE__ */ jsx11("div", { className: "w-full bg-card rounded-2xl overflow-hidden border border-border", children: /* @__PURE__ */ jsx11("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxs10("table", { className: "w-full text-left border-collapse", children: [
|
|
1120
|
+
/* @__PURE__ */ jsx11("thead", { children: /* @__PURE__ */ jsxs10("tr", { className: "bg-background border-b border-border", children: [
|
|
1121
|
+
/* @__PURE__ */ jsx11("th", { className: "px-6 py-4 text-xs font-semibold text-muted-foreground uppercase tracking-wider", children: "Status" }),
|
|
1122
|
+
/* @__PURE__ */ jsx11("th", { className: "px-6 py-4 text-xs font-semibold text-muted-foreground uppercase tracking-wider", children: "Sandbox Name" }),
|
|
1123
|
+
hasTeamSandboxes && /* @__PURE__ */ jsx11("th", { className: "px-6 py-4 text-xs font-semibold text-muted-foreground uppercase tracking-wider", children: "Scope" }),
|
|
1124
|
+
/* @__PURE__ */ jsx11("th", { className: "px-6 py-4 text-xs font-semibold text-muted-foreground uppercase tracking-wider", children: "Environment" }),
|
|
1125
|
+
/* @__PURE__ */ jsx11("th", { className: "px-6 py-4 text-xs font-semibold text-muted-foreground uppercase tracking-wider", children: "Resources" }),
|
|
1126
|
+
/* @__PURE__ */ jsx11("th", { className: "px-6 py-4 text-xs font-semibold text-muted-foreground uppercase tracking-wider text-right", children: "Actions" })
|
|
1042
1127
|
] }) }),
|
|
1043
|
-
/* @__PURE__ */
|
|
1128
|
+
/* @__PURE__ */ jsx11("tbody", { className: "divide-y divide-border", children: sandboxes.map((sb) => {
|
|
1044
1129
|
const sc = statusColors[sb.status] ?? statusColors.stopped;
|
|
1045
1130
|
const isActive = sb.status === "running";
|
|
1046
1131
|
const isHibernating = sb.status === "hibernating";
|
|
@@ -1062,7 +1147,7 @@ function SandboxTable({
|
|
|
1062
1147
|
// IDE, Delete, …), which keep their native
|
|
1063
1148
|
// semantics. Mouse users get the click-anywhere
|
|
1064
1149
|
// affordance; nobody loses access.
|
|
1065
|
-
/* @__PURE__ */
|
|
1150
|
+
/* @__PURE__ */ jsxs10(
|
|
1066
1151
|
"tr",
|
|
1067
1152
|
{
|
|
1068
1153
|
className: cn(
|
|
@@ -1071,69 +1156,69 @@ function SandboxTable({
|
|
|
1071
1156
|
),
|
|
1072
1157
|
onClick: onRowClick,
|
|
1073
1158
|
children: [
|
|
1074
|
-
/* @__PURE__ */
|
|
1075
|
-
/* @__PURE__ */
|
|
1076
|
-
/* @__PURE__ */
|
|
1159
|
+
/* @__PURE__ */ jsx11("td", { className: "px-6 py-5 whitespace-nowrap", children: /* @__PURE__ */ jsxs10("div", { className: "flex items-center gap-2", children: [
|
|
1160
|
+
/* @__PURE__ */ jsx11("span", { className: cn("flex h-2.5 w-2.5 rounded-full", sc.dot) }),
|
|
1161
|
+
/* @__PURE__ */ jsx11("span", { className: cn("text-xs font-bold uppercase tracking-wide", sc.text), children: sb.status.charAt(0).toUpperCase() + sb.status.slice(1) })
|
|
1077
1162
|
] }) }),
|
|
1078
|
-
/* @__PURE__ */
|
|
1079
|
-
/* @__PURE__ */
|
|
1080
|
-
sb.nodeId && /* @__PURE__ */
|
|
1163
|
+
/* @__PURE__ */ jsx11("td", { className: "px-6 py-5", children: /* @__PURE__ */ jsxs10("div", { className: "flex flex-col", children: [
|
|
1164
|
+
/* @__PURE__ */ jsx11("span", { className: "text-sm font-bold text-foreground group-hover:text-primary transition-colors", children: sb.name }),
|
|
1165
|
+
sb.nodeId && /* @__PURE__ */ jsx11("span", { className: "text-[10px] font-mono text-muted-foreground", children: sb.nodeId })
|
|
1081
1166
|
] }) }),
|
|
1082
|
-
hasTeamSandboxes && /* @__PURE__ */
|
|
1167
|
+
hasTeamSandboxes && /* @__PURE__ */ jsx11("td", { className: "px-6 py-5", children: sb.team ? /* @__PURE__ */ jsxs10(
|
|
1083
1168
|
"div",
|
|
1084
1169
|
{
|
|
1085
1170
|
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)]",
|
|
1086
1171
|
title: `Shared with ${sb.team.name ?? "Team"} \xB7 ${sb.team.role}`,
|
|
1087
1172
|
children: [
|
|
1088
|
-
/* @__PURE__ */
|
|
1089
|
-
/* @__PURE__ */
|
|
1090
|
-
/* @__PURE__ */
|
|
1173
|
+
/* @__PURE__ */ jsx11(Users2, { className: "h-3 w-3", "aria-hidden": "true" }),
|
|
1174
|
+
/* @__PURE__ */ jsx11("span", { children: sb.team.name ?? "Team" }),
|
|
1175
|
+
/* @__PURE__ */ jsxs10("span", { className: "font-normal text-muted-foreground", children: [
|
|
1091
1176
|
"\xB7 ",
|
|
1092
1177
|
sb.team.role
|
|
1093
1178
|
] })
|
|
1094
1179
|
]
|
|
1095
1180
|
}
|
|
1096
|
-
) : /* @__PURE__ */
|
|
1181
|
+
) : /* @__PURE__ */ jsxs10(
|
|
1097
1182
|
"div",
|
|
1098
1183
|
{
|
|
1099
1184
|
className: "inline-flex items-center gap-1.5 rounded-full bg-muted px-2.5 py-1 text-[11px] font-medium text-muted-foreground",
|
|
1100
1185
|
title: "Personal sandbox",
|
|
1101
1186
|
children: [
|
|
1102
|
-
/* @__PURE__ */
|
|
1187
|
+
/* @__PURE__ */ jsx11(User, { className: "h-3 w-3", "aria-hidden": "true" }),
|
|
1103
1188
|
"Personal"
|
|
1104
1189
|
]
|
|
1105
1190
|
}
|
|
1106
1191
|
) }),
|
|
1107
|
-
/* @__PURE__ */
|
|
1108
|
-
sb.imageIcon && /* @__PURE__ */
|
|
1109
|
-
sb.image && /* @__PURE__ */
|
|
1192
|
+
/* @__PURE__ */ jsx11("td", { className: "px-6 py-5", children: /* @__PURE__ */ jsxs10("div", { className: "flex items-center gap-3", children: [
|
|
1193
|
+
sb.imageIcon && /* @__PURE__ */ jsx11("div", { className: "w-8 h-8 rounded-lg bg-muted/50 flex items-center justify-center", children: sb.imageIcon }),
|
|
1194
|
+
sb.image && /* @__PURE__ */ jsx11("span", { className: "text-xs font-bold text-foreground", children: sb.image })
|
|
1110
1195
|
] }) }),
|
|
1111
|
-
/* @__PURE__ */
|
|
1112
|
-
/* @__PURE__ */
|
|
1113
|
-
/* @__PURE__ */
|
|
1114
|
-
] }) : isProvisioning ? /* @__PURE__ */
|
|
1115
|
-
/* @__PURE__ */
|
|
1196
|
+
/* @__PURE__ */ jsx11("td", { className: "px-6 py-5", children: isActive ? /* @__PURE__ */ jsxs10("div", { className: "space-y-3 w-48", children: [
|
|
1197
|
+
/* @__PURE__ */ jsx11(MiniMeter, { label: "CPU", percent: sb.cpuPercent ?? 0 }),
|
|
1198
|
+
/* @__PURE__ */ jsx11(MiniMeter, { label: "RAM", percent: sb.ramTotal ? Math.round((sb.ramUsed ?? 0) / sb.ramTotal * 100) : 0 })
|
|
1199
|
+
] }) : isProvisioning ? /* @__PURE__ */ jsxs10("div", { className: "flex items-center gap-2 text-primary italic text-[10px] font-bold", children: [
|
|
1200
|
+
/* @__PURE__ */ jsx11(RefreshCw, { className: "h-3.5 w-3.5 animate-spin" }),
|
|
1116
1201
|
sb.provisioningMessage ?? "Allocating nodes..."
|
|
1117
|
-
] }) : isHibernating ? /* @__PURE__ */
|
|
1118
|
-
/* @__PURE__ */
|
|
1119
|
-
/* @__PURE__ */
|
|
1202
|
+
] }) : isHibernating ? /* @__PURE__ */ jsxs10("div", { className: "space-y-3 w-48 opacity-30", children: [
|
|
1203
|
+
/* @__PURE__ */ jsx11(MiniMeter, { label: "CPU", percent: 0 }),
|
|
1204
|
+
/* @__PURE__ */ jsx11(MiniMeter, { label: "RAM", percent: 0 })
|
|
1120
1205
|
] }) : null }),
|
|
1121
|
-
/* @__PURE__ */
|
|
1122
|
-
isActive && /* @__PURE__ */
|
|
1123
|
-
/* @__PURE__ */
|
|
1206
|
+
/* @__PURE__ */ jsx11("td", { className: "px-6 py-5 text-right", children: /* @__PURE__ */ jsxs10("div", { className: "flex items-center justify-end gap-1", children: [
|
|
1207
|
+
isActive && /* @__PURE__ */ jsxs10(Fragment6, { children: [
|
|
1208
|
+
/* @__PURE__ */ jsx11("button", { type: "button", onClick: (e) => {
|
|
1124
1209
|
stopRowClick(e);
|
|
1125
1210
|
onOpenIDE?.(sb.id);
|
|
1126
|
-
}, className: "p-2 rounded-lg hover:bg-muted text-muted-foreground hover:text-foreground transition-all active:scale-90", title: "Open IDE", children: /* @__PURE__ */
|
|
1127
|
-
/* @__PURE__ */
|
|
1211
|
+
}, className: "p-2 rounded-lg hover:bg-muted text-muted-foreground hover:text-foreground transition-all active:scale-90", title: "Open IDE", children: /* @__PURE__ */ jsx11(Code22, { className: "h-4 w-4" }) }),
|
|
1212
|
+
/* @__PURE__ */ jsx11("button", { type: "button", onClick: (e) => {
|
|
1128
1213
|
stopRowClick(e);
|
|
1129
1214
|
onOpenTerminal?.(sb.id);
|
|
1130
|
-
}, className: "p-2 rounded-lg hover:bg-muted text-muted-foreground hover:text-foreground transition-all active:scale-90", title: "Terminal", children: /* @__PURE__ */
|
|
1131
|
-
/* @__PURE__ */
|
|
1215
|
+
}, className: "p-2 rounded-lg hover:bg-muted text-muted-foreground hover:text-foreground transition-all active:scale-90", title: "Terminal", children: /* @__PURE__ */ jsx11(Terminal2, { className: "h-4 w-4" }) }),
|
|
1216
|
+
/* @__PURE__ */ jsx11("button", { type: "button", onClick: (e) => {
|
|
1132
1217
|
stopRowClick(e);
|
|
1133
1218
|
onSSH?.(sb.id);
|
|
1134
|
-
}, className: "p-2 rounded-lg hover:bg-muted text-muted-foreground hover:text-foreground transition-all active:scale-90", title: "SSH", children: /* @__PURE__ */
|
|
1219
|
+
}, className: "p-2 rounded-lg hover:bg-muted text-muted-foreground hover:text-foreground transition-all active:scale-90", title: "SSH", children: /* @__PURE__ */ jsx11(Key, { className: "h-4 w-4" }) })
|
|
1135
1220
|
] }),
|
|
1136
|
-
resumeHandler && /* @__PURE__ */
|
|
1221
|
+
resumeHandler && /* @__PURE__ */ jsxs10(
|
|
1137
1222
|
"button",
|
|
1138
1223
|
{
|
|
1139
1224
|
type: "button",
|
|
@@ -1144,7 +1229,7 @@ function SandboxTable({
|
|
|
1144
1229
|
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",
|
|
1145
1230
|
title: resumeLabel,
|
|
1146
1231
|
children: [
|
|
1147
|
-
/* @__PURE__ */
|
|
1232
|
+
/* @__PURE__ */ jsx11(Play2, { className: "h-3 w-3" }),
|
|
1148
1233
|
resumeLabel
|
|
1149
1234
|
]
|
|
1150
1235
|
}
|
|
@@ -1158,55 +1243,55 @@ function SandboxTable({
|
|
|
1158
1243
|
if (isActive) {
|
|
1159
1244
|
const lifecycle = [];
|
|
1160
1245
|
if (onStop) lifecycle.push(
|
|
1161
|
-
/* @__PURE__ */
|
|
1162
|
-
/* @__PURE__ */
|
|
1246
|
+
/* @__PURE__ */ jsxs10(DropdownMenuItem3, { onClick: runItem(onStop), children: [
|
|
1247
|
+
/* @__PURE__ */ jsx11(PowerOff2, { className: "mr-2 h-4 w-4" }),
|
|
1163
1248
|
" Stop Sandbox"
|
|
1164
1249
|
] }, "stop")
|
|
1165
1250
|
);
|
|
1166
1251
|
if (onKeepAlive) lifecycle.push(
|
|
1167
|
-
/* @__PURE__ */
|
|
1168
|
-
/* @__PURE__ */
|
|
1252
|
+
/* @__PURE__ */ jsxs10(DropdownMenuItem3, { onClick: runItem(onKeepAlive), children: [
|
|
1253
|
+
/* @__PURE__ */ jsx11(Clock2, { className: "mr-2 h-4 w-4" }),
|
|
1169
1254
|
" Keep Alive"
|
|
1170
1255
|
] }, "keep-alive")
|
|
1171
1256
|
);
|
|
1172
1257
|
if (lifecycle.length) overflowSections.push(lifecycle);
|
|
1173
1258
|
const observability = [];
|
|
1174
1259
|
if (onUsage) observability.push(
|
|
1175
|
-
/* @__PURE__ */
|
|
1176
|
-
/* @__PURE__ */
|
|
1260
|
+
/* @__PURE__ */ jsxs10(DropdownMenuItem3, { onClick: runItem(onUsage), children: [
|
|
1261
|
+
/* @__PURE__ */ jsx11(BarChart22, { className: "mr-2 h-4 w-4" }),
|
|
1177
1262
|
" View Usage"
|
|
1178
1263
|
] }, "usage")
|
|
1179
1264
|
);
|
|
1180
1265
|
if (onHealth) observability.push(
|
|
1181
|
-
/* @__PURE__ */
|
|
1182
|
-
/* @__PURE__ */
|
|
1266
|
+
/* @__PURE__ */ jsxs10(DropdownMenuItem3, { onClick: runItem(onHealth), children: [
|
|
1267
|
+
/* @__PURE__ */ jsx11(Activity2, { className: "mr-2 h-4 w-4" }),
|
|
1183
1268
|
" Health Check"
|
|
1184
1269
|
] }, "health")
|
|
1185
1270
|
);
|
|
1186
1271
|
if (observability.length) overflowSections.push(observability);
|
|
1187
1272
|
if (onFork) overflowSections.push([
|
|
1188
|
-
/* @__PURE__ */
|
|
1189
|
-
/* @__PURE__ */
|
|
1273
|
+
/* @__PURE__ */ jsxs10(DropdownMenuItem3, { onClick: runItem(onFork), children: [
|
|
1274
|
+
/* @__PURE__ */ jsx11(Copy2, { className: "mr-2 h-4 w-4" }),
|
|
1190
1275
|
" Fork Sandbox"
|
|
1191
1276
|
] }, "fork")
|
|
1192
1277
|
]);
|
|
1193
1278
|
} else if (isResumable(sb.status)) {
|
|
1194
1279
|
if (onFork) overflowSections.push([
|
|
1195
|
-
/* @__PURE__ */
|
|
1196
|
-
/* @__PURE__ */
|
|
1280
|
+
/* @__PURE__ */ jsxs10(DropdownMenuItem3, { onClick: runItem(onFork), children: [
|
|
1281
|
+
/* @__PURE__ */ jsx11(Copy2, { className: "mr-2 h-4 w-4" }),
|
|
1197
1282
|
" Fork Sandbox"
|
|
1198
1283
|
] }, "fork")
|
|
1199
1284
|
]);
|
|
1200
1285
|
}
|
|
1201
1286
|
if (onMore) overflowSections.push([
|
|
1202
|
-
/* @__PURE__ */
|
|
1203
|
-
/* @__PURE__ */
|
|
1287
|
+
/* @__PURE__ */ jsxs10(DropdownMenuItem3, { onClick: runItem(onMore), children: [
|
|
1288
|
+
/* @__PURE__ */ jsx11(ExternalLink, { className: "mr-2 h-4 w-4" }),
|
|
1204
1289
|
" View Details"
|
|
1205
1290
|
] }, "view-details")
|
|
1206
1291
|
]);
|
|
1207
1292
|
if (overflowSections.length === 0) return null;
|
|
1208
|
-
return /* @__PURE__ */
|
|
1209
|
-
/* @__PURE__ */
|
|
1293
|
+
return /* @__PURE__ */ jsxs10(DropdownMenu3, { children: [
|
|
1294
|
+
/* @__PURE__ */ jsx11(DropdownMenuTrigger3, { asChild: true, children: /* @__PURE__ */ jsx11(
|
|
1210
1295
|
"button",
|
|
1211
1296
|
{
|
|
1212
1297
|
type: "button",
|
|
@@ -1214,19 +1299,19 @@ function SandboxTable({
|
|
|
1214
1299
|
className: "p-2 rounded-lg hover:bg-muted text-muted-foreground hover:text-foreground transition-all active:scale-90 outline-none",
|
|
1215
1300
|
"aria-label": "More actions",
|
|
1216
1301
|
title: "More actions",
|
|
1217
|
-
children: /* @__PURE__ */
|
|
1302
|
+
children: /* @__PURE__ */ jsx11(MoreVertical2, { className: "h-4 w-4" })
|
|
1218
1303
|
}
|
|
1219
1304
|
) }),
|
|
1220
|
-
/* @__PURE__ */
|
|
1221
|
-
sectionIdx > 0 && /* @__PURE__ */
|
|
1305
|
+
/* @__PURE__ */ jsx11(DropdownMenuContent3, { align: "end", className: "min-w-[180px]", children: overflowSections.map((section, sectionIdx) => /* @__PURE__ */ jsxs10(React5.Fragment, { children: [
|
|
1306
|
+
sectionIdx > 0 && /* @__PURE__ */ jsx11(DropdownMenuSeparator3, {}),
|
|
1222
1307
|
section
|
|
1223
1308
|
] }, sectionIdx)) })
|
|
1224
1309
|
] });
|
|
1225
1310
|
})(),
|
|
1226
|
-
onDelete && canAdminSandbox(sb) && /* @__PURE__ */
|
|
1311
|
+
onDelete && canAdminSandbox(sb) && /* @__PURE__ */ jsx11("button", { type: "button", onClick: (e) => {
|
|
1227
1312
|
stopRowClick(e);
|
|
1228
1313
|
onDelete(sb.id);
|
|
1229
|
-
}, 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__ */
|
|
1314
|
+
}, 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__ */ jsx11(Trash22, { className: "h-4 w-4" }) })
|
|
1230
1315
|
] }) })
|
|
1231
1316
|
]
|
|
1232
1317
|
},
|
|
@@ -1235,17 +1320,17 @@ function SandboxTable({
|
|
|
1235
1320
|
);
|
|
1236
1321
|
}) })
|
|
1237
1322
|
] }) }) }),
|
|
1238
|
-
totalPages > 1 && /* @__PURE__ */
|
|
1239
|
-
/* @__PURE__ */
|
|
1323
|
+
totalPages > 1 && /* @__PURE__ */ jsxs10("div", { className: "mt-6 flex flex-col md:flex-row justify-between items-center text-muted-foreground text-xs font-medium gap-4", children: [
|
|
1324
|
+
/* @__PURE__ */ jsxs10("p", { children: [
|
|
1240
1325
|
"Showing ",
|
|
1241
1326
|
sandboxes.length,
|
|
1242
1327
|
" of ",
|
|
1243
1328
|
totalCount,
|
|
1244
1329
|
" active sandboxes"
|
|
1245
1330
|
] }),
|
|
1246
|
-
/* @__PURE__ */
|
|
1247
|
-
/* @__PURE__ */
|
|
1248
|
-
Array.from({ length: Math.min(totalPages, 5) }, (_, i) => i + 1).map((p) => /* @__PURE__ */
|
|
1331
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex items-center gap-2", children: [
|
|
1332
|
+
/* @__PURE__ */ jsx11("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__ */ jsx11(ChevronLeft, { className: "h-4 w-4" }) }),
|
|
1333
|
+
Array.from({ length: Math.min(totalPages, 5) }, (_, i) => i + 1).map((p) => /* @__PURE__ */ jsx11(
|
|
1249
1334
|
"button",
|
|
1250
1335
|
{
|
|
1251
1336
|
type: "button",
|
|
@@ -1258,7 +1343,7 @@ function SandboxTable({
|
|
|
1258
1343
|
},
|
|
1259
1344
|
p
|
|
1260
1345
|
)),
|
|
1261
|
-
/* @__PURE__ */
|
|
1346
|
+
/* @__PURE__ */ jsx11("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__ */ jsx11(ChevronRight, { className: "h-4 w-4" }) })
|
|
1262
1347
|
] })
|
|
1263
1348
|
] })
|
|
1264
1349
|
] });
|
|
@@ -1266,51 +1351,51 @@ function SandboxTable({
|
|
|
1266
1351
|
|
|
1267
1352
|
// src/dashboard/invoice-table.tsx
|
|
1268
1353
|
import { Download, FileText } from "lucide-react";
|
|
1269
|
-
import { jsx as
|
|
1354
|
+
import { jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
1270
1355
|
var statusStyle = {
|
|
1271
1356
|
paid: "bg-[var(--accent-surface-soft)] text-primary border border-border",
|
|
1272
1357
|
pending: "bg-[var(--surface-warning-bg)] text-[var(--surface-warning-text)] border border-[var(--surface-warning-border)]",
|
|
1273
1358
|
failed: "bg-[var(--surface-danger-bg)] text-[var(--surface-danger-text)] border border-[var(--surface-danger-border)]"
|
|
1274
1359
|
};
|
|
1275
1360
|
function InvoiceTable({ invoices, onExportAll, onLoadMore, onViewInvoice, hasMore, className }) {
|
|
1276
|
-
return /* @__PURE__ */
|
|
1277
|
-
/* @__PURE__ */
|
|
1278
|
-
/* @__PURE__ */
|
|
1279
|
-
onExportAll && /* @__PURE__ */
|
|
1280
|
-
/* @__PURE__ */
|
|
1361
|
+
return /* @__PURE__ */ jsxs11("section", { className, children: [
|
|
1362
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex justify-between items-center mb-6 px-2", children: [
|
|
1363
|
+
/* @__PURE__ */ jsx12("h2", { className: "text-2xl font-bold text-foreground tracking-tight", children: "Invoice History" }),
|
|
1364
|
+
onExportAll && /* @__PURE__ */ jsxs11("button", { type: "button", onClick: onExportAll, className: "text-[10px] font-mono text-primary uppercase tracking-widest flex items-center gap-2 hover:underline", children: [
|
|
1365
|
+
/* @__PURE__ */ jsx12(Download, { className: "h-3.5 w-3.5" }),
|
|
1281
1366
|
"Export All"
|
|
1282
1367
|
] })
|
|
1283
1368
|
] }),
|
|
1284
|
-
/* @__PURE__ */
|
|
1285
|
-
/* @__PURE__ */
|
|
1286
|
-
/* @__PURE__ */
|
|
1287
|
-
/* @__PURE__ */
|
|
1288
|
-
/* @__PURE__ */
|
|
1289
|
-
/* @__PURE__ */
|
|
1290
|
-
/* @__PURE__ */
|
|
1369
|
+
/* @__PURE__ */ jsx12("div", { className: "bg-card rounded-xl overflow-hidden border border-border", children: /* @__PURE__ */ jsxs11("table", { className: "w-full text-left border-collapse", children: [
|
|
1370
|
+
/* @__PURE__ */ jsx12("thead", { children: /* @__PURE__ */ jsxs11("tr", { className: "bg-background border-b border-border", children: [
|
|
1371
|
+
/* @__PURE__ */ jsx12("th", { className: "px-6 py-4 font-mono text-[10px] text-muted-foreground uppercase tracking-widest", children: "Invoice ID" }),
|
|
1372
|
+
/* @__PURE__ */ jsx12("th", { className: "px-6 py-4 font-mono text-[10px] text-muted-foreground uppercase tracking-widest", children: "Date" }),
|
|
1373
|
+
/* @__PURE__ */ jsx12("th", { className: "px-6 py-4 font-mono text-[10px] text-muted-foreground uppercase tracking-widest", children: "Amount" }),
|
|
1374
|
+
/* @__PURE__ */ jsx12("th", { className: "px-6 py-4 font-mono text-[10px] text-muted-foreground uppercase tracking-widest", children: "Status" }),
|
|
1375
|
+
/* @__PURE__ */ jsx12("th", { className: "px-6 py-4 font-mono text-[10px] text-muted-foreground uppercase tracking-widest text-right", children: "Action" })
|
|
1291
1376
|
] }) }),
|
|
1292
|
-
/* @__PURE__ */
|
|
1293
|
-
/* @__PURE__ */
|
|
1294
|
-
/* @__PURE__ */
|
|
1295
|
-
/* @__PURE__ */
|
|
1377
|
+
/* @__PURE__ */ jsx12("tbody", { className: "divide-y divide-border", children: invoices.map((inv) => /* @__PURE__ */ jsxs11("tr", { className: "hover:bg-muted/50 transition-colors", children: [
|
|
1378
|
+
/* @__PURE__ */ jsx12("td", { className: "px-6 py-5 font-mono text-xs text-foreground", children: inv.id }),
|
|
1379
|
+
/* @__PURE__ */ jsx12("td", { className: "px-6 py-5 text-sm text-foreground", children: inv.date }),
|
|
1380
|
+
/* @__PURE__ */ jsxs11("td", { className: "px-6 py-5 text-sm font-bold text-foreground", children: [
|
|
1296
1381
|
"$",
|
|
1297
1382
|
inv.amount.toFixed(2)
|
|
1298
1383
|
] }),
|
|
1299
|
-
/* @__PURE__ */
|
|
1300
|
-
/* @__PURE__ */
|
|
1384
|
+
/* @__PURE__ */ jsx12("td", { className: "px-6 py-5", children: /* @__PURE__ */ jsx12("span", { className: cn("px-2 py-1 text-[10px] font-mono rounded uppercase", statusStyle[inv.status] ?? statusStyle.paid), children: inv.status }) }),
|
|
1385
|
+
/* @__PURE__ */ jsx12("td", { className: "px-6 py-5 text-right", children: /* @__PURE__ */ jsx12("button", { type: "button", onClick: () => onViewInvoice?.(inv.id), className: "text-muted-foreground hover:text-foreground transition-colors", children: /* @__PURE__ */ jsx12(FileText, { className: "h-4 w-4" }) }) })
|
|
1301
1386
|
] }, inv.id)) })
|
|
1302
1387
|
] }) }),
|
|
1303
|
-
hasMore && onLoadMore && /* @__PURE__ */
|
|
1388
|
+
hasMore && onLoadMore && /* @__PURE__ */ jsx12("div", { className: "mt-6 flex justify-center", children: /* @__PURE__ */ jsx12("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" }) })
|
|
1304
1389
|
] });
|
|
1305
1390
|
}
|
|
1306
1391
|
|
|
1307
1392
|
// src/dashboard/plan-cards.tsx
|
|
1308
1393
|
import { Check } from "lucide-react";
|
|
1309
|
-
import { jsx as
|
|
1394
|
+
import { jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
1310
1395
|
function PlanCards({ plans, className }) {
|
|
1311
|
-
return /* @__PURE__ */
|
|
1312
|
-
/* @__PURE__ */
|
|
1313
|
-
/* @__PURE__ */
|
|
1396
|
+
return /* @__PURE__ */ jsxs12("section", { className, children: [
|
|
1397
|
+
/* @__PURE__ */ jsx13("h2", { className: "text-2xl font-bold text-foreground tracking-tight mb-5 px-2", children: "Subscription Plans" }),
|
|
1398
|
+
/* @__PURE__ */ jsx13("div", { className: "grid grid-cols-1 md:grid-cols-3 gap-6", children: plans.map((plan) => /* @__PURE__ */ jsxs12(
|
|
1314
1399
|
"div",
|
|
1315
1400
|
{
|
|
1316
1401
|
className: cn(
|
|
@@ -1318,23 +1403,23 @@ function PlanCards({ plans, className }) {
|
|
|
1318
1403
|
plan.popular ? "bg-muted/50 border-border" : "bg-card border-border hover:bg-muted/50 hover:border-primary/20"
|
|
1319
1404
|
),
|
|
1320
1405
|
children: [
|
|
1321
|
-
plan.popular && /* @__PURE__ */
|
|
1322
|
-
/* @__PURE__ */
|
|
1323
|
-
/* @__PURE__ */
|
|
1324
|
-
/* @__PURE__ */
|
|
1406
|
+
plan.popular && /* @__PURE__ */ jsx13("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" }),
|
|
1407
|
+
/* @__PURE__ */ jsxs12("div", { className: "mb-4", children: [
|
|
1408
|
+
/* @__PURE__ */ jsx13("div", { className: cn("text-xs font-mono uppercase tracking-widest mb-2", plan.popular ? "text-primary" : "text-muted-foreground"), children: plan.name }),
|
|
1409
|
+
/* @__PURE__ */ jsxs12("div", { className: "text-3xl font-bold text-foreground", children: [
|
|
1325
1410
|
"$",
|
|
1326
1411
|
plan.price,
|
|
1327
|
-
/* @__PURE__ */
|
|
1412
|
+
/* @__PURE__ */ jsxs12("span", { className: "text-sm font-normal text-muted-foreground tracking-normal", children: [
|
|
1328
1413
|
"/",
|
|
1329
1414
|
plan.period ?? "mo"
|
|
1330
1415
|
] })
|
|
1331
1416
|
] })
|
|
1332
1417
|
] }),
|
|
1333
|
-
/* @__PURE__ */
|
|
1334
|
-
/* @__PURE__ */
|
|
1418
|
+
/* @__PURE__ */ jsx13("ul", { className: "space-y-2 mb-5 text-sm text-muted-foreground", children: plan.features.map((f, i) => /* @__PURE__ */ jsxs12("li", { className: "flex items-center gap-2", children: [
|
|
1419
|
+
/* @__PURE__ */ jsx13(Check, { className: "h-3.5 w-3.5 text-primary shrink-0" }),
|
|
1335
1420
|
f.text
|
|
1336
1421
|
] }, i)) }),
|
|
1337
|
-
/* @__PURE__ */
|
|
1422
|
+
/* @__PURE__ */ jsx13(
|
|
1338
1423
|
"button",
|
|
1339
1424
|
{
|
|
1340
1425
|
type: "button",
|
|
@@ -1356,27 +1441,27 @@ function PlanCards({ plans, className }) {
|
|
|
1356
1441
|
// src/dashboard/dashboard-layout.tsx
|
|
1357
1442
|
import * as React6 from "react";
|
|
1358
1443
|
import { Plus as Plus2, Bell } from "lucide-react";
|
|
1359
|
-
import { Fragment as
|
|
1444
|
+
import { Fragment as Fragment8, jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
1360
1445
|
function SettingsIconSmall({ className }) {
|
|
1361
|
-
return /* @__PURE__ */
|
|
1362
|
-
/* @__PURE__ */
|
|
1363
|
-
/* @__PURE__ */
|
|
1364
|
-
/* @__PURE__ */
|
|
1446
|
+
return /* @__PURE__ */ jsxs13("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: [
|
|
1447
|
+
/* @__PURE__ */ jsx14("title", { children: "Settings" }),
|
|
1448
|
+
/* @__PURE__ */ jsx14("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" }),
|
|
1449
|
+
/* @__PURE__ */ jsx14("circle", { cx: "12", cy: "12", r: "3" })
|
|
1365
1450
|
] });
|
|
1366
1451
|
}
|
|
1367
1452
|
function MenuIcon({ className }) {
|
|
1368
|
-
return /* @__PURE__ */
|
|
1369
|
-
/* @__PURE__ */
|
|
1370
|
-
/* @__PURE__ */
|
|
1371
|
-
/* @__PURE__ */
|
|
1372
|
-
/* @__PURE__ */
|
|
1453
|
+
return /* @__PURE__ */ jsxs13("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: [
|
|
1454
|
+
/* @__PURE__ */ jsx14("title", { children: "Menu icon" }),
|
|
1455
|
+
/* @__PURE__ */ jsx14("line", { x1: "4", x2: "20", y1: "12", y2: "12" }),
|
|
1456
|
+
/* @__PURE__ */ jsx14("line", { x1: "4", x2: "20", y1: "6", y2: "6" }),
|
|
1457
|
+
/* @__PURE__ */ jsx14("line", { x1: "4", x2: "20", y1: "18", y2: "18" })
|
|
1373
1458
|
] });
|
|
1374
1459
|
}
|
|
1375
1460
|
function XIcon({ className }) {
|
|
1376
|
-
return /* @__PURE__ */
|
|
1377
|
-
/* @__PURE__ */
|
|
1378
|
-
/* @__PURE__ */
|
|
1379
|
-
/* @__PURE__ */
|
|
1461
|
+
return /* @__PURE__ */ jsxs13("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: [
|
|
1462
|
+
/* @__PURE__ */ jsx14("title", { children: "Close icon" }),
|
|
1463
|
+
/* @__PURE__ */ jsx14("path", { d: "M18 6 6 18" }),
|
|
1464
|
+
/* @__PURE__ */ jsx14("path", { d: "m6 6 12 12" })
|
|
1380
1465
|
] });
|
|
1381
1466
|
}
|
|
1382
1467
|
function formatNotifDate(raw) {
|
|
@@ -1390,7 +1475,7 @@ function DefaultLink2({
|
|
|
1390
1475
|
children,
|
|
1391
1476
|
...rest
|
|
1392
1477
|
}) {
|
|
1393
|
-
return /* @__PURE__ */
|
|
1478
|
+
return /* @__PURE__ */ jsx14("a", { href: href ?? to, className, ...rest, children });
|
|
1394
1479
|
}
|
|
1395
1480
|
function DashboardLayoutInner({
|
|
1396
1481
|
children,
|
|
@@ -1445,16 +1530,16 @@ function DashboardLayoutInner({
|
|
|
1445
1530
|
);
|
|
1446
1531
|
const activePanel = panels.find((p) => p.mode === mode);
|
|
1447
1532
|
const buildSidebarContent = React6.useCallback(
|
|
1448
|
-
(showLabels) => /* @__PURE__ */
|
|
1449
|
-
/* @__PURE__ */
|
|
1450
|
-
/* @__PURE__ */
|
|
1451
|
-
/* @__PURE__ */
|
|
1533
|
+
(showLabels) => /* @__PURE__ */ jsxs13(Fragment8, { children: [
|
|
1534
|
+
/* @__PURE__ */ jsxs13(SidebarRail, { wide: showLabels, children: [
|
|
1535
|
+
/* @__PURE__ */ jsx14(SidebarRailHeader, { children: /* @__PURE__ */ jsx14(Link, { href: "/", to: "/", className: "p-1 rounded-md transition-colors hover:bg-muted/50", children: /* @__PURE__ */ jsx14(Logo, { variant, size: "sm", iconOnly: true }) }) }),
|
|
1536
|
+
/* @__PURE__ */ jsx14(SidebarRailNav, { children: navItems.map((item, i) => {
|
|
1452
1537
|
const isMode = modeSet.has(item.id);
|
|
1453
1538
|
const prevIsMode = i > 0 && modeSet.has(navItems[i - 1].id);
|
|
1454
1539
|
const showSep = i > 0 && isMode && !prevIsMode;
|
|
1455
|
-
return /* @__PURE__ */
|
|
1456
|
-
showSep && /* @__PURE__ */
|
|
1457
|
-
isMode ? /* @__PURE__ */
|
|
1540
|
+
return /* @__PURE__ */ jsxs13(React6.Fragment, { children: [
|
|
1541
|
+
showSep && /* @__PURE__ */ jsx14(RailSeparator, {}),
|
|
1542
|
+
isMode ? /* @__PURE__ */ jsx14(
|
|
1458
1543
|
RailModeButton,
|
|
1459
1544
|
{
|
|
1460
1545
|
mode: item.id,
|
|
@@ -1463,7 +1548,7 @@ function DashboardLayoutInner({
|
|
|
1463
1548
|
badge: item.badge,
|
|
1464
1549
|
showLabel: showLabels
|
|
1465
1550
|
}
|
|
1466
|
-
) : /* @__PURE__ */
|
|
1551
|
+
) : /* @__PURE__ */ jsx14(Link, { href: item.href, to: item.href, children: /* @__PURE__ */ jsx14(
|
|
1467
1552
|
RailButton,
|
|
1468
1553
|
{
|
|
1469
1554
|
icon: item.icon,
|
|
@@ -1474,11 +1559,11 @@ function DashboardLayoutInner({
|
|
|
1474
1559
|
) })
|
|
1475
1560
|
] }, item.id);
|
|
1476
1561
|
}) }),
|
|
1477
|
-
/* @__PURE__ */
|
|
1478
|
-
onSettingsClick ? /* @__PURE__ */
|
|
1562
|
+
/* @__PURE__ */ jsxs13(SidebarRailFooter, { children: [
|
|
1563
|
+
onSettingsClick ? /* @__PURE__ */ jsx14(RailButton, { icon: SettingsIconSmall, label: "Settings", onClick: onSettingsClick, showLabel: showLabels }) : /* @__PURE__ */ jsx14(Link, { href: settingsHref, to: settingsHref, children: /* @__PURE__ */ jsx14(RailButton, { icon: SettingsIconSmall, label: "Settings", showLabel: showLabels }) }),
|
|
1479
1564
|
railFooter,
|
|
1480
|
-
/* @__PURE__ */
|
|
1481
|
-
/* @__PURE__ */
|
|
1565
|
+
/* @__PURE__ */ jsx14(RailSeparator, {}),
|
|
1566
|
+
/* @__PURE__ */ jsx14(
|
|
1482
1567
|
ProfileAvatar,
|
|
1483
1568
|
{
|
|
1484
1569
|
user: sidebarUser,
|
|
@@ -1492,9 +1577,9 @@ function DashboardLayoutInner({
|
|
|
1492
1577
|
)
|
|
1493
1578
|
] })
|
|
1494
1579
|
] }),
|
|
1495
|
-
panels.length > 0 && /* @__PURE__ */
|
|
1496
|
-
/* @__PURE__ */
|
|
1497
|
-
/* @__PURE__ */
|
|
1580
|
+
panels.length > 0 && /* @__PURE__ */ jsxs13(SidebarPanel, { children: [
|
|
1581
|
+
/* @__PURE__ */ jsx14(SidebarPanelHeader, { title: activePanel?.title ?? mode }),
|
|
1582
|
+
/* @__PURE__ */ jsx14(SidebarPanelContent, { children: activePanel?.content })
|
|
1498
1583
|
] })
|
|
1499
1584
|
] }),
|
|
1500
1585
|
// biome-ignore lint/correctness/useExhaustiveDependencies: intentional — only the inputs that actually affect the sidebar tree
|
|
@@ -1519,8 +1604,8 @@ function DashboardLayoutInner({
|
|
|
1519
1604
|
);
|
|
1520
1605
|
const sidebarContent = React6.useMemo(() => buildSidebarContent(false), [buildSidebarContent]);
|
|
1521
1606
|
const mobileSidebarContent = React6.useMemo(() => buildSidebarContent(true), [buildSidebarContent]);
|
|
1522
|
-
return /* @__PURE__ */
|
|
1523
|
-
/* @__PURE__ */
|
|
1607
|
+
return /* @__PURE__ */ jsxs13("div", { className: cn("min-h-screen bg-background text-foreground", className), children: [
|
|
1608
|
+
/* @__PURE__ */ jsxs13(
|
|
1524
1609
|
"nav",
|
|
1525
1610
|
{
|
|
1526
1611
|
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",
|
|
@@ -1529,9 +1614,9 @@ function DashboardLayoutInner({
|
|
|
1529
1614
|
width: hidden ? "100%" : `calc(100% - ${contentMargin}px)`
|
|
1530
1615
|
},
|
|
1531
1616
|
children: [
|
|
1532
|
-
/* @__PURE__ */
|
|
1533
|
-
/* @__PURE__ */
|
|
1534
|
-
topNavLinks && topNavLinks.length > 0 && /* @__PURE__ */
|
|
1617
|
+
/* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-8", children: [
|
|
1618
|
+
/* @__PURE__ */ jsx14(Link, { href: "/", to: "/", className: "lg:hidden flex items-center p-1 rounded-md hover:bg-muted/50 transition-colors", children: /* @__PURE__ */ jsx14(Logo, { variant, size: "sm", iconOnly: true }) }),
|
|
1619
|
+
topNavLinks && topNavLinks.length > 0 && /* @__PURE__ */ jsx14("div", { className: "hidden md:flex gap-6", children: topNavLinks.map((link) => /* @__PURE__ */ jsx14(
|
|
1535
1620
|
Link,
|
|
1536
1621
|
{
|
|
1537
1622
|
href: link.href,
|
|
@@ -1545,21 +1630,21 @@ function DashboardLayoutInner({
|
|
|
1545
1630
|
link.href
|
|
1546
1631
|
)) })
|
|
1547
1632
|
] }),
|
|
1548
|
-
/* @__PURE__ */
|
|
1549
|
-
onNewSandbox && /* @__PURE__ */
|
|
1633
|
+
/* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-4", children: [
|
|
1634
|
+
onNewSandbox && /* @__PURE__ */ jsxs13(
|
|
1550
1635
|
"button",
|
|
1551
1636
|
{
|
|
1552
1637
|
type: "button",
|
|
1553
1638
|
onClick: onNewSandbox,
|
|
1554
1639
|
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",
|
|
1555
1640
|
children: [
|
|
1556
|
-
/* @__PURE__ */
|
|
1641
|
+
/* @__PURE__ */ jsx14(Plus2, { className: "h-3.5 w-3.5" }),
|
|
1557
1642
|
"New Sandbox"
|
|
1558
1643
|
]
|
|
1559
1644
|
}
|
|
1560
1645
|
),
|
|
1561
|
-
/* @__PURE__ */
|
|
1562
|
-
/* @__PURE__ */
|
|
1646
|
+
/* @__PURE__ */ jsxs13("div", { className: "relative", ref: notifRef, children: [
|
|
1647
|
+
/* @__PURE__ */ jsxs13(
|
|
1563
1648
|
"button",
|
|
1564
1649
|
{
|
|
1565
1650
|
type: "button",
|
|
@@ -1568,15 +1653,15 @@ function DashboardLayoutInner({
|
|
|
1568
1653
|
"aria-label": "Notifications",
|
|
1569
1654
|
"aria-expanded": notificationsOpen,
|
|
1570
1655
|
children: [
|
|
1571
|
-
/* @__PURE__ */
|
|
1572
|
-
(notifData?.unreadCount ?? 0) > 0 && /* @__PURE__ */
|
|
1656
|
+
/* @__PURE__ */ jsx14(Bell, { className: "h-4 w-4" }),
|
|
1657
|
+
(notifData?.unreadCount ?? 0) > 0 && /* @__PURE__ */ jsx14("span", { className: "absolute top-1 right-1 h-2 w-2 rounded-full bg-destructive" })
|
|
1573
1658
|
]
|
|
1574
1659
|
}
|
|
1575
1660
|
),
|
|
1576
|
-
notificationsOpen && /* @__PURE__ */
|
|
1577
|
-
/* @__PURE__ */
|
|
1578
|
-
/* @__PURE__ */
|
|
1579
|
-
(notifData?.unreadCount ?? 0) > 0 && notifData?.onMarkAllRead && /* @__PURE__ */
|
|
1661
|
+
notificationsOpen && /* @__PURE__ */ jsxs13("div", { className: "absolute right-0 top-full mt-2 w-80 rounded-lg border border-border bg-card shadow-[var(--shadow-dropdown)] z-50", children: [
|
|
1662
|
+
/* @__PURE__ */ jsxs13("div", { className: "flex items-center justify-between border-b border-border px-4 py-3", children: [
|
|
1663
|
+
/* @__PURE__ */ jsx14("p", { className: "font-bold text-foreground text-sm", children: "Notifications" }),
|
|
1664
|
+
(notifData?.unreadCount ?? 0) > 0 && notifData?.onMarkAllRead && /* @__PURE__ */ jsx14(
|
|
1580
1665
|
"button",
|
|
1581
1666
|
{
|
|
1582
1667
|
type: "button",
|
|
@@ -1588,11 +1673,11 @@ function DashboardLayoutInner({
|
|
|
1588
1673
|
}
|
|
1589
1674
|
)
|
|
1590
1675
|
] }),
|
|
1591
|
-
!notifData?.items || notifData.items.length === 0 ? /* @__PURE__ */
|
|
1592
|
-
/* @__PURE__ */
|
|
1593
|
-
/* @__PURE__ */
|
|
1594
|
-
/* @__PURE__ */
|
|
1595
|
-
] }) : /* @__PURE__ */
|
|
1676
|
+
!notifData?.items || notifData.items.length === 0 ? /* @__PURE__ */ jsxs13("div", { className: "flex flex-col items-center justify-center px-4 py-8 text-center", children: [
|
|
1677
|
+
/* @__PURE__ */ jsx14(Bell, { className: "h-8 w-8 text-muted-foreground/40 mb-2" }),
|
|
1678
|
+
/* @__PURE__ */ jsx14("p", { className: "text-muted-foreground text-sm", children: "No notifications yet" }),
|
|
1679
|
+
/* @__PURE__ */ jsx14("p", { className: "text-muted-foreground/60 text-xs mt-1", children: "We'll notify you about important updates" })
|
|
1680
|
+
] }) : /* @__PURE__ */ jsx14("div", { className: "max-h-80 overflow-y-auto", children: notifData.items.map((n) => /* @__PURE__ */ jsxs13(
|
|
1596
1681
|
"button",
|
|
1597
1682
|
{
|
|
1598
1683
|
type: "button",
|
|
@@ -1604,9 +1689,9 @@ function DashboardLayoutInner({
|
|
|
1604
1689
|
if (!n.read) notifData.onMarkRead?.(n.id);
|
|
1605
1690
|
},
|
|
1606
1691
|
children: [
|
|
1607
|
-
/* @__PURE__ */
|
|
1608
|
-
/* @__PURE__ */
|
|
1609
|
-
/* @__PURE__ */
|
|
1692
|
+
/* @__PURE__ */ jsx14("p", { className: cn("text-sm", !n.read ? "font-semibold text-foreground" : "text-muted-foreground"), children: n.title }),
|
|
1693
|
+
/* @__PURE__ */ jsx14("p", { className: "text-xs text-muted-foreground mt-0.5 line-clamp-2", children: n.message }),
|
|
1694
|
+
/* @__PURE__ */ jsx14("p", { className: "text-[10px] text-muted-foreground/50 mt-1", children: formatNotifDate(n.createdAt) })
|
|
1610
1695
|
]
|
|
1611
1696
|
},
|
|
1612
1697
|
n.id
|
|
@@ -1614,7 +1699,7 @@ function DashboardLayoutInner({
|
|
|
1614
1699
|
] })
|
|
1615
1700
|
] })
|
|
1616
1701
|
] }),
|
|
1617
|
-
/* @__PURE__ */
|
|
1702
|
+
/* @__PURE__ */ jsx14(
|
|
1618
1703
|
"button",
|
|
1619
1704
|
{
|
|
1620
1705
|
type: "button",
|
|
@@ -1622,14 +1707,14 @@ function DashboardLayoutInner({
|
|
|
1622
1707
|
className: "rounded-md p-2 hover:bg-muted/50 lg:hidden",
|
|
1623
1708
|
"aria-label": mobileMenuOpen ? "Close menu" : "Open menu",
|
|
1624
1709
|
"aria-expanded": mobileMenuOpen,
|
|
1625
|
-
children: mobileMenuOpen ? /* @__PURE__ */
|
|
1710
|
+
children: mobileMenuOpen ? /* @__PURE__ */ jsx14(XIcon, { className: "h-6 w-6" }) : /* @__PURE__ */ jsx14(MenuIcon, { className: "h-6 w-6" })
|
|
1626
1711
|
}
|
|
1627
1712
|
)
|
|
1628
1713
|
]
|
|
1629
1714
|
}
|
|
1630
1715
|
),
|
|
1631
|
-
mobileMenuOpen && /* @__PURE__ */
|
|
1632
|
-
/* @__PURE__ */
|
|
1716
|
+
mobileMenuOpen && /* @__PURE__ */ jsx14("div", { className: "fixed inset-0 z-30 bg-black/50 lg:hidden", onClick: () => setMobileMenuOpen(false), "aria-hidden": "true" }),
|
|
1717
|
+
/* @__PURE__ */ jsx14(
|
|
1633
1718
|
"aside",
|
|
1634
1719
|
{
|
|
1635
1720
|
className: cn(
|
|
@@ -1642,17 +1727,17 @@ function DashboardLayoutInner({
|
|
|
1642
1727
|
children: mobileSidebarContent
|
|
1643
1728
|
}
|
|
1644
1729
|
),
|
|
1645
|
-
/* @__PURE__ */
|
|
1646
|
-
/* @__PURE__ */
|
|
1730
|
+
/* @__PURE__ */ jsx14(Sidebar, { className: cn("hidden lg:flex", sidebarClassName), children: sidebarContent }),
|
|
1731
|
+
/* @__PURE__ */ jsx14(SidebarContent, { className: cn("pt-16 px-6 pb-8 lg:px-8 bg-background", contentClassName), children }),
|
|
1647
1732
|
footer
|
|
1648
1733
|
] });
|
|
1649
1734
|
}
|
|
1650
1735
|
function DashboardLayout({ defaultPanelOpen, defaultMode, ...props }) {
|
|
1651
|
-
return /* @__PURE__ */
|
|
1736
|
+
return /* @__PURE__ */ jsx14(SidebarProvider, { defaultPanelOpen, defaultMode, hasPanels: (props.panels?.length ?? 0) > 0, children: /* @__PURE__ */ jsx14(DashboardLayoutInner, { defaultPanelOpen, defaultMode, ...props }) });
|
|
1652
1737
|
}
|
|
1653
1738
|
|
|
1654
1739
|
// src/dashboard/sidebar-layout.tsx
|
|
1655
|
-
import { jsx as
|
|
1740
|
+
import { jsx as jsx15, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
1656
1741
|
var HIDE_BELOW_CLASS = {
|
|
1657
1742
|
md: "max-md:hidden",
|
|
1658
1743
|
lg: "max-lg:hidden"
|
|
@@ -1664,7 +1749,7 @@ function DefaultLink3({
|
|
|
1664
1749
|
children,
|
|
1665
1750
|
...rest
|
|
1666
1751
|
}) {
|
|
1667
|
-
return /* @__PURE__ */
|
|
1752
|
+
return /* @__PURE__ */ jsx15("a", { href: href ?? to, className, ...rest, children });
|
|
1668
1753
|
}
|
|
1669
1754
|
function SidebarLayoutInner({
|
|
1670
1755
|
children,
|
|
@@ -1691,13 +1776,14 @@ function SidebarLayoutInner({
|
|
|
1691
1776
|
contentClassName
|
|
1692
1777
|
}) {
|
|
1693
1778
|
const Link = LinkComponent ?? DefaultLink3;
|
|
1694
|
-
const { panelOpen, togglePanel, setPanelOpen } = useSidebar();
|
|
1779
|
+
const { panelOpen, togglePanel, setPanelOpen, railCollapsed, toggleRail } = useSidebar();
|
|
1695
1780
|
const handleNavClick = closePanelOnNavigate && panelOpen ? () => setPanelOpen(false) : void 0;
|
|
1696
1781
|
const hasProfile = user !== void 0 || onLogout !== void 0 || onSettingsClick !== void 0;
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1782
|
+
const showLabels = railLabels && !railCollapsed;
|
|
1783
|
+
return /* @__PURE__ */ jsxs14("div", { className: cn("min-h-screen bg-background text-foreground", className), children: [
|
|
1784
|
+
/* @__PURE__ */ jsx15("div", { className: cn(hideBelow && HIDE_BELOW_CLASS[hideBelow]), children: /* @__PURE__ */ jsxs14(Sidebar, { className: sidebarClassName, children: [
|
|
1785
|
+
/* @__PURE__ */ jsxs14(SidebarRail, { children: [
|
|
1786
|
+
(railHeaderContent !== void 0 || logo !== void 0) && /* @__PURE__ */ jsx15(SidebarRailHeader, { className: cn(showLabels && (railHeaderContent !== void 0 ? "px-2" : "justify-start px-4")), children: railHeaderContent !== void 0 ? railHeaderContent : /* @__PURE__ */ jsx15(
|
|
1701
1787
|
Link,
|
|
1702
1788
|
{
|
|
1703
1789
|
href: logoHref,
|
|
@@ -1706,21 +1792,21 @@ function SidebarLayoutInner({
|
|
|
1706
1792
|
children: logo
|
|
1707
1793
|
}
|
|
1708
1794
|
) }),
|
|
1709
|
-
/* @__PURE__ */
|
|
1795
|
+
/* @__PURE__ */ jsx15(SidebarRailNav, { className: showLabels ? "px-2" : void 0, children: navItems.map((item) => {
|
|
1710
1796
|
if (item.flyoutItems && item.flyoutItems.length > 0) {
|
|
1711
1797
|
const activeSet = new Set(item.flyoutActiveIds ?? []);
|
|
1712
|
-
return /* @__PURE__ */
|
|
1798
|
+
return /* @__PURE__ */ jsx15(
|
|
1713
1799
|
RailFlyout,
|
|
1714
1800
|
{
|
|
1715
1801
|
icon: item.icon,
|
|
1716
1802
|
label: item.label,
|
|
1717
1803
|
title: item.label,
|
|
1718
|
-
showLabel:
|
|
1804
|
+
showLabel: showLabels,
|
|
1719
1805
|
isActive: activeId === item.id || item.flyoutItems.some((f) => activeSet.has(f.id)),
|
|
1720
1806
|
children: item.flyoutItems.map((f) => {
|
|
1721
1807
|
const FIcon = f.icon;
|
|
1722
1808
|
const active = activeSet.has(f.id);
|
|
1723
|
-
return /* @__PURE__ */
|
|
1809
|
+
return /* @__PURE__ */ jsxs14(
|
|
1724
1810
|
Link,
|
|
1725
1811
|
{
|
|
1726
1812
|
href: f.href,
|
|
@@ -1732,8 +1818,8 @@ function SidebarLayoutInner({
|
|
|
1732
1818
|
active ? "bg-[var(--accent-surface-strong)] font-medium text-[var(--accent-text)]" : "text-muted-foreground hover:bg-[var(--accent-surface-soft)] hover:text-[var(--accent-text)]"
|
|
1733
1819
|
),
|
|
1734
1820
|
children: [
|
|
1735
|
-
/* @__PURE__ */
|
|
1736
|
-
/* @__PURE__ */
|
|
1821
|
+
/* @__PURE__ */ jsx15(FIcon, { className: "h-4 w-4 shrink-0" }),
|
|
1822
|
+
/* @__PURE__ */ jsx15("span", { className: "truncate", children: f.label })
|
|
1737
1823
|
]
|
|
1738
1824
|
},
|
|
1739
1825
|
f.id
|
|
@@ -1743,7 +1829,7 @@ function SidebarLayoutInner({
|
|
|
1743
1829
|
item.id
|
|
1744
1830
|
);
|
|
1745
1831
|
}
|
|
1746
|
-
return item.togglesPanel ? /* @__PURE__ */
|
|
1832
|
+
return item.togglesPanel ? /* @__PURE__ */ jsx15(
|
|
1747
1833
|
RailButton,
|
|
1748
1834
|
{
|
|
1749
1835
|
icon: item.icon,
|
|
@@ -1751,10 +1837,10 @@ function SidebarLayoutInner({
|
|
|
1751
1837
|
badge: item.badge,
|
|
1752
1838
|
isActive: panelOpen,
|
|
1753
1839
|
onClick: togglePanel,
|
|
1754
|
-
showLabel:
|
|
1840
|
+
showLabel: showLabels
|
|
1755
1841
|
},
|
|
1756
1842
|
item.id
|
|
1757
|
-
) : /* @__PURE__ */
|
|
1843
|
+
) : /* @__PURE__ */ jsx15(RailButton, { icon: item.icon, label: item.label, badge: item.badge, isActive: activeId === item.id, showLabel: showLabels, asChild: true, children: /* @__PURE__ */ jsx15(
|
|
1758
1844
|
Link,
|
|
1759
1845
|
{
|
|
1760
1846
|
href: item.href,
|
|
@@ -1764,10 +1850,11 @@ function SidebarLayoutInner({
|
|
|
1764
1850
|
}
|
|
1765
1851
|
) }, item.id);
|
|
1766
1852
|
}) }),
|
|
1767
|
-
(railFooter !== void 0 || hasProfile) && /* @__PURE__ */
|
|
1853
|
+
(railLabels || railFooter !== void 0 || hasProfile) && /* @__PURE__ */ jsxs14(SidebarRailFooter, { className: cn("border-t border-border pt-2", showLabels && "items-stretch px-2"), children: [
|
|
1854
|
+
railLabels && /* @__PURE__ */ jsx15(RailCollapseToggle, { collapsed: railCollapsed, showLabel: showLabels, onToggle: toggleRail }),
|
|
1768
1855
|
railFooter,
|
|
1769
1856
|
hasProfile && (() => {
|
|
1770
|
-
const profile = /* @__PURE__ */
|
|
1857
|
+
const profile = /* @__PURE__ */ jsx15(
|
|
1771
1858
|
ProfileAvatar,
|
|
1772
1859
|
{
|
|
1773
1860
|
user: user ?? void 0,
|
|
@@ -1775,42 +1862,48 @@ function SidebarLayoutInner({
|
|
|
1775
1862
|
onLogout,
|
|
1776
1863
|
onSettingsClick,
|
|
1777
1864
|
settingsHref,
|
|
1778
|
-
showDetails:
|
|
1865
|
+
showDetails: showLabels,
|
|
1779
1866
|
LinkComponent: Link,
|
|
1780
1867
|
children: profileMenuItems
|
|
1781
1868
|
}
|
|
1782
1869
|
);
|
|
1783
1870
|
if (!showThemeToggle) return profile;
|
|
1784
|
-
return
|
|
1785
|
-
/* @__PURE__ */
|
|
1786
|
-
/* @__PURE__ */
|
|
1787
|
-
] }) : /* @__PURE__ */
|
|
1788
|
-
/* @__PURE__ */
|
|
1871
|
+
return showLabels ? /* @__PURE__ */ jsxs14("div", { className: "flex w-full items-center gap-1", children: [
|
|
1872
|
+
/* @__PURE__ */ jsx15("div", { className: "min-w-0 flex-1", children: profile }),
|
|
1873
|
+
/* @__PURE__ */ jsx15(RailThemeToggle, {})
|
|
1874
|
+
] }) : /* @__PURE__ */ jsxs14("div", { className: "flex flex-col items-center gap-1", children: [
|
|
1875
|
+
/* @__PURE__ */ jsx15(RailThemeToggle, {}),
|
|
1789
1876
|
profile
|
|
1790
1877
|
] });
|
|
1791
1878
|
})()
|
|
1792
1879
|
] })
|
|
1793
1880
|
] }),
|
|
1794
|
-
panel != null && /* @__PURE__ */
|
|
1881
|
+
panel != null && /* @__PURE__ */ jsx15(SidebarPanel, { children: panel })
|
|
1795
1882
|
] }) }),
|
|
1796
|
-
/* @__PURE__ */
|
|
1883
|
+
/* @__PURE__ */ jsx15(SidebarContent, { className: contentClassName, children })
|
|
1797
1884
|
] });
|
|
1798
1885
|
}
|
|
1799
1886
|
function SidebarLayout({
|
|
1800
1887
|
panelOpen,
|
|
1801
1888
|
onPanelOpenChange,
|
|
1802
1889
|
defaultPanelOpen,
|
|
1890
|
+
railCollapsed,
|
|
1891
|
+
onRailCollapsedChange,
|
|
1892
|
+
defaultRailCollapsed,
|
|
1803
1893
|
...props
|
|
1804
1894
|
}) {
|
|
1805
|
-
return /* @__PURE__ */
|
|
1895
|
+
return /* @__PURE__ */ jsx15(
|
|
1806
1896
|
SidebarProvider,
|
|
1807
1897
|
{
|
|
1808
1898
|
panelOpen,
|
|
1809
1899
|
onPanelOpenChange,
|
|
1810
1900
|
defaultPanelOpen,
|
|
1901
|
+
railCollapsed,
|
|
1902
|
+
onRailCollapsedChange,
|
|
1903
|
+
defaultRailCollapsed,
|
|
1811
1904
|
hasPanels: props.panel != null,
|
|
1812
|
-
|
|
1813
|
-
children: /* @__PURE__ */
|
|
1905
|
+
labeledRail: props.railLabels ?? false,
|
|
1906
|
+
children: /* @__PURE__ */ jsx15(SidebarLayoutInner, { ...props })
|
|
1814
1907
|
}
|
|
1815
1908
|
);
|
|
1816
1909
|
}
|
|
@@ -1827,7 +1920,7 @@ import {
|
|
|
1827
1920
|
DropdownMenuSeparator as DropdownMenuSeparator4,
|
|
1828
1921
|
DropdownMenuTrigger as DropdownMenuTrigger4
|
|
1829
1922
|
} from "@tangle-network/ui/primitives";
|
|
1830
|
-
import { Fragment as
|
|
1923
|
+
import { Fragment as Fragment9, jsx as jsx16, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
1831
1924
|
function ProfileSelector({
|
|
1832
1925
|
profiles,
|
|
1833
1926
|
selectedId,
|
|
@@ -1842,77 +1935,77 @@ function ProfileSelector({
|
|
|
1842
1935
|
const selected = profiles.find((p) => p.id === selectedId);
|
|
1843
1936
|
const builtinProfiles = profiles.filter((p) => p.is_builtin);
|
|
1844
1937
|
const customProfiles = profiles.filter((p) => !p.is_builtin);
|
|
1845
|
-
return /* @__PURE__ */
|
|
1846
|
-
label && /* @__PURE__ */
|
|
1847
|
-
/* @__PURE__ */
|
|
1848
|
-
/* @__PURE__ */
|
|
1849
|
-
/* @__PURE__ */
|
|
1850
|
-
/* @__PURE__ */
|
|
1938
|
+
return /* @__PURE__ */ jsxs15("div", { className, children: [
|
|
1939
|
+
label && /* @__PURE__ */ jsx16("label", { className: "mb-2 block font-medium text-sm", children: label }),
|
|
1940
|
+
/* @__PURE__ */ jsxs15(DropdownMenu4, { children: [
|
|
1941
|
+
/* @__PURE__ */ jsx16(DropdownMenuTrigger4, { asChild: true, children: /* @__PURE__ */ jsxs15(Button2, { variant: "outline", className: "w-full justify-between", children: [
|
|
1942
|
+
/* @__PURE__ */ jsx16("span", { className: "truncate", children: selected ? selected.name : placeholder }),
|
|
1943
|
+
/* @__PURE__ */ jsx16(ChevronDown, { className: "ml-2 h-4 w-4 shrink-0 opacity-50" })
|
|
1851
1944
|
] }) }),
|
|
1852
|
-
/* @__PURE__ */
|
|
1853
|
-
/* @__PURE__ */
|
|
1945
|
+
/* @__PURE__ */ jsxs15(DropdownMenuContent4, { className: "w-[300px]", align: "start", children: [
|
|
1946
|
+
/* @__PURE__ */ jsxs15(
|
|
1854
1947
|
DropdownMenuItem4,
|
|
1855
1948
|
{
|
|
1856
1949
|
onClick: () => onSelect(null),
|
|
1857
1950
|
className: "flex items-center justify-between",
|
|
1858
1951
|
children: [
|
|
1859
|
-
/* @__PURE__ */
|
|
1860
|
-
!selectedId && /* @__PURE__ */
|
|
1952
|
+
/* @__PURE__ */ jsx16("span", { children: placeholder }),
|
|
1953
|
+
!selectedId && /* @__PURE__ */ jsx16(Check2, { className: "h-4 w-4 text-[var(--surface-success-text)]" })
|
|
1861
1954
|
]
|
|
1862
1955
|
}
|
|
1863
1956
|
),
|
|
1864
|
-
builtinProfiles.length > 0 && /* @__PURE__ */
|
|
1865
|
-
/* @__PURE__ */
|
|
1866
|
-
/* @__PURE__ */
|
|
1867
|
-
builtinProfiles.map((profile) => /* @__PURE__ */
|
|
1957
|
+
builtinProfiles.length > 0 && /* @__PURE__ */ jsxs15(Fragment9, { children: [
|
|
1958
|
+
/* @__PURE__ */ jsx16(DropdownMenuSeparator4, {}),
|
|
1959
|
+
/* @__PURE__ */ jsx16(DropdownMenuLabel2, { children: "Built-in Profiles" }),
|
|
1960
|
+
builtinProfiles.map((profile) => /* @__PURE__ */ jsxs15(
|
|
1868
1961
|
DropdownMenuItem4,
|
|
1869
1962
|
{
|
|
1870
1963
|
onClick: () => onSelect(profile),
|
|
1871
1964
|
className: "flex flex-col items-start gap-1",
|
|
1872
1965
|
children: [
|
|
1873
|
-
/* @__PURE__ */
|
|
1874
|
-
/* @__PURE__ */
|
|
1875
|
-
/* @__PURE__ */
|
|
1876
|
-
profile.extends && /* @__PURE__ */
|
|
1966
|
+
/* @__PURE__ */ jsxs15("div", { className: "flex w-full items-center justify-between", children: [
|
|
1967
|
+
/* @__PURE__ */ jsxs15("div", { className: "flex items-center gap-2", children: [
|
|
1968
|
+
/* @__PURE__ */ jsx16("span", { className: "font-medium", children: profile.name }),
|
|
1969
|
+
profile.extends && /* @__PURE__ */ jsxs15(Badge, { variant: "secondary", className: "border-0 text-xs", children: [
|
|
1877
1970
|
"extends ",
|
|
1878
1971
|
profile.extends
|
|
1879
1972
|
] })
|
|
1880
1973
|
] }),
|
|
1881
|
-
selectedId === profile.id && /* @__PURE__ */
|
|
1974
|
+
selectedId === profile.id && /* @__PURE__ */ jsx16(Check2, { className: "h-4 w-4 text-[var(--surface-success-text)]" })
|
|
1882
1975
|
] }),
|
|
1883
|
-
profile.description && /* @__PURE__ */
|
|
1976
|
+
profile.description && /* @__PURE__ */ jsx16("span", { className: "line-clamp-1 text-muted-foreground text-xs", children: profile.description })
|
|
1884
1977
|
]
|
|
1885
1978
|
},
|
|
1886
1979
|
profile.id
|
|
1887
1980
|
))
|
|
1888
1981
|
] }),
|
|
1889
|
-
customProfiles.length > 0 && /* @__PURE__ */
|
|
1890
|
-
/* @__PURE__ */
|
|
1891
|
-
/* @__PURE__ */
|
|
1892
|
-
customProfiles.map((profile) => /* @__PURE__ */
|
|
1982
|
+
customProfiles.length > 0 && /* @__PURE__ */ jsxs15(Fragment9, { children: [
|
|
1983
|
+
/* @__PURE__ */ jsx16(DropdownMenuSeparator4, {}),
|
|
1984
|
+
/* @__PURE__ */ jsx16(DropdownMenuLabel2, { children: "Custom Profiles" }),
|
|
1985
|
+
customProfiles.map((profile) => /* @__PURE__ */ jsxs15(
|
|
1893
1986
|
DropdownMenuItem4,
|
|
1894
1987
|
{
|
|
1895
1988
|
onClick: () => onSelect(profile),
|
|
1896
1989
|
className: "flex flex-col items-start gap-1",
|
|
1897
1990
|
children: [
|
|
1898
|
-
/* @__PURE__ */
|
|
1899
|
-
/* @__PURE__ */
|
|
1900
|
-
/* @__PURE__ */
|
|
1901
|
-
profile.model && /* @__PURE__ */
|
|
1991
|
+
/* @__PURE__ */ jsxs15("div", { className: "flex w-full items-center justify-between", children: [
|
|
1992
|
+
/* @__PURE__ */ jsxs15("div", { className: "flex items-center gap-2", children: [
|
|
1993
|
+
/* @__PURE__ */ jsx16("span", { className: "font-medium", children: profile.name }),
|
|
1994
|
+
profile.model && /* @__PURE__ */ jsx16(Badge, { variant: "secondary", className: "border-0 text-xs", children: profile.model.split("/").pop() })
|
|
1902
1995
|
] }),
|
|
1903
|
-
selectedId === profile.id && /* @__PURE__ */
|
|
1996
|
+
selectedId === profile.id && /* @__PURE__ */ jsx16(Check2, { className: "h-4 w-4 text-[var(--surface-success-text)]" })
|
|
1904
1997
|
] }),
|
|
1905
|
-
profile.description && /* @__PURE__ */
|
|
1906
|
-
showMetrics && profile.metrics && profile.metrics.total_runs > 0 && /* @__PURE__ */
|
|
1907
|
-
/* @__PURE__ */
|
|
1998
|
+
profile.description && /* @__PURE__ */ jsx16("span", { className: "line-clamp-1 text-muted-foreground text-xs", children: profile.description }),
|
|
1999
|
+
showMetrics && profile.metrics && profile.metrics.total_runs > 0 && /* @__PURE__ */ jsxs15("div", { className: "flex gap-3 text-muted-foreground text-xs", children: [
|
|
2000
|
+
/* @__PURE__ */ jsxs15("span", { children: [
|
|
1908
2001
|
profile.metrics.total_runs,
|
|
1909
2002
|
" runs"
|
|
1910
2003
|
] }),
|
|
1911
|
-
/* @__PURE__ */
|
|
2004
|
+
/* @__PURE__ */ jsxs15("span", { children: [
|
|
1912
2005
|
profile.metrics.success_rate.toFixed(0),
|
|
1913
2006
|
"% success"
|
|
1914
2007
|
] }),
|
|
1915
|
-
/* @__PURE__ */
|
|
2008
|
+
/* @__PURE__ */ jsxs15("span", { children: [
|
|
1916
2009
|
"~",
|
|
1917
2010
|
(profile.metrics.avg_duration_ms / 1e3).toFixed(1),
|
|
1918
2011
|
"s avg"
|
|
@@ -1923,26 +2016,26 @@ function ProfileSelector({
|
|
|
1923
2016
|
profile.id
|
|
1924
2017
|
))
|
|
1925
2018
|
] }),
|
|
1926
|
-
(onCreateClick || onManageClick) && /* @__PURE__ */
|
|
1927
|
-
/* @__PURE__ */
|
|
1928
|
-
onCreateClick && /* @__PURE__ */
|
|
2019
|
+
(onCreateClick || onManageClick) && /* @__PURE__ */ jsxs15(Fragment9, { children: [
|
|
2020
|
+
/* @__PURE__ */ jsx16(DropdownMenuSeparator4, {}),
|
|
2021
|
+
onCreateClick && /* @__PURE__ */ jsxs15(
|
|
1929
2022
|
DropdownMenuItem4,
|
|
1930
2023
|
{
|
|
1931
2024
|
onClick: onCreateClick,
|
|
1932
2025
|
className: "text-[var(--surface-info-text)]",
|
|
1933
2026
|
children: [
|
|
1934
|
-
/* @__PURE__ */
|
|
2027
|
+
/* @__PURE__ */ jsx16(Plus3, { className: "mr-2 h-4 w-4" }),
|
|
1935
2028
|
"Create New Profile"
|
|
1936
2029
|
]
|
|
1937
2030
|
}
|
|
1938
2031
|
),
|
|
1939
|
-
onManageClick && /* @__PURE__ */
|
|
2032
|
+
onManageClick && /* @__PURE__ */ jsxs15(
|
|
1940
2033
|
DropdownMenuItem4,
|
|
1941
2034
|
{
|
|
1942
2035
|
onClick: onManageClick,
|
|
1943
2036
|
className: "text-muted-foreground",
|
|
1944
2037
|
children: [
|
|
1945
|
-
/* @__PURE__ */
|
|
2038
|
+
/* @__PURE__ */ jsx16(Settings, { className: "mr-2 h-4 w-4" }),
|
|
1946
2039
|
"Manage Profiles"
|
|
1947
2040
|
]
|
|
1948
2041
|
}
|
|
@@ -1968,26 +2061,26 @@ function ProfileComparison({
|
|
|
1968
2061
|
const fastestProfile = profilesWithMetrics.reduce(
|
|
1969
2062
|
(best, p) => (p.metrics?.avg_duration_ms ?? Number.POSITIVE_INFINITY) < (best.metrics?.avg_duration_ms ?? Number.POSITIVE_INFINITY) ? p : best
|
|
1970
2063
|
);
|
|
1971
|
-
return /* @__PURE__ */
|
|
1972
|
-
/* @__PURE__ */
|
|
1973
|
-
/* @__PURE__ */
|
|
2064
|
+
return /* @__PURE__ */ jsxs15("div", { className: `rounded-lg border border-border p-4 ${className ?? ""}`, children: [
|
|
2065
|
+
/* @__PURE__ */ jsx16("h4", { className: "mb-3 font-medium text-sm", children: "Profile Performance" }),
|
|
2066
|
+
/* @__PURE__ */ jsx16("div", { className: "space-y-3", children: profilesWithMetrics.map((profile) => {
|
|
1974
2067
|
const isBestSuccess = profile.id === bestSuccess.id;
|
|
1975
2068
|
const isFastest = profile.id === fastestProfile.id;
|
|
1976
|
-
return /* @__PURE__ */
|
|
2069
|
+
return /* @__PURE__ */ jsxs15(
|
|
1977
2070
|
"div",
|
|
1978
2071
|
{
|
|
1979
2072
|
className: "flex items-center justify-between gap-4",
|
|
1980
2073
|
children: [
|
|
1981
|
-
/* @__PURE__ */
|
|
1982
|
-
/* @__PURE__ */
|
|
1983
|
-
isBestSuccess && /* @__PURE__ */
|
|
1984
|
-
isFastest && !isBestSuccess && /* @__PURE__ */
|
|
2074
|
+
/* @__PURE__ */ jsxs15("div", { className: "flex items-center gap-2", children: [
|
|
2075
|
+
/* @__PURE__ */ jsx16("span", { className: "font-medium", children: profile.name }),
|
|
2076
|
+
isBestSuccess && /* @__PURE__ */ jsx16(Badge, { className: "border border-[var(--surface-success-border)] bg-[var(--surface-success-bg)] text-[var(--surface-success-text)] text-xs", children: "Best Success" }),
|
|
2077
|
+
isFastest && !isBestSuccess && /* @__PURE__ */ jsx16(Badge, { className: "border border-[var(--surface-info-border)] bg-[var(--surface-info-bg)] text-[var(--surface-info-text)] text-xs", children: "Fastest" })
|
|
1985
2078
|
] }),
|
|
1986
|
-
/* @__PURE__ */
|
|
1987
|
-
/* @__PURE__ */
|
|
1988
|
-
/* @__PURE__ */
|
|
2079
|
+
/* @__PURE__ */ jsxs15("div", { className: "flex items-center gap-4 text-sm", children: [
|
|
2080
|
+
/* @__PURE__ */ jsxs15("span", { children: [
|
|
2081
|
+
/* @__PURE__ */ jsx16("span", { className: "text-muted-foreground", children: "Success:" }),
|
|
1989
2082
|
" ",
|
|
1990
|
-
/* @__PURE__ */
|
|
2083
|
+
/* @__PURE__ */ jsxs15(
|
|
1991
2084
|
"span",
|
|
1992
2085
|
{
|
|
1993
2086
|
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)]",
|
|
@@ -1998,13 +2091,13 @@ function ProfileComparison({
|
|
|
1998
2091
|
}
|
|
1999
2092
|
)
|
|
2000
2093
|
] }),
|
|
2001
|
-
/* @__PURE__ */
|
|
2002
|
-
/* @__PURE__ */
|
|
2094
|
+
/* @__PURE__ */ jsxs15("span", { children: [
|
|
2095
|
+
/* @__PURE__ */ jsx16("span", { className: "text-muted-foreground", children: "Avg:" }),
|
|
2003
2096
|
" ",
|
|
2004
2097
|
((profile.metrics?.avg_duration_ms ?? 0) / 1e3).toFixed(1),
|
|
2005
2098
|
"s"
|
|
2006
2099
|
] }),
|
|
2007
|
-
/* @__PURE__ */
|
|
2100
|
+
/* @__PURE__ */ jsxs15("span", { className: "text-muted-foreground", children: [
|
|
2008
2101
|
profile.metrics?.total_runs,
|
|
2009
2102
|
" runs"
|
|
2010
2103
|
] })
|
|
@@ -2019,7 +2112,7 @@ function ProfileComparison({
|
|
|
2019
2112
|
|
|
2020
2113
|
// src/dashboard/metric-area-chart.tsx
|
|
2021
2114
|
import * as React7 from "react";
|
|
2022
|
-
import { jsx as
|
|
2115
|
+
import { jsx as jsx17, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
2023
2116
|
var TONE_VARS = {
|
|
2024
2117
|
primary: "var(--brand-primary, hsl(var(--primary)))",
|
|
2025
2118
|
success: "var(--status-running, #22c55e)",
|
|
@@ -2073,7 +2166,7 @@ function MetricAreaChart({
|
|
|
2073
2166
|
const yMax = maxValue ?? (observedMax > 0 ? observedMax * 1.1 : 1);
|
|
2074
2167
|
const segments = buildSegments(points, width, height, yMax);
|
|
2075
2168
|
const color = TONE_VARS[tone];
|
|
2076
|
-
return /* @__PURE__ */
|
|
2169
|
+
return /* @__PURE__ */ jsxs16(
|
|
2077
2170
|
"div",
|
|
2078
2171
|
{
|
|
2079
2172
|
className: cn(
|
|
@@ -2082,21 +2175,21 @@ function MetricAreaChart({
|
|
|
2082
2175
|
),
|
|
2083
2176
|
"data-testid": `metric-chart-${label.toLowerCase().replace(/\s+/g, "-")}`,
|
|
2084
2177
|
children: [
|
|
2085
|
-
/* @__PURE__ */
|
|
2086
|
-
/* @__PURE__ */
|
|
2087
|
-
/* @__PURE__ */
|
|
2088
|
-
/* @__PURE__ */
|
|
2089
|
-
detail && /* @__PURE__ */
|
|
2178
|
+
/* @__PURE__ */ jsxs16("div", { className: "flex items-baseline justify-between gap-3", children: [
|
|
2179
|
+
/* @__PURE__ */ jsx17("p", { className: "font-medium text-muted-foreground text-xs uppercase tracking-[0.12em]", children: label }),
|
|
2180
|
+
/* @__PURE__ */ jsxs16("div", { className: "text-right", children: [
|
|
2181
|
+
/* @__PURE__ */ jsx17("span", { className: "font-semibold text-foreground text-xl tabular-nums tracking-tight", children: latest === null ? "\u2014" : formatValue(latest) }),
|
|
2182
|
+
detail && /* @__PURE__ */ jsx17("span", { className: "ml-1.5 text-muted-foreground text-xs", children: detail })
|
|
2090
2183
|
] })
|
|
2091
2184
|
] }),
|
|
2092
|
-
/* @__PURE__ */
|
|
2185
|
+
/* @__PURE__ */ jsx17("div", { className: "mt-3", children: values.length === 0 ? /* @__PURE__ */ jsx17(
|
|
2093
2186
|
"div",
|
|
2094
2187
|
{
|
|
2095
2188
|
className: "flex items-center justify-center text-muted-foreground text-xs",
|
|
2096
2189
|
style: { height },
|
|
2097
2190
|
children: emptyState ?? "Waiting for samples\u2026"
|
|
2098
2191
|
}
|
|
2099
|
-
) : /* @__PURE__ */
|
|
2192
|
+
) : /* @__PURE__ */ jsxs16(
|
|
2100
2193
|
"svg",
|
|
2101
2194
|
{
|
|
2102
2195
|
viewBox: `0 0 ${width} ${height}`,
|
|
@@ -2106,7 +2199,7 @@ function MetricAreaChart({
|
|
|
2106
2199
|
role: "img",
|
|
2107
2200
|
"aria-label": `${label} chart`,
|
|
2108
2201
|
children: [
|
|
2109
|
-
[0.25, 0.5, 0.75].map((fraction) => /* @__PURE__ */
|
|
2202
|
+
[0.25, 0.5, 0.75].map((fraction) => /* @__PURE__ */ jsx17(
|
|
2110
2203
|
"line",
|
|
2111
2204
|
{
|
|
2112
2205
|
x1: 0,
|
|
@@ -2121,13 +2214,13 @@ function MetricAreaChart({
|
|
|
2121
2214
|
},
|
|
2122
2215
|
fraction
|
|
2123
2216
|
)),
|
|
2124
|
-
/* @__PURE__ */
|
|
2125
|
-
/* @__PURE__ */
|
|
2126
|
-
/* @__PURE__ */
|
|
2217
|
+
/* @__PURE__ */ jsx17("defs", { children: /* @__PURE__ */ jsxs16("linearGradient", { id: gradientId, x1: "0", y1: "0", x2: "0", y2: "1", children: [
|
|
2218
|
+
/* @__PURE__ */ jsx17("stop", { offset: "0%", stopColor: color, stopOpacity: 0.28 }),
|
|
2219
|
+
/* @__PURE__ */ jsx17("stop", { offset: "100%", stopColor: color, stopOpacity: 0.02 })
|
|
2127
2220
|
] }) }),
|
|
2128
|
-
segments.map((segment) => /* @__PURE__ */
|
|
2129
|
-
/* @__PURE__ */
|
|
2130
|
-
/* @__PURE__ */
|
|
2221
|
+
segments.map((segment) => /* @__PURE__ */ jsxs16(React7.Fragment, { children: [
|
|
2222
|
+
/* @__PURE__ */ jsx17("path", { d: segment.area, fill: `url(#${gradientId})` }),
|
|
2223
|
+
/* @__PURE__ */ jsx17(
|
|
2131
2224
|
"path",
|
|
2132
2225
|
{
|
|
2133
2226
|
d: segment.path,
|
|
@@ -2143,9 +2236,9 @@ function MetricAreaChart({
|
|
|
2143
2236
|
]
|
|
2144
2237
|
}
|
|
2145
2238
|
) }),
|
|
2146
|
-
/* @__PURE__ */
|
|
2147
|
-
/* @__PURE__ */
|
|
2148
|
-
/* @__PURE__ */
|
|
2239
|
+
/* @__PURE__ */ jsxs16("div", { className: "mt-1.5 flex justify-between text-[10px] text-muted-foreground tabular-nums", children: [
|
|
2240
|
+
/* @__PURE__ */ jsx17("span", { children: values.length > 0 ? formatValue(0) : "" }),
|
|
2241
|
+
/* @__PURE__ */ jsx17("span", { children: values.length > 0 ? formatValue(yMax) : "" })
|
|
2149
2242
|
] })
|
|
2150
2243
|
]
|
|
2151
2244
|
}
|
|
@@ -2165,7 +2258,7 @@ import {
|
|
|
2165
2258
|
} from "lucide-react";
|
|
2166
2259
|
import { Button as Button3 } from "@tangle-network/ui/primitives";
|
|
2167
2260
|
import { Badge as Badge2 } from "@tangle-network/ui/primitives";
|
|
2168
|
-
import { Fragment as
|
|
2261
|
+
import { Fragment as Fragment11, jsx as jsx18, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
2169
2262
|
var statusConfig = {
|
|
2170
2263
|
pending: {
|
|
2171
2264
|
icon: Clock3,
|
|
@@ -2249,19 +2342,19 @@ function VariantList({
|
|
|
2249
2342
|
isActioning,
|
|
2250
2343
|
className
|
|
2251
2344
|
}) {
|
|
2252
|
-
return /* @__PURE__ */
|
|
2345
|
+
return /* @__PURE__ */ jsx18("div", { className: `space-y-2 ${className || ""}`, children: variants.map((variant) => {
|
|
2253
2346
|
const status = statusConfig[variant.status];
|
|
2254
2347
|
const StatusIcon = status.icon;
|
|
2255
2348
|
const isSelected = variant.id === selectedId;
|
|
2256
|
-
return /* @__PURE__ */
|
|
2349
|
+
return /* @__PURE__ */ jsxs17(
|
|
2257
2350
|
"div",
|
|
2258
2351
|
{
|
|
2259
2352
|
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"}`,
|
|
2260
2353
|
onClick: () => onSelect?.(variant.id),
|
|
2261
2354
|
children: [
|
|
2262
|
-
/* @__PURE__ */
|
|
2263
|
-
/* @__PURE__ */
|
|
2264
|
-
/* @__PURE__ */
|
|
2355
|
+
/* @__PURE__ */ jsxs17("div", { className: "flex items-center gap-2", children: [
|
|
2356
|
+
/* @__PURE__ */ jsxs17(Badge2, { className: `shrink-0 ${status.bg} ${status.border} ${status.color}`, children: [
|
|
2357
|
+
/* @__PURE__ */ jsx18(
|
|
2265
2358
|
StatusIcon,
|
|
2266
2359
|
{
|
|
2267
2360
|
className: `mr-1 h-3 w-3 ${status.animate ? "animate-spin" : ""}`
|
|
@@ -2269,27 +2362,27 @@ function VariantList({
|
|
|
2269
2362
|
),
|
|
2270
2363
|
status.label
|
|
2271
2364
|
] }),
|
|
2272
|
-
/* @__PURE__ */
|
|
2273
|
-
variant.sublabel && /* @__PURE__ */
|
|
2365
|
+
/* @__PURE__ */ jsx18("span", { className: "truncate text-sm font-medium text-foreground", children: variant.label }),
|
|
2366
|
+
variant.sublabel && /* @__PURE__ */ jsxs17("span", { className: "shrink-0 text-xs text-muted-foreground", children: [
|
|
2274
2367
|
"(",
|
|
2275
2368
|
variant.sublabel,
|
|
2276
2369
|
")"
|
|
2277
2370
|
] }),
|
|
2278
|
-
variant.durationMs && /* @__PURE__ */
|
|
2279
|
-
/* @__PURE__ */
|
|
2371
|
+
variant.durationMs && /* @__PURE__ */ jsxs17("span", { className: "flex shrink-0 items-center gap-1 text-xs text-muted-foreground", children: [
|
|
2372
|
+
/* @__PURE__ */ jsx18(Timer, { className: "h-3 w-3" }),
|
|
2280
2373
|
(variant.durationMs / 1e3).toFixed(1),
|
|
2281
2374
|
"s"
|
|
2282
2375
|
] }),
|
|
2283
|
-
/* @__PURE__ */
|
|
2284
|
-
variant.outcome && /* @__PURE__ */
|
|
2376
|
+
/* @__PURE__ */ jsxs17("div", { className: "ml-auto flex shrink-0 items-center gap-1.5", children: [
|
|
2377
|
+
variant.outcome && /* @__PURE__ */ jsx18(
|
|
2285
2378
|
Badge2,
|
|
2286
2379
|
{
|
|
2287
2380
|
className: `${outcomeConfig[variant.outcome].bg} ${outcomeConfig[variant.outcome].border} ${outcomeConfig[variant.outcome].color}`,
|
|
2288
2381
|
children: outcomeConfig[variant.outcome].label
|
|
2289
2382
|
}
|
|
2290
2383
|
),
|
|
2291
|
-
variant.status === "completed" && variant.outcome === "pending_review" && onAccept && onReject && /* @__PURE__ */
|
|
2292
|
-
/* @__PURE__ */
|
|
2384
|
+
variant.status === "completed" && variant.outcome === "pending_review" && onAccept && onReject && /* @__PURE__ */ jsxs17(Fragment11, { children: [
|
|
2385
|
+
/* @__PURE__ */ jsxs17(
|
|
2293
2386
|
Button3,
|
|
2294
2387
|
{
|
|
2295
2388
|
variant: "outline",
|
|
@@ -2301,12 +2394,12 @@ function VariantList({
|
|
|
2301
2394
|
},
|
|
2302
2395
|
disabled: isActioning === variant.id,
|
|
2303
2396
|
children: [
|
|
2304
|
-
/* @__PURE__ */
|
|
2397
|
+
/* @__PURE__ */ jsx18(Check3, { className: "mr-1 h-3 w-3" }),
|
|
2305
2398
|
"Accept"
|
|
2306
2399
|
]
|
|
2307
2400
|
}
|
|
2308
2401
|
),
|
|
2309
|
-
/* @__PURE__ */
|
|
2402
|
+
/* @__PURE__ */ jsxs17(
|
|
2310
2403
|
Button3,
|
|
2311
2404
|
{
|
|
2312
2405
|
variant: "outline",
|
|
@@ -2318,13 +2411,13 @@ function VariantList({
|
|
|
2318
2411
|
},
|
|
2319
2412
|
disabled: isActioning === variant.id,
|
|
2320
2413
|
children: [
|
|
2321
|
-
/* @__PURE__ */
|
|
2414
|
+
/* @__PURE__ */ jsx18(X, { className: "mr-1 h-3 w-3" }),
|
|
2322
2415
|
"Reject"
|
|
2323
2416
|
]
|
|
2324
2417
|
}
|
|
2325
2418
|
)
|
|
2326
2419
|
] }),
|
|
2327
|
-
variant.detailsUrl && /* @__PURE__ */
|
|
2420
|
+
variant.detailsUrl && /* @__PURE__ */ jsx18(
|
|
2328
2421
|
Button3,
|
|
2329
2422
|
{
|
|
2330
2423
|
variant: "ghost",
|
|
@@ -2334,13 +2427,13 @@ function VariantList({
|
|
|
2334
2427
|
e.stopPropagation();
|
|
2335
2428
|
window.open(variant.detailsUrl, "_blank");
|
|
2336
2429
|
},
|
|
2337
|
-
children: /* @__PURE__ */
|
|
2430
|
+
children: /* @__PURE__ */ jsx18(ExternalLink2, { className: "h-3.5 w-3.5" })
|
|
2338
2431
|
}
|
|
2339
2432
|
)
|
|
2340
2433
|
] })
|
|
2341
2434
|
] }),
|
|
2342
|
-
variant.error && /* @__PURE__ */
|
|
2343
|
-
variant.summary && /* @__PURE__ */
|
|
2435
|
+
variant.error && /* @__PURE__ */ jsx18("p", { className: "mt-1.5 text-xs text-[var(--surface-danger-text)]", children: variant.error }),
|
|
2436
|
+
variant.summary && /* @__PURE__ */ jsx18("p", { className: "mt-1.5 line-clamp-2 text-xs text-muted-foreground", children: variant.summary })
|
|
2344
2437
|
]
|
|
2345
2438
|
},
|
|
2346
2439
|
variant.id
|
|
@@ -2351,7 +2444,7 @@ function VariantList({
|
|
|
2351
2444
|
// src/dashboard/system-logs.tsx
|
|
2352
2445
|
import { Terminal as Terminal3 } from "lucide-react";
|
|
2353
2446
|
import { useEffect as useEffect3, useRef as useRef3, useState as useState5 } from "react";
|
|
2354
|
-
import { jsx as
|
|
2447
|
+
import { jsx as jsx19, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
2355
2448
|
function SystemLogsViewer({ apiUrl, token, className }) {
|
|
2356
2449
|
const [logs, setLogs] = useState5([]);
|
|
2357
2450
|
const [error, setError] = useState5(null);
|
|
@@ -2404,18 +2497,18 @@ function SystemLogsViewer({ apiUrl, token, className }) {
|
|
|
2404
2497
|
const isAtBottom = scrollHeight - scrollTop - clientHeight < 20;
|
|
2405
2498
|
setIsFollowing((prev) => prev === isAtBottom ? prev : isAtBottom);
|
|
2406
2499
|
};
|
|
2407
|
-
return /* @__PURE__ */
|
|
2408
|
-
/* @__PURE__ */
|
|
2409
|
-
/* @__PURE__ */
|
|
2410
|
-
/* @__PURE__ */
|
|
2411
|
-
/* @__PURE__ */
|
|
2500
|
+
return /* @__PURE__ */ jsxs18("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: [
|
|
2501
|
+
/* @__PURE__ */ jsxs18("div", { className: "flex-none flex items-center justify-between border-b border-border bg-muted/50 backdrop-blur-md px-4 py-2", children: [
|
|
2502
|
+
/* @__PURE__ */ jsxs18("div", { className: "flex items-center gap-2", children: [
|
|
2503
|
+
/* @__PURE__ */ jsx19(Terminal3, { className: "h-4 w-4 text-primary animate-pulse" }),
|
|
2504
|
+
/* @__PURE__ */ jsx19("span", { className: "font-bold text-xs uppercase tracking-widest text-muted-foreground", children: "System Traces" })
|
|
2412
2505
|
] }),
|
|
2413
|
-
/* @__PURE__ */
|
|
2414
|
-
error && /* @__PURE__ */
|
|
2415
|
-
/* @__PURE__ */
|
|
2506
|
+
/* @__PURE__ */ jsxs18("div", { className: "flex items-center gap-3", children: [
|
|
2507
|
+
error && /* @__PURE__ */ jsxs18("span", { className: "text-destructive text-xs flex items-center gap-1", children: [
|
|
2508
|
+
/* @__PURE__ */ jsx19("span", { className: "w-2 h-2 rounded-full bg-destructive animate-ping" }),
|
|
2416
2509
|
" Error fetching logs"
|
|
2417
2510
|
] }),
|
|
2418
|
-
/* @__PURE__ */
|
|
2511
|
+
/* @__PURE__ */ jsx19(
|
|
2419
2512
|
"button",
|
|
2420
2513
|
{
|
|
2421
2514
|
onClick: () => {
|
|
@@ -2430,29 +2523,29 @@ function SystemLogsViewer({ apiUrl, token, className }) {
|
|
|
2430
2523
|
)
|
|
2431
2524
|
] })
|
|
2432
2525
|
] }),
|
|
2433
|
-
/* @__PURE__ */
|
|
2526
|
+
/* @__PURE__ */ jsx19(
|
|
2434
2527
|
"div",
|
|
2435
2528
|
{
|
|
2436
2529
|
ref: scrollRef,
|
|
2437
2530
|
onScroll: handleScroll,
|
|
2438
2531
|
className: "flex-1 overflow-y-auto p-4 space-y-1",
|
|
2439
|
-
children: logs.length === 0 && !error ? /* @__PURE__ */
|
|
2440
|
-
/* @__PURE__ */
|
|
2532
|
+
children: logs.length === 0 && !error ? /* @__PURE__ */ jsx19("div", { className: "flex h-full items-center justify-center text-muted-foreground italic", children: "Waiting for orchestrator logs..." }) : logs.map((log, i) => /* @__PURE__ */ jsxs18("div", { className: "break-words", children: [
|
|
2533
|
+
/* @__PURE__ */ jsxs18("span", { className: "text-muted-foreground mr-3 select-none", children: [
|
|
2441
2534
|
"[",
|
|
2442
2535
|
log.timestamp || i.toString().padStart(4, "0"),
|
|
2443
2536
|
"]"
|
|
2444
2537
|
] }),
|
|
2445
|
-
/* @__PURE__ */
|
|
2538
|
+
/* @__PURE__ */ jsxs18("span", { className: "text-primary/70 mr-2", children: [
|
|
2446
2539
|
"[",
|
|
2447
2540
|
log.level,
|
|
2448
2541
|
"]"
|
|
2449
2542
|
] }),
|
|
2450
|
-
/* @__PURE__ */
|
|
2543
|
+
/* @__PURE__ */ jsxs18("span", { className: "text-muted-foreground mr-2", children: [
|
|
2451
2544
|
"[",
|
|
2452
2545
|
log.scope,
|
|
2453
2546
|
"]"
|
|
2454
2547
|
] }),
|
|
2455
|
-
/* @__PURE__ */
|
|
2548
|
+
/* @__PURE__ */ jsx19("span", { className: log.level.toUpperCase() === "ERROR" || log.message.toLowerCase().includes("failed") ? "text-destructive" : log.level.toUpperCase() === "WARN" ? "text-warning" : "text-foreground", children: log.message })
|
|
2456
2549
|
] }, `${log.timestamp}-${log.scope}-${i}`))
|
|
2457
2550
|
}
|
|
2458
2551
|
)
|
|
@@ -2463,50 +2556,50 @@ function SystemLogsViewer({ apiUrl, token, className }) {
|
|
|
2463
2556
|
import { Clock as Clock4, Layers, MessageSquare, DollarSign } from "lucide-react";
|
|
2464
2557
|
import { StatCard } from "@tangle-network/ui/primitives";
|
|
2465
2558
|
import { Skeleton as Skeleton4 } from "@tangle-network/ui/primitives";
|
|
2466
|
-
import { jsx as
|
|
2559
|
+
import { jsx as jsx20, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
2467
2560
|
function UsageSummary({ data, loading = false, className }) {
|
|
2468
2561
|
if (loading || !data) {
|
|
2469
|
-
return /* @__PURE__ */
|
|
2562
|
+
return /* @__PURE__ */ jsx20("div", { className: cn("grid grid-cols-2 gap-4 lg:grid-cols-4", className), children: Array.from({ length: 4 }).map((_, i) => /* @__PURE__ */ jsx20(Skeleton4, { className: "h-28 rounded-xl" }, i)) });
|
|
2470
2563
|
}
|
|
2471
|
-
return /* @__PURE__ */
|
|
2472
|
-
/* @__PURE__ */
|
|
2564
|
+
return /* @__PURE__ */ jsxs19("div", { className: cn("grid grid-cols-2 gap-4 lg:grid-cols-4", className), children: [
|
|
2565
|
+
/* @__PURE__ */ jsx20(
|
|
2473
2566
|
StatCard,
|
|
2474
2567
|
{
|
|
2475
2568
|
variant: "sandbox",
|
|
2476
2569
|
title: "Compute Hours",
|
|
2477
2570
|
value: data.computeHours.toFixed(1),
|
|
2478
2571
|
subtitle: "This billing period",
|
|
2479
|
-
icon: /* @__PURE__ */
|
|
2572
|
+
icon: /* @__PURE__ */ jsx20(Clock4, { className: "h-5 w-5" })
|
|
2480
2573
|
}
|
|
2481
2574
|
),
|
|
2482
|
-
/* @__PURE__ */
|
|
2575
|
+
/* @__PURE__ */ jsx20(
|
|
2483
2576
|
StatCard,
|
|
2484
2577
|
{
|
|
2485
2578
|
variant: "sandbox",
|
|
2486
2579
|
title: "Active Sessions",
|
|
2487
2580
|
value: data.activeSessions,
|
|
2488
2581
|
subtitle: "Currently running",
|
|
2489
|
-
icon: /* @__PURE__ */
|
|
2582
|
+
icon: /* @__PURE__ */ jsx20(Layers, { className: "h-5 w-5" })
|
|
2490
2583
|
}
|
|
2491
2584
|
),
|
|
2492
|
-
/* @__PURE__ */
|
|
2585
|
+
/* @__PURE__ */ jsx20(
|
|
2493
2586
|
StatCard,
|
|
2494
2587
|
{
|
|
2495
2588
|
variant: "sandbox",
|
|
2496
2589
|
title: "Messages Sent",
|
|
2497
2590
|
value: data.messagesSent.toLocaleString(),
|
|
2498
2591
|
subtitle: "Agent interactions",
|
|
2499
|
-
icon: /* @__PURE__ */
|
|
2592
|
+
icon: /* @__PURE__ */ jsx20(MessageSquare, { className: "h-5 w-5" })
|
|
2500
2593
|
}
|
|
2501
2594
|
),
|
|
2502
|
-
/* @__PURE__ */
|
|
2595
|
+
/* @__PURE__ */ jsx20(
|
|
2503
2596
|
StatCard,
|
|
2504
2597
|
{
|
|
2505
2598
|
variant: "sandbox",
|
|
2506
2599
|
title: "Estimated Cost",
|
|
2507
2600
|
value: `$${data.estimatedCost.toFixed(2)}`,
|
|
2508
2601
|
subtitle: "This billing period",
|
|
2509
|
-
icon: /* @__PURE__ */
|
|
2602
|
+
icon: /* @__PURE__ */ jsx20(DollarSign, { className: "h-5 w-5" })
|
|
2510
2603
|
}
|
|
2511
2604
|
)
|
|
2512
2605
|
] });
|
|
@@ -2514,66 +2607,66 @@ function UsageSummary({ data, loading = false, className }) {
|
|
|
2514
2607
|
|
|
2515
2608
|
// src/dashboard/git-panel.tsx
|
|
2516
2609
|
import { GitBranch, GitCommit, FileEdit, FilePlus, File } from "lucide-react";
|
|
2517
|
-
import { jsx as
|
|
2610
|
+
import { jsx as jsx21, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
2518
2611
|
function GitPanel({ status, log, loading = false, onRefresh, className }) {
|
|
2519
2612
|
if (loading) {
|
|
2520
|
-
return /* @__PURE__ */
|
|
2521
|
-
/* @__PURE__ */
|
|
2613
|
+
return /* @__PURE__ */ jsx21("div", { className: cn("rounded-lg border border-border bg-card p-5", className), children: /* @__PURE__ */ jsxs20("div", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: [
|
|
2614
|
+
/* @__PURE__ */ jsx21("div", { className: "h-4 w-4 animate-spin rounded-full border-2 border-primary border-t-transparent" }),
|
|
2522
2615
|
"Loading git info..."
|
|
2523
2616
|
] }) });
|
|
2524
2617
|
}
|
|
2525
2618
|
if (!status) {
|
|
2526
|
-
return /* @__PURE__ */
|
|
2527
|
-
/* @__PURE__ */
|
|
2619
|
+
return /* @__PURE__ */ jsx21("div", { className: cn("rounded-lg border border-border bg-card p-5", className), children: /* @__PURE__ */ jsxs20("div", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: [
|
|
2620
|
+
/* @__PURE__ */ jsx21(GitBranch, { className: "h-4 w-4" }),
|
|
2528
2621
|
"No git repository detected"
|
|
2529
2622
|
] }) });
|
|
2530
2623
|
}
|
|
2531
2624
|
const changedCount = status.staged.length + status.modified.length + status.untracked.length;
|
|
2532
|
-
return /* @__PURE__ */
|
|
2533
|
-
/* @__PURE__ */
|
|
2534
|
-
/* @__PURE__ */
|
|
2535
|
-
/* @__PURE__ */
|
|
2536
|
-
/* @__PURE__ */
|
|
2537
|
-
status.isDirty && /* @__PURE__ */
|
|
2625
|
+
return /* @__PURE__ */ jsxs20("div", { className: cn("rounded-lg border border-border bg-card overflow-hidden", className), children: [
|
|
2626
|
+
/* @__PURE__ */ jsxs20("div", { className: "flex items-center justify-between border-b border-border bg-muted/30 px-4 py-3", children: [
|
|
2627
|
+
/* @__PURE__ */ jsxs20("div", { className: "flex items-center gap-2", children: [
|
|
2628
|
+
/* @__PURE__ */ jsx21(GitBranch, { className: "h-4 w-4 text-primary" }),
|
|
2629
|
+
/* @__PURE__ */ jsx21("span", { className: "text-sm font-bold text-foreground", children: status.branch }),
|
|
2630
|
+
status.isDirty && /* @__PURE__ */ jsxs20("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: [
|
|
2538
2631
|
changedCount,
|
|
2539
2632
|
" change",
|
|
2540
2633
|
changedCount !== 1 ? "s" : ""
|
|
2541
2634
|
] })
|
|
2542
2635
|
] }),
|
|
2543
|
-
onRefresh && /* @__PURE__ */
|
|
2636
|
+
onRefresh && /* @__PURE__ */ jsx21("button", { type: "button", onClick: onRefresh, className: "text-xs text-muted-foreground hover:text-foreground transition-colors", children: "Refresh" })
|
|
2544
2637
|
] }),
|
|
2545
|
-
changedCount > 0 && /* @__PURE__ */
|
|
2546
|
-
status.staged.map((f) => /* @__PURE__ */
|
|
2547
|
-
/* @__PURE__ */
|
|
2548
|
-
/* @__PURE__ */
|
|
2549
|
-
/* @__PURE__ */
|
|
2638
|
+
changedCount > 0 && /* @__PURE__ */ jsx21("div", { className: "border-b border-border px-4 py-3", children: /* @__PURE__ */ jsxs20("div", { className: "space-y-1.5", children: [
|
|
2639
|
+
status.staged.map((f) => /* @__PURE__ */ jsxs20("div", { className: "flex items-center gap-2 text-xs", children: [
|
|
2640
|
+
/* @__PURE__ */ jsx21(FilePlus, { className: "h-3 w-3 text-[var(--surface-success-text)]" }),
|
|
2641
|
+
/* @__PURE__ */ jsx21("span", { className: "font-mono text-foreground truncate", children: f }),
|
|
2642
|
+
/* @__PURE__ */ jsx21("span", { className: "text-[var(--surface-success-text)] text-[10px] font-bold ml-auto", children: "STAGED" })
|
|
2550
2643
|
] }, `s-${f}`)),
|
|
2551
|
-
status.modified.map((f) => /* @__PURE__ */
|
|
2552
|
-
/* @__PURE__ */
|
|
2553
|
-
/* @__PURE__ */
|
|
2644
|
+
status.modified.map((f) => /* @__PURE__ */ jsxs20("div", { className: "flex items-center gap-2 text-xs", children: [
|
|
2645
|
+
/* @__PURE__ */ jsx21(FileEdit, { className: "h-3 w-3 text-[var(--surface-warning-text)]" }),
|
|
2646
|
+
/* @__PURE__ */ jsx21("span", { className: "font-mono text-foreground truncate", children: f })
|
|
2554
2647
|
] }, `m-${f}`)),
|
|
2555
|
-
status.untracked.map((f) => /* @__PURE__ */
|
|
2556
|
-
/* @__PURE__ */
|
|
2557
|
-
/* @__PURE__ */
|
|
2648
|
+
status.untracked.map((f) => /* @__PURE__ */ jsxs20("div", { className: "flex items-center gap-2 text-xs", children: [
|
|
2649
|
+
/* @__PURE__ */ jsx21(File, { className: "h-3 w-3 text-muted-foreground" }),
|
|
2650
|
+
/* @__PURE__ */ jsx21("span", { className: "font-mono text-muted-foreground truncate", children: f })
|
|
2558
2651
|
] }, `u-${f}`))
|
|
2559
2652
|
] }) }),
|
|
2560
|
-
log.length > 0 && /* @__PURE__ */
|
|
2561
|
-
/* @__PURE__ */
|
|
2562
|
-
/* @__PURE__ */
|
|
2563
|
-
/* @__PURE__ */
|
|
2564
|
-
/* @__PURE__ */
|
|
2565
|
-
/* @__PURE__ */
|
|
2566
|
-
/* @__PURE__ */
|
|
2653
|
+
log.length > 0 && /* @__PURE__ */ jsxs20("div", { className: "px-4 py-3", children: [
|
|
2654
|
+
/* @__PURE__ */ jsx21("div", { className: "mb-2 text-[10px] font-bold uppercase tracking-widest text-muted-foreground", children: "Recent Commits" }),
|
|
2655
|
+
/* @__PURE__ */ jsx21("div", { className: "space-y-2", children: log.slice(0, 5).map((commit) => /* @__PURE__ */ jsxs20("div", { className: "flex items-start gap-2 text-xs", children: [
|
|
2656
|
+
/* @__PURE__ */ jsx21(GitCommit, { className: "h-3 w-3 text-muted-foreground mt-0.5 shrink-0" }),
|
|
2657
|
+
/* @__PURE__ */ jsxs20("div", { className: "min-w-0", children: [
|
|
2658
|
+
/* @__PURE__ */ jsx21("span", { className: "font-mono text-primary mr-1.5", children: commit.shortSha }),
|
|
2659
|
+
/* @__PURE__ */ jsx21("span", { className: "text-foreground", children: commit.message })
|
|
2567
2660
|
] })
|
|
2568
2661
|
] }, commit.shortSha)) })
|
|
2569
2662
|
] }),
|
|
2570
|
-
(status.ahead > 0 || status.behind > 0) && /* @__PURE__ */
|
|
2571
|
-
status.ahead > 0 && /* @__PURE__ */
|
|
2663
|
+
(status.ahead > 0 || status.behind > 0) && /* @__PURE__ */ jsxs20("div", { className: "border-t border-border px-4 py-2 flex items-center gap-3 text-xs text-muted-foreground", children: [
|
|
2664
|
+
status.ahead > 0 && /* @__PURE__ */ jsxs20("span", { children: [
|
|
2572
2665
|
"\u2191 ",
|
|
2573
2666
|
status.ahead,
|
|
2574
2667
|
" ahead"
|
|
2575
2668
|
] }),
|
|
2576
|
-
status.behind > 0 && /* @__PURE__ */
|
|
2669
|
+
status.behind > 0 && /* @__PURE__ */ jsxs20("span", { children: [
|
|
2577
2670
|
"\u2193 ",
|
|
2578
2671
|
status.behind,
|
|
2579
2672
|
" behind"
|
|
@@ -2585,7 +2678,7 @@ function GitPanel({ status, log, loading = false, onRefresh, className }) {
|
|
|
2585
2678
|
// src/dashboard/ports-list.tsx
|
|
2586
2679
|
import * as React9 from "react";
|
|
2587
2680
|
import { Copy as Copy3, Check as Check4, Globe, Plus as Plus4, Trash2 as Trash23 } from "lucide-react";
|
|
2588
|
-
import { jsx as
|
|
2681
|
+
import { jsx as jsx22, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
2589
2682
|
function PortsList({ ports, onExposePort, onRemovePort, isExposing = false, className }) {
|
|
2590
2683
|
const [newPort, setNewPort] = React9.useState("");
|
|
2591
2684
|
const [copiedPort, setCopiedPort] = React9.useState(null);
|
|
@@ -2612,48 +2705,48 @@ function PortsList({ ports, onExposePort, onRemovePort, isExposing = false, clas
|
|
|
2612
2705
|
setNewPort("");
|
|
2613
2706
|
}
|
|
2614
2707
|
};
|
|
2615
|
-
return /* @__PURE__ */
|
|
2616
|
-
ports.length > 0 ? /* @__PURE__ */
|
|
2617
|
-
/* @__PURE__ */
|
|
2618
|
-
/* @__PURE__ */
|
|
2619
|
-
/* @__PURE__ */
|
|
2620
|
-
/* @__PURE__ */
|
|
2621
|
-
/* @__PURE__ */
|
|
2708
|
+
return /* @__PURE__ */ jsxs21("div", { className: cn("space-y-4", className), children: [
|
|
2709
|
+
ports.length > 0 ? /* @__PURE__ */ jsx22("div", { className: "rounded-lg border border-border overflow-hidden", children: /* @__PURE__ */ jsxs21("table", { className: "w-full text-sm", children: [
|
|
2710
|
+
/* @__PURE__ */ jsx22("thead", { className: "bg-muted/30 border-b border-border", children: /* @__PURE__ */ jsxs21("tr", { children: [
|
|
2711
|
+
/* @__PURE__ */ jsx22("th", { className: "px-4 py-2.5 text-left text-xs font-medium text-muted-foreground", children: "Port" }),
|
|
2712
|
+
/* @__PURE__ */ jsx22("th", { className: "px-4 py-2.5 text-left text-xs font-medium text-muted-foreground", children: "Public URL" }),
|
|
2713
|
+
/* @__PURE__ */ jsx22("th", { className: "px-4 py-2.5 text-left text-xs font-medium text-muted-foreground", children: "Status" }),
|
|
2714
|
+
/* @__PURE__ */ jsx22("th", { className: "px-4 py-2.5 text-right text-xs font-medium text-muted-foreground w-20" })
|
|
2622
2715
|
] }) }),
|
|
2623
|
-
/* @__PURE__ */
|
|
2624
|
-
/* @__PURE__ */
|
|
2625
|
-
/* @__PURE__ */
|
|
2716
|
+
/* @__PURE__ */ jsx22("tbody", { className: "divide-y divide-border", children: ports.map((p) => /* @__PURE__ */ jsxs21("tr", { children: [
|
|
2717
|
+
/* @__PURE__ */ jsx22("td", { className: "px-4 py-3 font-mono text-xs text-foreground", children: p.port }),
|
|
2718
|
+
/* @__PURE__ */ jsx22("td", { className: "px-4 py-3", children: /* @__PURE__ */ jsxs21(
|
|
2626
2719
|
"button",
|
|
2627
2720
|
{
|
|
2628
2721
|
type: "button",
|
|
2629
2722
|
onClick: () => handleCopy(p.url, p.port),
|
|
2630
2723
|
className: "flex items-center gap-2 font-mono text-xs text-primary hover:underline cursor-pointer group",
|
|
2631
2724
|
children: [
|
|
2632
|
-
/* @__PURE__ */
|
|
2633
|
-
copiedPort === p.port ? /* @__PURE__ */
|
|
2725
|
+
/* @__PURE__ */ jsx22("span", { className: "truncate max-w-[300px]", children: p.url }),
|
|
2726
|
+
copiedPort === p.port ? /* @__PURE__ */ jsx22(Check4, { className: "h-3 w-3 text-[var(--surface-success-text)] shrink-0" }) : /* @__PURE__ */ jsx22(Copy3, { className: "h-3 w-3 opacity-0 group-hover:opacity-100 transition-opacity shrink-0" })
|
|
2634
2727
|
]
|
|
2635
2728
|
}
|
|
2636
2729
|
) }),
|
|
2637
|
-
/* @__PURE__ */
|
|
2730
|
+
/* @__PURE__ */ jsx22("td", { className: "px-4 py-3", children: /* @__PURE__ */ jsx22("span", { className: cn(
|
|
2638
2731
|
"inline-flex items-center gap-1.5 rounded-full px-2 py-0.5 text-[10px] font-bold uppercase tracking-wider",
|
|
2639
2732
|
p.status === "active" ? "bg-[var(--surface-success-bg)] text-[var(--surface-success-text)]" : "bg-[var(--surface-warning-bg)] text-[var(--surface-warning-text)]"
|
|
2640
2733
|
), children: p.status }) }),
|
|
2641
|
-
/* @__PURE__ */
|
|
2734
|
+
/* @__PURE__ */ jsx22("td", { className: "px-4 py-3 text-right", children: onRemovePort && /* @__PURE__ */ jsx22(
|
|
2642
2735
|
"button",
|
|
2643
2736
|
{
|
|
2644
2737
|
type: "button",
|
|
2645
2738
|
onClick: () => onRemovePort(p.port),
|
|
2646
2739
|
className: "p-1 text-muted-foreground hover:text-destructive transition-colors rounded",
|
|
2647
|
-
children: /* @__PURE__ */
|
|
2740
|
+
children: /* @__PURE__ */ jsx22(Trash23, { className: "h-3.5 w-3.5" })
|
|
2648
2741
|
}
|
|
2649
2742
|
) })
|
|
2650
2743
|
] }, p.port)) })
|
|
2651
|
-
] }) }) : /* @__PURE__ */
|
|
2652
|
-
/* @__PURE__ */
|
|
2653
|
-
/* @__PURE__ */
|
|
2744
|
+
] }) }) : /* @__PURE__ */ jsxs21("div", { className: "rounded-lg border border-border bg-muted/20 p-6 text-center", children: [
|
|
2745
|
+
/* @__PURE__ */ jsx22(Globe, { className: "mx-auto h-8 w-8 text-muted-foreground mb-2" }),
|
|
2746
|
+
/* @__PURE__ */ jsx22("p", { className: "text-sm text-muted-foreground", children: "No ports exposed yet" })
|
|
2654
2747
|
] }),
|
|
2655
|
-
/* @__PURE__ */
|
|
2656
|
-
/* @__PURE__ */
|
|
2748
|
+
/* @__PURE__ */ jsxs21("div", { className: "flex items-center gap-3", children: [
|
|
2749
|
+
/* @__PURE__ */ jsx22(
|
|
2657
2750
|
"input",
|
|
2658
2751
|
{
|
|
2659
2752
|
type: "number",
|
|
@@ -2663,10 +2756,10 @@ function PortsList({ ports, onExposePort, onRemovePort, isExposing = false, clas
|
|
|
2663
2756
|
value: newPort,
|
|
2664
2757
|
onChange: (e) => setNewPort(e.target.value),
|
|
2665
2758
|
onKeyDown: (e) => e.key === "Enter" && handleExpose(),
|
|
2666
|
-
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-
|
|
2759
|
+
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-visible:ring-1 focus-visible:ring-ring"
|
|
2667
2760
|
}
|
|
2668
2761
|
),
|
|
2669
|
-
/* @__PURE__ */
|
|
2762
|
+
/* @__PURE__ */ jsxs21(
|
|
2670
2763
|
"button",
|
|
2671
2764
|
{
|
|
2672
2765
|
type: "button",
|
|
@@ -2674,7 +2767,7 @@ function PortsList({ ports, onExposePort, onRemovePort, isExposing = false, clas
|
|
|
2674
2767
|
disabled: !newPort || isExposing,
|
|
2675
2768
|
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",
|
|
2676
2769
|
children: [
|
|
2677
|
-
/* @__PURE__ */
|
|
2770
|
+
/* @__PURE__ */ jsx22(Plus4, { className: "h-4 w-4" }),
|
|
2678
2771
|
"Expose"
|
|
2679
2772
|
]
|
|
2680
2773
|
}
|
|
@@ -2686,7 +2779,7 @@ function PortsList({ ports, onExposePort, onRemovePort, isExposing = false, clas
|
|
|
2686
2779
|
// src/dashboard/process-list.tsx
|
|
2687
2780
|
import * as React10 from "react";
|
|
2688
2781
|
import { Activity as Activity3, Plus as Plus5, Skull, Terminal as Terminal4 } from "lucide-react";
|
|
2689
|
-
import { jsx as
|
|
2782
|
+
import { jsx as jsx23, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
2690
2783
|
function formatUptime(startedAt) {
|
|
2691
2784
|
if (!startedAt) return "-";
|
|
2692
2785
|
const ms = Date.now() - new Date(startedAt).getTime();
|
|
@@ -2704,43 +2797,43 @@ function ProcessList({ processes, onSpawn, onKill, loading = false, className })
|
|
|
2704
2797
|
setNewCommand("");
|
|
2705
2798
|
}
|
|
2706
2799
|
};
|
|
2707
|
-
return /* @__PURE__ */
|
|
2708
|
-
loading ? /* @__PURE__ */
|
|
2709
|
-
/* @__PURE__ */
|
|
2710
|
-
/* @__PURE__ */
|
|
2711
|
-
] }) : processes.length > 0 ? /* @__PURE__ */
|
|
2712
|
-
/* @__PURE__ */
|
|
2713
|
-
/* @__PURE__ */
|
|
2714
|
-
/* @__PURE__ */
|
|
2715
|
-
/* @__PURE__ */
|
|
2716
|
-
/* @__PURE__ */
|
|
2717
|
-
/* @__PURE__ */
|
|
2800
|
+
return /* @__PURE__ */ jsxs22("div", { className: cn("space-y-4", className), children: [
|
|
2801
|
+
loading ? /* @__PURE__ */ jsxs22("div", { className: "rounded-lg border border-border bg-muted/20 p-6 text-center", children: [
|
|
2802
|
+
/* @__PURE__ */ jsx23(Activity3, { className: "mx-auto h-6 w-6 text-muted-foreground animate-spin mb-2" }),
|
|
2803
|
+
/* @__PURE__ */ jsx23("p", { className: "text-sm text-muted-foreground", children: "Loading processes..." })
|
|
2804
|
+
] }) : processes.length > 0 ? /* @__PURE__ */ jsx23("div", { className: "rounded-lg border border-border overflow-hidden", children: /* @__PURE__ */ jsxs22("table", { className: "w-full text-sm", children: [
|
|
2805
|
+
/* @__PURE__ */ jsx23("thead", { className: "bg-muted/30 border-b border-border", children: /* @__PURE__ */ jsxs22("tr", { children: [
|
|
2806
|
+
/* @__PURE__ */ jsx23("th", { className: "px-4 py-2.5 text-left text-xs font-medium text-muted-foreground", children: "PID" }),
|
|
2807
|
+
/* @__PURE__ */ jsx23("th", { className: "px-4 py-2.5 text-left text-xs font-medium text-muted-foreground", children: "Command" }),
|
|
2808
|
+
/* @__PURE__ */ jsx23("th", { className: "px-4 py-2.5 text-left text-xs font-medium text-muted-foreground", children: "Status" }),
|
|
2809
|
+
/* @__PURE__ */ jsx23("th", { className: "px-4 py-2.5 text-left text-xs font-medium text-muted-foreground", children: "Uptime" }),
|
|
2810
|
+
/* @__PURE__ */ jsx23("th", { className: "px-4 py-2.5 text-right text-xs font-medium text-muted-foreground w-20" })
|
|
2718
2811
|
] }) }),
|
|
2719
|
-
/* @__PURE__ */
|
|
2720
|
-
/* @__PURE__ */
|
|
2721
|
-
/* @__PURE__ */
|
|
2722
|
-
/* @__PURE__ */
|
|
2812
|
+
/* @__PURE__ */ jsx23("tbody", { className: "divide-y divide-border", children: processes.map((p) => /* @__PURE__ */ jsxs22("tr", { children: [
|
|
2813
|
+
/* @__PURE__ */ jsx23("td", { className: "px-4 py-3 font-mono text-xs text-foreground", children: p.pid }),
|
|
2814
|
+
/* @__PURE__ */ jsx23("td", { className: "px-4 py-3 font-mono text-xs text-foreground truncate max-w-[250px]", children: p.command }),
|
|
2815
|
+
/* @__PURE__ */ jsx23("td", { className: "px-4 py-3", children: /* @__PURE__ */ jsx23("span", { className: cn(
|
|
2723
2816
|
"inline-flex items-center gap-1.5 rounded-full px-2 py-0.5 text-[10px] font-bold uppercase tracking-wider",
|
|
2724
2817
|
p.running ? "bg-[var(--surface-success-bg)] text-[var(--surface-success-text)]" : "bg-muted text-muted-foreground"
|
|
2725
2818
|
), children: p.running ? "running" : `exited (${p.exitCode ?? "?"})` }) }),
|
|
2726
|
-
/* @__PURE__ */
|
|
2727
|
-
/* @__PURE__ */
|
|
2819
|
+
/* @__PURE__ */ jsx23("td", { className: "px-4 py-3 font-mono text-xs text-muted-foreground", children: formatUptime(p.startedAt) }),
|
|
2820
|
+
/* @__PURE__ */ jsx23("td", { className: "px-4 py-3 text-right", children: p.running && /* @__PURE__ */ jsx23(
|
|
2728
2821
|
"button",
|
|
2729
2822
|
{
|
|
2730
2823
|
type: "button",
|
|
2731
2824
|
onClick: () => onKill(p.pid),
|
|
2732
2825
|
className: "p-1 text-muted-foreground hover:text-destructive transition-colors rounded",
|
|
2733
2826
|
title: "Kill process",
|
|
2734
|
-
children: /* @__PURE__ */
|
|
2827
|
+
children: /* @__PURE__ */ jsx23(Skull, { className: "h-3.5 w-3.5" })
|
|
2735
2828
|
}
|
|
2736
2829
|
) })
|
|
2737
2830
|
] }, `${p.pid}-${p.startedAt ?? p.command}`)) })
|
|
2738
|
-
] }) }) : /* @__PURE__ */
|
|
2739
|
-
/* @__PURE__ */
|
|
2740
|
-
/* @__PURE__ */
|
|
2831
|
+
] }) }) : /* @__PURE__ */ jsxs22("div", { className: "rounded-lg border border-border bg-muted/20 p-6 text-center", children: [
|
|
2832
|
+
/* @__PURE__ */ jsx23(Terminal4, { className: "mx-auto h-8 w-8 text-muted-foreground mb-2" }),
|
|
2833
|
+
/* @__PURE__ */ jsx23("p", { className: "text-sm text-muted-foreground", children: "No processes running" })
|
|
2741
2834
|
] }),
|
|
2742
|
-
/* @__PURE__ */
|
|
2743
|
-
/* @__PURE__ */
|
|
2835
|
+
/* @__PURE__ */ jsxs22("div", { className: "flex items-center gap-3", children: [
|
|
2836
|
+
/* @__PURE__ */ jsx23(
|
|
2744
2837
|
"input",
|
|
2745
2838
|
{
|
|
2746
2839
|
type: "text",
|
|
@@ -2748,10 +2841,10 @@ function ProcessList({ processes, onSpawn, onKill, loading = false, className })
|
|
|
2748
2841
|
value: newCommand,
|
|
2749
2842
|
onChange: (e) => setNewCommand(e.target.value),
|
|
2750
2843
|
onKeyDown: (e) => e.key === "Enter" && handleSpawn(),
|
|
2751
|
-
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-
|
|
2844
|
+
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-visible:ring-1 focus-visible:ring-ring"
|
|
2752
2845
|
}
|
|
2753
2846
|
),
|
|
2754
|
-
/* @__PURE__ */
|
|
2847
|
+
/* @__PURE__ */ jsxs22(
|
|
2755
2848
|
"button",
|
|
2756
2849
|
{
|
|
2757
2850
|
type: "button",
|
|
@@ -2759,7 +2852,7 @@ function ProcessList({ processes, onSpawn, onKill, loading = false, className })
|
|
|
2759
2852
|
disabled: !newCommand.trim(),
|
|
2760
2853
|
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",
|
|
2761
2854
|
children: [
|
|
2762
|
-
/* @__PURE__ */
|
|
2855
|
+
/* @__PURE__ */ jsx23(Plus5, { className: "h-4 w-4" }),
|
|
2763
2856
|
"Spawn"
|
|
2764
2857
|
]
|
|
2765
2858
|
}
|
|
@@ -2771,7 +2864,7 @@ function ProcessList({ processes, onSpawn, onKill, loading = false, className })
|
|
|
2771
2864
|
// src/dashboard/network-config.tsx
|
|
2772
2865
|
import * as React11 from "react";
|
|
2773
2866
|
import { Network as Network2, Plus as Plus6, Trash2 as Trash24, ShieldAlert } from "lucide-react";
|
|
2774
|
-
import { jsx as
|
|
2867
|
+
import { jsx as jsx24, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
2775
2868
|
function NetworkConfig({ config, onUpdate, loading = false, className }) {
|
|
2776
2869
|
const [newCidr, setNewCidr] = React11.useState("");
|
|
2777
2870
|
const isValidCidr = (value) => {
|
|
@@ -2794,21 +2887,21 @@ function NetworkConfig({ config, onUpdate, loading = false, className }) {
|
|
|
2794
2887
|
}
|
|
2795
2888
|
};
|
|
2796
2889
|
if (loading || !config) {
|
|
2797
|
-
return /* @__PURE__ */
|
|
2798
|
-
/* @__PURE__ */
|
|
2799
|
-
/* @__PURE__ */
|
|
2890
|
+
return /* @__PURE__ */ jsxs23("div", { className: cn("rounded-lg border border-border bg-muted/20 p-6 text-center", className), children: [
|
|
2891
|
+
/* @__PURE__ */ jsx24(Network2, { className: "mx-auto h-6 w-6 text-muted-foreground animate-pulse mb-2" }),
|
|
2892
|
+
/* @__PURE__ */ jsx24("p", { className: "text-sm text-muted-foreground", children: "Loading network configuration..." })
|
|
2800
2893
|
] });
|
|
2801
2894
|
}
|
|
2802
|
-
return /* @__PURE__ */
|
|
2803
|
-
/* @__PURE__ */
|
|
2804
|
-
/* @__PURE__ */
|
|
2805
|
-
/* @__PURE__ */
|
|
2806
|
-
/* @__PURE__ */
|
|
2807
|
-
/* @__PURE__ */
|
|
2808
|
-
/* @__PURE__ */
|
|
2895
|
+
return /* @__PURE__ */ jsxs23("div", { className: cn("space-y-4", className), children: [
|
|
2896
|
+
/* @__PURE__ */ jsxs23("div", { className: "flex items-center justify-between rounded-lg border border-border bg-card px-4 py-3", children: [
|
|
2897
|
+
/* @__PURE__ */ jsxs23("div", { className: "flex items-center gap-3", children: [
|
|
2898
|
+
/* @__PURE__ */ jsx24(ShieldAlert, { className: "h-4 w-4 text-muted-foreground" }),
|
|
2899
|
+
/* @__PURE__ */ jsxs23("div", { children: [
|
|
2900
|
+
/* @__PURE__ */ jsx24("p", { className: "text-sm font-medium text-foreground", children: "Block Outbound Traffic" }),
|
|
2901
|
+
/* @__PURE__ */ jsx24("p", { className: "text-xs text-muted-foreground", children: "Prevent the sandbox from making external network requests" })
|
|
2809
2902
|
] })
|
|
2810
2903
|
] }),
|
|
2811
|
-
/* @__PURE__ */
|
|
2904
|
+
/* @__PURE__ */ jsx24(
|
|
2812
2905
|
"button",
|
|
2813
2906
|
{
|
|
2814
2907
|
type: "button",
|
|
@@ -2820,7 +2913,7 @@ function NetworkConfig({ config, onUpdate, loading = false, className }) {
|
|
|
2820
2913
|
"relative inline-flex h-6 w-11 items-center rounded-full transition-colors",
|
|
2821
2914
|
config.blockOutbound ? "bg-destructive" : "bg-muted"
|
|
2822
2915
|
),
|
|
2823
|
-
children: /* @__PURE__ */
|
|
2916
|
+
children: /* @__PURE__ */ jsx24(
|
|
2824
2917
|
"span",
|
|
2825
2918
|
{
|
|
2826
2919
|
className: cn(
|
|
@@ -2832,22 +2925,22 @@ function NetworkConfig({ config, onUpdate, loading = false, className }) {
|
|
|
2832
2925
|
}
|
|
2833
2926
|
)
|
|
2834
2927
|
] }),
|
|
2835
|
-
/* @__PURE__ */
|
|
2836
|
-
/* @__PURE__ */
|
|
2837
|
-
config.allowList.length > 0 ? /* @__PURE__ */
|
|
2838
|
-
/* @__PURE__ */
|
|
2839
|
-
/* @__PURE__ */
|
|
2928
|
+
/* @__PURE__ */ jsxs23("div", { children: [
|
|
2929
|
+
/* @__PURE__ */ jsx24("h4", { className: "text-xs font-medium text-muted-foreground mb-2 uppercase tracking-wider", children: "Allowlist (CIDR)" }),
|
|
2930
|
+
config.allowList.length > 0 ? /* @__PURE__ */ jsx24("div", { className: "space-y-1.5 mb-3", children: config.allowList.map((cidr) => /* @__PURE__ */ jsxs23("div", { className: "flex items-center justify-between rounded border border-border bg-muted/20 px-3 py-2", children: [
|
|
2931
|
+
/* @__PURE__ */ jsx24("span", { className: "font-mono text-xs text-foreground", children: cidr }),
|
|
2932
|
+
/* @__PURE__ */ jsx24(
|
|
2840
2933
|
"button",
|
|
2841
2934
|
{
|
|
2842
2935
|
type: "button",
|
|
2843
2936
|
onClick: () => handleRemoveCidr(cidr),
|
|
2844
2937
|
className: "p-1 text-muted-foreground hover:text-destructive transition-colors rounded",
|
|
2845
|
-
children: /* @__PURE__ */
|
|
2938
|
+
children: /* @__PURE__ */ jsx24(Trash24, { className: "h-3 w-3" })
|
|
2846
2939
|
}
|
|
2847
2940
|
)
|
|
2848
|
-
] }, cidr)) }) : /* @__PURE__ */
|
|
2849
|
-
/* @__PURE__ */
|
|
2850
|
-
/* @__PURE__ */
|
|
2941
|
+
] }, cidr)) }) : /* @__PURE__ */ jsx24("p", { className: "text-xs text-muted-foreground mb-3", children: "No CIDR rules configured. All traffic is allowed." }),
|
|
2942
|
+
/* @__PURE__ */ jsxs23("div", { className: "flex items-center gap-3", children: [
|
|
2943
|
+
/* @__PURE__ */ jsx24(
|
|
2851
2944
|
"input",
|
|
2852
2945
|
{
|
|
2853
2946
|
type: "text",
|
|
@@ -2855,10 +2948,10 @@ function NetworkConfig({ config, onUpdate, loading = false, className }) {
|
|
|
2855
2948
|
value: newCidr,
|
|
2856
2949
|
onChange: (e) => setNewCidr(e.target.value),
|
|
2857
2950
|
onKeyDown: (e) => e.key === "Enter" && handleAddCidr(),
|
|
2858
|
-
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-
|
|
2951
|
+
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-visible:ring-1 focus-visible:ring-ring"
|
|
2859
2952
|
}
|
|
2860
2953
|
),
|
|
2861
|
-
/* @__PURE__ */
|
|
2954
|
+
/* @__PURE__ */ jsxs23(
|
|
2862
2955
|
"button",
|
|
2863
2956
|
{
|
|
2864
2957
|
type: "button",
|
|
@@ -2866,7 +2959,7 @@ function NetworkConfig({ config, onUpdate, loading = false, className }) {
|
|
|
2866
2959
|
disabled: !newCidr.trim(),
|
|
2867
2960
|
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",
|
|
2868
2961
|
children: [
|
|
2869
|
-
/* @__PURE__ */
|
|
2962
|
+
/* @__PURE__ */ jsx24(Plus6, { className: "h-4 w-4" }),
|
|
2870
2963
|
"Add"
|
|
2871
2964
|
]
|
|
2872
2965
|
}
|
|
@@ -2879,7 +2972,7 @@ function NetworkConfig({ config, onUpdate, loading = false, className }) {
|
|
|
2879
2972
|
// src/dashboard/backend-config.tsx
|
|
2880
2973
|
import * as React12 from "react";
|
|
2881
2974
|
import { Bot, Plus as Plus7, RefreshCw as RefreshCw2, Trash2 as Trash25, Server, Wrench } from "lucide-react";
|
|
2882
|
-
import { Fragment as
|
|
2975
|
+
import { Fragment as Fragment12, jsx as jsx25, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
2883
2976
|
function BackendConfig({
|
|
2884
2977
|
status,
|
|
2885
2978
|
mcpServers,
|
|
@@ -2909,122 +3002,122 @@ function BackendConfig({
|
|
|
2909
3002
|
}
|
|
2910
3003
|
};
|
|
2911
3004
|
if (loading || !status) {
|
|
2912
|
-
return /* @__PURE__ */
|
|
2913
|
-
/* @__PURE__ */
|
|
2914
|
-
/* @__PURE__ */
|
|
3005
|
+
return /* @__PURE__ */ jsxs24("div", { className: cn("rounded-lg border border-border bg-muted/20 p-6 text-center", className), children: [
|
|
3006
|
+
/* @__PURE__ */ jsx25(Bot, { className: "mx-auto h-6 w-6 text-muted-foreground animate-pulse mb-2" }),
|
|
3007
|
+
/* @__PURE__ */ jsx25("p", { className: "text-sm text-muted-foreground", children: "Loading backend status..." })
|
|
2915
3008
|
] });
|
|
2916
3009
|
}
|
|
2917
|
-
return /* @__PURE__ */
|
|
2918
|
-
/* @__PURE__ */
|
|
2919
|
-
/* @__PURE__ */
|
|
2920
|
-
/* @__PURE__ */
|
|
2921
|
-
/* @__PURE__ */
|
|
3010
|
+
return /* @__PURE__ */ jsxs24("div", { className: cn("space-y-4", className), children: [
|
|
3011
|
+
/* @__PURE__ */ jsxs24("div", { className: "rounded-lg border border-border bg-card overflow-hidden", children: [
|
|
3012
|
+
/* @__PURE__ */ jsxs24("div", { className: "px-4 py-3 border-b border-border bg-muted/30 flex items-center justify-between", children: [
|
|
3013
|
+
/* @__PURE__ */ jsx25("h4", { className: "text-xs font-medium text-muted-foreground uppercase tracking-wider", children: "Agent Status" }),
|
|
3014
|
+
/* @__PURE__ */ jsxs24(
|
|
2922
3015
|
"button",
|
|
2923
3016
|
{
|
|
2924
3017
|
type: "button",
|
|
2925
3018
|
onClick: onRestart,
|
|
2926
3019
|
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",
|
|
2927
3020
|
children: [
|
|
2928
|
-
/* @__PURE__ */
|
|
3021
|
+
/* @__PURE__ */ jsx25(RefreshCw2, { className: "h-3 w-3" }),
|
|
2929
3022
|
"Restart"
|
|
2930
3023
|
]
|
|
2931
3024
|
}
|
|
2932
3025
|
)
|
|
2933
3026
|
] }),
|
|
2934
|
-
/* @__PURE__ */
|
|
2935
|
-
/* @__PURE__ */
|
|
2936
|
-
/* @__PURE__ */
|
|
3027
|
+
/* @__PURE__ */ jsx25("div", { className: "p-4", children: /* @__PURE__ */ jsxs24("dl", { className: "grid grid-cols-[100px_1fr] gap-y-3 text-sm", children: [
|
|
3028
|
+
/* @__PURE__ */ jsx25("dt", { className: "text-muted-foreground", children: "Status" }),
|
|
3029
|
+
/* @__PURE__ */ jsx25("dd", { children: /* @__PURE__ */ jsx25("span", { className: cn(
|
|
2937
3030
|
"inline-flex items-center gap-1.5 rounded-full px-2 py-0.5 text-[10px] font-bold uppercase tracking-wider",
|
|
2938
3031
|
status.running ? "bg-[var(--surface-success-bg)] text-[var(--surface-success-text)]" : "bg-destructive/10 text-destructive"
|
|
2939
3032
|
), children: status.running ? "Running" : "Stopped" }) }),
|
|
2940
|
-
/* @__PURE__ */
|
|
2941
|
-
/* @__PURE__ */
|
|
2942
|
-
status.provider && /* @__PURE__ */
|
|
2943
|
-
/* @__PURE__ */
|
|
2944
|
-
/* @__PURE__ */
|
|
3033
|
+
/* @__PURE__ */ jsx25("dt", { className: "text-muted-foreground", children: "Model" }),
|
|
3034
|
+
/* @__PURE__ */ jsx25("dd", { className: "font-mono text-xs", children: status.model ?? "Default" }),
|
|
3035
|
+
status.provider && /* @__PURE__ */ jsxs24(Fragment12, { children: [
|
|
3036
|
+
/* @__PURE__ */ jsx25("dt", { className: "text-muted-foreground", children: "Provider" }),
|
|
3037
|
+
/* @__PURE__ */ jsx25("dd", { className: "font-mono text-xs", children: status.provider })
|
|
2945
3038
|
] })
|
|
2946
3039
|
] }) })
|
|
2947
3040
|
] }),
|
|
2948
|
-
/* @__PURE__ */
|
|
2949
|
-
/* @__PURE__ */
|
|
2950
|
-
/* @__PURE__ */
|
|
2951
|
-
/* @__PURE__ */
|
|
3041
|
+
/* @__PURE__ */ jsxs24("div", { className: "rounded-lg border border-border bg-card overflow-hidden", children: [
|
|
3042
|
+
/* @__PURE__ */ jsxs24("div", { className: "px-4 py-3 border-b border-border bg-muted/30 flex items-center justify-between", children: [
|
|
3043
|
+
/* @__PURE__ */ jsxs24("h4", { className: "text-xs font-medium text-muted-foreground uppercase tracking-wider flex items-center gap-2", children: [
|
|
3044
|
+
/* @__PURE__ */ jsx25(Wrench, { className: "h-3.5 w-3.5" }),
|
|
2952
3045
|
"MCP Servers"
|
|
2953
3046
|
] }),
|
|
2954
|
-
/* @__PURE__ */
|
|
3047
|
+
/* @__PURE__ */ jsxs24(
|
|
2955
3048
|
"button",
|
|
2956
3049
|
{
|
|
2957
3050
|
type: "button",
|
|
2958
3051
|
onClick: () => setShowAddMcp(!showAddMcp),
|
|
2959
3052
|
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",
|
|
2960
3053
|
children: [
|
|
2961
|
-
/* @__PURE__ */
|
|
3054
|
+
/* @__PURE__ */ jsx25(Plus7, { className: "h-3 w-3" }),
|
|
2962
3055
|
"Add"
|
|
2963
3056
|
]
|
|
2964
3057
|
}
|
|
2965
3058
|
)
|
|
2966
3059
|
] }),
|
|
2967
|
-
mcpServers.length > 0 ? /* @__PURE__ */
|
|
2968
|
-
/* @__PURE__ */
|
|
2969
|
-
/* @__PURE__ */
|
|
2970
|
-
/* @__PURE__ */
|
|
2971
|
-
/* @__PURE__ */
|
|
2972
|
-
/* @__PURE__ */
|
|
3060
|
+
mcpServers.length > 0 ? /* @__PURE__ */ jsx25("div", { className: "divide-y divide-border", children: mcpServers.map((s) => /* @__PURE__ */ jsxs24("div", { className: "flex items-center justify-between px-4 py-3", children: [
|
|
3061
|
+
/* @__PURE__ */ jsxs24("div", { className: "flex items-center gap-3 min-w-0", children: [
|
|
3062
|
+
/* @__PURE__ */ jsx25(Server, { className: "h-3.5 w-3.5 text-muted-foreground shrink-0" }),
|
|
3063
|
+
/* @__PURE__ */ jsxs24("div", { className: "min-w-0", children: [
|
|
3064
|
+
/* @__PURE__ */ jsx25("p", { className: "text-sm font-medium text-foreground truncate", children: s.name }),
|
|
3065
|
+
/* @__PURE__ */ jsxs24("p", { className: "text-xs font-mono text-muted-foreground truncate", children: [
|
|
2973
3066
|
s.command,
|
|
2974
3067
|
" ",
|
|
2975
3068
|
s.args?.join(" ") ?? ""
|
|
2976
3069
|
] })
|
|
2977
3070
|
] })
|
|
2978
3071
|
] }),
|
|
2979
|
-
/* @__PURE__ */
|
|
2980
|
-
s.status && /* @__PURE__ */
|
|
3072
|
+
/* @__PURE__ */ jsxs24("div", { className: "flex items-center gap-2 shrink-0", children: [
|
|
3073
|
+
s.status && /* @__PURE__ */ jsx25("span", { className: cn(
|
|
2981
3074
|
"inline-flex items-center rounded-full px-1.5 py-0.5 text-[9px] font-bold uppercase",
|
|
2982
3075
|
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"
|
|
2983
3076
|
), children: s.status }),
|
|
2984
|
-
/* @__PURE__ */
|
|
3077
|
+
/* @__PURE__ */ jsx25(
|
|
2985
3078
|
"button",
|
|
2986
3079
|
{
|
|
2987
3080
|
type: "button",
|
|
2988
3081
|
onClick: () => onRemoveMcp(s.name),
|
|
2989
3082
|
className: "p-1 text-muted-foreground hover:text-destructive transition-colors rounded",
|
|
2990
|
-
children: /* @__PURE__ */
|
|
3083
|
+
children: /* @__PURE__ */ jsx25(Trash25, { className: "h-3.5 w-3.5" })
|
|
2991
3084
|
}
|
|
2992
3085
|
)
|
|
2993
3086
|
] })
|
|
2994
|
-
] }, s.name)) }) : /* @__PURE__ */
|
|
2995
|
-
showAddMcp && /* @__PURE__ */
|
|
2996
|
-
/* @__PURE__ */
|
|
3087
|
+
] }, s.name)) }) : /* @__PURE__ */ jsx25("div", { className: "p-4 text-center", children: /* @__PURE__ */ jsx25("p", { className: "text-xs text-muted-foreground", children: "No MCP servers configured" }) }),
|
|
3088
|
+
showAddMcp && /* @__PURE__ */ jsxs24("div", { className: "p-4 border-t border-border bg-muted/10 space-y-2", children: [
|
|
3089
|
+
/* @__PURE__ */ jsx25(
|
|
2997
3090
|
"input",
|
|
2998
3091
|
{
|
|
2999
3092
|
type: "text",
|
|
3000
3093
|
placeholder: "Server name",
|
|
3001
3094
|
value: mcpName,
|
|
3002
3095
|
onChange: (e) => setMcpName(e.target.value),
|
|
3003
|
-
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-
|
|
3096
|
+
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-visible:ring-1 focus-visible:ring-ring"
|
|
3004
3097
|
}
|
|
3005
3098
|
),
|
|
3006
|
-
/* @__PURE__ */
|
|
3099
|
+
/* @__PURE__ */ jsx25(
|
|
3007
3100
|
"input",
|
|
3008
3101
|
{
|
|
3009
3102
|
type: "text",
|
|
3010
3103
|
placeholder: "Command (e.g. npx @server/mcp)",
|
|
3011
3104
|
value: mcpCommand,
|
|
3012
3105
|
onChange: (e) => setMcpCommand(e.target.value),
|
|
3013
|
-
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-
|
|
3106
|
+
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-visible:ring-1 focus-visible:ring-ring"
|
|
3014
3107
|
}
|
|
3015
3108
|
),
|
|
3016
|
-
/* @__PURE__ */
|
|
3109
|
+
/* @__PURE__ */ jsx25(
|
|
3017
3110
|
"input",
|
|
3018
3111
|
{
|
|
3019
3112
|
type: "text",
|
|
3020
3113
|
placeholder: "Arguments (space-separated, optional)",
|
|
3021
3114
|
value: mcpArgs,
|
|
3022
3115
|
onChange: (e) => setMcpArgs(e.target.value),
|
|
3023
|
-
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-
|
|
3116
|
+
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-visible:ring-1 focus-visible:ring-ring"
|
|
3024
3117
|
}
|
|
3025
3118
|
),
|
|
3026
|
-
/* @__PURE__ */
|
|
3027
|
-
/* @__PURE__ */
|
|
3119
|
+
/* @__PURE__ */ jsxs24("div", { className: "flex justify-end gap-2 pt-1", children: [
|
|
3120
|
+
/* @__PURE__ */ jsx25(
|
|
3028
3121
|
"button",
|
|
3029
3122
|
{
|
|
3030
3123
|
type: "button",
|
|
@@ -3033,7 +3126,7 @@ function BackendConfig({
|
|
|
3033
3126
|
children: "Cancel"
|
|
3034
3127
|
}
|
|
3035
3128
|
),
|
|
3036
|
-
/* @__PURE__ */
|
|
3129
|
+
/* @__PURE__ */ jsx25(
|
|
3037
3130
|
"button",
|
|
3038
3131
|
{
|
|
3039
3132
|
type: "button",
|
|
@@ -3052,7 +3145,7 @@ function BackendConfig({
|
|
|
3052
3145
|
// src/dashboard/snapshot-list.tsx
|
|
3053
3146
|
import * as React13 from "react";
|
|
3054
3147
|
import { Camera, Clock as Clock5, HardDrive, Plus as Plus8, RotateCcw } from "lucide-react";
|
|
3055
|
-
import { jsx as
|
|
3148
|
+
import { jsx as jsx26, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
3056
3149
|
function formatBytes(bytes) {
|
|
3057
3150
|
if (bytes == null || bytes < 0) return "-";
|
|
3058
3151
|
if (bytes === 0) return "0 B";
|
|
@@ -3075,25 +3168,25 @@ function SnapshotList({ snapshots, onCreate, onRestore, onSaveAsTemplate, loadin
|
|
|
3075
3168
|
setTags("");
|
|
3076
3169
|
setShowCreate(false);
|
|
3077
3170
|
};
|
|
3078
|
-
return /* @__PURE__ */
|
|
3079
|
-
/* @__PURE__ */
|
|
3080
|
-
/* @__PURE__ */
|
|
3081
|
-
/* @__PURE__ */
|
|
3171
|
+
return /* @__PURE__ */ jsxs25("div", { className: cn("space-y-4", className), children: [
|
|
3172
|
+
/* @__PURE__ */ jsxs25("div", { className: "flex items-center justify-between", children: [
|
|
3173
|
+
/* @__PURE__ */ jsx26("h3", { className: "text-sm font-bold text-foreground", children: "Snapshots" }),
|
|
3174
|
+
/* @__PURE__ */ jsxs25(
|
|
3082
3175
|
"button",
|
|
3083
3176
|
{
|
|
3084
3177
|
type: "button",
|
|
3085
3178
|
onClick: () => setShowCreate(!showCreate),
|
|
3086
3179
|
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",
|
|
3087
3180
|
children: [
|
|
3088
|
-
/* @__PURE__ */
|
|
3181
|
+
/* @__PURE__ */ jsx26(Plus8, { className: "h-3.5 w-3.5" }),
|
|
3089
3182
|
"Create Snapshot"
|
|
3090
3183
|
]
|
|
3091
3184
|
}
|
|
3092
3185
|
)
|
|
3093
3186
|
] }),
|
|
3094
|
-
showCreate && /* @__PURE__ */
|
|
3095
|
-
/* @__PURE__ */
|
|
3096
|
-
/* @__PURE__ */
|
|
3187
|
+
showCreate && /* @__PURE__ */ jsxs25("div", { className: "rounded-lg border border-primary/20 bg-primary/5 p-4 space-y-3", children: [
|
|
3188
|
+
/* @__PURE__ */ jsx26("p", { className: "text-sm text-foreground font-medium", children: "Create a new snapshot of the current sandbox state." }),
|
|
3189
|
+
/* @__PURE__ */ jsx26(
|
|
3097
3190
|
"input",
|
|
3098
3191
|
{
|
|
3099
3192
|
type: "text",
|
|
@@ -3101,11 +3194,11 @@ function SnapshotList({ snapshots, onCreate, onRestore, onSaveAsTemplate, loadin
|
|
|
3101
3194
|
value: tags,
|
|
3102
3195
|
onChange: (e) => setTags(e.target.value),
|
|
3103
3196
|
onKeyDown: (e) => e.key === "Enter" && handleCreate(),
|
|
3104
|
-
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-
|
|
3197
|
+
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-visible:ring-1 focus-visible:ring-ring"
|
|
3105
3198
|
}
|
|
3106
3199
|
),
|
|
3107
|
-
/* @__PURE__ */
|
|
3108
|
-
/* @__PURE__ */
|
|
3200
|
+
/* @__PURE__ */ jsxs25("div", { className: "flex justify-end gap-2", children: [
|
|
3201
|
+
/* @__PURE__ */ jsx26(
|
|
3109
3202
|
"button",
|
|
3110
3203
|
{
|
|
3111
3204
|
type: "button",
|
|
@@ -3114,44 +3207,44 @@ function SnapshotList({ snapshots, onCreate, onRestore, onSaveAsTemplate, loadin
|
|
|
3114
3207
|
children: "Cancel"
|
|
3115
3208
|
}
|
|
3116
3209
|
),
|
|
3117
|
-
/* @__PURE__ */
|
|
3210
|
+
/* @__PURE__ */ jsxs25(
|
|
3118
3211
|
"button",
|
|
3119
3212
|
{
|
|
3120
3213
|
type: "button",
|
|
3121
3214
|
onClick: handleCreate,
|
|
3122
3215
|
className: "rounded-md bg-primary px-3 py-1.5 text-xs font-medium text-primary-foreground hover:bg-primary/90 transition-colors",
|
|
3123
3216
|
children: [
|
|
3124
|
-
/* @__PURE__ */
|
|
3217
|
+
/* @__PURE__ */ jsx26(Camera, { className: "h-3 w-3 mr-1.5 inline" }),
|
|
3125
3218
|
"Create"
|
|
3126
3219
|
]
|
|
3127
3220
|
}
|
|
3128
3221
|
)
|
|
3129
3222
|
] })
|
|
3130
3223
|
] }),
|
|
3131
|
-
loading ? /* @__PURE__ */
|
|
3132
|
-
/* @__PURE__ */
|
|
3133
|
-
/* @__PURE__ */
|
|
3134
|
-
] }) : snapshots.length > 0 ? /* @__PURE__ */
|
|
3135
|
-
/* @__PURE__ */
|
|
3136
|
-
/* @__PURE__ */
|
|
3137
|
-
/* @__PURE__ */
|
|
3138
|
-
/* @__PURE__ */
|
|
3139
|
-
/* @__PURE__ */
|
|
3140
|
-
/* @__PURE__ */
|
|
3224
|
+
loading ? /* @__PURE__ */ jsxs25("div", { className: "rounded-lg border border-border bg-muted/20 p-6 text-center", children: [
|
|
3225
|
+
/* @__PURE__ */ jsx26(Camera, { className: "mx-auto h-6 w-6 text-muted-foreground animate-pulse mb-2" }),
|
|
3226
|
+
/* @__PURE__ */ jsx26("p", { className: "text-sm text-muted-foreground", children: "Loading snapshots..." })
|
|
3227
|
+
] }) : snapshots.length > 0 ? /* @__PURE__ */ jsx26("div", { className: "rounded-lg border border-border overflow-hidden", children: /* @__PURE__ */ jsxs25("table", { className: "w-full text-sm", children: [
|
|
3228
|
+
/* @__PURE__ */ jsx26("thead", { className: "bg-muted/30 border-b border-border", children: /* @__PURE__ */ jsxs25("tr", { children: [
|
|
3229
|
+
/* @__PURE__ */ jsx26("th", { className: "px-4 py-2.5 text-left text-xs font-medium text-muted-foreground", children: "ID" }),
|
|
3230
|
+
/* @__PURE__ */ jsx26("th", { className: "px-4 py-2.5 text-left text-xs font-medium text-muted-foreground", children: "Created" }),
|
|
3231
|
+
/* @__PURE__ */ jsx26("th", { className: "px-4 py-2.5 text-left text-xs font-medium text-muted-foreground", children: "Size" }),
|
|
3232
|
+
/* @__PURE__ */ jsx26("th", { className: "px-4 py-2.5 text-left text-xs font-medium text-muted-foreground", children: "Tags" }),
|
|
3233
|
+
/* @__PURE__ */ jsx26("th", { className: "px-4 py-2.5 text-right text-xs font-medium text-muted-foreground w-24" })
|
|
3141
3234
|
] }) }),
|
|
3142
|
-
/* @__PURE__ */
|
|
3143
|
-
/* @__PURE__ */
|
|
3144
|
-
/* @__PURE__ */
|
|
3145
|
-
/* @__PURE__ */
|
|
3235
|
+
/* @__PURE__ */ jsx26("tbody", { className: "divide-y divide-border", children: snapshots.map((s) => /* @__PURE__ */ jsxs25("tr", { children: [
|
|
3236
|
+
/* @__PURE__ */ jsx26("td", { className: "px-4 py-3 font-mono text-xs text-foreground", children: s.id.slice(0, 12) }),
|
|
3237
|
+
/* @__PURE__ */ jsx26("td", { className: "px-4 py-3 text-xs text-muted-foreground", children: /* @__PURE__ */ jsxs25("span", { className: "inline-flex items-center gap-1.5", children: [
|
|
3238
|
+
/* @__PURE__ */ jsx26(Clock5, { className: "h-3 w-3" }),
|
|
3146
3239
|
formatDate(s.createdAt)
|
|
3147
3240
|
] }) }),
|
|
3148
|
-
/* @__PURE__ */
|
|
3149
|
-
/* @__PURE__ */
|
|
3241
|
+
/* @__PURE__ */ jsx26("td", { className: "px-4 py-3 text-xs text-muted-foreground", children: /* @__PURE__ */ jsxs25("span", { className: "inline-flex items-center gap-1.5", children: [
|
|
3242
|
+
/* @__PURE__ */ jsx26(HardDrive, { className: "h-3 w-3" }),
|
|
3150
3243
|
formatBytes(s.sizeBytes)
|
|
3151
3244
|
] }) }),
|
|
3152
|
-
/* @__PURE__ */
|
|
3153
|
-
/* @__PURE__ */
|
|
3154
|
-
/* @__PURE__ */
|
|
3245
|
+
/* @__PURE__ */ jsx26("td", { className: "px-4 py-3", children: s.tags?.length ? /* @__PURE__ */ jsx26("div", { className: "flex items-center gap-1 flex-wrap", children: s.tags.map((tag) => /* @__PURE__ */ jsx26("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__ */ jsx26("span", { className: "text-xs text-muted-foreground", children: "-" }) }),
|
|
3246
|
+
/* @__PURE__ */ jsx26("td", { className: "px-4 py-3 text-right", children: /* @__PURE__ */ jsxs25("div", { className: "flex items-center justify-end gap-2", children: [
|
|
3247
|
+
/* @__PURE__ */ jsxs25(
|
|
3155
3248
|
"button",
|
|
3156
3249
|
{
|
|
3157
3250
|
type: "button",
|
|
@@ -3159,12 +3252,12 @@ function SnapshotList({ snapshots, onCreate, onRestore, onSaveAsTemplate, loadin
|
|
|
3159
3252
|
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",
|
|
3160
3253
|
title: "Restore to new sandbox",
|
|
3161
3254
|
children: [
|
|
3162
|
-
/* @__PURE__ */
|
|
3255
|
+
/* @__PURE__ */ jsx26(RotateCcw, { className: "h-3 w-3" }),
|
|
3163
3256
|
"Restore"
|
|
3164
3257
|
]
|
|
3165
3258
|
}
|
|
3166
3259
|
),
|
|
3167
|
-
onSaveAsTemplate && /* @__PURE__ */
|
|
3260
|
+
onSaveAsTemplate && /* @__PURE__ */ jsx26(
|
|
3168
3261
|
"button",
|
|
3169
3262
|
{
|
|
3170
3263
|
type: "button",
|
|
@@ -3176,16 +3269,16 @@ function SnapshotList({ snapshots, onCreate, onRestore, onSaveAsTemplate, loadin
|
|
|
3176
3269
|
)
|
|
3177
3270
|
] }) })
|
|
3178
3271
|
] }, s.id)) })
|
|
3179
|
-
] }) }) : /* @__PURE__ */
|
|
3180
|
-
/* @__PURE__ */
|
|
3181
|
-
/* @__PURE__ */
|
|
3182
|
-
/* @__PURE__ */
|
|
3272
|
+
] }) }) : /* @__PURE__ */ jsxs25("div", { className: "rounded-lg border border-border bg-muted/20 p-6 text-center", children: [
|
|
3273
|
+
/* @__PURE__ */ jsx26(Camera, { className: "mx-auto h-8 w-8 text-muted-foreground mb-2" }),
|
|
3274
|
+
/* @__PURE__ */ jsx26("p", { className: "text-sm text-muted-foreground", children: "No snapshots yet" }),
|
|
3275
|
+
/* @__PURE__ */ jsx26("p", { className: "text-xs text-muted-foreground mt-1", children: "Create a snapshot to save the current state of your sandbox." })
|
|
3183
3276
|
] })
|
|
3184
3277
|
] });
|
|
3185
3278
|
}
|
|
3186
3279
|
|
|
3187
3280
|
// src/dashboard/promo-banner.tsx
|
|
3188
|
-
import { Fragment as
|
|
3281
|
+
import { Fragment as Fragment13, jsx as jsx27, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
3189
3282
|
function PromoBanner({
|
|
3190
3283
|
title,
|
|
3191
3284
|
description,
|
|
@@ -3200,21 +3293,21 @@ function PromoBanner({
|
|
|
3200
3293
|
"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",
|
|
3201
3294
|
disabled ? "opacity-50 cursor-not-allowed" : "hover:bg-[var(--btn-primary-hover)]"
|
|
3202
3295
|
);
|
|
3203
|
-
const buttonContent = /* @__PURE__ */
|
|
3296
|
+
const buttonContent = /* @__PURE__ */ jsxs26(Fragment13, { children: [
|
|
3204
3297
|
buttonLabel,
|
|
3205
|
-
/* @__PURE__ */
|
|
3206
|
-
/* @__PURE__ */
|
|
3207
|
-
/* @__PURE__ */
|
|
3298
|
+
/* @__PURE__ */ jsxs26("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: [
|
|
3299
|
+
/* @__PURE__ */ jsx27("path", { d: "M5 12h14" }),
|
|
3300
|
+
/* @__PURE__ */ jsx27("path", { d: "m12 5 7 7-7 7" })
|
|
3208
3301
|
] })
|
|
3209
3302
|
] });
|
|
3210
|
-
return /* @__PURE__ */
|
|
3211
|
-
/* @__PURE__ */
|
|
3212
|
-
/* @__PURE__ */
|
|
3213
|
-
/* @__PURE__ */
|
|
3214
|
-
href && !disabled ? /* @__PURE__ */
|
|
3303
|
+
return /* @__PURE__ */ jsxs26("div", { className: cn("relative overflow-hidden rounded-xl bg-[var(--brand-strong)] p-8 md:flex md:items-center md:justify-between", className), children: [
|
|
3304
|
+
/* @__PURE__ */ jsxs26("div", { className: "relative z-10", children: [
|
|
3305
|
+
/* @__PURE__ */ jsx27("h3", { className: "text-xl font-bold text-[var(--brand-strong-text)]", children: title }),
|
|
3306
|
+
/* @__PURE__ */ jsx27("p", { className: "mt-2 max-w-md text-sm text-[var(--brand-strong-text-muted)]", children: description }),
|
|
3307
|
+
href && !disabled ? /* @__PURE__ */ jsx27("a", { href, target: "_blank", rel: "noopener noreferrer", onClick, className: buttonClasses, children: buttonContent }) : /* @__PURE__ */ jsx27("button", { type: "button", onClick, disabled, className: buttonClasses, children: buttonContent })
|
|
3215
3308
|
] }),
|
|
3216
|
-
icon && /* @__PURE__ */
|
|
3217
|
-
/* @__PURE__ */
|
|
3309
|
+
icon && /* @__PURE__ */ jsx27("div", { className: "relative z-10 mt-6 flex items-center md:mt-0", children: /* @__PURE__ */ jsx27("div", { className: "flex h-16 w-16 items-center justify-center rounded-2xl border border-white/10 bg-white/10", children: icon }) }),
|
|
3310
|
+
/* @__PURE__ */ jsx27("div", { className: "pointer-events-none absolute inset-y-0 right-0 w-1/3 bg-gradient-to-l from-white/5 to-transparent" })
|
|
3218
3311
|
] });
|
|
3219
3312
|
}
|
|
3220
3313
|
|
|
@@ -3223,8 +3316,12 @@ export {
|
|
|
3223
3316
|
SIDEBAR_PANEL_WIDTH,
|
|
3224
3317
|
SIDEBAR_TOTAL_WIDTH,
|
|
3225
3318
|
SIDEBAR_MOBILE_WIDTH,
|
|
3319
|
+
SIDEBAR_RAIL_LABELED_WIDTH,
|
|
3226
3320
|
SidebarProvider,
|
|
3227
3321
|
useSidebar,
|
|
3322
|
+
RailTooltip,
|
|
3323
|
+
RailThemeToggle,
|
|
3324
|
+
RailCollapseToggle,
|
|
3228
3325
|
Sidebar,
|
|
3229
3326
|
SidebarRail,
|
|
3230
3327
|
SidebarRailHeader,
|