UNPKG

@cbpds/web-components

Version:
276 lines (275 loc) 10.5 kB
/*! * 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