@micha.bigler/ui-core-micha 1.4.6 → 1.4.8

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.
@@ -18,6 +18,6 @@ disabled = false, }) => {
18
18
  const supportsPasskey = !!onPasskeyLogin &&
19
19
  typeof window !== 'undefined' &&
20
20
  !!window.PublicKeyCredential;
21
- return (_jsxs(Box, { sx: { display: 'flex', flexDirection: 'column', gap: 3 }, children: [error && (_jsx(Typography, { color: "error", gutterBottom: true, children: error })), supportsPasskey && (_jsxs(_Fragment, { children: [_jsx(Button, { variant: "contained", fullWidth: true, type: "button", onClick: onPasskeyLogin, disabled: disabled, children: t('Auth.LOGIN_USE_PASSKEY_PRIMARY') }), _jsx(Divider, { sx: { my: 2 }, children: t('Auth.LOGIN_OR') })] })), _jsxs(Box, { component: "form", onSubmit: handleSubmit, sx: { display: 'flex', flexDirection: 'column', gap: 2 }, children: [_jsx(TextField, { label: t('Auth.LOGIN_EMAIL_LABEL'), type: "email", required: true, fullWidth: true, value: identifier, onChange: (e) => setIdentifier(e.target.value), disabled: disabled }), _jsx(TextField, { label: t('Auth.LOGIN_PASSWORD_LABEL'), type: "password", required: true, fullWidth: true, value: password, onChange: (e) => setPassword(e.target.value), disabled: disabled }), _jsx(Button, { type: "submit", variant: "contained", fullWidth: true, disabled: disabled, children: t('Auth.LOGIN_SUBMIT') })] }), _jsxs(Box, { children: [_jsx(Typography, { variant: "subtitle2", sx: { mb: 1 }, children: t('Auth.LOGIN_OTHER_METHODS_TITLE') }), _jsx(SocialLoginButtons, { onProviderClick: onSocialLogin })] }), _jsxs(Box, { children: [_jsx(Typography, { variant: "subtitle2", sx: { mb: 1 }, children: t('Auth.LOGIN_ACCOUNT_RECOVERY_TITLE') }), _jsxs(Box, { sx: { display: 'flex', gap: 1, flexWrap: 'wrap' }, children: [onSignUp && (_jsx(Button, { type: "button", variant: "outlined", onClick: onSignUp, disabled: disabled, children: t('Auth.LOGIN_SIGNUP_BUTTON') })), _jsx(Button, { type: "button", variant: "outlined", onClick: onForgotPassword, disabled: disabled, children: t('Auth.LOGIN_FORGOT_PASSWORD_BUTTON') })] })] })] }));
21
+ return (_jsxs(Box, { sx: { display: 'flex', flexDirection: 'column', gap: 3 }, children: [error && (_jsx(Typography, { color: "error", gutterBottom: true, children: error })), supportsPasskey && (_jsxs(_Fragment, { children: [_jsx(Button, { variant: "contained", fullWidth: true, type: "button", onClick: onPasskeyLogin, disabled: disabled, children: t('Auth.LOGIN_USE_PASSKEY_BUTTON') }), _jsx(Divider, { sx: { my: 2 }, children: t('Auth.LOGIN_OR') })] })), _jsxs(Box, { component: "form", onSubmit: handleSubmit, sx: { display: 'flex', flexDirection: 'column', gap: 2 }, children: [_jsx(TextField, { label: t('Auth.EMAIL_LABEL'), type: "email", required: true, fullWidth: true, value: identifier, onChange: (e) => setIdentifier(e.target.value), disabled: disabled }), _jsx(TextField, { label: t('Auth.LOGIN_PASSWORD_LABEL'), type: "password", required: true, fullWidth: true, value: password, onChange: (e) => setPassword(e.target.value), disabled: disabled }), _jsx(Button, { type: "submit", variant: "contained", fullWidth: true, disabled: disabled, children: t('Auth.LOGIN_SUBMIT') })] }), _jsxs(Box, { children: [_jsx(Divider, { sx: { my: 2 }, children: t('Auth.LOGIN_OR') }), _jsx(SocialLoginButtons, { onProviderClick: onSocialLogin })] }), _jsxs(Box, { children: [_jsx(Typography, { variant: "subtitle2", sx: { mb: 1 }, children: t('Auth.LOGIN_ACCOUNT_RECOVERY_TITLE') }), _jsxs(Box, { sx: { display: 'flex', gap: 1, flexWrap: 'wrap' }, children: [onSignUp && (_jsx(Button, { type: "button", variant: "outlined", onClick: onSignUp, disabled: disabled, children: t('Auth.LOGIN_SIGNUP_BUTTON') })), _jsx(Button, { type: "button", variant: "outlined", onClick: onForgotPassword, disabled: disabled, children: t('Auth.LOGIN_FORGOT_PASSWORD_BUTTON') })] })] })] }));
22
22
  };
