@junte/ui
Version:
Quality Angular UI components kit
499 lines • 53.9 kB
JavaScript
import { __decorate, __metadata, __values } from "tslib";
import { Component, ElementRef, EventEmitter, forwardRef, HostBinding, HostListener, Input, Output, ViewChild } from '@angular/core';
import { ControlValueAccessor, FormBuilder, NG_VALUE_ACCESSOR } from '@angular/forms';
import { NGXLogger } from 'ngx-logger';
import { filter, map, distinctUntilChanged } from 'rxjs/operators';
import { Key } from '../../core/enums/keyboard';
import { PropertyApi } from '../../core/decorators/api';
import { Feature } from '../../core/enums/feature';
import { Size } from '../../core/enums/size';
import { State } from '../../core/enums/state';
import { TextAlign, TextTransform } from '../../core/enums/text';
import { UI } from '../../core/enums/ui';
import { Width } from '../../core/enums/width';
import { InputAutocomplete, InputScheme, InputType } from './enums';
var DIGIT_MASK_CHAR = '_';
var DIGIT_KEYS = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
var DEFAULT_NUMBER = 0;
var InputComponent = /** @class */ (function () {
function InputComponent(logger, fb) {
var _this = this;
this.logger = logger;
this.fb = fb;
this.host = 'jnt-input-host';
this.ui = UI;
this.view = { password: { display: false } };
this._type = InputType.text;
this._placeholder = '';
this.inputControl = this.fb.control(null);
this.formattedControl = this.fb.control(null);
this.form = this.fb.group({
input: this.inputControl,
formatted: this.formattedControl
});
this.focused = false;
this.disabled = false;
this._scheme = InputScheme.normal;
this._size = Size.normal;
this._width = Width.default;
this.name = null;
this.autocomplete = InputAutocomplete.off;
this.textAlign = TextAlign.left;
this.min = null;
this.max = null;
this.step = 1;
this.readonly = false;
this.rows = 5;
this.features = [];
this.click = new EventEmitter();
this.tabindex = 1;
this.onChange = function () { return _this.logger.error('value accessor is not registered'); };
this.onTouched = function () { return _this.logger.error('value accessor is not registered'); };
this.registerOnChange = function (fn) { return _this.onChange = fn; };
this.registerOnTouched = function (fn) { return _this.onTouched = fn; };
this.onBlur = function () { return _this.onTouched(); };
}
InputComponent_1 = InputComponent;
Object.defineProperty(InputComponent.prototype, "withIcon", {
get: function () {
return !!this.icon;
},
enumerable: true,
configurable: true
});
Object.defineProperty(InputComponent.prototype, "scheme", {
set: function (scheme) {
this._scheme = scheme || InputScheme.normal;
},
enumerable: true,
configurable: true
});
Object.defineProperty(InputComponent.prototype, "placeholder", {
get: function () {
return this._placeholder;
},
set: function (placeholder) {
this._placeholder = placeholder || '';
},
enumerable: true,
configurable: true
});
Object.defineProperty(InputComponent.prototype, "type", {
get: function () {
return this._type;
},
set: function (type) {
this._type = type || InputType.text;
},
enumerable: true,
configurable: true
});
Object.defineProperty(InputComponent.prototype, "size", {
set: function (size) {
this._size = size || Size.normal;
},
enumerable: true,
configurable: true
});
Object.defineProperty(InputComponent.prototype, "width", {
set: function (width) {
this._width = width || Width.default;
},
enumerable: true,
configurable: true
});
Object.defineProperty(InputComponent.prototype, "mask", {
get: function () {
return this._mask;
},
set: function (mask) {
this._mask = mask;
if (!!mask) {
this.form.setValue(this.masking(this.inputControl.value || ''));
}
},
enumerable: true,
configurable: true
});
InputComponent.prototype.ngOnInit = function () {
var _this = this;
this.inputControl.valueChanges.subscribe(function (value) {
return _this.onChange(!!value ? (_this.type === InputType.number ? +value : value) : null);
});
this.formattedControl.valueChanges.pipe(distinctUntilChanged(), filter(function () { return !!_this.maskedInput; }), map(function (formatted) { return !!formatted ? formatted : _this.mask; })).subscribe(function (formatted) {
var position = formatted.indexOf(DIGIT_MASK_CHAR);
_this.maskedInput.nativeElement.setSelectionRange(position, position);
var cleared = { input: null, formatted: null };
for (var i = 0; i < _this.mask.length; i++) {
if (_this.mask.charAt(i) !== formatted.charAt(i)) {
cleared = _this.masking(formatted.substr(i));
break;
}
}
if (cleared.input !== _this.inputControl.value || cleared.formatted !== _this.formattedControl.value) {
_this.form.setValue(cleared);
}
});
};
InputComponent.prototype.masking = function (value) {
var e_1, _a;
if (value === void 0) { value = null; }
var chars = !!value ? value.replace(/\D/gi, '') : '';
var formatted = this.mask;
var length = this.mask.split(DIGIT_MASK_CHAR).length - 1;
try {
for (var chars_1 = __values(chars), chars_1_1 = chars_1.next(); !chars_1_1.done; chars_1_1 = chars_1.next()) {
var char = chars_1_1.value;
formatted = formatted.replace(DIGIT_MASK_CHAR, char);
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (chars_1_1 && !chars_1_1.done && (_a = chars_1.return)) _a.call(chars_1);
}
finally { if (e_1) throw e_1.error; }
}
return {
input: chars.substr(0, length) || null,
formatted: formatted !== this.mask ? formatted : null
};
};
InputComponent.prototype.pasteMask = function (event) {
event.preventDefault();
var text = event.clipboardData.getData('text');
var data = this.masking(text);
this.form.setValue(data);
};
InputComponent.prototype.keydownMask = function (event) {
var value = this.inputControl.value || '';
var data;
if (DIGIT_KEYS.includes(event.key)) {
data = this.masking(value + event.key);
}
else if (event.key === Key.backspace) {
data = this.masking(value.substr(0, value.length - 1));
}
else if (event.key === Key.tab
|| event.key === Key.arrowLeft
|| event.key === Key.arrowRight
|| (event.ctrlKey || event.metaKey) && event.key === Key.v) {
return;
}
event.preventDefault();
if (data !== undefined) {
this.form.setValue(data);
}
};
InputComponent.prototype.keydown = function (event) {
if (this.type === InputType.number) {
if (this.inputControl.value && this.inputControl.value.length === 1 && event.key === Key.backspace) {
this.inputControl.setValue(null);
}
}
if (event.key === Key.enter) {
event.preventDefault();
}
};
InputComponent.prototype.keyup = function () {
var value = this.inputControl.value;
if (this.type === InputType.text && !!this.transform && !!value) {
switch (this.transform) {
case TextTransform.capitalize:
value = value.charAt(0).toUpperCase() + value.slice(1);
break;
case TextTransform.lowercase:
value = value.toLowerCase();
break;
case TextTransform.uppercase:
value = value.toUpperCase();
break;
}
this.inputControl.setValue(value);
}
};
InputComponent.prototype.writeValue = function (value) {
this.form.patchValue(!!this.mask ? this.masking(value) : { input: value }, { emitEvent: false });
};
InputComponent.prototype.setDisabledState = function (disabled) {
this.disabled = disabled;
};
InputComponent.prototype.setNumber = function (step) {
if (this.inputControl.value === '' || this.inputControl.value === null) {
this.inputControl.setValue(DEFAULT_NUMBER);
}
else {
var number = +this.inputControl.value + step;
number = this.max !== undefined && this.max !== null ? Math.min(number, this.max) : number;
number = this.min !== undefined && this.min !== null ? Math.max(number, this.min) : number;
this.inputControl.setValue(number);
}
};
InputComponent.prototype.clear = function (event) {
this.inputControl.setValue(null);
this.formattedControl.setValue(this.mask);
event.stopPropagation();
};
InputComponent.prototype.focus = function () {
if (!!this.valueInput) {
this.valueInput.nativeElement.focus();
}
else if (!!this.maskedInput) {
this.maskedInput.nativeElement.focus();
}
};
var InputComponent_1;
InputComponent.ctorParameters = function () { return [
{ type: NGXLogger },
{ type: FormBuilder }
]; };
__decorate([
HostBinding('attr.host'),
__metadata("design:type", Object)
], InputComponent.prototype, "host", void 0);
__decorate([
ViewChild('valueInput', { read: ElementRef, static: false }),
__metadata("design:type", ElementRef)
], InputComponent.prototype, "valueInput", void 0);
__decorate([
ViewChild('maskedInput', { read: ElementRef, static: false }),
__metadata("design:type", ElementRef)
], InputComponent.prototype, "maskedInput", void 0);
__decorate([
HostBinding('attr.data-focused'),
__metadata("design:type", Object)
], InputComponent.prototype, "focused", void 0);
__decorate([
HostBinding('attr.data-disabled'),
__metadata("design:type", Object)
], InputComponent.prototype, "disabled", void 0);
__decorate([
HostBinding('attr.data-scheme'),
__metadata("design:type", String)
], InputComponent.prototype, "_scheme", void 0);
__decorate([
HostBinding('attr.data-size'),
__metadata("design:type", String)
], InputComponent.prototype, "_size", void 0);
__decorate([
HostBinding('attr.data-width'),
__metadata("design:type", String)
], InputComponent.prototype, "_width", void 0);
__decorate([
HostBinding('attr.data-with-icon'),
__metadata("design:type", Object),
__metadata("design:paramtypes", [])
], InputComponent.prototype, "withIcon", null);
__decorate([
PropertyApi({
description: 'Icon for input',
type: 'string',
}),
Input(),
__metadata("design:type", String)
], InputComponent.prototype, "icon", void 0);
__decorate([
PropertyApi({
description: 'Label for input',
type: 'string',
}),
Input(),
__metadata("design:type", String)
], InputComponent.prototype, "label", void 0);
__decorate([
PropertyApi({
description: 'Name for input',
type: 'string'
}),
Input(),
__metadata("design:type", String)
], InputComponent.prototype, "name", void 0);
__decorate([
PropertyApi({
description: 'Text transform for input',
path: 'ui.text.transform',
options: [TextTransform.capitalize, TextTransform.uppercase, TextTransform.lowercase]
}),
Input(),
__metadata("design:type", String)
], InputComponent.prototype, "transform", void 0);
__decorate([
PropertyApi({
description: 'Auto complete for input',
path: 'ui.input.autocomplete',
options: [InputAutocomplete.on, InputAutocomplete.off]
}),
Input(),
__metadata("design:type", String)
], InputComponent.prototype, "autocomplete", void 0);
__decorate([
PropertyApi({
description: 'Input text align',
path: 'ui.text.align',
default: TextAlign.left,
options: [TextAlign.left, TextAlign.right]
}),
HostBinding('attr.data-textAlign'),
Input(),
__metadata("design:type", String)
], InputComponent.prototype, "textAlign", void 0);
__decorate([
PropertyApi({
description: 'Minimum number value that can be entered. For input with typeControl = number',
type: 'number',
}),
Input(),
__metadata("design:type", Number)
], InputComponent.prototype, "min", void 0);
__decorate([
PropertyApi({
description: 'Maximum number value that can be entered. For input with typeControl = number',
type: 'number',
}),
Input(),
__metadata("design:type", Number)
], InputComponent.prototype, "max", void 0);
__decorate([
PropertyApi({
description: 'Step for entered value. For input with typeControl = number',
type: 'number',
}),
Input(),
__metadata("design:type", Object)
], InputComponent.prototype, "step", void 0);
__decorate([
PropertyApi({
description: 'Used to specify that the input field is read-only',
type: 'boolean',
default: 'false'
}),
Input(),
__metadata("design:type", Object)
], InputComponent.prototype, "readonly", void 0);
__decorate([
PropertyApi({
description: 'Input scheme',
path: 'ui.input.scheme',
default: InputScheme.normal,
options: [InputScheme.normal, InputScheme.success, InputScheme.failed]
}),
Input(),
__metadata("design:type", String),
__metadata("design:paramtypes", [String])
], InputComponent.prototype, "scheme", null);
__decorate([
PropertyApi({
description: 'Input placeholder',
type: 'string',
}),
Input(),
__metadata("design:type", String),
__metadata("design:paramtypes", [String])
], InputComponent.prototype, "placeholder", null);
__decorate([
PropertyApi({
description: 'Input typeControl',
path: 'ui.input.type',
default: InputType.text,
options: [InputType.text, InputType.number, InputType.password]
}),
Input(),
__metadata("design:type", String),
__metadata("design:paramtypes", [String])
], InputComponent.prototype, "type", null);
__decorate([
PropertyApi({
description: 'Input size',
path: 'ui.size',
default: Size.normal,
options: [Size.small, Size.normal, Size.large]
}),
Input(),
__metadata("design:type", String),
__metadata("design:paramtypes", [String])
], InputComponent.prototype, "size", null);
__decorate([
PropertyApi({
description: 'Input width',
path: 'ui.width',
default: Width.default,
options: [Width.default, Width.fluid]
}),
Input(),
__metadata("design:type", String),
__metadata("design:paramtypes", [String])
], InputComponent.prototype, "width", null);
__decorate([
PropertyApi({
description: 'Input state',
path: 'ui.state',
options: [State.loading, State.warning, State.checked]
}),
HostBinding('attr.data-state'),
Input(),
__metadata("design:type", String)
], InputComponent.prototype, "state", void 0);
__decorate([
PropertyApi({
description: 'Max rows for multiline mode',
type: 'number',
default: 5,
}),
Input(),
__metadata("design:type", Object)
], InputComponent.prototype, "rows", void 0);
__decorate([
PropertyApi({
description: 'Mask pattern where _ - is digit',
type: 'string',
default: null
}),
Input(),
__metadata("design:type", String),
__metadata("design:paramtypes", [String])
], InputComponent.prototype, "mask", null);
__decorate([
PropertyApi({
description: 'Button for reset input; Allow multiple lines in input',
path: 'ui.feature',
options: [Feature.allowEmpty, Feature.multiline],
}),
HostBinding('attr.data-features'),
Input(),
__metadata("design:type", Array)
], InputComponent.prototype, "features", void 0);
__decorate([
PropertyApi({
description: 'Click event',
path: 'EventEmitter'
}),
Output(),
__metadata("design:type", Object)
], InputComponent.prototype, "click", void 0);
__decorate([
HostBinding('attr.tabindex'),
__metadata("design:type", Object)
], InputComponent.prototype, "tabindex", void 0);
__decorate([
HostListener('blur'),
__metadata("design:type", Object)
], InputComponent.prototype, "onBlur", void 0);
InputComponent = InputComponent_1 = __decorate([
Component({
selector: 'jnt-input',
template: "<form child-of=\"jnt-input-host\" [formGroup]=\"form\">\n <div child-of=\"jnt-input-host\" data-label *ngIf=\"!!label\">{{label}}</div>\n <jnt-stack child-of=\"jnt-input-host\" data-content [orientation]=\"ui.orientation.horizontal\"\n [gutter]=\"ui.gutter.small\" [align]=\"ui.align.center\">\n <jnt-icon child-of=\"jnt-input-host\" data-label-icon *ngIf=\"!!icon && !label && !(features | includes : ui.feature.multiline)\"\n [icon]=\"icon\">\n </jnt-icon>\n\n <input child-of=\"jnt-input-host\" #maskedInput *ngIf=\"!!mask; else inputTemplate\"\n formControlName=\"formatted\"\n type=\"tel\"\n [name]=\"name\"\n (focusin)=\"focused = true\"\n (focusout)=\"focused = false\"\n [placeholder]=\"mask\"\n [readonly]=\"readonly ? readonly : null\"\n [autocomplete]=\"autocomplete\"\n (paste)=\"pasteMask($event)\"\n (keydown)=\"keydownMask($event)\" />\n\n <ng-template #inputTemplate>\n <textarea child-of=\"jnt-input-host\" *ngIf=\"features | includes: ui.feature.multiline; else singleLineTemplate\"\n formControlName=\"input\"\n [placeholder]=\"placeholder\"\n [attr.rows]=\"rows\"\n (focusin)=\"focused = true\"\n (focusout)=\"focused = false\">\n </textarea>\n <ng-template #singleLineTemplate>\n <input child-of=\"jnt-input-host\" #valueInput\n formControlName=\"input\"\n [name]=\"name\"\n [type]=\"type === ui.input.type.password && view.password.display ? ui.input.type.text : type\"\n [placeholder]=\"placeholder\"\n [readonly]=\"readonly ? readonly : null\"\n [autocomplete]=\"autocomplete\"\n [min]=\"min\"\n [max]=\"max\"\n (focusin)=\"focused = true\"\n (focusout)=\"focused = false\"\n (keydown)=\"keydown($event)\"\n (keyup)=\"keyup()\" />\n </ng-template>\n </ng-template>\n\n <div child-of=\"jnt-input-host\" data-loading *ngIf=\"state === ui.state.loading\">\n <jnt-spinner child-of=\"jnt-input-host\" data-spinner></jnt-spinner>\n </div>\n\n <div child-of=\"jnt-input-host\" data-warning *ngIf=\"state === ui.state.warning\">\n <jnt-icon child-of=\"jnt-input-host\" [icon]=\"ui.icons.warning\"></jnt-icon>\n </div>\n\n <div child-of=\"jnt-input-host\" data-checked *ngIf=\"state === ui.state.checked\">\n <jnt-icon child-of=\"jnt-input-host\" [icon]=\"ui.icons.checked\"></jnt-icon>\n </div>\n\n <button child-of=\"jnt-input-host\" data-view *ngIf=\"type === ui.input.type.password\"\n (click)=\"view.password.display = !view.password.display\" tabindex=\"-1\">\n <jnt-icon child-of=\"jnt-input-host\" [icon]=\"view.password.display ? ui.icons.viewHide : ui.icons.view\"></jnt-icon>\n </button>\n\n <button child-of=\"jnt-input-host\" data-reset *ngIf=\"features | includes: ui.feature.allowEmpty\" tabindex=\"-1\"\n (click)=\"clear($event)\">\n <jnt-icon child-of=\"jnt-input-host\" [icon]=\"ui.icons.closeSmall\"></jnt-icon>\n </button>\n\n <div child-of=\"jnt-input-host\" data-arrows *ngIf=\"type === ui.input.type.number\">\n <button child-of=\"jnt-input-host\" [disabled]=\"inputControl.disabled\" (click)=\"setNumber(step || 1)\" tabindex=\"-1\">\n <jnt-icon child-of=\"jnt-input-host\" [icon]=\"ui.icons.smallUp\"></jnt-icon>\n </button>\n <button child-of=\"jnt-input-host\" [disabled]=\"inputControl.disabled\" (click)=\"setNumber(-step || -1)\" tabindex=\"-1\">\n <jnt-icon child-of=\"jnt-input-host\" [icon]=\"ui.icons.smallDown\"></jnt-icon>\n </button>\n </div>\n </jnt-stack>\n</form>",
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(function () { return InputComponent_1; }),
multi: true
}
]
}),
__metadata("design:paramtypes", [NGXLogger,
FormBuilder])
], InputComponent);
return InputComponent;
}());
export { InputComponent };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5wdXQuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6Im5nOi8vQGp1bnRlL3VpLyIsInNvdXJjZXMiOlsibGliL2Zvcm1zL2lucHV0L2lucHV0LmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsT0FBTyxFQUNMLFNBQVMsRUFDVCxVQUFVLEVBQ1YsWUFBWSxFQUNaLFVBQVUsRUFDVixXQUFXLEVBQ1gsWUFBWSxFQUNaLEtBQUssRUFFTCxNQUFNLEVBQ04sU0FBUyxFQUNWLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxXQUFXLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUN0RixPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sWUFBWSxDQUFDO0FBQ3ZDLE9BQU8sRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDbkUsT0FBTyxFQUFFLEdBQUcsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQ2hELE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUN4RCxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDbkQsT0FBTyxFQUFFLElBQUksRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQzdDLE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUMvQyxPQUFPLEVBQUUsU0FBUyxFQUFFLGFBQWEsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQ2pFLE9BQU8sRUFBRSxFQUFFLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUN6QyxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDL0MsT0FBTyxFQUFFLGlCQUFpQixFQUFFLFdBQVcsRUFBRSxTQUFTLEVBQUUsTUFBTSxTQUFTLENBQUM7QUFFcEUsSUFBTSxlQUFlLEdBQUcsR0FBRyxDQUFDO0FBQzVCLElBQU0sVUFB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OzhDQU1QO0lBYUQ7UUFQQyxXQUFXLENBQUM7WUFDWCxXQUFXLEVBQUUsdURBQXVEO1lBQ3BFLElBQUksRUFBRSxZQUFZO1lBQ2xCLE9BQU8sRUFBRSxDQUFDLE9BQU8sQ0FBQyxVQUFVLEVBQUUsT0FBTyxDQUFDLFNBQVMsQ0FBQztTQUNqRCxDQUFDO1FBQ0QsV0FBVyxDQUFDLG9CQUFvQixDQUFDO1FBQ2pDLEtBQUssRUFBRTs7b0RBQ2lCO0lBT3pCO1FBTEMsV0FBVyxDQUFDO1lBQ1gsV0FBVyxFQUFFLGFBQWE7WUFDMUIsSUFBSSxFQUFFLGNBQWM7U0FDckIsQ0FBQztRQUNELE1BQU0sRUFBRTs7aURBQ3VCO0lBR2hDO1FBREMsV0FBVyxDQUFDLGVBQWUsQ0FBQzs7b0RBQ2hCO0lBTVM7UUFBckIsWUFBWSxDQUFDLE1BQU0sQ0FBQzs7a0RBQWlDO0lBOU8zQyxjQUFjO1FBWDFCLFNBQVMsQ0FBQztZQUNULFFBQVEsRUFBRSxXQUFXO1lBQ3JCLHN4SEFBd0M7WUFDeEMsU0FBUyxFQUFFO2dCQUNUO29CQUNFLE9BQU8sRUFBRSxpQkFBaUI7b0JBQzFCLFdBQVcsRUFBRSxVQUFVLENBQUMsY0FBTSxPQUFBLGdCQUFjLEVBQWQsQ0FBYyxDQUFDO29CQUM3QyxLQUFLLEVBQUUsSUFBSTtpQkFDWjthQUNGO1NBQ0YsQ0FBQzt5Q0FpUDRCLFNBQVM7WUFDYixXQUFXO09BalB4QixjQUFjLENBdVgxQjtJQUFELHFCQUFDO0NBQUEsQUF2WEQsSUF1WEM7U0F2WFksY0FBYyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIENvbXBvbmVudCxcbiAgRWxlbWVudFJlZixcbiAgRXZlbnRFbWl0dGVyLFxuICBmb3J3YXJkUmVmLFxuICBIb3N0QmluZGluZyxcbiAgSG9zdExpc3RlbmVyLFxuICBJbnB1dCxcbiAgT25Jbml0LFxuICBPdXRwdXQsXG4gIFZpZXdDaGlsZFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IENvbnRyb2xWYWx1ZUFjY2Vzc29yLCBGb3JtQnVpbGRlciwgTkdfVkFMVUVfQUNDRVNTT1IgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBOR1hMb2dnZXIgfSBmcm9tICduZ3gtbG9nZ2VyJztcbmltcG9ydCB7IGZpbHRlciwgbWFwLCBkaXN0aW5jdFVudGlsQ2hhbmdlZCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7IEtleSB9IGZyb20gJy4uLy4uL2NvcmUvZW51bXMva2V5Ym9hcmQnO1xuaW1wb3J0IHsgUHJvcGVydHlBcGkgfSBmcm9tICcuLi8uLi9jb3JlL2RlY29yYXRvcnMvYXBpJztcbmltcG9ydCB7IEZlYXR1cmUgfSBmcm9tICcuLi8uLi9jb3JlL2VudW1zL2ZlYXR1cmUnO1xuaW1wb3J0IHsgU2l6ZSB9IGZyb20gJy4uLy4uL2NvcmUvZW51bXMvc2l6ZSc7XG5pbXBvcnQgeyBTdGF0ZSB9IGZyb20gJy4uLy4uL2NvcmUvZW51bXMvc3RhdGUnO1xuaW1wb3J0IHsgVGV4dEFsaWduLCBUZXh0VHJhbnNmb3JtIH0gZnJvbSAnLi4vLi4vY29yZS9lbnVtcy90ZXh0JztcbmltcG9ydCB7IFVJIH0gZnJvbSAnLi4vLi4vY29yZS9lbnVtcy91aSc7XG5pbXBvcnQgeyBXaWR0aCB9IGZyb20gJy4uLy4uL2NvcmUvZW51bXMvd2lkdGgnO1xuaW1wb3J0IHsgSW5wdXRBdXRvY29tcGxldGUsIElucHV0U2NoZW1lLCBJbnB1dFR5cGUgfSBmcm9tICcuL2VudW1zJztcblxuY29uc3QgRElHSVRfTUFTS19DSEFSID0gJ18nO1xuY29uc3QgRElHSVRfS0VZUyA9IFsnMCcsICcxJywgJzInLCAnMycsICc0JywgJzUnLCAnNicsICc3JywgJzgnLCAnOSddO1xuY29uc3QgREVGQVVMVF9OVU1CRVIgPSAwO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdqbnQtaW5wdXQnLFxuICB0ZW1wbGF0ZVVybDogJy4vaW5wdXQuZW5jYXBzdWxhdGVkLmh0bWwnLFxuICBwcm92aWRlcnM6IFtcbiAgICB7XG4gICAgICBwcm92aWRlOiBOR19WQUxVRV9BQ0NFU1NPUixcbiAgICAgIHVzZUV4aXN0aW5nOiBmb3J3YXJkUmVmKCgpID0+IElucHV0Q29tcG9uZW50KSxcbiAgICAgIG11bHRpOiB0cnVlXG4gICAgfVxuICBdXG59KVxuZXhwb3J0IGNsYXNzIElucHV0Q29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBDb250cm9sVmFsdWVBY2Nlc3NvciB7XG5cbiAgQEhvc3RCaW5kaW5nKCdhdHRyLmhvc3QnKVxuICByZWFkb25seSBob3N0ID0gJ2pudC1pbnB1dC1ob3N0JztcblxuICB1aSA9IFVJO1xuICB2aWV3ID0ge3Bhc3N3b3JkOiB7ZGlzcGxheTogZmFsc2V9fTtcblxuICBwcml2YXRlIF9tYXNrOiBzdHJpbmc7XG4gIHByaXZhdGUgX3R5cGU6IElucHV0VHlwZSA9IElucHV0VHlwZS50ZXh0O1xuICBwcml2YXRlIF9wbGFjZWhvbGRlcjogc3RyaW5nID0gJyc7XG5cbiAgaW5wdXRDb250cm9sID0gdGhpcy5mYi5jb250cm9sKG51bGwpO1xuICBmb3JtYXR0ZWRDb250cm9sID0gdGhpcy5mYi5jb250cm9sKG51bGwpO1xuICBmb3JtID0gdGhpcy5mYi5ncm91cCh7XG4gICAgaW5wdXQ6IHRoaXMuaW5wdXRDb250cm9sLFxuICAgIGZvcm1hdHRlZDogdGhpcy5mb3JtYXR0ZWRDb250cm9sXG4gIH0pO1xuXG4gIEBWaWV3Q2hpbGQoJ3ZhbHVlSW5wdXQnLCB7cmVhZDogRWxlbWVudFJlZiwgc3RhdGljOiBmYWxzZX0pXG4gIHZhbHVlSW5wdXQ6IEVsZW1lbnRSZWY7XG5cbiAgQFZpZXdDaGlsZCgnbWFza2VkSW5wdXQnLCB7cmVhZDogRWxlbWVudFJlZiwgc3RhdGljOiBmYWxzZX0pXG4gIG1hc2tlZElucHV0OiBFbGVtZW50UmVmO1xuXG4gIEBIb3N0QmluZGluZygnYXR0ci5kYXRhLWZvY3VzZWQnKVxuICBmb2N1c2VkID0gZmFsc2U7XG5cbiAgQEhvc3RCaW5kaW5nKCdhdHRyLmRhdGEtZGlzYWJsZWQnKVxuICBkaXNhYmxlZCA9IGZhbHNlO1xuXG4gIEBIb3N0QmluZGluZygnYXR0ci5kYXRhLXNjaGVtZScpXG4gIF9zY2hlbWU6IElucHV0U2NoZW1lID0gSW5wdXRTY2hlbWUubm9ybWFsO1xuXG4gIEBIb3N0QmluZGluZygnYXR0ci5kYXRhLXNpemUnKVxuICBfc2l6ZTogU2l6ZSA9IFNpemUubm9ybWFsO1xuXG4gIEBIb3N0QmluZGluZygnYXR0ci5kYXRhLXdpZHRoJylcbiAgX3dpZHRoOiBXaWR0aCA9IFdpZHRoLmRlZmF1bHQ7XG5cbiAgQEhvc3RCaW5kaW5nKCdhdHRyLmRhdGEtd2l0aC1pY29uJylcbiAgZ2V0IHdpdGhJY29uKCkge1xuICAgIHJldHVybiAhIXRoaXMuaWNvbjtcbiAgfVxuXG4gIEBQcm9wZXJ0eUFwaSh7XG4gICAgZGVzY3JpcHRpb246ICdJY29uIGZvciBpbnB1dCcsXG4gICAgdHlwZTogJ3N0cmluZycsXG4gIH0pXG4gIEBJbnB1dCgpXG4gIGljb246IHN0cmluZztcblxuICBAUHJvcGVydHlBcGkoe1xuICAgIGRlc2NyaXB0aW9uOiAnTGFiZWwgZm9yIGlucHV0JyxcbiAgICB0eXBlOiAnc3RyaW5nJyxcbiAgfSlcbiAgQElucHV0KClcbiAgbGFiZWw6IHN0cmluZztcblxuICBAUHJvcGVydHlBcGkoe1xuICAgIGRlc2NyaXB0aW9uOiAnTmFtZSBmb3IgaW5wdXQnLFxuICAgIHR5cGU6ICdzdHJpbmcnXG4gIH0pXG4gIEBJbnB1dCgpXG4gIG5hbWU6IHN0cmluZyA9IG51bGw7XG5cbiAgQFByb3BlcnR5QXBpKHtcbiAgICBkZXNjcmlwdGlvbjogJ1RleHQgdHJhbnNmb3JtIGZvciBpbnB1dCcsXG4gICAgcGF0aDogJ3VpLnRleHQudHJhbnNmb3JtJyxcbiAgICBvcHRpb25zOiBbVGV4dFRyYW5zZm9ybS5jYXBpdGFsaXplLCBUZXh0VHJhbnNmb3JtLnVwcGVyY2FzZSwgVGV4dFRyYW5zZm9ybS5sb3dlcmNhc2VdXG4gIH0pXG4gIEBJbnB1dCgpXG4gIHRyYW5zZm9ybTogVGV4dFRyYW5zZm9ybTtcblxuICBAUHJvcGVydHlBcGkoe1xuICAgIGRlc2NyaXB0aW9uOiAnQXV0byBjb21wbGV0ZSBmb3IgaW5wdXQnLFxuICAgIHBhdGg6ICd1aS5pbnB1dC5hdXRvY29tcGxldGUnLFxuICAgIG9wdGlvbnM6IFtJbnB1dEF1dG9jb21wbGV0ZS5vbiwgSW5wdXRBdXRvY29tcGxldGUub2ZmXVxuICB9KVxuICBASW5wdXQoKVxuICBhdXRvY29tcGxldGU6IElucHV0QXV0b2NvbXBsZXRlID0gSW5wdXRBdXRvY29tcGxldGUub2ZmO1xuXG4gIEBQcm9wZXJ0eUFwaSh7XG4gICAgZGVzY3JpcHRpb246ICdJbnB1dCB0ZXh0IGFsaWduJyxcbiAgICBwYXRoOiAndWkudGV4dC5hbGlnbicsXG4gICAgZGVmYXVsdDogVGV4dEFsaWduLmxlZnQsXG4gICAgb3B0aW9uczogW1RleHRBbGlnbi5sZWZ0LCBUZXh0QWxpZ24ucmlnaHRdXG4gIH0pXG4gIEBIb3N0QmluZGluZygnYXR0ci5kYXRhLXRleHRBbGlnbicpXG4gIEBJbnB1dCgpXG4gIHRleHRBbGlnbjogVGV4dEFsaWduID0gVGV4dEFsaWduLmxlZnQ7XG5cbiAgQFByb3BlcnR5QXBpKHtcbiAgICBkZXNjcmlwdGlvbjogJ01pbmltdW0gbnVtYmVyIHZhbHVlIHRoYXQgY2FuIGJlIGVudGVyZWQuIEZvciBpbnB1dCB3aXRoIHR5cGVDb250cm9sID0gbnVtYmVyJyxcbiAgICB0eXBlOiAnbnVtYmVyJyxcbiAgfSlcbiAgQElucHV0KClcbiAgbWluOiBudW1iZXIgPSBudWxsO1xuXG4gIEBQcm9wZXJ0eUFwaSh7XG4gICAgZGVzY3JpcHRpb246ICdNYXhpbXVtIG51bWJlciB2YWx1ZSB0aGF0IGNhbiBiZSBlbnRlcmVkLiBGb3IgaW5wdXQgd2l0aCB0eXBlQ29udHJvbCA9IG51bWJlcicsXG4gICAgdHlwZTogJ251bWJlcicsXG4gIH0pXG4gIEBJbnB1dCgpXG4gIG1heDogbnVtYmVyID0gbnVsbDtcblxuICBAUHJvcGVydHlBcGkoe1xuICAgIGRlc2NyaXB0aW9uOiAnU3RlcCBmb3IgZW50ZXJlZCB2YWx1ZS4gRm9yIGlucHV0IHdpdGggdHlwZUNvbnRyb2wgPSBudW1iZXInLFxuICAgIHR5cGU6ICdudW1iZXInLFxuICB9KVxuICBASW5wdXQoKVxuICBzdGVwID0gMTtcblxuICBAUHJvcGVydHlBcGkoe1xuICAgIGRlc2NyaXB0aW9uOiAnVXNlZCB0byBzcGVjaWZ5IHRoYXQgdGhlIGlucHV0IGZpZWxkIGlzIHJlYWQtb25seScsXG4gICAgdHlwZTogJ2Jvb2xlYW4nLFxuICAgIGRlZmF1bHQ6ICdmYWxzZSdcbiAgfSlcbiAgQElucHV0KClcbiAgcmVhZG9ubHkgPSBmYWxzZTtcblxuICBAUHJvcGVydHlBcGkoe1xuICAgIGRlc2NyaXB0aW9uOiAnSW5wdXQgc2NoZW1lJyxcbiAgICBwYXRoOiAndWkuaW5wdXQuc2NoZW1lJyxcbiAgICBkZWZhdWx0OiBJbnB1dFNjaGVtZS5ub3JtYWwsXG4gICAgb3B0aW9uczogW0lucHV0U2NoZW1lLm5vcm1hbCwgSW5wdXRTY2hlbWUuc3VjY2VzcywgSW5wdXRTY2hlbWUuZmFpbGVkXVxuICB9KVxuICBASW5wdXQoKVxuICBzZXQgc2NoZW1lKHNjaGVtZTogSW5wdXRTY2hlbWUpIHtcbiAgICB0aGlzLl9zY2hlbWUgPSBzY2hlbWUgfHwgSW5wdXRTY2hlbWUubm9ybWFsO1xuICB9XG5cbiAgQFByb3BlcnR5QXBpKHtcbiAgICBkZXNjcmlwdGlvbjogJ0lucHV0IHBsYWNlaG9sZGVyJyxcbiAgICB0eXBlOiAnc3RyaW5nJyxcbiAgfSlcbiAgQElucHV0KClcbiAgc2V0IHBsYWNlaG9sZGVyKHBsYWNlaG9sZGVyOiBzdHJpbmcpIHtcbiAgICB0aGlzLl9wbGFjZWhvbGRlciA9IHBsYWNlaG9sZGVyIHx8ICcnO1xuICB9XG5cbiAgZ2V0IHBsYWNlaG9sZGVyKCkge1xuICAgIHJldHVybiB0aGlzLl9wbGFjZWhvbGRlcjtcbiAgfVxuXG4gIEBQcm9wZXJ0eUFwaSh7XG4gICAgZGVzY3JpcHRpb246ICdJbnB1dCB0eXBlQ29udHJvbCcsXG4gICAgcGF0aDogJ3VpLmlucHV0LnR5cGUnLFxuICAgIGRlZmF1bHQ6IElucHV0VHlwZS50ZXh0LFxuICAgIG9wdGlvbnM6IFtJbnB1dFR5cGUudGV4dCwgSW5wdXRUeXBlLm51bWJlciwgSW5wdXRUeXBlLnBhc3N3b3JkXVxuICB9KVxuICBASW5wdXQoKVxuICBzZXQgdHlwZSh0eXBlOiBJbnB1dFR5cGUpIHtcbiAgICB0aGlzLl90eXBlID0gdHlwZSB8fCBJbnB1dFR5cGUudGV4dDtcbiAgfVxuXG4gIGdldCB0eXBlKCkge1xuICAgIHJldHVybiB0aGlzLl90eXBlO1xuICB9XG5cbiAgQFByb3BlcnR5QXBpKHtcbiAgICBkZXNjcmlwdGlvbjogJ0lucHV0IHNpemUnLFxuICAgIHBhdGg6ICd1aS5zaXplJyxcbiAgICBkZWZhdWx0OiBTaXplLm5vcm1hbCxcbiAgICBvcHRpb25zOiBbU2l6ZS5zbWFsbCwgU2l6ZS5ub3JtYWwsIFNpemUubGFyZ2VdXG4gIH0pXG4gIEBJbnB1dCgpXG4gIHNldCBzaXplKHNpemU6IFNpemUpIHtcbiAgICB0aGlzLl9zaXplID0gc2l6ZSB8fCBTaXplLm5vcm1hbDtcbiAgfVxuXG4gIEBQcm9wZXJ0eUFwaSh7XG4gICAgZGVzY3JpcHRpb246ICdJbnB1dCB3aWR0aCcsXG4gICAgcGF0aDogJ3VpLndpZHRoJyxcbiAgICBkZWZhdWx0OiBXaWR0aC5kZWZhdWx0LFxuICAgIG9wdGlvbnM6IFtXaWR0aC5kZWZhdWx0LCBXaWR0aC5mbHVpZF1cbiAgfSlcbiAgQElucHV0KCkgc2V0IHdpZHRoKHdpZHRoOiBXaWR0aCkge1xuICAgIHRoaXMuX3dpZHRoID0gd2lkdGggfHwgV2lkdGguZGVmYXVsdDtcbiAgfVxuXG4gIEBQcm9wZXJ0eUFwaSh7XG4gICAgZGVzY3JpcHRpb246ICdJbnB1dCBzdGF0ZScsXG4gICAgcGF0aDogJ3VpLnN0YXRlJyxcbiAgICBvcHRpb25zOiBbU3RhdGUubG9hZGluZywgU3RhdGUud2FybmluZywgU3RhdGUuY2hlY2tlZF1cbiAgfSlcbiAgQEhvc3RCaW5kaW5nKCdhdHRyLmRhdGEtc3RhdGUnKVxuICBASW5wdXQoKVxuICBzdGF0ZTogU3RhdGU7XG5cbiAgQFByb3BlcnR5QXBpKHtcbiAgICBkZXNjcmlwdGlvbjogJ01heCByb3dzIGZvciBtdWx0aWxpbmUgbW9kZScsXG4gICAgdHlwZTogJ251bWJlcicsXG4gICAgZGVmYXVsdDogNSxcbiAgfSlcbiAgQElucHV0KClcbiAgcm93cyA9IDU7XG5cbiAgQFByb3BlcnR5QXBpKHtcbiAgICBkZXNjcmlwdGlvbjogJ01hc2sgcGF0dGVybiB3aGVyZSBfIC0gaXMgZGlnaXQnLFxuICAgIHR5cGU6ICdzdHJpbmcnLFxuICAgIGRlZmF1bHQ6IG51bGxcbiAgfSlcbiAgQElucHV0KClcbiAgc2V0IG1hc2sobWFzazogc3RyaW5nKSB7XG4gICAgdGhpcy5fbWFzayA9IG1hc2s7XG4gICAgaWYgKCEhbWFzaykge1xuICAgICAgdGhpcy5mb3JtLnNldFZhbHVlKHRoaXMubWFza2luZyh0aGlzLmlucHV0Q29udHJvbC52YWx1ZSB8fCAnJykpO1xuICAgIH1cbiAgfVxuXG4gIGdldCBtYXNrKCkge1xuICAgIHJldHVybiB0aGlzLl9tYXNrO1xuICB9XG5cbiAgQFByb3BlcnR5QXBpKHtcbiAgICBkZXNjcmlwdGlvbjogJ0J1dHRvbiBmb3IgcmVzZXQgaW5wdXQ7IEFsbG93IG11bHRpcGxlIGxpbmVzIGluIGlucHV0JyxcbiAgICBwYXRoOiAndWkuZmVhdHVyZScsXG4gICAgb3B0aW9uczogW0ZlYXR1cmUuYWxsb3dFbXB0eSwgRmVhdHVyZS5tdWx0aWxpbmVdLFxuICB9KVxuICBASG9zdEJpbmRpbmcoJ2F0dHIuZGF0YS1mZWF0dXJlcycpXG4gIEBJbnB1dCgpXG4gIGZlYXR1cmVzOiBGZWF0dXJlW10gPSBbXTtcblxuICBAUHJvcGVydHlBcGkoe1xuICAgIGRlc2NyaXB0aW9uOiAnQ2xpY2sgZXZlbnQnLFxuICAgIHBhdGg6ICdFdmVudEVtaXR0ZXInXG4gIH0pXG4gIEBPdXRwdXQoKVxuICBjbGljayA9IG5ldyBFdmVudEVtaXR0ZXI8YW55PigpO1xuXG4gIEBIb3N0QmluZGluZygnYXR0ci50YWJpbmRleCcpXG4gIHRhYmluZGV4ID0gMTtcblxuICBvbkNoYW5nZTogKHZhbHVlOiBhbnkpID0+IHZvaWQgPSAoKSA9PiB0aGlzLmxvZ2dlci5lcnJvcigndmFsdWUgYWNjZXNzb3IgaXMgbm90IHJlZ2lzdGVyZWQnKTtcbiAgb25Ub3VjaGVkOiAoKSA9PiB2b2lkID0gKCkgPT4gdGhpcy5sb2dnZXIuZXJyb3IoJ3ZhbHVlIGFjY2Vzc29yIGlzIG5vdCByZWdpc3RlcmVkJyk7XG4gIHJlZ2lzdGVyT25DaGFuZ2UgPSBmbiA9PiB0aGlzLm9uQ2hhbmdlID0gZm47XG4gIHJlZ2lzdGVyT25Ub3VjaGVkID0gZm4gPT4gdGhpcy5vblRvdWNoZWQgPSBmbjtcbiAgQEhvc3RMaXN0ZW5lcignYmx1cicpIG9uQmx1ciA9ICgpID0+IHRoaXMub25Ub3VjaGVkKCk7XG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSBsb2dnZXI6IE5HWExvZ2dlcixcbiAgICAgICAgICAgICAgcHJpdmF0ZSBmYjogRm9ybUJ1aWxkZXIpIHtcbiAgfVxuXG4gIG5nT25Jbml0KCkge1xuICAgIHRoaXMuaW5wdXRDb250cm9sLnZhbHVlQ2hhbmdlcy5zdWJzY3JpYmUodmFsdWUgPT5cbiAgICAgIHRoaXMub25DaGFuZ2UoISF2YWx1ZSA/ICh0aGlzLnR5cGUgPT09IElucHV0VHlwZS5udW1iZXIgPyArdmFsdWUgOiB2YWx1ZSkgOiBudWxsKSk7XG5cbiAgICB0aGlzLmZvcm1hdHRlZENvbnRyb2wudmFsdWVDaGFuZ2VzLnBpcGUoXG4gICAgICBkaXN0aW5jdFVudGlsQ2hhbmdlZCgpLFxuICAgICAgZmlsdGVyKCgpID0+ICEhdGhpcy5tYXNrZWRJbnB1dCksXG4gICAgICBtYXAoZm9ybWF0dGVkID0+ICEhZm9ybWF0dGVkID8gZm9ybWF0dGVkIDogdGhpcy5tYXNrKVxuICAgICkuc3Vic2NyaWJlKGZvcm1hdHRlZCA9PiB7XG4gICAgICBjb25zdCBwb3NpdGlvbiA9IGZvcm1hdHRlZC5pbmRleE9mKERJR0lUX01BU0tfQ0hBUik7XG4gICAgICB0aGlzLm1hc2tlZElucHV0Lm5hdGl2ZUVsZW1lbnQuc2V0U2VsZWN0aW9uUmFuZ2UocG9zaXRpb24sIHBvc2l0aW9uKTtcblxuICAgICAgbGV0IGNsZWFyZWQgPSB7aW5wdXQ6IG51bGwsIGZvcm1hdHRlZDogbnVsbH07XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMubWFzay5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZiAodGhpcy5tYXNrLmNoYXJBdChpKSAhPT0gZm9ybWF0dGVkLmNoYXJBdChpKSkge1xuICAgICAgICAgIGNsZWFyZWQgPSB0aGlzLm1hc2tpbmcoZm9ybWF0dGVkLnN1YnN0cihpKSk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGlmIChjbGVhcmVkLmlucHV0ICE9PSB0aGlzLmlucHV0Q29udHJvbC52YWx1ZSB8fCBjbGVhcmVkLmZvcm1hdHRlZCAhPT0gdGhpcy5mb3JtYXR0ZWRDb250cm9sLnZhbHVlKSB7XG4gICAgICAgIHRoaXMuZm9ybS5zZXRWYWx1ZShjbGVhcmVkKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgbWFza2luZyh2YWx1ZTogc3RyaW5nID0gbnVsbCk6IHtcbiAgICBpbnB1dDogc3RyaW5nLFxuICAgIGZvcm1hdHRlZDogc3RyaW5nXG4gIH0ge1xuICAgIGNvbnN0IGNoYXJzID0gISF2YWx1ZSA/IHZhbHVlLnJlcGxhY2UoL1xcRC9naSwgJycpIDogJyc7XG4gICAgbGV0IGZvcm1hdHRlZCA9IHRoaXMubWFzaztcbiAgICBjb25zdCBsZW5ndGggPSB0aGlzLm1hc2suc3BsaXQoRElHSVRfTUFTS19DSEFSKS5sZW5ndGggLSAxO1xuICAgIGZvciAobGV0IGNoYXIgb2YgY2h