@passflow/react 0.15.1 → 0.17.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 +39 -0
- package/README.md +94 -12
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.es.js +133 -143
- package/dist/index.es.js.map +1 -1
- package/dist/src/components/flow/index.d.cts +1 -1
- package/dist/src/components/flow/index.d.ts +1 -1
- package/dist/src/components/flow/index.d.ts.map +1 -1
- package/dist/src/components/flow/passflow/flow-router.d.cts +39 -0
- package/dist/src/components/flow/passflow/flow-router.d.ts +39 -0
- package/dist/src/components/flow/passflow/flow-router.d.ts.map +1 -0
- package/dist/src/components/flow/passflow/index.d.cts +25 -3
- package/dist/src/components/flow/passflow/index.d.ts +25 -3
- package/dist/src/components/flow/passflow/index.d.ts.map +1 -1
- package/dist/src/components/flow/two-factor-setup-magic-link/index.d.cts +6 -1
- package/dist/src/components/flow/two-factor-setup-magic-link/index.d.ts +6 -1
- package/dist/src/components/flow/two-factor-setup-magic-link/index.d.ts.map +1 -1
- package/dist/src/components/form/forgot-password/forgot-password.d.ts.map +1 -1
- package/dist/src/components/form/invitation-join/index.d.ts.map +1 -1
- package/dist/src/components/form/signin/index.d.ts.map +1 -1
- package/dist/src/components/form/signup/index.d.ts.map +1 -1
- package/dist/src/components/provider/passflow-provider.d.ts.map +1 -1
- package/dist/src/components/provider/use-dispose-on-replace.d.cts +17 -0
- package/dist/src/components/provider/use-dispose-on-replace.d.ts +17 -0
- package/dist/src/components/provider/use-dispose-on-replace.d.ts.map +1 -0
- package/dist/src/context/auth-context.d.cts +5 -4
- package/dist/src/context/auth-context.d.ts +5 -4
- package/dist/src/context/auth-context.d.ts.map +1 -1
- package/dist/src/context/index.d.cts +1 -0
- package/dist/src/context/index.d.ts +1 -0
- package/dist/src/context/index.d.ts.map +1 -1
- package/dist/src/context/search-context.d.cts +20 -0
- package/dist/src/context/search-context.d.ts +20 -0
- package/dist/src/context/search-context.d.ts.map +1 -0
- package/dist/src/hooks/index.d.cts +2 -1
- package/dist/src/hooks/index.d.ts +2 -1
- package/dist/src/hooks/index.d.ts.map +1 -1
- package/dist/src/hooks/use-refresh-status.d.cts +36 -0
- package/dist/src/hooks/use-refresh-status.d.ts +36 -0
- package/dist/src/hooks/use-refresh-status.d.ts.map +1 -0
- package/dist/src/hooks/use-session-expired.d.cts +8 -4
- package/dist/src/hooks/use-session-expired.d.ts +8 -4
- package/dist/src/hooks/use-session-expired.d.ts.map +1 -1
- package/dist/src/utils/url-params.d.cts +2 -4
- package/dist/src/utils/url-params.d.ts +2 -4
- package/dist/src/utils/url-params.d.ts.map +1 -1
- package/package.json +6 -5
package/dist/index.es.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.es.js","names":["_Fragment","flags","_Fragment","error","error","error","error","err","err","passflowWithMagicLink","error","error","_Fragment","logoRed","eyeOn","eyeOff","caretDown","onePassword","browserChrome","dotsVertical","linkedin","initialValues","validationError","_Fragment","_Fragment","_Fragment","Wrapper","Dialog","completionOptions","Wrapper","Wrapper","_Fragment","initialValues","queryString","Wrapper","_Fragment","Wrapper","Wrapper","queryString","queryString","challengeTypeFullString","Wrapper","Wrapper","Wrapper","Wrapper","FETCH_PRIORITY_OIDC","Passflow","PassflowEvent","classifyUpgradeError","parseToken","registerFetchMiddleware","requiredAcrLevel","React","createContext","forwardRef","useCallback","useContext","useEffect","useId","useLayoutEffect","useMemo","useReducer","useRef","useState","clsx","Yup","Fragment","jsx","jsxs","DialogPrimitive","OTPInput","REGEXP_ONLY_DIGITS","REGEXP_ONLY_DIGITS_AND_CHARS","getCountryForTimezone","defaultCountries","parseCountry","usePhoneInput","qs","phone","Controller","useForm","PopoverPrimitive","ErrorBoundary","BrowserRouter","HashRouter","MemoryRouter","Navigate","Route","Routes","useInRouterContext","useLocation","useNavigate","useParams","from","window","passflowReactAppVersion","console","log","AUTH_ERROR_COPY","password","message","scope","passwordless","passkey","authRedirectErrorMessage","verificationLinkErrorMessage","verificationRequestErrorMessage","authErrorFor","flow","operation","DEVICE_ERROR_COPY","code_required","code_invalid","code_expired","code_declined","code_already_approved","too_many_attempts","mode_disabled","app_unavailable","bad_credentials","missing_credentials","second_factor_invalid","missing_second_factor","account_blocked","passkey_failed","passkey_unsupported","offline","generic","RECOVERABLE","Set","REASON_TO_TYPE","invalid_user_code","unknown_user_code","expired_user_code","denied","already_approved","unknown_client","passkey_unavailable","unavailable","blocked","WEBAUTHN_NAME_TO_TYPE","NotAllowedError","AbortError","TimeoutError","UnknownError","NotSupportedError","InvalidStateError","ConstraintError","SecurityError","UNSUPPORTED_MESSAGE_PATTERNS","DeviceApiError","Error","reason","code","status","constructor","params","super","description","this","name","build","type","detail","isRecoverable","has","classifyDeviceError","err","isDOMExceptionLike","raw","lowered","toLowerCase","some","p","includes","byName","deviceErrorOfType","ERROR_PATTERNS","expired","not_enabled","invalid_code","getUserFriendlyErrorMessage","error","cn","classes","getAuthMethods","strategies","methods","internal","username","email","otp","magicLink","fim","providers","hasEmailMethods","hasSignInEmailMethods","hasPhoneMethods","hasSignInPhoneMethods","hasUsernameMethods","hasSignInUsernameMethods","strategy","identity","challenge","fim_type","fimType","push","getIdentityLabel","getPasswordlessData","currentMethod","label","challengeType","getUrlErrors","subUrl","searchParams","URLSearchParams","split","location","search","get","decodeURIComponent","getUrlWithTokens","async","passflow","url","format","tokens","getTokens","scopes","tokenParams","Object","entries","filter","_","value","map","key","encodeURIComponent","join","undefinedOnCatch","fn","t","authAction","title","completion","getInvitationAuthChrome","inviteToken","intent","invitation","tenantName","tenant_name","trim","inviterName","inviter_name","action","subtitle","routeToSecondFactor","navigate","twoFactorVerifyPath","isTwoFactorVerificationRequired","to","urlCarriesTwoFactorToken","hash","substring","STORAGE_KEY_PREFIX","REDIRECT_COUNT_KEY","LAST_ERROR_KEY","TwoFactorLoopPrevention","canRedirect","getRedirectCount","incrementRedirect","count","sessionStorage","setItem","String","getItem","Number","parseInt","reset","removeItem","setLastErrorType","errorType","getLastErrorType","isRepeatingError","getLoopDetectedMessage","activeInstance","pendingRelease","registerUpgradeAuthInstance","instance","queueMicrotask","releaseUpgradeAuthInstance","requireInstance","withAuth","next","attachAuth","useUrlParams","defaultValues","decodedSearch","input","DOMParser","parseFromString","documentElement","textContent","hasChanged","set","newUrl","pathname","toString","history","replaceState","getAll","newSearchParams","delete","pushState","isValidUrl","URL","protocol","emailRegex","passwordValidation","passwordPolicy","string","required","test","errors","min_password_length","minPasswordLength","require_lowercase","requireLowerCase","require_number","requireNumber","require_symbol","requireSymbol","require_uppercase","requireUpperCase","length","validationError","inner","path","field","ValidationError","Ripple","size","x","y","className","style","width","height","left","top","Button","variant","onClick","withIcon","asIcon","children","withRipple","pressed","rest","ripples","setRipples","styles","timer","setTimeout","clearTimeout","e","rect","currentTarget","getBoundingClientRect","rippleSize","Math","max","clientX","clientY","newRipple","Date","now","prev","ContinuingStatus","appName","role","COUNTRY_FLAG_POSITIONS","ad","ae","af","ag","ai","al","am","an","ao","aq","ar","as","at","au","aw","ax","az","ba","bb","bd","be","bf","bg","bh","bi","bj","bl","bm","bn","bo","br","bs","bt","bw","by","bz","ca","cc","cd","cf","cg","ch","ci","ck","cl","cm","co","cr","cu","cv","cw","cx","cy","cz","de","dj","dk","dm","do","dz","ec","ee","eg","eh","er","es","et","eu","fi","fj","fk","fm","fo","fr","ga","gb","gd","ge","gg","gh","gi","gl","gm","gn","gq","gr","gs","gt","gu","gw","gy","hk","hn","hr","ht","hu","ic","id","ie","il","im","in","iq","ir","is","it","je","jm","jo","jp","ke","kg","kh","ki","xk","km","kn","kp","kr","kw","ky","kz","la","lb","lc","li","lk","lr","ls","lt","lu","lv","ly","ma","mc","md","me","mf","mg","mh","mk","ml","mm","mn","mo","mp","mq","mr","ms","mt","mu","mv","mw","mx","my","mz","na","nc","ne","nf","ng","ni","nl","no","np","nr","nu","nz","om","pa","pe","pf","pg","ph","pk","pl","pn","pr","ps","pt","pw","py","qa","ro","rs","ru","rw","sa","sb","sc","sd","se","sg","sh","si","sk","sl","sm","sn","so","sr","ss","st","sv","sy","sz","tc","td","tf","tg","th","tj","tk","tl","tm","tn","tr","tt","tv","tw","tz","ua","ug","us","uy","uz","va","vc","ve","vg","vi","vn","vu","wf","ws","ye","za","zm","zw","COUNTRY_FLAG_ALIASES","bq","gf","gp","io","pm","re","yt","CountryFlag","iso2","country","normalized","candidate","getSupportedCountry","slice","toUpperCase","backgroundImage","backgroundPosition","Dialog","Root","DialogTrigger","Trigger","DialogPortal","Portal","DialogClose","Close","DialogOverlay","props","ref","Overlay","displayName","DialogContent","Content","DialogHeader","DialogFooter","DialogTitle","Title","DialogDescription","Description","CHARSETS","numeric","pattern","inputMode","alphanumeric","Slot","char","isActive","hasFakeCaret","state","FieldOtp","onChange","onComplete","charset","labelledBy","describedBy","autoFocus","maxLength","autoComplete","disabled","noScriptCSSFallback","containerClassName","render","slots","slot","position","htmlFor","generateMessage","requires","requiresString","requirements","keys","Intl","ListFormat","requirement","FieldPassword","withMessages","validationErrors","isError","isShowPassword","setIsShowPassword","errorStyles","fields","changeIcon","handleShowPassword","Icon","decorative","usePassflow","context","PassflowContext","AuthContext","AuthProvider","onSessionExpired","isLoading","setIsLoading","isSessionExpired","setIsSessionExpired","subscriber","onAuthChange","eventType","payload","SessionExpired","SignIn","Register","subscribe","unsubscribe","isAuthenticated","doRefresh","parsedTokens","getParsedTokens","logout","logOut","Provider","defaultNavigate","replace","searchParam","startsWith","href","NavigationContext","setNavigate","router","initialState","appSettings","appId","createTenantForNewUser","parseQueryParams","isDiscoveringAppId","hasSettingsError","passflowReducer","routes","signin","signup","verify_otp","verify_magic_link","forgot_password","forgot_password_success","reset_password","two_factor_verify","two_factor_recovery","two_factor_setup","two_factor_setup_magic_link","UpgradeContext","noop","INERT_UPGRADE_CONTEXT","enabled","prompt","selectedFactor","selectFactor","submit","cancel","dismiss","elevate","Promise","resolve","nonEmpty","getBackgroundImage","image","applyLoginThemeStyles","root","property","primary_color","text_color","content_color","secondary_text_color","background_color","background_image","card_color","input_background_color","input_border_color","button_text_color","passkey_button_text_color","passkey_button_background_color","divider_color","federated_button_background_color","federated_button_text_color","getLoginThemeCssVariables","removeProperty","setProperty","useAppSettings","setIsError","errorMessage","setErrorMessage","isFetchingRef","dispatch","current","urlsToTry","response","r","fetch","ok","settings","json","discoveredAppId","login_app","app_id","setAppId","stateUpdates","discoveredScopes","createTenant","create_tenant_for_new_user","discoveryError","warn","getAppSettings","finalStateUpdates","defaults","auth_strategies","getPasswordPolicySettings","fetchAllSettings","currentTheme","theme","matchMedia","matches","login_app_theme","color_scheme","getCurrentTheme","selectedStyle","dark_style","light_style","document","loginAppTheme","currentStyles","useAuth","useAuthCloudRedirect","cloudPassflowUrl","authRedirect","readParentChallengeId","requestPath","parentChallengeId","useConsent","setStatus","info","setInfo","granted","setGranted","setError","cancelled","res","method","credentials","headers","Accept","body","catch","error_description","data","requested_scopes","fetchInfo","toggleScope","add","decide","decision","base","endpoint","granted_scopes","csrf_token","JSON","stringify","errBody","kind","form","createElement","display","appendChild","submitFormPost","allow","deny","metadataByScope","Map","scope_metadata","meta","scopeMetadata","grantedScopes","DEVICE_ENDPOINTS","SECOND_FACTOR_METHODS","parseDeviceResponse","useDeviceVerify","setEmail","userCode","setUserCode","ticketRef","firstFactorTicketRef","approveAfterSecondFactorRef","secondFactorMethods","setSecondFactorMethods","activeRef","csrf","post","user_code","fail","terminal","classified","loadInfo","submitCode","holdTicket","second_factor_required","approval_ticket","known","m","toSecondFactorMethods","second_factor_methods","authenticatePassword","emailValue","owesSecondFactor","authenticatePasskey","PublicKeyCredential","DOMException","start","startAuthentication","assertion","optionsJSON","publicKey","passkey_challenge_id","passkey_data","approveWithTicket","signInWithPassword","signInWithPasskey","approve","confirmWithPassword","confirmWithPasskey","submitSecondFactor","clearError","isSecondFactorPending","useForgotPassword","sendPasswordResetEmail","useJoinInvite","token","joinInvitation","useLogout","parseSearch","parsed","parse","fromEntries","useNavigation","setTwoFactorVerifyPath","newNavigate","options","searchParamDefault","useOutsideClick","onClickOutside","handleClick","event","contains","target","addEventListener","removeEventListener","usePasswordlessComplete","passwordlessSignInComplete","getFullRedirectUrl","redirectUrl","origin","useProvider","redirect_url","create_tenant","federatedWithPopup","provider","federatedAuthWithPopup","invite_token","federatedWithRedirect","federatedAuthWithRedirect","useResetPassword","newPassword","resetPassword","useSessionExpired","expiredReason","setExpiredReason","resetSessionExpired","useSignIn","signIn","passwordlessSignIn","passkeyAuthenticate","useSignUp","cleanup","signUp","passwordlessResponse","passkeyRegister","useTrustedDevices","setData","devices","getTrustedDevices","revoke","deviceId","revokeTrustedDevice","device","refetch","useTwoFactorChallenge","setChallenge","selectedMethod","setSelectedMethod","requestChallenge","firstFactorMethod","twoFactor","first_factor_method","verify","trustDevice","challenge_id","verifyV2","trust_device","switchMethod","switchToAlternative","useTwoFactorManage","recoveryCodes","setRecoveryCodes","disable","disableTwoFactor","regenerateCodes","regenerateTwoFactorRecoveryCodes","recovery_codes","useTwoFactorMethods","availableMethods","setAvailableMethods","registeredMethods","setRegisteredMethods","refresh","getRegisteredMethods","available","removeMethod","methodId","useTwoFactorSetup","setupData","setSetupData","step","setStep","beginSetup","beginTwoFactorSetup","confirmSetup","confirmTwoFactorSetup","useTwoFactorSetupMagicLink","isRetrying","setIsRetrying","isValidated","setIsValidated","sessionToken","setSessionToken","userId","setUserId","expiresIn","setExpiresIn","retryCountdown","setRetryCountdown","validatedToken","setValidatedToken","shouldClearOnUnmount","countdownTimerRef","startCountdown","seconds","clearInterval","setInterval","validateToken","isRetry","validateTwoFactorSetupMagicLink","success","retryAfter","retry","clearMagicLinkSession","useTwoFactorStatus","getTwoFactorStatus","useTwoFactorVerify","setErrorType","errorDetails","setErrorDetails","isVerificationRequired","handleError","normalizedMessage","shouldAutoRedirect","classifyTwoFactorError","verifyTwoFactor","useRecoveryCode","useTwoFactorRecoveryCode","EMPTY_FACTORS","useUpgrade","factors","readPromptFactors","factorTypes","factor","insufficient","obtained","errorKind","previousError","busy","useUserPasskeys","getUserPasskeys","createUserPasskey","relyingPartyId","passkeyUsername","passkeyDisplayName","addUserPasskey","editUserPasskey","newName","passkeyId","renameUserPasskey","userPasskeys","deleteUserPasskey","FieldPhone","inputProps","show","setShow","filterValue","setFilterValue","isFocused","setIsFocused","refWrapper","searchInputRef","focus","userTZ","DateTimeFormat","resolvedOptions","timeZone","userCountry","inputValue","setCountry","handlePhoneValueChange","inputRef","defaultCountry","toLocaleLowerCase","filteredCountries","defCountry","countryName","preferredCountries","allCountries","preferredIso","handleClose","restoreFocus","querySelector","handleChangeCountry","renderCountry","dialCode","tabIndex","onKeyDown","preventDefault","Array","querySelectorAll","currentIndex","indexOf","min","handleOptionKeyDown","onFocus","onBlur","placeholder","FieldText","linkedin_default","matchTextColor","icons","general","logo","warning","mail","edit","close","check","trash","google","gitlab","apple","atlassian","bitbucket","discord","dropbox","facebook","github","hubspot","linear","linkedin","linledin","microsoft","notion","slack","tiktok","twitch","twitter","xero","src","alt","Link","LoginAlert","LoginDivider","LoginActionStack","LoginProgress","LoginScreenNotice","codeTestId","appNameTestId","LoginCodeEntry","initialCode","submitLabel","testId","onSubmit","setCode","normalizedCode","autoCapitalize","autoCorrect","spellCheck","Boolean","Switch","checked","generatedId","inputId","LoginConsent","allowLabel","denyLabel","busyLabel","allowTestId","denyTestId","onToggleScope","onAllow","onDeny","item","ProvidersBox","initialValues$2","email_or_username","LoginCredentials","computedDefaultMethod","initialMethod","identities","getDefaultMethod","defaultMethod","setDefaultMethod","passkeyOnly","setPasskeyOnly","forcePasskey","previousComputedMethod","previousForcePasskey","control","getValues","trigger","watch","formState","isDirty","isValid","handleSubmit","mode","nextForcePasskey","currentIdentity","find","hasPassword","hasPasswordless","passwordlessLabel","hasPasskey","hasIdentity","showCredentialFields","showStandalonePasskey","hasCredentialActions","controlsDisabled","errorScope","hasIdentityError","hasPasswordError","isNewPassword","credentialPurpose","toCredentials","values","emailOrUsername","handleReset","onReset","handleMethodChange","submitCurrentMethod","onPassword","onPasswordless","selectedIdentityValue","alternateIdentity","notice","allowPasskeyToggle","handlePasskeyExperienceChange","primaryLabel","selectLabel","rules","requiredMessage","validate","forgotPassword","getSearch","validateSync","primaryTestId","submitPasswordless","passwordlessLabelPrefix","onPasskey","passkeyLabel","footer","onProvider","LoginDeviceApproval","actionLabel","actionTestId","onApprove","LoginGeneralError","onAction","LoginInvitation","acceptLabel","switchAccountLabel","createAccountLabel","acceptTestId","onAccept","onSwitchAccount","onCreateAccount","LoginPasskeyProgress","working","recoverable","retryLabel","onRetry","METHOD_COPY","totp","hint","switchLabel","LoginSecondFactor","onMethodChange","setMethod","alternate","copy","isTOTP","LoginScreenShell","iconId","customCss","customLogo","customLogoAlt","removeBranding","LoginStatus","tone","primaryAction","LoginScreen","chrome","content","Popover","PopoverTrigger","PopoverAnchor","Anchor","PopoverContent","align","sideOffset","Spinner","UpgradeFactorList","selected","onSelect","CODE_FIELD_ID","CODE_ERROR_ID","UpgradeChallengeView","showAlternatives","cancelLabel","alternativesLabel","onSelectFactor","onToggleAlternatives","onCancel","reported","active","codeContract","needsCode","hasAlternatives","report","trimmed","noValidate","DEFAULT_FACTOR_LABELS","email_otp","sms_otp","OTP_CODE_CONTRACT","freeze","UPGRADE_FACTOR_CODE_CONTRACTS","toDialogFactors","labels","fallback","override","readString","readRecord","DIALOG_KIND_BY_UPGRADE_KIND","wrong_code","challenge_spent","not_registered","prepare_not_required","exhausted","attempts_exhausted","session_changed","fatal","network","upgradeKindOf","record","tagged","hasOwn","hasTransportFacts","dialogOutcomeFromError","readAssuranceBar","bar","acrValues","level","maxAge","describeAssuranceBar","parts","challengeBar","requiredLevel","terminalFromError","handlers","onDismiss","retryable","toDialogState","outcome","ui","previousKind","suggested","upgradeDialogDismissHandler","TONE","unsatisfiable","transport","BarRow","term","UpgradeStatus","autoClose","autoCloseMs","autoDismiss","dismissLabel","DESCRIPTION_ID","UpgradeDialog","open","onOpenChange","ConsentFlow","screen","consent","app_name","client_id","app_logo_url","getConsentLoginScreenProps","toCredentialsError","getDeviceLoginScreenProps","authenticated","getDeviceLoginMethods","deviceNotice","DeviceVerifyFlow","attemptedPasskeyChallenge","challengeKey","isAutomaticPasskeyReady","TwoFactorSetupForm","numInputs","showSecret","setShowSecret","otpId","otpLabelId","otpErrorId","totpDigits","qr_code","secret","recoveryCode","navigator","clipboard","writeText","TwoFactorSetupFlow","signInPath","shouldBlockRender","setShouldBlockRender","methodLabels","push_fcm","push_webpush","methodIcons","MethodSelector","onSelectMethod","isOpen","onClose","handleSelect","asChild","TwoFactorChallenge","onSuccess","onError","otpValue","setOtpValue","isMethodSelectorOpen","setIsMethodSelectorOpen","handleVerify","handleOtpChange","then","result","alternative_methods","code_sent_to","renderChallengeInput","TwoFactorRecoveryForm","onBack","trustDeviceLabel","setTrustDevice","handleBackToSignIn","isLoopDetected","isInputDisabled","completionOptions$1","completionOptions","TwoFactorVerifyForm","onUseRecovery","shouldAutoFocus","twoFactorSetupPath","computedSubtitle","handleSetup2FA","handleChange","errorStateOf","summaryError","summary","proof","factorsSignature","replaySignature","replay","maxBodyBytes","allowStreamingBody","UpgradeProvider","backend","interceptFetch","requireChallengeChannel","shouldIntercept","onUpgradeDiagnostic","maxAttempts","renderDialog","setPrompt","setState","setSelectedFactor","setBusy","setShowAlternatives","setOutcome","installed","setInstalled","resolveRef","requestRef","reportedSelectionRef","userCancelledRef","cancelRequestedRef","shouldInterceptRef","diagnosticRef","factorsRef","replayRef","replayPredicate","policy","settlePrompt","clearPromptView","promptHandler","request","onRequirementRaised","f","handleFlightSettled","summaryToState","summaryToOutcome","teardown","upgrade","enable","d","onFlightSettled","isArray","events","SignOut","onFactorSelected","toggleAlternatives","shown","requested","statedBar","waiter","channels","imperativeChallenge","asError","dialogState","dialogProps","AUTH_ENDPOINT_PATTERN","readParentChallengeIdFromURL","bootParentChallengeId","oidcRedirectFollowed","hasFollowedOIDCRedirect","useOIDCInterceptor","isAuthURL","injectParentChallenge","obj","parent_challenge_id","followRedirectURL","assign","unregisterFetchMiddleware","init","Request","outInit","rewritten","text","clone","priority","OriginalXHROpen","XMLHttpRequest","prototype","OriginalXHRSend","send","tracker","WeakMap","urlStr","isAuth","responseText","call","outBody","useSessionExchangeOnMount","baseUrl","exchangeState","setExchangeState","parentMeta","setParentMeta","attemptedRef","oidc_prompt_login","max_age","accessPayload","access_token","idPayload","id_token","authTime","auth_time","floor","accessToken","Authorization","oidc_prompt_none","redirect_uri","dest","run","OIDCExchangeContext","PassflowProvider","initialNavigate","config","needsDiscovery","landedWithTwoFactorToken","discoveryAttemptedRef","discoverAppId","passflowValue","handleSetNavigate","flowTwoFactorVerifyPath","setFlowTwoFactorVerifyPath","resolvedTwoFactorVerifyPath","pending","setPending","handleTokensRedirect","useSecondFactorLanding","navigationValue","oidcExchangeValue","upgradeEnabled","upgradeOptions","TwoFactorVerifyFlow","successAuthRedirect","useV2Flow","setMode","handleSuccess","initialValues$1","searchParamsForgotPasswordSchema","object","shape","oneOf","ForgotPassword","successResetRedirect","forgotPasswordSuccessPath","register","isErrorApp","errorApp","authMethods","default_method","abortEarly","currentSubscriptions","custom_css","logo_url","remove_passflow_logo","isEmail","match","isUsername","validatedPhone","isPhone","phoneNumber","redirect","currentSearchParams","newParams","searchParamsForgotPasswordSuccessSchema","identityValue","ForgotPasswordSuccess","resendPayload","ErrorComponent","goBackRedirectTo","application_name","toErrorMessage","excludeRoutes","withError","Component","route","FallbackComponent","InvitationJoin","signUpPath","joinInvite","invitationToken","invitationTokenData","parsedTokenCache","hasAuthenticatedSession","successJoinPath","acceptInvitation","initialValues","searchParamsResetPasswordSchema","ResetPassword","clearErrors","resetToken","resetTokenData","resetTokenType","onSubmitHanlder","passwordErrors","handlePasswordChange","SignInForm","hostname","verifyOTPPath","verifyMagicLinkPath","forgotPasswordPath","loginMethods","getLoginMethodConfig","errorUrl","messageUrl","invitationChrome","completeAuthentication","handlePassword","userPayload","submitPassword","handlePasswordless","challenge_type","handlePasskey","passkeyPayload","submitPasskey","relying_party_id","force_passwordless_login","SignUpForm","getSignUpMethodConfig","completeRegistration","oidcMayOwnRedirect","user","phone_number","SignUp","challengeTypeFullString$1","VerifyChallengeMagicLink","identity_value","TimerButton","totalSecond","setSeconds","interval","VerifyChallengeSuccess","challengeTypeFullString","VerifyChallengeOTPManual","challengeId","fetchPasswordlessComplete","valueOTP","setValueOTP","paramsError","setParamsError","showSuccessMessage","setShowSuccessMessage","fetchData","refetchResponse","onClickResendHandler","VerifyChallengeOTPRedirect","missingParameters","redirectSearchParamsVerifyChallengeOtpSchema","searchParamsVerifyChallengeOtpSchema","optional","VerifyChallengeOTP","typeChallenge","redirectParams","normalizePathPrefix","pathReplace","combineRoutesWithPrefix","prefix","reduce","acc","RouterProvider","routerType","RouterInnerWrapperProvider","PassflowRoutes","federatedDisplayMode","pathPrefix","parentBase","splat","tail","endsWith","encodeURI","useParentRouteBase","matchPaths","paths","element","PassflowFlow","errorUrlSuccess","messageUrlSuccess","isInHostRouter","flowRoutes","TwoFactorSetupMagicLinkFlow","redirectOnSuccess","isRetryable","isRateLimited","getErrorSubtitle","formatCountdown","padStart"],"sources":["../package.json","../src/utils/get-app-version.ts","../src/utils/auth-error.ts","../src/utils/classify-device-error.ts","../src/utils/classify-two-factor-error.ts","../src/utils/cn.ts","../src/utils/get-auth-methods.ts","../src/utils/get-form-labels.ts","../src/utils/get-url-errors.ts","../src/utils/get-url-with-tokens.ts","../src/utils/undefined-on-catch.ts","../src/utils/invitation-auth-chrome.ts","../src/utils/second-factor.ts","../src/utils/two-factor-loop-prevention.ts","../src/utils/upgrade-auth.ts","../src/utils/url-params.ts","../src/utils/validate-url.ts","../src/utils/validation-schemas/index.ts","../src/components/ui/button/index.tsx","../src/components/ui/continuing-status/index.tsx","../src/assets/icons/flags.png","../src/components/ui/country-flag/positions.ts","../src/components/ui/country-flag/index.tsx","../src/components/ui/dialog/index.tsx","../src/components/ui/fields/field-otp.tsx","../src/components/ui/fields/field-password.tsx","../src/hooks/use-passflow.ts","../src/context/auth-context.tsx","../src/context/navigation-context.ts","../src/context/passflow-context.ts","../src/context/router-context.ts","../src/context/upgrade-context.ts","../src/utils/login-theme.ts","../src/hooks/use-app-settings.ts","../src/hooks/use-auth.ts","../src/hooks/use-auth-cloud-redirect.ts","../src/hooks/use-consent.ts","../src/hooks/use-device-verify.ts","../src/hooks/use-forgot-password.ts","../src/hooks/use-join-invite.ts","../src/hooks/use-logout.ts","../src/hooks/use-navigation.ts","../src/hooks/use-outsideclick.ts","../src/hooks/use-passwordless-complete.ts","../src/hooks/use-provider.ts","../src/hooks/use-reset-password.ts","../src/hooks/use-session-expired.ts","../src/hooks/use-signin.ts","../src/hooks/use-signup.ts","../src/hooks/use-trusted-devices.ts","../src/hooks/use-two-factor-challenge.ts","../src/hooks/use-two-factor-manage.ts","../src/hooks/use-two-factor-methods.ts","../src/hooks/use-two-factor-setup.ts","../src/hooks/use-two-factor-setup-magic-link.ts","../src/hooks/use-two-factor-status.ts","../src/hooks/use-two-factor-verify.ts","../src/hooks/use-upgrade.ts","../src/hooks/use-user-passkeys.ts","../src/components/ui/fields/field-phone.tsx","../src/components/ui/fields/field-text.tsx","../src/assets/icons/general/browser-chrome.svg","../src/assets/icons/general/caret-down.svg","../src/assets/icons/general/check.svg","../src/assets/icons/general/close.svg","../src/assets/icons/general/dots-vertical.svg","../src/assets/icons/general/edit.svg","../src/assets/icons/general/eye-off.svg","../src/assets/icons/general/eye-on.svg","../src/assets/icons/general/key.svg","../src/assets/icons/general/label.svg","../src/assets/icons/general/logo.svg","../src/assets/icons/general/logo-red.svg","../src/assets/icons/general/mail.svg","../src/assets/icons/general/one-password.svg","../src/assets/icons/general/passkey.svg","../src/assets/icons/general/phone.svg","../src/assets/icons/general/search.svg","../src/assets/icons/general/trash.svg","../src/assets/icons/general/warning.svg","../src/assets/icons/providers/apple.svg","../src/assets/icons/providers/atlassian.svg","../src/assets/icons/providers/bitbucket.svg","../src/assets/icons/providers/discord.svg","../src/assets/icons/providers/dropbox.svg","../src/assets/icons/providers/facebook.svg","../src/assets/icons/providers/github.svg","../src/assets/icons/providers/gitlab.svg","../src/assets/icons/providers/google.svg","../src/assets/icons/providers/hubspot.svg","../src/assets/icons/providers/linear.svg","../src/assets/icons/providers/linkedin.svg","../src/assets/icons/providers/microsoft.svg","../src/assets/icons/providers/notion.svg","../src/assets/icons/providers/slack.svg","../src/assets/icons/providers/tiktok.svg","../src/assets/icons/providers/twitch.svg","../src/assets/icons/providers/twitter.svg","../src/assets/icons/providers/xero.svg","../src/components/ui/icon/index.tsx","../src/components/ui/link/index.tsx","../src/components/ui/login-screen/shared.tsx","../src/components/ui/login-screen/code-entry.tsx","../src/components/ui/switch/index.tsx","../src/components/ui/login-screen/consent.tsx","../src/components/ui/providers-box/index.tsx","../src/components/ui/login-screen/credentials.tsx","../src/components/ui/login-screen/device-approval.tsx","../src/components/ui/login-screen/general-error.tsx","../src/components/ui/login-screen/invitation.tsx","../src/components/ui/login-screen/passkey-progress.tsx","../src/components/ui/login-screen/second-factor.tsx","../src/components/ui/login-screen/shell.tsx","../src/components/ui/login-screen/status.tsx","../src/components/ui/login-screen/login-screen.tsx","../src/components/ui/popover/index.tsx","../src/components/ui/spinner/index.tsx","../src/components/ui/upgrade-dialog/factor-list.tsx","../src/components/ui/upgrade-dialog/challenge.tsx","../src/components/ui/upgrade-dialog/state-mapping.ts","../src/components/ui/upgrade-dialog/status.tsx","../src/components/ui/upgrade-dialog/upgrade-dialog.tsx","../src/components/flow/consent/screen.ts","../src/components/flow/consent/index.tsx","../src/components/flow/device-verify/screen.ts","../src/components/flow/device-verify/index.tsx","../src/components/form/two-factor-setup/two-factor-setup-form.tsx","../src/components/flow/two-factor-setup/index.tsx","../src/components/form/two-factor-challenge/method-selector.tsx","../src/components/form/two-factor-challenge/index.tsx","../src/components/form/two-factor-verify/two-factor-recovery-form.tsx","../src/components/form/two-factor-verify/two-factor-verify-form.tsx","../src/components/provider/upgrade-provider.tsx","../src/components/provider/passflow-provider.tsx","../src/components/flow/two-factor-verify/index.tsx","../src/components/form/forgot-password/forgot-password.tsx","../src/components/form/forgot-password/forgot-password-success.tsx","../src/components/error/index.tsx","../src/hocs/with-error.tsx","../src/components/form/invitation-join/index.tsx","../src/components/form/reset-password/index.tsx","../src/components/form/signin/index.tsx","../src/components/form/signup/index.tsx","../src/components/form/verify-challenge/verify-challenge-magic-link.tsx","../src/components/form/verify-challenge/timer-button.tsx","../src/components/form/verify-challenge/verify-challenge-success.tsx","../src/components/form/verify-challenge/verify-challenge-otp-manual.tsx","../src/components/form/verify-challenge/verify-challenge-otp-redirect.tsx","../src/components/form/verify-challenge/verify-challenge-otp.tsx","../src/components/flow/passflow/index.tsx","../src/components/flow/two-factor-setup-magic-link/index.tsx"],"sourcesContent":["{\n \"name\": \"@passflow/react\",\n \"description\": \"Passflow React UI Kit\",\n \"version\": \"0.15.1\",\n \"type\": \"module\",\n \"files\": [\n \"dist\",\n \"CHANGELOG.md\"\n ],\n \"main\": \"dist/index.cjs\",\n \"module\": \"dist/index.es.js\",\n \"types\": \"dist/src/index.d.ts\",\n \"exports\": {\n \".\": {\n \"import\": {\n \"types\": \"./dist/src/index.d.ts\",\n \"default\": \"./dist/index.es.js\"\n },\n \"require\": {\n \"types\": \"./dist/src/index.d.cts\",\n \"default\": \"./dist/index.cjs\"\n }\n },\n \"./dist/style.css\": \"./dist/style.css\"\n },\n \"scripts\": {\n \"dev\": \"vite\",\n \"build\": \"tsc && vite build && pnpm build:types\",\n \"build:types\": \"tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json && node scripts/fix-dts-specifiers.mjs && node scripts/emit-cts-types.mjs\",\n \"prepack\": \"pnpm build\",\n \"lint\": \"biome check src\",\n \"lint:fix\": \"biome check --write src\",\n \"format\": \"biome format src\",\n \"format:fix\": \"biome format --write src\",\n \"preview\": \"vite preview\",\n \"test\": \"playwright install chromium && playwright test --config=playwright/playwright.config.ts\",\n \"test:ui\": \"playwright install chromium && playwright test --config=playwright/playwright.ui.config.ts --ui\",\n \"test:unit\": \"vitest run\",\n \"test:unit:watch\": \"vitest\",\n \"test:coverage\": \"vitest run --coverage\",\n \"storybook\": \"storybook dev -p 6006\",\n \"build-storybook\": \"storybook build\"\n },\n \"engines\": {\n \"node\": \"^22.12.0 || ^24.0.0 || >=26.0.0\"\n },\n \"peerDependencies\": {\n \"react\": \"^18.0.0 || ^19.0.0\",\n \"react-dom\": \"^18.0.0 || ^19.0.0\",\n \"react-router\": \"^7.0.0 || ^8.0.0\"\n },\n \"dependencies\": {\n \"@passflow/core\": \"^0.20.1\",\n \"@radix-ui/react-dialog\": \"^1.3.1\",\n \"@radix-ui/react-popover\": \"^1.3.1\",\n \"@simplewebauthn/browser\": \"^14.0.0\",\n \"clsx\": \"^2.1.1\",\n \"countries-and-timezones\": \"^3.11.0\",\n \"dayjs\": \"^1.11.23\",\n \"input-otp\": \"^1.5.0\",\n \"phone\": \"^3.1.72\",\n \"query-string\": \"^10.0.0\",\n \"react-error-boundary\": \"^6.1.6\",\n \"react-hook-form\": \"^7.91.0\",\n \"react-international-phone\": \"^4.8.0\",\n \"yup\": \"^1.7.1\"\n },\n \"devDependencies\": {\n \"@axe-core/playwright\": \"4.14.0\",\n \"@biomejs/biome\": \"^2.6.4\",\n \"@playwright/test\": \"^1.64.1\",\n \"@storybook/addon-a11y\": \"10.6.5\",\n \"@storybook/addon-docs\": \"10.6.5\",\n \"@storybook/addon-themes\": \"10.6.5\",\n \"@storybook/react-vite\": \"10.6.5\",\n \"@testing-library/jest-dom\": \"^7.0.1\",\n \"@testing-library/react\": \"^16.3.3\",\n \"@testing-library/user-event\": \"^14.6.8\",\n \"@types/node\": \"^22.20.5\",\n \"@types/react\": \"^19.3.0\",\n \"@types/react-dom\": \"^19.3.0\",\n \"@vitejs/plugin-react\": \"^6.1.2\",\n \"@vitest/coverage-v8\": \"^5.0.5\",\n \"cssnano\": \"^9.9.0\",\n \"jsdom\": \"^30.1.3\",\n \"react\": \"^19.3.1\",\n \"react-dom\": \"^19.3.1\",\n \"react-router\": \"8.5.1\",\n \"storybook\": \"10.6.5\",\n \"terser\": \"^5.51.2\",\n \"tsc-alias\": \"^1.9.9\",\n \"typescript\": \"7.0.2\",\n \"vite\": \"^8.3.5\",\n \"vite-plugin-environment\": \"^1.1.4\",\n \"vitest\": \"^5.0.5\"\n },\n \"authors\": [\n {\n \"name\": \"Ivan Holiak\",\n \"url\": \"https://github.com/IvanHoliak\"\n },\n {\n \"name\": \"Jack Rudenko\",\n \"url\": \"https://madappgang.com\"\n }\n ],\n \"license\": \"MIT\",\n \"bugs\": {\n \"url\": \"https://github.com/MadAppGang/passflow-react-sdk/issues\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/MadAppGang/passflow-react-sdk.git\"\n },\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"keywords\": [\n \"passflow\",\n \"auth\",\n \"authentication\",\n \"passwordless\",\n \"session\",\n \"jwt\",\n \"react\",\n \"ui\",\n \"ui-kit\",\n \"react-ui-kit\",\n \"passflow-react-ui-kit\"\n ],\n \"packageManager\": \"pnpm@12.16.1\"\n}\n","import { version } from '../../package.json';\n\ndeclare global {\n interface Window {\n passflowReactAppVersion: () => void;\n }\n}\n\n// Runs when the module loads, so it must not assume a browser: SSR and plain Node have no window.\nif (typeof window !== 'undefined') {\n window.passflowReactAppVersion = () => {\n // eslint-disable-next-line no-console\n console.log(`App Version: ${version}`);\n };\n}\n","import type { AuthFlow, AuthOperation, AuthUiError } from '@/types';\n\nconst AUTH_ERROR_COPY: Record<AuthFlow, Record<AuthOperation, AuthUiError>> = {\n 'sign-in': {\n password: {\n message: \"We couldn't sign you in. Check your details and try again.\",\n scope: 'credentials',\n },\n passwordless: {\n message: \"We couldn't start passwordless sign-in. Check your connection and try again.\",\n scope: 'form',\n },\n passkey: {\n message: \"We couldn't complete passkey sign-in. Try again or use another sign-in method.\",\n scope: 'form',\n },\n },\n 'sign-up': {\n password: {\n message: \"We couldn't create your account. Check the information you entered and try again.\",\n scope: 'form',\n },\n passwordless: {\n message: \"We couldn't start passwordless registration. Check your connection and try again.\",\n scope: 'form',\n },\n passkey: {\n message: \"We couldn't create your account with a passkey. Try again or choose another method.\",\n scope: 'form',\n },\n },\n};\n\nexport const authRedirectErrorMessage = \"We couldn't continue this authentication request. Return to the app and try again.\";\n\nexport const verificationLinkErrorMessage =\n 'This verification link is invalid or incomplete. Request a new link or code and try again.';\n\nexport const invitationLinkErrorMessage = 'This invitation link is invalid or has expired.';\n\nexport const verificationRequestErrorMessage =\n 'This verification request is no longer available. Start again to request a new link or code.';\n\nexport const authErrorFor = (flow: AuthFlow, operation: AuthOperation): AuthUiError => AUTH_ERROR_COPY[flow][operation];\n","import type { DeviceError, DeviceErrorType } from '@/types/device-errors';\n\n/**\n * Turns anything that can go wrong on the device verification page into a\n * {@link DeviceError} — a sentence a person can read, plus the technical detail\n * demoted to `detail`.\n *\n * See types/device-errors.ts for why this exists at all. In short: the raw\n * strings are written for operators, and they leak.\n */\n\n/**\n * The user-facing copy. One entry per {@link DeviceErrorType}, and this table IS\n * the contract — nothing else in the flow may produce a user-visible sentence.\n *\n * Voice notes, since these are the words on the screen where someone authorizes\n * a shell:\n * - Say what happened, then what to do. Never why, in our terms.\n * - No jargon a user did not bring with them: no \"credential\", \"authenticator\",\n * \"assertion\", \"CSRF\", \"origin\", \"token\", \"challenge\", \"resident key\".\n * \"Passkey\" stays — it is the word on the button they just tapped.\n * - Never blame them, and never imply they broke something.\n * - Where we genuinely cannot tell (see passkey_failed), say so plainly and\n * offer both remedies rather than guessing at one.\n */\nconst DEVICE_ERROR_COPY: Record<DeviceErrorType, string> = {\n code_required: 'Enter the code shown on your device to continue.',\n code_invalid: \"That code isn't right. Check the code on your device and enter it again.\",\n code_expired: 'This code has expired. Start again on your device to get a new one.',\n code_declined: 'This request was already declined. Start again on your device if you still want to sign in.',\n code_already_approved: 'This device is already signed in. You can close this page and head back to it.',\n too_many_attempts: 'Too many incorrect codes were entered. Wait a few minutes, then try again.',\n mode_disabled:\n \"This app can't be signed in to this way. Ask whoever set it up to turn on QR sign-in, or sign in from your computer instead.\",\n app_unavailable: 'The app that asked you to sign in is no longer available. Start again from your device.',\n bad_credentials: \"That email or password isn't right.\",\n missing_credentials: 'Enter your email and password to continue.',\n second_factor_invalid: \"That code isn't right. Check it and enter it again.\",\n missing_second_factor: 'Enter the code to continue.',\n account_blocked: 'This account has been blocked. Contact whoever manages it for help.',\n // The three-cause sentence is deliberate, not hedging: the browser reports\n // \"cancelled\", \"timed out\" and \"no passkey here\" identically (by design — it\n // must not become an oracle for which accounts live on a device), so naming\n // one cause would be a guess presented as a fact.\n passkey_failed:\n \"We couldn't confirm your passkey. You may have cancelled it, waited too long, or there may be no passkey for this site on this device.\",\n passkey_unsupported:\n \"This device can't use a passkey to sign in here. Use a device you've set up a passkey on, or return to the app that asked you to sign in and start again.\",\n offline: \"We couldn't reach the server. Check your connection and try again.\",\n generic: 'Something went wrong on our end. Refresh the page and try again.',\n};\n\n/** Failures the user can plausibly clear by acting on this page. */\nconst RECOVERABLE: ReadonlySet<DeviceErrorType> = new Set<DeviceErrorType>([\n 'code_required',\n 'code_invalid',\n 'bad_credentials',\n 'missing_credentials',\n 'second_factor_invalid',\n 'missing_second_factor',\n 'passkey_failed',\n 'offline',\n 'generic',\n]);\n\n/**\n * Server `reason` codes -> our types.\n *\n * The server sends a stable machine reason precisely so this mapping can exist:\n * see the deviceReason* / deviceLookupError.Code constants in\n * src/web/oidc/device_page.go and device_verify.go. Its `error_description` is\n * for operators and never reaches the screen.\n *\n * Anything absent from this table — `csrf token missing or invalid`,\n * `cross-origin request refused`, `invalid JSON body`, `auth flow manager is not\n * wired` — deliberately falls through to `generic`. Those are our bugs or our\n * attacker's business, and in both cases the user's remedy is the same and their\n * screen should say so without teaching them the word \"CSRF\".\n */\nconst REASON_TO_TYPE: Record<string, DeviceErrorType> = {\n code_required: 'code_required',\n invalid_user_code: 'code_invalid',\n unknown_user_code: 'code_invalid',\n expired_user_code: 'code_expired',\n denied: 'code_declined',\n already_approved: 'code_already_approved',\n too_many_attempts: 'too_many_attempts',\n mode_disabled: 'mode_disabled',\n unknown_client: 'app_unavailable',\n passkey_unavailable: 'app_unavailable',\n unavailable: 'app_unavailable',\n bad_credentials: 'bad_credentials',\n missing_credentials: 'missing_credentials',\n second_factor_invalid: 'second_factor_invalid',\n missing_second_factor: 'missing_second_factor',\n blocked: 'account_blocked',\n passkey_failed: 'passkey_failed',\n};\n\n/**\n * WebAuthn DOMException names -> our types.\n *\n * Only the names that reliably mean something distinct to a USER are mapped.\n * NotAllowedError is the big one and it is intentionally lossy: it covers\n * cancel, timeout AND no-matching-credential, because the spec has browsers\n * conflate them so a page cannot probe which passkeys a device holds.\n */\nconst WEBAUTHN_NAME_TO_TYPE: Record<string, DeviceErrorType> = {\n NotAllowedError: 'passkey_failed',\n AbortError: 'passkey_failed',\n TimeoutError: 'passkey_failed',\n UnknownError: 'passkey_failed',\n // The authenticator or browser cannot satisfy the request as asked.\n NotSupportedError: 'passkey_unsupported',\n InvalidStateError: 'passkey_unsupported',\n ConstraintError: 'passkey_unsupported',\n // RP ID / origin misconfiguration. A deployment bug, not a user's problem —\n // they cannot fix it, so do not invite them to retry forever.\n SecurityError: 'passkey_unsupported',\n};\n\n/**\n * Message fragments that mean \"this authenticator cannot do discoverable\n * credentials\", whatever DOMException name the browser happened to attach.\n *\n * This is here because of a specific, observed regression: a real user hit\n *\n * \"Resident credentials or empty 'allowCredentials' lists are not supported\n * at this time.\"\n *\n * — Chrome's internal string for a virtual/limited authenticator being asked for\n * a discoverable credential. Matching on text as well as on name is belt and\n * braces: the name for this case is not stable across Chrome versions, and the\n * one thing that must never happen is this sentence reaching a user again.\n */\nconst UNSUPPORTED_MESSAGE_PATTERNS: readonly string[] = [\n 'resident credentials',\n 'allowcredentials',\n 'not supported at this time',\n 'discoverable credentials',\n 'is not supported',\n];\n\n/**\n * An error carrying a server-supplied reason code. Thrown by the device API\n * client so the classifier can map precisely rather than sniff strings.\n */\nexport class DeviceApiError extends Error {\n /** Stable machine reason from the server. */\n readonly reason: string;\n /** The OAuth2 error code (`invalid_request`, `unauthorized_client`, ...). */\n readonly code: string;\n /** HTTP status. */\n readonly status: number;\n\n constructor(params: { reason: string; code: string; status: number; description: string }) {\n // The Error message is the OPERATOR's string — it goes to the console and to\n // `detail`, never to the screen. classifyDeviceError picks the user's words.\n super(params.description || params.code || `device request failed (${params.status})`);\n this.name = 'DeviceApiError';\n this.reason = params.reason;\n this.code = params.code;\n this.status = params.status;\n }\n}\n\nconst build = (type: DeviceErrorType, detail?: string): DeviceError => ({\n type,\n message: DEVICE_ERROR_COPY[type],\n detail,\n isRecoverable: RECOVERABLE.has(type),\n});\n\nconst isDOMExceptionLike = (err: unknown): err is { name: string; message: string } =>\n typeof err === 'object' && err !== null && 'name' in err && typeof (err as { name: unknown }).name === 'string';\n\n/**\n * Classify any failure from the device verification flow.\n *\n * Order matters: the server's own reason wins when we have one (it knows more\n * than we can infer), then WebAuthn's message text, then WebAuthn's name, then\n * the network, then a safe default. Every path ends in copy from\n * DEVICE_ERROR_COPY — there is deliberately no branch that forwards a raw\n * string to `message`.\n */\nexport function classifyDeviceError(err: unknown): DeviceError {\n // 1. The server told us exactly what happened.\n if (err instanceof DeviceApiError) {\n const type = REASON_TO_TYPE[err.reason] ?? 'generic';\n return build(type, `${err.code}${err.reason ? `/${err.reason}` : ''}: ${err.message}`);\n }\n\n if (isDOMExceptionLike(err)) {\n const name = err.name;\n const raw = typeof err.message === 'string' ? err.message : '';\n const detail = raw ? `${name}: ${raw}` : name;\n\n // 2. The resident-credential family, matched on text. Checked BEFORE the\n // name table because the name for this case is not dependable — see\n // UNSUPPORTED_MESSAGE_PATTERNS.\n const lowered = raw.toLowerCase();\n if (UNSUPPORTED_MESSAGE_PATTERNS.some((p) => lowered.includes(p))) {\n return build('passkey_unsupported', detail);\n }\n\n // 3. A WebAuthn name we recognise.\n const byName = WEBAUTHN_NAME_TO_TYPE[name];\n if (byName) {\n return build(byName, detail);\n }\n\n // 4. fetch() rejects with TypeError when it cannot reach the network at all.\n if (name === 'TypeError') {\n return build('offline', detail);\n }\n\n return build('generic', detail);\n }\n\n return build('generic', typeof err === 'string' ? err : undefined);\n}\n\n/**\n * The copy for a type, without an error to classify. For states that are known\n * up front rather than thrown — e.g. a browser with no WebAuthn at all.\n */\nexport function deviceErrorOfType(type: DeviceErrorType, detail?: string): DeviceError {\n return build(type, detail);\n}\n","import type { TwoFactorError } from '@/types/two-factor-errors';\n\n/**\n * Error message patterns for classification\n */\nconst ERROR_PATTERNS = {\n expired: ['2FA verification expired or not required', 'verification expired', 'session expired', 'verification not required'],\n not_enabled: ['Two-factor authentication is not enabled for this user', '2FA is not enabled', 'two-factor not enabled'],\n invalid_code: ['invalid code', 'incorrect code', 'code mismatch', 'wrong code', 'invalid 2fa code'],\n} as const;\n\n/**\n * Classify 2FA error based on error message\n *\n * @param errorMessage - Error message from SDK\n * @returns Classified error with handling strategy\n */\nexport function classifyTwoFactorError(errorMessage: string): TwoFactorError {\n const normalizedMessage = errorMessage.toLowerCase();\n\n // Check for expired session (recoverable, auto-redirect)\n if (ERROR_PATTERNS.expired.some((pattern) => normalizedMessage.includes(pattern.toLowerCase()))) {\n return {\n type: 'expired',\n message: errorMessage,\n isRecoverable: true,\n shouldAutoRedirect: true,\n };\n }\n\n // Check for 2FA not enabled (non-recoverable, NO auto-redirect)\n if (ERROR_PATTERNS.not_enabled.some((pattern) => normalizedMessage.includes(pattern.toLowerCase()))) {\n return {\n type: 'not_enabled',\n message: errorMessage,\n isRecoverable: false,\n shouldAutoRedirect: false,\n };\n }\n\n // Check for invalid code (recoverable, allow retry)\n if (ERROR_PATTERNS.invalid_code.some((pattern) => normalizedMessage.includes(pattern.toLowerCase()))) {\n return {\n type: 'invalid_code',\n message: errorMessage,\n isRecoverable: true,\n shouldAutoRedirect: false,\n };\n }\n\n // Generic error (treat as recoverable with retry)\n return {\n type: 'generic',\n message: errorMessage,\n isRecoverable: true,\n shouldAutoRedirect: false,\n };\n}\n\n/**\n * Get user-friendly error message based on error type\n */\nexport function getUserFriendlyErrorMessage(error: TwoFactorError): string {\n switch (error.type) {\n case 'expired':\n return 'Your session has expired. Redirecting to sign in...';\n case 'not_enabled':\n return 'Two-factor authentication is not enabled for your account. Please contact your administrator to enable 2FA.';\n case 'invalid_code':\n return 'Invalid code. Please check your authenticator app and try again.';\n default:\n return error.message;\n }\n}\n","import clsx, { type ClassValue } from 'clsx';\n\n// Joins class names. The library styles with `passflow-*` classes only, so\n// there are no utility-class conflicts to resolve.\nexport const cn = (...classes: ClassValue[]) => clsx(classes);\n","import type { AuthStrategies, FimStrategy, InternalStrategy, Providers } from '@passflow/core';\n\nexport type AuthMethods = {\n internal: {\n username: {\n password: boolean;\n };\n email: {\n password: boolean;\n otp: boolean;\n magicLink: boolean;\n };\n phone: {\n password: boolean;\n otp: boolean;\n magicLink: boolean;\n };\n };\n fim: {\n providers: Providers[];\n };\n passkey: boolean;\n hasEmailMethods: boolean;\n hasSignInEmailMethods: boolean;\n hasPhoneMethods: boolean;\n hasSignInPhoneMethods: boolean;\n hasUsernameMethods: boolean;\n hasSignInUsernameMethods: boolean;\n};\n\nexport const getAuthMethods = (strategies?: AuthStrategies[]): AuthMethods => {\n const methods: AuthMethods = {\n internal: {\n username: {\n password: false,\n },\n email: {\n password: false,\n otp: false,\n magicLink: false,\n },\n phone: {\n password: false,\n otp: false,\n magicLink: false,\n },\n },\n fim: {\n providers: [],\n },\n passkey: false,\n hasEmailMethods: false,\n hasSignInEmailMethods: false,\n hasPhoneMethods: false,\n hasSignInPhoneMethods: false,\n hasUsernameMethods: false,\n hasSignInUsernameMethods: false,\n };\n\n if (!strategies) return methods;\n\n for (const strategy of strategies) {\n const { identity, challenge, fim_type: fimType } = strategy.strategy as InternalStrategy & FimStrategy;\n\n switch (strategy.type) {\n case 'internal':\n switch (identity) {\n case 'email':\n if (challenge === 'magic_link') methods.internal.email.magicLink = true;\n else methods.internal.email[challenge as keyof AuthMethods['internal']['email']] = true;\n methods.hasEmailMethods = true;\n\n if (methods.internal.email.magicLink || methods.internal.email.otp || methods.internal.email.password)\n methods.hasSignInEmailMethods = true;\n\n break;\n case 'phone':\n if (challenge === 'magic_link') methods.internal.phone.magicLink = true;\n else methods.internal.phone[challenge as keyof AuthMethods['internal']['phone']] = true;\n methods.hasPhoneMethods = true;\n\n if (methods.internal.phone.magicLink || methods.internal.phone.otp || methods.internal.phone.password)\n methods.hasSignInPhoneMethods = true;\n\n break;\n case 'username':\n methods.internal.username[challenge as keyof AuthMethods['internal']['username']] = true;\n methods.hasUsernameMethods = true;\n\n if (methods.internal.username.password) methods.hasSignInUsernameMethods = true;\n\n break;\n default:\n throw new Error(`Unsupported identity type: ${identity}`);\n }\n break;\n case 'fim':\n methods.fim.providers.push(fimType);\n break;\n case 'passkey':\n methods.passkey = true;\n break;\n default:\n throw new Error(`Unsupported strategy type: ${strategy.type}`);\n }\n }\n\n return methods;\n};\n","import type { InternalStrategyChallenge } from '@passflow/core';\n/* eslint-disable complexity */\nimport type { DefaultMethod } from '@/types';\nimport type { AuthMethods } from './get-auth-methods';\n\nexport const getIdentityLabel = (methods: AuthMethods, type: 'label' | 'button') => {\n if (methods.hasSignInEmailMethods && methods.hasSignInUsernameMethods)\n return type === 'label' ? 'Email or username' : 'Use email or username';\n if (methods.hasSignInEmailMethods) return type === 'label' ? 'Email' : 'Use email';\n if (methods.hasSignInUsernameMethods) return type === 'label' ? 'Username' : 'Use username';\n\n return null;\n};\n\nexport const getPasswordlessData = (\n methods: AuthMethods,\n currentMethod: DefaultMethod | null,\n): { label: string; challengeType: InternalStrategyChallenge } | null => {\n if (currentMethod === 'phone') {\n if (methods.internal.phone.otp) return { label: 'SMS code', challengeType: 'otp' };\n if (methods.internal.phone.magicLink) return { label: 'SMS link', challengeType: 'magic_link' };\n }\n\n if (currentMethod === 'email_or_username') {\n if (methods.internal.email.otp) return { label: 'email code', challengeType: 'otp' };\n if (methods.internal.email.magicLink) return { label: 'email link', challengeType: 'magic_link' };\n }\n\n return null;\n};\n\nexport const getValidationErrorsLabel = (methods: AuthMethods) => {\n if (methods.hasSignInEmailMethods && methods.hasSignInUsernameMethods) return 'Email or username is required';\n if (methods.hasSignInEmailMethods) return 'Email is required';\n if (methods.hasSignInUsernameMethods) return 'Username is required';\n\n return 'Field is required';\n};\n","export const getUrlErrors = (subUrl?: string) => {\n const searchParams = new URLSearchParams(subUrl ? subUrl.split('?')[1] : window.location.search);\n const error = searchParams.get('error');\n const message = searchParams.get('message');\n\n return { error, message: message ? decodeURIComponent(message) : null };\n};\n","import type { Passflow } from '@passflow/core';\n\nexport type TokenUrlFormat = 'query' | 'hash';\n\nexport const getUrlWithTokens = async (passflow: Passflow, url: string, format: TokenUrlFormat = 'hash'): Promise<string> => {\n const tokens = await passflow.getTokens(false);\n\n if (tokens) {\n tokens.scopes = undefined;\n const tokenParams = Object.entries(tokens)\n // eslint-disable-next-line no-unused-vars\n .filter(([_, value]) => value)\n .map(([key, value]) => `${key}=${encodeURIComponent(value as string)}`)\n .join('&');\n\n if (format === 'hash') {\n // Use hash fragment (more secure - not sent to server)\n return `${url}#${tokenParams}`;\n }\n // Use query parameters\n return `${url}?${tokenParams}`;\n }\n return url;\n};\n","export function undefinedOnCatch<T, K>(fn: (t: K) => T): (t: K) => T | undefined {\n return (t: K) => {\n try {\n return fn(t);\n } catch (error) {\n return undefined;\n }\n };\n}\n","import { type InvitationToken, parseToken } from '@passflow/core';\nimport { undefinedOnCatch } from './undefined-on-catch';\n\nexport type InvitationAuthIntent = 'sign-in' | 'sign-up';\n\ntype InvitationAuthChrome = {\n title: string;\n subtitle: string;\n};\n\nconst authAction = {\n 'sign-in': {\n title: 'Sign in',\n completion: 'sign in',\n },\n 'sign-up': {\n title: 'Create your account',\n completion: 'create your account',\n },\n} as const;\n\nexport const getInvitationAuthChrome = (\n inviteToken: string | null | undefined,\n intent: InvitationAuthIntent,\n): InvitationAuthChrome | null => {\n if (!inviteToken) return null;\n\n const invitation = undefinedOnCatch(parseToken)(inviteToken) as InvitationToken | undefined;\n const tenantName = invitation?.tenant_name?.trim();\n const inviterName = invitation?.inviter_name?.trim();\n const action = authAction[intent];\n\n return {\n title: tenantName ? `${action.title} to join ${tenantName}.` : `${action.title} to continue your invitation.`,\n subtitle: inviterName\n ? `${inviterName} invited you. After you ${action.completion}, you'll continue to the invitation.`\n : `After you ${action.completion}, you'll continue to the invitation.`,\n };\n};\n","import type { Passflow } from '@passflow/core';\nimport type { NavigateFunction } from '@/context';\n\n/**\n * Sends a sign-in that still owes its second factor to the 2FA screen.\n *\n * Every sign-in path can end this way: the server answers with a 2FA token in\n * place of tokens, `@passflow/core` keeps it and saves no session, and\n * `isTwoFactorVerificationRequired()` reads true. The caller must then stop:\n * no success redirect, and no `getUrlWithTokens` — there are no tokens yet.\n *\n * @returns true when it navigated, so the caller returns without redirecting\n */\nexport const routeToSecondFactor = (\n passflow: Pick<Passflow, 'isTwoFactorVerificationRequired'>,\n navigate: NavigateFunction,\n twoFactorVerifyPath: string,\n): boolean => {\n if (!passflow.isTwoFactorVerificationRequired()) return false;\n navigate({ to: twoFactorVerifyPath });\n return true;\n};\n\n/**\n * Whether the current URL is a landing that owes its second factor: a\n * federated sign-in on a non-PKCE app comes back with `#tfa_token=` in the\n * fragment and no tokens. Read it before `@passflow/core` is constructed,\n * because core adopts the token and strips the fragment as it starts.\n */\nexport const urlCarriesTwoFactorToken = (): boolean => {\n if (typeof window === 'undefined' || !window.location.hash) return false;\n return new URLSearchParams(window.location.hash.substring(1)).has('tfa_token');\n};\n","const STORAGE_KEY_PREFIX = 'passflow_2fa';\nconst REDIRECT_COUNT_KEY = `${STORAGE_KEY_PREFIX}_redirect_count`;\nconst LAST_ERROR_KEY = `${STORAGE_KEY_PREFIX}_last_error_type`;\nconst MAX_REDIRECTS = 3;\n\n/**\n * Loop prevention for 2FA redirect cycles\n */\nexport const TwoFactorLoopPrevention = {\n /**\n * Check if redirect should be allowed\n * @returns true if redirect is safe, false if loop detected\n */\n canRedirect(): boolean {\n try {\n const count = this.getRedirectCount();\n return count < MAX_REDIRECTS;\n } catch {\n // If sessionStorage is unavailable, allow redirect once\n return true;\n }\n },\n\n /**\n * Increment redirect counter\n */\n incrementRedirect(): void {\n try {\n const count = this.getRedirectCount();\n sessionStorage.setItem(REDIRECT_COUNT_KEY, String(count + 1));\n } catch {\n // Silently fail if sessionStorage unavailable\n }\n },\n\n /**\n * Get current redirect count\n */\n getRedirectCount(): number {\n try {\n const value = sessionStorage.getItem(REDIRECT_COUNT_KEY);\n return value ? Number.parseInt(value, 10) : 0;\n } catch {\n return 0;\n }\n },\n\n /**\n * Reset redirect counter (call on successful auth)\n */\n reset(): void {\n try {\n sessionStorage.removeItem(REDIRECT_COUNT_KEY);\n sessionStorage.removeItem(LAST_ERROR_KEY);\n } catch {\n // Silently fail if sessionStorage unavailable\n }\n },\n\n /**\n * Track last error type to detect repeated errors\n */\n setLastErrorType(errorType: string): void {\n try {\n sessionStorage.setItem(LAST_ERROR_KEY, errorType);\n } catch {\n // Silently fail if sessionStorage unavailable\n }\n },\n\n /**\n * Get last error type\n */\n getLastErrorType(): string | null {\n try {\n return sessionStorage.getItem(LAST_ERROR_KEY);\n } catch {\n return null;\n }\n },\n\n /**\n * Check if same error is repeating\n */\n isRepeatingError(errorType: string): boolean {\n const lastError = this.getLastErrorType();\n return lastError === errorType && this.getRedirectCount() > 0;\n },\n\n /**\n * Get user-friendly message when loop is detected\n */\n getLoopDetectedMessage(): string {\n return 'Unable to complete authentication. This may be a configuration issue. Please contact support.';\n },\n};\n\nexport default TwoFactorLoopPrevention;\n","/**\n * The free-function adapters — `withAuth` and `attachAuth` (§13.5).\n *\n * The core exposes both as methods on a configured `Passflow` instance, because\n * that is where the resolved interception scope is bound. The developer-facing\n * form is a bare import, so these two functions translate one into the other\n * and do nothing else:\n *\n * ```tsx\n * import { attachAuth } from '@passflow/react';\n *\n * const api = axios.create({ baseURL: 'https://api.example.com' });\n * useEffect(() => attachAuth(api), []);\n * ```\n *\n * **NO LOGIC IN AN ADAPTER.** Neither function parses a challenge, compares a\n * bar, decides scope, counts a retry or chooses an error class. Every one of\n * those decisions lives in the core's `handleChallenge`, which is what makes\n * all four surfaces behave identically.\n *\n * The instance is published by `UpgradeProvider`, which reads it from\n * `PassflowContext` — so the binding is the provider's instance, resolved at\n * call time rather than captured at import time.\n *\n * **The publication is synchronous, during the provider's render, and that is\n * load-bearing.** React runs a child's effects before its parent's in the same\n * commit, so publishing from the provider's `useEffect` would be too late for\n * the documented `useEffect(() => attachAuth(api), [])` above: the child's\n * effect would reach `requireInstance` with nothing registered and throw, and a\n * throw inside an effect tears the tree down. Attach order must not matter, so\n * the registry is written in render.\n *\n * **And the release is deferred by a microtask, which is what makes the pair\n * survive React Strict Mode.** Strict Mode mounts, unmounts and remounts\n * effects in development, and the child-before-parent effect order holds on the\n * remount pass too — while render, which is what published the instance, does\n * not run again. So an immediate release in the provider's effect cleanup\n * leaves the registry empty exactly when the remounting child's effect reads\n * it, and `attachAuth` throws again (verified: it does). Scheduling the release\n * instead means a re-registration in the same tick cancels it, which is\n * precisely a Strict Mode remount; a real unmount has no re-registration, so\n * the release lands one microtask later. Nothing observes that gap but a caller\n * reaching for an instance that has just been torn down.\n */\n\nimport type { FetchLike, Passflow, ResponseInterceptorHost } from '@passflow/core';\n\nlet activeInstance: Passflow | null = null;\n\n/**\n * The instance a scheduled release is waiting to clear, or `null` when no\n * release is pending. Any registration clears it, which is how a Strict Mode\n * remount cancels the release its own cleanup just scheduled.\n */\nlet pendingRelease: Passflow | null = null;\n\n/**\n * Publishes the provider's `Passflow` instance to the free functions, and\n * returns an unregister suitable as a React effect cleanup.\n *\n * Last registration wins, and the returned unregister is *deferred*: it clears\n * the instance on a microtask, and only if nothing has registered in the\n * meantime. See the module comment — that deferral is what keeps a Strict Mode\n * mount → unmount → remount from leaving the free functions unbound, and it is\n * why register and release are symmetric rather than one in render and one in a\n * cleanup that nothing undoes.\n */\nexport const registerUpgradeAuthInstance = (instance: Passflow): (() => void) => {\n activeInstance = instance;\n pendingRelease = null;\n return () => {\n pendingRelease = instance;\n queueMicrotask(() => {\n // A register (or a later release) superseded this one: leave it alone.\n if (pendingRelease !== instance) return;\n pendingRelease = null;\n releaseUpgradeAuthInstance(instance);\n });\n };\n};\n\n/**\n * Clears `instance` if it is still the registered one, and does nothing\n * otherwise. Idempotent, so an effect cleanup that runs after a newer provider\n * has already published cannot unbind the live instance.\n */\nexport const releaseUpgradeAuthInstance = (instance: Passflow): void => {\n if (activeInstance === instance) activeInstance = null;\n};\n\n/** The instance the free functions bind to, or `null` outside a provider. */\nexport const upgradeAuthInstance = (): Passflow | null => activeInstance;\n\nconst requireInstance = (name: string): Passflow => {\n if (activeInstance === null) {\n throw new Error(\n `[passflow] ${name}() needs a mounted <PassflowProvider>: the interception scope is bound to a configured Passflow instance. Call it from inside your app (an effect or a component), or use passflow.${name}() from usePassflow().`,\n );\n }\n return activeInstance;\n};\n\n/**\n * Wraps a `fetch` and returns the wrapper. Installs nothing and touches no\n * global — two verbs exist because the semantics genuinely differ: an axios\n * interceptor mutates, a fetch wrapper returns.\n */\nexport const withAuth = (next?: FetchLike): FetchLike => requireInstance('withAuth').withAuth(next);\n\n/**\n * Attaches step-up handling to an axios instance the caller already owns,\n * **mutating** it, and returns the `detach()` disposer — which is exactly what\n * a React effect needs.\n *\n * The parameter is typed structurally (duck-typed on\n * `interceptors.response.use`), so this package's axios version is not a\n * constraint on the caller's.\n */\nexport const attachAuth = (instance: ResponseInterceptorHost): (() => void) =>\n requireInstance('attachAuth').attachAuth(instance);\n","/**\n * Utility for native handling of URL parameters\n */\n\n/**\n * Decodes HTML entities in a string\n */\nconst decodeHtmlEntities = (input: string): string => {\n const doc = new DOMParser().parseFromString(input, 'text/html');\n return doc.documentElement.textContent || '';\n};\n\n/**\n * Get URL parameters\n * @param defaultValues Default values\n * @returns Object with methods getAll, get, set\n */\nexport const useUrlParams = <T extends Record<string, string>>(defaultValues?: T) => {\n // Decode HTML entities in location.search\n const decodedSearch = decodeHtmlEntities(window.location.search);\n const searchParams = new URLSearchParams(decodedSearch);\n\n // Set default values if parameters don't exist\n if (defaultValues) {\n let hasChanged = false;\n\n for (const [key, value] of Object.entries(defaultValues)) {\n if (!searchParams.has(key) && value !== '') {\n searchParams.set(key, value);\n hasChanged = true;\n }\n }\n\n if (hasChanged) {\n const newUrl = `${window.location.pathname}${searchParams.toString() ? `?${searchParams.toString()}` : ''}${window.location.hash}`;\n window.history.replaceState(null, '', newUrl);\n }\n }\n\n /**\n * Get all parameters\n */\n const getAll = () => {\n const params: Record<string, string> = {};\n\n for (const [key, value] of searchParams.entries()) {\n params[key] = value;\n }\n\n return params;\n };\n\n /**\n * Get parameter value\n * @param key Parameter key\n */\n const get = (key: string) => {\n const value = searchParams.get(key);\n return value === '' ? null : value;\n };\n\n /**\n * Set parameters\n * @param params Object with parameters\n */\n const set = (params: Record<string, string>) => {\n const newSearchParams = new URLSearchParams(window.location.search);\n\n for (const [key, value] of Object.entries(params)) {\n if (value === null || value === undefined || value === '') {\n newSearchParams.delete(key);\n } else {\n newSearchParams.set(key, value);\n }\n }\n\n const newUrl = `${window.location.pathname}${newSearchParams.toString() ? `?${newSearchParams.toString()}` : ''}${window.location.hash}`;\n window.history.pushState(null, '', newUrl);\n };\n\n return {\n getAll,\n get,\n set,\n };\n};\n","export const isValidUrl = (url: string): boolean => {\n try {\n const newUrl = new URL(url);\n return newUrl.protocol === 'http:' || newUrl.protocol === 'https:';\n } catch {\n return false;\n }\n};\n","/* eslint-disable complexity */\n/* eslint-disable max-len */\nimport type { PassflowPasswordPolicySettings } from '@passflow/core';\nimport * as Yup from 'yup';\n\nexport const emailRegex =\n /^(([^<>()[\\]\\\\.,;:\\s@\"]+(\\.[^<>()[\\]\\\\.,;:\\s@\"]+)*)|.(\".+\"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\])|(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$/;\nexport const phoneNumberRegex =\n /^(\\+{0,})(\\d{0,})([(]{1}\\d{1,3}[)]{0,}){0,}(\\s?\\d+|\\+\\d{2,3}\\s{1}\\d+|\\d+){1}[\\s|-]?\\d+([\\s|-]?\\d+){1,2}(\\s){0,}$/gm;\n\nexport const passwordValidation = (passwordPolicy: PassflowPasswordPolicySettings | null) =>\n Yup.string()\n .required()\n .test({\n test: (value: string) => {\n const errors: string[] = [];\n\n if (passwordPolicy) {\n const {\n min_password_length: minPasswordLength,\n require_lowercase: requireLowerCase,\n require_number: requireNumber,\n require_symbol: requireSymbol,\n require_uppercase: requireUpperCase,\n } = passwordPolicy;\n\n if ((value ?? '').length < minPasswordLength) errors.push('length');\n if (requireUpperCase && !/[A-Z]/.test(value)) errors.push('uppercase');\n if (requireLowerCase && !/[a-z]/.test(value)) errors.push('lowercase');\n if (requireNumber && !/\\d/.test(value)) errors.push('number');\n if (requireSymbol && !/[!@#$%^&*()_+{}[\\]:;<>,.?~\\\\-]/.test(value)) errors.push('symbol');\n }\n\n if (errors.length > 0) {\n const validationError = {\n errors,\n inner: true,\n path: 'password',\n field: 'password',\n message: errors,\n value,\n name: 'ValidationError',\n } as Yup.ValidationError & {\n inner: boolean;\n field: string;\n message: string[];\n };\n\n return new Yup.ValidationError(validationError, value, 'password');\n }\n\n return true;\n },\n });\n","/* eslint-disable react/button-has-type */\n/* eslint-disable react/jsx-props-no-spreading */\nimport {\n type ButtonHTMLAttributes,\n type CSSProperties,\n type FC,\n type JSX,\n type MouseEvent,\n type PropsWithChildren,\n useEffect,\n useState,\n} from 'react';\nimport { cn } from '@/utils';\nimport '@/styles/index.css';\n\ntype RippleProps = {\n size: number;\n x: number;\n y: number;\n};\n\nexport const Ripple: FC<RippleProps> = ({ size, x, y }) => {\n const style: CSSProperties = {\n width: size,\n height: size,\n left: x,\n top: y,\n };\n\n return <span className='passflow-ripple passflow-ripple-effect' style={style} />;\n};\n\ntype TButton = PropsWithChildren &\n ButtonHTMLAttributes<HTMLButtonElement> & {\n size: 'small' | 'medium' | 'big';\n /**\n * `link` is an action set in running text: no box, link colour, no ripple.\n */\n variant: 'primary' | 'secondary' | 'outlined' | 'warning' | 'clean' | 'provider' | 'dark' | 'option' | 'link';\n type: 'button' | 'submit' | 'reset';\n withIcon?: boolean;\n asIcon?: boolean;\n className?: string;\n withRipple?: boolean;\n /**\n * The `option` variant's second line — the hint under the label. Rendered\n * only by that variant, which owns the two-line geometry. It is part of the\n * button's accessible name (\"label hint\"), because it is visible text.\n */\n description?: string;\n /**\n * Toggle state for the `option` variant: mirrored to `aria-pressed` and\n * styled by the variant itself, so no call site has to describe what\n * \"selected\" looks like.\n */\n pressed?: boolean;\n };\n\nexport const Button: FC<TButton> = ({\n size,\n variant,\n type,\n onClick,\n withIcon = false,\n asIcon = false,\n className = '',\n children,\n withRipple = true,\n description,\n pressed,\n ...rest\n}) => {\n const [ripples, setRipples] = useState<JSX.Element[]>();\n\n const styles = {\n 'passflow-button passflow-button--big': size === 'big',\n 'passflow-button passflow-button--medium': size === 'medium',\n 'passflow-button passflow-button--small': size === 'small',\n 'passflow-button--primary': variant === 'primary',\n 'passflow-button--secondary': variant === 'secondary',\n 'passflow-button--outlined': variant === 'outlined',\n 'passflow-button--warning': variant === 'warning',\n 'passflow-button--clean': variant === 'clean',\n 'passflow-button--provider': variant === 'provider',\n 'passflow-button--dark': variant === 'dark',\n 'passflow-button--option': variant === 'option',\n 'passflow-button--link': variant === 'link',\n 'passflow-button--with-icon': withIcon,\n 'passflow-button--as-icon': asIcon,\n };\n\n const handleClick = (e: MouseEvent<HTMLButtonElement>) => {\n const rect = e.currentTarget.getBoundingClientRect();\n const rippleSize = Math.max(rect.width, rect.height);\n const x = e.clientX - rect.left - rippleSize / 2;\n const y = e.clientY - rect.top - rippleSize / 2;\n\n const newRipple = <Ripple key={Date.now()} size={rippleSize} x={x} y={y} />;\n\n setRipples((prev) => (prev ? [...prev, newRipple] : [newRipple]));\n\n onClick?.(e);\n };\n\n useEffect(() => {\n let timer: NodeJS.Timeout;\n if (ripples) {\n timer = setTimeout(() => {\n setRipples(undefined);\n }, 1000);\n }\n return () => clearTimeout(timer);\n }, [ripples]);\n\n return (\n <button className={cn(styles, className)} type={type} aria-pressed={pressed} onClick={handleClick} {...rest}>\n {variant === 'option' ? (\n // WCAG 2.5.3 (Label in Name): the button is named from its content, so\n // both visible lines are in the name (\"label hint\") and a voice user can\n // say what they see. The space keeps the two lines separate words in\n // that name; the column flex layout does not render it.\n <>\n <span className='passflow-button__option-label'>{children}</span>\n {description ? (\n <>\n {' '}\n <span className='passflow-button__option-hint'>{description}</span>\n </>\n ) : null}\n </>\n ) : (\n children\n )}\n {withRipple && variant !== 'link' && (\n <div aria-hidden className='passflow-ripple-container'>\n {ripples}\n </div>\n )}\n </button>\n );\n};\n","import type { FC } from 'react';\nimport './style.css';\n\nexport type ContinuingStatusProps = {\n /** The app the user is being taken to; without it the line stays generic. */\n appName?: string;\n};\n\n/** The full-page line shown while a session is handed over to the app that asked for it. */\nexport const ContinuingStatus: FC<ContinuingStatusProps> = ({ appName }) => (\n <div className='passflow-continuing-status' role='status'>\n {appName ? `Continuing to ${appName}…` : 'Continuing…'}\n </div>\n);\n","export default \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZgAAAGACAMAAACnYISRAAADAFBMVEUAAAAxQ5cSO5wAOJP////OESYBAAAANJgAJ33SDzT80Rb/AADKAADzKDgEfj3bFRr/zgDoDi4JhQHuHCYAak0AlEIAaDt1qtv/3wAAN4rdKBAAN6lFjdwBMnwOrS3cIyADh1EAVqVLsdjCKC/44BUBeV0BcsIEm0oEKov84kLVBgcAH6UCrcoAZsPpKjv+yAABAHYAoVtysuEAZQAetTrfIA7VKCQBKGXoAxLiCxcAc89ZgbwdRIoLSqn7+fgCki+kMTYAAJcAAK0Almy/CS/+6AYiSaYAUMPiPShkz//vKi0MHIy1Bwb9mgQiXjn88u8AmQADUpP/xyIxjyyHxuMAot7p6Ob9uAs5XbXUIT352gHFCx4jnkQMsF83lQT2PzNwGT06dMQAjMPhFyf1gQPdG0c1qDQAcijw9fjrhoivGyfFICYAAM0Bf/7hZmk9dir65OWNJCrTrjnwsSwmQILmVgUAoeHUOkn2zM3fOwh9mcj/eQDRyc7+mTL//wAHaajh6vPxsbKpstft8e8EOLhJcLQCmbTW4O0AAP/789j51tgfHRDphSjivAztj5XkcxHd3Nn821q2t7jyvcCUlZPuxwuTy6fsoKTqS00CcGlIZaLQHR7pYCSip6QTOIbozhy0yOSKvHblcn3xVmCOpyKGg4ZDNwXaUmGtWxZeCA8ZnQJYVFSdx+iQpMfIgozTqVK/pRTA4M40UmvVrBECVj0yWpeQi1LEPi/Psqx2iqlqvHywnztjnNl0dnJIk0746Lt+CRNhaWCBfsGo27jGYVfU7N+za2uPVj5taTLcRiOUgRcmqr/H0eVwrafOxBVmVwljcawxBAjmypK6nGYzNDJaRC+aDBrg1bhETEeDbAxQs5q9toe74fX86ZVDs2HA17iwjgx5xZbHyU91ukbGdB3tvnnOViLSihZRuICCMxAyHnWquxxVX4YohdFvlUWXWn1OeofpwUrliHQaOVYscBxonhhwk3M2lnmJLU9mMnChv1o4g6QRPyIzsqcmCFcOjBeew94WAAAABHRSTlMA/f5+Mw0WEQAAUx1JREFUeNrsnAlMI1UYx0fzCoKgKBKMwSsYb0EJbjDEkSgS41WPDdatxjOkQFJgJSkhVbvbIIEC4gKCB3LstliBFiW7gNDAChYlaoUqSGC9VlQQLzyiiTF+rzOdu0wvvDK/zs61pDD8+L/vvccLhIKCgoKCwo7xwrnATYZzMaczEERKyuy5FAjRJ7MpKQShrzLV6C5NUNcY9eWIgQgI8nMyEMTHF0hCBORkETJfj4jwPh4hXdoVPNJ0+P4rPoqKYCvCe+o68PukSQKf+NzknJt7Ex842JGTnMwV81ZKStkurphdZSkpbxGExlGMSBCzr7hWs6NiNLD9q8UgtJvrZTdCjJieV3uO9zw7/WxPzyc94Yt5oCM58WDyAwdzeGJwPk7JY8XknYIzRH8CEIOAnRNTU615p6a6WzOoCVUM9amIgFwjSehivjXBofZbv5Zva+HSlEaLOT49/XpPD3g5Ph2EmAmukgm/mJuTOx7IKa5PvrkjORkxgJhz03FE/GJwgNLPBTEJHBBC6kkzGXUx1YO5+wtqCjQ1mv2awUE5MWItOyImAeB8/Vdc2A1H3QTlZUIHF90XXkGLKXp2GsIy3QNyng02MRMTqRP0GS2mNzlnHyrOOZjBF8PYQIhxJBTzzv4lqxUNRltMTS7ebxZcC/vc3OiKQZKEIQZskJSNKy4cgBMyFW75E9MDr+NFxzFBiZkYyErNytqdNTDBacqSk3Oa0EEoMfymjGm/EGJaNbopUydcinwcMx8ZrzSad6TGHHYe2QyixlzPAQHUmdzXQxZnFO8jIxHDtl/fQquGD1cwYljuoI9StRDjF9M9AF6yBnYPdHPEAIngRSiGqfgIMf0AEKOpLd4HYkhU7NDU3bWyMu6t/hWhUIozRl7MtS6n03l4p8QUP1KOUPk+pA5STAIDI4at+JgB6jpQMmTETKxmpQ50d69mZa0yNQZJEvh+ud5YA2J0NaYq/TN33dX6qKH7yIGoizl82OUEvIevlRcj1iIv5pEm2NV3ZNRHKAb3kalSIxZjbJYQk8NsXDFZ3QO67qxVMiurOzVcMYjDM3c90/rozP6xH6IuBmvBeF2HdyQxjxRHV0yaWEzhBx+Y+WJABpccVkzqaurqQJapNhVO/GJO5yDflInElD/eonv3tegnxknj3aGmLEMNpTKKTdlucWIOHEAM8jUGKozJlAU1JpAY+eLPcuzYj/VrpM70Q7SLPxuZTTkxt/FAAD7KFv/ejqaWKBX/NHpIs32NeUISv5is1YEJXP1Xs5juMuIh311GHCYP/Vw22tI8vT/aYoBNJ8ZaEKaYne8us4MXdkgDYlSSbCtmwmeme/fubuxFusbIDzARB3J87/iR1aUF0w6IudbqtG66CkISw6rZ+QEmZ/DCDmnCEUMzkeUfYU5IN2XyUzIsOzpX5joCPbJ/kRjB83IGL5whTThiJvDGAKdiMfKTmH+jmOc3C8IQA/w9k5gkM3h5ktMPCEOMEOnEyE/7Iw7/hmn/f0oMLirCaf9IxbAQCgoKCgoKCgoKCgoK/x8CDawuo9hDE0fBDKzu4EMQMRS30jD352MkmOevW4tlCDRwCzydjmhO9YFoAr5PQFIlIYgrxfz54CJBZEgS+LlyJfkHxWgZGxYLc6rlr1v7T4n5s0KrLcViEoUbIPFcuYyYwdDFkM3NowgwmlEhyYi5PhpiVIv0/3hsNg99uqjir1sTi9GqShZVqsUSlfbfJebPB0u02r59ahAjaUbiuXTVtJgx/VhoYshC40y+1gEnDq3D3YJQoU/M9f7EnHlmRGJUdp8Wy9Dc3JDFp8aOv0EJHGI3KysHxyorNxkxU4tT81OwLU5FQcwLuyIWw1oxtJc3r7gpMYIXwH8uXlM2qE/u6AwtMaOj7pl8AzKn5wPNqHeUn5iurpDEJKSXanlitFBmLDHDjfHxjcNwAg2ZSAykdG2SRCQrxh4zNT8/FWOPhpgX459+IWIxUFi02vTe+iX3+rodixERUIxGRyWmI8TEmI2k2ZHvIPtAi6pKNzpj5NYY+HW81+kUiUF8WDGlIyMjhlKuGNyY2bAXbMYGDRnc4q9bizWp19bqF9QmrhgMR8z1knB/ot9/nz3ninn77V2PPS0rBjGo1dznoqz4Cot+H0kWrgOz5kC1WfBcsdWUGarGdIZYYwrTSTK9xOELTHphk8FB15jr8dbl3WpoaHC2BS1mpnRrq3SGIwawWzxz8T7mPBa7CuCvW4s11W+1lDdURSbmhBOkxdxzj+qFtl1Bi5lcWJjkiaELS7uaBEbdWIwxkBjBc8Wi6gh6ZWYDMuYvpvsaMvfoqKGd2yvb63WCGe9ekHJvMGJGtka29LBjxWA0FzJoVBj+urVYU1XV2kLLWrhi2LDAmVDMrpERlarhxWDFqBf27l1Qs89FFZamctKHudA8u77ubg5uPV4sRW5YYs4557oPy8ryaeJUFT+fA1CJAdqcDQ17Q0iMoSl9aya9ycAXk8eKyaO/QbFcTHVra5OTdayYRbsdKtO83b4oL4YNC3sGX4+fTz30DhOMmMceWwsoZmEJodl1IwosJlaC8MQAH8bFlWAteWUl+RXX+cX41HR5n24YbvB2BStGu6XX6/u2tFwxwO9+L7+rpMSMmUy1xlrTGCtmanHePj8PBzkxbFTouAjF2Bo9MZZGCyNGvilbC9iUqdecS5PjK0hOTEGBSEy8JNuKAco+zK+4uywOpEB8uIkBMRixmBg+bI0xNPXq2w38GgNUIR9VKkkxZ1PWzuYkZgr3yqbYxNwmCUGwUcH/xGJgWDu3POehr8Iq/gBV/FtI0ukcH19YIgP3yuBpTqwGToxGYiAzoOScsvwy2LGJwezpAjWNXXuCFnPrSF/fyK0iMQYSAaSBFSM2czZngKnFfblFOMqICdhdZgPz6aefztnoq0i7y+2Ta87xpTosRnIgQz1XNfIXfXwRfmKuq6j4ENx8WHH3OT9/WHEKmxjIDAwv29pgiBm8GIxQDNCLgF6VpBjgpDvvPEkwJWO3431kYgCLx2OJ8XgiFcM0aS243DBTMtx/ibQYzTsIvaPxe0HVYScGwpKCd9QpkxjhyP/eCMQALQi1qKTFSM+VabURi2GxRUEMp9xQYgIl5sTu7hM5iQlfjBjJubLIxNyrVt8bihggUjFiojiJyU6RsUdaTMGJJ3Kqf7TFAFEUA+j1qv+DGJlp/xC7ywoKCgoKCgoKCgoKCv89zqdIiotLOp+FIB6WhCBOGHz+xMrhtiQuF19MECdR3EVDXxLEGZIwA71LaBIpCOJmSeT+7oC6RS8YeMK9PhWPvnL88efRxPMI9P789WAJDARxgSQEcbUkBJEiCUH89NTlEmwr5il4MRu8KDEXn/S8Kbey8d8mpryqVyAGaOfeakJIRozOaEZq8xJAqum/a8FfD8YTsydcMYcOccXExDwZohgxl/vEXHzCfsgMNpOJX/8SMe3CxHxshtv1BhWNoQouzV9vI6bQ2OlqRiveccC7hFpdRiNC/PVgXDGTx5655AKwE6qYoveSkt4r4oqJ+SlUMZcLXgAWw89MsGL6Z/tv3zkxLfp7BWKys1+F+2QvTMeXt/TpSbh4NTt7GzEHXK7WNfXouA/y2IrVZS2E90+QxPd5yTqfncavQhBzKHN4bu6rzEOsGMDyVGSJocXwMyMWMzwsFtOfAd/1jP6/rykDMdmfkYgD+Vn2dmLIVhAzutTsda6seFcKFzqtLpdRKGbWaHTnGY2zlBgA2/GOgJ09e4IRU9R4T//GlVdu9N/TWMSKAZ4LXsxpNB3FB09jwWL4mRGKWX5s2fPYskDMR4kUH4Ui5oEHuGJukCRwU5YNfPwmAkbdWNCbH2dvL8Z61NrZeqB6LG0M1uDt7+xsdR01CtaDJbgRKllEyA1izH4x5TMz5eq6Y8dww7YncKcALNz3TWZm/8bGxp8bV/ZnZn5zHyMGsP14CRcQk0QDYjgwYg6WH8wQiHmJyYyUGJvHBptAzEgihSEUMQ0NwYupl2jKMGa/GDNcbCsGNbtcVmtrdWcarL/7dczaaj3aSQrWgyW4zaN5FY5CLMbykauzuZBEjnTAgUgdAjvPcMXMvdXFE/NLY2bmY2NjY4NjmxtXDiVlNv7CigHGBWLiJGHEtDSddlpvfQdXDDczYjHDtuVl27BATKKf4MW8GA+8KC8mcFOG0SEanawY8gB46fz++zesm7//bm1tdbU2C9eDJbhrj/z67g/vYDExmPk8q9vocJAO9cw+hGHFdH3x3a9fdLFi7h7KzMxMmtsANsfGKmeT4HLobu7vh8IQU97BTwybGYnib4Hfo98Vvpir/BTFxxcxF+E1ZViMDtyQZkQKxZzGA7+P8ai1dWlXRkZe6aUJ3k+g9iMkrDFux8tvfeSaocUAU3ZYR/2bdcbdhwRi2l5+/deX2zhi3sNiZq/EZv6sHPNmAu8VccTMRdyU8TIjFuOxWDx3hd2UgZiLfK+rjh86dJy6CEJMS8CmzD0DjVme2SwrRgd5WZp8w+V6f/PopnHyQKfLKCGm9chsq0/MnMdmgRWh9rx5WINYYq842mosZMUAX8y99QW/KWuDjGzQ7M3MbOM2ZZbxS7iEVfxfuoWbGXGvbHkZdtLFvz/4xFyUfdVV99GnWMxZkvjFkOqqXuniPzqKULODhOIvIwZitYRQrabmIY2mGqHCQtIsErP++mzngdmP10HMjTde0DU0t25f31Va+rZ93o6/uR8cZcXgroB08ccIi/8fTwXdK7tfEhADZniZEYkZGpLvLssnhoI6pcW8INrO2rYpe13cXQ4shlpsSaIBzebhNB2cqpGoKQMztrvvttn8UzIgZ7hk5O2Rkil27cApkoAYzC/QXb6S6i5DXFgxMMSMhhgmNFRmgh5gwj6ExOAXLzEvSJhhmzKDSMw0Z4DZix1Ny4kh66BrZaypLsRHJBYD3Orx3MrOleEa/yXw1dCyzSIvBvgm86vZ2a9wXFgxMIqJhhiwAi9eZiKfkpFPDNYQODGovKpJMCXzJn9Kph4uzR9vKwaAJf2fA0M/1iFWzKX+TXoSMz4eogPhee/TZZuMGKAIfpAb+VMyTwY1JXOtrBhshtrRmWmLXIx8YrAVcWgCN2U4Iu1x7J24dgQIxCQLxOi83iV1XZ15xTnKiJEExIjAdmTFiCcxcXmJSmJ4QGbeyX0tumLEyBd/ca8MZOkF0/5QNeQSQzIVKXQxGFkx4mn/y6UgFBQUFBQUFBQUFBT+Yu9cYNqo4zhOliuVDqc4HRPFB3uolUydoSbSNCQqqWRaxyYCTlDBpECsnWO8skU6hgsEAddJK+1QHgZfcw8UeehEk40hY0EUUaaiUzRzjo3pdLqY+Pvfo3f/u//1+kDjkvvccW0vGdB+9v3//v8/91C58NhARP6Endr6dlhqo3HkTyy6GEEJoHfIX4j7SSmtL8EfsuLj4/ftiweigHgOycDt+5sQdREI4r1R8hkoltsY8OPHLvIREXEVi/hYg2UMGhYdg/xA+FIiMDAnIiOmziwvxr5wBSz28MXkHMk+kUMUMyLWUmdAYt7Ys+cNqRiil2uDFYMfPyYSk5kZipiNG+dQzPQs2nrNfsTUrkiDRZqYKxniV1dXVFSvjmdf+hFz5GxOzhGCmJGRl0aScS1IMFjo6lJKDHh5HnkJSsxd8IUfPyYSU1ERnJik8o1JcXENDUlJmJhbxEvAYmbHMjIax8bOmP2JscMNM91pdhkx8dXbpxDV8VIxBQWYmBdOXIaJyelgxJw8pjt2EtMCBNaUfQ9akBdMDAXIiwEtCHxODBOTbKUoa3IQYsrj8vNhE5e0sSGAxFBEcDHTGRnWjDKH2xxgYvTsyouJb56aam2daZ3aC2ZEYtrnz2/HErP442wQk3Mi+6WOHCTmLNuUHTv2l0iLp07wBpAYwRsQt2PPg5dgxAAkMc2jo81sYjIpKjOYxGx8aPHih1A7BmIUEhOgmDFro+uMqx6Jkf8HcI9ZWGSaMuP2qYnumZlDPVN7jSIxloXw0Vgswhrz7ZGcy3KyF4MQltdzkJiTT14t0qLTyYvBvTwPeQlODBMZ7PgxaMp6m1tamnsZMRWAPzEGAyYGknLPPdCWwZOkABKjISIUM7thtrFq4ozTipoy+dOuy+imrIwspnqqp253a/fg8Z6pakxMe3tu7vz5ubnt7aJe2YnFHXQ7loO2Zzvo4i/R0npSUQxfXzAxlA+FxGDHj13UjNICW1pMKqz+xDQ0iMQ0wPdPwss/iCFEJiAxE1UZYxNWp/NMgdufGEgMIJeYiqmqiZ6J6aM9VVMVuJj5LGIx2YtpJR1nueJP0AIVR0kMX1+CF4Migx8/dtFoCxLTMhpAd3koXadLH8KKf3lSUjnKC5T/8BMzXTnhzMiospnj4syBitHDKhZjgis2wpXwTCIxCzkxCy1SMRxnkRiSFiRmDQcS43sBYvD6IitGqSm7SIBQjIGIIDFDOt0QubsMWngxVxJRFjPRaDObXY1uN+TFb40pc7cvbHfLNmUHGptGRpoaM0RNmT2X8ZJrJzRlHDlIjFSLghi8voSQGIIYvilTFuNtaPCSxDRA6Q9fzGxGY5Ujzn3GZXWwYmKJ+Ir/Azhc8d/b1AS35f69SVL8LblMXihcDF78kRiJFmUxeH0JuvjDgotBWUHFH3JDi4kTrbgYA6zkkX/4YqYnGgt6bBCZOHOZ0wwod5fJYuKrG6c2HW7cROguu1z19S4XJRIj7S7jWpTFiOuLshjlxICZd0ZH34H2TDkxNCGL8d9dnnbU28wOl5lHeYBJFgNm9jIDTMLI3+n0O1d2lhlgErQAguKJxAiKJ1ZfQksMrPIjcCYk7IbLTAhiooj4FVNng6SY7U7WSTiJATNGNCVjjA9GDNaU4VqUxUjqCxDClIy8GBJzKEZ+SsbLqLC5zTzKk5giMXM3u4xrURbjm7cMUQygIIaNSbmBe4j7T8QMmUkoTvv/a2JwLcpiOC9hiPl/JkZFRUVFRUVFRUVFReVC49yNJOQu4Cw/IDJedwUB+bmgXiuFoXTB6m0rScAAlgYNXIVERCxi0ekiIymKexURcQcHBWg4sBOOsN9nMZGIiDuJyA+0B2Te15JDa66RAmI0d/8sJ+ZKemWfwMqK6SWKuVm77Ip1C/jliv0z6/yJaXnncFBiKOubF7SYaKIZ+rT9lENEMRrNOaIYTgcs/ApiKky7aBd3cCuCvrT8i1csEKp5eoYkxlJjYsS0GHcFJYaitoUips5bWGhzBi5mPAVOCnSZ5l5M9OdyYpCbp6RigCwnJcJPYpp3jV7UjMXlDloMcOV1vJqZjo6OdVIxY9M1bGKA0aqgxEBoghaz/u689evzCtcHKGZRIfO61C4Sk9318eD4x3uywxATvUpOTBoQNbhGIgawWSRiWD78UKCGqTHvNFc2G4VaGDHAVSg0VzB2OtL7hWIsH9RYaqY3T5soToyxxQjNWRBi2NAkrLz3vXthG4iY9YXjUUuWaMaLUgITA15Sxu12V2epWMxzLxzak/1cOGLAzCckMRd7N3u9m3NjYqDc4GJKS1FoSGLAyr59sMWLf8thaks825jxNYbBuK4/HYwgP/3p/bwYS00+0DDG1xhjvBFCU2GihCjecJQPjYIYHWIDTOAaTp3K0kRFbdAhFMSMg5f7ocZYLK5aXMwLHTMjIzMdL/jERBKRv3VWNEIvbpqQmM3eGG9uGmzZcsOLqa/XiCsNIwassFu8V7ZlV4W0+LN0z6bP7u+H1Kzp55uymum6zbSYWZNPDJhBbporAxZTW8uGhgf2E2HFeMcL87Le2FealzI+JL5a7Kbeg9spDlYM1JfxBQuctTY7JU5M/+ntI6f7swMWY/qgpuYDEy4GcKBT32stAjG5m2GFrw0xXLlhxdhMzCnxWPeM/gFff00hhM8YMS2wQFhETdnWj7aCmNn9M2vWwGZmZg3fXZ5uyEfUjY1ZfGLii1teRGaMWwIU48jNdXChURYTiShKKcrL+ujt9XlFS4rE/6NHXjn1u1gMfAqLFiywR2naaiVi3v/jm/eDEGPZPT2924KLQdRTHrvLJRDjrQMx3piLN6fFsEC5oRPTSVGdGpKYDz6gEMJn+DgG75VdlboVzDzdP7Pu6XS2zvgSk9+AvAhvV0gHphg2xesv4fGbGPYPblV9fJFUErNEE5X10b7xvKJCiZidg2/IiKnVaAp8xf96htX9506fPte/mn0ZiJixMZKYAhDjdArFQFrqvDFpG3xinhi9mhZTUF9fIG3KNETkB5g3g5StydCUpafvn+1nvPDFH240Og39ZJEYFJh9RZcEKMZUW2uhL9VzDY98jaEQtvGUvLxzl3+WVzhuoxACMY2bNjWSm7Iye5udwsQA3d2vvtrdfX3gYsYAqRgXJL/TbhI2ZRsurttcF+PdcDFj5VTy1VczYrLQmuWghMiLuYcIiIGGbGsmXWRmu7khjU+MdZuVAkwHqkQ15lEP6PDQC0LhdAU8LspiyqDqF716CG60qnGK3xcF3MEhKv4mKP4iMatXDx5avZoXQ0nBxdfALW8DKv5QYLze3PRcpAWs0Mh2l2VrjLyYTMYLwA5phImpGmk6YDIdaBqpxBJTnEJrYfEoi4G4YCh1l1OWjGuK3i0cL2S7ywpiCN3l630YjbBRFBNJhO0u/yY9xgFseCExdeCldBSUYGIgLiIUawypV3YVKv7wxQ9p+O7y3qaRAwdGmvZSgsS0fME2YxpwoqGfyZ9HQoiLshg0kGEHmMpiyAPMhURCErPq9suIYkBNGiosAvxNyfCjS9hy+BWz9SrYoEdGj3GBcEqmam9l5d4qSiCm+ByY4BoxvXximNMVCHFRFgPUDcGUjGORghjplMzci/mceFSQr7Bg+JvEBJjRJWwDErO1IhUZ4dFe528Ss7jwEga9qMYQAgNiCHEBgp3EVBYDUMDcizl+mZwYsCJGedqfs6IshsSL8m/gTzCBoVD8IS4XtBjwQhTDFxZMjIqKioqKioqKioqKyoXHw0RggEZE/ngzigauu+PnPpIJPvD9wu+zkgj3/ZenpS2nEOJpeYoll0H+wtqdlqpqLYKCH56qBTJdHhc78PR6hRtAMJCcD5BmkWMAxVl55dlonH9dDH4dMF4Mvv+/FGMzlFG7hGIqbIZa7gMdGsI2cy/G7nC0lZa2ORz2sMW8CJeef/ZFqZhiNItWrCQGvw4YLwbfj4uJZZe1a9nnQYoxc2LuwhdGDOSjgNqWyolJ3W5oM1mr0Qe6/yUdxkv7uQ9UIxSjEX2g9y1del/AYizuFY7oaOcKtyVcMc+WlAwPl5Q8u2jR5UIxNxd3a41GbXfxzUpiogUkJJ+iSU7A92u178WePHnyaiwxb1ZWsn/cjw1GjFkhMdp520tL7dZkRkx1gcdBHU7Vog902XUnhF5OXLeM/UDhg+XFwAtRYpYuDaIpW6J3rlpVpl8iSp7DlpVlc2BibiECYlgvf5dM9sHmWSwxfFSKgxLTW75xqCE/7hWxmHnvNb68JXb5PCwxVivzHAglMUTo3z+5zeOktiAxW8ARVQG7aDHLlkFofHGBlzKJCUOMPWXA+dprzoEUvCmrj6Kpl4h5rqvrOZGYpYhjJSWJw5OTw4klJcfoHawYyAsDZMavGPw6YAm97rqhIbe7NwHfr01d/rLFsu1kqjAxqCkDkJtQaoyOCPP7Z/Z42kxIjKGAqszU8mJQaBqGhhpQXACFGkMUo/PR1SW9ybbbU7TC41lR5HELv48jisUhEvPQT6+++tML6AmsQjGTw32Tra2tfZN9w5O8GGLxjyeCXwcsYWTH7522vp1rE/D92nnLz58+fXo5X2PepI0Ab3LFfzkDiBFCEGOG1Y8YCsEXOBZazDokYxBdf2yQO1dc/uCQGMR9aANiAOawMOHP/fJL6c+t1+vzAL2+XijGxomxicR0/XD8rd1dXFoe4sUkPjjZ1zc83Nc3+WCiUMyHRs6I8UO/YvDrgCXE9vR0dh7tATHYfu28l3d0d+94eR6XmLWV1rX0o7VyLSsmjUjwidFHk6DFHDkCMn5E1x/7MUAxSwWIxHwbCXwrFlOg10d//nm0Xl8gFJPFicnCxUBgxne89QMI4eDFJE7+NTz812RiyGIShPRGAU880ZsgTl7sjk8/HVnJFv9YTkxsKGLM/sUQvehpMXt+ggasCF1/rChcMcCeyMg9OomYgU+iIyOjPxnwiYkC7BSLnTPEitn9w/HBH3Y/RGrKhoehLaMf6B1Bj2NwMe/1lHV2jh19TyJmdOfOna+MMmKAcJoypEapKeMKHN6U0XVlEF1/LISm7D6xmC8Byc+1DQysOn581cCAjRcjKC0OoRigH9WYfnLxn2ydhFVU/I2BF/8EjJcpW+fSowkSMb29Bw/u6OVrTCjFH0/MY0TY4l9JFRiQGFObp0dS/A2G0Iu//MBc76N8I/+cEdNGsbRhYsjdZTPN+ZLJxETomJWcZ14H310GGyu5FfiqvbQpQSKm+egrmzbtPPgLlxiuuwwPwY/8FcVUUPbS0i1IzBbK6WlLDrK7HK6Y/HxcDN9Pro/i8DPANHNmShITS8CLUAyADTAVE3OvoMz0JkjFGHegu4G/b+QSww0wQ0uM2a+Y1MOUw1NQnYrEaJOt4Gj7vHAHmLiYy8UrLmZjOS4G0eaw2x2Ql0DFAAfPP554/iD3KvgpGU7LvZge+Vq1EoFNyQSbGLffxFRbTW2G7alaRow2dRtV4HFlhj0lQ04MOAHEYvCmTISyGCJhFv+VgYjhG7DQBpj+E0PVGmww1mfFALuoMoNt7maXkQ52AdCjSExc/v9QTECJwZnrGuOCfGh5MUB1laVz7maXF5HAxZQHIEZFRUVFRUVFRUVFReXCQ0PEt1/HchdDRMS6HBIREbcCFHWrCPHxYzf++uuNzEByLQPFwr6EE3mI8L+neBr/je8euUGK3IWp5a8BcwkROCGLiOJBF8+wKN7A5waGf9g7E6ioqjCOj3WB5BRBtlmRLWa2YZ0COkEvKi1acE4bBtppgWqgDmJp0EQlTEYMm7KHmAgicJByKFYFJRZXUBIUEReMgMrMRK00q+++fbkzbwbEljO/ebz3Zk7pzPv5v9+9dx7vIZb3GGwScxctZsoztohRnD/WOeykIuZRAhbEdCTGmIbusiTG0/P/LeY6eICY+z5UE4NEKM4fu6Cr00oxj/z88yNWiHEodaxCuqYhs2I8I2L9rRPjCT/V1X5+9Rt/q4ZnvJgn8AKwu7aKmTa2YhjwB3vYJjEXipg6f/7Uzs6Jle5WiBnXunp16zgrxDjsclwFF0EzZO0nivE8hrT+nlYnpv70S2UnGxuPsp5Gn5hpY52Yu9jEwKeYQxKDeO4UIRXjNL/Wu7Fi/o6JVoj5efXQUNPP1ohxmN2RePCWfVrUAuVGJgaaschobY7nVZ5WiqmubW1ubm1ttdSUPXFOEoOIWEgMgC9vQSWsTxCuDmNOjOz8Mafbbisre+gJiRidoYVSivk9v2nOUFP+7+piMKWO8PX6kvUUgnIjEuOZcyzHP5JKD4uOPsaJQZjVqxEg7AnvPzLHqC2k0ov5z8WauA0hSocQ16iZPW6CGP2yZfrR1JgniFhIDPAThRAV2JS1WCSG3JTJzh+rmD+urHHcn6t8BTEtTQl7s1oUYn7u7a3r6+39WSwmPNycGNycJTtjN7jcCGIikDY9NhYas2iU7SkS09uLAGFPOKDGMJoUQQwLQidPghjASjFtVVVtWMy0MRYjJAZYhxDS9dUtRGpiZOePNVYMd3dXHE70FsQcMCXsXmFSiGnt3ZaWtq23VSRmV0fHLrIYYHap4xZnzD663LBi/LXR2mM5hceiI7Nz+MQIYSEcUG1kQWFkTlikUkxcWlqcLWJ26vU7z3VisBiKioyklImRIf1CbGJZ99ETJ2prE/8UxJhWBO7+tsUaMQ4dHbC6WYJFMWCmMFKbnpOTHuvv6SkXA2EhiZkUGz3JmOLPvz6eBR3e+NthxD1TF5O294or9i4TEoOInOXE/KSDwODrfRlsE1PR2Fl7ZGWut1gMdeTA3iOUsil7rNd0sqdH3JTNDg+fTRaD07TqS3lTBkDNP5YSG5aOwjytrDHa2IKI9IiwdIUY05FNm46YrBezrO2KK9pADDAyMYiI5cTQTVjg4sWBqr8ZJRVT1thV37bC171e1JQhymAgFf/TbbWnjxYpij9ZzAbH7aTijxuzyEiUHRlthH3LNWYqS3lYQXpEytfsM5GYAyZYBDHXESH0yqbBYyRi5hKxmJjfPBVoNF8TkYoZ7u7qOtqTVlTkrd5dbu7raTvU/KiKGMvdZSAWRRr9o6lo1e7yVI6M9KXRRVMFMVJsFwOMqRghMYc9PSeJHrBgMXcSkYrx7uwcHr78cEWZuxUDzJ+XLGkepyZGbYDpnxKbAsPL6GPqYmSQxfybE/O8l6fnBMkDzKg0ZRxde7q7uzq7vp9qzZRMK0zJqIlRnZLxBKBBgz2bxPyHEgORYSYxb/T0pHPCbyaoNWUCw4PdTk7ug11WT2Kqi1GfxMR6/kExEJhzkhhCgbG2KQMnXd4w9Q+rkUz7k8V0WzXt/x9MjB07duzYsWPHjh07duz81zA38HEjotG8T8T8F0FziGg0E2mQlxeaKEKjuYwBsdzIoNGEuGUjhoQExBDrEaLRBAevfEbGieBgc/edtPVC1uaPw4NE+OOwlF4tXcofh5VPk4ABppjXlmeucsT8e8RMVRNTEBLC3LJj/S+/rEcAFRESUqDRbAkObpd6+TE4+CC8n/COf1KM10D/QOrggBd/HJ450a4q5kfnNYmOnJiPiJxbMVMZNVMticH58IiGV7IHFuDsRMPTWHxAt2cGLz8hisvy4MztjvT7KR2BmE52QxAzYYL1YiAtqcmDA6LjgP/FWBbzWrvzHkfHxH9ezFReDN5XSww+gSUkJAWhlIEBvA4JyYlkDmjiGlFztjI4+Ev4bMz72WVBjDEiKirCqExMo+O8eY6NiQoxj+MrZjxuhRgiIAY4kWlBzLfOyauKutN4MYhHp1M0ZUFBbh4FzW5uk2BnhGKyiFisMdeRxdA2CiOjBwaitYUhIWHCAd3DN2ftwcFbHAH2/czuMCcmezpNtkJMd2lEQWm3oinzD8XXcgn158VcyOPlJeyLjsPAoCwxDQdaVjSZm8Sc8yO+LFA3onBWE7+UiFm3TiEmpPXzmL2LPdy8Pm/m3pDgMT/fQPhqmX6NovjXKQ4UGYkoDtuLP0Js+5VuNNIb8QFdlRwcfAL/iwzmi6cDQxhF/E7eOJ3FKH//2icLCp7Uymvt46GuAYBr6OMyMVFwO7gU2NwqF5OaCQyKxDToAhtMz6yQvx++6m+Ht52GdMs64WvyWSIxep+XX/bRy99QVLNbkK7g3uLP75WLMZTHxZUvVIhpMSEdSGsyyT8wlZ6dna48QRDEiFERg7S44odBcLTSf+mJB4ODf4SqD8WTFxNVEETfO4kkppgTU8y9/iTLrl3Fxbs2cM+445A3a1ZqXl7qrGl5UjFesXBry3S4J5yXTMxAZqazc2bmgCDmAFqBM91gIohZ6QztL3yKxM5l8FGck5aKxOQ/r9M9v1ouJsTt3uLduyM+L3CTi8mP27EjLl/2gcFISxbE1dTXp5OJiQ6LzQ4T3WbQi4iKGCA7BMhW1obtwQAUT0FMAVXsAARlE8QEcWKC5GJKS6OiNpTKxExIhcDk5QUETAudIBGTYgwriI4OC4tO4cUEOcwGkpbj78eWJ+En8BKI0aGGZ5qwmhVyMXPanbc4snTCiYt5IFImJl/ZXY7S7U43HIiySgxlyurr68lCLUM9PS0yMUZ8V0ejdWKuk4iJkoiJdTMjJhPEbBeLCWK8RCObxHSURkSUdsjF5Lnm5UFc8lxT5WIiI6OjIyON2ZwYo9aYEhEWrU1Yv2QJ3F46OiwiBV5ixRzAYjZJajA3eGGjvsd5Fu5iy5uydUoxe2vc3DyiQtysacpaerKaAKoFNnIxyJiTY0Sjacr4wQs9pJGJYZuyg4IY/i5wtjVlpRuqITHKpizAP/hK/wB5U1YQnY6Jji7gxCyqXLS6N9+nMlefv02fW+mzune1T+UiUVPmJ+0c0YMXrjeWuMY5yQGjVvyBqJhiur4oir9BWfwNvCikLP74zM2zUfxjETOkkRf/lfSQP1la/Oe5SFEv/jW7IgqerFEW/+CA0NCAYFnxL46ONhqZn2JWTHm+Pte3Up8f51PpuyguX1+Jn5TTxb+loeWZk2/Ieq0weOF6Y5D6aZuZ11W6y4yZmuYQkZhLiJgfOYcRGYkYfvDCDmmk3eUTXHd5j0hMl4sM893luzlwr+w490TUXYaaIe8uL42NzYYlm94sZcXo4xYaFubry7cZDPHl+nx4Eqcv57rLGxXDieRVfG9si3OAMFOgPsC8t7nZTS7mL97IX2pibiUiEzMVP9TGMZHc4IUf0ggDzB9FA8w1/ACz20WOqOYVBwUVG5FCzOt3NzfDisX2AWauT+5TkBKfRZWVEBmfyqfg4YObMqBhkfKiQ458b+xL51RemLoYIMpNJuYvWPgHXo1IDKhgxMCWwcliYtL5wYswpMFiVsHgRTYls4oWEz7ThSSGCIghYvuUTPy2hfHb4hfiBfa4J7SYoy8rEKaCYPCy2YFnBJOYl7AqmB9YzlJi1ObK2MGLgJaZxORH/YAw+gcxfpe7jF6M7ZOYE919c/WLfN0nVvr4VMKTRfQTXGNOv2xWDDN4cRidGAK2i7G9xuA+soxsN/K0/0o87f89aPgnxMCHgIu2TQS4Nd5oNL+CBrNimMGLWIwdO3bs2LFjx44dO3bs/Pe4noj5gdgfD5Mwf1/L24mYP0dgAhGN5jEiGs0FRDSaWUQ0Gm+W6RLMXczH/J9zERGNxo+IRnMvEY3mRiIqYhYvRhywz83m3kQQY/6+lrevWDHmYqa6XzBVIearr957b1aJ3zwBvxJGzPz5/wUxFi4kQDWWpVGIhkora+Sn2b9SijF/X8vbT50aazHuw93Dw7DhH4KYwX6RmP5BRkxtLayQgHAxH/HyT4uZQIQ+0Bnd3WUGhLRwsHVl3Y1pjBggUREa+X0tnc7b+3QGm5g6zsaZM1vPhpjeXpmYsoN79hzsJiZmnhi/eVhMLj5ZJNe2xDyNl6fZzViJCQ8niSkMC8uRiVncXdYdg4wR9PcWMfXd3YtZMcClamJ8j6+qkIkZWnGq7gwvxpsHWhYecYKzmnSIQyxGp5OJ2fTW2rVryvjIyMSUwOJXUlKC1dCJqUSo8tw3ZY5ERGLe+P77N5RiUlB2LAqTitGllRUhY9Ds6dNnBxlRUVmajhMDICny65I5jas/fPg8pilbweblFNxvs26rXMz8eITi5xPEmF64q48oBiGZmIotwHwziQElg4MHB2HDianV62uVTRniickQ/4O4lIjZEqAuJsNgyFCKeeNGr85OL9hIxeQYjTmFxmghM2zx16EI8OIwfXYx0kFelGLI1yUDL5sHBgZ+p8XU1bGBaYdTGU+dkYsBL2BGKaZl6IX9QwsJYnpjYnplxR/+R1hziSGIKcGbElbMfFiUiUE8GY2LpWIulz/MizH/Ou9lcZmjY71jolRMuJ/fvD/+mOfnFy4Vk1KA12FhUjGA7jdo+F/64Ycboc6QxJCvSwZiBlLzNv8sSsyZnp5DIGbFmTqpmEpEU6kQ0/QC0KdTitEVFenk3eWp4k6ZTAxIOXiwP2DWrH5WDMaimE6DWMzlZ1eMAZR0xhjKZGI6v/oD+KpTLgaF4RVBzPyXwl+C73p+VxXjJOGRZRnlGXqRmLpTZ+oOtZ/qGWrfapUYw9ALL9z1AkRGIQZ1diKRGAciksTM+jIZysI0Woz6ATV0OhaJxRC8nHUxQNcf8+b90SWvMTmosDCnkJI3ZYE6lOvtDnjvQLpAW8SMqz3adrRI1JRtrTtzpmeo50xPnXVNWROIgbbMpBDTG7N9e0yvDWIOzmJhmjIhJeTE4EOWmKZSY0bblBXJmzIAJ0ZZ/MNSEJVSQCj+8Z95g5fP4mXFf4ODFJmYw0nLahuv+KJKVPzPAD1ntvZYWfxbTC03v6AzmCi5GF2Vs3OVzhYx/YPJgyUB/YPWidFl1NcXxSAW8+OMd4iMvPjP+6qz86t5suIP5ISFvajoLjeWxaD4XF/f3HgUU9Qo6i7vcrAspn7nztraop07peOYoTNDdVZ3lymTqa+F0CvTwkVJk7XWiwFKBufNGwQxFpuyy4iMgRgMQUxXFzRnXW9YN8BsbMQDTJ0ODzDLipbxkQQvZDEC44oycs+TDTC3njkz6gFm7y3OwC29toiB+v99Caz8zCdm7MXMISL8+fPo1aimZDrCHVTEjOGUzBJnmiVqYshTMv9iMaOfxOyY7aAm5lxNYqqLgZzIJjERkf+YGNIHKHUAbBED/CNiSPyXEmPHjh07duzYsWPHjh07/zXMDdAeYghm4S98/RYR9WnwFyWQB6SfbdRoXGfMmLHgVmDajBnT8HYBvOCq0bzA4MzCv89pRPh7jt3Awt9z7CYicAV2IhqNr29lbXx8ua+vL0LCvkZzORHz59chREVSiEZynC8mchbF6BEBvWUxeifMRLxgKvpT4TfQAmbMuPJdEBI6Y0YAbN69Em/PnZjTRUVFGbUiMUBuHCcG71sSY/78OoQiayLHVswbCrCYiXqCl4mWxcSDEvpBLxtTU0EMRMQVzMAGkkN7cYWNJTGu3IPfsU7MkSNKMS8XJX33zcmdSTt9xGLy43J5MbDPivmKfYj3zJ9fR0XGpMVEahkx45nHGImpHpCI4c1otbwXy2LyUT6tBFZ0XBgxQMAMV89bPWfMgJUrjo1lMZyMJUu4XVbMVVfRYrbCQyHmuiM3NTTcdOQ6qZh1rV+k1e7I9Un74rtrRGIqy3H7hRC3L03M8ePixFwoQiwmsiYtI63GeBYTcyUsSjHVb9zY318NG14MZ2bf5Mn7WC8Wxfjkw6v5PkxoIC5A0npGDIQGygtmGsRFRQzP+vWypiwvz0Jirrvp119hJRHz0zc72+6ozMiovGPdzrSfeDG52+Lzc7EYYV9IzOVz16yZSz8hidn68enTH2/FYrTGGPCiTMxUItaISV7zZbJCzI2D1f0DA/3VgzfyYjgzk4ODJ3Ne1BODvbBxSfoGIRDDEAp2FtAbFTGv8VCUsE+LCQjAYraSxEBU2hYa2iA4IjF3lK89OmXKh2lp10+542irnhOzY9vCuPxtWAy3LyRmLvx8+SW7A8jOrwMxFd0gRlpjwAjDqMQkby8p2Z4pF1P9FpgBL29Vi8UIdYb1Yk2NgZ9NqcA3FMJiXANCF1yFXbiyvbKrFoQGuKqI2V9XV9eEUBNs9svFgBqFGIjKpVkIZV0KO6LEZHzx08vX+AQG+kCF2ZnGiRm3I36hIR+L4fZZMV+BFK4pgx0cGfn5dVtvP93AidEatawYPjKjEHPll10gJlkp5q2SqvqNb8nEgJkUByAFvNBY0SubOL8EtHynZbvXM2hm4dqPq/8s5rmamBbE0sKLuQrb9jfXlLX1YDE9bQ+LxXxdM2VKPgLiQEwNIwYR4RKTOZdNTiazlZ5fJxEjgL2oJwYREYs50rBJkRjISlVV1dq3+oUaw5thvMjFyC+EwIYF7o0Jx++LBAQsLH9eEJNqtZh7sIkmRNMkNGWbnVNTMxfgwMAiF2OidC1gUUeZxGJqY16Z8mEcQs9+OGVK2g41MTgha5KP0/U/eQ2XGCcJH3/cePfDSjFciXGAz0tEXUxw5p49W7YoxNw40L/2SNXaflHxF8xgL6pi2E4yjksS1qKLW0T3XlxnsU3ZNKEpm2WpKePM8F7uYcVkzgoAMeTEtOkQMuATTdrEYir2rrtjSvzixdum3LFu2Q5rBphzp2WunDt35bRpODkEMRtLvn99e6tMDBeY8aMSAxdm2RJM6JVV969d2z9QJSn+7niFAPqJihjaSxnuitG9s/OcMCMv/gcQYKJ3OTFJWAy5xvyaZTK1tZlMWb+KxZzeuw2iUlQE5SWmBhxZGmCyHbET02hOMKMZhZgd4d8f/34HOTGA7WJUxzHQI4MCUy1PjCBGvSnDcaG7YvH6R5hWjRfzrtBdfldFjAcLhbKzEcU9Y8QkgRishSCmra3n11972toEMZjy3XEfHs3IODolf3e52gATYHrLycl0f5mUGDDzcyt4IdUYcDMGYgAYx0BcRiOmDHfFoLCI5mVsHGAKYiIiCz08CiMjBDGT/CfBgqUQBphgJgsAL9KRf1tNTBEQ8w14URlgsmN+FiExSpRi+PJv7iZ0lsW8adOUDMadF+MOi2Uxn21M/c4AhYUNi5CYd+VTMu9aIaZQ2GCsmJLpgdAo58r0GUUZsPjArtoAU1DDjy+tFIPDglcjEGPrJKbtiano/yKOKSy8GkA6iRlqxSSmhxSCmK22zS4fLSrKpXdUB5jyxFgthovMv1LMzlooLAqYaf9Uca8M95tdbRcz+ml/lQGmEpvEqDRlduzYsWPHjh07duz8xzlfY+dfiZPTWKoZT0T8y5wdHcI+/+vViIUfKF0t4lUejea3T0loNO5SPotD6UH4772aiEazgIhG40JDIRaKec4P3BALP3C7g4hGE06Eu2YM8vZGF4lgxPz22XkKNRcQYc83u+oq+nyzK3nMnoemLqZ0A1A6cjHj/cyJqQA4L7kLqbDxwEjFIKClBQHnUsyrQb9PHGeVGPZ8s9BQ+nwzQQzhPDQf68RsKO0ohWWDSMzl8CCLqUpeU4+3iAf/+dMriGIqqjIzq1gzehRZDH9rUDQrxql7C3w91+0kE/OueFGI6cs652JeBTVO58vEuCseWAwC4iqG4xAgiCGchxaht0YMSJkeEjIb5FiRmCpX0FJ/WJYYoIwoJtPVNZMW47sNxQbBfxah1TFiPls5efL2VZMnr/xMlpgB/MPtvCsVY2poCLRSzH1nTQzgNx/aM/XEXHhV6K0Va9Z03xr67oWCGOJ5aIIYFwliMRs6ds0OD5+9q2ODFYnJ/PLqqw8nJx+WJWa81/gCCkkRi1mkowpwXLJRywv0n+MEXiavaofVSiermzKqbk6D6ZwnJjsW1Pz22Tj1xFx4a+qF3mvWel8YepWamOcjpGL6AutEYhyIsJeJwmKo3TsXy8QkM2KkiZm+ISA8XH4PV6Ep+6wcGaPgb4wyoqybL6MPRAko2ZK46iBsSvgDgTgijx3TIg5BTEtDQ0OdQV0M4tAmJGhVrwFjWUxhLELpBa/iUnO+WmIQENc9vI3UlAnnoekZMxIxWajPxSoxl+MFocU7v99oIDZlksR4lW7fsyfPa3qHRAxf/CvjUcp4oIAyDF12GSPmIC0mcQ1sDirF5C1YkEQQk9Ww/zqXLHUxgpfFuwUzqr+tAGLEsImJpVD0q5jpP0B7ZkEMe75ZaCp9vpkgRn4eWoRe2ZQZ0HUu1ieGCty9c1NVDEUq/tLElGw6vDcJ/shSuRhMLaWlq34sMt11GScGG1meuGo5bNYoxFALAEopZsilwcVliLJaTII2K45KUBfjTUSoMb87cfjSap4mwp5vdutS+nwzQYzsPDRARYxqYqjdacvql+0WiRGQ1pgNVXv37iKIEQYv44sjqT6woi4Gk7RgwTFlYqi+hjlzrhsyWC/mwIo+k3bUYsCMUPotibmSiJkv1mxvyoQaE3hgWcaBQKEpe5UETkx1gFdo9XhlUyYMXlLg/ElsRdyUtTsmtpObMio2llKKCaybc10DlH/rxaynqPWjbcoIZi6g8a30vUDMKMSAmcA6W2qMYfdug6j4IyJcdzxcWfyFwQtqupn1IhT/PYmr9kiK/7VE+JF/U4MLBL4hy/rinyAt/r5EVHplxbHpBdiMXExlXHz5uFGLIXeXXyNCJ0bcXVZPDEDqLosGL3WX8dD3Hr5sJbRh2/dAi7byspsZ1MS0NLjQYuoMI+suj0yMhxHBPy5sRiYmdyGKz+U7zraJ0auM/MHCM4rHa2xiJGLUE5NEeEOiwctlMjHYzHa4jyrvRV0MaurL+rXOFNiCzqWYQhy5AmlrBjogMfm6OFFi3G0Qo4/Qq4kBD3OkCy3mclsT4zWL9IZEgxe5GDBzPBGuTHkcvFgrBsjKgtU5FfMqm5jxIjMXMGZyKy8414kBLzYlxn8a8Q0JgxeFGAGbxDQ1WS3mPn59n1jMOGGBH2tqTDquMePFZviQjLr4K1CvMbaIyQsmvyFu8DI6Mcpp/3OamPGMFTdRa8apGKUYOyMHxIj53f6F5r8FJxl2M3bs2LFjx44dO/8/4Ld5Jk2CHwu325AMPC9mQCzsU/Oz0aWzQ4iv6+8nnqZkMwhztxyNJpCI+fO4fphu5v07khD94pLswt03EDF/fBBgMATG/PySGFpMDgBHeozEOHbsEptZyr2uXe/zD4gxfz2xq8/7jfj+HUrHXAxA1SjFTCrMzo6YRBQTHz96MdKbzWxO4l5P2IfiXz7nYhTncbl7X8CIgb+cEBr8uUrVxXi4XQSPx91GLmbx5woxXinpYTlEMfnXXJM/ejFAB9eceSU9nSd+Q/nPn00xx49bIeZCEe7DTt4V3k7e7lgMcH8+kkF/rlILYuae6B+YREhM26Hlh9pGl5iLIwrNNWU//WR9YhDH+s8/X6+4BRTdnC1Nfftp58mpwhvSUuiK+8+amIYVtB0bxAzP9B6uGnbfNMyIAXx0BDHYDFnMzKqyTZs9+v0nTGAiw4s5dSXmkC2J+U3RlHlcfHEUlH8O4UBT8fE6m8V890V18y/fScUk1ifim2jkOT892dn5aS/2DSUk7NuXkKDzOUtijhuwk5OGZyyJkZ7HNTxzuGzTzO4trJjnn1eEhj2gKWauvrS83yOn2aN/zSRZYlZcybBCEIN4AhcjHkuJIWJ78efy0uxXXd3cvF4qZlki3A4oZKnD5qedN+fxYpYACQhte/6siMkKpGNzQEWM+DwuuEnzlvojw91sU6bXXy2vNCCGMUMUM3e5f+y2bekemwcgMuIaM5kVE0wQU/P5sRqlmJixFrOvubl1Y3Pzd4IYng10a7Z582ZGjHbfElfXJfu0KGHf6kfOghhToBXFX3oel/umk0dPnp45jMXQrRiOL3TP5GKAMJKYlStLalavrhkYGJzwuDgxbVdytCnEBLaezGgNHIWYOwSQgKqYb1p/A1rFYrq7wUpjvaMjPaTxIoiJjXJgGY0Y9IxYTBAR6Vz98MynTp+6r6K7m07M8whBdsliIhBRzJHqz+PiavxBDFNkrBNz8p8QE/eI3+HDfo+Ui8QUFbFimCGNl7wpMxbDC6MXswI12SrGvfupI6d+dd/ENGV6wExTVkyRm7Jnqo/F94ZtfntAVmOWm2/KqJrWVpuaskskKMUYjepiMD6PAIsoWVOW6MhQ6gBIir+2wEHEaIq/DmXh8t9w3GoxU8u6T5yYOzzMjGMewcv9cYTiH+4ihy3+Px4ZKCwceGu5PwxlIDO8mD6LxT+QVPxHKia9uDjdKjFU3KLnyykkE9PJisF9AEl3OSXIQcyoussGhEwHTA2qiRFwH557YubwRCfL3eXwy82Jmbty00b/zYM4MG4ToPbLusunRN3lq4kQu8vqYu4TJSYqCgEjG2CCF4ENIZwY0B3lIGV0A8wVB0xZUGisFzN12HuuewU38qfjohTzxkwXshhg5twTgwNe4OUiUPO4eIB56tApKDBqYkaemPtYMZTRSI1YTGKM2EypQwgzJSMUl9GLEVATo0BtSga8KJBOyUBYIDEXcYkRsCUxI60xwAjFCCVGaM7wJGbBeId/kxhzk5jdLubEXMqLgfKCtSjFjD4xS8dMDIkNGg0uLv8mMeam/btcSJBml0cohjztb8eOHTt27NixY8eOHTv/PS5guIWF/8WcSUTM/4LSc0Q0mgeIaDSPKjm63Jm7sHbFEoYkLwYY6Jn5BaunaOCGFE+JoS+UPcEjx0OGhftUEjH/+j1EzP/3Lgy3sIQwaDTXELFCjBe9DoHlLItZvfpR/MNz/Vpn57WcmJ2Ml/e9eDGvd9kq5vGU9ELazEXsAkjPK/uXi3GHB0lMCDyimpOavVgt8Nx6MVt7erZaFrNu3aP0z/3049HKdufMTTNZMb68F0HM6zOn2yRmQpg2Z0JBIRgRmTF/n0oElJ8+7fMvEmMhMV5fJCUlRYETL3jYlJgz7e1neDFz9g/N2b9/qG///jl1Q3NYMdK8nHR2bp87kxNzUvAiiAEztoh53JidUzDBI4zODPvwMH99MATkXv/U9WdPjMFgm5h164iJIYupHuzv9xpJjelpb+/hxQyZTEN1WZi6pqY6XgzOCxOXD6EZWzkTYMR89gv28ouXVAyYCbdJTOwEaMlyQAiXF6WY2lOnDh2q5cTs8Hn2ZZKYsMLC6MLCMNvEBO7du9iimEkTJknErF5tVWLmY+CUF1jmC2g0nxCx3JTtb2rqq+vry+qDddOQssZA1V++aaYgpl7mpTgaxGBcTEiK5abMoyCnoPBxWgqrR359sMkftP84YzIWcz2wg0Lx10vQaO4HCj0KUJhH4f0CVtSk3W+trSGKOXQIVqDl7/bOB6aNKo7jaB5VqiFVQI0G/6CYmJnNzThdBidGXfxLdWInxhj/Rcs0pTiNldQIwz/pakvXtRaRjgmCM8CGVGAbwpx2jrG5KUMREWXMqWS4jIlMnUZ/76735x2v16P1T8zuc+2VqwS3fvL9/d67Pe7kiSkroyWGLiZgObrmpjXqxZCIpWw/iIG7goEYsEP2GMhMh17fClJEMWPYy02iFoRADMeHiEC4c6xhHgHf/OdiJJmRXx9sDH9MY7yY9pVftUSMPE+IqQqgQBUWcxHe1Igxe/q7ugbfeYci5sCBmaXs7HXrvkLoq3XrFqhLjN1WFygywRc5eItXDCQGatgWaDFb9m/ZwieGp/1Jvb4vXypmgvMiahHEAPupYgwyM9GHy+T1wRqCzSubCzgxQHWwHZTg7SK8F8Tg9X7ueqzkTtguUiHm1Tc6jh/veMNrlov5LSM1NeM3tpRJE1PAIIApUJkYu6nIHSgT8pKjIMZAhROTkQHPyOt94jwmN1LGXMX5hJh94GWnqIUQs19tYhCVGbdDHGpZWdqCxfAhoSYmLQ2lpdVjLZg7lcQ8xHLpaz1HHjz+8eHXnueOJYkZS00dYxOTRpSy9xjw8p7aHhMIFLmL7GJi4hNDHy6LkxcQIorhJpc7BS2kmP0qe4xaMUf2bpsY+IQTwyEkBna8mA2//pr76691nJQ7lUsZSGHFZB/OTj/c9vylcEiKOQBwzZ8Ug4D31PaYcE1doCpM9JjTqMQlJjcyeZGJ6QAvUi3mD7dcGBHzu05GomKWdD//2vElhBhK838Ru7joRaL5X0qFSwzYyG6bvqsY7rDNHT4Ue7jcbF6wwNysIjEIU/50OaqpQSLxivk6wg9fC2LEyQspBiaXNaKWd/Yf4/6NneIlcTFgZvFi8AJi0qhE3g+/mPtimHyfLkZIzPPHvQ2+4PHn2UOqmAvSSDHcLnZiEIu7LmCxqhKTT4UXc19EzP79GbwYcfKC+V0QMw1eOC2mV3+4UFj8QHhJVAxJLDFA1YYq4v1YiQFADt4pJOaCuGb+SCRRMfRSJk5eyMRM1oAWtn4Rq1Kwl/9MDEnsxFyKN0ELEN8pmcz/Qow4eYG4SL7/SM1btkj9IsSAl/+JGIBXopyYNF7MjxIlP/7XiYHJC/X7X7Hx9YsU87vufyWGII7EaGhoaGhoaGhoaGho/P94jArcNyXKhK43yoWpc6lE/4Wme6hEX/d1K4c+QjIHe7sT7rrcKFOC5ELf6VKi//r86VSiX+D6uZvo6+7S0/M7P8rrzE+X/X+voUJOhE8XUBCTezJdTErvPymGXPeVqJjCv0dMzjqKGN3SV6KJCe/YEc5Pz85WLQaMRF5uw1sMMbm5V1PFYDN0MS+QWzxiyHVfiYpZ8w8mRqdrXFoTJTGd4WdAzDHYaGIWLYouhuM2LAZR4RKQSRWDzSSemHOoyJYXbQ6y+OISU+dGRXArFIOUaH9fBTE5WMRKQUlTEy9G51yxooYmJi8v7+J8sPLux8dmiqm3GY22elGM4INIjKIY4GQnTQyYSVzMbTzvl4Q7hQOZmI3LVixb9v33k3GJecaKrM+oFoMEjEYkAGJ2r5Ukpa3VJSQGzISW4lYjF7Nj/fod+ekQmQ9nJqYIL7cpZ9w0MWRiUgQWLhS/Zj/odniWMrRbW1UaZEjvIeYwxl7JKIj5fOCnboRsvBrZuq+Nz7lXuNZ/uzG+UrbKZkuRiVG+TyXGwSIRI6XXYOgSxQCtS3GrkZcySAyIOQaBkYupR/XXFK1aZYUXpR5DiqmslInp7jhyJPekG8hanCKaCYX4vSgGvHg8DkYuZvt28VUUs7xz3Nk2MRD0mDzh2/I+uhjEEOu+IDFHVyz7PqSUGCQgF1NoSbEUynpMTDEOxrh1xMg4aGJ+ajUQYprgOQq37KuRiVleUrI8yqjMVn6NG5VbrchGEUNPzM55BsO8nVIxR548p3ZJbu6SX0gxgpnRxsZRbi8V4/Ft2hR0yMS888MP7/Cvgpjl69eP6waavhgY8Aa9KBz+bjmIIdd9dRjmfdf5/e37lBMj0l5mNpfl0IbL6sWgkRFGJoYrZk1+A9AqiBmwewZ0uiEws6KGEFOyY0cJXcwiY/011jVz09Yg4xnkcFkhMTcZDDelzEaMwek0cHtCzPRv09MmeWKOHSNfQUzJxC+Pvw9itg18EQx6mfBtJdW/gJhTpLQZ5v1c7DdsUymmtD2z9OXq9tL4xWAjDvxkJGKqd58KdBg4MmOKyYPEKIm5ZZEghuyp9B5TU1lZM6tSNi8U8vN7UYxxeHp6WF7KmO3bzfwrL+bzX0ug8zudA86gxwOlDL8hF5O5dM/55x/SZ6oU054Dq/fW5bRjMQYqKsTgi3WRYjCZrQbgXnj2UkoZrcfQS1kASllAWspAg7hRE7OQfSTe/B3f2I2zaP5w41KftPmfQrDt0PnXHuqOMY8RKS0rKzNDYOIVAzhWX3bZ6hnN/6eQgceVGav5f5YPD7qYelR1jXuVFTd/SmLUzmOA7GtJZj9c1lGRDpfffjsPXqhiwMyePeBFrZjNOS+/nLOZJkb9cNkBSN7n24tIX6zhMpSyvChiIC/uqvoAE7hGMTGxxNyZCi5SuYcoBrwkLEb9zdSeajtFvZic0urqUq75v0kl+t/3SiqcmF6Xy+Vn4cy0gRjWC32C2bnhu+jnyupXMcQEk5qYGKdkXgMfghfuS8VTMvJzMopi7qECYiioF1Ods7aaE5NOEPuUDF1MXKdkwhv3hSlieNLSYKecGEUxEBeW1D+5B3uoeBLzhSW5BP+6GKAUCtnfLqbDQNKkfBLzu87wd1QxIoqJURYDXijEOO3/34sB/k4xcZ32h0uCdyYqRkNDQ0NDQ0NDQ0ND4//HIipwwWrUrdM1oKJkAnLd19kCSUnXiZwmMvOaK4f0o048wXyCSvQJ6XVSTuOJfu7rJUxz1kskSZhzIojfDFyK0UuYj8G/YFU7WauXM9vrnincJ/SGFAoKYpIDaBs+I1+XLIVc9zVDzMmxxDxaq9+rA+IQs1LcZGLMFSYzVUzzLthl7SpISEzt6PpWvRzyc0hEjKvx/VmKSS5nmnS6ILIkSyDXfUWsDI9FxHyw8gNlMW/qQ434tGxrHGIkXq4jTtebNg0PD5oQOk8CK2ZXM+sla1dCYvb0Thx2wXEt/8AoXPfMuNWBWBz9RoTB70QX0+jq+/Tz6GKqYIFAoIoUk7yGgZtYeZm3iB90ugRWy4Kzh4c5MR/s3r37AwUxj+7R9+mARn9tdDE3UlFITMVgV2tr16YKQoyQGOwlS70YQYAoxt+7rdcv+uL+o2yZVVtxflN+cTsrxuHyT/aDHGbSPwJSHCOTfteIVMzCheS9D/pcjVDP6GIglUUPL3p4LikmxUaYoYtpGQsu4ErZnJbdaHfLnKhiDtT62TLWpx/bFYcYiRdCjGm4FRiuoPWYgl0xegzDyMUc0OOdtMeEWl16KRQx+cWPNUxNHeFK2Va/y2UAKavPWQ1f3wtHBxmpmMpKUowOQuN8nyqmCiEL6+NhiRig0FYByw3sRvH2O+S6L1zFWiaDoCd2YqDrtzpxGQvp37j77uhinuUJ7xu2CAdkYohSVsGJMamr6aQYY38/Q4rZM38PuxPE8BmcswSYwx+Rn8PJ+cU9psOcGDODBmtd/nv3be7r7dvsu9fg8vebiT/PihUyMWxoPl1OEWNDtoiQenAjiAEzq0wDOqfEDLnuC4uRNv8PSik9RihjQzpgr7/2y7vViLGgbhMSzCgkpmITLmWD8lKGqJBiKgY3bjzoIMR8PX8+dvI13l0viAEti1l4NeTnAGKm7b1TbVhMQXNBweCY696OqzHbLnFNfoMKvuLF7IRLWer1sNspiGkcamRDo5MSEWNERZyXubZVc0Ux2IzV5NQ5PVbeDLnu62yOliA/KpsTbVR2QO9q1AGj+rHL71Ylxmpqshut/JHSqMw0ODwMLSYOMSZ7/8HJEboYMjH3PLgYvyx+8B7umPwcTk6f6vAUF7NiXs7K2t7T0+8KbcA86RrLKmCysBiOmqV6YGmNmJjRvaNcaPwGEUGMmyoGeMbqATMmayH/g86ewYKxybOjX5hBmLywxVS/hb/A3CVUxFGZh2n4LOxRMypDZpPZjEjUiWEc/ZtMjIpSNmfxg3PY13sW82JOkXBy8VQPmuYSg7KymMNXvuror3O73XUHt8LYw3wzLwZYiL1A+xcT08eKGSLExCpl2IzR7tQNmFYVysXgOsY1/5YWJTHi5GVIX/vH3WrFNCFvsLwp9jyG4YlDjGPk4CZPhbz5H4CHnihlc94DL5yhB0tFMSLbpnpM08UTrJiCAuSd6ilb/SSI2VjLZGV9hbIIMcBCYlTGljKwI0Fs/kW05s+ZYeyw6tBsS6GKWcCOypTEiJMX/W+gRKUYMBP0NqmY+Z9HRV3zZwYDmzyMfLg8f750uMxVMuGew0vuoYjpCHWnn5XdEWLFQHoreq5809W/b8O+Qbh3vBkiLY7KoJbt3AmVTBTDxaXRmZohQRwuo8DcRXOriOEyz1uMF+7Ly6xJoZSy4DDeK4kRJy/Q9WVi9PCQbEC04XL0BJRSYZNKQT5ctlpnzGMOzZ9/SCKGLlhWyia6Ovq6up4SZv6eb7o8/aHW1snmr/tlo8TKhZCaSkIMxMX5bgYBMcEsl08w5WZIMS2QGHjEEiOZvNxNiAETJMpiTqMy+wtWx57533cf7NhSJohJEZ8pFDGUUzLmVwddfld/1uVlMYbvbFx+z5CheEpGxIKCuOiXS8UM17awcYklRjJ5IcVw6OVinqUi+/kxS1kiYg5BYIjEYB3sTvgythjAsXorWrcAxRCD4/JYRlxigDrkg/tYowAWI46RgdhixMkLKYaXIpYyZTGIyj+RGIAUg03wfqilLLGTmBCXOMUARahBp+tGbqLHqBMjTl5IMTwJJeZfEEPw94v5PTWDJkZDQ0NDQ0NDQ0NDQ+P/h3jJD3Licyom5yS8J95PphJ9YpWd/SqyWm6SkZR0JpWkJN/U/RSSTjwUxXyyeFZiqorKq8otR91uS5HF4ubFZB/bjsqVxey9/8z7zzzz/vtBDLJPaWLkYlK4LSIms30tXK2jdK16MUctlqPlRwPuNW5ruSXAiekBM0RoaGKGvl1fObT+271YDKo4rImhJyaFE7O2JQfsVK9NrJQtezObCA29lN0PaoYgNNzPCYYMMpJOPIjEkKUMyKmeRSnzeL3I0+DzeoNBD/J6PayYoWUhIjR0MXfcAdUMYNdlbQ3YRzUxRGIKbQjZCkUxmWvXwl5VMsCLz9vtsV996xVXXHG119Pg9Znw+7rGkBAakejNH6GR28+1mne8fpWUpBMPxIPF2Apt8BDFtLScql5Mg93X4PVecevExFNX2L3dPnsDK0anY0NDIhMDv1gN3/fII4/Az3Ef9d8Oo4gNy09wMclSIC4QGlFMdfUsxPi8dp/Xc/Wtn2y+9Wq7N2i3ByNi2NCoFlP07DL97c+WI1icI5J04kEXQ7yvVowvaPd5HigBHrD77EGfLy4x6KAr5JqEynjCi0nhN76UxS0GN/7xxvHx8c+9XtDki6uUYTGhgyiolTIeofkritFRYYVV2KH/L3eOjztLvD47jMqE5n8hvfnTxZSPjIwMas0fgiJuHPGKgdoV9JaMj5eM5/mCcCQbLpdV3yqgJAbYPTrvhB8uszPK1zkn/D4lLjFMENx4PB67HXZgJchgMUJcVoKPmGK0CaYAsVwK7+NPTBCGy/agNwgPO75vKpsYIi4xxWinZMjEPA46CDdxiQHACAb8MAzXS4i4xBSjncSkNv/Eegx9tEbEJaYY7bS/hoaGhobGP8xff9MS7Xw+B5wAAAAASUVORK5CYII=\"","// Coordinates in the bundled 408×384 flag sprite.\n// Geometry belongs to CountryFlag so consumers never construct sprite styles.\nexport const COUNTRY_FLAG_POSITIONS = {\n ad: '-48px -27px',\n ae: '-72px -27px',\n af: '-96px -27px',\n ag: '-120px -27px',\n ai: '-144px -27px',\n al: '-168px -27px',\n am: '-192px -27px',\n an: '-216px -27px',\n ao: '-240px -27px',\n aq: '-264px -27px',\n ar: '-288px -27px',\n as: '-312px -27px',\n at: '-336px -27px',\n au: '-360px -27px',\n aw: '-384px -27px',\n ax: '-0px -51px',\n az: '-24px -51px',\n ba: '-48px -51px',\n bb: '-72px -51px',\n bd: '-96px -51px',\n be: '-120px -51px',\n bf: '-144px -51px',\n bg: '-168px -51px',\n bh: '-192px -51px',\n bi: '-216px -51px',\n bj: '-240px -51px',\n bl: '-264px -51px',\n bm: '-288px -51px',\n bn: '-312px -51px',\n bo: '-336px -51px',\n br: '-360px -51px',\n bs: '-384px -51px',\n bt: '-0px -75px',\n bw: '-24px -75px',\n by: '-48px -75px',\n bz: '-72px -75px',\n ca: '-96px -75px',\n cc: '-120px -75px',\n cd: '-144px -75px',\n cf: '-168px -75px',\n cg: '-192px -75px',\n ch: '-216px -75px',\n ci: '-240px -75px',\n ck: '-264px -75px',\n cl: '-288px -75px',\n cm: '-312px -75px',\n cn: '-336px -75px',\n co: '-360px -75px',\n cr: '-384px -75px',\n cu: '-0px -99px',\n cv: '-24px -99px',\n cw: '-48px -99px',\n cx: '-72px -99px',\n cy: '-96px -99px',\n cz: '-120px -99px',\n de: '-144px -99px',\n dj: '-168px -99px',\n dk: '-192px -99px',\n dm: '-216px -99px',\n do: '-240px -99px',\n dz: '-264px -99px',\n ec: '-288px -99px',\n ee: '-312px -99px',\n eg: '-336px -99px',\n eh: '-360px -99px',\n er: '-384px -99px',\n es: '-0px -123px',\n et: '-24px -123px',\n eu: '-48px -123px',\n fi: '-72px -123px',\n fj: '-96px -123px',\n fk: '-120px -123px',\n fm: '-144px -123px',\n fo: '-168px -123px',\n fr: '-192px -123px',\n ga: '-216px -123px',\n gb: '-240px -123px',\n gd: '-264px -123px',\n ge: '-288px -123px',\n gg: '-312px -123px',\n gh: '-336px -123px',\n gi: '-360px -123px',\n gl: '-384px -123px',\n gm: '-0px -147px',\n gn: '-24px -147px',\n gq: '-48px -147px',\n gr: '-72px -147px',\n gs: '-96px -147px',\n gt: '-120px -147px',\n gu: '-144px -147px',\n gw: '-168px -147px',\n gy: '-192px -147px',\n hk: '-216px -147px',\n hn: '-240px -147px',\n hr: '-264px -147px',\n ht: '-288px -147px',\n hu: '-312px -147px',\n ic: '-336px -147px',\n id: '-360px -147px',\n ie: '-384px -147px',\n il: '-0px -171px',\n im: '-24px -171px',\n in: '-48px -171px',\n iq: '-72px -171px',\n ir: '-96px -171px',\n is: '-120px -171px',\n it: '-144px -171px',\n je: '-168px -171px',\n jm: '-192px -171px',\n jo: '-216px -171px',\n jp: '-240px -171px',\n ke: '-264px -171px',\n kg: '-288px -171px',\n kh: '-312px -171px',\n ki: '-336px -171px',\n xk: '-144px 3px',\n km: '-360px -171px',\n kn: '-384px -171px',\n kp: '-0px -195px',\n kr: '-24px -195px',\n kw: '-48px -195px',\n ky: '-72px -195px',\n kz: '-96px -195px',\n la: '-120px -195px',\n lb: '-144px -195px',\n lc: '-168px -195px',\n li: '-192px -195px',\n lk: '-216px -195px',\n lr: '-240px -195px',\n ls: '-264px -195px',\n lt: '-288px -195px',\n lu: '-312px -195px',\n lv: '-336px -195px',\n ly: '-360px -195px',\n ma: '-384px -195px',\n mc: '-0px -219px',\n md: '-24px -219px',\n me: '-48px -219px',\n mf: '-72px -219px',\n mg: '-96px -219px',\n mh: '-120px -219px',\n mk: '-144px -219px',\n ml: '-168px -219px',\n mm: '-192px -219px',\n mn: '-216px -219px',\n mo: '-240px -219px',\n mp: '-264px -219px',\n mq: '-288px -219px',\n mr: '-312px -219px',\n ms: '-336px -219px',\n mt: '-360px -219px',\n mu: '-384px -219px',\n mv: '-0px -243px',\n mw: '-24px -243px',\n mx: '-48px -243px',\n my: '-72px -243px',\n mz: '-96px -243px',\n na: '-120px -243px',\n nc: '-144px -243px',\n ne: '-168px -243px',\n nf: '-192px -243px',\n ng: '-216px -243px',\n ni: '-240px -243px',\n nl: '-264px -243px',\n no: '-288px -243px',\n np: '-312px -243px',\n nr: '-336px -243px',\n nu: '-360px -243px',\n nz: '-384px -243px',\n om: '-0px -267px',\n pa: '-24px -267px',\n pe: '-48px -267px',\n pf: '-72px -267px',\n pg: '-96px -267px',\n ph: '-120px -267px',\n pk: '-192px -267px',\n pl: '-216px -267px',\n pn: '-240px -267px',\n pr: '-264px -267px',\n ps: '-288px -267px',\n pt: '-312px -267px',\n pw: '-336px -267px',\n py: '-360px -267px',\n qa: '-384px -267px',\n ro: '-0px -291px',\n rs: '-24px -291px',\n ru: '-48px -291px',\n rw: '-72px -291px',\n sa: '-96px -291px',\n sb: '-120px -291px',\n sc: '-144px -291px',\n sd: '-168px -291px',\n se: '-192px -291px',\n sg: '-216px -291px',\n sh: '-240px -291px',\n si: '-264px -291px',\n sk: '-288px -291px',\n sl: '-312px -291px',\n sm: '-336px -291px',\n sn: '-360px -291px',\n so: '-384px -291px',\n sr: '-0px -315px',\n ss: '-24px -315px',\n st: '-48px -315px',\n sv: '-72px -315px',\n sy: '-96px -315px',\n sz: '-120px -315px',\n tc: '-144px -315px',\n td: '-168px -315px',\n tf: '-192px -315px',\n tg: '-216px -315px',\n th: '-240px -315px',\n tj: '-264px -315px',\n tk: '-288px -315px',\n tl: '-312px -315px',\n tm: '-336px -315px',\n tn: '-360px -315px',\n to: '-384px -315px',\n tr: '-0px -339px',\n tt: '-24px -339px',\n tv: '-48px -339px',\n tw: '-72px -339px',\n tz: '-96px -339px',\n ua: '-120px -339px',\n ug: '-144px -339px',\n us: '-168px -339px',\n uy: '-192px -339px',\n uz: '-216px -339px',\n va: '-240px -339px',\n vc: '-264px -339px',\n ve: '-288px -339px',\n vg: '-312px -339px',\n vi: '-336px -339px',\n vn: '-360px -339px',\n vu: '-384px -339px',\n wf: '-0px -363px',\n ws: '-24px -363px',\n ye: '-48px -363px',\n za: '-96px -363px',\n zm: '-120px -363px',\n zw: '-144px -363px',\n} as const;\n\nexport type SupportedCountryFlag = keyof typeof COUNTRY_FLAG_POSITIONS;\n","import type { CSSProperties, FC } from 'react';\nimport flags from '@/assets/icons/flags.png';\nimport { cn } from '@/utils';\nimport { COUNTRY_FLAG_POSITIONS, type SupportedCountryFlag } from './positions';\nimport './style.css';\n\nexport type CountryFlagProps = {\n iso2: string;\n className?: string;\n};\n\nconst COUNTRY_FLAG_ALIASES: Record<string, SupportedCountryFlag> = {\n bq: 'nl',\n gf: 'fr',\n gp: 'fr',\n io: 'gb',\n pm: 'fr',\n re: 'fr',\n yt: 'fr',\n};\n\nconst getSupportedCountry = (iso2: string): SupportedCountryFlag | null => {\n const normalized = iso2.trim().toLowerCase();\n const candidate = COUNTRY_FLAG_ALIASES[normalized] ?? normalized;\n return candidate in COUNTRY_FLAG_POSITIONS ? (candidate as SupportedCountryFlag) : null;\n};\n\nexport const CountryFlag: FC<CountryFlagProps> = ({ iso2, className }) => {\n const country = getSupportedCountry(iso2);\n\n if (!country) {\n return (\n <span\n aria-hidden='true'\n className={cn('passflow-country-flag passflow-country-flag--fallback', className)}\n data-country-flag={iso2.toLowerCase()}\n >\n {iso2.slice(0, 2).toUpperCase() || '–'}\n </span>\n );\n }\n\n const style: CSSProperties = {\n backgroundImage: `url(${flags})`,\n backgroundPosition: COUNTRY_FLAG_POSITIONS[country],\n };\n\n return (\n <span\n aria-hidden='true'\n className={cn('passflow-country-flag', className)}\n data-country-flag={iso2.toLowerCase()}\n style={style}\n />\n );\n};\n","import * as DialogPrimitive from '@radix-ui/react-dialog';\n/* eslint-disable react/jsx-props-no-spreading */\nimport { type ComponentPropsWithoutRef, type ElementRef, forwardRef, type HTMLAttributes } from 'react';\nimport { cn } from '@/utils';\n\nconst Dialog = DialogPrimitive.Root;\n\nconst DialogTrigger = DialogPrimitive.Trigger;\n\nconst DialogPortal = DialogPrimitive.Portal;\n\nconst DialogClose = DialogPrimitive.Close;\n\nconst DialogOverlay = forwardRef<\n ElementRef<typeof DialogPrimitive.Overlay>,\n ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>\n>(({ className, ...props }, ref) => (\n <DialogPrimitive.Overlay ref={ref} className={cn('passflow-dialog-overlay', className)} {...props} />\n));\nDialogOverlay.displayName = DialogPrimitive.Overlay.displayName;\n\nconst DialogContent = forwardRef<\n ElementRef<typeof DialogPrimitive.Content>,\n ComponentPropsWithoutRef<typeof DialogPrimitive.Content>\n>(({ className, children, ...props }, ref) => (\n <DialogPortal>\n <DialogOverlay />\n <DialogPrimitive.Content ref={ref} className={cn('passflow-dialog-content', className)} {...props}>\n {children}\n </DialogPrimitive.Content>\n </DialogPortal>\n));\nDialogContent.displayName = DialogPrimitive.Content.displayName;\n\nconst DialogHeader = ({ className, ...props }: HTMLAttributes<HTMLDivElement>) => (\n <div className={cn('passflow-dialog-header', className)} {...props} />\n);\nDialogHeader.displayName = 'DialogHeader';\n\nconst DialogFooter = ({ className, ...props }: HTMLAttributes<HTMLDivElement>) => (\n <div className={cn('passflow-dialog-footer', className)} {...props} />\n);\nDialogFooter.displayName = 'DialogFooter';\n\nconst DialogTitle = forwardRef<\n ElementRef<typeof DialogPrimitive.Title>,\n ComponentPropsWithoutRef<typeof DialogPrimitive.Title>\n>(({ className, ...props }, ref) => (\n <DialogPrimitive.Title ref={ref} className={cn('passflow-dialog-title', className)} {...props} />\n));\nDialogTitle.displayName = DialogPrimitive.Title.displayName;\n\nconst DialogDescription = forwardRef<\n ElementRef<typeof DialogPrimitive.Description>,\n ComponentPropsWithoutRef<typeof DialogPrimitive.Description>\n>(({ className, ...props }, ref) => (\n <DialogPrimitive.Description ref={ref} className={cn('passflow-dialog-description', className)} {...props} />\n));\nDialogDescription.displayName = DialogPrimitive.Description.displayName;\n\nexport {\n Dialog,\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogOverlay,\n DialogPortal,\n DialogTitle,\n DialogTrigger,\n};\n","import { OTPInput, REGEXP_ONLY_DIGITS, REGEXP_ONLY_DIGITS_AND_CHARS, type SlotProps } from 'input-otp';\nimport type { FC } from 'react';\nimport { cn } from '@/utils';\nimport '@/styles/index.css';\nimport './field-otp.css';\n\nexport type FieldOtpCharset = 'numeric' | 'alphanumeric';\n\nexport type FieldOtpState = 'default' | 'error' | 'disabled';\n\ntype FieldOtpBaseProps = {\n /** Id of the one real `<input>`; the boxes are drawn from its value. */\n id: string;\n /** Form field name, for a native form submit. */\n name?: string;\n /** Number of characters in the code, and of boxes drawn. */\n length: number;\n value: string;\n onChange: (value: string) => void;\n /** Called once the code reaches `length` characters. */\n onComplete?: (value: string) => void;\n /** Which characters are accepted; also picks the on-screen keyboard. Default `numeric`. */\n charset?: FieldOtpCharset;\n /** `error` marks the code invalid (`aria-invalid`); `disabled` locks it. Default `default`. */\n state?: FieldOtpState;\n /** Id of the element that describes it, such as the error message. */\n describedBy?: string;\n autoFocus?: boolean;\n};\n\n/**\n * The code field is named either by a visible label it draws itself (`label`),\n * or by an element the screen already shows (`labelledBy`), never both. A\n * hidden-only name fails axe `label-title-only` once `describedBy` is set.\n */\nexport type FieldOtpProps = FieldOtpBaseProps &\n (\n | {\n /** Visible prompt drawn above the boxes, as the field's `<label>`. */\n label: string;\n labelledBy?: never;\n }\n | {\n /** Id of a visible element on the screen that names the code field, such as a prompt or heading. */\n labelledBy: string;\n label?: never;\n }\n );\n\nconst CHARSETS: Record<FieldOtpCharset, { pattern: string; inputMode: 'numeric' | 'text' }> = {\n numeric: { pattern: REGEXP_ONLY_DIGITS, inputMode: 'numeric' },\n alphanumeric: { pattern: REGEXP_ONLY_DIGITS_AND_CHARS, inputMode: 'text' },\n};\n\ntype SlotViewProps = SlotProps & { state: FieldOtpState };\n\nconst Slot: FC<SlotViewProps> = ({ char, isActive, hasFakeCaret, state }) => (\n <div\n className={cn('passflow-field-otp', {\n 'passflow-field-otp--active': isActive,\n 'passflow-field-otp--error': state === 'error',\n 'passflow-field-otp--disabled': state === 'disabled',\n })}\n >\n {char}\n {hasFakeCaret ? <span className='passflow-field-otp__caret' /> : null}\n </div>\n);\n\n/**\n * A one-time code entered as a row of boxes.\n *\n * There is one real `<input>` (named, `autocomplete=\"one-time-code\"`), so SMS\n * autofill, password managers and pasting a whole code all work. The boxes are\n * a drawing of its value, hidden from assistive technology. With `label` the\n * field draws its own visible label above the boxes; with `labelledBy` it is\n * named by a prompt the screen already shows.\n */\nexport const FieldOtp: FC<FieldOtpProps> = ({\n id,\n name,\n length,\n value,\n onChange,\n onComplete,\n charset = 'numeric',\n state = 'default',\n label,\n labelledBy,\n describedBy,\n autoFocus = false,\n}) => {\n const { pattern, inputMode } = CHARSETS[charset];\n\n const input = (\n <OTPInput\n id={id}\n name={name}\n maxLength={length}\n value={value}\n onChange={onChange}\n onComplete={onComplete}\n pattern={pattern}\n inputMode={inputMode}\n autoComplete='one-time-code'\n disabled={state === 'disabled'}\n aria-labelledby={labelledBy}\n aria-describedby={describedBy}\n aria-invalid={state === 'error' ? true : undefined}\n autoFocus={autoFocus}\n noScriptCSSFallback={null}\n containerClassName={cn('passflow-field-otp-group', { 'passflow-field-otp-group--disabled': state === 'disabled' })}\n render={({ slots }) => (\n <div className='passflow-field-otp-slots' aria-hidden>\n {slots.map((slot, position) => (\n // Slots are positions in the code: the index is their identity.\n // biome-ignore lint/suspicious/noArrayIndexKey: a slot is its position\n <Slot key={position} {...slot} state={state} />\n ))}\n </div>\n )}\n />\n );\n\n if (label === undefined) return input;\n\n return (\n <div className='passflow-field-otp-field'>\n <label htmlFor={id} className='passflow-field-label'>\n {label}\n </label>\n {input}\n </div>\n );\n};\n","/* eslint-disable react/jsx-props-no-spreading */\nimport { forwardRef, type InputHTMLAttributes, useState } from 'react';\nimport { Button, Icon } from '..';\nimport '@/styles/index.css';\nimport type { PassflowPasswordPolicySettings } from '@passflow/core';\nimport { cn } from '@/utils';\n\ntype TFieldPassword = InputHTMLAttributes<HTMLInputElement> & {\n id: string;\n value: string;\n passwordPolicy: PassflowPasswordPolicySettings | null;\n withMessages?: boolean;\n validationErrors?: string | string[];\n isError?: boolean;\n className?: string;\n disabled?: boolean;\n};\n\nconst generateMessage = (\n requires: Record<'requireLowerCase' | 'requireUpperCase' | 'requireSymbol' | 'requireNumber', boolean>,\n) => {\n const requiresString = {\n requireNumber: 'number',\n requireSymbol: 'symbol',\n requireLowerCase: 'lowercase letter',\n requireUpperCase: 'uppercase letter',\n };\n const requirements = Object.keys(requires).filter((key) => requires[key as keyof typeof requires]);\n const requirementsString = new Intl.ListFormat('en').format(\n requirements.map((requirement) => requiresString[requirement as keyof typeof requiresString]),\n );\n\n return `Must contain a ${requirementsString}`;\n};\n\nexport const FieldPassword = forwardRef<HTMLInputElement, TFieldPassword>(\n (\n {\n id,\n value,\n passwordPolicy,\n withMessages = false,\n validationErrors = [],\n isError = false,\n className = '',\n disabled = false,\n ...rest\n },\n ref,\n ) => {\n const [isShowPassword, setIsShowPassword] = useState(false);\n\n const styles = {\n 'passflow-field--error': isError,\n };\n\n const errorStyles = (fields: string[]) => {\n if (value.length > 0 && !fields.some((field) => validationErrors.includes(field)))\n return 'passflow-password-validation-item--success';\n return null;\n };\n\n const changeIcon = (fields: string[]) => {\n if (value.length > 0 && !fields.some((field) => validationErrors.includes(field))) return 'check';\n return 'close';\n };\n\n const handleShowPassword = () => setIsShowPassword((prev) => !prev);\n\n const minPasswordLength = passwordPolicy?.min_password_length ?? 0;\n const requireLowerCase = passwordPolicy?.require_lowercase ?? false;\n const requireNumber = passwordPolicy?.require_number ?? false;\n const requireSymbol = passwordPolicy?.require_symbol ?? false;\n const requireUpperCase = passwordPolicy?.require_uppercase ?? false;\n\n return (\n <>\n <div className='passflow-field-wrapper'>\n <input\n ref={ref}\n id={id}\n value={value}\n type={isShowPassword ? 'text' : 'password'}\n className={cn('passflow-field-input passflow-field--focused passflow-field-input--with-icon', styles, className)}\n disabled={disabled}\n {...rest}\n />\n {isShowPassword ? (\n <Button\n className='passflow-button-display-password passflow-field-icon-button'\n size='small'\n type='button'\n variant='clean'\n asIcon\n withIcon\n disabled={disabled}\n aria-label='Hide password'\n onClick={handleShowPassword}\n >\n <Icon size='small' type='general' id='eye-on' decorative />\n </Button>\n ) : (\n <Button\n className='passflow-button-display-password passflow-field-icon-button'\n size='small'\n type='button'\n variant='clean'\n asIcon\n withIcon\n disabled={disabled}\n aria-label='Show password'\n onClick={handleShowPassword}\n >\n <Icon size='small' type='general' id='eye-off' decorative />\n </Button>\n )}\n </div>\n {withMessages && passwordPolicy && (\n <div className='passflow-password-validation'>\n <p className={cn('passflow-password-validation-item', errorStyles(['length']))}>\n <Icon size='small' id={changeIcon(['length'])} type='general' className={cn(errorStyles(['length']))} />\n At least {minPasswordLength} characters\n </p>\n <p className={cn('passflow-password-validation-item', errorStyles(['uppercase', 'lowercase', 'number', 'symbol']))}>\n <Icon\n size='small'\n id={changeIcon(['uppercase', 'lowercase', 'number', 'symbol'])}\n type='general'\n className={cn(errorStyles(['uppercase', 'lowercase', 'number', 'symbol']))}\n />\n {generateMessage({\n requireNumber,\n requireSymbol,\n requireLowerCase,\n requireUpperCase,\n })}\n </p>\n </div>\n )}\n </>\n );\n },\n);\n","import type { Passflow } from '@passflow/core';\nimport { useContext } from 'react';\nimport { PassflowContext } from '@/context';\n\nexport const usePassflow = (): Passflow => {\n const context = useContext(PassflowContext);\n if (!context) {\n throw new Error('useAuth must be used within an PassflowProvider');\n }\n\n const { passflow } = context;\n\n return passflow;\n};\n","import { type ParsedTokens, PassflowEvent, type PassflowSubscriber, type Tokens } from '@passflow/core';\nimport { createContext, type FC, type PropsWithChildren, useCallback, useEffect, useState } from 'react';\nimport { usePassflow } from '../hooks/use-passflow';\n\nexport type SessionExpiredHandler = (reason: 'refresh_failed' | 'token_invalid' | 'logged_out') => void;\n\nexport type AuthContextValue = {\n isAuthenticated: () => boolean;\n logout: () => void;\n isLoading: boolean;\n isSessionExpired: boolean;\n getTokens: (doRefresh: boolean) => Promise<{ tokens: Tokens | undefined; parsedTokens: ParsedTokens | undefined }>;\n};\n\nexport const AuthContext = createContext<AuthContextValue | undefined>(undefined);\n\nexport type AuthProviderProps = PropsWithChildren<{\n /**\n * Called when the session expires (token refresh failed).\n * Use this to redirect to your login page.\n */\n onSessionExpired?: SessionExpiredHandler;\n}>;\n\nexport const AuthProvider: FC<AuthProviderProps> = ({ children, onSessionExpired }) => {\n const passflow = usePassflow();\n const [isLoading, setIsLoading] = useState<boolean>(false);\n const [isSessionExpired, setIsSessionExpired] = useState<boolean>(false);\n\n // Subscribe to SessionExpired events\n useEffect(() => {\n const subscriber: PassflowSubscriber = {\n onAuthChange: (eventType, payload) => {\n if (eventType === PassflowEvent.SessionExpired) {\n const reason =\n (payload as { reason?: 'refresh_failed' | 'token_invalid' | 'logged_out' })?.reason ?? 'refresh_failed';\n setIsSessionExpired(true);\n onSessionExpired?.(reason);\n } else if (eventType === PassflowEvent.SignIn || eventType === PassflowEvent.Register) {\n // Reset session expired state on successful auth\n setIsSessionExpired(false);\n }\n },\n };\n\n passflow.subscribe(subscriber, [PassflowEvent.SessionExpired, PassflowEvent.SignIn, PassflowEvent.Register]);\n\n return () => {\n passflow.unsubscribe(subscriber);\n };\n }, [passflow, onSessionExpired]);\n\n const isAuthenticated = useCallback(() => passflow.isAuthenticated(), [passflow]);\n\n const getTokens = useCallback(\n async (doRefresh: boolean) => {\n setIsLoading(true);\n\n try {\n const tokens = await passflow.getTokens(doRefresh);\n const parsedTokens = tokens ? passflow.getParsedTokens() : undefined;\n\n return {\n tokens,\n parsedTokens,\n };\n } catch (e) {\n return {\n tokens: undefined,\n parsedTokens: undefined,\n };\n } finally {\n setIsLoading(false);\n }\n },\n [passflow],\n );\n\n const logout = useCallback(async () => {\n await passflow.logOut();\n }, [passflow]);\n\n const value = {\n isAuthenticated,\n logout,\n isLoading,\n isSessionExpired,\n getTokens,\n };\n\n return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;\n};\n","import { createContext } from 'react';\n\nexport type NavigateOptions = {\n to: string;\n search?: string;\n replace?: boolean;\n};\n\nexport type RouterType = 'default' | 'react-router' | 'tanstack-router' | 'wouter';\n\nexport type NavigateFunction = (options: NavigateOptions) => void;\n\nexport type NavigationContextType = {\n navigate: NavigateFunction;\n setNavigate: (navigate: NavigateFunction | null) => void;\n router: RouterType;\n /**\n * Where a sign-in that owes its second factor is sent when it lands on a\n * page outside the forms (a federated redirect carrying `#tfa_token=`).\n * `PassflowProvider` resolves it: a mounted `PassflowFlow` registers its own\n * (prefixed) route, else the provider's `twoFactorVerifyPath` prop, else\n * `routes.two_factor_verify.path`.\n */\n twoFactorVerifyPath?: string;\n /** Registers the 2FA route of a mounted flow; `null` withdraws it. */\n setTwoFactorVerifyPath?: (path: string | null) => void;\n};\n\nexport const defaultNavigate: NavigateFunction = ({ to, search, replace }) => {\n const searchParam = search ? (search.startsWith('?') ? search : `?${search}`) : '';\n if (replace) {\n window.location.replace(`${to}${searchParam}`);\n } else {\n window.location.href = `${to}${searchParam}`;\n }\n};\n\nexport const NavigationContext = createContext<NavigationContextType>({\n navigate: defaultNavigate,\n setNavigate: () => undefined,\n router: 'default',\n});\n","import type { AppSettings, Passflow, PassflowPasswordPolicySettings } from '@passflow/core';\nimport { createContext, type Dispatch } from 'react';\n\nexport type PassflowState = {\n appSettings: AppSettings | null;\n passwordPolicy: PassflowPasswordPolicySettings | null;\n url?: string;\n appId?: string;\n scopes?: string[];\n createTenantForNewUser?: boolean;\n parseQueryParams?: boolean;\n isDiscoveringAppId?: boolean;\n hasSettingsError?: boolean;\n};\n\nexport type PassflowAction = { type: 'SET_PASSFLOW_STATE'; payload: PassflowState };\n\nexport type PassflowContextType = {\n state: PassflowState;\n dispatch: Dispatch<PassflowAction>;\n passflow: Passflow;\n};\n\nexport const initialState: PassflowState = {\n appSettings: null,\n passwordPolicy: null,\n url: undefined,\n appId: undefined,\n scopes: undefined,\n createTenantForNewUser: undefined,\n parseQueryParams: true,\n isDiscoveringAppId: false,\n hasSettingsError: false,\n};\n\nexport const PassflowContext = createContext<PassflowContextType | undefined>(undefined);\n\nexport const passflowReducer = (state: PassflowState, action: PassflowAction): PassflowState => {\n switch (action.type) {\n case 'SET_PASSFLOW_STATE':\n return { ...state, ...action.payload };\n default:\n return state;\n }\n};\n","export const routes = {\n signin: {\n path: '/signin',\n },\n signup: {\n path: '/signup',\n },\n verify_otp: {\n path: '/verify-challenge-otp',\n },\n verify_magic_link: {\n path: '/verify-challenge-magic-link',\n },\n forgot_password: {\n path: '/forgot-password',\n },\n forgot_password_success: {\n path: '/forgot-password/success',\n },\n reset_password: {\n path: '/password/reset',\n },\n invitation: {\n path: '/invitation',\n },\n passkey: {\n path: '/passkeysss',\n },\n two_factor_verify: {\n path: '/two-factor-verify',\n },\n two_factor_recovery: {\n path: '/two-factor-recovery',\n },\n two_factor_setup: {\n path: '/two-factor-setup',\n },\n two_factor_setup_magic_link: {\n path: '/two-factor-setup-magic-link/:token',\n },\n};\n","/**\n * The assurance-upgrade context — the one channel between `UpgradeProvider`\n * and `useUpgrade` (architecture §8.2, §13.3).\n *\n * The provider owns the controller, the prompt handler and every transition;\n * this module owns only the shape they are read through. Two hooks each\n * installing a prompt handler would produce two prompts and defeat\n * single-flight, so nothing here installs anything.\n *\n * `status` is §13.5's `UpgradeHookState`, which is §13.3's settlement table\n * read down the hook column. Two consequences the types enforce:\n *\n * - **`insufficient` is a first-class state, not an error and not a success.**\n * \"Elevated to AAL2; this action requires AAL3\" is the normal path for an\n * AAL3 endpoint and a TOTP-only user, and a design cannot both claim the\n * server is the authority and delete the path by which its second refusal\n * reaches the user.\n * - **Cancellation is not a status.** It is `elevate()` resolving `null`. The\n * hook is the one surface where that is right, because there the\n * cancellation IS the whole value: the consumer is rendering a decision, not\n * handling a transport outcome.\n */\n\nimport type { AssuranceBar, UpgradeChallenge, UpgradeFactor, UpgradeFactorType } from '@passflow/core';\nimport { createContext } from 'react';\n\n/** What a protected elevation can fail with, in the hook's vocabulary (§13.3's table). */\nexport type UpgradeErrorStatusKind = 'exhausted' | 'unsatisfiable' | 'unavailable' | 'transport';\n\n/**\n * The hook's observable state. Exactly one terminal state per flight, taken\n * from the controller's outcome summary (§13.4).\n *\n * `idle` is also where a flight abandoned by a session change lands: nothing\n * happened, and nothing is reported as though it had.\n */\nexport type UpgradeHookState =\n | { status: 'idle' }\n | { status: 'challenged'; challenge: UpgradeChallenge; factors: UpgradeFactorType[] }\n | { status: 'submitting' }\n | { status: 'success' }\n | { status: 'insufficient'; obtained: AssuranceBar; required: AssuranceBar }\n | { status: 'error'; kind: UpgradeErrorStatusKind; error: Error };\n\n/** The states a flight can settle in. `null` alongside these is cancellation. */\nexport type UpgradeSettledState = Extract<UpgradeHookState, { status: 'idle' | 'success' | 'insufficient' | 'error' }>;\n\n/** A bar a caller states for itself on the imperative seam (§13.2 T10 / H-6). */\nexport type UpgradeElevateOptions = {\n acrValues?: string;\n maxAge?: number;\n};\n\n/** The open prompt, as the dialog and the hook read it. */\nexport type UpgradePromptView = {\n challenge: UpgradeChallenge;\n /** Already ranked by `selectFactors`; index 0 is the suggested factor. */\n factors: readonly UpgradeFactor[];\n /** The previous attempt's failure, when the controller re-prompted. */\n previousError?: Error;\n};\n\nexport type UpgradeContextValue = {\n /** True when the provider installed a prompt handler on this `Passflow` instance. */\n enabled: boolean;\n state: UpgradeHookState;\n /** The open prompt, or `null` when no elevation is collecting an answer. */\n prompt: UpgradePromptView | null;\n selectedFactor: UpgradeFactorType | null;\n /**\n * The factor-selection signal. Reports the user's choice to the controller\n * through `UpgradePromptRequest.onFactorSelected` the moment it is made and\n * before any answer is submitted — §13.2's late-join boundary (T3), which is\n * selection and not submission.\n */\n selectFactor: (factor: UpgradeFactorType) => void;\n /** Answers the open prompt. Resolves the controller's promise exactly once. */\n submit: (code?: string) => void;\n /** Declines the open prompt. Exactly once; never leaves the promise pending. */\n cancel: () => void;\n /** Acknowledges a terminal state, closing the dialog. Settles nothing. */\n dismiss: () => void;\n /**\n * Drives an elevation directly — a \"verify now\" button, or a headless\n * caller. Resolves **`null`** when the user cancelled, and otherwise the\n * flight's terminal state; it never rejects, because the hook's contract is\n * a rendered decision rather than a thrown transport outcome.\n */\n elevate: (options?: UpgradeElevateOptions) => Promise<UpgradeSettledState | null>;\n};\n\nexport const UpgradeContext = createContext<UpgradeContextValue | undefined>(undefined);\n\nconst noop = (): void => undefined;\n\n/**\n * What `useUpgrade` reads outside an `UpgradeProvider`: idle, inert, and it\n * does not throw (§9.5 H8) — a component that merely wants to know whether an\n * elevation is running is not a bug.\n *\n * `elevate` resolves `{ status: 'idle' }` rather than `null`: nothing was\n * asked and nothing was declined, and `null` means the user declined.\n */\nexport const INERT_UPGRADE_CONTEXT: UpgradeContextValue = {\n enabled: false,\n state: { status: 'idle' },\n prompt: null,\n selectedFactor: null,\n selectFactor: noop,\n submit: noop,\n cancel: noop,\n dismiss: noop,\n elevate: () => Promise.resolve({ status: 'idle' }),\n};\n","import type { LoginWebAppStyle } from '@passflow/core';\n\nexport type CompatibleLoginWebAppStyle = Partial<LoginWebAppStyle> & {\n /** Legacy field used by themes created before text_color was introduced. */\n content_color?: string;\n};\n\nconst nonEmpty = (value: unknown): string | null => (typeof value === 'string' && value.trim() ? value.trim() : null);\n\nconst getBackgroundImage = (value: unknown): string | null => {\n if (typeof value !== 'string') return null;\n\n const image = nonEmpty(value);\n return image ? `url(${image})` : 'none';\n};\n\nexport const getLoginThemeCssVariables = (style: CompatibleLoginWebAppStyle): Record<string, string | null> => ({\n '--passflow-primary-color': nonEmpty(style.primary_color),\n '--passflow-text-color': nonEmpty(style.text_color) ?? nonEmpty(style.content_color),\n '--passflow-secondary-text-color': nonEmpty(style.secondary_text_color),\n '--passflow-background-color': nonEmpty(style.background_color),\n '--passflow-background-image': getBackgroundImage(style.background_image),\n '--passflow-card-color': nonEmpty(style.card_color),\n '--passflow-branding-background-color': nonEmpty(style.card_color),\n '--passflow-input-background-color': nonEmpty(style.input_background_color),\n '--passflow-input-border-color': nonEmpty(style.input_border_color),\n '--passflow-button-text-color': nonEmpty(style.button_text_color),\n '--passflow-passkey-button-text-color': nonEmpty(style.passkey_button_text_color),\n '--passflow-passkey-button-background-color': nonEmpty(style.passkey_button_background_color),\n '--passflow-divider-color': nonEmpty(style.divider_color),\n '--passflow-federated_button_background_color': nonEmpty(style.federated_button_background_color),\n '--passflow-federated_button_text_color': nonEmpty(style.federated_button_text_color),\n});\n\nexport const applyLoginThemeStyles = (root: HTMLElement, style: CompatibleLoginWebAppStyle): void => {\n for (const [property, value] of Object.entries(getLoginThemeCssVariables(style))) {\n if (value === null) root.style.removeProperty(property);\n else root.style.setProperty(property, value);\n }\n};\n","import type { AppSettings, LoginWebAppStyle, LoginWebAppTheme, PassflowPasswordPolicySettings } from '@passflow/core';\nimport { useContext, useLayoutEffect, useRef, useState } from 'react';\nimport { PassflowContext } from '@/context';\nimport { applyLoginThemeStyles, type CompatibleLoginWebAppStyle } from '@/utils/login-theme';\nimport { usePassflow } from './use-passflow';\n\nexport type UseAppSettingsProps = () => {\n appSettings: AppSettings | null;\n passwordPolicy: PassflowPasswordPolicySettings | null;\n isLoading: boolean;\n isError: boolean;\n error: string;\n reset: () => void;\n currentTheme: string;\n currentStyles: LoginWebAppStyle | null;\n scopes: string[];\n createTenantForNewUser: boolean;\n loginAppTheme?: LoginWebAppTheme;\n};\n\nconst hasPasswordStrategy = (strategies: AppSettings['auth_strategies']): boolean => {\n return strategies?.some((strategy) => strategy.type === 'internal' && strategy.strategy?.challenge === 'password') ?? false;\n};\n\nexport const useAppSettings: UseAppSettingsProps = () => {\n const passflow = usePassflow();\n const context = useContext(PassflowContext);\n const [isError, setIsError] = useState(false);\n const [errorMessage, setErrorMessage] = useState('');\n const [isLoading, setIsLoading] = useState(false);\n const isFetchingRef = useRef(false);\n\n if (!context) {\n throw new Error('useAppSetting must be used within an PassflowProvider');\n }\n\n const { state, dispatch } = context;\n\n useLayoutEffect(() => {\n if (!state.appSettings && !state.hasSettingsError && !isFetchingRef.current) {\n const fetchAllSettings = async (): Promise<void> => {\n isFetchingRef.current = true;\n setIsLoading(true);\n try {\n // If appId is not provided, try to discover it from /settings endpoint\n if (!passflow.appId && !state.isDiscoveringAppId) {\n dispatch({\n type: 'SET_PASSFLOW_STATE',\n payload: {\n ...state,\n isDiscoveringAppId: true,\n },\n });\n\n try {\n // Try relative path first (works with dev server proxy and same-origin production)\n // Then fall back to absolute URL if configured\n const urlsToTry = ['/settings'];\n if (passflow.url) {\n urlsToTry.push(`${passflow.url}/settings`);\n }\n\n let response: Response | null = null;\n for (const url of urlsToTry) {\n try {\n const r = await fetch(url);\n if (r.ok) {\n response = r;\n break;\n }\n } catch {}\n }\n\n if (response?.ok) {\n const settings = await response.json();\n\n // Support both response formats:\n // Production: { login_app: { app_id: \"...\", ... } }\n // Dev: { appId: \"...\" }\n const discoveredAppId = settings.login_app?.app_id || settings.appId;\n\n if (discoveredAppId) {\n // Update the passflow instance with discovered appId using setAppId method\n passflow.setAppId(discoveredAppId);\n\n // Collect state updates to apply in one dispatch\n const stateUpdates: Partial<typeof state> = {\n appId: discoveredAppId,\n };\n\n // Also update scopes if available and not already set\n if (!state.scopes) {\n const discoveredScopes = settings.login_app?.scopes || settings.scopes;\n if (discoveredScopes) {\n stateUpdates.scopes = discoveredScopes;\n }\n }\n\n // Update createTenantForNewUser if available and not already set\n if (state.createTenantForNewUser === undefined) {\n const createTenant = settings.login_app?.create_tenant_for_new_user ?? settings.createTenantForNewUser;\n if (createTenant !== undefined) {\n stateUpdates.createTenantForNewUser = createTenant;\n }\n }\n\n // Apply discovered state updates\n dispatch({\n type: 'SET_PASSFLOW_STATE',\n payload: {\n ...state,\n ...stateUpdates,\n isDiscoveringAppId: false,\n },\n });\n } else {\n dispatch({\n type: 'SET_PASSFLOW_STATE',\n payload: {\n ...state,\n isDiscoveringAppId: false,\n },\n });\n }\n }\n } catch (discoveryError) {\n console.warn('Failed to discover appId from /settings:', discoveryError);\n // Continue with the flow - we'll handle missing appId later\n dispatch({\n type: 'SET_PASSFLOW_STATE',\n payload: {\n ...state,\n isDiscoveringAppId: false,\n },\n });\n }\n }\n\n let appSettings = {} as AppSettings;\n if (passflow.appId) {\n appSettings = await passflow.getAppSettings();\n }\n\n // Collect final state updates\n const finalStateUpdates: Partial<typeof state> = {\n appSettings,\n };\n\n if (!state.scopes) finalStateUpdates.scopes = appSettings.defaults?.scopes;\n if (state.createTenantForNewUser === undefined)\n finalStateUpdates.createTenantForNewUser = appSettings.defaults?.create_tenant_for_new_user;\n\n let passwordPolicy = null;\n if (appSettings.auth_strategies && hasPasswordStrategy(appSettings.auth_strategies)) {\n passwordPolicy = await passflow.getPasswordPolicySettings();\n }\n finalStateUpdates.passwordPolicy = passwordPolicy;\n\n dispatch({\n type: 'SET_PASSFLOW_STATE',\n payload: {\n ...state,\n ...finalStateUpdates,\n },\n });\n } catch (e) {\n setIsError(true);\n const error = e as Error;\n setErrorMessage(error.message);\n // Set error flag in context to prevent infinite retry loop\n dispatch({\n type: 'SET_PASSFLOW_STATE',\n payload: {\n ...state,\n hasSettingsError: true,\n },\n });\n } finally {\n setIsLoading(false);\n isFetchingRef.current = false;\n }\n };\n void fetchAllSettings();\n }\n }, [dispatch, state.appSettings, state.hasSettingsError, state.isDiscoveringAppId, passflow]);\n\n const reset = () => {\n setIsError(false);\n setErrorMessage('');\n setIsLoading(false);\n // Clear error flag in context to allow retry\n dispatch({\n type: 'SET_PASSFLOW_STATE',\n payload: {\n ...state,\n hasSettingsError: false,\n },\n });\n };\n\n // `custom_css` is not written here: each screen passes `currentStyles.custom_css`\n // to its shell, which renders it inline.\n const applyThemeStyles = (style: CompatibleLoginWebAppStyle) => {\n applyLoginThemeStyles(document.documentElement, style);\n };\n\n const getCurrentTheme = () => {\n const theme = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';\n\n if (state.appSettings?.login_app_theme?.color_scheme === 'system') return theme;\n\n return state.appSettings?.login_app_theme?.color_scheme ?? theme;\n };\n\n const currentTheme = getCurrentTheme();\n\n const selectedStyle = state.appSettings?.login_app_theme\n ? currentTheme === 'dark'\n ? state.appSettings?.login_app_theme.dark_style\n : state.appSettings?.login_app_theme.light_style\n : null;\n\n if (selectedStyle) {\n applyThemeStyles(selectedStyle);\n }\n\n return {\n appSettings: state.appSettings,\n scopes: state.scopes ?? [],\n createTenantForNewUser: state.createTenantForNewUser ?? false,\n loginAppTheme: state.appSettings?.login_app_theme,\n passwordPolicy: state.passwordPolicy,\n currentStyles: selectedStyle,\n currentTheme: currentTheme,\n isLoading,\n isError,\n error: errorMessage,\n reset,\n } as const;\n};\n","import { useContext } from 'react';\nimport { AuthContext, type AuthContextValue } from '@/context';\n\nexport const useAuth = (): AuthContextValue => {\n const context = useContext(AuthContext);\n if (!context) {\n throw new Error('useAuth must be used within an AuthProvider');\n }\n\n return context;\n};\n","import { usePassflow } from './use-passflow';\n\ntype UseAuthCloudRedirectProps = (cloudPassflowUrl: string) => () => void;\n\nexport const useAuthCloudRedirect: UseAuthCloudRedirectProps = (cloudPassflowUrl: string) => {\n const passflow = usePassflow();\n\n const redirect = () => passflow.authRedirect({ url: cloudPassflowUrl });\n\n return redirect;\n};\n","import { useCallback, useEffect, useMemo, useState } from 'react';\n\n/**\n * The OIDC consent decision, as a hook.\n *\n * The URL is the bearer. `parent_challenge_id` identifies a staged\n * authorization request the server is holding, and possessing that id is what\n * authorizes reading it — there is no Authorization header on the GET. The\n * server hands back a `csrf_token` with the request metadata, and every\n * state-changing POST must carry it back in `X-Passflow-CSRF`. That token is\n * the only thing separating a real decision from one a third-party page forged\n * on the user's behalf, so it is never optional and never cached across\n * challenges.\n *\n * The decision endpoints answer with a discriminated response rather than a\n * redirect status, because the OIDC `response_mode` decides HOW the user gets\n * back to the client: `query` is an ordinary navigation, `form_post` must be a\n * POST with the parameters in a form body (they cannot go in a URL). The server\n * knows which; the client just executes what it is told.\n */\n\nexport type ConsentScopeMetadata = {\n scope: string;\n label: string;\n description: string;\n};\n\n/** What GET /oidc/requests/{parent_challenge_id} hands the page to render itself. */\nexport type ConsentInfo = {\n client_id: string;\n app_name: string;\n app_logo_url: string;\n requested_scopes: string[];\n scope_metadata: ConsentScopeMetadata[];\n redirect_uri: string;\n state: string;\n response_mode: '' | 'query' | 'form_post';\n first_party: boolean;\n csrf_token: string;\n};\n\ntype DecisionResponse =\n | { kind: 'redirect'; url: string }\n | { kind: 'form_post'; action: string; fields: Record<string, string> };\n\ntype ApiErrorBody = {\n error?: string;\n error_description?: string;\n};\n\nexport type ConsentStatus =\n /** Fetching the staged request. */\n | 'loading'\n /** Metadata in hand; awaiting the user's decision. */\n | 'ready'\n /** A decision is in flight. */\n | 'working'\n /** Decision accepted; the browser is on its way back to the client. */\n | 'redirecting'\n /** The link itself is unusable — missing, expired, or rejected id. Terminal. */\n | 'invalid';\n\nexport type ConsentError = {\n message: string;\n description?: string;\n};\n\nexport type UseConsentProps = {\n status: ConsentStatus;\n info: ConsentInfo | null;\n /** The scopes still switched on. A subset of `info.requested_scopes`. */\n grantedScopes: string[];\n error: ConsentError | null;\n /** Metadata for a scope, falling back to the bare scope string. */\n scopeMetadata: (scope: string) => ConsentScopeMetadata;\n /** Switch one requested scope on or off before deciding. */\n toggleScope: (scope: string) => void;\n /** Grant the currently-selected subset. */\n allow: () => Promise<void>;\n /** Refuse the request outright (OAuth2 `access_denied`). */\n deny: () => Promise<void>;\n};\n\nconst readParentChallengeId = (): string => new URLSearchParams(window.location.search).get('parent_challenge_id') ?? '';\n\nconst requestPath = (parentChallengeId: string): string => `/oidc/requests/${encodeURIComponent(parentChallengeId)}`;\n\n/**\n * Execute a `form_post` decision: OIDC response_mode=form_post requires the\n * parameters to arrive as a POST body, which only a real form submission can\n * do cross-origin.\n */\nconst submitFormPost = (action: string, fields: Record<string, string>): void => {\n const form = document.createElement('form');\n form.method = 'POST';\n form.action = action;\n form.style.display = 'none';\n\n for (const [key, value] of Object.entries(fields)) {\n const input = document.createElement('input');\n input.type = 'hidden';\n input.name = key;\n input.value = value;\n form.appendChild(input);\n }\n\n document.body.appendChild(form);\n form.submit();\n};\n\nexport const useConsent = (): UseConsentProps => {\n const parentChallengeId = useMemo(readParentChallengeId, []);\n\n const [status, setStatus] = useState<ConsentStatus>('loading');\n const [info, setInfo] = useState<ConsentInfo | null>(null);\n const [granted, setGranted] = useState<Set<string>>(new Set());\n const [error, setError] = useState<ConsentError | null>(null);\n\n useEffect(() => {\n if (!parentChallengeId) {\n setStatus('invalid');\n setError({\n message: 'Invalid consent link',\n description: 'This consent link is missing required information. Please return to the application and try again.',\n });\n return;\n }\n\n let cancelled = false;\n\n const fetchInfo = async (): Promise<void> => {\n try {\n const res = await fetch(requestPath(parentChallengeId), {\n method: 'GET',\n credentials: 'same-origin',\n headers: { Accept: 'application/json' },\n });\n if (cancelled) return;\n\n if (!res.ok) {\n const body = ((await res.json().catch(() => ({}))) ?? {}) as ApiErrorBody;\n setStatus('invalid');\n setError({\n message: res.status >= 500 ? 'Something went wrong' : 'Consent request unavailable',\n description:\n body.error_description ||\n 'We could not load this consent request. Please return to the application and try again.',\n });\n return;\n }\n\n const data = (await res.json()) as ConsentInfo;\n if (cancelled) return;\n\n setInfo(data);\n // Everything asked for starts granted; the user switches OFF what they\n // do not want. Starting from none would train people to hit Allow on an\n // empty grant and wonder why the app is broken.\n setGranted(new Set(data.requested_scopes));\n setStatus('ready');\n } catch (err) {\n if (cancelled) return;\n setStatus('invalid');\n setError({\n message: 'Connection error',\n description: err instanceof Error ? err.message : 'Could not reach the server. Please check your connection.',\n });\n }\n };\n\n void fetchInfo();\n\n return () => {\n cancelled = true;\n };\n }, [parentChallengeId]);\n\n const toggleScope = useCallback((scope: string): void => {\n setGranted((prev) => {\n const next = new Set(prev);\n if (next.has(scope)) next.delete(scope);\n else next.add(scope);\n return next;\n });\n // Changing the selection invalidates whatever the last failed submit said.\n setError(null);\n }, []);\n\n const decide = useCallback(\n async (decision: 'allow' | 'deny'): Promise<void> => {\n if (!info) return;\n\n setStatus('working');\n setError(null);\n\n const base = requestPath(parentChallengeId);\n const endpoint = decision === 'allow' ? `${base}/consent` : `${base}/reject`;\n const body =\n decision === 'allow'\n ? { granted_scopes: info.requested_scopes.filter((scope) => granted.has(scope)) }\n : { error: 'access_denied', error_description: 'User denied consent' };\n\n try {\n const res = await fetch(endpoint, {\n method: 'POST',\n credentials: 'same-origin',\n headers: {\n 'Content-Type': 'application/json',\n Accept: 'application/json',\n 'X-Passflow-CSRF': info.csrf_token,\n },\n body: JSON.stringify(body),\n });\n\n if (!res.ok) {\n const errBody = ((await res.json().catch(() => ({}))) ?? {}) as ApiErrorBody;\n setStatus('ready');\n setError({\n message: errBody.error_description || 'Could not submit your decision. Please try again.',\n });\n return;\n }\n\n const data = (await res.json()) as DecisionResponse;\n\n if (data.kind === 'redirect') {\n setStatus('redirecting');\n window.location.href = data.url;\n return;\n }\n\n if (data.kind === 'form_post') {\n setStatus('redirecting');\n submitFormPost(data.action, data.fields);\n return;\n }\n\n setStatus('ready');\n setError({ message: 'Unexpected response from server.' });\n } catch (err) {\n setStatus('ready');\n setError({\n message: err instanceof Error ? err.message : 'Could not reach the server. Please try again.',\n });\n }\n },\n [granted, info, parentChallengeId],\n );\n\n const allow = useCallback(() => decide('allow'), [decide]);\n const deny = useCallback(() => decide('deny'), [decide]);\n\n const metadataByScope = useMemo(() => new Map((info?.scope_metadata ?? []).map((meta) => [meta.scope, meta])), [info]);\n\n const scopeMetadata = useCallback(\n (scope: string): ConsentScopeMetadata => metadataByScope.get(scope) ?? { scope, label: scope, description: '' },\n [metadataByScope],\n );\n\n const grantedScopes = useMemo(() => (info?.requested_scopes ?? []).filter((scope) => granted.has(scope)), [granted, info]);\n\n return { status, info, grantedScopes, error, scopeMetadata, toggleScope, allow, deny };\n};\n","import type { PublicKeyCredentialRequestOptionsJSON } from '@simplewebauthn/browser';\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport type { DeviceError } from '@/types/device-errors';\nimport { classifyDeviceError, DeviceApiError } from '@/utils';\n\n/**\n * The RFC 8628 verification flow, as a hook.\n *\n * ── The one rule the whole thing is built around ────────────────────────────\n * Signing in and approving are TWO ACTS, and this hook keeps them two. Proving\n * who you are (`/oidc/device/authenticate`) yields an approval ticket and\n * NOTHING else — no tokens, no session. Approving (`/oidc/device/approve`) is\n * what releases tokens to the waiting terminal, and it needs that ticket.\n *\n * The gap between them is not ceremony, it is RFC 8628 §5.4: an attacker can\n * start a device grant and walk a victim into approving it (STORM-2372). They\n * know the user_code — they created it — and the page is public, so they can\n * read its CSRF token too. Neither can be the authority for approval. Only the\n * ticket, held in this hook's memory and bound to the browser that actually\n * authenticated, can be.\n *\n * So: never collapse authenticate+approve into one call \"for convenience\".\n * Mode 1 puts both behind one TAP (see confirmWithPassword) — that is a UI\n * affordance and is fine, because the human still looked at the code first.\n * Mode 3 skips the tap entirely, which it earns by using an origin-bound\n * passkey; see the note on confirmWithPasskey.\n *\n * When the app requires a second factor, the first ticket cannot approve: the\n * server refuses it. The page asks for the factor (`/oidc/device/second-factor`)\n * and approves with the ticket that answers, which records both.\n */\n\n/** The UI the server resolved for this challenge. A closed set — the client does not choose. */\nexport type DeviceUIMode = 'consent' | 'full_login' | 'passkey';\n\n/** What GET /oidc/device/info hands the page to render itself. */\nexport type DeviceVerifyInfo = {\n mode: DeviceUIMode;\n /** Absent for `passkey` mode, by design — see device_page.go. */\n user_code?: string;\n app_name: string;\n csrf_token: string;\n methods: {\n password: boolean;\n passkey: boolean;\n };\n};\n\n/** A second factor the verification page can take. */\nexport type DeviceSecondFactorMethod = 'totp' | 'recovery_codes';\n\nexport type DeviceVerifyStatus =\n /** Asking the server what to render. */\n | 'loading'\n /** No code yet — show the entry form. */\n | 'code_entry'\n /** Info in hand; awaiting the user. */\n | 'ready'\n /** A call is in flight. */\n | 'working'\n /** A first factor proven; the app wants a second before anything can be approved. */\n | 'second_factor'\n /** Identity proven, ticket held, not yet approved. */\n | 'signed_in'\n /** Approved. The terminal has its tokens. */\n | 'done'\n /** The mode is switched off. Terminal, and nothing approvable is rendered. */\n | 'refused'\n /** Terminal failure — bad/expired code, dead app. */\n | 'failed';\n\nexport type UseDeviceVerifyProps = {\n status: DeviceVerifyStatus;\n info: DeviceVerifyInfo | null;\n error: DeviceError | null;\n /** The email that authenticated, once one has. */\n email: string | null;\n /** Whether an approval ticket is held. */\n isAuthenticated: boolean;\n /** Whether a first-factor ticket is waiting for its second factor. */\n isSecondFactorPending: boolean;\n /** The second factors the server takes, once a sign-in owes one. */\n secondFactorMethods: DeviceSecondFactorMethod[];\n /** Re-run the info lookup for a code typed by hand. */\n submitCode: (code: string) => void;\n /** Prove identity with a password. Does NOT approve. */\n signInWithPassword: (email: string, password: string) => Promise<void>;\n /** Prove identity with a passkey. Does NOT approve. */\n signInWithPasskey: () => Promise<void>;\n /** Approve, using the ticket already held. */\n approve: () => Promise<void>;\n /** One tap: prove identity if needed, then approve. */\n confirmWithPassword: (email: string, password: string) => Promise<void>;\n /** Passkey ceremony then approve, with no tap in between. */\n confirmWithPasskey: () => Promise<void>;\n /**\n * Prove the second factor. Approves too when the act that asked for it was\n * an approval (consent's tap, the passkey mode); otherwise lands on signed_in.\n */\n submitSecondFactor: (method: DeviceSecondFactorMethod, code: string) => Promise<void>;\n /** Clear a recoverable error so the user can try again. */\n clearError: () => void;\n};\n\nconst DEVICE_ENDPOINTS = {\n info: '/oidc/device/info',\n authenticate: '/oidc/device/authenticate',\n approve: '/oidc/device/approve',\n passkeyStart: '/oidc/device/passkey/start',\n secondFactor: '/oidc/device/second-factor',\n} as const;\n\n/** What /oidc/device/authenticate answers with. */\ntype DeviceAuthenticateResponse = {\n approval_ticket: string;\n email?: string;\n /** The app requires a second factor; this ticket cannot approve until one is given. */\n second_factor_required?: boolean;\n second_factor_methods?: string[];\n};\n\nconst SECOND_FACTOR_METHODS: readonly DeviceSecondFactorMethod[] = ['totp', 'recovery_codes'];\n\n/** The factors the server offers that this page can take, in its order. */\nconst toSecondFactorMethods = (methods: string[] | undefined): DeviceSecondFactorMethod[] => {\n const known = (methods ?? []).filter((m): m is DeviceSecondFactorMethod =>\n SECOND_FACTOR_METHODS.includes(m as DeviceSecondFactorMethod),\n );\n return known.length > 0 ? known : ['totp'];\n};\n\n/** Read `user_code` off the URL — the QR encodes verification_uri_complete. */\nconst readUserCodeFromURL = (): string => new URLSearchParams(window.location.search).get('user_code') ?? '';\n\n/**\n * Parse a device endpoint's response, turning any failure into a DeviceApiError\n * that carries the server's stable `reason`.\n */\nconst parseDeviceResponse = async <T>(res: Response): Promise<T> => {\n const body: unknown = await res.json().catch(() => ({}));\n const data = (body ?? {}) as Record<string, unknown>;\n\n if (!res.ok) {\n throw new DeviceApiError({\n reason: typeof data.reason === 'string' ? data.reason : '',\n code: typeof data.error === 'string' ? data.error : '',\n status: res.status,\n description: typeof data.error_description === 'string' ? data.error_description : '',\n });\n }\n return data as T;\n};\n\nexport const useDeviceVerify = (): UseDeviceVerifyProps => {\n const [status, setStatus] = useState<DeviceVerifyStatus>('loading');\n const [info, setInfo] = useState<DeviceVerifyInfo | null>(null);\n const [error, setError] = useState<DeviceError | null>(null);\n const [email, setEmail] = useState<string | null>(null);\n const [userCode, setUserCode] = useState<string>(() => readUserCodeFromURL());\n\n /**\n * The approval ticket. A ref, not state: it is an authorization handle, so it\n * must be readable synchronously by the call that follows the one that earned\n * it. `confirmWithPassword` authenticates and approves back-to-back within a\n * single event; a state read there would still be null, and the approve would\n * be refused for no reason a user could understand.\n */\n const ticketRef = useRef<string | null>(null);\n\n /**\n * The first-factor ticket, while the app still wants a second. Kept apart\n * from ticketRef because it cannot approve, so isAuthenticated must not\n * claim a sign-in the approval would refuse.\n */\n const firstFactorTicketRef = useRef<string | null>(null);\n /** Whether the act that asked for the second factor was an approval. */\n const approveAfterSecondFactorRef = useRef(false);\n const [secondFactorMethods, setSecondFactorMethods] = useState<DeviceSecondFactorMethod[]>([]);\n\n /** Guards against setting state after unmount, and against double-fires. */\n const activeRef = useRef(true);\n useEffect(() => {\n activeRef.current = true;\n return () => {\n activeRef.current = false;\n };\n }, []);\n\n const csrf = info?.csrf_token ?? '';\n\n /**\n * Every back-channel POST: same-origin, JSON, the challenge's CSRF token, and\n * the user_code that scopes it.\n */\n const post = useCallback(\n async <T>(path: string, body: Record<string, unknown>): Promise<T> => {\n const res = await fetch(path, {\n method: 'POST',\n credentials: 'same-origin',\n headers: {\n 'Content-Type': 'application/json',\n Accept: 'application/json',\n 'X-Passflow-CSRF': csrf,\n },\n body: JSON.stringify({ ...body, user_code: userCode }),\n });\n return parseDeviceResponse<T>(res);\n },\n [csrf, userCode],\n );\n\n /**\n * Record a failure: classified for the user, logged in full for us.\n *\n * This is the ONLY place a failure becomes user-visible, which is what makes\n * \"no technical string reaches the screen\" checkable rather than aspirational.\n */\n const fail = useCallback((err: unknown, terminal: DeviceVerifyStatus | null = null) => {\n const classified = classifyDeviceError(err);\n // The detail the user must never read, kept exactly where a developer will\n // look for it first.\n if (classified.detail) {\n console.error('[passflow] device verification:', classified.detail, err);\n }\n if (!activeRef.current) return;\n setError(classified);\n if (terminal) {\n setStatus(terminal);\n return;\n }\n setStatus(\n classified.type === 'mode_disabled'\n ? 'refused'\n : firstFactorTicketRef.current\n ? 'second_factor'\n : ticketRef.current\n ? 'signed_in'\n : 'ready',\n );\n }, []);\n\n // ── Load what to render ───────────────────────────────────────────────────\n const loadInfo = useCallback(async (code: string) => {\n if (!code) {\n setStatus('code_entry');\n setError(null);\n return;\n }\n setStatus('loading');\n setError(null);\n try {\n const res = await fetch(`${DEVICE_ENDPOINTS.info}?user_code=${encodeURIComponent(code)}`, {\n method: 'GET',\n credentials: 'same-origin',\n headers: { Accept: 'application/json' },\n });\n const data = await parseDeviceResponse<DeviceVerifyInfo>(res);\n if (!activeRef.current) return;\n setInfo(data);\n setStatus('ready');\n } catch (err) {\n const classified = classifyDeviceError(err);\n if (classified.detail) {\n console.error('[passflow] device verification:', classified.detail, err);\n }\n if (!activeRef.current) return;\n\n // `code_required` is not a failure — it is the code entry form.\n if (classified.type === 'code_required') {\n setError(null);\n setStatus('code_entry');\n return;\n }\n setError(classified);\n // A disabled mode gets its own terminal state so the page can render a\n // refusal with NOTHING approvable on it. A bad or dead code lands on the\n // entry form, where the remedy (type it again) actually lives.\n setStatus(classified.type === 'mode_disabled' ? 'refused' : 'failed');\n }\n }, []);\n\n useEffect(() => {\n void loadInfo(userCode);\n }, [loadInfo, userCode]);\n\n const submitCode = useCallback((code: string) => {\n setUserCode(code.trim());\n }, []);\n\n // ── Prove identity. Yields a ticket; approves nothing. ────────────────────\n /**\n * Hold the ticket an authentication earned. Returns true when the app wants\n * a second factor first, in which case the ticket cannot approve yet.\n */\n const holdTicket = useCallback((res: DeviceAuthenticateResponse): boolean => {\n if (res.second_factor_required) {\n firstFactorTicketRef.current = res.approval_ticket;\n ticketRef.current = null;\n if (activeRef.current) setSecondFactorMethods(toSecondFactorMethods(res.second_factor_methods));\n return true;\n }\n firstFactorTicketRef.current = null;\n ticketRef.current = res.approval_ticket;\n return false;\n }, []);\n\n const authenticatePassword = useCallback(\n async (emailValue: string, password: string): Promise<boolean> => {\n const res = await post<DeviceAuthenticateResponse>(DEVICE_ENDPOINTS.authenticate, {\n method: 'password',\n email: emailValue,\n password,\n });\n const owesSecondFactor = holdTicket(res);\n if (activeRef.current) setEmail(res.email ?? emailValue);\n return owesSecondFactor;\n },\n [post, holdTicket],\n );\n\n const authenticatePasskey = useCallback(async (): Promise<boolean> => {\n // Thrown as a DOMException so it travels the same road as every real\n // WebAuthn failure and lands on the same classified copy — rather than\n // becoming a second, parallel way for this page to describe a passkey\n // problem, which is how the copy drifts.\n if (typeof window === 'undefined' || !window.PublicKeyCredential) {\n throw new DOMException('this browser does not implement PublicKeyCredential', 'NotSupportedError');\n }\n\n const start = await post<{ passkey_challenge_id: string; publicKey: PublicKeyCredentialRequestOptionsJSON }>(\n DEVICE_ENDPOINTS.passkeyStart,\n {},\n );\n\n // The SDK's existing WebAuthn primitive, not a hand-rolled base64url dance.\n // @simplewebauthn/browser (v14, the same copy @passflow/core uses) takes the\n // server's JSON options as-is. Loaded on demand: only this branch needs it.\n const { startAuthentication } = await import('@simplewebauthn/browser');\n const assertion = await startAuthentication({ optionsJSON: start.publicKey });\n\n const res = await post<DeviceAuthenticateResponse>(DEVICE_ENDPOINTS.authenticate, {\n method: 'passkey',\n passkey_challenge_id: start.passkey_challenge_id,\n passkey_data: assertion,\n });\n const owesSecondFactor = holdTicket(res);\n if (activeRef.current) setEmail(res.email ?? null);\n return owesSecondFactor;\n }, [post, holdTicket]);\n\n // ── The act that releases tokens ──────────────────────────────────────────\n const approveWithTicket = useCallback(async (): Promise<void> => {\n await post(DEVICE_ENDPOINTS.approve, { approval_ticket: ticketRef.current });\n if (!activeRef.current) return;\n setStatus('done');\n }, [post]);\n\n const signInWithPassword = useCallback(\n async (emailValue: string, password: string) => {\n setStatus('working');\n setError(null);\n try {\n const owesSecondFactor = await authenticatePassword(emailValue, password);\n if (!activeRef.current) return;\n approveAfterSecondFactorRef.current = false;\n setStatus(owesSecondFactor ? 'second_factor' : 'signed_in');\n } catch (err) {\n fail(err);\n }\n },\n [authenticatePassword, fail],\n );\n\n const signInWithPasskey = useCallback(async () => {\n setStatus('working');\n setError(null);\n try {\n const owesSecondFactor = await authenticatePasskey();\n if (!activeRef.current) return;\n approveAfterSecondFactorRef.current = false;\n setStatus(owesSecondFactor ? 'second_factor' : 'signed_in');\n } catch (err) {\n fail(err);\n }\n }, [authenticatePasskey, fail]);\n\n const approve = useCallback(async () => {\n setStatus('working');\n setError(null);\n try {\n await approveWithTicket();\n } catch (err) {\n fail(err);\n }\n }, [approveWithTicket, fail]);\n\n /**\n * Mode 1's single tap: prove identity if we have not already, then approve.\n *\n * Two calls behind one button is the affordance; it is NOT a collapse of the\n * §5.4 check. The check is that a human read the code and chose to proceed,\n * and that is exactly what the tap is.\n */\n const confirmWithPassword = useCallback(\n async (emailValue: string, password: string) => {\n setStatus('working');\n setError(null);\n try {\n if (!ticketRef.current && (await authenticatePassword(emailValue, password))) {\n approveAfterSecondFactorRef.current = true;\n if (activeRef.current) setStatus('second_factor');\n return;\n }\n await approveWithTicket();\n } catch (err) {\n fail(err);\n }\n },\n [authenticatePassword, approveWithTicket, fail],\n );\n\n /**\n * Passkey then approve, with nothing in between.\n *\n * For Mode 3 this runs on load, with no user gesture, and both halves of that\n * are deliberate:\n * - WebAuthn L3's get() carries no transient-activation requirement (unlike\n * create()), so firing on load is legal. The phone's own biometric prompt\n * IS the interaction; a button first would add a step that protects nothing.\n * - No §5.4 confirm follows, because a passkey is origin-bound: the\n * authenticator scopes the assertion to this origin, so it cannot be\n * produced on an attacker's page or replayed to one. There is no phished\n * approval to catch and so nothing for the human to compare.\n */\n const confirmWithPasskey = useCallback(async () => {\n setStatus('working');\n setError(null);\n try {\n if (await authenticatePasskey()) {\n approveAfterSecondFactorRef.current = true;\n if (activeRef.current) setStatus('second_factor');\n return;\n }\n await approveWithTicket();\n } catch (err) {\n fail(err);\n }\n }, [authenticatePasskey, approveWithTicket, fail]);\n\n /**\n * The second factor, for a sign-in whose app requires one. The server checks\n * the code for the user the first ticket names and answers with a ticket\n * recording both factors, which is the one that can approve.\n *\n * It approves straight away when the act that asked for the factor was\n * itself an approval: consent's tap, or the passkey mode, which has none.\n */\n const submitSecondFactor = useCallback(\n async (method: DeviceSecondFactorMethod, code: string) => {\n setStatus('working');\n setError(null);\n try {\n const res = await post<{ approval_ticket: string }>(DEVICE_ENDPOINTS.secondFactor, {\n approval_ticket: firstFactorTicketRef.current,\n method,\n code,\n });\n ticketRef.current = res.approval_ticket;\n firstFactorTicketRef.current = null;\n if (approveAfterSecondFactorRef.current) {\n await approveWithTicket();\n return;\n }\n if (activeRef.current) setStatus('signed_in');\n } catch (err) {\n fail(err);\n }\n },\n [post, approveWithTicket, fail],\n );\n\n const clearError = useCallback(() => setError(null), []);\n\n return {\n status,\n info,\n error,\n email,\n isAuthenticated: ticketRef.current !== null,\n isSecondFactorPending: firstFactorTicketRef.current !== null,\n secondFactorMethods,\n submitCode,\n signInWithPassword,\n signInWithPasskey,\n approve,\n confirmWithPassword,\n confirmWithPasskey,\n submitSecondFactor,\n clearError,\n };\n};\n","import type { PassflowSendPasswordResetEmailPayload } from '@passflow/core';\nimport { useCallback, useState } from 'react';\nimport { usePassflow } from './use-passflow';\n\nexport type UseForgotPasswordProps = () => {\n fetch: (payload: PassflowSendPasswordResetEmailPayload) => Promise<boolean>;\n isLoading: boolean;\n isError: boolean;\n error: string;\n reset: () => void;\n};\n\nexport const useForgotPassword: UseForgotPasswordProps = () => {\n const passflow = usePassflow();\n const [isError, setIsError] = useState(false);\n const [errorMessage, setErrorMessage] = useState('');\n const [isLoading, setIsLoading] = useState(false);\n\n const fetch = useCallback(\n async (payload: PassflowSendPasswordResetEmailPayload): Promise<boolean> => {\n try {\n setIsLoading(true);\n await passflow.sendPasswordResetEmail(payload);\n setIsLoading(false);\n return true;\n } catch (e) {\n setIsError(true);\n const error = e as Error;\n setErrorMessage(error.message);\n return false;\n }\n },\n [passflow.sendPasswordResetEmail],\n );\n\n const reset = () => {\n setIsError(false);\n setErrorMessage('');\n setIsLoading(false);\n };\n\n return { fetch, isLoading, isError, error: errorMessage, reset } as const;\n};\n","import { useCallback, useState } from 'react';\nimport { usePassflow } from './use-passflow';\n\nconst invitationJoinError = \"We couldn't accept this invitation. Try again.\";\n\nexport type UseJoinInviteProps = () => {\n fetch: (token: string) => Promise<boolean>;\n isLoading: boolean;\n isError: boolean;\n error: string;\n};\n\nexport const useJoinInvite: UseJoinInviteProps = () => {\n const passflow = usePassflow();\n const [errorMessage, setErrorMessage] = useState('');\n const [isError, setIsError] = useState(false);\n const [isLoading, setIsLoading] = useState(false);\n\n const fetch = useCallback(\n async (token: string): Promise<boolean> => {\n setIsLoading(true);\n setIsError(false);\n setErrorMessage('');\n\n try {\n await passflow.joinInvitation(token);\n return true;\n } catch (error) {\n console.error('[passflow] accepting invitation failed', error);\n setIsError(true);\n setErrorMessage(invitationJoinError);\n return false;\n } finally {\n setIsLoading(false);\n }\n },\n [passflow.joinInvitation],\n );\n\n return { fetch, isLoading, isError, error: errorMessage } as const;\n};\n","import { useCallback, useState } from 'react';\nimport { usePassflow } from './use-passflow';\n\nexport type UseLogoutProps = () => {\n fetch: () => Promise<boolean>;\n isLoading: boolean;\n isError: boolean;\n error: string;\n};\n\nexport const useLogout: UseLogoutProps = () => {\n const passflow = usePassflow();\n const [errorMessage, setErrorMessage] = useState('');\n const [isError, setIsError] = useState(false);\n const [isLoading, setIsLoading] = useState(false);\n\n const fetch = useCallback(async (): Promise<boolean> => {\n try {\n setIsLoading(true);\n await passflow.logOut();\n setIsLoading(false);\n return true;\n } catch (e) {\n setIsError(true);\n const error = e as Error;\n setErrorMessage(error.message);\n return false;\n }\n }, [passflow]);\n\n return { fetch, isLoading, isError, error: errorMessage } as const;\n};\n","import qs from 'query-string';\nimport { useCallback, useContext } from 'react';\nimport { type NavigateFunction, type NavigateOptions, NavigationContext } from '@/context';\n\nexport type ReactRouterNavigateOptions = {\n pathname: string;\n search: string;\n replace?: boolean;\n};\n\nexport type TanstackRouterNavigateOptions = {\n to: string;\n search: Record<string, unknown>;\n replace?: boolean;\n};\n\nexport type WouterNavigateOptions = {\n to: string;\n search?: Record<string, unknown>;\n replace?: boolean;\n};\n\nexport type ReachRouterNavigateOptions = {\n to: string;\n search?: Record<string, unknown>;\n replace?: boolean;\n};\n\nconst parseSearch = (search: string): Record<string, string> => {\n if (!search) return {};\n const parsed = qs.parse(search.startsWith('?') ? search.slice(1) : search);\n return Object.fromEntries(Object.entries(parsed).map(([key, value]) => [key, String(value)]));\n};\n\nexport const useNavigation = () => {\n const { navigate, setNavigate, router, twoFactorVerifyPath, setTwoFactorVerifyPath } = useContext(NavigationContext);\n\n const wrappedSetNavigate = useCallback(\n (\n newNavigate:\n | ((\n to:\n | NavigateOptions\n | string\n | ReactRouterNavigateOptions\n | TanstackRouterNavigateOptions\n | WouterNavigateOptions\n | ReachRouterNavigateOptions,\n ) => void)\n | null,\n ) => {\n if (!newNavigate) {\n setNavigate(null);\n return;\n }\n\n const wrappedNavigate = ((options: NavigateOptions) => {\n const { to, search = '', replace = false } = options;\n\n switch (router) {\n case 'react-router':\n newNavigate({\n pathname: to,\n search: search.startsWith('?') ? search : `?${search}`,\n replace,\n } as ReactRouterNavigateOptions);\n break;\n\n case 'tanstack-router':\n newNavigate({\n to,\n search: parseSearch(search),\n replace,\n } as TanstackRouterNavigateOptions);\n break;\n\n case 'wouter': {\n const searchParamWouter = search ? (search.startsWith('?') ? search : `?${search}`) : '';\n newNavigate({ to: `${to}${searchParamWouter}`, replace } as WouterNavigateOptions);\n break;\n }\n\n default: {\n // default router\n const searchParamDefault = search ? (search.startsWith('?') ? search : `?${search}`) : '';\n if (replace) {\n window.location.replace(`${to}${searchParamDefault}`);\n } else {\n window.location.href = `${to}${searchParamDefault}`;\n }\n }\n }\n }) as NavigateFunction;\n\n setNavigate(wrappedNavigate);\n },\n [setNavigate, router],\n );\n\n return {\n navigate,\n setNavigate: wrappedSetNavigate,\n router,\n twoFactorVerifyPath,\n setTwoFactorVerifyPath,\n };\n};\n","import { type RefObject, useEffect } from 'react';\n\nexport const useOutsideClick = <T extends HTMLElement>(ref: RefObject<T | null>, onClickOutside?: () => void) => {\n useEffect(() => {\n const handleClick = (event: MouseEvent) => {\n if (ref.current && !ref.current.contains(event.target as Node)) {\n if (onClickOutside) {\n onClickOutside();\n }\n }\n };\n\n document.addEventListener('click', handleClick, true);\n\n return () => {\n document.removeEventListener('click', handleClick, true);\n };\n }, [onClickOutside, ref]);\n};\n","import type { PassflowPasswordlessSignInCompletePayload, PassflowValidationResponse } from '@passflow/core';\nimport { useCallback, useState } from 'react';\nimport { verificationRequestErrorMessage } from '@/utils';\nimport { usePassflow } from './use-passflow';\n\nexport type UsePasswordlessCompleteProps = () => {\n fetch: (payload: PassflowPasswordlessSignInCompletePayload) => Promise<PassflowValidationResponse | null>;\n isLoading: boolean;\n isError: boolean;\n error: string;\n reset: () => void;\n};\n\nexport const usePasswordlessComplete: UsePasswordlessCompleteProps = () => {\n const passflow = usePassflow();\n const [errorMessage, setErrorMessage] = useState('');\n const [isError, setIsError] = useState(false);\n const [isLoading, setIsLoading] = useState(false);\n\n const fetch = useCallback(\n async (payload: PassflowPasswordlessSignInCompletePayload): Promise<PassflowValidationResponse | null> => {\n setIsLoading(true);\n setIsError(false);\n setErrorMessage('');\n\n try {\n return await passflow.passwordlessSignInComplete(payload);\n } catch (error) {\n console.error('[passflow] passwordless verification failed', error);\n setIsError(true);\n setErrorMessage(verificationRequestErrorMessage);\n return null;\n } finally {\n setIsLoading(false);\n }\n },\n [passflow],\n );\n\n const reset = () => {\n setIsError(false);\n setErrorMessage('');\n setIsLoading(false);\n };\n\n return {\n fetch,\n isLoading,\n isError,\n error: errorMessage,\n reset,\n } as const;\n};\n","import type { PassflowFederatedAuthPayload, Providers } from '@passflow/core';\nimport { useContext } from 'react';\nimport { PassflowContext } from '@/context';\nimport { isValidUrl } from '@/utils';\nimport { usePassflow } from './use-passflow';\n\nconst getFullRedirectUrl = (redirectUrl?: string): string => {\n if (redirectUrl && isValidUrl(redirectUrl)) {\n return redirectUrl;\n }\n return redirectUrl ? `${window.location.origin}${redirectUrl.startsWith('/') ? '' : '/'}${redirectUrl}` : '';\n};\n\nexport type UseProviderProps = (\n redirectUrl?: string,\n createTenant?: boolean,\n) => {\n federatedWithPopup: (provider: Providers, inviteToken?: string) => void;\n federatedWithRedirect: (provider: Providers, inviteToken?: string) => void;\n};\n\nexport const useProvider: UseProviderProps = (redirectUrl, createTenant) => {\n const passflow = usePassflow();\n const context = useContext(PassflowContext);\n\n const payload = {\n redirect_url: getFullRedirectUrl(redirectUrl),\n scopes: context?.state.scopes,\n create_tenant: createTenant,\n };\n\n const federatedWithPopup = (provider: Providers, inviteToken?: string) =>\n passflow.federatedAuthWithPopup({ provider, invite_token: inviteToken, ...payload } as PassflowFederatedAuthPayload);\n const federatedWithRedirect = (provider: Providers, inviteToken?: string) =>\n passflow.federatedAuthWithRedirect({ provider, invite_token: inviteToken, ...payload } as PassflowFederatedAuthPayload);\n\n return {\n federatedWithPopup,\n federatedWithRedirect,\n };\n};\n","import { useCallback, useState } from 'react';\nimport { usePassflow } from './use-passflow';\n\nexport type UseResetPasswordProps = () => {\n fetch: (newPassword: string) => Promise<boolean>;\n isLoading: boolean;\n isError: boolean;\n error: string;\n reset: () => void;\n};\n\nexport const useResetPassword: UseResetPasswordProps = () => {\n const passflow = usePassflow();\n const [isError, setIsError] = useState(false);\n const [errorMessage, setErrorMessage] = useState('');\n const [isLoading, setIsLoading] = useState(false);\n\n const fetch = useCallback(\n async (newPassword: string): Promise<boolean> => {\n try {\n setIsLoading(true);\n await passflow.resetPassword(newPassword);\n setIsLoading(false);\n return true;\n } catch (e) {\n setIsError(true);\n const error = e as Error;\n setErrorMessage(error.message);\n return false;\n }\n },\n [passflow.resetPassword],\n );\n\n const reset = () => {\n setIsError(false);\n setErrorMessage('');\n setIsLoading(false);\n };\n\n return { fetch, isLoading, isError, error: errorMessage, reset } as const;\n};\n","import { PassflowEvent, type PassflowSubscriber } from '@passflow/core';\nimport { useEffect, useState } from 'react';\nimport { usePassflow } from './use-passflow';\n\nexport type SessionExpiredReason = 'refresh_failed' | 'token_invalid' | 'logged_out';\n\nexport interface UseSessionExpiredOptions {\n /**\n * Called when the session expires.\n * Use this to redirect to your login page.\n */\n onSessionExpired?: (reason: SessionExpiredReason) => void;\n}\n\nexport interface UseSessionExpiredResult {\n /**\n * True if the session has expired and user needs to re-authenticate.\n */\n isSessionExpired: boolean;\n /**\n * The reason why the session expired, if applicable.\n */\n expiredReason: SessionExpiredReason | null;\n /**\n * Reset the session expired state (e.g., after redirecting to login).\n */\n resetSessionExpired: () => void;\n}\n\n/**\n * Hook to handle session expiration events.\n *\n * When the SDK detects that the session is invalid (e.g., refresh token expired),\n * it emits a SessionExpired event. This hook allows you to react to that event\n * and redirect users to your login page.\n *\n * @example\n * ```tsx\n * function App() {\n * const { isSessionExpired } = useSessionExpired({\n * onSessionExpired: (reason) => {\n * console.log('Session expired:', reason);\n * window.location.href = '/login';\n * },\n * });\n *\n * if (isSessionExpired) {\n * return <div>Redirecting to login...</div>;\n * }\n *\n * return <YourApp />;\n * }\n * ```\n */\nexport function useSessionExpired(options?: UseSessionExpiredOptions): UseSessionExpiredResult {\n const passflow = usePassflow();\n const [isSessionExpired, setIsSessionExpired] = useState(false);\n const [expiredReason, setExpiredReason] = useState<SessionExpiredReason | null>(null);\n\n useEffect(() => {\n const subscriber: PassflowSubscriber = {\n onAuthChange: (eventType, payload) => {\n if (eventType === PassflowEvent.SessionExpired) {\n const reason = (payload as { reason?: SessionExpiredReason })?.reason ?? 'refresh_failed';\n setIsSessionExpired(true);\n setExpiredReason(reason);\n options?.onSessionExpired?.(reason);\n } else if (eventType === PassflowEvent.SignIn || eventType === PassflowEvent.Register) {\n // Reset on successful auth\n setIsSessionExpired(false);\n setExpiredReason(null);\n }\n },\n };\n\n passflow.subscribe(subscriber, [PassflowEvent.SessionExpired, PassflowEvent.SignIn, PassflowEvent.Register]);\n\n return () => {\n passflow.unsubscribe(subscriber);\n };\n }, [passflow, options?.onSessionExpired]);\n\n const resetSessionExpired = () => {\n setIsSessionExpired(false);\n setExpiredReason(null);\n };\n\n return {\n isSessionExpired,\n expiredReason,\n resetSessionExpired,\n };\n}\n","import type {\n PassflowPasskeyAuthenticateStartPayload,\n PassflowPasswordlessResponse,\n PassflowPasswordlessSignInPayload,\n PassflowSignInPayload,\n} from '@passflow/core';\nimport { useCallback, useState } from 'react';\nimport type { AuthOperation, AuthUiError } from '@/types';\nimport { authErrorFor } from '@/utils';\nimport { usePassflow } from './use-passflow';\n\nexport type UseSignInProps = () => {\n fetch: (\n payload: PassflowPasskeyAuthenticateStartPayload | PassflowSignInPayload | PassflowPasswordlessSignInPayload,\n type: AuthOperation,\n ) => Promise<boolean | string | PassflowPasswordlessResponse>;\n isLoading: boolean;\n isError: boolean;\n error: AuthUiError | null;\n reset: () => void;\n};\n\nexport const useSignIn: UseSignInProps = () => {\n const passflow = usePassflow();\n const [error, setError] = useState<AuthUiError | null>(null);\n const [isError, setIsError] = useState(false);\n const [isLoading, setIsLoading] = useState(false);\n\n const fetch = useCallback(\n async (\n payload: PassflowPasskeyAuthenticateStartPayload | PassflowSignInPayload | PassflowPasswordlessSignInPayload,\n type: AuthOperation,\n ): Promise<boolean | string | PassflowPasswordlessResponse> => {\n setIsLoading(true);\n setIsError(false);\n setError(null);\n const cleanup = () => setIsLoading(false);\n\n // We'll make sure to call cleanup after the operation completes\n try {\n if (type === 'password') await passflow.signIn(payload as PassflowSignInPayload);\n else if (type === 'passkey') {\n await passflow.passkeyAuthenticate(payload as PassflowPasskeyAuthenticateStartPayload);\n } else {\n return await passflow.passwordlessSignIn(payload as PassflowPasswordlessSignInPayload);\n }\n return true;\n } catch (error) {\n console.error(`[passflow] ${type} sign-in failed`, error);\n setIsError(true);\n setError(authErrorFor('sign-in', type));\n return false;\n } finally {\n cleanup();\n }\n },\n [passflow.passkeyAuthenticate, passflow.passwordlessSignIn, passflow.signIn],\n );\n\n const reset = () => {\n setIsError(false);\n setError(null);\n setIsLoading(false);\n };\n\n return { fetch, isLoading, isError, error, reset } as const;\n};\n","import type {\n PassflowPasskeyRegisterStartPayload,\n PassflowPasswordlessResponse,\n PassflowPasswordlessSignInPayload,\n PassflowSignUpPayload,\n} from '@passflow/core';\nimport { useCallback, useState } from 'react';\nimport type { AuthOperation, AuthUiError } from '@/types';\nimport { authErrorFor } from '@/utils';\nimport { usePassflow } from './use-passflow';\n\nexport type UseSignUpProps = () => {\n fetch: (\n payload: PassflowPasskeyRegisterStartPayload | PassflowSignUpPayload | PassflowPasswordlessSignInPayload,\n type: AuthOperation,\n ) => Promise<boolean | string | PassflowPasswordlessResponse>;\n isLoading: boolean;\n isError: boolean;\n error: AuthUiError | null;\n reset: () => void;\n};\n\nexport const useSignUp: UseSignUpProps = () => {\n const passflow = usePassflow();\n const [isError, setIsError] = useState(false);\n const [error, setError] = useState<AuthUiError | null>(null);\n const [isLoading, setIsLoading] = useState(false);\n\n const fetch = useCallback(\n async (\n payload: PassflowPasskeyRegisterStartPayload | PassflowSignUpPayload | PassflowPasswordlessSignInPayload,\n type: AuthOperation,\n ): Promise<boolean | PassflowPasswordlessResponse> => {\n setIsLoading(true);\n setIsError(false);\n setError(null);\n const cleanup = () => setIsLoading(false);\n\n try {\n if (type === 'password') await passflow.signUp(payload as PassflowSignUpPayload);\n else if (type === 'passkey') {\n await passflow.passkeyRegister(payload as PassflowPasskeyRegisterStartPayload);\n } else {\n const passwordlessResponse = await passflow.passwordlessSignIn(payload as PassflowPasswordlessSignInPayload);\n cleanup();\n return passwordlessResponse;\n }\n cleanup();\n return true;\n } catch (error) {\n console.error(`[passflow] ${type} sign-up failed`, error);\n setIsError(true);\n setError(authErrorFor('sign-up', type));\n cleanup();\n return false;\n } finally {\n cleanup();\n }\n },\n [passflow.signUp, passflow.passkeyRegister, passflow.passwordlessSignIn],\n );\n\n const reset = () => {\n setIsError(false);\n setError(null);\n setIsLoading(false);\n };\n\n return { fetch, isLoading, isError, error, reset } as const;\n};\n","import type { TwoFactorTrustedDevice } from '@passflow/core';\nimport { useCallback, useLayoutEffect, useState } from 'react';\nimport { usePassflow } from './use-passflow';\n\nexport type UseTrustedDevicesProps = () => {\n /** The devices the signed-in user trusted to skip the second factor on this app. */\n data: TwoFactorTrustedDevice[];\n refetch: () => Promise<TwoFactorTrustedDevice[] | null>;\n /**\n * Revokes one device; its next sign-in asks for the second factor again.\n * On success the device leaves `data` without a refetch.\n *\n * @returns true when the server revoked it\n */\n revoke: (deviceId: string) => Promise<boolean>;\n isLoading: boolean;\n isError: boolean;\n errorMessage: string;\n};\n\n/**\n * Hook to list and revoke the signed-in user's trusted devices\n */\nexport const useTrustedDevices: UseTrustedDevicesProps = () => {\n const passflow = usePassflow();\n const [data, setData] = useState<TwoFactorTrustedDevice[]>([]);\n const [isLoading, setIsLoading] = useState<boolean>(false);\n const [isError, setIsError] = useState<boolean>(false);\n const [errorMessage, setErrorMessage] = useState<string>('');\n\n const fail = useCallback((e: unknown) => {\n setIsError(true);\n setErrorMessage((e as Error).message);\n }, []);\n\n const fetch = useCallback(async (): Promise<TwoFactorTrustedDevice[] | null> => {\n setIsLoading(true);\n setIsError(false);\n setErrorMessage('');\n try {\n const devices = await passflow.getTrustedDevices();\n setData(devices);\n return devices;\n } catch (e) {\n fail(e);\n return null;\n } finally {\n setIsLoading(false);\n }\n }, [passflow, fail]);\n\n const revoke = useCallback(\n async (deviceId: string): Promise<boolean> => {\n setIsLoading(true);\n setIsError(false);\n setErrorMessage('');\n try {\n await passflow.revokeTrustedDevice(deviceId);\n setData((devices) => devices.filter((device) => device.id !== deviceId));\n return true;\n } catch (e) {\n fail(e);\n return false;\n } finally {\n setIsLoading(false);\n }\n },\n [passflow, fail],\n );\n\n useLayoutEffect(() => {\n void fetch();\n }, [fetch]);\n\n return {\n data,\n refetch: fetch,\n revoke,\n isLoading,\n isError,\n errorMessage,\n };\n};\n","import type { TwoFactorChallengeResponse, TwoFactorMethod, TwoFactorVerifyResponseV2 } from '@passflow/core';\nimport { useCallback, useState } from 'react';\nimport { usePassflow } from './use-passflow';\n\nexport type UseTwoFactorChallengeReturn = {\n challenge: TwoFactorChallengeResponse | null;\n isLoading: boolean;\n error: Error | null;\n requestChallenge: (firstFactorMethod?: string) => Promise<void>;\n verify: (response: string, trustDevice?: boolean) => Promise<TwoFactorVerifyResponseV2 | null>;\n switchMethod: (method: TwoFactorMethod) => Promise<void>;\n selectedMethod: TwoFactorMethod | null;\n reset: () => void;\n};\n\n/**\n * Hook to manage the v2 two-factor challenge flow with multi-method support\n */\nexport const useTwoFactorChallenge = (): UseTwoFactorChallengeReturn => {\n const passflow = usePassflow();\n const [challenge, setChallenge] = useState<TwoFactorChallengeResponse | null>(null);\n const [selectedMethod, setSelectedMethod] = useState<TwoFactorMethod | null>(null);\n const [isLoading, setIsLoading] = useState<boolean>(false);\n const [error, setError] = useState<Error | null>(null);\n\n const requestChallenge = useCallback(\n async (firstFactorMethod?: string): Promise<void> => {\n setIsLoading(true);\n setError(null);\n\n try {\n const response = await passflow.twoFactor.requestChallenge({\n first_factor_method: firstFactorMethod,\n });\n setChallenge(response);\n setSelectedMethod(response.method);\n } catch (e) {\n setError(e as Error);\n setChallenge(null);\n } finally {\n setIsLoading(false);\n }\n },\n [passflow],\n );\n\n const verify = useCallback(\n async (response: string, trustDevice = false): Promise<TwoFactorVerifyResponseV2 | null> => {\n if (!challenge?.challenge_id) {\n setError(new Error('No active challenge session'));\n return null;\n }\n\n setIsLoading(true);\n setError(null);\n\n try {\n const result = await passflow.twoFactor.verifyV2({\n challenge_id: challenge.challenge_id,\n method: selectedMethod || challenge.method,\n response,\n trust_device: trustDevice,\n });\n return result;\n } catch (e) {\n setError(e as Error);\n return null;\n } finally {\n setIsLoading(false);\n }\n },\n [passflow, challenge, selectedMethod],\n );\n\n const switchMethod = useCallback(\n async (method: TwoFactorMethod): Promise<void> => {\n if (!challenge?.challenge_id) {\n setError(new Error('No active challenge session'));\n return;\n }\n\n setIsLoading(true);\n setError(null);\n\n try {\n const response = await passflow.twoFactor.switchToAlternative({\n challenge_id: challenge.challenge_id,\n method,\n });\n setChallenge(response);\n setSelectedMethod(method);\n } catch (e) {\n setError(e as Error);\n } finally {\n setIsLoading(false);\n }\n },\n [passflow, challenge],\n );\n\n const reset = useCallback(() => {\n setChallenge(null);\n setSelectedMethod(null);\n setError(null);\n setIsLoading(false);\n }, []);\n\n return {\n challenge,\n isLoading,\n error,\n requestChallenge,\n verify,\n switchMethod,\n selectedMethod,\n reset,\n };\n};\n","import type { TwoFactorRegenerateResponse } from '@passflow/core';\nimport { useCallback, useState } from 'react';\nimport { usePassflow } from './use-passflow';\n\nexport type UseTwoFactorManageProps = () => {\n recoveryCodes: string[];\n disable: (code: string) => Promise<boolean>;\n regenerateCodes: (code: string) => Promise<TwoFactorRegenerateResponse | null>;\n reset: () => void;\n isLoading: boolean;\n isError: boolean;\n error: string;\n};\n\n/**\n * Hook to manage 2FA (disable, regenerate codes)\n */\nexport const useTwoFactorManage: UseTwoFactorManageProps = () => {\n const passflow = usePassflow();\n const [recoveryCodes, setRecoveryCodes] = useState<string[]>([]);\n const [isLoading, setIsLoading] = useState<boolean>(false);\n const [isError, setIsError] = useState<boolean>(false);\n const [error, setError] = useState<string>('');\n\n const disable = useCallback(\n async (code: string): Promise<boolean> => {\n setIsLoading(true);\n setIsError(false);\n setError('');\n try {\n await passflow.disableTwoFactor(code);\n return true;\n } catch (e) {\n setIsError(true);\n const err = e as Error;\n setError(err.message);\n return false;\n } finally {\n setIsLoading(false);\n }\n },\n [passflow],\n );\n\n const regenerateCodes = useCallback(\n async (code: string): Promise<TwoFactorRegenerateResponse | null> => {\n setIsLoading(true);\n setIsError(false);\n setError('');\n try {\n const response = await passflow.regenerateTwoFactorRecoveryCodes(code);\n setRecoveryCodes(response.recovery_codes);\n return response;\n } catch (e) {\n setIsError(true);\n const err = e as Error;\n setError(err.message);\n return null;\n } finally {\n setIsLoading(false);\n }\n },\n [passflow],\n );\n\n const reset = useCallback(() => {\n setRecoveryCodes([]);\n setIsError(false);\n setError('');\n }, []);\n\n return {\n recoveryCodes,\n disable,\n regenerateCodes,\n reset,\n isLoading,\n isError,\n error,\n };\n};\n","import type { RegisteredTwoFactorMethod, TwoFactorMethod } from '@passflow/core';\nimport { useCallback, useState } from 'react';\nimport { usePassflow } from './use-passflow';\n\nexport type UseTwoFactorMethodsReturn = {\n availableMethods: TwoFactorMethod[];\n registeredMethods: RegisteredTwoFactorMethod[];\n isLoading: boolean;\n error: Error | null;\n refresh: () => Promise<void>;\n removeMethod: (methodId: string) => Promise<void>;\n};\n\n/**\n * Hook to manage two-factor authentication methods\n */\nexport const useTwoFactorMethods = (): UseTwoFactorMethodsReturn => {\n const passflow = usePassflow();\n const [availableMethods, setAvailableMethods] = useState<TwoFactorMethod[]>([]);\n const [registeredMethods, setRegisteredMethods] = useState<RegisteredTwoFactorMethod[]>([]);\n const [isLoading, setIsLoading] = useState<boolean>(false);\n const [error, setError] = useState<Error | null>(null);\n\n const refresh = useCallback(async (): Promise<void> => {\n setIsLoading(true);\n setError(null);\n\n try {\n const methods = await passflow.twoFactor.getRegisteredMethods();\n setRegisteredMethods(methods);\n\n // Extract available methods from registered methods\n const available = methods.map((m) => m.method);\n setAvailableMethods(available);\n } catch (e) {\n setError(e as Error);\n setRegisteredMethods([]);\n setAvailableMethods([]);\n } finally {\n setIsLoading(false);\n }\n }, [passflow]);\n\n const removeMethod = useCallback(\n async (methodId: string): Promise<void> => {\n setIsLoading(true);\n setError(null);\n\n try {\n // Call remove method API (needs to be implemented in @passflow/core)\n // For now, this is a placeholder\n await passflow.twoFactor.removeMethod?.(methodId);\n\n // Refresh the methods list after removal\n await refresh();\n } catch (e) {\n setError(e as Error);\n } finally {\n setIsLoading(false);\n }\n },\n [passflow, refresh],\n );\n\n return {\n availableMethods,\n registeredMethods,\n isLoading,\n error,\n refresh,\n removeMethod,\n };\n};\n","import type { TwoFactorConfirmResponse, TwoFactorSetupResponse } from '@passflow/core';\nimport { useCallback, useState } from 'react';\nimport { usePassflow } from './use-passflow';\n\nexport type TwoFactorSetupStep = 'idle' | 'setup' | 'complete';\n\nexport type UseTwoFactorSetupProps = () => {\n setupData: TwoFactorSetupResponse | null;\n recoveryCodes: string[];\n step: TwoFactorSetupStep;\n beginSetup: () => Promise<TwoFactorSetupResponse | null>;\n confirmSetup: (code: string) => Promise<TwoFactorConfirmResponse | null>;\n reset: () => void;\n isLoading: boolean;\n isError: boolean;\n error: string;\n};\n\n/**\n * Hook to handle 2FA setup flow (enable 2FA)\n */\nexport const useTwoFactorSetup: UseTwoFactorSetupProps = () => {\n const passflow = usePassflow();\n const [setupData, setSetupData] = useState<TwoFactorSetupResponse | null>(null);\n const [recoveryCodes, setRecoveryCodes] = useState<string[]>([]);\n const [isLoading, setIsLoading] = useState<boolean>(false);\n const [isError, setIsError] = useState<boolean>(false);\n const [error, setError] = useState<string>('');\n const [step, setStep] = useState<TwoFactorSetupStep>('idle');\n\n const beginSetup = useCallback(async (): Promise<TwoFactorSetupResponse | null> => {\n setIsLoading(true);\n setIsError(false);\n setError('');\n try {\n const response = await passflow.beginTwoFactorSetup();\n setSetupData(response);\n setStep('setup');\n return response;\n } catch (e) {\n setIsError(true);\n const err = e as Error;\n setError(err.message);\n return null;\n } finally {\n setIsLoading(false);\n }\n }, [passflow]);\n\n const confirmSetup = useCallback(\n async (code: string): Promise<TwoFactorConfirmResponse | null> => {\n setIsLoading(true);\n setIsError(false);\n setError('');\n try {\n const response = await passflow.confirmTwoFactorSetup(code);\n setRecoveryCodes(response.recovery_codes);\n setStep('complete');\n return response;\n } catch (e) {\n setIsError(true);\n const err = e as Error;\n setError(err.message);\n return null;\n } finally {\n setIsLoading(false);\n }\n },\n [passflow],\n );\n\n const reset = useCallback(() => {\n setSetupData(null);\n setRecoveryCodes([]);\n setIsError(false);\n setError('');\n setStep('idle');\n }, []);\n\n return {\n setupData,\n recoveryCodes,\n step,\n beginSetup,\n confirmSetup,\n reset,\n isLoading,\n isError,\n error,\n };\n};\n","import { useCallback, useEffect, useRef, useState } from 'react';\nimport { usePassflow } from './use-passflow';\n\n/**\n * Magic link validation error type\n */\nexport type TwoFactorSetupMagicLinkError = {\n code: 'INVALID_TOKEN' | 'EXPIRED_TOKEN' | 'REVOKED_TOKEN' | 'RATE_LIMITED' | 'SERVER_ERROR';\n message: string;\n retryAfter?: number; // Seconds until retry allowed (for RATE_LIMITED)\n};\n\n/**\n * Expected response shape from passflow.validateTwoFactorSetupMagicLink\n */\ntype ValidationResponse = {\n success: boolean;\n sessionToken?: string;\n userId?: string;\n expiresIn?: number;\n appId?: string | null;\n error?: TwoFactorSetupMagicLinkError;\n};\n\n/**\n * Return type for useTwoFactorSetupMagicLink hook\n */\nexport type UseTwoFactorSetupMagicLinkReturn = {\n /** True during validation */\n isLoading: boolean;\n /** True during retry attempt */\n isRetrying: boolean;\n /** True if token validated successfully */\n isValidated: boolean;\n /** Error details if validation failed */\n error: TwoFactorSetupMagicLinkError | null;\n /** Session token if validated */\n sessionToken: string | null;\n /** User ID if validated */\n userId: string | null;\n /** App ID if validated (may be null) */\n appId: string | null;\n /** Session expiration in seconds */\n expiresIn: number | null;\n /** Retry countdown for rate-limited errors (null if not rate limited) */\n retryCountdown: number | null;\n /** Manual retry function for transient errors */\n retry: () => Promise<void>;\n};\n\n/**\n * Hook to validate magic link token for 2FA setup\n *\n * This hook:\n * - Validates token on mount (automatic)\n * - Caches validation result per token (prevents duplicate calls)\n * - Provides loading, error, and success states\n * - Allows manual retry for transient failures\n * - Handles rate limit countdown\n * - Cleans up conditionally on unmount (only if validation failed or not validated)\n *\n * Usage:\n * ```tsx\n * const { isLoading, isValidated, error, retry, retryCountdown } = useTwoFactorSetupMagicLink(token);\n *\n * if (isLoading) return <Loading />;\n * if (error) return <ErrorUI error={error} onRetry={retry} countdown={retryCountdown} />;\n * if (isValidated) return <TwoFactorSetupForm />;\n * ```\n */\nexport const useTwoFactorSetupMagicLink = (token: string): UseTwoFactorSetupMagicLinkReturn => {\n const passflow = usePassflow();\n\n // State management\n const [isLoading, setIsLoading] = useState<boolean>(true);\n const [isRetrying, setIsRetrying] = useState<boolean>(false);\n const [isValidated, setIsValidated] = useState<boolean>(false);\n const [error, setError] = useState<TwoFactorSetupMagicLinkError | null>(null);\n const [sessionToken, setSessionToken] = useState<string | null>(null);\n const [userId, setUserId] = useState<string | null>(null);\n const [appId, setAppId] = useState<string | null>(null);\n const [expiresIn, setExpiresIn] = useState<number | null>(null);\n const [retryCountdown, setRetryCountdown] = useState<number | null>(null);\n\n // Cache key for validation (prevents duplicate calls for same token)\n const [validatedToken, setValidatedToken] = useState<string | null>(null);\n\n // Ref to track if we should clear session on unmount\n const shouldClearOnUnmount = useRef<boolean>(true);\n\n // Countdown timer ref\n const countdownTimerRef = useRef<NodeJS.Timeout | null>(null);\n\n /**\n * Start rate limit countdown timer\n */\n const startCountdown = useCallback((seconds: number) => {\n // Clear existing timer\n if (countdownTimerRef.current) {\n clearInterval(countdownTimerRef.current);\n }\n\n setRetryCountdown(seconds);\n\n countdownTimerRef.current = setInterval(() => {\n setRetryCountdown((prev) => {\n if (prev === null || prev <= 1) {\n if (countdownTimerRef.current) {\n clearInterval(countdownTimerRef.current);\n countdownTimerRef.current = null;\n }\n return null;\n }\n return prev - 1;\n });\n }, 1000);\n }, []);\n\n /**\n * Validate token via JS SDK\n */\n const validateToken = useCallback(\n async (isRetry = false) => {\n // Skip if already validated this token\n if (!isRetry && validatedToken === token && isValidated) {\n return;\n }\n\n // Reset state\n if (isRetry) {\n setIsRetrying(true);\n } else {\n setIsLoading(true);\n }\n setError(null);\n\n try {\n // Call JS SDK validation method\n // Cast to unknown to support cases where React SDK builds before JS SDK types are updated\n const passflowWithMagicLink = passflow as unknown as {\n validateTwoFactorSetupMagicLink: (token: string) => Promise<ValidationResponse>;\n };\n const response = await passflowWithMagicLink.validateTwoFactorSetupMagicLink(token);\n\n if (response.success && response.sessionToken && response.userId) {\n // Success - store session details\n setSessionToken(response.sessionToken);\n setUserId(response.userId);\n setAppId(response.appId ?? null);\n setExpiresIn(response.expiresIn ?? null);\n setIsValidated(true);\n setValidatedToken(token);\n setRetryCountdown(null);\n // Don't clear session on unmount if validation succeeded\n shouldClearOnUnmount.current = false;\n } else if (response.error) {\n // Validation failed\n setError(response.error);\n setIsValidated(false);\n shouldClearOnUnmount.current = true;\n\n // Start countdown for rate-limited errors\n if (response.error.code === 'RATE_LIMITED' && response.error.retryAfter) {\n startCountdown(response.error.retryAfter);\n }\n }\n } catch (err) {\n // Unexpected error (shouldn't happen - SDK catches errors)\n setError({\n code: 'SERVER_ERROR',\n message: err instanceof Error ? err.message : 'An unexpected error occurred',\n });\n setIsValidated(false);\n shouldClearOnUnmount.current = true;\n } finally {\n setIsLoading(false);\n setIsRetrying(false);\n }\n },\n [token, validatedToken, isValidated, passflow, startCountdown],\n );\n\n /**\n * Manual retry for transient errors\n */\n const retry = useCallback(async () => {\n // Don't allow retry during countdown\n if (retryCountdown !== null && retryCountdown > 0) {\n return;\n }\n\n // Reset cache to allow retry\n setValidatedToken(null);\n await validateToken(true);\n }, [validateToken, retryCountdown]);\n\n /**\n * Validate on mount or when token changes\n */\n useEffect(() => {\n if (!token) {\n setError({\n code: 'INVALID_TOKEN',\n message: 'No token provided',\n });\n setIsLoading(false);\n return;\n }\n\n // Validate if token changed or not yet validated\n if (token !== validatedToken) {\n validateToken();\n }\n }, [token, validatedToken, validateToken]);\n\n /**\n * Cleanup on unmount - conditional based on validation state\n * Per review feedback: Only clear if validation failed or user navigated away before validation\n */\n useEffect(() => {\n return () => {\n // Clear countdown timer\n if (countdownTimerRef.current) {\n clearInterval(countdownTimerRef.current);\n }\n\n // Only clear magic link session if validation failed or wasn't validated\n // If isValidated=true, let the form handle session clearing after confirm\n if (shouldClearOnUnmount.current) {\n const passflowWithSession = passflow as unknown as { clearMagicLinkSession?: () => void };\n passflowWithSession.clearMagicLinkSession?.();\n }\n };\n }, [passflow]);\n\n return {\n isLoading,\n isRetrying,\n isValidated,\n error,\n sessionToken,\n userId,\n appId,\n expiresIn,\n retryCountdown,\n retry,\n };\n};\n","import type { TwoFactorStatusResponse } from '@passflow/core';\nimport { useCallback, useLayoutEffect, useState } from 'react';\nimport { usePassflow } from './use-passflow';\n\nexport type UseTwoFactorStatusProps = () => {\n data: TwoFactorStatusResponse | null;\n refetch: () => Promise<TwoFactorStatusResponse | null>;\n isLoading: boolean;\n isError: boolean;\n errorMessage: string;\n};\n\n/**\n * Hook to get the current 2FA enrollment status\n */\nexport const useTwoFactorStatus: UseTwoFactorStatusProps = () => {\n const passflow = usePassflow();\n const [data, setData] = useState<TwoFactorStatusResponse | null>(null);\n const [isLoading, setIsLoading] = useState<boolean>(false);\n const [isError, setIsError] = useState<boolean>(false);\n const [errorMessage, setErrorMessage] = useState<string>('');\n\n const fetch = useCallback(async (): Promise<TwoFactorStatusResponse | null> => {\n setIsLoading(true);\n setIsError(false);\n setErrorMessage('');\n try {\n const response = await passflow.getTwoFactorStatus();\n setData(response);\n return response;\n } catch (e) {\n setIsError(true);\n const error = e as Error;\n setErrorMessage(error.message);\n return null;\n } finally {\n setIsLoading(false);\n }\n }, [passflow]);\n\n useLayoutEffect(() => {\n void fetch();\n }, [fetch]);\n\n return {\n data,\n refetch: fetch,\n isLoading,\n isError,\n errorMessage,\n };\n};\n","import type { TwoFactorCompletionOptions, TwoFactorRecoveryResponse, TwoFactorVerifyResponse } from '@passflow/core';\nimport { useCallback, useState } from 'react';\nimport type { TwoFactorError, TwoFactorErrorType } from '@/types/two-factor-errors';\nimport { classifyTwoFactorError } from '@/utils/classify-two-factor-error';\nimport { usePassflow } from './use-passflow';\n\nexport type UseTwoFactorVerifyProps = () => {\n isVerificationRequired: () => boolean;\n /** `options.trustDevice` asks the server to trust this device for later sign-ins. */\n verify: (code: string, options?: TwoFactorCompletionOptions) => Promise<TwoFactorVerifyResponse | null>;\n /** `options.trustDevice` asks the server to trust this device for later sign-ins. */\n useRecoveryCode: (code: string, options?: TwoFactorCompletionOptions) => Promise<TwoFactorRecoveryResponse | null>;\n reset: () => void;\n isLoading: boolean;\n isError: boolean;\n error: string;\n errorType: TwoFactorErrorType | null;\n errorDetails: TwoFactorError | null;\n};\n\n/**\n * Hook to verify 2FA code during login with error classification\n */\nexport const useTwoFactorVerify: UseTwoFactorVerifyProps = () => {\n const passflow = usePassflow();\n const [isLoading, setIsLoading] = useState<boolean>(false);\n const [isError, setIsError] = useState<boolean>(false);\n const [error, setError] = useState<string>('');\n const [errorType, setErrorType] = useState<TwoFactorErrorType | null>(null);\n const [errorDetails, setErrorDetails] = useState<TwoFactorError | null>(null);\n\n const isVerificationRequired = useCallback((): boolean => {\n return passflow.isTwoFactorVerificationRequired();\n }, [passflow]);\n\n const handleError = useCallback((e: unknown) => {\n const err = e as Error;\n const classified = classifyTwoFactorError(err.message);\n\n setIsError(true);\n setError(err.message);\n setErrorType(classified.type);\n setErrorDetails(classified);\n }, []);\n\n const verify = useCallback(\n async (code: string, options?: TwoFactorCompletionOptions): Promise<TwoFactorVerifyResponse | null> => {\n setIsLoading(true);\n setIsError(false);\n setError('');\n setErrorType(null);\n setErrorDetails(null);\n\n try {\n const response = await passflow.verifyTwoFactor(code, options);\n return response;\n } catch (e) {\n handleError(e);\n return null;\n } finally {\n setIsLoading(false);\n }\n },\n [passflow, handleError],\n );\n\n const useRecoveryCode = useCallback(\n async (code: string, options?: TwoFactorCompletionOptions): Promise<TwoFactorRecoveryResponse | null> => {\n setIsLoading(true);\n setIsError(false);\n setError('');\n setErrorType(null);\n setErrorDetails(null);\n\n try {\n const response = await passflow.useTwoFactorRecoveryCode(code, options);\n return response;\n } catch (e) {\n handleError(e);\n return null;\n } finally {\n setIsLoading(false);\n }\n },\n [passflow, handleError],\n );\n\n const reset = useCallback(() => {\n setIsError(false);\n setError('');\n setErrorType(null);\n setErrorDetails(null);\n }, []);\n\n return {\n isVerificationRequired,\n verify,\n useRecoveryCode,\n reset,\n isLoading,\n isError,\n error,\n errorType,\n errorDetails,\n };\n};\n","/**\n * `useUpgrade` — the read side of the assurance-upgrade flow (§8.2, §13.3).\n *\n * It **reads `UpgradeContext` and installs nothing**. Installation belongs to\n * `UpgradeProvider` and only to it: two hooks each installing a prompt handler\n * would open two prompts and defeat single-flight.\n *\n * Outside an `UpgradeProvider` it returns `status: 'idle'` with no-op actions\n * rather than throwing (§9.5 H8).\n */\n\nimport type { AssuranceBar, UpgradeChallenge, UpgradeFactor, UpgradeFactorType } from '@passflow/core';\nimport { useContext, useMemo } from 'react';\nimport {\n INERT_UPGRADE_CONTEXT,\n UpgradeContext,\n type UpgradeContextValue,\n type UpgradeElevateOptions,\n type UpgradeErrorStatusKind,\n type UpgradeHookState,\n type UpgradePromptView,\n type UpgradeSettledState,\n} from '@/context/upgrade-context';\n\nexport type UseUpgradeResult = {\n /** True when an `UpgradeProvider` installed a prompt handler. */\n enabled: boolean;\n /** The whole state, as the discriminated union (§13.5's `UpgradeHookState`). */\n state: UpgradeHookState;\n /** The discriminant, for the common `status === 'challenged'` read. */\n status: UpgradeHookState['status'];\n /** What the server demanded — the MERGED requirement when challenges joined. */\n challenge: UpgradeChallenge | null;\n /** Usable factors, already ranked; index 0 is the suggested one. */\n factors: readonly UpgradeFactor[];\n /** The ranked factor types, which is what `UpgradeHookState.challenged` carries. */\n factorTypes: readonly UpgradeFactorType[];\n selectedFactor: UpgradeFactorType | null;\n /**\n * Elevated, and still not enough: the replay was re-challenged (§13.4).\n * Non-null **only** in the `insufficient` state, and it never coexists with\n * `status === 'success'` — this must not read as success.\n */\n insufficient: { obtained: AssuranceBar; required: AssuranceBar } | null;\n /** The terminal failure, in the `error` state only. */\n error: Error | null;\n /** Which failure class, in the `error` state only. */\n errorKind: UpgradeErrorStatusKind | null;\n /** The previous attempt's failure while the prompt is re-shown (a wrong code). */\n previousError: Error | null;\n /** True while a ceremony is on the wire. */\n busy: boolean;\n /** The factor-selection signal — §13.2's late-join boundary (T3). */\n selectFactor: (factor: UpgradeFactorType) => void;\n submit: (code?: string) => void;\n cancel: () => void;\n dismiss: () => void;\n /** Resolves `null` on cancellation; otherwise the flight's terminal state. */\n elevate: (options?: UpgradeElevateOptions) => Promise<UpgradeSettledState | null>;\n};\n\nconst EMPTY_FACTORS: readonly UpgradeFactor[] = [];\n\nconst readPromptFactors = (prompt: UpgradePromptView | null): readonly UpgradeFactor[] =>\n prompt === null ? EMPTY_FACTORS : prompt.factors;\n\nexport const useUpgrade = (): UseUpgradeResult => {\n const context: UpgradeContextValue = useContext(UpgradeContext) ?? INERT_UPGRADE_CONTEXT;\n const { enabled, state, prompt, selectedFactor, selectFactor, submit, cancel, dismiss, elevate } = context;\n\n return useMemo<UseUpgradeResult>(() => {\n const factors = readPromptFactors(prompt);\n\n return {\n enabled,\n state,\n status: state.status,\n challenge: state.status === 'challenged' ? state.challenge : (prompt?.challenge ?? null),\n factors,\n factorTypes: state.status === 'challenged' ? state.factors : factors.map((factor) => factor.type),\n selectedFactor,\n insufficient: state.status === 'insufficient' ? { obtained: state.obtained, required: state.required } : null,\n error: state.status === 'error' ? state.error : null,\n errorKind: state.status === 'error' ? state.kind : null,\n previousError: prompt?.previousError ?? null,\n busy: state.status === 'submitting',\n selectFactor,\n submit,\n cancel,\n dismiss,\n elevate,\n };\n }, [enabled, state, prompt, selectedFactor, selectFactor, submit, cancel, dismiss, elevate]);\n};\n","import type { PassflowUserPasskey } from '@passflow/core';\nimport { useLayoutEffect, useState } from 'react';\nimport { usePassflow } from './use-passflow';\n\nexport type UseUserPasskeysProps = () => {\n data: PassflowUserPasskey[];\n createUserPasskey: (relaingPartyId: string) => Promise<void>;\n editUserPasskey: (newName: string, passkeyId: string) => Promise<void>;\n deleteUserPasskey: (passkeyId: string) => Promise<void>;\n isLoading: boolean;\n isError: boolean;\n errorMessage: string;\n};\n\nexport const useUserPasskeys: UseUserPasskeysProps = () => {\n const passflow = usePassflow();\n const [data, setData] = useState<PassflowUserPasskey[]>([]);\n const [isError, setIsError] = useState<boolean>(false);\n const [errorMessage, setErrorMessage] = useState<string>('');\n const [isLoading, setIsLoading] = useState<boolean>(false);\n\n useLayoutEffect(() => {\n const fetch = async (): Promise<void> => {\n setIsLoading(true);\n try {\n const response = await passflow.getUserPasskeys();\n setData(response as unknown as PassflowUserPasskey[]);\n } catch (e) {\n setIsError(true);\n const error = e as Error;\n setErrorMessage(error.message);\n } finally {\n setIsLoading(false);\n }\n };\n\n void fetch();\n }, [passflow]);\n\n const createUserPasskey = async (\n relyingPartyId: string,\n passkeyUsername?: string,\n passkeyDisplayName?: string,\n ): Promise<void> => {\n setIsLoading(true);\n try {\n await passflow.addUserPasskey({ relyingPartyId, passkeyUsername, passkeyDisplayName });\n } catch (e) {\n setIsError(true);\n const error = e as Error;\n setErrorMessage(error.message);\n } finally {\n setIsLoading(false);\n }\n };\n\n const editUserPasskey = async (newName: string, passkeyId: string): Promise<void> => {\n setIsLoading(true);\n try {\n const editUserPasskeyStatus = await passflow.renameUserPasskey(newName, passkeyId);\n if (editUserPasskeyStatus) {\n const userPasskeys = await passflow.getUserPasskeys();\n setData(userPasskeys as unknown as PassflowUserPasskey[]);\n }\n } catch (e) {\n setIsError(true);\n const error = e as Error;\n setErrorMessage(error.message);\n } finally {\n setIsLoading(false);\n }\n };\n\n const deleteUserPasskey = async (passkeyId: string): Promise<void> => {\n setIsLoading(true);\n try {\n const deleteUserPasskeyStatus = await passflow.deleteUserPasskey(passkeyId);\n if (deleteUserPasskeyStatus) {\n const userPasskeys = await passflow.getUserPasskeys();\n setData(userPasskeys as unknown as PassflowUserPasskey[]);\n }\n } catch (e) {\n setIsError(true);\n const error = e as Error;\n setErrorMessage(error.message);\n } finally {\n setIsLoading(false);\n }\n };\n\n return {\n data,\n createUserPasskey,\n editUserPasskey,\n deleteUserPasskey,\n isLoading,\n isError,\n errorMessage,\n };\n};\n","import { getCountryForTimezone } from 'countries-and-timezones';\nimport {\n type ChangeEvent,\n type FC,\n type InputHTMLAttributes,\n type KeyboardEvent,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { type CountryIso2, defaultCountries, parseCountry, usePhoneInput } from 'react-international-phone';\nimport { useOutsideClick } from '@/hooks';\nimport { cn } from '@/utils';\nimport { Button, CountryFlag, Icon } from '..';\n\nimport '@/styles/index.css';\nimport 'react-international-phone/style.css';\n\ntype TFieldPhone = InputHTMLAttributes<HTMLInputElement> & {\n id: string;\n onChange: (event: ChangeEvent<HTMLInputElement>) => void;\n isError?: boolean;\n className?: string;\n // eslint-disable-next-line react/no-unused-prop-types\n ref?: null;\n};\n\nexport const FieldPhone: FC<TFieldPhone> = ({\n id,\n name,\n onChange,\n isError = false,\n className = '',\n disabled = false,\n ...inputProps\n}) => {\n const [show, setShow] = useState(false);\n const [filterValue, setFilterValue] = useState('');\n const [isFocused, setIsFocused] = useState(false);\n const refWrapper = useRef<HTMLDivElement>(null);\n const searchInputRef = useRef<HTMLInputElement>(null);\n\n useEffect(() => {\n if (show) searchInputRef.current?.focus();\n }, [show]);\n\n useOutsideClick(refWrapper, () => {\n setShow(false);\n setFilterValue('');\n });\n\n const userTZ = Intl.DateTimeFormat().resolvedOptions().timeZone;\n const userCountry = getCountryForTimezone(userTZ);\n const { inputValue, country, setCountry, handlePhoneValueChange, inputRef } = usePhoneInput({\n defaultCountry: userCountry?.id.toLocaleLowerCase() || 'us',\n });\n\n const handlePhoneChange = (event: ChangeEvent<HTMLInputElement>) => {\n handlePhoneValueChange(event);\n onChange(event);\n };\n\n const filteredCountries = useMemo(\n () =>\n defaultCountries.filter((defCountry) => {\n const { name: countryName } = parseCountry(defCountry);\n return countryName.toLowerCase().includes(filterValue.toLowerCase());\n }),\n [filterValue],\n );\n\n const preferredCountries = useMemo(\n () =>\n defaultCountries.filter((defCountry) => {\n const { iso2 } = parseCountry(defCountry);\n return iso2 === userCountry?.id.toLocaleLowerCase();\n }),\n [userCountry?.id],\n );\n\n const allCountries = useMemo(() => {\n if (filterValue) return filteredCountries;\n const preferredIso = new Set(preferredCountries.map((defCountry) => parseCountry(defCountry).iso2));\n return filteredCountries.filter((defCountry) => !preferredIso.has(parseCountry(defCountry).iso2));\n }, [filterValue, filteredCountries, preferredCountries]);\n\n const restoreCountryButtonFocus = () => {\n refWrapper.current?.querySelector<HTMLButtonElement>('.passflow-button-show-country')?.focus();\n };\n\n const handleShow = () => setShow(true);\n\n const handleClose = (restoreFocus = false) => {\n setShow(false);\n setFilterValue('');\n if (restoreFocus) restoreCountryButtonFocus();\n };\n\n const handleChangeCountry = (iso2: CountryIso2) => {\n setCountry(iso2);\n handleClose(true);\n };\n\n const handleOptionKeyDown = (event: KeyboardEvent<HTMLDivElement>, iso2: CountryIso2) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n handleChangeCountry(iso2);\n return;\n }\n\n if (event.key !== 'ArrowDown' && event.key !== 'ArrowUp') return;\n event.preventDefault();\n const options = Array.from(refWrapper.current?.querySelectorAll<HTMLElement>('[role=\"option\"]') ?? []);\n const currentIndex = options.indexOf(event.currentTarget);\n const nextIndex =\n event.key === 'ArrowDown' ? Math.min(currentIndex + 1, options.length - 1) : Math.max(currentIndex - 1, 0);\n options[nextIndex]?.focus();\n };\n\n const renderCountry = (defCountry: (typeof defaultCountries)[number]) => {\n const { name: countryName, dialCode, iso2 } = parseCountry(defCountry);\n return (\n <div\n key={iso2}\n role='option'\n aria-selected={iso2 === country.iso2}\n tabIndex={0}\n title={countryName}\n onClick={() => handleChangeCountry(iso2)}\n onKeyDown={(event) => handleOptionKeyDown(event, iso2)}\n className='passflow-country-search-item'\n >\n <CountryFlag iso2={iso2} className='passflow-country-search-flag' />\n <span className='passflow-country-search-name'>{countryName}</span>\n <span className='passflow-country-search-code'>+{dialCode}</span>\n </div>\n );\n };\n\n return (\n <div\n ref={refWrapper}\n className={cn(\n 'passflow-field-phone-wrapper',\n { 'passflow-field-phone-wrapper--focus': isFocused, 'passflow-field-phone-wrapper--error': isError },\n className,\n )}\n >\n <Button\n type='button'\n variant='clean'\n onClick={() => (show ? handleClose(true) : handleShow())}\n size='big'\n className='passflow-button-show-country'\n disabled={disabled}\n aria-label={`Select country, current ${country.iso2.toUpperCase()}`}\n aria-haspopup='listbox'\n aria-expanded={show}\n aria-controls='passflow-country-options'\n >\n <CountryFlag iso2={country.iso2} />\n <Icon type='general' id='caret-down' size='small' />\n </Button>\n\n {!show ? (\n <input\n {...inputProps}\n id={id}\n name={name}\n ref={inputRef}\n type='tel'\n value={inputValue}\n disabled={disabled}\n aria-invalid={isError}\n onChange={handlePhoneChange}\n onFocus={() => setIsFocused(true)}\n onBlur={() => setIsFocused(false)}\n className='passflow-field-phone-input'\n />\n ) : (\n <div className='passflow-field-country-search-wrapper'>\n <input\n ref={searchInputRef}\n role='combobox'\n aria-label='Search countries'\n aria-expanded='true'\n aria-controls='passflow-country-options'\n aria-autocomplete='list'\n value={filterValue}\n onChange={(event) => setFilterValue(event.target.value)}\n onKeyDown={(event) => {\n if (event.key === 'Escape') handleClose(true);\n if (event.key === 'ArrowDown') {\n event.preventDefault();\n refWrapper.current?.querySelector<HTMLElement>('[role=\"option\"]')?.focus();\n }\n }}\n className='passflow-field-country-search'\n onFocus={() => setIsFocused(true)}\n onBlur={() => setIsFocused(false)}\n placeholder='Search for a country'\n />\n <div className='passflow-field-country-search-icon'>\n <Icon type='general' id='search' size='small' />\n </div>\n </div>\n )}\n\n <div\n id='passflow-country-options'\n role='listbox'\n tabIndex={-1}\n aria-label='Countries'\n aria-hidden={!show}\n className={cn('passflow-country-search-wrapper', {\n 'passflow-country-search-wrapper--show': show,\n 'passflow-country-search-wrapper--hidden': !show,\n 'passflow-country-search-wrapper--without-preferred': !!filterValue || preferredCountries.length === 0,\n })}\n >\n {filteredCountries.length > 0 ? (\n <>\n <div role='presentation' aria-hidden='true' className='passflow-country-search-sticky-top' />\n {!filterValue && preferredCountries.length > 0 ? (\n <>\n {preferredCountries.map(renderCountry)}\n <div role='presentation' className='passflow-country-search-divider'>\n All countries\n </div>\n </>\n ) : null}\n {allCountries.map(renderCountry)}\n <div role='presentation' aria-hidden='true' className='passflow-country-search-sticky-bottom' />\n </>\n ) : (\n <div role='presentation' className='passflow-country-search-no-matches'>\n No matches\n </div>\n )}\n </div>\n </div>\n );\n};\n","/* eslint-disable react/jsx-props-no-spreading */\nimport { forwardRef, type InputHTMLAttributes } from 'react';\nimport '@/styles/index.css';\nimport { cn } from '@/utils';\n\ntype TFieldText = InputHTMLAttributes<HTMLInputElement> & {\n id: string;\n isError?: boolean;\n className?: string;\n disabled?: boolean;\n};\n\nexport const FieldText = forwardRef<HTMLInputElement, TFieldText>(\n ({ id, isError = false, className = '', disabled = false, ...rest }, ref) => {\n const styles = {\n 'passflow-field--error': isError,\n };\n\n return (\n <input\n ref={ref}\n id={id}\n type='text'\n className={cn('passflow-field-input passflow-field--focused', styles, className)}\n disabled={disabled}\n {...rest}\n />\n );\n },\n);\n","export default \"data:image/svg+xml,%3csvg%20width='44'%20height='44'%20viewBox='0%200%2044%2044'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3crect%20width='44'%20height='44'%20rx='6'%20fill='%23F3F5F7'/%3e%3cg%20clip-path='url(%23clip0_2691_4741)'%3e%3cpath%20d='M21.9999%2019.3334C20.5272%2019.3334%2019.3333%2020.5273%2019.3333%2022C19.3333%2023.4728%2020.5272%2024.6667%2021.9999%2024.6667C23.4727%2024.6667%2024.6666%2023.4728%2024.6666%2022C24.6666%2020.5273%2023.4727%2019.3334%2021.9999%2019.3334ZM21.9999%2019.3334H28.1133M16.6333%2018.04L19.6933%2023.3334M21.2533%2028.6267L24.3066%2023.3334M28.6666%2022C28.6666%2025.6819%2025.6818%2028.6667%2021.9999%2028.6667C18.318%2028.6667%2015.3333%2025.6819%2015.3333%2022C15.3333%2018.3181%2018.318%2015.3334%2021.9999%2015.3334C25.6818%2015.3334%2028.6666%2018.3181%2028.6666%2022Z'%20stroke='%237F7F7F'%20stroke-width='1.5'%20stroke-linecap='round'%20stroke-linejoin='round'/%3e%3c/g%3e%3cdefs%3e%3cclipPath%20id='clip0_2691_4741'%3e%3crect%20width='16'%20height='16'%20fill='white'%20transform='translate(14%2014)'/%3e%3c/clipPath%3e%3c/defs%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M4%206L8%2010L12%206H4Z'%20fill='%236B6F76'/%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M4%208L6.82843%2010.8284L12.4847%205.17155'%20stroke='%236B6F76'%20stroke-width='1.5'%20stroke-linecap='round'%20stroke-linejoin='round'/%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M10.6666%2010.6667L7.99993%208.00001M7.99993%208.00001L5.33325%205.33333M7.99993%208.00001L10.6666%205.33333M7.99993%208.00001L5.33325%2010.6667'%20stroke='%236B6F76'%20stroke-width='1.5'%20stroke-linecap='round'%20stroke-linejoin='round'/%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M8.00004%208.66667C8.36823%208.66667%208.66671%208.36819%208.66671%208C8.66671%207.63181%208.36823%207.33333%208.00004%207.33333C7.63185%207.33333%207.33337%207.63181%207.33337%208C7.33337%208.36819%207.63185%208.66667%208.00004%208.66667Z'%20stroke='%236B6F76'%20stroke-width='1.5'%20stroke-linecap='round'%20stroke-linejoin='round'/%3e%3cpath%20d='M8.00004%204C8.36823%204%208.66671%203.70152%208.66671%203.33333C8.66671%202.96514%208.36823%202.66667%208.00004%202.66667C7.63185%202.66667%207.33337%202.96514%207.33337%203.33333C7.33337%203.70152%207.63185%204%208.00004%204Z'%20stroke='%236B6F76'%20stroke-width='1.5'%20stroke-linecap='round'%20stroke-linejoin='round'/%3e%3cpath%20d='M8.00004%2013.3333C8.36823%2013.3333%208.66671%2013.0349%208.66671%2012.6667C8.66671%2012.2985%208.36823%2012%208.00004%2012C7.63185%2012%207.33337%2012.2985%207.33337%2012.6667C7.33337%2013.0349%207.63185%2013.3333%208.00004%2013.3333Z'%20stroke='%236B6F76'%20stroke-width='1.5'%20stroke-linecap='round'%20stroke-linejoin='round'/%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M11.6231%206.86026L9.13975%204.37687M2%2014L4.10117%2013.7665C4.35789%2013.738%204.48624%2013.7238%204.60622%2013.6849C4.71266%2013.6505%204.81395%2013.6018%204.90735%2013.5402C5.01263%2013.4708%205.10395%2013.3794%205.28659%2013.1968L13.4857%204.99772C14.1714%204.31195%2014.1714%203.2001%2013.4857%202.51433C12.7999%201.82856%2011.6881%201.82856%2011.0023%202.51433L2.80321%2010.7134C2.62056%2010.896%202.52924%2010.9874%202.45982%2011.0926C2.39823%2011.186%202.34955%2011.2873%202.31509%2011.3938C2.27625%2011.5138%202.26199%2011.6421%202.23346%2011.8988L2%2014Z'%20stroke='%236B6F76'%20stroke-width='1.5'%20stroke-linecap='round'%20stroke-linejoin='round'/%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M7.16196%203.39488C7.4329%203.35482%207.7124%203.33333%208.00028%203.33333C11.4036%203.33333%2013.6369%206.33656%2014.3871%207.52455C14.4779%207.66833%2014.5233%207.74023%2014.5488%207.85112C14.5678%207.93439%2014.5678%208.06578%2014.5487%208.14905C14.5233%208.25993%2014.4776%208.3323%2014.3861%208.47705C14.1862%208.79343%2013.8814%209.23807%2013.4777%209.7203M4.48288%204.47669C3.0415%205.45447%202.06297%206.81292%201.61407%207.52352C1.52286%207.66791%201.47725%207.74011%201.45183%207.85099C1.43273%207.93426%201.43272%208.06563%201.45181%208.14891C1.47722%208.25979%201.52262%208.33168%201.61342%208.47545C2.36369%209.66344%204.59694%2012.6667%208.00028%2012.6667C9.37255%2012.6667%2010.5546%2012.1784%2011.5259%2011.5177M2.00028%202L14.0003%2014M6.58606%206.58579C6.22413%206.94772%206.00028%207.44772%206.00028%208C6.00028%209.10457%206.89571%2010%208.00028%2010C8.55256%2010%209.05256%209.77614%209.41449%209.41421'%20stroke='%236B6F76'%20stroke-width='1.5'%20stroke-linecap='round'%20stroke-linejoin='round'/%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M1.61342%208.47545C1.52262%208.33169%201.47723%208.25981%201.45182%208.14895C1.43273%208.06567%201.43273%207.93434%201.45182%207.85106C1.47723%207.74019%201.52262%207.66831%201.61341%207.52455C2.36369%206.33656%204.59693%203.33334%208.00027%203.33334C11.4036%203.33334%2013.6369%206.33656%2014.3871%207.52455C14.4779%207.66831%2014.5233%207.74019%2014.5487%207.85106C14.5678%207.93434%2014.5678%208.06567%2014.5487%208.14895C14.5233%208.25981%2014.4779%208.33169%2014.3871%208.47545C13.6369%209.66344%2011.4036%2012.6667%208.00027%2012.6667C4.59693%2012.6667%202.36369%209.66344%201.61342%208.47545Z'%20stroke='%236B6F76'%20stroke-width='1.5'%20stroke-linecap='round'%20stroke-linejoin='round'/%3e%3cpath%20d='M8.00027%2010C9.10484%2010%2010.0003%209.10457%2010.0003%208C10.0003%206.89543%209.10484%206%208.00027%206C6.8957%206%206.00027%206.89543%206.00027%208C6.00027%209.10457%206.8957%2010%208.00027%2010Z'%20stroke='%236B6F76'%20stroke-width='1.5'%20stroke-linecap='round'%20stroke-linejoin='round'/%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M11.1111%206.1333C11.1111%205.81483%2010.9896%205.49636%2010.7466%205.25338C10.5037%205.01039%2010.1852%204.88889%209.86669%204.88889M9.86669%209.86667C11.9286%209.86667%2013.6%208.1952%2013.6%206.13333C13.6%204.07147%2011.9286%202.4%209.86669%202.4C7.80483%202.4%206.13336%204.07147%206.13336%206.13333C6.13336%206.30362%206.14476%206.47125%206.16684%206.63549C6.20316%206.90562%206.22131%207.04069%206.20909%207.12615C6.19636%207.21516%206.18015%207.26313%206.13627%207.34163C6.09416%207.41698%206.01993%207.4912%205.87148%207.63965L2.69162%2010.8195C2.584%2010.9271%202.53019%2010.9809%202.49171%2011.0437C2.4576%2011.0994%202.43246%2011.1601%202.41722%2011.2236C2.40002%2011.2952%202.40002%2011.3713%202.40002%2011.5235V12.6044C2.40002%2012.9529%202.40002%2013.1272%202.46784%2013.2603C2.5275%2013.3773%202.62269%2013.4725%202.73976%2013.5322C2.87286%2013.6%203.0471%2013.6%203.39558%2013.6H4.88891V12.3556H6.13336V11.1111H7.3778L8.36037%2010.1285C8.50882%209.98009%208.58305%209.90587%208.6584%209.86375C8.73689%209.81988%208.78486%209.80367%208.87388%209.79093C8.95933%209.77871%209.0944%209.79687%209.36453%209.83319C9.52878%209.85527%209.6964%209.86667%209.86669%209.86667Z'%20stroke='%236B6F76'%20stroke-width='1.5'%20stroke-linecap='round'%20stroke-linejoin='round'/%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='43'%20height='10'%20viewBox='0%200%2043%2010'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M8.91%209H5.346L5.236%207.988H3.674L3.564%209H0L2.178%200.53H6.732L8.91%209ZM4.158%203.665L4.037%204.721H4.873L4.752%203.665H4.158ZM16.6389%206.712C16.5215%207.482%2016.1145%208.087%2015.4179%208.527C14.7212%208.95967%2013.8082%209.176%2012.6789%209.176C11.5495%209.176%2010.6365%208.95967%209.93988%208.527C9.25054%208.09433%208.84354%207.49667%208.71888%206.734C8.68954%206.52867%208.66388%206.25367%208.64188%205.909C8.62721%205.557%208.61988%205.17933%208.61988%204.776C8.61988%204.38733%208.62721%204.028%208.64188%203.698C8.66388%203.36067%208.68954%203.09667%208.71888%202.906C8.84354%202.09933%209.25421%201.47233%209.95088%201.025C10.6475%200.577666%2011.5569%200.354%2012.6789%200.354C13.8082%200.354%2014.7212%200.577666%2015.4179%201.025C16.1145%201.465%2016.5215%202.07733%2016.6389%202.862C16.6682%203.05267%2016.6902%203.31667%2016.7049%203.654C16.7269%203.984%2016.7379%204.347%2016.7379%204.743C16.7379%205.161%2016.7269%205.54233%2016.7049%205.887C16.6902%206.23167%2016.6682%206.50667%2016.6389%206.712ZM12.9759%206.206V3.324C12.9759%203.126%2012.8769%203.027%2012.6789%203.027C12.4809%203.027%2012.3819%203.126%2012.3819%203.324V6.206C12.3819%206.404%2012.4809%206.503%2012.6789%206.503C12.8769%206.503%2012.9759%206.404%2012.9759%206.206ZM25.1574%206.712C25.0401%207.482%2024.6331%208.087%2023.9364%208.527C23.2398%208.95967%2022.3268%209.176%2021.1974%209.176C20.0681%209.176%2019.1551%208.95967%2018.4584%208.527C17.7691%208.09433%2017.3621%207.49667%2017.2374%206.734C17.2081%206.52867%2017.1824%206.25367%2017.1604%205.909C17.1458%205.557%2017.1384%205.17933%2017.1384%204.776C17.1384%204.38733%2017.1458%204.028%2017.1604%203.698C17.1824%203.36067%2017.2081%203.09667%2017.2374%202.906C17.3621%202.09933%2017.7728%201.47233%2018.4694%201.025C19.1661%200.577666%2020.0754%200.354%2021.1974%200.354C22.3268%200.354%2023.2398%200.577666%2023.9364%201.025C24.6331%201.465%2025.0401%202.07733%2025.1574%202.862C25.1868%203.05267%2025.2088%203.31667%2025.2234%203.654C25.2454%203.984%2025.2564%204.347%2025.2564%204.743C25.2564%205.161%2025.2454%205.54233%2025.2234%205.887C25.2088%206.23167%2025.1868%206.50667%2025.1574%206.712ZM21.4944%206.206V3.324C21.4944%203.126%2021.3954%203.027%2021.1974%203.027C20.9994%203.027%2020.9004%203.126%2020.9004%203.324V6.206C20.9004%206.404%2020.9994%206.503%2021.1974%206.503C21.3954%206.503%2021.4944%206.404%2021.4944%206.206ZM33.555%200.53V3.797H31.432V9H27.769V3.797H25.635V0.53H33.555ZM38.4495%202.906V0.53H42.0135V9H38.4495V6.272H37.5585V9H33.9945V0.53H37.5585V2.906H38.4495Z'%20fill='%236B6F76'/%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='44'%20height='44'%20viewBox='0%200%2044%2044'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3crect%20width='44'%20height='44'%20rx='8'%20fill='%231E1E1E'%20/%3e%3cpath%20d='M21.2532%2031H13.6932V12.52H24.9012C25.9252%2012.52%2026.8612%2012.72%2027.7092%2013.12C28.5732%2013.504%2029.2612%2014.184%2029.7732%2015.16C30.2852%2016.12%2030.5412%2017.456%2030.5412%2019.168C30.5412%2020.848%2030.2772%2022.184%2029.7492%2023.176C29.2212%2024.152%2028.5252%2024.856%2027.6612%2025.288C26.8132%2025.704%2025.8932%2025.912%2024.9012%2025.912H21.2532V31ZM23.1252%2018.592H20.8212V19.888H23.1972C23.3252%2019.888%2023.4612%2019.848%2023.6052%2019.768C23.7652%2019.688%2023.8452%2019.52%2023.8452%2019.264C23.8452%2018.992%2023.7572%2018.816%2023.5812%2018.736C23.4052%2018.64%2023.2532%2018.592%2023.1252%2018.592Z'%20fill='white'%20/%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='44'%20height='44'%20viewBox='0%200%2044%2044'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3crect%20width='44'%20height='44'%20rx='8'%20fill='%23D85D5D'%20/%3e%3cpath%20d='M21.2532%2031H13.6932V12.52H24.9012C25.9252%2012.52%2026.8612%2012.72%2027.7092%2013.12C28.5732%2013.504%2029.2612%2014.184%2029.7732%2015.16C30.2852%2016.12%2030.5412%2017.456%2030.5412%2019.168C30.5412%2020.848%2030.2772%2022.184%2029.7492%2023.176C29.2212%2024.152%2028.5252%2024.856%2027.6612%2025.288C26.8132%2025.704%2025.8932%2025.912%2024.9012%2025.912H21.2532V31ZM23.1252%2018.592H20.8212V19.888H23.1972C23.3252%2019.888%2023.4612%2019.848%2023.6052%2019.768C23.7652%2019.688%2023.8452%2019.52%2023.8452%2019.264C23.8452%2018.992%2023.7572%2018.816%2023.5812%2018.736C23.4052%2018.64%2023.2532%2018.592%2023.1252%2018.592Z'%20fill='white'%20/%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M1.33337%204.66666L6.77665%208.47696C7.21743%208.78551%207.43783%208.93978%207.67755%208.99954C7.8893%209.05232%208.11078%209.05232%208.32253%208.99954C8.56226%208.93978%208.78265%208.78551%209.22343%208.47696L14.6667%204.66666M4.53337%2013.3333H11.4667C12.5868%2013.3333%2013.1469%2013.3333%2013.5747%2013.1153C13.951%2012.9236%2014.257%2012.6176%2014.4487%2012.2413C14.6667%2011.8135%2014.6667%2011.2534%2014.6667%2010.1333V5.86666C14.6667%204.74656%2014.6667%204.18651%2014.4487%203.75868C14.257%203.38236%2013.951%203.0764%2013.5747%202.88465C13.1469%202.66666%2012.5868%202.66666%2011.4667%202.66666H4.53337C3.41327%202.66666%202.85322%202.66666%202.42539%202.88465C2.04907%203.0764%201.74311%203.38236%201.55136%203.75868C1.33337%204.18651%201.33337%204.74656%201.33337%205.86666V10.1333C1.33337%2011.2534%201.33337%2011.8135%201.55136%2012.2413C1.74311%2012.6176%202.04907%2012.9236%202.42539%2013.1153C2.85322%2013.3333%203.41327%2013.3333%204.53337%2013.3333Z'%20stroke='%236B6F76'%20stroke-width='1.5'%20stroke-linecap='round'%20stroke-linejoin='round'/%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='44'%20height='44'%20viewBox='0%200%2044%2044'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3crect%20width='44'%20height='44'%20rx='6'%20fill='%23F3F5F7'/%3e%3cg%20clip-path='url(%23clip0_2691_4730)'%3e%3cpath%20d='M20.8039%2020.4084V18.2344C20.8039%2017.9893%2021.0026%2017.7906%2021.2477%2017.7906H22.7785C23.0236%2017.7906%2023.2222%2017.9893%2023.2222%2018.2344V22.2139C23.2222%2022.2748%2023.1918%2022.3212%2023.1614%2022.3669L22.7785%2022.7498C22.6864%2022.8419%2022.6864%2022.9797%2022.7785%2023.0558L23.1614%2023.4386C23.1819%2023.4582%2023.198%2023.4821%2023.2086%2023.5085C23.2191%2023.5349%2023.2237%2023.5633%2023.2222%2023.5916V25.7648C23.2222%2025.8825%2023.1755%2025.9954%2023.0923%2026.0786C23.009%2026.1618%2022.8962%2026.2086%2022.7785%2026.2086H21.2477C21.13%2026.2086%2021.0171%2026.1618%2020.9339%2026.0786C20.8507%2025.9954%2020.8039%2025.8825%2020.8039%2025.7648V21.7853C20.8039%2021.7244%2020.8344%2021.678%2020.8648%2021.6323L21.2477%2021.2494C21.3398%2021.1573%2021.3398%2021.0195%2021.2477%2020.9434L20.8648%2020.5606C20.8443%2020.5411%2020.8282%2020.5174%2020.8177%2020.4911C20.8072%2020.4649%2020.8025%2020.4366%2020.8039%2020.4084ZM27.7064%2022C27.7064%2021.2503%2027.5587%2020.5079%2027.2718%2019.8153C26.9849%2019.1227%2026.5644%2018.4933%2026.0343%2017.9632C25.5042%2017.4331%2024.8748%2017.0126%2024.1822%2016.7257C23.4895%2016.4388%2022.7472%2016.2911%2021.9975%2016.2911C21.2478%2016.2911%2020.5054%2016.4388%2019.8128%2016.7257C19.1201%2017.0126%2018.4908%2017.4331%2017.9607%2017.9632C17.4305%2018.4933%2017.01%2019.1227%2016.7231%2019.8153C16.4362%2020.5079%2016.2886%2021.2503%2016.2886%2022C16.2886%2023.5141%2016.89%2024.9662%2017.9607%2026.0368C19.0313%2027.1074%2020.4834%2027.7089%2021.9975%2027.7089C23.5116%2027.7089%2024.9637%2027.1074%2026.0343%2026.0368C27.1049%2024.9662%2027.7064%2023.5141%2027.7064%2022ZM29.5127%2022C29.5127%2026.1477%2026.1452%2029.5%2022.0127%2029.5C17.865%2029.5%2014.5127%2026.1325%2014.5127%2022C14.5127%2017.8523%2017.8802%2014.5%2022.0127%2014.5C26.1452%2014.5%2029.5127%2017.8523%2029.5127%2022Z'%20fill='%237F7F7F'/%3e%3c/g%3e%3cdefs%3e%3cclipPath%20id='clip0_2691_4730'%3e%3crect%20width='16'%20height='16'%20fill='white'%20transform='translate(14%2014)'/%3e%3c/clipPath%3e%3c/defs%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='44'%20height='44'%20viewBox='0%200%2044%2044'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3crect%20width='44'%20height='44'%20rx='6'%20fill='%23F3F5F7'/%3e%3cpath%20d='M25.3333%2020C25.3333%2019.6587%2025.2031%2019.3175%2024.9428%2019.0572C24.6825%2018.7968%2024.3412%2018.6667%2024%2018.6667M24%2024C26.2091%2024%2028%2022.2091%2028%2020C28%2017.7909%2026.2091%2016%2024%2016C21.7909%2016%2020%2017.7909%2020%2020C20%2020.1825%2020.0122%2020.3621%2020.0359%2020.538C20.0748%2020.8275%2020.0942%2020.9722%2020.0811%2021.0637C20.0675%2021.1591%2020.0501%2021.2105%2020.0031%2021.2946C19.958%2021.3753%2019.8785%2021.4549%2019.7194%2021.6139L16.3124%2025.0209C16.1971%2025.1362%2016.1395%2025.1939%2016.0982%2025.2611C16.0617%2025.3208%2016.0348%2025.3858%2016.0184%2025.4538C16%2025.5306%2016%2025.6121%2016%2025.7752V26.9333C16%2027.3067%2016%2027.4934%2016.0727%2027.636C16.1366%2027.7614%2016.2386%2027.8634%2016.364%2027.9273C16.5066%2028%2016.6933%2028%2017.0667%2028H18.6667V26.6667H20V25.3333H21.3333L22.3861%2024.2806C22.5451%2024.1215%2022.6247%2024.042%2022.7054%2023.9969C22.7895%2023.9499%2022.8409%2023.9325%2022.9363%2023.9189C23.0278%2023.9058%2023.1725%2023.9252%2023.462%2023.9641C23.6379%2023.9878%2023.8175%2024%2024%2024Z'%20stroke='%237F7F7F'%20stroke-width='1.5'%20stroke-linecap='round'%20stroke-linejoin='round'/%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='17'%20height='16'%20viewBox='0%200%2017%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M8.49998%2011.6666H8.50665M5.96665%2014.6666H11.0333C11.78%2014.6666%2012.1534%2014.6666%2012.4386%2014.5213C12.6895%2014.3934%2012.8935%2014.1895%2013.0213%2013.9386C13.1666%2013.6534%2013.1666%2013.28%2013.1666%2012.5333V3.46659C13.1666%202.71985%2013.1666%202.34648%2013.0213%202.06126C12.8935%201.81038%2012.6895%201.60641%2012.4386%201.47858C12.1534%201.33325%2011.78%201.33325%2011.0333%201.33325H5.96665C5.21991%201.33325%204.84654%201.33325%204.56133%201.47858C4.31044%201.60641%204.10647%201.81038%203.97864%202.06126C3.83331%202.34648%203.83331%202.71985%203.83331%203.46659V12.5333C3.83331%2013.28%203.83331%2013.6534%203.97864%2013.9386C4.10647%2014.1895%204.31044%2014.3934%204.56133%2014.5213C4.84654%2014.6666%205.21991%2014.6666%205.96665%2014.6666ZM8.83331%2011.6666C8.83331%2011.8507%208.68407%2011.9999%208.49998%2011.9999C8.31588%2011.9999%208.16665%2011.8507%208.16665%2011.6666C8.16665%2011.4825%208.31588%2011.3333%208.49998%2011.3333C8.68407%2011.3333%208.83331%2011.4825%208.83331%2011.6666Z'%20stroke='%237F7F7F'%20stroke-width='1.5'%20stroke-linecap='round'%20stroke-linejoin='round'/%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M14%2014L11.1%2011.1M12.6667%207.33333C12.6667%2010.2789%2010.2789%2012.6667%207.33333%2012.6667C4.38781%2012.6667%202%2010.2789%202%207.33333C2%204.38781%204.38781%202%207.33333%202C10.2789%202%2012.6667%204.38781%2012.6667%207.33333Z'%20stroke='%236B6F76'%20stroke-width='1.5'%20stroke-linecap='round'%20stroke-linejoin='round'/%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M6%202H10M2%204H14M12.6667%204L12.1991%2011.0129C12.129%2012.065%2012.0939%2012.5911%2011.8667%2012.99C11.6666%2013.3412%2011.3648%2013.6235%2011.0011%2013.7998C10.588%2014%2010.0607%2014%209.00623%2014H6.99377C5.93927%2014%205.41202%2014%204.99889%2013.7998C4.63517%2013.6235%204.33339%2013.3412%204.13332%2012.99C3.90607%2012.5911%203.871%2012.065%203.80086%2011.0129L3.33333%204M6.66667%207V10.3333M9.33333%207V10.3333'%20stroke='%236B6F76'%20stroke-width='1.5'%20stroke-linecap='round'%20stroke-linejoin='round'/%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cg%20clip-path='url(%23clip0_2502_823)'%3e%3cpath%20d='M7.99992%205.33334V8M7.99992%2010.6667H8.00659M14.6666%208C14.6666%2011.6819%2011.6818%2014.6667%207.99992%2014.6667C4.31802%2014.6667%201.33325%2011.6819%201.33325%208C1.33325%204.3181%204.31802%201.33334%207.99992%201.33334C11.6818%201.33334%2014.6666%204.3181%2014.6666%208Z'%20stroke='%236B6F76'%20stroke-width='1.5'%20stroke-linecap='round'%20stroke-linejoin='round'/%3e%3c/g%3e%3cdefs%3e%3cclipPath%20id='clip0_2502_823'%3e%3crect%20width='16'%20height='16'%20fill='white'/%3e%3c/clipPath%3e%3c/defs%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M13.6167%204.77308C13.5312%204.83608%2012.0218%205.64397%2012.0218%207.44037C12.0218%209.51818%2013.9425%2010.2533%2014%2010.2715C13.9912%2010.3162%2013.6948%2011.2781%2012.9873%2012.2583C12.3564%2013.1207%2011.6976%2013.9818%2010.6952%2013.9818C9.69291%2013.9818%209.43498%2013.4287%208.27784%2013.4287C7.15021%2013.4287%206.74928%2014%205.83245%2014C4.9156%2014%204.27588%2013.2019%203.54034%2012.2218C2.68836%2011.0709%202%209.28291%202%207.58597C2%204.86409%203.86316%203.42054%205.69684%203.42054C6.67116%203.42054%207.48335%204.02821%208.09508%204.02821C8.67726%204.02821%209.58531%203.38414%2010.6937%203.38414C11.1139%203.38414%2012.6233%203.42054%2013.6167%204.77308ZM10.1676%202.23182C10.6259%201.71517%2010.9503%200.998298%2010.9503%200.281428C10.9503%200.182018%2010.9414%200.0812084%2010.9223%200C10.1764%200.0266027%209.28899%200.471848%208.75398%201.0613C8.33385%201.51495%207.94176%202.23182%207.94176%202.95849C7.94176%203.06771%207.96092%203.17691%207.9698%203.21192C8.01697%203.22032%208.09361%203.23012%208.17025%203.23012C8.83946%203.23012%209.68112%202.80448%2010.1676%202.23182Z'%20fill='black'/%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M5.14981%207.46537C4.94085%207.24181%204.61205%207.2541%204.47223%207.54219L1.03899%2014.4048C1.00767%2014.4674%200.992879%2014.5369%200.996019%2014.6068C0.999159%2014.6768%201.02013%2014.7447%201.05693%2014.8042C1.09373%2014.8637%201.14514%2014.9128%201.20627%2014.9469C1.26741%2014.9809%201.33623%2014.9987%201.4062%2014.9987H6.18693C6.26393%2015.0002%206.33969%2014.9792%206.40492%2014.9382C6.47014%2014.8973%206.52201%2014.8382%206.55414%2014.7682C7.58512%2012.641%206.96054%209.39978%205.14981%207.46537Z'%20fill='url(%23paint0_linear_2502_832)'/%3e%3cpath%20d='M7.66883%201.22039C5.74824%204.2626%205.875%207.63208%207.14029%2010.1611L9.44499%2014.7705C9.47857%2014.8394%209.53076%2014.8975%209.59567%2014.9382C9.66057%2014.979%209.73558%2015.0007%209.81221%2015.001H14.5929C14.6629%2015.001%2014.7317%2014.9832%2014.7929%2014.9492C14.854%2014.9151%2014.9054%2014.866%2014.9422%2014.8065C14.979%2014.747%2015%2014.6791%2015.0031%2014.6092C15.0063%2014.5393%2014.9915%2014.4697%2014.9601%2014.4071C14.9601%2014.4071%208.52849%201.53844%208.37023%201.21808C8.22196%200.929997%207.85474%200.923851%207.66883%201.22039Z'%20fill='%232681FF'/%3e%3cdefs%3e%3clinearGradient%20id='paint0_linear_2502_832'%20x1='7.03199'%20y1='8.52553'%20x2='3.40822'%20y2='14.802'%20gradientUnits='userSpaceOnUse'%3e%3cstop%20stop-color='%230052CC'/%3e%3cstop%20offset='0.92'%20stop-color='%232684FF'/%3e%3c/linearGradient%3e%3c/defs%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cg%20clip-path='url(%23clip0_2502_831)'%3e%3cpath%20d='M0.519254%200.768994C0.44444%200.768029%200.370321%200.783452%200.302102%200.814182C0.233882%200.84491%200.173216%200.890198%200.124362%200.94687C0.0755086%201.00354%200.0396522%201.07021%200.0193102%201.14222C-0.00103186%201.21422%20-0.00536625%201.28981%200.00661131%201.36366L2.18278%2014.5745C2.2099%2014.7362%202.2931%2014.883%202.41779%2014.9894C2.54249%2015.0959%202.70068%2015.155%202.8646%2015.1563H13.3046C13.4274%2015.1579%2013.5468%2015.1153%2013.6409%2015.0362C13.735%2014.9572%2013.7976%2014.847%2013.8172%2014.7257L15.9934%201.36622C16.0054%201.29237%2016.001%201.21678%2015.9807%201.14478C15.9603%201.07278%2015.9245%201.0061%2015.8756%200.94943C15.8268%200.892766%2015.7661%200.84747%2015.6979%200.816742C15.6297%200.786016%2015.5556%200.770592%2015.4807%200.771557L0.519254%200.768994ZM9.68272%2010.317H6.35057L5.44832%205.60322H10.4902L9.68272%2010.317Z'%20fill='%232684FF'/%3e%3cpath%20d='M15.3013%205.60321H10.4902L9.68272%2010.3169H6.35055L2.41602%2014.9871C2.54072%2015.0949%202.69972%2015.1549%202.86458%2015.1563H13.3071C13.43%2015.1579%2013.5494%2015.1153%2013.6434%2015.0362C13.7375%2014.9572%2013.8001%2014.847%2013.8198%2014.7257L15.3013%205.60321Z'%20fill='url(%23paint0_linear_2502_831)'/%3e%3c/g%3e%3cdefs%3e%3clinearGradient%20id='paint0_linear_2502_831'%20x1='16.4138'%20y1='6.92327'%20x2='8.46264'%20y2='13.1288'%20gradientUnits='userSpaceOnUse'%3e%3cstop%20offset='0.18'%20stop-color='%230052CC'/%3e%3cstop%20offset='1'%20stop-color='%232684FF'/%3e%3c/linearGradient%3e%3cclipPath%20id='clip0_2502_831'%3e%3crect%20width='16'%20height='16'%20fill='white'/%3e%3c/clipPath%3e%3c/defs%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cg%20clip-path='url(%23clip0_2502_836)'%3e%3cpath%20d='M13.5535%202.79193C12.5178%202.30734%2011.4104%201.95517%2010.2526%201.75464C10.1104%202.01171%209.94432%202.35748%209.82976%202.63254C8.59904%202.44745%207.37956%202.44745%206.17144%202.63254C6.05693%202.35748%205.88704%202.01171%205.74358%201.75464C4.58454%201.95517%203.47584%202.30864%202.44013%202.79449C0.351095%205.95129%20-0.215207%209.02968%200.0679444%2012.0644C1.4535%2013.099%202.79627%2013.7276%204.11638%2014.139C4.44233%2013.6903%204.73302%2013.2134%204.98345%2012.7109C4.5065%2012.5297%204.04969%2012.306%203.61805%2012.0464C3.73256%2011.9615%203.84457%2011.8729%203.95278%2011.7816C6.58546%2013.013%209.44592%2013.013%2012.0471%2011.7816C12.1566%2011.8729%2012.2686%2011.9615%2012.3819%2012.0464C11.949%2012.3073%2011.491%2012.531%2011.014%2012.7122C11.2644%2013.2134%2011.5538%2013.6916%2011.881%2014.1402C13.2024%2013.7289%2014.5464%2013.1004%2015.932%2012.0644C16.2642%208.5464%2015.3645%205.49628%2013.5535%202.79193ZM5.34212%2010.1981C4.55182%2010.1981%203.9037%209.46024%203.9037%208.56184C3.9037%207.66337%204.53798%206.92429%205.34212%206.92429C6.14628%206.92429%206.79438%207.66207%206.78054%208.56184C6.78178%209.46024%206.14628%2010.1981%205.34212%2010.1981ZM10.6578%2010.1981C9.86752%2010.1981%209.21944%209.46024%209.21944%208.56184C9.21944%207.66337%209.85368%206.92429%2010.6578%206.92429C11.462%206.92429%2012.1101%207.66207%2012.0962%208.56184C12.0962%209.46024%2011.462%2010.1981%2010.6578%2010.1981Z'%20fill='%235865F2'/%3e%3c/g%3e%3cdefs%3e%3cclipPath%20id='clip0_2502_836'%3e%3crect%20width='16'%20height='16'%20fill='white'/%3e%3c/clipPath%3e%3c/defs%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M8.01032%204.15504L4.00518%206.71006L8.01032%209.26513L4.00518%2011.8201L0%209.25129L4.00518%206.69625L0%204.15504L4.00518%201.60001L8.01032%204.15504ZM3.98446%2012.6418L7.98964%2010.0868L11.9948%2012.6418L7.98964%2015.1969L3.98446%2012.6418ZM8.01032%209.25129L12.0155%206.69625L8.01032%204.15504L11.9948%201.60001L16%204.15504L11.9948%206.71006L16%209.26513L11.9948%2011.8201L8.01032%209.25129Z'%20fill='%230061FF'/%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M8%2015C11.866%2015%2015%2011.866%2015%207.99997C15%204.13401%2011.866%201%208%201C4.134%201%201%204.13401%201%207.99997C1%2011.866%204.134%2015%208%2015Z'%20fill='%231977F3'/%3e%3cpath%20d='M10.6065%2010.1416L10.9172%208.16548H8.97241V6.88336C8.97241%206.34321%209.24363%205.81556%2010.1154%205.81556H11V4.1336C11%204.1336%2010.1973%204%209.43%204C7.82844%204%206.78107%204.94574%206.78107%206.65942V8.16548H5V10.1416H6.78107V14.9174C7.13809%2014.9721%207.50398%2015%207.87671%2015C8.24951%2015%208.6154%2014.9712%208.97241%2014.9174V10.1416H10.6065Z'%20fill='white'/%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20fill-rule='evenodd'%20clip-rule='evenodd'%20d='M7.97914%201C4.11986%201%201%204.20833%201%208.17748C1%2011.3502%202.999%2014.0359%205.77214%2014.9864C6.11886%2015.0579%206.24586%2014.832%206.24586%2014.642C6.24586%2014.4756%206.23443%2013.9052%206.23443%2013.311C4.293%2013.7388%203.88871%2012.4554%203.88871%2012.4554C3.57671%2011.6235%203.11443%2011.4097%203.11443%2011.4097C2.479%2010.97%203.16071%2010.97%203.16071%2010.97C3.86557%2011.0176%204.23543%2011.7068%204.23543%2011.7068C4.85929%2012.8%205.86457%2012.4911%206.269%2012.3009C6.32671%2011.8375%206.51171%2011.5166%206.70814%2011.3384C5.15971%2011.172%203.53057%2010.5541%203.53057%207.79715C3.53057%207.01285%203.80771%206.37119%204.24686%205.87215C4.17757%205.69394%203.93486%204.95704%204.31629%203.97077C4.31629%203.97077%204.90557%203.7806%206.23429%204.70752C6.80316%204.55041%207.38982%204.47049%207.97914%204.46981C8.56843%204.46981%209.16914%204.55308%209.72386%204.70752C11.0527%203.7806%2011.642%203.97077%2011.642%203.97077C12.0234%204.95704%2011.7806%205.69394%2011.7113%205.87215C12.162%206.37119%2012.4277%207.01285%2012.4277%207.79715C12.4277%2010.5541%2010.7986%2011.1601%209.23857%2011.3384C9.49286%2011.5642%209.71229%2011.9919%209.71229%2012.6693C9.71229%2013.6318%209.70086%2014.4043%209.70086%2014.6418C9.70086%2014.832%209.828%2015.0579%2010.1746%2014.9866C12.9477%2014.0358%2014.9467%2011.3502%2014.9467%208.17748C14.9581%204.20833%2011.8269%201%207.97914%201Z'%20fill='%2324292F'/%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cg%20clip-path='url(%23clip0_2502_834)'%3e%3cpath%20d='M7.99957%2015.3683L10.9471%206.30157H5.05627L7.99957%2015.3683Z'%20fill='%23E24329'/%3e%3cpath%20d='M0.92752%206.30157L0.0299048%209.05617C-0.0513217%209.30625%200.0363974%209.58242%200.25079%209.73834L7.99948%2015.3683L0.92752%206.30157Z'%20fill='%23FCA326'/%3e%3cpath%20d='M0.92749%206.30164H5.05611L3.27927%200.841173C3.18833%200.561813%202.792%200.561813%202.69779%200.841173L0.92749%206.30164Z'%20fill='%23E24329'/%3e%3cpath%20d='M15.0757%206.30157L15.9701%209.05617C16.0513%209.30625%2015.9636%209.58242%2015.7492%209.73834L7.99939%2015.3683L15.0757%206.30157Z'%20fill='%23FCA326'/%3e%3cpath%20d='M15.0757%206.30164H10.947L12.7206%200.841173C12.8116%200.561813%2013.2079%200.561813%2013.3021%200.841173L15.0757%206.30164Z'%20fill='%23E24329'/%3e%3cpath%20d='M7.99939%2015.3683L10.947%206.30157H15.0757L7.99939%2015.3683Z'%20fill='%23FC6D26'/%3e%3cpath%20d='M7.9994%2015.3683L0.92749%206.30157H5.05611L7.9994%2015.3683Z'%20fill='%23FC6D26'/%3e%3c/g%3e%3cdefs%3e%3cclipPath%20id='clip0_2502_834'%3e%3crect%20width='16'%20height='16'%20fill='white'/%3e%3c/clipPath%3e%3c/defs%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20fill-rule='evenodd'%20clip-rule='evenodd'%20d='M14.7%208.15554C14.7%207.57997%2014.6533%207.15997%2014.5523%206.72443H7.97998V9.32218H11.8377C11.76%209.96777%2011.34%2010.94%2010.4066%2011.5933L10.3936%2011.6803L12.4716%2013.2901L12.6155%2013.3045C13.9378%2012.0834%2014.7%2010.2867%2014.7%208.15554Z'%20fill='%234285F4'/%3e%3cpath%20fill-rule='evenodd'%20clip-rule='evenodd'%20d='M7.98022%2015C9.87019%2015%2011.4568%2014.3778%2012.6158%2013.3045L10.4069%2011.5933C9.81576%2012.0055%209.02242%2012.2933%207.98022%2012.2933C6.12911%2012.2933%204.558%2011.0722%203.99793%209.38446L3.91586%209.39143L1.75507%2011.0637L1.72681%2011.1422C2.87791%2013.4289%205.2424%2015%207.98022%2015Z'%20fill='%2334A853'/%3e%3cpath%20fill-rule='evenodd'%20clip-rule='evenodd'%20d='M3.9977%209.38448C3.84994%208.94893%203.76439%208.48223%203.76439%208.00002C3.76439%207.51778%203.8499%207.05111%203.98993%206.61557L3.98602%206.52279L1.79819%204.82367L1.72662%204.85773C1.25218%205.80664%200.97998%206.87219%200.97998%207.99998C0.97998%209.12777%201.25223%2010.1933%201.72662%2011.1422L3.99774%209.38443'%20fill='%23FBBC04'/%3e%3cpath%20fill-rule='evenodd'%20clip-rule='evenodd'%20d='M7.98022%203.70662C9.29466%203.70662%2010.1813%204.27442%2010.6869%204.7489L12.6625%202.82C11.4492%201.69221%209.87019%201%207.98022%201C5.2424%201%202.87795%202.5711%201.72681%204.85776L3.99016%206.6156C4.558%204.92782%206.12911%203.70666%207.98022%203.70666'%20fill='%23EA4335'/%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M11.013%205.51301V3.9479C11.4349%203.74999%2011.7057%203.32811%2011.7083%202.86197V2.82551C11.7083%202.15884%2011.1667%201.61978%2010.5026%201.61978H10.4661C9.79948%201.61978%209.26042%202.15884%209.26042%202.82551V2.86197C9.26302%203.32811%209.53385%203.74999%209.95573%203.9479V5.51301C9.35937%205.60415%208.79948%205.85155%208.33073%206.22915L4.03646%202.8828C4.06771%202.77343%204.08333%202.65884%204.08594%202.54426C4.08594%201.79426%203.47917%201.18488%202.72917%201.18488C1.97917%201.18228%201.36979%201.78905%201.36719%202.53905C1.36719%203.29165%201.97396%203.90103%202.72396%203.90103C2.96094%203.90103%203.1901%203.83593%203.39323%203.71874L7.6224%207.0104C6.84635%208.18488%206.86719%209.71353%207.67448%2010.8672L6.38802%2012.1536C6.28646%2012.1198%206.17708%2012.1042%206.06771%2012.1016C5.45313%2012.1016%204.95313%2012.6016%204.95313%2013.2187C4.95313%2013.8333%205.45313%2014.3333%206.06771%2014.3333C6.6849%2014.3333%207.1849%2013.8333%207.1849%2013.2187C7.18229%2013.1094%207.16406%2013%207.13281%2012.8958L8.40365%2011.625C9.54167%2012.5%2011.1016%2012.5755%2012.3177%2011.8125C13.5339%2011.0521%2014.1484%209.61457%2013.8568%208.20832C13.5651%206.80468%2012.4297%205.72915%2011.013%205.51301ZM10.4844%2010.6641C9.84375%2010.6797%209.24479%2010.3489%208.92187%209.79686C8.59635%209.24478%208.59635%208.56249%208.92187%208.0104C9.24479%207.45832%209.84375%207.12759%2010.4844%207.14322C11.4323%207.17707%2012.1823%207.95572%2012.1823%208.90363C12.1849%209.84895%2011.4349%2010.6276%2010.487%2010.6614'%20fill='%23FF7A59'/%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cmask%20id='mask0_2502_833'%20style='mask-type:luminance'%20maskUnits='userSpaceOnUse'%20x='1'%20y='1'%20width='14'%20height='14'%3e%3cpath%20d='M15%201H1V15H15V1Z'%20fill='white'/%3e%3c/mask%3e%3cg%20mask='url(%23mask0_2502_833)'%3e%3cpath%20d='M1.17156%209.61322C1.14041%209.48043%201.2986%209.39678%201.39505%209.49324L6.50679%2014.6049C6.60323%2014.7014%206.5196%2014.8596%206.38681%2014.8284C3.80721%2014.2233%201.77669%2012.1928%201.17156%209.61322ZM1.00026%207.56447C0.997795%207.60414%201.01271%207.64286%201.0408%207.67096L8.32907%2014.9592C8.35714%2014.9873%208.39585%2015.0022%208.43554%2014.9997C8.7672%2014.9791%209.09263%2014.9353%209.41029%2014.8701C9.51732%2014.8481%209.55449%2014.7166%209.47721%2014.6394L1.36063%206.52279C1.28337%206.44552%201.15187%206.48271%201.12989%206.58974C1.06466%206.90734%201.02092%207.23279%201.00026%207.56447ZM1.58953%205.15876C1.56622%205.21109%201.57809%205.27224%201.6186%205.31276L10.6872%2014.3814C10.7278%2014.4219%2010.7889%2014.4338%2010.8412%2014.4105C11.0913%2014.2991%2011.3336%2014.1735%2011.5672%2014.0347C11.6445%2013.9888%2011.6565%2013.8826%2011.5929%2013.819L2.18099%204.40714C2.11742%204.34356%202.01121%204.35549%201.96529%204.43279C1.8265%204.66636%201.70091%204.9087%201.58953%205.15876ZM2.77222%203.53036C2.7204%203.47855%202.7172%203.39544%202.76602%203.34079C4.04913%201.9043%205.9156%201%207.99327%201C11.863%201%2015%204.13702%2015%208.00672C15%2010.0844%2014.0957%2011.9509%2012.6592%2013.234C12.6046%2013.2828%2012.5214%2013.2796%2012.4696%2013.2278L2.77222%203.53036Z'%20fill='url(%23paint0_linear_2502_833)'/%3e%3c/g%3e%3cdefs%3e%3clinearGradient%20id='paint0_linear_2502_833'%20x1='8'%20y1='1'%20x2='8'%20y2='15'%20gradientUnits='userSpaceOnUse'%3e%3cstop%20stop-color='%235C6BF1'/%3e%3cstop%20offset='1'%20stop-color='%23283188'/%3e%3c/linearGradient%3e%3c/defs%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M12.9289%2012.9289H10.8545V9.68033C10.8545%208.90563%2010.8407%207.90839%209.77562%207.90839C8.69517%207.90839%208.52983%208.7524%208.52983%209.62391V12.9287H6.45547V6.24817H8.44688V7.16113H8.47481C8.88025%206.46785%209.63695%206.05224%2010.4396%206.08204C12.5421%206.08204%2012.9297%207.46497%2012.9297%209.2641L12.9289%2012.9289ZM4.11485%205.33497C3.45446%205.33497%202.91079%204.79161%202.91079%204.1312C2.91079%203.47081%203.45421%202.92738%204.1146%202.92738C4.77493%202.92738%205.31829%203.47068%205.31841%204.13096C5.31841%204.79123%204.77512%205.33491%204.11485%205.33497ZM5.15203%2012.9289H3.07549V6.24817H5.15203V12.9289ZM13.963%201.00097H2.03305C1.47303%200.994641%201.00683%201.45002%201%202.01004V13.9897C1.00658%2014.55%201.47272%2015.0059%202.03305%2014.9999H13.963C14.5247%2015.007%2014.9925%2014.5511%2015%2013.9897V2.00923C14.9925%201.44802%2014.5241%200.992699%2013.963%201.00009V1.00097Z'%20fill='%230A66C2'/%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M1%201H15V15H1V1Z'%20fill='%23F3F3F3'/%3e%3cpath%20d='M2%202H8V8H2V2Z'%20fill='%23F35325'/%3e%3cpath%20d='M8%202H14V8H8V2Z'%20fill='%2381BC06'/%3e%3cpath%20d='M2%208H8V14H2V8Z'%20fill='%2305A6F0'/%3e%3cpath%20d='M8%208H14V14H8V8Z'%20fill='%23FFBA08'/%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M2.33281%201.60396L10.0795%201.03183C11.031%200.95016%2011.2756%201.00523%2011.8738%201.44016L14.3467%203.18223C14.7546%203.48183%2014.8904%203.5635%2014.8904%203.8897V13.4438C14.8904%2014.0425%2014.6729%2014.3967%2013.9118%2014.4509L4.91582%2014.9955C4.34462%2015.0225%204.07255%2014.9409%203.77341%2014.5596L1.95248%2012.1917C1.62581%2011.7559%201.49048%2011.4297%201.49048%2011.0484V2.55596C1.49048%202.06643%201.70795%201.65809%202.33281%201.60396Z'%20fill='white'/%3e%3cpath%20fill-rule='evenodd'%20clip-rule='evenodd'%20d='M10.0795%201.03183L2.33281%201.60396C1.70795%201.65809%201.49048%202.06643%201.49048%202.55596V11.0484C1.49048%2011.4297%201.62581%2011.7559%201.95248%2012.1917L3.77341%2014.5596C4.07255%2014.9409%204.34462%2015.0225%204.91582%2014.9955L13.9118%2014.4509C14.6724%2014.3967%2014.8904%2014.0425%2014.8904%2013.4438V3.8897C14.8904%203.5803%2014.7681%203.49116%2014.4083%203.22703C14.3876%203.21212%2014.3669%203.19718%2014.3462%203.18223L11.8738%201.44016C11.2756%201.00523%2011.031%200.95016%2010.0795%201.03183ZM5.11929%203.73336C4.38475%203.78283%204.21815%203.79403%203.80095%203.45476L2.74021%202.61103C2.63241%202.50183%202.68654%202.36556%202.95814%202.33849L10.4052%201.79436C11.0306%201.73976%2011.3563%201.95769%2011.6008%202.14809L12.8781%203.07349C12.9327%203.10103%2013.0685%203.26389%2012.9052%203.26389L5.21449%203.72683L5.11929%203.73336ZM4.26295%2013.3621V5.25144C4.26295%204.89724%204.37168%204.7339%204.69742%204.70637L13.5305%204.1893C13.8301%204.16223%2013.9654%204.35263%2013.9654%204.70637V12.7629C13.9654%2013.1171%2013.9108%2013.4167%2013.4218%2013.4438L4.96902%2013.9338C4.47995%2013.9609%204.26295%2013.798%204.26295%2013.3621ZM12.607%205.68637C12.6611%205.93137%2012.607%206.17637%2012.362%206.20437L11.9546%206.2851V12.2734C11.6008%2012.4638%2011.2751%2012.5725%2011.003%2012.5725C10.5681%2012.5725%2010.4593%2012.4363%2010.1336%2012.0284L7.46942%207.83677V11.8921L8.31224%2012.083C8.31224%2012.083%208.31224%2012.573%207.63229%2012.573L5.75769%2012.6817C5.70309%2012.5725%205.75769%2012.3005%205.94762%2012.2463L6.43716%2012.1105V6.7485L5.75769%206.69344C5.70309%206.44844%205.83889%206.0947%206.21969%206.06717L8.23104%205.93184L11.003%2010.1776V6.42137L10.2965%206.34017C10.2419%206.0401%2010.4593%205.82217%2010.7309%205.79557L12.607%205.68637Z'%20fill='black'/%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M3.94137%209.84695C3.94137%2010.6564%203.28013%2011.3176%202.47069%2011.3176C1.66124%2011.3176%201%2010.6564%201%209.84695C1%209.03747%201.66124%208.37625%202.47069%208.37625H3.94137V9.84695Z'%20fill='%23E01E5A'/%3e%3cpath%20d='M4.68237%209.84695C4.68237%209.03747%205.34361%208.37625%206.15306%208.37625C6.9625%208.37625%207.62374%209.03747%207.62374%209.84695V13.5293C7.62374%2014.3388%206.9625%2015%206.15306%2015C5.34361%2015%204.68237%2014.3388%204.68237%2013.5293V9.84695Z'%20fill='%23E01E5A'/%3e%3cpath%20d='M6.15306%203.94137C5.34361%203.94137%204.68237%203.28013%204.68237%202.47069C4.68237%201.66124%205.34361%201%206.15306%201C6.9625%201%207.62374%201.66124%207.62374%202.47069V3.94137H6.15306Z'%20fill='%2336C5F0'/%3e%3cpath%20d='M6.15309%204.68237C6.96254%204.68237%207.62378%205.34361%207.62378%206.15306C7.62378%206.9625%206.96254%207.62374%206.15309%207.62374H2.47069C1.66124%207.62374%201%206.9625%201%206.15306C1%205.34361%201.66124%204.68237%202.47069%204.68237H6.15309Z'%20fill='%2336C5F0'/%3e%3cpath%20d='M12.0585%206.15306C12.0585%205.34361%2012.7197%204.68237%2013.5291%204.68237C14.3386%204.68237%2014.9998%205.34361%2014.9998%206.15306C14.9998%206.9625%2014.3386%207.62374%2013.5291%207.62374H12.0585V6.15306Z'%20fill='%232EB67D'/%3e%3cpath%20d='M11.3176%206.15309C11.3176%206.96254%2010.6563%207.62378%209.84685%207.62378C9.03744%207.62378%208.37622%206.96254%208.37622%206.15309V2.47069C8.37622%201.66124%209.03744%201%209.84685%201C10.6563%201%2011.3176%201.66124%2011.3176%202.47069V6.15309Z'%20fill='%232EB67D'/%3e%3cpath%20d='M9.84685%2012.0586C10.6563%2012.0586%2011.3176%2012.7199%2011.3176%2013.5293C11.3176%2014.3388%2010.6563%2015%209.84685%2015C9.03744%2015%208.37622%2014.3388%208.37622%2013.5293V12.0586H9.84685Z'%20fill='%23ECB22E'/%3e%3cpath%20d='M9.84685%2011.3176C9.03744%2011.3176%208.37622%2010.6564%208.37622%209.84695C8.37622%209.03747%209.03744%208.37625%209.84685%208.37625H13.5293C14.3388%208.37625%2015%209.03747%2015%209.84695C15%2010.6564%2014.3388%2011.3176%2013.5293%2011.3176H9.84685Z'%20fill='%23ECB22E'/%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M6.60974%205.91839V5.33278C6.40646%205.30058%206.20114%205.28293%205.99535%205.27998C4.00296%205.27577%202.23902%206.56688%201.64074%208.46732C1.04245%2010.3678%201.74866%2012.4365%203.38415%2013.5744C2.15905%2012.2633%201.81888%2010.3546%202.51559%208.70096C3.21229%207.0473%204.81576%205.95753%206.60974%205.91839Z'%20fill='%2325F4EE'/%3e%3cpath%20d='M6.72004%2012.552C7.834%2012.5505%208.74966%2011.6729%208.79844%2010.56V0.6288H10.6128C10.5758%200.421288%2010.5581%200.210783%2010.56%200H8.07844V9.9216C8.03716%2011.0402%207.11934%2011.9262%206.00004%2011.928C5.66555%2011.9252%205.33652%2011.8429%205.04004%2011.688C5.42976%2012.2279%206.05416%2012.5491%206.72004%2012.552Z'%20fill='%2325F4EE'/%3e%3cpath%20d='M14.0014%203.9984V3.4464C13.3337%203.44663%2012.6808%203.24959%2012.1246%202.88C12.6122%203.44675%2013.271%203.83934%2014.0014%203.9984Z'%20fill='%2325F4EE'/%3e%3cpath%20d='M12.125%202.87999C11.5772%202.25615%2011.2752%201.45422%2011.2754%200.623993H10.613C10.786%201.55168%2011.3327%202.36746%2012.125%202.87999Z'%20fill='%23FE2C55'/%3e%3cpath%20d='M5.99519%207.7616C5.03925%207.76652%204.20933%208.42142%203.98229%209.34998C3.75525%2010.2786%204.18936%2011.2426%205.03519%2011.688C4.57688%2011.0552%204.51214%2010.219%204.86761%209.5232C5.22308%208.82744%205.9387%208.3898%206.71999%208.3904C6.92831%208.39298%207.13519%208.42532%207.33439%208.4864V5.9616C7.13099%205.93112%206.92567%205.91509%206.71999%205.9136H6.60959V7.8336C6.40937%207.7799%206.20243%207.75566%205.99519%207.7616Z'%20fill='%23FE2C55'/%3e%3cpath%20d='M14.0015%203.99841V5.91841C12.7654%205.91603%2011.5613%205.52475%2010.5599%204.80001V9.84481C10.5546%2012.3621%208.51245%2014.4%205.99511%2014.4C5.06025%2014.4017%204.1479%2014.1132%203.38391%2013.5744C4.6589%2014.9457%206.64315%2015.3971%208.38585%2014.7123C10.1285%2014.0275%2011.2747%2012.346%2011.2751%2010.4736V5.44321C12.2799%206.16321%2013.4854%206.54937%2014.7215%206.54721V4.07521C14.4795%204.07445%2014.2382%204.04871%2014.0015%203.99841Z'%20fill='%23FE2C55'/%3e%3cpath%20d='M10.56%209.8448V4.79999C11.5645%205.52056%2012.7702%205.9068%2014.0064%205.90399V3.98399C13.2761%203.82977%2012.6157%203.4423%2012.1248%202.87999C11.3324%202.36746%2010.7857%201.55168%2010.6128%200.623993H8.7984V10.56C8.7621%2011.4464%208.16834%2012.2126%207.31904%2012.4691C6.46968%2012.7255%205.55115%2012.4159%205.03038%2011.6976C4.18454%2011.2522%203.75043%2010.2882%203.97747%209.35958C4.20452%208.43102%205.03444%207.77612%205.99038%207.7712C6.19878%207.77306%206.40578%207.8054%206.6048%207.8672V5.94719C4.80073%205.97776%203.18515%207.07136%202.48647%208.73486C1.78778%2010.3984%202.13799%2012.3176%203.37918%2013.6272C4.1507%2014.1482%205.06437%2014.4181%205.99518%2014.4C8.5125%2014.4%2010.5547%2012.3621%2010.56%209.8448Z'%20fill='black'/%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M14%207.94593L11.75%2010.1081H9.5L7.53124%2012V10.1081H5V2H14V7.94593Z'%20fill='white'/%3e%3cpath%20d='M4.70834%201L2%203.67857V13.3215H5.25V16L7.95833%2013.3215H10.125L15%208.5V1H4.70834ZM13.9166%207.96428L11.75%2010.1072H9.5833L7.6875%2011.9822V10.1072H5.25V2.07143H13.9166V7.96428Z'%20fill='%239146FF'/%3e%3cpath%20d='M12%204H11V7H12V4Z'%20fill='%239146FF'/%3e%3cpath%20d='M9%204H8V7H9V4Z'%20fill='%239146FF'/%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M9.14163%206.50461L13.6089%201H12.5503L8.67137%205.77958L5.57328%201H2L6.68492%208.22757L2%2014H3.05866L7.15491%208.9526L10.4267%2014H14L9.14137%206.50461H9.14163ZM7.69165%208.29124L7.21697%207.57154L3.44011%201.84479H5.06615L8.11412%206.46646L8.5888%207.18616L12.5508%2013.1936H10.9248L7.69165%208.29152V8.29124Z'%20fill='black'%20stroke='black'%20stroke-width='0.5'/%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cmask%20id='mask0_2502_830'%20style='mask-type:luminance'%20maskUnits='userSpaceOnUse'%20x='1'%20y='1'%20width='14'%20height='14'%3e%3cpath%20d='M15%201H1V15H15V1Z'%20fill='white'/%3e%3c/mask%3e%3cg%20mask='url(%23mask0_2502_830)'%3e%3cpath%20d='M7.99994%2014.9733C11.8512%2014.9733%2014.9732%2011.8513%2014.9732%207.99997C14.9732%204.14873%2011.8512%201.02667%207.99994%201.02667C4.14867%201.02667%201.02661%204.14873%201.02661%207.99997C1.02661%2011.8513%204.14867%2014.9733%207.99994%2014.9733Z'%20fill='%231AB4D7'/%3e%3cpath%20d='M4.36467%207.97988L5.55473%206.78688C5.59418%206.74667%205.61619%206.69343%205.61619%206.63697C5.61619%206.5193%205.52054%206.42374%205.40287%206.42374C5.34555%206.42374%205.29181%206.44621%205.2513%206.48723L4.06231%207.67564L2.86801%206.48544C2.82765%206.44566%202.77418%206.42374%202.71748%206.42374C2.59995%206.42374%202.50427%206.51925%202.50427%206.6368C2.50427%206.69415%202.52716%206.74796%202.56825%206.7885L3.75814%207.97822L2.56887%209.16973C2.52707%209.21089%202.50427%209.26479%202.50427%209.3224C2.50427%209.44007%202.59995%209.53548%202.71748%209.53548C2.77428%209.53548%202.8278%209.51343%202.86801%209.47325L4.06046%208.28241L5.24838%209.46891C5.29051%209.51245%205.34487%209.53562%205.40287%209.53562C5.52042%209.53562%205.61608%209.44007%205.61608%209.3224C5.61608%209.26563%205.59409%209.21229%205.55406%209.17211L4.36467%207.97988Z'%20fill='white'/%3e%3cpath%20d='M11.4393%207.97953C11.4393%208.19316%2011.6131%208.36697%2011.827%208.36697C12.0404%208.36697%2012.2142%208.19316%2012.2142%207.97953C12.2142%207.76582%2012.0404%207.59204%2011.827%207.59204C11.6131%207.59204%2011.4393%207.76582%2011.4393%207.97953Z'%20fill='white'/%3e%3cpath%20d='M10.7045%207.97969C10.7045%207.36096%2011.2078%206.85753%2011.8266%206.85753C12.4451%206.85753%2012.9485%207.36096%2012.9485%207.97969C12.9485%208.59828%2012.4451%209.10151%2011.8266%209.10151C11.2078%209.10151%2010.7045%208.59828%2010.7045%207.97969ZM10.2631%207.97969C10.2631%208.84167%2010.9645%209.543%2011.8266%209.543C12.6887%209.543%2013.3905%208.84167%2013.3905%207.97969C13.3905%207.11757%2012.6887%206.41608%2011.8266%206.41608C10.9645%206.41608%2010.2631%207.11757%2010.2631%207.97969Z'%20fill='white'/%3e%3cpath%20d='M10.152%206.44279L10.0864%206.4426C9.88947%206.4426%209.69956%206.50471%209.54094%206.62696C9.52001%206.5313%209.43447%206.45933%209.33269%206.45933C9.21544%206.45933%209.1215%206.55325%209.12122%206.67071L9.12192%209.3041C9.12227%209.42135%209.21789%209.51662%209.33514%209.51662C9.45246%209.51662%209.54808%209.42135%209.54836%209.30382L9.54843%207.68463C9.54843%207.14496%209.59778%206.927%2010.0601%206.86923C10.1028%206.86392%2010.1494%206.86475%2010.1494%206.86475C10.276%206.86041%2010.3659%206.77348%2010.3659%206.656C10.3659%206.53844%2010.2699%206.44279%2010.152%206.44279Z'%20fill='white'/%3e%3cpath%20d='M6.05791%207.72227C6.05791%207.71643%206.05836%207.71035%206.05864%207.70435C6.18243%207.215%206.62563%206.85287%207.15344%206.85287C7.68764%206.85287%208.13489%207.2239%208.25235%207.72227H6.05791ZM8.689%207.682C8.59709%207.24697%208.35895%206.88964%207.99626%206.66016C7.46613%206.32358%206.76607%206.3422%206.25401%206.70635C5.83632%207.00349%205.59521%207.48958%205.59521%207.9903C5.59521%208.11586%205.61035%208.24256%205.64186%208.3673C5.79957%208.98778%206.33294%209.45741%206.96885%209.53525C7.15754%209.55814%207.34122%209.54715%207.53141%209.49794C7.69485%209.45818%207.85299%209.39189%207.99871%209.29851C8.14993%209.20128%208.27628%209.07304%208.39864%208.9196C8.40116%208.9168%208.40361%208.91428%208.40613%208.91134C8.49104%208.80599%208.47529%208.65619%208.38198%208.58465C8.30323%208.52438%208.17107%208.49988%208.06712%208.63309C8.04472%208.66487%208.0198%208.69763%207.99238%208.73039C7.90969%208.82181%207.80712%208.91029%207.6842%208.97896C7.52779%209.06254%207.34955%209.11028%207.16006%209.11133C6.53986%209.1044%206.20799%208.67152%206.08993%208.36254C6.06932%208.30479%206.05342%208.24494%206.04234%208.18334C6.0409%208.17179%206.03983%208.16066%206.0394%208.15044C6.16763%208.15044%208.26501%208.15009%208.26501%208.15009C8.57014%208.14365%208.73436%207.92828%208.689%207.682Z'%20fill='white'/%3e%3c/g%3e%3c/svg%3e\"","import type { CSSProperties } from 'react';\nimport { cn } from '@/utils';\nimport { CountryFlag } from '../country-flag';\nimport '@/styles/index.css';\nimport './style.css';\n\nimport browserChrome from '@/assets/icons/general/browser-chrome.svg';\nimport caretDown from '@/assets/icons/general/caret-down.svg';\nimport check from '@/assets/icons/general/check.svg';\nimport close from '@/assets/icons/general/close.svg';\nimport dotsVertical from '@/assets/icons/general/dots-vertical.svg';\nimport edit from '@/assets/icons/general/edit.svg';\nimport eyeOff from '@/assets/icons/general/eye-off.svg';\nimport eyeOn from '@/assets/icons/general/eye-on.svg';\nimport key from '@/assets/icons/general/key.svg';\nimport label from '@/assets/icons/general/label.svg';\nimport logo from '@/assets/icons/general/logo.svg';\nimport logoRed from '@/assets/icons/general/logo-red.svg';\nimport mail from '@/assets/icons/general/mail.svg';\nimport onePassword from '@/assets/icons/general/one-password.svg';\nimport passkey from '@/assets/icons/general/passkey.svg';\nimport phone from '@/assets/icons/general/phone.svg';\nimport search from '@/assets/icons/general/search.svg';\nimport trash from '@/assets/icons/general/trash.svg';\nimport warning from '@/assets/icons/general/warning.svg';\nimport apple from '@/assets/icons/providers/apple.svg';\nimport atlassian from '@/assets/icons/providers/atlassian.svg';\nimport bitbucket from '@/assets/icons/providers/bitbucket.svg';\nimport discord from '@/assets/icons/providers/discord.svg';\nimport dropbox from '@/assets/icons/providers/dropbox.svg';\nimport facebook from '@/assets/icons/providers/facebook.svg';\nimport github from '@/assets/icons/providers/github.svg';\nimport gitlab from '@/assets/icons/providers/gitlab.svg';\nimport google from '@/assets/icons/providers/google.svg';\nimport hubspot from '@/assets/icons/providers/hubspot.svg';\nimport linear from '@/assets/icons/providers/linear.svg';\nimport linkedin from '@/assets/icons/providers/linkedin.svg';\nimport microsoft from '@/assets/icons/providers/microsoft.svg';\nimport notion from '@/assets/icons/providers/notion.svg';\nimport slack from '@/assets/icons/providers/slack.svg';\nimport tiktok from '@/assets/icons/providers/tiktok.svg';\nimport twitch from '@/assets/icons/providers/twitch.svg';\nimport twitter from '@/assets/icons/providers/twitter.svg';\nimport xero from '@/assets/icons/providers/xero.svg';\n\ntype TIcon = {\n type: 'general' | 'providers' | 'flags';\n id: string;\n size: 'small' | 'medium' | 'big' | 'large';\n className?: string;\n decorative?: boolean;\n matchTextColor?: boolean;\n};\n\ntype IconMaskStyle = CSSProperties & {\n '--passflow-icon-mask': string;\n};\n\nexport const Icon = ({ type, id, size, className = '', decorative = false, matchTextColor = false }: TIcon) => {\n const styles = {\n 'passflow-icon--small': size === 'small',\n 'passflow-icon--medium': size === 'medium',\n 'passflow-icon--big': size === 'big',\n 'passflow-icon--large': size === 'large',\n };\n\n const icons: Record<'providers' | 'general', Record<string, string>> = {\n general: {\n logo,\n 'logo-red': logoRed,\n warning,\n mail,\n edit,\n 'eye-on': eyeOn,\n 'eye-off': eyeOff,\n search,\n 'caret-down': caretDown,\n label,\n close,\n check,\n key,\n phone,\n 'one-password': onePassword,\n 'browser-chrome': browserChrome,\n passkey,\n 'dots-vertical': dotsVertical,\n trash,\n },\n providers: {\n google,\n gitlab,\n apple,\n atlassian,\n bitbucket,\n discord,\n dropbox,\n facebook,\n github,\n hubspot,\n linear,\n linkedin,\n linledin: linkedin,\n microsoft,\n notion,\n slack,\n tiktok,\n twitch,\n twitter,\n xero,\n },\n };\n\n if (matchTextColor && type === 'general') {\n const style: IconMaskStyle = {\n '--passflow-icon-mask': `url(\"${icons.general[id]}\")`,\n };\n\n return (\n <span\n className={cn('passflow-icon passflow-icon--match-text', styles, className)}\n style={style}\n role={decorative ? undefined : 'img'}\n aria-label={decorative ? undefined : id}\n aria-hidden={decorative || undefined}\n />\n );\n }\n\n if (type !== 'flags') {\n return <img className={cn('passflow-icon', styles, className)} src={icons[type][id]} alt={decorative ? '' : id} />;\n }\n\n return (\n <div className={cn('passflow-icon', styles, className)}>\n <CountryFlag iso2={id} />\n </div>\n );\n};\n","/* eslint-disable react/jsx-props-no-spreading */\nimport type { FC, MouseEvent, PropsWithChildren } from 'react';\nimport { useNavigation } from '@/hooks';\nimport '@/styles/index.css';\n\ntype LinkProps = PropsWithChildren<{\n to: string;\n search?: string;\n replace?: boolean;\n className?: string;\n onClick?: (e: MouseEvent<HTMLAnchorElement>) => void;\n}>;\n\nexport const Link: FC<LinkProps> = ({ to, search, replace = false, children, className, onClick, ...props }) => {\n const { navigate } = useNavigation();\n\n const handleClick = (e: MouseEvent<HTMLAnchorElement>) => {\n e.preventDefault();\n\n if (onClick) {\n onClick(e);\n }\n\n navigate({ to, search, replace });\n };\n\n const getHref = (): string => {\n const searchParam = search ? (search.startsWith('?') ? search : `?${search}`) : '';\n return `${to}${searchParam}`;\n };\n\n return (\n <a href={getHref()} onClick={handleClick} className={className} {...props}>\n {children}\n </a>\n );\n};\n","import type { FC, PropsWithChildren } from 'react';\nimport { Icon } from '../icon';\nimport type { LoginScreenNotice as LoginScreenNoticeProps } from './types';\n\nexport const LoginAlert: FC<{ message?: string | null; id?: string }> = ({ message, id }) => {\n if (!message) return null;\n\n return (\n <div id={id} className='passflow-form-error' role='alert'>\n <Icon size='small' id='warning' type='general' className='icon-warning' decorative />\n <span className='passflow-form-error-text'>{message}</span>\n </div>\n );\n};\n\nexport const LoginDivider: FC<{ label: string }> = ({ label }) => (\n <div className='passflow-form-divider' aria-hidden='true'>\n <div className='passflow-form-divider__line-left' />\n <span className='passflow-form-divider__text'>{label}</span>\n <div className='passflow-form-divider__line-right' />\n </div>\n);\n\nexport const LoginActionStack: FC<PropsWithChildren> = ({ children }) => (\n <div className='passflow-login-screen-actions'>{children}</div>\n);\n\nexport const LoginProgress: FC<{ message: string }> = ({ message }) => (\n <div className='passflow-login-screen-status' role='status' aria-live='polite'>\n <div className='passflow-login-screen-spinner passflow-login-screen-spinner--small' aria-hidden='true' />\n <p className='passflow-login-screen-text passflow-login-screen-centered-text'>{message}</p>\n </div>\n);\n\nexport const LoginScreenNotice: FC<LoginScreenNoticeProps> = ({ code, appName, message, codeTestId, appNameTestId }) => (\n <div className='passflow-login-screen-notice' role='note'>\n {code ? (\n <div className='passflow-login-screen-code' data-testid={codeTestId}>\n {code}\n </div>\n ) : null}\n <p className='passflow-login-screen-text passflow-login-screen-centered-text'>\n <span className='passflow-login-screen-app-name' data-testid={appNameTestId}>\n {appName}\n </span>{' '}\n {message}\n </p>\n </div>\n);\n","import type { FC, FormEvent } from 'react';\nimport { useState } from 'react';\nimport { Button } from '../button';\nimport { FieldText } from '../fields/field-text';\nimport { LoginAlert, LoginProgress } from './shared';\nimport type { LoginCodeEntryState } from './types';\n\nexport const LoginCodeEntry: FC<LoginCodeEntryState> = ({\n label = 'Code',\n initialCode = '',\n error,\n busy = false,\n submitLabel = 'Continue',\n testId,\n onSubmit,\n}) => {\n const [code, setCode] = useState(initialCode);\n\n const handleSubmit = (event: FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n const normalizedCode = code.trim();\n if (normalizedCode) onSubmit(normalizedCode);\n };\n\n return (\n <form className='passflow-form' data-testid={testId} aria-busy={busy} onSubmit={handleSubmit}>\n <div className='passflow-form-container'>\n <div className='passflow-form-field'>\n <div className='passflow-form-field__header'>\n <label htmlFor='device-user-code' className='passflow-field-label'>\n {label}\n </label>\n </div>\n <FieldText\n id='device-user-code'\n name='user_code'\n type='text'\n autoCapitalize='characters'\n autoComplete='off'\n autoCorrect='off'\n spellCheck={false}\n inputMode='text'\n className='passflow-login-screen-code-input'\n value={code}\n disabled={busy}\n aria-invalid={Boolean(error)}\n aria-describedby={error ? 'device-user-code-error' : undefined}\n isError={Boolean(error)}\n onChange={(event) => setCode(event.target.value)}\n />\n </div>\n <LoginAlert id='device-user-code-error' message={error} />\n </div>\n {busy ? <LoginProgress message='Checking the code…' /> : null}\n <Button size='big' variant='primary' type='submit' disabled={busy || code.trim().length === 0}>\n {busy ? 'Checking…' : submitLabel}\n </Button>\n </form>\n );\n};\n","import { type ChangeEvent, type FC, useId } from 'react';\nimport { cn } from '@/utils';\n\ntype TSwitch = {\n label: string;\n checked: boolean;\n disabled?: boolean;\n /**\n * Overrides the generated input id. Only needed when something outside this\n * component has to point at the input (`aria-describedby`, a test hook, a\n * label rendered elsewhere).\n *\n * The default is a `useId()` value rather than a constant, because a constant\n * breaks the moment a screen renders more than one Switch: duplicate DOM ids\n * are invalid, and every `<label htmlFor>` would resolve to the FIRST input,\n * so clicking row three would toggle row one. The consent screen renders one\n * Switch per requested scope, so this is load-bearing, not hygiene.\n */\n id?: string;\n onChange: (event: ChangeEvent<HTMLInputElement>) => void;\n};\n\nexport const Switch: FC<TSwitch> = ({ label, checked, disabled = false, id, onChange }) => {\n const generatedId = useId();\n const inputId = id ?? generatedId;\n\n return (\n <label className={cn('passflow-switch-wrapper', { 'passflow-switch-wrapper--disabled': disabled })} htmlFor={inputId}>\n <span className='passflow-switch-label'>{label}</span>\n <input\n id={inputId}\n type='checkbox'\n className='passflow-switch-input'\n checked={checked}\n disabled={disabled}\n onChange={onChange}\n />\n <div className='passflow-switch-track' />\n </label>\n );\n};\n","import type { FC } from 'react';\nimport { Button } from '../button';\nimport { Switch } from '../switch';\nimport { LoginAlert, LoginProgress, LoginScreenNotice } from './shared';\nimport type { LoginConsentState } from './types';\n\n/**\n * The OIDC consent screen: which scopes an application is asking for, and the\n * two decisions a user can make about them.\n *\n * Every scope starts granted and can be switched off individually — the Allow\n * button submits the subset that is still on, so \"Allow\" never grants more than\n * what is visible on screen. Deny is a peer of Allow, not a hidden link: a\n * consent screen where refusing is harder than accepting is a dark pattern.\n * For the same reason neither button takes initial focus: a bare Enter on a\n * freshly loaded screen must not grant every requested scope.\n */\nexport const LoginConsent: FC<LoginConsentState> = ({\n appName,\n scopes,\n prompt = 'wants to access your account.',\n busy = false,\n error,\n allowLabel = 'Allow',\n denyLabel = 'Deny',\n busyLabel = 'Submitting…',\n testId,\n allowTestId,\n denyTestId,\n appNameTestId,\n onToggleScope,\n onAllow,\n onDeny,\n}) => (\n <div className='passflow-form' data-testid={testId} aria-busy={busy}>\n <LoginScreenNotice appName={appName} message={prompt} appNameTestId={appNameTestId} />\n\n <div className='passflow-form-container'>\n <LoginAlert message={error} />\n\n {scopes.length ? (\n <ul className='passflow-consent-scopes'>\n {scopes.map((item) => (\n <li key={item.scope} className='passflow-consent-scope' data-testid={`consent-scope-${item.scope}`}>\n <Switch label={item.label} checked={item.granted} disabled={busy} onChange={() => onToggleScope(item.scope)} />\n {item.description ? <p className='passflow-consent-scope-description'>{item.description}</p> : null}\n </li>\n ))}\n </ul>\n ) : (\n <p className='passflow-login-screen-hint'>This application is not requesting access to any of your data.</p>\n )}\n </div>\n\n {busy ? <LoginProgress message={busyLabel} /> : null}\n\n <div className='passflow-consent-actions'>\n <Button size='big' variant='primary' type='button' data-testid={allowTestId} disabled={busy} onClick={onAllow}>\n {allowLabel}\n </Button>\n <Button size='big' variant='outlined' type='button' data-testid={denyTestId} disabled={busy} onClick={onDeny}>\n {denyLabel}\n </Button>\n </div>\n </div>\n);\n","import type { FC } from 'react';\nimport { Button } from '../button';\nimport { Icon } from '../icon';\nimport '@/styles/index.css';\nimport type { Providers } from '@passflow/core';\nimport { cn } from '@/utils';\n\ntype TProvidersBox = {\n providers: Providers[];\n onClick: (provider: Providers) => void;\n className?: string;\n};\n\nexport const ProvidersBox: FC<TProvidersBox> = ({ providers, onClick, className = '' }) => {\n const styles = {\n 'passflow-providers-box--grid': providers.length > 1,\n };\n\n return (\n <div className={cn('passflow-providers-box', styles, className)}>\n {providers.map((provider) => (\n <Button\n onClick={() => onClick(provider)}\n size='big'\n variant='provider'\n type='button'\n key={provider}\n withIcon\n className='passflow-provider-item'\n >\n <Icon size='small' type='providers' id={provider} decorative={providers.length <= 2} />\n {providers.length <= 2 && <p className='passflow-provider-text'>{provider}</p>}\n </Button>\n ))}\n </div>\n );\n};\n","import { phone } from 'phone';\nimport type { FC } from 'react';\nimport { useEffect, useRef, useState } from 'react';\nimport { Controller, useForm } from 'react-hook-form';\nimport type { DefaultMethod } from '@/types';\nimport { cn, emailRegex, passwordValidation } from '@/utils';\nimport { Button } from '../button';\nimport { FieldPassword } from '../fields/field-password';\nimport { FieldPhone } from '../fields/field-phone';\nimport { FieldText } from '../fields/field-text';\nimport { Icon } from '../icon';\nimport { Link } from '../link';\nimport { ProvidersBox } from '../providers-box';\nimport { Switch } from '../switch';\nimport { LoginActionStack, LoginAlert, LoginDivider, LoginProgress, LoginScreenNotice } from './shared';\nimport type { LoginCredentialsState, LoginCredentialsValues } from './types';\n\ntype LoginFormValues = {\n email_or_username: string;\n phone: string;\n password: string;\n};\n\nconst initialValues: LoginFormValues = {\n email_or_username: '',\n phone: '',\n password: '',\n};\n\nconst getDefaultMethod = (state: LoginCredentialsState): DefaultMethod | null => {\n if (state.initialMethod !== undefined && state.methods.identities.some((method) => method.id === state.initialMethod)) {\n return state.initialMethod;\n }\n return state.methods.identities[0]?.id ?? null;\n};\n\nexport const LoginCredentials: FC<LoginCredentialsState> = (state) => {\n const { methods } = state;\n const computedDefaultMethod = getDefaultMethod(state);\n const [defaultMethod, setDefaultMethod] = useState<DefaultMethod | null>(computedDefaultMethod);\n const [passkeyOnly, setPasskeyOnly] = useState(Boolean(state.forcePasskey));\n const previousComputedMethod = useRef(computedDefaultMethod);\n const previousForcePasskey = useRef(Boolean(state.forcePasskey));\n const {\n control,\n getValues,\n reset,\n trigger,\n watch,\n formState: { errors, isDirty, isValid },\n handleSubmit,\n } = useForm<LoginFormValues>({\n defaultValues: initialValues,\n mode: 'onChange',\n });\n\n useEffect(() => {\n if (previousComputedMethod.current === computedDefaultMethod) return;\n previousComputedMethod.current = computedDefaultMethod;\n setDefaultMethod(computedDefaultMethod);\n reset(initialValues);\n }, [computedDefaultMethod, reset]);\n\n useEffect(() => {\n const nextForcePasskey = Boolean(state.forcePasskey);\n if (previousForcePasskey.current === nextForcePasskey) return;\n previousForcePasskey.current = nextForcePasskey;\n setPasskeyOnly(nextForcePasskey);\n }, [state.forcePasskey]);\n\n const currentIdentity = methods.identities.find((method) => method.id === defaultMethod);\n const hasPassword = Boolean(currentIdentity?.password);\n const hasPasswordless = Boolean(currentIdentity?.passwordlessLabel);\n const hasPasskey = methods.passkey;\n const hasIdentity = Boolean(currentIdentity);\n const showCredentialFields = !passkeyOnly && hasIdentity;\n const showStandalonePasskey = hasPasskey && (passkeyOnly || !hasIdentity);\n const hasCredentialActions = hasPassword || hasPasswordless || hasPasskey;\n const controlsDisabled = Boolean(state.busy || state.disabled);\n const errorScope = state.error?.scope;\n const hasIdentityError = errorScope === 'identity' || errorScope === 'credentials';\n const hasPasswordError = errorScope === 'password' || errorScope === 'credentials';\n const isNewPassword = state.credentialPurpose === 'sign-up';\n\n const validatePassword = (value: string) => {\n if (!isNewPassword) return true;\n\n try {\n passwordValidation(state.passwordPolicy).validateSync(value);\n return true;\n } catch (error) {\n const validationError = error as { errors?: string[] };\n return validationError.errors?.join(', ') ?? 'Password does not meet the requirements';\n }\n };\n\n const toCredentials = (values: LoginFormValues): LoginCredentialsValues => ({\n method: defaultMethod,\n emailOrUsername: values.email_or_username,\n phone: values.phone,\n password: values.password,\n });\n\n const handleReset = () => {\n reset(initialValues);\n state.onReset?.();\n };\n\n const handleMethodChange = (method: DefaultMethod) => {\n setDefaultMethod(method);\n handleReset();\n };\n\n const handlePasskeyExperienceChange = (checked: boolean) => {\n setPasskeyOnly(checked);\n handleReset();\n };\n\n const submitCurrentMethod = handleSubmit((values) => {\n if (hasPassword) {\n state.onPassword?.(toCredentials(values));\n return;\n }\n if (hasPasswordless) state.onPasswordless?.(toCredentials(values));\n });\n\n const submitPasswordless = async () => {\n if (!defaultMethod || !state.onPasswordless) return;\n const identityField = defaultMethod === 'phone' ? 'phone' : 'email_or_username';\n if (!(await trigger(identityField))) return;\n state.onPasswordless(toCredentials(getValues()));\n };\n const selectedIdentityValue = defaultMethod === 'phone' ? watch('phone') : watch('email_or_username');\n const alternateIdentity = methods.identities.find((method) => method.id !== defaultMethod);\n\n return (\n <>\n {state.notice ? <LoginScreenNotice {...state.notice} /> : null}\n {state.allowPasskeyToggle && hasPasskey && hasIdentity && (hasPassword || hasPasswordless) ? (\n <div className='passflow-form-switch'>\n <Switch\n label='Passwordless experience'\n checked={passkeyOnly}\n disabled={controlsDisabled}\n onChange={(event) => handlePasskeyExperienceChange(event.target.checked)}\n />\n </div>\n ) : null}\n <form\n className='passflow-form'\n data-testid={state.testId}\n aria-busy={controlsDisabled && Boolean(state.busy)}\n onSubmit={submitCurrentMethod}\n >\n {state.busy ? <LoginProgress message={state.primaryLabel ?? 'Signing in…'} /> : null}\n {showCredentialFields ? (\n <>\n <div className='passflow-form-container'>\n {defaultMethod === 'email_or_username' ? (\n <div className='passflow-form-field'>\n <div className='passflow-form-field__header'>\n <label\n htmlFor='email_or_username'\n className={cn('passflow-field-label', {\n 'passflow-field-label--error': hasIdentityError || Boolean(errors.email_or_username),\n })}\n >\n {currentIdentity?.label}\n </label>\n {alternateIdentity ? (\n <Button\n size='small'\n variant='clean'\n type='button'\n className='passflow-field-label-button'\n disabled={controlsDisabled}\n onClick={() => handleMethodChange(alternateIdentity.id)}\n >\n {alternateIdentity.selectLabel}\n </Button>\n ) : null}\n </div>\n <Controller\n name='email_or_username'\n control={control}\n rules={{\n required: currentIdentity?.requiredMessage ?? 'Identity is required',\n ...(currentIdentity?.format === 'email'\n ? { pattern: { value: emailRegex, message: 'Invalid email' } }\n : undefined),\n }}\n render={({ field }) => (\n <FieldText\n {...field}\n id='email_or_username'\n type={currentIdentity?.format === 'email' ? 'email' : 'text'}\n autoComplete={currentIdentity?.format === 'email' ? 'email' : 'username'}\n aria-invalid={Boolean(errors.email_or_username)}\n aria-describedby={errors.email_or_username ? 'email_or_username-error' : undefined}\n isError={hasIdentityError || Boolean(errors.email_or_username)}\n disabled={controlsDisabled}\n />\n )}\n />\n {errors.email_or_username?.message ? (\n <LoginAlert id='email_or_username-error' message={errors.email_or_username.message} />\n ) : null}\n </div>\n ) : null}\n\n {defaultMethod === 'phone' ? (\n <div className='passflow-form-field'>\n <div className='passflow-form-field__header'>\n <label\n htmlFor='phone'\n className={cn('passflow-field-label', {\n 'passflow-field-label--error': hasIdentityError || Boolean(errors.phone),\n })}\n >\n Phone number\n </label>\n {alternateIdentity ? (\n <Button\n size='small'\n variant='clean'\n type='button'\n className='passflow-field-label-button'\n disabled={controlsDisabled}\n onClick={() => handleMethodChange(alternateIdentity.id)}\n >\n {alternateIdentity.selectLabel}\n </Button>\n ) : null}\n </div>\n <Controller\n name='phone'\n control={control}\n rules={{\n required: 'Phone number is required',\n validate: (value) => phone(value).isValid || 'Invalid phone number',\n }}\n render={({ field }) => (\n <FieldPhone\n id='phone'\n name='phone'\n onChange={field.onChange}\n aria-describedby={errors.phone ? 'phone-error' : undefined}\n isError={hasIdentityError || Boolean(errors.phone)}\n disabled={controlsDisabled}\n ref={null}\n />\n )}\n />\n {errors.phone?.message ? <LoginAlert id='phone-error' message={errors.phone.message} /> : null}\n </div>\n ) : null}\n\n {hasPassword ? (\n <div className='passflow-form-field'>\n <div className='passflow-form-field__header'>\n <label\n htmlFor='password'\n className={cn('passflow-field-label', {\n 'passflow-field-label--error': hasPasswordError || Boolean(errors.password),\n })}\n >\n Password\n </label>\n {state.forgotPassword ? (\n <Link\n to={state.forgotPassword.to}\n search={state.forgotPassword.getSearch?.(defaultMethod)}\n className='passflow-field-label-button'\n >\n Forgot Password?\n </Link>\n ) : null}\n </div>\n <Controller\n name='password'\n control={control}\n rules={{ required: 'Password is required', validate: validatePassword }}\n render={({ field }) => (\n <FieldPassword\n {...field}\n id='password'\n name='password'\n aria-invalid={Boolean(errors.password)}\n aria-describedby={errors.password && !isNewPassword ? 'password-error' : undefined}\n isError={hasPasswordError || Boolean(errors.password)}\n passwordPolicy={state.passwordPolicy}\n withMessages={isNewPassword}\n validationErrors={\n isNewPassword && errors.password?.message ? errors.password.message.split(', ') : undefined\n }\n autoComplete={isNewPassword ? 'new-password' : 'current-password'}\n disabled={controlsDisabled}\n />\n )}\n />\n {!isNewPassword && errors.password?.message ? (\n <LoginAlert id='password-error' message={errors.password.message} />\n ) : null}\n </div>\n ) : null}\n\n <LoginAlert message={state.error?.message} />\n </div>\n\n <LoginActionStack>\n {hasPassword && state.onPassword ? (\n <Button\n size='big'\n variant='primary'\n type='submit'\n disabled={controlsDisabled || !isDirty || !isValid}\n className='passflow-button-signin'\n data-testid={state.primaryTestId}\n >\n {state.primaryLabel ?? 'Sign In'}\n </Button>\n ) : null}\n {hasPasswordless && state.onPasswordless ? (\n <Button\n size='big'\n variant={hasPassword ? 'outlined' : 'primary'}\n type='button'\n className={cn('passflow-button-passwordless', {\n 'passflow-button-passwordless--active': hasPassword,\n })}\n disabled={controlsDisabled || selectedIdentityValue.trim().length === 0}\n onClick={() => void submitPasswordless()}\n >\n {state.passwordlessLabelPrefix ?? 'Sign In with'} {currentIdentity?.passwordlessLabel}\n </Button>\n ) : null}\n {hasPasskey && state.onPasskey ? (\n <Button\n size='big'\n variant='dark'\n type='button'\n className='passflow-button-passkey'\n withIcon\n disabled={controlsDisabled}\n onClick={state.onPasskey}\n >\n <Icon\n id='key'\n size='small'\n type='general'\n className='passflow-button-passkey-icon'\n decorative\n matchTextColor\n />\n {state.passkeyLabel ?? 'Sign In with a Passkey'}\n </Button>\n ) : null}\n </LoginActionStack>\n </>\n ) : null}\n\n {showStandalonePasskey ? (\n <>\n <LoginAlert message={state.error?.message} />\n {state.onPasskey ? (\n <LoginActionStack>\n <Button\n size='big'\n variant='dark'\n type='button'\n className='passflow-button-passkey'\n withIcon\n disabled={controlsDisabled}\n onClick={state.onPasskey}\n >\n <Icon\n id='key'\n size='small'\n type='general'\n className='passflow-button-passkey-icon'\n decorative\n matchTextColor\n />\n {state.passkeyLabel ?? 'Sign In with a Passkey'}\n </Button>\n </LoginActionStack>\n ) : null}\n </>\n ) : null}\n\n {state.footer ? (\n <div className={cn('passflow-form-actions', { 'passflow-form-actions--top-space': hasCredentialActions })}>\n <p className='passflow-dont-have-account'>\n {state.footer.prompt}{' '}\n <Link to={state.footer.to} search={state.footer.search} className='passflow-link'>\n {state.footer.label}\n </Link>\n </p>\n </div>\n ) : null}\n\n {methods.providers.length > 0 && state.onProvider ? (\n <div className='passflow-form-providers'>\n {hasCredentialActions ? <LoginDivider label='Or continue with' /> : null}\n <ProvidersBox providers={methods.providers} onClick={state.onProvider} />\n </div>\n ) : null}\n </form>\n </>\n );\n};\n","import type { FC } from 'react';\nimport { Button } from '../button';\nimport { Icon } from '../icon';\nimport { LoginAlert, LoginProgress, LoginScreenNotice } from './shared';\nimport type { LoginDeviceApprovalState } from './types';\n\nexport const LoginDeviceApproval: FC<LoginDeviceApprovalState> = ({\n appName,\n code,\n identity,\n busy = false,\n error,\n actionLabel = 'Approve this device',\n busyLabel = 'Approving…',\n testId,\n actionTestId,\n codeTestId,\n appNameTestId,\n onApprove,\n}) => (\n <div className='passflow-form' data-testid={testId} aria-busy={busy}>\n <LoginScreenNotice\n code={code}\n appName={appName}\n message='requested this sign-in. Confirm that the code matches your terminal.'\n codeTestId={codeTestId}\n appNameTestId={appNameTestId}\n />\n <div className='passflow-form-container passflow-login-screen-centered'>\n <div className='passflow-login-screen-success' role='status' aria-live='polite'>\n <Icon size='small' id='check' type='general' className='icon-success' decorative />\n <p className='passflow-login-screen-text'>\n {identity ? (\n <>\n Signed in as <strong className='passflow-login-screen-app-name'>{identity}</strong>.\n </>\n ) : (\n 'Signed in successfully.'\n )}\n </p>\n </div>\n <p className='passflow-login-screen-hint'>Approve this request to finish signing in on the device.</p>\n <LoginAlert message={error} />\n </div>\n {busy ? <LoginProgress message={busyLabel} /> : null}\n <Button\n size='big'\n variant='primary'\n type='button'\n autoFocus={!busy}\n data-testid={actionTestId}\n disabled={busy}\n onClick={onApprove}\n >\n {busy ? busyLabel : actionLabel}\n </Button>\n </div>\n);\n","import type { FC } from 'react';\nimport { Button } from '../button';\nimport type { LoginGeneralErrorState } from './types';\n\nexport const LoginGeneralError: FC<LoginGeneralErrorState> = ({\n message,\n detail = 'Go back to start again.',\n actionLabel = 'Go back',\n testId,\n onAction,\n}) => (\n <div className='passflow-error-container' data-testid={testId}>\n <div className='passflow-error-container-text-wrapper' role='alert' aria-live='assertive'>\n {message ? <h1 className='passflow-error-container-text'>{message}</h1> : null}\n <p className='passflow-error-container-text-secondary'>{detail}</p>\n </div>\n <Button size='big' type='button' variant='primary' onClick={onAction} className='passflow-button-go-back-error'>\n {actionLabel}\n </Button>\n </div>\n);\n","import type { FC } from 'react';\nimport { Button } from '../button';\nimport { LoginActionStack, LoginAlert, LoginProgress } from './shared';\nimport type { LoginInvitationState } from './types';\n\nexport const LoginInvitation: FC<LoginInvitationState> = ({\n identity,\n inviterName,\n busy = false,\n error,\n acceptLabel = 'Accept invitation',\n busyLabel = 'Accepting invitation…',\n switchAccountLabel = 'Switch account',\n createAccountLabel = 'Create a new account',\n testId,\n acceptTestId,\n onAccept,\n onSwitchAccount,\n onCreateAccount,\n}) => (\n <div className='passflow-form' data-testid={testId} aria-busy={busy}>\n <div className='passflow-form-container passflow-login-screen-centered'>\n {inviterName ? (\n <p className='passflow-login-screen-text passflow-login-screen-centered-text'>\n <strong className='passflow-login-screen-app-name'>{inviterName}</strong> sent this invitation.\n </p>\n ) : null}\n <p className='passflow-login-screen-text passflow-login-screen-centered-text'>\n {identity ? (\n <>\n You're signed in as <strong className='passflow-login-screen-app-name'>{identity}</strong>.\n </>\n ) : (\n 'You’re already signed in.'\n )}\n </p>\n <p className='passflow-login-screen-hint'>Continue with this account, or switch accounts?</p>\n <LoginAlert message={error} />\n </div>\n {busy ? <LoginProgress message={busyLabel} /> : null}\n <LoginActionStack>\n <Button\n size='big'\n variant='primary'\n type='button'\n autoFocus={!busy}\n data-testid={acceptTestId}\n disabled={busy}\n onClick={onAccept}\n >\n {busy ? busyLabel : acceptLabel}\n </Button>\n <Button size='big' variant='outlined' type='button' disabled={busy} onClick={onSwitchAccount}>\n {switchAccountLabel}\n </Button>\n <Button size='big' variant='clean' type='button' disabled={busy} onClick={onCreateAccount}>\n {createAccountLabel}\n </Button>\n </LoginActionStack>\n </div>\n);\n","import type { FC } from 'react';\nimport { Button } from '../button';\nimport { Icon } from '../icon';\nimport { LoginAlert } from './shared';\nimport type { LoginPasskeyProgressState } from './types';\n\nexport const LoginPasskeyProgress: FC<LoginPasskeyProgressState> = ({\n working,\n message,\n actionLabel = 'Continue with a passkey',\n error,\n recoverable = false,\n retryLabel = 'Try again',\n testId,\n onAction,\n onRetry,\n}) => (\n <div className='passflow-form' data-testid={testId}>\n <div className='passflow-form-container passflow-login-screen-centered'>\n <div className='passflow-login-screen-status' role='status'>\n {working ? <div className='passflow-login-screen-spinner' aria-hidden='true' /> : null}\n <p className='passflow-login-screen-text'>{message}</p>\n </div>\n <LoginAlert message={error} />\n </div>\n {!working && onAction ? (\n <Button size='big' variant='dark' type='button' className='passflow-button-passkey' withIcon onClick={onAction}>\n <Icon id='key' size='small' type='general' className='icon-white passflow-button-passkey-icon' decorative />\n {actionLabel}\n </Button>\n ) : !working && error && recoverable && onRetry ? (\n <Button size='big' variant='dark' type='button' className='passflow-button-passkey' withIcon onClick={onRetry}>\n <Icon id='key' size='small' type='general' className='icon-white passflow-button-passkey-icon' decorative />\n {retryLabel}\n </Button>\n ) : null}\n </div>\n);\n","import type { FC, FormEvent } from 'react';\nimport { useState } from 'react';\nimport { Button } from '../button';\nimport { FieldText } from '../fields/field-text';\nimport { LoginAlert, LoginProgress } from './shared';\nimport type { LoginSecondFactorMethod, LoginSecondFactorState } from './types';\n\n/** The words for each factor, matching the sign-in's own two-factor screens. */\nconst METHOD_COPY: Record<LoginSecondFactorMethod, { label: string; hint: string; switchLabel: string }> = {\n totp: {\n label: 'Authenticator code',\n hint: 'Enter the 6-digit code from your authenticator app.',\n switchLabel: 'Use authenticator app',\n },\n recovery_codes: {\n label: 'Recovery code',\n hint: 'Enter one of your recovery codes.',\n switchLabel: 'Use recovery code',\n },\n};\n\nexport const LoginSecondFactor: FC<LoginSecondFactorState> = ({\n methods,\n identity,\n busy = false,\n error,\n submitLabel = 'Verify',\n testId,\n onSubmit,\n onMethodChange,\n}) => {\n const [method, setMethod] = useState<LoginSecondFactorMethod>(methods[0] ?? 'totp');\n const [code, setCode] = useState('');\n const alternate = methods.find((m) => m !== method);\n const copy = METHOD_COPY[method];\n const isTOTP = method === 'totp';\n\n const handleSubmit = (event: FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n const normalizedCode = code.trim();\n if (normalizedCode) onSubmit(method, normalizedCode);\n };\n\n const switchTo = (next: LoginSecondFactorMethod) => {\n setMethod(next);\n setCode('');\n onMethodChange?.();\n };\n\n return (\n <form className='passflow-form' data-testid={testId} aria-busy={busy} onSubmit={handleSubmit}>\n <div className='passflow-form-container'>\n {identity ? (\n <p className='passflow-login-screen-hint'>\n Signed in as <strong className='passflow-login-screen-app-name'>{identity}</strong>.\n </p>\n ) : null}\n <div className='passflow-form-field'>\n <div className='passflow-form-field__header'>\n <label htmlFor='second-factor-code' className='passflow-field-label'>\n {copy.label}\n </label>\n {alternate ? (\n <Button\n size='small'\n variant='clean'\n type='button'\n className='passflow-field-label-button'\n disabled={busy}\n onClick={() => switchTo(alternate)}\n >\n {METHOD_COPY[alternate].switchLabel}\n </Button>\n ) : null}\n </div>\n <FieldText\n id='second-factor-code'\n name={isTOTP ? 'otp' : 'recovery_code'}\n type='text'\n autoComplete={isTOTP ? 'one-time-code' : 'off'}\n autoCapitalize={isTOTP ? 'off' : 'characters'}\n autoCorrect='off'\n spellCheck={false}\n inputMode={isTOTP ? 'numeric' : 'text'}\n autoFocus\n className='passflow-login-screen-code-input'\n value={code}\n disabled={busy}\n aria-invalid={Boolean(error)}\n aria-describedby={error ? 'second-factor-code-error' : 'second-factor-code-hint'}\n isError={Boolean(error)}\n onChange={(event) => setCode(event.target.value)}\n />\n <p id='second-factor-code-hint' className='passflow-login-screen-hint'>\n {copy.hint}\n </p>\n </div>\n <LoginAlert id='second-factor-code-error' message={error} />\n </div>\n {busy ? <LoginProgress message='Checking the code…' /> : null}\n <Button size='big' variant='primary' type='submit' disabled={busy || code.trim().length === 0}>\n {busy ? 'Checking…' : submitLabel}\n </Button>\n </form>\n );\n};\n","import type { FC, PropsWithChildren } from 'react';\nimport { cn } from '@/utils';\nimport { Icon } from '../icon';\nimport '@/styles/index.css';\nimport './login-screen.css';\n\nexport type LoginScreenShellProps = PropsWithChildren & {\n iconId?: string;\n title?: string;\n subtitle?: string;\n className?: string;\n customCss?: string;\n customLogo?: string;\n customLogoAlt?: string;\n removeBranding?: boolean;\n};\n\nexport const LoginScreenShell: FC<LoginScreenShellProps> = ({\n iconId = 'logo',\n title = '',\n subtitle = '',\n className = '',\n children,\n customCss,\n customLogo,\n customLogoAlt = 'Application logo',\n removeBranding = false,\n}) => (\n <div id='passflow-wrapper' className='passflow-wrapper'>\n {/*\n * The app's custom CSS (login theme `custom_css`), rendered inline as the\n * last layer so it overrides the kit's styles. Only when there is some.\n */}\n {customCss ? (\n <style className='psfw-custom-styles' data-passflow-style-layer='custom'>\n {customCss}\n </style>\n ) : null}\n <main className={cn('passflow-form-main-wrapper', className)}>\n <div className='passflow-form-main-container'>\n {customLogo ? (\n <img src={customLogo} alt={customLogoAlt} className='passflow-form-main-container-logo' />\n ) : (\n <Icon id={iconId} size='large' type='general' decorative />\n )}\n {title ? (\n <div className='passflow-form-header'>\n <h1 className='passflow-form-title'>{title}</h1>\n {subtitle ? <span className='passflow-form-subtitle'>{subtitle}</span> : null}\n </div>\n ) : null}\n </div>\n {children}\n </main>\n {!removeBranding ? (\n <footer className='passflow-branding'>\n <p className='passflow-branding-text'>\n Secured by <span className='passflow-branding-text-secondary passflow-secondary-font'>PASSFLOW</span>\n </p>\n </footer>\n ) : null}\n </div>\n);\n","import type { FC } from 'react';\nimport { Button } from '../button';\nimport { Icon } from '../icon';\nimport { LoginAlert } from './shared';\nimport type { LoginStatusState } from './types';\n\nexport const LoginStatus: FC<LoginStatusState> = ({\n tone,\n message,\n detail,\n recoverable = false,\n retryLabel = 'Try again',\n testId,\n onRetry,\n primaryAction,\n}) => (\n <div className='passflow-form' data-testid={testId}>\n <div className='passflow-form-container passflow-login-screen-centered'>\n {tone === 'success' ? (\n <div className='passflow-login-screen-success' role='status'>\n <Icon size='small' id='check' type='general' className='icon-success' decorative />\n <span className='passflow-login-screen-success-text'>{message}</span>\n </div>\n ) : (\n <LoginAlert message={message} />\n )}\n {detail ? <p className='passflow-login-screen-hint'>{detail}</p> : null}\n </div>\n {primaryAction ? (\n <Button size='big' variant='primary' type='button' onClick={primaryAction.onClick}>\n {primaryAction.label}\n </Button>\n ) : tone === 'error' && recoverable && onRetry ? (\n <Button size='big' variant='primary' type='button' onClick={onRetry}>\n {retryLabel}\n </Button>\n ) : null}\n </div>\n);\n","import type { FC } from 'react';\nimport { LoginCodeEntry } from './code-entry';\nimport { LoginConsent } from './consent';\nimport { LoginCredentials } from './credentials';\nimport { LoginDeviceApproval } from './device-approval';\nimport { LoginGeneralError } from './general-error';\nimport { LoginInvitation } from './invitation';\nimport { LoginPasskeyProgress } from './passkey-progress';\nimport { LoginSecondFactor } from './second-factor';\nimport { LoginScreenShell } from './shell';\nimport { LoginStatus } from './status';\nimport type { LoginScreenProps } from './types';\n\nexport const LoginScreen: FC<LoginScreenProps> = ({ chrome, state }) => {\n const content = (() => {\n switch (state.kind) {\n case 'credentials':\n return <LoginCredentials {...state} />;\n case 'code-entry':\n return <LoginCodeEntry {...state} />;\n case 'passkey-progress':\n return <LoginPasskeyProgress {...state} />;\n case 'device-approval':\n return <LoginDeviceApproval {...state} />;\n case 'second-factor':\n return <LoginSecondFactor {...state} />;\n case 'invitation':\n return <LoginInvitation {...state} />;\n case 'general-error':\n return <LoginGeneralError {...state} />;\n case 'consent':\n return <LoginConsent {...state} />;\n case 'status':\n return <LoginStatus {...state} />;\n }\n })();\n const isError = state.kind === 'general-error' || (state.kind === 'status' && state.tone === 'error');\n const className =\n state.kind === 'general-error'\n ? 'passflow-error-wrapper'\n : chrome.variant === 'sign-in'\n ? 'passflow-signin-wrapper'\n : undefined;\n\n return (\n <LoginScreenShell\n iconId={isError ? 'logo-red' : 'logo'}\n title={chrome.title}\n subtitle={chrome.subtitle}\n className={className}\n customCss={chrome.customCss}\n customLogo={chrome.customLogo}\n customLogoAlt={chrome.customLogoAlt}\n removeBranding={chrome.removeBranding}\n >\n {content}\n </LoginScreenShell>\n );\n};\n","import * as PopoverPrimitive from '@radix-ui/react-popover';\nimport { type ComponentPropsWithoutRef, type ElementRef, forwardRef } from 'react';\nimport { cn } from '@/utils';\n\nconst Popover = PopoverPrimitive.Root;\n\nconst PopoverTrigger = PopoverPrimitive.Trigger;\n\nconst PopoverAnchor = PopoverPrimitive.Anchor;\n\nconst PopoverContent = forwardRef<\n ElementRef<typeof PopoverPrimitive.Content>,\n ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>\n>(({ className, align = 'center', sideOffset = 4, ...props }, ref) => (\n <PopoverPrimitive.Portal>\n <PopoverPrimitive.Content\n ref={ref}\n align={align}\n sideOffset={sideOffset}\n className={cn('passflow-popover-content', className)}\n {...props}\n />\n </PopoverPrimitive.Portal>\n));\nPopoverContent.displayName = PopoverPrimitive.Content.displayName;\n\nexport { Popover, PopoverAnchor, PopoverContent, PopoverTrigger };\n","import type { FC } from 'react';\nimport { cn } from '@/utils';\nimport './spinner.css';\n\nexport type SpinnerSize = 'small' | 'medium';\n\nexport type SpinnerProps = {\n /** `small` sits inline beside a line of text; `medium` stands alone. */\n size?: SpinnerSize;\n /**\n * The accessible name. Omit it when a sibling already announces the busy\n * state — the ring is then decorative and hidden from assistive technology,\n * which is what a status region with its own live text wants.\n */\n label?: string;\n};\n\n/**\n * The indeterminate activity ring.\n *\n * It exists as a primitive so its diameter and stroke live in one place rather\n * than in each consuming component's stylesheet. The upgrade dialog uses it;\n * the login screen still draws its own identical ring in\n * `login-screen.css` and should be migrated onto this when that file is next\n * touched.\n */\nexport const Spinner: FC<SpinnerProps> = ({ size = 'medium', label }) => (\n <span\n className={cn('passflow-spinner', { 'passflow-spinner--small': size === 'small' })}\n role={label === undefined ? undefined : 'status'}\n aria-label={label}\n aria-hidden={label === undefined ? true : undefined}\n />\n);\n","import type { FC } from 'react';\nimport { Button } from '../button';\nimport type { UpgradeDialogFactor, UpgradeFactorType } from './types';\n\ntype UpgradeFactorListProps = {\n factors: readonly UpgradeDialogFactor[];\n selected: UpgradeFactorType;\n disabled?: boolean;\n label?: string;\n onSelect: (factor: UpgradeFactorType) => void;\n};\n\n/**\n * The \"use another way\" alternatives. Selecting one reports the user's choice;\n * it never navigates.\n *\n * Each row is `Button variant='option'`: the two-line geometry and the pressed\n * look belong to that variant in the button library, not to this list. The list\n * contributes layout only.\n */\nexport const UpgradeFactorList: FC<UpgradeFactorListProps> = ({\n factors,\n selected,\n disabled = false,\n label = 'Other verification methods',\n onSelect,\n}) => (\n <ul className='passflow-upgrade-dialog__alternatives' aria-label={label}>\n {factors.map((factor) => (\n <li key={factor.type} className='passflow-upgrade-dialog__alternative'>\n <Button\n size='big'\n variant='option'\n type='button'\n disabled={disabled}\n pressed={factor.type === selected}\n description={factor.hint}\n data-testid={`upgrade-dialog-factor-${factor.type}`}\n onClick={() => onSelect(factor.type)}\n >\n {factor.label}\n </Button>\n </li>\n ))}\n </ul>\n);\n","import { type FC, type FormEvent, useRef, useState } from 'react';\nimport { Button } from '../button';\nimport { FieldText } from '../fields/field-text';\nimport { LoginAlert } from '../login-screen';\nimport { UpgradeFactorList } from './factor-list';\nimport type { UpgradeDialogChallengeState, UpgradeFactorType } from './types';\n\nconst CODE_FIELD_ID = 'passflow-upgrade-code';\nconst CODE_ERROR_ID = 'passflow-upgrade-code-error';\n\n/**\n * The collecting view: the suggested factor, its input affordance, the\n * alternatives toggle, and the two terminal controls.\n *\n * Selection is reported through `onSelectFactor` before `onSubmit` ever fires —\n * architecture §13.2's late-join boundary is factor selection, not submission,\n * so the controller must learn of the choice while the user is still typing.\n */\nexport const UpgradeChallengeView: FC<UpgradeDialogChallengeState> = ({\n factors,\n selected,\n busy = false,\n error,\n showAlternatives = false,\n submitLabel = 'Verify',\n cancelLabel = 'Cancel',\n alternativesLabel = 'Use another way',\n testId,\n onSelectFactor,\n onToggleAlternatives,\n onSubmit,\n onCancel,\n}) => {\n const [code, setCode] = useState('');\n const reported = useRef<UpgradeFactorType | null>(null);\n\n const active = factors.find((factor) => factor.type === selected) ?? factors[0];\n // The code contract travels WITH the factor (§H12): length, charset and\n // autofill are the factor's own statement, never this component's guess. A\n // six-character cap applied to every factor truncated a 12-character recovery\n // code into a guaranteed rejection.\n const codeContract = active?.input === 'code' ? active.code : undefined;\n const needsCode = codeContract !== undefined;\n const hasAlternatives = factors.length > 1;\n\n const report = (factor: UpgradeFactorType) => {\n if (reported.current === factor) return;\n reported.current = factor;\n onSelectFactor(factor);\n };\n\n const choose = (factor: UpgradeFactorType) => {\n setCode('');\n report(factor);\n };\n\n const handleSubmit = (event: FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n if (!active) return;\n const trimmed = code.trim();\n if (needsCode && trimmed.length === 0) return;\n report(active.type);\n onSubmit(needsCode ? trimmed : undefined);\n };\n\n return (\n <form className='passflow-upgrade-dialog__form' data-testid={testId} aria-busy={busy} onSubmit={handleSubmit} noValidate>\n {active ? (\n <div className='passflow-upgrade-dialog__factor'>\n <span className='passflow-upgrade-dialog__factor-label'>{active.label}</span>\n {active.hint ? <span className='passflow-upgrade-dialog__factor-hint'>{active.hint}</span> : null}\n </div>\n ) : null}\n\n {codeContract ? (\n <div className='passflow-upgrade-dialog__field'>\n <label htmlFor={CODE_FIELD_ID} className='passflow-field-label'>\n Verification code\n </label>\n <FieldText\n id={CODE_FIELD_ID}\n name='upgrade_code'\n type='text'\n inputMode={codeContract.inputMode}\n autoComplete={codeContract.autoComplete}\n autoCorrect='off'\n autoCapitalize={codeContract.autoCapitalize}\n spellCheck={false}\n maxLength={codeContract.maxLength}\n value={code}\n disabled={busy}\n isError={Boolean(error)}\n aria-invalid={Boolean(error)}\n aria-describedby={error ? CODE_ERROR_ID : undefined}\n data-testid='upgrade-dialog-code'\n onChange={(event) => setCode(event.target.value)}\n />\n </div>\n ) : null}\n\n <LoginAlert id={CODE_ERROR_ID} message={error} />\n\n <div className='passflow-upgrade-dialog__actions'>\n <Button\n size='big'\n variant='primary'\n type='submit'\n disabled={busy || !active || (needsCode && code.trim().length === 0)}\n data-testid='upgrade-dialog-submit'\n >\n {busy ? 'Verifying…' : submitLabel}\n </Button>\n {hasAlternatives ? (\n <Button\n size='big'\n variant='clean'\n type='button'\n disabled={busy}\n aria-expanded={showAlternatives}\n data-testid='upgrade-dialog-alternatives'\n onClick={onToggleAlternatives}\n >\n {alternativesLabel}\n </Button>\n ) : null}\n {showAlternatives && hasAlternatives ? (\n <UpgradeFactorList factors={factors} selected={selected} disabled={busy} onSelect={choose} />\n ) : null}\n <Button size='big' variant='clean' type='button' data-testid='upgrade-dialog-cancel' onClick={onCancel}>\n {cancelLabel}\n </Button>\n </div>\n </form>\n );\n};\n","/**\n * Pure mapping from the controller's prompt request plus local UI state to the\n * dialog's rendering union. No React, no DOM, no styling — architecture §10.2\n * classifies this as non-visual state mapping, which is why it is the one file\n * in this folder a Vitest spec may cover.\n *\n * The inputs are declared structurally — `UpgradePromptSnapshot` is the shape of\n * `UpgradePromptRequest` that the dialog actually reads — but the one judgement\n * that is NOT structural is which kind of failure an error is: that belongs to\n * `@passflow/core`, which raises the errors, and is imported from it.\n */\n\nimport { classifyUpgradeError, type UpgradeErrorKind } from '@passflow/core';\nimport type {\n AssuranceBar,\n UpgradeDialogFactor,\n UpgradeDialogState,\n UpgradeFactorCodeContract,\n UpgradeFactorInput,\n UpgradeFactorType,\n} from './types';\n\nexport type UpgradeChallengeSnapshot = {\n requiredLevel?: number;\n acrValues?: string;\n maxAge?: number;\n};\n\nexport type UpgradeFactorSnapshot = {\n type: UpgradeFactorType;\n input: UpgradeFactorInput;\n};\n\nexport type UpgradePromptSnapshot = {\n challenge: UpgradeChallengeSnapshot;\n /** Already ranked by `selectFactors`; index 0 is the suggested factor. */\n factors: readonly UpgradeFactorSnapshot[];\n previousError?: unknown;\n};\n\nexport type UpgradeDialogLabels = Partial<Record<UpgradeFactorType, { label: string; hint?: string }>>;\n\n/** How the flight ended, as the controller's outcome summary reports it (§13.4). */\nexport type UpgradeDialogOutcome =\n | { kind: 'elevated' }\n | { kind: 'insufficient'; obtained: AssuranceBar; required: AssuranceBar }\n | { kind: 'cancelled' }\n | { kind: 'failed'; error: unknown };\n\nexport type UpgradeDialogUiState = {\n selected?: UpgradeFactorType | null;\n busy?: boolean;\n showAlternatives?: boolean;\n};\n\nexport type UpgradeDialogHandlers = {\n onSelectFactor: (factor: UpgradeFactorType) => void;\n onToggleAlternatives: () => void;\n onSubmit: (code?: string) => void;\n onCancel: () => void;\n onDismiss: () => void;\n onRetry?: () => void;\n};\n\nexport type ToDialogStateInput = {\n prompt: UpgradePromptSnapshot | null;\n outcome?: UpgradeDialogOutcome;\n ui?: UpgradeDialogUiState;\n labels?: UpgradeDialogLabels;\n handlers: UpgradeDialogHandlers;\n testId?: string;\n};\n\n/**\n * How an elevation failure reads to the user. `rejected` is the retryable\n * wrong-answer case, which keeps the dialog open on the challenge.\n */\nexport type UpgradeDialogErrorKind =\n | 'rejected'\n | 'cancelled'\n | 'exhausted'\n | 'unsatisfiable'\n | 'unavailable'\n | 'transport'\n | 'insufficient'\n | 'session-changed';\n\nexport const DEFAULT_FACTOR_LABELS: Record<UpgradeFactorType, { label: string; hint?: string }> = {\n totp: { label: 'Authenticator app', hint: 'Enter the code from your authenticator app' },\n passkey: { label: 'Passkey', hint: 'Confirm with your device' },\n recovery_codes: { label: 'Recovery code', hint: 'Enter one of your single-use recovery codes' },\n email_otp: { label: 'Email code', hint: 'Enter the code we emailed you' },\n sms_otp: { label: 'SMS code', hint: 'Enter the code we texted you' },\n};\n\nconst CHALLENGE_REASON = 'This action needs extra verification';\n\n/** A six-digit numeric one-time code — TOTP and the two OTP transports. */\nconst OTP_CODE_CONTRACT: UpgradeFactorCodeContract = Object.freeze({\n maxLength: 6,\n inputMode: 'numeric',\n autoComplete: 'one-time-code',\n autoCapitalize: 'off',\n});\n\n/**\n * Per-factor code contracts, keyed by the factor type, which is the only thing\n * about a factor the protocol guarantees.\n *\n * `recovery_codes` is the reason this table exists. The server generates them\n * at `DefaultRecoveryCodeLength` (12) from a 32-character alphanumeric charset\n * and accepts a configured length anywhere in 6..16, so the cap is the server's\n * MAXIMUM — capping at the default would reject a valid code on a deployment\n * that raised it, and capping at six (the old single hardcoded number) rejected\n * every code on every deployment. A shorter configured code simply types\n * shorter; a cap can only ever do harm by being too small.\n *\n * `null` means the factor collects nothing typed: its proof comes from the\n * ceremony, so there is no field and no contract to state.\n */\nexport const UPGRADE_FACTOR_CODE_CONTRACTS: Readonly<{\n totp: UpgradeFactorCodeContract;\n email_otp: UpgradeFactorCodeContract;\n sms_otp: UpgradeFactorCodeContract;\n recovery_codes: UpgradeFactorCodeContract;\n passkey: null;\n}> = Object.freeze({\n totp: OTP_CODE_CONTRACT,\n email_otp: OTP_CODE_CONTRACT,\n sms_otp: OTP_CODE_CONTRACT,\n recovery_codes: Object.freeze({\n maxLength: 16,\n inputMode: 'text',\n autoComplete: 'off',\n autoCapitalize: 'characters',\n }),\n passkey: null,\n});\n\n/**\n * The contract for a factor that collects a typed answer. A `'code'` factor the\n * table has no entry for falls back to the OTP shape rather than to no cap at\n * all, so an unknown future code factor is merely sub-optimal, never broken.\n */\nconst codeContractFor = (type: UpgradeFactorType): UpgradeFactorCodeContract =>\n UPGRADE_FACTOR_CODE_CONTRACTS[type] ?? OTP_CODE_CONTRACT;\n\n/** Index 0 stays index 0: `selectFactors` already ranked the list, and ranking is not filtering. */\nexport const toDialogFactors = (\n factors: readonly UpgradeFactorSnapshot[],\n labels?: UpgradeDialogLabels,\n): UpgradeDialogFactor[] =>\n factors.map((factor) => {\n const fallback = DEFAULT_FACTOR_LABELS[factor.type];\n const override = labels?.[factor.type];\n const base = {\n type: factor.type,\n label: override?.label ?? fallback.label,\n hint: override?.hint ?? fallback.hint,\n };\n return factor.input === 'code'\n ? { ...base, input: 'code' as const, code: codeContractFor(factor.type) }\n : { ...base, input: 'none' as const };\n });\n\nconst readString = (value: unknown): string | undefined => (typeof value === 'string' && value ? value : undefined);\n\nconst readRecord = (value: unknown): Record<string, unknown> | undefined =>\n typeof value === 'object' && value !== null ? (value as Record<string, unknown>) : undefined;\n\n/**\n * Every kind `@passflow/core` can classify, mapped to the panel the user sees.\n *\n * **This table is the fix for PFL-497's headline defect, and its totality is\n * the mechanism.** The previous version read `code` first, and since every\n * classified transport failure carries the same fixed literal\n * `code === 'upgrade_transport'`, that catch-all swallowed the kinds with their\n * own route — a mistyped code (`wrong_code`, retryable) landed on a terminal\n * panel. Routing by `kind` through a `Record<UpgradeErrorKind, …>` makes the\n * catch-all unnecessary and a missing route a TYPE error: a new kind added to\n * core cannot compile here until someone decides where it goes.\n *\n * `attempts_exhausted` is terminal (H3). It is the controller's local attempt\n * budget being spent, so the challenge the server holds will never be accepted\n * again; routing it with the retryable kinds re-prompted forever. It shares the\n * `exhausted` panel with the server's own `challenge_too_many_attempts`, which\n * is the same row of §13.3's settlement table.\n */\nconst DIALOG_KIND_BY_UPGRADE_KIND: Readonly<Record<UpgradeErrorKind, UpgradeDialogErrorKind>> = Object.freeze({\n // Retryable: the user answers again, the prompt stays open (§3.3, §13.3).\n wrong_code: 'rejected',\n challenge_spent: 'rejected',\n not_registered: 'rejected',\n prepare_not_required: 'rejected',\n // Terminal.\n exhausted: 'exhausted',\n attempts_exhausted: 'exhausted',\n unavailable: 'unavailable',\n session_changed: 'session-changed',\n fatal: 'transport',\n protocol: 'transport',\n network: 'transport',\n});\n\nconst isUpgradeErrorKind = (value: string | undefined): value is UpgradeErrorKind =>\n value !== undefined && Object.hasOwn(DIALOG_KIND_BY_UPGRADE_KIND, value);\n\n/**\n * Whether the value carries enough HTTP fact for core's classifier to say\n * anything at all. Without one of these, `classifyUpgradeError` would read the\n * value as a network failure, so a stray non-protocol object would be reported\n * to the user as a transport outcome it has no evidence for.\n */\nconst hasTransportFacts = (record: Record<string, unknown>): boolean =>\n typeof record.status === 'number' || typeof record.id === 'string' || readRecord(record.response) !== undefined;\n\n/**\n * The kind, as core determines it. The dialog states no kinds of its own.\n *\n * The already-tagged `kind` is read FIRST, and that order is load-bearing:\n * `classifyUpgradeError` passes a `UpgradeTransportError` through by\n * `instanceof`, which fails across a duplicated bundle or a structured clone,\n * and re-classifying an already-classified error by its bare status re-buckets\n * a `wrong_code` 401 into `session_changed`. The string is validated against\n * the route table, so a kind core does not know still falls through to the\n * classifier.\n */\nconst upgradeKindOf = (error: unknown, record: Record<string, unknown>): UpgradeErrorKind | undefined => {\n const tagged = readString(record.kind);\n if (isUpgradeErrorKind(tagged)) return tagged;\n if (!hasTransportFacts(record)) return undefined;\n // `'refresh'` is the commit round: the dialog only ever sees a failure that\n // already travelled through a flight, and the one round-dependent id\n // (`token.invalid`) means a session change there, which is the terminal\n // reading and the safe one for an un-tagged error.\n return classifyUpgradeError(error, 'refresh').kind;\n};\n\n/**\n * How a failure reads to the user, as the dialog's own vocabulary.\n *\n * Named `dialogOutcomeFromError`, not `classifyUpgradeError`: that name belongs\n * to `@passflow/core`, and holding it here shadowed core's symbol in the\n * package's own star exports, which made the real classifier unreachable to\n * consumers. This function decides nothing about what the error IS — core's\n * classifier does — only which panel that kind is shown on.\n *\n * The dedicated error classes are matched before the kind table because they\n * are not transport failures at all: they carry no `kind`, and core's\n * classifier has nothing to say about them.\n */\nexport const dialogOutcomeFromError = (error: unknown): UpgradeDialogErrorKind => {\n const record = readRecord(error);\n if (!record) return 'rejected';\n const code = readString(record.code);\n const name = readString(record.name);\n\n if (code === 'upgrade_cancelled' || name === 'UpgradeCancelledError' || record.cancelled === true) return 'cancelled';\n if (code === 'upgrade_unsatisfiable' || name === 'UpgradeUnsatisfiableError') return 'unsatisfiable';\n if (code === 'upgrade_unavailable' || name === 'UpgradeUnavailableError') return 'unavailable';\n if (code === 'upgrade_exhausted' || name === 'UpgradeExhaustedError') return 'exhausted';\n if (code === 'upgrade_insufficient' || name === 'UpgradeInsufficientError') return 'insufficient';\n if (code === 'upgrade_session_changed' || name === 'UpgradeSessionChangedError') return 'session-changed';\n\n const kind = upgradeKindOf(error, record);\n // Nothing identifiable: keep the prompt open rather than inventing a terminal\n // outcome. The controller's attempt budget bounds the re-prompting.\n return kind === undefined ? 'rejected' : DIALOG_KIND_BY_UPGRADE_KIND[kind];\n};\n\nexport const readAssuranceBar = (value: unknown): AssuranceBar | undefined => {\n const record = readRecord(value);\n if (!record) return undefined;\n const bar: AssuranceBar = {};\n if (typeof record.acrValues === 'string') bar.acrValues = record.acrValues;\n if (typeof record.level === 'number') bar.level = record.level;\n if (typeof record.maxAge === 'number') bar.maxAge = record.maxAge;\n return bar.acrValues === undefined && bar.level === undefined && bar.maxAge === undefined ? undefined : bar;\n};\n\n/** Human wording for a bar, on whichever axis it constrains. */\nexport const describeAssuranceBar = (bar?: AssuranceBar): string => {\n if (!bar) return 'an unknown level';\n const parts: string[] = [];\n if (bar.level !== undefined) parts.push(`AAL${bar.level}`);\n else if (bar.acrValues) parts.push(`acr ${bar.acrValues}`);\n if (bar.maxAge !== undefined) parts.push(`verified within ${bar.maxAge}s`);\n return parts.length > 0 ? parts.join(', ') : 'an unknown level';\n};\n\nconst challengeBar = (challenge: UpgradeChallengeSnapshot): AssuranceBar | undefined =>\n readAssuranceBar({\n acrValues: challenge.acrValues,\n level: challenge.requiredLevel,\n maxAge: challenge.maxAge,\n });\n\nconst errorMessage = (error: unknown, fallback: string): string => {\n const record = readRecord(error);\n return readString(record?.message) ?? fallback;\n};\n\nconst terminalFromError = (input: ToDialogStateInput, error: unknown): UpgradeDialogState => {\n const { handlers, testId } = input;\n switch (dialogOutcomeFromError(error)) {\n case 'cancelled':\n return {\n kind: 'cancelled',\n message: 'Verification cancelled',\n detail: 'The action that needed extra verification was not completed.',\n testId,\n onDismiss: handlers.onDismiss,\n };\n case 'exhausted':\n return {\n kind: 'exhausted',\n message: 'Too many attempts',\n detail: errorMessage(error, 'No attempts are left for this verification. Start the action again to retry.'),\n testId,\n onDismiss: handlers.onDismiss,\n };\n case 'unsatisfiable':\n return {\n kind: 'unsatisfiable',\n message: 'No usable verification method',\n detail: errorMessage(error, 'None of your verification methods can answer this request.'),\n required: input.prompt ? challengeBar(input.prompt.challenge) : undefined,\n testId,\n onDismiss: handlers.onDismiss,\n };\n case 'unavailable':\n return {\n kind: 'unavailable',\n message: 'Verification is unavailable',\n detail: errorMessage(error, 'This deployment cannot raise your assurance level right now.'),\n testId,\n onDismiss: handlers.onDismiss,\n };\n case 'session-changed':\n return {\n kind: 'cancelled',\n message: 'Verification stopped',\n detail: errorMessage(error, 'Your session changed while verifying, so the request was abandoned.'),\n testId,\n onDismiss: handlers.onDismiss,\n };\n case 'insufficient': {\n const record = readRecord(error);\n return {\n kind: 'insufficient',\n message: errorMessage(error, 'Verified, but not enough for this action'),\n obtained: readAssuranceBar(record?.obtained) ?? {},\n required: readAssuranceBar(record?.required) ?? {},\n testId,\n onDismiss: handlers.onDismiss,\n };\n }\n default:\n return {\n kind: 'transport',\n message: 'Verification could not be completed',\n detail: errorMessage(error, 'The verification request failed before it reached the server.'),\n retryable: readRecord(error)?.retryable === true,\n testId,\n onRetry: handlers.onRetry,\n onDismiss: handlers.onDismiss,\n };\n }\n};\n\n/**\n * The single projection. A terminal `outcome` always wins over an open prompt;\n * an empty offered factor list is the `no usable factor` outcome; a `busy`\n * ceremony with no code to type is `working`; everything else is the challenge.\n */\nexport const toDialogState = (input: ToDialogStateInput): UpgradeDialogState => {\n const { prompt, outcome, ui, labels, handlers, testId } = input;\n\n if (outcome) {\n switch (outcome.kind) {\n case 'elevated':\n return {\n kind: 'success',\n message: 'Verification complete',\n detail: 'Your request is continuing.',\n testId,\n // The happy path must clear itself: §13.4's \"reports success and\n // closes\". Without this the modal's focus trap covers the app after\n // every elevation.\n onDismiss: handlers.onDismiss,\n };\n case 'insufficient':\n return {\n kind: 'insufficient',\n message: `Verified to ${describeAssuranceBar(outcome.obtained)}; this action requires ${describeAssuranceBar(outcome.required)}`,\n obtained: outcome.obtained,\n required: outcome.required,\n detail: 'The elevation succeeded but the action was challenged again. Nothing was completed.',\n testId,\n onDismiss: handlers.onDismiss,\n };\n case 'cancelled':\n return {\n kind: 'cancelled',\n message: 'Verification cancelled',\n detail: 'The action that needed extra verification was not completed.',\n testId,\n onDismiss: handlers.onDismiss,\n };\n default:\n return terminalFromError(input, outcome.error);\n }\n }\n\n if (!prompt) {\n return {\n kind: 'working',\n message: 'Preparing verification…',\n testId,\n onCancel: handlers.onCancel,\n };\n }\n\n const previousKind = prompt.previousError === undefined ? undefined : dialogOutcomeFromError(prompt.previousError);\n if (previousKind !== undefined && previousKind !== 'rejected') {\n return terminalFromError(input, prompt.previousError);\n }\n\n const factors = toDialogFactors(prompt.factors, labels);\n const required = challengeBar(prompt.challenge);\n const suggested = factors[0];\n\n if (suggested === undefined) {\n return {\n kind: 'unsatisfiable',\n message: 'No usable verification method',\n detail: `This action requires ${describeAssuranceBar(required)}, and no verification method is available to answer it.`,\n required,\n testId,\n onDismiss: handlers.onDismiss,\n };\n }\n\n const selected = factors.find((factor) => factor.type === ui?.selected)?.type ?? suggested.type;\n const active = factors.find((factor) => factor.type === selected);\n const busy = ui?.busy === true;\n\n if (busy && active?.input === 'none') {\n return {\n kind: 'working',\n message: 'Waiting for your passkey…',\n detail: 'Follow the prompt from your device to confirm it is you.',\n testId,\n onCancel: handlers.onCancel,\n };\n }\n\n return {\n kind: 'challenge',\n factors,\n selected,\n reason: CHALLENGE_REASON,\n busy,\n error: previousKind === 'rejected' ? errorMessage(prompt.previousError, 'That code was not accepted. Try again.') : null,\n showAlternatives: ui?.showAlternatives === true,\n testId,\n onSelectFactor: handlers.onSelectFactor,\n onToggleAlternatives: handlers.onToggleAlternatives,\n onSubmit: handlers.onSubmit,\n onCancel: handlers.onCancel,\n };\n};\n\n/**\n * What Escape and an overlay click mean in each state. Cancellation must reach\n * the controller or the caller's promise hangs (§8.1), so this is never a bare\n * close; `success` has nothing to cancel, so it closes instead of cancelling —\n * returning `undefined` there made Escape and the overlay inert on the one\n * state every user reaches.\n */\nexport const upgradeDialogDismissHandler = (state: UpgradeDialogState): (() => void) | undefined => {\n switch (state.kind) {\n case 'challenge':\n return state.onCancel;\n case 'working':\n return state.onCancel;\n default:\n return state.onDismiss;\n }\n};\n","import { type FC, useEffect } from 'react';\nimport { Button } from '../button';\nimport { Icon } from '../icon';\nimport { Spinner } from '../spinner';\nimport { describeAssuranceBar } from './state-mapping';\nimport type { AssuranceBar, UpgradeDialogState } from './types';\n\n/** Every state that is not the collecting challenge. */\nexport type UpgradeStatusState = Exclude<UpgradeDialogState, { kind: 'challenge' }>;\n\ntype Tone = 'working' | 'success' | 'problem' | 'neutral';\n\nconst TONE: Record<UpgradeStatusState['kind'], Tone> = {\n working: 'working',\n success: 'success',\n insufficient: 'problem',\n unsatisfiable: 'problem',\n unavailable: 'problem',\n exhausted: 'problem',\n transport: 'problem',\n cancelled: 'neutral',\n};\n\n/**\n * How long `success` stays on screen before it closes itself (§13.4: \"reports\n * success and closes\"). Long enough to be read, short enough that the app is\n * never held behind a modal the user cannot see a reason for.\n */\nexport const UPGRADE_SUCCESS_AUTO_CLOSE_MS = 1800;\n\nconst BarRow: FC<{ term: string; bar: AssuranceBar }> = ({ term, bar }) => (\n <div className='passflow-upgrade-dialog__bar'>\n <span className='passflow-upgrade-dialog__bar-term'>{term}</span>\n <span className='passflow-upgrade-dialog__bar-value'>{describeAssuranceBar(bar)}</span>\n </div>\n);\n\n/**\n * The non-collecting views: `working`, `success` and the six terminal outcomes\n * of §13.3's settlement table.\n *\n * `insufficient` is deliberately rendered in the problem tone with both bars\n * shown: the elevation succeeded and the action still did not, and the dialog\n * must not report success when the replay was re-challenged (§13.4).\n *\n * `success` owns its own exit: a Done control and an auto-close timer, both\n * calling the state's `onDismiss`. The affordance lives here rather than in the\n * provider because a modal that cannot be closed is a property of this\n * component, and the Storybook story for the state has to show the way out.\n */\nexport const UpgradeStatus: FC<UpgradeStatusState> = (state) => {\n const tone = TONE[state.kind];\n const { detail } = state;\n\n const autoClose = state.kind === 'success' ? (state.autoCloseMs ?? UPGRADE_SUCCESS_AUTO_CLOSE_MS) : 0;\n const autoDismiss = state.kind === 'success' ? state.onDismiss : undefined;\n\n useEffect(() => {\n if (autoDismiss === undefined || autoClose <= 0) return;\n const timer = setTimeout(autoDismiss, autoClose);\n return () => clearTimeout(timer);\n }, [autoClose, autoDismiss]);\n\n return (\n <div className='passflow-upgrade-dialog__status' data-testid={state.testId} data-upgrade-state={state.kind}>\n <div\n className={`passflow-upgrade-dialog__status-head passflow-upgrade-dialog__status-head--${tone}`}\n role={tone === 'problem' ? 'alert' : 'status'}\n aria-live={tone === 'problem' ? 'assertive' : 'polite'}\n >\n {tone === 'working' ? <Spinner size='small' /> : null}\n {tone === 'success' ? <Icon size='small' id='check' type='general' className='icon-success' decorative /> : null}\n {tone === 'problem' ? <Icon size='small' id='warning' type='general' className='icon-warning' decorative /> : null}\n <span className='passflow-upgrade-dialog__status-message'>{state.message}</span>\n </div>\n\n {detail ? <p className='passflow-upgrade-dialog__status-detail'>{detail}</p> : null}\n\n {state.kind === 'insufficient' ? (\n <div className='passflow-upgrade-dialog__bars' data-testid='upgrade-dialog-bars'>\n <BarRow term='Verified' bar={state.obtained} />\n <BarRow term='Required' bar={state.required} />\n </div>\n ) : null}\n\n {state.kind === 'unsatisfiable' && state.required ? (\n <div className='passflow-upgrade-dialog__bars' data-testid='upgrade-dialog-bars'>\n <BarRow term='Required' bar={state.required} />\n </div>\n ) : null}\n\n <div className='passflow-upgrade-dialog__actions'>\n {state.kind === 'transport' && state.retryable && state.onRetry ? (\n <Button size='big' variant='primary' type='button' data-testid='upgrade-dialog-retry' onClick={state.onRetry}>\n {state.retryLabel ?? 'Try again'}\n </Button>\n ) : null}\n {state.kind === 'working' && state.onCancel ? (\n <Button size='big' variant='clean' type='button' data-testid='upgrade-dialog-cancel' onClick={state.onCancel}>\n Cancel\n </Button>\n ) : null}\n {state.kind !== 'working' ? (\n <Button size='big' variant='clean' type='button' data-testid='upgrade-dialog-dismiss' onClick={state.onDismiss}>\n {state.dismissLabel ?? (state.kind === 'success' ? 'Done' : 'Close')}\n </Button>\n ) : null}\n </div>\n </div>\n );\n};\n","import type { FC } from 'react';\nimport { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from '../dialog';\nimport { UpgradeChallengeView } from './challenge';\nimport { upgradeDialogDismissHandler } from './state-mapping';\nimport { UpgradeStatus } from './status';\nimport type { UpgradeDialogProps } from './types';\nimport './upgrade-dialog.css';\n\nconst DESCRIPTION_ID = 'passflow-upgrade-dialog-description';\n\n/**\n * The assurance-upgrade modal. A switch over `state.kind`, modelled on\n * `LoginScreen`: one discriminated union, one view per state, no transitions of\n * its own.\n *\n * Escape and an overlay click route to the state's cancel or dismiss callback,\n * never to a bare close — cancellation must reach the controller or the\n * caller's promise never settles (§8.1).\n */\nexport const UpgradeDialog: FC<UpgradeDialogProps> = ({ open, title = 'Extra verification required', state }) => {\n const dismiss = upgradeDialogDismissHandler(state);\n const description = state.kind === 'challenge' ? state.reason : undefined;\n\n return (\n <Dialog\n open={open}\n onOpenChange={(next) => {\n if (!next) dismiss?.();\n }}\n >\n <DialogContent\n className='passflow-upgrade-dialog'\n data-testid='upgrade-dialog'\n aria-describedby={description ? DESCRIPTION_ID : undefined}\n >\n <DialogHeader className='passflow-upgrade-dialog__header'>\n <DialogTitle>{title}</DialogTitle>\n {description ? <DialogDescription id={DESCRIPTION_ID}>{description}</DialogDescription> : null}\n </DialogHeader>\n {state.kind === 'challenge' ? <UpgradeChallengeView {...state} /> : <UpgradeStatus {...state} />}\n </DialogContent>\n </Dialog>\n );\n};\n","import type { LoginScreenProps } from '@/components/ui';\nimport type { UseConsentProps } from '@/hooks/use-consent';\n\n/**\n * Maps consent state onto the shared LoginScreen. Pure — every visual decision\n * lives in LoginScreen, every protocol decision lives in useConsent, and this\n * file is only the translation between them.\n */\nexport const getConsentLoginScreenProps = (consent: UseConsentProps): LoginScreenProps | null => {\n if (consent.status === 'loading') return null;\n\n if (consent.status === 'invalid') {\n return {\n chrome: {\n title: consent.error?.message ?? 'Consent request unavailable',\n },\n state: {\n kind: 'general-error',\n message: consent.error?.message,\n detail: consent.error?.description,\n actionLabel: 'Back to login',\n testId: 'consent-invalid',\n onAction: () => {\n window.location.href = '/web';\n },\n },\n };\n }\n\n if (consent.status === 'redirecting') {\n return {\n chrome: {\n title: 'Taking you back',\n subtitle: `Returning you to ${consent.info?.app_name || 'the application'}.`,\n },\n state: {\n kind: 'status',\n tone: 'success',\n message: 'Decision recorded',\n detail: 'You can close this page if it does not continue on its own.',\n testId: 'consent-redirecting',\n },\n };\n }\n\n const info = consent.info;\n if (!info) return null;\n\n const appName = info.app_name || info.client_id;\n const busy = consent.status === 'working';\n\n return {\n chrome: {\n title: `Allow ${appName} to access your account?`,\n subtitle: 'Choose what this application may use, then allow or deny.',\n // The app's own logo replaces the Passflow mark, which is what makes this\n // read as \"THIS app is asking\" rather than a generic Passflow screen.\n customLogo: info.app_logo_url || undefined,\n customLogoAlt: `${appName} logo`,\n },\n state: {\n kind: 'consent',\n appName,\n scopes: info.requested_scopes.map((scope) => {\n const meta = consent.scopeMetadata(scope);\n return {\n scope,\n label: meta.label || scope,\n description: meta.description || undefined,\n granted: consent.grantedScopes.includes(scope),\n };\n }),\n busy,\n error: consent.error?.message,\n allowLabel: 'Allow',\n denyLabel: 'Deny',\n busyLabel: 'Submitting…',\n testId: 'consent-screen',\n allowTestId: 'consent-allow',\n denyTestId: 'consent-deny',\n appNameTestId: 'consent-app-name',\n onToggleScope: consent.toggleScope,\n onAllow: () => void consent.allow(),\n onDeny: () => void consent.deny(),\n },\n };\n};\n","import type { FC } from 'react';\nimport { LoginScreen } from '@/components/ui';\nimport { useConsent } from '@/hooks/use-consent';\nimport { getConsentLoginScreenProps } from './screen';\n\n/**\n * OIDC consent controller, mounted by the host app on `/web/consent`.\n *\n * Standalone by design: it needs no PassflowProvider. The staged request is\n * addressed by `parent_challenge_id` on the URL and read with a same-origin\n * cookie, so there is no SDK client, no app settings lookup, and no token to\n * hold — which is also why mounting it inside the provider would be actively\n * wrong, since the provider's session-exchange probe would fire against a\n * challenge that is waiting for a human decision.\n */\nexport const ConsentFlow: FC = () => {\n const consent = useConsent();\n const screen = getConsentLoginScreenProps(consent);\n\n return screen ? <LoginScreen {...screen} /> : null;\n};\n","import type { LoginMethodConfig, LoginScreenProps } from '@/components/ui';\nimport type { UseDeviceVerifyProps } from '@/hooks/use-device-verify';\nimport type { AuthUiError, DeviceError } from '@/types';\nimport { deviceErrorOfType } from '@/utils';\n\nconst getDeviceLoginMethods = (device: UseDeviceVerifyProps): LoginMethodConfig => ({\n identities: device.info?.methods.password\n ? [\n {\n id: 'email_or_username',\n label: 'Email',\n selectLabel: 'Use email',\n requiredMessage: 'Email is required',\n format: 'email',\n password: true,\n },\n ]\n : [],\n passkey: Boolean(device.info?.methods.passkey),\n providers: [],\n});\n\nconst toCredentialsError = (error: DeviceError | null): AuthUiError | null => {\n if (!error) return null;\n\n return {\n message: error.message,\n scope: error.type === 'bad_credentials' || error.type === 'missing_credentials' ? 'credentials' : 'form',\n };\n};\n\nconst deviceNotice = (device: UseDeviceVerifyProps) => {\n if (!device.info) return undefined;\n\n return {\n code: device.info.user_code,\n appName: device.info.app_name,\n message: \"requested this sign-in. Confirm that the code matches your terminal. If it doesn't, close this page.\",\n codeTestId: 'device-consent-user-code',\n appNameTestId: 'device-consent-app-name',\n };\n};\n\nexport const getDeviceLoginScreenProps = (device: UseDeviceVerifyProps): LoginScreenProps | null => {\n if (device.status === 'loading') return null;\n\n if (device.status === 'code_entry') {\n return {\n chrome: {\n title: 'Enter the code',\n subtitle: 'Type the code shown on your device.',\n },\n state: {\n kind: 'code-entry',\n error: device.error?.message,\n testId: 'device-code-entry',\n onSubmit: device.submitCode,\n },\n };\n }\n\n if (device.status === 'done') {\n return {\n chrome: {\n title: device.info?.app_name ? `You're signed in to ${device.info.app_name}` : \"You're signed in\",\n subtitle: \"Head back to your terminal — it's ready to go.\",\n },\n state: {\n kind: 'status',\n tone: 'success',\n message: 'This device is approved',\n detail: 'You can close this page.',\n testId: device.info?.mode === 'passkey' ? 'device-auto-passkey-done' : 'device-done',\n },\n };\n }\n\n if (device.status === 'refused') {\n const error = device.error ?? deviceErrorOfType('mode_disabled');\n return {\n chrome: {\n title: \"Sign-in isn't available this way\",\n },\n state: {\n kind: 'status',\n tone: 'disabled',\n message: error.message,\n detail: 'Nothing was approved, and nothing was sent to the device that showed you this code.',\n testId: 'device-mode-disabled',\n },\n };\n }\n\n if (device.status === 'failed') {\n const error = device.error ?? deviceErrorOfType('generic');\n return {\n chrome: {\n title: \"That didn't work\",\n },\n state: {\n kind: 'status',\n tone: 'error',\n message: error.message,\n recoverable: error.isRecoverable,\n testId: 'device-failed',\n onRetry: error.isRecoverable ? () => device.submitCode('') : undefined,\n },\n };\n }\n\n if (!device.info) return null;\n\n // Every mode asks for the second factor the same way, before its approval.\n if (device.status === 'second_factor' || (device.status === 'working' && device.isSecondFactorPending)) {\n return {\n chrome: {\n title: 'Two-Factor Authentication',\n subtitle: `One more step to approve ${device.info.app_name}.`,\n },\n state: {\n kind: 'second-factor',\n methods: device.secondFactorMethods,\n identity: device.email,\n busy: device.status === 'working',\n error: device.error?.message,\n testId: 'device-second-factor',\n onSubmit: (method, code) => void device.submitSecondFactor(method, code),\n onMethodChange: device.clearError,\n },\n };\n }\n\n if (device.info.mode === 'passkey') {\n const working = (device.status === 'ready' || device.status === 'working') && !device.error;\n return {\n chrome: {\n title: `Sign in to ${device.info.app_name}`,\n subtitle: 'Confirm with your passkey to finish this device sign-in.',\n },\n state: {\n kind: 'passkey-progress',\n working,\n message: device.error\n ? \"Passkey sign-in couldn't continue.\"\n : 'Waiting for your passkey — follow the prompt on your device.',\n error: device.error?.message,\n recoverable: device.error?.isRecoverable,\n testId: 'device-auto-passkey',\n onRetry: device.error?.isRecoverable ? () => void device.confirmWithPasskey() : undefined,\n },\n };\n }\n\n const busy = device.status === 'working';\n const authenticated = device.isAuthenticated || device.status === 'signed_in';\n const methods = getDeviceLoginMethods(device);\n const notice = deviceNotice(device);\n\n if (device.info.mode === 'full_login') {\n if (authenticated) {\n return {\n chrome: {\n title: `Approve sign-in to ${device.info.app_name}`,\n subtitle: 'Confirm that the code matches your terminal before approving.',\n },\n state: {\n kind: 'device-approval',\n appName: device.info.app_name,\n code: device.info.user_code,\n identity: device.email,\n busy,\n error: device.error?.message,\n testId: 'device-full-login-approval',\n actionTestId: 'device-confirm',\n codeTestId: 'device-consent-user-code',\n appNameTestId: 'device-consent-app-name',\n onApprove: () => void device.approve(),\n },\n };\n }\n\n return {\n chrome: {\n title: `Sign in to approve ${device.info.app_name}`,\n subtitle: 'Confirm the code, then sign in to continue.',\n variant: 'sign-in',\n },\n state: {\n kind: 'credentials',\n methods,\n passwordPolicy: null,\n notice,\n busy,\n error: toCredentialsError(device.error),\n primaryLabel: busy ? 'Signing in…' : 'Sign In',\n passkeyLabel: 'Sign In with a Passkey',\n testId: 'device-full-login',\n onPassword: (values) => void device.signInWithPassword(values.emailOrUsername, values.password),\n onPasskey: () => void device.signInWithPasskey(),\n },\n };\n }\n\n return {\n chrome: {\n title: `Approve sign-in to ${device.info.app_name}`,\n subtitle: 'Confirm the code, then sign in to approve this request.',\n variant: 'sign-in',\n },\n state: {\n kind: 'credentials',\n methods,\n passwordPolicy: null,\n notice,\n busy,\n error: toCredentialsError(device.error),\n primaryLabel: busy ? 'Approving…' : 'Approve',\n primaryTestId: 'device-confirm',\n passkeyLabel: 'Approve with a Passkey',\n testId: 'device-consent',\n onPassword: (values) => void device.confirmWithPassword(values.emailOrUsername, values.password),\n onPasskey: () => void device.confirmWithPasskey(),\n },\n };\n};\n","import type { FC } from 'react';\nimport { useEffect, useRef } from 'react';\nimport { LoginScreen } from '@/components/ui';\nimport { useDeviceVerify } from '@/hooks/use-device-verify';\nimport { getDeviceLoginScreenProps } from './screen';\n\n/**\n * RFC 8628 device verification controller.\n *\n * The server selects consent, full-login, or passkey mode. This component owns\n * the state transition and automatic passkey attempt; the Storybook-backed\n * LoginScreen owns every visual state.\n */\nexport const DeviceVerifyFlow: FC = () => {\n const device = useDeviceVerify();\n const attemptedPasskeyChallenge = useRef<string | null>(null);\n const { confirmWithPasskey } = device;\n const challengeKey = device.info?.csrf_token ?? null;\n const isAutomaticPasskeyReady = device.info?.mode === 'passkey' && device.status === 'ready' && !device.error;\n\n useEffect(() => {\n if (!isAutomaticPasskeyReady || !challengeKey || attemptedPasskeyChallenge.current === challengeKey) return;\n\n attemptedPasskeyChallenge.current = challengeKey;\n void confirmWithPasskey();\n }, [challengeKey, confirmWithPasskey, isAutomaticPasskeyReady]);\n\n const screen = getDeviceLoginScreenProps(device);\n return screen ? <LoginScreen {...screen} /> : null;\n};\n","import type { FC, FormEvent } from 'react';\nimport { useId, useState } from 'react';\nimport { Button, FieldOtp, Icon } from '@/components/ui';\nimport { useTwoFactorSetup } from '@/hooks';\nimport { Wrapper } from '../wrapper';\n\nimport '@/styles/index.css';\n\ntype TwoFactorSetupFormProps = {\n onComplete?: (recoveryCodes: string[]) => void;\n onCancel?: () => void;\n numInputs?: number;\n};\n\nexport const TwoFactorSetupForm: FC<TwoFactorSetupFormProps> = ({ onComplete, onCancel, numInputs }) => {\n const [code, setCode] = useState('');\n const [showSecret, setShowSecret] = useState(false);\n const { setupData, recoveryCodes, step, beginSetup, confirmSetup, reset, isLoading, isError, error } = useTwoFactorSetup();\n const otpId = useId();\n const otpLabelId = `${otpId}-label`;\n const otpErrorId = `${otpId}-error`;\n\n // Get TOTP digits (defaults to 6 if not provided)\n const totpDigits = numInputs ?? 6;\n\n const handleCodeChange = (value: string) => {\n setCode(value);\n };\n\n const handleConfirm = async (e: FormEvent) => {\n e.preventDefault();\n const result = await confirmSetup(code);\n if (result) {\n // Don't call onComplete yet - wait for user to save codes\n }\n };\n\n const handleCopyRecoveryCodes = () => {\n navigator.clipboard.writeText(recoveryCodes.join('\\n'));\n };\n\n const handleComplete = () => {\n onComplete?.(recoveryCodes);\n reset();\n };\n\n // Step 1: Start setup\n if (step === 'idle') {\n return (\n <Wrapper\n title='Enable Two-Factor Authentication'\n subtitle='Add an extra layer of security to your account'\n className='passflow-2fa-setup'\n >\n <div className='passflow-2fa-setup-start'>\n <Button size='big' type='button' variant='primary' onClick={() => beginSetup()} disabled={isLoading}>\n {isLoading ? 'Loading...' : 'Get Started'}\n </Button>\n {onCancel && (\n <button type='button' className='passflow-link-button' onClick={onCancel}>\n Cancel\n </button>\n )}\n {isError && (\n <div className='passflow-field-error'>\n <Icon size='small' id='warning' type='general' className='icon-warning' />\n <span className='passflow-field-error-text'>{error}</span>\n </div>\n )}\n </div>\n </Wrapper>\n );\n }\n\n // Step 2: Show QR code and confirm\n if (step === 'setup' && setupData) {\n return (\n <Wrapper\n title='Scan QR Code'\n subtitle='Scan this code with your authenticator app (Google Authenticator, Authy, etc.)'\n className='passflow-2fa-setup'\n >\n <form onSubmit={handleConfirm} className='passflow-2fa-setup-qr'>\n <div className='passflow-2fa-qr-container'>\n <img src={`data:image/png;base64,${setupData.qr_code}`} alt='2FA QR Code' className='passflow-2fa-qr-image' />\n </div>\n\n <div className='passflow-2fa-secret-toggle'>\n <button type='button' className='passflow-link-button' onClick={() => setShowSecret(!showSecret)}>\n {showSecret ? 'Hide manual code' : \"Can't scan? Enter code manually\"}\n </button>\n {showSecret && <code className='passflow-2fa-secret-code'>{setupData.secret}</code>}\n </div>\n\n <div className='passflow-2fa-confirm-section'>\n <p id={otpLabelId} className='passflow-2fa-confirm-label'>\n Enter the {totpDigits}-digit code from your app to confirm:\n </p>\n <div id='otp-wrapper' className='passflow-verify-otp-wrapper'>\n <FieldOtp\n id={otpId}\n name='code'\n length={totpDigits}\n value={code}\n onChange={handleCodeChange}\n state={isError ? 'error' : 'default'}\n labelledBy={otpLabelId}\n describedBy={isError ? otpErrorId : undefined}\n autoFocus\n />\n {isError && (\n <div className='passflow-verify-otp-error'>\n <Icon size='small' id='warning' type='general' className='icon-warning' />\n <span id={otpErrorId} className='passflow-verify-otp-error-text'>\n {error}\n </span>\n </div>\n )}\n </div>\n </div>\n\n <Button size='big' type='submit' variant='primary' disabled={code.length !== totpDigits || isLoading}>\n {isLoading ? 'Confirming...' : 'Confirm & Enable'}\n </Button>\n </form>\n </Wrapper>\n );\n }\n\n // Step 3: Show recovery codes\n if (step === 'complete' && recoveryCodes.length > 0) {\n return (\n <Wrapper\n title='Save Your Recovery Codes'\n subtitle=\"Store these codes in a safe place. You'll need them if you lose access to your authenticator.\"\n className='passflow-2fa-setup'\n >\n <div className='passflow-2fa-setup-complete'>\n <div className='passflow-2fa-warning'>\n <Icon size='small' id='warning' type='general' className='icon-warning' />\n <span>These codes will only be shown once. Make sure to save them!</span>\n </div>\n\n <div className='passflow-2fa-recovery-codes'>\n {recoveryCodes.map((recoveryCode) => (\n <code key={recoveryCode} className='passflow-2fa-recovery-code'>\n {recoveryCode}\n </code>\n ))}\n </div>\n\n <Button size='big' type='button' variant='secondary' onClick={handleCopyRecoveryCodes}>\n Copy to Clipboard\n </Button>\n\n <Button size='big' type='button' variant='primary' onClick={handleComplete}>\n I've Saved These Codes\n </Button>\n </div>\n </Wrapper>\n );\n }\n\n return null;\n};\n","import type { FC } from 'react';\nimport { useEffect, useState } from 'react';\nimport { TwoFactorSetupForm } from '@/components/form/two-factor-setup';\nimport { routes } from '@/context';\nimport { useNavigation, usePassflow } from '@/hooks';\nimport type { SuccessAuthRedirect } from '@/types';\nimport { TwoFactorLoopPrevention } from '@/utils';\n\nimport '@/styles/index.css';\n\ntype TwoFactorSetupFlowProps = {\n successAuthRedirect?: SuccessAuthRedirect;\n twoFactorVerifyPath?: string;\n signInPath?: string;\n};\n\nexport const TwoFactorSetupFlow: FC<TwoFactorSetupFlowProps> = ({\n twoFactorVerifyPath = routes.two_factor_verify.path,\n signInPath = routes.signin.path,\n}) => {\n const [shouldBlockRender, setShouldBlockRender] = useState(false);\n const { navigate } = useNavigation();\n const passflow = usePassflow();\n\n // Handle initial verification requirement check\n // User must be in partial auth state (have tfa_token) to access setup\n useEffect(() => {\n if (!passflow.isTwoFactorVerificationRequired()) {\n // Not in partial auth state - redirect to sign-in\n if (TwoFactorLoopPrevention.canRedirect()) {\n TwoFactorLoopPrevention.incrementRedirect();\n navigate({ to: signInPath });\n setShouldBlockRender(true);\n } else {\n // Loop detected - let component handle gracefully\n setShouldBlockRender(false);\n }\n }\n }, [passflow, navigate, signInPath]);\n\n const handleSetupComplete = () => {\n // After setup is complete, redirect back to verify flow\n // User now has 2FA enabled and needs to verify with a code\n navigate({ to: twoFactorVerifyPath });\n };\n\n const handleCancel = () => {\n // User cancelled setup - reset loop prevention and go back to sign-in\n TwoFactorLoopPrevention.reset();\n navigate({ to: signInPath });\n };\n\n // Don't render if we're redirecting\n if (shouldBlockRender) {\n return null;\n }\n\n // Don't render if verification not required and no loop detected\n if (!passflow.isTwoFactorVerificationRequired() && TwoFactorLoopPrevention.canRedirect()) {\n return null;\n }\n\n return <TwoFactorSetupForm onComplete={handleSetupComplete} onCancel={handleCancel} />;\n};\n","import type { TwoFactorMethod } from '@passflow/core';\nimport * as Dialog from '@radix-ui/react-dialog';\nimport type { FC } from 'react';\n\ntype MethodSelectorProps = {\n availableMethods: TwoFactorMethod[];\n currentMethod: TwoFactorMethod;\n onSelectMethod: (method: TwoFactorMethod) => void;\n isOpen: boolean;\n onClose: () => void;\n};\n\nconst methodLabels: Partial<Record<TwoFactorMethod, string>> = {\n totp: 'Authenticator App',\n email_otp: 'Email Code',\n sms_otp: 'SMS Code',\n passkey: 'Passkey',\n recovery_codes: 'Recovery Code',\n push_fcm: 'Push Notification (FCM)',\n push_webpush: 'Push Notification (Web)',\n};\n\nconst methodIcons: Partial<Record<TwoFactorMethod, string>> = {\n totp: '📱',\n email_otp: '✉️',\n sms_otp: '💬',\n passkey: '🔑',\n recovery_codes: '🔒',\n push_fcm: '🔔',\n push_webpush: '🔔',\n};\n\nexport const MethodSelector: FC<MethodSelectorProps> = ({\n availableMethods,\n currentMethod,\n onSelectMethod,\n isOpen,\n onClose,\n}) => {\n const handleSelect = (method: TwoFactorMethod) => {\n onSelectMethod(method);\n onClose();\n };\n\n return (\n <Dialog.Root open={isOpen} onOpenChange={(open) => !open && onClose()}>\n <Dialog.Portal>\n <Dialog.Overlay className='pf-dialog-overlay' />\n <Dialog.Content className='pf-dialog-content pf-method-selector-dialog'>\n <Dialog.Title className='pf-dialog-title'>Choose Verification Method</Dialog.Title>\n <Dialog.Description className='pf-dialog-description'>\n Select an alternative method to verify your identity\n </Dialog.Description>\n\n <div className='pf-method-selector-list'>\n {availableMethods.map((method) => (\n <button\n key={method}\n type='button'\n className={`pf-method-selector-item ${method === currentMethod ? 'pf-method-selector-item-active' : ''}`}\n onClick={() => handleSelect(method)}\n disabled={method === currentMethod}\n >\n <span className='pf-method-icon'>{methodIcons[method] || '🔐'}</span>\n <span className='pf-method-label'>{methodLabels[method] || method}</span>\n {method === currentMethod && <span className='pf-method-current-badge'>Current</span>}\n </button>\n ))}\n </div>\n\n <Dialog.Close asChild>\n <button type='button' className='pf-dialog-close' aria-label='Close'>\n ×\n </button>\n </Dialog.Close>\n </Dialog.Content>\n </Dialog.Portal>\n </Dialog.Root>\n );\n};\n","import type { TwoFactorMethod } from '@passflow/core';\nimport type { FC } from 'react';\nimport { useEffect, useId, useState } from 'react';\nimport { FieldOtp } from '@/components/ui';\nimport { useTwoFactorChallenge } from '@/hooks/use-two-factor-challenge';\nimport { MethodSelector } from './method-selector';\n\ntype TwoFactorChallengeProps = {\n firstFactorMethod?: string;\n onSuccess?: () => void;\n onError?: (error: Error) => void;\n trustDevice?: boolean;\n};\n\nexport const TwoFactorChallenge: FC<TwoFactorChallengeProps> = ({\n firstFactorMethod,\n onSuccess,\n onError,\n trustDevice = false,\n}) => {\n const { challenge, isLoading, error, requestChallenge, verify, switchMethod, selectedMethod } = useTwoFactorChallenge();\n\n const [otpValue, setOtpValue] = useState('');\n const [isMethodSelectorOpen, setIsMethodSelectorOpen] = useState(false);\n const otpId = useId();\n const otpLabelId = `${otpId}-label`;\n const otpErrorId = `${otpId}-error`;\n\n // Request challenge on mount\n useEffect(() => {\n requestChallenge(firstFactorMethod);\n }, [requestChallenge, firstFactorMethod]);\n\n // Handle errors\n useEffect(() => {\n if (error && onError) {\n onError(error);\n }\n }, [error, onError]);\n\n const handleVerify = async () => {\n if (!otpValue) {\n return;\n }\n\n const result = await verify(otpValue, trustDevice);\n if (result) {\n onSuccess?.();\n }\n };\n\n const handleSwitchMethod = async (method: TwoFactorMethod) => {\n setOtpValue('');\n await switchMethod(method);\n };\n\n const handleOtpChange = (value: string) => {\n setOtpValue(value);\n\n // Auto-submit when OTP is complete (6 digits)\n if (value.length === 6) {\n setTimeout(() => {\n verify(value, trustDevice).then((result) => {\n if (result) {\n onSuccess?.();\n }\n });\n }, 100);\n }\n };\n\n if (!challenge) {\n return (\n <div className='pf-two-factor-challenge pf-loading'>\n <p>Loading challenge...</p>\n </div>\n );\n }\n\n const currentMethod = selectedMethod || challenge.method;\n const availableMethods = [challenge.method, ...(challenge.alternative_methods || [])];\n\n const renderChallengeInput = () => {\n switch (currentMethod) {\n case 'totp':\n case 'email_otp':\n case 'sms_otp':\n return (\n <div className='pf-challenge-input-wrapper'>\n <FieldOtp\n id={otpId}\n name='code'\n length={6}\n value={otpValue}\n onChange={handleOtpChange}\n state={isLoading ? 'disabled' : error ? 'error' : 'default'}\n labelledBy={otpLabelId}\n describedBy={error ? otpErrorId : undefined}\n autoFocus\n />\n {error && (\n <div id={otpErrorId} className='pf-otp-error'>\n {error.message}\n </div>\n )}\n {currentMethod === 'email_otp' && challenge.code_sent_to && (\n <p className='pf-challenge-hint'>Code sent to {challenge.code_sent_to}</p>\n )}\n {currentMethod === 'sms_otp' && challenge.code_sent_to && (\n <p className='pf-challenge-hint'>Code sent to {challenge.code_sent_to}</p>\n )}\n <button\n type='button'\n onClick={handleVerify}\n disabled={isLoading || otpValue.length !== 6}\n className='pf-button pf-button-primary'\n >\n {isLoading ? 'Verifying...' : 'Verify'}\n </button>\n </div>\n );\n\n case 'passkey':\n return (\n <div className='pf-challenge-input-wrapper'>\n <button type='button' onClick={handleVerify} disabled={isLoading} className='pf-button pf-button-primary'>\n {isLoading ? 'Verifying...' : 'Use Passkey'}\n </button>\n </div>\n );\n\n case 'recovery_codes':\n return (\n <div className='pf-challenge-input-wrapper'>\n <input\n type='text'\n value={otpValue}\n onChange={(e) => setOtpValue(e.target.value)}\n placeholder='Enter recovery code'\n disabled={isLoading}\n className='pf-input'\n />\n <button\n type='button'\n onClick={handleVerify}\n disabled={isLoading || !otpValue}\n className='pf-button pf-button-primary'\n >\n {isLoading ? 'Verifying...' : 'Verify'}\n </button>\n </div>\n );\n\n default:\n return <p>Unsupported method: {currentMethod}</p>;\n }\n };\n\n return (\n <div className='pf-two-factor-challenge'>\n <div className='pf-challenge-method-info'>\n <h3>Two-Factor Authentication</h3>\n <p id={otpLabelId}>Enter the verification code</p>\n </div>\n\n {renderChallengeInput()}\n\n {availableMethods.length > 1 && (\n <button\n type='button'\n onClick={() => setIsMethodSelectorOpen(true)}\n className='pf-button pf-button-secondary pf-button-switch-method'\n >\n Use different method\n </button>\n )}\n\n <MethodSelector\n availableMethods={availableMethods}\n currentMethod={currentMethod}\n onSelectMethod={handleSwitchMethod}\n isOpen={isMethodSelectorOpen}\n onClose={() => setIsMethodSelectorOpen(false)}\n />\n </div>\n );\n};\n","import type { ChangeEvent, FC, FormEvent } from 'react';\nimport { useState } from 'react';\nimport { Button, Icon, Switch } from '@/components/ui';\nimport { useTwoFactorVerify } from '@/hooks';\nimport { cn, getUserFriendlyErrorMessage, TwoFactorLoopPrevention } from '@/utils';\nimport { Wrapper } from '../wrapper';\n\nimport '@/styles/index.css';\n\ntype TwoFactorRecoveryFormProps = {\n onSuccess?: () => void;\n onBack?: () => void;\n title?: string;\n subtitle?: string;\n signInPath?: string;\n /** Label of the \"trust this device\" option, unticked by default. */\n trustDeviceLabel?: string;\n};\n\n/** Only a ticked box asks for trust; an unticked one sends no option at all. */\nconst completionOptions = (trustDevice: boolean) => (trustDevice ? { trustDevice: true } : undefined);\n\nexport const TwoFactorRecoveryForm: FC<TwoFactorRecoveryFormProps> = ({\n onSuccess,\n onBack,\n title = 'Use Recovery Code',\n subtitle = 'Enter one of your recovery codes',\n signInPath,\n trustDeviceLabel = 'Trust this device',\n}) => {\n const [code, setCode] = useState('');\n const [trustDevice, setTrustDevice] = useState(false);\n const { useRecoveryCode, isLoading, isError, errorDetails, reset } = useTwoFactorVerify();\n\n const handleChange = (e: ChangeEvent<HTMLInputElement>) => {\n reset();\n // Normalize: uppercase and remove spaces\n setCode(e.target.value.toUpperCase().replace(/\\s/g, ''));\n };\n\n const handleSubmit = async (e: FormEvent) => {\n e.preventDefault();\n const result = await useRecoveryCode(code, completionOptions(trustDevice));\n if (result) {\n onSuccess?.();\n }\n };\n\n const handleBackToSignIn = () => {\n TwoFactorLoopPrevention.reset();\n window.location.href = signInPath || '/signin';\n };\n\n // Check if loop detected\n const isLoopDetected = !TwoFactorLoopPrevention.canRedirect();\n\n // Render error content (same logic as verify form)\n const renderErrorContent = () => {\n if (!isError || !errorDetails) return null;\n\n if (isLoopDetected) {\n return (\n <div className='passflow-form-error passflow-form-error--critical'>\n <Icon size='medium' id='warning' type='general' className='icon-warning' />\n <div className='passflow-form-error-content'>\n <span className='passflow-form-error-text'>{TwoFactorLoopPrevention.getLoopDetectedMessage()}</span>\n {signInPath && (\n <Button\n type='button'\n size='medium'\n variant='secondary'\n onClick={handleBackToSignIn}\n className='passflow-button-back-to-signin'\n >\n Back to Sign In\n </Button>\n )}\n </div>\n </div>\n );\n }\n\n if (errorDetails.type === 'not_enabled') {\n return (\n <div className='passflow-form-error passflow-form-error--persistent'>\n <Icon size='medium' id='warning' type='general' className='icon-warning' />\n <div className='passflow-form-error-content'>\n <span className='passflow-form-error-text'>{getUserFriendlyErrorMessage(errorDetails)}</span>\n {signInPath && (\n <Button\n type='button'\n size='medium'\n variant='secondary'\n onClick={handleBackToSignIn}\n className='passflow-button-back-to-signin'\n >\n Back to Sign In\n </Button>\n )}\n </div>\n </div>\n );\n }\n\n if (errorDetails.type === 'expired') {\n return (\n <div className='passflow-form-info'>\n <Icon size='small' id='info' type='general' className='icon-info' />\n <span className='passflow-form-info-text'>{getUserFriendlyErrorMessage(errorDetails)}</span>\n </div>\n );\n }\n\n return (\n <div className='passflow-form-error'>\n <Icon size='small' id='warning' type='general' className='icon-warning' />\n <span className='passflow-form-error-text'>{getUserFriendlyErrorMessage(errorDetails)}</span>\n </div>\n );\n };\n\n const isInputDisabled =\n isLoading || errorDetails?.type === 'not_enabled' || errorDetails?.type === 'expired' || isLoopDetected;\n\n return (\n <Wrapper title={title} subtitle={subtitle} className='passflow-2fa-recovery'>\n <form onSubmit={handleSubmit} className='passflow-form'>\n <div className='passflow-form-container'>\n <div className='passflow-form-field'>\n <Switch\n label={trustDeviceLabel}\n checked={trustDevice}\n disabled={isInputDisabled}\n onChange={(event) => setTrustDevice(event.target.checked)}\n />\n </div>\n <div className='passflow-form-field'>\n <label htmlFor='recovery-code' className={cn('passflow-field-label', isError && 'passflow-field-label--error')}>\n Recovery Code\n </label>\n <input\n id='recovery-code'\n type='text'\n value={code}\n onChange={handleChange}\n placeholder='XXXX-XXXX'\n className={cn(\n 'passflow-field passflow-field--text passflow-field--focused',\n isError && 'passflow-field--error',\n isInputDisabled && 'passflow-field--disabled',\n )}\n autoComplete='off'\n disabled={isInputDisabled}\n />\n {renderErrorContent()}\n </div>\n </div>\n\n {!isInputDisabled && (\n <Button\n size='big'\n type='submit'\n variant='primary'\n disabled={code.length < 8 || isLoading}\n className='passflow-button-signin'\n >\n {isLoading ? 'Verifying...' : 'Verify'}\n </Button>\n )}\n\n {onBack && !isInputDisabled && (\n <div className='passflow-form-actions'>\n <p className='passflow-dont-have-account'>\n Have your device?{' '}\n <Button type='button' size='small' variant='link' onClick={onBack}>\n Use authenticator code\n </Button>\n </p>\n </div>\n )}\n </form>\n </Wrapper>\n );\n};\n","import type { FC, FormEvent } from 'react';\nimport { useId, useState } from 'react';\nimport { Button, FieldOtp, Icon, Switch } from '@/components/ui';\nimport { useTwoFactorVerify } from '@/hooks';\nimport { getUserFriendlyErrorMessage, TwoFactorLoopPrevention } from '@/utils';\nimport { Wrapper } from '../wrapper';\n\nimport '@/styles/index.css';\n\ntype TwoFactorVerifyFormProps = {\n onSuccess?: () => void;\n onUseRecovery?: () => void;\n title?: string;\n subtitle?: string;\n numInputs?: number;\n shouldAutoFocus?: boolean;\n signInPath?: string;\n twoFactorSetupPath?: string;\n /** Label of the \"trust this device\" option, unticked by default. */\n trustDeviceLabel?: string;\n};\n\n/** Only a ticked box asks for trust; an unticked one sends no option at all. */\nconst completionOptions = (trustDevice: boolean) => (trustDevice ? { trustDevice: true } : undefined);\n\nexport const TwoFactorVerifyForm: FC<TwoFactorVerifyFormProps> = ({\n onSuccess,\n onUseRecovery,\n title = 'Two-Factor Authentication',\n subtitle,\n numInputs,\n shouldAutoFocus = true,\n signInPath,\n twoFactorSetupPath,\n trustDeviceLabel = 'Trust this device',\n}) => {\n const [code, setCode] = useState('');\n const [trustDevice, setTrustDevice] = useState(false);\n const { verify, isLoading, isError, errorDetails, reset } = useTwoFactorVerify();\n const otpId = useId();\n const otpErrorId = `${otpId}-error`;\n\n // Get TOTP digits (defaults to 6 if not provided)\n const totpDigits = numInputs ?? 6;\n\n // Compute subtitle dynamically based on totpDigits\n const computedSubtitle = subtitle ?? `Enter the ${totpDigits}-digit code from your authenticator app`;\n\n const handleChange = (value: string) => {\n reset();\n setCode(value);\n };\n\n const handleSubmit = async (e: FormEvent) => {\n e.preventDefault();\n const result = await verify(code, completionOptions(trustDevice));\n if (result) {\n onSuccess?.();\n }\n };\n\n // Auto-submit when code is complete\n const handleOtpChange = async (value: string) => {\n handleChange(value);\n if (value.length === totpDigits) {\n const result = await verify(value, completionOptions(trustDevice));\n if (result) {\n onSuccess?.();\n }\n }\n };\n\n const handleBackToSignIn = () => {\n TwoFactorLoopPrevention.reset();\n window.location.href = signInPath || '/signin';\n };\n\n const handleSetup2FA = () => {\n // Navigate to 2FA setup page\n window.location.href = twoFactorSetupPath || '/two-factor-setup';\n };\n\n // Check if loop detected\n const isLoopDetected = !TwoFactorLoopPrevention.canRedirect();\n\n // Render different UI based on error type\n const renderErrorContent = () => {\n if (!isError || !errorDetails) return null;\n\n // Loop detected - critical error\n if (isLoopDetected) {\n return (\n <div className='passflow-form-error passflow-form-error--critical'>\n <Icon size='medium' id='warning' type='general' className='icon-warning' />\n <div className='passflow-form-error-content'>\n <span id={otpErrorId} className='passflow-form-error-text'>\n {TwoFactorLoopPrevention.getLoopDetectedMessage()}\n </span>\n {signInPath && (\n <Button\n type='button'\n size='medium'\n variant='secondary'\n onClick={handleBackToSignIn}\n className='passflow-button-back-to-signin'\n >\n Back to Sign In\n </Button>\n )}\n </div>\n </div>\n );\n }\n\n // 2FA not enabled - needs setup\n if (errorDetails.type === 'not_enabled') {\n return (\n <div className='passflow-form-error passflow-form-error--persistent'>\n <Icon size='medium' id='warning' type='general' className='icon-warning' />\n <div className='passflow-form-error-content'>\n <span id={otpErrorId} className='passflow-form-error-text'>\n You need to set up two-factor authentication first.\n </span>\n <div className='passflow-form-error-actions'>\n {twoFactorSetupPath && (\n <Button\n type='button'\n size='medium'\n variant='primary'\n onClick={handleSetup2FA}\n className='passflow-button-setup-2fa'\n >\n Set Up 2FA\n </Button>\n )}\n {signInPath && (\n <Button\n type='button'\n size='medium'\n variant='secondary'\n onClick={handleBackToSignIn}\n className='passflow-button-back-to-signin'\n >\n Back to Sign In\n </Button>\n )}\n </div>\n </div>\n </div>\n );\n }\n\n // Expired session - show redirect message\n if (errorDetails.type === 'expired') {\n return (\n <div className='passflow-form-info'>\n <Icon size='small' id='info' type='general' className='icon-info' />\n <span id={otpErrorId} className='passflow-form-info-text'>\n {getUserFriendlyErrorMessage(errorDetails)}\n </span>\n </div>\n );\n }\n\n // Invalid code or generic - allow retry\n return (\n <div className='passflow-form-error'>\n <Icon size='small' id='warning' type='general' className='icon-warning' />\n <span id={otpErrorId} className='passflow-form-error-text'>\n {getUserFriendlyErrorMessage(errorDetails)}\n </span>\n </div>\n );\n };\n\n // Disable input for non-recoverable errors\n const isInputDisabled =\n isLoading || errorDetails?.type === 'not_enabled' || errorDetails?.type === 'expired' || isLoopDetected;\n const otpState = isInputDisabled ? 'disabled' : isError ? 'error' : 'default';\n\n return (\n <Wrapper title={title} subtitle={computedSubtitle} className='passflow-2fa-verify'>\n <form onSubmit={handleSubmit} className='passflow-form'>\n <div className='passflow-form-container'>\n {/* Above the code: the code submits itself on its last digit. */}\n <div className='passflow-form-field'>\n <Switch\n label={trustDeviceLabel}\n checked={trustDevice}\n disabled={isInputDisabled}\n onChange={(event) => setTrustDevice(event.target.checked)}\n />\n </div>\n <div className='passflow-verify-otp-wrapper'>\n <FieldOtp\n id={otpId}\n name='code'\n length={totpDigits}\n value={code}\n onChange={handleOtpChange}\n state={otpState}\n label='Verification code'\n describedBy={isError && errorDetails ? otpErrorId : undefined}\n autoFocus={shouldAutoFocus && !isInputDisabled}\n />\n </div>\n {renderErrorContent()}\n </div>\n\n {!isInputDisabled && (\n <Button\n size='big'\n type='submit'\n variant='primary'\n disabled={code.length !== totpDigits || isLoading}\n className='passflow-button-signin'\n >\n {isLoading ? 'Verifying...' : 'Verify'}\n </Button>\n )}\n\n {onUseRecovery && !isInputDisabled && (\n <div className='passflow-form-actions'>\n <p className='passflow-dont-have-account'>\n Lost your device?{' '}\n <Button type='button' size='small' variant='link' onClick={onUseRecovery}>\n Use recovery code\n </Button>\n </p>\n </div>\n )}\n </form>\n </Wrapper>\n );\n};\n","/**\n * `UpgradeProvider` — the React side of the assurance-upgrade flow (§8.3).\n *\n * It owns the controller (through `passflow.upgrade`), bridges the\n * promise-returning `UpgradePromptHandler` to React state, and mounts the\n * dialog from `src/components/ui/upgrade-dialog`. It selects a state and maps\n * domain data onto that component's props; it renders no UI of its own and\n * styles nothing, per the project's component-library boundary.\n *\n * Three properties fall out of the shipped controller, and they are why this\n * is small:\n *\n * 1. **The wrong-code loop needs no plumbing.** The controller catches the\n * recoverable failure, sets `previousError` and calls `prompt()` again, so\n * the provider simply receives a new request and the dialog re-renders with\n * the error, still open.\n * 2. **Attempt budgeting needs no plumbing.** `maxAttempts` bounds the loop in\n * the controller and then fails the flight, which arrives here as the\n * `exhausted` terminal state.\n * 3. **Passkey has no code field.** `factors[i].input === 'none'` submits with\n * no code and the dialog shows `working` while the platform authenticator\n * runs.\n *\n * **The anti-leak rule is the single most important line in this file.** On\n * unmount, on teardown and on a session change, the pending prompt is resolved\n * `{ type: 'cancel' }`. A dangling `resolve` is an Observer leak wearing a\n * promise: the controller awaits forever, the elevation never settles, and\n * every request that joined the single flight hangs.\n *\n * **The session-change reset.** A challenge is server-bound to the session, so\n * an abandoned flight must never elevate a NEW session. The core discards its\n * controller on `SignIn` / `SignOut`; this provider discards its view of it in\n * the same breath, and the waiter that was mid-flight settles as\n * `session changed`, which the hook reports as `idle` — nothing that did not\n * happen is reported as though it had.\n */\n\nimport {\n type AssuranceBar,\n PassflowEvent,\n type PassflowSubscriber,\n type ReplayPolicy,\n requiredAcrLevel,\n type UpgradeChallenge,\n type UpgradeDiagnosticSink,\n type UpgradeFactor,\n type UpgradeFactorType,\n type UpgradeFlightSummary,\n type UpgradePromptHandler,\n type UpgradePromptResult,\n type UpgradeReplayInfo,\n type Waiter,\n} from '@passflow/core';\nimport { type FC, type ReactElement, type ReactNode, useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport type { UpgradeDialogLabels, UpgradeDialogOutcome, UpgradeDialogProps } from '@/components/ui/upgrade-dialog';\nimport { dialogOutcomeFromError, readAssuranceBar, toDialogState, UpgradeDialog } from '@/components/ui/upgrade-dialog';\nimport {\n UpgradeContext,\n type UpgradeContextValue,\n type UpgradeElevateOptions,\n type UpgradeErrorStatusKind,\n type UpgradeHookState,\n type UpgradePromptView,\n type UpgradeSettledState,\n} from '@/context/upgrade-context';\nimport { usePassflow } from '@/hooks/use-passflow';\nimport { registerUpgradeAuthInstance, upgradeAuthInstance } from '@/utils/upgrade-auth';\n\nexport type UpgradeProviderProps = {\n children?: ReactNode;\n /** Default `true`. `false` installs nothing and leaves the hook inert. */\n enabled?: boolean;\n /**\n * Where the customer's own API is — domain 2 (§13.5). Nothing outside this\n * and Passflow's own API is ever observed, and there is no allow-all opt-in.\n */\n backend?: string | string[];\n /**\n * Patches `globalThis.fetch` through the core's registry. **Off by default**,\n * and a different decision from enabling the UI: one prop for both would\n * bundle \"show me the verification prompt\" with \"patch the global\", and only\n * the second has the blast radius.\n */\n interceptFetch?: boolean;\n /** Requires the RFC 9470 channel. The body is then never read for a challenge. */\n requireChallengeChannel?: 'header';\n /** NARROWING ONLY: `false` excludes an admitted URL; `true` cannot widen. */\n shouldIntercept?: (url: string) => boolean;\n replay?: ReplayPolicy;\n /** The fetch surface's only cancellation option. Default `'resolve-original'`. */\n onCancel?: 'resolve-original' | 'reject';\n onUpgradeDiagnostic?: UpgradeDiagnosticSink;\n factors?: readonly UpgradeFactor[];\n maxAttempts?: number;\n relyingPartyId?: string;\n /** Per-factor wording for the dialog. */\n labels?: UpgradeDialogLabels;\n title?: string;\n /**\n * FR5's render-prop override. It receives the **exact** props the built-in\n * dialog would render — a typed, constrained override with no `className` or\n * `style` leak.\n *\n * It carries the same obligations as the built-in dialog, the selection\n * signal included: the `challenge` state's `onSelectFactor` must be called\n * when the user picks a factor, because that is the only thing that reports\n * §13.2's selection boundary to the controller. An override that never calls\n * it leaves the controller `collecting` for the whole ceremony, so a late\n * join re-ranks mid-entry — degraded, not silent.\n */\n renderDialog?: (props: UpgradeDialogProps) => ReactElement | null;\n};\n\ntype PendingResolve = ((result: UpgradePromptResult) => void) | undefined;\n\n/** §13.3's settlement table, hook column, for a flight that produced no proof. */\nconst errorStateOf = (error: Error): UpgradeSettledState => {\n switch (dialogOutcomeFromError(error)) {\n case 'cancelled':\n case 'session-changed':\n // Cancellation is not a status (§13.3): it is `elevate()` resolving null.\n return { status: 'idle' };\n case 'insufficient':\n return {\n status: 'insufficient',\n obtained: readAssuranceBar((error as { obtained?: unknown }).obtained) ?? {},\n required: readAssuranceBar((error as { required?: unknown }).required) ?? {},\n };\n case 'exhausted':\n return { status: 'error', kind: 'exhausted', error };\n case 'unsatisfiable':\n return { status: 'error', kind: 'unsatisfiable', error };\n case 'unavailable':\n return { status: 'error', kind: 'unavailable', error };\n default:\n return { status: 'error', kind: 'transport' satisfies UpgradeErrorStatusKind, error };\n }\n};\n\nconst summaryError = (summary: UpgradeFlightSummary): Error =>\n summary.error ??\n (summary.proof.status === 'failed' ? summary.proof.reason : undefined) ??\n new Error('The verification flight failed without reporting a reason.');\n\n/** One terminal state per flight, taken from the controller's summary (§13.4). */\nconst summaryToState = (summary: UpgradeFlightSummary): UpgradeSettledState => {\n if (summary.terminal === 'success') return { status: 'success' };\n if (summary.terminal === 'insufficient') {\n return {\n status: 'insufficient',\n obtained: summary.insufficient?.obtained ?? {},\n required: summary.insufficient?.required ?? {},\n };\n }\n return errorStateOf(summaryError(summary));\n};\n\nconst summaryToOutcome = (summary: UpgradeFlightSummary): UpgradeDialogOutcome => {\n if (summary.terminal === 'success') return { kind: 'elevated' };\n if (summary.terminal === 'insufficient') {\n return {\n kind: 'insufficient',\n obtained: summary.insufficient?.obtained ?? {},\n required: summary.insufficient?.required ?? {},\n };\n }\n return { kind: 'failed', error: summaryError(summary) };\n};\n\nconst asError = (value: unknown): Error => (value instanceof Error ? value : new Error(String(value)));\n\nconst statedBar = (options?: UpgradeElevateOptions): AssuranceBar | undefined => {\n if (options === undefined) return undefined;\n const bar = readAssuranceBar({\n acrValues: options.acrValues,\n level: requiredAcrLevel(options.acrValues),\n maxAge: options.maxAge,\n });\n return bar;\n};\n\n/**\n * The imperative seam's challenge. A caller asking for a bar states it here;\n * the parsing of `acrValues` is the core's `requiredAcrLevel`, never a second\n * reading of the ACR list.\n */\nconst imperativeChallenge = (options?: UpgradeElevateOptions): UpgradeChallenge => ({\n acrValues: options?.acrValues,\n requiredLevel: requiredAcrLevel(options?.acrValues),\n maxAge: options?.maxAge,\n status: 403,\n channels: [],\n});\n\n/**\n * Value identity for `factors`, so a fresh array literal with the same factors\n * does not tear down and reinstall the interceptors (H13).\n *\n * The factor TYPE is the identity: everything else on an `UpgradeFactor` is the\n * `assert` implementation, and the registry is keyed by type. A caller who\n * swaps one type's implementation for another keeps the installed one until the\n * type list itself changes — the same trade the `backend` join already makes,\n * and the alternative is an unconditional reinstall on every render.\n */\nconst factorsSignature = (factors?: readonly UpgradeFactor[]): string =>\n factors === undefined ? '\\u0000default' : factors.map((factor) => factor.type).join('\\u0000');\n\n/**\n * Value identity for `replay` (H13). The policy is a union, so each arm gets\n * its own comparable signature:\n *\n * - a mode string compares as itself;\n * - a limits object compares by its two fields;\n * - a PREDICATE compares as the constant `fn`, because a function's identity is\n * never stable across renders. The current closure is reached through a ref\n * and called by a stable proxy, which is the same pattern `shouldIntercept`\n * and `onUpgradeDiagnostic` already use here.\n */\nconst replaySignature = (replay?: ReplayPolicy): string => {\n if (replay === undefined) return 'none';\n if (typeof replay === 'string') return `mode:${replay}`;\n if (typeof replay === 'function') return 'fn';\n return `limits:${replay.maxBodyBytes ?? ''}:${replay.allowStreamingBody ?? ''}`;\n};\n\nexport const UpgradeProvider: FC<UpgradeProviderProps> = ({\n children,\n enabled = true,\n backend,\n interceptFetch = false,\n requireChallengeChannel,\n shouldIntercept,\n replay,\n onCancel,\n onUpgradeDiagnostic,\n factors,\n maxAttempts,\n relyingPartyId,\n labels,\n title,\n renderDialog,\n}) => {\n const passflow = usePassflow();\n\n const [prompt, setPrompt] = useState<UpgradePromptView | null>(null);\n const [state, setState] = useState<UpgradeHookState>({ status: 'idle' });\n const [selectedFactor, setSelectedFactor] = useState<UpgradeFactorType | null>(null);\n const [busy, setBusy] = useState(false);\n const [showAlternatives, setShowAlternatives] = useState(false);\n const [outcome, setOutcome] = useState<UpgradeDialogOutcome | undefined>(undefined);\n const [installed, setInstalled] = useState(false);\n\n /** The open prompt's resolver. Cleared the instant it is used — H3's \"once\". */\n const resolveRef = useRef<PendingResolve>(undefined);\n /** The open request, so the selection signal reaches the controller. */\n const requestRef = useRef<Parameters<UpgradePromptHandler>[0] | null>(null);\n /** Whether this prompt already reported a selection (§13.2 T3 fires once). */\n const reportedSelectionRef = useRef(false);\n /** Set by `cancel()`: the user closed the dialog, so no terminal panel is shown. */\n const userCancelledRef = useRef(false);\n /**\n * H11 — cancellation is STICKY for the rest of the flight.\n *\n * After a submit the prompt's resolver is already spent, so `cancel()` has\n * nothing to answer and the cancellation was simply lost: the flight ran on,\n * and the controller re-prompted the user it had just been told to stop\n * asking. The intent is recorded here and answered at the first boundary the\n * controller offers — its next `prompt()` call — which settles the flight as\n * `UpgradeCancelledError` and so puts every surface on §13.3's asymmetric\n * contract (fetch resolves the untouched 401/403, axios and the imperative\n * seam reject, `useUpgrade().elevate` resolves `null`). Cleared when the\n * flight settles, so it can never leak into the next one.\n *\n * It cannot abort a request already on the wire: the core exposes no abort\n * channel for a round in progress, and inventing one here would be a second\n * lifecycle authority beside the controller (§13.2).\n */\n const cancelRequestedRef = useRef(false);\n\n // Callback props are read through refs so that re-rendering with a new inline\n // closure never tears down and reinstalls the interceptors.\n const shouldInterceptRef = useRef(shouldIntercept);\n const diagnosticRef = useRef(onUpgradeDiagnostic);\n shouldInterceptRef.current = shouldIntercept;\n diagnosticRef.current = onUpgradeDiagnostic;\n\n // H13: `factors` and `replay` are compared by VALUE in the install effect's\n // dependencies (see `factorsSignature` / `replaySignature`) and read through\n // these refs, so an inline array or an inline predicate no longer reinstalls\n // the interceptors on every render. `onCancel` needs neither: it is a string\n // union, so it already compares by value.\n const factorsRef = useRef(factors);\n const replayRef = useRef(replay);\n factorsRef.current = factors;\n replayRef.current = replay;\n\n /**\n * The stable stand-in for a caller-supplied replay PREDICATE. The non-function\n * arms are passed through untouched; this is only ever installed when the\n * policy is a function, and a change of arm changes the signature and\n * reinstalls, which is why the fallback is unreachable rather than a decision.\n */\n const replayPredicate = useCallback((info: UpgradeReplayInfo): boolean => {\n const policy = replayRef.current;\n return typeof policy === 'function' ? policy(info) : true;\n }, []);\n\n /** Resolves a pending prompt exactly once. The anti-leak primitive. */\n const settlePrompt = useCallback((result: UpgradePromptResult): boolean => {\n const resolve = resolveRef.current;\n if (resolve === undefined) return false;\n resolveRef.current = undefined;\n resolve(result);\n return true;\n }, []);\n\n const clearPromptView = useCallback(() => {\n requestRef.current = null;\n reportedSelectionRef.current = false;\n setPrompt(null);\n setSelectedFactor(null);\n setShowAlternatives(false);\n setBusy(false);\n }, []);\n\n const promptHandler = useCallback<UpgradePromptHandler>(\n (request) =>\n new Promise<UpgradePromptResult>((resolve) => {\n // H11: the user cancelled after submitting and the controller came back\n // for another answer. Answer the cancellation instead of re-opening a\n // dialog they already closed.\n if (cancelRequestedRef.current) {\n resolve({ type: 'cancel' });\n return;\n }\n\n // Branch 2's channel (§13.2 T2): the controller pushes a raised bar and\n // a re-ranked list into the OPEN prompt, which updates without\n // resolving. Subscribed synchronously, before anything is awaited.\n request.onRequirementRaised = (next) => {\n setPrompt({ challenge: next.challenge, factors: next.factors, previousError: request.previousError });\n setState({ status: 'challenged', challenge: next.challenge, factors: next.factors.map((f) => f.type) });\n };\n\n resolveRef.current = resolve;\n requestRef.current = request;\n reportedSelectionRef.current = false;\n userCancelledRef.current = false;\n setOutcome(undefined);\n setSelectedFactor(null);\n setShowAlternatives(false);\n setBusy(false);\n setPrompt({ challenge: request.challenge, factors: request.factors, previousError: request.previousError });\n setState({\n status: 'challenged',\n challenge: request.challenge,\n factors: request.factors.map((factor) => factor.type),\n });\n }),\n [],\n );\n\n const handleFlightSettled = useCallback(\n (summary: UpgradeFlightSummary) => {\n cancelRequestedRef.current = false;\n setState(summaryToState(summary));\n setOutcome(userCancelledRef.current ? undefined : summaryToOutcome(summary));\n clearPromptView();\n },\n [clearPromptView],\n );\n\n useEffect(() => {\n if (!enabled) {\n setInstalled(false);\n return;\n }\n\n const teardown = passflow.upgrade.enable({\n prompt: promptHandler,\n backend,\n interceptFetch,\n requireChallengeChannel,\n shouldIntercept: shouldIntercept === undefined ? undefined : (url) => shouldInterceptRef.current?.(url) !== false,\n replay: typeof replayRef.current === 'function' ? replayPredicate : replayRef.current,\n onCancel,\n onUpgradeDiagnostic: onUpgradeDiagnostic === undefined ? undefined : (d) => diagnosticRef.current?.(d),\n factors: factorsRef.current,\n maxAttempts,\n relyingPartyId,\n onFlightSettled: handleFlightSettled,\n });\n setInstalled(true);\n\n return () => {\n // The anti-leak rule: never leave the controller awaiting an answer.\n settlePrompt({ type: 'cancel' });\n teardown();\n setInstalled(false);\n };\n // `backend` is compared by value so a fresh array literal does not reinstall.\n }, [\n passflow,\n enabled,\n Array.isArray(backend) ? backend.join('\\u0000') : backend,\n interceptFetch,\n requireChallengeChannel,\n shouldIntercept === undefined,\n onUpgradeDiagnostic === undefined,\n // H13: compared by value, never by identity — an inline policy object, an\n // inline predicate or a fresh factor array must not reinstall.\n replaySignature(replay),\n replayPredicate,\n onCancel,\n factorsSignature(factors),\n maxAttempts,\n relyingPartyId,\n promptHandler,\n handleFlightSettled,\n settlePrompt,\n ]);\n\n /**\n * Publishes this provider's instance to the free-function adapters, twice,\n * for two different reasons — and both are load-bearing.\n *\n * **The render-phase write** exists because React runs a child's effects\n * before the parent's in the same commit, so the documented\n * `useEffect(() => attachAuth(api), [])` in a child would otherwise reach\n * `requireInstance` with nothing registered and throw — and a throw inside an\n * effect unmounts the tree. Publishing in render makes attach order\n * irrelevant. It is guarded and idempotent, so a re-render or a discarded\n * Strict-Mode render changes nothing.\n *\n * **The effect re-registers and releases through the same call**, so the pair\n * is symmetric: `registerUpgradeAuthInstance` returns the release for its own\n * registration, and that release is deferred by a microtask and cancelled by\n * any registration in the meantime (see `utils/upgrade-auth`). React Strict\n * Mode mounts, unmounts and remounts effects in development, and a cleanup\n * that released immediately would leave the registry empty for the remount —\n * render does not run again, and the child-before-parent effect order holds\n * on the remount pass as well, so the re-registration here cannot be early\n * enough on its own. Measured, not assumed: with an immediate release the\n * remounting child's `attachAuth` throws.\n *\n * A ref cannot be the publication channel, which is why this is not the ref\n * shape: the free functions are bare module imports called by code that never\n * sees this component's context or refs, so the module-level registry is the\n * only channel children can read.\n */\n if (upgradeAuthInstance() !== passflow) registerUpgradeAuthInstance(passflow);\n useEffect(() => registerUpgradeAuthInstance(passflow), [passflow]);\n\n /**\n * The session-change reset. The core discards its controller here; the view\n * of it must go with it, or a dialog from the old session would collect an\n * answer that can only elevate the new one.\n */\n useEffect(() => {\n const subscriber: PassflowSubscriber = {\n onAuthChange: () => {\n cancelRequestedRef.current = false;\n settlePrompt({ type: 'cancel' });\n clearPromptView();\n setOutcome(undefined);\n setState({ status: 'idle' });\n },\n };\n const events = [PassflowEvent.SignIn, PassflowEvent.SignOut];\n passflow.subscribe(subscriber, events);\n return () => passflow.unsubscribe(subscriber, events);\n }, [passflow, settlePrompt, clearPromptView]);\n\n const selectFactor = useCallback((factor: UpgradeFactorType) => {\n setSelectedFactor(factor);\n // §13.2 T3: the selection boundary, reported before any answer is\n // submitted. `selected` is defined off this call and off nothing else.\n requestRef.current?.onFactorSelected(factor);\n reportedSelectionRef.current = true;\n }, []);\n\n const submit = useCallback(\n (code?: string) => {\n const request = requestRef.current;\n if (request === null || resolveRef.current === undefined) return;\n const factor = selectedFactor ?? request.factors[0]?.type;\n if (factor === undefined) return;\n if (!reportedSelectionRef.current) {\n // A submit that skipped the picker still selected a factor — the\n // suggested one — and the controller must hear it before the ceremony.\n request.onFactorSelected(factor);\n reportedSelectionRef.current = true;\n }\n setBusy(true);\n setState({ status: 'submitting' });\n settlePrompt({ type: 'submit', factor, code });\n },\n [selectedFactor, settlePrompt],\n );\n\n const cancel = useCallback(() => {\n userCancelledRef.current = true;\n cancelRequestedRef.current = true;\n if (!settlePrompt({ type: 'cancel' })) {\n // Nothing was pending: either a terminal panel is on screen, or an answer\n // is in flight. Close it either way — the sticky flag answers the\n // controller's next prompt, and leaving a busy dialog open would ask the\n // user to wait for a flight they have abandoned.\n setOutcome(undefined);\n }\n clearPromptView();\n setState({ status: 'idle' });\n }, [settlePrompt, clearPromptView]);\n\n const dismiss = useCallback(() => {\n setOutcome(undefined);\n }, []);\n\n const toggleAlternatives = useCallback(() => {\n setShowAlternatives((shown) => !shown);\n }, []);\n\n const elevate = useCallback(\n async (options?: UpgradeElevateOptions): Promise<UpgradeSettledState | null> => {\n const requested = statedBar(options);\n const waiter: Waiter = requested === undefined ? { kind: 'imperative' } : { kind: 'imperative', requested };\n try {\n await passflow.upgrade.elevate(imperativeChallenge(options), waiter);\n return { status: 'success' };\n } catch (error) {\n // The one surface where cancellation resolves `null`: there the\n // cancellation IS the whole value (§13.3).\n if (dialogOutcomeFromError(error) === 'cancelled') return null;\n return errorStateOf(asError(error));\n }\n },\n [passflow],\n );\n\n const value = useMemo<UpgradeContextValue>(\n () => ({\n enabled: enabled && installed,\n state,\n prompt,\n selectedFactor,\n selectFactor,\n submit,\n cancel,\n dismiss,\n elevate,\n }),\n [enabled, installed, state, prompt, selectedFactor, selectFactor, submit, cancel, dismiss, elevate],\n );\n\n const dialogState = toDialogState({\n prompt:\n prompt === null ? null : { challenge: prompt.challenge, factors: prompt.factors, previousError: prompt.previousError },\n outcome,\n ui: { selected: selectedFactor, busy, showAlternatives },\n labels,\n handlers: {\n onSelectFactor: selectFactor,\n onToggleAlternatives: toggleAlternatives,\n onSubmit: submit,\n onCancel: cancel,\n onDismiss: dismiss,\n },\n });\n\n const dialogProps: UpgradeDialogProps = {\n open: prompt !== null || outcome !== undefined,\n title,\n state: dialogState,\n };\n\n return (\n <UpgradeContext.Provider value={value}>\n {children}\n {/* Mounted after `children` so it overlays them. */}\n {renderDialog === undefined ? <UpgradeDialog {...dialogProps} /> : renderDialog(dialogProps)}\n </UpgradeContext.Provider>\n );\n};\n","import { FETCH_PRIORITY_OIDC, Passflow, type PassflowConfig, registerFetchMiddleware } from '@passflow/core';\nimport React, { type FC, type ReactNode, useCallback, useEffect, useMemo, useReducer, useRef, useState } from 'react';\nimport { UpgradeProvider, type UpgradeProviderProps } from '@/components/provider/upgrade-provider';\nimport { ContinuingStatus } from '@/components/ui/continuing-status';\nimport {\n AuthProvider,\n defaultNavigate,\n initialState,\n type NavigateFunction,\n NavigationContext,\n PassflowContext,\n passflowReducer,\n type RouterType,\n routes,\n} from '@/context';\nimport { urlCarriesTwoFactorToken } from '@/utils/second-factor';\nimport '@/styles/index.css';\n\n/**\n * The assurance-upgrade options a consumer may set on `PassflowProvider`.\n *\n * `children`, `enabled` and `backend` are owned by `PassflowProvider` itself:\n * `backend` is a top-level prop (§13.5 — \"where your API is\" is the headline\n * act, not a nested detail) and `enabled` is derived from `upgrade`/`backend`\n * below, so there is exactly one source for each.\n */\nexport type PassflowUpgradeOptions = Omit<UpgradeProviderProps, 'children' | 'enabled' | 'backend'>;\n\ntype PassflowProviderProps = PassflowConfig & {\n children: ReactNode;\n navigate?: NavigateFunction;\n router?: RouterType;\n /**\n * Where the customer's own API is — domain 2 of §13.5's two-domain\n * interception model. Nothing outside this and Passflow's own API is ever\n * observed, and there is no allow-all opt-in. `string | string[]`, an origin\n * or a same-origin path prefix (`'/api'`).\n */\n backend?: string | string[];\n /**\n * Automatic assurance upgrade (step-up). `undefined` ⇒ **off**, so no\n * existing consumer changes behaviour on upgrade. `true` ⇒ on with\n * defaults; an object ⇒ on with those options; `false` ⇒ off even when\n * `backend` is declared.\n *\n * Declaring `backend` also turns it on: naming where your API is has no\n * other meaning, and §13.5's acceptance configuration is `backend` plus one\n * attached client. The global `window.fetch` patch is a separate, explicit\n * act (`upgrade={{ interceptFetch: true }}`) and stays off by default.\n */\n upgrade?: boolean | PassflowUpgradeOptions;\n /**\n * Where to send a sign-in that lands on this page owing its second factor:\n * a federated redirect on a non-PKCE app comes back with `#tfa_token=` and\n * no tokens. A mounted `PassflowFlow` registers its own (prefixed) route,\n * which wins; set this when the landing page renders no flow, or the flow\n * is mounted elsewhere. Defaults to `routes.two_factor_verify.path`.\n */\n twoFactorVerifyPath?: string;\n};\n\n/**\n * Passflow auth-endpoint regex used by the OIDC interceptor below.\n * Matches every endpoint that takes credentials + an optional\n * parent_challenge_id so the SDK can inject the parent on outbound\n * POSTs and follow `redirect_url` on responses.\n *\n * The set is canonical with the server's AuthFlow dispatcher; if a\n * new credential endpoint lands server-side, it must be added here.\n *\n * - /auth/login — password login\n * - /auth/register — password sign-up\n * - /auth/passwordless/* — OTP / magic-link start+complete\n * - /auth/passkey/* — passkey registration/auth\n * - /auth/2fa/* — second-factor verify\n * - /auth/federated/start — federated start (callback is server)\n * - /auth/session/exchange — RFC 8693-style session exchange\n * (ADR-2; activated on Leg 2 of\n * OIDC two-step flows)\n */\nexport const AUTH_ENDPOINT_PATTERN =\n /\\/auth\\/(login|register|passwordless|passkey|2fa|session\\/exchange)\\b|\\/auth\\/federated\\/start\\b/;\n\n/**\n * Read `parent_challenge_id` from the current URL's query string.\n * Returns `undefined` when not present so callers can short-circuit\n * the OIDC interceptor on non-OIDC mounts.\n *\n * Lowercases only the parameter KEYS (not values) so the\n * KSUID-shaped value isn't corrupted on the way through. (URL params\n * are case-sensitive per RFC 3986; some Passflow URLs use mixed\n * case like `appId=...`. The lowercase-keys treatment mirrors what\n * the bundled login-app was doing pre-SDK-migration.)\n */\nexport const readParentChallengeIdFromURL = (): string | undefined => {\n if (typeof window === 'undefined') return undefined;\n const raw = new URLSearchParams(window.location.search);\n // Lowercase only keys, preserve values (values are often\n // case-sensitive — KSUIDs, JWTs, OIDC state, etc.).\n const lower = new URLSearchParams(Array.from(raw, ([key, value]) => [key.toLowerCase(), value]));\n const value = lower.get('parent_challenge_id');\n return value || undefined;\n};\n\n// Captured at module evaluation — before React mounts and before any\n// consumer-side router can rewrite the URL. The provider's mount-time\n// read stays primary (a consumer could mount the SDK long after boot,\n// on a different URL); this is the fallback that makes the OIDC opt-in\n// immune to mount-vs-navigation timing. Observed in the field: the\n// OIDF conformance login intermittently proceeded as a plain\n// first-party login (tokens in the response, no redirect_url) because\n// the whole OIDC layer keyed off a single mount-time read.\nconst bootParentChallengeId = readParentChallengeIdFromURL();\n\n/**\n * The RFC 8628 device verification page (`/oidc/device`) is the ONE auth surface\n * that must never silently exchange an existing session. A device grant is\n * approved only through the explicit authenticate → user_code confirmation →\n * approve path (see `useDeviceVerify` + src/web/oidc/device_verify.go). Letting\n * the exchange-on-mount probe solve a device parent would approve a grant with\n * no §5.4 code check — the STORM-2372 device-code phishing attack. The server\n * now refuses this at `/auth/session/exchange` too; this is the client half of\n * the same guard, so the probe never even fires here.\n */\nconst isDeviceVerificationURL = (): boolean => typeof window !== 'undefined' && window.location.pathname === '/oidc/device';\n\n/**\n * Set once the OIDC interceptor has started following a server-issued\n * `redirect_url`. Module-level on purpose: it is read by the credential forms,\n * which are siblings of the provider rather than children of a context it could\n * publish through, and its lifetime is exactly one page — the navigation it\n * records is what ends that page.\n */\nlet oidcRedirectFollowed = false;\n\n/**\n * Has the OIDC interceptor already taken ownership of the post-login navigation?\n *\n * A credential form MUST NOT navigate after a successful login when this is\n * true. Two navigations do not queue — the second cancels the first, and the\n * first is the one that completes the OIDC flow:\n *\n * 1. The interceptor calls `window.location.assign(redirect_url)` to hand the\n * authorization code back to the RP (a CLI's `127.0.0.1:<port>/callback`,\n * a web RP's `redirect_uri`, …).\n * 2. `window.location.assign` does not halt script execution, so the form's\n * success handler keeps running and sets `window.location.href` to the\n * app's default post-login page.\n * 3. The browser drops the in-flight request from (1) and goes to (2).\n *\n * Whether (1) has already been delivered when (2) lands is pure scheduling, so\n * this presents as a flake rather than a clean break. Measured against the CLI\n * loopback flow (RFC 8252 §7.3): roughly a third of real browser sign-ins had\n * the GET to the CLI's loopback port aborted mid-flight, and the CLI then sat\n * waiting for a callback that had already been cancelled until it timed out.\n */\nexport const hasFollowedOIDCRedirect = (): boolean => oidcRedirectFollowed;\n\n/**\n * Install the global OIDC AuthFlow interceptor on `fetch` and\n * `XMLHttpRequest`. The interceptor:\n *\n * 1. Injects `parent_challenge_id` on every Passflow auth POST\n * body (when one is present on the SDK's host URL).\n * 2. Watches Passflow auth responses for a JSON\n * `{ redirect_url: \"...\" }` and, when present, calls\n * `window.location.assign(redirect_url)` to follow the\n * server-side dispatch.\n *\n * Why both fetch and XHR: `@passflow/core` uses axios, which on the\n * browser delegates to XMLHttpRequest. Other consumer code (and the\n * SDK's own `/oidc/requests/{id}` GET) uses fetch. Patching both\n * keeps the interceptor uniform.\n *\n * No-op when `parent_challenge_id` is absent from the URL.\n *\n * Implementation note: previously this hook lived in the bundled\n * login-app at `login-app/src/App.tsx::useAuthFlowInterceptor`.\n * Moved into the SDK so any Passflow consumer that mounts\n * `<PassflowProvider>` gets full OIDC RP integration automatically.\n */\nconst useOIDCInterceptor = (parentChallengeId: string | undefined): void => {\n useEffect(() => {\n if (!parentChallengeId || typeof window === 'undefined') {\n return;\n }\n\n const isAuthURL = (url: string): boolean => AUTH_ENDPOINT_PATTERN.test(url);\n\n const injectParentChallenge = (raw: string | null | undefined): string | undefined => {\n if (!raw) return undefined;\n try {\n const obj = JSON.parse(raw) as Record<string, unknown>;\n if ('parent_challenge_id' in obj) return undefined;\n obj.parent_challenge_id = parentChallengeId;\n return JSON.stringify(obj);\n } catch {\n return undefined;\n }\n };\n\n const followRedirectURL = (raw: string | null | undefined): void => {\n if (!raw) return;\n try {\n const obj = JSON.parse(raw) as { redirect_url?: unknown };\n if (typeof obj.redirect_url === 'string' && obj.redirect_url) {\n // Claim the navigation BEFORE starting it. `assign` does not stop\n // JavaScript: the credential form's own success handler runs right\n // after this and would otherwise navigate on top of us. See\n // `hasFollowedOIDCRedirect` for why that is fatal, not cosmetic.\n oidcRedirectFollowed = true;\n window.location.assign(obj.redirect_url);\n }\n } catch {\n // Non-JSON — ignore.\n }\n };\n\n // fetch() interceptor (covers code paths that use the platform fetch API).\n //\n // Installed through the core's fetch registry rather than by assigning\n // `window.fetch` here. Two features that each capture and restore the\n // global compose as `A(B(native))`, and whichever cleanup runs first\n // restores a fetch that predates the other patch — so one interceptor\n // disappears non-deterministically (architecture §13.5, \"the OIDC\n // collision: 'untouched' is withdrawn\"). The registry owns the single\n // patch, reference-counts it, and never restores over a foreign patch.\n //\n // Priority matters behaviourally: OIDC is the OUTER layer\n // (`FETCH_PRIORITY_OIDC` = 10, outside `FETCH_PRIORITY_UPGRADE` = 20) so it\n // still observes the response the caller actually receives — including a\n // replayed one — which is what it reads `redirect_url` from. The logic\n // below is unchanged from the hand-rolled patch: `next` stands exactly\n // where the captured `originalFetch` stood.\n const unregisterFetchMiddleware = registerFetchMiddleware(\n async (next, input, init) => {\n let url = '';\n if (typeof input === 'string') url = input;\n else if (input instanceof URL) url = input.toString();\n else if (input instanceof Request) url = input.url;\n\n const method = init?.method?.toUpperCase() ?? 'GET';\n let outInit = init;\n if (method === 'POST' && isAuthURL(url) && typeof init?.body === 'string') {\n const rewritten = injectParentChallenge(init.body);\n if (rewritten !== undefined) outInit = { ...init, body: rewritten };\n }\n\n const response = await next(input, outInit);\n\n if (response.ok && isAuthURL(url)) {\n try {\n const cloned = response.clone();\n const text = await cloned.text();\n followRedirectURL(text);\n } catch {\n // ignore\n }\n }\n\n return response;\n },\n { priority: FETCH_PRIORITY_OIDC, name: 'passflow-oidc-authflow' },\n );\n\n // XMLHttpRequest interceptor — `@passflow/core` uses axios, which in\n // the browser uses XHR under the hood. The fetch interceptor above\n // does NOT catch those calls.\n const OriginalXHROpen = XMLHttpRequest.prototype.open;\n const OriginalXHRSend = XMLHttpRequest.prototype.send;\n\n type XHRTracker = { method?: string; url?: string; isAuth?: boolean };\n const tracker = new WeakMap<XMLHttpRequest, XHRTracker>();\n\n XMLHttpRequest.prototype.open = function (\n this: XMLHttpRequest,\n method: string,\n url: string | URL,\n ...rest: unknown[]\n ): void {\n const urlStr = typeof url === 'string' ? url : url.toString();\n tracker.set(this, {\n method: method?.toUpperCase(),\n url: urlStr,\n isAuth: isAuthURL(urlStr),\n });\n this.addEventListener('load', () => {\n const meta = tracker.get(this);\n if (!meta?.isAuth) return;\n if (this.status >= 200 && this.status < 300) {\n // Server returns 200 + JSON body { redirect_url: \"...\" } when\n // an AuthFlow parent (OIDC, federated, future upgrade) needs\n // the SPA to navigate. See ADR-2.\n followRedirectURL(typeof this.responseText === 'string' ? this.responseText : null);\n }\n });\n // @ts-expect-error spread into open's varargs signature\n OriginalXHROpen.call(this, method, url, ...rest);\n };\n\n XMLHttpRequest.prototype.send = function (this: XMLHttpRequest, body?: Document | XMLHttpRequestBodyInit | null): void {\n const meta = tracker.get(this);\n let outBody: Document | XMLHttpRequestBodyInit | null | undefined = body;\n if (meta?.isAuth && meta.method === 'POST' && typeof body === 'string') {\n const rewritten = injectParentChallenge(body);\n if (rewritten !== undefined) outBody = rewritten;\n }\n OriginalXHRSend.call(this, outBody as Document | XMLHttpRequestBodyInit | null);\n };\n\n return () => {\n // Fetch teardown is the registry's: it removes the one patch on the last\n // registration's removal and declines to restore over a stranger's patch.\n // Nothing here captures or restores `window.fetch`.\n unregisterFetchMiddleware();\n XMLHttpRequest.prototype.open = OriginalXHROpen;\n XMLHttpRequest.prototype.send = OriginalXHRSend;\n };\n }, [parentChallengeId]);\n};\n\n/**\n * Parent-challenge metadata returned by GET /oidc/requests/{id}.\n * Subset used by the SDK's exchange-on-mount probe.\n */\ntype ParentChallengeMeta = {\n request_id: string;\n app_name?: string;\n client_id?: string;\n redirect_uri?: string;\n state?: string;\n response_mode?: string;\n // Server-side fields the SDK consults to decide whether to render\n // the login form vs auto-exchange. The OP at /oidc/authorize is\n // stateless (cookie-blind by design — see ADR-2); the SDK enforces\n // prompt directives because the SDK holds the session.\n oidc_prompt_login?: boolean;\n oidc_prompt_none?: boolean;\n max_age?: number;\n};\n\n/**\n * Token-exchange-on-mount probe per ADR-2 Leg 2. When a parent\n * challenge is present in the URL AND the SDK has an existing\n * session AND the parent allows exchange (no `prompt=login`,\n * `max_age` not exceeded), POST the access token to\n * /auth/session/exchange so the OP can issue a fresh authorization\n * code for the RP without re-prompting the user.\n *\n * Decision-making is the SDK's; the server enforces too (defence in\n * depth — see `auth_util.EvaluatePolicy`).\n *\n * Today the response branches are:\n *\n * - 200 { redirect_url } → the interceptor's fetch wrapper follows\n * the redirect (sole owner of redirect_url navigation; this hook\n * must never navigate on OK responses — see the res.ok branch).\n * - 403 { error: \"upgrade_required\", ... } → falls through to the\n * login form. Factor elevation on an existing session is\n * `UpgradeProvider`'s flow, not this probe's.\n * - 401 → clear stale tokens, fall through to login form.\n *\n * On any decision-point that ends with \"render login form,\" the\n * SDK consumer's existing PassflowFlow render path picks up\n * naturally.\n */\n/**\n * `'upgrade_required'` is vestigial and kept deliberately (§8.4): it is\n * unreachable today — the 403 branch below sets `'fallback_to_login'` — and\n * removing a member from an exported union would be a type-level breaking\n * change for anyone reading `OIDCExchangeContextValue`. Assurance elevation is\n * now `UpgradeProvider`'s job, not a placeholder's.\n */\ntype ExchangeState = 'idle' | 'exchanging' | 'upgrade_required' | 'fallback_to_login';\n\nconst useSessionExchangeOnMount = (\n parentChallengeId: string | undefined,\n passflow: Passflow,\n baseUrl: string | undefined,\n appId: string | undefined,\n): { exchangeState: ExchangeState; parentMeta?: ParentChallengeMeta } => {\n const [exchangeState, setExchangeState] = useState<ExchangeState>('idle');\n const [parentMeta, setParentMeta] = useState<ParentChallengeMeta | undefined>(undefined);\n const attemptedRef = useRef(false);\n\n useEffect(() => {\n if (!parentChallengeId || attemptedRef.current) {\n return;\n }\n // Never auto-exchange on the device verification page — that would approve\n // a device grant with no user_code check (see isDeviceVerificationURL).\n if (isDeviceVerificationURL()) {\n return;\n }\n // Wait until appId has been discovered before attempting the\n // exchange — otherwise the request 400s on \"Application ID is\n // missing from request\".\n if (!appId) {\n return;\n }\n attemptedRef.current = true;\n\n const run = async () => {\n // Fetch parent metadata upfront — we need OIDC `prompt` /\n // `max_age` directives to make the right decision regardless\n // of session state.\n let meta: ParentChallengeMeta | undefined;\n try {\n const base = baseUrl ?? '';\n const url = `${base}/oidc/requests/${encodeURIComponent(parentChallengeId)}`;\n const res = await fetch(url);\n if (res.ok) {\n meta = (await res.json()) as ParentChallengeMeta;\n setParentMeta(meta);\n }\n } catch {\n // Network error fetching parent → fall through to login form;\n // the user's POST will fail loudly enough.\n }\n\n // prompt=login on parent → render login form with banner.\n // The login interceptor will pick up parent_challenge_id and\n // dispatch normally. (Check this BEFORE attempting exchange —\n // even with a session, prompt=login means we must re-prompt.)\n if (meta?.oidc_prompt_login) {\n setExchangeState('fallback_to_login');\n return;\n }\n\n // max_age check: if parent set max_age, compare against the SDK's\n // known auth_time on the access token. When the access token's\n // auth_time is older than max_age (in seconds), the parent\n // demands re-auth.\n if (meta?.max_age && meta.max_age > 0) {\n const parsed = passflow.getParsedTokens?.();\n const accessPayload = parsed?.access_token?.payload as { auth_time?: number } | undefined;\n const idPayload = parsed?.id_token?.payload as { auth_time?: number } | undefined;\n const authTime = accessPayload?.auth_time ?? idPayload?.auth_time;\n if (authTime && typeof authTime === 'number') {\n const ageSeconds = Math.floor(Date.now() / 1000) - authTime;\n if (ageSeconds > meta.max_age) {\n setExchangeState('fallback_to_login');\n return;\n }\n }\n }\n\n // Attempt exchange. Use credentials: 'include' so the cookie-mode\n // access token (HttpOnly) accompanies the request even when the\n // SDK has no token in localStorage. Server's middleware.Token\n // falls back from Authorization header to cookie automatically.\n //\n // We always attempt the exchange (don't gate on isAuthenticated()\n // because in cookie mode the SDK can't see the HttpOnly access\n // token — the server is the authority). If the server returns 401\n // we know there's no session and we fall through to login.\n setExchangeState('exchanging');\n try {\n let accessToken: string | undefined;\n try {\n const tokens = await passflow.getTokens(false);\n accessToken = tokens?.access_token;\n } catch {\n // No token in SDK storage — that's OK for cookie mode; the\n // server will read from cookie. We still call /auth/session/\n // exchange and let the server's token middleware decide.\n }\n const base = baseUrl ?? '';\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n };\n if (accessToken) {\n headers.Authorization = `Bearer ${accessToken}`;\n }\n if (appId) {\n // App middleware reads X-Passflow-ClientID; without it the\n // request gets 400 \"Application ID is missing from request\".\n headers['X-Passflow-ClientID'] = appId;\n }\n const res = await fetch(`${base}/auth/session/exchange`, {\n method: 'POST',\n credentials: 'include',\n headers,\n body: JSON.stringify({ parent_challenge_id: parentChallengeId }),\n });\n if (res.ok) {\n // Redirect-following for OK auth responses is owned SOLELY\n // by useOIDCInterceptor's fetch wrapper (this request\n // matches AUTH_ENDPOINT_PATTERN, and the wrapper follows\n // redirect_url before handing the response back to us).\n // Do NOT navigate here as well: window.location.assign()\n // doesn't halt script, so a second assign races the first\n // and re-presents the single-use authorization code to the\n // RP — observed as duplicate callback hits in OIDF\n // conformance (oidcc-id-token-hint INTERRUPTED).\n // We parse the body only to decide the no-redirect branch.\n try {\n const body = (await res.json()) as { redirect_url?: string };\n if (body.redirect_url) {\n // Interceptor navigation is already scheduled; stay in\n // 'exchanging' so no login UI flashes while we leave.\n return;\n }\n } catch {\n // ignore\n }\n // Successful but no redirect — unusual. Fall through.\n setExchangeState('fallback_to_login');\n return;\n }\n if (res.status === 403) {\n // upgrade_required. The server's MaxAge enforcement (Subtask D\n // partial) triggers this on max_age-exceeded sessions; the SDK\n // should render the login form to let the user re-auth. Factor\n // elevation on a live session is handled by `UpgradeProvider`\n // (architecture §13), which replaced the old placeholder.\n setExchangeState('fallback_to_login');\n return;\n }\n if (res.status === 401 || res.status === 400) {\n // No valid session. For prompt=none, OIDC requires us to\n // route the user back to the RP with error=login_required\n // WITHOUT rendering an interactive login form. For other\n // cases, fall through to the login form. We intentionally\n // do NOT call passflow.logOut() here — clearing cookies\n // here would also clear any session that exists but wasn't\n // visible to the SDK due to the cookie-mode HttpOnly\n // constraint; the user would lose their session for a\n // failed exchange that's the SDK's fault, not theirs.\n if (meta?.oidc_prompt_none && meta.redirect_uri) {\n const dest = new URL(meta.redirect_uri);\n dest.searchParams.set('error', 'login_required');\n dest.searchParams.set('error_description', 'user is not authenticated');\n if (meta.state) dest.searchParams.set('state', meta.state);\n window.location.assign(dest.toString());\n return;\n }\n setExchangeState('fallback_to_login');\n return;\n }\n setExchangeState('fallback_to_login');\n } catch {\n setExchangeState('fallback_to_login');\n }\n };\n\n void run();\n }, [parentChallengeId, passflow, baseUrl, appId]);\n\n return { exchangeState, parentMeta };\n};\n\n/**\n * Context surface exposed to children so the SDK's own components\n * (or consumer code) can read the OIDC parent-challenge state.\n */\nexport type OIDCExchangeContextValue = {\n parentChallengeId?: string;\n parentMeta?: ParentChallengeMeta;\n exchangeState: ExchangeState;\n};\n\n/**\n * Sends a landing that owes its second factor to the 2FA screen.\n *\n * A federated sign-in on a non-PKCE app comes back to its redirect URL with\n * the 2FA token in the fragment and no tokens. Core adopts it as it is\n * constructed (`parseQueryParams`, on by default) and strips the fragment;\n * with that off, the token is adopted here through `handleTokensRedirect()`.\n *\n * The navigation runs one render after mount, not in the mount effect: the\n * flow's router and its 2FA route register themselves in their own mount\n * effects, which run before this one, and their state lands in the next\n * render. Navigating at mount would go through the default full-page\n * navigation to the unprefixed route.\n */\nconst useSecondFactorLanding = (\n landedWithTwoFactorToken: boolean,\n passflow: Passflow,\n navigate: NavigateFunction,\n twoFactorVerifyPath: string,\n) => {\n const [pending, setPending] = useState(false);\n\n // Once, on mount — the landing is a property of the page load.\n useEffect(() => {\n if (!landedWithTwoFactorToken) return;\n // A signed-in user owes no factor: a `#tfa_token=` link is not theirs to answer.\n if (passflow.isAuthenticated()) return;\n if (!passflow.isTwoFactorVerificationRequired()) passflow.handleTokensRedirect();\n if (passflow.isTwoFactorVerificationRequired()) setPending(true);\n }, []);\n\n useEffect(() => {\n if (!pending) return;\n setPending(false);\n navigate({ to: twoFactorVerifyPath, replace: true });\n }, [pending, navigate, twoFactorVerifyPath]);\n};\n\nexport const OIDCExchangeContext = React.createContext<OIDCExchangeContextValue>({\n exchangeState: 'idle',\n});\n\nexport const PassflowProvider: FC<PassflowProviderProps> = ({\n children,\n navigate: initialNavigate,\n router = 'default',\n backend,\n upgrade,\n twoFactorVerifyPath,\n // `backend` and `upgrade` are destructured out on purpose: they are\n // interception policy, not client-wide configuration, and §13.5 keeps them\n // off `PassflowConfig` — which is what `config` is spread into below.\n ...config\n}) => {\n // If appId is not provided, set isDiscoveringAppId to true to signal\n // that auto-discovery should happen (prevents showing error before discovery)\n const needsDiscovery = !config.appId;\n\n const [state, dispatch] = useReducer(passflowReducer, {\n ...initialState,\n ...config,\n isDiscoveringAppId: needsDiscovery,\n });\n\n const [navigate, setNavigate] = useState<NavigateFunction>(() => {\n if (initialNavigate) {\n return initialNavigate;\n }\n return defaultNavigate;\n });\n\n // Read before core is constructed: core adopts `#tfa_token=` and strips it.\n const [landedWithTwoFactorToken] = useState(urlCarriesTwoFactorToken);\n\n const passflow = useMemo(() => new Passflow(state), [state]);\n\n // OIDC AuthFlow integration: the interceptor injects\n // parent_challenge_id on outbound auth POSTs + follows\n // server-returned redirect_url; the exchange-on-mount probe decides\n // whether to render login form vs auto-exchange. See ADR-2.\n const parentChallengeId = useMemo(() => readParentChallengeIdFromURL() ?? bootParentChallengeId, []);\n useOIDCInterceptor(parentChallengeId);\n const { exchangeState, parentMeta } = useSessionExchangeOnMount(parentChallengeId, passflow, config.url, state.appId);\n\n // Auto-discover appId from /settings endpoint if not provided\n const discoveryAttemptedRef = useRef(false);\n useEffect(() => {\n if (needsDiscovery && !discoveryAttemptedRef.current && state.isDiscoveringAppId) {\n discoveryAttemptedRef.current = true;\n\n const discoverAppId = async () => {\n // Try relative path first (works with dev server proxy and same-origin production)\n // Then fall back to absolute URL if configured\n const urlsToTry = ['/settings'];\n if (config.url) {\n urlsToTry.push(`${config.url}/settings`);\n }\n\n for (const url of urlsToTry) {\n try {\n const response = await fetch(url);\n if (response.ok) {\n const settings = await response.json();\n const discoveredAppId = settings.login_app?.app_id || settings.appId;\n\n if (discoveredAppId) {\n passflow.setAppId(discoveredAppId);\n dispatch({\n type: 'SET_PASSFLOW_STATE',\n payload: {\n ...state,\n appId: discoveredAppId,\n scopes: settings.login_app?.scopes || settings.scopes || state.scopes,\n createTenantForNewUser:\n settings.login_app?.create_tenant_for_new_user ??\n settings.createTenantForNewUser ??\n state.createTenantForNewUser,\n isDiscoveringAppId: false,\n },\n });\n return;\n }\n }\n } catch (error) {}\n }\n\n // All URLs failed\n console.warn('Failed to discover appId from /settings');\n dispatch({\n type: 'SET_PASSFLOW_STATE',\n payload: {\n ...state,\n isDiscoveringAppId: false,\n },\n });\n };\n\n void discoverAppId();\n }\n }, [needsDiscovery, state.isDiscoveringAppId, config.url, passflow, state]);\n\n const passflowValue = useMemo(() => ({ state, dispatch, passflow }), [state, passflow]);\n\n const handleSetNavigate = useCallback((newNavigate: NavigateFunction | null) => {\n setNavigate(() => newNavigate || defaultNavigate);\n }, []);\n\n const [flowTwoFactorVerifyPath, setFlowTwoFactorVerifyPath] = useState<string | null>(null);\n const resolvedTwoFactorVerifyPath = flowTwoFactorVerifyPath ?? twoFactorVerifyPath ?? routes.two_factor_verify.path;\n useSecondFactorLanding(landedWithTwoFactorToken, passflow, navigate, resolvedTwoFactorVerifyPath);\n\n const navigationValue = useMemo(\n () => ({\n navigate,\n setNavigate: handleSetNavigate,\n router,\n twoFactorVerifyPath: resolvedTwoFactorVerifyPath,\n setTwoFactorVerifyPath: setFlowTwoFactorVerifyPath,\n }),\n [navigate, handleSetNavigate, router, resolvedTwoFactorVerifyPath],\n );\n\n const oidcExchangeValue = useMemo<OIDCExchangeContextValue>(\n () => ({ parentChallengeId, parentMeta, exchangeState }),\n [parentChallengeId, parentMeta, exchangeState],\n );\n\n // `undefined` ⇒ off, so no existing consumer changes behaviour. `false`\n // forces it off even when a `backend` is declared; declaring a `backend` is\n // itself an opt-in, since naming where your API is has no other meaning.\n const upgradeEnabled = upgrade === false ? false : upgrade !== undefined || backend !== undefined;\n const upgradeOptions = useMemo<PassflowUpgradeOptions>(\n () => (typeof upgrade === 'object' && upgrade !== null ? upgrade : {}),\n [upgrade],\n );\n\n // Render the placeholder while exchange is in flight. Once it\n // resolves (either via navigation or by falling through), children\n // mount as normal. The `upgrade_required` path renders children alone:\n // assurance elevation is `UpgradeProvider`'s job now (§8.4).\n return (\n <PassflowContext.Provider value={passflowValue}>\n <NavigationContext.Provider value={navigationValue}>\n <OIDCExchangeContext.Provider value={oidcExchangeValue}>\n <AuthProvider>\n {/* Mounted outside the exchange branch so a state change does not\n tear down and reinstall the upgrade interceptors. */}\n <UpgradeProvider {...upgradeOptions} enabled={upgradeEnabled} backend={backend}>\n {exchangeState === 'exchanging' ? <ContinuingStatus appName={parentMeta?.app_name} /> : children}\n </UpgradeProvider>\n </AuthProvider>\n </OIDCExchangeContext.Provider>\n </NavigationContext.Provider>\n </PassflowContext.Provider>\n );\n};\n","import type { FC } from 'react';\nimport { useEffect, useState } from 'react';\nimport { TwoFactorChallenge } from '@/components/form/two-factor-challenge';\nimport { TwoFactorRecoveryForm, TwoFactorVerifyForm } from '@/components/form/two-factor-verify';\nimport { hasFollowedOIDCRedirect } from '@/components/provider/passflow-provider';\nimport { routes } from '@/context';\nimport { useNavigation, usePassflow, useTwoFactorVerify } from '@/hooks';\nimport type { SuccessAuthRedirect } from '@/types';\nimport { getUrlWithTokens, isValidUrl, TwoFactorLoopPrevention } from '@/utils';\n\nimport '@/styles/index.css';\n\ntype TwoFactorVerifyFlowProps = {\n successAuthRedirect?: SuccessAuthRedirect;\n signInPath?: string;\n twoFactorSetupPath?: string;\n useV2Flow?: boolean;\n};\n\nexport const TwoFactorVerifyFlow: FC<TwoFactorVerifyFlowProps> = ({\n successAuthRedirect,\n signInPath = routes.signin.path,\n twoFactorSetupPath = routes.two_factor_setup?.path ?? '/two-factor-setup',\n useV2Flow = false,\n}) => {\n const [mode, setMode] = useState<'verify' | 'recovery'>('verify');\n const [shouldBlockRender, setShouldBlockRender] = useState(false);\n const { navigate } = useNavigation();\n const passflow = usePassflow();\n const { errorType } = useTwoFactorVerify();\n\n // Handle initial verification requirement check\n useEffect(() => {\n if (!passflow.isTwoFactorVerificationRequired()) {\n // Only redirect if we can safely do so (no loop detected)\n if (TwoFactorLoopPrevention.canRedirect()) {\n TwoFactorLoopPrevention.incrementRedirect();\n navigate({ to: signInPath });\n setShouldBlockRender(true);\n } else {\n // Loop detected - let component render error state\n setShouldBlockRender(false);\n }\n }\n }, [passflow, navigate, signInPath]);\n\n // Handle error-based redirect\n useEffect(() => {\n if (errorType === 'expired') {\n // Session expired - safe to redirect if no loop detected\n if (TwoFactorLoopPrevention.canRedirect()) {\n TwoFactorLoopPrevention.incrementRedirect();\n TwoFactorLoopPrevention.setLastErrorType('expired');\n\n // Brief delay for user to see \"redirecting\" message\n setTimeout(() => {\n navigate({ to: signInPath });\n }, 1500);\n }\n } else if (errorType === 'not_enabled') {\n // Configuration error - DO NOT redirect\n // Track error but don't increment redirect count\n TwoFactorLoopPrevention.setLastErrorType('not_enabled');\n }\n }, [errorType, navigate, signInPath]);\n\n const handleSuccess = async () => {\n // Reset loop prevention on successful auth\n TwoFactorLoopPrevention.reset();\n\n // `/auth/2fa/*` is an interceptor-matched endpoint, so an OIDC login that\n // required a second factor has already been dispatched back to the RP by\n // the time this runs. Navigating again would cancel that in flight — see\n // `hasFollowedOIDCRedirect`.\n if (hasFollowedOIDCRedirect()) return;\n\n if (successAuthRedirect) {\n if (!isValidUrl(successAuthRedirect)) {\n navigate({ to: successAuthRedirect });\n } else {\n window.location.href = await getUrlWithTokens(passflow, successAuthRedirect);\n }\n }\n };\n\n const handleUseRecovery = () => {\n setMode('recovery');\n };\n\n const handleBackToVerify = () => {\n setMode('verify');\n };\n\n // Don't render if we're redirecting\n if (shouldBlockRender) {\n return null;\n }\n\n // Don't render if verification not required and no loop detected\n if (!passflow.isTwoFactorVerificationRequired() && TwoFactorLoopPrevention.canRedirect()) {\n return null;\n }\n\n // V2 flow with multi-method support\n if (useV2Flow) {\n return <TwoFactorChallenge onSuccess={handleSuccess} />;\n }\n\n // Legacy V1 flow\n return (\n <>\n {mode === 'verify' ? (\n <TwoFactorVerifyForm\n onSuccess={handleSuccess}\n onUseRecovery={handleUseRecovery}\n signInPath={signInPath}\n twoFactorSetupPath={twoFactorSetupPath}\n />\n ) : (\n <TwoFactorRecoveryForm onSuccess={handleSuccess} onBack={handleBackToVerify} signInPath={signInPath} />\n )}\n </>\n );\n};\n","import type { PassflowSendPasswordResetEmailPayload } from '@passflow/core';\nimport { phone } from 'phone';\n/* eslint-disable max-len */\n/* eslint-disable react/jsx-props-no-spreading */\n/* eslint-disable complexity */\n/* eslint-disable jsx-a11y/label-has-associated-control */\nimport { type FC, useMemo } from 'react';\nimport { Controller, useForm } from 'react-hook-form';\nimport * as Yup from 'yup';\nimport { Button, FieldPhone, FieldText, Icon, Link } from '@/components/ui';\nimport { routes } from '@/context';\nimport { useAppSettings, useForgotPassword, useNavigation } from '@/hooks';\nimport { cn, emailRegex, getAuthMethods, getIdentityLabel, useUrlParams } from '@/utils';\nimport { Wrapper } from '../wrapper';\n\nimport '@/styles/index.css';\nimport queryString from 'query-string';\n\nconst initialValues = {\n email_or_username: '',\n phone: '',\n};\n\nconst searchParamsForgotPasswordSchema = Yup.object().shape({\n defaultMethod: Yup.string().oneOf(['email_or_username', 'phone']).required(),\n});\n\ntype TForgotPassword = {\n successResetRedirect?: string;\n signInPath?: string;\n forgotPasswordSuccessPath?: string;\n};\n\nexport const ForgotPassword: FC<TForgotPassword> = ({\n successResetRedirect,\n signInPath = routes.signin.path,\n forgotPasswordSuccessPath = routes.forgot_password_success.path,\n}) => {\n const {\n getValues,\n control,\n register,\n formState: { errors, isDirty, isValid },\n } = useForm({\n defaultValues: initialValues,\n });\n\n const { appSettings, currentStyles, isError: isErrorApp, error: errorApp, loginAppTheme } = useAppSettings();\n\n if (isErrorApp) throw new Error(errorApp);\n\n const authMethods = useMemo(() => getAuthMethods(appSettings?.auth_strategies), [appSettings]);\n const { navigate } = useNavigation();\n const { get } = useUrlParams({\n default_method: '',\n });\n\n const params = {\n defaultMethod: get('default_method'),\n };\n\n try {\n searchParamsForgotPasswordSchema.validateSync(params, { abortEarly: false });\n } catch (err) {\n throw new Error('Invalid default method param');\n }\n\n const { defaultMethod } = params;\n\n const { fetch, error, isError, isLoading } = useForgotPassword();\n\n const onSubmitHanlder = async () => {\n const values = getValues();\n const isEmail = values.email_or_username.match(emailRegex);\n const isUsername = !isEmail && values.email_or_username.length > 0;\n const validatedPhone = phone(values.phone);\n const isPhone = validatedPhone.isValid;\n\n const payload = {\n ...(isEmail && { email: values.email_or_username }),\n ...(isUsername && { username: values.email_or_username }),\n ...(isPhone && { phone: validatedPhone.phoneNumber }),\n redirect_url: successResetRedirect ?? appSettings?.defaults?.redirect,\n } as PassflowSendPasswordResetEmailPayload;\n\n const status = await fetch(payload);\n\n if (status) {\n const currentSearchParams = new URLSearchParams(window.location.search);\n const newParams = queryString.stringify({\n ...Object.fromEntries(currentSearchParams.entries()),\n ...payload,\n });\n navigate({ to: forgotPasswordSuccessPath, search: newParams });\n }\n };\n\n // if (!state)\n // return (\n // <Navigate\n // to={{\n // pathname: signInPath ?? routes.signin.path,\n // search: window.location.search,\n // }}\n // replace\n // />\n // );\n\n const currentSubtitle =\n defaultMethod === 'email_or_username'\n ? 'Enter the email address you used when you joined and we’ll send you instructions to reset your password.'\n : 'Enter the mobile phone number you used when you joined and we’ll send you the reset link.';\n\n const currentSubscriptions =\n defaultMethod === 'email_or_username'\n ? 'For security reasons, we do NOT store your password. So rest assured that we will never send your password via email.'\n : 'For security reasons, we do NOT store your password. So rest assured that we will never send your password via SMS.';\n\n return (\n <Wrapper\n title='Forgot password?'\n subtitle={currentSubtitle}\n className='passflow-forgot-password-wrapper'\n customCss={currentStyles?.custom_css}\n customLogo={currentStyles?.logo_url}\n removeBranding={loginAppTheme?.remove_passflow_logo}\n >\n <span className='passflow-form-subscriptions'>{currentSubscriptions}</span>\n\n <form onSubmit={(e) => e.preventDefault()} className='passflow-form'>\n <div className='passflow-form-container'>\n <div className='passflow-form-field'>\n {defaultMethod === 'email_or_username' && (\n <>\n <div className='passflow-form-field__header'>\n <label htmlFor='identity' className={cn('passflow-field-label', { 'passflow-field-label--error': isError })}>\n {getIdentityLabel(authMethods, 'label')}\n </label>\n </div>\n <Controller\n name='email_or_username'\n control={control}\n rules={{\n required: 'Email is required',\n pattern: {\n value: emailRegex,\n message: 'Invalid email',\n },\n }}\n render={({ field }) => (\n <FieldText\n {...field}\n {...register('email_or_username')}\n isError={isError || Object.hasOwn(errors, 'email_or_username')}\n id='email_or_username'\n type='text'\n name='email_or_username'\n />\n )}\n />\n </>\n )}\n {defaultMethod === 'phone' && (\n <>\n <div className='passflow-form-field__header'>\n <label htmlFor='phone' className={cn('passflow-field-label', { 'passflow-field-label--error': isError })}>\n Phone\n </label>\n </div>\n <Controller\n name='phone'\n control={control}\n rules={{\n required: 'Phone is required',\n validate: (value) => {\n const validatePhone = phone(value);\n if (validatePhone.isValid) return true;\n return 'Invalid phone number';\n },\n }}\n render={({ field }) => (\n <FieldPhone\n {...field}\n {...register('phone')}\n onChange={(e) => field.onChange(e)}\n id='phone'\n name='phone'\n isError={isError || Object.hasOwn(errors, 'phone')}\n ref={null}\n />\n )}\n />\n </>\n )}\n {isError && (\n <div className='passflow-form-error'>\n <Icon size='small' id='warning' type='general' className='icon-warning' />\n <span className='passflow-form-error-text'>{error}</span>\n </div>\n )}\n </div>\n </div>\n <div className='passflow-send-reset-wrapper'>\n <Button\n size='big'\n variant='primary'\n type='button'\n disabled={!isDirty || !isValid || isLoading}\n className='passflow-button-send-reset-password'\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n onClick={onSubmitHanlder}\n >\n Send reset instructions\n </Button>\n <p className='passflow-remember-password'>\n Remember your password?{' '}\n <Link to={signInPath ?? routes.signin.path} className='passflow-link'>\n Sign In\n </Link>{' '}\n </p>\n </div>\n </form>\n </Wrapper>\n );\n};\n","/* eslint-disable no-nested-ternary */\n/* eslint-disable complexity */\nimport * as Yup from 'yup';\nimport { Button } from '@/components/ui';\nimport { useAppSettings, useForgotPassword } from '@/hooks';\nimport { Wrapper } from '../wrapper';\nimport '@/styles/index.css';\nimport type { PassflowSendPasswordResetEmailPayload } from '@passflow/core';\nimport { useUrlParams, verificationLinkErrorMessage } from '@/utils';\n\nconst searchParamsForgotPasswordSuccessSchema = Yup.object().shape({\n identity: Yup.string().oneOf(['email', 'phone']).required(),\n identityValue: Yup.string().required(),\n redirectUrl: Yup.string().required(),\n});\n\nexport const ForgotPasswordSuccess = () => {\n const { currentStyles, loginAppTheme } = useAppSettings();\n const { fetch: refetch } = useForgotPassword();\n const { get } = useUrlParams();\n\n const params = {\n identity: get('email') ? 'email' : get('phone') ? 'phone' : null,\n identityValue: get('email') ? get('email') : get('phone') ? get('phone') : null,\n redirectUrl: get('redirect_url'),\n };\n\n try {\n searchParamsForgotPasswordSuccessSchema.validateSync(params, { abortEarly: false });\n } catch (error) {\n console.error('[passflow] invalid password-reset confirmation link', error);\n throw new Error(verificationLinkErrorMessage);\n }\n\n const onClickResendHandler = async () => {\n const resendPayload = {\n ...(params.identity === 'email' ? { email: params.identityValue } : undefined),\n ...(params.identity === 'phone' ? { phone: params.identityValue } : undefined),\n redirect_url: params.redirectUrl,\n };\n\n await refetch(resendPayload as PassflowSendPasswordResetEmailPayload);\n };\n\n return (\n <Wrapper\n title={`Check your ${params.identity}`}\n className='passflow-forgot-password-success-wrapper'\n customCss={currentStyles?.custom_css}\n customLogo={currentStyles?.logo_url}\n removeBranding={loginAppTheme?.remove_passflow_logo}\n >\n <div className='passflow-forgot-password-success-container'>\n <p className='passflow-forgot-password-success-text'>\n We sent a link to {params.identity === 'phone' ? 'phone number' : 'email address'}{' '}\n <strong className='passflow-forgot-password-success-text--strong'>{params.identityValue}</strong>. Click the link to\n reset your password.\n </p>\n <Button\n size='big'\n variant='secondary'\n type='button'\n className='passflow-button-resend-reset-password'\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n onClick={onClickResendHandler}\n >\n Resend {params.identity === 'email' ? 'email' : 'SMS'}\n </Button>\n </div>\n </Wrapper>\n );\n};\n","import type { FC } from 'react';\nimport { LoginScreen } from '@/components/ui';\nimport { useAppSettings, useNavigation } from '@/hooks';\nimport { isValidUrl } from '@/utils';\n\nexport type TError = {\n goBackRedirectTo: string;\n error?: string;\n};\n\nconst defaultErrorMessage = 'Something went wrong';\n\nexport const ErrorComponent: FC<TError> = ({ error = defaultErrorMessage, goBackRedirectTo }) => {\n const { navigate } = useNavigation();\n const { currentStyles, loginAppTheme } = useAppSettings();\n\n const handleGoBack = () => {\n if (!isValidUrl(goBackRedirectTo)) navigate({ to: goBackRedirectTo });\n else window.location.href = goBackRedirectTo;\n };\n\n return (\n <LoginScreen\n chrome={{\n title: '',\n customCss: currentStyles?.custom_css,\n customLogo: currentStyles?.logo_url,\n customLogoAlt: `${loginAppTheme?.application_name ?? 'Application'} logo`,\n removeBranding: loginAppTheme?.remove_passflow_logo,\n }}\n state={{\n kind: 'general-error',\n message: error,\n onAction: handleGoBack,\n }}\n />\n );\n};\n","/* eslint-disable react/prop-types */\n/* eslint-disable react/jsx-props-no-spreading */\nimport { type ComponentType, useContext } from 'react';\nimport { ErrorBoundary, type FallbackProps } from 'react-error-boundary';\nimport type { TError } from '@/components/error';\nimport type { PassflowProps } from '@/components/flow/passflow';\nimport type { TInvitationJoinFlow, TSignIn, TSignUp } from '@/components/form';\nimport { PassflowContext } from '@/context';\n\ntype UnionType = TSignIn | TSignUp | TInvitationJoinFlow | PassflowProps;\n// react-error-boundary 6 types the caught value as unknown: anything can be thrown.\nconst toErrorMessage = (error: unknown) => (error instanceof Error ? error.message : String(error));\n\nconst excludeRoutes = ['verify-challenge-otp', 'password/reset', 'two-factor-verify', 'two-factor-recovery'];\n\nexport const withError =\n <P extends UnionType>(Component: ComponentType<P>, ErrorComponent: ComponentType<TError>) =>\n (props: P) => {\n const context = useContext(PassflowContext);\n const { successAuthRedirect } = props;\n const { pathname } = window.location;\n\n // Allow excluded routes to render without checking appId\n if (excludeRoutes.some((route) => pathname.includes(route))) {\n return (\n <ErrorBoundary\n // eslint-disable-next-line react/no-unstable-nested-components\n FallbackComponent={({ error }: FallbackProps) => (\n <ErrorComponent goBackRedirectTo={successAuthRedirect ?? '/'} error={toErrorMessage(error)} />\n )}\n >\n <Component {...props} />\n </ErrorBoundary>\n );\n }\n\n // If we're still discovering the appId, don't show error yet\n if (context?.state.isDiscoveringAppId) {\n return null; // Or render a loading spinner if desired\n }\n\n // After discovery is complete, check if we have the required config\n // Only appId is required - URL defaults to current origin if not provided\n if (!context?.state.appId) {\n const errorMessage = 'Missing appId';\n return <ErrorComponent goBackRedirectTo={successAuthRedirect ?? '/'} error={errorMessage} />;\n }\n\n return (\n <ErrorBoundary\n // eslint-disable-next-line react/no-unstable-nested-components\n FallbackComponent={({ error }: FallbackProps) => (\n <ErrorComponent goBackRedirectTo={successAuthRedirect ?? '/'} error={toErrorMessage(error)} />\n )}\n >\n <Component {...props} />\n </ErrorBoundary>\n );\n };\n\nexport default withError;\n","import { type InvitationToken, parseToken } from '@passflow/core';\nimport { type FC, useEffect } from 'react';\nimport { ErrorComponent } from '@/components/error';\nimport { LoginScreen } from '@/components/ui';\nimport { routes } from '@/context';\nimport { withError } from '@/hocs';\nimport { useAppSettings, useJoinInvite, useNavigation, usePassflow } from '@/hooks';\nimport { getUrlWithTokens, invitationLinkErrorMessage, isValidUrl, undefinedOnCatch, useUrlParams } from '@/utils';\n\nexport type TInvitationJoinFlow = {\n successAuthRedirect?: string;\n signInPath?: string;\n signUpPath?: string;\n};\n\nconst InvitationJoinFlow: FC<TInvitationJoinFlow> = ({\n signInPath = routes.signin.path,\n signUpPath = routes.signup.path,\n successAuthRedirect,\n}) => {\n const { appSettings, currentStyles, loginAppTheme } = useAppSettings();\n const { navigate } = useNavigation();\n const { get } = useUrlParams();\n const passflow = usePassflow();\n const { fetch: joinInvite, isLoading, error, isError } = useJoinInvite();\n const invitationToken = get('invite_token');\n const invitationTokenData = invitationToken ? undefinedOnCatch(parseToken)(invitationToken) : undefined;\n const parsedTokenCache = passflow.getParsedTokens();\n const hasAuthenticatedSession = Boolean(parsedTokenCache?.access_token);\n\n useEffect(() => {\n if (invitationTokenData && !hasAuthenticatedSession) {\n navigate({ to: signInPath, search: window.location.search });\n }\n }, [hasAuthenticatedSession, invitationTokenData, navigate, signInPath]);\n\n if (!invitationTokenData) {\n console.error('[passflow] invitation token could not be parsed');\n throw new Error(invitationLinkErrorMessage);\n }\n if (!hasAuthenticatedSession) return null;\n\n const {\n inviter_name: inviterName,\n tenant_name: tenantName,\n redirect_url: redirectUrl,\n } = invitationTokenData as InvitationToken;\n\n const acceptInvitation = async () => {\n if (!invitationToken) return;\n\n const joined = await joinInvite(invitationToken);\n if (!joined) return;\n\n const successJoinPath = redirectUrl ?? successAuthRedirect ?? appSettings?.defaults?.redirect ?? '';\n if (!isValidUrl(successJoinPath)) navigate({ to: successJoinPath });\n else window.location.href = await getUrlWithTokens(passflow, successJoinPath);\n };\n\n const navigateToSignIn = () => navigate({ to: signInPath, search: window.location.search });\n const navigateToSignUp = () => navigate({ to: signUpPath, search: window.location.search });\n\n return (\n <LoginScreen\n chrome={{\n title: `You've been invited to join ${tenantName}.`,\n subtitle: 'Review the invitation before continuing.',\n customCss: currentStyles?.custom_css,\n customLogo: currentStyles?.logo_url,\n customLogoAlt: `${loginAppTheme?.application_name ?? 'Application'} logo`,\n removeBranding: loginAppTheme?.remove_passflow_logo,\n }}\n state={{\n kind: 'invitation',\n identity: parsedTokenCache?.id_token?.email,\n inviterName: inviterName || undefined,\n busy: isLoading,\n error: isError ? error : null,\n testId: 'invitation-join',\n acceptTestId: 'invitation-accept',\n onAccept: () => void acceptInvitation(),\n onSwitchAccount: navigateToSignIn,\n onCreateAccount: navigateToSignUp,\n }}\n />\n );\n};\n\nexport const InvitationJoin = withError(InvitationJoinFlow, ErrorComponent);\n","/* eslint-disable max-len */\n/* eslint-disable react/jsx-props-no-spreading */\n/* eslint-disable jsx-a11y/label-has-associated-control */\nimport type { FC } from 'react';\nimport * as Yup from 'yup';\nimport { Button, FieldPassword, Icon } from '@/components/ui';\nimport { routes } from '@/context';\nimport { useAppSettings, useNavigation, usePassflow, useResetPassword } from '@/hooks';\nimport {\n cn,\n getUrlWithTokens,\n isValidUrl,\n passwordValidation,\n routeToSecondFactor,\n undefinedOnCatch,\n useUrlParams,\n} from '@/utils';\nimport { Wrapper } from '../wrapper';\nimport '@/styles/index.css';\nimport { parseToken, type Token } from '@passflow/core';\nimport { Controller, useForm } from 'react-hook-form';\nimport type { SuccessAuthRedirect } from '@/types';\n\nconst initialValues = {\n password: '',\n};\n\nconst searchParamsResetPasswordSchema = Yup.object().shape({\n token: Yup.string().required(),\n});\n\ntype TResetPassword = {\n successAuthRedirect?: SuccessAuthRedirect;\n twoFactorVerifyPath?: string;\n};\n\ntype ResetToken = Token & {\n redirect_url: string;\n};\n\nexport const ResetPassword: FC<TResetPassword> = ({\n successAuthRedirect,\n twoFactorVerifyPath = routes.two_factor_verify.path,\n}) => {\n const {\n getValues,\n control,\n register,\n trigger,\n formState: { errors, isDirty, isValid },\n clearErrors,\n setError,\n } = useForm({\n defaultValues: initialValues,\n });\n\n const passflow = usePassflow();\n const { appSettings } = useAppSettings();\n const { fetch, error, isError, isLoading } = useResetPassword();\n const { navigate } = useNavigation();\n const { get } = useUrlParams();\n const { passwordPolicy, currentStyles, isError: isErrorApp, error: errorApp, loginAppTheme } = useAppSettings();\n\n if (isErrorApp) throw new Error(errorApp);\n\n const params = {\n token: get('token'),\n };\n\n try {\n searchParamsResetPasswordSchema.validateSync(params, { abortEarly: false });\n } catch (err) {\n throw new Error('Invalid reset token.');\n }\n\n const { token: resetToken } = params;\n\n const resetTokenData = resetToken ? undefinedOnCatch(parseToken)(resetToken) : undefined;\n\n const onSubmitHanlder = async () => {\n const values = getValues();\n const resetTokenType = resetTokenData as ResetToken;\n const status = await fetch(values.password);\n // A user with 2FA is signed in only once the second factor passes.\n if (status && routeToSecondFactor(passflow, navigate, twoFactorVerifyPath)) return;\n if (status) {\n if (!isValidUrl(resetTokenType?.redirect_url ?? successAuthRedirect ?? appSettings?.defaults?.redirect))\n navigate({ to: resetTokenType?.redirect_url ?? successAuthRedirect ?? appSettings?.defaults?.redirect });\n else\n window.location.href = await getUrlWithTokens(\n passflow,\n resetTokenType?.redirect_url ?? successAuthRedirect ?? appSettings?.defaults?.redirect,\n );\n }\n };\n\n const handlePasswordChange = async () => {\n await trigger(['password']);\n };\n\n return (\n <Wrapper\n title='Reset password'\n subtitle='Let’s get you back in.'\n className='passflow-reset-password-wrapper'\n customCss={currentStyles?.custom_css}\n customLogo={currentStyles?.logo_url}\n removeBranding={loginAppTheme?.remove_passflow_logo}\n >\n <span className='passflow-reset-password-text'>Enter your new password below.</span>\n <form\n onSubmit={(e) => {\n e.preventDefault();\n void onSubmitHanlder();\n }}\n className='passflow-form passflow-reset-password-form'\n >\n <div className='passflow-form-container'>\n <div className='passflow-form-field'>\n <div className='passflow-form-field__header'>\n <label htmlFor='password' className={cn('passflow-field-label', { 'passflow-field-label--error': isError })}>\n New password\n </label>\n </div>\n <Controller\n name='password'\n control={control}\n rules={{\n required: 'Password is required',\n validate: (value) => {\n try {\n passwordValidation(passwordPolicy).validateSync(value);\n clearErrors('password');\n return true;\n } catch (err) {\n const passwordErrors = err as { errors: string[] };\n setError('password', {\n type: 'manual',\n message: passwordErrors.errors.join(', '),\n });\n return passwordErrors.errors.join(', ');\n }\n },\n }}\n render={({ field }) => (\n <FieldPassword\n {...field}\n {...register('password')}\n isError={isError}\n passwordPolicy={passwordPolicy}\n validationErrors={\n Object.hasOwn(errors, 'password') && errors.password?.message\n ? errors.password.message.split(', ')\n : undefined\n }\n id='password'\n name='password'\n withMessages\n onChange={(e) => {\n field.onChange(e);\n void handlePasswordChange();\n }}\n />\n )}\n />\n {isError && (\n <div className='passflow-form-error'>\n <Icon size='small' id='warning' type='general' className='icon-warning' />\n <span className='passflow-form-error-text'>{error}</span>\n </div>\n )}\n </div>\n </div>\n <Button\n size='big'\n variant='primary'\n type='submit'\n disabled={!isDirty || !isValid || isLoading}\n className='passflow-button-reset-password'\n >\n Save new password\n </Button>\n </form>\n </Wrapper>\n );\n};\n","import type {\n PassflowPasskeyAuthenticateStartPayload,\n PassflowPasswordlessResponse,\n PassflowPasswordlessSignInPayload,\n PassflowSignInPayload,\n Providers,\n} from '@passflow/core';\nimport { phone } from 'phone';\nimport queryString from 'query-string';\nimport type { FC } from 'react';\nimport { useMemo } from 'react';\nimport { ErrorComponent } from '@/components/error';\nimport { hasFollowedOIDCRedirect, readParentChallengeIdFromURL } from '@/components/provider/passflow-provider';\nimport { type LoginCredentialsValues, type LoginMethodConfig, LoginScreen } from '@/components/ui';\nimport { routes } from '@/context';\nimport { withError } from '@/hocs';\nimport { useAppSettings, useNavigation, usePassflow, useProvider, useSignIn } from '@/hooks';\nimport type { SuccessAuthRedirect } from '@/types';\nimport {\n type AuthMethods,\n authRedirectErrorMessage,\n emailRegex,\n getAuthMethods,\n getIdentityLabel,\n getInvitationAuthChrome,\n getPasswordlessData,\n getUrlErrors,\n getUrlWithTokens,\n isValidUrl,\n routeToSecondFactor,\n useUrlParams,\n} from '@/utils';\n\nconst getLoginMethodConfig = (authMethods: AuthMethods): LoginMethodConfig => {\n const identities: LoginMethodConfig['identities'] = [];\n\n if (authMethods.hasSignInEmailMethods || authMethods.hasSignInUsernameMethods) {\n const label = getIdentityLabel(authMethods, 'label') ?? 'Email or username';\n identities.push({\n id: 'email_or_username',\n label,\n selectLabel: getIdentityLabel(authMethods, 'button') ?? 'Use email',\n requiredMessage: `${label} is required`,\n format: authMethods.hasSignInEmailMethods && !authMethods.hasSignInUsernameMethods ? 'email' : undefined,\n password: authMethods.internal.email.password || authMethods.internal.username.password,\n passwordlessLabel: getPasswordlessData(authMethods, 'email_or_username')?.label,\n });\n }\n\n if (authMethods.hasSignInPhoneMethods) {\n identities.push({\n id: 'phone',\n label: 'Phone number',\n selectLabel: 'Use phone',\n requiredMessage: 'Phone number is required',\n password: authMethods.internal.phone.password,\n passwordlessLabel: getPasswordlessData(authMethods, 'phone')?.label,\n });\n }\n\n return {\n identities,\n passkey: authMethods.passkey,\n providers: authMethods.fim.providers,\n };\n};\n\nexport type TSignIn = {\n successAuthRedirect?: SuccessAuthRedirect;\n relyingPartyId?: string;\n federatedDisplayMode?: 'modal' | 'redirect';\n signUpPath?: string;\n verifyOTPPath?: string;\n verifyMagicLinkPath?: string;\n forgotPasswordPath?: string;\n twoFactorVerifyPath?: string;\n};\n\nexport const SignInForm: FC<TSignIn> = ({\n successAuthRedirect,\n relyingPartyId = window.location.hostname,\n signUpPath = routes.signup.path,\n verifyOTPPath = routes.verify_otp.path,\n verifyMagicLinkPath = routes.verify_magic_link.path,\n forgotPasswordPath = routes.forgot_password.path,\n twoFactorVerifyPath = routes.two_factor_verify.path,\n}) => {\n const passflow = usePassflow();\n const { navigate } = useNavigation();\n const {\n appSettings,\n scopes,\n createTenantForNewUser,\n passwordPolicy,\n currentStyles,\n isError: isErrorApp,\n error: errorApp,\n loginAppTheme,\n } = useAppSettings();\n const { federatedWithRedirect } = useProvider(successAuthRedirect, createTenantForNewUser);\n\n if (isErrorApp) throw new Error(errorApp);\n\n const authMethods = useMemo(() => getAuthMethods(appSettings?.auth_strategies), [appSettings]);\n const loginMethods = useMemo(() => getLoginMethodConfig(authMethods), [authMethods]);\n const { error: errorUrl, message: messageUrl } = getUrlErrors();\n\n if (errorUrl) {\n console.error('[passflow] sign-in redirect returned an error', { error: errorUrl, message: messageUrl });\n throw new Error(authRedirectErrorMessage);\n }\n\n const { get } = useUrlParams({ invite_token: '' });\n const inviteToken = get('invite_token');\n const invitationChrome = getInvitationAuthChrome(inviteToken, 'sign-in');\n const { fetch, isError, error, reset, isLoading } = useSignIn();\n\n const oidcLayerOwnsRedirect = (): boolean => {\n if (hasFollowedOIDCRedirect()) return true;\n if (readParentChallengeIdFromURL()) {\n console.error(\n '[passflow] login took the legacy token path while parent_challenge_id is present on the URL — the OIDC interceptor did not engage and the RP redirect will not happen',\n );\n }\n return false;\n };\n\n const completeAuthentication = async () => {\n if (routeToSecondFactor(passflow, navigate, twoFactorVerifyPath ?? routes.two_factor_verify.path)) return;\n if (oidcLayerOwnsRedirect()) return;\n const redirectUrl = successAuthRedirect ?? appSettings?.defaults?.redirect ?? '';\n if (!isValidUrl(redirectUrl)) navigate({ to: redirectUrl });\n else window.location.href = await getUrlWithTokens(passflow, redirectUrl);\n };\n\n const submitPassword = async (userPayload: PassflowSignInPayload) => {\n const payload = {\n ...userPayload,\n ...(inviteToken && { invite_token: inviteToken }),\n } as PassflowSignInPayload;\n\n const status = await fetch(payload, 'password');\n if (status) await completeAuthentication();\n };\n\n const submitPasskey = async (passkeyPayload: PassflowPasskeyAuthenticateStartPayload) => {\n const payload = {\n ...passkeyPayload,\n ...(inviteToken && { invite_token: inviteToken }),\n } as PassflowPasskeyAuthenticateStartPayload;\n\n const response = await fetch(payload, 'passkey');\n if (response) await completeAuthentication();\n };\n\n const submitPasswordless = async (\n userPayload: Partial<PassflowPasswordlessSignInPayload>,\n method: LoginCredentialsValues['method'],\n ) => {\n const challengeType = getPasswordlessData(authMethods, method)?.challengeType;\n const payload = {\n ...userPayload,\n challenge_type: challengeType,\n create_tenant: createTenantForNewUser,\n redirect_url: successAuthRedirect ?? appSettings?.defaults?.redirect,\n ...(inviteToken && { invite_token: inviteToken }),\n } as PassflowPasswordlessSignInPayload;\n\n const response = await fetch(payload, 'passwordless');\n if (!response) return;\n\n const passwordlessResponse = response as PassflowPasswordlessResponse;\n const params = new URLSearchParams(window.location.search);\n const newParams = queryString.stringify({\n ...Object.fromEntries(params.entries()),\n ...payload,\n ...passwordlessResponse,\n type: 'passwordless',\n challenge_type: challengeType,\n create_tenant: createTenantForNewUser,\n });\n\n if (challengeType === 'otp') navigate({ to: verifyOTPPath ?? routes.verify_otp.path, search: newParams });\n if (challengeType === 'magic_link')\n navigate({ to: verifyMagicLinkPath ?? routes.verify_magic_link.path, search: newParams });\n };\n\n const handlePassword = async (values: LoginCredentialsValues) => {\n const isEmail = Boolean(values.emailOrUsername.match(emailRegex));\n const isUsername = values.method === 'email_or_username' && !isEmail && values.emailOrUsername.length > 0;\n const validatedPhone = phone(values.phone);\n const payload = {\n ...(isEmail && { email: values.emailOrUsername }),\n ...(isUsername && { username: values.emailOrUsername }),\n ...(validatedPhone.isValid && { phone: validatedPhone.phoneNumber }),\n scopes,\n password: values.password,\n };\n\n await submitPassword(payload as PassflowSignInPayload);\n };\n\n const handlePasswordless = async (values: LoginCredentialsValues) => {\n const isEmail = Boolean(values.emailOrUsername.match(emailRegex));\n const validatedPhone = phone(values.phone);\n const payload = {\n ...(isEmail && { email: values.emailOrUsername }),\n ...(validatedPhone.isValid && { phone: validatedPhone.phoneNumber }),\n scopes,\n };\n\n await submitPasswordless(payload as Partial<PassflowPasswordlessSignInPayload>, values.method);\n };\n\n const handlePasskey = async () => {\n await submitPasskey({ relying_party_id: relyingPartyId, scopes });\n };\n\n const handleProvider = (provider: Providers) => federatedWithRedirect(provider, inviteToken ?? undefined);\n\n return (\n <LoginScreen\n chrome={{\n title: invitationChrome?.title ?? 'Sign In to your account',\n subtitle: invitationChrome?.subtitle ?? 'To Passflow by Madappgang',\n variant: 'sign-in',\n customCss: currentStyles?.custom_css,\n customLogo: currentStyles?.logo_url,\n customLogoAlt: `${loginAppTheme?.application_name ?? 'Application'} logo`,\n removeBranding: loginAppTheme?.remove_passflow_logo,\n }}\n state={{\n kind: 'credentials',\n methods: loginMethods,\n passwordPolicy,\n forcePasskey: Boolean(appSettings?.force_passwordless_login && authMethods.passkey),\n allowPasskeyToggle: true,\n busy: isLoading,\n primaryLabel: isLoading ? 'Signing in…' : 'Sign In',\n error: isError ? error : null,\n forgotPassword: {\n to: forgotPasswordPath ?? routes.forgot_password.path,\n getSearch: (method) =>\n queryString.stringify({\n ...queryString.parse(window.location.search),\n default_method: method,\n }),\n },\n footer: {\n prompt: \"Don't have an account?\",\n label: 'Sign Up',\n to: signUpPath ?? routes.signup.path,\n search: window.location.search,\n },\n onPassword: (values) => void handlePassword(values),\n onPasswordless: (values) => void handlePasswordless(values),\n onPasskey: () => void handlePasskey(),\n onProvider: handleProvider,\n onReset: reset,\n }}\n />\n );\n};\n\nexport const SignIn = withError(SignInForm, ErrorComponent);\n","import type {\n PassflowPasskeyRegisterStartPayload,\n PassflowPasswordlessResponse,\n PassflowPasswordlessSignInPayload,\n PassflowSignUpPayload,\n PassflowUserPayload,\n Providers,\n} from '@passflow/core';\nimport { phone } from 'phone';\nimport queryString from 'query-string';\nimport type { FC } from 'react';\nimport { useMemo } from 'react';\nimport { ErrorComponent } from '@/components/error';\nimport { hasFollowedOIDCRedirect } from '@/components/provider/passflow-provider';\nimport { type LoginCredentialsValues, type LoginMethodConfig, LoginScreen } from '@/components/ui';\nimport { routes } from '@/context';\nimport { withError } from '@/hocs';\nimport { useAppSettings, useNavigation, usePassflow, useProvider, useSignUp } from '@/hooks';\nimport type { DefaultMethod, SuccessAuthRedirect } from '@/types';\nimport {\n type AuthMethods,\n authRedirectErrorMessage,\n emailRegex,\n getAuthMethods,\n getInvitationAuthChrome,\n getPasswordlessData,\n getUrlErrors,\n getUrlWithTokens,\n isValidUrl,\n routeToSecondFactor,\n useUrlParams,\n} from '@/utils';\n\nconst getSignUpMethodConfig = (authMethods: AuthMethods): LoginMethodConfig => {\n const identities: LoginMethodConfig['identities'] = [];\n\n if (authMethods.hasEmailMethods || authMethods.hasUsernameMethods) {\n const label =\n authMethods.hasEmailMethods && authMethods.hasUsernameMethods\n ? 'Email or username'\n : authMethods.hasUsernameMethods\n ? 'Username'\n : 'Email';\n identities.push({\n id: 'email_or_username',\n label,\n selectLabel: authMethods.hasUsernameMethods && !authMethods.hasEmailMethods ? 'Use username' : 'Use email',\n requiredMessage: `${label} is required`,\n format: authMethods.hasEmailMethods && !authMethods.hasUsernameMethods ? 'email' : undefined,\n password: authMethods.internal.email.password || authMethods.internal.username.password,\n passwordlessLabel: getPasswordlessData(authMethods, 'email_or_username')?.label,\n });\n }\n\n if (authMethods.hasPhoneMethods) {\n identities.push({\n id: 'phone',\n label: 'Phone number',\n selectLabel: 'Use phone',\n requiredMessage: 'Phone number is required',\n password: authMethods.internal.phone.password,\n passwordlessLabel: getPasswordlessData(authMethods, 'phone')?.label,\n });\n }\n\n return {\n identities,\n passkey: authMethods.passkey,\n providers: authMethods.fim.providers,\n };\n};\n\nexport type TSignUp = {\n successAuthRedirect?: SuccessAuthRedirect;\n relyingPartyId?: string;\n federatedDisplayMode?: 'modal' | 'redirect';\n signInPath?: string;\n verifyOTPPath?: string;\n verifyMagicLinkPath?: string;\n twoFactorVerifyPath?: string;\n};\n\nexport const SignUpForm: FC<TSignUp> = ({\n successAuthRedirect,\n relyingPartyId = window.location.hostname,\n signInPath = routes.signin.path,\n verifyOTPPath = routes.verify_otp.path,\n verifyMagicLinkPath = routes.verify_magic_link.path,\n twoFactorVerifyPath = routes.two_factor_verify.path,\n}) => {\n const passflow = usePassflow();\n const { navigate } = useNavigation();\n const {\n appSettings,\n scopes,\n createTenantForNewUser,\n passwordPolicy,\n currentStyles,\n isError: isErrorApp,\n error: errorApp,\n loginAppTheme,\n } = useAppSettings();\n const { federatedWithRedirect } = useProvider(successAuthRedirect, createTenantForNewUser);\n\n if (isErrorApp) throw new Error(errorApp);\n\n const authMethods = useMemo(() => getAuthMethods(appSettings?.auth_strategies), [appSettings]);\n const loginMethods = useMemo(() => getSignUpMethodConfig(authMethods), [authMethods]);\n const { error: errorUrl, message: messageUrl } = getUrlErrors();\n\n if (errorUrl) {\n console.error('[passflow] sign-up redirect returned an error', { error: errorUrl, message: messageUrl });\n throw new Error(authRedirectErrorMessage);\n }\n\n const { get } = useUrlParams({ invite_token: '' });\n const inviteToken = get('invite_token');\n const invitationChrome = getInvitationAuthChrome(inviteToken, 'sign-up');\n const { fetch, isError, error, reset, isLoading } = useSignUp();\n\n // The server can answer a sign-up with a 2FA token in place of tokens, as it\n // does a sign-in, so the 2FA screen comes before any success redirect.\n const completeRegistration = async ({ oidcMayOwnRedirect = false } = {}) => {\n if (routeToSecondFactor(passflow, navigate, twoFactorVerifyPath ?? routes.two_factor_verify.path)) return;\n if (oidcMayOwnRedirect && hasFollowedOIDCRedirect()) return;\n const redirectUrl = successAuthRedirect ?? appSettings?.defaults?.redirect ?? '';\n if (!isValidUrl(redirectUrl)) navigate({ to: redirectUrl });\n else window.location.href = await getUrlWithTokens(passflow, redirectUrl);\n };\n\n const submitPassword = async (userPayload: PassflowUserPayload) => {\n const payload = {\n user: userPayload,\n create_tenant: createTenantForNewUser,\n ...(inviteToken ? { invite_token: inviteToken } : {}),\n } as PassflowSignUpPayload;\n\n if (await fetch(payload, 'password')) await completeRegistration({ oidcMayOwnRedirect: true });\n };\n\n const submitPasskey = async () => {\n const redirectUrl = successAuthRedirect ?? appSettings?.defaults?.redirect ?? '';\n const payload = {\n relying_party_id: relyingPartyId,\n create_tenant: createTenantForNewUser,\n redirect_url: redirectUrl,\n ...(inviteToken ? { invite_token: inviteToken } : {}),\n scopes,\n } as PassflowPasskeyRegisterStartPayload;\n\n if (await fetch(payload, 'passkey')) await completeRegistration({ oidcMayOwnRedirect: true });\n };\n\n const submitPasswordless = async (userPayload: Partial<PassflowPasswordlessSignInPayload>, method: DefaultMethod | null) => {\n const challengeType = getPasswordlessData(authMethods, method)?.challengeType;\n const payload = {\n ...userPayload,\n challenge_type: challengeType,\n create_tenant: createTenantForNewUser,\n redirect_url: successAuthRedirect ?? appSettings?.defaults?.redirect,\n ...(inviteToken ? { invite_token: inviteToken } : {}),\n } as PassflowPasswordlessSignInPayload;\n\n const response = await fetch(payload, 'passwordless');\n if (!response) return;\n\n const passwordlessResponse = response as PassflowPasswordlessResponse;\n const params = new URLSearchParams(window.location.search);\n const newParams = queryString.stringify({\n ...Object.fromEntries(params.entries()),\n ...payload,\n ...passwordlessResponse,\n type: 'passwordless',\n challenge_type: challengeType,\n create_tenant: createTenantForNewUser,\n });\n\n if (challengeType === 'otp') navigate({ to: verifyOTPPath ?? routes.verify_otp.path, search: newParams });\n if (challengeType === 'magic_link')\n navigate({ to: verifyMagicLinkPath ?? routes.verify_magic_link.path, search: newParams });\n };\n\n const handlePassword = async (values: LoginCredentialsValues) => {\n const isEmail = Boolean(values.emailOrUsername.match(emailRegex));\n const isUsername = values.method === 'email_or_username' && !isEmail && values.emailOrUsername.length > 0;\n const validatedPhone = phone(values.phone);\n const user = {\n ...(isEmail ? { email: values.emailOrUsername } : {}),\n ...(isUsername ? { username: values.emailOrUsername } : {}),\n ...(validatedPhone.isValid ? { phone_number: validatedPhone.phoneNumber } : {}),\n password: values.password,\n scopes,\n } as PassflowUserPayload;\n\n await submitPassword(user);\n };\n\n const handlePasswordless = async (values: LoginCredentialsValues) => {\n const isEmail = Boolean(values.emailOrUsername.match(emailRegex));\n const validatedPhone = phone(values.phone);\n const payload = {\n ...(isEmail ? { email: values.emailOrUsername } : {}),\n ...(validatedPhone.isValid ? { phone: validatedPhone.phoneNumber } : {}),\n scopes,\n };\n\n await submitPasswordless(payload as Partial<PassflowPasswordlessSignInPayload>, values.method);\n };\n\n const handleProvider = (provider: Providers) => federatedWithRedirect(provider, inviteToken ?? undefined);\n\n return (\n <LoginScreen\n chrome={{\n title: invitationChrome?.title ?? 'Create your account',\n subtitle: invitationChrome?.subtitle ?? 'For Passflow by Madappgang',\n variant: 'sign-in',\n customCss: currentStyles?.custom_css,\n customLogo: currentStyles?.logo_url,\n customLogoAlt: `${loginAppTheme?.application_name ?? 'Application'} logo`,\n removeBranding: loginAppTheme?.remove_passflow_logo,\n }}\n state={{\n kind: 'credentials',\n methods: loginMethods,\n passwordPolicy,\n credentialPurpose: 'sign-up',\n forcePasskey: Boolean(appSettings?.force_passwordless_login && authMethods.passkey),\n allowPasskeyToggle: true,\n busy: isLoading,\n primaryLabel: isLoading ? 'Creating account…' : 'Sign Up',\n passwordlessLabelPrefix: 'Sign Up with',\n passkeyLabel: 'Sign Up with a Passkey',\n error: isError ? error : null,\n footer: {\n prompt: 'Already have an account?',\n label: 'Sign In',\n to: signInPath ?? routes.signin.path,\n search: window.location.search,\n },\n onPassword: (values) => void handlePassword(values),\n onPasswordless: (values) => void handlePasswordless(values),\n onPasskey: () => void submitPasskey(),\n onProvider: handleProvider,\n onReset: reset,\n }}\n />\n );\n};\n\nexport const SignUp = withError(SignUpForm, ErrorComponent);\n","/* eslint-disable no-nested-ternary */\nimport type { PassflowPasswordlessSignInPayload } from '@passflow/core';\nimport { Button } from '@/components/ui';\nimport { useAppSettings, useSignIn } from '@/hooks';\nimport { Wrapper } from '../wrapper';\nimport '@/styles/index.css';\nimport { useUrlParams } from '@/utils';\n\nconst challengeTypeFullString = {\n email: 'email address',\n phone: 'phone number',\n};\n\nexport const VerifyChallengeMagicLink = () => {\n const { currentStyles, loginAppTheme } = useAppSettings();\n const { fetch: refetch } = useSignIn();\n const { get } = useUrlParams({\n identity: '',\n identity_value: '',\n challenge_type: '',\n type: '',\n redirect_url: '',\n });\n\n const identity = get('email') ? 'email' : get('phone') ? 'phone' : undefined;\n const identityValue = get('email') ? get('email') : get('phone') ? get('phone') : undefined;\n const challengeType = get('challenge_type');\n const type = get('type') as 'passkey' | 'password' | 'passwordless';\n const redirectUrl = get('redirect_url');\n\n const onClickResendHandler = async () => {\n const resendPayload = {\n ...(identity === 'email' ? { email: identityValue } : undefined),\n ...(identity === 'phone' ? { phone: identityValue } : undefined),\n challenge_type: challengeType,\n redirect_url: redirectUrl,\n };\n\n await refetch(resendPayload as PassflowPasswordlessSignInPayload, type);\n };\n\n return (\n <Wrapper\n title='Check your email'\n className='passflow-verify-challenge-magic-link-wrapper'\n customCss={currentStyles?.custom_css}\n customLogo={currentStyles?.logo_url}\n removeBranding={loginAppTheme?.remove_passflow_logo}\n >\n <div className='passflow-verify-challenge-magic-link-container'>\n <p className='passflow-verify-challenge-magic-link-text'>\n We sent a link to {challengeTypeFullString[identity as keyof typeof challengeTypeFullString]}{' '}\n {identityValue && <strong className='passflow-verify-challenge-magic-link-text--strong'>{identityValue}</strong>}.\n Click on the link to confirm your registration.\n </p>\n {type === 'passwordless' && (\n <Button\n size='big'\n variant='secondary'\n type='button'\n className='passflow-button-resend-magic-link'\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n onClick={onClickResendHandler}\n >\n Resend email\n </Button>\n )}\n </div>\n </Wrapper>\n );\n};\n","import { type FC, type PropsWithChildren, useEffect, useState } from 'react';\nimport { Button } from '@/components/ui';\nimport '@/styles/index.css';\nimport { cn } from '@/utils';\n\ntype TTimerButton = PropsWithChildren & {\n totalSecond: number;\n onClick: () => void;\n className?: string;\n};\n\nexport const TimerButton: FC<TTimerButton> = ({ totalSecond, onClick, className = '', ...props }) => {\n const [seconds, setSeconds] = useState(totalSecond);\n\n useEffect(() => {\n const interval = setInterval(() => {\n if (seconds > 0) {\n setSeconds((prev) => prev - 1);\n }\n }, 1000);\n\n return () => {\n clearInterval(interval);\n };\n }, [seconds]);\n\n const onClickHandler = () => {\n onClick();\n setSeconds(totalSecond);\n };\n\n return (\n <Button\n disabled={seconds > 0}\n size='small'\n variant='clean'\n type='button'\n className={cn(\n 'passflow-button-timer',\n {\n 'passflow-button-timer--active': seconds > 0,\n 'passflow-button-timer--inactive': seconds === 0,\n },\n className,\n )}\n onClick={onClickHandler}\n {...props}\n >\n Resend {seconds > 0 ? `(${seconds})` : ''}\n </Button>\n );\n};\n","import type { FC } from 'react';\nimport { useAppSettings } from '@/hooks';\nimport { Wrapper } from '../wrapper';\n\nexport const VerifyChallengeSuccess: FC = () => {\n const { currentStyles, loginAppTheme } = useAppSettings();\n\n return (\n <Wrapper\n iconId='logo'\n className='passflow-verify-challenge-success-wrapper'\n customCss={currentStyles?.custom_css}\n customLogo={currentStyles?.logo_url}\n removeBranding={loginAppTheme?.remove_passflow_logo}\n >\n <div className='passflow-verify-challenge-success-wrapper'>\n <div className='passflow-verify-challenge-success-container'>\n <p className='passflow-verify-challenge-success-text'>Successful verification!</p>\n <p className='passflow-verify-challenge-success-text-secondary'>But there is no redirect URL for further redirect.</p>\n </div>\n </div>\n </Wrapper>\n );\n};\n","import type {\n InternalStrategyChallenge,\n PassflowPasswordlessResponse,\n PassflowPasswordlessSignInCompletePayload,\n PassflowPasswordlessSignInPayload,\n} from '@passflow/core';\n/* eslint-disable no-void */\n/* eslint-disable complexity */\nimport { type FC, useEffect, useId, useState } from 'react';\nimport { Button, FieldOtp, Icon } from '@/components/ui';\nimport { routes } from '@/context';\nimport { useAppSettings, useNavigation, usePassflow, usePasswordlessComplete, useSignIn } from '@/hooks';\nimport { getUrlWithTokens, isValidUrl, routeToSecondFactor, useUrlParams } from '@/utils';\nimport { Wrapper } from '../wrapper';\nimport { TimerButton } from './timer-button';\nimport { VerifyChallengeSuccess } from './verify-challenge-success';\n\nimport '@/styles/index.css';\n\ntype VerifyChallengeOTPManualProps = {\n identity: string | null;\n identityValue: string | null;\n challengeType: string | null;\n challengeId: string | null;\n type: 'passwordless' | 'passkey' | null;\n numInputs: number;\n shouldAutoFocus: boolean;\n signUpPath: string;\n successAuthRedirect?: string;\n twoFactorVerifyPath?: string;\n};\n\nconst challengeTypeFullString = {\n email: 'email address',\n phone: 'phone number',\n};\n\nexport const VerifyChallengeOTPManual: FC<VerifyChallengeOTPManualProps> = ({\n identity,\n identityValue,\n challengeType,\n challengeId,\n type,\n numInputs,\n shouldAutoFocus,\n successAuthRedirect,\n signUpPath,\n twoFactorVerifyPath = routes.two_factor_verify.path,\n}) => {\n const passflow = usePassflow();\n const { appSettings, createTenantForNewUser, currentStyles, loginAppTheme } = useAppSettings();\n const { navigate } = useNavigation();\n const { fetch: refetch } = useSignIn();\n const { fetch: fetchPasswordlessComplete, isError, error } = usePasswordlessComplete();\n const [valueOTP, setValueOTP] = useState('');\n const [paramsError, setParamsError] = useState<string | null>(null);\n const [showSuccessMessage, setShowSuccessMessage] = useState(false);\n const { set } = useUrlParams();\n const otpId = useId();\n const otpErrorId = `${otpId}-error`;\n\n const onChangeOTP = (value: string) => setValueOTP(value);\n\n const onClickResendHandler = async () => {\n if (type && identity && identityValue && challengeType) {\n const payload: PassflowPasswordlessSignInPayload = {\n create_tenant: createTenantForNewUser,\n challenge_type: challengeType as InternalStrategyChallenge,\n redirect_url: successAuthRedirect ?? appSettings?.defaults?.redirect ?? '',\n ...(identity === 'email' ? { email: identityValue } : { phone: identityValue }),\n };\n\n const refetchResponse = (await refetch(payload, type)) as PassflowPasswordlessResponse;\n if (refetchResponse) {\n set({ challenge_id: refetchResponse.challenge_id });\n } else {\n setParamsError('Something went wrong. Please try again later.');\n }\n }\n };\n\n useEffect(() => {\n if (valueOTP.length === numInputs && challengeId) {\n const payload: PassflowPasswordlessSignInCompletePayload = {\n challenge_id: challengeId,\n challenge_type: 'otp',\n otp: valueOTP,\n };\n const fetchData = async () => {\n const response = await fetchPasswordlessComplete(payload);\n if (response) {\n // The code completed the first factor only: no tokens yet.\n if (routeToSecondFactor(passflow, navigate, twoFactorVerifyPath)) return;\n if (response.redirect_url) {\n if (!isValidUrl(response.redirect_url)) navigate({ to: response.redirect_url });\n else window.location.href = await getUrlWithTokens(passflow, response.redirect_url);\n } else {\n setShowSuccessMessage(true);\n }\n }\n };\n void fetchData();\n }\n }, [valueOTP, numInputs, fetchPasswordlessComplete, challengeId, navigate, passflow, twoFactorVerifyPath]);\n\n if (paramsError) throw new Error(paramsError);\n\n if (showSuccessMessage) return <VerifyChallengeSuccess />;\n\n const onClickNavigateBack = () => navigate({ to: signUpPath });\n\n return (\n <Wrapper\n title={`Verify your ${identity}`}\n subtitle={`We sent OTP code to your ${challengeTypeFullString[identity as keyof typeof challengeTypeFullString]}`}\n className='passflow-verify-otp'\n customCss={currentStyles?.custom_css}\n customLogo={currentStyles?.logo_url}\n removeBranding={loginAppTheme?.remove_passflow_logo}\n >\n <div className='passflow-verify-otp-container'>\n {identityValue && (\n <Button\n size='big'\n type='button'\n variant='outlined'\n className='passflow-verify-otp-button'\n withIcon\n onClick={onClickNavigateBack}\n >\n <Icon id={identity === 'email' ? 'mail' : 'phone'} type='general' size='small' />\n {identityValue}\n <Icon id='edit' type='general' size='small' className='passflow-verify-otp-button-icon' />\n </Button>\n )}\n <div id='otp-wrapper' className='passflow-verify-otp-wrapper'>\n <FieldOtp\n id={otpId}\n name='otp'\n length={numInputs}\n value={valueOTP}\n onChange={onChangeOTP}\n state={isError ? 'error' : 'default'}\n label='Verification code'\n describedBy={isError ? otpErrorId : undefined}\n autoFocus={shouldAutoFocus}\n />\n {isError && (\n <div className='passflow-verify-otp-error'>\n <Icon size='small' id='warning' type='general' className='icon-warning' />\n <span id={otpErrorId} className='passflow-verify-otp-error-text'>\n {error}\n </span>\n </div>\n )}\n </div>\n </div>\n {type === 'passwordless' && (\n <p className='passflow-verify-otp-resend'>\n Don't receive a code?\n <TimerButton totalSecond={30} onClick={() => void onClickResendHandler()} />\n </p>\n )}\n </Wrapper>\n );\n};\n","import { useEffect, useState } from 'react';\nimport { routes } from '@/context';\nimport { useNavigation, usePassflow, usePasswordlessComplete } from '@/hooks';\nimport {\n getUrlWithTokens,\n isValidUrl,\n routeToSecondFactor,\n verificationLinkErrorMessage,\n verificationRequestErrorMessage,\n} from '@/utils';\nimport { VerifyChallengeSuccess } from './verify-challenge-success';\n\ntype VerifyChallengeOTPRedirectProps = {\n appId: string | null;\n otp: string | null;\n challengeId: string | null;\n twoFactorVerifyPath?: string;\n};\n\nexport const VerifyChallengeOTPRedirect = ({\n otp,\n challengeId,\n appId,\n twoFactorVerifyPath = routes.two_factor_verify.path,\n}: VerifyChallengeOTPRedirectProps) => {\n const passflow = usePassflow();\n const { navigate } = useNavigation();\n const [paramsError, setParamsError] = useState<string | null>(null);\n const [showSuccessMessage, setShowSuccessMessage] = useState(false);\n const { fetch, isError, error, isLoading } = usePasswordlessComplete();\n\n // Run once on mount - intentionally empty dependency array\n useEffect(() => {\n const fetchData = async () => {\n if (!appId || !otp || !challengeId) {\n const missingParameters = [!appId && 'app_id', !otp && 'otp', !challengeId && 'challenge_id'].filter(Boolean);\n console.error('[passflow] passwordless verification redirect is missing required parameters', missingParameters);\n setParamsError(verificationLinkErrorMessage);\n return;\n }\n\n if (!isLoading) {\n const response = await fetch({ otp, challenge_id: challengeId });\n\n if (response) {\n // The link completed the first factor only: no tokens yet.\n if (routeToSecondFactor(passflow, navigate, twoFactorVerifyPath)) return;\n if (response.redirect_url) {\n if (!isValidUrl(response.redirect_url)) navigate({ to: response.redirect_url });\n else window.location.href = await getUrlWithTokens(passflow, response.redirect_url);\n } else {\n setShowSuccessMessage(true);\n }\n } else {\n setParamsError(verificationRequestErrorMessage);\n }\n }\n };\n\n void fetchData();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n if (isError && error) throw new Error(error);\n\n if (paramsError) throw new Error(paramsError);\n\n if (showSuccessMessage) return <VerifyChallengeSuccess />;\n\n return null;\n};\n","/* eslint-disable complexity */\n/* eslint-disable no-nested-ternary */\nimport type { FC } from 'react';\nimport * as Yup from 'yup';\nimport type { SuccessAuthRedirect } from '@/types';\nimport { VerifyChallengeOTPManual } from './verify-challenge-otp-manual';\nimport { VerifyChallengeOTPRedirect } from './verify-challenge-otp-redirect';\n\nimport '@/styles/index.css';\nimport { routes } from '@/context';\nimport { useUrlParams, verificationLinkErrorMessage } from '@/utils';\n\ntype TVerifyChallengeOTP = {\n numInputs: number;\n shouldAutoFocus: boolean;\n signUpPath: string;\n successAuthRedirect?: SuccessAuthRedirect;\n twoFactorVerifyPath?: string;\n};\n\nconst redirectSearchParamsVerifyChallengeOtpSchema = Yup.object().shape({\n appId: Yup.string().required(),\n challengeId: Yup.string().required(),\n otp: Yup.string().required(),\n});\n\nconst searchParamsVerifyChallengeOtpSchema = Yup.object().shape({\n challengeId: Yup.string().required(),\n identity: Yup.string().oneOf(['email', 'phone']).required(),\n identityValue: Yup.string().required(),\n challengeType: Yup.string().required(),\n type: Yup.string().oneOf(['passwordless', 'passkey']).optional(),\n});\n\nexport const VerifyChallengeOTP: FC<TVerifyChallengeOTP> = ({\n successAuthRedirect,\n numInputs,\n shouldAutoFocus,\n signUpPath,\n twoFactorVerifyPath = routes.two_factor_verify.path,\n}) => {\n const { get } = useUrlParams({\n otp: '',\n app_id: '',\n challenge_id: '',\n identity: '',\n identity_value: '',\n challenge_type: '',\n type: '',\n });\n\n const typeChallenge = get('type');\n\n if (typeChallenge !== 'passwordless' && typeChallenge !== 'passkey') {\n const redirectParams = {\n appId: get('app_id'),\n challengeId: get('challenge_id'),\n otp: get('otp'),\n };\n\n try {\n redirectSearchParamsVerifyChallengeOtpSchema.validateSync(redirectParams, { abortEarly: false });\n } catch (error) {\n console.error('[passflow] invalid passwordless verification redirect', error);\n throw new Error(verificationLinkErrorMessage);\n }\n\n const { appId, otp, challengeId } = redirectParams;\n\n return (\n <VerifyChallengeOTPRedirect appId={appId} challengeId={challengeId} otp={otp} twoFactorVerifyPath={twoFactorVerifyPath} />\n );\n }\n\n const params = {\n challengeId: get('challenge_id'),\n identity: get('email') ? 'email' : get('phone') ? 'phone' : null,\n identityValue: get('email') ? get('email') : get('phone') ? get('phone') : null,\n challengeType: get('challenge_type'),\n type: get('type'),\n };\n\n try {\n searchParamsVerifyChallengeOtpSchema.validateSync(params, { abortEarly: false });\n } catch (error) {\n console.error('[passflow] invalid passwordless verification link', error);\n throw new Error(verificationLinkErrorMessage);\n }\n\n const { challengeId, identity, identityValue, challengeType, type } = params;\n\n if (!type) {\n console.error('[passflow] passwordless verification link is missing its flow type');\n throw new Error(verificationLinkErrorMessage);\n }\n\n return (\n <VerifyChallengeOTPManual\n identity={identity}\n identityValue={identityValue}\n challengeType={challengeType}\n challengeId={challengeId}\n type={type as 'passwordless' | 'passkey'}\n numInputs={numInputs}\n shouldAutoFocus={shouldAutoFocus}\n signUpPath={signUpPath}\n successAuthRedirect={successAuthRedirect}\n twoFactorVerifyPath={twoFactorVerifyPath}\n />\n );\n};\n","import { type FC, type ReactNode, useContext, useEffect, useMemo } from 'react';\nimport { TwoFactorSetupFlow } from '@/components/flow/two-factor-setup';\nimport { TwoFactorVerifyFlow } from '@/components/flow/two-factor-verify';\nimport {\n ForgotPassword,\n ForgotPasswordSuccess,\n InvitationJoin,\n ResetPassword,\n SignIn,\n SignUp,\n VerifyChallengeMagicLink,\n VerifyChallengeOTP,\n} from '@/components/form';\nimport { NavigationContext, routes } from '@/context';\nimport '@/styles/index.css';\n// react-router (v7 or v8) is a required peer dependency, shared with the host app and\n// never bundled. It is imported statically, so a missing peer fails at module\n// load with the resolver's own error; no runtime guard could run earlier.\nimport {\n BrowserRouter,\n HashRouter,\n MemoryRouter,\n Navigate,\n Route,\n Routes,\n useInRouterContext,\n useLocation,\n useNavigate,\n useParams,\n} from 'react-router';\nimport { ErrorComponent } from '@/components/error';\nimport { withError } from '@/hocs';\nimport { useNavigation } from '@/hooks';\nimport type { SuccessAuthRedirect } from '@/types';\nimport { authRedirectErrorMessage, getUrlErrors } from '@/utils';\n\nexport type PassflowProps = {\n successAuthRedirect?: SuccessAuthRedirect;\n federatedDisplayMode?: 'modal' | 'redirect';\n error?: string;\n relyingPartyId?: string;\n pathPrefix?: string;\n /**\n * The router the flow creates for itself. Ignored when the flow is rendered\n * inside a host react-router `<Router>`: the flow then uses the host's router.\n */\n routerType?: 'browser' | 'hash' | 'memory';\n basename?: string;\n};\n\ntype RouterKind = NonNullable<PassflowProps['routerType']>;\n\nconst normalizePathPrefix = (path?: string) => {\n if (!path) return '';\n const pathReplace = path.replace(/^\\/+|\\/+$/g, '');\n return pathReplace.startsWith('/') ? pathReplace : `/${pathReplace}`;\n};\n\nconst combineRoutesWithPrefix = (prefix?: string) =>\n Object.keys(routes).reduce(\n (acc, key) => {\n const PATH = key as keyof typeof routes;\n acc[PATH] = `${normalizePathPrefix(prefix)}${routes[key as keyof typeof routes]?.path}`;\n return acc;\n },\n {} as Record<keyof typeof routes, string>,\n );\n\nconst RouterProvider: FC<{ children: ReactNode; routerType: RouterKind }> = ({ children, routerType }) => {\n switch (routerType) {\n case 'hash':\n return <HashRouter>{children}</HashRouter>;\n case 'memory':\n return <MemoryRouter>{children}</MemoryRouter>;\n default:\n return <BrowserRouter>{children}</BrowserRouter>;\n }\n};\n\n/**\n * Where the flow is mounted inside a host router: the pathname its parent route\n * consumed, without a trailing slash. Under `<Route path='/auth/*'>` at\n * `/auth/signin` this is `/auth`. With no parent route (the flow's own router, or\n * a host router with no `<Routes>` around the flow) it is `''`.\n */\nconst useParentRouteBase = (): string => {\n const { pathname } = useLocation();\n const splat = useParams()['*'];\n if (splat === undefined) return '';\n const tail = pathname.endsWith(splat) ? splat : encodeURI(splat);\n const base = pathname.endsWith(tail) ? pathname.slice(0, pathname.length - tail.length) : pathname;\n return base.replace(/\\/+$/, '');\n};\n\nconst RouterInnerWrapperProvider: FC<{ children: ReactNode }> = ({ children }) => {\n const navigate = useNavigate();\n // Registered with the provider directly, not through useNavigation's adapter: that\n // adapter shapes calls for the host's own navigate according to the provider's\n // `router` prop, and with the default value it sends every step through\n // window.location, out of this router. The flow always runs inside a React Router (its own or the host's).\n const { setNavigate } = useContext(NavigationContext);\n\n useEffect(() => {\n setNavigate(({ to, search = '', replace = false }) => {\n // React Router reads `replace` from the options argument only.\n navigate({ pathname: to, search: search && !search.startsWith('?') ? `?${search}` : search }, { replace });\n });\n }, [navigate, setNavigate]);\n\n return children;\n};\n\ntype PassflowRoutesProps = Required<Pick<PassflowProps, 'federatedDisplayMode' | 'relyingPartyId' | 'pathPrefix'>> &\n Pick<PassflowProps, 'successAuthRedirect'>;\n\n/**\n * The flow's routes, rendered inside whichever router is in context. Route\n * `path`s are matched against what the parent route left over (the whole\n * pathname when there is no parent route), so they carry only `pathPrefix`.\n * Navigation targets are absolute, so they also carry the parent route's base.\n */\nconst PassflowRoutes: FC<PassflowRoutesProps> = ({ successAuthRedirect, federatedDisplayMode, relyingPartyId, pathPrefix }) => {\n const parentBase = useParentRouteBase();\n const matchPaths = useMemo(() => combineRoutesWithPrefix(pathPrefix), [pathPrefix]);\n const paths = useMemo(\n () => combineRoutesWithPrefix(`${parentBase}${normalizePathPrefix(pathPrefix)}`),\n [parentBase, pathPrefix],\n );\n\n // A landing that owes its second factor goes to this flow's own (prefixed)\n // 2FA route; PassflowProvider does the navigation.\n const { setTwoFactorVerifyPath } = useNavigation();\n useEffect(() => {\n setTwoFactorVerifyPath?.(paths.two_factor_verify);\n return () => setTwoFactorVerifyPath?.(null);\n }, [setTwoFactorVerifyPath, paths.two_factor_verify]);\n\n return (\n <RouterInnerWrapperProvider>\n <Routes>\n <Route\n path={matchPaths.signin}\n element={\n <SignIn\n successAuthRedirect={successAuthRedirect}\n relyingPartyId={relyingPartyId}\n federatedDisplayMode={federatedDisplayMode}\n signUpPath={paths.signup}\n forgotPasswordPath={paths.forgot_password}\n verifyMagicLinkPath={paths.verify_magic_link}\n verifyOTPPath={paths.verify_otp}\n twoFactorVerifyPath={paths.two_factor_verify}\n />\n }\n />\n <Route\n path={matchPaths.signup}\n element={\n <SignUp\n successAuthRedirect={successAuthRedirect}\n relyingPartyId={relyingPartyId}\n federatedDisplayMode={federatedDisplayMode}\n signInPath={paths.signin}\n verifyMagicLinkPath={paths.verify_magic_link}\n verifyOTPPath={paths.verify_otp}\n twoFactorVerifyPath={paths.two_factor_verify}\n />\n }\n />\n <Route\n path={matchPaths.verify_otp}\n element={\n <VerifyChallengeOTP\n successAuthRedirect={successAuthRedirect}\n numInputs={6}\n shouldAutoFocus\n signUpPath={paths.signup}\n twoFactorVerifyPath={paths.two_factor_verify}\n />\n }\n />\n <Route path={matchPaths.verify_magic_link} element={<VerifyChallengeMagicLink />} />\n <Route\n path={matchPaths.forgot_password}\n element={\n <ForgotPassword\n successResetRedirect={successAuthRedirect}\n signInPath={paths.signin}\n forgotPasswordSuccessPath={paths.forgot_password_success}\n />\n }\n />\n <Route path={matchPaths.forgot_password_success} element={<ForgotPasswordSuccess />} />\n <Route\n path={matchPaths.reset_password}\n element={<ResetPassword successAuthRedirect={successAuthRedirect} twoFactorVerifyPath={paths.two_factor_verify} />}\n />\n <Route\n path={matchPaths.invitation}\n element={\n <InvitationJoin successAuthRedirect={successAuthRedirect} signInPath={paths.signin} signUpPath={paths.signup} />\n }\n />\n <Route\n path={matchPaths.two_factor_verify}\n element={\n <TwoFactorVerifyFlow\n successAuthRedirect={successAuthRedirect}\n signInPath={paths.signin}\n twoFactorSetupPath={paths.two_factor_setup}\n />\n }\n />\n <Route\n path={matchPaths.two_factor_setup}\n element={\n <TwoFactorSetupFlow\n successAuthRedirect={successAuthRedirect}\n twoFactorVerifyPath={paths.two_factor_verify}\n signInPath={paths.signin}\n />\n }\n />\n <Route\n path='*'\n element={\n <Navigate\n to={{\n pathname: paths.signin,\n search: window.location.search,\n }}\n />\n }\n />\n </Routes>\n </RouterInnerWrapperProvider>\n );\n};\n\nconst PassflowWrapper: FC<PassflowProps> = ({\n successAuthRedirect,\n federatedDisplayMode = 'redirect',\n error = undefined,\n relyingPartyId = window.location.hostname,\n pathPrefix = '',\n routerType,\n}) => {\n const { error: errorUrlSuccess, message: messageUrlSuccess } = getUrlErrors(successAuthRedirect);\n\n if (errorUrlSuccess) {\n console.error('[passflow] authentication redirect returned an error', {\n error: errorUrlSuccess,\n message: messageUrlSuccess,\n });\n throw new Error(authRedirectErrorMessage);\n }\n\n // Inside a host react-router <Router> the flow must not create its own: the\n // router is a shared peer, and a nested <Router> throws. The host's router\n // then owns history, and the flow's routes resolve under its parent route.\n const isInHostRouter = useInRouterContext();\n useEffect(() => {\n if (isInHostRouter && routerType) {\n console.warn(\n `[passflow] PassflowFlow is inside a react-router <Router>, so routerType='${routerType}' is ignored and the host router is used.`,\n );\n }\n }, [isInHostRouter, routerType]);\n\n if (error) throw new Error(error);\n\n const flowRoutes = (\n <PassflowRoutes\n successAuthRedirect={successAuthRedirect}\n federatedDisplayMode={federatedDisplayMode}\n relyingPartyId={relyingPartyId}\n pathPrefix={pathPrefix}\n />\n );\n\n if (isInHostRouter) return flowRoutes;\n\n return <RouterProvider routerType={routerType ?? 'browser'}>{flowRoutes}</RouterProvider>;\n};\n\nexport const PassflowFlow = withError(PassflowWrapper, ErrorComponent);\n","import type { FC } from 'react';\nimport { useEffect } from 'react';\nimport { useParams } from 'react-router';\nimport { TwoFactorSetupForm } from '@/components/form/two-factor-setup';\nimport { Wrapper } from '@/components/form/wrapper';\nimport { Button, Icon } from '@/components/ui';\nimport { routes } from '@/context';\nimport { type UseTwoFactorSetupMagicLinkReturn, useNavigation, useTwoFactorSetupMagicLink } from '@/hooks';\n\nimport '@/styles/index.css';\n\n/**\n * Error type for magic link validation\n */\ntype MagicLinkError = NonNullable<UseTwoFactorSetupMagicLinkReturn['error']>;\n\n/**\n * Props for TwoFactorSetupMagicLinkFlow component\n */\nexport type TwoFactorSetupMagicLinkFlowProps = {\n /** Callback after successful setup */\n onSuccess?: () => void;\n /** Callback on validation error */\n onError?: (error: MagicLinkError) => void;\n /** Whether to redirect after setup (default: true) */\n redirectOnSuccess?: boolean;\n /** Path to sign-in page (default: /signin) */\n signInPath?: string;\n};\n\n/**\n * Flow component for magic link 2FA setup\n *\n * This component:\n * 1. Extracts token from URL params\n * 2. Validates token via useTwoFactorSetupMagicLink hook\n * 3. Shows loading state during validation\n * 4. Shows error UI if validation fails\n * 5. Renders TwoFactorSetupForm if validation succeeds\n * 6. Redirects to sign-in after successful setup\n *\n * Route: /two-factor-setup-magic-link/:token\n */\nexport const TwoFactorSetupMagicLinkFlow: FC<TwoFactorSetupMagicLinkFlowProps> = ({\n onSuccess,\n onError,\n redirectOnSuccess = true,\n signInPath = routes.signin.path,\n}) => {\n const { token } = useParams<{ token: string }>();\n const { navigate } = useNavigation();\n\n // Validate magic link token\n const { isLoading, isRetrying, isValidated, error, retry, retryCountdown } = useTwoFactorSetupMagicLink(token || '');\n\n /**\n * Handle validation error\n */\n useEffect(() => {\n if (error) {\n onError?.(error);\n }\n }, [error, onError]);\n\n /**\n * Handle successful 2FA setup completion\n */\n const handleSetupComplete = () => {\n onSuccess?.();\n\n if (redirectOnSuccess) {\n // Redirect to sign-in page\n navigate({\n to: signInPath,\n });\n }\n };\n\n /**\n * Handle setup cancellation\n */\n const handleCancel = () => {\n navigate({ to: signInPath });\n };\n\n /**\n * Render: Loading state\n */\n if (isLoading) {\n return (\n <Wrapper\n title='Validating Magic Link'\n subtitle='Please wait while we verify your link...'\n className='passflow-2fa-magic-link-loading'\n >\n <div className='passflow-loading-container' role='status' aria-live='polite' aria-busy='true'>\n <Icon id='logo' type='general' size='large' className='passflow-loading-spinner' />\n <p className='passflow-loading-text'>Validating your magic link...</p>\n </div>\n </Wrapper>\n );\n }\n\n /**\n * Render: Error state\n */\n if (error) {\n const isRetryable = error.code === 'SERVER_ERROR' || error.code === 'RATE_LIMITED';\n const isRateLimited = error.code === 'RATE_LIMITED' && retryCountdown !== null && retryCountdown > 0;\n\n return (\n <Wrapper\n title='Magic Link Validation Failed'\n subtitle={getErrorSubtitle(error.code)}\n className='passflow-2fa-magic-link-error'\n >\n <div className='passflow-error-container' role='alert' aria-live='assertive'>\n <div className='passflow-error-icon'>\n <Icon id='warning' type='general' size='large' />\n </div>\n\n <p className='passflow-error-message' id='error-message'>\n {error.message}\n </p>\n\n <div className='passflow-error-actions'>\n {isRetryable && (\n <Button\n size='big'\n type='button'\n variant='primary'\n onClick={retry}\n disabled={isRateLimited || isRetrying}\n aria-describedby='error-message'\n >\n {isRetrying ? 'Retrying...' : isRateLimited ? `Try again in ${formatCountdown(retryCountdown)}` : 'Try Again'}\n </Button>\n )}\n\n <Button size='big' type='button' variant='secondary' onClick={() => navigate({ to: signInPath })}>\n Back to Sign In\n </Button>\n </div>\n\n {!isRetryable && (\n <p className='passflow-error-help-text'>Please contact your administrator to request a new magic link.</p>\n )}\n </div>\n </Wrapper>\n );\n }\n\n /**\n * Render: Success state - show 2FA setup form\n */\n if (isValidated) {\n return <TwoFactorSetupForm onComplete={handleSetupComplete} onCancel={handleCancel} />;\n }\n\n // Fallback (should not reach here)\n return null;\n};\n\n/**\n * Get user-friendly subtitle for error codes\n */\nfunction getErrorSubtitle(code: string): string {\n switch (code) {\n case 'EXPIRED_TOKEN':\n return 'This magic link has expired';\n case 'INVALID_TOKEN':\n return 'This magic link is invalid';\n case 'REVOKED_TOKEN':\n return 'This magic link has been revoked';\n case 'RATE_LIMITED':\n return 'Too many attempts';\n case 'SERVER_ERROR':\n return 'Something went wrong';\n default:\n return 'An error occurred';\n }\n}\n\n/**\n * Format countdown seconds as MM:SS\n */\nfunction formatCountdown(seconds: number | null): string {\n if (seconds === null) return '';\n const mins = Math.floor(seconds / 60);\n const secs = seconds % 60;\n return `${mins}:${secs.toString().padStart(2, '0')}`;\n}\n"],"mappings":"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AAI,eACJC,GAAI,aACJC,GAAI,cACJC,GAAI,cACJC,GAAI,cACJC,GAAI,cACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJpP,GAAI,eACJqP,GAAI,eACJC,GAAI,eACJC,GAAI,aACJC,GAAI,cACJC,GAAI,cACJC,GAAI,cACJC,GAAI,cACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,cACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,cACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,cACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,aACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,cACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,cACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,cACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,cACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,cACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,cACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJjV,GAAI,gBACJkV,GAAI,cACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,cACJC,GAAI,eACJC,GAAI,eACJC,GA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"}
|
|
1
|
+
{"version":3,"file":"index.es.js","names":["withQuestionMark","_Fragment","flags","_Fragment","error","error","error","error","err","err","passflowWithMagicLink","error","error","_Fragment","logoRed","eyeOn","eyeOff","caretDown","onePassword","browserChrome","dotsVertical","linkedin","initialValues","validationError","_Fragment","_Fragment","_Fragment","Wrapper","Wrapper","Dialog","completionOptions","Wrapper","Wrapper","_Fragment","initialValues","queryString","Wrapper","_Fragment","Wrapper","Wrapper","queryString","queryString","challengeTypeFullString","Wrapper","Wrapper","Wrapper","FETCH_PRIORITY_OIDC","Passflow","PassflowEvent","classifyUpgradeError","parseToken","registerFetchMiddleware","requiredAcrLevel","React","createContext","forwardRef","useCallback","useContext","useEffect","useId","useLayoutEffect","useMemo","useReducer","useRef","useState","useSyncExternalStore","clsx","Yup","Fragment","jsx","jsxs","DialogPrimitive","OTPInput","REGEXP_ONLY_DIGITS","REGEXP_ONLY_DIGITS_AND_CHARS","getCountryForTimezone","defaultCountries","parseCountry","usePhoneInput","qs","phone","Controller","useForm","PopoverPrimitive","ErrorBoundary","from","window","passflowReactAppVersion","console","log","AUTH_ERROR_COPY","password","message","scope","passwordless","passkey","authRedirectErrorMessage","verificationLinkErrorMessage","verificationRequestErrorMessage","authErrorFor","flow","operation","DEVICE_ERROR_COPY","code_required","code_invalid","code_expired","code_declined","code_already_approved","too_many_attempts","mode_disabled","app_unavailable","bad_credentials","missing_credentials","second_factor_invalid","missing_second_factor","account_blocked","passkey_failed","passkey_unsupported","offline","generic","RECOVERABLE","Set","REASON_TO_TYPE","invalid_user_code","unknown_user_code","expired_user_code","denied","already_approved","unknown_client","passkey_unavailable","unavailable","blocked","WEBAUTHN_NAME_TO_TYPE","NotAllowedError","AbortError","TimeoutError","UnknownError","NotSupportedError","InvalidStateError","ConstraintError","SecurityError","UNSUPPORTED_MESSAGE_PATTERNS","DeviceApiError","Error","reason","code","status","constructor","params","super","description","this","name","build","type","detail","isRecoverable","has","classifyDeviceError","err","isDOMExceptionLike","raw","lowered","toLowerCase","some","p","includes","byName","deviceErrorOfType","ERROR_PATTERNS","expired","not_enabled","invalid_code","getUserFriendlyErrorMessage","error","cn","classes","getAuthMethods","strategies","methods","internal","username","email","otp","magicLink","fim","providers","hasEmailMethods","hasSignInEmailMethods","hasPhoneMethods","hasSignInPhoneMethods","hasUsernameMethods","hasSignInUsernameMethods","strategy","identity","challenge","fim_type","fimType","push","getIdentityLabel","getPasswordlessData","currentMethod","label","challengeType","getUrlErrors","subUrl","searchParams","URLSearchParams","split","location","search","get","decodeURIComponent","getUrlWithTokens","async","passflow","url","format","tokens","getTokens","scopes","tokenParams","Object","entries","filter","_","value","map","key","encodeURIComponent","join","undefinedOnCatch","fn","t","authAction","title","completion","getInvitationAuthChrome","inviteToken","intent","invitation","tenantName","tenant_name","trim","inviterName","inviter_name","action","subtitle","routeToSecondFactor","navigate","twoFactorVerifyPath","isTwoFactorVerificationRequired","to","urlCarriesTwoFactorToken","hash","substring","STORAGE_KEY_PREFIX","REDIRECT_COUNT_KEY","LAST_ERROR_KEY","TwoFactorLoopPrevention","canRedirect","getRedirectCount","incrementRedirect","count","sessionStorage","setItem","String","getItem","Number","parseInt","reset","removeItem","setLastErrorType","errorType","getLastErrorType","isRepeatingError","getLoopDetectedMessage","activeInstance","pendingRelease","registerUpgradeAuthInstance","instance","queueMicrotask","releaseUpgradeAuthInstance","requireInstance","withAuth","next","attachAuth","SearchContext","read","write","replace","pathname","history","replaceState","pushState","useSearchSource","withQuestionMark$1","toString","useUrlParams","defaultValues","source","decodedSearch","input","DOMParser","parseFromString","documentElement","textContent","hasChanged","set","getAll","newSearchParams","delete","isValidUrl","newUrl","URL","protocol","emailRegex","passwordValidation","passwordPolicy","string","required","test","errors","min_password_length","minPasswordLength","require_lowercase","requireLowerCase","require_number","requireNumber","require_symbol","requireSymbol","require_uppercase","requireUpperCase","length","validationError","inner","path","field","ValidationError","Ripple","size","x","y","className","style","width","height","left","top","Button","variant","onClick","withIcon","asIcon","children","withRipple","pressed","rest","ripples","setRipples","styles","timer","setTimeout","clearTimeout","e","rect","currentTarget","getBoundingClientRect","rippleSize","Math","max","clientX","clientY","newRipple","Date","now","prev","ContinuingStatus","appName","role","COUNTRY_FLAG_POSITIONS","ad","ae","af","ag","ai","al","am","an","ao","aq","ar","as","at","au","aw","ax","az","ba","bb","bd","be","bf","bg","bh","bi","bj","bl","bm","bn","bo","br","bs","bt","bw","by","bz","ca","cc","cd","cf","cg","ch","ci","ck","cl","cm","co","cr","cu","cv","cw","cx","cy","cz","de","dj","dk","dm","do","dz","ec","ee","eg","eh","er","es","et","eu","fi","fj","fk","fm","fo","fr","ga","gb","gd","ge","gg","gh","gi","gl","gm","gn","gq","gr","gs","gt","gu","gw","gy","hk","hn","hr","ht","hu","ic","id","ie","il","im","in","iq","ir","is","it","je","jm","jo","jp","ke","kg","kh","ki","xk","km","kn","kp","kr","kw","ky","kz","la","lb","lc","li","lk","lr","ls","lt","lu","lv","ly","ma","mc","md","me","mf","mg","mh","mk","ml","mm","mn","mo","mp","mq","mr","ms","mt","mu","mv","mw","mx","my","mz","na","nc","ne","nf","ng","ni","nl","no","np","nr","nu","nz","om","pa","pe","pf","pg","ph","pk","pl","pn","pr","ps","pt","pw","py","qa","ro","rs","ru","rw","sa","sb","sc","sd","se","sg","sh","si","sk","sl","sm","sn","so","sr","ss","st","sv","sy","sz","tc","td","tf","tg","th","tj","tk","tl","tm","tn","tr","tt","tv","tw","tz","ua","ug","us","uy","uz","va","vc","ve","vg","vi","vn","vu","wf","ws","ye","za","zm","zw","COUNTRY_FLAG_ALIASES","bq","gf","gp","io","pm","re","yt","CountryFlag","iso2","country","normalized","candidate","getSupportedCountry","slice","toUpperCase","backgroundImage","backgroundPosition","Dialog","Root","DialogTrigger","Trigger","DialogPortal","Portal","DialogClose","Close","DialogOverlay","props","ref","Overlay","displayName","DialogContent","Content","DialogHeader","DialogFooter","DialogTitle","Title","DialogDescription","Description","CHARSETS","numeric","pattern","inputMode","alphanumeric","Slot","char","isActive","hasFakeCaret","state","FieldOtp","onChange","onComplete","charset","labelledBy","describedBy","autoFocus","maxLength","autoComplete","disabled","noScriptCSSFallback","containerClassName","render","slots","slot","position","htmlFor","generateMessage","requires","requiresString","requirements","keys","Intl","ListFormat","requirement","FieldPassword","withMessages","validationErrors","isError","isShowPassword","setIsShowPassword","errorStyles","fields","changeIcon","handleShowPassword","Icon","decorative","usePassflow","context","PassflowContext","AuthContext","AuthProvider","onSessionExpired","isLoading","setIsLoading","isSessionExpired","setIsSessionExpired","subscriber","onAuthChange","eventType","payload","SessionExpired","SignIn","Register","subscribe","unsubscribe","isAuthenticated","doRefresh","parsedTokens","getParsedTokens","logout","logOut","Provider","defaultNavigate","searchParam","startsWith","href","NavigationContext","setNavigate","router","initialState","appSettings","appId","createTenantForNewUser","parseQueryParams","isDiscoveringAppId","hasSettingsError","passflowReducer","routes","signin","signup","verify_otp","verify_magic_link","forgot_password","forgot_password_success","reset_password","two_factor_verify","two_factor_recovery","two_factor_setup","two_factor_setup_magic_link","UpgradeContext","noop","INERT_UPGRADE_CONTEXT","enabled","prompt","selectedFactor","selectFactor","submit","cancel","dismiss","elevate","Promise","resolve","nonEmpty","getBackgroundImage","image","applyLoginThemeStyles","root","property","primary_color","text_color","content_color","secondary_text_color","background_color","background_image","card_color","input_background_color","input_border_color","button_text_color","passkey_button_text_color","passkey_button_background_color","divider_color","federated_button_background_color","federated_button_text_color","getLoginThemeCssVariables","removeProperty","setProperty","useAppSettings","setIsError","errorMessage","setErrorMessage","isFetchingRef","dispatch","current","urlsToTry","response","r","fetch","ok","settings","json","discoveredAppId","login_app","app_id","setAppId","stateUpdates","discoveredScopes","createTenant","create_tenant_for_new_user","discoveryError","warn","getAppSettings","finalStateUpdates","defaults","auth_strategies","getPasswordPolicySettings","fetchAllSettings","currentTheme","theme","matchMedia","matches","login_app_theme","color_scheme","getCurrentTheme","selectedStyle","dark_style","light_style","document","loginAppTheme","currentStyles","useAuth","useAuthCloudRedirect","cloudPassflowUrl","authRedirect","readParentChallengeId","requestPath","parentChallengeId","useConsent","setStatus","info","setInfo","granted","setGranted","setError","cancelled","res","method","credentials","headers","Accept","body","catch","error_description","data","requested_scopes","fetchInfo","toggleScope","add","decide","decision","base","endpoint","granted_scopes","csrf_token","JSON","stringify","errBody","kind","form","createElement","display","appendChild","submitFormPost","allow","deny","metadataByScope","Map","scope_metadata","meta","scopeMetadata","grantedScopes","DEVICE_ENDPOINTS","SECOND_FACTOR_METHODS","parseDeviceResponse","useDeviceVerify","setEmail","userCode","setUserCode","ticketRef","firstFactorTicketRef","approveAfterSecondFactorRef","secondFactorMethods","setSecondFactorMethods","activeRef","csrf","post","user_code","fail","terminal","classified","loadInfo","submitCode","holdTicket","second_factor_required","approval_ticket","known","m","toSecondFactorMethods","second_factor_methods","authenticatePassword","emailValue","owesSecondFactor","authenticatePasskey","PublicKeyCredential","DOMException","start","startAuthentication","assertion","optionsJSON","publicKey","passkey_challenge_id","passkey_data","approveWithTicket","signInWithPassword","signInWithPasskey","approve","confirmWithPassword","confirmWithPasskey","submitSecondFactor","clearError","isSecondFactorPending","useForgotPassword","sendPasswordResetEmail","useJoinInvite","token","joinInvitation","useLogout","parseSearch","parsed","parse","fromEntries","useNavigation","setTwoFactorVerifyPath","newNavigate","options","searchParamDefault","useOutsideClick","onClickOutside","handleClick","event","contains","target","addEventListener","removeEventListener","usePasswordlessComplete","passwordlessSignInComplete","getFullRedirectUrl","redirectUrl","origin","useProvider","redirect_url","create_tenant","federatedWithPopup","provider","federatedAuthWithPopup","invite_token","federatedWithRedirect","federatedAuthWithRedirect","IDLE","isFailing","since","nextRetryAt","EVENTS","RefreshFailing","RefreshRecovered","SignOut","useRefreshStatus","failing","useResetPassword","newPassword","resetPassword","useSessionExpired","expiredReason","setExpiredReason","resetSessionExpired","useSignIn","signIn","passwordlessSignIn","passkeyAuthenticate","useSignUp","cleanup","signUp","passwordlessResponse","passkeyRegister","useTrustedDevices","setData","devices","getTrustedDevices","revoke","deviceId","revokeTrustedDevice","device","refetch","useTwoFactorChallenge","setChallenge","selectedMethod","setSelectedMethod","requestChallenge","firstFactorMethod","twoFactor","first_factor_method","verify","trustDevice","challenge_id","verifyV2","trust_device","switchMethod","switchToAlternative","useTwoFactorManage","recoveryCodes","setRecoveryCodes","disable","disableTwoFactor","regenerateCodes","regenerateTwoFactorRecoveryCodes","recovery_codes","useTwoFactorMethods","availableMethods","setAvailableMethods","registeredMethods","setRegisteredMethods","refresh","getRegisteredMethods","available","removeMethod","methodId","useTwoFactorSetup","setupData","setSetupData","step","setStep","beginSetup","beginTwoFactorSetup","confirmSetup","confirmTwoFactorSetup","useTwoFactorSetupMagicLink","isRetrying","setIsRetrying","isValidated","setIsValidated","sessionToken","setSessionToken","userId","setUserId","expiresIn","setExpiresIn","retryCountdown","setRetryCountdown","validatedToken","setValidatedToken","shouldClearOnUnmount","countdownTimerRef","startCountdown","seconds","clearInterval","setInterval","validateToken","isRetry","validateTwoFactorSetupMagicLink","success","retryAfter","retry","clearMagicLinkSession","useTwoFactorStatus","getTwoFactorStatus","useTwoFactorVerify","setErrorType","errorDetails","setErrorDetails","isVerificationRequired","handleError","normalizedMessage","shouldAutoRedirect","classifyTwoFactorError","verifyTwoFactor","useRecoveryCode","useTwoFactorRecoveryCode","EMPTY_FACTORS","useUpgrade","factors","readPromptFactors","factorTypes","factor","insufficient","obtained","errorKind","previousError","busy","useUserPasskeys","getUserPasskeys","createUserPasskey","relyingPartyId","passkeyUsername","passkeyDisplayName","addUserPasskey","editUserPasskey","newName","passkeyId","renameUserPasskey","userPasskeys","deleteUserPasskey","FieldPhone","inputProps","show","setShow","filterValue","setFilterValue","isFocused","setIsFocused","refWrapper","searchInputRef","focus","userTZ","DateTimeFormat","resolvedOptions","timeZone","userCountry","inputValue","setCountry","handlePhoneValueChange","inputRef","defaultCountry","toLocaleLowerCase","filteredCountries","defCountry","countryName","preferredCountries","allCountries","preferredIso","handleClose","restoreFocus","querySelector","handleChangeCountry","renderCountry","dialCode","tabIndex","onKeyDown","preventDefault","Array","querySelectorAll","currentIndex","indexOf","min","handleOptionKeyDown","onFocus","onBlur","placeholder","FieldText","linkedin_default","matchTextColor","icons","general","logo","warning","mail","edit","close","check","trash","google","gitlab","apple","atlassian","bitbucket","discord","dropbox","facebook","github","hubspot","linear","linkedin","linledin","microsoft","notion","slack","tiktok","twitch","twitter","xero","src","alt","Link","LoginAlert","LoginDivider","LoginActionStack","LoginProgress","LoginScreenNotice","codeTestId","appNameTestId","LoginCodeEntry","initialCode","submitLabel","testId","onSubmit","setCode","normalizedCode","autoCapitalize","autoCorrect","spellCheck","Boolean","Switch","checked","generatedId","inputId","LoginConsent","allowLabel","denyLabel","busyLabel","allowTestId","denyTestId","onToggleScope","onAllow","onDeny","item","ProvidersBox","initialValues$2","email_or_username","LoginCredentials","computedDefaultMethod","initialMethod","identities","getDefaultMethod","defaultMethod","setDefaultMethod","passkeyOnly","setPasskeyOnly","forcePasskey","previousComputedMethod","previousForcePasskey","control","getValues","trigger","watch","formState","isDirty","isValid","handleSubmit","mode","nextForcePasskey","currentIdentity","find","hasPassword","hasPasswordless","passwordlessLabel","hasPasskey","hasIdentity","showCredentialFields","showStandalonePasskey","hasCredentialActions","controlsDisabled","errorScope","hasIdentityError","hasPasswordError","isNewPassword","credentialPurpose","toCredentials","values","emailOrUsername","handleReset","onReset","handleMethodChange","submitCurrentMethod","onPassword","onPasswordless","selectedIdentityValue","alternateIdentity","notice","allowPasskeyToggle","handlePasskeyExperienceChange","primaryLabel","selectLabel","rules","requiredMessage","validate","forgotPassword","getSearch","validateSync","primaryTestId","submitPasswordless","passwordlessLabelPrefix","onPasskey","passkeyLabel","footer","onProvider","LoginDeviceApproval","actionLabel","actionTestId","onApprove","LoginGeneralError","onAction","LoginInvitation","acceptLabel","switchAccountLabel","createAccountLabel","acceptTestId","onAccept","onSwitchAccount","onCreateAccount","LoginPasskeyProgress","working","recoverable","retryLabel","onRetry","METHOD_COPY","totp","hint","switchLabel","LoginSecondFactor","onMethodChange","setMethod","alternate","copy","isTOTP","LoginScreenShell","iconId","customCss","customLogo","customLogoAlt","removeBranding","LoginStatus","tone","primaryAction","LoginScreen","chrome","content","Popover","PopoverTrigger","PopoverAnchor","Anchor","PopoverContent","align","sideOffset","Spinner","UpgradeFactorList","selected","onSelect","CODE_FIELD_ID","CODE_ERROR_ID","UpgradeChallengeView","showAlternatives","cancelLabel","alternativesLabel","onSelectFactor","onToggleAlternatives","onCancel","reported","active","codeContract","needsCode","hasAlternatives","report","trimmed","noValidate","DEFAULT_FACTOR_LABELS","email_otp","sms_otp","OTP_CODE_CONTRACT","freeze","UPGRADE_FACTOR_CODE_CONTRACTS","toDialogFactors","labels","fallback","override","readString","readRecord","DIALOG_KIND_BY_UPGRADE_KIND","wrong_code","challenge_spent","not_registered","prepare_not_required","exhausted","attempts_exhausted","session_changed","fatal","network","upgradeKindOf","record","tagged","hasOwn","hasTransportFacts","dialogOutcomeFromError","readAssuranceBar","bar","acrValues","level","maxAge","describeAssuranceBar","parts","challengeBar","requiredLevel","terminalFromError","handlers","onDismiss","retryable","toDialogState","outcome","ui","previousKind","suggested","upgradeDialogDismissHandler","TONE","unsatisfiable","transport","BarRow","term","UpgradeStatus","autoClose","autoCloseMs","autoDismiss","dismissLabel","DESCRIPTION_ID","UpgradeDialog","open","onOpenChange","ConsentFlow","screen","consent","app_name","client_id","app_logo_url","getConsentLoginScreenProps","toCredentialsError","getDeviceLoginScreenProps","authenticated","getDeviceLoginMethods","deviceNotice","DeviceVerifyFlow","attemptedPasskeyChallenge","challengeKey","isAutomaticPasskeyReady","TwoFactorSetupForm","numInputs","showSecret","setShowSecret","otpId","otpLabelId","otpErrorId","totpDigits","qr_code","secret","recoveryCode","navigator","clipboard","writeText","TwoFactorSetupFlow","signInPath","shouldBlockRender","setShouldBlockRender","MAGIC_LINK_SEGMENT","TwoFactorSetupMagicLinkFlow","tokenProp","onSuccess","onError","redirectOnSuccess","found","exec","tokenFromUrl","isRetryable","isRateLimited","getErrorSubtitle","formatCountdown","floor","padStart","methodLabels","push_fcm","push_webpush","methodIcons","MethodSelector","onSelectMethod","isOpen","onClose","handleSelect","asChild","TwoFactorChallenge","otpValue","setOtpValue","isMethodSelectorOpen","setIsMethodSelectorOpen","handleVerify","handleOtpChange","then","result","alternative_methods","code_sent_to","renderChallengeInput","TwoFactorRecoveryForm","onBack","trustDeviceLabel","setTrustDevice","handleBackToSignIn","isLoopDetected","isInputDisabled","completionOptions$1","completionOptions","TwoFactorVerifyForm","onUseRecovery","shouldAutoFocus","twoFactorSetupPath","computedSubtitle","handleSetup2FA","handleChange","errorStateOf","summaryError","summary","proof","factorsSignature","replaySignature","replay","maxBodyBytes","allowStreamingBody","UpgradeProvider","backend","interceptFetch","requireChallengeChannel","shouldIntercept","onUpgradeDiagnostic","maxAttempts","renderDialog","setPrompt","setState","setSelectedFactor","setBusy","setShowAlternatives","setOutcome","installed","setInstalled","resolveRef","requestRef","reportedSelectionRef","userCancelledRef","cancelRequestedRef","shouldInterceptRef","diagnosticRef","factorsRef","replayRef","replayPredicate","policy","settlePrompt","clearPromptView","promptHandler","request","onRequirementRaised","f","handleFlightSettled","summaryToState","summaryToOutcome","teardown","upgrade","enable","d","onFlightSettled","isArray","events","onFactorSelected","toggleAlternatives","shown","requested","statedBar","waiter","channels","imperativeChallenge","asError","dialogState","dialogProps","AUTH_ENDPOINT_PATTERN","readParentChallengeIdFromURL","bootParentChallengeId","oidcRedirectFollowed","hasFollowedOIDCRedirect","useOIDCInterceptor","isAuthURL","injectParentChallenge","obj","parent_challenge_id","followRedirectURL","assign","unregisterFetchMiddleware","init","Request","outInit","rewritten","text","clone","priority","OriginalXHROpen","XMLHttpRequest","prototype","OriginalXHRSend","send","tracker","WeakMap","urlStr","isAuth","responseText","call","outBody","useSessionExchangeOnMount","baseUrl","exchangeState","setExchangeState","parentMeta","setParentMeta","attemptedRef","oidc_prompt_login","max_age","accessPayload","access_token","idPayload","id_token","authTime","auth_time","accessToken","Authorization","oidc_prompt_none","redirect_uri","dest","run","OIDCExchangeContext","PassflowProvider","initialNavigate","config","needsDiscovery","landedWithTwoFactorToken","pending","scheduled","dispose","useDisposeOnReplace","discoveryAttemptedRef","discoverAppId","passflowValue","handleSetNavigate","flowTwoFactorVerifyPath","setFlowTwoFactorVerifyPath","resolvedTwoFactorVerifyPath","setPending","handleTokensRedirect","useSecondFactorLanding","navigationValue","oidcExchangeValue","upgradeEnabled","upgradeOptions","TwoFactorVerifyFlow","successAuthRedirect","useV2Flow","setMode","handleSuccess","initialValues$1","searchParamsForgotPasswordSchema","object","shape","oneOf","ForgotPassword","successResetRedirect","forgotPasswordSuccessPath","register","isErrorApp","errorApp","authMethods","searchSource","default_method","abortEarly","currentSubscriptions","custom_css","logo_url","remove_passflow_logo","isEmail","match","isUsername","validatedPhone","isPhone","phoneNumber","redirect","currentSearchParams","newParams","searchParamsForgotPasswordSuccessSchema","identityValue","ForgotPasswordSuccess","resendPayload","ErrorComponent","goBackRedirectTo","application_name","toErrorMessage","excludeRoutes","withError","Component","route","FallbackComponent","InvitationJoin","signUpPath","joinInvite","invitationToken","invitationTokenData","parsedTokenCache","hasAuthenticatedSession","successJoinPath","acceptInvitation","initialValues","searchParamsResetPasswordSchema","ResetPassword","clearErrors","resetToken","resetTokenData","resetTokenType","onSubmitHanlder","passwordErrors","handlePasswordChange","SignInForm","hostname","verifyOTPPath","verifyMagicLinkPath","forgotPasswordPath","loginMethods","getLoginMethodConfig","errorUrl","messageUrl","invitationChrome","completeAuthentication","handlePassword","userPayload","submitPassword","handlePasswordless","challenge_type","handlePasskey","passkeyPayload","submitPasskey","relying_party_id","force_passwordless_login","SignUpForm","getSignUpMethodConfig","completeRegistration","oidcMayOwnRedirect","user","phone_number","SignUp","challengeTypeFullString$1","VerifyChallengeMagicLink","identity_value","TimerButton","totalSecond","setSeconds","interval","VerifyChallengeSuccess","challengeTypeFullString","VerifyChallengeOTPManual","challengeId","fetchPasswordlessComplete","valueOTP","setValueOTP","paramsError","setParamsError","showSuccessMessage","setShowSuccessMessage","fetchData","refetchResponse","onClickResendHandler","VerifyChallengeOTPRedirect","missingParameters","redirectSearchParamsVerifyChallengeOtpSchema","searchParamsVerifyChallengeOtpSchema","optional","VerifyChallengeOTP","typeChallenge","redirectParams","FLOW_SCREENS","escapeRegExp","patternSource","segment","paramNames","SCREENS_BY_LENGTH","sort","a","b","decode","normalizePrefix","prefix","trimTrailingSlash","screenPath","withQuestionMark","cached","compute","last","listenTo","listener","announceUrlChange","dispatchEvent","PopStateEvent","readHash","queryAt","createHistory","routerType","initial","listeners","createMemoryHistory","PassflowRoutes","federatedDisplayMode","pathPrefix","detectedPrefix","RegExp","detectPrefix","paths","navigateRef","query","names","index","matchScreen","strayInsideFlow","isUnderPrefix","pathnameRef","FlowScreenView","PassflowFlow","controlledLocation","controlledNavigate","errorUrlSuccess","messageUrlSuccess","ownLocation","useFlowLocation"],"sources":["../package.json","../src/utils/get-app-version.ts","../src/utils/auth-error.ts","../src/utils/classify-device-error.ts","../src/utils/classify-two-factor-error.ts","../src/utils/cn.ts","../src/utils/get-auth-methods.ts","../src/utils/get-form-labels.ts","../src/utils/get-url-errors.ts","../src/utils/get-url-with-tokens.ts","../src/utils/undefined-on-catch.ts","../src/utils/invitation-auth-chrome.ts","../src/utils/second-factor.ts","../src/utils/two-factor-loop-prevention.ts","../src/utils/upgrade-auth.ts","../src/context/search-context.ts","../src/utils/url-params.ts","../src/utils/validate-url.ts","../src/utils/validation-schemas/index.ts","../src/components/ui/button/index.tsx","../src/components/ui/continuing-status/index.tsx","../src/assets/icons/flags.png","../src/components/ui/country-flag/positions.ts","../src/components/ui/country-flag/index.tsx","../src/components/ui/dialog/index.tsx","../src/components/ui/fields/field-otp.tsx","../src/components/ui/fields/field-password.tsx","../src/hooks/use-passflow.ts","../src/context/auth-context.tsx","../src/context/navigation-context.ts","../src/context/passflow-context.ts","../src/context/router-context.ts","../src/context/upgrade-context.ts","../src/utils/login-theme.ts","../src/hooks/use-app-settings.ts","../src/hooks/use-auth.ts","../src/hooks/use-auth-cloud-redirect.ts","../src/hooks/use-consent.ts","../src/hooks/use-device-verify.ts","../src/hooks/use-forgot-password.ts","../src/hooks/use-join-invite.ts","../src/hooks/use-logout.ts","../src/hooks/use-navigation.ts","../src/hooks/use-outsideclick.ts","../src/hooks/use-passwordless-complete.ts","../src/hooks/use-provider.ts","../src/hooks/use-refresh-status.ts","../src/hooks/use-reset-password.ts","../src/hooks/use-session-expired.ts","../src/hooks/use-signin.ts","../src/hooks/use-signup.ts","../src/hooks/use-trusted-devices.ts","../src/hooks/use-two-factor-challenge.ts","../src/hooks/use-two-factor-manage.ts","../src/hooks/use-two-factor-methods.ts","../src/hooks/use-two-factor-setup.ts","../src/hooks/use-two-factor-setup-magic-link.ts","../src/hooks/use-two-factor-status.ts","../src/hooks/use-two-factor-verify.ts","../src/hooks/use-upgrade.ts","../src/hooks/use-user-passkeys.ts","../src/components/ui/fields/field-phone.tsx","../src/components/ui/fields/field-text.tsx","../src/assets/icons/general/browser-chrome.svg","../src/assets/icons/general/caret-down.svg","../src/assets/icons/general/check.svg","../src/assets/icons/general/close.svg","../src/assets/icons/general/dots-vertical.svg","../src/assets/icons/general/edit.svg","../src/assets/icons/general/eye-off.svg","../src/assets/icons/general/eye-on.svg","../src/assets/icons/general/key.svg","../src/assets/icons/general/label.svg","../src/assets/icons/general/logo.svg","../src/assets/icons/general/logo-red.svg","../src/assets/icons/general/mail.svg","../src/assets/icons/general/one-password.svg","../src/assets/icons/general/passkey.svg","../src/assets/icons/general/phone.svg","../src/assets/icons/general/search.svg","../src/assets/icons/general/trash.svg","../src/assets/icons/general/warning.svg","../src/assets/icons/providers/apple.svg","../src/assets/icons/providers/atlassian.svg","../src/assets/icons/providers/bitbucket.svg","../src/assets/icons/providers/discord.svg","../src/assets/icons/providers/dropbox.svg","../src/assets/icons/providers/facebook.svg","../src/assets/icons/providers/github.svg","../src/assets/icons/providers/gitlab.svg","../src/assets/icons/providers/google.svg","../src/assets/icons/providers/hubspot.svg","../src/assets/icons/providers/linear.svg","../src/assets/icons/providers/linkedin.svg","../src/assets/icons/providers/microsoft.svg","../src/assets/icons/providers/notion.svg","../src/assets/icons/providers/slack.svg","../src/assets/icons/providers/tiktok.svg","../src/assets/icons/providers/twitch.svg","../src/assets/icons/providers/twitter.svg","../src/assets/icons/providers/xero.svg","../src/components/ui/icon/index.tsx","../src/components/ui/link/index.tsx","../src/components/ui/login-screen/shared.tsx","../src/components/ui/login-screen/code-entry.tsx","../src/components/ui/switch/index.tsx","../src/components/ui/login-screen/consent.tsx","../src/components/ui/providers-box/index.tsx","../src/components/ui/login-screen/credentials.tsx","../src/components/ui/login-screen/device-approval.tsx","../src/components/ui/login-screen/general-error.tsx","../src/components/ui/login-screen/invitation.tsx","../src/components/ui/login-screen/passkey-progress.tsx","../src/components/ui/login-screen/second-factor.tsx","../src/components/ui/login-screen/shell.tsx","../src/components/ui/login-screen/status.tsx","../src/components/ui/login-screen/login-screen.tsx","../src/components/ui/popover/index.tsx","../src/components/ui/spinner/index.tsx","../src/components/ui/upgrade-dialog/factor-list.tsx","../src/components/ui/upgrade-dialog/challenge.tsx","../src/components/ui/upgrade-dialog/state-mapping.ts","../src/components/ui/upgrade-dialog/status.tsx","../src/components/ui/upgrade-dialog/upgrade-dialog.tsx","../src/components/flow/consent/screen.ts","../src/components/flow/consent/index.tsx","../src/components/flow/device-verify/screen.ts","../src/components/flow/device-verify/index.tsx","../src/components/form/two-factor-setup/two-factor-setup-form.tsx","../src/components/flow/two-factor-setup/index.tsx","../src/components/flow/two-factor-setup-magic-link/index.tsx","../src/components/form/two-factor-challenge/method-selector.tsx","../src/components/form/two-factor-challenge/index.tsx","../src/components/form/two-factor-verify/two-factor-recovery-form.tsx","../src/components/form/two-factor-verify/two-factor-verify-form.tsx","../src/components/provider/upgrade-provider.tsx","../src/components/provider/use-dispose-on-replace.ts","../src/components/provider/passflow-provider.tsx","../src/components/flow/two-factor-verify/index.tsx","../src/components/form/forgot-password/forgot-password.tsx","../src/components/form/forgot-password/forgot-password-success.tsx","../src/components/error/index.tsx","../src/hocs/with-error.tsx","../src/components/form/invitation-join/index.tsx","../src/components/form/reset-password/index.tsx","../src/components/form/signin/index.tsx","../src/components/form/signup/index.tsx","../src/components/form/verify-challenge/verify-challenge-magic-link.tsx","../src/components/form/verify-challenge/timer-button.tsx","../src/components/form/verify-challenge/verify-challenge-success.tsx","../src/components/form/verify-challenge/verify-challenge-otp-manual.tsx","../src/components/form/verify-challenge/verify-challenge-otp-redirect.tsx","../src/components/form/verify-challenge/verify-challenge-otp.tsx","../src/components/flow/passflow/flow-router.ts","../src/components/flow/passflow/index.tsx"],"sourcesContent":["{\n \"name\": \"@passflow/react\",\n \"description\": \"Passflow React UI Kit\",\n \"version\": \"0.17.0\",\n \"type\": \"module\",\n \"files\": [\n \"dist\",\n \"CHANGELOG.md\"\n ],\n \"main\": \"dist/index.cjs\",\n \"module\": \"dist/index.es.js\",\n \"types\": \"dist/src/index.d.ts\",\n \"exports\": {\n \".\": {\n \"import\": {\n \"types\": \"./dist/src/index.d.ts\",\n \"default\": \"./dist/index.es.js\"\n },\n \"require\": {\n \"types\": \"./dist/src/index.d.cts\",\n \"default\": \"./dist/index.cjs\"\n }\n },\n \"./dist/style.css\": \"./dist/style.css\"\n },\n \"scripts\": {\n \"dev\": \"vite\",\n \"build\": \"tsc && vite build && pnpm build:types\",\n \"build:types\": \"tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json && node scripts/fix-dts-specifiers.mjs && node scripts/emit-cts-types.mjs\",\n \"prepack\": \"pnpm build\",\n \"lint\": \"biome check src\",\n \"lint:fix\": \"biome check --write src\",\n \"format\": \"biome format src\",\n \"format:fix\": \"biome format --write src\",\n \"preview\": \"vite preview\",\n \"test\": \"playwright install chromium && playwright test --config=playwright/playwright.config.ts\",\n \"test:ui\": \"playwright install chromium && playwright test --config=playwright/playwright.ui.config.ts --ui\",\n \"test:unit\": \"vitest run\",\n \"test:unit:watch\": \"vitest\",\n \"test:coverage\": \"vitest run --coverage\",\n \"storybook\": \"storybook dev -p 6006\",\n \"build-storybook\": \"storybook build\"\n },\n \"engines\": {\n \"node\": \"^22.12.0 || ^24.0.0 || >=26.0.0\"\n },\n \"peerDependencies\": {\n \"react\": \"^18.0.0 || ^19.0.0\",\n \"react-dom\": \"^18.0.0 || ^19.0.0\"\n },\n \"dependencies\": {\n \"@passflow/core\": \"^0.21.0\",\n \"@radix-ui/react-dialog\": \"^1.3.1\",\n \"@radix-ui/react-popover\": \"^1.3.1\",\n \"@simplewebauthn/browser\": \"^14.0.0\",\n \"clsx\": \"^2.1.1\",\n \"countries-and-timezones\": \"^3.11.0\",\n \"dayjs\": \"^1.11.23\",\n \"input-otp\": \"^1.5.0\",\n \"phone\": \"^3.1.72\",\n \"query-string\": \"^10.0.0\",\n \"react-error-boundary\": \"^6.1.6\",\n \"react-hook-form\": \"^7.91.0\",\n \"react-international-phone\": \"^4.8.0\",\n \"yup\": \"^1.7.1\"\n },\n \"devDependencies\": {\n \"@axe-core/playwright\": \"4.14.0\",\n \"@biomejs/biome\": \"^2.6.4\",\n \"@playwright/test\": \"^1.64.1\",\n \"@storybook/addon-a11y\": \"10.6.5\",\n \"@storybook/addon-docs\": \"10.6.5\",\n \"@storybook/addon-themes\": \"10.6.5\",\n \"@storybook/react-vite\": \"10.6.5\",\n \"@tanstack/react-router\": \"^1.170.46\",\n \"@testing-library/jest-dom\": \"^7.0.1\",\n \"@testing-library/react\": \"^16.3.3\",\n \"@testing-library/user-event\": \"^14.6.8\",\n \"@types/node\": \"^22.20.5\",\n \"@types/react\": \"^19.3.0\",\n \"@types/react-dom\": \"^19.3.0\",\n \"@vitejs/plugin-react\": \"^6.1.2\",\n \"@vitest/coverage-v8\": \"^5.0.5\",\n \"cssnano\": \"^9.9.0\",\n \"jsdom\": \"^30.1.3\",\n \"react\": \"^19.3.1\",\n \"react-dom\": \"^19.3.1\",\n \"react-router\": \"8.5.1\",\n \"storybook\": \"10.6.5\",\n \"terser\": \"^5.51.2\",\n \"tsc-alias\": \"^1.9.9\",\n \"typescript\": \"7.0.2\",\n \"vite\": \"^8.3.5\",\n \"vite-plugin-environment\": \"^1.1.4\",\n \"vitest\": \"^5.0.5\",\n \"wouter\": \"^3.13.0\"\n },\n \"authors\": [\n {\n \"name\": \"Ivan Holiak\",\n \"url\": \"https://github.com/IvanHoliak\"\n },\n {\n \"name\": \"Jack Rudenko\",\n \"url\": \"https://madappgang.com\"\n }\n ],\n \"license\": \"MIT\",\n \"bugs\": {\n \"url\": \"https://github.com/MadAppGang/passflow-react-sdk/issues\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/MadAppGang/passflow-react-sdk.git\"\n },\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"keywords\": [\n \"passflow\",\n \"auth\",\n \"authentication\",\n \"passwordless\",\n \"session\",\n \"jwt\",\n \"react\",\n \"ui\",\n \"ui-kit\",\n \"react-ui-kit\",\n \"passflow-react-ui-kit\"\n ],\n \"packageManager\": \"pnpm@12.16.1\"\n}\n","import { version } from '../../package.json';\n\ndeclare global {\n interface Window {\n passflowReactAppVersion: () => void;\n }\n}\n\n// Runs when the module loads, so it must not assume a browser: SSR and plain Node have no window.\nif (typeof window !== 'undefined') {\n window.passflowReactAppVersion = () => {\n // eslint-disable-next-line no-console\n console.log(`App Version: ${version}`);\n };\n}\n","import type { AuthFlow, AuthOperation, AuthUiError } from '@/types';\n\nconst AUTH_ERROR_COPY: Record<AuthFlow, Record<AuthOperation, AuthUiError>> = {\n 'sign-in': {\n password: {\n message: \"We couldn't sign you in. Check your details and try again.\",\n scope: 'credentials',\n },\n passwordless: {\n message: \"We couldn't start passwordless sign-in. Check your connection and try again.\",\n scope: 'form',\n },\n passkey: {\n message: \"We couldn't complete passkey sign-in. Try again or use another sign-in method.\",\n scope: 'form',\n },\n },\n 'sign-up': {\n password: {\n message: \"We couldn't create your account. Check the information you entered and try again.\",\n scope: 'form',\n },\n passwordless: {\n message: \"We couldn't start passwordless registration. Check your connection and try again.\",\n scope: 'form',\n },\n passkey: {\n message: \"We couldn't create your account with a passkey. Try again or choose another method.\",\n scope: 'form',\n },\n },\n};\n\nexport const authRedirectErrorMessage = \"We couldn't continue this authentication request. Return to the app and try again.\";\n\nexport const verificationLinkErrorMessage =\n 'This verification link is invalid or incomplete. Request a new link or code and try again.';\n\nexport const invitationLinkErrorMessage = 'This invitation link is invalid or has expired.';\n\nexport const verificationRequestErrorMessage =\n 'This verification request is no longer available. Start again to request a new link or code.';\n\nexport const authErrorFor = (flow: AuthFlow, operation: AuthOperation): AuthUiError => AUTH_ERROR_COPY[flow][operation];\n","import type { DeviceError, DeviceErrorType } from '@/types/device-errors';\n\n/**\n * Turns anything that can go wrong on the device verification page into a\n * {@link DeviceError} — a sentence a person can read, plus the technical detail\n * demoted to `detail`.\n *\n * See types/device-errors.ts for why this exists at all. In short: the raw\n * strings are written for operators, and they leak.\n */\n\n/**\n * The user-facing copy. One entry per {@link DeviceErrorType}, and this table IS\n * the contract — nothing else in the flow may produce a user-visible sentence.\n *\n * Voice notes, since these are the words on the screen where someone authorizes\n * a shell:\n * - Say what happened, then what to do. Never why, in our terms.\n * - No jargon a user did not bring with them: no \"credential\", \"authenticator\",\n * \"assertion\", \"CSRF\", \"origin\", \"token\", \"challenge\", \"resident key\".\n * \"Passkey\" stays — it is the word on the button they just tapped.\n * - Never blame them, and never imply they broke something.\n * - Where we genuinely cannot tell (see passkey_failed), say so plainly and\n * offer both remedies rather than guessing at one.\n */\nconst DEVICE_ERROR_COPY: Record<DeviceErrorType, string> = {\n code_required: 'Enter the code shown on your device to continue.',\n code_invalid: \"That code isn't right. Check the code on your device and enter it again.\",\n code_expired: 'This code has expired. Start again on your device to get a new one.',\n code_declined: 'This request was already declined. Start again on your device if you still want to sign in.',\n code_already_approved: 'This device is already signed in. You can close this page and head back to it.',\n too_many_attempts: 'Too many incorrect codes were entered. Wait a few minutes, then try again.',\n mode_disabled:\n \"This app can't be signed in to this way. Ask whoever set it up to turn on QR sign-in, or sign in from your computer instead.\",\n app_unavailable: 'The app that asked you to sign in is no longer available. Start again from your device.',\n bad_credentials: \"That email or password isn't right.\",\n missing_credentials: 'Enter your email and password to continue.',\n second_factor_invalid: \"That code isn't right. Check it and enter it again.\",\n missing_second_factor: 'Enter the code to continue.',\n account_blocked: 'This account has been blocked. Contact whoever manages it for help.',\n // The three-cause sentence is deliberate, not hedging: the browser reports\n // \"cancelled\", \"timed out\" and \"no passkey here\" identically (by design — it\n // must not become an oracle for which accounts live on a device), so naming\n // one cause would be a guess presented as a fact.\n passkey_failed:\n \"We couldn't confirm your passkey. You may have cancelled it, waited too long, or there may be no passkey for this site on this device.\",\n passkey_unsupported:\n \"This device can't use a passkey to sign in here. Use a device you've set up a passkey on, or return to the app that asked you to sign in and start again.\",\n offline: \"We couldn't reach the server. Check your connection and try again.\",\n generic: 'Something went wrong on our end. Refresh the page and try again.',\n};\n\n/** Failures the user can plausibly clear by acting on this page. */\nconst RECOVERABLE: ReadonlySet<DeviceErrorType> = new Set<DeviceErrorType>([\n 'code_required',\n 'code_invalid',\n 'bad_credentials',\n 'missing_credentials',\n 'second_factor_invalid',\n 'missing_second_factor',\n 'passkey_failed',\n 'offline',\n 'generic',\n]);\n\n/**\n * Server `reason` codes -> our types.\n *\n * The server sends a stable machine reason precisely so this mapping can exist:\n * see the deviceReason* / deviceLookupError.Code constants in\n * src/web/oidc/device_page.go and device_verify.go. Its `error_description` is\n * for operators and never reaches the screen.\n *\n * Anything absent from this table — `csrf token missing or invalid`,\n * `cross-origin request refused`, `invalid JSON body`, `auth flow manager is not\n * wired` — deliberately falls through to `generic`. Those are our bugs or our\n * attacker's business, and in both cases the user's remedy is the same and their\n * screen should say so without teaching them the word \"CSRF\".\n */\nconst REASON_TO_TYPE: Record<string, DeviceErrorType> = {\n code_required: 'code_required',\n invalid_user_code: 'code_invalid',\n unknown_user_code: 'code_invalid',\n expired_user_code: 'code_expired',\n denied: 'code_declined',\n already_approved: 'code_already_approved',\n too_many_attempts: 'too_many_attempts',\n mode_disabled: 'mode_disabled',\n unknown_client: 'app_unavailable',\n passkey_unavailable: 'app_unavailable',\n unavailable: 'app_unavailable',\n bad_credentials: 'bad_credentials',\n missing_credentials: 'missing_credentials',\n second_factor_invalid: 'second_factor_invalid',\n missing_second_factor: 'missing_second_factor',\n blocked: 'account_blocked',\n passkey_failed: 'passkey_failed',\n};\n\n/**\n * WebAuthn DOMException names -> our types.\n *\n * Only the names that reliably mean something distinct to a USER are mapped.\n * NotAllowedError is the big one and it is intentionally lossy: it covers\n * cancel, timeout AND no-matching-credential, because the spec has browsers\n * conflate them so a page cannot probe which passkeys a device holds.\n */\nconst WEBAUTHN_NAME_TO_TYPE: Record<string, DeviceErrorType> = {\n NotAllowedError: 'passkey_failed',\n AbortError: 'passkey_failed',\n TimeoutError: 'passkey_failed',\n UnknownError: 'passkey_failed',\n // The authenticator or browser cannot satisfy the request as asked.\n NotSupportedError: 'passkey_unsupported',\n InvalidStateError: 'passkey_unsupported',\n ConstraintError: 'passkey_unsupported',\n // RP ID / origin misconfiguration. A deployment bug, not a user's problem —\n // they cannot fix it, so do not invite them to retry forever.\n SecurityError: 'passkey_unsupported',\n};\n\n/**\n * Message fragments that mean \"this authenticator cannot do discoverable\n * credentials\", whatever DOMException name the browser happened to attach.\n *\n * This is here because of a specific, observed regression: a real user hit\n *\n * \"Resident credentials or empty 'allowCredentials' lists are not supported\n * at this time.\"\n *\n * — Chrome's internal string for a virtual/limited authenticator being asked for\n * a discoverable credential. Matching on text as well as on name is belt and\n * braces: the name for this case is not stable across Chrome versions, and the\n * one thing that must never happen is this sentence reaching a user again.\n */\nconst UNSUPPORTED_MESSAGE_PATTERNS: readonly string[] = [\n 'resident credentials',\n 'allowcredentials',\n 'not supported at this time',\n 'discoverable credentials',\n 'is not supported',\n];\n\n/**\n * An error carrying a server-supplied reason code. Thrown by the device API\n * client so the classifier can map precisely rather than sniff strings.\n */\nexport class DeviceApiError extends Error {\n /** Stable machine reason from the server. */\n readonly reason: string;\n /** The OAuth2 error code (`invalid_request`, `unauthorized_client`, ...). */\n readonly code: string;\n /** HTTP status. */\n readonly status: number;\n\n constructor(params: { reason: string; code: string; status: number; description: string }) {\n // The Error message is the OPERATOR's string — it goes to the console and to\n // `detail`, never to the screen. classifyDeviceError picks the user's words.\n super(params.description || params.code || `device request failed (${params.status})`);\n this.name = 'DeviceApiError';\n this.reason = params.reason;\n this.code = params.code;\n this.status = params.status;\n }\n}\n\nconst build = (type: DeviceErrorType, detail?: string): DeviceError => ({\n type,\n message: DEVICE_ERROR_COPY[type],\n detail,\n isRecoverable: RECOVERABLE.has(type),\n});\n\nconst isDOMExceptionLike = (err: unknown): err is { name: string; message: string } =>\n typeof err === 'object' && err !== null && 'name' in err && typeof (err as { name: unknown }).name === 'string';\n\n/**\n * Classify any failure from the device verification flow.\n *\n * Order matters: the server's own reason wins when we have one (it knows more\n * than we can infer), then WebAuthn's message text, then WebAuthn's name, then\n * the network, then a safe default. Every path ends in copy from\n * DEVICE_ERROR_COPY — there is deliberately no branch that forwards a raw\n * string to `message`.\n */\nexport function classifyDeviceError(err: unknown): DeviceError {\n // 1. The server told us exactly what happened.\n if (err instanceof DeviceApiError) {\n const type = REASON_TO_TYPE[err.reason] ?? 'generic';\n return build(type, `${err.code}${err.reason ? `/${err.reason}` : ''}: ${err.message}`);\n }\n\n if (isDOMExceptionLike(err)) {\n const name = err.name;\n const raw = typeof err.message === 'string' ? err.message : '';\n const detail = raw ? `${name}: ${raw}` : name;\n\n // 2. The resident-credential family, matched on text. Checked BEFORE the\n // name table because the name for this case is not dependable — see\n // UNSUPPORTED_MESSAGE_PATTERNS.\n const lowered = raw.toLowerCase();\n if (UNSUPPORTED_MESSAGE_PATTERNS.some((p) => lowered.includes(p))) {\n return build('passkey_unsupported', detail);\n }\n\n // 3. A WebAuthn name we recognise.\n const byName = WEBAUTHN_NAME_TO_TYPE[name];\n if (byName) {\n return build(byName, detail);\n }\n\n // 4. fetch() rejects with TypeError when it cannot reach the network at all.\n if (name === 'TypeError') {\n return build('offline', detail);\n }\n\n return build('generic', detail);\n }\n\n return build('generic', typeof err === 'string' ? err : undefined);\n}\n\n/**\n * The copy for a type, without an error to classify. For states that are known\n * up front rather than thrown — e.g. a browser with no WebAuthn at all.\n */\nexport function deviceErrorOfType(type: DeviceErrorType, detail?: string): DeviceError {\n return build(type, detail);\n}\n","import type { TwoFactorError } from '@/types/two-factor-errors';\n\n/**\n * Error message patterns for classification\n */\nconst ERROR_PATTERNS = {\n expired: ['2FA verification expired or not required', 'verification expired', 'session expired', 'verification not required'],\n not_enabled: ['Two-factor authentication is not enabled for this user', '2FA is not enabled', 'two-factor not enabled'],\n invalid_code: ['invalid code', 'incorrect code', 'code mismatch', 'wrong code', 'invalid 2fa code'],\n} as const;\n\n/**\n * Classify 2FA error based on error message\n *\n * @param errorMessage - Error message from SDK\n * @returns Classified error with handling strategy\n */\nexport function classifyTwoFactorError(errorMessage: string): TwoFactorError {\n const normalizedMessage = errorMessage.toLowerCase();\n\n // Check for expired session (recoverable, auto-redirect)\n if (ERROR_PATTERNS.expired.some((pattern) => normalizedMessage.includes(pattern.toLowerCase()))) {\n return {\n type: 'expired',\n message: errorMessage,\n isRecoverable: true,\n shouldAutoRedirect: true,\n };\n }\n\n // Check for 2FA not enabled (non-recoverable, NO auto-redirect)\n if (ERROR_PATTERNS.not_enabled.some((pattern) => normalizedMessage.includes(pattern.toLowerCase()))) {\n return {\n type: 'not_enabled',\n message: errorMessage,\n isRecoverable: false,\n shouldAutoRedirect: false,\n };\n }\n\n // Check for invalid code (recoverable, allow retry)\n if (ERROR_PATTERNS.invalid_code.some((pattern) => normalizedMessage.includes(pattern.toLowerCase()))) {\n return {\n type: 'invalid_code',\n message: errorMessage,\n isRecoverable: true,\n shouldAutoRedirect: false,\n };\n }\n\n // Generic error (treat as recoverable with retry)\n return {\n type: 'generic',\n message: errorMessage,\n isRecoverable: true,\n shouldAutoRedirect: false,\n };\n}\n\n/**\n * Get user-friendly error message based on error type\n */\nexport function getUserFriendlyErrorMessage(error: TwoFactorError): string {\n switch (error.type) {\n case 'expired':\n return 'Your session has expired. Redirecting to sign in...';\n case 'not_enabled':\n return 'Two-factor authentication is not enabled for your account. Please contact your administrator to enable 2FA.';\n case 'invalid_code':\n return 'Invalid code. Please check your authenticator app and try again.';\n default:\n return error.message;\n }\n}\n","import clsx, { type ClassValue } from 'clsx';\n\n// Joins class names. The library styles with `passflow-*` classes only, so\n// there are no utility-class conflicts to resolve.\nexport const cn = (...classes: ClassValue[]) => clsx(classes);\n","import type { AuthStrategies, FimStrategy, InternalStrategy, Providers } from '@passflow/core';\n\nexport type AuthMethods = {\n internal: {\n username: {\n password: boolean;\n };\n email: {\n password: boolean;\n otp: boolean;\n magicLink: boolean;\n };\n phone: {\n password: boolean;\n otp: boolean;\n magicLink: boolean;\n };\n };\n fim: {\n providers: Providers[];\n };\n passkey: boolean;\n hasEmailMethods: boolean;\n hasSignInEmailMethods: boolean;\n hasPhoneMethods: boolean;\n hasSignInPhoneMethods: boolean;\n hasUsernameMethods: boolean;\n hasSignInUsernameMethods: boolean;\n};\n\nexport const getAuthMethods = (strategies?: AuthStrategies[]): AuthMethods => {\n const methods: AuthMethods = {\n internal: {\n username: {\n password: false,\n },\n email: {\n password: false,\n otp: false,\n magicLink: false,\n },\n phone: {\n password: false,\n otp: false,\n magicLink: false,\n },\n },\n fim: {\n providers: [],\n },\n passkey: false,\n hasEmailMethods: false,\n hasSignInEmailMethods: false,\n hasPhoneMethods: false,\n hasSignInPhoneMethods: false,\n hasUsernameMethods: false,\n hasSignInUsernameMethods: false,\n };\n\n if (!strategies) return methods;\n\n for (const strategy of strategies) {\n const { identity, challenge, fim_type: fimType } = strategy.strategy as InternalStrategy & FimStrategy;\n\n switch (strategy.type) {\n case 'internal':\n switch (identity) {\n case 'email':\n if (challenge === 'magic_link') methods.internal.email.magicLink = true;\n else methods.internal.email[challenge as keyof AuthMethods['internal']['email']] = true;\n methods.hasEmailMethods = true;\n\n if (methods.internal.email.magicLink || methods.internal.email.otp || methods.internal.email.password)\n methods.hasSignInEmailMethods = true;\n\n break;\n case 'phone':\n if (challenge === 'magic_link') methods.internal.phone.magicLink = true;\n else methods.internal.phone[challenge as keyof AuthMethods['internal']['phone']] = true;\n methods.hasPhoneMethods = true;\n\n if (methods.internal.phone.magicLink || methods.internal.phone.otp || methods.internal.phone.password)\n methods.hasSignInPhoneMethods = true;\n\n break;\n case 'username':\n methods.internal.username[challenge as keyof AuthMethods['internal']['username']] = true;\n methods.hasUsernameMethods = true;\n\n if (methods.internal.username.password) methods.hasSignInUsernameMethods = true;\n\n break;\n default:\n throw new Error(`Unsupported identity type: ${identity}`);\n }\n break;\n case 'fim':\n methods.fim.providers.push(fimType);\n break;\n case 'passkey':\n methods.passkey = true;\n break;\n default:\n throw new Error(`Unsupported strategy type: ${strategy.type}`);\n }\n }\n\n return methods;\n};\n","import type { InternalStrategyChallenge } from '@passflow/core';\n/* eslint-disable complexity */\nimport type { DefaultMethod } from '@/types';\nimport type { AuthMethods } from './get-auth-methods';\n\nexport const getIdentityLabel = (methods: AuthMethods, type: 'label' | 'button') => {\n if (methods.hasSignInEmailMethods && methods.hasSignInUsernameMethods)\n return type === 'label' ? 'Email or username' : 'Use email or username';\n if (methods.hasSignInEmailMethods) return type === 'label' ? 'Email' : 'Use email';\n if (methods.hasSignInUsernameMethods) return type === 'label' ? 'Username' : 'Use username';\n\n return null;\n};\n\nexport const getPasswordlessData = (\n methods: AuthMethods,\n currentMethod: DefaultMethod | null,\n): { label: string; challengeType: InternalStrategyChallenge } | null => {\n if (currentMethod === 'phone') {\n if (methods.internal.phone.otp) return { label: 'SMS code', challengeType: 'otp' };\n if (methods.internal.phone.magicLink) return { label: 'SMS link', challengeType: 'magic_link' };\n }\n\n if (currentMethod === 'email_or_username') {\n if (methods.internal.email.otp) return { label: 'email code', challengeType: 'otp' };\n if (methods.internal.email.magicLink) return { label: 'email link', challengeType: 'magic_link' };\n }\n\n return null;\n};\n\nexport const getValidationErrorsLabel = (methods: AuthMethods) => {\n if (methods.hasSignInEmailMethods && methods.hasSignInUsernameMethods) return 'Email or username is required';\n if (methods.hasSignInEmailMethods) return 'Email is required';\n if (methods.hasSignInUsernameMethods) return 'Username is required';\n\n return 'Field is required';\n};\n","export const getUrlErrors = (subUrl?: string) => {\n const searchParams = new URLSearchParams(subUrl ? subUrl.split('?')[1] : window.location.search);\n const error = searchParams.get('error');\n const message = searchParams.get('message');\n\n return { error, message: message ? decodeURIComponent(message) : null };\n};\n","import type { Passflow } from '@passflow/core';\n\nexport type TokenUrlFormat = 'query' | 'hash';\n\nexport const getUrlWithTokens = async (passflow: Passflow, url: string, format: TokenUrlFormat = 'hash'): Promise<string> => {\n const tokens = await passflow.getTokens(false);\n\n if (tokens) {\n tokens.scopes = undefined;\n const tokenParams = Object.entries(tokens)\n // eslint-disable-next-line no-unused-vars\n .filter(([_, value]) => value)\n .map(([key, value]) => `${key}=${encodeURIComponent(value as string)}`)\n .join('&');\n\n if (format === 'hash') {\n // Use hash fragment (more secure - not sent to server)\n return `${url}#${tokenParams}`;\n }\n // Use query parameters\n return `${url}?${tokenParams}`;\n }\n return url;\n};\n","export function undefinedOnCatch<T, K>(fn: (t: K) => T): (t: K) => T | undefined {\n return (t: K) => {\n try {\n return fn(t);\n } catch (error) {\n return undefined;\n }\n };\n}\n","import { type InvitationToken, parseToken } from '@passflow/core';\nimport { undefinedOnCatch } from './undefined-on-catch';\n\nexport type InvitationAuthIntent = 'sign-in' | 'sign-up';\n\ntype InvitationAuthChrome = {\n title: string;\n subtitle: string;\n};\n\nconst authAction = {\n 'sign-in': {\n title: 'Sign in',\n completion: 'sign in',\n },\n 'sign-up': {\n title: 'Create your account',\n completion: 'create your account',\n },\n} as const;\n\nexport const getInvitationAuthChrome = (\n inviteToken: string | null | undefined,\n intent: InvitationAuthIntent,\n): InvitationAuthChrome | null => {\n if (!inviteToken) return null;\n\n const invitation = undefinedOnCatch(parseToken)(inviteToken) as InvitationToken | undefined;\n const tenantName = invitation?.tenant_name?.trim();\n const inviterName = invitation?.inviter_name?.trim();\n const action = authAction[intent];\n\n return {\n title: tenantName ? `${action.title} to join ${tenantName}.` : `${action.title} to continue your invitation.`,\n subtitle: inviterName\n ? `${inviterName} invited you. After you ${action.completion}, you'll continue to the invitation.`\n : `After you ${action.completion}, you'll continue to the invitation.`,\n };\n};\n","import type { Passflow } from '@passflow/core';\nimport type { NavigateFunction } from '@/context';\n\n/**\n * Sends a sign-in that still owes its second factor to the 2FA screen.\n *\n * Every sign-in path can end this way: the server answers with a 2FA token in\n * place of tokens, `@passflow/core` keeps it and saves no session, and\n * `isTwoFactorVerificationRequired()` reads true. The caller must then stop:\n * no success redirect, and no `getUrlWithTokens` — there are no tokens yet.\n *\n * @returns true when it navigated, so the caller returns without redirecting\n */\nexport const routeToSecondFactor = (\n passflow: Pick<Passflow, 'isTwoFactorVerificationRequired'>,\n navigate: NavigateFunction,\n twoFactorVerifyPath: string,\n): boolean => {\n if (!passflow.isTwoFactorVerificationRequired()) return false;\n navigate({ to: twoFactorVerifyPath });\n return true;\n};\n\n/**\n * Whether the current URL is a landing that owes its second factor: a\n * federated sign-in on a non-PKCE app comes back with `#tfa_token=` in the\n * fragment and no tokens. Read it before `@passflow/core` is constructed,\n * because core adopts the token and strips the fragment as it starts.\n */\nexport const urlCarriesTwoFactorToken = (): boolean => {\n if (typeof window === 'undefined' || !window.location.hash) return false;\n return new URLSearchParams(window.location.hash.substring(1)).has('tfa_token');\n};\n","const STORAGE_KEY_PREFIX = 'passflow_2fa';\nconst REDIRECT_COUNT_KEY = `${STORAGE_KEY_PREFIX}_redirect_count`;\nconst LAST_ERROR_KEY = `${STORAGE_KEY_PREFIX}_last_error_type`;\nconst MAX_REDIRECTS = 3;\n\n/**\n * Loop prevention for 2FA redirect cycles\n */\nexport const TwoFactorLoopPrevention = {\n /**\n * Check if redirect should be allowed\n * @returns true if redirect is safe, false if loop detected\n */\n canRedirect(): boolean {\n try {\n const count = this.getRedirectCount();\n return count < MAX_REDIRECTS;\n } catch {\n // If sessionStorage is unavailable, allow redirect once\n return true;\n }\n },\n\n /**\n * Increment redirect counter\n */\n incrementRedirect(): void {\n try {\n const count = this.getRedirectCount();\n sessionStorage.setItem(REDIRECT_COUNT_KEY, String(count + 1));\n } catch {\n // Silently fail if sessionStorage unavailable\n }\n },\n\n /**\n * Get current redirect count\n */\n getRedirectCount(): number {\n try {\n const value = sessionStorage.getItem(REDIRECT_COUNT_KEY);\n return value ? Number.parseInt(value, 10) : 0;\n } catch {\n return 0;\n }\n },\n\n /**\n * Reset redirect counter (call on successful auth)\n */\n reset(): void {\n try {\n sessionStorage.removeItem(REDIRECT_COUNT_KEY);\n sessionStorage.removeItem(LAST_ERROR_KEY);\n } catch {\n // Silently fail if sessionStorage unavailable\n }\n },\n\n /**\n * Track last error type to detect repeated errors\n */\n setLastErrorType(errorType: string): void {\n try {\n sessionStorage.setItem(LAST_ERROR_KEY, errorType);\n } catch {\n // Silently fail if sessionStorage unavailable\n }\n },\n\n /**\n * Get last error type\n */\n getLastErrorType(): string | null {\n try {\n return sessionStorage.getItem(LAST_ERROR_KEY);\n } catch {\n return null;\n }\n },\n\n /**\n * Check if same error is repeating\n */\n isRepeatingError(errorType: string): boolean {\n const lastError = this.getLastErrorType();\n return lastError === errorType && this.getRedirectCount() > 0;\n },\n\n /**\n * Get user-friendly message when loop is detected\n */\n getLoopDetectedMessage(): string {\n return 'Unable to complete authentication. This may be a configuration issue. Please contact support.';\n },\n};\n\nexport default TwoFactorLoopPrevention;\n","/**\n * The free-function adapters — `withAuth` and `attachAuth` (§13.5).\n *\n * The core exposes both as methods on a configured `Passflow` instance, because\n * that is where the resolved interception scope is bound. The developer-facing\n * form is a bare import, so these two functions translate one into the other\n * and do nothing else:\n *\n * ```tsx\n * import { attachAuth } from '@passflow/react';\n *\n * const api = axios.create({ baseURL: 'https://api.example.com' });\n * useEffect(() => attachAuth(api), []);\n * ```\n *\n * **NO LOGIC IN AN ADAPTER.** Neither function parses a challenge, compares a\n * bar, decides scope, counts a retry or chooses an error class. Every one of\n * those decisions lives in the core's `handleChallenge`, which is what makes\n * all four surfaces behave identically.\n *\n * The instance is published by `UpgradeProvider`, which reads it from\n * `PassflowContext` — so the binding is the provider's instance, resolved at\n * call time rather than captured at import time.\n *\n * **The publication is synchronous, during the provider's render, and that is\n * load-bearing.** React runs a child's effects before its parent's in the same\n * commit, so publishing from the provider's `useEffect` would be too late for\n * the documented `useEffect(() => attachAuth(api), [])` above: the child's\n * effect would reach `requireInstance` with nothing registered and throw, and a\n * throw inside an effect tears the tree down. Attach order must not matter, so\n * the registry is written in render.\n *\n * **And the release is deferred by a microtask, which is what makes the pair\n * survive React Strict Mode.** Strict Mode mounts, unmounts and remounts\n * effects in development, and the child-before-parent effect order holds on the\n * remount pass too — while render, which is what published the instance, does\n * not run again. So an immediate release in the provider's effect cleanup\n * leaves the registry empty exactly when the remounting child's effect reads\n * it, and `attachAuth` throws again (verified: it does). Scheduling the release\n * instead means a re-registration in the same tick cancels it, which is\n * precisely a Strict Mode remount; a real unmount has no re-registration, so\n * the release lands one microtask later. Nothing observes that gap but a caller\n * reaching for an instance that has just been torn down.\n */\n\nimport type { FetchLike, Passflow, ResponseInterceptorHost } from '@passflow/core';\n\nlet activeInstance: Passflow | null = null;\n\n/**\n * The instance a scheduled release is waiting to clear, or `null` when no\n * release is pending. Any registration clears it, which is how a Strict Mode\n * remount cancels the release its own cleanup just scheduled.\n */\nlet pendingRelease: Passflow | null = null;\n\n/**\n * Publishes the provider's `Passflow` instance to the free functions, and\n * returns an unregister suitable as a React effect cleanup.\n *\n * Last registration wins, and the returned unregister is *deferred*: it clears\n * the instance on a microtask, and only if nothing has registered in the\n * meantime. See the module comment — that deferral is what keeps a Strict Mode\n * mount → unmount → remount from leaving the free functions unbound, and it is\n * why register and release are symmetric rather than one in render and one in a\n * cleanup that nothing undoes.\n */\nexport const registerUpgradeAuthInstance = (instance: Passflow): (() => void) => {\n activeInstance = instance;\n pendingRelease = null;\n return () => {\n pendingRelease = instance;\n queueMicrotask(() => {\n // A register (or a later release) superseded this one: leave it alone.\n if (pendingRelease !== instance) return;\n pendingRelease = null;\n releaseUpgradeAuthInstance(instance);\n });\n };\n};\n\n/**\n * Clears `instance` if it is still the registered one, and does nothing\n * otherwise. Idempotent, so an effect cleanup that runs after a newer provider\n * has already published cannot unbind the live instance.\n */\nexport const releaseUpgradeAuthInstance = (instance: Passflow): void => {\n if (activeInstance === instance) activeInstance = null;\n};\n\n/** The instance the free functions bind to, or `null` outside a provider. */\nexport const upgradeAuthInstance = (): Passflow | null => activeInstance;\n\nconst requireInstance = (name: string): Passflow => {\n if (activeInstance === null) {\n throw new Error(\n `[passflow] ${name}() needs a mounted <PassflowProvider>: the interception scope is bound to a configured Passflow instance. Call it from inside your app (an effect or a component), or use passflow.${name}() from usePassflow().`,\n );\n }\n return activeInstance;\n};\n\n/**\n * Wraps a `fetch` and returns the wrapper. Installs nothing and touches no\n * global — two verbs exist because the semantics genuinely differ: an axios\n * interceptor mutates, a fetch wrapper returns.\n */\nexport const withAuth = (next?: FetchLike): FetchLike => requireInstance('withAuth').withAuth(next);\n\n/**\n * Attaches step-up handling to an axios instance the caller already owns,\n * **mutating** it, and returns the `detach()` disposer — which is exactly what\n * a React effect needs.\n *\n * The parameter is typed structurally (duck-typed on\n * `interceptors.response.use`), so this package's axios version is not a\n * constraint on the caller's.\n */\nexport const attachAuth = (instance: ResponseInterceptorHost): (() => void) =>\n requireInstance('attachAuth').attachAuth(instance);\n","import { createContext, useContext } from 'react';\n\n/**\n * Where the forms read and write their search params (`?challenge_id=…`).\n *\n * Outside PassflowFlow it is the address bar, as it always was. Inside, PassflowFlow\n * provides its own location, so the forms see the right params when the flow keeps a\n * memory or hash history, or is driven by an app router that does not use the address\n * bar. In the default browser mode both are the same URL.\n */\nexport type SearchSource = {\n /** The current search string, with its leading `?` or empty. */\n read: () => string;\n /** Moves to the same path with a new search string. */\n write: (search: string, options: { replace: boolean }) => void;\n};\n\nexport const addressBarSearch: SearchSource = {\n read: () => window.location.search,\n write: (search, { replace }) => {\n const url = `${window.location.pathname}${search}${window.location.hash}`;\n if (replace) window.history.replaceState(null, '', url);\n else window.history.pushState(null, '', url);\n },\n};\n\nexport const SearchContext = createContext<SearchSource>(addressBarSearch);\n\nexport const useSearchSource = () => useContext(SearchContext);\n","/**\n * Utility for native handling of URL parameters\n */\nimport { useSearchSource } from '../context/search-context';\n\n/**\n * Decodes HTML entities in a string\n */\nconst decodeHtmlEntities = (input: string): string => {\n const doc = new DOMParser().parseFromString(input, 'text/html');\n return doc.documentElement.textContent || '';\n};\n\nconst withQuestionMark = (params: URLSearchParams) => (params.toString() ? `?${params.toString()}` : '');\n\n/**\n * Get URL parameters. Inside PassflowFlow they come from the flow's location; outside it, from the\n * address bar.\n * @param defaultValues Default values\n * @returns Object with methods getAll, get, set\n */\nexport const useUrlParams = <T extends Record<string, string>>(defaultValues?: T) => {\n const source = useSearchSource();\n // Decode HTML entities in location.search\n const decodedSearch = decodeHtmlEntities(source.read());\n const searchParams = new URLSearchParams(decodedSearch);\n\n // Set default values if parameters don't exist\n if (defaultValues) {\n let hasChanged = false;\n\n for (const [key, value] of Object.entries(defaultValues)) {\n if (!searchParams.has(key) && value !== '') {\n searchParams.set(key, value);\n hasChanged = true;\n }\n }\n\n if (hasChanged) {\n source.write(withQuestionMark(searchParams), { replace: true });\n }\n }\n\n /**\n * Get all parameters\n */\n const getAll = () => {\n const params: Record<string, string> = {};\n\n for (const [key, value] of searchParams.entries()) {\n params[key] = value;\n }\n\n return params;\n };\n\n /**\n * Get parameter value\n * @param key Parameter key\n */\n const get = (key: string) => {\n const value = searchParams.get(key);\n return value === '' ? null : value;\n };\n\n /**\n * Set parameters\n * @param params Object with parameters\n */\n const set = (params: Record<string, string>) => {\n const newSearchParams = new URLSearchParams(source.read());\n\n for (const [key, value] of Object.entries(params)) {\n if (value === null || value === undefined || value === '') {\n newSearchParams.delete(key);\n } else {\n newSearchParams.set(key, value);\n }\n }\n\n source.write(withQuestionMark(newSearchParams), { replace: false });\n };\n\n return {\n getAll,\n get,\n set,\n };\n};\n","export const isValidUrl = (url: string): boolean => {\n try {\n const newUrl = new URL(url);\n return newUrl.protocol === 'http:' || newUrl.protocol === 'https:';\n } catch {\n return false;\n }\n};\n","/* eslint-disable complexity */\n/* eslint-disable max-len */\nimport type { PassflowPasswordPolicySettings } from '@passflow/core';\nimport * as Yup from 'yup';\n\nexport const emailRegex =\n /^(([^<>()[\\]\\\\.,;:\\s@\"]+(\\.[^<>()[\\]\\\\.,;:\\s@\"]+)*)|.(\".+\"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\])|(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$/;\nexport const phoneNumberRegex =\n /^(\\+{0,})(\\d{0,})([(]{1}\\d{1,3}[)]{0,}){0,}(\\s?\\d+|\\+\\d{2,3}\\s{1}\\d+|\\d+){1}[\\s|-]?\\d+([\\s|-]?\\d+){1,2}(\\s){0,}$/gm;\n\nexport const passwordValidation = (passwordPolicy: PassflowPasswordPolicySettings | null) =>\n Yup.string()\n .required()\n .test({\n test: (value: string) => {\n const errors: string[] = [];\n\n if (passwordPolicy) {\n const {\n min_password_length: minPasswordLength,\n require_lowercase: requireLowerCase,\n require_number: requireNumber,\n require_symbol: requireSymbol,\n require_uppercase: requireUpperCase,\n } = passwordPolicy;\n\n if ((value ?? '').length < minPasswordLength) errors.push('length');\n if (requireUpperCase && !/[A-Z]/.test(value)) errors.push('uppercase');\n if (requireLowerCase && !/[a-z]/.test(value)) errors.push('lowercase');\n if (requireNumber && !/\\d/.test(value)) errors.push('number');\n if (requireSymbol && !/[!@#$%^&*()_+{}[\\]:;<>,.?~\\\\-]/.test(value)) errors.push('symbol');\n }\n\n if (errors.length > 0) {\n const validationError = {\n errors,\n inner: true,\n path: 'password',\n field: 'password',\n message: errors,\n value,\n name: 'ValidationError',\n } as Yup.ValidationError & {\n inner: boolean;\n field: string;\n message: string[];\n };\n\n return new Yup.ValidationError(validationError, value, 'password');\n }\n\n return true;\n },\n });\n","/* eslint-disable react/button-has-type */\n/* eslint-disable react/jsx-props-no-spreading */\nimport {\n type ButtonHTMLAttributes,\n type CSSProperties,\n type FC,\n type JSX,\n type MouseEvent,\n type PropsWithChildren,\n useEffect,\n useState,\n} from 'react';\nimport { cn } from '@/utils';\nimport '@/styles/index.css';\n\ntype RippleProps = {\n size: number;\n x: number;\n y: number;\n};\n\nexport const Ripple: FC<RippleProps> = ({ size, x, y }) => {\n const style: CSSProperties = {\n width: size,\n height: size,\n left: x,\n top: y,\n };\n\n return <span className='passflow-ripple passflow-ripple-effect' style={style} />;\n};\n\ntype TButton = PropsWithChildren &\n ButtonHTMLAttributes<HTMLButtonElement> & {\n size: 'small' | 'medium' | 'big';\n /**\n * `link` is an action set in running text: no box, link colour, no ripple.\n */\n variant: 'primary' | 'secondary' | 'outlined' | 'warning' | 'clean' | 'provider' | 'dark' | 'option' | 'link';\n type: 'button' | 'submit' | 'reset';\n withIcon?: boolean;\n asIcon?: boolean;\n className?: string;\n withRipple?: boolean;\n /**\n * The `option` variant's second line — the hint under the label. Rendered\n * only by that variant, which owns the two-line geometry. It is part of the\n * button's accessible name (\"label hint\"), because it is visible text.\n */\n description?: string;\n /**\n * Toggle state for the `option` variant: mirrored to `aria-pressed` and\n * styled by the variant itself, so no call site has to describe what\n * \"selected\" looks like.\n */\n pressed?: boolean;\n };\n\nexport const Button: FC<TButton> = ({\n size,\n variant,\n type,\n onClick,\n withIcon = false,\n asIcon = false,\n className = '',\n children,\n withRipple = true,\n description,\n pressed,\n ...rest\n}) => {\n const [ripples, setRipples] = useState<JSX.Element[]>();\n\n const styles = {\n 'passflow-button passflow-button--big': size === 'big',\n 'passflow-button passflow-button--medium': size === 'medium',\n 'passflow-button passflow-button--small': size === 'small',\n 'passflow-button--primary': variant === 'primary',\n 'passflow-button--secondary': variant === 'secondary',\n 'passflow-button--outlined': variant === 'outlined',\n 'passflow-button--warning': variant === 'warning',\n 'passflow-button--clean': variant === 'clean',\n 'passflow-button--provider': variant === 'provider',\n 'passflow-button--dark': variant === 'dark',\n 'passflow-button--option': variant === 'option',\n 'passflow-button--link': variant === 'link',\n 'passflow-button--with-icon': withIcon,\n 'passflow-button--as-icon': asIcon,\n };\n\n const handleClick = (e: MouseEvent<HTMLButtonElement>) => {\n const rect = e.currentTarget.getBoundingClientRect();\n const rippleSize = Math.max(rect.width, rect.height);\n const x = e.clientX - rect.left - rippleSize / 2;\n const y = e.clientY - rect.top - rippleSize / 2;\n\n const newRipple = <Ripple key={Date.now()} size={rippleSize} x={x} y={y} />;\n\n setRipples((prev) => (prev ? [...prev, newRipple] : [newRipple]));\n\n onClick?.(e);\n };\n\n useEffect(() => {\n let timer: NodeJS.Timeout;\n if (ripples) {\n timer = setTimeout(() => {\n setRipples(undefined);\n }, 1000);\n }\n return () => clearTimeout(timer);\n }, [ripples]);\n\n return (\n <button className={cn(styles, className)} type={type} aria-pressed={pressed} onClick={handleClick} {...rest}>\n {variant === 'option' ? (\n // WCAG 2.5.3 (Label in Name): the button is named from its content, so\n // both visible lines are in the name (\"label hint\") and a voice user can\n // say what they see. The space keeps the two lines separate words in\n // that name; the column flex layout does not render it.\n <>\n <span className='passflow-button__option-label'>{children}</span>\n {description ? (\n <>\n {' '}\n <span className='passflow-button__option-hint'>{description}</span>\n </>\n ) : null}\n </>\n ) : (\n children\n )}\n {withRipple && variant !== 'link' && (\n <div aria-hidden className='passflow-ripple-container'>\n {ripples}\n </div>\n )}\n </button>\n );\n};\n","import type { FC } from 'react';\nimport './style.css';\n\nexport type ContinuingStatusProps = {\n /** The app the user is being taken to; without it the line stays generic. */\n appName?: string;\n};\n\n/** The full-page line shown while a session is handed over to the app that asked for it. */\nexport const ContinuingStatus: FC<ContinuingStatusProps> = ({ appName }) => (\n <div className='passflow-continuing-status' role='status'>\n {appName ? `Continuing to ${appName}…` : 'Continuing…'}\n </div>\n);\n","export default \"data:image/png;base64,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\"","// Coordinates in the bundled 408×384 flag sprite.\n// Geometry belongs to CountryFlag so consumers never construct sprite styles.\nexport const COUNTRY_FLAG_POSITIONS = {\n ad: '-48px -27px',\n ae: '-72px -27px',\n af: '-96px -27px',\n ag: '-120px -27px',\n ai: '-144px -27px',\n al: '-168px -27px',\n am: '-192px -27px',\n an: '-216px -27px',\n ao: '-240px -27px',\n aq: '-264px -27px',\n ar: '-288px -27px',\n as: '-312px -27px',\n at: '-336px -27px',\n au: '-360px -27px',\n aw: '-384px -27px',\n ax: '-0px -51px',\n az: '-24px -51px',\n ba: '-48px -51px',\n bb: '-72px -51px',\n bd: '-96px -51px',\n be: '-120px -51px',\n bf: '-144px -51px',\n bg: '-168px -51px',\n bh: '-192px -51px',\n bi: '-216px -51px',\n bj: '-240px -51px',\n bl: '-264px -51px',\n bm: '-288px -51px',\n bn: '-312px -51px',\n bo: '-336px -51px',\n br: '-360px -51px',\n bs: '-384px -51px',\n bt: '-0px -75px',\n bw: '-24px -75px',\n by: '-48px -75px',\n bz: '-72px -75px',\n ca: '-96px -75px',\n cc: '-120px -75px',\n cd: '-144px -75px',\n cf: '-168px -75px',\n cg: '-192px -75px',\n ch: '-216px -75px',\n ci: '-240px -75px',\n ck: '-264px -75px',\n cl: '-288px -75px',\n cm: '-312px -75px',\n cn: '-336px -75px',\n co: '-360px -75px',\n cr: '-384px -75px',\n cu: '-0px -99px',\n cv: '-24px -99px',\n cw: '-48px -99px',\n cx: '-72px -99px',\n cy: '-96px -99px',\n cz: '-120px -99px',\n de: '-144px -99px',\n dj: '-168px -99px',\n dk: '-192px -99px',\n dm: '-216px -99px',\n do: '-240px -99px',\n dz: '-264px -99px',\n ec: '-288px -99px',\n ee: '-312px -99px',\n eg: '-336px -99px',\n eh: '-360px -99px',\n er: '-384px -99px',\n es: '-0px -123px',\n et: '-24px -123px',\n eu: '-48px -123px',\n fi: '-72px -123px',\n fj: '-96px -123px',\n fk: '-120px -123px',\n fm: '-144px -123px',\n fo: '-168px -123px',\n fr: '-192px -123px',\n ga: '-216px -123px',\n gb: '-240px -123px',\n gd: '-264px -123px',\n ge: '-288px -123px',\n gg: '-312px -123px',\n gh: '-336px -123px',\n gi: '-360px -123px',\n gl: '-384px -123px',\n gm: '-0px -147px',\n gn: '-24px -147px',\n gq: '-48px -147px',\n gr: '-72px -147px',\n gs: '-96px -147px',\n gt: '-120px -147px',\n gu: '-144px -147px',\n gw: '-168px -147px',\n gy: '-192px -147px',\n hk: '-216px -147px',\n hn: '-240px -147px',\n hr: '-264px -147px',\n ht: '-288px -147px',\n hu: '-312px -147px',\n ic: '-336px -147px',\n id: '-360px -147px',\n ie: '-384px -147px',\n il: '-0px -171px',\n im: '-24px -171px',\n in: '-48px -171px',\n iq: '-72px -171px',\n ir: '-96px -171px',\n is: '-120px -171px',\n it: '-144px -171px',\n je: '-168px -171px',\n jm: '-192px -171px',\n jo: '-216px -171px',\n jp: '-240px -171px',\n ke: '-264px -171px',\n kg: '-288px -171px',\n kh: '-312px -171px',\n ki: '-336px -171px',\n xk: '-144px 3px',\n km: '-360px -171px',\n kn: '-384px -171px',\n kp: '-0px -195px',\n kr: '-24px -195px',\n kw: '-48px -195px',\n ky: '-72px -195px',\n kz: '-96px -195px',\n la: '-120px -195px',\n lb: '-144px -195px',\n lc: '-168px -195px',\n li: '-192px -195px',\n lk: '-216px -195px',\n lr: '-240px -195px',\n ls: '-264px -195px',\n lt: '-288px -195px',\n lu: '-312px -195px',\n lv: '-336px -195px',\n ly: '-360px -195px',\n ma: '-384px -195px',\n mc: '-0px -219px',\n md: '-24px -219px',\n me: '-48px -219px',\n mf: '-72px -219px',\n mg: '-96px -219px',\n mh: '-120px -219px',\n mk: '-144px -219px',\n ml: '-168px -219px',\n mm: '-192px -219px',\n mn: '-216px -219px',\n mo: '-240px -219px',\n mp: '-264px -219px',\n mq: '-288px -219px',\n mr: '-312px -219px',\n ms: '-336px -219px',\n mt: '-360px -219px',\n mu: '-384px -219px',\n mv: '-0px -243px',\n mw: '-24px -243px',\n mx: '-48px -243px',\n my: '-72px -243px',\n mz: '-96px -243px',\n na: '-120px -243px',\n nc: '-144px -243px',\n ne: '-168px -243px',\n nf: '-192px -243px',\n ng: '-216px -243px',\n ni: '-240px -243px',\n nl: '-264px -243px',\n no: '-288px -243px',\n np: '-312px -243px',\n nr: '-336px -243px',\n nu: '-360px -243px',\n nz: '-384px -243px',\n om: '-0px -267px',\n pa: '-24px -267px',\n pe: '-48px -267px',\n pf: '-72px -267px',\n pg: '-96px -267px',\n ph: '-120px -267px',\n pk: '-192px -267px',\n pl: '-216px -267px',\n pn: '-240px -267px',\n pr: '-264px -267px',\n ps: '-288px -267px',\n pt: '-312px -267px',\n pw: '-336px -267px',\n py: '-360px -267px',\n qa: '-384px -267px',\n ro: '-0px -291px',\n rs: '-24px -291px',\n ru: '-48px -291px',\n rw: '-72px -291px',\n sa: '-96px -291px',\n sb: '-120px -291px',\n sc: '-144px -291px',\n sd: '-168px -291px',\n se: '-192px -291px',\n sg: '-216px -291px',\n sh: '-240px -291px',\n si: '-264px -291px',\n sk: '-288px -291px',\n sl: '-312px -291px',\n sm: '-336px -291px',\n sn: '-360px -291px',\n so: '-384px -291px',\n sr: '-0px -315px',\n ss: '-24px -315px',\n st: '-48px -315px',\n sv: '-72px -315px',\n sy: '-96px -315px',\n sz: '-120px -315px',\n tc: '-144px -315px',\n td: '-168px -315px',\n tf: '-192px -315px',\n tg: '-216px -315px',\n th: '-240px -315px',\n tj: '-264px -315px',\n tk: '-288px -315px',\n tl: '-312px -315px',\n tm: '-336px -315px',\n tn: '-360px -315px',\n to: '-384px -315px',\n tr: '-0px -339px',\n tt: '-24px -339px',\n tv: '-48px -339px',\n tw: '-72px -339px',\n tz: '-96px -339px',\n ua: '-120px -339px',\n ug: '-144px -339px',\n us: '-168px -339px',\n uy: '-192px -339px',\n uz: '-216px -339px',\n va: '-240px -339px',\n vc: '-264px -339px',\n ve: '-288px -339px',\n vg: '-312px -339px',\n vi: '-336px -339px',\n vn: '-360px -339px',\n vu: '-384px -339px',\n wf: '-0px -363px',\n ws: '-24px -363px',\n ye: '-48px -363px',\n za: '-96px -363px',\n zm: '-120px -363px',\n zw: '-144px -363px',\n} as const;\n\nexport type SupportedCountryFlag = keyof typeof COUNTRY_FLAG_POSITIONS;\n","import type { CSSProperties, FC } from 'react';\nimport flags from '@/assets/icons/flags.png';\nimport { cn } from '@/utils';\nimport { COUNTRY_FLAG_POSITIONS, type SupportedCountryFlag } from './positions';\nimport './style.css';\n\nexport type CountryFlagProps = {\n iso2: string;\n className?: string;\n};\n\nconst COUNTRY_FLAG_ALIASES: Record<string, SupportedCountryFlag> = {\n bq: 'nl',\n gf: 'fr',\n gp: 'fr',\n io: 'gb',\n pm: 'fr',\n re: 'fr',\n yt: 'fr',\n};\n\nconst getSupportedCountry = (iso2: string): SupportedCountryFlag | null => {\n const normalized = iso2.trim().toLowerCase();\n const candidate = COUNTRY_FLAG_ALIASES[normalized] ?? normalized;\n return candidate in COUNTRY_FLAG_POSITIONS ? (candidate as SupportedCountryFlag) : null;\n};\n\nexport const CountryFlag: FC<CountryFlagProps> = ({ iso2, className }) => {\n const country = getSupportedCountry(iso2);\n\n if (!country) {\n return (\n <span\n aria-hidden='true'\n className={cn('passflow-country-flag passflow-country-flag--fallback', className)}\n data-country-flag={iso2.toLowerCase()}\n >\n {iso2.slice(0, 2).toUpperCase() || '–'}\n </span>\n );\n }\n\n const style: CSSProperties = {\n backgroundImage: `url(${flags})`,\n backgroundPosition: COUNTRY_FLAG_POSITIONS[country],\n };\n\n return (\n <span\n aria-hidden='true'\n className={cn('passflow-country-flag', className)}\n data-country-flag={iso2.toLowerCase()}\n style={style}\n />\n );\n};\n","import * as DialogPrimitive from '@radix-ui/react-dialog';\n/* eslint-disable react/jsx-props-no-spreading */\nimport { type ComponentPropsWithoutRef, type ElementRef, forwardRef, type HTMLAttributes } from 'react';\nimport { cn } from '@/utils';\n\nconst Dialog = DialogPrimitive.Root;\n\nconst DialogTrigger = DialogPrimitive.Trigger;\n\nconst DialogPortal = DialogPrimitive.Portal;\n\nconst DialogClose = DialogPrimitive.Close;\n\nconst DialogOverlay = forwardRef<\n ElementRef<typeof DialogPrimitive.Overlay>,\n ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>\n>(({ className, ...props }, ref) => (\n <DialogPrimitive.Overlay ref={ref} className={cn('passflow-dialog-overlay', className)} {...props} />\n));\nDialogOverlay.displayName = DialogPrimitive.Overlay.displayName;\n\nconst DialogContent = forwardRef<\n ElementRef<typeof DialogPrimitive.Content>,\n ComponentPropsWithoutRef<typeof DialogPrimitive.Content>\n>(({ className, children, ...props }, ref) => (\n <DialogPortal>\n <DialogOverlay />\n <DialogPrimitive.Content ref={ref} className={cn('passflow-dialog-content', className)} {...props}>\n {children}\n </DialogPrimitive.Content>\n </DialogPortal>\n));\nDialogContent.displayName = DialogPrimitive.Content.displayName;\n\nconst DialogHeader = ({ className, ...props }: HTMLAttributes<HTMLDivElement>) => (\n <div className={cn('passflow-dialog-header', className)} {...props} />\n);\nDialogHeader.displayName = 'DialogHeader';\n\nconst DialogFooter = ({ className, ...props }: HTMLAttributes<HTMLDivElement>) => (\n <div className={cn('passflow-dialog-footer', className)} {...props} />\n);\nDialogFooter.displayName = 'DialogFooter';\n\nconst DialogTitle = forwardRef<\n ElementRef<typeof DialogPrimitive.Title>,\n ComponentPropsWithoutRef<typeof DialogPrimitive.Title>\n>(({ className, ...props }, ref) => (\n <DialogPrimitive.Title ref={ref} className={cn('passflow-dialog-title', className)} {...props} />\n));\nDialogTitle.displayName = DialogPrimitive.Title.displayName;\n\nconst DialogDescription = forwardRef<\n ElementRef<typeof DialogPrimitive.Description>,\n ComponentPropsWithoutRef<typeof DialogPrimitive.Description>\n>(({ className, ...props }, ref) => (\n <DialogPrimitive.Description ref={ref} className={cn('passflow-dialog-description', className)} {...props} />\n));\nDialogDescription.displayName = DialogPrimitive.Description.displayName;\n\nexport {\n Dialog,\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogOverlay,\n DialogPortal,\n DialogTitle,\n DialogTrigger,\n};\n","import { OTPInput, REGEXP_ONLY_DIGITS, REGEXP_ONLY_DIGITS_AND_CHARS, type SlotProps } from 'input-otp';\nimport type { FC } from 'react';\nimport { cn } from '@/utils';\nimport '@/styles/index.css';\nimport './field-otp.css';\n\nexport type FieldOtpCharset = 'numeric' | 'alphanumeric';\n\nexport type FieldOtpState = 'default' | 'error' | 'disabled';\n\ntype FieldOtpBaseProps = {\n /** Id of the one real `<input>`; the boxes are drawn from its value. */\n id: string;\n /** Form field name, for a native form submit. */\n name?: string;\n /** Number of characters in the code, and of boxes drawn. */\n length: number;\n value: string;\n onChange: (value: string) => void;\n /** Called once the code reaches `length` characters. */\n onComplete?: (value: string) => void;\n /** Which characters are accepted; also picks the on-screen keyboard. Default `numeric`. */\n charset?: FieldOtpCharset;\n /** `error` marks the code invalid (`aria-invalid`); `disabled` locks it. Default `default`. */\n state?: FieldOtpState;\n /** Id of the element that describes it, such as the error message. */\n describedBy?: string;\n autoFocus?: boolean;\n};\n\n/**\n * The code field is named either by a visible label it draws itself (`label`),\n * or by an element the screen already shows (`labelledBy`), never both. A\n * hidden-only name fails axe `label-title-only` once `describedBy` is set.\n */\nexport type FieldOtpProps = FieldOtpBaseProps &\n (\n | {\n /** Visible prompt drawn above the boxes, as the field's `<label>`. */\n label: string;\n labelledBy?: never;\n }\n | {\n /** Id of a visible element on the screen that names the code field, such as a prompt or heading. */\n labelledBy: string;\n label?: never;\n }\n );\n\nconst CHARSETS: Record<FieldOtpCharset, { pattern: string; inputMode: 'numeric' | 'text' }> = {\n numeric: { pattern: REGEXP_ONLY_DIGITS, inputMode: 'numeric' },\n alphanumeric: { pattern: REGEXP_ONLY_DIGITS_AND_CHARS, inputMode: 'text' },\n};\n\ntype SlotViewProps = SlotProps & { state: FieldOtpState };\n\nconst Slot: FC<SlotViewProps> = ({ char, isActive, hasFakeCaret, state }) => (\n <div\n className={cn('passflow-field-otp', {\n 'passflow-field-otp--active': isActive,\n 'passflow-field-otp--error': state === 'error',\n 'passflow-field-otp--disabled': state === 'disabled',\n })}\n >\n {char}\n {hasFakeCaret ? <span className='passflow-field-otp__caret' /> : null}\n </div>\n);\n\n/**\n * A one-time code entered as a row of boxes.\n *\n * There is one real `<input>` (named, `autocomplete=\"one-time-code\"`), so SMS\n * autofill, password managers and pasting a whole code all work. The boxes are\n * a drawing of its value, hidden from assistive technology. With `label` the\n * field draws its own visible label above the boxes; with `labelledBy` it is\n * named by a prompt the screen already shows.\n */\nexport const FieldOtp: FC<FieldOtpProps> = ({\n id,\n name,\n length,\n value,\n onChange,\n onComplete,\n charset = 'numeric',\n state = 'default',\n label,\n labelledBy,\n describedBy,\n autoFocus = false,\n}) => {\n const { pattern, inputMode } = CHARSETS[charset];\n\n const input = (\n <OTPInput\n id={id}\n name={name}\n maxLength={length}\n value={value}\n onChange={onChange}\n onComplete={onComplete}\n pattern={pattern}\n inputMode={inputMode}\n autoComplete='one-time-code'\n disabled={state === 'disabled'}\n aria-labelledby={labelledBy}\n aria-describedby={describedBy}\n aria-invalid={state === 'error' ? true : undefined}\n autoFocus={autoFocus}\n noScriptCSSFallback={null}\n containerClassName={cn('passflow-field-otp-group', { 'passflow-field-otp-group--disabled': state === 'disabled' })}\n render={({ slots }) => (\n <div className='passflow-field-otp-slots' aria-hidden>\n {slots.map((slot, position) => (\n // Slots are positions in the code: the index is their identity.\n // biome-ignore lint/suspicious/noArrayIndexKey: a slot is its position\n <Slot key={position} {...slot} state={state} />\n ))}\n </div>\n )}\n />\n );\n\n if (label === undefined) return input;\n\n return (\n <div className='passflow-field-otp-field'>\n <label htmlFor={id} className='passflow-field-label'>\n {label}\n </label>\n {input}\n </div>\n );\n};\n","/* eslint-disable react/jsx-props-no-spreading */\nimport { forwardRef, type InputHTMLAttributes, useState } from 'react';\nimport { Button, Icon } from '..';\nimport '@/styles/index.css';\nimport type { PassflowPasswordPolicySettings } from '@passflow/core';\nimport { cn } from '@/utils';\n\ntype TFieldPassword = InputHTMLAttributes<HTMLInputElement> & {\n id: string;\n value: string;\n passwordPolicy: PassflowPasswordPolicySettings | null;\n withMessages?: boolean;\n validationErrors?: string | string[];\n isError?: boolean;\n className?: string;\n disabled?: boolean;\n};\n\nconst generateMessage = (\n requires: Record<'requireLowerCase' | 'requireUpperCase' | 'requireSymbol' | 'requireNumber', boolean>,\n) => {\n const requiresString = {\n requireNumber: 'number',\n requireSymbol: 'symbol',\n requireLowerCase: 'lowercase letter',\n requireUpperCase: 'uppercase letter',\n };\n const requirements = Object.keys(requires).filter((key) => requires[key as keyof typeof requires]);\n const requirementsString = new Intl.ListFormat('en').format(\n requirements.map((requirement) => requiresString[requirement as keyof typeof requiresString]),\n );\n\n return `Must contain a ${requirementsString}`;\n};\n\nexport const FieldPassword = forwardRef<HTMLInputElement, TFieldPassword>(\n (\n {\n id,\n value,\n passwordPolicy,\n withMessages = false,\n validationErrors = [],\n isError = false,\n className = '',\n disabled = false,\n ...rest\n },\n ref,\n ) => {\n const [isShowPassword, setIsShowPassword] = useState(false);\n\n const styles = {\n 'passflow-field--error': isError,\n };\n\n const errorStyles = (fields: string[]) => {\n if (value.length > 0 && !fields.some((field) => validationErrors.includes(field)))\n return 'passflow-password-validation-item--success';\n return null;\n };\n\n const changeIcon = (fields: string[]) => {\n if (value.length > 0 && !fields.some((field) => validationErrors.includes(field))) return 'check';\n return 'close';\n };\n\n const handleShowPassword = () => setIsShowPassword((prev) => !prev);\n\n const minPasswordLength = passwordPolicy?.min_password_length ?? 0;\n const requireLowerCase = passwordPolicy?.require_lowercase ?? false;\n const requireNumber = passwordPolicy?.require_number ?? false;\n const requireSymbol = passwordPolicy?.require_symbol ?? false;\n const requireUpperCase = passwordPolicy?.require_uppercase ?? false;\n\n return (\n <>\n <div className='passflow-field-wrapper'>\n <input\n ref={ref}\n id={id}\n value={value}\n type={isShowPassword ? 'text' : 'password'}\n className={cn('passflow-field-input passflow-field--focused passflow-field-input--with-icon', styles, className)}\n disabled={disabled}\n {...rest}\n />\n {isShowPassword ? (\n <Button\n className='passflow-button-display-password passflow-field-icon-button'\n size='small'\n type='button'\n variant='clean'\n asIcon\n withIcon\n disabled={disabled}\n aria-label='Hide password'\n onClick={handleShowPassword}\n >\n <Icon size='small' type='general' id='eye-on' decorative />\n </Button>\n ) : (\n <Button\n className='passflow-button-display-password passflow-field-icon-button'\n size='small'\n type='button'\n variant='clean'\n asIcon\n withIcon\n disabled={disabled}\n aria-label='Show password'\n onClick={handleShowPassword}\n >\n <Icon size='small' type='general' id='eye-off' decorative />\n </Button>\n )}\n </div>\n {withMessages && passwordPolicy && (\n <div className='passflow-password-validation'>\n <p className={cn('passflow-password-validation-item', errorStyles(['length']))}>\n <Icon size='small' id={changeIcon(['length'])} type='general' className={cn(errorStyles(['length']))} />\n At least {minPasswordLength} characters\n </p>\n <p className={cn('passflow-password-validation-item', errorStyles(['uppercase', 'lowercase', 'number', 'symbol']))}>\n <Icon\n size='small'\n id={changeIcon(['uppercase', 'lowercase', 'number', 'symbol'])}\n type='general'\n className={cn(errorStyles(['uppercase', 'lowercase', 'number', 'symbol']))}\n />\n {generateMessage({\n requireNumber,\n requireSymbol,\n requireLowerCase,\n requireUpperCase,\n })}\n </p>\n </div>\n )}\n </>\n );\n },\n);\n","import type { Passflow } from '@passflow/core';\nimport { useContext } from 'react';\nimport { PassflowContext } from '@/context';\n\nexport const usePassflow = (): Passflow => {\n const context = useContext(PassflowContext);\n if (!context) {\n throw new Error('useAuth must be used within an PassflowProvider');\n }\n\n const { passflow } = context;\n\n return passflow;\n};\n","import {\n type ParsedTokens,\n PassflowEvent,\n type PassflowSubscriber,\n type SessionExpiredReason,\n type Tokens,\n} from '@passflow/core';\nimport { createContext, type FC, type PropsWithChildren, useCallback, useEffect, useState } from 'react';\nimport { usePassflow } from '../hooks/use-passflow';\n\nexport type SessionExpiredHandler = (reason: SessionExpiredReason) => void;\n\nexport type AuthContextValue = {\n isAuthenticated: () => boolean;\n logout: () => void;\n isLoading: boolean;\n isSessionExpired: boolean;\n getTokens: (doRefresh: boolean) => Promise<{ tokens: Tokens | undefined; parsedTokens: ParsedTokens | undefined }>;\n};\n\nexport const AuthContext = createContext<AuthContextValue | undefined>(undefined);\n\nexport type AuthProviderProps = PropsWithChildren<{\n /**\n * Called when the session has really ended: last auth strike, no successor token pair\n * in time, or another user's tokens in storage. A transient refresh failure keeps the\n * session and does not call this. Use this to redirect to your login page.\n */\n onSessionExpired?: SessionExpiredHandler;\n}>;\n\nexport const AuthProvider: FC<AuthProviderProps> = ({ children, onSessionExpired }) => {\n const passflow = usePassflow();\n const [isLoading, setIsLoading] = useState<boolean>(false);\n const [isSessionExpired, setIsSessionExpired] = useState<boolean>(false);\n\n // Subscribe to SessionExpired events\n useEffect(() => {\n const subscriber: PassflowSubscriber = {\n onAuthChange: (eventType, payload) => {\n if (eventType === PassflowEvent.SessionExpired) {\n const reason = (payload as { reason?: SessionExpiredReason })?.reason ?? 'refresh_failed';\n setIsSessionExpired(true);\n onSessionExpired?.(reason);\n } else if (eventType === PassflowEvent.SignIn || eventType === PassflowEvent.Register) {\n // Reset session expired state on successful auth\n setIsSessionExpired(false);\n }\n },\n };\n\n passflow.subscribe(subscriber, [PassflowEvent.SessionExpired, PassflowEvent.SignIn, PassflowEvent.Register]);\n\n return () => {\n passflow.unsubscribe(subscriber);\n };\n }, [passflow, onSessionExpired]);\n\n const isAuthenticated = useCallback(() => passflow.isAuthenticated(), [passflow]);\n\n const getTokens = useCallback(\n async (doRefresh: boolean) => {\n setIsLoading(true);\n\n try {\n const tokens = await passflow.getTokens(doRefresh);\n const parsedTokens = tokens ? passflow.getParsedTokens() : undefined;\n\n return {\n tokens,\n parsedTokens,\n };\n } catch (e) {\n return {\n tokens: undefined,\n parsedTokens: undefined,\n };\n } finally {\n setIsLoading(false);\n }\n },\n [passflow],\n );\n\n const logout = useCallback(async () => {\n await passflow.logOut();\n }, [passflow]);\n\n const value = {\n isAuthenticated,\n logout,\n isLoading,\n isSessionExpired,\n getTokens,\n };\n\n return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;\n};\n","import { createContext } from 'react';\n\nexport type NavigateOptions = {\n to: string;\n search?: string;\n replace?: boolean;\n};\n\nexport type RouterType = 'default' | 'react-router' | 'tanstack-router' | 'wouter';\n\nexport type NavigateFunction = (options: NavigateOptions) => void;\n\nexport type NavigationContextType = {\n navigate: NavigateFunction;\n setNavigate: (navigate: NavigateFunction | null) => void;\n router: RouterType;\n /**\n * Where a sign-in that owes its second factor is sent when it lands on a\n * page outside the forms (a federated redirect carrying `#tfa_token=`).\n * `PassflowProvider` resolves it: a mounted `PassflowFlow` registers its own\n * (prefixed) route, else the provider's `twoFactorVerifyPath` prop, else\n * `routes.two_factor_verify.path`.\n */\n twoFactorVerifyPath?: string;\n /** Registers the 2FA route of a mounted flow; `null` withdraws it. */\n setTwoFactorVerifyPath?: (path: string | null) => void;\n};\n\nexport const defaultNavigate: NavigateFunction = ({ to, search, replace }) => {\n const searchParam = search ? (search.startsWith('?') ? search : `?${search}`) : '';\n if (replace) {\n window.location.replace(`${to}${searchParam}`);\n } else {\n window.location.href = `${to}${searchParam}`;\n }\n};\n\nexport const NavigationContext = createContext<NavigationContextType>({\n navigate: defaultNavigate,\n setNavigate: () => undefined,\n router: 'default',\n});\n","import type { AppSettings, Passflow, PassflowPasswordPolicySettings } from '@passflow/core';\nimport { createContext, type Dispatch } from 'react';\n\nexport type PassflowState = {\n appSettings: AppSettings | null;\n passwordPolicy: PassflowPasswordPolicySettings | null;\n url?: string;\n appId?: string;\n scopes?: string[];\n createTenantForNewUser?: boolean;\n parseQueryParams?: boolean;\n isDiscoveringAppId?: boolean;\n hasSettingsError?: boolean;\n};\n\nexport type PassflowAction = { type: 'SET_PASSFLOW_STATE'; payload: PassflowState };\n\nexport type PassflowContextType = {\n state: PassflowState;\n dispatch: Dispatch<PassflowAction>;\n passflow: Passflow;\n};\n\nexport const initialState: PassflowState = {\n appSettings: null,\n passwordPolicy: null,\n url: undefined,\n appId: undefined,\n scopes: undefined,\n createTenantForNewUser: undefined,\n parseQueryParams: true,\n isDiscoveringAppId: false,\n hasSettingsError: false,\n};\n\nexport const PassflowContext = createContext<PassflowContextType | undefined>(undefined);\n\nexport const passflowReducer = (state: PassflowState, action: PassflowAction): PassflowState => {\n switch (action.type) {\n case 'SET_PASSFLOW_STATE':\n return { ...state, ...action.payload };\n default:\n return state;\n }\n};\n","export const routes = {\n signin: {\n path: '/signin',\n },\n signup: {\n path: '/signup',\n },\n verify_otp: {\n path: '/verify-challenge-otp',\n },\n verify_magic_link: {\n path: '/verify-challenge-magic-link',\n },\n forgot_password: {\n path: '/forgot-password',\n },\n forgot_password_success: {\n path: '/forgot-password/success',\n },\n reset_password: {\n path: '/password/reset',\n },\n invitation: {\n path: '/invitation',\n },\n passkey: {\n path: '/passkeysss',\n },\n two_factor_verify: {\n path: '/two-factor-verify',\n },\n two_factor_recovery: {\n path: '/two-factor-recovery',\n },\n two_factor_setup: {\n path: '/two-factor-setup',\n },\n two_factor_setup_magic_link: {\n path: '/two-factor-setup-magic-link/:token',\n },\n};\n","/**\n * The assurance-upgrade context — the one channel between `UpgradeProvider`\n * and `useUpgrade` (architecture §8.2, §13.3).\n *\n * The provider owns the controller, the prompt handler and every transition;\n * this module owns only the shape they are read through. Two hooks each\n * installing a prompt handler would produce two prompts and defeat\n * single-flight, so nothing here installs anything.\n *\n * `status` is §13.5's `UpgradeHookState`, which is §13.3's settlement table\n * read down the hook column. Two consequences the types enforce:\n *\n * - **`insufficient` is a first-class state, not an error and not a success.**\n * \"Elevated to AAL2; this action requires AAL3\" is the normal path for an\n * AAL3 endpoint and a TOTP-only user, and a design cannot both claim the\n * server is the authority and delete the path by which its second refusal\n * reaches the user.\n * - **Cancellation is not a status.** It is `elevate()` resolving `null`. The\n * hook is the one surface where that is right, because there the\n * cancellation IS the whole value: the consumer is rendering a decision, not\n * handling a transport outcome.\n */\n\nimport type { AssuranceBar, UpgradeChallenge, UpgradeFactor, UpgradeFactorType } from '@passflow/core';\nimport { createContext } from 'react';\n\n/** What a protected elevation can fail with, in the hook's vocabulary (§13.3's table). */\nexport type UpgradeErrorStatusKind = 'exhausted' | 'unsatisfiable' | 'unavailable' | 'transport';\n\n/**\n * The hook's observable state. Exactly one terminal state per flight, taken\n * from the controller's outcome summary (§13.4).\n *\n * `idle` is also where a flight abandoned by a session change lands: nothing\n * happened, and nothing is reported as though it had.\n */\nexport type UpgradeHookState =\n | { status: 'idle' }\n | { status: 'challenged'; challenge: UpgradeChallenge; factors: UpgradeFactorType[] }\n | { status: 'submitting' }\n | { status: 'success' }\n | { status: 'insufficient'; obtained: AssuranceBar; required: AssuranceBar }\n | { status: 'error'; kind: UpgradeErrorStatusKind; error: Error };\n\n/** The states a flight can settle in. `null` alongside these is cancellation. */\nexport type UpgradeSettledState = Extract<UpgradeHookState, { status: 'idle' | 'success' | 'insufficient' | 'error' }>;\n\n/** A bar a caller states for itself on the imperative seam (§13.2 T10 / H-6). */\nexport type UpgradeElevateOptions = {\n acrValues?: string;\n maxAge?: number;\n};\n\n/** The open prompt, as the dialog and the hook read it. */\nexport type UpgradePromptView = {\n challenge: UpgradeChallenge;\n /** Already ranked by `selectFactors`; index 0 is the suggested factor. */\n factors: readonly UpgradeFactor[];\n /** The previous attempt's failure, when the controller re-prompted. */\n previousError?: Error;\n};\n\nexport type UpgradeContextValue = {\n /** True when the provider installed a prompt handler on this `Passflow` instance. */\n enabled: boolean;\n state: UpgradeHookState;\n /** The open prompt, or `null` when no elevation is collecting an answer. */\n prompt: UpgradePromptView | null;\n selectedFactor: UpgradeFactorType | null;\n /**\n * The factor-selection signal. Reports the user's choice to the controller\n * through `UpgradePromptRequest.onFactorSelected` the moment it is made and\n * before any answer is submitted — §13.2's late-join boundary (T3), which is\n * selection and not submission.\n */\n selectFactor: (factor: UpgradeFactorType) => void;\n /** Answers the open prompt. Resolves the controller's promise exactly once. */\n submit: (code?: string) => void;\n /** Declines the open prompt. Exactly once; never leaves the promise pending. */\n cancel: () => void;\n /** Acknowledges a terminal state, closing the dialog. Settles nothing. */\n dismiss: () => void;\n /**\n * Drives an elevation directly — a \"verify now\" button, or a headless\n * caller. Resolves **`null`** when the user cancelled, and otherwise the\n * flight's terminal state; it never rejects, because the hook's contract is\n * a rendered decision rather than a thrown transport outcome.\n */\n elevate: (options?: UpgradeElevateOptions) => Promise<UpgradeSettledState | null>;\n};\n\nexport const UpgradeContext = createContext<UpgradeContextValue | undefined>(undefined);\n\nconst noop = (): void => undefined;\n\n/**\n * What `useUpgrade` reads outside an `UpgradeProvider`: idle, inert, and it\n * does not throw (§9.5 H8) — a component that merely wants to know whether an\n * elevation is running is not a bug.\n *\n * `elevate` resolves `{ status: 'idle' }` rather than `null`: nothing was\n * asked and nothing was declined, and `null` means the user declined.\n */\nexport const INERT_UPGRADE_CONTEXT: UpgradeContextValue = {\n enabled: false,\n state: { status: 'idle' },\n prompt: null,\n selectedFactor: null,\n selectFactor: noop,\n submit: noop,\n cancel: noop,\n dismiss: noop,\n elevate: () => Promise.resolve({ status: 'idle' }),\n};\n","import type { LoginWebAppStyle } from '@passflow/core';\n\nexport type CompatibleLoginWebAppStyle = Partial<LoginWebAppStyle> & {\n /** Legacy field used by themes created before text_color was introduced. */\n content_color?: string;\n};\n\nconst nonEmpty = (value: unknown): string | null => (typeof value === 'string' && value.trim() ? value.trim() : null);\n\nconst getBackgroundImage = (value: unknown): string | null => {\n if (typeof value !== 'string') return null;\n\n const image = nonEmpty(value);\n return image ? `url(${image})` : 'none';\n};\n\nexport const getLoginThemeCssVariables = (style: CompatibleLoginWebAppStyle): Record<string, string | null> => ({\n '--passflow-primary-color': nonEmpty(style.primary_color),\n '--passflow-text-color': nonEmpty(style.text_color) ?? nonEmpty(style.content_color),\n '--passflow-secondary-text-color': nonEmpty(style.secondary_text_color),\n '--passflow-background-color': nonEmpty(style.background_color),\n '--passflow-background-image': getBackgroundImage(style.background_image),\n '--passflow-card-color': nonEmpty(style.card_color),\n '--passflow-branding-background-color': nonEmpty(style.card_color),\n '--passflow-input-background-color': nonEmpty(style.input_background_color),\n '--passflow-input-border-color': nonEmpty(style.input_border_color),\n '--passflow-button-text-color': nonEmpty(style.button_text_color),\n '--passflow-passkey-button-text-color': nonEmpty(style.passkey_button_text_color),\n '--passflow-passkey-button-background-color': nonEmpty(style.passkey_button_background_color),\n '--passflow-divider-color': nonEmpty(style.divider_color),\n '--passflow-federated_button_background_color': nonEmpty(style.federated_button_background_color),\n '--passflow-federated_button_text_color': nonEmpty(style.federated_button_text_color),\n});\n\nexport const applyLoginThemeStyles = (root: HTMLElement, style: CompatibleLoginWebAppStyle): void => {\n for (const [property, value] of Object.entries(getLoginThemeCssVariables(style))) {\n if (value === null) root.style.removeProperty(property);\n else root.style.setProperty(property, value);\n }\n};\n","import type { AppSettings, LoginWebAppStyle, LoginWebAppTheme, PassflowPasswordPolicySettings } from '@passflow/core';\nimport { useContext, useLayoutEffect, useRef, useState } from 'react';\nimport { PassflowContext } from '@/context';\nimport { applyLoginThemeStyles, type CompatibleLoginWebAppStyle } from '@/utils/login-theme';\nimport { usePassflow } from './use-passflow';\n\nexport type UseAppSettingsProps = () => {\n appSettings: AppSettings | null;\n passwordPolicy: PassflowPasswordPolicySettings | null;\n isLoading: boolean;\n isError: boolean;\n error: string;\n reset: () => void;\n currentTheme: string;\n currentStyles: LoginWebAppStyle | null;\n scopes: string[];\n createTenantForNewUser: boolean;\n loginAppTheme?: LoginWebAppTheme;\n};\n\nconst hasPasswordStrategy = (strategies: AppSettings['auth_strategies']): boolean => {\n return strategies?.some((strategy) => strategy.type === 'internal' && strategy.strategy?.challenge === 'password') ?? false;\n};\n\nexport const useAppSettings: UseAppSettingsProps = () => {\n const passflow = usePassflow();\n const context = useContext(PassflowContext);\n const [isError, setIsError] = useState(false);\n const [errorMessage, setErrorMessage] = useState('');\n const [isLoading, setIsLoading] = useState(false);\n const isFetchingRef = useRef(false);\n\n if (!context) {\n throw new Error('useAppSetting must be used within an PassflowProvider');\n }\n\n const { state, dispatch } = context;\n\n useLayoutEffect(() => {\n if (!state.appSettings && !state.hasSettingsError && !isFetchingRef.current) {\n const fetchAllSettings = async (): Promise<void> => {\n isFetchingRef.current = true;\n setIsLoading(true);\n try {\n // If appId is not provided, try to discover it from /settings endpoint\n if (!passflow.appId && !state.isDiscoveringAppId) {\n dispatch({\n type: 'SET_PASSFLOW_STATE',\n payload: {\n ...state,\n isDiscoveringAppId: true,\n },\n });\n\n try {\n // Try relative path first (works with dev server proxy and same-origin production)\n // Then fall back to absolute URL if configured\n const urlsToTry = ['/settings'];\n if (passflow.url) {\n urlsToTry.push(`${passflow.url}/settings`);\n }\n\n let response: Response | null = null;\n for (const url of urlsToTry) {\n try {\n const r = await fetch(url);\n if (r.ok) {\n response = r;\n break;\n }\n } catch {}\n }\n\n if (response?.ok) {\n const settings = await response.json();\n\n // Support both response formats:\n // Production: { login_app: { app_id: \"...\", ... } }\n // Dev: { appId: \"...\" }\n const discoveredAppId = settings.login_app?.app_id || settings.appId;\n\n if (discoveredAppId) {\n // Update the passflow instance with discovered appId using setAppId method\n passflow.setAppId(discoveredAppId);\n\n // Collect state updates to apply in one dispatch\n const stateUpdates: Partial<typeof state> = {\n appId: discoveredAppId,\n };\n\n // Also update scopes if available and not already set\n if (!state.scopes) {\n const discoveredScopes = settings.login_app?.scopes || settings.scopes;\n if (discoveredScopes) {\n stateUpdates.scopes = discoveredScopes;\n }\n }\n\n // Update createTenantForNewUser if available and not already set\n if (state.createTenantForNewUser === undefined) {\n const createTenant = settings.login_app?.create_tenant_for_new_user ?? settings.createTenantForNewUser;\n if (createTenant !== undefined) {\n stateUpdates.createTenantForNewUser = createTenant;\n }\n }\n\n // Apply discovered state updates\n dispatch({\n type: 'SET_PASSFLOW_STATE',\n payload: {\n ...state,\n ...stateUpdates,\n isDiscoveringAppId: false,\n },\n });\n } else {\n dispatch({\n type: 'SET_PASSFLOW_STATE',\n payload: {\n ...state,\n isDiscoveringAppId: false,\n },\n });\n }\n }\n } catch (discoveryError) {\n console.warn('Failed to discover appId from /settings:', discoveryError);\n // Continue with the flow - we'll handle missing appId later\n dispatch({\n type: 'SET_PASSFLOW_STATE',\n payload: {\n ...state,\n isDiscoveringAppId: false,\n },\n });\n }\n }\n\n let appSettings = {} as AppSettings;\n if (passflow.appId) {\n appSettings = await passflow.getAppSettings();\n }\n\n // Collect final state updates\n const finalStateUpdates: Partial<typeof state> = {\n appSettings,\n };\n\n if (!state.scopes) finalStateUpdates.scopes = appSettings.defaults?.scopes;\n if (state.createTenantForNewUser === undefined)\n finalStateUpdates.createTenantForNewUser = appSettings.defaults?.create_tenant_for_new_user;\n\n let passwordPolicy = null;\n if (appSettings.auth_strategies && hasPasswordStrategy(appSettings.auth_strategies)) {\n passwordPolicy = await passflow.getPasswordPolicySettings();\n }\n finalStateUpdates.passwordPolicy = passwordPolicy;\n\n dispatch({\n type: 'SET_PASSFLOW_STATE',\n payload: {\n ...state,\n ...finalStateUpdates,\n },\n });\n } catch (e) {\n setIsError(true);\n const error = e as Error;\n setErrorMessage(error.message);\n // Set error flag in context to prevent infinite retry loop\n dispatch({\n type: 'SET_PASSFLOW_STATE',\n payload: {\n ...state,\n hasSettingsError: true,\n },\n });\n } finally {\n setIsLoading(false);\n isFetchingRef.current = false;\n }\n };\n void fetchAllSettings();\n }\n }, [dispatch, state.appSettings, state.hasSettingsError, state.isDiscoveringAppId, passflow]);\n\n const reset = () => {\n setIsError(false);\n setErrorMessage('');\n setIsLoading(false);\n // Clear error flag in context to allow retry\n dispatch({\n type: 'SET_PASSFLOW_STATE',\n payload: {\n ...state,\n hasSettingsError: false,\n },\n });\n };\n\n // `custom_css` is not written here: each screen passes `currentStyles.custom_css`\n // to its shell, which renders it inline.\n const applyThemeStyles = (style: CompatibleLoginWebAppStyle) => {\n applyLoginThemeStyles(document.documentElement, style);\n };\n\n const getCurrentTheme = () => {\n const theme = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';\n\n if (state.appSettings?.login_app_theme?.color_scheme === 'system') return theme;\n\n return state.appSettings?.login_app_theme?.color_scheme ?? theme;\n };\n\n const currentTheme = getCurrentTheme();\n\n const selectedStyle = state.appSettings?.login_app_theme\n ? currentTheme === 'dark'\n ? state.appSettings?.login_app_theme.dark_style\n : state.appSettings?.login_app_theme.light_style\n : null;\n\n if (selectedStyle) {\n applyThemeStyles(selectedStyle);\n }\n\n return {\n appSettings: state.appSettings,\n scopes: state.scopes ?? [],\n createTenantForNewUser: state.createTenantForNewUser ?? false,\n loginAppTheme: state.appSettings?.login_app_theme,\n passwordPolicy: state.passwordPolicy,\n currentStyles: selectedStyle,\n currentTheme: currentTheme,\n isLoading,\n isError,\n error: errorMessage,\n reset,\n } as const;\n};\n","import { useContext } from 'react';\nimport { AuthContext, type AuthContextValue } from '@/context';\n\nexport const useAuth = (): AuthContextValue => {\n const context = useContext(AuthContext);\n if (!context) {\n throw new Error('useAuth must be used within an AuthProvider');\n }\n\n return context;\n};\n","import { usePassflow } from './use-passflow';\n\ntype UseAuthCloudRedirectProps = (cloudPassflowUrl: string) => () => void;\n\nexport const useAuthCloudRedirect: UseAuthCloudRedirectProps = (cloudPassflowUrl: string) => {\n const passflow = usePassflow();\n\n const redirect = () => passflow.authRedirect({ url: cloudPassflowUrl });\n\n return redirect;\n};\n","import { useCallback, useEffect, useMemo, useState } from 'react';\n\n/**\n * The OIDC consent decision, as a hook.\n *\n * The URL is the bearer. `parent_challenge_id` identifies a staged\n * authorization request the server is holding, and possessing that id is what\n * authorizes reading it — there is no Authorization header on the GET. The\n * server hands back a `csrf_token` with the request metadata, and every\n * state-changing POST must carry it back in `X-Passflow-CSRF`. That token is\n * the only thing separating a real decision from one a third-party page forged\n * on the user's behalf, so it is never optional and never cached across\n * challenges.\n *\n * The decision endpoints answer with a discriminated response rather than a\n * redirect status, because the OIDC `response_mode` decides HOW the user gets\n * back to the client: `query` is an ordinary navigation, `form_post` must be a\n * POST with the parameters in a form body (they cannot go in a URL). The server\n * knows which; the client just executes what it is told.\n */\n\nexport type ConsentScopeMetadata = {\n scope: string;\n label: string;\n description: string;\n};\n\n/** What GET /oidc/requests/{parent_challenge_id} hands the page to render itself. */\nexport type ConsentInfo = {\n client_id: string;\n app_name: string;\n app_logo_url: string;\n requested_scopes: string[];\n scope_metadata: ConsentScopeMetadata[];\n redirect_uri: string;\n state: string;\n response_mode: '' | 'query' | 'form_post';\n first_party: boolean;\n csrf_token: string;\n};\n\ntype DecisionResponse =\n | { kind: 'redirect'; url: string }\n | { kind: 'form_post'; action: string; fields: Record<string, string> };\n\ntype ApiErrorBody = {\n error?: string;\n error_description?: string;\n};\n\nexport type ConsentStatus =\n /** Fetching the staged request. */\n | 'loading'\n /** Metadata in hand; awaiting the user's decision. */\n | 'ready'\n /** A decision is in flight. */\n | 'working'\n /** Decision accepted; the browser is on its way back to the client. */\n | 'redirecting'\n /** The link itself is unusable — missing, expired, or rejected id. Terminal. */\n | 'invalid';\n\nexport type ConsentError = {\n message: string;\n description?: string;\n};\n\nexport type UseConsentProps = {\n status: ConsentStatus;\n info: ConsentInfo | null;\n /** The scopes still switched on. A subset of `info.requested_scopes`. */\n grantedScopes: string[];\n error: ConsentError | null;\n /** Metadata for a scope, falling back to the bare scope string. */\n scopeMetadata: (scope: string) => ConsentScopeMetadata;\n /** Switch one requested scope on or off before deciding. */\n toggleScope: (scope: string) => void;\n /** Grant the currently-selected subset. */\n allow: () => Promise<void>;\n /** Refuse the request outright (OAuth2 `access_denied`). */\n deny: () => Promise<void>;\n};\n\nconst readParentChallengeId = (): string => new URLSearchParams(window.location.search).get('parent_challenge_id') ?? '';\n\nconst requestPath = (parentChallengeId: string): string => `/oidc/requests/${encodeURIComponent(parentChallengeId)}`;\n\n/**\n * Execute a `form_post` decision: OIDC response_mode=form_post requires the\n * parameters to arrive as a POST body, which only a real form submission can\n * do cross-origin.\n */\nconst submitFormPost = (action: string, fields: Record<string, string>): void => {\n const form = document.createElement('form');\n form.method = 'POST';\n form.action = action;\n form.style.display = 'none';\n\n for (const [key, value] of Object.entries(fields)) {\n const input = document.createElement('input');\n input.type = 'hidden';\n input.name = key;\n input.value = value;\n form.appendChild(input);\n }\n\n document.body.appendChild(form);\n form.submit();\n};\n\nexport const useConsent = (): UseConsentProps => {\n const parentChallengeId = useMemo(readParentChallengeId, []);\n\n const [status, setStatus] = useState<ConsentStatus>('loading');\n const [info, setInfo] = useState<ConsentInfo | null>(null);\n const [granted, setGranted] = useState<Set<string>>(new Set());\n const [error, setError] = useState<ConsentError | null>(null);\n\n useEffect(() => {\n if (!parentChallengeId) {\n setStatus('invalid');\n setError({\n message: 'Invalid consent link',\n description: 'This consent link is missing required information. Please return to the application and try again.',\n });\n return;\n }\n\n let cancelled = false;\n\n const fetchInfo = async (): Promise<void> => {\n try {\n const res = await fetch(requestPath(parentChallengeId), {\n method: 'GET',\n credentials: 'same-origin',\n headers: { Accept: 'application/json' },\n });\n if (cancelled) return;\n\n if (!res.ok) {\n const body = ((await res.json().catch(() => ({}))) ?? {}) as ApiErrorBody;\n setStatus('invalid');\n setError({\n message: res.status >= 500 ? 'Something went wrong' : 'Consent request unavailable',\n description:\n body.error_description ||\n 'We could not load this consent request. Please return to the application and try again.',\n });\n return;\n }\n\n const data = (await res.json()) as ConsentInfo;\n if (cancelled) return;\n\n setInfo(data);\n // Everything asked for starts granted; the user switches OFF what they\n // do not want. Starting from none would train people to hit Allow on an\n // empty grant and wonder why the app is broken.\n setGranted(new Set(data.requested_scopes));\n setStatus('ready');\n } catch (err) {\n if (cancelled) return;\n setStatus('invalid');\n setError({\n message: 'Connection error',\n description: err instanceof Error ? err.message : 'Could not reach the server. Please check your connection.',\n });\n }\n };\n\n void fetchInfo();\n\n return () => {\n cancelled = true;\n };\n }, [parentChallengeId]);\n\n const toggleScope = useCallback((scope: string): void => {\n setGranted((prev) => {\n const next = new Set(prev);\n if (next.has(scope)) next.delete(scope);\n else next.add(scope);\n return next;\n });\n // Changing the selection invalidates whatever the last failed submit said.\n setError(null);\n }, []);\n\n const decide = useCallback(\n async (decision: 'allow' | 'deny'): Promise<void> => {\n if (!info) return;\n\n setStatus('working');\n setError(null);\n\n const base = requestPath(parentChallengeId);\n const endpoint = decision === 'allow' ? `${base}/consent` : `${base}/reject`;\n const body =\n decision === 'allow'\n ? { granted_scopes: info.requested_scopes.filter((scope) => granted.has(scope)) }\n : { error: 'access_denied', error_description: 'User denied consent' };\n\n try {\n const res = await fetch(endpoint, {\n method: 'POST',\n credentials: 'same-origin',\n headers: {\n 'Content-Type': 'application/json',\n Accept: 'application/json',\n 'X-Passflow-CSRF': info.csrf_token,\n },\n body: JSON.stringify(body),\n });\n\n if (!res.ok) {\n const errBody = ((await res.json().catch(() => ({}))) ?? {}) as ApiErrorBody;\n setStatus('ready');\n setError({\n message: errBody.error_description || 'Could not submit your decision. Please try again.',\n });\n return;\n }\n\n const data = (await res.json()) as DecisionResponse;\n\n if (data.kind === 'redirect') {\n setStatus('redirecting');\n window.location.href = data.url;\n return;\n }\n\n if (data.kind === 'form_post') {\n setStatus('redirecting');\n submitFormPost(data.action, data.fields);\n return;\n }\n\n setStatus('ready');\n setError({ message: 'Unexpected response from server.' });\n } catch (err) {\n setStatus('ready');\n setError({\n message: err instanceof Error ? err.message : 'Could not reach the server. Please try again.',\n });\n }\n },\n [granted, info, parentChallengeId],\n );\n\n const allow = useCallback(() => decide('allow'), [decide]);\n const deny = useCallback(() => decide('deny'), [decide]);\n\n const metadataByScope = useMemo(() => new Map((info?.scope_metadata ?? []).map((meta) => [meta.scope, meta])), [info]);\n\n const scopeMetadata = useCallback(\n (scope: string): ConsentScopeMetadata => metadataByScope.get(scope) ?? { scope, label: scope, description: '' },\n [metadataByScope],\n );\n\n const grantedScopes = useMemo(() => (info?.requested_scopes ?? []).filter((scope) => granted.has(scope)), [granted, info]);\n\n return { status, info, grantedScopes, error, scopeMetadata, toggleScope, allow, deny };\n};\n","import type { PublicKeyCredentialRequestOptionsJSON } from '@simplewebauthn/browser';\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport type { DeviceError } from '@/types/device-errors';\nimport { classifyDeviceError, DeviceApiError } from '@/utils';\n\n/**\n * The RFC 8628 verification flow, as a hook.\n *\n * ── The one rule the whole thing is built around ────────────────────────────\n * Signing in and approving are TWO ACTS, and this hook keeps them two. Proving\n * who you are (`/oidc/device/authenticate`) yields an approval ticket and\n * NOTHING else — no tokens, no session. Approving (`/oidc/device/approve`) is\n * what releases tokens to the waiting terminal, and it needs that ticket.\n *\n * The gap between them is not ceremony, it is RFC 8628 §5.4: an attacker can\n * start a device grant and walk a victim into approving it (STORM-2372). They\n * know the user_code — they created it — and the page is public, so they can\n * read its CSRF token too. Neither can be the authority for approval. Only the\n * ticket, held in this hook's memory and bound to the browser that actually\n * authenticated, can be.\n *\n * So: never collapse authenticate+approve into one call \"for convenience\".\n * Mode 1 puts both behind one TAP (see confirmWithPassword) — that is a UI\n * affordance and is fine, because the human still looked at the code first.\n * Mode 3 skips the tap entirely, which it earns by using an origin-bound\n * passkey; see the note on confirmWithPasskey.\n *\n * When the app requires a second factor, the first ticket cannot approve: the\n * server refuses it. The page asks for the factor (`/oidc/device/second-factor`)\n * and approves with the ticket that answers, which records both.\n */\n\n/** The UI the server resolved for this challenge. A closed set — the client does not choose. */\nexport type DeviceUIMode = 'consent' | 'full_login' | 'passkey';\n\n/** What GET /oidc/device/info hands the page to render itself. */\nexport type DeviceVerifyInfo = {\n mode: DeviceUIMode;\n /** Absent for `passkey` mode, by design — see device_page.go. */\n user_code?: string;\n app_name: string;\n csrf_token: string;\n methods: {\n password: boolean;\n passkey: boolean;\n };\n};\n\n/** A second factor the verification page can take. */\nexport type DeviceSecondFactorMethod = 'totp' | 'recovery_codes';\n\nexport type DeviceVerifyStatus =\n /** Asking the server what to render. */\n | 'loading'\n /** No code yet — show the entry form. */\n | 'code_entry'\n /** Info in hand; awaiting the user. */\n | 'ready'\n /** A call is in flight. */\n | 'working'\n /** A first factor proven; the app wants a second before anything can be approved. */\n | 'second_factor'\n /** Identity proven, ticket held, not yet approved. */\n | 'signed_in'\n /** Approved. The terminal has its tokens. */\n | 'done'\n /** The mode is switched off. Terminal, and nothing approvable is rendered. */\n | 'refused'\n /** Terminal failure — bad/expired code, dead app. */\n | 'failed';\n\nexport type UseDeviceVerifyProps = {\n status: DeviceVerifyStatus;\n info: DeviceVerifyInfo | null;\n error: DeviceError | null;\n /** The email that authenticated, once one has. */\n email: string | null;\n /** Whether an approval ticket is held. */\n isAuthenticated: boolean;\n /** Whether a first-factor ticket is waiting for its second factor. */\n isSecondFactorPending: boolean;\n /** The second factors the server takes, once a sign-in owes one. */\n secondFactorMethods: DeviceSecondFactorMethod[];\n /** Re-run the info lookup for a code typed by hand. */\n submitCode: (code: string) => void;\n /** Prove identity with a password. Does NOT approve. */\n signInWithPassword: (email: string, password: string) => Promise<void>;\n /** Prove identity with a passkey. Does NOT approve. */\n signInWithPasskey: () => Promise<void>;\n /** Approve, using the ticket already held. */\n approve: () => Promise<void>;\n /** One tap: prove identity if needed, then approve. */\n confirmWithPassword: (email: string, password: string) => Promise<void>;\n /** Passkey ceremony then approve, with no tap in between. */\n confirmWithPasskey: () => Promise<void>;\n /**\n * Prove the second factor. Approves too when the act that asked for it was\n * an approval (consent's tap, the passkey mode); otherwise lands on signed_in.\n */\n submitSecondFactor: (method: DeviceSecondFactorMethod, code: string) => Promise<void>;\n /** Clear a recoverable error so the user can try again. */\n clearError: () => void;\n};\n\nconst DEVICE_ENDPOINTS = {\n info: '/oidc/device/info',\n authenticate: '/oidc/device/authenticate',\n approve: '/oidc/device/approve',\n passkeyStart: '/oidc/device/passkey/start',\n secondFactor: '/oidc/device/second-factor',\n} as const;\n\n/** What /oidc/device/authenticate answers with. */\ntype DeviceAuthenticateResponse = {\n approval_ticket: string;\n email?: string;\n /** The app requires a second factor; this ticket cannot approve until one is given. */\n second_factor_required?: boolean;\n second_factor_methods?: string[];\n};\n\nconst SECOND_FACTOR_METHODS: readonly DeviceSecondFactorMethod[] = ['totp', 'recovery_codes'];\n\n/** The factors the server offers that this page can take, in its order. */\nconst toSecondFactorMethods = (methods: string[] | undefined): DeviceSecondFactorMethod[] => {\n const known = (methods ?? []).filter((m): m is DeviceSecondFactorMethod =>\n SECOND_FACTOR_METHODS.includes(m as DeviceSecondFactorMethod),\n );\n return known.length > 0 ? known : ['totp'];\n};\n\n/** Read `user_code` off the URL — the QR encodes verification_uri_complete. */\nconst readUserCodeFromURL = (): string => new URLSearchParams(window.location.search).get('user_code') ?? '';\n\n/**\n * Parse a device endpoint's response, turning any failure into a DeviceApiError\n * that carries the server's stable `reason`.\n */\nconst parseDeviceResponse = async <T>(res: Response): Promise<T> => {\n const body: unknown = await res.json().catch(() => ({}));\n const data = (body ?? {}) as Record<string, unknown>;\n\n if (!res.ok) {\n throw new DeviceApiError({\n reason: typeof data.reason === 'string' ? data.reason : '',\n code: typeof data.error === 'string' ? data.error : '',\n status: res.status,\n description: typeof data.error_description === 'string' ? data.error_description : '',\n });\n }\n return data as T;\n};\n\nexport const useDeviceVerify = (): UseDeviceVerifyProps => {\n const [status, setStatus] = useState<DeviceVerifyStatus>('loading');\n const [info, setInfo] = useState<DeviceVerifyInfo | null>(null);\n const [error, setError] = useState<DeviceError | null>(null);\n const [email, setEmail] = useState<string | null>(null);\n const [userCode, setUserCode] = useState<string>(() => readUserCodeFromURL());\n\n /**\n * The approval ticket. A ref, not state: it is an authorization handle, so it\n * must be readable synchronously by the call that follows the one that earned\n * it. `confirmWithPassword` authenticates and approves back-to-back within a\n * single event; a state read there would still be null, and the approve would\n * be refused for no reason a user could understand.\n */\n const ticketRef = useRef<string | null>(null);\n\n /**\n * The first-factor ticket, while the app still wants a second. Kept apart\n * from ticketRef because it cannot approve, so isAuthenticated must not\n * claim a sign-in the approval would refuse.\n */\n const firstFactorTicketRef = useRef<string | null>(null);\n /** Whether the act that asked for the second factor was an approval. */\n const approveAfterSecondFactorRef = useRef(false);\n const [secondFactorMethods, setSecondFactorMethods] = useState<DeviceSecondFactorMethod[]>([]);\n\n /** Guards against setting state after unmount, and against double-fires. */\n const activeRef = useRef(true);\n useEffect(() => {\n activeRef.current = true;\n return () => {\n activeRef.current = false;\n };\n }, []);\n\n const csrf = info?.csrf_token ?? '';\n\n /**\n * Every back-channel POST: same-origin, JSON, the challenge's CSRF token, and\n * the user_code that scopes it.\n */\n const post = useCallback(\n async <T>(path: string, body: Record<string, unknown>): Promise<T> => {\n const res = await fetch(path, {\n method: 'POST',\n credentials: 'same-origin',\n headers: {\n 'Content-Type': 'application/json',\n Accept: 'application/json',\n 'X-Passflow-CSRF': csrf,\n },\n body: JSON.stringify({ ...body, user_code: userCode }),\n });\n return parseDeviceResponse<T>(res);\n },\n [csrf, userCode],\n );\n\n /**\n * Record a failure: classified for the user, logged in full for us.\n *\n * This is the ONLY place a failure becomes user-visible, which is what makes\n * \"no technical string reaches the screen\" checkable rather than aspirational.\n */\n const fail = useCallback((err: unknown, terminal: DeviceVerifyStatus | null = null) => {\n const classified = classifyDeviceError(err);\n // The detail the user must never read, kept exactly where a developer will\n // look for it first.\n if (classified.detail) {\n console.error('[passflow] device verification:', classified.detail, err);\n }\n if (!activeRef.current) return;\n setError(classified);\n if (terminal) {\n setStatus(terminal);\n return;\n }\n setStatus(\n classified.type === 'mode_disabled'\n ? 'refused'\n : firstFactorTicketRef.current\n ? 'second_factor'\n : ticketRef.current\n ? 'signed_in'\n : 'ready',\n );\n }, []);\n\n // ── Load what to render ───────────────────────────────────────────────────\n const loadInfo = useCallback(async (code: string) => {\n if (!code) {\n setStatus('code_entry');\n setError(null);\n return;\n }\n setStatus('loading');\n setError(null);\n try {\n const res = await fetch(`${DEVICE_ENDPOINTS.info}?user_code=${encodeURIComponent(code)}`, {\n method: 'GET',\n credentials: 'same-origin',\n headers: { Accept: 'application/json' },\n });\n const data = await parseDeviceResponse<DeviceVerifyInfo>(res);\n if (!activeRef.current) return;\n setInfo(data);\n setStatus('ready');\n } catch (err) {\n const classified = classifyDeviceError(err);\n if (classified.detail) {\n console.error('[passflow] device verification:', classified.detail, err);\n }\n if (!activeRef.current) return;\n\n // `code_required` is not a failure — it is the code entry form.\n if (classified.type === 'code_required') {\n setError(null);\n setStatus('code_entry');\n return;\n }\n setError(classified);\n // A disabled mode gets its own terminal state so the page can render a\n // refusal with NOTHING approvable on it. A bad or dead code lands on the\n // entry form, where the remedy (type it again) actually lives.\n setStatus(classified.type === 'mode_disabled' ? 'refused' : 'failed');\n }\n }, []);\n\n useEffect(() => {\n void loadInfo(userCode);\n }, [loadInfo, userCode]);\n\n const submitCode = useCallback((code: string) => {\n setUserCode(code.trim());\n }, []);\n\n // ── Prove identity. Yields a ticket; approves nothing. ────────────────────\n /**\n * Hold the ticket an authentication earned. Returns true when the app wants\n * a second factor first, in which case the ticket cannot approve yet.\n */\n const holdTicket = useCallback((res: DeviceAuthenticateResponse): boolean => {\n if (res.second_factor_required) {\n firstFactorTicketRef.current = res.approval_ticket;\n ticketRef.current = null;\n if (activeRef.current) setSecondFactorMethods(toSecondFactorMethods(res.second_factor_methods));\n return true;\n }\n firstFactorTicketRef.current = null;\n ticketRef.current = res.approval_ticket;\n return false;\n }, []);\n\n const authenticatePassword = useCallback(\n async (emailValue: string, password: string): Promise<boolean> => {\n const res = await post<DeviceAuthenticateResponse>(DEVICE_ENDPOINTS.authenticate, {\n method: 'password',\n email: emailValue,\n password,\n });\n const owesSecondFactor = holdTicket(res);\n if (activeRef.current) setEmail(res.email ?? emailValue);\n return owesSecondFactor;\n },\n [post, holdTicket],\n );\n\n const authenticatePasskey = useCallback(async (): Promise<boolean> => {\n // Thrown as a DOMException so it travels the same road as every real\n // WebAuthn failure and lands on the same classified copy — rather than\n // becoming a second, parallel way for this page to describe a passkey\n // problem, which is how the copy drifts.\n if (typeof window === 'undefined' || !window.PublicKeyCredential) {\n throw new DOMException('this browser does not implement PublicKeyCredential', 'NotSupportedError');\n }\n\n const start = await post<{ passkey_challenge_id: string; publicKey: PublicKeyCredentialRequestOptionsJSON }>(\n DEVICE_ENDPOINTS.passkeyStart,\n {},\n );\n\n // The SDK's existing WebAuthn primitive, not a hand-rolled base64url dance.\n // @simplewebauthn/browser (v14, the same copy @passflow/core uses) takes the\n // server's JSON options as-is. Loaded on demand: only this branch needs it.\n const { startAuthentication } = await import('@simplewebauthn/browser');\n const assertion = await startAuthentication({ optionsJSON: start.publicKey });\n\n const res = await post<DeviceAuthenticateResponse>(DEVICE_ENDPOINTS.authenticate, {\n method: 'passkey',\n passkey_challenge_id: start.passkey_challenge_id,\n passkey_data: assertion,\n });\n const owesSecondFactor = holdTicket(res);\n if (activeRef.current) setEmail(res.email ?? null);\n return owesSecondFactor;\n }, [post, holdTicket]);\n\n // ── The act that releases tokens ──────────────────────────────────────────\n const approveWithTicket = useCallback(async (): Promise<void> => {\n await post(DEVICE_ENDPOINTS.approve, { approval_ticket: ticketRef.current });\n if (!activeRef.current) return;\n setStatus('done');\n }, [post]);\n\n const signInWithPassword = useCallback(\n async (emailValue: string, password: string) => {\n setStatus('working');\n setError(null);\n try {\n const owesSecondFactor = await authenticatePassword(emailValue, password);\n if (!activeRef.current) return;\n approveAfterSecondFactorRef.current = false;\n setStatus(owesSecondFactor ? 'second_factor' : 'signed_in');\n } catch (err) {\n fail(err);\n }\n },\n [authenticatePassword, fail],\n );\n\n const signInWithPasskey = useCallback(async () => {\n setStatus('working');\n setError(null);\n try {\n const owesSecondFactor = await authenticatePasskey();\n if (!activeRef.current) return;\n approveAfterSecondFactorRef.current = false;\n setStatus(owesSecondFactor ? 'second_factor' : 'signed_in');\n } catch (err) {\n fail(err);\n }\n }, [authenticatePasskey, fail]);\n\n const approve = useCallback(async () => {\n setStatus('working');\n setError(null);\n try {\n await approveWithTicket();\n } catch (err) {\n fail(err);\n }\n }, [approveWithTicket, fail]);\n\n /**\n * Mode 1's single tap: prove identity if we have not already, then approve.\n *\n * Two calls behind one button is the affordance; it is NOT a collapse of the\n * §5.4 check. The check is that a human read the code and chose to proceed,\n * and that is exactly what the tap is.\n */\n const confirmWithPassword = useCallback(\n async (emailValue: string, password: string) => {\n setStatus('working');\n setError(null);\n try {\n if (!ticketRef.current && (await authenticatePassword(emailValue, password))) {\n approveAfterSecondFactorRef.current = true;\n if (activeRef.current) setStatus('second_factor');\n return;\n }\n await approveWithTicket();\n } catch (err) {\n fail(err);\n }\n },\n [authenticatePassword, approveWithTicket, fail],\n );\n\n /**\n * Passkey then approve, with nothing in between.\n *\n * For Mode 3 this runs on load, with no user gesture, and both halves of that\n * are deliberate:\n * - WebAuthn L3's get() carries no transient-activation requirement (unlike\n * create()), so firing on load is legal. The phone's own biometric prompt\n * IS the interaction; a button first would add a step that protects nothing.\n * - No §5.4 confirm follows, because a passkey is origin-bound: the\n * authenticator scopes the assertion to this origin, so it cannot be\n * produced on an attacker's page or replayed to one. There is no phished\n * approval to catch and so nothing for the human to compare.\n */\n const confirmWithPasskey = useCallback(async () => {\n setStatus('working');\n setError(null);\n try {\n if (await authenticatePasskey()) {\n approveAfterSecondFactorRef.current = true;\n if (activeRef.current) setStatus('second_factor');\n return;\n }\n await approveWithTicket();\n } catch (err) {\n fail(err);\n }\n }, [authenticatePasskey, approveWithTicket, fail]);\n\n /**\n * The second factor, for a sign-in whose app requires one. The server checks\n * the code for the user the first ticket names and answers with a ticket\n * recording both factors, which is the one that can approve.\n *\n * It approves straight away when the act that asked for the factor was\n * itself an approval: consent's tap, or the passkey mode, which has none.\n */\n const submitSecondFactor = useCallback(\n async (method: DeviceSecondFactorMethod, code: string) => {\n setStatus('working');\n setError(null);\n try {\n const res = await post<{ approval_ticket: string }>(DEVICE_ENDPOINTS.secondFactor, {\n approval_ticket: firstFactorTicketRef.current,\n method,\n code,\n });\n ticketRef.current = res.approval_ticket;\n firstFactorTicketRef.current = null;\n if (approveAfterSecondFactorRef.current) {\n await approveWithTicket();\n return;\n }\n if (activeRef.current) setStatus('signed_in');\n } catch (err) {\n fail(err);\n }\n },\n [post, approveWithTicket, fail],\n );\n\n const clearError = useCallback(() => setError(null), []);\n\n return {\n status,\n info,\n error,\n email,\n isAuthenticated: ticketRef.current !== null,\n isSecondFactorPending: firstFactorTicketRef.current !== null,\n secondFactorMethods,\n submitCode,\n signInWithPassword,\n signInWithPasskey,\n approve,\n confirmWithPassword,\n confirmWithPasskey,\n submitSecondFactor,\n clearError,\n };\n};\n","import type { PassflowSendPasswordResetEmailPayload } from '@passflow/core';\nimport { useCallback, useState } from 'react';\nimport { usePassflow } from './use-passflow';\n\nexport type UseForgotPasswordProps = () => {\n fetch: (payload: PassflowSendPasswordResetEmailPayload) => Promise<boolean>;\n isLoading: boolean;\n isError: boolean;\n error: string;\n reset: () => void;\n};\n\nexport const useForgotPassword: UseForgotPasswordProps = () => {\n const passflow = usePassflow();\n const [isError, setIsError] = useState(false);\n const [errorMessage, setErrorMessage] = useState('');\n const [isLoading, setIsLoading] = useState(false);\n\n const fetch = useCallback(\n async (payload: PassflowSendPasswordResetEmailPayload): Promise<boolean> => {\n try {\n setIsLoading(true);\n await passflow.sendPasswordResetEmail(payload);\n setIsLoading(false);\n return true;\n } catch (e) {\n setIsError(true);\n const error = e as Error;\n setErrorMessage(error.message);\n return false;\n }\n },\n [passflow.sendPasswordResetEmail],\n );\n\n const reset = () => {\n setIsError(false);\n setErrorMessage('');\n setIsLoading(false);\n };\n\n return { fetch, isLoading, isError, error: errorMessage, reset } as const;\n};\n","import { useCallback, useState } from 'react';\nimport { usePassflow } from './use-passflow';\n\nconst invitationJoinError = \"We couldn't accept this invitation. Try again.\";\n\nexport type UseJoinInviteProps = () => {\n fetch: (token: string) => Promise<boolean>;\n isLoading: boolean;\n isError: boolean;\n error: string;\n};\n\nexport const useJoinInvite: UseJoinInviteProps = () => {\n const passflow = usePassflow();\n const [errorMessage, setErrorMessage] = useState('');\n const [isError, setIsError] = useState(false);\n const [isLoading, setIsLoading] = useState(false);\n\n const fetch = useCallback(\n async (token: string): Promise<boolean> => {\n setIsLoading(true);\n setIsError(false);\n setErrorMessage('');\n\n try {\n await passflow.joinInvitation(token);\n return true;\n } catch (error) {\n console.error('[passflow] accepting invitation failed', error);\n setIsError(true);\n setErrorMessage(invitationJoinError);\n return false;\n } finally {\n setIsLoading(false);\n }\n },\n [passflow.joinInvitation],\n );\n\n return { fetch, isLoading, isError, error: errorMessage } as const;\n};\n","import { useCallback, useState } from 'react';\nimport { usePassflow } from './use-passflow';\n\nexport type UseLogoutProps = () => {\n fetch: () => Promise<boolean>;\n isLoading: boolean;\n isError: boolean;\n error: string;\n};\n\nexport const useLogout: UseLogoutProps = () => {\n const passflow = usePassflow();\n const [errorMessage, setErrorMessage] = useState('');\n const [isError, setIsError] = useState(false);\n const [isLoading, setIsLoading] = useState(false);\n\n const fetch = useCallback(async (): Promise<boolean> => {\n try {\n setIsLoading(true);\n await passflow.logOut();\n setIsLoading(false);\n return true;\n } catch (e) {\n setIsError(true);\n const error = e as Error;\n setErrorMessage(error.message);\n return false;\n }\n }, [passflow]);\n\n return { fetch, isLoading, isError, error: errorMessage } as const;\n};\n","import qs from 'query-string';\nimport { useCallback, useContext } from 'react';\nimport { type NavigateFunction, type NavigateOptions, NavigationContext } from '@/context';\n\nexport type ReactRouterNavigateOptions = {\n pathname: string;\n search: string;\n replace?: boolean;\n};\n\nexport type TanstackRouterNavigateOptions = {\n to: string;\n search: Record<string, unknown>;\n replace?: boolean;\n};\n\nexport type WouterNavigateOptions = {\n to: string;\n search?: Record<string, unknown>;\n replace?: boolean;\n};\n\nexport type ReachRouterNavigateOptions = {\n to: string;\n search?: Record<string, unknown>;\n replace?: boolean;\n};\n\nconst parseSearch = (search: string): Record<string, string> => {\n if (!search) return {};\n const parsed = qs.parse(search.startsWith('?') ? search.slice(1) : search);\n return Object.fromEntries(Object.entries(parsed).map(([key, value]) => [key, String(value)]));\n};\n\nexport const useNavigation = () => {\n const { navigate, setNavigate, router, twoFactorVerifyPath, setTwoFactorVerifyPath } = useContext(NavigationContext);\n\n const wrappedSetNavigate = useCallback(\n (\n newNavigate:\n | ((\n to:\n | NavigateOptions\n | string\n | ReactRouterNavigateOptions\n | TanstackRouterNavigateOptions\n | WouterNavigateOptions\n | ReachRouterNavigateOptions,\n ) => void)\n | null,\n ) => {\n if (!newNavigate) {\n setNavigate(null);\n return;\n }\n\n const wrappedNavigate = ((options: NavigateOptions) => {\n const { to, search = '', replace = false } = options;\n\n switch (router) {\n case 'react-router':\n newNavigate({\n pathname: to,\n search: search.startsWith('?') ? search : `?${search}`,\n replace,\n } as ReactRouterNavigateOptions);\n break;\n\n case 'tanstack-router':\n newNavigate({\n to,\n search: parseSearch(search),\n replace,\n } as TanstackRouterNavigateOptions);\n break;\n\n case 'wouter': {\n const searchParamWouter = search ? (search.startsWith('?') ? search : `?${search}`) : '';\n newNavigate({ to: `${to}${searchParamWouter}`, replace } as WouterNavigateOptions);\n break;\n }\n\n default: {\n // default router\n const searchParamDefault = search ? (search.startsWith('?') ? search : `?${search}`) : '';\n if (replace) {\n window.location.replace(`${to}${searchParamDefault}`);\n } else {\n window.location.href = `${to}${searchParamDefault}`;\n }\n }\n }\n }) as NavigateFunction;\n\n setNavigate(wrappedNavigate);\n },\n [setNavigate, router],\n );\n\n return {\n navigate,\n setNavigate: wrappedSetNavigate,\n router,\n twoFactorVerifyPath,\n setTwoFactorVerifyPath,\n };\n};\n","import { type RefObject, useEffect } from 'react';\n\nexport const useOutsideClick = <T extends HTMLElement>(ref: RefObject<T | null>, onClickOutside?: () => void) => {\n useEffect(() => {\n const handleClick = (event: MouseEvent) => {\n if (ref.current && !ref.current.contains(event.target as Node)) {\n if (onClickOutside) {\n onClickOutside();\n }\n }\n };\n\n document.addEventListener('click', handleClick, true);\n\n return () => {\n document.removeEventListener('click', handleClick, true);\n };\n }, [onClickOutside, ref]);\n};\n","import type { PassflowPasswordlessSignInCompletePayload, PassflowValidationResponse } from '@passflow/core';\nimport { useCallback, useState } from 'react';\nimport { verificationRequestErrorMessage } from '@/utils';\nimport { usePassflow } from './use-passflow';\n\nexport type UsePasswordlessCompleteProps = () => {\n fetch: (payload: PassflowPasswordlessSignInCompletePayload) => Promise<PassflowValidationResponse | null>;\n isLoading: boolean;\n isError: boolean;\n error: string;\n reset: () => void;\n};\n\nexport const usePasswordlessComplete: UsePasswordlessCompleteProps = () => {\n const passflow = usePassflow();\n const [errorMessage, setErrorMessage] = useState('');\n const [isError, setIsError] = useState(false);\n const [isLoading, setIsLoading] = useState(false);\n\n const fetch = useCallback(\n async (payload: PassflowPasswordlessSignInCompletePayload): Promise<PassflowValidationResponse | null> => {\n setIsLoading(true);\n setIsError(false);\n setErrorMessage('');\n\n try {\n return await passflow.passwordlessSignInComplete(payload);\n } catch (error) {\n console.error('[passflow] passwordless verification failed', error);\n setIsError(true);\n setErrorMessage(verificationRequestErrorMessage);\n return null;\n } finally {\n setIsLoading(false);\n }\n },\n [passflow],\n );\n\n const reset = () => {\n setIsError(false);\n setErrorMessage('');\n setIsLoading(false);\n };\n\n return {\n fetch,\n isLoading,\n isError,\n error: errorMessage,\n reset,\n } as const;\n};\n","import type { PassflowFederatedAuthPayload, Providers } from '@passflow/core';\nimport { useContext } from 'react';\nimport { PassflowContext } from '@/context';\nimport { isValidUrl } from '@/utils';\nimport { usePassflow } from './use-passflow';\n\nconst getFullRedirectUrl = (redirectUrl?: string): string => {\n if (redirectUrl && isValidUrl(redirectUrl)) {\n return redirectUrl;\n }\n return redirectUrl ? `${window.location.origin}${redirectUrl.startsWith('/') ? '' : '/'}${redirectUrl}` : '';\n};\n\nexport type UseProviderProps = (\n redirectUrl?: string,\n createTenant?: boolean,\n) => {\n federatedWithPopup: (provider: Providers, inviteToken?: string) => void;\n federatedWithRedirect: (provider: Providers, inviteToken?: string) => void;\n};\n\nexport const useProvider: UseProviderProps = (redirectUrl, createTenant) => {\n const passflow = usePassflow();\n const context = useContext(PassflowContext);\n\n const payload = {\n redirect_url: getFullRedirectUrl(redirectUrl),\n scopes: context?.state.scopes,\n create_tenant: createTenant,\n };\n\n const federatedWithPopup = (provider: Providers, inviteToken?: string) =>\n passflow.federatedAuthWithPopup({ provider, invite_token: inviteToken, ...payload } as PassflowFederatedAuthPayload);\n const federatedWithRedirect = (provider: Providers, inviteToken?: string) =>\n passflow.federatedAuthWithRedirect({ provider, invite_token: inviteToken, ...payload } as PassflowFederatedAuthPayload);\n\n return {\n federatedWithPopup,\n federatedWithRedirect,\n };\n};\n","import { PassflowEvent, type PassflowEventPayload, type PassflowSubscriber } from '@passflow/core';\nimport { useEffect, useState } from 'react';\nimport { usePassflow } from './use-passflow';\n\nexport interface UseRefreshStatusResult {\n /**\n * True inside a transient-failure episode: a token refresh failed for a reason that\n * does not end the session (network, 5xx) and core is retrying. The session is kept.\n */\n isFailing: boolean;\n /**\n * Epoch ms of the episode's first transient failure (`RefreshFailing.since`).\n */\n since: number | null;\n /**\n * Epoch ms of the pending retry, when core knows it (`RefreshFailing.nextRetryAt`).\n */\n nextRetryAt: number | null;\n}\n\nconst IDLE: UseRefreshStatusResult = { isFailing: false, since: null, nextRetryAt: null };\n\nconst EVENTS = [\n PassflowEvent.RefreshFailing,\n PassflowEvent.RefreshRecovered,\n PassflowEvent.SessionExpired,\n PassflowEvent.SignOut,\n PassflowEvent.SignIn,\n PassflowEvent.Register,\n];\n\n/**\n * Hook to show a \"connection trouble\" notice while token refresh is failing transiently.\n *\n * Set by `RefreshFailing`; cleared by `RefreshRecovered`, and by `SessionExpired`,\n * `SignOut`, `SignIn` and `Register`, which end or replace the session the episode\n * belonged to. A real end of the session is reported by `useSessionExpired`, not here.\n *\n * Core reports the episode only as events (there is no getter to read on mount), so a\n * component that mounts after `RefreshFailing` starts idle. Call the hook in a component\n * that lives for the whole app, near `PassflowProvider`.\n *\n * @example\n * ```tsx\n * function ConnectionNotice() {\n * const { isFailing } = useRefreshStatus();\n * return isFailing ? <Banner>Reconnecting...</Banner> : null;\n * }\n * ```\n */\nexport function useRefreshStatus(): UseRefreshStatusResult {\n const passflow = usePassflow();\n const [status, setStatus] = useState<UseRefreshStatusResult>(IDLE);\n\n useEffect(() => {\n const subscriber: PassflowSubscriber = {\n onAuthChange: (eventType, payload) => {\n if (eventType === PassflowEvent.RefreshFailing) {\n const failing = payload as PassflowEventPayload[PassflowEvent.RefreshFailing] | undefined;\n setStatus({\n isFailing: true,\n since: failing?.since ?? null,\n nextRetryAt: failing?.nextRetryAt ?? null,\n });\n } else {\n setStatus(IDLE);\n }\n },\n };\n\n passflow.subscribe(subscriber, EVENTS);\n\n return () => {\n passflow.unsubscribe(subscriber);\n };\n }, [passflow]);\n\n return status;\n}\n","import { useCallback, useState } from 'react';\nimport { usePassflow } from './use-passflow';\n\nexport type UseResetPasswordProps = () => {\n fetch: (newPassword: string) => Promise<boolean>;\n isLoading: boolean;\n isError: boolean;\n error: string;\n reset: () => void;\n};\n\nexport const useResetPassword: UseResetPasswordProps = () => {\n const passflow = usePassflow();\n const [isError, setIsError] = useState(false);\n const [errorMessage, setErrorMessage] = useState('');\n const [isLoading, setIsLoading] = useState(false);\n\n const fetch = useCallback(\n async (newPassword: string): Promise<boolean> => {\n try {\n setIsLoading(true);\n await passflow.resetPassword(newPassword);\n setIsLoading(false);\n return true;\n } catch (e) {\n setIsError(true);\n const error = e as Error;\n setErrorMessage(error.message);\n return false;\n }\n },\n [passflow.resetPassword],\n );\n\n const reset = () => {\n setIsError(false);\n setErrorMessage('');\n setIsLoading(false);\n };\n\n return { fetch, isLoading, isError, error: errorMessage, reset } as const;\n};\n","import { PassflowEvent, type PassflowSubscriber, type SessionExpiredReason } from '@passflow/core';\nimport { useEffect, useState } from 'react';\nimport { usePassflow } from './use-passflow';\n\nexport interface UseSessionExpiredOptions {\n /**\n * Called when the session expires.\n * Use this to redirect to your login page.\n */\n onSessionExpired?: (reason: SessionExpiredReason) => void;\n}\n\nexport interface UseSessionExpiredResult {\n /**\n * True if the session has expired and user needs to re-authenticate.\n */\n isSessionExpired: boolean;\n /**\n * The reason why the session expired, if applicable.\n */\n expiredReason: SessionExpiredReason | null;\n /**\n * Reset the session expired state (e.g., after redirecting to login).\n */\n resetSessionExpired: () => void;\n}\n\n/**\n * Hook to handle session expiration events.\n *\n * Core emits SessionExpired only when the session has really ended: the last\n * auth strike (`'refresh_failed'`), no successor token pair in time\n * (`'successor_timeout'`), or another user's tokens in storage\n * (`'identity_changed'`). A transient refresh failure (network, 5xx) keeps the\n * session and is reported as RefreshFailing / RefreshRecovered instead; see\n * `useRefreshStatus`. This hook lets you react to the real end and redirect\n * users to your login page.\n *\n * @example\n * ```tsx\n * function App() {\n * const { isSessionExpired } = useSessionExpired({\n * onSessionExpired: (reason) => {\n * console.log('Session expired:', reason);\n * window.location.href = '/login';\n * },\n * });\n *\n * if (isSessionExpired) {\n * return <div>Redirecting to login...</div>;\n * }\n *\n * return <YourApp />;\n * }\n * ```\n */\nexport function useSessionExpired(options?: UseSessionExpiredOptions): UseSessionExpiredResult {\n const passflow = usePassflow();\n const [isSessionExpired, setIsSessionExpired] = useState(false);\n const [expiredReason, setExpiredReason] = useState<SessionExpiredReason | null>(null);\n\n useEffect(() => {\n const subscriber: PassflowSubscriber = {\n onAuthChange: (eventType, payload) => {\n if (eventType === PassflowEvent.SessionExpired) {\n const reason = (payload as { reason?: SessionExpiredReason })?.reason ?? 'refresh_failed';\n setIsSessionExpired(true);\n setExpiredReason(reason);\n options?.onSessionExpired?.(reason);\n } else if (eventType === PassflowEvent.SignIn || eventType === PassflowEvent.Register) {\n // Reset on successful auth\n setIsSessionExpired(false);\n setExpiredReason(null);\n }\n },\n };\n\n passflow.subscribe(subscriber, [PassflowEvent.SessionExpired, PassflowEvent.SignIn, PassflowEvent.Register]);\n\n return () => {\n passflow.unsubscribe(subscriber);\n };\n }, [passflow, options?.onSessionExpired]);\n\n const resetSessionExpired = () => {\n setIsSessionExpired(false);\n setExpiredReason(null);\n };\n\n return {\n isSessionExpired,\n expiredReason,\n resetSessionExpired,\n };\n}\n","import type {\n PassflowPasskeyAuthenticateStartPayload,\n PassflowPasswordlessResponse,\n PassflowPasswordlessSignInPayload,\n PassflowSignInPayload,\n} from '@passflow/core';\nimport { useCallback, useState } from 'react';\nimport type { AuthOperation, AuthUiError } from '@/types';\nimport { authErrorFor } from '@/utils';\nimport { usePassflow } from './use-passflow';\n\nexport type UseSignInProps = () => {\n fetch: (\n payload: PassflowPasskeyAuthenticateStartPayload | PassflowSignInPayload | PassflowPasswordlessSignInPayload,\n type: AuthOperation,\n ) => Promise<boolean | string | PassflowPasswordlessResponse>;\n isLoading: boolean;\n isError: boolean;\n error: AuthUiError | null;\n reset: () => void;\n};\n\nexport const useSignIn: UseSignInProps = () => {\n const passflow = usePassflow();\n const [error, setError] = useState<AuthUiError | null>(null);\n const [isError, setIsError] = useState(false);\n const [isLoading, setIsLoading] = useState(false);\n\n const fetch = useCallback(\n async (\n payload: PassflowPasskeyAuthenticateStartPayload | PassflowSignInPayload | PassflowPasswordlessSignInPayload,\n type: AuthOperation,\n ): Promise<boolean | string | PassflowPasswordlessResponse> => {\n setIsLoading(true);\n setIsError(false);\n setError(null);\n const cleanup = () => setIsLoading(false);\n\n // We'll make sure to call cleanup after the operation completes\n try {\n if (type === 'password') await passflow.signIn(payload as PassflowSignInPayload);\n else if (type === 'passkey') {\n await passflow.passkeyAuthenticate(payload as PassflowPasskeyAuthenticateStartPayload);\n } else {\n return await passflow.passwordlessSignIn(payload as PassflowPasswordlessSignInPayload);\n }\n return true;\n } catch (error) {\n console.error(`[passflow] ${type} sign-in failed`, error);\n setIsError(true);\n setError(authErrorFor('sign-in', type));\n return false;\n } finally {\n cleanup();\n }\n },\n [passflow.passkeyAuthenticate, passflow.passwordlessSignIn, passflow.signIn],\n );\n\n const reset = () => {\n setIsError(false);\n setError(null);\n setIsLoading(false);\n };\n\n return { fetch, isLoading, isError, error, reset } as const;\n};\n","import type {\n PassflowPasskeyRegisterStartPayload,\n PassflowPasswordlessResponse,\n PassflowPasswordlessSignInPayload,\n PassflowSignUpPayload,\n} from '@passflow/core';\nimport { useCallback, useState } from 'react';\nimport type { AuthOperation, AuthUiError } from '@/types';\nimport { authErrorFor } from '@/utils';\nimport { usePassflow } from './use-passflow';\n\nexport type UseSignUpProps = () => {\n fetch: (\n payload: PassflowPasskeyRegisterStartPayload | PassflowSignUpPayload | PassflowPasswordlessSignInPayload,\n type: AuthOperation,\n ) => Promise<boolean | string | PassflowPasswordlessResponse>;\n isLoading: boolean;\n isError: boolean;\n error: AuthUiError | null;\n reset: () => void;\n};\n\nexport const useSignUp: UseSignUpProps = () => {\n const passflow = usePassflow();\n const [isError, setIsError] = useState(false);\n const [error, setError] = useState<AuthUiError | null>(null);\n const [isLoading, setIsLoading] = useState(false);\n\n const fetch = useCallback(\n async (\n payload: PassflowPasskeyRegisterStartPayload | PassflowSignUpPayload | PassflowPasswordlessSignInPayload,\n type: AuthOperation,\n ): Promise<boolean | PassflowPasswordlessResponse> => {\n setIsLoading(true);\n setIsError(false);\n setError(null);\n const cleanup = () => setIsLoading(false);\n\n try {\n if (type === 'password') await passflow.signUp(payload as PassflowSignUpPayload);\n else if (type === 'passkey') {\n await passflow.passkeyRegister(payload as PassflowPasskeyRegisterStartPayload);\n } else {\n const passwordlessResponse = await passflow.passwordlessSignIn(payload as PassflowPasswordlessSignInPayload);\n cleanup();\n return passwordlessResponse;\n }\n cleanup();\n return true;\n } catch (error) {\n console.error(`[passflow] ${type} sign-up failed`, error);\n setIsError(true);\n setError(authErrorFor('sign-up', type));\n cleanup();\n return false;\n } finally {\n cleanup();\n }\n },\n [passflow.signUp, passflow.passkeyRegister, passflow.passwordlessSignIn],\n );\n\n const reset = () => {\n setIsError(false);\n setError(null);\n setIsLoading(false);\n };\n\n return { fetch, isLoading, isError, error, reset } as const;\n};\n","import type { TwoFactorTrustedDevice } from '@passflow/core';\nimport { useCallback, useLayoutEffect, useState } from 'react';\nimport { usePassflow } from './use-passflow';\n\nexport type UseTrustedDevicesProps = () => {\n /** The devices the signed-in user trusted to skip the second factor on this app. */\n data: TwoFactorTrustedDevice[];\n refetch: () => Promise<TwoFactorTrustedDevice[] | null>;\n /**\n * Revokes one device; its next sign-in asks for the second factor again.\n * On success the device leaves `data` without a refetch.\n *\n * @returns true when the server revoked it\n */\n revoke: (deviceId: string) => Promise<boolean>;\n isLoading: boolean;\n isError: boolean;\n errorMessage: string;\n};\n\n/**\n * Hook to list and revoke the signed-in user's trusted devices\n */\nexport const useTrustedDevices: UseTrustedDevicesProps = () => {\n const passflow = usePassflow();\n const [data, setData] = useState<TwoFactorTrustedDevice[]>([]);\n const [isLoading, setIsLoading] = useState<boolean>(false);\n const [isError, setIsError] = useState<boolean>(false);\n const [errorMessage, setErrorMessage] = useState<string>('');\n\n const fail = useCallback((e: unknown) => {\n setIsError(true);\n setErrorMessage((e as Error).message);\n }, []);\n\n const fetch = useCallback(async (): Promise<TwoFactorTrustedDevice[] | null> => {\n setIsLoading(true);\n setIsError(false);\n setErrorMessage('');\n try {\n const devices = await passflow.getTrustedDevices();\n setData(devices);\n return devices;\n } catch (e) {\n fail(e);\n return null;\n } finally {\n setIsLoading(false);\n }\n }, [passflow, fail]);\n\n const revoke = useCallback(\n async (deviceId: string): Promise<boolean> => {\n setIsLoading(true);\n setIsError(false);\n setErrorMessage('');\n try {\n await passflow.revokeTrustedDevice(deviceId);\n setData((devices) => devices.filter((device) => device.id !== deviceId));\n return true;\n } catch (e) {\n fail(e);\n return false;\n } finally {\n setIsLoading(false);\n }\n },\n [passflow, fail],\n );\n\n useLayoutEffect(() => {\n void fetch();\n }, [fetch]);\n\n return {\n data,\n refetch: fetch,\n revoke,\n isLoading,\n isError,\n errorMessage,\n };\n};\n","import type { TwoFactorChallengeResponse, TwoFactorMethod, TwoFactorVerifyResponseV2 } from '@passflow/core';\nimport { useCallback, useState } from 'react';\nimport { usePassflow } from './use-passflow';\n\nexport type UseTwoFactorChallengeReturn = {\n challenge: TwoFactorChallengeResponse | null;\n isLoading: boolean;\n error: Error | null;\n requestChallenge: (firstFactorMethod?: string) => Promise<void>;\n verify: (response: string, trustDevice?: boolean) => Promise<TwoFactorVerifyResponseV2 | null>;\n switchMethod: (method: TwoFactorMethod) => Promise<void>;\n selectedMethod: TwoFactorMethod | null;\n reset: () => void;\n};\n\n/**\n * Hook to manage the v2 two-factor challenge flow with multi-method support\n */\nexport const useTwoFactorChallenge = (): UseTwoFactorChallengeReturn => {\n const passflow = usePassflow();\n const [challenge, setChallenge] = useState<TwoFactorChallengeResponse | null>(null);\n const [selectedMethod, setSelectedMethod] = useState<TwoFactorMethod | null>(null);\n const [isLoading, setIsLoading] = useState<boolean>(false);\n const [error, setError] = useState<Error | null>(null);\n\n const requestChallenge = useCallback(\n async (firstFactorMethod?: string): Promise<void> => {\n setIsLoading(true);\n setError(null);\n\n try {\n const response = await passflow.twoFactor.requestChallenge({\n first_factor_method: firstFactorMethod,\n });\n setChallenge(response);\n setSelectedMethod(response.method);\n } catch (e) {\n setError(e as Error);\n setChallenge(null);\n } finally {\n setIsLoading(false);\n }\n },\n [passflow],\n );\n\n const verify = useCallback(\n async (response: string, trustDevice = false): Promise<TwoFactorVerifyResponseV2 | null> => {\n if (!challenge?.challenge_id) {\n setError(new Error('No active challenge session'));\n return null;\n }\n\n setIsLoading(true);\n setError(null);\n\n try {\n const result = await passflow.twoFactor.verifyV2({\n challenge_id: challenge.challenge_id,\n method: selectedMethod || challenge.method,\n response,\n trust_device: trustDevice,\n });\n return result;\n } catch (e) {\n setError(e as Error);\n return null;\n } finally {\n setIsLoading(false);\n }\n },\n [passflow, challenge, selectedMethod],\n );\n\n const switchMethod = useCallback(\n async (method: TwoFactorMethod): Promise<void> => {\n if (!challenge?.challenge_id) {\n setError(new Error('No active challenge session'));\n return;\n }\n\n setIsLoading(true);\n setError(null);\n\n try {\n const response = await passflow.twoFactor.switchToAlternative({\n challenge_id: challenge.challenge_id,\n method,\n });\n setChallenge(response);\n setSelectedMethod(method);\n } catch (e) {\n setError(e as Error);\n } finally {\n setIsLoading(false);\n }\n },\n [passflow, challenge],\n );\n\n const reset = useCallback(() => {\n setChallenge(null);\n setSelectedMethod(null);\n setError(null);\n setIsLoading(false);\n }, []);\n\n return {\n challenge,\n isLoading,\n error,\n requestChallenge,\n verify,\n switchMethod,\n selectedMethod,\n reset,\n };\n};\n","import type { TwoFactorRegenerateResponse } from '@passflow/core';\nimport { useCallback, useState } from 'react';\nimport { usePassflow } from './use-passflow';\n\nexport type UseTwoFactorManageProps = () => {\n recoveryCodes: string[];\n disable: (code: string) => Promise<boolean>;\n regenerateCodes: (code: string) => Promise<TwoFactorRegenerateResponse | null>;\n reset: () => void;\n isLoading: boolean;\n isError: boolean;\n error: string;\n};\n\n/**\n * Hook to manage 2FA (disable, regenerate codes)\n */\nexport const useTwoFactorManage: UseTwoFactorManageProps = () => {\n const passflow = usePassflow();\n const [recoveryCodes, setRecoveryCodes] = useState<string[]>([]);\n const [isLoading, setIsLoading] = useState<boolean>(false);\n const [isError, setIsError] = useState<boolean>(false);\n const [error, setError] = useState<string>('');\n\n const disable = useCallback(\n async (code: string): Promise<boolean> => {\n setIsLoading(true);\n setIsError(false);\n setError('');\n try {\n await passflow.disableTwoFactor(code);\n return true;\n } catch (e) {\n setIsError(true);\n const err = e as Error;\n setError(err.message);\n return false;\n } finally {\n setIsLoading(false);\n }\n },\n [passflow],\n );\n\n const regenerateCodes = useCallback(\n async (code: string): Promise<TwoFactorRegenerateResponse | null> => {\n setIsLoading(true);\n setIsError(false);\n setError('');\n try {\n const response = await passflow.regenerateTwoFactorRecoveryCodes(code);\n setRecoveryCodes(response.recovery_codes);\n return response;\n } catch (e) {\n setIsError(true);\n const err = e as Error;\n setError(err.message);\n return null;\n } finally {\n setIsLoading(false);\n }\n },\n [passflow],\n );\n\n const reset = useCallback(() => {\n setRecoveryCodes([]);\n setIsError(false);\n setError('');\n }, []);\n\n return {\n recoveryCodes,\n disable,\n regenerateCodes,\n reset,\n isLoading,\n isError,\n error,\n };\n};\n","import type { RegisteredTwoFactorMethod, TwoFactorMethod } from '@passflow/core';\nimport { useCallback, useState } from 'react';\nimport { usePassflow } from './use-passflow';\n\nexport type UseTwoFactorMethodsReturn = {\n availableMethods: TwoFactorMethod[];\n registeredMethods: RegisteredTwoFactorMethod[];\n isLoading: boolean;\n error: Error | null;\n refresh: () => Promise<void>;\n removeMethod: (methodId: string) => Promise<void>;\n};\n\n/**\n * Hook to manage two-factor authentication methods\n */\nexport const useTwoFactorMethods = (): UseTwoFactorMethodsReturn => {\n const passflow = usePassflow();\n const [availableMethods, setAvailableMethods] = useState<TwoFactorMethod[]>([]);\n const [registeredMethods, setRegisteredMethods] = useState<RegisteredTwoFactorMethod[]>([]);\n const [isLoading, setIsLoading] = useState<boolean>(false);\n const [error, setError] = useState<Error | null>(null);\n\n const refresh = useCallback(async (): Promise<void> => {\n setIsLoading(true);\n setError(null);\n\n try {\n const methods = await passflow.twoFactor.getRegisteredMethods();\n setRegisteredMethods(methods);\n\n // Extract available methods from registered methods\n const available = methods.map((m) => m.method);\n setAvailableMethods(available);\n } catch (e) {\n setError(e as Error);\n setRegisteredMethods([]);\n setAvailableMethods([]);\n } finally {\n setIsLoading(false);\n }\n }, [passflow]);\n\n const removeMethod = useCallback(\n async (methodId: string): Promise<void> => {\n setIsLoading(true);\n setError(null);\n\n try {\n // Call remove method API (needs to be implemented in @passflow/core)\n // For now, this is a placeholder\n await passflow.twoFactor.removeMethod?.(methodId);\n\n // Refresh the methods list after removal\n await refresh();\n } catch (e) {\n setError(e as Error);\n } finally {\n setIsLoading(false);\n }\n },\n [passflow, refresh],\n );\n\n return {\n availableMethods,\n registeredMethods,\n isLoading,\n error,\n refresh,\n removeMethod,\n };\n};\n","import type { TwoFactorConfirmResponse, TwoFactorSetupResponse } from '@passflow/core';\nimport { useCallback, useState } from 'react';\nimport { usePassflow } from './use-passflow';\n\nexport type TwoFactorSetupStep = 'idle' | 'setup' | 'complete';\n\nexport type UseTwoFactorSetupProps = () => {\n setupData: TwoFactorSetupResponse | null;\n recoveryCodes: string[];\n step: TwoFactorSetupStep;\n beginSetup: () => Promise<TwoFactorSetupResponse | null>;\n confirmSetup: (code: string) => Promise<TwoFactorConfirmResponse | null>;\n reset: () => void;\n isLoading: boolean;\n isError: boolean;\n error: string;\n};\n\n/**\n * Hook to handle 2FA setup flow (enable 2FA)\n */\nexport const useTwoFactorSetup: UseTwoFactorSetupProps = () => {\n const passflow = usePassflow();\n const [setupData, setSetupData] = useState<TwoFactorSetupResponse | null>(null);\n const [recoveryCodes, setRecoveryCodes] = useState<string[]>([]);\n const [isLoading, setIsLoading] = useState<boolean>(false);\n const [isError, setIsError] = useState<boolean>(false);\n const [error, setError] = useState<string>('');\n const [step, setStep] = useState<TwoFactorSetupStep>('idle');\n\n const beginSetup = useCallback(async (): Promise<TwoFactorSetupResponse | null> => {\n setIsLoading(true);\n setIsError(false);\n setError('');\n try {\n const response = await passflow.beginTwoFactorSetup();\n setSetupData(response);\n setStep('setup');\n return response;\n } catch (e) {\n setIsError(true);\n const err = e as Error;\n setError(err.message);\n return null;\n } finally {\n setIsLoading(false);\n }\n }, [passflow]);\n\n const confirmSetup = useCallback(\n async (code: string): Promise<TwoFactorConfirmResponse | null> => {\n setIsLoading(true);\n setIsError(false);\n setError('');\n try {\n const response = await passflow.confirmTwoFactorSetup(code);\n setRecoveryCodes(response.recovery_codes);\n setStep('complete');\n return response;\n } catch (e) {\n setIsError(true);\n const err = e as Error;\n setError(err.message);\n return null;\n } finally {\n setIsLoading(false);\n }\n },\n [passflow],\n );\n\n const reset = useCallback(() => {\n setSetupData(null);\n setRecoveryCodes([]);\n setIsError(false);\n setError('');\n setStep('idle');\n }, []);\n\n return {\n setupData,\n recoveryCodes,\n step,\n beginSetup,\n confirmSetup,\n reset,\n isLoading,\n isError,\n error,\n };\n};\n","import { useCallback, useEffect, useRef, useState } from 'react';\nimport { usePassflow } from './use-passflow';\n\n/**\n * Magic link validation error type\n */\nexport type TwoFactorSetupMagicLinkError = {\n code: 'INVALID_TOKEN' | 'EXPIRED_TOKEN' | 'REVOKED_TOKEN' | 'RATE_LIMITED' | 'SERVER_ERROR';\n message: string;\n retryAfter?: number; // Seconds until retry allowed (for RATE_LIMITED)\n};\n\n/**\n * Expected response shape from passflow.validateTwoFactorSetupMagicLink\n */\ntype ValidationResponse = {\n success: boolean;\n sessionToken?: string;\n userId?: string;\n expiresIn?: number;\n appId?: string | null;\n error?: TwoFactorSetupMagicLinkError;\n};\n\n/**\n * Return type for useTwoFactorSetupMagicLink hook\n */\nexport type UseTwoFactorSetupMagicLinkReturn = {\n /** True during validation */\n isLoading: boolean;\n /** True during retry attempt */\n isRetrying: boolean;\n /** True if token validated successfully */\n isValidated: boolean;\n /** Error details if validation failed */\n error: TwoFactorSetupMagicLinkError | null;\n /** Session token if validated */\n sessionToken: string | null;\n /** User ID if validated */\n userId: string | null;\n /** App ID if validated (may be null) */\n appId: string | null;\n /** Session expiration in seconds */\n expiresIn: number | null;\n /** Retry countdown for rate-limited errors (null if not rate limited) */\n retryCountdown: number | null;\n /** Manual retry function for transient errors */\n retry: () => Promise<void>;\n};\n\n/**\n * Hook to validate magic link token for 2FA setup\n *\n * This hook:\n * - Validates token on mount (automatic)\n * - Caches validation result per token (prevents duplicate calls)\n * - Provides loading, error, and success states\n * - Allows manual retry for transient failures\n * - Handles rate limit countdown\n * - Cleans up conditionally on unmount (only if validation failed or not validated)\n *\n * Usage:\n * ```tsx\n * const { isLoading, isValidated, error, retry, retryCountdown } = useTwoFactorSetupMagicLink(token);\n *\n * if (isLoading) return <Loading />;\n * if (error) return <ErrorUI error={error} onRetry={retry} countdown={retryCountdown} />;\n * if (isValidated) return <TwoFactorSetupForm />;\n * ```\n */\nexport const useTwoFactorSetupMagicLink = (token: string): UseTwoFactorSetupMagicLinkReturn => {\n const passflow = usePassflow();\n\n // State management\n const [isLoading, setIsLoading] = useState<boolean>(true);\n const [isRetrying, setIsRetrying] = useState<boolean>(false);\n const [isValidated, setIsValidated] = useState<boolean>(false);\n const [error, setError] = useState<TwoFactorSetupMagicLinkError | null>(null);\n const [sessionToken, setSessionToken] = useState<string | null>(null);\n const [userId, setUserId] = useState<string | null>(null);\n const [appId, setAppId] = useState<string | null>(null);\n const [expiresIn, setExpiresIn] = useState<number | null>(null);\n const [retryCountdown, setRetryCountdown] = useState<number | null>(null);\n\n // Cache key for validation (prevents duplicate calls for same token)\n const [validatedToken, setValidatedToken] = useState<string | null>(null);\n\n // Ref to track if we should clear session on unmount\n const shouldClearOnUnmount = useRef<boolean>(true);\n\n // Countdown timer ref\n const countdownTimerRef = useRef<NodeJS.Timeout | null>(null);\n\n /**\n * Start rate limit countdown timer\n */\n const startCountdown = useCallback((seconds: number) => {\n // Clear existing timer\n if (countdownTimerRef.current) {\n clearInterval(countdownTimerRef.current);\n }\n\n setRetryCountdown(seconds);\n\n countdownTimerRef.current = setInterval(() => {\n setRetryCountdown((prev) => {\n if (prev === null || prev <= 1) {\n if (countdownTimerRef.current) {\n clearInterval(countdownTimerRef.current);\n countdownTimerRef.current = null;\n }\n return null;\n }\n return prev - 1;\n });\n }, 1000);\n }, []);\n\n /**\n * Validate token via JS SDK\n */\n const validateToken = useCallback(\n async (isRetry = false) => {\n // Skip if already validated this token\n if (!isRetry && validatedToken === token && isValidated) {\n return;\n }\n\n // Reset state\n if (isRetry) {\n setIsRetrying(true);\n } else {\n setIsLoading(true);\n }\n setError(null);\n\n try {\n // Call JS SDK validation method\n // Cast to unknown to support cases where React SDK builds before JS SDK types are updated\n const passflowWithMagicLink = passflow as unknown as {\n validateTwoFactorSetupMagicLink: (token: string) => Promise<ValidationResponse>;\n };\n const response = await passflowWithMagicLink.validateTwoFactorSetupMagicLink(token);\n\n if (response.success && response.sessionToken && response.userId) {\n // Success - store session details\n setSessionToken(response.sessionToken);\n setUserId(response.userId);\n setAppId(response.appId ?? null);\n setExpiresIn(response.expiresIn ?? null);\n setIsValidated(true);\n setValidatedToken(token);\n setRetryCountdown(null);\n // Don't clear session on unmount if validation succeeded\n shouldClearOnUnmount.current = false;\n } else if (response.error) {\n // Validation failed\n setError(response.error);\n setIsValidated(false);\n shouldClearOnUnmount.current = true;\n\n // Start countdown for rate-limited errors\n if (response.error.code === 'RATE_LIMITED' && response.error.retryAfter) {\n startCountdown(response.error.retryAfter);\n }\n }\n } catch (err) {\n // Unexpected error (shouldn't happen - SDK catches errors)\n setError({\n code: 'SERVER_ERROR',\n message: err instanceof Error ? err.message : 'An unexpected error occurred',\n });\n setIsValidated(false);\n shouldClearOnUnmount.current = true;\n } finally {\n setIsLoading(false);\n setIsRetrying(false);\n }\n },\n [token, validatedToken, isValidated, passflow, startCountdown],\n );\n\n /**\n * Manual retry for transient errors\n */\n const retry = useCallback(async () => {\n // Don't allow retry during countdown\n if (retryCountdown !== null && retryCountdown > 0) {\n return;\n }\n\n // Reset cache to allow retry\n setValidatedToken(null);\n await validateToken(true);\n }, [validateToken, retryCountdown]);\n\n /**\n * Validate on mount or when token changes\n */\n useEffect(() => {\n if (!token) {\n setError({\n code: 'INVALID_TOKEN',\n message: 'No token provided',\n });\n setIsLoading(false);\n return;\n }\n\n // Validate if token changed or not yet validated\n if (token !== validatedToken) {\n validateToken();\n }\n }, [token, validatedToken, validateToken]);\n\n /**\n * Cleanup on unmount - conditional based on validation state\n * Per review feedback: Only clear if validation failed or user navigated away before validation\n */\n useEffect(() => {\n return () => {\n // Clear countdown timer\n if (countdownTimerRef.current) {\n clearInterval(countdownTimerRef.current);\n }\n\n // Only clear magic link session if validation failed or wasn't validated\n // If isValidated=true, let the form handle session clearing after confirm\n if (shouldClearOnUnmount.current) {\n const passflowWithSession = passflow as unknown as { clearMagicLinkSession?: () => void };\n passflowWithSession.clearMagicLinkSession?.();\n }\n };\n }, [passflow]);\n\n return {\n isLoading,\n isRetrying,\n isValidated,\n error,\n sessionToken,\n userId,\n appId,\n expiresIn,\n retryCountdown,\n retry,\n };\n};\n","import type { TwoFactorStatusResponse } from '@passflow/core';\nimport { useCallback, useLayoutEffect, useState } from 'react';\nimport { usePassflow } from './use-passflow';\n\nexport type UseTwoFactorStatusProps = () => {\n data: TwoFactorStatusResponse | null;\n refetch: () => Promise<TwoFactorStatusResponse | null>;\n isLoading: boolean;\n isError: boolean;\n errorMessage: string;\n};\n\n/**\n * Hook to get the current 2FA enrollment status\n */\nexport const useTwoFactorStatus: UseTwoFactorStatusProps = () => {\n const passflow = usePassflow();\n const [data, setData] = useState<TwoFactorStatusResponse | null>(null);\n const [isLoading, setIsLoading] = useState<boolean>(false);\n const [isError, setIsError] = useState<boolean>(false);\n const [errorMessage, setErrorMessage] = useState<string>('');\n\n const fetch = useCallback(async (): Promise<TwoFactorStatusResponse | null> => {\n setIsLoading(true);\n setIsError(false);\n setErrorMessage('');\n try {\n const response = await passflow.getTwoFactorStatus();\n setData(response);\n return response;\n } catch (e) {\n setIsError(true);\n const error = e as Error;\n setErrorMessage(error.message);\n return null;\n } finally {\n setIsLoading(false);\n }\n }, [passflow]);\n\n useLayoutEffect(() => {\n void fetch();\n }, [fetch]);\n\n return {\n data,\n refetch: fetch,\n isLoading,\n isError,\n errorMessage,\n };\n};\n","import type { TwoFactorCompletionOptions, TwoFactorRecoveryResponse, TwoFactorVerifyResponse } from '@passflow/core';\nimport { useCallback, useState } from 'react';\nimport type { TwoFactorError, TwoFactorErrorType } from '@/types/two-factor-errors';\nimport { classifyTwoFactorError } from '@/utils/classify-two-factor-error';\nimport { usePassflow } from './use-passflow';\n\nexport type UseTwoFactorVerifyProps = () => {\n isVerificationRequired: () => boolean;\n /** `options.trustDevice` asks the server to trust this device for later sign-ins. */\n verify: (code: string, options?: TwoFactorCompletionOptions) => Promise<TwoFactorVerifyResponse | null>;\n /** `options.trustDevice` asks the server to trust this device for later sign-ins. */\n useRecoveryCode: (code: string, options?: TwoFactorCompletionOptions) => Promise<TwoFactorRecoveryResponse | null>;\n reset: () => void;\n isLoading: boolean;\n isError: boolean;\n error: string;\n errorType: TwoFactorErrorType | null;\n errorDetails: TwoFactorError | null;\n};\n\n/**\n * Hook to verify 2FA code during login with error classification\n */\nexport const useTwoFactorVerify: UseTwoFactorVerifyProps = () => {\n const passflow = usePassflow();\n const [isLoading, setIsLoading] = useState<boolean>(false);\n const [isError, setIsError] = useState<boolean>(false);\n const [error, setError] = useState<string>('');\n const [errorType, setErrorType] = useState<TwoFactorErrorType | null>(null);\n const [errorDetails, setErrorDetails] = useState<TwoFactorError | null>(null);\n\n const isVerificationRequired = useCallback((): boolean => {\n return passflow.isTwoFactorVerificationRequired();\n }, [passflow]);\n\n const handleError = useCallback((e: unknown) => {\n const err = e as Error;\n const classified = classifyTwoFactorError(err.message);\n\n setIsError(true);\n setError(err.message);\n setErrorType(classified.type);\n setErrorDetails(classified);\n }, []);\n\n const verify = useCallback(\n async (code: string, options?: TwoFactorCompletionOptions): Promise<TwoFactorVerifyResponse | null> => {\n setIsLoading(true);\n setIsError(false);\n setError('');\n setErrorType(null);\n setErrorDetails(null);\n\n try {\n const response = await passflow.verifyTwoFactor(code, options);\n return response;\n } catch (e) {\n handleError(e);\n return null;\n } finally {\n setIsLoading(false);\n }\n },\n [passflow, handleError],\n );\n\n const useRecoveryCode = useCallback(\n async (code: string, options?: TwoFactorCompletionOptions): Promise<TwoFactorRecoveryResponse | null> => {\n setIsLoading(true);\n setIsError(false);\n setError('');\n setErrorType(null);\n setErrorDetails(null);\n\n try {\n const response = await passflow.useTwoFactorRecoveryCode(code, options);\n return response;\n } catch (e) {\n handleError(e);\n return null;\n } finally {\n setIsLoading(false);\n }\n },\n [passflow, handleError],\n );\n\n const reset = useCallback(() => {\n setIsError(false);\n setError('');\n setErrorType(null);\n setErrorDetails(null);\n }, []);\n\n return {\n isVerificationRequired,\n verify,\n useRecoveryCode,\n reset,\n isLoading,\n isError,\n error,\n errorType,\n errorDetails,\n };\n};\n","/**\n * `useUpgrade` — the read side of the assurance-upgrade flow (§8.2, §13.3).\n *\n * It **reads `UpgradeContext` and installs nothing**. Installation belongs to\n * `UpgradeProvider` and only to it: two hooks each installing a prompt handler\n * would open two prompts and defeat single-flight.\n *\n * Outside an `UpgradeProvider` it returns `status: 'idle'` with no-op actions\n * rather than throwing (§9.5 H8).\n */\n\nimport type { AssuranceBar, UpgradeChallenge, UpgradeFactor, UpgradeFactorType } from '@passflow/core';\nimport { useContext, useMemo } from 'react';\nimport {\n INERT_UPGRADE_CONTEXT,\n UpgradeContext,\n type UpgradeContextValue,\n type UpgradeElevateOptions,\n type UpgradeErrorStatusKind,\n type UpgradeHookState,\n type UpgradePromptView,\n type UpgradeSettledState,\n} from '@/context/upgrade-context';\n\nexport type UseUpgradeResult = {\n /** True when an `UpgradeProvider` installed a prompt handler. */\n enabled: boolean;\n /** The whole state, as the discriminated union (§13.5's `UpgradeHookState`). */\n state: UpgradeHookState;\n /** The discriminant, for the common `status === 'challenged'` read. */\n status: UpgradeHookState['status'];\n /** What the server demanded — the MERGED requirement when challenges joined. */\n challenge: UpgradeChallenge | null;\n /** Usable factors, already ranked; index 0 is the suggested one. */\n factors: readonly UpgradeFactor[];\n /** The ranked factor types, which is what `UpgradeHookState.challenged` carries. */\n factorTypes: readonly UpgradeFactorType[];\n selectedFactor: UpgradeFactorType | null;\n /**\n * Elevated, and still not enough: the replay was re-challenged (§13.4).\n * Non-null **only** in the `insufficient` state, and it never coexists with\n * `status === 'success'` — this must not read as success.\n */\n insufficient: { obtained: AssuranceBar; required: AssuranceBar } | null;\n /** The terminal failure, in the `error` state only. */\n error: Error | null;\n /** Which failure class, in the `error` state only. */\n errorKind: UpgradeErrorStatusKind | null;\n /** The previous attempt's failure while the prompt is re-shown (a wrong code). */\n previousError: Error | null;\n /** True while a ceremony is on the wire. */\n busy: boolean;\n /** The factor-selection signal — §13.2's late-join boundary (T3). */\n selectFactor: (factor: UpgradeFactorType) => void;\n submit: (code?: string) => void;\n cancel: () => void;\n dismiss: () => void;\n /** Resolves `null` on cancellation; otherwise the flight's terminal state. */\n elevate: (options?: UpgradeElevateOptions) => Promise<UpgradeSettledState | null>;\n};\n\nconst EMPTY_FACTORS: readonly UpgradeFactor[] = [];\n\nconst readPromptFactors = (prompt: UpgradePromptView | null): readonly UpgradeFactor[] =>\n prompt === null ? EMPTY_FACTORS : prompt.factors;\n\nexport const useUpgrade = (): UseUpgradeResult => {\n const context: UpgradeContextValue = useContext(UpgradeContext) ?? INERT_UPGRADE_CONTEXT;\n const { enabled, state, prompt, selectedFactor, selectFactor, submit, cancel, dismiss, elevate } = context;\n\n return useMemo<UseUpgradeResult>(() => {\n const factors = readPromptFactors(prompt);\n\n return {\n enabled,\n state,\n status: state.status,\n challenge: state.status === 'challenged' ? state.challenge : (prompt?.challenge ?? null),\n factors,\n factorTypes: state.status === 'challenged' ? state.factors : factors.map((factor) => factor.type),\n selectedFactor,\n insufficient: state.status === 'insufficient' ? { obtained: state.obtained, required: state.required } : null,\n error: state.status === 'error' ? state.error : null,\n errorKind: state.status === 'error' ? state.kind : null,\n previousError: prompt?.previousError ?? null,\n busy: state.status === 'submitting',\n selectFactor,\n submit,\n cancel,\n dismiss,\n elevate,\n };\n }, [enabled, state, prompt, selectedFactor, selectFactor, submit, cancel, dismiss, elevate]);\n};\n","import type { PassflowUserPasskey } from '@passflow/core';\nimport { useLayoutEffect, useState } from 'react';\nimport { usePassflow } from './use-passflow';\n\nexport type UseUserPasskeysProps = () => {\n data: PassflowUserPasskey[];\n createUserPasskey: (relaingPartyId: string) => Promise<void>;\n editUserPasskey: (newName: string, passkeyId: string) => Promise<void>;\n deleteUserPasskey: (passkeyId: string) => Promise<void>;\n isLoading: boolean;\n isError: boolean;\n errorMessage: string;\n};\n\nexport const useUserPasskeys: UseUserPasskeysProps = () => {\n const passflow = usePassflow();\n const [data, setData] = useState<PassflowUserPasskey[]>([]);\n const [isError, setIsError] = useState<boolean>(false);\n const [errorMessage, setErrorMessage] = useState<string>('');\n const [isLoading, setIsLoading] = useState<boolean>(false);\n\n useLayoutEffect(() => {\n const fetch = async (): Promise<void> => {\n setIsLoading(true);\n try {\n const response = await passflow.getUserPasskeys();\n setData(response as unknown as PassflowUserPasskey[]);\n } catch (e) {\n setIsError(true);\n const error = e as Error;\n setErrorMessage(error.message);\n } finally {\n setIsLoading(false);\n }\n };\n\n void fetch();\n }, [passflow]);\n\n const createUserPasskey = async (\n relyingPartyId: string,\n passkeyUsername?: string,\n passkeyDisplayName?: string,\n ): Promise<void> => {\n setIsLoading(true);\n try {\n await passflow.addUserPasskey({ relyingPartyId, passkeyUsername, passkeyDisplayName });\n } catch (e) {\n setIsError(true);\n const error = e as Error;\n setErrorMessage(error.message);\n } finally {\n setIsLoading(false);\n }\n };\n\n const editUserPasskey = async (newName: string, passkeyId: string): Promise<void> => {\n setIsLoading(true);\n try {\n const editUserPasskeyStatus = await passflow.renameUserPasskey(newName, passkeyId);\n if (editUserPasskeyStatus) {\n const userPasskeys = await passflow.getUserPasskeys();\n setData(userPasskeys as unknown as PassflowUserPasskey[]);\n }\n } catch (e) {\n setIsError(true);\n const error = e as Error;\n setErrorMessage(error.message);\n } finally {\n setIsLoading(false);\n }\n };\n\n const deleteUserPasskey = async (passkeyId: string): Promise<void> => {\n setIsLoading(true);\n try {\n const deleteUserPasskeyStatus = await passflow.deleteUserPasskey(passkeyId);\n if (deleteUserPasskeyStatus) {\n const userPasskeys = await passflow.getUserPasskeys();\n setData(userPasskeys as unknown as PassflowUserPasskey[]);\n }\n } catch (e) {\n setIsError(true);\n const error = e as Error;\n setErrorMessage(error.message);\n } finally {\n setIsLoading(false);\n }\n };\n\n return {\n data,\n createUserPasskey,\n editUserPasskey,\n deleteUserPasskey,\n isLoading,\n isError,\n errorMessage,\n };\n};\n","import { getCountryForTimezone } from 'countries-and-timezones';\nimport {\n type ChangeEvent,\n type FC,\n type InputHTMLAttributes,\n type KeyboardEvent,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { type CountryIso2, defaultCountries, parseCountry, usePhoneInput } from 'react-international-phone';\nimport { useOutsideClick } from '@/hooks';\nimport { cn } from '@/utils';\nimport { Button, CountryFlag, Icon } from '..';\n\nimport '@/styles/index.css';\nimport 'react-international-phone/style.css';\n\ntype TFieldPhone = InputHTMLAttributes<HTMLInputElement> & {\n id: string;\n onChange: (event: ChangeEvent<HTMLInputElement>) => void;\n isError?: boolean;\n className?: string;\n // eslint-disable-next-line react/no-unused-prop-types\n ref?: null;\n};\n\nexport const FieldPhone: FC<TFieldPhone> = ({\n id,\n name,\n onChange,\n isError = false,\n className = '',\n disabled = false,\n ...inputProps\n}) => {\n const [show, setShow] = useState(false);\n const [filterValue, setFilterValue] = useState('');\n const [isFocused, setIsFocused] = useState(false);\n const refWrapper = useRef<HTMLDivElement>(null);\n const searchInputRef = useRef<HTMLInputElement>(null);\n\n useEffect(() => {\n if (show) searchInputRef.current?.focus();\n }, [show]);\n\n useOutsideClick(refWrapper, () => {\n setShow(false);\n setFilterValue('');\n });\n\n const userTZ = Intl.DateTimeFormat().resolvedOptions().timeZone;\n const userCountry = getCountryForTimezone(userTZ);\n const { inputValue, country, setCountry, handlePhoneValueChange, inputRef } = usePhoneInput({\n defaultCountry: userCountry?.id.toLocaleLowerCase() || 'us',\n });\n\n const handlePhoneChange = (event: ChangeEvent<HTMLInputElement>) => {\n handlePhoneValueChange(event);\n onChange(event);\n };\n\n const filteredCountries = useMemo(\n () =>\n defaultCountries.filter((defCountry) => {\n const { name: countryName } = parseCountry(defCountry);\n return countryName.toLowerCase().includes(filterValue.toLowerCase());\n }),\n [filterValue],\n );\n\n const preferredCountries = useMemo(\n () =>\n defaultCountries.filter((defCountry) => {\n const { iso2 } = parseCountry(defCountry);\n return iso2 === userCountry?.id.toLocaleLowerCase();\n }),\n [userCountry?.id],\n );\n\n const allCountries = useMemo(() => {\n if (filterValue) return filteredCountries;\n const preferredIso = new Set(preferredCountries.map((defCountry) => parseCountry(defCountry).iso2));\n return filteredCountries.filter((defCountry) => !preferredIso.has(parseCountry(defCountry).iso2));\n }, [filterValue, filteredCountries, preferredCountries]);\n\n const restoreCountryButtonFocus = () => {\n refWrapper.current?.querySelector<HTMLButtonElement>('.passflow-button-show-country')?.focus();\n };\n\n const handleShow = () => setShow(true);\n\n const handleClose = (restoreFocus = false) => {\n setShow(false);\n setFilterValue('');\n if (restoreFocus) restoreCountryButtonFocus();\n };\n\n const handleChangeCountry = (iso2: CountryIso2) => {\n setCountry(iso2);\n handleClose(true);\n };\n\n const handleOptionKeyDown = (event: KeyboardEvent<HTMLDivElement>, iso2: CountryIso2) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n handleChangeCountry(iso2);\n return;\n }\n\n if (event.key !== 'ArrowDown' && event.key !== 'ArrowUp') return;\n event.preventDefault();\n const options = Array.from(refWrapper.current?.querySelectorAll<HTMLElement>('[role=\"option\"]') ?? []);\n const currentIndex = options.indexOf(event.currentTarget);\n const nextIndex =\n event.key === 'ArrowDown' ? Math.min(currentIndex + 1, options.length - 1) : Math.max(currentIndex - 1, 0);\n options[nextIndex]?.focus();\n };\n\n const renderCountry = (defCountry: (typeof defaultCountries)[number]) => {\n const { name: countryName, dialCode, iso2 } = parseCountry(defCountry);\n return (\n <div\n key={iso2}\n role='option'\n aria-selected={iso2 === country.iso2}\n tabIndex={0}\n title={countryName}\n onClick={() => handleChangeCountry(iso2)}\n onKeyDown={(event) => handleOptionKeyDown(event, iso2)}\n className='passflow-country-search-item'\n >\n <CountryFlag iso2={iso2} className='passflow-country-search-flag' />\n <span className='passflow-country-search-name'>{countryName}</span>\n <span className='passflow-country-search-code'>+{dialCode}</span>\n </div>\n );\n };\n\n return (\n <div\n ref={refWrapper}\n className={cn(\n 'passflow-field-phone-wrapper',\n { 'passflow-field-phone-wrapper--focus': isFocused, 'passflow-field-phone-wrapper--error': isError },\n className,\n )}\n >\n <Button\n type='button'\n variant='clean'\n onClick={() => (show ? handleClose(true) : handleShow())}\n size='big'\n className='passflow-button-show-country'\n disabled={disabled}\n aria-label={`Select country, current ${country.iso2.toUpperCase()}`}\n aria-haspopup='listbox'\n aria-expanded={show}\n aria-controls='passflow-country-options'\n >\n <CountryFlag iso2={country.iso2} />\n <Icon type='general' id='caret-down' size='small' />\n </Button>\n\n {!show ? (\n <input\n {...inputProps}\n id={id}\n name={name}\n ref={inputRef}\n type='tel'\n value={inputValue}\n disabled={disabled}\n aria-invalid={isError}\n onChange={handlePhoneChange}\n onFocus={() => setIsFocused(true)}\n onBlur={() => setIsFocused(false)}\n className='passflow-field-phone-input'\n />\n ) : (\n <div className='passflow-field-country-search-wrapper'>\n <input\n ref={searchInputRef}\n role='combobox'\n aria-label='Search countries'\n aria-expanded='true'\n aria-controls='passflow-country-options'\n aria-autocomplete='list'\n value={filterValue}\n onChange={(event) => setFilterValue(event.target.value)}\n onKeyDown={(event) => {\n if (event.key === 'Escape') handleClose(true);\n if (event.key === 'ArrowDown') {\n event.preventDefault();\n refWrapper.current?.querySelector<HTMLElement>('[role=\"option\"]')?.focus();\n }\n }}\n className='passflow-field-country-search'\n onFocus={() => setIsFocused(true)}\n onBlur={() => setIsFocused(false)}\n placeholder='Search for a country'\n />\n <div className='passflow-field-country-search-icon'>\n <Icon type='general' id='search' size='small' />\n </div>\n </div>\n )}\n\n <div\n id='passflow-country-options'\n role='listbox'\n tabIndex={-1}\n aria-label='Countries'\n aria-hidden={!show}\n className={cn('passflow-country-search-wrapper', {\n 'passflow-country-search-wrapper--show': show,\n 'passflow-country-search-wrapper--hidden': !show,\n 'passflow-country-search-wrapper--without-preferred': !!filterValue || preferredCountries.length === 0,\n })}\n >\n {filteredCountries.length > 0 ? (\n <>\n <div role='presentation' aria-hidden='true' className='passflow-country-search-sticky-top' />\n {!filterValue && preferredCountries.length > 0 ? (\n <>\n {preferredCountries.map(renderCountry)}\n <div role='presentation' className='passflow-country-search-divider'>\n All countries\n </div>\n </>\n ) : null}\n {allCountries.map(renderCountry)}\n <div role='presentation' aria-hidden='true' className='passflow-country-search-sticky-bottom' />\n </>\n ) : (\n <div role='presentation' className='passflow-country-search-no-matches'>\n No matches\n </div>\n )}\n </div>\n </div>\n );\n};\n","/* eslint-disable react/jsx-props-no-spreading */\nimport { forwardRef, type InputHTMLAttributes } from 'react';\nimport '@/styles/index.css';\nimport { cn } from '@/utils';\n\ntype TFieldText = InputHTMLAttributes<HTMLInputElement> & {\n id: string;\n isError?: boolean;\n className?: string;\n disabled?: boolean;\n};\n\nexport const FieldText = forwardRef<HTMLInputElement, TFieldText>(\n ({ id, isError = false, className = '', disabled = false, ...rest }, ref) => {\n const styles = {\n 'passflow-field--error': isError,\n };\n\n return (\n <input\n ref={ref}\n id={id}\n type='text'\n className={cn('passflow-field-input passflow-field--focused', styles, className)}\n disabled={disabled}\n {...rest}\n />\n );\n },\n);\n","export default \"data:image/svg+xml,%3csvg%20width='44'%20height='44'%20viewBox='0%200%2044%2044'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3crect%20width='44'%20height='44'%20rx='6'%20fill='%23F3F5F7'/%3e%3cg%20clip-path='url(%23clip0_2691_4741)'%3e%3cpath%20d='M21.9999%2019.3334C20.5272%2019.3334%2019.3333%2020.5273%2019.3333%2022C19.3333%2023.4728%2020.5272%2024.6667%2021.9999%2024.6667C23.4727%2024.6667%2024.6666%2023.4728%2024.6666%2022C24.6666%2020.5273%2023.4727%2019.3334%2021.9999%2019.3334ZM21.9999%2019.3334H28.1133M16.6333%2018.04L19.6933%2023.3334M21.2533%2028.6267L24.3066%2023.3334M28.6666%2022C28.6666%2025.6819%2025.6818%2028.6667%2021.9999%2028.6667C18.318%2028.6667%2015.3333%2025.6819%2015.3333%2022C15.3333%2018.3181%2018.318%2015.3334%2021.9999%2015.3334C25.6818%2015.3334%2028.6666%2018.3181%2028.6666%2022Z'%20stroke='%237F7F7F'%20stroke-width='1.5'%20stroke-linecap='round'%20stroke-linejoin='round'/%3e%3c/g%3e%3cdefs%3e%3cclipPath%20id='clip0_2691_4741'%3e%3crect%20width='16'%20height='16'%20fill='white'%20transform='translate(14%2014)'/%3e%3c/clipPath%3e%3c/defs%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M4%206L8%2010L12%206H4Z'%20fill='%236B6F76'/%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M4%208L6.82843%2010.8284L12.4847%205.17155'%20stroke='%236B6F76'%20stroke-width='1.5'%20stroke-linecap='round'%20stroke-linejoin='round'/%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M10.6666%2010.6667L7.99993%208.00001M7.99993%208.00001L5.33325%205.33333M7.99993%208.00001L10.6666%205.33333M7.99993%208.00001L5.33325%2010.6667'%20stroke='%236B6F76'%20stroke-width='1.5'%20stroke-linecap='round'%20stroke-linejoin='round'/%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M8.00004%208.66667C8.36823%208.66667%208.66671%208.36819%208.66671%208C8.66671%207.63181%208.36823%207.33333%208.00004%207.33333C7.63185%207.33333%207.33337%207.63181%207.33337%208C7.33337%208.36819%207.63185%208.66667%208.00004%208.66667Z'%20stroke='%236B6F76'%20stroke-width='1.5'%20stroke-linecap='round'%20stroke-linejoin='round'/%3e%3cpath%20d='M8.00004%204C8.36823%204%208.66671%203.70152%208.66671%203.33333C8.66671%202.96514%208.36823%202.66667%208.00004%202.66667C7.63185%202.66667%207.33337%202.96514%207.33337%203.33333C7.33337%203.70152%207.63185%204%208.00004%204Z'%20stroke='%236B6F76'%20stroke-width='1.5'%20stroke-linecap='round'%20stroke-linejoin='round'/%3e%3cpath%20d='M8.00004%2013.3333C8.36823%2013.3333%208.66671%2013.0349%208.66671%2012.6667C8.66671%2012.2985%208.36823%2012%208.00004%2012C7.63185%2012%207.33337%2012.2985%207.33337%2012.6667C7.33337%2013.0349%207.63185%2013.3333%208.00004%2013.3333Z'%20stroke='%236B6F76'%20stroke-width='1.5'%20stroke-linecap='round'%20stroke-linejoin='round'/%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M11.6231%206.86026L9.13975%204.37687M2%2014L4.10117%2013.7665C4.35789%2013.738%204.48624%2013.7238%204.60622%2013.6849C4.71266%2013.6505%204.81395%2013.6018%204.90735%2013.5402C5.01263%2013.4708%205.10395%2013.3794%205.28659%2013.1968L13.4857%204.99772C14.1714%204.31195%2014.1714%203.2001%2013.4857%202.51433C12.7999%201.82856%2011.6881%201.82856%2011.0023%202.51433L2.80321%2010.7134C2.62056%2010.896%202.52924%2010.9874%202.45982%2011.0926C2.39823%2011.186%202.34955%2011.2873%202.31509%2011.3938C2.27625%2011.5138%202.26199%2011.6421%202.23346%2011.8988L2%2014Z'%20stroke='%236B6F76'%20stroke-width='1.5'%20stroke-linecap='round'%20stroke-linejoin='round'/%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M7.16196%203.39488C7.4329%203.35482%207.7124%203.33333%208.00028%203.33333C11.4036%203.33333%2013.6369%206.33656%2014.3871%207.52455C14.4779%207.66833%2014.5233%207.74023%2014.5488%207.85112C14.5678%207.93439%2014.5678%208.06578%2014.5487%208.14905C14.5233%208.25993%2014.4776%208.3323%2014.3861%208.47705C14.1862%208.79343%2013.8814%209.23807%2013.4777%209.7203M4.48288%204.47669C3.0415%205.45447%202.06297%206.81292%201.61407%207.52352C1.52286%207.66791%201.47725%207.74011%201.45183%207.85099C1.43273%207.93426%201.43272%208.06563%201.45181%208.14891C1.47722%208.25979%201.52262%208.33168%201.61342%208.47545C2.36369%209.66344%204.59694%2012.6667%208.00028%2012.6667C9.37255%2012.6667%2010.5546%2012.1784%2011.5259%2011.5177M2.00028%202L14.0003%2014M6.58606%206.58579C6.22413%206.94772%206.00028%207.44772%206.00028%208C6.00028%209.10457%206.89571%2010%208.00028%2010C8.55256%2010%209.05256%209.77614%209.41449%209.41421'%20stroke='%236B6F76'%20stroke-width='1.5'%20stroke-linecap='round'%20stroke-linejoin='round'/%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M1.61342%208.47545C1.52262%208.33169%201.47723%208.25981%201.45182%208.14895C1.43273%208.06567%201.43273%207.93434%201.45182%207.85106C1.47723%207.74019%201.52262%207.66831%201.61341%207.52455C2.36369%206.33656%204.59693%203.33334%208.00027%203.33334C11.4036%203.33334%2013.6369%206.33656%2014.3871%207.52455C14.4779%207.66831%2014.5233%207.74019%2014.5487%207.85106C14.5678%207.93434%2014.5678%208.06567%2014.5487%208.14895C14.5233%208.25981%2014.4779%208.33169%2014.3871%208.47545C13.6369%209.66344%2011.4036%2012.6667%208.00027%2012.6667C4.59693%2012.6667%202.36369%209.66344%201.61342%208.47545Z'%20stroke='%236B6F76'%20stroke-width='1.5'%20stroke-linecap='round'%20stroke-linejoin='round'/%3e%3cpath%20d='M8.00027%2010C9.10484%2010%2010.0003%209.10457%2010.0003%208C10.0003%206.89543%209.10484%206%208.00027%206C6.8957%206%206.00027%206.89543%206.00027%208C6.00027%209.10457%206.8957%2010%208.00027%2010Z'%20stroke='%236B6F76'%20stroke-width='1.5'%20stroke-linecap='round'%20stroke-linejoin='round'/%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M11.1111%206.1333C11.1111%205.81483%2010.9896%205.49636%2010.7466%205.25338C10.5037%205.01039%2010.1852%204.88889%209.86669%204.88889M9.86669%209.86667C11.9286%209.86667%2013.6%208.1952%2013.6%206.13333C13.6%204.07147%2011.9286%202.4%209.86669%202.4C7.80483%202.4%206.13336%204.07147%206.13336%206.13333C6.13336%206.30362%206.14476%206.47125%206.16684%206.63549C6.20316%206.90562%206.22131%207.04069%206.20909%207.12615C6.19636%207.21516%206.18015%207.26313%206.13627%207.34163C6.09416%207.41698%206.01993%207.4912%205.87148%207.63965L2.69162%2010.8195C2.584%2010.9271%202.53019%2010.9809%202.49171%2011.0437C2.4576%2011.0994%202.43246%2011.1601%202.41722%2011.2236C2.40002%2011.2952%202.40002%2011.3713%202.40002%2011.5235V12.6044C2.40002%2012.9529%202.40002%2013.1272%202.46784%2013.2603C2.5275%2013.3773%202.62269%2013.4725%202.73976%2013.5322C2.87286%2013.6%203.0471%2013.6%203.39558%2013.6H4.88891V12.3556H6.13336V11.1111H7.3778L8.36037%2010.1285C8.50882%209.98009%208.58305%209.90587%208.6584%209.86375C8.73689%209.81988%208.78486%209.80367%208.87388%209.79093C8.95933%209.77871%209.0944%209.79687%209.36453%209.83319C9.52878%209.85527%209.6964%209.86667%209.86669%209.86667Z'%20stroke='%236B6F76'%20stroke-width='1.5'%20stroke-linecap='round'%20stroke-linejoin='round'/%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='43'%20height='10'%20viewBox='0%200%2043%2010'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M8.91%209H5.346L5.236%207.988H3.674L3.564%209H0L2.178%200.53H6.732L8.91%209ZM4.158%203.665L4.037%204.721H4.873L4.752%203.665H4.158ZM16.6389%206.712C16.5215%207.482%2016.1145%208.087%2015.4179%208.527C14.7212%208.95967%2013.8082%209.176%2012.6789%209.176C11.5495%209.176%2010.6365%208.95967%209.93988%208.527C9.25054%208.09433%208.84354%207.49667%208.71888%206.734C8.68954%206.52867%208.66388%206.25367%208.64188%205.909C8.62721%205.557%208.61988%205.17933%208.61988%204.776C8.61988%204.38733%208.62721%204.028%208.64188%203.698C8.66388%203.36067%208.68954%203.09667%208.71888%202.906C8.84354%202.09933%209.25421%201.47233%209.95088%201.025C10.6475%200.577666%2011.5569%200.354%2012.6789%200.354C13.8082%200.354%2014.7212%200.577666%2015.4179%201.025C16.1145%201.465%2016.5215%202.07733%2016.6389%202.862C16.6682%203.05267%2016.6902%203.31667%2016.7049%203.654C16.7269%203.984%2016.7379%204.347%2016.7379%204.743C16.7379%205.161%2016.7269%205.54233%2016.7049%205.887C16.6902%206.23167%2016.6682%206.50667%2016.6389%206.712ZM12.9759%206.206V3.324C12.9759%203.126%2012.8769%203.027%2012.6789%203.027C12.4809%203.027%2012.3819%203.126%2012.3819%203.324V6.206C12.3819%206.404%2012.4809%206.503%2012.6789%206.503C12.8769%206.503%2012.9759%206.404%2012.9759%206.206ZM25.1574%206.712C25.0401%207.482%2024.6331%208.087%2023.9364%208.527C23.2398%208.95967%2022.3268%209.176%2021.1974%209.176C20.0681%209.176%2019.1551%208.95967%2018.4584%208.527C17.7691%208.09433%2017.3621%207.49667%2017.2374%206.734C17.2081%206.52867%2017.1824%206.25367%2017.1604%205.909C17.1458%205.557%2017.1384%205.17933%2017.1384%204.776C17.1384%204.38733%2017.1458%204.028%2017.1604%203.698C17.1824%203.36067%2017.2081%203.09667%2017.2374%202.906C17.3621%202.09933%2017.7728%201.47233%2018.4694%201.025C19.1661%200.577666%2020.0754%200.354%2021.1974%200.354C22.3268%200.354%2023.2398%200.577666%2023.9364%201.025C24.6331%201.465%2025.0401%202.07733%2025.1574%202.862C25.1868%203.05267%2025.2088%203.31667%2025.2234%203.654C25.2454%203.984%2025.2564%204.347%2025.2564%204.743C25.2564%205.161%2025.2454%205.54233%2025.2234%205.887C25.2088%206.23167%2025.1868%206.50667%2025.1574%206.712ZM21.4944%206.206V3.324C21.4944%203.126%2021.3954%203.027%2021.1974%203.027C20.9994%203.027%2020.9004%203.126%2020.9004%203.324V6.206C20.9004%206.404%2020.9994%206.503%2021.1974%206.503C21.3954%206.503%2021.4944%206.404%2021.4944%206.206ZM33.555%200.53V3.797H31.432V9H27.769V3.797H25.635V0.53H33.555ZM38.4495%202.906V0.53H42.0135V9H38.4495V6.272H37.5585V9H33.9945V0.53H37.5585V2.906H38.4495Z'%20fill='%236B6F76'/%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='44'%20height='44'%20viewBox='0%200%2044%2044'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3crect%20width='44'%20height='44'%20rx='8'%20fill='%231E1E1E'%20/%3e%3cpath%20d='M21.2532%2031H13.6932V12.52H24.9012C25.9252%2012.52%2026.8612%2012.72%2027.7092%2013.12C28.5732%2013.504%2029.2612%2014.184%2029.7732%2015.16C30.2852%2016.12%2030.5412%2017.456%2030.5412%2019.168C30.5412%2020.848%2030.2772%2022.184%2029.7492%2023.176C29.2212%2024.152%2028.5252%2024.856%2027.6612%2025.288C26.8132%2025.704%2025.8932%2025.912%2024.9012%2025.912H21.2532V31ZM23.1252%2018.592H20.8212V19.888H23.1972C23.3252%2019.888%2023.4612%2019.848%2023.6052%2019.768C23.7652%2019.688%2023.8452%2019.52%2023.8452%2019.264C23.8452%2018.992%2023.7572%2018.816%2023.5812%2018.736C23.4052%2018.64%2023.2532%2018.592%2023.1252%2018.592Z'%20fill='white'%20/%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='44'%20height='44'%20viewBox='0%200%2044%2044'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3crect%20width='44'%20height='44'%20rx='8'%20fill='%23D85D5D'%20/%3e%3cpath%20d='M21.2532%2031H13.6932V12.52H24.9012C25.9252%2012.52%2026.8612%2012.72%2027.7092%2013.12C28.5732%2013.504%2029.2612%2014.184%2029.7732%2015.16C30.2852%2016.12%2030.5412%2017.456%2030.5412%2019.168C30.5412%2020.848%2030.2772%2022.184%2029.7492%2023.176C29.2212%2024.152%2028.5252%2024.856%2027.6612%2025.288C26.8132%2025.704%2025.8932%2025.912%2024.9012%2025.912H21.2532V31ZM23.1252%2018.592H20.8212V19.888H23.1972C23.3252%2019.888%2023.4612%2019.848%2023.6052%2019.768C23.7652%2019.688%2023.8452%2019.52%2023.8452%2019.264C23.8452%2018.992%2023.7572%2018.816%2023.5812%2018.736C23.4052%2018.64%2023.2532%2018.592%2023.1252%2018.592Z'%20fill='white'%20/%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M1.33337%204.66666L6.77665%208.47696C7.21743%208.78551%207.43783%208.93978%207.67755%208.99954C7.8893%209.05232%208.11078%209.05232%208.32253%208.99954C8.56226%208.93978%208.78265%208.78551%209.22343%208.47696L14.6667%204.66666M4.53337%2013.3333H11.4667C12.5868%2013.3333%2013.1469%2013.3333%2013.5747%2013.1153C13.951%2012.9236%2014.257%2012.6176%2014.4487%2012.2413C14.6667%2011.8135%2014.6667%2011.2534%2014.6667%2010.1333V5.86666C14.6667%204.74656%2014.6667%204.18651%2014.4487%203.75868C14.257%203.38236%2013.951%203.0764%2013.5747%202.88465C13.1469%202.66666%2012.5868%202.66666%2011.4667%202.66666H4.53337C3.41327%202.66666%202.85322%202.66666%202.42539%202.88465C2.04907%203.0764%201.74311%203.38236%201.55136%203.75868C1.33337%204.18651%201.33337%204.74656%201.33337%205.86666V10.1333C1.33337%2011.2534%201.33337%2011.8135%201.55136%2012.2413C1.74311%2012.6176%202.04907%2012.9236%202.42539%2013.1153C2.85322%2013.3333%203.41327%2013.3333%204.53337%2013.3333Z'%20stroke='%236B6F76'%20stroke-width='1.5'%20stroke-linecap='round'%20stroke-linejoin='round'/%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='44'%20height='44'%20viewBox='0%200%2044%2044'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3crect%20width='44'%20height='44'%20rx='6'%20fill='%23F3F5F7'/%3e%3cg%20clip-path='url(%23clip0_2691_4730)'%3e%3cpath%20d='M20.8039%2020.4084V18.2344C20.8039%2017.9893%2021.0026%2017.7906%2021.2477%2017.7906H22.7785C23.0236%2017.7906%2023.2222%2017.9893%2023.2222%2018.2344V22.2139C23.2222%2022.2748%2023.1918%2022.3212%2023.1614%2022.3669L22.7785%2022.7498C22.6864%2022.8419%2022.6864%2022.9797%2022.7785%2023.0558L23.1614%2023.4386C23.1819%2023.4582%2023.198%2023.4821%2023.2086%2023.5085C23.2191%2023.5349%2023.2237%2023.5633%2023.2222%2023.5916V25.7648C23.2222%2025.8825%2023.1755%2025.9954%2023.0923%2026.0786C23.009%2026.1618%2022.8962%2026.2086%2022.7785%2026.2086H21.2477C21.13%2026.2086%2021.0171%2026.1618%2020.9339%2026.0786C20.8507%2025.9954%2020.8039%2025.8825%2020.8039%2025.7648V21.7853C20.8039%2021.7244%2020.8344%2021.678%2020.8648%2021.6323L21.2477%2021.2494C21.3398%2021.1573%2021.3398%2021.0195%2021.2477%2020.9434L20.8648%2020.5606C20.8443%2020.5411%2020.8282%2020.5174%2020.8177%2020.4911C20.8072%2020.4649%2020.8025%2020.4366%2020.8039%2020.4084ZM27.7064%2022C27.7064%2021.2503%2027.5587%2020.5079%2027.2718%2019.8153C26.9849%2019.1227%2026.5644%2018.4933%2026.0343%2017.9632C25.5042%2017.4331%2024.8748%2017.0126%2024.1822%2016.7257C23.4895%2016.4388%2022.7472%2016.2911%2021.9975%2016.2911C21.2478%2016.2911%2020.5054%2016.4388%2019.8128%2016.7257C19.1201%2017.0126%2018.4908%2017.4331%2017.9607%2017.9632C17.4305%2018.4933%2017.01%2019.1227%2016.7231%2019.8153C16.4362%2020.5079%2016.2886%2021.2503%2016.2886%2022C16.2886%2023.5141%2016.89%2024.9662%2017.9607%2026.0368C19.0313%2027.1074%2020.4834%2027.7089%2021.9975%2027.7089C23.5116%2027.7089%2024.9637%2027.1074%2026.0343%2026.0368C27.1049%2024.9662%2027.7064%2023.5141%2027.7064%2022ZM29.5127%2022C29.5127%2026.1477%2026.1452%2029.5%2022.0127%2029.5C17.865%2029.5%2014.5127%2026.1325%2014.5127%2022C14.5127%2017.8523%2017.8802%2014.5%2022.0127%2014.5C26.1452%2014.5%2029.5127%2017.8523%2029.5127%2022Z'%20fill='%237F7F7F'/%3e%3c/g%3e%3cdefs%3e%3cclipPath%20id='clip0_2691_4730'%3e%3crect%20width='16'%20height='16'%20fill='white'%20transform='translate(14%2014)'/%3e%3c/clipPath%3e%3c/defs%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='44'%20height='44'%20viewBox='0%200%2044%2044'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3crect%20width='44'%20height='44'%20rx='6'%20fill='%23F3F5F7'/%3e%3cpath%20d='M25.3333%2020C25.3333%2019.6587%2025.2031%2019.3175%2024.9428%2019.0572C24.6825%2018.7968%2024.3412%2018.6667%2024%2018.6667M24%2024C26.2091%2024%2028%2022.2091%2028%2020C28%2017.7909%2026.2091%2016%2024%2016C21.7909%2016%2020%2017.7909%2020%2020C20%2020.1825%2020.0122%2020.3621%2020.0359%2020.538C20.0748%2020.8275%2020.0942%2020.9722%2020.0811%2021.0637C20.0675%2021.1591%2020.0501%2021.2105%2020.0031%2021.2946C19.958%2021.3753%2019.8785%2021.4549%2019.7194%2021.6139L16.3124%2025.0209C16.1971%2025.1362%2016.1395%2025.1939%2016.0982%2025.2611C16.0617%2025.3208%2016.0348%2025.3858%2016.0184%2025.4538C16%2025.5306%2016%2025.6121%2016%2025.7752V26.9333C16%2027.3067%2016%2027.4934%2016.0727%2027.636C16.1366%2027.7614%2016.2386%2027.8634%2016.364%2027.9273C16.5066%2028%2016.6933%2028%2017.0667%2028H18.6667V26.6667H20V25.3333H21.3333L22.3861%2024.2806C22.5451%2024.1215%2022.6247%2024.042%2022.7054%2023.9969C22.7895%2023.9499%2022.8409%2023.9325%2022.9363%2023.9189C23.0278%2023.9058%2023.1725%2023.9252%2023.462%2023.9641C23.6379%2023.9878%2023.8175%2024%2024%2024Z'%20stroke='%237F7F7F'%20stroke-width='1.5'%20stroke-linecap='round'%20stroke-linejoin='round'/%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='17'%20height='16'%20viewBox='0%200%2017%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M8.49998%2011.6666H8.50665M5.96665%2014.6666H11.0333C11.78%2014.6666%2012.1534%2014.6666%2012.4386%2014.5213C12.6895%2014.3934%2012.8935%2014.1895%2013.0213%2013.9386C13.1666%2013.6534%2013.1666%2013.28%2013.1666%2012.5333V3.46659C13.1666%202.71985%2013.1666%202.34648%2013.0213%202.06126C12.8935%201.81038%2012.6895%201.60641%2012.4386%201.47858C12.1534%201.33325%2011.78%201.33325%2011.0333%201.33325H5.96665C5.21991%201.33325%204.84654%201.33325%204.56133%201.47858C4.31044%201.60641%204.10647%201.81038%203.97864%202.06126C3.83331%202.34648%203.83331%202.71985%203.83331%203.46659V12.5333C3.83331%2013.28%203.83331%2013.6534%203.97864%2013.9386C4.10647%2014.1895%204.31044%2014.3934%204.56133%2014.5213C4.84654%2014.6666%205.21991%2014.6666%205.96665%2014.6666ZM8.83331%2011.6666C8.83331%2011.8507%208.68407%2011.9999%208.49998%2011.9999C8.31588%2011.9999%208.16665%2011.8507%208.16665%2011.6666C8.16665%2011.4825%208.31588%2011.3333%208.49998%2011.3333C8.68407%2011.3333%208.83331%2011.4825%208.83331%2011.6666Z'%20stroke='%237F7F7F'%20stroke-width='1.5'%20stroke-linecap='round'%20stroke-linejoin='round'/%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M14%2014L11.1%2011.1M12.6667%207.33333C12.6667%2010.2789%2010.2789%2012.6667%207.33333%2012.6667C4.38781%2012.6667%202%2010.2789%202%207.33333C2%204.38781%204.38781%202%207.33333%202C10.2789%202%2012.6667%204.38781%2012.6667%207.33333Z'%20stroke='%236B6F76'%20stroke-width='1.5'%20stroke-linecap='round'%20stroke-linejoin='round'/%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M6%202H10M2%204H14M12.6667%204L12.1991%2011.0129C12.129%2012.065%2012.0939%2012.5911%2011.8667%2012.99C11.6666%2013.3412%2011.3648%2013.6235%2011.0011%2013.7998C10.588%2014%2010.0607%2014%209.00623%2014H6.99377C5.93927%2014%205.41202%2014%204.99889%2013.7998C4.63517%2013.6235%204.33339%2013.3412%204.13332%2012.99C3.90607%2012.5911%203.871%2012.065%203.80086%2011.0129L3.33333%204M6.66667%207V10.3333M9.33333%207V10.3333'%20stroke='%236B6F76'%20stroke-width='1.5'%20stroke-linecap='round'%20stroke-linejoin='round'/%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cg%20clip-path='url(%23clip0_2502_823)'%3e%3cpath%20d='M7.99992%205.33334V8M7.99992%2010.6667H8.00659M14.6666%208C14.6666%2011.6819%2011.6818%2014.6667%207.99992%2014.6667C4.31802%2014.6667%201.33325%2011.6819%201.33325%208C1.33325%204.3181%204.31802%201.33334%207.99992%201.33334C11.6818%201.33334%2014.6666%204.3181%2014.6666%208Z'%20stroke='%236B6F76'%20stroke-width='1.5'%20stroke-linecap='round'%20stroke-linejoin='round'/%3e%3c/g%3e%3cdefs%3e%3cclipPath%20id='clip0_2502_823'%3e%3crect%20width='16'%20height='16'%20fill='white'/%3e%3c/clipPath%3e%3c/defs%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M13.6167%204.77308C13.5312%204.83608%2012.0218%205.64397%2012.0218%207.44037C12.0218%209.51818%2013.9425%2010.2533%2014%2010.2715C13.9912%2010.3162%2013.6948%2011.2781%2012.9873%2012.2583C12.3564%2013.1207%2011.6976%2013.9818%2010.6952%2013.9818C9.69291%2013.9818%209.43498%2013.4287%208.27784%2013.4287C7.15021%2013.4287%206.74928%2014%205.83245%2014C4.9156%2014%204.27588%2013.2019%203.54034%2012.2218C2.68836%2011.0709%202%209.28291%202%207.58597C2%204.86409%203.86316%203.42054%205.69684%203.42054C6.67116%203.42054%207.48335%204.02821%208.09508%204.02821C8.67726%204.02821%209.58531%203.38414%2010.6937%203.38414C11.1139%203.38414%2012.6233%203.42054%2013.6167%204.77308ZM10.1676%202.23182C10.6259%201.71517%2010.9503%200.998298%2010.9503%200.281428C10.9503%200.182018%2010.9414%200.0812084%2010.9223%200C10.1764%200.0266027%209.28899%200.471848%208.75398%201.0613C8.33385%201.51495%207.94176%202.23182%207.94176%202.95849C7.94176%203.06771%207.96092%203.17691%207.9698%203.21192C8.01697%203.22032%208.09361%203.23012%208.17025%203.23012C8.83946%203.23012%209.68112%202.80448%2010.1676%202.23182Z'%20fill='black'/%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M5.14981%207.46537C4.94085%207.24181%204.61205%207.2541%204.47223%207.54219L1.03899%2014.4048C1.00767%2014.4674%200.992879%2014.5369%200.996019%2014.6068C0.999159%2014.6768%201.02013%2014.7447%201.05693%2014.8042C1.09373%2014.8637%201.14514%2014.9128%201.20627%2014.9469C1.26741%2014.9809%201.33623%2014.9987%201.4062%2014.9987H6.18693C6.26393%2015.0002%206.33969%2014.9792%206.40492%2014.9382C6.47014%2014.8973%206.52201%2014.8382%206.55414%2014.7682C7.58512%2012.641%206.96054%209.39978%205.14981%207.46537Z'%20fill='url(%23paint0_linear_2502_832)'/%3e%3cpath%20d='M7.66883%201.22039C5.74824%204.2626%205.875%207.63208%207.14029%2010.1611L9.44499%2014.7705C9.47857%2014.8394%209.53076%2014.8975%209.59567%2014.9382C9.66057%2014.979%209.73558%2015.0007%209.81221%2015.001H14.5929C14.6629%2015.001%2014.7317%2014.9832%2014.7929%2014.9492C14.854%2014.9151%2014.9054%2014.866%2014.9422%2014.8065C14.979%2014.747%2015%2014.6791%2015.0031%2014.6092C15.0063%2014.5393%2014.9915%2014.4697%2014.9601%2014.4071C14.9601%2014.4071%208.52849%201.53844%208.37023%201.21808C8.22196%200.929997%207.85474%200.923851%207.66883%201.22039Z'%20fill='%232681FF'/%3e%3cdefs%3e%3clinearGradient%20id='paint0_linear_2502_832'%20x1='7.03199'%20y1='8.52553'%20x2='3.40822'%20y2='14.802'%20gradientUnits='userSpaceOnUse'%3e%3cstop%20stop-color='%230052CC'/%3e%3cstop%20offset='0.92'%20stop-color='%232684FF'/%3e%3c/linearGradient%3e%3c/defs%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cg%20clip-path='url(%23clip0_2502_831)'%3e%3cpath%20d='M0.519254%200.768994C0.44444%200.768029%200.370321%200.783452%200.302102%200.814182C0.233882%200.84491%200.173216%200.890198%200.124362%200.94687C0.0755086%201.00354%200.0396522%201.07021%200.0193102%201.14222C-0.00103186%201.21422%20-0.00536625%201.28981%200.00661131%201.36366L2.18278%2014.5745C2.2099%2014.7362%202.2931%2014.883%202.41779%2014.9894C2.54249%2015.0959%202.70068%2015.155%202.8646%2015.1563H13.3046C13.4274%2015.1579%2013.5468%2015.1153%2013.6409%2015.0362C13.735%2014.9572%2013.7976%2014.847%2013.8172%2014.7257L15.9934%201.36622C16.0054%201.29237%2016.001%201.21678%2015.9807%201.14478C15.9603%201.07278%2015.9245%201.0061%2015.8756%200.94943C15.8268%200.892766%2015.7661%200.84747%2015.6979%200.816742C15.6297%200.786016%2015.5556%200.770592%2015.4807%200.771557L0.519254%200.768994ZM9.68272%2010.317H6.35057L5.44832%205.60322H10.4902L9.68272%2010.317Z'%20fill='%232684FF'/%3e%3cpath%20d='M15.3013%205.60321H10.4902L9.68272%2010.3169H6.35055L2.41602%2014.9871C2.54072%2015.0949%202.69972%2015.1549%202.86458%2015.1563H13.3071C13.43%2015.1579%2013.5494%2015.1153%2013.6434%2015.0362C13.7375%2014.9572%2013.8001%2014.847%2013.8198%2014.7257L15.3013%205.60321Z'%20fill='url(%23paint0_linear_2502_831)'/%3e%3c/g%3e%3cdefs%3e%3clinearGradient%20id='paint0_linear_2502_831'%20x1='16.4138'%20y1='6.92327'%20x2='8.46264'%20y2='13.1288'%20gradientUnits='userSpaceOnUse'%3e%3cstop%20offset='0.18'%20stop-color='%230052CC'/%3e%3cstop%20offset='1'%20stop-color='%232684FF'/%3e%3c/linearGradient%3e%3cclipPath%20id='clip0_2502_831'%3e%3crect%20width='16'%20height='16'%20fill='white'/%3e%3c/clipPath%3e%3c/defs%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cg%20clip-path='url(%23clip0_2502_836)'%3e%3cpath%20d='M13.5535%202.79193C12.5178%202.30734%2011.4104%201.95517%2010.2526%201.75464C10.1104%202.01171%209.94432%202.35748%209.82976%202.63254C8.59904%202.44745%207.37956%202.44745%206.17144%202.63254C6.05693%202.35748%205.88704%202.01171%205.74358%201.75464C4.58454%201.95517%203.47584%202.30864%202.44013%202.79449C0.351095%205.95129%20-0.215207%209.02968%200.0679444%2012.0644C1.4535%2013.099%202.79627%2013.7276%204.11638%2014.139C4.44233%2013.6903%204.73302%2013.2134%204.98345%2012.7109C4.5065%2012.5297%204.04969%2012.306%203.61805%2012.0464C3.73256%2011.9615%203.84457%2011.8729%203.95278%2011.7816C6.58546%2013.013%209.44592%2013.013%2012.0471%2011.7816C12.1566%2011.8729%2012.2686%2011.9615%2012.3819%2012.0464C11.949%2012.3073%2011.491%2012.531%2011.014%2012.7122C11.2644%2013.2134%2011.5538%2013.6916%2011.881%2014.1402C13.2024%2013.7289%2014.5464%2013.1004%2015.932%2012.0644C16.2642%208.5464%2015.3645%205.49628%2013.5535%202.79193ZM5.34212%2010.1981C4.55182%2010.1981%203.9037%209.46024%203.9037%208.56184C3.9037%207.66337%204.53798%206.92429%205.34212%206.92429C6.14628%206.92429%206.79438%207.66207%206.78054%208.56184C6.78178%209.46024%206.14628%2010.1981%205.34212%2010.1981ZM10.6578%2010.1981C9.86752%2010.1981%209.21944%209.46024%209.21944%208.56184C9.21944%207.66337%209.85368%206.92429%2010.6578%206.92429C11.462%206.92429%2012.1101%207.66207%2012.0962%208.56184C12.0962%209.46024%2011.462%2010.1981%2010.6578%2010.1981Z'%20fill='%235865F2'/%3e%3c/g%3e%3cdefs%3e%3cclipPath%20id='clip0_2502_836'%3e%3crect%20width='16'%20height='16'%20fill='white'/%3e%3c/clipPath%3e%3c/defs%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M8.01032%204.15504L4.00518%206.71006L8.01032%209.26513L4.00518%2011.8201L0%209.25129L4.00518%206.69625L0%204.15504L4.00518%201.60001L8.01032%204.15504ZM3.98446%2012.6418L7.98964%2010.0868L11.9948%2012.6418L7.98964%2015.1969L3.98446%2012.6418ZM8.01032%209.25129L12.0155%206.69625L8.01032%204.15504L11.9948%201.60001L16%204.15504L11.9948%206.71006L16%209.26513L11.9948%2011.8201L8.01032%209.25129Z'%20fill='%230061FF'/%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M8%2015C11.866%2015%2015%2011.866%2015%207.99997C15%204.13401%2011.866%201%208%201C4.134%201%201%204.13401%201%207.99997C1%2011.866%204.134%2015%208%2015Z'%20fill='%231977F3'/%3e%3cpath%20d='M10.6065%2010.1416L10.9172%208.16548H8.97241V6.88336C8.97241%206.34321%209.24363%205.81556%2010.1154%205.81556H11V4.1336C11%204.1336%2010.1973%204%209.43%204C7.82844%204%206.78107%204.94574%206.78107%206.65942V8.16548H5V10.1416H6.78107V14.9174C7.13809%2014.9721%207.50398%2015%207.87671%2015C8.24951%2015%208.6154%2014.9712%208.97241%2014.9174V10.1416H10.6065Z'%20fill='white'/%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20fill-rule='evenodd'%20clip-rule='evenodd'%20d='M7.97914%201C4.11986%201%201%204.20833%201%208.17748C1%2011.3502%202.999%2014.0359%205.77214%2014.9864C6.11886%2015.0579%206.24586%2014.832%206.24586%2014.642C6.24586%2014.4756%206.23443%2013.9052%206.23443%2013.311C4.293%2013.7388%203.88871%2012.4554%203.88871%2012.4554C3.57671%2011.6235%203.11443%2011.4097%203.11443%2011.4097C2.479%2010.97%203.16071%2010.97%203.16071%2010.97C3.86557%2011.0176%204.23543%2011.7068%204.23543%2011.7068C4.85929%2012.8%205.86457%2012.4911%206.269%2012.3009C6.32671%2011.8375%206.51171%2011.5166%206.70814%2011.3384C5.15971%2011.172%203.53057%2010.5541%203.53057%207.79715C3.53057%207.01285%203.80771%206.37119%204.24686%205.87215C4.17757%205.69394%203.93486%204.95704%204.31629%203.97077C4.31629%203.97077%204.90557%203.7806%206.23429%204.70752C6.80316%204.55041%207.38982%204.47049%207.97914%204.46981C8.56843%204.46981%209.16914%204.55308%209.72386%204.70752C11.0527%203.7806%2011.642%203.97077%2011.642%203.97077C12.0234%204.95704%2011.7806%205.69394%2011.7113%205.87215C12.162%206.37119%2012.4277%207.01285%2012.4277%207.79715C12.4277%2010.5541%2010.7986%2011.1601%209.23857%2011.3384C9.49286%2011.5642%209.71229%2011.9919%209.71229%2012.6693C9.71229%2013.6318%209.70086%2014.4043%209.70086%2014.6418C9.70086%2014.832%209.828%2015.0579%2010.1746%2014.9866C12.9477%2014.0358%2014.9467%2011.3502%2014.9467%208.17748C14.9581%204.20833%2011.8269%201%207.97914%201Z'%20fill='%2324292F'/%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cg%20clip-path='url(%23clip0_2502_834)'%3e%3cpath%20d='M7.99957%2015.3683L10.9471%206.30157H5.05627L7.99957%2015.3683Z'%20fill='%23E24329'/%3e%3cpath%20d='M0.92752%206.30157L0.0299048%209.05617C-0.0513217%209.30625%200.0363974%209.58242%200.25079%209.73834L7.99948%2015.3683L0.92752%206.30157Z'%20fill='%23FCA326'/%3e%3cpath%20d='M0.92749%206.30164H5.05611L3.27927%200.841173C3.18833%200.561813%202.792%200.561813%202.69779%200.841173L0.92749%206.30164Z'%20fill='%23E24329'/%3e%3cpath%20d='M15.0757%206.30157L15.9701%209.05617C16.0513%209.30625%2015.9636%209.58242%2015.7492%209.73834L7.99939%2015.3683L15.0757%206.30157Z'%20fill='%23FCA326'/%3e%3cpath%20d='M15.0757%206.30164H10.947L12.7206%200.841173C12.8116%200.561813%2013.2079%200.561813%2013.3021%200.841173L15.0757%206.30164Z'%20fill='%23E24329'/%3e%3cpath%20d='M7.99939%2015.3683L10.947%206.30157H15.0757L7.99939%2015.3683Z'%20fill='%23FC6D26'/%3e%3cpath%20d='M7.9994%2015.3683L0.92749%206.30157H5.05611L7.9994%2015.3683Z'%20fill='%23FC6D26'/%3e%3c/g%3e%3cdefs%3e%3cclipPath%20id='clip0_2502_834'%3e%3crect%20width='16'%20height='16'%20fill='white'/%3e%3c/clipPath%3e%3c/defs%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20fill-rule='evenodd'%20clip-rule='evenodd'%20d='M14.7%208.15554C14.7%207.57997%2014.6533%207.15997%2014.5523%206.72443H7.97998V9.32218H11.8377C11.76%209.96777%2011.34%2010.94%2010.4066%2011.5933L10.3936%2011.6803L12.4716%2013.2901L12.6155%2013.3045C13.9378%2012.0834%2014.7%2010.2867%2014.7%208.15554Z'%20fill='%234285F4'/%3e%3cpath%20fill-rule='evenodd'%20clip-rule='evenodd'%20d='M7.98022%2015C9.87019%2015%2011.4568%2014.3778%2012.6158%2013.3045L10.4069%2011.5933C9.81576%2012.0055%209.02242%2012.2933%207.98022%2012.2933C6.12911%2012.2933%204.558%2011.0722%203.99793%209.38446L3.91586%209.39143L1.75507%2011.0637L1.72681%2011.1422C2.87791%2013.4289%205.2424%2015%207.98022%2015Z'%20fill='%2334A853'/%3e%3cpath%20fill-rule='evenodd'%20clip-rule='evenodd'%20d='M3.9977%209.38448C3.84994%208.94893%203.76439%208.48223%203.76439%208.00002C3.76439%207.51778%203.8499%207.05111%203.98993%206.61557L3.98602%206.52279L1.79819%204.82367L1.72662%204.85773C1.25218%205.80664%200.97998%206.87219%200.97998%207.99998C0.97998%209.12777%201.25223%2010.1933%201.72662%2011.1422L3.99774%209.38443'%20fill='%23FBBC04'/%3e%3cpath%20fill-rule='evenodd'%20clip-rule='evenodd'%20d='M7.98022%203.70662C9.29466%203.70662%2010.1813%204.27442%2010.6869%204.7489L12.6625%202.82C11.4492%201.69221%209.87019%201%207.98022%201C5.2424%201%202.87795%202.5711%201.72681%204.85776L3.99016%206.6156C4.558%204.92782%206.12911%203.70666%207.98022%203.70666'%20fill='%23EA4335'/%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M11.013%205.51301V3.9479C11.4349%203.74999%2011.7057%203.32811%2011.7083%202.86197V2.82551C11.7083%202.15884%2011.1667%201.61978%2010.5026%201.61978H10.4661C9.79948%201.61978%209.26042%202.15884%209.26042%202.82551V2.86197C9.26302%203.32811%209.53385%203.74999%209.95573%203.9479V5.51301C9.35937%205.60415%208.79948%205.85155%208.33073%206.22915L4.03646%202.8828C4.06771%202.77343%204.08333%202.65884%204.08594%202.54426C4.08594%201.79426%203.47917%201.18488%202.72917%201.18488C1.97917%201.18228%201.36979%201.78905%201.36719%202.53905C1.36719%203.29165%201.97396%203.90103%202.72396%203.90103C2.96094%203.90103%203.1901%203.83593%203.39323%203.71874L7.6224%207.0104C6.84635%208.18488%206.86719%209.71353%207.67448%2010.8672L6.38802%2012.1536C6.28646%2012.1198%206.17708%2012.1042%206.06771%2012.1016C5.45313%2012.1016%204.95313%2012.6016%204.95313%2013.2187C4.95313%2013.8333%205.45313%2014.3333%206.06771%2014.3333C6.6849%2014.3333%207.1849%2013.8333%207.1849%2013.2187C7.18229%2013.1094%207.16406%2013%207.13281%2012.8958L8.40365%2011.625C9.54167%2012.5%2011.1016%2012.5755%2012.3177%2011.8125C13.5339%2011.0521%2014.1484%209.61457%2013.8568%208.20832C13.5651%206.80468%2012.4297%205.72915%2011.013%205.51301ZM10.4844%2010.6641C9.84375%2010.6797%209.24479%2010.3489%208.92187%209.79686C8.59635%209.24478%208.59635%208.56249%208.92187%208.0104C9.24479%207.45832%209.84375%207.12759%2010.4844%207.14322C11.4323%207.17707%2012.1823%207.95572%2012.1823%208.90363C12.1849%209.84895%2011.4349%2010.6276%2010.487%2010.6614'%20fill='%23FF7A59'/%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cmask%20id='mask0_2502_833'%20style='mask-type:luminance'%20maskUnits='userSpaceOnUse'%20x='1'%20y='1'%20width='14'%20height='14'%3e%3cpath%20d='M15%201H1V15H15V1Z'%20fill='white'/%3e%3c/mask%3e%3cg%20mask='url(%23mask0_2502_833)'%3e%3cpath%20d='M1.17156%209.61322C1.14041%209.48043%201.2986%209.39678%201.39505%209.49324L6.50679%2014.6049C6.60323%2014.7014%206.5196%2014.8596%206.38681%2014.8284C3.80721%2014.2233%201.77669%2012.1928%201.17156%209.61322ZM1.00026%207.56447C0.997795%207.60414%201.01271%207.64286%201.0408%207.67096L8.32907%2014.9592C8.35714%2014.9873%208.39585%2015.0022%208.43554%2014.9997C8.7672%2014.9791%209.09263%2014.9353%209.41029%2014.8701C9.51732%2014.8481%209.55449%2014.7166%209.47721%2014.6394L1.36063%206.52279C1.28337%206.44552%201.15187%206.48271%201.12989%206.58974C1.06466%206.90734%201.02092%207.23279%201.00026%207.56447ZM1.58953%205.15876C1.56622%205.21109%201.57809%205.27224%201.6186%205.31276L10.6872%2014.3814C10.7278%2014.4219%2010.7889%2014.4338%2010.8412%2014.4105C11.0913%2014.2991%2011.3336%2014.1735%2011.5672%2014.0347C11.6445%2013.9888%2011.6565%2013.8826%2011.5929%2013.819L2.18099%204.40714C2.11742%204.34356%202.01121%204.35549%201.96529%204.43279C1.8265%204.66636%201.70091%204.9087%201.58953%205.15876ZM2.77222%203.53036C2.7204%203.47855%202.7172%203.39544%202.76602%203.34079C4.04913%201.9043%205.9156%201%207.99327%201C11.863%201%2015%204.13702%2015%208.00672C15%2010.0844%2014.0957%2011.9509%2012.6592%2013.234C12.6046%2013.2828%2012.5214%2013.2796%2012.4696%2013.2278L2.77222%203.53036Z'%20fill='url(%23paint0_linear_2502_833)'/%3e%3c/g%3e%3cdefs%3e%3clinearGradient%20id='paint0_linear_2502_833'%20x1='8'%20y1='1'%20x2='8'%20y2='15'%20gradientUnits='userSpaceOnUse'%3e%3cstop%20stop-color='%235C6BF1'/%3e%3cstop%20offset='1'%20stop-color='%23283188'/%3e%3c/linearGradient%3e%3c/defs%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M12.9289%2012.9289H10.8545V9.68033C10.8545%208.90563%2010.8407%207.90839%209.77562%207.90839C8.69517%207.90839%208.52983%208.7524%208.52983%209.62391V12.9287H6.45547V6.24817H8.44688V7.16113H8.47481C8.88025%206.46785%209.63695%206.05224%2010.4396%206.08204C12.5421%206.08204%2012.9297%207.46497%2012.9297%209.2641L12.9289%2012.9289ZM4.11485%205.33497C3.45446%205.33497%202.91079%204.79161%202.91079%204.1312C2.91079%203.47081%203.45421%202.92738%204.1146%202.92738C4.77493%202.92738%205.31829%203.47068%205.31841%204.13096C5.31841%204.79123%204.77512%205.33491%204.11485%205.33497ZM5.15203%2012.9289H3.07549V6.24817H5.15203V12.9289ZM13.963%201.00097H2.03305C1.47303%200.994641%201.00683%201.45002%201%202.01004V13.9897C1.00658%2014.55%201.47272%2015.0059%202.03305%2014.9999H13.963C14.5247%2015.007%2014.9925%2014.5511%2015%2013.9897V2.00923C14.9925%201.44802%2014.5241%200.992699%2013.963%201.00009V1.00097Z'%20fill='%230A66C2'/%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M1%201H15V15H1V1Z'%20fill='%23F3F3F3'/%3e%3cpath%20d='M2%202H8V8H2V2Z'%20fill='%23F35325'/%3e%3cpath%20d='M8%202H14V8H8V2Z'%20fill='%2381BC06'/%3e%3cpath%20d='M2%208H8V14H2V8Z'%20fill='%2305A6F0'/%3e%3cpath%20d='M8%208H14V14H8V8Z'%20fill='%23FFBA08'/%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M2.33281%201.60396L10.0795%201.03183C11.031%200.95016%2011.2756%201.00523%2011.8738%201.44016L14.3467%203.18223C14.7546%203.48183%2014.8904%203.5635%2014.8904%203.8897V13.4438C14.8904%2014.0425%2014.6729%2014.3967%2013.9118%2014.4509L4.91582%2014.9955C4.34462%2015.0225%204.07255%2014.9409%203.77341%2014.5596L1.95248%2012.1917C1.62581%2011.7559%201.49048%2011.4297%201.49048%2011.0484V2.55596C1.49048%202.06643%201.70795%201.65809%202.33281%201.60396Z'%20fill='white'/%3e%3cpath%20fill-rule='evenodd'%20clip-rule='evenodd'%20d='M10.0795%201.03183L2.33281%201.60396C1.70795%201.65809%201.49048%202.06643%201.49048%202.55596V11.0484C1.49048%2011.4297%201.62581%2011.7559%201.95248%2012.1917L3.77341%2014.5596C4.07255%2014.9409%204.34462%2015.0225%204.91582%2014.9955L13.9118%2014.4509C14.6724%2014.3967%2014.8904%2014.0425%2014.8904%2013.4438V3.8897C14.8904%203.5803%2014.7681%203.49116%2014.4083%203.22703C14.3876%203.21212%2014.3669%203.19718%2014.3462%203.18223L11.8738%201.44016C11.2756%201.00523%2011.031%200.95016%2010.0795%201.03183ZM5.11929%203.73336C4.38475%203.78283%204.21815%203.79403%203.80095%203.45476L2.74021%202.61103C2.63241%202.50183%202.68654%202.36556%202.95814%202.33849L10.4052%201.79436C11.0306%201.73976%2011.3563%201.95769%2011.6008%202.14809L12.8781%203.07349C12.9327%203.10103%2013.0685%203.26389%2012.9052%203.26389L5.21449%203.72683L5.11929%203.73336ZM4.26295%2013.3621V5.25144C4.26295%204.89724%204.37168%204.7339%204.69742%204.70637L13.5305%204.1893C13.8301%204.16223%2013.9654%204.35263%2013.9654%204.70637V12.7629C13.9654%2013.1171%2013.9108%2013.4167%2013.4218%2013.4438L4.96902%2013.9338C4.47995%2013.9609%204.26295%2013.798%204.26295%2013.3621ZM12.607%205.68637C12.6611%205.93137%2012.607%206.17637%2012.362%206.20437L11.9546%206.2851V12.2734C11.6008%2012.4638%2011.2751%2012.5725%2011.003%2012.5725C10.5681%2012.5725%2010.4593%2012.4363%2010.1336%2012.0284L7.46942%207.83677V11.8921L8.31224%2012.083C8.31224%2012.083%208.31224%2012.573%207.63229%2012.573L5.75769%2012.6817C5.70309%2012.5725%205.75769%2012.3005%205.94762%2012.2463L6.43716%2012.1105V6.7485L5.75769%206.69344C5.70309%206.44844%205.83889%206.0947%206.21969%206.06717L8.23104%205.93184L11.003%2010.1776V6.42137L10.2965%206.34017C10.2419%206.0401%2010.4593%205.82217%2010.7309%205.79557L12.607%205.68637Z'%20fill='black'/%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M3.94137%209.84695C3.94137%2010.6564%203.28013%2011.3176%202.47069%2011.3176C1.66124%2011.3176%201%2010.6564%201%209.84695C1%209.03747%201.66124%208.37625%202.47069%208.37625H3.94137V9.84695Z'%20fill='%23E01E5A'/%3e%3cpath%20d='M4.68237%209.84695C4.68237%209.03747%205.34361%208.37625%206.15306%208.37625C6.9625%208.37625%207.62374%209.03747%207.62374%209.84695V13.5293C7.62374%2014.3388%206.9625%2015%206.15306%2015C5.34361%2015%204.68237%2014.3388%204.68237%2013.5293V9.84695Z'%20fill='%23E01E5A'/%3e%3cpath%20d='M6.15306%203.94137C5.34361%203.94137%204.68237%203.28013%204.68237%202.47069C4.68237%201.66124%205.34361%201%206.15306%201C6.9625%201%207.62374%201.66124%207.62374%202.47069V3.94137H6.15306Z'%20fill='%2336C5F0'/%3e%3cpath%20d='M6.15309%204.68237C6.96254%204.68237%207.62378%205.34361%207.62378%206.15306C7.62378%206.9625%206.96254%207.62374%206.15309%207.62374H2.47069C1.66124%207.62374%201%206.9625%201%206.15306C1%205.34361%201.66124%204.68237%202.47069%204.68237H6.15309Z'%20fill='%2336C5F0'/%3e%3cpath%20d='M12.0585%206.15306C12.0585%205.34361%2012.7197%204.68237%2013.5291%204.68237C14.3386%204.68237%2014.9998%205.34361%2014.9998%206.15306C14.9998%206.9625%2014.3386%207.62374%2013.5291%207.62374H12.0585V6.15306Z'%20fill='%232EB67D'/%3e%3cpath%20d='M11.3176%206.15309C11.3176%206.96254%2010.6563%207.62378%209.84685%207.62378C9.03744%207.62378%208.37622%206.96254%208.37622%206.15309V2.47069C8.37622%201.66124%209.03744%201%209.84685%201C10.6563%201%2011.3176%201.66124%2011.3176%202.47069V6.15309Z'%20fill='%232EB67D'/%3e%3cpath%20d='M9.84685%2012.0586C10.6563%2012.0586%2011.3176%2012.7199%2011.3176%2013.5293C11.3176%2014.3388%2010.6563%2015%209.84685%2015C9.03744%2015%208.37622%2014.3388%208.37622%2013.5293V12.0586H9.84685Z'%20fill='%23ECB22E'/%3e%3cpath%20d='M9.84685%2011.3176C9.03744%2011.3176%208.37622%2010.6564%208.37622%209.84695C8.37622%209.03747%209.03744%208.37625%209.84685%208.37625H13.5293C14.3388%208.37625%2015%209.03747%2015%209.84695C15%2010.6564%2014.3388%2011.3176%2013.5293%2011.3176H9.84685Z'%20fill='%23ECB22E'/%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M6.60974%205.91839V5.33278C6.40646%205.30058%206.20114%205.28293%205.99535%205.27998C4.00296%205.27577%202.23902%206.56688%201.64074%208.46732C1.04245%2010.3678%201.74866%2012.4365%203.38415%2013.5744C2.15905%2012.2633%201.81888%2010.3546%202.51559%208.70096C3.21229%207.0473%204.81576%205.95753%206.60974%205.91839Z'%20fill='%2325F4EE'/%3e%3cpath%20d='M6.72004%2012.552C7.834%2012.5505%208.74966%2011.6729%208.79844%2010.56V0.6288H10.6128C10.5758%200.421288%2010.5581%200.210783%2010.56%200H8.07844V9.9216C8.03716%2011.0402%207.11934%2011.9262%206.00004%2011.928C5.66555%2011.9252%205.33652%2011.8429%205.04004%2011.688C5.42976%2012.2279%206.05416%2012.5491%206.72004%2012.552Z'%20fill='%2325F4EE'/%3e%3cpath%20d='M14.0014%203.9984V3.4464C13.3337%203.44663%2012.6808%203.24959%2012.1246%202.88C12.6122%203.44675%2013.271%203.83934%2014.0014%203.9984Z'%20fill='%2325F4EE'/%3e%3cpath%20d='M12.125%202.87999C11.5772%202.25615%2011.2752%201.45422%2011.2754%200.623993H10.613C10.786%201.55168%2011.3327%202.36746%2012.125%202.87999Z'%20fill='%23FE2C55'/%3e%3cpath%20d='M5.99519%207.7616C5.03925%207.76652%204.20933%208.42142%203.98229%209.34998C3.75525%2010.2786%204.18936%2011.2426%205.03519%2011.688C4.57688%2011.0552%204.51214%2010.219%204.86761%209.5232C5.22308%208.82744%205.9387%208.3898%206.71999%208.3904C6.92831%208.39298%207.13519%208.42532%207.33439%208.4864V5.9616C7.13099%205.93112%206.92567%205.91509%206.71999%205.9136H6.60959V7.8336C6.40937%207.7799%206.20243%207.75566%205.99519%207.7616Z'%20fill='%23FE2C55'/%3e%3cpath%20d='M14.0015%203.99841V5.91841C12.7654%205.91603%2011.5613%205.52475%2010.5599%204.80001V9.84481C10.5546%2012.3621%208.51245%2014.4%205.99511%2014.4C5.06025%2014.4017%204.1479%2014.1132%203.38391%2013.5744C4.6589%2014.9457%206.64315%2015.3971%208.38585%2014.7123C10.1285%2014.0275%2011.2747%2012.346%2011.2751%2010.4736V5.44321C12.2799%206.16321%2013.4854%206.54937%2014.7215%206.54721V4.07521C14.4795%204.07445%2014.2382%204.04871%2014.0015%203.99841Z'%20fill='%23FE2C55'/%3e%3cpath%20d='M10.56%209.8448V4.79999C11.5645%205.52056%2012.7702%205.9068%2014.0064%205.90399V3.98399C13.2761%203.82977%2012.6157%203.4423%2012.1248%202.87999C11.3324%202.36746%2010.7857%201.55168%2010.6128%200.623993H8.7984V10.56C8.7621%2011.4464%208.16834%2012.2126%207.31904%2012.4691C6.46968%2012.7255%205.55115%2012.4159%205.03038%2011.6976C4.18454%2011.2522%203.75043%2010.2882%203.97747%209.35958C4.20452%208.43102%205.03444%207.77612%205.99038%207.7712C6.19878%207.77306%206.40578%207.8054%206.6048%207.8672V5.94719C4.80073%205.97776%203.18515%207.07136%202.48647%208.73486C1.78778%2010.3984%202.13799%2012.3176%203.37918%2013.6272C4.1507%2014.1482%205.06437%2014.4181%205.99518%2014.4C8.5125%2014.4%2010.5547%2012.3621%2010.56%209.8448Z'%20fill='black'/%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M14%207.94593L11.75%2010.1081H9.5L7.53124%2012V10.1081H5V2H14V7.94593Z'%20fill='white'/%3e%3cpath%20d='M4.70834%201L2%203.67857V13.3215H5.25V16L7.95833%2013.3215H10.125L15%208.5V1H4.70834ZM13.9166%207.96428L11.75%2010.1072H9.5833L7.6875%2011.9822V10.1072H5.25V2.07143H13.9166V7.96428Z'%20fill='%239146FF'/%3e%3cpath%20d='M12%204H11V7H12V4Z'%20fill='%239146FF'/%3e%3cpath%20d='M9%204H8V7H9V4Z'%20fill='%239146FF'/%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M9.14163%206.50461L13.6089%201H12.5503L8.67137%205.77958L5.57328%201H2L6.68492%208.22757L2%2014H3.05866L7.15491%208.9526L10.4267%2014H14L9.14137%206.50461H9.14163ZM7.69165%208.29124L7.21697%207.57154L3.44011%201.84479H5.06615L8.11412%206.46646L8.5888%207.18616L12.5508%2013.1936H10.9248L7.69165%208.29152V8.29124Z'%20fill='black'%20stroke='black'%20stroke-width='0.5'/%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cmask%20id='mask0_2502_830'%20style='mask-type:luminance'%20maskUnits='userSpaceOnUse'%20x='1'%20y='1'%20width='14'%20height='14'%3e%3cpath%20d='M15%201H1V15H15V1Z'%20fill='white'/%3e%3c/mask%3e%3cg%20mask='url(%23mask0_2502_830)'%3e%3cpath%20d='M7.99994%2014.9733C11.8512%2014.9733%2014.9732%2011.8513%2014.9732%207.99997C14.9732%204.14873%2011.8512%201.02667%207.99994%201.02667C4.14867%201.02667%201.02661%204.14873%201.02661%207.99997C1.02661%2011.8513%204.14867%2014.9733%207.99994%2014.9733Z'%20fill='%231AB4D7'/%3e%3cpath%20d='M4.36467%207.97988L5.55473%206.78688C5.59418%206.74667%205.61619%206.69343%205.61619%206.63697C5.61619%206.5193%205.52054%206.42374%205.40287%206.42374C5.34555%206.42374%205.29181%206.44621%205.2513%206.48723L4.06231%207.67564L2.86801%206.48544C2.82765%206.44566%202.77418%206.42374%202.71748%206.42374C2.59995%206.42374%202.50427%206.51925%202.50427%206.6368C2.50427%206.69415%202.52716%206.74796%202.56825%206.7885L3.75814%207.97822L2.56887%209.16973C2.52707%209.21089%202.50427%209.26479%202.50427%209.3224C2.50427%209.44007%202.59995%209.53548%202.71748%209.53548C2.77428%209.53548%202.8278%209.51343%202.86801%209.47325L4.06046%208.28241L5.24838%209.46891C5.29051%209.51245%205.34487%209.53562%205.40287%209.53562C5.52042%209.53562%205.61608%209.44007%205.61608%209.3224C5.61608%209.26563%205.59409%209.21229%205.55406%209.17211L4.36467%207.97988Z'%20fill='white'/%3e%3cpath%20d='M11.4393%207.97953C11.4393%208.19316%2011.6131%208.36697%2011.827%208.36697C12.0404%208.36697%2012.2142%208.19316%2012.2142%207.97953C12.2142%207.76582%2012.0404%207.59204%2011.827%207.59204C11.6131%207.59204%2011.4393%207.76582%2011.4393%207.97953Z'%20fill='white'/%3e%3cpath%20d='M10.7045%207.97969C10.7045%207.36096%2011.2078%206.85753%2011.8266%206.85753C12.4451%206.85753%2012.9485%207.36096%2012.9485%207.97969C12.9485%208.59828%2012.4451%209.10151%2011.8266%209.10151C11.2078%209.10151%2010.7045%208.59828%2010.7045%207.97969ZM10.2631%207.97969C10.2631%208.84167%2010.9645%209.543%2011.8266%209.543C12.6887%209.543%2013.3905%208.84167%2013.3905%207.97969C13.3905%207.11757%2012.6887%206.41608%2011.8266%206.41608C10.9645%206.41608%2010.2631%207.11757%2010.2631%207.97969Z'%20fill='white'/%3e%3cpath%20d='M10.152%206.44279L10.0864%206.4426C9.88947%206.4426%209.69956%206.50471%209.54094%206.62696C9.52001%206.5313%209.43447%206.45933%209.33269%206.45933C9.21544%206.45933%209.1215%206.55325%209.12122%206.67071L9.12192%209.3041C9.12227%209.42135%209.21789%209.51662%209.33514%209.51662C9.45246%209.51662%209.54808%209.42135%209.54836%209.30382L9.54843%207.68463C9.54843%207.14496%209.59778%206.927%2010.0601%206.86923C10.1028%206.86392%2010.1494%206.86475%2010.1494%206.86475C10.276%206.86041%2010.3659%206.77348%2010.3659%206.656C10.3659%206.53844%2010.2699%206.44279%2010.152%206.44279Z'%20fill='white'/%3e%3cpath%20d='M6.05791%207.72227C6.05791%207.71643%206.05836%207.71035%206.05864%207.70435C6.18243%207.215%206.62563%206.85287%207.15344%206.85287C7.68764%206.85287%208.13489%207.2239%208.25235%207.72227H6.05791ZM8.689%207.682C8.59709%207.24697%208.35895%206.88964%207.99626%206.66016C7.46613%206.32358%206.76607%206.3422%206.25401%206.70635C5.83632%207.00349%205.59521%207.48958%205.59521%207.9903C5.59521%208.11586%205.61035%208.24256%205.64186%208.3673C5.79957%208.98778%206.33294%209.45741%206.96885%209.53525C7.15754%209.55814%207.34122%209.54715%207.53141%209.49794C7.69485%209.45818%207.85299%209.39189%207.99871%209.29851C8.14993%209.20128%208.27628%209.07304%208.39864%208.9196C8.40116%208.9168%208.40361%208.91428%208.40613%208.91134C8.49104%208.80599%208.47529%208.65619%208.38198%208.58465C8.30323%208.52438%208.17107%208.49988%208.06712%208.63309C8.04472%208.66487%208.0198%208.69763%207.99238%208.73039C7.90969%208.82181%207.80712%208.91029%207.6842%208.97896C7.52779%209.06254%207.34955%209.11028%207.16006%209.11133C6.53986%209.1044%206.20799%208.67152%206.08993%208.36254C6.06932%208.30479%206.05342%208.24494%206.04234%208.18334C6.0409%208.17179%206.03983%208.16066%206.0394%208.15044C6.16763%208.15044%208.26501%208.15009%208.26501%208.15009C8.57014%208.14365%208.73436%207.92828%208.689%207.682Z'%20fill='white'/%3e%3c/g%3e%3c/svg%3e\"","import type { CSSProperties } from 'react';\nimport { cn } from '@/utils';\nimport { CountryFlag } from '../country-flag';\nimport '@/styles/index.css';\nimport './style.css';\n\nimport browserChrome from '@/assets/icons/general/browser-chrome.svg';\nimport caretDown from '@/assets/icons/general/caret-down.svg';\nimport check from '@/assets/icons/general/check.svg';\nimport close from '@/assets/icons/general/close.svg';\nimport dotsVertical from '@/assets/icons/general/dots-vertical.svg';\nimport edit from '@/assets/icons/general/edit.svg';\nimport eyeOff from '@/assets/icons/general/eye-off.svg';\nimport eyeOn from '@/assets/icons/general/eye-on.svg';\nimport key from '@/assets/icons/general/key.svg';\nimport label from '@/assets/icons/general/label.svg';\nimport logo from '@/assets/icons/general/logo.svg';\nimport logoRed from '@/assets/icons/general/logo-red.svg';\nimport mail from '@/assets/icons/general/mail.svg';\nimport onePassword from '@/assets/icons/general/one-password.svg';\nimport passkey from '@/assets/icons/general/passkey.svg';\nimport phone from '@/assets/icons/general/phone.svg';\nimport search from '@/assets/icons/general/search.svg';\nimport trash from '@/assets/icons/general/trash.svg';\nimport warning from '@/assets/icons/general/warning.svg';\nimport apple from '@/assets/icons/providers/apple.svg';\nimport atlassian from '@/assets/icons/providers/atlassian.svg';\nimport bitbucket from '@/assets/icons/providers/bitbucket.svg';\nimport discord from '@/assets/icons/providers/discord.svg';\nimport dropbox from '@/assets/icons/providers/dropbox.svg';\nimport facebook from '@/assets/icons/providers/facebook.svg';\nimport github from '@/assets/icons/providers/github.svg';\nimport gitlab from '@/assets/icons/providers/gitlab.svg';\nimport google from '@/assets/icons/providers/google.svg';\nimport hubspot from '@/assets/icons/providers/hubspot.svg';\nimport linear from '@/assets/icons/providers/linear.svg';\nimport linkedin from '@/assets/icons/providers/linkedin.svg';\nimport microsoft from '@/assets/icons/providers/microsoft.svg';\nimport notion from '@/assets/icons/providers/notion.svg';\nimport slack from '@/assets/icons/providers/slack.svg';\nimport tiktok from '@/assets/icons/providers/tiktok.svg';\nimport twitch from '@/assets/icons/providers/twitch.svg';\nimport twitter from '@/assets/icons/providers/twitter.svg';\nimport xero from '@/assets/icons/providers/xero.svg';\n\ntype TIcon = {\n type: 'general' | 'providers' | 'flags';\n id: string;\n size: 'small' | 'medium' | 'big' | 'large';\n className?: string;\n decorative?: boolean;\n matchTextColor?: boolean;\n};\n\ntype IconMaskStyle = CSSProperties & {\n '--passflow-icon-mask': string;\n};\n\nexport const Icon = ({ type, id, size, className = '', decorative = false, matchTextColor = false }: TIcon) => {\n const styles = {\n 'passflow-icon--small': size === 'small',\n 'passflow-icon--medium': size === 'medium',\n 'passflow-icon--big': size === 'big',\n 'passflow-icon--large': size === 'large',\n };\n\n const icons: Record<'providers' | 'general', Record<string, string>> = {\n general: {\n logo,\n 'logo-red': logoRed,\n warning,\n mail,\n edit,\n 'eye-on': eyeOn,\n 'eye-off': eyeOff,\n search,\n 'caret-down': caretDown,\n label,\n close,\n check,\n key,\n phone,\n 'one-password': onePassword,\n 'browser-chrome': browserChrome,\n passkey,\n 'dots-vertical': dotsVertical,\n trash,\n },\n providers: {\n google,\n gitlab,\n apple,\n atlassian,\n bitbucket,\n discord,\n dropbox,\n facebook,\n github,\n hubspot,\n linear,\n linkedin,\n linledin: linkedin,\n microsoft,\n notion,\n slack,\n tiktok,\n twitch,\n twitter,\n xero,\n },\n };\n\n if (matchTextColor && type === 'general') {\n const style: IconMaskStyle = {\n '--passflow-icon-mask': `url(\"${icons.general[id]}\")`,\n };\n\n return (\n <span\n className={cn('passflow-icon passflow-icon--match-text', styles, className)}\n style={style}\n role={decorative ? undefined : 'img'}\n aria-label={decorative ? undefined : id}\n aria-hidden={decorative || undefined}\n />\n );\n }\n\n if (type !== 'flags') {\n return <img className={cn('passflow-icon', styles, className)} src={icons[type][id]} alt={decorative ? '' : id} />;\n }\n\n return (\n <div className={cn('passflow-icon', styles, className)}>\n <CountryFlag iso2={id} />\n </div>\n );\n};\n","/* eslint-disable react/jsx-props-no-spreading */\nimport type { FC, MouseEvent, PropsWithChildren } from 'react';\nimport { useNavigation } from '@/hooks';\nimport '@/styles/index.css';\n\ntype LinkProps = PropsWithChildren<{\n to: string;\n search?: string;\n replace?: boolean;\n className?: string;\n onClick?: (e: MouseEvent<HTMLAnchorElement>) => void;\n}>;\n\nexport const Link: FC<LinkProps> = ({ to, search, replace = false, children, className, onClick, ...props }) => {\n const { navigate } = useNavigation();\n\n const handleClick = (e: MouseEvent<HTMLAnchorElement>) => {\n e.preventDefault();\n\n if (onClick) {\n onClick(e);\n }\n\n navigate({ to, search, replace });\n };\n\n const getHref = (): string => {\n const searchParam = search ? (search.startsWith('?') ? search : `?${search}`) : '';\n return `${to}${searchParam}`;\n };\n\n return (\n <a href={getHref()} onClick={handleClick} className={className} {...props}>\n {children}\n </a>\n );\n};\n","import type { FC, PropsWithChildren } from 'react';\nimport { Icon } from '../icon';\nimport type { LoginScreenNotice as LoginScreenNoticeProps } from './types';\n\nexport const LoginAlert: FC<{ message?: string | null; id?: string }> = ({ message, id }) => {\n if (!message) return null;\n\n return (\n <div id={id} className='passflow-form-error' role='alert'>\n <Icon size='small' id='warning' type='general' className='icon-warning' decorative />\n <span className='passflow-form-error-text'>{message}</span>\n </div>\n );\n};\n\nexport const LoginDivider: FC<{ label: string }> = ({ label }) => (\n <div className='passflow-form-divider' aria-hidden='true'>\n <div className='passflow-form-divider__line-left' />\n <span className='passflow-form-divider__text'>{label}</span>\n <div className='passflow-form-divider__line-right' />\n </div>\n);\n\nexport const LoginActionStack: FC<PropsWithChildren> = ({ children }) => (\n <div className='passflow-login-screen-actions'>{children}</div>\n);\n\nexport const LoginProgress: FC<{ message: string }> = ({ message }) => (\n <div className='passflow-login-screen-status' role='status' aria-live='polite'>\n <div className='passflow-login-screen-spinner passflow-login-screen-spinner--small' aria-hidden='true' />\n <p className='passflow-login-screen-text passflow-login-screen-centered-text'>{message}</p>\n </div>\n);\n\nexport const LoginScreenNotice: FC<LoginScreenNoticeProps> = ({ code, appName, message, codeTestId, appNameTestId }) => (\n <div className='passflow-login-screen-notice' role='note'>\n {code ? (\n <div className='passflow-login-screen-code' data-testid={codeTestId}>\n {code}\n </div>\n ) : null}\n <p className='passflow-login-screen-text passflow-login-screen-centered-text'>\n <span className='passflow-login-screen-app-name' data-testid={appNameTestId}>\n {appName}\n </span>{' '}\n {message}\n </p>\n </div>\n);\n","import type { FC, FormEvent } from 'react';\nimport { useState } from 'react';\nimport { Button } from '../button';\nimport { FieldText } from '../fields/field-text';\nimport { LoginAlert, LoginProgress } from './shared';\nimport type { LoginCodeEntryState } from './types';\n\nexport const LoginCodeEntry: FC<LoginCodeEntryState> = ({\n label = 'Code',\n initialCode = '',\n error,\n busy = false,\n submitLabel = 'Continue',\n testId,\n onSubmit,\n}) => {\n const [code, setCode] = useState(initialCode);\n\n const handleSubmit = (event: FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n const normalizedCode = code.trim();\n if (normalizedCode) onSubmit(normalizedCode);\n };\n\n return (\n <form className='passflow-form' data-testid={testId} aria-busy={busy} onSubmit={handleSubmit}>\n <div className='passflow-form-container'>\n <div className='passflow-form-field'>\n <div className='passflow-form-field__header'>\n <label htmlFor='device-user-code' className='passflow-field-label'>\n {label}\n </label>\n </div>\n <FieldText\n id='device-user-code'\n name='user_code'\n type='text'\n autoCapitalize='characters'\n autoComplete='off'\n autoCorrect='off'\n spellCheck={false}\n inputMode='text'\n className='passflow-login-screen-code-input'\n value={code}\n disabled={busy}\n aria-invalid={Boolean(error)}\n aria-describedby={error ? 'device-user-code-error' : undefined}\n isError={Boolean(error)}\n onChange={(event) => setCode(event.target.value)}\n />\n </div>\n <LoginAlert id='device-user-code-error' message={error} />\n </div>\n {busy ? <LoginProgress message='Checking the code…' /> : null}\n <Button size='big' variant='primary' type='submit' disabled={busy || code.trim().length === 0}>\n {busy ? 'Checking…' : submitLabel}\n </Button>\n </form>\n );\n};\n","import { type ChangeEvent, type FC, useId } from 'react';\nimport { cn } from '@/utils';\n\ntype TSwitch = {\n label: string;\n checked: boolean;\n disabled?: boolean;\n /**\n * Overrides the generated input id. Only needed when something outside this\n * component has to point at the input (`aria-describedby`, a test hook, a\n * label rendered elsewhere).\n *\n * The default is a `useId()` value rather than a constant, because a constant\n * breaks the moment a screen renders more than one Switch: duplicate DOM ids\n * are invalid, and every `<label htmlFor>` would resolve to the FIRST input,\n * so clicking row three would toggle row one. The consent screen renders one\n * Switch per requested scope, so this is load-bearing, not hygiene.\n */\n id?: string;\n onChange: (event: ChangeEvent<HTMLInputElement>) => void;\n};\n\nexport const Switch: FC<TSwitch> = ({ label, checked, disabled = false, id, onChange }) => {\n const generatedId = useId();\n const inputId = id ?? generatedId;\n\n return (\n <label className={cn('passflow-switch-wrapper', { 'passflow-switch-wrapper--disabled': disabled })} htmlFor={inputId}>\n <span className='passflow-switch-label'>{label}</span>\n <input\n id={inputId}\n type='checkbox'\n className='passflow-switch-input'\n checked={checked}\n disabled={disabled}\n onChange={onChange}\n />\n <div className='passflow-switch-track' />\n </label>\n );\n};\n","import type { FC } from 'react';\nimport { Button } from '../button';\nimport { Switch } from '../switch';\nimport { LoginAlert, LoginProgress, LoginScreenNotice } from './shared';\nimport type { LoginConsentState } from './types';\n\n/**\n * The OIDC consent screen: which scopes an application is asking for, and the\n * two decisions a user can make about them.\n *\n * Every scope starts granted and can be switched off individually — the Allow\n * button submits the subset that is still on, so \"Allow\" never grants more than\n * what is visible on screen. Deny is a peer of Allow, not a hidden link: a\n * consent screen where refusing is harder than accepting is a dark pattern.\n * For the same reason neither button takes initial focus: a bare Enter on a\n * freshly loaded screen must not grant every requested scope.\n */\nexport const LoginConsent: FC<LoginConsentState> = ({\n appName,\n scopes,\n prompt = 'wants to access your account.',\n busy = false,\n error,\n allowLabel = 'Allow',\n denyLabel = 'Deny',\n busyLabel = 'Submitting…',\n testId,\n allowTestId,\n denyTestId,\n appNameTestId,\n onToggleScope,\n onAllow,\n onDeny,\n}) => (\n <div className='passflow-form' data-testid={testId} aria-busy={busy}>\n <LoginScreenNotice appName={appName} message={prompt} appNameTestId={appNameTestId} />\n\n <div className='passflow-form-container'>\n <LoginAlert message={error} />\n\n {scopes.length ? (\n <ul className='passflow-consent-scopes'>\n {scopes.map((item) => (\n <li key={item.scope} className='passflow-consent-scope' data-testid={`consent-scope-${item.scope}`}>\n <Switch label={item.label} checked={item.granted} disabled={busy} onChange={() => onToggleScope(item.scope)} />\n {item.description ? <p className='passflow-consent-scope-description'>{item.description}</p> : null}\n </li>\n ))}\n </ul>\n ) : (\n <p className='passflow-login-screen-hint'>This application is not requesting access to any of your data.</p>\n )}\n </div>\n\n {busy ? <LoginProgress message={busyLabel} /> : null}\n\n <div className='passflow-consent-actions'>\n <Button size='big' variant='primary' type='button' data-testid={allowTestId} disabled={busy} onClick={onAllow}>\n {allowLabel}\n </Button>\n <Button size='big' variant='outlined' type='button' data-testid={denyTestId} disabled={busy} onClick={onDeny}>\n {denyLabel}\n </Button>\n </div>\n </div>\n);\n","import type { FC } from 'react';\nimport { Button } from '../button';\nimport { Icon } from '../icon';\nimport '@/styles/index.css';\nimport type { Providers } from '@passflow/core';\nimport { cn } from '@/utils';\n\ntype TProvidersBox = {\n providers: Providers[];\n onClick: (provider: Providers) => void;\n className?: string;\n};\n\nexport const ProvidersBox: FC<TProvidersBox> = ({ providers, onClick, className = '' }) => {\n const styles = {\n 'passflow-providers-box--grid': providers.length > 1,\n };\n\n return (\n <div className={cn('passflow-providers-box', styles, className)}>\n {providers.map((provider) => (\n <Button\n onClick={() => onClick(provider)}\n size='big'\n variant='provider'\n type='button'\n key={provider}\n withIcon\n className='passflow-provider-item'\n >\n <Icon size='small' type='providers' id={provider} decorative={providers.length <= 2} />\n {providers.length <= 2 && <p className='passflow-provider-text'>{provider}</p>}\n </Button>\n ))}\n </div>\n );\n};\n","import { phone } from 'phone';\nimport type { FC } from 'react';\nimport { useEffect, useRef, useState } from 'react';\nimport { Controller, useForm } from 'react-hook-form';\nimport type { DefaultMethod } from '@/types';\nimport { cn, emailRegex, passwordValidation } from '@/utils';\nimport { Button } from '../button';\nimport { FieldPassword } from '../fields/field-password';\nimport { FieldPhone } from '../fields/field-phone';\nimport { FieldText } from '../fields/field-text';\nimport { Icon } from '../icon';\nimport { Link } from '../link';\nimport { ProvidersBox } from '../providers-box';\nimport { Switch } from '../switch';\nimport { LoginActionStack, LoginAlert, LoginDivider, LoginProgress, LoginScreenNotice } from './shared';\nimport type { LoginCredentialsState, LoginCredentialsValues } from './types';\n\ntype LoginFormValues = {\n email_or_username: string;\n phone: string;\n password: string;\n};\n\nconst initialValues: LoginFormValues = {\n email_or_username: '',\n phone: '',\n password: '',\n};\n\nconst getDefaultMethod = (state: LoginCredentialsState): DefaultMethod | null => {\n if (state.initialMethod !== undefined && state.methods.identities.some((method) => method.id === state.initialMethod)) {\n return state.initialMethod;\n }\n return state.methods.identities[0]?.id ?? null;\n};\n\nexport const LoginCredentials: FC<LoginCredentialsState> = (state) => {\n const { methods } = state;\n const computedDefaultMethod = getDefaultMethod(state);\n const [defaultMethod, setDefaultMethod] = useState<DefaultMethod | null>(computedDefaultMethod);\n const [passkeyOnly, setPasskeyOnly] = useState(Boolean(state.forcePasskey));\n const previousComputedMethod = useRef(computedDefaultMethod);\n const previousForcePasskey = useRef(Boolean(state.forcePasskey));\n const {\n control,\n getValues,\n reset,\n trigger,\n watch,\n formState: { errors, isDirty, isValid },\n handleSubmit,\n } = useForm<LoginFormValues>({\n defaultValues: initialValues,\n mode: 'onChange',\n });\n\n useEffect(() => {\n if (previousComputedMethod.current === computedDefaultMethod) return;\n previousComputedMethod.current = computedDefaultMethod;\n setDefaultMethod(computedDefaultMethod);\n reset(initialValues);\n }, [computedDefaultMethod, reset]);\n\n useEffect(() => {\n const nextForcePasskey = Boolean(state.forcePasskey);\n if (previousForcePasskey.current === nextForcePasskey) return;\n previousForcePasskey.current = nextForcePasskey;\n setPasskeyOnly(nextForcePasskey);\n }, [state.forcePasskey]);\n\n const currentIdentity = methods.identities.find((method) => method.id === defaultMethod);\n const hasPassword = Boolean(currentIdentity?.password);\n const hasPasswordless = Boolean(currentIdentity?.passwordlessLabel);\n const hasPasskey = methods.passkey;\n const hasIdentity = Boolean(currentIdentity);\n const showCredentialFields = !passkeyOnly && hasIdentity;\n const showStandalonePasskey = hasPasskey && (passkeyOnly || !hasIdentity);\n const hasCredentialActions = hasPassword || hasPasswordless || hasPasskey;\n const controlsDisabled = Boolean(state.busy || state.disabled);\n const errorScope = state.error?.scope;\n const hasIdentityError = errorScope === 'identity' || errorScope === 'credentials';\n const hasPasswordError = errorScope === 'password' || errorScope === 'credentials';\n const isNewPassword = state.credentialPurpose === 'sign-up';\n\n const validatePassword = (value: string) => {\n if (!isNewPassword) return true;\n\n try {\n passwordValidation(state.passwordPolicy).validateSync(value);\n return true;\n } catch (error) {\n const validationError = error as { errors?: string[] };\n return validationError.errors?.join(', ') ?? 'Password does not meet the requirements';\n }\n };\n\n const toCredentials = (values: LoginFormValues): LoginCredentialsValues => ({\n method: defaultMethod,\n emailOrUsername: values.email_or_username,\n phone: values.phone,\n password: values.password,\n });\n\n const handleReset = () => {\n reset(initialValues);\n state.onReset?.();\n };\n\n const handleMethodChange = (method: DefaultMethod) => {\n setDefaultMethod(method);\n handleReset();\n };\n\n const handlePasskeyExperienceChange = (checked: boolean) => {\n setPasskeyOnly(checked);\n handleReset();\n };\n\n const submitCurrentMethod = handleSubmit((values) => {\n if (hasPassword) {\n state.onPassword?.(toCredentials(values));\n return;\n }\n if (hasPasswordless) state.onPasswordless?.(toCredentials(values));\n });\n\n const submitPasswordless = async () => {\n if (!defaultMethod || !state.onPasswordless) return;\n const identityField = defaultMethod === 'phone' ? 'phone' : 'email_or_username';\n if (!(await trigger(identityField))) return;\n state.onPasswordless(toCredentials(getValues()));\n };\n const selectedIdentityValue = defaultMethod === 'phone' ? watch('phone') : watch('email_or_username');\n const alternateIdentity = methods.identities.find((method) => method.id !== defaultMethod);\n\n return (\n <>\n {state.notice ? <LoginScreenNotice {...state.notice} /> : null}\n {state.allowPasskeyToggle && hasPasskey && hasIdentity && (hasPassword || hasPasswordless) ? (\n <div className='passflow-form-switch'>\n <Switch\n label='Passwordless experience'\n checked={passkeyOnly}\n disabled={controlsDisabled}\n onChange={(event) => handlePasskeyExperienceChange(event.target.checked)}\n />\n </div>\n ) : null}\n <form\n className='passflow-form'\n data-testid={state.testId}\n aria-busy={controlsDisabled && Boolean(state.busy)}\n onSubmit={submitCurrentMethod}\n >\n {state.busy ? <LoginProgress message={state.primaryLabel ?? 'Signing in…'} /> : null}\n {showCredentialFields ? (\n <>\n <div className='passflow-form-container'>\n {defaultMethod === 'email_or_username' ? (\n <div className='passflow-form-field'>\n <div className='passflow-form-field__header'>\n <label\n htmlFor='email_or_username'\n className={cn('passflow-field-label', {\n 'passflow-field-label--error': hasIdentityError || Boolean(errors.email_or_username),\n })}\n >\n {currentIdentity?.label}\n </label>\n {alternateIdentity ? (\n <Button\n size='small'\n variant='clean'\n type='button'\n className='passflow-field-label-button'\n disabled={controlsDisabled}\n onClick={() => handleMethodChange(alternateIdentity.id)}\n >\n {alternateIdentity.selectLabel}\n </Button>\n ) : null}\n </div>\n <Controller\n name='email_or_username'\n control={control}\n rules={{\n required: currentIdentity?.requiredMessage ?? 'Identity is required',\n ...(currentIdentity?.format === 'email'\n ? { pattern: { value: emailRegex, message: 'Invalid email' } }\n : undefined),\n }}\n render={({ field }) => (\n <FieldText\n {...field}\n id='email_or_username'\n type={currentIdentity?.format === 'email' ? 'email' : 'text'}\n autoComplete={currentIdentity?.format === 'email' ? 'email' : 'username'}\n aria-invalid={Boolean(errors.email_or_username)}\n aria-describedby={errors.email_or_username ? 'email_or_username-error' : undefined}\n isError={hasIdentityError || Boolean(errors.email_or_username)}\n disabled={controlsDisabled}\n />\n )}\n />\n {errors.email_or_username?.message ? (\n <LoginAlert id='email_or_username-error' message={errors.email_or_username.message} />\n ) : null}\n </div>\n ) : null}\n\n {defaultMethod === 'phone' ? (\n <div className='passflow-form-field'>\n <div className='passflow-form-field__header'>\n <label\n htmlFor='phone'\n className={cn('passflow-field-label', {\n 'passflow-field-label--error': hasIdentityError || Boolean(errors.phone),\n })}\n >\n Phone number\n </label>\n {alternateIdentity ? (\n <Button\n size='small'\n variant='clean'\n type='button'\n className='passflow-field-label-button'\n disabled={controlsDisabled}\n onClick={() => handleMethodChange(alternateIdentity.id)}\n >\n {alternateIdentity.selectLabel}\n </Button>\n ) : null}\n </div>\n <Controller\n name='phone'\n control={control}\n rules={{\n required: 'Phone number is required',\n validate: (value) => phone(value).isValid || 'Invalid phone number',\n }}\n render={({ field }) => (\n <FieldPhone\n id='phone'\n name='phone'\n onChange={field.onChange}\n aria-describedby={errors.phone ? 'phone-error' : undefined}\n isError={hasIdentityError || Boolean(errors.phone)}\n disabled={controlsDisabled}\n ref={null}\n />\n )}\n />\n {errors.phone?.message ? <LoginAlert id='phone-error' message={errors.phone.message} /> : null}\n </div>\n ) : null}\n\n {hasPassword ? (\n <div className='passflow-form-field'>\n <div className='passflow-form-field__header'>\n <label\n htmlFor='password'\n className={cn('passflow-field-label', {\n 'passflow-field-label--error': hasPasswordError || Boolean(errors.password),\n })}\n >\n Password\n </label>\n {state.forgotPassword ? (\n <Link\n to={state.forgotPassword.to}\n search={state.forgotPassword.getSearch?.(defaultMethod)}\n className='passflow-field-label-button'\n >\n Forgot Password?\n </Link>\n ) : null}\n </div>\n <Controller\n name='password'\n control={control}\n rules={{ required: 'Password is required', validate: validatePassword }}\n render={({ field }) => (\n <FieldPassword\n {...field}\n id='password'\n name='password'\n aria-invalid={Boolean(errors.password)}\n aria-describedby={errors.password && !isNewPassword ? 'password-error' : undefined}\n isError={hasPasswordError || Boolean(errors.password)}\n passwordPolicy={state.passwordPolicy}\n withMessages={isNewPassword}\n validationErrors={\n isNewPassword && errors.password?.message ? errors.password.message.split(', ') : undefined\n }\n autoComplete={isNewPassword ? 'new-password' : 'current-password'}\n disabled={controlsDisabled}\n />\n )}\n />\n {!isNewPassword && errors.password?.message ? (\n <LoginAlert id='password-error' message={errors.password.message} />\n ) : null}\n </div>\n ) : null}\n\n <LoginAlert message={state.error?.message} />\n </div>\n\n <LoginActionStack>\n {hasPassword && state.onPassword ? (\n <Button\n size='big'\n variant='primary'\n type='submit'\n disabled={controlsDisabled || !isDirty || !isValid}\n className='passflow-button-signin'\n data-testid={state.primaryTestId}\n >\n {state.primaryLabel ?? 'Sign In'}\n </Button>\n ) : null}\n {hasPasswordless && state.onPasswordless ? (\n <Button\n size='big'\n variant={hasPassword ? 'outlined' : 'primary'}\n type='button'\n className={cn('passflow-button-passwordless', {\n 'passflow-button-passwordless--active': hasPassword,\n })}\n disabled={controlsDisabled || selectedIdentityValue.trim().length === 0}\n onClick={() => void submitPasswordless()}\n >\n {state.passwordlessLabelPrefix ?? 'Sign In with'} {currentIdentity?.passwordlessLabel}\n </Button>\n ) : null}\n {hasPasskey && state.onPasskey ? (\n <Button\n size='big'\n variant='dark'\n type='button'\n className='passflow-button-passkey'\n withIcon\n disabled={controlsDisabled}\n onClick={state.onPasskey}\n >\n <Icon\n id='key'\n size='small'\n type='general'\n className='passflow-button-passkey-icon'\n decorative\n matchTextColor\n />\n {state.passkeyLabel ?? 'Sign In with a Passkey'}\n </Button>\n ) : null}\n </LoginActionStack>\n </>\n ) : null}\n\n {showStandalonePasskey ? (\n <>\n <LoginAlert message={state.error?.message} />\n {state.onPasskey ? (\n <LoginActionStack>\n <Button\n size='big'\n variant='dark'\n type='button'\n className='passflow-button-passkey'\n withIcon\n disabled={controlsDisabled}\n onClick={state.onPasskey}\n >\n <Icon\n id='key'\n size='small'\n type='general'\n className='passflow-button-passkey-icon'\n decorative\n matchTextColor\n />\n {state.passkeyLabel ?? 'Sign In with a Passkey'}\n </Button>\n </LoginActionStack>\n ) : null}\n </>\n ) : null}\n\n {state.footer ? (\n <div className={cn('passflow-form-actions', { 'passflow-form-actions--top-space': hasCredentialActions })}>\n <p className='passflow-dont-have-account'>\n {state.footer.prompt}{' '}\n <Link to={state.footer.to} search={state.footer.search} className='passflow-link'>\n {state.footer.label}\n </Link>\n </p>\n </div>\n ) : null}\n\n {methods.providers.length > 0 && state.onProvider ? (\n <div className='passflow-form-providers'>\n {hasCredentialActions ? <LoginDivider label='Or continue with' /> : null}\n <ProvidersBox providers={methods.providers} onClick={state.onProvider} />\n </div>\n ) : null}\n </form>\n </>\n );\n};\n","import type { FC } from 'react';\nimport { Button } from '../button';\nimport { Icon } from '../icon';\nimport { LoginAlert, LoginProgress, LoginScreenNotice } from './shared';\nimport type { LoginDeviceApprovalState } from './types';\n\nexport const LoginDeviceApproval: FC<LoginDeviceApprovalState> = ({\n appName,\n code,\n identity,\n busy = false,\n error,\n actionLabel = 'Approve this device',\n busyLabel = 'Approving…',\n testId,\n actionTestId,\n codeTestId,\n appNameTestId,\n onApprove,\n}) => (\n <div className='passflow-form' data-testid={testId} aria-busy={busy}>\n <LoginScreenNotice\n code={code}\n appName={appName}\n message='requested this sign-in. Confirm that the code matches your terminal.'\n codeTestId={codeTestId}\n appNameTestId={appNameTestId}\n />\n <div className='passflow-form-container passflow-login-screen-centered'>\n <div className='passflow-login-screen-success' role='status' aria-live='polite'>\n <Icon size='small' id='check' type='general' className='icon-success' decorative />\n <p className='passflow-login-screen-text'>\n {identity ? (\n <>\n Signed in as <strong className='passflow-login-screen-app-name'>{identity}</strong>.\n </>\n ) : (\n 'Signed in successfully.'\n )}\n </p>\n </div>\n <p className='passflow-login-screen-hint'>Approve this request to finish signing in on the device.</p>\n <LoginAlert message={error} />\n </div>\n {busy ? <LoginProgress message={busyLabel} /> : null}\n <Button\n size='big'\n variant='primary'\n type='button'\n autoFocus={!busy}\n data-testid={actionTestId}\n disabled={busy}\n onClick={onApprove}\n >\n {busy ? busyLabel : actionLabel}\n </Button>\n </div>\n);\n","import type { FC } from 'react';\nimport { Button } from '../button';\nimport type { LoginGeneralErrorState } from './types';\n\nexport const LoginGeneralError: FC<LoginGeneralErrorState> = ({\n message,\n detail = 'Go back to start again.',\n actionLabel = 'Go back',\n testId,\n onAction,\n}) => (\n <div className='passflow-error-container' data-testid={testId}>\n <div className='passflow-error-container-text-wrapper' role='alert' aria-live='assertive'>\n {message ? <h1 className='passflow-error-container-text'>{message}</h1> : null}\n <p className='passflow-error-container-text-secondary'>{detail}</p>\n </div>\n <Button size='big' type='button' variant='primary' onClick={onAction} className='passflow-button-go-back-error'>\n {actionLabel}\n </Button>\n </div>\n);\n","import type { FC } from 'react';\nimport { Button } from '../button';\nimport { LoginActionStack, LoginAlert, LoginProgress } from './shared';\nimport type { LoginInvitationState } from './types';\n\nexport const LoginInvitation: FC<LoginInvitationState> = ({\n identity,\n inviterName,\n busy = false,\n error,\n acceptLabel = 'Accept invitation',\n busyLabel = 'Accepting invitation…',\n switchAccountLabel = 'Switch account',\n createAccountLabel = 'Create a new account',\n testId,\n acceptTestId,\n onAccept,\n onSwitchAccount,\n onCreateAccount,\n}) => (\n <div className='passflow-form' data-testid={testId} aria-busy={busy}>\n <div className='passflow-form-container passflow-login-screen-centered'>\n {inviterName ? (\n <p className='passflow-login-screen-text passflow-login-screen-centered-text'>\n <strong className='passflow-login-screen-app-name'>{inviterName}</strong> sent this invitation.\n </p>\n ) : null}\n <p className='passflow-login-screen-text passflow-login-screen-centered-text'>\n {identity ? (\n <>\n You're signed in as <strong className='passflow-login-screen-app-name'>{identity}</strong>.\n </>\n ) : (\n 'You’re already signed in.'\n )}\n </p>\n <p className='passflow-login-screen-hint'>Continue with this account, or switch accounts?</p>\n <LoginAlert message={error} />\n </div>\n {busy ? <LoginProgress message={busyLabel} /> : null}\n <LoginActionStack>\n <Button\n size='big'\n variant='primary'\n type='button'\n autoFocus={!busy}\n data-testid={acceptTestId}\n disabled={busy}\n onClick={onAccept}\n >\n {busy ? busyLabel : acceptLabel}\n </Button>\n <Button size='big' variant='outlined' type='button' disabled={busy} onClick={onSwitchAccount}>\n {switchAccountLabel}\n </Button>\n <Button size='big' variant='clean' type='button' disabled={busy} onClick={onCreateAccount}>\n {createAccountLabel}\n </Button>\n </LoginActionStack>\n </div>\n);\n","import type { FC } from 'react';\nimport { Button } from '../button';\nimport { Icon } from '../icon';\nimport { LoginAlert } from './shared';\nimport type { LoginPasskeyProgressState } from './types';\n\nexport const LoginPasskeyProgress: FC<LoginPasskeyProgressState> = ({\n working,\n message,\n actionLabel = 'Continue with a passkey',\n error,\n recoverable = false,\n retryLabel = 'Try again',\n testId,\n onAction,\n onRetry,\n}) => (\n <div className='passflow-form' data-testid={testId}>\n <div className='passflow-form-container passflow-login-screen-centered'>\n <div className='passflow-login-screen-status' role='status'>\n {working ? <div className='passflow-login-screen-spinner' aria-hidden='true' /> : null}\n <p className='passflow-login-screen-text'>{message}</p>\n </div>\n <LoginAlert message={error} />\n </div>\n {!working && onAction ? (\n <Button size='big' variant='dark' type='button' className='passflow-button-passkey' withIcon onClick={onAction}>\n <Icon id='key' size='small' type='general' className='icon-white passflow-button-passkey-icon' decorative />\n {actionLabel}\n </Button>\n ) : !working && error && recoverable && onRetry ? (\n <Button size='big' variant='dark' type='button' className='passflow-button-passkey' withIcon onClick={onRetry}>\n <Icon id='key' size='small' type='general' className='icon-white passflow-button-passkey-icon' decorative />\n {retryLabel}\n </Button>\n ) : null}\n </div>\n);\n","import type { FC, FormEvent } from 'react';\nimport { useState } from 'react';\nimport { Button } from '../button';\nimport { FieldText } from '../fields/field-text';\nimport { LoginAlert, LoginProgress } from './shared';\nimport type { LoginSecondFactorMethod, LoginSecondFactorState } from './types';\n\n/** The words for each factor, matching the sign-in's own two-factor screens. */\nconst METHOD_COPY: Record<LoginSecondFactorMethod, { label: string; hint: string; switchLabel: string }> = {\n totp: {\n label: 'Authenticator code',\n hint: 'Enter the 6-digit code from your authenticator app.',\n switchLabel: 'Use authenticator app',\n },\n recovery_codes: {\n label: 'Recovery code',\n hint: 'Enter one of your recovery codes.',\n switchLabel: 'Use recovery code',\n },\n};\n\nexport const LoginSecondFactor: FC<LoginSecondFactorState> = ({\n methods,\n identity,\n busy = false,\n error,\n submitLabel = 'Verify',\n testId,\n onSubmit,\n onMethodChange,\n}) => {\n const [method, setMethod] = useState<LoginSecondFactorMethod>(methods[0] ?? 'totp');\n const [code, setCode] = useState('');\n const alternate = methods.find((m) => m !== method);\n const copy = METHOD_COPY[method];\n const isTOTP = method === 'totp';\n\n const handleSubmit = (event: FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n const normalizedCode = code.trim();\n if (normalizedCode) onSubmit(method, normalizedCode);\n };\n\n const switchTo = (next: LoginSecondFactorMethod) => {\n setMethod(next);\n setCode('');\n onMethodChange?.();\n };\n\n return (\n <form className='passflow-form' data-testid={testId} aria-busy={busy} onSubmit={handleSubmit}>\n <div className='passflow-form-container'>\n {identity ? (\n <p className='passflow-login-screen-hint'>\n Signed in as <strong className='passflow-login-screen-app-name'>{identity}</strong>.\n </p>\n ) : null}\n <div className='passflow-form-field'>\n <div className='passflow-form-field__header'>\n <label htmlFor='second-factor-code' className='passflow-field-label'>\n {copy.label}\n </label>\n {alternate ? (\n <Button\n size='small'\n variant='clean'\n type='button'\n className='passflow-field-label-button'\n disabled={busy}\n onClick={() => switchTo(alternate)}\n >\n {METHOD_COPY[alternate].switchLabel}\n </Button>\n ) : null}\n </div>\n <FieldText\n id='second-factor-code'\n name={isTOTP ? 'otp' : 'recovery_code'}\n type='text'\n autoComplete={isTOTP ? 'one-time-code' : 'off'}\n autoCapitalize={isTOTP ? 'off' : 'characters'}\n autoCorrect='off'\n spellCheck={false}\n inputMode={isTOTP ? 'numeric' : 'text'}\n autoFocus\n className='passflow-login-screen-code-input'\n value={code}\n disabled={busy}\n aria-invalid={Boolean(error)}\n aria-describedby={error ? 'second-factor-code-error' : 'second-factor-code-hint'}\n isError={Boolean(error)}\n onChange={(event) => setCode(event.target.value)}\n />\n <p id='second-factor-code-hint' className='passflow-login-screen-hint'>\n {copy.hint}\n </p>\n </div>\n <LoginAlert id='second-factor-code-error' message={error} />\n </div>\n {busy ? <LoginProgress message='Checking the code…' /> : null}\n <Button size='big' variant='primary' type='submit' disabled={busy || code.trim().length === 0}>\n {busy ? 'Checking…' : submitLabel}\n </Button>\n </form>\n );\n};\n","import type { FC, PropsWithChildren } from 'react';\nimport { cn } from '@/utils';\nimport { Icon } from '../icon';\nimport '@/styles/index.css';\nimport './login-screen.css';\n\nexport type LoginScreenShellProps = PropsWithChildren & {\n iconId?: string;\n title?: string;\n subtitle?: string;\n className?: string;\n customCss?: string;\n customLogo?: string;\n customLogoAlt?: string;\n removeBranding?: boolean;\n};\n\nexport const LoginScreenShell: FC<LoginScreenShellProps> = ({\n iconId = 'logo',\n title = '',\n subtitle = '',\n className = '',\n children,\n customCss,\n customLogo,\n customLogoAlt = 'Application logo',\n removeBranding = false,\n}) => (\n <div id='passflow-wrapper' className='passflow-wrapper'>\n {/*\n * The app's custom CSS (login theme `custom_css`), rendered inline as the\n * last layer so it overrides the kit's styles. Only when there is some.\n */}\n {customCss ? (\n <style className='psfw-custom-styles' data-passflow-style-layer='custom'>\n {customCss}\n </style>\n ) : null}\n <main className={cn('passflow-form-main-wrapper', className)}>\n <div className='passflow-form-main-container'>\n {customLogo ? (\n <img src={customLogo} alt={customLogoAlt} className='passflow-form-main-container-logo' />\n ) : (\n <Icon id={iconId} size='large' type='general' decorative />\n )}\n {title ? (\n <div className='passflow-form-header'>\n <h1 className='passflow-form-title'>{title}</h1>\n {subtitle ? <span className='passflow-form-subtitle'>{subtitle}</span> : null}\n </div>\n ) : null}\n </div>\n {children}\n </main>\n {!removeBranding ? (\n <footer className='passflow-branding'>\n <p className='passflow-branding-text'>\n Secured by <span className='passflow-branding-text-secondary passflow-secondary-font'>PASSFLOW</span>\n </p>\n </footer>\n ) : null}\n </div>\n);\n","import type { FC } from 'react';\nimport { Button } from '../button';\nimport { Icon } from '../icon';\nimport { LoginAlert } from './shared';\nimport type { LoginStatusState } from './types';\n\nexport const LoginStatus: FC<LoginStatusState> = ({\n tone,\n message,\n detail,\n recoverable = false,\n retryLabel = 'Try again',\n testId,\n onRetry,\n primaryAction,\n}) => (\n <div className='passflow-form' data-testid={testId}>\n <div className='passflow-form-container passflow-login-screen-centered'>\n {tone === 'success' ? (\n <div className='passflow-login-screen-success' role='status'>\n <Icon size='small' id='check' type='general' className='icon-success' decorative />\n <span className='passflow-login-screen-success-text'>{message}</span>\n </div>\n ) : (\n <LoginAlert message={message} />\n )}\n {detail ? <p className='passflow-login-screen-hint'>{detail}</p> : null}\n </div>\n {primaryAction ? (\n <Button size='big' variant='primary' type='button' onClick={primaryAction.onClick}>\n {primaryAction.label}\n </Button>\n ) : tone === 'error' && recoverable && onRetry ? (\n <Button size='big' variant='primary' type='button' onClick={onRetry}>\n {retryLabel}\n </Button>\n ) : null}\n </div>\n);\n","import type { FC } from 'react';\nimport { LoginCodeEntry } from './code-entry';\nimport { LoginConsent } from './consent';\nimport { LoginCredentials } from './credentials';\nimport { LoginDeviceApproval } from './device-approval';\nimport { LoginGeneralError } from './general-error';\nimport { LoginInvitation } from './invitation';\nimport { LoginPasskeyProgress } from './passkey-progress';\nimport { LoginSecondFactor } from './second-factor';\nimport { LoginScreenShell } from './shell';\nimport { LoginStatus } from './status';\nimport type { LoginScreenProps } from './types';\n\nexport const LoginScreen: FC<LoginScreenProps> = ({ chrome, state }) => {\n const content = (() => {\n switch (state.kind) {\n case 'credentials':\n return <LoginCredentials {...state} />;\n case 'code-entry':\n return <LoginCodeEntry {...state} />;\n case 'passkey-progress':\n return <LoginPasskeyProgress {...state} />;\n case 'device-approval':\n return <LoginDeviceApproval {...state} />;\n case 'second-factor':\n return <LoginSecondFactor {...state} />;\n case 'invitation':\n return <LoginInvitation {...state} />;\n case 'general-error':\n return <LoginGeneralError {...state} />;\n case 'consent':\n return <LoginConsent {...state} />;\n case 'status':\n return <LoginStatus {...state} />;\n }\n })();\n const isError = state.kind === 'general-error' || (state.kind === 'status' && state.tone === 'error');\n const className =\n state.kind === 'general-error'\n ? 'passflow-error-wrapper'\n : chrome.variant === 'sign-in'\n ? 'passflow-signin-wrapper'\n : undefined;\n\n return (\n <LoginScreenShell\n iconId={isError ? 'logo-red' : 'logo'}\n title={chrome.title}\n subtitle={chrome.subtitle}\n className={className}\n customCss={chrome.customCss}\n customLogo={chrome.customLogo}\n customLogoAlt={chrome.customLogoAlt}\n removeBranding={chrome.removeBranding}\n >\n {content}\n </LoginScreenShell>\n );\n};\n","import * as PopoverPrimitive from '@radix-ui/react-popover';\nimport { type ComponentPropsWithoutRef, type ElementRef, forwardRef } from 'react';\nimport { cn } from '@/utils';\n\nconst Popover = PopoverPrimitive.Root;\n\nconst PopoverTrigger = PopoverPrimitive.Trigger;\n\nconst PopoverAnchor = PopoverPrimitive.Anchor;\n\nconst PopoverContent = forwardRef<\n ElementRef<typeof PopoverPrimitive.Content>,\n ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>\n>(({ className, align = 'center', sideOffset = 4, ...props }, ref) => (\n <PopoverPrimitive.Portal>\n <PopoverPrimitive.Content\n ref={ref}\n align={align}\n sideOffset={sideOffset}\n className={cn('passflow-popover-content', className)}\n {...props}\n />\n </PopoverPrimitive.Portal>\n));\nPopoverContent.displayName = PopoverPrimitive.Content.displayName;\n\nexport { Popover, PopoverAnchor, PopoverContent, PopoverTrigger };\n","import type { FC } from 'react';\nimport { cn } from '@/utils';\nimport './spinner.css';\n\nexport type SpinnerSize = 'small' | 'medium';\n\nexport type SpinnerProps = {\n /** `small` sits inline beside a line of text; `medium` stands alone. */\n size?: SpinnerSize;\n /**\n * The accessible name. Omit it when a sibling already announces the busy\n * state — the ring is then decorative and hidden from assistive technology,\n * which is what a status region with its own live text wants.\n */\n label?: string;\n};\n\n/**\n * The indeterminate activity ring.\n *\n * It exists as a primitive so its diameter and stroke live in one place rather\n * than in each consuming component's stylesheet. The upgrade dialog uses it;\n * the login screen still draws its own identical ring in\n * `login-screen.css` and should be migrated onto this when that file is next\n * touched.\n */\nexport const Spinner: FC<SpinnerProps> = ({ size = 'medium', label }) => (\n <span\n className={cn('passflow-spinner', { 'passflow-spinner--small': size === 'small' })}\n role={label === undefined ? undefined : 'status'}\n aria-label={label}\n aria-hidden={label === undefined ? true : undefined}\n />\n);\n","import type { FC } from 'react';\nimport { Button } from '../button';\nimport type { UpgradeDialogFactor, UpgradeFactorType } from './types';\n\ntype UpgradeFactorListProps = {\n factors: readonly UpgradeDialogFactor[];\n selected: UpgradeFactorType;\n disabled?: boolean;\n label?: string;\n onSelect: (factor: UpgradeFactorType) => void;\n};\n\n/**\n * The \"use another way\" alternatives. Selecting one reports the user's choice;\n * it never navigates.\n *\n * Each row is `Button variant='option'`: the two-line geometry and the pressed\n * look belong to that variant in the button library, not to this list. The list\n * contributes layout only.\n */\nexport const UpgradeFactorList: FC<UpgradeFactorListProps> = ({\n factors,\n selected,\n disabled = false,\n label = 'Other verification methods',\n onSelect,\n}) => (\n <ul className='passflow-upgrade-dialog__alternatives' aria-label={label}>\n {factors.map((factor) => (\n <li key={factor.type} className='passflow-upgrade-dialog__alternative'>\n <Button\n size='big'\n variant='option'\n type='button'\n disabled={disabled}\n pressed={factor.type === selected}\n description={factor.hint}\n data-testid={`upgrade-dialog-factor-${factor.type}`}\n onClick={() => onSelect(factor.type)}\n >\n {factor.label}\n </Button>\n </li>\n ))}\n </ul>\n);\n","import { type FC, type FormEvent, useRef, useState } from 'react';\nimport { Button } from '../button';\nimport { FieldText } from '../fields/field-text';\nimport { LoginAlert } from '../login-screen';\nimport { UpgradeFactorList } from './factor-list';\nimport type { UpgradeDialogChallengeState, UpgradeFactorType } from './types';\n\nconst CODE_FIELD_ID = 'passflow-upgrade-code';\nconst CODE_ERROR_ID = 'passflow-upgrade-code-error';\n\n/**\n * The collecting view: the suggested factor, its input affordance, the\n * alternatives toggle, and the two terminal controls.\n *\n * Selection is reported through `onSelectFactor` before `onSubmit` ever fires —\n * architecture §13.2's late-join boundary is factor selection, not submission,\n * so the controller must learn of the choice while the user is still typing.\n */\nexport const UpgradeChallengeView: FC<UpgradeDialogChallengeState> = ({\n factors,\n selected,\n busy = false,\n error,\n showAlternatives = false,\n submitLabel = 'Verify',\n cancelLabel = 'Cancel',\n alternativesLabel = 'Use another way',\n testId,\n onSelectFactor,\n onToggleAlternatives,\n onSubmit,\n onCancel,\n}) => {\n const [code, setCode] = useState('');\n const reported = useRef<UpgradeFactorType | null>(null);\n\n const active = factors.find((factor) => factor.type === selected) ?? factors[0];\n // The code contract travels WITH the factor (§H12): length, charset and\n // autofill are the factor's own statement, never this component's guess. A\n // six-character cap applied to every factor truncated a 12-character recovery\n // code into a guaranteed rejection.\n const codeContract = active?.input === 'code' ? active.code : undefined;\n const needsCode = codeContract !== undefined;\n const hasAlternatives = factors.length > 1;\n\n const report = (factor: UpgradeFactorType) => {\n if (reported.current === factor) return;\n reported.current = factor;\n onSelectFactor(factor);\n };\n\n const choose = (factor: UpgradeFactorType) => {\n setCode('');\n report(factor);\n };\n\n const handleSubmit = (event: FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n if (!active) return;\n const trimmed = code.trim();\n if (needsCode && trimmed.length === 0) return;\n report(active.type);\n onSubmit(needsCode ? trimmed : undefined);\n };\n\n return (\n <form className='passflow-upgrade-dialog__form' data-testid={testId} aria-busy={busy} onSubmit={handleSubmit} noValidate>\n {active ? (\n <div className='passflow-upgrade-dialog__factor'>\n <span className='passflow-upgrade-dialog__factor-label'>{active.label}</span>\n {active.hint ? <span className='passflow-upgrade-dialog__factor-hint'>{active.hint}</span> : null}\n </div>\n ) : null}\n\n {codeContract ? (\n <div className='passflow-upgrade-dialog__field'>\n <label htmlFor={CODE_FIELD_ID} className='passflow-field-label'>\n Verification code\n </label>\n <FieldText\n id={CODE_FIELD_ID}\n name='upgrade_code'\n type='text'\n inputMode={codeContract.inputMode}\n autoComplete={codeContract.autoComplete}\n autoCorrect='off'\n autoCapitalize={codeContract.autoCapitalize}\n spellCheck={false}\n maxLength={codeContract.maxLength}\n value={code}\n disabled={busy}\n isError={Boolean(error)}\n aria-invalid={Boolean(error)}\n aria-describedby={error ? CODE_ERROR_ID : undefined}\n data-testid='upgrade-dialog-code'\n onChange={(event) => setCode(event.target.value)}\n />\n </div>\n ) : null}\n\n <LoginAlert id={CODE_ERROR_ID} message={error} />\n\n <div className='passflow-upgrade-dialog__actions'>\n <Button\n size='big'\n variant='primary'\n type='submit'\n disabled={busy || !active || (needsCode && code.trim().length === 0)}\n data-testid='upgrade-dialog-submit'\n >\n {busy ? 'Verifying…' : submitLabel}\n </Button>\n {hasAlternatives ? (\n <Button\n size='big'\n variant='clean'\n type='button'\n disabled={busy}\n aria-expanded={showAlternatives}\n data-testid='upgrade-dialog-alternatives'\n onClick={onToggleAlternatives}\n >\n {alternativesLabel}\n </Button>\n ) : null}\n {showAlternatives && hasAlternatives ? (\n <UpgradeFactorList factors={factors} selected={selected} disabled={busy} onSelect={choose} />\n ) : null}\n <Button size='big' variant='clean' type='button' data-testid='upgrade-dialog-cancel' onClick={onCancel}>\n {cancelLabel}\n </Button>\n </div>\n </form>\n );\n};\n","/**\n * Pure mapping from the controller's prompt request plus local UI state to the\n * dialog's rendering union. No React, no DOM, no styling — architecture §10.2\n * classifies this as non-visual state mapping, which is why it is the one file\n * in this folder a Vitest spec may cover.\n *\n * The inputs are declared structurally — `UpgradePromptSnapshot` is the shape of\n * `UpgradePromptRequest` that the dialog actually reads — but the one judgement\n * that is NOT structural is which kind of failure an error is: that belongs to\n * `@passflow/core`, which raises the errors, and is imported from it.\n */\n\nimport { classifyUpgradeError, type UpgradeErrorKind } from '@passflow/core';\nimport type {\n AssuranceBar,\n UpgradeDialogFactor,\n UpgradeDialogState,\n UpgradeFactorCodeContract,\n UpgradeFactorInput,\n UpgradeFactorType,\n} from './types';\n\nexport type UpgradeChallengeSnapshot = {\n requiredLevel?: number;\n acrValues?: string;\n maxAge?: number;\n};\n\nexport type UpgradeFactorSnapshot = {\n type: UpgradeFactorType;\n input: UpgradeFactorInput;\n};\n\nexport type UpgradePromptSnapshot = {\n challenge: UpgradeChallengeSnapshot;\n /** Already ranked by `selectFactors`; index 0 is the suggested factor. */\n factors: readonly UpgradeFactorSnapshot[];\n previousError?: unknown;\n};\n\nexport type UpgradeDialogLabels = Partial<Record<UpgradeFactorType, { label: string; hint?: string }>>;\n\n/** How the flight ended, as the controller's outcome summary reports it (§13.4). */\nexport type UpgradeDialogOutcome =\n | { kind: 'elevated' }\n | { kind: 'insufficient'; obtained: AssuranceBar; required: AssuranceBar }\n | { kind: 'cancelled' }\n | { kind: 'failed'; error: unknown };\n\nexport type UpgradeDialogUiState = {\n selected?: UpgradeFactorType | null;\n busy?: boolean;\n showAlternatives?: boolean;\n};\n\nexport type UpgradeDialogHandlers = {\n onSelectFactor: (factor: UpgradeFactorType) => void;\n onToggleAlternatives: () => void;\n onSubmit: (code?: string) => void;\n onCancel: () => void;\n onDismiss: () => void;\n onRetry?: () => void;\n};\n\nexport type ToDialogStateInput = {\n prompt: UpgradePromptSnapshot | null;\n outcome?: UpgradeDialogOutcome;\n ui?: UpgradeDialogUiState;\n labels?: UpgradeDialogLabels;\n handlers: UpgradeDialogHandlers;\n testId?: string;\n};\n\n/**\n * How an elevation failure reads to the user. `rejected` is the retryable\n * wrong-answer case, which keeps the dialog open on the challenge.\n */\nexport type UpgradeDialogErrorKind =\n | 'rejected'\n | 'cancelled'\n | 'exhausted'\n | 'unsatisfiable'\n | 'unavailable'\n | 'transport'\n | 'insufficient'\n | 'session-changed';\n\nexport const DEFAULT_FACTOR_LABELS: Record<UpgradeFactorType, { label: string; hint?: string }> = {\n totp: { label: 'Authenticator app', hint: 'Enter the code from your authenticator app' },\n passkey: { label: 'Passkey', hint: 'Confirm with your device' },\n recovery_codes: { label: 'Recovery code', hint: 'Enter one of your single-use recovery codes' },\n email_otp: { label: 'Email code', hint: 'Enter the code we emailed you' },\n sms_otp: { label: 'SMS code', hint: 'Enter the code we texted you' },\n};\n\nconst CHALLENGE_REASON = 'This action needs extra verification';\n\n/** A six-digit numeric one-time code — TOTP and the two OTP transports. */\nconst OTP_CODE_CONTRACT: UpgradeFactorCodeContract = Object.freeze({\n maxLength: 6,\n inputMode: 'numeric',\n autoComplete: 'one-time-code',\n autoCapitalize: 'off',\n});\n\n/**\n * Per-factor code contracts, keyed by the factor type, which is the only thing\n * about a factor the protocol guarantees.\n *\n * `recovery_codes` is the reason this table exists. The server generates them\n * at `DefaultRecoveryCodeLength` (12) from a 32-character alphanumeric charset\n * and accepts a configured length anywhere in 6..16, so the cap is the server's\n * MAXIMUM — capping at the default would reject a valid code on a deployment\n * that raised it, and capping at six (the old single hardcoded number) rejected\n * every code on every deployment. A shorter configured code simply types\n * shorter; a cap can only ever do harm by being too small.\n *\n * `null` means the factor collects nothing typed: its proof comes from the\n * ceremony, so there is no field and no contract to state.\n */\nexport const UPGRADE_FACTOR_CODE_CONTRACTS: Readonly<{\n totp: UpgradeFactorCodeContract;\n email_otp: UpgradeFactorCodeContract;\n sms_otp: UpgradeFactorCodeContract;\n recovery_codes: UpgradeFactorCodeContract;\n passkey: null;\n}> = Object.freeze({\n totp: OTP_CODE_CONTRACT,\n email_otp: OTP_CODE_CONTRACT,\n sms_otp: OTP_CODE_CONTRACT,\n recovery_codes: Object.freeze({\n maxLength: 16,\n inputMode: 'text',\n autoComplete: 'off',\n autoCapitalize: 'characters',\n }),\n passkey: null,\n});\n\n/**\n * The contract for a factor that collects a typed answer. A `'code'` factor the\n * table has no entry for falls back to the OTP shape rather than to no cap at\n * all, so an unknown future code factor is merely sub-optimal, never broken.\n */\nconst codeContractFor = (type: UpgradeFactorType): UpgradeFactorCodeContract =>\n UPGRADE_FACTOR_CODE_CONTRACTS[type] ?? OTP_CODE_CONTRACT;\n\n/** Index 0 stays index 0: `selectFactors` already ranked the list, and ranking is not filtering. */\nexport const toDialogFactors = (\n factors: readonly UpgradeFactorSnapshot[],\n labels?: UpgradeDialogLabels,\n): UpgradeDialogFactor[] =>\n factors.map((factor) => {\n const fallback = DEFAULT_FACTOR_LABELS[factor.type];\n const override = labels?.[factor.type];\n const base = {\n type: factor.type,\n label: override?.label ?? fallback.label,\n hint: override?.hint ?? fallback.hint,\n };\n return factor.input === 'code'\n ? { ...base, input: 'code' as const, code: codeContractFor(factor.type) }\n : { ...base, input: 'none' as const };\n });\n\nconst readString = (value: unknown): string | undefined => (typeof value === 'string' && value ? value : undefined);\n\nconst readRecord = (value: unknown): Record<string, unknown> | undefined =>\n typeof value === 'object' && value !== null ? (value as Record<string, unknown>) : undefined;\n\n/**\n * Every kind `@passflow/core` can classify, mapped to the panel the user sees.\n *\n * **This table is the fix for PFL-497's headline defect, and its totality is\n * the mechanism.** The previous version read `code` first, and since every\n * classified transport failure carries the same fixed literal\n * `code === 'upgrade_transport'`, that catch-all swallowed the kinds with their\n * own route — a mistyped code (`wrong_code`, retryable) landed on a terminal\n * panel. Routing by `kind` through a `Record<UpgradeErrorKind, …>` makes the\n * catch-all unnecessary and a missing route a TYPE error: a new kind added to\n * core cannot compile here until someone decides where it goes.\n *\n * `attempts_exhausted` is terminal (H3). It is the controller's local attempt\n * budget being spent, so the challenge the server holds will never be accepted\n * again; routing it with the retryable kinds re-prompted forever. It shares the\n * `exhausted` panel with the server's own `challenge_too_many_attempts`, which\n * is the same row of §13.3's settlement table.\n */\nconst DIALOG_KIND_BY_UPGRADE_KIND: Readonly<Record<UpgradeErrorKind, UpgradeDialogErrorKind>> = Object.freeze({\n // Retryable: the user answers again, the prompt stays open (§3.3, §13.3).\n wrong_code: 'rejected',\n challenge_spent: 'rejected',\n not_registered: 'rejected',\n prepare_not_required: 'rejected',\n // Terminal.\n exhausted: 'exhausted',\n attempts_exhausted: 'exhausted',\n unavailable: 'unavailable',\n session_changed: 'session-changed',\n fatal: 'transport',\n protocol: 'transport',\n network: 'transport',\n});\n\nconst isUpgradeErrorKind = (value: string | undefined): value is UpgradeErrorKind =>\n value !== undefined && Object.hasOwn(DIALOG_KIND_BY_UPGRADE_KIND, value);\n\n/**\n * Whether the value carries enough HTTP fact for core's classifier to say\n * anything at all. Without one of these, `classifyUpgradeError` would read the\n * value as a network failure, so a stray non-protocol object would be reported\n * to the user as a transport outcome it has no evidence for.\n */\nconst hasTransportFacts = (record: Record<string, unknown>): boolean =>\n typeof record.status === 'number' || typeof record.id === 'string' || readRecord(record.response) !== undefined;\n\n/**\n * The kind, as core determines it. The dialog states no kinds of its own.\n *\n * The already-tagged `kind` is read FIRST, and that order is load-bearing:\n * `classifyUpgradeError` passes a `UpgradeTransportError` through by\n * `instanceof`, which fails across a duplicated bundle or a structured clone,\n * and re-classifying an already-classified error by its bare status re-buckets\n * a `wrong_code` 401 into `session_changed`. The string is validated against\n * the route table, so a kind core does not know still falls through to the\n * classifier.\n */\nconst upgradeKindOf = (error: unknown, record: Record<string, unknown>): UpgradeErrorKind | undefined => {\n const tagged = readString(record.kind);\n if (isUpgradeErrorKind(tagged)) return tagged;\n if (!hasTransportFacts(record)) return undefined;\n // `'refresh'` is the commit round: the dialog only ever sees a failure that\n // already travelled through a flight, and the one round-dependent id\n // (`token.invalid`) means a session change there, which is the terminal\n // reading and the safe one for an un-tagged error.\n return classifyUpgradeError(error, 'refresh').kind;\n};\n\n/**\n * How a failure reads to the user, as the dialog's own vocabulary.\n *\n * Named `dialogOutcomeFromError`, not `classifyUpgradeError`: that name belongs\n * to `@passflow/core`, and holding it here shadowed core's symbol in the\n * package's own star exports, which made the real classifier unreachable to\n * consumers. This function decides nothing about what the error IS — core's\n * classifier does — only which panel that kind is shown on.\n *\n * The dedicated error classes are matched before the kind table because they\n * are not transport failures at all: they carry no `kind`, and core's\n * classifier has nothing to say about them.\n */\nexport const dialogOutcomeFromError = (error: unknown): UpgradeDialogErrorKind => {\n const record = readRecord(error);\n if (!record) return 'rejected';\n const code = readString(record.code);\n const name = readString(record.name);\n\n if (code === 'upgrade_cancelled' || name === 'UpgradeCancelledError' || record.cancelled === true) return 'cancelled';\n if (code === 'upgrade_unsatisfiable' || name === 'UpgradeUnsatisfiableError') return 'unsatisfiable';\n if (code === 'upgrade_unavailable' || name === 'UpgradeUnavailableError') return 'unavailable';\n if (code === 'upgrade_exhausted' || name === 'UpgradeExhaustedError') return 'exhausted';\n if (code === 'upgrade_insufficient' || name === 'UpgradeInsufficientError') return 'insufficient';\n if (code === 'upgrade_session_changed' || name === 'UpgradeSessionChangedError') return 'session-changed';\n\n const kind = upgradeKindOf(error, record);\n // Nothing identifiable: keep the prompt open rather than inventing a terminal\n // outcome. The controller's attempt budget bounds the re-prompting.\n return kind === undefined ? 'rejected' : DIALOG_KIND_BY_UPGRADE_KIND[kind];\n};\n\nexport const readAssuranceBar = (value: unknown): AssuranceBar | undefined => {\n const record = readRecord(value);\n if (!record) return undefined;\n const bar: AssuranceBar = {};\n if (typeof record.acrValues === 'string') bar.acrValues = record.acrValues;\n if (typeof record.level === 'number') bar.level = record.level;\n if (typeof record.maxAge === 'number') bar.maxAge = record.maxAge;\n return bar.acrValues === undefined && bar.level === undefined && bar.maxAge === undefined ? undefined : bar;\n};\n\n/** Human wording for a bar, on whichever axis it constrains. */\nexport const describeAssuranceBar = (bar?: AssuranceBar): string => {\n if (!bar) return 'an unknown level';\n const parts: string[] = [];\n if (bar.level !== undefined) parts.push(`AAL${bar.level}`);\n else if (bar.acrValues) parts.push(`acr ${bar.acrValues}`);\n if (bar.maxAge !== undefined) parts.push(`verified within ${bar.maxAge}s`);\n return parts.length > 0 ? parts.join(', ') : 'an unknown level';\n};\n\nconst challengeBar = (challenge: UpgradeChallengeSnapshot): AssuranceBar | undefined =>\n readAssuranceBar({\n acrValues: challenge.acrValues,\n level: challenge.requiredLevel,\n maxAge: challenge.maxAge,\n });\n\nconst errorMessage = (error: unknown, fallback: string): string => {\n const record = readRecord(error);\n return readString(record?.message) ?? fallback;\n};\n\nconst terminalFromError = (input: ToDialogStateInput, error: unknown): UpgradeDialogState => {\n const { handlers, testId } = input;\n switch (dialogOutcomeFromError(error)) {\n case 'cancelled':\n return {\n kind: 'cancelled',\n message: 'Verification cancelled',\n detail: 'The action that needed extra verification was not completed.',\n testId,\n onDismiss: handlers.onDismiss,\n };\n case 'exhausted':\n return {\n kind: 'exhausted',\n message: 'Too many attempts',\n detail: errorMessage(error, 'No attempts are left for this verification. Start the action again to retry.'),\n testId,\n onDismiss: handlers.onDismiss,\n };\n case 'unsatisfiable':\n return {\n kind: 'unsatisfiable',\n message: 'No usable verification method',\n detail: errorMessage(error, 'None of your verification methods can answer this request.'),\n required: input.prompt ? challengeBar(input.prompt.challenge) : undefined,\n testId,\n onDismiss: handlers.onDismiss,\n };\n case 'unavailable':\n return {\n kind: 'unavailable',\n message: 'Verification is unavailable',\n detail: errorMessage(error, 'This deployment cannot raise your assurance level right now.'),\n testId,\n onDismiss: handlers.onDismiss,\n };\n case 'session-changed':\n return {\n kind: 'cancelled',\n message: 'Verification stopped',\n detail: errorMessage(error, 'Your session changed while verifying, so the request was abandoned.'),\n testId,\n onDismiss: handlers.onDismiss,\n };\n case 'insufficient': {\n const record = readRecord(error);\n return {\n kind: 'insufficient',\n message: errorMessage(error, 'Verified, but not enough for this action'),\n obtained: readAssuranceBar(record?.obtained) ?? {},\n required: readAssuranceBar(record?.required) ?? {},\n testId,\n onDismiss: handlers.onDismiss,\n };\n }\n default:\n return {\n kind: 'transport',\n message: 'Verification could not be completed',\n detail: errorMessage(error, 'The verification request failed before it reached the server.'),\n retryable: readRecord(error)?.retryable === true,\n testId,\n onRetry: handlers.onRetry,\n onDismiss: handlers.onDismiss,\n };\n }\n};\n\n/**\n * The single projection. A terminal `outcome` always wins over an open prompt;\n * an empty offered factor list is the `no usable factor` outcome; a `busy`\n * ceremony with no code to type is `working`; everything else is the challenge.\n */\nexport const toDialogState = (input: ToDialogStateInput): UpgradeDialogState => {\n const { prompt, outcome, ui, labels, handlers, testId } = input;\n\n if (outcome) {\n switch (outcome.kind) {\n case 'elevated':\n return {\n kind: 'success',\n message: 'Verification complete',\n detail: 'Your request is continuing.',\n testId,\n // The happy path must clear itself: §13.4's \"reports success and\n // closes\". Without this the modal's focus trap covers the app after\n // every elevation.\n onDismiss: handlers.onDismiss,\n };\n case 'insufficient':\n return {\n kind: 'insufficient',\n message: `Verified to ${describeAssuranceBar(outcome.obtained)}; this action requires ${describeAssuranceBar(outcome.required)}`,\n obtained: outcome.obtained,\n required: outcome.required,\n detail: 'The elevation succeeded but the action was challenged again. Nothing was completed.',\n testId,\n onDismiss: handlers.onDismiss,\n };\n case 'cancelled':\n return {\n kind: 'cancelled',\n message: 'Verification cancelled',\n detail: 'The action that needed extra verification was not completed.',\n testId,\n onDismiss: handlers.onDismiss,\n };\n default:\n return terminalFromError(input, outcome.error);\n }\n }\n\n if (!prompt) {\n return {\n kind: 'working',\n message: 'Preparing verification…',\n testId,\n onCancel: handlers.onCancel,\n };\n }\n\n const previousKind = prompt.previousError === undefined ? undefined : dialogOutcomeFromError(prompt.previousError);\n if (previousKind !== undefined && previousKind !== 'rejected') {\n return terminalFromError(input, prompt.previousError);\n }\n\n const factors = toDialogFactors(prompt.factors, labels);\n const required = challengeBar(prompt.challenge);\n const suggested = factors[0];\n\n if (suggested === undefined) {\n return {\n kind: 'unsatisfiable',\n message: 'No usable verification method',\n detail: `This action requires ${describeAssuranceBar(required)}, and no verification method is available to answer it.`,\n required,\n testId,\n onDismiss: handlers.onDismiss,\n };\n }\n\n const selected = factors.find((factor) => factor.type === ui?.selected)?.type ?? suggested.type;\n const active = factors.find((factor) => factor.type === selected);\n const busy = ui?.busy === true;\n\n if (busy && active?.input === 'none') {\n return {\n kind: 'working',\n message: 'Waiting for your passkey…',\n detail: 'Follow the prompt from your device to confirm it is you.',\n testId,\n onCancel: handlers.onCancel,\n };\n }\n\n return {\n kind: 'challenge',\n factors,\n selected,\n reason: CHALLENGE_REASON,\n busy,\n error: previousKind === 'rejected' ? errorMessage(prompt.previousError, 'That code was not accepted. Try again.') : null,\n showAlternatives: ui?.showAlternatives === true,\n testId,\n onSelectFactor: handlers.onSelectFactor,\n onToggleAlternatives: handlers.onToggleAlternatives,\n onSubmit: handlers.onSubmit,\n onCancel: handlers.onCancel,\n };\n};\n\n/**\n * What Escape and an overlay click mean in each state. Cancellation must reach\n * the controller or the caller's promise hangs (§8.1), so this is never a bare\n * close; `success` has nothing to cancel, so it closes instead of cancelling —\n * returning `undefined` there made Escape and the overlay inert on the one\n * state every user reaches.\n */\nexport const upgradeDialogDismissHandler = (state: UpgradeDialogState): (() => void) | undefined => {\n switch (state.kind) {\n case 'challenge':\n return state.onCancel;\n case 'working':\n return state.onCancel;\n default:\n return state.onDismiss;\n }\n};\n","import { type FC, useEffect } from 'react';\nimport { Button } from '../button';\nimport { Icon } from '../icon';\nimport { Spinner } from '../spinner';\nimport { describeAssuranceBar } from './state-mapping';\nimport type { AssuranceBar, UpgradeDialogState } from './types';\n\n/** Every state that is not the collecting challenge. */\nexport type UpgradeStatusState = Exclude<UpgradeDialogState, { kind: 'challenge' }>;\n\ntype Tone = 'working' | 'success' | 'problem' | 'neutral';\n\nconst TONE: Record<UpgradeStatusState['kind'], Tone> = {\n working: 'working',\n success: 'success',\n insufficient: 'problem',\n unsatisfiable: 'problem',\n unavailable: 'problem',\n exhausted: 'problem',\n transport: 'problem',\n cancelled: 'neutral',\n};\n\n/**\n * How long `success` stays on screen before it closes itself (§13.4: \"reports\n * success and closes\"). Long enough to be read, short enough that the app is\n * never held behind a modal the user cannot see a reason for.\n */\nexport const UPGRADE_SUCCESS_AUTO_CLOSE_MS = 1800;\n\nconst BarRow: FC<{ term: string; bar: AssuranceBar }> = ({ term, bar }) => (\n <div className='passflow-upgrade-dialog__bar'>\n <span className='passflow-upgrade-dialog__bar-term'>{term}</span>\n <span className='passflow-upgrade-dialog__bar-value'>{describeAssuranceBar(bar)}</span>\n </div>\n);\n\n/**\n * The non-collecting views: `working`, `success` and the six terminal outcomes\n * of §13.3's settlement table.\n *\n * `insufficient` is deliberately rendered in the problem tone with both bars\n * shown: the elevation succeeded and the action still did not, and the dialog\n * must not report success when the replay was re-challenged (§13.4).\n *\n * `success` owns its own exit: a Done control and an auto-close timer, both\n * calling the state's `onDismiss`. The affordance lives here rather than in the\n * provider because a modal that cannot be closed is a property of this\n * component, and the Storybook story for the state has to show the way out.\n */\nexport const UpgradeStatus: FC<UpgradeStatusState> = (state) => {\n const tone = TONE[state.kind];\n const { detail } = state;\n\n const autoClose = state.kind === 'success' ? (state.autoCloseMs ?? UPGRADE_SUCCESS_AUTO_CLOSE_MS) : 0;\n const autoDismiss = state.kind === 'success' ? state.onDismiss : undefined;\n\n useEffect(() => {\n if (autoDismiss === undefined || autoClose <= 0) return;\n const timer = setTimeout(autoDismiss, autoClose);\n return () => clearTimeout(timer);\n }, [autoClose, autoDismiss]);\n\n return (\n <div className='passflow-upgrade-dialog__status' data-testid={state.testId} data-upgrade-state={state.kind}>\n <div\n className={`passflow-upgrade-dialog__status-head passflow-upgrade-dialog__status-head--${tone}`}\n role={tone === 'problem' ? 'alert' : 'status'}\n aria-live={tone === 'problem' ? 'assertive' : 'polite'}\n >\n {tone === 'working' ? <Spinner size='small' /> : null}\n {tone === 'success' ? <Icon size='small' id='check' type='general' className='icon-success' decorative /> : null}\n {tone === 'problem' ? <Icon size='small' id='warning' type='general' className='icon-warning' decorative /> : null}\n <span className='passflow-upgrade-dialog__status-message'>{state.message}</span>\n </div>\n\n {detail ? <p className='passflow-upgrade-dialog__status-detail'>{detail}</p> : null}\n\n {state.kind === 'insufficient' ? (\n <div className='passflow-upgrade-dialog__bars' data-testid='upgrade-dialog-bars'>\n <BarRow term='Verified' bar={state.obtained} />\n <BarRow term='Required' bar={state.required} />\n </div>\n ) : null}\n\n {state.kind === 'unsatisfiable' && state.required ? (\n <div className='passflow-upgrade-dialog__bars' data-testid='upgrade-dialog-bars'>\n <BarRow term='Required' bar={state.required} />\n </div>\n ) : null}\n\n <div className='passflow-upgrade-dialog__actions'>\n {state.kind === 'transport' && state.retryable && state.onRetry ? (\n <Button size='big' variant='primary' type='button' data-testid='upgrade-dialog-retry' onClick={state.onRetry}>\n {state.retryLabel ?? 'Try again'}\n </Button>\n ) : null}\n {state.kind === 'working' && state.onCancel ? (\n <Button size='big' variant='clean' type='button' data-testid='upgrade-dialog-cancel' onClick={state.onCancel}>\n Cancel\n </Button>\n ) : null}\n {state.kind !== 'working' ? (\n <Button size='big' variant='clean' type='button' data-testid='upgrade-dialog-dismiss' onClick={state.onDismiss}>\n {state.dismissLabel ?? (state.kind === 'success' ? 'Done' : 'Close')}\n </Button>\n ) : null}\n </div>\n </div>\n );\n};\n","import type { FC } from 'react';\nimport { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from '../dialog';\nimport { UpgradeChallengeView } from './challenge';\nimport { upgradeDialogDismissHandler } from './state-mapping';\nimport { UpgradeStatus } from './status';\nimport type { UpgradeDialogProps } from './types';\nimport './upgrade-dialog.css';\n\nconst DESCRIPTION_ID = 'passflow-upgrade-dialog-description';\n\n/**\n * The assurance-upgrade modal. A switch over `state.kind`, modelled on\n * `LoginScreen`: one discriminated union, one view per state, no transitions of\n * its own.\n *\n * Escape and an overlay click route to the state's cancel or dismiss callback,\n * never to a bare close — cancellation must reach the controller or the\n * caller's promise never settles (§8.1).\n */\nexport const UpgradeDialog: FC<UpgradeDialogProps> = ({ open, title = 'Extra verification required', state }) => {\n const dismiss = upgradeDialogDismissHandler(state);\n const description = state.kind === 'challenge' ? state.reason : undefined;\n\n return (\n <Dialog\n open={open}\n onOpenChange={(next) => {\n if (!next) dismiss?.();\n }}\n >\n <DialogContent\n className='passflow-upgrade-dialog'\n data-testid='upgrade-dialog'\n aria-describedby={description ? DESCRIPTION_ID : undefined}\n >\n <DialogHeader className='passflow-upgrade-dialog__header'>\n <DialogTitle>{title}</DialogTitle>\n {description ? <DialogDescription id={DESCRIPTION_ID}>{description}</DialogDescription> : null}\n </DialogHeader>\n {state.kind === 'challenge' ? <UpgradeChallengeView {...state} /> : <UpgradeStatus {...state} />}\n </DialogContent>\n </Dialog>\n );\n};\n","import type { LoginScreenProps } from '@/components/ui';\nimport type { UseConsentProps } from '@/hooks/use-consent';\n\n/**\n * Maps consent state onto the shared LoginScreen. Pure — every visual decision\n * lives in LoginScreen, every protocol decision lives in useConsent, and this\n * file is only the translation between them.\n */\nexport const getConsentLoginScreenProps = (consent: UseConsentProps): LoginScreenProps | null => {\n if (consent.status === 'loading') return null;\n\n if (consent.status === 'invalid') {\n return {\n chrome: {\n title: consent.error?.message ?? 'Consent request unavailable',\n },\n state: {\n kind: 'general-error',\n message: consent.error?.message,\n detail: consent.error?.description,\n actionLabel: 'Back to login',\n testId: 'consent-invalid',\n onAction: () => {\n window.location.href = '/web';\n },\n },\n };\n }\n\n if (consent.status === 'redirecting') {\n return {\n chrome: {\n title: 'Taking you back',\n subtitle: `Returning you to ${consent.info?.app_name || 'the application'}.`,\n },\n state: {\n kind: 'status',\n tone: 'success',\n message: 'Decision recorded',\n detail: 'You can close this page if it does not continue on its own.',\n testId: 'consent-redirecting',\n },\n };\n }\n\n const info = consent.info;\n if (!info) return null;\n\n const appName = info.app_name || info.client_id;\n const busy = consent.status === 'working';\n\n return {\n chrome: {\n title: `Allow ${appName} to access your account?`,\n subtitle: 'Choose what this application may use, then allow or deny.',\n // The app's own logo replaces the Passflow mark, which is what makes this\n // read as \"THIS app is asking\" rather than a generic Passflow screen.\n customLogo: info.app_logo_url || undefined,\n customLogoAlt: `${appName} logo`,\n },\n state: {\n kind: 'consent',\n appName,\n scopes: info.requested_scopes.map((scope) => {\n const meta = consent.scopeMetadata(scope);\n return {\n scope,\n label: meta.label || scope,\n description: meta.description || undefined,\n granted: consent.grantedScopes.includes(scope),\n };\n }),\n busy,\n error: consent.error?.message,\n allowLabel: 'Allow',\n denyLabel: 'Deny',\n busyLabel: 'Submitting…',\n testId: 'consent-screen',\n allowTestId: 'consent-allow',\n denyTestId: 'consent-deny',\n appNameTestId: 'consent-app-name',\n onToggleScope: consent.toggleScope,\n onAllow: () => void consent.allow(),\n onDeny: () => void consent.deny(),\n },\n };\n};\n","import type { FC } from 'react';\nimport { LoginScreen } from '@/components/ui';\nimport { useConsent } from '@/hooks/use-consent';\nimport { getConsentLoginScreenProps } from './screen';\n\n/**\n * OIDC consent controller, mounted by the host app on `/web/consent`.\n *\n * Standalone by design: it needs no PassflowProvider. The staged request is\n * addressed by `parent_challenge_id` on the URL and read with a same-origin\n * cookie, so there is no SDK client, no app settings lookup, and no token to\n * hold — which is also why mounting it inside the provider would be actively\n * wrong, since the provider's session-exchange probe would fire against a\n * challenge that is waiting for a human decision.\n */\nexport const ConsentFlow: FC = () => {\n const consent = useConsent();\n const screen = getConsentLoginScreenProps(consent);\n\n return screen ? <LoginScreen {...screen} /> : null;\n};\n","import type { LoginMethodConfig, LoginScreenProps } from '@/components/ui';\nimport type { UseDeviceVerifyProps } from '@/hooks/use-device-verify';\nimport type { AuthUiError, DeviceError } from '@/types';\nimport { deviceErrorOfType } from '@/utils';\n\nconst getDeviceLoginMethods = (device: UseDeviceVerifyProps): LoginMethodConfig => ({\n identities: device.info?.methods.password\n ? [\n {\n id: 'email_or_username',\n label: 'Email',\n selectLabel: 'Use email',\n requiredMessage: 'Email is required',\n format: 'email',\n password: true,\n },\n ]\n : [],\n passkey: Boolean(device.info?.methods.passkey),\n providers: [],\n});\n\nconst toCredentialsError = (error: DeviceError | null): AuthUiError | null => {\n if (!error) return null;\n\n return {\n message: error.message,\n scope: error.type === 'bad_credentials' || error.type === 'missing_credentials' ? 'credentials' : 'form',\n };\n};\n\nconst deviceNotice = (device: UseDeviceVerifyProps) => {\n if (!device.info) return undefined;\n\n return {\n code: device.info.user_code,\n appName: device.info.app_name,\n message: \"requested this sign-in. Confirm that the code matches your terminal. If it doesn't, close this page.\",\n codeTestId: 'device-consent-user-code',\n appNameTestId: 'device-consent-app-name',\n };\n};\n\nexport const getDeviceLoginScreenProps = (device: UseDeviceVerifyProps): LoginScreenProps | null => {\n if (device.status === 'loading') return null;\n\n if (device.status === 'code_entry') {\n return {\n chrome: {\n title: 'Enter the code',\n subtitle: 'Type the code shown on your device.',\n },\n state: {\n kind: 'code-entry',\n error: device.error?.message,\n testId: 'device-code-entry',\n onSubmit: device.submitCode,\n },\n };\n }\n\n if (device.status === 'done') {\n return {\n chrome: {\n title: device.info?.app_name ? `You're signed in to ${device.info.app_name}` : \"You're signed in\",\n subtitle: \"Head back to your terminal — it's ready to go.\",\n },\n state: {\n kind: 'status',\n tone: 'success',\n message: 'This device is approved',\n detail: 'You can close this page.',\n testId: device.info?.mode === 'passkey' ? 'device-auto-passkey-done' : 'device-done',\n },\n };\n }\n\n if (device.status === 'refused') {\n const error = device.error ?? deviceErrorOfType('mode_disabled');\n return {\n chrome: {\n title: \"Sign-in isn't available this way\",\n },\n state: {\n kind: 'status',\n tone: 'disabled',\n message: error.message,\n detail: 'Nothing was approved, and nothing was sent to the device that showed you this code.',\n testId: 'device-mode-disabled',\n },\n };\n }\n\n if (device.status === 'failed') {\n const error = device.error ?? deviceErrorOfType('generic');\n return {\n chrome: {\n title: \"That didn't work\",\n },\n state: {\n kind: 'status',\n tone: 'error',\n message: error.message,\n recoverable: error.isRecoverable,\n testId: 'device-failed',\n onRetry: error.isRecoverable ? () => device.submitCode('') : undefined,\n },\n };\n }\n\n if (!device.info) return null;\n\n // Every mode asks for the second factor the same way, before its approval.\n if (device.status === 'second_factor' || (device.status === 'working' && device.isSecondFactorPending)) {\n return {\n chrome: {\n title: 'Two-Factor Authentication',\n subtitle: `One more step to approve ${device.info.app_name}.`,\n },\n state: {\n kind: 'second-factor',\n methods: device.secondFactorMethods,\n identity: device.email,\n busy: device.status === 'working',\n error: device.error?.message,\n testId: 'device-second-factor',\n onSubmit: (method, code) => void device.submitSecondFactor(method, code),\n onMethodChange: device.clearError,\n },\n };\n }\n\n if (device.info.mode === 'passkey') {\n const working = (device.status === 'ready' || device.status === 'working') && !device.error;\n return {\n chrome: {\n title: `Sign in to ${device.info.app_name}`,\n subtitle: 'Confirm with your passkey to finish this device sign-in.',\n },\n state: {\n kind: 'passkey-progress',\n working,\n message: device.error\n ? \"Passkey sign-in couldn't continue.\"\n : 'Waiting for your passkey — follow the prompt on your device.',\n error: device.error?.message,\n recoverable: device.error?.isRecoverable,\n testId: 'device-auto-passkey',\n onRetry: device.error?.isRecoverable ? () => void device.confirmWithPasskey() : undefined,\n },\n };\n }\n\n const busy = device.status === 'working';\n const authenticated = device.isAuthenticated || device.status === 'signed_in';\n const methods = getDeviceLoginMethods(device);\n const notice = deviceNotice(device);\n\n if (device.info.mode === 'full_login') {\n if (authenticated) {\n return {\n chrome: {\n title: `Approve sign-in to ${device.info.app_name}`,\n subtitle: 'Confirm that the code matches your terminal before approving.',\n },\n state: {\n kind: 'device-approval',\n appName: device.info.app_name,\n code: device.info.user_code,\n identity: device.email,\n busy,\n error: device.error?.message,\n testId: 'device-full-login-approval',\n actionTestId: 'device-confirm',\n codeTestId: 'device-consent-user-code',\n appNameTestId: 'device-consent-app-name',\n onApprove: () => void device.approve(),\n },\n };\n }\n\n return {\n chrome: {\n title: `Sign in to approve ${device.info.app_name}`,\n subtitle: 'Confirm the code, then sign in to continue.',\n variant: 'sign-in',\n },\n state: {\n kind: 'credentials',\n methods,\n passwordPolicy: null,\n notice,\n busy,\n error: toCredentialsError(device.error),\n primaryLabel: busy ? 'Signing in…' : 'Sign In',\n passkeyLabel: 'Sign In with a Passkey',\n testId: 'device-full-login',\n onPassword: (values) => void device.signInWithPassword(values.emailOrUsername, values.password),\n onPasskey: () => void device.signInWithPasskey(),\n },\n };\n }\n\n return {\n chrome: {\n title: `Approve sign-in to ${device.info.app_name}`,\n subtitle: 'Confirm the code, then sign in to approve this request.',\n variant: 'sign-in',\n },\n state: {\n kind: 'credentials',\n methods,\n passwordPolicy: null,\n notice,\n busy,\n error: toCredentialsError(device.error),\n primaryLabel: busy ? 'Approving…' : 'Approve',\n primaryTestId: 'device-confirm',\n passkeyLabel: 'Approve with a Passkey',\n testId: 'device-consent',\n onPassword: (values) => void device.confirmWithPassword(values.emailOrUsername, values.password),\n onPasskey: () => void device.confirmWithPasskey(),\n },\n };\n};\n","import type { FC } from 'react';\nimport { useEffect, useRef } from 'react';\nimport { LoginScreen } from '@/components/ui';\nimport { useDeviceVerify } from '@/hooks/use-device-verify';\nimport { getDeviceLoginScreenProps } from './screen';\n\n/**\n * RFC 8628 device verification controller.\n *\n * The server selects consent, full-login, or passkey mode. This component owns\n * the state transition and automatic passkey attempt; the Storybook-backed\n * LoginScreen owns every visual state.\n */\nexport const DeviceVerifyFlow: FC = () => {\n const device = useDeviceVerify();\n const attemptedPasskeyChallenge = useRef<string | null>(null);\n const { confirmWithPasskey } = device;\n const challengeKey = device.info?.csrf_token ?? null;\n const isAutomaticPasskeyReady = device.info?.mode === 'passkey' && device.status === 'ready' && !device.error;\n\n useEffect(() => {\n if (!isAutomaticPasskeyReady || !challengeKey || attemptedPasskeyChallenge.current === challengeKey) return;\n\n attemptedPasskeyChallenge.current = challengeKey;\n void confirmWithPasskey();\n }, [challengeKey, confirmWithPasskey, isAutomaticPasskeyReady]);\n\n const screen = getDeviceLoginScreenProps(device);\n return screen ? <LoginScreen {...screen} /> : null;\n};\n","import type { FC, FormEvent } from 'react';\nimport { useId, useState } from 'react';\nimport { Button, FieldOtp, Icon } from '@/components/ui';\nimport { useTwoFactorSetup } from '@/hooks';\nimport { Wrapper } from '../wrapper';\n\nimport '@/styles/index.css';\n\ntype TwoFactorSetupFormProps = {\n onComplete?: (recoveryCodes: string[]) => void;\n onCancel?: () => void;\n numInputs?: number;\n};\n\nexport const TwoFactorSetupForm: FC<TwoFactorSetupFormProps> = ({ onComplete, onCancel, numInputs }) => {\n const [code, setCode] = useState('');\n const [showSecret, setShowSecret] = useState(false);\n const { setupData, recoveryCodes, step, beginSetup, confirmSetup, reset, isLoading, isError, error } = useTwoFactorSetup();\n const otpId = useId();\n const otpLabelId = `${otpId}-label`;\n const otpErrorId = `${otpId}-error`;\n\n // Get TOTP digits (defaults to 6 if not provided)\n const totpDigits = numInputs ?? 6;\n\n const handleCodeChange = (value: string) => {\n setCode(value);\n };\n\n const handleConfirm = async (e: FormEvent) => {\n e.preventDefault();\n const result = await confirmSetup(code);\n if (result) {\n // Don't call onComplete yet - wait for user to save codes\n }\n };\n\n const handleCopyRecoveryCodes = () => {\n navigator.clipboard.writeText(recoveryCodes.join('\\n'));\n };\n\n const handleComplete = () => {\n onComplete?.(recoveryCodes);\n reset();\n };\n\n // Step 1: Start setup\n if (step === 'idle') {\n return (\n <Wrapper\n title='Enable Two-Factor Authentication'\n subtitle='Add an extra layer of security to your account'\n className='passflow-2fa-setup'\n >\n <div className='passflow-2fa-setup-start'>\n <Button size='big' type='button' variant='primary' onClick={() => beginSetup()} disabled={isLoading}>\n {isLoading ? 'Loading...' : 'Get Started'}\n </Button>\n {onCancel && (\n <button type='button' className='passflow-link-button' onClick={onCancel}>\n Cancel\n </button>\n )}\n {isError && (\n <div className='passflow-field-error'>\n <Icon size='small' id='warning' type='general' className='icon-warning' />\n <span className='passflow-field-error-text'>{error}</span>\n </div>\n )}\n </div>\n </Wrapper>\n );\n }\n\n // Step 2: Show QR code and confirm\n if (step === 'setup' && setupData) {\n return (\n <Wrapper\n title='Scan QR Code'\n subtitle='Scan this code with your authenticator app (Google Authenticator, Authy, etc.)'\n className='passflow-2fa-setup'\n >\n <form onSubmit={handleConfirm} className='passflow-2fa-setup-qr'>\n <div className='passflow-2fa-qr-container'>\n <img src={`data:image/png;base64,${setupData.qr_code}`} alt='2FA QR Code' className='passflow-2fa-qr-image' />\n </div>\n\n <div className='passflow-2fa-secret-toggle'>\n <button type='button' className='passflow-link-button' onClick={() => setShowSecret(!showSecret)}>\n {showSecret ? 'Hide manual code' : \"Can't scan? Enter code manually\"}\n </button>\n {showSecret && <code className='passflow-2fa-secret-code'>{setupData.secret}</code>}\n </div>\n\n <div className='passflow-2fa-confirm-section'>\n <p id={otpLabelId} className='passflow-2fa-confirm-label'>\n Enter the {totpDigits}-digit code from your app to confirm:\n </p>\n <div id='otp-wrapper' className='passflow-verify-otp-wrapper'>\n <FieldOtp\n id={otpId}\n name='code'\n length={totpDigits}\n value={code}\n onChange={handleCodeChange}\n state={isError ? 'error' : 'default'}\n labelledBy={otpLabelId}\n describedBy={isError ? otpErrorId : undefined}\n autoFocus\n />\n {isError && (\n <div className='passflow-verify-otp-error'>\n <Icon size='small' id='warning' type='general' className='icon-warning' />\n <span id={otpErrorId} className='passflow-verify-otp-error-text'>\n {error}\n </span>\n </div>\n )}\n </div>\n </div>\n\n <Button size='big' type='submit' variant='primary' disabled={code.length !== totpDigits || isLoading}>\n {isLoading ? 'Confirming...' : 'Confirm & Enable'}\n </Button>\n </form>\n </Wrapper>\n );\n }\n\n // Step 3: Show recovery codes\n if (step === 'complete' && recoveryCodes.length > 0) {\n return (\n <Wrapper\n title='Save Your Recovery Codes'\n subtitle=\"Store these codes in a safe place. You'll need them if you lose access to your authenticator.\"\n className='passflow-2fa-setup'\n >\n <div className='passflow-2fa-setup-complete'>\n <div className='passflow-2fa-warning'>\n <Icon size='small' id='warning' type='general' className='icon-warning' />\n <span>These codes will only be shown once. Make sure to save them!</span>\n </div>\n\n <div className='passflow-2fa-recovery-codes'>\n {recoveryCodes.map((recoveryCode) => (\n <code key={recoveryCode} className='passflow-2fa-recovery-code'>\n {recoveryCode}\n </code>\n ))}\n </div>\n\n <Button size='big' type='button' variant='secondary' onClick={handleCopyRecoveryCodes}>\n Copy to Clipboard\n </Button>\n\n <Button size='big' type='button' variant='primary' onClick={handleComplete}>\n I've Saved These Codes\n </Button>\n </div>\n </Wrapper>\n );\n }\n\n return null;\n};\n","import type { FC } from 'react';\nimport { useEffect, useState } from 'react';\nimport { TwoFactorSetupForm } from '@/components/form/two-factor-setup';\nimport { routes } from '@/context';\nimport { useNavigation, usePassflow } from '@/hooks';\nimport type { SuccessAuthRedirect } from '@/types';\nimport { TwoFactorLoopPrevention } from '@/utils';\n\nimport '@/styles/index.css';\n\ntype TwoFactorSetupFlowProps = {\n successAuthRedirect?: SuccessAuthRedirect;\n twoFactorVerifyPath?: string;\n signInPath?: string;\n};\n\nexport const TwoFactorSetupFlow: FC<TwoFactorSetupFlowProps> = ({\n twoFactorVerifyPath = routes.two_factor_verify.path,\n signInPath = routes.signin.path,\n}) => {\n const [shouldBlockRender, setShouldBlockRender] = useState(false);\n const { navigate } = useNavigation();\n const passflow = usePassflow();\n\n // Handle initial verification requirement check\n // User must be in partial auth state (have tfa_token) to access setup\n useEffect(() => {\n if (!passflow.isTwoFactorVerificationRequired()) {\n // Not in partial auth state - redirect to sign-in\n if (TwoFactorLoopPrevention.canRedirect()) {\n TwoFactorLoopPrevention.incrementRedirect();\n navigate({ to: signInPath });\n setShouldBlockRender(true);\n } else {\n // Loop detected - let component handle gracefully\n setShouldBlockRender(false);\n }\n }\n }, [passflow, navigate, signInPath]);\n\n const handleSetupComplete = () => {\n // After setup is complete, redirect back to verify flow\n // User now has 2FA enabled and needs to verify with a code\n navigate({ to: twoFactorVerifyPath });\n };\n\n const handleCancel = () => {\n // User cancelled setup - reset loop prevention and go back to sign-in\n TwoFactorLoopPrevention.reset();\n navigate({ to: signInPath });\n };\n\n // Don't render if we're redirecting\n if (shouldBlockRender) {\n return null;\n }\n\n // Don't render if verification not required and no loop detected\n if (!passflow.isTwoFactorVerificationRequired() && TwoFactorLoopPrevention.canRedirect()) {\n return null;\n }\n\n return <TwoFactorSetupForm onComplete={handleSetupComplete} onCancel={handleCancel} />;\n};\n","import type { FC } from 'react';\nimport { useEffect } from 'react';\nimport { TwoFactorSetupForm } from '@/components/form/two-factor-setup';\nimport { Wrapper } from '@/components/form/wrapper';\nimport { Button, Icon } from '@/components/ui';\nimport { routes } from '@/context';\nimport { type UseTwoFactorSetupMagicLinkReturn, useNavigation, useTwoFactorSetupMagicLink } from '@/hooks';\n\nimport '@/styles/index.css';\n\n/**\n * Error type for magic link validation\n */\ntype MagicLinkError = NonNullable<UseTwoFactorSetupMagicLinkReturn['error']>;\n\n/**\n * Props for TwoFactorSetupMagicLinkFlow component\n */\nexport type TwoFactorSetupMagicLinkFlowProps = {\n /**\n * The magic-link token. Leave it out and it is read from the URL: the path\n * segment after `/two-factor-setup-magic-link/` (or the same after `#`).\n */\n token?: string;\n /** Callback after successful setup */\n onSuccess?: () => void;\n /** Callback on validation error */\n onError?: (error: MagicLinkError) => void;\n /** Whether to redirect after setup (default: true) */\n redirectOnSuccess?: boolean;\n /** Path to sign-in page (default: /signin) */\n signInPath?: string;\n};\n\nconst MAGIC_LINK_SEGMENT = /\\/two-factor-setup-magic-link\\/([^/?#]+)/;\n\n/** The token in the current URL's path, or after `#` for hash routing; '' when there is none. */\nconst tokenFromUrl = (): string => {\n const found = MAGIC_LINK_SEGMENT.exec(window.location.pathname) ?? MAGIC_LINK_SEGMENT.exec(window.location.hash);\n if (!found?.[1]) return '';\n try {\n return decodeURIComponent(found[1]);\n } catch {\n return found[1];\n }\n};\n\n/**\n * Flow component for magic link 2FA setup\n *\n * This component:\n * 1. Takes the token from its `token` prop, or from the URL\n * 2. Validates token via useTwoFactorSetupMagicLink hook\n * 3. Shows loading state during validation\n * 4. Shows error UI if validation fails\n * 5. Renders TwoFactorSetupForm if validation succeeds\n * 6. Redirects to sign-in after successful setup\n *\n * Route: /two-factor-setup-magic-link/:token\n */\nexport const TwoFactorSetupMagicLinkFlow: FC<TwoFactorSetupMagicLinkFlowProps> = ({\n token: tokenProp,\n onSuccess,\n onError,\n redirectOnSuccess = true,\n signInPath = routes.signin.path,\n}) => {\n const token = tokenProp ?? tokenFromUrl();\n const { navigate } = useNavigation();\n\n // Validate magic link token\n const { isLoading, isRetrying, isValidated, error, retry, retryCountdown } = useTwoFactorSetupMagicLink(token);\n\n /**\n * Handle validation error\n */\n useEffect(() => {\n if (error) {\n onError?.(error);\n }\n }, [error, onError]);\n\n /**\n * Handle successful 2FA setup completion\n */\n const handleSetupComplete = () => {\n onSuccess?.();\n\n if (redirectOnSuccess) {\n // Redirect to sign-in page\n navigate({\n to: signInPath,\n });\n }\n };\n\n /**\n * Handle setup cancellation\n */\n const handleCancel = () => {\n navigate({ to: signInPath });\n };\n\n /**\n * Render: Loading state\n */\n if (isLoading) {\n return (\n <Wrapper\n title='Validating Magic Link'\n subtitle='Please wait while we verify your link...'\n className='passflow-2fa-magic-link-loading'\n >\n <div className='passflow-loading-container' role='status' aria-live='polite' aria-busy='true'>\n <Icon id='logo' type='general' size='large' className='passflow-loading-spinner' />\n <p className='passflow-loading-text'>Validating your magic link...</p>\n </div>\n </Wrapper>\n );\n }\n\n /**\n * Render: Error state\n */\n if (error) {\n const isRetryable = error.code === 'SERVER_ERROR' || error.code === 'RATE_LIMITED';\n const isRateLimited = error.code === 'RATE_LIMITED' && retryCountdown !== null && retryCountdown > 0;\n\n return (\n <Wrapper\n title='Magic Link Validation Failed'\n subtitle={getErrorSubtitle(error.code)}\n className='passflow-2fa-magic-link-error'\n >\n <div className='passflow-error-container' role='alert' aria-live='assertive'>\n <div className='passflow-error-icon'>\n <Icon id='warning' type='general' size='large' />\n </div>\n\n <p className='passflow-error-message' id='error-message'>\n {error.message}\n </p>\n\n <div className='passflow-error-actions'>\n {isRetryable && (\n <Button\n size='big'\n type='button'\n variant='primary'\n onClick={retry}\n disabled={isRateLimited || isRetrying}\n aria-describedby='error-message'\n >\n {isRetrying ? 'Retrying...' : isRateLimited ? `Try again in ${formatCountdown(retryCountdown)}` : 'Try Again'}\n </Button>\n )}\n\n <Button size='big' type='button' variant='secondary' onClick={() => navigate({ to: signInPath })}>\n Back to Sign In\n </Button>\n </div>\n\n {!isRetryable && (\n <p className='passflow-error-help-text'>Please contact your administrator to request a new magic link.</p>\n )}\n </div>\n </Wrapper>\n );\n }\n\n /**\n * Render: Success state - show 2FA setup form\n */\n if (isValidated) {\n return <TwoFactorSetupForm onComplete={handleSetupComplete} onCancel={handleCancel} />;\n }\n\n // Fallback (should not reach here)\n return null;\n};\n\n/**\n * Get user-friendly subtitle for error codes\n */\nfunction getErrorSubtitle(code: string): string {\n switch (code) {\n case 'EXPIRED_TOKEN':\n return 'This magic link has expired';\n case 'INVALID_TOKEN':\n return 'This magic link is invalid';\n case 'REVOKED_TOKEN':\n return 'This magic link has been revoked';\n case 'RATE_LIMITED':\n return 'Too many attempts';\n case 'SERVER_ERROR':\n return 'Something went wrong';\n default:\n return 'An error occurred';\n }\n}\n\n/**\n * Format countdown seconds as MM:SS\n */\nfunction formatCountdown(seconds: number | null): string {\n if (seconds === null) return '';\n const mins = Math.floor(seconds / 60);\n const secs = seconds % 60;\n return `${mins}:${secs.toString().padStart(2, '0')}`;\n}\n","import type { TwoFactorMethod } from '@passflow/core';\nimport * as Dialog from '@radix-ui/react-dialog';\nimport type { FC } from 'react';\n\ntype MethodSelectorProps = {\n availableMethods: TwoFactorMethod[];\n currentMethod: TwoFactorMethod;\n onSelectMethod: (method: TwoFactorMethod) => void;\n isOpen: boolean;\n onClose: () => void;\n};\n\nconst methodLabels: Partial<Record<TwoFactorMethod, string>> = {\n totp: 'Authenticator App',\n email_otp: 'Email Code',\n sms_otp: 'SMS Code',\n passkey: 'Passkey',\n recovery_codes: 'Recovery Code',\n push_fcm: 'Push Notification (FCM)',\n push_webpush: 'Push Notification (Web)',\n};\n\nconst methodIcons: Partial<Record<TwoFactorMethod, string>> = {\n totp: '📱',\n email_otp: '✉️',\n sms_otp: '💬',\n passkey: '🔑',\n recovery_codes: '🔒',\n push_fcm: '🔔',\n push_webpush: '🔔',\n};\n\nexport const MethodSelector: FC<MethodSelectorProps> = ({\n availableMethods,\n currentMethod,\n onSelectMethod,\n isOpen,\n onClose,\n}) => {\n const handleSelect = (method: TwoFactorMethod) => {\n onSelectMethod(method);\n onClose();\n };\n\n return (\n <Dialog.Root open={isOpen} onOpenChange={(open) => !open && onClose()}>\n <Dialog.Portal>\n <Dialog.Overlay className='pf-dialog-overlay' />\n <Dialog.Content className='pf-dialog-content pf-method-selector-dialog'>\n <Dialog.Title className='pf-dialog-title'>Choose Verification Method</Dialog.Title>\n <Dialog.Description className='pf-dialog-description'>\n Select an alternative method to verify your identity\n </Dialog.Description>\n\n <div className='pf-method-selector-list'>\n {availableMethods.map((method) => (\n <button\n key={method}\n type='button'\n className={`pf-method-selector-item ${method === currentMethod ? 'pf-method-selector-item-active' : ''}`}\n onClick={() => handleSelect(method)}\n disabled={method === currentMethod}\n >\n <span className='pf-method-icon'>{methodIcons[method] || '🔐'}</span>\n <span className='pf-method-label'>{methodLabels[method] || method}</span>\n {method === currentMethod && <span className='pf-method-current-badge'>Current</span>}\n </button>\n ))}\n </div>\n\n <Dialog.Close asChild>\n <button type='button' className='pf-dialog-close' aria-label='Close'>\n ×\n </button>\n </Dialog.Close>\n </Dialog.Content>\n </Dialog.Portal>\n </Dialog.Root>\n );\n};\n","import type { TwoFactorMethod } from '@passflow/core';\nimport type { FC } from 'react';\nimport { useEffect, useId, useState } from 'react';\nimport { FieldOtp } from '@/components/ui';\nimport { useTwoFactorChallenge } from '@/hooks/use-two-factor-challenge';\nimport { MethodSelector } from './method-selector';\n\ntype TwoFactorChallengeProps = {\n firstFactorMethod?: string;\n onSuccess?: () => void;\n onError?: (error: Error) => void;\n trustDevice?: boolean;\n};\n\nexport const TwoFactorChallenge: FC<TwoFactorChallengeProps> = ({\n firstFactorMethod,\n onSuccess,\n onError,\n trustDevice = false,\n}) => {\n const { challenge, isLoading, error, requestChallenge, verify, switchMethod, selectedMethod } = useTwoFactorChallenge();\n\n const [otpValue, setOtpValue] = useState('');\n const [isMethodSelectorOpen, setIsMethodSelectorOpen] = useState(false);\n const otpId = useId();\n const otpLabelId = `${otpId}-label`;\n const otpErrorId = `${otpId}-error`;\n\n // Request challenge on mount\n useEffect(() => {\n requestChallenge(firstFactorMethod);\n }, [requestChallenge, firstFactorMethod]);\n\n // Handle errors\n useEffect(() => {\n if (error && onError) {\n onError(error);\n }\n }, [error, onError]);\n\n const handleVerify = async () => {\n if (!otpValue) {\n return;\n }\n\n const result = await verify(otpValue, trustDevice);\n if (result) {\n onSuccess?.();\n }\n };\n\n const handleSwitchMethod = async (method: TwoFactorMethod) => {\n setOtpValue('');\n await switchMethod(method);\n };\n\n const handleOtpChange = (value: string) => {\n setOtpValue(value);\n\n // Auto-submit when OTP is complete (6 digits)\n if (value.length === 6) {\n setTimeout(() => {\n verify(value, trustDevice).then((result) => {\n if (result) {\n onSuccess?.();\n }\n });\n }, 100);\n }\n };\n\n if (!challenge) {\n return (\n <div className='pf-two-factor-challenge pf-loading'>\n <p>Loading challenge...</p>\n </div>\n );\n }\n\n const currentMethod = selectedMethod || challenge.method;\n const availableMethods = [challenge.method, ...(challenge.alternative_methods || [])];\n\n const renderChallengeInput = () => {\n switch (currentMethod) {\n case 'totp':\n case 'email_otp':\n case 'sms_otp':\n return (\n <div className='pf-challenge-input-wrapper'>\n <FieldOtp\n id={otpId}\n name='code'\n length={6}\n value={otpValue}\n onChange={handleOtpChange}\n state={isLoading ? 'disabled' : error ? 'error' : 'default'}\n labelledBy={otpLabelId}\n describedBy={error ? otpErrorId : undefined}\n autoFocus\n />\n {error && (\n <div id={otpErrorId} className='pf-otp-error'>\n {error.message}\n </div>\n )}\n {currentMethod === 'email_otp' && challenge.code_sent_to && (\n <p className='pf-challenge-hint'>Code sent to {challenge.code_sent_to}</p>\n )}\n {currentMethod === 'sms_otp' && challenge.code_sent_to && (\n <p className='pf-challenge-hint'>Code sent to {challenge.code_sent_to}</p>\n )}\n <button\n type='button'\n onClick={handleVerify}\n disabled={isLoading || otpValue.length !== 6}\n className='pf-button pf-button-primary'\n >\n {isLoading ? 'Verifying...' : 'Verify'}\n </button>\n </div>\n );\n\n case 'passkey':\n return (\n <div className='pf-challenge-input-wrapper'>\n <button type='button' onClick={handleVerify} disabled={isLoading} className='pf-button pf-button-primary'>\n {isLoading ? 'Verifying...' : 'Use Passkey'}\n </button>\n </div>\n );\n\n case 'recovery_codes':\n return (\n <div className='pf-challenge-input-wrapper'>\n <input\n type='text'\n value={otpValue}\n onChange={(e) => setOtpValue(e.target.value)}\n placeholder='Enter recovery code'\n disabled={isLoading}\n className='pf-input'\n />\n <button\n type='button'\n onClick={handleVerify}\n disabled={isLoading || !otpValue}\n className='pf-button pf-button-primary'\n >\n {isLoading ? 'Verifying...' : 'Verify'}\n </button>\n </div>\n );\n\n default:\n return <p>Unsupported method: {currentMethod}</p>;\n }\n };\n\n return (\n <div className='pf-two-factor-challenge'>\n <div className='pf-challenge-method-info'>\n <h3>Two-Factor Authentication</h3>\n <p id={otpLabelId}>Enter the verification code</p>\n </div>\n\n {renderChallengeInput()}\n\n {availableMethods.length > 1 && (\n <button\n type='button'\n onClick={() => setIsMethodSelectorOpen(true)}\n className='pf-button pf-button-secondary pf-button-switch-method'\n >\n Use different method\n </button>\n )}\n\n <MethodSelector\n availableMethods={availableMethods}\n currentMethod={currentMethod}\n onSelectMethod={handleSwitchMethod}\n isOpen={isMethodSelectorOpen}\n onClose={() => setIsMethodSelectorOpen(false)}\n />\n </div>\n );\n};\n","import type { ChangeEvent, FC, FormEvent } from 'react';\nimport { useState } from 'react';\nimport { Button, Icon, Switch } from '@/components/ui';\nimport { useTwoFactorVerify } from '@/hooks';\nimport { cn, getUserFriendlyErrorMessage, TwoFactorLoopPrevention } from '@/utils';\nimport { Wrapper } from '../wrapper';\n\nimport '@/styles/index.css';\n\ntype TwoFactorRecoveryFormProps = {\n onSuccess?: () => void;\n onBack?: () => void;\n title?: string;\n subtitle?: string;\n signInPath?: string;\n /** Label of the \"trust this device\" option, unticked by default. */\n trustDeviceLabel?: string;\n};\n\n/** Only a ticked box asks for trust; an unticked one sends no option at all. */\nconst completionOptions = (trustDevice: boolean) => (trustDevice ? { trustDevice: true } : undefined);\n\nexport const TwoFactorRecoveryForm: FC<TwoFactorRecoveryFormProps> = ({\n onSuccess,\n onBack,\n title = 'Use Recovery Code',\n subtitle = 'Enter one of your recovery codes',\n signInPath,\n trustDeviceLabel = 'Trust this device',\n}) => {\n const [code, setCode] = useState('');\n const [trustDevice, setTrustDevice] = useState(false);\n const { useRecoveryCode, isLoading, isError, errorDetails, reset } = useTwoFactorVerify();\n\n const handleChange = (e: ChangeEvent<HTMLInputElement>) => {\n reset();\n // Normalize: uppercase and remove spaces\n setCode(e.target.value.toUpperCase().replace(/\\s/g, ''));\n };\n\n const handleSubmit = async (e: FormEvent) => {\n e.preventDefault();\n const result = await useRecoveryCode(code, completionOptions(trustDevice));\n if (result) {\n onSuccess?.();\n }\n };\n\n const handleBackToSignIn = () => {\n TwoFactorLoopPrevention.reset();\n window.location.href = signInPath || '/signin';\n };\n\n // Check if loop detected\n const isLoopDetected = !TwoFactorLoopPrevention.canRedirect();\n\n // Render error content (same logic as verify form)\n const renderErrorContent = () => {\n if (!isError || !errorDetails) return null;\n\n if (isLoopDetected) {\n return (\n <div className='passflow-form-error passflow-form-error--critical'>\n <Icon size='medium' id='warning' type='general' className='icon-warning' />\n <div className='passflow-form-error-content'>\n <span className='passflow-form-error-text'>{TwoFactorLoopPrevention.getLoopDetectedMessage()}</span>\n {signInPath && (\n <Button\n type='button'\n size='medium'\n variant='secondary'\n onClick={handleBackToSignIn}\n className='passflow-button-back-to-signin'\n >\n Back to Sign In\n </Button>\n )}\n </div>\n </div>\n );\n }\n\n if (errorDetails.type === 'not_enabled') {\n return (\n <div className='passflow-form-error passflow-form-error--persistent'>\n <Icon size='medium' id='warning' type='general' className='icon-warning' />\n <div className='passflow-form-error-content'>\n <span className='passflow-form-error-text'>{getUserFriendlyErrorMessage(errorDetails)}</span>\n {signInPath && (\n <Button\n type='button'\n size='medium'\n variant='secondary'\n onClick={handleBackToSignIn}\n className='passflow-button-back-to-signin'\n >\n Back to Sign In\n </Button>\n )}\n </div>\n </div>\n );\n }\n\n if (errorDetails.type === 'expired') {\n return (\n <div className='passflow-form-info'>\n <Icon size='small' id='info' type='general' className='icon-info' />\n <span className='passflow-form-info-text'>{getUserFriendlyErrorMessage(errorDetails)}</span>\n </div>\n );\n }\n\n return (\n <div className='passflow-form-error'>\n <Icon size='small' id='warning' type='general' className='icon-warning' />\n <span className='passflow-form-error-text'>{getUserFriendlyErrorMessage(errorDetails)}</span>\n </div>\n );\n };\n\n const isInputDisabled =\n isLoading || errorDetails?.type === 'not_enabled' || errorDetails?.type === 'expired' || isLoopDetected;\n\n return (\n <Wrapper title={title} subtitle={subtitle} className='passflow-2fa-recovery'>\n <form onSubmit={handleSubmit} className='passflow-form'>\n <div className='passflow-form-container'>\n <div className='passflow-form-field'>\n <Switch\n label={trustDeviceLabel}\n checked={trustDevice}\n disabled={isInputDisabled}\n onChange={(event) => setTrustDevice(event.target.checked)}\n />\n </div>\n <div className='passflow-form-field'>\n <label htmlFor='recovery-code' className={cn('passflow-field-label', isError && 'passflow-field-label--error')}>\n Recovery Code\n </label>\n <input\n id='recovery-code'\n type='text'\n value={code}\n onChange={handleChange}\n placeholder='XXXX-XXXX'\n className={cn(\n 'passflow-field passflow-field--text passflow-field--focused',\n isError && 'passflow-field--error',\n isInputDisabled && 'passflow-field--disabled',\n )}\n autoComplete='off'\n disabled={isInputDisabled}\n />\n {renderErrorContent()}\n </div>\n </div>\n\n {!isInputDisabled && (\n <Button\n size='big'\n type='submit'\n variant='primary'\n disabled={code.length < 8 || isLoading}\n className='passflow-button-signin'\n >\n {isLoading ? 'Verifying...' : 'Verify'}\n </Button>\n )}\n\n {onBack && !isInputDisabled && (\n <div className='passflow-form-actions'>\n <p className='passflow-dont-have-account'>\n Have your device?{' '}\n <Button type='button' size='small' variant='link' onClick={onBack}>\n Use authenticator code\n </Button>\n </p>\n </div>\n )}\n </form>\n </Wrapper>\n );\n};\n","import type { FC, FormEvent } from 'react';\nimport { useId, useState } from 'react';\nimport { Button, FieldOtp, Icon, Switch } from '@/components/ui';\nimport { useTwoFactorVerify } from '@/hooks';\nimport { getUserFriendlyErrorMessage, TwoFactorLoopPrevention } from '@/utils';\nimport { Wrapper } from '../wrapper';\n\nimport '@/styles/index.css';\n\ntype TwoFactorVerifyFormProps = {\n onSuccess?: () => void;\n onUseRecovery?: () => void;\n title?: string;\n subtitle?: string;\n numInputs?: number;\n shouldAutoFocus?: boolean;\n signInPath?: string;\n twoFactorSetupPath?: string;\n /** Label of the \"trust this device\" option, unticked by default. */\n trustDeviceLabel?: string;\n};\n\n/** Only a ticked box asks for trust; an unticked one sends no option at all. */\nconst completionOptions = (trustDevice: boolean) => (trustDevice ? { trustDevice: true } : undefined);\n\nexport const TwoFactorVerifyForm: FC<TwoFactorVerifyFormProps> = ({\n onSuccess,\n onUseRecovery,\n title = 'Two-Factor Authentication',\n subtitle,\n numInputs,\n shouldAutoFocus = true,\n signInPath,\n twoFactorSetupPath,\n trustDeviceLabel = 'Trust this device',\n}) => {\n const [code, setCode] = useState('');\n const [trustDevice, setTrustDevice] = useState(false);\n const { verify, isLoading, isError, errorDetails, reset } = useTwoFactorVerify();\n const otpId = useId();\n const otpErrorId = `${otpId}-error`;\n\n // Get TOTP digits (defaults to 6 if not provided)\n const totpDigits = numInputs ?? 6;\n\n // Compute subtitle dynamically based on totpDigits\n const computedSubtitle = subtitle ?? `Enter the ${totpDigits}-digit code from your authenticator app`;\n\n const handleChange = (value: string) => {\n reset();\n setCode(value);\n };\n\n const handleSubmit = async (e: FormEvent) => {\n e.preventDefault();\n const result = await verify(code, completionOptions(trustDevice));\n if (result) {\n onSuccess?.();\n }\n };\n\n // Auto-submit when code is complete\n const handleOtpChange = async (value: string) => {\n handleChange(value);\n if (value.length === totpDigits) {\n const result = await verify(value, completionOptions(trustDevice));\n if (result) {\n onSuccess?.();\n }\n }\n };\n\n const handleBackToSignIn = () => {\n TwoFactorLoopPrevention.reset();\n window.location.href = signInPath || '/signin';\n };\n\n const handleSetup2FA = () => {\n // Navigate to 2FA setup page\n window.location.href = twoFactorSetupPath || '/two-factor-setup';\n };\n\n // Check if loop detected\n const isLoopDetected = !TwoFactorLoopPrevention.canRedirect();\n\n // Render different UI based on error type\n const renderErrorContent = () => {\n if (!isError || !errorDetails) return null;\n\n // Loop detected - critical error\n if (isLoopDetected) {\n return (\n <div className='passflow-form-error passflow-form-error--critical'>\n <Icon size='medium' id='warning' type='general' className='icon-warning' />\n <div className='passflow-form-error-content'>\n <span id={otpErrorId} className='passflow-form-error-text'>\n {TwoFactorLoopPrevention.getLoopDetectedMessage()}\n </span>\n {signInPath && (\n <Button\n type='button'\n size='medium'\n variant='secondary'\n onClick={handleBackToSignIn}\n className='passflow-button-back-to-signin'\n >\n Back to Sign In\n </Button>\n )}\n </div>\n </div>\n );\n }\n\n // 2FA not enabled - needs setup\n if (errorDetails.type === 'not_enabled') {\n return (\n <div className='passflow-form-error passflow-form-error--persistent'>\n <Icon size='medium' id='warning' type='general' className='icon-warning' />\n <div className='passflow-form-error-content'>\n <span id={otpErrorId} className='passflow-form-error-text'>\n You need to set up two-factor authentication first.\n </span>\n <div className='passflow-form-error-actions'>\n {twoFactorSetupPath && (\n <Button\n type='button'\n size='medium'\n variant='primary'\n onClick={handleSetup2FA}\n className='passflow-button-setup-2fa'\n >\n Set Up 2FA\n </Button>\n )}\n {signInPath && (\n <Button\n type='button'\n size='medium'\n variant='secondary'\n onClick={handleBackToSignIn}\n className='passflow-button-back-to-signin'\n >\n Back to Sign In\n </Button>\n )}\n </div>\n </div>\n </div>\n );\n }\n\n // Expired session - show redirect message\n if (errorDetails.type === 'expired') {\n return (\n <div className='passflow-form-info'>\n <Icon size='small' id='info' type='general' className='icon-info' />\n <span id={otpErrorId} className='passflow-form-info-text'>\n {getUserFriendlyErrorMessage(errorDetails)}\n </span>\n </div>\n );\n }\n\n // Invalid code or generic - allow retry\n return (\n <div className='passflow-form-error'>\n <Icon size='small' id='warning' type='general' className='icon-warning' />\n <span id={otpErrorId} className='passflow-form-error-text'>\n {getUserFriendlyErrorMessage(errorDetails)}\n </span>\n </div>\n );\n };\n\n // Disable input for non-recoverable errors\n const isInputDisabled =\n isLoading || errorDetails?.type === 'not_enabled' || errorDetails?.type === 'expired' || isLoopDetected;\n const otpState = isInputDisabled ? 'disabled' : isError ? 'error' : 'default';\n\n return (\n <Wrapper title={title} subtitle={computedSubtitle} className='passflow-2fa-verify'>\n <form onSubmit={handleSubmit} className='passflow-form'>\n <div className='passflow-form-container'>\n {/* Above the code: the code submits itself on its last digit. */}\n <div className='passflow-form-field'>\n <Switch\n label={trustDeviceLabel}\n checked={trustDevice}\n disabled={isInputDisabled}\n onChange={(event) => setTrustDevice(event.target.checked)}\n />\n </div>\n <div className='passflow-verify-otp-wrapper'>\n <FieldOtp\n id={otpId}\n name='code'\n length={totpDigits}\n value={code}\n onChange={handleOtpChange}\n state={otpState}\n label='Verification code'\n describedBy={isError && errorDetails ? otpErrorId : undefined}\n autoFocus={shouldAutoFocus && !isInputDisabled}\n />\n </div>\n {renderErrorContent()}\n </div>\n\n {!isInputDisabled && (\n <Button\n size='big'\n type='submit'\n variant='primary'\n disabled={code.length !== totpDigits || isLoading}\n className='passflow-button-signin'\n >\n {isLoading ? 'Verifying...' : 'Verify'}\n </Button>\n )}\n\n {onUseRecovery && !isInputDisabled && (\n <div className='passflow-form-actions'>\n <p className='passflow-dont-have-account'>\n Lost your device?{' '}\n <Button type='button' size='small' variant='link' onClick={onUseRecovery}>\n Use recovery code\n </Button>\n </p>\n </div>\n )}\n </form>\n </Wrapper>\n );\n};\n","/**\n * `UpgradeProvider` — the React side of the assurance-upgrade flow (§8.3).\n *\n * It owns the controller (through `passflow.upgrade`), bridges the\n * promise-returning `UpgradePromptHandler` to React state, and mounts the\n * dialog from `src/components/ui/upgrade-dialog`. It selects a state and maps\n * domain data onto that component's props; it renders no UI of its own and\n * styles nothing, per the project's component-library boundary.\n *\n * Three properties fall out of the shipped controller, and they are why this\n * is small:\n *\n * 1. **The wrong-code loop needs no plumbing.** The controller catches the\n * recoverable failure, sets `previousError` and calls `prompt()` again, so\n * the provider simply receives a new request and the dialog re-renders with\n * the error, still open.\n * 2. **Attempt budgeting needs no plumbing.** `maxAttempts` bounds the loop in\n * the controller and then fails the flight, which arrives here as the\n * `exhausted` terminal state.\n * 3. **Passkey has no code field.** `factors[i].input === 'none'` submits with\n * no code and the dialog shows `working` while the platform authenticator\n * runs.\n *\n * **The anti-leak rule is the single most important line in this file.** On\n * unmount, on teardown and on a session change, the pending prompt is resolved\n * `{ type: 'cancel' }`. A dangling `resolve` is an Observer leak wearing a\n * promise: the controller awaits forever, the elevation never settles, and\n * every request that joined the single flight hangs.\n *\n * **The session-change reset.** A challenge is server-bound to the session, so\n * an abandoned flight must never elevate a NEW session. The core discards its\n * controller on `SignIn` / `SignOut`; this provider discards its view of it in\n * the same breath, and the waiter that was mid-flight settles as\n * `session changed`, which the hook reports as `idle` — nothing that did not\n * happen is reported as though it had.\n */\n\nimport {\n type AssuranceBar,\n PassflowEvent,\n type PassflowSubscriber,\n type ReplayPolicy,\n requiredAcrLevel,\n type UpgradeChallenge,\n type UpgradeDiagnosticSink,\n type UpgradeFactor,\n type UpgradeFactorType,\n type UpgradeFlightSummary,\n type UpgradePromptHandler,\n type UpgradePromptResult,\n type UpgradeReplayInfo,\n type Waiter,\n} from '@passflow/core';\nimport { type FC, type ReactElement, type ReactNode, useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport type { UpgradeDialogLabels, UpgradeDialogOutcome, UpgradeDialogProps } from '@/components/ui/upgrade-dialog';\nimport { dialogOutcomeFromError, readAssuranceBar, toDialogState, UpgradeDialog } from '@/components/ui/upgrade-dialog';\nimport {\n UpgradeContext,\n type UpgradeContextValue,\n type UpgradeElevateOptions,\n type UpgradeErrorStatusKind,\n type UpgradeHookState,\n type UpgradePromptView,\n type UpgradeSettledState,\n} from '@/context/upgrade-context';\nimport { usePassflow } from '@/hooks/use-passflow';\nimport { registerUpgradeAuthInstance, upgradeAuthInstance } from '@/utils/upgrade-auth';\n\nexport type UpgradeProviderProps = {\n children?: ReactNode;\n /** Default `true`. `false` installs nothing and leaves the hook inert. */\n enabled?: boolean;\n /**\n * Where the customer's own API is — domain 2 (§13.5). Nothing outside this\n * and Passflow's own API is ever observed, and there is no allow-all opt-in.\n */\n backend?: string | string[];\n /**\n * Patches `globalThis.fetch` through the core's registry. **Off by default**,\n * and a different decision from enabling the UI: one prop for both would\n * bundle \"show me the verification prompt\" with \"patch the global\", and only\n * the second has the blast radius.\n */\n interceptFetch?: boolean;\n /** Requires the RFC 9470 channel. The body is then never read for a challenge. */\n requireChallengeChannel?: 'header';\n /** NARROWING ONLY: `false` excludes an admitted URL; `true` cannot widen. */\n shouldIntercept?: (url: string) => boolean;\n replay?: ReplayPolicy;\n /** The fetch surface's only cancellation option. Default `'resolve-original'`. */\n onCancel?: 'resolve-original' | 'reject';\n onUpgradeDiagnostic?: UpgradeDiagnosticSink;\n factors?: readonly UpgradeFactor[];\n maxAttempts?: number;\n relyingPartyId?: string;\n /** Per-factor wording for the dialog. */\n labels?: UpgradeDialogLabels;\n title?: string;\n /**\n * FR5's render-prop override. It receives the **exact** props the built-in\n * dialog would render — a typed, constrained override with no `className` or\n * `style` leak.\n *\n * It carries the same obligations as the built-in dialog, the selection\n * signal included: the `challenge` state's `onSelectFactor` must be called\n * when the user picks a factor, because that is the only thing that reports\n * §13.2's selection boundary to the controller. An override that never calls\n * it leaves the controller `collecting` for the whole ceremony, so a late\n * join re-ranks mid-entry — degraded, not silent.\n */\n renderDialog?: (props: UpgradeDialogProps) => ReactElement | null;\n};\n\ntype PendingResolve = ((result: UpgradePromptResult) => void) | undefined;\n\n/** §13.3's settlement table, hook column, for a flight that produced no proof. */\nconst errorStateOf = (error: Error): UpgradeSettledState => {\n switch (dialogOutcomeFromError(error)) {\n case 'cancelled':\n case 'session-changed':\n // Cancellation is not a status (§13.3): it is `elevate()` resolving null.\n return { status: 'idle' };\n case 'insufficient':\n return {\n status: 'insufficient',\n obtained: readAssuranceBar((error as { obtained?: unknown }).obtained) ?? {},\n required: readAssuranceBar((error as { required?: unknown }).required) ?? {},\n };\n case 'exhausted':\n return { status: 'error', kind: 'exhausted', error };\n case 'unsatisfiable':\n return { status: 'error', kind: 'unsatisfiable', error };\n case 'unavailable':\n return { status: 'error', kind: 'unavailable', error };\n default:\n return { status: 'error', kind: 'transport' satisfies UpgradeErrorStatusKind, error };\n }\n};\n\nconst summaryError = (summary: UpgradeFlightSummary): Error =>\n summary.error ??\n (summary.proof.status === 'failed' ? summary.proof.reason : undefined) ??\n new Error('The verification flight failed without reporting a reason.');\n\n/** One terminal state per flight, taken from the controller's summary (§13.4). */\nconst summaryToState = (summary: UpgradeFlightSummary): UpgradeSettledState => {\n if (summary.terminal === 'success') return { status: 'success' };\n if (summary.terminal === 'insufficient') {\n return {\n status: 'insufficient',\n obtained: summary.insufficient?.obtained ?? {},\n required: summary.insufficient?.required ?? {},\n };\n }\n return errorStateOf(summaryError(summary));\n};\n\nconst summaryToOutcome = (summary: UpgradeFlightSummary): UpgradeDialogOutcome => {\n if (summary.terminal === 'success') return { kind: 'elevated' };\n if (summary.terminal === 'insufficient') {\n return {\n kind: 'insufficient',\n obtained: summary.insufficient?.obtained ?? {},\n required: summary.insufficient?.required ?? {},\n };\n }\n return { kind: 'failed', error: summaryError(summary) };\n};\n\nconst asError = (value: unknown): Error => (value instanceof Error ? value : new Error(String(value)));\n\nconst statedBar = (options?: UpgradeElevateOptions): AssuranceBar | undefined => {\n if (options === undefined) return undefined;\n const bar = readAssuranceBar({\n acrValues: options.acrValues,\n level: requiredAcrLevel(options.acrValues),\n maxAge: options.maxAge,\n });\n return bar;\n};\n\n/**\n * The imperative seam's challenge. A caller asking for a bar states it here;\n * the parsing of `acrValues` is the core's `requiredAcrLevel`, never a second\n * reading of the ACR list.\n */\nconst imperativeChallenge = (options?: UpgradeElevateOptions): UpgradeChallenge => ({\n acrValues: options?.acrValues,\n requiredLevel: requiredAcrLevel(options?.acrValues),\n maxAge: options?.maxAge,\n status: 403,\n channels: [],\n});\n\n/**\n * Value identity for `factors`, so a fresh array literal with the same factors\n * does not tear down and reinstall the interceptors (H13).\n *\n * The factor TYPE is the identity: everything else on an `UpgradeFactor` is the\n * `assert` implementation, and the registry is keyed by type. A caller who\n * swaps one type's implementation for another keeps the installed one until the\n * type list itself changes — the same trade the `backend` join already makes,\n * and the alternative is an unconditional reinstall on every render.\n */\nconst factorsSignature = (factors?: readonly UpgradeFactor[]): string =>\n factors === undefined ? '\\u0000default' : factors.map((factor) => factor.type).join('\\u0000');\n\n/**\n * Value identity for `replay` (H13). The policy is a union, so each arm gets\n * its own comparable signature:\n *\n * - a mode string compares as itself;\n * - a limits object compares by its two fields;\n * - a PREDICATE compares as the constant `fn`, because a function's identity is\n * never stable across renders. The current closure is reached through a ref\n * and called by a stable proxy, which is the same pattern `shouldIntercept`\n * and `onUpgradeDiagnostic` already use here.\n */\nconst replaySignature = (replay?: ReplayPolicy): string => {\n if (replay === undefined) return 'none';\n if (typeof replay === 'string') return `mode:${replay}`;\n if (typeof replay === 'function') return 'fn';\n return `limits:${replay.maxBodyBytes ?? ''}:${replay.allowStreamingBody ?? ''}`;\n};\n\nexport const UpgradeProvider: FC<UpgradeProviderProps> = ({\n children,\n enabled = true,\n backend,\n interceptFetch = false,\n requireChallengeChannel,\n shouldIntercept,\n replay,\n onCancel,\n onUpgradeDiagnostic,\n factors,\n maxAttempts,\n relyingPartyId,\n labels,\n title,\n renderDialog,\n}) => {\n const passflow = usePassflow();\n\n const [prompt, setPrompt] = useState<UpgradePromptView | null>(null);\n const [state, setState] = useState<UpgradeHookState>({ status: 'idle' });\n const [selectedFactor, setSelectedFactor] = useState<UpgradeFactorType | null>(null);\n const [busy, setBusy] = useState(false);\n const [showAlternatives, setShowAlternatives] = useState(false);\n const [outcome, setOutcome] = useState<UpgradeDialogOutcome | undefined>(undefined);\n const [installed, setInstalled] = useState(false);\n\n /** The open prompt's resolver. Cleared the instant it is used — H3's \"once\". */\n const resolveRef = useRef<PendingResolve>(undefined);\n /** The open request, so the selection signal reaches the controller. */\n const requestRef = useRef<Parameters<UpgradePromptHandler>[0] | null>(null);\n /** Whether this prompt already reported a selection (§13.2 T3 fires once). */\n const reportedSelectionRef = useRef(false);\n /** Set by `cancel()`: the user closed the dialog, so no terminal panel is shown. */\n const userCancelledRef = useRef(false);\n /**\n * H11 — cancellation is STICKY for the rest of the flight.\n *\n * After a submit the prompt's resolver is already spent, so `cancel()` has\n * nothing to answer and the cancellation was simply lost: the flight ran on,\n * and the controller re-prompted the user it had just been told to stop\n * asking. The intent is recorded here and answered at the first boundary the\n * controller offers — its next `prompt()` call — which settles the flight as\n * `UpgradeCancelledError` and so puts every surface on §13.3's asymmetric\n * contract (fetch resolves the untouched 401/403, axios and the imperative\n * seam reject, `useUpgrade().elevate` resolves `null`). Cleared when the\n * flight settles, so it can never leak into the next one.\n *\n * It cannot abort a request already on the wire: the core exposes no abort\n * channel for a round in progress, and inventing one here would be a second\n * lifecycle authority beside the controller (§13.2).\n */\n const cancelRequestedRef = useRef(false);\n\n // Callback props are read through refs so that re-rendering with a new inline\n // closure never tears down and reinstalls the interceptors.\n const shouldInterceptRef = useRef(shouldIntercept);\n const diagnosticRef = useRef(onUpgradeDiagnostic);\n shouldInterceptRef.current = shouldIntercept;\n diagnosticRef.current = onUpgradeDiagnostic;\n\n // H13: `factors` and `replay` are compared by VALUE in the install effect's\n // dependencies (see `factorsSignature` / `replaySignature`) and read through\n // these refs, so an inline array or an inline predicate no longer reinstalls\n // the interceptors on every render. `onCancel` needs neither: it is a string\n // union, so it already compares by value.\n const factorsRef = useRef(factors);\n const replayRef = useRef(replay);\n factorsRef.current = factors;\n replayRef.current = replay;\n\n /**\n * The stable stand-in for a caller-supplied replay PREDICATE. The non-function\n * arms are passed through untouched; this is only ever installed when the\n * policy is a function, and a change of arm changes the signature and\n * reinstalls, which is why the fallback is unreachable rather than a decision.\n */\n const replayPredicate = useCallback((info: UpgradeReplayInfo): boolean => {\n const policy = replayRef.current;\n return typeof policy === 'function' ? policy(info) : true;\n }, []);\n\n /** Resolves a pending prompt exactly once. The anti-leak primitive. */\n const settlePrompt = useCallback((result: UpgradePromptResult): boolean => {\n const resolve = resolveRef.current;\n if (resolve === undefined) return false;\n resolveRef.current = undefined;\n resolve(result);\n return true;\n }, []);\n\n const clearPromptView = useCallback(() => {\n requestRef.current = null;\n reportedSelectionRef.current = false;\n setPrompt(null);\n setSelectedFactor(null);\n setShowAlternatives(false);\n setBusy(false);\n }, []);\n\n const promptHandler = useCallback<UpgradePromptHandler>(\n (request) =>\n new Promise<UpgradePromptResult>((resolve) => {\n // H11: the user cancelled after submitting and the controller came back\n // for another answer. Answer the cancellation instead of re-opening a\n // dialog they already closed.\n if (cancelRequestedRef.current) {\n resolve({ type: 'cancel' });\n return;\n }\n\n // Branch 2's channel (§13.2 T2): the controller pushes a raised bar and\n // a re-ranked list into the OPEN prompt, which updates without\n // resolving. Subscribed synchronously, before anything is awaited.\n request.onRequirementRaised = (next) => {\n setPrompt({ challenge: next.challenge, factors: next.factors, previousError: request.previousError });\n setState({ status: 'challenged', challenge: next.challenge, factors: next.factors.map((f) => f.type) });\n };\n\n resolveRef.current = resolve;\n requestRef.current = request;\n reportedSelectionRef.current = false;\n userCancelledRef.current = false;\n setOutcome(undefined);\n setSelectedFactor(null);\n setShowAlternatives(false);\n setBusy(false);\n setPrompt({ challenge: request.challenge, factors: request.factors, previousError: request.previousError });\n setState({\n status: 'challenged',\n challenge: request.challenge,\n factors: request.factors.map((factor) => factor.type),\n });\n }),\n [],\n );\n\n const handleFlightSettled = useCallback(\n (summary: UpgradeFlightSummary) => {\n cancelRequestedRef.current = false;\n setState(summaryToState(summary));\n setOutcome(userCancelledRef.current ? undefined : summaryToOutcome(summary));\n clearPromptView();\n },\n [clearPromptView],\n );\n\n useEffect(() => {\n if (!enabled) {\n setInstalled(false);\n return;\n }\n\n const teardown = passflow.upgrade.enable({\n prompt: promptHandler,\n backend,\n interceptFetch,\n requireChallengeChannel,\n shouldIntercept: shouldIntercept === undefined ? undefined : (url) => shouldInterceptRef.current?.(url) !== false,\n replay: typeof replayRef.current === 'function' ? replayPredicate : replayRef.current,\n onCancel,\n onUpgradeDiagnostic: onUpgradeDiagnostic === undefined ? undefined : (d) => diagnosticRef.current?.(d),\n factors: factorsRef.current,\n maxAttempts,\n relyingPartyId,\n onFlightSettled: handleFlightSettled,\n });\n setInstalled(true);\n\n return () => {\n // The anti-leak rule: never leave the controller awaiting an answer.\n settlePrompt({ type: 'cancel' });\n teardown();\n setInstalled(false);\n };\n // `backend` is compared by value so a fresh array literal does not reinstall.\n }, [\n passflow,\n enabled,\n Array.isArray(backend) ? backend.join('\\u0000') : backend,\n interceptFetch,\n requireChallengeChannel,\n shouldIntercept === undefined,\n onUpgradeDiagnostic === undefined,\n // H13: compared by value, never by identity — an inline policy object, an\n // inline predicate or a fresh factor array must not reinstall.\n replaySignature(replay),\n replayPredicate,\n onCancel,\n factorsSignature(factors),\n maxAttempts,\n relyingPartyId,\n promptHandler,\n handleFlightSettled,\n settlePrompt,\n ]);\n\n /**\n * Publishes this provider's instance to the free-function adapters, twice,\n * for two different reasons — and both are load-bearing.\n *\n * **The render-phase write** exists because React runs a child's effects\n * before the parent's in the same commit, so the documented\n * `useEffect(() => attachAuth(api), [])` in a child would otherwise reach\n * `requireInstance` with nothing registered and throw — and a throw inside an\n * effect unmounts the tree. Publishing in render makes attach order\n * irrelevant. It is guarded and idempotent, so a re-render or a discarded\n * Strict-Mode render changes nothing.\n *\n * **The effect re-registers and releases through the same call**, so the pair\n * is symmetric: `registerUpgradeAuthInstance` returns the release for its own\n * registration, and that release is deferred by a microtask and cancelled by\n * any registration in the meantime (see `utils/upgrade-auth`). React Strict\n * Mode mounts, unmounts and remounts effects in development, and a cleanup\n * that released immediately would leave the registry empty for the remount —\n * render does not run again, and the child-before-parent effect order holds\n * on the remount pass as well, so the re-registration here cannot be early\n * enough on its own. Measured, not assumed: with an immediate release the\n * remounting child's `attachAuth` throws.\n *\n * A ref cannot be the publication channel, which is why this is not the ref\n * shape: the free functions are bare module imports called by code that never\n * sees this component's context or refs, so the module-level registry is the\n * only channel children can read.\n */\n if (upgradeAuthInstance() !== passflow) registerUpgradeAuthInstance(passflow);\n useEffect(() => registerUpgradeAuthInstance(passflow), [passflow]);\n\n /**\n * The session-change reset. The core discards its controller here; the view\n * of it must go with it, or a dialog from the old session would collect an\n * answer that can only elevate the new one.\n */\n useEffect(() => {\n const subscriber: PassflowSubscriber = {\n onAuthChange: () => {\n cancelRequestedRef.current = false;\n settlePrompt({ type: 'cancel' });\n clearPromptView();\n setOutcome(undefined);\n setState({ status: 'idle' });\n },\n };\n const events = [PassflowEvent.SignIn, PassflowEvent.SignOut];\n passflow.subscribe(subscriber, events);\n return () => passflow.unsubscribe(subscriber, events);\n }, [passflow, settlePrompt, clearPromptView]);\n\n const selectFactor = useCallback((factor: UpgradeFactorType) => {\n setSelectedFactor(factor);\n // §13.2 T3: the selection boundary, reported before any answer is\n // submitted. `selected` is defined off this call and off nothing else.\n requestRef.current?.onFactorSelected(factor);\n reportedSelectionRef.current = true;\n }, []);\n\n const submit = useCallback(\n (code?: string) => {\n const request = requestRef.current;\n if (request === null || resolveRef.current === undefined) return;\n const factor = selectedFactor ?? request.factors[0]?.type;\n if (factor === undefined) return;\n if (!reportedSelectionRef.current) {\n // A submit that skipped the picker still selected a factor — the\n // suggested one — and the controller must hear it before the ceremony.\n request.onFactorSelected(factor);\n reportedSelectionRef.current = true;\n }\n setBusy(true);\n setState({ status: 'submitting' });\n settlePrompt({ type: 'submit', factor, code });\n },\n [selectedFactor, settlePrompt],\n );\n\n const cancel = useCallback(() => {\n userCancelledRef.current = true;\n cancelRequestedRef.current = true;\n if (!settlePrompt({ type: 'cancel' })) {\n // Nothing was pending: either a terminal panel is on screen, or an answer\n // is in flight. Close it either way — the sticky flag answers the\n // controller's next prompt, and leaving a busy dialog open would ask the\n // user to wait for a flight they have abandoned.\n setOutcome(undefined);\n }\n clearPromptView();\n setState({ status: 'idle' });\n }, [settlePrompt, clearPromptView]);\n\n const dismiss = useCallback(() => {\n setOutcome(undefined);\n }, []);\n\n const toggleAlternatives = useCallback(() => {\n setShowAlternatives((shown) => !shown);\n }, []);\n\n const elevate = useCallback(\n async (options?: UpgradeElevateOptions): Promise<UpgradeSettledState | null> => {\n const requested = statedBar(options);\n const waiter: Waiter = requested === undefined ? { kind: 'imperative' } : { kind: 'imperative', requested };\n try {\n await passflow.upgrade.elevate(imperativeChallenge(options), waiter);\n return { status: 'success' };\n } catch (error) {\n // The one surface where cancellation resolves `null`: there the\n // cancellation IS the whole value (§13.3).\n if (dialogOutcomeFromError(error) === 'cancelled') return null;\n return errorStateOf(asError(error));\n }\n },\n [passflow],\n );\n\n const value = useMemo<UpgradeContextValue>(\n () => ({\n enabled: enabled && installed,\n state,\n prompt,\n selectedFactor,\n selectFactor,\n submit,\n cancel,\n dismiss,\n elevate,\n }),\n [enabled, installed, state, prompt, selectedFactor, selectFactor, submit, cancel, dismiss, elevate],\n );\n\n const dialogState = toDialogState({\n prompt:\n prompt === null ? null : { challenge: prompt.challenge, factors: prompt.factors, previousError: prompt.previousError },\n outcome,\n ui: { selected: selectedFactor, busy, showAlternatives },\n labels,\n handlers: {\n onSelectFactor: selectFactor,\n onToggleAlternatives: toggleAlternatives,\n onSubmit: submit,\n onCancel: cancel,\n onDismiss: dismiss,\n },\n });\n\n const dialogProps: UpgradeDialogProps = {\n open: prompt !== null || outcome !== undefined,\n title,\n state: dialogState,\n };\n\n return (\n <UpgradeContext.Provider value={value}>\n {children}\n {/* Mounted after `children` so it overlays them. */}\n {renderDialog === undefined ? <UpgradeDialog {...dialogProps} /> : renderDialog(dialogProps)}\n </UpgradeContext.Provider>\n );\n};\n","import type { Passflow } from '@passflow/core';\nimport { useEffect, useRef } from 'react';\n\ntype Disposable = Pick<Passflow, 'dispose'>;\n\ntype PendingDispose = {\n instance: Disposable;\n timer: ReturnType<typeof setTimeout>;\n};\n\n/**\n * Disposes a Passflow instance once it is replaced (a new `useMemo` value) or the\n * provider unmounts. Each instance owns refresh timers, a BroadcastChannel and Web\n * Locks; one left undisposed keeps acting as an extra tab.\n *\n * Why the dispose is deferred: React StrictMode runs effect cleanup and setup again\n * for the same instance in one commit, while `useMemo` keeps that instance live. An\n * immediate dispose in cleanup would kill the instance the app keeps using, and core\n * forbids using an instance after `dispose()`. So cleanup only schedules the dispose\n * (`setTimeout(0)`); a setup that sees the same instance cancels it. A different\n * instance or a real unmount leaves the timer to fire.\n */\nexport function useDisposeOnReplace(instance: Disposable): void {\n const pending = useRef<PendingDispose | null>(null);\n\n useEffect(() => {\n const scheduled = pending.current;\n if (scheduled) {\n if (scheduled.instance === instance) clearTimeout(scheduled.timer);\n pending.current = null;\n }\n\n return () => {\n const timer = setTimeout(() => instance.dispose(), 0);\n pending.current = { instance, timer };\n };\n }, [instance]);\n}\n","import { FETCH_PRIORITY_OIDC, Passflow, type PassflowConfig, registerFetchMiddleware } from '@passflow/core';\nimport React, { type FC, type ReactNode, useCallback, useEffect, useMemo, useReducer, useRef, useState } from 'react';\nimport { UpgradeProvider, type UpgradeProviderProps } from '@/components/provider/upgrade-provider';\nimport { useDisposeOnReplace } from '@/components/provider/use-dispose-on-replace';\nimport { ContinuingStatus } from '@/components/ui/continuing-status';\nimport {\n AuthProvider,\n defaultNavigate,\n initialState,\n type NavigateFunction,\n NavigationContext,\n PassflowContext,\n passflowReducer,\n type RouterType,\n routes,\n} from '@/context';\nimport { urlCarriesTwoFactorToken } from '@/utils/second-factor';\nimport '@/styles/index.css';\n\n/**\n * The assurance-upgrade options a consumer may set on `PassflowProvider`.\n *\n * `children`, `enabled` and `backend` are owned by `PassflowProvider` itself:\n * `backend` is a top-level prop (§13.5 — \"where your API is\" is the headline\n * act, not a nested detail) and `enabled` is derived from `upgrade`/`backend`\n * below, so there is exactly one source for each.\n */\nexport type PassflowUpgradeOptions = Omit<UpgradeProviderProps, 'children' | 'enabled' | 'backend'>;\n\ntype PassflowProviderProps = PassflowConfig & {\n children: ReactNode;\n navigate?: NavigateFunction;\n router?: RouterType;\n /**\n * Where the customer's own API is — domain 2 of §13.5's two-domain\n * interception model. Nothing outside this and Passflow's own API is ever\n * observed, and there is no allow-all opt-in. `string | string[]`, an origin\n * or a same-origin path prefix (`'/api'`).\n */\n backend?: string | string[];\n /**\n * Automatic assurance upgrade (step-up). `undefined` ⇒ **off**, so no\n * existing consumer changes behaviour on upgrade. `true` ⇒ on with\n * defaults; an object ⇒ on with those options; `false` ⇒ off even when\n * `backend` is declared.\n *\n * Declaring `backend` also turns it on: naming where your API is has no\n * other meaning, and §13.5's acceptance configuration is `backend` plus one\n * attached client. The global `window.fetch` patch is a separate, explicit\n * act (`upgrade={{ interceptFetch: true }}`) and stays off by default.\n */\n upgrade?: boolean | PassflowUpgradeOptions;\n /**\n * Where to send a sign-in that lands on this page owing its second factor:\n * a federated redirect on a non-PKCE app comes back with `#tfa_token=` and\n * no tokens. A mounted `PassflowFlow` registers its own (prefixed) route,\n * which wins; set this when the landing page renders no flow, or the flow\n * is mounted elsewhere. Defaults to `routes.two_factor_verify.path`.\n */\n twoFactorVerifyPath?: string;\n};\n\n/**\n * Passflow auth-endpoint regex used by the OIDC interceptor below.\n * Matches every endpoint that takes credentials + an optional\n * parent_challenge_id so the SDK can inject the parent on outbound\n * POSTs and follow `redirect_url` on responses.\n *\n * The set is canonical with the server's AuthFlow dispatcher; if a\n * new credential endpoint lands server-side, it must be added here.\n *\n * - /auth/login — password login\n * - /auth/register — password sign-up\n * - /auth/passwordless/* — OTP / magic-link start+complete\n * - /auth/passkey/* — passkey registration/auth\n * - /auth/2fa/* — second-factor verify\n * - /auth/federated/start — federated start (callback is server)\n * - /auth/session/exchange — RFC 8693-style session exchange\n * (ADR-2; activated on Leg 2 of\n * OIDC two-step flows)\n */\nexport const AUTH_ENDPOINT_PATTERN =\n /\\/auth\\/(login|register|passwordless|passkey|2fa|session\\/exchange)\\b|\\/auth\\/federated\\/start\\b/;\n\n/**\n * Read `parent_challenge_id` from the current URL's query string.\n * Returns `undefined` when not present so callers can short-circuit\n * the OIDC interceptor on non-OIDC mounts.\n *\n * Lowercases only the parameter KEYS (not values) so the\n * KSUID-shaped value isn't corrupted on the way through. (URL params\n * are case-sensitive per RFC 3986; some Passflow URLs use mixed\n * case like `appId=...`. The lowercase-keys treatment mirrors what\n * the bundled login-app was doing pre-SDK-migration.)\n */\nexport const readParentChallengeIdFromURL = (): string | undefined => {\n if (typeof window === 'undefined') return undefined;\n const raw = new URLSearchParams(window.location.search);\n // Lowercase only keys, preserve values (values are often\n // case-sensitive — KSUIDs, JWTs, OIDC state, etc.).\n const lower = new URLSearchParams(Array.from(raw, ([key, value]) => [key.toLowerCase(), value]));\n const value = lower.get('parent_challenge_id');\n return value || undefined;\n};\n\n// Captured at module evaluation — before React mounts and before any\n// consumer-side router can rewrite the URL. The provider's mount-time\n// read stays primary (a consumer could mount the SDK long after boot,\n// on a different URL); this is the fallback that makes the OIDC opt-in\n// immune to mount-vs-navigation timing. Observed in the field: the\n// OIDF conformance login intermittently proceeded as a plain\n// first-party login (tokens in the response, no redirect_url) because\n// the whole OIDC layer keyed off a single mount-time read.\nconst bootParentChallengeId = readParentChallengeIdFromURL();\n\n/**\n * The RFC 8628 device verification page (`/oidc/device`) is the ONE auth surface\n * that must never silently exchange an existing session. A device grant is\n * approved only through the explicit authenticate → user_code confirmation →\n * approve path (see `useDeviceVerify` + src/web/oidc/device_verify.go). Letting\n * the exchange-on-mount probe solve a device parent would approve a grant with\n * no §5.4 code check — the STORM-2372 device-code phishing attack. The server\n * now refuses this at `/auth/session/exchange` too; this is the client half of\n * the same guard, so the probe never even fires here.\n */\nconst isDeviceVerificationURL = (): boolean => typeof window !== 'undefined' && window.location.pathname === '/oidc/device';\n\n/**\n * Set once the OIDC interceptor has started following a server-issued\n * `redirect_url`. Module-level on purpose: it is read by the credential forms,\n * which are siblings of the provider rather than children of a context it could\n * publish through, and its lifetime is exactly one page — the navigation it\n * records is what ends that page.\n */\nlet oidcRedirectFollowed = false;\n\n/**\n * Has the OIDC interceptor already taken ownership of the post-login navigation?\n *\n * A credential form MUST NOT navigate after a successful login when this is\n * true. Two navigations do not queue — the second cancels the first, and the\n * first is the one that completes the OIDC flow:\n *\n * 1. The interceptor calls `window.location.assign(redirect_url)` to hand the\n * authorization code back to the RP (a CLI's `127.0.0.1:<port>/callback`,\n * a web RP's `redirect_uri`, …).\n * 2. `window.location.assign` does not halt script execution, so the form's\n * success handler keeps running and sets `window.location.href` to the\n * app's default post-login page.\n * 3. The browser drops the in-flight request from (1) and goes to (2).\n *\n * Whether (1) has already been delivered when (2) lands is pure scheduling, so\n * this presents as a flake rather than a clean break. Measured against the CLI\n * loopback flow (RFC 8252 §7.3): roughly a third of real browser sign-ins had\n * the GET to the CLI's loopback port aborted mid-flight, and the CLI then sat\n * waiting for a callback that had already been cancelled until it timed out.\n */\nexport const hasFollowedOIDCRedirect = (): boolean => oidcRedirectFollowed;\n\n/**\n * Install the global OIDC AuthFlow interceptor on `fetch` and\n * `XMLHttpRequest`. The interceptor:\n *\n * 1. Injects `parent_challenge_id` on every Passflow auth POST\n * body (when one is present on the SDK's host URL).\n * 2. Watches Passflow auth responses for a JSON\n * `{ redirect_url: \"...\" }` and, when present, calls\n * `window.location.assign(redirect_url)` to follow the\n * server-side dispatch.\n *\n * Why both fetch and XHR: `@passflow/core` uses axios, which on the\n * browser delegates to XMLHttpRequest. Other consumer code (and the\n * SDK's own `/oidc/requests/{id}` GET) uses fetch. Patching both\n * keeps the interceptor uniform.\n *\n * No-op when `parent_challenge_id` is absent from the URL.\n *\n * Implementation note: previously this hook lived in the bundled\n * login-app at `login-app/src/App.tsx::useAuthFlowInterceptor`.\n * Moved into the SDK so any Passflow consumer that mounts\n * `<PassflowProvider>` gets full OIDC RP integration automatically.\n */\nconst useOIDCInterceptor = (parentChallengeId: string | undefined): void => {\n useEffect(() => {\n if (!parentChallengeId || typeof window === 'undefined') {\n return;\n }\n\n const isAuthURL = (url: string): boolean => AUTH_ENDPOINT_PATTERN.test(url);\n\n const injectParentChallenge = (raw: string | null | undefined): string | undefined => {\n if (!raw) return undefined;\n try {\n const obj = JSON.parse(raw) as Record<string, unknown>;\n if ('parent_challenge_id' in obj) return undefined;\n obj.parent_challenge_id = parentChallengeId;\n return JSON.stringify(obj);\n } catch {\n return undefined;\n }\n };\n\n const followRedirectURL = (raw: string | null | undefined): void => {\n if (!raw) return;\n try {\n const obj = JSON.parse(raw) as { redirect_url?: unknown };\n if (typeof obj.redirect_url === 'string' && obj.redirect_url) {\n // Claim the navigation BEFORE starting it. `assign` does not stop\n // JavaScript: the credential form's own success handler runs right\n // after this and would otherwise navigate on top of us. See\n // `hasFollowedOIDCRedirect` for why that is fatal, not cosmetic.\n oidcRedirectFollowed = true;\n window.location.assign(obj.redirect_url);\n }\n } catch {\n // Non-JSON — ignore.\n }\n };\n\n // fetch() interceptor (covers code paths that use the platform fetch API).\n //\n // Installed through the core's fetch registry rather than by assigning\n // `window.fetch` here. Two features that each capture and restore the\n // global compose as `A(B(native))`, and whichever cleanup runs first\n // restores a fetch that predates the other patch — so one interceptor\n // disappears non-deterministically (architecture §13.5, \"the OIDC\n // collision: 'untouched' is withdrawn\"). The registry owns the single\n // patch, reference-counts it, and never restores over a foreign patch.\n //\n // Priority matters behaviourally: OIDC is the OUTER layer\n // (`FETCH_PRIORITY_OIDC` = 10, outside `FETCH_PRIORITY_UPGRADE` = 20) so it\n // still observes the response the caller actually receives — including a\n // replayed one — which is what it reads `redirect_url` from. The logic\n // below is unchanged from the hand-rolled patch: `next` stands exactly\n // where the captured `originalFetch` stood.\n const unregisterFetchMiddleware = registerFetchMiddleware(\n async (next, input, init) => {\n let url = '';\n if (typeof input === 'string') url = input;\n else if (input instanceof URL) url = input.toString();\n else if (input instanceof Request) url = input.url;\n\n const method = init?.method?.toUpperCase() ?? 'GET';\n let outInit = init;\n if (method === 'POST' && isAuthURL(url) && typeof init?.body === 'string') {\n const rewritten = injectParentChallenge(init.body);\n if (rewritten !== undefined) outInit = { ...init, body: rewritten };\n }\n\n const response = await next(input, outInit);\n\n if (response.ok && isAuthURL(url)) {\n try {\n const cloned = response.clone();\n const text = await cloned.text();\n followRedirectURL(text);\n } catch {\n // ignore\n }\n }\n\n return response;\n },\n { priority: FETCH_PRIORITY_OIDC, name: 'passflow-oidc-authflow' },\n );\n\n // XMLHttpRequest interceptor — `@passflow/core` uses axios, which in\n // the browser uses XHR under the hood. The fetch interceptor above\n // does NOT catch those calls.\n const OriginalXHROpen = XMLHttpRequest.prototype.open;\n const OriginalXHRSend = XMLHttpRequest.prototype.send;\n\n type XHRTracker = { method?: string; url?: string; isAuth?: boolean };\n const tracker = new WeakMap<XMLHttpRequest, XHRTracker>();\n\n XMLHttpRequest.prototype.open = function (\n this: XMLHttpRequest,\n method: string,\n url: string | URL,\n ...rest: unknown[]\n ): void {\n const urlStr = typeof url === 'string' ? url : url.toString();\n tracker.set(this, {\n method: method?.toUpperCase(),\n url: urlStr,\n isAuth: isAuthURL(urlStr),\n });\n this.addEventListener('load', () => {\n const meta = tracker.get(this);\n if (!meta?.isAuth) return;\n if (this.status >= 200 && this.status < 300) {\n // Server returns 200 + JSON body { redirect_url: \"...\" } when\n // an AuthFlow parent (OIDC, federated, future upgrade) needs\n // the SPA to navigate. See ADR-2.\n followRedirectURL(typeof this.responseText === 'string' ? this.responseText : null);\n }\n });\n // @ts-expect-error spread into open's varargs signature\n OriginalXHROpen.call(this, method, url, ...rest);\n };\n\n XMLHttpRequest.prototype.send = function (this: XMLHttpRequest, body?: Document | XMLHttpRequestBodyInit | null): void {\n const meta = tracker.get(this);\n let outBody: Document | XMLHttpRequestBodyInit | null | undefined = body;\n if (meta?.isAuth && meta.method === 'POST' && typeof body === 'string') {\n const rewritten = injectParentChallenge(body);\n if (rewritten !== undefined) outBody = rewritten;\n }\n OriginalXHRSend.call(this, outBody as Document | XMLHttpRequestBodyInit | null);\n };\n\n return () => {\n // Fetch teardown is the registry's: it removes the one patch on the last\n // registration's removal and declines to restore over a stranger's patch.\n // Nothing here captures or restores `window.fetch`.\n unregisterFetchMiddleware();\n XMLHttpRequest.prototype.open = OriginalXHROpen;\n XMLHttpRequest.prototype.send = OriginalXHRSend;\n };\n }, [parentChallengeId]);\n};\n\n/**\n * Parent-challenge metadata returned by GET /oidc/requests/{id}.\n * Subset used by the SDK's exchange-on-mount probe.\n */\ntype ParentChallengeMeta = {\n request_id: string;\n app_name?: string;\n client_id?: string;\n redirect_uri?: string;\n state?: string;\n response_mode?: string;\n // Server-side fields the SDK consults to decide whether to render\n // the login form vs auto-exchange. The OP at /oidc/authorize is\n // stateless (cookie-blind by design — see ADR-2); the SDK enforces\n // prompt directives because the SDK holds the session.\n oidc_prompt_login?: boolean;\n oidc_prompt_none?: boolean;\n max_age?: number;\n};\n\n/**\n * Token-exchange-on-mount probe per ADR-2 Leg 2. When a parent\n * challenge is present in the URL AND the SDK has an existing\n * session AND the parent allows exchange (no `prompt=login`,\n * `max_age` not exceeded), POST the access token to\n * /auth/session/exchange so the OP can issue a fresh authorization\n * code for the RP without re-prompting the user.\n *\n * Decision-making is the SDK's; the server enforces too (defence in\n * depth — see `auth_util.EvaluatePolicy`).\n *\n * Today the response branches are:\n *\n * - 200 { redirect_url } → the interceptor's fetch wrapper follows\n * the redirect (sole owner of redirect_url navigation; this hook\n * must never navigate on OK responses — see the res.ok branch).\n * - 403 { error: \"upgrade_required\", ... } → falls through to the\n * login form. Factor elevation on an existing session is\n * `UpgradeProvider`'s flow, not this probe's.\n * - 401 → clear stale tokens, fall through to login form.\n *\n * On any decision-point that ends with \"render login form,\" the\n * SDK consumer's existing PassflowFlow render path picks up\n * naturally.\n */\n/**\n * `'upgrade_required'` is vestigial and kept deliberately (§8.4): it is\n * unreachable today — the 403 branch below sets `'fallback_to_login'` — and\n * removing a member from an exported union would be a type-level breaking\n * change for anyone reading `OIDCExchangeContextValue`. Assurance elevation is\n * now `UpgradeProvider`'s job, not a placeholder's.\n */\ntype ExchangeState = 'idle' | 'exchanging' | 'upgrade_required' | 'fallback_to_login';\n\nconst useSessionExchangeOnMount = (\n parentChallengeId: string | undefined,\n passflow: Passflow,\n baseUrl: string | undefined,\n appId: string | undefined,\n): { exchangeState: ExchangeState; parentMeta?: ParentChallengeMeta } => {\n const [exchangeState, setExchangeState] = useState<ExchangeState>('idle');\n const [parentMeta, setParentMeta] = useState<ParentChallengeMeta | undefined>(undefined);\n const attemptedRef = useRef(false);\n\n useEffect(() => {\n if (!parentChallengeId || attemptedRef.current) {\n return;\n }\n // Never auto-exchange on the device verification page — that would approve\n // a device grant with no user_code check (see isDeviceVerificationURL).\n if (isDeviceVerificationURL()) {\n return;\n }\n // Wait until appId has been discovered before attempting the\n // exchange — otherwise the request 400s on \"Application ID is\n // missing from request\".\n if (!appId) {\n return;\n }\n attemptedRef.current = true;\n\n const run = async () => {\n // Fetch parent metadata upfront — we need OIDC `prompt` /\n // `max_age` directives to make the right decision regardless\n // of session state.\n let meta: ParentChallengeMeta | undefined;\n try {\n const base = baseUrl ?? '';\n const url = `${base}/oidc/requests/${encodeURIComponent(parentChallengeId)}`;\n const res = await fetch(url);\n if (res.ok) {\n meta = (await res.json()) as ParentChallengeMeta;\n setParentMeta(meta);\n }\n } catch {\n // Network error fetching parent → fall through to login form;\n // the user's POST will fail loudly enough.\n }\n\n // prompt=login on parent → render login form with banner.\n // The login interceptor will pick up parent_challenge_id and\n // dispatch normally. (Check this BEFORE attempting exchange —\n // even with a session, prompt=login means we must re-prompt.)\n if (meta?.oidc_prompt_login) {\n setExchangeState('fallback_to_login');\n return;\n }\n\n // max_age check: if parent set max_age, compare against the SDK's\n // known auth_time on the access token. When the access token's\n // auth_time is older than max_age (in seconds), the parent\n // demands re-auth.\n if (meta?.max_age && meta.max_age > 0) {\n const parsed = passflow.getParsedTokens?.();\n const accessPayload = parsed?.access_token?.payload as { auth_time?: number } | undefined;\n const idPayload = parsed?.id_token?.payload as { auth_time?: number } | undefined;\n const authTime = accessPayload?.auth_time ?? idPayload?.auth_time;\n if (authTime && typeof authTime === 'number') {\n const ageSeconds = Math.floor(Date.now() / 1000) - authTime;\n if (ageSeconds > meta.max_age) {\n setExchangeState('fallback_to_login');\n return;\n }\n }\n }\n\n // Attempt exchange. Use credentials: 'include' so the cookie-mode\n // access token (HttpOnly) accompanies the request even when the\n // SDK has no token in localStorage. Server's middleware.Token\n // falls back from Authorization header to cookie automatically.\n //\n // We always attempt the exchange (don't gate on isAuthenticated()\n // because in cookie mode the SDK can't see the HttpOnly access\n // token — the server is the authority). If the server returns 401\n // we know there's no session and we fall through to login.\n setExchangeState('exchanging');\n try {\n let accessToken: string | undefined;\n try {\n const tokens = await passflow.getTokens(false);\n accessToken = tokens?.access_token;\n } catch {\n // No token in SDK storage — that's OK for cookie mode; the\n // server will read from cookie. We still call /auth/session/\n // exchange and let the server's token middleware decide.\n }\n const base = baseUrl ?? '';\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n };\n if (accessToken) {\n headers.Authorization = `Bearer ${accessToken}`;\n }\n if (appId) {\n // App middleware reads X-Passflow-ClientID; without it the\n // request gets 400 \"Application ID is missing from request\".\n headers['X-Passflow-ClientID'] = appId;\n }\n const res = await fetch(`${base}/auth/session/exchange`, {\n method: 'POST',\n credentials: 'include',\n headers,\n body: JSON.stringify({ parent_challenge_id: parentChallengeId }),\n });\n if (res.ok) {\n // Redirect-following for OK auth responses is owned SOLELY\n // by useOIDCInterceptor's fetch wrapper (this request\n // matches AUTH_ENDPOINT_PATTERN, and the wrapper follows\n // redirect_url before handing the response back to us).\n // Do NOT navigate here as well: window.location.assign()\n // doesn't halt script, so a second assign races the first\n // and re-presents the single-use authorization code to the\n // RP — observed as duplicate callback hits in OIDF\n // conformance (oidcc-id-token-hint INTERRUPTED).\n // We parse the body only to decide the no-redirect branch.\n try {\n const body = (await res.json()) as { redirect_url?: string };\n if (body.redirect_url) {\n // Interceptor navigation is already scheduled; stay in\n // 'exchanging' so no login UI flashes while we leave.\n return;\n }\n } catch {\n // ignore\n }\n // Successful but no redirect — unusual. Fall through.\n setExchangeState('fallback_to_login');\n return;\n }\n if (res.status === 403) {\n // upgrade_required. The server's MaxAge enforcement (Subtask D\n // partial) triggers this on max_age-exceeded sessions; the SDK\n // should render the login form to let the user re-auth. Factor\n // elevation on a live session is handled by `UpgradeProvider`\n // (architecture §13), which replaced the old placeholder.\n setExchangeState('fallback_to_login');\n return;\n }\n if (res.status === 401 || res.status === 400) {\n // No valid session. For prompt=none, OIDC requires us to\n // route the user back to the RP with error=login_required\n // WITHOUT rendering an interactive login form. For other\n // cases, fall through to the login form. We intentionally\n // do NOT call passflow.logOut() here — clearing cookies\n // here would also clear any session that exists but wasn't\n // visible to the SDK due to the cookie-mode HttpOnly\n // constraint; the user would lose their session for a\n // failed exchange that's the SDK's fault, not theirs.\n if (meta?.oidc_prompt_none && meta.redirect_uri) {\n const dest = new URL(meta.redirect_uri);\n dest.searchParams.set('error', 'login_required');\n dest.searchParams.set('error_description', 'user is not authenticated');\n if (meta.state) dest.searchParams.set('state', meta.state);\n window.location.assign(dest.toString());\n return;\n }\n setExchangeState('fallback_to_login');\n return;\n }\n setExchangeState('fallback_to_login');\n } catch {\n setExchangeState('fallback_to_login');\n }\n };\n\n void run();\n }, [parentChallengeId, passflow, baseUrl, appId]);\n\n return { exchangeState, parentMeta };\n};\n\n/**\n * Context surface exposed to children so the SDK's own components\n * (or consumer code) can read the OIDC parent-challenge state.\n */\nexport type OIDCExchangeContextValue = {\n parentChallengeId?: string;\n parentMeta?: ParentChallengeMeta;\n exchangeState: ExchangeState;\n};\n\n/**\n * Sends a landing that owes its second factor to the 2FA screen.\n *\n * A federated sign-in on a non-PKCE app comes back to its redirect URL with\n * the 2FA token in the fragment and no tokens. Core adopts it as it is\n * constructed (`parseQueryParams`, on by default) and strips the fragment;\n * with that off, the token is adopted here through `handleTokensRedirect()`.\n *\n * The navigation runs one render after mount, not in the mount effect: the\n * flow's router and its 2FA route register themselves in their own mount\n * effects, which run before this one, and their state lands in the next\n * render. Navigating at mount would go through the default full-page\n * navigation to the unprefixed route.\n */\nconst useSecondFactorLanding = (\n landedWithTwoFactorToken: boolean,\n passflow: Passflow,\n navigate: NavigateFunction,\n twoFactorVerifyPath: string,\n) => {\n const [pending, setPending] = useState(false);\n\n // Once, on mount — the landing is a property of the page load.\n useEffect(() => {\n if (!landedWithTwoFactorToken) return;\n // A signed-in user owes no factor: a `#tfa_token=` link is not theirs to answer.\n if (passflow.isAuthenticated()) return;\n if (!passflow.isTwoFactorVerificationRequired()) passflow.handleTokensRedirect();\n if (passflow.isTwoFactorVerificationRequired()) setPending(true);\n }, []);\n\n useEffect(() => {\n if (!pending) return;\n setPending(false);\n navigate({ to: twoFactorVerifyPath, replace: true });\n }, [pending, navigate, twoFactorVerifyPath]);\n};\n\nexport const OIDCExchangeContext = React.createContext<OIDCExchangeContextValue>({\n exchangeState: 'idle',\n});\n\nexport const PassflowProvider: FC<PassflowProviderProps> = ({\n children,\n navigate: initialNavigate,\n router = 'default',\n backend,\n upgrade,\n twoFactorVerifyPath,\n // `backend` and `upgrade` are destructured out on purpose: they are\n // interception policy, not client-wide configuration, and §13.5 keeps them\n // off `PassflowConfig` — which is what `config` is spread into below.\n ...config\n}) => {\n // If appId is not provided, set isDiscoveringAppId to true to signal\n // that auto-discovery should happen (prevents showing error before discovery)\n const needsDiscovery = !config.appId;\n\n const [state, dispatch] = useReducer(passflowReducer, {\n ...initialState,\n ...config,\n isDiscoveringAppId: needsDiscovery,\n });\n\n const [navigate, setNavigate] = useState<NavigateFunction>(() => {\n if (initialNavigate) {\n return initialNavigate;\n }\n return defaultNavigate;\n });\n\n // Read before core is constructed: core adopts `#tfa_token=` and strips it.\n const [landedWithTwoFactorToken] = useState(urlCarriesTwoFactorToken);\n\n const passflow = useMemo(() => new Passflow(state), [state]);\n useDisposeOnReplace(passflow);\n\n // OIDC AuthFlow integration: the interceptor injects\n // parent_challenge_id on outbound auth POSTs + follows\n // server-returned redirect_url; the exchange-on-mount probe decides\n // whether to render login form vs auto-exchange. See ADR-2.\n const parentChallengeId = useMemo(() => readParentChallengeIdFromURL() ?? bootParentChallengeId, []);\n useOIDCInterceptor(parentChallengeId);\n const { exchangeState, parentMeta } = useSessionExchangeOnMount(parentChallengeId, passflow, config.url, state.appId);\n\n // Auto-discover appId from /settings endpoint if not provided\n const discoveryAttemptedRef = useRef(false);\n useEffect(() => {\n if (needsDiscovery && !discoveryAttemptedRef.current && state.isDiscoveringAppId) {\n discoveryAttemptedRef.current = true;\n\n const discoverAppId = async () => {\n // Try relative path first (works with dev server proxy and same-origin production)\n // Then fall back to absolute URL if configured\n const urlsToTry = ['/settings'];\n if (config.url) {\n urlsToTry.push(`${config.url}/settings`);\n }\n\n for (const url of urlsToTry) {\n try {\n const response = await fetch(url);\n if (response.ok) {\n const settings = await response.json();\n const discoveredAppId = settings.login_app?.app_id || settings.appId;\n\n if (discoveredAppId) {\n passflow.setAppId(discoveredAppId);\n dispatch({\n type: 'SET_PASSFLOW_STATE',\n payload: {\n ...state,\n appId: discoveredAppId,\n scopes: settings.login_app?.scopes || settings.scopes || state.scopes,\n createTenantForNewUser:\n settings.login_app?.create_tenant_for_new_user ??\n settings.createTenantForNewUser ??\n state.createTenantForNewUser,\n isDiscoveringAppId: false,\n },\n });\n return;\n }\n }\n } catch (error) {}\n }\n\n // All URLs failed\n console.warn('Failed to discover appId from /settings');\n dispatch({\n type: 'SET_PASSFLOW_STATE',\n payload: {\n ...state,\n isDiscoveringAppId: false,\n },\n });\n };\n\n void discoverAppId();\n }\n }, [needsDiscovery, state.isDiscoveringAppId, config.url, passflow, state]);\n\n const passflowValue = useMemo(() => ({ state, dispatch, passflow }), [state, passflow]);\n\n const handleSetNavigate = useCallback((newNavigate: NavigateFunction | null) => {\n setNavigate(() => newNavigate || defaultNavigate);\n }, []);\n\n const [flowTwoFactorVerifyPath, setFlowTwoFactorVerifyPath] = useState<string | null>(null);\n const resolvedTwoFactorVerifyPath = flowTwoFactorVerifyPath ?? twoFactorVerifyPath ?? routes.two_factor_verify.path;\n useSecondFactorLanding(landedWithTwoFactorToken, passflow, navigate, resolvedTwoFactorVerifyPath);\n\n const navigationValue = useMemo(\n () => ({\n navigate,\n setNavigate: handleSetNavigate,\n router,\n twoFactorVerifyPath: resolvedTwoFactorVerifyPath,\n setTwoFactorVerifyPath: setFlowTwoFactorVerifyPath,\n }),\n [navigate, handleSetNavigate, router, resolvedTwoFactorVerifyPath],\n );\n\n const oidcExchangeValue = useMemo<OIDCExchangeContextValue>(\n () => ({ parentChallengeId, parentMeta, exchangeState }),\n [parentChallengeId, parentMeta, exchangeState],\n );\n\n // `undefined` ⇒ off, so no existing consumer changes behaviour. `false`\n // forces it off even when a `backend` is declared; declaring a `backend` is\n // itself an opt-in, since naming where your API is has no other meaning.\n const upgradeEnabled = upgrade === false ? false : upgrade !== undefined || backend !== undefined;\n const upgradeOptions = useMemo<PassflowUpgradeOptions>(\n () => (typeof upgrade === 'object' && upgrade !== null ? upgrade : {}),\n [upgrade],\n );\n\n // Render the placeholder while exchange is in flight. Once it\n // resolves (either via navigation or by falling through), children\n // mount as normal. The `upgrade_required` path renders children alone:\n // assurance elevation is `UpgradeProvider`'s job now (§8.4).\n return (\n <PassflowContext.Provider value={passflowValue}>\n <NavigationContext.Provider value={navigationValue}>\n <OIDCExchangeContext.Provider value={oidcExchangeValue}>\n <AuthProvider>\n {/* Mounted outside the exchange branch so a state change does not\n tear down and reinstall the upgrade interceptors. */}\n <UpgradeProvider {...upgradeOptions} enabled={upgradeEnabled} backend={backend}>\n {exchangeState === 'exchanging' ? <ContinuingStatus appName={parentMeta?.app_name} /> : children}\n </UpgradeProvider>\n </AuthProvider>\n </OIDCExchangeContext.Provider>\n </NavigationContext.Provider>\n </PassflowContext.Provider>\n );\n};\n","import type { FC } from 'react';\nimport { useEffect, useState } from 'react';\nimport { TwoFactorChallenge } from '@/components/form/two-factor-challenge';\nimport { TwoFactorRecoveryForm, TwoFactorVerifyForm } from '@/components/form/two-factor-verify';\nimport { hasFollowedOIDCRedirect } from '@/components/provider/passflow-provider';\nimport { routes } from '@/context';\nimport { useNavigation, usePassflow, useTwoFactorVerify } from '@/hooks';\nimport type { SuccessAuthRedirect } from '@/types';\nimport { getUrlWithTokens, isValidUrl, TwoFactorLoopPrevention } from '@/utils';\n\nimport '@/styles/index.css';\n\ntype TwoFactorVerifyFlowProps = {\n successAuthRedirect?: SuccessAuthRedirect;\n signInPath?: string;\n twoFactorSetupPath?: string;\n useV2Flow?: boolean;\n};\n\nexport const TwoFactorVerifyFlow: FC<TwoFactorVerifyFlowProps> = ({\n successAuthRedirect,\n signInPath = routes.signin.path,\n twoFactorSetupPath = routes.two_factor_setup?.path ?? '/two-factor-setup',\n useV2Flow = false,\n}) => {\n const [mode, setMode] = useState<'verify' | 'recovery'>('verify');\n const [shouldBlockRender, setShouldBlockRender] = useState(false);\n const { navigate } = useNavigation();\n const passflow = usePassflow();\n const { errorType } = useTwoFactorVerify();\n\n // Handle initial verification requirement check\n useEffect(() => {\n if (!passflow.isTwoFactorVerificationRequired()) {\n // Only redirect if we can safely do so (no loop detected)\n if (TwoFactorLoopPrevention.canRedirect()) {\n TwoFactorLoopPrevention.incrementRedirect();\n navigate({ to: signInPath });\n setShouldBlockRender(true);\n } else {\n // Loop detected - let component render error state\n setShouldBlockRender(false);\n }\n }\n }, [passflow, navigate, signInPath]);\n\n // Handle error-based redirect\n useEffect(() => {\n if (errorType === 'expired') {\n // Session expired - safe to redirect if no loop detected\n if (TwoFactorLoopPrevention.canRedirect()) {\n TwoFactorLoopPrevention.incrementRedirect();\n TwoFactorLoopPrevention.setLastErrorType('expired');\n\n // Brief delay for user to see \"redirecting\" message\n setTimeout(() => {\n navigate({ to: signInPath });\n }, 1500);\n }\n } else if (errorType === 'not_enabled') {\n // Configuration error - DO NOT redirect\n // Track error but don't increment redirect count\n TwoFactorLoopPrevention.setLastErrorType('not_enabled');\n }\n }, [errorType, navigate, signInPath]);\n\n const handleSuccess = async () => {\n // Reset loop prevention on successful auth\n TwoFactorLoopPrevention.reset();\n\n // `/auth/2fa/*` is an interceptor-matched endpoint, so an OIDC login that\n // required a second factor has already been dispatched back to the RP by\n // the time this runs. Navigating again would cancel that in flight — see\n // `hasFollowedOIDCRedirect`.\n if (hasFollowedOIDCRedirect()) return;\n\n if (successAuthRedirect) {\n if (!isValidUrl(successAuthRedirect)) {\n navigate({ to: successAuthRedirect });\n } else {\n window.location.href = await getUrlWithTokens(passflow, successAuthRedirect);\n }\n }\n };\n\n const handleUseRecovery = () => {\n setMode('recovery');\n };\n\n const handleBackToVerify = () => {\n setMode('verify');\n };\n\n // Don't render if we're redirecting\n if (shouldBlockRender) {\n return null;\n }\n\n // Don't render if verification not required and no loop detected\n if (!passflow.isTwoFactorVerificationRequired() && TwoFactorLoopPrevention.canRedirect()) {\n return null;\n }\n\n // V2 flow with multi-method support\n if (useV2Flow) {\n return <TwoFactorChallenge onSuccess={handleSuccess} />;\n }\n\n // Legacy V1 flow\n return (\n <>\n {mode === 'verify' ? (\n <TwoFactorVerifyForm\n onSuccess={handleSuccess}\n onUseRecovery={handleUseRecovery}\n signInPath={signInPath}\n twoFactorSetupPath={twoFactorSetupPath}\n />\n ) : (\n <TwoFactorRecoveryForm onSuccess={handleSuccess} onBack={handleBackToVerify} signInPath={signInPath} />\n )}\n </>\n );\n};\n","import type { PassflowSendPasswordResetEmailPayload } from '@passflow/core';\nimport { phone } from 'phone';\n/* eslint-disable max-len */\n/* eslint-disable react/jsx-props-no-spreading */\n/* eslint-disable complexity */\n/* eslint-disable jsx-a11y/label-has-associated-control */\nimport { type FC, useMemo } from 'react';\nimport { Controller, useForm } from 'react-hook-form';\nimport * as Yup from 'yup';\nimport { Button, FieldPhone, FieldText, Icon, Link } from '@/components/ui';\nimport { routes, useSearchSource } from '@/context';\nimport { useAppSettings, useForgotPassword, useNavigation } from '@/hooks';\nimport { cn, emailRegex, getAuthMethods, getIdentityLabel, useUrlParams } from '@/utils';\nimport { Wrapper } from '../wrapper';\n\nimport '@/styles/index.css';\nimport queryString from 'query-string';\n\nconst initialValues = {\n email_or_username: '',\n phone: '',\n};\n\nconst searchParamsForgotPasswordSchema = Yup.object().shape({\n defaultMethod: Yup.string().oneOf(['email_or_username', 'phone']).required(),\n});\n\ntype TForgotPassword = {\n successResetRedirect?: string;\n signInPath?: string;\n forgotPasswordSuccessPath?: string;\n};\n\nexport const ForgotPassword: FC<TForgotPassword> = ({\n successResetRedirect,\n signInPath = routes.signin.path,\n forgotPasswordSuccessPath = routes.forgot_password_success.path,\n}) => {\n const {\n getValues,\n control,\n register,\n formState: { errors, isDirty, isValid },\n } = useForm({\n defaultValues: initialValues,\n });\n\n const { appSettings, currentStyles, isError: isErrorApp, error: errorApp, loginAppTheme } = useAppSettings();\n\n if (isErrorApp) throw new Error(errorApp);\n\n const authMethods = useMemo(() => getAuthMethods(appSettings?.auth_strategies), [appSettings]);\n const { navigate } = useNavigation();\n const searchSource = useSearchSource();\n const { get } = useUrlParams({\n default_method: '',\n });\n\n const params = {\n defaultMethod: get('default_method'),\n };\n\n try {\n searchParamsForgotPasswordSchema.validateSync(params, { abortEarly: false });\n } catch (err) {\n throw new Error('Invalid default method param');\n }\n\n const { defaultMethod } = params;\n\n const { fetch, error, isError, isLoading } = useForgotPassword();\n\n const onSubmitHanlder = async () => {\n const values = getValues();\n const isEmail = values.email_or_username.match(emailRegex);\n const isUsername = !isEmail && values.email_or_username.length > 0;\n const validatedPhone = phone(values.phone);\n const isPhone = validatedPhone.isValid;\n\n const payload = {\n ...(isEmail && { email: values.email_or_username }),\n ...(isUsername && { username: values.email_or_username }),\n ...(isPhone && { phone: validatedPhone.phoneNumber }),\n redirect_url: successResetRedirect ?? appSettings?.defaults?.redirect,\n } as PassflowSendPasswordResetEmailPayload;\n\n const status = await fetch(payload);\n\n if (status) {\n const currentSearchParams = new URLSearchParams(searchSource.read());\n const newParams = queryString.stringify({\n ...Object.fromEntries(currentSearchParams.entries()),\n ...payload,\n });\n navigate({ to: forgotPasswordSuccessPath, search: newParams });\n }\n };\n\n // if (!state)\n // return (\n // <Navigate\n // to={{\n // pathname: signInPath ?? routes.signin.path,\n // search: window.location.search,\n // }}\n // replace\n // />\n // );\n\n const currentSubtitle =\n defaultMethod === 'email_or_username'\n ? 'Enter the email address you used when you joined and we’ll send you instructions to reset your password.'\n : 'Enter the mobile phone number you used when you joined and we’ll send you the reset link.';\n\n const currentSubscriptions =\n defaultMethod === 'email_or_username'\n ? 'For security reasons, we do NOT store your password. So rest assured that we will never send your password via email.'\n : 'For security reasons, we do NOT store your password. So rest assured that we will never send your password via SMS.';\n\n return (\n <Wrapper\n title='Forgot password?'\n subtitle={currentSubtitle}\n className='passflow-forgot-password-wrapper'\n customCss={currentStyles?.custom_css}\n customLogo={currentStyles?.logo_url}\n removeBranding={loginAppTheme?.remove_passflow_logo}\n >\n <span className='passflow-form-subscriptions'>{currentSubscriptions}</span>\n\n <form onSubmit={(e) => e.preventDefault()} className='passflow-form'>\n <div className='passflow-form-container'>\n <div className='passflow-form-field'>\n {defaultMethod === 'email_or_username' && (\n <>\n <div className='passflow-form-field__header'>\n <label htmlFor='identity' className={cn('passflow-field-label', { 'passflow-field-label--error': isError })}>\n {getIdentityLabel(authMethods, 'label')}\n </label>\n </div>\n <Controller\n name='email_or_username'\n control={control}\n rules={{\n required: 'Email is required',\n pattern: {\n value: emailRegex,\n message: 'Invalid email',\n },\n }}\n render={({ field }) => (\n <FieldText\n {...field}\n {...register('email_or_username')}\n isError={isError || Object.hasOwn(errors, 'email_or_username')}\n id='email_or_username'\n type='text'\n name='email_or_username'\n />\n )}\n />\n </>\n )}\n {defaultMethod === 'phone' && (\n <>\n <div className='passflow-form-field__header'>\n <label htmlFor='phone' className={cn('passflow-field-label', { 'passflow-field-label--error': isError })}>\n Phone\n </label>\n </div>\n <Controller\n name='phone'\n control={control}\n rules={{\n required: 'Phone is required',\n validate: (value) => {\n const validatePhone = phone(value);\n if (validatePhone.isValid) return true;\n return 'Invalid phone number';\n },\n }}\n render={({ field }) => (\n <FieldPhone\n {...field}\n {...register('phone')}\n onChange={(e) => field.onChange(e)}\n id='phone'\n name='phone'\n isError={isError || Object.hasOwn(errors, 'phone')}\n ref={null}\n />\n )}\n />\n </>\n )}\n {isError && (\n <div className='passflow-form-error'>\n <Icon size='small' id='warning' type='general' className='icon-warning' />\n <span className='passflow-form-error-text'>{error}</span>\n </div>\n )}\n </div>\n </div>\n <div className='passflow-send-reset-wrapper'>\n <Button\n size='big'\n variant='primary'\n type='button'\n disabled={!isDirty || !isValid || isLoading}\n className='passflow-button-send-reset-password'\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n onClick={onSubmitHanlder}\n >\n Send reset instructions\n </Button>\n <p className='passflow-remember-password'>\n Remember your password?{' '}\n <Link to={signInPath ?? routes.signin.path} className='passflow-link'>\n Sign In\n </Link>{' '}\n </p>\n </div>\n </form>\n </Wrapper>\n );\n};\n","/* eslint-disable no-nested-ternary */\n/* eslint-disable complexity */\nimport * as Yup from 'yup';\nimport { Button } from '@/components/ui';\nimport { useAppSettings, useForgotPassword } from '@/hooks';\nimport { Wrapper } from '../wrapper';\nimport '@/styles/index.css';\nimport type { PassflowSendPasswordResetEmailPayload } from '@passflow/core';\nimport { useUrlParams, verificationLinkErrorMessage } from '@/utils';\n\nconst searchParamsForgotPasswordSuccessSchema = Yup.object().shape({\n identity: Yup.string().oneOf(['email', 'phone']).required(),\n identityValue: Yup.string().required(),\n redirectUrl: Yup.string().required(),\n});\n\nexport const ForgotPasswordSuccess = () => {\n const { currentStyles, loginAppTheme } = useAppSettings();\n const { fetch: refetch } = useForgotPassword();\n const { get } = useUrlParams();\n\n const params = {\n identity: get('email') ? 'email' : get('phone') ? 'phone' : null,\n identityValue: get('email') ? get('email') : get('phone') ? get('phone') : null,\n redirectUrl: get('redirect_url'),\n };\n\n try {\n searchParamsForgotPasswordSuccessSchema.validateSync(params, { abortEarly: false });\n } catch (error) {\n console.error('[passflow] invalid password-reset confirmation link', error);\n throw new Error(verificationLinkErrorMessage);\n }\n\n const onClickResendHandler = async () => {\n const resendPayload = {\n ...(params.identity === 'email' ? { email: params.identityValue } : undefined),\n ...(params.identity === 'phone' ? { phone: params.identityValue } : undefined),\n redirect_url: params.redirectUrl,\n };\n\n await refetch(resendPayload as PassflowSendPasswordResetEmailPayload);\n };\n\n return (\n <Wrapper\n title={`Check your ${params.identity}`}\n className='passflow-forgot-password-success-wrapper'\n customCss={currentStyles?.custom_css}\n customLogo={currentStyles?.logo_url}\n removeBranding={loginAppTheme?.remove_passflow_logo}\n >\n <div className='passflow-forgot-password-success-container'>\n <p className='passflow-forgot-password-success-text'>\n We sent a link to {params.identity === 'phone' ? 'phone number' : 'email address'}{' '}\n <strong className='passflow-forgot-password-success-text--strong'>{params.identityValue}</strong>. Click the link to\n reset your password.\n </p>\n <Button\n size='big'\n variant='secondary'\n type='button'\n className='passflow-button-resend-reset-password'\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n onClick={onClickResendHandler}\n >\n Resend {params.identity === 'email' ? 'email' : 'SMS'}\n </Button>\n </div>\n </Wrapper>\n );\n};\n","import type { FC } from 'react';\nimport { LoginScreen } from '@/components/ui';\nimport { useAppSettings, useNavigation } from '@/hooks';\nimport { isValidUrl } from '@/utils';\n\nexport type TError = {\n goBackRedirectTo: string;\n error?: string;\n};\n\nconst defaultErrorMessage = 'Something went wrong';\n\nexport const ErrorComponent: FC<TError> = ({ error = defaultErrorMessage, goBackRedirectTo }) => {\n const { navigate } = useNavigation();\n const { currentStyles, loginAppTheme } = useAppSettings();\n\n const handleGoBack = () => {\n if (!isValidUrl(goBackRedirectTo)) navigate({ to: goBackRedirectTo });\n else window.location.href = goBackRedirectTo;\n };\n\n return (\n <LoginScreen\n chrome={{\n title: '',\n customCss: currentStyles?.custom_css,\n customLogo: currentStyles?.logo_url,\n customLogoAlt: `${loginAppTheme?.application_name ?? 'Application'} logo`,\n removeBranding: loginAppTheme?.remove_passflow_logo,\n }}\n state={{\n kind: 'general-error',\n message: error,\n onAction: handleGoBack,\n }}\n />\n );\n};\n","/* eslint-disable react/prop-types */\n/* eslint-disable react/jsx-props-no-spreading */\nimport { type ComponentType, useContext } from 'react';\nimport { ErrorBoundary, type FallbackProps } from 'react-error-boundary';\nimport type { TError } from '@/components/error';\nimport type { PassflowProps } from '@/components/flow/passflow';\nimport type { TInvitationJoinFlow, TSignIn, TSignUp } from '@/components/form';\nimport { PassflowContext } from '@/context';\n\ntype UnionType = TSignIn | TSignUp | TInvitationJoinFlow | PassflowProps;\n// react-error-boundary 6 types the caught value as unknown: anything can be thrown.\nconst toErrorMessage = (error: unknown) => (error instanceof Error ? error.message : String(error));\n\nconst excludeRoutes = ['verify-challenge-otp', 'password/reset', 'two-factor-verify', 'two-factor-recovery'];\n\nexport const withError =\n <P extends UnionType>(Component: ComponentType<P>, ErrorComponent: ComponentType<TError>) =>\n (props: P) => {\n const context = useContext(PassflowContext);\n const { successAuthRedirect } = props;\n const { pathname } = window.location;\n\n // Allow excluded routes to render without checking appId\n if (excludeRoutes.some((route) => pathname.includes(route))) {\n return (\n <ErrorBoundary\n // eslint-disable-next-line react/no-unstable-nested-components\n FallbackComponent={({ error }: FallbackProps) => (\n <ErrorComponent goBackRedirectTo={successAuthRedirect ?? '/'} error={toErrorMessage(error)} />\n )}\n >\n <Component {...props} />\n </ErrorBoundary>\n );\n }\n\n // If we're still discovering the appId, don't show error yet\n if (context?.state.isDiscoveringAppId) {\n return null; // Or render a loading spinner if desired\n }\n\n // After discovery is complete, check if we have the required config\n // Only appId is required - URL defaults to current origin if not provided\n if (!context?.state.appId) {\n const errorMessage = 'Missing appId';\n return <ErrorComponent goBackRedirectTo={successAuthRedirect ?? '/'} error={errorMessage} />;\n }\n\n return (\n <ErrorBoundary\n // eslint-disable-next-line react/no-unstable-nested-components\n FallbackComponent={({ error }: FallbackProps) => (\n <ErrorComponent goBackRedirectTo={successAuthRedirect ?? '/'} error={toErrorMessage(error)} />\n )}\n >\n <Component {...props} />\n </ErrorBoundary>\n );\n };\n\nexport default withError;\n","import { type InvitationToken, parseToken } from '@passflow/core';\nimport { type FC, useEffect } from 'react';\nimport { ErrorComponent } from '@/components/error';\nimport { LoginScreen } from '@/components/ui';\nimport { routes, useSearchSource } from '@/context';\nimport { withError } from '@/hocs';\nimport { useAppSettings, useJoinInvite, useNavigation, usePassflow } from '@/hooks';\nimport { getUrlWithTokens, invitationLinkErrorMessage, isValidUrl, undefinedOnCatch, useUrlParams } from '@/utils';\n\nexport type TInvitationJoinFlow = {\n successAuthRedirect?: string;\n signInPath?: string;\n signUpPath?: string;\n};\n\nconst InvitationJoinFlow: FC<TInvitationJoinFlow> = ({\n signInPath = routes.signin.path,\n signUpPath = routes.signup.path,\n successAuthRedirect,\n}) => {\n const { appSettings, currentStyles, loginAppTheme } = useAppSettings();\n const { navigate } = useNavigation();\n const searchSource = useSearchSource();\n const { get } = useUrlParams();\n const passflow = usePassflow();\n const { fetch: joinInvite, isLoading, error, isError } = useJoinInvite();\n const invitationToken = get('invite_token');\n const invitationTokenData = invitationToken ? undefinedOnCatch(parseToken)(invitationToken) : undefined;\n const parsedTokenCache = passflow.getParsedTokens();\n const hasAuthenticatedSession = Boolean(parsedTokenCache?.access_token);\n\n useEffect(() => {\n if (invitationTokenData && !hasAuthenticatedSession) {\n navigate({ to: signInPath, search: searchSource.read() });\n }\n }, [hasAuthenticatedSession, invitationTokenData, navigate, searchSource, signInPath]);\n\n if (!invitationTokenData) {\n console.error('[passflow] invitation token could not be parsed');\n throw new Error(invitationLinkErrorMessage);\n }\n if (!hasAuthenticatedSession) return null;\n\n const {\n inviter_name: inviterName,\n tenant_name: tenantName,\n redirect_url: redirectUrl,\n } = invitationTokenData as InvitationToken;\n\n const acceptInvitation = async () => {\n if (!invitationToken) return;\n\n const joined = await joinInvite(invitationToken);\n if (!joined) return;\n\n const successJoinPath = redirectUrl ?? successAuthRedirect ?? appSettings?.defaults?.redirect ?? '';\n if (!isValidUrl(successJoinPath)) navigate({ to: successJoinPath });\n else window.location.href = await getUrlWithTokens(passflow, successJoinPath);\n };\n\n const navigateToSignIn = () => navigate({ to: signInPath, search: searchSource.read() });\n const navigateToSignUp = () => navigate({ to: signUpPath, search: searchSource.read() });\n\n return (\n <LoginScreen\n chrome={{\n title: `You've been invited to join ${tenantName}.`,\n subtitle: 'Review the invitation before continuing.',\n customCss: currentStyles?.custom_css,\n customLogo: currentStyles?.logo_url,\n customLogoAlt: `${loginAppTheme?.application_name ?? 'Application'} logo`,\n removeBranding: loginAppTheme?.remove_passflow_logo,\n }}\n state={{\n kind: 'invitation',\n identity: parsedTokenCache?.id_token?.email,\n inviterName: inviterName || undefined,\n busy: isLoading,\n error: isError ? error : null,\n testId: 'invitation-join',\n acceptTestId: 'invitation-accept',\n onAccept: () => void acceptInvitation(),\n onSwitchAccount: navigateToSignIn,\n onCreateAccount: navigateToSignUp,\n }}\n />\n );\n};\n\nexport const InvitationJoin = withError(InvitationJoinFlow, ErrorComponent);\n","/* eslint-disable max-len */\n/* eslint-disable react/jsx-props-no-spreading */\n/* eslint-disable jsx-a11y/label-has-associated-control */\nimport type { FC } from 'react';\nimport * as Yup from 'yup';\nimport { Button, FieldPassword, Icon } from '@/components/ui';\nimport { routes } from '@/context';\nimport { useAppSettings, useNavigation, usePassflow, useResetPassword } from '@/hooks';\nimport {\n cn,\n getUrlWithTokens,\n isValidUrl,\n passwordValidation,\n routeToSecondFactor,\n undefinedOnCatch,\n useUrlParams,\n} from '@/utils';\nimport { Wrapper } from '../wrapper';\nimport '@/styles/index.css';\nimport { parseToken, type Token } from '@passflow/core';\nimport { Controller, useForm } from 'react-hook-form';\nimport type { SuccessAuthRedirect } from '@/types';\n\nconst initialValues = {\n password: '',\n};\n\nconst searchParamsResetPasswordSchema = Yup.object().shape({\n token: Yup.string().required(),\n});\n\ntype TResetPassword = {\n successAuthRedirect?: SuccessAuthRedirect;\n twoFactorVerifyPath?: string;\n};\n\ntype ResetToken = Token & {\n redirect_url: string;\n};\n\nexport const ResetPassword: FC<TResetPassword> = ({\n successAuthRedirect,\n twoFactorVerifyPath = routes.two_factor_verify.path,\n}) => {\n const {\n getValues,\n control,\n register,\n trigger,\n formState: { errors, isDirty, isValid },\n clearErrors,\n setError,\n } = useForm({\n defaultValues: initialValues,\n });\n\n const passflow = usePassflow();\n const { appSettings } = useAppSettings();\n const { fetch, error, isError, isLoading } = useResetPassword();\n const { navigate } = useNavigation();\n const { get } = useUrlParams();\n const { passwordPolicy, currentStyles, isError: isErrorApp, error: errorApp, loginAppTheme } = useAppSettings();\n\n if (isErrorApp) throw new Error(errorApp);\n\n const params = {\n token: get('token'),\n };\n\n try {\n searchParamsResetPasswordSchema.validateSync(params, { abortEarly: false });\n } catch (err) {\n throw new Error('Invalid reset token.');\n }\n\n const { token: resetToken } = params;\n\n const resetTokenData = resetToken ? undefinedOnCatch(parseToken)(resetToken) : undefined;\n\n const onSubmitHanlder = async () => {\n const values = getValues();\n const resetTokenType = resetTokenData as ResetToken;\n const status = await fetch(values.password);\n // A user with 2FA is signed in only once the second factor passes.\n if (status && routeToSecondFactor(passflow, navigate, twoFactorVerifyPath)) return;\n if (status) {\n if (!isValidUrl(resetTokenType?.redirect_url ?? successAuthRedirect ?? appSettings?.defaults?.redirect))\n navigate({ to: resetTokenType?.redirect_url ?? successAuthRedirect ?? appSettings?.defaults?.redirect });\n else\n window.location.href = await getUrlWithTokens(\n passflow,\n resetTokenType?.redirect_url ?? successAuthRedirect ?? appSettings?.defaults?.redirect,\n );\n }\n };\n\n const handlePasswordChange = async () => {\n await trigger(['password']);\n };\n\n return (\n <Wrapper\n title='Reset password'\n subtitle='Let’s get you back in.'\n className='passflow-reset-password-wrapper'\n customCss={currentStyles?.custom_css}\n customLogo={currentStyles?.logo_url}\n removeBranding={loginAppTheme?.remove_passflow_logo}\n >\n <span className='passflow-reset-password-text'>Enter your new password below.</span>\n <form\n onSubmit={(e) => {\n e.preventDefault();\n void onSubmitHanlder();\n }}\n className='passflow-form passflow-reset-password-form'\n >\n <div className='passflow-form-container'>\n <div className='passflow-form-field'>\n <div className='passflow-form-field__header'>\n <label htmlFor='password' className={cn('passflow-field-label', { 'passflow-field-label--error': isError })}>\n New password\n </label>\n </div>\n <Controller\n name='password'\n control={control}\n rules={{\n required: 'Password is required',\n validate: (value) => {\n try {\n passwordValidation(passwordPolicy).validateSync(value);\n clearErrors('password');\n return true;\n } catch (err) {\n const passwordErrors = err as { errors: string[] };\n setError('password', {\n type: 'manual',\n message: passwordErrors.errors.join(', '),\n });\n return passwordErrors.errors.join(', ');\n }\n },\n }}\n render={({ field }) => (\n <FieldPassword\n {...field}\n {...register('password')}\n isError={isError}\n passwordPolicy={passwordPolicy}\n validationErrors={\n Object.hasOwn(errors, 'password') && errors.password?.message\n ? errors.password.message.split(', ')\n : undefined\n }\n id='password'\n name='password'\n withMessages\n onChange={(e) => {\n field.onChange(e);\n void handlePasswordChange();\n }}\n />\n )}\n />\n {isError && (\n <div className='passflow-form-error'>\n <Icon size='small' id='warning' type='general' className='icon-warning' />\n <span className='passflow-form-error-text'>{error}</span>\n </div>\n )}\n </div>\n </div>\n <Button\n size='big'\n variant='primary'\n type='submit'\n disabled={!isDirty || !isValid || isLoading}\n className='passflow-button-reset-password'\n >\n Save new password\n </Button>\n </form>\n </Wrapper>\n );\n};\n","import type {\n PassflowPasskeyAuthenticateStartPayload,\n PassflowPasswordlessResponse,\n PassflowPasswordlessSignInPayload,\n PassflowSignInPayload,\n Providers,\n} from '@passflow/core';\nimport { phone } from 'phone';\nimport queryString from 'query-string';\nimport type { FC } from 'react';\nimport { useMemo } from 'react';\nimport { ErrorComponent } from '@/components/error';\nimport { hasFollowedOIDCRedirect, readParentChallengeIdFromURL } from '@/components/provider/passflow-provider';\nimport { type LoginCredentialsValues, type LoginMethodConfig, LoginScreen } from '@/components/ui';\nimport { routes, useSearchSource } from '@/context';\nimport { withError } from '@/hocs';\nimport { useAppSettings, useNavigation, usePassflow, useProvider, useSignIn } from '@/hooks';\nimport type { SuccessAuthRedirect } from '@/types';\nimport {\n type AuthMethods,\n authRedirectErrorMessage,\n emailRegex,\n getAuthMethods,\n getIdentityLabel,\n getInvitationAuthChrome,\n getPasswordlessData,\n getUrlErrors,\n getUrlWithTokens,\n isValidUrl,\n routeToSecondFactor,\n useUrlParams,\n} from '@/utils';\n\nconst getLoginMethodConfig = (authMethods: AuthMethods): LoginMethodConfig => {\n const identities: LoginMethodConfig['identities'] = [];\n\n if (authMethods.hasSignInEmailMethods || authMethods.hasSignInUsernameMethods) {\n const label = getIdentityLabel(authMethods, 'label') ?? 'Email or username';\n identities.push({\n id: 'email_or_username',\n label,\n selectLabel: getIdentityLabel(authMethods, 'button') ?? 'Use email',\n requiredMessage: `${label} is required`,\n format: authMethods.hasSignInEmailMethods && !authMethods.hasSignInUsernameMethods ? 'email' : undefined,\n password: authMethods.internal.email.password || authMethods.internal.username.password,\n passwordlessLabel: getPasswordlessData(authMethods, 'email_or_username')?.label,\n });\n }\n\n if (authMethods.hasSignInPhoneMethods) {\n identities.push({\n id: 'phone',\n label: 'Phone number',\n selectLabel: 'Use phone',\n requiredMessage: 'Phone number is required',\n password: authMethods.internal.phone.password,\n passwordlessLabel: getPasswordlessData(authMethods, 'phone')?.label,\n });\n }\n\n return {\n identities,\n passkey: authMethods.passkey,\n providers: authMethods.fim.providers,\n };\n};\n\nexport type TSignIn = {\n successAuthRedirect?: SuccessAuthRedirect;\n relyingPartyId?: string;\n federatedDisplayMode?: 'modal' | 'redirect';\n signUpPath?: string;\n verifyOTPPath?: string;\n verifyMagicLinkPath?: string;\n forgotPasswordPath?: string;\n twoFactorVerifyPath?: string;\n};\n\nexport const SignInForm: FC<TSignIn> = ({\n successAuthRedirect,\n relyingPartyId = window.location.hostname,\n signUpPath = routes.signup.path,\n verifyOTPPath = routes.verify_otp.path,\n verifyMagicLinkPath = routes.verify_magic_link.path,\n forgotPasswordPath = routes.forgot_password.path,\n twoFactorVerifyPath = routes.two_factor_verify.path,\n}) => {\n const passflow = usePassflow();\n const { navigate } = useNavigation();\n const searchSource = useSearchSource();\n const {\n appSettings,\n scopes,\n createTenantForNewUser,\n passwordPolicy,\n currentStyles,\n isError: isErrorApp,\n error: errorApp,\n loginAppTheme,\n } = useAppSettings();\n const { federatedWithRedirect } = useProvider(successAuthRedirect, createTenantForNewUser);\n\n if (isErrorApp) throw new Error(errorApp);\n\n const authMethods = useMemo(() => getAuthMethods(appSettings?.auth_strategies), [appSettings]);\n const loginMethods = useMemo(() => getLoginMethodConfig(authMethods), [authMethods]);\n const { error: errorUrl, message: messageUrl } = getUrlErrors();\n\n if (errorUrl) {\n console.error('[passflow] sign-in redirect returned an error', { error: errorUrl, message: messageUrl });\n throw new Error(authRedirectErrorMessage);\n }\n\n const { get } = useUrlParams({ invite_token: '' });\n const inviteToken = get('invite_token');\n const invitationChrome = getInvitationAuthChrome(inviteToken, 'sign-in');\n const { fetch, isError, error, reset, isLoading } = useSignIn();\n\n const oidcLayerOwnsRedirect = (): boolean => {\n if (hasFollowedOIDCRedirect()) return true;\n if (readParentChallengeIdFromURL()) {\n console.error(\n '[passflow] login took the legacy token path while parent_challenge_id is present on the URL — the OIDC interceptor did not engage and the RP redirect will not happen',\n );\n }\n return false;\n };\n\n const completeAuthentication = async () => {\n if (routeToSecondFactor(passflow, navigate, twoFactorVerifyPath ?? routes.two_factor_verify.path)) return;\n if (oidcLayerOwnsRedirect()) return;\n const redirectUrl = successAuthRedirect ?? appSettings?.defaults?.redirect ?? '';\n if (!isValidUrl(redirectUrl)) navigate({ to: redirectUrl });\n else window.location.href = await getUrlWithTokens(passflow, redirectUrl);\n };\n\n const submitPassword = async (userPayload: PassflowSignInPayload) => {\n const payload = {\n ...userPayload,\n ...(inviteToken && { invite_token: inviteToken }),\n } as PassflowSignInPayload;\n\n const status = await fetch(payload, 'password');\n if (status) await completeAuthentication();\n };\n\n const submitPasskey = async (passkeyPayload: PassflowPasskeyAuthenticateStartPayload) => {\n const payload = {\n ...passkeyPayload,\n ...(inviteToken && { invite_token: inviteToken }),\n } as PassflowPasskeyAuthenticateStartPayload;\n\n const response = await fetch(payload, 'passkey');\n if (response) await completeAuthentication();\n };\n\n const submitPasswordless = async (\n userPayload: Partial<PassflowPasswordlessSignInPayload>,\n method: LoginCredentialsValues['method'],\n ) => {\n const challengeType = getPasswordlessData(authMethods, method)?.challengeType;\n const payload = {\n ...userPayload,\n challenge_type: challengeType,\n create_tenant: createTenantForNewUser,\n redirect_url: successAuthRedirect ?? appSettings?.defaults?.redirect,\n ...(inviteToken && { invite_token: inviteToken }),\n } as PassflowPasswordlessSignInPayload;\n\n const response = await fetch(payload, 'passwordless');\n if (!response) return;\n\n const passwordlessResponse = response as PassflowPasswordlessResponse;\n const params = new URLSearchParams(searchSource.read());\n const newParams = queryString.stringify({\n ...Object.fromEntries(params.entries()),\n ...payload,\n ...passwordlessResponse,\n type: 'passwordless',\n challenge_type: challengeType,\n create_tenant: createTenantForNewUser,\n });\n\n if (challengeType === 'otp') navigate({ to: verifyOTPPath ?? routes.verify_otp.path, search: newParams });\n if (challengeType === 'magic_link')\n navigate({ to: verifyMagicLinkPath ?? routes.verify_magic_link.path, search: newParams });\n };\n\n const handlePassword = async (values: LoginCredentialsValues) => {\n const isEmail = Boolean(values.emailOrUsername.match(emailRegex));\n const isUsername = values.method === 'email_or_username' && !isEmail && values.emailOrUsername.length > 0;\n const validatedPhone = phone(values.phone);\n const payload = {\n ...(isEmail && { email: values.emailOrUsername }),\n ...(isUsername && { username: values.emailOrUsername }),\n ...(validatedPhone.isValid && { phone: validatedPhone.phoneNumber }),\n scopes,\n password: values.password,\n };\n\n await submitPassword(payload as PassflowSignInPayload);\n };\n\n const handlePasswordless = async (values: LoginCredentialsValues) => {\n const isEmail = Boolean(values.emailOrUsername.match(emailRegex));\n const validatedPhone = phone(values.phone);\n const payload = {\n ...(isEmail && { email: values.emailOrUsername }),\n ...(validatedPhone.isValid && { phone: validatedPhone.phoneNumber }),\n scopes,\n };\n\n await submitPasswordless(payload as Partial<PassflowPasswordlessSignInPayload>, values.method);\n };\n\n const handlePasskey = async () => {\n await submitPasskey({ relying_party_id: relyingPartyId, scopes });\n };\n\n const handleProvider = (provider: Providers) => federatedWithRedirect(provider, inviteToken ?? undefined);\n\n return (\n <LoginScreen\n chrome={{\n title: invitationChrome?.title ?? 'Sign In to your account',\n subtitle: invitationChrome?.subtitle ?? 'To Passflow by Madappgang',\n variant: 'sign-in',\n customCss: currentStyles?.custom_css,\n customLogo: currentStyles?.logo_url,\n customLogoAlt: `${loginAppTheme?.application_name ?? 'Application'} logo`,\n removeBranding: loginAppTheme?.remove_passflow_logo,\n }}\n state={{\n kind: 'credentials',\n methods: loginMethods,\n passwordPolicy,\n forcePasskey: Boolean(appSettings?.force_passwordless_login && authMethods.passkey),\n allowPasskeyToggle: true,\n busy: isLoading,\n primaryLabel: isLoading ? 'Signing in…' : 'Sign In',\n error: isError ? error : null,\n forgotPassword: {\n to: forgotPasswordPath ?? routes.forgot_password.path,\n getSearch: (method) =>\n queryString.stringify({\n ...queryString.parse(searchSource.read()),\n default_method: method,\n }),\n },\n footer: {\n prompt: \"Don't have an account?\",\n label: 'Sign Up',\n to: signUpPath ?? routes.signup.path,\n search: searchSource.read(),\n },\n onPassword: (values) => void handlePassword(values),\n onPasswordless: (values) => void handlePasswordless(values),\n onPasskey: () => void handlePasskey(),\n onProvider: handleProvider,\n onReset: reset,\n }}\n />\n );\n};\n\nexport const SignIn = withError(SignInForm, ErrorComponent);\n","import type {\n PassflowPasskeyRegisterStartPayload,\n PassflowPasswordlessResponse,\n PassflowPasswordlessSignInPayload,\n PassflowSignUpPayload,\n PassflowUserPayload,\n Providers,\n} from '@passflow/core';\nimport { phone } from 'phone';\nimport queryString from 'query-string';\nimport type { FC } from 'react';\nimport { useMemo } from 'react';\nimport { ErrorComponent } from '@/components/error';\nimport { hasFollowedOIDCRedirect } from '@/components/provider/passflow-provider';\nimport { type LoginCredentialsValues, type LoginMethodConfig, LoginScreen } from '@/components/ui';\nimport { routes, useSearchSource } from '@/context';\nimport { withError } from '@/hocs';\nimport { useAppSettings, useNavigation, usePassflow, useProvider, useSignUp } from '@/hooks';\nimport type { DefaultMethod, SuccessAuthRedirect } from '@/types';\nimport {\n type AuthMethods,\n authRedirectErrorMessage,\n emailRegex,\n getAuthMethods,\n getInvitationAuthChrome,\n getPasswordlessData,\n getUrlErrors,\n getUrlWithTokens,\n isValidUrl,\n routeToSecondFactor,\n useUrlParams,\n} from '@/utils';\n\nconst getSignUpMethodConfig = (authMethods: AuthMethods): LoginMethodConfig => {\n const identities: LoginMethodConfig['identities'] = [];\n\n if (authMethods.hasEmailMethods || authMethods.hasUsernameMethods) {\n const label =\n authMethods.hasEmailMethods && authMethods.hasUsernameMethods\n ? 'Email or username'\n : authMethods.hasUsernameMethods\n ? 'Username'\n : 'Email';\n identities.push({\n id: 'email_or_username',\n label,\n selectLabel: authMethods.hasUsernameMethods && !authMethods.hasEmailMethods ? 'Use username' : 'Use email',\n requiredMessage: `${label} is required`,\n format: authMethods.hasEmailMethods && !authMethods.hasUsernameMethods ? 'email' : undefined,\n password: authMethods.internal.email.password || authMethods.internal.username.password,\n passwordlessLabel: getPasswordlessData(authMethods, 'email_or_username')?.label,\n });\n }\n\n if (authMethods.hasPhoneMethods) {\n identities.push({\n id: 'phone',\n label: 'Phone number',\n selectLabel: 'Use phone',\n requiredMessage: 'Phone number is required',\n password: authMethods.internal.phone.password,\n passwordlessLabel: getPasswordlessData(authMethods, 'phone')?.label,\n });\n }\n\n return {\n identities,\n passkey: authMethods.passkey,\n providers: authMethods.fim.providers,\n };\n};\n\nexport type TSignUp = {\n successAuthRedirect?: SuccessAuthRedirect;\n relyingPartyId?: string;\n federatedDisplayMode?: 'modal' | 'redirect';\n signInPath?: string;\n verifyOTPPath?: string;\n verifyMagicLinkPath?: string;\n twoFactorVerifyPath?: string;\n};\n\nexport const SignUpForm: FC<TSignUp> = ({\n successAuthRedirect,\n relyingPartyId = window.location.hostname,\n signInPath = routes.signin.path,\n verifyOTPPath = routes.verify_otp.path,\n verifyMagicLinkPath = routes.verify_magic_link.path,\n twoFactorVerifyPath = routes.two_factor_verify.path,\n}) => {\n const passflow = usePassflow();\n const { navigate } = useNavigation();\n const searchSource = useSearchSource();\n const {\n appSettings,\n scopes,\n createTenantForNewUser,\n passwordPolicy,\n currentStyles,\n isError: isErrorApp,\n error: errorApp,\n loginAppTheme,\n } = useAppSettings();\n const { federatedWithRedirect } = useProvider(successAuthRedirect, createTenantForNewUser);\n\n if (isErrorApp) throw new Error(errorApp);\n\n const authMethods = useMemo(() => getAuthMethods(appSettings?.auth_strategies), [appSettings]);\n const loginMethods = useMemo(() => getSignUpMethodConfig(authMethods), [authMethods]);\n const { error: errorUrl, message: messageUrl } = getUrlErrors();\n\n if (errorUrl) {\n console.error('[passflow] sign-up redirect returned an error', { error: errorUrl, message: messageUrl });\n throw new Error(authRedirectErrorMessage);\n }\n\n const { get } = useUrlParams({ invite_token: '' });\n const inviteToken = get('invite_token');\n const invitationChrome = getInvitationAuthChrome(inviteToken, 'sign-up');\n const { fetch, isError, error, reset, isLoading } = useSignUp();\n\n // The server can answer a sign-up with a 2FA token in place of tokens, as it\n // does a sign-in, so the 2FA screen comes before any success redirect.\n const completeRegistration = async ({ oidcMayOwnRedirect = false } = {}) => {\n if (routeToSecondFactor(passflow, navigate, twoFactorVerifyPath ?? routes.two_factor_verify.path)) return;\n if (oidcMayOwnRedirect && hasFollowedOIDCRedirect()) return;\n const redirectUrl = successAuthRedirect ?? appSettings?.defaults?.redirect ?? '';\n if (!isValidUrl(redirectUrl)) navigate({ to: redirectUrl });\n else window.location.href = await getUrlWithTokens(passflow, redirectUrl);\n };\n\n const submitPassword = async (userPayload: PassflowUserPayload) => {\n const payload = {\n user: userPayload,\n create_tenant: createTenantForNewUser,\n ...(inviteToken ? { invite_token: inviteToken } : {}),\n } as PassflowSignUpPayload;\n\n if (await fetch(payload, 'password')) await completeRegistration({ oidcMayOwnRedirect: true });\n };\n\n const submitPasskey = async () => {\n const redirectUrl = successAuthRedirect ?? appSettings?.defaults?.redirect ?? '';\n const payload = {\n relying_party_id: relyingPartyId,\n create_tenant: createTenantForNewUser,\n redirect_url: redirectUrl,\n ...(inviteToken ? { invite_token: inviteToken } : {}),\n scopes,\n } as PassflowPasskeyRegisterStartPayload;\n\n if (await fetch(payload, 'passkey')) await completeRegistration({ oidcMayOwnRedirect: true });\n };\n\n const submitPasswordless = async (userPayload: Partial<PassflowPasswordlessSignInPayload>, method: DefaultMethod | null) => {\n const challengeType = getPasswordlessData(authMethods, method)?.challengeType;\n const payload = {\n ...userPayload,\n challenge_type: challengeType,\n create_tenant: createTenantForNewUser,\n redirect_url: successAuthRedirect ?? appSettings?.defaults?.redirect,\n ...(inviteToken ? { invite_token: inviteToken } : {}),\n } as PassflowPasswordlessSignInPayload;\n\n const response = await fetch(payload, 'passwordless');\n if (!response) return;\n\n const passwordlessResponse = response as PassflowPasswordlessResponse;\n const params = new URLSearchParams(searchSource.read());\n const newParams = queryString.stringify({\n ...Object.fromEntries(params.entries()),\n ...payload,\n ...passwordlessResponse,\n type: 'passwordless',\n challenge_type: challengeType,\n create_tenant: createTenantForNewUser,\n });\n\n if (challengeType === 'otp') navigate({ to: verifyOTPPath ?? routes.verify_otp.path, search: newParams });\n if (challengeType === 'magic_link')\n navigate({ to: verifyMagicLinkPath ?? routes.verify_magic_link.path, search: newParams });\n };\n\n const handlePassword = async (values: LoginCredentialsValues) => {\n const isEmail = Boolean(values.emailOrUsername.match(emailRegex));\n const isUsername = values.method === 'email_or_username' && !isEmail && values.emailOrUsername.length > 0;\n const validatedPhone = phone(values.phone);\n const user = {\n ...(isEmail ? { email: values.emailOrUsername } : {}),\n ...(isUsername ? { username: values.emailOrUsername } : {}),\n ...(validatedPhone.isValid ? { phone_number: validatedPhone.phoneNumber } : {}),\n password: values.password,\n scopes,\n } as PassflowUserPayload;\n\n await submitPassword(user);\n };\n\n const handlePasswordless = async (values: LoginCredentialsValues) => {\n const isEmail = Boolean(values.emailOrUsername.match(emailRegex));\n const validatedPhone = phone(values.phone);\n const payload = {\n ...(isEmail ? { email: values.emailOrUsername } : {}),\n ...(validatedPhone.isValid ? { phone: validatedPhone.phoneNumber } : {}),\n scopes,\n };\n\n await submitPasswordless(payload as Partial<PassflowPasswordlessSignInPayload>, values.method);\n };\n\n const handleProvider = (provider: Providers) => federatedWithRedirect(provider, inviteToken ?? undefined);\n\n return (\n <LoginScreen\n chrome={{\n title: invitationChrome?.title ?? 'Create your account',\n subtitle: invitationChrome?.subtitle ?? 'For Passflow by Madappgang',\n variant: 'sign-in',\n customCss: currentStyles?.custom_css,\n customLogo: currentStyles?.logo_url,\n customLogoAlt: `${loginAppTheme?.application_name ?? 'Application'} logo`,\n removeBranding: loginAppTheme?.remove_passflow_logo,\n }}\n state={{\n kind: 'credentials',\n methods: loginMethods,\n passwordPolicy,\n credentialPurpose: 'sign-up',\n forcePasskey: Boolean(appSettings?.force_passwordless_login && authMethods.passkey),\n allowPasskeyToggle: true,\n busy: isLoading,\n primaryLabel: isLoading ? 'Creating account…' : 'Sign Up',\n passwordlessLabelPrefix: 'Sign Up with',\n passkeyLabel: 'Sign Up with a Passkey',\n error: isError ? error : null,\n footer: {\n prompt: 'Already have an account?',\n label: 'Sign In',\n to: signInPath ?? routes.signin.path,\n search: searchSource.read(),\n },\n onPassword: (values) => void handlePassword(values),\n onPasswordless: (values) => void handlePasswordless(values),\n onPasskey: () => void submitPasskey(),\n onProvider: handleProvider,\n onReset: reset,\n }}\n />\n );\n};\n\nexport const SignUp = withError(SignUpForm, ErrorComponent);\n","/* eslint-disable no-nested-ternary */\nimport type { PassflowPasswordlessSignInPayload } from '@passflow/core';\nimport { Button } from '@/components/ui';\nimport { useAppSettings, useSignIn } from '@/hooks';\nimport { Wrapper } from '../wrapper';\nimport '@/styles/index.css';\nimport { useUrlParams } from '@/utils';\n\nconst challengeTypeFullString = {\n email: 'email address',\n phone: 'phone number',\n};\n\nexport const VerifyChallengeMagicLink = () => {\n const { currentStyles, loginAppTheme } = useAppSettings();\n const { fetch: refetch } = useSignIn();\n const { get } = useUrlParams({\n identity: '',\n identity_value: '',\n challenge_type: '',\n type: '',\n redirect_url: '',\n });\n\n const identity = get('email') ? 'email' : get('phone') ? 'phone' : undefined;\n const identityValue = get('email') ? get('email') : get('phone') ? get('phone') : undefined;\n const challengeType = get('challenge_type');\n const type = get('type') as 'passkey' | 'password' | 'passwordless';\n const redirectUrl = get('redirect_url');\n\n const onClickResendHandler = async () => {\n const resendPayload = {\n ...(identity === 'email' ? { email: identityValue } : undefined),\n ...(identity === 'phone' ? { phone: identityValue } : undefined),\n challenge_type: challengeType,\n redirect_url: redirectUrl,\n };\n\n await refetch(resendPayload as PassflowPasswordlessSignInPayload, type);\n };\n\n return (\n <Wrapper\n title='Check your email'\n className='passflow-verify-challenge-magic-link-wrapper'\n customCss={currentStyles?.custom_css}\n customLogo={currentStyles?.logo_url}\n removeBranding={loginAppTheme?.remove_passflow_logo}\n >\n <div className='passflow-verify-challenge-magic-link-container'>\n <p className='passflow-verify-challenge-magic-link-text'>\n We sent a link to {challengeTypeFullString[identity as keyof typeof challengeTypeFullString]}{' '}\n {identityValue && <strong className='passflow-verify-challenge-magic-link-text--strong'>{identityValue}</strong>}.\n Click on the link to confirm your registration.\n </p>\n {type === 'passwordless' && (\n <Button\n size='big'\n variant='secondary'\n type='button'\n className='passflow-button-resend-magic-link'\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n onClick={onClickResendHandler}\n >\n Resend email\n </Button>\n )}\n </div>\n </Wrapper>\n );\n};\n","import { type FC, type PropsWithChildren, useEffect, useState } from 'react';\nimport { Button } from '@/components/ui';\nimport '@/styles/index.css';\nimport { cn } from '@/utils';\n\ntype TTimerButton = PropsWithChildren & {\n totalSecond: number;\n onClick: () => void;\n className?: string;\n};\n\nexport const TimerButton: FC<TTimerButton> = ({ totalSecond, onClick, className = '', ...props }) => {\n const [seconds, setSeconds] = useState(totalSecond);\n\n useEffect(() => {\n const interval = setInterval(() => {\n if (seconds > 0) {\n setSeconds((prev) => prev - 1);\n }\n }, 1000);\n\n return () => {\n clearInterval(interval);\n };\n }, [seconds]);\n\n const onClickHandler = () => {\n onClick();\n setSeconds(totalSecond);\n };\n\n return (\n <Button\n disabled={seconds > 0}\n size='small'\n variant='clean'\n type='button'\n className={cn(\n 'passflow-button-timer',\n {\n 'passflow-button-timer--active': seconds > 0,\n 'passflow-button-timer--inactive': seconds === 0,\n },\n className,\n )}\n onClick={onClickHandler}\n {...props}\n >\n Resend {seconds > 0 ? `(${seconds})` : ''}\n </Button>\n );\n};\n","import type { FC } from 'react';\nimport { useAppSettings } from '@/hooks';\nimport { Wrapper } from '../wrapper';\n\nexport const VerifyChallengeSuccess: FC = () => {\n const { currentStyles, loginAppTheme } = useAppSettings();\n\n return (\n <Wrapper\n iconId='logo'\n className='passflow-verify-challenge-success-wrapper'\n customCss={currentStyles?.custom_css}\n customLogo={currentStyles?.logo_url}\n removeBranding={loginAppTheme?.remove_passflow_logo}\n >\n <div className='passflow-verify-challenge-success-wrapper'>\n <div className='passflow-verify-challenge-success-container'>\n <p className='passflow-verify-challenge-success-text'>Successful verification!</p>\n <p className='passflow-verify-challenge-success-text-secondary'>But there is no redirect URL for further redirect.</p>\n </div>\n </div>\n </Wrapper>\n );\n};\n","import type {\n InternalStrategyChallenge,\n PassflowPasswordlessResponse,\n PassflowPasswordlessSignInCompletePayload,\n PassflowPasswordlessSignInPayload,\n} from '@passflow/core';\n/* eslint-disable no-void */\n/* eslint-disable complexity */\nimport { type FC, useEffect, useId, useState } from 'react';\nimport { Button, FieldOtp, Icon } from '@/components/ui';\nimport { routes } from '@/context';\nimport { useAppSettings, useNavigation, usePassflow, usePasswordlessComplete, useSignIn } from '@/hooks';\nimport { getUrlWithTokens, isValidUrl, routeToSecondFactor, useUrlParams } from '@/utils';\nimport { Wrapper } from '../wrapper';\nimport { TimerButton } from './timer-button';\nimport { VerifyChallengeSuccess } from './verify-challenge-success';\n\nimport '@/styles/index.css';\n\ntype VerifyChallengeOTPManualProps = {\n identity: string | null;\n identityValue: string | null;\n challengeType: string | null;\n challengeId: string | null;\n type: 'passwordless' | 'passkey' | null;\n numInputs: number;\n shouldAutoFocus: boolean;\n signUpPath: string;\n successAuthRedirect?: string;\n twoFactorVerifyPath?: string;\n};\n\nconst challengeTypeFullString = {\n email: 'email address',\n phone: 'phone number',\n};\n\nexport const VerifyChallengeOTPManual: FC<VerifyChallengeOTPManualProps> = ({\n identity,\n identityValue,\n challengeType,\n challengeId,\n type,\n numInputs,\n shouldAutoFocus,\n successAuthRedirect,\n signUpPath,\n twoFactorVerifyPath = routes.two_factor_verify.path,\n}) => {\n const passflow = usePassflow();\n const { appSettings, createTenantForNewUser, currentStyles, loginAppTheme } = useAppSettings();\n const { navigate } = useNavigation();\n const { fetch: refetch } = useSignIn();\n const { fetch: fetchPasswordlessComplete, isError, error } = usePasswordlessComplete();\n const [valueOTP, setValueOTP] = useState('');\n const [paramsError, setParamsError] = useState<string | null>(null);\n const [showSuccessMessage, setShowSuccessMessage] = useState(false);\n const { set } = useUrlParams();\n const otpId = useId();\n const otpErrorId = `${otpId}-error`;\n\n const onChangeOTP = (value: string) => setValueOTP(value);\n\n const onClickResendHandler = async () => {\n if (type && identity && identityValue && challengeType) {\n const payload: PassflowPasswordlessSignInPayload = {\n create_tenant: createTenantForNewUser,\n challenge_type: challengeType as InternalStrategyChallenge,\n redirect_url: successAuthRedirect ?? appSettings?.defaults?.redirect ?? '',\n ...(identity === 'email' ? { email: identityValue } : { phone: identityValue }),\n };\n\n const refetchResponse = (await refetch(payload, type)) as PassflowPasswordlessResponse;\n if (refetchResponse) {\n set({ challenge_id: refetchResponse.challenge_id });\n } else {\n setParamsError('Something went wrong. Please try again later.');\n }\n }\n };\n\n useEffect(() => {\n if (valueOTP.length === numInputs && challengeId) {\n const payload: PassflowPasswordlessSignInCompletePayload = {\n challenge_id: challengeId,\n challenge_type: 'otp',\n otp: valueOTP,\n };\n const fetchData = async () => {\n const response = await fetchPasswordlessComplete(payload);\n if (response) {\n // The code completed the first factor only: no tokens yet.\n if (routeToSecondFactor(passflow, navigate, twoFactorVerifyPath)) return;\n if (response.redirect_url) {\n if (!isValidUrl(response.redirect_url)) navigate({ to: response.redirect_url });\n else window.location.href = await getUrlWithTokens(passflow, response.redirect_url);\n } else {\n setShowSuccessMessage(true);\n }\n }\n };\n void fetchData();\n }\n }, [valueOTP, numInputs, fetchPasswordlessComplete, challengeId, navigate, passflow, twoFactorVerifyPath]);\n\n if (paramsError) throw new Error(paramsError);\n\n if (showSuccessMessage) return <VerifyChallengeSuccess />;\n\n const onClickNavigateBack = () => navigate({ to: signUpPath });\n\n return (\n <Wrapper\n title={`Verify your ${identity}`}\n subtitle={`We sent OTP code to your ${challengeTypeFullString[identity as keyof typeof challengeTypeFullString]}`}\n className='passflow-verify-otp'\n customCss={currentStyles?.custom_css}\n customLogo={currentStyles?.logo_url}\n removeBranding={loginAppTheme?.remove_passflow_logo}\n >\n <div className='passflow-verify-otp-container'>\n {identityValue && (\n <Button\n size='big'\n type='button'\n variant='outlined'\n className='passflow-verify-otp-button'\n withIcon\n onClick={onClickNavigateBack}\n >\n <Icon id={identity === 'email' ? 'mail' : 'phone'} type='general' size='small' />\n {identityValue}\n <Icon id='edit' type='general' size='small' className='passflow-verify-otp-button-icon' />\n </Button>\n )}\n <div id='otp-wrapper' className='passflow-verify-otp-wrapper'>\n <FieldOtp\n id={otpId}\n name='otp'\n length={numInputs}\n value={valueOTP}\n onChange={onChangeOTP}\n state={isError ? 'error' : 'default'}\n label='Verification code'\n describedBy={isError ? otpErrorId : undefined}\n autoFocus={shouldAutoFocus}\n />\n {isError && (\n <div className='passflow-verify-otp-error'>\n <Icon size='small' id='warning' type='general' className='icon-warning' />\n <span id={otpErrorId} className='passflow-verify-otp-error-text'>\n {error}\n </span>\n </div>\n )}\n </div>\n </div>\n {type === 'passwordless' && (\n <p className='passflow-verify-otp-resend'>\n Don't receive a code?\n <TimerButton totalSecond={30} onClick={() => void onClickResendHandler()} />\n </p>\n )}\n </Wrapper>\n );\n};\n","import { useEffect, useState } from 'react';\nimport { routes } from '@/context';\nimport { useNavigation, usePassflow, usePasswordlessComplete } from '@/hooks';\nimport {\n getUrlWithTokens,\n isValidUrl,\n routeToSecondFactor,\n verificationLinkErrorMessage,\n verificationRequestErrorMessage,\n} from '@/utils';\nimport { VerifyChallengeSuccess } from './verify-challenge-success';\n\ntype VerifyChallengeOTPRedirectProps = {\n appId: string | null;\n otp: string | null;\n challengeId: string | null;\n twoFactorVerifyPath?: string;\n};\n\nexport const VerifyChallengeOTPRedirect = ({\n otp,\n challengeId,\n appId,\n twoFactorVerifyPath = routes.two_factor_verify.path,\n}: VerifyChallengeOTPRedirectProps) => {\n const passflow = usePassflow();\n const { navigate } = useNavigation();\n const [paramsError, setParamsError] = useState<string | null>(null);\n const [showSuccessMessage, setShowSuccessMessage] = useState(false);\n const { fetch, isError, error, isLoading } = usePasswordlessComplete();\n\n // Run once on mount - intentionally empty dependency array\n useEffect(() => {\n const fetchData = async () => {\n if (!appId || !otp || !challengeId) {\n const missingParameters = [!appId && 'app_id', !otp && 'otp', !challengeId && 'challenge_id'].filter(Boolean);\n console.error('[passflow] passwordless verification redirect is missing required parameters', missingParameters);\n setParamsError(verificationLinkErrorMessage);\n return;\n }\n\n if (!isLoading) {\n const response = await fetch({ otp, challenge_id: challengeId });\n\n if (response) {\n // The link completed the first factor only: no tokens yet.\n if (routeToSecondFactor(passflow, navigate, twoFactorVerifyPath)) return;\n if (response.redirect_url) {\n if (!isValidUrl(response.redirect_url)) navigate({ to: response.redirect_url });\n else window.location.href = await getUrlWithTokens(passflow, response.redirect_url);\n } else {\n setShowSuccessMessage(true);\n }\n } else {\n setParamsError(verificationRequestErrorMessage);\n }\n }\n };\n\n void fetchData();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n if (isError && error) throw new Error(error);\n\n if (paramsError) throw new Error(paramsError);\n\n if (showSuccessMessage) return <VerifyChallengeSuccess />;\n\n return null;\n};\n","/* eslint-disable complexity */\n/* eslint-disable no-nested-ternary */\nimport type { FC } from 'react';\nimport * as Yup from 'yup';\nimport type { SuccessAuthRedirect } from '@/types';\nimport { VerifyChallengeOTPManual } from './verify-challenge-otp-manual';\nimport { VerifyChallengeOTPRedirect } from './verify-challenge-otp-redirect';\n\nimport '@/styles/index.css';\nimport { routes } from '@/context';\nimport { useUrlParams, verificationLinkErrorMessage } from '@/utils';\n\ntype TVerifyChallengeOTP = {\n numInputs: number;\n shouldAutoFocus: boolean;\n signUpPath: string;\n successAuthRedirect?: SuccessAuthRedirect;\n twoFactorVerifyPath?: string;\n};\n\nconst redirectSearchParamsVerifyChallengeOtpSchema = Yup.object().shape({\n appId: Yup.string().required(),\n challengeId: Yup.string().required(),\n otp: Yup.string().required(),\n});\n\nconst searchParamsVerifyChallengeOtpSchema = Yup.object().shape({\n challengeId: Yup.string().required(),\n identity: Yup.string().oneOf(['email', 'phone']).required(),\n identityValue: Yup.string().required(),\n challengeType: Yup.string().required(),\n type: Yup.string().oneOf(['passwordless', 'passkey']).optional(),\n});\n\nexport const VerifyChallengeOTP: FC<TVerifyChallengeOTP> = ({\n successAuthRedirect,\n numInputs,\n shouldAutoFocus,\n signUpPath,\n twoFactorVerifyPath = routes.two_factor_verify.path,\n}) => {\n const { get } = useUrlParams({\n otp: '',\n app_id: '',\n challenge_id: '',\n identity: '',\n identity_value: '',\n challenge_type: '',\n type: '',\n });\n\n const typeChallenge = get('type');\n\n if (typeChallenge !== 'passwordless' && typeChallenge !== 'passkey') {\n const redirectParams = {\n appId: get('app_id'),\n challengeId: get('challenge_id'),\n otp: get('otp'),\n };\n\n try {\n redirectSearchParamsVerifyChallengeOtpSchema.validateSync(redirectParams, { abortEarly: false });\n } catch (error) {\n console.error('[passflow] invalid passwordless verification redirect', error);\n throw new Error(verificationLinkErrorMessage);\n }\n\n const { appId, otp, challengeId } = redirectParams;\n\n return (\n <VerifyChallengeOTPRedirect appId={appId} challengeId={challengeId} otp={otp} twoFactorVerifyPath={twoFactorVerifyPath} />\n );\n }\n\n const params = {\n challengeId: get('challenge_id'),\n identity: get('email') ? 'email' : get('phone') ? 'phone' : null,\n identityValue: get('email') ? get('email') : get('phone') ? get('phone') : null,\n challengeType: get('challenge_type'),\n type: get('type'),\n };\n\n try {\n searchParamsVerifyChallengeOtpSchema.validateSync(params, { abortEarly: false });\n } catch (error) {\n console.error('[passflow] invalid passwordless verification link', error);\n throw new Error(verificationLinkErrorMessage);\n }\n\n const { challengeId, identity, identityValue, challengeType, type } = params;\n\n if (!type) {\n console.error('[passflow] passwordless verification link is missing its flow type');\n throw new Error(verificationLinkErrorMessage);\n }\n\n return (\n <VerifyChallengeOTPManual\n identity={identity}\n identityValue={identityValue}\n challengeType={challengeType}\n challengeId={challengeId}\n type={type as 'passwordless' | 'passkey'}\n numInputs={numInputs}\n shouldAutoFocus={shouldAutoFocus}\n signUpPath={signUpPath}\n successAuthRedirect={successAuthRedirect}\n twoFactorVerifyPath={twoFactorVerifyPath}\n />\n );\n};\n","/**\n * The flow's own router: no router library. PassflowFlow has a fixed set of\n * screens, one path parameter (`:token`) and search params, so it matches paths\n * itself and keeps one of three histories, or takes the location from the host.\n *\n * Browser history is the default and works on its own or inside a host router\n * (React Router, TanStack Router, Wouter): the flow moves the URL with\n * `history.pushState` and then fires `popstate`, the event every browser-history\n * router listens to, so the host's location follows. Back and Forward reach the\n * flow through the same event.\n */\nimport { routes } from '@/context';\n\nexport type FlowLocation = { pathname: string; search: string };\nexport type FlowNavigateOptions = { replace: boolean };\nexport type FlowNavigate = (location: FlowLocation, options: FlowNavigateOptions) => void;\n\nexport type FlowHistory = {\n /** The current location. Returns the same object until the location changes. */\n read: () => FlowLocation;\n subscribe: (listener: () => void) => () => void;\n navigate: FlowNavigate;\n};\n\n/** The screens PassflowFlow renders, keyed as in `routes`. */\nexport const FLOW_SCREENS = [\n 'signin',\n 'signup',\n 'verify_otp',\n 'verify_magic_link',\n 'forgot_password',\n 'forgot_password_success',\n 'reset_password',\n 'invitation',\n 'two_factor_verify',\n 'two_factor_setup',\n 'two_factor_setup_magic_link',\n] as const satisfies readonly (keyof typeof routes)[];\n\nexport type FlowScreen = (typeof FLOW_SCREENS)[number];\n\nexport type FlowMatch = { screen: FlowScreen; params: Record<string, string> };\n\nconst escapeRegExp = (text: string) => text.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n\n/** `/two-factor-setup-magic-link/:token` → a pattern for the path's segments, capturing params. */\nconst patternSource = (path: string) =>\n path\n .split('/')\n .map((segment) => (segment.startsWith(':') ? '([^/]+)' : escapeRegExp(segment)))\n .join('/');\n\nconst paramNames = (path: string) =>\n path\n .split('/')\n .filter((segment) => segment.startsWith(':'))\n .map((segment) => segment.slice(1));\n\n// Longest first, so `/forgot-password/success` wins over `/forgot-password`.\nconst SCREENS_BY_LENGTH = [...FLOW_SCREENS].sort((a, b) => routes[b].path.length - routes[a].path.length);\n\nconst decode = (value: string) => {\n try {\n return decodeURIComponent(value);\n } catch {\n return value;\n }\n};\n\n/** `'/auth/'` → `'/auth'`, `'auth'` → `'/auth'`, `'/'` or `''` → `''`. */\nexport const normalizePrefix = (prefix: string | undefined): string => {\n const trimmed = (prefix ?? '').replace(/^\\/+|\\/+$/g, '');\n return trimmed ? `/${trimmed}` : '';\n};\n\nconst trimTrailingSlash = (pathname: string) => (pathname.length > 1 ? pathname.replace(/\\/+$/, '') : pathname);\n\n/** The screen at `pathname` under `prefix`, or null when the path is not one of the flow's screens. */\nexport const matchScreen = (pathname: string, prefix: string): FlowMatch | null => {\n const path = trimTrailingSlash(pathname);\n for (const screen of SCREENS_BY_LENGTH) {\n const route = routes[screen].path;\n const match = new RegExp(`^${escapeRegExp(prefix)}${patternSource(route)}$`).exec(path);\n if (match) {\n const names = paramNames(route);\n return { screen, params: Object.fromEntries(names.map((name, index) => [name, decode(match[index + 1] ?? '')])) };\n }\n }\n return null;\n};\n\n/**\n * Where the flow is mounted, worked out from the first URL it sees: the part in\n * front of a screen path (`/auth/signin` → `/auth`), or the whole path when it\n * names no screen (`/auth` → `/auth`, `/` → `''`).\n */\nexport const detectPrefix = (pathname: string): string => {\n const path = trimTrailingSlash(pathname);\n for (const screen of SCREENS_BY_LENGTH) {\n const match = new RegExp(`^(.*?)${patternSource(routes[screen].path)}$`).exec(path);\n if (match) return normalizePrefix(match[1]);\n }\n return normalizePrefix(path);\n};\n\n/** The absolute path of a screen under `prefix`; `params` fill `:name` segments. */\nexport const screenPath = (screen: FlowScreen, prefix: string, params: Record<string, string> = {}): string =>\n `${prefix}${routes[screen].path.replace(/:(\\w+)/g, (_, name: string) => encodeURIComponent(params[name] ?? ''))}`;\n\nexport const isUnderPrefix = (pathname: string, prefix: string) =>\n prefix === '' || pathname === prefix || pathname.startsWith(`${prefix}/`);\n\nexport const withQuestionMark = (search: string) => (search && !search.startsWith('?') ? `?${search}` : search);\n\n/** Keeps `read` stable between changes, as `useSyncExternalStore` requires. */\nconst cached = (compute: () => FlowLocation) => {\n let last: FlowLocation | null = null;\n return () => {\n const next = compute();\n if (!last || last.pathname !== next.pathname || last.search !== next.search) last = next;\n return last;\n };\n};\n\nconst listenTo = (events: string[]) => (listener: () => void) => {\n for (const event of events) window.addEventListener(event, listener);\n return () => {\n for (const event of events) window.removeEventListener(event, listener);\n };\n};\n\n/** Tells every browser-history router on the page (the flow included) that the URL moved. */\nconst announceUrlChange = () => window.dispatchEvent(new PopStateEvent('popstate', { state: window.history.state }));\n\nexport const createBrowserHistory = (): FlowHistory => ({\n read: cached(() => ({ pathname: window.location.pathname, search: window.location.search })),\n subscribe: listenTo(['popstate']),\n navigate: ({ pathname, search }, { replace }) => {\n const url = `${pathname}${withQuestionMark(search)}`;\n // The current state is kept so a host router's own bookkeeping (its history\n // index and key) stays readable after the move.\n if (replace) window.history.replaceState(window.history.state, '', url);\n else window.history.pushState(window.history.state, '', url);\n announceUrlChange();\n },\n});\n\nconst readHash = (): FlowLocation => {\n const raw = window.location.hash.replace(/^#/, '') || '/';\n const queryAt = raw.indexOf('?');\n const pathname = queryAt >= 0 ? raw.slice(0, queryAt) : raw;\n return { pathname: pathname.startsWith('/') ? pathname : `/${pathname}`, search: queryAt >= 0 ? raw.slice(queryAt) : '' };\n};\n\nexport const createHashHistory = (): FlowHistory => ({\n read: cached(readHash),\n subscribe: listenTo(['popstate', 'hashchange']),\n navigate: ({ pathname, search }, { replace }) => {\n const url = `${window.location.pathname}${window.location.search}#${pathname}${withQuestionMark(search)}`;\n if (replace) window.history.replaceState(window.history.state, '', url);\n else window.history.pushState(window.history.state, '', url);\n announceUrlChange();\n },\n});\n\nexport const createMemoryHistory = (initial: FlowLocation = { pathname: '/', search: '' }): FlowHistory => {\n const entries: FlowLocation[] = [initial];\n const listeners = new Set<() => void>();\n return {\n read: () => entries[entries.length - 1] as FlowLocation,\n subscribe: (listener) => {\n listeners.add(listener);\n return () => listeners.delete(listener);\n },\n navigate: ({ pathname, search }, { replace }) => {\n const next = { pathname, search: withQuestionMark(search) };\n if (replace) entries[entries.length - 1] = next;\n else entries.push(next);\n for (const listener of listeners) listener();\n },\n };\n};\n","import { type FC, useContext, useEffect, useMemo, useRef, useState, useSyncExternalStore } from 'react';\nimport { TwoFactorSetupFlow } from '@/components/flow/two-factor-setup';\nimport { TwoFactorSetupMagicLinkFlow } from '@/components/flow/two-factor-setup-magic-link';\nimport { TwoFactorVerifyFlow } from '@/components/flow/two-factor-verify';\nimport {\n ForgotPassword,\n ForgotPasswordSuccess,\n InvitationJoin,\n ResetPassword,\n SignIn,\n SignUp,\n VerifyChallengeMagicLink,\n VerifyChallengeOTP,\n} from '@/components/form';\nimport { NavigationContext, SearchContext, type SearchSource } from '@/context';\nimport '@/styles/index.css';\nimport { ErrorComponent } from '@/components/error';\nimport { withError } from '@/hocs';\nimport { useNavigation } from '@/hooks';\nimport type { SuccessAuthRedirect } from '@/types';\nimport { authRedirectErrorMessage, getUrlErrors } from '@/utils';\nimport {\n createBrowserHistory,\n createHashHistory,\n createMemoryHistory,\n detectPrefix,\n FLOW_SCREENS,\n type FlowHistory,\n type FlowLocation,\n type FlowMatch,\n type FlowNavigate,\n type FlowScreen,\n isUnderPrefix,\n matchScreen,\n normalizePrefix,\n screenPath,\n withQuestionMark,\n} from './flow-router';\n\nexport type { FlowLocation as PassflowFlowLocation, FlowNavigate as PassflowFlowNavigate } from './flow-router';\n\ntype PassflowBaseProps = {\n successAuthRedirect?: SuccessAuthRedirect;\n federatedDisplayMode?: 'modal' | 'redirect';\n error?: string;\n relyingPartyId?: string;\n /**\n * Where the flow is mounted, such as `/auth`: its screens are then `/auth/signin`,\n * `/auth/signup`, and so on. Leave it out and the flow works it out from the first\n * URL it sees (`/auth/signin` or `/auth` → `/auth`; `/` → none).\n */\n pathPrefix?: string;\n /**\n * The history the flow keeps when the app does not pass `location`. `browser`\n * (the default) uses the address bar, on its own or inside the app's router;\n * `hash` keeps the flow's path after `#`; `memory` leaves the URL alone.\n */\n routerType?: 'browser' | 'hash' | 'memory';\n /** @deprecated Never had an effect. Use `pathPrefix`. */\n basename?: string;\n};\n\nexport type PassflowProps = PassflowBaseProps &\n (\n | {\n location?: undefined;\n navigate?: undefined;\n }\n | {\n /**\n * Full control: the app's router owns the location. Pass its current\n * `{ pathname, search }` and a `navigate` that moves it; `routerType` is then\n * not used. Not needed for an app router in browser mode, which the default\n * already follows.\n */\n location: FlowLocation;\n navigate: FlowNavigate;\n }\n );\n\ntype RouterKind = NonNullable<PassflowBaseProps['routerType']>;\n\nconst createHistory = (routerType: RouterKind): FlowHistory => {\n if (routerType === 'hash') return createHashHistory();\n if (routerType === 'memory') return createMemoryHistory();\n return createBrowserHistory();\n};\n\n/** The location the flow renders and how it moves: its own history, or the app's when it passes both. */\nconst useFlowLocation = (\n routerType: RouterKind,\n controlledLocation: FlowLocation | undefined,\n controlledNavigate: FlowNavigate | undefined,\n): { location: FlowLocation; navigate: FlowNavigate } => {\n const history = useMemo(() => createHistory(routerType), [routerType]);\n const ownLocation = useSyncExternalStore(history.subscribe, history.read);\n if (controlledLocation && controlledNavigate) {\n return {\n location: { pathname: controlledLocation.pathname, search: withQuestionMark(controlledLocation.search ?? '') },\n navigate: controlledNavigate,\n };\n }\n return { location: ownLocation, navigate: history.navigate };\n};\n\ntype PassflowRoutesProps = Required<Pick<PassflowBaseProps, 'federatedDisplayMode' | 'relyingPartyId'>> &\n Pick<PassflowBaseProps, 'successAuthRedirect' | 'pathPrefix'> & {\n location: FlowLocation;\n navigate: FlowNavigate;\n };\n\nconst PassflowRoutes: FC<PassflowRoutesProps> = ({\n successAuthRedirect,\n federatedDisplayMode,\n relyingPartyId,\n pathPrefix,\n location,\n navigate,\n}) => {\n // Fixed from the first URL unless the app names it.\n const [detectedPrefix] = useState(() => detectPrefix(location.pathname));\n const prefix = pathPrefix === undefined ? detectedPrefix : normalizePrefix(pathPrefix);\n\n const paths = useMemo(\n () => Object.fromEntries(FLOW_SCREENS.map((screen) => [screen, screenPath(screen, prefix)])) as Record<FlowScreen, string>,\n [prefix],\n );\n\n // The forms navigate through the provider. Registered once, reading the latest\n // `navigate` through a ref: an app's inline `navigate` prop changes every render,\n // and re-registering it would re-render the provider and loop.\n const navigateRef = useRef(navigate);\n navigateRef.current = navigate;\n const { setNavigate } = useContext(NavigationContext);\n useEffect(() => {\n setNavigate(({ to, search = '', replace = false }) => {\n const queryAt = to.indexOf('?');\n const pathname = queryAt >= 0 ? to.slice(0, queryAt) : to;\n const query = search || (queryAt >= 0 ? to.slice(queryAt) : '');\n navigateRef.current({ pathname, search: withQuestionMark(query) }, { replace });\n });\n }, [setNavigate]);\n\n // A landing that owes its second factor goes to this flow's own (prefixed)\n // 2FA route; PassflowProvider does the navigation.\n const { setTwoFactorVerifyPath } = useNavigation();\n useEffect(() => {\n setTwoFactorVerifyPath?.(paths.two_factor_verify);\n return () => setTwoFactorVerifyPath?.(null);\n }, [setTwoFactorVerifyPath, paths.two_factor_verify]);\n\n const match = matchScreen(location.pathname, prefix);\n // A path inside the flow that names no screen goes to sign-in, keeping its search\n // params. A path outside the flow belongs to the app: the flow renders nothing.\n const strayInsideFlow = !match && isUnderPrefix(location.pathname, prefix);\n useEffect(() => {\n if (strayInsideFlow) navigateRef.current({ pathname: paths.signin, search: location.search }, { replace: true });\n }, [strayInsideFlow, paths.signin, location.search]);\n\n // The forms read and write search params through the flow's location, not the\n // address bar, so memory, hash and app-driven flows carry them too. A write can\n // happen while a form renders (default params), so it moves after the render.\n const pathnameRef = useRef(location.pathname);\n pathnameRef.current = location.pathname;\n const searchSource = useMemo<SearchSource>(\n () => ({\n read: () => location.search,\n write: (search, { replace }) =>\n queueMicrotask(() => navigateRef.current({ pathname: pathnameRef.current, search }, { replace })),\n }),\n [location.search],\n );\n\n if (!match) return null;\n\n return (\n <SearchContext.Provider value={searchSource}>\n <FlowScreenView\n match={match}\n paths={paths}\n successAuthRedirect={successAuthRedirect}\n federatedDisplayMode={federatedDisplayMode}\n relyingPartyId={relyingPartyId}\n />\n </SearchContext.Provider>\n );\n};\n\ntype FlowScreenViewProps = Pick<PassflowRoutesProps, 'successAuthRedirect' | 'federatedDisplayMode' | 'relyingPartyId'> & {\n match: FlowMatch;\n paths: Record<FlowScreen, string>;\n};\n\n/** The screen a matched path names, wired to the flow's other screens. */\nconst FlowScreenView: FC<FlowScreenViewProps> = ({\n match,\n paths,\n successAuthRedirect,\n federatedDisplayMode,\n relyingPartyId,\n}) => {\n switch (match.screen) {\n case 'signin':\n return (\n <SignIn\n successAuthRedirect={successAuthRedirect}\n relyingPartyId={relyingPartyId}\n federatedDisplayMode={federatedDisplayMode}\n signUpPath={paths.signup}\n forgotPasswordPath={paths.forgot_password}\n verifyMagicLinkPath={paths.verify_magic_link}\n verifyOTPPath={paths.verify_otp}\n twoFactorVerifyPath={paths.two_factor_verify}\n />\n );\n case 'signup':\n return (\n <SignUp\n successAuthRedirect={successAuthRedirect}\n relyingPartyId={relyingPartyId}\n federatedDisplayMode={federatedDisplayMode}\n signInPath={paths.signin}\n verifyMagicLinkPath={paths.verify_magic_link}\n verifyOTPPath={paths.verify_otp}\n twoFactorVerifyPath={paths.two_factor_verify}\n />\n );\n case 'verify_otp':\n return (\n <VerifyChallengeOTP\n successAuthRedirect={successAuthRedirect}\n numInputs={6}\n shouldAutoFocus\n signUpPath={paths.signup}\n twoFactorVerifyPath={paths.two_factor_verify}\n />\n );\n case 'verify_magic_link':\n return <VerifyChallengeMagicLink />;\n case 'forgot_password':\n return (\n <ForgotPassword\n successResetRedirect={successAuthRedirect}\n signInPath={paths.signin}\n forgotPasswordSuccessPath={paths.forgot_password_success}\n />\n );\n case 'forgot_password_success':\n return <ForgotPasswordSuccess />;\n case 'reset_password':\n return <ResetPassword successAuthRedirect={successAuthRedirect} twoFactorVerifyPath={paths.two_factor_verify} />;\n case 'invitation':\n return <InvitationJoin successAuthRedirect={successAuthRedirect} signInPath={paths.signin} signUpPath={paths.signup} />;\n case 'two_factor_verify':\n return (\n <TwoFactorVerifyFlow\n successAuthRedirect={successAuthRedirect}\n signInPath={paths.signin}\n twoFactorSetupPath={paths.two_factor_setup}\n />\n );\n case 'two_factor_setup':\n return (\n <TwoFactorSetupFlow\n successAuthRedirect={successAuthRedirect}\n twoFactorVerifyPath={paths.two_factor_verify}\n signInPath={paths.signin}\n />\n );\n case 'two_factor_setup_magic_link':\n return <TwoFactorSetupMagicLinkFlow token={match.params.token ?? ''} signInPath={paths.signin} />;\n }\n};\n\nconst PassflowWrapper: FC<PassflowProps> = ({\n successAuthRedirect,\n federatedDisplayMode = 'redirect',\n error = undefined,\n relyingPartyId = window.location.hostname,\n pathPrefix,\n routerType = 'browser',\n location: controlledLocation,\n navigate: controlledNavigate,\n}) => {\n const { error: errorUrlSuccess, message: messageUrlSuccess } = getUrlErrors(successAuthRedirect);\n const { location, navigate } = useFlowLocation(routerType, controlledLocation, controlledNavigate);\n\n if (errorUrlSuccess) {\n console.error('[passflow] authentication redirect returned an error', {\n error: errorUrlSuccess,\n message: messageUrlSuccess,\n });\n throw new Error(authRedirectErrorMessage);\n }\n\n if (error) throw new Error(error);\n\n return (\n <PassflowRoutes\n successAuthRedirect={successAuthRedirect}\n federatedDisplayMode={federatedDisplayMode}\n relyingPartyId={relyingPartyId}\n pathPrefix={pathPrefix}\n location={location}\n navigate={navigate}\n />\n );\n};\n\nexport const PassflowFlow = withError(PassflowWrapper, ErrorComponent);\n"],"mappings":"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AAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,aACJC,GAAI,cACJC,GAAI,cACJC,GAAI,cACJC,GAAI,cACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJ3P,GAAI,eACJ4P,GAAI,eACJC,GAAI,eACJC,GAAI,aACJC,GAAI,cACJC,GAAI,cACJC,GAAI,cACJC,GAAI,cACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,cACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,cACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,cACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,aACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,cACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,cACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,cACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,cACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,cACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,cACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJxV,GAAI,gBACJyV,GAAI,cACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,eACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJC,GAAI,gBACJ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"}
|