UNPKG

@dnanpm/styleguide

Version:

DNA Styleguide repository provides the set of components and theme object used in various DNA projects.

189 lines (182 loc) 10.7 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var icons = require('@dnanpm/icons'); var React = require('react'); var reactSpring = require('react-spring'); var styledComponents = require('styled-components'); var theme = require('../../../themes/theme.js'); var navigation = require('../../../themes/themeComponents/navigation.js'); var styledUtils = require('../../../utils/styledUtils.js'); var NavContext = require('../context/NavContext.js'); var globalNavStyles = require('../globalNavStyles.js'); var LinkModifier = require('./LinkModifier.js'); function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; } var React__default = /*#__PURE__*/_interopDefaultCompat(React); const MobileMenuWrapper = styledComponents.styled(reactSpring.animated.div) ` width: ${100 * navigation.menuLevelsAmount}%; display: flex; button { border: 0; background: transparent; } `; const mobileMenu = `calc(100vh - ${navigation.headerMaxHeight})`; const MenuLinkBackLink = styledComponents.styled(globalNavStyles.MenuLink) ``; const MobileMenuContainer = styledComponents.styled.nav ` width: 100%; position: absolute; top: ${navigation.navMaxHeight}; right: 0; overflow: hidden; overflow-y: auto; transition: max-height 0.2s ease-in-out; background-color: ${theme.default.color.background.sand.default}; max-height: ${mobileMenu}; height: ${mobileMenu}; max-width: ${navigation.mobileNavMaxWidth}; ${globalNavStyles.MenuList} { display: block; width: ${100 / navigation.menuLevelsAmount}%; position: relative; border-top: 4px solid ${theme.default.color.background.white.default}; &:first-of-type { background: ${theme.default.color.background.white.default}; > ${globalNavStyles.MenuItem} > ${globalNavStyles.MenuLink} { font-weight: ${theme.default.fontWeight.bold}; height: ${styledUtils.getMultipliedSize(theme.default.base.baseHeight, 6)}; } } &:not(:first-of-type) { background: ${theme.default.color.background.sand.default}; } ${globalNavStyles.MenuItem} { border-bottom: 1px solid ${theme.default.color.line.L04}; } margin-bottom: ${navigation.headerMaxHeight}; // make sure items are visible in different devices which might calculate vh differently } ${globalNavStyles.MenuLink}, ${globalNavStyles.MenuLinkWithChildren} { line-height: ${theme.default.lineHeight.default}; padding: ${styledUtils.getMultipliedSize(theme.default.base.baseWidth, 2)}; font-size: ${theme.default.fontSize.default}; display: flex; flex-grow: 1; align-items: center; height: ${styledUtils.getMultipliedSize(theme.default.base.baseHeight, 5)}; &:hover { cursor: pointer; text-decoration: none; } } ${MenuLinkBackLink} { font-weight: ${theme.default.fontWeight.bold}; background: ${theme.default.color.background.white.default}; color: ${theme.default.color.text.pink}; justify-content: flex-start; gap: ${styledUtils.getMultipliedSize(theme.default.base.baseHeight, 1)}; height: ${styledUtils.getMultipliedSize(theme.default.base.baseHeight, 6)}; } ${globalNavStyles.FeaturedBlock} { border-bottom: 1px solid ${theme.default.color.line.L04}; section > a { font-size: ${theme.default.fontSize.s}; line-height: ${theme.default.lineHeight.s}; padding: ${styledUtils.getMultipliedSize(theme.default.base.baseHeight, 1)}; height: auto; } } `; const MenuItemBackLink = ({ currentLevel, backRef, }) => { const { backToPreviousCategoryLabel, handleNavMenuClick, lang, menuLevel: { scrollPosition }, level1Items, level2Items, getBackLink, } = React.useContext(NavContext.default); const menuElements = currentLevel === 2 ? level1Items : level2Items; const tabNavigationDisabled = scrollPosition !== currentLevel - 1; const backLink = getBackLink(menuElements, currentLevel - 1); const mobileMenuBackClick = () => { handleNavMenuClick(null, `level${currentLevel - 1}Mobile`); }; return (React__default.default.createElement(globalNavStyles.MenuItem, { "data-testid": `mobile-nav-menu-backlink-level-${currentLevel}` }, React__default.default.createElement(MenuLinkBackLink, { as: "button", ref: backRef, onClick: mobileMenuBackClick, tabIndex: tabNavigationDisabled ? -1 : undefined, "aria-label": `${backToPreviousCategoryLabel} ${backLink.titles[lang]}` }, React__default.default.createElement(icons.ChevronLeft, { size: "1.5rem" }), backLink.titles[lang]))); }; const SubMenuItem = ({ menuItem, currentLevel, itemIndex, mobileMenuRef, firstItemRef, }) => { const { handleNavMenuClick, menuLevel, lang, currentUrl } = React.useContext(NavContext.default); const hasChildren = !!menuItem.pages.length; const indexLevel = currentLevel - 1; const tabNavigationDisabled = menuLevel.scrollPosition !== indexLevel; const menuUrl = menuItem.urls[lang]; const mobileMenuClick = (element) => (e) => { var _a, _b; (_b = (_a = mobileMenuRef === null || mobileMenuRef === void 0 ? void 0 : mobileMenuRef.current) === null || _a === void 0 ? void 0 : _a.scroll) === null || _b === void 0 ? void 0 : _b.call(_a, { top: 0, left: 0, behavior: 'smooth', }); e.preventDefault(); handleNavMenuClick(element.id, `level${currentLevel}Mobile`); }; const renderMenuItem = (children) => (React__default.default.createElement(globalNavStyles.MenuItem, { key: menuItem.id, "data-testid": `mobile-menu-level-${currentLevel}-link-${itemIndex + 1}`, "$isActive": LinkModifier.isSelected(currentUrl, menuUrl, true) }, children)); if (hasChildren && currentLevel < 3) { return renderMenuItem(React__default.default.createElement(globalNavStyles.MenuLink, { as: "button", ref: firstItemRef, onClick: mobileMenuClick(menuItem), tabIndex: tabNavigationDisabled ? -1 : undefined }, menuItem.titles[lang], React__default.default.createElement(icons.ChevronRight, { color: theme.default.color.default.pink }))); } return renderMenuItem(React__default.default.createElement(LinkModifier.default, { menuItem: menuItem, disabledTabIndex: tabNavigationDisabled })); }; const SubMenuMobile = ({ currentLevel, menuItem, mobileMenuRef }) => { const { collapseSize, featuredItemsAriaLabel, menuLevel } = React.useContext(NavContext.default); const indexLevel = currentLevel - 1; const tabNavigationDisabled = menuLevel.scrollPosition !== indexLevel; const backRef = React.useRef(null); const firstItemRef = React.useRef(null); React.useEffect(() => { // Delay focus to allow animation to finish const timer = setTimeout(() => { if (currentLevel === 1 && firstItemRef.current) { firstItemRef.current.focus(); } if (currentLevel > 1 && backRef.current) { backRef.current.focus(); } }, 300); return () => clearTimeout(timer); }, [menuItem, currentLevel]); if (!(menuItem === null || menuItem === void 0 ? void 0 : menuItem.pages.length)) { return null; } const featuredItems = currentLevel === 2 ? menuItem.pages.filter(subMenuItem => !subMenuItem.pages.length) : []; const menuItems = menuItem.pages.filter(subMenuItem => !featuredItems.includes(subMenuItem)); return (React__default.default.createElement(React__default.default.Fragment, null, currentLevel > 1 && React__default.default.createElement(MenuItemBackLink, { backRef: backRef, currentLevel: currentLevel }), featuredItems.length > 0 && (React__default.default.createElement(globalNavStyles.FeaturedBlock, { "$collapseSize": collapseSize }, React__default.default.createElement("section", { "aria-label": featuredItemsAriaLabel }, featuredItems.map(subMenuItem => (React__default.default.createElement(LinkModifier.default, { key: subMenuItem.id, menuItem: subMenuItem, showIcon: true, disabledTabIndex: tabNavigationDisabled })))))), menuItems.map((subMenuItem, index) => (React__default.default.createElement(SubMenuItem, { currentLevel: currentLevel, itemIndex: index, key: subMenuItem.id, menuItem: subMenuItem, mobileMenuRef: mobileMenuRef, firstItemRef: index === 0 ? firstItemRef : undefined }))))); }; const NavigationMenuMobile = ({ mobileMenuRef }) => { const { items, menuLevel, level1Items, level2Items } = React.useContext(NavContext.default); const { mainNavigation } = items; if (!(mainNavigation === null || mainNavigation === void 0 ? void 0 : mainNavigation.pages.length)) { return null; } const renderMenuList = (scrollPosition, level, menuItem) => (React__default.default.createElement(globalNavStyles.MenuList, { "aria-hidden": menuLevel.scrollPosition !== scrollPosition, "aria-disabled": menuLevel.scrollPosition !== scrollPosition, "data-testid": `mobile-nav-menu-level-${level}`, "$isInView": menuLevel.scrollPosition === scrollPosition }, menuLevel.scrollPosition === scrollPosition && (React__default.default.createElement(SubMenuMobile, { currentLevel: level, menuItem: menuItem, mobileMenuRef: mobileMenuRef })))); return (React__default.default.createElement(React__default.default.Fragment, null, renderMenuList(0, 1, mainNavigation), menuLevel.level1Mobile !== null && renderMenuList(1, 2, level1Items[menuLevel.level1Mobile]), menuLevel.level2Mobile !== null && renderMenuList(2, 3, level2Items[menuLevel.level2Mobile]))); }; const RenderMobileMenu = () => { const { menuLevel, isMobileMenuOpen } = React.useContext(NavContext.default); const mobileMenuRef = React.useRef(null); const slidingMenuAnimation = reactSpring.useSpring({ transform: `translateX(${(menuLevel.scrollPosition / navigation.menuLevelsAmount) * -100}%)`, }); if (!isMobileMenuOpen) { return null; } return (React__default.default.createElement(MobileMenuContainer, { ref: mobileMenuRef, role: "dialog", "aria-modal": "true" }, React__default.default.createElement(MobileMenuWrapper, { style: slidingMenuAnimation }, React__default.default.createElement(NavigationMenuMobile, { mobileMenuRef: mobileMenuRef })))); }; exports.MenuItemBackLink = MenuItemBackLink; exports.default = RenderMobileMenu;