UNPKG

@octopusdeploy/design-system-components

Version:
168 lines (167 loc) • 7.56 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const jsx_runtime_1 = require("react/jsx-runtime"); const css_1 = require("@emotion/css"); const design_system_tokens_1 = require("@octopusdeploy/design-system-tokens"); const lodash_throttle_1 = __importDefault(require("lodash.throttle")); const React = __importStar(require("react")); const routing_1 = require("../../routing"); const LinksMenu_1 = require("./LinksMenu"); class PriorityNavigation extends React.Component { lastKnownContainerWidth = undefined; resizeObserver; constructor(props) { super(props); this.resizeObserver = new ResizeObserver((0, lodash_throttle_1.default)(this.onResize, 100)); this.state = { itemWidths: undefined, isMoreMenuOpen: false, priorityItems: this.props.navigationItems, moreItems: [], }; } // eslint-disable-next-line react/no-unsafe UNSAFE_componentWillReceiveProps() { if (this.lastKnownContainerWidth !== undefined && this.state.itemWidths !== undefined) { this.updateNavigation(this.lastKnownContainerWidth, this.state.itemWidths); } } componentWillUnmount() { this.resizeObserver.disconnect(); } render() { const hasMeasuredItemWidths = this.state.itemWidths !== undefined; const priorityItems = hasMeasuredItemWidths ? this.state.priorityItems : this.props.navigationItems; const moreItems = hasMeasuredItemWidths ? this.state.moreItems : []; const showMoreItems = !hasMeasuredItemWidths || moreItems.length > 0; return ((0, jsx_runtime_1.jsx)("nav", { "data-amplitude-unmask": true, className: styles.container, children: (0, jsx_runtime_1.jsxs)("ul", { ref: this.setNavigation, className: styles.ul, children: [priorityItems.map((item, index) => ((0, jsx_runtime_1.jsx)(NavItem, { item: item }, `navItem-${index}`))), showMoreItems && (0, jsx_runtime_1.jsx)(MoreNavItem, { moreItems: moreItems })] }) })); } howManyItemsInMenuArray = (array, outerWidth, initialWidth, maximumNumberInNav) => { let total = initialWidth; for (let i = 0; i < array.length; i++) { if (i > maximumNumberInNav) { return maximumNumberInNav; } total += array[i]; if (total > (outerWidth || 0)) { return i; } } return array.length; }; updateNavigation = (containerWidth, itemWidths) => { const arrayAmount = this.howManyItemsInMenuArray(itemWidths, containerWidth, itemWidths[itemWidths.length - 1], this.props.maxNavigationItems); const navItemsCopy = this.props.navigationItems; const priorityItems = navItemsCopy.slice(0, arrayAmount); const moreItems = priorityItems.length !== navItemsCopy.length ? navItemsCopy.slice(arrayAmount, navItemsCopy.length) : []; this.setState({ priorityItems, moreItems, }); }; onResize = (entries) => { const navigation = entries[0].target; if (this.state.itemWidths === undefined) { const itemWidths = Array.prototype.slice.call(navigation.children).map((item) => item.getBoundingClientRect().width); this.setState({ itemWidths }, () => { this.updateNavigation(navigation.clientWidth, itemWidths); }); } else if (navigation.clientWidth !== this.lastKnownContainerWidth) { this.updateNavigation(navigation.clientWidth, this.state.itemWidths); } this.lastKnownContainerWidth = navigation.clientWidth; }; setNavigation = (el) => { this.resizeObserver.disconnect(); if (el !== null) { this.resizeObserver.observe(el); } }; } const NavItem = (props) => { const item = props.item; const Link = (0, routing_1.useOctopusLinkComponent)(); const isUrlActive = (0, routing_1.useIsUrlActive)(); const urlIsActive = isUrlActive(item.url, item.exact ? "if path matches exactly" : "if path partially matches"); const handleClick = (event) => { const target = event.currentTarget; const label = target.innerText ?? target.getAttribute("aria-label") ?? ""; const href = target.href; item?.onClick(label, href); }; return ((0, jsx_runtime_1.jsx)("li", { className: styles.li, children: (0, jsx_runtime_1.jsx)(Link, { href: item.url, className: (0, css_1.cx)(styles.link, { [styles.selectedLink]: urlIsActive }), onClick: handleClick, disableImplicitEventTracking: true, children: (0, jsx_runtime_1.jsx)("span", { children: item.text }) }) })); }; function MoreNavItem(props) { return ((0, jsx_runtime_1.jsx)("li", { className: styles.li, children: (0, jsx_runtime_1.jsx)(LinksMenu_1.LinksMenu, { className: styles.link, items: props.moreItems, label: "More" }) }, "navItem-more")); } const styles = { container: (0, css_1.css)({ overflow: "hidden", whiteSpace: "nowrap", height: "2.5rem", margin: 0, paddingBottom: 0, }), ul: (0, css_1.css)({ margin: 0, }), li: (0, css_1.css)({ display: "inline-block", }), link: (0, css_1.css)({ font: design_system_tokens_1.text.body.regular.medium, color: design_system_tokens_1.themeTokens.color.navList.text.default, display: "flex", alignItems: "center", padding: `0 ${design_system_tokens_1.space[16]}`, height: "2.5rem", ":hover": { color: design_system_tokens_1.themeTokens.color.navList.text.active, }, }), selectedLink: (0, css_1.css)({ color: design_system_tokens_1.themeTokens.color.navList.text.active, ":hover": { // We need to re-apply the same styles here because we have global css trying to style this hover state color: design_system_tokens_1.themeTokens.color.navList.text.active, }, }), }; exports.default = PriorityNavigation;