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

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 (314) hide show
  1. package/package.json +5 -4
  2. package/src/auth/AdminRoute.d.ts +8 -0
  3. package/src/auth/AdminRoute.d.ts.map +1 -0
  4. package/src/auth/AdminRoute.js +28 -0
  5. package/src/auth/Private.d.ts +6 -0
  6. package/src/auth/Private.d.ts.map +1 -0
  7. package/src/auth/Private.js +14 -0
  8. package/src/auth/PrivateRoute.d.ts +8 -0
  9. package/src/auth/PrivateRoute.d.ts.map +1 -0
  10. package/src/auth/PrivateRoute.js +23 -0
  11. package/src/auth/UnAuth.d.ts +6 -0
  12. package/src/auth/UnAuth.d.ts.map +1 -0
  13. package/src/auth/UnAuth.js +14 -0
  14. package/src/auth/UnAuthRoute.d.ts +8 -0
  15. package/src/auth/UnAuthRoute.d.ts.map +1 -0
  16. package/src/auth/UnAuthRoute.js +22 -0
  17. package/src/auth/{index.ts → index.d.ts} +3 -2
  18. package/src/auth/index.d.ts.map +1 -0
  19. package/src/auth/index.js +12 -0
  20. package/src/components/ApiAccess.d.ts +16 -0
  21. package/src/components/ApiAccess.d.ts.map +1 -0
  22. package/src/components/ApiAccess.js +77 -0
  23. package/src/components/BackupCodeLoginForm.d.ts +43 -0
  24. package/src/components/BackupCodeLoginForm.d.ts.map +1 -0
  25. package/src/components/BackupCodeLoginForm.js +139 -0
  26. package/src/components/BackupCodesForm.d.ts +26 -0
  27. package/src/components/BackupCodesForm.d.ts.map +1 -0
  28. package/src/components/BackupCodesForm.js +120 -0
  29. package/src/components/CategoryMenu.d.ts +17 -0
  30. package/src/components/CategoryMenu.d.ts.map +1 -0
  31. package/src/components/CategoryMenu.js +65 -0
  32. package/src/components/ChangePasswordForm.d.ts +26 -0
  33. package/src/components/ChangePasswordForm.d.ts.map +1 -0
  34. package/src/components/ChangePasswordForm.js +78 -0
  35. package/src/components/ConfirmationDialog.d.ts +13 -0
  36. package/src/components/ConfirmationDialog.d.ts.map +1 -0
  37. package/src/components/ConfirmationDialog.js +10 -0
  38. package/src/components/CurrencyCodeSelector.d.ts +9 -0
  39. package/src/components/CurrencyCodeSelector.d.ts.map +1 -0
  40. package/src/components/CurrencyCodeSelector.js +31 -0
  41. package/src/components/CurrencyInput.d.ts +13 -0
  42. package/src/components/CurrencyInput.d.ts.map +1 -0
  43. package/src/components/CurrencyInput.js +22 -0
  44. package/src/components/DashboardPage.d.ts +8 -0
  45. package/src/components/DashboardPage.d.ts.map +1 -0
  46. package/src/components/DashboardPage.js +10 -0
  47. package/src/components/DropdownMenu.d.ts +13 -0
  48. package/src/components/DropdownMenu.d.ts.map +1 -0
  49. package/src/components/DropdownMenu.js +63 -0
  50. package/src/components/ExpirationSecondsSelector.d.ts +13 -0
  51. package/src/components/ExpirationSecondsSelector.d.ts.map +1 -0
  52. package/src/components/ExpirationSecondsSelector.js +32 -0
  53. package/src/components/FakeEmailAdminPanel.d.ts +23 -0
  54. package/src/components/FakeEmailAdminPanel.d.ts.map +1 -0
  55. package/src/components/FakeEmailAdminPanel.js +147 -0
  56. package/src/components/Flag.d.ts +20 -0
  57. package/src/components/Flag.d.ts.map +1 -0
  58. package/src/components/Flag.js +43 -0
  59. package/src/components/ForgotPasswordForm.d.ts +18 -0
  60. package/src/components/ForgotPasswordForm.d.ts.map +1 -0
  61. package/src/components/ForgotPasswordForm.js +61 -0
  62. package/src/components/LoginForm.d.ts +44 -0
  63. package/src/components/LoginForm.d.ts.map +1 -0
  64. package/src/components/LoginForm.js +123 -0
  65. package/src/components/LogoutPage.d.ts +8 -0
  66. package/src/components/LogoutPage.d.ts.map +1 -0
  67. package/src/components/LogoutPage.js +16 -0
  68. package/src/components/RegisterForm.d.ts +100 -0
  69. package/src/components/RegisterForm.d.ts.map +1 -0
  70. package/src/components/RegisterForm.js +306 -0
  71. package/src/components/ResetPasswordForm.d.ts +23 -0
  72. package/src/components/ResetPasswordForm.d.ts.map +1 -0
  73. package/src/components/ResetPasswordForm.js +78 -0
  74. package/src/components/SideMenu.d.ts +8 -0
  75. package/src/components/SideMenu.d.ts.map +1 -0
  76. package/src/components/SideMenu.js +25 -0
  77. package/src/components/SideMenuListItem.d.ts +13 -0
  78. package/src/components/SideMenuListItem.d.ts.map +1 -0
  79. package/src/components/SideMenuListItem.js +44 -0
  80. package/src/components/T.d.ts +7 -0
  81. package/src/components/T.d.ts.map +1 -0
  82. package/src/components/T.js +13 -0
  83. package/src/components/TDiv.d.ts +9 -0
  84. package/src/components/TDiv.d.ts.map +1 -0
  85. package/src/components/TDiv.js +14 -0
  86. package/src/components/TImgAlt.d.ts +10 -0
  87. package/src/components/TImgAlt.d.ts.map +1 -0
  88. package/src/components/TImgAlt.js +14 -0
  89. package/src/components/TopMenu.d.ts +50 -0
  90. package/src/components/TopMenu.d.ts.map +1 -0
  91. package/src/components/TopMenu.js +79 -0
  92. package/src/components/TotpSetupForm.d.ts +24 -0
  93. package/src/components/TotpSetupForm.d.ts.map +1 -0
  94. package/src/components/TotpSetupForm.js +82 -0
  95. package/src/components/TotpVerificationForm.d.ts +23 -0
  96. package/src/components/TotpVerificationForm.d.ts.map +1 -0
  97. package/src/components/TotpVerificationForm.js +66 -0
  98. package/src/components/TranslatedTitle.d.ts +8 -0
  99. package/src/components/TranslatedTitle.d.ts.map +1 -0
  100. package/src/components/TranslatedTitle.js +15 -0
  101. package/src/components/UserLanguageSelector.d.ts +4 -0
  102. package/src/components/UserLanguageSelector.d.ts.map +1 -0
  103. package/src/components/UserLanguageSelector.js +31 -0
  104. package/src/components/UserMenu.d.ts +4 -0
  105. package/src/components/UserMenu.d.ts.map +1 -0
  106. package/src/components/UserMenu.js +12 -0
  107. package/src/components/UserSettingsForm.d.ts +113 -0
  108. package/src/components/UserSettingsForm.d.ts.map +1 -0
  109. package/src/components/UserSettingsForm.js +269 -0
  110. package/src/components/VerifyEmailPage.d.ts +24 -0
  111. package/src/components/VerifyEmailPage.d.ts.map +1 -0
  112. package/src/components/VerifyEmailPage.js +81 -0
  113. package/src/components/{index.ts → index.d.ts} +1 -1
  114. package/src/components/index.d.ts.map +1 -0
  115. package/src/components/index.js +35 -0
  116. package/src/contexts/AuthProvider.d.ts +19 -0
  117. package/src/contexts/AuthProvider.d.ts.map +1 -0
  118. package/src/contexts/AuthProvider.js +514 -0
  119. package/src/contexts/I18nProvider.d.ts +27 -0
  120. package/src/contexts/I18nProvider.d.ts.map +1 -0
  121. package/src/contexts/I18nProvider.js +60 -0
  122. package/src/contexts/MenuContext.d.ts +28 -0
  123. package/src/contexts/MenuContext.d.ts.map +1 -0
  124. package/src/contexts/MenuContext.js +307 -0
  125. package/src/contexts/SuiteConfigProvider.d.ts +44 -0
  126. package/src/contexts/SuiteConfigProvider.d.ts.map +1 -0
  127. package/src/contexts/SuiteConfigProvider.js +43 -0
  128. package/src/contexts/ThemeProvider.d.ts +15 -0
  129. package/src/contexts/ThemeProvider.d.ts.map +1 -0
  130. package/src/contexts/ThemeProvider.js +36 -0
  131. package/src/contexts/auth-context.d.ts +172 -0
  132. package/src/contexts/auth-context.d.ts.map +1 -0
  133. package/src/contexts/auth-context.js +13 -0
  134. package/src/contexts/{index.ts → index.d.ts} +1 -0
  135. package/src/contexts/index.d.ts.map +1 -0
  136. package/src/contexts/index.js +8 -0
  137. package/src/hooks/{index.ts → index.d.ts} +1 -0
  138. package/src/hooks/index.d.ts.map +1 -0
  139. package/src/hooks/index.js +9 -0
  140. package/src/hooks/useAuthenticatedApi.d.ts +34 -0
  141. package/src/hooks/useAuthenticatedApi.d.ts.map +1 -0
  142. package/src/hooks/useAuthenticatedApi.js +46 -0
  143. package/src/hooks/useBackupCodes.d.ts +15 -0
  144. package/src/hooks/useBackupCodes.d.ts.map +1 -0
  145. package/src/hooks/useBackupCodes.js +74 -0
  146. package/src/hooks/useEmailVerification.d.ts +10 -0
  147. package/src/hooks/useEmailVerification.d.ts.map +1 -0
  148. package/src/hooks/useEmailVerification.js +40 -0
  149. package/src/hooks/useExpiringValue.d.ts +14 -0
  150. package/src/hooks/useExpiringValue.d.ts.map +1 -0
  151. package/src/hooks/useExpiringValue.js +53 -0
  152. package/src/hooks/useLocalStorage.d.ts +2 -0
  153. package/src/hooks/useLocalStorage.d.ts.map +1 -0
  154. package/src/hooks/useLocalStorage.js +15 -0
  155. package/src/hooks/useUserSettings.d.ts +48 -0
  156. package/src/hooks/useUserSettings.d.ts.map +1 -0
  157. package/src/hooks/useUserSettings.js +171 -0
  158. package/src/{index.ts → index.d.ts} +1 -1
  159. package/src/index.d.ts.map +1 -0
  160. package/src/index.js +12 -0
  161. package/src/interfaces/IAppConfig.d.ts +8 -0
  162. package/src/interfaces/IAppConfig.d.ts.map +1 -0
  163. package/src/interfaces/IAppConfig.js +2 -0
  164. package/src/interfaces/ICategoryConfig.d.ts +41 -0
  165. package/src/interfaces/ICategoryConfig.d.ts.map +1 -0
  166. package/src/interfaces/ICategoryConfig.js +2 -0
  167. package/src/interfaces/IMenuConfig.d.ts +28 -0
  168. package/src/interfaces/IMenuConfig.d.ts.map +1 -0
  169. package/src/interfaces/IMenuConfig.js +2 -0
  170. package/src/interfaces/IMenuOption.d.ts +82 -0
  171. package/src/interfaces/IMenuOption.d.ts.map +1 -0
  172. package/src/interfaces/IMenuOption.js +2 -0
  173. package/src/interfaces/{index.ts → index.d.ts} +1 -0
  174. package/src/interfaces/index.d.ts.map +1 -0
  175. package/src/interfaces/index.js +7 -0
  176. package/src/services/__mocks__/authService.d.ts +21 -0
  177. package/src/services/__mocks__/authService.d.ts.map +1 -0
  178. package/src/services/__mocks__/authService.js +15 -0
  179. package/src/services/api.d.ts +3 -0
  180. package/src/services/api.d.ts.map +1 -0
  181. package/src/services/api.js +14 -0
  182. package/src/services/authService.d.ts +126 -0
  183. package/src/services/authService.d.ts.map +1 -0
  184. package/src/services/authService.js +471 -0
  185. package/src/services/authenticatedApi.d.ts +3 -0
  186. package/src/services/authenticatedApi.d.ts.map +1 -0
  187. package/src/services/authenticatedApi.js +18 -0
  188. package/src/services/index.d.ts +4 -0
  189. package/src/services/index.d.ts.map +1 -0
  190. package/src/services/index.js +6 -0
  191. package/src/types/MenuType.d.ts +11 -0
  192. package/src/types/MenuType.d.ts.map +1 -0
  193. package/src/types/MenuType.js +12 -0
  194. package/src/types/expirationSeconds.d.ts +3 -0
  195. package/src/types/expirationSeconds.d.ts.map +1 -0
  196. package/src/types/expirationSeconds.js +17 -0
  197. package/src/types/index.d.ts +2 -0
  198. package/src/types/index.d.ts.map +1 -0
  199. package/src/types/index.js +4 -0
  200. package/src/types/translation.d.ts +10 -0
  201. package/src/types/translation.d.ts.map +1 -0
  202. package/src/types/translation.js +9 -0
  203. package/src/wrappers/BackupCodeLoginWrapper.d.ts +8 -0
  204. package/src/wrappers/BackupCodeLoginWrapper.d.ts.map +1 -0
  205. package/src/wrappers/BackupCodeLoginWrapper.js +20 -0
  206. package/src/wrappers/BackupCodesWrapper.d.ts +7 -0
  207. package/src/wrappers/BackupCodesWrapper.d.ts.map +1 -0
  208. package/src/wrappers/BackupCodesWrapper.js +17 -0
  209. package/src/wrappers/ChangePasswordFormWrapper.d.ts +8 -0
  210. package/src/wrappers/ChangePasswordFormWrapper.d.ts.map +1 -0
  211. package/src/wrappers/ChangePasswordFormWrapper.js +21 -0
  212. package/src/wrappers/ForgotPasswordFormWrapper.d.ts +8 -0
  213. package/src/wrappers/ForgotPasswordFormWrapper.d.ts.map +1 -0
  214. package/src/wrappers/ForgotPasswordFormWrapper.js +29 -0
  215. package/src/wrappers/LoginFormWrapper.d.ts +21 -0
  216. package/src/wrappers/LoginFormWrapper.d.ts.map +1 -0
  217. package/src/wrappers/LoginFormWrapper.js +72 -0
  218. package/src/wrappers/LogoutPageWrapper.d.ts +9 -0
  219. package/src/wrappers/LogoutPageWrapper.d.ts.map +1 -0
  220. package/src/wrappers/LogoutPageWrapper.js +21 -0
  221. package/src/wrappers/RegisterFormWrapper.d.ts +20 -0
  222. package/src/wrappers/RegisterFormWrapper.d.ts.map +1 -0
  223. package/src/wrappers/RegisterFormWrapper.js +51 -0
  224. package/src/wrappers/ResetPasswordFormWrapper.d.ts +9 -0
  225. package/src/wrappers/ResetPasswordFormWrapper.d.ts.map +1 -0
  226. package/src/wrappers/ResetPasswordFormWrapper.js +34 -0
  227. package/src/wrappers/UserSettingsFormWrapper.d.ts +29 -0
  228. package/src/wrappers/UserSettingsFormWrapper.d.ts.map +1 -0
  229. package/src/wrappers/UserSettingsFormWrapper.js +95 -0
  230. package/src/wrappers/VerifyEmailPageWrapper.d.ts +8 -0
  231. package/src/wrappers/VerifyEmailPageWrapper.d.ts.map +1 -0
  232. package/src/wrappers/VerifyEmailPageWrapper.js +21 -0
  233. package/src/wrappers/{index.tsx → index.d.ts} +1 -10
  234. package/src/wrappers/index.d.ts.map +1 -0
  235. package/src/wrappers/index.js +24 -0
  236. package/LICENSE +0 -21
  237. package/src/auth/AdminRoute.tsx +0 -54
  238. package/src/auth/Private.tsx +0 -17
  239. package/src/auth/PrivateRoute.tsx +0 -28
  240. package/src/auth/UnAuth.tsx +0 -16
  241. package/src/auth/UnAuthRoute.tsx +0 -30
  242. package/src/components/ApiAccess.tsx +0 -175
  243. package/src/components/BackupCodeLoginForm.tsx +0 -489
  244. package/src/components/BackupCodesForm.tsx +0 -287
  245. package/src/components/CategoryMenu.tsx +0 -155
  246. package/src/components/ChangePasswordForm.tsx +0 -273
  247. package/src/components/ConfirmationDialog.tsx +0 -48
  248. package/src/components/CurrencyCodeSelector.tsx +0 -60
  249. package/src/components/CurrencyInput.tsx +0 -80
  250. package/src/components/DashboardPage.tsx +0 -24
  251. package/src/components/DropdownMenu.tsx +0 -105
  252. package/src/components/ExpirationSecondsSelector.tsx +0 -60
  253. package/src/components/FakeEmailAdminPanel.tsx +0 -374
  254. package/src/components/Flag.tsx +0 -52
  255. package/src/components/ForgotPasswordForm.tsx +0 -174
  256. package/src/components/LoginForm.tsx +0 -468
  257. package/src/components/LogoutPage.tsx +0 -21
  258. package/src/components/RegisterForm.tsx +0 -1169
  259. package/src/components/ResetPasswordForm.tsx +0 -247
  260. package/src/components/SideMenu.tsx +0 -46
  261. package/src/components/SideMenuListItem.tsx +0 -75
  262. package/src/components/T.tsx +0 -24
  263. package/src/components/TDiv.tsx +0 -26
  264. package/src/components/TImgAlt.tsx +0 -28
  265. package/src/components/TopMenu.tsx +0 -252
  266. package/src/components/TotpSetupForm.tsx +0 -188
  267. package/src/components/TotpVerificationForm.tsx +0 -148
  268. package/src/components/TranslatedTitle.tsx +0 -31
  269. package/src/components/UserLanguageSelector.tsx +0 -45
  270. package/src/components/UserMenu.tsx +0 -15
  271. package/src/components/UserSettingsForm.tsx +0 -904
  272. package/src/components/VerifyEmailPage.tsx +0 -222
  273. package/src/components/__tests__/RegisterForm.totp.spec.tsx +0 -377
  274. package/src/components/__tests__/TotpSetupForm.spec.tsx +0 -258
  275. package/src/components/__tests__/TotpVerificationForm.spec.tsx +0 -259
  276. package/src/components/__tests__/UserSettingsForm.totp.spec.tsx +0 -396
  277. package/src/contexts/AuthProvider.spec.tsx +0 -1284
  278. package/src/contexts/AuthProvider.tsx +0 -977
  279. package/src/contexts/I18nProvider.tsx +0 -164
  280. package/src/contexts/MenuContext.tsx +0 -426
  281. package/src/contexts/SuiteConfigProvider.tsx +0 -93
  282. package/src/contexts/ThemeProvider.tsx +0 -67
  283. package/src/hooks/useAuthenticatedApi.tsx +0 -67
  284. package/src/hooks/useBackupCodes.ts +0 -105
  285. package/src/hooks/useEmailVerification.ts +0 -54
  286. package/src/hooks/useExpiringValue.ts +0 -78
  287. package/src/hooks/useLocalStorage.ts +0 -18
  288. package/src/hooks/useUserSettings.ts +0 -271
  289. package/src/interfaces/IAppConfig.ts +0 -7
  290. package/src/interfaces/ICategoryConfig.ts +0 -41
  291. package/src/interfaces/IMenuConfig.ts +0 -28
  292. package/src/interfaces/IMenuOption.ts +0 -79
  293. package/src/services/__mocks__/authService.ts +0 -14
  294. package/src/services/__tests__/authService.totp.property.spec.ts +0 -360
  295. package/src/services/__tests__/authService.totp.spec.ts +0 -439
  296. package/src/services/api.ts +0 -13
  297. package/src/services/authService.ts +0 -692
  298. package/src/services/authenticatedApi.ts +0 -17
  299. package/src/services/index.ts +0 -3
  300. package/src/types/MenuType.ts +0 -15
  301. package/src/types/expirationSeconds.ts +0 -18
  302. package/src/types/index.ts +0 -1
  303. package/src/types/translation.ts +0 -20
  304. package/src/wrappers/BackupCodeLoginWrapper.tsx +0 -34
  305. package/src/wrappers/BackupCodesWrapper.tsx +0 -28
  306. package/src/wrappers/ChangePasswordFormWrapper.tsx +0 -34
  307. package/src/wrappers/ForgotPasswordFormWrapper.tsx +0 -45
  308. package/src/wrappers/LoginFormWrapper.tsx +0 -108
  309. package/src/wrappers/LogoutPageWrapper.tsx +0 -30
  310. package/src/wrappers/RegisterFormWrapper.tsx +0 -109
  311. package/src/wrappers/ResetPasswordFormWrapper.tsx +0 -57
  312. package/src/wrappers/UserSettingsFormWrapper.tsx +0 -140
  313. package/src/wrappers/VerifyEmailPageWrapper.tsx +0 -27
  314. package/src/wrappers/__tests__/LoginFormWrapper.totp.spec.tsx +0 -339
