@unicitylabs/sphere-ui 0.1.1 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,9 +1,67 @@
1
- import * as react from 'react';
2
- import { ButtonHTMLAttributes, ReactNode, InputHTMLAttributes, SelectHTMLAttributes, TextareaHTMLAttributes } from 'react';
3
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import * as react from 'react';
3
+ import { ReactNode, ButtonHTMLAttributes, InputHTMLAttributes, SelectHTMLAttributes, TextareaHTMLAttributes } from 'react';
4
4
  import { ColumnDef } from '@tanstack/react-table';
5
5
  export { A as AchievementData, a as AchievementFormApi, Q as QueryKeys, b as QuestData, c as QuestFormApi, T as TrackData, d as TrackFormApi } from './index-DMHfA7fr.js';
6
6
 
7
+ interface DashboardLayoutProps {
8
+ /** Sidebar header — logo + app name */
9
+ logo: ReactNode;
10
+ /** Navigation content */
11
+ nav: ReactNode;
12
+ /** Footer content (e.g. sign out button) */
13
+ footer?: ReactNode;
14
+ children: ReactNode;
15
+ }
16
+ /**
17
+ * Dashboard shell with sidebar + main content area.
18
+ * Used by sphere-backoffice and sphere-dev.
19
+ */
20
+ declare function DashboardLayout({ logo, nav, footer, children }: DashboardLayoutProps): react_jsx_runtime.JSX.Element;
21
+
22
+ interface AppLogoProps {
23
+ /** Short code displayed in the icon (e.g. "SQ", "SD") */
24
+ icon?: string | ReactNode;
25
+ /** App title (e.g. "SPHERE QUESTS") */
26
+ title: string;
27
+ /** Subtitle (e.g. "ADMIN", "DEVELOPER") */
28
+ subtitle?: string;
29
+ /** Click handler (e.g. navigate to dashboard) */
30
+ onClick?: () => void;
31
+ }
32
+ /**
33
+ * App logo for dashboard sidebar.
34
+ * Orange icon + Anton title + Geist subtitle.
35
+ */
36
+ declare function AppLogo({ icon, title, subtitle, onClick }: AppLogoProps): react_jsx_runtime.JSX.Element;
37
+
38
+ interface NavItem {
39
+ to: string;
40
+ label: string;
41
+ /** SVG path data for the icon (24x24 viewBox) */
42
+ icon?: string;
43
+ /** Custom icon element (overrides icon path) */
44
+ iconElement?: ReactNode;
45
+ /** Badge count (e.g. pending reviews) */
46
+ badge?: number;
47
+ }
48
+ interface NavGroup {
49
+ label?: string;
50
+ items: NavItem[];
51
+ }
52
+ interface SidebarNavProps {
53
+ groups: NavGroup[];
54
+ /** Current path for active state detection */
55
+ currentPath: string;
56
+ /** Called when a nav item is clicked */
57
+ onNavigate: (to: string) => void;
58
+ }
59
+ /**
60
+ * Sidebar navigation with grouped items, icons, and badges.
61
+ * Matches the admin panel sidebar style exactly.
62
+ */
63
+ declare function SidebarNav({ groups, currentPath, onNavigate }: SidebarNavProps): react_jsx_runtime.JSX.Element;
64
+
7
65
  interface InputProps extends InputHTMLAttributes<HTMLInputElement> {
8
66
  error?: boolean;
9
67
  }
@@ -52,11 +110,12 @@ interface ConfirmDialogProps {
52
110
  title: string;
53
111
  message: string;
54
112
  confirmLabel?: string;
113
+ confirmPending?: boolean;
55
114
  variant?: 'danger' | 'default';
56
115
  onConfirm: () => void;
57
116
  onCancel: () => void;
58
117
  }
59
- declare function ConfirmDialog({ isOpen, title, message, confirmLabel, variant, onConfirm, onCancel, }: ConfirmDialogProps): react.ReactPortal | null;
118
+ declare function ConfirmDialog({ isOpen, title, message, confirmLabel, confirmPending, variant, onConfirm, onCancel, }: ConfirmDialogProps): react.ReactPortal | null;
60
119
 
