@tangle-network/sandbox-ui 0.23.1 → 0.23.2

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.
@@ -17,7 +17,7 @@ import {
17
17
  DropdownMenuSeparator,
18
18
  DropdownMenuTrigger
19
19
  } from "@tangle-network/ui/primitives";
20
- import { Skeleton } from "@tangle-network/ui/primitives";
20
+ import { Skeleton, useTheme } from "@tangle-network/ui/primitives";
21
21
 
22
22
  // src/dashboard/sidebar-context.tsx
23
23
  import * as React from "react";
@@ -142,6 +142,41 @@ function LogOutIcon({ className }) {
142
142
  /* @__PURE__ */ jsx2("line", { x1: "21", x2: "9", y1: "12", y2: "12" })
143
143
  ] });
144
144
  }
145
+ function SunIcon({ className }) {
146
+ return /* @__PURE__ */ jsxs("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: [
147
+ /* @__PURE__ */ jsx2("title", { children: "Light mode icon" }),
148
+ /* @__PURE__ */ jsx2("circle", { cx: "12", cy: "12", r: "4" }),
149
+ /* @__PURE__ */ jsx2("path", { d: "M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41" })
150
+ ] });
151
+ }
152
+ function MoonIcon({ className }) {
153
+ return /* @__PURE__ */ jsxs("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: [
154
+ /* @__PURE__ */ jsx2("title", { children: "Dark mode icon" }),
155
+ /* @__PURE__ */ jsx2("path", { d: "M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z" })
156
+ ] });
157
+ }
158
+ function RailThemeToggle({ className }) {
159
+ const { theme, setTheme } = useTheme();
160
+ const [mounted, setMounted] = React2.useState(false);
161
+ React2.useEffect(() => setMounted(true), []);
162
+ const isDark = mounted && (theme === "dark" || theme === "system" && typeof window !== "undefined" && window.matchMedia("(prefers-color-scheme: dark)").matches);
163
+ return /* @__PURE__ */ jsx2(
164
+ "button",
165
+ {
166
+ type: "button",
167
+ onClick: () => setTheme(isDark ? "light" : "dark"),
168
+ "aria-label": "Toggle theme",
169
+ title: isDark ? "Switch to light mode" : "Switch to dark mode",
170
+ className: cn(
171
+ "flex h-9 w-9 shrink-0 items-center justify-center rounded-lg text-muted-foreground transition-colors",
172
+ "hover:bg-[var(--accent-surface-soft)] hover:text-[var(--accent-text)]",
173
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary",
174
+ className
175
+ ),
176
+ children: isDark ? /* @__PURE__ */ jsx2(SunIcon, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx2(MoonIcon, { className: "h-4 w-4" })
177
+ }
178
+ );
179
+ }
145
180
  function Sidebar({ children, className, style }) {
146
181
  const { panelOpen, hidden, hasPanels, railWidth } = useSidebar();
147
182
  return /* @__PURE__ */ jsx2(
@@ -174,20 +209,20 @@ function SidebarRail({ children, className, wide = false }) {
174
209
  );
175
210
  }
176
211
  function SidebarRailHeader({ children, className }) {
177
- return /* @__PURE__ */ jsx2("div", { className: cn("flex h-14 items-center justify-center border-b border-border", className), children });
212
+ return /* @__PURE__ */ jsx2("div", { className: cn("flex h-14 shrink-0 items-center justify-center border-b border-border", className), children });
178
213
  }
179
214
  function SidebarRailNav({ children, className }) {
180
- return /* @__PURE__ */ jsx2("nav", { className: cn("flex flex-col items-center gap-1 py-3 flex-1", className), children });
215
+ return /* @__PURE__ */ jsx2("nav", { className: cn("flex flex-col items-center gap-1 py-3 flex-1 min-h-0 overflow-y-auto", className), children });
181
216
  }
182
217
  function SidebarRailFooter({ children, className }) {
183
- return /* @__PURE__ */ jsx2("div", { className: cn("flex flex-col items-center gap-1 pb-3", className), children });
218
+ return /* @__PURE__ */ jsx2("div", { className: cn("flex flex-col items-center gap-1 pb-3 shrink-0", className), children });
184
219
  }
185
220
  function RailSeparator({ className }) {
186
221
  return /* @__PURE__ */ jsx2("div", { className: cn("my-2 h-px w-10 bg-[var(--md3-outline-variant)]", className) });
187
222
  }
188
223
  function RailButton({ icon: Icon, label, isActive, badge, onClick, className, showLabel, asChild, children }) {
189
224
  const classes = cn(
190
- "group relative flex items-center justify-center rounded-xl transition-all duration-200",
225
+ "group relative flex shrink-0 items-center justify-center rounded-xl transition-all duration-200",
191
226
  showLabel ? "w-full justify-start px-3 h-11 gap-3" : "w-11 h-11 justify-center",
192
227
  "hover:bg-[var(--accent-surface-soft)] hover:text-[var(--accent-text)]",
193
228
  "active:scale-95",
@@ -289,13 +324,7 @@ function ProfileAvatar({
289
324
  user?.avatarUrl && /* @__PURE__ */ jsx2(AvatarImage, { src: user.avatarUrl, alt: "" }),
290
325
  /* @__PURE__ */ jsx2(AvatarFallback, { className: "text-[10px] bg-violet-500/20 text-violet-300", children: getInitials(user?.name, user?.email) })
291
326
  ] }),
292
- showDetails && /* @__PURE__ */ jsx2("div", { className: "min-w-0 flex-1", children: isLoading ? /* @__PURE__ */ jsxs(Fragment, { children: [
293
- /* @__PURE__ */ jsx2(Skeleton, { className: "mb-1 h-3.5 w-20" }),
294
- /* @__PURE__ */ jsx2(Skeleton, { className: "h-3 w-28" })
295
- ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
296
- /* @__PURE__ */ jsx2("p", { className: "truncate text-sm font-medium text-foreground", children: user?.name ?? user?.email ?? "Not signed in" }),
297
- user?.email && user?.name && /* @__PURE__ */ jsx2("p", { className: "truncate text-xs text-muted-foreground", children: user.email })
298
- ] }) })
327
+ showDetails && /* @__PURE__ */ jsx2("div", { className: "min-w-0 flex-1", children: isLoading ? /* @__PURE__ */ jsx2(Skeleton, { className: "h-3.5 w-24" }) : /* @__PURE__ */ jsx2("p", { className: "truncate text-sm font-medium text-foreground", children: user?.name ?? user?.email ?? "Not signed in" }) })
299
328
  ]
300
329
  }
301
330
  ) }),
