@digitaldefiance/express-suite-react-components 5.0.1 → 5.0.2

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 (311) hide show
  1. package/LICENSE +21 -0
  2. package/package.json +3 -4
  3. package/src/auth/AdminRoute.tsx +54 -0
  4. package/src/auth/Private.tsx +17 -0
  5. package/src/auth/PrivateRoute.tsx +28 -0
  6. package/src/auth/UnAuth.tsx +16 -0
  7. package/src/auth/UnAuthRoute.tsx +30 -0
  8. package/src/auth/{index.d.ts → index.ts} +2 -3
  9. package/src/components/ApiAccess.tsx +175 -0
  10. package/src/components/BackupCodeLoginForm.tsx +489 -0
  11. package/src/components/BackupCodesForm.tsx +287 -0
  12. package/src/components/CategoryMenu.tsx +155 -0
  13. package/src/components/ChangePasswordForm.tsx +273 -0
  14. package/src/components/ConfirmationDialog.tsx +48 -0
  15. package/src/components/CurrencyCodeSelector.tsx +60 -0
  16. package/src/components/CurrencyInput.tsx +80 -0
  17. package/src/components/DashboardPage.tsx +24 -0
  18. package/src/components/DropdownMenu.tsx +105 -0
  19. package/src/components/ExpirationSecondsSelector.tsx +60 -0
  20. package/src/components/FakeEmailAdminPanel.tsx +374 -0
  21. package/src/components/Flag.tsx +52 -0
  22. package/src/components/ForgotPasswordForm.tsx +174 -0
  23. package/src/components/LoginForm.tsx +468 -0
  24. package/src/components/LogoutPage.tsx +21 -0
  25. package/src/components/RegisterForm.tsx +1169 -0
  26. package/src/components/ResetPasswordForm.tsx +247 -0
  27. package/src/components/SideMenu.tsx +46 -0
  28. package/src/components/SideMenuListItem.tsx +75 -0
  29. package/src/components/T.tsx +24 -0
  30. package/src/components/TDiv.tsx +26 -0
  31. package/src/components/TImgAlt.tsx +28 -0
  32. package/src/components/TopMenu.tsx +252 -0
  33. package/src/components/TotpSetupForm.tsx +188 -0
  34. package/src/components/TotpVerificationForm.tsx +148 -0
  35. package/src/components/TranslatedTitle.tsx +31 -0
  36. package/src/components/UserLanguageSelector.tsx +45 -0
  37. package/src/components/UserMenu.tsx +15 -0
  38. package/src/components/UserSettingsForm.tsx +904 -0
  39. package/src/components/VerifyEmailPage.tsx +222 -0
  40. package/src/components/__tests__/RegisterForm.totp.spec.tsx +377 -0
  41. package/src/components/__tests__/TotpSetupForm.spec.tsx +258 -0
  42. package/src/components/__tests__/TotpVerificationForm.spec.tsx +259 -0
  43. package/src/components/__tests__/UserSettingsForm.totp.spec.tsx +396 -0
  44. package/src/components/{index.d.ts → index.ts} +1 -1
  45. package/src/contexts/AuthProvider.spec.tsx +1284 -0
  46. package/src/contexts/AuthProvider.tsx +977 -0
  47. package/src/contexts/I18nProvider.tsx +164 -0
  48. package/src/contexts/MenuContext.tsx +426 -0
  49. package/src/contexts/SuiteConfigProvider.tsx +93 -0
  50. package/src/contexts/ThemeProvider.tsx +67 -0
  51. package/src/contexts/{index.d.ts → index.ts} +0 -1
  52. package/src/hooks/{index.d.ts → index.ts} +0 -1
  53. package/src/hooks/useAuthenticatedApi.tsx +67 -0
  54. package/src/hooks/useBackupCodes.ts +105 -0
  55. package/src/hooks/useEmailVerification.ts +54 -0
  56. package/src/hooks/useExpiringValue.ts +78 -0
  57. package/src/hooks/useLocalStorage.ts +18 -0
  58. package/src/hooks/useUserSettings.ts +271 -0
  59. package/src/{index.d.ts → index.ts} +1 -1
  60. package/src/interfaces/IAppConfig.ts +7 -0
  61. package/src/interfaces/ICategoryConfig.ts +41 -0
  62. package/src/interfaces/IMenuConfig.ts +28 -0
  63. package/src/interfaces/IMenuOption.ts +79 -0
  64. package/src/interfaces/{index.d.ts → index.ts} +0 -1
  65. package/src/services/__mocks__/authService.ts +14 -0
  66. package/src/services/__tests__/authService.totp.property.spec.ts +360 -0
  67. package/src/services/__tests__/authService.totp.spec.ts +439 -0
  68. package/src/services/api.ts +13 -0
  69. package/src/services/authService.ts +692 -0
  70. package/src/services/authenticatedApi.ts +17 -0
  71. package/src/services/index.ts +3 -0
  72. package/src/types/MenuType.ts +15 -0
  73. package/src/types/expirationSeconds.ts +18 -0
  74. package/src/types/index.ts +1 -0
  75. package/src/types/translation.ts +20 -0
  76. package/src/wrappers/BackupCodeLoginWrapper.tsx +34 -0
  77. package/src/wrappers/BackupCodesWrapper.tsx +28 -0
  78. package/src/wrappers/ChangePasswordFormWrapper.tsx +34 -0
  79. package/src/wrappers/ForgotPasswordFormWrapper.tsx +45 -0
  80. package/src/wrappers/LoginFormWrapper.tsx +108 -0
  81. package/src/wrappers/LogoutPageWrapper.tsx +30 -0
  82. package/src/wrappers/RegisterFormWrapper.tsx +109 -0
  83. package/src/wrappers/ResetPasswordFormWrapper.tsx +57 -0
  84. package/src/wrappers/UserSettingsFormWrapper.tsx +140 -0
  85. package/src/wrappers/VerifyEmailPageWrapper.tsx +27 -0
  86. package/src/wrappers/__tests__/LoginFormWrapper.totp.spec.tsx +339 -0
  87. package/src/wrappers/{index.d.ts → index.tsx} +10 -1
  88. package/src/auth/AdminRoute.d.ts +0 -8
  89. package/src/auth/AdminRoute.d.ts.map +0 -1
  90. package/src/auth/AdminRoute.js +0 -28
  91. package/src/auth/Private.d.ts +0 -6
  92. package/src/auth/Private.d.ts.map +0 -1
  93. package/src/auth/Private.js +0 -14
  94. package/src/auth/PrivateRoute.d.ts +0 -8
  95. package/src/auth/PrivateRoute.d.ts.map +0 -1
  96. package/src/auth/PrivateRoute.js +0 -23
  97. package/src/auth/UnAuth.d.ts +0 -6
  98. package/src/auth/UnAuth.d.ts.map +0 -1
  99. package/src/auth/UnAuth.js +0 -14
  100. package/src/auth/UnAuthRoute.d.ts +0 -8
  101. package/src/auth/UnAuthRoute.d.ts.map +0 -1
  102. package/src/auth/UnAuthRoute.js +0 -22
  103. package/src/auth/index.d.ts.map +0 -1
  104. package/src/auth/index.js +0 -12
  105. package/src/components/ApiAccess.d.ts +0 -16
  106. package/src/components/ApiAccess.d.ts.map +0 -1
  107. package/src/components/ApiAccess.js +0 -77
  108. package/src/components/BackupCodeLoginForm.d.ts +0 -43
  109. package/src/components/BackupCodeLoginForm.d.ts.map +0 -1
  110. package/src/components/BackupCodeLoginForm.js +0 -139
  111. package/src/components/BackupCodesForm.d.ts +0 -26
  112. package/src/components/BackupCodesForm.d.ts.map +0 -1
  113. package/src/components/BackupCodesForm.js +0 -120
  114. package/src/components/CategoryMenu.d.ts +0 -17
  115. package/src/components/CategoryMenu.d.ts.map +0 -1
  116. package/src/components/CategoryMenu.js +0 -65
  117. package/src/components/ChangePasswordForm.d.ts +0 -26
  118. package/src/components/ChangePasswordForm.d.ts.map +0 -1
  119. package/src/components/ChangePasswordForm.js +0 -78
  120. package/src/components/ConfirmationDialog.d.ts +0 -13
  121. package/src/components/ConfirmationDialog.d.ts.map +0 -1
  122. package/src/components/ConfirmationDialog.js +0 -10
  123. package/src/components/CurrencyCodeSelector.d.ts +0 -9
  124. package/src/components/CurrencyCodeSelector.d.ts.map +0 -1
  125. package/src/components/CurrencyCodeSelector.js +0 -31
  126. package/src/components/CurrencyInput.d.ts +0 -13
  127. package/src/components/CurrencyInput.d.ts.map +0 -1
  128. package/src/components/CurrencyInput.js +0 -22
  129. package/src/components/DashboardPage.d.ts +0 -8
  130. package/src/components/DashboardPage.d.ts.map +0 -1
  131. package/src/components/DashboardPage.js +0 -10
  132. package/src/components/DropdownMenu.d.ts +0 -13
  133. package/src/components/DropdownMenu.d.ts.map +0 -1
  134. package/src/components/DropdownMenu.js +0 -63
  135. package/src/components/ExpirationSecondsSelector.d.ts +0 -13
  136. package/src/components/ExpirationSecondsSelector.d.ts.map +0 -1
  137. package/src/components/ExpirationSecondsSelector.js +0 -32
  138. package/src/components/FakeEmailAdminPanel.d.ts +0 -23
  139. package/src/components/FakeEmailAdminPanel.d.ts.map +0 -1
  140. package/src/components/FakeEmailAdminPanel.js +0 -147
  141. package/src/components/Flag.d.ts +0 -20
  142. package/src/components/Flag.d.ts.map +0 -1
  143. package/src/components/Flag.js +0 -43
  144. package/src/components/ForgotPasswordForm.d.ts +0 -18
  145. package/src/components/ForgotPasswordForm.d.ts.map +0 -1
  146. package/src/components/ForgotPasswordForm.js +0 -61
  147. package/src/components/LoginForm.d.ts +0 -44
  148. package/src/components/LoginForm.d.ts.map +0 -1
  149. package/src/components/LoginForm.js +0 -123
  150. package/src/components/LogoutPage.d.ts +0 -8
  151. package/src/components/LogoutPage.d.ts.map +0 -1
  152. package/src/components/LogoutPage.js +0 -16
  153. package/src/components/RegisterForm.d.ts +0 -100
  154. package/src/components/RegisterForm.d.ts.map +0 -1
  155. package/src/components/RegisterForm.js +0 -306
  156. package/src/components/ResetPasswordForm.d.ts +0 -23
  157. package/src/components/ResetPasswordForm.d.ts.map +0 -1
  158. package/src/components/ResetPasswordForm.js +0 -78
  159. package/src/components/SideMenu.d.ts +0 -8
  160. package/src/components/SideMenu.d.ts.map +0 -1
  161. package/src/components/SideMenu.js +0 -25
  162. package/src/components/SideMenuListItem.d.ts +0 -13
  163. package/src/components/SideMenuListItem.d.ts.map +0 -1
  164. package/src/components/SideMenuListItem.js +0 -44
  165. package/src/components/T.d.ts +0 -7
  166. package/src/components/T.d.ts.map +0 -1
  167. package/src/components/T.js +0 -13
  168. package/src/components/TDiv.d.ts +0 -9
  169. package/src/components/TDiv.d.ts.map +0 -1
  170. package/src/components/TDiv.js +0 -14
  171. package/src/components/TImgAlt.d.ts +0 -10
  172. package/src/components/TImgAlt.d.ts.map +0 -1
  173. package/src/components/TImgAlt.js +0 -14
  174. package/src/components/TopMenu.d.ts +0 -50
  175. package/src/components/TopMenu.d.ts.map +0 -1
  176. package/src/components/TopMenu.js +0 -79
  177. package/src/components/TotpSetupForm.d.ts +0 -24
  178. package/src/components/TotpSetupForm.d.ts.map +0 -1
  179. package/src/components/TotpSetupForm.js +0 -82
  180. package/src/components/TotpVerificationForm.d.ts +0 -23
  181. package/src/components/TotpVerificationForm.d.ts.map +0 -1
  182. package/src/components/TotpVerificationForm.js +0 -66
  183. package/src/components/TranslatedTitle.d.ts +0 -8
  184. package/src/components/TranslatedTitle.d.ts.map +0 -1
  185. package/src/components/TranslatedTitle.js +0 -15
  186. package/src/components/UserLanguageSelector.d.ts +0 -4
  187. package/src/components/UserLanguageSelector.d.ts.map +0 -1
  188. package/src/components/UserLanguageSelector.js +0 -31
  189. package/src/components/UserMenu.d.ts +0 -4
  190. package/src/components/UserMenu.d.ts.map +0 -1
  191. package/src/components/UserMenu.js +0 -12
  192. package/src/components/UserSettingsForm.d.ts +0 -113
  193. package/src/components/UserSettingsForm.d.ts.map +0 -1
  194. package/src/components/UserSettingsForm.js +0 -269
  195. package/src/components/VerifyEmailPage.d.ts +0 -24
  196. package/src/components/VerifyEmailPage.d.ts.map +0 -1
  197. package/src/components/VerifyEmailPage.js +0 -81
  198. package/src/components/index.d.ts.map +0 -1
  199. package/src/components/index.js +0 -35
  200. package/src/contexts/AuthProvider.d.ts +0 -186
  201. package/src/contexts/AuthProvider.d.ts.map +0 -1
  202. package/src/contexts/AuthProvider.js +0 -515
  203. package/src/contexts/I18nProvider.d.ts +0 -27
  204. package/src/contexts/I18nProvider.d.ts.map +0 -1
  205. package/src/contexts/I18nProvider.js +0 -60
  206. package/src/contexts/MenuContext.d.ts +0 -20
  207. package/src/contexts/MenuContext.d.ts.map +0 -1
  208. package/src/contexts/MenuContext.js +0 -275
  209. package/src/contexts/SuiteConfigProvider.d.ts +0 -44
  210. package/src/contexts/SuiteConfigProvider.d.ts.map +0 -1
  211. package/src/contexts/SuiteConfigProvider.js +0 -43
  212. package/src/contexts/ThemeProvider.d.ts +0 -15
  213. package/src/contexts/ThemeProvider.d.ts.map +0 -1
  214. package/src/contexts/ThemeProvider.js +0 -36
  215. package/src/contexts/index.d.ts.map +0 -1
  216. package/src/contexts/index.js +0 -8
  217. package/src/hooks/index.d.ts.map +0 -1
  218. package/src/hooks/index.js +0 -9
  219. package/src/hooks/useAuthenticatedApi.d.ts +0 -34
  220. package/src/hooks/useAuthenticatedApi.d.ts.map +0 -1
  221. package/src/hooks/useAuthenticatedApi.js +0 -46
  222. package/src/hooks/useBackupCodes.d.ts +0 -15
  223. package/src/hooks/useBackupCodes.d.ts.map +0 -1
  224. package/src/hooks/useBackupCodes.js +0 -74
  225. package/src/hooks/useEmailVerification.d.ts +0 -10
  226. package/src/hooks/useEmailVerification.d.ts.map +0 -1
  227. package/src/hooks/useEmailVerification.js +0 -40
  228. package/src/hooks/useExpiringValue.d.ts +0 -14
  229. package/src/hooks/useExpiringValue.d.ts.map +0 -1
  230. package/src/hooks/useExpiringValue.js +0 -53
  231. package/src/hooks/useLocalStorage.d.ts +0 -2
  232. package/src/hooks/useLocalStorage.d.ts.map +0 -1
  233. package/src/hooks/useLocalStorage.js +0 -15
  234. package/src/hooks/useUserSettings.d.ts +0 -48
  235. package/src/hooks/useUserSettings.d.ts.map +0 -1
  236. package/src/hooks/useUserSettings.js +0 -171
  237. package/src/index.d.ts.map +0 -1
  238. package/src/index.js +0 -12
  239. package/src/interfaces/IAppConfig.d.ts +0 -8
  240. package/src/interfaces/IAppConfig.d.ts.map +0 -1
  241. package/src/interfaces/IAppConfig.js +0 -2
  242. package/src/interfaces/ICategoryConfig.d.ts +0 -41
  243. package/src/interfaces/ICategoryConfig.d.ts.map +0 -1
  244. package/src/interfaces/ICategoryConfig.js +0 -2
  245. package/src/interfaces/IMenuConfig.d.ts +0 -28
  246. package/src/interfaces/IMenuConfig.d.ts.map +0 -1
  247. package/src/interfaces/IMenuConfig.js +0 -2
  248. package/src/interfaces/IMenuOption.d.ts +0 -82
  249. package/src/interfaces/IMenuOption.d.ts.map +0 -1
  250. package/src/interfaces/IMenuOption.js +0 -2
  251. package/src/interfaces/index.d.ts.map +0 -1
  252. package/src/interfaces/index.js +0 -7
  253. package/src/services/__mocks__/authService.d.ts +0 -21
  254. package/src/services/__mocks__/authService.d.ts.map +0 -1
  255. package/src/services/__mocks__/authService.js +0 -15
  256. package/src/services/api.d.ts +0 -3
  257. package/src/services/api.d.ts.map +0 -1
  258. package/src/services/api.js +0 -14
  259. package/src/services/authService.d.ts +0 -126
  260. package/src/services/authService.d.ts.map +0 -1
  261. package/src/services/authService.js +0 -471
  262. package/src/services/authenticatedApi.d.ts +0 -3
  263. package/src/services/authenticatedApi.d.ts.map +0 -1
  264. package/src/services/authenticatedApi.js +0 -18
  265. package/src/services/index.d.ts +0 -4
  266. package/src/services/index.d.ts.map +0 -1
  267. package/src/services/index.js +0 -6
  268. package/src/types/MenuType.d.ts +0 -11
  269. package/src/types/MenuType.d.ts.map +0 -1
  270. package/src/types/MenuType.js +0 -12
  271. package/src/types/expirationSeconds.d.ts +0 -3
  272. package/src/types/expirationSeconds.d.ts.map +0 -1
  273. package/src/types/expirationSeconds.js +0 -17
  274. package/src/types/index.d.ts +0 -2
  275. package/src/types/index.d.ts.map +0 -1
  276. package/src/types/index.js +0 -4
  277. package/src/types/translation.d.ts +0 -10
  278. package/src/types/translation.d.ts.map +0 -1
  279. package/src/types/translation.js +0 -9
  280. package/src/wrappers/BackupCodeLoginWrapper.d.ts +0 -8
  281. package/src/wrappers/BackupCodeLoginWrapper.d.ts.map +0 -1
  282. package/src/wrappers/BackupCodeLoginWrapper.js +0 -20
  283. package/src/wrappers/BackupCodesWrapper.d.ts +0 -7
  284. package/src/wrappers/BackupCodesWrapper.d.ts.map +0 -1
  285. package/src/wrappers/BackupCodesWrapper.js +0 -17
  286. package/src/wrappers/ChangePasswordFormWrapper.d.ts +0 -8
  287. package/src/wrappers/ChangePasswordFormWrapper.d.ts.map +0 -1
  288. package/src/wrappers/ChangePasswordFormWrapper.js +0 -21
  289. package/src/wrappers/ForgotPasswordFormWrapper.d.ts +0 -8
  290. package/src/wrappers/ForgotPasswordFormWrapper.d.ts.map +0 -1
  291. package/src/wrappers/ForgotPasswordFormWrapper.js +0 -29
  292. package/src/wrappers/LoginFormWrapper.d.ts +0 -21
  293. package/src/wrappers/LoginFormWrapper.d.ts.map +0 -1
  294. package/src/wrappers/LoginFormWrapper.js +0 -72
  295. package/src/wrappers/LogoutPageWrapper.d.ts +0 -9
  296. package/src/wrappers/LogoutPageWrapper.d.ts.map +0 -1
  297. package/src/wrappers/LogoutPageWrapper.js +0 -21
  298. package/src/wrappers/RegisterFormWrapper.d.ts +0 -20
  299. package/src/wrappers/RegisterFormWrapper.d.ts.map +0 -1
  300. package/src/wrappers/RegisterFormWrapper.js +0 -51
  301. package/src/wrappers/ResetPasswordFormWrapper.d.ts +0 -9
  302. package/src/wrappers/ResetPasswordFormWrapper.d.ts.map +0 -1
  303. package/src/wrappers/ResetPasswordFormWrapper.js +0 -34
  304. package/src/wrappers/UserSettingsFormWrapper.d.ts +0 -29
  305. package/src/wrappers/UserSettingsFormWrapper.d.ts.map +0 -1
  306. package/src/wrappers/UserSettingsFormWrapper.js +0 -95
  307. package/src/wrappers/VerifyEmailPageWrapper.d.ts +0 -8
  308. package/src/wrappers/VerifyEmailPageWrapper.d.ts.map +0 -1
  309. package/src/wrappers/VerifyEmailPageWrapper.js +0 -21
  310. package/src/wrappers/index.d.ts.map +0 -1
  311. package/src/wrappers/index.js +0 -24
