@tangle-network/sandbox-ui 0.16.1 → 0.16.3
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/{chunk-X3UATIZH.js → chunk-5I363RL7.js} +176 -75
- package/dist/dashboard.d.ts +7 -1
- package/dist/dashboard.js +1 -1
- package/dist/globals.css +6 -0
- package/dist/index.js +1 -1
- package/dist/pages.d.ts +16 -2
- package/dist/pages.js +129 -63
- package/dist/styles.css +6 -0
- package/package.json +1 -1
|
@@ -666,8 +666,34 @@ function NewSandboxCard({ onClick, className }) {
|
|
|
666
666
|
}
|
|
667
667
|
|
|
668
668
|
// src/dashboard/sandbox-table.tsx
|
|
669
|
-
import
|
|
670
|
-
import {
|
|
669
|
+
import * as React3 from "react";
|
|
670
|
+
import {
|
|
671
|
+
Activity as Activity2,
|
|
672
|
+
BarChart2 as BarChart22,
|
|
673
|
+
ChevronLeft,
|
|
674
|
+
ChevronRight,
|
|
675
|
+
Clock as Clock2,
|
|
676
|
+
Code2 as Code22,
|
|
677
|
+
Copy as Copy2,
|
|
678
|
+
ExternalLink,
|
|
679
|
+
Key,
|
|
680
|
+
MoreVertical as MoreVertical2,
|
|
681
|
+
Play as Play2,
|
|
682
|
+
PowerOff as PowerOff2,
|
|
683
|
+
RefreshCw,
|
|
684
|
+
Terminal as Terminal2,
|
|
685
|
+
Trash2 as Trash22,
|
|
686
|
+
User,
|
|
687
|
+
Users as Users2
|
|
688
|
+
} from "lucide-react";
|
|
689
|
+
import {
|
|
690
|
+
DropdownMenu as DropdownMenu3,
|
|
691
|
+
DropdownMenuContent as DropdownMenuContent3,
|
|
692
|
+
DropdownMenuItem as DropdownMenuItem3,
|
|
693
|
+
DropdownMenuSeparator as DropdownMenuSeparator3,
|
|
694
|
+
DropdownMenuTrigger as DropdownMenuTrigger3
|
|
695
|
+
} from "@tangle-network/ui/primitives";
|
|
696
|
+
import { Fragment as Fragment5, jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
671
697
|
var statusColors = {
|
|
672
698
|
running: { dot: "bg-[var(--code-success)] animate-pulse", text: "text-[var(--code-success)]", bar: "bg-[var(--code-success)]" },
|
|
673
699
|
hibernating: { dot: "bg-muted-foreground", text: "text-muted-foreground", bar: "bg-muted-foreground" },
|
|
@@ -705,6 +731,11 @@ function SandboxTable({
|
|
|
705
731
|
onWake,
|
|
706
732
|
onMore,
|
|
707
733
|
onDelete,
|
|
734
|
+
onStop,
|
|
735
|
+
onKeepAlive,
|
|
736
|
+
onUsage,
|
|
737
|
+
onHealth,
|
|
738
|
+
onFork,
|
|
708
739
|
className
|
|
709
740
|
}) {
|
|
710
741
|
const totalCount = total ?? sandboxes.length;
|
|
@@ -812,7 +843,7 @@ function SandboxTable({
|
|
|
812
843
|
/* @__PURE__ */ jsx7(MiniMeter, { label: "RAM", percent: 0 })
|
|
813
844
|
] }) : null }),
|
|
814
845
|
/* @__PURE__ */ jsx7("td", { className: "px-6 py-5 text-right", children: /* @__PURE__ */ jsxs6("div", { className: "flex items-center justify-end gap-1", children: [
|
|
815
|
-
isActive && /* @__PURE__ */ jsxs6(
|
|
846
|
+
isActive && /* @__PURE__ */ jsxs6(Fragment5, { children: [
|
|
816
847
|
/* @__PURE__ */ jsx7("button", { type: "button", onClick: (e) => {
|
|
817
848
|
stopRowClick(e);
|
|
818
849
|
onOpenIDE?.(sb.id);
|
|
@@ -842,10 +873,80 @@ function SandboxTable({
|
|
|
842
873
|
]
|
|
843
874
|
}
|
|
844
875
|
),
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
876
|
+
(() => {
|
|
877
|
+
const runItem = (handler) => (e) => {
|
|
878
|
+
e.stopPropagation();
|
|
879
|
+
handler(sb.id);
|
|
880
|
+
};
|
|
881
|
+
const overflowSections = [];
|
|
882
|
+
if (isActive) {
|
|
883
|
+
const lifecycle = [];
|
|
884
|
+
if (onStop) lifecycle.push(
|
|
885
|
+
/* @__PURE__ */ jsxs6(DropdownMenuItem3, { onClick: runItem(onStop), children: [
|
|
886
|
+
/* @__PURE__ */ jsx7(PowerOff2, { className: "mr-2 h-4 w-4" }),
|
|
887
|
+
" Stop Sandbox"
|
|
888
|
+
] }, "stop")
|
|
889
|
+
);
|
|
890
|
+
if (onKeepAlive) lifecycle.push(
|
|
891
|
+
/* @__PURE__ */ jsxs6(DropdownMenuItem3, { onClick: runItem(onKeepAlive), children: [
|
|
892
|
+
/* @__PURE__ */ jsx7(Clock2, { className: "mr-2 h-4 w-4" }),
|
|
893
|
+
" Keep Alive"
|
|
894
|
+
] }, "keep-alive")
|
|
895
|
+
);
|
|
896
|
+
if (lifecycle.length) overflowSections.push(lifecycle);
|
|
897
|
+
const observability = [];
|
|
898
|
+
if (onUsage) observability.push(
|
|
899
|
+
/* @__PURE__ */ jsxs6(DropdownMenuItem3, { onClick: runItem(onUsage), children: [
|
|
900
|
+
/* @__PURE__ */ jsx7(BarChart22, { className: "mr-2 h-4 w-4" }),
|
|
901
|
+
" View Usage"
|
|
902
|
+
] }, "usage")
|
|
903
|
+
);
|
|
904
|
+
if (onHealth) observability.push(
|
|
905
|
+
/* @__PURE__ */ jsxs6(DropdownMenuItem3, { onClick: runItem(onHealth), children: [
|
|
906
|
+
/* @__PURE__ */ jsx7(Activity2, { className: "mr-2 h-4 w-4" }),
|
|
907
|
+
" Health Check"
|
|
908
|
+
] }, "health")
|
|
909
|
+
);
|
|
910
|
+
if (observability.length) overflowSections.push(observability);
|
|
911
|
+
if (onFork) overflowSections.push([
|
|
912
|
+
/* @__PURE__ */ jsxs6(DropdownMenuItem3, { onClick: runItem(onFork), children: [
|
|
913
|
+
/* @__PURE__ */ jsx7(Copy2, { className: "mr-2 h-4 w-4" }),
|
|
914
|
+
" Fork Sandbox"
|
|
915
|
+
] }, "fork")
|
|
916
|
+
]);
|
|
917
|
+
} else if (isResumable(sb.status)) {
|
|
918
|
+
if (onFork) overflowSections.push([
|
|
919
|
+
/* @__PURE__ */ jsxs6(DropdownMenuItem3, { onClick: runItem(onFork), children: [
|
|
920
|
+
/* @__PURE__ */ jsx7(Copy2, { className: "mr-2 h-4 w-4" }),
|
|
921
|
+
" Fork Sandbox"
|
|
922
|
+
] }, "fork")
|
|
923
|
+
]);
|
|
924
|
+
}
|
|
925
|
+
if (onMore) overflowSections.push([
|
|
926
|
+
/* @__PURE__ */ jsxs6(DropdownMenuItem3, { onClick: runItem(onMore), children: [
|
|
927
|
+
/* @__PURE__ */ jsx7(ExternalLink, { className: "mr-2 h-4 w-4" }),
|
|
928
|
+
" View Details"
|
|
929
|
+
] }, "view-details")
|
|
930
|
+
]);
|
|
931
|
+
if (overflowSections.length === 0) return null;
|
|
932
|
+
return /* @__PURE__ */ jsxs6(DropdownMenu3, { children: [
|
|
933
|
+
/* @__PURE__ */ jsx7(DropdownMenuTrigger3, { asChild: true, children: /* @__PURE__ */ jsx7(
|
|
934
|
+
"button",
|
|
935
|
+
{
|
|
936
|
+
type: "button",
|
|
937
|
+
onClick: stopRowClick,
|
|
938
|
+
className: "p-2 rounded-lg hover:bg-muted text-muted-foreground hover:text-foreground transition-all active:scale-90 outline-none",
|
|
939
|
+
"aria-label": "More actions",
|
|
940
|
+
title: "More actions",
|
|
941
|
+
children: /* @__PURE__ */ jsx7(MoreVertical2, { className: "h-4 w-4" })
|
|
942
|
+
}
|
|
943
|
+
) }),
|
|
944
|
+
/* @__PURE__ */ jsx7(DropdownMenuContent3, { align: "end", className: "min-w-[180px]", children: overflowSections.map((section, sectionIdx) => /* @__PURE__ */ jsxs6(React3.Fragment, { children: [
|
|
945
|
+
sectionIdx > 0 && /* @__PURE__ */ jsx7(DropdownMenuSeparator3, {}),
|
|
946
|
+
section
|
|
947
|
+
] }, sectionIdx)) })
|
|
948
|
+
] });
|
|
949
|
+
})(),
|
|
849
950
|
onDelete && canAdminSandbox(sb) && /* @__PURE__ */ jsx7("button", { type: "button", onClick: (e) => {
|
|
850
951
|
stopRowClick(e);
|
|
851
952
|
onDelete(sb.id);
|
|
@@ -1115,9 +1216,9 @@ function HarnessPicker({
|
|
|
1115
1216
|
}
|
|
1116
1217
|
|
|
1117
1218
|
// src/dashboard/dashboard-layout.tsx
|
|
1118
|
-
import * as
|
|
1219
|
+
import * as React4 from "react";
|
|
1119
1220
|
import { Plus as Plus2, Bell } from "lucide-react";
|
|
1120
|
-
import { Fragment as
|
|
1221
|
+
import { Fragment as Fragment7, jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1121
1222
|
function SettingsIconSmall({ className }) {
|
|
1122
1223
|
return /* @__PURE__ */ jsxs10("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: [
|
|
1123
1224
|
/* @__PURE__ */ jsx12("title", { children: "Settings" }),
|
|
@@ -1178,10 +1279,10 @@ function DashboardLayoutInner({
|
|
|
1178
1279
|
notifications: notifData
|
|
1179
1280
|
}) {
|
|
1180
1281
|
const Link = LinkComponent;
|
|
1181
|
-
const [mobileMenuOpen, setMobileMenuOpen] =
|
|
1182
|
-
const [notificationsOpen, setNotificationsOpen] =
|
|
1183
|
-
const notifRef =
|
|
1184
|
-
|
|
1282
|
+
const [mobileMenuOpen, setMobileMenuOpen] = React4.useState(false);
|
|
1283
|
+
const [notificationsOpen, setNotificationsOpen] = React4.useState(false);
|
|
1284
|
+
const notifRef = React4.useRef(null);
|
|
1285
|
+
React4.useEffect(() => {
|
|
1185
1286
|
if (!notificationsOpen) return;
|
|
1186
1287
|
const handler = (e) => {
|
|
1187
1288
|
if (notifRef.current && !notifRef.current.contains(e.target)) {
|
|
@@ -1199,21 +1300,21 @@ function DashboardLayoutInner({
|
|
|
1199
1300
|
};
|
|
1200
1301
|
}, [notificationsOpen]);
|
|
1201
1302
|
const { contentMargin, hidden, mode, hasPanels, panelOpen } = useSidebar();
|
|
1202
|
-
const modeSet =
|
|
1203
|
-
const sidebarUser =
|
|
1303
|
+
const modeSet = React4.useMemo(() => new Set(modeItems), [modeItems]);
|
|
1304
|
+
const sidebarUser = React4.useMemo(
|
|
1204
1305
|
() => user ? { email: user.email, name: user.name, tier: user.tier, avatarUrl: user.avatarUrl } : void 0,
|
|
1205
1306
|
[user?.email, user?.name, user?.tier, user?.avatarUrl]
|
|
1206
1307
|
);
|
|
1207
1308
|
const activePanel = panels.find((p) => p.mode === mode);
|
|
1208
|
-
const buildSidebarContent =
|
|
1209
|
-
(showLabels) => /* @__PURE__ */ jsxs10(
|
|
1309
|
+
const buildSidebarContent = React4.useCallback(
|
|
1310
|
+
(showLabels) => /* @__PURE__ */ jsxs10(Fragment7, { children: [
|
|
1210
1311
|
/* @__PURE__ */ jsxs10(SidebarRail, { wide: showLabels, children: [
|
|
1211
1312
|
/* @__PURE__ */ jsx12(SidebarRailHeader, { children: /* @__PURE__ */ jsx12(Link, { href: "/", to: "/", className: "p-1 rounded-md transition-colors hover:bg-muted/50", children: /* @__PURE__ */ jsx12(Logo, { variant, size: "sm", iconOnly: true }) }) }),
|
|
1212
1313
|
/* @__PURE__ */ jsx12(SidebarRailNav, { children: navItems.map((item, i) => {
|
|
1213
1314
|
const isMode = modeSet.has(item.id);
|
|
1214
1315
|
const prevIsMode = i > 0 && modeSet.has(navItems[i - 1].id);
|
|
1215
1316
|
const showSep = i > 0 && isMode && !prevIsMode;
|
|
1216
|
-
return /* @__PURE__ */ jsxs10(
|
|
1317
|
+
return /* @__PURE__ */ jsxs10(React4.Fragment, { children: [
|
|
1217
1318
|
showSep && /* @__PURE__ */ jsx12(RailSeparator, {}),
|
|
1218
1319
|
isMode ? /* @__PURE__ */ jsx12(
|
|
1219
1320
|
RailModeButton,
|
|
@@ -1278,8 +1379,8 @@ function DashboardLayoutInner({
|
|
|
1278
1379
|
mode
|
|
1279
1380
|
]
|
|
1280
1381
|
);
|
|
1281
|
-
const sidebarContent =
|
|
1282
|
-
const mobileSidebarContent =
|
|
1382
|
+
const sidebarContent = React4.useMemo(() => buildSidebarContent(false), [buildSidebarContent]);
|
|
1383
|
+
const mobileSidebarContent = React4.useMemo(() => buildSidebarContent(true), [buildSidebarContent]);
|
|
1283
1384
|
return /* @__PURE__ */ jsxs10("div", { className: cn("min-h-screen bg-background text-foreground", className), children: [
|
|
1284
1385
|
/* @__PURE__ */ jsxs10(
|
|
1285
1386
|
"nav",
|
|
@@ -1417,14 +1518,14 @@ import { Check as Check2, ChevronDown as ChevronDown2, Plus as Plus3, Settings }
|
|
|
1417
1518
|
import { Button } from "@tangle-network/ui/primitives";
|
|
1418
1519
|
import { Badge } from "@tangle-network/ui/primitives";
|
|
1419
1520
|
import {
|
|
1420
|
-
DropdownMenu as
|
|
1421
|
-
DropdownMenuContent as
|
|
1422
|
-
DropdownMenuItem as
|
|
1521
|
+
DropdownMenu as DropdownMenu4,
|
|
1522
|
+
DropdownMenuContent as DropdownMenuContent4,
|
|
1523
|
+
DropdownMenuItem as DropdownMenuItem4,
|
|
1423
1524
|
DropdownMenuLabel as DropdownMenuLabel2,
|
|
1424
|
-
DropdownMenuSeparator as
|
|
1425
|
-
DropdownMenuTrigger as
|
|
1525
|
+
DropdownMenuSeparator as DropdownMenuSeparator4,
|
|
1526
|
+
DropdownMenuTrigger as DropdownMenuTrigger4
|
|
1426
1527
|
} from "@tangle-network/ui/primitives";
|
|
1427
|
-
import { Fragment as
|
|
1528
|
+
import { Fragment as Fragment8, jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
1428
1529
|
function ProfileSelector({
|
|
1429
1530
|
profiles,
|
|
1430
1531
|
selectedId,
|
|
@@ -1441,14 +1542,14 @@ function ProfileSelector({
|
|
|
1441
1542
|
const customProfiles = profiles.filter((p) => !p.is_builtin);
|
|
1442
1543
|
return /* @__PURE__ */ jsxs11("div", { className, children: [
|
|
1443
1544
|
label && /* @__PURE__ */ jsx13("label", { className: "mb-2 block font-medium text-sm", children: label }),
|
|
1444
|
-
/* @__PURE__ */ jsxs11(
|
|
1445
|
-
/* @__PURE__ */ jsx13(
|
|
1545
|
+
/* @__PURE__ */ jsxs11(DropdownMenu4, { children: [
|
|
1546
|
+
/* @__PURE__ */ jsx13(DropdownMenuTrigger4, { asChild: true, children: /* @__PURE__ */ jsxs11(Button, { variant: "outline", className: "w-full justify-between", children: [
|
|
1446
1547
|
/* @__PURE__ */ jsx13("span", { className: "truncate", children: selected ? selected.name : placeholder }),
|
|
1447
1548
|
/* @__PURE__ */ jsx13(ChevronDown2, { className: "ml-2 h-4 w-4 shrink-0 opacity-50" })
|
|
1448
1549
|
] }) }),
|
|
1449
|
-
/* @__PURE__ */ jsxs11(
|
|
1550
|
+
/* @__PURE__ */ jsxs11(DropdownMenuContent4, { className: "w-[300px]", align: "start", children: [
|
|
1450
1551
|
/* @__PURE__ */ jsxs11(
|
|
1451
|
-
|
|
1552
|
+
DropdownMenuItem4,
|
|
1452
1553
|
{
|
|
1453
1554
|
onClick: () => onSelect(null),
|
|
1454
1555
|
className: "flex items-center justify-between",
|
|
@@ -1458,11 +1559,11 @@ function ProfileSelector({
|
|
|
1458
1559
|
]
|
|
1459
1560
|
}
|
|
1460
1561
|
),
|
|
1461
|
-
builtinProfiles.length > 0 && /* @__PURE__ */ jsxs11(
|
|
1462
|
-
/* @__PURE__ */ jsx13(
|
|
1562
|
+
builtinProfiles.length > 0 && /* @__PURE__ */ jsxs11(Fragment8, { children: [
|
|
1563
|
+
/* @__PURE__ */ jsx13(DropdownMenuSeparator4, {}),
|
|
1463
1564
|
/* @__PURE__ */ jsx13(DropdownMenuLabel2, { children: "Built-in Profiles" }),
|
|
1464
1565
|
builtinProfiles.map((profile) => /* @__PURE__ */ jsxs11(
|
|
1465
|
-
|
|
1566
|
+
DropdownMenuItem4,
|
|
1466
1567
|
{
|
|
1467
1568
|
onClick: () => onSelect(profile),
|
|
1468
1569
|
className: "flex flex-col items-start gap-1",
|
|
@@ -1483,11 +1584,11 @@ function ProfileSelector({
|
|
|
1483
1584
|
profile.id
|
|
1484
1585
|
))
|
|
1485
1586
|
] }),
|
|
1486
|
-
customProfiles.length > 0 && /* @__PURE__ */ jsxs11(
|
|
1487
|
-
/* @__PURE__ */ jsx13(
|
|
1587
|
+
customProfiles.length > 0 && /* @__PURE__ */ jsxs11(Fragment8, { children: [
|
|
1588
|
+
/* @__PURE__ */ jsx13(DropdownMenuSeparator4, {}),
|
|
1488
1589
|
/* @__PURE__ */ jsx13(DropdownMenuLabel2, { children: "Custom Profiles" }),
|
|
1489
1590
|
customProfiles.map((profile) => /* @__PURE__ */ jsxs11(
|
|
1490
|
-
|
|
1591
|
+
DropdownMenuItem4,
|
|
1491
1592
|
{
|
|
1492
1593
|
onClick: () => onSelect(profile),
|
|
1493
1594
|
className: "flex flex-col items-start gap-1",
|
|
@@ -1520,10 +1621,10 @@ function ProfileSelector({
|
|
|
1520
1621
|
profile.id
|
|
1521
1622
|
))
|
|
1522
1623
|
] }),
|
|
1523
|
-
(onCreateClick || onManageClick) && /* @__PURE__ */ jsxs11(
|
|
1524
|
-
/* @__PURE__ */ jsx13(
|
|
1624
|
+
(onCreateClick || onManageClick) && /* @__PURE__ */ jsxs11(Fragment8, { children: [
|
|
1625
|
+
/* @__PURE__ */ jsx13(DropdownMenuSeparator4, {}),
|
|
1525
1626
|
onCreateClick && /* @__PURE__ */ jsxs11(
|
|
1526
|
-
|
|
1627
|
+
DropdownMenuItem4,
|
|
1527
1628
|
{
|
|
1528
1629
|
onClick: onCreateClick,
|
|
1529
1630
|
className: "text-[var(--surface-info-text)]",
|
|
@@ -1534,7 +1635,7 @@ function ProfileSelector({
|
|
|
1534
1635
|
}
|
|
1535
1636
|
),
|
|
1536
1637
|
onManageClick && /* @__PURE__ */ jsxs11(
|
|
1537
|
-
|
|
1638
|
+
DropdownMenuItem4,
|
|
1538
1639
|
{
|
|
1539
1640
|
onClick: onManageClick,
|
|
1540
1641
|
className: "text-muted-foreground",
|
|
@@ -1618,8 +1719,8 @@ function ProfileComparison({
|
|
|
1618
1719
|
import {
|
|
1619
1720
|
Check as Check3,
|
|
1620
1721
|
CheckCircle2,
|
|
1621
|
-
Clock as
|
|
1622
|
-
ExternalLink,
|
|
1722
|
+
Clock as Clock3,
|
|
1723
|
+
ExternalLink as ExternalLink2,
|
|
1623
1724
|
Loader2,
|
|
1624
1725
|
Timer,
|
|
1625
1726
|
X,
|
|
@@ -1627,10 +1728,10 @@ import {
|
|
|
1627
1728
|
} from "lucide-react";
|
|
1628
1729
|
import { Button as Button2 } from "@tangle-network/ui/primitives";
|
|
1629
1730
|
import { Badge as Badge2 } from "@tangle-network/ui/primitives";
|
|
1630
|
-
import { Fragment as
|
|
1731
|
+
import { Fragment as Fragment9, jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
1631
1732
|
var statusConfig = {
|
|
1632
1733
|
pending: {
|
|
1633
|
-
icon:
|
|
1734
|
+
icon: Clock3,
|
|
1634
1735
|
color: "text-[var(--surface-warning-text)]",
|
|
1635
1736
|
bg: "bg-[var(--surface-warning-bg)]",
|
|
1636
1737
|
border: "border-[var(--surface-warning-border)]",
|
|
@@ -1750,7 +1851,7 @@ function VariantList({
|
|
|
1750
1851
|
children: outcomeConfig[variant.outcome].label
|
|
1751
1852
|
}
|
|
1752
1853
|
),
|
|
1753
|
-
variant.status === "completed" && variant.outcome === "pending_review" && onAccept && onReject && /* @__PURE__ */ jsxs12(
|
|
1854
|
+
variant.status === "completed" && variant.outcome === "pending_review" && onAccept && onReject && /* @__PURE__ */ jsxs12(Fragment9, { children: [
|
|
1754
1855
|
/* @__PURE__ */ jsxs12(
|
|
1755
1856
|
Button2,
|
|
1756
1857
|
{
|
|
@@ -1796,7 +1897,7 @@ function VariantList({
|
|
|
1796
1897
|
e.stopPropagation();
|
|
1797
1898
|
window.open(variant.detailsUrl, "_blank");
|
|
1798
1899
|
},
|
|
1799
|
-
children: /* @__PURE__ */ jsx14(
|
|
1900
|
+
children: /* @__PURE__ */ jsx14(ExternalLink2, { className: "h-3.5 w-3.5" })
|
|
1800
1901
|
}
|
|
1801
1902
|
)
|
|
1802
1903
|
] })
|
|
@@ -1922,7 +2023,7 @@ function SystemLogsViewer({ apiUrl, token, className }) {
|
|
|
1922
2023
|
}
|
|
1923
2024
|
|
|
1924
2025
|
// src/dashboard/usage-summary.tsx
|
|
1925
|
-
import { Clock as
|
|
2026
|
+
import { Clock as Clock4, Layers, MessageSquare, DollarSign } from "lucide-react";
|
|
1926
2027
|
import { StatCard } from "@tangle-network/ui/primitives";
|
|
1927
2028
|
import { Skeleton as Skeleton2 } from "@tangle-network/ui/primitives";
|
|
1928
2029
|
import { jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
@@ -1938,7 +2039,7 @@ function UsageSummary({ data, loading = false, className }) {
|
|
|
1938
2039
|
title: "Compute Hours",
|
|
1939
2040
|
value: data.computeHours.toFixed(1),
|
|
1940
2041
|
subtitle: "This billing period",
|
|
1941
|
-
icon: /* @__PURE__ */ jsx16(
|
|
2042
|
+
icon: /* @__PURE__ */ jsx16(Clock4, { className: "h-5 w-5" })
|
|
1942
2043
|
}
|
|
1943
2044
|
),
|
|
1944
2045
|
/* @__PURE__ */ jsx16(
|
|
@@ -2045,14 +2146,14 @@ function GitPanel({ status, log, loading = false, onRefresh, className }) {
|
|
|
2045
2146
|
}
|
|
2046
2147
|
|
|
2047
2148
|
// src/dashboard/ports-list.tsx
|
|
2048
|
-
import * as
|
|
2049
|
-
import { Copy as
|
|
2149
|
+
import * as React6 from "react";
|
|
2150
|
+
import { Copy as Copy3, Check as Check4, Globe, Plus as Plus4, Trash2 as Trash23 } from "lucide-react";
|
|
2050
2151
|
import { jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
2051
2152
|
function PortsList({ ports, onExposePort, onRemovePort, isExposing = false, className }) {
|
|
2052
|
-
const [newPort, setNewPort] =
|
|
2053
|
-
const [copiedPort, setCopiedPort] =
|
|
2054
|
-
const copyTimerRef =
|
|
2055
|
-
|
|
2153
|
+
const [newPort, setNewPort] = React6.useState("");
|
|
2154
|
+
const [copiedPort, setCopiedPort] = React6.useState(null);
|
|
2155
|
+
const copyTimerRef = React6.useRef(null);
|
|
2156
|
+
React6.useEffect(() => {
|
|
2056
2157
|
return () => {
|
|
2057
2158
|
if (copyTimerRef.current) clearTimeout(copyTimerRef.current);
|
|
2058
2159
|
};
|
|
@@ -2092,7 +2193,7 @@ function PortsList({ ports, onExposePort, onRemovePort, isExposing = false, clas
|
|
|
2092
2193
|
className: "flex items-center gap-2 font-mono text-xs text-primary hover:underline cursor-pointer group",
|
|
2093
2194
|
children: [
|
|
2094
2195
|
/* @__PURE__ */ jsx18("span", { className: "truncate max-w-[300px]", children: p.url }),
|
|
2095
|
-
copiedPort === p.port ? /* @__PURE__ */ jsx18(Check4, { className: "h-3 w-3 text-[var(--surface-success-text)] shrink-0" }) : /* @__PURE__ */ jsx18(
|
|
2196
|
+
copiedPort === p.port ? /* @__PURE__ */ jsx18(Check4, { className: "h-3 w-3 text-[var(--surface-success-text)] shrink-0" }) : /* @__PURE__ */ jsx18(Copy3, { className: "h-3 w-3 opacity-0 group-hover:opacity-100 transition-opacity shrink-0" })
|
|
2096
2197
|
]
|
|
2097
2198
|
}
|
|
2098
2199
|
) }),
|
|
@@ -2146,8 +2247,8 @@ function PortsList({ ports, onExposePort, onRemovePort, isExposing = false, clas
|
|
|
2146
2247
|
}
|
|
2147
2248
|
|
|
2148
2249
|
// src/dashboard/process-list.tsx
|
|
2149
|
-
import * as
|
|
2150
|
-
import { Activity as
|
|
2250
|
+
import * as React7 from "react";
|
|
2251
|
+
import { Activity as Activity3, Plus as Plus5, Skull, Terminal as Terminal4 } from "lucide-react";
|
|
2151
2252
|
import { jsx as jsx19, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
2152
2253
|
function formatUptime(startedAt) {
|
|
2153
2254
|
if (!startedAt) return "-";
|
|
@@ -2158,7 +2259,7 @@ function formatUptime(startedAt) {
|
|
|
2158
2259
|
return `${Math.floor(ms / 36e5)}h ${Math.floor(ms % 36e5 / 6e4)}m`;
|
|
2159
2260
|
}
|
|
2160
2261
|
function ProcessList({ processes, onSpawn, onKill, loading = false, className }) {
|
|
2161
|
-
const [newCommand, setNewCommand] =
|
|
2262
|
+
const [newCommand, setNewCommand] = React7.useState("");
|
|
2162
2263
|
const handleSpawn = () => {
|
|
2163
2264
|
const cmd = newCommand.trim();
|
|
2164
2265
|
if (cmd) {
|
|
@@ -2168,7 +2269,7 @@ function ProcessList({ processes, onSpawn, onKill, loading = false, className })
|
|
|
2168
2269
|
};
|
|
2169
2270
|
return /* @__PURE__ */ jsxs17("div", { className: cn("space-y-4", className), children: [
|
|
2170
2271
|
loading ? /* @__PURE__ */ jsxs17("div", { className: "rounded-lg border border-border bg-muted/20 p-6 text-center", children: [
|
|
2171
|
-
/* @__PURE__ */ jsx19(
|
|
2272
|
+
/* @__PURE__ */ jsx19(Activity3, { className: "mx-auto h-6 w-6 text-muted-foreground animate-spin mb-2" }),
|
|
2172
2273
|
/* @__PURE__ */ jsx19("p", { className: "text-sm text-muted-foreground", children: "Loading processes..." })
|
|
2173
2274
|
] }) : processes.length > 0 ? /* @__PURE__ */ jsx19("div", { className: "rounded-lg border border-border overflow-hidden", children: /* @__PURE__ */ jsxs17("table", { className: "w-full text-sm", children: [
|
|
2174
2275
|
/* @__PURE__ */ jsx19("thead", { className: "bg-muted/30 border-b border-border", children: /* @__PURE__ */ jsxs17("tr", { children: [
|
|
@@ -2231,11 +2332,11 @@ function ProcessList({ processes, onSpawn, onKill, loading = false, className })
|
|
|
2231
2332
|
}
|
|
2232
2333
|
|
|
2233
2334
|
// src/dashboard/network-config.tsx
|
|
2234
|
-
import * as
|
|
2335
|
+
import * as React8 from "react";
|
|
2235
2336
|
import { Network as Network2, Plus as Plus6, Trash2 as Trash24, ShieldAlert } from "lucide-react";
|
|
2236
2337
|
import { jsx as jsx20, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
2237
2338
|
function NetworkConfig({ config, onUpdate, loading = false, className }) {
|
|
2238
|
-
const [newCidr, setNewCidr] =
|
|
2339
|
+
const [newCidr, setNewCidr] = React8.useState("");
|
|
2239
2340
|
const isValidCidr = (value) => {
|
|
2240
2341
|
const match = value.match(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\/(\d{1,2})$/);
|
|
2241
2342
|
if (!match) return false;
|
|
@@ -2339,9 +2440,9 @@ function NetworkConfig({ config, onUpdate, loading = false, className }) {
|
|
|
2339
2440
|
}
|
|
2340
2441
|
|
|
2341
2442
|
// src/dashboard/backend-config.tsx
|
|
2342
|
-
import * as
|
|
2443
|
+
import * as React9 from "react";
|
|
2343
2444
|
import { Bot, Plus as Plus7, RefreshCw as RefreshCw2, Trash2 as Trash25, Server, Wrench } from "lucide-react";
|
|
2344
|
-
import { Fragment as
|
|
2445
|
+
import { Fragment as Fragment10, jsx as jsx21, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
2345
2446
|
function BackendConfig({
|
|
2346
2447
|
status,
|
|
2347
2448
|
mcpServers,
|
|
@@ -2351,10 +2452,10 @@ function BackendConfig({
|
|
|
2351
2452
|
loading = false,
|
|
2352
2453
|
className
|
|
2353
2454
|
}) {
|
|
2354
|
-
const [showAddMcp, setShowAddMcp] =
|
|
2355
|
-
const [mcpName, setMcpName] =
|
|
2356
|
-
const [mcpCommand, setMcpCommand] =
|
|
2357
|
-
const [mcpArgs, setMcpArgs] =
|
|
2455
|
+
const [showAddMcp, setShowAddMcp] = React9.useState(false);
|
|
2456
|
+
const [mcpName, setMcpName] = React9.useState("");
|
|
2457
|
+
const [mcpCommand, setMcpCommand] = React9.useState("");
|
|
2458
|
+
const [mcpArgs, setMcpArgs] = React9.useState("");
|
|
2358
2459
|
const handleAddMcp = () => {
|
|
2359
2460
|
const name = mcpName.trim();
|
|
2360
2461
|
const command = mcpCommand.trim();
|
|
@@ -2401,7 +2502,7 @@ function BackendConfig({
|
|
|
2401
2502
|
), children: status.running ? "Running" : "Stopped" }) }),
|
|
2402
2503
|
/* @__PURE__ */ jsx21("dt", { className: "text-muted-foreground", children: "Model" }),
|
|
2403
2504
|
/* @__PURE__ */ jsx21("dd", { className: "font-mono text-xs", children: status.model ?? "Default" }),
|
|
2404
|
-
status.provider && /* @__PURE__ */ jsxs19(
|
|
2505
|
+
status.provider && /* @__PURE__ */ jsxs19(Fragment10, { children: [
|
|
2405
2506
|
/* @__PURE__ */ jsx21("dt", { className: "text-muted-foreground", children: "Provider" }),
|
|
2406
2507
|
/* @__PURE__ */ jsx21("dd", { className: "font-mono text-xs", children: status.provider })
|
|
2407
2508
|
] })
|
|
@@ -2512,8 +2613,8 @@ function BackendConfig({
|
|
|
2512
2613
|
}
|
|
2513
2614
|
|
|
2514
2615
|
// src/dashboard/snapshot-list.tsx
|
|
2515
|
-
import * as
|
|
2516
|
-
import { Camera, Clock as
|
|
2616
|
+
import * as React10 from "react";
|
|
2617
|
+
import { Camera, Clock as Clock5, HardDrive, Plus as Plus8, RotateCcw } from "lucide-react";
|
|
2517
2618
|
import { jsx as jsx22, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
2518
2619
|
function formatBytes(bytes) {
|
|
2519
2620
|
if (bytes == null || bytes < 0) return "-";
|
|
@@ -2529,8 +2630,8 @@ function formatDate(dateStr) {
|
|
|
2529
2630
|
return d.toLocaleDateString(void 0, { month: "short", day: "numeric", hour: "2-digit", minute: "2-digit" });
|
|
2530
2631
|
}
|
|
2531
2632
|
function SnapshotList({ snapshots, onCreate, onRestore, onSaveAsTemplate, loading = false, className }) {
|
|
2532
|
-
const [showCreate, setShowCreate] =
|
|
2533
|
-
const [tags, setTags] =
|
|
2633
|
+
const [showCreate, setShowCreate] = React10.useState(false);
|
|
2634
|
+
const [tags, setTags] = React10.useState("");
|
|
2534
2635
|
const handleCreate = () => {
|
|
2535
2636
|
const tagList = tags.trim() ? tags.trim().split(",").map((t) => t.trim()).filter(Boolean) : void 0;
|
|
2536
2637
|
onCreate(tagList);
|
|
@@ -2604,7 +2705,7 @@ function SnapshotList({ snapshots, onCreate, onRestore, onSaveAsTemplate, loadin
|
|
|
2604
2705
|
/* @__PURE__ */ jsx22("tbody", { className: "divide-y divide-border", children: snapshots.map((s) => /* @__PURE__ */ jsxs20("tr", { children: [
|
|
2605
2706
|
/* @__PURE__ */ jsx22("td", { className: "px-4 py-3 font-mono text-xs text-foreground", children: s.id.slice(0, 12) }),
|
|
2606
2707
|
/* @__PURE__ */ jsx22("td", { className: "px-4 py-3 text-xs text-muted-foreground", children: /* @__PURE__ */ jsxs20("span", { className: "inline-flex items-center gap-1.5", children: [
|
|
2607
|
-
/* @__PURE__ */ jsx22(
|
|
2708
|
+
/* @__PURE__ */ jsx22(Clock5, { className: "h-3 w-3" }),
|
|
2608
2709
|
formatDate(s.createdAt)
|
|
2609
2710
|
] }) }),
|
|
2610
2711
|
/* @__PURE__ */ jsx22("td", { className: "px-4 py-3 text-xs text-muted-foreground", children: /* @__PURE__ */ jsxs20("span", { className: "inline-flex items-center gap-1.5", children: [
|
|
@@ -2647,7 +2748,7 @@ function SnapshotList({ snapshots, onCreate, onRestore, onSaveAsTemplate, loadin
|
|
|
2647
2748
|
}
|
|
2648
2749
|
|
|
2649
2750
|
// src/dashboard/promo-banner.tsx
|
|
2650
|
-
import { Fragment as
|
|
2751
|
+
import { Fragment as Fragment11, jsx as jsx23, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
2651
2752
|
function PromoBanner({
|
|
2652
2753
|
title,
|
|
2653
2754
|
description,
|
|
@@ -2662,7 +2763,7 @@ function PromoBanner({
|
|
|
2662
2763
|
"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",
|
|
2663
2764
|
disabled ? "opacity-50 cursor-not-allowed" : "hover:bg-[var(--btn-primary-hover)]"
|
|
2664
2765
|
);
|
|
2665
|
-
const buttonContent = /* @__PURE__ */ jsxs21(
|
|
2766
|
+
const buttonContent = /* @__PURE__ */ jsxs21(Fragment11, { children: [
|
|
2666
2767
|
buttonLabel,
|
|
2667
2768
|
/* @__PURE__ */ jsxs21("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: [
|
|
2668
2769
|
/* @__PURE__ */ jsx23("path", { d: "M5 12h14" }),
|
package/dist/dashboard.d.ts
CHANGED
|
@@ -249,10 +249,16 @@ interface SandboxTableProps {
|
|
|
249
249
|
*/
|
|
250
250
|
onWake?: (id: string) => void;
|
|
251
251
|
onMore?: (id: string) => void;
|
|
252
|
+
/** Fired on the user's first click; the caller owns the confirmation step. */
|
|
252
253
|
onDelete?: (id: string) => void;
|
|
254
|
+
onStop?: (id: string) => void;
|
|
255
|
+
onKeepAlive?: (id: string) => void;
|
|
256
|
+
onUsage?: (id: string) => void;
|
|
257
|
+
onHealth?: (id: string) => void;
|
|
258
|
+
onFork?: (id: string) => void;
|
|
253
259
|
className?: string;
|
|
254
260
|
}
|
|
255
|
-
declare function SandboxTable({ sandboxes, page, pageSize, total, onPageChange, onOpenIDE, onOpenTerminal, onSSH, onResume, onWake, onMore, onDelete, className, }: SandboxTableProps): react_jsx_runtime.JSX.Element;
|
|
261
|
+
declare function SandboxTable({ sandboxes, page, pageSize, total, onPageChange, onOpenIDE, onOpenTerminal, onSSH, onResume, onWake, onMore, onDelete, onStop, onKeepAlive, onUsage, onHealth, onFork, className, }: SandboxTableProps): react_jsx_runtime.JSX.Element;
|
|
256
262
|
|
|
257
263
|
interface Invoice {
|
|
258
264
|
id: string;
|
package/dist/dashboard.js
CHANGED
package/dist/globals.css
CHANGED
|
@@ -591,6 +591,9 @@
|
|
|
591
591
|
.h-\[500px\] {
|
|
592
592
|
height: 500px;
|
|
593
593
|
}
|
|
594
|
+
.h-auto {
|
|
595
|
+
height: auto;
|
|
596
|
+
}
|
|
594
597
|
.h-full {
|
|
595
598
|
height: 100%;
|
|
596
599
|
}
|
|
@@ -615,6 +618,9 @@
|
|
|
615
618
|
.min-h-0 {
|
|
616
619
|
min-height: calc(var(--spacing) * 0);
|
|
617
620
|
}
|
|
621
|
+
.min-h-24 {
|
|
622
|
+
min-height: calc(var(--spacing) * 24);
|
|
623
|
+
}
|
|
618
624
|
.min-h-\[2px\] {
|
|
619
625
|
min-height: 2px;
|
|
620
626
|
}
|
package/dist/index.js
CHANGED
package/dist/pages.d.ts
CHANGED
|
@@ -59,6 +59,19 @@ interface PlanTierInfo {
|
|
|
59
59
|
ramMaxGB: number;
|
|
60
60
|
storageMaxGB: number;
|
|
61
61
|
}
|
|
62
|
+
interface SshKeyOption {
|
|
63
|
+
id: string;
|
|
64
|
+
name: string;
|
|
65
|
+
fingerprint: string;
|
|
66
|
+
keyType: string;
|
|
67
|
+
}
|
|
68
|
+
interface SshAccessConfig {
|
|
69
|
+
keys?: SshKeyOption[];
|
|
70
|
+
selectedKeyIds: string[];
|
|
71
|
+
inlinePublicKeys: string;
|
|
72
|
+
onSelectedKeyIdsChange: (keyIds: string[]) => void;
|
|
73
|
+
onInlinePublicKeysChange: (publicKeys: string) => void;
|
|
74
|
+
}
|
|
62
75
|
interface ProvisioningWizardProps {
|
|
63
76
|
environments?: EnvironmentOption[];
|
|
64
77
|
onLoadEnvironments?: () => Promise<EnvironmentEntry[]>;
|
|
@@ -107,6 +120,7 @@ interface ProvisioningWizardProps {
|
|
|
107
120
|
* persistence (e.g. localStorage, account settings API).
|
|
108
121
|
*/
|
|
109
122
|
onSetDefault?: (modelId: string) => void;
|
|
123
|
+
sshAccess?: SshAccessConfig;
|
|
110
124
|
/** Real pricing rates from the API for accurate cost calculation */
|
|
111
125
|
pricingRates?: PricingRates;
|
|
112
126
|
/**
|
|
@@ -141,7 +155,7 @@ interface ProvisioningConfig {
|
|
|
141
155
|
startupScriptIds?: string[];
|
|
142
156
|
}
|
|
143
157
|
declare function resolveEnvironment(env: EnvironmentEntry): EnvironmentOption;
|
|
144
|
-
declare function ProvisioningWizard({ environments: environmentsProp, onLoadEnvironments, onSubmit, onBack, className, variant, defaultEnvironment, defaultConfig, skipToReview, onLoadStartupScripts, resourceLimits, models, popular, defaultModel, onSetDefault, pricingRates, planTiers, }: ProvisioningWizardProps): react_jsx_runtime.JSX.Element;
|
|
158
|
+
declare function ProvisioningWizard({ environments: environmentsProp, onLoadEnvironments, onSubmit, onBack, className, variant, defaultEnvironment, defaultConfig, skipToReview, onLoadStartupScripts, resourceLimits, models, popular, defaultModel, onSetDefault, sshAccess, pricingRates, planTiers, }: ProvisioningWizardProps): react_jsx_runtime.JSX.Element;
|
|
145
159
|
|
|
146
160
|
type ProductVariant = "sandbox";
|
|
147
161
|
interface StandalonePricingPageProps {
|
|
@@ -307,4 +321,4 @@ type TemplateCategory = "blockchain" | "ai-ml" | "frontend" | "infrastructure" |
|
|
|
307
321
|
type TemplatePreset = Omit<ProvisioningConfig, "name" | "gitUrl" | "envVars" | "driver" | "startupScriptIds" | "modelTier">;
|
|
308
322
|
declare function getPresetForTemplate(id: string): TemplatePreset;
|
|
309
323
|
|
|
310
|
-
export { BillingPage, type BillingPageData, type BillingPageProps, type EnvironmentEntry, type EnvironmentOption, ModelInfo, type PlanTierInfo, type PricingRates, PricingTier, type ProductVariant$1 as ProductVariant, type Profile, type ProfileFormData, type ProfileMetrics, ProfilesPage, type ProfilesPageProps, type ProvisioningConfig, ProvisioningWizard, type ProvisioningWizardProps, type ResourceLimits, type ScriptType, type Secret, type SecretsApiClient, SecretsPage, type SecretsPageProps, StandalonePricingPage, type StandalonePricingPageProps, type StartupScript, type StartupScriptEntry, type StartupScriptFormData, type StartupScriptsApiClient, StartupScriptsPage, type StartupScriptsPageProps, type TemplateCategory, type TemplatePreset, TemplatesPage, type TemplatesPageProps, getPresetForTemplate, resolveEnvironment };
|
|
324
|
+
export { BillingPage, type BillingPageData, type BillingPageProps, type EnvironmentEntry, type EnvironmentOption, ModelInfo, type PlanTierInfo, type PricingRates, PricingTier, type ProductVariant$1 as ProductVariant, type Profile, type ProfileFormData, type ProfileMetrics, ProfilesPage, type ProfilesPageProps, type ProvisioningConfig, ProvisioningWizard, type ProvisioningWizardProps, type ResourceLimits, type ScriptType, type Secret, type SecretsApiClient, SecretsPage, type SecretsPageProps, type SshAccessConfig, type SshKeyOption, StandalonePricingPage, type StandalonePricingPageProps, type StartupScript, type StartupScriptEntry, type StartupScriptFormData, type StartupScriptsApiClient, StartupScriptsPage, type StartupScriptsPageProps, type TemplateCategory, type TemplatePreset, TemplatesPage, type TemplatesPageProps, getPresetForTemplate, resolveEnvironment };
|
package/dist/pages.js
CHANGED
|
@@ -7,6 +7,11 @@ import {
|
|
|
7
7
|
UsageChart,
|
|
8
8
|
canonicalModelId
|
|
9
9
|
} from "./chunk-27X3DWMO.js";
|
|
10
|
+
import {
|
|
11
|
+
Badge,
|
|
12
|
+
Button,
|
|
13
|
+
Textarea
|
|
14
|
+
} from "./chunk-7ZA5SEK3.js";
|
|
10
15
|
import {
|
|
11
16
|
cn
|
|
12
17
|
} from "./chunk-EI44GEQ5.js";
|
|
@@ -439,6 +444,59 @@ function computeHourlyCost(cpu, ram, storage, rates) {
|
|
|
439
444
|
total: Math.max(floor, lineSum)
|
|
440
445
|
};
|
|
441
446
|
}
|
|
447
|
+
function SshAccessStep({ config }) {
|
|
448
|
+
const keys = config.keys ?? [];
|
|
449
|
+
const inlineKeyCount = config.inlinePublicKeys.split(/\r?\n/).map((key) => key.trim()).filter(Boolean).length;
|
|
450
|
+
const totalKeyCount = config.selectedKeyIds.length + inlineKeyCount;
|
|
451
|
+
return /* @__PURE__ */ jsxs2("div", { className: "space-y-4", children: [
|
|
452
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex items-start justify-between gap-4", children: [
|
|
453
|
+
/* @__PURE__ */ jsxs2("div", { children: [
|
|
454
|
+
/* @__PURE__ */ jsx2("p", { className: "font-medium text-foreground text-sm", children: "SSH Access" }),
|
|
455
|
+
/* @__PURE__ */ jsx2("p", { className: "mt-1 text-muted-foreground text-xs", children: "Select stored keys or paste public keys for authorized_keys." })
|
|
456
|
+
] }),
|
|
457
|
+
/* @__PURE__ */ jsxs2(Badge, { variant: "outline", children: [
|
|
458
|
+
totalKeyCount,
|
|
459
|
+
" key",
|
|
460
|
+
totalKeyCount === 1 ? "" : "s"
|
|
461
|
+
] })
|
|
462
|
+
] }),
|
|
463
|
+
keys.length > 0 && /* @__PURE__ */ jsx2("div", { className: "grid gap-2 sm:grid-cols-2", children: keys.map((key) => {
|
|
464
|
+
const selected = config.selectedKeyIds.includes(key.id);
|
|
465
|
+
return /* @__PURE__ */ jsx2(
|
|
466
|
+
Button,
|
|
467
|
+
{
|
|
468
|
+
type: "button",
|
|
469
|
+
variant: selected ? "sandbox" : "outline",
|
|
470
|
+
className: "h-auto justify-start p-3 text-left",
|
|
471
|
+
"aria-pressed": selected,
|
|
472
|
+
onClick: () => {
|
|
473
|
+
config.onSelectedKeyIdsChange(
|
|
474
|
+
selected ? config.selectedKeyIds.filter((id) => id !== key.id) : [...config.selectedKeyIds, key.id]
|
|
475
|
+
);
|
|
476
|
+
},
|
|
477
|
+
children: /* @__PURE__ */ jsxs2("span", { className: "min-w-0", children: [
|
|
478
|
+
/* @__PURE__ */ jsx2("span", { className: "block font-medium text-foreground", children: key.name }),
|
|
479
|
+
/* @__PURE__ */ jsxs2("span", { className: "block truncate font-mono text-muted-foreground text-xs", children: [
|
|
480
|
+
key.keyType,
|
|
481
|
+
" \xB7 ",
|
|
482
|
+
key.fingerprint
|
|
483
|
+
] })
|
|
484
|
+
] })
|
|
485
|
+
},
|
|
486
|
+
key.id
|
|
487
|
+
);
|
|
488
|
+
}) }),
|
|
489
|
+
/* @__PURE__ */ jsx2(
|
|
490
|
+
Textarea,
|
|
491
|
+
{
|
|
492
|
+
className: "min-h-24 font-mono text-xs",
|
|
493
|
+
placeholder: "Paste one public key per line",
|
|
494
|
+
value: config.inlinePublicKeys,
|
|
495
|
+
onChange: (event) => config.onInlinePublicKeysChange(event.target.value)
|
|
496
|
+
}
|
|
497
|
+
)
|
|
498
|
+
] });
|
|
499
|
+
}
|
|
442
500
|
function ProvisioningWizard({
|
|
443
501
|
environments: environmentsProp,
|
|
444
502
|
onLoadEnvironments,
|
|
@@ -455,6 +513,7 @@ function ProvisioningWizard({
|
|
|
455
513
|
popular,
|
|
456
514
|
defaultModel,
|
|
457
515
|
onSetDefault,
|
|
516
|
+
sshAccess,
|
|
458
517
|
pricingRates,
|
|
459
518
|
planTiers
|
|
460
519
|
}) {
|
|
@@ -585,8 +644,10 @@ function ProvisioningWizard({
|
|
|
585
644
|
};
|
|
586
645
|
}, []);
|
|
587
646
|
const isMultistep = variant === "multistep";
|
|
647
|
+
const stepLabels = sshAccess ? ["Environment", "Resources", "AI Agent", "Access"] : ["Environment", "Resources", "AI Agent"];
|
|
648
|
+
const finalStep = stepLabels.length;
|
|
588
649
|
const [currentStep, setCurrentStep] = React2.useState(
|
|
589
|
-
skipToReview && dc && isMultistep ?
|
|
650
|
+
skipToReview && dc && isMultistep ? finalStep : 1
|
|
590
651
|
);
|
|
591
652
|
const [isDeploying, setIsDeploying] = React2.useState(false);
|
|
592
653
|
const [deployError, setDeployError] = React2.useState(null);
|
|
@@ -700,41 +761,40 @@ function ProvisioningWizard({
|
|
|
700
761
|
] }),
|
|
701
762
|
/* @__PURE__ */ jsxs2("div", { className: "grid grid-cols-12 gap-6 flex-1 min-h-0", children: [
|
|
702
763
|
/* @__PURE__ */ jsxs2("div", { className: "col-span-12 xl:col-span-8 flex flex-col min-h-0", children: [
|
|
703
|
-
isMultistep && /* @__PURE__ */ jsx2("div", { className: "flex items-center gap-2 mb-4 bg-card border border-border p-3 rounded-2xl mx-auto max-w-2xl justify-between shrink-0", children:
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
] }, s)) }),
|
|
764
|
+
isMultistep && /* @__PURE__ */ jsx2("div", { className: "flex items-center gap-2 mb-4 bg-card border border-border p-3 rounded-2xl mx-auto max-w-2xl justify-between shrink-0", children: stepLabels.map((label, index) => {
|
|
765
|
+
const s = index + 1;
|
|
766
|
+
return /* @__PURE__ */ jsxs2("div", { className: "flex items-center", children: [
|
|
767
|
+
/* @__PURE__ */ jsx2(
|
|
768
|
+
"div",
|
|
769
|
+
{
|
|
770
|
+
className: cn(
|
|
771
|
+
"w-7 h-7 rounded-full flex items-center justify-center font-bold text-xs shrink-0 transition-all duration-200",
|
|
772
|
+
currentStep === s ? "bg-primary text-primary-foreground ring-2 ring-primary/30 ring-offset-2 ring-offset-card shadow-sm" : currentStep > s ? "bg-primary text-primary-foreground" : "bg-muted border border-border text-muted-foreground"
|
|
773
|
+
),
|
|
774
|
+
children: currentStep > s ? /* @__PURE__ */ jsx2(Check, { className: "h-3.5 w-3.5" }) : s
|
|
775
|
+
}
|
|
776
|
+
),
|
|
777
|
+
/* @__PURE__ */ jsx2(
|
|
778
|
+
"span",
|
|
779
|
+
{
|
|
780
|
+
className: cn(
|
|
781
|
+
"ml-2 sm:ml-3 font-bold text-sm tracking-tight hidden sm:inline transition-colors duration-200",
|
|
782
|
+
currentStep === s ? "text-foreground" : currentStep > s ? "text-primary" : "text-muted-foreground"
|
|
783
|
+
),
|
|
784
|
+
children: label
|
|
785
|
+
}
|
|
786
|
+
),
|
|
787
|
+
s < finalStep && /* @__PURE__ */ jsx2(
|
|
788
|
+
"div",
|
|
789
|
+
{
|
|
790
|
+
className: cn(
|
|
791
|
+
"w-4 sm:w-8 h-0.5 mx-2 sm:mx-4 rounded-full transition-colors duration-300",
|
|
792
|
+
currentStep > s ? "bg-primary" : "bg-border"
|
|
793
|
+
)
|
|
794
|
+
}
|
|
795
|
+
)
|
|
796
|
+
] }, s);
|
|
797
|
+
}) }),
|
|
738
798
|
dc && isMultistep && /* @__PURE__ */ jsxs2("div", { className: "flex items-center justify-between bg-card border border-border rounded-2xl px-4 py-3 shrink-0", children: [
|
|
739
799
|
/* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-2 text-sm", children: [
|
|
740
800
|
/* @__PURE__ */ jsx2(Info, { className: "h-4 w-4 text-primary shrink-0" }),
|
|
@@ -1206,6 +1266,13 @@ function ProvisioningWizard({
|
|
|
1206
1266
|
] })
|
|
1207
1267
|
] })
|
|
1208
1268
|
] })
|
|
1269
|
+
] }) }),
|
|
1270
|
+
sshAccess && (!isMultistep || currentStep === 4) && /* @__PURE__ */ jsx2(React2.Fragment, { children: /* @__PURE__ */ jsxs2("section", { className: "bg-card border border-border rounded-[24px] p-6 shadow-2xl relative overflow-hidden animate-in fade-in slide-in-from-bottom-4 duration-300", children: [
|
|
1271
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-3 mb-5", children: [
|
|
1272
|
+
/* @__PURE__ */ jsx2("div", { className: "flex h-9 w-9 shrink-0 items-center justify-center rounded-xl bg-primary/10 border border-primary/20 text-primary", children: /* @__PURE__ */ jsx2(Settings, { className: "h-5 w-5" }) }),
|
|
1273
|
+
/* @__PURE__ */ jsx2("h2", { className: "text-lg font-bold text-foreground tracking-tight", children: "Access Configuration" })
|
|
1274
|
+
] }),
|
|
1275
|
+
/* @__PURE__ */ jsx2(SshAccessStep, { config: sshAccess })
|
|
1209
1276
|
] }) })
|
|
1210
1277
|
] })
|
|
1211
1278
|
] }),
|
|
@@ -1310,16 +1377,15 @@ function ProvisioningWizard({
|
|
|
1310
1377
|
/* @__PURE__ */ jsx2("p", { className: "text-sm font-medium text-destructive", children: deployError })
|
|
1311
1378
|
] }),
|
|
1312
1379
|
/* @__PURE__ */ jsx2("div", { className: "space-y-3", children: isMultistep ? /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
1313
|
-
currentStep <
|
|
1380
|
+
currentStep < finalStep ? /* @__PURE__ */ jsxs2(
|
|
1314
1381
|
"button",
|
|
1315
1382
|
{
|
|
1316
1383
|
type: "button",
|
|
1317
1384
|
onClick: () => setCurrentStep((s) => s + 1),
|
|
1318
1385
|
className: "w-full relative overflow-hidden h-12 bg-primary text-primary-foreground font-extrabold text-sm rounded-2xl hover:brightness-110 transition-all active:scale-[0.98] shadow-md",
|
|
1319
1386
|
children: [
|
|
1320
|
-
"Continue to",
|
|
1321
|
-
|
|
1322
|
-
currentStep === 1 ? "Resources" : "Agent Config"
|
|
1387
|
+
"Continue to ",
|
|
1388
|
+
stepLabels[currentStep]
|
|
1323
1389
|
]
|
|
1324
1390
|
}
|
|
1325
1391
|
) : /* @__PURE__ */ jsx2(
|
|
@@ -1544,8 +1610,8 @@ import {
|
|
|
1544
1610
|
Trash2 as Trash22
|
|
1545
1611
|
} from "lucide-react";
|
|
1546
1612
|
import * as React4 from "react";
|
|
1547
|
-
import { Button } from "@tangle-network/ui/primitives";
|
|
1548
|
-
import { Badge } from "@tangle-network/ui/primitives";
|
|
1613
|
+
import { Button as Button2 } from "@tangle-network/ui/primitives";
|
|
1614
|
+
import { Badge as Badge2 } from "@tangle-network/ui/primitives";
|
|
1549
1615
|
import { Card } from "@tangle-network/ui/primitives";
|
|
1550
1616
|
import {
|
|
1551
1617
|
Dialog,
|
|
@@ -1618,7 +1684,7 @@ function ProfilesPage({
|
|
|
1618
1684
|
] }),
|
|
1619
1685
|
/* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-3", children: [
|
|
1620
1686
|
onCompareClick && customProfiles.length >= 2 && /* @__PURE__ */ jsx4(
|
|
1621
|
-
|
|
1687
|
+
Button2,
|
|
1622
1688
|
{
|
|
1623
1689
|
variant: "outline",
|
|
1624
1690
|
onClick: () => onCompareClick(customProfiles),
|
|
@@ -1626,7 +1692,7 @@ function ProfilesPage({
|
|
|
1626
1692
|
}
|
|
1627
1693
|
),
|
|
1628
1694
|
/* @__PURE__ */ jsxs4(
|
|
1629
|
-
|
|
1695
|
+
Button2,
|
|
1630
1696
|
{
|
|
1631
1697
|
onClick: () => setCreateDialogOpen(true),
|
|
1632
1698
|
disabled: !canCreateMore,
|
|
@@ -1661,7 +1727,7 @@ function ProfilesPage({
|
|
|
1661
1727
|
error && /* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-2 rounded-lg border border-[var(--surface-danger-border)] bg-[var(--surface-danger-bg)] p-3 text-[var(--surface-danger-text)] text-sm", children: [
|
|
1662
1728
|
/* @__PURE__ */ jsx4(AlertCircle, { className: "h-4 w-4" }),
|
|
1663
1729
|
/* @__PURE__ */ jsx4("span", { children: error }),
|
|
1664
|
-
/* @__PURE__ */ jsx4(
|
|
1730
|
+
/* @__PURE__ */ jsx4(Button2, { variant: "ghost", size: "sm", onClick: loadProfiles, children: "Retry" })
|
|
1665
1731
|
] }),
|
|
1666
1732
|
loading && /* @__PURE__ */ jsx4("div", { className: "flex items-center justify-center py-12", children: /* @__PURE__ */ jsx4(Loader22, { className: "h-8 w-8 animate-spin text-muted-foreground" }) }),
|
|
1667
1733
|
!loading && /* @__PURE__ */ jsxs4("div", { className: "space-y-8", children: [
|
|
@@ -1679,7 +1745,7 @@ function ProfilesPage({
|
|
|
1679
1745
|
icon: /* @__PURE__ */ jsx4(Settings2, { className: "h-8 w-8" }),
|
|
1680
1746
|
title: "No custom profiles yet",
|
|
1681
1747
|
description: "Create a profile to customize agent behavior",
|
|
1682
|
-
action: canCreateMore ? /* @__PURE__ */ jsxs4(
|
|
1748
|
+
action: canCreateMore ? /* @__PURE__ */ jsxs4(Button2, { onClick: () => setCreateDialogOpen(true), children: [
|
|
1683
1749
|
/* @__PURE__ */ jsx4(Plus2, { className: "mr-2 h-4 w-4" }),
|
|
1684
1750
|
"Create Profile"
|
|
1685
1751
|
] }) : void 0
|
|
@@ -1781,14 +1847,14 @@ function ProfileCard({
|
|
|
1781
1847
|
/* @__PURE__ */ jsxs4("div", { className: "flex-1", children: [
|
|
1782
1848
|
/* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-2", children: [
|
|
1783
1849
|
/* @__PURE__ */ jsx4("h3", { className: "font-medium", children: profile.name }),
|
|
1784
|
-
isBuiltin && /* @__PURE__ */ jsx4(
|
|
1785
|
-
profile.is_public && !isBuiltin && /* @__PURE__ */ jsx4(
|
|
1850
|
+
isBuiltin && /* @__PURE__ */ jsx4(Badge2, { variant: "secondary", className: "border-0 text-xs", children: "Built-in" }),
|
|
1851
|
+
profile.is_public && !isBuiltin && /* @__PURE__ */ jsx4(Badge2, { className: "border border-[var(--surface-info-border)] bg-[var(--surface-info-bg)] text-[var(--surface-info-text)] text-xs", children: "Public" })
|
|
1786
1852
|
] }),
|
|
1787
1853
|
profile.description && /* @__PURE__ */ jsx4("p", { className: "mt-1 line-clamp-2 text-muted-foreground text-sm", children: profile.description })
|
|
1788
1854
|
] }),
|
|
1789
1855
|
!isBuiltin && /* @__PURE__ */ jsxs4("div", { className: "flex gap-1", onClick: (e) => e.stopPropagation(), children: [
|
|
1790
1856
|
onEdit && /* @__PURE__ */ jsx4(
|
|
1791
|
-
|
|
1857
|
+
Button2,
|
|
1792
1858
|
{
|
|
1793
1859
|
variant: "ghost",
|
|
1794
1860
|
size: "icon",
|
|
@@ -1798,7 +1864,7 @@ function ProfileCard({
|
|
|
1798
1864
|
}
|
|
1799
1865
|
),
|
|
1800
1866
|
onDelete && /* @__PURE__ */ jsx4(
|
|
1801
|
-
|
|
1867
|
+
Button2,
|
|
1802
1868
|
{
|
|
1803
1869
|
variant: "ghost",
|
|
1804
1870
|
size: "icon",
|
|
@@ -1810,11 +1876,11 @@ function ProfileCard({
|
|
|
1810
1876
|
] })
|
|
1811
1877
|
] }),
|
|
1812
1878
|
/* @__PURE__ */ jsxs4("div", { className: "mt-3 flex flex-wrap gap-2", children: [
|
|
1813
|
-
profile.extends && /* @__PURE__ */ jsxs4(
|
|
1879
|
+
profile.extends && /* @__PURE__ */ jsxs4(Badge2, { variant: "outline", className: "text-xs", children: [
|
|
1814
1880
|
"extends ",
|
|
1815
1881
|
profile.extends
|
|
1816
1882
|
] }),
|
|
1817
|
-
profile.model && /* @__PURE__ */ jsx4(
|
|
1883
|
+
profile.model && /* @__PURE__ */ jsx4(Badge2, { variant: "outline", className: "text-xs", children: profile.model.split("/").pop() })
|
|
1818
1884
|
] }),
|
|
1819
1885
|
profile.metrics && profile.metrics.total_runs > 0 && /* @__PURE__ */ jsxs4("div", { className: "mt-3 flex gap-4 border-border border-t pt-3 text-muted-foreground text-xs", children: [
|
|
1820
1886
|
/* @__PURE__ */ jsxs4("span", { children: [
|
|
@@ -2020,8 +2086,8 @@ function ProfileFormDialog({
|
|
|
2020
2086
|
/* @__PURE__ */ jsx4("label", { htmlFor: "is_public", className: "text-sm", children: "Make this profile public (visible to other users)" })
|
|
2021
2087
|
] }),
|
|
2022
2088
|
/* @__PURE__ */ jsxs4(DialogFooter, { children: [
|
|
2023
|
-
/* @__PURE__ */ jsx4(
|
|
2024
|
-
/* @__PURE__ */ jsxs4(
|
|
2089
|
+
/* @__PURE__ */ jsx4(Button2, { type: "button", variant: "outline", onClick: onClose, children: "Cancel" }),
|
|
2090
|
+
/* @__PURE__ */ jsxs4(Button2, { type: "submit", disabled: saving || !formData.name, children: [
|
|
2025
2091
|
saving && /* @__PURE__ */ jsx4(Loader22, { className: "mr-2 h-4 w-4 animate-spin" }),
|
|
2026
2092
|
isEditing ? "Save Changes" : "Create Profile"
|
|
2027
2093
|
] })
|
|
@@ -2069,9 +2135,9 @@ function DeleteProfileDialog({
|
|
|
2069
2135
|
" recorded runs. Deleting it will lose all performance metrics."
|
|
2070
2136
|
] }),
|
|
2071
2137
|
/* @__PURE__ */ jsxs4(DialogFooter, { children: [
|
|
2072
|
-
/* @__PURE__ */ jsx4(
|
|
2138
|
+
/* @__PURE__ */ jsx4(Button2, { variant: "outline", onClick: onClose, children: "Cancel" }),
|
|
2073
2139
|
/* @__PURE__ */ jsxs4(
|
|
2074
|
-
|
|
2140
|
+
Button2,
|
|
2075
2141
|
{
|
|
2076
2142
|
variant: "destructive",
|
|
2077
2143
|
onClick: handleDelete,
|
|
@@ -2096,8 +2162,8 @@ function ProfileDetailDialog({
|
|
|
2096
2162
|
/* @__PURE__ */ jsxs4(DialogHeader, { children: [
|
|
2097
2163
|
/* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-2", children: [
|
|
2098
2164
|
/* @__PURE__ */ jsx4(DialogTitle, { children: profile.name }),
|
|
2099
|
-
profile.is_builtin && /* @__PURE__ */ jsx4(
|
|
2100
|
-
profile.is_public && !profile.is_builtin && /* @__PURE__ */ jsx4(
|
|
2165
|
+
profile.is_builtin && /* @__PURE__ */ jsx4(Badge2, { variant: "secondary", className: "border-0", children: "Built-in" }),
|
|
2166
|
+
profile.is_public && !profile.is_builtin && /* @__PURE__ */ jsx4(Badge2, { className: "border border-[var(--surface-info-border)] bg-[var(--surface-info-bg)] text-[var(--surface-info-text)]", children: "Public" })
|
|
2101
2167
|
] }),
|
|
2102
2168
|
profile.description && /* @__PURE__ */ jsx4(DialogDescription, { children: profile.description })
|
|
2103
2169
|
] }),
|
|
@@ -2114,14 +2180,14 @@ function ProfileDetailDialog({
|
|
|
2114
2180
|
] }),
|
|
2115
2181
|
profile.tags && profile.tags.length > 0 && /* @__PURE__ */ jsxs4("div", { children: [
|
|
2116
2182
|
/* @__PURE__ */ jsx4("label", { className: "font-medium text-muted-foreground text-xs", children: "Tags" }),
|
|
2117
|
-
/* @__PURE__ */ jsx4("div", { className: "mt-1 flex flex-wrap gap-1", children: profile.tags.map((tag) => /* @__PURE__ */ jsx4(
|
|
2183
|
+
/* @__PURE__ */ jsx4("div", { className: "mt-1 flex flex-wrap gap-1", children: profile.tags.map((tag) => /* @__PURE__ */ jsx4(Badge2, { variant: "outline", className: "text-xs", children: tag }, tag)) })
|
|
2118
2184
|
] }),
|
|
2119
2185
|
profile.system_prompt && /* @__PURE__ */ jsxs4("div", { children: [
|
|
2120
2186
|
/* @__PURE__ */ jsx4("label", { className: "font-medium text-muted-foreground text-xs", children: "System Prompt" }),
|
|
2121
2187
|
/* @__PURE__ */ jsxs4("div", { className: "relative mt-1", children: [
|
|
2122
2188
|
/* @__PURE__ */ jsx4("pre", { className: "max-h-48 overflow-auto rounded-lg bg-muted p-3 font-mono text-sm", children: profile.system_prompt }),
|
|
2123
2189
|
/* @__PURE__ */ jsx4(
|
|
2124
|
-
|
|
2190
|
+
Button2,
|
|
2125
2191
|
{
|
|
2126
2192
|
variant: "ghost",
|
|
2127
2193
|
size: "icon",
|
|
@@ -2169,12 +2235,12 @@ function ProfileDetailDialog({
|
|
|
2169
2235
|
] })
|
|
2170
2236
|
] }),
|
|
2171
2237
|
/* @__PURE__ */ jsxs4(DialogFooter, { children: [
|
|
2172
|
-
/* @__PURE__ */ jsx4(
|
|
2173
|
-
onDuplicate && /* @__PURE__ */ jsxs4(
|
|
2238
|
+
/* @__PURE__ */ jsx4(Button2, { variant: "outline", onClick: onClose, children: "Close" }),
|
|
2239
|
+
onDuplicate && /* @__PURE__ */ jsxs4(Button2, { variant: "outline", onClick: onDuplicate, children: [
|
|
2174
2240
|
/* @__PURE__ */ jsx4(Copy, { className: "mr-2 h-4 w-4" }),
|
|
2175
2241
|
"Duplicate"
|
|
2176
2242
|
] }),
|
|
2177
|
-
onEdit && /* @__PURE__ */ jsxs4(
|
|
2243
|
+
onEdit && /* @__PURE__ */ jsxs4(Button2, { onClick: onEdit, children: [
|
|
2178
2244
|
/* @__PURE__ */ jsx4(Edit2, { className: "mr-2 h-4 w-4" }),
|
|
2179
2245
|
"Edit"
|
|
2180
2246
|
] })
|
package/dist/styles.css
CHANGED
|
@@ -591,6 +591,9 @@
|
|
|
591
591
|
.h-\[500px\] {
|
|
592
592
|
height: 500px;
|
|
593
593
|
}
|
|
594
|
+
.h-auto {
|
|
595
|
+
height: auto;
|
|
596
|
+
}
|
|
594
597
|
.h-full {
|
|
595
598
|
height: 100%;
|
|
596
599
|
}
|
|
@@ -615,6 +618,9 @@
|
|
|
615
618
|
.min-h-0 {
|
|
616
619
|
min-height: calc(var(--spacing) * 0);
|
|
617
620
|
}
|
|
621
|
+
.min-h-24 {
|
|
622
|
+
min-height: calc(var(--spacing) * 24);
|
|
623
|
+
}
|
|
618
624
|
.min-h-\[2px\] {
|
|
619
625
|
min-height: 2px;
|
|
620
626
|
}
|
package/package.json
CHANGED