@claromentis/design-system
Version:
Claromentis Design System Component Library
184 lines (183 loc) • 4.93 kB
JavaScript
import { h } from '@stencil/core';
/**
* @slot - Allows menu items to be added to the dropdown menu.
*/
export class Cardmenu {
constructor() {
this.toggle = false;
this.isMobile = false;
this.closeOnSelect = false;
}
/**
* Listen for mousedown events and handle them
*/
handleClick(event) {
// Close the menu if the user clicks elsewhere on the page
if (!this.toggle)
return;
if (event.composedPath().indexOf(this.element) === -1)
this.toggle = false;
// Close Menu on Item Select
const targetElement = event.target;
if (this.closeOnSelect && targetElement.parentElement.closest('cla-menu')) {
this.toggle = false;
}
}
/**
* Listen for window resize events and handle
*/
handleWindowResize() {
this.checkIfMobile();
}
/**
* Listen for keydown events and handle
*
*/
handleKeyDown(event) {
const targetElement = event.target;
switch (event.key) {
case "Enter":
// open/close menu when the toggle button is focussed
if (targetElement.className === "dropdown-toggle-button") {
this.toggleMenu();
}
//when closeOnSelect is true close menu when 'Enter' is pressed
if (this.closeOnSelect && targetElement.parentElement.closest('cla-menu')) {
this.toggle = false;
}
break;
case "Escape":
//close menu when escape key is pressed
if (this.toggle) {
this.toggleMenu();
}
break;
case "Tab":
//close menu if tab away from last item
if (this.toggle && targetElement.parentElement.closest('cla-menu') &&
targetElement.nextElementSibling === null && !event.shiftKey) {
this.toggleMenu();
}
}
}
componentWillLoad() {
//make non-link menu items tabbable
let childrenArray = Array.from(this.element.children);
childrenArray.forEach(function (menuItem) {
menuItem.setAttribute('tabindex', '0');
});
}
componentDidLoad() {
this.checkIfMobile();
}
/**
* Checks if screen width is a mobile width
*
* @return Boolean
*/
checkIfMobile() {
return window.screen.width < 768 ? this.isMobile = true : this.isMobile = false;
}
/**
* Toggles the opening and closing of the menu.
*
* @return Boolean
*/
toggleMenu() {
return this.toggle = !this.toggle;
}
/**
* Get the map of CSS classes for the button.
*
* @return CssClassMap
*/
getMenuClassMap() {
return {
'dropdown-menu': true,
'dropdown-menu-right': this.isMobile ? true : false
};
}
render() {
return (h("div", { class: this.toggle ? "dropdown-wrapper in" : "dropdown-wrapper" }, h("button", { class: "dropdown-toggle-button", onMouseDown: () => this.toggleMenu(), onKeyDown: (e) => this.handleKeyDown(e) }, h("span", { class: "dot" }), h("span", { class: "dot" }), h("span", { class: "dot" }), h("span", { class: "sr-only" }, "toggle dropdown")), h("div", { class: this.getMenuClassMap() }, h("slot", null))));
}
static get is() { return "cla-menu"; }
static get encapsulation() { return "shadow"; }
static get originalStyleUrls() {
return {
"$": ["cla-menu.scss"]
};
}
static get styleUrls() {
return {
"$": ["cla-menu.css"]
};
}
static get properties() {
return {
"closeOnSelect": {
"type": "boolean",
"mutable": false,
"complexType": {
"original": "boolean",
"resolved": "boolean",
"references": {}
},
"required": false,
"optional": true,
"docs": {
"tags": [],
"text": "If 'true' the menu will close when an item is selected"
},
"attribute": "close-on-select",
"reflect": false,
"defaultValue": "false"
}
};
}
static get states() {
return {
"toggle": {},
"isMobile": {}
};
}
static get events() {
return [{
"method": "toggleEvent",
"name": "toggleEvent",
"bubbles": true,
"cancelable": true,
"composed": true,
"docs": {
"tags": [],
"text": "Emitted when the menu is toggled."
},
"complexType": {
"original": "any",
"resolved": "any",
"references": {}
}
}];
}
static get elementRef() { return "element"; }
static get listeners() {
return [{
"name": "mousedown",
"method": "handleClick",
"target": "window",
"capture": false,
"passive": true
}, {
"name": "resize",
"method": "handleWindowResize",
"target": "window",
"capture": false,
"passive": true
}, {
"name": "keydown",
"method": "handleKeyDown",
"target": "window",
"capture": false,
"passive": false
}];
}
}