gentics-ui-core
Version:
This is the common core framework for the Gentics CMS and Mesh UI, and other Angular applications.
173 lines • 21.7 kB
JavaScript
import { Component, ContentChildren, QueryList, Input, Output, EventEmitter } from '@angular/core';
import { Tab } from './tab.component';
import { coerceToBoolean } from '../../common/coerce-to-boolean';
import * as i0 from "@angular/core";
import * as i1 from "@angular/common";
import * as i2 from "@angular/router";
import * as i3 from "../icon/icon.directive";
/**
* Tabs can be either pure or stateful. Stateful tabs will keep track of which one is active by keeping an internal
* state.
*
* Pure tabs will only change the active tab when the `activeId` property is updated.
*
* ## Stateful Tabs
* ```html
* <gtx-tabs (tabChange)="goToTab($event)">
* <gtx-tab title="Details">Optional content here.</gtx-tab>
* <gtx-tab title="Orders"></gtx-tab>
* <gtx-tab title="Notes"></gtx-tab>
* </gtx-tabs>
* ```
*
* ## Pure Tabs
* ```html
* <gtx-tabs pure [activeId]="activeTab">
* <gtx-tab title="Details" id="1" (select)="activeTab = $event"></gtx-tab>
* <gtx-tab title="Orders" id="2" (select)="activeTab = $event"></gtx-tab>
* <gtx-tab title="Notes" id="3" (select)="activeTab = $event"></gtx-tab>
* </gtx-tabs>
* ```
*
* ## With `routerLink`
* A gtx-tab can take an optional `[routerLink]` binding which will set router links for the tabs.
* ```html
* <gtx-tabs pure [activeId]="activeTab">
* <gtx-tab title="Details" id="1" [routerLink]="['customer', 'details']"></gtx-tab>
* <gtx-tab title="Orders" id="2" [routerLink]="['customer', 'orders']"></gtx-tab>
* <gtx-tab title="Notes" id="3" [routerLink]="['customer', 'notes']"></gtx-tab>
* </gtx-tabs>
* ```
* * ##### Vertical Tabs
* A gtx-tabs can take an optional `vertical` property which allows to display tabs vertically.
* ```html
* <gtx-tabs vertical>
* <gtx-tab title="Details"></gtx-tab>
* <gtx-tab title="Orders"></gtx-tab>
* <gtx-tab title="Notes"></gtx-tab>
* </gtx-tabs>
* ```
* * * ##### Active Tabs with Icons
* A gtx-tabs can take an optional `hideTitle` property which allows to hide the title for non-active tabs with icons.
* ```html
* <gtx-tabs hideTitle>
* <gtx-tab icon="folder" title="Tab 1">Tab 1 Content</gtx-tab>
* <gtx-tab icon="cloud" title="Tab 2">Tab 2 Content</gtx-tab>
* </gtx-tabs>
* ```
*
*/
export class Tabs {
constructor() {
/**
* Fires an event whenever the active tab changes. Argument is the id of the selected tab.
*/
this.tabChange = new EventEmitter();
this.shouldHideTitle = false;
this.verticalTabs = false;
this.tabsShouldWrap = false;
this.isPure = false;
}
/**
* When present (or set to true), tabs are displayed vertically.
*/
set vertical(val) {
this.verticalTabs = coerceToBoolean(val);
}
/**
* When present (or set to true), only active tabs with icons will show the title.
* Non-active tabs with icons will hide the title, show only icon.
*/
set hideTitle(val) {
this.shouldHideTitle = coerceToBoolean(val);
}
/**
* When present, sets the tabs to pure (stateless) mode.
*/
set pure(val) {
this.isPure = val != null;
}
/**
* When present (or set to true), tabs which do not fit into the width of their container will wrap onto
* a new line. Otherwise, tabs will remain on one line and the contents will be elided if all the available
* space is filled.
*/
set wrap(val) {
this.tabsShouldWrap = coerceToBoolean(val);
}
ngAfterContentInit() {
if (this.isPure) {
this.tabsChangeSubscription = this.tabs.changes.subscribe(() => {
setTimeout(() => this.setActiveTab());
});
}
else {
let activeTabs = this.tabs.filter(tab => tab.active);
// if there is no active tab set, activate the first
if (activeTabs.length === 0) {
this.tabs.first.active = true;
}
}
this.tabs.notifyOnChanges();
}
ngOnChanges(changes) {
this.setActiveTab();
}
ngOnDestroy() {
if (this.tabsChangeSubscription) {
this.tabsChangeSubscription.unsubscribe();
}
}
/**
* Sets the tab with id === this.activeId to active.
*/
setActiveTab() {
if (this.tabs) {
let tabToActivate = this.tabs.filter(t => t.id === this.activeId)[0];
if (tabToActivate) {
this.setAsActive(tabToActivate);
}
}
}
/**
* Invoked when a tab link is clicked.
*/
selectTab(tab) {
if (tab.disabled) {
return;
}
if (!this.isPure) {
this.setAsActive(tab);
this.tabChange.emit(tab.id);
}
else {
tab.select.emit(tab.id);
}
}
setAsActive(tab) {
this.tabs.toArray().forEach(tab => tab.active = false);
tab.active = true;
}
}
/** @nocollapse */ Tabs.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.8", ngImport: i0, type: Tabs, deps: [], target: i0.ɵɵFactoryTarget.Component });
/** @nocollapse */ Tabs.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.8", type: Tabs, selector: "gtx-tabs", inputs: { vertical: "vertical", hideTitle: "hideTitle", activeId: "activeId", pure: "pure", wrap: "wrap" }, outputs: { tabChange: "tabChange" }, queries: [{ propertyName: "tabs", predicate: Tab }], usesOnChanges: true, ngImport: i0, template: "<ul class=\"tab-links\" [class.vertical]=\"verticalTabs\" [class.wrap]=\"tabsShouldWrap\">\n <li class=\"tab-link\" role=\"presentation\"\n *ngFor=\"let tab of tabs\"\n [title]=\"tab.title\"\n (click)=\"selectTab(tab)\"\n [ngClass]=\"{\n disabled: tab.disabled,\n 'is-active': tab.active,\n 'has-icon': !!tab.icon,\n 'icon-only': shouldHideTitle && !tab.active || (tab.icon && !tab.title)\n }\">\n <a role=\"tab\" *ngIf=\"tab.routerLink && !tab.disabled\" [routerLink]=\"tab.routerLink\">\n <icon *ngIf=\"tab.icon\">{{tab.icon}}</icon><span [class.animatedTitle]=\"shouldHideTitle\" *ngIf=\"!shouldHideTitle || tab.active || (!tab.active && !tab.icon)\">{{ tab.title }}</span></a>\n <a role=\"tab\" *ngIf=\"!tab.routerLink || tab.disabled\">\n <icon *ngIf=\"tab.icon\">{{tab.icon}}</icon><span [class.animatedTitle]=\"shouldHideTitle\" *ngIf=\"!shouldHideTitle || tab.active || (!tab.active && !tab.icon)\">{{ tab.title }}</span></a>\n </li>\n</ul>\n<ng-content></ng-content>\n", directives: [{ type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.RouterLinkWithHref, selector: "a[routerLink],area[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "preserveFragment", "skipLocationChange", "replaceUrl", "state", "relativeTo", "routerLink"] }, { type: i3.Icon, selector: "icon" }] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.8", ngImport: i0, type: Tabs, decorators: [{
type: Component,
args: [{ selector: 'gtx-tabs', template: "<ul class=\"tab-links\" [class.vertical]=\"verticalTabs\" [class.wrap]=\"tabsShouldWrap\">\n <li class=\"tab-link\" role=\"presentation\"\n *ngFor=\"let tab of tabs\"\n [title]=\"tab.title\"\n (click)=\"selectTab(tab)\"\n [ngClass]=\"{\n disabled: tab.disabled,\n 'is-active': tab.active,\n 'has-icon': !!tab.icon,\n 'icon-only': shouldHideTitle && !tab.active || (tab.icon && !tab.title)\n }\">\n <a role=\"tab\" *ngIf=\"tab.routerLink && !tab.disabled\" [routerLink]=\"tab.routerLink\">\n <icon *ngIf=\"tab.icon\">{{tab.icon}}</icon><span [class.animatedTitle]=\"shouldHideTitle\" *ngIf=\"!shouldHideTitle || tab.active || (!tab.active && !tab.icon)\">{{ tab.title }}</span></a>\n <a role=\"tab\" *ngIf=\"!tab.routerLink || tab.disabled\">\n <icon *ngIf=\"tab.icon\">{{tab.icon}}</icon><span [class.animatedTitle]=\"shouldHideTitle\" *ngIf=\"!shouldHideTitle || tab.active || (!tab.active && !tab.icon)\">{{ tab.title }}</span></a>\n </li>\n</ul>\n<ng-content></ng-content>\n" }]
}], propDecorators: { tabs: [{
type: ContentChildren,
args: [Tab]
}], tabChange: [{
type: Output
}], vertical: [{
type: Input
}], hideTitle: [{
type: Input
}], activeId: [{
type: Input
}], pure: [{
type: Input
}], wrap: [{
type: Input
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFicy5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvY29tcG9uZW50cy90YWJzL3RhYnMuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vc3JjL2NvbXBvbmVudHMvdGFicy90YWJzLnRwbC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBQyxTQUFTLEVBQUUsZUFBZSxFQUFFLFNBQVMsRUFBb0IsS0FBSyxFQUFFLE1BQU0sRUFBRSxZQUFZLEVBQXNDLE1BQU0sZUFBZSxDQUFDO0FBQ3hKLE9BQU8sRUFBQyxHQUFHLEVBQUMsTUFBTSxpQkFBaUIsQ0FBQztBQUNwQyxPQUFPLEVBQUMsZUFBZSxFQUFDLE1BQU0sZ0NBQWdDLENBQUM7Ozs7O0FBRy9EOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FtREc7QUFLSCxNQUFNLE9BQU8sSUFBSTtJQUpqQjtRQVFJOztXQUVHO1FBQ08sY0FBUyxHQUFHLElBQUksWUFBWSxFQUFVLENBQUM7UUFzQ2pELG9CQUFlLEdBQVksS0FBSyxDQUFDO1FBQ2pDLGlCQUFZLEdBQVksS0FBSyxDQUFDO1FBQzlCLG1CQUFjLEdBQVksS0FBSyxDQUFDO1FBQ3hCLFdBQU0sR0FBWSxLQUFLLENBQUM7S0E4RG5DO0lBckdHOztPQUVHO0lBQ0gsSUFBYSxRQUFRLENBQUMsR0FBUTtRQUMxQixJQUFJLENBQUMsWUFBWSxHQUFHLGVBQWUsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUM3QyxDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsSUFBYSxTQUFTLENBQUMsR0FBUTtRQUMzQixJQUFJLENBQUMsZUFBZSxHQUFHLGVBQWUsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNoRCxDQUFDO0lBT0Q7O09BRUc7SUFDSCxJQUFhLElBQUksQ0FBQyxHQUFRO1FBQ3RCLElBQUksQ0FBQyxNQUFNLEdBQUcsR0FBRyxJQUFJLElB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ZW50Q2hpbGRyZW4sIFF1ZXJ5TGlzdCwgQWZ0ZXJDb250ZW50SW5pdCwgSW5wdXQsIE91dHB1dCwgRXZlbnRFbWl0dGVyLCBTaW1wbGVDaGFuZ2VzLCBPbkNoYW5nZXMsIE9uRGVzdHJveX0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge1RhYn0gZnJvbSAnLi90YWIuY29tcG9uZW50JztcbmltcG9ydCB7Y29lcmNlVG9Cb29sZWFufSBmcm9tICcuLi8uLi9jb21tb24vY29lcmNlLXRvLWJvb2xlYW4nO1xuaW1wb3J0IHsgU3Vic2NyaXB0aW9uIH0gZnJvbSAncnhqcyc7XG5cbi8qKlxuICogVGFicyBjYW4gYmUgZWl0aGVyIHB1cmUgb3Igc3RhdGVmdWwuIFN0YXRlZnVsIHRhYnMgd2lsbCBrZWVwIHRyYWNrIG9mIHdoaWNoIG9uZSBpcyBhY3RpdmUgYnkga2VlcGluZyBhbiBpbnRlcm5hbFxuICogc3RhdGUuXG4gKlxuICogUHVyZSB0YWJzIHdpbGwgb25seSBjaGFuZ2UgdGhlIGFjdGl2ZSB0YWIgd2hlbiB0aGUgYGFjdGl2ZUlkYCBwcm9wZXJ0eSBpcyB1cGRhdGVkLlxuICpcbiAqICMjIFN0YXRlZnVsIFRhYnNcbiAqIGBgYGh0bWxcbiAqIDxndHgtdGFicyAodGFiQ2hhbmdlKT1cImdvVG9UYWIoJGV2ZW50KVwiPlxuICogICAgIDxndHgtdGFiIHRpdGxlPVwiRGV0YWlsc1wiPk9wdGlvbmFsIGNvbnRlbnQgaGVyZS48L2d0eC10YWI+XG4gKiAgICAgPGd0eC10YWIgdGl0bGU9XCJPcmRlcnNcIj48L2d0eC10YWI+XG4gKiAgICAgPGd0eC10YWIgdGl0bGU9XCJOb3Rlc1wiPjwvZ3R4LXRhYj5cbiAqIDwvZ3R4LXRhYnM+XG4gKiBgYGBcbiAqXG4gKiAjIyBQdXJlIFRhYnNcbiAqIGBgYGh0bWxcbiAqIDxndHgtdGFicyBwdXJlIFthY3RpdmVJZF09XCJhY3RpdmVUYWJcIj5cbiAqICAgICA8Z3R4LXRhYiB0aXRsZT1cIkRldGFpbHNcIiBpZD1cIjFcIiAoc2VsZWN0KT1cImFjdGl2ZVRhYiA9ICRldmVudFwiPjwvZ3R4LXRhYj5cbiAqICAgICA8Z3R4LXRhYiB0aXRsZT1cIk9yZGVyc1wiIGlkPVwiMlwiIChzZWxlY3QpPVwiYWN0aXZlVGFiID0gJGV2ZW50XCI+PC9ndHgtdGFiPlxuICogICAgIDxndHgtdGFiIHRpdGxlPVwiTm90ZXNcIiBpZD1cIjNcIiAoc2VsZWN0KT1cImFjdGl2ZVRhYiA9ICRldmVudFwiPjwvZ3R4LXRhYj5cbiAqIDwvZ3R4LXRhYnM+XG4gKiBgYGBcbiAqXG4gKiAjIyBXaXRoIGByb3V0ZXJMaW5rYFxuICogQSBndHgtdGFiIGNhbiB0YWtlIGFuIG9wdGlvbmFsIGBbcm91dGVyTGlua11gIGJpbmRpbmcgd2hpY2ggd2lsbCBzZXQgcm91dGVyIGxpbmtzIGZvciB0aGUgdGFicy5cbiAqIGBgYGh0bWxcbiAqIDxndHgtdGFicyBwdXJlIFthY3RpdmVJZF09XCJhY3RpdmVUYWJcIj5cbiAqICAgICA8Z3R4LXRhYiB0aXRsZT1cIkRldGFpbHNcIiBpZD1cIjFcIiBbcm91dGVyTGlua109XCJbJ2N1c3RvbWVyJywgJ2RldGFpbHMnXVwiPjwvZ3R4LXRhYj5cbiAqICAgICA8Z3R4LXRhYiB0aXRsZT1cIk9yZGVyc1wiIGlkPVwiMlwiIFtyb3V0ZXJMaW5rXT1cIlsnY3VzdG9tZXInLCAnb3JkZXJzJ11cIj48L2d0eC10YWI+XG4gKiAgICAgPGd0eC10YWIgdGl0bGU9XCJOb3Rlc1wiIGlkPVwiM1wiIFtyb3V0ZXJMaW5rXT1cIlsnY3VzdG9tZXInLCAnbm90ZXMnXVwiPjwvZ3R4LXRhYj5cbiAqIDwvZ3R4LXRhYnM+XG4gKiBgYGBcbiAqICAqICMjIyMjIFZlcnRpY2FsIFRhYnNcbiAqIEEgZ3R4LXRhYnMgY2FuIHRha2UgYW4gb3B0aW9uYWwgYHZlcnRpY2FsYCBwcm9wZXJ0eSB3aGljaCBhbGxvd3MgdG8gZGlzcGxheSB0YWJzIHZlcnRpY2FsbHkuXG4gKiBgYGBodG1sXG4gKiA8Z3R4LXRhYnMgdmVydGljYWw+XG4gKiAgICAgICAgPGd0eC10YWIgdGl0bGU9XCJEZXRhaWxzXCI+PC9ndHgtdGFiPlxuICogICAgICAgIDxndHgtdGFiIHRpdGxlPVwiT3JkZXJzXCI+PC9ndHgtdGFiPlxuICogICAgICAgIDxndHgtdGFiIHRpdGxlPVwiTm90ZXNcIj48L2d0eC10YWI+XG4gKiA8L2d0eC10YWJzPlxuICogYGBgXG4gKiAgKiAgKiAjIyMjIyBBY3RpdmUgVGFicyB3aXRoIEljb25zXG4gKiBBIGd0eC10YWJzIGNhbiB0YWtlIGFuIG9wdGlvbmFsIGBoaWRlVGl0bGVgIHByb3BlcnR5IHdoaWNoIGFsbG93cyB0byBoaWRlIHRoZSB0aXRsZSBmb3Igbm9uLWFjdGl2ZSB0YWJzIHdpdGggaWNvbnMuXG4gKiBgYGBodG1sXG4gKiA8Z3R4LXRhYnMgaGlkZVRpdGxlPlxuICogICAgICAgICAgIDxndHgtdGFiIGljb249XCJmb2xkZXJcIiB0aXRsZT1cIlRhYiAxXCI+VGFiIDEgQ29udGVudDwvZ3R4LXRhYj5cbiAqICAgICAgICAgICA8Z3R4LXRhYiBpY29uPVwiY2xvdWRcIiB0aXRsZT1cIlRhYiAyXCI+VGFiIDIgQ29udGVudDwvZ3R4LXRhYj5cbiAqIDwvZ3R4LXRhYnM+XG4gKiBgYGBcbiAqXG4gKi9cbkBDb21wb25lbnQoe1xuICAgIHNlbGVjdG9yOiAnZ3R4LXRhYnMnLFxuICAgIHRlbXBsYXRlVXJsOiAnLi90YWJzLnRwbC5odG1sJ1xufSlcbmV4cG9ydCBjbGFzcyBUYWJzIGltcGxlbWVudHMgQWZ0ZXJDb250ZW50SW5pdCwgT25DaGFuZ2VzLCBPbkRlc3Ryb3kge1xuXG4gICAgQENvbnRlbnRDaGlsZHJlbihUYWIpIHRhYnM6IFF1ZXJ5TGlzdDxUYWI+O1xuXG4gICAgLyoqXG4gICAgICogRmlyZXMgYW4gZXZlbnQgd2hlbmV2ZXIgdGhlIGFjdGl2ZSB0YWIgY2hhbmdlcy4gQXJndW1lbnQgaXMgdGhlIGlkIG9mIHRoZSBzZWxlY3RlZCB0YWIuXG4gICAgICovXG4gICAgQE91dHB1dCgpIHRhYkNoYW5nZSA9IG5ldyBFdmVudEVtaXR0ZXI8c3RyaW5nPigpO1xuXG4gICAgLyoqXG4gICAgICogV2hlbiBwcmVzZW50IChvciBzZXQgdG8gdHJ1ZSksIHRhYnMgYXJlIGRpc3BsYXllZCB2ZXJ0aWNhbGx5LlxuICAgICAqL1xuICAgIEBJbnB1dCgpIHNldCB2ZXJ0aWNhbCh2YWw6IGFueSkge1xuICAgICAgICB0aGlzLnZlcnRpY2FsVGFicyA9IGNvZXJjZVRvQm9vbGVhbih2YWwpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFdoZW4gcHJlc2VudCAob3Igc2V0IHRvIHRydWUpLCBvbmx5IGFjdGl2ZSB0YWJzIHdpdGggaWNvbnMgd2lsbCBzaG93IHRoZSB0aXRsZS5cbiAgICAgKiBOb24tYWN0aXZlIHRhYnMgd2l0aCBpY29ucyB3aWxsIGhpZGUgdGhlIHRpdGxlLCBzaG93IG9ubHkgaWNvbi5cbiAgICAgKi9cbiAgICBASW5wdXQoKSBzZXQgaGlkZVRpdGxlKHZhbDogYW55KSB7XG4gICAgICAgIHRoaXMuc2hvdWxkSGlkZVRpdGxlID0gY29lcmNlVG9Cb29sZWFuKHZhbCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGlkIG9mIHRoZSBhY3RpdmUgdGFiLiBTaG91bGQgb25seSBiZSB1c2VkIGluIHB1cmUgKHN0YXRlbGVzcykgbW9kZS5cbiAgICAgKi9cbiAgICBASW5wdXQoKSBhY3RpdmVJZDogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogV2hlbiBwcmVzZW50LCBzZXRzIHRoZSB0YWJzIHRvIHB1cmUgKHN0YXRlbGVzcykgbW9kZS5cbiAgICAgKi9cbiAgICBASW5wdXQoKSBzZXQgcHVyZSh2YWw6IGFueSkge1xuICAgICAgICB0aGlzLmlzUHVyZSA9IHZhbCAhPSBudWxsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFdoZW4gcHJlc2VudCAob3Igc2V0IHRvIHRydWUpLCB0YWJzIHdoaWNoIGRvIG5vdCBmaXQgaW50byB0aGUgd2lkdGggb2YgdGhlaXIgY29udGFpbmVyIHdpbGwgd3JhcCBvbnRvXG4gICAgICogYSBuZXcgbGluZS4gT3RoZXJ3aXNlLCB0YWJzIHdpbGwgcmVtYWluIG9uIG9uZSBsaW5lIGFuZCB0aGUgY29udGVudHMgd2lsbCBiZSBlbGlkZWQgaWYgYWxsIHRoZSBhdmFpbGFibGVcbiAgICAgKiBzcGFjZSBpcyBmaWxsZWQuXG4gICAgICovXG4gICAgQElucHV0KCkgc2V0IHdyYXAodmFsOiBhbnkpIHtcbiAgICAgICAgdGhpcy50YWJzU2hvdWxkV3JhcCA9IGNvZXJjZVRvQm9vbGVhbih2YWwpO1xuICAgIH1cblxuICAgIHNob3VsZEhpZGVUaXRsZTogYm9vbGVhbiA9IGZhbHNlO1xuICAgIHZlcnRpY2FsVGFiczogYm9vbGVhbiA9IGZhbHNlO1xuICAgIHRhYnNTaG91bGRXcmFwOiBib29sZWFuID0gZmFsc2U7XG4gICAgcHJpdmF0ZSBpc1B1cmU6IGJvb2xlYW4gPSBmYWxzZTtcblxuICAgIHRhYnNDaGFuZ2VTdWJzY3JpcHRpb246IFN1YnNjcmlwdGlvbjtcblxuICAgIG5nQWZ0ZXJDb250ZW50SW5pdCgpOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMuaXNQdXJlKSB7XG4gICAgICAgICAgICB0aGlzLnRhYnNDaGFuZ2VTdWJzY3JpcHRpb24gPSB0aGlzLnRhYnMuY2hhbmdlcy5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4gdGhpcy5zZXRBY3RpdmVUYWIoKSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGxldCBhY3RpdmVUYWJzID0gdGhpcy50YWJzLmZpbHRlcih0YWIgPT4gdGFiLmFjdGl2ZSk7XG5cbiAgICAgICAgICAgIC8vIGlmIHRoZXJlIGlzIG5vIGFjdGl2ZSB0YWIgc2V0LCBhY3RpdmF0ZSB0aGUgZmlyc3RcbiAgICAgICAgICAgIGlmIChhY3RpdmVUYWJzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHRoaXMudGFicy5maXJzdC5hY3RpdmUgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHRoaXMudGFicy5ub3RpZnlPbkNoYW5nZXMoKTtcbiAgICB9XG5cbiAgICBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKTogdm9pZCB7XG4gICAgICAgIHRoaXMuc2V0QWN0aXZlVGFiKCk7XG4gICAgfVxuXG4gICAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgICAgIGlmICh0aGlzLnRhYnNDaGFuZ2VTdWJzY3JpcHRpb24pIHtcbiAgICAgICAgICAgIHRoaXMudGFic0NoYW5nZVN1YnNjcmlwdGlvbi51bnN1YnNjcmliZSgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgdGFiIHdpdGggaWQgPT09IHRoaXMuYWN0aXZlSWQgdG8gYWN0aXZlLlxuICAgICAqL1xuICAgIHNldEFjdGl2ZVRhYigpOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMudGFicykge1xuICAgICAgICAgICAgbGV0IHRhYlRvQWN0aXZhdGUgPSB0aGlzLnRhYnMuZmlsdGVyKHQgPT4gdC5pZCA9PT0gdGhpcy5hY3RpdmVJZClbMF07XG4gICAgICAgICAgICBpZiAodGFiVG9BY3RpdmF0ZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0QXNBY3RpdmUodGFiVG9BY3RpdmF0ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBJbnZva2VkIHdoZW4gYSB0YWIgbGluayBpcyBjbGlja2VkLlxuICAgICAqL1xuICAgIHNlbGVjdFRhYih0YWI6IFRhYik6IHZvaWQge1xuICAgICAgICBpZiAodGFiLmRpc2FibGVkKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF0aGlzLmlzUHVyZSkge1xuICAgICAgICAgICAgdGhpcy5zZXRBc0FjdGl2ZSh0YWIpO1xuICAgICAgICAgICAgdGhpcy50YWJDaGFuZ2UuZW1pdCh0YWIuaWQpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGFiLnNlbGVjdC5lbWl0KHRhYi5pZCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIHNldEFzQWN0aXZlKHRhYjogVGFiKTogdm9pZCB7XG4gICAgICAgIHRoaXMudGFicy50b0FycmF5KCkuZm9yRWFjaCh0YWIgPT4gdGFiLmFjdGl2ZSA9IGZhbHNlKTtcbiAgICAgICAgdGFiLmFjdGl2ZSA9IHRydWU7XG4gICAgfVxuXG59XG4iLCI8dWwgY2xhc3M9XCJ0YWItbGlua3NcIiBbY2xhc3MudmVydGljYWxdPVwidmVydGljYWxUYWJzXCIgW2NsYXNzLndyYXBdPVwidGFic1Nob3VsZFdyYXBcIj5cbiAgICA8bGkgY2xhc3M9XCJ0YWItbGlua1wiIHJvbGU9XCJwcmVzZW50YXRpb25cIlxuICAgICAgICAgICAgKm5nRm9yPVwibGV0IHRhYiBvZiB0YWJzXCJcbiAgICAgICAgICAgIFt0aXRsZV09XCJ0YWIudGl0bGVcIlxuICAgICAgICAgICAgKGNsaWNrKT1cInNlbGVjdFRhYih0YWIpXCJcbiAgICAgICAgICAgIFtuZ0NsYXNzXT1cIntcbiAgICAgICAgICAgICAgICBkaXNhYmxlZDogdGFiLmRpc2FibGVkLFxuICAgICAgICAgICAgICAgICdpcy1hY3RpdmUnOiB0YWIuYWN0aXZlLFxuICAgICAgICAgICAgICAgICdoYXMtaWNvbic6ICEhdGFiLmljb24sXG4gICAgICAgICAgICAgICAgJ2ljb24tb25seSc6IHNob3VsZEhpZGVUaXRsZSAmJiAhdGFiLmFjdGl2ZSB8fCAodGFiLmljb24gJiYgIXRhYi50aXRsZSlcbiAgICAgICAgICAgIH1cIj5cbiAgICAgICAgPGEgcm9sZT1cInRhYlwiICpuZ0lmPVwidGFiLnJvdXRlckxpbmsgJiYgIXRhYi5kaXNhYmxlZFwiIFtyb3V0ZXJMaW5rXT1cInRhYi5yb3V0ZXJMaW5rXCI+XG4gICAgICAgICAgICA8aWNvbiAqbmdJZj1cInRhYi5pY29uXCI+e3t0YWIuaWNvbn19PC9pY29uPjxzcGFuIFtjbGFzcy5hbmltYXRlZFRpdGxlXT1cInNob3VsZEhpZGVUaXRsZVwiICpuZ0lmPVwiIXNob3VsZEhpZGVUaXRsZSB8fCB0YWIuYWN0aXZlIHx8ICghdGFiLmFjdGl2ZSAmJiAhdGFiLmljb24pXCI+e3sgdGFiLnRpdGxlIH19PC9zcGFuPjwvYT5cbiAgICAgICAgPGEgcm9sZT1cInRhYlwiICpuZ0lmPVwiIXRhYi5yb3V0ZXJMaW5rIHx8IHRhYi5kaXNhYmxlZFwiPlxuICAgICAgICAgICAgPGljb24gKm5nSWY9XCJ0YWIuaWNvblwiPnt7dGFiLmljb259fTwvaWNvbj48c3BhbiBbY2xhc3MuYW5pbWF0ZWRUaXRsZV09XCJzaG91bGRIaWRlVGl0bGVcIiAqbmdJZj1cIiFzaG91bGRIaWRlVGl0bGUgfHwgdGFiLmFjdGl2ZSB8fCAoIXRhYi5hY3RpdmUgJiYgIXRhYi5pY29uKVwiPnt7IHRhYi50aXRsZSB9fTwvc3Bhbj48L2E+XG4gICAgPC9saT5cbjwvdWw+XG48bmctY29udGVudD48L25nLWNvbnRlbnQ+XG4iXX0=