@main12/auth-login 0.1.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.
Files changed (59) hide show
  1. package/README.md +218 -0
  2. package/dist/auth/application/hooks/useForgotPasswordFlow.d.ts +10 -0
  3. package/dist/auth/application/hooks/useForgotPasswordFlow.js +45 -0
  4. package/dist/auth/application/hooks/useLoginFlow.d.ts +30 -0
  5. package/dist/auth/application/hooks/useLoginFlow.js +105 -0
  6. package/dist/auth/application/hooks/useSetPasswordFlow.d.ts +18 -0
  7. package/dist/auth/application/hooks/useSetPasswordFlow.js +59 -0
  8. package/dist/auth/application/hooks/useVerifyOtpFlow.d.ts +18 -0
  9. package/dist/auth/application/hooks/useVerifyOtpFlow.js +84 -0
  10. package/dist/auth/application/services/authService.d.ts +26 -0
  11. package/dist/auth/application/services/authService.js +90 -0
  12. package/dist/auth/domain/otp.d.ts +25 -0
  13. package/dist/auth/domain/otp.js +41 -0
  14. package/dist/auth/domain/passwordRules.d.ts +12 -0
  15. package/dist/auth/domain/passwordRules.js +34 -0
  16. package/dist/auth/domain/types.d.ts +35 -0
  17. package/dist/auth/domain/types.js +2 -0
  18. package/dist/components/AuthLayout.d.ts +20 -0
  19. package/dist/components/AuthLayout.js +49 -0
  20. package/dist/components/PoweredBy.d.ts +10 -0
  21. package/dist/components/PoweredBy.js +50 -0
  22. package/dist/components/email/baseTemplate.d.ts +13 -0
  23. package/dist/components/email/baseTemplate.js +69 -0
  24. package/dist/components/email/constants.d.ts +26 -0
  25. package/dist/components/email/constants.js +30 -0
  26. package/dist/components/email/index.d.ts +7 -0
  27. package/dist/components/email/index.js +7 -0
  28. package/dist/components/email/templates/otp.d.ts +16 -0
  29. package/dist/components/email/templates/otp.js +38 -0
  30. package/dist/components/email/templates/passwordChanged.d.ts +15 -0
  31. package/dist/components/email/templates/passwordChanged.js +33 -0
  32. package/dist/components/email/templates/passwordReset.d.ts +15 -0
  33. package/dist/components/email/templates/passwordReset.js +36 -0
  34. package/dist/components/email/templates/welcome.d.ts +16 -0
  35. package/dist/components/email/templates/welcome.js +38 -0
  36. package/dist/components/email/translations.d.ts +45 -0
  37. package/dist/components/email/translations.js +88 -0
  38. package/dist/components/pages/ForgotPasswordPage.d.ts +5 -0
  39. package/dist/components/pages/ForgotPasswordPage.js +45 -0
  40. package/dist/components/pages/LoginPage.d.ts +11 -0
  41. package/dist/components/pages/LoginPage.js +222 -0
  42. package/dist/components/pages/SetPasswordPage.d.ts +5 -0
  43. package/dist/components/pages/SetPasswordPage.js +74 -0
  44. package/dist/components/pages/SignupPage.d.ts +10 -0
  45. package/dist/components/pages/SignupPage.js +129 -0
  46. package/dist/components/pages/VerifyOtpPage.d.ts +5 -0
  47. package/dist/components/pages/VerifyOtpPage.js +87 -0
  48. package/dist/components/ui/index.d.ts +57 -0
  49. package/dist/components/ui/index.js +121 -0
  50. package/dist/css.d.js +0 -0
  51. package/dist/endpoints/authEndpoints.d.ts +22 -0
  52. package/dist/endpoints/authEndpoints.js +422 -0
  53. package/dist/exports/client.d.ts +24 -0
  54. package/dist/exports/client.js +22 -0
  55. package/dist/exports/rsc.d.ts +6 -0
  56. package/dist/exports/rsc.js +5 -0
  57. package/dist/index.d.ts +12 -0
  58. package/dist/index.js +16 -0
  59. package/package.json +115 -0
