@limetech/lime-elements
Version:
258 lines (257 loc) • 7.6 kB
JavaScript
import { MDCMenu } from '@material/menu';
import { MDCRipple } from '@material/ripple';
import { strings as menuStrings } from '@material/menu/constants';
import { h, } from '@stencil/core';
import { MenuListRenderer } from './menu-list-renderer';
const { SELECTED_EVENT } = menuStrings;
/**
* @private
*/
export class MenuList {
constructor() {
this.MenuListRenderer = new MenuListRenderer();
this.setup = () => {
this.setupMenu();
this.setupListeners();
};
this.setupMenu = () => {
if (this.mdcMenu) {
this.teardown();
this.mdcMenu = null;
}
const element = this.element.shadowRoot.querySelector('.mdc-menu');
if (!element) {
return;
}
this.mdcMenu = new MDCMenu(element);
this.mdcMenu.hasTypeahead = true;
this.mdcMenu.wrapFocus = true;
// eslint-disable-next-line sonarjs/constructor-for-side-effects
for (const item of this.mdcMenu.items)
new MDCRipple(item);
};
this.setupListeners = () => {
if (!this.mdcMenu) {
return;
}
this.mdcMenu.unlisten(SELECTED_EVENT, this.handleMenuSelect);
this.mdcMenu.listen(SELECTED_EVENT, this.handleMenuSelect);
};
this.teardown = () => {
var _a, _b;
(_a = this.mdcMenu) === null || _a === void 0 ? void 0 : _a.unlisten(SELECTED_EVENT, this.handleMenuSelect);
(_b = this.mdcMenu) === null || _b === void 0 ? void 0 : _b.destroy();
};
this.handleMenuSelect = (event) => {
this.handleSingleSelect(event.detail.index);
};
this.handleSingleSelect = (index) => {
const MenuItems = this.items.filter(this.isMenuItem);
if (MenuItems[index].disabled) {
return;
}
const selectedItem = MenuItems.find((item) => {
return !!item.selected;
});
let interactedItem;
if (selectedItem) {
interactedItem = Object.assign(Object.assign({}, selectedItem), { selected: false });
this.select.emit(interactedItem);
}
if (MenuItems[index] !== selectedItem) {
interactedItem = Object.assign(Object.assign({}, MenuItems[index]), { selected: false });
this.select.emit(interactedItem);
}
this.interact.emit(interactedItem);
};
this.isMenuItem = (item) => {
return !('separator' in item);
};
this.items = undefined;
this.badgeIcons = undefined;
this.iconSize = 'small';
this.maxLinesSecondaryText = 3;
}
connectedCallback() {
this.setup();
}
disconnectedCallback() {
this.teardown();
}
componentDidLoad() {
this.setup();
this.triggerIconColorWarning();
}
render() {
this.config = {
badgeIcons: this.badgeIcons,
iconSize: this.iconSize,
};
const html = this.MenuListRenderer.render(this.items, this.config);
return h("div", { class: "mdc-menu mdc-menu-surface" }, html);
}
itemsChanged() {
setTimeout(() => {
this.setup();
}, 0);
}
triggerIconColorWarning() {
var _a;
if ((_a = this.items) === null || _a === void 0 ? void 0 : _a.some((item) => 'iconColor' in item)) {
console.warn("The `iconColor` prop is deprecated now! Use the new `Icon` interface and instead of `iconColor: 'color-name'` write `icon {name: 'icon-name', color: 'color-name'}`.");
}
}
static get is() { return "limel-menu-list"; }
static get encapsulation() { return "shadow"; }
static get delegatesFocus() { return true; }
static get originalStyleUrls() {
return {
"$": ["menu-list.scss"]
};
}
static get styleUrls() {
return {
"$": ["menu-list.css"]
};
}
static get properties() {
return {
"items": {
"type": "unknown",
"mutable": false,
"complexType": {
"original": "Array<MenuItem | ListSeparator>",
"resolved": "(ListSeparator | MenuItem<any>)[]",
"references": {
"Array": {
"location": "global"
},
"MenuItem": {
"location": "import",
"path": "../menu/menu.types"
},
"ListSeparator": {
"location": "import",
"path": "../list/list-item.types"
}
}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "List of items to display"
}
},
"badgeIcons": {
"type": "boolean",
"mutable": false,
"complexType": {
"original": "boolean",
"resolved": "boolean",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "Set to `true` if the list should display larger icons with a background"
},
"attribute": "badge-icons",
"reflect": false
},
"iconSize": {
"type": "string",
"mutable": false,
"complexType": {
"original": "IconSize",
"resolved": "\"large\" | \"medium\" | \"small\" | \"x-small\"",
"references": {
"IconSize": {
"location": "import",
"path": "../icon/icon.types"
}
}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "Size of the icons in the list"
},
"attribute": "icon-size",
"reflect": false,
"defaultValue": "'small'"
},
"maxLinesSecondaryText": {
"type": "number",
"mutable": false,
"complexType": {
"original": "number",
"resolved": "number",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "By default, lists will display 3 lines of text, and then truncate the rest.\nConsumers can increase or decrease this number by specifying\n`maxLinesSecondaryText`. If consumer enters zero or negative\nnumbers we default to 1; and if they type decimals we round up."
},
"attribute": "max-lines-secondary-text",
"reflect": false,
"defaultValue": "3"
}
};
}
static get events() {
return [{
"method": "select",
"name": "select",
"bubbles": true,
"cancelable": true,
"composed": true,
"docs": {
"tags": [],
"text": "Fired when a new value has been selected from the list."
},
"complexType": {
"original": "MenuItem",
"resolved": "MenuItem<any>",
"references": {
"MenuItem": {
"location": "import",
"path": "../menu/menu.types"
}
}
}
}, {
"method": "interact",
"name": "interact",
"bubbles": true,
"cancelable": true,
"composed": true,
"docs": {
"tags": [],
"text": "Fires when a user interacts with an item in the list (e.g., click,\nkeyboard select)."
},
"complexType": {
"original": "MenuItem",
"resolved": "MenuItem<any>",
"references": {
"MenuItem": {
"location": "import",
"path": "../menu/menu.types"
}
}
}
}];
}
static get elementRef() { return "element"; }
static get watchers() {
return [{
"propName": "items",
"methodName": "itemsChanged"
}];
}
}
//# sourceMappingURL=menu-list.js.map