@aurum-sdk/core 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,2432 @@
1
+ // src/contexts/WidgetContext.tsx
2
+ import { createContext, useContext } from "react";
3
+ import { jsx } from "react/jsx-runtime";
4
+ var WidgetContext = createContext(null);
5
+ var useWidgetContext = () => {
6
+ const context = useContext(WidgetContext);
7
+ if (!context) {
8
+ throw new Error("useWidgetContext must be used within a WidgetProvider");
9
+ }
10
+ return context;
11
+ };
12
+ var WidgetProvider = ({
13
+ children,
14
+ mode,
15
+ brandConfig,
16
+ onDismiss,
17
+ headerPortalRef = null
18
+ }) => {
19
+ const contextValue = {
20
+ mode,
21
+ brandConfig,
22
+ onDismiss,
23
+ headerPortalRef
24
+ };
25
+ return /* @__PURE__ */ jsx(WidgetContext.Provider, { value: contextValue, children });
26
+ };
27
+
28
+ // src/store/aurumStore.ts
29
+ import { create } from "zustand";
30
+ import { persist, createJSONStorage } from "zustand/middleware";
31
+ var getStorage = () => ({
32
+ getItem: (name) => {
33
+ if (typeof window === "undefined") return null;
34
+ return localStorage.getItem(name);
35
+ },
36
+ setItem: (name, value) => {
37
+ if (typeof window === "undefined") return;
38
+ localStorage.setItem(name, value);
39
+ },
40
+ removeItem: (name) => {
41
+ if (typeof window === "undefined") return;
42
+ localStorage.removeItem(name);
43
+ }
44
+ });
45
+ var storeCreator = persist(
46
+ (set) => ({
47
+ walletId: null,
48
+ address: null,
49
+ walletName: null,
50
+ email: null,
51
+ isConnected: false,
52
+ lastUsedWalletId: null,
53
+ setConnection: (walletId, address, walletName, email) => set({
54
+ walletId,
55
+ address,
56
+ walletName,
57
+ email: email ?? null,
58
+ isConnected: true,
59
+ lastUsedWalletId: walletId
60
+ }),
61
+ clearConnection: () => set({
62
+ walletId: null,
63
+ address: null,
64
+ walletName: null,
65
+ email: null,
66
+ isConnected: false
67
+ })
68
+ }),
69
+ {
70
+ name: "@aurum-sdk/core-store",
71
+ storage: createJSONStorage(getStorage),
72
+ skipHydration: typeof window === "undefined"
73
+ }
74
+ );
75
+ var useAurumStore = create(storeCreator);
76
+ var waitForStoreHydration = () => {
77
+ return new Promise((resolve) => {
78
+ if (useAurumStore.persist.hasHydrated()) {
79
+ resolve();
80
+ return;
81
+ }
82
+ useAurumStore.persist.onFinishHydration(() => resolve());
83
+ });
84
+ };
85
+
86
+ // src/utils/sortWallets.ts
87
+ import { WalletId } from "@aurum-sdk/types";
88
+ var WALLET_PRIORITY = [
89
+ WalletId.MetaMask,
90
+ WalletId.Phantom,
91
+ WalletId.WalletConnect,
92
+ WalletId.Brave,
93
+ WalletId.Rabby,
94
+ WalletId.CoinbaseWallet,
95
+ WalletId.Ledger
96
+ ];
97
+ function sortWallets(wallets, options = {}) {
98
+ const { filterHidden = true } = options;
99
+ const lastUsedWalletId = useAurumStore.getState().lastUsedWalletId;
100
+ let result = [...wallets];
101
+ if (filterHidden) {
102
+ result = result.filter((wallet) => !wallet.hide);
103
+ }
104
+ result.sort((a, b) => {
105
+ if (a.id === lastUsedWalletId) return -1;
106
+ if (b.id === lastUsedWalletId) return 1;
107
+ const aInstalled = a.isInstalled();
108
+ const bInstalled = b.isInstalled();
109
+ if (aInstalled !== bInstalled) {
110
+ return aInstalled ? -1 : 1;
111
+ }
112
+ const aIndex = WALLET_PRIORITY.indexOf(a.id);
113
+ const bIndex = WALLET_PRIORITY.indexOf(b.id);
114
+ if (aIndex === -1 && bIndex === -1) return 0;
115
+ if (aIndex === -1) return 1;
116
+ if (bIndex === -1) return -1;
117
+ return aIndex - bIndex;
118
+ });
119
+ return result;
120
+ }
121
+
122
+ // src/utils/platform/isMobile.ts
123
+ import MobileDetect from "mobile-detect";
124
+ function isMobile() {
125
+ if (typeof window === "undefined" || typeof navigator === "undefined") {
126
+ return false;
127
+ }
128
+ const md = new MobileDetect(window.navigator.userAgent);
129
+ return md.mobile() !== null || md.tablet() !== null;
130
+ }
131
+
132
+ // src/contexts/NavigationContext.tsx
133
+ import { createContext as createContext2, useContext as useContext2, useState } from "react";
134
+ import { jsx as jsx2 } from "react/jsx-runtime";
135
+ var NavigationContext = createContext2(void 0);
136
+ var NavigationProvider = ({ children, initialPage }) => {
137
+ const [currentPage, setCurrentPage] = useState(initialPage);
138
+ const [pageHistory, setPageHistory] = useState([initialPage]);
139
+ const navigateTo = (pageId) => {
140
+ setCurrentPage(pageId);
141
+ setPageHistory((prev) => [...prev, pageId]);
142
+ };
143
+ const navigateBack = () => {
144
+ if (pageHistory.length > 1) {
145
+ const newHistory = pageHistory.slice(0, -1);
146
+ const previousPage = newHistory[newHistory.length - 1];
147
+ setPageHistory(newHistory);
148
+ setCurrentPage(previousPage);
149
+ }
150
+ };
151
+ const canNavigateBack = pageHistory.length > 1;
152
+ const value = {
153
+ currentPage,
154
+ navigateTo,
155
+ navigateBack,
156
+ canNavigateBack
157
+ };
158
+ return /* @__PURE__ */ jsx2(NavigationContext.Provider, { value, children });
159
+ };
160
+ var useNavigation = () => {
161
+ const context = useContext2(NavigationContext);
162
+ if (context === void 0) {
163
+ throw new Error("useNavigation must be used within a NavigationProvider");
164
+ }
165
+ return context;
166
+ };
167
+
168
+ // src/contexts/ConnectModalContext.tsx
169
+ import { createContext as createContext4, useContext as useContext4, useState as useState13 } from "react";
170
+
171
+ // src/components/ConnectModal/SelectWallet.tsx
172
+ import { useMemo as useMemo3 } from "react";
173
+
174
+ // src/ui/Badge/Badge.tsx
175
+ import { jsx as jsx3 } from "react/jsx-runtime";
176
+ var RecentBadge = () => {
177
+ return /* @__PURE__ */ jsx3("span", { className: "aurum-badge-recent", children: "Recent" });
178
+ };
179
+
180
+ // src/ui/Button/Button.tsx
181
+ import { jsx as jsx4, jsxs } from "react/jsx-runtime";
182
+ var Button = ({
183
+ variant = "primary",
184
+ size = "md",
185
+ loading = false,
186
+ expand = false,
187
+ disabled = false,
188
+ className,
189
+ children,
190
+ ...props
191
+ }) => {
192
+ const baseClassName = "aurum-button";
193
+ const classes = [
194
+ baseClassName,
195
+ `${baseClassName}--${variant}`,
196
+ `${baseClassName}--${size}`,
197
+ expand && `${baseClassName}--full-width`,
198
+ loading && `${baseClassName}--loading`,
199
+ disabled && `${baseClassName}--disabled`,
200
+ className
201
+ ].filter(Boolean).join(" ");
202
+ return /* @__PURE__ */ jsxs("button", { className: classes, disabled: disabled || loading, ...props, children: [
203
+ loading && /* @__PURE__ */ jsx4(Spinner, { color: "currentColor" }),
204
+ children
205
+ ] });
206
+ };
207
+
208
+ // src/ui/Column/Column.tsx
209
+ import { jsx as jsx5 } from "react/jsx-runtime";
210
+ var Column = ({
211
+ align = "center",
212
+ gap = 8,
213
+ justify = "center",
214
+ style,
215
+ children
216
+ }) => {
217
+ return /* @__PURE__ */ jsx5(
218
+ "div",
219
+ {
220
+ style: {
221
+ display: "flex",
222
+ flexDirection: "column",
223
+ alignItems: align,
224
+ gap: `${gap}px`,
225
+ justifyContent: justify,
226
+ ...style
227
+ },
228
+ children
229
+ }
230
+ );
231
+ };
232
+
233
+ // src/ui/CopyButton/CopyButton.tsx
234
+ import { useState as useState2 } from "react";
235
+ import { Copy, CopyCheck } from "lucide-react";
236
+ import { jsx as jsx6, jsxs as jsxs2 } from "react/jsx-runtime";
237
+ var variantColorMap = {
238
+ primary: "var(--color-foreground)",
239
+ secondary: "var(--color-foreground-muted)",
240
+ tertiary: "var(--color-foreground-subtle)",
241
+ success: "var(--color-success)",
242
+ error: "var(--color-error)",
243
+ brand: "var(--color-primary)"
244
+ };
245
+ var CopyButton = ({
246
+ text,
247
+ label,
248
+ copiedLabel,
249
+ variant = "brand",
250
+ size = "sm",
251
+ iconSize = 16,
252
+ disabled = false
253
+ }) => {
254
+ const [isCopied, setIsCopied] = useState2(false);
255
+ const handleCopy = async () => {
256
+ if (!text || disabled || isCopied) return;
257
+ try {
258
+ await navigator.clipboard.writeText(text);
259
+ setIsCopied(true);
260
+ setTimeout(() => {
261
+ setIsCopied(false);
262
+ }, 1500);
263
+ } catch (error) {
264
+ console.error("Failed to copy text", error);
265
+ }
266
+ };
267
+ if (!label && !copiedLabel) {
268
+ return /* @__PURE__ */ jsx6(
269
+ Button,
270
+ {
271
+ variant: "text",
272
+ size,
273
+ onClick: handleCopy,
274
+ disabled,
275
+ style: { cursor: disabled ? "not-allowed" : "pointer", padding: "0.25rem" },
276
+ children: isCopied ? /* @__PURE__ */ jsx6(CopyCheck, { size: iconSize, color: "var(--color-success)" }) : /* @__PURE__ */ jsx6(Copy, { size: iconSize, color: variantColorMap[variant] })
277
+ }
278
+ );
279
+ }
280
+ return /* @__PURE__ */ jsx6(
281
+ Button,
282
+ {
283
+ variant: "text",
284
+ size,
285
+ onClick: handleCopy,
286
+ disabled,
287
+ style: { cursor: disabled ? "not-allowed" : "pointer" },
288
+ children: isCopied ? /* @__PURE__ */ jsxs2(
289
+ Text,
290
+ {
291
+ variant: "success",
292
+ size: "sm",
293
+ align: "center",
294
+ weight: "semibold",
295
+ style: { display: "flex", alignItems: "center", gap: 6 },
296
+ children: [
297
+ /* @__PURE__ */ jsx6(CopyCheck, { size: iconSize, color: "var(--color-success)" }),
298
+ copiedLabel || "Copied"
299
+ ]
300
+ }
301
+ ) : /* @__PURE__ */ jsxs2(
302
+ Text,
303
+ {
304
+ variant,
305
+ size: "sm",
306
+ align: "center",
307
+ weight: "semibold",
308
+ style: { display: "flex", alignItems: "center", gap: 6 },
309
+ children: [
310
+ /* @__PURE__ */ jsx6(Copy, { size: iconSize, color: variantColorMap[variant] }),
311
+ label || "Copy"
312
+ ]
313
+ }
314
+ )
315
+ }
316
+ );
317
+ };
318
+
319
+ // src/ui/Divider/Divider.tsx
320
+ import { jsx as jsx7, jsxs as jsxs3 } from "react/jsx-runtime";
321
+ var Divider = ({ children }) => {
322
+ return /* @__PURE__ */ jsxs3("div", { className: "divider", children: [
323
+ /* @__PURE__ */ jsx7("div", { className: "divider-line" }),
324
+ children && /* @__PURE__ */ jsx7("div", { className: "divider-text", children }),
325
+ /* @__PURE__ */ jsx7("div", { className: "divider-line" })
326
+ ] });
327
+ };
328
+
329
+ // src/ui/Modal/Modal.tsx
330
+ import { useRef as useRef3, useEffect as useEffect3, useState as useState4, useCallback, useMemo as useMemo2 } from "react";
331
+
332
+ // src/hooks/useFocusTrap.ts
333
+ import { useEffect } from "react";
334
+ var FOCUSABLE_SELECTOR = 'button:not([disabled]), [href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])';
335
+ function getDeepActiveElement() {
336
+ let active = document.activeElement;
337
+ while (active?.shadowRoot?.activeElement) {
338
+ active = active.shadowRoot.activeElement;
339
+ }
340
+ return active;
341
+ }
342
+ function useFocusTrap(containerRef, { isActive, onEscape, refocusKey }) {
343
+ useEffect(() => {
344
+ if (isActive && containerRef.current) {
345
+ const timer = setTimeout(() => {
346
+ containerRef.current?.focus();
347
+ }, 50);
348
+ return () => clearTimeout(timer);
349
+ }
350
+ }, [refocusKey, isActive]);
351
+ useEffect(() => {
352
+ if (!isActive) return;
353
+ const handleKeyDown = (e) => {
354
+ if (e.key === "Escape") {
355
+ onEscape?.();
356
+ return;
357
+ }
358
+ if (e.key !== "Tab" || !containerRef.current) return;
359
+ const focusableElements = containerRef.current.querySelectorAll(FOCUSABLE_SELECTOR);
360
+ if (focusableElements.length === 0) return;
361
+ const firstElement = focusableElements[0];
362
+ const lastElement = focusableElements[focusableElements.length - 1];
363
+ const activeElement = getDeepActiveElement();
364
+ if (e.shiftKey && activeElement === firstElement) {
365
+ e.preventDefault();
366
+ lastElement.focus();
367
+ } else if (!e.shiftKey && activeElement === lastElement) {
368
+ e.preventDefault();
369
+ firstElement.focus();
370
+ } else if (!Array.from(focusableElements).includes(activeElement)) {
371
+ e.preventDefault();
372
+ if (e.shiftKey) {
373
+ lastElement.focus();
374
+ } else {
375
+ firstElement.focus();
376
+ }
377
+ }
378
+ };
379
+ document.addEventListener("keydown", handleKeyDown);
380
+ return () => document.removeEventListener("keydown", handleKeyDown);
381
+ }, [isActive, onEscape]);
382
+ }
383
+
384
+ // src/components/PageTransitionContainer/PageTransitionContainer.tsx
385
+ import { useRef as useRef2 } from "react";
386
+
387
+ // src/hooks/usePageTransition.ts
388
+ import { useEffect as useEffect2, useRef, useState as useState3, useLayoutEffect, useMemo } from "react";
389
+
390
+ // src/constants/theme.ts
391
+ import {
392
+ BORDER_RADIUS_SCALES
393
+ } from "@aurum-sdk/types";
394
+ var DEFAULT_THEME = "dark";
395
+ var ANIMATION_DURATION = {
396
+ SHAKE: 300,
397
+ MODAL_HEIGHT_TRANSITION: 200
398
+ };
399
+ var DEFAULT_BORDER_RADIUS = "md";
400
+ var DEFAULT_MODAL_Z_INDEX = 1e3;
401
+ var DEFAULT_APP_NAME = "Aurum";
402
+ var DEFAULT_FONT = "'Inter', -apple-system, sans-serif";
403
+ var DEFAULT_WALLET_LAYOUT = "stacked";
404
+ var getBorderRadiusScale = (token) => {
405
+ return BORDER_RADIUS_SCALES[token];
406
+ };
407
+ var defaultLightThemeConfig = {
408
+ logo: "",
409
+ theme: "light",
410
+ primaryColor: "#000000",
411
+ borderRadius: DEFAULT_BORDER_RADIUS,
412
+ modalZIndex: DEFAULT_MODAL_Z_INDEX,
413
+ appName: DEFAULT_APP_NAME,
414
+ hideFooter: false,
415
+ font: DEFAULT_FONT,
416
+ walletLayout: DEFAULT_WALLET_LAYOUT
417
+ };
418
+ var defaultDarkThemeConfig = {
419
+ logo: "",
420
+ theme: "dark",
421
+ primaryColor: "#ffffff",
422
+ borderRadius: DEFAULT_BORDER_RADIUS,
423
+ modalZIndex: DEFAULT_MODAL_Z_INDEX,
424
+ appName: DEFAULT_APP_NAME,
425
+ hideFooter: false,
426
+ font: DEFAULT_FONT,
427
+ walletLayout: DEFAULT_WALLET_LAYOUT
428
+ };
429
+ var getDefaultThemeConfig = (theme) => {
430
+ return theme === "dark" ? defaultDarkThemeConfig : defaultLightThemeConfig;
431
+ };
432
+
433
+ // src/constants/layout.ts
434
+ var PAGE_CONTENT_PADDING = 0.25;
435
+ var PAGE_MIN_HEIGHT = "8rem";
436
+ var PAGE_MAX_HEIGHT = "600";
437
+ var HEADER_HEIGHT = "3.5rem";
438
+ var POWERED_BY_SPACER_REM = 2.5;
439
+ var contentWrapperStyle = { paddingTop: HEADER_HEIGHT };
440
+
441
+ // src/hooks/usePageTransition.ts
442
+ function useContentHeight(contentRef, transitionKey) {
443
+ const [contentHeight, setContentHeight] = useState3(null);
444
+ useLayoutEffect(() => {
445
+ if (contentRef.current) {
446
+ setContentHeight(contentRef.current.scrollHeight);
447
+ }
448
+ }, [transitionKey]);
449
+ useEffect2(() => {
450
+ if (!contentRef.current) return;
451
+ const resizeObserver = new ResizeObserver((entries) => {
452
+ for (const entry of entries) {
453
+ setContentHeight(entry.target.scrollHeight);
454
+ }
455
+ });
456
+ resizeObserver.observe(contentRef.current);
457
+ return () => resizeObserver.disconnect();
458
+ }, [transitionKey]);
459
+ return contentHeight;
460
+ }
461
+ function usePageActiveState(transitionKey) {
462
+ const prevKeyRef = useRef(transitionKey);
463
+ const [isPageActive, setIsPageActive] = useState3(true);
464
+ useEffect2(() => {
465
+ if (prevKeyRef.current === transitionKey) return;
466
+ prevKeyRef.current = transitionKey;
467
+ setIsPageActive(false);
468
+ requestAnimationFrame(() => {
469
+ requestAnimationFrame(() => setIsPageActive(true));
470
+ });
471
+ }, [transitionKey]);
472
+ return isPageActive;
473
+ }
474
+ function usePageContainerStyle(contentHeight) {
475
+ return useMemo(
476
+ () => ({
477
+ height: contentHeight ? `${contentHeight / 16 + PAGE_CONTENT_PADDING * 2}rem` : "auto",
478
+ minHeight: PAGE_MIN_HEIGHT,
479
+ maxHeight: PAGE_MAX_HEIGHT,
480
+ padding: `${PAGE_CONTENT_PADDING}rem`,
481
+ margin: `${-PAGE_CONTENT_PADDING}rem`,
482
+ width: `calc(100% + ${PAGE_CONTENT_PADDING * 2}rem)`,
483
+ boxSizing: "border-box",
484
+ transition: contentHeight ? `height ${ANIMATION_DURATION.MODAL_HEIGHT_TRANSITION}ms cubic-bezier(0.4, 0, 0.2, 1)` : "none"
485
+ }),
486
+ [contentHeight]
487
+ );
488
+ }
489
+
490
+ // src/components/PageTransitionContainer/PageTransitionContainer.tsx
491
+ import { jsx as jsx8 } from "react/jsx-runtime";
492
+ var PageTransitionContainer = ({ transitionKey, children }) => {
493
+ const pageRef = useRef2(null);
494
+ const contentRef = useRef2(null);
495
+ const contentHeight = useContentHeight(contentRef, transitionKey);
496
+ const isPageActive = usePageActiveState(transitionKey);
497
+ const containerStyle = usePageContainerStyle(contentHeight);
498
+ return /* @__PURE__ */ jsx8("div", { className: "modal-page-container", style: containerStyle, children: /* @__PURE__ */ jsx8("div", { ref: pageRef, className: `modal-page ${isPageActive ? "active" : ""}`, children: /* @__PURE__ */ jsx8("div", { ref: contentRef, style: contentWrapperStyle, children }) }, transitionKey) });
499
+ };
500
+
501
+ // src/components/PoweredBy/PoweredBy.tsx
502
+ import { AurumLogo } from "@aurum-sdk/logos/react";
503
+ import { jsx as jsx9, jsxs as jsxs4 } from "react/jsx-runtime";
504
+ var PoweredBy = () => {
505
+ const { brandConfig } = useWidgetContext();
506
+ return /* @__PURE__ */ jsx9("div", { className: "powered-by-container", children: /* @__PURE__ */ jsx9(Row, { align: "center", justify: "center", gap: 0, children: /* @__PURE__ */ jsxs4(
507
+ Button,
508
+ {
509
+ variant: "text",
510
+ size: "xs",
511
+ onClick: () => window.open("https://npmjs.com/package/@aurum-sdk/core", "_blank"),
512
+ style: { gap: "0.15rem" },
513
+ children: [
514
+ /* @__PURE__ */ jsx9(Text, { variant: "secondary", size: "xs", children: "Powered by" }),
515
+ /* @__PURE__ */ jsxs4(Row, { align: "center", justify: "center", gap: 0, children: [
516
+ /* @__PURE__ */ jsx9(
517
+ AurumLogo,
518
+ {
519
+ variant: "icon",
520
+ size: 22,
521
+ radius: brandConfig.borderRadius,
522
+ sizeSlot: "xs",
523
+ color: "var(--color-foreground-muted)",
524
+ title: "Aurum"
525
+ }
526
+ ),
527
+ /* @__PURE__ */ jsx9(Text, { variant: "secondary", weight: "bold", style: { fontSize: "13px" }, children: "Aurum" })
528
+ ] })
529
+ ]
530
+ }
531
+ ) }) });
532
+ };
533
+
534
+ // src/ui/Modal/Modal.tsx
535
+ import { Fragment, jsx as jsx10, jsxs as jsxs5 } from "react/jsx-runtime";
536
+ var Modal = ({
537
+ isOpen,
538
+ onCloseComplete,
539
+ children,
540
+ closeOnOverlayClick = true,
541
+ transitionKey = "default",
542
+ brandConfig
543
+ }) => {
544
+ const overlayRef = useRef3(null);
545
+ const dialogRef = useRef3(null);
546
+ const headerPortalRef = useRef3(null);
547
+ const [animState, setAnimState] = useState4("closed");
548
+ useEffect3(() => {
549
+ if (isOpen && animState === "closed") {
550
+ setAnimState("entering");
551
+ }
552
+ }, [isOpen, animState]);
553
+ useEffect3(() => {
554
+ if (animState !== "entering") return;
555
+ const rafId = requestAnimationFrame(() => {
556
+ setAnimState("open");
557
+ dialogRef.current?.focus();
558
+ });
559
+ return () => cancelAnimationFrame(rafId);
560
+ }, [animState]);
561
+ useEffect3(() => {
562
+ if (animState !== "exiting") return;
563
+ const dialog = dialogRef.current;
564
+ if (!dialog) return;
565
+ const handleTransitionEnd = (e) => {
566
+ if (e.target === dialog) {
567
+ setAnimState("closed");
568
+ onCloseComplete();
569
+ }
570
+ };
571
+ dialog.addEventListener("transitionend", handleTransitionEnd);
572
+ return () => dialog.removeEventListener("transitionend", handleTransitionEnd);
573
+ }, [animState, onCloseComplete]);
574
+ useEffect3(() => {
575
+ if (animState === "closed") return;
576
+ document.body.style.overflow = "hidden";
577
+ return () => {
578
+ document.body.style.overflow = "unset";
579
+ };
580
+ }, [animState]);
581
+ const handleClose = useCallback(() => {
582
+ if (animState === "open" || animState === "entering") {
583
+ setAnimState("exiting");
584
+ }
585
+ }, [animState]);
586
+ const handleOverlayClick = useCallback(
587
+ (e) => {
588
+ if (closeOnOverlayClick && e.target === overlayRef.current) {
589
+ handleClose();
590
+ }
591
+ },
592
+ [closeOnOverlayClick, handleClose]
593
+ );
594
+ const focusTrapOptions = useMemo2(
595
+ () => ({
596
+ isActive: animState !== "closed",
597
+ onEscape: handleClose,
598
+ refocusKey: transitionKey
599
+ }),
600
+ [animState, handleClose, transitionKey]
601
+ );
602
+ useFocusTrap(dialogRef, focusTrapOptions);
603
+ const overlayClassName = useMemo2(() => {
604
+ const classes = ["modal-overlay"];
605
+ if (animState === "open") classes.push("modal-open");
606
+ if (animState === "exiting") classes.push("modal-exiting");
607
+ return classes.join(" ");
608
+ }, [animState]);
609
+ if (animState === "closed") return null;
610
+ return /* @__PURE__ */ jsx10(WidgetProvider, { mode: "modal", brandConfig, onDismiss: handleClose, headerPortalRef, children: /* @__PURE__ */ jsx10("div", { ref: overlayRef, className: overlayClassName, onClick: handleOverlayClick, children: /* @__PURE__ */ jsxs5("div", { ref: dialogRef, className: "modal-content", role: "dialog", "aria-modal": "true", tabIndex: -1, children: [
611
+ /* @__PURE__ */ jsx10("div", { ref: headerPortalRef }),
612
+ /* @__PURE__ */ jsx10(PageTransitionContainer, { transitionKey, children }),
613
+ brandConfig.hideFooter ? /* @__PURE__ */ jsx10(Spacer, { size: "0.3125rem" }) : /* @__PURE__ */ jsxs5(Fragment, { children: [
614
+ /* @__PURE__ */ jsx10(Spacer, { size: `${POWERED_BY_SPACER_REM}rem` }),
615
+ /* @__PURE__ */ jsx10(PoweredBy, {})
616
+ ] })
617
+ ] }) }) });
618
+ };
619
+
620
+ // src/ui/Row/Row.tsx
621
+ import { jsx as jsx11 } from "react/jsx-runtime";
622
+ var Row = ({
623
+ align = "center",
624
+ justify = "center",
625
+ children,
626
+ gap = 8,
627
+ style,
628
+ ...props
629
+ }) => {
630
+ return /* @__PURE__ */ jsx11(
631
+ "div",
632
+ {
633
+ style: {
634
+ display: "flex",
635
+ flexDirection: "row",
636
+ alignItems: align,
637
+ justifyContent: justify,
638
+ gap: `${gap}px`,
639
+ ...style
640
+ },
641
+ ...props,
642
+ children
643
+ }
644
+ );
645
+ };
646
+
647
+ // src/ui/Spacer/Spacer.tsx
648
+ import { jsx as jsx12 } from "react/jsx-runtime";
649
+ var Spacer = ({ size = 16 }) => {
650
+ return /* @__PURE__ */ jsx12("div", { style: { height: size } });
651
+ };
652
+
653
+ // src/ui/Spinner/Spinner.tsx
654
+ import { Loader2 } from "lucide-react";
655
+ import { jsx as jsx13 } from "react/jsx-runtime";
656
+ var Spinner = ({
657
+ size = 16,
658
+ color = "var(--aurum-primary-color)",
659
+ strokeWidth = 2
660
+ }) => {
661
+ return /* @__PURE__ */ jsx13(
662
+ Loader2,
663
+ {
664
+ className: "spinner",
665
+ strokeWidth,
666
+ size,
667
+ style: {
668
+ width: `${size}px`,
669
+ height: `${size}px`,
670
+ color
671
+ }
672
+ }
673
+ );
674
+ };
675
+
676
+ // src/ui/Text/Text.tsx
677
+ import { jsx as jsx14 } from "react/jsx-runtime";
678
+ var Text = ({
679
+ variant = "primary",
680
+ as = "p",
681
+ size = "md",
682
+ weight = "normal",
683
+ align = "left",
684
+ children,
685
+ className,
686
+ style,
687
+ ...props
688
+ }) => {
689
+ const Element = as;
690
+ const baseClassName = "aurum-text";
691
+ const classes = [
692
+ baseClassName,
693
+ `${baseClassName}--${variant}`,
694
+ size && `${baseClassName}--${size}`,
695
+ weight && `${baseClassName}--${weight}`,
696
+ align && `${baseClassName}--align-${align}`,
697
+ className
698
+ ].filter(Boolean).join(" ");
699
+ return /* @__PURE__ */ jsx14(Element, { className: classes, ...props, style, children });
700
+ };
701
+
702
+ // src/ui/ThemeContainer.tsx
703
+ import { jsx as jsx15 } from "react/jsx-runtime";
704
+ var ThemeContainer = ({ children, theme = "light" }) => {
705
+ return /* @__PURE__ */ jsx15("div", { className: "aurum-sdk", "data-theme": theme, children });
706
+ };
707
+
708
+ // src/components/ConnectModal/SelectWallet.tsx
709
+ import { X } from "lucide-react";
710
+
711
+ // src/components/ModalHeader/ModalHeader.tsx
712
+ import { useLayoutEffect as useLayoutEffect2, useState as useState5 } from "react";
713
+ import { createPortal } from "react-dom";
714
+ import { jsx as jsx16, jsxs as jsxs6 } from "react/jsx-runtime";
715
+ var ModalHeader = ({ leftAction, rightAction, title }) => {
716
+ const { headerPortalRef, mode } = useWidgetContext();
717
+ const [portalTarget, setPortalTarget] = useState5(null);
718
+ useLayoutEffect2(() => {
719
+ if (headerPortalRef) {
720
+ setPortalTarget(headerPortalRef.current);
721
+ }
722
+ }, [headerPortalRef]);
723
+ const resolvedRightAction = mode === "widget" ? null : rightAction;
724
+ const headerContent = /* @__PURE__ */ jsxs6("header", { className: "modal-header", children: [
725
+ /* @__PURE__ */ jsx16("div", { className: "modal-header-left", children: leftAction }),
726
+ /* @__PURE__ */ jsx16("div", { className: "modal-header-center", children: typeof title === "string" ? /* @__PURE__ */ jsx16(Text, { align: "center", variant: "secondary", style: { fontSize: "15px" }, children: title }) : title }),
727
+ /* @__PURE__ */ jsx16("div", { className: "modal-header-right", children: resolvedRightAction })
728
+ ] });
729
+ if (!portalTarget) return null;
730
+ return createPortal(headerContent, portalTarget);
731
+ };
732
+
733
+ // src/components/ConnectModal/EmailAuth.tsx
734
+ import { useEffect as useEffect4, useState as useState7 } from "react";
735
+
736
+ // src/contexts/EmailAuthContext.tsx
737
+ import { createContext as createContext3, useContext as useContext3, useState as useState6 } from "react";
738
+
739
+ // src/services/sentry.ts
740
+ import * as Sentry from "@sentry/browser";
741
+ var initialized = false;
742
+ var telemetryEnabled = true;
743
+ function getEnvironment() {
744
+ if (typeof window !== "undefined") {
745
+ const hostname = window.location.hostname;
746
+ if (hostname === "localhost" || hostname === "127.0.0.1") {
747
+ return "development";
748
+ }
749
+ }
750
+ return "production";
751
+ }
752
+ function initSentry(enabled = true) {
753
+ telemetryEnabled = enabled;
754
+ if (initialized || !telemetryEnabled || true) return;
755
+ initialized = true;
756
+ Sentry.init({
757
+ dsn: "",
758
+ environment: getEnvironment(),
759
+ release: `@aurum-sdk/core@${"0.1.0"}`,
760
+ sendDefaultPii: false,
761
+ enableLogs: true
762
+ });
763
+ }
764
+ var sentryLogger = {
765
+ info: (message, attributes) => {
766
+ if (telemetryEnabled) Sentry.logger.info(message, attributes);
767
+ },
768
+ warn: (message, attributes) => {
769
+ if (telemetryEnabled) Sentry.logger.warn(message, attributes);
770
+ },
771
+ error: (message, attributes) => {
772
+ if (telemetryEnabled) Sentry.logger.error(message, attributes);
773
+ }
774
+ };
775
+
776
+ // src/utils/isConfigError.ts
777
+ var isConfigError = (error) => {
778
+ const name = error?.name;
779
+ return name === "ConfigError";
780
+ };
781
+ var createConfigError = (adapterName) => {
782
+ const error = new Error(`Missing required project ID for ${adapterName}`);
783
+ error.name = "ConfigError";
784
+ return error;
785
+ };
786
+
787
+ // src/contexts/EmailAuthContext.tsx
788
+ import { jsx as jsx17 } from "react/jsx-runtime";
789
+ var EmailAuthContext = createContext3(null);
790
+ var useEmailAuth = () => {
791
+ const context = useContext3(EmailAuthContext);
792
+ if (!context) {
793
+ throw new Error("useEmailAuth must be used within an EmailAuthProvider");
794
+ }
795
+ return context;
796
+ };
797
+ var EmailAuthProvider = ({
798
+ children,
799
+ displayedWallets,
800
+ onConnect,
801
+ navigateTo,
802
+ setSelectedWallet
803
+ }) => {
804
+ const initialAuthState = {
805
+ email: "",
806
+ authResult: null,
807
+ step: "email"
808
+ };
809
+ const [error, setError] = useState6("");
810
+ const [emailAuthState, setEmailAuthState] = useState6(initialAuthState);
811
+ const resetEmailAuth = () => {
812
+ setEmailAuthState(initialAuthState);
813
+ setError("");
814
+ };
815
+ const clearError = () => {
816
+ setError("");
817
+ };
818
+ const attemptEmailAuth = async (email, emailAdapter) => {
819
+ setError("");
820
+ if (!emailAdapter.emailAuthStart) {
821
+ sentryLogger.error("emailAuthStart not implemented");
822
+ throw new Error("emailAuthStart not implemented");
823
+ }
824
+ const authResult = await emailAdapter.emailAuthStart(email);
825
+ setEmailAuthState((prev) => ({ ...prev, authResult, step: "otp" }));
826
+ navigateTo(PAGE_IDS.EMAIL_VERIFY_OTP);
827
+ };
828
+ const handleAlreadyAuthenticatedError = async (email, emailAdapter) => {
829
+ try {
830
+ await emailAdapter.disconnect();
831
+ await attemptEmailAuth(email, emailAdapter);
832
+ } catch (retryError) {
833
+ sentryLogger.error("Failed to retry email OTP after disconnect:", { error: retryError });
834
+ setError("Failed to send email verification");
835
+ setEmailAuthState((prev) => ({ ...prev, step: "email" }));
836
+ }
837
+ };
838
+ const sendEmailOTP = async (email) => {
839
+ const emailAdapter = displayedWallets.find((adapter) => adapter.id === "email");
840
+ if (!emailAdapter) {
841
+ sentryLogger.error("sendEmailOTP: Email adapter not found");
842
+ throw new Error("Email adapter not found");
843
+ }
844
+ setEmailAuthState((prev) => ({ ...prev, email }));
845
+ try {
846
+ await attemptEmailAuth(email, emailAdapter);
847
+ } catch (error2) {
848
+ setEmailAuthState((prev) => ({ ...prev, step: "email" }));
849
+ const errorMessage = error2.message?.toLowerCase() ?? "";
850
+ const isAlreadyAuthenticated = errorMessage.includes("user is already authenticated");
851
+ if (isConfigError(error2)) {
852
+ navigateTo(PAGE_IDS.CONFIG_ERROR);
853
+ } else if (isAlreadyAuthenticated) {
854
+ try {
855
+ await handleAlreadyAuthenticatedError(email, emailAdapter);
856
+ } catch {
857
+ setError("Failed to send email verification");
858
+ }
859
+ } else {
860
+ setError("Failed to send email verification");
861
+ }
862
+ }
863
+ };
864
+ const verifyEmailOTPAndConnect = async (otp) => {
865
+ try {
866
+ if (!emailAuthState.authResult) {
867
+ sentryLogger.error("No auth result found");
868
+ throw new Error("No auth result found");
869
+ }
870
+ const emailAdapter = displayedWallets.find((adapter) => adapter.id === "email");
871
+ if (!emailAdapter) {
872
+ sentryLogger.error("verifyEmailOTPAndConnect: Email adapter not found");
873
+ throw new Error("Email adapter not found");
874
+ }
875
+ setEmailAuthState((prev) => ({ ...prev, step: "connecting" }));
876
+ if (!emailAdapter.emailAuthVerify) {
877
+ sentryLogger.error("emailAuthVerify not implemented");
878
+ throw new Error("emailAuthVerify not implemented");
879
+ }
880
+ const verifyResult = await emailAdapter.emailAuthVerify(emailAuthState.authResult.flowId, otp);
881
+ setSelectedWallet(emailAdapter);
882
+ setEmailAuthState((prev) => ({ ...prev, step: "success" }));
883
+ setTimeout(() => {
884
+ onConnect({
885
+ walletId: emailAdapter.id,
886
+ address: verifyResult.user?.evmAccounts?.[0] ?? "",
887
+ provider: emailAdapter.getProvider(),
888
+ email: emailAuthState.email
889
+ });
890
+ }, 1500);
891
+ } catch {
892
+ setError("Invalid or expired code");
893
+ setEmailAuthState((prev) => ({ ...prev, step: "otp" }));
894
+ }
895
+ };
896
+ const contextValue = {
897
+ error,
898
+ emailAuthState,
899
+ clearError,
900
+ sendEmailOTP,
901
+ resetEmailAuth,
902
+ verifyEmailOTPAndConnect
903
+ };
904
+ return /* @__PURE__ */ jsx17(EmailAuthContext.Provider, { value: contextValue, children });
905
+ };
906
+
907
+ // src/components/ConnectModal/EmailAuth.tsx
908
+ import { ChevronRight, Mail } from "lucide-react";
909
+ import { Fragment as Fragment2, jsx as jsx18, jsxs as jsxs7 } from "react/jsx-runtime";
910
+ var EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
911
+ var EmailAuth = () => {
912
+ const { emailAuthState, error, sendEmailOTP, clearError } = useEmailAuth();
913
+ const [email, setEmail] = useState7(emailAuthState.email);
914
+ const [isValidEmail, setIsValidEmail] = useState7(false);
915
+ const [isLoading, setIsLoading] = useState7(false);
916
+ const [isFocused, setIsFocused] = useState7(false);
917
+ const [isButtonFocused, setIsButtonFocused] = useState7(false);
918
+ const showPrimary = isValidEmail && (isFocused || isButtonFocused);
919
+ useEffect4(() => {
920
+ setIsValidEmail(EMAIL_REGEX.test(email));
921
+ }, [email]);
922
+ const handleSend = async () => {
923
+ try {
924
+ setIsLoading(true);
925
+ await sendEmailOTP(email);
926
+ } finally {
927
+ setIsLoading(false);
928
+ }
929
+ };
930
+ const handleKeyDown = (e) => {
931
+ if (error) {
932
+ clearError();
933
+ }
934
+ if (e.key === "Enter" && isValidEmail) {
935
+ handleSend();
936
+ }
937
+ };
938
+ const getInputClassName = () => {
939
+ const classes = ["email-auth-input"];
940
+ if (error) classes.push("email-auth-input--error");
941
+ return classes.join(" ");
942
+ };
943
+ return /* @__PURE__ */ jsxs7(Fragment2, { children: [
944
+ /* @__PURE__ */ jsxs7("div", { style: { position: "relative", width: "100%" }, children: [
945
+ /* @__PURE__ */ jsx18("div", { className: "email-auth-icon", children: /* @__PURE__ */ jsx18(Mail, { size: 20, color: "var(--color-foreground-muted)" }) }),
946
+ /* @__PURE__ */ jsx18(
947
+ "input",
948
+ {
949
+ "aria-label": "Email address",
950
+ id: "email-input",
951
+ name: "email",
952
+ type: "email",
953
+ autoComplete: "email",
954
+ inputMode: "email",
955
+ value: email,
956
+ className: getInputClassName(),
957
+ disabled: isLoading,
958
+ onBlur: () => setIsFocused(false),
959
+ onKeyDown: handleKeyDown,
960
+ onFocus: () => setIsFocused(true),
961
+ placeholder: "Email address",
962
+ onChange: (e) => setEmail(e.target.value)
963
+ }
964
+ ),
965
+ /* @__PURE__ */ jsx18(
966
+ Button,
967
+ {
968
+ size: "sm",
969
+ variant: showPrimary ? "primary" : "secondary",
970
+ loading: isLoading,
971
+ onClick: handleSend,
972
+ disabled: !isValidEmail,
973
+ className: "email-auth-submit-button",
974
+ onFocus: () => setIsButtonFocused(true),
975
+ onBlur: () => setIsButtonFocused(false),
976
+ children: !isLoading && /* @__PURE__ */ jsx18(
977
+ ChevronRight,
978
+ {
979
+ size: 16,
980
+ color: showPrimary ? "var(--color-primary-foreground)" : "var(--color-foreground-subtle)"
981
+ }
982
+ )
983
+ }
984
+ )
985
+ ] }),
986
+ error && /* @__PURE__ */ jsx18(Text, { variant: "error", size: "sm", align: "left", style: { width: "100%", marginTop: "0.3125rem" }, children: error })
987
+ ] });
988
+ };
989
+
990
+ // src/components/WalletLogoWrapper/WalletLogoWrapper.tsx
991
+ import { WalletLogo as BaseLogo } from "@aurum-sdk/logos/react";
992
+ import { jsx as jsx19 } from "react/jsx-runtime";
993
+ var WalletLogoWrapper = ({ radius, variant = "brand", ...props }) => {
994
+ const { brandConfig } = useWidgetContext();
995
+ return /* @__PURE__ */ jsx19(BaseLogo, { radius: radius ?? brandConfig.borderRadius, variant, ...props });
996
+ };
997
+
998
+ // src/components/WalletButton/GridWalletButton.tsx
999
+ import { jsx as jsx20 } from "react/jsx-runtime";
1000
+ var GridWalletButton = ({
1001
+ wallet,
1002
+ connectWallet
1003
+ }) => {
1004
+ return /* @__PURE__ */ jsx20(
1005
+ Button,
1006
+ {
1007
+ variant: "secondary",
1008
+ onClick: () => connectWallet(wallet),
1009
+ "aria-label": `Connect with ${wallet.name}`,
1010
+ title: wallet.name,
1011
+ children: /* @__PURE__ */ jsx20(WalletLogoWrapper, { id: wallet.id, size: 44, variant: "icon" })
1012
+ }
1013
+ );
1014
+ };
1015
+
1016
+ // src/components/ConnectModal/WalletListGrid.tsx
1017
+ import { jsx as jsx21 } from "react/jsx-runtime";
1018
+ var getGridColumns = (walletCount) => {
1019
+ if (walletCount <= 2) return 2;
1020
+ if (walletCount === 3) return 3;
1021
+ if (walletCount === 5) return 3;
1022
+ if (walletCount === 6) return 3;
1023
+ return 4;
1024
+ };
1025
+ var WalletListGrid = ({ wallets }) => {
1026
+ const { connectWallet } = useConnectModal();
1027
+ const columns = getGridColumns(wallets.length);
1028
+ return /* @__PURE__ */ jsx21("div", { className: "aurum-wallet-grid", style: { "--grid-columns": columns }, children: wallets.map((wallet) => /* @__PURE__ */ jsx21(GridWalletButton, { wallet, connectWallet }, wallet.id)) });
1029
+ };
1030
+
1031
+ // src/components/ConnectModal/WalletListStacked.tsx
1032
+ import { ChevronRight as ChevronRight3 } from "lucide-react";
1033
+
1034
+ // src/components/WalletButton/WalletButton.tsx
1035
+ import { QrCode } from "lucide-react";
1036
+
1037
+ // src/components/WalletButton/WalletButtonLabel.tsx
1038
+ import { ChevronRight as ChevronRight2 } from "lucide-react";
1039
+ import { jsx as jsx22 } from "react/jsx-runtime";
1040
+ var WalletButtonLabel = ({ type }) => {
1041
+ if (!type) return /* @__PURE__ */ jsx22(ChevronRight2, { size: 18, color: "var(--color-foreground-subtle)" });
1042
+ return /* @__PURE__ */ jsx22(RecentBadge, {});
1043
+ };
1044
+
1045
+ // src/components/WalletButton/WalletButton.tsx
1046
+ import { WalletId as WalletId2 } from "@aurum-sdk/types";
1047
+ import { jsx as jsx23, jsxs as jsxs8 } from "react/jsx-runtime";
1048
+ var WalletButton = ({
1049
+ wallet,
1050
+ connectWallet,
1051
+ isLastUsed = false,
1052
+ iconSize = 32
1053
+ }) => {
1054
+ const label = isLastUsed ? "Recent" : void 0;
1055
+ return /* @__PURE__ */ jsx23(
1056
+ Button,
1057
+ {
1058
+ variant: "secondary",
1059
+ onClick: () => connectWallet(wallet),
1060
+ expand: true,
1061
+ style: { borderRadius: "var(--aurum-border-radius-md)" },
1062
+ children: /* @__PURE__ */ jsxs8(Row, { justify: "space-between", align: "center", style: { width: "100%" }, children: [
1063
+ /* @__PURE__ */ jsxs8(Row, { align: "center", gap: 10, children: [
1064
+ /* @__PURE__ */ jsx23(WalletLogoWrapper, { id: wallet.id, size: iconSize, sizeSlot: "sm" }),
1065
+ /* @__PURE__ */ jsx23(Text, { weight: "semibold", size: "md", children: wallet.name })
1066
+ ] }),
1067
+ wallet.id === WalletId2.WalletConnect && !isLastUsed ? /* @__PURE__ */ jsx23(QrCode, { color: "var(--color-foreground)", size: 18 }) : /* @__PURE__ */ jsx23(WalletButtonLabel, { type: label })
1068
+ ] })
1069
+ },
1070
+ wallet.id
1071
+ );
1072
+ };
1073
+
1074
+ // src/components/ConnectModal/AdditionalWalletsIcon.tsx
1075
+ import { jsx as jsx24, jsxs as jsxs9 } from "react/jsx-runtime";
1076
+ var AdditionalWalletsIcon = ({ additionalWallets, size = 32 }) => {
1077
+ const walletCount = additionalWallets.length;
1078
+ if (walletCount === 1) {
1079
+ const iconSize2 = Math.floor(size * 0.7);
1080
+ return /* @__PURE__ */ jsx24("div", { className: "additional-wallets-container", style: { width: size, height: size }, children: /* @__PURE__ */ jsx24(
1081
+ WalletLogoWrapper,
1082
+ {
1083
+ id: additionalWallets[0].id,
1084
+ size: iconSize2,
1085
+ sizeSlot: "xs",
1086
+ title: additionalWallets[0].name
1087
+ }
1088
+ ) });
1089
+ }
1090
+ if (walletCount === 2) {
1091
+ const iconSize2 = Math.floor(size * 0.55);
1092
+ return /* @__PURE__ */ jsx24("div", { className: "additional-wallets-container", style: { width: size, height: size }, children: /* @__PURE__ */ jsxs9(Row, { align: "center", gap: 0, children: [
1093
+ /* @__PURE__ */ jsx24(
1094
+ "div",
1095
+ {
1096
+ className: "circular-icon-wrapper circular-icon-wrapper--front",
1097
+ style: { width: iconSize2, height: iconSize2 },
1098
+ children: /* @__PURE__ */ jsx24(
1099
+ WalletLogoWrapper,
1100
+ {
1101
+ id: additionalWallets[0].id,
1102
+ size: iconSize2,
1103
+ sizeSlot: "xs",
1104
+ title: additionalWallets[0].name
1105
+ }
1106
+ )
1107
+ }
1108
+ ),
1109
+ /* @__PURE__ */ jsx24(
1110
+ "div",
1111
+ {
1112
+ className: "circular-icon-wrapper circular-icon-wrapper--back",
1113
+ style: { width: iconSize2, height: iconSize2 },
1114
+ children: /* @__PURE__ */ jsx24(
1115
+ WalletLogoWrapper,
1116
+ {
1117
+ id: additionalWallets[1].id,
1118
+ size: iconSize2,
1119
+ sizeSlot: "xs",
1120
+ title: additionalWallets[1].name
1121
+ }
1122
+ )
1123
+ }
1124
+ )
1125
+ ] }) });
1126
+ }
1127
+ const walletsToShow = additionalWallets.slice(0, 4);
1128
+ const iconSize = Math.floor(size * 0.4);
1129
+ return /* @__PURE__ */ jsxs9("div", { className: "additional-wallets-grid", style: { width: size, height: size }, children: [
1130
+ walletsToShow.map((wallet) => /* @__PURE__ */ jsx24("div", { className: "additional-wallets-grid-item", style: { width: iconSize, height: iconSize }, children: /* @__PURE__ */ jsx24(WalletLogoWrapper, { id: wallet.id, size: iconSize, sizeSlot: "xs", title: wallet.name }) }, wallet.id)),
1131
+ walletsToShow.length === 3 && /* @__PURE__ */ jsx24("div", { className: "additional-wallets-placeholder", style: { width: iconSize, height: iconSize } })
1132
+ ] });
1133
+ };
1134
+
1135
+ // src/components/ConnectModal/WalletListStacked.tsx
1136
+ import { jsx as jsx25, jsxs as jsxs10 } from "react/jsx-runtime";
1137
+ var WalletListStacked = ({ wallets, hasEmailAuth }) => {
1138
+ const { navigateTo } = useNavigation();
1139
+ const { connectWallet } = useConnectModal();
1140
+ const lastUsedWalletId = useAurumStore((state) => state.lastUsedWalletId);
1141
+ const showAllButton = hasEmailAuth ? wallets.length > 4 : wallets.length > 5;
1142
+ const walletsToShow = showAllButton ? wallets.slice(0, 3) : wallets;
1143
+ const additionalWallets = showAllButton ? wallets.slice(3) : [];
1144
+ const goToAllWallets = () => {
1145
+ navigateTo(PAGE_IDS.ALL_WALLETS);
1146
+ };
1147
+ return /* @__PURE__ */ jsxs10(Column, { children: [
1148
+ walletsToShow.map((wallet) => /* @__PURE__ */ jsx25(
1149
+ WalletButton,
1150
+ {
1151
+ wallet,
1152
+ connectWallet,
1153
+ isLastUsed: wallet.id === lastUsedWalletId
1154
+ },
1155
+ wallet.id
1156
+ )),
1157
+ showAllButton && /* @__PURE__ */ jsx25(Button, { variant: "secondary", onClick: goToAllWallets, expand: true, children: /* @__PURE__ */ jsxs10(Row, { justify: "space-between", align: "center", style: { width: "100%" }, children: [
1158
+ /* @__PURE__ */ jsxs10(Row, { align: "center", gap: 10, children: [
1159
+ /* @__PURE__ */ jsx25(AdditionalWalletsIcon, { additionalWallets, size: 32 }),
1160
+ /* @__PURE__ */ jsx25(Text, { weight: "semibold", size: "md", children: "All Wallets" })
1161
+ ] }),
1162
+ /* @__PURE__ */ jsx25(ChevronRight3, { size: 18, color: "var(--color-foreground-subtle)" })
1163
+ ] }) })
1164
+ ] });
1165
+ };
1166
+
1167
+ // src/components/ConnectModal/SelectWallet.tsx
1168
+ import { WalletId as WalletId3 } from "@aurum-sdk/types";
1169
+ import { Fragment as Fragment3, jsx as jsx26, jsxs as jsxs11 } from "react/jsx-runtime";
1170
+ var SelectWalletPage = () => {
1171
+ const { displayedWallets } = useConnectModal();
1172
+ const { onDismiss, brandConfig } = useWidgetContext();
1173
+ const hasEmailAuth = displayedWallets.some((wallet) => wallet.id === WalletId3.Email);
1174
+ const sortedWallets = useMemo3(() => sortWallets(displayedWallets), [displayedWallets]);
1175
+ const isGridLayout = brandConfig.walletLayout === "grid";
1176
+ return /* @__PURE__ */ jsxs11(Fragment3, { children: [
1177
+ /* @__PURE__ */ jsx26(
1178
+ ModalHeader,
1179
+ {
1180
+ title: "Log in or sign up",
1181
+ rightAction: /* @__PURE__ */ jsx26(Button, { size: "sm", variant: "close", onClick: onDismiss, "aria-label": "Close", children: /* @__PURE__ */ jsx26(X, { size: 20, color: "var(--color-foreground-muted)" }) })
1182
+ }
1183
+ ),
1184
+ hasEmailAuth && /* @__PURE__ */ jsxs11(Fragment3, { children: [
1185
+ /* @__PURE__ */ jsx26(Column, { align: "center", gap: 0, children: /* @__PURE__ */ jsx26(EmailAuth, {}) }),
1186
+ sortedWallets.length > 0 && /* @__PURE__ */ jsxs11(Fragment3, { children: [
1187
+ /* @__PURE__ */ jsx26(Spacer, { size: 20 }),
1188
+ /* @__PURE__ */ jsx26(Divider, { children: "or continue with" }),
1189
+ /* @__PURE__ */ jsx26(Spacer, { size: 20 })
1190
+ ] })
1191
+ ] }),
1192
+ isGridLayout ? /* @__PURE__ */ jsx26(WalletListGrid, { wallets: sortedWallets }) : /* @__PURE__ */ jsx26(WalletListStacked, { wallets: sortedWallets, hasEmailAuth })
1193
+ ] });
1194
+ };
1195
+
1196
+ // src/components/ConnectModal/ConnectionStatus/ConnectionStatusBase.tsx
1197
+ import { useEffect as useEffect5, useState as useState8 } from "react";
1198
+ import { X as X3, ChevronLeft, CircleCheck } from "lucide-react";
1199
+
1200
+ // src/components/ConnectModal/ConnectionStatus/ConnectionIconsRow.tsx
1201
+ import { AurumLogo as AurumLogo2 } from "@aurum-sdk/logos/react";
1202
+ import { RotateCcw } from "lucide-react";
1203
+
1204
+ // src/components/ConnectModal/BrandLogo.tsx
1205
+ import { getLogoRadius } from "@aurum-sdk/logos/react";
1206
+ import { jsx as jsx27 } from "react/jsx-runtime";
1207
+ var BrandLogo = ({ size = 70, sizeSlot = "sm" }) => {
1208
+ const { brandConfig } = useWidgetContext();
1209
+ return brandConfig.logo ? /* @__PURE__ */ jsx27(
1210
+ "img",
1211
+ {
1212
+ src: brandConfig.logo,
1213
+ alt: `${brandConfig.appName} logo`,
1214
+ style: {
1215
+ width: size,
1216
+ height: size,
1217
+ objectFit: "cover",
1218
+ borderRadius: getLogoRadius(brandConfig.borderRadius, sizeSlot)
1219
+ }
1220
+ }
1221
+ ) : null;
1222
+ };
1223
+
1224
+ // src/components/ConnectModal/ConnectionStatus/StatusIcons.tsx
1225
+ import { X as X2 } from "lucide-react";
1226
+ import { jsx as jsx28, jsxs as jsxs12 } from "react/jsx-runtime";
1227
+ var ELLIPSES_COUNT = 3;
1228
+ var StatusIcons = ({ success, error }) => {
1229
+ const getStatusKey = () => {
1230
+ if (success) return "success";
1231
+ if (error) return "error";
1232
+ return "connecting";
1233
+ };
1234
+ if (success) {
1235
+ return /* @__PURE__ */ jsx28(
1236
+ Row,
1237
+ {
1238
+ align: "center",
1239
+ justify: "center",
1240
+ gap: 0,
1241
+ style: { padding: "0 0.5rem", minHeight: "3rem" },
1242
+ children: /* @__PURE__ */ jsx28("div", { className: "ellipses-success", children: Array.from({ length: ELLIPSES_COUNT }, (_, i) => /* @__PURE__ */ jsx28("span", { children: "\xB7" }, i)) })
1243
+ },
1244
+ getStatusKey()
1245
+ );
1246
+ }
1247
+ if (error) {
1248
+ const dotsBeforeIcon = Math.floor(ELLIPSES_COUNT / 2);
1249
+ const dotsAfterIcon = ELLIPSES_COUNT - dotsBeforeIcon - 1;
1250
+ return /* @__PURE__ */ jsx28(
1251
+ Row,
1252
+ {
1253
+ align: "center",
1254
+ justify: "center",
1255
+ gap: 0,
1256
+ style: { padding: "0 0.5rem", minHeight: "3rem" },
1257
+ children: /* @__PURE__ */ jsxs12("div", { className: "status-icon-with-dots error", children: [
1258
+ Array.from({ length: dotsBeforeIcon }, (_, i) => /* @__PURE__ */ jsx28("span", { className: "dot", children: "\xB7" }, `before-${i}`)),
1259
+ /* @__PURE__ */ jsx28("div", { className: "icon-center", children: /* @__PURE__ */ jsx28(X2, { size: 24, color: "var(--color-error)" }) }),
1260
+ Array.from({ length: dotsAfterIcon }, (_, i) => /* @__PURE__ */ jsx28("span", { className: "dot", children: "\xB7" }, `after-${i}`))
1261
+ ] })
1262
+ },
1263
+ getStatusKey()
1264
+ );
1265
+ }
1266
+ return /* @__PURE__ */ jsx28(
1267
+ Row,
1268
+ {
1269
+ align: "center",
1270
+ justify: "center",
1271
+ gap: 0,
1272
+ style: { padding: "0 0.5rem", minHeight: "3rem" },
1273
+ children: /* @__PURE__ */ jsx28("div", { className: "ellipses-loading", children: Array.from({ length: ELLIPSES_COUNT }, (_, i) => /* @__PURE__ */ jsx28("span", { children: "\xB7" }, i)) })
1274
+ },
1275
+ getStatusKey()
1276
+ );
1277
+ };
1278
+
1279
+ // src/components/ConnectModal/ConnectionStatus/ConnectionIconsRow.tsx
1280
+ import { jsx as jsx29, jsxs as jsxs13 } from "react/jsx-runtime";
1281
+ var ConnectionIconsRow = ({
1282
+ brandConfig,
1283
+ walletId,
1284
+ walletName,
1285
+ success,
1286
+ error,
1287
+ shouldShake,
1288
+ onRetry
1289
+ }) => {
1290
+ return /* @__PURE__ */ jsx29("div", { className: `connection-icons-row ${shouldShake ? "wallet-icon-shake" : ""}`, children: /* @__PURE__ */ jsxs13(Row, { gap: 4, children: [
1291
+ /* @__PURE__ */ jsx29("div", { className: "brand-logo-container", children: brandConfig.logo ? /* @__PURE__ */ jsx29(BrandLogo, { size: 54, sizeSlot: "md" }) : /* @__PURE__ */ jsx29(AurumLogo2, { variant: "black", size: 53, radius: brandConfig.borderRadius, sizeSlot: "md", title: "Aurum" }) }),
1292
+ /* @__PURE__ */ jsx29(StatusIcons, { success, error }),
1293
+ /* @__PURE__ */ jsxs13("div", { className: "wallet-logo-with-retry", children: [
1294
+ /* @__PURE__ */ jsx29(WalletLogoWrapper, { id: walletId, size: 54, sizeSlot: "md", title: walletName }),
1295
+ error && /* @__PURE__ */ jsx29(Button, { variant: "secondary", className: "retry-icon-overlay", onClick: onRetry, "aria-label": "Retry connection", children: /* @__PURE__ */ jsx29(RotateCcw, { size: 18 }) })
1296
+ ] })
1297
+ ] }) });
1298
+ };
1299
+
1300
+ // src/components/ConnectModal/ConnectionStatus/ConnectionStatusBase.tsx
1301
+ import { Fragment as Fragment4, jsx as jsx30, jsxs as jsxs14 } from "react/jsx-runtime";
1302
+ var ConnectionStatusBase = ({
1303
+ title,
1304
+ pendingHeaderText,
1305
+ pendingSubContent,
1306
+ extraContent
1307
+ }) => {
1308
+ const { selectedWallet, error, success, goBackToHome, retryConnection } = useConnectModal();
1309
+ const { onDismiss, brandConfig } = useWidgetContext();
1310
+ const [shouldShake, setShouldShake] = useState8(false);
1311
+ useEffect5(() => {
1312
+ if (error) {
1313
+ setShouldShake(true);
1314
+ const timer = setTimeout(() => {
1315
+ setShouldShake(false);
1316
+ }, ANIMATION_DURATION.SHAKE);
1317
+ return () => clearTimeout(timer);
1318
+ }
1319
+ }, [error]);
1320
+ if (!selectedWallet) {
1321
+ return null;
1322
+ }
1323
+ const getHeaderVariant = () => {
1324
+ if (success) return "success";
1325
+ if (error) return "error";
1326
+ return "primary";
1327
+ };
1328
+ const getHeaderText = () => {
1329
+ if (success) return "";
1330
+ if (error) return "Request Rejected";
1331
+ return pendingHeaderText;
1332
+ };
1333
+ const renderSubContent = () => {
1334
+ if (success) {
1335
+ return /* @__PURE__ */ jsx30("div", { className: "success-icon-large", children: /* @__PURE__ */ jsx30(CircleCheck, { color: "var(--aurum-primary-color)", size: 46 }) });
1336
+ }
1337
+ if (error) {
1338
+ return /* @__PURE__ */ jsxs14(Text, { align: "center", size: "sm", variant: "secondary", children: [
1339
+ "Please try again or select a ",
1340
+ "\n",
1341
+ "different wallet"
1342
+ ] });
1343
+ }
1344
+ return pendingSubContent;
1345
+ };
1346
+ return /* @__PURE__ */ jsxs14(Fragment4, { children: [
1347
+ /* @__PURE__ */ jsx30(
1348
+ ModalHeader,
1349
+ {
1350
+ leftAction: success ? null : /* @__PURE__ */ jsx30(Button, { size: "sm", variant: "close", onClick: goBackToHome, "aria-label": "Go back", children: /* @__PURE__ */ jsx30(ChevronLeft, { size: 20, color: "var(--color-foreground-muted)" }) }),
1351
+ rightAction: success ? null : /* @__PURE__ */ jsx30(Button, { size: "sm", variant: "close", onClick: onDismiss, "aria-label": "Close", children: /* @__PURE__ */ jsx30(X3, { size: 20, color: "var(--color-foreground-muted)" }) }),
1352
+ title: title || selectedWallet.name
1353
+ }
1354
+ ),
1355
+ /* @__PURE__ */ jsx30(Spacer, { size: 12 }),
1356
+ /* @__PURE__ */ jsxs14(Column, { align: "center", style: { maxWidth: "15.625rem", margin: "0 auto" }, gap: 8, children: [
1357
+ /* @__PURE__ */ jsx30(
1358
+ ConnectionIconsRow,
1359
+ {
1360
+ brandConfig,
1361
+ walletId: selectedWallet.id,
1362
+ walletName: selectedWallet.name,
1363
+ success,
1364
+ error,
1365
+ shouldShake,
1366
+ onRetry: retryConnection
1367
+ }
1368
+ ),
1369
+ /* @__PURE__ */ jsx30(Spacer, { size: 12 }),
1370
+ /* @__PURE__ */ jsx30(Column, { align: "center", justify: "start", gap: 0, style: { minHeight: "5rem", width: "100%" }, children: /* @__PURE__ */ jsxs14(Column, { gap: 8, style: { width: "100%" }, align: "center", children: [
1371
+ /* @__PURE__ */ jsx30(Row, { align: "center", justify: "center", gap: 0, style: { width: "100%" }, children: /* @__PURE__ */ jsx30(Text, { size: "lg", variant: getHeaderVariant(), weight: "bold", align: "center", children: getHeaderText() }) }),
1372
+ /* @__PURE__ */ jsx30(Row, { align: "center", justify: "center", gap: 0, style: { width: "100%", whiteSpace: "pre-line" }, children: renderSubContent() }),
1373
+ extraContent
1374
+ ] }) })
1375
+ ] }),
1376
+ /* @__PURE__ */ jsx30(Spacer, { size: 12 })
1377
+ ] });
1378
+ };
1379
+
1380
+ // src/components/ConnectModal/ConnectionStatus/Desktop.tsx
1381
+ import { WalletId as WalletId4 } from "@aurum-sdk/types";
1382
+ import { jsx as jsx31 } from "react/jsx-runtime";
1383
+ var ConnectionStatusPage = () => {
1384
+ const { selectedWallet } = useConnectModal();
1385
+ return /* @__PURE__ */ jsx31(
1386
+ ConnectionStatusBase,
1387
+ {
1388
+ pendingHeaderText: `Approve in ${selectedWallet?.name}`,
1389
+ pendingSubContent: /* @__PURE__ */ jsx31(Text, { align: "center", size: "sm", variant: "secondary", children: selectedWallet?.id === WalletId4.Ledger ? `Please wait for the Ledger Live modal to open` : `Please check your wallet to
1390
+ approve the connection` })
1391
+ }
1392
+ );
1393
+ };
1394
+
1395
+ // src/components/ConnectModal/ConnectionStatus/Mobile.tsx
1396
+ import { useState as useState9, useEffect as useEffect6 } from "react";
1397
+ import { jsx as jsx32, jsxs as jsxs15 } from "react/jsx-runtime";
1398
+ var ConnectionStatusMobilePage = () => {
1399
+ const { selectedWallet, error, success, retryConnection } = useConnectModal();
1400
+ const [showLaunchButton, setShowLaunchButton] = useState9(false);
1401
+ useEffect6(() => {
1402
+ const timer = setTimeout(() => setShowLaunchButton(true), 5e3);
1403
+ return () => clearTimeout(timer);
1404
+ }, []);
1405
+ return /* @__PURE__ */ jsx32(
1406
+ ConnectionStatusBase,
1407
+ {
1408
+ title: selectedWallet?.name,
1409
+ pendingHeaderText: `Opening ${selectedWallet?.name}`,
1410
+ pendingSubContent: /* @__PURE__ */ jsxs15(Text, { size: "sm", variant: "secondary", align: "center", style: { maxWidth: "18.75rem" }, children: [
1411
+ "If ",
1412
+ selectedWallet?.name,
1413
+ " doesn't open automatically, click the button below"
1414
+ ] }),
1415
+ extraContent: showLaunchButton && !success && !error ? /* @__PURE__ */ jsx32(Button, { variant: "tertiary", size: "md", onClick: retryConnection, style: { width: "100%", marginTop: "0.5rem" }, children: "Launch App" }) : void 0
1416
+ }
1417
+ );
1418
+ };
1419
+
1420
+ // src/components/ConnectModal/QRCodePage.tsx
1421
+ import { useEffect as useEffect8, useState as useState10, useRef as useRef5 } from "react";
1422
+
1423
+ // src/components/QRCodeDisplay/QRCodeDisplay.tsx
1424
+ import { useRef as useRef4, useEffect as useEffect7 } from "react";
1425
+ import { QRCode } from "react-qrcode-logo";
1426
+
1427
+ // src/utils/generateQrCodeWalletLogo.tsx
1428
+ import { getLogoDataUri } from "@aurum-sdk/logos";
1429
+ import { WalletId as WalletId5 } from "@aurum-sdk/types";
1430
+ var generateQrCodeWalletLogo = (walletAdapter) => {
1431
+ if (walletAdapter && walletAdapter.id !== WalletId5.AppKit && walletAdapter.icon) {
1432
+ return walletAdapter.icon;
1433
+ }
1434
+ return getLogoDataUri(WalletId5.WalletConnect) ?? "";
1435
+ };
1436
+
1437
+ // src/components/QRCodeDisplay/QREye.tsx
1438
+ import { jsx as jsx33, jsxs as jsxs16 } from "react/jsx-runtime";
1439
+ var QREye = ({ x, y, eyeSize, eyeRadius, dotSize, fillColor, bgColor }) => {
1440
+ const padding = dotSize * 0.8;
1441
+ const centerRadius = (eyeSize - 4 * padding) / 2 * 1.1;
1442
+ return /* @__PURE__ */ jsxs16("g", { children: [
1443
+ /* @__PURE__ */ jsx33(
1444
+ "rect",
1445
+ {
1446
+ x,
1447
+ y,
1448
+ width: eyeSize,
1449
+ height: eyeSize,
1450
+ fill: fillColor,
1451
+ rx: eyeRadius,
1452
+ ry: eyeRadius,
1453
+ className: "qr-skeleton-eye"
1454
+ }
1455
+ ),
1456
+ /* @__PURE__ */ jsx33(
1457
+ "rect",
1458
+ {
1459
+ x: x + padding,
1460
+ y: y + padding,
1461
+ width: eyeSize - 2 * padding,
1462
+ height: eyeSize - 2 * padding,
1463
+ fill: bgColor,
1464
+ rx: eyeRadius / 2,
1465
+ ry: eyeRadius / 2
1466
+ }
1467
+ ),
1468
+ /* @__PURE__ */ jsx33("circle", { cx: x + eyeSize / 2, cy: y + eyeSize / 2, r: centerRadius, fill: fillColor, className: "qr-skeleton-eye" })
1469
+ ] });
1470
+ };
1471
+
1472
+ // src/components/QRCodeDisplay/generateSkeletonDots.tsx
1473
+ import { jsx as jsx34 } from "react/jsx-runtime";
1474
+ var generateSkeletonDots = ({
1475
+ logoSize,
1476
+ dotSize,
1477
+ eyeSize,
1478
+ gridSize,
1479
+ fillColor
1480
+ }) => {
1481
+ const dots = [];
1482
+ for (let row = 0; row < gridSize; row++) {
1483
+ for (let col = 0; col < gridSize; col++) {
1484
+ const x = col * dotSize;
1485
+ const y = row * dotSize;
1486
+ const eyeAreaWithPadding = Math.ceil(eyeSize / dotSize);
1487
+ const isTopLeftEye = row < eyeAreaWithPadding && col < eyeAreaWithPadding;
1488
+ const isTopRightEye = row < eyeAreaWithPadding && col >= gridSize - eyeAreaWithPadding;
1489
+ const isBottomLeftEye = row >= gridSize - eyeAreaWithPadding && col < eyeAreaWithPadding;
1490
+ const centerX = (gridSize - 1) / 2;
1491
+ const centerY = (gridSize - 1) / 2;
1492
+ const logoPaddingInGridUnits = 6 / dotSize;
1493
+ const logoHalfSize = logoSize / dotSize / 2 + logoPaddingInGridUnits;
1494
+ const isLogoArea = Math.abs(col - centerX) < logoHalfSize && Math.abs(row - centerY) < logoHalfSize;
1495
+ if (!isTopLeftEye && !isTopRightEye && !isBottomLeftEye && !isLogoArea) {
1496
+ dots.push(
1497
+ /* @__PURE__ */ jsx34(
1498
+ "circle",
1499
+ {
1500
+ cx: x + dotSize / 2,
1501
+ cy: y + dotSize / 2,
1502
+ r: dotSize * 0.25,
1503
+ fill: fillColor,
1504
+ className: "qr-skeleton-dot"
1505
+ },
1506
+ `${row}-${col}`
1507
+ )
1508
+ );
1509
+ }
1510
+ }
1511
+ }
1512
+ return dots;
1513
+ };
1514
+
1515
+ // src/components/QRCodeDisplay/QRCodeSkeleton.tsx
1516
+ import { jsx as jsx35, jsxs as jsxs17 } from "react/jsx-runtime";
1517
+ var QRCodeSkeleton = ({ size = 128 }) => {
1518
+ const { brandConfig } = useWidgetContext();
1519
+ const { selectedWallet } = useConnectModal();
1520
+ const fillColor = brandConfig.theme === "light" ? "#777777" : "#6b7280";
1521
+ const bgColor = brandConfig.theme === "light" ? "#ffffff" : "#121212";
1522
+ const logoSize = size * 0.2;
1523
+ const eyeRadius = 6;
1524
+ const dotSize = size / 40;
1525
+ const eyeSize = 32;
1526
+ const gridSize = 40;
1527
+ return /* @__PURE__ */ jsx35("div", { className: "qr-skeleton-container", style: { height: size }, children: /* @__PURE__ */ jsxs17("svg", { width: size, height: size, className: "qr-skeleton-svg", children: [
1528
+ /* @__PURE__ */ jsx35("rect", { width: size, height: size, fill: bgColor }),
1529
+ generateSkeletonDots({ logoSize, dotSize, eyeSize, gridSize, fillColor }),
1530
+ /* @__PURE__ */ jsx35(
1531
+ QREye,
1532
+ {
1533
+ x: 0,
1534
+ y: 0,
1535
+ eyeSize,
1536
+ eyeRadius,
1537
+ dotSize,
1538
+ fillColor,
1539
+ bgColor
1540
+ }
1541
+ ),
1542
+ /* @__PURE__ */ jsx35(
1543
+ QREye,
1544
+ {
1545
+ x: size - eyeSize,
1546
+ y: 0,
1547
+ eyeSize,
1548
+ eyeRadius,
1549
+ dotSize,
1550
+ fillColor,
1551
+ bgColor
1552
+ }
1553
+ ),
1554
+ /* @__PURE__ */ jsx35(
1555
+ QREye,
1556
+ {
1557
+ x: 0,
1558
+ y: size - eyeSize,
1559
+ eyeSize,
1560
+ eyeRadius,
1561
+ dotSize,
1562
+ fillColor,
1563
+ bgColor
1564
+ }
1565
+ ),
1566
+ /* @__PURE__ */ jsx35(
1567
+ "rect",
1568
+ {
1569
+ x: size / 2 - logoSize / 2,
1570
+ y: size / 2 - logoSize / 2,
1571
+ width: logoSize,
1572
+ height: logoSize,
1573
+ fill: bgColor,
1574
+ rx: 6,
1575
+ ry: 6
1576
+ }
1577
+ ),
1578
+ /* @__PURE__ */ jsx35(
1579
+ "image",
1580
+ {
1581
+ x: size / 2 - logoSize / 2,
1582
+ y: size / 2 - logoSize / 2,
1583
+ width: logoSize,
1584
+ height: logoSize,
1585
+ href: generateQrCodeWalletLogo(selectedWallet || void 0),
1586
+ opacity: "1.0"
1587
+ }
1588
+ )
1589
+ ] }) });
1590
+ };
1591
+
1592
+ // src/components/QRCodeDisplay/QRCodeDisplay.tsx
1593
+ import { WalletId as WalletId6 } from "@aurum-sdk/types";
1594
+ import { jsx as jsx36, jsxs as jsxs18 } from "react/jsx-runtime";
1595
+ var QRCodeDisplay = ({ uri, size = 256 }) => {
1596
+ const { brandConfig } = useWidgetContext();
1597
+ const { selectedWallet, displayedWallets, connectWallet } = useConnectModal();
1598
+ const qrCodeDisplayColor = brandConfig.theme === "light" ? "#000000" : "#6b7280";
1599
+ const bgColor = brandConfig.theme === "light" ? "#ffffff" : "#121212";
1600
+ const logoWalletRef = useRef4(null);
1601
+ useEffect7(() => {
1602
+ if (selectedWallet && selectedWallet.id !== WalletId6.AppKit) {
1603
+ logoWalletRef.current = selectedWallet;
1604
+ }
1605
+ }, [selectedWallet]);
1606
+ const logoWallet = logoWalletRef.current || selectedWallet;
1607
+ const appKitAdapter = displayedWallets.find(({ id }) => id === WalletId6.AppKit);
1608
+ const handleAppKitConnect = async () => {
1609
+ if (appKitAdapter) {
1610
+ connectWallet(appKitAdapter);
1611
+ }
1612
+ };
1613
+ return /* @__PURE__ */ jsx36(Column, { align: "center", gap: 16, children: /* @__PURE__ */ jsxs18(Column, { align: "center", gap: 4, children: [
1614
+ /* @__PURE__ */ jsx36(
1615
+ "div",
1616
+ {
1617
+ className: `qr-container ${!uri ? "qr-container-shimmer" : ""}`,
1618
+ style: {
1619
+ width: size,
1620
+ height: size
1621
+ },
1622
+ children: !uri ? /* @__PURE__ */ jsx36(QRCodeSkeleton, { size }) : /* @__PURE__ */ jsx36(
1623
+ QRCode,
1624
+ {
1625
+ value: uri,
1626
+ size,
1627
+ quietZone: 0,
1628
+ bgColor,
1629
+ fgColor: qrCodeDisplayColor,
1630
+ logoImage: generateQrCodeWalletLogo(logoWallet || void 0),
1631
+ logoWidth: size * 0.2,
1632
+ logoHeight: size * 0.2,
1633
+ removeQrCodeBehindLogo: true,
1634
+ logoPadding: 6,
1635
+ qrStyle: "dots",
1636
+ eyeRadius: getBorderRadiusScale(brandConfig.borderRadius).xs
1637
+ }
1638
+ )
1639
+ }
1640
+ ),
1641
+ /* @__PURE__ */ jsxs18(Row, { justify: appKitAdapter ? "space-between" : "center", style: { width: "100%" }, children: [
1642
+ /* @__PURE__ */ jsx36(CopyButton, { text: uri || "", disabled: !uri, variant: "secondary", label: "Copy URI" }),
1643
+ appKitAdapter && /* @__PURE__ */ jsx36(
1644
+ Button,
1645
+ {
1646
+ variant: "text",
1647
+ size: "sm",
1648
+ onClick: handleAppKitConnect,
1649
+ style: { color: "var(--color-foreground-muted)", fontWeight: "500" },
1650
+ children: "Open Modal"
1651
+ }
1652
+ )
1653
+ ] })
1654
+ ] }) });
1655
+ };
1656
+
1657
+ // src/components/ConnectModal/QRCodePage.tsx
1658
+ import { ChevronLeft as ChevronLeft2, X as X4, SquareArrowOutUpRight, CircleCheck as CircleCheck2 } from "lucide-react";
1659
+ import { WalletId as WalletId7, WalletName } from "@aurum-sdk/types";
1660
+ import { Fragment as Fragment5, jsx as jsx37, jsxs as jsxs19 } from "react/jsx-runtime";
1661
+ var QRCodePage = () => {
1662
+ const { onDismiss } = useWidgetContext();
1663
+ const { navigateTo } = useNavigation();
1664
+ const { selectedWallet, error, configError, retryConnection, qrSuccess } = useConnectModal();
1665
+ const [connectionUri, setConnectionUri] = useState10(null);
1666
+ const originalWalletRef = useRef5(null);
1667
+ useEffect8(() => {
1668
+ if (selectedWallet && selectedWallet.id !== WalletId7.AppKit) {
1669
+ originalWalletRef.current = selectedWallet;
1670
+ }
1671
+ }, [selectedWallet]);
1672
+ const displayWallet = originalWalletRef.current || selectedWallet;
1673
+ const goBackToHome = () => {
1674
+ navigateTo(PAGE_IDS.SELECT_WALLET);
1675
+ };
1676
+ const title = displayWallet?.name === WalletName.WalletConnect || displayWallet?.name === WalletName.AppKit ? "Scan QR code" : `Scan with ${displayWallet?.name} app`;
1677
+ useEffect8(() => {
1678
+ const handleWalletConnectURI = (event) => {
1679
+ setConnectionUri(event.detail.uri);
1680
+ };
1681
+ window.addEventListener("walletconnect:uri", handleWalletConnectURI);
1682
+ return () => {
1683
+ window.removeEventListener("walletconnect:uri", handleWalletConnectURI);
1684
+ };
1685
+ }, []);
1686
+ useEffect8(() => {
1687
+ if (error && !configError) {
1688
+ setConnectionUri(null);
1689
+ retryConnection();
1690
+ }
1691
+ }, [error, configError]);
1692
+ if (!selectedWallet) {
1693
+ return null;
1694
+ }
1695
+ return /* @__PURE__ */ jsxs19(Fragment5, { children: [
1696
+ /* @__PURE__ */ jsx37(
1697
+ ModalHeader,
1698
+ {
1699
+ leftAction: qrSuccess ? null : /* @__PURE__ */ jsx37(Button, { size: "sm", variant: "close", onClick: goBackToHome, "aria-label": "Go back", children: /* @__PURE__ */ jsx37(ChevronLeft2, { size: 20, color: "var(--color-foreground-muted)" }) }),
1700
+ title,
1701
+ rightAction: qrSuccess ? null : /* @__PURE__ */ jsx37(Button, { size: "sm", variant: "close", onClick: onDismiss, "aria-label": "Close", children: /* @__PURE__ */ jsx37(X4, { size: 20, color: "var(--color-foreground-muted)" }) })
1702
+ }
1703
+ ),
1704
+ qrSuccess ? /* @__PURE__ */ jsx37(Column, { align: "center", style: { height: "8rem" }, children: /* @__PURE__ */ jsx37(CircleCheck2, { color: "var(--aurum-primary-color)", size: 46 }) }) : /* @__PURE__ */ jsxs19(Fragment5, { children: [
1705
+ /* @__PURE__ */ jsx37(Column, { align: "center", gap: 24, children: /* @__PURE__ */ jsx37(QRCodeDisplay, { uri: error ? null : connectionUri }) }),
1706
+ displayWallet?.downloadUrl && /* @__PURE__ */ jsxs19(Fragment5, { children: [
1707
+ /* @__PURE__ */ jsx37(Spacer, { size: 15 }),
1708
+ /* @__PURE__ */ jsxs19(
1709
+ Button,
1710
+ {
1711
+ variant: "tertiary",
1712
+ expand: true,
1713
+ onClick: () => window.open(displayWallet.downloadUrl ?? "", "_blank", "noopener,noreferrer"),
1714
+ children: [
1715
+ /* @__PURE__ */ jsx37(SquareArrowOutUpRight, { size: 16, color: "var(--color-foreground-muted)" }),
1716
+ /* @__PURE__ */ jsxs19(Text, { size: "sm", weight: "semibold", variant: "secondary", children: [
1717
+ "Download ",
1718
+ displayWallet.name
1719
+ ] })
1720
+ ]
1721
+ }
1722
+ )
1723
+ ] })
1724
+ ] })
1725
+ ] });
1726
+ };
1727
+
1728
+ // src/components/ConnectModal/AllWallets.tsx
1729
+ import { useMemo as useMemo4 } from "react";
1730
+ import { X as X5, ChevronLeft as ChevronLeft3 } from "lucide-react";
1731
+ import { Fragment as Fragment6, jsx as jsx38, jsxs as jsxs20 } from "react/jsx-runtime";
1732
+ var AllWalletsPage = () => {
1733
+ const { onDismiss } = useWidgetContext();
1734
+ const { navigateTo } = useNavigation();
1735
+ const { displayedWallets, connectWallet } = useConnectModal();
1736
+ const lastUsedWalletId = useAurumStore((state) => state.lastUsedWalletId);
1737
+ const sortedWallets = useMemo4(() => sortWallets(displayedWallets), [displayedWallets]);
1738
+ const goBackToSelectWallet = () => {
1739
+ navigateTo(PAGE_IDS.SELECT_WALLET);
1740
+ };
1741
+ return /* @__PURE__ */ jsxs20(Fragment6, { children: [
1742
+ /* @__PURE__ */ jsx38(
1743
+ ModalHeader,
1744
+ {
1745
+ leftAction: /* @__PURE__ */ jsx38(Button, { size: "sm", variant: "close", onClick: goBackToSelectWallet, "aria-label": "Go back", children: /* @__PURE__ */ jsx38(ChevronLeft3, { size: 20, color: "var(--color-foreground-muted)" }) }),
1746
+ rightAction: /* @__PURE__ */ jsx38(Button, { size: "sm", variant: "close", onClick: onDismiss, "aria-label": "Close", children: /* @__PURE__ */ jsx38(X5, { size: 20, color: "var(--color-foreground-muted)" }) }),
1747
+ title: "All Wallets"
1748
+ }
1749
+ ),
1750
+ /* @__PURE__ */ jsx38(Column, { justify: "start", style: { maxHeight: "22rem", overflowY: "auto" }, children: sortedWallets.map((wallet) => {
1751
+ return /* @__PURE__ */ jsx38(
1752
+ WalletButton,
1753
+ {
1754
+ wallet,
1755
+ connectWallet,
1756
+ isLastUsed: wallet.id === lastUsedWalletId
1757
+ },
1758
+ wallet.id
1759
+ );
1760
+ }) })
1761
+ ] });
1762
+ };
1763
+
1764
+ // src/components/ConnectModal/DownloadWalletPage.tsx
1765
+ import { X as X6, SquareArrowOutUpRight as SquareArrowOutUpRight2, ChevronLeft as ChevronLeft4 } from "lucide-react";
1766
+ import { Fragment as Fragment7, jsx as jsx39, jsxs as jsxs21 } from "react/jsx-runtime";
1767
+ var DownloadWalletPage = () => {
1768
+ const { selectedWallet, goBackToHome } = useConnectModal();
1769
+ const { onDismiss } = useWidgetContext();
1770
+ if (!selectedWallet) {
1771
+ return null;
1772
+ }
1773
+ const downloadUrl = selectedWallet.downloadUrl;
1774
+ const handleDownload = () => {
1775
+ if (downloadUrl) {
1776
+ window.open(downloadUrl, "_blank", "noopener,noreferrer");
1777
+ }
1778
+ };
1779
+ return /* @__PURE__ */ jsxs21(Fragment7, { children: [
1780
+ /* @__PURE__ */ jsx39(
1781
+ ModalHeader,
1782
+ {
1783
+ leftAction: /* @__PURE__ */ jsx39(Button, { size: "sm", variant: "close", onClick: goBackToHome, "aria-label": "Go back", children: /* @__PURE__ */ jsx39(ChevronLeft4, { size: 20, color: "var(--color-foreground-muted)" }) }),
1784
+ rightAction: /* @__PURE__ */ jsx39(Button, { size: "sm", variant: "close", onClick: onDismiss, "aria-label": "Close", children: /* @__PURE__ */ jsx39(X6, { size: 20, color: "var(--color-foreground-muted)" }) }),
1785
+ title: `Install ${selectedWallet.name}`
1786
+ }
1787
+ ),
1788
+ /* @__PURE__ */ jsxs21(Column, { align: "center", gap: 24, justify: "center", children: [
1789
+ /* @__PURE__ */ jsx39(WalletLogoWrapper, { id: selectedWallet.id, size: 64, sizeSlot: "lg", title: selectedWallet.name }),
1790
+ /* @__PURE__ */ jsxs21(Column, { align: "center", gap: 12, children: [
1791
+ /* @__PURE__ */ jsxs21(Text, { size: "lg", weight: "semibold", align: "center", children: [
1792
+ "Install ",
1793
+ selectedWallet.name
1794
+ ] }),
1795
+ /* @__PURE__ */ jsxs21(Text, { size: "md", variant: "secondary", align: "center", style: { maxWidth: "20rem" }, children: [
1796
+ selectedWallet.name,
1797
+ " not installed. Please download then try again."
1798
+ ] })
1799
+ ] }),
1800
+ downloadUrl && /* @__PURE__ */ jsx39(Fragment7, { children: /* @__PURE__ */ jsxs21(Button, { variant: "tertiary", onClick: handleDownload, expand: true, children: [
1801
+ /* @__PURE__ */ jsx39(SquareArrowOutUpRight2, { size: 16, color: "var(--color-foreground-muted)" }),
1802
+ /* @__PURE__ */ jsxs21(Text, { size: "sm", weight: "semibold", variant: "secondary", children: [
1803
+ "Download ",
1804
+ selectedWallet.name
1805
+ ] })
1806
+ ] }) })
1807
+ ] })
1808
+ ] });
1809
+ };
1810
+
1811
+ // src/components/ConnectModal/EmailVerifyOtp/EmailVerifyOtp.tsx
1812
+ import { X as X7, ChevronLeft as ChevronLeft5, Check, CircleCheck as CircleCheck3 } from "lucide-react";
1813
+
1814
+ // src/components/ConnectModal/EmailVerifyOtp/constants.ts
1815
+ var OTP_LENGTH = 6;
1816
+ var RESEND_COUNTDOWN_SECONDS = 30;
1817
+
1818
+ // src/components/ConnectModal/EmailVerifyOtp/styles.ts
1819
+ var getOtpInputStyles = (isFocused, hasError, hideCaret) => ({
1820
+ width: "2.625rem",
1821
+ height: "3rem",
1822
+ textAlign: "center",
1823
+ fontFamily: "inherit",
1824
+ fontSize: "1.375rem",
1825
+ border: `${hasError || !isFocused ? "0.0625rem" : "0.125rem"} solid ${hasError ? "var(--color-error)" : isFocused ? "var(--color-border-focus)" : "var(--color-border-muted)"}`,
1826
+ borderRadius: "var(--aurum-border-radius-sm)",
1827
+ outline: "none",
1828
+ backgroundColor: "var(--color-accent)",
1829
+ color: "var(--color-foreground)",
1830
+ caretColor: hideCaret ? "transparent" : "auto",
1831
+ transition: "border-color 0.3s ease"
1832
+ });
1833
+ var emailHighlightStyles = {
1834
+ fontWeight: "bold",
1835
+ color: "var(--color-primary)"
1836
+ };
1837
+
1838
+ // src/components/ConnectModal/EmailVerifyOtp/useCountdown.ts
1839
+ import { useState as useState11, useEffect as useEffect9 } from "react";
1840
+ var useCountdown = () => {
1841
+ const [countdown, setCountdown] = useState11(0);
1842
+ const [canResend, setCanResend] = useState11(true);
1843
+ const startCountdown = (seconds) => {
1844
+ setCanResend(false);
1845
+ setCountdown(seconds);
1846
+ };
1847
+ useEffect9(() => {
1848
+ if (countdown <= 0) return;
1849
+ const timer = setTimeout(() => {
1850
+ const newCountdown = countdown - 1;
1851
+ setCountdown(newCountdown);
1852
+ if (newCountdown === 0) {
1853
+ setCanResend(true);
1854
+ }
1855
+ }, 1e3);
1856
+ return () => clearTimeout(timer);
1857
+ }, [countdown]);
1858
+ return { countdown, canResend, startCountdown };
1859
+ };
1860
+
1861
+ // src/components/ConnectModal/EmailVerifyOtp/useOtpInputs.ts
1862
+ import { useState as useState12, useRef as useRef6, useEffect as useEffect10 } from "react";
1863
+ var useOtpInputs = ({
1864
+ emailAuthState,
1865
+ error,
1866
+ clearError,
1867
+ onComplete,
1868
+ isVerifying
1869
+ }) => {
1870
+ const [otp, setOtp] = useState12(Array(OTP_LENGTH).fill(""));
1871
+ const [focusedIndex, setFocusedIndex] = useState12(0);
1872
+ const inputRefs = useRef6([]);
1873
+ const isOtpComplete = otp.every((digit) => digit !== "");
1874
+ const handleInputChange = (index, value) => {
1875
+ if (error) clearError();
1876
+ if (emailAuthState.step === "connecting" || !/^\d*$/.test(value)) return;
1877
+ const newOtp = [...otp];
1878
+ newOtp[index] = value.slice(-1);
1879
+ setOtp(newOtp);
1880
+ if (value && index < OTP_LENGTH - 1) {
1881
+ inputRefs.current[index + 1]?.focus();
1882
+ }
1883
+ };
1884
+ const handleKeyDown = (index, e) => {
1885
+ if (e.key === "Backspace" && !otp[index] && index > 0) {
1886
+ inputRefs.current[index - 1]?.focus();
1887
+ }
1888
+ };
1889
+ const handlePaste = (e) => {
1890
+ e.preventDefault();
1891
+ if (error) clearError();
1892
+ if (emailAuthState.step === "connecting" || !/^\d*$/.test(e.clipboardData.getData("text"))) return;
1893
+ const pastedData = e.clipboardData.getData("text").replace(/\D/g, "").slice(0, OTP_LENGTH);
1894
+ const newOtp = Array(OTP_LENGTH).fill("").map((_, i) => pastedData[i] || "");
1895
+ setOtp(newOtp);
1896
+ const nextEmptyIndex = newOtp.findIndex((digit) => !digit);
1897
+ if (nextEmptyIndex !== -1) {
1898
+ inputRefs.current[nextEmptyIndex]?.focus();
1899
+ }
1900
+ };
1901
+ useEffect10(() => {
1902
+ if (isOtpComplete && otp.join("").length === OTP_LENGTH) {
1903
+ onComplete(otp.join(""));
1904
+ }
1905
+ }, [otp]);
1906
+ useEffect10(() => {
1907
+ inputRefs.current[0]?.focus();
1908
+ const timer = setTimeout(() => {
1909
+ inputRefs.current[0]?.focus();
1910
+ }, 100);
1911
+ return () => clearTimeout(timer);
1912
+ }, []);
1913
+ useEffect10(() => {
1914
+ if (error) {
1915
+ setOtp(Array(OTP_LENGTH).fill(""));
1916
+ inputRefs.current[0]?.focus();
1917
+ }
1918
+ }, [error]);
1919
+ useEffect10(() => {
1920
+ if (isVerifying) {
1921
+ setFocusedIndex(0);
1922
+ }
1923
+ }, [isVerifying]);
1924
+ return {
1925
+ otp,
1926
+ setOtp,
1927
+ focusedIndex,
1928
+ setFocusedIndex,
1929
+ inputRefs,
1930
+ handleInputChange,
1931
+ handleKeyDown,
1932
+ handlePaste
1933
+ };
1934
+ };
1935
+
1936
+ // src/components/ConnectModal/EmailVerifyOtp/EmailVerifyOtp.tsx
1937
+ import { jsx as jsx40, jsxs as jsxs22 } from "react/jsx-runtime";
1938
+ var EmailVerifyOTP = () => {
1939
+ const { onDismiss } = useWidgetContext();
1940
+ const { goBackToHome } = useConnectModal();
1941
+ const { emailAuthState, sendEmailOTP, verifyEmailOTPAndConnect, error, clearError } = useEmailAuth();
1942
+ const isVerifying = emailAuthState.step === "connecting" && !error;
1943
+ const { otp, setOtp, focusedIndex, setFocusedIndex, inputRefs, handleInputChange, handleKeyDown, handlePaste } = useOtpInputs({
1944
+ emailAuthState,
1945
+ error,
1946
+ clearError,
1947
+ onComplete: verifyEmailOTPAndConnect,
1948
+ isVerifying
1949
+ });
1950
+ const { canResend, startCountdown } = useCountdown();
1951
+ const isSuccess = emailAuthState.step === "success";
1952
+ const showOtpInputs = !isVerifying && !isSuccess;
1953
+ const canResendOtp = canResend && emailAuthState.step !== "success";
1954
+ const handleBackToHome = () => {
1955
+ if (emailAuthState.step !== "otp") return;
1956
+ clearError();
1957
+ goBackToHome();
1958
+ };
1959
+ const handleResendOTP = async () => {
1960
+ if (!canResendOtp) return;
1961
+ if (error) clearError();
1962
+ startCountdown(RESEND_COUNTDOWN_SECONDS);
1963
+ await sendEmailOTP(emailAuthState.email);
1964
+ setOtp(Array(OTP_LENGTH).fill(""));
1965
+ inputRefs.current[0]?.focus();
1966
+ };
1967
+ return /* @__PURE__ */ jsxs22("div", { children: [
1968
+ /* @__PURE__ */ jsx40(
1969
+ ModalHeader,
1970
+ {
1971
+ leftAction: isSuccess ? null : /* @__PURE__ */ jsx40(Button, { size: "sm", variant: "close", onClick: handleBackToHome, "aria-label": "Go back", children: /* @__PURE__ */ jsx40(ChevronLeft5, { size: 20, color: "var(--color-foreground-muted)" }) }),
1972
+ rightAction: isSuccess ? null : /* @__PURE__ */ jsx40(Button, { size: "sm", variant: "close", onClick: onDismiss, "aria-label": "Close", children: /* @__PURE__ */ jsx40(X7, { size: 20, color: "var(--color-foreground-muted)" }) }),
1973
+ title: "Verify Email"
1974
+ }
1975
+ ),
1976
+ /* @__PURE__ */ jsxs22(Column, { gap: 24, children: [
1977
+ /* @__PURE__ */ jsxs22(Text, { align: "center", variant: "secondary", children: [
1978
+ "Enter the 6-digit code sent to",
1979
+ /* @__PURE__ */ jsx40("br", {}),
1980
+ " ",
1981
+ /* @__PURE__ */ jsx40("span", { style: emailHighlightStyles, children: emailAuthState.email })
1982
+ ] }),
1983
+ /* @__PURE__ */ jsxs22(Column, { align: "center", gap: 12, children: [
1984
+ /* @__PURE__ */ jsxs22("div", { style: { position: "relative", height: "3rem" }, children: [
1985
+ /* @__PURE__ */ jsx40(
1986
+ Row,
1987
+ {
1988
+ justify: "center",
1989
+ gap: 8,
1990
+ style: {
1991
+ opacity: showOtpInputs ? 1 : 0,
1992
+ pointerEvents: showOtpInputs ? "auto" : "none",
1993
+ position: "relative"
1994
+ },
1995
+ children: otp.map((digit, index) => /* @__PURE__ */ jsx40(
1996
+ "input",
1997
+ {
1998
+ "aria-label": "OTP input",
1999
+ id: `otp-input-${index}`,
2000
+ type: "text",
2001
+ autoFocus: index === 0,
2002
+ maxLength: 1,
2003
+ value: digit,
2004
+ inputMode: "numeric",
2005
+ onPaste: handlePaste,
2006
+ onBlur: () => setFocusedIndex(null),
2007
+ onFocus: () => setFocusedIndex(index),
2008
+ onKeyDown: (e) => handleKeyDown(index, e),
2009
+ ref: (el) => inputRefs.current[index] = el,
2010
+ style: getOtpInputStyles(focusedIndex === index, !!error, !showOtpInputs),
2011
+ onChange: (e) => handleInputChange(index, e.target.value)
2012
+ },
2013
+ index
2014
+ ))
2015
+ }
2016
+ ),
2017
+ !showOtpInputs && /* @__PURE__ */ jsx40(Column, { align: "center", justify: "center", style: { position: "absolute", inset: 0 }, children: isVerifying ? /* @__PURE__ */ jsx40(Spinner, { size: 32, color: "var(--aurum-primary-color)" }) : isSuccess ? /* @__PURE__ */ jsx40(CircleCheck3, { size: 46, color: "var(--aurum-primary-color)" }) : null })
2018
+ ] }),
2019
+ /* @__PURE__ */ jsx40(
2020
+ Text,
2021
+ {
2022
+ align: "center",
2023
+ variant: "error",
2024
+ size: "sm",
2025
+ style: { visibility: error ? "visible" : "hidden", height: "1rem", display: isSuccess ? "none" : "block" },
2026
+ children: error
2027
+ }
2028
+ )
2029
+ ] }),
2030
+ !isSuccess && /* @__PURE__ */ jsx40(Column, { align: "center", justify: "center", children: /* @__PURE__ */ jsx40(Row, { align: "center", justify: "center", style: { minHeight: "2rem" }, children: canResend ? /* @__PURE__ */ jsxs22(Row, { align: "baseline", gap: 2, children: [
2031
+ /* @__PURE__ */ jsx40(Text, { size: "sm", variant: "secondary", children: "Didn't receive the code?" }),
2032
+ /* @__PURE__ */ jsx40(
2033
+ Button,
2034
+ {
2035
+ size: "sm",
2036
+ variant: "text",
2037
+ onClick: handleResendOTP,
2038
+ onMouseDown: (e) => e.preventDefault(),
2039
+ disabled: !canResendOtp,
2040
+ children: "Resend"
2041
+ }
2042
+ )
2043
+ ] }) : /* @__PURE__ */ jsxs22(Row, { align: "center", gap: 4, children: [
2044
+ /* @__PURE__ */ jsx40(Text, { size: "sm", variant: "secondary", children: "Email re-sent" }),
2045
+ /* @__PURE__ */ jsx40(Check, { size: 14, color: "var(--color-foreground-muted)" })
2046
+ ] }) }) })
2047
+ ] })
2048
+ ] });
2049
+ };
2050
+
2051
+ // src/components/ConnectModal/ConfigErrorPage.tsx
2052
+ import { X as X8, AlertTriangle, ChevronLeft as ChevronLeft6 } from "lucide-react";
2053
+ import { Fragment as Fragment8, jsx as jsx41, jsxs as jsxs23 } from "react/jsx-runtime";
2054
+ var ConfigErrorPage = () => {
2055
+ const { onDismiss } = useWidgetContext();
2056
+ const { goBackToHome } = useConnectModal();
2057
+ return /* @__PURE__ */ jsxs23(Fragment8, { children: [
2058
+ /* @__PURE__ */ jsx41(
2059
+ ModalHeader,
2060
+ {
2061
+ leftAction: /* @__PURE__ */ jsx41(Button, { size: "sm", variant: "close", onClick: goBackToHome, "aria-label": "Go back", children: /* @__PURE__ */ jsx41(ChevronLeft6, { size: 20, color: "var(--color-foreground-muted)" }) }),
2062
+ rightAction: /* @__PURE__ */ jsx41(Button, { size: "sm", variant: "close", onClick: onDismiss, "aria-label": "Close", children: /* @__PURE__ */ jsx41(X8, { size: 20, color: "var(--color-foreground-muted)" }) }),
2063
+ title: "Error"
2064
+ }
2065
+ ),
2066
+ /* @__PURE__ */ jsxs23(Column, { align: "center", gap: 24, justify: "center", children: [
2067
+ /* @__PURE__ */ jsx41(
2068
+ "div",
2069
+ {
2070
+ style: {
2071
+ width: 64,
2072
+ height: 64,
2073
+ borderRadius: "var(--aurum-border-radius-md)",
2074
+ backgroundColor: "color-mix(in srgb, var(--color-error) 80%, transparent)",
2075
+ display: "flex",
2076
+ alignItems: "center",
2077
+ justifyContent: "center"
2078
+ },
2079
+ children: /* @__PURE__ */ jsx41(AlertTriangle, { size: 32, color: "white" })
2080
+ }
2081
+ ),
2082
+ /* @__PURE__ */ jsxs23(Column, { align: "center", gap: 12, children: [
2083
+ /* @__PURE__ */ jsx41(Text, { size: "lg", weight: "semibold", align: "center", children: "Configuration Error" }),
2084
+ /* @__PURE__ */ jsx41(Text, { size: "md", variant: "secondary", align: "center", style: { maxWidth: "20rem" }, children: "Missing required project ID" })
2085
+ ] }),
2086
+ /* @__PURE__ */ jsx41(Button, { variant: "secondary", onClick: goBackToHome, expand: true, children: /* @__PURE__ */ jsx41(Text, { size: "sm", weight: "semibold", children: "Back" }) })
2087
+ ] })
2088
+ ] });
2089
+ };
2090
+
2091
+ // src/components/ConnectModal/PageIds.tsx
2092
+ import { jsx as jsx42 } from "react/jsx-runtime";
2093
+ var PAGE_IDS = {
2094
+ SELECT_WALLET: "select-wallet",
2095
+ ALL_WALLETS: "all-wallets",
2096
+ QR_CODE: "qr-code",
2097
+ MOBILE_DEEP_LINK: "mobile-deep-link",
2098
+ DOWNLOAD_WALLET: "download-wallet",
2099
+ CONNECTING: "connecting",
2100
+ EMAIL_VERIFY_OTP: "email-verify-otp",
2101
+ CONFIG_ERROR: "config-error"
2102
+ };
2103
+ var PAGE_COMPONENTS = {
2104
+ [PAGE_IDS.SELECT_WALLET]: /* @__PURE__ */ jsx42(SelectWalletPage, {}),
2105
+ [PAGE_IDS.ALL_WALLETS]: /* @__PURE__ */ jsx42(AllWalletsPage, {}),
2106
+ [PAGE_IDS.QR_CODE]: /* @__PURE__ */ jsx42(QRCodePage, {}),
2107
+ [PAGE_IDS.MOBILE_DEEP_LINK]: /* @__PURE__ */ jsx42(ConnectionStatusMobilePage, {}),
2108
+ [PAGE_IDS.DOWNLOAD_WALLET]: /* @__PURE__ */ jsx42(DownloadWalletPage, {}),
2109
+ [PAGE_IDS.CONNECTING]: /* @__PURE__ */ jsx42(ConnectionStatusPage, {}),
2110
+ [PAGE_IDS.EMAIL_VERIFY_OTP]: /* @__PURE__ */ jsx42(EmailVerifyOTP, {}),
2111
+ [PAGE_IDS.CONFIG_ERROR]: /* @__PURE__ */ jsx42(ConfigErrorPage, {})
2112
+ };
2113
+
2114
+ // src/utils/walletConnectDeepLink.ts
2115
+ var clearExistingDeepLinkListeners = () => {
2116
+ const existingListeners = window.__aurumDeepLinkListeners ?? [];
2117
+ existingListeners.forEach((cleanup) => cleanup());
2118
+ window.__aurumDeepLinkListeners = [];
2119
+ };
2120
+ var createWalletConnectHandlers = (deepLinkBaseUrl, onRejection) => {
2121
+ const handleUri = (event) => {
2122
+ const uri = event.detail.uri;
2123
+ if (uri && deepLinkBaseUrl) {
2124
+ const deepLinkUrl = `${deepLinkBaseUrl}${encodeURIComponent(uri)}`;
2125
+ window.location.href = deepLinkUrl;
2126
+ }
2127
+ };
2128
+ const handleDisconnect = () => {
2129
+ onRejection();
2130
+ };
2131
+ return { handleUri, handleDisconnect };
2132
+ };
2133
+ var setupEventListeners = (handlers) => {
2134
+ const { handleUri, handleDisconnect } = handlers;
2135
+ window.addEventListener("walletconnect:uri", handleUri);
2136
+ window.addEventListener("walletconnect:disconnect", handleDisconnect);
2137
+ return () => {
2138
+ window.removeEventListener("walletconnect:uri", handleUri);
2139
+ window.removeEventListener("walletconnect:disconnect", handleDisconnect);
2140
+ };
2141
+ };
2142
+ var registerGlobalCleanup = (cleanupFn) => {
2143
+ if (!window.__aurumDeepLinkListeners) {
2144
+ window.__aurumDeepLinkListeners = [];
2145
+ }
2146
+ const cleanup = () => {
2147
+ const cleanupList = window.__aurumDeepLinkListeners ?? [];
2148
+ const index = cleanupList.indexOf(cleanup);
2149
+ if (index > -1) cleanupList.splice(index, 1);
2150
+ cleanupFn();
2151
+ };
2152
+ window.__aurumDeepLinkListeners?.push(cleanup);
2153
+ return cleanup;
2154
+ };
2155
+
2156
+ // src/hooks/useConnectSelectedWallet.tsx
2157
+ import { WalletId as WalletId8 } from "@aurum-sdk/types";
2158
+ var useConnectSelectedWallet = () => {
2159
+ const { navigateTo } = useNavigation();
2160
+ const connectInstalledWallet = async ({ adapter, onConnect, setSuccess }) => {
2161
+ navigateTo(PAGE_IDS.CONNECTING);
2162
+ try {
2163
+ const { address, provider } = await adapter.connect();
2164
+ setSuccess?.(true);
2165
+ setTimeout(() => {
2166
+ onConnect({ walletId: adapter.id, address, provider });
2167
+ }, 1e3);
2168
+ } catch (error) {
2169
+ if (isConfigError(error)) {
2170
+ navigateTo(PAGE_IDS.CONFIG_ERROR);
2171
+ return;
2172
+ }
2173
+ throw error;
2174
+ }
2175
+ };
2176
+ const connectUninstalledWalletQRCode = async ({ displayedWallets, onConnect, setSuccess }) => {
2177
+ const walletConnectAdapter = displayedWallets?.find(({ id }) => id === WalletId8.WalletConnect);
2178
+ if (!walletConnectAdapter) {
2179
+ sentryLogger.error("connectUninstalledWalletQRCode: WalletConnect adapter not found");
2180
+ throw new Error("WalletConnect adapter not found");
2181
+ }
2182
+ navigateTo(PAGE_IDS.QR_CODE);
2183
+ try {
2184
+ const { address, provider } = await walletConnectAdapter.connect();
2185
+ setSuccess?.(true);
2186
+ setTimeout(() => {
2187
+ onConnect({ walletId: walletConnectAdapter.id, address, provider });
2188
+ }, 1e3);
2189
+ } catch (error) {
2190
+ if (isConfigError(error)) {
2191
+ navigateTo(PAGE_IDS.CONFIG_ERROR);
2192
+ return;
2193
+ }
2194
+ throw error;
2195
+ }
2196
+ };
2197
+ const connectWithMobileDeepLink = async ({
2198
+ displayedWallets,
2199
+ adapter,
2200
+ onConnect,
2201
+ setSuccess
2202
+ }) => {
2203
+ const walletConnectAdapter = displayedWallets?.find(({ id }) => id === WalletId8.WalletConnect);
2204
+ if (!walletConnectAdapter) {
2205
+ sentryLogger.error("connectWithMobileDeepLink: WalletConnect adapter not found");
2206
+ throw new Error("WalletConnect adapter not found");
2207
+ }
2208
+ let isRejected = false;
2209
+ clearExistingDeepLinkListeners();
2210
+ const handlers = createWalletConnectHandlers(adapter.wcDeepLinkUrl, () => {
2211
+ isRejected = true;
2212
+ });
2213
+ const cleanupEventListeners = setupEventListeners(handlers);
2214
+ const cleanupGlobal = registerGlobalCleanup(cleanupEventListeners);
2215
+ try {
2216
+ navigateTo(PAGE_IDS.MOBILE_DEEP_LINK);
2217
+ const { address, provider } = await walletConnectAdapter.connect();
2218
+ cleanupGlobal();
2219
+ if (isRejected) {
2220
+ return;
2221
+ }
2222
+ setSuccess?.(true);
2223
+ setTimeout(() => {
2224
+ onConnect({ walletId: walletConnectAdapter.id, address, provider });
2225
+ }, 1e3);
2226
+ } catch (error) {
2227
+ cleanupGlobal();
2228
+ if (isConfigError(error)) {
2229
+ navigateTo(PAGE_IDS.CONFIG_ERROR);
2230
+ return;
2231
+ }
2232
+ throw error;
2233
+ }
2234
+ };
2235
+ const connectAppKit = async ({ adapter, onConnect, setSuccess }) => {
2236
+ try {
2237
+ const { address, provider } = await adapter.connect();
2238
+ setSuccess?.(true);
2239
+ setTimeout(() => {
2240
+ onConnect({ walletId: adapter.id, address, provider });
2241
+ }, 1e3);
2242
+ } catch (error) {
2243
+ if (isConfigError(error)) {
2244
+ navigateTo(PAGE_IDS.CONFIG_ERROR);
2245
+ return;
2246
+ }
2247
+ }
2248
+ };
2249
+ const redirectToDownloadPage = async () => {
2250
+ navigateTo(PAGE_IDS.DOWNLOAD_WALLET);
2251
+ };
2252
+ return {
2253
+ // Both mobile and desktop
2254
+ connectInstalledWallet,
2255
+ connectAppKit,
2256
+ redirectToDownloadPage,
2257
+ // Desktop only
2258
+ connectUninstalledWalletQRCode,
2259
+ // Mobile only
2260
+ connectWithMobileDeepLink
2261
+ };
2262
+ };
2263
+
2264
+ // src/contexts/ConnectModalContext.tsx
2265
+ import { WalletId as WalletId9 } from "@aurum-sdk/types";
2266
+ import { jsx as jsx43 } from "react/jsx-runtime";
2267
+ var ConnectModalContext = createContext4(null);
2268
+ var useConnectModal = () => {
2269
+ const context = useContext4(ConnectModalContext);
2270
+ if (!context) {
2271
+ throw new Error("useConnectModal must be used within a ConnectModalProvider");
2272
+ }
2273
+ return context;
2274
+ };
2275
+ var ConnectModalProvider = ({ children, displayedWallets, onConnect }) => {
2276
+ const { navigateTo } = useNavigation();
2277
+ const {
2278
+ redirectToDownloadPage,
2279
+ connectInstalledWallet,
2280
+ connectWithMobileDeepLink,
2281
+ connectUninstalledWalletQRCode,
2282
+ connectAppKit
2283
+ } = useConnectSelectedWallet();
2284
+ const [error, setError] = useState13(false);
2285
+ const [configError, setConfigError] = useState13(false);
2286
+ const [success, setSuccess] = useState13(false);
2287
+ const [qrSuccess, setQrSuccess] = useState13(false);
2288
+ const [selectedWallet, setSelectedWallet] = useState13(null);
2289
+ const connectWallet = async (wallet) => {
2290
+ try {
2291
+ setError(false);
2292
+ setConfigError(false);
2293
+ setSuccess(false);
2294
+ setQrSuccess(false);
2295
+ setSelectedWallet(wallet);
2296
+ const isOnMobile = isMobile();
2297
+ const isDesktop = !isOnMobile;
2298
+ const hasDeepLink = Boolean(wallet.wcDeepLinkUrl);
2299
+ if (isDesktop) {
2300
+ if (wallet.id === WalletId9.AppKit)
2301
+ return await connectAppKit({ adapter: wallet, onConnect, setSuccess: setQrSuccess });
2302
+ if (!wallet.isInstalled() && !hasDeepLink) {
2303
+ return await redirectToDownloadPage();
2304
+ }
2305
+ if (wallet.id === WalletId9.WalletConnect || !wallet.isInstalled())
2306
+ return await connectUninstalledWalletQRCode({
2307
+ adapter: wallet,
2308
+ displayedWallets,
2309
+ onConnect,
2310
+ setSuccess: setQrSuccess
2311
+ });
2312
+ return await connectInstalledWallet({ adapter: wallet, onConnect, setSuccess });
2313
+ }
2314
+ if (isOnMobile) {
2315
+ if (wallet.id === WalletId9.WalletConnect || wallet.id === WalletId9.AppKit) {
2316
+ const appkitAdapter = displayedWallets?.find(({ id }) => id === WalletId9.AppKit);
2317
+ if (!appkitAdapter) {
2318
+ sentryLogger.error("AppKit adapter not found");
2319
+ throw new Error("AppKit adapter not found");
2320
+ }
2321
+ return await connectAppKit({ adapter: appkitAdapter, onConnect, setSuccess: setQrSuccess });
2322
+ }
2323
+ if (wallet.isInstalled()) return await connectInstalledWallet({ adapter: wallet, onConnect, setSuccess });
2324
+ if (hasDeepLink) {
2325
+ return await connectWithMobileDeepLink({ adapter: wallet, displayedWallets, onConnect, setSuccess });
2326
+ }
2327
+ return await redirectToDownloadPage();
2328
+ }
2329
+ } catch (err) {
2330
+ setError(true);
2331
+ if (isConfigError(err)) {
2332
+ setConfigError(true);
2333
+ }
2334
+ }
2335
+ };
2336
+ const retryConnection = () => {
2337
+ if (selectedWallet) connectWallet(selectedWallet);
2338
+ };
2339
+ const goBackToHome = () => {
2340
+ navigateTo(PAGE_IDS.SELECT_WALLET);
2341
+ setSelectedWallet(null);
2342
+ setError(false);
2343
+ setConfigError(false);
2344
+ setSuccess(false);
2345
+ setQrSuccess(false);
2346
+ };
2347
+ const contextValue = {
2348
+ error,
2349
+ configError,
2350
+ success,
2351
+ qrSuccess,
2352
+ selectedWallet,
2353
+ displayedWallets,
2354
+ goBackToHome,
2355
+ connectWallet,
2356
+ retryConnection,
2357
+ setSelectedWallet,
2358
+ setSuccess,
2359
+ setQrSuccess
2360
+ };
2361
+ return /* @__PURE__ */ jsx43(ConnectModalContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx43(
2362
+ EmailAuthProvider,
2363
+ {
2364
+ onConnect,
2365
+ navigateTo,
2366
+ displayedWallets,
2367
+ setSelectedWallet,
2368
+ children
2369
+ }
2370
+ ) });
2371
+ };
2372
+
2373
+ // src/components/ConnectUIProviders.tsx
2374
+ import { jsx as jsx44 } from "react/jsx-runtime";
2375
+ var ConnectUIProviders = ({ children, onConnect, displayedWallets }) => /* @__PURE__ */ jsx44(NavigationProvider, { initialPage: PAGE_IDS.SELECT_WALLET, children: /* @__PURE__ */ jsx44(ConnectModalProvider, { onConnect, displayedWallets, children }) });
2376
+
2377
+ // src/components/ConnectModal/ConnectPages.tsx
2378
+ var ConnectPages = () => {
2379
+ const { currentPage } = useNavigation();
2380
+ return PAGE_COMPONENTS[currentPage] || PAGE_COMPONENTS[PAGE_IDS.SELECT_WALLET];
2381
+ };
2382
+
2383
+ // src/styles/bundledStyles.ts
2384
+ var bundledStyles = "/* ui/globals.css */\n/* ============================================\n AURUM SDK - DESIGN TOKEN SYSTEM\n ============================================\n\n Google Fonts:\n - Noto Sans: 400, 500, 600, 700\n ============================================ */\n\n@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');\n\n/* ============================================\n External variables (injected by createShadowRoot.ts):\n - --aurum-primary-color: Brand color from dapp\n - --aurum-border-radius-*: Radius scale tokens\n - --aurum-modal-z-index: Modal z-index\n - --aurum-font-family: Font family from dapp\n ============================================ */\n\n/* Base reset styles for Shadow DOM */\n:host {\n all: initial;\n}\n\n*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\n/* Ensure form elements inherit font from parent */\ninput,\nbutton,\ntextarea,\nselect {\n font-family: inherit;\n}\n\n.aurum-sdk {\n /* ==========================================\n TYPOGRAPHY\n ========================================== */\n font-family: var(--aurum-font-family);\n font-size: 1rem;\n line-height: 1.5;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n\n /* Font weights */\n --font-normal: 400;\n --font-medium: 500;\n --font-semibold: 600;\n --font-bold: 700;\n\n /* ==========================================\n TRANSITIONS\n ========================================== */\n --duration-fast: 100ms;\n --duration-normal: 200ms;\n --duration-slow: 300ms;\n --ease-default: cubic-bezier(0.4, 0, 0.2, 1);\n --ease-in: cubic-bezier(0.4, 0, 1, 1);\n --ease-out: cubic-bezier(0, 0, 0.2, 1);\n\n /* ==========================================\n LIGHT THEME COLORS (Default)\n ========================================== */\n\n /* Foreground / Text */\n --color-foreground: #0c0c0c;\n --color-foreground-muted: #787878;\n --color-foreground-subtle: #979797;\n\n /* Card surfaces */\n --color-card: #ffffff;\n\n /* Borders */\n --color-border: #d9d9d9;\n --color-border-muted: #c0c0c0;\n --color-border-focus: var(--aurum-primary-color);\n\n /* Brand / Primary (from integrator) */\n --color-primary: var(--aurum-primary-color);\n --color-primary-foreground: #ffffff;\n --color-primary-hover: color-mix(in srgb, var(--aurum-primary-color) 85%, #000);\n --color-primary-muted: color-mix(in srgb, var(--aurum-primary-color) 15%, transparent);\n\n /* Interactive elements */\n --color-accent: #f1f1f1;\n --color-accent-foreground: #0d0d0d;\n --color-accent-hover: #e6e6e6;\n\n /* Semantic colors */\n --color-success: #22c55e;\n --color-error: #ef4444;\n\n /* Overlay / Modal */\n --color-overlay: rgb(0 0 0 / 0.5);\n\n /* Ring (focus indicator) */\n --color-ring: var(--aurum-primary-color);\n --ring-offset: 0.125rem;\n\n /* Shadows */\n --shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);\n}\n\n/* ==========================================\n DARK THEME COLORS\n ========================================== */\n\n.aurum-sdk[data-theme='dark'] {\n /* Foreground / Text */\n --color-foreground: #fafafa;\n --color-foreground-muted: #a9a9a9;\n --color-foreground-subtle: #777777;\n\n /* Card surfaces */\n --color-card: #151515;\n\n /* Borders */\n --color-border: #282828;\n --color-border-muted: #424242;\n --color-border-focus: var(--aurum-primary-color);\n\n /* Brand / Primary (from integrator) */\n --color-primary: var(--aurum-primary-color);\n --color-primary-foreground: #0a0a0a;\n --color-primary-hover: color-mix(in srgb, var(--aurum-primary-color) 85%, #fff);\n --color-primary-muted: color-mix(in srgb, var(--aurum-primary-color) 20%, transparent);\n\n /* Interactive elements */\n --color-accent: #272727;\n --color-accent-foreground: #fafafa;\n --color-accent-hover: #404040;\n\n /* Semantic colors */\n --color-success: #22c55e;\n --color-error: #ef4444;\n\n /* Overlay / Modal */\n --color-overlay: rgb(0 0 0 / 0.7);\n\n /* Ring (focus indicator) */\n --color-ring: var(--aurum-primary-color);\n --ring-offset: 0.125rem;\n\n /* Shadows */\n --shadow: 0 20px 25px -5px rgb(0 0 0 / 0.5), 0 8px 10px -6px rgb(0 0 0 / 0.5);\n}\n\n\n/* components/ConnectModal/AdditionalWalletsIcon.css */\n.additional-wallets-container {\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.additional-wallets-grid {\n display: grid;\n grid-template-columns: 1fr 1fr;\n grid-template-rows: 1fr 1fr;\n gap: 0.125rem;\n align-items: center;\n justify-items: center;\n}\n\n.additional-wallets-grid-item {\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.additional-wallets-placeholder {\n background-color: var(--aurum-color-bg-tertiary);\n border-radius: var(--aurum-border-radius-xs);\n opacity: 0.4;\n}\n\n.circular-icon-wrapper {\n border-radius: 50%;\n overflow: hidden;\n border: 2px solid var(--aurum-color-bg-secondary);\n}\n\n.circular-icon-wrapper--front {\n z-index: 2;\n}\n\n.circular-icon-wrapper--back {\n margin-left: -0.5rem;\n z-index: 1;\n}\n\n\n/* components/ConnectModal/ConnectionStatus/ConnectionStatus.css */\n@keyframes shake {\n 0%,\n 100% {\n transform: translateX(0);\n }\n 20%,\n 60% {\n transform: translateX(-0.125rem);\n }\n 40%,\n 80% {\n transform: translateX(0.125rem);\n }\n}\n\n@keyframes opacity-pulse {\n 0%,\n 100% {\n opacity: 0.4;\n }\n 50% {\n opacity: 1;\n }\n}\n\n@keyframes scale-in {\n from {\n transform: scale(0.75);\n }\n to {\n transform: scale(1);\n }\n}\n\n.wallet-icon-shake {\n /* Duration synced with ANIMATION_DURATION.SHAKE in constants/theme.ts */\n animation: shake var(--duration-slow) var(--ease-default);\n}\n\n.ellipses-loading,\n.ellipses-success,\n.status-icon-with-dots {\n display: flex;\n gap: 0.25rem;\n align-items: center;\n justify-content: center;\n width: 100%;\n}\n\n.ellipses-loading span,\n.ellipses-success span,\n.status-icon-with-dots .dot,\n.status-icon-with-dots .icon-center {\n font-size: 3rem;\n line-height: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 0.9375rem;\n height: 3rem;\n margin: 0;\n padding: 0;\n flex-shrink: 0;\n}\n\n.ellipses-loading span,\n.ellipses-success span,\n.status-icon-with-dots .dot {\n transform: translateY(-0.28125rem);\n}\n\n.status-icon-with-dots .icon-center {\n transform: translateY(-0.2rem);\n}\n\n.ellipses-loading span {\n color: var(--color-foreground-subtle);\n opacity: 0.4;\n animation: opacity-pulse 1.5s var(--ease-default) infinite;\n will-change: opacity;\n}\n\n.ellipses-loading span:nth-child(2) {\n animation-delay: 0.2s;\n}\n.ellipses-loading span:nth-child(3) {\n animation-delay: 0.4s;\n}\n.ellipses-loading span:nth-child(4) {\n animation-delay: 0.6s;\n}\n.ellipses-loading span:nth-child(5) {\n animation-delay: 0.8s;\n}\n\n.ellipses-success span,\n.status-icon-with-dots.success .dot {\n color: var(--aurum-primary-color);\n}\n\n.status-icon-with-dots.error .dot {\n color: var(--color-error);\n}\n\n.status-button {\n display: flex;\n align-items: flex-start;\n justify-content: center;\n width: 100%;\n}\n\n.success-icon-large {\n animation: scale-in var(--duration-fast) var(--ease-out);\n}\n\n/* Logo containers for visual balance */\n.brand-logo-container,\n.wallet-logo-with-retry {\n position: relative;\n display: inline-block;\n}\n\n/* Always reserve space on both sides to prevent layout shift when retry button appears/disappears */\n.brand-logo-container {\n margin-left: 0.375rem; /* Matches retry button's right: -0.375rem */\n}\n\n.wallet-logo-with-retry {\n margin-right: 0.375rem; /* Reserve space for retry button */\n}\n\n.retry-icon-overlay.retry-icon-overlay {\n position: absolute;\n bottom: -0.125rem;\n right: -0.375rem;\n width: 1.625rem;\n height: 1.625rem;\n min-width: 1.625rem;\n min-height: 1.625rem;\n border-radius: 50%;\n padding: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n\n/* components/ConnectModal/EmailAuth.css */\n.email-auth-input {\n width: 100%;\n outline: none;\n font-family: inherit;\n font-size: 1rem;\n line-height: 1.75rem;\n box-sizing: border-box;\n padding: 0.75rem 3rem 0.75rem 3rem;\n color: var(--color-foreground);\n transition:\n outline 0.2s ease,\n border-color 0.2s ease;\n background-color: var(--color-card);\n border-width: 1px;\n border-style: solid;\n border-color: var(--color-border);\n border-radius: var(--aurum-border-radius-md);\n}\n\n.email-auth-input:hover:not(:focus):not(.email-auth-input--error) {\n border-color: var(--color-border-muted);\n}\n\n.email-auth-input:focus {\n outline: 2px solid var(--color-ring);\n outline-offset: var(--ring-offset);\n}\n\n.email-auth-input--error {\n outline: 2px solid var(--color-error);\n outline-offset: var(--ring-offset);\n}\n\n.email-auth-submit-button.aurum-button {\n top: 50%;\n right: 0.75rem;\n height: auto;\n padding: 0.5rem;\n min-width: auto;\n position: absolute;\n transform: translateY(-50%);\n border-radius: var(--aurum-border-radius-sm);\n}\n\n.email-auth-icon {\n top: 50%;\n left: 1rem;\n position: absolute;\n transform: translateY(-50%);\n display: flex;\n align-items: center;\n pointer-events: none;\n}\n\n\n/* components/ConnectModal/WalletGrid.css */\n.aurum-wallet-grid {\n display: grid;\n grid-template-columns: repeat(var(--grid-columns, 3), 1fr);\n gap: 10px;\n width: 100%;\n}\n\n\n/* components/ModalHeader/ModalHeader.css */\n.modal-header {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n padding: 1rem;\n background-color: var(--color-card);\n border-radius: var(--aurum-border-radius-lg) var(--aurum-border-radius-lg) 0 0;\n z-index: 1;\n display: grid;\n grid-template-columns: 1fr auto 1fr;\n align-items: center;\n}\n\n.modal-header > div {\n display: flex;\n align-items: center;\n width: 100%;\n}\n\n.modal-header-left {\n justify-content: flex-start;\n min-width: 2.25rem;\n height: 2.25rem;\n}\n\n.modal-header-center {\n justify-content: center;\n max-width: 12.5rem;\n text-align: center;\n line-height: 1.2;\n overflow-wrap: break-word;\n}\n\n.modal-header-right {\n justify-content: flex-end;\n min-width: 2.25rem;\n height: 2.25rem;\n}\n\n\n/* components/PoweredBy/PoweredBy.css */\n.powered-by-container {\n position: absolute;\n bottom: 1rem;\n left: 0;\n right: 0;\n width: 100%;\n}\n\n\n/* components/QRCodeDisplay/QRCodeDisplay.css */\n@keyframes qr-shimmer {\n 0% {\n transform: translateX(-100%);\n }\n 100% {\n transform: translateX(100%);\n }\n}\n\n.qr-container-shimmer {\n position: relative;\n overflow: hidden; /* Keep for shimmer animation */\n}\n\n.qr-container-shimmer::before {\n content: '';\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background: linear-gradient(\n 90deg,\n transparent 0%,\n color-mix(in srgb, var(--color-foreground) 10%, transparent) 50%,\n transparent 100%\n );\n animation: qr-shimmer 2s infinite;\n pointer-events: none;\n z-index: 1;\n}\n\n.qr-container {\n border-radius: var(--aurum-border-radius-md);\n border: 1px solid var(--color-border);\n padding: 0.5rem;\n box-sizing: content-box;\n transition: border-color var(--duration-slow) var(--ease-default);\n}\n\n.qr-subtitle {\n max-width: 15rem;\n}\n\n\n/* components/QRCodeDisplay/QRCodeSkeleton.css */\n.qr-skeleton-container {\n width: 100%;\n position: relative;\n}\n\n.qr-skeleton-svg {\n display: block;\n position: relative;\n z-index: 2;\n border-radius: var(--aurum-border-radius-sm);\n}\n\n.qr-skeleton-dot {\n opacity: 0.7;\n}\n\n.qr-skeleton-eye {\n opacity: 0.7;\n}\n\n\n/* components/SpinnerWithIcon/SpinnerWithIcon.css */\n.spinner-with-icon {\n transition: all var(--duration-normal) var(--ease-default);\n}\n\n.spinner-with-icon svg {\n transition: color var(--duration-normal) var(--ease-default);\n}\n\n\n/* components/widgets/widgets.css */\n/* Widget-specific styles that match modal-content */\n\n.widget-provider {\n position: relative;\n width: 23.75rem;\n min-width: 17rem;\n margin: 0 auto;\n padding: 1.25rem 1.5rem;\n background-color: var(--color-card);\n border-radius: var(--aurum-border-radius-lg);\n border: 1px solid var(--color-border-muted);\n box-sizing: border-box;\n color: var(--color-card-foreground);\n box-shadow: var(--shadow);\n outline: none;\n overflow-x: auto;\n}\n\n.widget-provider .modal-header {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n}\n\n@media (max-width: 30.25rem) {\n .widget-provider {\n width: 100%;\n max-width: 100%;\n border-radius: var(--aurum-border-radius-md);\n display: flex;\n flex-direction: column;\n }\n\n /* Ensure page wrapper fills width in flex container on mobile */\n /* .widget-pages {\n width: 100%;\n } */\n}\n\n\n/* ui/Badge/Badge.css */\n.aurum-badge-recent {\n padding: 0.25rem 0.5rem;\n border-radius: var(--aurum-border-radius-xs);\n\n font-size: 0.65rem;\n line-height: 1;\n letter-spacing: 0.07em;\n text-transform: uppercase;\n\n color: var(--color-foreground-muted);\n}\n\n\n/* ui/Button/Button.css */\n.aurum-button {\n display: flex;\n align-items: center;\n justify-content: center;\n border: none;\n font-weight: var(--font-semibold);\n cursor: pointer;\n transition:\n background-color var(--duration-normal) var(--ease-default),\n color var(--duration-normal) var(--ease-default),\n transform var(--duration-fast) var(--ease-default),\n box-shadow var(--duration-normal) var(--ease-default);\n text-decoration: none;\n box-sizing: border-box;\n position: relative;\n outline: none;\n font-family: inherit;\n}\n\n.aurum-button:focus-visible {\n outline: 2px solid var(--color-ring);\n outline-offset: var(--ring-offset);\n}\n\n.aurum-button--xs {\n padding: 0.25rem 0.5rem;\n font-size: 0.75rem;\n gap: 0.25rem;\n border-radius: var(--aurum-border-radius-xs);\n}\n\n.aurum-button--sm {\n padding: 0.5rem 0.75rem;\n font-size: 0.875rem;\n gap: 0.25rem;\n border-radius: calc(var(--aurum-border-radius-sm) - 2px);\n}\n\n.aurum-button--md {\n padding: 0.75rem 1rem;\n font-size: 0.9rem;\n gap: 0.5rem;\n border-radius: calc(var(--aurum-border-radius-md) - 2px);\n}\n\n.aurum-button--lg {\n padding: 1rem 1.5rem;\n font-size: 1rem;\n gap: 0.75rem;\n border-radius: var(--aurum-border-radius-md);\n}\n\n.aurum-button--full-width {\n width: 100%;\n}\n\n.aurum-button--primary {\n background-color: var(--color-primary);\n color: var(--color-primary-foreground);\n}\n\n.aurum-button--primary:active:not(:disabled) {\n transform: scale(0.98);\n}\n\n.aurum-button--secondary {\n background-color: var(--color-accent);\n color: var(--color-accent-foreground);\n}\n\n.aurum-button--secondary:active:not(:disabled) {\n transform: scale(0.98);\n}\n\n.aurum-button--tertiary {\n background: transparent;\n color: var(--color-foreground);\n border: 1px solid var(--color-border);\n}\n\n.aurum-button--tertiary:active:not(:disabled) {\n transform: scale(0.98);\n}\n\n.aurum-button--text {\n background: transparent;\n color: var(--color-primary);\n padding: 0.25rem;\n}\n\n.aurum-button--text:not(.aurum-button--full-width) {\n width: fit-content;\n}\n\n.aurum-button--text:active:not(:disabled) {\n transform: scale(0.98);\n}\n\n.aurum-button--close {\n background: transparent;\n color: var(--color-foreground-muted);\n border: none;\n padding: 0.5rem;\n border-radius: var(--aurum-border-radius-md);\n font-size: 1.25rem;\n line-height: 1;\n}\n\n.aurum-button--close:active:not(:disabled) {\n transform: scale(0.95);\n}\n\n/* Hover styles only for devices with hover capability (not touch) */\n@media (hover: hover) {\n .aurum-button--primary:hover:not(:disabled) {\n background-color: var(--color-primary-hover);\n }\n\n .aurum-button--secondary:hover:not(:disabled) {\n background-color: var(--color-accent-hover);\n }\n\n .aurum-button--tertiary:hover:not(:disabled) {\n background-color: var(--color-accent);\n border-color: var(--color-border-muted);\n }\n\n .aurum-button--text:hover:not(:disabled) {\n opacity: 0.7;\n }\n\n .aurum-button--close:hover:not(:disabled) {\n background-color: var(--color-accent);\n color: var(--color-foreground);\n }\n}\n\n.aurum-button--disabled,\n.aurum-button:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n pointer-events: none;\n}\n\n.aurum-button--loading {\n pointer-events: none;\n}\n\n\n/* ui/Divider/Divider.css */\n.divider {\n display: flex;\n align-items: center;\n width: 100%;\n}\n\n.divider-line {\n flex: 1;\n height: 1px;\n background-color: var(--color-border);\n}\n\n.divider-text {\n padding: 0 1rem;\n color: var(--color-foreground-subtle);\n font-size: 0.875rem;\n font-weight: var(--font-medium);\n}\n\n\n/* ui/Modal/Modal.css */\n.modal-overlay {\n position: fixed;\n inset: 0;\n display: flex;\n justify-content: center;\n align-items: center;\n z-index: var(--aurum-modal-z-index);\n background-color: var(--color-overlay);\n opacity: 0;\n}\n\n.modal-overlay.modal-open {\n opacity: 1;\n transition: opacity 150ms ease-out;\n}\n\n.modal-overlay.modal-exiting {\n opacity: 0;\n transition: opacity 150ms ease-in;\n}\n\n.modal-content {\n position: relative;\n width: 23.75rem;\n min-width: 17rem;\n padding: 1.25rem 1.5rem;\n color: var(--color-card-foreground);\n background-color: var(--color-card);\n border-radius: var(--aurum-border-radius-lg);\n box-shadow: var(--shadow);\n border: 1px solid var(--color-border-muted);\n outline: none;\n opacity: 0;\n transform: scale(0.95);\n}\n\n.modal-overlay.modal-open .modal-content {\n opacity: 1;\n transform: scale(1);\n transition:\n opacity 150ms ease-out,\n transform 150ms ease-out;\n}\n\n.modal-overlay.modal-exiting .modal-content {\n opacity: 0;\n transform: scale(0.95);\n transition:\n opacity 150ms ease-in,\n transform 150ms ease-in;\n}\n\n.modal-page-container {\n position: relative;\n width: 100%;\n overflow-x: visible;\n overflow-y: auto;\n scrollbar-width: none;\n -ms-overflow-style: none;\n}\n\n.modal-page-container::-webkit-scrollbar {\n display: none;\n}\n\n.modal-page {\n position: relative;\n width: 100%;\n box-sizing: border-box;\n opacity: 0;\n transition: opacity 0s;\n}\n\n.modal-page.active {\n opacity: 1;\n transition: opacity var(--duration-slow) var(--ease-out);\n}\n\n/* Mobile drawer layout */\n@media (max-width: 30.25rem) {\n .modal-overlay {\n align-items: flex-end;\n justify-content: center;\n opacity: 1;\n transition: none;\n }\n\n .modal-overlay.modal-open {\n transition: none;\n }\n\n .modal-overlay.modal-exiting {\n opacity: 1;\n background-color: transparent;\n transition: none;\n }\n\n .modal-content {\n width: 100%;\n max-height: 82vh;\n max-height: 82dvh;\n min-height: 35vh;\n min-height: 35dvh;\n padding: 1rem;\n border-radius: var(--aurum-border-radius-lg) var(--aurum-border-radius-lg) 0 0;\n border-bottom: none;\n display: flex;\n flex-direction: column;\n height: auto;\n opacity: 1;\n transform: translateY(100%);\n }\n\n .modal-overlay.modal-open .modal-content {\n opacity: 1;\n transform: translateY(0);\n transition: transform 300ms cubic-bezier(0.4, 0, 0.2, 1);\n }\n\n .modal-overlay.modal-exiting .modal-content {\n opacity: 1;\n transform: translateY(100%);\n transition: transform 300ms cubic-bezier(0.4, 0, 0.2, 1);\n }\n\n .modal-page-container {\n flex: 0 1 auto;\n display: flex;\n flex-direction: column;\n overflow-y: auto;\n }\n\n .modal-page {\n flex: 0 1 auto;\n display: flex;\n flex-direction: column;\n }\n}\n\n\n/* ui/Spinner/Spinner.css */\n.spinner {\n flex-shrink: 0;\n animation: spinner-rotate 1s linear infinite;\n}\n\n@keyframes spinner-rotate {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n}\n\n\n/* ui/Text/Text.css */\n.aurum-text {\n margin: 0;\n padding: 0;\n font-family: inherit;\n line-height: 1.5;\n}\n\n.aurum-text--primary {\n color: var(--color-foreground);\n}\n\n.aurum-text--secondary {\n color: var(--color-foreground-muted);\n}\n\n.aurum-text--tertiary {\n color: var(--color-foreground-subtle);\n}\n\n.aurum-text--error {\n color: var(--color-error);\n}\n\n.aurum-text--brand {\n color: var(--color-primary);\n}\n\n.aurum-text--success {\n color: var(--color-success);\n}\n\n.aurum-text--xs {\n font-size: 0.75rem;\n line-height: 1.4;\n}\n\n.aurum-text--sm {\n font-size: 0.875rem;\n line-height: 1.45;\n}\n\n.aurum-text--md {\n font-size: 1rem;\n line-height: 1.5;\n}\n\n.aurum-text--lg {\n font-size: 1.125rem;\n line-height: 1.5;\n}\n\n.aurum-text--normal {\n font-weight: var(--font-normal);\n}\n\n.aurum-text--semibold {\n font-weight: var(--font-semibold);\n}\n\n.aurum-text--bold {\n font-weight: var(--font-bold);\n}\n\n.aurum-text--align-left {\n text-align: left;\n}\n\n.aurum-text--align-center {\n text-align: center;\n}\n\n.aurum-text--align-right {\n text-align: right;\n}\n\n\n";
2385
+
2386
+ // src/utils/generateBrandStyles.ts
2387
+ function generateBrandCssVariables(brandConfig) {
2388
+ const r = getBorderRadiusScale(brandConfig.borderRadius);
2389
+ const fontFamily = brandConfig.font === DEFAULT_FONT ? brandConfig.font : `${brandConfig.font}, ${DEFAULT_FONT}`;
2390
+ return `
2391
+ .aurum-sdk {
2392
+ --aurum-primary-color: ${brandConfig.primaryColor};
2393
+ --aurum-border-radius-xs: ${r.xs}px;
2394
+ --aurum-border-radius-sm: ${r.sm}px;
2395
+ --aurum-border-radius-md: ${r.md}px;
2396
+ --aurum-border-radius-lg: ${r.lg}px;
2397
+ --aurum-border-radius-xl: ${r.xl}px;
2398
+ --aurum-border-radius: ${r.md}px;
2399
+ --aurum-modal-z-index: ${brandConfig.modalZIndex};
2400
+ --aurum-font-family: ${fontFamily};
2401
+ }
2402
+ `;
2403
+ }
2404
+ function generateCompleteStyles(brandConfig) {
2405
+ return `${bundledStyles}
2406
+ ${generateBrandCssVariables(brandConfig)}`;
2407
+ }
2408
+
2409
+ export {
2410
+ useAurumStore,
2411
+ waitForStoreHydration,
2412
+ useWidgetContext,
2413
+ WidgetProvider,
2414
+ DEFAULT_THEME,
2415
+ getDefaultThemeConfig,
2416
+ POWERED_BY_SPACER_REM,
2417
+ PageTransitionContainer,
2418
+ PoweredBy,
2419
+ Modal,
2420
+ Spacer,
2421
+ ThemeContainer,
2422
+ useNavigation,
2423
+ sortWallets,
2424
+ initSentry,
2425
+ sentryLogger,
2426
+ createConfigError,
2427
+ isMobile,
2428
+ ConnectUIProviders,
2429
+ ConnectPages,
2430
+ generateCompleteStyles
2431
+ };
2432
+ //# sourceMappingURL=chunk-U5BSED2R.mjs.map