@octopusdeploy/design-system-components
Version:
The design systems component library.
168 lines (167 loc) • 7.56 kB
JavaScript
;
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;