UNPKG

gentics-ui-core

Version:

This is the common core framework for the Gentics CMS and Mesh UI, and other Angular applications.

253 lines 30.6 kB
import { ChangeDetectorRef, Component, ElementRef, EventEmitter, forwardRef, HostListener, Input, Output, Renderer2, ViewChild } from '@angular/core'; import { NG_VALUE_ACCESSOR } from '@angular/forms'; import * as i0 from "@angular/core"; const GTX_INPUT_VALUE_ACCESSOR = { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => InputField), multi: true }; /** * E-mail validator regex from Angular 8 * @todo Implement with validators * @see https://github.com/angular/angular/blob/8.2.9/packages/forms/src/validators.ts#L60 */ const EMAIL_REGEXP = "^(?=.{1,254}$)(?=.{1,64}@)[-!#$%&'*+/0-9=?A-Z^_`a-z{|}~]+(\\.[-!#$%&'*+/0-9=?A-Z^_`a-z{|}~]+)*@[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?(\\.[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?)*$"; /** * Telephone number validator regex * @todo Implement with validators * @see https://stackoverflow.com/a/26516985 */ const TEL_REGEXP = "^([()\\- x+]*\d[()\\- x+]*){4,16}$"; /** * URL validator regex * @todo Implement with validators * @see https://stackoverflow.com/a/52017332 */ const URL_REGEXP = "(^|\\s)((https?:\\/\\/)?[\\w-]+(\\.[\\w-]+)+\\.?(:\\d+)?(\\/\\S*)?)"; const ACTIVE_CLASS = 'active'; /** * The InputField wraps the native `<input>` form element but should only be used for * text, number, password, tel, email or url types. Other types (date, range, file) should have dedicated components. * * * Note that the class is named `InputField` since `Input` is used by the Angular framework to denote * component inputs. * * ```html * <gtx-input label="Text Input Label"></gtx-input> * <gtx-input placeholder="Number Input Placeholder" * type="number" min="0" max="100" step="5"></gtx-input> * ``` */ export class InputField { constructor(renderer, changeDetector) { this.renderer = renderer; this.changeDetector = changeDetector; /** * Sets the input field to be auto-focused. Handled by `AutofocusDirective`. */ this.autofocus = false; /** * Sets the disabled state */ this.disabled = false; /** * A label for the input */ this.label = ''; /** * Sets the readonly state of the input */ this.readonly = false; /** * Sets the required state of the input */ this.required = false; /** * Can be "text", "number", "password", "tel", "email" or "url". */ this.type = 'text'; /** * Sets the value of the input. */ this.value = ''; /** * Fires when the input loses focus. */ this.blur = new EventEmitter(); /** * Fires when the input gains focus. */ this.focus = new EventEmitter(); /** * Fires whenever a char is entered into the field. */ this.change = new EventEmitter(); this.onChange = (newValue) => { }; this.onTouched = () => { }; } ngOnInit() { /** * Set default regex patterns for specific field types if not set */ if (!this.pattern) { switch (this.type) { case 'email': this.pattern = EMAIL_REGEXP; break; case 'tel': this.pattern = TEL_REGEXP; break; case 'url': this.pattern = URL_REGEXP; break; default: } } } /** * The Materialize input includes a dynamic label that changes position depending on the state of the input. * When the label has the "active" class, it moves above the input, otherwise it resides inside the input * itself. * * The Materialize "forms.js" script normally takes care of adding/removing the active class on page load, * but this does not work in a SPA setting where new views with inputs can be created without a page load * event to trigger the `Materialize.updateTextFields()` method. Therefore we need to handle it ourselves * when the input component is created. */ ngAfterViewInit() { const input = this.inputElement.nativeElement; const label = this.labelElement.nativeElement; if (input && label) { if (String(this.value).length > 0 || this.placeholder) { this.renderer.addClass(label, ACTIVE_CLASS); } else { this.renderer.removeClass(label, ACTIVE_CLASS); } } } ngOnChanges(changes) { const valueChange = changes['value']; if (valueChange) { this.writeValue(valueChange.currentValue); } } onKeyDown(event) { if (this.type === 'number') { const keyboardEvent = event; if ((keyboardEvent.key === '-' && event.target.value) || keyboardEvent.key === '+') { keyboardEvent.preventDefault(); } else if (keyboardEvent.key === '-' && !event.target.value) { event.target.value = '-'; } } } onBlur(e) { e.stopPropagation(); const target = e.target; this.blur.emit(this.normalizeValue(target.value)); this.onTouched(); } onFocus(e) { const target = e.target; this.focus.emit(this.normalizeValue(target.value)); } onInput(e) { const target = e.target; this.updateValue(target); const value = this.currentValue = this.normalizeValue(target.value); this.onChange(value); this.change.emit(value); } writeValue(valueToWrite) { const value = this.normalizeValue(valueToWrite); if (value !== this.currentValue) { this.renderer.setProperty(this.inputElement.nativeElement, 'value', this.currentValue = value); } } // ValueAccessor members registerOnChange(fn) { this.onChange = fn; } registerOnTouched(fn) { this.onTouched = fn; } setDisabledState(disabled) { this.disabled = disabled; this.changeDetector.markForCheck(); } normalizeValue(val) { if (this.type === 'number') { return val == null ? 0 : Number(val); } else { return val == null ? '' : String(val); } } updateValue(target) { if (this.type === 'number') { if (this.max && Number(target.value) > this.max) { target.value = String(this.max); } else if (this.min && Number(target.value) < this.min) { target.value = String(this.min); } } } } /** @nocollapse */ InputField.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.8", ngImport: i0, type: InputField, deps: [{ token: i0.Renderer2 }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); /** @nocollapse */ InputField.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.8", type: InputField, selector: "gtx-input", inputs: { autocomplete: "autocomplete", autofocus: "autofocus", disabled: "disabled", id: "id", label: "label", max: "max", min: "min", maxlength: "maxlength", name: "name", pattern: "pattern", placeholder: "placeholder", readonly: "readonly", required: "required", step: "step", type: "type", value: "value" }, outputs: { blur: "blur", focus: "focus", change: "change" }, host: { listeners: { "keydown": "onKeyDown($event)" } }, providers: [GTX_INPUT_VALUE_ACCESSOR], viewQueries: [{ propertyName: "inputElement", first: true, predicate: ["inputElement"], descendants: true, static: true }, { propertyName: "labelElement", first: true, predicate: ["labelElement"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: "<input\n [attr.autocomplete]=\"autocomplete || null\"\n [attr.id]=\"id\"\n [attr.max]=\"max\"\n [attr.maxlength]=\"maxlength\"\n [attr.min]=\"min\"\n [attr.name]=\"name\"\n [attr.pattern]=\"pattern\"\n [attr.placeholder]=\"placeholder\"\n [attr.step]=\"step\"\n\n [disabled]=\"disabled\"\n [readonly]=\"readonly\"\n [required]=\"required\"\n [type]=\"type\"\n\n (blur)=\"onBlur($event)\"\n (change)=\"onBlur($event)\"\n (focus)=\"onFocus($event)\"\n (input)=\"onInput($event)\"\n\n #inputElement\n><label [attr.for]=\"id\" (click)=\"inputElement.focus()\" #labelElement>{{ label }}</label>\n" }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.8", ngImport: i0, type: InputField, decorators: [{ type: Component, args: [{ selector: 'gtx-input', providers: [GTX_INPUT_VALUE_ACCESSOR], template: "<input\n [attr.autocomplete]=\"autocomplete || null\"\n [attr.id]=\"id\"\n [attr.max]=\"max\"\n [attr.maxlength]=\"maxlength\"\n [attr.min]=\"min\"\n [attr.name]=\"name\"\n [attr.pattern]=\"pattern\"\n [attr.placeholder]=\"placeholder\"\n [attr.step]=\"step\"\n\n [disabled]=\"disabled\"\n [readonly]=\"readonly\"\n [required]=\"required\"\n [type]=\"type\"\n\n (blur)=\"onBlur($event)\"\n (change)=\"onBlur($event)\"\n (focus)=\"onFocus($event)\"\n (input)=\"onInput($event)\"\n\n #inputElement\n><label [attr.for]=\"id\" (click)=\"inputElement.focus()\" #labelElement>{{ label }}</label>\n" }] }], ctorParameters: function () { return [{ type: i0.Renderer2 }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { autocomplete: [{ type: Input }], autofocus: [{ type: Input }], disabled: [{ type: Input }], id: [{ type: Input }], label: [{ type: Input }], max: [{ type: Input }], min: [{ type: Input }], maxlength: [{ type: Input }], name: [{ type: Input }], pattern: [{ type: Input }], placeholder: [{ type: Input }], readonly: [{ type: Input }], required: [{ type: Input }], step: [{ type: Input }], type: [{ type: Input }], value: [{ type: Input }], blur: [{ type: Output }], focus: [{ type: Output }], change: [{ type: Output }], inputElement: [{ type: ViewChild, args: ['inputElement', { static: true }] }], labelElement: [{ type: ViewChild, args: ['labelElement', { static: true }] }], onKeyDown: [{ type: HostListener, args: ['keydown', ['$event']] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5wdXQuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL2NvbXBvbmVudHMvaW5wdXQvaW5wdXQuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vc3JjL2NvbXBvbmVudHMvaW5wdXQvaW5wdXQudHBsLmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUVILGlCQUFpQixFQUNqQixTQUFTLEVBQ1QsVUFBVSxFQUNWLFlBQVksRUFDWixVQUFVLEVBQ1YsWUFBWSxFQUNaLEtBQUssRUFHTCxNQUFNLEVBQ04sU0FBUyxFQUVULFNBQVMsRUFDWixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQXVCLGlCQUFpQixFQUFDLE1BQU0sZ0JBQWdCLENBQUM7O0FBRXZFLE1BQU0sd0JBQXdCLEdBQUc7SUFDN0IsT0FBTyxFQUFFLGlCQUFpQjtJQUMxQixXQUFXLEVBQUUsVUFBVSxDQUFDLEdBQUcsRUFBRSxDQUFDLFVBQVUsQ0FBQztJQUN6QyxLQUFLLEVBQUUsSUFBSTtDQUNkLENBQUM7QUFFRjs7OztHQUlHO0FBQ0gsTUFBTSxZQUFZLEdBQ2QsOExBQThMLENBQUM7QUFFbk07Ozs7R0FJRztBQUNILE1BQU0sVUFBVSxHQUFHLG9DQUFvQyxDQUFDO0FBRXhEOzs7O0dBSUc7QUFDSCxNQUFNLFVBQVUsR0FBRyxxRUFBcUUsQ0FBQztBQUV6RixNQUFNLFlBQVksR0FBRyxRQUFRLENBQUM7QUFFOUI7Ozs7Ozs7Ozs7Ozs7R0FhRztBQU1ILE1BQU0sT0FBTyxVQUFVO0lBb0duQixZQUFvQixRQUFtQixFQUNuQixjQUFpQztRQURqQyxhQUFRLEdBQVIsUUFBUSxDQUFXO1FBQ25CLG1CQUFjLEdBQWQsY0FBYyxDQUFtQjtRQWhHckQ7O1dBRUc7UUFDTSxjQUFTLEdBQVksS0FBSyxDQUFDO1FBRXBDOztXQUVHO1FBQ00sYUFBUSxHQUFZLEtBQUssQ0FBQztRQU9uQzs7V0FFRztRQUNNLFVB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Qyx3QkFBd0IsQ0FBQztnSUFNNUIsWUFBWTtzQkFBcEIsS0FBSztnQkFJRyxTQUFTO3NCQUFqQixLQUFLO2dCQUtHLFFBQVE7c0JBQWhCLEtBQUs7Z0JBS0csRUFBRTtzQkFBVixLQUFLO2dCQUtHLEtBQUs7c0JBQWIsS0FBSztnQkFLRyxHQUFHO3NCQUFYLEtBQUs7Z0JBS0csR0FBRztzQkFBWCxLQUFLO2dCQUtHLFNBQVM7c0JBQWpCLEtBQUs7Z0JBS0csSUFBSTtzQkFBWixLQUFLO2dCQUtHLE9BQU87c0JBQWYsS0FBSztnQkFLRyxXQUFXO3NCQUFuQixLQUFLO2dCQUtHLFFBQVE7c0JBQWhCLEtBQUs7Z0JBS0csUUFBUTtzQkFBaEIsS0FBSztnQkFLRyxJQUFJO3NCQUFaLEtBQUs7Z0JBS0csSUFBSTtzQkFBWixLQUFLO2dCQUtHLEtBQUs7c0JBQWIsS0FBSztnQkFLSSxJQUFJO3NCQUFiLE1BQU07Z0JBS0csS0FBSztzQkFBZCxNQUFNO2dCQUtHLE1BQU07c0JBQWYsTUFBTTtnQkFFOEMsWUFBWTtzQkFBaEUsU0FBUzt1QkFBQyxjQUFjLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFO2dCQUNVLFlBQVk7c0JBQWhFLFNBQVM7dUJBQUMsY0FBYyxFQUFFLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRTtnQkEyRHBDLFNBQVM7c0JBRGYsWUFBWTt1QkFBQyxTQUFTLEVBQUUsQ0FBQyxRQUFRLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICAgIEFmdGVyVmlld0luaXQsXG4gICAgQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gICAgQ29tcG9uZW50LFxuICAgIEVsZW1lbnRSZWYsXG4gICAgRXZlbnRFbWl0dGVyLFxuICAgIGZvcndhcmRSZWYsXG4gICAgSG9zdExpc3RlbmVyLFxuICAgIElucHV0LFxuICAgIE9uQ2hhbmdlcyxcbiAgICBPbkluaXQsXG4gICAgT3V0cHV0LFxuICAgIFJlbmRlcmVyMixcbiAgICBTaW1wbGVDaGFuZ2VzLFxuICAgIFZpZXdDaGlsZFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7Q29udHJvbFZhbHVlQWNjZXNzb3IsIE5HX1ZBTFVFX0FDQ0VTU09SfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5cbmNvbnN0IEdUWF9JTlBVVF9WQUxVRV9BQ0NFU1NPUiA9IHtcbiAgICBwcm92aWRlOiBOR19WQUxVRV9BQ0NFU1NPUixcbiAgICB1c2VFeGlzdGluZzogZm9yd2FyZFJlZigoKSA9PiBJbnB1dEZpZWxkKSxcbiAgICBtdWx0aTogdHJ1ZVxufTtcblxuLyoqXG4gKiBFLW1haWwgdmFsaWRhdG9yIHJlZ2V4IGZyb20gQW5ndWxhciA4XG4gKiBAdG9kbyBJbXBsZW1lbnQgd2l0aCB2YWxpZGF0b3JzXG4gKiBAc2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9hbmd1bGFyL2FuZ3VsYXIvYmxvYi84LjIuOS9wYWNrYWdlcy9mb3Jtcy9zcmMvdmFsaWRhdG9ycy50cyNMNjBcbiAqL1xuY29uc3QgRU1BSUxfUkVHRVhQID1cbiAgICBcIl4oPz0uezEsMjU0fSQpKD89LnsxLDY0fUApWy0hIyQlJicqKy8wLTk9P0EtWl5fYGEtent8fX5dKyhcXFxcLlstISMkJSYnKisvMC05PT9BLVpeX2BhLXp7fH1+XSspKkBbQS1aYS16MC05XShbQS1aYS16MC05LV17MCw2MX1bQS1aYS16MC05XSk/KFxcXFwuW0EtWmEtejAtOV0oW0EtWmEtejAtOS1dezAsNjF9W0EtWmEtejAtOV0pPykqJFwiO1xuXG4vKipcbiAqIFRlbGVwaG9uZSBudW1iZXIgdmFsaWRhdG9yIHJlZ2V4XG4gKiBAdG9kbyBJbXBsZW1lbnQgd2l0aCB2YWxpZGF0b3JzXG4gKiBAc2VlIGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vYS8yNjUxNjk4NVxuICovXG5jb25zdCBURUxfUkVHRVhQID0gXCJeKFsoKVxcXFwtIHgrXSpcXGRbKClcXFxcLSB4K10qKXs0LDE2fSRcIjtcblxuLyoqXG4gKiBVUkwgdmFsaWRhdG9yIHJlZ2V4XG4gKiBAdG9kbyBJbXBsZW1lbnQgd2l0aCB2YWxpZGF0b3JzXG4gKiBAc2VlIGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vYS81MjAxNzMzMlxuICovXG5jb25zdCBVUkxfUkVHRVhQID0gXCIoXnxcXFxccykoKGh0dHBzPzpcXFxcL1xcXFwvKT9bXFxcXHctXSsoXFxcXC5bXFxcXHctXSspK1xcXFwuPyg6XFxcXGQrKT8oXFxcXC9cXFxcUyopPylcIjtcblxuY29uc3QgQUNUSVZFX0NMQVNTID0gJ2FjdGl2ZSc7XG5cbi8qKlxuICogVGhlIElucHV0RmllbGQgd3JhcHMgdGhlIG5hdGl2ZSBgPGlucHV0PmAgZm9ybSBlbGVtZW50IGJ1dCBzaG91bGQgb25seSBiZSB1c2VkIGZvclxuICogdGV4dCwgbnVtYmVyLCBwYXNzd29yZCwgdGVsLCBlbWFpbCBvciB1cmwgdHlwZXMuIE90aGVyIHR5cGVzIChkYXRlLCByYW5nZSwgZmlsZSkgc2hvdWxkIGhhdmUgZGVkaWNhdGVkIGNvbXBvbmVudHMuXG4gKlxuICpcbiAqIE5vdGUgdGhhdCB0aGUgY2xhc3MgaXMgbmFtZWQgYElucHV0RmllbGRgIHNpbmNlIGBJbnB1dGAgaXMgdXNlZCBieSB0aGUgQW5ndWxhciBmcmFtZXdvcmsgdG8gZGVub3RlXG4gKiBjb21wb25lbnQgaW5wdXRzLlxuICpcbiAqIGBgYGh0bWxcbiAqIDxndHgtaW5wdXQgbGFiZWw9XCJUZXh0IElucHV0IExhYmVsXCI+PC9ndHgtaW5wdXQ+XG4gKiA8Z3R4LWlucHV0IHBsYWNlaG9sZGVyPVwiTnVtYmVyIElucHV0IFBsYWNlaG9sZGVyXCJcbiAqICAgICAgICAgICAgdHlwZT1cIm51bWJlclwiIG1pbj1cIjBcIiBtYXg9XCIxMDBcIiBzdGVwPVwiNVwiPjwvZ3R4LWlucHV0PlxuICogYGBgXG4gKi9cbkBDb21wb25lbnQoe1xuICAgIHNlbGVjdG9yOiAnZ3R4LWlucHV0JyxcbiAgICB0ZW1wbGF0ZVVybDogJy4vaW5wdXQudHBsLmh0bWwnLFxuICAgIHByb3ZpZGVyczogW0dUWF9JTlBVVF9WQUxVRV9BQ0NFU1NPUl1cbn0pXG5leHBvcnQgY2xhc3MgSW5wdXRGaWVsZCBpbXBsZW1lbnRzIEFmdGVyVmlld0luaXQsIENvbnRyb2xWYWx1ZUFjY2Vzc29yLCBPbkluaXQsIE9uQ2hhbmdlcyB7XG4gICAgLyoqXG4gICAgICogU2V0cyBhdXRvY29tcGxldGUgYXR0cmlidXRlIG9uIHRoZSBpbnB1dCBmaWVsZFxuICAgICAqL1xuICAgIEBJbnB1dCgpIGF1dG9jb21wbGV0ZTogc3RyaW5nO1xuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIGlucHV0IGZpZWxkIHRvIGJlIGF1dG8tZm9jdXNlZC4gSGFuZGxlZCBieSBgQXV0b2ZvY3VzRGlyZWN0aXZlYC5cbiAgICAgKi9cbiAgICBASW5wdXQoKSBhdXRvZm9jdXM6IGJvb2xlYW4gPSBmYWxzZTtcblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIGRpc2FibGVkIHN0YXRlXG4gICAgICovXG4gICAgQElucHV0KCkgZGlzYWJsZWQ6IGJvb2xlYW4gPSBmYWxzZTtcblxuICAgIC8qKlxuICAgICAqIElucHV0IGZpZWxkIGlkXG4gICAgICovXG4gICAgQElucHV0KCkgaWQ6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEEgbGFiZWwgZm9yIHRoZSBpbnB1dFxuICAgICAqL1xuICAgIEBJbnB1dCgpIGxhYmVsOiBzdHJpbmcgPSAnJztcblxuICAgIC8qKlxuICAgICAqIE1heCBhbGxvd2VkIHZhbHVlIChhcHBsaWVzIHdoZW4gdHlwZSA9IFwibnVtYmVyXCIpXG4gICAgICovXG4gICAgQElucHV0KCkgbWF4OiBudW1iZXI7XG5cbiAgICAvKipcbiAgICAgKiBNaW4gYWxsb3dlZCB2YWx1ZSAoYXBwbGllcyB3aGVuIHR5cGUgPSBcIm51bWJlclwiKVxuICAgICAqL1xuICAgIEBJbnB1dCgpIG1pbjogbnVtYmVyO1xuXG4gICAgLyoqXG4gICAgICogTWF4IGFsbG93ZWQgbGVuZ3RoIGluIGNoYXJhY3RlcnNcbiAgICAgKi9cbiAgICBASW5wdXQoKSBtYXhsZW5ndGg6IG51bWJlcjtcblxuICAgIC8qKlxuICAgICAqIElucHV0IGZpZWxkIG5hbWVcbiAgICAgKi9cbiAgICBASW5wdXQoKSBuYW1lOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBSZWdleCBwYXR0ZXJuIGZvciBjb21wbGV4IHZhbGlkYXRpb25cbiAgICAgKi9cbiAgICBASW5wdXQoKSBwYXR0ZXJuOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBQbGFjZWhvbGRlciB0ZXh0IHRvIGRpc3BsYXkgd2hlbiB0aGUgZmllbGQgaXMgZW1wdHlcbiAgICAgKi9cbiAgICBASW5wdXQoKSBwbGFjZWhvbGRlcjogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgcmVhZG9ubHkgc3RhdGUgb2YgdGhlIGlucHV0XG4gICAgICovXG4gICAgQElucHV0KCkgcmVhZG9ubHk6IGJvb2xlYW4gPSBmYWxzZTtcblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIHJlcXVpcmVkIHN0YXRlIG9mIHRoZSBpbnB1dFxuICAgICAqL1xuICAgIEBJbnB1dCgpIHJlcXVpcmVkOiBib29sZWFuID0gZmFsc2U7XG5cbiAgICAvKipcbiAgICAgKiBJbmNyZW1lbnQgc3RlcCAoYXBwbGllcyB3aGVuIHR5cGUgPSBcIm51bWJlclwiKVxuICAgICAqL1xuICAgIEBJbnB1dCgpIHN0ZXA6IG51bWJlcjtcblxuICAgIC8qKlxuICAgICAqIENhbiBiZSBcInRleHRcIiwgXCJudW1iZXJcIiwgXCJwYXNzd29yZFwiLCBcInRlbFwiLCBcImVtYWlsXCIgb3IgXCJ1cmxcIi5cbiAgICAgKi9cbiAgICBASW5wdXQoKSB0eXBlOiAndGV4dCcgfCAnbnVtYmVyJyB8ICdwYXNzd29yZCcgfCAndGVsJyB8ICdlbWFpbCcgfCAndXJsJyA9ICd0ZXh0JztcblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIHZhbHVlIG9mIHRoZSBpbnB1dC5cbiAgICAgKi9cbiAgICBASW5wdXQoKSB2YWx1ZTogc3RyaW5nfG51bWJlciA9ICcnO1xuXG4gICAgLyoqXG4gICAgICogRmlyZXMgd2hlbiB0aGUgaW5wdXQgbG9zZXMgZm9jdXMuXG4gICAgICovXG4gICAgQE91dHB1dCgpIGJsdXIgPSBuZXcgRXZlbnRFbWl0dGVyPHN0cmluZ3xudW1iZXI+KCk7XG5cbiAgICAvKipcbiAgICAgKiBGaXJlcyB3aGVuIHRoZSBpbnB1dCBnYWlucyBmb2N1cy5cbiAgICAgKi9cbiAgICBAT3V0cHV0KCkgZm9jdXMgPSBuZXcgRXZlbnRFbWl0dGVyPHN0cmluZ3xudW1iZXI+KCk7XG5cbiAgICAvKipcbiAgICAgKiBGaXJlcyB3aGVuZXZlciBhIGNoYXIgaXMgZW50ZXJlZCBpbnRvIHRoZSBmaWVsZC5cbiAgICAgKi9cbiAgICBAT3V0cHV0KCkgY2hhbmdlID0gbmV3IEV2ZW50RW1pdHRlcjxzdHJpbmd8bnVtYmVyPigpO1xuXG4gICAgQFZpZXdDaGlsZCgnaW5wdXRFbGVtZW50JywgeyBzdGF0aWM6IHRydWUgfSkgcHJpdmF0ZSBpbnB1dEVsZW1lbnQ6IEVsZW1lbnRSZWY7XG4gICAgQFZpZXdDaGlsZCgnbGFiZWxFbGVtZW50JywgeyBzdGF0aWM6IHRydWUgfSkgcHJpdmF0ZSBsYWJlbEVsZW1lbnQ6IEVsZW1lbnRSZWY7XG5cbiAgICBwcml2YXRlIGN1cnJlbnRWYWx1ZTogc3RyaW5nIHwgbnVtYmVyO1xuXG4gICAgY29uc3RydWN0b3IocHJpdmF0ZSByZW5kZXJlcjogUmVuZGVyZXIyLFxuICAgICAgICAgICAgICAgIHByaXZhdGUgY2hhbmdlRGV0ZWN0b3I6IENoYW5nZURldGVjdG9yUmVmKSB7IH1cblxuXG4gICAgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBTZXQgZGVmYXVsdCByZWdleCBwYXR0ZXJucyBmb3Igc3BlY2lmaWMgZmllbGQgdHlwZXMgaWYgbm90IHNldFxuICAgICAgICAgKi9cbiAgICAgICAgaWYgKCF0aGlzLnBhdHRlcm4pIHtcbiAgICAgICAgICAgIHN3aXRjaCAodGhpcy50eXBlKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAnZW1haWwnOlxuICAgICAgICAgICAgICAgICAgICB0aGlzLnBhdHRlcm4gPSBFTUFJTF9SRUdFWFA7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgJ3RlbCc6XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucGF0dGVybiA9IFRFTF9SRUdFWFA7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgJ3VybCc6XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucGF0dGVybiA9IFVSTF9SRUdFWFA7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgTWF0ZXJpYWxpemUgaW5wdXQgaW5jbHVkZXMgYSBkeW5hbWljIGxhYmVsIHRoYXQgY2hhbmdlcyBwb3NpdGlvbiBkZXBlbmRpbmcgb24gdGhlIHN0YXRlIG9mIHRoZSBpbnB1dC5cbiAgICAgKiBXaGVuIHRoZSBsYWJlbCBoYXMgdGhlIFwiYWN0aXZlXCIgY2xhc3MsIGl0IG1vdmVzIGFib3ZlIHRoZSBpbnB1dCwgb3RoZXJ3aXNlIGl0IHJlc2lkZXMgaW5zaWRlIHRoZSBpbnB1dFxuICAgICAqIGl0c2VsZi5cbiAgICAgKlxuICAgICAqIFRoZSBNYXRlcmlhbGl6ZSBcImZvcm1zLmpzXCIgc2NyaXB0IG5vcm1hbGx5IHRha2VzIGNhcmUgb2YgYWRkaW5nL3JlbW92aW5nIHRoZSBhY3RpdmUgY2xhc3Mgb24gcGFnZSBsb2FkLFxuICAgICAqIGJ1dCB0aGlzIGRvZXMgbm90IHdvcmsgaW4gYSBTUEEgc2V0dGluZyB3aGVyZSBuZXcgdmlld3Mgd2l0aCBpbnB1dHMgY2FuIGJlIGNyZWF0ZWQgd2l0aG91dCBhIHBhZ2UgbG9hZFxuICAgICAqIGV2ZW50IHRvIHRyaWdnZXIgdGhlIGBNYXRlcmlhbGl6ZS51cGRhdGVUZXh0RmllbGRzKClgIG1ldGhvZC4gVGhlcmVmb3JlIHdlIG5lZWQgdG8gaGFuZGxlIGl0IG91cnNlbHZlc1xuICAgICAqIHdoZW4gdGhlIGlucHV0IGNvbXBvbmVudCBpcyBjcmVhdGVkLlxuICAgICAqL1xuICAgIG5nQWZ0ZXJWaWV3SW5pdCgpOiB2b2lkIHtcbiAgICAgICAgY29uc3QgaW5wdXQ6IEhUTUxJbnB1dEVsZW1lbnQgPSB0aGlzLmlucHV0RWxlbWVudC5uYXRpdmVFbGVtZW50O1xuICAgICAgICBjb25zdCBsYWJlbDogSFRNTExhYmVsRWxlbWVudCA9IHRoaXMubGFiZWxFbGVtZW50Lm5hdGl2ZUVsZW1lbnQ7XG5cbiAgICAgICAgaWYgKGlucHV0ICYmIGxhYmVsKSB7XG4gICAgICAgICAgICBpZiAoU3RyaW5nKHRoaXMudmFsdWUpLmxlbmd0aCA+IDAgfHwgdGhpcy5wbGFjZWhvbGRlcikge1xuICAgICAgICAgICAgICAgIHRoaXMucmVuZGVyZXIuYWRkQ2xhc3MobGFiZWwsIEFDVElWRV9DTEFTUyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMucmVuZGVyZXIucmVtb3ZlQ2xhc3MobGFiZWwsIEFDVElWRV9DTEFTUyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IHZhbHVlQ2hhbmdlID0gY2hhbmdlc1sndmFsdWUnXTtcbiAgICAgICAgaWYgKHZhbHVlQ2hhbmdlKSB7XG4gICAgICAgICAgICB0aGlzLndyaXRlVmFsdWUodmFsdWVDaGFuZ2UuY3VycmVudFZhbHVlKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIEBIb3N0TGlzdGVuZXIoJ2tleWRvd24nLCBbJyRldmVudCddKVxuICAgIHB1YmxpYyBvbktleURvd24oZXZlbnQpIHtcbiAgICAgICAgaWYgKHRoaXMudHlwZSA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICAgIGNvbnN0IGtleWJvYXJkRXZlbnQgPSBldmVudCBhcyBLZXlib2FyZEV2ZW50O1xuICAgICAgICAgICAgaWYgKChrZXlib2FyZEV2ZW50LmtleSA9PT0gJy0nICYmIGV2ZW50LnRhcmdldC52YWx1ZSkgfHwga2V5Ym9hcmRFdmVudC5rZXkgPT09ICcrJykge1xuICAgICAgICAgICAgICAgIGtleWJvYXJkRXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoa2V5Ym9hcmRFdmVudC5rZXkgPT09ICctJyAmJiAhZXZlbnQudGFyZ2V0LnZhbHVlKSB7XG4gICAgICAgICAgICAgICAgZXZlbnQudGFyZ2V0LnZhbHVlID0gJy0nO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgb25CbHVyKGU6IEV2ZW50KTogdm9pZCB7XG4gICAgICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICAgIGNvbnN0IHRhcmdldCA9IGUudGFyZ2V0IGFzIEhUTUxJbnB1dEVsZW1lbnQ7XG4gICAgICAgIHRoaXMuYmx1ci5lbWl0KHRoaXMubm9ybWFsaXplVmFsdWUodGFyZ2V0LnZhbHVlKSk7XG4gICAgICAgIHRoaXMub25Ub3VjaGVkKCk7XG4gICAgfVxuXG4gICAgb25Gb2N1cyhlOiBFdmVudCk6IHZvaWQge1xuICAgICAgICBjb25zdCB0YXJnZXQgPSBlLnRhcmdldCBhcyBIVE1MSW5wdXRFbGVtZW50O1xuICAgICAgICB0aGlzLmZvY3VzLmVtaXQodGhpcy5ub3JtYWxpemVWYWx1ZSh0YXJnZXQudmFsdWUpKTtcbiAgICB9XG5cbiAgICBvbklucHV0KGU6IEV2ZW50KTogdm9pZCB7XG4gICAgICAgIGNvbnN0IHRhcmdldCA9IGUudGFyZ2V0IGFzIEhUTUxJbnB1dEVsZW1lbnQ7XG4gICAgICAgIHRoaXMudXBkYXRlVmFsdWUodGFyZ2V0KTtcbiAgICAgICAgY29uc3QgdmFsdWUgPSB0aGlzLmN1cnJlbnRWYWx1ZSA9IHRoaXMubm9ybWFsaXplVmFsdWUodGFyZ2V0LnZhbHVlKTtcbiAgICAgICAgdGhpcy5vbkNoYW5nZSh2YWx1ZSk7XG4gICAgICAgIHRoaXMuY2hhbmdlLmVtaXQodmFsdWUpO1xuICAgIH1cblxuICAgIHdyaXRlVmFsdWUodmFsdWVUb1dyaXRlOiBhbnkpOiB2b2lkIHtcbiAgICAgICAgY29uc3QgdmFsdWUgPSB0aGlzLm5vcm1hbGl6ZVZhbHVlKHZhbHVlVG9Xcml0ZSk7XG4gICAgICAgIGlmICh2YWx1ZSAhPT0gdGhpcy5jdXJyZW50VmFsdWUpIHtcbiAgICAgICAgICAgIHRoaXMucmVuZGVyZXIuc2V0UHJvcGVydHkodGhpcy5pbnB1dEVsZW1lbnQubmF0aXZlRWxlbWVudCwgJ3ZhbHVlJywgdGhpcy5jdXJyZW50VmFsdWUgPSB2YWx1ZSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBWYWx1ZUFjY2Vzc29yIG1lbWJlcnNcbiAgICByZWdpc3Rlck9uQ2hhbmdlKGZuOiAobmV3VmFsdWU6IHN0cmluZyB8IG51bWJlcikgPT4gdm9pZCk6IHZvaWQge1xuICAgICAgICB0aGlzLm9uQ2hhbmdlID0gZm47XG4gICAgfVxuICAgIHJlZ2lzdGVyT25Ub3VjaGVkKGZuOiAoKSA9PiB2b2lkKTogdm9pZCB7XG4gICAgICAgIHRoaXMub25Ub3VjaGVkID0gZm47XG4gICAgfVxuICAgIHNldERpc2FibGVkU3RhdGUoZGlzYWJsZWQ6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5kaXNhYmxlZCA9IGRpc2FibGVkO1xuICAgICAgICB0aGlzLmNoYW5nZURldGVjdG9yLm1hcmtGb3JDaGVjaygpO1xuICAgIH1cbiAgICBwcml2YXRlIG9uQ2hhbmdlID0gKG5ld1ZhbHVlOiBzdHJpbmcgfCBudW1iZXIpOiB2b2lkID0+IHt9O1xuICAgIHByaXZhdGUgb25Ub3VjaGVkID0gKCk6IHZvaWQgPT4ge307XG5cbiAgICBwcml2YXRlIG5vcm1hbGl6ZVZhbHVlKHZhbDogYW55KTogc3RyaW5nfG51bWJlciB7XG4gICAgICAgIGlmICh0aGlzLnR5cGUgPT09ICdudW1iZXInKSB7XG4gICAgICAgICAgICByZXR1cm4gdmFsID09IG51bGwgPyAwIDogTnVtYmVyKHZhbCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gdmFsID09IG51bGwgPyAnJyA6IFN0cmluZyh2YWwpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSB1cGRhdGVWYWx1ZSh0YXJnZXQ6IEhUTUxJbnB1dEVsZW1lbnQpOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMudHlwZSA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLm1heCAmJiBOdW1iZXIodGFyZ2V0LnZhbHVlKSA+IHRoaXMubWF4KSB7XG4gICAgICAgICAgICAgICAgdGFyZ2V0LnZhbHVlID0gU3RyaW5nKHRoaXMubWF4KTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAodGhpcy5taW4gJiYgTnVtYmVyKHRhcmdldC52YWx1ZSkgPCB0aGlzLm1pbikge1xuICAgICAgICAgICAgICAgIHRhcmdldC52YWx1ZSA9IFN0cmluZyh0aGlzLm1pbik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG59XG4iLCI8aW5wdXRcbiAgICBbYXR0ci5hdXRvY29tcGxldGVdPVwiYXV0b2NvbXBsZXRlIHx8IG51bGxcIlxuICAgIFthdHRyLmlkXT1cImlkXCJcbiAgICBbYXR0ci5tYXhdPVwibWF4XCJcbiAgICBbYXR0ci5tYXhsZW5ndGhdPVwibWF4bGVuZ3RoXCJcbiAgICBbYXR0ci5taW5dPVwibWluXCJcbiAgICBbYXR0ci5uYW1lXT1cIm5hbWVcIlxuICAgIFthdHRyLnBhdHRlcm5dPVwicGF0dGVyblwiXG4gICAgW2F0dHIucGxhY2Vob2xkZXJdPVwicGxhY2Vob2xkZXJcIlxuICAgIFthdHRyLnN0ZXBdPVwic3RlcFwiXG5cbiAgICBbZGlzYWJsZWRdPVwiZGlzYWJsZWRcIlxuICAgIFtyZWFkb25seV09XCJyZWFkb25seVwiXG4gICAgW3JlcXVpcmVkXT1cInJlcXVpcmVkXCJcbiAgICBbdHlwZV09XCJ0eXBlXCJcblxuICAgIChibHVyKT1cIm9uQmx1cigkZXZlbnQpXCJcbiAgICAoY2hhbmdlKT1cIm9uQmx1cigkZXZlbnQpXCJcbiAgICAoZm9jdXMpPVwib25Gb2N1cygkZXZlbnQpXCJcbiAgICAoaW5wdXQpPVwib25JbnB1dCgkZXZlbnQpXCJcblxuICAgICNpbnB1dEVsZW1lbnRcbj48bGFiZWwgW2F0dHIuZm9yXT1cImlkXCIgKGNsaWNrKT1cImlucHV0RWxlbWVudC5mb2N1cygpXCIgI2xhYmVsRWxlbWVudD57eyBsYWJlbCB9fTwvbGFiZWw+XG4iXX0=