@tangle-network/sandbox-ui 0.52.0 → 0.53.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-RT4MLYYM.js → chunk-KN2ZRAW6.js} +612 -248
- package/dist/{chunk-MGIOO3RL.js → chunk-P6L4KBYK.js} +1 -1
- package/dist/dashboard.d.ts +173 -25
- package/dist/dashboard.js +5 -1
- package/dist/globals.css +42 -37
- package/dist/index.d.ts +1 -1
- package/dist/index.js +6 -2
- package/dist/integrations.js +53 -52
- package/dist/styles.css +42 -37
- package/dist/workbench.js +2 -2
- package/package.json +2 -1
|
@@ -7,7 +7,8 @@ import {
|
|
|
7
7
|
} from "./chunk-EI44GEQ5.js";
|
|
8
8
|
|
|
9
9
|
// src/dashboard/app-sidebar.tsx
|
|
10
|
-
import * as
|
|
10
|
+
import * as React3 from "react";
|
|
11
|
+
import { createPortal as createPortal2 } from "react-dom";
|
|
11
12
|
import { Avatar, AvatarFallback, AvatarImage } from "@tangle-network/ui/primitives";
|
|
12
13
|
import {
|
|
13
14
|
DropdownMenu,
|
|
@@ -15,9 +16,13 @@ import {
|
|
|
15
16
|
DropdownMenuItem,
|
|
16
17
|
DropdownMenuLabel,
|
|
17
18
|
DropdownMenuSeparator,
|
|
19
|
+
DropdownMenuSub,
|
|
20
|
+
DropdownMenuSubContent,
|
|
21
|
+
DropdownMenuSubTrigger,
|
|
18
22
|
DropdownMenuTrigger
|
|
19
23
|
} from "@tangle-network/ui/primitives";
|
|
20
24
|
import { Skeleton, useTheme } from "@tangle-network/ui/primitives";
|
|
25
|
+
import { Check, Monitor, PanelLeft } from "lucide-react";
|
|
21
26
|
|
|
22
27
|
// src/dashboard/sidebar-context.tsx
|
|
23
28
|
import * as React from "react";
|
|
@@ -135,27 +140,61 @@ function useSidebar() {
|
|
|
135
140
|
}
|
|
136
141
|
|
|
137
142
|
// src/dashboard/rail-tooltip.tsx
|
|
143
|
+
import * as React2 from "react";
|
|
144
|
+
import { createPortal } from "react-dom";
|
|
138
145
|
import { Fragment, jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
146
|
+
var RAIL_FLOATING_SURFACE = "rounded-md border border-[var(--md3-outline-variant)] bg-surface-container-highest shadow-[0_8px_30px_rgba(0,0,0,0.45)] ring-1 ring-[#ffffff14]";
|
|
139
147
|
function RailTooltip({ label, children, disabled, className }) {
|
|
148
|
+
const ref = React2.useRef(null);
|
|
149
|
+
const timer = React2.useRef(null);
|
|
150
|
+
const [coords, setCoords] = React2.useState(null);
|
|
151
|
+
React2.useEffect(() => () => {
|
|
152
|
+
if (timer.current) clearTimeout(timer.current);
|
|
153
|
+
}, []);
|
|
140
154
|
if (disabled) return /* @__PURE__ */ jsx2(Fragment, { children });
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
155
|
+
const open = () => {
|
|
156
|
+
if (timer.current) clearTimeout(timer.current);
|
|
157
|
+
timer.current = setTimeout(() => {
|
|
158
|
+
const el = ref.current;
|
|
159
|
+
if (!el) return;
|
|
160
|
+
const r = el.getBoundingClientRect();
|
|
161
|
+
setCoords({ top: r.top + r.height / 2, left: r.right + 8 });
|
|
162
|
+
}, 250);
|
|
163
|
+
};
|
|
164
|
+
const close = () => {
|
|
165
|
+
if (timer.current) clearTimeout(timer.current);
|
|
166
|
+
setCoords(null);
|
|
167
|
+
};
|
|
168
|
+
return /* @__PURE__ */ jsxs(
|
|
169
|
+
"span",
|
|
170
|
+
{
|
|
171
|
+
ref,
|
|
172
|
+
className: cn("relative flex", className),
|
|
173
|
+
onMouseEnter: open,
|
|
174
|
+
onMouseLeave: close,
|
|
175
|
+
onFocusCapture: open,
|
|
176
|
+
onBlurCapture: close,
|
|
177
|
+
children: [
|
|
178
|
+
children,
|
|
179
|
+
coords !== null && typeof document !== "undefined" && createPortal(
|
|
180
|
+
/* @__PURE__ */ jsx2(
|
|
181
|
+
"span",
|
|
182
|
+
{
|
|
183
|
+
role: "tooltip",
|
|
184
|
+
"aria-hidden": "true",
|
|
185
|
+
style: { position: "fixed", top: coords.top, left: coords.left, transform: "translateY(-50%)" },
|
|
186
|
+
className: cn(
|
|
187
|
+
"pointer-events-none z-[70] whitespace-nowrap px-2 py-1 text-xs font-medium text-popover-foreground",
|
|
188
|
+
RAIL_FLOATING_SURFACE
|
|
189
|
+
),
|
|
190
|
+
children: label
|
|
191
|
+
}
|
|
192
|
+
),
|
|
193
|
+
document.body
|
|
194
|
+
)
|
|
195
|
+
]
|
|
196
|
+
}
|
|
197
|
+
);
|
|
159
198
|
}
|
|
160
199
|
|
|
161
200
|
// src/dashboard/app-sidebar.tsx
|
|
@@ -204,8 +243,8 @@ function MoonIcon({ className }) {
|
|
|
204
243
|
}
|
|
205
244
|
function RailThemeToggle({ className }) {
|
|
206
245
|
const { theme, setTheme } = useTheme();
|
|
207
|
-
const [mounted, setMounted] =
|
|
208
|
-
|
|
246
|
+
const [mounted, setMounted] = React3.useState(false);
|
|
247
|
+
React3.useEffect(() => setMounted(true), []);
|
|
209
248
|
const isDark = mounted && (theme === "dark" || theme === "system" && typeof window !== "undefined" && window.matchMedia("(prefers-color-scheme: dark)").matches);
|
|
210
249
|
return /* @__PURE__ */ jsx3(
|
|
211
250
|
"button",
|
|
@@ -260,6 +299,67 @@ function RailCollapseToggle({ collapsed, showLabel, onToggle, className }) {
|
|
|
260
299
|
}
|
|
261
300
|
) });
|
|
262
301
|
}
|
|
302
|
+
function PanelToggleButton({ collapsed, onToggle, className }) {
|
|
303
|
+
const label = collapsed ? "Expand sidebar" : "Collapse sidebar";
|
|
304
|
+
return /* @__PURE__ */ jsx3(
|
|
305
|
+
"button",
|
|
306
|
+
{
|
|
307
|
+
type: "button",
|
|
308
|
+
onClick: onToggle,
|
|
309
|
+
"aria-label": label,
|
|
310
|
+
"aria-pressed": collapsed,
|
|
311
|
+
title: label,
|
|
312
|
+
className: cn(
|
|
313
|
+
"flex h-8 w-8 shrink-0 items-center justify-center rounded-md text-muted-foreground transition-colors",
|
|
314
|
+
"hover:bg-[var(--accent-surface-soft)] hover:text-foreground",
|
|
315
|
+
"focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
316
|
+
className
|
|
317
|
+
),
|
|
318
|
+
children: /* @__PURE__ */ jsx3(PanelLeft, { className: "h-[18px] w-[18px] shrink-0" })
|
|
319
|
+
}
|
|
320
|
+
);
|
|
321
|
+
}
|
|
322
|
+
function RailHeader({ brand, brandHref, children, collapsed, onToggle, collapsible = true, LinkComponent, className }) {
|
|
323
|
+
const Link = LinkComponent ?? DefaultLink;
|
|
324
|
+
const brandNode = brandHref !== void 0 ? /* @__PURE__ */ jsx3(
|
|
325
|
+
Link,
|
|
326
|
+
{
|
|
327
|
+
href: brandHref,
|
|
328
|
+
to: brandHref,
|
|
329
|
+
"aria-label": "Home",
|
|
330
|
+
className: "flex items-center justify-center rounded-md p-1 transition-colors hover:bg-[var(--accent-surface-soft)]",
|
|
331
|
+
children: brand
|
|
332
|
+
}
|
|
333
|
+
) : /* @__PURE__ */ jsx3("span", { className: "flex items-center justify-center p-1", children: brand });
|
|
334
|
+
return /* @__PURE__ */ jsx3(
|
|
335
|
+
"div",
|
|
336
|
+
{
|
|
337
|
+
className: cn(
|
|
338
|
+
"flex h-14 shrink-0 items-center border-b border-[var(--md3-outline-variant)]",
|
|
339
|
+
collapsed ? "justify-center px-2" : "gap-2 px-3",
|
|
340
|
+
className
|
|
341
|
+
),
|
|
342
|
+
children: collapsed ? collapsible ? /* @__PURE__ */ jsx3(RailTooltip, { label: "Expand sidebar", children: /* @__PURE__ */ jsxs2(
|
|
343
|
+
"button",
|
|
344
|
+
{
|
|
345
|
+
type: "button",
|
|
346
|
+
onClick: onToggle,
|
|
347
|
+
"aria-label": "Expand sidebar",
|
|
348
|
+
"aria-pressed": true,
|
|
349
|
+
className: "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",
|
|
350
|
+
children: [
|
|
351
|
+
/* @__PURE__ */ jsx3("span", { className: "flex items-center justify-center transition-opacity duration-150 group-hover/brand:opacity-0", children: brand }),
|
|
352
|
+
/* @__PURE__ */ jsx3("span", { className: "pointer-events-none absolute inset-0 flex items-center justify-center text-foreground opacity-0 transition-opacity duration-150 group-hover/brand:opacity-100", children: /* @__PURE__ */ jsx3(PanelLeft, { className: "h-[18px] w-[18px]" }) })
|
|
353
|
+
]
|
|
354
|
+
}
|
|
355
|
+
) }) : brandNode : /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
356
|
+
brand !== void 0 && brandNode,
|
|
357
|
+
/* @__PURE__ */ jsx3("div", { className: "min-w-0 flex-1", children }),
|
|
358
|
+
collapsible && /* @__PURE__ */ jsx3(PanelToggleButton, { collapsed, onToggle })
|
|
359
|
+
] })
|
|
360
|
+
}
|
|
361
|
+
);
|
|
362
|
+
}
|
|
263
363
|
function Sidebar({ children, className, style }) {
|
|
264
364
|
const { panelOpen, hidden, hasPanels, railWidth } = useSidebar();
|
|
265
365
|
return /* @__PURE__ */ jsx3(
|
|
@@ -294,8 +394,8 @@ function SidebarRail({ children, className, wide = false }) {
|
|
|
294
394
|
function SidebarRailHeader({ children, className }) {
|
|
295
395
|
return /* @__PURE__ */ jsx3("div", { className: cn("flex h-14 shrink-0 items-center justify-center border-b border-[var(--md3-outline-variant)]", className), children });
|
|
296
396
|
}
|
|
297
|
-
function SidebarRailNav({ children, className }) {
|
|
298
|
-
return /* @__PURE__ */ jsx3("nav", { className: cn("flex flex-col items-center gap-1 py-3 flex-1 min-h-0 overflow-y-auto", className), children });
|
|
397
|
+
function SidebarRailNav({ children, className, onClick }) {
|
|
398
|
+
return /* @__PURE__ */ jsx3("nav", { onClick, className: cn("flex flex-col items-center gap-1 py-3 flex-1 min-h-0 overflow-y-auto", className), children });
|
|
299
399
|
}
|
|
300
400
|
function SidebarRailFooter({ children, className }) {
|
|
301
401
|
return /* @__PURE__ */ jsx3("div", { className: cn("flex flex-col items-center gap-1 pb-3 shrink-0", className), children });
|
|
@@ -303,13 +403,16 @@ function SidebarRailFooter({ children, className }) {
|
|
|
303
403
|
function RailSeparator({ className }) {
|
|
304
404
|
return /* @__PURE__ */ jsx3("div", { className: cn("my-2 h-px w-10 bg-[var(--md3-outline-variant)]", className) });
|
|
305
405
|
}
|
|
306
|
-
function RailButton({ icon: Icon, label, isActive, badge, onClick, className, showLabel, asChild, children }) {
|
|
406
|
+
function RailButton({ icon: Icon, label, isActive, badge, onClick, className, showLabel, asChild, children, variant = "normal" }) {
|
|
307
407
|
const classes = cn(
|
|
308
408
|
"relative flex shrink-0 items-center justify-center rounded-md transition-colors duration-150",
|
|
309
409
|
showLabel ? "w-full justify-start px-2.5 h-9 gap-2.5" : "w-9 h-9 justify-center",
|
|
310
410
|
// Quiet press feedback via color only — no scale on the full-width row.
|
|
311
411
|
"focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
312
|
-
|
|
412
|
+
// The active item (route matches) and any explicit primary share one
|
|
413
|
+
// emphasized look — a filled accent pill with an accent ring — so the
|
|
414
|
+
// current destination clearly stands out from the default rows.
|
|
415
|
+
variant === "primary" || isActive ? "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",
|
|
313
416
|
className
|
|
314
417
|
);
|
|
315
418
|
const iconWithBadge = /* @__PURE__ */ jsxs2("span", { className: "relative flex shrink-0 items-center justify-center", children: [
|
|
@@ -320,9 +423,9 @@ function RailButton({ icon: Icon, label, isActive, badge, onClick, className, sh
|
|
|
320
423
|
iconWithBadge,
|
|
321
424
|
showLabel && /* @__PURE__ */ jsx3("span", { className: "text-[13.5px] font-medium", children: label })
|
|
322
425
|
] });
|
|
323
|
-
if (asChild &&
|
|
426
|
+
if (asChild && React3.isValidElement(children)) {
|
|
324
427
|
const child = children;
|
|
325
|
-
const merged =
|
|
428
|
+
const merged = React3.cloneElement(
|
|
326
429
|
child,
|
|
327
430
|
{ className: cn(classes, child.props.className), "aria-label": child.props["aria-label"] ?? label },
|
|
328
431
|
content
|
|
@@ -340,9 +443,9 @@ function RailFlyout({
|
|
|
340
443
|
children,
|
|
341
444
|
className
|
|
342
445
|
}) {
|
|
343
|
-
const [open, setOpen] =
|
|
344
|
-
const ref =
|
|
345
|
-
|
|
446
|
+
const [open, setOpen] = React3.useState(false);
|
|
447
|
+
const ref = React3.useRef(null);
|
|
448
|
+
React3.useEffect(() => {
|
|
346
449
|
if (!open) return;
|
|
347
450
|
const onPointer = (e) => {
|
|
348
451
|
if (ref.current && !ref.current.contains(e.target)) setOpen(false);
|
|
@@ -402,8 +505,8 @@ function RailFlyout({
|
|
|
402
505
|
if (el.closest("a,button")) setOpen(false);
|
|
403
506
|
},
|
|
404
507
|
className: cn(
|
|
405
|
-
"absolute top-0 z-50 min-w-[12rem]
|
|
406
|
-
|
|
508
|
+
"absolute left-full top-0 z-50 ml-2 min-w-[12rem] p-1.5",
|
|
509
|
+
RAIL_FLOATING_SURFACE
|
|
407
510
|
),
|
|
408
511
|
children: [
|
|
409
512
|
/* @__PURE__ */ jsx3("p", { className: "px-2 pb-1 pt-1 text-[10px] font-semibold uppercase tracking-wider text-muted-foreground/70 select-none", children: title ?? label }),
|
|
@@ -419,6 +522,233 @@ function ChevronRightIcon({ className }) {
|
|
|
419
522
|
/* @__PURE__ */ jsx3("path", { d: "m9 18 6-6-6-6" })
|
|
420
523
|
] });
|
|
421
524
|
}
|
|
525
|
+
function useExpandableItems(subItems, loadSubItems) {
|
|
526
|
+
const [items, setItems] = React3.useState(subItems ?? null);
|
|
527
|
+
const [loading, setLoading] = React3.useState(false);
|
|
528
|
+
const loadedRef = React3.useRef(subItems !== void 0);
|
|
529
|
+
React3.useEffect(() => {
|
|
530
|
+
if (subItems !== void 0) {
|
|
531
|
+
setItems(subItems);
|
|
532
|
+
loadedRef.current = true;
|
|
533
|
+
}
|
|
534
|
+
}, [subItems]);
|
|
535
|
+
const ensureLoaded = React3.useCallback(() => {
|
|
536
|
+
if (loadedRef.current || !loadSubItems) return;
|
|
537
|
+
loadedRef.current = true;
|
|
538
|
+
setLoading(true);
|
|
539
|
+
Promise.resolve(loadSubItems()).then(
|
|
540
|
+
(resolved) => {
|
|
541
|
+
setItems(resolved);
|
|
542
|
+
setLoading(false);
|
|
543
|
+
},
|
|
544
|
+
() => {
|
|
545
|
+
setItems([]);
|
|
546
|
+
setLoading(false);
|
|
547
|
+
loadedRef.current = false;
|
|
548
|
+
}
|
|
549
|
+
);
|
|
550
|
+
}, [loadSubItems]);
|
|
551
|
+
return { items, loading, ensureLoaded };
|
|
552
|
+
}
|
|
553
|
+
function SubItemsSkeleton() {
|
|
554
|
+
const widths = ["w-[88%]", "w-[76%]", "w-[82%]", "w-[64%]"];
|
|
555
|
+
return /* @__PURE__ */ jsx3("div", { className: "flex flex-col gap-1.5 px-2 py-1.5", children: widths.map((w, i) => /* @__PURE__ */ jsx3(Skeleton, { className: cn("h-4", w) }, i)) });
|
|
556
|
+
}
|
|
557
|
+
function RailExpandable({
|
|
558
|
+
icon: Icon,
|
|
559
|
+
label,
|
|
560
|
+
href,
|
|
561
|
+
isActive,
|
|
562
|
+
showLabel,
|
|
563
|
+
subItems,
|
|
564
|
+
loadSubItems,
|
|
565
|
+
activeSubIds,
|
|
566
|
+
emptyLabel = "Nothing here yet",
|
|
567
|
+
onNavigate,
|
|
568
|
+
LinkComponent,
|
|
569
|
+
className
|
|
570
|
+
}) {
|
|
571
|
+
const Link = LinkComponent ?? DefaultLink;
|
|
572
|
+
const [open, setOpen] = React3.useState(false);
|
|
573
|
+
const { items, loading, ensureLoaded } = useExpandableItems(subItems, loadSubItems);
|
|
574
|
+
const activeSet = React3.useMemo(() => new Set(activeSubIds ?? []), [activeSubIds]);
|
|
575
|
+
const triggerRef = React3.useRef(null);
|
|
576
|
+
const closeTimer = React3.useRef(null);
|
|
577
|
+
const [coords, setCoords] = React3.useState(null);
|
|
578
|
+
React3.useEffect(() => () => {
|
|
579
|
+
if (closeTimer.current) clearTimeout(closeTimer.current);
|
|
580
|
+
}, []);
|
|
581
|
+
const subLink = (item) => {
|
|
582
|
+
const FIcon = item.icon;
|
|
583
|
+
const active = activeSet.has(item.id);
|
|
584
|
+
return /* @__PURE__ */ jsxs2(
|
|
585
|
+
Link,
|
|
586
|
+
{
|
|
587
|
+
href: item.href,
|
|
588
|
+
to: item.href,
|
|
589
|
+
onClick: onNavigate,
|
|
590
|
+
...item.prefetch !== void 0 ? { prefetch: item.prefetch } : {},
|
|
591
|
+
className: cn(
|
|
592
|
+
"flex h-8 items-center gap-2 rounded-md px-2.5 text-[12px] transition-colors",
|
|
593
|
+
active ? "bg-[var(--accent-surface-strong)] font-medium text-[var(--accent-text)]" : "text-muted-foreground hover:bg-[var(--accent-surface-soft)] hover:text-foreground"
|
|
594
|
+
),
|
|
595
|
+
children: [
|
|
596
|
+
FIcon ? /* @__PURE__ */ jsx3(FIcon, { className: "h-4 w-4 shrink-0" }) : null,
|
|
597
|
+
/* @__PURE__ */ jsx3("span", { className: "truncate", children: item.label })
|
|
598
|
+
]
|
|
599
|
+
},
|
|
600
|
+
item.id
|
|
601
|
+
);
|
|
602
|
+
};
|
|
603
|
+
const list = loading ? /* @__PURE__ */ jsx3(SubItemsSkeleton, {}) : items && items.length > 0 ? items.map(subLink) : /* @__PURE__ */ jsx3("p", { className: "px-2.5 py-1.5 text-xs text-muted-foreground", children: emptyLabel });
|
|
604
|
+
if (!showLabel) {
|
|
605
|
+
const triggerClasses = cn(
|
|
606
|
+
"relative flex h-9 w-9 items-center justify-center rounded-md transition-colors duration-150",
|
|
607
|
+
"focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
608
|
+
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"
|
|
609
|
+
);
|
|
610
|
+
const openFlyout = () => {
|
|
611
|
+
if (closeTimer.current) {
|
|
612
|
+
clearTimeout(closeTimer.current);
|
|
613
|
+
closeTimer.current = null;
|
|
614
|
+
}
|
|
615
|
+
ensureLoaded();
|
|
616
|
+
const el = triggerRef.current;
|
|
617
|
+
if (el) {
|
|
618
|
+
const r = el.getBoundingClientRect();
|
|
619
|
+
const m = 8;
|
|
620
|
+
const left = r.right + m;
|
|
621
|
+
const spaceBelow = window.innerHeight - r.top - m;
|
|
622
|
+
const spaceAbove = r.bottom - m;
|
|
623
|
+
setCoords(
|
|
624
|
+
spaceBelow >= spaceAbove ? { left, top: r.top, maxHeight: spaceBelow } : { left, bottom: window.innerHeight - r.bottom, maxHeight: spaceAbove }
|
|
625
|
+
);
|
|
626
|
+
}
|
|
627
|
+
setOpen(true);
|
|
628
|
+
};
|
|
629
|
+
const scheduleClose = () => {
|
|
630
|
+
if (closeTimer.current) clearTimeout(closeTimer.current);
|
|
631
|
+
closeTimer.current = setTimeout(() => setOpen(false), 140);
|
|
632
|
+
};
|
|
633
|
+
const cancelClose = () => {
|
|
634
|
+
if (closeTimer.current) {
|
|
635
|
+
clearTimeout(closeTimer.current);
|
|
636
|
+
closeTimer.current = null;
|
|
637
|
+
}
|
|
638
|
+
};
|
|
639
|
+
return /* @__PURE__ */ jsxs2(
|
|
640
|
+
"div",
|
|
641
|
+
{
|
|
642
|
+
ref: triggerRef,
|
|
643
|
+
className: cn("relative", className),
|
|
644
|
+
onMouseEnter: openFlyout,
|
|
645
|
+
onMouseLeave: scheduleClose,
|
|
646
|
+
onFocusCapture: openFlyout,
|
|
647
|
+
onBlurCapture: (e) => {
|
|
648
|
+
if (!e.currentTarget.contains(e.relatedTarget)) scheduleClose();
|
|
649
|
+
},
|
|
650
|
+
children: [
|
|
651
|
+
href ? /* @__PURE__ */ jsx3(Link, { href, to: href, onClick: onNavigate, "aria-label": label, className: triggerClasses, children: /* @__PURE__ */ jsx3(Icon, { className: "h-[17px] w-[17px] shrink-0" }) }) : /* @__PURE__ */ jsx3("button", { type: "button", "aria-label": label, "aria-haspopup": "menu", "aria-expanded": open, className: triggerClasses, children: /* @__PURE__ */ jsx3(Icon, { className: "h-[17px] w-[17px] shrink-0" }) }),
|
|
652
|
+
open && coords !== null && typeof document !== "undefined" && createPortal2(
|
|
653
|
+
/* @__PURE__ */ jsxs2(
|
|
654
|
+
"div",
|
|
655
|
+
{
|
|
656
|
+
role: "menu",
|
|
657
|
+
style: {
|
|
658
|
+
position: "fixed",
|
|
659
|
+
left: coords.left,
|
|
660
|
+
top: coords.top,
|
|
661
|
+
bottom: coords.bottom,
|
|
662
|
+
maxHeight: coords.maxHeight
|
|
663
|
+
},
|
|
664
|
+
onMouseEnter: cancelClose,
|
|
665
|
+
onMouseLeave: scheduleClose,
|
|
666
|
+
onClickCapture: (e) => {
|
|
667
|
+
if (e.target.closest("a")) setOpen(false);
|
|
668
|
+
},
|
|
669
|
+
className: cn("z-[70] flex w-60 flex-col overflow-hidden p-1.5", RAIL_FLOATING_SURFACE),
|
|
670
|
+
children: [
|
|
671
|
+
/* @__PURE__ */ jsx3("p", { className: "shrink-0 px-2 pb-1 pt-1 text-[10px] font-semibold uppercase tracking-wider text-muted-foreground/70 select-none", children: label }),
|
|
672
|
+
/* @__PURE__ */ jsx3("div", { className: "flex min-h-0 flex-1 flex-col gap-0.5 overflow-y-auto", children: list })
|
|
673
|
+
]
|
|
674
|
+
}
|
|
675
|
+
),
|
|
676
|
+
document.body
|
|
677
|
+
)
|
|
678
|
+
]
|
|
679
|
+
}
|
|
680
|
+
);
|
|
681
|
+
}
|
|
682
|
+
const toggle = () => {
|
|
683
|
+
setOpen((v) => {
|
|
684
|
+
const next = !v;
|
|
685
|
+
if (next) ensureLoaded();
|
|
686
|
+
return next;
|
|
687
|
+
});
|
|
688
|
+
};
|
|
689
|
+
return /* @__PURE__ */ jsxs2("div", { className: cn("w-full", className), children: [
|
|
690
|
+
/* @__PURE__ */ jsxs2(
|
|
691
|
+
"div",
|
|
692
|
+
{
|
|
693
|
+
className: cn(
|
|
694
|
+
"group/exp relative flex h-9 w-full items-center rounded-md transition-colors duration-150",
|
|
695
|
+
isActive ? "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"
|
|
696
|
+
),
|
|
697
|
+
children: [
|
|
698
|
+
/* @__PURE__ */ jsxs2(
|
|
699
|
+
"button",
|
|
700
|
+
{
|
|
701
|
+
type: "button",
|
|
702
|
+
onClick: toggle,
|
|
703
|
+
"aria-expanded": open,
|
|
704
|
+
"aria-label": open ? `Collapse ${label}` : `Expand ${label}`,
|
|
705
|
+
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",
|
|
706
|
+
children: [
|
|
707
|
+
/* @__PURE__ */ jsx3(
|
|
708
|
+
Icon,
|
|
709
|
+
{
|
|
710
|
+
className: cn(
|
|
711
|
+
"h-[17px] w-[17px] shrink-0 transition-opacity duration-150",
|
|
712
|
+
open ? "opacity-0" : "opacity-100 group-hover/exp:opacity-0"
|
|
713
|
+
)
|
|
714
|
+
}
|
|
715
|
+
),
|
|
716
|
+
/* @__PURE__ */ jsx3(
|
|
717
|
+
ChevronRightIcon,
|
|
718
|
+
{
|
|
719
|
+
className: cn(
|
|
720
|
+
"absolute h-4 w-4 transition-all duration-150",
|
|
721
|
+
open ? "rotate-90 opacity-100" : "opacity-0 group-hover/exp:opacity-100"
|
|
722
|
+
)
|
|
723
|
+
}
|
|
724
|
+
)
|
|
725
|
+
]
|
|
726
|
+
}
|
|
727
|
+
),
|
|
728
|
+
href ? /* @__PURE__ */ jsx3(
|
|
729
|
+
Link,
|
|
730
|
+
{
|
|
731
|
+
href,
|
|
732
|
+
to: href,
|
|
733
|
+
onClick: onNavigate,
|
|
734
|
+
className: "flex h-9 min-w-0 flex-1 items-center pr-2.5 text-[13.5px] font-medium",
|
|
735
|
+
children: /* @__PURE__ */ jsx3("span", { className: "truncate", children: label })
|
|
736
|
+
}
|
|
737
|
+
) : /* @__PURE__ */ jsx3(
|
|
738
|
+
"button",
|
|
739
|
+
{
|
|
740
|
+
type: "button",
|
|
741
|
+
onClick: toggle,
|
|
742
|
+
className: "flex h-9 min-w-0 flex-1 items-center pr-2.5 text-left text-[13.5px] font-medium",
|
|
743
|
+
children: /* @__PURE__ */ jsx3("span", { className: "truncate", children: label })
|
|
744
|
+
}
|
|
745
|
+
)
|
|
746
|
+
]
|
|
747
|
+
}
|
|
748
|
+
),
|
|
749
|
+
open && /* @__PURE__ */ jsx3("div", { className: "mt-0.5 flex flex-col gap-0.5 pl-3", children: list })
|
|
750
|
+
] });
|
|
751
|
+
}
|
|
422
752
|
function RailModeButton({ mode, icon, label, badge, className, showLabel }) {
|
|
423
753
|
const { panelOpen, mode: currentMode, switchMode } = useSidebar();
|
|
424
754
|
return /* @__PURE__ */ jsx3(
|
|
@@ -468,6 +798,58 @@ function SidebarContent({ children, className }) {
|
|
|
468
798
|
}
|
|
469
799
|
);
|
|
470
800
|
}
|
|
801
|
+
var APPEARANCE_META = {
|
|
802
|
+
light: { label: "Light", Icon: SunIcon },
|
|
803
|
+
dark: { label: "Dark", Icon: MoonIcon },
|
|
804
|
+
system: { label: "System", Icon: Monitor }
|
|
805
|
+
};
|
|
806
|
+
function AppearanceMenuSection({ appearance, divider = true }) {
|
|
807
|
+
const modes = appearance.modes ?? ["light", "dark", "system"];
|
|
808
|
+
const [systemDark, setSystemDark] = React3.useState(false);
|
|
809
|
+
React3.useEffect(() => {
|
|
810
|
+
if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
|
|
811
|
+
const mq = window.matchMedia("(prefers-color-scheme: dark)");
|
|
812
|
+
setSystemDark(mq.matches);
|
|
813
|
+
const onChange = () => setSystemDark(mq.matches);
|
|
814
|
+
mq.addEventListener("change", onChange);
|
|
815
|
+
return () => mq.removeEventListener("change", onChange);
|
|
816
|
+
}, []);
|
|
817
|
+
const resolved = appearance.value === "system" ? systemDark ? "dark" : "light" : appearance.value;
|
|
818
|
+
const TriggerIcon = resolved === "dark" ? MoonIcon : SunIcon;
|
|
819
|
+
const caption = appearance.value === "system" ? `System (${resolved === "dark" ? "Dark" : "Light"})` : APPEARANCE_META[appearance.value].label;
|
|
820
|
+
return /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
821
|
+
divider && /* @__PURE__ */ jsx3(DropdownMenuSeparator, {}),
|
|
822
|
+
/* @__PURE__ */ jsxs2(DropdownMenuSub, { children: [
|
|
823
|
+
/* @__PURE__ */ jsxs2(DropdownMenuSubTrigger, { children: [
|
|
824
|
+
/* @__PURE__ */ jsx3("span", { "aria-hidden": "true", className: "mr-2 inline-flex shrink-0", children: /* @__PURE__ */ jsx3(TriggerIcon, { className: "h-4 w-4" }) }),
|
|
825
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex min-w-0 flex-col leading-tight", children: [
|
|
826
|
+
/* @__PURE__ */ jsx3("span", { children: "Appearance" }),
|
|
827
|
+
/* @__PURE__ */ jsx3("span", { className: "text-xs text-muted-foreground", children: caption })
|
|
828
|
+
] })
|
|
829
|
+
] }),
|
|
830
|
+
/* @__PURE__ */ jsx3(DropdownMenuSubContent, { sideOffset: 6, className: "min-w-[12rem]", children: modes.map((m) => {
|
|
831
|
+
const { label, Icon } = APPEARANCE_META[m];
|
|
832
|
+
const active = appearance.value === m;
|
|
833
|
+
return /* @__PURE__ */ jsxs2(
|
|
834
|
+
DropdownMenuItem,
|
|
835
|
+
{
|
|
836
|
+
onSelect: (e) => {
|
|
837
|
+
e.preventDefault();
|
|
838
|
+
appearance.onChange(m);
|
|
839
|
+
},
|
|
840
|
+
className: "gap-3 py-2 text-[14px]",
|
|
841
|
+
children: [
|
|
842
|
+
/* @__PURE__ */ jsx3("span", { "aria-hidden": "true", className: "inline-flex shrink-0", children: /* @__PURE__ */ jsx3(Icon, { className: "h-[18px] w-[18px]" }) }),
|
|
843
|
+
/* @__PURE__ */ jsx3("span", { className: "flex-1", children: label }),
|
|
844
|
+
active && /* @__PURE__ */ jsx3("span", { "aria-hidden": "true", className: "inline-flex shrink-0 text-[var(--accent-text)]", children: /* @__PURE__ */ jsx3(Check, { className: "h-[18px] w-[18px]" }) })
|
|
845
|
+
]
|
|
846
|
+
},
|
|
847
|
+
m
|
|
848
|
+
);
|
|
849
|
+
}) })
|
|
850
|
+
] })
|
|
851
|
+
] });
|
|
852
|
+
}
|
|
471
853
|
function ProfileAvatar({
|
|
472
854
|
user,
|
|
473
855
|
isLoading = false,
|
|
@@ -477,6 +859,7 @@ function ProfileAvatar({
|
|
|
477
859
|
children,
|
|
478
860
|
className,
|
|
479
861
|
showDetails = false,
|
|
862
|
+
appearance,
|
|
480
863
|
LinkComponent
|
|
481
864
|
}) {
|
|
482
865
|
const Link = LinkComponent ?? DefaultLink;
|
|
@@ -501,7 +884,7 @@ function ProfileAvatar({
|
|
|
501
884
|
]
|
|
502
885
|
}
|
|
503
886
|
) }),
|
|
504
|
-
/* @__PURE__ */ jsxs2(DropdownMenuContent, { side: "
|
|
887
|
+
/* @__PURE__ */ jsxs2(DropdownMenuContent, { side: "top", align: "start", sideOffset: 8, className: "w-72", children: [
|
|
505
888
|
/* @__PURE__ */ jsx3(DropdownMenuLabel, { className: "p-0 font-normal", children: /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-3 px-2 py-3", children: [
|
|
506
889
|
/* @__PURE__ */ jsxs2(Avatar, { className: "h-12 w-12 shrink-0", children: [
|
|
507
890
|
user?.avatarUrl && /* @__PURE__ */ jsx3(AvatarImage, { src: user.avatarUrl, alt: "" }),
|
|
@@ -521,6 +904,7 @@ function ProfileAvatar({
|
|
|
521
904
|
] }) }),
|
|
522
905
|
/* @__PURE__ */ jsx3(DropdownMenuSeparator, {}),
|
|
523
906
|
children,
|
|
907
|
+
appearance && /* @__PURE__ */ jsx3(AppearanceMenuSection, { appearance, divider: Boolean(children) }),
|
|
524
908
|
onSettingsClick ? /* @__PURE__ */ jsxs2(DropdownMenuItem, { onClick: onSettingsClick, children: [
|
|
525
909
|
/* @__PURE__ */ jsx3(SettingsIcon, { className: "mr-2 h-4 w-4", "aria-hidden": "true" }),
|
|
526
910
|
"Settings"
|
|
@@ -540,7 +924,7 @@ function ProfileAvatar({
|
|
|
540
924
|
}
|
|
541
925
|
|
|
542
926
|
// src/dashboard/credit-balance.tsx
|
|
543
|
-
import * as
|
|
927
|
+
import * as React4 from "react";
|
|
544
928
|
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
545
929
|
function CreditBalance({
|
|
546
930
|
amount,
|
|
@@ -549,7 +933,7 @@ function CreditBalance({
|
|
|
549
933
|
quickAmounts = [10, 25, 100],
|
|
550
934
|
className
|
|
551
935
|
}) {
|
|
552
|
-
const [topUpValue, setTopUpValue] =
|
|
936
|
+
const [topUpValue, setTopUpValue] = React4.useState("50.00");
|
|
553
937
|
return /* @__PURE__ */ jsxs3(
|
|
554
938
|
"div",
|
|
555
939
|
{
|
|
@@ -679,12 +1063,12 @@ function OutOfCreditsModal({
|
|
|
679
1063
|
}
|
|
680
1064
|
|
|
681
1065
|
// src/dashboard/cluster-status-bar.tsx
|
|
682
|
-
import * as
|
|
1066
|
+
import * as React5 from "react";
|
|
683
1067
|
import { Fragment as Fragment4, jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
684
1068
|
function ClusterStatusBar({ items, latency, className }) {
|
|
685
1069
|
if (!items?.length) return null;
|
|
686
1070
|
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: [
|
|
687
|
-
items.map((item, i) => /* @__PURE__ */ jsxs5(
|
|
1071
|
+
items.map((item, i) => /* @__PURE__ */ jsxs5(React5.Fragment, { children: [
|
|
688
1072
|
i > 0 && /* @__PURE__ */ jsx6("span", { "aria-hidden": true, className: "h-5 w-px shrink-0 bg-border" }),
|
|
689
1073
|
/* @__PURE__ */ jsxs5("div", { className: "flex shrink-0 items-center gap-2", children: [
|
|
690
1074
|
item.icon ? /* @__PURE__ */ jsx6("span", { className: "flex shrink-0 items-center text-[var(--md3-primary)] [&_svg]:h-[18px] [&_svg]:w-[18px]", children: item.icon }) : null,
|
|
@@ -776,7 +1160,7 @@ function ResourceSnapshot({
|
|
|
776
1160
|
}
|
|
777
1161
|
|
|
778
1162
|
// src/dashboard/activity-feed.tsx
|
|
779
|
-
import * as
|
|
1163
|
+
import * as React6 from "react";
|
|
780
1164
|
import { Skeleton as Skeleton3 } from "@tangle-network/ui/primitives";
|
|
781
1165
|
import { timeAgo } from "@tangle-network/ui/utils";
|
|
782
1166
|
import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
@@ -789,7 +1173,7 @@ function ActivityFeed({
|
|
|
789
1173
|
emptyLabel = "No recent activity",
|
|
790
1174
|
className
|
|
791
1175
|
}) {
|
|
792
|
-
const sorted =
|
|
1176
|
+
const sorted = React6.useMemo(
|
|
793
1177
|
() => [...items].sort((a, b) => (b.timestamp ?? 0) - (a.timestamp ?? 0)).slice(0, maxItems),
|
|
794
1178
|
[items, maxItems]
|
|
795
1179
|
);
|
|
@@ -1103,7 +1487,7 @@ function NewSandboxCard({ onClick, className }) {
|
|
|
1103
1487
|
}
|
|
1104
1488
|
|
|
1105
1489
|
// src/dashboard/sandbox-table.tsx
|
|
1106
|
-
import * as
|
|
1490
|
+
import * as React7 from "react";
|
|
1107
1491
|
import {
|
|
1108
1492
|
Activity as Activity2,
|
|
1109
1493
|
BarChart2 as BarChart22,
|
|
@@ -1378,7 +1762,7 @@ function SandboxTable({
|
|
|
1378
1762
|
children: /* @__PURE__ */ jsx11(MoreVertical2, { className: "h-4 w-4" })
|
|
1379
1763
|
}
|
|
1380
1764
|
) }),
|
|
1381
|
-
/* @__PURE__ */ jsx11(DropdownMenuContent3, { align: "end", className: "min-w-[180px]", children: overflowSections.map((section, sectionIdx) => /* @__PURE__ */ jsxs10(
|
|
1765
|
+
/* @__PURE__ */ jsx11(DropdownMenuContent3, { align: "end", className: "min-w-[180px]", children: overflowSections.map((section, sectionIdx) => /* @__PURE__ */ jsxs10(React7.Fragment, { children: [
|
|
1382
1766
|
sectionIdx > 0 && /* @__PURE__ */ jsx11(DropdownMenuSeparator3, {}),
|
|
1383
1767
|
section
|
|
1384
1768
|
] }, sectionIdx)) })
|
|
@@ -1466,7 +1850,7 @@ function InvoiceTable({ invoices, onExportAll, onLoadMore, onViewInvoice, hasMor
|
|
|
1466
1850
|
}
|
|
1467
1851
|
|
|
1468
1852
|
// src/dashboard/plan-cards.tsx
|
|
1469
|
-
import { Check } from "lucide-react";
|
|
1853
|
+
import { Check as Check2 } from "lucide-react";
|
|
1470
1854
|
import { jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
1471
1855
|
function PlanCards({ plans, className }) {
|
|
1472
1856
|
return /* @__PURE__ */ jsxs12("section", { className, children: [
|
|
@@ -1492,7 +1876,7 @@ function PlanCards({ plans, className }) {
|
|
|
1492
1876
|
] })
|
|
1493
1877
|
] }),
|
|
1494
1878
|
/* @__PURE__ */ jsx13("ul", { className: "space-y-2 mb-5 text-sm text-muted-foreground", children: plan.features.map((f, i) => /* @__PURE__ */ jsxs12("li", { className: "flex items-center gap-2", children: [
|
|
1495
|
-
/* @__PURE__ */ jsx13(
|
|
1879
|
+
/* @__PURE__ */ jsx13(Check2, { className: "h-3.5 w-3.5 text-primary shrink-0" }),
|
|
1496
1880
|
f.text
|
|
1497
1881
|
] }, i)) }),
|
|
1498
1882
|
/* @__PURE__ */ jsx13(
|
|
@@ -1515,16 +1899,9 @@ function PlanCards({ plans, className }) {
|
|
|
1515
1899
|
}
|
|
1516
1900
|
|
|
1517
1901
|
// src/dashboard/dashboard-layout.tsx
|
|
1518
|
-
import * as
|
|
1519
|
-
import { Plus as Plus2, Bell
|
|
1902
|
+
import * as React8 from "react";
|
|
1903
|
+
import { Plus as Plus2, Bell } from "lucide-react";
|
|
1520
1904
|
import { Fragment as Fragment9, jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
1521
|
-
function SettingsIconSmall({ className }) {
|
|
1522
|
-
return /* @__PURE__ */ jsxs13("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, children: [
|
|
1523
|
-
/* @__PURE__ */ jsx14("title", { children: "Settings" }),
|
|
1524
|
-
/* @__PURE__ */ jsx14("path", { d: "M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z" }),
|
|
1525
|
-
/* @__PURE__ */ jsx14("circle", { cx: "12", cy: "12", r: "3" })
|
|
1526
|
-
] });
|
|
1527
|
-
}
|
|
1528
1905
|
function MenuIcon({ className }) {
|
|
1529
1906
|
return /* @__PURE__ */ jsxs13("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, children: [
|
|
1530
1907
|
/* @__PURE__ */ jsx14("title", { children: "Menu icon" }),
|
|
@@ -1574,19 +1951,18 @@ function DashboardLayoutInner({
|
|
|
1574
1951
|
topBarLeading,
|
|
1575
1952
|
LinkComponent = DefaultLink2,
|
|
1576
1953
|
logoHref = "/",
|
|
1577
|
-
onLogoClick,
|
|
1578
|
-
logoAriaLabel = "Toggle navigation",
|
|
1579
1954
|
labeledRail = false,
|
|
1580
1955
|
footer,
|
|
1581
1956
|
railFooter,
|
|
1582
1957
|
profileMenuItems,
|
|
1958
|
+
appearance,
|
|
1583
1959
|
notifications: notifData
|
|
1584
1960
|
}) {
|
|
1585
1961
|
const Link = LinkComponent;
|
|
1586
|
-
const [mobileMenuOpen, setMobileMenuOpen] =
|
|
1587
|
-
const [notificationsOpen, setNotificationsOpen] =
|
|
1588
|
-
const notifRef =
|
|
1589
|
-
|
|
1962
|
+
const [mobileMenuOpen, setMobileMenuOpen] = React8.useState(false);
|
|
1963
|
+
const [notificationsOpen, setNotificationsOpen] = React8.useState(false);
|
|
1964
|
+
const notifRef = React8.useRef(null);
|
|
1965
|
+
React8.useEffect(() => {
|
|
1590
1966
|
if (!notificationsOpen) return;
|
|
1591
1967
|
const handler = (e) => {
|
|
1592
1968
|
if (notifRef.current && !notifRef.current.contains(e.target)) {
|
|
@@ -1604,123 +1980,87 @@ function DashboardLayoutInner({
|
|
|
1604
1980
|
};
|
|
1605
1981
|
}, [notificationsOpen]);
|
|
1606
1982
|
const { contentMargin, hidden, mode, hasPanels, panelOpen, toggleRail, railCollapsed } = useSidebar();
|
|
1607
|
-
const modeSet =
|
|
1608
|
-
const sidebarUser =
|
|
1983
|
+
const modeSet = React8.useMemo(() => new Set(modeItems), [modeItems]);
|
|
1984
|
+
const sidebarUser = React8.useMemo(
|
|
1609
1985
|
() => user ? { email: user.email, name: user.name, tier: user.tier, avatarUrl: user.avatarUrl } : void 0,
|
|
1610
1986
|
[user?.email, user?.name, user?.tier, user?.avatarUrl]
|
|
1611
1987
|
);
|
|
1612
1988
|
const activePanel = panels.find((p) => p.mode === mode);
|
|
1613
|
-
const buildSidebarContent =
|
|
1989
|
+
const buildSidebarContent = React8.useCallback(
|
|
1614
1990
|
(showLabels, allowCollapse) => /* @__PURE__ */ jsxs13(Fragment9, { children: [
|
|
1615
1991
|
/* @__PURE__ */ jsxs13(SidebarRail, { wide: showLabels, children: [
|
|
1616
|
-
/* @__PURE__ */ jsx14(
|
|
1617
|
-
|
|
1992
|
+
/* @__PURE__ */ jsx14(
|
|
1993
|
+
RailHeader,
|
|
1618
1994
|
{
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1995
|
+
brand: /* @__PURE__ */ jsx14(Logo, { variant, size: "sm", iconOnly: true }),
|
|
1996
|
+
brandHref: logoHref,
|
|
1997
|
+
collapsed: !showLabels,
|
|
1998
|
+
onToggle: toggleRail,
|
|
1999
|
+
collapsible: allowCollapse,
|
|
2000
|
+
LinkComponent: Link
|
|
1624
2001
|
}
|
|
1625
|
-
)
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
// through to the plain logo link. Expanded: full logotype with a
|
|
1629
|
-
// collapse chevron that fades in on hover. Collapsed: the mark,
|
|
1630
|
-
// with an expand chevron overlay on hover.
|
|
1631
|
-
/* @__PURE__ */ jsxs13(
|
|
1632
|
-
"button",
|
|
1633
|
-
{
|
|
1634
|
-
type: "button",
|
|
1635
|
-
onClick: toggleRail,
|
|
1636
|
-
"aria-label": railCollapsed ? "Expand navigation" : "Collapse navigation",
|
|
1637
|
-
"aria-expanded": !railCollapsed,
|
|
1638
|
-
className: cn(
|
|
1639
|
-
"group/logo relative flex items-center gap-2 rounded-md p-1 transition-colors hover:bg-surface-container-high",
|
|
1640
|
-
showLabels && "w-full"
|
|
1641
|
-
),
|
|
1642
|
-
children: [
|
|
1643
|
-
/* @__PURE__ */ jsx14(Logo, { variant, size: "sm", iconOnly: !showLabels }),
|
|
1644
|
-
showLabels ? /* @__PURE__ */ jsx14(ChevronsLeft, { className: "ml-auto h-4 w-4 shrink-0 text-muted-foreground opacity-0 transition-opacity group-hover/logo:opacity-100" }) : /* @__PURE__ */ jsx14("span", { className: "absolute inset-0 flex items-center justify-center rounded-md bg-surface-container-high opacity-0 transition-opacity group-hover/logo:opacity-100", children: /* @__PURE__ */ jsx14(ChevronsRight, { className: "h-4 w-4 text-foreground" }) })
|
|
1645
|
-
]
|
|
1646
|
-
}
|
|
1647
|
-
)
|
|
1648
|
-
) : /* @__PURE__ */ jsx14(
|
|
1649
|
-
Link,
|
|
2002
|
+
),
|
|
2003
|
+
/* @__PURE__ */ jsx14(
|
|
2004
|
+
SidebarRailNav,
|
|
1650
2005
|
{
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
2006
|
+
className: cn(showLabels ? "px-2" : void 0, !showLabels && allowCollapse && "cursor-pointer"),
|
|
2007
|
+
onClick: !showLabels && allowCollapse ? (e) => {
|
|
2008
|
+
if (e.target === e.currentTarget) toggleRail();
|
|
2009
|
+
} : void 0,
|
|
2010
|
+
children: navItems.map((item, i) => {
|
|
2011
|
+
const isMode = modeSet.has(item.id);
|
|
2012
|
+
const prevIsMode = i > 0 && modeSet.has(navItems[i - 1].id);
|
|
2013
|
+
const showSep = i > 0 && isMode && !prevIsMode;
|
|
2014
|
+
return /* @__PURE__ */ jsxs13(React8.Fragment, { children: [
|
|
2015
|
+
showSep && /* @__PURE__ */ jsx14(
|
|
2016
|
+
RailSeparator,
|
|
2017
|
+
{
|
|
2018
|
+
className: showLabels ? "w-full" : void 0
|
|
2019
|
+
}
|
|
2020
|
+
),
|
|
2021
|
+
isMode ? /* @__PURE__ */ jsx14(
|
|
2022
|
+
RailModeButton,
|
|
2023
|
+
{
|
|
2024
|
+
mode: item.id,
|
|
2025
|
+
icon: item.icon,
|
|
2026
|
+
label: item.label,
|
|
2027
|
+
badge: item.badge,
|
|
2028
|
+
showLabel: showLabels
|
|
2029
|
+
}
|
|
2030
|
+
) : /* @__PURE__ */ jsx14(
|
|
2031
|
+
RailButton,
|
|
2032
|
+
{
|
|
2033
|
+
icon: item.icon,
|
|
2034
|
+
label: item.label,
|
|
2035
|
+
isActive: activeNavId === item.id,
|
|
2036
|
+
showLabel: showLabels,
|
|
2037
|
+
asChild: true,
|
|
2038
|
+
children: /* @__PURE__ */ jsx14(Link, { href: item.href, to: item.href })
|
|
2039
|
+
}
|
|
2040
|
+
)
|
|
2041
|
+
] }, item.id);
|
|
2042
|
+
})
|
|
1655
2043
|
}
|
|
1656
|
-
)
|
|
1657
|
-
/* @__PURE__ */ jsx14(
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
}
|
|
1677
|
-
) : /* @__PURE__ */ jsx14(
|
|
1678
|
-
RailButton,
|
|
1679
|
-
{
|
|
1680
|
-
icon: item.icon,
|
|
1681
|
-
label: item.label,
|
|
1682
|
-
isActive: activeNavId === item.id,
|
|
1683
|
-
showLabel: showLabels,
|
|
1684
|
-
asChild: true,
|
|
1685
|
-
children: /* @__PURE__ */ jsx14(Link, { href: item.href, to: item.href })
|
|
1686
|
-
}
|
|
1687
|
-
)
|
|
1688
|
-
] }, item.id);
|
|
1689
|
-
}) }),
|
|
1690
|
-
/* @__PURE__ */ jsxs13(SidebarRailFooter, { className: cn(showLabels && "items-stretch px-2"), children: [
|
|
1691
|
-
onSettingsClick ? /* @__PURE__ */ jsx14(RailButton, { icon: SettingsIconSmall, label: "Settings", onClick: onSettingsClick, showLabel: showLabels }) : /* @__PURE__ */ jsx14(RailButton, { icon: SettingsIconSmall, label: "Settings", showLabel: showLabels, asChild: true, children: /* @__PURE__ */ jsx14(Link, { href: settingsHref, to: settingsHref }) }),
|
|
1692
|
-
/* @__PURE__ */ jsx14(RailSeparator, { className: showLabels ? "w-full" : void 0 }),
|
|
1693
|
-
railFooter !== void 0 ? showLabels ? /* @__PURE__ */ jsxs13("div", { className: "flex w-full items-center gap-1", children: [
|
|
1694
|
-
/* @__PURE__ */ jsx14("div", { className: "min-w-0 flex-1", children: /* @__PURE__ */ jsx14(
|
|
1695
|
-
ProfileAvatar,
|
|
1696
|
-
{
|
|
1697
|
-
user: sidebarUser,
|
|
1698
|
-
isLoading,
|
|
1699
|
-
onLogout,
|
|
1700
|
-
onSettingsClick,
|
|
1701
|
-
settingsHref,
|
|
1702
|
-
showDetails: showLabels,
|
|
1703
|
-
LinkComponent,
|
|
1704
|
-
children: profileMenuItems
|
|
1705
|
-
}
|
|
1706
|
-
) }),
|
|
1707
|
-
/* @__PURE__ */ jsx14("div", { className: "shrink-0", children: railFooter })
|
|
1708
|
-
] }) : /* @__PURE__ */ jsxs13("div", { className: "flex flex-col items-center gap-1", children: [
|
|
1709
|
-
railFooter,
|
|
1710
|
-
/* @__PURE__ */ jsx14(
|
|
1711
|
-
ProfileAvatar,
|
|
1712
|
-
{
|
|
1713
|
-
user: sidebarUser,
|
|
1714
|
-
isLoading,
|
|
1715
|
-
onLogout,
|
|
1716
|
-
onSettingsClick,
|
|
1717
|
-
settingsHref,
|
|
1718
|
-
showDetails: showLabels,
|
|
1719
|
-
LinkComponent,
|
|
1720
|
-
children: profileMenuItems
|
|
1721
|
-
}
|
|
1722
|
-
)
|
|
1723
|
-
] }) : /* @__PURE__ */ jsx14(
|
|
2044
|
+
),
|
|
2045
|
+
/* @__PURE__ */ jsx14(SidebarRailFooter, { className: cn("border-t border-[var(--md3-outline-variant)] pt-2", showLabels && "items-stretch px-2"), children: railFooter !== void 0 ? showLabels ? /* @__PURE__ */ jsxs13("div", { className: "flex w-full items-center gap-1", children: [
|
|
2046
|
+
/* @__PURE__ */ jsx14("div", { className: "min-w-0 flex-1", children: /* @__PURE__ */ jsx14(
|
|
2047
|
+
ProfileAvatar,
|
|
2048
|
+
{
|
|
2049
|
+
user: sidebarUser,
|
|
2050
|
+
isLoading,
|
|
2051
|
+
onLogout,
|
|
2052
|
+
onSettingsClick,
|
|
2053
|
+
settingsHref,
|
|
2054
|
+
showDetails: showLabels,
|
|
2055
|
+
appearance,
|
|
2056
|
+
LinkComponent,
|
|
2057
|
+
children: profileMenuItems
|
|
2058
|
+
}
|
|
2059
|
+
) }),
|
|
2060
|
+
/* @__PURE__ */ jsx14("div", { className: "shrink-0", children: railFooter })
|
|
2061
|
+
] }) : /* @__PURE__ */ jsxs13("div", { className: "flex flex-col items-center gap-1", children: [
|
|
2062
|
+
railFooter,
|
|
2063
|
+
/* @__PURE__ */ jsx14(
|
|
1724
2064
|
ProfileAvatar,
|
|
1725
2065
|
{
|
|
1726
2066
|
user: sidebarUser,
|
|
@@ -1729,11 +2069,25 @@ function DashboardLayoutInner({
|
|
|
1729
2069
|
onSettingsClick,
|
|
1730
2070
|
settingsHref,
|
|
1731
2071
|
showDetails: showLabels,
|
|
2072
|
+
appearance,
|
|
1732
2073
|
LinkComponent,
|
|
1733
2074
|
children: profileMenuItems
|
|
1734
2075
|
}
|
|
1735
2076
|
)
|
|
1736
|
-
] })
|
|
2077
|
+
] }) : /* @__PURE__ */ jsx14(
|
|
2078
|
+
ProfileAvatar,
|
|
2079
|
+
{
|
|
2080
|
+
user: sidebarUser,
|
|
2081
|
+
isLoading,
|
|
2082
|
+
onLogout,
|
|
2083
|
+
onSettingsClick,
|
|
2084
|
+
settingsHref,
|
|
2085
|
+
showDetails: showLabels,
|
|
2086
|
+
appearance,
|
|
2087
|
+
LinkComponent,
|
|
2088
|
+
children: profileMenuItems
|
|
2089
|
+
}
|
|
2090
|
+
) })
|
|
1737
2091
|
] }),
|
|
1738
2092
|
panels.length > 0 && /* @__PURE__ */ jsxs13(SidebarPanel, { children: [
|
|
1739
2093
|
/* @__PURE__ */ jsx14(SidebarPanelHeader, { title: activePanel?.title ?? mode }),
|
|
@@ -1744,8 +2098,6 @@ function DashboardLayoutInner({
|
|
|
1744
2098
|
[
|
|
1745
2099
|
Link,
|
|
1746
2100
|
variant,
|
|
1747
|
-
onLogoClick,
|
|
1748
|
-
logoAriaLabel,
|
|
1749
2101
|
logoHref,
|
|
1750
2102
|
labeledRail,
|
|
1751
2103
|
toggleRail,
|
|
@@ -1761,16 +2113,17 @@ function DashboardLayoutInner({
|
|
|
1761
2113
|
onLogout,
|
|
1762
2114
|
LinkComponent,
|
|
1763
2115
|
profileMenuItems,
|
|
2116
|
+
appearance,
|
|
1764
2117
|
panels,
|
|
1765
2118
|
activePanel,
|
|
1766
2119
|
mode
|
|
1767
2120
|
]
|
|
1768
2121
|
);
|
|
1769
|
-
const sidebarContent =
|
|
2122
|
+
const sidebarContent = React8.useMemo(
|
|
1770
2123
|
() => buildSidebarContent(labeledRail && !railCollapsed, labeledRail),
|
|
1771
2124
|
[buildSidebarContent, labeledRail, railCollapsed]
|
|
1772
2125
|
);
|
|
1773
|
-
const mobileSidebarContent =
|
|
2126
|
+
const mobileSidebarContent = React8.useMemo(() => buildSidebarContent(true, false), [buildSidebarContent]);
|
|
1774
2127
|
return /* @__PURE__ */ jsxs13("div", { className: cn("min-h-screen bg-surface text-foreground", className), children: [
|
|
1775
2128
|
/* @__PURE__ */ jsxs13(
|
|
1776
2129
|
"nav",
|
|
@@ -1933,9 +2286,8 @@ function SidebarLayoutInner({
|
|
|
1933
2286
|
onSettingsClick,
|
|
1934
2287
|
settingsHref,
|
|
1935
2288
|
profileMenuItems,
|
|
1936
|
-
|
|
2289
|
+
appearance,
|
|
1937
2290
|
railFooter,
|
|
1938
|
-
railCollapseToggle = "footer",
|
|
1939
2291
|
LinkComponent,
|
|
1940
2292
|
hideBelow,
|
|
1941
2293
|
railLabels = false,
|
|
@@ -1947,26 +2299,46 @@ function SidebarLayoutInner({
|
|
|
1947
2299
|
const Link = LinkComponent ?? DefaultLink3;
|
|
1948
2300
|
const { panelOpen, togglePanel, setPanelOpen, railCollapsed, toggleRail } = useSidebar();
|
|
1949
2301
|
const handleNavClick = closePanelOnNavigate && panelOpen ? () => setPanelOpen(false) : void 0;
|
|
2302
|
+
const expandOnEmptyClick = railLabels && railCollapsed ? (e) => {
|
|
2303
|
+
if (e.target === e.currentTarget) toggleRail();
|
|
2304
|
+
} : void 0;
|
|
1950
2305
|
const hasProfile = user !== void 0 || onLogout !== void 0 || onSettingsClick !== void 0;
|
|
1951
2306
|
const showLabels = railLabels && !railCollapsed;
|
|
1952
2307
|
return /* @__PURE__ */ jsxs14("div", { className: cn("min-h-screen bg-surface text-foreground", className), children: [
|
|
1953
2308
|
/* @__PURE__ */ jsx15("div", { className: cn(hideBelow && HIDE_BELOW_CLASS[hideBelow]), children: /* @__PURE__ */ jsxs14(Sidebar, { className: sidebarClassName, children: [
|
|
1954
2309
|
/* @__PURE__ */ jsxs14(SidebarRail, { children: [
|
|
1955
|
-
(
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
2310
|
+
(logo !== void 0 || railHeaderContent !== void 0 || railLabels) && /* @__PURE__ */ jsx15(
|
|
2311
|
+
RailHeader,
|
|
2312
|
+
{
|
|
2313
|
+
brand: logo,
|
|
2314
|
+
brandHref: logoHref,
|
|
2315
|
+
collapsed: !showLabels,
|
|
2316
|
+
onToggle: toggleRail,
|
|
2317
|
+
collapsible: railLabels,
|
|
2318
|
+
LinkComponent,
|
|
2319
|
+
children: railHeaderContent
|
|
2320
|
+
}
|
|
2321
|
+
),
|
|
2322
|
+
/* @__PURE__ */ jsx15(SidebarRailNav, { className: cn(showLabels ? "px-2" : void 0, expandOnEmptyClick && "cursor-pointer"), onClick: expandOnEmptyClick, children: navItems.map((item) => {
|
|
2323
|
+
if (item.expandable) {
|
|
2324
|
+
return /* @__PURE__ */ jsx15(
|
|
2325
|
+
RailExpandable,
|
|
2326
|
+
{
|
|
2327
|
+
icon: item.icon,
|
|
2328
|
+
label: item.label,
|
|
2329
|
+
href: item.href,
|
|
2330
|
+
isActive: activeId === item.id,
|
|
2331
|
+
showLabel: showLabels,
|
|
2332
|
+
subItems: item.subItems,
|
|
2333
|
+
loadSubItems: item.loadSubItems,
|
|
2334
|
+
activeSubIds: item.subActiveIds,
|
|
2335
|
+
emptyLabel: item.emptyLabel,
|
|
2336
|
+
onNavigate: handleNavClick,
|
|
2337
|
+
LinkComponent
|
|
2338
|
+
},
|
|
2339
|
+
item.id
|
|
2340
|
+
);
|
|
2341
|
+
}
|
|
1970
2342
|
if (item.flyoutItems && item.flyoutItems.length > 0) {
|
|
1971
2343
|
const activeSet = new Set(item.flyoutActiveIds ?? []);
|
|
1972
2344
|
return /* @__PURE__ */ jsx15(
|
|
@@ -2014,7 +2386,7 @@ function SidebarLayoutInner({
|
|
|
2014
2386
|
showLabel: showLabels
|
|
2015
2387
|
},
|
|
2016
2388
|
item.id
|
|
2017
|
-
) : /* @__PURE__ */ jsx15(RailButton, { icon: item.icon, label: item.label, badge: item.badge, isActive: activeId === item.id, showLabel: showLabels, asChild: true, children: /* @__PURE__ */ jsx15(
|
|
2389
|
+
) : /* @__PURE__ */ jsx15(RailButton, { icon: item.icon, label: item.label, badge: item.badge, isActive: activeId === item.id, showLabel: showLabels, variant: item.variant, asChild: true, children: /* @__PURE__ */ jsx15(
|
|
2018
2390
|
Link,
|
|
2019
2391
|
{
|
|
2020
2392
|
href: item.href,
|
|
@@ -2024,32 +2396,22 @@ function SidebarLayoutInner({
|
|
|
2024
2396
|
}
|
|
2025
2397
|
) }, item.id);
|
|
2026
2398
|
}) }),
|
|
2027
|
-
(
|
|
2028
|
-
railLabels && railCollapseToggle === "footer" && /* @__PURE__ */ jsx15(RailCollapseToggle, { collapsed: railCollapsed, showLabel: showLabels, onToggle: toggleRail }),
|
|
2399
|
+
(railFooter !== void 0 || hasProfile) && /* @__PURE__ */ jsxs14(SidebarRailFooter, { className: cn("border-t border-[var(--md3-outline-variant)] pt-2", showLabels && "items-stretch px-2"), children: [
|
|
2029
2400
|
railFooter,
|
|
2030
|
-
hasProfile &&
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
if (!showThemeToggle) return profile;
|
|
2045
|
-
return showLabels ? /* @__PURE__ */ jsxs14("div", { className: "flex w-full items-center gap-1", children: [
|
|
2046
|
-
/* @__PURE__ */ jsx15("div", { className: "min-w-0 flex-1", children: profile }),
|
|
2047
|
-
/* @__PURE__ */ jsx15(RailThemeToggle, {})
|
|
2048
|
-
] }) : /* @__PURE__ */ jsxs14("div", { className: "flex flex-col items-center gap-1", children: [
|
|
2049
|
-
/* @__PURE__ */ jsx15(RailThemeToggle, {}),
|
|
2050
|
-
profile
|
|
2051
|
-
] });
|
|
2052
|
-
})()
|
|
2401
|
+
hasProfile && /* @__PURE__ */ jsx15(
|
|
2402
|
+
ProfileAvatar,
|
|
2403
|
+
{
|
|
2404
|
+
user: user ?? void 0,
|
|
2405
|
+
isLoading,
|
|
2406
|
+
onLogout,
|
|
2407
|
+
onSettingsClick,
|
|
2408
|
+
settingsHref,
|
|
2409
|
+
showDetails: showLabels,
|
|
2410
|
+
appearance,
|
|
2411
|
+
LinkComponent: Link,
|
|
2412
|
+
children: profileMenuItems
|
|
2413
|
+
}
|
|
2414
|
+
)
|
|
2053
2415
|
] })
|
|
2054
2416
|
] }),
|
|
2055
2417
|
panel != null && /* @__PURE__ */ jsx15(SidebarPanel, { children: panel })
|
|
@@ -2083,7 +2445,7 @@ function SidebarLayout({
|
|
|
2083
2445
|
}
|
|
2084
2446
|
|
|
2085
2447
|
// src/dashboard/profile-selector.tsx
|
|
2086
|
-
import { Check as
|
|
2448
|
+
import { Check as Check3, ChevronDown, Plus as Plus3, Settings } from "lucide-react";
|
|
2087
2449
|
import { Button as Button2 } from "@tangle-network/ui/primitives";
|
|
2088
2450
|
import { Badge } from "@tangle-network/ui/primitives";
|
|
2089
2451
|
import {
|
|
@@ -2124,7 +2486,7 @@ function ProfileSelector({
|
|
|
2124
2486
|
className: "flex items-center justify-between",
|
|
2125
2487
|
children: [
|
|
2126
2488
|
/* @__PURE__ */ jsx16("span", { children: placeholder }),
|
|
2127
|
-
!selectedId && /* @__PURE__ */ jsx16(
|
|
2489
|
+
!selectedId && /* @__PURE__ */ jsx16(Check3, { className: "h-4 w-4 text-[var(--surface-success-text)]" })
|
|
2128
2490
|
]
|
|
2129
2491
|
}
|
|
2130
2492
|
),
|
|
@@ -2145,7 +2507,7 @@ function ProfileSelector({
|
|
|
2145
2507
|
profile.extends
|
|
2146
2508
|
] })
|
|
2147
2509
|
] }),
|
|
2148
|
-
selectedId === profile.id && /* @__PURE__ */ jsx16(
|
|
2510
|
+
selectedId === profile.id && /* @__PURE__ */ jsx16(Check3, { className: "h-4 w-4 text-[var(--surface-success-text)]" })
|
|
2149
2511
|
] }),
|
|
2150
2512
|
profile.description && /* @__PURE__ */ jsx16("span", { className: "line-clamp-1 text-muted-foreground text-xs", children: profile.description })
|
|
2151
2513
|
]
|
|
@@ -2167,7 +2529,7 @@ function ProfileSelector({
|
|
|
2167
2529
|
/* @__PURE__ */ jsx16("span", { className: "font-medium", children: profile.name }),
|
|
2168
2530
|
profile.model && /* @__PURE__ */ jsx16(Badge, { variant: "secondary", className: "border-0 text-xs", children: profile.model.split("/").pop() })
|
|
2169
2531
|
] }),
|
|
2170
|
-
selectedId === profile.id && /* @__PURE__ */ jsx16(
|
|
2532
|
+
selectedId === profile.id && /* @__PURE__ */ jsx16(Check3, { className: "h-4 w-4 text-[var(--surface-success-text)]" })
|
|
2171
2533
|
] }),
|
|
2172
2534
|
profile.description && /* @__PURE__ */ jsx16("span", { className: "line-clamp-1 text-muted-foreground text-xs", children: profile.description }),
|
|
2173
2535
|
showMetrics && profile.metrics && profile.metrics.total_runs > 0 && /* @__PURE__ */ jsxs15("div", { className: "flex gap-3 text-muted-foreground text-xs", children: [
|
|
@@ -2285,7 +2647,7 @@ function ProfileComparison({
|
|
|
2285
2647
|
}
|
|
2286
2648
|
|
|
2287
2649
|
// src/dashboard/metric-area-chart.tsx
|
|
2288
|
-
import * as
|
|
2650
|
+
import * as React9 from "react";
|
|
2289
2651
|
import { jsx as jsx17, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
2290
2652
|
var TONE_VARS = {
|
|
2291
2653
|
primary: "var(--brand-primary, hsl(var(--primary)))",
|
|
@@ -2332,7 +2694,7 @@ function MetricAreaChart({
|
|
|
2332
2694
|
emptyState,
|
|
2333
2695
|
className
|
|
2334
2696
|
}) {
|
|
2335
|
-
const gradientId =
|
|
2697
|
+
const gradientId = React9.useId();
|
|
2336
2698
|
const width = 400;
|
|
2337
2699
|
const values = points.map((p) => p.value).filter((v) => v !== null);
|
|
2338
2700
|
const latest = values.length > 0 ? values[values.length - 1] : null;
|
|
@@ -2392,7 +2754,7 @@ function MetricAreaChart({
|
|
|
2392
2754
|
/* @__PURE__ */ jsx17("stop", { offset: "0%", stopColor: color, stopOpacity: 0.28 }),
|
|
2393
2755
|
/* @__PURE__ */ jsx17("stop", { offset: "100%", stopColor: color, stopOpacity: 0.02 })
|
|
2394
2756
|
] }) }),
|
|
2395
|
-
segments.map((segment) => /* @__PURE__ */ jsxs16(
|
|
2757
|
+
segments.map((segment) => /* @__PURE__ */ jsxs16(React9.Fragment, { children: [
|
|
2396
2758
|
/* @__PURE__ */ jsx17("path", { d: segment.area, fill: `url(#${gradientId})` }),
|
|
2397
2759
|
/* @__PURE__ */ jsx17(
|
|
2398
2760
|
"path",
|
|
@@ -2421,7 +2783,7 @@ function MetricAreaChart({
|
|
|
2421
2783
|
|
|
2422
2784
|
// src/dashboard/variant-list.tsx
|
|
2423
2785
|
import {
|
|
2424
|
-
Check as
|
|
2786
|
+
Check as Check4,
|
|
2425
2787
|
CheckCircle2,
|
|
2426
2788
|
Clock as Clock3,
|
|
2427
2789
|
ExternalLink as ExternalLink2,
|
|
@@ -2568,7 +2930,7 @@ function VariantList({
|
|
|
2568
2930
|
},
|
|
2569
2931
|
disabled: isActioning === variant.id,
|
|
2570
2932
|
children: [
|
|
2571
|
-
/* @__PURE__ */ jsx18(
|
|
2933
|
+
/* @__PURE__ */ jsx18(Check4, { className: "mr-1 h-3 w-3" }),
|
|
2572
2934
|
"Accept"
|
|
2573
2935
|
]
|
|
2574
2936
|
}
|
|
@@ -2617,14 +2979,14 @@ function VariantList({
|
|
|
2617
2979
|
|
|
2618
2980
|
// src/dashboard/system-logs.tsx
|
|
2619
2981
|
import { Terminal as Terminal2 } from "lucide-react";
|
|
2620
|
-
import { useEffect as
|
|
2982
|
+
import { useEffect as useEffect4, useRef as useRef4, useState as useState6 } from "react";
|
|
2621
2983
|
import { jsx as jsx19, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
2622
2984
|
function SystemLogsViewer({ apiUrl, token, className }) {
|
|
2623
|
-
const [logs, setLogs] =
|
|
2624
|
-
const [error, setError] =
|
|
2625
|
-
const [isFollowing, setIsFollowing] =
|
|
2626
|
-
const scrollRef =
|
|
2627
|
-
|
|
2985
|
+
const [logs, setLogs] = useState6([]);
|
|
2986
|
+
const [error, setError] = useState6(null);
|
|
2987
|
+
const [isFollowing, setIsFollowing] = useState6(true);
|
|
2988
|
+
const scrollRef = useRef4(null);
|
|
2989
|
+
useEffect4(() => {
|
|
2628
2990
|
let timeoutId;
|
|
2629
2991
|
let backoff = 2e3;
|
|
2630
2992
|
const controller = new AbortController();
|
|
@@ -2660,7 +3022,7 @@ function SystemLogsViewer({ apiUrl, token, className }) {
|
|
|
2660
3022
|
clearTimeout(timeoutId);
|
|
2661
3023
|
};
|
|
2662
3024
|
}, [apiUrl, token]);
|
|
2663
|
-
|
|
3025
|
+
useEffect4(() => {
|
|
2664
3026
|
if (isFollowing && scrollRef.current) {
|
|
2665
3027
|
scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
|
|
2666
3028
|
}
|
|
@@ -2867,14 +3229,14 @@ function GitPanel({ status, log, loading = false, onRefresh, className }) {
|
|
|
2867
3229
|
}
|
|
2868
3230
|
|
|
2869
3231
|
// src/dashboard/ports-list.tsx
|
|
2870
|
-
import * as
|
|
2871
|
-
import { Copy as Copy3, Check as
|
|
3232
|
+
import * as React11 from "react";
|
|
3233
|
+
import { Copy as Copy3, Check as Check5, Globe, Plus as Plus4, Trash2 as Trash23 } from "lucide-react";
|
|
2872
3234
|
import { jsx as jsx22, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
2873
3235
|
function PortsList({ ports, onExposePort, onRemovePort, isExposing = false, className }) {
|
|
2874
|
-
const [newPort, setNewPort] =
|
|
2875
|
-
const [copiedPort, setCopiedPort] =
|
|
2876
|
-
const copyTimerRef =
|
|
2877
|
-
|
|
3236
|
+
const [newPort, setNewPort] = React11.useState("");
|
|
3237
|
+
const [copiedPort, setCopiedPort] = React11.useState(null);
|
|
3238
|
+
const copyTimerRef = React11.useRef(null);
|
|
3239
|
+
React11.useEffect(() => {
|
|
2878
3240
|
return () => {
|
|
2879
3241
|
if (copyTimerRef.current) clearTimeout(copyTimerRef.current);
|
|
2880
3242
|
};
|
|
@@ -2914,7 +3276,7 @@ function PortsList({ ports, onExposePort, onRemovePort, isExposing = false, clas
|
|
|
2914
3276
|
className: "flex items-center gap-2 font-mono text-xs text-primary hover:underline cursor-pointer group",
|
|
2915
3277
|
children: [
|
|
2916
3278
|
/* @__PURE__ */ jsx22("span", { className: "truncate max-w-[300px]", children: p.url }),
|
|
2917
|
-
copiedPort === p.port ? /* @__PURE__ */ jsx22(
|
|
3279
|
+
copiedPort === p.port ? /* @__PURE__ */ jsx22(Check5, { className: "h-3 w-3 text-[var(--surface-success-text)] shrink-0" }) : /* @__PURE__ */ jsx22(Copy3, { className: "h-3 w-3 opacity-0 group-hover:opacity-100 transition-opacity shrink-0" })
|
|
2918
3280
|
]
|
|
2919
3281
|
}
|
|
2920
3282
|
) }),
|
|
@@ -2968,7 +3330,7 @@ function PortsList({ ports, onExposePort, onRemovePort, isExposing = false, clas
|
|
|
2968
3330
|
}
|
|
2969
3331
|
|
|
2970
3332
|
// src/dashboard/process-list.tsx
|
|
2971
|
-
import * as
|
|
3333
|
+
import * as React12 from "react";
|
|
2972
3334
|
import { Activity as Activity3, Plus as Plus5, Skull, Terminal as Terminal3 } from "lucide-react";
|
|
2973
3335
|
import { jsx as jsx23, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
2974
3336
|
function formatUptime(startedAt) {
|
|
@@ -2980,7 +3342,7 @@ function formatUptime(startedAt) {
|
|
|
2980
3342
|
return `${Math.floor(ms / 36e5)}h ${Math.floor(ms % 36e5 / 6e4)}m`;
|
|
2981
3343
|
}
|
|
2982
3344
|
function ProcessList({ processes, onSpawn, onKill, loading = false, className }) {
|
|
2983
|
-
const [newCommand, setNewCommand] =
|
|
3345
|
+
const [newCommand, setNewCommand] = React12.useState("");
|
|
2984
3346
|
const handleSpawn = () => {
|
|
2985
3347
|
const cmd = newCommand.trim();
|
|
2986
3348
|
if (cmd) {
|
|
@@ -3053,11 +3415,11 @@ function ProcessList({ processes, onSpawn, onKill, loading = false, className })
|
|
|
3053
3415
|
}
|
|
3054
3416
|
|
|
3055
3417
|
// src/dashboard/network-config.tsx
|
|
3056
|
-
import * as
|
|
3418
|
+
import * as React13 from "react";
|
|
3057
3419
|
import { Network as Network2, Plus as Plus6, Trash2 as Trash24, ShieldAlert } from "lucide-react";
|
|
3058
3420
|
import { jsx as jsx24, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
3059
3421
|
function NetworkConfig({ config, onUpdate, loading = false, className }) {
|
|
3060
|
-
const [newCidr, setNewCidr] =
|
|
3422
|
+
const [newCidr, setNewCidr] = React13.useState("");
|
|
3061
3423
|
const isValidCidr = (value) => {
|
|
3062
3424
|
const match = value.match(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\/(\d{1,2})$/);
|
|
3063
3425
|
if (!match) return false;
|
|
@@ -3161,7 +3523,7 @@ function NetworkConfig({ config, onUpdate, loading = false, className }) {
|
|
|
3161
3523
|
}
|
|
3162
3524
|
|
|
3163
3525
|
// src/dashboard/backend-config.tsx
|
|
3164
|
-
import * as
|
|
3526
|
+
import * as React14 from "react";
|
|
3165
3527
|
import { Bot, Plus as Plus7, RefreshCw as RefreshCw2, Trash2 as Trash25, Server, Wrench } from "lucide-react";
|
|
3166
3528
|
import { Fragment as Fragment13, jsx as jsx25, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
3167
3529
|
function BackendConfig({
|
|
@@ -3173,10 +3535,10 @@ function BackendConfig({
|
|
|
3173
3535
|
loading = false,
|
|
3174
3536
|
className
|
|
3175
3537
|
}) {
|
|
3176
|
-
const [showAddMcp, setShowAddMcp] =
|
|
3177
|
-
const [mcpName, setMcpName] =
|
|
3178
|
-
const [mcpCommand, setMcpCommand] =
|
|
3179
|
-
const [mcpArgs, setMcpArgs] =
|
|
3538
|
+
const [showAddMcp, setShowAddMcp] = React14.useState(false);
|
|
3539
|
+
const [mcpName, setMcpName] = React14.useState("");
|
|
3540
|
+
const [mcpCommand, setMcpCommand] = React14.useState("");
|
|
3541
|
+
const [mcpArgs, setMcpArgs] = React14.useState("");
|
|
3180
3542
|
const handleAddMcp = () => {
|
|
3181
3543
|
const name = mcpName.trim();
|
|
3182
3544
|
const command = mcpCommand.trim();
|
|
@@ -3334,7 +3696,7 @@ function BackendConfig({
|
|
|
3334
3696
|
}
|
|
3335
3697
|
|
|
3336
3698
|
// src/dashboard/snapshot-list.tsx
|
|
3337
|
-
import * as
|
|
3699
|
+
import * as React15 from "react";
|
|
3338
3700
|
import { Camera, Clock as Clock5, HardDrive as HardDrive2, Plus as Plus8, RotateCcw } from "lucide-react";
|
|
3339
3701
|
import { jsx as jsx26, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
3340
3702
|
function formatBytes(bytes) {
|
|
@@ -3351,8 +3713,8 @@ function formatDate(dateStr) {
|
|
|
3351
3713
|
return d.toLocaleDateString(void 0, { month: "short", day: "numeric", hour: "2-digit", minute: "2-digit" });
|
|
3352
3714
|
}
|
|
3353
3715
|
function SnapshotList({ snapshots, onCreate, onRestore, onSaveAsTemplate, loading = false, className }) {
|
|
3354
|
-
const [showCreate, setShowCreate] =
|
|
3355
|
-
const [tags, setTags] =
|
|
3716
|
+
const [showCreate, setShowCreate] = React15.useState(false);
|
|
3717
|
+
const [tags, setTags] = React15.useState("");
|
|
3356
3718
|
const handleCreate = () => {
|
|
3357
3719
|
const tagList = tags.trim() ? tags.trim().split(",").map((t) => t.trim()).filter(Boolean) : void 0;
|
|
3358
3720
|
onCreate(tagList);
|
|
@@ -3513,6 +3875,7 @@ export {
|
|
|
3513
3875
|
RailTooltip,
|
|
3514
3876
|
RailThemeToggle,
|
|
3515
3877
|
RailCollapseToggle,
|
|
3878
|
+
RailHeader,
|
|
3516
3879
|
Sidebar,
|
|
3517
3880
|
SidebarRail,
|
|
3518
3881
|
SidebarRailHeader,
|
|
@@ -3521,6 +3884,7 @@ export {
|
|
|
3521
3884
|
RailSeparator,
|
|
3522
3885
|
RailButton,
|
|
3523
3886
|
RailFlyout,
|
|
3887
|
+
RailExpandable,
|
|
3524
3888
|
RailModeButton,
|
|
3525
3889
|
SidebarPanel,
|
|
3526
3890
|
SidebarPanelHeader,
|