@digitaldefiance/express-suite-react-components 2.4.3 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/README.md +133 -0
  2. package/package.json +4 -4
  3. package/src/components/TopMenu.js +2 -2
  4. package/src/components/VerifyEmailPage.js +7 -7
  5. package/src/contexts/AuthProvider.d.ts.map +1 -1
  6. package/src/contexts/AuthProvider.js +25 -11
  7. package/src/contexts/MenuContext.d.ts +1 -0
  8. package/src/contexts/MenuContext.d.ts.map +1 -1
  9. package/src/contexts/MenuContext.js +40 -31
  10. package/src/contexts/SuiteConfigProvider.d.ts +44 -0
  11. package/src/contexts/SuiteConfigProvider.d.ts.map +1 -0
  12. package/src/contexts/SuiteConfigProvider.js +43 -0
  13. package/src/contexts/ThemeProvider.d.ts +1 -0
  14. package/src/contexts/ThemeProvider.d.ts.map +1 -1
  15. package/src/contexts/ThemeProvider.js +3 -0
  16. package/src/contexts/index.d.ts +1 -0
  17. package/src/contexts/index.d.ts.map +1 -1
  18. package/src/contexts/index.js +1 -0
  19. package/src/hooks/index.d.ts +3 -0
  20. package/src/hooks/index.d.ts.map +1 -1
  21. package/src/hooks/index.js +3 -0
  22. package/src/hooks/useBackupCodes.d.ts +15 -0
  23. package/src/hooks/useBackupCodes.d.ts.map +1 -0
  24. package/src/hooks/useBackupCodes.js +70 -0
  25. package/src/hooks/useEmailVerification.d.ts +10 -0
  26. package/src/hooks/useEmailVerification.d.ts.map +1 -0
  27. package/src/hooks/useEmailVerification.js +36 -0
  28. package/src/hooks/useUserSettings.d.ts +29 -0
  29. package/src/hooks/useUserSettings.d.ts.map +1 -0
  30. package/src/hooks/useUserSettings.js +103 -0
  31. package/src/wrappers/BackupCodeLoginWrapper.d.ts +8 -0
  32. package/src/wrappers/BackupCodeLoginWrapper.d.ts.map +1 -0
  33. package/src/wrappers/BackupCodeLoginWrapper.js +21 -0
  34. package/src/wrappers/BackupCodesWrapper.d.ts +7 -0
  35. package/src/wrappers/BackupCodesWrapper.d.ts.map +1 -0
  36. package/src/wrappers/BackupCodesWrapper.js +17 -0
  37. package/src/wrappers/ChangePasswordFormWrapper.d.ts +8 -0
  38. package/src/wrappers/ChangePasswordFormWrapper.d.ts.map +1 -0
  39. package/src/wrappers/ChangePasswordFormWrapper.js +21 -0
  40. package/src/wrappers/LoginFormWrapper.d.ts +9 -0
  41. package/src/wrappers/LoginFormWrapper.d.ts.map +1 -0
  42. package/src/wrappers/LoginFormWrapper.js +43 -0
  43. package/src/wrappers/LogoutPageWrapper.d.ts +9 -0
  44. package/src/wrappers/LogoutPageWrapper.d.ts.map +1 -0
  45. package/src/wrappers/LogoutPageWrapper.js +21 -0
  46. package/src/wrappers/RegisterFormWrapper.d.ts +9 -0
  47. package/src/wrappers/RegisterFormWrapper.d.ts.map +1 -0
  48. package/src/wrappers/RegisterFormWrapper.js +26 -0
  49. package/src/wrappers/UserSettingsFormWrapper.d.ts +8 -0
  50. package/src/wrappers/UserSettingsFormWrapper.d.ts.map +1 -0
  51. package/src/wrappers/UserSettingsFormWrapper.js +23 -0
  52. package/src/wrappers/VerifyEmailPageWrapper.d.ts +8 -0
  53. package/src/wrappers/VerifyEmailPageWrapper.d.ts.map +1 -0
  54. package/src/wrappers/VerifyEmailPageWrapper.js +20 -0
  55. package/src/wrappers/index.d.ts +16 -22
  56. package/src/wrappers/index.d.ts.map +1 -1
  57. package/src/wrappers/index.js +17 -158
package/README.md CHANGED
@@ -31,6 +31,19 @@ yarn add @digitaldefiance/express-suite-react-components
31
31
  - **DashboardPage** - Basic dashboard layout
32
32
  - **ApiAccess** - API token display and copy component
33
33
 
34
+ ### Wrapper Components
35
+
36
+ Pre-configured components that integrate with application contexts. See the [Component Wrappers Guide](WRAPPERS.md) for detailed usage.
37
+
38
+ - **LoginFormWrapper** - Pre-configured login with auth context integration
39
+ - **RegisterFormWrapper** - Pre-configured registration with auth context integration
40
+ - **ChangePasswordFormWrapper** - Pre-configured password change with auth context
41
+ - **BackupCodeLoginWrapper** - Pre-configured backup code login
42
+ - **BackupCodesWrapper** - Pre-configured backup codes management
43
+ - **UserSettingsFormWrapper** - Pre-configured settings form with auto-fetch
44
+ - **VerifyEmailPageWrapper** - Pre-configured email verification
45
+ - **LogoutPageWrapper** - Pre-configured logout with navigation
46
+
34
47
  ### UI Components
35
48
 
36
49
  - **ConfirmationDialog** - Reusable confirmation dialog
@@ -49,14 +62,19 @@ yarn add @digitaldefiance/express-suite-react-components
49
62
 
50
63
  - **useLocalStorage** - React hook for localStorage with state sync
51
64
  - **useExpiringValue** - React hook for values that expire after a duration
65
+ - **useBackupCodes** - Manage backup code generation and retrieval
66
+ - **useUserSettings** - Fetch and update user settings with context integration
67
+ - **useEmailVerification** - Handle email verification flow
52
68
 
53
69
  ### Contexts & Providers
54
70
 
55
71
  - **I18nProvider** - Internationalization context with i18n engine integration
56
72
  - **AppThemeProvider** - MUI theme provider with dark/light mode toggle
57
73
  - **ThemeToggleButton** - Button component for theme switching
74
+ - **SuiteConfigProvider** - Centralized configuration context (baseUrl, routes, languages)
58
75
  - **useI18n** - Hook for accessing i18n context
59
76
  - **useTheme** - Hook for accessing theme context
77
+ - **useSuiteConfig** - Hook for accessing suite configuration
60
78
 
61
79
  ### Services
62
80
 
@@ -70,6 +88,44 @@ yarn add @digitaldefiance/express-suite-react-components
70
88
 
71
89
  ## Usage
72
90
 
