@heycar-uikit/core
Version:
The React UI library from HeyCar
124 lines (120 loc) • 10.1 kB
JavaScript
import React, { useState } from 'react';
import Grid from '../../grid/modern';
import { Close, Search, HeartDefault, Dealer, Call, Hamburger } from '../../icons/modern';
import Logo from '../../logo/modern';
import Typography from '../../typography/modern';
import LanguageList from './components/LanguageList.js';
import NavigationBurgerMenu from './components/NavigationBurgerMenu.js';
import NavigationDropdown from './components/NavigationDropdown.js';
import { MAX_FAVES_DISPLAY_NO, DEFAULT_LOCALE } from './constants/Header.constants.js';
import { useLangList } from './hooks/useLangList.js';
import { useNavigationItem } from './hooks/useNavigationItem.js';
import { hasHeaderItems, getCurrentLang } from './utils/headerItemHelpers.js';
import '../../collapse/modern';
import './components/SubNav.js';
import './utils/navigationHelpers.js';
var styles = {"header":"header__header_idaml","isBurgerOpen":"header__isBurgerOpen_idaml","headerInner":"header__headerInner_idaml","colLeft":"header__colLeft_idaml","colRight":"header__colRight_idaml","logo":"header__logo_idaml","searchWrapper":"header__searchWrapper_idaml","closeSearch":"header__closeSearch_idaml","active":"header__active_idaml","faves":"header__faves_idaml","counter":"header__counter_idaml","item":"header__item_idaml","horizontalNavOnly":"header__horizontalNavOnly_idaml","desktopOnly":"header__desktopOnly_idaml","focused":"header__focused_idaml","notHorizontalNav":"header__notHorizontalNav_idaml","asideItem":"header__asideItem_idaml","langWrapper":"header__langWrapper_idaml","navWrapper":"header__navWrapper_idaml"};
require('./styles/default.css');
const DefaultLinkComponent = (props) => React.createElement("a", { ...props });
const Header = React.forwardRef(({ accountItemConfig, auxiliaryDetails, callItemConfig, currentRoute, dataTestId, favoritesItemConfig, langItemConfig, LinkComponent, locale = DEFAULT_LOCALE, logoHref, navigation, onToggleBurgerMenu, searchItemConfig, trackingFn, }, ref) => {
// State items
const [isNavTrayOpen, setIsNavTrayOpen] = useState(false);
const [activeNavItem, setActiveNavItem] = useState(undefined);
const [isSearchOpen, setIsSearchOpen] = useState(false);
const toggleBurgerMenu = (isOpen) => {
setIsNavTrayOpen(isOpen);
if (typeof onToggleBurgerMenu === 'function')
onToggleBurgerMenu(isOpen);
};
const resetMenuState = () => {
setActiveNavItem(undefined);
toggleBurgerMenu(false);
};
const { itemOnClick } = useNavigationItem(activeNavItem, setActiveNavItem, resetMenuState);
// Link component
const Link = (LinkComponent || DefaultLinkComponent);
// Header items
const { hasSearch, hasFaves, hasLang, hasAccount, hasCall } = hasHeaderItems(searchItemConfig, favoritesItemConfig, langItemConfig, accountItemConfig, callItemConfig);
const favesCount = favoritesItemConfig?.favoritesNumber || 0;
// Lang
const currentLang = hasLang
? getCurrentLang(langItemConfig.currentLang, langItemConfig.options)
: undefined;
const LangIco = currentLang?.icon;
const { isLangListOpen, keyboardOpen, setIsFocused, setIsHovering } = useLangList();
// Event handlers
const handleSearchToggle = (newState) => {
setIsSearchOpen(newState);
if (searchItemConfig?.onClick)
searchItemConfig.onClick(newState);
};
return (React.createElement("header", { className: `${styles.header} ${isNavTrayOpen ? styles.isBurgerOpen : ''}`, "data-test-id": dataTestId, ref: ref },
React.createElement(Grid.Container, { className: styles.headerInner },
React.createElement(Grid.Row, { gutter: { mobile: 8, tablet: 12, desktop: 24 } },
React.createElement(Grid.Col, { className: styles.colLeft },
React.createElement(Link, { "aria-label": locale.logoLabel, className: styles.logo, href: logoHref, onClick: () => itemOnClick({
fn: trackingFn,
obj: { label: 'Logo', href: logoHref },
}) },
React.createElement(Logo, null)),
hasSearch && (React.createElement("div", { className: `${styles.searchWrapper} ${isSearchOpen ? styles.active : ''}` },
React.createElement("button", { "aria-label": locale.closeSearchLabel, className: styles.closeSearch, onClick: () => itemOnClick({
fn: trackingFn,
obj: {
label: 'Mobile Search Toggle',
action: 'close',
},
}, () => handleSearchToggle(false)) },
React.createElement(Close, null)),
searchItemConfig.Component))),
React.createElement(Grid.Col, { className: styles.colRight },
hasSearch && (React.createElement("button", { "aria-label": searchItemConfig.label, className: `${styles.notHorizontalNav} ${styles.item}`, onClick: () => itemOnClick({
fn: trackingFn,
obj: { label: 'Mobile Search Toggle', action: 'open' },
}, () => handleSearchToggle(true)) },
React.createElement(Search, null))),
hasFaves && (React.createElement(Link, { "aria-label": favoritesItemConfig.label, className: `${styles.item} ${styles.faves}`, href: favoritesItemConfig.href, onClick: () => itemOnClick({
fn: trackingFn,
obj: {
label: favoritesItemConfig.label,
href: favoritesItemConfig.href,
},
}, favoritesItemConfig.onClick) },
React.createElement(HeartDefault, null),
React.createElement("span", { "aria-label": locale.favoritesCountLabel, className: `${styles.counter} ${favesCount > 0 ? styles.active : ''}` }, favesCount > MAX_FAVES_DISPLAY_NO
? MAX_FAVES_DISPLAY_NO
: favesCount),
React.createElement(Typography, { variant: "subheading3" }, favoritesItemConfig.label))),
hasLang && currentLang && (React.createElement("div", { className: styles.langWrapper },
React.createElement("button", { "aria-haspopup": "menu", "aria-label": `${locale.langListHeading} - ${locale.spaceBarNotification}`, className: `${styles.horizontalNavOnly} ${styles.item} ${isLangListOpen ? styles.focused : ''}`, onBlur: () => setIsFocused(false), onFocus: () => setIsFocused(true), onKeyDown: e => keyboardOpen(e), onMouseOut: () => setIsHovering(false), onMouseOver: () => setIsHovering(true) },
LangIco,
React.createElement(Typography, { variant: "subheading3" }, currentLang.shortName)),
isLangListOpen && (React.createElement(LanguageList, { dataTestId: "header-language-list", heading: locale.langListHeading, itemOnClick: itemOnClick, onFocusEvents: setIsFocused, onHoverEvents: setIsHovering, options: langItemConfig.options, trackingFn: trackingFn })))),
hasAccount && (React.createElement("button", { "aria-label": accountItemConfig.label, className: `${styles.horizontalNavOnly} ${styles.item}`, onClick: () => itemOnClick({
fn: trackingFn,
obj: { label: accountItemConfig.label },
}, accountItemConfig.onClick) },
React.createElement(Dealer, null),
React.createElement(Typography, { variant: "subheading3" }, accountItemConfig.label))),
hasCall && (React.createElement(Link, { "aria-label": callItemConfig.label, className: `${styles.horizontalNavOnly} ${styles.item} ${styles.asideItem}`, href: callItemConfig.href, onClick: () => itemOnClick({
fn: trackingFn,
obj: {
label: callItemConfig.label,
href: callItemConfig.href,
},
}, callItemConfig.onClick) },
React.createElement(Call, null),
React.createElement(Typography, { variant: "subheading3" }, callItemConfig.label))),
React.createElement("button", { "aria-label": DEFAULT_LOCALE.burgerMenuButtonLabel, className: `${styles.notHorizontalNav} ${styles.item}`, onClick: () => itemOnClick({
fn: trackingFn,
obj: {
label: 'Burger Menu Toggle',
action: isNavTrayOpen ? 'close' : 'open',
},
}, () => toggleBurgerMenu(!isNavTrayOpen), false) }, isNavTrayOpen ? React.createElement(Close, null) : React.createElement(Hamburger, null))))),
React.createElement("div", { className: `${styles.navWrapper} ${isNavTrayOpen ? 'navOpen' : ''}` },
React.createElement(NavigationBurgerMenu, { Link: Link, accountItemConfig: accountItemConfig, activeNavItem: activeNavItem, auxiliaryDetails: auxiliaryDetails, currentLang: currentLang?.langCode, dataTestId: `${dataTestId}-navigation`, itemOnClick: itemOnClick, langItemConfig: langItemConfig, locale: locale, navigation: navigation, setActiveNavItem: setActiveNavItem, trackingFn: trackingFn }),
React.createElement(NavigationDropdown, { Link: Link, activeNavItem: activeNavItem, currentRoute: currentRoute, dataTestId: `${dataTestId}-navigation`, itemOnClick: itemOnClick, locale: locale, navigation: navigation, setActiveNavItem: setActiveNavItem, trackingFn: trackingFn }))));
});
Header.displayName = 'Header';
export { Header as default };