@cavos/kit 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,999 @@
1
+ import { CavosAuth, HttpRecoveryClient, Cavos, generateRecoveryCode } from '../chunk-XWBX2ZIO.mjs';
2
+ import { createContext, useState, useRef, useEffect, useCallback, useContext } from 'react';
3
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
4
+
5
+ var cavosLogoBase64 = "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";
6
+ var STYLE_ID = "cavos-modal-styles-v2";
7
+ function injectStyles() {
8
+ if (typeof document === "undefined") return;
9
+ if (document.getElementById(STYLE_ID)) return;
10
+ const el = document.createElement("style");
11
+ el.id = STYLE_ID;
12
+ el.textContent = `
13
+ @keyframes cavos-fade { from { opacity:0; } to { opacity:1; } }
14
+ @keyframes cavos-up {
15
+ from { opacity:0; transform:translateY(12px) scale(0.985); }
16
+ to { opacity:1; transform:translateY(0) scale(1); }
17
+ }
18
+ @keyframes cavos-sheet {
19
+ from { transform:translateY(100%); }
20
+ to { transform:translateY(0); }
21
+ }
22
+ @keyframes cavos-spin {
23
+ from { transform:rotate(0deg); } to { transform:rotate(360deg); }
24
+ }
25
+ @keyframes cavos-pop {
26
+ 0% { transform:scale(0.5); opacity:0; }
27
+ 60% { transform:scale(1.12); opacity:1; }
28
+ 100% { transform:scale(1); opacity:1; }
29
+ }
30
+ @keyframes cavos-check-draw {
31
+ from { stroke-dashoffset: 30; }
32
+ to { stroke-dashoffset: 0; }
33
+ }
34
+ @keyframes cavos-ring-glow {
35
+ 0%,100% { box-shadow: 0 0 0 0 rgba(34,197,94,0.4); }
36
+ 50% { box-shadow: 0 0 0 10px rgba(34,197,94,0); }
37
+ }
38
+ .cavos-check-circle {
39
+ animation: cavos-pop 0.45s cubic-bezier(.22,1,.36,1) forwards;
40
+ }
41
+ .cavos-check-path {
42
+ stroke-dasharray: 30;
43
+ stroke-dashoffset: 30;
44
+ animation: cavos-check-draw 0.35s 0.2s cubic-bezier(.22,1,.36,1) forwards;
45
+ }
46
+ .cavos-input-inner:focus { outline:none; }
47
+ .cavos-provider:active { transform:scale(0.99); }
48
+ .cavos-primary-btn:active { transform:scale(0.98); }
49
+ .cavos-otp-input {
50
+ width: 100%;
51
+ text-align: center;
52
+ font-size: 22px;
53
+ font-weight: 600;
54
+ background: transparent;
55
+ border: none;
56
+ outline: none;
57
+ color: inherit;
58
+ font-family: inherit;
59
+ caret-color: transparent;
60
+ }
61
+ .cavos-otp-box {
62
+ transition: border-color 0.15s, box-shadow 0.15s, transform 0.1s;
63
+ }
64
+ .cavos-otp-box-filled {
65
+ transform: scale(1.04);
66
+ }
67
+ .cavos-divider-line {
68
+ flex: 1;
69
+ height: 1px;
70
+ }
71
+ /* Theme-aware interaction styles. The overlay carries data-cavos-theme so
72
+ hovers/focus rings stay legible in both light and dark \u2014 the previous
73
+ rgba(0,0,0,\u2026) rules disappeared against the dark background. */
74
+ [data-cavos-theme="light"] .cavos-input-row:focus-within {
75
+ border-color: rgba(0,0,0,0.35) !important;
76
+ box-shadow: 0 0 0 3px rgba(0,0,0,0.06) !important;
77
+ }
78
+ [data-cavos-theme="dark"] .cavos-input-row:focus-within {
79
+ border-color: rgba(255,255,255,0.45) !important;
80
+ box-shadow: 0 0 0 3px rgba(255,255,255,0.08) !important;
81
+ }
82
+ [data-cavos-theme="light"] .cavos-provider:hover { background: rgba(0,0,0,0.035) !important; }
83
+ [data-cavos-theme="dark"] .cavos-provider:hover { background: rgba(255,255,255,0.07) !important; }
84
+ [data-cavos-theme="light"] .cavos-close:hover { background: rgba(0,0,0,0.05) !important; }
85
+ [data-cavos-theme="dark"] .cavos-close:hover { background: rgba(255,255,255,0.08) !important; }
86
+ [data-cavos-theme="light"] .cavos-sub-btn:hover { color: rgba(0,0,0,0.6) !important; }
87
+ [data-cavos-theme="dark"] .cavos-sub-btn:hover { color: rgba(255,255,255,0.65) !important; }
88
+ [data-cavos-theme="light"] .cavos-submit-btn:hover { color: rgba(0,0,0,0.8) !important; }
89
+ [data-cavos-theme="dark"] .cavos-submit-btn:hover { color: rgba(255,255,255,0.85) !important; }
90
+ [data-cavos-theme="light"] .cavos-primary-btn:hover { opacity: 0.88; }
91
+ [data-cavos-theme="dark"] .cavos-primary-btn:hover { opacity: 0.9; }
92
+ [data-cavos-theme="light"] .cavos-divider-line { background: rgba(0,0,0,0.08); }
93
+ [data-cavos-theme="dark"] .cavos-divider-line { background: rgba(255,255,255,0.1); }
94
+ `;
95
+ document.head.appendChild(el);
96
+ }
97
+ var GoogleIcon = () => /* @__PURE__ */ jsxs("svg", { width: "18", height: "18", viewBox: "0 0 18 18", fill: "none", children: [
98
+ /* @__PURE__ */ jsx("path", { d: "M17.64 9.2c0-.637-.057-1.251-.164-1.84H9v3.481h4.844c-.209 1.125-.843 2.078-1.796 2.717v2.258h2.908c1.702-1.567 2.684-3.875 2.684-6.615z", fill: "#4285F4" }),
99
+ /* @__PURE__ */ jsx("path", { d: "M9 18c2.43 0 4.467-.806 5.956-2.184l-2.908-2.258c-.806.54-1.837.86-3.048.86-2.344 0-4.328-1.584-5.036-3.711H.957v2.332A8.997 8.997 0 009 18z", fill: "#34A853" }),
100
+ /* @__PURE__ */ jsx("path", { d: "M3.964 10.707A5.41 5.41 0 013.682 9c0-.593.102-1.17.282-1.707V4.961H.957A8.996 8.996 0 000 9c0 1.452.348 2.827.957 4.039l3.007-2.332z", fill: "#FBBC05" }),
101
+ /* @__PURE__ */ jsx("path", { d: "M9 3.58c1.321 0 2.508.454 3.44 1.345l2.582-2.58C13.463.891 11.426 0 9 0A8.997 8.997 0 00.957 4.961L3.964 7.293C4.672 5.163 6.656 3.58 9 3.58z", fill: "#EA4335" })
102
+ ] });
103
+ var AppleIcon = () => /* @__PURE__ */ jsx("svg", { width: "16", height: "16", viewBox: "0 0 814 1000", fill: "currentColor", children: /* @__PURE__ */ jsx("path", { d: "M788.1 340.9c-5.8 4.5-108.2 62.2-108.2 190.5 0 148.4 130.3 200.9 134.2 202.2-.6 3.2-20.7 71.9-68.7 141.9-42.8 61.6-87.5 123.1-155.5 123.1s-85.5-39.5-164-39.5c-76 0-103.7 40.8-165.9 40.8s-105-57.8-155.5-127.4C46 790.7 0 663 0 541.8c0-194.3 126.4-297.5 250.8-297.5 66.1 0 121.2 43.4 162.7 43.4 39.5 0 101.1-46 176.3-46 28.5 0 130.9 2.6 198.3 99.2zm-234-181.5c31.1-36.9 53.1-88.1 53.1-139.3 0-7.1-.6-14.3-1.9-20.1-50.6 1.9-110.8 33.7-147.1 75.8-28.5 32.4-55.1 83.6-55.1 135.5 0 7.8 1.3 15.6 1.9 18.1 3.2.6 8.4 1.3 13.6 1.3 45.4 0 102.5-30.4 135.5-71.3z" }) });
104
+ var EmailIcon = () => /* @__PURE__ */ jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round", children: [
105
+ /* @__PURE__ */ jsx("rect", { x: "2", y: "4", width: "20", height: "16", rx: "2" }),
106
+ /* @__PURE__ */ jsx("path", { d: "m22 7-8.97 5.7a1.94 1.94 0 01-2.06 0L2 7" })
107
+ ] });
108
+ var CavosLogo = ({ invert }) => /* @__PURE__ */ jsx("img", { src: `data:image/png;base64,${cavosLogoBase64}`, alt: "Cavos", style: { width: "auto", height: "16px", objectFit: "contain", opacity: 0.55, flexShrink: 0, filter: invert ? "invert(1)" : "none" } });
109
+ function Spinner({ size = 16, color = "#888" }) {
110
+ return /* @__PURE__ */ jsxs(
111
+ "svg",
112
+ {
113
+ width: size,
114
+ height: size,
115
+ viewBox: "0 0 24 24",
116
+ fill: "none",
117
+ style: { animation: "cavos-spin 0.75s linear infinite", flexShrink: 0 },
118
+ children: [
119
+ /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "10", stroke: color, strokeOpacity: "0.2", strokeWidth: "2.5" }),
120
+ /* @__PURE__ */ jsx("path", { d: "M12 2a10 10 0 0110 10", stroke: color, strokeWidth: "2.5", strokeLinecap: "round" })
121
+ ]
122
+ }
123
+ );
124
+ }
125
+ function useIsMobile() {
126
+ const [isMobile, setIsMobile] = useState(false);
127
+ useEffect(() => {
128
+ const mq = window.matchMedia("(max-width: 640px)");
129
+ setIsMobile(mq.matches);
130
+ const handler = (e) => setIsMobile(e.matches);
131
+ mq.addEventListener("change", handler);
132
+ return () => mq.removeEventListener("change", handler);
133
+ }, []);
134
+ return isMobile;
135
+ }
136
+ var FONT = '-apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif';
137
+ function baseOverlay(isMobile) {
138
+ return {
139
+ position: "fixed",
140
+ inset: 0,
141
+ background: "rgba(0,0,0,0.5)",
142
+ backdropFilter: "blur(10px)",
143
+ WebkitBackdropFilter: "blur(10px)",
144
+ zIndex: 9999,
145
+ display: "flex",
146
+ alignItems: isMobile ? "flex-end" : "center",
147
+ justifyContent: "center",
148
+ padding: isMobile ? "0" : "16px",
149
+ animation: "cavos-fade 0.18s ease",
150
+ fontFamily: FONT
151
+ };
152
+ }
153
+ function lightCard(isMobile, bg) {
154
+ return isMobile ? {
155
+ background: bg,
156
+ borderRadius: "20px 20px 0 0",
157
+ width: "100%",
158
+ maxWidth: "100%",
159
+ boxShadow: "0 -8px 40px rgba(0,0,0,0.18)",
160
+ animation: "cavos-sheet 0.32s cubic-bezier(0.22,1,0.36,1)",
161
+ overflow: "hidden"
162
+ } : {
163
+ background: bg,
164
+ borderRadius: "22px",
165
+ width: "100%",
166
+ maxWidth: "400px",
167
+ boxShadow: "0 24px 60px rgba(0,0,0,0.22), 0 0 0 1px rgba(0,0,0,0.05)",
168
+ animation: "cavos-up 0.25s cubic-bezier(0.22,1,0.36,1)",
169
+ overflow: "hidden"
170
+ };
171
+ }
172
+ function providerBtn(textColor) {
173
+ const isLight = textColor === "#111111" || textColor === "#111";
174
+ return {
175
+ width: "100%",
176
+ display: "flex",
177
+ alignItems: "center",
178
+ justifyContent: "center",
179
+ gap: "10px",
180
+ padding: "12px 16px",
181
+ background: isLight ? "#fff" : "rgba(255,255,255,0.04)",
182
+ border: `1px solid ${isLight ? "rgba(0,0,0,0.12)" : "rgba(255,255,255,0.12)"}`,
183
+ borderRadius: "12px",
184
+ cursor: "pointer",
185
+ fontSize: "14px",
186
+ fontWeight: 500,
187
+ color: textColor,
188
+ fontFamily: "inherit",
189
+ transition: "background 0.15s, transform 0.1s, border-color 0.15s",
190
+ position: "relative"
191
+ };
192
+ }
193
+ function footerBar(textColor) {
194
+ const isLight = textColor === "#111111" || textColor === "#111";
195
+ return {
196
+ borderTop: `1px solid ${isLight ? "rgba(0,0,0,0.06)" : "rgba(255,255,255,0.06)"}`,
197
+ padding: "12px 20px",
198
+ display: "flex",
199
+ alignItems: "center",
200
+ justifyContent: "center",
201
+ gap: "5px",
202
+ fontSize: "11px",
203
+ color: isLight ? "rgba(0,0,0,0.28)" : "rgba(255,255,255,0.28)"
204
+ };
205
+ }
206
+ function closeBtn(textColor) {
207
+ return {
208
+ position: "absolute",
209
+ top: "16px",
210
+ right: "16px",
211
+ width: "28px",
212
+ height: "28px",
213
+ borderRadius: "50%",
214
+ border: "none",
215
+ background: "transparent",
216
+ cursor: "pointer",
217
+ display: "flex",
218
+ alignItems: "center",
219
+ justifyContent: "center",
220
+ color: textColor === "#111111" || textColor === "#111" ? "rgba(0,0,0,0.3)" : "rgba(255,255,255,0.4)",
221
+ padding: 0,
222
+ transition: "background 0.15s"
223
+ };
224
+ }
225
+ function mobileHandle() {
226
+ return {
227
+ width: "36px",
228
+ height: "4px",
229
+ borderRadius: "2px",
230
+ background: "rgba(0,0,0,0.15)",
231
+ margin: "12px auto 0"
232
+ };
233
+ }
234
+ var CloseX = () => /* @__PURE__ */ jsxs("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", children: [
235
+ /* @__PURE__ */ jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
236
+ /* @__PURE__ */ jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
237
+ ] });
238
+ function CavosAuthModal({
239
+ open,
240
+ onClose,
241
+ appName,
242
+ providers = ["google", "apple", "email"],
243
+ emailMode = "magic-link",
244
+ primaryColor = "#0A0908",
245
+ theme = "light"
246
+ }) {
247
+ const {
248
+ login,
249
+ sendMagicLink,
250
+ sendOtp,
251
+ verifyOtp,
252
+ isAuthenticated,
253
+ address,
254
+ walletStatus,
255
+ authError,
256
+ clearAuthError,
257
+ resendDeviceApproval,
258
+ recover
259
+ } = useCavos();
260
+ const isMobile = useIsMobile();
261
+ const isLight = theme !== "dark";
262
+ const backgroundColor = isLight ? "#ffffff" : "#111111";
263
+ const textColor = isLight ? "#111111" : "#ffffff";
264
+ const subTextColor = isLight ? "rgba(0,0,0,0.4)" : "rgba(255,255,255,0.4)";
265
+ const inputBg = isLight ? "#fff" : "rgba(255,255,255,0.06)";
266
+ const inputBorder = isLight ? "1px solid rgba(0,0,0,0.12)" : "1px solid rgba(255,255,255,0.12)";
267
+ const errBg = isLight ? "rgba(239,68,68,0.06)" : "rgba(239,68,68,0.08)";
268
+ const errColor = isLight ? "#dc2626" : "#f87171";
269
+ const errBorder = isLight ? "rgba(239,68,68,0.18)" : "rgba(239,68,68,0.2)";
270
+ const card = lightCard(isMobile, backgroundColor);
271
+ const overlay = baseOverlay(isMobile);
272
+ const handle = mobileHandle();
273
+ const footer = footerBar(textColor);
274
+ const close = closeBtn(textColor);
275
+ const pBtn = providerBtn(textColor);
276
+ const [screen, setScreen] = useState("select");
277
+ const [email, setEmail] = useState("");
278
+ const [otpCode, setOtpCode] = useState("");
279
+ const [error, setError] = useState("");
280
+ const [busy, setBusy] = useState(false);
281
+ const [deployState, setDeployState] = useState("loading");
282
+ const [resendCountdown, setResendCountdown] = useState(0);
283
+ const [deviceResendBusy, setDeviceResendBusy] = useState(false);
284
+ const [recoverCode, setRecoverCode] = useState("");
285
+ const [recoverBusy, setRecoverBusy] = useState(false);
286
+ const doneHandledRef = useRef(false);
287
+ const closeTimerRef = useRef(null);
288
+ const otpBoxRefs = useRef([null, null, null, null, null, null]);
289
+ const setOtpDigit = (i, raw) => {
290
+ const digit = raw.replace(/\D/g, "").slice(-1);
291
+ setOtpCode((prev) => {
292
+ const chars = prev.split("");
293
+ while (chars.length < 6) chars.push("");
294
+ chars[i] = digit;
295
+ const next = chars.join("").slice(0, 6);
296
+ if (digit && i < 5) {
297
+ const target = i + 1;
298
+ otpBoxRefs.current[target]?.focus();
299
+ }
300
+ return next;
301
+ });
302
+ };
303
+ const onOtpKeyDown = (i, e) => {
304
+ if (e.key === "Backspace" && !otpCode[i] && i > 0) {
305
+ otpBoxRefs.current[i - 1]?.focus();
306
+ e.preventDefault();
307
+ } else if (e.key === "ArrowLeft" && i > 0) {
308
+ otpBoxRefs.current[i - 1]?.focus();
309
+ e.preventDefault();
310
+ } else if (e.key === "ArrowRight" && i < 5) {
311
+ otpBoxRefs.current[i + 1]?.focus();
312
+ e.preventDefault();
313
+ }
314
+ };
315
+ const onOtpPaste = (e) => {
316
+ const text = e.clipboardData.getData("text").replace(/\D/g, "").slice(0, 6);
317
+ if (!text) return;
318
+ e.preventDefault();
319
+ setOtpCode(text);
320
+ const focusIdx = Math.min(text.length, 5);
321
+ otpBoxRefs.current[focusIdx]?.focus();
322
+ };
323
+ useEffect(() => {
324
+ injectStyles();
325
+ }, []);
326
+ useEffect(() => {
327
+ if (!authError) return;
328
+ setBusy(false);
329
+ setDeployState("loading");
330
+ if (screen !== "device-approval") setScreen("select");
331
+ setError(authError);
332
+ clearAuthError();
333
+ }, [authError, clearAuthError, screen]);
334
+ const triggerDone = useCallback((addr) => {
335
+ if (doneHandledRef.current) return;
336
+ doneHandledRef.current = true;
337
+ setScreen("deploying");
338
+ setDeployState("done");
339
+ closeTimerRef.current = setTimeout(() => {
340
+ onClose();
341
+ setScreen("select");
342
+ setDeployState("loading");
343
+ setEmail("");
344
+ setOtpCode("");
345
+ setError("");
346
+ doneHandledRef.current = false;
347
+ }, 1600);
348
+ }, [onClose]);
349
+ useEffect(() => {
350
+ if (!open) return;
351
+ if (walletStatus.isDeploying && screen !== "deploying" && screen !== "verify") {
352
+ setScreen("deploying");
353
+ setDeployState("loading");
354
+ doneHandledRef.current = false;
355
+ }
356
+ if (isAuthenticated && address && walletStatus.isReady) {
357
+ triggerDone(address);
358
+ }
359
+ if (walletStatus.awaitingApproval && screen !== "device-approval" && screen !== "recover") {
360
+ setScreen("device-approval");
361
+ doneHandledRef.current = false;
362
+ }
363
+ }, [open, isAuthenticated, address, walletStatus.isReady, walletStatus.isDeploying, walletStatus.awaitingApproval, screen, triggerDone]);
364
+ useEffect(() => () => {
365
+ if (closeTimerRef.current) clearTimeout(closeTimerRef.current);
366
+ }, []);
367
+ const handleClose = () => {
368
+ if (screen === "deploying") return;
369
+ setScreen("select");
370
+ setEmail("");
371
+ setOtpCode("");
372
+ setError("");
373
+ doneHandledRef.current = false;
374
+ onClose();
375
+ };
376
+ const handleOAuth = async (provider) => {
377
+ setError("");
378
+ setBusy(true);
379
+ try {
380
+ await login(provider);
381
+ } catch (e) {
382
+ const msg = e instanceof Error ? e.message : "Authentication failed.";
383
+ setError(msg);
384
+ setBusy(false);
385
+ }
386
+ };
387
+ const handleMagicLinkSubmit = async (e) => {
388
+ e.preventDefault();
389
+ if (!email) return;
390
+ setError("");
391
+ setBusy(true);
392
+ try {
393
+ await sendMagicLink(email);
394
+ setScreen("verify");
395
+ setResendCountdown(60);
396
+ } catch (e2) {
397
+ setError(e2 instanceof Error ? e2.message : "Failed to send magic link.");
398
+ } finally {
399
+ setBusy(false);
400
+ }
401
+ };
402
+ const handleOtpRequestSubmit = async (e) => {
403
+ e.preventDefault();
404
+ if (!email) return;
405
+ setError("");
406
+ setBusy(true);
407
+ try {
408
+ await sendOtp(email);
409
+ setOtpCode("");
410
+ setScreen("otp-code");
411
+ setResendCountdown(60);
412
+ } catch (e2) {
413
+ setError(e2 instanceof Error ? e2.message : "Failed to send code.");
414
+ } finally {
415
+ setBusy(false);
416
+ }
417
+ };
418
+ const handleOtpVerifySubmit = async (e) => {
419
+ e.preventDefault();
420
+ if (!email || otpCode.length !== 6) return;
421
+ setError("");
422
+ setBusy(true);
423
+ try {
424
+ await verifyOtp(email, otpCode);
425
+ setScreen("deploying");
426
+ setDeployState("loading");
427
+ } catch (e2) {
428
+ setError(e2 instanceof Error ? e2.message : "Invalid or expired code.");
429
+ setBusy(false);
430
+ }
431
+ };
432
+ const handleResend = async () => {
433
+ if (resendCountdown > 0) return;
434
+ setError("");
435
+ try {
436
+ if (emailMode === "otp") {
437
+ await sendOtp(email);
438
+ setOtpCode("");
439
+ } else {
440
+ await sendMagicLink(email);
441
+ }
442
+ setResendCountdown(60);
443
+ } catch (e) {
444
+ setError(e instanceof Error ? e.message : "Failed to resend.");
445
+ }
446
+ };
447
+ useEffect(() => {
448
+ if (resendCountdown <= 0) return;
449
+ const t = setTimeout(() => setResendCountdown((c) => c - 1), 1e3);
450
+ return () => clearTimeout(t);
451
+ }, [resendCountdown]);
452
+ if (!open) return null;
453
+ const handleDeviceResend = async () => {
454
+ if (resendCountdown > 0 || deviceResendBusy) return;
455
+ setDeviceResendBusy(true);
456
+ setError("");
457
+ try {
458
+ await resendDeviceApproval();
459
+ setResendCountdown(60);
460
+ } catch (e) {
461
+ setError(e instanceof Error ? e.message : "Failed to resend. Try again.");
462
+ } finally {
463
+ setDeviceResendBusy(false);
464
+ }
465
+ };
466
+ if (screen === "device-approval") {
467
+ const expired = walletStatus.awaitingApproval && !walletStatus.pendingRequestId;
468
+ return /* @__PURE__ */ jsx("div", { style: overlay, "data-cavos-theme": theme, role: "dialog", "aria-modal": true, children: /* @__PURE__ */ jsxs("div", { style: { ...card, position: "relative" }, children: [
469
+ isMobile && /* @__PURE__ */ jsx("div", { style: handle }),
470
+ /* @__PURE__ */ jsx("button", { className: "cavos-close", style: close, onClick: handleClose, "aria-label": "Close", children: /* @__PURE__ */ jsx(CloseX, {}) }),
471
+ /* @__PURE__ */ jsxs("div", { style: { padding: isMobile ? "28px 24px 32px" : "48px 24px 32px", textAlign: "center" }, children: [
472
+ /* @__PURE__ */ jsx("div", { style: { width: 48, height: 48, borderRadius: "50%", margin: "0 auto 16px", background: expired ? "rgba(239,68,68,0.08)" : "rgba(59,130,246,0.08)", border: `1px solid ${expired ? "rgba(239,68,68,0.18)" : "rgba(59,130,246,0.18)"}`, display: "flex", alignItems: "center", justifyContent: "center" }, children: /* @__PURE__ */ jsxs("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: expired ? "#dc2626" : "#3b82f6", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
473
+ /* @__PURE__ */ jsx("rect", { x: "5", y: "2", width: "14", height: "20", rx: "2.5" }),
474
+ /* @__PURE__ */ jsx("path", { d: "M12 18h.01" })
475
+ ] }) }),
476
+ /* @__PURE__ */ jsx("h2", { style: { margin: "0 0 8px", fontSize: "17px", fontWeight: 600, color: textColor, letterSpacing: "-0.02em" }, children: expired ? "Approval link expired" : "Approve this device" }),
477
+ /* @__PURE__ */ jsx("p", { style: { margin: "0 0 20px", fontSize: "13px", color: subTextColor, lineHeight: 1.55 }, children: expired ? "The approval link is no longer valid. Request a new one below." : /* @__PURE__ */ jsxs(Fragment, { children: [
478
+ "For your security, we sent an email to approve this device.",
479
+ appName ? /* @__PURE__ */ jsxs(Fragment, { children: [
480
+ " Open it on a device where you're already signed in to your ",
481
+ appName,
482
+ " account."
483
+ ] }) : null
484
+ ] }) }),
485
+ error && /* @__PURE__ */ jsx("div", { style: { background: errBg, border: `1px solid ${errBorder}`, borderRadius: "10px", padding: "9px 13px", fontSize: "13px", color: errColor, marginBottom: "14px" }, children: error }),
486
+ expired ? /* @__PURE__ */ jsxs("button", { className: "cavos-primary-btn", style: { width: "100%", padding: "12px", borderRadius: "12px", border: "none", background: primaryColor, color: "#fff", fontSize: "14px", fontWeight: 500, cursor: "pointer", fontFamily: "inherit", display: "flex", alignItems: "center", justifyContent: "center", gap: "8px", opacity: deviceResendBusy ? 0.65 : 1 }, onClick: handleDeviceResend, disabled: deviceResendBusy, children: [
487
+ deviceResendBusy && /* @__PURE__ */ jsx(Spinner, { size: 15, color: "#fff" }),
488
+ deviceResendBusy ? "Sending\u2026" : "Request a new link"
489
+ ] }) : /* @__PURE__ */ jsxs("div", { style: { background: isLight ? "rgba(0,0,0,0.03)" : "rgba(255,255,255,0.04)", border: `1px solid ${isLight ? "rgba(0,0,0,0.06)" : "rgba(255,255,255,0.06)"}`, borderRadius: "12px", padding: "14px 16px", display: "flex", alignItems: "center", gap: 10, justifyContent: "center", marginBottom: "14px" }, children: [
490
+ /* @__PURE__ */ jsx(Spinner, { size: 14, color: subTextColor }),
491
+ /* @__PURE__ */ jsx("span", { style: { fontSize: "12px", color: subTextColor }, children: "Waiting for approval\u2026" })
492
+ ] }),
493
+ !expired && /* @__PURE__ */ jsx("button", { className: "cavos-sub-btn", style: { background: "none", border: "none", cursor: resendCountdown > 0 ? "default" : "pointer", fontSize: "13px", color: subTextColor, width: "100%", textAlign: "center", padding: 0, fontFamily: "inherit", transition: "color 0.15s", opacity: resendCountdown > 0 ? 0.6 : 1 }, onClick: handleDeviceResend, disabled: resendCountdown > 0 || deviceResendBusy, children: resendCountdown > 0 ? `Resend email in ${resendCountdown}s` : "Resend approval email" }),
494
+ /* @__PURE__ */ jsx("button", { className: "cavos-sub-btn", style: { background: "none", border: "none", cursor: "pointer", fontSize: "13px", color: subTextColor, width: "100%", textAlign: "center", padding: "14px 0 0", fontFamily: "inherit", transition: "color 0.15s" }, onClick: () => {
495
+ setScreen("recover");
496
+ setError("");
497
+ }, children: "Sign in with recovery phrase instead" })
498
+ ] }),
499
+ /* @__PURE__ */ jsxs("div", { style: footer, children: [
500
+ /* @__PURE__ */ jsx(CavosLogo, { invert: !isLight }),
501
+ /* @__PURE__ */ jsx("span", { children: "Secured by Cavos" })
502
+ ] })
503
+ ] }) });
504
+ }
505
+ const handleRecoverSubmit = async (e) => {
506
+ e.preventDefault();
507
+ if (!recoverCode.trim()) return;
508
+ setRecoverBusy(true);
509
+ setError("");
510
+ try {
511
+ await recover(recoverCode);
512
+ setScreen("deploying");
513
+ setDeployState("loading");
514
+ } catch (e2) {
515
+ setError(e2 instanceof Error ? e2.message : "Sign-in failed. Check your recovery phrase and try again.");
516
+ setRecoverBusy(false);
517
+ }
518
+ };
519
+ if (screen === "recover") {
520
+ return /* @__PURE__ */ jsx("div", { style: overlay, "data-cavos-theme": theme, role: "dialog", "aria-modal": true, onClick: (e) => {
521
+ if (e.target === e.currentTarget) handleClose();
522
+ }, children: /* @__PURE__ */ jsxs("div", { style: { ...card, position: "relative" }, children: [
523
+ isMobile && /* @__PURE__ */ jsx("div", { style: handle }),
524
+ /* @__PURE__ */ jsx("button", { className: "cavos-close", style: { ...close, left: "16px", right: "auto" }, onClick: () => {
525
+ setScreen("device-approval");
526
+ setError("");
527
+ setRecoverCode("");
528
+ }, "aria-label": "Back", children: /* @__PURE__ */ jsx("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "M19 12H5M12 5l-7 7 7 7" }) }) }),
529
+ /* @__PURE__ */ jsx("button", { className: "cavos-close", style: close, onClick: handleClose, "aria-label": "Close", children: /* @__PURE__ */ jsx(CloseX, {}) }),
530
+ /* @__PURE__ */ jsxs("div", { style: { padding: isMobile ? "28px 22px 32px" : "52px 22px 22px" }, children: [
531
+ /* @__PURE__ */ jsx("h2", { style: { margin: "0 0 6px", fontSize: "17px", fontWeight: 600, color: textColor, letterSpacing: "-0.02em", textAlign: "center" }, children: "Sign in with recovery phrase" }),
532
+ /* @__PURE__ */ jsx("p", { style: { margin: "0 0 20px", fontSize: "13px", color: subTextColor, textAlign: "center", lineHeight: 1.5 }, children: "Enter the recovery phrase you saved when you set up this account." }),
533
+ error && /* @__PURE__ */ jsx("div", { style: { background: errBg, border: `1px solid ${errBorder}`, borderRadius: "10px", padding: "10px 14px", fontSize: "13px", color: errColor, marginBottom: "14px" }, children: error }),
534
+ /* @__PURE__ */ jsxs("form", { onSubmit: handleRecoverSubmit, style: { display: "flex", flexDirection: "column", gap: "10px" }, children: [
535
+ /* @__PURE__ */ jsx(
536
+ "textarea",
537
+ {
538
+ className: "cavos-input-inner",
539
+ style: { width: "100%", padding: "12px 14px", border: inputBorder, borderRadius: "12px", fontSize: "14px", color: textColor, background: inputBg, fontFamily: "inherit", boxSizing: "border-box", resize: "vertical", minHeight: 72, lineHeight: 1.5 },
540
+ placeholder: "Enter your recovery phrase",
541
+ value: recoverCode,
542
+ onChange: (e) => setRecoverCode(e.target.value),
543
+ required: true,
544
+ disabled: recoverBusy,
545
+ autoFocus: true
546
+ }
547
+ ),
548
+ /* @__PURE__ */ jsxs("button", { type: "submit", className: "cavos-primary-btn", style: { width: "100%", padding: "12px", marginTop: "4px", borderRadius: "12px", border: "none", background: primaryColor, color: "#fff", fontSize: "14px", fontWeight: 500, cursor: "pointer", fontFamily: "inherit", display: "flex", alignItems: "center", justifyContent: "center", gap: "8px", transition: "opacity 0.15s, transform 0.1s", opacity: recoverBusy ? 0.65 : 1 }, disabled: recoverBusy, children: [
549
+ recoverBusy && /* @__PURE__ */ jsx(Spinner, { size: 15, color: "#fff" }),
550
+ recoverBusy ? "Restoring access\u2026" : "Restore access"
551
+ ] })
552
+ ] })
553
+ ] }),
554
+ /* @__PURE__ */ jsxs("div", { style: footer, children: [
555
+ /* @__PURE__ */ jsx(CavosLogo, { invert: !isLight }),
556
+ /* @__PURE__ */ jsx("span", { children: "Secured by Cavos" })
557
+ ] })
558
+ ] }) });
559
+ }
560
+ if (screen === "deploying") {
561
+ const isDone = deployState === "done";
562
+ return /* @__PURE__ */ jsx("div", { style: overlay, "data-cavos-theme": theme, role: "dialog", "aria-modal": true, children: /* @__PURE__ */ jsxs("div", { style: card, children: [
563
+ isMobile && /* @__PURE__ */ jsx("div", { style: handle }),
564
+ /* @__PURE__ */ jsxs("div", { style: { padding: "52px 28px 44px", display: "flex", flexDirection: "column", alignItems: "center", textAlign: "center", gap: "16px" }, children: [
565
+ isDone ? /* @__PURE__ */ jsx("div", { className: "cavos-check-circle", style: { width: 64, height: 64, borderRadius: "50%", background: "rgba(34,197,94,0.12)", border: "1.5px solid rgba(34,197,94,0.35)", display: "flex", alignItems: "center", justifyContent: "center", animation: "cavos-ring-glow 1.5s ease-out" }, children: /* @__PURE__ */ jsx("svg", { width: "28", height: "28", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsx("polyline", { className: "cavos-check-path", points: "20 6 9 17 4 12", stroke: "#22c55e", strokeWidth: "2.2", strokeLinecap: "round", strokeLinejoin: "round" }) }) }) : /* @__PURE__ */ jsx("div", { style: { width: 64, height: 64, borderRadius: "50%", background: isLight ? "rgba(0,0,0,0.04)" : "rgba(255,255,255,0.04)", border: `1.5px solid ${isLight ? "rgba(0,0,0,0.08)" : "rgba(255,255,255,0.08)"}`, display: "flex", alignItems: "center", justifyContent: "center" }, children: /* @__PURE__ */ jsx(Spinner, { size: 26, color: isLight ? "rgba(0,0,0,0.4)" : "rgba(255,255,255,0.6)" }) }),
566
+ /* @__PURE__ */ jsxs("div", { children: [
567
+ /* @__PURE__ */ jsx("h2", { style: { margin: 0, fontSize: "17px", fontWeight: 600, color: textColor, letterSpacing: "-0.02em" }, children: isDone ? "You're all set" : "Setting up your account" }),
568
+ /* @__PURE__ */ jsx("p", { style: { margin: "6px 0 0", fontSize: "13px", color: subTextColor }, children: isDone ? "Your account is ready" : "This only takes a moment\u2026" })
569
+ ] })
570
+ ] }),
571
+ /* @__PURE__ */ jsxs("div", { style: footer, children: [
572
+ /* @__PURE__ */ jsx(CavosLogo, { invert: !isLight }),
573
+ /* @__PURE__ */ jsx("span", { children: "Secured by Cavos" })
574
+ ] })
575
+ ] }) });
576
+ }
577
+ if (screen === "verify") {
578
+ return /* @__PURE__ */ jsx("div", { style: overlay, "data-cavos-theme": theme, role: "dialog", "aria-modal": true, onClick: (e) => {
579
+ if (e.target === e.currentTarget) handleClose();
580
+ }, children: /* @__PURE__ */ jsxs("div", { style: { ...card, position: "relative" }, children: [
581
+ isMobile && /* @__PURE__ */ jsx("div", { style: handle }),
582
+ /* @__PURE__ */ jsx("button", { className: "cavos-close", style: close, onClick: handleClose, "aria-label": "Close", children: /* @__PURE__ */ jsx(CloseX, {}) }),
583
+ /* @__PURE__ */ jsxs("div", { style: { padding: isMobile ? "28px 24px 32px" : "40px 24px 24px", textAlign: "center" }, children: [
584
+ /* @__PURE__ */ jsx("div", { style: { width: 48, height: 48, borderRadius: "50%", margin: "0 auto 16px", background: "rgba(34,197,94,0.08)", border: "1px solid rgba(34,197,94,0.18)", display: "flex", alignItems: "center", justifyContent: "center" }, children: /* @__PURE__ */ jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "#22c55e", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z" }) }) }),
585
+ /* @__PURE__ */ jsx("h2", { style: { margin: "0 0 8px", fontSize: "17px", fontWeight: 600, color: textColor, letterSpacing: "-0.02em" }, children: "Check your inbox" }),
586
+ /* @__PURE__ */ jsxs("p", { style: { margin: "0 0 22px", fontSize: "13px", color: subTextColor, lineHeight: 1.55 }, children: [
587
+ "We sent a sign-in link to ",
588
+ /* @__PURE__ */ jsx("strong", { style: { color: textColor, fontWeight: 500 }, children: email }),
589
+ ".",
590
+ /* @__PURE__ */ jsx("br", {}),
591
+ "Open it on this device to continue."
592
+ ] }),
593
+ error && /* @__PURE__ */ jsx("div", { style: { background: errBg, border: `1px solid ${errBorder}`, borderRadius: "10px", padding: "9px 13px", fontSize: "13px", color: errColor, marginBottom: "14px" }, children: error }),
594
+ /* @__PURE__ */ jsx("button", { className: "cavos-primary-btn", style: { width: "100%", padding: "12px", borderRadius: "12px", border: "none", background: resendCountdown > 0 ? isLight ? "rgba(0,0,0,0.06)" : "rgba(255,255,255,0.08)" : primaryColor, color: resendCountdown > 0 ? subTextColor : "#fff", fontSize: "14px", fontWeight: 500, cursor: resendCountdown > 0 ? "default" : "pointer", fontFamily: "inherit", transition: "opacity 0.15s", marginBottom: "8px" }, onClick: handleResend, disabled: resendCountdown > 0, children: resendCountdown > 0 ? `Resend in ${resendCountdown}s` : "Resend link" }),
595
+ /* @__PURE__ */ jsx("button", { className: "cavos-sub-btn", style: { background: "none", border: "none", cursor: "pointer", fontSize: "13px", color: subTextColor, width: "100%", textAlign: "center", padding: "8px 0 0", fontFamily: "inherit", transition: "color 0.15s" }, onClick: () => {
596
+ setScreen("magic-link");
597
+ setError("");
598
+ }, children: "Use a different email" })
599
+ ] }),
600
+ /* @__PURE__ */ jsxs("div", { style: footer, children: [
601
+ /* @__PURE__ */ jsx(CavosLogo, { invert: !isLight }),
602
+ /* @__PURE__ */ jsx("span", { children: "Secured by Cavos" })
603
+ ] })
604
+ ] }) });
605
+ }
606
+ if (screen === "otp-code") {
607
+ return /* @__PURE__ */ jsx("div", { style: overlay, "data-cavos-theme": theme, role: "dialog", "aria-modal": true, onClick: (e) => {
608
+ if (e.target === e.currentTarget) handleClose();
609
+ }, children: /* @__PURE__ */ jsxs("div", { style: { ...card, position: "relative" }, children: [
610
+ isMobile && /* @__PURE__ */ jsx("div", { style: handle }),
611
+ /* @__PURE__ */ jsx("button", { className: "cavos-close", style: { ...close, left: "16px", right: "auto" }, onClick: () => {
612
+ setScreen("magic-link");
613
+ setError("");
614
+ setOtpCode("");
615
+ }, "aria-label": "Back", children: /* @__PURE__ */ jsx("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "M19 12H5M12 5l-7 7 7 7" }) }) }),
616
+ /* @__PURE__ */ jsx("button", { className: "cavos-close", style: close, onClick: handleClose, "aria-label": "Close", children: /* @__PURE__ */ jsx(CloseX, {}) }),
617
+ /* @__PURE__ */ jsxs("div", { style: { padding: isMobile ? "28px 22px 32px" : "52px 22px 22px", textAlign: "center" }, children: [
618
+ /* @__PURE__ */ jsx("h2", { style: { margin: "0 0 8px", fontSize: "17px", fontWeight: 600, color: textColor, letterSpacing: "-0.02em" }, children: "Enter your code" }),
619
+ /* @__PURE__ */ jsxs("p", { style: { margin: "0 0 20px", fontSize: "13px", color: subTextColor, lineHeight: 1.5 }, children: [
620
+ "We sent a 6-digit code to ",
621
+ /* @__PURE__ */ jsx("strong", { style: { color: textColor, fontWeight: 500 }, children: email }),
622
+ "."
623
+ ] }),
624
+ error && /* @__PURE__ */ jsx("div", { style: { background: errBg, border: `1px solid ${errBorder}`, borderRadius: "10px", padding: "10px 14px", fontSize: "13px", color: errColor, marginBottom: "14px", textAlign: "left" }, children: error }),
625
+ /* @__PURE__ */ jsxs("form", { onSubmit: handleOtpVerifySubmit, style: { display: "flex", flexDirection: "column", gap: "16px" }, children: [
626
+ /* @__PURE__ */ jsx("div", { style: { display: "flex", gap: "8px", justifyContent: "center" }, onPaste: onOtpPaste, children: [0, 1, 2, 3, 4, 5].map((i) => /* @__PURE__ */ jsx(
627
+ "input",
628
+ {
629
+ ref: (el) => {
630
+ otpBoxRefs.current[i] = el;
631
+ },
632
+ className: `cavos-input-inner cavos-otp-box ${otpCode[i] ? "cavos-otp-box-filled" : ""}`,
633
+ style: {
634
+ width: "44px",
635
+ height: "52px",
636
+ padding: 0,
637
+ border: inputBorder,
638
+ borderRadius: "12px",
639
+ fontSize: "22px",
640
+ fontWeight: 600,
641
+ color: textColor,
642
+ background: inputBg,
643
+ fontFamily: "inherit",
644
+ boxSizing: "border-box",
645
+ textAlign: "center"
646
+ },
647
+ type: "text",
648
+ inputMode: "numeric",
649
+ autoComplete: i === 0 ? "one-time-code" : "off",
650
+ maxLength: 1,
651
+ value: otpCode[i] ?? "",
652
+ onChange: (e) => setOtpDigit(i, e.target.value),
653
+ onKeyDown: (e) => onOtpKeyDown(i, e),
654
+ onFocus: (e) => e.target.select(),
655
+ disabled: busy,
656
+ autoFocus: i === 0
657
+ },
658
+ i
659
+ )) }),
660
+ /* @__PURE__ */ jsxs("button", { type: "submit", className: "cavos-primary-btn", style: { width: "100%", padding: "12px", marginTop: "4px", borderRadius: "12px", border: "none", background: primaryColor, color: "#fff", fontSize: "14px", fontWeight: 500, cursor: "pointer", fontFamily: "inherit", display: "flex", alignItems: "center", justifyContent: "center", gap: "8px", transition: "opacity 0.15s, transform 0.1s", opacity: busy || otpCode.length !== 6 ? 0.65 : 1 }, disabled: busy || otpCode.length !== 6, children: [
661
+ busy && /* @__PURE__ */ jsx(Spinner, { size: 15, color: "#fff" }),
662
+ busy ? "Verifying\u2026" : "Continue"
663
+ ] })
664
+ ] }),
665
+ /* @__PURE__ */ jsx("button", { className: "cavos-primary-btn", style: { width: "100%", padding: "12px", borderRadius: "12px", border: "none", background: resendCountdown > 0 ? isLight ? "rgba(0,0,0,0.06)" : "rgba(255,255,255,0.08)" : "transparent", color: resendCountdown > 0 ? subTextColor : primaryColor, fontSize: "14px", fontWeight: 500, cursor: resendCountdown > 0 ? "default" : "pointer", fontFamily: "inherit", transition: "opacity 0.15s", marginTop: "8px" }, onClick: handleResend, disabled: resendCountdown > 0 || busy, children: resendCountdown > 0 ? `Resend in ${resendCountdown}s` : "Resend code" }),
666
+ /* @__PURE__ */ jsx("button", { className: "cavos-sub-btn", style: { background: "none", border: "none", cursor: "pointer", fontSize: "13px", color: subTextColor, width: "100%", textAlign: "center", padding: "8px 0 0", fontFamily: "inherit", transition: "color 0.15s" }, onClick: () => {
667
+ setScreen("magic-link");
668
+ setError("");
669
+ setOtpCode("");
670
+ }, children: "Use a different email" })
671
+ ] }),
672
+ /* @__PURE__ */ jsxs("div", { style: footer, children: [
673
+ /* @__PURE__ */ jsx(CavosLogo, { invert: !isLight }),
674
+ /* @__PURE__ */ jsx("span", { children: "Secured by Cavos" })
675
+ ] })
676
+ ] }) });
677
+ }
678
+ if (screen === "magic-link") {
679
+ const isOtp = emailMode === "otp";
680
+ return /* @__PURE__ */ jsx("div", { style: overlay, "data-cavos-theme": theme, role: "dialog", "aria-modal": true, onClick: (e) => {
681
+ if (e.target === e.currentTarget) handleClose();
682
+ }, children: /* @__PURE__ */ jsxs("div", { style: { ...card, position: "relative" }, children: [
683
+ isMobile && /* @__PURE__ */ jsx("div", { style: handle }),
684
+ /* @__PURE__ */ jsx("button", { className: "cavos-close", style: { ...close, left: "16px", right: "auto" }, onClick: () => {
685
+ setScreen("select");
686
+ setError("");
687
+ }, "aria-label": "Back", children: /* @__PURE__ */ jsx("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "M19 12H5M12 5l-7 7 7 7" }) }) }),
688
+ /* @__PURE__ */ jsx("button", { className: "cavos-close", style: close, onClick: handleClose, "aria-label": "Close", children: /* @__PURE__ */ jsx(CloseX, {}) }),
689
+ /* @__PURE__ */ jsxs("div", { style: { padding: isMobile ? "28px 22px 32px" : "52px 22px 22px" }, children: [
690
+ /* @__PURE__ */ jsx("h2", { style: { margin: "0 0 6px", fontSize: "17px", fontWeight: 600, color: textColor, letterSpacing: "-0.02em", textAlign: "center" }, children: "Sign in with email" }),
691
+ /* @__PURE__ */ jsx("p", { style: { margin: "0 0 20px", fontSize: "13px", color: subTextColor, textAlign: "center", lineHeight: 1.5 }, children: isOtp ? "We'll send a secure sign-in code to your inbox." : "We'll send a secure sign-in link to your inbox." }),
692
+ error && /* @__PURE__ */ jsx("div", { style: { background: errBg, border: `1px solid ${errBorder}`, borderRadius: "10px", padding: "10px 14px", fontSize: "13px", color: errColor, marginBottom: "14px" }, children: error }),
693
+ /* @__PURE__ */ jsxs("form", { onSubmit: isOtp ? handleOtpRequestSubmit : handleMagicLinkSubmit, style: { display: "flex", flexDirection: "column", gap: "10px" }, children: [
694
+ /* @__PURE__ */ jsx("input", { className: "cavos-input-inner", style: { width: "100%", padding: "12px 14px", border: inputBorder, borderRadius: "12px", fontSize: "14px", color: textColor, background: inputBg, fontFamily: "inherit", boxSizing: "border-box", transition: "border-color 0.15s" }, type: "email", placeholder: "your@email.com", value: email, onChange: (e) => setEmail(e.target.value), required: true, disabled: busy, autoFocus: true }),
695
+ /* @__PURE__ */ jsxs("button", { type: "submit", className: "cavos-primary-btn", style: { width: "100%", padding: "12px", marginTop: "4px", borderRadius: "12px", border: "none", background: primaryColor, color: "#fff", fontSize: "14px", fontWeight: 500, cursor: "pointer", fontFamily: "inherit", display: "flex", alignItems: "center", justifyContent: "center", gap: "8px", transition: "opacity 0.15s, transform 0.1s", opacity: busy ? 0.65 : 1 }, disabled: busy, children: [
696
+ busy && /* @__PURE__ */ jsx(Spinner, { size: 15, color: "#fff" }),
697
+ busy ? "Sending\u2026" : isOtp ? "Send code" : "Send magic link"
698
+ ] })
699
+ ] })
700
+ ] }),
701
+ /* @__PURE__ */ jsxs("div", { style: footer, children: [
702
+ /* @__PURE__ */ jsx(CavosLogo, { invert: !isLight }),
703
+ /* @__PURE__ */ jsx("span", { children: "Secured by Cavos" })
704
+ ] })
705
+ ] }) });
706
+ }
707
+ const showEmail = providers.includes("email");
708
+ const showGoogle = providers.includes("google");
709
+ const showApple = providers.includes("apple");
710
+ const hasSocial = showGoogle || showApple;
711
+ const btnIcon = (icon, busyIcon, color) => /* @__PURE__ */ jsx("span", { style: { position: "absolute", left: "16px", width: 20, height: 20, display: "flex", alignItems: "center", justifyContent: "center", color, flexShrink: 0 }, children: busy ? busyIcon : icon });
712
+ return /* @__PURE__ */ jsx("div", { style: overlay, "data-cavos-theme": theme, role: "dialog", "aria-modal": true, onClick: (e) => {
713
+ if (e.target === e.currentTarget) handleClose();
714
+ }, children: /* @__PURE__ */ jsxs("div", { style: { ...card, position: "relative" }, children: [
715
+ isMobile && /* @__PURE__ */ jsx("div", { style: handle }),
716
+ /* @__PURE__ */ jsx("button", { className: "cavos-close", style: close, onClick: handleClose, "aria-label": "Close", children: /* @__PURE__ */ jsx(CloseX, {}) }),
717
+ /* @__PURE__ */ jsxs("div", { style: { padding: isMobile ? "24px 20px 32px" : "40px 24px 24px" }, children: [
718
+ /* @__PURE__ */ jsx("h2", { style: { margin: "0 0 22px", fontSize: "17px", fontWeight: 600, color: textColor, letterSpacing: "-0.02em", textAlign: "center" }, children: appName ? `Sign in to ${appName}` : "Log in or sign up" }),
719
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "10px" }, children: [
720
+ showGoogle && /* @__PURE__ */ jsxs("button", { className: "cavos-provider", style: { ...pBtn, ...busy ? { opacity: 0.55, cursor: "not-allowed" } : {} }, onClick: () => handleOAuth("google"), disabled: busy, children: [
721
+ btnIcon(/* @__PURE__ */ jsx(GoogleIcon, {}), /* @__PURE__ */ jsx(Spinner, { size: 14, color: "#888" }), "#4285F4"),
722
+ /* @__PURE__ */ jsx("span", { children: "Continue with Google" })
723
+ ] }),
724
+ showApple && /* @__PURE__ */ jsxs("button", { className: "cavos-provider", style: { ...pBtn, ...busy ? { opacity: 0.55, cursor: "not-allowed" } : {} }, onClick: () => handleOAuth("apple"), disabled: busy, children: [
725
+ btnIcon(/* @__PURE__ */ jsx(AppleIcon, {}), /* @__PURE__ */ jsx(Spinner, { size: 14, color: isLight ? "#111" : "#fff" }), isLight ? "#111" : "#fff"),
726
+ /* @__PURE__ */ jsx("span", { children: "Continue with Apple" })
727
+ ] }),
728
+ showEmail && hasSocial && /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: "12px", margin: "6px 0 2px" }, children: [
729
+ /* @__PURE__ */ jsx("span", { className: "cavos-divider-line", style: { background: isLight ? "rgba(0,0,0,0.08)" : "rgba(255,255,255,0.08)" } }),
730
+ /* @__PURE__ */ jsx("span", { style: { fontSize: "12px", color: subTextColor, textTransform: "uppercase", letterSpacing: "0.05em" }, children: "or" }),
731
+ /* @__PURE__ */ jsx("span", { className: "cavos-divider-line", style: { background: isLight ? "rgba(0,0,0,0.08)" : "rgba(255,255,255,0.08)" } })
732
+ ] }),
733
+ showEmail && /* @__PURE__ */ jsxs("button", { className: "cavos-provider", style: { ...pBtn, cursor: busy ? "not-allowed" : "pointer" }, onClick: () => setScreen("magic-link"), disabled: busy, children: [
734
+ btnIcon(/* @__PURE__ */ jsx(EmailIcon, {}), /* @__PURE__ */ jsx(Spinner, { size: 14, color: subTextColor }), subTextColor),
735
+ /* @__PURE__ */ jsx("span", { children: "Continue with email" })
736
+ ] })
737
+ ] }),
738
+ error && /* @__PURE__ */ jsx("div", { style: { marginTop: "14px", background: errBg, border: `1px solid ${errBorder}`, borderRadius: "10px", padding: "9px 13px", fontSize: "13px", color: errColor }, children: error }),
739
+ /* @__PURE__ */ jsxs("p", { style: { margin: "18px 0 0", fontSize: "11px", color: subTextColor, textAlign: "center", lineHeight: 1.55 }, children: [
740
+ "By continuing you agree to the",
741
+ " ",
742
+ /* @__PURE__ */ jsx("a", { href: "https://cavos.xyz/user-privacy", target: "_blank", rel: "noopener noreferrer", style: { color: isLight ? "rgba(0,0,0,0.45)" : "rgba(255,255,255,0.45)", textDecoration: "underline" }, children: "Privacy Policy" }),
743
+ " & ",
744
+ /* @__PURE__ */ jsx("a", { href: "https://cavos.xyz/user-terms", target: "_blank", rel: "noopener noreferrer", style: { color: isLight ? "rgba(0,0,0,0.45)" : "rgba(255,255,255,0.45)", textDecoration: "underline" }, children: "Terms" }),
745
+ "."
746
+ ] })
747
+ ] }),
748
+ /* @__PURE__ */ jsxs("div", { style: footer, children: [
749
+ /* @__PURE__ */ jsx(CavosLogo, { invert: !isLight }),
750
+ /* @__PURE__ */ jsx("span", { children: "Secured by Cavos" })
751
+ ] })
752
+ ] }) });
753
+ }
754
+ function useCavosAuth() {
755
+ const { openModal, closeModal, isAuthenticated, address, user, walletStatus, logout } = useCavos();
756
+ return { openModal, closeModal, isAuthenticated, address, user, walletStatus, logout };
757
+ }
758
+ var CavosContext = createContext(null);
759
+ var INITIAL_STATUS = {
760
+ isDeploying: false,
761
+ isReady: false,
762
+ needsDeviceApproval: false,
763
+ awaitingApproval: false,
764
+ pendingRequestId: null
765
+ };
766
+ function CavosProvider({ config, modal, children }) {
767
+ const [auth] = useState(
768
+ () => new CavosAuth({ appId: config.appId, backendUrl: config.authBackendUrl })
769
+ );
770
+ const [cavos, setCavos] = useState(null);
771
+ const [identity, setIdentity] = useState(null);
772
+ const [walletStatus, setWalletStatus] = useState(INITIAL_STATUS);
773
+ const [isLoading, setIsLoading] = useState(false);
774
+ const [authError, setAuthError] = useState(null);
775
+ const [modalOpen, setModalOpen] = useState(false);
776
+ const [branding, setBranding] = useState({});
777
+ const configRef = useRef(config);
778
+ useEffect(() => {
779
+ configRef.current = config;
780
+ }, [config]);
781
+ useEffect(() => {
782
+ if (!config.appId || typeof window === "undefined") return;
783
+ const base = config.authBackendUrl ?? "https://cavos.xyz";
784
+ fetch(`${base}/api/oauth/firebase/app-branding?app_id=${encodeURIComponent(config.appId)}`).then((r) => r.ok ? r.json() : null).then((d) => {
785
+ if (d?.name) setBranding((b) => ({ ...b, appName: d.name }));
786
+ if (d?.logo_url) setBranding((b) => ({ ...b, appLogo: d.logo_url }));
787
+ }).catch(() => {
788
+ });
789
+ }, [config.appId, config.authBackendUrl]);
790
+ const openModal = useCallback(() => setModalOpen(true), []);
791
+ const closeModal = useCallback(() => setModalOpen(false), []);
792
+ const clearAuthError = useCallback(() => setAuthError(null), []);
793
+ const resendDeviceApproval = useCallback(async () => {
794
+ if (!identity || !cavos || !cavos.pendingRequestId) return;
795
+ const backendUrl = configRef.current.authBackendUrl ?? "https://cavos.xyz";
796
+ if (!configRef.current.appId) return;
797
+ const recovery = new HttpRecoveryClient({ baseUrl: backendUrl, appId: configRef.current.appId });
798
+ await recovery.requestDeviceAddition({
799
+ userId: identity.userId,
800
+ accountAddress: cavos.address,
801
+ newSigner: cavos.publicKey,
802
+ ...identity.email ? { email: identity.email } : {}
803
+ });
804
+ }, [identity, cavos]);
805
+ const connect = useCallback(async (id) => {
806
+ setWalletStatus({ ...INITIAL_STATUS, isDeploying: true });
807
+ const c = await Cavos.connect({
808
+ network: configRef.current.network,
809
+ identity: id,
810
+ appSalt: configRef.current.appSalt,
811
+ paymasterApiKey: configRef.current.paymasterApiKey,
812
+ ...configRef.current.appId ? { appId: configRef.current.appId } : {},
813
+ ...configRef.current.authBackendUrl ? { backendUrl: configRef.current.authBackendUrl } : {},
814
+ ...configRef.current.rpcUrl ? { rpcUrl: configRef.current.rpcUrl } : {}
815
+ });
816
+ setCavos(c);
817
+ setIdentity(id);
818
+ setWalletStatus({
819
+ isDeploying: false,
820
+ isReady: c.status === "ready",
821
+ needsDeviceApproval: c.status === "needs-device-approval",
822
+ awaitingApproval: c.status === "needs-device-approval" && !!c.pendingRequestId,
823
+ pendingRequestId: c.pendingRequestId
824
+ });
825
+ modal?.onSuccess?.(c.address);
826
+ return c;
827
+ }, [modal]);
828
+ useEffect(() => {
829
+ if (typeof window === "undefined") return;
830
+ const params = new URLSearchParams(window.location.search);
831
+ const authData = params.get("auth_data") || params.get("zk_auth_data");
832
+ if (!authData) return;
833
+ setModalOpen(true);
834
+ setWalletStatus({ ...INITIAL_STATUS, isDeploying: true });
835
+ let cancelled = false;
836
+ (async () => {
837
+ setIsLoading(true);
838
+ try {
839
+ await handleCallback(authData);
840
+ if (!cancelled) window.history.replaceState({}, document.title, window.location.pathname);
841
+ } catch (e) {
842
+ console.error("[CavosProvider] OAuth callback error:", e);
843
+ if (!cancelled) {
844
+ const msg = e instanceof Error ? e.message : "Sign-in failed. Please try again.";
845
+ setAuthError(msg);
846
+ setWalletStatus(INITIAL_STATUS);
847
+ }
848
+ } finally {
849
+ if (!cancelled) setIsLoading(false);
850
+ }
851
+ })();
852
+ return () => {
853
+ cancelled = true;
854
+ };
855
+ }, []);
856
+ const handleCallback = useCallback(async (authData) => {
857
+ const id = await auth.handleCallback(authData);
858
+ await connect(id);
859
+ }, [auth, connect]);
860
+ const login = useCallback(async (provider) => {
861
+ if (typeof window === "undefined") throw new Error("OAuth requires a browser");
862
+ setAuthError(null);
863
+ const url = await (provider === "google" ? auth.getGoogleOAuthUrl(window.location.origin + window.location.pathname) : auth.getAppleOAuthUrl(window.location.origin + window.location.pathname));
864
+ window.location.href = url;
865
+ }, [auth]);
866
+ const sendMagicLink = useCallback(async (email) => {
867
+ await auth.sendMagicLink(email);
868
+ }, [auth]);
869
+ const sendOtp = useCallback(async (email) => {
870
+ await auth.sendOtp(email);
871
+ }, [auth]);
872
+ const verifyOtp = useCallback(async (email, code) => {
873
+ setAuthError(null);
874
+ const id = await auth.verifyOtp(email, code);
875
+ await connect(id);
876
+ }, [auth, connect]);
877
+ const execute = useCallback(async (calls) => {
878
+ if (!cavos) throw new Error("Not logged in");
879
+ return cavos.execute(calls);
880
+ }, [cavos]);
881
+ const addSigner = useCallback(
882
+ async (pubkey) => {
883
+ if (!cavos) throw new Error("Not logged in");
884
+ return cavos.addSigner(pubkey);
885
+ },
886
+ [cavos]
887
+ );
888
+ const setupRecovery = useCallback(async () => {
889
+ if (!cavos) throw new Error("Not logged in");
890
+ const code = generateRecoveryCode();
891
+ await cavos.setupRecovery(code);
892
+ return code;
893
+ }, [cavos]);
894
+ const recover = useCallback(async (code) => {
895
+ if (!identity) throw new Error("Sign in first so we know which account to recover.");
896
+ setAuthError(null);
897
+ setWalletStatus({ ...INITIAL_STATUS, isDeploying: true });
898
+ try {
899
+ const c = await Cavos.recover({
900
+ code,
901
+ identity,
902
+ network: configRef.current.network,
903
+ appSalt: configRef.current.appSalt,
904
+ paymasterApiKey: configRef.current.paymasterApiKey,
905
+ ...configRef.current.appId ? { appId: configRef.current.appId } : {},
906
+ ...configRef.current.authBackendUrl ? { backendUrl: configRef.current.authBackendUrl } : {},
907
+ ...configRef.current.rpcUrl ? { rpcUrl: configRef.current.rpcUrl } : {}
908
+ });
909
+ setCavos(c);
910
+ setWalletStatus({ ...INITIAL_STATUS, isReady: true });
911
+ modal?.onSuccess?.(c.address);
912
+ } catch (e) {
913
+ const msg = e instanceof Error ? e.message : "Recovery failed. Check your code and try again.";
914
+ setAuthError(msg);
915
+ setWalletStatus(INITIAL_STATUS);
916
+ throw e;
917
+ }
918
+ }, [identity, modal]);
919
+ useEffect(() => {
920
+ if (!walletStatus.awaitingApproval || !walletStatus.pendingRequestId || !identity) return;
921
+ if (!configRef.current.appId) return;
922
+ const backendUrl = configRef.current.authBackendUrl ?? "https://cavos.xyz";
923
+ const recovery = new HttpRecoveryClient({ baseUrl: backendUrl, appId: configRef.current.appId });
924
+ const requestId = walletStatus.pendingRequestId;
925
+ let cancelled = false;
926
+ const tick = async () => {
927
+ try {
928
+ const r = await recovery.getPendingRequest(requestId);
929
+ if (cancelled || !r) return;
930
+ if (r.status === "expired") {
931
+ setWalletStatus((s) => ({ ...s, pendingRequestId: null }));
932
+ return;
933
+ }
934
+ if (r.status === "approved") {
935
+ await connect(identity);
936
+ }
937
+ } catch {
938
+ }
939
+ };
940
+ const interval = setInterval(tick, 4e3);
941
+ return () => {
942
+ cancelled = true;
943
+ clearInterval(interval);
944
+ };
945
+ }, [walletStatus.awaitingApproval, walletStatus.pendingRequestId, identity, connect]);
946
+ const logout = useCallback(() => {
947
+ setCavos(null);
948
+ setIdentity(null);
949
+ setWalletStatus(INITIAL_STATUS);
950
+ setAuthError(null);
951
+ }, []);
952
+ const value = {
953
+ openModal,
954
+ closeModal,
955
+ isAuthenticated: !!cavos,
956
+ user: identity ? { userId: identity.userId, email: identity.email, provider: identity.provider } : null,
957
+ address: cavos?.address ?? null,
958
+ walletStatus,
959
+ isLoading,
960
+ authError,
961
+ clearAuthError,
962
+ login,
963
+ sendMagicLink,
964
+ sendOtp,
965
+ verifyOtp,
966
+ handleCallback,
967
+ execute,
968
+ addSigner,
969
+ resendDeviceApproval,
970
+ setupRecovery,
971
+ recover,
972
+ logout
973
+ };
974
+ return /* @__PURE__ */ jsxs(CavosContext.Provider, { value, children: [
975
+ children,
976
+ modal !== void 0 && /* @__PURE__ */ jsx(
977
+ CavosAuthModal,
978
+ {
979
+ open: modalOpen,
980
+ onClose: closeModal,
981
+ appName: branding.appName ?? modal.appName,
982
+ appLogo: branding.appLogo ?? modal.appLogo,
983
+ providers: modal.providers,
984
+ emailMode: modal.emailMode,
985
+ primaryColor: modal.primaryColor,
986
+ theme: modal.theme
987
+ }
988
+ )
989
+ ] });
990
+ }
991
+ function useCavos() {
992
+ const ctx = useContext(CavosContext);
993
+ if (!ctx) throw new Error("useCavos must be used within a CavosProvider");
994
+ return ctx;
995
+ }
996
+
997
+ export { CavosAuthModal, CavosProvider, useCavos, useCavosAuth };
998
+ //# sourceMappingURL=index.mjs.map
999
+ //# sourceMappingURL=index.mjs.map