@main12/auth-login 0.4.2 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/README.md +54 -7
  2. package/dist/components/AuthCard.d.ts +41 -0
  3. package/dist/components/AuthCard.js +28 -0
  4. package/dist/components/AuthCardServer.d.ts +29 -0
  5. package/dist/components/AuthCardServer.js +57 -0
  6. package/dist/components/AuthLayout.d.ts +23 -13
  7. package/dist/components/AuthLayout.js +26 -87
  8. package/dist/components/AuthPages.d.ts +4 -29
  9. package/dist/components/AuthPages.js +23 -105
  10. package/dist/components/AuthPagesServer.d.ts +3 -4
  11. package/dist/components/AuthPagesServer.js +15 -8
  12. package/dist/components/auth-card/AuthCardShell.d.ts +21 -0
  13. package/dist/components/auth-card/AuthCardShell.js +104 -0
  14. package/dist/components/auth-card/FormRenderer.d.ts +32 -0
  15. package/dist/components/auth-card/FormRenderer.js +88 -0
  16. package/dist/components/auth-card/formConfigs.d.ts +25 -0
  17. package/dist/components/auth-card/formConfigs.js +56 -0
  18. package/dist/components/auth-card/index.d.ts +3 -0
  19. package/dist/components/auth-card/index.js +3 -0
  20. package/dist/components/forms/ForgotPasswordForm.d.ts +7 -0
  21. package/dist/components/forms/ForgotPasswordForm.js +56 -0
  22. package/dist/components/forms/LoginForm.d.ts +15 -0
  23. package/dist/components/forms/LoginForm.js +247 -0
  24. package/dist/components/forms/SetPasswordForm.d.ts +7 -0
  25. package/dist/components/forms/SetPasswordForm.js +75 -0
  26. package/dist/components/forms/SignupForm.d.ts +13 -0
  27. package/dist/components/forms/SignupForm.js +152 -0
  28. package/dist/components/forms/VerifyOtpForm.d.ts +9 -0
  29. package/dist/components/forms/VerifyOtpForm.js +107 -0
  30. package/dist/components/forms/index.d.ts +19 -0
  31. package/dist/components/forms/index.js +21 -0
  32. package/dist/components/pages/ForgotPasswordPage.d.ts +2 -1
  33. package/dist/components/pages/ForgotPasswordPageHero.d.ts +3 -2
  34. package/dist/components/pages/ForgotPasswordPageHero.js +70 -64
  35. package/dist/components/pages/ForgotPasswordPageTailwind.d.ts +3 -2
  36. package/dist/components/pages/ForgotPasswordPageTailwind.js +42 -36
  37. package/dist/components/pages/LoginPage.d.ts +2 -1
  38. package/dist/components/pages/LoginPageHero.d.ts +2 -1
  39. package/dist/components/pages/LoginPageHero.js +297 -291
  40. package/dist/components/pages/LoginPageTailwind.d.ts +2 -1
  41. package/dist/components/pages/LoginPageTailwind.js +197 -191
  42. package/dist/components/pages/SetPasswordPage.d.ts +2 -1
  43. package/dist/components/pages/SetPasswordPageHero.d.ts +3 -2
  44. package/dist/components/pages/SetPasswordPageHero.js +98 -92
  45. package/dist/components/pages/SetPasswordPageTailwind.d.ts +3 -2
  46. package/dist/components/pages/SetPasswordPageTailwind.js +63 -57
  47. package/dist/components/pages/SignupPage.d.ts +2 -1
  48. package/dist/components/pages/SignupPageHero.d.ts +3 -2
  49. package/dist/components/pages/SignupPageHero.js +139 -133
  50. package/dist/components/pages/SignupPageTailwind.d.ts +3 -2
  51. package/dist/components/pages/SignupPageTailwind.js +123 -117
  52. package/dist/components/pages/VerifyOtpPage.d.ts +2 -1
  53. package/dist/components/pages/VerifyOtpPageHero.d.ts +2 -1
  54. package/dist/components/pages/VerifyOtpPageHero.js +110 -104
  55. package/dist/components/pages/VerifyOtpPageTailwind.d.ts +2 -1
  56. package/dist/components/pages/VerifyOtpPageTailwind.js +60 -54
  57. package/dist/components/ui/translations.d.ts +9 -0
  58. package/dist/components/ui/translations.js +18 -0
  59. package/dist/config.d.ts +12 -0
  60. package/dist/config.js +11 -0
  61. package/dist/exports/client.d.ts +5 -0
  62. package/dist/exports/client.js +5 -0
  63. package/dist/exports/rsc.d.ts +7 -0
  64. package/dist/exports/rsc.js +8 -0
  65. package/dist/index.js +12 -2
  66. package/package.json +3 -2
