@hxui/angular
Version:
An Angular library based on the [HXUI design system](https://hxui.io).
272 lines (269 loc) • 24.7 kB
JavaScript
import { Component, ContentChildren, forwardRef, Input, QueryList, } from '@angular/core';
import { TabDirective } from './tab.directive';
import { TabsetConfig } from './tabset.config';
import * as i0 from "@angular/core";
import * as i1 from "./tabset.config";
import * as i2 from "@angular/common";
import * as i3 from "./ng-transclude.directive";
export class TabsetComponent {
constructor(config) {
/** if true tabs will be placed vertically */
this.vertical = false;
/** if true tabs fill the container and have a consistent width */
this.justified = false;
this.hasInfo = false;
this.stickyHeader = false;
this.stickyHeaderOffset = 0;
this.tag = 'link';
this.changeFn = async () => true;
this.tabs = [];
Object.assign(this, config);
}
/** navigation context class: 'tabs' or 'pills' */
get type() {
return this._type;
}
set type(value) {
this._type = value;
}
ngAfterContentInit() {
// get all active tabs
const activeTabs = this._tabList.filter(tab => tab.active);
// if there is no active tab set, activate the first
if (activeTabs.length === 0) {
this._selectTab(this._tabList.last);
}
}
_selectTab(tab) {
// deactivate all tabs
this._tabList.toArray().forEach(tab => (tab.active = false));
// activate the tab the user has clicked on.
tab.active = true;
}
selectTab(tab) {
this.changeFn().then(res => !!res && this._selectTab(tab));
}
ngOnDestroy() {
this.isDestroyed = true;
}
addTab(tab) {
this.tabs.push(tab);
tab.active = this.tabs.length === 1 && tab.active !== false;
}
removeTab(tab, options = { reselect: true, emit: true }) {
const index = this.tabs.indexOf(tab);
if (index === -1 || this.isDestroyed) {
return;
}
// Select a new tab if the tab to be removed is selected and not destroyed
if (options.reselect && tab.active && this.hasAvailableTabs(index)) {
const newActiveIndex = this.getClosestTabIndex(index);
this.tabs[newActiveIndex].active = true;
}
if (options.emit) {
tab.removed.emit(tab);
}
this.tabs.splice(index, 1);
if (tab.elementRef.nativeElement && tab.elementRef.nativeElement.remove) {
tab.elementRef.nativeElement.remove();
}
}
getStickyHeaderPosition() {
return this.stickyHeader ? 'sticky' : 'relative';
}
getClosestTabIndex(index) {
const tabsLength = this.tabs.length;
if (!tabsLength) {
return -1;
}
for (let step = 1; step <= tabsLength; step += 1) {
const prevIndex = index - step;
const nextIndex = index + step;
if (this.tabs[prevIndex] && !this.tabs[prevIndex].disabled) {
return prevIndex;
}
if (this.tabs[nextIndex] && !this.tabs[nextIndex].disabled) {
return nextIndex;
}
}
return -1;
}
hasAvailableTabs(index) {
const tabsLength = this.tabs.length;
if (!tabsLength) {
return false;
}
for (let i = 0; i < tabsLength; i += 1) {
if (!this.tabs[i].disabled && i !== index) {
return true;
}
}
return false;
}
}
TabsetComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: TabsetComponent, deps: [{ token: i1.TabsetConfig }], target: i0.ɵɵFactoryTarget.Component });
TabsetComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: TabsetComponent, selector: "hx-tabset", inputs: { vertical: "vertical", justified: "justified", hasInfo: "hasInfo", type: "type", contentCustomClass: "contentCustomClass", stickyHeader: "stickyHeader", stickyHeaderOffset: "stickyHeaderOffset", tag: "tag", changeFn: "changeFn" }, host: { classAttribute: "hx-tab-container" }, queries: [{ propertyName: "_tabList", predicate: i0.forwardRef(function () { return TabDirective; }) }], ngImport: i0, template: `
<ul
class="hx-nav hx-nav-{{ type }}"
[ngStyle]="{
position: getStickyHeaderPosition(),
'top.rem': stickyHeaderOffset
}"
[class.is-vertical]="vertical"
[class.is-justified]="justified"
[class.has-info]="hasInfo"
>
<li
*ngFor="let tab of tabs"
[ngClass]="['hx-nav-item', tab.customClass || '']"
[class.is-active]="!!tab?.active"
[class.is-disabled]="!!tab?.disabled"
[class.is-button]="tag === 'button'"
>
<button
*ngIf="tag === 'button'"
class="hx-nav-link"
[class.is-active]="!!tab?.active"
[class.is-disabled]="!!tab?.disabled"
[attr.disabled]="!!tab?.disabled ? '' : null"
(click)="selectTab(tab)"
>
<span [ngTransclude]="tab.headingRef">{{ tab.heading }}</span>
<span *ngIf="tab.removable">
<span
(click)="removeTab(tab)"
class="icon close-outline is-small"
></span>
</span>
</button>
<a
*ngIf="tag === 'link'"
class="hx-nav-link"
[class.is-active]="!!tab?.active"
[class.is-disabled]="!!tab?.disabled"
[attr.disabled]="!!tab?.disabled ? '' : null"
(click)="selectTab(tab)"
>
<span [ngTransclude]="tab.headingRef">{{ tab.heading }}</span>
<span *ngIf="tab.removable">
<span
(click)="removeTab(tab)"
class="icon close-outline is-small"
></span>
</span>
</a>
</li>
</ul>
<div class="hx-tab-content {{ contentCustomClass }}">
<ng-content></ng-content>
</div>
`, isInline: true, styles: [":host,ul.hx-nav{background-color:inherit}button.hx-nav-link{border-width:0;border-bottom-width:1px;border-color:transparent;background-color:transparent;line-height:1.5;cursor:pointer}:where(.is-justified) .is-button.hx-nav-item{display:flex}:where(.is-justified .is-button) button.hx-nav-link{display:flex}\n"], directives: [{ type: i2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i3.NgTranscludeDirective, selector: "[ngTransclude]", inputs: ["ngTransclude"] }] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: TabsetComponent, decorators: [{
type: Component,
args: [{
selector: 'hx-tabset',
host: {
class: 'hx-tab-container',
},
template: `
<ul
class="hx-nav hx-nav-{{ type }}"
[ngStyle]="{
position: getStickyHeaderPosition(),
'top.rem': stickyHeaderOffset
}"
[class.is-vertical]="vertical"
[class.is-justified]="justified"
[class.has-info]="hasInfo"
>
<li
*ngFor="let tab of tabs"
[ngClass]="['hx-nav-item', tab.customClass || '']"
[class.is-active]="!!tab?.active"
[class.is-disabled]="!!tab?.disabled"
[class.is-button]="tag === 'button'"
>
<button
*ngIf="tag === 'button'"
class="hx-nav-link"
[class.is-active]="!!tab?.active"
[class.is-disabled]="!!tab?.disabled"
[attr.disabled]="!!tab?.disabled ? '' : null"
(click)="selectTab(tab)"
>
<span [ngTransclude]="tab.headingRef">{{ tab.heading }}</span>
<span *ngIf="tab.removable">
<span
(click)="removeTab(tab)"
class="icon close-outline is-small"
></span>
</span>
</button>
<a
*ngIf="tag === 'link'"
class="hx-nav-link"
[class.is-active]="!!tab?.active"
[class.is-disabled]="!!tab?.disabled"
[attr.disabled]="!!tab?.disabled ? '' : null"
(click)="selectTab(tab)"
>
<span [ngTransclude]="tab.headingRef">{{ tab.heading }}</span>
<span *ngIf="tab.removable">
<span
(click)="removeTab(tab)"
class="icon close-outline is-small"
></span>
</span>
</a>
</li>
</ul>
<div class="hx-tab-content {{ contentCustomClass }}">
<ng-content></ng-content>
</div>
`,
styles: [
`
:host,
ul.hx-nav {
background-color: inherit;
}
button.hx-nav-link {
border-width: 0;
border-bottom-width: 1px;
border-color: transparent;
background-color: transparent;
line-height: 1.5;
cursor: pointer;
}
:where(.is-justified) .is-button.hx-nav-item {
display: flex;
}
:where(.is-justified .is-button) button.hx-nav-link {
display: flex;
}
`,
],
}]
}], ctorParameters: function () { return [{ type: i1.TabsetConfig }]; }, propDecorators: { vertical: [{
type: Input
}], justified: [{
type: Input
}], hasInfo: [{
type: Input
}], type: [{
type: Input
}], contentCustomClass: [{
type: Input
}], stickyHeader: [{
type: Input
}], stickyHeaderOffset: [{
type: Input
}], tag: [{
type: Input
}], changeFn: [{
type: Input
}], _tabList: [{
type: ContentChildren,
args: [forwardRef(() => TabDirective)]
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFic2V0LmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2h4LXVpL3NyYy9saWIvdGFicy90YWJzZXQuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFFTCxTQUFTLEVBQ1QsZUFBZSxFQUNmLFVBQVUsRUFDVixLQUFLLEVBRUwsU0FBUyxHQUNWLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMvQyxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0saUJBQWlCLENBQUM7Ozs7O0FBeUYvQyxNQUFNLE9BQU8sZUFBZTtJQW1DMUIsWUFBWSxNQUFvQjtRQWxDaEMsNkNBQTZDO1FBQ3BDLGFBQVEsR0FBRyxLQUFLLENBQUM7UUFFMUIsa0VBQWtFO1FBQ3pELGNBQVMsR0FBRyxLQUFLLENBQUM7UUFFbEIsWUFBTyxHQUFHLEtBQUssQ0FBQztRQVloQixpQkFBWSxHQUFHLEtBQUssQ0FBQztRQUNyQix1QkFBa0IsR0FBRyxDQUFDLENBQUM7UUFFdkIsUUFBRyxHQUFzQixNQUFNLENBQUM7UUFHekMsYUFBUSxHQUFHLEtBQUssSUFBSSxFQUFFLENBQUMsSUFBSSxDQUFDO1FBSzVCLFNBQUksR0FBbUIsRUFBRSxDQUFDO1FBTXhCLE1BQU0sQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLE1BQU0sQ0FBQyxDQUFDO0lBQzlCLENBQUM7SUE1QkQsa0RBQWtEO0lBQ2xELElBQ0ksSUFBSTtRQUNOLE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQztJQUNwQixDQUFDO0lBQ0QsSUFBSSxJQUFJLENBQUMsS0FBYTtRQUNwQixJQUFJLENBQUMsS0FBSyxHQUFHLEtBQUssQ0FBQztJQUNyQixDQUFDO0lBdUJELGtCQUFrQjtRQUNoQixzQkFBc0I7UUFDdEIsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxN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QUFFO3dCQUNKLEtBQUssRUFBRSxrQkFBa0I7cUJBQzFCO29CQUNELFFBQVEsRUFBRTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQXVEVDtvQkFDRCxNQUFNLEVBQUU7d0JBQ047Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7S0FzQkM7cUJBQ0Y7aUJBQ0Y7bUdBR1UsUUFBUTtzQkFBaEIsS0FBSztnQkFHRyxTQUFTO3NCQUFqQixLQUFLO2dCQUVHLE9BQU87c0JBQWYsS0FBSztnQkFJRixJQUFJO3NCQURQLEtBQUs7Z0JBUUcsa0JBQWtCO3NCQUExQixLQUFLO2dCQUNHLFlBQVk7c0JBQXBCLEtBQUs7Z0JBQ0csa0JBQWtCO3NCQUExQixLQUFLO2dCQUVHLEdBQUc7c0JBQVgsS0FBSztnQkFHTixRQUFRO3NCQURQLEtBQUs7Z0JBSUUsUUFBUTtzQkFEZixlQUFlO3VCQUFDLFVBQVUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxZQUFZLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xyXG4gIEFmdGVyQ29udGVudEluaXQsXHJcbiAgQ29tcG9uZW50LFxyXG4gIENvbnRlbnRDaGlsZHJlbixcclxuICBmb3J3YXJkUmVmLFxyXG4gIElucHV0LFxyXG4gIE9uRGVzdHJveSxcclxuICBRdWVyeUxpc3QsXHJcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7IFRhYkRpcmVjdGl2ZSB9IGZyb20gJy4vdGFiLmRpcmVjdGl2ZSc7XHJcbmltcG9ydCB7IFRhYnNldENvbmZpZyB9IGZyb20gJy4vdGFic2V0LmNvbmZpZyc7XHJcblxyXG5AQ29tcG9uZW50KHtcclxuICBzZWxlY3RvcjogJ2h4LXRhYnNldCcsXHJcbiAgaG9zdDoge1xyXG4gICAgY2xhc3M6ICdoeC10YWItY29udGFpbmVyJyxcclxuICB9LFxyXG4gIHRlbXBsYXRlOiBgXHJcbiAgICA8dWxcclxuICAgICAgY2xhc3M9XCJoeC1uYXYgaHgtbmF2LXt7IHR5cGUgfX1cIlxyXG4gICAgICBbbmdTdHlsZV09XCJ7XHJcbiAgICAgICAgcG9zaXRpb246IGdldFN0aWNreUhlYWRlclBvc2l0aW9uKCksXHJcbiAgICAgICAgJ3RvcC5yZW0nOiBzdGlja3lIZWFkZXJPZmZzZXRcclxuICAgICAgfVwiXHJcbiAgICAgIFtjbGFzcy5pcy12ZXJ0aWNhbF09XCJ2ZXJ0aWNhbFwiXHJcbiAgICAgIFtjbGFzcy5pcy1qdXN0aWZpZWRdPVwianVzdGlmaWVkXCJcclxuICAgICAgW2NsYXNzLmhhcy1pbmZvXT1cImhhc0luZm9cIlxyXG4gICAgPlxyXG4gICAgICA8bGlcclxuICAgICAgICAqbmdGb3I9XCJsZXQgdGFiIG9mIHRhYnNcIlxyXG4gICAgICAgIFtuZ0NsYXNzXT1cIlsnaHgtbmF2LWl0ZW0nLCB0YWIuY3VzdG9tQ2xhc3MgfHwgJyddXCJcclxuICAgICAgICBbY2xhc3MuaXMtYWN0aXZlXT1cIiEhdGFiPy5hY3RpdmVcIlxyXG4gICAgICAgIFtjbGFzcy5pcy1kaXNhYmxlZF09XCIhIXRhYj8uZGlzYWJsZWRcIlxyXG4gICAgICAgIFtjbGFzcy5pcy1idXR0b25dPVwidGFnID09PSAnYnV0dG9uJ1wiXHJcbiAgICAgID5cclxuICAgICAgICA8YnV0dG9uXHJcbiAgICAgICAgICAqbmdJZj1cInRhZyA9PT0gJ2J1dHRvbidcIlxyXG4gICAgICAgICAgY2xhc3M9XCJoeC1uYXYtbGlua1wiXHJcbiAgICAgICAgICBbY2xhc3MuaXMtYWN0aXZlXT1cIiEhdGFiPy5hY3RpdmVcIlxyXG4gICAgICAgICAgW2NsYXNzLmlzLWRpc2FibGVkXT1cIiEhdGFiPy5kaXNhYmxlZFwiXHJcbiAgICAgICAgICBbYXR0ci5kaXNhYmxlZF09XCIhIXRhYj8uZGlzYWJsZWQgPyAnJyA6IG51bGxcIlxyXG4gICAgICAgICAgKGNsaWNrKT1cInNlbGVjdFRhYih0YWIpXCJcclxuICAgICAgICA+XHJcbiAgICAgICAgICA8c3BhbiBbbmdUcmFuc2NsdWRlXT1cInRhYi5oZWFkaW5nUmVmXCI+e3sgdGFiLmhlYWRpbmcgfX08L3NwYW4+XHJcbiAgICAgICAgICA8c3BhbiAqbmdJZj1cInRhYi5yZW1vdmFibGVcIj5cclxuICAgICAgICAgICAgPHNwYW5cclxuICAgICAgICAgICAgICAoY2xpY2spPVwicmVtb3ZlVGFiKHRhYilcIlxyXG4gICAgICAgICAgICAgIGNsYXNzPVwiaWNvbiBjbG9zZS1vdXRsaW5lIGlzLXNtYWxsXCJcclxuICAgICAgICAgICAgPjwvc3Bhbj5cclxuICAgICAgICAgIDwvc3Bhbj5cclxuICAgICAgICA8L2J1dHRvbj5cclxuICAgICAgICA8YVxyXG4gICAgICAgICAgKm5nSWY9XCJ0YWcgPT09ICdsaW5rJ1wiXHJcbiAgICAgICAgICBjbGFzcz1cImh4LW5hdi1saW5rXCJcclxuICAgICAgICAgIFtjbGFzcy5pcy1hY3RpdmVdPVwiISF0YWI/LmFjdGl2ZVwiXHJcbiAgICAgICAgICBbY2xhc3MuaXMtZGlzYWJsZWRdPVwiISF0YWI/LmRpc2FibGVkXCJcclxuICAgICAgICAgIFthdHRyLmRpc2FibGVkXT1cIiEhdGFiPy5kaXNhYmxlZCA/ICcnIDogbnVsbFwiXHJcbiAgICAgICAgICAoY2xpY2spPVwic2VsZWN0VGFiKHRhYilcIlxyXG4gICAgICAgID5cclxuICAgICAgICAgIDxzcGFuIFtuZ1RyYW5zY2x1ZGVdPVwidGFiLmhlYWRpbmdSZWZcIj57eyB0YWIuaGVhZGluZyB9fTwvc3Bhbj5cclxuICAgICAgICAgIDxzcGFuICpuZ0lmPVwidGFiLnJlbW92YWJsZVwiPlxyXG4gICAgICAgICAgICA8c3BhblxyXG4gICAgICAgICAgICAgIChjbGljayk9XCJyZW1vdmVUYWIodGFiKVwiXHJcbiAgICAgICAgICAgICAgY2xhc3M9XCJpY29uIGNsb3NlLW91dGxpbmUgaXMtc21hbGxcIlxyXG4gICAgICAgICAgICA+PC9zcGFuPlxyXG4gICAgICAgICAgPC9zcGFuPlxyXG4gICAgICAgIDwvYT5cclxuICAgICAgPC9saT5cclxuICAgIDwvdWw+XHJcbiAgICA8ZGl2IGNsYXNzPVwiaHgtdGFiLWNvbnRlbnQge3sgY29udGVudEN1c3RvbUNsYXNzIH19XCI+XHJcbiAgICAgIDxuZy1jb250ZW50PjwvbmctY29udGVudD5cclxuICAgIDwvZGl2PlxyXG4gIGAsXHJcbiAgc3R5bGVzOiBbXHJcbiAgICBgXHJcbiAgICAgIDpob3N0LFxyXG4gICAgICB1bC5oeC1uYXYge1xyXG4gICAgICAgIGJhY2tncm91bmQtY29sb3I6IGluaGVyaXQ7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGJ1dHRvbi5oeC1uYXYtbGluayB7XHJcbiAgICAgICAgYm9yZGVyLXdpZHRoOiAwO1xyXG4gICAgICAgIGJvcmRlci1ib3R0b20td2lkdGg6IDFweDtcclxuICAgICAgICBib3JkZXItY29sb3I6IHRyYW5zcGFyZW50O1xyXG4gICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRyYW5zcGFyZW50O1xyXG4gICAgICAgIGxpbmUtaGVpZ2h0OiAxLjU7XHJcbiAgICAgICAgY3Vyc29yOiBwb2ludGVyO1xyXG4gICAgICB9XHJcblxyXG4gICAgICA6d2hlcmUoLmlzLWp1c3RpZmllZCkgLmlzLWJ1dHRvbi5oeC1uYXYtaXRlbSB7XHJcbiAgICAgICAgZGlzcGxheTogZmxleDtcclxuICAgICAgfVxyXG5cclxuICAgICAgOndoZXJlKC5pcy1qdXN0aWZpZWQgLmlzLWJ1dHRvbikgYnV0dG9uLmh4LW5hdi1saW5rIHtcclxuICAgICAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgICB9XHJcbiAgICBgLFxyXG4gIF0sXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBUYWJzZXRDb21wb25lbnQgaW1wbGVtZW50cyBPbkRlc3Ryb3ksIEFmdGVyQ29udGVudEluaXQge1xyXG4gIC8qKiBpZiB0cnVlIHRhYnMgd2lsbCBiZSBwbGFjZWQgdmVydGljYWxseSAqL1xyXG4gIEBJbnB1dCgpIHZlcnRpY2FsID0gZmFsc2U7XHJcblxyXG4gIC8qKiBpZiB0cnVlIHRhYnMgZmlsbCB0aGUgY29udGFpbmVyIGFuZCBoYXZlIGEgY29uc2lzdGVudCB3aWR0aCAqL1xyXG4gIEBJbnB1dCgpIGp1c3RpZmllZCA9IGZhbHNlO1xyXG5cclxuICBASW5wdXQoKSBoYXNJbmZvID0gZmFsc2U7XHJcblxyXG4gIC8qKiBuYXZpZ2F0aW9uIGNvbnRleHQgY2xhc3M6ICd0YWJzJyBvciAncGlsbHMnICovXHJcbiAgQElucHV0KClcclxuICBnZXQgdHlwZSgpOiBzdHJpbmcge1xyXG4gICAgcmV0dXJuIHRoaXMuX3R5cGU7XHJcbiAgfVxyXG4gIHNldCB0eXBlKHZhbHVlOiBzdHJpbmcpIHtcclxuICAgIHRoaXMuX3R5cGUgPSB2YWx1ZTtcclxuICB9XHJcblxyXG4gIEBJbnB1dCgpIGNvbnRlbnRDdXN0b21DbGFzczogc3RyaW5nO1xyXG4gIEBJbnB1dCgpIHN0aWNreUhlYWRlciA9IGZhbHNlO1xyXG4gIEBJbnB1dCgpIHN0aWNreUhlYWRlck9mZnNldCA9IDA7XHJcblxyXG4gIEBJbnB1dCgpIHRhZzogJ2xpbmsnIHwgJ2J1dHRvbicgPSAnbGluayc7XHJcblxyXG4gIEBJbnB1dCgpXHJcbiAgY2hhbmdlRm4gPSBhc3luYyAoKSA9PiB0cnVlO1xyXG5cclxuICBAQ29udGVudENoaWxkcmVuKGZvcndhcmRSZWYoKCkgPT4gVGFiRGlyZWN0aXZlKSlcclxuICBwcml2YXRlIF90YWJMaXN0OiBRdWVyeUxpc3Q8VGFiRGlyZWN0aXZlPjtcclxuXHJcbiAgdGFiczogVGFiRGlyZWN0aXZlW10gPSBbXTtcclxuXHJcbiAgcHJvdGVjdGVkIGlzRGVzdHJveWVkOiBib29sZWFuO1xyXG4gIHByb3RlY3RlZCBfdHlwZTogc3RyaW5nO1xyXG5cclxuICBjb25zdHJ1Y3Rvcihjb25maWc6IFRhYnNldENvbmZpZykge1xyXG4gICAgT2JqZWN0LmFzc2lnbih0aGlzLCBjb25maWcpO1xyXG4gIH1cclxuXHJcbiAgbmdBZnRlckNvbnRlbnRJbml0KCkge1xyXG4gICAgLy8gZ2V0IGFsbCBhY3RpdmUgdGFic1xyXG4gICAgY29uc3QgYWN0aXZlVGFicyA9IHRoaXMuX3RhYkxpc3QuZmlsdGVyKHRhYiA9PiB0YWIuYWN0aXZlKTtcclxuXHJcbiAgICAvLyBpZiB0aGVyZSBpcyBubyBhY3RpdmUgdGFiIHNldCwgYWN0aXZhdGUgdGhlIGZpcnN0XHJcbiAgICBpZiAoYWN0aXZlVGFicy5sZW5ndGggPT09IDApIHtcclxuICAgICAgdGhpcy5fc2VsZWN0VGFiKHRoaXMuX3RhYkxpc3QubGFzdCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIF9zZWxlY3RUYWIodGFiOiBUYWJEaXJlY3RpdmUpIHtcclxuICAgIC8vIGRlYWN0aXZhdGUgYWxsIHRhYnNcclxuICAgIHRoaXMuX3RhYkxpc3QudG9BcnJheSgpLmZvckVhY2godGFiID0+ICh0YWIuYWN0aXZlID0gZmFsc2UpKTtcclxuXHJcbiAgICAvLyBhY3RpdmF0ZSB0aGUgdGFiIHRoZSB1c2VyIGhhcyBjbGlja2VkIG9uLlxyXG4gICAgdGFiLmFjdGl2ZSA9IHRydWU7XHJcbiAgfVxyXG5cclxuICBzZWxlY3RUYWIodGFiOiBUYWJEaXJlY3RpdmUpIHtcclxuICAgIHRoaXMuY2hhbmdlRm4oKS50aGVuKHJlcyA9PiAhIXJlcyAmJiB0aGlzLl9zZWxlY3RUYWIodGFiKSk7XHJcbiAgfVxyXG5cclxuICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcclxuICAgIHRoaXMuaXNEZXN0cm95ZWQgPSB0cnVlO1xyXG4gIH1cclxuXHJcbiAgYWRkVGFiKHRhYjogVGFiRGlyZWN0aXZlKTogdm9pZCB7XHJcbiAgICB0aGlzLnRhYnMucHVzaCh0YWIpO1xyXG4gICAgdGFiLmFjdGl2ZSA9IHRoaXMudGFicy5sZW5ndGggPT09IDEgJiYgdGFiLmFjdGl2ZSAhPT0gZmFsc2U7XHJcbiAgfVxyXG5cclxuICByZW1vdmVUYWIodGFiOiBUYWJEaXJlY3RpdmUsIG9wdGlvbnMgPSB7IHJlc2VsZWN0OiB0cnVlLCBlbWl0OiB0cnVlIH0pOiB2b2lkIHtcclxuICAgIGNvbnN0IGluZGV4ID0gdGhpcy50YWJzLmluZGV4T2YodGFiKTtcclxuICAgIGlmIChpbmRleCA9PT0gLTEgfHwgdGhpcy5pc0Rlc3Ryb3llZCkge1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcbiAgICAvLyBTZWxlY3QgYSBuZXcgdGFiIGlmIHRoZSB0YWIgdG8gYmUgcmVtb3ZlZCBpcyBzZWxlY3RlZCBhbmQgbm90IGRlc3Ryb3llZFxyXG4gICAgaWYgKG9wdGlvbnMucmVzZWxlY3QgJiYgdGFiLmFjdGl2ZSAmJiB0aGlzLmhhc0F2YWlsYWJsZVRhYnMoaW5kZXgpKSB7XHJcbiAgICAgIGNvbnN0IG5ld0FjdGl2ZUluZGV4ID0gdGhpcy5nZXRDbG9zZXN0VGFiSW5kZXgoaW5kZXgpO1xyXG4gICAgICB0aGlzLnRhYnNbbmV3QWN0aXZlSW5kZXhdLmFjdGl2ZSA9IHRydWU7XHJcbiAgICB9XHJcbiAgICBpZiAob3B0aW9ucy5lbWl0KSB7XHJcbiAgICAgIHRhYi5yZW1vdmVkLmVtaXQodGFiKTtcclxuICAgIH1cclxuICAgIHRoaXMudGFicy5zcGxpY2UoaW5kZXgsIDEpO1xyXG4gICAgaWYgKHRhYi5lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQgJiYgdGFiLmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudC5yZW1vdmUpIHtcclxuICAgICAgdGFiLmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudC5yZW1vdmUoKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIGdldFN0aWNreUhlYWRlclBvc2l0aW9uKCk6IHN0cmluZyB7XHJcbiAgICByZXR1cm4gdGhpcy5zdGlja3lIZWFkZXIgPyAnc3RpY2t5JyA6ICdyZWxhdGl2ZSc7XHJcbiAgfVxyXG5cclxuICBwcm90ZWN0ZWQgZ2V0Q2xvc2VzdFRhYkluZGV4KGluZGV4OiBudW1iZXIpOiBudW1iZXIge1xyXG4gICAgY29uc3QgdGFic0xlbmd0aCA9IHRoaXMudGFicy5sZW5ndGg7XHJcbiAgICBpZiAoIXRhYnNMZW5ndGgpIHtcclxuICAgICAgcmV0dXJuIC0xO1xyXG4gICAgfVxyXG5cclxuICAgIGZvciAobGV0IHN0ZXAgPSAxOyBzdGVwIDw9IHRhYnNMZW5ndGg7IHN0ZXAgKz0gMSkge1xyXG4gICAgICBjb25zdCBwcmV2SW5kZXggPSBpbmRleCAtIHN0ZXA7XHJcbiAgICAgIGNvbnN0IG5leHRJbmRleCA9IGluZGV4ICsgc3RlcDtcclxuICAgICAgaWYgKHRoaXMudGFic1twcmV2SW5kZXhdICYmICF0aGlzLnRhYnNbcHJldkluZGV4XS5kaXNhYmxlZCkge1xyXG4gICAgICAgIHJldHVybiBwcmV2SW5kZXg7XHJcbiAgICAgIH1cclxuICAgICAgaWYgKHRoaXMudGFic1tuZXh0SW5kZXhdICYmICF0aGlzLnRhYnNbbmV4dEluZGV4XS5kaXNhYmxlZCkge1xyXG4gICAgICAgIHJldHVybiBuZXh0SW5kZXg7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIHJldHVybiAtMTtcclxuICB9XHJcblxyXG4gIHByb3RlY3RlZCBoYXNBdmFpbGFibGVUYWJzKGluZGV4OiBudW1iZXIpOiBib29sZWFuIHtcclxuICAgIGNvbnN0IHRhYnNMZW5ndGggPSB0aGlzLnRhYnMubGVuZ3RoO1xyXG4gICAgaWYgKCF0YWJzTGVuZ3RoKSB7XHJcbiAgICAgIHJldHVybiBmYWxzZTtcclxuICAgIH1cclxuXHJcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRhYnNMZW5ndGg7IGkgKz0gMSkge1xyXG4gICAgICBpZiAoIXRoaXMudGFic1tpXS5kaXNhYmxlZCAmJiBpICE9PSBpbmRleCkge1xyXG4gICAgICAgIHJldHVybiB0cnVlO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICByZXR1cm4gZmFsc2U7XHJcbiAgfVxyXG59XHJcbiJdfQ==