@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 +23 -0
- package/package.json +3 -3
- package/src/components/SideMenu.d.ts.map +1 -1
- package/src/components/SideMenu.js +2 -2
- package/src/components/SideMenuListItem.d.ts +3 -3
- package/src/components/SideMenuListItem.d.ts.map +1 -1
- package/src/components/SideMenuListItem.js +7 -2
- package/src/components/TopMenu.d.ts +10 -0
- package/src/components/TopMenu.d.ts.map +1 -1
- package/src/components/TopMenu.js +5 -7
- package/src/interfaces/IMenuOption.d.ts +3 -2
- package/src/interfaces/IMenuOption.d.ts.map +1 -1
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
|
|
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.
|
|
29
|
-
"@digitaldefiance/suite-core-lib": "
|
|
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,
|
|
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?:
|
|
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":"
|
|
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' &&
|
|
18
|
-
|
|
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":"
|
|
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 =
|
|
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
|
|
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,
|
|
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"}
|