@tangle-network/sandbox-ui 0.121.1 → 0.122.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.
@@ -1,14 +1,14 @@
1
- import { Wt as Logo, o as Button$1 } from "./primitives-BQGtwZX3.js";
1
+ import { Wt as Logo, o as Button$1 } from "./primitives-C4qn9fZ8.js";
2
2
  import { t as cn$1 } from "./utils-DzWbktWG.js";
3
3
  import { n as MOTION_SURFACE, r as MOTION_TRAVEL, t as MOTION_CONTROL } from "./motion-DkyBRJb9.js";
4
4
  import { i as moonshot_default } from "./model-brand-hMyDTUqB.js";
5
- import "./info-panel-C9cqDzOL.js";
5
+ import "./page-layout-Cf90DTWr.js";
6
6
  import { Avatar, AvatarFallback, AvatarImage, Badge, Button, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, Skeleton, StatCard, useTheme } from "@tangle-network/ui/primitives";
7
7
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
8
8
  import * as React$1 from "react";
9
9
  import { useEffect, useRef, useState } from "react";
10
10
  import { createPortal } from "react-dom";
11
- import { Activity, BarChart2, Bell, Bot, Box, Camera, Check, CheckCircle2, ChevronDown, ChevronLeft, ChevronRight, Clock, Code2, Copy, Cpu, DollarSign, Download, ExternalLink, File, FileEdit, FilePlus, FileText, GitBranch, GitCommit, Globe, HardDrive, Key, Layers, Loader2, MemoryStick, MessageSquare, Monitor, MoreHorizontal, MoreVertical, Network, PanelLeft, Play, Plug, Plus, Power, PowerOff, RefreshCw, RotateCcw, Server, Settings, ShieldAlert, Skull, Terminal, Timer, Trash2, User, Users, Wrench, X, XCircle } from "lucide-react";
11
+ import { Activity, BarChart2, Bell, Bot, Box, Camera, Check, CheckCircle2, ChevronDown, ChevronLeft, ChevronRight, Clock, Code2, Copy, Cpu, DollarSign, Download, ExternalLink, File, FileEdit, FilePlus, FileText, GitBranch, GitCommit, Globe, HardDrive, Key, Layers, Loader2, MemoryStick, MessageSquare, Monitor, MoreHorizontal, MoreVertical, Network, PanelLeft, Play, Plug, Plus, Power, PowerOff, RotateCcw, Server, Settings, ShieldAlert, Skull, Terminal, Timer, Trash2, User, Users, Wrench, X, XCircle } from "lucide-react";
12
12
  import { focusField, focusFieldWithin, focusRing, focusRingInset, timeAgo } from "@tangle-network/ui/utils";
13
13
  import * as Select$1 from "@radix-ui/react-select";
14
14
  //#region src/dashboard/sidebar-context.tsx
@@ -1464,6 +1464,10 @@ const STATUS_META = {
1464
1464
  label: "Failed",
1465
1465
  color: "var(--status-error)"
1466
1466
  },
1467
+ expired: {
1468
+ label: "Expired",
1469
+ color: "var(--status-deleted)"
1470
+ },
1467
1471
  archived: {
1468
1472
  label: "Archived",
1469
1473
  color: "var(--status-deleted)"
@@ -1489,16 +1493,13 @@ function Spec({ icon, value, unit }) {
1489
1493
  ]
1490
1494
  });
1491
1495
  }