91
+ ### Getting Started with Wrappers
92
+
93
+ For the quickest setup, use wrapper components that handle context integration automatically. See the [Component Wrappers Guide](WRAPPERS.md) for comprehensive examples.
94
+
95
+ ```tsx
96
+ import {
97
+ SuiteConfigProvider,
98
+ AuthProvider,
99
+ LoginFormWrapper
100
+ } from '@digitaldefiance/express-suite-react-components';
101
+
102
+ function App() {
103
+ return (
104
+ <SuiteConfigProvider
105
+ baseUrl="https://api.example.com"
106
+ routes={{
107
+ dashboard: '/dashboard',
108
+ login: '/login',
109
+ }}
110
+ languages={[
111
+ { code: 'en-US', label: 'English (US)' },
112
+ ]}
113
+ >
114
+ <AuthProvider baseUrl="https://api.example.com" onAuthError={() => {}}>
115
+ {/* Use wrappers for instant integration */}
116
+ <LoginFormWrapper />
117
+
118
+ {/* Or customize via props */}
119
+ <LoginFormWrapper
120
+ redirectTo="/custom-dashboard"
121
+ componentProps={{ loginType: 'username' }}
122
+ />
123
+ </AuthProvider>
124
+ </SuiteConfigProvider>
125
+ );
126
+ }
127
+ ```
128
+
73
129
  ### Menu System
74
130
 
75
131
  The menu system supports extensible menu types. See the [Menu Type Extensibility Guide](docs/MENU_TYPE_EXTENSIBILITY.md) for details on creating custom menus.
