accessible-menu
Advanced tools
Comparing version 1.0.6 to 1.0.7
@@ -5,2 +5,15 @@ # Changelog | ||
### [1.0.7](https://github.com/NickDJM/accessible-menu/compare/v1.0.6...v1.0.7) (2021-03-24) | ||
### Bug Fixes | ||
* **menu:** wait for menu to render before focussing child ([c5dae5d](https://github.com/NickDJM/accessible-menu/commit/c5dae5d59df145ca018128cf81fbd4a82493b8e3)), closes [#99](https://github.com/NickDJM/accessible-menu/issues/99) | ||
### Build System | ||
* update config for linting ([7259769](https://github.com/NickDJM/accessible-menu/commit/72597695911c1f58060800d3a809348ccceba38a)) | ||
* **npm:** security updates for dev dependencies ([4153685](https://github.com/NickDJM/accessible-menu/commit/415368540edc33b54287473a3c7ba0e09b3e7219)) | ||
### [1.0.6](https://github.com/NickDJM/accessible-menu/compare/v1.0.5...v1.0.6) (2020-02-26) | ||
@@ -7,0 +20,0 @@ |
@@ -12,3 +12,3 @@ "use strict"; | ||
var validate = { | ||
var validate$3 = { | ||
event: function event(value) { | ||
@@ -35,3 +35,3 @@ if (!(value instanceof Event)) { | ||
// Run validation. | ||
validate.keyboardEvent(event); | ||
validate$3.keyboardEvent(event); | ||
@@ -71,3 +71,3 @@ try { | ||
// Run validation. | ||
validate.event(event); | ||
validate$3.event(event); | ||
event.preventDefault(); | ||
@@ -78,3 +78,3 @@ event.stopPropagation(); | ||
var validate$1 = { | ||
var validate$2 = { | ||
menuToggleElement: function menuToggleElement(element) { | ||
@@ -124,5 +124,3 @@ // Ensure element is an HTML element. | ||
var MenuToggle = | ||
/*#__PURE__*/ | ||
function () { | ||
var MenuToggle = /*#__PURE__*/function () { | ||
/** | ||
@@ -150,7 +148,7 @@ * {@inheritdoc} | ||
// Run validations. | ||
validate$1.menuToggleElement(menuToggleElement); | ||
validate$1.parentElement(parentElement); | ||
validate$1.menu(menu); | ||
validate$1.openClass(openClass); | ||
validate$1.parentMenu(parentMenu); | ||
validate$2.menuToggleElement(menuToggleElement); | ||
validate$2.parentElement(parentElement); | ||
validate$2.menu(menu); | ||
validate$2.openClass(openClass); | ||
validate$2.parentMenu(parentMenu); | ||
this.domElements = { | ||
@@ -202,7 +200,69 @@ toggle: menuToggleElement, | ||
}, { | ||
key: "expand", | ||
key: "element", | ||
get: function get() { | ||
return this.domElements.toggle; | ||
} | ||
/** | ||
* The toggle's parent DOM element. | ||
* | ||
* @returns {HTMLElement} - The parent element. | ||
*/ | ||
}, { | ||
key: "parentElement", | ||
get: function get() { | ||
return this.domElements.parent; | ||
} | ||
/** | ||
* The menu controlled by the toggle. | ||
* | ||
* @returns {Menu} - The menu element. | ||
*/ | ||
}, { | ||
key: "menu", | ||
get: function get() { | ||
return this.elements.menu; | ||
} | ||
/** | ||
* The menu containing the toggle. | ||
* | ||
* @returns {Menu} - The menu element. | ||
*/ | ||
}, { | ||
key: "parentMenu", | ||
get: function get() { | ||
return this.elements.parentMenu; | ||
} | ||
/** | ||
* The open state on the menu. | ||
* | ||
* @returns {boolean} - The open state. | ||
*/ | ||
}, { | ||
key: "isOpen", | ||
get: function get() { | ||
return this.show; | ||
} | ||
/** | ||
* Set the open state on the menu. | ||
* | ||
* @param {boolean} value - The open state. | ||
*/ | ||
, | ||
set: function set(value) { | ||
if (typeof value !== "boolean") { | ||
throw new TypeError("Open state must be true or false."); | ||
} | ||
this.show = value; | ||
} | ||
/** | ||
* Expands the submenu. | ||
*/ | ||
}, { | ||
key: "expand", | ||
value: function expand() { | ||
@@ -339,64 +399,2 @@ // Assign new WAI-ARIA/class values. | ||
} | ||
}, { | ||
key: "element", | ||
get: function get() { | ||
return this.domElements.toggle; | ||
} | ||
/** | ||
* The toggle's parent DOM element. | ||
* | ||
* @returns {HTMLElement} - The parent element. | ||
*/ | ||
}, { | ||
key: "parentElement", | ||
get: function get() { | ||
return this.domElements.parent; | ||
} | ||
/** | ||
* The menu controlled by the toggle. | ||
* | ||
* @returns {Menu} - The menu element. | ||
*/ | ||
}, { | ||
key: "menu", | ||
get: function get() { | ||
return this.elements.menu; | ||
} | ||
/** | ||
* The menu containing the toggle. | ||
* | ||
* @returns {Menu} - The menu element. | ||
*/ | ||
}, { | ||
key: "parentMenu", | ||
get: function get() { | ||
return this.elements.parentMenu; | ||
} | ||
/** | ||
* The open state on the menu. | ||
* | ||
* @returns {boolean} - The open state. | ||
*/ | ||
}, { | ||
key: "isOpen", | ||
get: function get() { | ||
return this.show; | ||
} | ||
/** | ||
* Set the open state on the menu. | ||
* | ||
* @param {boolean} value - The open state. | ||
*/ | ||
, | ||
set: function set(value) { | ||
if (typeof value !== "boolean") { | ||
throw new TypeError("Open state must be true or false."); | ||
} | ||
this.show = value; | ||
} | ||
}]); | ||
@@ -408,3 +406,3 @@ | ||
var validate$2 = { | ||
var validate$1 = { | ||
menuItemElement: function menuItemElement(element) { | ||
@@ -455,5 +453,3 @@ // Ensure element is an HTML element. | ||
var MenuItem = | ||
/*#__PURE__*/ | ||
function () { | ||
var MenuItem = /*#__PURE__*/function () { | ||
/** | ||
@@ -484,8 +480,8 @@ * {@inheritdoc} | ||
// Run validations. | ||
validate$2.menuItemElement(menuItemElement); | ||
validate$2.menuLinkElement(menuLinkElement); | ||
validate$2.parentMenu(parentMenu); | ||
validate$2.isSubmenuItem(isSubmenuItem); | ||
validate$2.childMenu(childMenu); | ||
validate$2.toggle(toggle); | ||
validate$1.menuItemElement(menuItemElement); | ||
validate$1.menuLinkElement(menuLinkElement); | ||
validate$1.parentMenu(parentMenu); | ||
validate$1.isSubmenuItem(isSubmenuItem); | ||
validate$1.childMenu(childMenu); | ||
validate$1.toggle(toggle); | ||
this.domElements = { | ||
@@ -522,28 +518,2 @@ menuItem: menuItemElement, | ||
}, { | ||
key: "focus", | ||
/** | ||
* Focuses the menu item's link and set proper tabIndex. | ||
*/ | ||
value: function focus() { | ||
this.linkElement.focus(); | ||
if (this.parentMenu.isTopLevel) { | ||
this.linkElement.tabIndex = 0; | ||
} | ||
} | ||
/** | ||
* Blurs the menu item's link and set proper tabIndex. | ||
*/ | ||
}, { | ||
key: "blur", | ||
value: function blur() { | ||
this.linkElement.blur(); | ||
if (this.parentMenu.isTopLevel) { | ||
this.linkElement.tabIndex = -1; | ||
} | ||
} | ||
}, { | ||
key: "element", | ||
@@ -608,2 +578,28 @@ get: function get() { | ||
} | ||
/** | ||
* Focuses the menu item's link and set proper tabIndex. | ||
*/ | ||
}, { | ||
key: "focus", | ||
value: function focus() { | ||
this.linkElement.focus(); | ||
if (this.parentMenu.isTopLevel) { | ||
this.linkElement.tabIndex = 0; | ||
} | ||
} | ||
/** | ||
* Blurs the menu item's link and set proper tabIndex. | ||
*/ | ||
}, { | ||
key: "blur", | ||
value: function blur() { | ||
this.linkElement.blur(); | ||
if (this.parentMenu.isTopLevel) { | ||
this.linkElement.tabIndex = -1; | ||
} | ||
} | ||
}]); | ||
@@ -615,3 +611,3 @@ | ||
var validate$3 = { | ||
var validate = { | ||
menuElement: function menuElement(element) { | ||
@@ -691,5 +687,3 @@ // Ensure element is an HTML element. | ||
var Menu = | ||
/*#__PURE__*/ | ||
function () { | ||
var Menu = /*#__PURE__*/function () { | ||
/** | ||
@@ -733,9 +727,9 @@ * {@inheritdoc} | ||
// Run validations. | ||
validate$3.menuElement(menuElement); | ||
validate$3.menuItemSelector(menuItemSelector); | ||
validate$3.hasSubmenus(submenuItemSelector, submenuToggleSelector, submenuSelector); | ||
validate$3.openClass(openClass); | ||
validate$3.isTopLevel(isTopLevel); | ||
validate$3.isDropdown(controllerElement, containerElement); | ||
validate$3.parentMenu(parentMenu); | ||
validate.menuElement(menuElement); | ||
validate.menuItemSelector(menuItemSelector); | ||
validate.hasSubmenus(submenuItemSelector, submenuToggleSelector, submenuSelector); | ||
validate.openClass(openClass); | ||
validate.isTopLevel(isTopLevel); | ||
validate.isDropdown(controllerElement, containerElement); | ||
validate.parentMenu(parentMenu); | ||
this.domElements = { | ||
@@ -811,5 +805,173 @@ menu: menuElement, | ||
}, { | ||
key: "findRootMenu", | ||
key: "element", | ||
get: function get() { | ||
return this.domElements.menu; | ||
} | ||
/** | ||
* The menu's controller element in the DOM. | ||
* | ||
* @returns {HTMLElement|null} - The controller element. | ||
*/ | ||
}, { | ||
key: "controllerElement", | ||
get: function get() { | ||
return this.domElements.controller; | ||
} | ||
/** | ||
* The menu's container element in the DOM. | ||
* | ||
* @returns {HTMLElement|null} - The container element. | ||
*/ | ||
}, { | ||
key: "containerElement", | ||
get: function get() { | ||
return this.domElements.container; | ||
} | ||
/** | ||
* The menu item DOM elements contained in the menu. | ||
* | ||
* @returns {HTMLElement[]} - The menu items. | ||
*/ | ||
}, { | ||
key: "menuItemElements", | ||
get: function get() { | ||
return this.domElements.menuItems; | ||
} | ||
/** | ||
* The submenu item DOM elements contained in the menu. | ||
* | ||
* @returns {HTMLElement[]} - The submenu items. | ||
*/ | ||
}, { | ||
key: "submenuItemElements", | ||
get: function get() { | ||
return this.domElements.submenuItems; | ||
} | ||
/** | ||
* The menu items contained in the menu. | ||
* | ||
* @returns {MenuItem[]} - The menu items. | ||
*/ | ||
}, { | ||
key: "menuItems", | ||
get: function get() { | ||
return this.elements.menuItems; | ||
} | ||
/** | ||
* The menu toggles contained in the menu. | ||
* | ||
* @returns {MenuToggle[]} - The menu toggles. | ||
*/ | ||
}, { | ||
key: "menuToggles", | ||
get: function get() { | ||
return this.elements.menuToggles; | ||
} | ||
/** | ||
* The parent menu containing this menu. | ||
* | ||
* @returns {Menu|null} - The parent menu. | ||
*/ | ||
}, { | ||
key: "parentMenu", | ||
get: function get() { | ||
return this.elements.parentMenu; | ||
} | ||
/** | ||
* The root menu containing this menu. | ||
* | ||
* @returns {Menu|null} - The root menu. | ||
*/ | ||
}, { | ||
key: "rootMenu", | ||
get: function get() { | ||
return this.elements.rootMenu; | ||
} | ||
/** | ||
* The menu's controller toggle. | ||
* | ||
* @returns {MenuToggle} - The toggle. | ||
*/ | ||
}, { | ||
key: "controller", | ||
get: function get() { | ||
return this.elements.controller; | ||
} | ||
/** | ||
* The DOM Selectors for the menu. | ||
* | ||
* @returns {object} - The DOM Selectors. | ||
*/ | ||
}, { | ||
key: "selector", | ||
get: function get() { | ||
return this.domSelectors; | ||
} | ||
/** | ||
* The focus state of the menu. | ||
* | ||
* @returns {string} - The focus state (self, child, none). | ||
*/ | ||
}, { | ||
key: "currentFocus", | ||
get: function get() { | ||
return this.focusState; | ||
} | ||
/** | ||
* The class used for open submenus. | ||
* | ||
* @returns {string} - The open class. | ||
*/ | ||
, | ||
set: | ||
/** | ||
* Set the focus state of the menu. | ||
* | ||
* @param {string} value - The focus state (self, child, none). | ||
*/ | ||
function set(value) { | ||
var states = ["self", "child", "none"]; | ||
if (!states.includes(value)) { | ||
throw new Error("Focus state must be 'self', 'child', or 'none'."); | ||
} | ||
this.focusState = value; | ||
} | ||
/** | ||
* Set the class used for open submenus. | ||
* | ||
* @param {string} value - The open class. | ||
*/ | ||
}, { | ||
key: "openClass", | ||
get: function get() { | ||
return this.submenuOpenClass; | ||
} | ||
/** | ||
* The currently focussed menu item. | ||
* | ||
* @returns {MenuItem} - The menu item. | ||
*/ | ||
, | ||
set: function set(value) { | ||
if (typeof value !== "string") { | ||
throw new TypeError("Class must be a string."); | ||
} | ||
this.submenuOpenClass = value; | ||
} | ||
/** | ||
* Finds the root Menu element. | ||
@@ -819,2 +981,21 @@ * | ||
*/ | ||
}, { | ||
key: "currentMenuItem", | ||
get: function get() { | ||
return this.menuItems[this.focussedChild]; | ||
} | ||
/** | ||
* A flag marking the root menu. | ||
* | ||
* @returns {boolean} - The top-level flag. | ||
*/ | ||
}, { | ||
key: "isTopLevel", | ||
get: function get() { | ||
return this.root; | ||
} | ||
}, { | ||
key: "findRootMenu", | ||
value: function findRootMenu(menu) { | ||
@@ -989,5 +1170,8 @@ if (menu.isTopLevel) { | ||
_this5.currentMenuItem.toggle.open(); | ||
_this5.currentMenuItem.toggle.open(); // This ensures the the menu is _visually_ open before the child is focussed. | ||
_this5.currentMenuItem.childMenu.focusFirstChild(); | ||
requestAnimationFrame(function () { | ||
_this5.currentMenuItem.childMenu.focusFirstChild(); | ||
}); | ||
} | ||
@@ -1000,5 +1184,8 @@ } else if (key === "ArrowUp") { | ||
_this5.currentMenuItem.toggle.open(); | ||
_this5.currentMenuItem.toggle.open(); // This ensures the the menu is _visually_ open before the child is focussed. | ||
_this5.currentMenuItem.childMenu.focusLastChild(); | ||
requestAnimationFrame(function () { | ||
_this5.currentMenuItem.childMenu.focusLastChild(); | ||
}); | ||
} | ||
@@ -1321,189 +1508,2 @@ } else if (key === "Home") { | ||
} | ||
}, { | ||
key: "element", | ||
get: function get() { | ||
return this.domElements.menu; | ||
} | ||
/** | ||
* The menu's controller element in the DOM. | ||
* | ||
* @returns {HTMLElement|null} - The controller element. | ||
*/ | ||
}, { | ||
key: "controllerElement", | ||
get: function get() { | ||
return this.domElements.controller; | ||
} | ||
/** | ||
* The menu's container element in the DOM. | ||
* | ||
* @returns {HTMLElement|null} - The container element. | ||
*/ | ||
}, { | ||
key: "containerElement", | ||
get: function get() { | ||
return this.domElements.container; | ||
} | ||
/** | ||
* The menu item DOM elements contained in the menu. | ||
* | ||
* @returns {HTMLElement[]} - The menu items. | ||
*/ | ||
}, { | ||
key: "menuItemElements", | ||
get: function get() { | ||
return this.domElements.menuItems; | ||
} | ||
/** | ||
* The submenu item DOM elements contained in the menu. | ||
* | ||
* @returns {HTMLElement[]} - The submenu items. | ||
*/ | ||
}, { | ||
key: "submenuItemElements", | ||
get: function get() { | ||
return this.domElements.submenuItems; | ||
} | ||
/** | ||
* The menu items contained in the menu. | ||
* | ||
* @returns {MenuItem[]} - The menu items. | ||
*/ | ||
}, { | ||
key: "menuItems", | ||
get: function get() { | ||
return this.elements.menuItems; | ||
} | ||
/** | ||
* The menu toggles contained in the menu. | ||
* | ||
* @returns {MenuToggle[]} - The menu toggles. | ||
*/ | ||
}, { | ||
key: "menuToggles", | ||
get: function get() { | ||
return this.elements.menuToggles; | ||
} | ||
/** | ||
* The parent menu containing this menu. | ||
* | ||
* @returns {Menu|null} - The parent menu. | ||
*/ | ||
}, { | ||
key: "parentMenu", | ||
get: function get() { | ||
return this.elements.parentMenu; | ||
} | ||
/** | ||
* The root menu containing this menu. | ||
* | ||
* @returns {Menu|null} - The root menu. | ||
*/ | ||
}, { | ||
key: "rootMenu", | ||
get: function get() { | ||
return this.elements.rootMenu; | ||
} | ||
/** | ||
* The menu's controller toggle. | ||
* | ||
* @returns {MenuToggle} - The toggle. | ||
*/ | ||
}, { | ||
key: "controller", | ||
get: function get() { | ||
return this.elements.controller; | ||
} | ||
/** | ||
* The DOM Selectors for the menu. | ||
* | ||
* @returns {object} - The DOM Selectors. | ||
*/ | ||
}, { | ||
key: "selector", | ||
get: function get() { | ||
return this.domSelectors; | ||
} | ||
/** | ||
* The focus state of the menu. | ||
* | ||
* @returns {string} - The focus state (self, child, none). | ||
*/ | ||
}, { | ||
key: "currentFocus", | ||
get: function get() { | ||
return this.focusState; | ||
} | ||
/** | ||
* The class used for open submenus. | ||
* | ||
* @returns {string} - The open class. | ||
*/ | ||
, | ||
/** | ||
* Set the focus state of the menu. | ||
* | ||
* @param {string} value - The focus state (self, child, none). | ||
*/ | ||
set: function set(value) { | ||
var states = ["self", "child", "none"]; | ||
if (!states.includes(value)) { | ||
throw new Error("Focus state must be 'self', 'child', or 'none'."); | ||
} | ||
this.focusState = value; | ||
} | ||
/** | ||
* Set the class used for open submenus. | ||
* | ||
* @param {string} value - The open class. | ||
*/ | ||
}, { | ||
key: "openClass", | ||
get: function get() { | ||
return this.submenuOpenClass; | ||
} | ||
/** | ||
* The currently focussed menu item. | ||
* | ||
* @returns {MenuItem} - The menu item. | ||
*/ | ||
, | ||
set: function set(value) { | ||
if (typeof value !== "string") { | ||
throw new TypeError("Class must be a string."); | ||
} | ||
this.submenuOpenClass = value; | ||
} | ||
}, { | ||
key: "currentMenuItem", | ||
get: function get() { | ||
return this.menuItems[this.focussedChild]; | ||
} | ||
/** | ||
* A flag marking the root menu. | ||
* | ||
* @returns {boolean} - The top-level flag. | ||
*/ | ||
}, { | ||
key: "isTopLevel", | ||
get: function get() { | ||
return this.root; | ||
} | ||
}]); | ||
@@ -1510,0 +1510,0 @@ |
@@ -1,1 +0,1 @@ | ||
"use strict";function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function _defineProperties(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function _createClass(e,t,n){return t&&_defineProperties(e.prototype,t),n&&_defineProperties(e,n),e}var AccessibleMenu=function(){var e={event:function(e){if(!(e instanceof Event))throw new TypeError("event must be an event.")},keyboardEvent:function(e){if(!(e instanceof KeyboardEvent))throw new TypeError("event must be a keyboard event.")}};function t(t){e.event(t),t.preventDefault(),t.stopPropagation()}var n={menuToggleElement:function(e){if(!(e instanceof HTMLElement))throw new TypeError("menuToggleElement must be an HTML Element.")},parentElement:function(e){if(!(e instanceof HTMLElement))throw new TypeError("parentElement must be an HTML Element.")},menu:function(e){if(!(e instanceof i))throw new TypeError("menu must be a Menu.")},openClass:function(e){if("string"!=typeof e)throw TypeError("openClass must be a string.");if(e.replace(/[_a-zA-Z0-9-]/g,"").length>0)throw Error("openClass must be a valid CSS class.")},parentMenu:function(e){if(null!==e&&!(e instanceof i))throw new TypeError("parentMenu must be a Menu.")}},r=function(){function e(t){var r=t.menuToggleElement,u=t.parentElement,s=t.menu,o=t.openClass,i=void 0===o?"show":o,l=t.parentMenu,c=void 0===l?null:l;_classCallCheck(this,e),n.menuToggleElement(r),n.parentElement(u),n.menu(s),n.openClass(i),n.parentMenu(c),this.domElements={toggle:r,parent:u},this.elements={menu:s,parentMenu:c},this.openClass=i,this.show=!1,this.initialize()}return _createClass(e,[{key:"initialize",value:function(){if(this.element.setAttribute("aria-haspopup","true"),this.element.setAttribute("aria-expanded","false"),this.element.setAttribute("role","button"),""===this.element.id||""===this.menu.element.id){var e=Math.random().toString(36).replace(/[^a-z]+/g,"").substr(0,10),t="".concat(this.element.innerText.toLowerCase().replace(/[^a-zA-Z0-9\s]/g,"").replace(/\s/g,"-"),"-").concat(e);this.element.id=this.element.id||"".concat(t,"-menu-button"),this.menu.element.id=this.menu.element.id||"".concat(t,"-menu")}this.menu.element.setAttribute("aria-labelledby",this.element.id),this.element.setAttribute("aria-controls",this.menu.element.id),this.handleClick()}},{key:"expand",value:function(){this.element.setAttribute("aria-expanded","true"),this.parentElement.classList.add(this.openClass),this.menu.element.classList.add(this.openClass)}},{key:"open",value:function(){this.isOpen=!0,this.expand(),this.closeSiblings(),this.parentMenu&&(this.parentMenu.currentFocus="child"),this.menu.currentFocus="self",this.menu.focusFirstChild()}},{key:"preview",value:function(){this.isOpen=!0,this.expand(),this.closeSiblings(),this.parentMenu&&(this.parentMenu.currentFocus="self",this.parentMenu.focusCurrentChild()),this.menu.currentFocus="none"}},{key:"close",value:function(){this.isOpen&&(this.isOpen=!1,this.element.setAttribute("aria-expanded","false"),this.parentElement.classList.remove(this.openClass),this.menu.element.classList.remove(this.openClass),this.menu.focusFirstChild(),this.closeChildren(),this.menu.blur(),this.parentMenu?(this.parentMenu.currentFocus="self",this.parentMenu.focusCurrentChild()):this.menu.isTopLevel&&this.menu.focusController())}},{key:"toggle",value:function(){this.isOpen?this.close():this.open()}},{key:"closeSiblings",value:function(){var e=this;try{this.parentMenu.menuToggles.forEach((function(t){t!==e&&t.close()}))}catch(e){}}},{key:"closeChildren",value:function(){this.menu.menuToggles.forEach((function(e){return e.close()}))}},{key:"handleClick",value:function(){var e=this;this.element.addEventListener("click",(function(n){t(n),e.toggle()}))}},{key:"element",get:function(){return this.domElements.toggle}},{key:"parentElement",get:function(){return this.domElements.parent}},{key:"menu",get:function(){return this.elements.menu}},{key:"parentMenu",get:function(){return this.elements.parentMenu}},{key:"isOpen",get:function(){return this.show},set:function(e){if("boolean"!=typeof e)throw new TypeError("Open state must be true or false.");this.show=e}}]),e}(),u={menuItemElement:function(e){if(!(e instanceof HTMLElement))throw new TypeError("menuItemElement must be an HTML Element.")},menuLinkElement:function(e){if(!(e instanceof HTMLElement))throw new TypeError("menuLinkElement must be an HTML Element.")},parentMenu:function(e){if(!(e instanceof i))throw new TypeError("parentMenu must be a Menu.")},isSubmenuItem:function(e){if("boolean"!=typeof e)throw new TypeError("isSubmenuItem must be true or false")},childMenu:function(e){if(null!==e&&!(e instanceof i))throw new TypeError("childMenu must be a Menu.")},toggle:function(e){if(null!==e&&!(e instanceof r))throw new TypeError("toggle must be a MenuToggle.")}},s=function(){function e(t){var n=t.menuItemElement,r=t.menuLinkElement,s=t.parentMenu,o=t.isSubmenuItem,i=void 0!==o&&o,l=t.childMenu,c=void 0===l?null:l,m=t.toggle,a=void 0===m?null:m;_classCallCheck(this,e),u.menuItemElement(n),u.menuLinkElement(r),u.parentMenu(s),u.isSubmenuItem(i),u.childMenu(c),u.toggle(a),this.domElements={menuItem:n,link:r},this.elements={parentMenu:s,childMenu:c,toggle:a},this.isController=i,this.initialize()}return _createClass(e,[{key:"initialize",value:function(){this.element.setAttribute("role","none"),this.linkElement.setAttribute("role","menuitem"),this.linkElement.tabIndex=-1}},{key:"focus",value:function(){this.linkElement.focus(),this.parentMenu.isTopLevel&&(this.linkElement.tabIndex=0)}},{key:"blur",value:function(){this.linkElement.blur(),this.parentMenu.isTopLevel&&(this.linkElement.tabIndex=-1)}},{key:"element",get:function(){return this.domElements.menuItem}},{key:"linkElement",get:function(){return this.domElements.link}},{key:"parentMenu",get:function(){return this.elements.parentMenu}},{key:"childMenu",get:function(){return this.elements.childMenu}},{key:"toggle",get:function(){return this.elements.toggle}},{key:"isSubmenuItem",get:function(){return this.isController}}]),e}(),o={menuElement:function(e){if(!(e instanceof HTMLElement))throw new TypeError("menuElement must be an HTML Element.")},menuItemSelector:function(e){if("string"!=typeof e)throw new TypeError("menuItemSelector must be a CSS selector string.")},hasSubmenus:function(e,t,n){if(null!==e||null!==t||null!==n){if("string"!=typeof e)throw new TypeError("submenuItemSelector must be a CSS selector string.");if("string"!=typeof e)throw new TypeError("submenuToggleSelector must be a CSS selector string.");if("string"!=typeof n)throw new TypeError("submenuSelector must be a CSS selector string.")}},openClass:function(e){if("string"!=typeof e)throw TypeError("openClass must be a string.");if(e.replace(/[_a-zA-Z0-9-]/g,"").length>0)throw Error("openClass must be a valid CSS class.")},isTopLevel:function(e){if("boolean"!=typeof e)throw new TypeError("isTopLevel must be true of false.")},isDropdown:function(e,t){if(null!==e||null!==t){if(!(e instanceof HTMLElement))throw new TypeError("controllerElement must be an HTML Element if containerElement is provided.");if(!(t instanceof HTMLElement))throw new TypeError("containerElement must be an HTML Element if controllerElement is provided.")}},parentMenu:function(e){if(null!==e&&!(e instanceof i))throw new TypeError("parentMenu must be a Menu.")}},i=function(){function n(e){var t=e.menuElement,r=e.menuItemSelector,u=e.submenuItemSelector,s=void 0===u?null:u,i=e.submenuToggleSelector,l=void 0===i?null:i,c=e.submenuSelector,m=void 0===c?null:c,a=e.openClass,h=void 0===a?"show":a,f=e.isTopLevel,d=void 0===f||f,p=e.controllerElement,E=void 0===p?null:p,g=e.containerElement,C=void 0===g?null:g,b=e.parentMenu,M=void 0===b?null:b;_classCallCheck(this,n),o.menuElement(t),o.menuItemSelector(r),o.hasSubmenus(s,l,m),o.openClass(h),o.isTopLevel(d),o.isDropdown(E,C),o.parentMenu(M),this.domElements={menu:t,controller:E,container:C,menuItems:Array.from(t.querySelectorAll(r)).filter((function(e){return e.parentElement===t})),submenuItems:Array.from(t.querySelectorAll(s)).filter((function(e){return e.parentElement===t}))},this.domSelectors={"menu-items":r,"submenu-items":s,"submenu-toggle":l,submenu:m},this.elements={menuItems:[],menuToggles:[],controller:null,parentMenu:M,rootMenu:d?this:null},this.focussedChild=0,this.focusState="none",this.openClass=h,this.root=d,this.initialize()}return _createClass(n,[{key:"initialize",value:function(){if(this.element.setAttribute("role","menubar"),null===this.rootMenu&&this.findRootMenu(this),this.createMenuItems(),this.handleKeydown(),this.handleClick(),this.isTopLevel&&(this.currentMenuItem.linkElement.tabIndex=0,this.handleFocus(),this.controllerElement&&this.containerElement)){var e=new r({menuToggleElement:this.controllerElement,parentElement:this.containerElement,menu:this,openClass:this.openClass});this.elements.controller=e}}},{key:"findRootMenu",value:function(e){if(e.isTopLevel)this.elements.rootMenu=e;else{if(null===e.parentMenu)throw new Error("Cannot find root menu.");this.findRootMenu(e.parentMenu)}}},{key:"createMenuItems",value:function(){var e=this;this.menuItemElements.forEach((function(t){var u;if(e.submenuItemElements.includes(t)){var o=t.querySelector(e.selector["submenu-toggle"]),i=new n({menuElement:t.querySelector(e.selector.submenu),menuItemSelector:e.selector["menu-items"],submenuItemSelector:e.selector["submenu-items"],submenuToggleSelector:e.selector["submenu-toggle"],submenuSelector:e.selector.submenu,openClass:e.openClass,isTopLevel:!1,parentMenu:e}),l=new r({menuToggleElement:o,parentElement:t,menu:i,openClass:e.openClass,parentMenu:e});e.elements.menuToggles.push(l),u=new s({menuItemElement:t,menuLinkElement:o,parentMenu:e,isSubmenuItem:!0,childMenu:i,toggle:l})}else{var c=t.querySelector("a");u=new s({menuItemElement:t,menuLinkElement:c,parentMenu:e})}e.elements.menuItems.push(u)}))}},{key:"handleFocus",value:function(){var e=this;this.menuItems.forEach((function(t){t.linkElement.addEventListener("focusin",(function(){"none"===e.currentFocus&&(e.currentFocus="self",e.focusCurrentChild())})),t.linkElement.addEventListener("focusout",(function(){"none"===e.currentFocus&&(e.blur(),e.closeChildren())}))}))}},{key:"handleKeydown",value:function(){var n=this;this.element.addEventListener("keydown",(function(r){var u=function(t){e.keyboardEvent(t);try{var n=t.key||t.keyCode,r={Enter:"Enter"===n||13===n,Space:" "===n||"Spacebar"===n||32===n,Escape:"Escape"===n||"Esc"===n||27===n,ArrowUp:"ArrowUp"===n||"Up"===n||38===n,ArrowRight:"ArrowRight"===n||"Right"===n||39===n,ArrowDown:"ArrowDown"===n||"Down"===n||40===n,ArrowLeft:"ArrowLeft"===n||"Left"===n||37===n,Home:"Home"===n||36===n,End:"End"===n||35===n,Character:!!n.match(/^[a-zA-Z]{1}$/),Tab:"Tab"===n||9===n};return Object.keys(r).find((function(e){return!0===r[e]}))}catch(e){return""}}(r),s=r.altKey,o=r.crtlKey,i=r.metaKey,l=s||o||i;if(n.isTopLevel){if("none"===n.currentFocus)"Space"!==u&&"Enter"!==u||(t(r),n.currentFocus="self",n.focusFirstChild());else if("self"===n.currentFocus)if("ArrowRight"===u){t(r);var c=n.currentMenuItem.isSubmenuItem&&n.currentMenuItem.toggle.isOpen;n.focusNextChild(),c&&(n.currentMenuItem.isSubmenuItem?n.currentMenuItem.toggle.preview():n.closeChildren())}else if("ArrowLeft"===u){t(r);var m=n.currentMenuItem.isSubmenuItem&&n.currentMenuItem.toggle.isOpen;n.focusPreviousChild(),m&&(n.currentMenuItem.isSubmenuItem?n.currentMenuItem.toggle.preview():n.closeChildren())}else"ArrowDown"===u?n.currentMenuItem.isSubmenuItem&&(t(r),n.currentMenuItem.toggle.open(),n.currentMenuItem.childMenu.focusFirstChild()):"ArrowUp"===u?n.currentMenuItem.isSubmenuItem&&(t(r),n.currentMenuItem.toggle.open(),n.currentMenuItem.childMenu.focusLastChild()):"Home"===u?(t(r),n.focusFirstChild()):"End"===u?(t(r),n.focusLastChild()):"Escape"===u&&null!==n.controller&&n.controller.close()}else"Space"===u||"Enter"===u?(t(r),n.currentMenuItem.linkElement.click()):"Escape"===u?(t(r),n.rootMenu.closeChildren(),n.rootMenu.focusCurrentChild()):"ArrowRight"===u?n.currentMenuItem.isSubmenuItem?(t(r),n.currentMenuItem.toggle.open()):(t(r),n.rootMenu.closeChildren(),n.rootMenu.focusNextChild(),n.rootMenu.currentMenuItem.isSubmenuItem&&n.rootMenu.currentMenuItem.toggle.preview()):"ArrowLeft"===u?n.parentMenu.currentMenuItem.isSubmenuItem&&(t(r),n.parentMenu.currentMenuItem.toggle.close(),n.parentMenu===n.rootMenu&&(n.rootMenu.closeChildren(),n.rootMenu.focusPreviousChild(),n.rootMenu.currentMenuItem.isSubmenuItem&&n.rootMenu.currentMenuItem.toggle.preview())):"ArrowDown"===u?(t(r),n.focusNextChild()):"ArrowUp"===u?(t(r),n.focusPreviousChild()):"Home"===u?(t(r),n.focusFirstChild()):"End"===u&&(t(r),n.focusLastChild());"Character"!==u||l||(t(r),n.focusNextChildWithCharacter(r.key)),"none"!==n.currentFocus&&"Tab"===u&&(n.rootMenu.blur(),n.rootMenu.closeChildren())}))}},{key:"handleClick",value:function(){var e=this;document.addEventListener("click",(function(t){e.element.contains(t.target)||e.element===t.target||(e.blur(),e.closeChildren(),e.controller&&e.controller.close())})),this.menuItems.forEach((function(t){t.linkElement.addEventListener("click",(function(){e.focussedChild=e.menuItems.indexOf(t)}))}))}},{key:"focus",value:function(){this.currentFocus="self",this.element.focus()}},{key:"blur",value:function(){this.currentFocus="none",this.element.blur(),this.isTopLevel&&this.controller&&this.controller.close()}},{key:"focusFirstChild",value:function(){this.blurCurrentChild(),this.focussedChild=0,this.focusCurrentChild()}},{key:"focusLastChild",value:function(){this.blurCurrentChild(),this.focussedChild=this.menuItems.length-1,this.focusCurrentChild()}},{key:"focusNextChild",value:function(){this.focussedChild===this.menuItems.length-1?this.focusFirstChild():(this.blurCurrentChild(),this.focussedChild=this.focussedChild+1,this.focusCurrentChild())}},{key:"focusPreviousChild",value:function(){0===this.focussedChild?this.focusLastChild():(this.blurCurrentChild(),this.focussedChild=this.focussedChild-1,this.focusCurrentChild())}},{key:"focusCurrentChild",value:function(){-1!==this.focussedChild&&this.currentMenuItem.focus()}},{key:"blurCurrentChild",value:function(){-1!==this.focussedChild&&this.currentMenuItem.blur()}},{key:"focusNextChildWithCharacter",value:function(e){for(var t=e.toLowerCase(),n=this.focussedChild+1,r=!1;!r&&n<this.menuItems.length;){this.menuItems[n].element.innerText.toLowerCase().startsWith(t)&&(r=!0,this.focussedChild=n,this.focusCurrentChild()),n++}}},{key:"focusController",value:function(){this.controllerElement&&(this.controllerElement.focus(),this.currentFocus="none")}},{key:"focusContainer",value:function(){this.containerElement&&(this.containerElement.focus(),this.currentFocus="none")}},{key:"closeChildren",value:function(){this.menuToggles.forEach((function(e){return e.close()}))}},{key:"element",get:function(){return this.domElements.menu}},{key:"controllerElement",get:function(){return this.domElements.controller}},{key:"containerElement",get:function(){return this.domElements.container}},{key:"menuItemElements",get:function(){return this.domElements.menuItems}},{key:"submenuItemElements",get:function(){return this.domElements.submenuItems}},{key:"menuItems",get:function(){return this.elements.menuItems}},{key:"menuToggles",get:function(){return this.elements.menuToggles}},{key:"parentMenu",get:function(){return this.elements.parentMenu}},{key:"rootMenu",get:function(){return this.elements.rootMenu}},{key:"controller",get:function(){return this.elements.controller}},{key:"selector",get:function(){return this.domSelectors}},{key:"currentFocus",get:function(){return this.focusState},set:function(e){if(!["self","child","none"].includes(e))throw new Error("Focus state must be 'self', 'child', or 'none'.");this.focusState=e}},{key:"openClass",get:function(){return this.submenuOpenClass},set:function(e){if("string"!=typeof e)throw new TypeError("Class must be a string.");this.submenuOpenClass=e}},{key:"currentMenuItem",get:function(){return this.menuItems[this.focussedChild]}},{key:"isTopLevel",get:function(){return this.root}}]),n}();return i}(); | ||
"use strict";function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function _defineProperties(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function _createClass(e,t,n){return t&&_defineProperties(e.prototype,t),n&&_defineProperties(e,n),e}var AccessibleMenu=function(){var e=function(e){if(!(e instanceof Event))throw new TypeError("event must be an event.")},t=function(e){if(!(e instanceof KeyboardEvent))throw new TypeError("event must be a keyboard event.")};function n(t){e(t),t.preventDefault(),t.stopPropagation()}var r=function(e){if(!(e instanceof HTMLElement))throw new TypeError("menuToggleElement must be an HTML Element.")},s=function(e){if(!(e instanceof HTMLElement))throw new TypeError("parentElement must be an HTML Element.")},u=function(e){if(!(e instanceof w))throw new TypeError("menu must be a Menu.")},i=function(e){if("string"!=typeof e)throw TypeError("openClass must be a string.");if(e.replace(/[_a-zA-Z0-9-]/g,"").length>0)throw Error("openClass must be a valid CSS class.")},o=function(e){if(null!==e&&!(e instanceof w))throw new TypeError("parentMenu must be a Menu.")},l=function(){function e(t){var n=t.menuToggleElement,l=t.parentElement,c=t.menu,m=t.openClass,a=void 0===m?"show":m,h=t.parentMenu,f=void 0===h?null:h;_classCallCheck(this,e),r(n),s(l),u(c),i(a),o(f),this.domElements={toggle:n,parent:l},this.elements={menu:c,parentMenu:f},this.openClass=a,this.show=!1,this.initialize()}return _createClass(e,[{key:"initialize",value:function(){if(this.element.setAttribute("aria-haspopup","true"),this.element.setAttribute("aria-expanded","false"),this.element.setAttribute("role","button"),""===this.element.id||""===this.menu.element.id){var e=Math.random().toString(36).replace(/[^a-z]+/g,"").substr(0,10),t="".concat(this.element.innerText.toLowerCase().replace(/[^a-zA-Z0-9\s]/g,"").replace(/\s/g,"-"),"-").concat(e);this.element.id=this.element.id||"".concat(t,"-menu-button"),this.menu.element.id=this.menu.element.id||"".concat(t,"-menu")}this.menu.element.setAttribute("aria-labelledby",this.element.id),this.element.setAttribute("aria-controls",this.menu.element.id),this.handleClick()}},{key:"element",get:function(){return this.domElements.toggle}},{key:"parentElement",get:function(){return this.domElements.parent}},{key:"menu",get:function(){return this.elements.menu}},{key:"parentMenu",get:function(){return this.elements.parentMenu}},{key:"isOpen",get:function(){return this.show},set:function(e){if("boolean"!=typeof e)throw new TypeError("Open state must be true or false.");this.show=e}},{key:"expand",value:function(){this.element.setAttribute("aria-expanded","true"),this.parentElement.classList.add(this.openClass),this.menu.element.classList.add(this.openClass)}},{key:"open",value:function(){this.isOpen=!0,this.expand(),this.closeSiblings(),this.parentMenu&&(this.parentMenu.currentFocus="child"),this.menu.currentFocus="self",this.menu.focusFirstChild()}},{key:"preview",value:function(){this.isOpen=!0,this.expand(),this.closeSiblings(),this.parentMenu&&(this.parentMenu.currentFocus="self",this.parentMenu.focusCurrentChild()),this.menu.currentFocus="none"}},{key:"close",value:function(){this.isOpen&&(this.isOpen=!1,this.element.setAttribute("aria-expanded","false"),this.parentElement.classList.remove(this.openClass),this.menu.element.classList.remove(this.openClass),this.menu.focusFirstChild(),this.closeChildren(),this.menu.blur(),this.parentMenu?(this.parentMenu.currentFocus="self",this.parentMenu.focusCurrentChild()):this.menu.isTopLevel&&this.menu.focusController())}},{key:"toggle",value:function(){this.isOpen?this.close():this.open()}},{key:"closeSiblings",value:function(){var e=this;try{this.parentMenu.menuToggles.forEach((function(t){t!==e&&t.close()}))}catch(e){}}},{key:"closeChildren",value:function(){this.menu.menuToggles.forEach((function(e){return e.close()}))}},{key:"handleClick",value:function(){var e=this;this.element.addEventListener("click",(function(t){n(t),e.toggle()}))}}]),e}(),c=function(e){if(!(e instanceof HTMLElement))throw new TypeError("menuItemElement must be an HTML Element.")},m=function(e){if(!(e instanceof HTMLElement))throw new TypeError("menuLinkElement must be an HTML Element.")},a=function(e){if(!(e instanceof w))throw new TypeError("parentMenu must be a Menu.")},h=function(e){if("boolean"!=typeof e)throw new TypeError("isSubmenuItem must be true or false")},f=function(e){if(null!==e&&!(e instanceof w))throw new TypeError("childMenu must be a Menu.")},d=function(e){if(null!==e&&!(e instanceof l))throw new TypeError("toggle must be a MenuToggle.")},p=function(){function e(t){var n=t.menuItemElement,r=t.menuLinkElement,s=t.parentMenu,u=t.isSubmenuItem,i=void 0!==u&&u,o=t.childMenu,l=void 0===o?null:o,p=t.toggle,g=void 0===p?null:p;_classCallCheck(this,e),c(n),m(r),a(s),h(i),f(l),d(g),this.domElements={menuItem:n,link:r},this.elements={parentMenu:s,childMenu:l,toggle:g},this.isController=i,this.initialize()}return _createClass(e,[{key:"initialize",value:function(){this.element.setAttribute("role","none"),this.linkElement.setAttribute("role","menuitem"),this.linkElement.tabIndex=-1}},{key:"element",get:function(){return this.domElements.menuItem}},{key:"linkElement",get:function(){return this.domElements.link}},{key:"parentMenu",get:function(){return this.elements.parentMenu}},{key:"childMenu",get:function(){return this.elements.childMenu}},{key:"toggle",get:function(){return this.elements.toggle}},{key:"isSubmenuItem",get:function(){return this.isController}},{key:"focus",value:function(){this.linkElement.focus(),this.parentMenu.isTopLevel&&(this.linkElement.tabIndex=0)}},{key:"blur",value:function(){this.linkElement.blur(),this.parentMenu.isTopLevel&&(this.linkElement.tabIndex=-1)}}]),e}(),g=function(e){if(!(e instanceof HTMLElement))throw new TypeError("menuElement must be an HTML Element.")},E=function(e){if("string"!=typeof e)throw new TypeError("menuItemSelector must be a CSS selector string.")},C=function(e,t,n){if(null!==e||null!==t||null!==n){if("string"!=typeof e)throw new TypeError("submenuItemSelector must be a CSS selector string.");if("string"!=typeof e)throw new TypeError("submenuToggleSelector must be a CSS selector string.");if("string"!=typeof n)throw new TypeError("submenuSelector must be a CSS selector string.")}},b=function(e){if("string"!=typeof e)throw TypeError("openClass must be a string.");if(e.replace(/[_a-zA-Z0-9-]/g,"").length>0)throw Error("openClass must be a valid CSS class.")},y=function(e){if("boolean"!=typeof e)throw new TypeError("isTopLevel must be true of false.")},M=function(e,t){if(null!==e||null!==t){if(!(e instanceof HTMLElement))throw new TypeError("controllerElement must be an HTML Element if containerElement is provided.");if(!(t instanceof HTMLElement))throw new TypeError("containerElement must be an HTML Element if controllerElement is provided.")}},v=function(e){if(null!==e&&!(e instanceof w))throw new TypeError("parentMenu must be a Menu.")},w=function(){function e(t){var n=t.menuElement,r=t.menuItemSelector,s=t.submenuItemSelector,u=void 0===s?null:s,i=t.submenuToggleSelector,o=void 0===i?null:i,l=t.submenuSelector,c=void 0===l?null:l,m=t.openClass,a=void 0===m?"show":m,h=t.isTopLevel,f=void 0===h||h,d=t.controllerElement,p=void 0===d?null:d,w=t.containerElement,k=void 0===w?null:w,I=t.parentMenu,T=void 0===I?null:I;_classCallCheck(this,e),g(n),E(r),C(u,o,c),b(a),y(f),M(p,k),v(T),this.domElements={menu:n,controller:p,container:k,menuItems:Array.from(n.querySelectorAll(r)).filter((function(e){return e.parentElement===n})),submenuItems:Array.from(n.querySelectorAll(u)).filter((function(e){return e.parentElement===n}))},this.domSelectors={"menu-items":r,"submenu-items":u,"submenu-toggle":o,submenu:c},this.elements={menuItems:[],menuToggles:[],controller:null,parentMenu:T,rootMenu:f?this:null},this.focussedChild=0,this.focusState="none",this.openClass=a,this.root=f,this.initialize()}return _createClass(e,[{key:"initialize",value:function(){if(this.element.setAttribute("role","menubar"),null===this.rootMenu&&this.findRootMenu(this),this.createMenuItems(),this.handleKeydown(),this.handleClick(),this.isTopLevel&&(this.currentMenuItem.linkElement.tabIndex=0,this.handleFocus(),this.controllerElement&&this.containerElement)){var e=new l({menuToggleElement:this.controllerElement,parentElement:this.containerElement,menu:this,openClass:this.openClass});this.elements.controller=e}}},{key:"element",get:function(){return this.domElements.menu}},{key:"controllerElement",get:function(){return this.domElements.controller}},{key:"containerElement",get:function(){return this.domElements.container}},{key:"menuItemElements",get:function(){return this.domElements.menuItems}},{key:"submenuItemElements",get:function(){return this.domElements.submenuItems}},{key:"menuItems",get:function(){return this.elements.menuItems}},{key:"menuToggles",get:function(){return this.elements.menuToggles}},{key:"parentMenu",get:function(){return this.elements.parentMenu}},{key:"rootMenu",get:function(){return this.elements.rootMenu}},{key:"controller",get:function(){return this.elements.controller}},{key:"selector",get:function(){return this.domSelectors}},{key:"currentFocus",get:function(){return this.focusState},set:function(e){if(!["self","child","none"].includes(e))throw new Error("Focus state must be 'self', 'child', or 'none'.");this.focusState=e}},{key:"openClass",get:function(){return this.submenuOpenClass},set:function(e){if("string"!=typeof e)throw new TypeError("Class must be a string.");this.submenuOpenClass=e}},{key:"currentMenuItem",get:function(){return this.menuItems[this.focussedChild]}},{key:"isTopLevel",get:function(){return this.root}},{key:"findRootMenu",value:function(e){if(e.isTopLevel)this.elements.rootMenu=e;else{if(null===e.parentMenu)throw new Error("Cannot find root menu.");this.findRootMenu(e.parentMenu)}}},{key:"createMenuItems",value:function(){var t=this;this.menuItemElements.forEach((function(n){var r;if(t.submenuItemElements.includes(n)){var s=n.querySelector(t.selector["submenu-toggle"]),u=new e({menuElement:n.querySelector(t.selector.submenu),menuItemSelector:t.selector["menu-items"],submenuItemSelector:t.selector["submenu-items"],submenuToggleSelector:t.selector["submenu-toggle"],submenuSelector:t.selector.submenu,openClass:t.openClass,isTopLevel:!1,parentMenu:t}),i=new l({menuToggleElement:s,parentElement:n,menu:u,openClass:t.openClass,parentMenu:t});t.elements.menuToggles.push(i),r=new p({menuItemElement:n,menuLinkElement:s,parentMenu:t,isSubmenuItem:!0,childMenu:u,toggle:i})}else{var o=n.querySelector("a");r=new p({menuItemElement:n,menuLinkElement:o,parentMenu:t})}t.elements.menuItems.push(r)}))}},{key:"handleFocus",value:function(){var e=this;this.menuItems.forEach((function(t){t.linkElement.addEventListener("focusin",(function(){"none"===e.currentFocus&&(e.currentFocus="self",e.focusCurrentChild())})),t.linkElement.addEventListener("focusout",(function(){"none"===e.currentFocus&&(e.blur(),e.closeChildren())}))}))}},{key:"handleKeydown",value:function(){var e=this;this.element.addEventListener("keydown",(function(r){var s=function(e){t(e);try{var n=e.key||e.keyCode,r={Enter:"Enter"===n||13===n,Space:" "===n||"Spacebar"===n||32===n,Escape:"Escape"===n||"Esc"===n||27===n,ArrowUp:"ArrowUp"===n||"Up"===n||38===n,ArrowRight:"ArrowRight"===n||"Right"===n||39===n,ArrowDown:"ArrowDown"===n||"Down"===n||40===n,ArrowLeft:"ArrowLeft"===n||"Left"===n||37===n,Home:"Home"===n||36===n,End:"End"===n||35===n,Character:!!n.match(/^[a-zA-Z]{1}$/),Tab:"Tab"===n||9===n};return Object.keys(r).find((function(e){return!0===r[e]}))}catch(e){return""}}(r),u=r.altKey,i=r.crtlKey,o=r.metaKey,l=u||i||o;if(e.isTopLevel){if("none"===e.currentFocus)"Space"!==s&&"Enter"!==s||(n(r),e.currentFocus="self",e.focusFirstChild());else if("self"===e.currentFocus)if("ArrowRight"===s){n(r);var c=e.currentMenuItem.isSubmenuItem&&e.currentMenuItem.toggle.isOpen;e.focusNextChild(),c&&(e.currentMenuItem.isSubmenuItem?e.currentMenuItem.toggle.preview():e.closeChildren())}else if("ArrowLeft"===s){n(r);var m=e.currentMenuItem.isSubmenuItem&&e.currentMenuItem.toggle.isOpen;e.focusPreviousChild(),m&&(e.currentMenuItem.isSubmenuItem?e.currentMenuItem.toggle.preview():e.closeChildren())}else"ArrowDown"===s?e.currentMenuItem.isSubmenuItem&&(n(r),e.currentMenuItem.toggle.open(),requestAnimationFrame((function(){e.currentMenuItem.childMenu.focusFirstChild()}))):"ArrowUp"===s?e.currentMenuItem.isSubmenuItem&&(n(r),e.currentMenuItem.toggle.open(),requestAnimationFrame((function(){e.currentMenuItem.childMenu.focusLastChild()}))):"Home"===s?(n(r),e.focusFirstChild()):"End"===s?(n(r),e.focusLastChild()):"Escape"===s&&null!==e.controller&&e.controller.close()}else"Space"===s||"Enter"===s?(n(r),e.currentMenuItem.linkElement.click()):"Escape"===s?(n(r),e.rootMenu.closeChildren(),e.rootMenu.focusCurrentChild()):"ArrowRight"===s?e.currentMenuItem.isSubmenuItem?(n(r),e.currentMenuItem.toggle.open()):(n(r),e.rootMenu.closeChildren(),e.rootMenu.focusNextChild(),e.rootMenu.currentMenuItem.isSubmenuItem&&e.rootMenu.currentMenuItem.toggle.preview()):"ArrowLeft"===s?e.parentMenu.currentMenuItem.isSubmenuItem&&(n(r),e.parentMenu.currentMenuItem.toggle.close(),e.parentMenu===e.rootMenu&&(e.rootMenu.closeChildren(),e.rootMenu.focusPreviousChild(),e.rootMenu.currentMenuItem.isSubmenuItem&&e.rootMenu.currentMenuItem.toggle.preview())):"ArrowDown"===s?(n(r),e.focusNextChild()):"ArrowUp"===s?(n(r),e.focusPreviousChild()):"Home"===s?(n(r),e.focusFirstChild()):"End"===s&&(n(r),e.focusLastChild());"Character"!==s||l||(n(r),e.focusNextChildWithCharacter(r.key)),"none"!==e.currentFocus&&"Tab"===s&&(e.rootMenu.blur(),e.rootMenu.closeChildren())}))}},{key:"handleClick",value:function(){var e=this;document.addEventListener("click",(function(t){e.element.contains(t.target)||e.element===t.target||(e.blur(),e.closeChildren(),e.controller&&e.controller.close())})),this.menuItems.forEach((function(t){t.linkElement.addEventListener("click",(function(){e.focussedChild=e.menuItems.indexOf(t)}))}))}},{key:"focus",value:function(){this.currentFocus="self",this.element.focus()}},{key:"blur",value:function(){this.currentFocus="none",this.element.blur(),this.isTopLevel&&this.controller&&this.controller.close()}},{key:"focusFirstChild",value:function(){this.blurCurrentChild(),this.focussedChild=0,this.focusCurrentChild()}},{key:"focusLastChild",value:function(){this.blurCurrentChild(),this.focussedChild=this.menuItems.length-1,this.focusCurrentChild()}},{key:"focusNextChild",value:function(){this.focussedChild===this.menuItems.length-1?this.focusFirstChild():(this.blurCurrentChild(),this.focussedChild=this.focussedChild+1,this.focusCurrentChild())}},{key:"focusPreviousChild",value:function(){0===this.focussedChild?this.focusLastChild():(this.blurCurrentChild(),this.focussedChild=this.focussedChild-1,this.focusCurrentChild())}},{key:"focusCurrentChild",value:function(){-1!==this.focussedChild&&this.currentMenuItem.focus()}},{key:"blurCurrentChild",value:function(){-1!==this.focussedChild&&this.currentMenuItem.blur()}},{key:"focusNextChildWithCharacter",value:function(e){for(var t=e.toLowerCase(),n=this.focussedChild+1,r=!1;!r&&n<this.menuItems.length;){this.menuItems[n].element.innerText.toLowerCase().startsWith(t)&&(r=!0,this.focussedChild=n,this.focusCurrentChild()),n++}}},{key:"focusController",value:function(){this.controllerElement&&(this.controllerElement.focus(),this.currentFocus="none")}},{key:"focusContainer",value:function(){this.containerElement&&(this.containerElement.focus(),this.currentFocus="none")}},{key:"closeChildren",value:function(){this.menuToggles.forEach((function(e){return e.close()}))}}]),e}();return w}(); |
{ | ||
"name": "accessible-menu", | ||
"version": "1.0.6", | ||
"version": "1.0.7", | ||
"description": "A JavaScript library to help you generate WAI-ARIA accessible menus in the DOM.", | ||
@@ -20,3 +20,4 @@ "main": "index.js", | ||
"minify": "npx terser dist/accessibleMenu.js -c -m -o dist/accessibleMenu.min.js", | ||
"build": "npm run bundle && npm run compile && npm run minify" | ||
"build": "npm run bundle && npm run compile && npm run minify", | ||
"compile:test": "npx babel test/js --out-dir test/js/ie --ignore 'test/js/ie/*.js' && npx sass test/scss:test/css" | ||
}, | ||
@@ -47,20 +48,21 @@ "repository": { | ||
"@babel/preset-env": "^7.7.4", | ||
"@commitlint/cli": "^8.2.0", | ||
"@commitlint/config-conventional": "^8.2.0", | ||
"@commitlint/cli": "^12.0.1", | ||
"@commitlint/config-conventional": "^12.0.1", | ||
"commitizen": "^4.0.3", | ||
"eslint": "^6.7.0", | ||
"eslint-config-prettier": "^6.7.0", | ||
"eslint-config-standard": "^14.1.0", | ||
"eslint": "^7.22.0", | ||
"eslint-config-prettier": "^8.1.0", | ||
"eslint-config-standard": "^16.0.2", | ||
"eslint-plugin-import": "^2.18.2", | ||
"eslint-plugin-jsdoc": "^18.1.4", | ||
"eslint-plugin-node": "^10.0.0", | ||
"eslint-plugin-jsdoc": "^32.3.0", | ||
"eslint-plugin-node": "^11.1.0", | ||
"eslint-plugin-prettier": "^3.1.1", | ||
"eslint-plugin-promise": "^4.2.1", | ||
"eslint-plugin-standard": "^4.0.1", | ||
"husky": "^3.1.0", | ||
"prettier": "^1.19.1", | ||
"rollup": "^1.27.4", | ||
"standard-version": "^7.0.1", | ||
"terser": "^4.4.0" | ||
"eslint-plugin-standard": "^5.0.0", | ||
"husky": "^4.3.8", | ||
"prettier": "^2.2.1", | ||
"rollup": "^2.42.3", | ||
"sass": "^1.29.0", | ||
"standard-version": "^9.1.1", | ||
"terser": "^5.6.1" | ||
} | ||
} |
@@ -12,3 +12,3 @@ // Custom validation for params. | ||
} | ||
} | ||
}, | ||
}; | ||
@@ -41,3 +41,3 @@ | ||
Character: !!key.match(/^[a-zA-Z]{1}$/), | ||
Tab: key === "Tab" || key === 9 | ||
Tab: key === "Tab" || key === 9, | ||
}; | ||
@@ -44,0 +44,0 @@ |
@@ -83,3 +83,3 @@ import MenuItem from "./menuItem"; | ||
} | ||
} | ||
}, | ||
}; | ||
@@ -116,3 +116,3 @@ | ||
containerElement = null, | ||
parentMenu = null | ||
parentMenu = null, | ||
}) { | ||
@@ -141,3 +141,3 @@ // Run validations. | ||
menuElement.querySelectorAll(submenuItemSelector) | ||
).filter(item => item.parentElement === menuElement) | ||
).filter(item => item.parentElement === menuElement), | ||
}; | ||
@@ -148,3 +148,3 @@ this.domSelectors = { | ||
"submenu-toggle": submenuToggleSelector, | ||
submenu: submenuSelector | ||
submenu: submenuSelector, | ||
}; | ||
@@ -156,3 +156,3 @@ this.elements = { | ||
parentMenu: parentMenu, | ||
rootMenu: isTopLevel ? this : null | ||
rootMenu: isTopLevel ? this : null, | ||
}; | ||
@@ -191,3 +191,3 @@ this.focussedChild = 0; | ||
menu: this, | ||
openClass: this.openClass | ||
openClass: this.openClass, | ||
}); | ||
@@ -400,3 +400,3 @@ | ||
isTopLevel: false, | ||
parentMenu: this | ||
parentMenu: this, | ||
}); | ||
@@ -410,3 +410,3 @@ | ||
openClass: this.openClass, | ||
parentMenu: this | ||
parentMenu: this, | ||
}); | ||
@@ -424,3 +424,3 @@ | ||
childMenu: menu, | ||
toggle | ||
toggle, | ||
}); | ||
@@ -434,3 +434,3 @@ } else { | ||
menuLinkElement: link, | ||
parentMenu: this | ||
parentMenu: this, | ||
}); | ||
@@ -535,3 +535,6 @@ } | ||
this.currentMenuItem.toggle.open(); | ||
this.currentMenuItem.childMenu.focusFirstChild(); | ||
// This ensures the the menu is _visually_ open before the child is focussed. | ||
requestAnimationFrame(() => { | ||
this.currentMenuItem.childMenu.focusFirstChild(); | ||
}); | ||
} | ||
@@ -544,3 +547,6 @@ } else if (key === "ArrowUp") { | ||
this.currentMenuItem.toggle.open(); | ||
this.currentMenuItem.childMenu.focusLastChild(); | ||
// This ensures the the menu is _visually_ open before the child is focussed. | ||
requestAnimationFrame(() => { | ||
this.currentMenuItem.childMenu.focusLastChild(); | ||
}); | ||
} | ||
@@ -547,0 +553,0 @@ } else if (key === "Home") { |
@@ -47,3 +47,3 @@ import Menu from "./menu"; | ||
} | ||
} | ||
}, | ||
}; | ||
@@ -72,3 +72,3 @@ | ||
childMenu = null, | ||
toggle = null | ||
toggle = null, | ||
}) { | ||
@@ -85,3 +85,3 @@ // Run validations. | ||
menuItem: menuItemElement, | ||
link: menuLinkElement | ||
link: menuLinkElement, | ||
}; | ||
@@ -92,3 +92,3 @@ | ||
childMenu, | ||
toggle | ||
toggle, | ||
}; | ||
@@ -95,0 +95,0 @@ |
@@ -44,3 +44,3 @@ import Menu from "./menu"; | ||
} | ||
} | ||
}, | ||
}; | ||
@@ -67,3 +67,3 @@ | ||
openClass = "show", | ||
parentMenu = null | ||
parentMenu = null, | ||
}) { | ||
@@ -79,7 +79,7 @@ // Run validations. | ||
toggle: menuToggleElement, | ||
parent: parentElement | ||
parent: parentElement, | ||
}; | ||
this.elements = { | ||
menu: menu, | ||
parentMenu: parentMenu | ||
parentMenu: parentMenu, | ||
}; | ||
@@ -86,0 +86,0 @@ this.openClass = openClass; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
119615
2526
21