xui
Version:
xUI Components for Angular
264 lines • 36.1 kB
JavaScript
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, HostBinding, HostListener, Inject, Input, Output } from '@angular/core';
import { MAT_SNACK_BAR_DATA, MatSnackBar } from '@angular/material/snack-bar';
import { ComponentPortal } from '@angular/cdk/portal';
import { animate, state, style, transition, trigger, useAnimation } from '@angular/animations';
import { bounce, fadeInBottom, fadeOutBottom } from '../utils/animations';
import { lastValueFrom, Subject } from 'rxjs';
import { delay } from '../utils';
import * as i0 from "@angular/core";
import * as i1 from "@angular/material/snack-bar";
import * as i2 from "@angular/common";
import * as i3 from "../icon/icon.component";
import * as i4 from "@angular/cdk/portal";
import * as i5 from "@angular/cdk/a11y";
import * as i6 from "@ngx-translate/core";
import * as i7 from "../button/button.component";
export class SettingsComponent {
onKeydownHandler() {
this.close();
}
constructor(snackBar, cdr) {
this.snackBar = snackBar;
this.cdr = cdr;
this.mouseDown = false;
this.menuFocused = false;
this.defaultPage = 1;
this.opened = false;
this.openedAnimation = 'closed';
this.animationState = false;
this.canExit = true;
this.afterClosed = new EventEmitter();
this.stateChanged = (canExit) => {
this.canExit = canExit;
if (!canExit) {
if (!this.snackbarRef) {
this.snackbarRef = this.snackBar.openFromComponent(SaveResetSnackbarComponent, {
panelClass: 'x-settings-snackbar',
duration: undefined,
data: {
save: async () => {
try {
await this.instance?.save();
await this.hideSnackbar();
this.cdr.markForCheck();
}
catch (e) {
// TODO: show error snackbar
}
},
reset: async () => {
await this.instance?.reset();
await this.hideSnackbar();
this.cdr.markForCheck();
}
}
});
}
}
else {
this.hideSnackbar();
}
};
}
open(page = 1) {
this.defaultPage = page;
this.opened = true;
this.openedAnimation = 'opened';
this.navigate(this.defaultPage);
this.cdr.markForCheck();
}
async close() {
if (!this.canExit) {
this.animationState = true;
this.snackbarRef?.instance.alert();
return;
}
this.openedAnimation = 'closed';
await delay(100);
this.opened = false;
this.afterClosed.emit();
this.cdr.markForCheck();
}
attached(ref) {
this.instance = ref.instance;
this.instance.stateChanged = this.stateChanged;
}
navigate(idx) {
if (this.instance) {
if (!this.canExit) {
return;
}
}
const item = this.items?.[idx];
if (item) {
this.defaultPage = idx;
this.focusedItem = idx;
if (item.action) {
item.action();
}
else if (item.component) {
this.portal = new ComponentPortal(item.component);
}
}
}
focusPrev() {
let cur = this.focusedItem ?? this.items?.length ?? 0;
do {
cur--;
if (cur < 0) {
cur = (this.items?.length ?? 1) - 1;
}
} while (this.items?.[cur].type !== 'item');
this.focusedItem = cur;
}
focusNext() {
let cur = this.focusedItem ?? this.items?.length ?? 0;
do {
cur++;
if (cur >= (this.items?.length ?? 0)) {
cur = 0;
}
} while (this.items?.[cur].type !== 'item');
this.focusedItem = cur;
}
async hideSnackbar() {
await this.snackbarRef?.instance.close();
this.snackbarRef?.dismiss();
this.snackbarRef = undefined;
this.canExit = true;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.1", ngImport: i0, type: SettingsComponent, deps: [{ token: i1.MatSnackBar }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.1.1", type: SettingsComponent, selector: "xui-settings", inputs: { items: "items" }, outputs: { afterClosed: "afterClosed" }, host: { listeners: { "document:keydown.escape": "onKeydownHandler()" } }, ngImport: i0, template: "<dialog [open]=\"opened\" cdkTrapFocus>\n <div class=\"x-settings\" [@open]=\"openedAnimation\" [@bounce]=\"animationState\" (@bounce.done)=\"animationState = false\">\n <div class=\"x-settings-menu\">\n <nav\n tabindex=\"0\"\n (keydown.enter)=\"navigate(focusedItem ?? 0)\"\n (keydown.space)=\"navigate(focusedItem ?? 0)\"\n (keydown.arrowDown)=\"focusNext()\"\n (keydown.arrowUp)=\"focusPrev()\"\n (mousedown)=\"mouseDown = true\"\n (mouseup)=\"mouseDown = false\"\n (focusin)=\"menuFocused = !mouseDown\"\n (focusout)=\"menuFocused = false\"\n >\n <div\n *ngFor=\"let item of items; let i = index\"\n [class.x-settings-menu-item]=\"item.type === 'item'\"\n [class.x-settings-menu-item-active]=\"i === defaultPage\"\n [class.x-settings-menu-item-focus]=\"i === focusedItem && menuFocused\"\n [class.x-settings-menu-category]=\"item.type === 'category'\"\n [class.x-settings-menu-divider]=\"item.type === 'divider'\"\n [class.x-settings-menu-red]=\"item.critical\"\n (click)=\"navigate(i); menuFocused = false\"\n >\n {{ item.name ? (item.name | translate) : '' }}\n </div>\n </nav>\n </div>\n <div class=\"x-settings-right\">\n <div class=\"x-settings-content\">\n <ng-template [cdkPortalOutlet]=\"portal\" (attached)=\"attached($event)\"></ng-template>\n </div>\n\n <div class=\"x-settings-close-anchor\">\n <div class=\"x-settings-close\" (click)=\"close()\">\n <xui-icon tabindex=\"0\" (keydown.space)=\"close()\" (keydown.enter)=\"close()\">close-circle-outline</xui-icon>\n ESC\n </div>\n </div>\n </div>\n </div>\n</dialog>\n", dependencies: [{ kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "component", type: i3.IconComponent, selector: "xui-icon" }, { kind: "directive", type: i4.CdkPortalOutlet, selector: "[cdkPortalOutlet]", inputs: ["cdkPortalOutlet"], outputs: ["attached"], exportAs: ["cdkPortalOutlet"] }, { kind: "directive", type: i5.CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "pipe", type: i6.TranslatePipe, name: "translate" }], animations: [
trigger('bounce', [transition('* => *', useAnimation(bounce))]),
trigger('open', [
state('closed', style({
opacity: 0,
transform: 'scale(1.05)'
})),
state('opened', style({
opacity: 1,
transform: 'scale(1)'
})),
transition('* => *', animate(100))
])
], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.1", ngImport: i0, type: SettingsComponent, decorators: [{
type: Component,
args: [{ selector: 'xui-settings', changeDetection: ChangeDetectionStrategy.OnPush, animations: [
trigger('bounce', [transition('* => *', useAnimation(bounce))]),
trigger('open', [
state('closed', style({
opacity: 0,
transform: 'scale(1.05)'
})),
state('opened', style({
opacity: 1,
transform: 'scale(1)'
})),
transition('* => *', animate(100))
])
], template: "<dialog [open]=\"opened\" cdkTrapFocus>\n <div class=\"x-settings\" [@open]=\"openedAnimation\" [@bounce]=\"animationState\" (@bounce.done)=\"animationState = false\">\n <div class=\"x-settings-menu\">\n <nav\n tabindex=\"0\"\n (keydown.enter)=\"navigate(focusedItem ?? 0)\"\n (keydown.space)=\"navigate(focusedItem ?? 0)\"\n (keydown.arrowDown)=\"focusNext()\"\n (keydown.arrowUp)=\"focusPrev()\"\n (mousedown)=\"mouseDown = true\"\n (mouseup)=\"mouseDown = false\"\n (focusin)=\"menuFocused = !mouseDown\"\n (focusout)=\"menuFocused = false\"\n >\n <div\n *ngFor=\"let item of items; let i = index\"\n [class.x-settings-menu-item]=\"item.type === 'item'\"\n [class.x-settings-menu-item-active]=\"i === defaultPage\"\n [class.x-settings-menu-item-focus]=\"i === focusedItem && menuFocused\"\n [class.x-settings-menu-category]=\"item.type === 'category'\"\n [class.x-settings-menu-divider]=\"item.type === 'divider'\"\n [class.x-settings-menu-red]=\"item.critical\"\n (click)=\"navigate(i); menuFocused = false\"\n >\n {{ item.name ? (item.name | translate) : '' }}\n </div>\n </nav>\n </div>\n <div class=\"x-settings-right\">\n <div class=\"x-settings-content\">\n <ng-template [cdkPortalOutlet]=\"portal\" (attached)=\"attached($event)\"></ng-template>\n </div>\n\n <div class=\"x-settings-close-anchor\">\n <div class=\"x-settings-close\" (click)=\"close()\">\n <xui-icon tabindex=\"0\" (keydown.space)=\"close()\" (keydown.enter)=\"close()\">close-circle-outline</xui-icon>\n ESC\n </div>\n </div>\n </div>\n </div>\n</dialog>\n" }]
}], ctorParameters: function () { return [{ type: i1.MatSnackBar }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { items: [{
type: Input
}], afterClosed: [{
type: Output
}], onKeydownHandler: [{
type: HostListener,
args: ['document:keydown.escape']
}] } });
export class SaveResetSnackbarComponent {
constructor(data, cdr) {
this.data = data;
this.cdr = cdr;
this._doneAnimating = new Subject();
this.animation = 'open';
this.save = () => {
return this.data.save();
};
this.reset = () => {
return this.data.reset();
};
}
async close() {
this.animation = 'close';
return await lastValueFrom(this._doneAnimating.asObservable());
}
async alert() {
this.animation = 'alert';
await delay(1000);
this.animation = 'open';
this.cdr.markForCheck();
}
_animationDone(event) {
if (event.toState === 'close') {
this._doneAnimating.next(undefined);
this._doneAnimating.complete();
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.1", ngImport: i0, type: SaveResetSnackbarComponent, deps: [{ token: MAT_SNACK_BAR_DATA }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.1.1", type: SaveResetSnackbarComponent, selector: "xui-settings-snackbar", host: { listeners: { "@fade.done": "_animationDone($event)" }, properties: { "@fade": "this.animation" } }, ngImport: i0, template: `
{{ 'xui.settings.save_changes_text' | translate }}
<div>
<xui-button size="small" color="minimal" [onClick]="reset">{{ 'xui.settings.reset' | translate }}</xui-button>
<xui-button size="small" color="success" type="raised" [onClick]="save">
{{ 'xui.settings.save' | translate }}
</xui-button>
</div>
`, isInline: true, dependencies: [{ kind: "component", type: i7.ButtonComponent, selector: "xui-button", inputs: ["type", "size", "color", "shine", "disabled", "onClick", "stateDelay"], outputs: ["click"] }, { kind: "pipe", type: i6.TranslatePipe, name: "translate" }], animations: [
trigger('fade', [
state('close', style({
display: 'none'
})),
state('alert', style({
backgroundColor: 'var(--color-error-darker)',
transform: 'scale(1.1)'
})),
transition('open => alert', animate(200)),
transition('alert => open', animate(200)),
transition('open => close', useAnimation(fadeOutBottom)),
transition('void => open', useAnimation(fadeInBottom))
])
], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.1", ngImport: i0, type: SaveResetSnackbarComponent, decorators: [{
type: Component,
args: [{
selector: 'xui-settings-snackbar',
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
{{ 'xui.settings.save_changes_text' | translate }}
<div>
<xui-button size="small" color="minimal" [onClick]="reset">{{ 'xui.settings.reset' | translate }}</xui-button>
<xui-button size="small" color="success" type="raised" [onClick]="save">
{{ 'xui.settings.save' | translate }}
</xui-button>
</div>
`,
animations: [
trigger('fade', [
state('close', style({
display: 'none'
})),
state('alert', style({
backgroundColor: 'var(--color-error-darker)',
transform: 'scale(1.1)'
})),
transition('open => alert', animate(200)),
transition('alert => open', animate(200)),
transition('open => close', useAnimation(fadeOutBottom)),
transition('void => open', useAnimation(fadeInBottom))
])
]
}]
}], ctorParameters: function () { return [{ type: undefined, decorators: [{
type: Inject,
args: [MAT_SNACK_BAR_DATA]
}] }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { animation: [{
type: HostBinding,
args: ['@fade']
}], _animationDone: [{
type: HostListener,
args: ['@fade.done', ['$event']]
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2V0dGluZ3MuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vbGlicy94dWkvc3JjL3NldHRpbmdzL3NldHRpbmdzLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uL2xpYnMveHVpL3NyYy9zZXR0aW5ncy9zZXR0aW5ncy5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsdUJBQXVCLEVBQ3ZCLGlCQUFpQixFQUNqQixTQUFTLEVBRVQsWUFBWSxFQUNaLFdBQVcsRUFDWCxZQUFZLEVBQ1osTUFBTSxFQUNOLEtBQUssRUFDTCxNQUFNLEVBQ1AsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLGtCQUFrQixFQUFFLFdBQVcsRUFBa0IsTUFBTSw2QkFBNkIsQ0FBQztBQUM5RixPQUFPLEVBQThCLGVBQWUsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBRWxGLE9BQU8sRUFBRSxPQUFPLEVBQWtCLEtBQUssRUFBRSxLQUFLLEVBQUUsVUFBVSxFQUFFLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUMvRyxPQUFPLEVBQUUsTUFBTSxFQUFFLFlBQVksRUFBRSxhQUFhLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUMxRSxPQUFPLEVBQUUsYUFBYSxFQUFFLE9BQU8sRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUM5QyxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0sVUFBVSxDQUFDOzs7Ozs7Ozs7QUEyQmpDLE1BQU0sT0FBTyxpQkFBaUI7SUFtQmEsZ0JBQWdCO1FBQ3ZELElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztJQUNmLENBQUM7SUFFRCxZQUFvQixRQUFxQixFQUFVLEdBQXNCO1FBQXJELGFBQVEsR0FBUixRQUFRLENBQWE7UUFBVSxRQUFHLEdBQUgsR0FBRyxDQUFtQjtRQXRCekUsY0FBUyxHQUFHLEtBQUssQ0FBQztRQUNsQixnQkFBVyxH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Ozs7O0dBUVQ7b0JBQ0QsVUFBVSxFQUFFO3dCQUNWLE9BQU8sQ0FBQyxNQUFNLEVBQUU7NEJBQ2QsS0FBSyxDQUNILE9BQU8sRUFDUCxLQUFLLENBQUM7Z0NBQ0osT0FBTyxFQUFFLE1BQU07NkJBQ2hCLENBQUMsQ0FDSDs0QkFDRCxLQUFLLENBQ0gsT0FBTyxFQUNQLEtBQUssQ0FBQztnQ0FDSixlQUFlLEVBQUUsMkJBQTJCO2dDQUM1QyxTQUFTLEVBQUUsWUFBWTs2QkFDeEIsQ0FBQyxDQUNIOzRCQUNELFVBQVUsQ0FBQyxlQUFlLEVBQUUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDOzRCQUN6QyxVQUFVLENBQUMsZUFBZSxFQUFFLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQzs0QkFDekMsVUFBVSxDQUFDLGVBQWUsRUFBRSxZQUFZLENBQUMsYUFBYSxDQUFDLENBQUM7NEJBQ3hELFVBQVUsQ0FBQyxjQUFjLEVBQUUsWUFBWSxDQUFDLFlBQVksQ0FBQyxDQUFDO3lCQUN2RCxDQUFDO3FCQUNIO2lCQUNGOzswQkFPYyxNQUFNOzJCQUFDLGtCQUFrQjs0RUFGdEMsU0FBUztzQkFEUixXQUFXO3VCQUFDLE9BQU87Z0JBMEJwQixjQUFjO3NCQURiLFlBQVk7dUJBQUMsWUFBWSxFQUFFLENBQUMsUUFBUSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXG4gIENoYW5nZURldGVjdG9yUmVmLFxuICBDb21wb25lbnQsXG4gIENvbXBvbmVudFJlZixcbiAgRXZlbnRFbWl0dGVyLFxuICBIb3N0QmluZGluZyxcbiAgSG9zdExpc3RlbmVyLFxuICBJbmplY3QsXG4gIElucHV0LFxuICBPdXRwdXRcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBNQVRfU05BQ0tfQkFSX0RBVEEsIE1hdFNuYWNrQmFyLCBNYXRTbmFja0JhclJlZiB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL3NuYWNrLWJhcic7XG5pbXBvcnQgeyBDZGtQb3J0YWxPdXRsZXRBdHRhY2hlZFJlZiwgQ29tcG9uZW50UG9ydGFsIH0gZnJvbSAnQGFuZ3VsYXIvY2RrL3BvcnRhbCc7XG5pbXBvcnQgeyBTZXR0aW5nc1BhZ2UgfSBmcm9tICcuL3NldHRpbmdzLnR5cGVzJztcbmltcG9ydCB7IGFuaW1hdGUsIEFuaW1hdGlvbkV2ZW50LCBzdGF0ZSwgc3R5bGUsIHRyYW5zaXRpb24sIHRyaWdnZXIsIHVzZUFuaW1hdGlvbiB9IGZyb20gJ0Bhbmd1bGFyL2FuaW1hdGlvbnMnO1xuaW1wb3J0IHsgYm91bmNlLCBmYWRlSW5Cb3R0b20sIGZhZGVPdXRCb3R0b20gfSBmcm9tICcuLi91dGlscy9hbmltYXRpb25zJztcbmltcG9ydCB7IGxhc3RWYWx1ZUZyb20sIFN1YmplY3QgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IGRlbGF5IH0gZnJvbSAnLi4vdXRpbHMnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICd4dWktc2V0dGluZ3MnLFxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbiAgdGVtcGxhdGVVcmw6ICcuL3NldHRpbmdzLmNvbXBvbmVudC5odG1sJyxcbiAgYW5pbWF0aW9uczogW1xuICAgIHRyaWdnZXIoJ2JvdW5jZScsIFt0cmFuc2l0aW9uKCcqID0+IConLCB1c2VBbmltYXRpb24oYm91bmNlKSldKSxcbiAgICB0cmlnZ2VyKCdvcGVuJywgW1xuICAgICAgc3RhdGUoXG4gICAgICAgICdjbG9zZWQnLFxuICAgICAgICBzdHlsZSh7XG4gICAgICAgICAgb3BhY2l0eTogMCxcbiAgICAgICAgICB0cmFuc2Zvcm06ICdzY2FsZSgxLjA1KSdcbiAgICAgICAgfSlcbiAgICAgICksXG4gICAgICBzdGF0ZShcbiAgICAgICAgJ29wZW5lZCcsXG4gICAgICAgIHN0eWxlKHtcbiAgICAgICAgICBvcGFjaXR5OiAxLFxuICAgICAgICAgIHRyYW5zZm9ybTogJ3NjYWxlKDEpJ1xuICAgICAgICB9KVxuICAgICAgKSxcbiAgICAgIHRyYW5zaXRpb24oJyogPT4gKicsIGFuaW1hdGUoMTAwKSlcbiAgICBdKVxuICBdXG59KVxuZXhwb3J0IGNsYXNzIFNldHRpbmdzQ29tcG9uZW50IHtcbiAgbW91c2VEb3duID0gZmFsc2U7XG4gIG1lbnVGb2N1c2VkID0gZmFsc2U7XG4gIGZvY3VzZWRJdGVtPzogbnVtYmVyO1xuXG4gIGRlZmF1bHRQYWdlID0gMTtcbiAgb3BlbmVkID0gZmFsc2U7XG4gIG9wZW5lZEFuaW1hdGlvbjogJ29wZW5lZCcgfCAnY2xvc2VkJyA9ICdjbG9zZWQnO1xuICBhbmltYXRpb25TdGF0ZSA9IGZhbHNlO1xuXG4gIHBvcnRhbD86IENvbXBvbmVudFBvcnRhbDxTZXR0aW5nc1BhZ2U+O1xuICBpbnN0YW5jZT86IFNldHRpbmdzUGFnZTtcblxuICBwcml2YXRlIHNuYWNrYmFyUmVmPzogTWF0U25hY2tCYXJSZWY8U2F2ZVJlc2V0U25hY2tiYXJDb21wb25lbnQ+O1xuICBwcml2YXRlIGNhbkV4aXQgPSB0cnVlO1xuXG4gIEBJbnB1dCgpIGl0ZW1zPzogTWVudUl0ZW1bXTtcbiAgQE91dHB1dCgpIGFmdGVyQ2xvc2VkID0gbmV3IEV2ZW50RW1pdHRlcjx2b2lkPigpO1xuXG4gIEBIb3N0TGlzdGVuZXIoJ2RvY3VtZW50OmtleWRvd24uZXNjYXBlJykgb25LZXlkb3duSGFuZGxlcigpIHtcbiAgICB0aGlzLmNsb3NlKCk7XG4gIH1cblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHNuYWNrQmFyOiBNYXRTbmFja0JhciwgcHJpdmF0ZSBjZHI6IENoYW5nZURldGVjdG9yUmVmKSB7fVxuXG4gIHN0YXRlQ2hhbmdlZCA9IChjYW5FeGl0OiBib29sZWFuKSA9PiB7XG4gICAgdGhpcy5jYW5FeGl0ID0gY2FuRXhpdDtcblxuICAgIGlmICghY2FuRXhpdCkge1xuICAgICAgaWYgKCF0aGlzLnNuYWNrYmFyUmVmKSB7XG4gICAgICAgIHRoaXMuc25hY2tiYXJSZWYgPSB0aGlzLnNuYWNrQmFyLm9wZW5Gcm9tQ29tcG9uZW50KFNhdmVSZXNldFNuYWNrYmFyQ29tcG9uZW50LCB7XG4gICAgICAgICAgcGFuZWxDbGFzczogJ3gtc2V0dGluZ3Mtc25hY2tiYXInLFxuICAgICAgICAgIGR1cmF0aW9uOiB1bmRlZmluZWQhLFxuICAgICAgICAgIGRhdGE6IHtcbiAgICAgICAgICAgIHNhdmU6IGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLmluc3RhbmNlPy5zYXZlKCk7XG4gICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5oaWRlU25hY2tiYXIoKTtcbiAgICAgICAgICAgICAgICB0aGlzLmNkci5tYXJrRm9yQ2hlY2soKTtcbiAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgIC8vIFRPRE86IHNob3cgZXJyb3Igc25hY2tiYXJcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHJlc2V0OiBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICAgIGF3YWl0IHRoaXMuaW5zdGFuY2U/LnJlc2V0KCk7XG4gICAgICAgICAgICAgIGF3YWl0IHRoaXMuaGlkZVNuYWNrYmFyKCk7XG4gICAgICAgICAgICAgIHRoaXMuY2RyLm1hcmtGb3JDaGVjaygpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuaGlkZVNuYWNrYmFyKCk7XG4gICAgfVxuICB9O1xuXG4gIG9wZW4ocGFnZSA9IDEpIHtcbiAgICB0aGlzLmRlZmF1bHRQYWdlID0gcGFnZTtcbiAgICB0aGlzLm9wZW5lZCA9IHRydWU7XG4gICAgdGhpcy5vcGVuZWRBbmltYXRpb24gPSAnb3BlbmVkJztcbiAgICB0aGlzLm5hdmlnYXRlKHRoaXMuZGVmYXVsdFBhZ2UpO1xuICAgIHRoaXMuY2RyLm1hcmtGb3JDaGVjaygpO1xuICB9XG5cbiAgYXN5bmMgY2xvc2UoKSB7XG4gICAgaWYgKCF0aGlzLmNhbkV4aXQpIHtcbiAgICAgIHRoaXMuYW5pbWF0aW9uU3RhdGUgPSB0cnVlO1xuICAgICAgdGhpcy5zbmFja2JhclJlZj8uaW5zdGFuY2UuYWxlcnQoKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLm9wZW5lZEFuaW1hdGlvbiA9ICdjbG9zZWQnO1xuICAgIGF3YWl0IGRlbGF5KDEwMCk7XG4gICAgdGhpcy5vcGVuZWQgPSBmYWxzZTtcbiAgICB0aGlzLmFmdGVyQ2xvc2VkLmVtaXQoKTtcbiAgICB0aGlzLmNkci5tYXJrRm9yQ2hlY2soKTtcbiAgfVxuXG4gIGF0dGFjaGVkKHJlZjogQ2RrUG9ydGFsT3V0bGV0QXR0YWNoZWRSZWYpIHtcbiAgICB0aGlzLmluc3RhbmNlID0gKHJlZiBhcyBDb21wb25lbnRSZWY8U2V0dGluZ3NQYWdlPikuaW5zdGFuY2U7XG4gICAgdGhpcy5pbnN0YW5jZS5zdGF0ZUNoYW5nZWQgPSB0aGlzLnN0YXRlQ2hhbmdlZDtcbiAgfVxuXG4gIG5hdmlnYXRlKGlkeDogbnVtYmVyKSB7XG4gICAgaWYgKHRoaXMuaW5zdGFuY2UpIHtcbiAgICAgIGlmICghdGhpcy5jYW5FeGl0KSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBpdGVtID0gdGhpcy5pdGVtcz8uW2lkeF07XG4gICAgaWYgKGl0ZW0pIHtcbiAgICAgIHRoaXMuZGVmYXVsdFBhZ2UgPSBpZHg7XG4gICAgICB0aGlzLmZvY3VzZWRJdGVtID0gaWR4O1xuXG4gICAgICBpZiAoaXRlbS5hY3Rpb24pIHtcbiAgICAgICAgaXRlbS5hY3Rpb24oKTtcbiAgICAgIH0gZWxzZSBpZiAoaXRlbS5jb21wb25lbnQpIHtcbiAgICAgICAgdGhpcy5wb3J0YWwgPSBuZXcgQ29tcG9uZW50UG9ydGFsKGl0ZW0uY29tcG9uZW50KTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBmb2N1c1ByZXYoKSB7XG4gICAgbGV0IGN1ciA9IHRoaXMuZm9jdXNlZEl0ZW0gPz8gdGhpcy5pdGVtcz8ubGVuZ3RoID8/IDA7XG5cbiAgICBkbyB7XG4gICAgICBjdXItLTtcbiAgICAgIGlmIChjdXIgPCAwKSB7XG4gICAgICAgIGN1ciA9ICh0aGlzLml0ZW1zPy5sZW5ndGggPz8gMSkgLSAxO1xuICAgICAgfVxuICAgIH0gd2hpbGUgKHRoaXMuaXRlbXM/LltjdXJdLnR5cGUgIT09ICdpdGVtJyk7XG4gICAgdGhpcy5mb2N1c2VkSXRlbSA9IGN1cjtcbiAgfVxuXG4gIGZvY3VzTmV4dCgpIHtcbiAgICBsZXQgY3VyID0gdGhpcy5mb2N1c2VkSXRlbSA/PyB0aGlzLml0ZW1zPy5sZW5ndGggPz8gMDtcblxuICAgIGRvIHtcbiAgICAgIGN1cisrO1xuICAgICAgaWYgKGN1ciA+PSAodGhpcy5pdGVtcz8ubGVuZ3RoID8/IDApKSB7XG4gICAgICAgIGN1ciA9IDA7XG4gICAgICB9XG4gICAgfSB3aGlsZSAodGhpcy5pdGVtcz8uW2N1cl0udHlwZSAhPT0gJ2l0ZW0nKTtcbiAgICB0aGlzLmZvY3VzZWRJdGVtID0gY3VyO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBoaWRlU25hY2tiYXIoKSB7XG4gICAgYXdhaXQgdGhpcy5zbmFja2JhclJlZj8uaW5zdGFuY2UuY2xvc2UoKTtcbiAgICB0aGlzLnNuYWNrYmFyUmVmPy5kaXNtaXNzKCk7XG4gICAgdGhpcy5zbmFja2JhclJlZiA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLmNhbkV4aXQgPSB0cnVlO1xuICB9XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgTWVudUl0ZW0ge1xuICB0eXBlOiAnY2F0ZWdvcnknIHwgJ2l0ZW0nIHwgJ2RpdmlkZXInO1xuICBuYW1lPzogc3RyaW5nO1xuICBjcml0aWNhbD86IGJvb2xlYW47XG4gIGNvbXBvbmVudD86IGFueTtcbiAgYWN0aW9uPzogKCkgPT4gdm9pZDtcbn1cblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAneHVpLXNldHRpbmdzLXNuYWNrYmFyJyxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gIHRlbXBsYXRlOiBgXG4gICAge3sgJ3h1aS5zZXR0aW5ncy5zYXZlX2NoYW5nZXNfdGV4dCcgfCB0cmFuc2xhdGUgfX1cbiAgICA8ZGl2PlxuICAgICAgPHh1aS1idXR0b24gc2l6ZT1cInNtYWxsXCIgY29sb3I9XCJtaW5pbWFsXCIgW29uQ2xpY2tdPVwicmVzZXRcIj57eyAneHVpLnNldHRpbmdzLnJlc2V0JyB8IHRyYW5zbGF0ZSB9fTwveHVpLWJ1dHRvbj5cbiAgICAgIDx4dWktYnV0dG9uIHNpemU9XCJzbWFsbFwiIGNvbG9yPVwic3VjY2Vzc1wiIHR5cGU9XCJyYWlzZWRcIiBbb25DbGlja109XCJzYXZlXCI+XG4gICAgICAgIHt7ICd4dWkuc2V0dGluZ3Muc2F2ZScgfCB0cmFuc2xhdGUgfX1cbiAgICAgIDwveHVpLWJ1dHRvbj5cbiAgICA8L2Rpdj5cbiAgYCxcbiAgYW5pbWF0aW9uczogW1xuICAgIHRyaWdnZXIoJ2ZhZGUnLCBbXG4gICAgICBzdGF0ZShcbiAgICAgICAgJ2Nsb3NlJyxcbiAgICAgICAgc3R5bGUoe1xuICAgICAgICAgIGRpc3BsYXk6ICdub25lJ1xuICAgICAgICB9KVxuICAgICAgKSxcbiAgICAgIHN0YXRlKFxuICAgICAgICAnYWxlcnQnLFxuICAgICAgICBzdHlsZSh7XG4gICAgICAgICAgYmFja2dyb3VuZENvbG9yOiAndmFyKC0tY29sb3ItZXJyb3ItZGFya2VyKScsXG4gICAgICAgICAgdHJhbnNmb3JtOiAnc2NhbGUoMS4xKSdcbiAgICAgICAgfSlcbiAgICAgICksXG4gICAgICB0cmFuc2l0aW9uKCdvcGVuID0+IGFsZXJ0JywgYW5pbWF0ZSgyMDApKSxcbiAgICAgIHRyYW5zaXRpb24oJ2FsZXJ0ID0+IG9wZW4nLCBhbmltYXRlKDIwMCkpLFxuICAgICAgdHJhbnNpdGlvbignb3BlbiA9PiBjbG9zZScsIHVzZUFuaW1hdGlvbihmYWRlT3V0Qm90dG9tKSksXG4gICAgICB0cmFuc2l0aW9uKCd2b2lkID0+IG9wZW4nLCB1c2VBbmltYXRpb24oZmFkZUluQm90dG9tKSlcbiAgICBdKVxuICBdXG59KVxuZXhwb3J0IGNsYXNzIFNhdmVSZXNldFNuYWNrYmFyQ29tcG9uZW50IHtcbiAgX2RvbmVBbmltYXRpbmcgPSBuZXcgU3ViamVjdCgpO1xuXG4gIEBIb3N0QmluZGluZygnQGZhZGUnKVxuICBhbmltYXRpb24gPSAnb3Blbic7XG5cbiAgY29uc3RydWN0b3IoQEluamVjdChNQVRfU05BQ0tfQkFSX0RBVEEpIHByaXZhdGUgZGF0YTogYW55LCBwcml2YXRlIGNkcjogQ2hhbmdlRGV0ZWN0b3JSZWYpIHt9XG5cbiAgYXN5bmMgY2xvc2UoKSB7XG4gICAgdGhpcy5hbmltYXRpb24gPSAnY2xvc2UnO1xuICAgIHJldHVybiBhd2FpdCBsYXN0VmFsdWVGcm9tKHRoaXMuX2RvbmVBbmltYXRpbmcuYXNPYnNlcnZhYmxlKCkpO1xuICB9XG5cbiAgYXN5bmMgYWxlcnQoKSB7XG4gICAgdGhpcy5hbmltYXRpb24gPSAnYWxlcnQnO1xuICAgIGF3YWl0IGRlbGF5KDEwMDApO1xuICAgIHRoaXMuYW5pbWF0aW9uID0gJ29wZW4nO1xuICAgIHRoaXMuY2RyLm1hcmtGb3JDaGVjaygpO1xuICB9XG5cbiAgc2F2ZSA9ICgpID0+IHtcbiAgICByZXR1cm4gdGhpcy5kYXRhLnNhdmUoKTtcbiAgfTtcblxuICByZXNldCA9ICgpID0+IHtcbiAgICByZXR1cm4gdGhpcy5kYXRhLnJlc2V0KCk7XG4gIH07XG5cbiAgQEhvc3RMaXN0ZW5lcignQGZhZGUuZG9uZScsIFsnJGV2ZW50J10pXG4gIF9hbmltYXRpb25Eb25lKGV2ZW50OiBBbmltYXRpb25FdmVudCkge1xuICAgIGlmIChldmVudC50b1N0YXRlID09PSAnY2xvc2UnKSB7XG4gICAgICB0aGlzLl9kb25lQW5pbWF0aW5nLm5leHQodW5kZWZpbmVkKTtcbiAgICAgIHRoaXMuX2RvbmVBbmltYXRpbmcuY29tcGxldGUoKTtcbiAgICB9XG4gIH1cbn1cbiIsIjxkaWFsb2cgW29wZW5dPVwib3BlbmVkXCIgY2RrVHJhcEZvY3VzPlxuICA8ZGl2IGNsYXNzPVwieC1zZXR0aW5nc1wiIFtAb3Blbl09XCJvcGVuZWRBbmltYXRpb25cIiBbQGJvdW5jZV09XCJhbmltYXRpb25TdGF0ZVwiIChAYm91bmNlLmRvbmUpPVwiYW5pbWF0aW9uU3RhdGUgPSBmYWxzZVwiPlxuICAgIDxkaXYgY2xhc3M9XCJ4LXNldHRpbmdzLW1lbnVcIj5cbiAgICAgIDxuYXZcbiAgICAgICAgdGFiaW5kZXg9XCIwXCJcbiAgICAgICAgKGtleWRvd24uZW50ZXIpPVwibmF2aWdhdGUoZm9jdXNlZEl0ZW0gPz8gMClcIlxuICAgICAgICAoa2V5ZG93bi5zcGFjZSk9XCJuYXZpZ2F0ZShmb2N1c2VkSXRlbSA/PyAwKVwiXG4gICAgICAgIChrZXlkb3duLmFycm93RG93bik9XCJmb2N1c05leHQoKVwiXG4gICAgICAgIChrZXlkb3duLmFycm93VXApPVwiZm9jdXNQcmV2KClcIlxuICAgICAgICAobW91c2Vkb3duKT1cIm1vdXNlRG93biA9IHRydWVcIlxuICAgICAgICAobW91c2V1cCk9XCJtb3VzZURvd24gPSBmYWxzZVwiXG4gICAgICAgIChmb2N1c2luKT1cIm1lbnVGb2N1c2VkID0gIW1vdXNlRG93blwiXG4gICAgICAgIChmb2N1c291dCk9XCJtZW51Rm9jdXNlZCA9IGZhbHNlXCJcbiAgICAgID5cbiAgICAgICAgPGRpdlxuICAgICAgICAgICpuZ0Zvcj1cImxldCBpdGVtIG9mIGl0ZW1zOyBsZXQgaSA9IGluZGV4XCJcbiAgICAgICAgICBbY2xhc3MueC1zZXR0aW5ncy1tZW51LWl0ZW1dPVwiaXRlbS50eXBlID09PSAnaXRlbSdcIlxuICAgICAgICAgIFtjbGFzcy54LXNldHRpbmdzLW1lbnUtaXRlbS1hY3RpdmVdPVwiaSA9PT0gZGVmYXVsdFBhZ2VcIlxuICAgICAgICAgIFtjbGFzcy54LXNldHRpbmdzLW1lbnUtaXRlbS1mb2N1c109XCJpID09PSBmb2N1c2VkSXRlbSAmJiBtZW51Rm9jdXNlZFwiXG4gICAgICAgICAgW2NsYXNzLngtc2V0dGluZ3MtbWVudS1jYXRlZ29yeV09XCJpdGVtLnR5cGUgPT09ICdjYXRlZ29yeSdcIlxuICAgICAgICAgIFtjbGFzcy54LXNldHRpbmdzLW1lbnUtZGl2aWRlcl09XCJpdGVtLnR5cGUgPT09ICdkaXZpZGVyJ1wiXG4gICAgICAgICAgW2NsYXNzLngtc2V0dGluZ3MtbWVudS1yZWRdPVwiaXRlbS5jcml0aWNhbFwiXG4gICAgICAgICAgKGNsaWNrKT1cIm5hdmlnYXRlKGkpOyBtZW51Rm9jdXNlZCA9IGZhbHNlXCJcbiAgICAgICAgPlxuICAgICAgICAgIHt7IGl0ZW0ubmFtZSA/IChpdGVtLm5hbWUgfCB0cmFuc2xhdGUpIDogJycgfX1cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L25hdj5cbiAgICA8L2Rpdj5cbiAgICA8ZGl2IGNsYXNzPVwieC1zZXR0aW5ncy1yaWdodFwiPlxuICAgICAgPGRpdiBjbGFzcz1cIngtc2V0dGluZ3MtY29udGVudFwiPlxuICAgICAgICA8bmctdGVtcGxhdGUgW2Nka1BvcnRhbE91dGxldF09XCJwb3J0YWxcIiAoYXR0YWNoZWQpPVwiYXR0YWNoZWQoJGV2ZW50KVwiPjwvbmctdGVtcGxhdGU+XG4gICAgICA8L2Rpdj5cblxuICAgICAgPGRpdiBjbGFzcz1cIngtc2V0dGluZ3MtY2xvc2UtYW5jaG9yXCI+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJ4LXNldHRpbmdzLWNsb3NlXCIgKGNsaWNrKT1cImNsb3NlKClcIj5cbiAgICAgICAgICA8eHVpLWljb24gdGFiaW5kZXg9XCIwXCIgKGtleWRvd24uc3BhY2UpPVwiY2xvc2UoKVwiIChrZXlkb3duLmVudGVyKT1cImNsb3NlKClcIj5jbG9zZS1jaXJjbGUtb3V0bGluZTwveHVpLWljb24+XG4gICAgICAgICAgRVNDXG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9kaXY+XG4gICAgPC9kaXY+XG4gIDwvZGl2PlxuPC9kaWFsb2c+XG4iXX0=