61
120
  interface StatusBadgeProps {
62
121
  status: string;
@@ -196,4 +255,4 @@ declare const IconStar: (p: IconProps) => react_jsx_runtime.JSX.Element;
196
255
  declare const IconDiamond: (p: IconProps) => react_jsx_runtime.JSX.Element;
197
256
  declare const IconCircle: (p: IconProps) => react_jsx_runtime.JSX.Element;
198
257
 
199
- export { AddressDisplay, AlertBanner, Button, type ButtonProps, type ButtonVariant, ChainInput, ConfirmDialog, CustomSelect, DataTable, EmptyState, Field, FormModal, IconArrowRight, IconBack, IconChain, IconCheck, IconChevronDown, IconChevronUp, IconChevronsDown, IconChevronsRight, IconCircle, IconDiamond, IconEdit, IconPlay, IconPlus, IconQuests, IconSearch, IconSettings, IconStar, IconTracks, IconTrash, IconUndo, IconX, Input, type InputProps, JsonPanel, JsonToggleButton, type MemoCondition, MemoConditionsEditor, PageShell, SearchInput, Section, Select, type SelectOption, type SelectProps, StatusBadge, Textarea, type TextareaProps, tagColor };
258
+ export { AddressDisplay, AlertBanner, AppLogo, Button, type ButtonProps, type ButtonVariant, ChainInput, ConfirmDialog, CustomSelect, DashboardLayout, DataTable, EmptyState, Field, FormModal, IconArrowRight, IconBack, IconChain, IconCheck, IconChevronDown, IconChevronUp, IconChevronsDown, IconChevronsRight, IconCircle, IconDiamond, IconEdit, IconPlay, IconPlus, IconQuests, IconSearch, IconSettings, IconStar, IconTracks, IconTrash, IconUndo, IconX, Input, type InputProps, JsonPanel, JsonToggleButton, type MemoCondition, MemoConditionsEditor, type NavGroup, type NavItem, PageShell, SearchInput, Section, Select, type SelectOption, type SelectProps, SidebarNav, StatusBadge, Textarea, type TextareaProps, tagColor };
package/dist/index.js CHANGED
@@ -1,10 +1,195 @@
1
+ // src/components/DashboardLayout.tsx
2
+ import { useState } from "react";
3
+ import { Menu } from "lucide-react";
4
+ import { jsx, jsxs } from "react/jsx-runtime";
5
+ function DashboardLayout({ logo, nav, footer, children }) {
6
+ const [mobileOpen, setMobileOpen] = useState(false);
7
+ return /* @__PURE__ */ jsxs("div", { className: "min-h-screen flex sphere-dashboard", style: { background: "var(--bg-root)" }, children: [
8
+ mobileOpen && /* @__PURE__ */ jsx(
9
+ "div",
10
+ {
11
+ className: "lg:hidden fixed inset-0 bg-black/50 z-40",
12
+ onClick: () => setMobileOpen(false)
13
+ }
14
+ ),
15
+ /* @__PURE__ */ jsxs(
16
+ "aside",
17
+ {
18
+ className: `fixed lg:static inset-y-0 left-0 z-50 w-56 shrink-0 flex flex-col transition-transform lg:translate-x-0 ${mobileOpen ? "translate-x-0" : "-translate-x-full"}`,
19
+ style: {
20
+ background: "linear-gradient(180deg, rgba(255,111,0,0.03) 0%, var(--bg-root) 40%)",
21
+ borderRight: "1px solid var(--border)"
22
+ },
23
+ children: [
24
+ /* @__PURE__ */ jsx(
25
+ "div",
26
+ {
27
+ className: "absolute top-0 left-0 right-0 h-px",
28
+ style: { background: "linear-gradient(90deg, transparent, var(--accent), transparent)" }
29
+ }
30
+ ),
31
+ /* @__PURE__ */ jsx("div", { className: "px-5 py-5", style: { borderBottom: "1px solid var(--border)" }, children: logo }),
32
+ /* @__PURE__ */ jsx("nav", { className: "flex-1 px-3 py-3 flex flex-col overflow-y-auto", children: nav }),
33
+ footer && /* @__PURE__ */ jsx("div", { className: "px-3 py-4", style: { borderTop: "1px solid var(--border)" }, children: footer })
34
+ ]
35
+ }
36
+ ),
37
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 flex flex-col min-w-0", children: [
38
+ /* @__PURE__ */ jsx("div", { className: "lg:hidden flex items-center gap-3 p-4", style: { borderBottom: "1px solid var(--border)" }, children: /* @__PURE__ */ jsx(
39
+ "button",
40
+ {
41
+ onClick: () => setMobileOpen(true),
42
+ style: { color: "var(--text-muted)" },
43
+ children: /* @__PURE__ */ jsx(Menu, { className: "w-5 h-5" })
44
+ }
45
+ ) }),
46
+ /* @__PURE__ */ jsx("main", { className: "flex-1 overflow-auto", children })
47
+ ] })
48
+ ] });
49
+ }
50
+
51
+ // src/components/AppLogo.tsx
52
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
53
+ function AppLogo({ icon, title, subtitle, onClick }) {
54
+ const content = /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-2.5", children: [
55
+ /* @__PURE__ */ jsx2(
56
+ "div",
57
+ {
58
+ className: "w-8 h-8 rounded-lg flex items-center justify-center text-white text-xs relative",
59
+ style: {
60
+ background: "var(--accent)",
61
+ boxShadow: "0 0 16px rgba(255, 111, 0, 0.2)",
62
+ fontFamily: "var(--font-display)",
63
+ letterSpacing: "0.04em"
64
+ },
65
+ children: icon ?? title.slice(0, 2)
66
+ }
67
+ ),
68
+ /* @__PURE__ */ jsxs2("div", { children: [
69
+ /* @__PURE__ */ jsx2(
70
+ "div",
71
+ {
72
+ className: "text-sm",
73
+ style: {
74
+ fontFamily: "var(--font-display)",
75
+ color: "var(--text-primary)",
76
+ letterSpacing: "0.04em",
77
+ textTransform: "uppercase"
78
+ },
79
+ children: title
80
+ }
81
+ ),
82
+ subtitle && /* @__PURE__ */ jsx2(
83
+ "div",
84
+ {
85
+ className: "text-[10px] tracking-widest uppercase",
86
+ style: { color: "var(--text-muted)", fontFamily: "var(--font-body)" },
87
+ children: subtitle
88
+ }
89
+ )
90
+ ] })
91
+ ] });
92
+ if (onClick) {
93
+ return /* @__PURE__ */ jsx2("button", { onClick, className: "cursor-pointer text-left", children: content });
94
+ }
95
+ return content;
96
+ }
97
+
98
+ // src/components/SidebarNav.tsx
99
+ import { Fragment, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
100
+ function SvgIcon({ d }) {
101
+ return /* @__PURE__ */ jsx3(
102
+ "svg",
103
+ {
104
+ width: "16",
105
+ height: "16",
106
+ className: "w-4 h-4 shrink-0",
107
+ viewBox: "0 0 24 24",
108
+ fill: "none",
109
+ stroke: "currentColor",
110
+ strokeWidth: "1.5",
111
+ strokeLinecap: "round",
112
+ strokeLinejoin: "round",
113
+ children: /* @__PURE__ */ jsx3("path", { d })
114
+ }
115
+ );
116
+ }
117
+ function SidebarNav({ groups, currentPath, onNavigate }) {
118
+ const isActive = (to) => {
119
+ if (to === "/") return currentPath === "/";
120
+ return currentPath === to || currentPath.startsWith(to + "/");
121
+ };
122
+ return /* @__PURE__ */ jsx3(Fragment, { children: groups.map((group, gi) => /* @__PURE__ */ jsxs3("div", { children: [
123
+ group.label && /* @__PURE__ */ jsx3(
124
+ "div",
125
+ {
126
+ className: "px-3 pt-5 pb-1.5",
127
+ style: {
128
+ fontFamily: "var(--font-body)",
129
+ fontSize: "0.6rem",
130
+ fontWeight: 600,
131
+ letterSpacing: "0.1em",
132
+ textTransform: "uppercase",
133
+ color: "var(--text-muted)"
134
+ },
135
+ children: group.label
136
+ }
137
+ ),
138
+ /* @__PURE__ */ jsx3("div", { className: "flex flex-col gap-0.5", children: group.items.map((item) => {
139
+ const active = isActive(item.to);
140
+ return /* @__PURE__ */ jsxs3(
141
+ "button",
142
+ {
143
+ onClick: () => onNavigate(item.to),
144
+ className: "flex items-center gap-3 px-3 py-2 rounded-lg text-[0.8125rem] transition-all w-full text-left",
145
+ style: active ? {
146
+ background: "var(--accent-glow)",
147
+ color: "var(--accent-text)",
148
+ fontWeight: 600,
149
+ fontFamily: "var(--font-body)",
150
+ boxShadow: "inset 2px 0 0 var(--accent)"
151
+ } : {
152
+ color: "var(--text-secondary)",
153
+ fontFamily: "var(--font-body)"
154
+ },
155
+ onMouseEnter: (e) => {
156
+ if (!active) {
157
+ e.currentTarget.style.background = "var(--bg-hover)";
158
+ e.currentTarget.style.color = "var(--text-primary)";
159
+ }
160
+ },
161
+ onMouseLeave: (e) => {
162
+ if (!active) {
163
+ e.currentTarget.style.background = "transparent";
164
+ e.currentTarget.style.color = "var(--text-secondary)";
165
+ }
166
+ },
167
+ children: [
168
+ item.iconElement ?? (item.icon && /* @__PURE__ */ jsx3(SvgIcon, { d: item.icon })),
169
+ item.label,
170
+ item.badge != null && item.badge > 0 && /* @__PURE__ */ jsx3(
171
+ "span",
172
+ {
173
+ className: "ml-auto min-w-5 h-5 flex items-center justify-center rounded-full text-[10px] font-bold text-white px-1.5",
174
+ style: { background: "var(--accent)" },
175
+ children: item.badge
176
+ }
177
+ )
178
+ ]
179
+ },
180
+ item.to
181
+ );
182
+ }) })
183
+ ] }, gi)) });
184
+ }
185
+
1
186
  // src/components/Input.tsx
2
187
  import { forwardRef } from "react";
3
- import { jsx, jsxs } from "react/jsx-runtime";
188
+ import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
4
189
  var inputBase = "w-full px-4 py-2.5 bg-neutral-100 dark:bg-white/6 text-neutral-900 dark:text-white placeholder-neutral-400 dark:placeholder-white/25 rounded-xl border border-neutral-200 dark:border-white/8 focus:outline-none focus:border-orange-500 dark:focus:border-brand-orange transition-colors disabled:opacity-50";
5
190
  var inputError = "border-red-400 dark:border-red-500/50 focus:border-red-500";
6
191
  var Input = forwardRef(
7
- ({ className = "", error, ...props }, ref) => /* @__PURE__ */ jsx(
192
+ ({ className = "", error, ...props }, ref) => /* @__PURE__ */ jsx4(
8
193
  "input",
9
194
  {
10
195
  ref,
@@ -15,7 +200,7 @@ var Input = forwardRef(
15
200
  );
16
201
  Input.displayName = "Input";
17
202
  var Textarea = forwardRef(
18
- ({ className = "", error, ...props }, ref) => /* @__PURE__ */ jsx(
203
+ ({ className = "", error, ...props }, ref) => /* @__PURE__ */ jsx4(
19
204
  "textarea",
20
205
  {
21
206
  ref,
@@ -26,7 +211,7 @@ var Textarea = forwardRef(
26
211
  );
27
212
  Textarea.displayName = "Textarea";
28
213
  var Select = forwardRef(
29
- ({ className = "", error, children, ...props }, ref) => /* @__PURE__ */ jsx(
214
+ ({ className = "", error, children, ...props }, ref) => /* @__PURE__ */ jsx4(
30
215
  "select",
31
216
  {
32
217
  ref,
@@ -48,7 +233,7 @@ var buttonVariants = {
48
233
  ghost: "text-neutral-500 dark:text-white/45 hover:text-neutral-900 dark:hover:text-white hover:bg-neutral-100 dark:hover:bg-white/6"
49
234
  };
50
235
  var Button = forwardRef(
51
- ({ variant = "primary", icon, children, className = "", disabled, ...props }, ref) => /* @__PURE__ */ jsxs(
236
+ ({ variant = "primary", icon, children, className = "", disabled, ...props }, ref) => /* @__PURE__ */ jsxs4(
52
237
  "button",
53
238
  {
54
239
  ref,
@@ -65,21 +250,21 @@ var Button = forwardRef(
65
250
  Button.displayName = "Button";
66
251
 
67
252
  // src/components/Field.tsx
68
- import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
253
+ import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
69
254
  function Field({ label, required, error, hint, className, children }) {
70
- return /* @__PURE__ */ jsxs2("div", { className, children: [
71
- /* @__PURE__ */ jsxs2("label", { className: "text-xs block mb-1", style: { color: "var(--text-muted)" }, children: [
255
+ return /* @__PURE__ */ jsxs5("div", { className, children: [
256
+ /* @__PURE__ */ jsxs5("label", { className: "text-xs block mb-1", style: { color: "var(--text-muted)" }, children: [
72
257
  label,
73
- required && /* @__PURE__ */ jsx2("span", { className: "text-red-400 ml-0.5", children: "*" })
258
+ required && /* @__PURE__ */ jsx5("span", { className: "text-red-400 ml-0.5", children: "*" })
74
259
  ] }),
75
260
  children,
76
- hint && /* @__PURE__ */ jsx2("p", { className: "text-[10px] mt-1", style: { color: "var(--text-muted)" }, children: hint }),
77
- error && /* @__PURE__ */ jsx2("p", { className: "text-xs text-red-400 mt-1", children: error })
261
+ hint && /* @__PURE__ */ jsx5("p", { className: "text-[10px] mt-1", style: { color: "var(--text-muted)" }, children: hint }),
262
+ error && /* @__PURE__ */ jsx5("p", { className: "text-xs text-red-400 mt-1", children: error })
78
263
  ] });
79
264
  }
80
265
  function Section({ title, children }) {
81
- return /* @__PURE__ */ jsxs2("div", { children: [
82
- /* @__PURE__ */ jsx2("h2", { className: "text-sm font-semibold mb-3 pb-2 border-b", style: { color: "var(--text-secondary)", borderColor: "var(--border)" }, children: title }),
266
+ return /* @__PURE__ */ jsxs5("div", { children: [
267
+ /* @__PURE__ */ jsx5("h2", { className: "text-sm font-semibold mb-3 pb-2 border-b", style: { color: "var(--text-secondary)", borderColor: "var(--border)" }, children: title }),
83
268
  children
84
269
  ] });
85
270
  }
@@ -87,7 +272,7 @@ function Section({ title, children }) {
87
272
  // src/components/FormModal.tsx
88
273
  import { useEffect } from "react";
89
274
  import { createPortal } from "react-dom";
90
- import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
275
+ import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
91
276
  function FormModal({ title, isOpen, onClose, children, maxWidth = "max-w-lg" }) {
92
277
  useEffect(() => {
93
278
  if (!isOpen) return;
@@ -99,7 +284,7 @@ function FormModal({ title, isOpen, onClose, children, maxWidth = "max-w-lg" })
99
284
  }, [isOpen, onClose]);
100
285
  if (!isOpen) return null;
101
286
  return createPortal(
102
- /* @__PURE__ */ jsx3("div", { className: "fixed inset-0 flex items-start justify-center z-50 p-4 overflow-y-auto", style: { background: "rgba(0,0,0,0.7)" }, children: /* @__PURE__ */ jsxs3(
287
+ /* @__PURE__ */ jsx6("div", { className: "fixed inset-0 flex items-start justify-center z-50 p-4 overflow-y-auto", style: { background: "rgba(0,0,0,0.7)" }, children: /* @__PURE__ */ jsxs6(
103
288
  "div",
104
289
  {
105
290
  className: `w-full ${maxWidth} mt-12 mb-12 animate-fade-in`,
@@ -111,9 +296,9 @@ function FormModal({ title, isOpen, onClose, children, maxWidth = "max-w-lg" })
111
296
  padding: "1.5rem"
112
297
  },
113
298
  children: [
114
- /* @__PURE__ */ jsxs3("div", { className: "flex items-center justify-between mb-5", children: [
115
- /* @__PURE__ */ jsx3("h2", { style: { fontFamily: "var(--font-display)", fontSize: "1.05rem", letterSpacing: "0.04em", color: "var(--text-primary)" }, children: title }),
116
- /* @__PURE__ */ jsx3(
299
+ /* @__PURE__ */ jsxs6("div", { className: "flex items-center justify-between mb-5", children: [
300
+ /* @__PURE__ */ jsx6("h2", { style: { fontFamily: "var(--font-display)", fontSize: "1.05rem", letterSpacing: "0.04em", color: "var(--text-primary)" }, children: title }),
301
+ /* @__PURE__ */ jsx6(
117
302
  "button",
118
303
  {
119
304
  onClick: onClose,
@@ -136,12 +321,13 @@ function FormModal({ title, isOpen, onClose, children, maxWidth = "max-w-lg" })
136
321
  // src/components/ConfirmDialog.tsx
137
322
  import { useEffect as useEffect2 } from "react";
138
323
  import { createPortal as createPortal2 } from "react-dom";
139
- import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
324
+ import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
140
325
  function ConfirmDialog({
141
326
  isOpen,
142
327
  title,
143
328
  message,
144
329
  confirmLabel = "Confirm",
330
+ confirmPending,
145
331
  variant = "default",
146
332
  onConfirm,
147
333
  onCancel
@@ -156,17 +342,24 @@ function ConfirmDialog({
156
342
  }, [isOpen, onCancel]);
157
343
  if (!isOpen) return null;
158
344
  return createPortal2(
159
- /* @__PURE__ */ jsx4("div", { className: "fixed inset-0 flex items-center justify-center z-50 p-4", style: { background: "rgba(0,0,0,0.7)" }, children: /* @__PURE__ */ jsxs4("div", { className: "admin-card p-6 w-full max-w-sm animate-fade-in", children: [
160
- /* @__PURE__ */ jsx4("h3", { className: "font-semibold text-white mb-2", children: title }),
161
- /* @__PURE__ */ jsx4("p", { className: "text-sm mb-5", style: { color: "var(--text-muted)" }, children: message }),
162
- /* @__PURE__ */ jsxs4("div", { className: "flex gap-3", children: [
163
- /* @__PURE__ */ jsx4("button", { onClick: onCancel, className: "btn-secondary flex-1", children: "Cancel" }),
164
- /* @__PURE__ */ jsx4(
345
+ /* @__PURE__ */ jsx7("div", { className: "fixed inset-0 flex items-center justify-center z-50 p-4", style: { background: "rgba(0,0,0,0.7)" }, children: /* @__PURE__ */ jsxs7("div", { className: "admin-card p-6 w-full max-w-sm animate-fade-in", children: [
346
+ /* @__PURE__ */ jsx7("h3", { className: "font-semibold text-white mb-2", children: title }),
347
+ /* @__PURE__ */ jsx7("p", { className: "text-sm mb-5", style: { color: "var(--text-muted)" }, children: message }),
348
+ /* @__PURE__ */ jsxs7("div", { className: "flex gap-3", children: [
349
+ /* @__PURE__ */ jsx7("button", { onClick: onCancel, disabled: confirmPending, className: "btn-secondary flex-1", children: "Cancel" }),
350
+ /* @__PURE__ */ jsxs7(
165
351
  "button",
166
352
  {
167
353
  onClick: onConfirm,
168
- className: `flex-1 ${variant === "danger" ? "btn-danger" : "btn-primary"}`,
169
- children: confirmLabel
354
+ disabled: confirmPending,
355
+ className: `flex-1 inline-flex items-center justify-center gap-2 ${variant === "danger" ? "btn-danger" : "btn-primary"}`,
356
+ children: [
357
+ confirmPending && /* @__PURE__ */ jsxs7("svg", { className: "w-4 h-4 animate-spin", viewBox: "0 0 24 24", fill: "none", children: [
358
+ /* @__PURE__ */ jsx7("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
359
+ /* @__PURE__ */ jsx7("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z" })
360
+ ] }),
361
+ confirmLabel
362
+ ]
170
363
  }
171
364
  )
172
365
  ] })
@@ -176,7 +369,7 @@ function ConfirmDialog({
176
369
  }
177
370
 
178
371
  // src/components/StatusBadge.tsx
179
- import { jsx as jsx5 } from "react/jsx-runtime";
372
+ import { jsx as jsx8 } from "react/jsx-runtime";
180
373
  var STATUS_COLORS = {
181
374
  ACTIVE: "badge-green",
182
375
  DRAFT: "badge-gray",
@@ -187,14 +380,14 @@ var STATUS_COLORS = {
187
380
  REJECTED: "badge-red"
188
381
  };
189
382
  function StatusBadge({ status, className = "" }) {
190
- return /* @__PURE__ */ jsx5("span", { className: `badge ${STATUS_COLORS[status] ?? "badge-gray"} ${className}`, children: status });
383
+ return /* @__PURE__ */ jsx8("span", { className: `badge ${STATUS_COLORS[status] ?? "badge-gray"} ${className}`, children: status });
191
384
  }
192
385
 
193
386
  // src/components/SearchInput.tsx
194
- import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
387
+ import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
195
388
  function SearchInput({ value, onChange, placeholder = "Search..." }) {
196
- return /* @__PURE__ */ jsxs5("div", { className: "relative", children: [
197
- /* @__PURE__ */ jsxs5(
389
+ return /* @__PURE__ */ jsxs8("div", { className: "relative", children: [
390
+ /* @__PURE__ */ jsxs8(
198
391
  "svg",
199
392
  {
200
393
  width: "16",
@@ -208,12 +401,12 @@ function SearchInput({ value, onChange, placeholder = "Search..." }) {
208
401
  className: "absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4",
209
402
  style: { color: "var(--text-muted)" },
210
403
  children: [
211
- /* @__PURE__ */ jsx6("circle", { cx: "11", cy: "11", r: "8" }),
212
- /* @__PURE__ */ jsx6("path", { d: "m21 21-4.35-4.35" })
404
+ /* @__PURE__ */ jsx9("circle", { cx: "11", cy: "11", r: "8" }),
405
+ /* @__PURE__ */ jsx9("path", { d: "m21 21-4.35-4.35" })
213
406
  ]
214
407
  }
215
408
  ),
216
- /* @__PURE__ */ jsx6(
409
+ /* @__PURE__ */ jsx9(
217
410
  "input",
218
411
  {
219
412
  type: "text",
@@ -223,7 +416,7 @@ function SearchInput({ value, onChange, placeholder = "Search..." }) {
223
416
  placeholder
224
417
  }
225
418
  ),
226
- value && /* @__PURE__ */ jsx6(
419
+ value && /* @__PURE__ */ jsx9(
227
420
  "button",
228
421
  {
229
422
  onClick: () => onChange(""),
@@ -238,26 +431,26 @@ function SearchInput({ value, onChange, placeholder = "Search..." }) {
238
431
  }
239
432
 
240
433
  // src/components/EmptyState.tsx
241
- import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
434
+ import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
242
435
  function EmptyState({ title, description, action }) {
243
- return /* @__PURE__ */ jsxs6("div", { className: "flex flex-col items-center justify-center py-16 text-center", children: [
244
- /* @__PURE__ */ jsx7(
436
+ return /* @__PURE__ */ jsxs9("div", { className: "flex flex-col items-center justify-center py-16 text-center", children: [
437
+ /* @__PURE__ */ jsx10(
245
438
  "div",
246
439
  {
247
440
  className: "w-12 h-12 rounded-xl flex items-center justify-center mb-4",
248
441
  style: { background: "var(--bg-elevated)", border: "1px solid var(--border)" },
249
- children: /* @__PURE__ */ jsx7("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", style: { color: "var(--text-muted)" }, children: /* @__PURE__ */ jsx7("path", { d: "M20 13V6a2 2 0 0 0-2-2H6a2 2 0 0 0-2 2v7m16 0v5a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2v-5m16 0h-2.586a1 1 0 0 0-.707.293l-2.414 2.414a1 1 0 0 1-.707.293h-3.172a1 1 0 0 1-.707-.293l-2.414-2.414A1 1 0 0 0 6.586 13H4" }) })
442
+ children: /* @__PURE__ */ jsx10("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", style: { color: "var(--text-muted)" }, children: /* @__PURE__ */ jsx10("path", { d: "M20 13V6a2 2 0 0 0-2-2H6a2 2 0 0 0-2 2v7m16 0v5a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2v-5m16 0h-2.586a1 1 0 0 0-.707.293l-2.414 2.414a1 1 0 0 1-.707.293h-3.172a1 1 0 0 1-.707-.293l-2.414-2.414A1 1 0 0 0 6.586 13H4" }) })
250
443
  }
251
444
  ),
252
- /* @__PURE__ */ jsx7("div", { className: "text-sm font-medium mb-1", style: { color: "var(--text-secondary)" }, children: title }),
253
- description && /* @__PURE__ */ jsx7("div", { className: "text-xs mb-4", style: { color: "var(--text-muted)" }, children: description }),
445
+ /* @__PURE__ */ jsx10("div", { className: "text-sm font-medium mb-1", style: { color: "var(--text-secondary)" }, children: title }),
446
+ description && /* @__PURE__ */ jsx10("div", { className: "text-xs mb-4", style: { color: "var(--text-muted)" }, children: description }),
254
447
  action
255
448
  ] });
256
449
  }
257
450
 
258
451
  // src/components/CustomSelect.tsx
259
- import { useState, useRef, useEffect as useEffect3 } from "react";
260
- import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
452
+ import { useState as useState2, useRef, useEffect as useEffect3 } from "react";
453
+ import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
261
454
  function CustomSelect({
262
455
  options,
263
456
  value,
@@ -266,7 +459,7 @@ function CustomSelect({
266
459
  className = "",
267
460
  size = "md"
268
461
  }) {
269
- const [open, setOpen] = useState(false);
462
+ const [open, setOpen] = useState2(false);
270
463
  const ref = useRef(null);
271
464
  const selected = options.find((o) => o.value === value);
272
465
  const label = selected?.label ?? placeholder ?? "Select...";
@@ -287,8 +480,8 @@ function CustomSelect({
287
480
  return () => document.removeEventListener("keydown", handler);
288
481
  }, [open]);
289
482
  const textSize = size === "sm" ? "text-xs" : "text-sm";
290
- return /* @__PURE__ */ jsxs7("div", { ref, className: `relative ${className}`, children: [
291
- /* @__PURE__ */ jsxs7(
483
+ return /* @__PURE__ */ jsxs10("div", { ref, className: `relative ${className}`, children: [
484
+ /* @__PURE__ */ jsxs10(
292
485
  "button",
293
486
  {
294
487
  type: "button",
@@ -296,8 +489,8 @@ function CustomSelect({
296
489
  className: `admin-input w-full flex items-center justify-between gap-2 ${textSize} text-left`,
297
490
  style: { color: selected ? "var(--text-primary)" : "var(--text-muted)" },
298
491
  children: [
299
- /* @__PURE__ */ jsx8("span", { className: "truncate", children: label }),
300
- /* @__PURE__ */ jsx8(
492
+ /* @__PURE__ */ jsx11("span", { className: "truncate", children: label }),
493
+ /* @__PURE__ */ jsx11(
301
494
  "svg",
302
495
  {
303
496
  width: "12",
@@ -313,13 +506,13 @@ function CustomSelect({
313
506
  color: "var(--text-muted)",
314
507
  transform: open ? "rotate(180deg)" : "rotate(0deg)"
315
508
  },
316
- children: /* @__PURE__ */ jsx8("path", { d: "M3 4.5L6 7.5L9 4.5" })
509
+ children: /* @__PURE__ */ jsx11("path", { d: "M3 4.5L6 7.5L9 4.5" })
317
510
  }
318
511
  )
319
512
  ]
320
513
  }
321
514
  ),
322
- open && /* @__PURE__ */ jsx8(
515
+ open && /* @__PURE__ */ jsx11(
323
516
  "div",
324
517
  {
325
518
  className: "absolute left-0 right-0 top-full mt-1 z-30 py-1 max-h-48 overflow-y-auto",
@@ -329,7 +522,7 @@ function CustomSelect({
329
522
  borderRadius: "var(--radius-md)",
330
523
  boxShadow: "0 8px 24px rgba(0,0,0,0.4)"
331
524
  },
332
- children: options.map((opt) => /* @__PURE__ */ jsx8(
525
+ children: options.map((opt) => /* @__PURE__ */ jsx11(
333
526
  "button",
334
527
  {
335
528
  type: "button",
@@ -358,22 +551,22 @@ function CustomSelect({
358
551
  }
359
552
 
360
553
  // src/components/PageShell.tsx
361
- import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
554
+ import { jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
362
555
  function PageShell({ title, subtitle, action, maxWidth, children }) {
363
- return /* @__PURE__ */ jsxs8("div", { className: `p-6 lg:p-8 ${maxWidth ?? ""}`, children: [
364
- /* @__PURE__ */ jsxs8("div", { className: "page-header", children: [
365
- /* @__PURE__ */ jsxs8("div", { children: [
366
- /* @__PURE__ */ jsx9("h1", { className: "page-title", children: title }),
367
- subtitle && /* @__PURE__ */ jsx9("p", { className: "page-subtitle", children: subtitle })
556
+ return /* @__PURE__ */ jsxs11("div", { className: `p-6 lg:p-8 ${maxWidth ?? ""}`, children: [
557
+ /* @__PURE__ */ jsxs11("div", { className: "page-header", children: [
558
+ /* @__PURE__ */ jsxs11("div", { children: [
559
+ /* @__PURE__ */ jsx12("h1", { className: "page-title", children: title }),
560
+ subtitle && /* @__PURE__ */ jsx12("p", { className: "page-subtitle", children: subtitle })
368
561
  ] }),
369
562
  action
370
563
  ] }),
371
- /* @__PURE__ */ jsx9("div", { className: "animate-fade-in", children })
564
+ /* @__PURE__ */ jsx12("div", { className: "animate-fade-in", children })
372
565
  ] });
373
566
  }
374
567
 
375
568
  // src/components/DataTable.tsx
376
- import { useState as useState2, useMemo } from "react";
569
+ import { useState as useState3, useMemo } from "react";
377
570
  import {
378
571
  useReactTable,
379
572
  getCoreRowModel,
@@ -381,7 +574,7 @@ import {
381
574
  getFilteredRowModel,
382
575
  flexRender
383
576
  } from "@tanstack/react-table";
384
- import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
577
+ import { jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
385
578
  function DataTable({
386
579
  columns,
387
580
  data,
@@ -391,8 +584,8 @@ function DataTable({
391
584
  enableSearch = true,
392
585
  onRowClick
393
586
  }) {
394
- const [sorting, setSorting] = useState2([]);
395
- const [globalFilter, setGlobalFilter] = useState2("");
587
+ const [sorting, setSorting] = useState3([]);
588
+ const [globalFilter, setGlobalFilter] = useState3("");
396
589
  const stableColumns = useMemo(() => columns, [columns]);
397
590
  const table = useReactTable({
398
591
  data,
@@ -405,10 +598,10 @@ function DataTable({
405
598
  getFilteredRowModel: getFilteredRowModel()
406
599
  });
407
600
  if (isLoading) {
408
- return /* @__PURE__ */ jsx10("div", { className: "py-12 text-center", style: { color: "var(--text-muted)" }, children: "Loading\u2026" });
601
+ return /* @__PURE__ */ jsx13("div", { className: "py-12 text-center", style: { color: "var(--text-muted)" }, children: "Loading\u2026" });
409
602
  }
410
- return /* @__PURE__ */ jsxs9("div", { children: [
411
- enableSearch && /* @__PURE__ */ jsx10("div", { className: "mb-4 max-w-xs", children: /* @__PURE__ */ jsx10(
603
+ return /* @__PURE__ */ jsxs12("div", { children: [
604
+ enableSearch && /* @__PURE__ */ jsx13("div", { className: "mb-4 max-w-xs", children: /* @__PURE__ */ jsx13(
412
605
  SearchInput,
413
606
  {
414
607
  value: globalFilter,
@@ -416,21 +609,21 @@ function DataTable({
416
609
  placeholder: searchPlaceholder ?? "Search..."
417
610
  }
418
611
  ) }),
419
- table.getRowModel().rows.length === 0 ? /* @__PURE__ */ jsx10(EmptyState, { title: emptyMessage }) : /* @__PURE__ */ jsx10("div", { className: "admin-card overflow-hidden", children: /* @__PURE__ */ jsxs9("table", { className: "admin-table", children: [
420
- /* @__PURE__ */ jsx10("thead", { children: table.getHeaderGroups().map((hg) => /* @__PURE__ */ jsx10("tr", { children: hg.headers.map((header) => /* @__PURE__ */ jsx10(
612
+ table.getRowModel().rows.length === 0 ? /* @__PURE__ */ jsx13(EmptyState, { title: emptyMessage }) : /* @__PURE__ */ jsx13("div", { className: "admin-card overflow-hidden", children: /* @__PURE__ */ jsxs12("table", { className: "admin-table", children: [
613
+ /* @__PURE__ */ jsx13("thead", { children: table.getHeaderGroups().map((hg) => /* @__PURE__ */ jsx13("tr", { children: hg.headers.map((header) => /* @__PURE__ */ jsx13(
421
614
  "th",
422
615
  {
423
616
  className: header.column.getCanSort() ? "cursor-pointer select-none" : "",
424
617
  onClick: header.column.getToggleSortingHandler(),
425
- children: /* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-1", children: [
618
+ children: /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-1", children: [
426
619
  flexRender(header.column.columnDef.header, header.getContext()),
427
- header.column.getIsSorted() === "asc" && /* @__PURE__ */ jsx10("span", { style: { color: "var(--accent-text)" }, children: "\u25B2" }),
428
- header.column.getIsSorted() === "desc" && /* @__PURE__ */ jsx10("span", { style: { color: "var(--accent-text)" }, children: "\u25BC" })
620
+ header.column.getIsSorted() === "asc" && /* @__PURE__ */ jsx13("span", { style: { color: "var(--accent-text)" }, children: "\u25B2" }),
621
+ header.column.getIsSorted() === "desc" && /* @__PURE__ */ jsx13("span", { style: { color: "var(--accent-text)" }, children: "\u25BC" })
429
622
  ] })
430
623
  },
431
624
  header.id
432
625
  )) }, hg.id)) }),
433
- /* @__PURE__ */ jsx10("tbody", { children: table.getRowModel().rows.map((row) => /* @__PURE__ */ jsx10(
626
+ /* @__PURE__ */ jsx13("tbody", { children: table.getRowModel().rows.map((row) => /* @__PURE__ */ jsx13(
434
627
  "tr",
435
628
  {
436
629
  onClick: () => onRowClick?.(row.original),
@@ -442,7 +635,7 @@ function DataTable({
442
635
  onMouseLeave: (e) => {
443
636
  if (onRowClick) e.currentTarget.style.background = "";
444
637
  },
445
- children: row.getVisibleCells().map((cell) => /* @__PURE__ */ jsx10("td", { children: flexRender(cell.column.columnDef.cell, cell.getContext()) }, cell.id))
638
+ children: row.getVisibleCells().map((cell) => /* @__PURE__ */ jsx13("td", { children: flexRender(cell.column.columnDef.cell, cell.getContext()) }, cell.id))
446
639
  },
447
640
  row.id
448
641
  )) })
@@ -451,7 +644,7 @@ function DataTable({
451
644
  }
452
645
 
453
646
  // src/components/AlertBanner.tsx
454
- import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
647
+ import { jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
455
648
  var STYLES = {
456
649
  warning: {
457
650
  bg: "rgba(251,191,36,0.06)",
@@ -468,16 +661,16 @@ var STYLES = {
468
661
  };
469
662
  function AlertBanner({ type, title, children }) {
470
663
  const s = STYLES[type];
471
- return /* @__PURE__ */ jsx11(
664
+ return /* @__PURE__ */ jsx14(
472
665
  "div",
473
666
  {
474
667
  className: "rounded-lg p-3 text-sm",
475
668
  style: { background: s.bg, border: `1px solid ${s.border}` },
476
- children: /* @__PURE__ */ jsxs10("div", { className: "flex items-start gap-2", children: [
477
- /* @__PURE__ */ jsx11("span", { className: "flex-shrink-0 text-sm leading-5", children: s.icon }),
478
- /* @__PURE__ */ jsxs10("div", { children: [
479
- /* @__PURE__ */ jsx11("div", { className: "font-medium text-xs mb-0.5", style: { color: s.titleColor }, children: title }),
480
- /* @__PURE__ */ jsx11("div", { style: { color: "var(--text-muted)", fontSize: "0.75rem", lineHeight: "1.4" }, children })
669
+ children: /* @__PURE__ */ jsxs13("div", { className: "flex items-start gap-2", children: [
670
+ /* @__PURE__ */ jsx14("span", { className: "flex-shrink-0 text-sm leading-5", children: s.icon }),
671
+ /* @__PURE__ */ jsxs13("div", { children: [
672
+ /* @__PURE__ */ jsx14("div", { className: "font-medium text-xs mb-0.5", style: { color: s.titleColor }, children: title }),
673
+ /* @__PURE__ */ jsx14("div", { style: { color: "var(--text-muted)", fontSize: "0.75rem", lineHeight: "1.4" }, children })
481
674
  ] })
482
675
  ] })
483
676
  }
@@ -485,8 +678,8 @@ function AlertBanner({ type, title, children }) {
485
678
  }
486
679
 
487
680
  // src/components/AddressDisplay.tsx
488
- import { useState as useState3, useCallback } from "react";
489
- import { Fragment, jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
681
+ import { useState as useState4, useCallback } from "react";
682
+ import { Fragment as Fragment2, jsx as jsx15, jsxs as jsxs14 } from "react/jsx-runtime";
490
683
  function truncateAddress(address) {
491
684
  const prefix = "DIRECT://";
492
685
  if (address.startsWith(prefix)) {
@@ -501,7 +694,7 @@ function truncateAddress(address) {
501
694
  return address;
502
695
  }
503
696
  function AddressDisplay({ address, nametag, truncate = true }) {
504
- const [copied, setCopied] = useState3(false);
697
+ const [copied, setCopied] = useState4(false);
505
698
  const handleCopy = useCallback(() => {
506
699
  navigator.clipboard.writeText(address).then(() => {
507
700
  setCopied(true);
@@ -509,13 +702,13 @@ function AddressDisplay({ address, nametag, truncate = true }) {
509
702
  });
510
703
  }, [address]);
511
704
  const displayAddress = truncate ? truncateAddress(address) : address;
512
- return /* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-1.5 min-w-0", children: [
513
- /* @__PURE__ */ jsx12("div", { className: "min-w-0 flex-1", children: nametag ? /* @__PURE__ */ jsxs11(Fragment, { children: [
514
- /* @__PURE__ */ jsxs11("div", { className: "text-sm font-medium", style: { color: "var(--text-primary)" }, children: [
705
+ return /* @__PURE__ */ jsxs14("div", { className: "flex items-center gap-1.5 min-w-0", children: [
706
+ /* @__PURE__ */ jsx15("div", { className: "min-w-0 flex-1", children: nametag ? /* @__PURE__ */ jsxs14(Fragment2, { children: [
707
+ /* @__PURE__ */ jsxs14("div", { className: "text-sm font-medium", style: { color: "var(--text-primary)" }, children: [
515
708
  "@",
516
709
  nametag
517
710
  ] }),
518
- /* @__PURE__ */ jsx12(
711
+ /* @__PURE__ */ jsx15(
519
712
  "div",
520
713
  {
521
714
  className: "text-[11px] font-mono truncate",
@@ -524,7 +717,7 @@ function AddressDisplay({ address, nametag, truncate = true }) {
524
717
  children: displayAddress
525
718
  }
526
719
  )
527
- ] }) : /* @__PURE__ */ jsx12(
720
+ ] }) : /* @__PURE__ */ jsx15(
528
721
  "div",
529
722
  {
530
723
  className: "text-xs font-mono truncate",
@@ -533,7 +726,7 @@ function AddressDisplay({ address, nametag, truncate = true }) {
533
726
  children: displayAddress
534
727
  }
535
728
  ) }),
536
- /* @__PURE__ */ jsx12(
729
+ /* @__PURE__ */ jsx15(
537
730
  "button",
538
731
  {
539
732
  onClick: handleCopy,
@@ -546,9 +739,9 @@ function AddressDisplay({ address, nametag, truncate = true }) {
546
739
  if (!copied) e.currentTarget.style.color = "var(--text-muted)";
547
740
  },
548
741
  title: copied ? "Copied!" : "Copy address",
549
- children: copied ? /* @__PURE__ */ jsx12("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx12("path", { d: "M20 6L9 17l-5-5" }) }) : /* @__PURE__ */ jsxs11("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
550
- /* @__PURE__ */ jsx12("rect", { x: "9", y: "9", width: "13", height: "13", rx: "2", ry: "2" }),
551
- /* @__PURE__ */ jsx12("path", { d: "M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" })
742
+ children: copied ? /* @__PURE__ */ jsx15("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx15("path", { d: "M20 6L9 17l-5-5" }) }) : /* @__PURE__ */ jsxs14("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
743
+ /* @__PURE__ */ jsx15("rect", { x: "9", y: "9", width: "13", height: "13", rx: "2", ry: "2" }),
744
+ /* @__PURE__ */ jsx15("path", { d: "M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" })
552
745
  ] })
553
746
  }
554
747
  )
@@ -556,17 +749,17 @@ function AddressDisplay({ address, nametag, truncate = true }) {
556
749
  }
557
750
 
558
751
  // src/components/JsonPanel.tsx
559
- import { useState as useState4, useEffect as useEffect4, useRef as useRef2, useCallback as useCallback2 } from "react";
560
- import { jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
752
+ import { useState as useState5, useEffect as useEffect4, useRef as useRef2, useCallback as useCallback2 } from "react";
753
+ import { jsx as jsx16, jsxs as jsxs15 } from "react/jsx-runtime";
561
754
  function JsonPanel({
562
755
  value,
563
756
  onChange,
564
757
  excludeKeys = [],
565
758
  title = "JSON"
566
759
  }) {
567
- const [text, setText] = useState4("");
568
- const [parseError, setParseError] = useState4(null);
569
- const [isEditing, setIsEditing] = useState4(false);
760
+ const [text, setText] = useState5("");
761
+ const [parseError, setParseError] = useState5(null);
762
+ const [isEditing, setIsEditing] = useState5(false);
570
763
  const textareaRef = useRef2(null);
571
764
  useEffect4(() => {
572
765
  if (isEditing) return;
@@ -590,24 +783,24 @@ function JsonPanel({
590
783
  }, [onChange]);
591
784
  const handleFocus = useCallback2(() => setIsEditing(true), []);
592
785
  const handleBlur = useCallback2(() => setIsEditing(false), []);
593
- const [copied, setCopied] = useState4(false);
786
+ const [copied, setCopied] = useState5(false);
594
787
  const handleCopy = useCallback2(async () => {
595
788
  await navigator.clipboard.writeText(text);
596
789
  setCopied(true);
597
790
  setTimeout(() => setCopied(false), 1500);
598
791
  }, [text]);
599
792
  const lineCount = text.split("\n").length;
600
- return /* @__PURE__ */ jsxs12("div", { className: "flex flex-col h-full", style: { minWidth: 320 }, children: [
601
- /* @__PURE__ */ jsxs12("div", { className: "flex items-center justify-between px-3 py-2", style: { borderBottom: "1px solid var(--border)" }, children: [
602
- /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-2", children: [
603
- /* @__PURE__ */ jsxs12("span", { className: "text-xs font-mono font-semibold", style: { color: "var(--text-muted)" }, children: [
793
+ return /* @__PURE__ */ jsxs15("div", { className: "flex flex-col h-full", style: { minWidth: 320 }, children: [
794
+ /* @__PURE__ */ jsxs15("div", { className: "flex items-center justify-between px-3 py-2", style: { borderBottom: "1px solid var(--border)" }, children: [
795
+ /* @__PURE__ */ jsxs15("div", { className: "flex items-center gap-2", children: [
796
+ /* @__PURE__ */ jsxs15("span", { className: "text-xs font-mono font-semibold", style: { color: "var(--text-muted)" }, children: [
604
797
  "{ }",
605
798
  " ",
606
799
  title
607
800
  ] }),
608
- parseError && /* @__PURE__ */ jsx13("span", { className: "text-[10px] px-1.5 py-0.5 rounded", style: { background: "rgba(239,68,68,0.1)", color: "#f87171" }, children: "Error" })
801
+ parseError && /* @__PURE__ */ jsx16("span", { className: "text-[10px] px-1.5 py-0.5 rounded", style: { background: "rgba(239,68,68,0.1)", color: "#f87171" }, children: "Error" })
609
802
  ] }),
610
- /* @__PURE__ */ jsx13(
803
+ /* @__PURE__ */ jsx16(
611
804
  "button",
612
805
  {
613
806
  onClick: handleCopy,
@@ -628,8 +821,8 @@ function JsonPanel({
628
821
  }
629
822
  )
630
823
  ] }),
631
- /* @__PURE__ */ jsx13("div", { className: "flex-1 relative overflow-hidden", children: /* @__PURE__ */ jsxs12("div", { className: "absolute inset-0 flex overflow-auto", children: [
632
- /* @__PURE__ */ jsx13(
824
+ /* @__PURE__ */ jsx16("div", { className: "flex-1 relative overflow-hidden", children: /* @__PURE__ */ jsxs15("div", { className: "absolute inset-0 flex overflow-auto", children: [
825
+ /* @__PURE__ */ jsx16(
633
826
  "div",
634
827
  {
635
828
  className: "shrink-0 text-right pr-2 pt-3 select-none",
@@ -643,10 +836,10 @@ function JsonPanel({
643
836
  background: "var(--bg-surface)",
644
837
  borderRight: "1px solid var(--border)"
645
838
  },
646
- children: Array.from({ length: lineCount }, (_, i) => /* @__PURE__ */ jsx13("div", { children: i + 1 }, i))
839
+ children: Array.from({ length: lineCount }, (_, i) => /* @__PURE__ */ jsx16("div", { children: i + 1 }, i))
647
840
  }
648
841
  ),
649
- /* @__PURE__ */ jsx13(
842
+ /* @__PURE__ */ jsx16(
650
843
  "textarea",
651
844
  {
652
845
  ref: textareaRef,
@@ -668,11 +861,11 @@ function JsonPanel({
668
861
  }
669
862
  )
670
863
  ] }) }),
671
- parseError && /* @__PURE__ */ jsx13("div", { className: "px-3 py-1.5 text-[10px]", style: { background: "rgba(239,68,68,0.06)", color: "#f87171", borderTop: "1px solid rgba(239,68,68,0.15)" }, children: parseError })
864
+ parseError && /* @__PURE__ */ jsx16("div", { className: "px-3 py-1.5 text-[10px]", style: { background: "rgba(239,68,68,0.06)", color: "#f87171", borderTop: "1px solid rgba(239,68,68,0.15)" }, children: parseError })
672
865
  ] });
673
866
  }
674
867
  function JsonToggleButton({ active, onClick }) {
675
- return /* @__PURE__ */ jsx13(
868
+ return /* @__PURE__ */ jsx16(
676
869
  "button",
677
870
  {
678
871
  onClick,
@@ -703,8 +896,8 @@ function JsonToggleButton({ active, onClick }) {
703
896
  }
704
897
 
705
898
  // src/components/ChainInput.tsx
706
- import { useState as useState5, useId } from "react";
707
- import { jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
899
+ import { useState as useState6, useId } from "react";
900
+ import { jsx as jsx17, jsxs as jsxs16 } from "react/jsx-runtime";
708
901
  var TAG_PALETTES = [
709
902
  { bg: "rgba(16, 185, 129, 0.12)", color: "#34d399", border: "rgba(16, 185, 129, 0.2)" },
710
903
  { bg: "rgba(59, 130, 246, 0.12)", color: "#60a5fa", border: "rgba(59, 130, 246, 0.2)" },
@@ -723,8 +916,8 @@ function tagColor(tag) {
723
916
  return TAG_PALETTES[Math.abs(hash) % TAG_PALETTES.length];
724
917
  }
725
918
  function ChainInput({ chains, suggestions, onChange, size = "md" }) {
726
- const [input, setInput] = useState5("");
727
- const [open, setOpen] = useState5(false);
919
+ const [input, setInput] = useState6("");
920
+ const [open, setOpen] = useState6(false);
728
921
  const inputId = useId();
729
922
  const entries = Object.entries(chains);
730
923
  const available = suggestions.filter((s) => !(s in chains) && (!input || s.toLowerCase().includes(input.toLowerCase())));
@@ -758,8 +951,8 @@ function ChainInput({ chains, suggestions, onChange, size = "md" }) {
758
951
  const isSm = size === "sm";
759
952
  const textSize = isSm ? "text-[0.6rem]" : "text-[0.65rem]";
760
953
  const minH = isSm ? "min-h-[32px]" : "min-h-[38px]";
761
- return /* @__PURE__ */ jsxs13("div", { className: "relative", children: [
762
- /* @__PURE__ */ jsxs13(
954
+ return /* @__PURE__ */ jsxs16("div", { className: "relative", children: [
955
+ /* @__PURE__ */ jsxs16(
763
956
  "div",
764
957
  {
765
958
  className: `admin-input flex flex-wrap gap-1.5 !p-1.5 ${minH} cursor-text`,
@@ -767,14 +960,14 @@ function ChainInput({ chains, suggestions, onChange, size = "md" }) {
767
960
  children: [
768
961
  entries.map(([name, order]) => {
769
962
  const c = tagColor(name);
770
- return /* @__PURE__ */ jsxs13(
963
+ return /* @__PURE__ */ jsxs16(
771
964
  "span",
772
965
  {
773
966
  className: `inline-flex items-center gap-1 ${textSize} font-semibold px-2 py-0.5 rounded`,
774
967
  style: { background: c.bg, color: c.color, border: `1px solid ${c.border}` },
775
968
  children: [
776
969
  name,
777
- /* @__PURE__ */ jsx14(
970
+ /* @__PURE__ */ jsx17(
778
971
  "input",
779
972
  {
780
973
  type: "number",
@@ -786,7 +979,7 @@ function ChainInput({ chains, suggestions, onChange, size = "md" }) {
786
979
  onClick: (e) => e.stopPropagation()
787
980
  }
788
981
  ),
789
- /* @__PURE__ */ jsx14(
982
+ /* @__PURE__ */ jsx17(
790
983
  "button",
791
984
  {
792
985
  type: "button",
@@ -803,7 +996,7 @@ function ChainInput({ chains, suggestions, onChange, size = "md" }) {
803
996
  name
804
997
  );
805
998
  }),
806
- /* @__PURE__ */ jsx14(
999
+ /* @__PURE__ */ jsx17(
807
1000
  "input",
808
1001
  {
809
1002
  id: inputId,
@@ -823,13 +1016,13 @@ function ChainInput({ chains, suggestions, onChange, size = "md" }) {
823
1016
  ]
824
1017
  }
825
1018
  ),
826
- open && (available.length > 0 || isNew) && /* @__PURE__ */ jsxs13(
1019
+ open && (available.length > 0 || isNew) && /* @__PURE__ */ jsxs16(
827
1020
  "div",
828
1021
  {
829
1022
  className: "absolute left-0 right-0 top-full mt-1 z-20 py-1 max-h-40 overflow-y-auto",
830
1023
  style: { background: "var(--bg-elevated)", border: "1px solid var(--border)", borderRadius: "var(--radius-md)" },
831
1024
  children: [
832
- isNew && /* @__PURE__ */ jsxs13(
1025
+ isNew && /* @__PURE__ */ jsxs16(
833
1026
  "button",
834
1027
  {
835
1028
  onMouseDown: () => addChain(trimmed),
@@ -850,7 +1043,7 @@ function ChainInput({ chains, suggestions, onChange, size = "md" }) {
850
1043
  ),
851
1044
  available.map((s) => {
852
1045
  const c = tagColor(s);
853
- return /* @__PURE__ */ jsxs13(
1046
+ return /* @__PURE__ */ jsxs16(
854
1047
  "button",
855
1048
  {
856
1049
  onMouseDown: () => addChain(s),
@@ -863,7 +1056,7 @@ function ChainInput({ chains, suggestions, onChange, size = "md" }) {
863
1056
  e.currentTarget.style.background = "transparent";
864
1057
  },
865
1058
  children: [
866
- /* @__PURE__ */ jsx14("span", { className: "w-2 h-2 rounded-full flex-shrink-0", style: { background: c.color } }),
1059
+ /* @__PURE__ */ jsx17("span", { className: "w-2 h-2 rounded-full flex-shrink-0", style: { background: c.color } }),
867
1060
  s
868
1061
  ]
869
1062
  },
@@ -877,7 +1070,7 @@ function ChainInput({ chains, suggestions, onChange, size = "md" }) {
877
1070
  }
878
1071
 
879
1072
  // src/components/MemoConditionsEditor.tsx
880
- import { Fragment as Fragment2, jsx as jsx15, jsxs as jsxs14 } from "react/jsx-runtime";
1073
+ import { Fragment as Fragment3, jsx as jsx18, jsxs as jsxs17 } from "react/jsx-runtime";
881
1074
  var MEMO_OPERATORS = [
882
1075
  { value: "eq", label: "Equals (=)", values: 1 },
883
1076
  { value: "neq", label: "Not equals (\u2260)", values: 1 },
@@ -923,16 +1116,16 @@ function MemoConditionsEditor({ conditions, onChange }) {
923
1116
  const remove = (i) => onChange(conditions.filter((_, idx) => idx !== i));
924
1117
  const update = (i, patch) => onChange(conditions.map((c, idx) => idx === i ? { ...c, ...patch } : c));
925
1118
  const opMeta = (op) => MEMO_OPERATORS.find((o) => o.value === op) ?? MEMO_OPERATORS[0];
926
- return /* @__PURE__ */ jsxs14("div", { children: [
927
- /* @__PURE__ */ jsxs14("div", { className: "flex items-center gap-2 mb-2", children: [
928
- /* @__PURE__ */ jsx15("span", { className: "text-xs font-medium", style: { color: "var(--text-muted)" }, children: "Memo Conditions" }),
929
- /* @__PURE__ */ jsx15("button", { type: "button", onClick: add, className: "text-[10px] px-2 py-0.5 rounded cursor-pointer", style: { background: "var(--bg-elevated)", color: "var(--accent-text)" }, children: "+ Add" })
1119
+ return /* @__PURE__ */ jsxs17("div", { children: [
1120
+ /* @__PURE__ */ jsxs17("div", { className: "flex items-center gap-2 mb-2", children: [
1121
+ /* @__PURE__ */ jsx18("span", { className: "text-xs font-medium", style: { color: "var(--text-muted)" }, children: "Memo Conditions" }),
1122
+ /* @__PURE__ */ jsx18("button", { type: "button", onClick: add, className: "text-[10px] px-2 py-0.5 rounded cursor-pointer", style: { background: "var(--bg-elevated)", color: "var(--accent-text)" }, children: "+ Add" })
930
1123
  ] }),
931
- conditions.length > 0 ? /* @__PURE__ */ jsx15("div", { className: "flex flex-col gap-2", children: conditions.map((cond, i) => {
1124
+ conditions.length > 0 ? /* @__PURE__ */ jsx18("div", { className: "flex flex-col gap-2", children: conditions.map((cond, i) => {
932
1125
  const meta = opMeta(cond.operator);
933
- return /* @__PURE__ */ jsxs14("div", { className: "rounded-lg p-2.5", style: { background: "rgba(255,255,255,0.02)", border: "1px solid var(--border)" }, children: [
934
- /* @__PURE__ */ jsxs14("div", { className: "flex gap-2 items-center", children: [
935
- /* @__PURE__ */ jsx15(
1126
+ return /* @__PURE__ */ jsxs17("div", { className: "rounded-lg p-2.5", style: { background: "rgba(255,255,255,0.02)", border: "1px solid var(--border)" }, children: [
1127
+ /* @__PURE__ */ jsxs17("div", { className: "flex gap-2 items-center", children: [
1128
+ /* @__PURE__ */ jsx18(
936
1129
  "input",
937
1130
  {
938
1131
  className: "admin-input flex-1 text-xs",
@@ -941,7 +1134,7 @@ function MemoConditionsEditor({ conditions, onChange }) {
941
1134
  onChange: (e) => update(i, { key: e.target.value })
942
1135
  }
943
1136
  ),
944
- /* @__PURE__ */ jsx15(
1137
+ /* @__PURE__ */ jsx18(
945
1138
  CustomSelect,
946
1139
  {
947
1140
  size: "sm",
@@ -951,7 +1144,7 @@ function MemoConditionsEditor({ conditions, onChange }) {
951
1144
  options: MEMO_OPERATORS.map((o) => ({ value: o.value, label: o.label }))
952
1145
  }
953
1146
  ),
954
- meta.values >= 1 && /* @__PURE__ */ jsx15(
1147
+ meta.values >= 1 && /* @__PURE__ */ jsx18(
955
1148
  "input",
956
1149
  {
957
1150
  className: "admin-input flex-1 text-xs",
@@ -960,9 +1153,9 @@ function MemoConditionsEditor({ conditions, onChange }) {
960
1153
  onChange: (e) => update(i, { value: e.target.value })
961
1154
  }
962
1155
  ),
963
- meta.values === 2 && /* @__PURE__ */ jsxs14(Fragment2, { children: [
964
- /* @__PURE__ */ jsx15("span", { className: "text-[10px]", style: { color: "var(--text-muted)" }, children: "and" }),
965
- /* @__PURE__ */ jsx15(
1156
+ meta.values === 2 && /* @__PURE__ */ jsxs17(Fragment3, { children: [
1157
+ /* @__PURE__ */ jsx18("span", { className: "text-[10px]", style: { color: "var(--text-muted)" }, children: "and" }),
1158
+ /* @__PURE__ */ jsx18(
966
1159
  "input",
967
1160
  {
968
1161
  className: "admin-input flex-1 text-xs",
@@ -972,18 +1165,18 @@ function MemoConditionsEditor({ conditions, onChange }) {
972
1165
  }
973
1166
  )
974
1167
  ] }),
975
- /* @__PURE__ */ jsx15("button", { type: "button", onClick: () => remove(i), className: "text-red-400 text-sm px-1 cursor-pointer", children: "\xD7" })
1168
+ /* @__PURE__ */ jsx18("button", { type: "button", onClick: () => remove(i), className: "text-red-400 text-sm px-1 cursor-pointer", children: "\xD7" })
976
1169
  ] }),
977
- /* @__PURE__ */ jsx15("p", { className: "text-[10px] mt-1.5 ml-0.5", style: { color: "var(--text-muted)", fontStyle: "italic" }, children: conditionPreview(cond) })
1170
+ /* @__PURE__ */ jsx18("p", { className: "text-[10px] mt-1.5 ml-0.5", style: { color: "var(--text-muted)", fontStyle: "italic" }, children: conditionPreview(cond) })
978
1171
  ] }, i);
979
- }) }) : /* @__PURE__ */ jsx15("p", { className: "text-[10px]", style: { color: "var(--text-muted)" }, children: 'No conditions \u2014 matches any memo transaction. Click "+ Add" to filter.' })
1172
+ }) }) : /* @__PURE__ */ jsx18("p", { className: "text-[10px]", style: { color: "var(--text-muted)" }, children: 'No conditions \u2014 matches any memo transaction. Click "+ Add" to filter.' })
980
1173
  ] });
981
1174
  }
982
1175
 
983
1176
  // src/components/Icons.tsx
984
- import { jsx as jsx16 } from "react/jsx-runtime";
1177
+ import { jsx as jsx19 } from "react/jsx-runtime";
985
1178
  function I({ d, size = 16, className, style }) {
986
- return /* @__PURE__ */ jsx16(
1179
+ return /* @__PURE__ */ jsx19(
987
1180
  "svg",
988
1181
  {
989
1182
  width: size,
@@ -996,7 +1189,7 @@ function I({ d, size = 16, className, style }) {
996
1189
  strokeLinejoin: "round",
997
1190
  className,
998
1191
  style,
999
- children: /* @__PURE__ */ jsx16("path", { d })
1192
+ children: /* @__PURE__ */ jsx19("path", { d })
1000
1193
  }
1001
1194
  );
1002
1195
  }
@@ -1028,34 +1221,36 @@ var P = {
1028
1221
  diamond: "M2.7 10.3a2.41 2.41 0 0 0 0 3.41l7.59 7.59a2.41 2.41 0 0 0 3.41 0l7.59-7.59a2.41 2.41 0 0 0 0-3.41L13.7 2.71a2.41 2.41 0 0 0-3.41 0L2.7 10.3z",
1029
1222
  circle: "M12 12m-4 0a4 4 0 1 0 8 0 4 4 0 1 0-8 0"
1030
1223
  };
1031
- var IconBack = (p) => /* @__PURE__ */ jsx16(I, { d: P.back, ...p });
1032
- var IconUndo = (p) => /* @__PURE__ */ jsx16(I, { d: P.undo, ...p });
1033
- var IconQuests = (p) => /* @__PURE__ */ jsx16(I, { d: P.quests, ...p });
1034
- var IconTracks = (p) => /* @__PURE__ */ jsx16(I, { d: P.tracks, ...p });
1035
- var IconSettings = (p) => /* @__PURE__ */ jsx16(I, { d: P.settings, ...p });
1036
- var IconChain = (p) => /* @__PURE__ */ jsx16(I, { d: P.chain, ...p });
1037
- var IconPlus = (p) => /* @__PURE__ */ jsx16(I, { d: P.plus, ...p });
1038
- var IconEdit = (p) => /* @__PURE__ */ jsx16(I, { d: P.edit, ...p });
1039
- var IconTrash = (p) => /* @__PURE__ */ jsx16(I, { d: P.trash, ...p });
1040
- var IconX = (p) => /* @__PURE__ */ jsx16(I, { d: P.x, ...p });
1041
- var IconCheck = (p) => /* @__PURE__ */ jsx16(I, { d: P.check, ...p });
1042
- var IconSearch = (p) => /* @__PURE__ */ jsx16(I, { d: P.search, ...p });
1043
- var IconChevronUp = (p) => /* @__PURE__ */ jsx16(I, { d: P.chevronUp, ...p });
1044
- var IconChevronDown = (p) => /* @__PURE__ */ jsx16(I, { d: P.chevronDown, ...p });
1045
- var IconChevronsDown = (p) => /* @__PURE__ */ jsx16(I, { d: P.chevronsDown, ...p });
1046
- var IconChevronsRight = (p) => /* @__PURE__ */ jsx16(I, { d: P.chevronsRight, ...p });
1047
- var IconArrowRight = (p) => /* @__PURE__ */ jsx16(I, { d: P.arrowRight, ...p });
1048
- var IconPlay = (p) => /* @__PURE__ */ jsx16(I, { d: P.play, ...p });
1049
- var IconStar = (p) => /* @__PURE__ */ jsx16(I, { d: P.star, ...p });
1050
- var IconDiamond = (p) => /* @__PURE__ */ jsx16(I, { d: P.diamond, ...p });
1051
- var IconCircle = (p) => /* @__PURE__ */ jsx16(I, { d: P.circle, ...p });
1224
+ var IconBack = (p) => /* @__PURE__ */ jsx19(I, { d: P.back, ...p });
1225
+ var IconUndo = (p) => /* @__PURE__ */ jsx19(I, { d: P.undo, ...p });
1226
+ var IconQuests = (p) => /* @__PURE__ */ jsx19(I, { d: P.quests, ...p });
1227
+ var IconTracks = (p) => /* @__PURE__ */ jsx19(I, { d: P.tracks, ...p });
1228
+ var IconSettings = (p) => /* @__PURE__ */ jsx19(I, { d: P.settings, ...p });
1229
+ var IconChain = (p) => /* @__PURE__ */ jsx19(I, { d: P.chain, ...p });
1230
+ var IconPlus = (p) => /* @__PURE__ */ jsx19(I, { d: P.plus, ...p });
1231
+ var IconEdit = (p) => /* @__PURE__ */ jsx19(I, { d: P.edit, ...p });
1232
+ var IconTrash = (p) => /* @__PURE__ */ jsx19(I, { d: P.trash, ...p });
1233
+ var IconX = (p) => /* @__PURE__ */ jsx19(I, { d: P.x, ...p });
1234
+ var IconCheck = (p) => /* @__PURE__ */ jsx19(I, { d: P.check, ...p });
1235
+ var IconSearch = (p) => /* @__PURE__ */ jsx19(I, { d: P.search, ...p });
1236
+ var IconChevronUp = (p) => /* @__PURE__ */ jsx19(I, { d: P.chevronUp, ...p });
1237
+ var IconChevronDown = (p) => /* @__PURE__ */ jsx19(I, { d: P.chevronDown, ...p });
1238
+ var IconChevronsDown = (p) => /* @__PURE__ */ jsx19(I, { d: P.chevronsDown, ...p });
1239
+ var IconChevronsRight = (p) => /* @__PURE__ */ jsx19(I, { d: P.chevronsRight, ...p });
1240
+ var IconArrowRight = (p) => /* @__PURE__ */ jsx19(I, { d: P.arrowRight, ...p });
1241
+ var IconPlay = (p) => /* @__PURE__ */ jsx19(I, { d: P.play, ...p });
1242
+ var IconStar = (p) => /* @__PURE__ */ jsx19(I, { d: P.star, ...p });
1243
+ var IconDiamond = (p) => /* @__PURE__ */ jsx19(I, { d: P.diamond, ...p });
1244
+ var IconCircle = (p) => /* @__PURE__ */ jsx19(I, { d: P.circle, ...p });
1052
1245
  export {
1053
1246
  AddressDisplay,
1054
1247
  AlertBanner,
1248
+ AppLogo,
1055
1249
  Button,
1056
1250
  ChainInput,
1057
1251
  ConfirmDialog,
1058
1252
  CustomSelect,
1253
+ DashboardLayout,
1059
1254
  DataTable,
1060
1255
  EmptyState,
1061
1256
  Field,
@@ -1089,6 +1284,7 @@ export {
1089
1284
  SearchInput,
1090
1285
  Section,
1091
1286
  Select,
1287
+ SidebarNav,
1092
1288
  StatusBadge,
1093
1289
  Textarea,
1094
1290
  tagColor
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unicitylabs/sphere-ui",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -76,6 +76,17 @@ body {
76
76
  ::-webkit-scrollbar-thumb { background: #1a1a1a; border-radius: 10px; }
77
77
  ::-webkit-scrollbar-thumb:hover { background: rgba(255, 255, 255, 0.15); }
78
78
 
79
- /* Anton (--font-display) is NOT applied globally to headings.
80
- Sphere uses Geist for all text by default.
81
- Apply Anton explicitly where needed: style={{ fontFamily: 'var(--font-display)' }} */
79
+ /* Anton for headings in dashboard apps (admin, dev portal).
80
+ Add class="sphere-dashboard" on <body> or root to activate.
81
+ Sphere wallet does NOT use this it uses Geist everywhere. */
82
+ .sphere-dashboard h1,
83
+ .sphere-dashboard h2,
84
+ .sphere-dashboard h3 {
85
+ font-family: var(--font-display);
86
+ font-weight: 400;
87
+ letter-spacing: 0.02em;
88
+ text-transform: uppercase;
89
+ -webkit-font-smoothing: antialiased;
90
+ -moz-osx-font-smoothing: grayscale;
91
+ text-rendering: geometricPrecision;
92
+ }