@main12/auth-login 0.1.0 → 0.1.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.
- package/dist/components/pages/ForgotPasswordPage.d.ts +1 -1
- package/dist/components/pages/ForgotPasswordPage.js +9 -42
- package/dist/components/pages/ForgotPasswordPageHero.d.ts +5 -0
- package/dist/components/pages/ForgotPasswordPageHero.js +69 -0
- package/dist/components/pages/ForgotPasswordPageTailwind.d.ts +5 -0
- package/dist/components/pages/ForgotPasswordPageTailwind.js +45 -0
- package/dist/components/pages/LoginPage.js +8 -218
- package/dist/components/pages/LoginPageHero.d.ts +11 -0
- package/dist/components/pages/LoginPageHero.js +298 -0
- package/dist/components/pages/LoginPageTailwind.d.ts +11 -0
- package/dist/components/pages/LoginPageTailwind.js +222 -0
- package/dist/components/pages/SetPasswordPage.d.ts +1 -1
- package/dist/components/pages/SetPasswordPage.js +9 -71
- package/dist/components/pages/SetPasswordPageHero.d.ts +5 -0
- package/dist/components/pages/SetPasswordPageHero.js +93 -0
- package/dist/components/pages/SetPasswordPageTailwind.d.ts +5 -0
- package/dist/components/pages/SetPasswordPageTailwind.js +74 -0
- package/dist/components/pages/SignupPage.d.ts +1 -1
- package/dist/components/pages/SignupPage.js +9 -126
- package/dist/components/pages/SignupPageHero.d.ts +10 -0
- package/dist/components/pages/SignupPageHero.js +150 -0
- package/dist/components/pages/SignupPageTailwind.d.ts +10 -0
- package/dist/components/pages/SignupPageTailwind.js +129 -0
- package/dist/components/pages/VerifyOtpPage.js +8 -83
- package/dist/components/pages/VerifyOtpPageHero.d.ts +5 -0
- package/dist/components/pages/VerifyOtpPageHero.js +104 -0
- package/dist/components/pages/VerifyOtpPageTailwind.d.ts +5 -0
- package/dist/components/pages/VerifyOtpPageTailwind.js +87 -0
- package/dist/config.d.ts +8 -0
- package/dist/config.js +6 -0
- package/dist/index.d.ts +4 -4
- package/dist/index.js +5 -1
- package/package.json +5 -2
|
@@ -1,87 +1,12 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import { jsx as _jsx
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import { useVerifyOtpFlow } from '../../auth/application/hooks/useVerifyOtpFlow.js';
|
|
7
|
-
import { AuthLayout } from '../AuthLayout.js';
|
|
8
|
-
function VerifyOtpContent({ loginUrl = '/login', logo, poweredBy, cardClassName, backgroundClass }) {
|
|
9
|
-
const searchParams = useSearchParams();
|
|
10
|
-
const email = searchParams.get('email') || '';
|
|
11
|
-
const purpose = searchParams.get('purpose') || 'login';
|
|
12
|
-
const redirectTo = searchParams.get('redirect') || '/';
|
|
13
|
-
const { otp, error, isLoading, isResending, resendCooldown, setOtp, handleSubmit, handleResendCode } = useVerifyOtpFlow({
|
|
14
|
-
email,
|
|
15
|
-
purpose,
|
|
16
|
-
redirectTo
|
|
17
|
-
});
|
|
18
|
-
if (!email) return null;
|
|
19
|
-
const isPasswordReset = purpose === 'password-reset';
|
|
20
|
-
return /*#__PURE__*/ _jsx(AuthLayout, {
|
|
21
|
-
logo: logo,
|
|
22
|
-
title: isPasswordReset ? 'Reset Password' : 'Check Your Email',
|
|
23
|
-
subtitle: isPasswordReset ? 'Enter the code to reset your password' : 'We sent a 6-digit code to',
|
|
24
|
-
poweredBy: poweredBy,
|
|
25
|
-
cardClassName: cardClassName,
|
|
26
|
-
backgroundClass: backgroundClass,
|
|
27
|
-
footer: /*#__PURE__*/ _jsx("a", {
|
|
28
|
-
href: loginUrl,
|
|
29
|
-
className: "text-sm text-gray-600 hover:text-gray-900 flex items-center gap-1",
|
|
30
|
-
children: "← Back to Login"
|
|
31
|
-
}),
|
|
32
|
-
children: /*#__PURE__*/ _jsxs("div", {
|
|
33
|
-
className: "flex flex-col items-center gap-4",
|
|
34
|
-
children: [
|
|
35
|
-
/*#__PURE__*/ _jsx("p", {
|
|
36
|
-
className: "text-gray-700 text-sm font-medium",
|
|
37
|
-
children: email
|
|
38
|
-
}),
|
|
39
|
-
/*#__PURE__*/ _jsx(OtpInput, {
|
|
40
|
-
value: otp,
|
|
41
|
-
onValueChange: setOtp,
|
|
42
|
-
isDisabled: isLoading,
|
|
43
|
-
autoFocus: true
|
|
44
|
-
}),
|
|
45
|
-
error && /*#__PURE__*/ _jsx("div", {
|
|
46
|
-
className: "w-full bg-red-50 text-red-600 border border-red-200 rounded-lg p-3 text-sm animate-[fadeIn_0.2s_ease-out]",
|
|
47
|
-
children: error
|
|
48
|
-
}),
|
|
49
|
-
/*#__PURE__*/ _jsx(Button, {
|
|
50
|
-
variant: "primary",
|
|
51
|
-
isLoading: isLoading,
|
|
52
|
-
isDisabled: otp.length !== 6,
|
|
53
|
-
onPress: handleSubmit,
|
|
54
|
-
children: "Verify"
|
|
55
|
-
}),
|
|
56
|
-
/*#__PURE__*/ _jsxs("div", {
|
|
57
|
-
className: "text-center",
|
|
58
|
-
children: [
|
|
59
|
-
/*#__PURE__*/ _jsx("p", {
|
|
60
|
-
className: "text-gray-600 text-sm mb-2",
|
|
61
|
-
children: "Didn't receive a code?"
|
|
62
|
-
}),
|
|
63
|
-
/*#__PURE__*/ _jsx("button", {
|
|
64
|
-
onClick: handleResendCode,
|
|
65
|
-
disabled: isResending || resendCooldown > 0,
|
|
66
|
-
className: "text-[#0071e3] font-medium text-sm hover:underline disabled:opacity-50 disabled:cursor-not-allowed",
|
|
67
|
-
children: isResending ? 'Sending...' : resendCooldown > 0 ? `Resend in ${resendCooldown}s` : 'Resend Code'
|
|
68
|
-
})
|
|
69
|
-
]
|
|
70
|
-
})
|
|
71
|
-
]
|
|
72
|
-
})
|
|
73
|
-
});
|
|
74
|
-
}
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { pluginConfig } from '../../config.js';
|
|
4
|
+
import VerifyOtpPageTailwind from './VerifyOtpPageTailwind.js';
|
|
5
|
+
import VerifyOtpPageHero from './VerifyOtpPageHero.js';
|
|
75
6
|
export default function VerifyOtpPage(props) {
|
|
76
|
-
return /*#__PURE__*/ _jsx(
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
size: "lg"
|
|
81
|
-
})
|
|
82
|
-
}),
|
|
83
|
-
children: /*#__PURE__*/ _jsx(VerifyOtpContent, {
|
|
84
|
-
...props
|
|
85
|
-
})
|
|
7
|
+
return pluginConfig.style === 'hero-ui' ? /*#__PURE__*/ _jsx(VerifyOtpPageHero, {
|
|
8
|
+
...props
|
|
9
|
+
}) : /*#__PURE__*/ _jsx(VerifyOtpPageTailwind, {
|
|
10
|
+
...props
|
|
86
11
|
});
|
|
87
12
|
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import React, { Suspense } from 'react';
|
|
4
|
+
import { useSearchParams } from 'next/navigation';
|
|
5
|
+
import { Button, InputOtp, Spinner as HSpinner } from '@heroui/react';
|
|
6
|
+
import { Icon } from '@iconify/react';
|
|
7
|
+
import { motion } from 'framer-motion';
|
|
8
|
+
import { useVerifyOtpFlow } from '../../auth/application/hooks/useVerifyOtpFlow.js';
|
|
9
|
+
import { AuthLayout } from '../AuthLayout.js';
|
|
10
|
+
function VerifyOtpHeroContent({ loginUrl = '/login', logo, poweredBy, cardClassName, backgroundClass }) {
|
|
11
|
+
const searchParams = useSearchParams();
|
|
12
|
+
const email = searchParams.get('email') || '';
|
|
13
|
+
const purpose = searchParams.get('purpose') || 'login';
|
|
14
|
+
const redirectTo = searchParams.get('redirect') || '/';
|
|
15
|
+
const { otp, error, isLoading, isResending, resendCooldown, setOtp, handleSubmit, handleResendCode } = useVerifyOtpFlow({
|
|
16
|
+
email,
|
|
17
|
+
purpose,
|
|
18
|
+
redirectTo
|
|
19
|
+
});
|
|
20
|
+
if (!email) return null;
|
|
21
|
+
return /*#__PURE__*/ _jsx(AuthLayout, {
|
|
22
|
+
logo: logo,
|
|
23
|
+
title: purpose === 'password-reset' ? 'Reset Password' : 'Check Your Email',
|
|
24
|
+
subtitle: purpose === 'password-reset' ? 'Enter the code to reset your password' : 'We sent a 6-digit code to',
|
|
25
|
+
poweredBy: poweredBy,
|
|
26
|
+
cardClassName: cardClassName,
|
|
27
|
+
backgroundClass: backgroundClass,
|
|
28
|
+
footer: /*#__PURE__*/ _jsxs("a", {
|
|
29
|
+
href: loginUrl,
|
|
30
|
+
className: "text-sm text-gray-600 hover:text-gray-900 flex items-center gap-1",
|
|
31
|
+
children: [
|
|
32
|
+
/*#__PURE__*/ _jsx(Icon, {
|
|
33
|
+
icon: "lucide:arrow-left",
|
|
34
|
+
width: 16
|
|
35
|
+
}),
|
|
36
|
+
"Back to Login"
|
|
37
|
+
]
|
|
38
|
+
}),
|
|
39
|
+
children: /*#__PURE__*/ _jsxs("div", {
|
|
40
|
+
className: "flex flex-col items-center gap-4",
|
|
41
|
+
children: [
|
|
42
|
+
/*#__PURE__*/ _jsx("p", {
|
|
43
|
+
className: "text-gray-700 text-sm font-medium",
|
|
44
|
+
children: email
|
|
45
|
+
}),
|
|
46
|
+
/*#__PURE__*/ _jsx(InputOtp, {
|
|
47
|
+
length: 6,
|
|
48
|
+
value: otp,
|
|
49
|
+
onValueChange: setOtp,
|
|
50
|
+
isDisabled: isLoading,
|
|
51
|
+
autoFocus: true
|
|
52
|
+
}),
|
|
53
|
+
error && /*#__PURE__*/ _jsx(motion.div, {
|
|
54
|
+
className: "w-full bg-red-50 text-red-600 border border-red-200 rounded-lg p-3 text-sm",
|
|
55
|
+
initial: {
|
|
56
|
+
opacity: 0
|
|
57
|
+
},
|
|
58
|
+
animate: {
|
|
59
|
+
opacity: 1
|
|
60
|
+
},
|
|
61
|
+
children: error
|
|
62
|
+
}),
|
|
63
|
+
/*#__PURE__*/ _jsx(Button, {
|
|
64
|
+
fullWidth: true,
|
|
65
|
+
size: "lg",
|
|
66
|
+
color: "primary",
|
|
67
|
+
isLoading: isLoading,
|
|
68
|
+
isDisabled: otp.length !== 6,
|
|
69
|
+
onPress: handleSubmit,
|
|
70
|
+
className: "h-12 font-semibold",
|
|
71
|
+
children: "Verify"
|
|
72
|
+
}),
|
|
73
|
+
/*#__PURE__*/ _jsxs("div", {
|
|
74
|
+
className: "text-center",
|
|
75
|
+
children: [
|
|
76
|
+
/*#__PURE__*/ _jsx("p", {
|
|
77
|
+
className: "text-gray-600 text-sm mb-2",
|
|
78
|
+
children: "Didn't receive a code?"
|
|
79
|
+
}),
|
|
80
|
+
/*#__PURE__*/ _jsx("button", {
|
|
81
|
+
onClick: handleResendCode,
|
|
82
|
+
disabled: isResending || resendCooldown > 0,
|
|
83
|
+
className: "text-primary font-medium text-sm hover:underline disabled:opacity-50",
|
|
84
|
+
children: isResending ? 'Sending...' : resendCooldown > 0 ? `Resend in ${resendCooldown}s` : 'Resend Code'
|
|
85
|
+
})
|
|
86
|
+
]
|
|
87
|
+
})
|
|
88
|
+
]
|
|
89
|
+
})
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
export default function VerifyOtpPageHero(props) {
|
|
93
|
+
return /*#__PURE__*/ _jsx(Suspense, {
|
|
94
|
+
fallback: /*#__PURE__*/ _jsx("div", {
|
|
95
|
+
className: "min-h-screen flex items-center justify-center",
|
|
96
|
+
children: /*#__PURE__*/ _jsx(HSpinner, {
|
|
97
|
+
size: "lg"
|
|
98
|
+
})
|
|
99
|
+
}),
|
|
100
|
+
children: /*#__PURE__*/ _jsx(VerifyOtpHeroContent, {
|
|
101
|
+
...props
|
|
102
|
+
})
|
|
103
|
+
});
|
|
104
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import React, { Suspense } from 'react';
|
|
4
|
+
import { useSearchParams } from 'next/navigation';
|
|
5
|
+
import { Button, OtpInput, Spinner } from '../ui/index.js';
|
|
6
|
+
import { useVerifyOtpFlow } from '../../auth/application/hooks/useVerifyOtpFlow.js';
|
|
7
|
+
import { AuthLayout } from '../AuthLayout.js';
|
|
8
|
+
function VerifyOtpContent({ loginUrl = '/login', logo, poweredBy, cardClassName, backgroundClass }) {
|
|
9
|
+
const searchParams = useSearchParams();
|
|
10
|
+
const email = searchParams.get('email') || '';
|
|
11
|
+
const purpose = searchParams.get('purpose') || 'login';
|
|
12
|
+
const redirectTo = searchParams.get('redirect') || '/';
|
|
13
|
+
const { otp, error, isLoading, isResending, resendCooldown, setOtp, handleSubmit, handleResendCode } = useVerifyOtpFlow({
|
|
14
|
+
email,
|
|
15
|
+
purpose,
|
|
16
|
+
redirectTo
|
|
17
|
+
});
|
|
18
|
+
if (!email) return null;
|
|
19
|
+
const isPasswordReset = purpose === 'password-reset';
|
|
20
|
+
return /*#__PURE__*/ _jsx(AuthLayout, {
|
|
21
|
+
logo: logo,
|
|
22
|
+
title: isPasswordReset ? 'Reset Password' : 'Check Your Email',
|
|
23
|
+
subtitle: isPasswordReset ? 'Enter the code to reset your password' : 'We sent a 6-digit code to',
|
|
24
|
+
poweredBy: poweredBy,
|
|
25
|
+
cardClassName: cardClassName,
|
|
26
|
+
backgroundClass: backgroundClass,
|
|
27
|
+
footer: /*#__PURE__*/ _jsx("a", {
|
|
28
|
+
href: loginUrl,
|
|
29
|
+
className: "text-sm text-gray-600 hover:text-gray-900 flex items-center gap-1",
|
|
30
|
+
children: "← Back to Login"
|
|
31
|
+
}),
|
|
32
|
+
children: /*#__PURE__*/ _jsxs("div", {
|
|
33
|
+
className: "flex flex-col items-center gap-4",
|
|
34
|
+
children: [
|
|
35
|
+
/*#__PURE__*/ _jsx("p", {
|
|
36
|
+
className: "text-gray-700 text-sm font-medium",
|
|
37
|
+
children: email
|
|
38
|
+
}),
|
|
39
|
+
/*#__PURE__*/ _jsx(OtpInput, {
|
|
40
|
+
value: otp,
|
|
41
|
+
onValueChange: setOtp,
|
|
42
|
+
isDisabled: isLoading,
|
|
43
|
+
autoFocus: true
|
|
44
|
+
}),
|
|
45
|
+
error && /*#__PURE__*/ _jsx("div", {
|
|
46
|
+
className: "w-full bg-red-50 text-red-600 border border-red-200 rounded-lg p-3 text-sm animate-[fadeIn_0.2s_ease-out]",
|
|
47
|
+
children: error
|
|
48
|
+
}),
|
|
49
|
+
/*#__PURE__*/ _jsx(Button, {
|
|
50
|
+
variant: "primary",
|
|
51
|
+
isLoading: isLoading,
|
|
52
|
+
isDisabled: otp.length !== 6,
|
|
53
|
+
onPress: handleSubmit,
|
|
54
|
+
children: "Verify"
|
|
55
|
+
}),
|
|
56
|
+
/*#__PURE__*/ _jsxs("div", {
|
|
57
|
+
className: "text-center",
|
|
58
|
+
children: [
|
|
59
|
+
/*#__PURE__*/ _jsx("p", {
|
|
60
|
+
className: "text-gray-600 text-sm mb-2",
|
|
61
|
+
children: "Didn't receive a code?"
|
|
62
|
+
}),
|
|
63
|
+
/*#__PURE__*/ _jsx("button", {
|
|
64
|
+
onClick: handleResendCode,
|
|
65
|
+
disabled: isResending || resendCooldown > 0,
|
|
66
|
+
className: "text-[#0071e3] font-medium text-sm hover:underline disabled:opacity-50 disabled:cursor-not-allowed",
|
|
67
|
+
children: isResending ? 'Sending...' : resendCooldown > 0 ? `Resend in ${resendCooldown}s` : 'Resend Code'
|
|
68
|
+
})
|
|
69
|
+
]
|
|
70
|
+
})
|
|
71
|
+
]
|
|
72
|
+
})
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
export default function VerifyOtpPage(props) {
|
|
76
|
+
return /*#__PURE__*/ _jsx(Suspense, {
|
|
77
|
+
fallback: /*#__PURE__*/ _jsx("div", {
|
|
78
|
+
className: "min-h-screen flex items-center justify-center",
|
|
79
|
+
children: /*#__PURE__*/ _jsx(Spinner, {
|
|
80
|
+
size: "lg"
|
|
81
|
+
})
|
|
82
|
+
}),
|
|
83
|
+
children: /*#__PURE__*/ _jsx(VerifyOtpContent, {
|
|
84
|
+
...props
|
|
85
|
+
})
|
|
86
|
+
});
|
|
87
|
+
}
|
package/dist/config.d.ts
ADDED
package/dist/config.js
ADDED
package/dist/index.d.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import type { Config } from 'payload';
|
|
2
|
+
import { pluginConfig, type AuthStyle } from './config.js';
|
|
2
3
|
export interface AuthLoginPluginOptions {
|
|
3
|
-
/** Enable/disable the plugin */
|
|
4
4
|
enabled?: boolean;
|
|
5
|
-
/** Project name used in emails */
|
|
6
5
|
projectName?: string;
|
|
7
|
-
/** Contact email used in email footers */
|
|
8
6
|
contactEmail?: string;
|
|
9
|
-
/** Domain for links in emails */
|
|
10
7
|
domain?: string;
|
|
8
|
+
/** UI style for auth pages: 'tailwind' (default) or 'hero-ui' */
|
|
9
|
+
style?: AuthStyle;
|
|
11
10
|
}
|
|
12
11
|
export declare const authLoginPlugin: (options?: AuthLoginPluginOptions) => (config: Config) => Config;
|
|
12
|
+
export { pluginConfig };
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { authEndpoints } from './endpoints/authEndpoints.js';
|
|
2
|
+
import { pluginConfig } from './config.js';
|
|
2
3
|
export const authLoginPlugin = (options = {})=>(config)=>{
|
|
3
4
|
if (options.enabled === false) return config;
|
|
5
|
+
// Set global style config — all page components read this at render time
|
|
6
|
+
pluginConfig.style = options.style || 'tailwind';
|
|
4
7
|
// Register auth API endpoints
|
|
5
8
|
config.endpoints = [
|
|
6
9
|
...config.endpoints || [],
|
|
@@ -10,7 +13,8 @@ export const authLoginPlugin = (options = {})=>(config)=>{
|
|
|
10
13
|
const incomingOnInit = config.onInit;
|
|
11
14
|
config.onInit = async (payload)=>{
|
|
12
15
|
if (incomingOnInit) await incomingOnInit(payload);
|
|
13
|
-
payload.logger.info(`[auth-login]
|
|
16
|
+
payload.logger.info(`[auth-login] Initialized (style: ${pluginConfig.style}) for ${options.projectName || 'project'}`);
|
|
14
17
|
};
|
|
15
18
|
return config;
|
|
16
19
|
};
|
|
20
|
+
export { pluginConfig };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@main12/auth-login",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Reusable Payload CMS auth plugin — login, signup, OTP, forgot password, branded emails, Powered by Main12",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -42,6 +42,8 @@
|
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"@eslint/eslintrc": "^3.2.0",
|
|
45
|
+
"@heroui/react": "^2.8.10",
|
|
46
|
+
"@iconify/react": "^6.0.2",
|
|
45
47
|
"@payloadcms/db-sqlite": "3.82.1",
|
|
46
48
|
"@payloadcms/next": "3.82.1",
|
|
47
49
|
"@payloadcms/richtext-lexical": "3.82.1",
|
|
@@ -54,6 +56,7 @@
|
|
|
54
56
|
"copyfiles": "2.4.1",
|
|
55
57
|
"cross-env": "10.1.0",
|
|
56
58
|
"eslint": "^9.23.0",
|
|
59
|
+
"framer-motion": "^12.43.0",
|
|
57
60
|
"next": "16.2.7",
|
|
58
61
|
"payload": "3.82.1",
|
|
59
62
|
"react": "19.2.6",
|
|
@@ -112,4 +115,4 @@
|
|
|
112
115
|
]
|
|
113
116
|
},
|
|
114
117
|
"registry": "https://registry.npmjs.org/"
|
|
115
|
-
}
|
|
118
|
+
}
|