UNPKG

@avdbrink/ngx-contextmenu

Version:

An Angular component to show a context menu on an arbitrary component

945 lines (929 loc) 109 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core'), require('rxjs'), require('@angular/cdk/a11y'), require('@angular/cdk/overlay'), require('@angular/cdk/portal'), require('rxjs/operators'), require('@angular/common')) : typeof define === 'function' && define.amd ? define('ngx-contextmenu', ['exports', '@angular/core', 'rxjs', '@angular/cdk/a11y', '@angular/cdk/overlay', '@angular/cdk/portal', 'rxjs/operators', '@angular/common'], factory) : (factory((global['ngx-contextmenu'] = {}),global.ng.core,global.rxjs,global.ng.cdk.a11y,global.ng.cdk.overlay,global.ng.cdk.portal,global.rxjs.operators,global.ng.common)); }(this, (function (exports,core,rxjs,a11y,overlay,portal,operators,common) { 'use strict'; /*! ***************************************************************************** Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. See the Apache Version 2.0 License for specific language governing permissions and limitations under the License. ***************************************************************************** */ var __assign = Object.assign || function __assign(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ var /** @type {?} */ CONTEXT_MENU_OPTIONS = new core.InjectionToken('CONTEXT_MENU_OPTIONS'); /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ var /** @type {?} */ ARROW_LEFT_KEYCODE = 37; var ContextMenuContentComponent = (function () { function ContextMenuContentComponent(changeDetector, elementRef, options, renderer) { this.changeDetector = changeDetector; this.elementRef = elementRef; this.options = options; this.renderer = renderer; this.menuItems = []; this.isLeaf = false; this.execute = new core.EventEmitter(); this.openSubMenu = new core.EventEmitter(); this.closeLeafMenu = new core.EventEmitter(); this.closeAllMenus = new core.EventEmitter(); this.autoFocus = false; this.useBootstrap4 = false; this.highlightParentItems = false; this.subscription = new rxjs.Subscription(); if (options) { this.autoFocus = options.autoFocus; this.useBootstrap4 = options.useBootstrap4; this.highlightParentItems = options.highlightParentItems; } } /** * @return {?} */ ContextMenuContentComponent.prototype.ngOnInit = /** * @return {?} */ function () { var _this = this; this.menuItems.forEach(function (menuItem) { menuItem.currentItem = _this.item; _this.subscription.add(menuItem.execute.subscribe(function (event) { return _this.execute.emit(__assign({}, event, { menuItem: menuItem })); })); }); var /** @type {?} */ queryList = new core.QueryList(); queryList.reset(this.menuItems); this._keyManager = new a11y.ActiveDescendantKeyManager(queryList).withWrap(); }; /** * @return {?} */ ContextMenuContentComponent.prototype.ngAfterViewInit = /** * @return {?} */ function () { var _this = this; if (this.autoFocus) { setTimeout(function () { return _this.focus(); }); } this.overlay.updatePosition(); }; /** * @return {?} */ ContextMenuContentComponent.prototype.ngOnDestroy = /** * @return {?} */ function () { this.subscription.unsubscribe(); }; /** * @return {?} */ ContextMenuContentComponent.prototype.focus = /** * @return {?} */ function () { if (this.autoFocus) { this.menuElement.nativeElement.focus(); } }; /** * @param {?} $event * @return {?} */ ContextMenuContentComponent.prototype.stopEvent = /** * @param {?} $event * @return {?} */ function ($event) { $event.stopPropagation(); }; /** * @param {?} menuItem * @return {?} */ ContextMenuContentComponent.prototype.isMenuItemEnabled = /** * @param {?} menuItem * @return {?} */ function (menuItem) { return this.evaluateIfFunction(menuItem && menuItem.enabled); }; /** * @param {?} menuItem * @return {?} */ ContextMenuContentComponent.prototype.isMenuItemVisible = /** * @param {?} menuItem * @return {?} */ function (menuItem) { return this.evaluateIfFunction(menuItem && menuItem.visible); }; /** * @param {?} value * @return {?} */ ContextMenuContentComponent.prototype.evaluateIfFunction = /** * @param {?} value * @return {?} */ function (value) { if (value instanceof Function) { return value(this.item); } return value; }; /** * @param {?} link * @return {?} */ ContextMenuContentComponent.prototype.isDisabled = /** * @param {?} link * @return {?} */ function (link) { return link.enabled && !link.enabled(this.item); }; /** * @param {?} event * @return {?} */ ContextMenuContentComponent.prototype.onKeyEvent = /** * @param {?} event * @return {?} */ function (event) { if (!this.isLeaf) { return; } this._keyManager.onKeydown(event); }; /** * @param {?=} event * @return {?} */ ContextMenuContentComponent.prototype.keyboardOpenSubMenu = /** * @param {?=} event * @return {?} */ function (event) { if (!this.isLeaf) { return; } this.cancelEvent(event); var /** @type {?} */ menuItem = this.menuItems[this._keyManager.activeItemIndex]; if (menuItem) { this.onOpenSubMenu(menuItem); } }; /** * @param {?=} event * @return {?} */ ContextMenuContentComponent.prototype.keyboardMenuItemSelect = /** * @param {?=} event * @return {?} */ function (event) { if (!this.isLeaf) { return; } this.cancelEvent(event); var /** @type {?} */ menuItem = this.menuItems[this._keyManager.activeItemIndex]; if (menuItem) { this.onMenuItemSelect(menuItem, event); } }; /** * @param {?} event * @return {?} */ ContextMenuContentComponent.prototype.onCloseLeafMenu = /** * @param {?} event * @return {?} */ function (event) { if (!this.isLeaf) { return; } this.cancelEvent(event); this.closeLeafMenu.emit({ exceptRootMenu: event.keyCode === ARROW_LEFT_KEYCODE, event: event }); }; /** * @param {?} event * @return {?} */ ContextMenuContentComponent.prototype.closeMenu = /** * @param {?} event * @return {?} */ function (event) { if (event.type === 'click' && event.button === 2) { return; } this.closeAllMenus.emit({ event: event }); }; /** * @param {?} menuItem * @param {?=} event * @return {?} */ ContextMenuContentComponent.prototype.onOpenSubMenu = /** * @param {?} menuItem * @param {?=} event * @return {?} */ function (menuItem, event) { var /** @type {?} */ anchorElementRef = this.menuItemElements.toArray()[this._keyManager.activeItemIndex]; var /** @type {?} */ anchorElement = anchorElementRef && anchorElementRef.nativeElement; if (this.highlightParentItems) { this.menuItems.forEach(function (item) { return item.isActiveParent = (item === menuItem && menuItem.subMenu); }); } this.openSubMenu.emit({ anchorElement: anchorElement, contextMenu: menuItem.subMenu, event: event, item: this.item, parentContextMenu: this, }); }; /** * @param {?} menuItem * @param {?} event * @return {?} */ ContextMenuContentComponent.prototype.onMenuItemSelect = /** * @param {?} menuItem * @param {?} event * @return {?} */ function (menuItem, event) { event.preventDefault(); event.stopPropagation(); this.onOpenSubMenu(menuItem, event); if (!menuItem.subMenu) { menuItem.triggerExecute(this.item, event); } }; /** * @param {?} event * @return {?} */ ContextMenuContentComponent.prototype.cancelEvent = /** * @param {?} event * @return {?} */ function (event) { if (!event) { return; } var /** @type {?} */ target = event.target; if (['INPUT', 'TEXTAREA', 'SELECT'].indexOf(target.tagName) > -1 || target.isContentEditable) { return; } event.preventDefault(); event.stopPropagation(); }; ContextMenuContentComponent.decorators = [ { type: core.Component, args: [{ selector: 'context-menu-content', styles: [ ".passive {\n display: block;\n padding: 3px 20px;\n clear: both;\n font-weight: normal;\n line-height: @line-height-base;\n white-space: nowrap;\n }\n .hasSubMenu:before {\n content: \"\u25B6\";\n float: right;\n }\n .activeParent {\n text-decoration: none;\n color: #262626;\n background-color: #f5f5f5;\n }", ], template: "<div class=\"dropdown open show ngx-contextmenu\" [ngClass]=\"menuClass\" tabindex=\"0\">\n <ul #menu class=\"dropdown-menu show\" style=\"position: static; float: none;\" tabindex=\"0\">\n <li #li *ngFor=\"let menuItem of menuItems; let i = index\" [class.disabled]=\"!isMenuItemEnabled(menuItem)\"\n [class.divider]=\"menuItem.divider\" [class.dropdown-divider]=\"useBootstrap4 && menuItem.divider\"\n [class.active]=\"menuItem.isActive && isMenuItemEnabled(menuItem)\"\n [attr.role]=\"menuItem.divider ? 'separator' : undefined\">\n <a *ngIf=\"!menuItem.divider && !menuItem.passive\" href [class.dropdown-item]=\"useBootstrap4\"\n [class.active]=\"menuItem.isActive && isMenuItemEnabled(menuItem)\"\n [class.activeParent]=\"highlightParentItems && menuItem.isActiveParent && isMenuItemEnabled(menuItem)\"\n [class.disabled]=\"useBootstrap4 && !isMenuItemEnabled(menuItem)\" [class.hasSubMenu]=\"!!menuItem.subMenu\"\n (click)=\"onMenuItemSelect(menuItem, $event)\" (mouseenter)=\"onOpenSubMenu(menuItem, $event)\">\n <ng-template [ngTemplateOutlet]=\"menuItem.template\" [ngTemplateOutletContext]=\"{ $implicit: item }\"></ng-template>\n </a>\n\n <span (click)=\"stopEvent($event)\" (contextmenu)=\"stopEvent($event)\" class=\"passive\"\n *ngIf=\"!menuItem.divider && menuItem.passive\" [class.dropdown-item]=\"useBootstrap4\"\n [class.disabled]=\"useBootstrap4 && !isMenuItemEnabled(menuItem)\">\n <ng-template [ngTemplateOutlet]=\"menuItem.template\" [ngTemplateOutletContext]=\"{ $implicit: item }\"></ng-template>\n </span>\n </li>\n </ul>\n </div>\n ", },] }, ]; /** @nocollapse */ ContextMenuContentComponent.ctorParameters = function () { return [ { type: core.ChangeDetectorRef }, { type: core.ElementRef }, { type: undefined, decorators: [{ type: core.Optional }, { type: core.Inject, args: [CONTEXT_MENU_OPTIONS,] }] }, { type: core.Renderer } ]; }; ContextMenuContentComponent.propDecorators = { menuItems: [{ type: core.Input }], item: [{ type: core.Input }], event: [{ type: core.Input }], parentContextMenu: [{ type: core.Input }], menuClass: [{ type: core.Input }], overlay: [{ type: core.Input }], isLeaf: [{ type: core.Input }], execute: [{ type: core.Output }], openSubMenu: [{ type: core.Output }], closeLeafMenu: [{ type: core.Output }], closeAllMenus: [{ type: core.Output }], menuElement: [{ type: core.ViewChild, args: ['menu',] }], menuItemElements: [{ type: core.ViewChildren, args: ['li',] }], onKeyEvent: [{ type: core.HostListener, args: ['window:keydown.ArrowDown', ['$event'],] }, { type: core.HostListener, args: ['window:keydown.ArrowUp', ['$event'],] }], keyboardOpenSubMenu: [{ type: core.HostListener, args: ['window:keydown.ArrowRight', ['$event'],] }], keyboardMenuItemSelect: [{ type: core.HostListener, args: ['window:keydown.Enter', ['$event'],] }, { type: core.HostListener, args: ['window:keydown.Space', ['$event'],] }], onCloseLeafMenu: [{ type: core.HostListener, args: ['window:keydown.Escape', ['$event'],] }, { type: core.HostListener, args: ['window:keydown.ArrowLeft', ['$event'],] }], closeMenu: [{ type: core.HostListener, args: ['document:click', ['$event'],] }, { type: core.HostListener, args: ['document:contextmenu', ['$event'],] }] }; return ContextMenuContentComponent; }()); /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ var ContextMenuService = (function () { function ContextMenuService(overlay$$1, scrollStrategy) { this.overlay = overlay$$1; this.scrollStrategy = scrollStrategy; this.isDestroyingLeafMenu = false; this.show = new rxjs.Subject(); this.triggerClose = new rxjs.Subject(); this.close = new rxjs.Subject(); this.overlays = []; this.fakeElement = { getBoundingClientRect: function () { return ({ bottom: 0, height: 0, left: 0, right: 0, top: 0, width: 0, }); } }; } /** * @param {?} context * @return {?} */ ContextMenuService.prototype.openContextMenu = /** * @param {?} context * @return {?} */ function (context) { var anchorElement = context.anchorElement, event = context.event, parentContextMenu = context.parentContextMenu; if (!parentContextMenu) { var /** @type {?} */ mouseEvent_1 = (event); this.fakeElement.getBoundingClientRect = function () { return ({ bottom: mouseEvent_1.clientY, height: 0, left: mouseEvent_1.clientX, right: mouseEvent_1.clientX, top: mouseEvent_1.clientY, width: 0, }); }; this.closeAllContextMenus({ eventType: 'cancel', event: event }); var /** @type {?} */ positionStrategy = this.overlay.position().connectedTo(new core.ElementRef(anchorElement || this.fakeElement), { originX: 'start', originY: 'bottom' }, { overlayX: 'start', overlayY: 'top' }) .withFallbackPosition({ originX: 'start', originY: 'top' }, { overlayX: 'start', overlayY: 'bottom' }) .withFallbackPosition({ originX: 'end', originY: 'top' }, { overlayX: 'start', overlayY: 'top' }) .withFallbackPosition({ originX: 'start', originY: 'top' }, { overlayX: 'end', overlayY: 'top' }) .withFallbackPosition({ originX: 'end', originY: 'center' }, { overlayX: 'start', overlayY: 'center' }) .withFallbackPosition({ originX: 'start', originY: 'center' }, { overlayX: 'end', overlayY: 'center' }); this.overlays = [this.overlay.create({ positionStrategy: positionStrategy, panelClass: 'ngx-contextmenu', scrollStrategy: this.scrollStrategy.close(), })]; this.attachContextMenu(this.overlays[0], context); } else { var /** @type {?} */ positionStrategy = this.overlay.position().connectedTo(new core.ElementRef(event ? event.target : anchorElement), { originX: 'end', originY: 'top' }, { overlayX: 'start', overlayY: 'top' }) .withFallbackPosition({ originX: 'start', originY: 'top' }, { overlayX: 'end', overlayY: 'top' }) .withFallbackPosition({ originX: 'end', originY: 'bottom' }, { overlayX: 'start', overlayY: 'bottom' }) .withFallbackPosition({ originX: 'start', originY: 'bottom' }, { overlayX: 'end', overlayY: 'bottom' }); var /** @type {?} */ newOverlay = this.overlay.create({ positionStrategy: positionStrategy, panelClass: 'ngx-contextmenu', scrollStrategy: this.scrollStrategy.close(), }); this.destroySubMenus(parentContextMenu); this.overlays = this.overlays.concat(newOverlay); this.attachContextMenu(newOverlay, context); } }; /** * @param {?} overlay * @param {?} context * @return {?} */ ContextMenuService.prototype.attachContextMenu = /** * @param {?} overlay * @param {?} context * @return {?} */ function (overlay$$1, context) { var _this = this; var event = context.event, item = context.item, menuItems = context.menuItems, menuClass = context.menuClass; var /** @type {?} */ contextMenuContent = overlay$$1.attach(new portal.ComponentPortal(ContextMenuContentComponent)); contextMenuContent.instance.event = event; contextMenuContent.instance.item = item; contextMenuContent.instance.menuItems = menuItems; contextMenuContent.instance.overlay = overlay$$1; contextMenuContent.instance.isLeaf = true; contextMenuContent.instance.menuClass = menuClass; ((overlay$$1)).contextMenu = contextMenuContent.instance; var /** @type {?} */ subscriptions = new rxjs.Subscription(); subscriptions.add(contextMenuContent.instance.execute.asObservable() .subscribe(function (executeEvent) { return _this.closeAllContextMenus(__assign({ eventType: 'execute' }, executeEvent)); })); subscriptions.add(contextMenuContent.instance.closeAllMenus.asObservable() .subscribe(function (closeAllEvent) { return _this.closeAllContextMenus(__assign({ eventType: 'cancel' }, closeAllEvent)); })); subscriptions.add(contextMenuContent.instance.closeLeafMenu.asObservable() .subscribe(function (closeLeafMenuEvent) { return _this.destroyLeafMenu(closeLeafMenuEvent); })); subscriptions.add(contextMenuContent.instance.openSubMenu.asObservable() .subscribe(function (subMenuEvent) { _this.destroySubMenus(contextMenuContent.instance); if (!subMenuEvent.contextMenu) { contextMenuContent.instance.isLeaf = true; return; } contextMenuContent.instance.isLeaf = false; _this.show.next(subMenuEvent); })); contextMenuContent.onDestroy(function () { menuItems.forEach(function (menuItem) { return menuItem.isActive = false; }); subscriptions.unsubscribe(); }); contextMenuContent.changeDetectorRef.detectChanges(); }; /** * @param {?} closeEvent * @return {?} */ ContextMenuService.prototype.closeAllContextMenus = /** * @param {?} closeEvent * @return {?} */ function (closeEvent) { if (this.overlays) { this.close.next(closeEvent); this.overlays.forEach(function (overlay$$1, index) { overlay$$1.detach(); overlay$$1.dispose(); }); } this.overlays = []; }; /** * @return {?} */ ContextMenuService.prototype.getLastAttachedOverlay = /** * @return {?} */ function () { var /** @type {?} */ overlay$$1 = this.overlays[this.overlays.length - 1]; while (this.overlays.length > 1 && overlay$$1 && !overlay$$1.hasAttached()) { overlay$$1.detach(); overlay$$1.dispose(); this.overlays = this.overlays.slice(0, -1); overlay$$1 = this.overlays[this.overlays.length - 1]; } return overlay$$1; }; /** * @param {?=} __0 * @return {?} */ ContextMenuService.prototype.destroyLeafMenu = /** * @param {?=} __0 * @return {?} */ function (_a) { var _this = this; var _b = _a === void 0 ? {} : _a, exceptRootMenu = _b.exceptRootMenu, event = _b.event; if (this.isDestroyingLeafMenu) { return; } this.isDestroyingLeafMenu = true; setTimeout(function () { var /** @type {?} */ overlay$$1 = _this.getLastAttachedOverlay(); if (_this.overlays.length > 1 && overlay$$1) { overlay$$1.detach(); overlay$$1.dispose(); } if (!exceptRootMenu && _this.overlays.length > 0 && overlay$$1) { _this.close.next({ eventType: 'cancel', event: event }); overlay$$1.detach(); overlay$$1.dispose(); } var /** @type {?} */ newLeaf = _this.getLastAttachedOverlay(); if (newLeaf) { newLeaf.contextMenu.isLeaf = true; } _this.isDestroyingLeafMenu = false; }); }; /** * @param {?} contextMenu * @return {?} */ ContextMenuService.prototype.destroySubMenus = /** * @param {?} contextMenu * @return {?} */ function (contextMenu) { var /** @type {?} */ overlay$$1 = contextMenu.overlay; var /** @type {?} */ index = this.overlays.indexOf(overlay$$1); this.overlays.slice(index + 1).forEach(function (subMenuOverlay) { subMenuOverlay.detach(); subMenuOverlay.dispose(); }); }; /** * @param {?} contextMenuContent * @return {?} */ ContextMenuService.prototype.isLeafMenu = /** * @param {?} contextMenuContent * @return {?} */ function (contextMenuContent) { var /** @type {?} */ overlay$$1 = this.getLastAttachedOverlay(); return contextMenuContent.overlay === overlay$$1; }; ContextMenuService.decorators = [ { type: core.Injectable }, ]; /** @nocollapse */ ContextMenuService.ctorParameters = function () { return [ { type: overlay.Overlay }, { type: overlay.ScrollStrategyOptions } ]; }; return ContextMenuService; }()); var ContextMenuAttachDirective = (function () { function ContextMenuAttachDirective(contextMenuService) { this.contextMenuService = contextMenuService; } /** * @param {?} event * @return {?} */ ContextMenuAttachDirective.prototype.onContextMenu = /** * @param {?} event * @return {?} */ function (event) { if (!this.contextMenu.disabled) { this.contextMenuService.show.next({ contextMenu: this.contextMenu, event: event, item: this.contextMenuSubject, }); event.preventDefault(); event.stopPropagation(); } }; ContextMenuAttachDirective.decorators = [ { type: core.Directive, args: [{ selector: '[contextMenu]', },] }, ]; /** @nocollapse */ ContextMenuAttachDirective.ctorParameters = function () { return [ { type: ContextMenuService } ]; }; ContextMenuAttachDirective.propDecorators = { contextMenuSubject: [{ type: core.Input }], contextMenu: [{ type: core.Input }], onContextMenu: [{ type: core.HostListener, args: ['contextmenu', ['$event'],] }] }; return ContextMenuAttachDirective; }()); /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ var ContextMenuItemDirective = (function () { function ContextMenuItemDirective(template, elementRef) { this.template = template; this.elementRef = elementRef; this.divider = false; this.enabled = true; this.passive = false; this.visible = true; this.execute = new core.EventEmitter(); this.isActive = false; this.isActiveParent = false; } Object.defineProperty(ContextMenuItemDirective.prototype, "disabled", { get: /** * @return {?} */ function () { return this.passive || this.divider || !this.evaluateIfFunction(this.enabled, this.currentItem); }, enumerable: true, configurable: true }); /** * @param {?} value * @param {?} item * @return {?} */ ContextMenuItemDirective.prototype.evaluateIfFunction = /** * @param {?} value * @param {?} item * @return {?} */ function (value, item) { if (value instanceof Function) { return value(item); } return value; }; /** * @return {?} */ ContextMenuItemDirective.prototype.setActiveStyles = /** * @return {?} */ function () { this.isActive = true; }; /** * @return {?} */ ContextMenuItemDirective.prototype.setInactiveStyles = /** * @return {?} */ function () { this.isActive = false; }; /** * @return {?} */ ContextMenuItemDirective.prototype.setActiveParentStyles = /** * @return {?} */ function () { this.isActiveParent = true; }; /** * @return {?} */ ContextMenuItemDirective.prototype.setInActiveParentStyles = /** * @return {?} */ function () { this.isActiveParent = false; }; /** * @param {?} item * @param {?=} $event * @return {?} */ ContextMenuItemDirective.prototype.triggerExecute = /** * @param {?} item * @param {?=} $event * @return {?} */ function (item, $event) { if (!this.evaluateIfFunction(this.enabled, item)) { return; } this.execute.emit({ event: $event, item: item }); }; ContextMenuItemDirective.decorators = [ { type: core.Directive, args: [{ /* tslint:disable:directive-selector-type */ selector: '[contextMenuItem]', },] }, ]; /** @nocollapse */ ContextMenuItemDirective.ctorParameters = function () { return [ { type: core.TemplateRef }, { type: core.ElementRef } ]; }; ContextMenuItemDirective.propDecorators = { subMenu: [{ type: core.Input }], divider: [{ type: core.Input }], enabled: [{ type: core.Input }], passive: [{ type: core.Input }], visible: [{ type: core.Input }], execute: [{ type: core.Output }] }; return ContextMenuItemDirective; }()); /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ var ContextMenuComponent = (function () { function ContextMenuComponent(_contextMenuService, changeDetector, elementRef, options) { var _this = this; this._contextMenuService = _contextMenuService; this.changeDetector = changeDetector; this.elementRef = elementRef; this.options = options; this.menuClass = ""; this.autoFocus = false; this.useBootstrap4 = false; this.highlightParentItems = false; this.disabled = false; this.close = new core.EventEmitter(); this.open = new core.EventEmitter(); this.visibleMenuItems = []; this.links = []; this.subscription = new rxjs.Subscription(); if (options) { this.autoFocus = options.autoFocus; this.useBootstrap4 = options.useBootstrap4; this.highlightParentItems = options.highlightParentItems; } this.subscription.add(_contextMenuService.show.subscribe(function (menuEvent) { _this.onMenuEvent(menuEvent); })); } /** * @return {?} */ ContextMenuComponent.prototype.ngOnDestroy = /** * @return {?} */ function () { this.subscription.unsubscribe(); }; /** * @param {?} menuEvent * @return {?} */ ContextMenuComponent.prototype.onMenuEvent = /** * @param {?} menuEvent * @return {?} */ function (menuEvent) { var _this = this; if (this.disabled) { return; } var contextMenu = menuEvent.contextMenu, event = menuEvent.event, item = menuEvent.item; if (contextMenu && contextMenu !== this) { return; } this.event = event; this.item = item; this.setVisibleMenuItems(); this._contextMenuService.openContextMenu(__assign({}, menuEvent, { menuItems: this.visibleMenuItems, menuClass: this.menuClass })); this._contextMenuService.close.asObservable().pipe(operators.first()).subscribe(function (closeEvent) { return _this.close.emit(closeEvent); }); this.open.next(menuEvent); }; /** * @param {?} menuItem * @return {?} */ ContextMenuComponent.prototype.isMenuItemVisible = /** * @param {?} menuItem * @return {?} */ function (menuItem) { return this.evaluateIfFunction(menuItem.visible); }; /** * @return {?} */ ContextMenuComponent.prototype.setVisibleMenuItems = /** * @return {?} */ function () { var _this = this; this.visibleMenuItems = this.menuItems.filter(function (menuItem) { return _this.isMenuItemVisible(menuItem); }); }; /** * @param {?} value * @return {?} */ ContextMenuComponent.prototype.evaluateIfFunction = /** * @param {?} value * @return {?} */ function (value) { if (value instanceof Function) { return value(this.item); } return value; }; ContextMenuComponent.decorators = [ { type: core.Component, args: [{ encapsulation: core.ViewEncapsulation.None, selector: 'context-menu', styles: ["\n .cdk-overlay-container {\n position: fixed;\n z-index: 1000;\n pointer-events: none;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n }\n .ngx-contextmenu.cdk-overlay-pane {\n position: absolute;\n pointer-events: auto;\n box-sizing: border-box;\n }\n"], template: " ", },] }, ]; /** @nocollapse */ ContextMenuComponent.ctorParameters = function () { return [ { type: ContextMenuService }, { type: core.ChangeDetectorRef }, { type: core.ElementRef }, { type: undefined, decorators: [{ type: core.Optional }, { type: core.Inject, args: [CONTEXT_MENU_OPTIONS,] }] } ]; }; ContextMenuComponent.propDecorators = { menuClass: [{ type: core.Input }], autoFocus: [{ type: core.Input }], useBootstrap4: [{ type: core.Input }], highlightParentItems: [{ type: core.Input }], disabled: [{ type: core.Input }], close: [{ type: core.Output }], open: [{ type: core.Output }], menuItems: [{ type: core.ContentChildren, args: [ContextMenuItemDirective,] }], menuElement: [{ type: core.ViewChild, args: ['menu',] }] }; return ContextMenuComponent; }()); /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ var ContextMenuModule = (function () { function ContextMenuModule() { } /** * @param {?=} options * @return {?} */ ContextMenuModule.forRoot = /** * @param {?=} options * @return {?} */ function (options) { return { ngModule: ContextMenuModule, providers: [ ContextMenuService, { provide: CONTEXT_MENU_OPTIONS, useValue: options, }, ], }; }; ContextMenuModule.decorators = [ { type: core.NgModule, args: [{ declarations: [ ContextMenuAttachDirective, ContextMenuComponent, ContextMenuContentComponent, ContextMenuItemDirective, ], entryComponents: [ ContextMenuContentComponent, ], exports: [ ContextMenuAttachDirective, ContextMenuComponent, ContextMenuItemDirective, ], imports: [ common.CommonModule, overlay.OverlayModule, ], },] }, ]; return ContextMenuModule; }()); /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ exports.ContextMenuModule = ContextMenuModule; exports.ContextMenuComponent = ContextMenuComponent; exports.ContextMenuService = ContextMenuService; exports.ɵa = ContextMenuAttachDirective; exports.ɵb = ContextMenuItemDirective; exports.ɵc = CONTEXT_MENU_OPTIONS; exports.ɵd = ContextMenuContentComponent; Object.defineProperty(exports, '__esModule', { value: true }); }))); //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LWNvbnRleHRtZW51LnVtZC5qcy5tYXAiLCJzb3VyY2VzIjpbbnVsbCwibmc6Ly9uZ3gtY29udGV4dG1lbnUvbGliL2NvbnRleHRNZW51LnRva2Vucy50cyIsIm5nOi8vbmd4LWNvbnRleHRtZW51L2xpYi9jb250ZXh0TWVudUNvbnRlbnQuY29tcG9uZW50LnRzIiwibmc6Ly9uZ3gtY29udGV4dG1lbnUvbGliL2NvbnRleHRNZW51LnNlcnZpY2UudHMiLCJuZzovL25neC1jb250ZXh0bWVudS9saWIvY29udGV4dE1lbnUuYXR0YWNoLmRpcmVjdGl2ZS50cyIsIm5nOi8vbmd4LWNvbnRleHRtZW51L2xpYi9jb250ZXh0TWVudS5pdGVtLmRpcmVjdGl2ZS50cyIsIm5nOi8vbmd4LWNvbnRleHRtZW51L2xpYi9jb250ZXh0TWVudS5jb21wb25lbnQudHMiLCJuZzovL25neC1jb250ZXh0bWVudS9saWIvbmd4LWNvbnRleHRtZW51LnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qISAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxyXG5Db3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cclxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTsgeW91IG1heSBub3QgdXNlXHJcbnRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlXHJcbkxpY2Vuc2UgYXQgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXHJcblxyXG5USElTIENPREUgSVMgUFJPVklERUQgT04gQU4gKkFTIElTKiBCQVNJUywgV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZXHJcbktJTkQsIEVJVEhFUiBFWFBSRVNTIE9SIElNUExJRUQsIElOQ0xVRElORyBXSVRIT1VUIExJTUlUQVRJT04gQU5ZIElNUExJRURcclxuV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIFRJVExFLCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSxcclxuTUVSQ0hBTlRBQkxJVFkgT1IgTk9OLUlORlJJTkdFTUVOVC5cclxuXHJcblNlZSB0aGUgQXBhY2hlIFZlcnNpb24gMi4wIExpY2Vuc2UgZm9yIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9uc1xyXG5hbmQgbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXHJcbioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqICovXHJcbi8qIGdsb2JhbCBSZWZsZWN0LCBQcm9taXNlICovXHJcblxyXG52YXIgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxyXG4gICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxyXG4gICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19leHRlbmRzKGQsIGIpIHtcclxuICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XHJcbiAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cclxuICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcclxufVxyXG5cclxuZXhwb3J0IHZhciBfX2Fzc2lnbiA9IE9iamVjdC5hc3NpZ24gfHwgZnVuY3Rpb24gX19hc3NpZ24odCkge1xyXG4gICAgZm9yICh2YXIgcywgaSA9IDEsIG4gPSBhcmd1bWVudHMubGVuZ3RoOyBpIDwgbjsgaSsrKSB7XHJcbiAgICAgICAgcyA9IGFyZ3VtZW50c1tpXTtcclxuICAgICAgICBmb3IgKHZhciBwIGluIHMpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwocywgcCkpIHRbcF0gPSBzW3BdO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIHQ7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX3Jlc3QocywgZSkge1xyXG4gICAgdmFyIHQgPSB7fTtcclxuICAgIGZvciAodmFyIHAgaW4gcykgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChzLCBwKSAmJiBlLmluZGV4T2YocCkgPCAwKVxyXG4gICAgICAgIHRbcF0gPSBzW3BdO1xyXG4gICAgaWYgKHMgIT0gbnVsbCAmJiB0eXBlb2YgT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyA9PT0gXCJmdW5jdGlvblwiKVxyXG4gICAgICAgIGZvciAodmFyIGkgPSAwLCBwID0gT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyhzKTsgaSA8IHAubGVuZ3RoOyBpKyspIGlmIChlLmluZGV4T2YocFtpXSkgPCAwKVxyXG4gICAgICAgICAgICB0W3BbaV1dID0gc1twW2ldXTtcclxuICAgIHJldHVybiB0O1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYykge1xyXG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcclxuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5kZWNvcmF0ZSA9PT0gXCJmdW5jdGlvblwiKSByID0gUmVmbGVjdC5kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYyk7XHJcbiAgICBlbHNlIGZvciAodmFyIGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSBpZiAoZCA9IGRlY29yYXRvcnNbaV0pIHIgPSAoYyA8IDMgPyBkKHIpIDogYyA+IDMgPyBkKHRhcmdldCwga2V5LCByKSA6IGQodGFyZ2V0LCBrZXkpKSB8fCByO1xyXG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fcGFyYW0ocGFyYW1JbmRleCwgZGVjb3JhdG9yKSB7XHJcbiAgICByZXR1cm4gZnVuY3Rpb24gKHRhcmdldCwga2V5KSB7IGRlY29yYXRvcih0YXJnZXQsIGtleSwgcGFyYW1JbmRleCk7IH1cclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fbWV0YWRhdGEobWV0YWRhdGFLZXksIG1ldGFkYXRhVmFsdWUpIHtcclxuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5tZXRhZGF0YSA9PT0gXCJmdW5jdGlvblwiKSByZXR1cm4gUmVmbGVjdC5tZXRhZGF0YShtZXRhZGF0YUtleSwgbWV0YWRhdGFWYWx1ZSk7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2F3YWl0ZXIodGhpc0FyZywgX2FyZ3VtZW50cywgUCwgZ2VuZXJhdG9yKSB7XHJcbiAgICByZXR1cm4gbmV3IChQIHx8IChQID0gUHJvbWlzZSkpKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcclxuICAgICAgICBmdW5jdGlvbiBmdWxmaWxsZWQodmFsdWUpIHsgdHJ5IHsgc3RlcChnZW5lcmF0b3IubmV4dCh2YWx1ZSkpOyB9IGNhdGNoIChlKSB7IHJlamVjdChlKTsgfSB9XHJcbiAgICAgICAgZnVuY3Rpb24gcmVqZWN0ZWQodmFsdWUpIHsgdHJ5IHsgc3RlcChnZW5lcmF0b3JbXCJ0aHJvd1wiXSh2YWx1ZSkpOyB9IGNhdGNoIChlKSB7IHJlamVjdChlKTsgfSB9XHJcbiAgICAgICAgZnVuY3Rpb24gc3RlcChyZXN1bHQpIHsgcmVzdWx0LmRvbmUgPyByZXNvbHZlKHJlc3VsdC52YWx1ZSkgOiBuZXcgUChmdW5jdGlvbiAocmVzb2x2ZSkgeyByZXNvbHZlKHJlc3VsdC52YWx1ZSk7IH0pLnRoZW4oZnVsZmlsbGVkLCByZWplY3RlZCk7IH1cclxuICAgICAgICBzdGVwKChnZW5lcmF0b3IgPSBnZW5lcmF0b3IuYXBwbHkodGhpc0FyZywgX2FyZ3VtZW50cyB8fCBbXSkpLm5leHQoKSk7XHJcbiAgICB9KTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fZ2VuZXJhdG9yKHRoaXNBcmcsIGJvZHkpIHtcclxuICAgIHZhciBfID0geyBsYWJlbDogMCwgc2VudDogZnVuY3Rpb24oKSB7IGlmICh0WzBdICYgMSkgdGhyb3cgdFsxXTsgcmV0dXJuIHRbMV07IH0sIHRyeXM6IFtdLCBvcHM6IFtdIH0sIGYsIHksIHQsIGc7XHJcbiAgICByZXR1cm4gZyA9IHsgbmV4dDogdmVyYigwKSwgXCJ0aHJvd1wiOiB2ZXJiKDEpLCBcInJldHVyblwiOiB2ZXJiKDIpIH0sIHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiAoZ1tTeW1ib2wuaXRlcmF0b3JdID0gZnVuY3Rpb24oKSB7IHJldHVybiB0aGlzOyB9KSwgZztcclxuICAgIGZ1bmN0aW9uIHZlcmIobikgeyByZXR1cm4gZnVuY3Rpb24gKHYpIHsgcmV0dXJuIHN0ZXAoW24sIHZdKTsgfTsgfVxyXG4gICAgZnVuY3Rpb24gc3RlcChvcCkge1xyXG4gICAgICAgIGlmIChmKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiR2VuZXJhdG9yIGlzIGFscmVhZHkgZXhlY3V0aW5nLlwiKTtcclxuICAgICAgICB3aGlsZSAoXykgdHJ5IHtcclxuICAgICAgICAgICAgaWYgKGYgPSAxLCB5ICYmICh0ID0gb3BbMF0gJiAyID8geVtcInJldHVyblwiXSA6IG9wWzBdID8geVtcInRocm93XCJdIHx8ICgodCA9IHlbXCJyZXR1cm5cIl0pICYmIHQuY2FsbCh5KSwgMCkgOiB5Lm5leHQpICYmICEodCA9IHQuY2FsbCh5LCBvcFsxXSkpLmRvbmUpIHJldHVybiB0O1xyXG4gICAgICAgICAgICBpZiAoeSA9IDAsIHQpIG9wID0gW29wWzBdICYgMiwgdC52YWx1ZV07XHJcbiAgICAgICAgICAgIHN3aXRjaCAob3BbMF0pIHtcclxuICAgICAgICAgICAgICAgIGNhc2UgMDogY2FzZSAxOiB0ID0gb3A7IGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgY2FzZSA0OiBfLmxhYmVsKys7IHJldHVybiB7IHZhbHVlOiBvcFsxXSwgZG9uZTogZmFsc2UgfTtcclxuICAgICAgICAgICAgICAgIGNhc2UgNTogXy5sYWJlbCsrOyB5ID0gb3BbMV07IG9wID0gWzBdOyBjb250aW51ZTtcclxuICAgICAgICAgICAgICAgIGNhc2UgNzogb3AgPSBfLm9wcy5wb3AoKTsgXy50cnlzLnBvcCgpOyBjb250aW51ZTtcclxuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEodCA9IF8udHJ5cywgdCA9IHQubGVuZ3RoID4gMCAmJiB0W3QubGVuZ3RoIC0gMV0pICYmIChvcFswXSA9PT0gNiB8fCBvcFswXSA9PT0gMikpIHsgXyA9IDA7IGNvbnRpbnVlOyB9XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wWzBdID09PSAzICYmICghdCB8fCAob3BbMV0gPiB0WzBdICYmIG9wWzFdIDwgdFszXSkpKSB7IF8ubGFiZWwgPSBvcFsxXTsgYnJlYWs7IH1cclxuICAgICAgICAgICAgICAgICAgICBpZiAob3BbMF0gPT09IDYgJiYgXy5sYWJlbCA8IHRbMV0pIHsgXy5sYWJlbCA9IHRbMV07IHQgPSBvcDsgYnJlYWs7IH1cclxuICAgICAgICAgICAgICAgICAgICBpZiAodCAmJiBfLmxhYmVsIDwgdFsyXSkgeyBfLmxhYmVsID0gdFsyXTsgXy5vcHMucHVzaChvcCk7IGJyZWFrOyB9XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRbMl0pIF8ub3BzLnBvcCgpO1xyXG4gICAgICAgICAgICAgICAgICAgIF8udHJ5cy5wb3AoKTsgY29udGludWU7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgb3AgPSBib2R5LmNhbGwodGhpc0FyZywgXyk7XHJcbiAgICAgICAgfSBjYXRjaCAoZSkgeyBvcCA9IFs2LCBlXTsgeSA9IDA7IH0gZmluYWxseSB7IGYgPSB0ID0gMDsgfVxyXG4gICAgICAgIGlmIChvcFswXSAmIDUpIHRocm93IG9wWzFdOyByZXR1cm4geyB2YWx1ZTogb3BbMF0gPyBvcFsxXSA6IHZvaWQgMCwgZG9uZTogdHJ1ZSB9O1xyXG4gICAgfVxyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19leHBvcnRTdGFyKG0sIGV4cG9ydHMpIHtcclxuICAgIGZvciAodmFyIHAgaW4gbSkgaWYgKCFleHBvcnRzLmhhc093blByb3BlcnR5KHApKSBleHBvcnRzW3BdID0gbVtwXTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fdmFsdWVzKG8pIHtcclxuICAgIHZhciBtID0gdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIG9bU3ltYm9sLml0ZXJhdG9yXSwgaSA9IDA7XHJcbiAgICBpZiAobSkgcmV0dXJuIG0uY2FsbChvKTtcclxuICAgIHJldHVybiB7XHJcbiAgICAgICAgbmV4dDogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICBpZiAobyAmJiBpID49IG8ubGVuZ3RoKSBvID0gdm9pZCAwO1xyXG4gICAgICAgICAgICByZXR1cm4geyB2YWx1ZTogbyAmJiBvW2krK10sIGRvbmU6ICFvIH07XHJcbiAgICAgICAgfVxyXG4gICAgfTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fcmVhZChvLCBuKSB7XHJcbiAgICB2YXIgbSA9IHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiBvW1N5bWJvbC5pdGVyYXRvcl07XHJcbiAgICBpZiAoIW0pIHJldHVybiBvO1xyXG4gICAgdmFyIGkgPSBtLmNhbGwobyksIHIsIGFyID0gW10sIGU7XHJcbiAgICB0cnkge1xyXG4gICAgICAgIHdoaWxlICgobiA9PT0gdm9pZCAwIHx8IG4tLSA+IDApICYmICEociA9IGkubmV4dCgpKS5kb25lKSBhci5wdXNoKHIudmFsdWUpO1xyXG4gICAgfVxyXG4gICAgY2F0Y2ggKGVycm9yKSB7IGUgPSB7IGVycm9yOiBlcnJvciB9OyB9XHJcbiAgICBmaW5hbGx5IHtcclxuICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICBpZiAociAmJiAhci5kb25lICYmIChtID0gaVtcInJldHVyblwiXSkpIG0uY2FsbChpKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgZmluYWxseSB7IGlmIChlKSB0aHJvdyBlLmVycm9yOyB9XHJcbiAgICB9XHJcbiAgICByZXR1cm4gYXI7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX3NwcmVhZCgpIHtcclxuICAgIGZvciAodmFyIGFyID0gW10sIGkgPSAwOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKVxyXG4gICAgICAgIGFyID0gYXIuY29uY2F0KF9fcmVhZChhcmd1bWVudHNbaV0pKTtcclxuICAgIHJldHVybiBhcjtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fYXdhaXQodikge1xyXG4gICAgcmV0dXJuIHRoaXMgaW5zdGFuY2VvZiBfX2F3YWl0ID8gKHRoaXMudiA9IHYsIHRoaXMpIDogbmV3IF9fYXdhaXQodik7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2FzeW5jR2VuZXJhdG9yKHRoaXNBcmcsIF9hcmd1bWVudHMsIGdlbmVyYXRvcikge1xyXG4gICAgaWYgKCFTeW1ib2wuYXN5bmNJdGVyYXRvcikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlN5bWJvbC5hc3luY0l0ZXJhdG9yIGlzIG5vdCBkZWZpbmVkLlwiKTtcclxuICAgIHZhciBnID0gZ2VuZXJhdG9yLmFwcGx5KHRoaXNBcmcsIF9hcmd1bWVudHMgfHwgW10pLCBpLCBxID0gW107XHJcbiAgICByZXR1cm4gaSA9IHt9LCB2ZXJiKFwibmV4dFwiKSwgdmVyYihcInRocm93XCIpLCB2ZXJiKFwicmV0dXJuXCIpLCBpW1N5bWJvbC5hc3luY0l0ZXJhdG9yXSA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXM7IH0sIGk7XHJcbiAgICBmdW5jdGlvbiB2ZXJiKG4pIHsgaWYgKGdbbl0pIGlbbl0gPSBmdW5jdGlvbiAodikgeyByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKGEsIGIpIHsgcS5wdXNoKFtuLCB2LCBhLCBiXSkgPiAxIHx8IHJlc3VtZShuLCB2KTsgfSk7IH07IH1cclxuICAgIGZ1bmN0aW9uIHJlc3VtZShuLCB2KSB7IHRyeSB7IHN0ZXAoZ1tuXSh2KSk7IH0gY2F0Y2ggKGUpIHsgc2V0dGxlKHFbMF1bM10sIGUpOyB9IH1cclxuICAgIGZ1bmN0a