@@ -1562,6 +1591,7 @@ function SidebarLayoutInner({
1562
1591
  onSettingsClick,
1563
1592
  settingsHref,
1564
1593
  profileMenuItems,
1594
+ showThemeToggle = false,
1565
1595
  railFooter,
1566
1596
  LinkComponent,
1567
1597
  hideBelow,
@@ -1603,19 +1633,29 @@ function SidebarLayoutInner({
1603
1633
  ) }),
1604
1634
  (railFooter !== void 0 || hasProfile) && /* @__PURE__ */ jsxs13(SidebarRailFooter, { className: cn("border-t border-border pt-2", railLabels && "items-stretch px-2"), children: [
1605
1635
  railFooter,
1606
- hasProfile && /* @__PURE__ */ jsx14(
1607
- ProfileAvatar,
1608
- {
1609
- user: user ?? void 0,
1610
- isLoading,
1611
- onLogout,
1612
- onSettingsClick,
1613
- settingsHref,
1614
- showDetails: railLabels,
1615
- LinkComponent: Link,
1616
- children: profileMenuItems
1617
- }
1618
- )
1636
+ hasProfile && (() => {
1637
+ const profile = /* @__PURE__ */ jsx14(
1638
+ ProfileAvatar,
1639
+ {
1640
+ user: user ?? void 0,
1641
+ isLoading,
1642
+ onLogout,
1643
+ onSettingsClick,
1644
+ settingsHref,
1645
+ showDetails: railLabels,
1646
+ LinkComponent: Link,
1647
+ children: profileMenuItems
1648
+ }
1649
+ );
1650
+ if (!showThemeToggle) return profile;
1651
+ return railLabels ? /* @__PURE__ */ jsxs13("div", { className: "flex w-full items-center gap-1", children: [
1652
+ /* @__PURE__ */ jsx14("div", { className: "min-w-0 flex-1", children: profile }),
1653
+ /* @__PURE__ */ jsx14(RailThemeToggle, {})
1654
+ ] }) : /* @__PURE__ */ jsxs13("div", { className: "flex flex-col items-center gap-1", children: [
1655
+ /* @__PURE__ */ jsx14(RailThemeToggle, {}),
1656
+ profile
1657
+ ] });
1658
+ })()
1619
1659
  ] })
1620
1660
  ] }),