23
23
  export default LoginForm;
@@ -67,6 +67,6 @@ const MfaLoginComponent = ({ availableTypes, identifier, onSuccess, onCancel })
67
67
  setSubmitting(false);
68
68
  }
69
69
  };
70
- return (_jsxs(Box, { children: [_jsx(Typography, { variant: "h6", gutterBottom: true, children: t('Auth.MFA_TITLE', 'Additional verification required') }), _jsx(Typography, { variant: "body2", sx: { mb: 2 }, children: t('Auth.MFA_SUBTITLE', 'Please confirm your login using one of the available methods.') }), errorKey && (_jsx(Alert, { severity: "error", sx: { mb: 2 }, children: t(errorKey) })), infoKey && (_jsx(Alert, { severity: "info", sx: { mb: 2 }, children: t(infoKey) })), _jsxs(Stack, { spacing: 2, children: [supportsTotpOrRecovery && (_jsxs(Box, { component: "form", onSubmit: handleSubmitCode, children: [_jsx(TextField, { label: t('Auth.MFA_CODE_LABEL', 'Authenticator code (or recovery code)'), value: code, onChange: (e) => setCode(e.target.value), fullWidth: true, disabled: submitting || helpRequested, autoComplete: "one-time-code", sx: { mb: 2 } }), _jsx(Button, { type: "submit", variant: "contained", fullWidth: true, disabled: submitting || !code.trim() || helpRequested, children: t('Auth.MFA_VERIFY', 'Verify') })] })), supportsWebauthn && (_jsx(Button, { variant: "outlined", fullWidth: true, onClick: handlePasskey, disabled: submitting || helpRequested, children: t('Auth.MFA_USE_PASSKEY', 'Use passkey / security key') })), _jsx(Button, { size: "small", onClick: onCancel, disabled: submitting, children: t('Auth.MFA_BACK_TO_LOGIN', 'Back to login') }), _jsx(Button, { size: "small", color: "secondary", onClick: handleNeedHelp, disabled: submitting || helpRequested, children: t('Auth.MFA_NEED_HELP', "I can't use any of these methods") })] })] }));
70
+ return (_jsxs(Box, { children: [_jsx(Typography, { variant: "body2", sx: { mb: 2 }, children: t('Auth.MFA_SUBTITLE', 'Please confirm your login using one of the available methods.') }), errorKey && (_jsx(Alert, { severity: "error", sx: { mb: 2 }, children: t(errorKey) })), infoKey && (_jsx(Alert, { severity: "info", sx: { mb: 2 }, children: t(infoKey) })), _jsxs(Stack, { spacing: 2, children: [supportsWebauthn && (_jsx(Button, { variant: "contained", fullWidth: true, onClick: handlePasskey, disabled: submitting || helpRequested, children: t('Auth.MFA_USE_PASSKEY', 'Use passkey / security key') })), supportsTotpOrRecovery && (_jsxs(Box, { component: "form", onSubmit: handleSubmitCode, children: [_jsx(TextField, { label: t('Auth.MFA_CODE_LABEL', 'Authenticator code (or recovery code)'), value: code, onChange: (e) => setCode(e.target.value), fullWidth: true, disabled: submitting || helpRequested, autoComplete: "one-time-code", sx: { mb: 2 } }), _jsx(Button, { type: "submit", variant: "contained", fullWidth: true, disabled: submitting || !code.trim() || helpRequested, children: t('Auth.MFA_VERIFY', 'Verify') })] })), _jsxs(Stack, { direction: "row", spacing: 1, sx: { mt: 1 }, children: [_jsx(Button, { fullWidth: true, size: "small", variant: "outlined", onClick: onCancel, disabled: submitting, children: t('Auth.MFA_BACK_TO_LOGIN', 'Back to login') }), _jsx(Button, { fullWidth: true, size: "small", variant: "outlined", color: "secondary", onClick: handleNeedHelp, disabled: submitting || helpRequested, children: t('Auth.MFA_NEED_HELP', "I can't use any of these methods") })] })] })] }));
71
71
  };
