ngx-numeric-range-form-field
Version:
Angular material numeric range form field
160 lines • 27.6 kB
JavaScript
import { ChangeDetectionStrategy, Component, EventEmitter, Host, Input, Output, Self } from '@angular/core';
import { FormControl } from '@angular/forms';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { NumericRangeFormService } from '../form/numeric-range-form.service';
import * as i0 from "@angular/core";
import * as i1 from "@angular/forms";
import * as i2 from "../form/numeric-range-form.service";
import * as i3 from "@angular/common";
import * as i4 from "@angular/material/form-field";
import * as i5 from "@angular/material/icon";
import * as i6 from "../control/numeric-range-form-field-control.component";
export class NumericRangeFormFieldContainerComponent {
get minimumControl() {
return this.formService.minimumControl;
}
get maximumControl() {
return this.formService.maximumControl;
}
constructor(controlDirective, formService, changeDetectorRef) {
this.controlDirective = controlDirective;
this.formService = formService;
this.changeDetectorRef = changeDetectorRef;
this.appearance = 'outline';
this.floatLabel = 'always';
this.minPlaceholder = 'From';
this.maxPlaceholder = 'To';
this.readonly = false;
this.minReadonly = false;
this.maxReadonly = false;
this.resettable = true;
this.requiredErrorMessage = 'Field is required!';
this.minimumErrorMessage = 'Minimum has been reached!';
this.maximumErrorMessage = 'Maximum has exceeded!';
this.invalidRangeErrorMessage = 'Inserted range is not valid!';
this.blurred = new EventEmitter();
this.enterPressed = new EventEmitter();
this.numericRangeChanged = new EventEmitter();
this.formGroup = this.formService.formGroup;
this.control = new FormControl();
this.unsubscribe$ = new Subject();
this.onTouched = () => { };
this.controlDirective.valueAccessor = this;
}
ngOnChanges(changes) {
if (changes.dynamicSyncValidators) {
this.control.setErrors(null);
this.control.setValidators(this.dynamicSyncValidators);
this.control.updateValueAndValidity({ emitEvent: false });
}
}
ngOnInit() {
this.setSyncValidator(this.controlDirective.control.validator);
this.setAsyncValidator(this.controlDirective.control.asyncValidator);
this.controlDirective.control.setValidators([this.validate.bind(this)]); // overrides the parent control validators by sending out errors from validate()
this.controlDirective.control.updateValueAndValidity({ emitEvent: false });
this.changeDetectorRef.detectChanges();
}
ngOnDestroy() {
this.unsubscribe$.next();
this.unsubscribe$.complete();
}
writeValue(value) {
value === null
? this.control.reset()
: this.control.setValue(value, {
emitEvent: false
});
}
registerOnChange(fn) {
this.control.valueChanges.pipe(takeUntil(this.unsubscribe$)).subscribe(fn);
}
registerOnTouched(fn) {
this.onTouched = fn;
}
setDisabledState(isDisabled) {
isDisabled ? this.control.disable() : this.control.enable();
}
validate(control) {
const errors = {
...this.minimumControl.errors,
...this.maximumControl.errors
};
return Object.keys(errors).length ? errors : null;
}
onEnterPressed() {
this.enterPressed.emit();
}
onBlur() {
this.onTouched();
this.blurred.emit();
}
onRangeValuesChanged(value) {
this.numericRangeChanged.emit(value);
}
onReset() {
this.formGroup.reset();
}
setSyncValidator(validator) {
if (!validator) {
return;
}
this.control.addValidators(validator); // sets the validators from parent control
this.control.updateValueAndValidity();
}
setAsyncValidator(asyncValidator) {
if (!asyncValidator) {
return;
}
this.control.addAsyncValidators(asyncValidator);
this.control.updateValueAndValidity();
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.5", ngImport: i0, type: NumericRangeFormFieldContainerComponent, deps: [{ token: i1.NgControl, self: true }, { token: i2.NumericRangeFormService, host: true }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.5", type: NumericRangeFormFieldContainerComponent, selector: "ngx-numeric-range-form-field", inputs: { label: "label", appearance: "appearance", floatLabel: "floatLabel", minPlaceholder: "minPlaceholder", maxPlaceholder: "maxPlaceholder", readonly: "readonly", minReadonly: "minReadonly", maxReadonly: "maxReadonly", resettable: "resettable", required: "required", requiredErrorMessage: "requiredErrorMessage", minimumErrorMessage: "minimumErrorMessage", maximumErrorMessage: "maximumErrorMessage", invalidRangeErrorMessage: "invalidRangeErrorMessage", dynamicSyncValidators: "dynamicSyncValidators" }, outputs: { blurred: "blurred", enterPressed: "enterPressed", numericRangeChanged: "numericRangeChanged" }, providers: [NumericRangeFormService], usesOnChanges: true, ngImport: i0, template: "<mat-form-field\n\t[appearance]=\"appearance\"\n\t[floatLabel]=\"floatLabel\"\n\tclass=\"numeric-range-field\"\n>\n\t<mat-label>{{ label }}</mat-label>\n\t<ngx-numeric-range-form-field-control\n\t\tid=\"numeric-range-form-control\"\n\t\t[formControl]=\"control\"\n\t\t[minPlaceholder]=\"minPlaceholder\"\n\t\t[maxPlaceholder]=\"maxPlaceholder\"\n\t\t[readonly]=\"readonly\"\n\t\t[minReadonly]=\"minReadonly\"\n\t\t[maxReadonly]=\"maxReadonly\"\n\t\t[required]=\"required\"\n\t\t(blurred)=\"onBlur()\"\n\t\t(enterPressed)=\"onEnterPressed()\"\n\t\t(numericRangeChanged)=\"onRangeValuesChanged($event)\"\n\t\t[dynamicSyncValidators]=\"dynamicSyncValidators\"\n\t></ngx-numeric-range-form-field-control>\n\n\t<mat-icon\n\t\t(click)=\"onReset()\"\n\t\t*ngIf=\"\n\t\t\tresettable &&\n\t\t\t!readonly &&\n\t\t\t!minReadonly &&\n\t\t\t!maxReadonly &&\n\t\t\t(minimumControl.value !== null || maximumControl.value !== null) &&\n\t\t\t!formGroup.disabled\n\t\t\"\n\t\tcolor=\"primary\"\n\t\tclass=\"pointer\"\n\t\tmatSuffix\n\t\t>close\n\t</mat-icon>\n\n\t<mat-error\n\t\t*ngIf=\"\n\t\t\tminimumControl.hasError('required') || maximumControl.hasError('required')\n\t\t\"\n\t>\n\t\t{{ requiredErrorMessage }}\n\t</mat-error>\n\n\t<mat-error\n\t\t*ngIf=\"minimumControl.hasError('min') || maximumControl.hasError('min')\"\n\t>\n\t\t{{ minimumErrorMessage }}\n\t</mat-error>\n\n\t<mat-error\n\t\t*ngIf=\"minimumControl.hasError('max') || maximumControl.hasError('max')\"\n\t>\n\t\t{{ maximumErrorMessage }}\n\t</mat-error>\n\n\t<mat-error\n\t\t*ngIf=\"\n\t\t\tformGroup.hasError('notValidRange') &&\n\t\t\t!minimumControl.errors &&\n\t\t\t!maximumControl.errors\n\t\t\"\n\t>\n\t\t{{ invalidRangeErrorMessage }}\n\t</mat-error>\n</mat-form-field>\n", styles: [":host .numeric-range-field{width:100%}:host mat-icon{cursor:context-menu}:host .pointer{cursor:pointer}\n"], dependencies: [{ kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatLabel, selector: "mat-label" }, { kind: "directive", type: i4.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i4.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i6.NumericRangeFormFieldControlComponent, selector: "ngx-numeric-range-form-field-control", inputs: ["value", "placeholder", "minPlaceholder", "maxPlaceholder", "readonly", "minReadonly", "maxReadonly", "required", "disabled", "errorStateMatcher", "autofilled", "dynamicSyncValidators"], outputs: ["blurred", "enterPressed", "numericRangeChanged"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.5", ngImport: i0, type: NumericRangeFormFieldContainerComponent, decorators: [{
type: Component,
args: [{ selector: 'ngx-numeric-range-form-field', changeDetection: ChangeDetectionStrategy.OnPush, providers: [NumericRangeFormService], template: "<mat-form-field\n\t[appearance]=\"appearance\"\n\t[floatLabel]=\"floatLabel\"\n\tclass=\"numeric-range-field\"\n>\n\t<mat-label>{{ label }}</mat-label>\n\t<ngx-numeric-range-form-field-control\n\t\tid=\"numeric-range-form-control\"\n\t\t[formControl]=\"control\"\n\t\t[minPlaceholder]=\"minPlaceholder\"\n\t\t[maxPlaceholder]=\"maxPlaceholder\"\n\t\t[readonly]=\"readonly\"\n\t\t[minReadonly]=\"minReadonly\"\n\t\t[maxReadonly]=\"maxReadonly\"\n\t\t[required]=\"required\"\n\t\t(blurred)=\"onBlur()\"\n\t\t(enterPressed)=\"onEnterPressed()\"\n\t\t(numericRangeChanged)=\"onRangeValuesChanged($event)\"\n\t\t[dynamicSyncValidators]=\"dynamicSyncValidators\"\n\t></ngx-numeric-range-form-field-control>\n\n\t<mat-icon\n\t\t(click)=\"onReset()\"\n\t\t*ngIf=\"\n\t\t\tresettable &&\n\t\t\t!readonly &&\n\t\t\t!minReadonly &&\n\t\t\t!maxReadonly &&\n\t\t\t(minimumControl.value !== null || maximumControl.value !== null) &&\n\t\t\t!formGroup.disabled\n\t\t\"\n\t\tcolor=\"primary\"\n\t\tclass=\"pointer\"\n\t\tmatSuffix\n\t\t>close\n\t</mat-icon>\n\n\t<mat-error\n\t\t*ngIf=\"\n\t\t\tminimumControl.hasError('required') || maximumControl.hasError('required')\n\t\t\"\n\t>\n\t\t{{ requiredErrorMessage }}\n\t</mat-error>\n\n\t<mat-error\n\t\t*ngIf=\"minimumControl.hasError('min') || maximumControl.hasError('min')\"\n\t>\n\t\t{{ minimumErrorMessage }}\n\t</mat-error>\n\n\t<mat-error\n\t\t*ngIf=\"minimumControl.hasError('max') || maximumControl.hasError('max')\"\n\t>\n\t\t{{ maximumErrorMessage }}\n\t</mat-error>\n\n\t<mat-error\n\t\t*ngIf=\"\n\t\t\tformGroup.hasError('notValidRange') &&\n\t\t\t!minimumControl.errors &&\n\t\t\t!maximumControl.errors\n\t\t\"\n\t>\n\t\t{{ invalidRangeErrorMessage }}\n\t</mat-error>\n</mat-form-field>\n", styles: [":host .numeric-range-field{width:100%}:host mat-icon{cursor:context-menu}:host .pointer{cursor:pointer}\n"] }]
}], ctorParameters: () => [{ type: i1.NgControl, decorators: [{
type: Self
}] }, { type: i2.NumericRangeFormService, decorators: [{
type: Host
}] }, { type: i0.ChangeDetectorRef }], propDecorators: { label: [{
type: Input
}], appearance: [{
type: Input
}], floatLabel: [{
type: Input
}], minPlaceholder: [{
type: Input
}], maxPlaceholder: [{
type: Input
}], readonly: [{
type: Input
}], minReadonly: [{
type: Input
}], maxReadonly: [{
type: Input
}], resettable: [{
type: Input
}], required: [{
type: Input
}], requiredErrorMessage: [{
type: Input
}], minimumErrorMessage: [{
type: Input
}], maximumErrorMessage: [{
type: Input
}], invalidRangeErrorMessage: [{
type: Input
}], dynamicSyncValidators: [{
type: Input
}], blurred: [{
type: Output
}], enterPressed: [{
type: Output
}], numericRangeChanged: [{
type: Output
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibnVtZXJpYy1yYW5nZS1mb3JtLWZpZWxkLWNvbnRhaW5lci5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtbnVtZXJpYy1yYW5nZS1mb3JtLWZpZWxkL3NyYy9saWIvY29udGFpbmVyL251bWVyaWMtcmFuZ2UtZm9ybS1maWVsZC1jb250YWluZXIuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LW51bWVyaWMtcmFuZ2UtZm9ybS1maWVsZC9zcmMvbGliL2NvbnRhaW5lci9udW1lcmljLXJhbmdlLWZvcm0tZmllbGQtY29udGFpbmVyLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTix1QkFBdUIsRUFFdkIsU0FBUyxFQUNULFlBQVksRUFDWixJQUFJLEVBQ0osS0FBSyxFQUlMLE1BQU0sRUFDTixJQUFJLEVBRUosTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUlOLFdBQVcsRUFLWCxNQUFNLGdCQUFnQixDQUFDO0FBS3hCLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDL0IsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBSzNDLE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxNQUFNLG9DQUFvQyxDQUFDOzs7Ozs7OztBQVM3RSxNQUFNLE9BQU8sdUNBQXVDO0lBbUNuRCxJQUFJLGNBQWM7UUFDakIsT0FBTyxJQUFJLENBQUMsV0FBVyxDQUFDLGNBQWMsQ0FBQztJQUN4QyxDQUFDO0lBRUQsSUFBSSxjQUFjO1FBQ2pCLE9BQU8sSUFBSSxDQUFDLFdBQVcsQ0FBQyxjQUFjLENBQUM7SUFDeEMsQ0FBQztJQUVELFlBQ2lCLGdCQUEyQixFQUMzQixXQUFvQyxFQUM1QyxpQkFBb0M7UUFGNUIscUJBQWdCLEdBQWhCLGdCQUFnQixDQUFXO1FBQzNCLGdCQUFXLEdBQVgsV0FBVyxDQUF5QjtRQUM1QyxzQkFBaUIsR0FBakIsaUJBQWlCLENBQW1CO1FBMUNwQyxlQUFVLEdBQTJCLFNBQVMsQ0FBQztRQUMvQyxlQUFVLEdBQW1CLFFBQVEsQ0FBQztRQUV0QyxtQkFBYyxHQUFHLE1BQU0sQ0FBQztRQUN4QixtQkFBYyxHQUFHLElBQUksQ0FBQztRQUV0QixhQUFRLEdBQUcsS0FBSyxDQUFDO1FBQ2pCLGdCQUFXLEdBQUcsS0FBSyxDQUFDO1FBQ3BCLGdCQUFXLEdBQUcsS0FBSyxDQUFDO1FBRXBCLGVBQVUsR0FBRyxJQUFJLENBQUM7UUFHbEIseUJBQW9CLEdBQUcsb0JBQW9CLENBQUM7UUFFNUMsd0JBQW1CLEdBQUcsMkJBQTJCLENBQUM7UUFDbEQsd0JBQW1CLEdBQUcsdUJBQXVCLENBQUM7UUFDOUMsNkJBQXdCLEdBQUcsOEJBQThCLENBQUM7UUFHekQsWUFBTyxHQUFHLElBQUksWUFBWSxFQUFRLENBQUM7UUFDbkMsaUJBQVksR0FBRyxJQUFJLFlBQVksRUFBUSxDQUFDO1FBQ3hDLHdCQUFtQixHQUFHLElBQUksWUFBWSxFQUFpQixDQUFDO1FBRWxFLGNBQVMsR0FBMEIsSUFBSSxDQUFDLFdBQVcsQ0FBQyxTQUFTLENBQUM7UUFDOUQsWUFBTyxHQUFHLElBQUksV0FBVyxFQUFFLENBQUM7UUFFcEIsaUJBQVksR0FBRyxJQUFJLE9BQU8sRUFBUSxDQUFDO1FBRTNDLGNBQVMsR0FBRyxHQUFHLEVBQUUsR0FBRSxDQUFDLENBQUM7UUFlcEIsSUFBSSxDQUFDLGdCQUFnQixDQUFDLGFBQWEsR0FBRyxJQUFJLENBQUM7SUFDNUMsQ0FBQztJQUVELFdBQVcsQ0FBQyxPQUFzQjtRQUNqQyxJQUFJLE9BQU8sQ0FBQyxxQkFBcUIsRUFBRSxDQUFDO1lBQ25DLElBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQzdCLElBQUksQ0FBQyxPQUFPLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDO1lBQ3ZELElBQUksQ0FBQyxPQUFPLENBQUMsc0JBQXNCLENBQUMsRUFBRSxTQUFTLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQztRQUMzRCxDQUFDO0lBQ0YsQ0FBQztJQUVELFFBQVE7UUFDUCxJQUFJLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUMvRCxJQUFJLENBQUMsaUJBQWlCLENBQUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxjQUFjLENBQUMsQ0FBQztRQUVyRSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsT0FBTyxDQUFDLGFBQWEsQ0FBQyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLGdGQUFnRjtRQUN6SixJQUFJLENBQUMsZ0JBQWdCLENBQUMsT0FBTyxDQUFDLHNCQUFzQixDQUFDLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7UUFFM0UsSUFBSSxDQUFDLGlCQUFpQixDQUFDLGFBQWEsRUFBRSxDQUFDO0lBQ3hDLENBQUM7SUFFRCxXQUFXO1FBQ1YsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUN6QixJQUFJLENBQUMsWUFBWSxDQUFDLFFBQVEsRUFBRSxDQUFDO0lBQzlCLENBQUM7SUFFRCxVQUFVLENBQUMsS0FBb0I7UUFDOUIsS0FBSyxLQUFLLElBQUk7WUFDYixDQUFDLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLEVBQUU7WUFDdEIsQ0FBQyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLEtBQUssRUFBRTtnQkFDN0IsU0FBUyxFQUFFLEtBQUs7YUFDZixDQUFDLENBQUM7SUFDUCxDQUFDO0lBRUQsZ0JBQWdCLENBQUMsRUFBTztRQUN2QixJQUFJLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUM1RSxDQUFDO0lBRUQsaUJBQWlCLENBQUMsRUFBTztRQUN4QixJQUFJLENBQUMsU0FBUyxHQUFHLEVBQUUsQ0FBQztJQUNyQixDQUFDO0lBRUQsZ0JBQWdCLENBQUMsVUFBbUI7UUFDbkMsVUFBVSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sRUFBRSxDQUFDO0lBQzdELENBQUM7SUFFRCxRQUFRLENBQUMsT0FBd0I7UUFDaEMsTUFBTSxNQUFNLEdBQUc7WUFDZCxHQUFHLElBQUksQ0FBQyxjQUFjLENBQUMsTUFBTTtZQUM3QixHQUFHLElBQUksQ0FBQyxjQUFjLENBQUMsTUFBTTtTQUM3QixDQUFDO1FBRUYsT0FBTyxNQUFNLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7SUFDbkQsQ0FBQztJQUVELGNBQWM7UUFDYixJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksRUFBRSxDQUFDO0lBQzFCLENBQUM7SUFFRCxNQUFNO1FBQ0wsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO1FBQ2pCLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxFQUFFLENBQUM7SUFDckIsQ0FBQztJQUVELG9CQUFvQixDQUFDLEtBQW9CO1FBQ3hDLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDdEMsQ0FBQztJQUVELE9BQU87UUFDTixJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssRUFBRSxDQUFDO0lBQ3hCLENBQUM7SUFFTyxnQkFBZ0IsQ0FBQyxTQUFzQjtRQUM5QyxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7WUFDaEIsT0FBTztRQUNSLENBQUM7UUFFRCxJQUFJLENBQUMsT0FBTyxDQUFDLGFBQWEsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLDBDQUEwQztRQUNqRixJQUFJLENBQUMsT0FBTyxDQUFDLHNCQUFzQixFQUFFLENBQUM7SUFDdkMsQ0FBQztJQUVPLGlCQUFpQixDQUFDLGNBQWdDO1FBQ3pELElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQztZQUNyQixPQUFPO1FBQ1IsQ0FBQztRQUVELElBQUksQ0FBQyxPQUFPLENBQUMsa0JBQWtCLENBQUMsY0FBYyxDQUFDLENBQUM7UUFDaEQsSUFBSSxDQUFDLE9BQU8sQ0FBQyxzQkFBc0IsRUFBRSxDQUFDO0lBQ3ZDLENBQUM7OEdBeElXLHVDQUF1QztrR0FBdkMsdUNBQXVDLGdxQkFGeEMsQ0FBQyx1QkFBdUIsQ0FBQywrQ0N6Q3JDLHlzREFtRUE7OzJGRHhCYSx1Q0FBdUM7a0JBUG5ELFNBQVM7K0JBQ0MsOEJBQThCLG1CQUd2Qix1QkFBdUIsQ0FBQyxNQUFNLGFBQ3BDLENBQUMsdUJBQXVCLENBQUM7OzBCQThDbEMsSUFBSTs7MEJBQ0osSUFBSTt5RUExQ0csS0FBSztzQkFBYixLQUFLO2dCQUNHLFVBQVU7c0JBQWxCLEtBQUs7Z0JBQ0csVUFBVTtzQkFBbEIsS0FBSztnQkFFRyxjQUFjO3NCQUF0QixLQUFLO2dCQUNHLGNBQWM7c0JBQXRCLEtBQUs7Z0JBRUcsUUFBUTtzQkFBaEIsS0FBSztnQkFDRyxXQUFXO3NCQUFuQixLQUFLO2dCQUNHLFdBQVc7c0JBQW5CLEtBQUs7Z0JBRUcsVUFBVTtzQkFBbEIsS0FBSztnQkFFRyxRQUFRO3NCQUFoQixLQUFLO2dCQUNHLG9CQUFvQjtzQkFBNUIsS0FBSztnQkFFRyxtQkFBbUI7c0JBQTNCLEtBQUs7Z0JBQ0csbUJBQW1CO3NCQUEzQixLQUFLO2dCQUNHLHdCQUF3QjtzQkFBaEMsS0FBSztnQkFDRyxxQkFBcUI7c0JBQTdCLEtBQUs7Z0JBRUksT0FBTztzQkFBaEIsTUFBTTtnQkFDRyxZQUFZO3NCQUFyQixNQUFNO2dCQUNHLG1CQUFtQjtzQkFBNUIsTUFBTSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG5cdENoYW5nZURldGVjdGlvblN0cmF0ZWd5LFxuXHRDaGFuZ2VEZXRlY3RvclJlZixcblx0Q29tcG9uZW50LFxuXHRFdmVudEVtaXR0ZXIsXG5cdEhvc3QsXG5cdElucHV0LFxuXHRPbkNoYW5nZXMsXG5cdE9uRGVzdHJveSxcblx0T25Jbml0LFxuXHRPdXRwdXQsXG5cdFNlbGYsXG5cdFNpbXBsZUNoYW5nZXNcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge1xuXHRBYnN0cmFjdENvbnRyb2wsXG5cdEFzeW5jVmFsaWRhdG9yRm4sXG5cdENvbnRyb2xWYWx1ZUFjY2Vzc29yLFxuXHRGb3JtQ29udHJvbCxcblx0TmdDb250cm9sLFxuXHRWYWxpZGF0aW9uRXJyb3JzLFxuXHRWYWxpZGF0b3IsXG5cdFZhbGlkYXRvckZuXG59IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCB7XG5cdEZsb2F0TGFiZWxUeXBlLFxuXHRNYXRGb3JtRmllbGRBcHBlYXJhbmNlXG59IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2Zvcm0tZmllbGQnO1xuaW1wb3J0IHsgU3ViamVjdCB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgdGFrZVVudGlsIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHtcblx0SU51bWVyaWNSYW5nZSxcblx0TnVtZXJpY1JhbmdlRm9ybUdyb3VwXG59IGZyb20gJy4uL2Zvcm0vbW9kZWwvbnVtZXJpYy1yYW5nZS1maWVsZC5tb2RlbCc7XG5pbXBvcnQgeyBOdW1lcmljUmFuZ2VGb3JtU2VydmljZSB9IGZyb20gJy4uL2Zvcm0vbnVtZXJpYy1yYW5nZS1mb3JtLnNlcnZpY2UnO1xuXG5AQ29tcG9uZW50KHtcblx0c2VsZWN0b3I6ICduZ3gtbnVtZXJpYy1yYW5nZS1mb3JtLWZpZWxkJyxcblx0dGVtcGxhdGVVcmw6ICcuL251bWVyaWMtcmFuZ2UtZm9ybS1maWVsZC1jb250YWluZXIuY29tcG9uZW50Lmh0bWwnLFxuXHRzdHlsZVVybHM6IFsnLi9udW1lcmljLXJhbmdlLWZvcm0tZmllbGQtY29udGFpbmVyLmNvbXBvbmVudC5zY3NzJ10sXG5cdGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxuXHRwcm92aWRlcnM6IFtOdW1lcmljUmFuZ2VGb3JtU2VydmljZV1cbn0pXG5leHBvcnQgY2xhc3MgTnVtZXJpY1JhbmdlRm9ybUZpZWxkQ29udGFpbmVyQ29tcG9uZW50XG5cdGltcGxlbWVudHMgT25DaGFuZ2VzLCBPbkluaXQsIE9uRGVzdHJveSwgQ29udHJvbFZhbHVlQWNjZXNzb3IsIFZhbGlkYXRvclxue1xuXHRASW5wdXQoKSBsYWJlbDogc3RyaW5nO1xuXHRASW5wdXQoKSBhcHBlYXJhbmNlOiBNYXRGb3JtRmllbGRBcHBlYXJhbmNlID0gJ291dGxpbmUnO1xuXHRASW5wdXQoKSBmbG9hdExhYmVsOiBGbG9hdExhYmVsVHlwZSA9ICdhbHdheXMnO1xuXG5cdEBJbnB1dCgpIG1pblBsYWNlaG9sZGVyID0gJ0Zyb20nO1xuXHRASW5wdXQoKSBtYXhQbGFjZWhvbGRlciA9ICdUbyc7XG5cblx0QElucHV0KCkgcmVhZG9ubHkgPSBmYWxzZTtcblx0QElucHV0KCkgbWluUmVhZG9ubHkgPSBmYWxzZTtcblx0QElucHV0KCkgbWF4UmVhZG9ubHkgPSBmYWxzZTtcblxuXHRASW5wdXQoKSByZXNldHRhYmxlID0gdHJ1ZTtcblxuXHRASW5wdXQoKSByZXF1aXJlZDogYm9vbGVhbjtcblx0QElucHV0KCkgcmVxdWlyZWRFcnJvck1lc3NhZ2UgPSAnRmllbGQgaXMgcmVxdWlyZWQhJztcblxuXHRASW5wdXQoKSBtaW5pbXVtRXJyb3JNZXNzYWdlID0gJ01pbmltdW0gaGFzIGJlZW4gcmVhY2hlZCEnO1xuXHRASW5wdXQoKSBtYXhpbXVtRXJyb3JNZXNzYWdlID0gJ01heGltdW0gaGFzIGV4Y2VlZGVkISc7XG5cdEBJbnB1dCgpIGludmFsaWRSYW5nZUVycm9yTWVzc2FnZSA9ICdJbnNlcnRlZCByYW5nZSBpcyBub3QgdmFsaWQhJztcblx0QElucHV0KCkgZHluYW1pY1N5bmNWYWxpZGF0b3JzOiBWYWxpZGF0b3JGbiB8IFZhbGlkYXRvckZuW107XG5cblx0QE91dHB1dCgpIGJsdXJyZWQgPSBuZXcgRXZlbnRFbWl0dGVyPHZvaWQ+KCk7XG5cdEBPdXRwdXQoKSBlbnRlclByZXNzZWQgPSBuZXcgRXZlbnRFbWl0dGVyPHZvaWQ+KCk7XG5cdEBPdXRwdXQoKSBudW1lcmljUmFuZ2VDaGFuZ2VkID0gbmV3IEV2ZW50RW1pdHRlcjxJTnVtZXJpY1JhbmdlPigpO1xuXG5cdGZvcm1Hcm91cDogTnVtZXJpY1JhbmdlRm9ybUdyb3VwID0gdGhpcy5mb3JtU2VydmljZS5mb3JtR3JvdXA7XG5cdGNvbnRyb2wgPSBuZXcgRm9ybUNvbnRyb2woKTtcblxuXHRwcml2YXRlIHVuc3Vic2NyaWJlJCA9IG5ldyBTdWJqZWN0PHZvaWQ+KCk7XG5cblx0b25Ub3VjaGVkID0gKCkgPT4ge307XG5cblx0Z2V0IG1pbmltdW1Db250cm9sKCk6IEZvcm1Db250cm9sPG51bWJlcj4ge1xuXHRcdHJldHVybiB0aGlzLmZvcm1TZXJ2aWNlLm1pbmltdW1Db250cm9sO1xuXHR9XG5cblx0Z2V0IG1heGltdW1Db250cm9sKCk6IEZvcm1Db250cm9sPG51bWJlcj4ge1xuXHRcdHJldHVybiB0aGlzLmZvcm1TZXJ2aWNlLm1heGltdW1Db250cm9sO1xuXHR9XG5cblx0Y29uc3RydWN0b3IoXG5cdFx0QFNlbGYoKSBwcml2YXRlIGNvbnRyb2xEaXJlY3RpdmU6IE5nQ29udHJvbCxcblx0XHRASG9zdCgpIHByaXZhdGUgZm9ybVNlcnZpY2U6IE51bWVyaWNSYW5nZUZvcm1TZXJ2aWNlLFxuXHRcdHByaXZhdGUgY2hhbmdlRGV0ZWN0b3JSZWY6IENoYW5nZURldGVjdG9yUmVmXG5cdCkge1xuXHRcdHRoaXMuY29udHJvbERpcmVjdGl2ZS52YWx1ZUFjY2Vzc29yID0gdGhpcztcblx0fVxuXG5cdG5nT25DaGFuZ2VzKGNoYW5nZXM6IFNpbXBsZUNoYW5nZXMpOiB2b2lkIHtcblx0XHRpZiAoY2hhbmdlcy5keW5hbWljU3luY1ZhbGlkYXRvcnMpIHtcblx0XHRcdHRoaXMuY29udHJvbC5zZXRFcnJvcnMobnVsbCk7XG5cdFx0XHR0aGlzLmNvbnRyb2wuc2V0VmFsaWRhdG9ycyh0aGlzLmR5bmFtaWNTeW5jVmFsaWRhdG9ycyk7XG5cdFx0XHR0aGlzLmNvbnRyb2wudXBkYXRlVmFsdWVBbmRWYWxpZGl0eSh7IGVtaXRFdmVudDogZmFsc2UgfSk7XG5cdFx0fVxuXHR9XG5cblx0bmdPbkluaXQoKTogdm9pZCB7XG5cdFx0dGhpcy5zZXRTeW5jVmFsaWRhdG9yKHRoaXMuY29udHJvbERpcmVjdGl2ZS5jb250cm9sLnZhbGlkYXRvcik7XG5cdFx0dGhpcy5zZXRBc3luY1ZhbGlkYXRvcih0aGlzLmNvbnRyb2xEaXJlY3RpdmUuY29udHJvbC5hc3luY1ZhbGlkYXRvcik7XG5cblx0XHR0aGlzLmNvbnRyb2xEaXJlY3RpdmUuY29udHJvbC5zZXRWYWxpZGF0b3JzKFt0aGlzLnZhbGlkYXRlLmJpbmQodGhpcyldKTsgLy8gb3ZlcnJpZGVzIHRoZSBwYXJlbnQgY29udHJvbCB2YWxpZGF0b3JzIGJ5IHNlbmRpbmcgb3V0IGVycm9ycyBmcm9tIHZhbGlkYXRlKClcblx0XHR0aGlzLmNvbnRyb2xEaXJlY3RpdmUuY29udHJvbC51cGRhdGVWYWx1ZUFuZFZhbGlkaXR5KHsgZW1pdEV2ZW50OiBmYWxzZSB9KTtcblxuXHRcdHRoaXMuY2hhbmdlRGV0ZWN0b3JSZWYuZGV0ZWN0Q2hhbmdlcygpO1xuXHR9XG5cblx0bmdPbkRlc3Ryb3koKTogdm9pZCB7XG5cdFx0dGhpcy51bnN1YnNjcmliZSQubmV4dCgpO1xuXHRcdHRoaXMudW5zdWJzY3JpYmUkLmNvbXBsZXRlKCk7XG5cdH1cblxuXHR3cml0ZVZhbHVlKHZhbHVlOiBJTnVtZXJpY1JhbmdlKTogdm9pZCB7XG5cdFx0dmFsdWUgPT09IG51bGxcblx0XHRcdD8gdGhpcy5jb250cm9sLnJlc2V0KClcblx0XHRcdDogdGhpcy5jb250cm9sLnNldFZhbHVlKHZhbHVlLCB7XG5cdFx0XHRcdFx0ZW1pdEV2ZW50OiBmYWxzZVxuXHRcdFx0ICB9KTtcblx0fVxuXG5cdHJlZ2lzdGVyT25DaGFuZ2UoZm46IGFueSk6IHZvaWQge1xuXHRcdHRoaXMuY29udHJvbC52YWx1ZUNoYW5nZXMucGlwZSh0YWtlVW50aWwodGhpcy51bnN1YnNjcmliZSQpKS5zdWJzY3JpYmUoZm4pO1xuXHR9XG5cblx0cmVnaXN0ZXJPblRvdWNoZWQoZm46IGFueSk6IHZvaWQge1xuXHRcdHRoaXMub25Ub3VjaGVkID0gZm47XG5cdH1cblxuXHRzZXREaXNhYmxlZFN0YXRlKGlzRGlzYWJsZWQ6IGJvb2xlYW4pOiB2b2lkIHtcblx0XHRpc0Rpc2FibGVkID8gdGhpcy5jb250cm9sLmRpc2FibGUoKSA6IHRoaXMuY29udHJvbC5lbmFibGUoKTtcblx0fVxuXG5cdHZhbGlkYXRlKGNvbnRyb2w6IEFic3RyYWN0Q29udHJvbCk6IFZhbGlkYXRpb25FcnJvcnMgfCBudWxsIHtcblx0XHRjb25zdCBlcnJvcnMgPSB7XG5cdFx0XHQuLi50aGlzLm1pbmltdW1Db250cm9sLmVycm9ycyxcblx0XHRcdC4uLnRoaXMubWF4aW11bUNvbnRyb2wuZXJyb3JzXG5cdFx0fTtcblxuXHRcdHJldHVybiBPYmplY3Qua2V5cyhlcnJvcnMpLmxlbmd0aCA/IGVycm9ycyA6IG51bGw7XG5cdH1cblxuXHRvbkVudGVyUHJlc3NlZCgpOiB2b2lkIHtcblx0XHR0aGlzLmVudGVyUHJlc3NlZC5lbWl0KCk7XG5cdH1cblxuXHRvbkJsdXIoKTogdm9pZCB7XG5cdFx0dGhpcy5vblRvdWNoZWQoKTtcblx0XHR0aGlzLmJsdXJyZWQuZW1pdCgpO1xuXHR9XG5cblx0b25SYW5nZVZhbHVlc0NoYW5nZWQodmFsdWU6IElOdW1lcmljUmFuZ2UpOiB2b2lkIHtcblx0XHR0aGlzLm51bWVyaWNSYW5nZUNoYW5nZWQuZW1pdCh2YWx1ZSk7XG5cdH1cblxuXHRvblJlc2V0KCk6IHZvaWQge1xuXHRcdHRoaXMuZm9ybUdyb3VwLnJlc2V0KCk7XG5cdH1cblxuXHRwcml2YXRlIHNldFN5bmNWYWxpZGF0b3IodmFsaWRhdG9yOiBWYWxpZGF0b3JGbik6IHZvaWQge1xuXHRcdGlmICghdmFsaWRhdG9yKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0dGhpcy5jb250cm9sLmFkZFZhbGlkYXRvcnModmFsaWRhdG9yKTsgLy8gc2V0cyB0aGUgdmFsaWRhdG9ycyBmcm9tIHBhcmVudCBjb250cm9sXG5cdFx0dGhpcy5jb250cm9sLnVwZGF0ZVZhbHVlQW5kVmFsaWRpdHkoKTtcblx0fVxuXG5cdHByaXZhdGUgc2V0QXN5bmNWYWxpZGF0b3IoYXN5bmNWYWxpZGF0b3I6IEFzeW5jVmFsaWRhdG9yRm4pOiB2b2lkIHtcblx0XHRpZiAoIWFzeW5jVmFsaWRhdG9yKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0dGhpcy5jb250cm9sLmFkZEFzeW5jVmFsaWRhdG9ycyhhc3luY1ZhbGlkYXRvcik7XG5cdFx0dGhpcy5jb250cm9sLnVwZGF0ZVZhbHVlQW5kVmFsaWRpdHkoKTtcblx0fVxufVxuIiwiPG1hdC1mb3JtLWZpZWxkXG5cdFthcHBlYXJhbmNlXT1cImFwcGVhcmFuY2VcIlxuXHRbZmxvYXRMYWJlbF09XCJmbG9hdExhYmVsXCJcblx0Y2xhc3M9XCJudW1lcmljLXJhbmdlLWZpZWxkXCJcbj5cblx0PG1hdC1sYWJlbD57eyBsYWJlbCB9fTwvbWF0LWxhYmVsPlxuXHQ8bmd4LW51bWVyaWMtcmFuZ2UtZm9ybS1maWVsZC1jb250cm9sXG5cdFx0aWQ9XCJudW1lcmljLXJhbmdlLWZvcm0tY29udHJvbFwiXG5cdFx0W2Zvcm1Db250cm9sXT1cImNvbnRyb2xcIlxuXHRcdFttaW5QbGFjZWhvbGRlcl09XCJtaW5QbGFjZWhvbGRlclwiXG5cdFx0W21heFBsYWNlaG9sZGVyXT1cIm1heFBsYWNlaG9sZGVyXCJcblx0XHRbcmVhZG9ubHldPVwicmVhZG9ubHlcIlxuXHRcdFttaW5SZWFkb25seV09XCJtaW5SZWFkb25seVwiXG5cdFx0W21heFJlYWRvbmx5XT1cIm1heFJlYWRvbmx5XCJcblx0XHRbcmVxdWlyZWRdPVwicmVxdWlyZWRcIlxuXHRcdChibHVycmVkKT1cIm9uQmx1cigpXCJcblx0XHQoZW50ZXJQcmVzc2VkKT1cIm9uRW50ZXJQcmVzc2VkKClcIlxuXHRcdChudW1lcmljUmFuZ2VDaGFuZ2VkKT1cIm9uUmFuZ2VWYWx1ZXNDaGFuZ2VkKCRldmVudClcIlxuXHRcdFtkeW5hbWljU3luY1ZhbGlkYXRvcnNdPVwiZHluYW1pY1N5bmNWYWxpZGF0b3JzXCJcblx0Pjwvbmd4LW51bWVyaWMtcmFuZ2UtZm9ybS1maWVsZC1jb250cm9sPlxuXG5cdDxtYXQtaWNvblxuXHRcdChjbGljayk9XCJvblJlc2V0KClcIlxuXHRcdCpuZ0lmPVwiXG5cdFx0XHRyZXNldHRhYmxlICYmXG5cdFx0XHQhcmVhZG9ubHkgJiZcblx0XHRcdCFtaW5SZWFkb25seSAmJlxuXHRcdFx0IW1heFJlYWRvbmx5ICYmXG5cdFx0XHQobWluaW11bUNvbnRyb2wudmFsdWUgIT09IG51bGwgfHwgbWF4aW11bUNvbnRyb2wudmFsdWUgIT09IG51bGwpICYmXG5cdFx0XHQhZm9ybUdyb3VwLmRpc2FibGVkXG5cdFx0XCJcblx0XHRjb2xvcj1cInByaW1hcnlcIlxuXHRcdGNsYXNzPVwicG9pbnRlclwiXG5cdFx0bWF0U3VmZml4XG5cdFx0PmNsb3NlXG5cdDwvbWF0LWljb24+XG5cblx0PG1hdC1lcnJvclxuXHRcdCpuZ0lmPVwiXG5cdFx0XHRtaW5pbXVtQ29udHJvbC5oYXNFcnJvcigncmVxdWlyZWQnKSB8fCBtYXhpbXVtQ29udHJvbC5oYXNFcnJvcigncmVxdWlyZWQnKVxuXHRcdFwiXG5cdD5cblx0XHR7eyByZXF1aXJlZEVycm9yTWVzc2FnZSB9fVxuXHQ8L21hdC1lcnJvcj5cblxuXHQ8bWF0LWVycm9yXG5cdFx0Km5nSWY9XCJtaW5pbXVtQ29udHJvbC5oYXNFcnJvcignbWluJykgfHwgbWF4aW11bUNvbnRyb2wuaGFzRXJyb3IoJ21pbicpXCJcblx0PlxuXHRcdHt7IG1pbmltdW1FcnJvck1lc3NhZ2UgfX1cblx0PC9tYXQtZXJyb3I+XG5cblx0PG1hdC1lcnJvclxuXHRcdCpuZ0lmPVwibWluaW11bUNvbnRyb2wuaGFzRXJyb3IoJ21heCcpIHx8IG1heGltdW1Db250cm9sLmhhc0Vycm9yKCdtYXgnKVwiXG5cdD5cblx0XHR7eyBtYXhpbXVtRXJyb3JNZXNzYWdlIH19XG5cdDwvbWF0LWVycm9yPlxuXG5cdDxtYXQtZXJyb3Jcblx0XHQqbmdJZj1cIlxuXHRcdFx0Zm9ybUdyb3VwLmhhc0Vycm9yKCdub3RWYWxpZFJhbmdlJykgJiZcblx0XHRcdCFtaW5pbXVtQ29udHJvbC5lcnJvcnMgJiZcblx0XHRcdCFtYXhpbXVtQ29udHJvbC5lcnJvcnNcblx0XHRcIlxuXHQ+XG5cdFx0e3sgaW52YWxpZFJhbmdlRXJyb3JNZXNzYWdlIH19XG5cdDwvbWF0LWVycm9yPlxuPC9tYXQtZm9ybS1maWVsZD5cbiJdfQ==