ng-otp-input
Version:
A fully customizable, one-time password input component for the web built with Angular.
384 lines • 28.7 kB
JavaScript
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
import { Component, Input, Output, EventEmitter } from '@angular/core';
import { FormGroup, FormControl } from '@angular/forms';
import { KeysPipe } from '../../pipes/keys.pipe';
import { Config } from '../../models/config';
var NgOtpInputComponent = /** @class */ (function () {
function NgOtpInputComponent(keysPipe) {
this.keysPipe = keysPipe;
this.config = { length: 4 };
// tslint:disable-next-line: no-output-on-prefix
this.onInputChange = new EventEmitter();
this.inputControls = new Array(this.config.length);
this.componentKey = Math.random()
.toString(36)
.substring(2) + new Date().getTime().toString(36);
}
/**
* @return {?}
*/
NgOtpInputComponent.prototype.ngOnInit = /**
* @return {?}
*/
function () {
this.otpForm = new FormGroup({});
for (var index = 0; index < this.config.length; index++) {
this.otpForm.addControl(this.getControlName(index), new FormControl());
}
this.inputType = this.getInputType();
};
/**
* @return {?}
*/
NgOtpInputComponent.prototype.ngAfterViewInit = /**
* @return {?}
*/
function () {
var _this = this;
if (!this.config.disableAutoFocus) {
/** @type {?} */
var containerItem = document.getElementById("c_" + this.componentKey);
if (containerItem) {
containerItem.addEventListener('paste', (/**
* @param {?} evt
* @return {?}
*/
function (evt) { return _this.handlePaste(evt); }));
/** @type {?} */
var ele = containerItem.getElementsByClassName('otp-input')[0];
if (ele && ele.focus) {
ele.focus();
}
}
}
};
/**
* @private
* @param {?} idx
* @return {?}
*/
NgOtpInputComponent.prototype.getControlName = /**
* @private
* @param {?} idx
* @return {?}
*/
function (idx) {
return "ctrl_" + idx;
};
/**
* @param {?} event
* @return {?}
*/
NgOtpInputComponent.prototype.ifLeftArrow = /**
* @param {?} event
* @return {?}
*/
function (event) {
return this.ifKeyCode(event, 37);
};
/**
* @param {?} event
* @return {?}
*/
NgOtpInputComponent.prototype.ifRightArrow = /**
* @param {?} event
* @return {?}
*/
function (event) {
return this.ifKeyCode(event, 39);
};
/**
* @param {?} event
* @return {?}
*/
NgOtpInputComponent.prototype.ifBackspaceOrDelete = /**
* @param {?} event
* @return {?}
*/
function (event) {
return (event.key === 'Backspace' ||
event.key === 'Delete' ||
this.ifKeyCode(event, 8) ||
this.ifKeyCode(event, 46));
};
/**
* @param {?} event
* @param {?} targetCode
* @return {?}
*/
NgOtpInputComponent.prototype.ifKeyCode = /**
* @param {?} event
* @param {?} targetCode
* @return {?}
*/
function (event, targetCode) {
/** @type {?} */
var key = event.keyCode || event.charCode;
// tslint:disable-next-line: triple-equals
return key == targetCode ? true : false;
};
/**
* @param {?} $event
* @return {?}
*/
NgOtpInputComponent.prototype.onKeyDown = /**
* @param {?} $event
* @return {?}
*/
function ($event) {
/** @type {?} */
var isSpace = this.ifKeyCode($event, 32);
if (isSpace) { // prevent space
return false;
}
};
/**
* @param {?} $event
* @param {?} inputIdx
* @return {?}
*/
NgOtpInputComponent.prototype.onKeyUp = /**
* @param {?} $event
* @param {?} inputIdx
* @return {?}
*/
function ($event, inputIdx) {
/** @type {?} */
var nextInputId = this.appendKey("otp_" + (inputIdx + 1));
/** @type {?} */
var prevInputId = this.appendKey("otp_" + (inputIdx - 1));
if (this.ifRightArrow($event)) {
this.setSelected(nextInputId);
return;
}
if (this.ifLeftArrow($event)) {
this.setSelected(prevInputId);
return;
}
/** @type {?} */
var isBackspace = this.ifBackspaceOrDelete($event);
if (isBackspace && !$event.target.value) {
this.setSelected(prevInputId);
this.rebuildValue();
return;
}
if (!$event.target.value) {
return;
}
if (this.ifValidEntry($event)) {
this.setSelected(nextInputId);
}
this.rebuildValue();
};
/**
* @param {?} id
* @return {?}
*/
NgOtpInputComponent.prototype.appendKey = /**
* @param {?} id
* @return {?}
*/
function (id) {
return id + "_" + this.componentKey;
};
/**
* @param {?} eleId
* @return {?}
*/
NgOtpInputComponent.prototype.setSelected = /**
* @param {?} eleId
* @return {?}
*/
function (eleId) {
this.focusTo(eleId);
/** @type {?} */
var ele = document.getElementById(eleId);
if (ele && ele.setSelectionRange) {
setTimeout((/**
* @return {?}
*/
function () {
ele.setSelectionRange(0, 1);
}), 0);
}
};
/**
* @param {?} event
* @return {?}
*/
NgOtpInputComponent.prototype.ifValidEntry = /**
* @param {?} event
* @return {?}
*/
function (event) {
/** @type {?} */
var inp = String.fromCharCode(event.keyCode);
/** @type {?} */
var isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
return (isMobile ||
/[a-zA-Z0-9-_]/.test(inp) ||
(this.config.allowKeyCodes &&
this.config.allowKeyCodes.includes(event.keyCode)) ||
(event.keyCode >= 96 && event.keyCode <= 105));
};
/**
* @param {?} eleId
* @return {?}
*/
NgOtpInputComponent.prototype.focusTo = /**
* @param {?} eleId
* @return {?}
*/
function (eleId) {
/** @type {?} */
var ele = document.getElementById(eleId);
if (ele) {
ele.focus();
}
};
// method to set component value
// method to set component value
/**
* @param {?} value
* @return {?}
*/
NgOtpInputComponent.prototype.setValue =
// method to set component value
/**
* @param {?} value
* @return {?}
*/
function (value) {
var _this = this;
if (this.config.allowNumbersOnly && isNaN(value)) {
return;
}
this.otpForm.reset();
if (!value) {
this.rebuildValue();
return;
}
value = value.toString().replace(/\s/g, ''); // remove whitespace
Array.from(value).forEach((/**
* @param {?} c
* @param {?} idx
* @return {?}
*/
function (c, idx) {
if (_this.otpForm.get(_this.getControlName(idx))) {
_this.otpForm.get(_this.getControlName(idx)).setValue(c);
}
}));
if (!this.config.disableAutoFocus) {
/** @type {?} */
var containerItem = document.getElementById("c_" + this.componentKey);
/** @type {?} */
var indexOfElementToFocus = value.length < this.config.length ? value.length : (this.config.length - 1);
/** @type {?} */
var ele = containerItem.getElementsByClassName('otp-input')[indexOfElementToFocus];
if (ele && ele.focus) {
ele.focus();
}
}
this.rebuildValue();
};
/**
* @return {?}
*/
NgOtpInputComponent.prototype.rebuildValue = /**
* @return {?}
*/
function () {
var _this = this;
/** @type {?} */
var val = '';
this.keysPipe.transform(this.otpForm.controls).forEach((/**
* @param {?} k
* @return {?}
*/
function (k) {
if (_this.otpForm.controls[k].value) {
val += _this.otpForm.controls[k].value;
}
}));
this.onInputChange.emit(val);
};
/**
* @return {?}
*/
NgOtpInputComponent.prototype.getInputType = /**
* @return {?}
*/
function () {
return this.config.isPasswordInput
? 'password'
: this.config.allowNumbersOnly
? 'tel'
: 'text';
};
/**
* @param {?} e
* @return {?}
*/
NgOtpInputComponent.prototype.handlePaste = /**
* @param {?} e
* @return {?}
*/
function (e) {
// Get pasted data via clipboard API
/** @type {?} */
var clipboardData = e.clipboardData || window['clipboardData'];
if (clipboardData) {
/** @type {?} */
var pastedData = clipboardData.getData('Text');
}
// Stop data actually being pasted into div
e.stopPropagation();
e.preventDefault();
if (!pastedData) {
return;
}
this.setValue(pastedData);
};
NgOtpInputComponent.decorators = [
{ type: Component, args: [{
// tslint:disable-next-line: component-selector
selector: 'ng-otp-input',
template: "<div class=\"wrapper {{config.containerClass}}\" id=\"c_{{componentKey}}\" *ngIf=\"otpForm?.controls\"\r\n [ngStyle]=\"config.containerStyles\">\r\n <input [pattern]=\"config.allowNumbersOnly ? '\\\\d*' : ''\" [type]=\"inputType\" numberOnly [placeholder]=\"config?.placeholder || ''\"\r\n [disabledNumberOnly]=\"!config.allowNumbersOnly\" [ngStyle]=\"config.inputStyles\" maxlength=\"1\"\r\n class=\"otp-input {{config.inputClass}}\" autocomplete=\"off\" *ngFor=\"let item of otpForm?.controls | keys;let i=index\"\r\n [formControl]=\"otpForm.controls[item]\" id=\"otp_{{i}}_{{componentKey}}\" (keydown)=\"onKeyDown($event)\"\r\n (keyup)=\"onKeyUp($event,i)\">\r\n</div>",
styles: [".otp-input{width:50px;height:50px;border-radius:4px;border:1px solid #c5c5c5;text-align:center;font-size:32px}.wrapper .otp-input:not(:last-child){margin-right:8px}@media screen and (max-width:767px){.otp-input{width:40px;font-size:24px;height:40px}}@media screen and (max-width:420px){.otp-input{width:30px;font-size:18px;height:30px}}"]
}] }
];
/** @nocollapse */
NgOtpInputComponent.ctorParameters = function () { return [
{ type: KeysPipe }
]; };
NgOtpInputComponent.propDecorators = {
config: [{ type: Input }],
onInputChange: [{ type: Output }]
};
return NgOtpInputComponent;
}());
export { NgOtpInputComponent };
if (false) {
/** @type {?} */
NgOtpInputComponent.prototype.config;
/** @type {?} */
NgOtpInputComponent.prototype.onInputChange;
/** @type {?} */
NgOtpInputComponent.prototype.otpForm;
/** @type {?} */
NgOtpInputComponent.prototype.inputControls;
/** @type {?} */
NgOtpInputComponent.prototype.componentKey;
/** @type {?} */
NgOtpInputComponent.prototype.inputType;
/**
* @type {?}
* @private
*/
NgOtpInputComponent.prototype.keysPipe;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmctb3RwLWlucHV0LmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiJuZzovL25nLW90cC1pbnB1dC8iLCJzb3VyY2VzIjpbImxpYi9jb21wb25lbnRzL25nLW90cC1pbnB1dC9uZy1vdHAtaW5wdXQuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFBQSxPQUFPLEVBQ0wsU0FBUyxFQUVULEtBQUssRUFDTCxNQUFNLEVBQ04sWUFBWSxFQUViLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxTQUFTLEVBQUUsV0FBVyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDeEQsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQ2pELE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUM3QztJQWlCRSw2QkFBb0IsUUFBa0I7UUFBbEIsYUFBUSxHQUFSLFFBQVEsQ0FBVTtRQVY3QixXQUFNLEdBQVcsRUFBRSxNQUFNLEVBQUUsQ0FBQyxFQUFFLENBQUM7O1FBRTlCLGtCQUFhLEdBQUcsSUFBSSxZQUFZLEVBQVUsQ0FBQztRQUVyRCxrQkFBYSxHQUFrQixJQUFJLEtBQUssQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQzdELGlCQUFZLEdBQ1YsSUFBSSxDQUFDLE1BQU0sRUFBRTthQUNWLFFBQVEsQ0FBQyxFQUFFLENBQUM7YUFDWixTQUFTLENBQUMsQ0FBQyxDQUFDLEdBQUcsSUFBSSxJQUFJLEVBQUUsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDLENBQUM7SUFFYixDQUFDOzs7O0lBRTFDLHNDQUFROzs7SUFBUjtRQUNFLElBQUksQ0FBQyxPQUFPLEdBQUcsSUFBSSxTQUFTLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDakMsS0FBSyxJQUFJLEtBQUssR0FBRyxDQUFDLEVBQUUsS0FBSyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxF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bnQsXHJcbiAgT25Jbml0LFxyXG4gIElucHV0LFxyXG4gIE91dHB1dCxcclxuICBFdmVudEVtaXR0ZXIsXHJcbiAgQWZ0ZXJWaWV3SW5pdFxyXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBGb3JtR3JvdXAsIEZvcm1Db250cm9sIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xyXG5pbXBvcnQgeyBLZXlzUGlwZSB9IGZyb20gJy4uLy4uL3BpcGVzL2tleXMucGlwZSc7XHJcbmltcG9ydCB7IENvbmZpZyB9IGZyb20gJy4uLy4uL21vZGVscy9jb25maWcnO1xyXG5AQ29tcG9uZW50KHtcclxuICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6IGNvbXBvbmVudC1zZWxlY3RvclxyXG4gIHNlbGVjdG9yOiAnbmctb3RwLWlucHV0JyxcclxuICB0ZW1wbGF0ZVVybDogJy4vbmctb3RwLWlucHV0LmNvbXBvbmVudC5odG1sJyxcclxuICBzdHlsZVVybHM6IFsnLi9uZy1vdHAtaW5wdXQuY29tcG9uZW50LnNjc3MnXVxyXG59KVxyXG5leHBvcnQgY2xhc3MgTmdPdHBJbnB1dENvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgQWZ0ZXJWaWV3SW5pdCB7XHJcbiAgQElucHV0KCkgY29uZmlnOiBDb25maWcgPSB7IGxlbmd0aDogNCB9O1xyXG4gIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTogbm8tb3V0cHV0LW9uLXByZWZpeFxyXG4gIEBPdXRwdXQoKSBvbklucHV0Q2hhbmdlID0gbmV3IEV2ZW50RW1pdHRlcjxzdHJpbmc+KCk7XHJcbiAgb3RwRm9ybTogRm9ybUdyb3VwO1xyXG4gIGlucHV0Q29udHJvbHM6IEZvcm1Db250cm9sW10gPSBuZXcgQXJyYXkodGhpcy5jb25maWcubGVuZ3RoKTtcclxuICBjb21wb25lbnRLZXkgPVxyXG4gICAgTWF0aC5yYW5kb20oKVxyXG4gICAgICAudG9TdHJpbmcoMzYpXHJcbiAgICAgIC5zdWJzdHJpbmcoMikgKyBuZXcgRGF0ZSgpLmdldFRpbWUoKS50b1N0cmluZygzNik7XHJcbiAgaW5wdXRUeXBlOiBzdHJpbmc7XHJcbiAgY29uc3RydWN0b3IocHJpdmF0ZSBrZXlzUGlwZTogS2V5c1BpcGUpIHt9XHJcblxyXG4gIG5nT25Jbml0KCkge1xyXG4gICAgdGhpcy5vdHBGb3JtID0gbmV3IEZvcm1Hcm91cCh7fSk7XHJcbiAgICBmb3IgKGxldCBpbmRleCA9IDA7IGluZGV4IDwgdGhpcy5jb25maWcubGVuZ3RoOyBpbmRleCsrKSB7XHJcbiAgICAgIHRoaXMub3RwRm9ybS5hZGRDb250cm9sKHRoaXMuZ2V0Q29udHJvbE5hbWUoaW5kZXgpLCBuZXcgRm9ybUNvbnRyb2woKSk7XHJcbiAgICB9XHJcbiAgICB0aGlzLmlucHV0VHlwZSA9IHRoaXMuZ2V0SW5wdXRUeXBlKCk7XHJcbiAgICBcclxuICB9XHJcbiAgbmdBZnRlclZpZXdJbml0KCk6IHZvaWQge1xyXG4gICAgaWYgKCF0aGlzLmNvbmZpZy5kaXNhYmxlQXV0b0ZvY3VzKSB7XHJcbiAgICAgIGNvbnN0IGNvbnRhaW5lckl0ZW0gPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChgY18ke3RoaXMuY29tcG9uZW50S2V5fWApO1xyXG4gICAgICBpZiAoY29udGFpbmVySXRlbSkge1xyXG4gICAgICAgIGNvbnRhaW5lckl0ZW0uYWRkRXZlbnRMaXN0ZW5lcigncGFzdGUnLCAoZXZ0KSA9PiB0aGlzLmhhbmRsZVBhc3RlKGV2dCkpO1xyXG4gICAgICAgIGNvbnN0IGVsZTogYW55ID0gY29udGFpbmVySXRlbS5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKCdvdHAtaW5wdXQnKVswXTtcclxuICAgICAgICBpZiAoZWxlICYmIGVsZS5mb2N1cykge1xyXG4gICAgICAgICAgZWxlLmZvY3VzKCk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG4gIHByaXZhdGUgZ2V0Q29udHJvbE5hbWUoaWR4KSB7XHJcbiAgICByZXR1cm4gYGN0cmxfJHtpZHh9YDtcclxuICB9XHJcblxyXG4gIGlmTGVmdEFycm93KGV2ZW50KSB7XHJcbiAgICByZXR1cm4gdGhpcy5pZktleUNvZGUoZXZlbnQsIDM3KTtcclxuICB9XHJcblxyXG5cclxuICBpZlJpZ2h0QXJyb3coZXZlbnQpIHtcclxuICAgIHJldHVybiB0aGlzLmlmS2V5Q29kZShldmVudCwgMzkpO1xyXG4gIH1cclxuXHJcbiAgaWZCYWNrc3BhY2VPckRlbGV0ZShldmVudCkge1xyXG4gICAgcmV0dXJuIChcclxuICAgICAgZXZlbnQua2V5ID09PSAnQmFja3NwYWNlJyB8fFxyXG4gICAgICBldmVudC5rZXkgPT09ICdEZWxldGUnIHx8XHJcbiAgICAgIHRoaXMuaWZLZXlDb2RlKGV2ZW50LCA4KSB8fFxyXG4gICAgICB0aGlzLmlmS2V5Q29kZShldmVudCwgNDYpXHJcbiAgICApO1xyXG4gIH1cclxuXHJcbiAgaWZLZXlDb2RlKGV2ZW50LCB0YXJnZXRDb2RlKSB7XHJcbiAgICBjb25zdCBrZXkgPSBldmVudC5rZXlDb2RlIHx8IGV2ZW50LmNoYXJDb2RlO1xyXG4gICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOiB0cmlwbGUtZXF1YWxzXHJcbiAgICByZXR1cm4ga2V5ID09IHRhcmdldENvZGUgPyB0cnVlIDogZmFsc2U7XHJcbiAgfVxyXG4gIG9uS2V5RG93bigkZXZlbnQpIHtcclxuICAgIHZhciBpc1NwYWNlPXRoaXMuaWZLZXlDb2RlKCRldmVudCwzMilcclxuICAgIGlmIChpc1NwYWNlKSB7Ly8gcHJldmVudCBzcGFjZVxyXG4gICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgb25LZXlVcCgkZXZlbnQsIGlucHV0SWR4KSB7XHJcbiAgICBjb25zdCBuZXh0SW5wdXRJZCA9IHRoaXMuYXBwZW5kS2V5KGBvdHBfJHtpbnB1dElkeCArIDF9YCk7XHJcbiAgICBjb25zdCBwcmV2SW5wdXRJZCA9IHRoaXMuYXBwZW5kS2V5KGBvdHBfJHtpbnB1dElkeCAtIDF9YCk7XHJcbiAgICBpZiAodGhpcy5pZlJpZ2h0QXJyb3coJGV2ZW50KSkge1xyXG4gICAgICB0aGlzLnNldFNlbGVjdGVkKG5leHRJbnB1dElkKTtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG4gICAgaWYgKHRoaXMuaWZMZWZ0QXJyb3coJGV2ZW50KSkge1xyXG4gICAgICB0aGlzLnNldFNlbGVjdGVkKHByZXZJbnB1dElkKTtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG4gICAgY29uc3QgaXNCYWNrc3BhY2UgPSB0aGlzLmlmQmFja3NwYWNlT3JEZWxldGUoJGV2ZW50KTtcclxuICAgIGlmIChpc0JhY2tzcGFjZSAmJiAhJGV2ZW50LnRhcmdldC52YWx1ZSkge1xyXG4gICAgICB0aGlzLnNldFNlbGVjdGVkKHByZXZJbnB1dElkKTtcclxuICAgICAgdGhpcy5yZWJ1aWxkVmFsdWUoKTtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG4gICAgaWYgKCEkZXZlbnQudGFyZ2V0LnZhbHVlKSB7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuICAgIGlmICh0aGlzLmlmVmFsaWRFbnRyeSgkZXZlbnQpKSB7XHJcbiAgICAgIHRoaXMuc2V0U2VsZWN0ZWQobmV4dElucHV0SWQpO1xyXG4gICAgfVxyXG4gICAgdGhpcy5yZWJ1aWxkVmFsdWUoKTtcclxuICB9XHJcblxyXG4gIGFwcGVuZEtleShpZCkge1xyXG4gICAgcmV0dXJuIGAke2lkfV8ke3RoaXMuY29tcG9uZW50S2V5fWA7XHJcbiAgfVxyXG5cclxuICBzZXRTZWxlY3RlZChlbGVJZCkge1xyXG4gICAgdGhpcy5mb2N1c1RvKGVsZUlkKTtcclxuICAgIGNvbnN0IGVsZTogYW55ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoZWxlSWQpO1xyXG4gICAgaWYgKGVsZSAmJiBlbGUuc2V0U2VsZWN0aW9uUmFuZ2UpIHtcclxuICAgICAgc2V0VGltZW91dCgoKSA9PiB7XHJcbiAgICAgICAgZWxlLnNldFNlbGVjdGlvblJhbmdlKDAsIDEpO1xyXG4gICAgICB9LCAwKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIGlmVmFsaWRFbnRyeShldmVudCkge1xyXG4gICAgY29uc3QgaW5wID0gU3RyaW5nLmZyb21DaGFyQ29kZShldmVudC5rZXlDb2RlKTtcclxuICAgIGNvbnN0IGlzTW9iaWxlID0gL2lQaG9uZXxpUGFkfGlQb2R8QW5kcm9pZC9pLnRlc3QobmF2aWdhdG9yLnVzZXJBZ2VudCk7XHJcbiAgICByZXR1cm4gKFxyXG4gICAgICBpc01vYmlsZSB8fFxyXG4gICAgICAvW2EtekEtWjAtOS1fXS8udGVzdChpbnApIHx8XHJcbiAgICAgICh0aGlzLmNvbmZpZy5hbGxvd0tleUNvZGVzICYmXHJcbiAgICAgICAgdGhpcy5jb25maWcuYWxsb3dLZXlDb2Rlcy5pbmNsdWRlcyhldmVudC5rZXlDb2RlKSkgfHxcclxuICAgICAgKGV2ZW50LmtleUNvZGUgPj0gOTYgJiYgZXZlbnQua2V5Q29kZSA8PSAxMDUpXHJcbiAgICApO1xyXG4gIH1cclxuXHJcbiAgZm9jdXNUbyhlbGVJZCkge1xyXG4gICAgY29uc3QgZWxlOiBhbnkgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChlbGVJZCk7XHJcbiAgICBpZiAoZWxlKSB7XHJcbiAgICAgIGVsZS5mb2N1cygpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLy8gbWV0aG9kIHRvIHNldCBjb21wb25lbnQgdmFsdWVcclxuICBzZXRWYWx1ZSh2YWx1ZTogYW55KSB7XHJcbiAgICBpZiAodGhpcy5jb25maWcuYWxsb3dOdW1iZXJzT25seSAmJiBpc05hTih2YWx1ZSkpIHtcclxuICAgICAgICByZXR1cm47XHJcbiAgICB9XHJcbiAgICB0aGlzLm90cEZvcm0ucmVzZXQoKTtcclxuICAgICBpZiAoIXZhbHVlKSB7XHJcbiAgICAgICB0aGlzLnJlYnVpbGRWYWx1ZSgpO1xyXG4gICAgICAgcmV0dXJuO1xyXG4gICAgIH1cclxuICAgICB2YWx1ZSA9IHZhbHVlLnRvU3RyaW5nKCkucmVwbGFjZSgvXFxzL2csICcnKTsgLy8gcmVtb3ZlIHdoaXRlc3BhY2VcclxuICAgICBBcnJheS5mcm9tKHZhbHVlKS5mb3JFYWNoKChjLCBpZHgpID0+IHtcclxuICAgICAgICAgIGlmICh0aGlzLm90cEZvcm0uZ2V0KHRoaXMuZ2V0Q29udHJvbE5hbWUoaWR4KSkpIHtcclxuICAgICAgICAgICAgdGhpcy5vdHBGb3JtLmdldCh0aGlzLmdldENvbnRyb2xOYW1lKGlkeCkpLnNldFZhbHVlKGMpO1xyXG4gICAgICAgICAgfVxyXG4gICAgIH0pO1xyXG4gICAgIGlmICghdGhpcy5jb25maWcuZGlzYWJsZUF1dG9Gb2N1cykge1xyXG4gICAgICBjb25zdCBjb250YWluZXJJdGVtID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoYGNfJHt0aGlzLmNvbXBvbmVudEtleX1gKTtcclxuICAgICAgdmFyIGluZGV4T2ZFbGVtZW50VG9Gb2N1cyA9IHZhbHVlLmxlbmd0aCA8IHRoaXMuY29uZmlnLmxlbmd0aCA/IHZhbHVlLmxlbmd0aCA6ICh0aGlzLmNvbmZpZy5sZW5ndGggLSAxKTtcclxuICAgICAgbGV0IGVsZSA6IGFueSA9IGNvbnRhaW5lckl0ZW0uZ2V0RWxlbWVudHNCeUNsYXNzTmFtZSgnb3RwLWlucHV0JylbaW5kZXhPZkVsZW1lbnRUb0ZvY3VzXTtcclxuICAgICAgaWYgKGVsZSAmJiBlbGUuZm9jdXMpIHtcclxuICAgICAgICBlbGUuZm9jdXMoKTtcclxuICAgICAgfVxyXG4gICAgIH1cclxuICAgICB0aGlzLnJlYnVpbGRWYWx1ZSgpO1xyXG4gIH1cclxuXHJcblxyXG4gIHJlYnVpbGRWYWx1ZSgpIHtcclxuICAgIGxldCB2YWwgPSAnJztcclxuICAgIHRoaXMua2V5c1BpcGUudHJhbnNmb3JtKHRoaXMub3RwRm9ybS5jb250cm9scykuZm9yRWFjaChrID0+IHtcclxuICAgICAgaWYgKHRoaXMub3RwRm9ybS5jb250cm9sc1trXS52YWx1ZSkge1xyXG4gICAgICAgIHZhbCArPSB0aGlzLm90cEZvcm0uY29udHJvbHNba10udmFsdWU7XHJcbiAgICAgIH1cclxuICAgIH0pO1xyXG4gICAgdGhpcy5vbklucHV0Q2hhbmdlLmVtaXQodmFsKTtcclxuICB9XHJcbiAgZ2V0SW5wdXRUeXBlKCk6c3RyaW5ne1xyXG4gICAgcmV0dXJuIHRoaXMuY29uZmlnLmlzUGFzc3dvcmRJbnB1dCBcclxuICAgICAgPyAncGFzc3dvcmQnIFxyXG4gICAgICA6IHRoaXMuY29uZmlnLmFsbG93TnVtYmVyc09ubHkgXHJcbiAgICAgICAgPyAndGVsJ1xyXG4gICAgICAgIDogJ3RleHQnO1xyXG4gIH1cclxuICBoYW5kbGVQYXN0ZShlKSB7XHJcbiAgICAvLyBHZXQgcGFzdGVkIGRhdGEgdmlhIGNsaXBib2FyZCBBUElcclxuICAgIGxldCBjbGlwYm9hcmREYXRhID0gZS5jbGlwYm9hcmREYXRhIHx8IHdpbmRvd1snY2xpcGJvYXJkRGF0YSddO1xyXG4gICAgaWYoY2xpcGJvYXJkRGF0YSl7XHJcbiAgICAgdmFyIHBhc3RlZERhdGEgPWNsaXBib2FyZERhdGEuZ2V0RGF0YSgnVGV4dCcpO1xyXG4gICAgfVxyXG4gICAgLy8gU3RvcCBkYXRhIGFjdHVhbGx5IGJlaW5nIHBhc3RlZCBpbnRvIGRpdlxyXG4gICAgZS5zdG9wUHJvcGFnYXRpb24oKTtcclxuICAgIGUucHJldmVudERlZmF1bHQoKTtcclxuICAgIGlmICghcGFzdGVkRGF0YSkge1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcbiAgICB0aGlzLnNldFZhbHVlKHBhc3RlZERhdGEpO1xyXG4gIH1cclxufVxyXG4iXX0=