kaleido-ui 0.1.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.
@@ -0,0 +1,1191 @@
1
+ "use client";
2
+
3
+ // src/web/utils/cn.ts
4
+ import { clsx } from "clsx";
5
+ import { twMerge } from "tailwind-merge";
6
+ function cn(...inputs) {
7
+ return twMerge(clsx(inputs));
8
+ }
9
+
10
+ // src/web/primitives/button.tsx
11
+ import * as React from "react";
12
+ import { Slot } from "@radix-ui/react-slot";
13
+ import { cva } from "class-variance-authority";
14
+ import { jsx } from "react/jsx-runtime";
15
+ var buttonVariants = cva(
16
+ "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-xl text-sm font-semibold ring-offset-background transition-all duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 active:scale-[0.98]",
17
+ {
18
+ variants: {
19
+ variant: {
20
+ default: "bg-primary text-primary-foreground hover:bg-primary/90 shadow-glow-subtle hover:shadow-glow",
21
+ destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
22
+ outline: "border border-border bg-transparent hover:bg-accent hover:text-accent-foreground hover:border-primary/30",
23
+ secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
24
+ ghost: "hover:bg-white/5 hover:text-foreground",
25
+ link: "text-primary underline-offset-4 hover:underline",
26
+ glow: "bg-primary text-primary-foreground shadow-glow hover:shadow-glow-strong animate-pulse-glow",
27
+ surface: "bg-card text-card-foreground border border-border hover:bg-accent hover:border-primary/30",
28
+ cta: "w-full bg-primary hover:bg-primary-dark text-primary-foreground font-bold rounded-2xl shadow-glow-accent disabled:opacity-50 disabled:cursor-not-allowed disabled:shadow-none",
29
+ "cta-gradient": "w-full bg-gradient-to-r from-primary to-primary-dark text-primary-foreground font-extrabold rounded-2xl shadow-[0_8px_30px_rgba(43,238,121,0.35)] hover:opacity-90 hover:-translate-y-0.5 active:translate-y-0 active:opacity-100 disabled:opacity-40 disabled:shadow-none disabled:cursor-not-allowed disabled:bg-surface-highlight disabled:text-white/50",
30
+ "danger-subtle": "w-full bg-red-500/10 border border-red-500/20 text-red-400 font-bold rounded-xl hover:bg-red-500/20"
31
+ },
32
+ size: {
33
+ default: "h-11 px-5 py-2",
34
+ sm: "h-9 rounded-lg px-3 text-xs",
35
+ lg: "h-14 rounded-xl px-8 text-base font-bold",
36
+ xl: "h-16 rounded-2xl px-10 text-lg font-bold",
37
+ cta: "h-14 py-4 px-6 text-lg",
38
+ "cta-lg": "h-[60px] py-5 px-6 text-lg",
39
+ icon: "h-10 w-10 rounded-full",
40
+ "icon-lg": "h-12 w-12 rounded-full",
41
+ "icon-xl": "h-14 w-14 rounded-full"
42
+ }
43
+ },
44
+ defaultVariants: {
45
+ variant: "default",
46
+ size: "default"
47
+ }
48
+ }
49
+ );
50
+ var Button = React.forwardRef(
51
+ ({ className, variant, size, asChild = false, ...props }, ref) => {
52
+ const Comp = asChild ? Slot : "button";
53
+ return /* @__PURE__ */ jsx(
54
+ Comp,
55
+ {
56
+ className: cn(buttonVariants({ variant, size, className })),
57
+ ref,
58
+ ...props
59
+ }
60
+ );
61
+ }
62
+ );
63
+ Button.displayName = "Button";
64
+
65
+ // src/web/primitives/card.tsx
66
+ import * as React2 from "react";
67
+ import { jsx as jsx2 } from "react/jsx-runtime";
68
+ var Card = React2.forwardRef(
69
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsx2(
70
+ "div",
71
+ {
72
+ ref,
73
+ className: cn(
74
+ "rounded-2xl border border-border/50 bg-card text-card-foreground shadow-sm transition-colors",
75
+ className
76
+ ),
77
+ ...props
78
+ }
79
+ )
80
+ );
81
+ Card.displayName = "Card";
82
+ var CardHeader = React2.forwardRef(
83
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsx2("div", { ref, className: cn("flex flex-col space-y-1.5 p-6", className), ...props })
84
+ );
85
+ CardHeader.displayName = "CardHeader";
86
+ var CardTitle = React2.forwardRef(
87
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsx2(
88
+ "h3",
89
+ {
90
+ ref,
91
+ className: cn("text-2xl font-semibold leading-none tracking-tight", className),
92
+ ...props
93
+ }
94
+ )
95
+ );
96
+ CardTitle.displayName = "CardTitle";
97
+ var CardDescription = React2.forwardRef(
98
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsx2("p", { ref, className: cn("text-sm text-muted-foreground", className), ...props })
99
+ );
100
+ CardDescription.displayName = "CardDescription";
101
+ var CardContent = React2.forwardRef(
102
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsx2("div", { ref, className: cn("p-6 pt-0", className), ...props })
103
+ );
104
+ CardContent.displayName = "CardContent";
105
+ var CardFooter = React2.forwardRef(
106
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsx2("div", { ref, className: cn("flex items-center p-6 pt-0", className), ...props })
107
+ );
108
+ CardFooter.displayName = "CardFooter";
109
+
110
+ // src/web/primitives/input.tsx
111
+ import * as React3 from "react";
112
+ import { jsx as jsx3 } from "react/jsx-runtime";
113
+ var Input = React3.forwardRef(
114
+ ({ className, type, ...props }, ref) => {
115
+ return /* @__PURE__ */ jsx3(
116
+ "input",
117
+ {
118
+ type,
119
+ className: cn(
120
+ "flex h-12 w-full rounded-xl border border-border bg-card px-4 py-3 text-base ring-offset-background transition-all file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/50 focus-visible:border-primary disabled:cursor-not-allowed disabled:opacity-50",
121
+ className
122
+ ),
123
+ ref,
124
+ ...props
125
+ }
126
+ );
127
+ }
128
+ );
129
+ Input.displayName = "Input";
130
+
131
+ // src/web/primitives/dialog.tsx
132
+ import * as React4 from "react";
133
+ import * as DialogPrimitive from "@radix-ui/react-dialog";
134
+
135
+ // src/web/primitives/icon.tsx
136
+ import { jsx as jsx4 } from "react/jsx-runtime";
137
+ var sizeClasses = {
138
+ xs: "text-[14px]",
139
+ sm: "text-[16px]",
140
+ md: "text-[20px]",
141
+ lg: "text-[24px]",
142
+ xl: "text-[32px]",
143
+ "2xl": "text-[48px]"
144
+ };
145
+ function Icon({
146
+ name,
147
+ filled = false,
148
+ size = "lg",
149
+ className,
150
+ ...props
151
+ }) {
152
+ return /* @__PURE__ */ jsx4(
153
+ "span",
154
+ {
155
+ className: cn(
156
+ "material-symbols-outlined",
157
+ filled && "filled",
158
+ sizeClasses[size],
159
+ className
160
+ ),
161
+ ...props,
162
+ children: name
163
+ }
164
+ );
165
+ }
166
+ var Icons = {
167
+ // Navigation
168
+ ArrowBack: (props) => /* @__PURE__ */ jsx4(Icon, { name: "arrow_back", ...props }),
169
+ ArrowForward: (props) => /* @__PURE__ */ jsx4(Icon, { name: "arrow_forward", ...props }),
170
+ Close: (props) => /* @__PURE__ */ jsx4(Icon, { name: "close", ...props }),
171
+ Menu: (props) => /* @__PURE__ */ jsx4(Icon, { name: "menu", ...props }),
172
+ // Actions
173
+ Send: (props) => /* @__PURE__ */ jsx4(Icon, { name: "arrow_upward", ...props }),
174
+ Receive: (props) => /* @__PURE__ */ jsx4(Icon, { name: "arrow_downward", ...props }),
175
+ Swap: (props) => /* @__PURE__ */ jsx4(Icon, { name: "swap_horiz", ...props }),
176
+ Copy: (props) => /* @__PURE__ */ jsx4(Icon, { name: "content_copy", ...props }),
177
+ Paste: (props) => /* @__PURE__ */ jsx4(Icon, { name: "content_paste", ...props }),
178
+ Refresh: (props) => /* @__PURE__ */ jsx4(Icon, { name: "refresh", ...props }),
179
+ Share: (props) => /* @__PURE__ */ jsx4(Icon, { name: "ios_share", ...props }),
180
+ QrCode: (props) => /* @__PURE__ */ jsx4(Icon, { name: "qr_code_2", ...props }),
181
+ QrScanner: (props) => /* @__PURE__ */ jsx4(Icon, { name: "qr_code_scanner", ...props }),
182
+ // Status
183
+ Check: (props) => /* @__PURE__ */ jsx4(Icon, { name: "check", ...props }),
184
+ CheckCircle: (props) => /* @__PURE__ */ jsx4(Icon, { name: "check_circle", ...props }),
185
+ Error: (props) => /* @__PURE__ */ jsx4(Icon, { name: "error", ...props }),
186
+ Warning: (props) => /* @__PURE__ */ jsx4(Icon, { name: "warning", ...props }),
187
+ Info: (props) => /* @__PURE__ */ jsx4(Icon, { name: "info", ...props }),
188
+ Pending: (props) => /* @__PURE__ */ jsx4(Icon, { name: "hourglass_top", ...props }),
189
+ // Navigation tabs
190
+ Wallet: (props) => /* @__PURE__ */ jsx4(Icon, { name: "account_balance_wallet", ...props }),
191
+ Activity: (props) => /* @__PURE__ */ jsx4(Icon, { name: "history", ...props }),
192
+ Settings: (props) => /* @__PURE__ */ jsx4(Icon, { name: "settings", ...props }),
193
+ // Networks
194
+ Lightning: (props) => /* @__PURE__ */ jsx4(Icon, { name: "bolt", ...props }),
195
+ Bitcoin: (props) => /* @__PURE__ */ jsx4(Icon, { name: "currency_bitcoin", ...props }),
196
+ Ark: (props) => /* @__PURE__ */ jsx4(Icon, { name: "hexagon", ...props }),
197
+ // Security
198
+ Lock: (props) => /* @__PURE__ */ jsx4(Icon, { name: "lock", ...props }),
199
+ Unlock: (props) => /* @__PURE__ */ jsx4(Icon, { name: "lock_open", ...props }),
200
+ Shield: (props) => /* @__PURE__ */ jsx4(Icon, { name: "shield", ...props }),
201
+ Key: (props) => /* @__PURE__ */ jsx4(Icon, { name: "key", ...props }),
202
+ Fingerprint: (props) => /* @__PURE__ */ jsx4(Icon, { name: "fingerprint", ...props }),
203
+ Visibility: (props) => /* @__PURE__ */ jsx4(Icon, { name: "visibility", ...props }),
204
+ VisibilityOff: (props) => /* @__PURE__ */ jsx4(Icon, { name: "visibility_off", ...props }),
205
+ // Misc
206
+ ExpandMore: (props) => /* @__PURE__ */ jsx4(Icon, { name: "expand_more", ...props }),
207
+ ExpandLess: (props) => /* @__PURE__ */ jsx4(Icon, { name: "expand_less", ...props }),
208
+ ChevronRight: (props) => /* @__PURE__ */ jsx4(Icon, { name: "chevron_right", ...props }),
209
+ OpenInNew: (props) => /* @__PURE__ */ jsx4(Icon, { name: "open_in_new", ...props }),
210
+ Search: (props) => /* @__PURE__ */ jsx4(Icon, { name: "search", ...props }),
211
+ Add: (props) => /* @__PURE__ */ jsx4(Icon, { name: "add", ...props }),
212
+ Download: (props) => /* @__PURE__ */ jsx4(Icon, { name: "download", ...props }),
213
+ Upload: (props) => /* @__PURE__ */ jsx4(Icon, { name: "upload", ...props }),
214
+ Edit: (props) => /* @__PURE__ */ jsx4(Icon, { name: "edit", ...props }),
215
+ Delete: (props) => /* @__PURE__ */ jsx4(Icon, { name: "delete", ...props }),
216
+ Timer: (props) => /* @__PURE__ */ jsx4(Icon, { name: "timer", ...props }),
217
+ Person: (props) => /* @__PURE__ */ jsx4(Icon, { name: "person", ...props }),
218
+ Hub: (props) => /* @__PURE__ */ jsx4(Icon, { name: "hub", ...props }),
219
+ Verified: (props) => /* @__PURE__ */ jsx4(Icon, { name: "verified", ...props }),
220
+ // Agent / AI
221
+ SmartToy: (props) => /* @__PURE__ */ jsx4(Icon, { name: "smart_toy", ...props }),
222
+ Psychology: (props) => /* @__PURE__ */ jsx4(Icon, { name: "psychology", ...props }),
223
+ Event: (props) => /* @__PURE__ */ jsx4(Icon, { name: "event", ...props }),
224
+ PlayArrow: (props) => /* @__PURE__ */ jsx4(Icon, { name: "play_arrow", ...props }),
225
+ ChatBubble: (props) => /* @__PURE__ */ jsx4(Icon, { name: "chat_bubble", ...props }),
226
+ Progress: (props) => /* @__PURE__ */ jsx4(Icon, { name: "progress_activity", ...props })
227
+ };
228
+
229
+ // src/web/primitives/dialog.tsx
230
+ import { jsx as jsx5, jsxs } from "react/jsx-runtime";
231
+ var Dialog = DialogPrimitive.Root;
232
+ var DialogTrigger = DialogPrimitive.Trigger;
233
+ var DialogPortal = DialogPrimitive.Portal;
234
+ var DialogClose = DialogPrimitive.Close;
235
+ var DialogOverlay = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx5(
236
+ DialogPrimitive.Overlay,
237
+ {
238
+ ref,
239
+ className: cn(
240
+ "fixed inset-0 z-50 bg-background/80 backdrop-blur-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
241
+ className
242
+ ),
243
+ ...props
244
+ }
245
+ ));
246
+ DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
247
+ var DialogContent = React4.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(DialogPortal, { children: [
248
+ /* @__PURE__ */ jsx5(DialogOverlay, {}),
249
+ /* @__PURE__ */ jsxs(
250
+ DialogPrimitive.Content,
251
+ {
252
+ ref,
253
+ className: cn(
254
+ "fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] rounded-lg",
255
+ className
256
+ ),
257
+ ...props,
258
+ children: [
259
+ children,
260
+ /* @__PURE__ */ jsxs(DialogPrimitive.Close, { className: "absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground", children: [
261
+ /* @__PURE__ */ jsx5(Icon, { name: "close", size: "sm" }),
262
+ /* @__PURE__ */ jsx5("span", { className: "sr-only", children: "Close" })
263
+ ] })
264
+ ]
265
+ }
266
+ )
267
+ ] }));
268
+ DialogContent.displayName = DialogPrimitive.Content.displayName;
269
+ var DialogHeader = ({ className, ...props }) => /* @__PURE__ */ jsx5("div", { className: cn("flex flex-col space-y-1.5 text-center sm:text-left", className), ...props });
270
+ DialogHeader.displayName = "DialogHeader";
271
+ var DialogFooter = ({ className, ...props }) => /* @__PURE__ */ jsx5("div", { className: cn("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", className), ...props });
272
+ DialogFooter.displayName = "DialogFooter";
273
+ var DialogTitle = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx5(
274
+ DialogPrimitive.Title,
275
+ {
276
+ ref,
277
+ className: cn("text-lg font-semibold leading-none tracking-tight", className),
278
+ ...props
279
+ }
280
+ ));
281
+ DialogTitle.displayName = DialogPrimitive.Title.displayName;
282
+ var DialogDescription = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx5(
283
+ DialogPrimitive.Description,
284
+ {
285
+ ref,
286
+ className: cn("text-sm text-muted-foreground", className),
287
+ ...props
288
+ }
289
+ ));
290
+ DialogDescription.displayName = DialogPrimitive.Description.displayName;
291
+
292
+ // src/web/primitives/tabs.tsx
293
+ import * as React5 from "react";
294
+ import * as TabsPrimitive from "@radix-ui/react-tabs";
295
+ import { jsx as jsx6 } from "react/jsx-runtime";
296
+ var Tabs = TabsPrimitive.Root;
297
+ var TabsList = React5.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx6(
298
+ TabsPrimitive.List,
299
+ {
300
+ ref,
301
+ className: cn(
302
+ "inline-flex h-12 items-center justify-center gap-2 rounded-xl bg-card p-1.5 text-muted-foreground border border-border/50",
303
+ className
304
+ ),
305
+ ...props
306
+ }
307
+ ));
308
+ TabsList.displayName = TabsPrimitive.List.displayName;
309
+ var TabsTrigger = React5.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx6(
310
+ TabsPrimitive.Trigger,
311
+ {
312
+ ref,
313
+ className: cn(
314
+ "inline-flex items-center justify-center whitespace-nowrap rounded-lg px-4 py-2 text-sm font-semibold ring-offset-background transition-all duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
315
+ "hover:text-foreground hover:bg-white/5",
316
+ "data-[state=active]:bg-primary data-[state=active]:text-primary-foreground data-[state=active]:shadow-glow-subtle",
317
+ className
318
+ ),
319
+ ...props
320
+ }
321
+ ));
322
+ TabsTrigger.displayName = TabsPrimitive.Trigger.displayName;
323
+ var TabsContent = React5.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx6(
324
+ TabsPrimitive.Content,
325
+ {
326
+ ref,
327
+ className: cn(
328
+ "mt-4 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 animate-fade-in",
329
+ className
330
+ ),
331
+ ...props
332
+ }
333
+ ));
334
+ TabsContent.displayName = TabsPrimitive.Content.displayName;
335
+
336
+ // src/web/primitives/label.tsx
337
+ import * as React6 from "react";
338
+ import * as LabelPrimitive from "@radix-ui/react-label";
339
+ import { cva as cva2 } from "class-variance-authority";
340
+ import { jsx as jsx7 } from "react/jsx-runtime";
341
+ var labelVariants = cva2(
342
+ "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
343
+ );
344
+ var Label = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx7(
345
+ LabelPrimitive.Root,
346
+ {
347
+ ref,
348
+ className: cn(labelVariants(), className),
349
+ ...props
350
+ }
351
+ ));
352
+ Label.displayName = LabelPrimitive.Root.displayName;
353
+
354
+ // src/web/primitives/toast.tsx
355
+ import * as React7 from "react";
356
+ import * as ToastPrimitives from "@radix-ui/react-toast";
357
+ import { cva as cva3 } from "class-variance-authority";
358
+ import { jsx as jsx8 } from "react/jsx-runtime";
359
+ var ToastProvider = ToastPrimitives.Provider;
360
+ var ToastViewport = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx8(
361
+ ToastPrimitives.Viewport,
362
+ {
363
+ ref,
364
+ className: cn(
365
+ "fixed bottom-20 left-0 right-0 z-[100] flex max-h-screen w-full flex-col items-center p-4 gap-2",
366
+ className
367
+ ),
368
+ ...props
369
+ }
370
+ ));
371
+ ToastViewport.displayName = ToastPrimitives.Viewport.displayName;
372
+ var toastVariants = cva3(
373
+ "group pointer-events-auto relative flex w-full max-w-md items-center justify-between space-x-3 overflow-hidden rounded-xl border backdrop-blur-xl p-4 pr-10 shadow-[0_0_30px_rgba(0,0,0,0.3)] transition-all data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=move]:transition-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-bottom-full data-[state=open]:slide-in-from-bottom-full",
374
+ {
375
+ variants: {
376
+ variant: {
377
+ default: "border-white/10 bg-surface-dark/95 text-white",
378
+ destructive: "border-red-500/20 bg-red-500/10 text-red-400"
379
+ }
380
+ },
381
+ defaultVariants: {
382
+ variant: "default"
383
+ }
384
+ }
385
+ );
386
+ var Toast = React7.forwardRef(({ className, variant, ...props }, ref) => {
387
+ return /* @__PURE__ */ jsx8(
388
+ ToastPrimitives.Root,
389
+ {
390
+ ref,
391
+ className: cn(toastVariants({ variant }), className),
392
+ ...props
393
+ }
394
+ );
395
+ });
396
+ Toast.displayName = ToastPrimitives.Root.displayName;
397
+ var ToastAction = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx8(
398
+ ToastPrimitives.Action,
399
+ {
400
+ ref,
401
+ className: cn(
402
+ "inline-flex h-8 shrink-0 items-center justify-center rounded-md border bg-transparent px-3 text-sm font-medium ring-offset-background transition-colors hover:bg-secondary focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 group-[.destructive]:border-muted/40 group-[.destructive]:hover:border-destructive/30 group-[.destructive]:hover:bg-destructive group-[.destructive]:hover:text-destructive-foreground group-[.destructive]:focus:ring-destructive",
403
+ className
404
+ ),
405
+ ...props
406
+ }
407
+ ));
408
+ ToastAction.displayName = ToastPrimitives.Action.displayName;
409
+ var ToastClose = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx8(
410
+ ToastPrimitives.Close,
411
+ {
412
+ ref,
413
+ className: cn(
414
+ "absolute right-2 top-2 rounded-full p-1 text-white/50 opacity-100 transition-all hover:text-white hover:bg-white/10 focus:opacity-100 focus:outline-none focus:ring-2 focus:ring-primary group-[.destructive]:text-red-300 group-[.destructive]:hover:text-red-50 group-[.destructive]:hover:bg-red-500/20 group-[.destructive]:focus:ring-red-400",
415
+ className
416
+ ),
417
+ "toast-close": "",
418
+ ...props,
419
+ children: /* @__PURE__ */ jsx8(Icon, { name: "close", size: "sm" })
420
+ }
421
+ ));
422
+ ToastClose.displayName = ToastPrimitives.Close.displayName;
423
+ var ToastTitle = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx8(
424
+ ToastPrimitives.Title,
425
+ {
426
+ ref,
427
+ className: cn("text-sm font-semibold text-white", className),
428
+ ...props
429
+ }
430
+ ));
431
+ ToastTitle.displayName = ToastPrimitives.Title.displayName;
432
+ var ToastDescription = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx8(
433
+ ToastPrimitives.Description,
434
+ {
435
+ ref,
436
+ className: cn("text-xs text-white/70", className),
437
+ ...props
438
+ }
439
+ ));
440
+ ToastDescription.displayName = ToastPrimitives.Description.displayName;
441
+
442
+ // src/web/primitives/toaster.tsx
443
+ import { useEffect as useEffect2, useState as useState2 } from "react";
444
+
445
+ // src/web/hooks/use-toast.ts
446
+ import * as React8 from "react";
447
+ var TOAST_LIMIT = 1;
448
+ var TOAST_REMOVE_DELAY = 1e3;
449
+ var count = 0;
450
+ function genId() {
451
+ count = (count + 1) % Number.MAX_SAFE_INTEGER;
452
+ return count.toString();
453
+ }
454
+ var toastTimeouts = /* @__PURE__ */ new Map();
455
+ var addToRemoveQueue = (toastId) => {
456
+ if (toastTimeouts.has(toastId)) return;
457
+ const timeout = setTimeout(() => {
458
+ toastTimeouts.delete(toastId);
459
+ dispatch({ type: "REMOVE_TOAST", toastId });
460
+ }, TOAST_REMOVE_DELAY);
461
+ toastTimeouts.set(toastId, timeout);
462
+ };
463
+ var reducer = (state, action) => {
464
+ switch (action.type) {
465
+ case "ADD_TOAST":
466
+ return {
467
+ ...state,
468
+ toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT)
469
+ };
470
+ case "UPDATE_TOAST":
471
+ return {
472
+ ...state,
473
+ toasts: state.toasts.map(
474
+ (t) => t.id === action.toast.id ? { ...t, ...action.toast } : t
475
+ )
476
+ };
477
+ case "DISMISS_TOAST": {
478
+ const { toastId } = action;
479
+ if (toastId) {
480
+ addToRemoveQueue(toastId);
481
+ } else {
482
+ state.toasts.forEach((toast2) => addToRemoveQueue(toast2.id));
483
+ }
484
+ return {
485
+ ...state,
486
+ toasts: state.toasts.map(
487
+ (t) => t.id === toastId || toastId === void 0 ? { ...t, open: false } : t
488
+ )
489
+ };
490
+ }
491
+ case "REMOVE_TOAST":
492
+ if (action.toastId === void 0) return { ...state, toasts: [] };
493
+ return {
494
+ ...state,
495
+ toasts: state.toasts.filter((t) => t.id !== action.toastId)
496
+ };
497
+ }
498
+ };
499
+ var listeners = [];
500
+ var memoryState = { toasts: [] };
501
+ function dispatch(action) {
502
+ memoryState = reducer(memoryState, action);
503
+ listeners.forEach((listener) => listener(memoryState));
504
+ }
505
+ function toast({ duration = 4e3, ...props }) {
506
+ const id = genId();
507
+ const update = (props2) => dispatch({ type: "UPDATE_TOAST", toast: { ...props2, id } });
508
+ const dismiss = () => dispatch({ type: "DISMISS_TOAST", toastId: id });
509
+ dispatch({
510
+ type: "ADD_TOAST",
511
+ toast: {
512
+ ...props,
513
+ id,
514
+ open: true,
515
+ duration,
516
+ onOpenChange: (open) => {
517
+ if (!open) dismiss();
518
+ }
519
+ }
520
+ });
521
+ if (duration > 0) {
522
+ setTimeout(() => dismiss(), duration);
523
+ }
524
+ return { id, dismiss, update };
525
+ }
526
+ function useToast() {
527
+ const [state, setState] = React8.useState(memoryState);
528
+ React8.useEffect(() => {
529
+ listeners.push(setState);
530
+ return () => {
531
+ const index = listeners.indexOf(setState);
532
+ if (index > -1) listeners.splice(index, 1);
533
+ };
534
+ }, [state]);
535
+ return {
536
+ ...state,
537
+ toast,
538
+ dismiss: (toastId) => dispatch({ type: "DISMISS_TOAST", toastId })
539
+ };
540
+ }
541
+
542
+ // src/web/primitives/toaster.tsx
543
+ import { jsx as jsx9, jsxs as jsxs2 } from "react/jsx-runtime";
544
+ function ToastWithProgress({ id, title, description, action, duration = 4e3, variant, ...props }) {
545
+ const [progress, setProgress] = useState2(100);
546
+ useEffect2(() => {
547
+ const interval = 50;
548
+ const decrement = interval / duration * 100;
549
+ const timer = setInterval(() => {
550
+ setProgress((prev) => {
551
+ const next = prev - decrement;
552
+ return next <= 0 ? 0 : next;
553
+ });
554
+ }, interval);
555
+ return () => clearInterval(timer);
556
+ }, [duration]);
557
+ const getIcon = () => {
558
+ if (variant === "destructive") {
559
+ return /* @__PURE__ */ jsx9(Icon, { name: "error", size: "md", className: "text-red-400" });
560
+ }
561
+ return /* @__PURE__ */ jsx9(Icon, { name: "check_circle", size: "md", className: "text-primary" });
562
+ };
563
+ return /* @__PURE__ */ jsxs2(Toast, { ...props, variant, children: [
564
+ /* @__PURE__ */ jsxs2("div", { className: "flex items-start gap-3 flex-1", children: [
565
+ getIcon(),
566
+ /* @__PURE__ */ jsxs2("div", { className: "grid gap-1 flex-1", children: [
567
+ title && /* @__PURE__ */ jsx9(ToastTitle, { children: title }),
568
+ description && /* @__PURE__ */ jsx9(ToastDescription, { children: description })
569
+ ] })
570
+ ] }),
571
+ action,
572
+ /* @__PURE__ */ jsx9(ToastClose, {}),
573
+ /* @__PURE__ */ jsx9("div", { className: "absolute bottom-0 left-0 right-0 h-1 bg-white/10 overflow-hidden", children: /* @__PURE__ */ jsx9(
574
+ "div",
575
+ {
576
+ className: `h-full transition-all ease-linear ${variant === "destructive" ? "bg-red-500" : "bg-primary"}`,
577
+ style: { width: `${progress}%` }
578
+ }
579
+ ) })
580
+ ] });
581
+ }
582
+ function Toaster() {
583
+ const { toasts } = useToast();
584
+ return /* @__PURE__ */ jsxs2(ToastProvider, { children: [
585
+ toasts.map(function({ id, title, description, action, duration, ...props }) {
586
+ return /* @__PURE__ */ jsx9(
587
+ ToastWithProgress,
588
+ {
589
+ id,
590
+ title,
591
+ description,
592
+ action,
593
+ duration,
594
+ ...props
595
+ },
596
+ id
597
+ );
598
+ }),
599
+ /* @__PURE__ */ jsx9(ToastViewport, {})
600
+ ] });
601
+ }
602
+
603
+ // src/web/components/status-badge.tsx
604
+ import { jsx as jsx10, jsxs as jsxs3 } from "react/jsx-runtime";
605
+ function StatusBadge({ status, className }) {
606
+ const config = {
607
+ success: {
608
+ color: "text-primary",
609
+ bg: "bg-primary/10",
610
+ border: "border-primary/20",
611
+ icon: "check_circle",
612
+ label: "Success"
613
+ },
614
+ completed: {
615
+ color: "text-primary",
616
+ bg: "bg-primary/10",
617
+ border: "border-primary/20",
618
+ icon: "check_circle",
619
+ label: "Completed"
620
+ },
621
+ pending: {
622
+ color: "text-yellow-500",
623
+ bg: "bg-yellow-500/10",
624
+ border: "border-yellow-500/20",
625
+ icon: "schedule",
626
+ label: "Pending"
627
+ },
628
+ failed: {
629
+ color: "text-red-500",
630
+ bg: "bg-red-500/10",
631
+ border: "border-red-500/20",
632
+ icon: "error",
633
+ label: "Failed"
634
+ },
635
+ error: {
636
+ color: "text-red-500",
637
+ bg: "bg-red-500/10",
638
+ border: "border-red-500/20",
639
+ icon: "error",
640
+ label: "Error"
641
+ }
642
+ };
643
+ const { color, bg, border, icon, label } = config[status];
644
+ return /* @__PURE__ */ jsxs3(
645
+ "div",
646
+ {
647
+ className: cn(
648
+ "inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full border font-medium text-xs",
649
+ bg,
650
+ border,
651
+ color,
652
+ className
653
+ ),
654
+ children: [
655
+ /* @__PURE__ */ jsx10("span", { className: "material-symbols-outlined text-[14px]", children: icon }),
656
+ /* @__PURE__ */ jsx10("span", { children: label })
657
+ ]
658
+ }
659
+ );
660
+ }
661
+
662
+ // src/web/components/network-badge.tsx
663
+ import { jsx as jsx11, jsxs as jsxs4 } from "react/jsx-runtime";
664
+ var networkConfig = {
665
+ L1: {
666
+ color: "text-network-bitcoin",
667
+ bg: "bg-network-bitcoin/10 backdrop-blur-md",
668
+ border: "border-network-bitcoin/20",
669
+ label: "L1",
670
+ iconSuffix: "bitcoin/bitcoin-logo.svg"
671
+ },
672
+ LN: {
673
+ color: "text-purple-400",
674
+ bg: "bg-purple-500/10 backdrop-blur-md",
675
+ border: "border-purple-500/20",
676
+ label: "LN",
677
+ iconSuffix: "lightning/lightning.svg"
678
+ },
679
+ RGB20: {
680
+ color: "text-network-rgb",
681
+ bg: "bg-network-rgb/10 backdrop-blur-md",
682
+ border: "border-network-rgb/20",
683
+ label: "RGB",
684
+ iconSuffix: "rgb/rgb-logo.svg"
685
+ },
686
+ RGB21: {
687
+ color: "text-network-rgb",
688
+ bg: "bg-network-rgb/10 backdrop-blur-md",
689
+ border: "border-network-rgb/20",
690
+ label: "RGB21",
691
+ iconSuffix: "rgb/rgb-logo.svg"
692
+ },
693
+ "RGB-L1": {
694
+ color: "text-network-rgb",
695
+ bg: "bg-network-rgb/10 backdrop-blur-md",
696
+ border: "border-network-rgb/20",
697
+ label: "RGB L1",
698
+ iconSuffix: "rgb/rgb-logo.svg"
699
+ },
700
+ "RGB-LN": {
701
+ color: "text-network-rgb",
702
+ bg: "bg-network-rgb/10 backdrop-blur-md",
703
+ border: "border-network-rgb/20",
704
+ label: "RGB LN",
705
+ iconSuffix: "rgb/rgb-logo.svg"
706
+ },
707
+ Spark: {
708
+ color: "text-network-spark",
709
+ bg: "bg-network-spark/10 backdrop-blur-md",
710
+ border: "border-network-spark/20",
711
+ label: "Spark",
712
+ iconSuffix: "spark/Asterisk/Spark Asterisk White.svg"
713
+ },
714
+ Arkade: {
715
+ color: "text-network-arkade",
716
+ bg: "bg-network-arkade/10 backdrop-blur-md",
717
+ border: "border-network-arkade/20",
718
+ label: "Arkade",
719
+ iconSuffix: "arkade/arkade-icon.svg"
720
+ }
721
+ };
722
+ function NetworkBadge({ network, iconBasePath = "/icons", className }) {
723
+ const { color, bg, border, label, iconSuffix } = networkConfig[network];
724
+ const icon = `${iconBasePath}/${iconSuffix}`;
725
+ return /* @__PURE__ */ jsxs4(
726
+ "span",
727
+ {
728
+ className: cn(
729
+ "text-xxs px-2 py-0.5 rounded-full font-bold border shadow-inner flex items-center justify-center gap-1 w-max transition-all",
730
+ bg,
731
+ border,
732
+ color,
733
+ className
734
+ ),
735
+ children: [
736
+ /* @__PURE__ */ jsx11(
737
+ "img",
738
+ {
739
+ src: icon,
740
+ alt: network,
741
+ className: cn("size-3 object-contain", network === "Spark" && "opacity-80")
742
+ }
743
+ ),
744
+ label
745
+ ]
746
+ }
747
+ );
748
+ }
749
+
750
+ // src/web/components/asset-icon.tsx
751
+ import { useEffect as useEffect4, useState as useState4 } from "react";
752
+
753
+ // src/web/hooks/use-asset-icon.ts
754
+ import { useState as useState3, useEffect as useEffect3 } from "react";
755
+ var DEFAULT_ICON_CDN_BASE_URL = "https://raw.githubusercontent.com/kaleidoswap/coinmarketcap-icons-cryptos/refs/heads/main/icons/";
756
+ var DICEBEAR_SHAPES_BASE_URL = "https://api.dicebear.com/9.x/shapes/svg";
757
+ var TICKER_MAPPINGS = {
758
+ SAT: "BTC",
759
+ None: ""
760
+ };
761
+ var VALID_ICON_TICKER_REGEX = /^[A-Z0-9-]{1,12}$/;
762
+ function getAssetIconUrl(ticker, cdnBaseUrl = DEFAULT_ICON_CDN_BASE_URL) {
763
+ if (!ticker || ticker.trim() === "") return "";
764
+ const normalized = ticker.toUpperCase().trim();
765
+ if (!VALID_ICON_TICKER_REGEX.test(normalized)) return "";
766
+ if (TICKER_MAPPINGS[normalized] !== void 0) {
767
+ const mapped = TICKER_MAPPINGS[normalized];
768
+ if (mapped === "") return "";
769
+ return getAssetIconUrl(mapped, cdnBaseUrl);
770
+ }
771
+ return `${cdnBaseUrl}${normalized.toLowerCase()}.png`;
772
+ }
773
+ function getFallbackAssetIconUrl(seed) {
774
+ const normalized = seed.trim();
775
+ if (!normalized) return "";
776
+ const params = new URLSearchParams({
777
+ seed: normalized,
778
+ backgroundType: "gradientLinear",
779
+ radius: "50"
780
+ });
781
+ return `${DICEBEAR_SHAPES_BASE_URL}?${params.toString()}`;
782
+ }
783
+ function useAssetIcon(ticker, cdnBaseUrl) {
784
+ const [url, setUrl] = useState3(() => getAssetIconUrl(ticker, cdnBaseUrl));
785
+ useEffect3(() => {
786
+ setUrl(getAssetIconUrl(ticker, cdnBaseUrl));
787
+ }, [ticker, cdnBaseUrl]);
788
+ return url;
789
+ }
790
+
791
+ // src/web/components/asset-icon.tsx
792
+ import { jsx as jsx12 } from "react/jsx-runtime";
793
+ var ASSET_COLORS = {
794
+ BTC: "bg-transparent",
795
+ ETH: "bg-[#627EEA]",
796
+ USDT: "bg-[#26A17B]",
797
+ USDC: "bg-[#2775CA]"
798
+ };
799
+ var LOCAL_ICONS = {
800
+ BTC: "/icons/bitcoin/bitcoin-logo.svg",
801
+ ARKADE: "/icons/arkade/arkade-icon.svg",
802
+ RGB: "/icons/rgb/rgb-logo.svg",
803
+ SPARK: "/icons/spark/Asterisk/Spark Asterisk White.svg"
804
+ };
805
+ function AssetIcon({ ticker, logoUri, cdnBaseUrl, size = 40, className }) {
806
+ const normTicker = ticker.toUpperCase();
807
+ const localIcon = LOCAL_ICONS[normTicker];
808
+ const cdnUrl = useAssetIcon(ticker, cdnBaseUrl);
809
+ const fallbackUrl = getFallbackAssetIconUrl(ticker);
810
+ const [useFallback, setUseFallback] = useState4(!logoUri && !localIcon && !cdnUrl && !!fallbackUrl);
811
+ const [failed, setFailed] = useState4(false);
812
+ useEffect4(() => {
813
+ setFailed(false);
814
+ setUseFallback(!logoUri && !localIcon && !cdnUrl && !!fallbackUrl);
815
+ }, [logoUri, localIcon, cdnUrl, fallbackUrl]);
816
+ const iconUrl = logoUri ? logoUri : localIcon ? localIcon : failed ? null : useFallback || !cdnUrl ? fallbackUrl || null : cdnUrl || fallbackUrl || null;
817
+ const bgColor = ASSET_COLORS[normTicker] || "bg-slate-600";
818
+ if (iconUrl) {
819
+ return /* @__PURE__ */ jsx12(
820
+ "div",
821
+ {
822
+ className: cn(
823
+ "rounded-full overflow-hidden flex items-center justify-center shadow-inner",
824
+ !localIcon && bgColor,
825
+ className
826
+ ),
827
+ style: { width: size, height: size },
828
+ children: /* @__PURE__ */ jsx12(
829
+ "img",
830
+ {
831
+ src: iconUrl,
832
+ alt: `${ticker} icon`,
833
+ width: size,
834
+ height: size,
835
+ className: "object-cover w-full h-full",
836
+ onError: () => {
837
+ if (logoUri) {
838
+ setFailed(false);
839
+ setUseFallback(!localIcon && !!fallbackUrl);
840
+ return;
841
+ }
842
+ if (localIcon) return;
843
+ if (!useFallback && fallbackUrl) {
844
+ setUseFallback(true);
845
+ return;
846
+ }
847
+ setFailed(true);
848
+ }
849
+ }
850
+ )
851
+ }
852
+ );
853
+ }
854
+ return /* @__PURE__ */ jsx12(
855
+ "div",
856
+ {
857
+ className: cn(
858
+ "rounded-full flex items-center justify-center font-bold text-white shadow-inner border border-white/10",
859
+ bgColor,
860
+ className
861
+ ),
862
+ style: { width: size, height: size, fontSize: size * 0.4 },
863
+ children: ticker.charAt(0).toUpperCase()
864
+ }
865
+ );
866
+ }
867
+
868
+ // src/web/components/asset-card.tsx
869
+ import { jsx as jsx13, jsxs as jsxs5 } from "react/jsx-runtime";
870
+ function AssetCard({
871
+ ticker,
872
+ name,
873
+ displayBalance,
874
+ networks = [],
875
+ logoUri,
876
+ balanceVisible = true,
877
+ onClick,
878
+ className
879
+ }) {
880
+ const shown = balanceVisible ? displayBalance : "\u2022\u2022\u2022\u2022\u2022\u2022";
881
+ return /* @__PURE__ */ jsxs5(
882
+ "div",
883
+ {
884
+ className: cn(
885
+ "p-4 rounded-card bg-background-dark/40 backdrop-blur-xl border border-white/5 transition-all shadow-sm relative overflow-hidden group",
886
+ onClick && "cursor-pointer hover:border-primary/40 hover:shadow-glow-subtle active:scale-[0.98]",
887
+ className
888
+ ),
889
+ onClick,
890
+ children: [
891
+ /* @__PURE__ */ jsx13("div", { className: "absolute inset-0 bg-gradient-to-br from-white/5 to-transparent opacity-0 group-hover:opacity-100 transition-opacity pointer-events-none" }),
892
+ /* @__PURE__ */ jsxs5("div", { className: "flex items-center justify-between relative z-10", children: [
893
+ /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-3", children: [
894
+ /* @__PURE__ */ jsx13(
895
+ AssetIcon,
896
+ {
897
+ ticker,
898
+ logoUri,
899
+ size: 44,
900
+ className: "group-hover:scale-105 transition-transform"
901
+ }
902
+ ),
903
+ /* @__PURE__ */ jsxs5("div", { className: "flex flex-col", children: [
904
+ /* @__PURE__ */ jsx13(
905
+ "span",
906
+ {
907
+ className: cn(
908
+ "font-bold text-base leading-tight tracking-wide text-white",
909
+ onClick && "group-hover:text-primary transition-colors"
910
+ ),
911
+ children: name
912
+ }
913
+ ),
914
+ /* @__PURE__ */ jsx13("div", { className: "flex flex-wrap gap-1 mt-1", children: networks.map((network) => /* @__PURE__ */ jsx13(NetworkBadge, { network }, network)) })
915
+ ] })
916
+ ] }),
917
+ /* @__PURE__ */ jsxs5("div", { className: "text-right", children: [
918
+ /* @__PURE__ */ jsx13("p", { className: "font-bold text-base tracking-tight text-white group-hover:text-white/90 transition-colors", children: shown }),
919
+ /* @__PURE__ */ jsx13("p", { className: "text-tiny text-slate-400 font-medium tracking-wide uppercase mt-0.5", children: ticker })
920
+ ] })
921
+ ] })
922
+ ]
923
+ }
924
+ );
925
+ }
926
+
927
+ // src/web/components/transaction-card.tsx
928
+ import { jsx as jsx14, jsxs as jsxs6 } from "react/jsx-runtime";
929
+ function TransactionCard({
930
+ direction,
931
+ status,
932
+ displayAmount,
933
+ unit = "sats",
934
+ timestamp,
935
+ onClick,
936
+ className
937
+ }) {
938
+ const isInbound = direction === "inbound";
939
+ const formatDate = (ts) => new Date(ts * 1e3).toLocaleDateString();
940
+ return /* @__PURE__ */ jsxs6(
941
+ "div",
942
+ {
943
+ className: cn(
944
+ "p-4 rounded-card bg-background-dark/40 backdrop-blur-xl border border-white/5 flex items-center justify-between transition-all shadow-sm relative overflow-hidden group",
945
+ onClick && "cursor-pointer hover:border-primary/40 hover:shadow-glow-subtle active:scale-[0.98]",
946
+ className
947
+ ),
948
+ onClick,
949
+ children: [
950
+ /* @__PURE__ */ jsx14("div", { className: "absolute inset-0 bg-gradient-to-br from-white/5 to-transparent opacity-0 group-hover:opacity-100 transition-opacity pointer-events-none" }),
951
+ /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-3 relative z-10", children: [
952
+ /* @__PURE__ */ jsx14(
953
+ "div",
954
+ {
955
+ className: cn(
956
+ "size-11 rounded-full flex items-center justify-center shadow-inner group-hover:scale-105 transition-transform",
957
+ isInbound ? "bg-primary/20 text-primary border border-primary/20" : "bg-white/5 text-slate-300 border border-white/10"
958
+ ),
959
+ children: /* @__PURE__ */ jsx14("span", { className: "material-symbols-outlined text-[20px]", children: isInbound ? "arrow_downward" : "arrow_outward" })
960
+ }
961
+ ),
962
+ /* @__PURE__ */ jsxs6("div", { className: "flex flex-col", children: [
963
+ /* @__PURE__ */ jsx14(
964
+ "span",
965
+ {
966
+ className: cn(
967
+ "font-bold text-sm text-white tracking-wide",
968
+ onClick && "group-hover:text-primary transition-colors"
969
+ ),
970
+ children: isInbound ? "Received" : "Sent"
971
+ }
972
+ ),
973
+ /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-2 mt-1", children: [
974
+ /* @__PURE__ */ jsx14(StatusBadge, { status, className: "text-xxs px-1.5 py-0.5" }),
975
+ /* @__PURE__ */ jsx14("span", { className: "text-tiny text-slate-400 font-medium tracking-wide", children: formatDate(timestamp) })
976
+ ] })
977
+ ] })
978
+ ] }),
979
+ /* @__PURE__ */ jsxs6("div", { className: "text-right relative z-10", children: [
980
+ /* @__PURE__ */ jsxs6(
981
+ "p",
982
+ {
983
+ className: cn(
984
+ "font-bold text-base tracking-tight group-hover:opacity-90 transition-opacity",
985
+ isInbound ? "text-primary" : "text-white"
986
+ ),
987
+ children: [
988
+ isInbound ? "+" : "-",
989
+ displayAmount
990
+ ]
991
+ }
992
+ ),
993
+ /* @__PURE__ */ jsx14("p", { className: "text-tiny text-slate-400 font-medium tracking-wide uppercase mt-0.5", children: unit })
994
+ ] })
995
+ ]
996
+ }
997
+ );
998
+ }
999
+
1000
+ // src/web/components/page-header.tsx
1001
+ import { jsx as jsx15, jsxs as jsxs7 } from "react/jsx-runtime";
1002
+ function PageHeader({ left, title, right, borderClassName = "border-border" }) {
1003
+ if (!title) {
1004
+ return /* @__PURE__ */ jsxs7("header", { className: `sticky top-0 z-20 flex items-center border-b bg-background-dark/95 px-4 py-3.5 backdrop-blur ${borderClassName}`, children: [
1005
+ /* @__PURE__ */ jsx15("div", { className: "flex shrink-0 items-center", children: left }),
1006
+ /* @__PURE__ */ jsx15("div", { className: "ml-auto flex min-w-0 items-center justify-end gap-2", children: right })
1007
+ ] });
1008
+ }
1009
+ return /* @__PURE__ */ jsxs7("header", { className: `sticky top-0 z-20 flex items-center border-b bg-background-dark/95 px-4 py-3.5 backdrop-blur ${borderClassName}`, children: [
1010
+ /* @__PURE__ */ jsx15("div", { className: "flex min-w-0 flex-1 items-center", children: left }),
1011
+ /* @__PURE__ */ jsx15("span", { className: "font-bold text-body text-white shrink-0", children: title }),
1012
+ /* @__PURE__ */ jsx15("div", { className: "flex min-w-0 flex-1 items-center justify-end gap-2", children: right })
1013
+ ] });
1014
+ }
1015
+
1016
+ // src/web/components/setting-item.tsx
1017
+ import { jsx as jsx16, jsxs as jsxs8 } from "react/jsx-runtime";
1018
+ function SettingItem({
1019
+ icon,
1020
+ iconSrc,
1021
+ iconAlt,
1022
+ title,
1023
+ description,
1024
+ value,
1025
+ onClick,
1026
+ showChevron = true,
1027
+ className,
1028
+ iconColor = "text-primary"
1029
+ }) {
1030
+ const isClickable = !!onClick;
1031
+ return /* @__PURE__ */ jsx16(
1032
+ "div",
1033
+ {
1034
+ className: cn(
1035
+ "p-5 rounded-2xl glass-panel border border-white/10 shadow-inner transition-all duration-200",
1036
+ isClickable && "cursor-pointer hover:bg-white/5 active:scale-[0.98]",
1037
+ className
1038
+ ),
1039
+ onClick,
1040
+ children: /* @__PURE__ */ jsxs8("div", { className: "flex items-center justify-between gap-3", children: [
1041
+ /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-3 flex-1 min-w-0", children: [
1042
+ (icon || iconSrc) && /* @__PURE__ */ jsx16(
1043
+ "div",
1044
+ {
1045
+ className: cn(
1046
+ "flex-shrink-0 size-10 rounded-xl flex items-center justify-center bg-black/20 shadow-inner border border-white/5",
1047
+ iconColor
1048
+ ),
1049
+ children: iconSrc ? /* @__PURE__ */ jsx16("img", { src: iconSrc, alt: iconAlt ?? title, className: "size-5 object-contain" }) : /* @__PURE__ */ jsx16("span", { className: "material-symbols-outlined text-[20px]", children: icon })
1050
+ }
1051
+ ),
1052
+ /* @__PURE__ */ jsxs8("div", { className: "flex flex-col flex-1 min-w-0", children: [
1053
+ /* @__PURE__ */ jsx16("span", { className: "font-bold text-body text-white tracking-wide", children: title }),
1054
+ description && /* @__PURE__ */ jsx16("span", { className: "text-sm text-slate-400 mt-0.5 font-medium", children: description })
1055
+ ] })
1056
+ ] }),
1057
+ /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-2 flex-shrink-0", children: [
1058
+ value && /* @__PURE__ */ jsx16("span", { className: "text-xs text-slate-400 font-mono", children: value }),
1059
+ showChevron && isClickable && /* @__PURE__ */ jsx16("span", { className: "material-symbols-outlined text-[16px] text-slate-500", children: "chevron_right" })
1060
+ ] })
1061
+ ] })
1062
+ }
1063
+ );
1064
+ }
1065
+
1066
+ // src/web/components/section-label.tsx
1067
+ import { jsx as jsx17 } from "react/jsx-runtime";
1068
+ function SectionLabel({ children, className }) {
1069
+ return /* @__PURE__ */ jsx17("span", { className: cn("text-xxs font-black uppercase tracking-[0.22em] text-white/30", className), children });
1070
+ }
1071
+
1072
+ // src/web/components/alert-banner.tsx
1073
+ import { jsx as jsx18, jsxs as jsxs9 } from "react/jsx-runtime";
1074
+ var variantStyles = {
1075
+ error: {
1076
+ container: "bg-red-500/10 border-red-500/20",
1077
+ icon: "text-red-400",
1078
+ iconName: "error"
1079
+ },
1080
+ warning: {
1081
+ container: "bg-amber-500/10 border-amber-500/20",
1082
+ icon: "text-amber-400",
1083
+ iconName: "warning"
1084
+ },
1085
+ info: {
1086
+ container: "bg-blue-500/10 border-blue-500/20",
1087
+ icon: "text-blue-400",
1088
+ iconName: "info"
1089
+ },
1090
+ success: {
1091
+ container: "bg-primary/10 border-primary/20",
1092
+ icon: "text-primary",
1093
+ iconName: "check_circle"
1094
+ }
1095
+ };
1096
+ function AlertBanner({ variant = "info", icon, children, className }) {
1097
+ const styles = variantStyles[variant];
1098
+ return /* @__PURE__ */ jsxs9("div", { className: cn("rounded-xl border p-3 flex items-start gap-2", styles.container, className), children: [
1099
+ /* @__PURE__ */ jsx18(Icon, { name: icon ?? styles.iconName, size: "md", className: cn("shrink-0 mt-0.5", styles.icon) }),
1100
+ /* @__PURE__ */ jsx18("div", { className: "text-sm", children })
1101
+ ] });
1102
+ }
1103
+
1104
+ // src/web/components/error-boundary.tsx
1105
+ import { Component } from "react";
1106
+ import { jsx as jsx19, jsxs as jsxs10 } from "react/jsx-runtime";
1107
+ var ErrorBoundary = class extends Component {
1108
+ constructor(props) {
1109
+ super(props);
1110
+ this.state = { hasError: false, error: null };
1111
+ }
1112
+ static getDerivedStateFromError(error) {
1113
+ return { hasError: true, error };
1114
+ }
1115
+ componentDidCatch(error, info) {
1116
+ console.error("[ErrorBoundary] Render crash:", error, info);
1117
+ }
1118
+ render() {
1119
+ if (this.state.hasError) {
1120
+ return this.props.fallback ?? /* @__PURE__ */ jsxs10("div", { className: "min-h-screen bg-background-dark text-white font-display flex flex-col items-center justify-center p-6 gap-4", children: [
1121
+ /* @__PURE__ */ jsx19("span", { className: "material-symbols-outlined text-red-400 text-[48px]", children: "error" }),
1122
+ /* @__PURE__ */ jsx19("h2", { className: "text-lg font-bold", children: "Something went wrong" }),
1123
+ /* @__PURE__ */ jsx19("p", { className: "text-sm text-white/50 text-center", children: this.state.error?.message ?? "An unexpected error occurred." }),
1124
+ /* @__PURE__ */ jsx19(
1125
+ "button",
1126
+ {
1127
+ onClick: () => {
1128
+ this.setState({ hasError: false, error: null });
1129
+ this.props.onReset?.();
1130
+ },
1131
+ className: "px-6 py-3 rounded-xl bg-primary text-black font-bold hover:bg-primary/90 transition-all",
1132
+ children: "Try Again"
1133
+ }
1134
+ )
1135
+ ] });
1136
+ }
1137
+ return this.props.children;
1138
+ }
1139
+ };
1140
+ export {
1141
+ AlertBanner,
1142
+ AssetCard,
1143
+ AssetIcon,
1144
+ Button,
1145
+ Card,
1146
+ CardContent,
1147
+ CardDescription,
1148
+ CardFooter,
1149
+ CardHeader,
1150
+ CardTitle,
1151
+ Dialog,
1152
+ DialogClose,
1153
+ DialogContent,
1154
+ DialogDescription,
1155
+ DialogFooter,
1156
+ DialogHeader,
1157
+ DialogOverlay,
1158
+ DialogPortal,
1159
+ DialogTitle,
1160
+ DialogTrigger,
1161
+ ErrorBoundary,
1162
+ Icon,
1163
+ Icons,
1164
+ Input,
1165
+ Label,
1166
+ NetworkBadge,
1167
+ PageHeader,
1168
+ SectionLabel,
1169
+ SettingItem,
1170
+ StatusBadge,
1171
+ Tabs,
1172
+ TabsContent,
1173
+ TabsList,
1174
+ TabsTrigger,
1175
+ Toast,
1176
+ ToastAction,
1177
+ ToastClose,
1178
+ ToastDescription,
1179
+ ToastProvider,
1180
+ ToastTitle,
1181
+ ToastViewport,
1182
+ Toaster,
1183
+ TransactionCard,
1184
+ buttonVariants,
1185
+ cn,
1186
+ getAssetIconUrl,
1187
+ getFallbackAssetIconUrl,
1188
+ toast,
1189
+ useAssetIcon,
1190
+ useToast
1191
+ };