1621
1661
  panel != null && /* @__PURE__ */ jsx14(SidebarPanel, { children: panel })
@@ -2177,14 +2217,14 @@ function VariantList({
2177
2217
 
2178
2218
  // src/dashboard/system-logs.tsx
2179
2219
  import { Terminal as Terminal3 } from "lucide-react";
2180
- import { useEffect as useEffect2, useRef as useRef2, useState as useState4 } from "react";
2220
+ import { useEffect as useEffect3, useRef as useRef2, useState as useState5 } from "react";
2181
2221
  import { jsx as jsx18, jsxs as jsxs17 } from "react/jsx-runtime";
2182
2222
  function SystemLogsViewer({ apiUrl, token, className }) {
2183
- const [logs, setLogs] = useState4([]);
2184
- const [error, setError] = useState4(null);
2185
- const [isFollowing, setIsFollowing] = useState4(true);
2223
+ const [logs, setLogs] = useState5([]);
2224
+ const [error, setError] = useState5(null);
2225
+ const [isFollowing, setIsFollowing] = useState5(true);
2186
2226
  const scrollRef = useRef2(null);
2187
- useEffect2(() => {
2227
+ useEffect3(() => {
2188
2228
  let timeoutId;
2189
2229
  let backoff = 2e3;
2190
2230
  const controller = new AbortController();
@@ -2220,7 +2260,7 @@ function SystemLogsViewer({ apiUrl, token, className }) {
2220
2260
  clearTimeout(timeoutId);
2221
2261
  };
2222
2262
  }, [apiUrl, token]);
2223
- useEffect2(() => {
2263
+ useEffect3(() => {
2224
2264
  if (isFollowing && scrollRef.current) {
2225
2265
  scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
2226
2266
  }
@@ -535,6 +535,8 @@ interface SidebarLayoutProps {
535
535
  settingsHref?: string;
536
536
  /** Extra items rendered before settings/logout in the profile menu. */
537
537
  profileMenuItems?: React.ReactNode;
538
+ /** Render a light/dark theme switch in the profile menu (uses the shared `useTheme`). */
539
+ showThemeToggle?: boolean;
538
540
  /** Extra content in the rail footer, above the profile avatar. */
539
541
  railFooter?: React.ReactNode;
540
542
  LinkComponent?: React.ComponentType<any>;
package/dist/dashboard.js CHANGED
@@ -47,7 +47,7 @@ import {
47
47
  canAdminSandbox,
48
48
  parseInsufficientBalance,
49
49
  useSidebar
50
- } from "./chunk-CB3KBKYN.js";
50
+ } from "./chunk-MBYBQWRN.js";
51
51
  import {
52
52
  BillingDashboard,
53
53
  InfoPanel,
package/dist/index.js CHANGED
@@ -189,7 +189,7 @@ import {
189
189
  canAdminSandbox,
190
190
  parseInsufficientBalance,
191
191
  useSidebar
192
- } from "./chunk-CB3KBKYN.js";
192
+ } from "./chunk-MBYBQWRN.js";
193
193
  import {
194
194
  BillingDashboard,
195
195
  InfoPanel,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tangle-network/sandbox-ui",
3
- "version": "0.23.1",
3
+ "version": "0.23.2",
4
4
  "description": "Unified UI component library for Tangle Sandbox — primitives, chat, dashboard, terminal, editor, and workspace components",
5
5
  "repository": {
6
6
  "type": "git",