UNPKG

kwikui

Version:

KwikID's UI Component Library in Angular

208 lines 28.1 kB
import { Component, EventEmitter, forwardRef, Input, Output } from "@angular/core"; import { FormControl, FormGroup, NG_VALUE_ACCESSOR } from "@angular/forms"; import { TUI_INPUT_PASSWORD_DEFAULT_OPTIONS, TUI_INPUT_PASSWORD_OPTIONS } from "@taiga-ui/kit"; import { Subscription } from "rxjs"; import { distinctUntilChanged } from "rxjs/operators"; import { throwErrorMessage } from "../../../../helpers/kwikui.common.helpers"; import { DEFAULT_VALUES, VALIDATE_KEY_VALUES } from "./input-password.constants"; import { isValidKeyValue } from "./input-password.validations"; import * as i0 from "@angular/core"; import * as i1 from "@taiga-ui/kit"; import * as i2 from "@taiga-ui/core"; import * as i3 from "@angular/forms"; import * as i4 from "@angular/common"; export class KwikUIInputPasswordComponent { constructor() { this.disabled = DEFAULT_VALUES.disabled; this.focus = DEFAULT_VALUES.focus; this.formControl = new FormControl({}); this.formControlName = DEFAULT_VALUES.formControlName; this.hintContent = DEFAULT_VALUES.hintContent; this.icon = DEFAULT_VALUES.icon; this.id = DEFAULT_VALUES.id; this.invalid = DEFAULT_VALUES.invalid; this.label = DEFAULT_VALUES.label; this.placeholder = DEFAULT_VALUES.placeholder; this.postfix = DEFAULT_VALUES.postfix; this.prefix = DEFAULT_VALUES.prefix; this.properties = { readOnly: false }; this.size = DEFAULT_VALUES.size; this.validators = { required: true }; this.getKeyValue = new EventEmitter(); this.formGroup = new FormGroup({}); this.subscriptions = new Subscription(); } ngOnInit() { this.formGroup.addControl(this.formControlName, this.formControl); this.focus = this.focus === undefined ? false : this.focus; this.invalid = this.invalid === undefined ? false : this.invalid && this.focus; this.validators = Object.assign({}, this.validators); this.properties = Object.assign({}, this.properties); this.setDisabled(); this.subscriptions.add(this.formGroup.controls[this.formControlName].valueChanges .pipe(distinctUntilChanged()) // makes sure the value has actually changed. .subscribe((value) => this.handleInputValueChange(value))); } ngOnChanges(changes) { const verifyChange = (key) => { return changes.hasOwnProperty(key) && !changes[key].firstChange; }; for (const change of Object.entries(changes)) { const key = change[0]; const value = change[1].currentValue; this.validateInputProperty(key, value); } if (verifyChange("formControl")) { this.formControl = changes.formControl.currentValue; } if (verifyChange("invalid")) { this.invalid = Boolean(changes.invalid.currentValue); this.setError(); } if (verifyChange("focus")) { this.focus = Boolean(changes.focus.currentValue); } if (verifyChange("disabled")) { this.disabled = Boolean(changes.disabled.currentValue); this.setDisabled(); } } ngOnDestroy() { this.subscriptions.unsubscribe(); // ensure when component is destroyed the subscription is also and not left open. } validateInputProperty(key, value) { if (VALIDATE_KEY_VALUES[key] && !isValidKeyValue(key, value)) { this[key] = DEFAULT_VALUES[key]; throwErrorMessage("kwikui-input-password", this.id, key, value, DEFAULT_VALUES[key]); } } /** * @description Handles setting up of error and focus on the input field is it is invalid */ setDisabled() { if (this.formGroup.controls[this.formControlName] !== undefined) { if (this.disabled === true) { this.formGroup.controls[this.formControlName].disable({ emitEvent: false }); } else { this.formGroup.controls[this.formControlName].enable({ emitEvent: false }); } } } /** * @description Handles setting up of error and focus on the input field is it is invalid */ setError() { if (this.formGroup.controls[this.formControlName] !== undefined && this.formGroup.controls[this.formControlName].invalid) { this.invalid = true; this.focus = true; } else { this.invalid = false; this.focus = false; } } /** * @description Handles firing of 2 events on (keyup) event * * @param value */ handleInputValueChange(value) { if (value === this.formControl.value) { this.emitEvent(this.getKeyValue, { key: this.formControlName, value: this.formControl.value }); } } handleFocusedChange(e) { if (!this.invalid) { this.focus = e; } } emitEvent(event, data) { event.emit(data); } /** Method Implementations for Abstract Control */ writeValue(value) { } registerOnChange(fn) { } registerOnTouched(fn) { } setDisabledState(isDisabled) { } } /** @nocollapse */ KwikUIInputPasswordComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.17", ngImport: i0, type: KwikUIInputPasswordComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); /** @nocollapse */ KwikUIInputPasswordComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.17", type: KwikUIInputPasswordComponent, selector: "kwikui-input-password", inputs: { disabled: "disabled", focus: "focus", formControl: "formControl", formControlName: "formControlName", hintContent: "hintContent", icon: "icon", id: "id", invalid: "invalid", label: "label", placeholder: "placeholder", postfix: "postfix", prefix: "prefix", properties: "properties", size: "size", validators: "validators" }, outputs: { getKeyValue: "getKeyValue" }, providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef((() => KwikUIInputPasswordComponent)), multi: true }, { provide: TUI_INPUT_PASSWORD_OPTIONS, useValue: Object.assign(Object.assign({}, TUI_INPUT_PASSWORD_DEFAULT_OPTIONS), { icons: { hide: "tuiIconEyeOff", show: "tuiIconEye" } }) } ], usesOnChanges: true, ngImport: i0, template: "<div [formGroup]=\"formGroup\">\n <tui-input-password\n [formControlName]=\"formControlName\"\n [nativeId]=\"id\"\n [pseudoFocus]=\"focus ?? null\"\n [pseudoInvalid]=\"invalid === undefined ? null : invalid\"\n [readOnly]=\"properties?.readOnly ?? false\"\n [tuiHintContent]=\"hintContent\"\n [tuiTextfieldCleaner]=\"true\"\n [tuiTextfieldIconLeft]=\"icon\"\n [tuiTextfieldPostfix]=\"postfix\"\n [tuiTextfieldPrefix]=\"prefix\"\n [tuiTextfieldSize]=\"size\"\n (focusedChange)=\"handleFocusedChange($event)\"\n >\n {{ label }}\n <span\n class=\"tui-required\"\n *ngIf=\"validators.required\"\n ></span>\n <input\n tuiTextfield\n [attr.placeholder]=\"placeholder ?? ''\"\n [attr.required]=\"validators.required\"\n />\n </tui-input-password>\n</div>\n", styles: [""], components: [{ type: i1.TuiInputPasswordComponent, selector: "tui-input-password" }, { type: i2.TuiTextfieldComponent, selector: "input[tuiTextfield], textarea[tuiTextfield]" }], directives: [{ type: i3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { type: i3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { type: i1.TuiInputPasswordDirective, selector: "tui-input-password" }, { type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i3.FormControlName, selector: "[formControlName]", inputs: ["disabled", "formControlName", "ngModel"], outputs: ["ngModelChange"] }, { type: i2.TuiHintOptionsDirective, selector: "[tuiHintContent]", inputs: ["tuiHintContent", "tuiHintDirection", "tuiHintAppearance", "tuiHintShowDelay", "tuiHintHideDelay"] }, { type: i2.TuiTextfieldCleanerDirective, selector: "[tuiTextfieldCleaner]", inputs: ["tuiTextfieldCleaner"] }, { type: i2.TuiTextfieldIconLeftDirective, selector: "[tuiTextfieldIconLeft]", inputs: ["tuiTextfieldIconLeft"] }, { type: i2.TuiTextfieldPostfixDirective, selector: "[tuiTextfieldPostfix]", inputs: ["tuiTextfieldPostfix"] }, { type: i2.TuiTextfieldPrefixDirective, selector: "[tuiTextfieldPrefix]", inputs: ["tuiTextfieldPrefix"] }, { type: i2.TuiTextfieldSizeDirective, selector: "[tuiTextfieldSize]", inputs: ["tuiTextfieldSize"] }, { type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.17", ngImport: i0, type: KwikUIInputPasswordComponent, decorators: [{ type: Component, args: [{ selector: "kwikui-input-password", templateUrl: "./input-password.component.html", styleUrls: ["./input-password.component.scss"], providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef((() => KwikUIInputPasswordComponent)), multi: true }, { provide: TUI_INPUT_PASSWORD_OPTIONS, useValue: Object.assign(Object.assign({}, TUI_INPUT_PASSWORD_DEFAULT_OPTIONS), { icons: { hide: "tuiIconEyeOff", show: "tuiIconEye" } }) } ] }] }], ctorParameters: function () { return []; }, propDecorators: { disabled: [{ type: Input }], focus: [{ type: Input }], formControl: [{ type: Input }], formControlName: [{ type: Input }], hintContent: [{ type: Input }], icon: [{ type: Input }], id: [{ type: Input }], invalid: [{ type: Input }], label: [{ type: Input }], placeholder: [{ type: Input }], postfix: [{ type: Input }], prefix: [{ type: Input }], properties: [{ type: Input }], size: [{ type: Input }], validators: [{ type: Input }], getKeyValue: [{ type: Output }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5wdXQtcGFzc3dvcmQuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMva3dpa3VpL3NyYy9saWIvY29tcG9uZW50cy9jb3JlL2lucHV0cy9pbnB1dC1wYXNzd29yZC9pbnB1dC1wYXNzd29yZC5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9rd2lrdWkvc3JjL2xpYi9jb21wb25lbnRzL2NvcmUvaW5wdXRzL2lucHV0LXBhc3N3b3JkL2lucHV0LXBhc3N3b3JkLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCxTQUFTLEVBQ1QsWUFBWSxFQUNaLFVBQVUsRUFDVixLQUFLLEVBR0wsTUFBTSxFQUVQLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFFTCxXQUFXLEVBQ1gsU0FBUyxFQUNULGlCQUFpQixFQUNsQixNQUFNLGdCQUFnQixDQUFDO0FBQ3hCLE9BQU8sRUFDTCxrQ0FBa0MsRUFDbEMsMEJBQTBCLEVBQzNCLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDcEMsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDdEQsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sMkNBQTJDLENBQUM7QUFDOUUsT0FBTyxFQUNMLGNBQWMsRUFDZCxtQkFBbUIsRUFDcEIsTUFBTSw0QkFBNEIsQ0FBQztBQUVwQyxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sOEJBQThCLENBQUM7Ozs7OztBQXdCL0QsTUFBTSxPQUFPLDRCQUE0QjtJQXNDdkM7UUFwQ1MsYUFBUSxHQUFZLGNBQWMsQ0FBQyxRQUFRLENBQUM7UUFFNUMsVUFBSyxHQUFZLGNBQWMsQ0FBQyxLQUFLLENBQUM7UUFFdEMsZ0JBQVcsR0FBZ0IsSUFBSSxX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QUNGO3lCQUNGO3FCQUNGO2lCQUNGOzBFQUdVLFFBQVE7c0JBQWhCLEtBQUs7Z0JBRUcsS0FBSztzQkFBYixLQUFLO2dCQUVHLFdBQVc7c0JBQW5CLEtBQUs7Z0JBRUcsZUFBZTtzQkFBdkIsS0FBSztnQkFFRyxXQUFXO3NCQUFuQixLQUFLO2dCQUVHLElBQUk7c0JBQVosS0FBSztnQkFFRyxFQUFFO3NCQUFWLEtBQUs7Z0JBRUcsT0FBTztzQkFBZixLQUFLO2dCQUVHLEtBQUs7c0JBQWIsS0FBSztnQkFFRyxXQUFXO3NCQUFuQixLQUFLO2dCQUVHLE9BQU87c0JBQWYsS0FBSztnQkFFRyxNQUFNO3NCQUFkLEtBQUs7Z0JBRUcsVUFBVTtzQkFBbEIsS0FBSztnQkFFRyxJQUFJO3NCQUFaLEtBQUs7Z0JBRUcsVUFBVTtzQkFBbEIsS0FBSztnQkFFSSxXQUFXO3NCQUFwQixNQUFNIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQ29tcG9uZW50LFxuICBFdmVudEVtaXR0ZXIsXG4gIGZvcndhcmRSZWYsXG4gIElucHV0LFxuICBPbkNoYW5nZXMsXG4gIE9uSW5pdCxcbiAgT3V0cHV0LFxuICBTaW1wbGVDaGFuZ2VzXG59IGZyb20gXCJAYW5ndWxhci9jb3JlXCI7XG5pbXBvcnQge1xuICBDb250cm9sVmFsdWVBY2Nlc3NvcixcbiAgRm9ybUNvbnRyb2wsXG4gIEZvcm1Hcm91cCxcbiAgTkdfVkFMVUVfQUNDRVNTT1Jcbn0gZnJvbSBcIkBhbmd1bGFyL2Zvcm1zXCI7XG5pbXBvcnQge1xuICBUVUlfSU5QVVRfUEFTU1dPUkRfREVGQVVMVF9PUFRJT05TLFxuICBUVUlfSU5QVVRfUEFTU1dPUkRfT1BUSU9OU1xufSBmcm9tIFwiQHRhaWdhLXVpL2tpdFwiO1xuaW1wb3J0IHsgU3Vic2NyaXB0aW9uIH0gZnJvbSBcInJ4anNcIjtcbmltcG9ydCB7IGRpc3RpbmN0VW50aWxDaGFuZ2VkIH0gZnJvbSBcInJ4anMvb3BlcmF0b3JzXCI7XG5pbXBvcnQgeyB0aHJvd0Vycm9yTWVzc2FnZSB9IGZyb20gXCIuLi8uLi8uLi8uLi9oZWxwZXJzL2t3aWt1aS5jb21tb24uaGVscGVyc1wiO1xuaW1wb3J0IHtcbiAgREVGQVVMVF9WQUxVRVMsXG4gIFZBTElEQVRFX0tFWV9WQUxVRVNcbn0gZnJvbSBcIi4vaW5wdXQtcGFzc3dvcmQuY29uc3RhbnRzXCI7XG5pbXBvcnQgeyBUS3dpa1VJSW5wdXRQYXNzd29yZFNpemUgfSBmcm9tIFwiLi9pbnB1dC1wYXNzd29yZC5kZWZpbml0aW9uc1wiO1xuaW1wb3J0IHsgaXNWYWxpZEtleVZhbHVlIH0gZnJvbSBcIi4vaW5wdXQtcGFzc3dvcmQudmFsaWRhdGlvbnNcIjtcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiBcImt3aWt1aS1pbnB1dC1wYXNzd29yZFwiLFxuICB0ZW1wbGF0ZVVybDogXCIuL2lucHV0LXBhc3N3b3JkLmNvbXBvbmVudC5odG1sXCIsXG4gIHN0eWxlVXJsczogW1wiLi9pbnB1dC1wYXNzd29yZC5jb21wb25lbnQuc2Nzc1wiXSxcbiAgcHJvdmlkZXJzOiBbXG4gICAge1xuICAgICAgcHJvdmlkZTogTkdfVkFMVUVfQUNDRVNTT1IsXG4gICAgICB1c2VFeGlzdGluZzogZm9yd2FyZFJlZigoKSA9PiBLd2lrVUlJbnB1dFBhc3N3b3JkQ29tcG9uZW50KSxcbiAgICAgIG11bHRpOiB0cnVlXG4gICAgfSxcbiAgICB7XG4gICAgICBwcm92aWRlOiBUVUlfSU5QVVRfUEFTU1dPUkRfT1BUSU9OUyxcbiAgICAgIHVzZVZhbHVlOiB7XG4gICAgICAgIC4uLlRVSV9JTlBVVF9QQVNTV09SRF9ERUZBVUxUX09QVElPTlMsXG4gICAgICAgIGljb25zOiB7XG4gICAgICAgICAgaGlkZTogXCJ0dWlJY29uRXllT2ZmXCIsXG4gICAgICAgICAgc2hvdzogXCJ0dWlJY29uRXllXCJcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgXVxufSlcbmV4cG9ydCBjbGFzcyBLd2lrVUlJbnB1dFBhc3N3b3JkQ29tcG9uZW50XG4gIGltcGxlbWVudHMgT25Jbml0LCBPbkNoYW5nZXMsIENvbnRyb2xWYWx1ZUFjY2Vzc29yIHtcbiAgQElucHV0KCkgZGlzYWJsZWQ6IGJvb2xlYW4gPSBERUZBVUxUX1ZBTFVFUy5kaXNhYmxlZDtcblxuICBASW5wdXQoKSBmb2N1czogYm9vbGVhbiA9IERFRkFVTFRfVkFMVUVTLmZvY3VzO1xuXG4gIEBJbnB1dCgpIGZvcm1Db250cm9sOiBGb3JtQ29udHJvbCA9IG5ldyBGb3JtQ29udHJvbCh7fSk7XG5cbiAgQElucHV0KCkgZm9ybUNvbnRyb2xOYW1lOiBzdHJpbmcgPSBERUZBVUxUX1ZBTFVFUy5mb3JtQ29udHJvbE5hbWU7XG5cbiAgQElucHV0KCkgaGludENvbnRlbnQ6IHN0cmluZyA9IERFRkFVTFRfVkFMVUVTLmhpbnRDb250ZW50O1xuXG4gIEBJbnB1dCgpIGljb246IHN0cmluZyA9IERFRkFVTFRfVkFMVUVTLmljb247XG5cbiAgQElucHV0KCkgaWQ6IHN0cmluZyA9IERFRkFVTFRfVkFMVUVTLmlkO1xuXG4gIEBJbnB1dCgpIGludmFsaWQ6IGJvb2xlYW4gPSBERUZBVUxUX1ZBTFVFUy5pbnZhbGlkO1xuXG4gIEBJbnB1dCgpIGxhYmVsOiBzdHJpbmcgPSBERUZBVUxUX1ZBTFVFUy5sYWJlbDtcblxuICBASW5wdXQoKSBwbGFjZWhvbGRlcjogc3RyaW5nID0gREVGQVVMVF9WQUxVRVMucGxhY2Vob2xkZXI7XG5cbiAgQElucHV0KCkgcG9zdGZpeDogc3RyaW5nID0gREVGQVVMVF9WQUxVRVMucG9zdGZpeDtcblxuICBASW5wdXQoKSBwcmVmaXg6IHN0cmluZyA9IERFRkFVTFRfVkFMVUVTLnByZWZpeDtcblxuICBASW5wdXQoKSBwcm9wZXJ0aWVzID0geyByZWFkT25seTogZmFsc2UgfTtcblxuICBASW5wdXQoKSBzaXplOiBUS3dpa1VJSW5wdXRQYXNzd29yZFNpemUgPSBERUZBVUxUX1ZBTFVFUy5zaXplO1xuXG4gIEBJbnB1dCgpIHZhbGlkYXRvcnMgPSB7IHJlcXVpcmVkOiB0cnVlIH07XG5cbiAgQE91dHB1dCgpIGdldEtleVZhbHVlOiBFdmVudEVtaXR0ZXI8YW55PiA9IG5ldyBFdmVudEVtaXR0ZXI8YW55PigpO1xuXG4gIGZvcm1Hcm91cDogRm9ybUdyb3VwID0gbmV3IEZvcm1Hcm91cCh7fSk7XG5cbiAgc3Vic2NyaXB0aW9ucyA9IG5ldyBTdWJzY3JpcHRpb24oKTtcblxuICBjb25zdHJ1Y3RvcigpIHt9XG5cbiAgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgdGhpcy5mb3JtR3JvdXAuYWRkQ29udHJvbCh0aGlzLmZvcm1Db250cm9sTmFtZSwgdGhpcy5mb3JtQ29udHJvbCk7XG4gICAgdGhpcy5mb2N1cyA9IHRoaXMuZm9jdXMgPT09IHVuZGVmaW5lZCA/IGZhbHNlIDogdGhpcy5mb2N1cztcbiAgICB0aGlzLmludmFsaWQgPVxuICAgICAgdGhpcy5pbnZhbGlkID09PSB1bmRlZmluZWQgPyBmYWxzZSA6IHRoaXMuaW52YWxpZCAmJiB0aGlzLmZvY3VzO1xuICAgIHRoaXMudmFsaWRhdG9ycyA9IHsgLi4udGhpcy52YWxpZGF0b3JzIH07XG4gICAgdGhpcy5wcm9wZXJ0aWVzID0geyAuLi50aGlzLnByb3BlcnRpZXMgfTtcbiAgICB0aGlzLnNldERpc2FibGVkKCk7XG5cbiAgICB0aGlzLnN1YnNjcmlwdGlvbnMuYWRkKFxuICAgICAgdGhpcy5mb3JtR3JvdXAuY29udHJvbHNbdGhpcy5mb3JtQ29udHJvbE5hbWVdLnZhbHVlQ2hhbmdlc1xuICAgICAgICAucGlwZShkaXN0aW5jdFVudGlsQ2hhbmdlZCgpKSAvLyBtYWtlcyBzdXJlIHRoZSB2YWx1ZSBoYXMgYWN0dWFsbHkgY2hhbmdlZC5cbiAgICAgICAgLnN1YnNjcmliZSgodmFsdWUpID0+IHRoaXMuaGFuZGxlSW5wdXRWYWx1ZUNoYW5nZSh2YWx1ZSkpXG4gICAgKTtcbiAgfVxuXG4gIG5nT25DaGFuZ2VzKGNoYW5nZXM6IFNpbXBsZUNoYW5nZXMpIHtcbiAgICBjb25zdCB2ZXJpZnlDaGFuZ2UgPSAoa2V5OiBzdHJpbmcpID0+IHtcbiAgICAgIHJldHVybiBjaGFuZ2VzLmhhc093blByb3BlcnR5KGtleSkgJiYgIWNoYW5nZXNba2V5XS5maXJzdENoYW5nZTtcbiAgICB9O1xuXG4gICAgZm9yIChjb25zdCBjaGFuZ2Ugb2YgT2JqZWN0LmVudHJpZXMoY2hhbmdlcykpIHtcbiAgICAgIGNvbnN0IGtleTogc3RyaW5nID0gY2hhbmdlWzBdO1xuICAgICAgY29uc3QgdmFsdWU6IGFueSA9IGNoYW5nZVsxXS5jdXJyZW50VmFsdWU7XG4gICAgICB0aGlzLnZhbGlkYXRlSW5wdXRQcm9wZXJ0eShrZXksIHZhbHVlKTtcbiAgICB9XG5cbiAgICBpZiAodmVyaWZ5Q2hhbmdlKFwiZm9ybUNvbnRyb2xcIikpIHtcbiAgICAgIHRoaXMuZm9ybUNvbnRyb2wgPSBjaGFuZ2VzLmZvcm1Db250cm9sLmN1cnJlbnRWYWx1ZTtcbiAgICB9XG4gICAgaWYgKHZlcmlmeUNoYW5nZShcImludmFsaWRcIikpIHtcbiAgICAgIHRoaXMuaW52YWxpZCA9IEJvb2xlYW4oY2hhbmdlcy5pbnZhbGlkLmN1cnJlbnRWYWx1ZSk7XG4gICAgICB0aGlzLnNldEVycm9yKCk7XG4gICAgfVxuICAgIGlmICh2ZXJpZnlDaGFuZ2UoXCJmb2N1c1wiKSkge1xuICAgICAgdGhpcy5mb2N1cyA9IEJvb2xlYW4oY2hhbmdlcy5mb2N1cy5jdXJyZW50VmFsdWUpO1xuICAgIH1cbiAgICBpZiAodmVyaWZ5Q2hhbmdlKFwiZGlzYWJsZWRcIikpIHtcbiAgICAgIHRoaXMuZGlzYWJsZWQgPSBCb29sZWFuKGNoYW5nZXMuZGlzYWJsZWQuY3VycmVudFZhbHVlKTtcbiAgICAgIHRoaXMuc2V0RGlzYWJsZWQoKTtcbiAgICB9XG4gIH1cblxuICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICB0aGlzLnN1YnNjcmlwdGlvbnMudW5zdWJzY3JpYmUoKTtcbiAgICAvLyBlbnN1cmUgd2hlbiBjb21wb25lbnQgaXMgZGVzdHJveWVkIHRoZSBzdWJzY3JpcHRpb24gaXMgYWxzbyBhbmQgbm90IGxlZnQgb3Blbi5cbiAgfVxuXG4gIHByaXZhdGUgdmFsaWRhdGVJbnB1dFByb3BlcnR5KGtleTogc3RyaW5nLCB2YWx1ZTogYW55KTogdm9pZCB7XG4gICAgaWYgKFZBTElEQVRFX0tFWV9WQUxVRVNba2V5XSAmJiAhaXNWYWxpZEtleVZhbHVlKGtleSwgdmFsdWUpKSB7XG4gICAgICB0aGlzW2tleV0gPSBERUZBVUxUX1ZBTFVFU1trZXldO1xuICAgICAgdGhyb3dFcnJvck1lc3NhZ2UoXG4gICAgICAgIFwia3dpa3VpLWlucHV0LXBhc3N3b3JkXCIsXG4gICAgICAgIHRoaXMuaWQsXG4gICAgICAgIGtleSxcbiAgICAgICAgdmFsdWUsXG4gICAgICAgIERFRkFVTFRfVkFMVUVTW2tleV1cbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBIYW5kbGVzIHNldHRpbmcgdXAgb2YgZXJyb3IgYW5kIGZvY3VzIG9uIHRoZSBpbnB1dCBmaWVsZCBpcyBpdCBpcyBpbnZhbGlkXG4gICAqL1xuICBzZXREaXNhYmxlZCgpIHtcbiAgICBpZiAodGhpcy5mb3JtR3JvdXAuY29udHJvbHNbdGhpcy5mb3JtQ29udHJvbE5hbWVdICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGlmICh0aGlzLmRpc2FibGVkID09PSB0cnVlKSB7XG4gICAgICAgIHRoaXMuZm9ybUdyb3VwLmNvbnRyb2xzW3RoaXMuZm9ybUNvbnRyb2xOYW1lXS5kaXNhYmxlKHtcbiAgICAgICAgICBlbWl0RXZlbnQ6IGZhbHNlXG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5mb3JtR3JvdXAuY29udHJvbHNbdGhpcy5mb3JtQ29udHJvbE5hbWVdLmVuYWJsZSh7XG4gICAgICAgICAgZW1pdEV2ZW50OiBmYWxzZVxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEhhbmRsZXMgc2V0dGluZyB1cCBvZiBlcnJvciBhbmQgZm9jdXMgb24gdGhlIGlucHV0IGZpZWxkIGlzIGl0IGlzIGludmFsaWRcbiAgICovXG4gIHNldEVycm9yKCkge1xuICAgIGlmIChcbiAgICAgIHRoaXMuZm9ybUdyb3VwLmNvbnRyb2xzW3RoaXMuZm9ybUNvbnRyb2xOYW1lXSAhPT0gdW5kZWZpbmVkICYmXG4gICAgICB0aGlzLmZvcm1Hcm91cC5jb250cm9sc1t0aGlzLmZvcm1Db250cm9sTmFtZV0uaW52YWxpZFxuICAgICkge1xuICAgICAgdGhpcy5pbnZhbGlkID0gdHJ1ZTtcbiAgICAgIHRoaXMuZm9jdXMgPSB0cnVlO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmludmFsaWQgPSBmYWxzZTtcbiAgICAgIHRoaXMuZm9jdXMgPSBmYWxzZTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEhhbmRsZXMgZmlyaW5nIG9mIDIgZXZlbnRzIG9uIChrZXl1cCkgZXZlbnRcbiAgICpcbiAgICogQHBhcmFtIHZhbHVlXG4gICAqL1xuICBoYW5kbGVJbnB1dFZhbHVlQ2hhbmdlKHZhbHVlOiBhbnkpIHtcbiAgICBpZiAodmFsdWUgPT09IHRoaXMuZm9ybUNvbnRyb2wudmFsdWUpIHtcbiAgICAgIHRoaXMuZW1pdEV2ZW50KHRoaXMuZ2V0S2V5VmFsdWUsIHtcbiAgICAgICAga2V5OiB0aGlzLmZvcm1Db250cm9sTmFtZSxcbiAgICAgICAgdmFsdWU6IHRoaXMuZm9ybUNvbnRyb2wudmFsdWVcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIGhhbmRsZUZvY3VzZWRDaGFuZ2UoZTogYW55KSB7XG4gICAgaWYgKCF0aGlzLmludmFsaWQpIHtcbiAgICAgIHRoaXMuZm9jdXMgPSBlO1xuICAgIH1cbiAgfVxuXG4gIGVtaXRFdmVudChldmVudDogYW55LCBkYXRhOiBhbnkpIHtcbiAgICBldmVudC5lbWl0KGRhdGEpO1xuICB9XG5cbiAgLyoqIE1ldGhvZCBJbXBsZW1lbnRhdGlvbnMgZm9yIEFic3RyYWN0IENvbnRyb2wgKi9cbiAgd3JpdGVWYWx1ZSh2YWx1ZTogYW55KTogdm9pZCB7fVxuXG4gIHJlZ2lzdGVyT25DaGFuZ2UoZm46IGFueSk6IHZvaWQge31cblxuICByZWdpc3Rlck9uVG91Y2hlZChmbjogYW55KTogdm9pZCB7fVxuXG4gIHNldERpc2FibGVkU3RhdGU/KGlzRGlzYWJsZWQ6IGJvb2xlYW4pOiB2b2lkIHt9XG59XG4iLCI8ZGl2IFtmb3JtR3JvdXBdPVwiZm9ybUdyb3VwXCI+XG4gIDx0dWktaW5wdXQtcGFzc3dvcmRcbiAgICBbZm9ybUNvbnRyb2xOYW1lXT1cImZvcm1Db250cm9sTmFtZVwiXG4gICAgW25hdGl2ZUlkXT1cImlkXCJcbiAgICBbcHNldWRvRm9jdXNdPVwiZm9jdXMgPz8gbnVsbFwiXG4gICAgW3BzZXVkb0ludmFsaWRdPVwiaW52YWxpZCA9PT0gdW5kZWZpbmVkID8gbnVsbCA6IGludmFsaWRcIlxuICAgIFtyZWFkT25seV09XCJwcm9wZXJ0aWVzPy5yZWFkT25seSA/PyBmYWxzZVwiXG4gICAgW3R1aUhpbnRDb250ZW50XT1cImhpbnRDb250ZW50XCJcbiAgICBbdHVpVGV4dGZpZWxkQ2xlYW5lcl09XCJ0cnVlXCJcbiAgICBbdHVpVGV4dGZpZWxkSWNvbkxlZnRdPVwiaWNvblwiXG4gICAgW3R1aVRleHRmaWVsZFBvc3RmaXhdPVwicG9zdGZpeFwiXG4gICAgW3R1aVRleHRmaWVsZFByZWZpeF09XCJwcmVmaXhcIlxuICAgIFt0dWlUZXh0ZmllbGRTaXplXT1cInNpemVcIlxuICAgIChmb2N1c2VkQ2hhbmdlKT1cImhhbmRsZUZvY3VzZWRDaGFuZ2UoJGV2ZW50KVwiXG4gID5cbiAgICB7eyBsYWJlbCB9fVxuICAgIDxzcGFuXG4gICAgICBjbGFzcz1cInR1aS1yZXF1aXJlZFwiXG4gICAgICAqbmdJZj1cInZhbGlkYXRvcnMucmVxdWlyZWRcIlxuICAgID48L3NwYW4+XG4gICAgPGlucHV0XG4gICAgICB0dWlUZXh0ZmllbGRcbiAgICAgIFthdHRyLnBsYWNlaG9sZGVyXT1cInBsYWNlaG9sZGVyID8/ICcnXCJcbiAgICAgIFthdHRyLnJlcXVpcmVkXT1cInZhbGlkYXRvcnMucmVxdWlyZWRcIlxuICAgIC8+XG4gIDwvdHVpLWlucHV0LXBhc3N3b3JkPlxuPC9kaXY+XG4iXX0=