1492
- function UnknownMetric({ label }) {
1493
- return /* @__PURE__ */ jsxs("div", {
1494
- className: "flex items-center justify-between text-xs font-mono uppercase tracking-wide text-muted-foreground",
1495
- children: [/* @__PURE__ */ jsx("span", { children: label }), /* @__PURE__ */ jsx("span", { children: "Unknown" })]
1496
- });
1496
+ function validMetric(value, max) {
1497
+ return value != null && max != null && Number.isFinite(value) && Number.isFinite(max) && max > 0 && value >= 0 && value <= max;
1497
1498
  }
1498
1499
  function SandboxCard({ sandbox, onOpenIDE, onOpenTerminal, onWake, onRestore, onDelete, onStop, onResume, onFork, onKeepAlive, onUsage, onHealth, className }) {
1499
1500
  const isRunning = sandbox.status === "running";
1500
1501
  const isTransitioning = sandbox.status === "provisioning" || sandbox.status === "creating";
1501
- const isStopped = !isRunning && !isTransitioning;
1502
+ const isStopped = !isRunning && !isTransitioning && sandbox.status !== "expired";
1502
1503
  const isHibernating = sandbox.status === "hibernating";
1503
1504
  const resolveResumeHandler = (status) => {
1504
1505
  if (onResume) return onResume;
@@ -1513,6 +1514,9 @@ function SandboxCard({ sandbox, onOpenIDE, onOpenTerminal, onWake, onRestore, on
1513
1514
  const ramTotal = sandbox.ramTotal;
1514
1515
  const diskUsed = sandbox.diskUsed;
1515
1516
  const diskTotal = sandbox.diskTotal;
1517
+ const hasCpu = validMetric(cpuPercent, 100);
1518
+ const hasRam = validMetric(ramUsed, ramTotal);
1519
+ const hasDisk = validMetric(diskUsed, diskTotal);
1516
1520
  const specs = [
1517
1521
  sandbox.vcpu != null && {
1518
1522
  key: "vcpu",
@@ -1647,26 +1651,23 @@ function SandboxCard({ sandbox, onOpenIDE, onOpenTerminal, onWake, onRestore, on
1647
1651
  children: ["up ", sandbox.uptime]
1648
1652
  })]
1649
1653
  }),
1650
- isRunning ? /* @__PURE__ */ jsxs("div", {
1654
+ isRunning && (hasCpu || hasRam || hasDisk) ? /* @__PURE__ */ jsxs("div", {
1651
1655
  className: "space-y-2 rounded-md border border-[var(--md3-outline-variant)] bg-surface-container-high p-3",
1652
1656
  children: [
1653
- cpuPercent != null ? /* @__PURE__ */ jsx(ResourceMeter, {
1657
+ hasCpu && cpuPercent != null && /* @__PURE__ */ jsx(ResourceMeter, {
1654
1658
  label: "CPU",
1655
1659
  value: cpuPercent,
1656
1660
  max: 100,
1657
1661
  icon: /* @__PURE__ */ jsx(Cpu, { className: "h-3 w-3" })
1658
- }) : /* @__PURE__ */ jsx(UnknownMetric, { label: "CPU" }),
1659
- ramUsed != null && ramTotal != null && ramTotal > 0 ? /* @__PURE__ */ jsx(ResourceMeter, {
1662
+ }),
1663
+ hasRam && ramUsed != null && ramTotal != null && /* @__PURE__ */ jsx(ResourceMeter, {
1660
1664
  label: "RAM",
1661
1665
  value: ramUsed,
1662
1666
  max: ramTotal,
1663
1667
  valueLabel: String(ramUsed) + " / " + String(ramTotal) + " GB",
1664
1668
  icon: /* @__PURE__ */ jsx(MemoryStick, { className: "h-3 w-3" })
1665
- }) : ramUsed != null ? /* @__PURE__ */ jsxs("p", {
1666
- className: "flex items-center justify-between text-xs font-mono uppercase tracking-wide text-muted-foreground",
1667
- children: [/* @__PURE__ */ jsx("span", { children: "RAM" }), /* @__PURE__ */ jsxs("span", { children: [String(ramUsed), " GB used; capacity unknown"] })]
1668
- }) : /* @__PURE__ */ jsx(UnknownMetric, { label: "RAM" }),
1669
- diskUsed != null && diskTotal != null && diskTotal > 0 && /* @__PURE__ */ jsx(ResourceMeter, {
1669
+ }),
1670
+ hasDisk && diskUsed != null && diskTotal != null && /* @__PURE__ */ jsx(ResourceMeter, {
1670
1671
  label: "DISK",
1671
1672
  value: diskUsed,
1672
1673
  max: diskTotal,
@@ -1714,7 +1715,7 @@ function SandboxCard({ sandbox, onOpenIDE, onOpenTerminal, onWake, onRestore, on
1714
1715
  })
1715
1716
  ]
1716
1717
  }),
1717
- /* @__PURE__ */ jsx("div", {
1718
+ sandbox.status !== "expired" && /* @__PURE__ */ jsx("div", {
1718
1719
  className: "border-t border-[var(--md3-outline-variant)] pt-3",
1719
1720
  children: isRunning ? /* @__PURE__ */ jsxs("button", {
1720
1721
  type: "button",
@@ -1786,6 +1787,11 @@ const statusColors = {
1786
1787
  text: "text-[var(--surface-danger-text)]",
1787
1788
  bar: "bg-[var(--code-error)]"
1788
1789
  },
1790
+ expired: {
1791
+ dot: "bg-border",
1792
+ text: "text-muted-foreground",
1793
+ bar: "bg-border"
1794
+ },
1789
1795
  archived: {
1790
1796
  dot: "bg-border",
1791
1797
  text: "text-muted-foreground",
@@ -1793,27 +1799,33 @@ const statusColors = {
1793
1799
  }
1794
1800
  };
1795
1801
  function isResumable(status) {
1796
- return status !== "running" && status !== "provisioning" && status !== "creating";
1802
+ return status !== "running" && status !== "provisioning" && status !== "creating" && status !== "expired";
1803
+ }
1804
+ function validPercent(value) {
1805
+ return value != null && Number.isFinite(value) && value >= 0 && value <= 100;
1797
1806
  }
1798
- function MiniMeter({ label, percent, className }) {
1799
- const hasValue = percent != null && Number.isFinite(percent);
1807
+ function ramPercent(sandbox) {
1808
+ if (sandbox.ramUsed == null || sandbox.ramTotal == null || !Number.isFinite(sandbox.ramUsed) || !Number.isFinite(sandbox.ramTotal) || sandbox.ramTotal <= 0) return void 0;
1809
+ const value = sandbox.ramUsed / sandbox.ramTotal * 100;
1810
+ return validPercent(value) ? Math.round(value) : void 0;
1811
+ }
1812
+ function MiniMeter({ label, percent }) {
1813
+ if (!validPercent(percent)) return null;
1800
1814
  return /* @__PURE__ */ jsxs("div", {
1801
- className: cn$1("space-y-1", className),
1815
+ className: "min-w-0 flex-1 space-y-1.5",
1816
+ "aria-label": `${label} ${percent}%`,
1802
1817
  children: [/* @__PURE__ */ jsxs("div", {
1803
- className: "flex justify-between text-[10px] font-mono text-muted-foreground",
1804
- children: [/* @__PURE__ */ jsx("span", {
1805
- className: "font-bold",
1806
- children: label
1807
- }), /* @__PURE__ */ jsx("span", {
1808
- className: hasValue ? "text-[var(--accent-text)]" : "text-muted-foreground",
1809
- children: hasValue ? String(percent) + "%" : "Unknown"
1818
+ className: "flex justify-between gap-2 text-xs text-muted-foreground",
1819
+ children: [/* @__PURE__ */ jsx("span", { children: label }), /* @__PURE__ */ jsxs("span", {
1820
+ className: "tabular-nums text-foreground",
1821
+ children: [percent, "%"]
1810
1822
  })]
1811
1823
  }), /* @__PURE__ */ jsx("div", {
1812
- className: "h-1.5 w-full overflow-hidden rounded-full bg-muted",
1824
+ className: "h-1 w-full overflow-hidden rounded-full bg-surface-container-high",
1813
1825
  "aria-hidden": "true",
1814
- children: hasValue && /* @__PURE__ */ jsx("div", {
1826
+ children: /* @__PURE__ */ jsx("div", {
1815
1827
  className: "h-full rounded-full bg-primary",
1816
- style: { width: String(percent) + "%" }
1828
+ style: { width: `${percent}%` }
1817
1829
  })
1818
1830
  })]
1819
1831
  });
@@ -1827,41 +1839,25 @@ function StatusIndicator({ status }) {
1827
1839
  "aria-hidden": "true",
1828
1840
  ...sc.dot.includes("animate-") ? { "data-motion": "essential" } : {}
1829
1841
  }), /* @__PURE__ */ jsx("span", {
1830
- className: cn$1("text-xs font-bold uppercase tracking-wide", sc.text),
1842
+ className: cn$1("text-xs font-medium", sc.text),
1831
1843
  children: status.charAt(0).toUpperCase() + status.slice(1)
1832
1844
  })]
1833
1845
  });
1834
1846
  }
1835
- function SandboxResources({ sandbox, className }) {
1836
- if (sandbox.status === "running") {
1837
- const ramPercent = sandbox.ramUsed != null && sandbox.ramTotal != null && sandbox.ramTotal > 0 ? Math.round(sandbox.ramUsed / sandbox.ramTotal * 100) : void 0;
1838
- return /* @__PURE__ */ jsxs("div", {
1839
- className: cn$1("min-w-0 space-y-3", className),
1840
- children: [/* @__PURE__ */ jsx(MiniMeter, {
1841
- label: "CPU",
1842
- percent: sandbox.cpuPercent
1843
- }), /* @__PURE__ */ jsx(MiniMeter, {
1844
- label: "RAM",
1845
- percent: ramPercent
1846
- })]
1847
- });
1848
- }
1849
- if (sandbox.status === "provisioning" || sandbox.status === "creating") return /* @__PURE__ */ jsxs("div", {
1850
- className: cn$1("flex min-w-0 items-center gap-2 text-[var(--accent-text)] italic text-[10px] font-bold", className),
1851
- children: [/* @__PURE__ */ jsx(RefreshCw, {
1852
- className: "h-3.5 w-3.5 shrink-0 animate-spin",
1853
- "data-motion": "essential"
1854
- }), /* @__PURE__ */ jsx("span", {
1855
- className: "min-w-0 truncate",
1856
- title: sandbox.provisioningMessage ?? "Allocating nodes...",
1857
- children: sandbox.provisioningMessage ?? "Allocating nodes..."
1847
+ function SandboxResources({ sandbox }) {
1848
+ if (sandbox.status !== "running") return null;
1849
+ const ram = ramPercent(sandbox);
1850
+ if (!validPercent(sandbox.cpuPercent) && ram == null) return null;
1851
+ return /* @__PURE__ */ jsxs("div", {
1852
+ className: "flex min-w-0 items-center gap-4",
1853
+ children: [/* @__PURE__ */ jsx(MiniMeter, {
1854
+ label: "CPU",
1855
+ percent: sandbox.cpuPercent
1856
+ }), /* @__PURE__ */ jsx(MiniMeter, {
1857
+ label: "RAM",
1858
+ percent: ram
1858
1859
  })]
1859
1860
  });
1860
- if (sandbox.status === "hibernating") return /* @__PURE__ */ jsx("p", {
1861
- className: cn$1("text-xs text-muted-foreground", className),
1862
- children: "Not running"
1863
- });
1864
- return null;
1865
1861
  }
1866
1862
  function getPageItems(page, totalPages) {
1867
1863
  if (totalPages <= 7) return Array.from({ length: totalPages }, (_, index) => index + 1);
@@ -1889,6 +1885,7 @@ function SandboxTable({ sandboxes, page = 1, pageSize = 10, total, onPageChange,
1889
1885
  const rangeStart = totalCount === 0 || sandboxes.length === 0 ? 0 : (currentPage - 1) * safePageSize + 1;
1890
1886
  const rangeEnd = rangeStart === 0 ? 0 : Math.min(rangeStart + sandboxes.length - 1, totalCount);
1891
1887
  const hasTeamSandboxes = sandboxes.some((sb) => sb.team !== void 0);
1888
+ const hasResources = sandboxes.some((sb) => sb.status === "running" && (validPercent(sb.cpuPercent) || ramPercent(sb) != null));
1892
1889
  const resolveResumeHandler = (status) => {
1893
1890
  if (onResume) return onResume;
1894
1891
  if (status === "hibernating") return onWake;
@@ -1902,7 +1899,7 @@ function SandboxTable({ sandboxes, page = 1, pageSize = 10, total, onPageChange,
1902
1899
  return /* @__PURE__ */ jsxs("div", {
1903
1900
  className: cn$1("w-full", className),
1904
1901
  children: [/* @__PURE__ */ jsx("div", {
1905
- className: "w-full bg-surface-container rounded-2xl overflow-hidden border border-[var(--md3-outline-variant)]",
1902
+ className: "w-full bg-surface-container rounded-xl overflow-hidden border border-[var(--md3-outline-variant)]",
1906
1903
  children: /* @__PURE__ */ jsx("div", {
1907
1904
  className: cn$1("max-h-[min(60vh,35rem)] overflow-x-hidden overflow-y-auto", focusRingInset),
1908
1905
  role: "region",
@@ -1917,32 +1914,27 @@ function SandboxTable({ sandboxes, page = 1, pageSize = 10, total, onPageChange,
1917
1914
  children: [
1918
1915
  /* @__PURE__ */ jsx("th", {
1919
1916
  scope: "col",
1920
- className: "hidden w-36 px-3 py-4 text-xs font-semibold uppercase tracking-wider text-muted-foreground xl:table-cell",
1917
+ className: "hidden w-36 px-4 py-3 text-xs font-medium text-muted-foreground md:table-cell",
1921
1918
  children: "Status"
1922
1919
  }),
1923
1920
  /* @__PURE__ */ jsx("th", {
1924
1921
  scope: "col",
1925
- className: "px-3 py-4 text-xs font-semibold uppercase tracking-wider text-muted-foreground xl:px-6",
1922
+ className: "px-4 py-3 text-xs font-medium text-muted-foreground",
1926
1923
  children: "Sandbox"
1927
1924
  }),
1928
1925
  hasTeamSandboxes && /* @__PURE__ */ jsx("th", {
1929
1926
  scope: "col",
1930
- className: "hidden w-32 px-3 py-4 text-xs font-semibold uppercase tracking-wider text-muted-foreground xl:table-cell",
1927
+ className: "hidden w-40 px-4 py-3 text-xs font-medium text-muted-foreground xl:table-cell",
1931
1928
  children: "Scope"
1932
1929
  }),
1933
- /* @__PURE__ */ jsx("th", {
1934
- scope: "col",
1935
- className: "hidden w-28 px-3 py-4 text-xs font-semibold uppercase tracking-wider text-muted-foreground xl:table-cell",
1936
- children: "Environment"
1937
- }),
1938
- /* @__PURE__ */ jsx("th", {
1930
+ hasResources && /* @__PURE__ */ jsx("th", {
1939
1931
  scope: "col",
1940
- className: "hidden w-48 px-3 py-4 text-xs font-semibold uppercase tracking-wider text-muted-foreground xl:table-cell",
1932
+ className: "hidden w-52 px-4 py-3 text-xs font-medium text-muted-foreground lg:table-cell",
1941
1933
  children: "Resources"
1942
1934
  }),
1943
1935
  /* @__PURE__ */ jsx("th", {
1944
1936
  scope: "col",
1945
- className: "w-28 px-2 py-4 text-right text-xs font-semibold uppercase tracking-wider text-muted-foreground xl:w-72 xl:px-4",
1937
+ className: "w-44 px-3 py-3 text-right text-xs font-medium text-muted-foreground sm:w-48 sm:px-4",
1946
1938
  children: "Actions"
1947
1939
  })
1948
1940
  ]
@@ -1952,86 +1944,50 @@ function SandboxTable({ sandboxes, page = 1, pageSize = 10, total, onPageChange,
1952
1944
  children: sandboxes.map((sb) => {
1953
1945
  const isActive = sb.status === "running";
1954
1946
  const isHibernating = sb.status === "hibernating";
1955
- const isProvisioning = sb.status === "provisioning" || sb.status === "creating";
1956
1947
  const resumeHandler = isResumable(sb.status) ? resolveResumeHandler(sb.status) : void 0;
1957
1948
  const onRowClick = resolveRowClick(sb);
1958
1949
  const resumeLabel = isHibernating ? "Wake Up" : "Resume";
1959
1950
  const stopRowClick = (e) => e.stopPropagation();
1960
1951
  return /* @__PURE__ */ jsxs("tr", {
1961
- className: cn$1("group relative transition-colors", onRowClick ? "cursor-pointer hover:bg-surface-container-high" : "hover:bg-surface-container-high"),
1952
+ className: cn$1("group relative h-[72px] transition-colors", onRowClick ? "cursor-pointer hover:bg-surface-container-high" : "hover:bg-surface-container-high"),
1962
1953
  onClick: onRowClick,
1963
1954
  children: [
1964
1955
  /* @__PURE__ */ jsx("td", {
1965
- className: "hidden px-3 py-4 align-top xl:table-cell xl:w-36 xl:px-4 xl:py-5",
1956
+ className: "hidden px-4 py-3 align-middle md:table-cell",
1966
1957
  children: /* @__PURE__ */ jsx(StatusIndicator, { status: sb.status })
1967
1958
  }),
1968
1959
  /* @__PURE__ */ jsx("td", {
1969
- className: "min-w-0 px-3 py-4 align-top xl:px-6 xl:py-5",
1960
+ className: "min-w-0 px-4 py-3 align-middle",
1970
1961
  children: /* @__PURE__ */ jsxs("div", {
1971
- className: "flex min-w-0 flex-col gap-2",
1972
- children: [/* @__PURE__ */ jsxs("div", {
1973
- className: "flex min-w-0 items-start gap-2",
1974
- children: [/* @__PURE__ */ jsx("div", {
1975
- className: "shrink-0 xl:hidden",
1976
- children: /* @__PURE__ */ jsx(StatusIndicator, { status: sb.status })
1977
- }), /* @__PURE__ */ jsxs("div", {
1978
- className: "min-w-0 flex-1",
1979
- children: [/* @__PURE__ */ jsx("span", {
1980
- className: "block min-w-0 truncate text-sm font-bold text-foreground transition-colors group-hover:text-[var(--accent-text)]",
1981
- title: sb.name,
1982
- "aria-label": sb.name,
1983
- children: sb.name
1984
- }), sb.nodeId && /* @__PURE__ */ jsx("span", {
1985
- className: "block min-w-0 truncate text-[10px] font-mono text-muted-foreground",
1986
- title: sb.nodeId,
1987
- children: sb.nodeId
1988
- })]
1989
- })]
1962
+ className: "min-w-0 space-y-1",
1963
+ children: [/* @__PURE__ */ jsx("span", {
1964
+ className: "block truncate text-sm font-semibold text-foreground",
1965
+ title: sb.name,
1966
+ "aria-label": sb.name,
1967
+ children: sb.name
1990
1968
  }), /* @__PURE__ */ jsxs("div", {
1991
- className: "grid min-w-0 gap-1 text-[11px] xl:hidden",
1969
+ className: "flex min-w-0 items-center gap-2 text-xs text-muted-foreground",
1992
1970
  children: [
1993
- hasTeamSandboxes && /* @__PURE__ */ jsxs("div", {
1994
- className: "flex min-w-0 gap-2",
1995
- children: [/* @__PURE__ */ jsx("span", {
1996
- className: "shrink-0 text-muted-foreground",
1997
- children: "Scope"
1998
- }), sb.team ? /* @__PURE__ */ jsxs("span", {
1999
- className: "min-w-0 truncate text-foreground",
2000
- title: "Shared with " + (sb.team.name ?? "Team") + " · " + sb.team.role,
2001
- children: [
2002
- sb.team.name ?? "Team",
2003
- " - ",
2004
- sb.team.role
2005
- ]
2006
- }) : /* @__PURE__ */ jsx("span", {
2007
- className: "text-foreground",
2008
- children: "Personal"
2009
- })]
1971
+ /* @__PURE__ */ jsx("span", {
1972
+ className: "md:hidden",
1973
+ children: /* @__PURE__ */ jsx(StatusIndicator, { status: sb.status })
2010
1974
  }),
2011
- (sb.customImage ?? sb.image) && /* @__PURE__ */ jsxs("div", {
2012
- className: "flex min-w-0 gap-2",
2013
- children: [/* @__PURE__ */ jsx("span", {
2014
- className: "shrink-0 text-muted-foreground",
2015
- children: "Environment"
2016
- }), /* @__PURE__ */ jsx("span", {
2017
- className: "min-w-0 truncate text-foreground",
2018
- title: sb.customImage ?? sb.image,
2019
- children: sb.customImage ?? sb.image
2020
- })]
1975
+ sb.nodeId && /* @__PURE__ */ jsx("span", {
1976
+ className: "hidden truncate font-mono text-xs md:block",
1977
+ title: sb.nodeId,
1978
+ children: sb.nodeId
2021
1979
  }),
2022
- (isActive || isProvisioning || isHibernating) && /* @__PURE__ */ jsxs("div", {
2023
- className: "flex min-w-0 flex-col gap-1",
2024
- children: [/* @__PURE__ */ jsx("span", {
2025
- className: "text-muted-foreground",
2026
- children: "Resources"
2027
- }), /* @__PURE__ */ jsx(SandboxResources, { sandbox: sb })]
1980
+ hasTeamSandboxes && /* @__PURE__ */ jsx("span", {
1981
+ className: "truncate xl:hidden",
1982
+ title: sb.team ? `${sb.team.name ?? "Team"} · ${sb.team.role}` : "Personal",
1983
+ children: sb.team ? `${sb.team.name ?? "Team"} · ${sb.team.role}` : "Personal"
2028
1984
  })
2029
1985
  ]
2030
1986
  })]
2031
1987
  })
2032
1988
  }),
2033
1989
  hasTeamSandboxes && /* @__PURE__ */ jsx("td", {
2034
- className: "hidden px-3 py-4 align-top xl:table-cell xl:px-4 xl:py-5",
1990
+ className: "hidden px-4 py-3 align-middle xl:table-cell",
2035
1991
  children: sb.team ? /* @__PURE__ */ jsxs("div", {
2036
1992
  className: "inline-flex max-w-full items-center gap-1.5 overflow-hidden rounded-full bg-[var(--accent-surface-soft)] px-2.5 py-1 text-[11px] font-semibold text-[var(--accent-text)]",
2037
1993
  title: "Shared with " + (sb.team.name ?? "Team") + " · " + sb.team.role,
@@ -2058,73 +2014,41 @@ function SandboxTable({ sandboxes, page = 1, pageSize = 10, total, onPageChange,
2058
2014
  }), "Personal"]
2059
2015
  })
2060
2016
  }),
2061
- /* @__PURE__ */ jsx("td", {
2062
- className: "hidden px-3 py-4 align-top xl:table-cell xl:px-4 xl:py-5",
2063
- children: /* @__PURE__ */ jsxs("div", {
2064
- className: "flex min-w-0 items-center gap-2",
2065
- children: [sb.imageIcon && /* @__PURE__ */ jsx("div", {
2066
- className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-surface-container-high",
2067
- children: sb.imageIcon
2068
- }), (sb.customImage ?? sb.image) && /* @__PURE__ */ jsx("span", {
2069
- className: "min-w-0 truncate text-xs font-bold text-foreground",
2070
- title: sb.customImage ?? sb.image,
2071
- children: sb.customImage ?? sb.image
2072
- })]
2073
- })
2074
- }),
2075
- /* @__PURE__ */ jsx("td", {
2076
- className: "hidden px-3 py-4 align-top xl:table-cell xl:px-4 xl:py-5",
2017
+ hasResources && /* @__PURE__ */ jsx("td", {
2018
+ className: "hidden px-4 py-3 align-middle lg:table-cell",
2077
2019
  children: /* @__PURE__ */ jsx(SandboxResources, { sandbox: sb })
2078
2020
  }),
2079
2021
  /* @__PURE__ */ jsx("td", {
2080
- className: "w-28 px-2 py-3 text-right align-top xl:w-72 xl:px-4 xl:py-5",
2022
+ className: "w-44 px-3 py-3 text-right align-middle sm:w-48 sm:px-4",
2081
2023
  children: /* @__PURE__ */ jsxs("div", {
2082
- className: "flex min-w-0 flex-wrap items-center justify-end gap-1",
2024
+ className: "flex min-w-0 items-center justify-end gap-2",
2083
2025
  children: [
2084
- isActive && /* @__PURE__ */ jsxs(Fragment, { children: [
2085
- /* @__PURE__ */ jsx("button", {
2086
- type: "button",
2087
- onClick: (e) => {
2088
- stopRowClick(e);
2089
- onOpenIDE?.(sb.id);
2090
- },
2091
- className: cn$1("min-h-11 min-w-11 shrink-0 p-2 rounded-lg hover:bg-surface-container-high text-muted-foreground hover:text-foreground transition-all active:scale-90", focusRing),
2092
- "aria-label": "Open IDE",
2093
- title: "Open IDE",
2094
- children: /* @__PURE__ */ jsx(Code2, { className: "h-4 w-4" })
2095
- }),
2096
- /* @__PURE__ */ jsx("button", {
2097
- type: "button",
2098
- onClick: (e) => {
2099
- stopRowClick(e);
2100
- onOpenTerminal?.(sb.id);
2101
- },
2102
- className: cn$1("min-h-11 min-w-11 shrink-0 p-2 rounded-lg hover:bg-surface-container-high text-muted-foreground hover:text-foreground transition-all active:scale-90", focusRing),
2103
- "aria-label": "Open terminal",
2104
- title: "Terminal",
2105
- children: /* @__PURE__ */ jsx(Terminal, { className: "h-4 w-4" })
2106
- }),
2107
- /* @__PURE__ */ jsx("button", {
2108
- type: "button",
2109
- onClick: (e) => {
2110
- stopRowClick(e);
2111
- onSSH?.(sb.id);
2112
- },
2113
- className: cn$1("min-h-11 min-w-11 shrink-0 p-2 rounded-lg hover:bg-surface-container-high text-muted-foreground hover:text-foreground transition-all active:scale-90", focusRing),
2114
- "aria-label": "Open SSH details",
2115
- title: "SSH",
2116
- children: /* @__PURE__ */ jsx(Key, { className: "h-4 w-4" })
2117
- })
2118
- ] }),
2026
+ isActive && onOpenIDE && /* @__PURE__ */ jsxs("button", {
2027
+ type: "button",
2028
+ onClick: (e) => {
2029
+ stopRowClick(e);
2030
+ onOpenIDE(sb.id);
2031
+ },
2032
+ className: cn$1("inline-flex min-h-11 shrink-0 whitespace-nowrap items-center justify-center gap-2 rounded-lg border border-[var(--border-accent)] bg-[var(--accent-surface-soft)] px-3 text-sm font-semibold text-[var(--accent-text)] shadow-sm transition-colors hover:bg-[var(--accent-surface-strong)]", focusRing),
2033
+ "aria-label": "Open IDE",
2034
+ title: "Open IDE",
2035
+ children: [/* @__PURE__ */ jsx(Code2, {
2036
+ className: "h-4 w-4 shrink-0",
2037
+ "aria-hidden": "true"
2038
+ }), /* @__PURE__ */ jsx("span", { children: "Open" })]
2039
+ }),
2119
2040
  resumeHandler && /* @__PURE__ */ jsxs("button", {
2120
2041
  type: "button",
2121
2042
  onClick: (e) => {
2122
2043
  stopRowClick(e);
2123
2044
  resumeHandler(sb.id);
2124
2045
  },
2125
- className: cn$1("inline-flex min-h-11 items-center gap-1.5 px-3 py-1.5 rounded-lg border border-[var(--md3-outline-variant)] text-[var(--accent-text)] text-[10px] font-bold uppercase tracking-wider hover:bg-[var(--accent-surface-soft)] active:scale-95 transition-all", focusRing),
2046
+ className: cn$1("inline-flex min-h-11 shrink-0 whitespace-nowrap items-center justify-center gap-1.5 px-3 rounded-lg border border-[var(--border-accent)] bg-[var(--accent-surface-soft)] text-[var(--accent-text)] text-sm font-semibold shadow-sm hover:bg-[var(--accent-surface-strong)] transition-colors", focusRing),
2126
2047
  title: resumeLabel,
2127
- children: [/* @__PURE__ */ jsx(Play, { className: "h-3 w-3" }), resumeLabel]
2048
+ children: [/* @__PURE__ */ jsx(Play, {
2049
+ className: "h-4 w-4 shrink-0",
2050
+ "aria-hidden": "true"
2051
+ }), resumeLabel]
2128
2052
  }),
2129
2053
  (() => {
2130
2054
  const runItem = (handler) => (e) => {
@@ -2133,6 +2057,16 @@ function SandboxTable({ sandboxes, page = 1, pageSize = 10, total, onPageChange,
2133
2057
  };
2134
2058
  const overflowSections = [];
2135
2059
  if (isActive) {
2060
+ const access = [];
2061
+ if (onOpenTerminal) access.push(/* @__PURE__ */ jsxs(DropdownMenuItem, {
2062
+ onClick: runItem(onOpenTerminal),
2063
+ children: [/* @__PURE__ */ jsx(Terminal, { className: "mr-2 h-4 w-4" }), " Open terminal"]
2064
+ }, "terminal"));
2065
+ if (onSSH) access.push(/* @__PURE__ */ jsxs(DropdownMenuItem, {
2066
+ onClick: runItem(onSSH),
2067
+ children: [/* @__PURE__ */ jsx(Key, { className: "mr-2 h-4 w-4" }), " SSH details"]
2068
+ }, "ssh"));
2069
+ if (access.length) overflowSections.push(access);
2136
2070
  const lifecycle = [];
2137
2071
  if (onStop) lifecycle.push(/* @__PURE__ */ jsxs(DropdownMenuItem, {
2138
2072
  onClick: runItem(onStop),
@@ -2167,34 +2101,29 @@ function SandboxTable({ sandboxes, page = 1, pageSize = 10, total, onPageChange,
2167
2101
  onClick: runItem(onMore),
2168
2102
  children: [/* @__PURE__ */ jsx(ExternalLink, { className: "mr-2 h-4 w-4" }), " View Details"]
2169
2103
  }, "view-details")]);
2104
+ if (onDelete && canAdminSandbox(sb)) overflowSections.push([/* @__PURE__ */ jsxs(DropdownMenuItem, {
2105
+ onClick: runItem(onDelete),
2106
+ className: "text-destructive focus:text-destructive",
2107
+ "aria-label": `Delete ${sb.name}`,
2108
+ children: [/* @__PURE__ */ jsx(Trash2, { className: "mr-2 h-4 w-4" }), " Delete"]
2109
+ }, "delete")]);
2170
2110
  if (overflowSections.length === 0) return null;
2171
2111
  return /* @__PURE__ */ jsxs(DropdownMenu, { children: [/* @__PURE__ */ jsx(DropdownMenuTrigger, {
2172
2112
  asChild: true,
2173
2113
  children: /* @__PURE__ */ jsx("button", {
2174
2114
  type: "button",
2175
2115
  onClick: stopRowClick,
2176
- className: `min-h-11 min-w-11 shrink-0 p-2 rounded-lg hover:bg-surface-container-high text-muted-foreground hover:text-foreground transition-all active:scale-90 ${focusRing}`,
2116
+ className: `inline-flex min-h-11 min-w-11 shrink-0 items-center justify-center rounded-lg border border-border bg-surface-container-high text-foreground shadow-sm transition-colors hover:bg-surface-container-highest ${focusRing}`,
2177
2117
  "aria-label": `More actions for ${sb.name}`,
2178
2118
  title: "More actions",
2179
2119
  children: /* @__PURE__ */ jsx(MoreVertical, { className: "h-4 w-4" })
2180
2120
  })
2181
2121
  }), /* @__PURE__ */ jsx(DropdownMenuContent, {
2182
2122
  align: "end",
2183
- className: "min-w-[180px]",
2123
+ className: "min-w-[200px] border-border bg-surface-container-high shadow-xl [&_[role=menuitem]]:min-h-10 [&_[role=menuitem]]:text-sm",
2184
2124
  children: overflowSections.map((section, sectionIdx) => /* @__PURE__ */ jsxs(React$1.Fragment, { children: [sectionIdx > 0 && /* @__PURE__ */ jsx(DropdownMenuSeparator, {}), section] }, sectionIdx))
2185
2125
  })] });
2186
- })(),
2187
- onDelete && canAdminSandbox(sb) && /* @__PURE__ */ jsx("button", {
2188
- type: "button",
2189
- "aria-label": `Delete ${sb.name}`,
2190
- onClick: (e) => {
2191
- stopRowClick(e);
2192
- onDelete(sb.id);
2193
- },
2194
- className: `min-h-11 min-w-11 shrink-0 p-2 rounded-lg hover:bg-[var(--surface-danger-bg)] text-muted-foreground hover:text-[var(--surface-danger-text)] transition-all active:scale-90 ${focusRing}`,
2195
- title: "Delete",
2196
- children: /* @__PURE__ */ jsx(Trash2, { className: "h-4 w-4" })
2197
- })
2126
+ })()
2198
2127
  ]
2199
2128
  })
2200
2129
  })
@@ -2227,7 +2156,7 @@ function SandboxTable({ sandboxes, page = 1, pageSize = 10, total, onPageChange,
2227
2156
  onClick: () => onPageChange?.(currentPage - 1),
2228
2157
  disabled: !onPageChange || currentPage <= 1,
2229
2158
  "aria-label": "Previous page",
2230
- className: cn$1("min-h-11 min-w-11 rounded-lg border border-[var(--md3-outline-variant)] p-2 transition-colors hover:bg-surface-container-high disabled:opacity-30", focusRing),
2159
+ className: cn$1("inline-flex min-h-11 min-w-11 items-center justify-center rounded-lg border border-border bg-surface-container-high p-2 shadow-sm transition-colors hover:bg-surface-container-highest disabled:opacity-30", focusRing),
2231
2160
  children: /* @__PURE__ */ jsx(ChevronLeft, { className: "h-4 w-4" })
2232
2161
  }),
2233
2162
  getPageItems(currentPage, totalPages).map((item) => typeof item === "number" ? /* @__PURE__ */ jsx("button", {
@@ -2236,7 +2165,7 @@ function SandboxTable({ sandboxes, page = 1, pageSize = 10, total, onPageChange,
2236
2165
  disabled: !onPageChange,
2237
2166
  "aria-label": "Go to page " + item,
2238
2167
  "aria-current": item === currentPage ? "page" : void 0,
2239
- className: cn$1("min-h-11 min-w-11 rounded-lg px-2 py-1 transition-colors", item === currentPage ? "border border-[var(--md3-outline)] bg-[var(--accent-surface-soft)] text-[var(--accent-text)]" : "hover:bg-surface-container-high", !onPageChange && "cursor-not-allowed opacity-30"),
2168
+ className: cn$1("inline-flex min-h-11 min-w-11 items-center justify-center rounded-lg px-2 py-1 transition-colors", item === currentPage ? "border border-[var(--md3-outline)] bg-[var(--accent-surface-soft)] text-[var(--accent-text)]" : "hover:bg-surface-container-high", !onPageChange && "cursor-not-allowed opacity-30"),
2240
2169
  children: item
2241
2170
  }, item) : /* @__PURE__ */ jsx("span", {
2242
2171
  className: "px-1",
@@ -2248,7 +2177,7 @@ function SandboxTable({ sandboxes, page = 1, pageSize = 10, total, onPageChange,
2248
2177
  onClick: () => onPageChange?.(currentPage + 1),
2249
2178
  disabled: !onPageChange || currentPage >= totalPages,
2250
2179
  "aria-label": "Next page",
2251
- className: cn$1("min-h-11 min-w-11 rounded-lg border border-[var(--md3-outline-variant)] p-2 transition-colors hover:bg-surface-container-high disabled:opacity-30", focusRing),
2180
+ className: cn$1("inline-flex min-h-11 min-w-11 items-center justify-center rounded-lg border border-border bg-surface-container-high p-2 shadow-sm transition-colors hover:bg-surface-container-highest disabled:opacity-30", focusRing),
2252
2181
  children: /* @__PURE__ */ jsx(ChevronRight, { className: "h-4 w-4" })
2253
2182
  })
2254
2183
  ]
@@ -5109,4 +5038,28 @@ function PromoBanner({ title, description, buttonLabel, href, onClick, icon, dis
5109
5038
  });
5110
5039
  }
5111
5040
  //#endregion
5112
- export { SidebarRailNav as $, ResourceMeter as A, RailFlyout as B, InvoiceTable as C, canAdminSandbox as D, SandboxCard as E, CreditBalance as F, Sidebar as G, RailModeButton as H, ProfileAvatar as I, SidebarPanelContent as J, SidebarContent as K, RailButton as L, INSUFFICIENT_BALANCE_CODE as M, OutOfCreditsModal as N, ActivityFeed as O, parseInsufficientBalance as P, SidebarRailHeader as Q, RailCollapseToggle as R, PlanCards as S, NewSandboxCard as T, RailSeparator as U, RailHeader as V, RailThemeToggle as W, SidebarRail as X, SidebarPanelHeader as Y, SidebarRailFooter as Z, HarnessPicker as _, ProcessList as a, SIDEBAR_TOTAL_WIDTH as at, HarnessLogo as b, UsageSummary as c, MetricAreaChart as d, RailTooltip as et, ProfileComparison as f, HARNESS_OPTIONS as g, DashboardLayout as h, NetworkConfig as i, SIDEBAR_RAIL_WIDTH as it, ClusterStatusBar as j, ResourceSnapshot as k, SystemLogsViewer as l, SidebarLayout as m, SnapshotList as n, SIDEBAR_PANEL_WIDTH as nt, PortsList as o, SidebarProvider as ot, ProfileSelector as p, SidebarPanel as q, BackendConfig as r, SIDEBAR_RAIL_LABELED_WIDTH as rt, GitPanel as s, useSidebar as st, PromoBanner as t, SIDEBAR_MOBILE_WIDTH as tt, VariantList as u, chatCapableHarnesses as v, SandboxTable as w, BackendSelector as x, HARNESS_BRAND as y, RailExpandable as z };
5041
+ //#region src/dashboard/info-panel.tsx
5042
+ function InfoPanel({ label, title, description, className }) {
5043
+ return /* @__PURE__ */ jsxs("div", {
5044
+ className: cn$1("rounded-lg bg-[var(--brand-strong)] p-5 text-[var(--brand-strong-text)] relative overflow-hidden", className),
5045
+ children: [/* @__PURE__ */ jsxs("div", {
5046
+ className: "relative z-10",
5047
+ children: [
5048
+ /* @__PURE__ */ jsx("p", {
5049
+ className: "text-[10px] font-bold uppercase tracking-widest text-[var(--brand-strong-text-dim)]",
5050
+ children: label
5051
+ }),
5052
+ /* @__PURE__ */ jsx("h3", {
5053
+ className: "mt-1 text-lg font-bold",
5054
+ children: title
5055
+ }),
5056
+ /* @__PURE__ */ jsx("p", {
5057
+ className: "mt-1 text-sm text-[var(--brand-strong-text-muted)]",
5058
+ children: description
5059
+ })
5060
+ ]
5061
+ }), /* @__PURE__ */ jsx("div", { className: "absolute right-0 top-0 h-full w-1/3 bg-white/5 -skew-x-12 translate-x-12 pointer-events-none" })]
5062
+ });
5063
+ }
5064
+ //#endregion
5065
+ export { SidebarRailHeader as $, ResourceSnapshot as A, RailExpandable as B, PlanCards as C, SandboxCard as D, NewSandboxCard as E, parseInsufficientBalance as F, RailThemeToggle as G, RailHeader as H, CreditBalance as I, SidebarPanel as J, Sidebar as K, ProfileAvatar as L, ClusterStatusBar as M, INSUFFICIENT_BALANCE_CODE as N, canAdminSandbox as O, OutOfCreditsModal as P, SidebarRailFooter as Q, RailButton as R, BackendSelector as S, SandboxTable as T, RailModeButton as U, RailFlyout as V, RailSeparator as W, SidebarPanelHeader as X, SidebarPanelContent as Y, SidebarRail as Z, HARNESS_OPTIONS as _, NetworkConfig as a, SIDEBAR_RAIL_WIDTH as at, HARNESS_BRAND as b, GitPanel as c, useSidebar as ct, VariantList as d, SidebarRailNav as et, MetricAreaChart as f, DashboardLayout as g, SidebarLayout as h, BackendConfig as i, SIDEBAR_RAIL_LABELED_WIDTH as it, ResourceMeter as j, ActivityFeed as k, UsageSummary as l, ProfileSelector as m, PromoBanner as n, SIDEBAR_MOBILE_WIDTH as nt, ProcessList as o, SIDEBAR_TOTAL_WIDTH as ot, ProfileComparison as p, SidebarContent as q, SnapshotList as r, SIDEBAR_PANEL_WIDTH as rt, PortsList as s, SidebarProvider as st, InfoPanel as t, RailTooltip as tt, SystemLogsViewer as u, HarnessPicker as v, InvoiceTable as w, HarnessLogo as x, chatCapableHarnesses as y, RailCollapseToggle as z };