truly-ui
Version:
Web Components for Desktop Applications.
179 lines (177 loc) • 28 kB
JavaScript
/*
MIT License
Copyright (c) 2019 Temainfo Software
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
import { Component, ContentChildren, forwardRef, Input, ViewChild, } from '@angular/core';
import { TlTab } from './tab/tab';
import { TlModal } from '../modal/modal';
import { KeyEvent } from '../core/enums/key-events';
import * as i0 from "@angular/core";
import * as i1 from "@angular/common";
export class TlTabControl {
constructor(renderer) {
this.renderer = renderer;
this.height = 'auto';
this.tabsHeight = '25px';
this.widthSeparator = '';
this.widthTabs = 0;
this.widthWrapper = 0;
this.topPosition = 0;
}
ngAfterContentInit() {
const selectedTab = this.tabs.find(tab => tab.selected);
if (!selectedTab && this.tabs.first) {
this.tabs.first.selected = true;
}
this.setTabProperties();
this.getElementList();
}
ngAfterViewInit() {
this.getWrapperWidth();
this.getTabsComponent();
}
getTabsComponent() {
this.tabs.forEach((item, index) => {
this.listenLastElementTab(item.lastComponent, index);
this.listenPreviousElementTab(item.firstComponent, index);
});
}
listenLastElementTab(last, index) {
if (last) {
this.renderer.listen(last, 'keydown', ($event) => {
this.handleKeyDownLastElementTab($event, index);
});
}
}
listenPreviousElementTab(first, index) {
if (first) {
this.renderer.listen(first, 'keydown', ($event) => {
this.handleKeyDownFirstElementTab($event, index);
});
}
}
handleKeyDownLastElementTab($event, index) {
if ([KeyEvent.TAB, KeyEvent.ENTER, KeyEvent.ARROWDOWN].indexOf($event.code) >= 0 && (!$event.shiftKey)) {
this.nextTabAndElement(index);
}
if (($event.code === KeyEvent.TAB) && ($event.ctrlKey)) {
this.nextTabAndElement(index);
}
}
handleKeyDownFirstElementTab($event, index) {
if ([KeyEvent.ARROWUP].indexOf($event.code) >= 0) {
this.previousTabAndElement(index);
}
if (($event.code === KeyEvent.TAB) && ($event.shiftKey)) {
this.previousTabAndElement(index);
}
}
nextTabAndElement(index) {
if (this.tabs.toArray()[index + 1]) {
this.resetTabsSelected();
this.tabs.toArray()[index + 1].selected = true;
this.setFocusNext(index + 1);
}
}
previousTabAndElement(index) {
if (this.tabs.toArray()[index - 1]) {
this.resetTabsSelected();
this.tabs.toArray()[index - 1].selected = true;
this.setFocusPrevious(index - 1);
}
}
selectTab(tab) {
this.tabs.forEach(item => item.selected = false);
tab.selected = true;
}
getWrapperWidth() {
this.widthWrapper = Math.round(this.wrapper.nativeElement.offsetWidth);
}
getElementList() {
setTimeout(() => {
const templateChildren = this.tabsHeader.elementRef.nativeElement.parentElement.children;
for (let element = 0; element < templateChildren.length; element++) {
if (templateChildren[element].localName === 'ul') {
this.elementListTabs = templateChildren[element].children;
}
}
this.setWidthSeparator();
}, 1);
}
setFocusNext(index) {
setTimeout(() => {
this.tabs.toArray()[index].firstComponent.focus();
}, 1);
}
setFocusPrevious(index) {
setTimeout(() => {
this.tabs.toArray()[index].lastComponent.focus();
}, 1);
}
setTabProperties() {
this.tabs.forEach((item) => {
item.height = this.height;
});
}
setWidthSeparator() {
this.widthTabs = 0;
for (let i = 0; i < this.elementListTabs.length; i++) {
this.widthTabs = this.widthTabs + Number(this.elementListTabs[i].offsetWidth);
}
this.topPosition = (this.line.nativeElement.offsetHeight / 2) - 1;
this.widthSeparator = 'calc(100% - ' + (this.widthTabs) + 'px' + ' )';
}
resetTabsSelected() {
this.tabs.forEach((item) => {
item.selected = false;
});
}
get tabsContext() {
return {
tabs: this.tabs
};
}
}
/** @nocollapse */ TlTabControl.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TlTabControl, deps: [{ token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Component });
/** @nocollapse */ TlTabControl.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: TlTabControl, selector: "tl-tabcontrol", inputs: { height: "height", tabsHeight: "tabsHeight" }, queries: [{ propertyName: "tabs", predicate: i0.forwardRef(function () { return TlTab; }) }], viewQueries: [{ propertyName: "tabsHeader", first: true, predicate: ["tabsHeader"], descendants: true, static: true }, { propertyName: "wrapper", first: true, predicate: ["wrapperTab"], descendants: true, static: true }, { propertyName: "line", first: true, predicate: ["line"], descendants: true, static: true }, { propertyName: "modal", first: true, predicate: i0.forwardRef(function () { return TlModal; }), descendants: true, static: true }], ngImport: i0, template: " <div class=\"wrapper-tabcontrol\" #wrapperTab>\n <ng-template #tabsHeader let-tabs=\"tabs\">\n <ul class=\"tab-panel-buttons\" [style.display]=\"tabs ? 'block' : 'none'\">\n <li *ngFor=\"let tab of tabs\"\n [ngStyle]=\"{'height': tabsHeight, 'line-height': tabsHeight}\"\n [ngClass]=\"{'tab-selected': tab.selected}\" (click)=\"selectTab(tab)\">\n {{tab.title}}\n </li>\n </ul>\n </ng-template>\n\n <div class=\"line-separator\"\n #line\n [style.width]=\"widthSeparator\"\n [style.top]=\"topPosition - 1 + 'px'\"\n [style.left]=\"(widthTabs) +'px'\">\n </div>\n\n <ng-container *ngTemplateOutlet=\"tabsHeader; context: tabsContext\"></ng-container>\n <ng-content></ng-content>\n </div>\n", styles: ["*{box-sizing:border-box}.wrapper-tabcontrol{position:relative;height:100%;width:100%;overflow:hidden;-webkit-user-select:none;user-select:none;box-sizing:border-box}.wrapper-tabcontrol>.line-separator{left:0;position:absolute;box-sizing:border-box;font-size:12px;height:26px;line-height:26px;overflow:hidden;width:100%}.wrapper-tabcontrol>.line-separator:after{display:inline-block;width:100%;content:\".\";font-size:0;color:transparent;height:1px;top:9px;position:relative}.wrapper-tabcontrol>.tab-panel-buttons{box-sizing:border-box;margin:0;padding:0}.wrapper-tabcontrol>.tab-panel-buttons li{display:inline-block;font-family:Segoe UI,Lato,\"sans-serif\",Arial;font-size:1em;min-width:70px;text-align:center;padding:0 10px;line-height:25px;height:25px;box-sizing:border-box}.wrapper-tabcontrol>.tab-panel-buttons li:hover{cursor:pointer}.selected{border-bottom:0!important}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TlTabControl, decorators: [{
type: Component,
args: [{ selector: 'tl-tabcontrol', template: " <div class=\"wrapper-tabcontrol\" #wrapperTab>\n <ng-template #tabsHeader let-tabs=\"tabs\">\n <ul class=\"tab-panel-buttons\" [style.display]=\"tabs ? 'block' : 'none'\">\n <li *ngFor=\"let tab of tabs\"\n [ngStyle]=\"{'height': tabsHeight, 'line-height': tabsHeight}\"\n [ngClass]=\"{'tab-selected': tab.selected}\" (click)=\"selectTab(tab)\">\n {{tab.title}}\n </li>\n </ul>\n </ng-template>\n\n <div class=\"line-separator\"\n #line\n [style.width]=\"widthSeparator\"\n [style.top]=\"topPosition - 1 + 'px'\"\n [style.left]=\"(widthTabs) +'px'\">\n </div>\n\n <ng-container *ngTemplateOutlet=\"tabsHeader; context: tabsContext\"></ng-container>\n <ng-content></ng-content>\n </div>\n", styles: ["*{box-sizing:border-box}.wrapper-tabcontrol{position:relative;height:100%;width:100%;overflow:hidden;-webkit-user-select:none;user-select:none;box-sizing:border-box}.wrapper-tabcontrol>.line-separator{left:0;position:absolute;box-sizing:border-box;font-size:12px;height:26px;line-height:26px;overflow:hidden;width:100%}.wrapper-tabcontrol>.line-separator:after{display:inline-block;width:100%;content:\".\";font-size:0;color:transparent;height:1px;top:9px;position:relative}.wrapper-tabcontrol>.tab-panel-buttons{box-sizing:border-box;margin:0;padding:0}.wrapper-tabcontrol>.tab-panel-buttons li{display:inline-block;font-family:Segoe UI,Lato,\"sans-serif\",Arial;font-size:1em;min-width:70px;text-align:center;padding:0 10px;line-height:25px;height:25px;box-sizing:border-box}.wrapper-tabcontrol>.tab-panel-buttons li:hover{cursor:pointer}.selected{border-bottom:0!important}\n"] }]
}], ctorParameters: function () { return [{ type: i0.Renderer2 }]; }, propDecorators: { height: [{
type: Input,
args: ['height']
}], tabsHeight: [{
type: Input,
args: ['tabsHeight']
}], tabsHeader: [{
type: ViewChild,
args: ['tabsHeader', { static: true }]
}], wrapper: [{
type: ViewChild,
args: ['wrapperTab', { static: true }]
}], line: [{
type: ViewChild,
args: ['line', { static: true }]
}], tabs: [{
type: ContentChildren,
args: [forwardRef(() => TlTab)]
}], modal: [{
type: ViewChild,
args: [forwardRef(() => TlModal), { static: true }]
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFiY29udHJvbC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL3RydWx5LXVpL3NyYy9jb21wb25lbnRzL3RhYmNvbnRyb2wvdGFiY29udHJvbC50cyIsIi4uLy4uLy4uLy4uL3Byb2plY3RzL3RydWx5LXVpL3NyYy9jb21wb25lbnRzL3RhYmNvbnRyb2wvdGFiY29udHJvbC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQW9CRztBQUNILE9BQU8sRUFDTCxTQUFTLEVBQUUsZUFBZSxFQUFhLFVBQVUsRUFBRSxLQUFLLEVBQW9CLFNBQVMsR0FDdEYsTUFBTSxlQUFlLENBQUM7QUFFdkIsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUNsQyxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDekMsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLDBCQUEwQixDQUFDOzs7QUFRcEQsTUFBTSxPQUFPLFlBQVk7SUEwQnJCLFlBQW9CLFFBQW1CO1FBQW5CLGFBQVEsR0FBUixRQUFRLENBQVc7UUF4QnBCLFdBQU0sR0FBRyxNQUFNLENBQUM7UUFFWixlQUFVLEdBQUcsTUFBTSxDQUFDO1FBY3BDLG1CQUFjLEdBQUcsRUFBRSxDQUFDO1FBRXBCLGNBQVMsR0FBRyxDQUFDLENBQUM7UUFFZCxpQkFBWSxHQUFHLENBQUMsQ0FBQztRQUVqQixnQkFBVyxHQUFHLENBQUMsQ0FBQztJQUVvQixDQUFDO0lBRTVDLGtCQUFrQjtRQUNoQixNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUN4RCxJQUFJLENBQUMsV0FBVyxJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFO1lBQ25DLElBQUksQ0FBQyxJQUFJLENBQUMs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cmlnaHQgKGMpIDIwMTkgVGVtYWluZm8gU29mdHdhcmVcblxuIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhIGNvcHlcbiBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZSBcIlNvZnR3YXJlXCIpLCB0byBkZWFsXG4gaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0c1xuIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCwgZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yIHNlbGxcbiBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXNcbiBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOlxuIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkIGluIGFsbFxuIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXG4gVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUlxuIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZLFxuIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRVxuIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVJcbiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SIE9USEVSV0lTRSwgQVJJU0lORyBGUk9NLFxuIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU4gVEhFXG4gU09GVFdBUkUuXG4gKi9cbmltcG9ydCB7XG4gIENvbXBvbmVudCwgQ29udGVudENoaWxkcmVuLCBRdWVyeUxpc3QsIGZvcndhcmRSZWYsIElucHV0LCBBZnRlckNvbnRlbnRJbml0LCBWaWV3Q2hpbGQsIEFmdGVyVmlld0luaXQsIFJlbmRlcmVyMixcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5cbmltcG9ydCB7IFRsVGFiIH0gZnJvbSAnLi90YWIvdGFiJztcbmltcG9ydCB7IFRsTW9kYWwgfSBmcm9tICcuLi9tb2RhbC9tb2RhbCc7XG5pbXBvcnQgeyBLZXlFdmVudCB9IGZyb20gJy4uL2NvcmUvZW51bXMva2V5LWV2ZW50cyc7XG5pbXBvcnQge0ZpeGVkUG9zaXRpb25EaXJlY3RpdmV9IGZyb20gJy4uL21pc2MvZml4ZWQtcG9zaXRpb24uZGlyZWN0aXZlJztcblxuQENvbXBvbmVudCgge1xuICAgIHNlbGVjdG9yOiAndGwtdGFiY29udHJvbCcsXG4gICAgdGVtcGxhdGVVcmw6ICcuL3RhYmNvbnRyb2wuaHRtbCcsXG4gICAgc3R5bGVVcmxzOiBbICcuL3RhYmNvbnRyb2wuc2NzcycgXVxufSApXG5leHBvcnQgY2xhc3MgVGxUYWJDb250cm9sIGltcGxlbWVudHMgQWZ0ZXJDb250ZW50SW5pdCwgQWZ0ZXJWaWV3SW5pdCB7XG5cbiAgICBASW5wdXQoICdoZWlnaHQnICkgaGVpZ2h0ID0gJ2F1dG8nO1xuXG4gICAgQElucHV0KCAndGFic0hlaWdodCcgKSB0YWJzSGVpZ2h0ID0gJzI1cHgnO1xuXG4gICAgQFZpZXdDaGlsZCgndGFic0hlYWRlcicsIHtzdGF0aWM6IHRydWV9KSB0YWJzSGVhZGVyO1xuXG4gICAgQFZpZXdDaGlsZCgnd3JhcHBlclRhYicsIHtzdGF0aWM6IHRydWV9KSB3cmFwcGVyO1xuXG4gICAgQFZpZXdDaGlsZCgnbGluZScsIHtzdGF0aWM6IHRydWV9KSBsaW5lO1xuXG4gICAgQENvbnRlbnRDaGlsZHJlbiggZm9yd2FyZFJlZigoKSA9PiBUbFRhYiApKSB0YWJzOiBRdWVyeUxpc3Q8VGxUYWI+O1xuXG4gICAgQFZpZXdDaGlsZCggZm9yd2FyZFJlZigoKSA9PiBUbE1vZGFsICksIHtzdGF0aWM6IHRydWV9KSBtb2RhbDogUXVlcnlMaXN0PFRsTW9kYWw+O1xuXG4gICAgcHJpdmF0ZSBlbGVtZW50TGlzdFRhYnM7XG5cbiAgICBwdWJsaWMgd2lkdGhTZXBhcmF0b3IgPSAnJztcblxuICAgIHB1YmxpYyB3aWR0aFRhYnMgPSAwO1xuXG4gICAgcHVibGljIHdpZHRoV3JhcHBlciA9IDA7XG5cbiAgICBwdWJsaWMgdG9wUG9zaXRpb24gPSAwO1xuXG4gICAgY29uc3RydWN0b3IocHJpdmF0ZSByZW5kZXJlcjogUmVuZGVyZXIyICkge31cblxuICAgIG5nQWZ0ZXJDb250ZW50SW5pdCgpIHtcbiAgICAgIGNvbnN0IHNlbGVjdGVkVGFiID0gdGhpcy50YWJzLmZpbmQodGFiID0+IHRhYi5zZWxlY3RlZCk7XG4gICAgICBpZiAoIXNlbGVjdGVkVGFiICYmIHRoaXMudGFicy5maXJzdCkge1xuICAgICAgICB0aGlzLnRhYnMuZmlyc3Quc2VsZWN0ZWQgPSB0cnVlO1xuICAgICAgfVxuICAgICAgdGhpcy5zZXRUYWJQcm9wZXJ0aWVzKCk7XG4gICAgICB0aGlzLmdldEVsZW1lbnRMaXN0KCk7XG4gICAgfVxuXG4gICAgbmdBZnRlclZpZXdJbml0KCkge1xuICAgICAgdGhpcy5nZXRXcmFwcGVyV2lkdGgoKTtcbiAgICAgIHRoaXMuZ2V0VGFic0NvbXBvbmVudCgpO1xuICAgIH1cblxuICAgIGdldFRhYnNDb21wb25lbnQoKSB7XG4gICAgICB0aGlzLnRhYnMuZm9yRWFjaCggKCBpdGVtLCBpbmRleCApID0+IHtcbiAgICAgICAgdGhpcy5saXN0ZW5MYXN0RWxlbWVudFRhYiggaXRlbS5sYXN0Q29tcG9uZW50LCBpbmRleCApO1xuICAgICAgICB0aGlzLmxpc3RlblByZXZpb3VzRWxlbWVudFRhYiggaXRlbS5maXJzdENvbXBvbmVudCwgaW5kZXggKTtcbiAgICAgIH0gKTtcbiAgICB9XG5cbiAgICBsaXN0ZW5MYXN0RWxlbWVudFRhYiggbGFzdCwgaW5kZXggKSB7XG4gICAgICBpZiAoIGxhc3QgKSB7XG4gICAgICAgIHRoaXMucmVuZGVyZXIubGlzdGVuKCBsYXN0LCAna2V5ZG93bicsICggJGV2ZW50ICkgPT4ge1xuICAgICAgICAgIHRoaXMuaGFuZGxlS2V5RG93bkxhc3RFbGVtZW50VGFiKCAkZXZlbnQsIGluZGV4ICk7XG4gICAgICAgIH0gKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBsaXN0ZW5QcmV2aW91c0VsZW1lbnRUYWIoIGZpcnN0LCBpbmRleCApIHtcbiAgICAgIGlmICggZmlyc3QgKSB7XG4gICAgICAgIHRoaXMucmVuZGVyZXIubGlzdGVuKCBmaXJzdCwgJ2tleWRvd24nLCAoICRldmVudCApID0+IHtcbiAgICAgICAgICB0aGlzLmhhbmRsZUtleURvd25GaXJzdEVsZW1lbnRUYWIoICRldmVudCwgaW5kZXggKTtcbiAgICAgICAgfSApO1xuICAgICAgfVxuICAgIH1cblxuICAgIGhhbmRsZUtleURvd25MYXN0RWxlbWVudFRhYiggJGV2ZW50LCBpbmRleCApIHtcbiAgICAgIGlmICggWyBLZXlFdmVudC5UQUIsIEtleUV2ZW50LkVOVEVSLCBLZXlFdmVudC5BUlJPV0RPV04gXS5pbmRleE9mKCAkZXZlbnQuY29kZSApID49IDAgJiYgKCEkZXZlbnQuc2hpZnRLZXkpICkge1xuICAgICAgICB0aGlzLm5leHRUYWJBbmRFbGVtZW50KCBpbmRleCApO1xuICAgICAgfVxuICAgICAgaWYgKCAoJGV2ZW50LmNvZGUgPT09IEtleUV2ZW50LlRBQikgJiYgKCRldmVudC5jdHJsS2V5KSApIHtcbiAgICAgICAgdGhpcy5uZXh0VGFiQW5kRWxlbWVudCggaW5kZXggKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBoYW5kbGVLZXlEb3duRmlyc3RFbGVtZW50VGFiKCAkZXZlbnQsIGluZGV4ICkge1xuICAgICAgaWYgKCBbIEtleUV2ZW50LkFSUk9XVVAgXS5pbmRleE9mKCAkZXZlbnQuY29kZSApID49IDAgKSB7XG4gICAgICAgIHRoaXMucHJldmlvdXNUYWJBbmRFbGVtZW50KCBpbmRleCApO1xuICAgICAgfVxuICAgICAgaWYgKCAoJGV2ZW50LmNvZGUgPT09IEtleUV2ZW50LlRBQikgJiYgKCRldmVudC5zaGlmdEtleSkgKSB7XG4gICAgICAgIHRoaXMucHJldmlvdXNUYWJBbmRFbGVtZW50KCBpbmRleCApO1xuICAgICAgfVxuICAgIH1cblxuICAgIG5leHRUYWJBbmRFbGVtZW50KCBpbmRleCApIHtcbiAgICAgIGlmICggdGhpcy50YWJzLnRvQXJyYXkoKVsgaW5kZXggKyAxIF0gKSB7XG4gICAgICAgIHRoaXMucmVzZXRUYWJzU2VsZWN0ZWQoKTtcbiAgICAgICAgdGhpcy50YWJzLnRvQXJyYXkoKVsgaW5kZXggKyAxIF0uc2VsZWN0ZWQgPSB0cnVlO1xuICAgICAgICB0aGlzLnNldEZvY3VzTmV4dCggaW5kZXggKyAxICk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcHJldmlvdXNUYWJBbmRFbGVtZW50KCBpbmRleCApIHtcbiAgICAgIGlmICggdGhpcy50YWJzLnRvQXJyYXkoKVsgaW5kZXggLSAxIF0gKSB7XG4gICAgICAgIHRoaXMucmVzZXRUYWJzU2VsZWN0ZWQoKTtcbiAgICAgICAgdGhpcy50YWJzLnRvQXJyYXkoKVsgaW5kZXggLSAxIF0uc2VsZWN0ZWQgPSB0cnVlO1xuICAgICAgICB0aGlzLnNldEZvY3VzUHJldmlvdXMoIGluZGV4IC0gMSApO1xuICAgICAgfVxuICAgIH1cblxuICAgIHNlbGVjdFRhYih0YWI6IFRsVGFiKSB7XG4gICAgICB0aGlzLnRhYnMuZm9yRWFjaChpdGVtID0+IGl0ZW0uc2VsZWN0ZWQgPSBmYWxzZSk7XG4gICAgICB0YWIuc2VsZWN0ZWQgPSB0cnVlO1xuICAgIH1cblxuICAgIGdldFdyYXBwZXJXaWR0aCgpIHtcbiAgICAgIHRoaXMud2lkdGhXcmFwcGVyID0gTWF0aC5yb3VuZCggdGhpcy53cmFwcGVyLm5hdGl2ZUVsZW1lbnQub2Zmc2V0V2lkdGggKTtcbiAgICB9XG5cbiAgICBnZXRFbGVtZW50TGlzdCgpIHtcbiAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICBjb25zdCB0ZW1wbGF0ZUNoaWxkcmVuID0gdGhpcy50YWJzSGVhZGVyLmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudC5wYXJlbnRFbGVtZW50LmNoaWxkcmVuO1xuICAgICAgICBmb3IgKGxldCBlbGVtZW50ID0gMDsgZWxlbWVudCA8IHRlbXBsYXRlQ2hpbGRyZW4ubGVuZ3RoOyBlbGVtZW50KyspIHtcbiAgICAgICAgICBpZiAodGVtcGxhdGVDaGlsZHJlbltlbGVtZW50XS5sb2NhbE5hbWUgPT09ICd1bCcpIHtcbiAgICAgICAgICAgIHRoaXMuZWxlbWVudExpc3RUYWJzID0gdGVtcGxhdGVDaGlsZHJlbltlbGVtZW50XS5jaGlsZHJlbjtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5zZXRXaWR0aFNlcGFyYXRvcigpO1xuICAgICAgfSwgMSk7XG4gICAgfVxuXG4gICAgc2V0Rm9jdXNOZXh0KCBpbmRleCApIHtcbiAgICAgIHNldFRpbWVvdXQoICgpID0+IHtcbiAgICAgICAgdGhpcy50YWJzLnRvQXJyYXkoKVsgaW5kZXggXS5maXJzdENvbXBvbmVudC5mb2N1cygpO1xuICAgICAgfSwgMSApO1xuICAgIH1cblxuICAgIHNldEZvY3VzUHJldmlvdXMoIGluZGV4ICkge1xuICAgICAgc2V0VGltZW91dCggKCkgPT4ge1xuICAgICAgICB0aGlzLnRhYnMudG9BcnJheSgpWyBpbmRleCBdLmxhc3RDb21wb25lbnQuZm9jdXMoKTtcbiAgICAgIH0sIDEgKTtcbiAgICB9XG5cbiAgICBzZXRUYWJQcm9wZXJ0aWVzKCkge1xuICAgICAgdGhpcy50YWJzLmZvckVhY2goICggaXRlbSApID0+IHtcbiAgICAgICAgaXRlbS5oZWlnaHQgPSB0aGlzLmhlaWdodDtcbiAgICAgIH0gKTtcbiAgICB9XG5cbiAgICBzZXRXaWR0aFNlcGFyYXRvcigpIHtcbiAgICAgIHRoaXMud2lkdGhUYWJzID0gMDtcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5lbGVtZW50TGlzdFRhYnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdGhpcy53aWR0aFRhYnMgPSB0aGlzLndpZHRoVGFicyArIE51bWJlcih0aGlzLmVsZW1lbnRMaXN0VGFic1tpXS5vZmZzZXRXaWR0aCk7XG4gICAgICB9XG4gICAgICB0aGlzLnRvcFBvc2l0aW9uID0gKHRoaXMubGluZS5uYXRpdmVFbGVtZW50Lm9mZnNldEhlaWdodCAvIDIpIC0gMTtcbiAgICAgIHRoaXMud2lkdGhTZXBhcmF0b3IgPSAnY2FsYygxMDAlIC0gJyArICh0aGlzLndpZHRoVGFicykgKyAncHgnICsgJyApJztcbiAgICB9XG5cbiAgICByZXNldFRhYnNTZWxlY3RlZCgpIHtcbiAgICAgIHRoaXMudGFicy5mb3JFYWNoKCAoIGl0ZW0gKSA9PiB7XG4gICAgICAgIGl0ZW0uc2VsZWN0ZWQgPSBmYWxzZTtcbiAgICAgIH0gKTtcbiAgICB9XG5cbiAgICBnZXQgdGFic0NvbnRleHQoKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICB0YWJzOiB0aGlzLnRhYnNcbiAgICAgIH07XG4gICAgfVxuXG59XG5cblxuIiwiICA8ZGl2IGNsYXNzPVwid3JhcHBlci10YWJjb250cm9sXCIgI3dyYXBwZXJUYWI+XG4gICAgPG5nLXRlbXBsYXRlICN0YWJzSGVhZGVyIGxldC10YWJzPVwidGFic1wiPlxuICAgICAgPHVsIGNsYXNzPVwidGFiLXBhbmVsLWJ1dHRvbnNcIiBbc3R5bGUuZGlzcGxheV09XCJ0YWJzID8gJ2Jsb2NrJyA6ICdub25lJ1wiPlxuICAgICAgICA8bGkgKm5nRm9yPVwibGV0IHRhYiBvZiB0YWJzXCJcbiAgICAgICAgICAgIFtuZ1N0eWxlXT1cInsnaGVpZ2h0JzogdGFic0hlaWdodCwgJ2xpbmUtaGVpZ2h0JzogdGFic0hlaWdodH1cIlxuICAgICAgICAgICAgW25nQ2xhc3NdPVwieyd0YWItc2VsZWN0ZWQnOiB0YWIuc2VsZWN0ZWR9XCIgKGNsaWNrKT1cInNlbGVjdFRhYih0YWIpXCI+XG4gICAgICAgICAge3t0YWIudGl0bGV9fVxuICAgICAgICA8L2xpPlxuICAgICAgPC91bD5cbiAgICA8L25nLXRlbXBsYXRlPlxuXG4gICAgPGRpdiBjbGFzcz1cImxpbmUtc2VwYXJhdG9yXCJcbiAgICAgICAgICAjbGluZVxuICAgICAgICAgIFtzdHlsZS53aWR0aF09XCJ3aWR0aFNlcGFyYXRvclwiXG4gICAgICAgICAgW3N0eWxlLnRvcF09XCJ0b3BQb3NpdGlvbiAtIDEgKyAncHgnXCJcbiAgICAgICAgICBbc3R5bGUubGVmdF09XCIod2lkdGhUYWJzKSArJ3B4J1wiPlxuICAgIDwvZGl2PlxuXG4gICAgPG5nLWNvbnRhaW5lciAqbmdUZW1wbGF0ZU91dGxldD1cInRhYnNIZWFkZXI7IGNvbnRleHQ6IHRhYnNDb250ZXh0XCI+PC9uZy1jb250YWluZXI+XG4gICAgPG5nLWNvbnRlbnQ+PC9uZy1jb250ZW50PlxuICA8L2Rpdj5cbiJdfQ==