@tangle-network/sandbox-ui 0.113.4 → 0.113.5

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,7 +1,7 @@
1
1
  import {
2
2
  Button,
3
3
  Logo
4
- } from "./chunk-2XPJ2XF7.js";
4
+ } from "./chunk-ANSC5AFC.js";
5
5
  import {
6
6
  moonshot_default
7
7
  } from "./chunk-RQZRXKMR.js";
@@ -227,7 +227,8 @@ function RailTooltip({ label, children, disabled, className }) {
227
227
  }
228
228
 
229
229
  // src/dashboard/app-sidebar.tsx
230
- import { Fragment, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
230
+ import { focusRing } from "@tangle-network/ui/utils";
231
+ import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
231
232
  function DefaultLink({
232
233
  href,
233
234
  to,
@@ -286,7 +287,7 @@ function RailThemeToggle({ className }) {
286
287
  "flex h-9 w-9 shrink-0 items-center justify-center rounded-md text-muted-foreground transition-colors",
287
288
  MOTION_CONTROL,
288
289
  "hover:bg-[var(--accent-surface-soft)] hover:text-foreground",
289
- "focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
290
+ focusRing,
290
291
  className
291
292
  ),
292
293
  children: isDark ? /* @__PURE__ */ jsx3(SunIcon, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx3(MoonIcon, { className: "h-4 w-4" })
@@ -320,7 +321,7 @@ function RailCollapseToggle({ collapsed, showLabel, onToggle, className }) {
320
321
  MOTION_CONTROL,
321
322
  showLabel ? "h-9 w-full justify-start gap-2.5 px-2.5" : "h-9 w-9 justify-center",
322
323
  "hover:bg-[var(--accent-surface-soft)] hover:text-foreground",
323
- "focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
324
+ focusRing,
324
325
  className
325
326
  ),
326
327
  children: [
@@ -344,15 +345,22 @@ function PanelToggleButton({ collapsed, onToggle, className }) {
344
345
  "flex h-8 w-8 shrink-0 items-center justify-center rounded-md text-muted-foreground transition-colors",
345
346
  MOTION_CONTROL,
346
347
  "hover:bg-[var(--accent-surface-soft)] hover:text-foreground",
347
- "focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
348
+ focusRing,
348
349
  className
349
350
  ),
350
351
  children: /* @__PURE__ */ jsx3(PanelLeft, { className: "h-[18px] w-[18px] shrink-0" })
351
352
  }
352
353
  );
353
354
  }
355
+ function isRenderable(node) {
356
+ return React3.Children.toArray(node).some(
357
+ (child) => React3.isValidElement(child) && child.type === React3.Fragment ? isRenderable(child.props.children) : true
358
+ );
359
+ }
354
360
  function RailHeader({ brand, brandHref, children, collapsed, onToggle, collapsible = true, LinkComponent, className }) {
355
361
  const Link = LinkComponent ?? DefaultLink;
362
+ const hasBrand = isRenderable(brand);
363
+ const hasChildren = isRenderable(children);
356
364
  const brandNode = brandHref !== void 0 ? /* @__PURE__ */ jsx3(
357
365
  Link,
358
366
  {
@@ -371,21 +379,50 @@ function RailHeader({ brand, brandHref, children, collapsed, onToggle, collapsib
371
379
  collapsed ? "justify-center px-2" : "gap-2 px-3",
372
380
  className
373
381
  ),
374
- children: collapsed ? collapsible ? /* @__PURE__ */ jsx3(RailTooltip, { label: "Expand sidebar", children: /* @__PURE__ */ jsxs2(
382
+ children: collapsed ? !hasBrand && hasChildren ? (
383
+ // No brand mark: `children` (SidebarLayout's `railHeaderContent`) is
384
+ // the only rail-top content the consumer gave us, so render it here
385
+ // too. Dropping it left an EMPTY header — the collapsed rail showed
386
+ // nothing at all where the product's mark belongs. With neither a
387
+ // brand nor children, the plain expand button below still owns the
388
+ // rail top so the rail stays expandable.
389
+ //
390
+ // Rendered outside the expand button on purpose: content that owns
391
+ // the rail top is routinely interactive itself (a mark that expands
392
+ // the rail on click), and a <button> inside a <button> is invalid
393
+ // HTML that React refuses to hydrate.
394
+ //
395
+ // The explicit "Expand sidebar" control stays in the tree for
396
+ // keyboard and assistive-tech users (the content may be a passive
397
+ // switcher, and the empty-rail click fallback is mouse-only). It sits
398
+ // over the content, invisible and non-interactive until it receives
399
+ // keyboard focus, so it costs no rail width.
400
+ /* @__PURE__ */ jsxs2("div", { className: "relative flex min-w-0 items-center justify-center", children: [
401
+ children,
402
+ collapsible && /* @__PURE__ */ jsx3(
403
+ PanelToggleButton,
404
+ {
405
+ collapsed,
406
+ onToggle,
407
+ className: "pointer-events-none absolute inset-0 m-auto bg-background opacity-0 focus-visible:pointer-events-auto focus-visible:opacity-100"
408
+ }
409
+ )
410
+ ] })
411
+ ) : collapsible ? /* @__PURE__ */ jsx3(RailTooltip, { label: "Expand sidebar", children: /* @__PURE__ */ jsxs2(
375
412
  "button",
376
413
  {
377
414
  type: "button",
378
415
  onClick: onToggle,
379
416
  "aria-label": "Expand sidebar",
380
417
  "aria-pressed": true,
381
- className: cn("group/brand relative flex h-9 w-9 items-center justify-center rounded-md transition-colors hover:bg-[var(--accent-surface-soft)] focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring", MOTION_CONTROL),
418
+ className: cn("group/brand relative flex h-9 w-9 items-center justify-center rounded-md transition-colors hover:bg-[var(--accent-surface-soft)]", focusRing, MOTION_CONTROL),
382
419
  children: [
383
420
  /* @__PURE__ */ jsx3("span", { className: cn("flex items-center justify-center transition-opacity group-hover/brand:opacity-0", MOTION_CONTROL), children: brand }),
384
421
  /* @__PURE__ */ jsx3("span", { className: cn("pointer-events-none absolute inset-0 flex items-center justify-center text-foreground opacity-0 transition-opacity group-hover/brand:opacity-100", MOTION_CONTROL), children: /* @__PURE__ */ jsx3(PanelLeft, { className: "h-[18px] w-[18px]" }) })
385
422
  ]
386
423
  }
387
- ) }) : brandNode : /* @__PURE__ */ jsxs2(Fragment, { children: [
388
- brand !== void 0 && brandNode,
424
+ ) }) : brandNode : /* @__PURE__ */ jsxs2(Fragment2, { children: [
425
+ hasBrand && brandNode,
389
426
  /* @__PURE__ */ jsx3("div", { className: "min-w-0 flex-1", children }),
390
427
  collapsible && /* @__PURE__ */ jsx3(PanelToggleButton, { collapsed, onToggle })
391
428
  ] })
@@ -445,7 +482,7 @@ function RailButton({ icon: Icon2, label, isActive, badge, onClick, className, s
445
482
  MOTION_CONTROL,
446
483
  showLabel ? "w-full justify-start px-2.5 h-9 gap-2.5" : "w-9 h-9 justify-center",
447
484
  // Quiet press feedback via color only — no scale on the full-width row.
448
- "focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
485
+ focusRing,
449
486
  // The active item (route matches) and any explicit primary share one
450
487
  // emphasized look — a filled accent pill with an accent ring — so the
451
488
  // current destination clearly stands out from the default rows.
@@ -456,7 +493,7 @@ function RailButton({ icon: Icon2, label, isActive, badge, onClick, className, s
456
493
  /* @__PURE__ */ jsx3(Icon2, { className: "h-[17px] w-[17px] shrink-0" }),
457
494
  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 })
458
495
  ] });
459
- const content = /* @__PURE__ */ jsxs2(Fragment, { children: [
496
+ const content = /* @__PURE__ */ jsxs2(Fragment2, { children: [
460
497
  iconWithBadge,
461
498
  showLabel && /* @__PURE__ */ jsx3("span", { className: "text-[13.5px] font-medium", children: label })
462
499
  ] });
@@ -512,7 +549,7 @@ function RailFlyout({
512
549
  "relative flex shrink-0 items-center rounded-md transition-colors",
513
550
  MOTION_CONTROL,
514
551
  showLabel ? "w-full justify-start px-2.5 h-9 gap-2.5" : "w-9 h-9 justify-center",
515
- "focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
552
+ focusRing,
516
553
  active ? "bg-[var(--accent-surface-strong)] text-[var(--accent-text)]" : "text-muted-foreground hover:bg-[var(--accent-surface-soft)] hover:text-foreground",
517
554
  className
518
555
  );
@@ -724,7 +761,7 @@ function RailExpandable({
724
761
  const triggerClasses = cn(
725
762
  "relative flex h-9 w-9 items-center justify-center rounded-md transition-colors",
726
763
  MOTION_CONTROL,
727
- "focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
764
+ focusRing,
728
765
  isActive || open ? "bg-[var(--accent-surface-strong)] text-[var(--accent-text)] font-medium ring-1 ring-inset ring-[var(--border-accent)]" : "text-muted-foreground hover:bg-[var(--accent-surface-soft)] hover:text-foreground"
729
766
  );
730
767
  const openFlyout = () => {
@@ -828,7 +865,7 @@ function RailExpandable({
828
865
  "aria-expanded": open,
829
866
  "aria-controls": discloseId,
830
867
  "aria-label": open ? `Collapse ${label}` : `Expand ${label}`,
831
- className: "relative flex h-9 w-9 shrink-0 items-center justify-center rounded-md focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
868
+ className: `relative flex h-9 w-9 shrink-0 items-center justify-center rounded-md ${focusRing}`,
832
869
  children: [
833
870
  /* @__PURE__ */ jsx3(
834
871
  Icon2,
@@ -945,7 +982,7 @@ function AppearanceMenuSection({ appearance, divider = true }) {
945
982
  const resolved = appearance.value === "system" ? systemDark ? "dark" : "light" : appearance.value;
946
983
  const TriggerIcon = resolved === "dark" ? MoonIcon : SunIcon;
947
984
  const caption = appearance.value === "system" ? `System (${resolved === "dark" ? "Dark" : "Light"})` : APPEARANCE_META[appearance.value].label;
948
- return /* @__PURE__ */ jsxs2(Fragment, { children: [
985
+ return /* @__PURE__ */ jsxs2(Fragment2, { children: [
949
986
  divider && /* @__PURE__ */ jsx3(DropdownMenuSeparator, {}),
950
987
  /* @__PURE__ */ jsxs2(DropdownMenuSub, { children: [
951
988
  /* @__PURE__ */ jsxs2(DropdownMenuSubTrigger, { children: [
@@ -999,7 +1036,7 @@ function ProfileAvatar({
999
1036
  className: cn(
1000
1037
  "flex items-center rounded-lg transition-colors hover:bg-[var(--accent-surface-soft)]",
1001
1038
  MOTION_CONTROL,
1002
- "focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
1039
+ focusRing,
1003
1040
  showDetails ? "w-full gap-2.5 px-3 py-2 text-left" : "justify-center w-12 h-12",
1004
1041
  className
1005
1042
  ),
@@ -1019,10 +1056,10 @@ function ProfileAvatar({
1019
1056
  user?.avatarUrl && /* @__PURE__ */ jsx3(AvatarImage, { src: user.avatarUrl, alt: "" }),
1020
1057
  /* @__PURE__ */ jsx3(AvatarFallback, { className: "text-sm bg-[var(--surface-violet-bg)] text-[var(--surface-violet-text)]", children: getInitials(user?.name, user?.email) })
1021
1058
  ] }),
1022
- /* @__PURE__ */ jsx3("div", { className: "min-w-0 flex-1", children: isLoading ? /* @__PURE__ */ jsxs2(Fragment, { children: [
1059
+ /* @__PURE__ */ jsx3("div", { className: "min-w-0 flex-1", children: isLoading ? /* @__PURE__ */ jsxs2(Fragment2, { children: [
1023
1060
  /* @__PURE__ */ jsx3(Skeleton, { className: "h-4 w-24 mb-1" }),
1024
1061
  /* @__PURE__ */ jsx3(Skeleton, { className: "h-3 w-32" })
1025
- ] }) : /* @__PURE__ */ jsxs2(Fragment, { children: [
1062
+ ] }) : /* @__PURE__ */ jsxs2(Fragment2, { children: [
1026
1063
  /* @__PURE__ */ jsx3("p", { className: "text-sm font-semibold truncate", children: user?.name ?? user?.email ?? "Not logged in" }),
1027
1064
  user?.email && user?.name && /* @__PURE__ */ jsx3("p", { className: "text-xs text-muted-foreground truncate", children: user.email }),
1028
1065
  user?.tier && /* @__PURE__ */ jsxs2("p", { className: "text-xs text-muted-foreground capitalize", children: [
@@ -1041,7 +1078,7 @@ function ProfileAvatar({
1041
1078
  /* @__PURE__ */ jsx3(SettingsIcon, { className: "mr-2 h-4 w-4", "aria-hidden": "true" }),
1042
1079
  "Settings"
1043
1080
  ] }) }),
1044
- onLogout && /* @__PURE__ */ jsxs2(Fragment, { children: [
1081
+ onLogout && /* @__PURE__ */ jsxs2(Fragment2, { children: [
1045
1082
  /* @__PURE__ */ jsx3(DropdownMenuSeparator, {}),
1046
1083
  /* @__PURE__ */ jsxs2(DropdownMenuItem, { className: "text-[var(--surface-danger-text)]", onClick: onLogout, children: [
1047
1084
  /* @__PURE__ */ jsx3(LogOutIcon, { className: "mr-2 h-4 w-4", "aria-hidden": "true" }),
@@ -1054,6 +1091,7 @@ function ProfileAvatar({
1054
1091
 
1055
1092
  // src/dashboard/credit-balance.tsx
1056
1093
  import * as React4 from "react";
1094
+ import { focusFieldWithin } from "@tangle-network/ui/utils";
1057
1095
  import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
1058
1096
  function CreditBalance({
1059
1097
  amount,
@@ -1080,7 +1118,7 @@ function CreditBalance({
1080
1118
  /* @__PURE__ */ jsx4("p", { className: "text-sm text-muted-foreground leading-relaxed", children: description })
1081
1119
  ] }),
1082
1120
  onTopUp && /* @__PURE__ */ jsxs3("div", { className: "space-y-2.5 mt-5", children: [
1083
- /* @__PURE__ */ jsxs3("div", { className: "bg-surface-container-low border border-[var(--md3-outline-variant)] p-1 rounded-lg flex items-center", children: [
1121
+ /* @__PURE__ */ jsxs3("div", { className: `bg-surface-container-low border p-1 rounded-lg flex items-center ${focusFieldWithin}`, children: [
1084
1122
  /* @__PURE__ */ jsx4(
1085
1123
  "input",
1086
1124
  {
@@ -1193,7 +1231,7 @@ function OutOfCreditsModal({
1193
1231
 
1194
1232
  // src/dashboard/cluster-status-bar.tsx
1195
1233
  import * as React5 from "react";
1196
- import { Fragment as Fragment3, jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
1234
+ import { Fragment as Fragment4, jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
1197
1235
  function ClusterStatusBar({ items, latency, className }) {
1198
1236
  if (!items?.length) return null;
1199
1237
  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: "flex items-center gap-4 overflow-x-auto rounded-full border border-[var(--md3-outline-variant)] bg-surface-container px-5 py-2.5 shadow-sm", children: [
@@ -1207,7 +1245,7 @@ function ClusterStatusBar({ items, latency, className }) {
1207
1245
  ] })
1208
1246
  ] })
1209
1247
  ] }, i)),
1210
- latency && /* @__PURE__ */ jsxs5(Fragment3, { children: [
1248
+ latency && /* @__PURE__ */ jsxs5(Fragment4, { children: [
1211
1249
  /* @__PURE__ */ jsx6("span", { "aria-hidden": true, className: "h-5 w-px shrink-0 bg-border" }),
1212
1250
  /* @__PURE__ */ jsxs5("div", { className: "flex shrink-0 items-center gap-2", children: [
1213
1251
  /* @__PURE__ */ jsxs5("span", { className: "relative flex h-2.5 w-2.5 items-center justify-center", children: [
@@ -1357,7 +1395,8 @@ import {
1357
1395
  HardDrive,
1358
1396
  Box
1359
1397
  } from "lucide-react";
1360
- import { Fragment as Fragment4, jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
1398
+ import { focusRing as focusRing2 } from "@tangle-network/ui/utils";
1399
+ import { Fragment as Fragment5, jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
1361
1400
  function canAdminSandbox(sandbox) {
1362
1401
  if (!sandbox.team) return true;
1363
1402
  return sandbox.team.role === "owner" || sandbox.team.role === "admin";
@@ -1451,13 +1490,13 @@ function SandboxCard({
1451
1490
  "button",
1452
1491
  {
1453
1492
  type: "button",
1454
- className: "rounded-md p-1.5 text-muted-foreground transition-colors hover:bg-surface-container-high hover:text-foreground outline-none",
1493
+ className: `rounded-md p-1.5 text-muted-foreground transition-colors hover:bg-surface-container-high hover:text-foreground ${focusRing2}`,
1455
1494
  "aria-label": "Sandbox options",
1456
1495
  children: /* @__PURE__ */ jsx10(MoreVertical, { className: "h-4 w-4" })
1457
1496
  }
1458
1497
  ) }),
1459
1498
  /* @__PURE__ */ jsxs9(DropdownMenuContent2, { align: "end", className: "min-w-[180px]", children: [
1460
- isRunning && /* @__PURE__ */ jsxs9(Fragment4, { children: [
1499
+ isRunning && /* @__PURE__ */ jsxs9(Fragment5, { children: [
1461
1500
  onStop && /* @__PURE__ */ jsxs9(DropdownMenuItem2, { onClick: () => onStop(sandbox.id), children: [
1462
1501
  /* @__PURE__ */ jsx10(PowerOff, { className: "mr-2 h-4 w-4" }),
1463
1502
  " Stop Sandbox"
@@ -1476,7 +1515,7 @@ function SandboxCard({
1476
1515
  " Health Check"
1477
1516
  ] }),
1478
1517
  (onUsage || onHealth) && /* @__PURE__ */ jsx10(DropdownMenuSeparator2, {}),
1479
- onFork && /* @__PURE__ */ jsxs9(Fragment4, { children: [
1518
+ onFork && /* @__PURE__ */ jsxs9(Fragment5, { children: [
1480
1519
  /* @__PURE__ */ jsxs9(DropdownMenuItem2, { onClick: () => onFork(sandbox.id), children: [
1481
1520
  /* @__PURE__ */ jsx10(Copy, { className: "mr-2 h-4 w-4" }),
1482
1521
  " Fork Sandbox"
@@ -1484,7 +1523,7 @@ function SandboxCard({
1484
1523
  /* @__PURE__ */ jsx10(DropdownMenuSeparator2, {})
1485
1524
  ] })
1486
1525
  ] }),
1487
- isStopped && /* @__PURE__ */ jsxs9(Fragment4, { children: [
1526
+ isStopped && /* @__PURE__ */ jsxs9(Fragment5, { children: [
1488
1527
  resumeHandler && /* @__PURE__ */ jsxs9(DropdownMenuItem2, { onClick: () => resumeHandler(sandbox.id), children: [
1489
1528
  /* @__PURE__ */ jsx10(Power, { className: "mr-2 h-4 w-4" }),
1490
1529
  " ",
@@ -1647,7 +1686,8 @@ import {
1647
1686
  DropdownMenuSeparator as DropdownMenuSeparator3,
1648
1687
  DropdownMenuTrigger as DropdownMenuTrigger3
1649
1688
  } from "@tangle-network/ui/primitives";
1650
- import { Fragment as Fragment6, jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
1689
+ import { focusRing as focusRing3 } from "@tangle-network/ui/utils";
1690
+ import { Fragment as Fragment7, jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
1651
1691
  var statusColors = {
1652
1692
  running: { dot: "bg-[var(--code-success)] animate-pulse", text: "text-[var(--code-success)]", bar: "bg-[var(--code-success)]" },
1653
1693
  hibernating: { dot: "bg-muted-foreground", text: "text-muted-foreground", bar: "bg-muted-foreground" },
@@ -1803,7 +1843,7 @@ function SandboxTable({
1803
1843
  /* @__PURE__ */ jsx11(MiniMeter, { label: "RAM", percent: 0 })
1804
1844
  ] }) : null }),
1805
1845
  /* @__PURE__ */ jsx11("td", { className: "px-6 py-5 text-right", children: /* @__PURE__ */ jsxs10("div", { className: "flex items-center justify-end gap-1", children: [
1806
- isActive && /* @__PURE__ */ jsxs10(Fragment6, { children: [
1846
+ isActive && /* @__PURE__ */ jsxs10(Fragment7, { children: [
1807
1847
  /* @__PURE__ */ jsx11("button", { type: "button", onClick: (e) => {
1808
1848
  stopRowClick(e);
1809
1849
  onOpenIDE?.(sb.id);
@@ -1895,7 +1935,7 @@ function SandboxTable({
1895
1935
  {
1896
1936
  type: "button",
1897
1937
  onClick: stopRowClick,
1898
- className: "p-2 rounded-lg hover:bg-surface-container-high text-muted-foreground hover:text-foreground transition-all active:scale-90 outline-none",
1938
+ className: `p-2 rounded-lg hover:bg-surface-container-high text-muted-foreground hover:text-foreground transition-all active:scale-90 ${focusRing3}`,
1899
1939
  "aria-label": "More actions",
1900
1940
  title: "More actions",
1901
1941
  children: /* @__PURE__ */ jsx11(MoreVertical2, { className: "h-4 w-4" })
@@ -2040,6 +2080,7 @@ function PlanCards({ plans, className }) {
2040
2080
  // src/dashboard/backend-selector.tsx
2041
2081
  import { ChevronDown } from "lucide-react";
2042
2082
  import * as Select from "@radix-ui/react-select";
2083
+ import { focusRing as focusRing4 } from "@tangle-network/ui/utils";
2043
2084
  import { jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
2044
2085
  function BackendSelector({
2045
2086
  backends,
@@ -2063,7 +2104,7 @@ function BackendSelector({
2063
2104
  "px-2.5 text-xs font-medium text-foreground shadow-sm",
2064
2105
  "transition-colors duration-[var(--transition-fast)]",
2065
2106
  "hover:border-[var(--md3-outline-variant)] hover:bg-surface-container-high",
2066
- "focus:outline-none focus-visible:ring-1 focus-visible:ring-ring",
2107
+ focusRing4,
2067
2108
  "data-[state=open]:border-[var(--md3-outline)] data-[state=open]:bg-surface-container-high",
2068
2109
  "disabled:opacity-50 disabled:cursor-not-allowed",
2069
2110
  triggerClassName
@@ -2084,7 +2125,7 @@ function BackendSelector({
2084
2125
  "border border-[var(--md3-outline-variant)] bg-surface-container px-3 py-2.5 text-sm text-left",
2085
2126
  "transition-colors duration-[var(--transition-fast)]",
2086
2127
  "hover:border-[var(--md3-outline-variant)] hover:bg-surface-container-high",
2087
- "focus:outline-none focus-visible:ring-1 focus-visible:ring-ring",
2128
+ focusRing4,
2088
2129
  "data-[state=open]:border-[var(--md3-outline)] data-[state=open]:bg-surface-container-high",
2089
2130
  "disabled:opacity-50 disabled:cursor-not-allowed",
2090
2131
  triggerClassName
@@ -2338,7 +2379,7 @@ function useBrandThemeSync() {
2338
2379
  }
2339
2380
 
2340
2381
  // src/dashboard/dashboard-layout.tsx
2341
- import { Fragment as Fragment8, jsx as jsx17, jsxs as jsxs14 } from "react/jsx-runtime";
2382
+ import { Fragment as Fragment9, jsx as jsx17, jsxs as jsxs14 } from "react/jsx-runtime";
2342
2383
  function MenuIcon({ className }) {
2343
2384
  return /* @__PURE__ */ jsxs14("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: [
2344
2385
  /* @__PURE__ */ jsx17("title", { children: "Menu icon" }),
@@ -2425,7 +2466,7 @@ function DashboardLayoutInner({
2425
2466
  );
2426
2467
  const activePanel = panels.find((p) => p.mode === mode);
2427
2468
  const buildSidebarContent = React9.useCallback(
2428
- (showLabels, allowCollapse) => /* @__PURE__ */ jsxs14(Fragment8, { children: [
2469
+ (showLabels, allowCollapse) => /* @__PURE__ */ jsxs14(Fragment9, { children: [
2429
2470
  /* @__PURE__ */ jsxs14(SidebarRail, { wide: showLabels, children: [
2430
2471
  /* @__PURE__ */ jsx17(
2431
2472
  RailHeader,
@@ -2706,7 +2747,7 @@ function DashboardLayout({ defaultPanelOpen, defaultMode, labeledRail, defaultRa
2706
2747
 
2707
2748
  // src/dashboard/sidebar-layout.tsx
2708
2749
  import * as React10 from "react";
2709
- import { Fragment as Fragment9, jsx as jsx18, jsxs as jsxs15 } from "react/jsx-runtime";
2750
+ import { Fragment as Fragment10, jsx as jsx18, jsxs as jsxs15 } from "react/jsx-runtime";
2710
2751
  var HIDE_BELOW_CLASS = {
2711
2752
  md: "max-md:hidden",
2712
2753
  lg: "max-lg:hidden"
@@ -2939,7 +2980,7 @@ function SidebarLayoutInner({
2939
2980
  breakpoint: hideBelow,
2940
2981
  onClose: closeMobileNav,
2941
2982
  header: railHeaderContent ?? logo,
2942
- footer: railFooter !== void 0 || hasProfile ? /* @__PURE__ */ jsxs15(Fragment9, { children: [
2983
+ footer: railFooter !== void 0 || hasProfile ? /* @__PURE__ */ jsxs15(Fragment10, { children: [
2943
2984
  railFooter,
2944
2985
  hasProfile && /* @__PURE__ */ jsx18(
2945
2986
  ProfileAvatar,
@@ -3096,7 +3137,7 @@ import {
3096
3137
  DropdownMenuSeparator as DropdownMenuSeparator4,
3097
3138
  DropdownMenuTrigger as DropdownMenuTrigger4
3098
3139
  } from "@tangle-network/ui/primitives";
3099
- import { Fragment as Fragment10, jsx as jsx19, jsxs as jsxs16 } from "react/jsx-runtime";
3140
+ import { Fragment as Fragment11, jsx as jsx19, jsxs as jsxs16 } from "react/jsx-runtime";
3100
3141
  function ProfileSelector({
3101
3142
  profiles,
3102
3143
  selectedId,
@@ -3130,7 +3171,7 @@ function ProfileSelector({
3130
3171
  ]
3131
3172
  }
3132
3173
  ),
3133
- builtinProfiles.length > 0 && /* @__PURE__ */ jsxs16(Fragment10, { children: [
3174
+ builtinProfiles.length > 0 && /* @__PURE__ */ jsxs16(Fragment11, { children: [
3134
3175
  /* @__PURE__ */ jsx19(DropdownMenuSeparator4, {}),
3135
3176
  /* @__PURE__ */ jsx19(DropdownMenuLabel2, { children: "Built-in Profiles" }),
3136
3177
  builtinProfiles.map((profile) => /* @__PURE__ */ jsxs16(
@@ -3155,7 +3196,7 @@ function ProfileSelector({
3155
3196
  profile.id
3156
3197
  ))
3157
3198
  ] }),
3158
- customProfiles.length > 0 && /* @__PURE__ */ jsxs16(Fragment10, { children: [
3199
+ customProfiles.length > 0 && /* @__PURE__ */ jsxs16(Fragment11, { children: [
3159
3200
  /* @__PURE__ */ jsx19(DropdownMenuSeparator4, {}),
3160
3201
  /* @__PURE__ */ jsx19(DropdownMenuLabel2, { children: "Custom Profiles" }),
3161
3202
  customProfiles.map((profile) => /* @__PURE__ */ jsxs16(
@@ -3192,7 +3233,7 @@ function ProfileSelector({
3192
3233
  profile.id
3193
3234
  ))
3194
3235
  ] }),
3195
- (onCreateClick || onManageClick) && /* @__PURE__ */ jsxs16(Fragment10, { children: [
3236
+ (onCreateClick || onManageClick) && /* @__PURE__ */ jsxs16(Fragment11, { children: [
3196
3237
  /* @__PURE__ */ jsx19(DropdownMenuSeparator4, {}),
3197
3238
  onCreateClick && /* @__PURE__ */ jsxs16(
3198
3239
  DropdownMenuItem4,
@@ -3434,7 +3475,7 @@ import {
3434
3475
  } from "lucide-react";
3435
3476
  import { Button as Button3 } from "@tangle-network/ui/primitives";
3436
3477
  import { Badge as Badge2 } from "@tangle-network/ui/primitives";
3437
- import { Fragment as Fragment12, jsx as jsx21, jsxs as jsxs18 } from "react/jsx-runtime";
3478
+ import { Fragment as Fragment13, jsx as jsx21, jsxs as jsxs18 } from "react/jsx-runtime";
3438
3479
  var statusConfig = {
3439
3480
  pending: {
3440
3481
  icon: Clock3,
@@ -3558,7 +3599,7 @@ function VariantList({
3558
3599
  children: outcomeConfig[variant.outcome].label
3559
3600
  }
3560
3601
  ),
3561
- variant.status === "completed" && variant.outcome === "pending_review" && onAccept && onReject && /* @__PURE__ */ jsxs18(Fragment12, { children: [
3602
+ variant.status === "completed" && variant.outcome === "pending_review" && onAccept && onReject && /* @__PURE__ */ jsxs18(Fragment13, { children: [
3562
3603
  /* @__PURE__ */ jsxs18(
3563
3604
  Button3,
3564
3605
  {
@@ -3872,6 +3913,7 @@ function GitPanel({ status, log, loading = false, onRefresh, className }) {
3872
3913
  // src/dashboard/ports-list.tsx
3873
3914
  import * as React13 from "react";
3874
3915
  import { Copy as Copy3, Check as Check5, Globe, Plus as Plus4, Trash2 as Trash23 } from "lucide-react";
3916
+ import { focusField, focusRing as focusRing5 } from "@tangle-network/ui/utils";
3875
3917
  import { jsx as jsx25, jsxs as jsxs22 } from "react/jsx-runtime";
3876
3918
  function PortsList({ ports, onExposePort, onRemovePort, isExposing = false, className }) {
3877
3919
  const [newPort, setNewPort] = React13.useState("");
@@ -3950,7 +3992,7 @@ function PortsList({ ports, onExposePort, onRemovePort, isExposing = false, clas
3950
3992
  value: newPort,
3951
3993
  onChange: (e) => setNewPort(e.target.value),
3952
3994
  onKeyDown: (e) => e.key === "Enter" && handleExpose(),
3953
- className: "flex-1 rounded-lg border border-[var(--md3-outline-variant)] bg-surface-container-low px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground focus:outline-none focus-visible:border-primary focus-visible:ring-2 focus-visible:ring-ring"
3995
+ className: `flex-1 rounded-lg border bg-surface-container-low px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground ${focusField}`
3954
3996
  }
3955
3997
  ),
3956
3998
  /* @__PURE__ */ jsxs22(
@@ -3959,7 +4001,7 @@ function PortsList({ ports, onExposePort, onRemovePort, isExposing = false, clas
3959
4001
  type: "button",
3960
4002
  onClick: handleExpose,
3961
4003
  disabled: !newPort || isExposing,
3962
- className: "inline-flex items-center gap-2 rounded-lg bg-primary px-4 py-2 text-sm font-semibold text-primary-foreground shadow-sm transition-colors hover:bg-primary/90 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-not-allowed disabled:bg-primary/55 disabled:text-primary-foreground/90 disabled:shadow-none",
4004
+ className: `inline-flex items-center gap-2 rounded-lg bg-primary px-4 py-2 text-sm font-semibold text-primary-foreground shadow-sm transition-colors hover:bg-primary/90 disabled:cursor-not-allowed disabled:bg-primary/55 disabled:text-primary-foreground/90 disabled:shadow-none ${focusRing5}`,
3963
4005
  children: [
3964
4006
  /* @__PURE__ */ jsx25(Plus4, { className: "h-4 w-4" }),
3965
4007
  "Expose"
@@ -3973,6 +4015,7 @@ function PortsList({ ports, onExposePort, onRemovePort, isExposing = false, clas
3973
4015
  // src/dashboard/process-list.tsx
3974
4016
  import * as React14 from "react";
3975
4017
  import { Activity as Activity3, Plus as Plus5, Skull, Terminal as Terminal4 } from "lucide-react";
4018
+ import { focusField as focusField2 } from "@tangle-network/ui/utils";
3976
4019
  import { jsx as jsx26, jsxs as jsxs23 } from "react/jsx-runtime";
3977
4020
  function formatUptime(startedAt) {
3978
4021
  if (!startedAt) return "-";
@@ -4035,7 +4078,7 @@ function ProcessList({ processes, onSpawn, onKill, loading = false, className })
4035
4078
  value: newCommand,
4036
4079
  onChange: (e) => setNewCommand(e.target.value),
4037
4080
  onKeyDown: (e) => e.key === "Enter" && handleSpawn(),
4038
- className: "flex-1 rounded-lg border border-[var(--md3-outline-variant)] bg-surface-container-low 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"
4081
+ className: `flex-1 rounded-lg border bg-surface-container-low px-3 py-2 text-sm font-mono text-foreground placeholder:text-muted-foreground ${focusField2}`
4039
4082
  }
4040
4083
  ),
4041
4084
  /* @__PURE__ */ jsxs23(
@@ -4058,6 +4101,7 @@ function ProcessList({ processes, onSpawn, onKill, loading = false, className })
4058
4101
  // src/dashboard/network-config.tsx
4059
4102
  import * as React15 from "react";
4060
4103
  import { Network as Network2, Plus as Plus6, Trash2 as Trash24, ShieldAlert } from "lucide-react";
4104
+ import { focusField as focusField3 } from "@tangle-network/ui/utils";
4061
4105
  import { jsx as jsx27, jsxs as jsxs24 } from "react/jsx-runtime";
4062
4106
  function NetworkConfig({ config, onUpdate, loading = false, className }) {
4063
4107
  const [newCidr, setNewCidr] = React15.useState("");
@@ -4142,7 +4186,7 @@ function NetworkConfig({ config, onUpdate, loading = false, className }) {
4142
4186
  value: newCidr,
4143
4187
  onChange: (e) => setNewCidr(e.target.value),
4144
4188
  onKeyDown: (e) => e.key === "Enter" && handleAddCidr(),
4145
- className: "flex-1 rounded-lg border border-[var(--md3-outline-variant)] bg-surface-container-low 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"
4189
+ className: `flex-1 rounded-lg border bg-surface-container-low px-3 py-2 text-sm font-mono text-foreground placeholder:text-muted-foreground ${focusField3}`
4146
4190
  }
4147
4191
  ),
4148
4192
  /* @__PURE__ */ jsxs24(
@@ -4166,7 +4210,8 @@ function NetworkConfig({ config, onUpdate, loading = false, className }) {
4166
4210
  // src/dashboard/backend-config.tsx
4167
4211
  import * as React16 from "react";
4168
4212
  import { Bot as Bot2, Plus as Plus7, Trash2 as Trash25, Server, Wrench } from "lucide-react";
4169
- import { Fragment as Fragment13, jsx as jsx28, jsxs as jsxs25 } from "react/jsx-runtime";
4213
+ import { focusField as focusField4 } from "@tangle-network/ui/utils";
4214
+ import { Fragment as Fragment14, jsx as jsx28, jsxs as jsxs25 } from "react/jsx-runtime";
4170
4215
  function BackendConfig({
4171
4216
  status,
4172
4217
  mcpServers,
@@ -4223,7 +4268,7 @@ function BackendConfig({
4223
4268
  ), children: status.running ? "Running" : "Stopped" }) }),
4224
4269
  /* @__PURE__ */ jsx28("dt", { className: "text-muted-foreground", children: "Model" }),
4225
4270
  /* @__PURE__ */ jsx28("dd", { className: "font-mono text-xs", children: status.model ?? "Default" }),
4226
- status.provider && /* @__PURE__ */ jsxs25(Fragment13, { children: [
4271
+ status.provider && /* @__PURE__ */ jsxs25(Fragment14, { children: [
4227
4272
  /* @__PURE__ */ jsx28("dt", { className: "text-muted-foreground", children: "Provider" }),
4228
4273
  /* @__PURE__ */ jsx28("dd", { className: "font-mono text-xs", children: status.provider })
4229
4274
  ] })
@@ -4284,7 +4329,7 @@ function BackendConfig({
4284
4329
  placeholder: "Server name",
4285
4330
  value: mcpName,
4286
4331
  onChange: (e) => setMcpName(e.target.value),
4287
- className: "w-full rounded-lg border border-[var(--md3-outline-variant)] bg-surface-container-low px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground focus:outline-none focus-visible:ring-1 focus-visible:ring-ring"
4332
+ className: `w-full rounded-lg border bg-surface-container-low px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground ${focusField4}`
4288
4333
  }
4289
4334
  ),
4290
4335
  /* @__PURE__ */ jsx28(
@@ -4294,7 +4339,7 @@ function BackendConfig({
4294
4339
  placeholder: "Command (e.g. npx @server/mcp)",
4295
4340
  value: mcpCommand,
4296
4341
  onChange: (e) => setMcpCommand(e.target.value),
4297
- className: "w-full rounded-lg border border-[var(--md3-outline-variant)] bg-surface-container-low 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"
4342
+ className: `w-full rounded-lg border bg-surface-container-low px-3 py-2 text-sm font-mono text-foreground placeholder:text-muted-foreground ${focusField4}`
4298
4343
  }
4299
4344
  ),
4300
4345
  /* @__PURE__ */ jsx28(
@@ -4304,7 +4349,7 @@ function BackendConfig({
4304
4349
  placeholder: "Arguments (space-separated, optional)",
4305
4350
  value: mcpArgs,
4306
4351
  onChange: (e) => setMcpArgs(e.target.value),
4307
- className: "w-full rounded-lg border border-[var(--md3-outline-variant)] bg-surface-container-low 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"
4352
+ className: `w-full rounded-lg border bg-surface-container-low px-3 py-2 text-sm font-mono text-foreground placeholder:text-muted-foreground ${focusField4}`
4308
4353
  }
4309
4354
  ),
4310
4355
  /* @__PURE__ */ jsxs25("div", { className: "flex justify-end gap-2 pt-1", children: [
@@ -4336,6 +4381,7 @@ function BackendConfig({
4336
4381
  // src/dashboard/snapshot-list.tsx
4337
4382
  import * as React17 from "react";
4338
4383
  import { Camera, Clock as Clock5, HardDrive as HardDrive2, Plus as Plus8, RotateCcw } from "lucide-react";
4384
+ import { focusField as focusField5 } from "@tangle-network/ui/utils";
4339
4385
  import { jsx as jsx29, jsxs as jsxs26 } from "react/jsx-runtime";
4340
4386
  function formatBytes(bytes) {
4341
4387
  if (bytes == null || bytes < 0) return "-";
@@ -4385,7 +4431,7 @@ function SnapshotList({ snapshots, onCreate, onRestore, onSaveAsTemplate, loadin
4385
4431
  value: tags,
4386
4432
  onChange: (e) => setTags(e.target.value),
4387
4433
  onKeyDown: (e) => e.key === "Enter" && handleCreate(),
4388
- className: "w-full rounded-lg border border-[var(--md3-outline-variant)] bg-surface-container-low px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground focus:outline-none focus-visible:ring-1 focus-visible:ring-ring"
4434
+ className: `w-full rounded-lg border bg-surface-container-low px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground ${focusField5}`
4389
4435
  }
4390
4436
  ),
4391
4437
  /* @__PURE__ */ jsxs26("div", { className: "flex justify-end gap-2", children: [
@@ -4469,7 +4515,7 @@ function SnapshotList({ snapshots, onCreate, onRestore, onSaveAsTemplate, loadin
4469
4515
  }
4470
4516
 
4471
4517
  // src/dashboard/promo-banner.tsx
4472
- import { Fragment as Fragment14, jsx as jsx30, jsxs as jsxs27 } from "react/jsx-runtime";
4518
+ import { Fragment as Fragment15, jsx as jsx30, jsxs as jsxs27 } from "react/jsx-runtime";
4473
4519
  function PromoBanner({
4474
4520
  title,
4475
4521
  description,
@@ -4484,7 +4530,7 @@ function PromoBanner({
4484
4530
  "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",
4485
4531
  disabled ? "opacity-50 cursor-not-allowed" : "hover:bg-[var(--btn-primary-hover)]"
4486
4532
  );
4487
- const buttonContent = /* @__PURE__ */ jsxs27(Fragment14, { children: [
4533
+ const buttonContent = /* @__PURE__ */ jsxs27(Fragment15, { children: [
4488
4534
  buttonLabel,
4489
4535
  /* @__PURE__ */ jsxs27("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: [
4490
4536
  /* @__PURE__ */ jsx30("path", { d: "M5 12h14" }),