@digitaldefiance/express-suite-react-components 2.5.13 → 2.8.5

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.
package/README.md CHANGED
@@ -362,6 +362,29 @@ MIT © Digital Defiance
362
362
 
363
363
  ## ChangeLog
364
364
 
365
+ ### Version 2.7.5
366
+
367
+ **Type Safety Improvements**
368
+
369
+ - **ELIMINATED**: All unsafe `as any` type casts from production code
370
+ - **IMPROVED**: Window interface extension for `APP_CONFIG` property
371
+ - **ENHANCED**: Navigation state type handling with proper type guards
372
+ - **IMPROVED**: Menu option link type to support both react-router `To` and state passing
373
+ - **VERIFIED**: All 227 tests passing with full type safety
374
+ - **VERIFIED**: TypeScript compilation successful with strict checking
375
+
376
+ **Technical Details**
377
+
378
+ - Added local Window interface extension in TopMenu component for APP_CONFIG
379
+ - Replaced `(option.link as any).state` with type-safe property access using `'state' in option.link` guard
380
+ - Enhanced `IMenuOption.link` to support `To | { pathname: string; state?: unknown }` for flexible navigation
381
+ - Updated `tsconfig.lib.json` to include global type definitions
382
+ - Fixed `typeRoots` path in `tsconfig.base.json`
383
+
384
+ ### Version 2.5.14
385
+
386
+ - Update suite-core-lib
387
+
365
388
  ### Version 2.5.13
366
389
 
367
390
  - Try to fix saving of settings
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@digitaldefiance/express-suite-react-components",
3
- "version": "2.5.13",
3
+ "version": "2.8.5",
4
4
  "description": "React MUI components for Digital Defiance Express Suite",
5
5
  "main": "src/index.js",
6
6
  "types": "src/index.d.ts",
@@ -25,8 +25,8 @@
25
25
  "react-router-dom": "6.29.0"
26
26
  },
