@volr/react-ui 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +341 -0
- package/dist/index.cjs +3141 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +236 -0
- package/dist/index.d.ts +236 -0
- package/dist/index.js +3124 -0
- package/dist/index.js.map +1 -0
- package/package.json +82 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,3141 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var React3 = require('react');
|
|
4
|
+
var reactDom = require('react-dom');
|
|
5
|
+
var react = require('@volr/react');
|
|
6
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
7
|
+
var clsx = require('clsx');
|
|
8
|
+
var tailwindMerge = require('tailwind-merge');
|
|
9
|
+
|
|
10
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
11
|
+
|
|
12
|
+
var React3__default = /*#__PURE__*/_interopDefault(React3);
|
|
13
|
+
|
|
14
|
+
// src/providers/VolrUIProvider.tsx
|
|
15
|
+
|
|
16
|
+
// src/i18n/locales/en.ts
|
|
17
|
+
var en = {
|
|
18
|
+
common: {
|
|
19
|
+
back: "Back",
|
|
20
|
+
loading: "Loading..."
|
|
21
|
+
},
|
|
22
|
+
login: {
|
|
23
|
+
title: "Sign in",
|
|
24
|
+
description: "Choose your preferred sign-in method",
|
|
25
|
+
or: "or",
|
|
26
|
+
poweredBy: "Powered by Volr",
|
|
27
|
+
terms: "By continuing, you agree to our Terms of Service and Privacy Policy",
|
|
28
|
+
email: {
|
|
29
|
+
title: "Sign in with email",
|
|
30
|
+
description: "Enter your email to receive a verification code",
|
|
31
|
+
label: "Email Login",
|
|
32
|
+
emailLabel: "Email address",
|
|
33
|
+
placeholder: "Enter Email",
|
|
34
|
+
sendCode: "Send verification code",
|
|
35
|
+
codeLabel: "6-digit verification code",
|
|
36
|
+
codePlaceholder: "000000",
|
|
37
|
+
verifyTitle: "Enter verification code",
|
|
38
|
+
verifyDescription: "We sent a code to",
|
|
39
|
+
resend: "Resend code",
|
|
40
|
+
submit: "Verify"
|
|
41
|
+
},
|
|
42
|
+
social: {
|
|
43
|
+
google: "Sign in with Google",
|
|
44
|
+
twitter: "Sign in with Twitter",
|
|
45
|
+
apple: "Sign in with Apple"
|
|
46
|
+
},
|
|
47
|
+
wallet: {
|
|
48
|
+
title: "Sign in with wallet",
|
|
49
|
+
signDescription: "Sign the message to verify your wallet",
|
|
50
|
+
connected: "Connected",
|
|
51
|
+
connect: "Connect wallet",
|
|
52
|
+
sign: "Sign message",
|
|
53
|
+
label: "Wallet Login"
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
passkey: {
|
|
57
|
+
touchId: "Use Touch ID to create your passkey",
|
|
58
|
+
faceId: "Use Face ID to create your passkey",
|
|
59
|
+
fingerprint: "Use your fingerprint to create your passkey",
|
|
60
|
+
biometric: "Use biometric authentication to create your passkey",
|
|
61
|
+
creating: "Creating your secure passkey...",
|
|
62
|
+
encrypting: "Encrypting your wallet...",
|
|
63
|
+
uploading: "Uploading encrypted data...",
|
|
64
|
+
registering: "Registering wallet provider...",
|
|
65
|
+
start: "Create passkey",
|
|
66
|
+
logout: "Logout",
|
|
67
|
+
errors: {
|
|
68
|
+
cancelled: "Passkey creation was cancelled. Please try again.",
|
|
69
|
+
alreadyExists: "A passkey already exists for this account.",
|
|
70
|
+
notSupported: "Your device doesn't support passkeys.",
|
|
71
|
+
generic: "Failed to create passkey. Please try again."
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
success: {
|
|
75
|
+
title: "Success!",
|
|
76
|
+
message: "You're all set. Redirecting..."
|
|
77
|
+
},
|
|
78
|
+
deposit: {
|
|
79
|
+
selectTitle: "Select asset to deposit",
|
|
80
|
+
qrTitle: "Deposit",
|
|
81
|
+
scanInstruction: "Scan QR code to deposit",
|
|
82
|
+
yourAddress: "Your deposit address",
|
|
83
|
+
copy: "Copy address",
|
|
84
|
+
copied: "Copied!",
|
|
85
|
+
listening: "Waiting for deposit...",
|
|
86
|
+
detected: "Deposit confirmed!",
|
|
87
|
+
completed: "Deposit completed",
|
|
88
|
+
completedDescription: "Your deposit has been credited to your account.",
|
|
89
|
+
amount: "Amount",
|
|
90
|
+
previousBalance: "Previous balance",
|
|
91
|
+
newBalance: "New balance",
|
|
92
|
+
seeMore: "See more",
|
|
93
|
+
seeLess: "See less",
|
|
94
|
+
noAssets: "No deposit assets configured.",
|
|
95
|
+
otherToken: "Deposit with another token",
|
|
96
|
+
noToken: "Don't have this token?",
|
|
97
|
+
getOtherToken: "Deposit with another token"
|
|
98
|
+
},
|
|
99
|
+
errors: {
|
|
100
|
+
webauthnNotSupported: "WebAuthn API is not supported",
|
|
101
|
+
passkeyCreationFailed: "Failed to create passkey",
|
|
102
|
+
passkeyCreationError: "An error occurred while creating passkey",
|
|
103
|
+
emailLoginFailed: "Email login failed",
|
|
104
|
+
socialLoginFailed: "Social login failed",
|
|
105
|
+
walletConnectionFailed: "Wallet connection failed",
|
|
106
|
+
passkeySetupFailed: "Passkey setup failed"
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
// src/i18n/locales/ko.ts
|
|
111
|
+
var ko = {
|
|
112
|
+
common: {
|
|
113
|
+
back: "\uB4A4\uB85C",
|
|
114
|
+
loading: "\uB85C\uB529 \uC911..."
|
|
115
|
+
},
|
|
116
|
+
login: {
|
|
117
|
+
title: "\uB85C\uADF8\uC778",
|
|
118
|
+
description: "\uB85C\uADF8\uC778 \uBC29\uC2DD\uC744 \uC120\uD0DD\uD558\uC138\uC694",
|
|
119
|
+
or: "\uB610\uB294",
|
|
120
|
+
poweredBy: "Powered by Volr",
|
|
121
|
+
terms: "\uACC4\uC18D \uC9C4\uD589\uD558\uBA74 \uC11C\uBE44\uC2A4 \uC57D\uAD00 \uBC0F \uAC1C\uC778\uC815\uBCF4 \uBCF4\uD638\uC815\uCC45\uC5D0 \uB3D9\uC758\uD558\uB294 \uAC83\uC785\uB2C8\uB2E4",
|
|
122
|
+
email: {
|
|
123
|
+
title: "\uC774\uBA54\uC77C\uB85C \uB85C\uADF8\uC778",
|
|
124
|
+
description: "\uC778\uC99D \uCF54\uB4DC\uB97C \uBC1B\uC744 \uC774\uBA54\uC77C \uC8FC\uC18C\uB97C \uC785\uB825\uD558\uC138\uC694",
|
|
125
|
+
label: "\uC774\uBA54\uC77C \uB85C\uADF8\uC778",
|
|
126
|
+
emailLabel: "\uC774\uBA54\uC77C \uC8FC\uC18C",
|
|
127
|
+
placeholder: "\uC774\uBA54\uC77C \uC785\uB825",
|
|
128
|
+
sendCode: "\uC778\uC99D\uCF54\uB4DC \uC804\uC1A1",
|
|
129
|
+
codeLabel: "6\uC790\uB9AC \uC778\uC99D\uCF54\uB4DC",
|
|
130
|
+
codePlaceholder: "000000",
|
|
131
|
+
verifyTitle: "\uC778\uC99D\uCF54\uB4DC \uC785\uB825",
|
|
132
|
+
verifyDescription: "\uB2E4\uC74C \uC8FC\uC18C\uB85C \uCF54\uB4DC\uB97C \uC804\uC1A1\uD588\uC2B5\uB2C8\uB2E4",
|
|
133
|
+
resend: "\uCF54\uB4DC \uC7AC\uC804\uC1A1",
|
|
134
|
+
submit: "\uD655\uC778"
|
|
135
|
+
},
|
|
136
|
+
social: {
|
|
137
|
+
google: "\uAD6C\uAE00\uB85C \uB85C\uADF8\uC778",
|
|
138
|
+
twitter: "\uD2B8\uC704\uD130\uB85C \uB85C\uADF8\uC778",
|
|
139
|
+
apple: "\uC560\uD50C\uB85C \uB85C\uADF8\uC778"
|
|
140
|
+
},
|
|
141
|
+
wallet: {
|
|
142
|
+
title: "\uC9C0\uAC11\uC73C\uB85C \uB85C\uADF8\uC778",
|
|
143
|
+
signDescription: "\uBA54\uC2DC\uC9C0\uC5D0 \uC11C\uBA85\uD558\uC5EC \uC9C0\uAC11\uC744 \uC778\uC99D\uD558\uC138\uC694",
|
|
144
|
+
connected: "\uC5F0\uACB0\uB428",
|
|
145
|
+
connect: "\uC9C0\uAC11 \uC5F0\uACB0",
|
|
146
|
+
sign: "\uBA54\uC2DC\uC9C0 \uC11C\uBA85",
|
|
147
|
+
label: "\uC9C0\uAC11 \uB85C\uADF8\uC778"
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
passkey: {
|
|
151
|
+
touchId: "Touch ID\uB97C \uC0AC\uC6A9\uD558\uC5EC \uD328\uC2A4\uD0A4\uB97C \uC0DD\uC131\uD558\uC138\uC694",
|
|
152
|
+
faceId: "Face ID\uB97C \uC0AC\uC6A9\uD558\uC5EC \uD328\uC2A4\uD0A4\uB97C \uC0DD\uC131\uD558\uC138\uC694",
|
|
153
|
+
fingerprint: "\uC9C0\uBB38\uC744 \uC0AC\uC6A9\uD558\uC5EC \uD328\uC2A4\uD0A4\uB97C \uC0DD\uC131\uD558\uC138\uC694",
|
|
154
|
+
biometric: "\uC0DD\uCCB4 \uC778\uC99D\uC744 \uC0AC\uC6A9\uD558\uC5EC \uD328\uC2A4\uD0A4\uB97C \uC0DD\uC131\uD558\uC138\uC694",
|
|
155
|
+
creating: "\uBCF4\uC548 \uD328\uC2A4\uD0A4\uB97C \uC0DD\uC131\uD558\uB294 \uC911...",
|
|
156
|
+
encrypting: "\uC9C0\uAC11\uC744 \uC554\uD638\uD654\uD558\uB294 \uC911...",
|
|
157
|
+
uploading: "\uC554\uD638\uD654\uB41C \uB370\uC774\uD130\uB97C \uC5C5\uB85C\uB4DC\uD558\uB294 \uC911...",
|
|
158
|
+
registering: "\uC9C0\uAC11 \uACF5\uAE09\uC790\uB97C \uB4F1\uB85D\uD558\uB294 \uC911...",
|
|
159
|
+
start: "\uD328\uC2A4\uD0A4 \uC0DD\uC131",
|
|
160
|
+
logout: "\uB85C\uADF8\uC544\uC6C3",
|
|
161
|
+
errors: {
|
|
162
|
+
cancelled: "\uD328\uC2A4\uD0A4 \uC0DD\uC131\uC774 \uCDE8\uC18C\uB418\uC5C8\uC2B5\uB2C8\uB2E4. \uB2E4\uC2DC \uC2DC\uB3C4\uD574\uC8FC\uC138\uC694.",
|
|
163
|
+
alreadyExists: "\uC774\uBBF8 \uC774 \uACC4\uC815\uC5D0 \uD328\uC2A4\uD0A4\uAC00 \uC874\uC7AC\uD569\uB2C8\uB2E4.",
|
|
164
|
+
notSupported: "\uC774 \uAE30\uAE30\uB294 \uD328\uC2A4\uD0A4\uB97C \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.",
|
|
165
|
+
generic: "\uD328\uC2A4\uD0A4 \uC0DD\uC131\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4. \uB2E4\uC2DC \uC2DC\uB3C4\uD574\uC8FC\uC138\uC694."
|
|
166
|
+
}
|
|
167
|
+
},
|
|
168
|
+
success: {
|
|
169
|
+
title: "\uC644\uB8CC!",
|
|
170
|
+
message: "\uBAA8\uB4E0 \uC124\uC815\uC774 \uC644\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4. \uB9AC\uB2E4\uC774\uB809\uD2B8 \uC911..."
|
|
171
|
+
},
|
|
172
|
+
deposit: {
|
|
173
|
+
selectTitle: "\uCDA9\uC804\uD560 \uC790\uC0B0\uC744 \uC120\uD0DD\uD558\uC138\uC694",
|
|
174
|
+
qrTitle: "\uC785\uAE08\uD558\uAE30",
|
|
175
|
+
scanInstruction: "QR \uCF54\uB4DC\uB97C \uC2A4\uCE94\uD558\uC5EC \uC785\uAE08\uD558\uC138\uC694",
|
|
176
|
+
yourAddress: "Your deposit address",
|
|
177
|
+
copy: "\uC8FC\uC18C \uBCF5\uC0AC",
|
|
178
|
+
copied: "\uBCF5\uC0AC\uB418\uC5C8\uC2B5\uB2C8\uB2E4!",
|
|
179
|
+
listening: "\uC785\uAE08\uC744 \uAE30\uB2E4\uB9AC\uB294 \uC911...",
|
|
180
|
+
detected: "\uC785\uAE08\uC774 \uD655\uC778\uB418\uC5C8\uC2B5\uB2C8\uB2E4!",
|
|
181
|
+
completed: "\uC785\uAE08 \uC644\uB8CC",
|
|
182
|
+
completedDescription: "\uC785\uAE08\uC774 \uACC4\uC815\uC5D0 \uC785\uAE08\uB418\uC5C8\uC2B5\uB2C8\uB2E4.",
|
|
183
|
+
amount: "\uC785\uAE08 \uAE08\uC561",
|
|
184
|
+
previousBalance: "\uC774\uC804 \uC794\uC561",
|
|
185
|
+
newBalance: "\uC0C8 \uC794\uC561",
|
|
186
|
+
seeMore: "\uC790\uC138\uD788 \uBCF4\uAE30",
|
|
187
|
+
seeLess: "\uAC04\uB2E8\uD788 \uBCF4\uAE30",
|
|
188
|
+
noAssets: "\uC124\uC815\uB41C \uCDA9\uC804 \uC790\uC0B0\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.",
|
|
189
|
+
otherToken: "\uB2E4\uB978 \uD1A0\uD070\uC73C\uB85C \uCDA9\uC804\uD558\uAE30",
|
|
190
|
+
noToken: "\uC774 \uD1A0\uD070\uC774 \uC5C6\uC73C\uC2E0\uAC00\uC694?",
|
|
191
|
+
getOtherToken: "\uB2E4\uB978 \uD1A0\uD070\uC73C\uB85C \uC785\uAE08\uD558\uAE30"
|
|
192
|
+
},
|
|
193
|
+
errors: {
|
|
194
|
+
webauthnNotSupported: "WebAuthn API\uAC00 \uC9C0\uC6D0\uB418\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.",
|
|
195
|
+
passkeyCreationFailed: "\uD328\uC2A4\uD0A4 \uC0DD\uC131\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4.",
|
|
196
|
+
passkeyCreationError: "\uD328\uC2A4\uD0A4 \uC0DD\uC131 \uC911 \uBB38\uC81C\uAC00 \uBC1C\uC0DD\uD588\uC2B5\uB2C8\uB2E4.",
|
|
197
|
+
emailLoginFailed: "\uC774\uBA54\uC77C \uB85C\uADF8\uC778\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4.",
|
|
198
|
+
socialLoginFailed: "\uC18C\uC15C \uB85C\uADF8\uC778\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4.",
|
|
199
|
+
walletConnectionFailed: "\uC9C0\uAC11 \uC5F0\uACB0\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4.",
|
|
200
|
+
passkeySetupFailed: "\uD328\uC2A4\uD0A4 \uC124\uC815\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4."
|
|
201
|
+
}
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
// src/i18n/index.ts
|
|
205
|
+
var translations = {
|
|
206
|
+
en,
|
|
207
|
+
ko
|
|
208
|
+
};
|
|
209
|
+
function getTranslations(locale = "en") {
|
|
210
|
+
return translations[locale] || translations.en;
|
|
211
|
+
}
|
|
212
|
+
var I18nContext = React3.createContext(null);
|
|
213
|
+
function useI18n() {
|
|
214
|
+
const context = React3.useContext(I18nContext);
|
|
215
|
+
if (!context) {
|
|
216
|
+
return {
|
|
217
|
+
locale: "en",
|
|
218
|
+
translations: getTranslations("en"),
|
|
219
|
+
t: (key) => {
|
|
220
|
+
const translations2 = getTranslations("en");
|
|
221
|
+
const keys = key.split(".");
|
|
222
|
+
let value = translations2;
|
|
223
|
+
for (const k of keys) {
|
|
224
|
+
if (value && typeof value === "object" && k in value) {
|
|
225
|
+
value = value[k];
|
|
226
|
+
} else {
|
|
227
|
+
if (process.env.NODE_ENV !== "production") {
|
|
228
|
+
console.warn(`[i18n] Missing key: ${key} (locale: en)`);
|
|
229
|
+
}
|
|
230
|
+
return key;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
return typeof value === "string" ? value : key;
|
|
234
|
+
},
|
|
235
|
+
setLocale: () => {
|
|
236
|
+
}
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
return context;
|
|
240
|
+
}
|
|
241
|
+
function detectLocale() {
|
|
242
|
+
if (typeof window === "undefined" || !window.navigator?.language) {
|
|
243
|
+
return "en";
|
|
244
|
+
}
|
|
245
|
+
const lang = window.navigator.language.toLowerCase();
|
|
246
|
+
return lang.startsWith("ko") ? "ko" : "en";
|
|
247
|
+
}
|
|
248
|
+
function I18nProvider({ children }) {
|
|
249
|
+
const [locale, setLocale] = React3.useState(detectLocale());
|
|
250
|
+
const translations2 = React3.useMemo(() => getTranslations(locale), [locale]);
|
|
251
|
+
const t = React3.useMemo(() => {
|
|
252
|
+
return (key) => {
|
|
253
|
+
const keys = key.split(".");
|
|
254
|
+
let value2 = translations2;
|
|
255
|
+
for (const k of keys) {
|
|
256
|
+
if (value2 && typeof value2 === "object" && k in value2) {
|
|
257
|
+
value2 = value2[k];
|
|
258
|
+
} else {
|
|
259
|
+
if (process.env.NODE_ENV !== "production") {
|
|
260
|
+
console.warn(`[i18n] Missing key: ${key} (locale: ${locale})`);
|
|
261
|
+
}
|
|
262
|
+
return key;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
return typeof value2 === "string" ? value2 : key;
|
|
266
|
+
};
|
|
267
|
+
}, [translations2]);
|
|
268
|
+
const value = React3.useMemo(
|
|
269
|
+
() => ({
|
|
270
|
+
locale,
|
|
271
|
+
translations: translations2,
|
|
272
|
+
t,
|
|
273
|
+
setLocale
|
|
274
|
+
}),
|
|
275
|
+
[locale, translations2, t, setLocale]
|
|
276
|
+
);
|
|
277
|
+
return /* @__PURE__ */ jsxRuntime.jsx(I18nContext.Provider, { value, children });
|
|
278
|
+
}
|
|
279
|
+
var useTranslation = useI18n;
|
|
280
|
+
var VolrModalContext = React3.createContext(null);
|
|
281
|
+
var useVolrModal = () => {
|
|
282
|
+
const context = React3.useContext(VolrModalContext);
|
|
283
|
+
if (!context) {
|
|
284
|
+
throw new Error("useVolrModal must be used within VolrUIProvider");
|
|
285
|
+
}
|
|
286
|
+
return context;
|
|
287
|
+
};
|
|
288
|
+
var VolrModalProvider = ({
|
|
289
|
+
children
|
|
290
|
+
}) => {
|
|
291
|
+
const [isOpen, setIsOpen] = React3.useState(false);
|
|
292
|
+
const [mode, setMode] = React3.useState("auth");
|
|
293
|
+
const { user } = react.useVolr();
|
|
294
|
+
const open = React3.useCallback(() => {
|
|
295
|
+
setMode(user ? "deposit" : "auth");
|
|
296
|
+
setIsOpen(true);
|
|
297
|
+
}, [user]);
|
|
298
|
+
const close = React3.useCallback(() => {
|
|
299
|
+
setIsOpen(false);
|
|
300
|
+
}, []);
|
|
301
|
+
const toggle = React3.useCallback(() => {
|
|
302
|
+
setIsOpen((prev) => !prev);
|
|
303
|
+
}, []);
|
|
304
|
+
return /* @__PURE__ */ jsxRuntime.jsx(VolrModalContext.Provider, { value: { isOpen, mode, open, close, toggle }, children });
|
|
305
|
+
};
|
|
306
|
+
function cn(...inputs) {
|
|
307
|
+
return tailwindMerge.twMerge(clsx.clsx(inputs));
|
|
308
|
+
}
|
|
309
|
+
function useMediaQuery(query) {
|
|
310
|
+
const [matches, setMatches] = React3.useState(() => {
|
|
311
|
+
if (typeof window === "undefined") return false;
|
|
312
|
+
return window.matchMedia(query).matches;
|
|
313
|
+
});
|
|
314
|
+
React3.useEffect(() => {
|
|
315
|
+
if (typeof window === "undefined") return;
|
|
316
|
+
const mql = window.matchMedia(query);
|
|
317
|
+
const handler = (event) => setMatches(event.matches);
|
|
318
|
+
mql.addEventListener("change", handler);
|
|
319
|
+
setMatches(mql.matches);
|
|
320
|
+
return () => mql.removeEventListener("change", handler);
|
|
321
|
+
}, [query]);
|
|
322
|
+
return matches;
|
|
323
|
+
}
|
|
324
|
+
var Modal = ({
|
|
325
|
+
open,
|
|
326
|
+
onOpenChange,
|
|
327
|
+
children,
|
|
328
|
+
className,
|
|
329
|
+
onPointerDownOutside,
|
|
330
|
+
onEscapeKeyDown,
|
|
331
|
+
variant: explicitVariant,
|
|
332
|
+
contentClassName
|
|
333
|
+
}) => {
|
|
334
|
+
const isMobile = useMediaQuery("(max-width: 500px)");
|
|
335
|
+
const variant = explicitVariant ?? (isMobile ? "bottom-sheet" : "centered");
|
|
336
|
+
React3__default.default.useEffect(() => {
|
|
337
|
+
const handleEscape = (e) => {
|
|
338
|
+
if (e.key === "Escape" && open) {
|
|
339
|
+
if (onEscapeKeyDown) {
|
|
340
|
+
onEscapeKeyDown(e);
|
|
341
|
+
} else {
|
|
342
|
+
onOpenChange(false);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
};
|
|
346
|
+
if (open) {
|
|
347
|
+
document.addEventListener("keydown", handleEscape);
|
|
348
|
+
}
|
|
349
|
+
return () => document.removeEventListener("keydown", handleEscape);
|
|
350
|
+
}, [open, onOpenChange, onEscapeKeyDown]);
|
|
351
|
+
if (!open) return null;
|
|
352
|
+
const isBottomSheet = variant === "bottom-sheet";
|
|
353
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
354
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
355
|
+
"div",
|
|
356
|
+
{
|
|
357
|
+
className: "volr:fixed volr:inset-0 volr:z-40 volr:bg-black/45",
|
|
358
|
+
onClick: (e) => {
|
|
359
|
+
if (onPointerDownOutside) {
|
|
360
|
+
onPointerDownOutside(e);
|
|
361
|
+
} else {
|
|
362
|
+
onOpenChange(false);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
),
|
|
367
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
368
|
+
"div",
|
|
369
|
+
{
|
|
370
|
+
className: cn(
|
|
371
|
+
"volr:fixed volr:inset-0 volr:z-50 volr:flex volr:items-center volr:justify-center",
|
|
372
|
+
isBottomSheet && "volr:items-end"
|
|
373
|
+
),
|
|
374
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
375
|
+
"div",
|
|
376
|
+
{
|
|
377
|
+
className: cn(
|
|
378
|
+
"volr:bg-white volr:border volr:border-slate-300 volr:shadow-xl volr:overflow-y-auto volr:relative volr:w-full",
|
|
379
|
+
isBottomSheet ? "volr:max-w-full volr:max-h-[85vh] volr:rounded-t-3xl volr:px-4 volr:py-6 volr:shadow-2xl" : "volr:rounded-2xl volr:p-5 volr:max-w-md volr:w-full volr:max-h-[90vh]",
|
|
380
|
+
className,
|
|
381
|
+
contentClassName
|
|
382
|
+
),
|
|
383
|
+
onClick: (e) => e.stopPropagation(),
|
|
384
|
+
children
|
|
385
|
+
}
|
|
386
|
+
)
|
|
387
|
+
}
|
|
388
|
+
)
|
|
389
|
+
] });
|
|
390
|
+
};
|
|
391
|
+
var ModalHeader = ({
|
|
392
|
+
className,
|
|
393
|
+
back = false,
|
|
394
|
+
onBack,
|
|
395
|
+
onClose,
|
|
396
|
+
children,
|
|
397
|
+
...props
|
|
398
|
+
}) => {
|
|
399
|
+
const { t } = useI18n();
|
|
400
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
401
|
+
"div",
|
|
402
|
+
{
|
|
403
|
+
className: cn(
|
|
404
|
+
"volr:flex volr:items-center volr:justify-between volr:mb-3",
|
|
405
|
+
className
|
|
406
|
+
),
|
|
407
|
+
...props,
|
|
408
|
+
children: [
|
|
409
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "volr:flex volr:items-center volr:gap-4 volr:flex-1", children: [
|
|
410
|
+
back && onBack && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
411
|
+
"button",
|
|
412
|
+
{
|
|
413
|
+
onClick: onBack,
|
|
414
|
+
className: "volr:p-2 volr:-ml-2 volr:rounded-lg volr:text-slate-500 hover:volr:text-slate-700 hover:volr:bg-slate-100 volr:transition-colors volr:flex volr:items-center volr:gap-1",
|
|
415
|
+
type: "button",
|
|
416
|
+
children: [
|
|
417
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
418
|
+
"svg",
|
|
419
|
+
{
|
|
420
|
+
width: "20",
|
|
421
|
+
height: "20",
|
|
422
|
+
viewBox: "0 0 24 24",
|
|
423
|
+
fill: "none",
|
|
424
|
+
stroke: "currentColor",
|
|
425
|
+
strokeWidth: "2",
|
|
426
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M19 12H5M12 19l-7-7 7-7" })
|
|
427
|
+
}
|
|
428
|
+
),
|
|
429
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "volr:text-sm volr:font-medium", children: t("common.back") })
|
|
430
|
+
]
|
|
431
|
+
}
|
|
432
|
+
),
|
|
433
|
+
children
|
|
434
|
+
] }),
|
|
435
|
+
onClose && /* @__PURE__ */ jsxRuntime.jsx(
|
|
436
|
+
"button",
|
|
437
|
+
{
|
|
438
|
+
type: "button",
|
|
439
|
+
onClick: onClose,
|
|
440
|
+
className: "volr:p-1 volr:rounded-lg volr:text-slate-400 hover:volr:text-slate-600 hover:volr:bg-slate-100 volr:transition-colors",
|
|
441
|
+
"aria-label": "Close",
|
|
442
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
443
|
+
"svg",
|
|
444
|
+
{
|
|
445
|
+
width: "20",
|
|
446
|
+
height: "20",
|
|
447
|
+
viewBox: "0 0 24 24",
|
|
448
|
+
fill: "none",
|
|
449
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
450
|
+
stroke: "currentColor",
|
|
451
|
+
strokeWidth: "2",
|
|
452
|
+
strokeLinecap: "round",
|
|
453
|
+
strokeLinejoin: "round",
|
|
454
|
+
children: [
|
|
455
|
+
/* @__PURE__ */ jsxRuntime.jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
|
|
456
|
+
/* @__PURE__ */ jsxRuntime.jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
|
|
457
|
+
]
|
|
458
|
+
}
|
|
459
|
+
)
|
|
460
|
+
}
|
|
461
|
+
)
|
|
462
|
+
]
|
|
463
|
+
}
|
|
464
|
+
);
|
|
465
|
+
};
|
|
466
|
+
var ModalTitle = ({
|
|
467
|
+
className,
|
|
468
|
+
...props
|
|
469
|
+
}) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
470
|
+
"h2",
|
|
471
|
+
{
|
|
472
|
+
className: cn(
|
|
473
|
+
"volr:text-lg volr:font-semibold volr:leading-none volr:tracking-tight",
|
|
474
|
+
className
|
|
475
|
+
),
|
|
476
|
+
...props
|
|
477
|
+
}
|
|
478
|
+
);
|
|
479
|
+
var sizeClasses = {
|
|
480
|
+
xl: "volr:text-xl",
|
|
481
|
+
"2xl": "volr:text-2xl",
|
|
482
|
+
"3xl": "volr:text-3xl"
|
|
483
|
+
};
|
|
484
|
+
var spacingClasses = {
|
|
485
|
+
tight: "volr:mb-3",
|
|
486
|
+
normal: "volr:mb-5",
|
|
487
|
+
loose: "volr:mb-7"
|
|
488
|
+
};
|
|
489
|
+
function ModalTitle2({
|
|
490
|
+
children,
|
|
491
|
+
size = "2xl",
|
|
492
|
+
spacing = "normal",
|
|
493
|
+
as: Component = "h2",
|
|
494
|
+
className = ""
|
|
495
|
+
}) {
|
|
496
|
+
const sizeClass = sizeClasses[size];
|
|
497
|
+
const spacingClass = spacingClasses[spacing];
|
|
498
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
499
|
+
Component,
|
|
500
|
+
{
|
|
501
|
+
className: `volr:font-bold volr:text-slate-900 ${sizeClass} ${spacingClass} ${className}`,
|
|
502
|
+
children
|
|
503
|
+
}
|
|
504
|
+
);
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
// src/components/features/passkey/utils/biometric.ts
|
|
508
|
+
function getBiometricType() {
|
|
509
|
+
const ua = navigator.userAgent;
|
|
510
|
+
if (/iPhone|iPad|iPod/.test(ua)) {
|
|
511
|
+
return "faceId";
|
|
512
|
+
}
|
|
513
|
+
if (/Macintosh|MacIntel/.test(ua)) {
|
|
514
|
+
return "touchId";
|
|
515
|
+
}
|
|
516
|
+
return "fingerprint";
|
|
517
|
+
}
|
|
518
|
+
function getUserFriendlyError(error, t) {
|
|
519
|
+
const msg = error.message.toLowerCase();
|
|
520
|
+
if (msg.includes("timed out") || msg.includes("not allowed") || msg.includes("cancelled")) {
|
|
521
|
+
return t("passkey.errors.cancelled");
|
|
522
|
+
}
|
|
523
|
+
if (msg.includes("already registered") || msg.includes("already exists")) {
|
|
524
|
+
return t("passkey.errors.alreadyExists");
|
|
525
|
+
}
|
|
526
|
+
if (msg.includes("not supported")) {
|
|
527
|
+
return t("passkey.errors.notSupported");
|
|
528
|
+
}
|
|
529
|
+
return t("passkey.errors.generic");
|
|
530
|
+
}
|
|
531
|
+
function WalletConnectedView({ user }) {
|
|
532
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "volr:text-center", children: [
|
|
533
|
+
/* @__PURE__ */ jsxRuntime.jsx(ModalTitle2, { size: "3xl", children: "Wallet Connected" }),
|
|
534
|
+
user.evmAddress ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "volr:bg-slate-50 volr:rounded-lg volr:p-5 volr:mb-6 volr:text-left", children: [
|
|
535
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "volr:mb-3", children: [
|
|
536
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "volr:text-xs volr:text-slate-500 volr:mb-1 volr:font-medium", children: "Wallet Address" }),
|
|
537
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "volr:text-sm volr:text-slate-900 volr:font-mono volr:break-all", children: user.evmAddress })
|
|
538
|
+
] }),
|
|
539
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
540
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "volr:text-xs volr:text-slate-500 volr:mb-1 volr:font-medium", children: "Key Storage Type" }),
|
|
541
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "volr:text-sm volr:text-slate-900 volr:capitalize", children: user.keyStorageType })
|
|
542
|
+
] })
|
|
543
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "volr:bg-slate-50 volr:rounded-lg volr:p-5 volr:mb-6 volr:text-left", children: [
|
|
544
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "volr:text-sm volr:text-slate-500 volr:mb-2", children: "Passkey is set up" }),
|
|
545
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "volr:text-xs volr:text-slate-400", children: "Wallet address will be available after provider is restored." })
|
|
546
|
+
] })
|
|
547
|
+
] });
|
|
548
|
+
}
|
|
549
|
+
function FaceIdIcon({ size }) {
|
|
550
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
551
|
+
"svg",
|
|
552
|
+
{
|
|
553
|
+
width: size,
|
|
554
|
+
height: size,
|
|
555
|
+
viewBox: "0 0 24 24",
|
|
556
|
+
fill: "none",
|
|
557
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
558
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
559
|
+
"path",
|
|
560
|
+
{
|
|
561
|
+
d: "M7.5,3 C7.77614237,3 8,3.22385763 8,3.5 C8,3.77614237 7.77614237,4 7.5,4 L5.5,4 C4.67157288,4 4,4.67157288 4,5.5 L4,7.53112887 C4,7.80727125 3.77614237,8.03112887 3.5,8.03112887 C3.22385763,8.03112887 3,7.80727125 3,7.53112887 L3,5.5 C3,4.11928813 4.11928813,3 5.5,3 L7.5,3 Z M16.5,4 C16.2238576,4 16,3.77614237 16,3.5 C16,3.22385763 16.2238576,3 16.5,3 L18.5,3 C19.8807119,3 21,4.11928813 21,5.5 L21,7.5 C21,7.77614237 20.7761424,8 20.5,8 C20.2238576,8 20,7.77614237 20,7.5 L20,5.5 C20,4.67157288 19.3284271,4 18.5,4 L16.5,4 Z M20,16.5 C20,16.2238576 20.2238576,16 20.5,16 C20.7761424,16 21,16.2238576 21,16.5 L21,18.5 C21,19.8807119 19.8807119,21 18.5,21 L16.5,21 C16.2238576,21 16,20.7761424 16,20.5 C16,20.2238576 16.2238576,20 16.5,20 L18.5,20 C19.3284271,20 20,19.3284271 20,18.5 L20,16.5 Z M3,16.5 C3,16.2238576 3.22385763,16 3.5,16 C3.77614237,16 4,16.2238576 4,16.5 L4,18.5 C4,19.3284271 4.67157288,20 5.5,20 L7.5,20 C7.77614237,20 8,20.2238576 8,20.5 C8,20.7761424 7.77614237,21 7.5,21 L5.5,21 C4.11928813,21 3,19.8807119 3,18.5 L3,16.5 Z M8,8.5 C8,8.22385763 8.22385763,8 8.5,8 C8.77614237,8 9,8.22385763 9,8.5 L9,9.5 C9,9.77614237 8.77614237,10 8.5,10 C8.22385763,10 8,9.77614237 8,9.5 L8,8.5 Z M16,8.5 C16,8.22385763 16.2238576,8 16.5,8 C16.7761424,8 17,8.22385763 17,8.5 L17,9.5 C17,9.77614237 16.7761424,10 16.5,10 C16.2238576,10 16,9.77614237 16,9.5 L16,8.5 Z M12,8.5 C12,8.22385763 12.2238576,8 12.5,8 C12.7761424,8 13,8.22385763 13,8.5 L13,12.5 C13,13.3284271 12.3284271,14 11.5,14 C11.2238576,14 11,13.7761424 11,13.5 C11,13.2238576 11.2238576,13 11.5,13 C11.7761424,13 12,12.7761424 12,12.5 L12,8.5 Z M8.1,15.8 C7.93431458,15.5790861 7.9790861,15.2656854 8.2,15.1 C8.4209139,14.9343146 8.73431458,14.9790861 8.9,15.2 C9.81096778,16.4146237 10.8353763,17 12,17 C13.1646237,17 14.1890322,16.4146237 15.1,15.2 C15.2656854,14.9790861 15.5790861,14.9343146 15.8,15.1 C16.0209139,15.2656854 16.0656854,15.5790861 15.9,15.8 C14.8109678,17.252043 13.502043,18 12,18 C10.497957,18 9.18903222,17.252043 8.1,15.8 Z",
|
|
562
|
+
fill: "#3b82f6"
|
|
563
|
+
}
|
|
564
|
+
)
|
|
565
|
+
}
|
|
566
|
+
);
|
|
567
|
+
}
|
|
568
|
+
function TouchIdIcon({ size }) {
|
|
569
|
+
const fill = "#ef4444";
|
|
570
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
571
|
+
"svg",
|
|
572
|
+
{
|
|
573
|
+
width: size,
|
|
574
|
+
height: size,
|
|
575
|
+
viewBox: "0 0 24 24",
|
|
576
|
+
fill: "none",
|
|
577
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
578
|
+
children: [
|
|
579
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
580
|
+
"path",
|
|
581
|
+
{
|
|
582
|
+
d: "M18.4558 14.6734C18.4921 15.5205 18.3742 16.4404 18.2653 17.3604C18.2562 17.4514 18.238 17.5425 18.2108 17.6245C18.1564 17.8613 18.0384 18.0708 17.7571 18.0252C17.4759 17.9706 17.4123 17.7429 17.4577 17.497C17.5484 16.8958 17.5938 16.2947 17.6483 15.6936C17.8025 13.9539 17.6483 12.2325 17.2218 10.5474C16.5322 7.84233 13.801 6.12999 11.0879 6.62183C8.28416 7.13189 6.33331 9.63663 6.58737 12.4419C6.65996 13.2435 6.88681 14.0268 6.83237 14.8374C6.82329 15.0013 6.82329 15.1744 6.787 15.3383C6.74163 15.5569 6.63274 15.7573 6.3696 15.73C6.08832 15.7027 5.98851 15.4841 6.01573 15.2382C6.05202 14.8465 6.07925 14.4548 6.0248 14.0632C5.8887 13.0158 5.68908 11.9683 5.8887 10.9027C6.4422 7.96073 9.00099 5.77477 11.9681 5.75656C14.8898 5.73834 17.5121 7.89698 18.0838 10.8025C18.3288 12.0503 18.483 13.3163 18.4558 14.6734Z",
|
|
583
|
+
fill
|
|
584
|
+
}
|
|
585
|
+
),
|
|
586
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
587
|
+
"path",
|
|
588
|
+
{
|
|
589
|
+
d: "M21.0963 11.112C21.1053 11.4399 21.1235 11.7132 20.7877 11.7496C20.4702 11.786 20.3885 11.531 20.3431 11.276C20.1344 9.84601 19.7443 8.47978 18.8913 7.29572C16.7772 4.35379 13.9099 3.19705 10.3802 3.78908C7.16809 4.32646 4.55485 6.95872 3.8471 10.183C3.78359 10.4745 3.79266 10.9208 3.3299 10.8206C2.83992 10.7204 3.03047 10.3014 3.10306 9.99174C3.99228 6.10255 7.24975 3.26992 11.1242 2.88737C15.7337 2.43197 20.1617 5.63804 20.9874 10.5018C21.0327 10.7386 21.069 10.9663 21.0963 11.112Z",
|
|
590
|
+
fill
|
|
591
|
+
}
|
|
592
|
+
),
|
|
593
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
594
|
+
"path",
|
|
595
|
+
{
|
|
596
|
+
d: "M12.1405 2.22257C7.19532 2.04952 2.73105 5.82029 2.23199 11.2123C2.14126 12.2051 2.27736 13.1797 2.43161 14.1543C2.58587 15.0924 2.30458 15.9212 1.72386 16.659C1.56054 16.8685 1.35184 17.078 1.07963 16.8503C0.798344 16.6226 0.961671 16.3858 1.13407 16.1763C1.68757 15.5023 1.76016 14.7281 1.61498 13.8992C0.607796 7.85141 4.50042 2.44117 10.5617 1.50303C11.4418 1.3664 12.3401 1.32997 13.2293 1.4757C13.4834 1.52124 13.7375 1.585 13.7193 1.90378C13.6921 2.259 13.4199 2.24989 13.1477 2.24079C12.812 2.21346 12.4762 2.22257 12.1405 2.22257Z",
|
|
597
|
+
fill
|
|
598
|
+
}
|
|
599
|
+
),
|
|
600
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
601
|
+
"path",
|
|
602
|
+
{
|
|
603
|
+
d: "M14.1094 14.6278C14.064 17.9432 13.075 20.9398 11.0969 23.6085C10.9335 23.8271 10.7521 24.1003 10.4345 23.8726C10.1351 23.654 10.2802 23.399 10.4526 23.1622C11.9498 21.1402 12.8844 18.8813 13.2111 16.3766C13.4107 14.8373 13.3472 13.3254 13.0477 11.8134C12.9207 11.1667 12.3581 10.8297 11.723 10.9664C11.1876 11.0848 10.8519 11.6221 10.9698 12.2324C11.2511 13.7261 11.2874 15.2108 11.0152 16.7045C10.9608 17.0051 10.9608 17.4423 10.5162 17.3785C10.0625 17.3147 10.1986 16.914 10.253 16.6043C10.4889 15.229 10.498 13.8627 10.2258 12.4965C9.98988 11.3034 10.6069 10.3834 11.7502 10.1739C12.7392 9.99178 13.6466 10.7022 13.8553 11.8316C13.9188 12.1777 13.9823 12.5147 14.0095 12.8609C14.0549 13.4438 14.1457 14.0358 14.1094 14.6278Z",
|
|
604
|
+
fill
|
|
605
|
+
}
|
|
606
|
+
),
|
|
607
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
608
|
+
"path",
|
|
609
|
+
{
|
|
610
|
+
d: "M22.8111 14.6825C22.8564 15.484 22.7748 16.3402 22.684 17.1963C22.6568 17.4787 22.6477 17.8885 22.2122 17.8248C21.7948 17.761 21.8765 17.3876 21.9128 17.087C22.2122 14.5732 22.1033 12.0775 21.4863 9.63656C20.6424 6.25743 18.5192 3.98039 15.2799 2.73257C15.2073 2.70525 15.1347 2.68703 15.0621 2.65971C14.8443 2.56863 14.6719 2.432 14.7536 2.17698C14.8443 1.90373 15.0712 1.87641 15.3162 1.94927C15.9423 2.14054 16.5411 2.39557 17.1037 2.72347C20.2704 4.55421 22.0307 7.33219 22.5388 10.939C22.7112 12.1595 22.8473 13.38 22.8111 14.6825Z",
|
|
611
|
+
fill
|
|
612
|
+
}
|
|
613
|
+
),
|
|
614
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
615
|
+
"path",
|
|
616
|
+
{
|
|
617
|
+
d: "M11.8227 7.21389C12.0042 7.21389 12.0677 7.20478 12.1221 7.21389C12.3853 7.24121 12.6847 7.28675 12.6938 7.61465C12.7029 7.97897 12.3944 8.02451 12.104 8.02451C10.5796 7.99719 9.41817 8.63476 8.61061 9.91901C8.07526 10.7752 7.90286 11.7133 8.09341 12.7152C8.70135 16.0033 7.81212 18.8359 5.4711 21.204C5.38944 21.286 5.2987 21.3771 5.19889 21.4499C4.99927 21.6139 4.7815 21.6685 4.60002 21.4499C4.42762 21.2496 4.51836 21.0492 4.68169 20.8852C5.17167 20.4116 5.6435 19.9198 6.0246 19.3551C7.28585 17.4697 7.81212 15.4021 7.35844 13.1706C6.7505 10.1103 8.80116 7.3414 11.8227 7.21389Z",
|
|
618
|
+
fill
|
|
619
|
+
}
|
|
620
|
+
),
|
|
621
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
622
|
+
"path",
|
|
623
|
+
{
|
|
624
|
+
d: "M17.0128 14.3092C17.0037 17.7065 16.2415 20.6303 14.7171 23.3627C14.6899 23.4173 14.6627 23.472 14.6264 23.5175C14.4812 23.7543 14.2907 23.9001 14.0275 23.7361C13.7825 23.5904 13.8279 23.3536 13.9549 23.135C14.2635 22.5976 14.5357 22.042 14.7897 21.4682C15.7969 19.2003 16.2597 16.823 16.2415 14.3456C16.2324 13.2435 16.1145 12.1323 15.8604 11.0576C15.6517 10.1377 15.1618 9.39078 14.4086 8.81697C14.2544 8.69856 14.082 8.58926 13.9368 8.47086C13.7825 8.34334 13.6918 8.18851 13.8098 7.99723C13.9277 7.79686 14.1092 7.75131 14.3179 7.8515C14.826 8.10653 15.2434 8.46175 15.6154 8.89894C16.3504 9.76422 16.668 10.7934 16.8132 11.8955C16.9221 12.7881 17.04 13.6716 17.0128 14.3092Z",
|
|
625
|
+
fill
|
|
626
|
+
}
|
|
627
|
+
),
|
|
628
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
629
|
+
"path",
|
|
630
|
+
{
|
|
631
|
+
d: "M12.0223 0.0183811C13.7554 -0.100025 15.3796 0.309842 16.9493 1.01117C16.9947 1.02939 17.031 1.0476 17.0763 1.06582C17.3395 1.17512 17.5572 1.32996 17.4302 1.64874C17.2941 1.97664 17.0219 1.88555 16.7769 1.76715C15.924 1.36639 15.0348 1.0476 14.1092 0.910981C9.6994 0.218761 6.03362 1.56677 3.16632 5.02787C2.97577 5.26468 2.80337 5.67455 2.42227 5.39219C2.01396 5.09163 2.37691 4.79106 2.56745 4.54514C4.62719 1.96753 7.30394 0.464681 10.5705 0.0274892C11.0423 -0.0362679 11.5323 0.0183811 12.0223 0.0183811Z",
|
|
632
|
+
fill
|
|
633
|
+
}
|
|
634
|
+
),
|
|
635
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
636
|
+
"path",
|
|
637
|
+
{
|
|
638
|
+
d: "M19.9166 14.3454C19.9257 16.9595 19.5264 19.2456 18.7461 21.468C18.6916 21.6137 18.6372 21.7504 18.5827 21.8961C18.492 22.1329 18.3378 22.306 18.0655 22.2058C17.8024 22.1056 17.7752 21.887 17.8659 21.6411C17.9839 21.2949 18.1018 20.9579 18.2107 20.6027C18.8822 18.5078 19.2179 16.3492 19.1362 14.145C19.0637 12.287 18.9638 10.4107 18.0565 8.70747C17.9204 8.45244 17.757 8.21563 17.6119 7.9606C17.4939 7.75112 17.4757 7.54163 17.6844 7.3959C17.9113 7.23195 18.0837 7.35946 18.2289 7.54163C18.9003 8.43423 19.2996 9.44523 19.5173 10.52C19.7805 11.8771 19.9438 13.2251 19.9166 14.3454Z",
|
|
639
|
+
fill
|
|
640
|
+
}
|
|
641
|
+
),
|
|
642
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
643
|
+
"path",
|
|
644
|
+
{
|
|
645
|
+
d: "M4.61846 14.4365C4.57309 14.136 4.50958 13.6714 4.44606 13.2069C4.06496 10.4471 4.90882 8.12457 6.94133 6.23007C7.01392 6.15721 7.10466 6.09345 7.18632 6.02969C7.35872 5.9204 7.53112 5.92039 7.6763 6.07523C7.83056 6.23007 7.80334 6.41224 7.6763 6.56707C7.55835 6.7037 7.42224 6.83121 7.29521 6.95873C5.48954 8.74392 4.80901 10.8843 5.26269 13.3891C5.64379 15.4931 5.07215 17.3238 3.66572 18.8995C3.48425 19.0999 3.26648 19.273 3.04871 19.4369C2.88538 19.5553 2.70391 19.5644 2.55873 19.4005C2.40447 19.2183 2.44077 19.0361 2.59502 18.8722C2.73113 18.7265 2.87631 18.599 3.01241 18.4532C4.05589 17.3785 4.57309 16.0942 4.61846 14.4365Z",
|
|
646
|
+
fill
|
|
647
|
+
}
|
|
648
|
+
),
|
|
649
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
650
|
+
"path",
|
|
651
|
+
{
|
|
652
|
+
d: "M12.6577 14.6552C12.5942 17.8886 11.5688 20.7668 9.50003 23.2715C9.45466 23.3262 9.40929 23.3899 9.35485 23.4446C9.18245 23.6358 8.97376 23.7269 8.76506 23.5448C8.56544 23.3808 8.61081 23.1622 8.75599 22.971C9.00098 22.6431 9.26412 22.3334 9.50003 21.9964C11.0335 19.856 11.7957 17.4514 11.8955 14.8192C11.9227 13.9994 11.8138 13.1888 11.6868 12.3782C11.6687 12.2871 11.6505 12.196 11.6414 12.1049C11.6233 11.8681 11.6868 11.6677 11.9499 11.6313C12.2131 11.5858 12.3401 11.7497 12.3855 11.9865C12.567 12.87 12.6668 13.7626 12.6577 14.6552Z",
|
|
653
|
+
fill
|
|
654
|
+
}
|
|
655
|
+
),
|
|
656
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
657
|
+
"path",
|
|
658
|
+
{
|
|
659
|
+
d: "M23.9998 11.5857C23.9998 11.7679 23.9998 11.95 23.9998 12.1322C23.9998 12.369 23.9363 12.5694 23.655 12.5785C23.3737 12.5876 23.2648 12.3872 23.2467 12.1322C23.2285 11.6768 23.2195 11.2214 23.165 10.7751C22.7839 7.55078 21.2868 4.95495 18.7371 2.96937C18.5102 2.78721 18.1382 2.61415 18.3923 2.25894C18.6373 1.92193 18.9367 2.17696 19.1726 2.35913C22.2214 4.6726 23.773 7.77848 23.9998 11.5857Z",
|
|
660
|
+
fill
|
|
661
|
+
}
|
|
662
|
+
),
|
|
663
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
664
|
+
"path",
|
|
665
|
+
{
|
|
666
|
+
d: "M15.5522 14.0449C15.5522 14.1815 15.5522 14.3181 15.5522 14.4547C15.5431 14.7007 15.4615 14.9284 15.1711 14.9284C14.8807 14.9284 14.8082 14.7098 14.7991 14.4547C14.7537 13.5348 14.6811 12.6149 14.5178 11.7041C14.1821 9.86423 12.3583 8.92609 10.7794 9.79137C10.2532 10.0828 9.85391 10.52 9.64521 11.1029C9.61799 11.1758 9.59077 11.2487 9.57262 11.3215C9.49096 11.5766 9.39115 11.8498 9.05542 11.7496C8.69247 11.6403 8.76506 11.3306 8.84673 11.0665C9.20967 9.95532 9.9265 9.17201 11.0516 8.84412C12.9662 8.27941 14.8082 9.40883 15.2437 11.3944C15.4342 12.2597 15.5068 13.1523 15.5522 14.0449Z",
|
|
667
|
+
fill
|
|
668
|
+
}
|
|
669
|
+
),
|
|
670
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
671
|
+
"path",
|
|
672
|
+
{
|
|
673
|
+
d: "M9.73564 14.6279C9.69934 17.497 8.67401 19.9653 6.70502 22.0511C6.6415 22.1149 6.57799 22.1786 6.51447 22.2424C6.32392 22.4245 6.09708 22.5338 5.87931 22.3152C5.64339 22.0875 5.7795 21.8689 5.97005 21.6868C6.62335 21.0492 7.17685 20.3388 7.63961 19.5464C8.65587 17.7794 9.11863 15.8849 8.93715 13.8355C8.92808 13.6807 8.919 13.535 8.919 13.3801C8.90993 13.1342 8.97345 12.8974 9.25473 12.8792C9.54509 12.8519 9.63583 13.0705 9.67212 13.3164C9.69934 13.4985 9.73564 13.6716 9.74471 13.8538C9.74471 14.1088 9.73564 14.3638 9.73564 14.6279Z",
|
|
674
|
+
fill
|
|
675
|
+
}
|
|
676
|
+
),
|
|
677
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
678
|
+
"path",
|
|
679
|
+
{
|
|
680
|
+
d: "M0.00881775 12.0866C-0.0274771 10.1648 0.389914 8.4616 1.15211 6.83124C1.20655 6.70372 1.27007 6.58532 1.35173 6.47602C1.46061 6.33029 1.61487 6.25742 1.78727 6.3485C1.97782 6.43959 2.05041 6.60353 1.97782 6.80391C1.88708 7.05894 1.76912 7.30486 1.66024 7.55989C0.743789 9.72763 0.516946 11.9682 0.997854 14.2817C1.06137 14.5823 1.28821 15.0013 0.798232 15.1197C0.308251 15.2381 0.308251 14.7644 0.244735 14.4639C0.0814075 13.6441 -0.0365509 12.8153 0.00881775 12.0866Z",
|
|
681
|
+
fill
|
|
682
|
+
}
|
|
683
|
+
),
|
|
684
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
685
|
+
"path",
|
|
686
|
+
{
|
|
687
|
+
d: "M11.9136 4.29004C13.6648 4.3538 15.171 4.80921 16.5049 5.78378C16.5502 5.82021 16.6047 5.85665 16.65 5.89308C16.8497 6.07524 17.1309 6.25741 16.886 6.56708C16.65 6.87676 16.4051 6.66727 16.1782 6.50333C14.0731 4.95494 11.7956 4.69991 9.36385 5.61073C9.3094 5.62894 9.25496 5.65627 9.19145 5.67448C8.97368 5.75646 8.75591 5.75646 8.64702 5.51965C8.51999 5.25551 8.67424 5.08245 8.90109 4.97316C9.58162 4.65437 10.2894 4.47221 11.0243 4.37202C11.3601 4.33559 11.6867 4.31737 11.9136 4.29004Z",
|
|
688
|
+
fill
|
|
689
|
+
}
|
|
690
|
+
),
|
|
691
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
692
|
+
"path",
|
|
693
|
+
{
|
|
694
|
+
d: "M15.4521 16.5042C15.2797 17.9068 14.9531 19.2457 14.454 20.5391C14.0457 21.5865 13.5467 22.5884 12.9206 23.5266C12.8571 23.6268 12.7935 23.7361 12.7119 23.8271C12.5486 24.0184 12.3399 24.0548 12.1493 23.9273C11.9406 23.7907 11.9769 23.5903 12.0858 23.3991C12.2763 23.0712 12.4941 22.7615 12.6847 22.4336C13.71 20.6484 14.3724 18.7448 14.6355 16.6954C14.6446 16.5861 14.6718 16.486 14.699 16.3858C14.7535 16.1672 14.8896 16.0306 15.1255 16.0579C15.3705 16.0943 15.4521 16.2856 15.4521 16.5042Z",
|
|
695
|
+
fill
|
|
696
|
+
}
|
|
697
|
+
),
|
|
698
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
699
|
+
"path",
|
|
700
|
+
{
|
|
701
|
+
d: "M21.3501 14.7098C21.3773 16.4676 21.1414 18.1891 20.7331 19.8923C20.7149 19.947 20.7059 20.0107 20.6877 20.0654C20.6061 20.3295 20.5425 20.6574 20.1705 20.5572C19.8166 20.4661 19.8529 20.1655 19.9255 19.8832C20.1161 19.1454 20.2703 18.4077 20.3611 17.6517C20.5425 16.2673 20.6786 14.8828 20.5425 13.4802C20.5153 13.1978 20.5516 12.9246 20.8783 12.879C21.2503 12.8335 21.3229 13.134 21.332 13.4255C21.3592 13.8536 21.3501 14.2817 21.3501 14.7098Z",
|
|
702
|
+
fill
|
|
703
|
+
}
|
|
704
|
+
),
|
|
705
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
706
|
+
"path",
|
|
707
|
+
{
|
|
708
|
+
d: "M3.94694 14.5094C3.8925 16.0031 3.3753 17.1872 2.34089 18.1435C2.16849 18.2984 1.97794 18.3894 1.77832 18.2073C1.56963 18.016 1.59685 17.7792 1.7874 17.6061C3.15753 16.3583 3.34808 14.8099 2.96698 13.0976C2.91254 12.8517 2.92161 12.5875 2.92161 12.3325C2.93069 12.1321 3.04864 11.9773 3.25734 11.9773C3.46604 11.9682 3.61122 12.0957 3.63844 12.2961C3.7564 13.0612 3.85621 13.8263 3.94694 14.5094Z",
|
|
709
|
+
fill
|
|
710
|
+
}
|
|
711
|
+
),
|
|
712
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
713
|
+
"path",
|
|
714
|
+
{
|
|
715
|
+
d: "M10.3619 18.9908C10.2711 19.2002 10.1532 19.4735 10.0262 19.7467C9.48173 20.9035 8.78305 21.96 7.89382 22.8799C7.70328 23.0712 7.49458 23.2534 7.24052 23.0075C7.0046 22.7798 7.14978 22.5612 7.32218 22.379C8.30214 21.3316 9.05526 20.1384 9.60876 18.8086C9.6995 18.59 9.8356 18.3987 10.1169 18.4807C10.3256 18.5445 10.3891 18.7084 10.3619 18.9908Z",
|
|
716
|
+
fill
|
|
717
|
+
}
|
|
718
|
+
),
|
|
719
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
720
|
+
"path",
|
|
721
|
+
{
|
|
722
|
+
d: "M6.33312 17.2874C6.3059 17.3785 6.26054 17.506 6.21517 17.6244C5.75241 18.7174 5.05373 19.6282 4.17358 20.4115C3.96488 20.6028 3.71989 20.7121 3.50212 20.448C3.29343 20.202 3.46583 19.9835 3.65638 19.8286C4.50023 19.1091 5.11725 18.2256 5.54371 17.2055C5.64352 16.9778 5.77055 16.8047 6.05184 16.8594C6.23331 16.914 6.32405 17.0506 6.33312 17.2874Z",
|
|
723
|
+
fill
|
|
724
|
+
}
|
|
725
|
+
),
|
|
726
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
727
|
+
"path",
|
|
728
|
+
{
|
|
729
|
+
d: "M17.8026 19.5554C17.7753 19.6647 17.7572 19.7831 17.7209 19.9015C17.4215 20.9216 17.0676 21.9144 16.5957 22.8708C16.4778 23.1167 16.3145 23.3444 16.006 23.1987C15.7156 23.062 15.7882 22.7979 15.8971 22.5702C16.3508 21.5774 16.7409 20.5573 17.0313 19.5099C17.0948 19.2639 17.2218 19.0909 17.5122 19.1455C17.7209 19.1911 17.8026 19.3459 17.8026 19.5554Z",
|
|
730
|
+
fill
|
|
731
|
+
}
|
|
732
|
+
)
|
|
733
|
+
]
|
|
734
|
+
}
|
|
735
|
+
);
|
|
736
|
+
}
|
|
737
|
+
function FingerprintIcon({ size }) {
|
|
738
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
739
|
+
"svg",
|
|
740
|
+
{
|
|
741
|
+
width: size,
|
|
742
|
+
height: size,
|
|
743
|
+
viewBox: "0 0 24 24",
|
|
744
|
+
fill: "none",
|
|
745
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
746
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
747
|
+
"path",
|
|
748
|
+
{
|
|
749
|
+
d: "M17.81 4.47c-.08 0-.16-.02-.23-.06C15.66 3.42 14 3 12.01 3c-1.98 0-3.86.47-5.57 1.41-.24.13-.54.04-.68-.2-.13-.24-.04-.55.2-.68C7.82 2.52 9.86 2 12.01 2c2.13 0 3.99.47 6.03 1.52.25.13.34.43.21.67-.09.18-.26.28-.44.28zM3.5 9.72c-.1 0-.2-.03-.29-.09-.23-.16-.28-.47-.12-.7.99-1.4 2.25-2.5 3.75-3.27C9.98 4.04 14 4.03 17.15 5.65c1.5.77 2.76 1.86 3.75 3.25.16.22.11.54-.12.7-.23.16-.54.11-.7-.12-.9-1.26-2.04-2.25-3.39-2.94-2.87-1.47-6.54-1.47-9.4.01-1.36.7-2.5 1.7-3.4 2.96-.08.14-.23.21-.39.21zm6.25 12.07c-.13 0-.26-.05-.35-.15-.87-.87-1.34-1.43-2.01-2.64-.69-1.23-1.05-2.73-1.05-4.34 0-2.97 2.54-5.39 5.66-5.39s5.66 2.42 5.66 5.39c0 .28-.22.5-.5.5s-.5-.22-.5-.5c0-2.42-2.09-4.39-4.66-4.39-2.57 0-4.66 1.97-4.66 4.39 0 1.44.32 2.77.93 3.85.64 1.15 1.08 1.64 1.85 2.42.19.2.19.51 0 .71-.11.1-.24.15-.37.15zm7.17-1.85c-1.19 0-2.24-.3-3.1-.89-1.49-1.01-2.38-2.65-2.38-4.39 0-.28.22-.5.5-.5s.5.22.5.5c0 1.41.72 2.74 1.94 3.56.71.48 1.54.71 2.54.71.24 0 .64-.03 1.04-.1.27-.05.53.13.58.41.05.27-.13.53-.41.58-.57.11-1.07.12-1.21.12zM14.91 22c-.04 0-.09-.01-.13-.02-1.59-.44-2.63-1.03-3.72-2.1-1.4-1.39-2.17-3.24-2.17-5.22 0-1.62 1.38-2.94 3.08-2.94 1.7 0 3.08 1.32 3.08 2.94 0 1.07.93 1.94 2.08 1.94s2.08-.87 2.08-1.94c0-3.77-3.25-6.83-7.25-6.83-2.84 0-5.44 1.58-6.61 4.03-.39.81-.59 1.76-.59 2.8 0 .78.07 2.01.67 3.61.1.26-.03.55-.29.64-.26.1-.55-.04-.64-.29-.49-1.31-.73-2.61-.73-3.96 0-1.2.23-2.29.68-3.24 1.33-2.79 4.28-4.6 7.51-4.6 4.55 0 8.25 3.51 8.25 7.83 0 1.62-1.38 2.94-3.08 2.94s-3.08-1.32-3.08-2.94c0-1.07-.93-1.94-2.08-1.94s-2.08.87-2.08 1.94c0 1.71.66 3.31 1.87 4.51.95.94 1.86 1.46 3.27 1.85.27.07.42.35.35.61-.05.23-.26.38-.47.38z",
|
|
750
|
+
fill: "#3b82f6"
|
|
751
|
+
}
|
|
752
|
+
)
|
|
753
|
+
}
|
|
754
|
+
);
|
|
755
|
+
}
|
|
756
|
+
function BiometricIcon({ type, size = 80, animate = false }) {
|
|
757
|
+
const className = animate ? "volr:animate-pulse" : "";
|
|
758
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, children: [
|
|
759
|
+
type === "faceId" && /* @__PURE__ */ jsxRuntime.jsx(FaceIdIcon, { size }),
|
|
760
|
+
type === "touchId" && /* @__PURE__ */ jsxRuntime.jsx(TouchIdIcon, { size }),
|
|
761
|
+
type === "fingerprint" && /* @__PURE__ */ jsxRuntime.jsx(FingerprintIcon, { size })
|
|
762
|
+
] });
|
|
763
|
+
}
|
|
764
|
+
function PasskeyEnrollForm({
|
|
765
|
+
biometricType,
|
|
766
|
+
biometricMessage,
|
|
767
|
+
errorMessage,
|
|
768
|
+
accentColor,
|
|
769
|
+
onEnroll,
|
|
770
|
+
onLogout,
|
|
771
|
+
buttonText,
|
|
772
|
+
logoutText
|
|
773
|
+
}) {
|
|
774
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
775
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "volr:my-8 volr:flex volr:justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(BiometricIcon, { type: biometricType, size: 60 }) }),
|
|
776
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "volr:text-base volr:text-slate-600 volr:mb-8", children: biometricMessage }),
|
|
777
|
+
errorMessage && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "volr:mb-6 volr:p-3 volr:rounded-lg volr:bg-rose-50 volr:border volr:border-rose-200 volr:text-rose-700 volr:text-sm volr:flex volr:items-start volr:gap-2 volr:text-left", children: [
|
|
778
|
+
/* @__PURE__ */ jsxRuntime.jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "currentColor", className: "volr:flex-shrink-0 volr:mt-0.5", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z" }) }),
|
|
779
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: errorMessage })
|
|
780
|
+
] }),
|
|
781
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "volr:flex volr:flex-col volr:gap-3", children: [
|
|
782
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
783
|
+
"button",
|
|
784
|
+
{
|
|
785
|
+
onClick: onEnroll,
|
|
786
|
+
className: "volr:w-full volr:py-3 volr:px-6 volr:rounded-lg volr:text-white volr:text-base volr:font-medium volr:transition-colors",
|
|
787
|
+
style: { backgroundColor: accentColor },
|
|
788
|
+
children: buttonText
|
|
789
|
+
}
|
|
790
|
+
),
|
|
791
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
792
|
+
"button",
|
|
793
|
+
{
|
|
794
|
+
onClick: onLogout,
|
|
795
|
+
className: "volr:w-full volr:py-3 volr:text-sm volr:font-medium volr:text-slate-600 volr:rounded-lg volr:transition-colors hover:volr:bg-slate-50",
|
|
796
|
+
children: logoutText
|
|
797
|
+
}
|
|
798
|
+
)
|
|
799
|
+
] })
|
|
800
|
+
] });
|
|
801
|
+
}
|
|
802
|
+
function PasskeyEnrollLoading({
|
|
803
|
+
biometricType,
|
|
804
|
+
stepMessage,
|
|
805
|
+
isEnrolling,
|
|
806
|
+
accentColor,
|
|
807
|
+
onRetry,
|
|
808
|
+
onLogout,
|
|
809
|
+
buttonText,
|
|
810
|
+
logoutText,
|
|
811
|
+
progress = 0
|
|
812
|
+
}) {
|
|
813
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
814
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "volr:mb-8 volr:flex volr:justify-center volr:items-center volr:min-h-[120px]", children: /* @__PURE__ */ jsxRuntime.jsx(BiometricIcon, { type: biometricType, size: 60, animate: isEnrolling }) }),
|
|
815
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "volr:text-base volr:text-slate-500 volr:mb-4", children: stepMessage }),
|
|
816
|
+
isEnrolling && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "volr:w-full volr:mb-6", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "volr:w-full volr:h-2 volr:bg-slate-100 volr:rounded-full volr:overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
817
|
+
"div",
|
|
818
|
+
{
|
|
819
|
+
className: "volr:h-full volr:rounded-full volr:transition-all volr:duration-500 volr:ease-out",
|
|
820
|
+
style: {
|
|
821
|
+
backgroundColor: accentColor,
|
|
822
|
+
width: `${progress}%`
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
) }) }),
|
|
826
|
+
!isEnrolling && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "volr:flex volr:flex-col volr:gap-3 volr:mt-6", children: [
|
|
827
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
828
|
+
"button",
|
|
829
|
+
{
|
|
830
|
+
onClick: onRetry,
|
|
831
|
+
className: "volr:w-full volr:py-3 volr:px-6 volr:rounded-lg volr:text-white volr:text-base volr:font-medium volr:transition-colors",
|
|
832
|
+
style: { backgroundColor: accentColor },
|
|
833
|
+
children: buttonText
|
|
834
|
+
}
|
|
835
|
+
),
|
|
836
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
837
|
+
"button",
|
|
838
|
+
{
|
|
839
|
+
onClick: onLogout,
|
|
840
|
+
className: "volr:w-full volr:py-3 volr:text-sm volr:font-medium volr:text-slate-600 volr:rounded-lg volr:transition-colors hover:volr:bg-slate-50",
|
|
841
|
+
children: logoutText
|
|
842
|
+
}
|
|
843
|
+
)
|
|
844
|
+
] })
|
|
845
|
+
] });
|
|
846
|
+
}
|
|
847
|
+
function PasskeyEnrollView({
|
|
848
|
+
onComplete,
|
|
849
|
+
onError,
|
|
850
|
+
onLogout,
|
|
851
|
+
onClose,
|
|
852
|
+
isOpen = true,
|
|
853
|
+
wrapInModal = true
|
|
854
|
+
}) {
|
|
855
|
+
const { user, logout, setUser } = react.useVolr();
|
|
856
|
+
const { client } = react.useInternalAuth();
|
|
857
|
+
const { t } = useI18n();
|
|
858
|
+
const { accentColor } = useVolrUI();
|
|
859
|
+
const {
|
|
860
|
+
enroll,
|
|
861
|
+
step,
|
|
862
|
+
isEnrolling,
|
|
863
|
+
error: enrollmentError
|
|
864
|
+
} = react.usePasskeyEnrollment();
|
|
865
|
+
const [hasStarted, setHasStarted] = React3.useState(false);
|
|
866
|
+
const [errorMessage, setErrorMessage] = React3.useState(null);
|
|
867
|
+
const [isRefreshing, setIsRefreshing] = React3.useState(false);
|
|
868
|
+
const biometricType = getBiometricType();
|
|
869
|
+
const hasPasskey = user?.keyStorageType === "passkey";
|
|
870
|
+
React3.useEffect(() => {
|
|
871
|
+
console.log("[PasskeyEnrollView] User state:", {
|
|
872
|
+
user,
|
|
873
|
+
keyStorageType: user?.keyStorageType,
|
|
874
|
+
evmAddress: user?.evmAddress,
|
|
875
|
+
hasPasskey
|
|
876
|
+
});
|
|
877
|
+
}, [user, hasPasskey]);
|
|
878
|
+
React3.useEffect(() => {
|
|
879
|
+
if (hasPasskey && !user?.evmAddress && !isRefreshing) {
|
|
880
|
+
const refreshUserData = async () => {
|
|
881
|
+
try {
|
|
882
|
+
setIsRefreshing(true);
|
|
883
|
+
const response = await client.post(
|
|
884
|
+
"/auth/refresh",
|
|
885
|
+
{}
|
|
886
|
+
);
|
|
887
|
+
if (response.user) {
|
|
888
|
+
console.log(
|
|
889
|
+
"[PasskeyEnrollView] Updated user data:",
|
|
890
|
+
response.user
|
|
891
|
+
);
|
|
892
|
+
setUser({
|
|
893
|
+
...user,
|
|
894
|
+
...response.user
|
|
895
|
+
});
|
|
896
|
+
}
|
|
897
|
+
} catch (error) {
|
|
898
|
+
console.error(
|
|
899
|
+
"[PasskeyEnrollView] Failed to refresh user data:",
|
|
900
|
+
error
|
|
901
|
+
);
|
|
902
|
+
} finally {
|
|
903
|
+
setIsRefreshing(false);
|
|
904
|
+
}
|
|
905
|
+
};
|
|
906
|
+
refreshUserData();
|
|
907
|
+
}
|
|
908
|
+
}, [hasPasskey, user?.evmAddress, isRefreshing, client, setUser, user]);
|
|
909
|
+
React3.useEffect(() => {
|
|
910
|
+
if (!user?.id) {
|
|
911
|
+
const error = new Error("User ID is required for passkey enrollment");
|
|
912
|
+
setErrorMessage(getUserFriendlyError(error, t));
|
|
913
|
+
if (onError) {
|
|
914
|
+
onError(error);
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
if (!user?.email) {
|
|
918
|
+
const error = new Error("User email is required for passkey enrollment");
|
|
919
|
+
setErrorMessage(getUserFriendlyError(error, t));
|
|
920
|
+
if (onError) {
|
|
921
|
+
onError(error);
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
}, [user, onError, t]);
|
|
925
|
+
React3.useEffect(() => {
|
|
926
|
+
if (enrollmentError) {
|
|
927
|
+
const friendlyMessage = getUserFriendlyError(enrollmentError, t);
|
|
928
|
+
setErrorMessage(friendlyMessage);
|
|
929
|
+
if (onError) {
|
|
930
|
+
onError(enrollmentError);
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
}, [enrollmentError, onError, t]);
|
|
934
|
+
const handleEnroll = async () => {
|
|
935
|
+
if (!user?.id || !user?.email) {
|
|
936
|
+
const error = new Error(
|
|
937
|
+
"User ID and email are required for passkey enrollment"
|
|
938
|
+
);
|
|
939
|
+
setErrorMessage(getUserFriendlyError(error, t));
|
|
940
|
+
if (onError) {
|
|
941
|
+
onError(error);
|
|
942
|
+
}
|
|
943
|
+
return;
|
|
944
|
+
}
|
|
945
|
+
try {
|
|
946
|
+
setErrorMessage(null);
|
|
947
|
+
await enroll();
|
|
948
|
+
setHasStarted(false);
|
|
949
|
+
onComplete();
|
|
950
|
+
} catch (error) {
|
|
951
|
+
setHasStarted(false);
|
|
952
|
+
}
|
|
953
|
+
};
|
|
954
|
+
const handleLogout = async () => {
|
|
955
|
+
try {
|
|
956
|
+
await logout();
|
|
957
|
+
if (onLogout) {
|
|
958
|
+
onLogout();
|
|
959
|
+
}
|
|
960
|
+
} catch (error) {
|
|
961
|
+
if (onError) {
|
|
962
|
+
onError(error instanceof Error ? error : new Error("Logout failed"));
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
};
|
|
966
|
+
const getStepMessage = () => {
|
|
967
|
+
switch (step) {
|
|
968
|
+
case "creating":
|
|
969
|
+
return t("passkey.creating");
|
|
970
|
+
case "encrypting":
|
|
971
|
+
return t("passkey.encrypting");
|
|
972
|
+
case "uploading":
|
|
973
|
+
return t("passkey.uploading");
|
|
974
|
+
case "registering":
|
|
975
|
+
return t("passkey.registering");
|
|
976
|
+
default:
|
|
977
|
+
return "";
|
|
978
|
+
}
|
|
979
|
+
};
|
|
980
|
+
const getProgress = () => {
|
|
981
|
+
switch (step) {
|
|
982
|
+
case "creating":
|
|
983
|
+
return 25;
|
|
984
|
+
case "encrypting":
|
|
985
|
+
return 50;
|
|
986
|
+
case "uploading":
|
|
987
|
+
return 75;
|
|
988
|
+
case "registering":
|
|
989
|
+
return 90;
|
|
990
|
+
default:
|
|
991
|
+
return 0;
|
|
992
|
+
}
|
|
993
|
+
};
|
|
994
|
+
const getBiometricMessage = () => {
|
|
995
|
+
if (biometricType === "faceId") {
|
|
996
|
+
return t("passkey.faceId");
|
|
997
|
+
}
|
|
998
|
+
if (biometricType === "touchId") {
|
|
999
|
+
return t("passkey.touchId");
|
|
1000
|
+
}
|
|
1001
|
+
return t("passkey.fingerprint");
|
|
1002
|
+
};
|
|
1003
|
+
if (hasPasskey) {
|
|
1004
|
+
const handleClose = () => {
|
|
1005
|
+
if (onClose) {
|
|
1006
|
+
onClose();
|
|
1007
|
+
} else if (onComplete) {
|
|
1008
|
+
onComplete();
|
|
1009
|
+
}
|
|
1010
|
+
};
|
|
1011
|
+
const walletContent = /* @__PURE__ */ jsxRuntime.jsx(WalletConnectedView, { user });
|
|
1012
|
+
if (!wrapInModal) {
|
|
1013
|
+
return walletContent;
|
|
1014
|
+
}
|
|
1015
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Modal, { open: isOpen, onOpenChange: (open) => !open && handleClose(), children: walletContent });
|
|
1016
|
+
}
|
|
1017
|
+
const content = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "volr:text-center", children: [
|
|
1018
|
+
/* @__PURE__ */ jsxRuntime.jsx(ModalTitle2, { size: "xl", children: t("passkey.start") }),
|
|
1019
|
+
!hasStarted ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1020
|
+
PasskeyEnrollForm,
|
|
1021
|
+
{
|
|
1022
|
+
biometricType,
|
|
1023
|
+
biometricMessage: getBiometricMessage(),
|
|
1024
|
+
errorMessage,
|
|
1025
|
+
accentColor,
|
|
1026
|
+
onEnroll: () => {
|
|
1027
|
+
setHasStarted(true);
|
|
1028
|
+
handleEnroll();
|
|
1029
|
+
},
|
|
1030
|
+
onLogout: handleLogout,
|
|
1031
|
+
buttonText: t("passkey.start"),
|
|
1032
|
+
logoutText: t("passkey.logout")
|
|
1033
|
+
}
|
|
1034
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
1035
|
+
PasskeyEnrollLoading,
|
|
1036
|
+
{
|
|
1037
|
+
biometricType,
|
|
1038
|
+
stepMessage: getStepMessage(),
|
|
1039
|
+
isEnrolling,
|
|
1040
|
+
accentColor,
|
|
1041
|
+
progress: getProgress(),
|
|
1042
|
+
onRetry: handleEnroll,
|
|
1043
|
+
onLogout: handleLogout,
|
|
1044
|
+
buttonText: t("passkey.start"),
|
|
1045
|
+
logoutText: t("passkey.logout")
|
|
1046
|
+
}
|
|
1047
|
+
)
|
|
1048
|
+
] });
|
|
1049
|
+
if (!wrapInModal) {
|
|
1050
|
+
return content;
|
|
1051
|
+
}
|
|
1052
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Modal, { open: isOpen, onOpenChange: (open) => !open && onLogout?.(), children: content });
|
|
1053
|
+
}
|
|
1054
|
+
function MpcConnectView({
|
|
1055
|
+
onComplete,
|
|
1056
|
+
onError,
|
|
1057
|
+
isOpen = true,
|
|
1058
|
+
wrapInModal = true
|
|
1059
|
+
}) {
|
|
1060
|
+
const {
|
|
1061
|
+
connect,
|
|
1062
|
+
step,
|
|
1063
|
+
isConnecting,
|
|
1064
|
+
error: connectionError
|
|
1065
|
+
} = react.useMpcConnection();
|
|
1066
|
+
const [errorMessage, setErrorMessage] = React3.useState(null);
|
|
1067
|
+
React3.useEffect(() => {
|
|
1068
|
+
if (connectionError) {
|
|
1069
|
+
setErrorMessage(connectionError.message);
|
|
1070
|
+
if (onError) {
|
|
1071
|
+
onError(connectionError);
|
|
1072
|
+
}
|
|
1073
|
+
}
|
|
1074
|
+
}, [connectionError, onError]);
|
|
1075
|
+
React3.useEffect(() => {
|
|
1076
|
+
handleConnect();
|
|
1077
|
+
}, []);
|
|
1078
|
+
const handleConnect = async () => {
|
|
1079
|
+
try {
|
|
1080
|
+
setErrorMessage(null);
|
|
1081
|
+
await connect();
|
|
1082
|
+
setTimeout(() => {
|
|
1083
|
+
onComplete();
|
|
1084
|
+
}, 1e3);
|
|
1085
|
+
} catch (error) {
|
|
1086
|
+
}
|
|
1087
|
+
};
|
|
1088
|
+
const getStepMessage = () => {
|
|
1089
|
+
switch (step) {
|
|
1090
|
+
case "connecting":
|
|
1091
|
+
return "Establishing secure connection...";
|
|
1092
|
+
case "registering":
|
|
1093
|
+
return "Registering wallet provider...";
|
|
1094
|
+
default:
|
|
1095
|
+
return "";
|
|
1096
|
+
}
|
|
1097
|
+
};
|
|
1098
|
+
const content = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "volr:p-8 volr:max-w-md volr:mx-auto volr:text-center", children: [
|
|
1099
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "volr:text-2xl volr:font-bold volr:mb-6 volr:font-georama", children: "Connecting to MPC Provider" }),
|
|
1100
|
+
errorMessage && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "volr:mb-4 volr:p-3 volr:bg-red-50 volr:border volr:border-red-200 volr:rounded-lg volr:text-red-700 volr:text-sm volr:text-left", children: errorMessage }),
|
|
1101
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "volr:mb-8 volr:flex volr:justify-center volr:items-center volr:min-h-[120px]", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1102
|
+
"div",
|
|
1103
|
+
{
|
|
1104
|
+
className: `volr:text-8xl ${isConnecting ? "volr:animate-pulse" : ""}`,
|
|
1105
|
+
children: "\u{1F512}"
|
|
1106
|
+
}
|
|
1107
|
+
) }),
|
|
1108
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "volr:text-base volr:text-gray-500 volr:mb-6 volr:leading-relaxed volr:font-georama", children: getStepMessage() })
|
|
1109
|
+
] });
|
|
1110
|
+
if (!wrapInModal) {
|
|
1111
|
+
return content;
|
|
1112
|
+
}
|
|
1113
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1114
|
+
Modal,
|
|
1115
|
+
{
|
|
1116
|
+
open: isOpen,
|
|
1117
|
+
onOpenChange: (open) => {
|
|
1118
|
+
if (!open && !isConnecting && onError) {
|
|
1119
|
+
onError(new Error("Connection cancelled"));
|
|
1120
|
+
}
|
|
1121
|
+
},
|
|
1122
|
+
onPointerDownOutside: (e) => {
|
|
1123
|
+
if (isConnecting) e.preventDefault();
|
|
1124
|
+
},
|
|
1125
|
+
onEscapeKeyDown: (e) => {
|
|
1126
|
+
if (isConnecting) e.preventDefault();
|
|
1127
|
+
},
|
|
1128
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-w-md mx-auto", children: [
|
|
1129
|
+
/* @__PURE__ */ jsxRuntime.jsx(ModalTitle, { className: "sr-only", children: "MPC Connection" }),
|
|
1130
|
+
content
|
|
1131
|
+
] })
|
|
1132
|
+
}
|
|
1133
|
+
);
|
|
1134
|
+
}
|
|
1135
|
+
function OptionButton({
|
|
1136
|
+
icon,
|
|
1137
|
+
title,
|
|
1138
|
+
description,
|
|
1139
|
+
onClick,
|
|
1140
|
+
className,
|
|
1141
|
+
...rest
|
|
1142
|
+
}) {
|
|
1143
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1144
|
+
"button",
|
|
1145
|
+
{
|
|
1146
|
+
type: "button",
|
|
1147
|
+
onClick,
|
|
1148
|
+
className: cn(
|
|
1149
|
+
"volr:group volr:flex volr:items-center volr:gap-3 volr:rounded-lg volr:border volr:border-slate-200 volr:bg-white volr:p-3 volr:transition-colors volr:focus-visible:outline-none volr:focus-visible:ring-2 volr:focus-visible:ring-slate-300 volr:hover:bg-slate-50",
|
|
1150
|
+
className
|
|
1151
|
+
),
|
|
1152
|
+
...rest,
|
|
1153
|
+
children: [
|
|
1154
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "volr:flex volr:h-8 volr:w-8 volr:items-center volr:justify-center volr:text-slate-700", children: icon }),
|
|
1155
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "volr:flex volr:min-w-0 volr:flex-col", children: [
|
|
1156
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "volr:truncate volr:text-left volr:text-sm volr:font-medium volr:text-slate-900", children: title }),
|
|
1157
|
+
description ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "volr:truncate volr:text-left volr:text-xs volr:text-slate-500", children: description }) : null
|
|
1158
|
+
] })
|
|
1159
|
+
]
|
|
1160
|
+
}
|
|
1161
|
+
);
|
|
1162
|
+
}
|
|
1163
|
+
function GoogleIcon() {
|
|
1164
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
|
|
1165
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1166
|
+
"path",
|
|
1167
|
+
{
|
|
1168
|
+
d: "M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z",
|
|
1169
|
+
fill: "#4285F4"
|
|
1170
|
+
}
|
|
1171
|
+
),
|
|
1172
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1173
|
+
"path",
|
|
1174
|
+
{
|
|
1175
|
+
d: "M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z",
|
|
1176
|
+
fill: "#34A853"
|
|
1177
|
+
}
|
|
1178
|
+
),
|
|
1179
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1180
|
+
"path",
|
|
1181
|
+
{
|
|
1182
|
+
d: "M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z",
|
|
1183
|
+
fill: "#FBBC05"
|
|
1184
|
+
}
|
|
1185
|
+
),
|
|
1186
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1187
|
+
"path",
|
|
1188
|
+
{
|
|
1189
|
+
d: "M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z",
|
|
1190
|
+
fill: "#EA4335"
|
|
1191
|
+
}
|
|
1192
|
+
)
|
|
1193
|
+
] });
|
|
1194
|
+
}
|
|
1195
|
+
function TwitterXIcon() {
|
|
1196
|
+
return /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1197
|
+
"path",
|
|
1198
|
+
{
|
|
1199
|
+
d: "M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z",
|
|
1200
|
+
fill: "#000000"
|
|
1201
|
+
}
|
|
1202
|
+
) });
|
|
1203
|
+
}
|
|
1204
|
+
function AppleIcon() {
|
|
1205
|
+
return /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1206
|
+
"path",
|
|
1207
|
+
{
|
|
1208
|
+
d: "M18.71 19.5c-.83 1.24-1.71 2.45-3.05 2.47-1.34.03-1.77-.79-3.29-.79-1.53 0-2 .77-3.27.82-1.31.05-2.3-1.32-3.14-2.53C4.25 17 2.94 12.45 4.7 9.39c.87-1.52 2.43-2.48 4.12-2.51 1.28-.02 2.5.87 3.29.87.78 0 2.26-1.07 3.81-.91.65.03 2.47.26 3.64 1.98-.09.06-2.17 1.28-2.15 3.81.03 3.02 2.65 4.03 2.68 4.04-.03.07-.42 1.44-1.38 2.83M13 3.5c.73-.83 1.94-1.46 2.94-1.5.13 1.17-.34 2.35-1.04 3.19-.69.85-1.83 1.51-2.95 1.42-.15-1.15.41-2.35 1.05-3.11z",
|
|
1209
|
+
fill: "#000000"
|
|
1210
|
+
}
|
|
1211
|
+
) });
|
|
1212
|
+
}
|
|
1213
|
+
function SocialOption({
|
|
1214
|
+
provider,
|
|
1215
|
+
onClick
|
|
1216
|
+
}) {
|
|
1217
|
+
const { t } = useI18n();
|
|
1218
|
+
const icons = {
|
|
1219
|
+
google: /* @__PURE__ */ jsxRuntime.jsx(GoogleIcon, {}),
|
|
1220
|
+
twitter: /* @__PURE__ */ jsxRuntime.jsx(TwitterXIcon, {}),
|
|
1221
|
+
apple: /* @__PURE__ */ jsxRuntime.jsx(AppleIcon, {})
|
|
1222
|
+
};
|
|
1223
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1224
|
+
OptionButton,
|
|
1225
|
+
{
|
|
1226
|
+
onClick,
|
|
1227
|
+
icon: icons[provider],
|
|
1228
|
+
title: t(`login.social.${provider}`)
|
|
1229
|
+
}
|
|
1230
|
+
);
|
|
1231
|
+
}
|
|
1232
|
+
function WalletIcon(props) {
|
|
1233
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1234
|
+
"svg",
|
|
1235
|
+
{
|
|
1236
|
+
width: "24",
|
|
1237
|
+
height: "24",
|
|
1238
|
+
viewBox: "0 0 24 24",
|
|
1239
|
+
fill: "none",
|
|
1240
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1241
|
+
"aria-hidden": "true",
|
|
1242
|
+
...props,
|
|
1243
|
+
children: [
|
|
1244
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1245
|
+
"path",
|
|
1246
|
+
{
|
|
1247
|
+
d: "M4 7.5C4 6.11929 5.11929 5 6.5 5H16.5C17.3284 5 18 5.67157 18 6.5C18 7.32843 17.3284 8 16.5 8H6.5C5.11929 8 4 6.88071 4 5.5V7.5Z",
|
|
1248
|
+
stroke: "currentColor",
|
|
1249
|
+
strokeWidth: "1.6",
|
|
1250
|
+
strokeLinecap: "round"
|
|
1251
|
+
}
|
|
1252
|
+
),
|
|
1253
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1254
|
+
"rect",
|
|
1255
|
+
{
|
|
1256
|
+
x: "3.2",
|
|
1257
|
+
y: "7.6",
|
|
1258
|
+
width: "17.6",
|
|
1259
|
+
height: "11.2",
|
|
1260
|
+
rx: "2.4",
|
|
1261
|
+
stroke: "currentColor",
|
|
1262
|
+
strokeWidth: "1.6"
|
|
1263
|
+
}
|
|
1264
|
+
),
|
|
1265
|
+
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "16.6", cy: "13.2", r: "1.2", fill: "currentColor" })
|
|
1266
|
+
]
|
|
1267
|
+
}
|
|
1268
|
+
);
|
|
1269
|
+
}
|
|
1270
|
+
function WalletOption({ onClick }) {
|
|
1271
|
+
const { t } = useI18n();
|
|
1272
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1273
|
+
OptionButton,
|
|
1274
|
+
{
|
|
1275
|
+
onClick,
|
|
1276
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "volr:text-slate-700", children: /* @__PURE__ */ jsxRuntime.jsx(WalletIcon, {}) }),
|
|
1277
|
+
title: t("login.wallet.label")
|
|
1278
|
+
}
|
|
1279
|
+
);
|
|
1280
|
+
}
|
|
1281
|
+
function PoweredBy() {
|
|
1282
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "volr:mt-8 volr:text-xs volr:text-slate-400 volr:text-center volr:flex volr:items-baseline volr:justify-center volr:gap-1", children: [
|
|
1283
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Powered by" }),
|
|
1284
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1285
|
+
"svg",
|
|
1286
|
+
{
|
|
1287
|
+
viewBox: "0 0 943 289",
|
|
1288
|
+
fill: "none",
|
|
1289
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1290
|
+
className: "volr:inline-block",
|
|
1291
|
+
style: { height: "0.8em", width: "auto", verticalAlign: "baseline" },
|
|
1292
|
+
"aria-label": "Volr",
|
|
1293
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1294
|
+
"path",
|
|
1295
|
+
{
|
|
1296
|
+
d: "M138.4 284L-0.00019535 0H87.1998L184.4 208L281.2 0H363.6L225.2 284H138.4ZM471.931 288.8C453.531 288.8 435.931 286.533 419.131 282C402.331 277.2 387.264 270.267 373.931 261.2C360.864 252.133 350.464 240.933 342.731 227.6C335.264 214.267 331.531 198.8 331.531 181.2C331.531 157.733 337.664 138 349.931 122C362.464 106 379.398 94 400.731 86C422.064 77.7333 445.798 73.6 471.931 73.6C498.064 73.6 521.664 77.7333 542.731 86C564.064 94 580.864 106 593.131 122C605.664 138 611.931 157.733 611.931 181.2C611.931 198.8 608.064 214.267 600.331 227.6C592.864 240.933 582.464 252.133 569.131 261.2C556.064 270.267 541.131 277.2 524.331 282C507.531 286.533 490.064 288.8 471.931 288.8ZM471.931 236C490.598 236 505.531 231.2 516.731 221.6C528.198 211.733 533.931 198.933 533.931 183.2V179.2C533.931 163.2 528.198 150.4 516.731 140.8C505.531 131.2 490.598 126.4 471.931 126.4C453.264 126.4 438.198 131.2 426.731 140.8C415.264 150.4 409.531 163.2 409.531 179.2V183.2C409.531 198.933 415.264 211.733 426.731 221.6C438.198 231.2 453.264 236 471.931 236ZM643.865 284V0H721.465V284H643.865ZM763.006 284V78.4H839.406V106.8C848.739 95.3333 860.473 86.9333 874.606 81.6C888.739 76.2667 903.406 73.6 918.606 73.6C921.539 73.6 925.006 73.7333 929.006 74C933.006 74.2667 937.406 74.8 942.206 75.6V135.2C935.006 134.4 926.873 133.733 917.806 133.2C909.006 132.667 900.073 132.8 891.006 133.6C881.939 134.4 873.539 136.4 865.806 139.6C858.339 142.533 852.206 147.333 847.406 154C842.873 160.667 840.606 169.733 840.606 181.2V284H763.006Z",
|
|
1297
|
+
fill: "#303030"
|
|
1298
|
+
}
|
|
1299
|
+
)
|
|
1300
|
+
}
|
|
1301
|
+
)
|
|
1302
|
+
] });
|
|
1303
|
+
}
|
|
1304
|
+
function EmailInlineInput({ onSubmit, accentColor }) {
|
|
1305
|
+
const { t } = useI18n();
|
|
1306
|
+
const [email, setEmail] = React3.useState("");
|
|
1307
|
+
const [error, setError] = React3.useState(null);
|
|
1308
|
+
const [isLoading, setIsLoading] = React3.useState(false);
|
|
1309
|
+
const handleSubmit = async (e) => {
|
|
1310
|
+
e.preventDefault();
|
|
1311
|
+
setError(null);
|
|
1312
|
+
setIsLoading(true);
|
|
1313
|
+
try {
|
|
1314
|
+
await onSubmit(email);
|
|
1315
|
+
} catch (err) {
|
|
1316
|
+
setError(err instanceof Error ? err.message : "Failed to send code");
|
|
1317
|
+
} finally {
|
|
1318
|
+
setIsLoading(false);
|
|
1319
|
+
}
|
|
1320
|
+
};
|
|
1321
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: handleSubmit, children: [
|
|
1322
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "volr:relative", children: [
|
|
1323
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "volr:absolute volr:left-3 volr:top-1/2 volr:-translate-y-1/2 volr:pointer-events-none", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1324
|
+
"svg",
|
|
1325
|
+
{
|
|
1326
|
+
width: "20",
|
|
1327
|
+
height: "20",
|
|
1328
|
+
viewBox: "0 0 24 24",
|
|
1329
|
+
fill: "none",
|
|
1330
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1331
|
+
className: "volr:text-slate-400",
|
|
1332
|
+
children: [
|
|
1333
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1334
|
+
"path",
|
|
1335
|
+
{
|
|
1336
|
+
d: "M3 8L10.89 13.26C11.2187 13.4793 11.6049 13.5963 12 13.5963C12.3951 13.5963 12.7813 13.4793 13.11 13.26L21 8",
|
|
1337
|
+
stroke: "currentColor",
|
|
1338
|
+
strokeWidth: "1.8",
|
|
1339
|
+
strokeLinecap: "round",
|
|
1340
|
+
strokeLinejoin: "round"
|
|
1341
|
+
}
|
|
1342
|
+
),
|
|
1343
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1344
|
+
"rect",
|
|
1345
|
+
{
|
|
1346
|
+
x: "3",
|
|
1347
|
+
y: "6",
|
|
1348
|
+
width: "18",
|
|
1349
|
+
height: "12",
|
|
1350
|
+
rx: "2.2",
|
|
1351
|
+
stroke: "currentColor",
|
|
1352
|
+
strokeWidth: "1.8"
|
|
1353
|
+
}
|
|
1354
|
+
)
|
|
1355
|
+
]
|
|
1356
|
+
}
|
|
1357
|
+
) }),
|
|
1358
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1359
|
+
"input",
|
|
1360
|
+
{
|
|
1361
|
+
type: "email",
|
|
1362
|
+
value: email,
|
|
1363
|
+
onChange: (e) => setEmail(e.target.value),
|
|
1364
|
+
required: true,
|
|
1365
|
+
placeholder: t("login.email.placeholder"),
|
|
1366
|
+
className: "volr:w-full volr:pl-11 volr:pr-3 volr:py-3 volr:rounded-lg volr:border volr:border-slate-300 volr:text-base volr:outline-none focus:volr:ring-2 focus:volr:ring-slate-300 focus:volr:border-slate-400"
|
|
1367
|
+
}
|
|
1368
|
+
)
|
|
1369
|
+
] }),
|
|
1370
|
+
error && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "volr:mt-2 volr:rounded-lg volr:border volr:bg-rose-50 volr:border-rose-200 volr:text-rose-800 volr:text-sm volr:p-3", children: error }),
|
|
1371
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1372
|
+
"button",
|
|
1373
|
+
{
|
|
1374
|
+
type: "submit",
|
|
1375
|
+
disabled: isLoading || !email,
|
|
1376
|
+
className: "volr:w-full volr:mt-3 volr:px-6 volr:py-3 volr:rounded-lg volr:text-white volr:text-base volr:font-medium volr:transition disabled:volr:cursor-not-allowed",
|
|
1377
|
+
style: { backgroundColor: isLoading || !email ? "#cbd5e1" : accentColor },
|
|
1378
|
+
children: isLoading ? t("common.loading") : t("login.email.sendCode")
|
|
1379
|
+
}
|
|
1380
|
+
)
|
|
1381
|
+
] });
|
|
1382
|
+
}
|
|
1383
|
+
function Divider({ text = "\uB610\uB294" }) {
|
|
1384
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "volr:flex volr:items-center volr:gap-3 volr:my-6", children: [
|
|
1385
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "volr:flex-1 volr:h-px volr:bg-slate-200" }),
|
|
1386
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "volr:text-sm volr:text-slate-400", children: text }),
|
|
1387
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "volr:flex-1 volr:h-px volr:bg-slate-200" })
|
|
1388
|
+
] });
|
|
1389
|
+
}
|
|
1390
|
+
function BrandingPanel({ config }) {
|
|
1391
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { style: { backgroundColor: config.backgroundColor }, children: config.component });
|
|
1392
|
+
}
|
|
1393
|
+
function SigninSelectScreen({
|
|
1394
|
+
onSelectMethod,
|
|
1395
|
+
onEmailSubmit,
|
|
1396
|
+
branding,
|
|
1397
|
+
onClose
|
|
1398
|
+
}) {
|
|
1399
|
+
const { t } = useI18n();
|
|
1400
|
+
const {
|
|
1401
|
+
accentColor,
|
|
1402
|
+
enabledLoginMethods = ["email", "social", "siwe"],
|
|
1403
|
+
socialProviders = ["google", "twitter", "apple"]
|
|
1404
|
+
} = useVolrUI();
|
|
1405
|
+
const isWide = useMediaQuery("(min-width: 896px)");
|
|
1406
|
+
const showBrandingColumn = Boolean(branding) && isWide;
|
|
1407
|
+
const isEmailEnabled = enabledLoginMethods.includes("email");
|
|
1408
|
+
const isSocialEnabled = enabledLoginMethods.includes("social");
|
|
1409
|
+
const isSiweEnabled = enabledLoginMethods.includes("siwe");
|
|
1410
|
+
const hasEmailAndOthers = isEmailEnabled && (isSocialEnabled || isSiweEnabled);
|
|
1411
|
+
const hasOnlySocialAndWallet = !isEmailEnabled && isSocialEnabled && isSiweEnabled;
|
|
1412
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1413
|
+
"div",
|
|
1414
|
+
{
|
|
1415
|
+
className: showBrandingColumn ? "volr:max-w-4xl volr:w-full volr:mx-auto volr:grid volr:grid-cols-[minmax(0,1.1fr)_minmax(0,1fr)] volr:gap-4" : "volr:max-w-md volr:w-full volr:mx-auto",
|
|
1416
|
+
children: [
|
|
1417
|
+
showBrandingColumn && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "volr:flex", children: /* @__PURE__ */ jsxRuntime.jsx(BrandingPanel, { config: branding }) }),
|
|
1418
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1419
|
+
"div",
|
|
1420
|
+
{
|
|
1421
|
+
className: `volr:flex volr:flex-col volr:gap-4 ${showBrandingColumn ? "volr:p-4" : ""}`,
|
|
1422
|
+
children: [
|
|
1423
|
+
/* @__PURE__ */ jsxRuntime.jsx(ModalHeader, { onClose }),
|
|
1424
|
+
/* @__PURE__ */ jsxRuntime.jsx(ModalTitle2, { size: "2xl", children: t("login.title") }),
|
|
1425
|
+
isEmailEnabled && /* @__PURE__ */ jsxRuntime.jsx(
|
|
1426
|
+
EmailInlineInput,
|
|
1427
|
+
{
|
|
1428
|
+
onSubmit: onEmailSubmit,
|
|
1429
|
+
accentColor
|
|
1430
|
+
}
|
|
1431
|
+
),
|
|
1432
|
+
hasEmailAndOthers && /* @__PURE__ */ jsxRuntime.jsx(Divider, {}),
|
|
1433
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "volr:flex volr:flex-col volr:gap-3", children: [
|
|
1434
|
+
isSocialEnabled && socialProviders.map((provider) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
1435
|
+
SocialOption,
|
|
1436
|
+
{
|
|
1437
|
+
provider,
|
|
1438
|
+
onClick: () => onSelectMethod(provider)
|
|
1439
|
+
},
|
|
1440
|
+
provider
|
|
1441
|
+
)),
|
|
1442
|
+
hasOnlySocialAndWallet && /* @__PURE__ */ jsxRuntime.jsx(Divider, {}),
|
|
1443
|
+
isSiweEnabled && /* @__PURE__ */ jsxRuntime.jsx(WalletOption, { onClick: () => onSelectMethod("siwe") })
|
|
1444
|
+
] }),
|
|
1445
|
+
/* @__PURE__ */ jsxRuntime.jsx(PoweredBy, {})
|
|
1446
|
+
]
|
|
1447
|
+
}
|
|
1448
|
+
)
|
|
1449
|
+
]
|
|
1450
|
+
}
|
|
1451
|
+
);
|
|
1452
|
+
}
|
|
1453
|
+
function CodeInputScreen({ email, onSubmit, onResend }) {
|
|
1454
|
+
const { t } = useI18n();
|
|
1455
|
+
const { accentColor } = useVolrUI();
|
|
1456
|
+
const [digits, setDigits] = React3.useState(Array(6).fill(""));
|
|
1457
|
+
const [error, setError] = React3.useState(null);
|
|
1458
|
+
const [isLoading, setIsLoading] = React3.useState(false);
|
|
1459
|
+
const inputRefs = React3.useRef([]);
|
|
1460
|
+
React3.useEffect(() => {
|
|
1461
|
+
inputRefs.current[0]?.focus();
|
|
1462
|
+
}, []);
|
|
1463
|
+
React3.useEffect(() => {
|
|
1464
|
+
const code = digits.join("");
|
|
1465
|
+
if (code.length === 6 && !isLoading) {
|
|
1466
|
+
handleSubmit(code);
|
|
1467
|
+
}
|
|
1468
|
+
}, [digits]);
|
|
1469
|
+
const handleSubmit = async (code) => {
|
|
1470
|
+
if (code.length !== 6) return;
|
|
1471
|
+
setError(null);
|
|
1472
|
+
setIsLoading(true);
|
|
1473
|
+
try {
|
|
1474
|
+
await onSubmit(code);
|
|
1475
|
+
} catch (err) {
|
|
1476
|
+
setError(err instanceof Error ? err.message : "Invalid code");
|
|
1477
|
+
setDigits(Array(6).fill(""));
|
|
1478
|
+
inputRefs.current[0]?.focus();
|
|
1479
|
+
} finally {
|
|
1480
|
+
setIsLoading(false);
|
|
1481
|
+
}
|
|
1482
|
+
};
|
|
1483
|
+
const handleChange = (index, value) => {
|
|
1484
|
+
if (!/^\d*$/.test(value)) return;
|
|
1485
|
+
const newDigits = [...digits];
|
|
1486
|
+
newDigits[index] = value.slice(-1);
|
|
1487
|
+
setDigits(newDigits);
|
|
1488
|
+
if (value && index < 5) {
|
|
1489
|
+
inputRefs.current[index + 1]?.focus();
|
|
1490
|
+
}
|
|
1491
|
+
};
|
|
1492
|
+
const handleKeyDown = (index, e) => {
|
|
1493
|
+
if (e.key === "Backspace") {
|
|
1494
|
+
if (!digits[index] && index > 0) {
|
|
1495
|
+
inputRefs.current[index - 1]?.focus();
|
|
1496
|
+
} else {
|
|
1497
|
+
const newDigits = [...digits];
|
|
1498
|
+
newDigits[index] = "";
|
|
1499
|
+
setDigits(newDigits);
|
|
1500
|
+
}
|
|
1501
|
+
} else if (e.key === "ArrowLeft" && index > 0) {
|
|
1502
|
+
inputRefs.current[index - 1]?.focus();
|
|
1503
|
+
} else if (e.key === "ArrowRight" && index < 5) {
|
|
1504
|
+
inputRefs.current[index + 1]?.focus();
|
|
1505
|
+
}
|
|
1506
|
+
};
|
|
1507
|
+
const handlePaste = (e) => {
|
|
1508
|
+
e.preventDefault();
|
|
1509
|
+
const pastedData = e.clipboardData.getData("text").replace(/\D/g, "").slice(0, 6);
|
|
1510
|
+
const newDigits = pastedData.split("").concat(Array(6).fill("")).slice(0, 6);
|
|
1511
|
+
setDigits(newDigits);
|
|
1512
|
+
const lastIndex = Math.min(pastedData.length, 5);
|
|
1513
|
+
inputRefs.current[lastIndex]?.focus();
|
|
1514
|
+
};
|
|
1515
|
+
const handleResend = async () => {
|
|
1516
|
+
setError(null);
|
|
1517
|
+
try {
|
|
1518
|
+
await onResend();
|
|
1519
|
+
} catch (err) {
|
|
1520
|
+
setError(err instanceof Error ? err.message : "Failed to resend code");
|
|
1521
|
+
}
|
|
1522
|
+
};
|
|
1523
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1524
|
+
/* @__PURE__ */ jsxRuntime.jsx(ModalTitle2, { size: "3xl", spacing: "tight", children: t("login.email.verifyTitle") }),
|
|
1525
|
+
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "volr:text-sm volr:text-slate-500 volr:mb-8", children: [
|
|
1526
|
+
t("login.email.verifyDescription"),
|
|
1527
|
+
" ",
|
|
1528
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "volr:font-medium volr:text-slate-700", children: email })
|
|
1529
|
+
] }),
|
|
1530
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "volr:flex volr:gap-3 volr:mb-6 volr:justify-center", children: digits.map((digit, index) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
1531
|
+
"input",
|
|
1532
|
+
{
|
|
1533
|
+
ref: (el) => inputRefs.current[index] = el,
|
|
1534
|
+
type: "text",
|
|
1535
|
+
inputMode: "numeric",
|
|
1536
|
+
maxLength: 1,
|
|
1537
|
+
value: digit,
|
|
1538
|
+
onChange: (e) => handleChange(index, e.target.value),
|
|
1539
|
+
onKeyDown: (e) => handleKeyDown(index, e),
|
|
1540
|
+
onPaste: index === 0 ? handlePaste : void 0,
|
|
1541
|
+
disabled: isLoading,
|
|
1542
|
+
className: "volr:w-12 volr:h-14 volr:text-center volr:text-2xl volr:font-semibold volr:rounded-lg volr:border-2 volr:border-slate-300 volr:outline-none volr:transition-all disabled:volr:bg-slate-50 disabled:volr:cursor-not-allowed",
|
|
1543
|
+
style: {
|
|
1544
|
+
borderColor: digit ? accentColor : void 0
|
|
1545
|
+
},
|
|
1546
|
+
onFocus: (e) => {
|
|
1547
|
+
e.target.style.borderColor = accentColor;
|
|
1548
|
+
e.target.style.boxShadow = `0 0 0 3px ${accentColor}20`;
|
|
1549
|
+
},
|
|
1550
|
+
onBlur: (e) => {
|
|
1551
|
+
if (!digit) {
|
|
1552
|
+
e.target.style.borderColor = "#cbd5e1";
|
|
1553
|
+
}
|
|
1554
|
+
e.target.style.boxShadow = "none";
|
|
1555
|
+
}
|
|
1556
|
+
},
|
|
1557
|
+
index
|
|
1558
|
+
)) }),
|
|
1559
|
+
error && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "volr:mb-6 volr:p-3 volr:rounded-lg volr:bg-rose-50 volr:border volr:border-rose-200 volr:text-rose-700 volr:text-sm volr:flex volr:items-start volr:gap-2", children: [
|
|
1560
|
+
/* @__PURE__ */ jsxRuntime.jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "currentColor", className: "volr:flex-shrink-0 volr:mt-0.5", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z" }) }),
|
|
1561
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: error })
|
|
1562
|
+
] }),
|
|
1563
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1564
|
+
"button",
|
|
1565
|
+
{
|
|
1566
|
+
type: "button",
|
|
1567
|
+
onClick: handleResend,
|
|
1568
|
+
disabled: isLoading,
|
|
1569
|
+
className: "volr:w-full volr:py-3 volr:text-sm volr:font-medium volr:rounded-lg volr:transition-colors disabled:volr:opacity-50 disabled:volr:cursor-not-allowed hover:volr:bg-slate-50",
|
|
1570
|
+
style: { color: accentColor },
|
|
1571
|
+
children: t("login.email.resend")
|
|
1572
|
+
}
|
|
1573
|
+
)
|
|
1574
|
+
] });
|
|
1575
|
+
}
|
|
1576
|
+
function SiweLoginScreen({
|
|
1577
|
+
isOpen = true,
|
|
1578
|
+
wrapInModal = true,
|
|
1579
|
+
onSuccess,
|
|
1580
|
+
onBack,
|
|
1581
|
+
onError,
|
|
1582
|
+
onClose
|
|
1583
|
+
}) {
|
|
1584
|
+
const { t } = useI18n();
|
|
1585
|
+
const { accentColor } = useVolrUI();
|
|
1586
|
+
const { requestSiweNonce, verifySiweSignature } = react.useVolrLogin();
|
|
1587
|
+
const [isLoading, setIsLoading] = React3.useState(false);
|
|
1588
|
+
const [step, setStep] = React3.useState("connect");
|
|
1589
|
+
const [account, setAccount] = React3.useState(null);
|
|
1590
|
+
const [error, setError] = React3.useState(null);
|
|
1591
|
+
const [walletConnector, setWalletConnector] = React3.useState(
|
|
1592
|
+
void 0
|
|
1593
|
+
);
|
|
1594
|
+
const detectWalletConnector = () => {
|
|
1595
|
+
if (typeof window === "undefined" || !window.ethereum) {
|
|
1596
|
+
return void 0;
|
|
1597
|
+
}
|
|
1598
|
+
const provider = window.ethereum;
|
|
1599
|
+
console.log(provider.info);
|
|
1600
|
+
if (provider.info?.rdns) {
|
|
1601
|
+
return provider.info.rdns;
|
|
1602
|
+
}
|
|
1603
|
+
if (provider.isMetaMask) return "io.metamask";
|
|
1604
|
+
if (provider.isCoinbaseWallet) return "com.coinbase.wallet";
|
|
1605
|
+
if (provider.isRabby) return "io.rabby";
|
|
1606
|
+
if (provider.isZerion) return "io.zerion";
|
|
1607
|
+
if (provider.isBraveWallet) return "com.brave.wallet";
|
|
1608
|
+
return "unknown";
|
|
1609
|
+
};
|
|
1610
|
+
React3.useEffect(() => {
|
|
1611
|
+
if (typeof window !== "undefined" && window.ethereum) {
|
|
1612
|
+
window.ethereum.request({ method: "eth_accounts" }).then((accounts) => {
|
|
1613
|
+
if (accounts.length > 0) {
|
|
1614
|
+
setAccount(accounts[0]);
|
|
1615
|
+
setStep("sign");
|
|
1616
|
+
setWalletConnector(detectWalletConnector());
|
|
1617
|
+
}
|
|
1618
|
+
}).catch(() => {
|
|
1619
|
+
});
|
|
1620
|
+
}
|
|
1621
|
+
}, []);
|
|
1622
|
+
const handleConnectWallet = async () => {
|
|
1623
|
+
setError(null);
|
|
1624
|
+
setIsLoading(true);
|
|
1625
|
+
try {
|
|
1626
|
+
if (typeof window === "undefined" || !window.ethereum) {
|
|
1627
|
+
throw new Error(
|
|
1628
|
+
"No Ethereum wallet found. Please install MetaMask or another wallet."
|
|
1629
|
+
);
|
|
1630
|
+
}
|
|
1631
|
+
const accounts = await window.ethereum.request({
|
|
1632
|
+
method: "eth_requestAccounts"
|
|
1633
|
+
});
|
|
1634
|
+
if (accounts.length === 0) {
|
|
1635
|
+
throw new Error("No accounts found");
|
|
1636
|
+
}
|
|
1637
|
+
setAccount(accounts[0]);
|
|
1638
|
+
setStep("sign");
|
|
1639
|
+
setWalletConnector(detectWalletConnector());
|
|
1640
|
+
} catch (err) {
|
|
1641
|
+
const errorMessage = err instanceof Error ? err.message : "Failed to connect wallet";
|
|
1642
|
+
setError(errorMessage);
|
|
1643
|
+
onError(err instanceof Error ? err : new Error(errorMessage));
|
|
1644
|
+
} finally {
|
|
1645
|
+
setIsLoading(false);
|
|
1646
|
+
}
|
|
1647
|
+
};
|
|
1648
|
+
const handleSign = async () => {
|
|
1649
|
+
if (!account) return;
|
|
1650
|
+
setError(null);
|
|
1651
|
+
setIsLoading(true);
|
|
1652
|
+
try {
|
|
1653
|
+
const chainIdHex = await window.ethereum.request({
|
|
1654
|
+
method: "eth_chainId"
|
|
1655
|
+
});
|
|
1656
|
+
const chainId = parseInt(chainIdHex, 16);
|
|
1657
|
+
const nonce = await requestSiweNonce();
|
|
1658
|
+
const domain = typeof window !== "undefined" ? window.location.host : "localhost";
|
|
1659
|
+
const origin = typeof window !== "undefined" ? window.location.origin : "http://localhost";
|
|
1660
|
+
const statement = "Sign in with Ethereum to continue";
|
|
1661
|
+
const issuedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1662
|
+
const message = `${domain} wants you to sign in with your Ethereum account:
|
|
1663
|
+
${account}
|
|
1664
|
+
|
|
1665
|
+
${statement}
|
|
1666
|
+
|
|
1667
|
+
URI: ${origin}
|
|
1668
|
+
Version: 1
|
|
1669
|
+
Chain ID: ${chainId}
|
|
1670
|
+
Nonce: ${nonce}
|
|
1671
|
+
Issued At: ${issuedAt}`;
|
|
1672
|
+
const signature = await window.ethereum.request({
|
|
1673
|
+
method: "personal_sign",
|
|
1674
|
+
params: [message, account]
|
|
1675
|
+
});
|
|
1676
|
+
const result = await verifySiweSignature(message, signature, {
|
|
1677
|
+
walletConnector,
|
|
1678
|
+
chainId
|
|
1679
|
+
});
|
|
1680
|
+
onSuccess({
|
|
1681
|
+
userId: result.userId,
|
|
1682
|
+
isNewUser: result.isNewUser,
|
|
1683
|
+
keyStorageType: result.keyStorageType,
|
|
1684
|
+
signerType: result.signerType || null
|
|
1685
|
+
});
|
|
1686
|
+
} catch (err) {
|
|
1687
|
+
const errorMessage = err instanceof Error ? err.message : "Failed to sign message";
|
|
1688
|
+
setError(errorMessage);
|
|
1689
|
+
onError(err instanceof Error ? err : new Error(errorMessage));
|
|
1690
|
+
} finally {
|
|
1691
|
+
setIsLoading(false);
|
|
1692
|
+
}
|
|
1693
|
+
};
|
|
1694
|
+
const content = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "volr:max-w-md volr:mx-auto", children: [
|
|
1695
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1696
|
+
"button",
|
|
1697
|
+
{
|
|
1698
|
+
onClick: onBack,
|
|
1699
|
+
className: "volr:flex volr:items-center volr:gap-1 volr:p-1 volr:border-none volr:bg-transparent volr:cursor-pointer volr:text-sm volr:text-gray-500 volr:mb-4 volr:rounded-lg hover:volr:bg-slate-100 volr:transition-colors",
|
|
1700
|
+
children: [
|
|
1701
|
+
"\u2190 ",
|
|
1702
|
+
t("common.back")
|
|
1703
|
+
]
|
|
1704
|
+
}
|
|
1705
|
+
),
|
|
1706
|
+
/* @__PURE__ */ jsxRuntime.jsx(ModalTitle, { children: t("login.wallet.title") }),
|
|
1707
|
+
account && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "volr:p-3 volr:bg-gray-100 volr:rounded-lg volr:mb-6", children: [
|
|
1708
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "volr:text-xs volr:text-gray-500 volr:mb-1", children: t("login.wallet.connected") }),
|
|
1709
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "volr:text-sm volr:font-medium volr:text-gray-900 volr:font-mono", children: [
|
|
1710
|
+
account.slice(0, 6),
|
|
1711
|
+
"...",
|
|
1712
|
+
account.slice(-4)
|
|
1713
|
+
] })
|
|
1714
|
+
] }),
|
|
1715
|
+
error && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "volr:mb-4 volr:p-3 volr:bg-red-50 volr:border volr:border-red-200 volr:rounded-lg volr:text-red-700 volr:text-sm", children: error }),
|
|
1716
|
+
step === "connect" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1717
|
+
"button",
|
|
1718
|
+
{
|
|
1719
|
+
onClick: handleConnectWallet,
|
|
1720
|
+
disabled: isLoading,
|
|
1721
|
+
className: `volr:w-full volr:py-3 volr:px-6 volr:text-white volr:border-none volr:rounded-lg volr:text-base volr:font-medium volr:transition-all volr:duration-200 ${isLoading ? "volr:bg-gray-400 volr:cursor-not-allowed" : "volr:cursor-pointer"}`,
|
|
1722
|
+
style: {
|
|
1723
|
+
backgroundColor: isLoading ? void 0 : accentColor
|
|
1724
|
+
},
|
|
1725
|
+
children: isLoading ? t("common.loading") : t("login.wallet.connect")
|
|
1726
|
+
}
|
|
1727
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
1728
|
+
"button",
|
|
1729
|
+
{
|
|
1730
|
+
onClick: handleSign,
|
|
1731
|
+
disabled: isLoading,
|
|
1732
|
+
className: `volr:w-full volr:py-3 volr:px-6 volr:text-white volr:border-none volr:rounded-lg volr:text-base volr:font-medium volr:transition-all volr:duration-200 ${isLoading ? "volr:bg-gray-400 volr:cursor-not-allowed" : "volr:cursor-pointer"}`,
|
|
1733
|
+
style: {
|
|
1734
|
+
backgroundColor: isLoading ? void 0 : accentColor
|
|
1735
|
+
},
|
|
1736
|
+
children: isLoading ? t("common.loading") : t("login.wallet.sign")
|
|
1737
|
+
}
|
|
1738
|
+
)
|
|
1739
|
+
] });
|
|
1740
|
+
if (!wrapInModal) {
|
|
1741
|
+
return content;
|
|
1742
|
+
}
|
|
1743
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1744
|
+
Modal,
|
|
1745
|
+
{
|
|
1746
|
+
open: isOpen,
|
|
1747
|
+
onOpenChange: (open) => !open && (onClose?.() || onBack?.()),
|
|
1748
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-w-md mx-auto", children: [
|
|
1749
|
+
/* @__PURE__ */ jsxRuntime.jsx(ModalTitle, { className: "sr-only", children: t("login.wallet.title") }),
|
|
1750
|
+
content
|
|
1751
|
+
] })
|
|
1752
|
+
}
|
|
1753
|
+
);
|
|
1754
|
+
}
|
|
1755
|
+
function LoginSuccessScreen({
|
|
1756
|
+
onClose,
|
|
1757
|
+
delay = 1500
|
|
1758
|
+
}) {
|
|
1759
|
+
const { t } = useI18n();
|
|
1760
|
+
const { accentColor } = useVolrUI();
|
|
1761
|
+
React3.useEffect(() => {
|
|
1762
|
+
const timer = setTimeout(() => {
|
|
1763
|
+
onClose();
|
|
1764
|
+
}, delay);
|
|
1765
|
+
return () => {
|
|
1766
|
+
clearTimeout(timer);
|
|
1767
|
+
};
|
|
1768
|
+
}, [onClose, delay]);
|
|
1769
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "volr:flex volr:flex-col volr:items-center volr:justify-center volr:py-12 volr:px-4", children: [
|
|
1770
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "volr:relative volr:mb-8", children: [
|
|
1771
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1772
|
+
"div",
|
|
1773
|
+
{
|
|
1774
|
+
className: "volr:absolute volr:inset-0 volr:rounded-full volr:blur-2xl volr:opacity-30",
|
|
1775
|
+
style: {
|
|
1776
|
+
backgroundColor: accentColor,
|
|
1777
|
+
animation: "volr-pulse 2s ease-in-out infinite"
|
|
1778
|
+
}
|
|
1779
|
+
}
|
|
1780
|
+
),
|
|
1781
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1782
|
+
"div",
|
|
1783
|
+
{
|
|
1784
|
+
className: "volr:relative volr:w-24 volr:h-24 volr:rounded-full volr:flex volr:items-center volr:justify-center volr:shadow-lg",
|
|
1785
|
+
style: {
|
|
1786
|
+
backgroundColor: accentColor + "c0",
|
|
1787
|
+
animation: "volr-scale-in 0.5s cubic-bezier(0.34, 1.56, 0.64, 1) forwards"
|
|
1788
|
+
},
|
|
1789
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1790
|
+
"svg",
|
|
1791
|
+
{
|
|
1792
|
+
width: "48",
|
|
1793
|
+
height: "48",
|
|
1794
|
+
viewBox: "0 0 24 24",
|
|
1795
|
+
fill: "none",
|
|
1796
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1797
|
+
style: {
|
|
1798
|
+
animation: "volr-fade-in 0.3s ease-out 0.3s both"
|
|
1799
|
+
},
|
|
1800
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1801
|
+
"path",
|
|
1802
|
+
{
|
|
1803
|
+
d: "M5 13L9 17L19 7",
|
|
1804
|
+
stroke: "white",
|
|
1805
|
+
strokeWidth: "2.5",
|
|
1806
|
+
strokeLinecap: "round",
|
|
1807
|
+
strokeLinejoin: "round",
|
|
1808
|
+
style: {
|
|
1809
|
+
strokeDasharray: "24",
|
|
1810
|
+
strokeDashoffset: "24",
|
|
1811
|
+
animation: "volr-check-draw 0.4s ease-out 0.3s forwards"
|
|
1812
|
+
}
|
|
1813
|
+
}
|
|
1814
|
+
)
|
|
1815
|
+
}
|
|
1816
|
+
)
|
|
1817
|
+
}
|
|
1818
|
+
)
|
|
1819
|
+
] }),
|
|
1820
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1821
|
+
"div",
|
|
1822
|
+
{
|
|
1823
|
+
className: "volr:text-center volr:space-y-2",
|
|
1824
|
+
style: {
|
|
1825
|
+
animation: "volr-fade-in-up 0.5s ease-out 0.5s both"
|
|
1826
|
+
},
|
|
1827
|
+
children: [
|
|
1828
|
+
/* @__PURE__ */ jsxRuntime.jsx(ModalTitle2, { size: "2xl", spacing: "tight", children: t("success.title") }),
|
|
1829
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "volr:text-base volr:text-slate-600", children: t("success.message") || "You're all set. Redirecting..." })
|
|
1830
|
+
]
|
|
1831
|
+
}
|
|
1832
|
+
),
|
|
1833
|
+
/* @__PURE__ */ jsxRuntime.jsx("style", { children: `
|
|
1834
|
+
@keyframes volr-scale-in {
|
|
1835
|
+
0% {
|
|
1836
|
+
transform: scale(0);
|
|
1837
|
+
opacity: 0;
|
|
1838
|
+
}
|
|
1839
|
+
100% {
|
|
1840
|
+
transform: scale(1);
|
|
1841
|
+
opacity: 1;
|
|
1842
|
+
}
|
|
1843
|
+
}
|
|
1844
|
+
|
|
1845
|
+
@keyframes volr-check-draw {
|
|
1846
|
+
0% {
|
|
1847
|
+
stroke-dashoffset: 24;
|
|
1848
|
+
}
|
|
1849
|
+
100% {
|
|
1850
|
+
stroke-dashoffset: 0;
|
|
1851
|
+
}
|
|
1852
|
+
}
|
|
1853
|
+
|
|
1854
|
+
@keyframes volr-fade-in {
|
|
1855
|
+
0% {
|
|
1856
|
+
opacity: 0;
|
|
1857
|
+
}
|
|
1858
|
+
100% {
|
|
1859
|
+
opacity: 1;
|
|
1860
|
+
}
|
|
1861
|
+
}
|
|
1862
|
+
|
|
1863
|
+
@keyframes volr-fade-in-up {
|
|
1864
|
+
0% {
|
|
1865
|
+
opacity: 0;
|
|
1866
|
+
transform: translateY(10px);
|
|
1867
|
+
}
|
|
1868
|
+
100% {
|
|
1869
|
+
opacity: 1;
|
|
1870
|
+
transform: translateY(0);
|
|
1871
|
+
}
|
|
1872
|
+
}
|
|
1873
|
+
|
|
1874
|
+
@keyframes volr-pulse {
|
|
1875
|
+
0%, 100% {
|
|
1876
|
+
transform: scale(1);
|
|
1877
|
+
opacity: 0.3;
|
|
1878
|
+
}
|
|
1879
|
+
50% {
|
|
1880
|
+
transform: scale(1.1);
|
|
1881
|
+
opacity: 0.2;
|
|
1882
|
+
}
|
|
1883
|
+
}
|
|
1884
|
+
` })
|
|
1885
|
+
] });
|
|
1886
|
+
}
|
|
1887
|
+
function SigninModal({ isOpen, onClose, onError }) {
|
|
1888
|
+
const { config, logout, user } = react.useVolr();
|
|
1889
|
+
const { appName, branding } = useVolrUI();
|
|
1890
|
+
const { requestEmailCode, verifyEmailCode } = react.useVolrLogin();
|
|
1891
|
+
const [currentScreen, setCurrentScreen] = React3.useState("method-select");
|
|
1892
|
+
const [email, setEmail] = React3.useState("");
|
|
1893
|
+
const hasPasskey = user?.keyStorageType === "passkey";
|
|
1894
|
+
const isMobile = useMediaQuery("(max-width: 500px)");
|
|
1895
|
+
const isWideViewport = useMediaQuery("(min-width: 864px)");
|
|
1896
|
+
const shouldUseWideLayout = !isMobile && isWideViewport && Boolean(branding) && currentScreen === "method-select";
|
|
1897
|
+
React3.useEffect(() => {
|
|
1898
|
+
if (!isOpen) {
|
|
1899
|
+
setCurrentScreen("method-select");
|
|
1900
|
+
setEmail("");
|
|
1901
|
+
}
|
|
1902
|
+
}, [isOpen]);
|
|
1903
|
+
if (!isOpen) {
|
|
1904
|
+
return null;
|
|
1905
|
+
}
|
|
1906
|
+
const handleSelectMethod = (method) => {
|
|
1907
|
+
if (method === "siwe") {
|
|
1908
|
+
setCurrentScreen("siwe-login");
|
|
1909
|
+
} else {
|
|
1910
|
+
handleSocialLogin(method);
|
|
1911
|
+
}
|
|
1912
|
+
};
|
|
1913
|
+
const handleSocialLogin = (provider) => {
|
|
1914
|
+
const baseUrl = config.apiBaseUrl.replace(/\/+$/, "");
|
|
1915
|
+
const projectApiKey = config.projectApiKey;
|
|
1916
|
+
window.location.href = `${baseUrl}/auth/${provider}?projectApiKey=${encodeURIComponent(
|
|
1917
|
+
projectApiKey
|
|
1918
|
+
)}`;
|
|
1919
|
+
};
|
|
1920
|
+
const handleEmailSubmit = async (emailValue) => {
|
|
1921
|
+
setEmail(emailValue);
|
|
1922
|
+
await requestEmailCode(emailValue);
|
|
1923
|
+
setCurrentScreen("code-input");
|
|
1924
|
+
};
|
|
1925
|
+
const handleCodeSubmit = async (code) => {
|
|
1926
|
+
const result = await verifyEmailCode(email, code);
|
|
1927
|
+
if (result.keyStorageType) {
|
|
1928
|
+
setCurrentScreen("success");
|
|
1929
|
+
return;
|
|
1930
|
+
}
|
|
1931
|
+
if (result.isNewUser) {
|
|
1932
|
+
setCurrentScreen("passkey-setup");
|
|
1933
|
+
} else {
|
|
1934
|
+
setCurrentScreen("success");
|
|
1935
|
+
}
|
|
1936
|
+
};
|
|
1937
|
+
const handleSiweSuccess = (data) => {
|
|
1938
|
+
if (data.keyStorageType) {
|
|
1939
|
+
setCurrentScreen("success");
|
|
1940
|
+
return;
|
|
1941
|
+
}
|
|
1942
|
+
setCurrentScreen("passkey-setup");
|
|
1943
|
+
};
|
|
1944
|
+
const handlePasskeyComplete = () => {
|
|
1945
|
+
setCurrentScreen("success");
|
|
1946
|
+
};
|
|
1947
|
+
const handlePasskeyError = (error) => {
|
|
1948
|
+
if (onError) {
|
|
1949
|
+
onError(error);
|
|
1950
|
+
}
|
|
1951
|
+
};
|
|
1952
|
+
const handleLogout = async () => {
|
|
1953
|
+
try {
|
|
1954
|
+
await logout();
|
|
1955
|
+
setCurrentScreen("method-select");
|
|
1956
|
+
setEmail("");
|
|
1957
|
+
onClose();
|
|
1958
|
+
} catch (error) {
|
|
1959
|
+
if (onError) {
|
|
1960
|
+
onError(error instanceof Error ? error : new Error("Logout failed"));
|
|
1961
|
+
}
|
|
1962
|
+
}
|
|
1963
|
+
};
|
|
1964
|
+
const handleSuccessClose = () => {
|
|
1965
|
+
setCurrentScreen("method-select");
|
|
1966
|
+
setEmail("");
|
|
1967
|
+
onClose();
|
|
1968
|
+
};
|
|
1969
|
+
const handleBackdropClick = (_e) => {
|
|
1970
|
+
if (currentScreen !== "passkey-setup" || hasPasskey) {
|
|
1971
|
+
setCurrentScreen("method-select");
|
|
1972
|
+
setEmail("");
|
|
1973
|
+
onClose();
|
|
1974
|
+
}
|
|
1975
|
+
};
|
|
1976
|
+
const handleModalClose = () => {
|
|
1977
|
+
onClose();
|
|
1978
|
+
};
|
|
1979
|
+
const renderCurrentScreen = () => {
|
|
1980
|
+
switch (currentScreen) {
|
|
1981
|
+
case "method-select":
|
|
1982
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1983
|
+
SigninSelectScreen,
|
|
1984
|
+
{
|
|
1985
|
+
onClose,
|
|
1986
|
+
onSelectMethod: handleSelectMethod,
|
|
1987
|
+
onEmailSubmit: handleEmailSubmit,
|
|
1988
|
+
appName,
|
|
1989
|
+
branding: shouldUseWideLayout ? branding : void 0
|
|
1990
|
+
},
|
|
1991
|
+
"method-select"
|
|
1992
|
+
);
|
|
1993
|
+
case "code-input":
|
|
1994
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1995
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1996
|
+
ModalHeader,
|
|
1997
|
+
{
|
|
1998
|
+
back: true,
|
|
1999
|
+
onBack: () => setCurrentScreen("method-select"),
|
|
2000
|
+
onClose
|
|
2001
|
+
}
|
|
2002
|
+
),
|
|
2003
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2004
|
+
CodeInputScreen,
|
|
2005
|
+
{
|
|
2006
|
+
email,
|
|
2007
|
+
onSubmit: handleCodeSubmit,
|
|
2008
|
+
onBack: () => setCurrentScreen("method-select"),
|
|
2009
|
+
onResend: () => requestEmailCode(email)
|
|
2010
|
+
},
|
|
2011
|
+
"code-input"
|
|
2012
|
+
)
|
|
2013
|
+
] });
|
|
2014
|
+
case "siwe-login":
|
|
2015
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2016
|
+
SiweLoginScreen,
|
|
2017
|
+
{
|
|
2018
|
+
wrapInModal: false,
|
|
2019
|
+
onSuccess: handleSiweSuccess,
|
|
2020
|
+
onBack: () => setCurrentScreen("method-select"),
|
|
2021
|
+
onError: handlePasskeyError
|
|
2022
|
+
},
|
|
2023
|
+
"siwe-login"
|
|
2024
|
+
);
|
|
2025
|
+
case "passkey-setup":
|
|
2026
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2027
|
+
PasskeyEnrollView,
|
|
2028
|
+
{
|
|
2029
|
+
wrapInModal: false,
|
|
2030
|
+
onComplete: handlePasskeyComplete,
|
|
2031
|
+
onError: handlePasskeyError,
|
|
2032
|
+
onLogout: handleLogout,
|
|
2033
|
+
onClose: handleSuccessClose
|
|
2034
|
+
},
|
|
2035
|
+
"passkey-setup"
|
|
2036
|
+
);
|
|
2037
|
+
case "success":
|
|
2038
|
+
return /* @__PURE__ */ jsxRuntime.jsx(LoginSuccessScreen, { onClose: handleSuccessClose }, "success");
|
|
2039
|
+
default:
|
|
2040
|
+
return null;
|
|
2041
|
+
}
|
|
2042
|
+
};
|
|
2043
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2044
|
+
Modal,
|
|
2045
|
+
{
|
|
2046
|
+
open: isOpen,
|
|
2047
|
+
onOpenChange: (open) => !open && handleModalClose(),
|
|
2048
|
+
onPointerDownOutside: (e) => {
|
|
2049
|
+
handleBackdropClick();
|
|
2050
|
+
},
|
|
2051
|
+
onEscapeKeyDown: (e) => {
|
|
2052
|
+
if (currentScreen === "passkey-setup" && !hasPasskey) {
|
|
2053
|
+
e.preventDefault();
|
|
2054
|
+
}
|
|
2055
|
+
},
|
|
2056
|
+
contentClassName: isMobile ? "volr:max-w-none" : shouldUseWideLayout ? "volr:max-w-4xl volr:w-full volr:p-3" : void 0,
|
|
2057
|
+
children: [
|
|
2058
|
+
renderCurrentScreen(),
|
|
2059
|
+
/* @__PURE__ */ jsxRuntime.jsx("style", { children: `
|
|
2060
|
+
@keyframes spin {
|
|
2061
|
+
from {
|
|
2062
|
+
transform: rotate(0deg);
|
|
2063
|
+
}
|
|
2064
|
+
to {
|
|
2065
|
+
transform: rotate(360deg);
|
|
2066
|
+
}
|
|
2067
|
+
}
|
|
2068
|
+
` })
|
|
2069
|
+
]
|
|
2070
|
+
}
|
|
2071
|
+
);
|
|
2072
|
+
}
|
|
2073
|
+
function AssetSelectView({
|
|
2074
|
+
assets,
|
|
2075
|
+
onSelect
|
|
2076
|
+
}) {
|
|
2077
|
+
const { t } = useI18n();
|
|
2078
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "volr:px-6 volr:pb-6", children: [
|
|
2079
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "volr:text-2xl volr:font-bold volr:text-slate-900 volr:mb-2 volr:text-center", children: t("deposit.selectTitle") }),
|
|
2080
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "volr:text-sm volr:text-slate-500 volr:mb-8 volr:text-center", children: "Supported token" }),
|
|
2081
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "volr:space-y-3", children: assets.map((a, idx) => {
|
|
2082
|
+
const isNative = a.token === "native";
|
|
2083
|
+
const tokenSymbol = isNative ? "ETH" : a.token.symbol;
|
|
2084
|
+
const tokenName = isNative ? "Ethereum" : a.token.symbol;
|
|
2085
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2086
|
+
"button",
|
|
2087
|
+
{
|
|
2088
|
+
className: cn(
|
|
2089
|
+
"volr:w-full volr:p-4 volr:rounded-xl volr:border-2 volr:border-slate-200",
|
|
2090
|
+
"volr:text-left volr:transition-all",
|
|
2091
|
+
"hover:volr:border-slate-300 hover:volr:bg-slate-50 hover:volr:shadow-sm",
|
|
2092
|
+
"volr:flex volr:items-center volr:gap-4"
|
|
2093
|
+
),
|
|
2094
|
+
onClick: () => onSelect(idx),
|
|
2095
|
+
children: [
|
|
2096
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "volr:flex-shrink-0", children: !isNative && a.token.iconUrl ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2097
|
+
"img",
|
|
2098
|
+
{
|
|
2099
|
+
alt: a.token.symbol,
|
|
2100
|
+
src: a.token.iconUrl,
|
|
2101
|
+
className: "volr:w-10 volr:h-10 volr:rounded-full volr:border volr:border-slate-200"
|
|
2102
|
+
}
|
|
2103
|
+
) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "volr:w-10 volr:h-10 volr:rounded-full volr:bg-gradient-to-br volr:from-blue-500 volr:to-purple-600 volr:flex volr:items-center volr:justify-center volr:text-white volr:font-bold volr:text-sm", children: tokenSymbol.slice(0, 2) }) }),
|
|
2104
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "volr:flex-1 volr:min-w-0", children: [
|
|
2105
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "volr:flex volr:items-center volr:gap-2 volr:mb-1", children: [
|
|
2106
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "volr:text-base volr:font-semibold volr:text-slate-900", children: tokenSymbol }),
|
|
2107
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "volr:text-xs volr:px-2 volr:py-0.5 volr:rounded-full volr:bg-slate-100 volr:text-slate-600 volr:font-medium", children: [
|
|
2108
|
+
"Chain ",
|
|
2109
|
+
a.chainId
|
|
2110
|
+
] })
|
|
2111
|
+
] }),
|
|
2112
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "volr:text-sm volr:text-slate-500", children: tokenName }),
|
|
2113
|
+
!isNative && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "volr:text-xs volr:text-slate-400 volr:font-mono volr:truncate volr:mt-1", children: a.token.address })
|
|
2114
|
+
] }),
|
|
2115
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "volr:flex-shrink-0 volr:text-slate-400", children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "9 18 15 12 9 6" }) }) })
|
|
2116
|
+
]
|
|
2117
|
+
},
|
|
2118
|
+
`${a.chainId}-${idx}`
|
|
2119
|
+
);
|
|
2120
|
+
}) })
|
|
2121
|
+
] });
|
|
2122
|
+
}
|
|
2123
|
+
var CopyButton = ({ text, className, onCopy }) => {
|
|
2124
|
+
const [copied, setCopied] = React3.useState(false);
|
|
2125
|
+
const handleCopy = async () => {
|
|
2126
|
+
try {
|
|
2127
|
+
await navigator.clipboard.writeText(text);
|
|
2128
|
+
setCopied(true);
|
|
2129
|
+
setTimeout(() => setCopied(false), 2e3);
|
|
2130
|
+
onCopy?.();
|
|
2131
|
+
} catch (error) {
|
|
2132
|
+
console.error("Copy failed:", error);
|
|
2133
|
+
}
|
|
2134
|
+
};
|
|
2135
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2136
|
+
"button",
|
|
2137
|
+
{
|
|
2138
|
+
onClick: handleCopy,
|
|
2139
|
+
className: cn(
|
|
2140
|
+
"volr:p-2 volr:rounded-lg volr:text-slate-400 hover:volr:text-slate-700 hover:volr:bg-white volr:transition-all",
|
|
2141
|
+
className
|
|
2142
|
+
),
|
|
2143
|
+
"aria-label": "Copy",
|
|
2144
|
+
children: copied ? /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", children: /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "20 6 9 17 4 12" }) }) : /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
|
|
2145
|
+
/* @__PURE__ */ jsxRuntime.jsx("rect", { x: "9", y: "9", width: "13", height: "13", rx: "2", ry: "2" }),
|
|
2146
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" })
|
|
2147
|
+
] })
|
|
2148
|
+
}
|
|
2149
|
+
);
|
|
2150
|
+
};
|
|
2151
|
+
var TextLinkButton = React3__default.default.forwardRef(({ showArrow = false, className, children, ...props }, ref) => {
|
|
2152
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2153
|
+
"button",
|
|
2154
|
+
{
|
|
2155
|
+
ref,
|
|
2156
|
+
type: "button",
|
|
2157
|
+
className: cn(
|
|
2158
|
+
"volr:text-slate-600 hover:volr:text-slate-900 volr:underline volr:transition-colors",
|
|
2159
|
+
className
|
|
2160
|
+
),
|
|
2161
|
+
...props,
|
|
2162
|
+
children: [
|
|
2163
|
+
children,
|
|
2164
|
+
showArrow && " \u2192"
|
|
2165
|
+
]
|
|
2166
|
+
}
|
|
2167
|
+
);
|
|
2168
|
+
});
|
|
2169
|
+
TextLinkButton.displayName = "TextLinkButton";
|
|
2170
|
+
var OtherTokenModal = ({
|
|
2171
|
+
open,
|
|
2172
|
+
onOpenChange
|
|
2173
|
+
}) => {
|
|
2174
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Modal, { open, onOpenChange, children: [
|
|
2175
|
+
/* @__PURE__ */ jsxRuntime.jsx(ModalHeader, { onClose: () => onOpenChange(false) }),
|
|
2176
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "volr:px-6 volr:pb-6 volr:text-center", children: [
|
|
2177
|
+
/* @__PURE__ */ jsxRuntime.jsx(ModalTitle2, { className: "volr:mb-4", children: "Coming Soon" }),
|
|
2178
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "volr:text-sm volr:text-slate-600", children: "Swap and bridge recommendations will be available here soon." })
|
|
2179
|
+
] })
|
|
2180
|
+
] });
|
|
2181
|
+
};
|
|
2182
|
+
var DepositQRStatusOverlay = ({
|
|
2183
|
+
status
|
|
2184
|
+
}) => {
|
|
2185
|
+
if (status !== "detected") return null;
|
|
2186
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2187
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2188
|
+
"div",
|
|
2189
|
+
{
|
|
2190
|
+
className: "volr:absolute volr:inset-0 volr:rounded-2xl volr:pointer-events-none",
|
|
2191
|
+
style: {
|
|
2192
|
+
boxShadow: "0 0 0 4px rgba(16, 185, 129, 0.3), 0 0 30px rgba(16, 185, 129, 0.4)",
|
|
2193
|
+
animation: "volrPulseGlow 1.5s ease-out infinite"
|
|
2194
|
+
}
|
|
2195
|
+
}
|
|
2196
|
+
),
|
|
2197
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "volr:absolute volr:inset-0 volr:overflow-visible volr:pointer-events-none volr:-z-10", children: [
|
|
2198
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2199
|
+
"div",
|
|
2200
|
+
{
|
|
2201
|
+
className: "volr:absolute volr:w-48 volr:h-48 volr:rounded-full volr:opacity-0",
|
|
2202
|
+
style: {
|
|
2203
|
+
background: "radial-gradient(circle, rgba(16,185,129,0.7) 0%, rgba(16,185,129,0) 60%)",
|
|
2204
|
+
filter: "blur(50px)",
|
|
2205
|
+
top: "5%",
|
|
2206
|
+
left: "0%",
|
|
2207
|
+
animation: "volrGlowPulse 1.8s ease-out forwards"
|
|
2208
|
+
}
|
|
2209
|
+
}
|
|
2210
|
+
),
|
|
2211
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2212
|
+
"div",
|
|
2213
|
+
{
|
|
2214
|
+
className: "volr:absolute volr:w-44 volr:h-44 volr:rounded-full volr:opacity-0",
|
|
2215
|
+
style: {
|
|
2216
|
+
background: "radial-gradient(circle, rgba(6,182,212,0.65) 0%, rgba(6,182,212,0) 60%)",
|
|
2217
|
+
filter: "blur(45px)",
|
|
2218
|
+
bottom: "10%",
|
|
2219
|
+
right: "-5%",
|
|
2220
|
+
animation: "volrGlowPulse 2s ease-out 0.1s forwards"
|
|
2221
|
+
}
|
|
2222
|
+
}
|
|
2223
|
+
),
|
|
2224
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2225
|
+
"div",
|
|
2226
|
+
{
|
|
2227
|
+
className: "volr:absolute volr:w-40 volr:h-40 volr:rounded-full volr:opacity-0",
|
|
2228
|
+
style: {
|
|
2229
|
+
background: "radial-gradient(circle, rgba(20,184,166,0.6) 0%, rgba(20,184,166,0) 60%)",
|
|
2230
|
+
filter: "blur(40px)",
|
|
2231
|
+
top: "50%",
|
|
2232
|
+
left: "50%",
|
|
2233
|
+
transform: "translateX(-50%)",
|
|
2234
|
+
animation: "volrGlowPulse 2.2s ease-out 0.2s forwards"
|
|
2235
|
+
}
|
|
2236
|
+
}
|
|
2237
|
+
)
|
|
2238
|
+
] }),
|
|
2239
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2240
|
+
"div",
|
|
2241
|
+
{
|
|
2242
|
+
className: "volr:absolute volr:-top-3 volr:-right-3 volr:rounded-full volr:p-3 volr:bg-gradient-to-br volr:from-emerald-400 volr:to-teal-500 volr:shadow-2xl volr:shadow-emerald-500/50 volr:border-4 volr:border-white volr:z-20",
|
|
2243
|
+
style: {
|
|
2244
|
+
animation: "volrBounceIn 0.5s cubic-bezier(0.68, -0.55, 0.265, 1.55) forwards"
|
|
2245
|
+
},
|
|
2246
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2247
|
+
"svg",
|
|
2248
|
+
{
|
|
2249
|
+
width: "20",
|
|
2250
|
+
height: "20",
|
|
2251
|
+
viewBox: "0 0 24 24",
|
|
2252
|
+
fill: "none",
|
|
2253
|
+
stroke: "white",
|
|
2254
|
+
strokeWidth: "3",
|
|
2255
|
+
strokeLinecap: "round",
|
|
2256
|
+
strokeLinejoin: "round",
|
|
2257
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "20 6 9 17 4 12" })
|
|
2258
|
+
}
|
|
2259
|
+
)
|
|
2260
|
+
}
|
|
2261
|
+
),
|
|
2262
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "volr:absolute volr:inset-0 volr:pointer-events-none volr:overflow-visible", children: [
|
|
2263
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2264
|
+
"div",
|
|
2265
|
+
{
|
|
2266
|
+
className: "volr:absolute volr:w-2 volr:h-2 volr:bg-emerald-400 volr:rounded-full volr:opacity-0",
|
|
2267
|
+
style: {
|
|
2268
|
+
top: "20%",
|
|
2269
|
+
left: "20%",
|
|
2270
|
+
animation: "volrParticle1 1s ease-out forwards"
|
|
2271
|
+
}
|
|
2272
|
+
}
|
|
2273
|
+
),
|
|
2274
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2275
|
+
"div",
|
|
2276
|
+
{
|
|
2277
|
+
className: "volr:absolute volr:w-1.5 volr:h-1.5 volr:bg-cyan-400 volr:rounded-full volr:opacity-0",
|
|
2278
|
+
style: {
|
|
2279
|
+
top: "30%",
|
|
2280
|
+
right: "25%",
|
|
2281
|
+
animation: "volrParticle2 1.2s ease-out 0.1s forwards"
|
|
2282
|
+
}
|
|
2283
|
+
}
|
|
2284
|
+
),
|
|
2285
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2286
|
+
"div",
|
|
2287
|
+
{
|
|
2288
|
+
className: "volr:absolute volr:w-2 volr:h-2 volr:bg-teal-400 volr:rounded-full volr:opacity-0",
|
|
2289
|
+
style: {
|
|
2290
|
+
bottom: "25%",
|
|
2291
|
+
left: "30%",
|
|
2292
|
+
animation: "volrParticle3 1.1s ease-out 0.2s forwards"
|
|
2293
|
+
}
|
|
2294
|
+
}
|
|
2295
|
+
),
|
|
2296
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2297
|
+
"div",
|
|
2298
|
+
{
|
|
2299
|
+
className: "volr:absolute volr:w-1.5 volr:h-1.5 volr:bg-emerald-300 volr:rounded-full volr:opacity-0",
|
|
2300
|
+
style: {
|
|
2301
|
+
bottom: "30%",
|
|
2302
|
+
right: "20%",
|
|
2303
|
+
animation: "volrParticle4 1.3s ease-out 0.15s forwards"
|
|
2304
|
+
}
|
|
2305
|
+
}
|
|
2306
|
+
)
|
|
2307
|
+
] }),
|
|
2308
|
+
/* @__PURE__ */ jsxRuntime.jsx("style", { children: `
|
|
2309
|
+
@keyframes volrGlowPulse {
|
|
2310
|
+
0% {
|
|
2311
|
+
transform: scale(0.5);
|
|
2312
|
+
opacity: 0;
|
|
2313
|
+
}
|
|
2314
|
+
40% {
|
|
2315
|
+
opacity: 1;
|
|
2316
|
+
}
|
|
2317
|
+
100% {
|
|
2318
|
+
transform: scale(1.6);
|
|
2319
|
+
opacity: 0;
|
|
2320
|
+
}
|
|
2321
|
+
}
|
|
2322
|
+
@keyframes volrBounceIn {
|
|
2323
|
+
0% {
|
|
2324
|
+
transform: scale(0);
|
|
2325
|
+
opacity: 0;
|
|
2326
|
+
}
|
|
2327
|
+
50% {
|
|
2328
|
+
transform: scale(1.2);
|
|
2329
|
+
}
|
|
2330
|
+
70% {
|
|
2331
|
+
transform: scale(0.9);
|
|
2332
|
+
}
|
|
2333
|
+
100% {
|
|
2334
|
+
transform: scale(1);
|
|
2335
|
+
opacity: 1;
|
|
2336
|
+
}
|
|
2337
|
+
}
|
|
2338
|
+
@keyframes volrPulseGlow {
|
|
2339
|
+
0%, 100% {
|
|
2340
|
+
opacity: 0.6;
|
|
2341
|
+
}
|
|
2342
|
+
50% {
|
|
2343
|
+
opacity: 1;
|
|
2344
|
+
}
|
|
2345
|
+
}
|
|
2346
|
+
@keyframes volrParticle1 {
|
|
2347
|
+
0% {
|
|
2348
|
+
transform: translate(0, 0) scale(0);
|
|
2349
|
+
opacity: 0;
|
|
2350
|
+
}
|
|
2351
|
+
20% {
|
|
2352
|
+
opacity: 1;
|
|
2353
|
+
}
|
|
2354
|
+
100% {
|
|
2355
|
+
transform: translate(-20px, -30px) scale(1);
|
|
2356
|
+
opacity: 0;
|
|
2357
|
+
}
|
|
2358
|
+
}
|
|
2359
|
+
@keyframes volrParticle2 {
|
|
2360
|
+
0% {
|
|
2361
|
+
transform: translate(0, 0) scale(0);
|
|
2362
|
+
opacity: 0;
|
|
2363
|
+
}
|
|
2364
|
+
20% {
|
|
2365
|
+
opacity: 1;
|
|
2366
|
+
}
|
|
2367
|
+
100% {
|
|
2368
|
+
transform: translate(25px, -35px) scale(1);
|
|
2369
|
+
opacity: 0;
|
|
2370
|
+
}
|
|
2371
|
+
}
|
|
2372
|
+
@keyframes volrParticle3 {
|
|
2373
|
+
0% {
|
|
2374
|
+
transform: translate(0, 0) scale(0);
|
|
2375
|
+
opacity: 0;
|
|
2376
|
+
}
|
|
2377
|
+
20% {
|
|
2378
|
+
opacity: 1;
|
|
2379
|
+
}
|
|
2380
|
+
100% {
|
|
2381
|
+
transform: translate(-30px, 25px) scale(1);
|
|
2382
|
+
opacity: 0;
|
|
2383
|
+
}
|
|
2384
|
+
}
|
|
2385
|
+
@keyframes volrParticle4 {
|
|
2386
|
+
0% {
|
|
2387
|
+
transform: translate(0, 0) scale(0);
|
|
2388
|
+
opacity: 0;
|
|
2389
|
+
}
|
|
2390
|
+
20% {
|
|
2391
|
+
opacity: 1;
|
|
2392
|
+
}
|
|
2393
|
+
100% {
|
|
2394
|
+
transform: translate(30px, 30px) scale(1);
|
|
2395
|
+
opacity: 0;
|
|
2396
|
+
}
|
|
2397
|
+
}
|
|
2398
|
+
` })
|
|
2399
|
+
] });
|
|
2400
|
+
};
|
|
2401
|
+
var DepositCompletedToast = ({
|
|
2402
|
+
onClose,
|
|
2403
|
+
previousBalance,
|
|
2404
|
+
newBalance,
|
|
2405
|
+
delta,
|
|
2406
|
+
decimals,
|
|
2407
|
+
symbol
|
|
2408
|
+
}) => {
|
|
2409
|
+
const { t } = useI18n();
|
|
2410
|
+
const [expanded, setExpanded] = React3.useState(false);
|
|
2411
|
+
const formatAmount = (amount) => {
|
|
2412
|
+
const divisor = BigInt(10 ** decimals);
|
|
2413
|
+
const whole = amount / divisor;
|
|
2414
|
+
const fraction = amount % divisor;
|
|
2415
|
+
const fractionStr = fraction.toString().padStart(decimals, "0").slice(0, 4);
|
|
2416
|
+
return `${whole}.${fractionStr}`;
|
|
2417
|
+
};
|
|
2418
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2419
|
+
"div",
|
|
2420
|
+
{
|
|
2421
|
+
className: cn(
|
|
2422
|
+
"volr:absolute volr:bottom-0 volr:left-0 volr:right-0",
|
|
2423
|
+
"volr:bg-white volr:border-t volr:border-slate-200 volr:shadow-lg",
|
|
2424
|
+
"volr:transition-all volr:duration-300 volr:ease-out",
|
|
2425
|
+
expanded ? "volr:max-h-96" : "volr:max-h-24"
|
|
2426
|
+
),
|
|
2427
|
+
style: {
|
|
2428
|
+
animation: "volrSlideUp 0.3s ease-out"
|
|
2429
|
+
},
|
|
2430
|
+
children: [
|
|
2431
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "volr:p-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "volr:flex volr:items-start volr:gap-3", children: [
|
|
2432
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "volr:flex-shrink-0 volr:w-10 volr:h-10 volr:rounded-full volr:bg-gradient-to-br volr:from-emerald-500 volr:to-teal-500 volr:flex volr:items-center volr:justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2433
|
+
"svg",
|
|
2434
|
+
{
|
|
2435
|
+
width: "20",
|
|
2436
|
+
height: "20",
|
|
2437
|
+
viewBox: "0 0 24 24",
|
|
2438
|
+
fill: "none",
|
|
2439
|
+
stroke: "white",
|
|
2440
|
+
strokeWidth: "2.5",
|
|
2441
|
+
strokeLinecap: "round",
|
|
2442
|
+
strokeLinejoin: "round",
|
|
2443
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "20 6 9 17 4 12" })
|
|
2444
|
+
}
|
|
2445
|
+
) }),
|
|
2446
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "volr:flex-1 volr:min-w-0", children: [
|
|
2447
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "volr:flex volr:items-start volr:justify-between volr:gap-2 volr:mb-1", children: [
|
|
2448
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "volr:text-sm volr:font-semibold volr:text-slate-900", children: t("deposit.completed") }),
|
|
2449
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2450
|
+
"button",
|
|
2451
|
+
{
|
|
2452
|
+
onClick: onClose,
|
|
2453
|
+
className: "volr:flex-shrink-0 volr:text-slate-400 hover:volr:text-slate-600 volr:transition-colors",
|
|
2454
|
+
"aria-label": "Close",
|
|
2455
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2456
|
+
"svg",
|
|
2457
|
+
{
|
|
2458
|
+
width: "16",
|
|
2459
|
+
height: "16",
|
|
2460
|
+
viewBox: "0 0 24 24",
|
|
2461
|
+
fill: "none",
|
|
2462
|
+
stroke: "currentColor",
|
|
2463
|
+
strokeWidth: "2",
|
|
2464
|
+
children: [
|
|
2465
|
+
/* @__PURE__ */ jsxRuntime.jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
|
|
2466
|
+
/* @__PURE__ */ jsxRuntime.jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
|
|
2467
|
+
]
|
|
2468
|
+
}
|
|
2469
|
+
)
|
|
2470
|
+
}
|
|
2471
|
+
)
|
|
2472
|
+
] }),
|
|
2473
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "volr:text-xs volr:text-slate-600 volr:mb-3", children: t("deposit.completedDescription") }),
|
|
2474
|
+
expanded && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "volr:space-y-2 volr:mb-3 volr:animate-[volrFadeIn_0.2s_ease-out]", children: [
|
|
2475
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "volr:flex volr:justify-between volr:text-xs", children: [
|
|
2476
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "volr:text-slate-500", children: t("deposit.amount") }),
|
|
2477
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "volr:font-mono volr:text-slate-900 volr:font-medium", children: [
|
|
2478
|
+
"+",
|
|
2479
|
+
formatAmount(delta),
|
|
2480
|
+
" ",
|
|
2481
|
+
symbol
|
|
2482
|
+
] })
|
|
2483
|
+
] }),
|
|
2484
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "volr:flex volr:justify-between volr:text-xs", children: [
|
|
2485
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "volr:text-slate-500", children: t("deposit.previousBalance") }),
|
|
2486
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "volr:font-mono volr:text-slate-600", children: [
|
|
2487
|
+
formatAmount(previousBalance),
|
|
2488
|
+
" ",
|
|
2489
|
+
symbol
|
|
2490
|
+
] })
|
|
2491
|
+
] }),
|
|
2492
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "volr:flex volr:justify-between volr:text-xs", children: [
|
|
2493
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "volr:text-slate-500", children: t("deposit.newBalance") }),
|
|
2494
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "volr:font-mono volr:text-slate-900 volr:font-semibold", children: [
|
|
2495
|
+
formatAmount(newBalance),
|
|
2496
|
+
" ",
|
|
2497
|
+
symbol
|
|
2498
|
+
] })
|
|
2499
|
+
] })
|
|
2500
|
+
] }),
|
|
2501
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2502
|
+
"button",
|
|
2503
|
+
{
|
|
2504
|
+
onClick: () => setExpanded(!expanded),
|
|
2505
|
+
className: "volr:w-full volr:py-2 volr:text-xs volr:font-medium volr:text-slate-700 hover:volr:text-slate-900 volr:bg-slate-50 hover:volr:bg-slate-100 volr:rounded-lg volr:transition-colors",
|
|
2506
|
+
children: expanded ? t("deposit.seeLess") : t("deposit.seeMore")
|
|
2507
|
+
}
|
|
2508
|
+
)
|
|
2509
|
+
] })
|
|
2510
|
+
] }) }),
|
|
2511
|
+
/* @__PURE__ */ jsxRuntime.jsx("style", { children: `
|
|
2512
|
+
@keyframes volrSlideUp {
|
|
2513
|
+
from {
|
|
2514
|
+
transform: translateY(100%);
|
|
2515
|
+
opacity: 0;
|
|
2516
|
+
}
|
|
2517
|
+
to {
|
|
2518
|
+
transform: translateY(0);
|
|
2519
|
+
opacity: 1;
|
|
2520
|
+
}
|
|
2521
|
+
}
|
|
2522
|
+
@keyframes volrFadeIn {
|
|
2523
|
+
from {
|
|
2524
|
+
opacity: 0;
|
|
2525
|
+
}
|
|
2526
|
+
to {
|
|
2527
|
+
opacity: 1;
|
|
2528
|
+
}
|
|
2529
|
+
}
|
|
2530
|
+
` })
|
|
2531
|
+
]
|
|
2532
|
+
}
|
|
2533
|
+
);
|
|
2534
|
+
};
|
|
2535
|
+
function DepositQRView(props) {
|
|
2536
|
+
const { t } = useI18n();
|
|
2537
|
+
const { config } = react.useVolr();
|
|
2538
|
+
const { client } = react.useInternalAuth();
|
|
2539
|
+
const [chainName, setChainName] = React3.useState(null);
|
|
2540
|
+
const [showOtherTokenModal, setShowOtherTokenModal] = React3.useState(false);
|
|
2541
|
+
const [showToast, setShowToast] = React3.useState(false);
|
|
2542
|
+
const eip681 = React3.useMemo(() => {
|
|
2543
|
+
return `ethereum:${props.address}`;
|
|
2544
|
+
}, [props.address]);
|
|
2545
|
+
const status = react.useDepositListener({
|
|
2546
|
+
chainId: props.chainId,
|
|
2547
|
+
asset: props.asset === "native" ? { kind: "native" } : {
|
|
2548
|
+
kind: "erc20",
|
|
2549
|
+
token: {
|
|
2550
|
+
address: props.asset.address,
|
|
2551
|
+
decimals: props.asset.decimals
|
|
2552
|
+
}
|
|
2553
|
+
},
|
|
2554
|
+
address: props.address
|
|
2555
|
+
});
|
|
2556
|
+
React3.useEffect(() => {
|
|
2557
|
+
console.log("[DepositQRView] Status changed:", status);
|
|
2558
|
+
if (status.state === "detected") {
|
|
2559
|
+
setShowToast(true);
|
|
2560
|
+
}
|
|
2561
|
+
}, [status.state]);
|
|
2562
|
+
const getNetworkInfo = React3.useCallback(
|
|
2563
|
+
react.createGetNetworkInfo({ client, rpcOverrides: config.rpcOverrides }),
|
|
2564
|
+
[client, config.rpcOverrides]
|
|
2565
|
+
);
|
|
2566
|
+
React3.useEffect(() => {
|
|
2567
|
+
let cancelled = false;
|
|
2568
|
+
const loadChainName = async () => {
|
|
2569
|
+
try {
|
|
2570
|
+
const info = await getNetworkInfo(props.chainId, false);
|
|
2571
|
+
if (!cancelled) {
|
|
2572
|
+
setChainName(info.name);
|
|
2573
|
+
}
|
|
2574
|
+
} catch (error) {
|
|
2575
|
+
if (!cancelled) {
|
|
2576
|
+
setChainName(`Chain ${props.chainId}`);
|
|
2577
|
+
}
|
|
2578
|
+
}
|
|
2579
|
+
};
|
|
2580
|
+
loadChainName();
|
|
2581
|
+
return () => {
|
|
2582
|
+
cancelled = true;
|
|
2583
|
+
};
|
|
2584
|
+
}, [getNetworkInfo, props.chainId]);
|
|
2585
|
+
const tokenSymbol = props.asset === "native" ? "ETH" : props.asset.symbol;
|
|
2586
|
+
const displayChainName = chainName || `Chain ${props.chainId}`;
|
|
2587
|
+
const decimals = props.asset === "native" ? 18 : props.asset.decimals;
|
|
2588
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "volr:relative volr:px-5 volr:pb-5", children: [
|
|
2589
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "volr:mb-8", children: [
|
|
2590
|
+
/* @__PURE__ */ jsxRuntime.jsx(ModalTitle2, { className: "volr:mb-3", children: t("deposit.qrTitle") }),
|
|
2591
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "volr:inline-flex volr:items-center volr:gap-2 volr:px-3 volr:py-1.5 volr:rounded-lg volr:bg-slate-100", children: [
|
|
2592
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "volr:text-sm volr:font-medium volr:text-slate-700", children: tokenSymbol }),
|
|
2593
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "volr:text-slate-400", children: "\u2022" }),
|
|
2594
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "volr:text-sm volr:text-slate-500", children: displayChainName })
|
|
2595
|
+
] })
|
|
2596
|
+
] }),
|
|
2597
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "volr:flex volr:justify-center volr:mb-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "volr:relative", children: [
|
|
2598
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "volr:relative volr:rounded-2xl volr:bg-white volr:p-5 volr:shadow-sm volr:border volr:border-slate-200/50 volr:z-10", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2599
|
+
"img",
|
|
2600
|
+
{
|
|
2601
|
+
alt: "Deposit QR",
|
|
2602
|
+
width: 240,
|
|
2603
|
+
height: 240,
|
|
2604
|
+
src: `https://api.qrserver.com/v1/create-qr-code/?size=240x240&data=${encodeURIComponent(
|
|
2605
|
+
eip681
|
|
2606
|
+
)}`,
|
|
2607
|
+
className: "volr:rounded-lg volr:relative volr:z-10"
|
|
2608
|
+
}
|
|
2609
|
+
) }),
|
|
2610
|
+
/* @__PURE__ */ jsxRuntime.jsx(DepositQRStatusOverlay, { status: status.state })
|
|
2611
|
+
] }) }),
|
|
2612
|
+
status.state === "listening" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "volr:flex volr:items-center volr:justify-center volr:gap-2 volr:mb-4", children: [
|
|
2613
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "volr:w-1.5 volr:h-1.5 volr:bg-blue-500 volr:rounded-full volr:animate-pulse" }),
|
|
2614
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "volr:text-xs volr:text-slate-600", children: t("deposit.listening") })
|
|
2615
|
+
] }),
|
|
2616
|
+
status.state === "idle" && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "volr:text-xs volr:text-slate-500 volr:text-center volr:mb-4", children: "Initializing..." }),
|
|
2617
|
+
status.state === "error" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "volr:text-xs volr:text-red-500 volr:text-center volr:mb-4", children: [
|
|
2618
|
+
"Error: ",
|
|
2619
|
+
status.message
|
|
2620
|
+
] }),
|
|
2621
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "volr:space-y-3", children: [
|
|
2622
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "volr:relative volr:bg-slate-50/50 volr:border volr:border-slate-200/50 volr:rounded-lg volr:p-3 volr:group hover:volr:bg-slate-50 hover:volr:border-slate-200 volr:transition-all", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "volr:flex volr:items-center volr:justify-between volr:gap-3", children: [
|
|
2623
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "volr:font-mono volr:text-xs volr:font-medium volr:text-slate-700 volr:flex-1 volr:text-center", children: `${props.address.slice(0, 10)}...${props.address.slice(-8)}` }),
|
|
2624
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2625
|
+
CopyButton,
|
|
2626
|
+
{
|
|
2627
|
+
text: props.address,
|
|
2628
|
+
className: "volr:flex-shrink-0 volr:absolute volr:right-2"
|
|
2629
|
+
}
|
|
2630
|
+
)
|
|
2631
|
+
] }) }) }),
|
|
2632
|
+
status.state === "error" && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "volr:text-xs volr:text-red-500 volr:text-center volr:mb-4", children: status.message })
|
|
2633
|
+
] }),
|
|
2634
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "volr:text-center volr:pt-4 volr:border-t volr:border-slate-100", children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "volr:text-xs volr:text-slate-500", children: [
|
|
2635
|
+
t("deposit.noToken"),
|
|
2636
|
+
" ",
|
|
2637
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2638
|
+
TextLinkButton,
|
|
2639
|
+
{
|
|
2640
|
+
onClick: () => setShowOtherTokenModal(true),
|
|
2641
|
+
showArrow: true,
|
|
2642
|
+
children: t("deposit.getOtherToken")
|
|
2643
|
+
}
|
|
2644
|
+
)
|
|
2645
|
+
] }) }),
|
|
2646
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2647
|
+
OtherTokenModal,
|
|
2648
|
+
{
|
|
2649
|
+
open: showOtherTokenModal,
|
|
2650
|
+
onOpenChange: setShowOtherTokenModal
|
|
2651
|
+
}
|
|
2652
|
+
),
|
|
2653
|
+
showToast && status.state === "detected" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
2654
|
+
DepositCompletedToast,
|
|
2655
|
+
{
|
|
2656
|
+
onClose: () => setShowToast(false),
|
|
2657
|
+
previousBalance: status.previousBalance,
|
|
2658
|
+
newBalance: status.newBalance,
|
|
2659
|
+
delta: status.delta,
|
|
2660
|
+
decimals,
|
|
2661
|
+
symbol: tokenSymbol
|
|
2662
|
+
}
|
|
2663
|
+
)
|
|
2664
|
+
] });
|
|
2665
|
+
}
|
|
2666
|
+
var DepositModal = ({
|
|
2667
|
+
open,
|
|
2668
|
+
onOpenChange
|
|
2669
|
+
}) => {
|
|
2670
|
+
const { config, user } = react.useVolr();
|
|
2671
|
+
const supportedAssets = config.deposit?.supportedAssets ?? [];
|
|
2672
|
+
const hasAssets = supportedAssets.length > 0;
|
|
2673
|
+
const [selectedIdx, setSelectedIdx] = React3.useState(
|
|
2674
|
+
supportedAssets.length === 1 ? 0 : -1
|
|
2675
|
+
);
|
|
2676
|
+
const selected = React3.useMemo(
|
|
2677
|
+
() => supportedAssets[selectedIdx],
|
|
2678
|
+
[supportedAssets, selectedIdx]
|
|
2679
|
+
);
|
|
2680
|
+
const showSelector = hasAssets && supportedAssets.length > 1 && selectedIdx === -1;
|
|
2681
|
+
const showQR = hasAssets && user?.evmAddress && selectedIdx >= 0;
|
|
2682
|
+
const body = React3.useMemo(() => {
|
|
2683
|
+
if (!hasAssets) {
|
|
2684
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "volr:text-center volr:py-8", children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "volr:text-sm volr:text-slate-600", children: "No deposit assets configured. Please contact the app developer." }) });
|
|
2685
|
+
}
|
|
2686
|
+
if (!user?.evmAddress) {
|
|
2687
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "volr:text-center volr:py-8", children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "volr:text-sm volr:text-slate-600", children: "Wallet address is not ready. Please finish wallet setup first." }) });
|
|
2688
|
+
}
|
|
2689
|
+
if (supportedAssets.length === 1) {
|
|
2690
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2691
|
+
DepositQRView,
|
|
2692
|
+
{
|
|
2693
|
+
chainId: supportedAssets[0].chainId,
|
|
2694
|
+
asset: supportedAssets[0].token,
|
|
2695
|
+
address: user.evmAddress,
|
|
2696
|
+
onBack: void 0
|
|
2697
|
+
}
|
|
2698
|
+
);
|
|
2699
|
+
}
|
|
2700
|
+
if (showSelector) {
|
|
2701
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2702
|
+
AssetSelectView,
|
|
2703
|
+
{
|
|
2704
|
+
assets: supportedAssets,
|
|
2705
|
+
onSelect: (idx) => setSelectedIdx(idx)
|
|
2706
|
+
}
|
|
2707
|
+
);
|
|
2708
|
+
}
|
|
2709
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2710
|
+
DepositQRView,
|
|
2711
|
+
{
|
|
2712
|
+
chainId: selected.chainId,
|
|
2713
|
+
asset: selected.token,
|
|
2714
|
+
address: user.evmAddress,
|
|
2715
|
+
onBack: () => setSelectedIdx(-1)
|
|
2716
|
+
}
|
|
2717
|
+
);
|
|
2718
|
+
}, [
|
|
2719
|
+
hasAssets,
|
|
2720
|
+
selected,
|
|
2721
|
+
selectedIdx,
|
|
2722
|
+
showSelector,
|
|
2723
|
+
supportedAssets,
|
|
2724
|
+
user?.evmAddress
|
|
2725
|
+
]);
|
|
2726
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Modal, { open, onOpenChange, children: [
|
|
2727
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2728
|
+
ModalHeader,
|
|
2729
|
+
{
|
|
2730
|
+
back: showQR && supportedAssets.length > 1,
|
|
2731
|
+
onBack: showQR ? () => setSelectedIdx(-1) : void 0,
|
|
2732
|
+
onClose: () => onOpenChange(false)
|
|
2733
|
+
}
|
|
2734
|
+
),
|
|
2735
|
+
body
|
|
2736
|
+
] });
|
|
2737
|
+
};
|
|
2738
|
+
|
|
2739
|
+
// src/generated/volr-sdk-css.ts
|
|
2740
|
+
var VOLR_SDK_CSS = '/*! tailwindcss v4.1.17 | MIT License | https://tailwindcss.com */\n@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-space-y-reverse:0;--tw-border-style:solid;--tw-gradient-position:initial;--tw-gradient-from:#0000;--tw-gradient-via:#0000;--tw-gradient-to:#0000;--tw-gradient-stops:initial;--tw-gradient-via-stops:initial;--tw-gradient-from-position:0%;--tw-gradient-via-position:50%;--tw-gradient-to-position:100%;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-duration:initial;--tw-ease:initial}}}@layer theme{:root,:host{--volr-font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--volr-color-red-50:oklch(97.1% .013 17.38);--volr-color-red-200:oklch(88.5% .062 18.334);--volr-color-red-500:oklch(63.7% .237 25.331);--volr-color-red-600:oklch(57.7% .245 27.325);--volr-color-red-700:oklch(50.5% .213 27.518);--volr-color-green-600:oklch(62.7% .194 149.214);--volr-color-emerald-300:oklch(84.5% .143 164.978);--volr-color-emerald-400:oklch(76.5% .177 163.223);--volr-color-emerald-500:oklch(69.6% .17 162.48);--volr-color-teal-400:oklch(77.7% .152 181.912);--volr-color-teal-500:oklch(70.4% .14 182.503);--volr-color-cyan-400:oklch(78.9% .154 211.53);--volr-color-blue-500:oklch(62.3% .214 259.815);--volr-color-purple-600:oklch(55.8% .288 302.321);--volr-color-rose-50:oklch(96.9% .015 12.422);--volr-color-rose-200:oklch(89.2% .058 10.001);--volr-color-rose-700:oklch(51.4% .222 16.935);--volr-color-rose-800:oklch(45.5% .188 13.697);--volr-color-slate-50:oklch(98.4% .003 247.858);--volr-color-slate-100:oklch(96.8% .007 247.896);--volr-color-slate-200:oklch(92.9% .013 255.508);--volr-color-slate-300:oklch(86.9% .022 252.894);--volr-color-slate-400:oklch(70.4% .04 256.788);--volr-color-slate-500:oklch(55.4% .046 257.417);--volr-color-slate-600:oklch(44.6% .043 257.281);--volr-color-slate-700:oklch(37.2% .044 257.287);--volr-color-slate-900:oklch(20.8% .042 265.755);--volr-color-gray-100:oklch(96.7% .003 264.542);--volr-color-gray-400:oklch(70.7% .022 261.325);--volr-color-gray-500:oklch(55.1% .027 264.364);--volr-color-gray-900:oklch(21% .034 264.665);--volr-color-black:#000;--volr-color-white:#fff;--volr-spacing:.25rem;--volr-container-md:28rem;--volr-container-4xl:56rem;--volr-text-xs:.75rem;--volr-text-xs--line-height:calc(1/.75);--volr-text-sm:.875rem;--volr-text-sm--line-height:calc(1.25/.875);--volr-text-base:1rem;--volr-text-base--line-height:calc(1.5/1);--volr-text-lg:1.125rem;--volr-text-lg--line-height:calc(1.75/1.125);--volr-text-xl:1.25rem;--volr-text-xl--line-height:calc(1.75/1.25);--volr-text-2xl:1.5rem;--volr-text-2xl--line-height:calc(2/1.5);--volr-text-3xl:1.875rem;--volr-text-3xl--line-height:calc(2.25/1.875);--volr-text-8xl:6rem;--volr-text-8xl--line-height:1;--volr-font-weight-medium:500;--volr-font-weight-semibold:600;--volr-font-weight-bold:700;--volr-tracking-tight:-.025em;--volr-leading-relaxed:1.625;--volr-radius-lg:.5rem;--volr-radius-xl:.75rem;--volr-radius-2xl:1rem;--volr-radius-3xl:1.5rem;--volr-ease-out:cubic-bezier(0,0,.2,1);--volr-animate-pulse:pulse 2s cubic-bezier(.4,0,.6,1)infinite;--volr-blur-2xl:40px;--volr-default-transition-duration:.15s;--volr-default-transition-timing-function:cubic-bezier(.4,0,.2,1)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}body{line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1;color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab,currentColor 50%,transparent)}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}[data-volr-root]{color:inherit;font-family:inherit;font-size:1rem;line-height:1.5}[data-volr-root] *{font-family:inherit}}@layer components{.volr-dialog-overlay{inset:calc(var(--volr-spacing)*0);z-index:40;background-color:var(--volr-color-black);position:fixed}@supports (color:color-mix(in lab, red, red)){.volr-dialog-overlay{background-color:color-mix(in oklab,var(--volr-color-black)45%,transparent)}}.volr-dialog-content{z-index:50;border-radius:var(--volr-radius-2xl);border-style:var(--tw-border-style);border-width:1px;border-color:var(--volr-color-slate-300);background-color:var(--volr-color-white);padding:calc(var(--volr-spacing)*7);--tw-shadow:0 20px 25px -5px var(--tw-shadow-color,#0000001a),0 8px 10px -6px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);width:calc(100% - 2rem);max-width:28rem;max-height:85vh;position:fixed;top:50%;left:50%;overflow-y:auto;transform:translate(-50%,-50%)}@media (max-width:640px){.volr-dialog-content{top:auto;right:calc(var(--volr-spacing)*0);bottom:calc(var(--volr-spacing)*0);left:calc(var(--volr-spacing)*0);border-radius:1.25rem 1.25rem 0 0;width:100%;max-width:100%;margin:0 auto;transform:translateY(0)}}.volr-dialog-close{top:calc(var(--volr-spacing)*4);right:calc(var(--volr-spacing)*4);height:calc(var(--volr-spacing)*8);width:calc(var(--volr-spacing)*8);color:var(--volr-color-slate-400);cursor:pointer;background-color:#0000;border:none;border-radius:3.40282e38px;justify-content:center;align-items:center;display:inline-flex;position:absolute}.volr-dialog-close:hover{color:#475569;background-color:#f1f5f9}.volr-dialog-close:focus-visible{outline:none;box-shadow:0 0 0 2px #94a3b8b3}.volr-dialog-close-icon{height:calc(var(--volr-spacing)*4);width:calc(var(--volr-spacing)*4)}}@layer utilities{.volr\\:pointer-events-none{pointer-events:none}.volr\\:absolute{position:absolute}.volr\\:fixed{position:fixed}.volr\\:relative{position:relative}.volr\\:inset-0{inset:calc(var(--volr-spacing)*0)}.volr\\:-top-3{top:calc(var(--volr-spacing)*-3)}.volr\\:top-1\\/2{top:50%}.volr\\:-right-3{right:calc(var(--volr-spacing)*-3)}.volr\\:right-0{right:calc(var(--volr-spacing)*0)}.volr\\:right-2{right:calc(var(--volr-spacing)*2)}.volr\\:bottom-0{bottom:calc(var(--volr-spacing)*0)}.volr\\:left-0{left:calc(var(--volr-spacing)*0)}.volr\\:left-3{left:calc(var(--volr-spacing)*3)}.volr\\:-z-10{z-index:calc(10*-1)}.volr\\:z-10{z-index:10}.volr\\:z-20{z-index:20}.volr\\:z-40{z-index:40}.volr\\:z-50{z-index:50}.volr\\:mx-auto{margin-inline:auto}.volr\\:my-6{margin-block:calc(var(--volr-spacing)*6)}.volr\\:my-8{margin-block:calc(var(--volr-spacing)*8)}.volr\\:mt-0\\.5{margin-top:calc(var(--volr-spacing)*.5)}.volr\\:mt-1{margin-top:calc(var(--volr-spacing)*1)}.volr\\:mt-2{margin-top:calc(var(--volr-spacing)*2)}.volr\\:mt-3{margin-top:calc(var(--volr-spacing)*3)}.volr\\:mt-6{margin-top:calc(var(--volr-spacing)*6)}.volr\\:mt-8{margin-top:calc(var(--volr-spacing)*8)}.volr\\:mb-1{margin-bottom:calc(var(--volr-spacing)*1)}.volr\\:mb-2{margin-bottom:calc(var(--volr-spacing)*2)}.volr\\:mb-3{margin-bottom:calc(var(--volr-spacing)*3)}.volr\\:mb-4{margin-bottom:calc(var(--volr-spacing)*4)}.volr\\:mb-5{margin-bottom:calc(var(--volr-spacing)*5)}.volr\\:mb-6{margin-bottom:calc(var(--volr-spacing)*6)}.volr\\:mb-7{margin-bottom:calc(var(--volr-spacing)*7)}.volr\\:mb-8{margin-bottom:calc(var(--volr-spacing)*8)}.volr\\:-ml-2{margin-left:calc(var(--volr-spacing)*-2)}.volr\\:flex{display:flex}.volr\\:grid{display:grid}.volr\\:inline-block{display:inline-block}.volr\\:inline-flex{display:inline-flex}.volr\\:h-1\\.5{height:calc(var(--volr-spacing)*1.5)}.volr\\:h-2{height:calc(var(--volr-spacing)*2)}.volr\\:h-8{height:calc(var(--volr-spacing)*8)}.volr\\:h-10{height:calc(var(--volr-spacing)*10)}.volr\\:h-14{height:calc(var(--volr-spacing)*14)}.volr\\:h-24{height:calc(var(--volr-spacing)*24)}.volr\\:h-40{height:calc(var(--volr-spacing)*40)}.volr\\:h-44{height:calc(var(--volr-spacing)*44)}.volr\\:h-48{height:calc(var(--volr-spacing)*48)}.volr\\:h-full{height:100%}.volr\\:h-px{height:1px}.volr\\:max-h-24{max-height:calc(var(--volr-spacing)*24)}.volr\\:max-h-96{max-height:calc(var(--volr-spacing)*96)}.volr\\:max-h-\\[85vh\\]{max-height:85vh}.volr\\:max-h-\\[90vh\\]{max-height:90vh}.volr\\:min-h-\\[120px\\]{min-height:120px}.volr\\:w-1\\.5{width:calc(var(--volr-spacing)*1.5)}.volr\\:w-2{width:calc(var(--volr-spacing)*2)}.volr\\:w-8{width:calc(var(--volr-spacing)*8)}.volr\\:w-10{width:calc(var(--volr-spacing)*10)}.volr\\:w-12{width:calc(var(--volr-spacing)*12)}.volr\\:w-24{width:calc(var(--volr-spacing)*24)}.volr\\:w-40{width:calc(var(--volr-spacing)*40)}.volr\\:w-44{width:calc(var(--volr-spacing)*44)}.volr\\:w-48{width:calc(var(--volr-spacing)*48)}.volr\\:w-full{width:100%}.volr\\:max-w-4xl{max-width:var(--volr-container-4xl)}.volr\\:max-w-full{max-width:100%}.volr\\:max-w-md{max-width:var(--volr-container-md)}.volr\\:max-w-none{max-width:none}.volr\\:min-w-0{min-width:calc(var(--volr-spacing)*0)}.volr\\:flex-1{flex:1}.volr\\:flex-shrink-0{flex-shrink:0}.volr\\:-translate-y-1\\/2{--tw-translate-y:calc(calc(1/2*100%)*-1);translate:var(--tw-translate-x)var(--tw-translate-y)}.volr\\:animate-\\[volrFadeIn_0\\.2s_ease-out\\]{animation:.2s ease-out volrFadeIn}.volr\\:animate-pulse{animation:var(--volr-animate-pulse)}.volr\\:cursor-not-allowed{cursor:not-allowed}.volr\\:cursor-pointer{cursor:pointer}.volr\\:grid-cols-\\[minmax\\(0\\,1\\.1fr\\)_minmax\\(0\\,1fr\\)\\]{grid-template-columns:minmax(0,1.1fr) minmax(0,1fr)}.volr\\:flex-col{flex-direction:column}.volr\\:items-baseline{align-items:baseline}.volr\\:items-center{align-items:center}.volr\\:items-end{align-items:flex-end}.volr\\:items-start{align-items:flex-start}.volr\\:justify-between{justify-content:space-between}.volr\\:justify-center{justify-content:center}.volr\\:gap-1{gap:calc(var(--volr-spacing)*1)}.volr\\:gap-2{gap:calc(var(--volr-spacing)*2)}.volr\\:gap-3{gap:calc(var(--volr-spacing)*3)}.volr\\:gap-4{gap:calc(var(--volr-spacing)*4)}:where(.volr\\:space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--volr-spacing)*2)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--volr-spacing)*2)*calc(1 - var(--tw-space-y-reverse)))}:where(.volr\\:space-y-3>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--volr-spacing)*3)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--volr-spacing)*3)*calc(1 - var(--tw-space-y-reverse)))}.volr\\:truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.volr\\:overflow-hidden{overflow:hidden}.volr\\:overflow-visible{overflow:visible}.volr\\:overflow-y-auto{overflow-y:auto}.volr\\:rounded-2xl{border-radius:var(--volr-radius-2xl)}.volr\\:rounded-full{border-radius:3.40282e38px}.volr\\:rounded-lg{border-radius:var(--volr-radius-lg)}.volr\\:rounded-xl{border-radius:var(--volr-radius-xl)}.volr\\:rounded-t-3xl{border-top-left-radius:var(--volr-radius-3xl);border-top-right-radius:var(--volr-radius-3xl)}.volr\\:border{border-style:var(--tw-border-style);border-width:1px}.volr\\:border-2{border-style:var(--tw-border-style);border-width:2px}.volr\\:border-4{border-style:var(--tw-border-style);border-width:4px}.volr\\:border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.volr\\:border-none{--tw-border-style:none;border-style:none}.volr\\:border-red-200{border-color:var(--volr-color-red-200)}.volr\\:border-rose-200{border-color:var(--volr-color-rose-200)}.volr\\:border-slate-100{border-color:var(--volr-color-slate-100)}.volr\\:border-slate-200,.volr\\:border-slate-200\\/50{border-color:var(--volr-color-slate-200)}@supports (color:color-mix(in lab, red, red)){.volr\\:border-slate-200\\/50{border-color:color-mix(in oklab,var(--volr-color-slate-200)50%,transparent)}}.volr\\:border-slate-300{border-color:var(--volr-color-slate-300)}.volr\\:border-white{border-color:var(--volr-color-white)}.volr\\:bg-black\\/45{background-color:var(--volr-color-black)}@supports (color:color-mix(in lab, red, red)){.volr\\:bg-black\\/45{background-color:color-mix(in oklab,var(--volr-color-black)45%,transparent)}}.volr\\:bg-blue-500{background-color:var(--volr-color-blue-500)}.volr\\:bg-cyan-400{background-color:var(--volr-color-cyan-400)}.volr\\:bg-emerald-300{background-color:var(--volr-color-emerald-300)}.volr\\:bg-emerald-400{background-color:var(--volr-color-emerald-400)}.volr\\:bg-gray-100{background-color:var(--volr-color-gray-100)}.volr\\:bg-gray-400{background-color:var(--volr-color-gray-400)}.volr\\:bg-red-50{background-color:var(--volr-color-red-50)}.volr\\:bg-rose-50{background-color:var(--volr-color-rose-50)}.volr\\:bg-slate-50,.volr\\:bg-slate-50\\/50{background-color:var(--volr-color-slate-50)}@supports (color:color-mix(in lab, red, red)){.volr\\:bg-slate-50\\/50{background-color:color-mix(in oklab,var(--volr-color-slate-50)50%,transparent)}}.volr\\:bg-slate-100{background-color:var(--volr-color-slate-100)}.volr\\:bg-slate-200{background-color:var(--volr-color-slate-200)}.volr\\:bg-teal-400{background-color:var(--volr-color-teal-400)}.volr\\:bg-transparent{background-color:#0000}.volr\\:bg-white{background-color:var(--volr-color-white)}.volr\\:bg-gradient-to-br{--tw-gradient-position:to bottom right in oklab;background-image:linear-gradient(var(--tw-gradient-stops))}.volr\\:from-blue-500{--tw-gradient-from:var(--volr-color-blue-500);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position),var(--tw-gradient-from)var(--tw-gradient-from-position),var(--tw-gradient-to)var(--tw-gradient-to-position))}.volr\\:from-emerald-400{--tw-gradient-from:var(--volr-color-emerald-400);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position),var(--tw-gradient-from)var(--tw-gradient-from-position),var(--tw-gradient-to)var(--tw-gradient-to-position))}.volr\\:from-emerald-500{--tw-gradient-from:var(--volr-color-emerald-500);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position),var(--tw-gradient-from)var(--tw-gradient-from-position),var(--tw-gradient-to)var(--tw-gradient-to-position))}.volr\\:to-purple-600{--tw-gradient-to:var(--volr-color-purple-600);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position),var(--tw-gradient-from)var(--tw-gradient-from-position),var(--tw-gradient-to)var(--tw-gradient-to-position))}.volr\\:to-teal-500{--tw-gradient-to:var(--volr-color-teal-500);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position),var(--tw-gradient-from)var(--tw-gradient-from-position),var(--tw-gradient-to)var(--tw-gradient-to-position))}.volr\\:p-1{padding:calc(var(--volr-spacing)*1)}.volr\\:p-2{padding:calc(var(--volr-spacing)*2)}.volr\\:p-3{padding:calc(var(--volr-spacing)*3)}.volr\\:p-4{padding:calc(var(--volr-spacing)*4)}.volr\\:p-5{padding:calc(var(--volr-spacing)*5)}.volr\\:p-8{padding:calc(var(--volr-spacing)*8)}.volr\\:px-2{padding-inline:calc(var(--volr-spacing)*2)}.volr\\:px-3{padding-inline:calc(var(--volr-spacing)*3)}.volr\\:px-4{padding-inline:calc(var(--volr-spacing)*4)}.volr\\:px-5{padding-inline:calc(var(--volr-spacing)*5)}.volr\\:px-6{padding-inline:calc(var(--volr-spacing)*6)}.volr\\:py-0\\.5{padding-block:calc(var(--volr-spacing)*.5)}.volr\\:py-1\\.5{padding-block:calc(var(--volr-spacing)*1.5)}.volr\\:py-2{padding-block:calc(var(--volr-spacing)*2)}.volr\\:py-3{padding-block:calc(var(--volr-spacing)*3)}.volr\\:py-4{padding-block:calc(var(--volr-spacing)*4)}.volr\\:py-6{padding-block:calc(var(--volr-spacing)*6)}.volr\\:py-8{padding-block:calc(var(--volr-spacing)*8)}.volr\\:py-12{padding-block:calc(var(--volr-spacing)*12)}.volr\\:pt-4{padding-top:calc(var(--volr-spacing)*4)}.volr\\:pr-3{padding-right:calc(var(--volr-spacing)*3)}.volr\\:pb-5{padding-bottom:calc(var(--volr-spacing)*5)}.volr\\:pb-6{padding-bottom:calc(var(--volr-spacing)*6)}.volr\\:pl-11{padding-left:calc(var(--volr-spacing)*11)}.volr\\:text-center{text-align:center}.volr\\:text-left{text-align:left}.volr\\:font-mono{font-family:var(--volr-font-mono)}.volr\\:text-2xl{font-size:var(--volr-text-2xl);line-height:var(--tw-leading,var(--volr-text-2xl--line-height))}.volr\\:text-3xl{font-size:var(--volr-text-3xl);line-height:var(--tw-leading,var(--volr-text-3xl--line-height))}.volr\\:text-8xl{font-size:var(--volr-text-8xl);line-height:var(--tw-leading,var(--volr-text-8xl--line-height))}.volr\\:text-base{font-size:var(--volr-text-base);line-height:var(--tw-leading,var(--volr-text-base--line-height))}.volr\\:text-lg{font-size:var(--volr-text-lg);line-height:var(--tw-leading,var(--volr-text-lg--line-height))}.volr\\:text-sm{font-size:var(--volr-text-sm);line-height:var(--tw-leading,var(--volr-text-sm--line-height))}.volr\\:text-xl{font-size:var(--volr-text-xl);line-height:var(--tw-leading,var(--volr-text-xl--line-height))}.volr\\:text-xs{font-size:var(--volr-text-xs);line-height:var(--tw-leading,var(--volr-text-xs--line-height))}.volr\\:leading-none{--tw-leading:1;line-height:1}.volr\\:leading-relaxed{--tw-leading:var(--volr-leading-relaxed);line-height:var(--volr-leading-relaxed)}.volr\\:font-bold{--tw-font-weight:var(--volr-font-weight-bold);font-weight:var(--volr-font-weight-bold)}.volr\\:font-medium{--tw-font-weight:var(--volr-font-weight-medium);font-weight:var(--volr-font-weight-medium)}.volr\\:font-semibold{--tw-font-weight:var(--volr-font-weight-semibold);font-weight:var(--volr-font-weight-semibold)}.volr\\:tracking-tight{--tw-tracking:var(--volr-tracking-tight);letter-spacing:var(--volr-tracking-tight)}.volr\\:break-all{word-break:break-all}.volr\\:text-gray-500{color:var(--volr-color-gray-500)}.volr\\:text-gray-900{color:var(--volr-color-gray-900)}.volr\\:text-green-600{color:var(--volr-color-green-600)}.volr\\:text-red-500{color:var(--volr-color-red-500)}.volr\\:text-red-600{color:var(--volr-color-red-600)}.volr\\:text-red-700{color:var(--volr-color-red-700)}.volr\\:text-rose-700{color:var(--volr-color-rose-700)}.volr\\:text-rose-800{color:var(--volr-color-rose-800)}.volr\\:text-slate-400{color:var(--volr-color-slate-400)}.volr\\:text-slate-500{color:var(--volr-color-slate-500)}.volr\\:text-slate-600{color:var(--volr-color-slate-600)}.volr\\:text-slate-700{color:var(--volr-color-slate-700)}.volr\\:text-slate-900{color:var(--volr-color-slate-900)}.volr\\:text-white{color:var(--volr-color-white)}.volr\\:capitalize{text-transform:capitalize}.volr\\:underline{text-decoration-line:underline}.volr\\:opacity-0{opacity:0}.volr\\:opacity-30{opacity:.3}.volr\\:shadow-2xl{--tw-shadow:0 25px 50px -12px var(--tw-shadow-color,#00000040);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.volr\\:shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a),0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.volr\\:shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a),0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.volr\\:shadow-xl{--tw-shadow:0 20px 25px -5px var(--tw-shadow-color,#0000001a),0 8px 10px -6px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.volr\\:shadow-emerald-500\\/50{--tw-shadow-color:var(--volr-color-emerald-500)}@supports (color:color-mix(in lab, red, red)){.volr\\:shadow-emerald-500\\/50{--tw-shadow-color:color-mix(in oklab,color-mix(in oklab,var(--volr-color-emerald-500)50%,transparent)var(--tw-shadow-alpha),transparent)}}.volr\\:blur-2xl{--tw-blur:blur(var(--volr-blur-2xl));filter:var(--tw-blur,)var(--tw-brightness,)var(--tw-contrast,)var(--tw-grayscale,)var(--tw-hue-rotate,)var(--tw-invert,)var(--tw-saturate,)var(--tw-sepia,)var(--tw-drop-shadow,)}.volr\\:transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--volr-default-transition-timing-function));transition-duration:var(--tw-duration,var(--volr-default-transition-duration))}.volr\\:transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--volr-default-transition-timing-function));transition-duration:var(--tw-duration,var(--volr-default-transition-duration))}.volr\\:transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--volr-default-transition-timing-function));transition-duration:var(--tw-duration,var(--volr-default-transition-duration))}.volr\\:duration-200{--tw-duration:.2s;transition-duration:.2s}.volr\\:duration-300{--tw-duration:.3s;transition-duration:.3s}.volr\\:duration-500{--tw-duration:.5s;transition-duration:.5s}.volr\\:ease-out{--tw-ease:var(--volr-ease-out);transition-timing-function:var(--volr-ease-out)}.volr\\:outline-none{--tw-outline-style:none;outline-style:none}@media (hover:hover){.volr\\:hover\\:bg-slate-50:hover{background-color:var(--volr-color-slate-50)}}.volr\\:focus-visible\\:ring-2:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(2px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.volr\\:focus-visible\\:ring-slate-300:focus-visible{--tw-ring-color:var(--volr-color-slate-300)}.volr\\:focus-visible\\:outline-none:focus-visible{--tw-outline-style:none;outline-style:none}.volr-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-gradient-position{syntax:"*";inherits:false}@property --tw-gradient-from{syntax:"<color>";inherits:false;initial-value:#0000}@property --tw-gradient-via{syntax:"<color>";inherits:false;initial-value:#0000}@property --tw-gradient-to{syntax:"<color>";inherits:false;initial-value:#0000}@property --tw-gradient-stops{syntax:"*";inherits:false}@property --tw-gradient-via-stops{syntax:"*";inherits:false}@property --tw-gradient-from-position{syntax:"<length-percentage>";inherits:false;initial-value:0%}@property --tw-gradient-via-position{syntax:"<length-percentage>";inherits:false;initial-value:50%}@property --tw-gradient-to-position{syntax:"<length-percentage>";inherits:false;initial-value:100%}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}@keyframes pulse{50%{opacity:.5}}';
|
|
2741
|
+
|
|
2742
|
+
// src/styles/inject-volr-styles.ts
|
|
2743
|
+
var injected = false;
|
|
2744
|
+
function ensureVolrStylesInjected() {
|
|
2745
|
+
if (typeof document === "undefined") return;
|
|
2746
|
+
if (injected) return;
|
|
2747
|
+
const id = "volr-sdk-styles";
|
|
2748
|
+
if (document.getElementById(id)) {
|
|
2749
|
+
injected = true;
|
|
2750
|
+
return;
|
|
2751
|
+
}
|
|
2752
|
+
const style = document.createElement("style");
|
|
2753
|
+
style.id = id;
|
|
2754
|
+
style.textContent = VOLR_SDK_CSS;
|
|
2755
|
+
document.head.appendChild(style);
|
|
2756
|
+
injected = true;
|
|
2757
|
+
}
|
|
2758
|
+
var VolrUIContext = React3__default.default.createContext(null);
|
|
2759
|
+
var useVolrUI = () => {
|
|
2760
|
+
const context = React3.useContext(VolrUIContext);
|
|
2761
|
+
if (!context) {
|
|
2762
|
+
throw new Error("useVolrUI must be used within VolrUIProvider");
|
|
2763
|
+
}
|
|
2764
|
+
return context;
|
|
2765
|
+
};
|
|
2766
|
+
function OnboardingFlow({
|
|
2767
|
+
keyStorageType,
|
|
2768
|
+
onComplete
|
|
2769
|
+
}) {
|
|
2770
|
+
const { logout } = react.useVolr();
|
|
2771
|
+
const handleEnrollComplete = () => {
|
|
2772
|
+
onComplete();
|
|
2773
|
+
};
|
|
2774
|
+
const handleEnrollError = (_err) => {
|
|
2775
|
+
};
|
|
2776
|
+
const handleLogout = async () => {
|
|
2777
|
+
try {
|
|
2778
|
+
await logout();
|
|
2779
|
+
onComplete();
|
|
2780
|
+
} catch (error) {
|
|
2781
|
+
}
|
|
2782
|
+
};
|
|
2783
|
+
if (keyStorageType === "passkey") {
|
|
2784
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2785
|
+
PasskeyEnrollView,
|
|
2786
|
+
{
|
|
2787
|
+
onComplete: handleEnrollComplete,
|
|
2788
|
+
onError: handleEnrollError,
|
|
2789
|
+
onLogout: handleLogout
|
|
2790
|
+
}
|
|
2791
|
+
);
|
|
2792
|
+
}
|
|
2793
|
+
if (keyStorageType === "mpc") {
|
|
2794
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2795
|
+
MpcConnectView,
|
|
2796
|
+
{
|
|
2797
|
+
onComplete: handleEnrollComplete,
|
|
2798
|
+
onError: handleEnrollError
|
|
2799
|
+
}
|
|
2800
|
+
);
|
|
2801
|
+
}
|
|
2802
|
+
return null;
|
|
2803
|
+
}
|
|
2804
|
+
var VolrUIProvider = ({
|
|
2805
|
+
config,
|
|
2806
|
+
children
|
|
2807
|
+
}) => {
|
|
2808
|
+
const {
|
|
2809
|
+
appName,
|
|
2810
|
+
accentColor = "#303030",
|
|
2811
|
+
enabledLoginMethods = ["email", "social", "siwe"],
|
|
2812
|
+
socialProviders = ["google", "twitter", "apple"],
|
|
2813
|
+
branding,
|
|
2814
|
+
keyStorageType
|
|
2815
|
+
} = config;
|
|
2816
|
+
const providerPolicy = config.providerPolicy ?? {
|
|
2817
|
+
enforceOnFirstLogin: true
|
|
2818
|
+
};
|
|
2819
|
+
const [showOnboarding, setShowOnboarding] = React3.useState(false);
|
|
2820
|
+
const [keyStorageTypeError, setKeyStorageTypeError] = React3.useState(
|
|
2821
|
+
null
|
|
2822
|
+
);
|
|
2823
|
+
React3.useEffect(() => {
|
|
2824
|
+
ensureVolrStylesInjected();
|
|
2825
|
+
}, []);
|
|
2826
|
+
React3.useEffect(() => {
|
|
2827
|
+
if (providerPolicy.enforceOnFirstLogin !== false && !keyStorageType) {
|
|
2828
|
+
const errorMessage = "keyStorageType must be specified in VolrUIProvider props. Please set keyStorageType prop in VolrUIProvider.";
|
|
2829
|
+
console.error(errorMessage);
|
|
2830
|
+
setKeyStorageTypeError(errorMessage);
|
|
2831
|
+
} else {
|
|
2832
|
+
setKeyStorageTypeError(null);
|
|
2833
|
+
}
|
|
2834
|
+
}, [keyStorageType, providerPolicy.enforceOnFirstLogin]);
|
|
2835
|
+
if (keyStorageTypeError) {
|
|
2836
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Modal, { open: true, onOpenChange: () => {
|
|
2837
|
+
}, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-w-md mx-auto", children: [
|
|
2838
|
+
/* @__PURE__ */ jsxRuntime.jsx(ModalTitle, { className: "text-red-600", children: "Configuration Error" }),
|
|
2839
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm text-gray-700 mb-6 leading-relaxed", children: keyStorageTypeError })
|
|
2840
|
+
] }) });
|
|
2841
|
+
}
|
|
2842
|
+
return /* @__PURE__ */ jsxRuntime.jsx(react.VolrProvider, { config, children: /* @__PURE__ */ jsxRuntime.jsx(I18nProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2843
|
+
VolrUIContext.Provider,
|
|
2844
|
+
{
|
|
2845
|
+
value: {
|
|
2846
|
+
accentColor,
|
|
2847
|
+
appName,
|
|
2848
|
+
enabledLoginMethods,
|
|
2849
|
+
socialProviders,
|
|
2850
|
+
branding,
|
|
2851
|
+
keyStorageType
|
|
2852
|
+
},
|
|
2853
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(VolrModalProvider, { children: [
|
|
2854
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2855
|
+
OnboardingChecker,
|
|
2856
|
+
{
|
|
2857
|
+
keyStorageType,
|
|
2858
|
+
enforceSelection: providerPolicy.enforceOnFirstLogin ?? true,
|
|
2859
|
+
onShowOnboarding: () => setShowOnboarding(true),
|
|
2860
|
+
onHideOnboarding: () => setShowOnboarding(false)
|
|
2861
|
+
}
|
|
2862
|
+
),
|
|
2863
|
+
/* @__PURE__ */ jsxRuntime.jsx(LoginModalPortal, {}),
|
|
2864
|
+
/* @__PURE__ */ jsxRuntime.jsx(DepositModalPortal, {}),
|
|
2865
|
+
showOnboarding && keyStorageType && /* @__PURE__ */ jsxRuntime.jsx(
|
|
2866
|
+
Modal,
|
|
2867
|
+
{
|
|
2868
|
+
open: true,
|
|
2869
|
+
onOpenChange: () => setShowOnboarding(false),
|
|
2870
|
+
onPointerDownOutside: (e) => e.preventDefault(),
|
|
2871
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-w-md mx-auto", children: [
|
|
2872
|
+
/* @__PURE__ */ jsxRuntime.jsx(ModalTitle, { className: "sr-only", children: "Onboarding" }),
|
|
2873
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2874
|
+
OnboardingFlow,
|
|
2875
|
+
{
|
|
2876
|
+
keyStorageType,
|
|
2877
|
+
onComplete: () => setShowOnboarding(false)
|
|
2878
|
+
}
|
|
2879
|
+
)
|
|
2880
|
+
] })
|
|
2881
|
+
}
|
|
2882
|
+
),
|
|
2883
|
+
children
|
|
2884
|
+
] })
|
|
2885
|
+
}
|
|
2886
|
+
) }) });
|
|
2887
|
+
};
|
|
2888
|
+
function LoginModalPortal() {
|
|
2889
|
+
const { isOpen, mode, close } = useVolrModal();
|
|
2890
|
+
const [portalRoot, setPortalRoot] = React3.useState(null);
|
|
2891
|
+
const [error, setError] = React3.useState(null);
|
|
2892
|
+
React3.useEffect(() => {
|
|
2893
|
+
if (typeof window === "undefined") return;
|
|
2894
|
+
let root = document.getElementById("volr-modal-root");
|
|
2895
|
+
if (!root) {
|
|
2896
|
+
root = document.createElement("div");
|
|
2897
|
+
root.id = "volr-modal-root";
|
|
2898
|
+
document.body.appendChild(root);
|
|
2899
|
+
}
|
|
2900
|
+
setPortalRoot(root);
|
|
2901
|
+
return () => {
|
|
2902
|
+
if (root && root.childNodes.length === 0) {
|
|
2903
|
+
root.remove();
|
|
2904
|
+
}
|
|
2905
|
+
};
|
|
2906
|
+
}, []);
|
|
2907
|
+
const handleClose = () => {
|
|
2908
|
+
console.log("[LoginModalPortal] handleClose called");
|
|
2909
|
+
setError(null);
|
|
2910
|
+
close();
|
|
2911
|
+
};
|
|
2912
|
+
const handleError = (err) => {
|
|
2913
|
+
console.error("[LoginModal] Error:", err);
|
|
2914
|
+
setError(err);
|
|
2915
|
+
};
|
|
2916
|
+
if (!portalRoot) return null;
|
|
2917
|
+
return reactDom.createPortal(
|
|
2918
|
+
/* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2919
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2920
|
+
SigninModal,
|
|
2921
|
+
{
|
|
2922
|
+
isOpen: isOpen && mode === "auth",
|
|
2923
|
+
onClose: handleClose,
|
|
2924
|
+
onError: handleError
|
|
2925
|
+
}
|
|
2926
|
+
),
|
|
2927
|
+
error && /* @__PURE__ */ jsxRuntime.jsx(
|
|
2928
|
+
"div",
|
|
2929
|
+
{
|
|
2930
|
+
style: {
|
|
2931
|
+
position: "fixed",
|
|
2932
|
+
bottom: "20px",
|
|
2933
|
+
right: "20px",
|
|
2934
|
+
backgroundColor: "#fef2f2",
|
|
2935
|
+
border: "1px solid #fecaca",
|
|
2936
|
+
borderRadius: "8px",
|
|
2937
|
+
padding: "12px 16px",
|
|
2938
|
+
maxWidth: "400px",
|
|
2939
|
+
boxShadow: "0 10px 15px -3px rgba(0, 0, 0, 0.1)",
|
|
2940
|
+
zIndex: 10001
|
|
2941
|
+
},
|
|
2942
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: "14px", color: "#991b1b" }, children: error.message })
|
|
2943
|
+
}
|
|
2944
|
+
)
|
|
2945
|
+
] }),
|
|
2946
|
+
portalRoot
|
|
2947
|
+
);
|
|
2948
|
+
}
|
|
2949
|
+
function DepositModalPortal() {
|
|
2950
|
+
const { isOpen, mode, close } = useVolrModal();
|
|
2951
|
+
const [portalRoot, setPortalRoot] = React3.useState(null);
|
|
2952
|
+
React3.useEffect(() => {
|
|
2953
|
+
if (typeof window === "undefined") return;
|
|
2954
|
+
let root = document.getElementById("volr-modal-root");
|
|
2955
|
+
if (!root) {
|
|
2956
|
+
root = document.createElement("div");
|
|
2957
|
+
root.id = "volr-modal-root";
|
|
2958
|
+
document.body.appendChild(root);
|
|
2959
|
+
}
|
|
2960
|
+
setPortalRoot(root);
|
|
2961
|
+
return () => {
|
|
2962
|
+
if (root && root.childNodes.length === 0) {
|
|
2963
|
+
root.remove();
|
|
2964
|
+
}
|
|
2965
|
+
};
|
|
2966
|
+
}, []);
|
|
2967
|
+
if (!portalRoot) return null;
|
|
2968
|
+
return reactDom.createPortal(
|
|
2969
|
+
/* @__PURE__ */ jsxRuntime.jsx(DepositModal, { open: isOpen && mode === "deposit", onOpenChange: close }),
|
|
2970
|
+
portalRoot
|
|
2971
|
+
);
|
|
2972
|
+
}
|
|
2973
|
+
function OnboardingChecker({
|
|
2974
|
+
keyStorageType,
|
|
2975
|
+
enforceSelection,
|
|
2976
|
+
onShowOnboarding,
|
|
2977
|
+
onHideOnboarding
|
|
2978
|
+
}) {
|
|
2979
|
+
const { user, provider, isLoading } = react.useVolr();
|
|
2980
|
+
const { isOpen: isLoginModalOpen } = useVolrModal();
|
|
2981
|
+
React3.useEffect(() => {
|
|
2982
|
+
if (isLoading) {
|
|
2983
|
+
return;
|
|
2984
|
+
}
|
|
2985
|
+
if (isLoginModalOpen) {
|
|
2986
|
+
onHideOnboarding();
|
|
2987
|
+
return;
|
|
2988
|
+
}
|
|
2989
|
+
if (user && !provider) {
|
|
2990
|
+
if (user.keyStorageType) {
|
|
2991
|
+
onHideOnboarding();
|
|
2992
|
+
return;
|
|
2993
|
+
}
|
|
2994
|
+
if (enforceSelection) {
|
|
2995
|
+
if (!keyStorageType) {
|
|
2996
|
+
console.error(
|
|
2997
|
+
"keyStorageType must be specified in VolrUIProvider props. Please set keyStorageType prop in VolrUIProvider."
|
|
2998
|
+
);
|
|
2999
|
+
return;
|
|
3000
|
+
}
|
|
3001
|
+
onShowOnboarding();
|
|
3002
|
+
}
|
|
3003
|
+
} else if (provider) {
|
|
3004
|
+
onHideOnboarding();
|
|
3005
|
+
}
|
|
3006
|
+
}, [
|
|
3007
|
+
user,
|
|
3008
|
+
provider,
|
|
3009
|
+
isLoading,
|
|
3010
|
+
isLoginModalOpen,
|
|
3011
|
+
enforceSelection,
|
|
3012
|
+
keyStorageType,
|
|
3013
|
+
onShowOnboarding,
|
|
3014
|
+
onHideOnboarding
|
|
3015
|
+
]);
|
|
3016
|
+
return null;
|
|
3017
|
+
}
|
|
3018
|
+
function useSwitchNetwork() {
|
|
3019
|
+
const { client } = react.useInternalAuth();
|
|
3020
|
+
return React3.useCallback(
|
|
3021
|
+
async (chainId) => {
|
|
3022
|
+
if (typeof window === "undefined" || !window.ethereum) {
|
|
3023
|
+
throw new Error("No wallet found");
|
|
3024
|
+
}
|
|
3025
|
+
const ethereum = window.ethereum;
|
|
3026
|
+
const chainIdHex = `0x${chainId.toString(16)}`;
|
|
3027
|
+
try {
|
|
3028
|
+
await ethereum.request({
|
|
3029
|
+
method: "wallet_switchEthereumChain",
|
|
3030
|
+
params: [{ chainId: chainIdHex }]
|
|
3031
|
+
});
|
|
3032
|
+
} catch (switchError) {
|
|
3033
|
+
if (switchError.code === 4902) {
|
|
3034
|
+
try {
|
|
3035
|
+
const response = await client.get(
|
|
3036
|
+
`/networks/${chainId}?includeWalletConfig=true&includeRpcUrl=true`
|
|
3037
|
+
);
|
|
3038
|
+
if (!response.rpcUrl) {
|
|
3039
|
+
throw new Error(`RPC URL not available for chainId ${chainId}`);
|
|
3040
|
+
}
|
|
3041
|
+
if (!response.nativeCurrency) {
|
|
3042
|
+
throw new Error(`Native currency configuration not available for chainId ${chainId}`);
|
|
3043
|
+
}
|
|
3044
|
+
await ethereum.request({
|
|
3045
|
+
method: "wallet_addEthereumChain",
|
|
3046
|
+
params: [
|
|
3047
|
+
{
|
|
3048
|
+
chainId: chainIdHex,
|
|
3049
|
+
chainName: response.name,
|
|
3050
|
+
nativeCurrency: response.nativeCurrency,
|
|
3051
|
+
rpcUrls: [response.rpcUrl],
|
|
3052
|
+
blockExplorerUrls: response.blockExplorerUrl ? [response.blockExplorerUrl] : void 0
|
|
3053
|
+
}
|
|
3054
|
+
]
|
|
3055
|
+
});
|
|
3056
|
+
} catch (addError) {
|
|
3057
|
+
throw new Error(
|
|
3058
|
+
`Failed to add network: ${addError instanceof Error ? addError.message : "Unknown error"}`
|
|
3059
|
+
);
|
|
3060
|
+
}
|
|
3061
|
+
} else {
|
|
3062
|
+
throw new Error(
|
|
3063
|
+
`Failed to switch network: ${switchError.message || "Unknown error"}`
|
|
3064
|
+
);
|
|
3065
|
+
}
|
|
3066
|
+
}
|
|
3067
|
+
},
|
|
3068
|
+
[client]
|
|
3069
|
+
);
|
|
3070
|
+
}
|
|
3071
|
+
async function switchNetwork(chainId, client) {
|
|
3072
|
+
const chainIdHex = `0x${chainId.toString(16)}`;
|
|
3073
|
+
if (typeof window === "undefined" || !window.ethereum) {
|
|
3074
|
+
throw new Error("No wallet found");
|
|
3075
|
+
}
|
|
3076
|
+
const ethereum = window.ethereum;
|
|
3077
|
+
try {
|
|
3078
|
+
await ethereum.request({
|
|
3079
|
+
method: "wallet_switchEthereumChain",
|
|
3080
|
+
params: [{ chainId: chainIdHex }]
|
|
3081
|
+
});
|
|
3082
|
+
} catch (switchError) {
|
|
3083
|
+
if (switchError.code === 4902) {
|
|
3084
|
+
try {
|
|
3085
|
+
const response = await client.get(
|
|
3086
|
+
`/networks/${chainId}?includeWalletConfig=true&includeRpcUrl=true`
|
|
3087
|
+
);
|
|
3088
|
+
if (!response.rpcUrl) {
|
|
3089
|
+
throw new Error(`RPC URL not available for chainId ${chainId}`);
|
|
3090
|
+
}
|
|
3091
|
+
if (!response.nativeCurrency) {
|
|
3092
|
+
throw new Error(`Native currency configuration not available for chainId ${chainId}`);
|
|
3093
|
+
}
|
|
3094
|
+
await ethereum.request({
|
|
3095
|
+
method: "wallet_addEthereumChain",
|
|
3096
|
+
params: [
|
|
3097
|
+
{
|
|
3098
|
+
chainId: chainIdHex,
|
|
3099
|
+
chainName: response.name,
|
|
3100
|
+
nativeCurrency: response.nativeCurrency,
|
|
3101
|
+
rpcUrls: [response.rpcUrl],
|
|
3102
|
+
blockExplorerUrls: response.blockExplorerUrl ? [response.blockExplorerUrl] : void 0
|
|
3103
|
+
}
|
|
3104
|
+
]
|
|
3105
|
+
});
|
|
3106
|
+
} catch (addError) {
|
|
3107
|
+
throw new Error(
|
|
3108
|
+
`Failed to add network: ${addError instanceof Error ? addError.message : "Unknown error"}`
|
|
3109
|
+
);
|
|
3110
|
+
}
|
|
3111
|
+
} else {
|
|
3112
|
+
throw new Error(
|
|
3113
|
+
`Failed to switch network: ${switchError.message || "Unknown error"}`
|
|
3114
|
+
);
|
|
3115
|
+
}
|
|
3116
|
+
}
|
|
3117
|
+
}
|
|
3118
|
+
async function getCurrentChainId() {
|
|
3119
|
+
if (typeof window === "undefined" || !window.ethereum) {
|
|
3120
|
+
throw new Error("No wallet found");
|
|
3121
|
+
}
|
|
3122
|
+
const chainIdHex = await window.ethereum.request({
|
|
3123
|
+
method: "eth_chainId"
|
|
3124
|
+
});
|
|
3125
|
+
return parseInt(chainIdHex, 16);
|
|
3126
|
+
}
|
|
3127
|
+
|
|
3128
|
+
exports.I18nContext = I18nContext;
|
|
3129
|
+
exports.I18nProvider = I18nProvider;
|
|
3130
|
+
exports.MpcConnectView = MpcConnectView;
|
|
3131
|
+
exports.PasskeyEnrollView = PasskeyEnrollView;
|
|
3132
|
+
exports.VolrUIProvider = VolrUIProvider;
|
|
3133
|
+
exports.getCurrentChainId = getCurrentChainId;
|
|
3134
|
+
exports.switchNetwork = switchNetwork;
|
|
3135
|
+
exports.useI18n = useI18n;
|
|
3136
|
+
exports.useSwitchNetwork = useSwitchNetwork;
|
|
3137
|
+
exports.useTranslation = useTranslation;
|
|
3138
|
+
exports.useVolrModal = useVolrModal;
|
|
3139
|
+
exports.useVolrUI = useVolrUI;
|
|
3140
|
+
//# sourceMappingURL=index.cjs.map
|
|
3141
|
+
//# sourceMappingURL=index.cjs.map
|