@tangle-network/sandbox-ui 0.52.0 → 0.54.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-MGIOO3RL.js → chunk-DLKDWMFM.js} +1 -1
- package/dist/{chunk-RT4MLYYM.js → chunk-SVNWL3ZR.js} +635 -248
- 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,30 @@ function PlanCards({ plans, className }) {
|
|
|
1515
1899
|
}
|
|
1516
1900
|
|
|
1517
1901
|
// src/dashboard/dashboard-layout.tsx
|
|
1518
|
-
import * as
|
|
1519
|
-
import { Plus as Plus2, Bell
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1902
|
+
import * as React9 from "react";
|
|
1903
|
+
import { Plus as Plus2, Bell } from "lucide-react";
|
|
1904
|
+
|
|
1905
|
+
// src/dashboard/use-brand-theme-sync.ts
|
|
1906
|
+
import * as React8 from "react";
|
|
1907
|
+
function useBrandThemeSync() {
|
|
1908
|
+
React8.useEffect(() => {
|
|
1909
|
+
if (typeof document === "undefined") return;
|
|
1910
|
+
const el = document.documentElement;
|
|
1911
|
+
const sync = () => {
|
|
1912
|
+
const dark = el.classList.contains("dark");
|
|
1913
|
+
el.classList.toggle("light", !dark);
|
|
1914
|
+
const next = dark ? "dark" : "light";
|
|
1915
|
+
if (el.getAttribute("data-theme") !== next) el.setAttribute("data-theme", next);
|
|
1916
|
+
};
|
|
1917
|
+
sync();
|
|
1918
|
+
const observer = new MutationObserver(sync);
|
|
1919
|
+
observer.observe(el, { attributes: true, attributeFilter: ["class"] });
|
|
1920
|
+
return () => observer.disconnect();
|
|
1921
|
+
}, []);
|
|
1527
1922
|
}
|
|
1923
|
+
|
|
1924
|
+
// src/dashboard/dashboard-layout.tsx
|
|
1925
|
+
import { Fragment as Fragment9, jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
1528
1926
|
function MenuIcon({ className }) {
|
|
1529
1927
|
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
1928
|
/* @__PURE__ */ jsx14("title", { children: "Menu icon" }),
|
|
@@ -1574,19 +1972,19 @@ function DashboardLayoutInner({
|
|
|
1574
1972
|
topBarLeading,
|
|
1575
1973
|
LinkComponent = DefaultLink2,
|
|
1576
1974
|
logoHref = "/",
|
|
1577
|
-
onLogoClick,
|
|
1578
|
-
logoAriaLabel = "Toggle navigation",
|
|
1579
1975
|
labeledRail = false,
|
|
1580
1976
|
footer,
|
|
1581
1977
|
railFooter,
|
|
1582
1978
|
profileMenuItems,
|
|
1979
|
+
appearance,
|
|
1583
1980
|
notifications: notifData
|
|
1584
1981
|
}) {
|
|
1982
|
+
useBrandThemeSync();
|
|
1585
1983
|
const Link = LinkComponent;
|
|
1586
|
-
const [mobileMenuOpen, setMobileMenuOpen] =
|
|
1587
|
-
const [notificationsOpen, setNotificationsOpen] =
|
|
1588
|
-
const notifRef =
|
|
1589
|
-
|
|
1984
|
+
const [mobileMenuOpen, setMobileMenuOpen] = React9.useState(false);
|
|
1985
|
+
const [notificationsOpen, setNotificationsOpen] = React9.useState(false);
|
|
1986
|
+
const notifRef = React9.useRef(null);
|
|
1987
|
+
React9.useEffect(() => {
|
|
1590
1988
|
if (!notificationsOpen) return;
|
|
1591
1989
|
const handler = (e) => {
|
|
1592
1990
|
if (notifRef.current && !notifRef.current.contains(e.target)) {
|
|
@@ -1604,123 +2002,87 @@ function DashboardLayoutInner({
|
|
|
1604
2002
|
};
|
|
1605
2003
|
}, [notificationsOpen]);
|
|
1606
2004
|
const { contentMargin, hidden, mode, hasPanels, panelOpen, toggleRail, railCollapsed } = useSidebar();
|
|
1607
|
-
const modeSet =
|
|
1608
|
-
const sidebarUser =
|
|
2005
|
+
const modeSet = React9.useMemo(() => new Set(modeItems), [modeItems]);
|
|
2006
|
+
const sidebarUser = React9.useMemo(
|
|
1609
2007
|
() => user ? { email: user.email, name: user.name, tier: user.tier, avatarUrl: user.avatarUrl } : void 0,
|
|
1610
2008
|
[user?.email, user?.name, user?.tier, user?.avatarUrl]
|
|
1611
2009
|
);
|
|
1612
2010
|
const activePanel = panels.find((p) => p.mode === mode);
|
|
1613
|
-
const buildSidebarContent =
|
|
2011
|
+
const buildSidebarContent = React9.useCallback(
|
|
1614
2012
|
(showLabels, allowCollapse) => /* @__PURE__ */ jsxs13(Fragment9, { children: [
|
|
1615
2013
|
/* @__PURE__ */ jsxs13(SidebarRail, { wide: showLabels, children: [
|
|
1616
|
-
/* @__PURE__ */ jsx14(
|
|
1617
|
-
|
|
2014
|
+
/* @__PURE__ */ jsx14(
|
|
2015
|
+
RailHeader,
|
|
1618
2016
|
{
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
2017
|
+
brand: /* @__PURE__ */ jsx14(Logo, { variant, size: "sm", iconOnly: true }),
|
|
2018
|
+
brandHref: logoHref,
|
|
2019
|
+
collapsed: !showLabels,
|
|
2020
|
+
onToggle: toggleRail,
|
|
2021
|
+
collapsible: allowCollapse,
|
|
2022
|
+
LinkComponent: Link
|
|
1624
2023
|
}
|
|
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,
|
|
2024
|
+
),
|
|
2025
|
+
/* @__PURE__ */ jsx14(
|
|
2026
|
+
SidebarRailNav,
|
|
1650
2027
|
{
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
2028
|
+
className: cn(showLabels ? "px-2" : void 0, !showLabels && allowCollapse && "cursor-pointer"),
|
|
2029
|
+
onClick: !showLabels && allowCollapse ? (e) => {
|
|
2030
|
+
if (e.target === e.currentTarget) toggleRail();
|
|
2031
|
+
} : void 0,
|
|
2032
|
+
children: navItems.map((item, i) => {
|
|
2033
|
+
const isMode = modeSet.has(item.id);
|
|
2034
|
+
const prevIsMode = i > 0 && modeSet.has(navItems[i - 1].id);
|
|
2035
|
+
const showSep = i > 0 && isMode && !prevIsMode;
|
|
2036
|
+
return /* @__PURE__ */ jsxs13(React9.Fragment, { children: [
|
|
2037
|
+
showSep && /* @__PURE__ */ jsx14(
|
|
2038
|
+
RailSeparator,
|
|
2039
|
+
{
|
|
2040
|
+
className: showLabels ? "w-full" : void 0
|
|
2041
|
+
}
|
|
2042
|
+
),
|
|
2043
|
+
isMode ? /* @__PURE__ */ jsx14(
|
|
2044
|
+
RailModeButton,
|
|
2045
|
+
{
|
|
2046
|
+
mode: item.id,
|
|
2047
|
+
icon: item.icon,
|
|
2048
|
+
label: item.label,
|
|
2049
|
+
badge: item.badge,
|
|
2050
|
+
showLabel: showLabels
|
|
2051
|
+
}
|
|
2052
|
+
) : /* @__PURE__ */ jsx14(
|
|
2053
|
+
RailButton,
|
|
2054
|
+
{
|
|
2055
|
+
icon: item.icon,
|
|
2056
|
+
label: item.label,
|
|
2057
|
+
isActive: activeNavId === item.id,
|
|
2058
|
+
showLabel: showLabels,
|
|
2059
|
+
asChild: true,
|
|
2060
|
+
children: /* @__PURE__ */ jsx14(Link, { href: item.href, to: item.href })
|
|
2061
|
+
}
|
|
2062
|
+
)
|
|
2063
|
+
] }, item.id);
|
|
2064
|
+
})
|
|
1655
2065
|
}
|
|
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(
|
|
2066
|
+
),
|
|
2067
|
+
/* @__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: [
|
|
2068
|
+
/* @__PURE__ */ jsx14("div", { className: "min-w-0 flex-1", children: /* @__PURE__ */ jsx14(
|
|
2069
|
+
ProfileAvatar,
|
|
2070
|
+
{
|
|
2071
|
+
user: sidebarUser,
|
|
2072
|
+
isLoading,
|
|
2073
|
+
onLogout,
|
|
2074
|
+
onSettingsClick,
|
|
2075
|
+
settingsHref,
|
|
2076
|
+
showDetails: showLabels,
|
|
2077
|
+
appearance,
|
|
2078
|
+
LinkComponent,
|
|
2079
|
+
children: profileMenuItems
|
|
2080
|
+
}
|
|
2081
|
+
) }),
|
|
2082
|
+
/* @__PURE__ */ jsx14("div", { className: "shrink-0", children: railFooter })
|
|
2083
|
+
] }) : /* @__PURE__ */ jsxs13("div", { className: "flex flex-col items-center gap-1", children: [
|
|
2084
|
+
railFooter,
|
|
2085
|
+
/* @__PURE__ */ jsx14(
|
|
1724
2086
|
ProfileAvatar,
|
|
1725
2087
|
{
|
|
1726
2088
|
user: sidebarUser,
|
|
@@ -1729,11 +2091,25 @@ function DashboardLayoutInner({
|
|
|
1729
2091
|
onSettingsClick,
|
|
1730
2092
|
settingsHref,
|
|
1731
2093
|
showDetails: showLabels,
|
|
2094
|
+
appearance,
|
|
1732
2095
|
LinkComponent,
|
|
1733
2096
|
children: profileMenuItems
|
|
1734
2097
|
}
|
|
1735
2098
|
)
|
|
1736
|
-
] })
|
|
2099
|
+
] }) : /* @__PURE__ */ jsx14(
|
|
2100
|
+
ProfileAvatar,
|
|
2101
|
+
{
|
|
2102
|
+
user: sidebarUser,
|
|
2103
|
+
isLoading,
|
|
2104
|
+
onLogout,
|
|
2105
|
+
onSettingsClick,
|
|
2106
|
+
settingsHref,
|
|
2107
|
+
showDetails: showLabels,
|
|
2108
|
+
appearance,
|
|
2109
|
+
LinkComponent,
|
|
2110
|
+
children: profileMenuItems
|
|
2111
|
+
}
|
|
2112
|
+
) })
|
|
1737
2113
|
] }),
|
|
1738
2114
|
panels.length > 0 && /* @__PURE__ */ jsxs13(SidebarPanel, { children: [
|
|
1739
2115
|
/* @__PURE__ */ jsx14(SidebarPanelHeader, { title: activePanel?.title ?? mode }),
|
|
@@ -1744,8 +2120,6 @@ function DashboardLayoutInner({
|
|
|
1744
2120
|
[
|
|
1745
2121
|
Link,
|
|
1746
2122
|
variant,
|
|
1747
|
-
onLogoClick,
|
|
1748
|
-
logoAriaLabel,
|
|
1749
2123
|
logoHref,
|
|
1750
2124
|
labeledRail,
|
|
1751
2125
|
toggleRail,
|
|
@@ -1761,16 +2135,17 @@ function DashboardLayoutInner({
|
|
|
1761
2135
|
onLogout,
|
|
1762
2136
|
LinkComponent,
|
|
1763
2137
|
profileMenuItems,
|
|
2138
|
+
appearance,
|
|
1764
2139
|
panels,
|
|
1765
2140
|
activePanel,
|
|
1766
2141
|
mode
|
|
1767
2142
|
]
|
|
1768
2143
|
);
|
|
1769
|
-
const sidebarContent =
|
|
2144
|
+
const sidebarContent = React9.useMemo(
|
|
1770
2145
|
() => buildSidebarContent(labeledRail && !railCollapsed, labeledRail),
|
|
1771
2146
|
[buildSidebarContent, labeledRail, railCollapsed]
|
|
1772
2147
|
);
|
|
1773
|
-
const mobileSidebarContent =
|
|
2148
|
+
const mobileSidebarContent = React9.useMemo(() => buildSidebarContent(true, false), [buildSidebarContent]);
|
|
1774
2149
|
return /* @__PURE__ */ jsxs13("div", { className: cn("min-h-screen bg-surface text-foreground", className), children: [
|
|
1775
2150
|
/* @__PURE__ */ jsxs13(
|
|
1776
2151
|
"nav",
|
|
@@ -1933,9 +2308,8 @@ function SidebarLayoutInner({
|
|
|
1933
2308
|
onSettingsClick,
|
|
1934
2309
|
settingsHref,
|
|
1935
2310
|
profileMenuItems,
|
|
1936
|
-
|
|
2311
|
+
appearance,
|
|
1937
2312
|
railFooter,
|
|
1938
|
-
railCollapseToggle = "footer",
|
|
1939
2313
|
LinkComponent,
|
|
1940
2314
|
hideBelow,
|
|
1941
2315
|
railLabels = false,
|
|
@@ -1944,29 +2318,50 @@ function SidebarLayoutInner({
|
|
|
1944
2318
|
sidebarClassName,
|
|
1945
2319
|
contentClassName
|
|
1946
2320
|
}) {
|
|
2321
|
+
useBrandThemeSync();
|
|
1947
2322
|
const Link = LinkComponent ?? DefaultLink3;
|
|
1948
2323
|
const { panelOpen, togglePanel, setPanelOpen, railCollapsed, toggleRail } = useSidebar();
|
|
1949
2324
|
const handleNavClick = closePanelOnNavigate && panelOpen ? () => setPanelOpen(false) : void 0;
|
|
2325
|
+
const expandOnEmptyClick = railLabels && railCollapsed ? (e) => {
|
|
2326
|
+
if (e.target === e.currentTarget) toggleRail();
|
|
2327
|
+
} : void 0;
|
|
1950
2328
|
const hasProfile = user !== void 0 || onLogout !== void 0 || onSettingsClick !== void 0;
|
|
1951
2329
|
const showLabels = railLabels && !railCollapsed;
|
|
1952
2330
|
return /* @__PURE__ */ jsxs14("div", { className: cn("min-h-screen bg-surface text-foreground", className), children: [
|
|
1953
2331
|
/* @__PURE__ */ jsx15("div", { className: cn(hideBelow && HIDE_BELOW_CLASS[hideBelow]), children: /* @__PURE__ */ jsxs14(Sidebar, { className: sidebarClassName, children: [
|
|
1954
2332
|
/* @__PURE__ */ jsxs14(SidebarRail, { children: [
|
|
1955
|
-
(
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
2333
|
+
(logo !== void 0 || railHeaderContent !== void 0 || railLabels) && /* @__PURE__ */ jsx15(
|
|
2334
|
+
RailHeader,
|
|
2335
|
+
{
|
|
2336
|
+
brand: logo,
|
|
2337
|
+
brandHref: logoHref,
|
|
2338
|
+
collapsed: !showLabels,
|
|
2339
|
+
onToggle: toggleRail,
|
|
2340
|
+
collapsible: railLabels,
|
|
2341
|
+
LinkComponent,
|
|
2342
|
+
children: railHeaderContent
|
|
2343
|
+
}
|
|
2344
|
+
),
|
|
2345
|
+
/* @__PURE__ */ jsx15(SidebarRailNav, { className: cn(showLabels ? "px-2" : void 0, expandOnEmptyClick && "cursor-pointer"), onClick: expandOnEmptyClick, children: navItems.map((item) => {
|
|
2346
|
+
if (item.expandable) {
|
|
2347
|
+
return /* @__PURE__ */ jsx15(
|
|
2348
|
+
RailExpandable,
|
|
2349
|
+
{
|
|
2350
|
+
icon: item.icon,
|
|
2351
|
+
label: item.label,
|
|
2352
|
+
href: item.href,
|
|
2353
|
+
isActive: activeId === item.id,
|
|
2354
|
+
showLabel: showLabels,
|
|
2355
|
+
subItems: item.subItems,
|
|
2356
|
+
loadSubItems: item.loadSubItems,
|
|
2357
|
+
activeSubIds: item.subActiveIds,
|
|
2358
|
+
emptyLabel: item.emptyLabel,
|
|
2359
|
+
onNavigate: handleNavClick,
|
|
2360
|
+
LinkComponent
|
|
2361
|
+
},
|
|
2362
|
+
item.id
|
|
2363
|
+
);
|
|
2364
|
+
}
|
|
1970
2365
|
if (item.flyoutItems && item.flyoutItems.length > 0) {
|
|
1971
2366
|
const activeSet = new Set(item.flyoutActiveIds ?? []);
|
|
1972
2367
|
return /* @__PURE__ */ jsx15(
|
|
@@ -2014,7 +2409,7 @@ function SidebarLayoutInner({
|
|
|
2014
2409
|
showLabel: showLabels
|
|
2015
2410
|
},
|
|
2016
2411
|
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(
|
|
2412
|
+
) : /* @__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
2413
|
Link,
|
|
2019
2414
|
{
|
|
2020
2415
|
href: item.href,
|
|
@@ -2024,32 +2419,22 @@ function SidebarLayoutInner({
|
|
|
2024
2419
|
}
|
|
2025
2420
|
) }, item.id);
|
|
2026
2421
|
}) }),
|
|
2027
|
-
(
|
|
2028
|
-
railLabels && railCollapseToggle === "footer" && /* @__PURE__ */ jsx15(RailCollapseToggle, { collapsed: railCollapsed, showLabel: showLabels, onToggle: toggleRail }),
|
|
2422
|
+
(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
2423
|
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
|
-
})()
|
|
2424
|
+
hasProfile && /* @__PURE__ */ jsx15(
|
|
2425
|
+
ProfileAvatar,
|
|
2426
|
+
{
|
|
2427
|
+
user: user ?? void 0,
|
|
2428
|
+
isLoading,
|
|
2429
|
+
onLogout,
|
|
2430
|
+
onSettingsClick,
|
|
2431
|
+
settingsHref,
|
|
2432
|
+
showDetails: showLabels,
|
|
2433
|
+
appearance,
|
|
2434
|
+
LinkComponent: Link,
|
|
2435
|
+
children: profileMenuItems
|
|
2436
|
+
}
|
|
2437
|
+
)
|
|
2053
2438
|
] })
|
|
2054
2439
|
] }),
|
|
2055
2440
|
panel != null && /* @__PURE__ */ jsx15(SidebarPanel, { children: panel })
|
|
@@ -2083,7 +2468,7 @@ function SidebarLayout({
|
|
|
2083
2468
|
}
|
|
2084
2469
|
|
|
2085
2470
|
// src/dashboard/profile-selector.tsx
|
|
2086
|
-
import { Check as
|
|
2471
|
+
import { Check as Check3, ChevronDown, Plus as Plus3, Settings } from "lucide-react";
|
|
2087
2472
|
import { Button as Button2 } from "@tangle-network/ui/primitives";
|
|
2088
2473
|
import { Badge } from "@tangle-network/ui/primitives";
|
|
2089
2474
|
import {
|
|
@@ -2124,7 +2509,7 @@ function ProfileSelector({
|
|
|
2124
2509
|
className: "flex items-center justify-between",
|
|
2125
2510
|
children: [
|
|
2126
2511
|
/* @__PURE__ */ jsx16("span", { children: placeholder }),
|
|
2127
|
-
!selectedId && /* @__PURE__ */ jsx16(
|
|
2512
|
+
!selectedId && /* @__PURE__ */ jsx16(Check3, { className: "h-4 w-4 text-[var(--surface-success-text)]" })
|
|
2128
2513
|
]
|
|
2129
2514
|
}
|
|
2130
2515
|
),
|
|
@@ -2145,7 +2530,7 @@ function ProfileSelector({
|
|
|
2145
2530
|
profile.extends
|
|
2146
2531
|
] })
|
|
2147
2532
|
] }),
|
|
2148
|
-
selectedId === profile.id && /* @__PURE__ */ jsx16(
|
|
2533
|
+
selectedId === profile.id && /* @__PURE__ */ jsx16(Check3, { className: "h-4 w-4 text-[var(--surface-success-text)]" })
|
|
2149
2534
|
] }),
|
|
2150
2535
|
profile.description && /* @__PURE__ */ jsx16("span", { className: "line-clamp-1 text-muted-foreground text-xs", children: profile.description })
|
|
2151
2536
|
]
|
|
@@ -2167,7 +2552,7 @@ function ProfileSelector({
|
|
|
2167
2552
|
/* @__PURE__ */ jsx16("span", { className: "font-medium", children: profile.name }),
|
|
2168
2553
|
profile.model && /* @__PURE__ */ jsx16(Badge, { variant: "secondary", className: "border-0 text-xs", children: profile.model.split("/").pop() })
|
|
2169
2554
|
] }),
|
|
2170
|
-
selectedId === profile.id && /* @__PURE__ */ jsx16(
|
|
2555
|
+
selectedId === profile.id && /* @__PURE__ */ jsx16(Check3, { className: "h-4 w-4 text-[var(--surface-success-text)]" })
|
|
2171
2556
|
] }),
|
|
2172
2557
|
profile.description && /* @__PURE__ */ jsx16("span", { className: "line-clamp-1 text-muted-foreground text-xs", children: profile.description }),
|
|
2173
2558
|
showMetrics && profile.metrics && profile.metrics.total_runs > 0 && /* @__PURE__ */ jsxs15("div", { className: "flex gap-3 text-muted-foreground text-xs", children: [
|
|
@@ -2285,7 +2670,7 @@ function ProfileComparison({
|
|
|
2285
2670
|
}
|
|
2286
2671
|
|
|
2287
2672
|
// src/dashboard/metric-area-chart.tsx
|
|
2288
|
-
import * as
|
|
2673
|
+
import * as React10 from "react";
|
|
2289
2674
|
import { jsx as jsx17, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
2290
2675
|
var TONE_VARS = {
|
|
2291
2676
|
primary: "var(--brand-primary, hsl(var(--primary)))",
|
|
@@ -2332,7 +2717,7 @@ function MetricAreaChart({
|
|
|
2332
2717
|
emptyState,
|
|
2333
2718
|
className
|
|
2334
2719
|
}) {
|
|
2335
|
-
const gradientId =
|
|
2720
|
+
const gradientId = React10.useId();
|
|
2336
2721
|
const width = 400;
|
|
2337
2722
|
const values = points.map((p) => p.value).filter((v) => v !== null);
|
|
2338
2723
|
const latest = values.length > 0 ? values[values.length - 1] : null;
|
|
@@ -2392,7 +2777,7 @@ function MetricAreaChart({
|
|
|
2392
2777
|
/* @__PURE__ */ jsx17("stop", { offset: "0%", stopColor: color, stopOpacity: 0.28 }),
|
|
2393
2778
|
/* @__PURE__ */ jsx17("stop", { offset: "100%", stopColor: color, stopOpacity: 0.02 })
|
|
2394
2779
|
] }) }),
|
|
2395
|
-
segments.map((segment) => /* @__PURE__ */ jsxs16(
|
|
2780
|
+
segments.map((segment) => /* @__PURE__ */ jsxs16(React10.Fragment, { children: [
|
|
2396
2781
|
/* @__PURE__ */ jsx17("path", { d: segment.area, fill: `url(#${gradientId})` }),
|
|
2397
2782
|
/* @__PURE__ */ jsx17(
|
|
2398
2783
|
"path",
|
|
@@ -2421,7 +2806,7 @@ function MetricAreaChart({
|
|
|
2421
2806
|
|
|
2422
2807
|
// src/dashboard/variant-list.tsx
|
|
2423
2808
|
import {
|
|
2424
|
-
Check as
|
|
2809
|
+
Check as Check4,
|
|
2425
2810
|
CheckCircle2,
|
|
2426
2811
|
Clock as Clock3,
|
|
2427
2812
|
ExternalLink as ExternalLink2,
|
|
@@ -2568,7 +2953,7 @@ function VariantList({
|
|
|
2568
2953
|
},
|
|
2569
2954
|
disabled: isActioning === variant.id,
|
|
2570
2955
|
children: [
|
|
2571
|
-
/* @__PURE__ */ jsx18(
|
|
2956
|
+
/* @__PURE__ */ jsx18(Check4, { className: "mr-1 h-3 w-3" }),
|
|
2572
2957
|
"Accept"
|
|
2573
2958
|
]
|
|
2574
2959
|
}
|
|
@@ -2617,14 +3002,14 @@ function VariantList({
|
|
|
2617
3002
|
|
|
2618
3003
|
// src/dashboard/system-logs.tsx
|
|
2619
3004
|
import { Terminal as Terminal2 } from "lucide-react";
|
|
2620
|
-
import { useEffect as
|
|
3005
|
+
import { useEffect as useEffect5, useRef as useRef4, useState as useState6 } from "react";
|
|
2621
3006
|
import { jsx as jsx19, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
2622
3007
|
function SystemLogsViewer({ apiUrl, token, className }) {
|
|
2623
|
-
const [logs, setLogs] =
|
|
2624
|
-
const [error, setError] =
|
|
2625
|
-
const [isFollowing, setIsFollowing] =
|
|
2626
|
-
const scrollRef =
|
|
2627
|
-
|
|
3008
|
+
const [logs, setLogs] = useState6([]);
|
|
3009
|
+
const [error, setError] = useState6(null);
|
|
3010
|
+
const [isFollowing, setIsFollowing] = useState6(true);
|
|
3011
|
+
const scrollRef = useRef4(null);
|
|
3012
|
+
useEffect5(() => {
|
|
2628
3013
|
let timeoutId;
|
|
2629
3014
|
let backoff = 2e3;
|
|
2630
3015
|
const controller = new AbortController();
|
|
@@ -2660,7 +3045,7 @@ function SystemLogsViewer({ apiUrl, token, className }) {
|
|
|
2660
3045
|
clearTimeout(timeoutId);
|
|
2661
3046
|
};
|
|
2662
3047
|
}, [apiUrl, token]);
|
|
2663
|
-
|
|
3048
|
+
useEffect5(() => {
|
|
2664
3049
|
if (isFollowing && scrollRef.current) {
|
|
2665
3050
|
scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
|
|
2666
3051
|
}
|
|
@@ -2867,14 +3252,14 @@ function GitPanel({ status, log, loading = false, onRefresh, className }) {
|
|
|
2867
3252
|
}
|
|
2868
3253
|
|
|
2869
3254
|
// src/dashboard/ports-list.tsx
|
|
2870
|
-
import * as
|
|
2871
|
-
import { Copy as Copy3, Check as
|
|
3255
|
+
import * as React12 from "react";
|
|
3256
|
+
import { Copy as Copy3, Check as Check5, Globe, Plus as Plus4, Trash2 as Trash23 } from "lucide-react";
|
|
2872
3257
|
import { jsx as jsx22, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
2873
3258
|
function PortsList({ ports, onExposePort, onRemovePort, isExposing = false, className }) {
|
|
2874
|
-
const [newPort, setNewPort] =
|
|
2875
|
-
const [copiedPort, setCopiedPort] =
|
|
2876
|
-
const copyTimerRef =
|
|
2877
|
-
|
|
3259
|
+
const [newPort, setNewPort] = React12.useState("");
|
|
3260
|
+
const [copiedPort, setCopiedPort] = React12.useState(null);
|
|
3261
|
+
const copyTimerRef = React12.useRef(null);
|
|
3262
|
+
React12.useEffect(() => {
|
|
2878
3263
|
return () => {
|
|
2879
3264
|
if (copyTimerRef.current) clearTimeout(copyTimerRef.current);
|
|
2880
3265
|
};
|
|
@@ -2914,7 +3299,7 @@ function PortsList({ ports, onExposePort, onRemovePort, isExposing = false, clas
|
|
|
2914
3299
|
className: "flex items-center gap-2 font-mono text-xs text-primary hover:underline cursor-pointer group",
|
|
2915
3300
|
children: [
|
|
2916
3301
|
/* @__PURE__ */ jsx22("span", { className: "truncate max-w-[300px]", children: p.url }),
|
|
2917
|
-
copiedPort === p.port ? /* @__PURE__ */ jsx22(
|
|
3302
|
+
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
3303
|
]
|
|
2919
3304
|
}
|
|
2920
3305
|
) }),
|
|
@@ -2968,7 +3353,7 @@ function PortsList({ ports, onExposePort, onRemovePort, isExposing = false, clas
|
|
|
2968
3353
|
}
|
|
2969
3354
|
|
|
2970
3355
|
// src/dashboard/process-list.tsx
|
|
2971
|
-
import * as
|
|
3356
|
+
import * as React13 from "react";
|
|
2972
3357
|
import { Activity as Activity3, Plus as Plus5, Skull, Terminal as Terminal3 } from "lucide-react";
|
|
2973
3358
|
import { jsx as jsx23, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
2974
3359
|
function formatUptime(startedAt) {
|
|
@@ -2980,7 +3365,7 @@ function formatUptime(startedAt) {
|
|
|
2980
3365
|
return `${Math.floor(ms / 36e5)}h ${Math.floor(ms % 36e5 / 6e4)}m`;
|
|
2981
3366
|
}
|
|
2982
3367
|
function ProcessList({ processes, onSpawn, onKill, loading = false, className }) {
|
|
2983
|
-
const [newCommand, setNewCommand] =
|
|
3368
|
+
const [newCommand, setNewCommand] = React13.useState("");
|
|
2984
3369
|
const handleSpawn = () => {
|
|
2985
3370
|
const cmd = newCommand.trim();
|
|
2986
3371
|
if (cmd) {
|
|
@@ -3053,11 +3438,11 @@ function ProcessList({ processes, onSpawn, onKill, loading = false, className })
|
|
|
3053
3438
|
}
|
|
3054
3439
|
|
|
3055
3440
|
// src/dashboard/network-config.tsx
|
|
3056
|
-
import * as
|
|
3441
|
+
import * as React14 from "react";
|
|
3057
3442
|
import { Network as Network2, Plus as Plus6, Trash2 as Trash24, ShieldAlert } from "lucide-react";
|
|
3058
3443
|
import { jsx as jsx24, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
3059
3444
|
function NetworkConfig({ config, onUpdate, loading = false, className }) {
|
|
3060
|
-
const [newCidr, setNewCidr] =
|
|
3445
|
+
const [newCidr, setNewCidr] = React14.useState("");
|
|
3061
3446
|
const isValidCidr = (value) => {
|
|
3062
3447
|
const match = value.match(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\/(\d{1,2})$/);
|
|
3063
3448
|
if (!match) return false;
|
|
@@ -3161,7 +3546,7 @@ function NetworkConfig({ config, onUpdate, loading = false, className }) {
|
|
|
3161
3546
|
}
|
|
3162
3547
|
|
|
3163
3548
|
// src/dashboard/backend-config.tsx
|
|
3164
|
-
import * as
|
|
3549
|
+
import * as React15 from "react";
|
|
3165
3550
|
import { Bot, Plus as Plus7, RefreshCw as RefreshCw2, Trash2 as Trash25, Server, Wrench } from "lucide-react";
|
|
3166
3551
|
import { Fragment as Fragment13, jsx as jsx25, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
3167
3552
|
function BackendConfig({
|
|
@@ -3173,10 +3558,10 @@ function BackendConfig({
|
|
|
3173
3558
|
loading = false,
|
|
3174
3559
|
className
|
|
3175
3560
|
}) {
|
|
3176
|
-
const [showAddMcp, setShowAddMcp] =
|
|
3177
|
-
const [mcpName, setMcpName] =
|
|
3178
|
-
const [mcpCommand, setMcpCommand] =
|
|
3179
|
-
const [mcpArgs, setMcpArgs] =
|
|
3561
|
+
const [showAddMcp, setShowAddMcp] = React15.useState(false);
|
|
3562
|
+
const [mcpName, setMcpName] = React15.useState("");
|
|
3563
|
+
const [mcpCommand, setMcpCommand] = React15.useState("");
|
|
3564
|
+
const [mcpArgs, setMcpArgs] = React15.useState("");
|
|
3180
3565
|
const handleAddMcp = () => {
|
|
3181
3566
|
const name = mcpName.trim();
|
|
3182
3567
|
const command = mcpCommand.trim();
|
|
@@ -3334,7 +3719,7 @@ function BackendConfig({
|
|
|
3334
3719
|
}
|
|
3335
3720
|
|
|
3336
3721
|
// src/dashboard/snapshot-list.tsx
|
|
3337
|
-
import * as
|
|
3722
|
+
import * as React16 from "react";
|
|
3338
3723
|
import { Camera, Clock as Clock5, HardDrive as HardDrive2, Plus as Plus8, RotateCcw } from "lucide-react";
|
|
3339
3724
|
import { jsx as jsx26, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
3340
3725
|
function formatBytes(bytes) {
|
|
@@ -3351,8 +3736,8 @@ function formatDate(dateStr) {
|
|
|
3351
3736
|
return d.toLocaleDateString(void 0, { month: "short", day: "numeric", hour: "2-digit", minute: "2-digit" });
|
|
3352
3737
|
}
|
|
3353
3738
|
function SnapshotList({ snapshots, onCreate, onRestore, onSaveAsTemplate, loading = false, className }) {
|
|
3354
|
-
const [showCreate, setShowCreate] =
|
|
3355
|
-
const [tags, setTags] =
|
|
3739
|
+
const [showCreate, setShowCreate] = React16.useState(false);
|
|
3740
|
+
const [tags, setTags] = React16.useState("");
|
|
3356
3741
|
const handleCreate = () => {
|
|
3357
3742
|
const tagList = tags.trim() ? tags.trim().split(",").map((t) => t.trim()).filter(Boolean) : void 0;
|
|
3358
3743
|
onCreate(tagList);
|
|
@@ -3513,6 +3898,7 @@ export {
|
|
|
3513
3898
|
RailTooltip,
|
|
3514
3899
|
RailThemeToggle,
|
|
3515
3900
|
RailCollapseToggle,
|
|
3901
|
+
RailHeader,
|
|
3516
3902
|
Sidebar,
|
|
3517
3903
|
SidebarRail,
|
|
3518
3904
|
SidebarRailHeader,
|
|
@@ -3521,6 +3907,7 @@ export {
|
|
|
3521
3907
|
RailSeparator,
|
|
3522
3908
|
RailButton,
|
|
3523
3909
|
RailFlyout,
|
|
3910
|
+
RailExpandable,
|
|
3524
3911
|
RailModeButton,
|
|
3525
3912
|
SidebarPanel,
|
|
3526
3913
|
SidebarPanelHeader,
|