@@ -1,164 +0,0 @@
1
- import {
2
- GlobalActiveContext,
3
- IActiveContext,
4
- LanguageRegistry,
5
- } from '@digitaldefiance/i18n-lib';
6
- import {
7
- createContext,
8
- FC,
9
- ReactNode,
10
- useCallback,
11
- useContext,
12
- useState,
13
- } from 'react';
14
-
15
- /**
16
- * Minimal structural interface accepted by I18nProvider.
17
- * Both I18nEngine and PluginI18nEngine satisfy this interface.
18
- */
19
- export interface II18nEngineCompat {
20
- setLanguage(language: string): void;
21
- translate(
22
- componentId: string,
23
- stringKey: string,
24
- variables?: Record<string, string | number>,
25
- language?: string
26
- ): string;
27
- translateStringKey?(
28
- key: string,
29
- vars?: Record<string, string | number>,
30
- language?: string
31
- ): string;
32
- /** Template processor that handles {{component.key}} and {variable} patterns */
33
- t?(
34
- template: string,
35
- variables?: Record<string, string | number>,
36
- language?: string
37
- ): string;
38
- }
39
-
40
- export interface I18nProviderProps {
41
- children: ReactNode;
42
- i18nEngine: II18nEngineCompat;
43
- onLanguageChange?: (language: string) => Promise<void>;
44
- }
45
-
46
- export interface I18nContextType {
47
- t: (
48
- key: string,
49
- vars?: Record<string, string | number>,
50
- language?: string
51
- ) => string;
52
- tBranded: <TStringKey extends string>(
53
- stringKey: TStringKey,
54
- vars?: Record<string, string | number>,
55
- language?: string
56
- ) => string;
57
- tComponent: <TStringKey extends string>(
58
- componentId: string,
59
- stringKey: TStringKey,
60
- vars?: Record<string, string | number>,
61
- language?: string
62
- ) => string;
63
- changeLanguage: (language: string) => void;
64
- currentLanguage: string;
65
- }
66
-
67
- const I18nContext = createContext<I18nContextType | undefined>(undefined);
68
-
69
- export const I18nProvider: FC<I18nProviderProps> = ({
70
- children,
71
- i18nEngine,
72
- onLanguageChange,
73
- }) => {
74
- const context = GlobalActiveContext.getInstance<
75
- string,
76
- IActiveContext<string>
77
- >();
78
- const [currentLanguage, setCurrentLanguage] = useState<string>(
79
- context.userLanguage
80
- );
81
-
82
- const changeLanguage = useCallback(
83
- async (language: string) => {
84
- const languageDetails = LanguageRegistry.getLanguageByCode(language);
85
- if (language && languageDetails) {
86
- context.userLanguage = language;
87
- i18nEngine.setLanguage(language);
88
- localStorage.setItem('language', languageDetails.name);
89
- localStorage.setItem('languageCode', language);
90
- setCurrentLanguage(language);
91
- if (onLanguageChange) {
92
- await onLanguageChange(language);
93
- }
94
- }
95
- },
96
- [onLanguageChange, i18nEngine, context]
97
- );
98
-
99
- const tBranded = useCallback(
100
- (
101
- key: string,
102
- vars?: Record<string, string | number>,
103
- language?: string
104
- ) => {
105
- if (!i18nEngine.translateStringKey) return `[${key}]`;
106
- return i18nEngine.translateStringKey(key, vars, language ?? currentLanguage);
107
- },
108
- [i18nEngine, currentLanguage]
109
- );
110
-
111
- const t = useCallback(
112
- (
113
- key: string,
114
- vars?: Record<string, string | number>,
115
- language?: string
116
- ) => {
117
- // If the engine has a template processor and the key looks like a template
118
- // (contains {{...}} or {variable} patterns), use t() for template resolution
119
- if (i18nEngine.t && (/\{\{/.test(key) || /\{[A-Za-z]/.test(key))) {
120
- return i18nEngine.t(key, vars, language ?? currentLanguage);
121
- }
122
- if (i18nEngine.translateStringKey) {
123
- return i18nEngine.translateStringKey(key, vars, language ?? currentLanguage);
124
- }
125
- return `[${key}]`;
126
- },
127
- [i18nEngine, currentLanguage]
128
- );
129
-
130
- const tComponent = useCallback(
131
- <TStringKey extends string>(
132
- componentId: string,
133
- stringKey: TStringKey,
134
- vars?: Record<string, string | number>,
135
- language?: string
136
- ): string => {
137
- return i18nEngine.translate(
138
- componentId,
139
- stringKey,
140
- vars,
141
- language ?? currentLanguage
142
- );
143
- },
144
- [currentLanguage, i18nEngine]
145
- );
146
-
147
- const value = {
148
- t,
149
- tComponent,
150
- tBranded,
151
- changeLanguage,
152
- currentLanguage,
153
- };
154
-
155
- return <I18nContext.Provider value={value}>{children}</I18nContext.Provider>;
156
- };
157
-
158
- export const useI18n = () => {
159
- const context = useContext(I18nContext);
160
- if (context === undefined) {
161
- throw new Error('useI18n must be used within an I18nProvider');
162
- }
163
- return context;
164
- };
@@ -1,426 +0,0 @@
1
- // src/app/menuContext.tsx
2
- import {
3
- IRoleDTO,
4
- SuiteCoreComponentId,
5
- SuiteCoreStringKey,
6
- SuiteCoreStringKeyValue,
7
- } from '@digitaldefiance/suite-core-lib';
8
- import {
9
- AccountCircle,
10
- Autorenew as AutorenewIcon,
11
- Brightness4,
12
- Brightness7,
13
- Dashboard as DashboardIcon,
14
- Key as KeyIcon,
15
- LockOpen as LockOpenIcon,
16
- LockReset as LockResetIcon,
17
- Login as LoginIcon,
18
- ExitToApp as LogoutIcon,
19
- PersonAdd as PersonAddIcon,
20
- Settings,
21
- } from '@mui/icons-material';
22
- import {
23
- FC,
24
- ReactNode,
25
- createContext,
26
- useCallback,
27
- useContext,
28
- useEffect,
29
- useMemo,
30
- useRef,
31
- useState,
32
- } from 'react';
33
- import { useUserSettings } from '../hooks';
34
- import { IMenuConfig } from '../interfaces/IMenuConfig';
35
- import { IMenuOption } from '../interfaces/IMenuOption';
36
- import { createAuthenticatedApiClient } from '../services';
37
- import { MenuType, MenuTypes } from '../types/MenuType';
38
- import { useAuth } from './AuthProvider';
39
- import { useI18n } from './I18nProvider';
40
- import { useSuiteConfig } from './SuiteConfigProvider';
41
- import { useTheme } from './ThemeProvider';
42
-
43
- interface MenuProviderProps {
44
- children: ReactNode;
45
- menuConfigs?: IMenuConfig[];
46
- enableBackupCodes?: boolean;
47
- /**
48
- * IDs of menu options to suppress from every menu. Matches both the built-in
49
- * options (e.g. 'change-password', 'user-settings', 'logout') and any option
50
- * registered via `menuConfigs`. Dividers left orphaned by the removal are
51
- * cleaned up automatically. Defaults to none hidden, so existing consumers are
52
- * unaffected.
53
- */
54
- hiddenMenuIds?: readonly string[];
55
- }
56
-
57
- interface MenuContextType {
58
- menuOptions: IMenuOption[];
59
- getMenuOptions: (
60
- menuType: MenuType,
61
- includeDividers: boolean
62
- ) => IMenuOption[];
63
- registerMenuOption: (option: IMenuOption) => () => void;
64
- registerMenuOptions: (options: IMenuOption[]) => () => void;
65
- getTopMenus: () => Array<IMenuConfig>;
66
- }
67
-
68
- const MenuContext = createContext<MenuContextType | undefined>(undefined);
69
-
70
- export const MenuProvider: FC<MenuProviderProps> = ({
71
- children,
72
- menuConfigs = [],
73
- enableBackupCodes = true,
74
- hiddenMenuIds = [],
75
- }) => {
76
- const {
77
- userData: user,
78
- isAuthenticated,
79
- admin: isGlobalAdmin,
80
- mnemonic,
81
- clearMnemonic,
82
- wallet,
83
- clearWallet,
84
- } = useAuth();
85
- const { mode: colorMode } = useTheme();
86
- const registeredMenuOptions = useRef(new Set<() => void>());
87
- const [registeredOptions, setRegisteredOptions] = useState<
88
- Map<string, IMenuOption>
89
- >(new Map<string, IMenuOption>());
90
- const { tComponent } = useI18n();
91
- const { baseUrl } = useSuiteConfig();
92
- const authenticatedApi = useMemo(
93
- () => createAuthenticatedApiClient(baseUrl),
94
- [baseUrl]
95
- );
96
- const { toggleColorMode } = useUserSettings({
97
- authenticatedApi,
98
- isAuthenticated,
99
- });
100
-
101
- const registerMenuOption = useCallback((option: IMenuOption) => {
102
- const unregister = () => {
103
- setRegisteredOptions((prev) => {
104
- const newMap = new Map(prev);
105
- newMap.delete(option.id);
106
- return newMap;
107
- });
108
- registeredMenuOptions.current.delete(unregister);
109
- };
110
-
111
- setRegisteredOptions((prev) => {
112
- const newMap = new Map(prev);
113
- newMap.set(option.id, option);
114
- return newMap;
115
- });
116
- registeredMenuOptions.current.add(unregister);
117
-
118
- return unregister;
119
- }, []);
120
-
121
- const registerMenuOptions = useCallback(
122
- (options: IMenuOption[]) => {
123
- const unregisterFunctions = options.map(registerMenuOption);
124
- return () => unregisterFunctions.forEach((f) => f());
125
- },
126
- [registerMenuOption]
127
- );
128
-
129
- const menuOptions = useMemo(() => {
130
- const isUserRestricted = () => {
131
- return user?.roles?.some((role: IRoleDTO) => role.child) ?? false;
132
- };
133
- let index = 0;
134
- const baseOptions: IMenuOption[] = [
135
- {
136
- id: 'dashboard',
137
- label: tComponent<SuiteCoreStringKeyValue>(
138
- SuiteCoreComponentId,
139
- SuiteCoreStringKey.Common_Dashboard
140
- ),
141
- icon: <DashboardIcon />,
142
- link: '/dashboard',
143
- requiresAuth: true,
144
- includeOnMenus: [MenuTypes.SideMenu],
145
- index: index++,
146
- },
147
- {
148
- id: 'user-divider',
149
- label: '',
150
- divider: true,
151
- includeOnMenus: [MenuTypes.SideMenu],
152
- index: index++,
153
- requiresAuth: false,
154
- },
155
- {
156
- id: 'logout',
157
- label: tComponent<SuiteCoreStringKeyValue>(
158
- SuiteCoreComponentId,
159
- SuiteCoreStringKey.LogoutButton
160
- ),
161
- icon: <LogoutIcon />,
162
- link: '/logout',
163
- requiresAuth: true,
164
- includeOnMenus: [MenuTypes.UserMenu, MenuTypes.SideMenu],
165
- index: index++,
166
- },
167
- {
168
- id: 'login',
169
- label: tComponent<SuiteCoreStringKeyValue>(
170
- SuiteCoreComponentId,
171
- SuiteCoreStringKey.Login_LoginButton
172
- ),
173
- icon: <LoginIcon />,
174
- link: '/login',
175
- requiresAuth: false,
176
- includeOnMenus: [MenuTypes.UserMenu, MenuTypes.SideMenu],
177
- index: index++,
178
- },
179
- {
180
- id: 'register',
181
- label: tComponent<SuiteCoreStringKeyValue>(
182
- SuiteCoreComponentId,
183
- SuiteCoreStringKey.RegisterButton
184
- ),
185
- icon: <PersonAddIcon />,
186
- link: '/register',
187
- requiresAuth: false,
188
- includeOnMenus: [MenuTypes.UserMenu, MenuTypes.SideMenu],
189
- index: index++,
190
- },
191
- {
192
- id: 'forgot-password',
193
- label: tComponent<SuiteCoreStringKeyValue>(
194
- SuiteCoreComponentId,
195
- SuiteCoreStringKey.ForgotPassword_Title
196
- ),
197
- icon: <LockOpenIcon />,
198
- link: '/forgot-password',
199
- requiresAuth: false,
200
- includeOnMenus: [MenuTypes.UserMenu, MenuTypes.SideMenu],
201
- index: index++,
202
- },
203
- {
204
- id: 'change-password',
205
- label: tComponent<SuiteCoreStringKeyValue>(
206
- SuiteCoreComponentId,
207
- SuiteCoreStringKey.Common_ChangePassword
208
- ),
209
- icon: <LockResetIcon />,
210
- link: '/change-password',
211
- requiresAuth: true,
212
- includeOnMenus: [MenuTypes.UserMenu, MenuTypes.SideMenu],
213
- index: index++,
214
- },
215
- ...(enableBackupCodes
216
- ? [
217
- {
218
- id: 'backup-code',
219
- label: tComponent<SuiteCoreStringKeyValue>(
220
- SuiteCoreComponentId,
221
- SuiteCoreStringKey.BackupCodeRecovery_Title
222
- ),
223
- icon: <KeyIcon />,
224
- link: '/backup-code',
225
- requiresAuth: false,
226
- includeOnMenus: [MenuTypes.UserMenu, MenuTypes.SideMenu],
227
- index: index++,
228
- },
229
- {
230
- id: 'backup-codes',
231
- label: tComponent<SuiteCoreStringKeyValue>(
232
- SuiteCoreComponentId,
233
- SuiteCoreStringKey.BackupCodeRecovery_GenerateNewCodes
234
- ),
235
- icon: <AutorenewIcon />,
236
- link: '/backup-codes',
237
- requiresAuth: true,
238
- includeOnMenus: [MenuTypes.UserMenu, MenuTypes.SideMenu],
239
- index: index++,
240
- },
241
- ]
242
- : []),
243
- {
244
- id: 'divider',
245
- label: '',
246
- divider: true,
247
- includeOnMenus: [MenuTypes.SideMenu],
248
- index: index++,
249
- requiresAuth: false,
250
- },
251
- {
252
- id: 'clear-mnemonic',
253
- label: tComponent<SuiteCoreStringKeyValue>(
254
- SuiteCoreComponentId,
255
- SuiteCoreStringKey.Common_ClearMnemonic
256
- ),
257
- action: clearMnemonic,
258
- icon: <KeyIcon />,
259
- requiresAuth: true,
260
- includeOnMenus: [MenuTypes.UserMenu, MenuTypes.SideMenu],
261
- index: index++,
262
- filter: () => !!mnemonic,
263
- },
264
- {
265
- id: 'clear-wallet',
266
- label: tComponent<SuiteCoreStringKeyValue>(
267
- SuiteCoreComponentId,
268
- SuiteCoreStringKey.Common_ClearWallet
269
- ),
270
- action: clearWallet,
271
- icon: <KeyIcon />,
272
- requiresAuth: true,
273
- includeOnMenus: [MenuTypes.UserMenu, MenuTypes.SideMenu],
274
- index: index++,
275
- filter: () => !!wallet,
276
- },
277
- ...(isUserRestricted() ? [] : []),
278
- {
279
- id: 'color-divider',
280
- label: '',
281
- divider: true,
282
- includeOnMenus: [MenuTypes.SideMenu],
283
- index: index++,
284
- requiresAuth: undefined,
285
- },
286
- {
287
- id: 'theme-toggle',
288
- label:
289
- colorMode === 'dark'
290
- ? tComponent<SuiteCoreStringKeyValue>(
291
- SuiteCoreComponentId,
292
- SuiteCoreStringKey.Common_ThemeToggle_Light
293
- )
294
- : tComponent<SuiteCoreStringKeyValue>(
295
- SuiteCoreComponentId,
296
- SuiteCoreStringKey.Common_ThemeToggle_Dark
297
- ),
298
- icon: colorMode === 'dark' ? <Brightness7 /> : <Brightness4 />,
299
- includeOnMenus: [MenuTypes.SideMenu],
300
- index: index++,
301
- requiresAuth: undefined,
302
- action: toggleColorMode,
303
- },
304
- {
305
- id: 'user-settings',
306
- label: tComponent<SuiteCoreStringKeyValue>(
307
- SuiteCoreComponentId,
308
- SuiteCoreStringKey.Settings_Title
309
- ),
310
- icon: <Settings />,
311
- link: '/user-settings',
312
- requiresAuth: true,
313
- includeOnMenus: [MenuTypes.UserMenu, MenuTypes.SideMenu],
314
- index: index++,
315
- },
316
- ];
317
-
318
- const allOptions = [...baseOptions, ...registeredOptions.values()];
319
- return allOptions.sort((a, b) => a.index - b.index);
320
- }, [
321
- tComponent,
322
- registeredOptions,
323
- user?.roles,
324
- colorMode,
325
- toggleColorMode,
326
- clearMnemonic,
327
- clearWallet,
328
- mnemonic,
329
- wallet,
330
- enableBackupCodes,
331
- ]);
332
-
333
- const getMenuOptions = useCallback(
334
- (menuType: MenuType, includeDividers: boolean) => {
335
- const hidden = new Set(hiddenMenuIds);
336
- const MenuFilter = (o: IMenuOption) => {
337
- // Suppress any option whose id the consumer asked to hide.
338
- if (hidden.has(o.id)) return false;
339
-
340
- // Apply the custom filter first
341
- let customFilterPasses = true;
342
- if (o.filter !== undefined) {
343
- customFilterPasses = o.filter(o);
344
- }
345
- if (!customFilterPasses) return false;
346
-
347
- if (o.divider === true && !includeDividers) return false;
348
-
349
- if (o.requiresAdmin === true && !isGlobalAdmin) return false;
350
-
351
- return (
352
- o.includeOnMenus.includes(menuType) &&
353
- (o.requiresAuth === undefined || o.requiresAuth === isAuthenticated)
354
- );
355
- };
356
-
357
- const filtered = menuOptions.filter(MenuFilter);
358
-
359
- // Drop dividers left orphaned once hidden items are removed: a divider at
360
- // the start or end of the list, or immediately following another divider,
361
- // carries no meaning and would show as a stray separator.
362
- return filtered.filter((o, i) => {
363
- if (o.divider !== true) return true;
364
- const prev = filtered[i - 1];
365
- if (prev === undefined || prev.divider === true) return false;
366
- if (i === filtered.length - 1) return false;
367
- return true;
368
- });
369
- },
370
- [hiddenMenuIds, isAuthenticated, isGlobalAdmin, menuOptions]
371
- );
372
-
373
- useEffect(() => {
374
- if (menuConfigs.length > 0) {
375
- return registerMenuOptions(
376
- menuConfigs.flatMap((config) => config.options)
377
- );
378
- }
379
- return undefined;
380
- }, [menuConfigs, registerMenuOptions]);
381
-
382
- const getTopMenus = useCallback(() => {
383
- const menus: Array<IMenuConfig & { isUserMenu?: boolean }> = [
384
- ...menuConfigs.map((config) => ({ ...config, isUserMenu: false })),
385
- {
386
- menuType: MenuTypes.UserMenu,
387
- menuIcon: <AccountCircle />,
388
- priority: 0,
389
- options: [],
390
- isUserMenu: true,
391
- },
392
- ];
393
- return menus.sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0));
394
- }, [menuConfigs]);
395
-
396
- const contextValue = useMemo(() => {
397
- return {
398
- menuOptions: menuOptions,
399
- getMenuOptions: getMenuOptions,
400
- registerMenuOption: registerMenuOption,
401
- registerMenuOptions: registerMenuOptions,
402
- getTopMenus: getTopMenus,
403
- };
404
- }, [
405
- menuOptions,
406
- getMenuOptions,
407
- registerMenuOption,
408
- registerMenuOptions,
409
- getTopMenus,
410
- ]);
411
-
412
- const memoizedChildren = useMemo(() => children, [children]);
413
- return (
414
- <MenuContext.Provider value={contextValue}>
415
- {memoizedChildren}
416
- </MenuContext.Provider>
417
- );
418
- };
419
-
420
- export const useMenu = (): MenuContextType => {
421
- const context = useContext(MenuContext);
422
- if (context === undefined) {
423
- throw new Error('useMenu must be used within a MenuProvider');
424
- }
425
- return context;
426
- };
@@ -1,93 +0,0 @@
1
- import { createContext, ReactNode, useContext } from 'react';
2
-
3
- export interface SuiteConfigRoutes {
4
- dashboard?: string;
5
- login?: string;
6
- register?: string;
7
- verifyEmail?: string;
8
- forgotPassword?: string;
9
- resetPassword?: string;
10
- settings?: string;
11
- }
12
-
13
- export interface SuiteConfigContextData {
14
- /**
15
- * Base URL for API calls
16
- */
17
- baseUrl: string;
18
-
19
- /**
20
- * Application routes for navigation
21
- */
22
- routes: SuiteConfigRoutes;
23
-
24
- /**
25
- * Available languages for the application
26
- */
27
- languages: Array<{ code: string; label: string }>;
28
-
29
- /**
30
- * Available timezones
31
- */
32
- timezones?: string[];
33
- }
34
-
35
- const defaultRoutes: SuiteConfigRoutes = {
36
- dashboard: '/dashboard',
37
- login: '/login',
38
- register: '/register',
39
- verifyEmail: '/verify-email',
40
- forgotPassword: '/forgot-password',
41
- resetPassword: '/reset-password',
42
- settings: '/settings',
43
- };
44
-
45
- const defaultLanguages = [
46
- { code: 'en-US', label: 'English (US)' },
47
- { code: 'en-GB', label: 'English (UK)' },
48
- { code: 'es-ES', label: 'Español' },
49
- { code: 'fr-FR', label: 'Français' },
50
- { code: 'de-DE', label: 'Deutsch' },
51
- { code: 'ja', label: '日本語' },
52
- { code: 'zh-CN', label: '中文 (简体)' },
53
- { code: 'uk', label: 'Українська' },
54
- ];
55
-
56
- const SuiteConfigContext = createContext<SuiteConfigContextData | undefined>(undefined);
57
-
58
- export interface SuiteConfigProviderProps {
59
- children: ReactNode;
60
- baseUrl: string;
61
- routes?: Partial<SuiteConfigRoutes>;
62
- languages?: Array<{ code: string; label: string }>;
63
- timezones?: string[];
64
- }
65
-
66
- export const SuiteConfigProvider = ({
67
- children,
68
- baseUrl,
69
- routes = {},
70
- languages = defaultLanguages,
71
- timezones,
72
- }: SuiteConfigProviderProps) => {
73
- const value: SuiteConfigContextData = {
74
- baseUrl,
75
- routes: { ...defaultRoutes, ...routes },
76
- languages,
77
- timezones,
78
- };
79
-
80
- return (
81
- <SuiteConfigContext.Provider value={value}>
82
- {children}
83
- </SuiteConfigContext.Provider>
84
- );
85
- };
86
-
87
- export const useSuiteConfig = (): SuiteConfigContextData => {
88
- const context = useContext(SuiteConfigContext);
89
- if (!context) {
90
- throw new Error('useSuiteConfig must be used within a SuiteConfigProvider');
91
- }
92
- return context;
93
- };