{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "login-form", "type": "registry:component", "title": "Login Form", "description": "Shared email, password, and Google continue form used by auth login layouts.", "registryDependencies": [ "tyrailleverett/nice-ui/style", "button", "input-group", "label", "separator", "tyrailleverett/nice-ui/logo", "tyrailleverett/nice-ui/password-input" ], "files": [ { "path": "registry/app/auth/login-form/login-form.tsx", "type": "registry:component", "target": "~/components/login-form.tsx", "content": "import {\n type ComponentProps,\n type FormEvent,\n type ReactNode,\n useCallback,\n} from \"react\";\n\nimport { LogoIcon } from \"@/components/logo\";\nimport { PasswordInput } from \"@/components/password-input\";\nimport { Button } from \"@/components/ui/button\";\nimport { InputGroup, InputGroupInput } from \"@/components/ui/input-group\";\nimport { Label } from \"@/components/ui/label\";\nimport { Separator } from \"@/components/ui/separator\";\nimport { cn } from \"@/lib/utils\";\n\nexport interface LoginFormLink {\n href: string;\n label: string;\n}\n\nexport interface LoginFormProps {\n className?: string;\n description?: string;\n emailPlaceholder?: string;\n forgotPasswordHref?: string;\n forgotPasswordLabel?: string;\n googleLabel?: string;\n idPrefix?: string;\n logo?: ReactNode;\n onGoogleContinue?: () => void;\n onSubmit?: (event: FormEvent) => void;\n passwordPlaceholder?: string;\n primaryAction?: string;\n showStrengthIndicator?: boolean;\n signInHref?: string;\n signInLabel?: string;\n signInPrompt?: string;\n title?: string;\n}\n\nexport const defaultLoginLegalLinks: LoginFormLink[] = [\n { href: \"#\", label: \"Privacy\" },\n { href: \"#\", label: \"Terms\" },\n { href: \"#\", label: \"Help\" },\n];\n\nconst defaultLogo = (\n \n);\n\nfunction GoogleIcon(props: ComponentProps<\"svg\">) {\n return (\n \n \n \n \n \n \n );\n}\n\nfunction OrDivider() {\n return (\n
\n
\n \n
\n
\n \n OR CONTINUE WITH EMAIL\n \n
\n
\n );\n}\n\nexport function LoginLegalNav({\n className,\n links = defaultLoginLegalLinks,\n}: {\n className?: string;\n links?: LoginFormLink[];\n}) {\n if (!links.length) {\n return null;\n }\n\n return (\n \n {links.map((link) => (\n \n {link.label}\n \n ))}\n \n );\n}\n\nexport function LoginForm({\n className,\n description,\n emailPlaceholder = \"Enter your email\",\n forgotPasswordHref = \"#\",\n forgotPasswordLabel = \"Forgot password?\",\n googleLabel = \"Continue with Google\",\n idPrefix = \"login\",\n logo = defaultLogo,\n onGoogleContinue,\n onSubmit,\n passwordPlaceholder = \"Enter your password\",\n primaryAction = \"Sign in with Email\",\n showStrengthIndicator = false,\n signInHref = \"#\",\n signInLabel = \"Sign up\",\n signInPrompt = \"Don't have an account?\",\n title = \"Sign in\",\n}: LoginFormProps) {\n const emailId = `${idPrefix}-email`;\n const passwordId = `${idPrefix}-password`;\n const accountPrompt = description ?? signInPrompt;\n\n const handleSubmit = useCallback(\n (event: FormEvent) => {\n event.preventDefault();\n onSubmit?.(event);\n },\n [onSubmit]\n );\n\n return (\n
\n {logo}\n
\n

{title}

\n {accountPrompt ? (\n

\n {accountPrompt}{\" \"}\n \n {signInLabel}\n \n

\n ) : null}\n
\n\n
\n \n \n {googleLabel}\n \n\n \n\n
\n
\n \n \n \n \n
\n \n
\n\n \n \n
\n );\n}\n" } ] }