@main12/auth-login 0.3.8 → 0.4.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/dist/components/AuthLayout.d.ts +9 -0
- package/dist/components/AuthPages.d.ts +15 -1
- package/dist/components/AuthPages.js +7 -1
- package/dist/components/AuthPagesServer.d.ts +6 -1
- package/dist/components/AuthPagesServer.js +11 -2
- package/dist/components/pages/ForgotPasswordPageHero.d.ts +1 -1
- package/dist/components/pages/ForgotPasswordPageHero.js +8 -6
- package/dist/components/pages/ForgotPasswordPageTailwind.d.ts +1 -1
- package/dist/components/pages/ForgotPasswordPageTailwind.js +12 -7
- package/dist/components/pages/LoginPageHero.js +18 -16
- package/dist/components/pages/LoginPageTailwind.js +18 -16
- package/dist/components/pages/SetPasswordPageHero.d.ts +1 -1
- package/dist/components/pages/SetPasswordPageHero.js +8 -6
- package/dist/components/pages/SetPasswordPageTailwind.d.ts +1 -1
- package/dist/components/pages/SetPasswordPageTailwind.js +9 -7
- package/dist/components/pages/SignupPageHero.d.ts +1 -1
- package/dist/components/pages/SignupPageHero.js +20 -14
- package/dist/components/pages/SignupPageTailwind.d.ts +1 -1
- package/dist/components/pages/SignupPageTailwind.js +17 -14
- package/dist/components/pages/VerifyOtpPageHero.js +9 -7
- package/dist/components/pages/VerifyOtpPageTailwind.js +13 -8
- package/dist/components/ui/locale.d.ts +29 -0
- package/dist/components/ui/locale.js +53 -0
- package/dist/components/ui/translations.d.ts +91 -0
- package/dist/components/ui/translations.js +179 -0
- package/package.json +1 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
import type { DeepPartial, UiTranslations } from './ui/translations';
|
|
2
3
|
export interface AuthLayoutConfig {
|
|
3
4
|
/** Component or URL. Falls back to pluginConfig when omitted. */
|
|
4
5
|
logo?: React.ReactNode;
|
|
@@ -13,6 +14,14 @@ export interface AuthLayoutConfig {
|
|
|
13
14
|
};
|
|
14
15
|
cardClassName?: string;
|
|
15
16
|
backgroundClass?: string;
|
|
17
|
+
/**
|
|
18
|
+
* Locale for this page's copy. Built-in support for 'en' and 'es'.
|
|
19
|
+
* Auto-detected by `<AuthPages />` when omitted; pass explicitly when using
|
|
20
|
+
* individual page components directly. Falls back to 'en'.
|
|
21
|
+
*/
|
|
22
|
+
locale?: string;
|
|
23
|
+
/** Partial translation overrides, keyed by locale. See `getUiTranslations`. */
|
|
24
|
+
messages?: Record<string, DeepPartial<UiTranslations>>;
|
|
16
25
|
}
|
|
17
26
|
export interface AuthLayoutProps extends AuthLayoutConfig {
|
|
18
27
|
children: React.ReactNode;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type React from 'react';
|
|
2
|
+
import type { DeepPartial, UiTranslations } from './ui/translations';
|
|
2
3
|
export interface AuthPagesProps {
|
|
3
4
|
/** The slug segments from the catch-all route, e.g. ['login'] or ['forgot-password'] */
|
|
4
5
|
slug?: string[];
|
|
@@ -30,5 +31,18 @@ export interface AuthPagesProps {
|
|
|
30
31
|
passwordLogin?: boolean;
|
|
31
32
|
/** Allow OTP-based login. @default true */
|
|
32
33
|
otpLogin?: boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Locale for the auth pages' copy. Built-in support for 'en' and 'es'.
|
|
36
|
+
* If omitted, auto-detected from the `NEXT_LOCALE` cookie, `Accept-Language`
|
|
37
|
+
* header, or `<html lang>` — works automatically with next-intl,
|
|
38
|
+
* next-i18next, or no i18n library at all. Falls back to 'en'.
|
|
39
|
+
*/
|
|
40
|
+
locale?: string;
|
|
41
|
+
/**
|
|
42
|
+
* Partial translation overrides, keyed by locale. Any key you omit falls
|
|
43
|
+
* back to the built-in English/Spanish copy. You can also add entirely new
|
|
44
|
+
* locales this way (e.g. `messages={{ fr: { login: { title: 'Bienvenue' } } }}`).
|
|
45
|
+
*/
|
|
46
|
+
messages?: Record<string, DeepPartial<UiTranslations>>;
|
|
33
47
|
}
|
|
34
|
-
export default function AuthPages({ slug, redirectTo, logo, onPasswordLogin, onSignup, basePath, showGoogleOAuth, backgroundClass, style, allowSignup, passwordLogin, otpLogin, }: AuthPagesProps): import("react/jsx-runtime").JSX.Element;
|
|
48
|
+
export default function AuthPages({ slug, redirectTo, logo, onPasswordLogin, onSignup, basePath, showGoogleOAuth, backgroundClass, style, allowSignup, passwordLogin, otpLogin, locale, messages, }: AuthPagesProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
3
|
import { pluginConfig, initClientConfig } from '../config.js';
|
|
4
|
+
import { detectClientLocale } from './ui/locale.js';
|
|
4
5
|
import LoginPage from './pages/LoginPage.js';
|
|
5
6
|
import SignupPage from './pages/SignupPage.js';
|
|
6
7
|
import ForgotPasswordPage from './pages/ForgotPasswordPage.js';
|
|
@@ -38,7 +39,7 @@ const defaultSignup = async ({ name, email })=>{
|
|
|
38
39
|
throw new Error(err.message || 'Signup failed');
|
|
39
40
|
}
|
|
40
41
|
};
|
|
41
|
-
export default function AuthPages({ slug, redirectTo = '/admin', logo, onPasswordLogin = defaultPasswordLogin, onSignup = defaultSignup, basePath = '/auth', showGoogleOAuth, backgroundClass, style, allowSignup = true, passwordLogin = true, otpLogin = true }) {
|
|
42
|
+
export default function AuthPages({ slug, redirectTo = '/admin', logo, onPasswordLogin = defaultPasswordLogin, onSignup = defaultSignup, basePath = '/auth', showGoogleOAuth, backgroundClass, style, allowSignup = true, passwordLogin = true, otpLogin = true, locale, messages }) {
|
|
42
43
|
// Sync server plugin config to client using props (which come from the server via AuthPagesServer)
|
|
43
44
|
initClientConfig({
|
|
44
45
|
style: style ?? pluginConfig.style,
|
|
@@ -46,10 +47,15 @@ export default function AuthPages({ slug, redirectTo = '/admin', logo, onPasswor
|
|
|
46
47
|
passwordLogin,
|
|
47
48
|
otpLogin
|
|
48
49
|
});
|
|
50
|
+
// Resolve locale client-side only if the server didn't already resolve one
|
|
51
|
+
// (AuthPagesServer always resolves and passes an explicit locale down).
|
|
52
|
+
const resolvedLocale = locale ?? detectClientLocale();
|
|
49
53
|
const page = slug?.[0] ?? 'login';
|
|
50
54
|
const base = basePath.replace(/\/$/, '');
|
|
51
55
|
const shared = {
|
|
52
56
|
logo,
|
|
57
|
+
locale: resolvedLocale,
|
|
58
|
+
messages,
|
|
53
59
|
...showGoogleOAuth !== undefined ? {
|
|
54
60
|
showGoogleOAuth
|
|
55
61
|
} : {},
|
|
@@ -7,6 +7,11 @@ export type { AuthPagesProps };
|
|
|
7
7
|
* down to the client component. No env vars involved — the plugin's
|
|
8
8
|
* `style`, `googleOAuthEnabled`, etc. options are the single source of truth.
|
|
9
9
|
*
|
|
10
|
+
* Locale is resolved per-request: an explicit `locale` prop always wins,
|
|
11
|
+
* otherwise it's auto-detected from the `NEXT_LOCALE` cookie or
|
|
12
|
+
* `Accept-Language` header (works automatically with next-intl,
|
|
13
|
+
* next-i18next, or no i18n library at all — no dependency required).
|
|
14
|
+
*
|
|
10
15
|
* ```tsx
|
|
11
16
|
* // app/(auth)/auth/[...slug]/page.tsx (NO 'use client' needed!)
|
|
12
17
|
* import { AuthPages } from '@main12/auth-login/rsc'
|
|
@@ -16,4 +21,4 @@ export type { AuthPagesProps };
|
|
|
16
21
|
* }
|
|
17
22
|
* ```
|
|
18
23
|
*/
|
|
19
|
-
export default function AuthPages(props: AuthPagesProps): import("react/jsx-runtime").JSX.Element
|
|
24
|
+
export default function AuthPages(props: AuthPagesProps): Promise<import("react/jsx-runtime").JSX.Element>;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { headers } from 'next/headers';
|
|
2
3
|
import AuthPagesClient from './AuthPages.js';
|
|
3
4
|
import { pluginConfig } from '../config.js';
|
|
5
|
+
import { detectServerLocale } from './ui/locale.js';
|
|
4
6
|
/**
|
|
5
7
|
* Server component wrapper for AuthPages.
|
|
6
8
|
* Reads plugin config directly from the shared `pluginConfig` singleton
|
|
@@ -8,6 +10,11 @@ import { pluginConfig } from '../config.js';
|
|
|
8
10
|
* down to the client component. No env vars involved — the plugin's
|
|
9
11
|
* `style`, `googleOAuthEnabled`, etc. options are the single source of truth.
|
|
10
12
|
*
|
|
13
|
+
* Locale is resolved per-request: an explicit `locale` prop always wins,
|
|
14
|
+
* otherwise it's auto-detected from the `NEXT_LOCALE` cookie or
|
|
15
|
+
* `Accept-Language` header (works automatically with next-intl,
|
|
16
|
+
* next-i18next, or no i18n library at all — no dependency required).
|
|
17
|
+
*
|
|
11
18
|
* ```tsx
|
|
12
19
|
* // app/(auth)/auth/[...slug]/page.tsx (NO 'use client' needed!)
|
|
13
20
|
* import { AuthPages } from '@main12/auth-login/rsc'
|
|
@@ -16,13 +23,15 @@ import { pluginConfig } from '../config.js';
|
|
|
16
23
|
* return <AuthPages slug={slug} />
|
|
17
24
|
* }
|
|
18
25
|
* ```
|
|
19
|
-
*/ export default function AuthPages(props) {
|
|
26
|
+
*/ export default async function AuthPages(props) {
|
|
27
|
+
const resolvedLocale = props.locale ?? detectServerLocale(await headers());
|
|
20
28
|
return /*#__PURE__*/ _jsx(AuthPagesClient, {
|
|
21
29
|
...props,
|
|
22
30
|
showGoogleOAuth: props.showGoogleOAuth ?? pluginConfig.googleOAuthEnabled,
|
|
23
31
|
style: props.style ?? pluginConfig.style,
|
|
24
32
|
allowSignup: props.allowSignup ?? pluginConfig.allowSignup,
|
|
25
33
|
passwordLogin: pluginConfig.passwordLogin,
|
|
26
|
-
otpLogin: pluginConfig.otpLogin
|
|
34
|
+
otpLogin: pluginConfig.otpLogin,
|
|
35
|
+
locale: resolvedLocale
|
|
27
36
|
});
|
|
28
37
|
}
|
|
@@ -2,4 +2,4 @@ import type { AuthLayoutConfig } from '../AuthLayout';
|
|
|
2
2
|
export interface ForgotPasswordPageHeroProps extends AuthLayoutConfig {
|
|
3
3
|
loginUrl?: string;
|
|
4
4
|
}
|
|
5
|
-
export default function ForgotPasswordPageHero({ loginUrl, logo, poweredBy, cardClassName, backgroundClass }: ForgotPasswordPageHeroProps): import("react/jsx-runtime").JSX.Element;
|
|
5
|
+
export default function ForgotPasswordPageHero({ loginUrl, logo, poweredBy, cardClassName, backgroundClass, locale, messages }: ForgotPasswordPageHeroProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -6,12 +6,14 @@ import { Icon } from '@iconify/react';
|
|
|
6
6
|
import { motion } from 'framer-motion';
|
|
7
7
|
import { useForgotPasswordFlow } from '../../auth/application/hooks/useForgotPasswordFlow.js';
|
|
8
8
|
import { AuthLayout } from '../AuthLayout.js';
|
|
9
|
-
|
|
9
|
+
import { getUiTranslations } from '../ui/translations.js';
|
|
10
|
+
export default function ForgotPasswordPageHero({ loginUrl = '/login', logo, poweredBy, cardClassName, backgroundClass, locale, messages }) {
|
|
10
11
|
const { email, error, isLoading, setEmail, handleSubmit } = useForgotPasswordFlow();
|
|
12
|
+
const t = getUiTranslations(locale, messages).forgotPassword;
|
|
11
13
|
return /*#__PURE__*/ _jsx(AuthLayout, {
|
|
12
14
|
logo: logo,
|
|
13
|
-
title:
|
|
14
|
-
subtitle:
|
|
15
|
+
title: t.title,
|
|
16
|
+
subtitle: t.subtitle,
|
|
15
17
|
poweredBy: poweredBy,
|
|
16
18
|
cardClassName: cardClassName,
|
|
17
19
|
backgroundClass: backgroundClass,
|
|
@@ -23,7 +25,7 @@ export default function ForgotPasswordPageHero({ loginUrl = '/login', logo, powe
|
|
|
23
25
|
icon: "lucide:arrow-left",
|
|
24
26
|
width: 16
|
|
25
27
|
}),
|
|
26
|
-
|
|
28
|
+
t.backToLogin
|
|
27
29
|
]
|
|
28
30
|
}),
|
|
29
31
|
children: /*#__PURE__*/ _jsxs("form", {
|
|
@@ -49,7 +51,7 @@ export default function ForgotPasswordPageHero({ loginUrl = '/login', logo, powe
|
|
|
49
51
|
children: [
|
|
50
52
|
/*#__PURE__*/ _jsx(Label, {
|
|
51
53
|
className: "text-gray-600",
|
|
52
|
-
children:
|
|
54
|
+
children: t.emailLabel
|
|
53
55
|
}),
|
|
54
56
|
/*#__PURE__*/ _jsx(Input, {
|
|
55
57
|
variant: "secondary"
|
|
@@ -68,7 +70,7 @@ export default function ForgotPasswordPageHero({ loginUrl = '/login', logo, powe
|
|
|
68
70
|
color: "current",
|
|
69
71
|
size: "sm"
|
|
70
72
|
}),
|
|
71
|
-
|
|
73
|
+
t.sendResetCode
|
|
72
74
|
]
|
|
73
75
|
})
|
|
74
76
|
})
|
|
@@ -2,4 +2,4 @@ import type { AuthLayoutConfig } from '../AuthLayout';
|
|
|
2
2
|
export interface ForgotPasswordPageProps extends AuthLayoutConfig {
|
|
3
3
|
loginUrl?: string;
|
|
4
4
|
}
|
|
5
|
-
export default function ForgotPasswordPage({ loginUrl, logo, poweredBy, cardClassName, backgroundClass, }: ForgotPasswordPageProps): import("react/jsx-runtime").JSX.Element;
|
|
5
|
+
export default function ForgotPasswordPage({ loginUrl, logo, poweredBy, cardClassName, backgroundClass, locale, messages, }: ForgotPasswordPageProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -4,19 +4,24 @@ import React from 'react';
|
|
|
4
4
|
import { Button, Input } from '../ui/index.js';
|
|
5
5
|
import { useForgotPasswordFlow } from '../../auth/application/hooks/useForgotPasswordFlow.js';
|
|
6
6
|
import { AuthLayout } from '../AuthLayout.js';
|
|
7
|
-
|
|
7
|
+
import { getUiTranslations } from '../ui/translations.js';
|
|
8
|
+
export default function ForgotPasswordPage({ loginUrl = '/login', logo, poweredBy, cardClassName, backgroundClass, locale, messages }) {
|
|
8
9
|
const { email, error, isLoading, setEmail, handleSubmit } = useForgotPasswordFlow();
|
|
10
|
+
const t = getUiTranslations(locale, messages).forgotPassword;
|
|
9
11
|
return /*#__PURE__*/ _jsx(AuthLayout, {
|
|
10
12
|
logo: logo,
|
|
11
|
-
title:
|
|
12
|
-
subtitle:
|
|
13
|
+
title: t.title,
|
|
14
|
+
subtitle: t.subtitle,
|
|
13
15
|
poweredBy: poweredBy,
|
|
14
16
|
cardClassName: cardClassName,
|
|
15
17
|
backgroundClass: backgroundClass,
|
|
16
|
-
footer: /*#__PURE__*/
|
|
18
|
+
footer: /*#__PURE__*/ _jsxs("a", {
|
|
17
19
|
href: loginUrl,
|
|
18
20
|
className: "text-sm text-gray-600 hover:text-gray-900 inline-flex items-center gap-1",
|
|
19
|
-
children:
|
|
21
|
+
children: [
|
|
22
|
+
"← ",
|
|
23
|
+
t.backToLogin
|
|
24
|
+
]
|
|
20
25
|
}),
|
|
21
26
|
children: /*#__PURE__*/ _jsxs("form", {
|
|
22
27
|
onSubmit: handleSubmit,
|
|
@@ -28,7 +33,7 @@ export default function ForgotPasswordPage({ loginUrl = '/login', logo, poweredB
|
|
|
28
33
|
}),
|
|
29
34
|
/*#__PURE__*/ _jsx(Input, {
|
|
30
35
|
type: "email",
|
|
31
|
-
label:
|
|
36
|
+
label: t.emailLabel,
|
|
32
37
|
value: email,
|
|
33
38
|
onChange: (e)=>setEmail(e.target.value),
|
|
34
39
|
isRequired: true
|
|
@@ -37,7 +42,7 @@ export default function ForgotPasswordPage({ loginUrl = '/login', logo, poweredB
|
|
|
37
42
|
type: "submit",
|
|
38
43
|
variant: "primary",
|
|
39
44
|
isLoading: isLoading,
|
|
40
|
-
children:
|
|
45
|
+
children: t.sendResetCode
|
|
41
46
|
})
|
|
42
47
|
]
|
|
43
48
|
})
|
|
@@ -7,15 +7,17 @@ import { motion, AnimatePresence } from 'framer-motion';
|
|
|
7
7
|
import { Icon } from '@iconify/react';
|
|
8
8
|
import { useLoginFlow } from '../../auth/application/hooks/useLoginFlow.js';
|
|
9
9
|
import { AuthLayout } from '../AuthLayout.js';
|
|
10
|
-
|
|
10
|
+
import { getUiTranslations } from '../ui/translations.js';
|
|
11
|
+
function LoginHeroContent({ onPasswordLogin, redirectTo = '/', showGoogleOAuth = true, signupUrl = '/signup', logo, poweredBy, cardClassName, backgroundClass, locale, messages }) {
|
|
11
12
|
const searchParams = useSearchParams();
|
|
12
13
|
const resolvedRedirect = searchParams.get('redirect') || redirectTo;
|
|
14
|
+
const t = getUiTranslations(locale, messages).login;
|
|
13
15
|
const { step, email, password, error, isLoading, isSendingOtp, showPassword, setEmail, setPassword, setShowPassword, handleEmailSubmit, handlePasswordSubmit, handleSendOtp, handleEditEmail, handleGoogleLogin } = useLoginFlow({
|
|
14
16
|
redirectTo: resolvedRedirect,
|
|
15
17
|
onPasswordLogin
|
|
16
18
|
});
|
|
17
|
-
const stepTitle = step === 'otp-prompt' ?
|
|
18
|
-
const stepSubtitle = step === 'otp-prompt' ?
|
|
19
|
+
const stepTitle = step === 'otp-prompt' ? t.otpPromptTitle : step === 'email' ? t.title : t.passwordStepTitle;
|
|
20
|
+
const stepSubtitle = step === 'otp-prompt' ? t.otpPromptSubtitle : step === 'email' ? t.subtitle : t.passwordStepSubtitle;
|
|
19
21
|
return /*#__PURE__*/ _jsx(AuthLayout, {
|
|
20
22
|
logo: logo,
|
|
21
23
|
title: stepTitle,
|
|
@@ -26,12 +28,12 @@ function LoginHeroContent({ onPasswordLogin, redirectTo = '/', showGoogleOAuth =
|
|
|
26
28
|
footer: signupUrl ? /*#__PURE__*/ _jsxs("p", {
|
|
27
29
|
className: "text-center text-gray-600 text-sm",
|
|
28
30
|
children: [
|
|
29
|
-
|
|
31
|
+
t.noAccount,
|
|
30
32
|
' ',
|
|
31
33
|
/*#__PURE__*/ _jsx("a", {
|
|
32
34
|
href: signupUrl,
|
|
33
35
|
className: "text-gray-900 font-medium hover:underline",
|
|
34
|
-
children:
|
|
36
|
+
children: t.signUpLink
|
|
35
37
|
})
|
|
36
38
|
]
|
|
37
39
|
}) : undefined,
|
|
@@ -67,7 +69,7 @@ function LoginHeroContent({ onPasswordLogin, redirectTo = '/', showGoogleOAuth =
|
|
|
67
69
|
icon: "flat-color-icons:google",
|
|
68
70
|
width: 20
|
|
69
71
|
}),
|
|
70
|
-
|
|
72
|
+
t.continueWithGoogle
|
|
71
73
|
]
|
|
72
74
|
}),
|
|
73
75
|
/*#__PURE__*/ _jsxs("div", {
|
|
@@ -78,7 +80,7 @@ function LoginHeroContent({ onPasswordLogin, redirectTo = '/', showGoogleOAuth =
|
|
|
78
80
|
}),
|
|
79
81
|
/*#__PURE__*/ _jsx("span", {
|
|
80
82
|
className: "text-gray-500 text-sm",
|
|
81
|
-
children:
|
|
83
|
+
children: t.or
|
|
82
84
|
}),
|
|
83
85
|
/*#__PURE__*/ _jsx(Separator, {
|
|
84
86
|
className: "flex-1"
|
|
@@ -110,7 +112,7 @@ function LoginHeroContent({ onPasswordLogin, redirectTo = '/', showGoogleOAuth =
|
|
|
110
112
|
children: [
|
|
111
113
|
/*#__PURE__*/ _jsx(Label, {
|
|
112
114
|
className: "text-gray-600",
|
|
113
|
-
children:
|
|
115
|
+
children: t.emailLabel
|
|
114
116
|
}),
|
|
115
117
|
/*#__PURE__*/ _jsx(Input, {
|
|
116
118
|
variant: "secondary"
|
|
@@ -128,7 +130,7 @@ function LoginHeroContent({ onPasswordLogin, redirectTo = '/', showGoogleOAuth =
|
|
|
128
130
|
color: "current",
|
|
129
131
|
size: "sm"
|
|
130
132
|
}),
|
|
131
|
-
|
|
133
|
+
t.continue
|
|
132
134
|
]
|
|
133
135
|
})
|
|
134
136
|
})
|
|
@@ -164,7 +166,7 @@ function LoginHeroContent({ onPasswordLogin, redirectTo = '/', showGoogleOAuth =
|
|
|
164
166
|
type: "button",
|
|
165
167
|
onClick: handleEditEmail,
|
|
166
168
|
className: "text-gray-600 text-sm font-medium hover:text-gray-900",
|
|
167
|
-
children:
|
|
169
|
+
children: t.edit
|
|
168
170
|
})
|
|
169
171
|
]
|
|
170
172
|
}),
|
|
@@ -192,7 +194,7 @@ function LoginHeroContent({ onPasswordLogin, redirectTo = '/', showGoogleOAuth =
|
|
|
192
194
|
children: [
|
|
193
195
|
/*#__PURE__*/ _jsx(Label, {
|
|
194
196
|
className: "text-gray-600",
|
|
195
|
-
children:
|
|
197
|
+
children: t.passwordLabel
|
|
196
198
|
}),
|
|
197
199
|
/*#__PURE__*/ _jsxs("div", {
|
|
198
200
|
className: "relative",
|
|
@@ -219,7 +221,7 @@ function LoginHeroContent({ onPasswordLogin, redirectTo = '/', showGoogleOAuth =
|
|
|
219
221
|
children: /*#__PURE__*/ _jsx("a", {
|
|
220
222
|
href: "/forgot-password",
|
|
221
223
|
className: "text-sm text-gray-700 hover:underline",
|
|
222
|
-
children:
|
|
224
|
+
children: t.forgotPassword
|
|
223
225
|
})
|
|
224
226
|
}),
|
|
225
227
|
/*#__PURE__*/ _jsx(Button, {
|
|
@@ -234,7 +236,7 @@ function LoginHeroContent({ onPasswordLogin, redirectTo = '/', showGoogleOAuth =
|
|
|
234
236
|
color: "current",
|
|
235
237
|
size: "sm"
|
|
236
238
|
}),
|
|
237
|
-
|
|
239
|
+
t.continue
|
|
238
240
|
]
|
|
239
241
|
})
|
|
240
242
|
})
|
|
@@ -270,7 +272,7 @@ function LoginHeroContent({ onPasswordLogin, redirectTo = '/', showGoogleOAuth =
|
|
|
270
272
|
type: "button",
|
|
271
273
|
onClick: handleEditEmail,
|
|
272
274
|
className: "text-gray-600 text-sm font-medium hover:text-gray-900",
|
|
273
|
-
children:
|
|
275
|
+
children: t.edit
|
|
274
276
|
})
|
|
275
277
|
]
|
|
276
278
|
}),
|
|
@@ -288,7 +290,7 @@ function LoginHeroContent({ onPasswordLogin, redirectTo = '/', showGoogleOAuth =
|
|
|
288
290
|
}),
|
|
289
291
|
/*#__PURE__*/ _jsx("p", {
|
|
290
292
|
className: "text-sm text-blue-700",
|
|
291
|
-
children:
|
|
293
|
+
children: t.verificationNotice
|
|
292
294
|
})
|
|
293
295
|
]
|
|
294
296
|
}),
|
|
@@ -304,7 +306,7 @@ function LoginHeroContent({ onPasswordLogin, redirectTo = '/', showGoogleOAuth =
|
|
|
304
306
|
color: "current",
|
|
305
307
|
size: "sm"
|
|
306
308
|
}),
|
|
307
|
-
isPending ?
|
|
309
|
+
isPending ? t.sendingCode : t.sendCode
|
|
308
310
|
]
|
|
309
311
|
})
|
|
310
312
|
})
|
|
@@ -5,15 +5,17 @@ import { useSearchParams } from 'next/navigation';
|
|
|
5
5
|
import { Button, Input, Divider, Spinner } from '../ui/index.js';
|
|
6
6
|
import { useLoginFlow } from '../../auth/application/hooks/useLoginFlow.js';
|
|
7
7
|
import { AuthLayout } from '../AuthLayout.js';
|
|
8
|
-
|
|
8
|
+
import { getUiTranslations } from '../ui/translations.js';
|
|
9
|
+
function LoginContent({ onPasswordLogin, redirectTo = '/', showGoogleOAuth = true, signupUrl = '/signup', logo, poweredBy, cardClassName, backgroundClass, locale, messages }) {
|
|
9
10
|
const searchParams = useSearchParams();
|
|
10
11
|
const resolvedRedirect = searchParams.get('redirect') || redirectTo;
|
|
12
|
+
const t = getUiTranslations(locale, messages).login;
|
|
11
13
|
const { step, email, password, error, isLoading, isSendingOtp, showPassword, setEmail, setPassword, setShowPassword, handleEmailSubmit, handlePasswordSubmit, handleSendOtp, handleEditEmail, handleGoogleLogin } = useLoginFlow({
|
|
12
14
|
redirectTo: resolvedRedirect,
|
|
13
15
|
onPasswordLogin
|
|
14
16
|
});
|
|
15
|
-
const stepTitle = step === 'otp-prompt' ?
|
|
16
|
-
const stepSubtitle = step === 'otp-prompt' ?
|
|
17
|
+
const stepTitle = step === 'otp-prompt' ? t.otpPromptTitle : step === 'email' ? t.title : t.passwordStepTitle;
|
|
18
|
+
const stepSubtitle = step === 'otp-prompt' ? t.otpPromptSubtitle : step === 'email' ? t.subtitle : t.passwordStepSubtitle;
|
|
17
19
|
return /*#__PURE__*/ _jsxs(AuthLayout, {
|
|
18
20
|
logo: logo,
|
|
19
21
|
title: stepTitle,
|
|
@@ -24,12 +26,12 @@ function LoginContent({ onPasswordLogin, redirectTo = '/', showGoogleOAuth = tru
|
|
|
24
26
|
footer: signupUrl ? /*#__PURE__*/ _jsxs("p", {
|
|
25
27
|
className: "text-center text-gray-600 text-sm",
|
|
26
28
|
children: [
|
|
27
|
-
|
|
29
|
+
t.noAccount,
|
|
28
30
|
' ',
|
|
29
31
|
/*#__PURE__*/ _jsx("a", {
|
|
30
32
|
href: signupUrl,
|
|
31
33
|
className: "text-gray-900 font-medium hover:underline",
|
|
32
|
-
children:
|
|
34
|
+
children: t.signUpLink
|
|
33
35
|
})
|
|
34
36
|
]
|
|
35
37
|
}) : undefined,
|
|
@@ -69,7 +71,7 @@ function LoginContent({ onPasswordLogin, redirectTo = '/', showGoogleOAuth = tru
|
|
|
69
71
|
})
|
|
70
72
|
]
|
|
71
73
|
}),
|
|
72
|
-
|
|
74
|
+
t.continueWithGoogle
|
|
73
75
|
]
|
|
74
76
|
}),
|
|
75
77
|
/*#__PURE__*/ _jsxs("div", {
|
|
@@ -80,7 +82,7 @@ function LoginContent({ onPasswordLogin, redirectTo = '/', showGoogleOAuth = tru
|
|
|
80
82
|
}),
|
|
81
83
|
/*#__PURE__*/ _jsx("span", {
|
|
82
84
|
className: "text-gray-500 text-sm",
|
|
83
|
-
children:
|
|
85
|
+
children: t.or
|
|
84
86
|
}),
|
|
85
87
|
/*#__PURE__*/ _jsx(Divider, {
|
|
86
88
|
className: "flex-1"
|
|
@@ -99,7 +101,7 @@ function LoginContent({ onPasswordLogin, redirectTo = '/', showGoogleOAuth = tru
|
|
|
99
101
|
}),
|
|
100
102
|
/*#__PURE__*/ _jsx(Input, {
|
|
101
103
|
type: "email",
|
|
102
|
-
label:
|
|
104
|
+
label: t.emailLabel,
|
|
103
105
|
value: email,
|
|
104
106
|
onValueChange: setEmail,
|
|
105
107
|
isRequired: true,
|
|
@@ -109,7 +111,7 @@ function LoginContent({ onPasswordLogin, redirectTo = '/', showGoogleOAuth = tru
|
|
|
109
111
|
type: "submit",
|
|
110
112
|
variant: "primary",
|
|
111
113
|
isLoading: isLoading,
|
|
112
|
-
children:
|
|
114
|
+
children: t.continue
|
|
113
115
|
})
|
|
114
116
|
]
|
|
115
117
|
})
|
|
@@ -129,7 +131,7 @@ function LoginContent({ onPasswordLogin, redirectTo = '/', showGoogleOAuth = tru
|
|
|
129
131
|
type: "button",
|
|
130
132
|
onClick: handleEditEmail,
|
|
131
133
|
className: "text-gray-600 text-sm font-medium hover:text-gray-900",
|
|
132
|
-
children:
|
|
134
|
+
children: t.edit
|
|
133
135
|
})
|
|
134
136
|
]
|
|
135
137
|
}),
|
|
@@ -143,7 +145,7 @@ function LoginContent({ onPasswordLogin, redirectTo = '/', showGoogleOAuth = tru
|
|
|
143
145
|
}),
|
|
144
146
|
/*#__PURE__*/ _jsx(Input, {
|
|
145
147
|
type: showPassword ? 'text' : 'password',
|
|
146
|
-
label:
|
|
148
|
+
label: t.passwordLabel,
|
|
147
149
|
value: password,
|
|
148
150
|
onValueChange: setPassword,
|
|
149
151
|
isRequired: true,
|
|
@@ -155,14 +157,14 @@ function LoginContent({ onPasswordLogin, redirectTo = '/', showGoogleOAuth = tru
|
|
|
155
157
|
children: /*#__PURE__*/ _jsx("a", {
|
|
156
158
|
href: "/forgot-password",
|
|
157
159
|
className: "text-sm text-gray-700 hover:text-gray-900 hover:underline",
|
|
158
|
-
children:
|
|
160
|
+
children: t.forgotPassword
|
|
159
161
|
})
|
|
160
162
|
}),
|
|
161
163
|
/*#__PURE__*/ _jsx(Button, {
|
|
162
164
|
type: "submit",
|
|
163
165
|
variant: "primary",
|
|
164
166
|
isLoading: isLoading,
|
|
165
|
-
children:
|
|
167
|
+
children: t.continue
|
|
166
168
|
})
|
|
167
169
|
]
|
|
168
170
|
})
|
|
@@ -182,7 +184,7 @@ function LoginContent({ onPasswordLogin, redirectTo = '/', showGoogleOAuth = tru
|
|
|
182
184
|
type: "button",
|
|
183
185
|
onClick: handleEditEmail,
|
|
184
186
|
className: "text-gray-600 text-sm font-medium hover:text-gray-900",
|
|
185
|
-
children:
|
|
187
|
+
children: t.edit
|
|
186
188
|
})
|
|
187
189
|
]
|
|
188
190
|
}),
|
|
@@ -201,7 +203,7 @@ function LoginContent({ onPasswordLogin, redirectTo = '/', showGoogleOAuth = tru
|
|
|
201
203
|
}),
|
|
202
204
|
/*#__PURE__*/ _jsx("p", {
|
|
203
205
|
className: "text-sm text-blue-700",
|
|
204
|
-
children:
|
|
206
|
+
children: t.verificationNotice
|
|
205
207
|
})
|
|
206
208
|
]
|
|
207
209
|
})
|
|
@@ -210,7 +212,7 @@ function LoginContent({ onPasswordLogin, redirectTo = '/', showGoogleOAuth = tru
|
|
|
210
212
|
variant: "primary",
|
|
211
213
|
isLoading: isSendingOtp,
|
|
212
214
|
onPress: handleSendOtp,
|
|
213
|
-
children: isSendingOtp ?
|
|
215
|
+
children: isSendingOtp ? t.sendingCode : t.sendCode
|
|
214
216
|
})
|
|
215
217
|
]
|
|
216
218
|
})
|
|
@@ -2,4 +2,4 @@ import type { AuthLayoutConfig } from '../AuthLayout';
|
|
|
2
2
|
export interface SetPasswordPageHeroProps extends AuthLayoutConfig {
|
|
3
3
|
redirectTo?: string;
|
|
4
4
|
}
|
|
5
|
-
export default function SetPasswordPageHero({ redirectTo, logo, poweredBy, cardClassName, backgroundClass }: SetPasswordPageHeroProps): import("react/jsx-runtime").JSX.Element;
|
|
5
|
+
export default function SetPasswordPageHero({ redirectTo, logo, poweredBy, cardClassName, backgroundClass, locale, messages }: SetPasswordPageHeroProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -6,17 +6,19 @@ import { Icon } from '@iconify/react';
|
|
|
6
6
|
import { motion } from 'framer-motion';
|
|
7
7
|
import { useSetPasswordFlow } from '../../auth/application/hooks/useSetPasswordFlow.js';
|
|
8
8
|
import { AuthLayout } from '../AuthLayout.js';
|
|
9
|
-
|
|
9
|
+
import { getUiTranslations } from '../ui/translations.js';
|
|
10
|
+
export default function SetPasswordPageHero({ redirectTo = '/', logo, poweredBy, cardClassName, backgroundClass, locale, messages }) {
|
|
10
11
|
const { password, confirmPassword, error, isLoading, showPassword, strength, setPassword, setConfirmPassword, setShowPassword, handleSubmit } = useSetPasswordFlow({
|
|
11
12
|
redirectTo
|
|
12
13
|
});
|
|
13
14
|
const bars = Array.from({
|
|
14
15
|
length: 5
|
|
15
16
|
}, (_, i)=>i < strength.score);
|
|
17
|
+
const t = getUiTranslations(locale, messages).setPassword;
|
|
16
18
|
return /*#__PURE__*/ _jsx(AuthLayout, {
|
|
17
19
|
logo: logo,
|
|
18
|
-
title:
|
|
19
|
-
subtitle:
|
|
20
|
+
title: t.title,
|
|
21
|
+
subtitle: t.subtitle,
|
|
20
22
|
poweredBy: poweredBy,
|
|
21
23
|
cardClassName: cardClassName,
|
|
22
24
|
backgroundClass: backgroundClass,
|
|
@@ -44,7 +46,7 @@ export default function SetPasswordPageHero({ redirectTo = '/', logo, poweredBy,
|
|
|
44
46
|
children: [
|
|
45
47
|
/*#__PURE__*/ _jsx(Label, {
|
|
46
48
|
className: "text-gray-600",
|
|
47
|
-
children:
|
|
49
|
+
children: t.newPasswordLabel
|
|
48
50
|
}),
|
|
49
51
|
/*#__PURE__*/ _jsxs("div", {
|
|
50
52
|
className: "relative",
|
|
@@ -82,7 +84,7 @@ export default function SetPasswordPageHero({ redirectTo = '/', logo, poweredBy,
|
|
|
82
84
|
children: [
|
|
83
85
|
/*#__PURE__*/ _jsx(Label, {
|
|
84
86
|
className: "text-gray-600",
|
|
85
|
-
children:
|
|
87
|
+
children: t.confirmPasswordLabel
|
|
86
88
|
}),
|
|
87
89
|
/*#__PURE__*/ _jsx(Input, {
|
|
88
90
|
variant: "secondary",
|
|
@@ -102,7 +104,7 @@ export default function SetPasswordPageHero({ redirectTo = '/', logo, poweredBy,
|
|
|
102
104
|
color: "current",
|
|
103
105
|
size: "sm"
|
|
104
106
|
}),
|
|
105
|
-
|
|
107
|
+
t.setPassword
|
|
106
108
|
]
|
|
107
109
|
})
|
|
108
110
|
})
|
|
@@ -2,4 +2,4 @@ import type { AuthLayoutConfig } from '../AuthLayout';
|
|
|
2
2
|
export interface SetPasswordPageProps extends AuthLayoutConfig {
|
|
3
3
|
redirectTo?: string;
|
|
4
4
|
}
|
|
5
|
-
export default function SetPasswordPage({ redirectTo, logo, poweredBy, cardClassName, backgroundClass, }: SetPasswordPageProps): import("react/jsx-runtime").JSX.Element;
|
|
5
|
+
export default function SetPasswordPage({ redirectTo, logo, poweredBy, cardClassName, backgroundClass, locale, messages, }: SetPasswordPageProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -4,17 +4,19 @@ import React from 'react';
|
|
|
4
4
|
import { Button, Input } from '../ui/index.js';
|
|
5
5
|
import { useSetPasswordFlow } from '../../auth/application/hooks/useSetPasswordFlow.js';
|
|
6
6
|
import { AuthLayout } from '../AuthLayout.js';
|
|
7
|
-
|
|
7
|
+
import { getUiTranslations } from '../ui/translations.js';
|
|
8
|
+
export default function SetPasswordPage({ redirectTo = '/', logo, poweredBy, cardClassName, backgroundClass, locale, messages }) {
|
|
8
9
|
const { password, confirmPassword, error, isLoading, showPassword, strength, setPassword, setConfirmPassword, setShowPassword, handleSubmit } = useSetPasswordFlow({
|
|
9
10
|
redirectTo
|
|
10
11
|
});
|
|
11
12
|
const strengthBars = Array.from({
|
|
12
13
|
length: 5
|
|
13
14
|
}, (_, i)=>i < strength.score);
|
|
15
|
+
const t = getUiTranslations(locale, messages).setPassword;
|
|
14
16
|
return /*#__PURE__*/ _jsx(AuthLayout, {
|
|
15
17
|
logo: logo,
|
|
16
|
-
title:
|
|
17
|
-
subtitle:
|
|
18
|
+
title: t.title,
|
|
19
|
+
subtitle: t.subtitle,
|
|
18
20
|
poweredBy: poweredBy,
|
|
19
21
|
cardClassName: cardClassName,
|
|
20
22
|
backgroundClass: backgroundClass,
|
|
@@ -31,7 +33,7 @@ export default function SetPasswordPage({ redirectTo = '/', logo, poweredBy, car
|
|
|
31
33
|
children: [
|
|
32
34
|
/*#__PURE__*/ _jsx(Input, {
|
|
33
35
|
type: showPassword ? 'text' : 'password',
|
|
34
|
-
label:
|
|
36
|
+
label: t.newPasswordLabel,
|
|
35
37
|
value: password,
|
|
36
38
|
onValueChange: setPassword,
|
|
37
39
|
isRequired: true,
|
|
@@ -53,11 +55,11 @@ export default function SetPasswordPage({ redirectTo = '/', logo, poweredBy, car
|
|
|
53
55
|
}),
|
|
54
56
|
password.length > 0 && !strength.isValid && /*#__PURE__*/ _jsx("p", {
|
|
55
57
|
className: "text-xs text-gray-500",
|
|
56
|
-
children:
|
|
58
|
+
children: t.passwordRequirements
|
|
57
59
|
}),
|
|
58
60
|
/*#__PURE__*/ _jsx(Input, {
|
|
59
61
|
type: showPassword ? 'text' : 'password',
|
|
60
|
-
label:
|
|
62
|
+
label: t.confirmPasswordLabel,
|
|
61
63
|
value: confirmPassword,
|
|
62
64
|
onValueChange: setConfirmPassword,
|
|
63
65
|
isRequired: true
|
|
@@ -66,7 +68,7 @@ export default function SetPasswordPage({ redirectTo = '/', logo, poweredBy, car
|
|
|
66
68
|
type: "submit",
|
|
67
69
|
variant: "primary",
|
|
68
70
|
isLoading: isLoading,
|
|
69
|
-
children:
|
|
71
|
+
children: t.setPassword
|
|
70
72
|
})
|
|
71
73
|
]
|
|
72
74
|
})
|
|
@@ -7,4 +7,4 @@ export interface SignupPageHeroProps extends AuthLayoutConfig {
|
|
|
7
7
|
showGoogleOAuth?: boolean;
|
|
8
8
|
loginUrl?: string;
|
|
9
9
|
}
|
|
10
|
-
export default function SignupPageHero({ onSignup, showGoogleOAuth, loginUrl, logo, poweredBy, cardClassName, backgroundClass }: SignupPageHeroProps): import("react/jsx-runtime").JSX.Element;
|
|
10
|
+
export default function SignupPageHero({ onSignup, showGoogleOAuth, loginUrl, logo, poweredBy, cardClassName, backgroundClass, locale, messages }: SignupPageHeroProps): import("react/jsx-runtime").JSX.Element;
|