@@ -0,0 +1,468 @@
1
+ import {
2
+ Constants,
3
+ SuiteCoreComponentId,
4
+ SuiteCoreStringKey,
5
+ SuiteCoreStringKeyValue,
6
+ } from '@digitaldefiance/suite-core-lib';
7
+ import { Visibility, VisibilityOff } from '@mui/icons-material';
8
+ import {
9
+ Alert,
10
+ Box,
11
+ Button,
12
+ Container,
13
+ IconButton,
14
+ InputAdornment,
15
+ Link,
16
+ TextField,
17
+ Typography,
18
+ } from '@mui/material';
19
+ import { useFormik } from 'formik';
20
+ import { FC, useState } from 'react';
21
+ import * as Yup from 'yup';
22
+ import { useI18n } from '../contexts';
23
+
24
+ export interface LoginFormValues {
25
+ email?: string;
26
+ username?: string;
27
+ password?: string;
28
+ mnemonic?: string;
29
+ [key: string]: string | boolean | undefined;
30
+ }
31
+
32
+ export interface LoginFormProps {
33
+ onSubmit: (values: LoginFormValues) => Promise<void>;
34
+ loginType?: 'email' | 'username';
35
+ authType?: 'password' | 'mnemonic';
36
+ allowLoginTypeToggle?: boolean;
37
+ allowAuthTypeToggle?: boolean;
38
+ showForgotPassword?: boolean;
39
+ showSignUp?: boolean;
40
+ forgotPasswordLink?: string;
41
+ signUpLink?: string;
42
+ emailLabel?: string;
43
+ usernameLabel?: string;
44
+ passwordLabel?: string;
45
+ mnemonicLabel?: string;
46
+ signInButtonText?: string;
47
+ forgotPasswordText?: string;
48
+ signUpText?: string;
49
+ useUsernameText?: string;
50
+ useEmailText?: string;
51
+ useMnemonicText?: string;
52
+ usePasswordText?: string;
53
+ toggleVisibilityLabel?: string;
54
+ titleText?: string;
55
+ emailValidation?: Yup.StringSchema;
56
+ usernameValidation?: Yup.StringSchema;
57
+ passwordValidation?: Yup.StringSchema;
58
+ mnemonicValidation?: Yup.StringSchema;
59
+ additionalFields?: (
60
+ formik: ReturnType<typeof useFormik<LoginFormValues>>
61
+ ) => React.ReactNode;
62
+ additionalInitialValues?: Record<string, string | boolean>;
63
+ additionalValidation?: Record<string, Yup.Schema>;
64
+ }
65
+
66
+ export const LoginForm: FC<LoginFormProps> = ({
67
+ onSubmit,
68
+ loginType: initialLoginType = 'email',
69
+ authType: initialAuthType = 'password',
70
+ allowLoginTypeToggle = true,
71
+ allowAuthTypeToggle = true,
72
+ showForgotPassword = true,
73
+ showSignUp = true,
74
+ forgotPasswordLink = '/forgot-password',
75
+ signUpLink = '/register',
76
+ emailLabel,
77
+ usernameLabel,
78
+ passwordLabel,
79
+ mnemonicLabel,
80
+ signInButtonText,
81
+ forgotPasswordText,
82
+ signUpText,
83
+ useUsernameText,
84
+ useEmailText,
85
+ useMnemonicText,
86
+ usePasswordText,
87
+ toggleVisibilityLabel,
88
+ titleText,
89
+ emailValidation,
90
+ usernameValidation,
91
+ passwordValidation,
92
+ mnemonicValidation,
93
+ additionalFields,
94
+ additionalInitialValues = {},
95
+ additionalValidation = {},
96
+ }) => {
97
+ const { tComponent } = useI18n();
98
+ const [loginType, setLoginType] = useState<'email' | 'username'>(
99
+ initialLoginType
100
+ );
101
+ const [authType, setAuthType] = useState<'password' | 'mnemonic'>(
102
+ initialAuthType
103
+ );
104
+ const [showSecret, setShowSecret] = useState(false);
105
+
106
+ // Use translations with fallbacks
107
+ const labels = {
108
+ title:
109
+ titleText ||
110
+ tComponent<SuiteCoreStringKeyValue>(
111
+ SuiteCoreComponentId,
112
+ SuiteCoreStringKey.Login_Title
113
+ ),
114
+ email:
115
+ emailLabel ||
116
+ tComponent<SuiteCoreStringKeyValue>(
117
+ SuiteCoreComponentId,
118
+ SuiteCoreStringKey.Common_Email
119
+ ),
120
+ username:
121
+ usernameLabel ||
122
+ tComponent<SuiteCoreStringKeyValue>(
123
+ SuiteCoreComponentId,
124
+ SuiteCoreStringKey.Common_Username
125
+ ),
126
+ password:
127
+ passwordLabel ||
128
+ tComponent<SuiteCoreStringKeyValue>(
129
+ SuiteCoreComponentId,
130
+ SuiteCoreStringKey.Common_Password
131
+ ),
132
+ mnemonic:
133
+ mnemonicLabel ||
134
+ tComponent<SuiteCoreStringKeyValue>(
135
+ SuiteCoreComponentId,
136
+ SuiteCoreStringKey.Common_Mnemonic
137
+ ),
138
+ signIn:
139
+ signInButtonText ||
140
+ tComponent<SuiteCoreStringKeyValue>(
141
+ SuiteCoreComponentId,
142
+ SuiteCoreStringKey.SignInButton
143
+ ),
144
+ forgotPassword:
145
+ forgotPasswordText ||
146
+ tComponent<SuiteCoreStringKeyValue>(
147
+ SuiteCoreComponentId,
148
+ SuiteCoreStringKey.Login_ForgotPassword
149
+ ),
150
+ signUp:
151
+ signUpText ||
152
+ tComponent<SuiteCoreStringKeyValue>(
153
+ SuiteCoreComponentId,
154
+ SuiteCoreStringKey.Login_SignUp
155
+ ),
156
+ useUsername:
157
+ useUsernameText ||
158
+ tComponent<SuiteCoreStringKeyValue>(
159
+ SuiteCoreComponentId,
160
+ SuiteCoreStringKey.Login_UseUsername
161
+ ),
162
+ useEmail:
163
+ useEmailText ||
164
+ tComponent<SuiteCoreStringKeyValue>(
165
+ SuiteCoreComponentId,
166
+ SuiteCoreStringKey.Login_UseEmailAddress
167
+ ),
168
+ useMnemonic:
169
+ useMnemonicText ||
170
+ tComponent<SuiteCoreStringKeyValue>(
171
+ SuiteCoreComponentId,
172
+ SuiteCoreStringKey.Common_UseMnemonic
173
+ ),
174
+ usePassword:
175
+ usePasswordText ||
176
+ tComponent<SuiteCoreStringKeyValue>(
177
+ SuiteCoreComponentId,
178
+ SuiteCoreStringKey.Common_UsePassword
179
+ ),
180
+ toggleVisibility:
181
+ toggleVisibilityLabel ||
182
+ tComponent<SuiteCoreStringKeyValue>(
183
+ SuiteCoreComponentId,
184
+ SuiteCoreStringKey.TogglePasswordVisibility
185
+ ),
186
+ passwordAuthInfo: tComponent<SuiteCoreStringKeyValue>(
187
+ SuiteCoreComponentId,
188
+ SuiteCoreStringKey.Login_PasswordAuthInfo
189
+ ),
190
+ };
191
+
192
+ const validation = {
193
+ email:
194
+ emailValidation ||
195
+ Yup.string()
196
+ .email(
197
+ tComponent<SuiteCoreStringKeyValue>(
198
+ SuiteCoreComponentId,
199
+ SuiteCoreStringKey.Validation_InvalidEmail
200
+ )
201
+ )
202
+ .required(
203
+ tComponent<SuiteCoreStringKeyValue>(
204
+ SuiteCoreComponentId,
205
+ SuiteCoreStringKey.Validation_Required
206
+ )
207
+ ),
208
+ username:
209
+ usernameValidation ||
210
+ Yup.string()
211
+ .matches(
212
+ Constants.UsernameRegex,
213
+ tComponent<SuiteCoreStringKeyValue>(
214
+ SuiteCoreComponentId,
215
+ SuiteCoreStringKey.Validation_UsernameRegexErrorTemplate
216
+ )
217
+ )
218
+ .required(
219
+ tComponent<SuiteCoreStringKeyValue>(
220
+ SuiteCoreComponentId,
221
+ SuiteCoreStringKey.Validation_Required
222
+ )
223
+ ),
224
+ password:
225
+ passwordValidation ||
226
+ Yup.string()
227
+ .min(
228
+ 1,
229
+ tComponent<SuiteCoreStringKeyValue>(
230
+ SuiteCoreComponentId,
231
+ SuiteCoreStringKey.Validation_Required
232
+ )
233
+ )
234
+ .required(
235
+ tComponent<SuiteCoreStringKeyValue>(
236
+ SuiteCoreComponentId,
237
+ SuiteCoreStringKey.Validation_Required
238
+ )
239
+ ),
240
+ mnemonic:
241
+ mnemonicValidation ||
242
+ Yup.string()
243
+ .matches(
244
+ Constants.MnemonicRegex,
245
+ tComponent<SuiteCoreStringKeyValue>(
246
+ SuiteCoreComponentId,
247
+ SuiteCoreStringKey.Validation_InvalidMnemonic
248
+ )
249
+ )
250
+ .required(
251
+ tComponent<SuiteCoreStringKeyValue>(
252
+ SuiteCoreComponentId,
253
+ SuiteCoreStringKey.Validation_Required
254
+ )
255
+ ),
256
+ };
257
+
258
+ const formik = useFormik<LoginFormValues>({
259
+ initialValues: {
260
+ email: '',
261
+ username: '',
262
+ mnemonic: '',
263
+ password: '',
264
+ ...additionalInitialValues,
265
+ },
266
+ validationSchema: Yup.object({
267
+ [loginType]:
268
+ loginType === 'email' ? validation.email : validation.username,
269
+ ...(authType === 'mnemonic'
270
+ ? { mnemonic: validation.mnemonic }
271
+ : { password: validation.password }),
272
+ ...additionalValidation,
273
+ }),
274
+ enableReinitialize: true,
275
+ onSubmit: async (values, { setStatus }) => {
276
+ try {
277
+ setStatus(null);
278
+ await onSubmit(values);
279
+ } catch (error: unknown) {
280
+ const err = error as { message?: string };
281
+ setStatus(
282
+ err.message ||
283
+ tComponent<SuiteCoreStringKeyValue>(
284
+ SuiteCoreComponentId,
285
+ SuiteCoreStringKey.Common_UnexpectedError
286
+ )
287
+ );
288
+ throw error;
289
+ }
290
+ },
291
+ });
292
+
293
+ return (
294
+ <Container component="main" maxWidth="xs">
295
+ <Box
296
+ sx={{
297
+ marginTop: 8,
298
+ display: 'flex',
299
+ flexDirection: 'column',
300
+ alignItems: 'center',
301
+ }}
302
+ >
303
+ <Typography component="h1" variant="h5">
304
+ {labels.title}
305
+ </Typography>
306
+ <Box
307
+ component="form"
308
+ onSubmit={formik.handleSubmit}
309
+ sx={{ mt: 1, width: '100%' }}
310
+ >
311
+ {formik.status && (
312
+ <Alert severity="error" sx={{ mb: 2 }}>
313
+ {formik.status}
314
+ </Alert>
315
+ )}
316
+ <TextField
317
+ margin="normal"
318
+ fullWidth
319
+ id={loginType}
320
+ label={loginType === 'email' ? labels.email : labels.username}
321
+ name={loginType}
322
+ autoComplete={loginType === 'email' ? 'email' : 'username'}
323
+ autoFocus
324
+ value={
325
+ loginType === 'email'
326
+ ? formik.values.email
327
+ : formik.values.username
328
+ }
329
+ onChange={formik.handleChange}
330
+ error={
331
+ formik.touched[loginType] && Boolean(formik.errors[loginType])
332
+ }
333
+ helperText={formik.touched[loginType] && formik.errors[loginType]}
334
+ />
335
+ {authType === 'password' ? (
336
+ <>
337
+ <TextField
338
+ margin="normal"
339
+ required
340
+ fullWidth
341
+ name="password"
342
+ label={labels.password}
343
+ id="password"
344
+ type={showSecret ? 'text' : 'password'}
345
+ value={formik.values.password}
346
+ onChange={formik.handleChange}
347
+ error={
348
+ formik.touched.password && Boolean(formik.errors.password)
349
+ }
350
+ helperText={formik.touched.password && formik.errors.password}
351
+ slotProps={{
352
+ input: {
353
+ endAdornment: (
354
+ <InputAdornment position="end">
355
+ <IconButton
356
+ aria-label={labels.toggleVisibility}
357
+ onClick={() => setShowSecret(!showSecret)}
358
+ edge="end"
359
+ >
360
+ {showSecret ? <VisibilityOff /> : <Visibility />}
361
+ </IconButton>
362
+ </InputAdornment>
363
+ ),
364
+ },
365
+ }}
366
+ />
367
+ <Alert severity="info" sx={{ mt: 1 }}>
368
+ {labels.passwordAuthInfo}
369
+ </Alert>
370
+ </>
371
+ ) : (
372
+ <TextField
373
+ margin="normal"
374
+ required
375
+ fullWidth
376
+ name="mnemonic"
377
+ label={labels.mnemonic}
378
+ id="mnemonic"
379
+ multiline
380
+ rows={3}
381
+ autoComplete="section-mnemonic current-password"
382
+ value={formik.values.mnemonic}
383
+ onChange={formik.handleChange}
384
+ error={formik.touched.mnemonic && Boolean(formik.errors.mnemonic)}
385
+ helperText={formik.touched.mnemonic && formik.errors.mnemonic}
386
+ type={showSecret ? 'text' : 'password'}
387
+ slotProps={{
388
+ input: {
389
+ endAdornment: (
390
+ <InputAdornment position="end">
391
+ <IconButton
392
+ aria-label={labels.toggleVisibility}
393
+ onClick={() => setShowSecret(!showSecret)}
394
+ edge="end"
395
+ >
396
+ {showSecret ? <VisibilityOff /> : <Visibility />}
397
+ </IconButton>
398
+ </InputAdornment>
399
+ ),
400
+ },
401
+ }}
402
+ />
403
+ )}
404
+ {additionalFields && additionalFields(formik)}
405
+ <Button
406
+ type="submit"
407
+ fullWidth
408
+ variant="contained"
409
+ sx={{ mt: 3, mb: 2 }}
410
+ disabled={formik.isSubmitting}
411
+ >
412
+ {labels.signIn}
413
+ </Button>
414
+ {(showForgotPassword || showSignUp) && (
415
+ <Box sx={{ display: 'flex', justifyContent: 'space-between' }}>
416
+ {showForgotPassword && (
417
+ <Link href={forgotPasswordLink} variant="body2">
418
+ {labels.forgotPassword}
419
+ </Link>
420
+ )}
421
+ {showSignUp && (
422
+ <Link href={signUpLink} variant="body2">
423
+ {labels.signUp}
424
+ </Link>
425
+ )}
426
+ </Box>
427
+ )}
428
+ {(allowLoginTypeToggle || allowAuthTypeToggle) && (
429
+ <Box sx={{ display: 'flex', gap: 1, mt: 2 }}>
430
+ {allowLoginTypeToggle && (
431
+ <Button
432
+ fullWidth
433
+ variant="text"
434
+ onClick={() => {
435
+ const newType =
436
+ loginType === 'email' ? 'username' : 'email';
437
+ formik.setFieldValue(loginType, '');
438
+ setLoginType(newType);
439
+ }}
440
+ >
441
+ {loginType === 'email' ? labels.useUsername : labels.useEmail}
442
+ </Button>
443
+ )}
444
+ {allowAuthTypeToggle && (
445
+ <Button
446
+ fullWidth
447
+ variant="text"
448
+ onClick={() => {
449
+ const newType =
450
+ authType === 'password' ? 'mnemonic' : 'password';
451
+ formik.setFieldValue(authType, '');
452
+ setAuthType(newType);
453
+ }}
454
+ >
455
+ {authType === 'password'
456
+ ? labels.useMnemonic
457
+ : labels.usePassword}
458
+ </Button>
459
+ )}
460
+ </Box>
461
+ )}
462
+ </Box>
463
+ </Box>
464
+ </Container>
465
+ );
466
+ };
467
+
468
+ export default LoginForm;
@@ -0,0 +1,21 @@
1
+ import { useEffect } from 'react';
2
+
3
+ export interface LogoutPageProps {
4
+ onLogout: () => Promise<void> | void;
5
+ onNavigate?: (path: string) => void;
6
+ redirectTo?: string;
7
+ }
8
+
9
+ export const LogoutPage = ({ onLogout, onNavigate, redirectTo = '/login' }: LogoutPageProps) => {
10
+ useEffect(() => {
11
+ const performLogout = async () => {
12
+ await onLogout();
13
+ onNavigate?.(redirectTo);
14
+ };
15
+ performLogout();
16
+ }, [onLogout, onNavigate, redirectTo]);
17
+
18
+ return null;
19
+ };
20
+
21
+ export default LogoutPage;