@cbpds/web-components
Version:
Web components for the CBP Design System.
276 lines (275 loc) • 10.5 kB
JavaScript
/*!
* CPB Design System web components - built with Stencil
*/
import { Host, h } from "@stencil/core";
import { setCSSProps, createNamespaceKey, doKeyboardNav, clickAwayListener } from "../../utils/utils";
export class CbpMenu {
constructor() {
this.position = 'bottom-start';
this.open = false;
this.uid = createNamespaceKey('cbp-menu');
this.accessibilityText = undefined;
this.context = undefined;
this.sx = {};
}
async openMenu() {
this.open = true;
}
async closeMenu() {
var _a;
this.open = false;
(_a = this.control) === null || _a === void 0 ? void 0 : _a.focus();
}
watchOpen(newValue) {
if (newValue) {
this.menuItems = Array.from(this.menu.querySelectorAll('button, a'));
clickAwayListener(this.host, _ => {
this.open = false;
});
this.toggleMenu.emit({
host: this.host,
control: this.control,
open: this.open
});
setTimeout(() => this.setCurrentMenuItem(), 500);
}
this.CBPButton.expanded = `${this.open}`;
}
clickAwayHandler({ target }) {
if (!target.closest(this.host))
this.open = false;
}
handleKeyPress(e) {
const { key, shiftKey } = e;
const openKeys = ['ArrowDown', 'ArrowRight', 'ArrowUp', 'ArrowLeft'];
const navKeys = ['ArrowDown', 'ArrowRight', 'ArrowUp', 'ArrowLeft', 'Enter', 'Home', 'End'];
if (key == 'Escape')
this.closeMenu();
if (key == 'Tab' && !shiftKey)
this.open = false;
if (openKeys.includes(key) && !this.open) {
this.open = true;
return;
}
if (navKeys.includes(key)) {
this.focusIndex = doKeyboardNav(this.menuItems, key, this.focusIndex);
this.setCurrentMenuItem(this.focusIndex);
}
return;
}
setCurrentMenuItem(i = 0) {
this.menuItems[i].focus();
}
handleKeyPressCloseButton(e) {
if (e.key == 'Tab' && !e.shiftKey)
this.open = false;
}
componentWillLoad() {
this.CBPButton = this.host.querySelector('cbp-button');
this.control = this.host.querySelector('button');
if (typeof this.sx == 'string') {
this.sx = JSON.parse(this.sx) || {};
}
setCSSProps(this.host, Object.assign({}, this.sx));
}
componentDidLoad() {
this.menuItems = Array.from(this.menu.querySelectorAll('button,a'));
if (!this.control)
this.control = this.host.querySelector('button');
if (this.control) {
this.CBPButton.controls = this.uid;
this.CBPButton.expanded = `${this.open}`;
this.control.setAttribute('aria-controls', `${this.uid}-menu`);
this.control.setAttribute("aria-haspopup", "menu");
}
}
render() {
var _a;
return (h(Host, { key: '21624525db101101290ee100b176d9742b9637a4', id: this.uid, onKeyDown: (e) => this.handleKeyPress(e) }, h("slot", { key: '7f2ea4fddb22560d4f06ee0cde151bb448de738f' }), h("div", { key: 'e0e13d603ec15a0dd9ed4f0089ad0b801e6287fa', ref: (el) => this.menu = el, id: `${this.uid}-menu`, class: "cbp-menu__menu", role: "menu", hidden: !this.open, "aria-labelledby": (_a = this.control) === null || _a === void 0 ? void 0 : _a.id }, h("slot", { key: '6abc181437d81e93d107cc2a86cb7028934cf9ed', name: "cbp-menu-items" }), h("cbp-menu-item", { key: 'b7851c6be73a18bd9b3d71f18e24a6f5f23a7280', class: "cbp-menu__close-btn" }, h("cbp-button", { key: 'b6ee4d56ca853d6301f5d93289a92d48497cc314', fill: "solid", color: "primary", context: "dark-inverts", onButtonClick: () => this.closeMenu(), onKeyDown: (e) => this.handleKeyPressCloseButton(e) }, h("cbp-icon", { key: '5bbdab67491d4d31f35481d19b98335e852a0abc', name: "circle-xmark", size: "var(--cbp-space-5x)" }), "Close")))));
}
static get is() { return "cbp-menu"; }
static get originalStyleUrls() {
return {
"$": ["cbp-menu.scss"]
};
}
static get styleUrls() {
return {
"$": ["cbp-menu.css"]
};
}
static get properties() {
return {
"position": {
"type": "string",
"mutable": false,
"complexType": {
"original": "'bottom-start' | \"bottom-end\" | 'top-start' | \"top-end\"",
"resolved": "\"bottom-end\" | \"bottom-start\" | \"top-end\" | \"top-start\"",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "Specifies the position of the menu. Defaults to \"bottom-start\"."
},
"attribute": "position",
"reflect": true,
"defaultValue": "'bottom-start'"
},
"open": {
"type": "boolean",
"mutable": false,
"complexType": {
"original": "boolean",
"resolved": "boolean",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "When set, specifies that the menu is open."
},
"attribute": "open",
"reflect": true,
"defaultValue": "false"
},
"uid": {
"type": "string",
"mutable": false,
"complexType": {
"original": "string",
"resolved": "string",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "Specifies a unique `ID` for the menu, used to wire up the controls and accessibility features."
},
"attribute": "uid",
"reflect": false,
"defaultValue": "createNamespaceKey('cbp-menu')"
},
"accessibilityText": {
"type": "string",
"mutable": false,
"complexType": {
"original": "string",
"resolved": "string",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "Creates an accessible label for the menu control."
},
"attribute": "accessibility-text",
"reflect": false
},
"context": {
"type": "string",
"mutable": false,
"complexType": {
"original": "'light-inverts' | 'light-always' | 'dark-inverts' | 'dark-always'",
"resolved": "\"dark-always\" | \"dark-inverts\" | \"light-always\" | \"light-inverts\"",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "Specifies the context of the component as it applies to the visual design and whether it inverts when light/dark mode is toggled. Default behavior is \"light-inverts\" and does not have to be specified."
},
"attribute": "context",
"reflect": true
},
"sx": {
"type": "any",
"mutable": false,
"complexType": {
"original": "any",
"resolved": "any",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "Supports adding inline styles as an object"
},
"attribute": "sx",
"reflect": false,
"defaultValue": "{}"
}
};
}
static get events() {
return [{
"method": "toggleMenu",
"name": "toggleMenu",
"bubbles": true,
"cancelable": true,
"composed": true,
"docs": {
"tags": [],
"text": "A custom event fired when the menu is opened or closed."
},
"complexType": {
"original": "any",
"resolved": "any",
"references": {}
}
}];
}
static get methods() {
return {
"openMenu": {
"complexType": {
"signature": "() => Promise<void>",
"parameters": [],
"references": {
"Promise": {
"location": "global",
"id": "global::Promise"
}
},
"return": "Promise<void>"
},
"docs": {
"text": "A public method for opening the menu.",
"tags": []
}
},
"closeMenu": {
"complexType": {
"signature": "() => Promise<void>",
"parameters": [],
"references": {
"Promise": {
"location": "global",
"id": "global::Promise"
}
},
"return": "Promise<void>"
},
"docs": {
"text": "A public method for closing the menu.",
"tags": []
}
}
};
}
static get elementRef() { return "host"; }
static get watchers() {
return [{
"propName": "open",
"methodName": "watchOpen"
}];
}
}
//# sourceMappingURL=cbp-menu.js.map