"use client" import { ArrowLeftIcon } from "lucide-react" import { type ReactNode, useContext, useEffect, useState } from "react" import { useIsHydrated } from "../../hooks/use-hydrated" import { AuthUIContext } from "../../lib/auth-ui-provider" import { socialProviders } from "../../lib/social-providers" import { cn, getViewByPath } from "../../lib/utils" import type { AuthViewPaths } from "../../lib/view-paths" import type { AuthLocalization } from "../../localization/auth-localization" import { AcceptInvitationCard } from "../organization/accept-invitation-card" import { Button } from "../ui/button" import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "../ui/card" import { Separator } from "../ui/separator" import { AuthCallback } from "./auth-callback" import { AuthForm, type AuthFormClassNames } from "./auth-form" import { EmailOTPButton } from "./email-otp-button" import { MagicLinkButton } from "./magic-link-button" import { OneTap } from "./one-tap" import { PasskeyButton } from "./passkey-button" import { ProviderButton } from "./provider-button" import { SignOut } from "./sign-out" export type AuthViewClassNames = { base?: string content?: string description?: string footer?: string footerLink?: string continueWith?: string form?: AuthFormClassNames header?: string separator?: string title?: string } export interface AuthViewProps { className?: string classNames?: AuthViewClassNames callbackURL?: string cardHeader?: ReactNode cardFooter?: ReactNode localization?: AuthLocalization path?: string pathname?: string redirectTo?: string socialLayout?: "auto" | "horizontal" | "grid" | "vertical" view?: keyof AuthViewPaths otpSeparators?: 0 | 1 | 2 } export function AuthView({ className, classNames, callbackURL, cardHeader, cardFooter, localization, path: pathProp, pathname, redirectTo, socialLayout: socialLayoutProp = "auto", view: viewProp, otpSeparators = 0 }: AuthViewProps) { const isHydrated = useIsHydrated() const { basePath, credentials, localization: contextLocalization, magicLink, emailOTP, oneTap, passkey, signUp, social, genericOAuth, viewPaths, Link } = useContext(AuthUIContext) localization = { ...contextLocalization, ...localization } let socialLayout = socialLayoutProp if (socialLayout === "auto") { socialLayout = !credentials ? "vertical" : social?.providers && social.providers.length > 2 ? "horizontal" : "vertical" } const path = pathProp ?? pathname?.split("/").pop() const view = viewProp || getViewByPath(viewPaths!, path) || "SIGN_IN" const [isSubmitting, setIsSubmitting] = useState(false) useEffect(() => { const handlePageHide = () => setIsSubmitting(false) window.addEventListener("pagehide", handlePageHide) return () => { setIsSubmitting(false) window.removeEventListener("pagehide", handlePageHide) } }, []) if (view === "CALLBACK") return if (view === "SIGN_OUT") return if (view === "ACCEPT_INVITATION") return ( ) const description = !credentials && !magicLink && !emailOTP ? localization.DISABLED_CREDENTIALS_DESCRIPTION : localization[`${view}_DESCRIPTION` as keyof typeof localization] return ( {cardHeader ? ( cardHeader ) : ( <> {localization[view as keyof typeof localization]} {description && ( {description} )} )} {oneTap && ["SIGN_IN", "SIGN_UP", "MAGIC_LINK", "EMAIL_OTP"].includes( view as string ) && ( )} {(credentials || magicLink || emailOTP) && (
{magicLink && ((credentials && [ "FORGOT_PASSWORD", "SIGN_UP", "SIGN_IN", "MAGIC_LINK", "EMAIL_OTP" ].includes(view as string)) || (emailOTP && view === "EMAIL_OTP")) && ( )} {emailOTP && ((credentials && [ "FORGOT_PASSWORD", "SIGN_UP", "SIGN_IN", "MAGIC_LINK", "EMAIL_OTP" ].includes(view as string)) || (magicLink && ["SIGN_IN", "MAGIC_LINK"].includes( view as string ))) && ( )}
)} {view !== "RESET_PASSWORD" && view !== "EMAIL_VERIFICATION" && (social?.providers?.length || genericOAuth?.providers?.length || (view === "SIGN_IN" && passkey)) && ( <> {(credentials || magicLink || emailOTP) && (
{localization.OR_CONTINUE_WITH}
)}
{(social?.providers?.length || genericOAuth?.providers?.length) && (
{social?.providers?.map((provider) => { const socialProvider = socialProviders.find( (socialProvider) => socialProvider.provider === provider ) if (!socialProvider) return null return ( ) })} {genericOAuth?.providers?.map( (provider) => ( ) )}
)} {passkey && [ "SIGN_IN", "MAGIC_LINK", "EMAIL_OTP", "RECOVER_ACCOUNT", "TWO_FACTOR", "FORGOT_PASSWORD" ].includes(view as string) && ( )}
)}
{cardFooter && ( {cardFooter} )} {credentials && signUp && ( {view === "SIGN_IN" || view === "MAGIC_LINK" || view === "EMAIL_OTP" ? ( localization.DONT_HAVE_AN_ACCOUNT ) : view === "SIGN_UP" ? ( localization.ALREADY_HAVE_AN_ACCOUNT ) : ( )} {view === "SIGN_IN" || view === "MAGIC_LINK" || view === "EMAIL_OTP" || view === "SIGN_UP" ? ( ) : ( )} )}
) }