@luminela/menu
Version:
A simple menubar component for Angular.
226 lines (219 loc) • 10 kB
JavaScript
import { Component, ContentChildren, Input, ElementRef, HostBinding, HostListener, NgModule } from '@angular/core';
import { MenuItemComponent, ContextMenuModule } from '@luminela/contextmenu';
import { v4 } from 'uuid';
import { ActiveDescendantKeyManager } from '@angular/cdk/a11y';
import { CommonModule } from '@angular/common';
class MenuComponent {
constructor() {
this.uid = v4();
this.focused = false;
this.disabled = false;
this.menuItems = [];
}
ngOnInit() {
}
ngOnDestroy() {
var _a;
(_a = this.subMenuItemsSubscription$) === null || _a === void 0 ? void 0 : _a.unsubscribe();
}
ngAfterContentInit() {
var _a;
if (((_a = this.menuItems) === null || _a === void 0 ? void 0 : _a.length) > 0) {
return;
}
this.createMenuItems();
this.initializeMenuItems(this.menuItems);
this.subMenuItemsSubscription$ = this.subMenuItems.changes.subscribe(() => {
this.createMenuItems();
this.initializeMenuItems(this.menuItems);
});
}
setActiveStyles() {
if (!this.disabled) {
this.focused = true;
}
}
setInactiveStyles() {
this.focused = false;
}
createMenuItems() {
if (!this.menuItems || this.menuItems.length === 0) {
this.menuItems = this.subMenuItems.map(smi => smi.getMenuItemData());
}
}
initializeMenuItems(items) {
items.forEach(item => {
var _a;
item.visible = item.visible !== false;
this.initializeMenuItems(((_a = item.menuItems) === null || _a === void 0 ? void 0 : _a.length) > 0 ? item.menuItems : []);
});
}
}
MenuComponent.decorators = [
{ type: Component, args: [{
selector: "yui-menu",
template: ""
},] }
];
MenuComponent.ctorParameters = () => [];
MenuComponent.propDecorators = {
subMenuItems: [{ type: ContentChildren, args: [MenuItemComponent,] }],
disabled: [{ type: Input }],
menuClass: [{ type: Input }],
menuItems: [{ type: Input }],
target: [{ type: Input }],
text: [{ type: Input }],
textTemplate: [{ type: Input }]
};
class MenuBarComponent {
constructor(hostElementRef) {
this.hostElementRef = hostElementRef;
this.menuThemeClass = "theme-light";
this.menuTheme = "light";
this.menuClass = "";
}
set theme(theme) {
this.menuTheme = theme;
this.menuThemeClass = theme === "dark" ? "theme-dark" : "theme-light";
}
get lt() {
return this.menuThemeClass === "theme-light";
}
get dt() {
return this.menuThemeClass === "theme-dark";
}
ngOnInit() {
}
ngAfterContentInit() {
console.log(this.menuList);
}
ngAfterViewInit() {
this.keyManager = new ActiveDescendantKeyManager(this.menuList.toArray()).withWrap(true).skipPredicate(m => m.disabled);
}
onMenuChange(data) {
this.menuChangeData = data;
}
onMenuClose(data) {
this.keyManager.setActiveItem(null);
this.previousMenuData = null;
if (!!this.currentMenu) {
this.currentMenu.focused = false;
this.currentMenu = null;
}
this.menuChangeData = null;
}
onMenuClick(event, menu) {
var _a;
if (this.previousMenuElement === event.target.closest(`[data-uid='${menu.uid}']`)) {
menu.focused = !menu.focused;
if (!menu.focused) {
(_a = this.previousMenuData) === null || _a === void 0 ? void 0 : _a.contextMenuRef.popupRef.close();
}
return;
}
this.previousMenuElement = event.target.closest("li").firstChild;
this.keyManager.setActiveItem(this.menuList.find(m => m.uid === menu.uid));
this.currentMenu = menu;
}
onMenuMouseEnter(event, menu) {
var _a;
if (this.previousMenuData) {
if (this.previousMenuElement === event.target.closest(`[data-uid='${menu.uid}']`)) {
return;
}
(_a = this.previousMenuData) === null || _a === void 0 ? void 0 : _a.contextMenuRef.popupRef.close();
event.target.dispatchEvent(new MouseEvent("click", Object.assign({}, event)));
this.keyManager.setActiveItem(this.menuList.find(m => m.uid === menu.uid));
}
this.previousMenuElement = event.target.closest("li").firstChild;
this.currentMenu = menu;
}
onMenuMouseLeave(event, menu) {
// this.currentMenu = null;
// menu.focused = false;
// this.keyManager.setActiveItem(null);
}
onMenuOpen(data) {
if (data.depth > 0) {
return;
}
this.previousMenuData = data;
}
onKeydown(event) {
var _a, _b, _c;
if (!this.previousMenuData) {
return;
}
switch (event.key) {
case "Enter":
case "NumEnter":
case " ":
this.keyManager.setActiveItem(null);
return;
case "ArrowUp":
case "ArrowDown":
console.log("Ignore " + event.key);
return;
case "ArrowLeft":
if (((_a = this.menuChangeData) === null || _a === void 0 ? void 0 : _a.depth) > 1) {
return;
}
this.keyManager.setPreviousItemActive();
break;
case "ArrowRight":
if (((_c = (_b = this.menuChangeData) === null || _b === void 0 ? void 0 : _b.item.menuItems) === null || _c === void 0 ? void 0 : _c.length) > 0) {
return;
}
this.keyManager.setNextItemActive();
break;
default:
this.keyManager.onKeydown(event);
break;
}
if (this.keyManager.activeItem) {
this.currentMenu = this.keyManager.activeItem;
document.querySelector(`[data-uid='${this.currentMenu.uid}']`).dispatchEvent(new MouseEvent("mouseenter"));
}
}
}
MenuBarComponent.decorators = [
{ type: Component, args: [{
selector: "yui-menu-bar",
template: "<div class=\"wrapper\">\n <ul class=\"menubar-list\" *ngIf=\"menuList?.length > 0\">\n <li *ngFor=\"let item of menuList\" #listElement (mouseenter)=\"onMenuMouseEnter($event, item)\"\n (mouseleave)=\"onMenuMouseLeave($event, item)\" (click)=\"onMenuClick($event, item)\"\n [attr.data-uid]=\"item.uid\"\n [ngClass]=\"{'active': item.focused && !item.disabled, 'disabled': item.disabled}\">\n <span *ngIf=\"!item.textTemplate\">{{item.text}}</span>\n <ng-container [ngTemplateOutlet]=\"item.textTemplate\" *ngIf=\"!!item.textTemplate\"></ng-container>\n <yui-contextmenu [target]=\"listElement\" [menuItems]=\"item.menuItems\" [theme]=\"menuTheme\" [menuClass]=\"menuClass\"\n [precise]=\"false\" trigger=\"click\" (menuOpen)=\"onMenuOpen($event)\"\n (menuClose)=\"onMenuClose($event)\" (menuChange)=\"onMenuChange($event)\"></yui-contextmenu>\n </li>\n </ul>\n</div>\n",
styles: ["div.wrapper{height:25px;width:100%}div.wrapper,div.wrapper *{-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none;box-sizing:border-box;user-select:none}ul.menubar-list{justify-content:flex-start;width:100%}ul.menubar-list,ul.menubar-list>li{align-items:center;display:flex;height:100%}ul.menubar-list>li{border-left:1px solid transparent;border-right:1px solid transparent;font-size:13px;font-weight:600;justify-content:center;padding:0 10px}ul.menubar-list>li.disabled{pointer-events:none}:host-context(.theme-light) ul.menubar-list{background:#e8e8e8;border-bottom:1px solid #d1d1d1}:host-context(.theme-light) ul.menubar-list>li{color:#383848}:host-context(.theme-light) ul.menubar-list>li.active,:host-context(.theme-light) ul.menubar-list>li:hover:not(.disabled){background:#f2f2f4}:host-context(.theme-light) ul.menubar-list>li.active:not(:first-child),:host-context(.theme-light) ul.menubar-list>li:hover:not(.disabled):not(:first-child){border-left:1px solid #d1d1d1}:host-context(.theme-light) ul.menubar-list>li.disabled{color:#a7a7af}:host-context(.theme-dark) ul.menubar-list{background:#383838;border-bottom:1px solid #585858}:host-context(.theme-dark) ul.menubar-list>li{color:#c0c0c6}:host-context(.theme-dark) ul.menubar-list>li.active,:host-context(.theme-dark) ul.menubar-list>li:hover:not(.disabled){background:#47474f}:host-context(.theme-dark) ul.menubar-list>li.active:not(:first-child),:host-context(.theme-dark) ul.menubar-list>li:hover:not(.disabled):not(:first-child){border-left:1px solid #585858}:host-context(.theme-dark) ul.menubar-list>li.disabled{color:#6a6a70}"]
},] }
];
MenuBarComponent.ctorParameters = () => [
{ type: ElementRef }
];
MenuBarComponent.propDecorators = {
menuList: [{ type: ContentChildren, args: [MenuComponent,] }],
menuClass: [{ type: Input }],
theme: [{ type: Input }],
lt: [{ type: HostBinding, args: ["class.theme-light",] }],
dt: [{ type: HostBinding, args: ["class.theme-dark",] }],
onKeydown: [{ type: HostListener, args: ["window:keydown", ["$event"],] }]
};
class MenuModule {
}
MenuModule.decorators = [
{ type: NgModule, args: [{
declarations: [MenuBarComponent, MenuComponent],
imports: [
CommonModule,
ContextMenuModule
],
exports: [
MenuBarComponent,
MenuComponent
]
},] }
];
/*
* Public API Surface of menu
*/
/**
* Generated bundle index. Do not edit.
*/
export { MenuBarComponent, MenuComponent, MenuModule };
//# sourceMappingURL=luminela-menu.js.map