@@ -1,14 +1,15 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { headers } from 'next/headers';
3
+ import { redirect } from 'next/navigation';
3
4
  import AuthPagesClient from './AuthPages.js';
4
- import { pluginConfig } from '../config.js';
5
+ import { getServerAllowSignup, getServerGoogleOAuthEnabled, pluginConfig } from '../config.js';
5
6
  import { detectServerLocale } from './ui/locale.js';
7
+ // Use pluginConfig singleton directly - standard Payload plugin pattern
6
8
  /**
7
9
  * Server component wrapper for AuthPages.
8
- * Reads plugin config directly from the shared `pluginConfig` singleton
9
- * (set by the plugin factory at Payload config build time) and passes it
10
- * down to the client component. No env vars involved — the plugin's
11
- * `style`, `googleOAuthEnabled`, etc. options are the single source of truth.
10
+ * Reads plugin config from environment variables set during plugin initialization,
11
+ * ensuring the correct settings are used even in linked monorepo setups where
12
+ * module singletons may not be shared across entry points.
12
13
  *
13
14
  * Locale is resolved per-request: an explicit `locale` prop always wins,
14
15
  * otherwise it's auto-detected from the `NEXT_LOCALE` cookie or
@@ -25,11 +26,17 @@ import { detectServerLocale } from './ui/locale.js';
25
26
  * ```
26
27
  */ export default async function AuthPages(props) {
27
28
  const resolvedLocale = props.locale ?? detectServerLocale(await headers());
29
+ const resolvedAllowSignup = props.allowSignup ?? getServerAllowSignup();
30
+ const basePath = props.basePath?.replace(/\/$/, '') ?? '/auth';
31
+ // Redirect /signup to /login when signup is disabled
32
+ const currentSlug = Array.isArray(props.slug) ? props.slug[0] : props.slug;
33
+ if (!resolvedAllowSignup && currentSlug === 'signup') {
34
+ redirect(`${basePath}/login`);
35
+ }
28
36
  return /*#__PURE__*/ _jsx(AuthPagesClient, {
29
37
  ...props,
30
- showGoogleOAuth: props.showGoogleOAuth ?? pluginConfig.googleOAuthEnabled,
31
- style: props.style ?? pluginConfig.style,
32
- allowSignup: props.allowSignup ?? pluginConfig.allowSignup,
38
+ showGoogleOAuth: props.showGoogleOAuth ?? getServerGoogleOAuthEnabled(),
39
+ allowSignup: resolvedAllowSignup,
33
40
  passwordLogin: pluginConfig.passwordLogin,
34
41
  otpLogin: pluginConfig.otpLogin,
35
42
  locale: resolvedLocale
@@ -0,0 +1,21 @@
1
+ import React from 'react';
2
+ export interface PoweredByConfig {
3
+ enabled?: boolean;
4
+ logoUrl?: string;
5
+ linkUrl?: string;
6
+ width?: number;
7
+ height?: number;
8
+ }
9
+ export interface AuthCardShellProps {
10
+ children: React.ReactNode;
11
+ logo?: React.ReactNode;
12
+ title?: string;
13
+ subtitle?: string;
14
+ footer?: React.ReactNode;
15
+ poweredBy?: PoweredByConfig;
16
+ cardClassName?: string;
17
+ removeBorder?: boolean;
18
+ removeShadow?: boolean;
19
+ mobileVariant?: 'plain' | 'card';
20
+ }
21
+ export declare function AuthCardShell({ children, logo, title, subtitle, footer, poweredBy, cardClassName, removeBorder, removeShadow, mobileVariant, }: AuthCardShellProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,104 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import React from 'react';
4
+ import { Card, CardContent, CardFooter } from '../ui/index.js';
5
+ import { PoweredBy } from '../PoweredBy.js';
6
+ import { pluginConfig } from '../../config.js';
7
+ function DefaultLogo() {
8
+ if (pluginConfig.Logo) {
9
+ const L = pluginConfig.Logo;
10
+ return /*#__PURE__*/ _jsx(L, {});
11
+ }
12
+ if (pluginConfig.logoUrl) {
13
+ return /*#__PURE__*/ _jsx("img", {
14
+ src: pluginConfig.logoUrl,
15
+ alt: "",
16
+ width: 180,
17
+ height: 42,
18
+ className: "object-contain"
19
+ });
20
+ }
21
+ return null;
22
+ }
23
+ export function AuthCardShell({ children, logo, title, subtitle, footer, poweredBy, cardClassName = '', removeBorder = false, removeShadow = false, mobileVariant = 'plain' }) {
24
+ const displayLogo = logo || /*#__PURE__*/ _jsx(DefaultLogo, {});
25
+ const header = (displayLogo || title) && /*#__PURE__*/ _jsxs("div", {
26
+ className: "flex flex-col items-center gap-2 pt-8 pb-4 px-8",
27
+ children: [
28
+ displayLogo && /*#__PURE__*/ _jsx("div", {
29
+ className: "flex justify-center mb-3",
30
+ children: displayLogo
31
+ }),
32
+ title && /*#__PURE__*/ _jsx("h1", {
33
+ className: "text-2xl font-bold text-gray-900 text-center tracking-tight",
34
+ children: title
35
+ }),
36
+ subtitle && /*#__PURE__*/ _jsx("p", {
37
+ className: "text-gray-600 text-sm text-center",
38
+ children: subtitle
39
+ })
40
+ ]
41
+ });
42
+ const cardBorderShadowClass = [
43
+ removeBorder ? '!border-0' : '',
44
+ removeShadow ? '!shadow-none' : ''
45
+ ].filter(Boolean).join(' ');
46
+ const cardBody = /*#__PURE__*/ _jsxs("div", {
47
+ className: "w-full max-w-md mx-auto animate-[fadeIn_0.5s_ease-out]",
48
+ style: {
49
+ maxWidth: '448px'
50
+ },
51
+ children: [
52
+ /*#__PURE__*/ _jsxs(Card, {
53
+ className: `${cardBorderShadowClass} ${cardClassName}`.trim(),
54
+ children: [
55
+ header,
56
+ /*#__PURE__*/ _jsx(CardContent, {
57
+ children: children
58
+ }),
59
+ footer && /*#__PURE__*/ _jsx(CardFooter, {
60
+ children: footer
61
+ })
62
+ ]
63
+ }),
64
+ /*#__PURE__*/ _jsx(PoweredBy, {
65
+ ...poweredBy
66
+ })
67
+ ]
68
+ });
69
+ if (mobileVariant === 'card') {
70
+ return /*#__PURE__*/ _jsx("div", {
71
+ className: "px-4 py-8 md:py-12",
72
+ children: cardBody
73
+ });
74
+ }
75
+ return /*#__PURE__*/ _jsxs(_Fragment, {
76
+ children: [
77
+ /*#__PURE__*/ _jsxs("div", {
78
+ className: "md:hidden flex flex-col w-full max-w-md mx-auto light [color-scheme:light] px-4 py-8",
79
+ "data-theme": "light",
80
+ style: {
81
+ maxWidth: '448px'
82
+ },
83
+ children: [
84
+ header,
85
+ /*#__PURE__*/ _jsx("div", {
86
+ className: "px-8 pb-6",
87
+ children: children
88
+ }),
89
+ footer && /*#__PURE__*/ _jsx("div", {
90
+ className: "px-8 pb-8 flex justify-center",
91
+ children: footer
92
+ }),
93
+ /*#__PURE__*/ _jsx(PoweredBy, {
94
+ ...poweredBy
95
+ })
96
+ ]
97
+ }),
98
+ /*#__PURE__*/ _jsx("div", {
99
+ className: "hidden md:flex items-center justify-center px-4 py-12 w-full h-full",
100
+ children: cardBody
101
+ })
102
+ ]
103
+ });
104
+ }
@@ -0,0 +1,32 @@
1
+ import React from 'react';
2
+ import { type DeepPartial, type UiTranslations } from '../ui/translations';
3
+ import { type PoweredByConfig } from './AuthCardShell';
4
+ export interface FormRendererProps {
5
+ slug: string | string[];
6
+ redirectTo?: string;
7
+ onPasswordLogin?: (credentials: {
8
+ email: string;
9
+ password: string;
10
+ }) => Promise<void>;
11
+ onSignup?: (data: {
12
+ name: string;
13
+ email: string;
14
+ }) => Promise<void>;
15
+ basePath?: string;
16
+ showGoogleOAuth?: boolean;
17
+ allowSignup?: boolean;
18
+ passwordLogin?: boolean;
19
+ otpLogin?: boolean;
20
+ locale?: string;
21
+ messages?: Record<string, DeepPartial<UiTranslations>>;
22
+ logo?: React.ReactNode;
23
+ title?: string;
24
+ subtitle?: string;
25
+ footer?: React.ReactNode;
26
+ poweredBy?: PoweredByConfig;
27
+ cardClassName?: string;
28
+ removeBorder?: boolean;
29
+ removeShadow?: boolean;
30
+ mobileVariant?: 'plain' | 'card';
31
+ }
32
+ export declare function FormRenderer({ slug, redirectTo, onPasswordLogin, onSignup, basePath, showGoogleOAuth, allowSignup, passwordLogin, otpLogin, locale, messages, logo, title: titleOverride, subtitle: subtitleOverride, footer, poweredBy, cardClassName, removeBorder, removeShadow, mobileVariant, }: FormRendererProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,88 @@
1
+ 'use client';
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import React, { useState } from 'react';
4
+ import { pluginConfig, initClientConfig } from '../../config.js';
5
+ import { detectClientLocale } from '../ui/locale.js';
6
+ import { getUiTranslations } from '../ui/translations.js';
7
+ import { AUTH_FORMS } from '../forms/index.js';
8
+ import { FORM_CONFIGS } from './formConfigs.js';
9
+ import { AuthCardShell } from './AuthCardShell.js';
10
+ const defaultPasswordLogin = async ({ email, password })=>{
11
+ const res = await fetch('/api/users/login', {
12
+ method: 'POST',
13
+ headers: {
14
+ 'Content-Type': 'application/json'
15
+ },
16
+ body: JSON.stringify({
17
+ email,
18
+ password
19
+ })
20
+ });
21
+ if (!res.ok) {
22
+ const err = await res.json();
23
+ throw new Error(err.errors?.[0]?.message || 'Login failed');
24
+ }
25
+ };
26
+ const defaultSignup = async ({ name, email })=>{
27
+ const res = await fetch('/api/auth/signup', {
28
+ method: 'POST',
29
+ headers: {
30
+ 'Content-Type': 'application/json'
31
+ },
32
+ body: JSON.stringify({
33
+ name,
34
+ email
35
+ })
36
+ });
37
+ if (!res.ok) {
38
+ const err = await res.json();
39
+ throw new Error(err.message || 'Signup failed');
40
+ }
41
+ };
42
+ export function FormRenderer({ slug, redirectTo = '/admin', onPasswordLogin = defaultPasswordLogin, onSignup = defaultSignup, basePath = '/auth', showGoogleOAuth, allowSignup = true, passwordLogin = true, otpLogin = true, locale, messages, logo, title: titleOverride, subtitle: subtitleOverride, footer, poweredBy, cardClassName, removeBorder, removeShadow, mobileVariant }) {
43
+ initClientConfig({
44
+ style: pluginConfig.style,
45
+ googleOAuthEnabled: showGoogleOAuth ?? pluginConfig.googleOAuthEnabled,
46
+ passwordLogin,
47
+ otpLogin
48
+ });
49
+ const resolvedLocale = locale ?? detectClientLocale();
50
+ const t = getUiTranslations(resolvedLocale, messages);
51
+ const normalizedSlug = Array.isArray(slug) ? slug[0] : slug;
52
+ const base = basePath.replace(/\/$/, '');
53
+ const [dynamicTitle, setDynamicTitle] = useState(undefined);
54
+ const [dynamicSubtitle, setDynamicSubtitle] = useState(undefined);
55
+ const effectiveSlug = !allowSignup && normalizedSlug === 'signup' ? 'login' : normalizedSlug in AUTH_FORMS ? normalizedSlug : 'login';
56
+ const config = FORM_CONFIGS[effectiveSlug];
57
+ const FormComponent = AUTH_FORMS[effectiveSlug];
58
+ const propsContext = {
59
+ redirectTo,
60
+ onPasswordLogin,
61
+ onSignup,
62
+ basePath: base,
63
+ showGoogleOAuth: showGoogleOAuth ?? pluginConfig.googleOAuthEnabled,
64
+ allowSignup,
65
+ locale: resolvedLocale,
66
+ messages,
67
+ setDynamicTitle,
68
+ setDynamicSubtitle
69
+ };
70
+ const translationSection = t[config.translationKey];
71
+ const title = titleOverride ?? dynamicTitle ?? translationSection.title;
72
+ const subtitle = subtitleOverride ?? dynamicSubtitle ?? translationSection.subtitle;
73
+ const formProps = config.getProps(propsContext);
74
+ return /*#__PURE__*/ _jsx(AuthCardShell, {
75
+ logo: logo,
76
+ title: title,
77
+ subtitle: subtitle,
78
+ footer: footer,
79
+ poweredBy: poweredBy,
80
+ cardClassName: cardClassName,
81
+ removeBorder: removeBorder,
82
+ removeShadow: removeShadow,
83
+ mobileVariant: mobileVariant,
84
+ children: /*#__PURE__*/ _jsx(FormComponent, {
85
+ ...formProps
86
+ })
87
+ });
88
+ }
@@ -0,0 +1,25 @@
1
+ import type { UiTranslations, DeepPartial } from '../ui/translations';
2
+ import type { AuthFormSlug } from '../forms/index';
3
+ export interface FormPropsContext {
4
+ redirectTo: string;
5
+ onPasswordLogin: (credentials: {
6
+ email: string;
7
+ password: string;
8
+ }) => Promise<void>;
9
+ onSignup: (data: {
10
+ name: string;
11
+ email: string;
12
+ }) => Promise<void>;
13
+ basePath: string;
14
+ showGoogleOAuth: boolean;
15
+ allowSignup: boolean;
16
+ locale: string;
17
+ messages?: Record<string, DeepPartial<UiTranslations>>;
18
+ setDynamicTitle: (title: string | undefined) => void;
19
+ setDynamicSubtitle: (subtitle: string | undefined) => void;
20
+ }
21
+ export interface FormConfig {
22
+ translationKey: keyof UiTranslations;
23
+ getProps: (ctx: FormPropsContext) => Record<string, any>;
24
+ }
25
+ export declare const FORM_CONFIGS: Record<AuthFormSlug, FormConfig>;
@@ -0,0 +1,56 @@
1
+ export const FORM_CONFIGS = {
2
+ 'login': {
3
+ translationKey: 'login',
4
+ getProps: (ctx)=>({
5
+ onPasswordLogin: ctx.onPasswordLogin,
6
+ redirectTo: ctx.redirectTo,
7
+ showGoogleOAuth: ctx.showGoogleOAuth,
8
+ signupUrl: ctx.allowSignup ? `${ctx.basePath}/signup` : undefined,
9
+ locale: ctx.locale,
10
+ messages: ctx.messages,
11
+ onStepChange: (_, title, subtitle)=>{
12
+ ctx.setDynamicTitle(title);
13
+ ctx.setDynamicSubtitle(subtitle);
14
+ }
15
+ })
16
+ },
17
+ 'signup': {
18
+ translationKey: 'signup',
19
+ getProps: (ctx)=>({
20
+ onSignup: ctx.onSignup,
21
+ showGoogleOAuth: ctx.showGoogleOAuth,
22
+ loginUrl: `${ctx.basePath}/login`,
23
+ verifyOtpUrl: `${ctx.basePath}/verify-otp`,
24
+ locale: ctx.locale,
25
+ messages: ctx.messages
26
+ })
27
+ },
28
+ 'forgot-password': {
29
+ translationKey: 'forgotPassword',
30
+ getProps: (ctx)=>({
31
+ loginUrl: `${ctx.basePath}/login`,
32
+ locale: ctx.locale,
33
+ messages: ctx.messages
34
+ })
35
+ },
36
+ 'verify-otp': {
37
+ translationKey: 'verifyOtp',
38
+ getProps: (ctx)=>({
39
+ loginUrl: `${ctx.basePath}/login`,
40
+ locale: ctx.locale,
41
+ messages: ctx.messages,
42
+ onPurposeChange: (_, title, subtitle)=>{
43
+ ctx.setDynamicTitle(title);
44
+ ctx.setDynamicSubtitle(subtitle);
45
+ }
46
+ })
47
+ },
48
+ 'set-password': {
49
+ translationKey: 'setPassword',
50
+ getProps: (ctx)=>({
51
+ redirectTo: ctx.redirectTo,
52
+ locale: ctx.locale,
53
+ messages: ctx.messages
54
+ })
55
+ }
56
+ };
@@ -0,0 +1,3 @@
1
+ export { AuthCardShell, type AuthCardShellProps, type PoweredByConfig } from './AuthCardShell';
2
+ export { FormRenderer, type FormRendererProps } from './FormRenderer';
3
+ export { FORM_CONFIGS, type FormConfig, type FormPropsContext } from './formConfigs';
@@ -0,0 +1,3 @@
1
+ export { AuthCardShell } from './AuthCardShell.js';
2
+ export { FormRenderer } from './FormRenderer.js';
3
+ export { FORM_CONFIGS } from './formConfigs.js';
@@ -0,0 +1,7 @@
1
+ import { type DeepPartial, type UiTranslations } from '../ui/translations';
2
+ export interface ForgotPasswordFormProps {
3
+ loginUrl?: string;
4
+ locale?: string;
5
+ messages?: Record<string, DeepPartial<UiTranslations>>;
6
+ }
7
+ export declare function ForgotPasswordForm({ loginUrl, locale, messages, }: ForgotPasswordFormProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,56 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import React from 'react';
4
+ import { Button, Input } from '../ui/index.js';
5
+ import { useForgotPasswordFlow } from '../../auth/application/hooks/useForgotPasswordFlow.js';
6
+ import { getUiTranslations } from '../ui/translations.js';
7
+ export function ForgotPasswordForm({ loginUrl = '/login', locale, messages }) {
8
+ const { email, error, isLoading, setEmail, handleSubmit } = useForgotPasswordFlow();
9
+ const translations = getUiTranslations(locale, messages);
10
+ const t = translations.forgotPassword;
11
+ const errors = translations.errors;
12
+ // Helper to translate error keys
13
+ const getErrorMessage = (err)=>{
14
+ if (!err) return null;
15
+ if (err in errors) return errors[err];
16
+ return err;
17
+ };
18
+ return /*#__PURE__*/ _jsxs(_Fragment, {
19
+ children: [
20
+ /*#__PURE__*/ _jsxs("form", {
21
+ onSubmit: handleSubmit,
22
+ className: "space-y-4",
23
+ children: [
24
+ error && /*#__PURE__*/ _jsx("div", {
25
+ className: "bg-red-50 text-red-600 border border-red-200 rounded-lg p-3 text-sm animate-[fadeIn_0.2s_ease-out]",
26
+ children: getErrorMessage(error)
27
+ }),
28
+ /*#__PURE__*/ _jsx(Input, {
29
+ type: "email",
30
+ label: t.emailLabel,
31
+ value: email,
32
+ onChange: (e)=>setEmail(e.target.value),
33
+ isRequired: true
34
+ }),
35
+ /*#__PURE__*/ _jsx(Button, {
36
+ type: "submit",
37
+ variant: "primary",
38
+ isLoading: isLoading,
39
+ children: t.sendResetCode
40
+ })
41
+ ]
42
+ }),
43
+ /*#__PURE__*/ _jsx("div", {
44
+ className: "text-center mt-6",
45
+ children: /*#__PURE__*/ _jsxs("a", {
46
+ href: loginUrl,
47
+ className: "text-sm text-gray-600 hover:text-gray-900 inline-flex items-center gap-1",
48
+ children: [
49
+ "← ",
50
+ t.backToLogin
51
+ ]
52
+ })
53
+ })
54
+ ]
55
+ });
56
+ }
@@ -0,0 +1,15 @@
1
+ import { type DeepPartial, type UiTranslations } from '../ui/translations';
2
+ export interface LoginFormProps {
3
+ onPasswordLogin: (credentials: {
4
+ email: string;
5
+ password: string;
6
+ }) => Promise<void>;
7
+ redirectTo?: string;
8
+ showGoogleOAuth?: boolean;
9
+ signupUrl?: string;
10
+ locale?: string;
11
+ messages?: Record<string, DeepPartial<UiTranslations>>;
12
+ /** Callback to update the card title based on current step */
13
+ onStepChange?: (step: 'email' | 'password' | 'otp-prompt', title: string, subtitle: string) => void;
14
+ }
15
+ export declare function LoginForm(props: LoginFormProps): import("react/jsx-runtime").JSX.Element;