@databiosphere/findable-ui 9.1.0 → 10.0.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.
- package/lib/components/Layout/components/Header/common/entities.d.ts +2 -2
- package/lib/components/Layout/components/Header/common/utils.d.ts +2 -3
- package/lib/components/Layout/components/Header/common/utils.js +94 -6
- package/lib/components/Layout/components/Header/components/Content/components/Actions/components/Menu/menu.js +2 -2
- package/lib/components/Layout/components/Header/components/Content/components/Navigation/common/utils.d.ts +3 -10
- package/lib/components/Layout/components/Header/components/Content/components/Navigation/common/utils.js +9 -15
- package/lib/components/Layout/components/Header/components/Content/components/Navigation/components/NavigationDrawer/navigationDrawer.d.ts +2 -1
- package/lib/components/Layout/components/Header/components/Content/components/Navigation/components/NavigationDrawer/navigationDrawer.js +10 -15
- package/lib/components/Layout/components/Header/components/Content/components/Navigation/components/NavigationMenu/navigationMenu.d.ts +2 -1
- package/lib/components/Layout/components/Header/components/Content/components/Navigation/components/NavigationMenu/navigationMenu.js +4 -4
- package/lib/components/Layout/components/Header/components/Content/components/Navigation/components/NavigationMenuItems/navigationMenuItems.js +2 -2
- package/lib/components/Layout/components/Header/components/Content/components/Navigation/navigation.d.ts +3 -2
- package/lib/components/Layout/components/Header/components/Content/components/Navigation/navigation.js +3 -3
- package/lib/components/Layout/components/Header/header.js +13 -10
- package/lib/components/Layout/components/Header/header.stories.js +0 -1
- package/lib/components/Layout/components/Header/hooks/useHeaderNavigation.d.ts +6 -0
- package/lib/components/Layout/components/Header/hooks/useHeaderNavigation.js +10 -0
- package/lib/components/Layout/components/Header/hooks/useHeaderVisibility.js +3 -3
- package/lib/components/Layout/components/Header/hooks/useMenu.d.ts +10 -0
- package/lib/components/Layout/components/Header/hooks/useMenu.js +17 -0
- package/lib/components/Layout/components/Sidebar/components/SidebarPositioner/sidebarPositioner.styles.js +1 -0
- package/lib/components/common/Dialog/hooks/useDialog.d.ts +11 -0
- package/lib/components/common/Dialog/hooks/useDialog.js +18 -0
- package/lib/components/common/Menu/hooks/useMenu.d.ts +14 -0
- package/lib/components/common/Menu/hooks/useMenu.js +33 -0
- package/package.json +1 -1
- package/src/components/Layout/components/Header/common/entities.ts +5 -2
- package/src/components/Layout/components/Header/common/utils.ts +107 -14
- package/src/components/Layout/components/Header/components/Content/components/Actions/components/Menu/menu.tsx +2 -2
- package/src/components/Layout/components/Header/components/Content/components/Navigation/common/utils.ts +9 -17
- package/src/components/Layout/components/Header/components/Content/components/Navigation/components/NavigationDrawer/navigationDrawer.tsx +12 -15
- package/src/components/Layout/components/Header/components/Content/components/Navigation/components/NavigationMenu/navigationMenu.tsx +5 -3
- package/src/components/Layout/components/Header/components/Content/components/Navigation/components/NavigationMenuItems/navigationMenuItems.tsx +2 -6
- package/src/components/Layout/components/Header/components/Content/components/Navigation/navigation.tsx +13 -4
- package/src/components/Layout/components/Header/header.stories.tsx +0 -1
- package/src/components/Layout/components/Header/header.tsx +12 -20
- package/src/components/Layout/components/Header/hooks/useHeaderNavigation.ts +19 -0
- package/src/components/Layout/components/Header/hooks/useHeaderVisibility.ts +3 -3
- package/src/{hooks → components/Layout/components/Header/hooks}/useMenu.ts +2 -2
- package/src/components/Layout/components/Sidebar/components/SidebarPositioner/sidebarPositioner.styles.ts +1 -0
- package/src/components/common/Dialog/hooks/useDialog.ts +28 -0
- package/src/{hooks/useMenuWithPosition.ts → components/common/Menu/hooks/useMenu.ts} +4 -4
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { BreakpointKey } from "../../../../../hooks/useBreakpointHelper";
|
|
2
2
|
import { Social } from "../../../../common/Socials/socials";
|
|
3
3
|
import { NavLinkItem } from "../components/Content/components/Navigation/navigation";
|
|
4
4
|
export declare type Navigation = [
|
|
@@ -6,11 +6,11 @@ export declare type Navigation = [
|
|
|
6
6
|
NavLinkItem[] | undefined,
|
|
7
7
|
NavLinkItem[] | undefined
|
|
8
8
|
];
|
|
9
|
+
export declare type SelectedMatch = SELECTED_MATCH | Partial<Record<BreakpointKey, boolean | SELECTED_MATCH>>;
|
|
9
10
|
export declare enum SELECTED_MATCH {
|
|
10
11
|
EQUALS = "EQUALS",
|
|
11
12
|
STARTS_WITH = "STARTS_WITH"
|
|
12
13
|
}
|
|
13
14
|
export interface SocialMedia {
|
|
14
|
-
label: ReactNode;
|
|
15
15
|
socials: Social[];
|
|
16
16
|
}
|
|
@@ -2,12 +2,11 @@ import { Breakpoint } from "@mui/material";
|
|
|
2
2
|
import { NavLinkItem } from "../components/Content/components/Navigation/navigation";
|
|
3
3
|
import { Navigation } from "./entities";
|
|
4
4
|
/**
|
|
5
|
-
* Returns the configured menu navigation links
|
|
5
|
+
* Returns the configured menu navigation links.
|
|
6
6
|
* @param navigation - Navigation links.
|
|
7
|
-
* @param breakpoint - Current breakpoint.
|
|
8
7
|
* @returns navigation links.
|
|
9
8
|
*/
|
|
10
|
-
export declare function getMenuNavigationLinks(navigation?: Navigation
|
|
9
|
+
export declare function getMenuNavigationLinks(navigation?: Navigation): NavLinkItem[];
|
|
11
10
|
/**
|
|
12
11
|
* Returns configured navigation links, for the current breakpoint.
|
|
13
12
|
* @param navigationLinks - Navigation links.
|
|
@@ -1,19 +1,42 @@
|
|
|
1
|
+
import { isClientSideNavigation } from "../../../../Links/common/utils";
|
|
2
|
+
import { SELECTED_MATCH } from "./entities";
|
|
1
3
|
/**
|
|
2
|
-
*
|
|
4
|
+
* Adds to the set of selected patterns, for the navigation link, at the current breakpoint.
|
|
5
|
+
* @param setOfPatterns - Set of selected patterns.
|
|
6
|
+
* @param navLinkItem - Navigation link.
|
|
7
|
+
* @param breakpoint - Breakpoint.
|
|
8
|
+
*/
|
|
9
|
+
function addSelectedPattern(setOfPatterns, navLinkItem, breakpoint) {
|
|
10
|
+
if (!navLinkItem.url)
|
|
11
|
+
return;
|
|
12
|
+
// Exclude external links.
|
|
13
|
+
if (!isClientSideNavigation(navLinkItem.url))
|
|
14
|
+
return;
|
|
15
|
+
// Get the configured selected match for the current breakpoint.
|
|
16
|
+
const selectedMatch = getSelectedMatch(navLinkItem.selectedMatch, breakpoint);
|
|
17
|
+
if (!selectedMatch)
|
|
18
|
+
return;
|
|
19
|
+
// Add the selected pattern for the navigation link.
|
|
20
|
+
if (selectedMatch === SELECTED_MATCH.EQUALS) {
|
|
21
|
+
setOfPatterns.add(getPatternEquals(navLinkItem.url));
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
setOfPatterns.add(getPatternStartsWith(navLinkItem.url));
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Returns the configured menu navigation links.
|
|
3
28
|
* @param navigation - Navigation links.
|
|
4
|
-
* @param breakpoint - Current breakpoint.
|
|
5
29
|
* @returns navigation links.
|
|
6
30
|
*/
|
|
7
|
-
export function getMenuNavigationLinks(navigation
|
|
31
|
+
export function getMenuNavigationLinks(navigation) {
|
|
8
32
|
if (!navigation)
|
|
9
33
|
return [];
|
|
10
|
-
|
|
34
|
+
return navigation.reduce((acc, navLinkItems) => {
|
|
11
35
|
if (!navLinkItems)
|
|
12
36
|
return acc;
|
|
13
37
|
acc.push(...navLinkItems);
|
|
14
38
|
return acc;
|
|
15
39
|
}, []);
|
|
16
|
-
return getNavigationLinks(navLinkItems, breakpoint);
|
|
17
40
|
}
|
|
18
41
|
/**
|
|
19
42
|
* Returns configured navigation links, for the current breakpoint.
|
|
@@ -24,7 +47,9 @@ export function getMenuNavigationLinks(navigation, breakpoint) {
|
|
|
24
47
|
export function getNavigationLinks(navigationLinks, breakpoint) {
|
|
25
48
|
if (!navigationLinks)
|
|
26
49
|
return [];
|
|
27
|
-
return navigationLinks
|
|
50
|
+
return navigationLinks
|
|
51
|
+
.map((navigationLink) => mapSelectedMatches(navigationLink, breakpoint))
|
|
52
|
+
.reduce((acc, navLinkItem) => {
|
|
28
53
|
const processedNavLink = processNavLinkItem(navLinkItem, breakpoint);
|
|
29
54
|
if (processedNavLink) {
|
|
30
55
|
acc.push(...processedNavLink);
|
|
@@ -32,6 +57,49 @@ export function getNavigationLinks(navigationLinks, breakpoint) {
|
|
|
32
57
|
return acc;
|
|
33
58
|
}, []);
|
|
34
59
|
}
|
|
60
|
+
/**
|
|
61
|
+
* Returns the pattern for an exact match, for the given URL e.g. "^/about$".
|
|
62
|
+
* @param url - URL.
|
|
63
|
+
* @returns pattern for an exact match.
|
|
64
|
+
*/
|
|
65
|
+
function getPatternEquals(url) {
|
|
66
|
+
return `^${url}$`;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Returns the pattern for a match that starts with the given URL e.g. "^/about".
|
|
70
|
+
* @param url - URL.
|
|
71
|
+
* @returns pattern for a match that starts with the given URL.
|
|
72
|
+
*/
|
|
73
|
+
function getPatternStartsWith(url) {
|
|
74
|
+
return `^${url}`;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Returns the configured selected match.
|
|
78
|
+
* @param selectedMatch - Selected match.
|
|
79
|
+
* @param breakpoint - Breakpoint.
|
|
80
|
+
* @returns selected match.
|
|
81
|
+
*/
|
|
82
|
+
function getSelectedMatch(selectedMatch, breakpoint) {
|
|
83
|
+
if (!selectedMatch)
|
|
84
|
+
return SELECTED_MATCH.STARTS_WITH;
|
|
85
|
+
if (typeof selectedMatch === "string")
|
|
86
|
+
return selectedMatch;
|
|
87
|
+
if (!breakpoint)
|
|
88
|
+
return;
|
|
89
|
+
return getSelectMatchValue(selectedMatch[breakpoint]);
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Returns the selected match value, for the current breakpoint.
|
|
93
|
+
* @param selectedMatchValue - Selected match value.
|
|
94
|
+
* @returns selected match.
|
|
95
|
+
*/
|
|
96
|
+
function getSelectMatchValue(selectedMatchValue) {
|
|
97
|
+
if (selectedMatchValue === false)
|
|
98
|
+
return undefined;
|
|
99
|
+
if (selectedMatchValue === true)
|
|
100
|
+
return SELECTED_MATCH.STARTS_WITH;
|
|
101
|
+
return selectedMatchValue || SELECTED_MATCH.STARTS_WITH;
|
|
102
|
+
}
|
|
35
103
|
/**
|
|
36
104
|
* Returns true if the link is flattened at the current breakpoint.
|
|
37
105
|
* @param navLinkItem - Navigation link.
|
|
@@ -58,6 +126,26 @@ function isLinkVisible(navLinkItem, breakpoint) {
|
|
|
58
126
|
return true; // Default is visible.
|
|
59
127
|
return navLinkItem.visible[breakpoint] !== false;
|
|
60
128
|
}
|
|
129
|
+
/**
|
|
130
|
+
* Returns the navigation link with the selected matches, for the current breakpoint.
|
|
131
|
+
* @param navLinkItem - Navigation link.
|
|
132
|
+
* @param breakpoint - Breakpoint.
|
|
133
|
+
* @returns navigation link with the selected matches.
|
|
134
|
+
*/
|
|
135
|
+
function mapSelectedMatches(navLinkItem, breakpoint) {
|
|
136
|
+
const setOfPatterns = new Set();
|
|
137
|
+
// Add selected pattern for the current navigation link.
|
|
138
|
+
addSelectedPattern(setOfPatterns, navLinkItem, breakpoint);
|
|
139
|
+
const cloneLink = { ...navLinkItem };
|
|
140
|
+
if (cloneLink.menuItems) {
|
|
141
|
+
cloneLink.menuItems = [...cloneLink.menuItems].map((menuItem) => mapSelectedMatches(menuItem, breakpoint));
|
|
142
|
+
for (const { selectedPatterns = [] } of cloneLink.menuItems) {
|
|
143
|
+
selectedPatterns.forEach((pattern) => setOfPatterns.add(pattern));
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
cloneLink.selectedPatterns = [...setOfPatterns];
|
|
147
|
+
return cloneLink;
|
|
148
|
+
}
|
|
61
149
|
/**
|
|
62
150
|
* Returns the processed navigation link item.
|
|
63
151
|
* Flattens menu items, and removes items that are not visible for the current breakpoint.
|
|
@@ -11,7 +11,7 @@ import { Socials } from "./components/Content/components/Socials/socials.styles"
|
|
|
11
11
|
import { Toolbar } from "./components/Toolbar/toolbar";
|
|
12
12
|
export const Menu = forwardRef(function HeaderMenu({ closeMenu, headerProps, open, openMenu, pathname, style }, ref) {
|
|
13
13
|
const { navigation, slogan, socialMedia } = headerProps;
|
|
14
|
-
const {
|
|
14
|
+
const { smDown } = useBreakpoint();
|
|
15
15
|
// Set drawer open state to false on change of media breakpoint from small desktop "md" and up.
|
|
16
16
|
useEffect(() => {
|
|
17
17
|
if (smDown)
|
|
@@ -28,6 +28,6 @@ export const Menu = forwardRef(function HeaderMenu({ closeMenu, headerProps, ope
|
|
|
28
28
|
React.createElement(Toolbar, { onClose: closeMenu, ...headerProps })),
|
|
29
29
|
React.createElement(Content, null,
|
|
30
30
|
slogan && React.createElement(Slogan, { slogan: slogan }),
|
|
31
|
-
React.createElement(Navigation, { closeAncestor: closeMenu, headerProps: headerProps, links: getMenuNavigationLinks(navigation
|
|
31
|
+
React.createElement(Navigation, { closeAncestor: closeMenu, headerProps: headerProps, links: getMenuNavigationLinks(navigation), pathname: pathname }),
|
|
32
32
|
socialMedia && (React.createElement(Socials, { buttonSize: "xlarge", socials: socialMedia.socials }))))));
|
|
33
33
|
});
|
|
@@ -1,15 +1,8 @@
|
|
|
1
|
-
import { SELECTED_MATCH } from "../../../../../common/entities";
|
|
2
1
|
/**
|
|
3
2
|
* Returns true if the navigation link is selected.
|
|
4
|
-
*
|
|
3
|
+
* The pathname is matched against the selected patterns.
|
|
5
4
|
* @param pathname - The current pathname.
|
|
6
|
-
* @param
|
|
5
|
+
* @param selectedPatterns - Selected match patterns.
|
|
7
6
|
* @returns true if the navigation link is selected.
|
|
8
7
|
*/
|
|
9
|
-
export declare function isNavigationLinkSelected(
|
|
10
|
-
/**
|
|
11
|
-
* Returns true if the selected match type is "EQUAL".
|
|
12
|
-
* @param selectedMatch - The selected match type.
|
|
13
|
-
* @returns True if the selected match type is "EQUAL".
|
|
14
|
-
*/
|
|
15
|
-
export declare function isSelectedMatchEqual(selectedMatch: SELECTED_MATCH): boolean;
|
|
8
|
+
export declare function isNavigationLinkSelected(pathname?: string, selectedPatterns?: string[]): boolean;
|
|
@@ -1,23 +1,17 @@
|
|
|
1
|
-
import { SELECTED_MATCH } from "../../../../../common/entities";
|
|
2
1
|
/**
|
|
3
2
|
* Returns true if the navigation link is selected.
|
|
4
|
-
*
|
|
3
|
+
* The pathname is matched against the selected patterns.
|
|
5
4
|
* @param pathname - The current pathname.
|
|
6
|
-
* @param
|
|
5
|
+
* @param selectedPatterns - Selected match patterns.
|
|
7
6
|
* @returns true if the navigation link is selected.
|
|
8
7
|
*/
|
|
9
|
-
export function isNavigationLinkSelected(
|
|
8
|
+
export function isNavigationLinkSelected(pathname, selectedPatterns) {
|
|
10
9
|
if (!pathname)
|
|
11
10
|
return false;
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
* @param selectedMatch - The selected match type.
|
|
19
|
-
* @returns True if the selected match type is "EQUAL".
|
|
20
|
-
*/
|
|
21
|
-
export function isSelectedMatchEqual(selectedMatch) {
|
|
22
|
-
return selectedMatch === SELECTED_MATCH.EQUALS;
|
|
11
|
+
for (const selectedPattern of selectedPatterns ?? []) {
|
|
12
|
+
if (new RegExp(selectedPattern).test(pathname)) {
|
|
13
|
+
return true;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
return false;
|
|
23
17
|
}
|
|
@@ -4,8 +4,9 @@ import { MenuItem } from "../NavigationMenuItems/navigationMenuItems";
|
|
|
4
4
|
export interface NavigationDrawerProps {
|
|
5
5
|
closeAncestor?: () => void;
|
|
6
6
|
headerProps?: HeaderProps;
|
|
7
|
+
isSelected?: boolean;
|
|
7
8
|
menuItems: MenuItem[];
|
|
8
9
|
menuLabel: ReactNode;
|
|
9
10
|
pathname?: string;
|
|
10
11
|
}
|
|
11
|
-
export declare const NavigationDrawer: ({ closeAncestor, headerProps, menuItems, menuLabel, pathname, }: NavigationDrawerProps) => JSX.Element;
|
|
12
|
+
export declare const NavigationDrawer: ({ closeAncestor, headerProps, isSelected, menuItems, menuLabel, pathname, }: NavigationDrawerProps) => JSX.Element;
|
|
@@ -1,30 +1,25 @@
|
|
|
1
1
|
import ArrowDropDownRoundedIcon from "@mui/icons-material/ArrowDropDownRounded";
|
|
2
|
-
import React, {
|
|
2
|
+
import React, { useCallback } from "react";
|
|
3
3
|
import { Button } from "../../../../../../../../../common/Button/button";
|
|
4
4
|
import { BackArrowIcon } from "../../../../../../../../../common/CustomIcon/components/BackArrowIcon/backArrowIcon";
|
|
5
|
+
import { useDialog } from "../../../../../../../../../common/Dialog/hooks/useDialog";
|
|
5
6
|
import { AppBar } from "../../../../../../header.styles";
|
|
6
7
|
import { DrawerNavigation as Navigation } from "../../../Actions/components/Menu/components/Content/components/Navigation/navigation.styles";
|
|
7
8
|
import { Toolbar } from "../../../Actions/components/Menu/components/Toolbar/toolbar";
|
|
8
9
|
import { Slide } from "./components/Slide/slide";
|
|
9
10
|
import { Button as BackButton, Content, Dialog, } from "./navigationDrawer.styles";
|
|
10
|
-
export const NavigationDrawer = ({ closeAncestor, headerProps, menuItems, menuLabel, pathname, }) => {
|
|
11
|
-
const
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
};
|
|
15
|
-
const closeDrawer = () => {
|
|
16
|
-
setDrawerOpen(false);
|
|
17
|
-
};
|
|
18
|
-
const closeDrawers = () => {
|
|
19
|
-
setDrawerOpen(false);
|
|
11
|
+
export const NavigationDrawer = ({ closeAncestor, headerProps, isSelected = false, menuItems, menuLabel, pathname, }) => {
|
|
12
|
+
const { onClose, onOpen, open } = useDialog();
|
|
13
|
+
const closeDrawers = useCallback(() => {
|
|
14
|
+
onClose();
|
|
20
15
|
closeAncestor?.();
|
|
21
|
-
};
|
|
16
|
+
}, [closeAncestor, onClose]);
|
|
22
17
|
return (React.createElement(React.Fragment, null,
|
|
23
|
-
React.createElement(Button, { EndIcon: ArrowDropDownRoundedIcon, onClick:
|
|
24
|
-
React.createElement(Dialog, { disableScrollLock: true, fullScreen: true, hideBackdrop: true, keepMounted: false, onClose: closeDrawers, open:
|
|
18
|
+
React.createElement(Button, { EndIcon: ArrowDropDownRoundedIcon, onClick: onOpen, variant: isSelected ? "activeNav" : "nav" }, menuLabel),
|
|
19
|
+
React.createElement(Dialog, { disableScrollLock: true, fullScreen: true, hideBackdrop: true, keepMounted: false, onClose: closeDrawers, open: open, PaperProps: { elevation: 0 }, TransitionComponent: Slide, transitionDuration: 300 },
|
|
25
20
|
React.createElement(AppBar, { component: "div", elevation: 1 },
|
|
26
21
|
React.createElement(Toolbar, { onClose: closeDrawers, ...headerProps })),
|
|
27
22
|
React.createElement(Content, null,
|
|
28
|
-
React.createElement(BackButton, { fullWidth: true, onClick:
|
|
23
|
+
React.createElement(BackButton, { fullWidth: true, onClick: onClose, StartIcon: BackArrowIcon, variant: "backNav" }, menuLabel),
|
|
29
24
|
React.createElement(Navigation, { closeAncestor: closeDrawers, headerProps: headerProps, links: menuItems, pathname: pathname })))));
|
|
30
25
|
};
|
|
@@ -5,8 +5,9 @@ export interface NavLinkMenuProps {
|
|
|
5
5
|
anchorOrigin?: MMenuProps["anchorOrigin"];
|
|
6
6
|
closeAncestor?: () => void;
|
|
7
7
|
disablePortal?: boolean;
|
|
8
|
+
isSelected?: boolean;
|
|
8
9
|
menuItems: MenuItem[];
|
|
9
10
|
menuLabel: ReactNode;
|
|
10
11
|
pathname?: string;
|
|
11
12
|
}
|
|
12
|
-
export declare const NavigationMenu: ({ anchorOrigin, closeAncestor, disablePortal, menuItems, menuLabel, pathname, }: NavLinkMenuProps) => JSX.Element;
|
|
13
|
+
export declare const NavigationMenu: ({ anchorOrigin, closeAncestor, disablePortal, isSelected, menuItems, menuLabel, pathname, }: NavLinkMenuProps) => JSX.Element;
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import ArrowDropDownRoundedIcon from "@mui/icons-material/ArrowDropDownRounded";
|
|
2
2
|
import React, { Fragment } from "react";
|
|
3
3
|
import { useBreakpoint } from "../../../../../../../../../../hooks/useBreakpoint";
|
|
4
|
-
import {
|
|
4
|
+
import { useMenu } from "../../../../../../../../../common/Menu/hooks/useMenu";
|
|
5
5
|
import { NavigationButtonLabel } from "../NavigationButtonLabel/navigationButtonLabel";
|
|
6
6
|
import { NavigationMenuItems, } from "../NavigationMenuItems/navigationMenuItems";
|
|
7
7
|
import { MENU_ANCHOR_ORIGIN_LEFT_BOTTOM, MENU_PROPS } from "./common/constants";
|
|
8
8
|
import { Button, Menu, StyledMenuItem } from "./navigationMenu.styles";
|
|
9
|
-
export const NavigationMenu = ({ anchorOrigin = MENU_ANCHOR_ORIGIN_LEFT_BOTTOM, closeAncestor, disablePortal, menuItems, menuLabel, pathname, }) => {
|
|
9
|
+
export const NavigationMenu = ({ anchorOrigin = MENU_ANCHOR_ORIGIN_LEFT_BOTTOM, closeAncestor, disablePortal, isSelected = false, menuItems, menuLabel, pathname, }) => {
|
|
10
10
|
const { mdUp } = useBreakpoint();
|
|
11
|
-
const { anchorEl, onClose, onToggleOpen, open } =
|
|
11
|
+
const { anchorEl, onClose, onToggleOpen, open } = useMenu();
|
|
12
12
|
const MenuItem = disablePortal ? StyledMenuItem : Fragment;
|
|
13
13
|
const menuItemProps = disablePortal ? { onMouseLeave: onClose } : {};
|
|
14
14
|
return (React.createElement(MenuItem, { ...menuItemProps },
|
|
15
|
-
React.createElement(Button, { EndIcon: ArrowDropDownRoundedIcon, isActive: open, onClick: onToggleOpen, variant: "nav" },
|
|
15
|
+
React.createElement(Button, { EndIcon: ArrowDropDownRoundedIcon, isActive: open, onClick: onToggleOpen, variant: isSelected ? "activeNav" : "nav" },
|
|
16
16
|
React.createElement(NavigationButtonLabel, { label: menuLabel })),
|
|
17
17
|
React.createElement(Menu, { ...MENU_PROPS, anchorEl: anchorEl, anchorOrigin: anchorOrigin, disablePortal: disablePortal, onClose: () => {
|
|
18
18
|
onClose();
|
|
@@ -9,13 +9,13 @@ import { MENU_ANCHOR_ORIGIN_RIGHT_TOP } from "../NavigationMenu/common/constants
|
|
|
9
9
|
import { NavigationMenu } from "../NavigationMenu/navigationMenu";
|
|
10
10
|
export const NavigationMenuItems = ({ closeMenu, menuItems, pathname, }) => {
|
|
11
11
|
const router = useRouter();
|
|
12
|
-
return (React.createElement(React.Fragment, null, menuItems.map(({ description, divider, icon, label, menuItems: nestedMenuItems,
|
|
12
|
+
return (React.createElement(React.Fragment, null, menuItems.map(({ description, divider, icon, label, menuItems: nestedMenuItems, selectedPatterns, target = ANCHOR_TARGET.SELF, url, }, i) => nestedMenuItems ? (React.createElement(NavigationMenu, { key: i, anchorOrigin: MENU_ANCHOR_ORIGIN_RIGHT_TOP, closeAncestor: closeMenu, disablePortal: true, menuItems: nestedMenuItems, menuLabel: label, pathname: pathname })) : (React.createElement(Fragment, { key: i },
|
|
13
13
|
React.createElement(MMenuItem, { disabled: !url, onClick: () => {
|
|
14
14
|
closeMenu();
|
|
15
15
|
isClientSideNavigation(url)
|
|
16
16
|
? router.push(url)
|
|
17
17
|
: window.open(url, target, REL_ATTRIBUTE.NO_OPENER_NO_REFERRER);
|
|
18
|
-
}, selected: isNavigationLinkSelected(
|
|
18
|
+
}, selected: isNavigationLinkSelected(pathname, selectedPatterns) },
|
|
19
19
|
icon && React.createElement(ListItemIcon, null, icon),
|
|
20
20
|
React.createElement(ListItemText, { primary: label, primaryTypographyProps: {
|
|
21
21
|
variant: url
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, { CSSProperties, ReactNode } from "react";
|
|
2
2
|
import { BreakpointKey } from "../../../../../../../../hooks/useBreakpointHelper";
|
|
3
3
|
import { ANCHOR_TARGET } from "../../../../../../../Links/common/entities";
|
|
4
|
-
import {
|
|
4
|
+
import { SelectedMatch } from "../../../../common/entities";
|
|
5
5
|
import { HeaderProps } from "../../../../header";
|
|
6
6
|
import { MenuItem } from "./components/NavigationMenuItems/navigationMenuItems";
|
|
7
7
|
export interface NavLinkItem {
|
|
@@ -9,7 +9,8 @@ export interface NavLinkItem {
|
|
|
9
9
|
flatten?: Partial<Record<BreakpointKey, boolean>>;
|
|
10
10
|
label: ReactNode;
|
|
11
11
|
menuItems?: MenuItem[];
|
|
12
|
-
selectedMatch?:
|
|
12
|
+
selectedMatch?: SelectedMatch;
|
|
13
|
+
selectedPatterns?: string[];
|
|
13
14
|
target?: ANCHOR_TARGET;
|
|
14
15
|
url: string;
|
|
15
16
|
visible?: Partial<Record<BreakpointKey, boolean>>;
|
|
@@ -12,15 +12,15 @@ import { Navigation as Links } from "./navigation.styles";
|
|
|
12
12
|
export const Navigation = forwardRef(function Navigation({ className, closeAncestor, headerProps, links, pathname, style, }, ref) {
|
|
13
13
|
const { mdUp } = useBreakpoint();
|
|
14
14
|
const router = useRouter();
|
|
15
|
-
return (React.createElement(Links, { ref: ref, className: className, style: style }, links.map(({ divider, label, menuItems,
|
|
16
|
-
mdUp ? (React.createElement(NavigationMenu, { closeAncestor: closeAncestor, menuItems: menuItems, menuLabel: label, pathname: pathname })) : (React.createElement(NavigationDrawer, { closeAncestor: closeAncestor, headerProps: headerProps, menuItems: menuItems, menuLabel: label, pathname: pathname })),
|
|
15
|
+
return (React.createElement(Links, { ref: ref, className: className, style: style }, links.map(({ divider, label, menuItems, selectedPatterns, target = ANCHOR_TARGET.SELF, url, }, i) => menuItems ? (React.createElement(Fragment, { key: i },
|
|
16
|
+
mdUp ? (React.createElement(NavigationMenu, { closeAncestor: closeAncestor, isSelected: isNavigationLinkSelected(pathname, selectedPatterns), menuItems: menuItems, menuLabel: label, pathname: pathname })) : (React.createElement(NavigationDrawer, { closeAncestor: closeAncestor, headerProps: headerProps, isSelected: isNavigationLinkSelected(pathname, selectedPatterns), menuItems: menuItems, menuLabel: label, pathname: pathname })),
|
|
17
17
|
divider && React.createElement(Divider, null))) : (React.createElement(Fragment, { key: i },
|
|
18
18
|
React.createElement(Button, { disabled: !url, onClick: () => {
|
|
19
19
|
closeAncestor?.();
|
|
20
20
|
isClientSideNavigation(url)
|
|
21
21
|
? router.push(url)
|
|
22
22
|
: window.open(url, target, REL_ATTRIBUTE.NO_OPENER_NO_REFERRER);
|
|
23
|
-
}, variant: isNavigationLinkSelected(
|
|
23
|
+
}, variant: isNavigationLinkSelected(pathname, selectedPatterns)
|
|
24
24
|
? "activeNav"
|
|
25
25
|
: "nav" },
|
|
26
26
|
React.createElement(NavigationButtonLabel, { label: label })),
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
import { Fade, Toolbar } from "@mui/material";
|
|
2
2
|
import { usePathname } from "next/navigation";
|
|
3
3
|
import React from "react";
|
|
4
|
-
import { useBreakpoint } from "../../../../hooks/useBreakpoint";
|
|
5
|
-
import { useMenu } from "../../../../hooks/useMenu";
|
|
6
4
|
import { APP_BAR_PROPS, FADE_TRANSITION_PROPS, TOOLBAR_PROPS, } from "./common/constants";
|
|
7
|
-
import { getNavigationLinks } from "./common/utils";
|
|
8
5
|
import { Announcements } from "./components/Announcements/announcements";
|
|
9
6
|
import { Actions } from "./components/Content/components/Actions/actions";
|
|
10
7
|
import { Authentication } from "./components/Content/components/Actions/components/Authentication/authentication";
|
|
@@ -15,16 +12,22 @@ import { Slogan } from "./components/Content/components/Slogan/slogan";
|
|
|
15
12
|
import { Divider } from "./components/Content/components/Slogan/slogan.styles";
|
|
16
13
|
import { Socials } from "./components/Content/components/Socials/socials.styles";
|
|
17
14
|
import { AppBar, Center, Left, Right } from "./header.styles";
|
|
15
|
+
import { useHeaderNavigation } from "./hooks/useHeaderNavigation";
|
|
18
16
|
import { useHeaderVisibility } from "./hooks/useHeaderVisibility";
|
|
19
17
|
import { useMeasureHeader } from "./hooks/useMeasureHeader";
|
|
18
|
+
import { useMenu } from "./hooks/useMenu";
|
|
20
19
|
export const Header = ({ ...headerProps }) => {
|
|
21
|
-
const {
|
|
22
|
-
const { isIn } = useHeaderVisibility(headerProps);
|
|
20
|
+
const { navigation } = useHeaderNavigation(headerProps);
|
|
21
|
+
const { isIn } = useHeaderVisibility({ ...headerProps, navigation });
|
|
23
22
|
const { headerRef } = useMeasureHeader();
|
|
24
23
|
const { onClose, onOpen, open } = useMenu();
|
|
25
24
|
const pathname = usePathname() ?? "";
|
|
26
|
-
const { actions, announcements, authenticationEnabled, className, logo,
|
|
27
|
-
const
|
|
25
|
+
const { actions, announcements, authenticationEnabled, className, logo, searchEnabled, searchURL, slogan, socialMedia, } = headerProps;
|
|
26
|
+
const [navItemsL, navItemsC, navItemsR] = navigation;
|
|
27
|
+
const navigationProps = {
|
|
28
|
+
headerProps: { ...headerProps, navigation },
|
|
29
|
+
pathname,
|
|
30
|
+
};
|
|
28
31
|
return (React.createElement(AppBar, { ...APP_BAR_PROPS, ref: headerRef, className: className },
|
|
29
32
|
React.createElement(Announcements, { announcements: announcements }),
|
|
30
33
|
React.createElement(Toolbar, { ...TOOLBAR_PROPS },
|
|
@@ -33,12 +36,12 @@ export const Header = ({ ...headerProps }) => {
|
|
|
33
36
|
logo,
|
|
34
37
|
isIn.isSloganIn && React.createElement(Divider, { flexItem: true, orientation: "vertical" }),
|
|
35
38
|
isIn.isSloganIn && React.createElement(Slogan, { slogan: slogan }),
|
|
36
|
-
isIn.isLeftNavigationIn && (React.createElement(DXNavigation, { ...navigationProps, links:
|
|
39
|
+
isIn.isLeftNavigationIn && (React.createElement(DXNavigation, { ...navigationProps, links: navItemsL })))),
|
|
37
40
|
React.createElement(Fade, { ...FADE_TRANSITION_PROPS, in: isIn.isCenterGroupIn },
|
|
38
|
-
React.createElement(Center, null, isIn.isCenterNavigationIn && (React.createElement(DXNavigation, { ...navigationProps, links:
|
|
41
|
+
React.createElement(Center, null, isIn.isCenterNavigationIn && (React.createElement(DXNavigation, { ...navigationProps, links: navItemsC })))),
|
|
39
42
|
React.createElement(Fade, { ...FADE_TRANSITION_PROPS, in: isIn.isRightGroupIn },
|
|
40
43
|
React.createElement(Right, null,
|
|
41
|
-
isIn.isRightNavigationIn && (React.createElement(DXNavigation, { ...navigationProps, links:
|
|
44
|
+
isIn.isRightNavigationIn && (React.createElement(DXNavigation, { ...navigationProps, links: navItemsR })),
|
|
42
45
|
isIn.isSocialsIn && (React.createElement(Socials, { buttonSize: "small", socials: socialMedia?.socials || [] })),
|
|
43
46
|
isIn.isActionsIn && (React.createElement(Actions, null,
|
|
44
47
|
React.createElement(Search, { closeMenu: onClose, searchEnabled: searchEnabled, searchURL: searchURL }),
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { NavLinkItem } from "../components/Content/components/Navigation/navigation";
|
|
2
|
+
import { HeaderProps } from "../header";
|
|
3
|
+
export interface UseHeaderNavigation {
|
|
4
|
+
navigation: [NavLinkItem[], NavLinkItem[], NavLinkItem[]];
|
|
5
|
+
}
|
|
6
|
+
export declare const useHeaderNavigation: (headerProps: HeaderProps) => UseHeaderNavigation;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { useBreakpoint } from "../../../../../hooks/useBreakpoint";
|
|
2
|
+
import { getNavigationLinks } from "../common/utils";
|
|
3
|
+
export const useHeaderNavigation = (headerProps) => {
|
|
4
|
+
const { breakpoint } = useBreakpoint();
|
|
5
|
+
const { navigation: [navL, navC, navR] = [] } = headerProps;
|
|
6
|
+
const navItemsL = getNavigationLinks(navL, breakpoint);
|
|
7
|
+
const navItemsC = getNavigationLinks(navC, breakpoint);
|
|
8
|
+
const navItemsR = getNavigationLinks(navR, breakpoint);
|
|
9
|
+
return { navigation: [navItemsL, navItemsC, navItemsR] };
|
|
10
|
+
};
|
|
@@ -12,9 +12,9 @@ export const useHeaderVisibility = (headerProps) => {
|
|
|
12
12
|
const hasActions = Boolean(actions);
|
|
13
13
|
const hasLogo = Boolean(logo);
|
|
14
14
|
const hasMenu = !mdUp;
|
|
15
|
-
const hasNavItemsC = Boolean(navItemsC);
|
|
16
|
-
const hasNavItemsL = Boolean(navItemsL);
|
|
17
|
-
const hasNavItemsR = Boolean(navItemsR);
|
|
15
|
+
const hasNavItemsC = Boolean(navItemsC && navItemsC.length > 0);
|
|
16
|
+
const hasNavItemsL = Boolean(navItemsL && navItemsL.length > 0);
|
|
17
|
+
const hasNavItemsR = Boolean(navItemsR && navItemsR.length > 0);
|
|
18
18
|
const hasSlogan = Boolean(slogan);
|
|
19
19
|
const hasSocials = Boolean(socialMedia);
|
|
20
20
|
// Determines header content visibility.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { useCallback, useState } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Menu functionality for menu dropdown.
|
|
4
|
+
* @returns menu functionality.
|
|
5
|
+
*/
|
|
6
|
+
export const useMenu = () => {
|
|
7
|
+
const [open, setOpen] = useState(false);
|
|
8
|
+
// Closes menu.
|
|
9
|
+
const onClose = useCallback(() => {
|
|
10
|
+
setOpen(false);
|
|
11
|
+
}, []);
|
|
12
|
+
// Opens menu.
|
|
13
|
+
const onOpen = useCallback(() => {
|
|
14
|
+
setOpen(true);
|
|
15
|
+
}, []);
|
|
16
|
+
return { onClose, onOpen, open };
|
|
17
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface UseDialog {
|
|
2
|
+
onClose: () => void;
|
|
3
|
+
onOpen: () => void;
|
|
4
|
+
open: boolean;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Dialog functionality.
|
|
8
|
+
* @param isOpen - Open state (initial).
|
|
9
|
+
* @returns dialog functionality.
|
|
10
|
+
*/
|
|
11
|
+
export declare const useDialog: (isOpen?: boolean) => UseDialog;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { useCallback, useState } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Dialog functionality.
|
|
4
|
+
* @param isOpen - Open state (initial).
|
|
5
|
+
* @returns dialog functionality.
|
|
6
|
+
*/
|
|
7
|
+
export const useDialog = (isOpen = false) => {
|
|
8
|
+
const [open, setOpen] = useState(isOpen);
|
|
9
|
+
// Closes dialog.
|
|
10
|
+
const onClose = useCallback(() => {
|
|
11
|
+
setOpen(false);
|
|
12
|
+
}, []);
|
|
13
|
+
// Opens dialog
|
|
14
|
+
const onOpen = useCallback(() => {
|
|
15
|
+
setOpen(true);
|
|
16
|
+
}, []);
|
|
17
|
+
return { onClose, onOpen, open };
|
|
18
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { MenuProps as MMenuProps } from "@mui/material";
|
|
2
|
+
import { MouseEvent } from "react";
|
|
3
|
+
export interface UseMenu {
|
|
4
|
+
anchorEl: MMenuProps["anchorEl"];
|
|
5
|
+
onClose: () => void;
|
|
6
|
+
onOpen: (event: MouseEvent<HTMLElement>) => void;
|
|
7
|
+
onToggleOpen: (event: MouseEvent<HTMLElement>) => void;
|
|
8
|
+
open: boolean;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Menu functionality for menu dropdown, with menu position.
|
|
12
|
+
* @returns menu functionality.
|
|
13
|
+
*/
|
|
14
|
+
export declare const useMenu: () => UseMenu;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { useCallback, useMemo, useState } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Menu functionality for menu dropdown, with menu position.
|
|
4
|
+
* @returns menu functionality.
|
|
5
|
+
*/
|
|
6
|
+
export const useMenu = () => {
|
|
7
|
+
const [anchorEl, setAnchorEl] = useState(null);
|
|
8
|
+
const open = useMemo(() => Boolean(anchorEl), [anchorEl]);
|
|
9
|
+
// Closes menu.
|
|
10
|
+
const onClose = useCallback(() => {
|
|
11
|
+
setAnchorEl(null);
|
|
12
|
+
}, []);
|
|
13
|
+
// Opens menu.
|
|
14
|
+
const onOpen = useCallback((event) => {
|
|
15
|
+
setAnchorEl(event.currentTarget);
|
|
16
|
+
}, []);
|
|
17
|
+
// Toggles menu open/close.
|
|
18
|
+
const onToggleOpen = useCallback((event) => {
|
|
19
|
+
if (open) {
|
|
20
|
+
setAnchorEl(null);
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
setAnchorEl(event.currentTarget);
|
|
24
|
+
}
|
|
25
|
+
}, [open]);
|
|
26
|
+
return {
|
|
27
|
+
anchorEl,
|
|
28
|
+
onClose,
|
|
29
|
+
onOpen,
|
|
30
|
+
onToggleOpen,
|
|
31
|
+
open,
|
|
32
|
+
};
|
|
33
|
+
};
|