27
27
  "dependencies": {
28
- "@digitaldefiance/i18n-lib": "3.6.4",
29
- "@digitaldefiance/suite-core-lib": "^2.2.22",
28
+ "@digitaldefiance/i18n-lib": "3.7.5",
29
+ "@digitaldefiance/suite-core-lib": "3.5.7",
30
30
  "@emotion/react": "^11.14.0",
31
31
  "@emotion/styled": "^11.14.0",
32
32
  "@mui/icons-material": "^7.0.2",
@@ -1 +1 @@
1
- {"version":3,"file":"SideMenu.d.ts","sourceRoot":"","sources":["../../../../../packages/digitaldefiance-express-suite-react-components/src/components/SideMenu.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAO3B,UAAU,aAAa;IACrB,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,eAAO,MAAM,QAAQ,EAAE,EAAE,CAAC,aAAa,CA4BtC,CAAC;AAEF,eAAe,QAAQ,CAAC"}
1
+ {"version":3,"file":"SideMenu.d.ts","sourceRoot":"","sources":["../../../../../packages/digitaldefiance-express-suite-react-components/src/components/SideMenu.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAO3B,UAAU,aAAa;IACrB,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,eAAO,MAAM,QAAQ,EAAE,EAAE,CAAC,aAAa,CA8BtC,CAAC;AAEF,eAAe,QAAQ,CAAC"}
@@ -4,8 +4,8 @@ exports.SideMenu = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const material_1 = require("@mui/material");
6
6
  const react_router_dom_1 = require("react-router-dom");
7
- const MenuType_1 = require("../types/MenuType");
8
7
  const MenuContext_1 = require("../contexts/MenuContext");
8
+ const MenuType_1 = require("../types/MenuType");
9
9
  const SideMenuListItem_1 = require("./SideMenuListItem");
10
10
  const SideMenu = ({ isOpen, onClose }) => {
11
11
  const { getMenuOptions } = (0, MenuContext_1.useMenu)();
@@ -15,7 +15,7 @@ const SideMenu = ({ isOpen, onClose }) => {
15
15
  if (typeof link === 'string') {
16
16
  navigate(link);
17
17
  }
18
- else {
18
+ else if (link.pathname) {
19
19
  navigate(link.pathname, { state: link.state });
20
20
  }
21
21
  };
@@ -3,10 +3,10 @@ import { IMenuOption } from '../interfaces';
3
3
  export interface SideMenuListItemProps {
4
4
  menuItem: IMenuOption;
5
5
  onClose: () => void;
6
- onNavigate?: (link: string | {
6
+ onNavigate?: (link: string | Partial<{
7
7
  pathname: string;
8
- state?: any;
9
- }) => void;
8
+ state?: unknown;
9
+ }>) => void;
10
10
  }
11
11
  export declare const SideMenuListItem: FC<SideMenuListItemProps>;
12
12
  export default SideMenuListItem;
@@ -1 +1 @@
1
- {"version":3,"file":"SideMenuListItem.d.ts","sourceRoot":"","sources":["../../../../../packages/digitaldefiance-express-suite-react-components/src/components/SideMenuListItem.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,EAAE,EAAe,MAAM,OAAO,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,WAAW,CAAC;IACtB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,GAAG,CAAA;KAAE,KAAK,IAAI,CAAC;CACzE;AAED,eAAO,MAAM,gBAAgB,EAAE,EAAE,CAAC,qBAAqB,CA+CtD,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
1
+ {"version":3,"file":"SideMenuListItem.d.ts","sourceRoot":"","sources":["../../../../../packages/digitaldefiance-express-suite-react-components/src/components/SideMenuListItem.tsx"],"names":[],"mappings":"AAMA,OAAO,EAAE,EAAE,EAAe,MAAM,OAAO,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,WAAW,CAAC;IACtB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,UAAU,CAAC,EAAE,CACX,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC,KAC1D,IAAI,CAAC;CACX;AAED,eAAO,MAAM,gBAAgB,EAAE,EAAE,CAAC,qBAAqB,CAsDtD,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
@@ -14,8 +14,13 @@ const SideMenuListItem = ({ menuItem, onClose, onNavigate, }) => {
14
14
  if (typeof option.link === 'string') {
15
15
  onNavigate(option.link);
16
16
  }
17
- else if (typeof option.link === 'object' && 'pathname' in option.link && option.link.pathname) {
18
- onNavigate({ pathname: option.link.pathname, state: option.link.state });
17
+ else if (typeof option.link === 'object' &&
18
+ 'pathname' in option.link &&
19
+ option.link.pathname) {
20
+ onNavigate({
21
+ pathname: option.link.pathname,
22
+ state: 'state' in option.link ? option.link.state : undefined,
23
+ });
19
24
  }
20
25
  }
21
26
  onClose();
@@ -1,5 +1,15 @@
1
1
  import React, { FC, ReactElement } from 'react';
2
2
  import { MenuType } from '../types/MenuType';
3
+ declare global {
4
+ interface Window {
5
+ APP_CONFIG?: {
6
+ hostname: string;
7
+ siteTitle: string;
8
+ server: string;
9
+ [key: string]: unknown;
10
+ };
11
+ }
12
+ }
3
13
  export interface AdditionalDropdownMenu {
4
14
  menuType: MenuType;
5
15
  menuIcon: ReactElement;
@@ -1 +1 @@
1
- {"version":3,"file":"TopMenu.d.ts","sourceRoot":"","sources":["../../../../../packages/digitaldefiance-express-suite-react-components/src/components/TopMenu.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,EAAE,EAAE,EAAE,YAAY,EAAwB,MAAM,OAAO,CAAC;AAUtE,OAAO,EAAE,QAAQ,EAAa,MAAM,mBAAmB,CAAC;AAExD,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,QAAQ,CAAC;IACnB,QAAQ,EAAE,YAAY,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,KAAK,CAAC,SAAS,CAAC;IACtB,eAAe,CAAC,EAAE,KAAK,CAAC,sBAAsB,CAAC,CAAC;CACjD;AAED,eAAO,MAAM,OAAO,EAAE,EAAE,CAAC,YAAY,CAmEpC,CAAC;AAEF,eAAe,OAAO,CAAC"}
1
+ {"version":3,"file":"TopMenu.d.ts","sourceRoot":"","sources":["../../../../../packages/digitaldefiance-express-suite-react-components/src/components/TopMenu.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,EAAE,EAAE,EAAE,YAAY,EAAwB,MAAM,OAAO,CAAC;AAKtE,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAO7C,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,UAAU,CAAC,EAAE;YACX,QAAQ,EAAE,MAAM,CAAC;YACjB,SAAS,EAAE,MAAM,CAAC;YAClB,MAAM,EAAE,MAAM,CAAC;YACf,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;SACxB,CAAC;KACH;CACF;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,QAAQ,CAAC;IACnB,QAAQ,EAAE,YAAY,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,KAAK,CAAC,SAAS,CAAC;IACtB,eAAe,CAAC,EAAE,KAAK,CAAC,sBAAsB,CAAC,CAAC;CACjD;AAED,eAAO,MAAM,OAAO,EAAE,EAAE,CAAC,YAAY,CAoFpC,CAAC;AAEF,eAAe,OAAO,CAAC"}
@@ -3,18 +3,18 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.TopMenu = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const jsx_runtime_1 = require("react/jsx-runtime");
6
+ const suite_core_lib_1 = require("@digitaldefiance/suite-core-lib");
6
7
  const Menu_1 = tslib_1.__importDefault(require("@mui/icons-material/Menu"));
7
- const DropdownMenu_1 = require("./DropdownMenu");
8
8
  const material_1 = require("@mui/material");
9
9
  const react_1 = require("react");
10
- const MenuContext_1 = require("../contexts/MenuContext");
11
10
  const react_router_dom_1 = require("react-router-dom");
12
11
  const AuthProvider_1 = require("../contexts/AuthProvider");
13
12
  const I18nProvider_1 = require("../contexts/I18nProvider");
13
+ const MenuContext_1 = require("../contexts/MenuContext");
14
+ const DropdownMenu_1 = require("./DropdownMenu");
14
15
  const SideMenu_1 = require("./SideMenu");
15
16
  const UserLanguageSelector_1 = require("./UserLanguageSelector");
16
17
  const UserMenu_1 = require("./UserMenu");
17
- const suite_core_lib_1 = require("@digitaldefiance/suite-core-lib");
18
18
  const TopMenu = ({ Logo, additionalMenus }) => {
19
19
  const { isAuthenticated } = (0, react_1.useContext)(AuthProvider_1.AuthContext);
20
20
  const { getTopMenus } = (0, MenuContext_1.useMenu)();
@@ -22,9 +22,7 @@ const TopMenu = ({ Logo, additionalMenus }) => {
22
22
  const handleOpenSideMenu = () => setIsSideMenuOpen(true);
23
23
  const handleCloseSideMenu = () => setIsSideMenuOpen(false);
24
24
  const { t, tComponent } = (0, I18nProvider_1.useI18n)();
25
- const appConfig = 'APP_CONFIG' in window
26
- ? window.APP_CONFIG
27
- : undefined;
25
+ const appConfig = window.APP_CONFIG;
28
26
  const siteTitle = tComponent(suite_core_lib_1.SuiteCoreComponentId, suite_core_lib_1.SuiteCoreStringKey.Common_SiteTemplate);
29
27
  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
28
  height: 40,
@@ -32,7 +30,7 @@ const TopMenu = ({ Logo, additionalMenus }) => {
32
30
  marginRight: 2,
33
31
  display: 'flex',
34
32
  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: 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 })] }));
33
+ }, 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
34
  };
37
35
  exports.TopMenu = TopMenu;
38
36
  exports.default = exports.TopMenu;
@@ -1,6 +1,6 @@
1
1
  import { ReactNode } from 'react';
2
- import { MenuType } from '../types/MenuType';
3
2
  import { To } from 'react-router-dom';
3
+ import { MenuType } from '../types/MenuType';
4
4
  export interface IMenuOption {
5
5
  /**
6
6
  * Unique identifier for the menu option
@@ -29,10 +29,11 @@ export interface IMenuOption {
29
29
  /**
30
30
  * Link to navigate to when the menu option is clicked
31
31
  * Mutually exclusive with `action`
32
+ * Can be a string, a react-router To object, or an object with pathname and optional state
32
33
  */
33
34
  link?: To | {
34
35
  pathname: string;
35
- state: any;
36
+ state?: unknown;
36
37
  };
37
38
  /**
38
39
  * Function to execute when the menu option is clicked
@@ -1 +1 @@
1
- {"version":3,"file":"IMenuOption.d.ts","sourceRoot":"","sources":["../../../../../packages/digitaldefiance-express-suite-react-components/src/interfaces/IMenuOption.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAClC,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AAEtC,MAAM,WAAW,WAAW;IAC1B;;OAEG;IACH,EAAE,EAAE,MAAM,CAAC;IACX;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,cAAc,EAAE,QAAQ,EAAE,CAAC;IAC3B;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;OAEG;IACH,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB;;;OAGG;IACH,IAAI,CAAC,EAAE,EAAE,GAAG;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,GAAG,CAAA;KAAE,CAAC;IAC7C;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB;;;;;OAKG;IACH,YAAY,EAAE,OAAO,GAAG,SAAS,CAAC;IAClC;;;;OAIG;IACH,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC;CAC3C"}
1
+ {"version":3,"file":"IMenuOption.d.ts","sourceRoot":"","sources":["../../../../../packages/digitaldefiance-express-suite-react-components/src/interfaces/IMenuOption.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAClC,OAAO,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AACtC,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAE7C,MAAM,WAAW,WAAW;IAC1B;;OAEG;IACH,EAAE,EAAE,MAAM,CAAC;IACX;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,cAAc,EAAE,QAAQ,EAAE,CAAC;IAC3B;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;OAEG;IACH,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB;;;;OAIG;IACH,IAAI,CAAC,EAAE,EAAE,GAAG;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IAClD;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB;;;;;OAKG;IACH,YAAY,EAAE,OAAO,GAAG,SAAS,CAAC;IAClC;;;;OAIG;IACH,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC;CAC3C"}