@drawboard/authagonal-login 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.
@@ -0,0 +1,51 @@
1
+ {
2
+ "signIn": "Se connecter",
3
+ "email": "E-mail",
4
+ "password": "Mot de passe",
5
+ "emailPlaceholder": "you@example.com",
6
+ "passwordPlaceholder": "Entrez votre mot de passe",
7
+ "signingIn": "Connexion en cours...",
8
+ "forgotPassword": "Mot de passe oublié ?",
9
+ "ssoChecking": "Vérification des options de connexion...",
10
+ "ssoNotice": "Votre organisation utilise l'authentification unique",
11
+ "continueWithSso": "Continuer avec SSO",
12
+ "errorInvalidCredentials": "E-mail ou mot de passe invalide",
13
+ "errorLockedOut": "Compte verrouillé. Réessayez dans {{seconds}} secondes",
14
+ "errorEmailNotConfirmed": "Veuillez vérifier votre e-mail pour confirmer votre compte",
15
+ "errorSsoRequired": "L'authentification unique est requise pour ce compte",
16
+ "errorEmailRequired": "L'e-mail est requis",
17
+ "errorPasswordRequired": "Le mot de passe est requis",
18
+ "errorUnexpected": "Une erreur inattendue s'est produite. Veuillez réessayer.",
19
+ "resetYourPassword": "Réinitialiser votre mot de passe",
20
+ "resetSubtitle": "Entrez votre adresse e-mail et nous vous enverrons un lien pour réinitialiser votre mot de passe.",
21
+ "sending": "Envoi en cours...",
22
+ "sendResetLink": "Envoyer le lien de réinitialisation",
23
+ "backToSignIn": "Retour à la connexion",
24
+ "checkYourEmail": "Vérifiez votre e-mail",
25
+ "resetEmailSent": "Si un compte existe avec cette adresse e-mail, vous recevrez un lien de réinitialisation sous peu.",
26
+ "setNewPassword": "Définir un nouveau mot de passe",
27
+ "newPassword": "Nouveau mot de passe",
28
+ "newPasswordPlaceholder": "Entrez le nouveau mot de passe",
29
+ "confirmPassword": "Confirmer le mot de passe",
30
+ "confirmPasswordPlaceholder": "Confirmez le nouveau mot de passe",
31
+ "resetting": "Réinitialisation en cours...",
32
+ "resetPassword": "Réinitialiser le mot de passe",
33
+ "passwordResetSuccess": "Mot de passe réinitialisé avec succès",
34
+ "passwordResetSuccessMessage": "Votre mot de passe a été réinitialisé. Vous pouvez maintenant vous connecter avec votre nouveau mot de passe.",
35
+ "invalidLink": "Lien invalide",
36
+ "invalidOrExpiredLink": "Ce lien de réinitialisation est invalide ou a expiré.",
37
+ "requestNewResetLink": "Demander un nouveau lien de réinitialisation",
38
+ "passwordNotMeetRequirements": "Le mot de passe ne répond pas aux exigences",
39
+ "passwordsDoNotMatch": "Les mots de passe ne correspondent pas",
40
+ "passwordWeakError": "Le mot de passe ne répond pas aux exigences de robustesse",
41
+ "signInTitle": "Connexion — {{appName}}",
42
+ "ruleMinLength": "Au moins {{count}} caractères",
43
+ "ruleUppercase": "Lettre majuscule",
44
+ "ruleLowercase": "Lettre minuscule",
45
+ "ruleDigit": "Chiffre",
46
+ "ruleSpecialChar": "Caractère spécial",
47
+ "continueWith": "Continuer avec {{provider}}",
48
+ "or": "ou",
49
+ "signedInAs": "Connect\u00e9 en tant que {{name}}",
50
+ "signedInMessage": "Vous \u00eates d\u00e9j\u00e0 authentifi\u00e9."
51
+ }
@@ -0,0 +1,37 @@
1
+ import i18n from 'i18next';
2
+ import { initReactI18next } from 'react-i18next';
3
+ import LanguageDetector from 'i18next-browser-languagedetector';
4
+
5
+ import en from './en.json';
6
+ import zhHans from './zh-Hans.json';
7
+ import de from './de.json';
8
+ import fr from './fr.json';
9
+ import es from './es.json';
10
+ import vi from './vi.json';
11
+ import pt from './pt.json';
12
+
13
+ i18n
14
+ .use(LanguageDetector)
15
+ .use(initReactI18next)
16
+ .init({
17
+ resources: {
18
+ en: { translation: en },
19
+ 'zh-Hans': { translation: zhHans },
20
+ de: { translation: de },
21
+ fr: { translation: fr },
22
+ es: { translation: es },
23
+ vi: { translation: vi },
24
+ pt: { translation: pt },
25
+ },
26
+ fallbackLng: 'en',
27
+ interpolation: {
28
+ escapeValue: false,
29
+ },
30
+ detection: {
31
+ order: ['localStorage', 'querystring', 'navigator'],
32
+ lookupQuerystring: 'lng',
33
+ caches: ['localStorage'],
34
+ },
35
+ });
36
+
37
+ export default i18n;
@@ -0,0 +1,51 @@
1
+ {
2
+ "signIn": "Entrar",
3
+ "email": "E-mail",
4
+ "password": "Senha",
5
+ "emailPlaceholder": "voce@exemplo.com",
6
+ "passwordPlaceholder": "Introduza a sua senha",
7
+ "signingIn": "A entrar...",
8
+ "forgotPassword": "Esqueceu a senha?",
9
+ "ssoChecking": "A verificar opções de início de sessão...",
10
+ "ssoNotice": "A sua organização utiliza início de sessão único",
11
+ "continueWithSso": "Continuar com SSO",
12
+ "errorInvalidCredentials": "E-mail ou senha inválidos",
13
+ "errorLockedOut": "Conta bloqueada. Tente novamente em {{seconds}} segundos",
14
+ "errorEmailNotConfirmed": "Verifique o seu e-mail para confirmar a sua conta",
15
+ "errorSsoRequired": "O início de sessão único é obrigatório para esta conta",
16
+ "errorEmailRequired": "O e-mail é obrigatório",
17
+ "errorPasswordRequired": "A senha é obrigatória",
18
+ "errorUnexpected": "Ocorreu um erro inesperado. Tente novamente.",
19
+ "resetYourPassword": "Redefinir a sua senha",
20
+ "resetSubtitle": "Introduza o seu endereço de e-mail e enviaremos um link para redefinir a sua senha.",
21
+ "sending": "A enviar...",
22
+ "sendResetLink": "Enviar link de redefinição",
23
+ "backToSignIn": "Voltar ao início de sessão",
24
+ "checkYourEmail": "Verifique o seu e-mail",
25
+ "resetEmailSent": "Se existir uma conta com esse e-mail, receberá um link de redefinição em breve.",
26
+ "setNewPassword": "Definir nova senha",
27
+ "newPassword": "Nova senha",
28
+ "newPasswordPlaceholder": "Introduza a nova senha",
29
+ "confirmPassword": "Confirmar senha",
30
+ "confirmPasswordPlaceholder": "Confirme a nova senha",
31
+ "resetting": "A redefinir...",
32
+ "resetPassword": "Redefinir senha",
33
+ "passwordResetSuccess": "Senha redefinida com sucesso",
34
+ "passwordResetSuccessMessage": "A sua senha foi redefinida. Pode agora entrar com a sua nova senha.",
35
+ "invalidLink": "Link inválido",
36
+ "invalidOrExpiredLink": "Este link de redefinição é inválido ou expirou.",
37
+ "requestNewResetLink": "Solicitar um novo link de redefinição",
38
+ "passwordNotMeetRequirements": "A senha não cumpre os requisitos",
39
+ "passwordsDoNotMatch": "As senhas não coincidem",
40
+ "passwordWeakError": "A senha não atende aos requisitos de segurança",
41
+ "signInTitle": "Entrar — {{appName}}",
42
+ "ruleMinLength": "Pelo menos {{count}} caracteres",
43
+ "ruleUppercase": "Letra maiúscula",
44
+ "ruleLowercase": "Letra minúscula",
45
+ "ruleDigit": "Número",
46
+ "ruleSpecialChar": "Caractere especial",
47
+ "continueWith": "Continuar com {{provider}}",
48
+ "or": "ou",
49
+ "signedInAs": "Conectado como {{name}}",
50
+ "signedInMessage": "Você já está autenticado."
51
+ }
@@ -0,0 +1,51 @@
1
+ {
2
+ "signIn": "Đăng nhập",
3
+ "email": "Email",
4
+ "password": "Mật khẩu",
5
+ "emailPlaceholder": "you@example.com",
6
+ "passwordPlaceholder": "Nhập mật khẩu của bạn",
7
+ "signingIn": "Đang đăng nhập...",
8
+ "forgotPassword": "Quên mật khẩu?",
9
+ "ssoChecking": "Đang kiểm tra tùy chọn đăng nhập...",
10
+ "ssoNotice": "Tổ chức của bạn sử dụng đăng nhập một lần",
11
+ "continueWithSso": "Tiếp tục với SSO",
12
+ "errorInvalidCredentials": "Email hoặc mật khẩu không hợp lệ",
13
+ "errorLockedOut": "Tài khoản đã bị khóa. Vui lòng thử lại sau {{seconds}} giây",
14
+ "errorEmailNotConfirmed": "Vui lòng kiểm tra email để xác minh tài khoản của bạn",
15
+ "errorSsoRequired": "Đăng nhập một lần là bắt buộc cho tài khoản này",
16
+ "errorEmailRequired": "Email là bắt buộc",
17
+ "errorPasswordRequired": "Mật khẩu là bắt buộc",
18
+ "errorUnexpected": "Đã xảy ra lỗi không mong muốn. Vui lòng thử lại.",
19
+ "resetYourPassword": "Đặt lại mật khẩu",
20
+ "resetSubtitle": "Nhập địa chỉ email của bạn và chúng tôi sẽ gửi cho bạn liên kết để đặt lại mật khẩu.",
21
+ "sending": "Đang gửi...",
22
+ "sendResetLink": "Gửi liên kết đặt lại",
23
+ "backToSignIn": "Quay lại đăng nhập",
24
+ "checkYourEmail": "Kiểm tra email của bạn",
25
+ "resetEmailSent": "Nếu tài khoản tồn tại với email đó, bạn sẽ nhận được liên kết đặt lại trong thời gian ngắn.",
26
+ "setNewPassword": "Đặt mật khẩu mới",
27
+ "newPassword": "Mật khẩu mới",
28
+ "newPasswordPlaceholder": "Nhập mật khẩu mới",
29
+ "confirmPassword": "Xác nhận mật khẩu",
30
+ "confirmPasswordPlaceholder": "Xác nhận mật khẩu mới",
31
+ "resetting": "Đang đặt lại...",
32
+ "resetPassword": "Đặt lại mật khẩu",
33
+ "passwordResetSuccess": "Đặt lại mật khẩu thành công",
34
+ "passwordResetSuccessMessage": "Mật khẩu của bạn đã được đặt lại. Bạn có thể đăng nhập bằng mật khẩu mới.",
35
+ "invalidLink": "Liên kết không hợp lệ",
36
+ "invalidOrExpiredLink": "Liên kết đặt lại này không hợp lệ hoặc đã hết hạn.",
37
+ "requestNewResetLink": "Yêu cầu liên kết đặt lại mới",
38
+ "passwordNotMeetRequirements": "Mật khẩu không đáp ứng các yêu cầu",
39
+ "passwordsDoNotMatch": "Mật khẩu không khớp",
40
+ "passwordWeakError": "Mật khẩu không đáp ứng yêu cầu về độ mạnh",
41
+ "signInTitle": "Đăng nhập — {{appName}}",
42
+ "ruleMinLength": "Ít nhất {{count}} ký tự",
43
+ "ruleUppercase": "Chữ cái viết hoa",
44
+ "ruleLowercase": "Chữ cái viết thường",
45
+ "ruleDigit": "Chữ số",
46
+ "ruleSpecialChar": "Ký tự đặc biệt",
47
+ "continueWith": "Tiếp tục với {{provider}}",
48
+ "or": "hoặc",
49
+ "signedInAs": "Đã đăng nhập với tên {{name}}",
50
+ "signedInMessage": "Bạn đã được xác thực."
51
+ }
@@ -0,0 +1,51 @@
1
+ {
2
+ "signIn": "登录",
3
+ "email": "电子邮件",
4
+ "password": "密码",
5
+ "emailPlaceholder": "you@example.com",
6
+ "passwordPlaceholder": "输入您的密码",
7
+ "signingIn": "正在登录...",
8
+ "forgotPassword": "忘记密码?",
9
+ "ssoChecking": "正在检查登录选项...",
10
+ "ssoNotice": "您的组织使用单点登录",
11
+ "continueWithSso": "使用 SSO 继续",
12
+ "errorInvalidCredentials": "电子邮件或密码无效",
13
+ "errorLockedOut": "账户已锁定。请在 {{seconds}} 秒后重试",
14
+ "errorEmailNotConfirmed": "请检查您的电子邮件以验证您的账户",
15
+ "errorSsoRequired": "此账户需要单点登录",
16
+ "errorEmailRequired": "电子邮件为必填项",
17
+ "errorPasswordRequired": "密码为必填项",
18
+ "errorUnexpected": "发生意外错误,请重试。",
19
+ "resetYourPassword": "重置密码",
20
+ "resetSubtitle": "输入您的电子邮件地址,我们将向您发送重置密码的链接。",
21
+ "sending": "正在发送...",
22
+ "sendResetLink": "发送重置链接",
23
+ "backToSignIn": "返回登录",
24
+ "checkYourEmail": "请查看您的电子邮件",
25
+ "resetEmailSent": "如果该电子邮件地址存在对应的账户,您将很快收到重置链接。",
26
+ "setNewPassword": "设置新密码",
27
+ "newPassword": "新密码",
28
+ "newPasswordPlaceholder": "输入新密码",
29
+ "confirmPassword": "确认密码",
30
+ "confirmPasswordPlaceholder": "确认新密码",
31
+ "resetting": "正在重置...",
32
+ "resetPassword": "重置密码",
33
+ "passwordResetSuccess": "密码重置成功",
34
+ "passwordResetSuccessMessage": "您的密码已重置。您现在可以使用新密码登录。",
35
+ "invalidLink": "无效链接",
36
+ "invalidOrExpiredLink": "此重置链接无效或已过期。",
37
+ "requestNewResetLink": "请求新的重置链接",
38
+ "passwordNotMeetRequirements": "密码不符合要求",
39
+ "passwordsDoNotMatch": "两次输入的密码不一致",
40
+ "passwordWeakError": "密码不符合强度要求",
41
+ "signInTitle": "登录 — {{appName}}",
42
+ "ruleMinLength": "至少 {{count}} 个字符",
43
+ "ruleUppercase": "大写字母",
44
+ "ruleLowercase": "小写字母",
45
+ "ruleDigit": "数字",
46
+ "ruleSpecialChar": "特殊字符",
47
+ "continueWith": "使用 {{provider}} 继续",
48
+ "or": "或",
49
+ "signedInAs": "已登录为 {{name}}",
50
+ "signedInMessage": "您已通过身份验证。"
51
+ }
package/src/index.ts ADDED
@@ -0,0 +1,28 @@
1
+ // Public API — consumers import from '@drawboard/authagonal-login'
2
+ //
3
+ // Usage:
4
+ // import { AuthLayout, LoginPage, useBranding } from '@drawboard/authagonal-login';
5
+
6
+ // Components
7
+ export { default as AuthLayout } from './components/AuthLayout';
8
+
9
+ // Pages
10
+ export { default as LoginPage } from './pages/LoginPage';
11
+ export { default as ForgotPasswordPage } from './pages/ForgotPasswordPage';
12
+ export { default as ResetPasswordPage } from './pages/ResetPasswordPage';
13
+
14
+ // Branding
15
+ export { loadBranding, BrandingContext, useBranding } from './branding';
16
+ export type { BrandingConfig } from './branding';
17
+
18
+ // API client
19
+ export { login, logout, forgotPassword, resetPassword, getSession, ssoCheck, getProviders, getPasswordPolicy, ApiRequestError } from './api';
20
+
21
+ // Types
22
+ export type { LoginResponse, ApiError, SessionResponse, SsoCheckResponse, ExternalProvider, ProvidersResponse, PasswordPolicyRule, PasswordPolicyResponse } from './types';
23
+
24
+ // i18n — re-export so consumers use the same react-i18next instance
25
+ export { default as i18n } from './i18n';
26
+ export { useTranslation } from 'react-i18next';
27
+
28
+ // Styles — import '@drawboard/authagonal-login/src/styles.css' in your entry point
package/src/main.tsx ADDED
@@ -0,0 +1,19 @@
1
+ import { StrictMode } from 'react';
2
+ import { createRoot } from 'react-dom/client';
3
+ import './styles.css';
4
+ import App from './App';
5
+ import { loadBranding, BrandingContext } from './branding';
6
+ import './i18n';
7
+ import i18n from './i18n';
8
+
9
+ loadBranding().then((config) => {
10
+ document.title = i18n.t('signInTitle', { appName: config.appName });
11
+
12
+ createRoot(document.getElementById('root')!).render(
13
+ <StrictMode>
14
+ <BrandingContext.Provider value={config}>
15
+ <App />
16
+ </BrandingContext.Provider>
17
+ </StrictMode>,
18
+ );
19
+ });
@@ -0,0 +1,100 @@
1
+ import { useState } from 'react';
2
+ import { useSearchParams, Link } from 'react-router-dom';
3
+ import { useTranslation } from 'react-i18next';
4
+ import { forgotPassword } from '../api';
5
+
6
+ export default function ForgotPasswordPage() {
7
+ const { t } = useTranslation();
8
+ const [searchParams] = useSearchParams();
9
+ const returnUrl = searchParams.get('returnUrl') || '';
10
+
11
+ const [email, setEmail] = useState('');
12
+ const [loading, setLoading] = useState(false);
13
+ const [submitted, setSubmitted] = useState(false);
14
+ const [error, setError] = useState('');
15
+
16
+ const loginLink = returnUrl
17
+ ? `/login?returnUrl=${encodeURIComponent(returnUrl)}`
18
+ : '/login';
19
+
20
+ async function handleSubmit(e: React.FormEvent) {
21
+ e.preventDefault();
22
+ setError('');
23
+ setLoading(true);
24
+
25
+ try {
26
+ await forgotPassword(email);
27
+ setSubmitted(true);
28
+ } catch {
29
+ // The API always returns 200 for anti-enumeration, but handle errors just in case
30
+ setError(t('errorUnexpected'));
31
+ } finally {
32
+ setLoading(false);
33
+ }
34
+ }
35
+
36
+ if (submitted) {
37
+ return (
38
+ <div>
39
+ <h2 className="auth-title">{t('checkYourEmail')}</h2>
40
+ <div className="alert-success">
41
+ {t('resetEmailSent')}
42
+ </div>
43
+ <div className="form-footer">
44
+ <Link to={loginLink} className="link">
45
+ {t('backToSignIn')}
46
+ </Link>
47
+ </div>
48
+ </div>
49
+ );
50
+ }
51
+
52
+ return (
53
+ <div>
54
+ <h2 className="auth-title">{t('resetYourPassword')}</h2>
55
+ <p className="auth-subtitle">
56
+ {t('resetSubtitle')}
57
+ </p>
58
+
59
+ {error && <div className="alert-error">{error}</div>}
60
+
61
+ <form onSubmit={handleSubmit}>
62
+ <div className="form-group">
63
+ <label htmlFor="email">{t('email')}</label>
64
+ <input
65
+ id="email"
66
+ type="email"
67
+ value={email}
68
+ onChange={(e) => setEmail(e.target.value)}
69
+ placeholder={t('emailPlaceholder')}
70
+ autoComplete="email"
71
+ autoFocus
72
+ maxLength={256}
73
+ required
74
+ />
75
+ </div>
76
+
77
+ <button
78
+ type="submit"
79
+ className="btn-primary"
80
+ disabled={loading}
81
+ >
82
+ {loading ? (
83
+ <span className="btn-loading">
84
+ <span className="spinner" />
85
+ {t('sending')}
86
+ </span>
87
+ ) : (
88
+ t('sendResetLink')
89
+ )}
90
+ </button>
91
+
92
+ <div className="form-footer">
93
+ <Link to={loginLink} className="link">
94
+ {t('backToSignIn')}
95
+ </Link>
96
+ </div>
97
+ </form>
98
+ </div>
99
+ );
100
+ }