UNPKG

robust-react-ui

Version:

A React component library, built with a focus on accessibility, extensibility and reusability.

303 lines (298 loc) 17.2 kB
'use strict'; function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } var React = require('react'); var React__default = _interopDefault(React); var index = require('../../utils/getClassNames/index.js'); var _tslib = require('../../_virtual/_tslib.js'); var FOCUS_DELAY = 120; var NavigationBar = function (_a) { var data = _a.data, onEnterLinkFunction = _a.onEnterLinkFunction, ariaLabel = _a.ariaLabel, id = _a.id; var _b = React.useState([]), nodes = _b[0], setNodes = _b[1]; var _c = React.useState(false), closeAll = _c[0], setCloseAll = _c[1]; React.useEffect(function () { var allNodes = []; var getNode = function (x, i) { var o = {}; if (x.children && x.children.length && x.children.length > 0) { o.menuOpen = false; o.hasMenu = true; } else { o.hasMenu = false; } o.id = x.id; o.parentId = x.parentId; o.ref = React.createRef(); o.order = i; o.name = x.linkName; return o; }; data.forEach(function (x, i) { var _a; var node0 = _tslib.__assign(_tslib.__assign({}, getNode(x, i)), { lv: 1 }); allNodes.push(node0); (_a = x.children) === null || _a === void 0 ? void 0 : _a.forEach(function (x2, i2) { var _a; var node1 = _tslib.__assign(_tslib.__assign({}, getNode(x2, i2)), { menuId: x.id, lv: 2 }); allNodes.push(node1); (_a = x2.children) === null || _a === void 0 ? void 0 : _a.forEach(function (x3, i3) { var node2 = _tslib.__assign(_tslib.__assign({}, getNode(x3, i3)), { menuId: x.id, lv: 3 }); allNodes.push(node2); }); }); }); setNodes(allNodes); }, []); var closeAllMenuButOne = function (menuId) { setNodes(nodes.map(function (n) { if (n.id === menuId) { return _tslib.__assign(_tslib.__assign({}, n), { menuOpen: true }); } return _tslib.__assign(_tslib.__assign({}, n), { menuOpen: false }); })); }; var traverseTopLevelMenu = function (menuId, dir) { var menuNodes = nodes.filter(function (x) { return x.parentId === null; }); var max = menuNodes.length - 1; var ord = menuNodes.find(function (x) { return x.id === menuId; }).order; var next = ord === max ? 0 : ord + 1; var prev = ord === 0 ? max : ord - 1; if (dir === 'LEFT') { var m = menuNodes.find(function (x) { return x.order === prev; }); m.ref.current.focus(); if (closeAll) closeAllMenuButOne(m.id); } if (dir === 'RIGHT') { var m = menuNodes.find(function (x) { return x.order === next; }); m.ref.current.focus(); if (closeAll) closeAllMenuButOne(m.id); } }; var openMenu = function (menuId) { setNodes(nodes.map(function (n) { if (n.id === menuId) { return _tslib.__assign(_tslib.__assign({}, n), { menuOpen: true }); } return n; })); // focus on first child setTimeout(function () { var _a, _b; var exists = nodes.find(function (n) { return n.parentId === menuId; }); (_b = (_a = exists === null || exists === void 0 ? void 0 : exists.ref) === null || _a === void 0 ? void 0 : _a.current) === null || _b === void 0 ? void 0 : _b.focus(); }, FOCUS_DELAY); }; var focusDownNode = function (node) { // get nodes at the level var filtered = nodes.filter(function (n) { return n.parentId === node.parentId; }); // find the current pos var currentNode = filtered.find(function (n) { return n.id === node.id; }); var max = filtered.length - 1; // set the next pos and focus if (currentNode.order === max) { filtered[0].ref.current.focus(); } else { filtered[currentNode.order + 1].ref.current.focus(); } }; var focusUpNode = function (node) { // get nodes at the level var filtered = nodes.filter(function (n) { return n.parentId === node.parentId; }); // find the current pos var currentNode = filtered.find(function (n) { return n.id === node.id; }); var max = filtered.length - 1; // set the next pos and focus if (currentNode.order === 0) { filtered[max].ref.current.focus(); } else { filtered[currentNode.order - 1].ref.current.focus(); } }; var handleLeftPress = function (node) { // if has children has parent close the current dropdown // focus on parent node var foundNode = nodes.find(function (n) { return n.id === node.id; }); if (foundNode.lv > 2) { setNodes(nodes.map(function (n) { if (n.id === node.parentId) { return _tslib.__assign(_tslib.__assign({}, n), { menuOpen: false }); } return n; })); setTimeout(function () { var _a, _b, _c; (_c = (_b = (_a = nodes.find(function (n) { return n.id === node.parentId; })) === null || _a === void 0 ? void 0 : _a.ref) === null || _b === void 0 ? void 0 : _b.current) === null || _c === void 0 ? void 0 : _c.focus(); }, FOCUS_DELAY); } else { // else navigate to the previous TOPLEVEL nav item if (!closeAll) setCloseAll(true); traverseTopLevelMenu(foundNode.menuId, 'LEFT'); } }; var handleRightPress = function (node) { // if has children open the menu var foundNode = nodes.find(function (n) { return n.id === node.id; }); if (foundNode.hasMenu) { // open menu openMenu(node.id); // focus on the first setTimeout(function () { var _a, _b, _c; (_c = (_b = (_a = nodes.find(function (n) { return n.parentId === node.id; })) === null || _a === void 0 ? void 0 : _a.ref) === null || _b === void 0 ? void 0 : _b.current) === null || _c === void 0 ? void 0 : _c.focus(); }, FOCUS_DELAY); } else { // else navigate to the next TOPLEVEL nav item if (!closeAll) setCloseAll(true); traverseTopLevelMenu(foundNode.menuId, 'RIGHT'); } }; var handleLinkDefaultAction = function (href) { if (onEnterLinkFunction) { onEnterLinkFunction(href); return; } if (typeof window !== 'undefined') { window.location.href = href; } }; var closeAllAndFocusTopMenu = function (node) { // node.parentId setNodes(nodes.map(function (x) { return (_tslib.__assign(_tslib.__assign({}, x), { menuOpen: false })); })); nodes.find(function (n) { return n.id === node.parentId; }).ref.current.focus(); }; return (React__default.createElement("nav", { className: "rrui-nav", "data-testid": "NavigationBar", "aria-label": ariaLabel }, React__default.createElement("ul", { id: id || null, role: "menubar", "aria-label": ariaLabel }, data.map(function (a, _ai) { var _a; var n = nodes.find(function (nodeToFind4) { return nodeToFind4.id === a.id; }); return (React__default.createElement("li", { role: "none", className: index({ 'rrui-nav__menu-item': true, 'rrui-nav__menu-item--expanded': n === null || n === void 0 ? void 0 : n.menuOpen, 'rrui-nav__menu-item--has-menu': n === null || n === void 0 ? void 0 : n.hasMenu, }), key: a.linkName + _ai.toString() }, React__default.createElement("a", { ref: n === null || n === void 0 ? void 0 : n.ref, onKeyDown: function (e) { // left if (e.keyCode === 37) { traverseTopLevelMenu(a.id, 'LEFT'); } // right if (e.keyCode === 39) { traverseTopLevelMenu(a.id, 'RIGHT'); } // enter if (e.keyCode === 13) { if (n.hasMenu) { openMenu(a.id); } else { handleLinkDefaultAction(a.linkHref); } } }, role: "menuitem", "aria-haspopup": (n === null || n === void 0 ? void 0 : n.hasMenu) ? 'true' : 'false', "aria-expanded": (n === null || n === void 0 ? void 0 : n.menuOpen) ? 'true' : 'false', href: a.linkHref ? a.linkHref : '#', tabIndex: 0 }, a.linkName, (n === null || n === void 0 ? void 0 : n.hasMenu) && (React__default.createElement("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: index({ 'rrui-nav__chevron': true, }) }, React__default.createElement("polyline", { points: "9 18 15 12 9 6" })))), a.children && (React__default.createElement("ul", { className: index({ 'rrui-nav__dropdown': true, 'rrui-nav__dropdown--open': (_a = nodes.find(function (nodeToFind2) { return nodeToFind2.id === a.id; })) === null || _a === void 0 ? void 0 : _a.menuOpen, }), role: "menu", "aria-label": a.linkName }, a.children.map(function (b, _bi) { var _a; var n2 = nodes.find(function (nodeToFind) { return nodeToFind.id === b.id; }); return (React__default.createElement(React__default.Fragment, { key: b.linkName + _bi.toString() }, React__default.createElement("li", { role: "none", className: index({ 'rrui-nav__dropdown-item': true, 'rrui-nav__dropdown-item--expanded': n2 === null || n2 === void 0 ? void 0 : n2.menuOpen, }) }, React__default.createElement("a", { ref: n2 === null || n2 === void 0 ? void 0 : n2.ref, id: b.id.toString(), role: "menuitem", href: b.linkHref ? b.linkHref : '#', "aria-haspopup": (n2 === null || n2 === void 0 ? void 0 : n2.hasMenu) ? 'true' : 'false', "aria-expanded": (n2 === null || n2 === void 0 ? void 0 : n2.menuOpen) ? 'true' : 'false', tabIndex: -1, onKeyDown: function (e) { e.preventDefault(); // up if (e.keyCode === 38) { focusUpNode(b); } // down if (e.keyCode === 40) { focusDownNode(b); } // right if (e.keyCode === 39) { handleRightPress(b); } // left if (e.keyCode === 37) { handleLeftPress(b); } // escape if (e.keyCode === 27) { closeAllAndFocusTopMenu(b); } // enter if (e.keyCode === 13) { if (n2.hasMenu) { handleRightPress(b); } else { handleLinkDefaultAction(b.linkHref); } } } }, b.linkName, (n2 === null || n2 === void 0 ? void 0 : n2.hasMenu) && (React__default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: index({ 'rrui-nav__chevron': true, 'rrui-nav__chevron--submenu': true, 'rrui-nav__chevron--expanded': n2 === null || n2 === void 0 ? void 0 : n2.menuOpen, }) }, React__default.createElement("polyline", { points: "9 18 15 12 9 6" })))), b.children && (React__default.createElement("ul", { className: index({ 'rrui-nav__dropdown': true, 'rrui-nav__dropdown--nested': true, 'rrui-nav__dropdown--open': (_a = nodes.find(function (nodeToFind3) { return nodeToFind3.id === b.id; })) === null || _a === void 0 ? void 0 : _a.menuOpen, }), role: "menu", "aria-label": b.linkName }, b.children.map(function (c, _ci) { var n3 = nodes.find(function (nodeToFind5) { return nodeToFind5.id === c.id; }); return (React__default.createElement(React__default.Fragment, { key: c.linkName + _ci.toString() }, React__default.createElement("li", { role: "none", className: "rrui-nav__dropdown-item" }, React__default.createElement("a", { onKeyDown: function (e) { e.preventDefault(); // up if (e.keyCode === 38) { focusUpNode(c); } // down if (e.keyCode === 40) { focusDownNode(c); } // right if (e.keyCode === 39) { handleRightPress(c); } // left or escape if (e.keyCode === 37 || e.keyCode === 27) { handleLeftPress(c); } // enter if (e.keyCode === 13) { if (n3.hasMenu) { handleRightPress(c); } else { handleLinkDefaultAction(c.linkHref); } } }, ref: n3 === null || n3 === void 0 ? void 0 : n3.ref, id: c.id.toString(), role: "menuitem", href: c.linkHref ? c.linkHref : '#', "aria-haspopup": "false", "aria-expanded": null, tabIndex: -1 }, c.linkName)), c.hasSeparator && (React__default.createElement("li", { role: "separator", className: "rrui-nav__separator" })))); })))), b.hasSeparator && (React__default.createElement("li", { role: "separator", className: "rrui-nav__separator" })))); }))))); })))); }; module.exports = NavigationBar; //# sourceMappingURL=NavigationBar.js.map