@@ -295,8 +351,77 @@ interface RegisterFormProps {
295
351
 
296
352
  MIT © Digital Defiance
297
353
 
354
+ ## Documentation
355
+
356
+ - **[Overview](docs/OVERVIEW.md)** - Package architecture and getting started guide
357
+ - **[Components Documentation](docs/COMPONENTS.md)** - API reference for presentational components
358
+ - **[Hooks Documentation](docs/HOOKS.md)** - API reference for custom React hooks
359
+ - **[Wrappers API Documentation](docs/WRAPPERS_API.md)** - API reference for wrapper components
360
+ - **[Component Wrappers Guide](WRAPPERS.md)** - Comprehensive guide to using wrappers, hooks, and components
361
+ - **[Menu Type Extensibility Guide](docs/MENU_TYPE_EXTENSIBILITY.md)** - Creating custom menu types
362
+
298
363
  ## ChangeLog
299
364
 
365
+ ### Version 2.5.0
366
+
367
+ #### Added
368
+
369
+ - **SuiteConfigProvider** - Centralized configuration context for baseUrl, routes, languages, and timezones
370
+ - **Component Wrappers** - Pre-configured wrapper components for all major forms and pages
371
+ - LoginFormWrapper, RegisterFormWrapper, ChangePasswordFormWrapper
372
+ - BackupCodeLoginWrapper, BackupCodesWrapper
373
+ - UserSettingsFormWrapper, VerifyEmailPageWrapper, LogoutPageWrapper
374
+ - **Business Logic Hooks** - Reusable hooks for common operations
375
+ - useBackupCodes - Manage backup code generation and retrieval
376
+ - useUserSettings - Fetch and update user settings with context integration
377
+ - useEmailVerification - Handle email verification flow
378
+ - **Component Wrappers Guide** - Comprehensive documentation at `WRAPPERS.md`
379
+
380
+ #### Changed
381
+
382
+ - **Wrapper Architecture** - All wrappers now use centralized SuiteConfigProvider
383
+ - **Consistent API** - All wrappers support `onSuccess`, `componentProps`, and configurable routing
384
+ - **Improved Testability** - Business logic extracted into hooks for easier testing
385
+ - **Better DX** - Three levels of abstraction: Wrappers (easy), Hooks (flexible), Components (full control)
386
+
387
+ #### Breaking Changes
388
+
389
+ - **BackupCodesWrapper** - No longer requires `baseUrl` prop (uses SuiteConfigProvider)
390
+ - **VerifyEmailPageWrapper** - No longer requires `baseUrl` prop (uses SuiteConfigProvider)
391
+ - **UserSettingsFormWrapper** - No longer requires `baseUrl` or `languages` props (uses SuiteConfigProvider)
392
+
393
+ #### Migration Guide
394
+
395
+ ```tsx
396
+ // Old (v2.4.x)
397
+ <BackupCodesWrapper baseUrl="https://api.example.com" />
398
+ <UserSettingsFormWrapper
399
+ baseUrl="https://api.example.com"
400
+ languages={[...]}
401
+ />
402
+
403
+ // New (v2.5.0)
404
+ <SuiteConfigProvider
405
+ baseUrl="https://api.example.com"
406
+ languages={[...]}
407
+ >
408
+ <BackupCodesWrapper />
409
+ <UserSettingsFormWrapper />
410
+ </SuiteConfigProvider>
411
+ ```
412
+
413
+ See [Component Wrappers Guide](WRAPPERS.md) for complete migration examples.
414
+
415
+ ### Version 2.4.5
416
+
417
+ - DarkMode improvements
418
+
419
+ ### Version 2.4.4
420
+
421
+ - Fix t(tComponent( calls
422
+ - Add enableBackupCode to MenuProvider
423
+ - Add User Settings to menu
424
+
300
425
  ### Version 2.4.3
301
426
 
302
427
  - Simplify UserSettingsForm/Wrapper
@@ -315,23 +440,27 @@ MIT © Digital Defiance
315
440
  ### Version 2.4.0
316
441
 
317
442
  #### Changed
443
+
318
444
  - **Version Bump**: Updated from 2.3.5 to 2.4.0
319
445
  - **Dependency Update**: Upgraded `@digitaldefiance/suite-core-lib` from ^2.2.5 to ^2.2.10
320
446
  - **Translation Keys**: Replaced `Login_UseEmail` with `Login_UseEmailAddress` in BackupCodeLoginForm and LoginForm
321
447
  - **Error Messages**: Updated password login error to use `Error_Login_PasswordLoginNotSetup` instead of `PasswordLogin_Setup_NotAvailable` in AuthProvider
322
448
 
323
449
  #### Added
450
+
324
451
  - **Error Handling**: LoginForm now displays error messages via Alert component with Formik status
325
452
  - **Error Recovery**: LoginForm onSubmit wrapped with try-catch to capture and display errors
326
453
  - **Menu Context Integration**: TopMenu now uses `useMenu()` hook and `getTopMenus()` method
327
454
  - **Menu Types**: Added `AccountCircle` icon import and `IMenuConfig` interface import
328
455
 
329
456
  #### Fixed
457
+
330
458
  - **Import Path**: Corrected `IAppConfig` import path from `../interfaces/AppConfig` to `../interfaces/IAppConfig`
331
459
  - **Menu Rendering**: Simplified TopMenu additional menus logic to use centralized menu context
332
460
  - **Error Type**: Added `errorType: 'PasswordLoginNotSetup'` to password login error responses
333
461
 
334
462
  #### Technical
463
+
335
464
  - Enhanced error propagation in authentication flows
336
465
  - Improved menu configuration architecture with context-based management
337
466
  - Better alignment with suite-core-lib translation key naming conventions
@@ -359,10 +488,12 @@ MIT © Digital Defiance
359
488
  ### v2.3.0
360
489
 
361
490
  #### Breaking Changes
491
+
362
492
  - **Removed `IncludeOnMenu` enum** - Replaced with extensible `MenuType` system using branded string types
363
493
  - Menu system now requires `MenuTypes` constant instead of enum values
364
494
 
365
495
  #### Added
496
+
366
497
  - **Extensible Menu Type System** - New `MenuType` branded string type with `createMenuType()` factory function
367
498
  - **`MenuTypes` constant** - Built-in menu types (SideMenu, TopMenu, UserMenu) replacing enum
368
499
  - **`createMenuType()` function** - Factory for creating custom menu types with type safety
@@ -371,6 +502,7 @@ MIT © Digital Defiance
371
502
  - **Menu Type Extensibility Guide** - Comprehensive documentation at `docs/MENU_TYPE_EXTENSIBILITY.md`
372
503
 
373
504
  #### Changed
505
+
374
506
  - **IMenuOption.includeOnMenus** - Now uses `MenuType[]` instead of `IncludeOnMenu[]`
375
507
  - **DropdownMenu.menuType** - Now accepts `MenuType` instead of `IncludeOnMenu`
376
508
  - **MenuContext.getMenuOptions** - Now accepts `MenuType` parameter instead of `IncludeOnMenu`
@@ -378,6 +510,7 @@ MIT © Digital Defiance
378
510
  - Updated README with menu system usage examples and extensibility guide link
379
511
 
380
512
  #### Migration Guide
513
+
381
514
  ```typescript
382
515
  // Old (v2.2.x)
383
516
  import { IncludeOnMenu } from '@digitaldefiance/express-suite-react-components';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@digitaldefiance/express-suite-react-components",
3
- "version": "2.4.3",
3
+ "version": "2.5.0",
4
4
  "description": "React MUI components for Digital Defiance Express Suite",
5
5
  "main": "src/index.js",
6
6
  "types": "src/index.d.ts",
@@ -8,9 +8,9 @@
8
8
  "build": "npx nx build digitaldefiance-express-suite-react-components",
9
9
  "build:stream": "npx nx build --outputStyle=stream digitaldefiance-express-suite-react-components",
10
10
  "build:logged": "npx nx build --outputStyle=stream digitaldefiance-express-suite-react-components 2>&1 | ansifilter -o build.log",
11
- "test": "npx nx test digitaldefiance-express-suite-react-components",
12
- "test:stream": "npx nx test --outputStyle=stream digitaldefiance-express-suite-react-components",
13
- "test:logged": "npx nx test --outputStyle=stream digitaldefiance-express-suite-react-components 2>&1 | ansifilter -o test.log",
11
+ "test": "NODE_OPTIONS='--max-old-space-size=6144' npx nx test digitaldefiance-express-suite-react-components",
12
+ "test:stream": "NODE_OPTIONS='--max-old-space-size=6144' npx nx test --outputStyle=stream digitaldefiance-express-suite-react-components",
13
+ "test:logged": "NODE_OPTIONS='--max-old-space-size=6144' npx nx test --outputStyle=stream digitaldefiance-express-suite-react-components 2>&1 | ansifilter -o test.log",
14
14
  "test:coverage": "npx jest --coverage --testPathPattern=digitaldefiance-express-suite-react-components --coverageReporters=text",
15
15
  "lint": "npx nx lint digitaldefiance-express-suite-react-components",
16
16
  "lint:fix": "npx nx lint digitaldefiance-express-suite-react-components --fix",
@@ -25,14 +25,14 @@ const TopMenu = ({ Logo, additionalMenus }) => {
25
25
  const appConfig = 'APP_CONFIG' in window
26
26
  ? window.APP_CONFIG
27
27
  : undefined;
28
- const siteTitle = t(tComponent(suite_core_lib_1.SuiteCoreComponentId, suite_core_lib_1.SuiteCoreStringKey.Common_SiteTemplate));
28
+ const siteTitle = tComponent(suite_core_lib_1.SuiteCoreComponentId, suite_core_lib_1.SuiteCoreStringKey.Common_SiteTemplate);
29
29
  return ((0, jsx_runtime_1.jsxs)(material_1.AppBar, { position: "fixed", sx: { top: 10 }, children: [(0, jsx_runtime_1.jsxs)(material_1.Toolbar, { children: [(0, jsx_runtime_1.jsx)(material_1.IconButton, { size: "large", edge: "start", color: "inherit", "aria-label": "menu", sx: { mr: 2 }, onClick: handleOpenSideMenu, children: (0, jsx_runtime_1.jsx)(Menu_1.default, {}) }), (0, jsx_runtime_1.jsx)(material_1.Box, { sx: {
30
30
  height: 40,
31
31
  width: 40,
32
32
  marginRight: 2,
33
33
  display: 'flex',
34
34
  alignItems: 'center',
35
- }, children: Logo }), (0, jsx_runtime_1.jsx)(material_1.Typography, { variant: "h6", component: "div", sx: { flexGrow: 1 }, children: siteTitle }), (0, jsx_runtime_1.jsxs)(material_1.Box, { sx: { display: 'flex', alignItems: 'center' }, children: [isAuthenticated ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(material_1.Button, { color: "inherit", component: react_router_dom_1.Link, to: "/dashboard", children: t(tComponent(suite_core_lib_1.SuiteCoreComponentId, suite_core_lib_1.SuiteCoreStringKey.Common_Dashboard)) }), getTopMenus().map((menu, index) => menu.isUserMenu ? (0, jsx_runtime_1.jsx)(UserMenu_1.UserMenu, {}, `user-menu`) : (0, jsx_runtime_1.jsx)(DropdownMenu_1.DropdownMenu, { menuType: menu.menuType, menuIcon: menu.menuIcon }, `menu-${index}`))] })) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(material_1.Button, { color: "inherit", component: react_router_dom_1.Link, to: "/login", children: t(tComponent(suite_core_lib_1.SuiteCoreComponentId, suite_core_lib_1.SuiteCoreStringKey.Login_LoginButton)) }), (0, jsx_runtime_1.jsx)(material_1.Button, { color: "inherit", component: react_router_dom_1.Link, to: "/register", children: t(tComponent(suite_core_lib_1.SuiteCoreComponentId, suite_core_lib_1.SuiteCoreStringKey.RegisterButton)) })] })), (0, jsx_runtime_1.jsx)(UserLanguageSelector_1.UserLanguageSelector, {})] })] }), (0, jsx_runtime_1.jsx)(SideMenu_1.SideMenu, { isOpen: isSideMenuOpen, onClose: handleCloseSideMenu })] }));
35
+ }, children: Logo }), (0, jsx_runtime_1.jsx)(material_1.Typography, { variant: "h6", component: "div", sx: { flexGrow: 1 }, children: siteTitle }), (0, jsx_runtime_1.jsxs)(material_1.Box, { sx: { display: 'flex', alignItems: 'center' }, children: [isAuthenticated ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(material_1.Button, { color: "inherit", component: react_router_dom_1.Link, to: "/dashboard", children: tComponent(suite_core_lib_1.SuiteCoreComponentId, suite_core_lib_1.SuiteCoreStringKey.Common_Dashboard) }), getTopMenus().map((menu, index) => menu.isUserMenu ? (0, jsx_runtime_1.jsx)(UserMenu_1.UserMenu, {}, `user-menu`) : (0, jsx_runtime_1.jsx)(DropdownMenu_1.DropdownMenu, { menuType: menu.menuType, menuIcon: menu.menuIcon }, `menu-${index}`))] })) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(material_1.Button, { color: "inherit", component: react_router_dom_1.Link, to: "/login", children: tComponent(suite_core_lib_1.SuiteCoreComponentId, suite_core_lib_1.SuiteCoreStringKey.Login_LoginButton) }), (0, jsx_runtime_1.jsx)(material_1.Button, { color: "inherit", component: react_router_dom_1.Link, to: "/register", children: tComponent(suite_core_lib_1.SuiteCoreComponentId, suite_core_lib_1.SuiteCoreStringKey.RegisterButton) })] })), (0, jsx_runtime_1.jsx)(UserLanguageSelector_1.UserLanguageSelector, {})] })] }), (0, jsx_runtime_1.jsx)(SideMenu_1.SideMenu, { isOpen: isSideMenuOpen, onClose: handleCloseSideMenu })] }));
36
36
  };
37
37
  exports.TopMenu = TopMenu;
38
38
  exports.default = exports.TopMenu;
@@ -12,13 +12,13 @@ const VerifyEmailPage = ({ token, onVerify, labels = {}, loginLink = '/login', r
12
12
  const [loading, setLoading] = (0, react_1.useState)(true);
13
13
  const [verificationStatus, setVerificationStatus] = (0, react_1.useState)('pending');
14
14
  const translatedLabels = {
15
- title: labels.title || t(tComponent(suite_core_lib_1.SuiteCoreComponentId, suite_core_lib_1.SuiteCoreStringKey.Common_EmailVerification)),
16
- success: labels.success || t(tComponent(suite_core_lib_1.SuiteCoreComponentId, suite_core_lib_1.SuiteCoreStringKey.EmailVerification_Success)),
17
- failed: labels.failed || t(tComponent(suite_core_lib_1.SuiteCoreComponentId, suite_core_lib_1.SuiteCoreStringKey.EmailVerification_Failed)),
18
- noToken: labels.noToken || t(tComponent(suite_core_lib_1.SuiteCoreComponentId, suite_core_lib_1.SuiteCoreStringKey.NoVerificationTokenProvided)),
19
- proceedToLogin: labels.proceedToLogin || t(tComponent(suite_core_lib_1.SuiteCoreComponentId, suite_core_lib_1.SuiteCoreStringKey.ProceedToLogin)),
20
- contactSupport: labels.contactSupport || t(tComponent(suite_core_lib_1.SuiteCoreComponentId, suite_core_lib_1.SuiteCoreStringKey.HavingTroubleContactSupport)),
21
- requestNewEmail: labels.requestNewEmail || t(tComponent(suite_core_lib_1.SuiteCoreComponentId, suite_core_lib_1.SuiteCoreStringKey.RequestNewVerificationEmail)),
15
+ title: labels.title || tComponent(suite_core_lib_1.SuiteCoreComponentId, suite_core_lib_1.SuiteCoreStringKey.Common_EmailVerification),
16
+ success: labels.success || tComponent(suite_core_lib_1.SuiteCoreComponentId, suite_core_lib_1.SuiteCoreStringKey.EmailVerification_Success),
17
+ failed: labels.failed || tComponent(suite_core_lib_1.SuiteCoreComponentId, suite_core_lib_1.SuiteCoreStringKey.EmailVerification_Failed),
18
+ noToken: labels.noToken || tComponent(suite_core_lib_1.SuiteCoreComponentId, suite_core_lib_1.SuiteCoreStringKey.NoVerificationTokenProvided),
19
+ proceedToLogin: labels.proceedToLogin || tComponent(suite_core_lib_1.SuiteCoreComponentId, suite_core_lib_1.SuiteCoreStringKey.ProceedToLogin),
20
+ contactSupport: labels.contactSupport || tComponent(suite_core_lib_1.SuiteCoreComponentId, suite_core_lib_1.SuiteCoreStringKey.HavingTroubleContactSupport),
21
+ requestNewEmail: labels.requestNewEmail || tComponent(suite_core_lib_1.SuiteCoreComponentId, suite_core_lib_1.SuiteCoreStringKey.RequestNewVerificationEmail),
22
22
  };
23
23
  (0, react_1.useEffect)(() => {
24
24
  const verifyEmail = async (verificationToken) => {
@@ -1 +1 @@
1
- {"version":3,"file":"AuthProvider.d.ts","sourceRoot":"","sources":["../../../../../packages/digitaldefiance-express-suite-react-components/src/contexts/AuthProvider.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"AuthProvider.d.ts","sourceRoot":"","sources":["../../../../../packages/digitaldefiance-express-suite-react-components/src/contexts/AuthProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,cAAc,EAE/B,WAAW,EACX,YAAY,EACZ,YAAY,EAIb,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAEL,YAAY,EAEb,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,EAEL,SAAS,EAMV,MAAM,OAAO,CAAC;AAOf,OAAO,EAAE,eAAe,EAAE,eAAe,EAA4C,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAEzI,MAAM,WAAW,eAAe;IAC9B;;OAEG;IACH,KAAK,EAAE,OAAO,CAAC;IACf;;OAEG;IACH,SAAS,EAAE,MAAM,CAAC;IAClB;;;;;;;;OAQG;IACH,eAAe,EAAE,CACf,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,OAAO,EAChB,eAAe,EAAE,OAAO,EACxB,WAAW,CAAC,EAAE,MAAM,KACjB,OAAO,CACR;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GACzE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CACrC,CAAC;IACF;;;OAGG;IACH,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB;;;;;OAKG;IACH,cAAc,EAAE,CACd,eAAe,EAAE,MAAM,EACvB,WAAW,EAAE,MAAM,KAChB,OAAO,CACR,eAAe,GACf;QACE,KAAK,EAAE,MAAM,CAAC;QACd,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;KAChC,CACJ,CAAC;IACF,aAAa,EAAE,MAAM,IAAI,CAAC;IAC1B,WAAW,EAAE,MAAM,IAAI,CAAC;IACxB,YAAY,EAAE,YAAY,CAAC;IAC3B,WAAW,EAAE,CACX,QAAQ,EAAE,YAAY,EACtB,QAAQ,CAAC,EAAE,MAAM,EACjB,KAAK,CAAC,EAAE,WAAW,EACnB,qBAAqB,CAAC,EAAE,MAAM,EAC9B,mBAAmB,CAAC,EAAE,MAAM,KACzB,OAAO,CACR;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,eAAe,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GACxD;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CACxC,CAAC;IACF,mBAAmB,EAAE,CACnB,QAAQ,EAAE,YAAY,EACtB,KAAK,EAAE,MAAM,EACb,QAAQ,CAAC,EAAE,MAAM,EACjB,KAAK,CAAC,EAAE,WAAW,EACnB,qBAAqB,CAAC,EAAE,MAAM,EAC9B,mBAAmB,CAAC,EAAE,MAAM,KACzB,OAAO,CACR;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,eAAe,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,GACzE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CACxC,CAAC;IACF,eAAe,EAAE,OAAO,CAAC;IAEzB,cAAc,EAAE,OAAO,CAAC;IACxB,wBAAwB,CAAC,EAAE,MAAM,OAAO,CAAC;IACzC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,QAAQ,CAAC,EAAE,YAAY,CAAC;IACxB,yBAAyB,EAAE,MAAM,CAAC;IAClC,aAAa,EAAE,CAAC,QAAQ,EAAE,YAAY,EAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,eAAe,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC7L,iBAAiB,EAAE,CACjB,QAAQ,CAAC,EAAE,MAAM,EACjB,KAAK,CAAC,EAAE,WAAW,KAChB,OAAO,CAAC,MAAM,GAAG;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC7D,YAAY,EAAE,MAAM,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,eAAe,CAAA;KAAE,CAAC,CAAC;IACtE,QAAQ,EAAE,CACR,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,QAAQ,CAAC,EAAE,MAAM,KACd,OAAO,CACR;QACE,OAAO,EAAE,OAAO,CAAC;QACjB,OAAO,EAAE,MAAM,CAAC;QAChB,QAAQ,EAAE,MAAM,CAAC;KAClB,GACD;QACE,KAAK,EAAE,MAAM,CAAC;QACd,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,GAAG,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;KAC/C,CACJ,CAAC;IACF,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,eAAe,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACvD;;;OAGG;IACH,wBAAwB,EAAE,MAAM,MAAM,CAAC;IACvC;;;OAGG;IACH,sBAAsB,EAAE,MAAM,MAAM,CAAC;IACrC,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,WAAW,EAAE,CAAC,QAAQ,EAAE,YAAY,EAAE,eAAe,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACxE,4BAA4B,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACxD,0BAA0B,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACtD,kBAAkB,EAAE,CAAC,QAAQ,EAAE,YAAY,EAAE,QAAQ,EAAE,YAAY,EAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACvM,OAAO,EAAE,CAAC,IAAI,EAAE,eAAe,GAAG,IAAI,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACzD,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,eAAe,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9D,IAAI,EAAE,cAAc,GAAG,IAAI,CAAC;IAC5B,QAAQ,EAAE,eAAe,GAAG,IAAI,CAAC;IACjC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,uBAAuB,EAAE,MAAM,CAAC;IAChC,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CAClD;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,EAAE,SAAS,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,UAAU,CAAC;IACtB,WAAW,EAAE,YAAY,CAAC;IAC1B;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;CACvB,CAAC;AAEF,eAAO,MAAM,WAAW,0CAEvB,CAAC;AAkhBF,eAAO,MAAM,YAAY,GAAI,yDAAyD,iBAAiB,4CAMtG,CAAC;AAEF,eAAO,MAAM,OAAO,uBAEnB,CAAC"}
@@ -6,6 +6,7 @@ const ecies_lib_1 = require("@digitaldefiance/ecies-lib");
6
6
  const i18n_lib_1 = require("@digitaldefiance/i18n-lib");
7
7
  const react_1 = require("react");
8
8
  const I18nProvider_1 = require("./I18nProvider");
9
+ const ThemeProvider_1 = require("./ThemeProvider");
9
10
  const authService_1 = require("../services/authService");
10
11
  const authenticatedApi_1 = require("../services/authenticatedApi");
11
12
  const useExpiringValue_1 = require("../hooks/useExpiringValue");
@@ -14,6 +15,7 @@ const suite_core_lib_1 = require("@digitaldefiance/suite-core-lib");
14
15
  exports.AuthContext = (0, react_1.createContext)({});
15
16
  const AuthProviderInner = ({ children, baseUrl, constants, eciesConfig, onLogout }) => {
16
17
  const { changeLanguage, currentLanguage, t, tComponent } = (0, I18nProvider_1.useI18n)();
18
+ const { setColorMode } = (0, ThemeProvider_1.useTheme)();
17
19
  const authService = (0, react_1.useMemo)(() => (0, authService_1.createAuthService)(constants, baseUrl, eciesConfig), [constants, baseUrl, eciesConfig]);
18
20
  const authenticatedApi = (0, react_1.useMemo)(() => (0, authenticatedApi_1.createAuthenticatedApiClient)(baseUrl), [baseUrl]);
19
21
  // Use the custom hooks for expiring values
@@ -97,6 +99,8 @@ const AuthProviderInner = ({ children, baseUrl, constants, eciesConfig, onLogout
97
99
  setIsGlobalAdmin(userData.roles.some((r) => r.admin));
98
100
  setIsAuthenticated(true);
99
101
  setToken(token);
102
+ // Set theme based on user's darkMode preference
103
+ setColorMode(userData.darkMode ? 'dark' : 'light');
100
104
  }
101
105
  }
102
106
  catch (error) {
@@ -109,7 +113,7 @@ const AuthProviderInner = ({ children, baseUrl, constants, eciesConfig, onLogout
109
113
  setLoading(false);
110
114
  setIsCheckingAuth(false);
111
115
  }
112
- }, [authService, clearMnemonic, clearWallet]);
116
+ }, [authService, clearMnemonic, clearWallet, setColorMode]);
113
117
  (0, react_1.useEffect)(() => {
114
118
  const token = localStorage.getItem('authToken');
115
119
  if (token) {
@@ -137,10 +141,12 @@ const AuthProviderInner = ({ children, baseUrl, constants, eciesConfig, onLogout
137
141
  setAuthState((prev) => prev + 1);
138
142
  localStorage.setItem('authToken', loginResult.token);
139
143
  localStorage.setItem('user', JSON.stringify(loginResult.user));
144
+ // Set theme based on user's darkMode preference
145
+ setColorMode(loginResult.user.darkMode ? 'dark' : 'light');
140
146
  return loginResult;
141
147
  }
142
148
  return loginResult;
143
- }, [authService, setMnemonic, setWallet]);
149
+ }, [authService, setMnemonic, setWallet, setColorMode]);
144
150
  const emailChallengeLogin = (0, react_1.useCallback)(async (mnemonic, token, username, email, expireMnemonicSeconds, expireWalletSeconds) => {
145
151
  setLoading(true);
146
152
  const loginResult = await authService.emailChallengeLogin(mnemonic, token, username, email);
@@ -156,10 +162,12 @@ const AuthProviderInner = ({ children, baseUrl, constants, eciesConfig, onLogout
156
162
  setAuthState((prev) => prev + 1);
157
163
  localStorage.setItem('authToken', loginResult.token);
158
164
  localStorage.setItem('user', JSON.stringify(loginResult.user));
165
+ // Set theme based on user's darkMode preference
166
+ setColorMode(loginResult.user.darkMode ? 'dark' : 'light');
159
167
  return loginResult;
160
168
  }
161
169
  return loginResult;
162
- }, [authService, setMnemonic, setWallet]);
170
+ }, [authService, setMnemonic, setWallet, setColorMode]);
163
171
  const getPasswordLoginService = (0, react_1.useCallback)(() => {
164
172
  const eciesService = new ecies_lib_1.ECIESService(eciesConfig);
165
173
  return new ecies_lib_1.PasswordLoginService(eciesService, new ecies_lib_1.Pbkdf2Service(ecies_lib_1.Constants.PBKDF2_PROFILES, ecies_lib_1.Constants.ECIES, ecies_lib_1.Constants.PBKDF2));
@@ -170,7 +178,7 @@ const AuthProviderInner = ({ children, baseUrl, constants, eciesConfig, onLogout
170
178
  }, []);
171
179
  const passwordLogin = (0, react_1.useCallback)(async (password, username, email) => {
172
180
  if (!isPasswordLoginAvailable()) {
173
- return { error: t(tComponent(suite_core_lib_1.SuiteCoreComponentId, suite_core_lib_1.SuiteCoreStringKey.Error_Login_PasswordLoginNotSetup)), errorType: 'PasswordLoginNotSetup' };
181
+ return { error: tComponent(suite_core_lib_1.SuiteCoreComponentId, suite_core_lib_1.SuiteCoreStringKey.Error_Login_PasswordLoginNotSetup), errorType: 'PasswordLoginNotSetup' };
174
182
  }
175
183
  setLoading(true);
176
184
  const passwordLoginService = getPasswordLoginService();
@@ -179,8 +187,12 @@ const AuthProviderInner = ({ children, baseUrl, constants, eciesConfig, onLogout
179
187
  setLoading(false);
180
188
  setWallet(wallet);
181
189
  setMnemonic(mnemonic);
190
+ // Set theme based on user's darkMode preference if login succeeded
191
+ if ('user' in loginResult) {
192
+ setColorMode(loginResult.user.darkMode ? 'dark' : 'light');
193
+ }
182
194
  return loginResult;
183
- }, [authService, getPasswordLoginService, setMnemonic, setWallet, t, tComponent, isPasswordLoginAvailable]);
195
+ }, [authService, getPasswordLoginService, setMnemonic, setWallet, t, tComponent, isPasswordLoginAvailable, setColorMode]);
184
196
  const refreshToken = (0, react_1.useCallback)(async () => {
185
197
  try {
186
198
  const result = await authService.refreshToken();
@@ -216,11 +228,11 @@ const AuthProviderInner = ({ children, baseUrl, constants, eciesConfig, onLogout
216
228
  setLoading(false);
217
229
  setWallet(wallet);
218
230
  setMnemonic(mnemonic);
219
- return { success: true, message: t(tComponent(suite_core_lib_1.SuiteCoreComponentId, suite_core_lib_1.SuiteCoreStringKey.PasswordLogin_Setup_Success)) };
231
+ return { success: true, message: tComponent(suite_core_lib_1.SuiteCoreComponentId, suite_core_lib_1.SuiteCoreStringKey.PasswordLogin_Setup_Success) };
220
232
  }
221
233
  catch {
222
234
  setLoading(false);
223
- return { success: false, message: t(tComponent(suite_core_lib_1.SuiteCoreComponentId, suite_core_lib_1.SuiteCoreStringKey.PasswordLogin_Setup_Failure)) };
235
+ return { success: false, message: tComponent(suite_core_lib_1.SuiteCoreComponentId, suite_core_lib_1.SuiteCoreStringKey.PasswordLogin_Setup_Failure) };
224
236
  }
225
237
  }, [setMnemonic, setWallet, t, tComponent]);
226
238
  const backupCodeLogin = (0, react_1.useCallback)(async (identifier, code, isEmail, recoverMnemonic, newPassword) => {
@@ -232,6 +244,8 @@ const AuthProviderInner = ({ children, baseUrl, constants, eciesConfig, onLogout
232
244
  if (loginResult.user) {
233
245
  setUser(loginResult.user);
234
246
  setIsAuthenticated(true);
247
+ // Set theme based on user's darkMode preference
248
+ setColorMode(loginResult.user.darkMode ? 'dark' : 'light');
235
249
  }
236
250
  setAuthState((prev) => prev + 1);
237
251
  return {
@@ -242,7 +256,7 @@ const AuthProviderInner = ({ children, baseUrl, constants, eciesConfig, onLogout
242
256
  };
243
257
  }
244
258
  return loginResult;
245
- }, [baseUrl]);
259
+ }, [baseUrl, setColorMode]);
246
260
  const logout = (0, react_1.useCallback)(async () => {
247
261
  localStorage.removeItem('user');
248
262
  localStorage.removeItem('authToken');
@@ -270,7 +284,7 @@ const AuthProviderInner = ({ children, baseUrl, constants, eciesConfig, onLogout
270
284
  }, [baseUrl]);
271
285
  const changePassword = (0, react_1.useCallback)(async (currentPassword, newPassword) => {
272
286
  if (!isPasswordLoginAvailable()) {
273
- return { error: t(tComponent(suite_core_lib_1.SuiteCoreComponentId, suite_core_lib_1.SuiteCoreStringKey.Error_Login_PasswordLoginNotSetup)), errorType: 'PasswordLoginNotSetup' };
287
+ return { error: tComponent(suite_core_lib_1.SuiteCoreComponentId, suite_core_lib_1.SuiteCoreStringKey.Error_Login_PasswordLoginNotSetup), errorType: 'PasswordLoginNotSetup' };
274
288
  }
275
289
  setLoading(true);
276
290
  try {
@@ -278,13 +292,13 @@ const AuthProviderInner = ({ children, baseUrl, constants, eciesConfig, onLogout
278
292
  const { mnemonic, wallet } = await passwordLoginService.getWalletAndMnemonicFromLocalStorageBundle(new ecies_lib_1.SecureString(currentPassword));
279
293
  if (!mnemonic) {
280
294
  setLoading(false);
281
- return { error: t(tComponent(suite_core_lib_1.SuiteCoreComponentId, suite_core_lib_1.SuiteCoreStringKey.PasswordLogin_InvalidCurrentPassword)), errorType: 'InvalidCurrentPassword' };
295
+ return { error: tComponent(suite_core_lib_1.SuiteCoreComponentId, suite_core_lib_1.SuiteCoreStringKey.PasswordLogin_InvalidCurrentPassword), errorType: 'InvalidCurrentPassword' };
282
296
  }
283
297
  await passwordLoginService.setupPasswordLoginLocalStorageBundle(mnemonic, new ecies_lib_1.SecureString(newPassword));
284
298
  setLoading(false);
285
299
  setWallet(wallet);
286
300
  setMnemonic(mnemonic);
287
- return { success: true, message: t(tComponent(suite_core_lib_1.SuiteCoreComponentId, suite_core_lib_1.SuiteCoreStringKey.PasswordChange_Success)) };
301
+ return { success: true, message: tComponent(suite_core_lib_1.SuiteCoreComponentId, suite_core_lib_1.SuiteCoreStringKey.PasswordChange_Success) };
288
302
  }
289
303
  catch (error) {
290
304
  setLoading(false);
@@ -5,6 +5,7 @@ import { IMenuConfig } from '../interfaces/IMenuConfig';
5
5
  interface MenuProviderProps {
6
6
  children: ReactNode;
7
7
  menuConfigs?: IMenuConfig[];
8
+ enableBackupCodes?: boolean;
8
9
  }
9
10
  interface MenuContextType {
10
11
  menuOptions: IMenuOption[];
@@ -1 +1 @@
1
- {"version":3,"file":"MenuContext.d.ts","sourceRoot":"","sources":["../../../../../packages/digitaldefiance-express-suite-react-components/src/contexts/MenuContext.tsx"],"names":[],"mappings":"AAgBA,OAAO,EACL,EAAE,EACF,SAAS,EAQV,MAAM,OAAO,CAAC;AAEf,OAAO,EAAE,QAAQ,EAAa,MAAM,mBAAmB,CAAC;AAExD,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAGxD,UAAU,iBAAiB;IACzB,QAAQ,EAAE,SAAS,CAAC;IACpB,WAAW,CAAC,EAAE,WAAW,EAAE,CAAC;CAC7B;AAED,UAAU,eAAe;IACvB,WAAW,EAAE,WAAW,EAAE,CAAC;IAC3B,cAAc,EAAE,CACd,QAAQ,EAAE,QAAQ,EAClB,eAAe,EAAE,OAAO,KACrB,WAAW,EAAE,CAAC;IACnB,kBAAkB,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,MAAM,IAAI,CAAC;IACxD,mBAAmB,EAAE,CAAC,OAAO,EAAE,WAAW,EAAE,KAAK,MAAM,IAAI,CAAC;IAC5D,WAAW,EAAE,MAAM,KAAK,CAAC,WAAW,CAAC,CAAC;CACvC;AAID,eAAO,MAAM,YAAY,EAAE,EAAE,CAAC,iBAAiB,CAwO9C,CAAC;AAEF,eAAO,MAAM,OAAO,QAAO,eAM1B,CAAC"}
1
+ {"version":3,"file":"MenuContext.d.ts","sourceRoot":"","sources":["../../../../../packages/digitaldefiance-express-suite-react-components/src/contexts/MenuContext.tsx"],"names":[],"mappings":"AAiBA,OAAO,EACL,EAAE,EACF,SAAS,EAQV,MAAM,OAAO,CAAC;AAEf,OAAO,EAAE,QAAQ,EAAa,MAAM,mBAAmB,CAAC;AAExD,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAGxD,UAAU,iBAAiB;IACzB,QAAQ,EAAE,SAAS,CAAC;IACpB,WAAW,CAAC,EAAE,WAAW,EAAE,CAAC;IAC5B,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,UAAU,eAAe;IACvB,WAAW,EAAE,WAAW,EAAE,CAAC;IAC3B,cAAc,EAAE,CACd,QAAQ,EAAE,QAAQ,EAClB,eAAe,EAAE,OAAO,KACrB,WAAW,EAAE,CAAC;IACnB,kBAAkB,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,MAAM,IAAI,CAAC;IACxD,mBAAmB,EAAE,CAAC,OAAO,EAAE,WAAW,EAAE,KAAK,MAAM,IAAI,CAAC;IAC5D,WAAW,EAAE,MAAM,KAAK,CAAC,WAAW,CAAC,CAAC;CACvC;AAID,eAAO,MAAM,YAAY,EAAE,EAAE,CAAC,iBAAiB,CAiP9C,CAAC;AAEF,eAAO,MAAM,OAAO,QAAO,eAM1B,CAAC"}
@@ -12,11 +12,11 @@ const MenuType_1 = require("../types/MenuType");
12
12
  const I18nProvider_1 = require("./I18nProvider");
13
13
  const ThemeProvider_1 = require("./ThemeProvider");
14
14
  const MenuContext = (0, react_1.createContext)(undefined);
15
- const MenuProvider = ({ children, menuConfigs = [] }) => {
15
+ const MenuProvider = ({ children, menuConfigs = [], enableBackupCodes = true }) => {
16
16
  const { userData: user, isAuthenticated, mnemonic, clearMnemonic, wallet, clearWallet } = (0, AuthProvider_1.useAuth)();
17
17
  const registeredMenuOptions = (0, react_1.useRef)(new Set());
18
18
  const [registeredOptions, setRegisteredOptions] = (0, react_1.useState)(new Map());
19
- const { t, tComponent } = (0, I18nProvider_1.useI18n)();
19
+ const { tComponent } = (0, I18nProvider_1.useI18n)();
20
20
  const { mode, toggleColorMode } = (0, ThemeProvider_1.useTheme)();
21
21
  const registerMenuOption = (0, react_1.useCallback)((option) => {
22
22
  const unregister = () => {
@@ -47,7 +47,7 @@ const MenuProvider = ({ children, menuConfigs = [] }) => {
47
47
  const baseOptions = [
48
48
  {
49
49
  id: 'dashboard',
50
- label: t(tComponent(suite_core_lib_1.SuiteCoreComponentId, suite_core_lib_2.SuiteCoreStringKey.Common_Dashboard)),
50
+ label: tComponent(suite_core_lib_1.SuiteCoreComponentId, suite_core_lib_2.SuiteCoreStringKey.Common_Dashboard),
51
51
  icon: (0, jsx_runtime_1.jsx)(icons_material_1.Dashboard, {}),
52
52
  link: '/dashboard',
53
53
  requiresAuth: true,
@@ -64,7 +64,7 @@ const MenuProvider = ({ children, menuConfigs = [] }) => {
64
64
  },
65
65
  {
66
66
  id: 'logout',
67
- label: t(tComponent(suite_core_lib_1.SuiteCoreComponentId, suite_core_lib_2.SuiteCoreStringKey.LogoutButton)),
67
+ label: tComponent(suite_core_lib_1.SuiteCoreComponentId, suite_core_lib_2.SuiteCoreStringKey.LogoutButton),
68
68
  icon: (0, jsx_runtime_1.jsx)(icons_material_1.ExitToApp, {}),
69
69
  link: '/logout',
70
70
  requiresAuth: true,
@@ -73,7 +73,7 @@ const MenuProvider = ({ children, menuConfigs = [] }) => {
73
73
  },
74
74
  {
75
75
  id: 'login',
76
- label: t(tComponent(suite_core_lib_1.SuiteCoreComponentId, suite_core_lib_2.SuiteCoreStringKey.Login_LoginButton)),
76
+ label: tComponent(suite_core_lib_1.SuiteCoreComponentId, suite_core_lib_2.SuiteCoreStringKey.Login_LoginButton),
77
77
  icon: (0, jsx_runtime_1.jsx)(icons_material_1.Login, {}),
78
78
  link: '/login',
79
79
  requiresAuth: false,
@@ -82,7 +82,7 @@ const MenuProvider = ({ children, menuConfigs = [] }) => {
82
82
  },
83
83
  {
84
84
  id: 'register',
85
- label: t(tComponent(suite_core_lib_1.SuiteCoreComponentId, suite_core_lib_2.SuiteCoreStringKey.RegisterButton)),
85
+ label: tComponent(suite_core_lib_1.SuiteCoreComponentId, suite_core_lib_2.SuiteCoreStringKey.RegisterButton),
86
86
  icon: (0, jsx_runtime_1.jsx)(icons_material_1.PersonAdd, {}),
87
87
  link: '/register',
88
88
  requiresAuth: false,
@@ -91,7 +91,7 @@ const MenuProvider = ({ children, menuConfigs = [] }) => {
91
91
  },
92
92
  {
93
93
  id: 'forgot-password',
94
- label: t(tComponent(suite_core_lib_1.SuiteCoreComponentId, suite_core_lib_2.SuiteCoreStringKey.ForgotPassword_Title)),
94
+ label: tComponent(suite_core_lib_1.SuiteCoreComponentId, suite_core_lib_2.SuiteCoreStringKey.ForgotPassword_Title),
95
95
  icon: (0, jsx_runtime_1.jsx)(icons_material_1.LockOpen, {}),
96
96
  link: '/forgot-password',
97
97
  requiresAuth: false,
@@ -100,31 +100,31 @@ const MenuProvider = ({ children, menuConfigs = [] }) => {
100
100
  },
101
101
  {
102
102
  id: 'change-password',
103
- label: t(tComponent(suite_core_lib_1.SuiteCoreComponentId, suite_core_lib_2.SuiteCoreStringKey.Common_ChangePassword)),
103
+ label: tComponent(suite_core_lib_1.SuiteCoreComponentId, suite_core_lib_2.SuiteCoreStringKey.Common_ChangePassword),
104
104
  icon: (0, jsx_runtime_1.jsx)(icons_material_1.LockReset, {}),
105
105
  link: '/change-password',
106
106
  requiresAuth: true,
107
107
  includeOnMenus: [MenuType_1.MenuTypes.UserMenu, MenuType_1.MenuTypes.SideMenu],
108
108
  index: index++,
109
109
  },
110
- {
111
- id: 'backup-code',
112
- label: t(tComponent(suite_core_lib_1.SuiteCoreComponentId, suite_core_lib_2.SuiteCoreStringKey.BackupCodeRecovery_Title)),
113
- icon: (0, jsx_runtime_1.jsx)(icons_material_1.Key, {}),
114
- link: '/backup-code',
115
- requiresAuth: false,
116
- includeOnMenus: [MenuType_1.MenuTypes.UserMenu, MenuType_1.MenuTypes.SideMenu],
117
- index: index++,
118
- },
119
- {
120
- id: 'backup-codes',
121
- label: t(tComponent(suite_core_lib_1.SuiteCoreComponentId, suite_core_lib_2.SuiteCoreStringKey.BackupCodeRecovery_GenerateNewCodes)),
122
- icon: (0, jsx_runtime_1.jsx)(icons_material_1.Autorenew, {}),
123
- link: '/backup-codes',
124
- requiresAuth: true,
125
- includeOnMenus: [MenuType_1.MenuTypes.UserMenu, MenuType_1.MenuTypes.SideMenu],
126
- index: index++,
127
- },
110
+ ...(enableBackupCodes ? [{
111
+ id: 'backup-code',
112
+ label: tComponent(suite_core_lib_1.SuiteCoreComponentId, suite_core_lib_2.SuiteCoreStringKey.BackupCodeRecovery_Title),
113
+ icon: (0, jsx_runtime_1.jsx)(icons_material_1.Key, {}),
114
+ link: '/backup-code',
115
+ requiresAuth: false,
116
+ includeOnMenus: [MenuType_1.MenuTypes.UserMenu, MenuType_1.MenuTypes.SideMenu],
117
+ index: index++,
118
+ },
119
+ {
120
+ id: 'backup-codes',
121
+ label: tComponent(suite_core_lib_1.SuiteCoreComponentId, suite_core_lib_2.SuiteCoreStringKey.BackupCodeRecovery_GenerateNewCodes),
122
+ icon: (0, jsx_runtime_1.jsx)(icons_material_1.Autorenew, {}),
123
+ link: '/backup-codes',
124
+ requiresAuth: true,
125
+ includeOnMenus: [MenuType_1.MenuTypes.UserMenu, MenuType_1.MenuTypes.SideMenu],
126
+ index: index++,
127
+ }] : []),
128
128
  {
129
129
  id: 'divider',
130
130
  label: '',
@@ -135,7 +135,7 @@ const MenuProvider = ({ children, menuConfigs = [] }) => {
135
135
  },
136
136
  {
137
137
  id: 'clear-mnemonic',
138
- label: t(tComponent(suite_core_lib_1.SuiteCoreComponentId, suite_core_lib_2.SuiteCoreStringKey.Common_ClearMnemonic)),
138
+ label: tComponent(suite_core_lib_1.SuiteCoreComponentId, suite_core_lib_2.SuiteCoreStringKey.Common_ClearMnemonic),
139
139
  action: clearMnemonic,
140
140
  icon: (0, jsx_runtime_1.jsx)(icons_material_1.Key, {}),
141
141
  requiresAuth: true,
@@ -145,7 +145,7 @@ const MenuProvider = ({ children, menuConfigs = [] }) => {
145
145
  },
146
146
  {
147
147
  id: 'clear-wallet',
148
- label: t(tComponent(suite_core_lib_1.SuiteCoreComponentId, suite_core_lib_2.SuiteCoreStringKey.Common_ClearWallet)),
148
+ label: tComponent(suite_core_lib_1.SuiteCoreComponentId, suite_core_lib_2.SuiteCoreStringKey.Common_ClearWallet),
149
149
  action: clearWallet,
150
150
  icon: (0, jsx_runtime_1.jsx)(icons_material_1.Key, {}),
151
151
  requiresAuth: true,
@@ -165,18 +165,27 @@ const MenuProvider = ({ children, menuConfigs = [] }) => {
165
165
  {
166
166
  id: 'theme-toggle',
167
167
  label: mode === 'dark'
168
- ? t(tComponent(suite_core_lib_1.SuiteCoreComponentId, suite_core_lib_2.SuiteCoreStringKey.Common_ThemeToggle_Light))
169
- : t(tComponent(suite_core_lib_1.SuiteCoreComponentId, suite_core_lib_2.SuiteCoreStringKey.Common_ThemeToggle_Dark)),
168
+ ? tComponent(suite_core_lib_1.SuiteCoreComponentId, suite_core_lib_2.SuiteCoreStringKey.Common_ThemeToggle_Light)
169
+ : tComponent(suite_core_lib_1.SuiteCoreComponentId, suite_core_lib_2.SuiteCoreStringKey.Common_ThemeToggle_Dark),
170
170
  icon: mode === 'dark' ? (0, jsx_runtime_1.jsx)(icons_material_1.Brightness7, {}) : (0, jsx_runtime_1.jsx)(icons_material_1.Brightness4, {}),
171
171
  includeOnMenus: [MenuType_1.MenuTypes.SideMenu],
172
172
  index: index++,
173
173
  requiresAuth: undefined,
174
174
  action: toggleColorMode,
175
175
  },
176
+ {
177
+ id: 'user-settings',
178
+ label: tComponent(suite_core_lib_1.SuiteCoreComponentId, suite_core_lib_2.SuiteCoreStringKey.Settings_Title),
179
+ icon: (0, jsx_runtime_1.jsx)(icons_material_1.Settings, {}),
180
+ link: '/user-settings',
181
+ requiresAuth: true,
182
+ includeOnMenus: [MenuType_1.MenuTypes.UserMenu, MenuType_1.MenuTypes.SideMenu],
183
+ index: index++,
184
+ }
176
185
  ];
177
186
  const allOptions = [...baseOptions, ...registeredOptions.values()];
178
187
  return allOptions.sort((a, b) => a.index - b.index);
179
- }, [t, tComponent, registeredOptions, user?.roles, mode, toggleColorMode]);
188
+ }, [tComponent, registeredOptions, user?.roles, mode, toggleColorMode]);
180
189
  const getMenuOptions = (0, react_1.useCallback)((menuType, includeDividers) => {
181
190
  const MenuFilter = (o) => {
182
191
  // Apply the custom filter first