72
72
  export default MfaLoginComponent;
@@ -27,7 +27,7 @@ const PasswordSetForm = ({ onSubmit, submitting = false }) => {
27
27
  onSubmit(password1);
28
28
  }
29
29
  };
30
- return (_jsxs(Box, { component: "form", onSubmit: handleSubmit, sx: { display: 'flex', flexDirection: 'column', gap: 2, mt: 2 }, children: [localErrorKey && (_jsx(Box, { sx: { color: 'error.main', fontSize: 14 }, children: t(localErrorKey) })), _jsx(TextField, { label: t('Auth.PASSWORD_NEW_LABEL'), type: "password", fullWidth: true, autoComplete: "new-password", value: password1, onChange: (e) => setPassword1(e.target.value), disabled: submitting }), _jsx(TextField, { label: t('Auth.PASSWORD_CONFIRM_LABEL'), type: "password", fullWidth: true, autoComplete: "new-password", value: password2, onChange: (e) => setPassword2(e.target.value), disabled: submitting }), _jsx(Button, { type: "submit", variant: "contained", disabled: submitting, children: submitting
30
+ return (_jsxs(Box, { component: "form", onSubmit: handleSubmit, sx: { display: 'flex', flexDirection: 'column', gap: 2, mt: 2 }, children: [localErrorKey && (_jsx(Box, { sx: { color: 'error.main', fontSize: 14 }, children: t(localErrorKey) })), _jsx(TextField, { label: t('Auth.NEW_PASSWORD_LABEL'), type: "password", fullWidth: true, autoComplete: "new-password", value: password1, onChange: (e) => setPassword1(e.target.value), disabled: submitting }), _jsx(TextField, { label: t('Auth.PASSWORD_CONFIRM_LABEL'), type: "password", fullWidth: true, autoComplete: "new-password", value: password2, onChange: (e) => setPassword2(e.target.value), disabled: submitting }), _jsx(Button, { type: "submit", variant: "contained", disabled: submitting, children: submitting
31
31
  ? t('Auth.PASSWORD_SET_BUTTON_LOADING')
32
32
  : t('Auth.PASSWORD_SET_BUTTON') })] }));
33
33
  };
@@ -104,6 +104,6 @@ showName = true, showPrivacy = true, showCookies = true, }) {
104
104
  // - Sonst i18n-Schlüssel verwenden
105
105
  const submitLabel = submitText || t('Profile.SAVE_BUTTON');
106
106
  const submitLabelLoading = t('Profile.SAVE_BUTTON_LOADING');
107
- return (_jsxs(Box, { component: "form", onSubmit: handleSubmit, sx: { maxWidth: 600, display: 'flex', flexDirection: 'column', gap: 2 }, children: [errorKey && (_jsx(Alert, { severity: "error", children: t(errorKey) })), successKey && (_jsx(Alert, { severity: "success", children: t(successKey) })), _jsxs(Stack, { spacing: 2, children: [_jsx(TextField, { label: t('Profile.USERNAME_LABEL'), value: username, fullWidth: true, disabled: true }), _jsx(TextField, { label: t('Profile.EMAIL_LABEL'), type: "email", value: email, fullWidth: true, disabled: true })] }), showName && (_jsxs(Stack, { spacing: 2, direction: { xs: 'column', sm: 'row' }, children: [_jsx(TextField, { label: t('Profile.FIRST_NAME_LABEL'), value: firstName, onChange: (e) => setFirstName(e.target.value), fullWidth: true }), _jsx(TextField, { label: t('Profile.LAST_NAME_LABEL'), value: lastName, onChange: (e) => setLastName(e.target.value), fullWidth: true })] })), (showPrivacy || showCookies) && (_jsxs(Box, { sx: { mt: 1 }, children: [_jsx(Typography, { variant: "subtitle1", gutterBottom: true, children: t('Profile.PRIVACY_SECTION_TITLE') }), _jsxs(Stack, { spacing: 1, children: [showPrivacy && (_jsx(FormControlLabel, { control: _jsx(Checkbox, { checked: acceptedPrivacy, onChange: (e) => setAcceptedPrivacy(e.target.checked) }), label: t('Profile.ACCEPT_PRIVACY_LABEL') })), showCookies && (_jsx(FormControlLabel, { control: _jsx(Checkbox, { checked: acceptedCookies, onChange: (e) => setAcceptedCookies(e.target.checked) }), label: t('Profile.ACCEPT_COOKIES_LABEL') }))] })] })), _jsx(Box, { sx: { mt: 2 }, children: _jsx(Button, { type: "submit", variant: "contained", disabled: saving, children: saving ? submitLabelLoading : submitLabel }) })] }));
107
+ return (_jsxs(Box, { component: "form", onSubmit: handleSubmit, sx: { maxWidth: 600, display: 'flex', flexDirection: 'column', gap: 2 }, children: [errorKey && (_jsx(Alert, { severity: "error", children: t(errorKey) })), successKey && (_jsx(Alert, { severity: "success", children: t(successKey) })), _jsxs(Stack, { spacing: 2, children: [_jsx(TextField, { label: t('Profile.USERNAME_LABEL'), value: username, fullWidth: true, disabled: true }), _jsx(TextField, { label: t('Auth.EMAIL_LABEL'), type: "email", value: email, fullWidth: true, disabled: true })] }), showName && (_jsxs(Stack, { spacing: 2, direction: { xs: 'column', sm: 'row' }, children: [_jsx(TextField, { label: t('Profile.FIRST_NAME_LABEL'), value: firstName, onChange: (e) => setFirstName(e.target.value), fullWidth: true }), _jsx(TextField, { label: t('Profile.LAST_NAME_LABEL'), value: lastName, onChange: (e) => setLastName(e.target.value), fullWidth: true })] })), (showPrivacy || showCookies) && (_jsxs(Box, { sx: { mt: 1 }, children: [_jsx(Typography, { variant: "subtitle1", gutterBottom: true, children: t('Profile.PRIVACY_SECTION_TITLE') }), _jsxs(Stack, { spacing: 1, children: [showPrivacy && (_jsx(FormControlLabel, { control: _jsx(Checkbox, { checked: acceptedPrivacy, onChange: (e) => setAcceptedPrivacy(e.target.checked) }), label: t('Profile.ACCEPT_PRIVACY_LABEL') })), showCookies && (_jsx(FormControlLabel, { control: _jsx(Checkbox, { checked: acceptedCookies, onChange: (e) => setAcceptedCookies(e.target.checked) }), label: t('Profile.ACCEPT_COOKIES_LABEL') }))] })] })), _jsx(Box, { sx: { mt: 2 }, children: _jsx(Button, { type: "submit", variant: "contained", disabled: saving, children: saving ? submitLabelLoading : submitLabel }) })] }));
108
108
  }
109
109
  export default ProfileComponent;
@@ -281,7 +281,7 @@ export const authTranslations = {
281
281
  "fr": "Saisissez votre adresse e-mail et le code d'accès pour demander une invitation.",
282
282
  "en": "Enter your email address and access code to request an invitation."
283
283
  },
284
- "Auth.SIGNUP_EMAIL_LABEL": {
284
+ "Auth.EMAIL_LABEL": {
285
285
  "de": "E-Mail-Adresse",
286
286
  "fr": "Adresse e-mail",
287
287
  "en": "Email address"
@@ -406,11 +406,6 @@ export const authTranslations = {
406
406
  "fr": "Impossible de supprimer le code d'accès.",
407
407
  "en": "Could not delete access code."
408
408
  },
409
- "Auth.LOGIN_EMAIL_LABEL": {
410
- "de": "E-Mail-Adresse",
411
- "fr": "Adresse e-mail",
412
- "en": "Email address"
413
- },
414
409
  "Auth.LOGIN_PASSWORD_LABEL": {
415
410
  "de": "Passwort",
416
411
  "fr": "Mot de passe",
@@ -426,7 +421,7 @@ export const authTranslations = {
426
421
  "fr": "Créer un compte",
427
422
  "en": "Sign up"
428
423
  },
429
- "Auth.LOGIN_FORGOT_PASSWORD_LINK": {
424
+ "Auth.LOGIN_FORGOT_PASSWORD_BUTTON": {
430
425
  "de": "Passwort vergessen?",
431
426
  "fr": "Mot de passe oublié ?",
432
427
  "en": "Forgot password?"
@@ -706,11 +701,6 @@ export const authTranslations = {
706
701
  "fr": "Nom d’utilisateur",
707
702
  "en": "Username"
708
703
  },
709
- "Profile.EMAIL_LABEL": {
710
- "de": "E-Mail",
711
- "fr": "E-mail",
712
- "en": "Email"
713
- },
714
704
  "Profile.FIRST_NAME_LABEL": {
715
705
  "de": "Vorname",
716
706
  "fr": "Prénom",
@@ -825,6 +815,16 @@ export const authTranslations = {
825
815
  "de": "Die Support-Anfrage konnte nicht gesendet werden. Bitte versuche es später erneut oder kontaktiere den Support direkt.",
826
816
  "fr": "La demande d'assistance n'a pas pu être envoyée. Veuillez réessayer plus tard ou contacter le support directement.",
827
817
  "en": "Could not send the support request. Please try again later or contact support directly."
828
- }
818
+ },
819
+ "Auth.LOGIN_OTHER_METHODS_TITLE": {
820
+ "de": "Andere Anmeldemethoden",
821
+ "fr": "Autres méthodes de connexion",
822
+ "en": "Other sign-in methods"
823
+ },
824
+ "Auth.LOGIN_ACCOUNT_RECOVERY_TITLE": {
825
+ "de": "Konto-Wiederherstellung",
826
+ "fr": "Récupération de compte",
827
+ "en": "Account recovery"
828
+ },
829
829
  // ...
830
830
  };
@@ -30,6 +30,6 @@ export function AccountPage() {
30
30
  const updatedUser = await authApi.updateUserProfile(payload);
31
31
  login(updatedUser);
32
32
  };
33
- return (_jsxs(WidePage, { title: "Account", children: [_jsx(Helmet, { children: _jsx("title", { children: "PROJECT_NAME \u2013 Account" }) }), _jsxs(Tabs, { value: tab, onChange: handleTabChange, sx: { mb: 3 }, children: [_jsx(Tab, { label: "Account", value: "account" }), _jsx(Tab, { label: "Security", value: "security" }), _jsx(Tab, { label: "Support", value: "support" })] }), tab === 'account' && (_jsx(Box, { sx: { mt: 1 }, children: _jsx(ProfileComponent, { onLoad: () => { }, onSubmit: handleProfileSubmit, submitText: "Save", showName: true, showPrivacy: true, showCookies: true }) })), tab === 'security' && (_jsx(Box, { sx: { mt: 1 }, children: _jsx(SecurityComponent, { fromRecovery: fromRecovery, fromWeakLogin: fromWeakLogin }) })), tab === 'support' && (_jsx(Box, { sx: { mt: 1 }, children: _jsx(SupportRecoveryRequestsTab, {}) }))] }));
33
+ return (_jsxs(WidePage, { title: "Account", children: [_jsx(Helmet, { children: _jsx("title", { children: "PROJECT_NAME \u2013 Account" }) }), _jsxs(Tabs, { value: tab, onChange: handleTabChange, sx: { mb: 3 }, children: [_jsx(Tab, { label: "Security", value: "security" }), _jsx(Tab, { label: "Account", value: "account" }), _jsx(Tab, { label: "Support", value: "support" })] }), tab === 'security' && (_jsx(Box, { sx: { mt: 1 }, children: _jsx(SecurityComponent, { fromRecovery: fromRecovery, fromWeakLogin: fromWeakLogin }) })), tab === 'account' && (_jsx(Box, { sx: { mt: 1 }, children: _jsx(ProfileComponent, { onLoad: () => { }, onSubmit: handleProfileSubmit, submitText: "Save", showName: true, showPrivacy: true, showCookies: true }) })), tab === 'support' && (_jsx(Box, { sx: { mt: 1 }, children: _jsx(SupportRecoveryRequestsTab, {}) }))] }));
34
34
  }
35
35
  export default AccountPage;
@@ -50,7 +50,7 @@ export function SignUpPage() {
50
50
  const handleGoToLogin = () => {
51
51
  navigate('/login');
52
52
  };
53
- return (_jsxs(NarrowPage, { title: t('Auth.PAGE_SIGNUP_TITLE'), subtitle: t('Auth.PAGE_SIGNUP_SUBTITLE'), children: [_jsx(Helmet, { children: _jsxs("title", { children: [t('App.NAME'), " \u2013 ", t('Auth.PAGE_SIGNUP_TITLE')] }) }), successKey && (_jsx(Alert, { severity: "success", sx: { mb: 2 }, children: t(successKey, { email }) })), errorKey && (_jsx(Alert, { severity: "error", sx: { mb: 2 }, children: t(errorKey) })), _jsxs(Box, { component: "form", onSubmit: handleSubmit, sx: { display: 'flex', flexDirection: 'column', gap: 2 }, children: [_jsx(TextField, { label: t('Auth.SIGNUP_EMAIL_LABEL'), type: "email", required: true, fullWidth: true, value: email, onChange: (e) => setEmail(e.target.value), disabled: submitting }), _jsx(TextField, { label: t('Auth.SIGNUP_ACCESS_CODE_LABEL'), type: "text", required: true, fullWidth: true, value: accessCode, onChange: (e) => setAccessCode(e.target.value), disabled: submitting }), _jsx(Button, { type: "submit", variant: "contained", disabled: submitting, children: submitting
53
+ return (_jsxs(NarrowPage, { title: t('Auth.PAGE_SIGNUP_TITLE'), subtitle: t('Auth.PAGE_SIGNUP_SUBTITLE'), children: [_jsx(Helmet, { children: _jsxs("title", { children: [t('App.NAME'), " \u2013 ", t('Auth.PAGE_SIGNUP_TITLE')] }) }), successKey && (_jsx(Alert, { severity: "success", sx: { mb: 2 }, children: t(successKey, { email }) })), errorKey && (_jsx(Alert, { severity: "error", sx: { mb: 2 }, children: t(errorKey) })), _jsxs(Box, { component: "form", onSubmit: handleSubmit, sx: { display: 'flex', flexDirection: 'column', gap: 2 }, children: [_jsx(TextField, { label: t('Auth.EMAIL_LABEL'), type: "email", required: true, fullWidth: true, value: email, onChange: (e) => setEmail(e.target.value), disabled: submitting }), _jsx(TextField, { label: t('Auth.SIGNUP_ACCESS_CODE_LABEL'), type: "text", required: true, fullWidth: true, value: accessCode, onChange: (e) => setAccessCode(e.target.value), disabled: submitting }), _jsx(Button, { type: "submit", variant: "contained", disabled: submitting, children: submitting
54
54
  ? t('Auth.SIGNUP_SUBMITTING')
55
55
  : t('Auth.SIGNUP_SUBMIT') })] }), _jsx(Box, { sx: { mt: 3 }, children: _jsxs(Typography, { variant: "body2", children: [t('Auth.SIGNUP_ALREADY_HAVE_ACCOUNT'), ' ', _jsx(Button, { onClick: handleGoToLogin, variant: "text", size: "small", children: t('Auth.SIGNUP_GO_TO_LOGIN') })] }) })] }));
56
56
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@micha.bigler/ui-core-micha",
3
- "version": "1.4.6",
3
+ "version": "1.4.8",
4
4
  "main": "dist/index.js",
5
5
  "module": "dist/index.js",
6
6
  "private": false,
@@ -53,7 +53,7 @@ const LoginForm = ({
53
53
  onClick={onPasskeyLogin}
54
54
  disabled={disabled}
55
55
  >
56
- {t('Auth.LOGIN_USE_PASSKEY_PRIMARY')}
56
+ {t('Auth.LOGIN_USE_PASSKEY_BUTTON')}
57
57
  </Button>
58
58
 
59
59
  <Divider sx={{ my: 2 }}>
@@ -69,7 +69,7 @@ const LoginForm = ({
69
69
  sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}
70
70
  >
71
71
  <TextField
72
- label={t('Auth.LOGIN_EMAIL_LABEL')}
72
+ label={t('Auth.EMAIL_LABEL')}
73
73
  type="email"
74
74
  required
75
75
  fullWidth
@@ -96,13 +96,15 @@ const LoginForm = ({
96
96
  >
97
97
  {t('Auth.LOGIN_SUBMIT')}
98
98
  </Button>
99
+
100
+
99
101
  </Box>
100
102
 
101
103
  {/* Other ways to sign in */}
102
104
  <Box>
103
- <Typography variant="subtitle2" sx={{ mb: 1 }}>
104
- {t('Auth.LOGIN_OTHER_METHODS_TITLE')}
105
- </Typography>
105
+ <Divider sx={{ my: 2 }}>
106
+ {t('Auth.LOGIN_OR')}
107
+ </Divider>
106
108
  <SocialLoginButtons onProviderClick={onSocialLogin} />
107
109
  </Box>
108
110
 
@@ -79,9 +79,6 @@ const MfaLoginComponent = ({ availableTypes, identifier, onSuccess, onCancel })
79
79
 
80
80
  return (
81
81
  <Box>
82
- <Typography variant="h6" gutterBottom>
83
- {t('Auth.MFA_TITLE', 'Additional verification required')}
84
- </Typography>
85
82
  <Typography variant="body2" sx={{ mb: 2 }}>
86
83
  {t(
87
84
  'Auth.MFA_SUBTITLE',
@@ -102,6 +99,17 @@ const MfaLoginComponent = ({ availableTypes, identifier, onSuccess, onCancel })
102
99
  )}
103
100
 
104
101
  <Stack spacing={2}>
102
+ {supportsWebauthn && (
103
+ <Button
104
+ variant="contained"
105
+ fullWidth
106
+ onClick={handlePasskey}
107
+ disabled={submitting || helpRequested}
108
+ >
109
+ {t('Auth.MFA_USE_PASSKEY', 'Use passkey / security key')}
110
+ </Button>
111
+ )}
112
+
105
113
  {supportsTotpOrRecovery && (
106
114
  <Box component="form" onSubmit={handleSubmitCode}>
107
115
  <TextField
@@ -127,36 +135,33 @@ const MfaLoginComponent = ({ availableTypes, identifier, onSuccess, onCancel })
127
135
  </Box>
128
136
  )}
129
137
 
130
- {supportsWebauthn && (
138
+
139
+
140
+ <Stack direction="row" spacing={1} sx={{ mt: 1 }}>
131
141
  <Button
142
+ fullWidth
143
+ size="small"
132
144
  variant="outlined"
145
+ onClick={onCancel}
146
+ disabled={submitting}
147
+ >
148
+ {t('Auth.MFA_BACK_TO_LOGIN', 'Back to login')}
149
+ </Button>
150
+
151
+ <Button
133
152
  fullWidth
134
- onClick={handlePasskey}
153
+ size="small"
154
+ variant="outlined"
155
+ color="secondary"
156
+ onClick={handleNeedHelp}
135
157
  disabled={submitting || helpRequested}
136
158
  >
137
- {t('Auth.MFA_USE_PASSKEY', 'Use passkey / security key')}
159
+ {t(
160
+ 'Auth.MFA_NEED_HELP',
161
+ "I can't use any of these methods",
162
+ )}
138
163
  </Button>
139
- )}
140
-
141
- <Button
142
- size="small"
143
- onClick={onCancel}
144
- disabled={submitting}
145
- >
146
- {t('Auth.MFA_BACK_TO_LOGIN', 'Back to login')}
147
- </Button>
148
-
149
- <Button
150
- size="small"
151
- color="secondary"
152
- onClick={handleNeedHelp}
153
- disabled={submitting || helpRequested}
154
- >
155
- {t(
156
- 'Auth.MFA_NEED_HELP',
157
- "I can't use any of these methods",
158
- )}
159
- </Button>
164
+ </Stack>
160
165
  </Stack>
161
166
  </Box>
162
167
  );
@@ -46,7 +46,7 @@ const PasswordSetForm = ({ onSubmit, submitting = false }) => {
46
46
  )}
47
47
 
48
48
  <TextField
49
- label={t('Auth.PASSWORD_NEW_LABEL')}
49
+ label={t('Auth.NEW_PASSWORD_LABEL')}
50
50
  type="password"
51
51
  fullWidth
52
52
  autoComplete="new-password"
@@ -159,7 +159,7 @@ export function ProfileComponent({
159
159
  disabled
160
160
  />
161
161
  <TextField
162
- label={t('Profile.EMAIL_LABEL')}
162
+ label={t('Auth.EMAIL_LABEL')}
163
163
  type="email"
164
164
  value={email}
165
165
  fullWidth
@@ -320,7 +320,7 @@ export const authTranslations = {
320
320
  "en": "Enter your email address and access code to request an invitation."
321
321
  },
322
322
 
323
- "Auth.SIGNUP_EMAIL_LABEL": {
323
+ "Auth.EMAIL_LABEL": {
324
324
  "de": "E-Mail-Adresse",
325
325
  "fr": "Adresse e-mail",
326
326
  "en": "Email address"
@@ -449,11 +449,6 @@ export const authTranslations = {
449
449
  "fr": "Impossible de supprimer le code d'accès.",
450
450
  "en": "Could not delete access code."
451
451
  },
452
- "Auth.LOGIN_EMAIL_LABEL": {
453
- "de": "E-Mail-Adresse",
454
- "fr": "Adresse e-mail",
455
- "en": "Email address"
456
- },
457
452
  "Auth.LOGIN_PASSWORD_LABEL": {
458
453
  "de": "Passwort",
459
454
  "fr": "Mot de passe",
@@ -469,7 +464,7 @@ export const authTranslations = {
469
464
  "fr": "Créer un compte",
470
465
  "en": "Sign up"
471
466
  },
472
- "Auth.LOGIN_FORGOT_PASSWORD_LINK": {
467
+ "Auth.LOGIN_FORGOT_PASSWORD_BUTTON": {
473
468
  "de": "Passwort vergessen?",
474
469
  "fr": "Mot de passe oublié ?",
475
470
  "en": "Forgot password?"
@@ -753,11 +748,6 @@ export const authTranslations = {
753
748
  "fr": "Nom d’utilisateur",
754
749
  "en": "Username"
755
750
  },
756
- "Profile.EMAIL_LABEL": {
757
- "de": "E-Mail",
758
- "fr": "E-mail",
759
- "en": "Email"
760
- },
761
751
  "Profile.FIRST_NAME_LABEL": {
762
752
  "de": "Vorname",
763
753
  "fr": "Prénom",
@@ -872,7 +862,17 @@ export const authTranslations = {
872
862
  "de": "Die Support-Anfrage konnte nicht gesendet werden. Bitte versuche es später erneut oder kontaktiere den Support direkt.",
873
863
  "fr": "La demande d'assistance n'a pas pu être envoyée. Veuillez réessayer plus tard ou contacter le support directement.",
874
864
  "en": "Could not send the support request. Please try again later or contact support directly."
875
- }
865
+ },
866
+ "Auth.LOGIN_OTHER_METHODS_TITLE": {
867
+ "de": "Andere Anmeldemethoden",
868
+ "fr": "Autres méthodes de connexion",
869
+ "en": "Other sign-in methods"
870
+ },
871
+ "Auth.LOGIN_ACCOUNT_RECOVERY_TITLE": {
872
+ "de": "Konto-Wiederherstellung",
873
+ "fr": "Récupération de compte",
874
+ "en": "Account recovery"
875
+ },
876
876
 
877
877
 
878
878
 
@@ -48,11 +48,20 @@ export function AccountPage() {
48
48
  onChange={handleTabChange}
49
49
  sx={{ mb: 3 }}
50
50
  >
51
- <Tab label="Account" value="account" />
52
51
  <Tab label="Security" value="security" />
52
+ <Tab label="Account" value="account" />
53
53
  <Tab label="Support" value="support" />
54
54
  </Tabs>
55
55
 
56
+ {tab === 'security' && (
57
+ <Box sx={{ mt: 1 }}>
58
+ <SecurityComponent
59
+ fromRecovery={fromRecovery}
60
+ fromWeakLogin={fromWeakLogin}
61
+ />
62
+ </Box>
63
+ )}
64
+
56
65
  {tab === 'account' && (
57
66
  <Box sx={{ mt: 1 }}>
58
67
  <ProfileComponent
@@ -66,14 +75,7 @@ export function AccountPage() {
66
75
  </Box>
67
76
  )}
68
77
 
69
- {tab === 'security' && (
70
- <Box sx={{ mt: 1 }}>
71
- <SecurityComponent
72
- fromRecovery={fromRecovery}
73
- fromWeakLogin={fromWeakLogin}
74
- />
75
- </Box>
76
- )}
78
+
77
79
 
78
80
  {tab === 'support' && (
79
81
  <Box sx={{ mt: 1 }}>
@@ -92,7 +92,7 @@ export function SignUpPage() {
92
92
  sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}
93
93
  >
94
94
  <TextField
95
- label={t('Auth.SIGNUP_EMAIL_LABEL')}
95
+ label={t('Auth.EMAIL_LABEL')}
96
96
  type="email"
97
97
  required
98
98
  fullWidth