@@ -0,0 +1,129 @@
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, Divider } from '../ui/index.js';
5
+ import { AuthLayout } from '../AuthLayout.js';
6
+ export default function SignupPage({ onSignup, showGoogleOAuth = true, loginUrl = '/login', logo, poweredBy, cardClassName, backgroundClass }) {
7
+ const [name, setName] = React.useState('');
8
+ const [email, setEmail] = React.useState('');
9
+ const [isLoading, setIsLoading] = React.useState(false);
10
+ const [error, setError] = React.useState(null);
11
+ const handleSubmit = async (e)=>{
12
+ e.preventDefault();
13
+ setIsLoading(true);
14
+ setError(null);
15
+ try {
16
+ await onSignup({
17
+ name,
18
+ email
19
+ });
20
+ window.location.href = `/verify-otp?email=${encodeURIComponent(email)}&purpose=signup`;
21
+ } catch (err) {
22
+ setError(err.message || 'Signup failed');
23
+ } finally{
24
+ setIsLoading(false);
25
+ }
26
+ };
27
+ return /*#__PURE__*/ _jsxs(AuthLayout, {
28
+ logo: logo,
29
+ title: "Create Account",
30
+ subtitle: "Enter your details to get started",
31
+ poweredBy: poweredBy,
32
+ cardClassName: cardClassName,
33
+ backgroundClass: backgroundClass,
34
+ footer: /*#__PURE__*/ _jsxs("p", {
35
+ className: "text-center text-gray-600 text-sm",
36
+ children: [
37
+ "Already have an account?",
38
+ ' ',
39
+ /*#__PURE__*/ _jsx("a", {
40
+ href: loginUrl,
41
+ className: "text-gray-900 font-medium hover:underline",
42
+ children: "Sign in"
43
+ })
44
+ ]
45
+ }),
46
+ children: [
47
+ showGoogleOAuth && /*#__PURE__*/ _jsxs(_Fragment, {
48
+ children: [
49
+ /*#__PURE__*/ _jsxs(Button, {
50
+ fullWidth: true,
51
+ variant: "bordered",
52
+ size: "lg",
53
+ className: "mb-4",
54
+ children: [
55
+ /*#__PURE__*/ _jsx("span", {
56
+ className: "text-lg",
57
+ children: "G"
58
+ }),
59
+ " Continue with Google"
60
+ ]
61
+ }),
62
+ /*#__PURE__*/ _jsxs("div", {
63
+ className: "flex items-center gap-4 my-4",
64
+ children: [
65
+ /*#__PURE__*/ _jsx(Divider, {
66
+ className: "flex-1"
67
+ }),
68
+ /*#__PURE__*/ _jsx("span", {
69
+ className: "text-gray-500 text-sm",
70
+ children: "or"
71
+ }),
72
+ /*#__PURE__*/ _jsx(Divider, {
73
+ className: "flex-1"
74
+ })
75
+ ]
76
+ })
77
+ ]
78
+ }),
79
+ /*#__PURE__*/ _jsxs("form", {
80
+ onSubmit: handleSubmit,
81
+ className: "space-y-4",
82
+ children: [
83
+ error && /*#__PURE__*/ _jsx("div", {
84
+ className: "bg-red-50 text-red-600 border border-red-200 rounded-lg p-3 text-sm animate-[fadeIn_0.2s_ease-out]",
85
+ children: error
86
+ }),
87
+ /*#__PURE__*/ _jsx(Input, {
88
+ label: "Full Name",
89
+ value: name,
90
+ onValueChange: setName,
91
+ isRequired: true
92
+ }),
93
+ /*#__PURE__*/ _jsx(Input, {
94
+ type: "email",
95
+ label: "Email",
96
+ value: email,
97
+ onValueChange: setEmail,
98
+ isRequired: true
99
+ }),
100
+ /*#__PURE__*/ _jsxs("p", {
101
+ className: "text-xs text-gray-600 text-center",
102
+ children: [
103
+ "By signing up, you agree to our",
104
+ ' ',
105
+ /*#__PURE__*/ _jsx("a", {
106
+ href: "/terms",
107
+ className: "text-gray-900 hover:underline",
108
+ children: "Terms of Service"
109
+ }),
110
+ " and",
111
+ ' ',
112
+ /*#__PURE__*/ _jsx("a", {
113
+ href: "/privacy",
114
+ className: "text-gray-900 hover:underline",
115
+ children: "Privacy Policy"
116
+ })
117
+ ]
118
+ }),
119
+ /*#__PURE__*/ _jsx(Button, {
120
+ type: "submit",
121
+ variant: "primary",
122
+ isLoading: isLoading,
123
+ children: "Create Account"
124
+ })
125
+ ]
126
+ })
127
+ ]
128
+ });
129
+ }
@@ -0,0 +1,5 @@
1
+ import type { AuthLayoutConfig } from '../AuthLayout.js';
2
+ export interface VerifyOtpPageProps extends AuthLayoutConfig {
3
+ loginUrl?: string;
4
+ }
5
+ export default function VerifyOtpPage(props: VerifyOtpPageProps): import("react/jsx-runtime").JSX.Element;
@@ -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
+ }
@@ -0,0 +1,57 @@
1
+ import React from 'react';
2
+ interface ButtonProps {
3
+ children: React.ReactNode;
4
+ type?: 'button' | 'submit';
5
+ fullWidth?: boolean;
6
+ size?: 'sm' | 'lg';
7
+ isLoading?: boolean;
8
+ isDisabled?: boolean;
9
+ onPress?: () => void;
10
+ onClick?: () => void;
11
+ variant?: 'primary' | 'bordered' | 'ghost' | 'tertiary';
12
+ className?: string;
13
+ }
14
+ export declare const Button: React.FC<ButtonProps>;
15
+ interface InputProps {
16
+ type?: string;
17
+ label?: string;
18
+ value: string;
19
+ onChange?: (e: React.ChangeEvent<HTMLInputElement>) => void;
20
+ onValueChange?: (value: string) => void;
21
+ isRequired?: boolean;
22
+ isDisabled?: boolean;
23
+ autoFocus?: boolean;
24
+ autoComplete?: string;
25
+ placeholder?: string;
26
+ className?: string;
27
+ name?: string;
28
+ }
29
+ export declare const Input: React.FC<InputProps>;
30
+ interface CardProps {
31
+ children: React.ReactNode;
32
+ className?: string;
33
+ }
34
+ export declare const Card: React.FC<CardProps>;
35
+ export declare const CardHeader: React.FC<CardProps>;
36
+ export declare const CardContent: React.FC<CardProps>;
37
+ export declare const CardFooter: React.FC<CardProps>;
38
+ export declare const CardTitle: React.FC<CardProps>;
39
+ export declare const CardDescription: React.FC<CardProps>;
40
+ export declare const Divider: React.FC<{
41
+ className?: string;
42
+ }>;
43
+ interface SpinnerProps {
44
+ size?: 'sm' | 'lg';
45
+ className?: string;
46
+ }
47
+ export declare const Spinner: React.FC<SpinnerProps>;
48
+ interface OtpInputProps {
49
+ length?: number;
50
+ value: string;
51
+ onChange?: (value: string) => void;
52
+ onValueChange?: (value: string) => void;
53
+ isDisabled?: boolean;
54
+ autoFocus?: boolean;
55
+ }
56
+ export declare const OtpInput: React.FC<OtpInputProps>;
57
+ export {};
@@ -0,0 +1,121 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import React from 'react';
3
+ const variantClasses = {
4
+ primary: 'bg-[#D5E855] text-gray-900 hover:bg-[#C9DC4A] font-semibold',
5
+ bordered: 'border border-gray-300 text-gray-700 hover:bg-gray-50 bg-white',
6
+ ghost: 'text-gray-600 hover:text-gray-900 bg-transparent',
7
+ tertiary: 'text-gray-600 hover:text-gray-900 bg-transparent underline'
8
+ };
9
+ export const Button = ({ children, type = 'button', fullWidth = true, size = 'lg', isLoading, isDisabled, onPress, onClick, variant = 'primary', className = '' })=>/*#__PURE__*/ _jsxs("button", {
10
+ type: type,
11
+ disabled: isDisabled || isLoading,
12
+ onClick: onPress || onClick,
13
+ className: `
14
+ ${fullWidth ? 'w-full' : ''}
15
+ ${size === 'lg' ? 'h-12 px-6 text-base' : 'h-8 px-3 text-sm'}
16
+ rounded-full transition-all duration-200 flex items-center justify-center gap-2
17
+ disabled:opacity-50 disabled:cursor-not-allowed
18
+ ${variantClasses[variant] || variantClasses.primary}
19
+ ${className}
20
+ `.trim(),
21
+ children: [
22
+ isLoading ? /*#__PURE__*/ _jsx(Spinner, {
23
+ size: "sm"
24
+ }) : null,
25
+ children
26
+ ]
27
+ });
28
+ export const Input = ({ type = 'text', label, value, onChange, onValueChange, isRequired, isDisabled, autoFocus, autoComplete, placeholder, className = '', name })=>/*#__PURE__*/ _jsxs("div", {
29
+ className: "w-full",
30
+ children: [
31
+ label && /*#__PURE__*/ _jsxs("label", {
32
+ className: "block text-sm font-medium text-gray-600 mb-1",
33
+ children: [
34
+ label,
35
+ isRequired ? ' *' : ''
36
+ ]
37
+ }),
38
+ /*#__PURE__*/ _jsx("input", {
39
+ type: type,
40
+ value: value,
41
+ onChange: onChange || (onValueChange ? (e)=>onValueChange(e.target.value) : undefined),
42
+ required: isRequired,
43
+ disabled: isDisabled,
44
+ autoFocus: autoFocus,
45
+ autoComplete: autoComplete,
46
+ placeholder: placeholder,
47
+ name: name,
48
+ className: `w-full h-12 px-4 bg-white border border-gray-300 hover:border-gray-400 rounded-xl text-gray-900 text-base transition-colors outline-none focus:border-[#D5E855] focus:ring-2 focus:ring-[#D5E855]/30 ${className}`
49
+ })
50
+ ]
51
+ });
52
+ export const Card = ({ children, className = '' })=>/*#__PURE__*/ _jsx("div", {
53
+ className: `bg-white rounded-2xl shadow-2xl ${className}`,
54
+ children: children
55
+ });
56
+ export const CardHeader = ({ children, className = '' })=>/*#__PURE__*/ _jsx("div", {
57
+ className: `flex flex-col items-center gap-2 pt-8 pb-2 px-6 ${className}`,
58
+ children: children
59
+ });
60
+ export const CardContent = ({ children, className = '' })=>/*#__PURE__*/ _jsx("div", {
61
+ className: `px-6 pb-4 ${className}`,
62
+ children: children
63
+ });
64
+ export const CardFooter = ({ children, className = '' })=>/*#__PURE__*/ _jsx("div", {
65
+ className: `px-6 pb-6 flex justify-center ${className}`,
66
+ children: children
67
+ });
68
+ export const CardTitle = ({ children, className = '' })=>/*#__PURE__*/ _jsx("h1", {
69
+ className: `text-xl font-semibold text-gray-900 ${className}`,
70
+ children: children
71
+ });
72
+ export const CardDescription = ({ children, className = '' })=>/*#__PURE__*/ _jsx("p", {
73
+ className: `text-gray-600 text-sm text-center ${className}`,
74
+ children: children
75
+ });
76
+ export const Divider = ({ className = '' })=>/*#__PURE__*/ _jsx("hr", {
77
+ className: `border-0 h-px bg-gray-200 ${className}`
78
+ });
79
+ export const Spinner = ({ size = 'lg', className = '' })=>/*#__PURE__*/ _jsx("div", {
80
+ className: `inline-block animate-spin rounded-full border-2 border-current border-t-transparent ${size === 'lg' ? 'w-6 h-6' : 'w-4 h-4'} ${className}`,
81
+ role: "status",
82
+ children: /*#__PURE__*/ _jsx("span", {
83
+ className: "sr-only",
84
+ children: "Loading..."
85
+ })
86
+ });
87
+ export const OtpInput = ({ length = 6, value, onChange, onValueChange, isDisabled, autoFocus })=>{
88
+ const setValue = onChange || onValueChange || (()=>{});
89
+ const inputs = Array.from({
90
+ length
91
+ }, (_, i)=>i);
92
+ return /*#__PURE__*/ _jsx("div", {
93
+ className: "flex justify-center gap-2",
94
+ children: inputs.map((i)=>/*#__PURE__*/ _jsx("input", {
95
+ type: "text",
96
+ inputMode: "numeric",
97
+ maxLength: 1,
98
+ value: value[i] || '',
99
+ disabled: isDisabled,
100
+ autoFocus: autoFocus && i === 0,
101
+ onChange: (e)=>{
102
+ const char = e.target.value.replace(/[^0-9]/g, '').slice(0, 1);
103
+ const newVal = value.split('');
104
+ newVal[i] = char;
105
+ setValue(newVal.join(''));
106
+ // Auto-focus next
107
+ if (char && i < length - 1) {
108
+ const next = e.target.parentElement?.nextElementSibling?.querySelector('input');
109
+ next?.focus();
110
+ }
111
+ },
112
+ onKeyDown: (e)=>{
113
+ if (e.key === 'Backspace' && !value[i] && i > 0) {
114
+ const prev = e.target.parentElement?.previousElementSibling?.querySelector('input');
115
+ prev?.focus();
116
+ }
117
+ },
118
+ className: "w-12 h-14 text-center text-2xl font-semibold text-gray-900 border-2 border-gray-300 rounded-xl focus:border-[#D5E855] focus:ring-2 focus:ring-[#D5E855]/30 outline-none transition-all bg-white"
119
+ }, i))
120
+ });
121
+ };
package/dist/css.d.js ADDED
File without changes
@@ -0,0 +1,22 @@
1
+ import type { Endpoint } from 'payload';
2
+ /**
3
+ * POST /api/auth/check-email — Check if user exists and has password
4
+ */
5
+ export declare const checkEmailEndpoint: Endpoint;
6
+ /**
7
+ * POST /api/auth/otp/send — Generate OTP, store it, send email via Payload
8
+ */
9
+ export declare const sendOtpEndpoint: Endpoint;
10
+ /**
11
+ * POST /api/auth/otp/verify — Verify OTP and login the user
12
+ */
13
+ export declare const verifyOtpEndpoint: Endpoint;
14
+ /**
15
+ * POST /api/auth/set-password — Set/update password for authenticated user
16
+ */
17
+ export declare const setPasswordEndpoint: Endpoint;
18
+ /**
19
+ * POST /api/auth/signup — Create new user + send welcome email
20
+ */
21
+ export declare const signupEndpoint: Endpoint;
22
+ export declare const authEndpoints: Endpoint[];