@databiosphere/findable-ui 9.0.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/Export/components/ExportToTerra/components/TerraSetUpForm/components/FormStep/components/ConnectTerraToNIHAccount/connectTerraToNIHAccount.js +1 -1
- 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/Actions/components/Search/components/SearchBar/common/utils.d.ts +1 -1
- package/lib/components/Layout/components/Header/components/Content/components/Actions/components/Search/components/SearchBar/common/utils.js +11 -1
- 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/lib/providers/authentication.js +1 -1
- package/package.json +1 -1
- package/src/components/Export/components/ExportToTerra/components/TerraSetUpForm/components/FormStep/components/ConnectTerraToNIHAccount/connectTerraToNIHAccount.tsx +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/Actions/components/Search/components/SearchBar/common/utils.ts +14 -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
- package/src/providers/authentication.tsx +1 -1
|
@@ -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
|
+
};
|
|
@@ -22,7 +22,7 @@ export const AuthContext = createContext({
|
|
|
22
22
|
authenticateUser: () => { },
|
|
23
23
|
authenticationStatus: AUTHENTICATION_STATUS.INCOMPLETE,
|
|
24
24
|
isAuthenticated: false,
|
|
25
|
-
isEnabled:
|
|
25
|
+
isEnabled: false,
|
|
26
26
|
// eslint-disable-next-line @typescript-eslint/no-empty-function -- allow dummy function for default state.
|
|
27
27
|
requestAuthentication: () => { },
|
|
28
28
|
terraNIHProfileLoginStatus: LOGIN_STATUS_NOT_STARTED,
|
package/package.json
CHANGED
|
@@ -19,7 +19,7 @@ export const ConnectTerraToNIHAccount = ({
|
|
|
19
19
|
}: ConnectTerraToNIHAccountProps): JSX.Element | null => {
|
|
20
20
|
const onGotoTutorial = (): void => {
|
|
21
21
|
window.open(
|
|
22
|
-
"https://support.terra.bio/hc/en-us/articles/
|
|
22
|
+
"https://support.terra.bio/hc/en-us/articles/19124069598235-Access-controlled-data-files-by-linking-your-NIH-account-in-Terra",
|
|
23
23
|
ANCHOR_TARGET.BLANK,
|
|
24
24
|
REL_ATTRIBUTE.NO_OPENER_NO_REFERRER
|
|
25
25
|
);
|
|
@@ -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
|
|
|
@@ -8,12 +8,15 @@ export type Navigation = [
|
|
|
8
8
|
NavLinkItem[] | undefined
|
|
9
9
|
]; // [LEFT, CENTER, RIGHT]
|
|
10
10
|
|
|
11
|
+
export type SelectedMatch =
|
|
12
|
+
| SELECTED_MATCH
|
|
13
|
+
| Partial<Record<BreakpointKey, boolean | SELECTED_MATCH>>;
|
|
14
|
+
|
|
11
15
|
export enum SELECTED_MATCH {
|
|
12
16
|
EQUALS = "EQUALS",
|
|
13
17
|
STARTS_WITH = "STARTS_WITH", // Default value.
|
|
14
18
|
}
|
|
15
19
|
|
|
16
20
|
export interface SocialMedia {
|
|
17
|
-
label: ReactNode;
|
|
18
21
|
socials: Social[];
|
|
19
22
|
}
|
|
@@ -1,24 +1,45 @@
|
|
|
1
1
|
import { Breakpoint } from "@mui/material";
|
|
2
|
+
import { isClientSideNavigation } from "../../../../Links/common/utils";
|
|
2
3
|
import { NavLinkItem } from "../components/Content/components/Navigation/navigation";
|
|
3
|
-
import { Navigation } from "./entities";
|
|
4
|
+
import { Navigation, SelectedMatch, SELECTED_MATCH } from "./entities";
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
|
-
*
|
|
7
|
+
* Adds to the set of selected patterns, for the navigation link, at the current breakpoint.
|
|
8
|
+
* @param setOfPatterns - Set of selected patterns.
|
|
9
|
+
* @param navLinkItem - Navigation link.
|
|
10
|
+
* @param breakpoint - Breakpoint.
|
|
11
|
+
*/
|
|
12
|
+
function addSelectedPattern(
|
|
13
|
+
setOfPatterns: Set<string>,
|
|
14
|
+
navLinkItem: NavLinkItem,
|
|
15
|
+
breakpoint?: Breakpoint
|
|
16
|
+
): void {
|
|
17
|
+
if (!navLinkItem.url) return;
|
|
18
|
+
// Exclude external links.
|
|
19
|
+
if (!isClientSideNavigation(navLinkItem.url)) return;
|
|
20
|
+
// Get the configured selected match for the current breakpoint.
|
|
21
|
+
const selectedMatch = getSelectedMatch(navLinkItem.selectedMatch, breakpoint);
|
|
22
|
+
if (!selectedMatch) return;
|
|
23
|
+
// Add the selected pattern for the navigation link.
|
|
24
|
+
if (selectedMatch === SELECTED_MATCH.EQUALS) {
|
|
25
|
+
setOfPatterns.add(getPatternEquals(navLinkItem.url));
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
setOfPatterns.add(getPatternStartsWith(navLinkItem.url));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Returns the configured menu navigation links.
|
|
7
33
|
* @param navigation - Navigation links.
|
|
8
|
-
* @param breakpoint - Current breakpoint.
|
|
9
34
|
* @returns navigation links.
|
|
10
35
|
*/
|
|
11
|
-
export function getMenuNavigationLinks(
|
|
12
|
-
navigation?: Navigation,
|
|
13
|
-
breakpoint?: Breakpoint
|
|
14
|
-
): NavLinkItem[] {
|
|
36
|
+
export function getMenuNavigationLinks(navigation?: Navigation): NavLinkItem[] {
|
|
15
37
|
if (!navigation) return [];
|
|
16
|
-
|
|
38
|
+
return navigation.reduce((acc: NavLinkItem[], navLinkItems) => {
|
|
17
39
|
if (!navLinkItems) return acc;
|
|
18
40
|
acc.push(...navLinkItems);
|
|
19
41
|
return acc;
|
|
20
42
|
}, []);
|
|
21
|
-
return getNavigationLinks(navLinkItems, breakpoint);
|
|
22
43
|
}
|
|
23
44
|
|
|
24
45
|
/**
|
|
@@ -32,16 +53,62 @@ export function getNavigationLinks(
|
|
|
32
53
|
breakpoint?: Breakpoint
|
|
33
54
|
): NavLinkItem[] {
|
|
34
55
|
if (!navigationLinks) return [];
|
|
35
|
-
return navigationLinks
|
|
36
|
-
(
|
|
56
|
+
return navigationLinks
|
|
57
|
+
.map((navigationLink) => mapSelectedMatches(navigationLink, breakpoint))
|
|
58
|
+
.reduce((acc: NavLinkItem[], navLinkItem: NavLinkItem) => {
|
|
37
59
|
const processedNavLink = processNavLinkItem(navLinkItem, breakpoint);
|
|
38
60
|
if (processedNavLink) {
|
|
39
61
|
acc.push(...processedNavLink);
|
|
40
62
|
}
|
|
41
63
|
return acc;
|
|
42
|
-
},
|
|
43
|
-
|
|
44
|
-
|
|
64
|
+
}, []);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Returns the pattern for an exact match, for the given URL e.g. "^/about$".
|
|
69
|
+
* @param url - URL.
|
|
70
|
+
* @returns pattern for an exact match.
|
|
71
|
+
*/
|
|
72
|
+
function getPatternEquals(url: string): string {
|
|
73
|
+
return `^${url}$`;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Returns the pattern for a match that starts with the given URL e.g. "^/about".
|
|
78
|
+
* @param url - URL.
|
|
79
|
+
* @returns pattern for a match that starts with the given URL.
|
|
80
|
+
*/
|
|
81
|
+
function getPatternStartsWith(url: string): string {
|
|
82
|
+
return `^${url}`;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Returns the configured selected match.
|
|
87
|
+
* @param selectedMatch - Selected match.
|
|
88
|
+
* @param breakpoint - Breakpoint.
|
|
89
|
+
* @returns selected match.
|
|
90
|
+
*/
|
|
91
|
+
function getSelectedMatch(
|
|
92
|
+
selectedMatch?: SelectedMatch,
|
|
93
|
+
breakpoint?: Breakpoint
|
|
94
|
+
): SELECTED_MATCH | undefined {
|
|
95
|
+
if (!selectedMatch) return SELECTED_MATCH.STARTS_WITH;
|
|
96
|
+
if (typeof selectedMatch === "string") return selectedMatch;
|
|
97
|
+
if (!breakpoint) return;
|
|
98
|
+
return getSelectMatchValue(selectedMatch[breakpoint]);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Returns the selected match value, for the current breakpoint.
|
|
103
|
+
* @param selectedMatchValue - Selected match value.
|
|
104
|
+
* @returns selected match.
|
|
105
|
+
*/
|
|
106
|
+
function getSelectMatchValue(
|
|
107
|
+
selectedMatchValue?: boolean | SELECTED_MATCH
|
|
108
|
+
): SELECTED_MATCH | undefined {
|
|
109
|
+
if (selectedMatchValue === false) return undefined;
|
|
110
|
+
if (selectedMatchValue === true) return SELECTED_MATCH.STARTS_WITH;
|
|
111
|
+
return selectedMatchValue || SELECTED_MATCH.STARTS_WITH;
|
|
45
112
|
}
|
|
46
113
|
|
|
47
114
|
/**
|
|
@@ -74,6 +141,32 @@ function isLinkVisible(
|
|
|
74
141
|
return navLinkItem.visible[breakpoint] !== false;
|
|
75
142
|
}
|
|
76
143
|
|
|
144
|
+
/**
|
|
145
|
+
* Returns the navigation link with the selected matches, for the current breakpoint.
|
|
146
|
+
* @param navLinkItem - Navigation link.
|
|
147
|
+
* @param breakpoint - Breakpoint.
|
|
148
|
+
* @returns navigation link with the selected matches.
|
|
149
|
+
*/
|
|
150
|
+
function mapSelectedMatches(
|
|
151
|
+
navLinkItem: NavLinkItem,
|
|
152
|
+
breakpoint?: Breakpoint
|
|
153
|
+
): NavLinkItem {
|
|
154
|
+
const setOfPatterns = new Set<string>();
|
|
155
|
+
// Add selected pattern for the current navigation link.
|
|
156
|
+
addSelectedPattern(setOfPatterns, navLinkItem, breakpoint);
|
|
157
|
+
const cloneLink = { ...navLinkItem };
|
|
158
|
+
if (cloneLink.menuItems) {
|
|
159
|
+
cloneLink.menuItems = [...cloneLink.menuItems].map((menuItem) =>
|
|
160
|
+
mapSelectedMatches(menuItem, breakpoint)
|
|
161
|
+
);
|
|
162
|
+
for (const { selectedPatterns = [] } of cloneLink.menuItems) {
|
|
163
|
+
selectedPatterns.forEach((pattern) => setOfPatterns.add(pattern));
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
cloneLink.selectedPatterns = [...setOfPatterns];
|
|
167
|
+
return cloneLink;
|
|
168
|
+
}
|
|
169
|
+
|
|
77
170
|
/**
|
|
78
171
|
* Returns the processed navigation link item.
|
|
79
172
|
* Flattens menu items, and removes items that are not visible for the current breakpoint.
|
|
@@ -26,7 +26,7 @@ export const Menu = forwardRef<HTMLButtonElement, MenuProps>(
|
|
|
26
26
|
ref
|
|
27
27
|
): JSX.Element | null {
|
|
28
28
|
const { navigation, slogan, socialMedia } = headerProps;
|
|
29
|
-
const {
|
|
29
|
+
const { smDown } = useBreakpoint();
|
|
30
30
|
|
|
31
31
|
// Set drawer open state to false on change of media breakpoint from small desktop "md" and up.
|
|
32
32
|
useEffect(() => {
|
|
@@ -61,7 +61,7 @@ export const Menu = forwardRef<HTMLButtonElement, MenuProps>(
|
|
|
61
61
|
<Navigation
|
|
62
62
|
closeAncestor={closeMenu}
|
|
63
63
|
headerProps={headerProps}
|
|
64
|
-
links={getMenuNavigationLinks(navigation
|
|
64
|
+
links={getMenuNavigationLinks(navigation)}
|
|
65
65
|
pathname={pathname}
|
|
66
66
|
/>
|
|
67
67
|
{socialMedia && (
|
|
@@ -1,6 +1,18 @@
|
|
|
1
1
|
import { ReadonlyURLSearchParams } from "next/navigation";
|
|
2
2
|
import { SEARCH_PARAMETERS } from "./constants";
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Return a new URLSearchParams object.
|
|
6
|
+
* @param searchParams - Search params.
|
|
7
|
+
* @returns new URLSearchParams object.
|
|
8
|
+
*/
|
|
9
|
+
function getNewURLSearchParams(
|
|
10
|
+
searchParams: ReadonlyURLSearchParams | null
|
|
11
|
+
): URLSearchParams {
|
|
12
|
+
if (!searchParams) return new URLSearchParams();
|
|
13
|
+
return new URLSearchParams(searchParams.toString());
|
|
14
|
+
}
|
|
15
|
+
|
|
4
16
|
/**
|
|
5
17
|
* Return the search params, for the given search string.
|
|
6
18
|
* @param searchParams - Current search params.
|
|
@@ -8,10 +20,10 @@ import { SEARCH_PARAMETERS } from "./constants";
|
|
|
8
20
|
* @returns updated search params.
|
|
9
21
|
*/
|
|
10
22
|
export function getSearchParams(
|
|
11
|
-
searchParams: ReadonlyURLSearchParams,
|
|
23
|
+
searchParams: ReadonlyURLSearchParams | null,
|
|
12
24
|
searchStr: string
|
|
13
25
|
): URLSearchParams {
|
|
14
|
-
const params =
|
|
26
|
+
const params = getNewURLSearchParams(searchParams);
|
|
15
27
|
params.set(SEARCH_PARAMETERS.QUERY, searchStr);
|
|
16
28
|
return params;
|
|
17
29
|
}
|
|
@@ -1,27 +1,19 @@
|
|
|
1
|
-
import { SELECTED_MATCH } from "../../../../../common/entities";
|
|
2
|
-
|
|
3
1
|
/**
|
|
4
2
|
* Returns true if the navigation link is selected.
|
|
5
|
-
*
|
|
3
|
+
* The pathname is matched against the selected patterns.
|
|
6
4
|
* @param pathname - The current pathname.
|
|
7
|
-
* @param
|
|
5
|
+
* @param selectedPatterns - Selected match patterns.
|
|
8
6
|
* @returns true if the navigation link is selected.
|
|
9
7
|
*/
|
|
10
8
|
export function isNavigationLinkSelected(
|
|
11
|
-
url: string,
|
|
12
9
|
pathname?: string,
|
|
13
|
-
|
|
10
|
+
selectedPatterns?: string[]
|
|
14
11
|
): boolean {
|
|
15
12
|
if (!pathname) return false;
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
* @param selectedMatch - The selected match type.
|
|
23
|
-
* @returns True if the selected match type is "EQUAL".
|
|
24
|
-
*/
|
|
25
|
-
export function isSelectedMatchEqual(selectedMatch: SELECTED_MATCH): boolean {
|
|
26
|
-
return selectedMatch === SELECTED_MATCH.EQUALS;
|
|
13
|
+
for (const selectedPattern of selectedPatterns ?? []) {
|
|
14
|
+
if (new RegExp(selectedPattern).test(pathname)) {
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return false;
|
|
27
19
|
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import ArrowDropDownRoundedIcon from "@mui/icons-material/ArrowDropDownRounded";
|
|
2
|
-
import React, { ReactNode,
|
|
2
|
+
import React, { ReactNode, 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 { HeaderProps } from "../../../../../../header";
|
|
6
7
|
import { AppBar } from "../../../../../../header.styles";
|
|
7
8
|
import { DrawerNavigation as Navigation } from "../../../Actions/components/Menu/components/Content/components/Navigation/navigation.styles";
|
|
@@ -17,6 +18,7 @@ import {
|
|
|
17
18
|
export interface NavigationDrawerProps {
|
|
18
19
|
closeAncestor?: () => void;
|
|
19
20
|
headerProps?: HeaderProps;
|
|
21
|
+
isSelected?: boolean;
|
|
20
22
|
menuItems: MenuItem[];
|
|
21
23
|
menuLabel: ReactNode;
|
|
22
24
|
pathname?: string;
|
|
@@ -25,27 +27,22 @@ export interface NavigationDrawerProps {
|
|
|
25
27
|
export const NavigationDrawer = ({
|
|
26
28
|
closeAncestor,
|
|
27
29
|
headerProps,
|
|
30
|
+
isSelected = false,
|
|
28
31
|
menuItems,
|
|
29
32
|
menuLabel,
|
|
30
33
|
pathname,
|
|
31
34
|
}: NavigationDrawerProps): JSX.Element => {
|
|
32
|
-
const
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
};
|
|
36
|
-
const closeDrawer = (): void => {
|
|
37
|
-
setDrawerOpen(false);
|
|
38
|
-
};
|
|
39
|
-
const closeDrawers = (): void => {
|
|
40
|
-
setDrawerOpen(false);
|
|
35
|
+
const { onClose, onOpen, open } = useDialog();
|
|
36
|
+
const closeDrawers = useCallback((): void => {
|
|
37
|
+
onClose();
|
|
41
38
|
closeAncestor?.();
|
|
42
|
-
};
|
|
39
|
+
}, [closeAncestor, onClose]);
|
|
43
40
|
return (
|
|
44
41
|
<>
|
|
45
42
|
<Button
|
|
46
43
|
EndIcon={ArrowDropDownRoundedIcon}
|
|
47
|
-
onClick={
|
|
48
|
-
variant="nav"
|
|
44
|
+
onClick={onOpen}
|
|
45
|
+
variant={isSelected ? "activeNav" : "nav"}
|
|
49
46
|
>
|
|
50
47
|
{menuLabel}
|
|
51
48
|
</Button>
|
|
@@ -55,7 +52,7 @@ export const NavigationDrawer = ({
|
|
|
55
52
|
hideBackdrop
|
|
56
53
|
keepMounted={false}
|
|
57
54
|
onClose={closeDrawers}
|
|
58
|
-
open={
|
|
55
|
+
open={open}
|
|
59
56
|
PaperProps={{ elevation: 0 }}
|
|
60
57
|
TransitionComponent={Slide}
|
|
61
58
|
transitionDuration={300}
|
|
@@ -66,7 +63,7 @@ export const NavigationDrawer = ({
|
|
|
66
63
|
<Content>
|
|
67
64
|
<BackButton
|
|
68
65
|
fullWidth
|
|
69
|
-
onClick={
|
|
66
|
+
onClick={onClose}
|
|
70
67
|
StartIcon={BackArrowIcon}
|
|
71
68
|
variant="backNav"
|
|
72
69
|
>
|
|
@@ -2,7 +2,7 @@ import ArrowDropDownRoundedIcon from "@mui/icons-material/ArrowDropDownRounded";
|
|
|
2
2
|
import { MenuProps as MMenuProps } from "@mui/material";
|
|
3
3
|
import React, { Fragment, ReactNode } from "react";
|
|
4
4
|
import { useBreakpoint } from "../../../../../../../../../../hooks/useBreakpoint";
|
|
5
|
-
import {
|
|
5
|
+
import { useMenu } from "../../../../../../../../../common/Menu/hooks/useMenu";
|
|
6
6
|
import { NavigationButtonLabel } from "../NavigationButtonLabel/navigationButtonLabel";
|
|
7
7
|
import {
|
|
8
8
|
MenuItem,
|
|
@@ -15,6 +15,7 @@ export interface NavLinkMenuProps {
|
|
|
15
15
|
anchorOrigin?: MMenuProps["anchorOrigin"];
|
|
16
16
|
closeAncestor?: () => void;
|
|
17
17
|
disablePortal?: boolean;
|
|
18
|
+
isSelected?: boolean;
|
|
18
19
|
menuItems: MenuItem[];
|
|
19
20
|
menuLabel: ReactNode;
|
|
20
21
|
pathname?: string;
|
|
@@ -24,12 +25,13 @@ export const NavigationMenu = ({
|
|
|
24
25
|
anchorOrigin = MENU_ANCHOR_ORIGIN_LEFT_BOTTOM,
|
|
25
26
|
closeAncestor,
|
|
26
27
|
disablePortal,
|
|
28
|
+
isSelected = false,
|
|
27
29
|
menuItems,
|
|
28
30
|
menuLabel,
|
|
29
31
|
pathname,
|
|
30
32
|
}: NavLinkMenuProps): JSX.Element => {
|
|
31
33
|
const { mdUp } = useBreakpoint();
|
|
32
|
-
const { anchorEl, onClose, onToggleOpen, open } =
|
|
34
|
+
const { anchorEl, onClose, onToggleOpen, open } = useMenu();
|
|
33
35
|
const MenuItem = disablePortal ? StyledMenuItem : Fragment;
|
|
34
36
|
const menuItemProps = disablePortal ? { onMouseLeave: onClose } : {};
|
|
35
37
|
return (
|
|
@@ -38,7 +40,7 @@ export const NavigationMenu = ({
|
|
|
38
40
|
EndIcon={ArrowDropDownRoundedIcon}
|
|
39
41
|
isActive={open}
|
|
40
42
|
onClick={onToggleOpen}
|
|
41
|
-
variant="nav"
|
|
43
|
+
variant={isSelected ? "activeNav" : "nav"}
|
|
42
44
|
>
|
|
43
45
|
<NavigationButtonLabel label={menuLabel} />
|
|
44
46
|
</Button>
|
|
@@ -49,7 +49,7 @@ export const NavigationMenuItems = ({
|
|
|
49
49
|
icon,
|
|
50
50
|
label,
|
|
51
51
|
menuItems: nestedMenuItems,
|
|
52
|
-
|
|
52
|
+
selectedPatterns,
|
|
53
53
|
target = ANCHOR_TARGET.SELF,
|
|
54
54
|
url,
|
|
55
55
|
},
|
|
@@ -79,11 +79,7 @@ export const NavigationMenuItems = ({
|
|
|
79
79
|
REL_ATTRIBUTE.NO_OPENER_NO_REFERRER
|
|
80
80
|
);
|
|
81
81
|
}}
|
|
82
|
-
selected={isNavigationLinkSelected(
|
|
83
|
-
url,
|
|
84
|
-
pathname,
|
|
85
|
-
selectedMatch
|
|
86
|
-
)}
|
|
82
|
+
selected={isNavigationLinkSelected(pathname, selectedPatterns)}
|
|
87
83
|
>
|
|
88
84
|
{icon && <ListItemIcon>{icon}</ListItemIcon>}
|
|
89
85
|
<ListItemText
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
REL_ATTRIBUTE,
|
|
9
9
|
} from "../../../../../../../Links/common/entities";
|
|
10
10
|
import { isClientSideNavigation } from "../../../../../../../Links/common/utils";
|
|
11
|
-
import {
|
|
11
|
+
import { SelectedMatch } from "../../../../common/entities";
|
|
12
12
|
import { HeaderProps } from "../../../../header";
|
|
13
13
|
import { isNavigationLinkSelected } from "./common/utils";
|
|
14
14
|
import { NavigationButtonLabel } from "./components/NavigationButtonLabel/navigationButtonLabel";
|
|
@@ -22,7 +22,8 @@ export interface NavLinkItem {
|
|
|
22
22
|
flatten?: Partial<Record<BreakpointKey, boolean>>;
|
|
23
23
|
label: ReactNode;
|
|
24
24
|
menuItems?: MenuItem[];
|
|
25
|
-
selectedMatch?:
|
|
25
|
+
selectedMatch?: SelectedMatch;
|
|
26
|
+
selectedPatterns?: string[];
|
|
26
27
|
target?: ANCHOR_TARGET;
|
|
27
28
|
url: string;
|
|
28
29
|
visible?: Partial<Record<BreakpointKey, boolean>>;
|
|
@@ -59,7 +60,7 @@ export const Navigation = forwardRef<HTMLDivElement, NavigationProps>(
|
|
|
59
60
|
divider,
|
|
60
61
|
label,
|
|
61
62
|
menuItems,
|
|
62
|
-
|
|
63
|
+
selectedPatterns,
|
|
63
64
|
target = ANCHOR_TARGET.SELF,
|
|
64
65
|
url,
|
|
65
66
|
},
|
|
@@ -70,6 +71,10 @@ export const Navigation = forwardRef<HTMLDivElement, NavigationProps>(
|
|
|
70
71
|
{mdUp ? (
|
|
71
72
|
<NavigationMenu
|
|
72
73
|
closeAncestor={closeAncestor}
|
|
74
|
+
isSelected={isNavigationLinkSelected(
|
|
75
|
+
pathname,
|
|
76
|
+
selectedPatterns
|
|
77
|
+
)}
|
|
73
78
|
menuItems={menuItems}
|
|
74
79
|
menuLabel={label}
|
|
75
80
|
pathname={pathname}
|
|
@@ -78,6 +83,10 @@ export const Navigation = forwardRef<HTMLDivElement, NavigationProps>(
|
|
|
78
83
|
<NavigationDrawer
|
|
79
84
|
closeAncestor={closeAncestor}
|
|
80
85
|
headerProps={headerProps}
|
|
86
|
+
isSelected={isNavigationLinkSelected(
|
|
87
|
+
pathname,
|
|
88
|
+
selectedPatterns
|
|
89
|
+
)}
|
|
81
90
|
menuItems={menuItems}
|
|
82
91
|
menuLabel={label}
|
|
83
92
|
pathname={pathname}
|
|
@@ -100,7 +109,7 @@ export const Navigation = forwardRef<HTMLDivElement, NavigationProps>(
|
|
|
100
109
|
);
|
|
101
110
|
}}
|
|
102
111
|
variant={
|
|
103
|
-
isNavigationLinkSelected(
|
|
112
|
+
isNavigationLinkSelected(pathname, selectedPatterns)
|
|
104
113
|
? "activeNav"
|
|
105
114
|
: "nav"
|
|
106
115
|
}
|
|
@@ -2,15 +2,12 @@ import { Fade, Toolbar } from "@mui/material";
|
|
|
2
2
|
import { usePathname } from "next/navigation";
|
|
3
3
|
import React, { ReactNode } from "react";
|
|
4
4
|
import { ComponentsConfig } from "../../../../config/entities";
|
|
5
|
-
import { useBreakpoint } from "../../../../hooks/useBreakpoint";
|
|
6
|
-
import { useMenu } from "../../../../hooks/useMenu";
|
|
7
5
|
import {
|
|
8
6
|
APP_BAR_PROPS,
|
|
9
7
|
FADE_TRANSITION_PROPS,
|
|
10
8
|
TOOLBAR_PROPS,
|
|
11
9
|
} from "./common/constants";
|
|
12
10
|
import { Navigation, SocialMedia } from "./common/entities";
|
|
13
|
-
import { getNavigationLinks } from "./common/utils";
|
|
14
11
|
import { Announcements } from "./components/Announcements/announcements";
|
|
15
12
|
import { Actions } from "./components/Content/components/Actions/actions";
|
|
16
13
|
import { Authentication } from "./components/Content/components/Actions/components/Authentication/authentication";
|
|
@@ -21,8 +18,10 @@ import { Slogan } from "./components/Content/components/Slogan/slogan";
|
|
|
21
18
|
import { Divider } from "./components/Content/components/Slogan/slogan.styles";
|
|
22
19
|
import { Socials } from "./components/Content/components/Socials/socials.styles";
|
|
23
20
|
import { AppBar, Center, Left, Right } from "./header.styles";
|
|
21
|
+
import { useHeaderNavigation } from "./hooks/useHeaderNavigation";
|
|
24
22
|
import { useHeaderVisibility } from "./hooks/useHeaderVisibility";
|
|
25
23
|
import { useMeasureHeader } from "./hooks/useMeasureHeader";
|
|
24
|
+
import { useMenu } from "./hooks/useMenu";
|
|
26
25
|
|
|
27
26
|
export interface HeaderProps {
|
|
28
27
|
actions?: ReactNode;
|
|
@@ -38,8 +37,8 @@ export interface HeaderProps {
|
|
|
38
37
|
}
|
|
39
38
|
|
|
40
39
|
export const Header = ({ ...headerProps }: HeaderProps): JSX.Element => {
|
|
41
|
-
const {
|
|
42
|
-
const { isIn } = useHeaderVisibility(headerProps);
|
|
40
|
+
const { navigation } = useHeaderNavigation(headerProps);
|
|
41
|
+
const { isIn } = useHeaderVisibility({ ...headerProps, navigation });
|
|
43
42
|
const { headerRef } = useMeasureHeader();
|
|
44
43
|
const { onClose, onOpen, open } = useMenu();
|
|
45
44
|
const pathname = usePathname() ?? "";
|
|
@@ -49,14 +48,16 @@ export const Header = ({ ...headerProps }: HeaderProps): JSX.Element => {
|
|
|
49
48
|
authenticationEnabled,
|
|
50
49
|
className,
|
|
51
50
|
logo,
|
|
52
|
-
navigation: [navItemsL, navItemsC, navItemsR] = [],
|
|
53
51
|
searchEnabled,
|
|
54
52
|
searchURL,
|
|
55
53
|
slogan,
|
|
56
54
|
socialMedia,
|
|
57
55
|
} = headerProps;
|
|
58
|
-
const
|
|
59
|
-
|
|
56
|
+
const [navItemsL, navItemsC, navItemsR] = navigation;
|
|
57
|
+
const navigationProps = {
|
|
58
|
+
headerProps: { ...headerProps, navigation },
|
|
59
|
+
pathname,
|
|
60
|
+
};
|
|
60
61
|
return (
|
|
61
62
|
<AppBar {...APP_BAR_PROPS} ref={headerRef} className={className}>
|
|
62
63
|
{/* Announcements */}
|
|
@@ -74,10 +75,7 @@ export const Header = ({ ...headerProps }: HeaderProps): JSX.Element => {
|
|
|
74
75
|
{isIn.isSloganIn && <Slogan slogan={slogan} />}
|
|
75
76
|
{/* Left navigation */}
|
|
76
77
|
{isIn.isLeftNavigationIn && (
|
|
77
|
-
<DXNavigation
|
|
78
|
-
{...navigationProps}
|
|
79
|
-
links={getNavigationLinks(navItemsL, breakpoint)}
|
|
80
|
-
/>
|
|
78
|
+
<DXNavigation {...navigationProps} links={navItemsL} />
|
|
81
79
|
)}
|
|
82
80
|
</Left>
|
|
83
81
|
</Fade>
|
|
@@ -86,10 +84,7 @@ export const Header = ({ ...headerProps }: HeaderProps): JSX.Element => {
|
|
|
86
84
|
<Center>
|
|
87
85
|
{/* Center navigation */}
|
|
88
86
|
{isIn.isCenterNavigationIn && (
|
|
89
|
-
<DXNavigation
|
|
90
|
-
{...navigationProps}
|
|
91
|
-
links={getNavigationLinks(navItemsC, breakpoint)}
|
|
92
|
-
/>
|
|
87
|
+
<DXNavigation {...navigationProps} links={navItemsC} />
|
|
93
88
|
)}
|
|
94
89
|
</Center>
|
|
95
90
|
</Fade>
|
|
@@ -98,10 +93,7 @@ export const Header = ({ ...headerProps }: HeaderProps): JSX.Element => {
|
|
|
98
93
|
<Right>
|
|
99
94
|
{/* Navigation */}
|
|
100
95
|
{isIn.isRightNavigationIn && (
|
|
101
|
-
<DXNavigation
|
|
102
|
-
{...navigationProps}
|
|
103
|
-
links={getNavigationLinks(navItemsR)}
|
|
104
|
-
/>
|
|
96
|
+
<DXNavigation {...navigationProps} links={navItemsR} />
|
|
105
97
|
)}
|
|
106
98
|
{/* Socials */}
|
|
107
99
|
{isIn.isSocialsIn && (
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { useBreakpoint } from "../../../../../hooks/useBreakpoint";
|
|
2
|
+
import { getNavigationLinks } from "../common/utils";
|
|
3
|
+
import { NavLinkItem } from "../components/Content/components/Navigation/navigation";
|
|
4
|
+
import { HeaderProps } from "../header";
|
|
5
|
+
|
|
6
|
+
export interface UseHeaderNavigation {
|
|
7
|
+
navigation: [NavLinkItem[], NavLinkItem[], NavLinkItem[]];
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const useHeaderNavigation = (
|
|
11
|
+
headerProps: HeaderProps
|
|
12
|
+
): UseHeaderNavigation => {
|
|
13
|
+
const { breakpoint } = useBreakpoint();
|
|
14
|
+
const { navigation: [navL, navC, navR] = [] } = headerProps;
|
|
15
|
+
const navItemsL = getNavigationLinks(navL, breakpoint);
|
|
16
|
+
const navItemsC = getNavigationLinks(navC, breakpoint);
|
|
17
|
+
const navItemsR = getNavigationLinks(navR, breakpoint);
|
|
18
|
+
return { navigation: [navItemsL, navItemsC, navItemsR] };
|
|
19
|
+
};
|
|
@@ -38,9 +38,9 @@ export const useHeaderVisibility = (
|
|
|
38
38
|
const hasActions = Boolean(actions);
|
|
39
39
|
const hasLogo = Boolean(logo);
|
|
40
40
|
const hasMenu = !mdUp;
|
|
41
|
-
const hasNavItemsC = Boolean(navItemsC);
|
|
42
|
-
const hasNavItemsL = Boolean(navItemsL);
|
|
43
|
-
const hasNavItemsR = Boolean(navItemsR);
|
|
41
|
+
const hasNavItemsC = Boolean(navItemsC && navItemsC.length > 0);
|
|
42
|
+
const hasNavItemsL = Boolean(navItemsL && navItemsL.length > 0);
|
|
43
|
+
const hasNavItemsR = Boolean(navItemsR && navItemsR.length > 0);
|
|
44
44
|
const hasSlogan = Boolean(slogan);
|
|
45
45
|
const hasSocials = Boolean(socialMedia);
|
|
46
46
|
// Determines header content visibility.
|