@seamless-auth/react 0.0.10 → 0.2.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/CHANGELOG.md +15 -0
- package/README.md +422 -54
- package/dist/AuthProvider.d.ts +20 -29
- package/dist/client/createSeamlessAuthClient.d.ts +171 -0
- package/dist/client/webauthnPrf.d.ts +27 -0
- package/dist/components/AuthFallbackOptions.d.ts +4 -1
- package/dist/fetchWithAuth.d.ts +0 -2
- package/dist/hooks/useAuthClient.d.ts +1 -0
- package/dist/hooks/usePasskeySupport.d.ts +4 -0
- package/dist/index.d.ts +9 -3
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/scopedRoles.d.ts +2 -0
- package/dist/types.d.ts +43 -0
- package/package.json +13 -4
- package/dist/context/InternalAuthContext.d.ts +0 -11
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { Credential, Organization, OrganizationMembership, User } from '../types';
|
|
2
|
+
import { PasskeyPrfInput, PasskeyPrfResult } from './webauthnPrf';
|
|
3
|
+
export interface SeamlessAuthClientOptions {
|
|
4
|
+
apiHost: string;
|
|
5
|
+
}
|
|
6
|
+
export interface LoginInput {
|
|
7
|
+
identifier: string;
|
|
8
|
+
passkeyAvailable: boolean;
|
|
9
|
+
}
|
|
10
|
+
export type LoginMethod = 'passkey' | 'magic_link' | 'email_otp' | 'phone_otp' | 'oauth';
|
|
11
|
+
export interface LoginStartResult {
|
|
12
|
+
message?: string;
|
|
13
|
+
identifierType?: 'email' | 'phone';
|
|
14
|
+
loginMethods?: LoginMethod[];
|
|
15
|
+
}
|
|
16
|
+
export interface RegisterInput {
|
|
17
|
+
email: string;
|
|
18
|
+
phone: string;
|
|
19
|
+
bootstrapToken?: string | null;
|
|
20
|
+
}
|
|
21
|
+
export interface PasskeyMetadata {
|
|
22
|
+
friendlyName: string;
|
|
23
|
+
platform: string;
|
|
24
|
+
browser: string;
|
|
25
|
+
deviceInfo: string;
|
|
26
|
+
}
|
|
27
|
+
export interface CurrentUserResult {
|
|
28
|
+
user: User;
|
|
29
|
+
credentials: Credential[];
|
|
30
|
+
organizations?: Organization[];
|
|
31
|
+
activeOrganization?: Organization | null;
|
|
32
|
+
}
|
|
33
|
+
export interface CreateOrganizationInput {
|
|
34
|
+
name: string;
|
|
35
|
+
slug?: string;
|
|
36
|
+
metadata?: Record<string, unknown> | null;
|
|
37
|
+
}
|
|
38
|
+
export interface UpdateOrganizationInput {
|
|
39
|
+
name?: string;
|
|
40
|
+
slug?: string;
|
|
41
|
+
metadata?: Record<string, unknown> | null;
|
|
42
|
+
}
|
|
43
|
+
export interface OrganizationMemberInput {
|
|
44
|
+
userId?: string;
|
|
45
|
+
email?: string;
|
|
46
|
+
roles?: string[];
|
|
47
|
+
scopes?: string[];
|
|
48
|
+
}
|
|
49
|
+
export interface OrganizationMemberUpdateInput {
|
|
50
|
+
roles?: string[];
|
|
51
|
+
scopes?: string[];
|
|
52
|
+
}
|
|
53
|
+
export interface OrganizationsResult {
|
|
54
|
+
organizations: Organization[];
|
|
55
|
+
activeOrganizationId?: string | null;
|
|
56
|
+
}
|
|
57
|
+
export interface OrganizationResult {
|
|
58
|
+
organization: Organization;
|
|
59
|
+
}
|
|
60
|
+
export interface OrganizationMembersResult {
|
|
61
|
+
members: OrganizationMembership[];
|
|
62
|
+
total: number;
|
|
63
|
+
}
|
|
64
|
+
export interface OAuthProvider {
|
|
65
|
+
id: string;
|
|
66
|
+
name: string;
|
|
67
|
+
scopes: string[];
|
|
68
|
+
}
|
|
69
|
+
export interface OAuthProvidersResult {
|
|
70
|
+
providers: OAuthProvider[];
|
|
71
|
+
}
|
|
72
|
+
export interface StartOAuthLoginInput {
|
|
73
|
+
providerId: string;
|
|
74
|
+
redirectUri?: string;
|
|
75
|
+
returnTo?: string;
|
|
76
|
+
}
|
|
77
|
+
export interface StartOAuthLoginResult {
|
|
78
|
+
provider: OAuthProvider;
|
|
79
|
+
state: string;
|
|
80
|
+
authorizationUrl: string;
|
|
81
|
+
}
|
|
82
|
+
export interface FinishOAuthLoginInput {
|
|
83
|
+
providerId: string;
|
|
84
|
+
code: string;
|
|
85
|
+
state: string;
|
|
86
|
+
}
|
|
87
|
+
export interface PasskeyLoginResult {
|
|
88
|
+
success: boolean;
|
|
89
|
+
mfaRequired: boolean;
|
|
90
|
+
message: string;
|
|
91
|
+
}
|
|
92
|
+
export interface PasskeyRegistrationResult {
|
|
93
|
+
success: boolean;
|
|
94
|
+
message: string;
|
|
95
|
+
credentialId?: string;
|
|
96
|
+
prfCapable?: boolean;
|
|
97
|
+
}
|
|
98
|
+
export interface RegisterPasskeyOptions {
|
|
99
|
+
metadata: PasskeyMetadata;
|
|
100
|
+
requestPrf?: boolean;
|
|
101
|
+
requirePrf?: boolean;
|
|
102
|
+
}
|
|
103
|
+
export type StepUpMethod = 'webauthn';
|
|
104
|
+
export interface StepUpStatus {
|
|
105
|
+
fresh: boolean;
|
|
106
|
+
method: StepUpMethod | null;
|
|
107
|
+
verifiedAt: string | null;
|
|
108
|
+
expiresAt: string | null;
|
|
109
|
+
maxAgeSeconds: number;
|
|
110
|
+
}
|
|
111
|
+
export interface StepUpVerificationResult extends StepUpStatus {
|
|
112
|
+
success: boolean;
|
|
113
|
+
message: string;
|
|
114
|
+
}
|
|
115
|
+
export interface PasskeyLoginOptions {
|
|
116
|
+
prf?: PasskeyPrfInput;
|
|
117
|
+
}
|
|
118
|
+
export interface PasskeyLoginWithPrfResult extends PasskeyLoginResult {
|
|
119
|
+
prf?: PasskeyPrfResult;
|
|
120
|
+
}
|
|
121
|
+
export interface StepUpWithPasskeyPrfResult extends StepUpVerificationResult {
|
|
122
|
+
credentialId: string | null;
|
|
123
|
+
prf: PasskeyPrfResult | null;
|
|
124
|
+
}
|
|
125
|
+
export type LogoutScope = 'current_session' | 'all_sessions';
|
|
126
|
+
export interface LogoutOptions {
|
|
127
|
+
scope?: LogoutScope;
|
|
128
|
+
}
|
|
129
|
+
export interface SeamlessAuthClient {
|
|
130
|
+
getCurrentUser: () => Promise<Response>;
|
|
131
|
+
login: (input: LoginInput) => Promise<Response>;
|
|
132
|
+
loginWithPasskey: (options?: PasskeyLoginOptions) => Promise<PasskeyLoginWithPrfResult>;
|
|
133
|
+
logout: (options?: LogoutOptions) => Promise<Response>;
|
|
134
|
+
logoutAllSessions: () => Promise<Response>;
|
|
135
|
+
deleteUser: () => Promise<Response>;
|
|
136
|
+
register: (input: RegisterInput) => Promise<Response>;
|
|
137
|
+
requestPhoneOtp: () => Promise<Response>;
|
|
138
|
+
verifyPhoneOtp: (verificationToken: string) => Promise<Response>;
|
|
139
|
+
requestLoginPhoneOtp: () => Promise<Response>;
|
|
140
|
+
verifyLoginPhoneOtp: (verificationToken: string) => Promise<Response>;
|
|
141
|
+
requestEmailOtp: () => Promise<Response>;
|
|
142
|
+
verifyEmailOtp: (verificationToken: string) => Promise<Response>;
|
|
143
|
+
requestLoginEmailOtp: () => Promise<Response>;
|
|
144
|
+
verifyLoginEmailOtp: (verificationToken: string) => Promise<Response>;
|
|
145
|
+
requestMagicLink: () => Promise<Response>;
|
|
146
|
+
checkMagicLink: () => Promise<Response>;
|
|
147
|
+
verifyMagicLink: (token: string) => Promise<Response>;
|
|
148
|
+
listOAuthProviders: () => Promise<OAuthProvidersResult>;
|
|
149
|
+
startOAuthLogin: (input: StartOAuthLoginInput) => Promise<StartOAuthLoginResult>;
|
|
150
|
+
finishOAuthLogin: (input: FinishOAuthLoginInput) => Promise<Response>;
|
|
151
|
+
registerPasskey: (input: PasskeyMetadata | RegisterPasskeyOptions) => Promise<PasskeyRegistrationResult>;
|
|
152
|
+
isPasskeyPrfSupported: () => Promise<boolean>;
|
|
153
|
+
getStepUpStatus: () => Promise<Response>;
|
|
154
|
+
verifyStepUpWithPasskey: () => Promise<StepUpVerificationResult>;
|
|
155
|
+
verifyStepUpWithPasskeyPrf: (input: PasskeyPrfInput) => Promise<StepUpWithPasskeyPrfResult>;
|
|
156
|
+
updateCredential: (input: {
|
|
157
|
+
id: string;
|
|
158
|
+
friendlyName: string | null;
|
|
159
|
+
}) => Promise<Response>;
|
|
160
|
+
deleteCredential: (id: string) => Promise<Response>;
|
|
161
|
+
listOrganizations: () => Promise<Response>;
|
|
162
|
+
createOrganization: (input: CreateOrganizationInput) => Promise<Response>;
|
|
163
|
+
getOrganization: (organizationId: string) => Promise<Response>;
|
|
164
|
+
updateOrganization: (organizationId: string, input: UpdateOrganizationInput) => Promise<Response>;
|
|
165
|
+
switchOrganization: (organizationId: string) => Promise<Response>;
|
|
166
|
+
listOrganizationMembers: (organizationId: string) => Promise<Response>;
|
|
167
|
+
addOrganizationMember: (organizationId: string, input: OrganizationMemberInput) => Promise<Response>;
|
|
168
|
+
updateOrganizationMember: (organizationId: string, userId: string, input: OrganizationMemberUpdateInput) => Promise<Response>;
|
|
169
|
+
removeOrganizationMember: (organizationId: string, userId: string) => Promise<Response>;
|
|
170
|
+
}
|
|
171
|
+
export declare const createSeamlessAuthClient: (opts: SeamlessAuthClientOptions) => SeamlessAuthClient;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type AuthenticationResponseJSON, type PublicKeyCredentialRequestOptionsJSON } from '@simplewebauthn/browser';
|
|
2
|
+
export type PasskeyPrfSalt = ArrayBuffer | ArrayBufferView | string;
|
|
3
|
+
export interface PasskeyPrfInput {
|
|
4
|
+
salt: PasskeyPrfSalt;
|
|
5
|
+
secondSalt?: PasskeyPrfSalt;
|
|
6
|
+
credentialId?: string;
|
|
7
|
+
}
|
|
8
|
+
export interface PasskeyPrfResult {
|
|
9
|
+
credentialId: string;
|
|
10
|
+
output: Uint8Array;
|
|
11
|
+
outputBase64url: string;
|
|
12
|
+
}
|
|
13
|
+
export declare function encodePrfSalt(salt: PasskeyPrfSalt): string;
|
|
14
|
+
export declare function createPrfRequestBody(input: PasskeyPrfInput): {
|
|
15
|
+
prf: {
|
|
16
|
+
secondSalt?: string | undefined;
|
|
17
|
+
salt: string;
|
|
18
|
+
};
|
|
19
|
+
credentialId?: string | undefined;
|
|
20
|
+
};
|
|
21
|
+
export declare function isPasskeyPrfSupported(): Promise<boolean>;
|
|
22
|
+
export declare function preparePrfRequestOptions(optionsJSON: PublicKeyCredentialRequestOptionsJSON): PublicKeyCredentialRequestOptionsJSON;
|
|
23
|
+
export declare function extractPasskeyPrfResult(credential: AuthenticationResponseJSON): PasskeyPrfResult | null;
|
|
24
|
+
export declare function stripPrfResultsFromAssertion(credential: AuthenticationResponseJSON): AuthenticationResponseJSON;
|
|
25
|
+
export declare function getRegistrationPrfCapable(attestationResponse: {
|
|
26
|
+
clientExtensionResults?: unknown;
|
|
27
|
+
}): boolean;
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
import type { LoginMethod } from '@/client/createSeamlessAuthClient';
|
|
2
3
|
interface AuthFallbackOptionsProps {
|
|
3
4
|
identifier: string;
|
|
4
5
|
onMagicLink: () => void;
|
|
6
|
+
onEmailOtp?: () => void;
|
|
5
7
|
onPhoneOtp: () => void;
|
|
6
|
-
onPasskeyRetry
|
|
8
|
+
onPasskeyRetry?: () => void;
|
|
9
|
+
loginMethods?: LoginMethod[];
|
|
7
10
|
}
|
|
8
11
|
declare const AuthFallbackOptions: React.FC<AuthFallbackOptionsProps>;
|
|
9
12
|
export default AuthFallbackOptions;
|
package/dist/fetchWithAuth.d.ts
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const useAuthClient: () => import("@/client/createSeamlessAuthClient").SeamlessAuthClient;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import { AuthContextType, AuthProvider, useAuth
|
|
1
|
+
import { AuthContextType, AuthProvider, useAuth } from '@/AuthProvider';
|
|
2
2
|
import { AuthRoutes } from '@/AuthRoutes';
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
import { createSeamlessAuthClient, CreateOrganizationInput, CurrentUserResult, FinishOAuthLoginInput, LoginInput, LoginMethod, LoginStartResult, OAuthProvider, OAuthProvidersResult, OrganizationMemberInput, OrganizationMemberUpdateInput, OrganizationMembersResult, OrganizationResult, OrganizationsResult, PasskeyLoginResult, PasskeyLoginWithPrfResult, PasskeyMetadata, PasskeyRegistrationResult, RegisterInput, RegisterPasskeyOptions, SeamlessAuthClient, SeamlessAuthClientOptions, StartOAuthLoginInput, StartOAuthLoginResult, StepUpMethod, StepUpStatus, StepUpWithPasskeyPrfResult, StepUpVerificationResult, UpdateOrganizationInput } from '@/client/createSeamlessAuthClient';
|
|
4
|
+
import { encodePrfSalt, extractPasskeyPrfResult, isPasskeyPrfSupported, PasskeyPrfInput, PasskeyPrfResult } from '@/client/webauthnPrf';
|
|
5
|
+
import { useAuthClient } from '@/hooks/useAuthClient';
|
|
6
|
+
import { usePasskeySupport } from '@/hooks/usePasskeySupport';
|
|
7
|
+
import { hasScopedRole, roleGrantsAccess } from '@/scopedRoles';
|
|
8
|
+
import { Credential, Organization, OrganizationMembership, User } from '@/types';
|
|
9
|
+
export { AuthProvider, AuthRoutes, createSeamlessAuthClient, encodePrfSalt, extractPasskeyPrfResult, hasScopedRole, isPasskeyPrfSupported, roleGrantsAccess, useAuth, useAuthClient, usePasskeySupport, };
|
|
10
|
+
export type { AuthContextType, Credential, CreateOrganizationInput, CurrentUserResult, FinishOAuthLoginInput, LoginInput, LoginMethod, LoginStartResult, OAuthProvider, OAuthProvidersResult, Organization, OrganizationMemberInput, OrganizationMembership, OrganizationMemberUpdateInput, OrganizationMembersResult, OrganizationResult, OrganizationsResult, PasskeyLoginWithPrfResult, PasskeyLoginResult, PasskeyMetadata, PasskeyPrfInput, PasskeyPrfResult, PasskeyRegistrationResult, RegisterInput, RegisterPasskeyOptions, SeamlessAuthClient, SeamlessAuthClientOptions, StartOAuthLoginInput, StartOAuthLoginResult, StepUpMethod, StepUpStatus, StepUpWithPasskeyPrfResult, StepUpVerificationResult, UpdateOrganizationInput, User, };
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{jsx as e,jsxs as o,Fragment as n}from"react/jsx-runtime";import{createContext as i,useContext as r,useState as t,useEffect as a,useCallback as l,useRef as s}from"react";import{useNavigate as d,useSearchParams as c,useLocation as _,Routes as m,Route as u,Navigate as g}from"react-router-dom";import{startAuthentication as p,startRegistration as h,WebAuthnError as f}from"@simplewebauthn/browser";import y,{AsYouType as b,parsePhoneNumberFromString as k}from"libphonenumber-js";const v=i(void 0),x=({value:o,children:n})=>e(v.Provider,{value:o,children:n}),w=()=>{const e=r(v);if(!e)throw new Error("useInternalAuth must be used within InternalAuthProvider");return e},N=e=>{const{authMode:o,authHost:n}=e;return async function(e,i){const r=`${n}${"server"===o?"auth":""}${e.startsWith("/")?e:`/${e}`}`,t={...i,credentials:"include",headers:{"Content-Type":"application/json",...i?.headers}},a=await fetch(r,t);if(a.ok)return a;throw console.warn("Auth fetch failed:",a.status,r),new Error(`Failed to make API call to ${r}`)}};const P=i(void 0),C=()=>{const e=r(P);if(!e)throw new Error("useAuth must be used within an AuthProvider");return e},T=({children:o,apiHost:n,autoDetectPreviousSignin:i=!0,mode:r="web"})=>{const[s,d]=t(null),[c,_]=t([]),[m,u]=t(!1),[g,p]=t(!0),[h,f]=t(null),{hasSignedInBefore:y,markSignedIn:b}=function(e="seamlessauth_seen"){const[o,n]=t(!1);return a(()=>{try{"true"===localStorage.getItem(e)&&n(!0)}catch{}},[e]),{hasSignedInBefore:o,markSignedIn:()=>{try{localStorage.setItem(e,"true"),n(!0)}catch{}}}}(),[k]=t(r),v=N({authMode:k,authHost:n}),w=l(async()=>{if(s)try{await v("/logout",{method:"GET"})}catch{console.error("Error during logout")}finally{u(!1),d(null),f(null)}},[v,s]),C=async()=>{p(!0);try{const e=await v("users/me",{method:"GET"});if(e.ok){const{user:o,credentials:n}=await e.json();d(o),_(n),u(!0)}else w()}catch{w()}finally{p(!1)}};return a(()=>{C()},[]),a(()=>{s&&m&&b()},[s,m,b]),e(P.Provider,{value:{user:s,logout:w,loading:g,deleteUser:async()=>{try{if((await v("/users/delete",{method:"delete"})).ok)return d(null),u(!1),void f(null);throw new Error("Could not delete user.")}catch(e){throw console.error("Something went wrong deleting user:",e),new Error("Could not delete user.")}},isAuthenticated:m,hasRole:e=>s?.roles?.includes(e),apiHost:n,token:h,markSignedIn:b,hasSignedInBefore:!!i&&y,mode:r,credentials:c,updateCredential:async e=>{const o=await v("users/credentials",{method:"POST",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify({friendlyName:e.friendlyName,id:e.id})});if(o.ok)return o.json();throw new Error("Failed to update credential")},deleteCredential:async e=>{const o=await v("users/credentials",{method:"DELETE",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify({id:e})});if(o.ok)return o.json();throw new Error("Failed to update credential")}},children:e(x,{value:{validateToken:C,setLoading:p},children:o})})};function M(e,o){void 0===o&&(o={});var n=o.insertAt;if(e&&"undefined"!=typeof document){var i=document.head||document.getElementsByTagName("head")[0],r=document.createElement("style");r.type="text/css","top"===n&&i.firstChild?i.insertBefore(r,i.firstChild):i.appendChild(r),r.styleSheet?r.styleSheet.cssText=e:r.appendChild(document.createTextNode(e))}}var S="login-module__container___YggDx",I="login-module__card___Ub-Py",O="login-module__heading___neEqb",E="login-module__inputGroup___P6qgS",A="login-module__label___mx5vu",j="login-module__input___U07lW",B="login-module__helperText___kDQ4-",z="login-module__error___40zxh",F="login-module__button___0kFBs",G="login-module__toggle___1JiG1",L="login-module__underline___gs-RS",V="login-module__phoneRow___oeNtq",D="login-module__select___rRV1O",H="login-module__phoneInput___2MPQC",R="login-module__fallbackCard___HdIk-",U="login-module__fallbackHeader___-il2v",q="login-module__fallbackDescription___ea5EB",K="login-module__fallbackActions___AD3ni",J="login-module__fallbackActionButton___lFgWf",W="login-module__actionTitle___ycrMp",$="login-module__actionSubtext___opaIV",Y="login-module__linkButton___5lsoe";M(".login-module__container___YggDx{align-items:center;color:#fff;display:flex;justify-content:center}.login-module__card___Ub-Py{background-color:#1f2937;border-radius:.5rem;box-shadow:0 4px 6px rgba(0,0,0,.1);max-width:28rem;padding:2rem;width:100%}.login-module__heading___neEqb{color:#fff;font-size:1.5rem;font-weight:700;margin-bottom:1.5rem;text-align:center}.login-module__message___qSejT{color:#68d391;text-align:center}.login-module__inputGroup___P6qgS{margin-bottom:1rem}.login-module__label___mx5vu{color:#d1d5db;display:block}.login-module__input___U07lW{background-color:#4b5563;border:1px solid #d1d5db;border-radius:.375rem;margin-top:.25rem;padding:.5rem;width:100%}.login-module__input___U07lW:focus{box-shadow:0 0 0 2px #3b82f6;outline:none}.login-module__helperText___kDQ4-{color:#9ca3af;font-size:.75rem;margin-top:.5rem}.login-module__error___40zxh{color:#f87171;font-size:.875rem}.login-module__button___0kFBs{background-color:#2563eb;border-radius:.375rem;color:#fff;cursor:pointer;margin-top:1rem;padding:.5rem;transition:background-color .3s;width:100%}.login-module__button___0kFBs:hover{background-color:#1d4ed8}.login-module__button___0kFBs:disabled{background-color:#9ca3af;cursor:not-allowed}.login-module__toggle___1JiG1{background:none;border:none;color:#60a5fa;cursor:pointer;font-size:.875rem;margin-top:1.5rem;text-align:center;width:100%}.login-module__underline___gs-RS{text-decoration:underline}.login-module__phoneRow___oeNtq{display:grid;gap:.5rem;grid-template-columns:1fr 3fr;margin-top:.25rem}.login-module__phoneInput___2MPQC,.login-module__select___rRV1O{background-color:#4b5563;border:1px solid #d1d5db;border-radius:.375rem;padding:.5rem;width:100%}@media (max-width:500px){.login-module__phoneRow___oeNtq{grid-template-columns:1fr}}.login-module__fallbackCard___HdIk-{background:hsla(0,0%,100%,.04);border:1px solid hsla(0,0%,100%,.08);border-radius:12px;display:flex;flex-direction:column;gap:14px;margin-top:18px;padding:18px}.login-module__fallbackHeader___-il2v{color:#f3f4f6;font-size:.95rem;font-weight:600}.login-module__fallbackDescription___ea5EB{color:#9ca3af;font-size:.85rem;line-height:1.4}.login-module__fallbackActions___AD3ni{display:flex;flex-direction:column;gap:10px}.login-module__fallbackActionButton___lFgWf{background:rgba(0,0,0,.25);border:1px solid hsla(0,0%,100%,.08);border-radius:8px;cursor:pointer;display:flex;flex-direction:column;padding:12px 14px;text-align:left;transition:all .15s ease}.login-module__fallbackActionButton___lFgWf:hover{background:hsla(0,0%,100%,.06);border-color:hsla(0,0%,100%,.15)}.login-module__actionTitle___ycrMp{color:#f9fafb;font-size:.9rem;font-weight:500}.login-module__actionSubtext___opaIV{color:#9ca3af;font-size:.75rem;margin-top:2px}.login-module__linkButton___5lsoe{background:none;border:none;color:#60a5fa;cursor:pointer;font-size:.8rem;margin-top:6px}.login-module__linkButton___5lsoe:hover{text-decoration:underline}");var Z="termsModal-module__overlay___-j6r5",Q="termsModal-module__modal___4PxZV",X="termsModal-module__header___B7wxb",ee="termsModal-module__title___Sucwt",oe="termsModal-module__closeBtn___evIs5",ne="termsModal-module__content___5BDhN",ie="termsModal-module__link___oPZrU";M(".termsModal-module__overlay___-j6r5{align-items:center;background-color:rgba(0,0,0,.7);display:flex;inset:0;justify-content:center;position:fixed;z-index:999}.termsModal-module__modal___4PxZV{background-color:#1a1a1a;border-radius:8px;box-shadow:0 10px 25px rgba(0,0,0,.4);color:#fff;max-height:80vh;max-width:640px;outline:none;overflow-y:auto;padding:24px;width:100%}.termsModal-module__header___B7wxb{align-items:center;display:flex;justify-content:space-between;margin-bottom:16px}.termsModal-module__title___Sucwt{color:#60a5fa;font-size:1.25rem;font-weight:700}.termsModal-module__closeBtn___evIs5{background:none;border:none;color:#ccc;cursor:pointer;font-size:1.75rem}.termsModal-module__closeBtn___evIs5:hover{color:#fff}.termsModal-module__content___5BDhN{color:#d1d5db;font-size:.9rem;line-height:1.6}.termsModal-module__link___oPZrU{color:#60a5fa;text-decoration:underline}.termsModal-module__link___oPZrU:hover{text-decoration:none}");const re=({isOpen:n,onClose:i})=>{const r=s(null);return a(()=>{const e=e=>{"Escape"===e.key&&i()};return n&&(document.addEventListener("keydown",e),r.current?.focus()),()=>{document.removeEventListener("keydown",e)}},[n,i]),n?e("div",{className:Z,role:"dialog","aria-modal":"true","aria-labelledby":"terms-title",children:o("div",{className:Q,tabIndex:-1,ref:r,children:[o("div",{className:X,children:[e("h2",{id:"terms-title",className:ee,children:"SMS Terms & Conditions"}),e("button",{onClick:i,className:oe,children:"×"})]}),o("div",{className:ne,children:[o("p",{children:[e("strong",{children:"Effective Date:"})," June 01, 2025"]}),e("p",{children:"By providing your phone number to SeamlessAuth, a Fells Code LLC product, you agree to receive SMS messages for identity verification, authentication, and account security."}),o("p",{children:[e("strong",{children:"1. Purpose:"})," SMS is used only for account security (OTP, MFA). No marketing messages."]}),o("p",{children:[e("strong",{children:"2. Frequency:"})," Based on login and account activity."]}),o("p",{children:[e("strong",{children:"3. Opt-Out:"})," Contact support@seamlessauth.com to opt out."]}),o("p",{children:[e("strong",{children:"4. Fees:"})," Message and data rates may apply."]}),o("p",{children:[e("strong",{children:"5. Supported Carriers:"})," Most major providers supported, delivery not guaranteed."]}),o("p",{children:[e("strong",{children:"6. Privacy:"})," Your phone number is not shared or sold. See our Privacy Policy."]}),o("p",{children:[e("strong",{children:"7. Changes:"})," Terms may be updated with notice on this page."]}),o("p",{children:["Questions? Email us at"," ",e("a",{className:ie,href:"mailto:support@seamlessauth.com",children:"support@seamlessauth.com"}),"."]})]})]})}):null},te=[{code:"US",name:"United States",dialCode:"+1",flag:"🇺🇸"},{code:"CA",name:"Canada",dialCode:"+1",flag:"🇨🇦"},{code:"GB",name:"United Kingdom",dialCode:"+44",flag:"🇬🇧"},{code:"IN",name:"India",dialCode:"+91",flag:"🇮🇳"},{code:"AU",name:"Australia",dialCode:"+61",flag:"🇦🇺"}];function ae({phone:n,setPhone:i,phoneError:r,setPhoneError:l}){const[s,d]=t(!1),[c,_]=t(te[0]);a(()=>{const e=function(){try{const e=Intl.DateTimeFormat().resolvedOptions().locale||"en-US",o=e.split("-")[1]?.toUpperCase()||"US";return te.find(e=>e.code===o)||te[0]}catch{return te[0]}}();_(e)},[]);return o("div",{className:E,children:[e("label",{id:"phone",className:A,children:"Phone Number"}),o("div",{className:V,children:[e("select",{value:c.code,onChange:e=>{const o=te.find(o=>o.code===e.target.value);if(o){_(o);const e=n.replace(/^\+\d+/,""),r=(new b).input(o.dialCode+e);i(r)}},className:D,children:te.map(e=>o("option",{value:e.code,children:[e.flag," (",e.dialCode,")"]},e.code))}),e("input",{"aria-labelledby":"phone",type:"tel",value:n,onChange:e=>{const o=e.target.value,n=o.startsWith(c.dialCode)?o:c.dialCode+o,t=(new b).input(n);i(t),r&&l("")},onBlur:()=>{if(n){const e=k(n),o=e?.isValid();l(o?"":"Please enter a valid phone number.")}},autoComplete:"off",placeholder:"(555) 123-4567",className:H})]}),o("p",{className:B,children:["By signing up, you agree to our"," ",e("button",{onClick:()=>d(!0),className:L,children:"SMS Terms & Conditions"}),"."]}),r&&e("p",{className:z,children:r}),e(re,{isOpen:s,onClose:()=>d(!1)})]})}const le=e=>{if("string"!=typeof e)return!1;const o=e.trim();if(o.length<3||o.length>320)return!1;const n=o.split("@");if(2!==n.length)return!1;const[i,r]=n;return!(!/^[A-Za-z0-9._%+-]+$/.test(i)||i.startsWith(".")||i.endsWith(".")||i.includes(".."))&&!(!/^[A-Za-z0-9.-]+\.[A-Za-z]{2,}$/.test(r)||r.startsWith("-")||r.endsWith("-")||r.startsWith(".")||r.endsWith(".")||r.includes(".."))},se=e=>{const o=y(e);return o?.isValid()||!1};async function de(){if(window.PublicKeyCredential&&"function"==typeof window.PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable)try{return await PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable()}catch(e){return console.error("Error checking passkey support:",e),!1}return!1}const ce=({identifier:n,onMagicLink:i,onPhoneOtp:r,onPasskeyRetry:t})=>{const a=le(n),l=se(n);return o("div",{className:R,children:[e("div",{className:U,children:"Passkeys unavailable on this device"}),e("p",{className:q,children:"Choose another secure sign-in method."}),o("div",{className:K,children:[a&&o("button",{type:"button",className:J,onClick:i,children:[e("span",{className:W,children:"Email Magic Link"}),e("span",{className:$,children:"Send a secure sign-in link to your email"})]}),l&&o("button",{type:"button",className:J,onClick:r,children:[e("span",{className:W,children:"Text Message Code"}),e("span",{className:$,children:"Receive a one-time code via SMS"})]})]}),e("button",{type:"button",className:Y,onClick:t,children:"Try passkey anyway"})]})},_e=()=>{const i=d(),{apiHost:r,hasSignedInBefore:l,mode:s}=C(),{validateToken:c}=w(),[_,m]=t(""),[u,g]=t(""),[h,f]=t("register"),[y,b]=t(""),[k,v]=t(""),[x,P]=t(""),[T,M]=t(""),[L,V]=t(""),[D,H]=t(!1),[R,U]=t(!1),[q,K]=t(null),J=N({authMode:s,authHost:r});a(()=>{!async function(){const e=await de();H(e)}(),l&&f("login");const e=new URLSearchParams(window.location.search).get("bootstrapToken");e&&e.length>10&&(K(e),console.log("Bootstrap token detected in URL"))},[l]);const W=async()=>{try{const e=await J("/webAuthn/login/start",{method:"POST"});if(!e.ok)return void console.error("Something went wrong getting webauthn options");const o=await e.json(),n=await p({optionsJSON:o}),r=await J("/webAuthn/login/finish",{method:"POST",body:JSON.stringify({assertionResponse:n})});r.ok||console.error("Failed to verify passkey");const t=await r.json();if("Success"===t.message)return t.mfaLogin?void i("/mfaLogin"):(await c(),void i("/"));console.error("Passkey login failed:",t.message)}catch(e){console.error("Passkey login error:",e)}};return e("div",{className:S,children:o("div",{className:I,children:[e("h2",{className:O,children:"login"===h?"Sign In":"Create Account"}),e(n,{children:o("form",{onSubmit:async e=>{e.preventDefault(),"login"===h&&(async()=>{if(v(""),(await J("/login",{method:"POST",body:JSON.stringify({identifier:_,passkeyAvailable:D})})).ok)if(D)try{await W()}catch(e){console.error("Passkey login failed",e),U(!0)}else U(!0);else v("Failed to send login link. Please try again.")})(),"register"===h&&(async()=>{v("");try{const e=await J("/registration/register",{method:"POST",body:JSON.stringify({email:u,phone:y,...q?{bootstrapToken:q}:{}})});if(!e.ok)return void v("Failed to register. Please try again.");"Success"===(await e.json()).message&&i("/verifyPhoneOTP"),v("An unexpected error occured. Try again. If the problem persists, try resetting your password")}catch(e){console.error("Unexpected login error",e),v("An unexpected error occured. Try again. If the problem persists, try resetting your password")}})()},children:["login"===h&&o("div",{className:E,children:[e("label",{htmlFor:"identifier",className:A,children:"Email Address / Phone Number"}),e("input",{id:"identifier",type:"text",value:_,onChange:e=>{const o=e.target.value;m(o)},autoComplete:"off",placeholder:"Email or Phone Number",className:j,onBlur:()=>{if(_){const e=le(_)||se(_);V(e?"":"Please enter a valid email or phone number")}},required:!0}),e("p",{className:B,children:"Phone numbers must include a country code e.g. +1"}),R&&e(ce,{identifier:_,onMagicLink:async()=>{try{if(!(await J("/magic-link",{method:"GET"})).ok)return void v("Failed to send magic link.");i("/magic-link-sent")}catch(e){console.error(e),v("Failed to send magic link.")}},onPhoneOtp:async()=>{try{if(!(await J("/login/phone-otp",{method:"POST",body:JSON.stringify({identifier:_})})).ok)return void v("Failed to send OTP.");i("/verifyPhoneOTP")}catch(e){console.error(e),v("Failed to send OTP.")}},onPasskeyRetry:W}),L&&e("p",{className:z,children:L})]}),"register"===h&&o(n,{children:[o("div",{className:E,children:[e("label",{htmlFor:"email",className:A,children:"Email Address"}),e("input",{id:"email",type:"email",value:u,onChange:e=>{const o=e.target.value;g(o)},autoComplete:"off",className:j,onBlur:()=>{if(u){const e=le(u);M(e?"":"Please enter a valid email")}},required:!0}),T&&e("p",{className:z,children:T})]}),e(ae,{phone:y,setPhone:b,phoneError:x,setPhoneError:P})]}),e("button",{type:"submit",className:F,disabled:!("login"===h&&_?le(_)||se(_):le(u)&&se(y)),children:"login"===h?"Login":"Register"}),k&&e("p",{className:z,children:k}),e("button",{type:"button",onClick:()=>f("login"===h?"register":"login"),className:G,children:"login"===h?"Don't have an account? Create one":"Already have an account? Sign in"})]})})]})})};var me="passKeyLogin-module__container___IUKxF",ue="passKeyLogin-module__card___2sKM1",ge="passKeyLogin-module__title___HZxvc",pe="passKeyLogin-module__button___FvR4I";M(".passKeyLogin-module__container___IUKxF{align-items:center;color:#fff;display:flex;justify-content:center;padding:1rem}.passKeyLogin-module__card___2sKM1{background-color:#1f2937;border-radius:1rem;box-shadow:0 4px 20px rgba(0,0,0,.4);display:flex;flex-direction:column;gap:1.5rem;max-width:400px;padding:2rem;width:100%}.passKeyLogin-module__title___HZxvc{color:#fff;font-size:1.5rem;font-weight:600;text-align:center}.passKeyLogin-module__button___FvR4I{background-color:#2563eb;border:1px solid #3b82f6;border-radius:.5rem;color:#fff;cursor:pointer;font-weight:500;padding:.75rem 1rem;text-align:center;transition:background-color .2s ease;width:100%}.passKeyLogin-module__button___FvR4I:hover{background-color:#1d4ed8}@media (max-width:480px){.passKeyLogin-module__card___2sKM1{padding:1.25rem}.passKeyLogin-module__button___FvR4I{font-size:1rem}}");const he=()=>{const n=d(),{apiHost:i,mode:r}=C(),{validateToken:t}=w(),a=N({authMode:r,authHost:i});return e("div",{className:me,children:o("div",{className:ue,children:[e("h2",{className:ge,children:"Login with Passkey"}),e("button",{onClick:async()=>{try{const e=await a("/webAuthn/login/start",{method:"POST",headers:{"Content-Type":"application/json"},credentials:"include"});if(!e.ok)return void console.error("Something went wrong getting webauthn options");const o=await e.json(),i=await p({optionsJSON:o}),r=await a("/webAuthn/login/finish",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({assertionResponse:i}),credentials:"include"});r.ok||console.error("Failed to verify passkey");const l=await r.json();if("Success"===l.message)return l.mfaLogin&&n("/mfaLogin"),await t(),void n("/");console.error("Passkey login failed")}catch{console.error("Passkey login error")}},className:pe,children:"Use Passkey"})]})})};var fe="registerPasskey-module__container___jqEh8",ye="registerPasskey-module__card___MJAyC",be="registerPasskey-module__loading___Q4i1x",ke="registerPasskey-module__spinner___V1nhd",ve="registerPasskey-module__supported___ihTih",xe="registerPasskey-module__title___vn2Qu",we="registerPasskey-module__description___AWmO-",Ne="registerPasskey-module__button___D3b4B",Pe="registerPasskey-module__message___RiOw-",Ce="registerPasskey-module__success___HP5aX",Te="registerPasskey-module__error___hGiqE";M(".registerPasskey-module__container___jqEh8{align-items:center;color:#fff;display:flex;justify-content:center;padding:1rem}.registerPasskey-module__card___MJAyC{background-color:#1f2937;border-radius:1rem;box-shadow:0 4px 20px rgba(0,0,0,.4);max-width:400px;padding:1.5rem;width:100%}.registerPasskey-module__loading___Q4i1x{align-items:center;background-color:#f9fafb;border-radius:.75rem;box-shadow:0 2px 8px rgba(0,0,0,.1);color:#374151;display:flex;font-weight:500;gap:.75rem;justify-content:center;padding:1.5rem}.registerPasskey-module__spinner___V1nhd{animation:registerPasskey-module__spin___oYcsC 1s linear infinite;border-color:#3b82f6 transparent;border-radius:9999px;border-style:solid;border-width:2px;height:1.5rem;width:1.5rem}@keyframes registerPasskey-module__spin___oYcsC{to{transform:rotate(1turn)}}.registerPasskey-module__supported___ihTih{background-color:#ecfdf5;border-radius:.75rem;box-shadow:0 2px 12px rgba(0,0,0,.1);color:#065f46;padding:1.25rem}.registerPasskey-module__title___vn2Qu{font-size:1.125rem;font-weight:600;margin-bottom:.5rem}.registerPasskey-module__description___AWmO-{margin-bottom:1rem}.registerPasskey-module__button___D3b4B{background-color:#059669;border:none;border-radius:.5rem;color:#fff;cursor:pointer;font-weight:500;padding:.75rem 1rem;transition:background-color .2s ease;width:100%}.registerPasskey-module__button___D3b4B:hover{background-color:#047857}.registerPasskey-module__message___RiOw-{font-size:.875rem;margin-top:1rem}.registerPasskey-module__success___HP5aX{color:#6ee7b7}.registerPasskey-module__error___hGiqE{color:#f87171}");var Me="deviceNameModal-module__overlay___fmdPd",Se="deviceNameModal-module__modal___uoEda",Ie="deviceNameModal-module__description___-HMTA",Oe="deviceNameModal-module__input___4vQMI",Ee="deviceNameModal-module__actions___KXw7b",Ae="deviceNameModal-module__primary___9Ozlk",je="deviceNameModal-module__secondary___HILhc";M(".deviceNameModal-module__overlay___fmdPd{align-items:center;background:rgba(0,0,0,.45);display:flex;inset:0;justify-content:center;position:fixed;z-index:1000}.deviceNameModal-module__modal___uoEda{background:#1f2937;border-radius:12px;box-shadow:0 20px 40px rgba(0,0,0,.15);color:#fff;max-width:420px;padding:24px;width:100%}.deviceNameModal-module__description___-HMTA{color:#fff;font-size:14px;margin-bottom:16px}.deviceNameModal-module__input___4vQMI{border:1px solid #ddd;border-radius:8px;font-size:14px;margin-bottom:20px;padding:10px 12px;width:100%}.deviceNameModal-module__actions___KXw7b{display:flex;gap:10px;justify-content:flex-end}.deviceNameModal-module__primary___9Ozlk{background:#2563eb;border:none;border-radius:8px;color:#fff;cursor:pointer;padding:8px 14px}.deviceNameModal-module__secondary___HILhc{background:transparent;border:1px solid #ccc;border-radius:8px;cursor:pointer;padding:8px 14px}");const Be=({isOpen:n,onCancel:i,onConfirm:r})=>{const[a,l]=t("");return n?e("div",{className:Me,children:o("div",{className:Se,children:[e("h3",{children:"Name This Device"}),e("p",{className:Ie,children:"Give this passkey a friendly name so you can recognize it later."}),e("input",{type:"text",placeholder:"e.g., MacBook Pro, iPhone, YubiKey",value:a,onChange:e=>l(e.target.value),className:Oe,autoFocus:!0}),o("div",{className:Ee,children:[e("button",{onClick:i,className:je,children:"Cancel"}),e("button",{onClick:()=>r(a.trim()),disabled:!a.trim(),className:Ae,children:"Continue"})]})]})}):null},ze=()=>{const{apiHost:i,mode:r}=C(),{validateToken:l}=w(),s=d(),[c,_]=t("idle"),[m,u]=t(""),[g,p]=t(!1),[y,b]=t(!1),[k,v]=t(null),x=N({authMode:r,authHost:i});a(()=>{!async function(){const e=await de();p(e)}()},[]);const P=async(e,o)=>{if(!(await x("/webAuthn/register/finish",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({attestationResponse:e,metadata:o}),credentials:"include"})).ok)throw new Error("Verification failed");await l()};return o(n,{children:[e("div",{className:fe,children:e("div",{className:ye,children:o("div",g?{className:ve,children:[e("h2",{className:xe,children:"Secure Your Account with a Passkey"}),e("p",{className:we,children:"Your device supports passkeys! Register one to skip passwords forever."}),e("button",{onClick:()=>{const{platform:e,browser:o,deviceInfo:n}=function(){const e=navigator.userAgent.toLowerCase();let o="unknown",n="unknown";return/iphone|ipad|ipod/.test(e)?o="ios":/android/.test(e)?o="android":/mac os/.test(e)?o="mac":/windows/.test(e)?o="windows":/linux/.test(e)&&(o="linux"),/chrome/.test(e)&&(n="chrome"),/safari/.test(e)&&!/chrome/.test(e)&&(n="safari"),/firefox/.test(e)&&(n="firefox"),/edg/.test(e)&&(n="edge"),{platform:o,browser:n,deviceInfo:`${o} • ${n}`}}();v({platform:e,browser:o,deviceInfo:n}),b(!0)},disabled:"loading"===c,className:Ne,children:"loading"===c?"Registering...":"Register Passkey"}),m&&e("p",{className:`${Pe} ${"success"===c?Ce:Te}`,children:m})]}:{className:be,children:[e("div",{className:ke}),e("span",{children:"Checking for Passkey Support..."})]})})}),e(Be,{isOpen:y,onCancel:()=>{b(!1),v(null)},onConfirm:async e=>{if(!k)return;const{platform:o,browser:n,deviceInfo:i}=k;_("loading");try{const r=await x("/webAuthn/register/start",{method:"GET",headers:{"Content-Type":"application/json"},credentials:"include"});if(!r.ok)throw new Error("Failed to fetch challenge");const t=await r.json();let a;try{a=await h({optionsJSON:t})}catch(e){if(e instanceof f)throw new Error(e.name);throw e}await P(a,{friendlyName:e,platform:o,browser:n,deviceInfo:i}),_("success"),u("Passkey registered successfully."),s("/")}catch(e){console.error(e),_("error"),u("Error registering passkey.")}finally{b(!1),v(null)}}})]})};var Fe="verifyOTP-module__container___wgoDE",Ge="verifyOTP-module__card___3cs2p",Le="verifyOTP-module__title___fZ-1d",Ve="verifyOTP-module__subtitle___dGSu3",De="verifyOTP-module__error___GEtlG",He="verifyOTP-module__success___46TjG",Re="verifyOTP-module__form___jiGG-",Ue="verifyOTP-module__label___Zq5Mi",qe="verifyOTP-module__timer___smq-a",Ke="verifyOTP-module__resend___PlmkG",Je="verifyOTP-module__button___8pIuO",We="verifyOTP-module__toggle___wbzVa";M(".verifyOTP-module__container___wgoDE{align-items:center;color:#fff;display:flex;justify-content:center;padding:1rem}.verifyOTP-module__card___3cs2p{background-color:#1f2937;border-radius:.5rem;box-shadow:0 0 10px rgba(0,0,0,.3);max-width:28rem;padding:1.5rem;width:100%}.verifyOTP-module__title___fZ-1d{color:#fff;font-size:1.5rem;font-weight:700;margin-bottom:1rem;text-align:center}.verifyOTP-module__subtitle___dGSu3{color:#9ca3af;font-size:.875rem;margin-bottom:1.5rem;text-align:center}.verifyOTP-module__error___GEtlG{color:#f87171;margin-bottom:1rem;text-align:center}.verifyOTP-module__success___46TjG{color:#34d399;margin-bottom:.75rem;text-align:center}.verifyOTP-module__form___jiGG-{display:flex;flex-direction:column;gap:1rem}.verifyOTP-module__label___Zq5Mi{color:#d1d5db;display:block;font-size:.875rem;margin-bottom:.25rem}.verifyOTP-module__timer___smq-a{color:#facc15;font-size:.875rem}.verifyOTP-module__input___yqIXM{background-color:#374151;border:1px solid #4b5563;border-radius:.375rem;color:#fff;outline:none;padding:.5rem;width:100%}.verifyOTP-module__input___yqIXM:focus{box-shadow:0 0 0 2px #3b82f6}.verifyOTP-module__resend___PlmkG{background:none;border:none;color:#60a5fa;cursor:pointer;font-size:.75rem;margin-top:.25rem;text-decoration:underline}.verifyOTP-module__resend___PlmkG:hover{color:#3b82f6}.verifyOTP-module__button___8pIuO{background-color:#2563eb;border:none;border-radius:.375rem;color:#fff;cursor:pointer;padding:.5rem;transition:background-color .2s;width:100%}.verifyOTP-module__button___8pIuO:hover{background-color:#1d4ed8}.verifyOTP-module__toggle___wbzVa{background:none;border:none;color:#60a5fa;cursor:pointer;font-size:.875rem;margin-top:1.5rem;text-align:center;width:100%}");var $e="otpInput-module__otpContainer___MUjby",Ye="otpInput-module__otpInput___3YMVm";M(".otpInput-module__otpContainer___MUjby{display:flex;gap:8px;justify-content:center;margin-top:8px}.otpInput-module__otpInput___3YMVm{background:#374151;border:1px solid #4b5563;border-radius:8px;color:#fff;font-size:1.2rem;height:48px;text-align:center;transition:border-color .15s ease,box-shadow .15s ease;width:42px}.otpInput-module__otpInput___3YMVm:focus{border-color:#60a5fa;box-shadow:0 0 0 2px rgba(96,165,250,.25);outline:none}");const Ze=({length:o=6,value:n,inputMode:i="numeric",onChange:r,name:t="otp"})=>{const a=s([]),l=n.split("").concat(Array(o).fill("")).slice(0,o),d=(e,o)=>{var n;if(o.length>1)c(e,o);else if(!o||(n=o,"numeric"===i?/^\d$/.test(n):/^[a-zA-Z]$/.test(n))){const n=[...l];n[e]=o;const i=n.join("");r(i),o&&a.current[e+1]&&a.current[e+1]?.focus()}},c=(e,n)=>{let t=n;t="numeric"===i?n.replace(/\D/g,""):n.replace(/[^a-zA-Z]/g,"");const s=t.slice(0,o).split(""),d=[...l];s.forEach((n,i)=>{e+i<o&&(d[e+i]=n)}),r(d.join("")),a.current[Math.min(e+s.length,o-1)]?.focus()};return e("div",{className:$e,role:"group","aria-label":"One-time password input",onPaste:e=>{e.preventDefault(),c(0,e.clipboardData.getData("text"))},children:l.map((n,s)=>e("input",{ref:e=>a.current[s]=e,type:"text",inputMode:"numeric"===i?"numeric":"text",autoComplete:"one-time-code",name:`${t}-${s}`,maxLength:1,value:n,className:Ye,onChange:e=>d(s,e.target.value),onKeyDown:e=>((e,n)=>{if("Backspace"===n.key){n.preventDefault();const o=[...l];l[e]?(o[e]="",r(o.join(""))):e>0&&(o[e-1]="",r(o.join("")),a.current[e-1]?.focus())}"ArrowLeft"===n.key&&e>0&&a.current[e-1]?.focus(),"ArrowRight"===n.key&&e<o-1&&a.current[e+1]?.focus()})(s,e),"aria-label":`Digit ${s+1}`},s))})},Qe=()=>{const n=d(),{apiHost:i,mode:r}=C(),[l,s]=t(""),[c,_]=t(null),[m,u]=t(""),[g,p]=t(!1),[h,f]=t(""),[y,b]=t(300),k=N({authMode:r,authHost:i}),v=async()=>{p(!0);try{if(!c){(await k("/otp/verify-phone-otp",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({verificationToken:l}),credentials:"include"})).ok?_(!0):u("Verification failed.")}}catch(e){console.error(e),u("Verification failed.")}p(!1)},x=async()=>{f(""),await(async()=>{u("");const e=await k("/otp/generate-phone-otp",{method:"GET",headers:{"Content-Type":"application/json"}}),o=await e.json();e.ok?(o.token&&localStorage.setItem("token",o.token),f("Verification SMS has been resent.")):u("Failed to send SMS code. If this persists, refresh the page and try again.")})(),f("Verification SMS has been resent.")};return a(()=>{const e=setInterval(()=>{b(e=>e>0?e-1:0)},1e3);return()=>clearInterval(e)},[]),a(()=>{c&&(async()=>{(await k("/otp/generate-email-otp",{method:"GET",headers:{"Content-Type":"application/json"}})).ok?n("/verifyEmailOTP"):u("Failed to send Email code. If this persists, refresh the page and try registering again.")})()},[c,n,k]),e("div",{className:Fe,children:o("div",{className:Ge,children:[e("h2",{className:Le,children:"Verify Your Phone Number"}),e("p",{className:Ve,children:"Enter the code sent to your phone number."}),m&&e("p",{className:De,children:m}),h&&e("p",{className:He,children:h}),o("form",{onSubmit:async e=>{if(e.preventDefault(),u(""),6===l.length){p(!0);try{v()}catch{u("Unexpected error occurred.")}finally{p(!1)}}else u("Please enter a valid code.")},className:Re,children:[o("div",{children:[o("label",{htmlFor:"phoneCode",className:Ue,children:["Phone Verification Code ",(P=c,!0===P?e("span",{className:"text-green-400 ml-2",children:"✅"}):!1===P?e("span",{className:"text-red-400 ml-2",children:"❌"}):null)," -"," ",o("span",{className:qe,children:["Code expires in: ",(w=y,`${Math.floor(w/60).toString().padStart(2,"0")}:${(w%60).toString().padStart(2,"0")}`)]})]}),e(Ze,{length:6,value:l,onChange:s}),e("button",{type:"button",onClick:()=>x(),className:Ke,children:"Resend code to phone"})]}),e("button",{type:"submit",className:Je,children:g?"Verifying...":"Verify & Continue"}),e("button",{type:"button",onClick:()=>n("/login"),className:We,children:"Back to login"})]})]})});var w,P},Xe=()=>{const n=d(),{apiHost:i,mode:r}=C(),{validateToken:l}=w(),[s,c]=t(!1),[_,m]=t(""),[u,g]=t(300),[p,h]=t(""),[f,y]=t(""),[b,k]=t(!1),v=N({authMode:r,authHost:i});return a(()=>{const e=setInterval(()=>{g(e=>e>0?e-1:0)},1e3);return()=>clearInterval(e)},[]),a(()=>{!async function(){const e=await de();k(e)}()},[]),e("div",{className:Fe,children:o("div",{className:Ge,children:[e("h2",{className:Le,children:"Verify Your Email"}),e("p",{className:Ve,children:"We sent you a verification email. Enter the code below."}),p&&e("p",{className:De,children:p}),f&&e("p",{className:He,children:f}),o("form",{onSubmit:async e=>{if(e.preventDefault(),h(""),6===_.length){c(!0);try{if(!(await v("/otp/verify-email-otp",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({verificationToken:_}),credentials:"include"})).ok)return void h("Verification failed.");b?n("/registerPasskey"):(await l(),n("/"))}catch(e){console.error(e),h("Verification failed.")}finally{c(!1)}}else h("Please enter a valid code.")},className:Re,children:[o("div",{children:[o("label",{htmlFor:"emailCode",className:Ue,children:["Email Verification Code",o("span",{className:qe,children:[" ","— Code expires in ",(x=u,`${Math.floor(x/60).toString().padStart(2,"0")}:${(x%60).toString().padStart(2,"0")}`)]})]}),e(Ze,{length:6,value:_,onChange:m,inputMode:"text"}),e("button",{type:"button",onClick:async()=>{h(""),y("");(await v("/otp/generate-email-otp",{method:"GET",headers:{"Content-Type":"application/json"}})).ok?y("Verification email has been resent."):h("Failed to send Email code. If this persists, refresh the page and try again.")},className:Ke,children:"Resend code to email"})]}),e("button",{type:"submit",className:Je,disabled:s,children:s?"Verifying...":"Verify & Continue"}),e("button",{type:"button",onClick:()=>n("/login"),className:We,children:"Back to login"})]})]})});var x};var eo={container:"verifyMagiclink-module__container___qrSXf",card:"verifyMagiclink-module__card___niKgr",title:"verifyMagiclink-module__title___SumxD",verificationContent:"verifyMagiclink-module__verificationContent___NdsS0",spinner:"verifyMagiclink-module__spinner___lnW1k",successIcon:"verifyMagiclink-module__successIcon___XjFEM",checkIcon:"verifyMagiclink-module__checkIcon___I0JOP",successText:"verifyMagiclink-module__successText___lO5Qq"};M(".verifyMagiclink-module__container___qrSXf{align-items:center;color:#fff;display:flex;justify-content:center;padding:1rem}.verifyMagiclink-module__card___niKgr{background-color:#1f2937;border-radius:.5rem;box-shadow:0 0 10px rgba(0,0,0,.3);max-width:28rem;padding:1.5rem;width:100%}.verifyMagiclink-module__title___SumxD{color:#fff;font-size:1.5rem;font-weight:700;margin-bottom:1rem;text-align:center}.verifyMagiclink-module__verificationContent___NdsS0{align-items:center;display:flex;flex-direction:column;gap:14px;margin:20px 0}.verifyMagiclink-module__spinner___lnW1k{animation:verifyMagiclink-module__spin___2lGzj .9s linear infinite;border:3px solid hsla(0,0%,100%,.15);border-radius:50%;border-top-color:#60a5fa;height:28px;width:28px}.verifyMagiclink-module__successIcon___XjFEM{align-items:center;background:rgba(16,185,129,.15);border-radius:50%;display:flex;height:36px;justify-content:center;width:36px}.verifyMagiclink-module__checkIcon___I0JOP{animation:verifyMagiclink-module__checkPop___-3qJu .25s ease-out;color:#34d399;height:22px;width:22px}.verifyMagiclink-module__successText___lO5Qq{color:#34d399;font-size:.9rem}@keyframes verifyMagiclink-module__checkPop___-3qJu{0%{opacity:0;transform:scale(.6)}80%{transform:scale(1.15)}to{opacity:1;transform:scale(1)}}@keyframes verifyMagiclink-module__spin___2lGzj{to{transform:rotate(1turn)}}");const oo=()=>{const[n]=c(),i=d(),r=n.get("token"),{apiHost:l,mode:s}=C(),[_,m]=t(""),[u,g]=t(""),p=N({authMode:s,authHost:l});return a(()=>{r?(async()=>{if(!(await p(`/magic-link/verify/${r}`,{method:"GET",headers:{"Content-Type":"application/json"}})).ok)return console.error("Failed to verify token"),void m("Failed to verify token");new BroadcastChannel("seamless-auth").postMessage({type:"MAGIC_LINK_AUTH_SUCCESS"}),g("You have been verified on the device and browser that initiated this request"),setTimeout(()=>{i("/")},900)})():(m("Missing token for verification."),console.error("No token found",r))},[r,p,i]),e("div",{className:eo.container,children:o("div",{className:eo.card,children:[e("h1",{className:eo.title,children:"Verifying your login"}),o("div",{className:eo.verificationContent,children:[!u&&!_&&e("div",{className:eo.spinner}),u&&e("div",{className:eo.successIcon,children:e("svg",{viewBox:"0 0 24 24",className:eo.checkIcon,fill:"none",stroke:"currentColor",strokeWidth:"2",children:e("path",{d:"M5 13l4 4L19 7"})})}),!u&&!_&&e("p",{className:eo.helperText,children:"Please wait while we securely verify your sign-in link."}),u&&e("p",{className:eo.successText,children:"Login verified. Redirecting…"}),_&&e("p",{className:eo.error,children:_})]})]})})};var no="magiclink-module__container___45zcA",io="magiclink-module__card___Au9oN",ro="magiclink-module__iconWrapper___k5ndr",to="magiclink-module__mailIcon___Pwb7q",ao="magiclink-module__iconRing___bdLvf",lo="magiclink-module__heading___b9cre",so="magiclink-module__message___kiVFj",co="magiclink-module__identifier___JtcFM",_o="magiclink-module__helperText___7Mlfh",mo="magiclink-module__actions___64I-3",uo="magiclink-module__secondaryButton___BntAI",go="magiclink-module__cooldown___Ib4rm",po="magiclink-module__linkButton___maJiv";M(".magiclink-module__container___45zcA{align-items:center;color:#fff;display:flex;justify-content:center}.magiclink-module__card___Au9oN{background-color:#1f2937;border-radius:.75rem;box-shadow:0 10px 25px rgba(0,0,0,.25);max-width:420px;padding:2.5rem 2rem;text-align:center;width:100%}.magiclink-module__iconWrapper___k5ndr{display:flex;justify-content:center;margin-bottom:1.25rem;position:relative}.magiclink-module__mailIcon___Pwb7q{color:#a5b4fc;height:38px;width:38px;z-index:2}.magiclink-module__iconRing___bdLvf{animation:magiclink-module__pulse___YGm-I 2s infinite;background:rgba(99,102,241,.15);border-radius:50%;height:72px;position:absolute;width:72px}@keyframes magiclink-module__pulse___YGm-I{0%{opacity:.8;transform:scale(.6)}70%{opacity:0;transform:scale(1.4)}to{opacity:0}}.magiclink-module__heading___b9cre{font-size:1.55rem;font-weight:600;margin-bottom:.75rem}.magiclink-module__message___kiVFj{color:#d1d5db;font-size:.95rem;line-height:1.4;margin-bottom:1rem}.magiclink-module__identifier___JtcFM{background:hsla(0,0%,100%,.05);border-radius:6px;display:inline-block;font-size:1rem;font-weight:600;margin-bottom:1rem;padding:.45rem .6rem}.magiclink-module__helperText___7Mlfh{color:#9ca3af;font-size:.85rem;line-height:1.4;margin-bottom:.6rem}.magiclink-module__actions___64I-3{display:flex;flex-direction:column;gap:.6rem;margin-top:1.6rem}.magiclink-module__secondaryButton___BntAI{background:#111827;border:1px solid #374151;border-radius:8px;color:#fff;cursor:pointer;font-weight:500;padding:.65rem}.magiclink-module__secondaryButton___BntAI:hover:not(:disabled){background:#1f2937}.magiclink-module__secondaryButton___BntAI:disabled{cursor:not-allowed;opacity:.5}.magiclink-module__cooldown___Ib4rm{color:#9ca3af;font-size:.8rem}.magiclink-module__linkButton___maJiv{background:none;border:none;color:#a5b4fc;cursor:pointer;font-size:.85rem;margin-top:.4rem}.magiclink-module__linkButton___maJiv:hover{text-decoration:underline}");const ho=()=>{const{apiHost:n,mode:i}=C(),{validateToken:r}=w(),l=d(),s=_(),c=N({authMode:i,authHost:n}),m=s.state?.identifier,[u,g]=t(30);a(()=>{const e=setInterval(()=>{g(e=>e>0?e-1:0)},1e3);return()=>clearInterval(e)},[]);return a(()=>{const e=new BroadcastChannel("seamless-auth");return e.onmessage=async e=>{if("MAGIC_LINK_AUTH_SUCCESS"===e.data?.type){200===(await c("/magic-link/check",{method:"GET",headers:{"Content-Type":"application/json"}})).status&&(await r(),l("/"))}},()=>{e.close()}},[c,l,r]),a(()=>{const e=setInterval(async()=>{try{200===(await c("/magic-link/check",{method:"GET",headers:{"Content-Type":"application/json"}})).status&&(await r(),l("/"))}catch{}},5e3);return()=>clearInterval(e)},[n,r,l]),e("div",{className:no,children:o("div",{className:io,children:[o("div",{className:ro,children:[e("div",{className:ao}),o("svg",{className:to,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.8",children:[e("path",{d:"M4 6h16v12H4z"}),e("path",{d:"m4 6 8 6 8-6"})]})]}),e("h2",{className:lo,children:"Check your email"}),e("p",{className:so,children:"If an account exists for this address, we sent a secure sign-in link."}),e("div",{className:co,children:m}),e("p",{className:_o,children:"Open the email and click the link to finish signing in."}),e("p",{className:_o,children:"Didn’t receive anything? Check your spam folder or try creating a new account."}),o("div",{className:mo,children:[e("button",{className:uo,disabled:u>0,onClick:async()=>{u>0||(await c("/magic-link",{method:"GET",headers:{"Content-Type":"application/json"}}),g(30))},children:"Resend link"}),u>0&&o("div",{className:go,children:["Available in ",u,"s"]}),e("button",{className:po,onClick:()=>l("/login"),children:"Change email or phone"})]})]})})},fo=()=>o(m,{children:[e(u,{path:"/login",element:e(_e,{})}),e(u,{path:"/passKeyLogin",element:e(he,{})}),e(u,{path:"/verifyPhoneOTP",element:e(Qe,{})}),e(u,{path:"/verifyEmailOTP",element:e(Xe,{})}),e(u,{path:"/verify-magiclink",element:e(oo,{})}),e(u,{path:"/registerPasskey",element:e(ze,{})}),e(u,{path:"/magic-link-sent",element:e(ho,{})}),e(u,{path:"*",element:e(g,{to:"/login",replace:!0})})]});export{T as AuthProvider,fo as AuthRoutes,C as useAuth};
|
|
1
|
+
import{jsx as e,jsxs as o,Fragment as t}from"react/jsx-runtime";import{bufferToBase64URLString as n,browserSupportsWebAuthn as i,base64URLStringToBuffer as r,startAuthentication as a,startRegistration as s,WebAuthnError as l}from"@simplewebauthn/browser";import{useState as d,useEffect as c,createContext as u,useMemo as _,useCallback as m,useContext as p,useRef as g}from"react";import{useNavigate as h,useLocation as f,useSearchParams as y,Routes as b,Route as k,Navigate as v}from"react-router-dom";import w,{AsYouType as x,parsePhoneNumberFromString as P}from"libphonenumber-js";function N(e){if(e instanceof ArrayBuffer)return e;const o=new Uint8Array(e.buffer,e.byteOffset,e.byteLength),t=new Uint8Array(o.byteLength);return t.set(o),t.buffer}function S(e){return"string"==typeof e?e:n(N(e))}function O(e){return"string"==typeof e?r(e):e}function C(e){return{...e.credentialId?{credentialId:e.credentialId}:{},prf:{salt:S(e.salt),...e.secondSalt?{secondSalt:S(e.secondSalt)}:{}}}}async function T(){return!!i()&&(("undefined"==typeof window||!1!==window.isSecureContext)&&(void 0!==globalThis.PublicKeyCredential&&"undefined"!=typeof navigator&&"function"==typeof navigator.credentials?.get))}function M(e){const o=e,t=o.extensions?.prf?.eval;return t?{...o,extensions:{...o.extensions,prf:{...o.extensions?.prf,eval:{...t,...t.first?{first:O(t.first)}:{},...t.second?{second:O(t.second)}:{}}}}}:e}function A(e){const o=e.clientExtensionResults,t=o?.prf?.results?.first;if(!t)return null;const i=(r=t)instanceof ArrayBuffer?new Uint8Array(r):new Uint8Array(r.buffer,r.byteOffset,r.byteLength);var r;return{credentialId:e.id,output:i,outputBase64url:n(N(i))}}function I(e){const o=e.clientExtensionResults;return o?.prf?.results?{...e,clientExtensionResults:{...e.clientExtensionResults,prf:{...o.prf,results:void 0}}}:e}function E(e){const o=e.clientExtensionResults;return!0===o?.prf?.enabled}const z=e=>({success:!1,fresh:!1,method:null,verifiedAt:null,expiresAt:null,maxAgeSeconds:0,message:e}),L=e=>({...z(e),credentialId:null,prf:null});function j(e){return e?{method:"POST",body:JSON.stringify(C(e))}:{method:"POST"}}const F=e=>{const o=(e=>{const{authHost:o}=e;return async function(e,t){const n=`${o?.replace(/\/+$/,"")??""}/auth${e.startsWith("/")?e:`/${e}`}`,i={...t,credentials:"include",headers:{"Content-Type":"application/json",...t?.headers}},r=await fetch(n,i);return r.ok||console.warn("Auth fetch failed:",r.status),r}})({authHost:e.apiHost});return{getCurrentUser:()=>o("users/me",{method:"GET"}),login:e=>o("/login",{method:"POST",body:JSON.stringify(e)}),loginWithPasskey:async e=>{const t=await o("/webAuthn/login/start",{...j(e?.prf)});if(!t.ok)return{success:!1,mfaRequired:!1,message:"Failed to start passkey login."};try{const e=await t.json(),n=await a({optionsJSON:M(e)}),i=A(n),r=I(n),s=await o("/webAuthn/login/finish",{method:"POST",body:JSON.stringify({assertionResponse:r})});if(!s.ok)return{success:!1,mfaRequired:!1,message:"Failed to verify passkey."};const l=await s.json();return"Success"===l.message?{success:!l.mfaLogin,mfaRequired:Boolean(l.mfaLogin),message:l.mfaLogin?"Passkey login requires MFA.":"Passkey login succeeded.",...i?{prf:i}:{}}:{success:!1,mfaRequired:!1,message:l.message??"Passkey login failed."}}catch{return console.error("Passkey login error."),{success:!1,mfaRequired:!1,message:"Passkey login failed."}}},logout:(e={})=>o("all_sessions"===e.scope?"/logout/all":"/logout",{method:"DELETE"}),logoutAllSessions:()=>o("/logout/all",{method:"DELETE"}),deleteUser:()=>o("/users/delete",{method:"DELETE"}),register:e=>o("/registration/register",{method:"POST",body:JSON.stringify({email:e.email,phone:e.phone,...e.bootstrapToken?{bootstrapToken:e.bootstrapToken}:{}})}),requestPhoneOtp:()=>o("/otp/generate-phone-otp",{method:"GET"}),verifyPhoneOtp:e=>o("/otp/verify-phone-otp",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({verificationToken:e}),credentials:"include"}),requestLoginPhoneOtp:()=>o("/otp/generate-login-phone-otp",{method:"GET"}),verifyLoginPhoneOtp:e=>o("/otp/verify-login-phone-otp",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({verificationToken:e}),credentials:"include"}),requestEmailOtp:()=>o("/otp/generate-email-otp",{method:"GET",headers:{"Content-Type":"application/json"}}),verifyEmailOtp:e=>o("/otp/verify-email-otp",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({verificationToken:e}),credentials:"include"}),requestLoginEmailOtp:()=>o("/otp/generate-login-email-otp",{method:"GET",headers:{"Content-Type":"application/json"}}),verifyLoginEmailOtp:e=>o("/otp/verify-login-email-otp",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({verificationToken:e}),credentials:"include"}),requestMagicLink:()=>o("/magic-link",{method:"GET"}),checkMagicLink:()=>o("/magic-link/check",{method:"GET",headers:{"Content-Type":"application/json"}}),verifyMagicLink:e=>o(`/magic-link/verify/${e}`,{method:"GET",headers:{"Content-Type":"application/json"}}),listOAuthProviders:async()=>{const e=await o("/oauth/providers",{method:"GET"});if(!e.ok)throw new Error("Failed to list OAuth providers.");return e.json()},startOAuthLogin:async e=>{const t=await o(`/oauth/${encodeURIComponent(e.providerId)}/start`,{method:"POST",body:JSON.stringify({...e.redirectUri?{redirectUri:e.redirectUri}:{},...e.returnTo?{returnTo:e.returnTo}:{}})});if(!t.ok)throw new Error("Failed to start OAuth login.");return t.json()},finishOAuthLogin:e=>o(`/oauth/${encodeURIComponent(e.providerId)}/callback`,{method:"POST",body:JSON.stringify({code:e.code,state:e.state})}),registerPasskey:async e=>{const t=function(e){return"metadata"in e?e:{metadata:e}}(e),n=await o(function(e){const o=new URLSearchParams;e.requirePrf?o.set("requirePrf","true"):e.requestPrf&&o.set("requestPrf","true");const t=o.toString();return"/webAuthn/register/start"+(t?`?${t}`:"")}(t),{method:"GET",headers:{"Content-Type":"application/json"},credentials:"include"});if(!n.ok)return{success:!1,message:"Failed to fetch passkey registration challenge."};const i=await n.json();let r;try{r=await s({optionsJSON:i})}catch(e){return e instanceof l?{success:!1,message:e.name}:(console.error("Passkey registration error."),{success:!1,message:"Passkey registration failed."})}return(await o("/webAuthn/register/finish",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({attestationResponse:r,metadata:{...t.metadata,prfCapable:E(r)}}),credentials:"include"})).ok?{success:!0,message:"Passkey registered successfully.",credentialId:r.id,prfCapable:E(r)}:{success:!1,message:"Verification failed."}},isPasskeyPrfSupported:T,getStepUpStatus:()=>o("/step-up/status",{method:"GET"}),verifyStepUpWithPasskey:async()=>{const e=await o("/step-up/webauthn/start",{method:"POST"});if(!e.ok)return z("Failed to start step-up authentication.");try{const t=await e.json(),n=I(await a({optionsJSON:M(t)})),i=await o("/step-up/webauthn/finish",{method:"POST",body:JSON.stringify({assertionResponse:n})});if(!i.ok)return z("Failed to verify step-up authentication.");const r=await i.json(),s="webauthn"===r.method?r.method:null,l="Success"===r.message&&!0===r.fresh&&"webauthn"===s;return{success:l,fresh:Boolean(r.fresh),method:s,verifiedAt:r.verifiedAt??null,expiresAt:r.expiresAt??null,maxAgeSeconds:r.maxAgeSeconds??0,message:l?"Step-up authentication succeeded.":r.message??"Step-up authentication failed."}}catch{return console.error("Step-up authentication error."),z("Step-up authentication failed.")}},verifyStepUpWithPasskeyPrf:async e=>{const t=await o("/step-up/webauthn/start",{...j(e)});if(!t.ok)return L("Failed to start step-up authentication.");try{const e=await t.json(),n=await a({optionsJSON:M(e)}),i=A(n),r=I(n);if(!i)return L("Passkey did not return PRF output.");const s=await o("/step-up/webauthn/finish",{method:"POST",body:JSON.stringify({assertionResponse:r})});if(!s.ok)return L("Failed to verify step-up authentication.");const l=await s.json(),d="webauthn"===l.method?l.method:null,c="Success"===l.message&&!0===l.fresh&&"webauthn"===d;return{success:c,fresh:Boolean(l.fresh),method:d,verifiedAt:l.verifiedAt??null,expiresAt:l.expiresAt??null,maxAgeSeconds:l.maxAgeSeconds??0,message:c?"Step-up authentication succeeded.":l.message??"Step-up authentication failed.",credentialId:i.credentialId,prf:i}}catch{return console.error("Step-up authentication error."),L("Step-up authentication failed.")}},updateCredential:e=>o("users/credentials",{method:"POST",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)}),deleteCredential:e=>o("users/credentials",{method:"DELETE",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify({id:e})}),listOrganizations:()=>o("/organizations",{method:"GET"}),createOrganization:e=>o("/organizations",{method:"POST",body:JSON.stringify(e)}),getOrganization:e=>o(`/organizations/${encodeURIComponent(e)}`,{method:"GET"}),updateOrganization:(e,t)=>o(`/organizations/${encodeURIComponent(e)}`,{method:"PATCH",body:JSON.stringify(t)}),switchOrganization:e=>o(`/organizations/${encodeURIComponent(e)}/switch`,{method:"POST"}),listOrganizationMembers:e=>o(`/organizations/${encodeURIComponent(e)}/members`,{method:"GET"}),addOrganizationMember:(e,t)=>o(`/organizations/${encodeURIComponent(e)}/members`,{method:"POST",body:JSON.stringify(t)}),updateOrganizationMember:(e,t,n)=>o(`/organizations/${encodeURIComponent(e)}/members/${encodeURIComponent(t)}`,{method:"PATCH",body:JSON.stringify(n)}),removeOrganizationMember:(e,t)=>o(`/organizations/${encodeURIComponent(e)}/members/${encodeURIComponent(t)}`,{method:"DELETE"})}};function U(e,o){const t=e.trim(),n=o.trim();if(!t||!n)return!1;if(t===n)return!0;if(t.endsWith(":*")){const e=t.slice(0,-2);return n===e||n.startsWith(`${e}:`)}if(!n.includes(":"))return!1;if(!t.includes(":"))return n.startsWith(`${t}:`);const i=t.split(":"),r=n.split(":"),a=i[i.length-1],s=r[r.length-1],l=i.slice(0,-1),d=r.slice(0,-1);return"write"===a&&"read"===s&&l.length===d.length&&l.every((e,o)=>e===d[o])}function B(e,o){if(!Array.isArray(e))return!1;const t=e.filter(e=>"string"==typeof e);return(Array.isArray(o)?o:[o]).some(e=>t.some(o=>U(o,e)))}const R=u(void 0),q=()=>{const e=p(R);if(!e)throw new Error("useAuth must be used within an AuthProvider");return e},G=({children:o,apiHost:t,autoDetectPreviousSignin:n=!0})=>{const[i,r]=d(null),[a,s]=d([]),[l,u]=d([]),[p,g]=d(null),[h,f]=d(null),[y,b]=d(!1),[k,v]=d(!0),{hasSignedInBefore:w,markSignedIn:x}=function(e="seamlessauth_seen"){const[o,t]=d(!1);return c(()=>{try{"true"===localStorage.getItem(e)&&t(!0)}catch{}},[e]),{hasSignedInBefore:o,markSignedIn:()=>{try{localStorage.setItem(e,"true"),t(!0)}catch{}}}}(),P=_(()=>F({apiHost:t}),[t]),N=m(()=>{b(!1),r(null),s([]),u([]),g(null),f(null)},[]),S=m(async()=>{try{await P.logout()}catch{console.error("Error during logout")}finally{N()}},[P,N]),O=m(async()=>{try{await P.logoutAllSessions()}catch{console.error("Error during logout")}finally{N()}},[P,N]),C=m(async()=>{v(!0);try{const e=await P.getCurrentUser();if(e.ok){const{user:o,credentials:t,organizations:n,activeOrganization:i}=await e.json();r(o),s(t??[]),u(n??[]),g(i??null),b(!0)}else await S()}catch{await S()}finally{v(!1)}},[P,S]),T=m(async()=>{const e=await P.getStepUpStatus();if(!e.ok)return f(null),null;const o=await e.json();return f(o),o},[P]),M=m(async()=>{const e=await P.verifyStepUpWithPasskey();return e.success&&f({fresh:e.fresh,method:e.method,verifiedAt:e.verifiedAt,expiresAt:e.expiresAt,maxAgeSeconds:e.maxAgeSeconds}),e},[P]),A=m(async e=>{const o=await P.verifyStepUpWithPasskeyPrf(e);return o.success&&f({fresh:o.fresh,method:o.method,verifiedAt:o.verifiedAt,expiresAt:o.expiresAt,maxAgeSeconds:o.maxAgeSeconds}),o},[P]);return c(()=>{C()},[C]),c(()=>{i&&y&&x()},[i,y,x]),e(R.Provider,{value:{user:i,logout:S,logoutAllSessions:O,refreshSession:C,loading:k,deleteUser:async()=>{try{if((await P.deleteUser()).ok)return r(null),b(!1),s([]),u([]),g(null),void f(null);throw new Error("Could not delete user.")}catch{throw console.error("Something went wrong deleting user."),new Error("Could not delete user.")}},isAuthenticated:y,hasRole:e=>i?.roles?.includes(e),hasScopedRole:e=>i?B(i.roles,e):void 0,apiHost:t,markSignedIn:x,hasSignedInBefore:!!n&&w,credentials:a,organizations:l,activeOrganization:p,switchOrganization:async e=>{if(!(await P.switchOrganization(e)).ok)throw new Error("Failed to switch organization");await C()},listOAuthProviders:()=>P.listOAuthProviders(),startOAuthLogin:e=>P.startOAuthLogin(e),finishOAuthLogin:async e=>{if(!(await P.finishOAuthLogin(e)).ok)throw new Error("Failed to finish OAuth login");await C()},stepUpStatus:h,updateCredential:async e=>{const o=await P.updateCredential({friendlyName:e.friendlyName,id:e.id});if(o.ok){const e=await o.json(),t=e.credential??e;return s(e=>e.map(e=>e.id===t.id?{...e,...t}:e)),e}throw new Error("Failed to update credential")},deleteCredential:async e=>{const o=await P.deleteCredential(e);if(o.ok){const t=await o.json();return s(o=>o.filter(o=>o.id!==e)),t}throw new Error("Failed to delete credential")},login:async(e,o)=>P.login({identifier:e,passkeyAvailable:o}),handlePasskeyLogin:async()=>{const e=await P.loginWithPasskey();return e.mfaRequired?(console.warn("Passkey login requested MFA, but the built-in MFA route is not currently available."),!1):e.success?(await C(),!0):(console.error("Passkey login failed."),!1)},refreshStepUpStatus:T,verifyStepUpWithPasskey:M,verifyStepUpWithPasskeyPrf:A},children:o})};function D(e,o){void 0===o&&(o={});var t=o.insertAt;if(e&&"undefined"!=typeof document){var n=document.head||document.getElementsByTagName("head")[0],i=document.createElement("style");i.type="text/css","top"===t&&n.firstChild?n.insertBefore(i,n.firstChild):n.appendChild(i),i.styleSheet?i.styleSheet.cssText=e:i.appendChild(document.createTextNode(e))}}var J="login-module__container___YggDx",V="login-module__card___Ub-Py",W="login-module__heading___neEqb",$="login-module__inputGroup___P6qgS",K="login-module__label___mx5vu",H="login-module__input___U07lW",Y="login-module__helperText___kDQ4-",Z="login-module__error___40zxh",Q="login-module__button___0kFBs",X="login-module__toggle___1JiG1",ee="login-module__underline___gs-RS",oe="login-module__phoneRow___oeNtq",te="login-module__select___rRV1O",ne="login-module__phoneInput___2MPQC",ie="login-module__fallbackCard___HdIk-",re="login-module__fallbackHeader___-il2v",ae="login-module__fallbackDescription___ea5EB",se="login-module__fallbackActions___AD3ni",le="login-module__fallbackActionButton___lFgWf",de="login-module__actionTitle___ycrMp",ce="login-module__actionSubtext___opaIV",ue="login-module__linkButton___5lsoe";D(".login-module__container___YggDx{align-items:center;color:#fff;display:flex;justify-content:center}.login-module__card___Ub-Py{background-color:#1f2937;border-radius:.5rem;box-shadow:0 4px 6px rgba(0,0,0,.1);max-width:28rem;padding:2rem;width:100%}.login-module__heading___neEqb{color:#fff;font-size:1.5rem;font-weight:700;margin-bottom:1.5rem;text-align:center}.login-module__message___qSejT{color:#68d391;text-align:center}.login-module__inputGroup___P6qgS{margin-bottom:1rem}.login-module__label___mx5vu{color:#d1d5db;display:block}.login-module__input___U07lW{background-color:#4b5563;border:1px solid #d1d5db;border-radius:.375rem;margin-top:.25rem;padding:.5rem;width:100%}.login-module__input___U07lW:focus{box-shadow:0 0 0 2px #3b82f6;outline:none}.login-module__helperText___kDQ4-{color:#9ca3af;font-size:.75rem;margin-top:.5rem}.login-module__error___40zxh{color:#f87171;font-size:.875rem}.login-module__button___0kFBs{background-color:#2563eb;border-radius:.375rem;color:#fff;cursor:pointer;margin-top:1rem;padding:.5rem;transition:background-color .3s;width:100%}.login-module__button___0kFBs:hover{background-color:#1d4ed8}.login-module__button___0kFBs:disabled{background-color:#9ca3af;cursor:not-allowed}.login-module__toggle___1JiG1{background:none;border:none;color:#60a5fa;cursor:pointer;font-size:.875rem;margin-top:1.5rem;text-align:center;width:100%}.login-module__underline___gs-RS{text-decoration:underline}.login-module__phoneRow___oeNtq{display:grid;gap:.5rem;grid-template-columns:1fr 3fr;margin-top:.25rem}.login-module__phoneInput___2MPQC,.login-module__select___rRV1O{background-color:#4b5563;border:1px solid #d1d5db;border-radius:.375rem;padding:.5rem;width:100%}@media (max-width:500px){.login-module__phoneRow___oeNtq{grid-template-columns:1fr}}.login-module__fallbackCard___HdIk-{background:hsla(0,0%,100%,.04);border:1px solid hsla(0,0%,100%,.08);border-radius:12px;display:flex;flex-direction:column;gap:14px;margin-top:18px;padding:18px}.login-module__fallbackHeader___-il2v{color:#f3f4f6;font-size:.95rem;font-weight:600}.login-module__fallbackDescription___ea5EB{color:#9ca3af;font-size:.85rem;line-height:1.4}.login-module__fallbackActions___AD3ni{display:flex;flex-direction:column;gap:10px}.login-module__fallbackActionButton___lFgWf{background:rgba(0,0,0,.25);border:1px solid hsla(0,0%,100%,.08);border-radius:8px;cursor:pointer;display:flex;flex-direction:column;padding:12px 14px;text-align:left;transition:all .15s ease}.login-module__fallbackActionButton___lFgWf:hover{background:hsla(0,0%,100%,.06);border-color:hsla(0,0%,100%,.15)}.login-module__actionTitle___ycrMp{color:#f9fafb;font-size:.9rem;font-weight:500}.login-module__actionSubtext___opaIV{color:#9ca3af;font-size:.75rem;margin-top:2px}.login-module__linkButton___5lsoe{background:none;border:none;color:#60a5fa;cursor:pointer;font-size:.8rem;margin-top:6px}.login-module__linkButton___5lsoe:hover{text-decoration:underline}");var _e="termsModal-module__overlay___-j6r5",me="termsModal-module__modal___4PxZV",pe="termsModal-module__header___B7wxb",ge="termsModal-module__title___Sucwt",he="termsModal-module__closeBtn___evIs5",fe="termsModal-module__content___5BDhN",ye="termsModal-module__link___oPZrU";D(".termsModal-module__overlay___-j6r5{align-items:center;background-color:rgba(0,0,0,.7);display:flex;inset:0;justify-content:center;position:fixed;z-index:999}.termsModal-module__modal___4PxZV{background-color:#1a1a1a;border-radius:8px;box-shadow:0 10px 25px rgba(0,0,0,.4);color:#fff;max-height:80vh;max-width:640px;outline:none;overflow-y:auto;padding:24px;width:100%}.termsModal-module__header___B7wxb{align-items:center;display:flex;justify-content:space-between;margin-bottom:16px}.termsModal-module__title___Sucwt{color:#60a5fa;font-size:1.25rem;font-weight:700}.termsModal-module__closeBtn___evIs5{background:none;border:none;color:#ccc;cursor:pointer;font-size:1.75rem}.termsModal-module__closeBtn___evIs5:hover{color:#fff}.termsModal-module__content___5BDhN{color:#d1d5db;font-size:.9rem;line-height:1.6}.termsModal-module__link___oPZrU{color:#60a5fa;text-decoration:underline}.termsModal-module__link___oPZrU:hover{text-decoration:none}");const be=({isOpen:t,onClose:n})=>{const i=g(null);return c(()=>{const e=e=>{"Escape"===e.key&&n()};return t&&(document.addEventListener("keydown",e),i.current?.focus()),()=>{document.removeEventListener("keydown",e)}},[t,n]),t?e("div",{className:_e,role:"dialog","aria-modal":"true","aria-labelledby":"terms-title",children:o("div",{className:me,tabIndex:-1,ref:i,children:[o("div",{className:pe,children:[e("h2",{id:"terms-title",className:ge,children:"SMS Terms & Conditions"}),e("button",{onClick:n,className:he,children:"×"})]}),o("div",{className:fe,children:[o("p",{children:[e("strong",{children:"Effective Date:"})," June 01, 2025"]}),e("p",{children:"By providing your phone number to SeamlessAuth, a Fells Code LLC product, you agree to receive SMS messages for identity verification, authentication, and account security."}),o("p",{children:[e("strong",{children:"1. Purpose:"})," SMS is used only for account security (OTP, MFA). No marketing messages."]}),o("p",{children:[e("strong",{children:"2. Frequency:"})," Based on login and account activity."]}),o("p",{children:[e("strong",{children:"3. Opt-Out:"})," Contact support@seamlessauth.com to opt out."]}),o("p",{children:[e("strong",{children:"4. Fees:"})," Message and data rates may apply."]}),o("p",{children:[e("strong",{children:"5. Supported Carriers:"})," Most major providers supported, delivery not guaranteed."]}),o("p",{children:[e("strong",{children:"6. Privacy:"})," Your phone number is not shared or sold. See our Privacy Policy."]}),o("p",{children:[e("strong",{children:"7. Changes:"})," Terms may be updated with notice on this page."]}),o("p",{children:["Questions? Email us at"," ",e("a",{className:ye,href:"mailto:support@seamlessauth.com",children:"support@seamlessauth.com"}),"."]})]})]})}):null},ke=[{code:"US",name:"United States",dialCode:"+1",flag:"🇺🇸"},{code:"CA",name:"Canada",dialCode:"+1",flag:"🇨🇦"},{code:"GB",name:"United Kingdom",dialCode:"+44",flag:"🇬🇧"},{code:"IN",name:"India",dialCode:"+91",flag:"🇮🇳"},{code:"AU",name:"Australia",dialCode:"+61",flag:"🇦🇺"}];function ve({phone:t,setPhone:n,phoneError:i,setPhoneError:r}){const[a,s]=d(!1),[l,u]=d(ke[0]);c(()=>{const e=function(){try{const e=Intl.DateTimeFormat().resolvedOptions().locale||"en-US",o=e.split("-")[1]?.toUpperCase()||"US";return ke.find(e=>e.code===o)||ke[0]}catch{return ke[0]}}();u(e)},[]);return o("div",{className:$,children:[e("label",{id:"phone",className:K,children:"Phone Number"}),o("div",{className:oe,children:[e("select",{value:l.code,onChange:e=>{const o=ke.find(o=>o.code===e.target.value);if(o){u(o);const e=t.replace(/^\+\d+/,""),i=(new x).input(o.dialCode+e);n(i)}},className:te,children:ke.map(e=>o("option",{value:e.code,children:[e.flag," (",e.dialCode,")"]},e.code))}),e("input",{"aria-labelledby":"phone",type:"tel",value:t,onChange:e=>{const o=e.target.value,t=o.startsWith(l.dialCode)?o:l.dialCode+o,a=(new x).input(t);n(a),i&&r("")},onBlur:()=>{if(t){const e=P(t),o=e?.isValid();r(o?"":"Please enter a valid phone number.")}},autoComplete:"off",placeholder:"(555) 123-4567",className:ne})]}),o("p",{className:Y,children:["By signing up, you agree to our"," ",e("button",{onClick:()=>s(!0),className:ee,children:"SMS Terms & Conditions"}),"."]}),i&&e("p",{className:Z,children:i}),e(be,{isOpen:a,onClose:()=>s(!1)})]})}const we=()=>{const{apiHost:e}=q();return _(()=>F({apiHost:e}),[e])},xe=e=>{if("string"!=typeof e)return!1;const o=e.trim();if(o.length<3||o.length>320)return!1;const t=o.split("@");if(2!==t.length)return!1;const[n,i]=t;return!(!/^[A-Za-z0-9._%+-]+$/.test(n)||n.startsWith(".")||n.endsWith(".")||n.includes(".."))&&!(!/^[A-Za-z0-9.-]+\.[A-Za-z]{2,}$/.test(i)||i.startsWith("-")||i.endsWith("-")||i.startsWith(".")||i.endsWith(".")||i.includes(".."))},Pe=e=>{const o=w(e);return o?.isValid()||!1};const Ne=()=>{const[e,o]=d(!1),[t,n]=d(!0);return c(()=>{let e=!0;return(async()=>{try{const t=await async function(){if(window.PublicKeyCredential&&"function"==typeof window.PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable)try{return await PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable()}catch{return console.error("Error checking passkey support."),!1}return!1}();e&&o(t)}catch{e&&o(!1)}finally{e&&n(!1)}})(),()=>{e=!1}},[]),{passkeySupported:e,loading:t}},Se=({identifier:t,onMagicLink:n,onEmailOtp:i,onPhoneOtp:r,onPasskeyRetry:a,loginMethods:s})=>{const l=new Set(s??["passkey","magic_link","phone_otp"]),d=l.has("magic_link")&&xe(t),c=l.has("email_otp")&&Boolean(i)&&xe(t),u=l.has("phone_otp")&&Pe(t),_=l.has("passkey")&&Boolean(a);return d||c||u||_?o("div",{className:ie,children:[e("div",{className:re,children:"Choose a sign-in method"}),e("p",{className:ae,children:"Choose another secure sign-in method."}),o("div",{className:se,children:[d&&o("button",{type:"button",className:le,onClick:n,children:[e("span",{className:de,children:"Email Magic Link"}),e("span",{className:ce,children:"Send a secure sign-in link to your email"})]}),c&&o("button",{type:"button",className:le,onClick:i,children:[e("span",{className:de,children:"Email Code"}),e("span",{className:ce,children:"Receive a one-time code by email"})]}),u&&o("button",{type:"button",className:le,onClick:r,children:[e("span",{className:de,children:"Text Message Code"}),e("span",{className:ce,children:"Receive a one-time code via SMS"})]})]}),_&&e("button",{type:"button",className:ue,onClick:a,children:"Try passkey anyway"})]}):null},Oe=["passkey","magic_link","phone_otp"],Ce=()=>{const n=h(),{hasSignedInBefore:i,login:r,handlePasskeyLogin:a}=q(),s=we(),{passkeySupported:l}=Ne(),[u,_]=d(""),[m,p]=d(""),[g,f]=d("register"),[y,b]=d(""),[k,v]=d(""),[w,x]=d(""),[P,N]=d(""),[S,O]=d(""),[C,T]=d(!1),[M,A]=d(Oe),[I,E]=d(null);c(()=>{i&&f("login");const e=new URLSearchParams(window.location.search).get("bootstrapToken");e&&e.length>10&&E(e)},[i]);return e("div",{className:J,children:o("div",{className:V,children:[e("h2",{className:W,children:"login"===g?"Sign In":"Create Account"}),e(t,{children:o("form",{onSubmit:async e=>{e.preventDefault(),v(""),T(!1);try{if("login"===g){const e=await r(u,l),o=await(async e=>{if(!e||"function"!=typeof e.json)return null;try{return await e.json()}catch{return null}})(e),t=o?.loginMethods?.length?o.loginMethods:Oe;if(A(t),e?.ok&&l&&t.includes("passkey")){return await a()?void n("/"):(T(!0),void v("Passkey sign-in could not be completed. Choose another sign-in method."))}return e?.ok?void T(!0):void v("Failed to start sign-in. Please try again.")}"register"===g&&await(async()=>{v("");try{const e=await s.register({email:m,phone:y,bootstrapToken:I});if(!e.ok)return void v("Failed to register. Please try again.");if("Success"===(await e.json()).message)return void n("/verifyPhoneOTP");v("An unexpected error occurred. Try again. If the problem persists, try resetting your password.")}catch{console.error("Unexpected login error."),v("An unexpected error occurred. Try again. If the problem persists, try resetting your password.")}})()}catch{console.error("Failed to continue sign-in."),v("Failed to continue sign-in. Please try again.")}},children:["login"===g&&o("div",{className:$,children:[e("label",{htmlFor:"identifier",className:K,children:"Email Address / Phone Number"}),e("input",{id:"identifier",type:"text",value:u,onChange:e=>{const o=e.target.value;_(o)},autoComplete:"off",placeholder:"Email or Phone Number",className:H,onBlur:()=>{if(u){const e=xe(u)||Pe(u);O(e?"":"Please enter a valid email or phone number")}},required:!0}),e("p",{className:Y,children:"Phone numbers must include a country code e.g. +1"}),C&&e(Se,{identifier:u,onMagicLink:async()=>{try{if(!(await s.requestMagicLink()).ok)return void v("Failed to send magic link.");n("/magiclinks-sent",{state:{identifier:u}})}catch{console.error("Failed to send magic link."),v("Failed to send magic link.")}},onEmailOtp:async()=>{try{if(!(await s.requestLoginEmailOtp()).ok)return void v("Failed to send email code.");n("/verifyEmailOTP",{state:{flow:"login"}})}catch{console.error("Failed to send email OTP."),v("Failed to send email code.")}},onPhoneOtp:async()=>{try{if(!(await s.requestLoginPhoneOtp()).ok)return void v("Failed to send OTP.");n("/verifyPhoneOTP",{state:{flow:"login"}})}catch{console.error("Failed to send phone OTP."),v("Failed to send OTP.")}},onPasskeyRetry:l?a:void 0,loginMethods:M}),S&&e("p",{className:Z,children:S})]}),"register"===g&&o(t,{children:[o("div",{className:$,children:[e("label",{htmlFor:"email",className:K,children:"Email Address"}),e("input",{id:"email",type:"email",value:m,onChange:e=>{const o=e.target.value;p(o)},autoComplete:"off",className:H,onBlur:()=>{if(m){const e=xe(m);N(e?"":"Please enter a valid email")}},required:!0}),P&&e("p",{className:Z,children:P})]}),e(ve,{phone:y,setPhone:b,phoneError:w,setPhoneError:x})]}),e("button",{type:"submit",className:Q,disabled:!("login"===g&&u?xe(u)||Pe(u):xe(m)&&Pe(y)),children:"login"===g?"Login":"Register"}),k&&e("p",{className:Z,children:k}),e("button",{type:"button",onClick:()=>f("login"===g?"register":"login"),className:X,children:"login"===g?"Don't have an account? Create one":"Already have an account? Sign in"})]})})]})})};var Te={container:"passKeyLogin-module__container___IUKxF",card:"passKeyLogin-module__card___2sKM1",title:"passKeyLogin-module__title___HZxvc",button:"passKeyLogin-module__button___FvR4I"};D(".passKeyLogin-module__container___IUKxF{align-items:center;color:#fff;display:flex;justify-content:center;padding:1rem}.passKeyLogin-module__card___2sKM1{background-color:#1f2937;border-radius:1rem;box-shadow:0 4px 20px rgba(0,0,0,.4);display:flex;flex-direction:column;gap:1.5rem;max-width:400px;padding:2rem;width:100%}.passKeyLogin-module__title___HZxvc{color:#fff;font-size:1.5rem;font-weight:600;text-align:center}.passKeyLogin-module__button___FvR4I{background-color:#2563eb;border:1px solid #3b82f6;border-radius:.5rem;color:#fff;cursor:pointer;font-weight:500;padding:.75rem 1rem;text-align:center;transition:background-color .2s ease;width:100%}.passKeyLogin-module__button___FvR4I:hover{background-color:#1d4ed8}@media (max-width:480px){.passKeyLogin-module__card___2sKM1{padding:1.25rem}.passKeyLogin-module__button___FvR4I{font-size:1rem}}");const Me=()=>{const t=h(),{handlePasskeyLogin:n}=q(),[i,r]=d("");return e("div",{className:Te.container,children:o("div",{className:Te.card,children:[e("h2",{className:Te.title,children:"Login with Passkey"}),e("button",{onClick:async()=>{r("");await n()?t("/"):r("Passkey sign-in could not be completed. Try another sign-in method.")},className:Te.button,children:"Use Passkey"}),i&&e("p",{className:Te.error,children:i})]})})};var Ae="registerPasskey-module__container___jqEh8",Ie="registerPasskey-module__card___MJAyC",Ee="registerPasskey-module__loading___Q4i1x",ze="registerPasskey-module__spinner___V1nhd",Le="registerPasskey-module__supported___ihTih",je="registerPasskey-module__title___vn2Qu",Fe="registerPasskey-module__description___AWmO-",Ue="registerPasskey-module__button___D3b4B",Be="registerPasskey-module__message___RiOw-",Re="registerPasskey-module__success___HP5aX",qe="registerPasskey-module__error___hGiqE";D(".registerPasskey-module__container___jqEh8{align-items:center;color:#fff;display:flex;justify-content:center;padding:1rem}.registerPasskey-module__card___MJAyC{background-color:#1f2937;border-radius:1rem;box-shadow:0 4px 20px rgba(0,0,0,.4);max-width:400px;padding:1.5rem;width:100%}.registerPasskey-module__loading___Q4i1x{align-items:center;background-color:#f9fafb;border-radius:.75rem;box-shadow:0 2px 8px rgba(0,0,0,.1);color:#374151;display:flex;font-weight:500;gap:.75rem;justify-content:center;padding:1.5rem}.registerPasskey-module__spinner___V1nhd{animation:registerPasskey-module__spin___oYcsC 1s linear infinite;border-color:#3b82f6 transparent;border-radius:9999px;border-style:solid;border-width:2px;height:1.5rem;width:1.5rem}@keyframes registerPasskey-module__spin___oYcsC{to{transform:rotate(1turn)}}.registerPasskey-module__supported___ihTih{background-color:#ecfdf5;border-radius:.75rem;box-shadow:0 2px 12px rgba(0,0,0,.1);color:#065f46;padding:1.25rem}.registerPasskey-module__title___vn2Qu{font-size:1.125rem;font-weight:600;margin-bottom:.5rem}.registerPasskey-module__description___AWmO-{margin-bottom:1rem}.registerPasskey-module__button___D3b4B{background-color:#059669;border:none;border-radius:.5rem;color:#fff;cursor:pointer;font-weight:500;padding:.75rem 1rem;transition:background-color .2s ease;width:100%}.registerPasskey-module__button___D3b4B:hover{background-color:#047857}.registerPasskey-module__message___RiOw-{font-size:.875rem;margin-top:1rem}.registerPasskey-module__success___HP5aX{color:#6ee7b7}.registerPasskey-module__error___hGiqE{color:#f87171}");var Ge="deviceNameModal-module__overlay___fmdPd",De="deviceNameModal-module__modal___uoEda",Je="deviceNameModal-module__description___-HMTA",Ve="deviceNameModal-module__input___4vQMI",We="deviceNameModal-module__actions___KXw7b",$e="deviceNameModal-module__primary___9Ozlk",Ke="deviceNameModal-module__secondary___HILhc";D(".deviceNameModal-module__overlay___fmdPd{align-items:center;background:rgba(0,0,0,.45);display:flex;inset:0;justify-content:center;position:fixed;z-index:1000}.deviceNameModal-module__modal___uoEda{background:#1f2937;border-radius:12px;box-shadow:0 20px 40px rgba(0,0,0,.15);color:#fff;max-width:420px;padding:24px;width:100%}.deviceNameModal-module__description___-HMTA{color:#fff;font-size:14px;margin-bottom:16px}.deviceNameModal-module__input___4vQMI{border:1px solid #ddd;border-radius:8px;font-size:14px;margin-bottom:20px;padding:10px 12px;width:100%}.deviceNameModal-module__actions___KXw7b{display:flex;gap:10px;justify-content:flex-end}.deviceNameModal-module__primary___9Ozlk{background:#2563eb;border:none;border-radius:8px;color:#fff;cursor:pointer;padding:8px 14px}.deviceNameModal-module__secondary___HILhc{background:transparent;border:1px solid #ccc;border-radius:8px;cursor:pointer;padding:8px 14px}");const He=({isOpen:t,onCancel:n,onConfirm:i})=>{const[r,a]=d("");return t?e("div",{className:Ge,children:o("div",{className:De,children:[e("h3",{children:"Name This Device"}),e("p",{className:Je,children:"Give this passkey a friendly name so you can recognize it later."}),e("input",{type:"text",placeholder:"e.g., MacBook Pro, iPhone, YubiKey",value:r,onChange:e=>a(e.target.value),className:Ve,autoFocus:!0}),o("div",{className:We,children:[e("button",{onClick:n,className:Ke,children:"Cancel"}),e("button",{onClick:()=>i(r.trim()),disabled:!r.trim(),className:$e,children:"Continue"})]})]})}):null},Ye=()=>{const{refreshSession:n}=q(),i=we(),{passkeySupported:r,loading:a}=Ne(),s=h(),[l,c]=d("idle"),[u,_]=d(""),[m,p]=d(!1),[g,f]=d(null);return o(t,{children:[e("div",{className:Ae,children:e("div",{className:Ie,children:o("div",a||!r?{className:Ee,children:[e("div",{className:ze}),e("span",{children:a?"Checking for Passkey Support...":"Passkeys are not supported on this device."})]}:{className:Le,children:[e("h2",{className:je,children:"Secure Your Account with a Passkey"}),e("p",{className:Fe,children:"Your device supports passkeys! Register one to skip passwords forever."}),e("button",{onClick:()=>{const{platform:e,browser:o,deviceInfo:t}=function(){const e=navigator.userAgent.toLowerCase();let o="unknown",t="unknown";return/iphone|ipad|ipod/.test(e)?o="ios":/android/.test(e)?o="android":/mac os/.test(e)?o="mac":/windows/.test(e)?o="windows":/linux/.test(e)&&(o="linux"),/chrome/.test(e)&&(t="chrome"),/safari/.test(e)&&!/chrome/.test(e)&&(t="safari"),/firefox/.test(e)&&(t="firefox"),/edg/.test(e)&&(t="edge"),{platform:o,browser:t,deviceInfo:`${o} • ${t}`}}();f({platform:e,browser:o,deviceInfo:t}),p(!0)},disabled:"loading"===l,className:Ue,children:"loading"===l?"Registering...":"Register Passkey"}),u&&e("p",{className:`${Be} ${"success"===l?Re:qe}`,children:u})]})})}),e(He,{isOpen:m,onCancel:()=>{p(!1),f(null)},onConfirm:async e=>{if(!g)return;const o={friendlyName:e,...g};c("loading");try{const e=await i.registerPasskey(o);if(!e.success)throw new Error(e.message);await n(),c("success"),_(e.message),s("/")}catch{console.error("Passkey registration failed."),c("error"),_("Error registering passkey.")}finally{p(!1),f(null)}}})]})};var Ze="verifyOTP-module__container___wgoDE",Qe="verifyOTP-module__card___3cs2p",Xe="verifyOTP-module__title___fZ-1d",eo="verifyOTP-module__subtitle___dGSu3",oo="verifyOTP-module__error___GEtlG",to="verifyOTP-module__success___46TjG",no="verifyOTP-module__form___jiGG-",io="verifyOTP-module__label___Zq5Mi",ro="verifyOTP-module__timer___smq-a",ao="verifyOTP-module__resend___PlmkG",so="verifyOTP-module__button___8pIuO",lo="verifyOTP-module__toggle___wbzVa";D(".verifyOTP-module__container___wgoDE{align-items:center;color:#fff;display:flex;justify-content:center;padding:1rem}.verifyOTP-module__card___3cs2p{background-color:#1f2937;border-radius:.5rem;box-shadow:0 0 10px rgba(0,0,0,.3);max-width:28rem;padding:1.5rem;width:100%}.verifyOTP-module__title___fZ-1d{color:#fff;font-size:1.5rem;font-weight:700;margin-bottom:1rem;text-align:center}.verifyOTP-module__subtitle___dGSu3{color:#9ca3af;font-size:.875rem;margin-bottom:1.5rem;text-align:center}.verifyOTP-module__error___GEtlG{color:#f87171;margin-bottom:1rem;text-align:center}.verifyOTP-module__success___46TjG{color:#34d399;margin-bottom:.75rem;text-align:center}.verifyOTP-module__form___jiGG-{display:flex;flex-direction:column;gap:1rem}.verifyOTP-module__label___Zq5Mi{color:#d1d5db;display:block;font-size:.875rem;margin-bottom:.25rem}.verifyOTP-module__timer___smq-a{color:#facc15;font-size:.875rem}.verifyOTP-module__input___yqIXM{background-color:#374151;border:1px solid #4b5563;border-radius:.375rem;color:#fff;outline:none;padding:.5rem;width:100%}.verifyOTP-module__input___yqIXM:focus{box-shadow:0 0 0 2px #3b82f6}.verifyOTP-module__resend___PlmkG{background:none;border:none;color:#60a5fa;cursor:pointer;font-size:.75rem;margin-top:.25rem;text-decoration:underline}.verifyOTP-module__resend___PlmkG:hover{color:#3b82f6}.verifyOTP-module__button___8pIuO{background-color:#2563eb;border:none;border-radius:.375rem;color:#fff;cursor:pointer;padding:.5rem;transition:background-color .2s;width:100%}.verifyOTP-module__button___8pIuO:hover{background-color:#1d4ed8}.verifyOTP-module__toggle___wbzVa{background:none;border:none;color:#60a5fa;cursor:pointer;font-size:.875rem;margin-top:1.5rem;text-align:center;width:100%}");var co="otpInput-module__otpContainer___MUjby",uo="otpInput-module__otpInput___3YMVm";D(".otpInput-module__otpContainer___MUjby{display:flex;gap:8px;justify-content:center;margin-top:8px}.otpInput-module__otpInput___3YMVm{background:#374151;border:1px solid #4b5563;border-radius:8px;color:#fff;font-size:1.2rem;height:48px;text-align:center;transition:border-color .15s ease,box-shadow .15s ease;width:42px}.otpInput-module__otpInput___3YMVm:focus{border-color:#60a5fa;box-shadow:0 0 0 2px rgba(96,165,250,.25);outline:none}");const _o=({length:o=6,value:t,inputMode:n="numeric",onChange:i,name:r="otp"})=>{const a=g([]),s=t.split("").concat(Array(o).fill("")).slice(0,o),l=(e,o)=>{var t;if(o.length>1)d(e,o);else if(!o||(t=o,"numeric"===n?/^\d$/.test(t):/^[a-zA-Z]$/.test(t))){const t=[...s];t[e]=o;const n=t.join("");i(n),o&&a.current[e+1]&&a.current[e+1]?.focus()}},d=(e,t)=>{let r=t;r="numeric"===n?t.replace(/\D/g,""):t.replace(/[^a-zA-Z]/g,"");const l=r.slice(0,o).split(""),d=[...s];l.forEach((t,n)=>{e+n<o&&(d[e+n]=t)}),i(d.join("")),a.current[Math.min(e+l.length,o-1)]?.focus()};return e("div",{className:co,role:"group","aria-label":"One-time password input",onPaste:e=>{e.preventDefault(),d(0,e.clipboardData.getData("text"))},children:s.map((t,d)=>e("input",{ref:e=>a.current[d]=e,type:"text",inputMode:"numeric"===n?"numeric":"text",autoComplete:"one-time-code",name:`${r}-${d}`,maxLength:1,value:t,className:uo,onChange:e=>l(d,e.target.value),onKeyDown:e=>((e,t)=>{if("Backspace"===t.key){t.preventDefault();const o=[...s];s[e]?(o[e]="",i(o.join(""))):e>0&&(o[e-1]="",i(o.join("")),a.current[e-1]?.focus())}"ArrowLeft"===t.key&&e>0&&a.current[e-1]?.focus(),"ArrowRight"===t.key&&e<o-1&&a.current[e+1]?.focus()})(d,e),"aria-label":`Digit ${d+1}`},d))})},mo=()=>{const t=h(),n=f(),{refreshSession:i}=q(),r="login"===n.state?.flow,[a,s]=d(""),[l,u]=d(null),[_,m]=d(""),[p,g]=d(!1),[y,b]=d(""),[k,v]=d(300),w=we(),x=async()=>{g(!0);try{if(!l){if((r?await w.verifyLoginPhoneOtp(a):await w.verifyPhoneOtp(a)).ok){if(r)return await i(),void t("/");u(!0)}else m("Verification failed.")}}catch{console.error("Phone OTP verification failed."),m("Verification failed.")}g(!1)},P=async()=>{b(""),await(async()=>{m(""),(r?await w.requestLoginPhoneOtp():await w.requestPhoneOtp()).ok?b("Verification SMS has been resent."):m("Failed to send SMS code. If this persists, refresh the page and try again.")})(),b("Verification SMS has been resent.")};return c(()=>{const e=setInterval(()=>{v(e=>e>0?e-1:0)},1e3);return()=>clearInterval(e)},[]),c(()=>{l&&!r&&(async()=>{(await w.requestEmailOtp()).ok?t("/verifyEmailOTP"):m("Failed to send Email code. If this persists, refresh the page and try registering again.")})()},[l,r,t,w]),e("div",{className:Ze,children:o("div",{className:Qe,children:[e("h2",{className:Xe,children:"Verify Your Phone Number"}),e("p",{className:eo,children:"Enter the code sent to your phone number."}),_&&e("p",{className:oo,children:_}),y&&e("p",{className:to,children:y}),o("form",{onSubmit:async e=>{if(e.preventDefault(),m(""),6===a.length){g(!0);try{await x()}catch{m("Unexpected error occurred.")}finally{g(!1)}}else m("Please enter a valid code.")},className:no,children:[o("div",{children:[o("label",{htmlFor:"phoneCode",className:io,children:["Phone Verification Code ",(S=l,!0===S?e("span",{className:"text-green-400 ml-2",children:"✅"}):!1===S?e("span",{className:"text-red-400 ml-2",children:"❌"}):null)," -"," ",o("span",{className:ro,children:["Code expires in: ",(N=k,`${Math.floor(N/60).toString().padStart(2,"0")}:${(N%60).toString().padStart(2,"0")}`)]})]}),e(_o,{length:6,value:a,onChange:s}),e("button",{type:"button",onClick:()=>P(),className:ao,children:"Resend code to phone"})]}),e("button",{type:"submit",className:so,children:p?"Verifying...":"Verify & Continue"}),e("button",{type:"button",onClick:()=>t("/login"),className:lo,children:"Back to login"})]})]})});var N,S},po=()=>{const t=h(),n=f(),{refreshSession:i}=q(),r=we(),{passkeySupported:a}=Ne(),s="login"===n.state?.flow,[l,u]=d(!1),[_,m]=d(""),[p,g]=d(300),[y,b]=d(""),[k,v]=d("");return c(()=>{const e=setInterval(()=>{g(e=>e>0?e-1:0)},1e3);return()=>clearInterval(e)},[]),e("div",{className:Ze,children:o("div",{className:Qe,children:[e("h2",{className:Xe,children:"Verify Your Email"}),e("p",{className:eo,children:"We sent you a verification email. Enter the code below."}),y&&e("p",{className:oo,children:y}),k&&e("p",{className:to,children:k}),o("form",{onSubmit:async e=>{if(e.preventDefault(),b(""),6===_.length){u(!0);try{if(!(s?await r.verifyLoginEmailOtp(_):await r.verifyEmailOtp(_)).ok)return void b("Verification failed.");if(s)return await i(),void t("/");a?t("/registerPasskey"):(await i(),t("/"))}catch{console.error("Email OTP verification failed."),b("Verification failed.")}finally{u(!1)}}else b("Please enter a valid code.")},className:no,children:[o("div",{children:[o("label",{htmlFor:"emailCode",className:io,children:["Email Verification Code",o("span",{className:ro,children:[" ","— Code expires in ",(w=p,`${Math.floor(w/60).toString().padStart(2,"0")}:${(w%60).toString().padStart(2,"0")}`)]})]}),e(_o,{length:6,value:_,onChange:m,inputMode:"text"}),e("button",{type:"button",onClick:async()=>{b(""),v("");(s?await r.requestLoginEmailOtp():await r.requestEmailOtp()).ok?v("Verification email has been resent."):b("Failed to send Email code. If this persists, refresh the page and try again.")},className:ao,children:"Resend code to email"})]}),e("button",{type:"submit",className:so,disabled:l,children:l?"Verifying...":"Verify & Continue"}),e("button",{type:"button",onClick:()=>t("/login"),className:lo,children:"Back to login"})]})]})});var w};var go={container:"verifyMagiclink-module__container___qrSXf",card:"verifyMagiclink-module__card___niKgr",title:"verifyMagiclink-module__title___SumxD",verificationContent:"verifyMagiclink-module__verificationContent___NdsS0",spinner:"verifyMagiclink-module__spinner___lnW1k",successIcon:"verifyMagiclink-module__successIcon___XjFEM",checkIcon:"verifyMagiclink-module__checkIcon___I0JOP",successText:"verifyMagiclink-module__successText___lO5Qq"};D(".verifyMagiclink-module__container___qrSXf{align-items:center;color:#fff;display:flex;justify-content:center;padding:1rem}.verifyMagiclink-module__card___niKgr{background-color:#1f2937;border-radius:.5rem;box-shadow:0 0 10px rgba(0,0,0,.3);max-width:28rem;padding:1.5rem;width:100%}.verifyMagiclink-module__title___SumxD{color:#fff;font-size:1.5rem;font-weight:700;margin-bottom:1rem;text-align:center}.verifyMagiclink-module__verificationContent___NdsS0{align-items:center;display:flex;flex-direction:column;gap:14px;margin:20px 0}.verifyMagiclink-module__spinner___lnW1k{animation:verifyMagiclink-module__spin___2lGzj .9s linear infinite;border:3px solid hsla(0,0%,100%,.15);border-radius:50%;border-top-color:#60a5fa;height:28px;width:28px}.verifyMagiclink-module__successIcon___XjFEM{align-items:center;background:rgba(16,185,129,.15);border-radius:50%;display:flex;height:36px;justify-content:center;width:36px}.verifyMagiclink-module__checkIcon___I0JOP{animation:verifyMagiclink-module__checkPop___-3qJu .25s ease-out;color:#34d399;height:22px;width:22px}.verifyMagiclink-module__successText___lO5Qq{color:#34d399;font-size:.9rem}@keyframes verifyMagiclink-module__checkPop___-3qJu{0%{opacity:0;transform:scale(.6)}80%{transform:scale(1.15)}to{opacity:1;transform:scale(1)}}@keyframes verifyMagiclink-module__spin___2lGzj{to{transform:rotate(1turn)}}");const ho=()=>{const[t]=y(),n=h(),i=t.get("token"),[r,a]=d(""),[s,l]=d(""),u=we();return c(()=>{let e=!0,o=null,t=null;return(async()=>{if(!i)return e&&a("Missing token for verification."),void console.error("No magic-link token found.");try{if(!(await u.verifyMagicLink(i)).ok)return console.error("Failed to verify token"),void(e&&a("Failed to verify token"))}catch{console.error("Failed to verify magic-link token.")}e&&(o=new BroadcastChannel("seamless-auth"),o.postMessage({type:"MAGIC_LINK_AUTH_SUCCESS"}),l("You have been verified on the device and browser that initiated this request"),t=setTimeout(()=>{e&&n("/")},900))})(),()=>{e=!1,o?.close(),t&&clearTimeout(t)}},[i,u,n]),e("div",{className:go.container,children:o("div",{className:go.card,children:[e("h1",{className:go.title,children:"Verifying your login"}),o("div",{className:go.verificationContent,children:[!s&&!r&&e("div",{className:go.spinner}),s&&e("div",{className:go.successIcon,children:e("svg",{viewBox:"0 0 24 24",className:go.checkIcon,fill:"none",stroke:"currentColor",strokeWidth:"2",children:e("path",{d:"M5 13l4 4L19 7"})})}),!s&&!r&&e("p",{className:go.helperText,children:"Please wait while we securely verify your sign-in link."}),s&&e("p",{className:go.successText,children:"Login verified. Redirecting…"}),r&&e("p",{className:go.error,children:r})]})]})})};var fo="magiclink-module__container___45zcA",yo="magiclink-module__card___Au9oN",bo="magiclink-module__iconWrapper___k5ndr",ko="magiclink-module__mailIcon___Pwb7q",vo="magiclink-module__iconRing___bdLvf",wo="magiclink-module__heading___b9cre",xo="magiclink-module__message___kiVFj",Po="magiclink-module__identifier___JtcFM",No="magiclink-module__helperText___7Mlfh",So="magiclink-module__actions___64I-3",Oo="magiclink-module__secondaryButton___BntAI",Co="magiclink-module__cooldown___Ib4rm",To="magiclink-module__linkButton___maJiv";D(".magiclink-module__container___45zcA{align-items:center;color:#fff;display:flex;justify-content:center}.magiclink-module__card___Au9oN{background-color:#1f2937;border-radius:.75rem;box-shadow:0 10px 25px rgba(0,0,0,.25);max-width:420px;padding:2.5rem 2rem;text-align:center;width:100%}.magiclink-module__iconWrapper___k5ndr{display:flex;justify-content:center;margin-bottom:1.25rem;position:relative}.magiclink-module__mailIcon___Pwb7q{color:#a5b4fc;height:38px;width:38px;z-index:2}.magiclink-module__iconRing___bdLvf{animation:magiclink-module__pulse___YGm-I 2s infinite;background:rgba(99,102,241,.15);border-radius:50%;height:72px;position:absolute;width:72px}@keyframes magiclink-module__pulse___YGm-I{0%{opacity:.8;transform:scale(.6)}70%{opacity:0;transform:scale(1.4)}to{opacity:0}}.magiclink-module__heading___b9cre{font-size:1.55rem;font-weight:600;margin-bottom:.75rem}.magiclink-module__message___kiVFj{color:#d1d5db;font-size:.95rem;line-height:1.4;margin-bottom:1rem}.magiclink-module__identifier___JtcFM{background:hsla(0,0%,100%,.05);border-radius:6px;display:inline-block;font-size:1rem;font-weight:600;margin-bottom:1rem;padding:.45rem .6rem}.magiclink-module__helperText___7Mlfh{color:#9ca3af;font-size:.85rem;line-height:1.4;margin-bottom:.6rem}.magiclink-module__actions___64I-3{display:flex;flex-direction:column;gap:.6rem;margin-top:1.6rem}.magiclink-module__secondaryButton___BntAI{background:#111827;border:1px solid #374151;border-radius:8px;color:#fff;cursor:pointer;font-weight:500;padding:.65rem}.magiclink-module__secondaryButton___BntAI:hover:not(:disabled){background:#1f2937}.magiclink-module__secondaryButton___BntAI:disabled{cursor:not-allowed;opacity:.5}.magiclink-module__cooldown___Ib4rm{color:#9ca3af;font-size:.8rem}.magiclink-module__linkButton___maJiv{background:none;border:none;color:#a5b4fc;cursor:pointer;font-size:.85rem;margin-top:.4rem}.magiclink-module__linkButton___maJiv:hover{text-decoration:underline}");const Mo=()=>{const{refreshSession:t}=q(),n=h(),i=f(),r=we(),a=i.state?.identifier,[s,l]=d(30);c(()=>{const e=setInterval(()=>{l(e=>e>0?e-1:0)},1e3);return()=>clearInterval(e)},[]);return c(()=>{const e=new BroadcastChannel("seamless-auth");return e.onmessage=async e=>{if("MAGIC_LINK_AUTH_SUCCESS"===e.data?.type){200===(await r.checkMagicLink()).status&&(await t(),n("/"))}},()=>{e.close()}},[r,n,t]),c(()=>{const e=setInterval(async()=>{try{200===(await r.checkMagicLink()).status&&(await t(),n("/"))}catch{}},5e3);return()=>clearInterval(e)},[r,t,n]),e("div",{className:fo,children:o("div",{className:yo,children:[o("div",{className:bo,children:[e("div",{className:vo}),o("svg",{className:ko,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.8",children:[e("path",{d:"M4 6h16v12H4z"}),e("path",{d:"m4 6 8 6 8-6"})]})]}),e("h2",{className:wo,children:"Check your email"}),e("p",{className:xo,children:"If an account exists for this address, we sent a secure sign-in link."}),a&&e("div",{className:Po,children:a}),e("p",{className:No,children:"Open the email and click the link to finish signing in."}),e("p",{className:No,children:"Didn’t receive anything? Check your spam folder or try creating a new account."}),o("div",{className:So,children:[e("button",{className:Oo,disabled:s>0,onClick:async()=>{s>0||(await r.requestMagicLink(),l(30))},children:"Resend link"}),s>0&&o("div",{className:Co,children:["Available in ",s,"s"]}),e("button",{className:To,onClick:()=>n("/login"),children:"Change email or phone"})]})]})})},Ao=()=>o(b,{children:[e(k,{path:"/login",element:e(Ce,{})}),e(k,{path:"/passKeyLogin",element:e(Me,{})}),e(k,{path:"/verifyPhoneOTP",element:e(mo,{})}),e(k,{path:"/verifyEmailOTP",element:e(po,{})}),e(k,{path:"/verify-magiclink",element:e(ho,{})}),e(k,{path:"/registerPasskey",element:e(Ye,{})}),e(k,{path:"/magiclinks-sent",element:e(Mo,{})}),e(k,{path:"*",element:e(v,{to:"/login",replace:!0})})]});export{G as AuthProvider,Ao as AuthRoutes,F as createSeamlessAuthClient,S as encodePrfSalt,A as extractPasskeyPrfResult,B as hasScopedRole,T as isPasskeyPrfSupported,U as roleGrantsAccess,q as useAuth,we as useAuthClient,Ne as usePasskeySupport};
|
|
2
2
|
//# sourceMappingURL=index.js.map
|