ngx-bootstrap
Version:
Native Angular Bootstrap Components
736 lines • 65.6 kB
JavaScript
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/* tslint:disable:max-file-line-count */
import { ChangeDetectorRef, Directive, ElementRef, EventEmitter, HostListener, Input, Output, Renderer2, TemplateRef, ViewContainerRef } from '@angular/core';
import { NgControl } from '@angular/forms';
import { from, isObservable } from 'rxjs';
import { ComponentLoaderFactory } from 'ngx-bootstrap/component-loader';
import { TypeaheadContainerComponent } from './typeahead-container.component';
import { TypeaheadMatch } from './typeahead-match.class';
import { TypeaheadConfig } from './typeahead.config';
import { getValueFromObject, latinize, tokenize } from './typeahead-utils';
import { PositioningService } from 'ngx-bootstrap/positioning';
import { debounceTime, filter, mergeMap, switchMap, toArray } from 'rxjs/operators';
export class TypeaheadDirective {
/**
* @param {?} cis
* @param {?} config
* @param {?} changeDetection
* @param {?} element
* @param {?} ngControl
* @param {?} positionService
* @param {?} renderer
* @param {?} viewContainerRef
*/
constructor(cis, config, changeDetection, element, ngControl, positionService, renderer, viewContainerRef) {
this.changeDetection = changeDetection;
this.element = element;
this.ngControl = ngControl;
this.positionService = positionService;
this.renderer = renderer;
/**
* minimal no of characters that needs to be entered before
* typeahead kicks-in. When set to 0, typeahead shows on focus with full
* list of options (limited as normal by typeaheadOptionsLimit)
*/
this.typeaheadMinLength = void 0;
/**
* should be used only in case of typeahead attribute is array.
* If true - loading of options will be async, otherwise - sync.
* true make sense if options array is large.
*/
this.typeaheadAsync = void 0;
/**
* match latin symbols.
* If true the word súper would match super and vice versa.
*/
this.typeaheadLatinize = true;
/**
* Can be use to search words by inserting a single white space between each characters
* for example 'C a l i f o r n i a' will match 'California'.
*/
this.typeaheadSingleWords = true;
/**
* should be used only in case typeaheadSingleWords attribute is true.
* Sets the word delimiter to break words. Defaults to space.
*/
this.typeaheadWordDelimiters = ' ';
/**
* should be used only in case typeaheadSingleWords attribute is true.
* Sets the word delimiter to match exact phrase.
* Defaults to simple and double quotes.
*/
this.typeaheadPhraseDelimiters = '\'"';
/**
* specifies if typeahead is scrollable
*/
this.typeaheadScrollable = false;
/**
* specifies number of options to show in scroll view
*/
this.typeaheadOptionsInScrollableView = 5;
/**
* fired when an options list was opened and the user clicked Tab
* If a value equal true, it will be chosen first or active item in the list
* If value equal false, it will be chosen an active item in the list or nothing
*/
this.typeaheadSelectFirstItem = true;
/**
* fired when 'busy' state of this component was changed,
* fired on async mode only, returns boolean
*/
this.typeaheadLoading = new EventEmitter();
/**
* fired on every key event and returns true
* in case of matches are not detected
*/
this.typeaheadNoResults = new EventEmitter();
/**
* fired when option was selected, return object with data of this option
*/
this.typeaheadOnSelect = new EventEmitter();
/**
* fired when blur event occurs. returns the active item
*/
// tslint:disable-next-line:no-any
this.typeaheadOnBlur = new EventEmitter();
/**
* This attribute indicates that the dropdown should be opened upwards
*/
this.dropup = false;
this.isActiveItemChanged = false;
this.isTypeaheadOptionsListActive = false;
// tslint:disable-next-line:no-any
this.keyUpEventEmitter = new EventEmitter();
this.placement = 'bottom-left';
this._subscriptions = [];
this._typeahead = cis.createLoader(element, viewContainerRef, renderer)
.provide({ provide: TypeaheadConfig, useValue: config });
Object.assign(this, { typeaheadHideResultsOnBlur: config.hideResultsOnBlur,
typeaheadSelectFirstItem: config.selectFirstItem,
typeaheadMinLength: config.minLength,
adaptivePosition: config.adaptivePosition
});
}
/**
* @return {?}
*/
ngOnInit() {
this.typeaheadOptionsLimit = this.typeaheadOptionsLimit || 20;
this.typeaheadMinLength =
this.typeaheadMinLength === void 0 ? 1 : this.typeaheadMinLength;
this.typeaheadWaitMs = this.typeaheadWaitMs || 0;
// async should be false in case of array
if (this.typeaheadAsync === undefined &&
!(isObservable(this.typeahead))) {
this.typeaheadAsync = false;
}
if (isObservable(this.typeahead)) {
this.typeaheadAsync = true;
}
if (this.typeaheadAsync) {
this.asyncActions();
}
else {
this.syncActions();
}
}
/**
* @param {?} e
* @return {?}
*/
// tslint:disable-next-line:no-any
onInput(e) {
// For `<input>`s, use the `value` property. For others that don't have a
// `value` (such as `<span contenteditable="true">`), use either
// `textContent` or `innerText` (depending on which one is supported, i.e.
// Firefox or IE).
/** @type {?} */
const value = e.target.value !== undefined
? e.target.value
: e.target.textContent !== undefined
? e.target.textContent
: e.target.innerText;
if (value != null && value.trim().length >= this.typeaheadMinLength) {
this.typeaheadLoading.emit(true);
this.keyUpEventEmitter.emit(e.target.value);
}
else {
this.typeaheadLoading.emit(false);
this.typeaheadNoResults.emit(false);
this.hide();
}
}
/**
* @param {?} event
* @return {?}
*/
onChange(event) {
if (this._container) {
// esc
/* tslint:disable-next-line: deprecation */
if (event.keyCode === 27 || event.key === 'Escape') {
this.hide();
return;
}
// up
/* tslint:disable-next-line: deprecation */
if (event.keyCode === 38 || event.key === 'ArrowUp') {
this.isActiveItemChanged = true;
this._container.prevActiveMatch();
return;
}
// down
/* tslint:disable-next-line: deprecation */
if (event.keyCode === 40 || event.key === 'ArrowDown') {
this.isActiveItemChanged = true;
this._container.nextActiveMatch();
return;
}
}
}
/**
* @return {?}
*/
onFocus() {
if (this.typeaheadMinLength === 0) {
this.typeaheadLoading.emit(true);
this.keyUpEventEmitter.emit(this.element.nativeElement.value || '');
}
}
/**
* @return {?}
*/
onBlur() {
if (this._container && !this._container.isFocused) {
this.typeaheadOnBlur.emit(this._container.active);
}
}
/**
* @param {?} event
* @return {?}
*/
onKeydown(event) {
// no container - no problems
if (!this._container) {
return;
}
/* tslint:disable-next-line: deprecation */
if (event.keyCode === 9 || event.key === 'Tab' || event.keyCode === 13 || event.key === 'Enter') {
event.preventDefault();
if (this.typeaheadSelectFirstItem) {
this._container.selectActiveMatch();
return;
}
if (!this.typeaheadSelectFirstItem) {
this._container.selectActiveMatch(this.isActiveItemChanged);
this.isActiveItemChanged = false;
this.hide();
}
}
}
/**
* @param {?} match
* @return {?}
*/
changeModel(match) {
/** @type {?} */
const valueStr = match.value;
this.ngControl.viewToModelUpdate(valueStr);
(this.ngControl.control).setValue(valueStr);
this.changeDetection.markForCheck();
this.hide();
}
/**
* @return {?}
*/
get matches() {
return this._matches;
}
/**
* @return {?}
*/
show() {
this.positionService.setOptions({
modifiers: {
flip: {
enabled: this.adaptivePosition
}
}
});
this._typeahead
.attach(TypeaheadContainerComponent)
// todo: add append to body, after updating positioning service
.to(this.container)
.position({ attachment: `${this.dropup ? 'top' : 'bottom'} left` })
.show({
typeaheadRef: this,
placement: this.placement,
animation: false,
dropup: this.dropup
});
this._outsideClickListener = this.renderer.listen('document', 'click', (e) => {
if (this.typeaheadMinLength === 0 && this.element.nativeElement.contains(e.target)) {
return undefined;
}
if (!this.typeaheadHideResultsOnBlur || this.element.nativeElement.contains(e.target)) {
return undefined;
}
this.onOutsideClick();
});
this._container = this._typeahead.instance;
this._container.parent = this;
// This improves the speed as it won't have to be done for each list item
/** @type {?} */
const normalizedQuery = (this.typeaheadLatinize
? latinize(this.ngControl.control.value)
: this.ngControl.control.value)
.toString()
.toLowerCase();
this._container.query = this.typeaheadSingleWords
? tokenize(normalizedQuery, this.typeaheadWordDelimiters, this.typeaheadPhraseDelimiters)
: normalizedQuery;
this._container.matches = this._matches;
this.element.nativeElement.focus();
}
/**
* @return {?}
*/
hide() {
if (this._typeahead.isShown) {
this._typeahead.hide();
this._outsideClickListener();
this._container = null;
}
}
/**
* @return {?}
*/
onOutsideClick() {
if (this._container && !this._container.isFocused) {
this.hide();
}
}
/**
* @return {?}
*/
ngOnDestroy() {
// clean up subscriptions
for (const sub of this._subscriptions) {
sub.unsubscribe();
}
this._typeahead.dispose();
}
/**
* @protected
* @return {?}
*/
asyncActions() {
this._subscriptions.push(this.keyUpEventEmitter
.pipe(debounceTime(this.typeaheadWaitMs), switchMap(() => this.typeahead))
.subscribe((matches) => {
this.finalizeAsyncCall(matches);
}));
}
/**
* @protected
* @return {?}
*/
syncActions() {
this._subscriptions.push(this.keyUpEventEmitter
.pipe(debounceTime(this.typeaheadWaitMs), mergeMap((value) => {
/** @type {?} */
const normalizedQuery = this.normalizeQuery(value);
return from(this.typeahead)
.pipe(filter((option) => {
return (option &&
this.testMatch(this.normalizeOption(option), normalizedQuery));
}), toArray());
}))
.subscribe((matches) => {
this.finalizeAsyncCall(matches);
}));
}
// tslint:disable-next-line:no-any
/**
* @protected
* @param {?} option
* @return {?}
*/
normalizeOption(option) {
/** @type {?} */
const optionValue = getValueFromObject(option, this.typeaheadOptionField);
/** @type {?} */
const normalizedOption = this.typeaheadLatinize
? latinize(optionValue)
: optionValue;
return normalizedOption.toLowerCase();
}
/**
* @protected
* @param {?} value
* @return {?}
*/
normalizeQuery(value) {
// If singleWords, break model here to not be doing extra work on each
// iteration
/** @type {?} */
let normalizedQuery = (this.typeaheadLatinize
? latinize(value)
: value)
.toString()
.toLowerCase();
normalizedQuery = this.typeaheadSingleWords
? tokenize(normalizedQuery, this.typeaheadWordDelimiters, this.typeaheadPhraseDelimiters)
: normalizedQuery;
return normalizedQuery;
}
/**
* @protected
* @param {?} match
* @param {?} test
* @return {?}
*/
testMatch(match, test) {
/** @type {?} */
let spaceLength;
if (typeof test === 'object') {
spaceLength = test.length;
for (let i = 0; i < spaceLength; i += 1) {
if (test[i].length > 0 && match.indexOf(test[i]) < 0) {
return false;
}
}
return true;
}
return match.indexOf(test) >= 0;
}
/**
* @protected
* @param {?} matches
* @return {?}
*/
finalizeAsyncCall(matches) {
this.prepareMatches(matches || []);
this.typeaheadLoading.emit(false);
this.typeaheadNoResults.emit(!this.hasMatches());
if (!this.hasMatches()) {
this.hide();
return;
}
if (this._container) {
// fix: remove usage of ngControl internals
/** @type {?} */
const _controlValue = (this.typeaheadLatinize
? latinize(this.ngControl.control.value)
: this.ngControl.control.value) || '';
// This improves the speed as it won't have to be done for each list item
/** @type {?} */
const normalizedQuery = _controlValue.toString().toLowerCase();
this._container.query = this.typeaheadSingleWords
? tokenize(normalizedQuery, this.typeaheadWordDelimiters, this.typeaheadPhraseDelimiters)
: normalizedQuery;
this._container.matches = this._matches;
}
else {
this.show();
}
}
/**
* @protected
* @param {?} options
* @return {?}
*/
prepareMatches(options) {
/** @type {?} */
const limited = options.slice(0, this.typeaheadOptionsLimit);
if (this.typeaheadGroupField) {
/** @type {?} */
let matches = [];
// extract all group names
/** @type {?} */
const groups = limited
.map((option) => getValueFromObject(option, this.typeaheadGroupField))
.filter((v, i, a) => a.indexOf(v) === i);
groups.forEach((group) => {
// add group header to array of matches
matches.push(new TypeaheadMatch(group, group, true));
// add each item of group to array of matches
matches = matches.concat(limited
.filter(
// tslint:disable-next-line:no-any
(option) => getValueFromObject(option, this.typeaheadGroupField) === group)
.map(
// tslint:disable-next-line:no-any
(option) => new TypeaheadMatch(option, getValueFromObject(option, this.typeaheadOptionField))));
});
this._matches = matches;
}
else {
this._matches = limited.map(
// tslint:disable-next-line:no-any
(option) => new TypeaheadMatch(option, getValueFromObject(option, this.typeaheadOptionField)));
}
}
/**
* @protected
* @return {?}
*/
hasMatches() {
return this._matches.length > 0;
}
}
TypeaheadDirective.decorators = [
{ type: Directive, args: [{ selector: '[typeahead]', exportAs: 'bs-typeahead' },] }
];
/** @nocollapse */
TypeaheadDirective.ctorParameters = () => [
{ type: ComponentLoaderFactory },
{ type: TypeaheadConfig },
{ type: ChangeDetectorRef },
{ type: ElementRef },
{ type: NgControl },
{ type: PositioningService },
{ type: Renderer2 },
{ type: ViewContainerRef }
];
TypeaheadDirective.propDecorators = {
typeahead: [{ type: Input }],
typeaheadMinLength: [{ type: Input }],
adaptivePosition: [{ type: Input }],
typeaheadWaitMs: [{ type: Input }],
typeaheadOptionsLimit: [{ type: Input }],
typeaheadOptionField: [{ type: Input }],
typeaheadGroupField: [{ type: Input }],
typeaheadAsync: [{ type: Input }],
typeaheadLatinize: [{ type: Input }],
typeaheadSingleWords: [{ type: Input }],
typeaheadWordDelimiters: [{ type: Input }],
typeaheadPhraseDelimiters: [{ type: Input }],
typeaheadItemTemplate: [{ type: Input }],
optionsListTemplate: [{ type: Input }],
typeaheadScrollable: [{ type: Input }],
typeaheadOptionsInScrollableView: [{ type: Input }],
typeaheadHideResultsOnBlur: [{ type: Input }],
typeaheadSelectFirstItem: [{ type: Input }],
typeaheadLoading: [{ type: Output }],
typeaheadNoResults: [{ type: Output }],
typeaheadOnSelect: [{ type: Output }],
typeaheadOnBlur: [{ type: Output }],
container: [{ type: Input }],
dropup: [{ type: Input }],
onInput: [{ type: HostListener, args: ['input', ['$event'],] }],
onChange: [{ type: HostListener, args: ['keyup', ['$event'],] }],
onFocus: [{ type: HostListener, args: ['click',] }, { type: HostListener, args: ['focus',] }],
onBlur: [{ type: HostListener, args: ['blur',] }],
onKeydown: [{ type: HostListener, args: ['keydown', ['$event'],] }]
};
if (false) {
/**
* options source, can be Array of strings, objects or
* an Observable for external matching process
* @type {?}
*/
TypeaheadDirective.prototype.typeahead;
/**
* minimal no of characters that needs to be entered before
* typeahead kicks-in. When set to 0, typeahead shows on focus with full
* list of options (limited as normal by typeaheadOptionsLimit)
* @type {?}
*/
TypeaheadDirective.prototype.typeaheadMinLength;
/**
* sets use adaptive position
* @type {?}
*/
TypeaheadDirective.prototype.adaptivePosition;
/**
* minimal wait time after last character typed before typeahead kicks-in
* @type {?}
*/
TypeaheadDirective.prototype.typeaheadWaitMs;
/**
* maximum length of options items list. The default value is 20
* @type {?}
*/
TypeaheadDirective.prototype.typeaheadOptionsLimit;
/**
* when options source is an array of objects, the name of field
* that contains the options value, we use array item as option in case
* of this field is missing. Supports nested properties and methods.
* @type {?}
*/
TypeaheadDirective.prototype.typeaheadOptionField;
/**
* when options source is an array of objects, the name of field that
* contains the group value, matches are grouped by this field when set.
* @type {?}
*/
TypeaheadDirective.prototype.typeaheadGroupField;
/**
* should be used only in case of typeahead attribute is array.
* If true - loading of options will be async, otherwise - sync.
* true make sense if options array is large.
* @type {?}
*/
TypeaheadDirective.prototype.typeaheadAsync;
/**
* match latin symbols.
* If true the word súper would match super and vice versa.
* @type {?}
*/
TypeaheadDirective.prototype.typeaheadLatinize;
/**
* Can be use to search words by inserting a single white space between each characters
* for example 'C a l i f o r n i a' will match 'California'.
* @type {?}
*/
TypeaheadDirective.prototype.typeaheadSingleWords;
/**
* should be used only in case typeaheadSingleWords attribute is true.
* Sets the word delimiter to break words. Defaults to space.
* @type {?}
*/
TypeaheadDirective.prototype.typeaheadWordDelimiters;
/**
* should be used only in case typeaheadSingleWords attribute is true.
* Sets the word delimiter to match exact phrase.
* Defaults to simple and double quotes.
* @type {?}
*/
TypeaheadDirective.prototype.typeaheadPhraseDelimiters;
/**
* used to specify a custom item template.
* Template variables exposed are called item and index;
* @type {?}
*/
TypeaheadDirective.prototype.typeaheadItemTemplate;
/**
* used to specify a custom options list template.
* Template variables: matches, itemTemplate, query
* @type {?}
*/
TypeaheadDirective.prototype.optionsListTemplate;
/**
* specifies if typeahead is scrollable
* @type {?}
*/
TypeaheadDirective.prototype.typeaheadScrollable;
/**
* specifies number of options to show in scroll view
* @type {?}
*/
TypeaheadDirective.prototype.typeaheadOptionsInScrollableView;
/**
* used to hide result on blur
* @type {?}
*/
TypeaheadDirective.prototype.typeaheadHideResultsOnBlur;
/**
* fired when an options list was opened and the user clicked Tab
* If a value equal true, it will be chosen first or active item in the list
* If value equal false, it will be chosen an active item in the list or nothing
* @type {?}
*/
TypeaheadDirective.prototype.typeaheadSelectFirstItem;
/**
* fired when 'busy' state of this component was changed,
* fired on async mode only, returns boolean
* @type {?}
*/
TypeaheadDirective.prototype.typeaheadLoading;
/**
* fired on every key event and returns true
* in case of matches are not detected
* @type {?}
*/
TypeaheadDirective.prototype.typeaheadNoResults;
/**
* fired when option was selected, return object with data of this option
* @type {?}
*/
TypeaheadDirective.prototype.typeaheadOnSelect;
/**
* fired when blur event occurs. returns the active item
* @type {?}
*/
TypeaheadDirective.prototype.typeaheadOnBlur;
/**
* A selector specifying the element the typeahead should be appended to.
* Currently only supports "body".
* @type {?}
*/
TypeaheadDirective.prototype.container;
/**
* This attribute indicates that the dropdown should be opened upwards
* @type {?}
*/
TypeaheadDirective.prototype.dropup;
/**
* if false don't focus the input element the typeahead directive is associated with on selection
* @type {?}
*/
TypeaheadDirective.prototype._container;
/** @type {?} */
TypeaheadDirective.prototype.isActiveItemChanged;
/** @type {?} */
TypeaheadDirective.prototype.isTypeaheadOptionsListActive;
/**
* @type {?}
* @protected
*/
TypeaheadDirective.prototype.keyUpEventEmitter;
/**
* @type {?}
* @protected
*/
TypeaheadDirective.prototype._matches;
/**
* @type {?}
* @protected
*/
TypeaheadDirective.prototype.placement;
/**
* @type {?}
* @private
*/
TypeaheadDirective.prototype._typeahead;
/**
* @type {?}
* @private
*/
TypeaheadDirective.prototype._subscriptions;
/**
* @type {?}
* @private
*/
TypeaheadDirective.prototype._outsideClickListener;
/**
* @type {?}
* @private
*/
TypeaheadDirective.prototype.changeDetection;
/**
* @type {?}
* @private
*/
TypeaheadDirective.prototype.element;
/**
* @type {?}
* @private
*/
TypeaheadDirective.prototype.ngControl;
/**
* @type {?}
* @private
*/
TypeaheadDirective.prototype.positionService;
/**
* @type {?}
* @private
*/
TypeaheadDirective.prototype.renderer;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZWFoZWFkLmRpcmVjdGl2ZS5qcyIsInNvdXJjZVJvb3QiOiJuZzovL25neC1ib290c3RyYXAvdHlwZWFoZWFkLyIsInNvdXJjZXMiOlsidHlwZWFoZWFkLmRpcmVjdGl2ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUNBLE9BQU8sRUFDTCxpQkFBaUIsRUFDakIsU0FBUyxFQUNULFVBQVUsRUFDVixZQUFZLEVBQ1osWUFBWSxFQUNaLEtBQUssRUFHTCxNQUFNLEVBQ04sU0FBUyxFQUNULFdBQVcsRUFDWCxnQkFBZ0IsRUFDakIsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBRTNDLE9BQU8sRUFBRSxJQUFJLEVBQWdCLFlBQVksRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUN4RCxPQUFPLEVBQW1CLHNCQUFzQixFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFDekYsT0FBTyxFQUFFLDJCQUEyQixFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDOUUsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQ3pELE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUNyRCxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsUUFBUSxFQUFFLFFBQVEsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQzNFLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQy9ELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxFQUFFLFFBQVEsRUFBRSxTQUFTLEVBQUUsT0FBTyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFHcEYsTUFBTSxPQUFPLGtCQUFrQjs7Ozs7Ozs7Ozs7SUF3SDdCLFlBQ0UsR0FBMkIsRUFDM0IsTUFBdUIsRUFDZixlQUFrQyxFQUNsQyxPQUFtQixFQUNuQixTQUFvQixFQUNwQixlQUFtQyxFQUNuQyxRQUFtQixFQUMzQixnQkFBa0M7UUFMMUIsb0JB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Qzs7Ozs7OztJQUt2Qyx1REFBMkM7Ozs7OztJQUszQyxtREFBaUQ7Ozs7OztJQUtqRCxpREFBK0M7Ozs7O0lBRS9DLGlEQUFxQzs7Ozs7SUFFckMsOERBQThDOzs7OztJQUU5Qyx3REFBNkM7Ozs7Ozs7SUFLN0Msc0RBQXlDOzs7Ozs7SUFJekMsOENBQXlEOzs7Ozs7SUFJekQsZ0RBQTJEOzs7OztJQUUzRCwrQ0FBaUU7Ozs7O0lBR2pFLDZDQUFvRDs7Ozs7O0lBTXBELHVDQUEyQjs7Ozs7SUFHM0Isb0NBQXdCOzs7OztJQWdCeEIsd0NBQXdDOztJQUN4QyxpREFBNEI7O0lBQzVCLDBEQUFxQzs7Ozs7SUFHckMsK0NBQW9FOzs7OztJQUNwRSxzQ0FBcUM7Ozs7O0lBQ3JDLHVDQUFvQzs7Ozs7SUFHcEMsd0NBQWlFOzs7OztJQUNqRSw0Q0FBNEM7Ozs7O0lBQzVDLG1EQUF3Qzs7Ozs7SUFLdEMsNkNBQTBDOzs7OztJQUMxQyxxQ0FBMkI7Ozs7O0lBQzNCLHVDQUE0Qjs7Ozs7SUFDNUIsNkNBQTJDOzs7OztJQUMzQyxzQ0FBMkIiLCJzb3VyY2VzQ29udGVudCI6WyIvKiB0c2xpbnQ6ZGlzYWJsZTptYXgtZmlsZS1saW5lLWNvdW50ICovXG5pbXBvcnQge1xuICBDaGFuZ2VEZXRlY3RvclJlZixcbiAgRGlyZWN0aXZlLFxuICBFbGVtZW50UmVmLFxuICBFdmVudEVtaXR0ZXIsXG4gIEhvc3RMaXN0ZW5lcixcbiAgSW5wdXQsXG4gIE9uRGVzdHJveSxcbiAgT25Jbml0LFxuICBPdXRwdXQsXG4gIFJlbmRlcmVyMixcbiAgVGVtcGxhdGVSZWYsXG4gIFZpZXdDb250YWluZXJSZWZcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBOZ0NvbnRyb2wgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5cbmltcG9ydCB7IGZyb20sIFN1YnNjcmlwdGlvbiwgaXNPYnNlcnZhYmxlIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBDb21wb25lbnRMb2FkZXIsIENvbXBvbmVudExvYWRlckZhY3RvcnkgfSBmcm9tICduZ3gtYm9vdHN0cmFwL2NvbXBvbmVudC1sb2FkZXInO1xuaW1wb3J0IHsgVHlwZWFoZWFkQ29udGFpbmVyQ29tcG9uZW50IH0gZnJvbSAnLi90eXBlYWhlYWQtY29udGFpbmVyLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBUeXBlYWhlYWRNYXRjaCB9IGZyb20gJy4vdHlwZWFoZWFkLW1hdGNoLmNsYXNzJztcbmltcG9ydCB7IFR5cGVhaGVhZENvbmZpZyB9IGZyb20gJy4vdHlwZWFoZWFkLmNvbmZpZyc7XG5pbXBvcnQgeyBnZXRWYWx1ZUZyb21PYmplY3QsIGxhdGluaXplLCB0b2tlbml6ZSB9IGZyb20gJy4vdHlwZWFoZWFkLXV0aWxzJztcbmltcG9ydCB7IFBvc2l0aW9uaW5nU2VydmljZSB9IGZyb20gJ25neC1ib290c3RyYXAvcG9zaXRpb25pbmcnO1xuaW1wb3J0IHsgZGVib3VuY2VUaW1lLCBmaWx0ZXIsIG1lcmdlTWFwLCBzd2l0Y2hNYXAsIHRvQXJyYXkgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5cbkBEaXJlY3RpdmUoe3NlbGVjdG9yOiAnW3R5cGVhaGVhZF0nLCBleHBvcnRBczogJ2JzLXR5cGVhaGVhZCd9KVxuZXhwb3J0IGNsYXNzIFR5cGVhaGVhZERpcmVjdGl2ZSBpbXBsZW1lbnRzIE9uSW5pdCwgT25EZXN0cm95IHtcbiAgLyoqIG9wdGlvbnMgc291cmNlLCBjYW4gYmUgQXJyYXkgb2Ygc3RyaW5ncywgb2JqZWN0cyBvclxuICAgKiBhbiBPYnNlcnZhYmxlIGZvciBleHRlcm5hbCBtYXRjaGluZyBwcm9jZXNzXG4gICAqL1xuICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1hbnlcbiAgQElucHV0KCkgdHlwZWFoZWFkOiBhbnk7XG4gIC8qKiBtaW5pbWFsIG5vIG9mIGNoYXJhY3RlcnMgdGhhdCBuZWVkcyB0byBiZSBlbnRlcmVkIGJlZm9yZVxuICAgKiB0eXBlYWhlYWQga2lja3MtaW4uIFdoZW4gc2V0IHRvIDAsIHR5cGVhaGVhZCBzaG93cyBvbiBmb2N1cyB3aXRoIGZ1bGxcbiAgICogbGlzdCBvZiBvcHRpb25zIChsaW1pdGVkIGFzIG5vcm1hbCBieSB0eXBlYWhlYWRPcHRpb25zTGltaXQpXG4gICAqL1xuICBASW5wdXQoKSB0eXBlYWhlYWRNaW5MZW5ndGg6IG51bWJlciA9IHZvaWQgMDtcbiAgLyoqIHNldHMgdXNlIGFkYXB0aXZlIHBvc2l0aW9uICovXG4gIEBJbnB1dCgpIGFkYXB0aXZlUG9zaXRpb246IGJvb2xlYW47XG4gIC8qKiBtaW5pbWFsIHdhaXQgdGltZSBhZnRlciBsYXN0IGNoYXJhY3RlciB0eXBlZCBiZWZvcmUgdHlwZWFoZWFkIGtpY2tzLWluICovXG4gIEBJbnB1dCgpIHR5cGVhaGVhZFdhaXRNczogbnVtYmVyO1xuICAvKiogbWF4aW11bSBsZW5ndGggb2Ygb3B0aW9ucyBpdGVtcyBsaXN0LiBUaGUgZGVmYXVsdCB2YWx1ZSBpcyAyMCAqL1xuICBASW5wdXQoKSB0eXBlYWhlYWRPcHRpb25zTGltaXQ6IG51bWJlcjtcbiAgLyoqIHdoZW4gb3B0aW9ucyBzb3VyY2UgaXMgYW4gYXJyYXkgb2Ygb2JqZWN0cywgdGhlIG5hbWUgb2YgZmllbGRcbiAgICogdGhhdCBjb250YWlucyB0aGUgb3B0aW9ucyB2YWx1ZSwgd2UgdXNlIGFycmF5IGl0ZW0gYXMgb3B0aW9uIGluIGNhc2VcbiAgICogb2YgdGhpcyBmaWVsZCBpcyBtaXNzaW5nLiBTdXBwb3J0cyBuZXN0ZWQgcHJvcGVydGllcyBhbmQgbWV0aG9kcy5cbiAgICovXG4gIEBJbnB1dCgpIHR5cGVhaGVhZE9wdGlvbkZpZWxkOiBzdHJpbmc7XG4gIC8qKiB3aGVuIG9wdGlvbnMgc291cmNlIGlzIGFuIGFycmF5IG9mIG9iamVjdHMsIHRoZSBuYW1lIG9mIGZpZWxkIHRoYXRcbiAgICogY29udGFpbnMgdGhlIGdyb3VwIHZhbHVlLCBtYXRjaGVzIGFyZSBncm91cGVkIGJ5IHRoaXMgZmllbGQgd2hlbiBzZXQuXG4gICAqL1xuICBASW5wdXQoKSB0eXBlYWhlYWRHcm91cEZpZWxkOiBzdHJpbmc7XG4gIC8qKiBzaG91bGQgYmUgdXNlZCBvbmx5IGluIGNhc2Ugb2YgdHlwZWFoZWFkIGF0dHJpYnV0ZSBpcyBhcnJheS5cbiAgICogSWYgdHJ1ZSAtIGxvYWRpbmcgb2Ygb3B0aW9ucyB3aWxsIGJlIGFzeW5jLCBvdGhlcndpc2UgLSBzeW5jLlxuICAgKiB0cnVlIG1ha2Ugc2Vuc2UgaWYgb3B0aW9ucyBhcnJheSBpcyBsYXJnZS5cbiAgICovXG4gIEBJbnB1dCgpIHR5cGVhaGVhZEFzeW5jOiBib29sZWFuID0gdm9pZCAwO1xuICAvKiogbWF0Y2ggbGF0aW4gc3ltYm9scy5cbiAgICogSWYgdHJ1ZSB0aGUgd29yZCBzw7pwZXIgd291bGQgbWF0Y2ggc3VwZXIgYW5kIHZpY2UgdmVyc2EuXG4gICAqL1xuICBASW5wdXQoKSB0eXBlYWhlYWRMYXRpbml6ZSA9IHRydWU7XG4gIC8qKiBDYW4gYmUgdXNlIHRvIHNlYXJjaCB3b3JkcyBieSBpbnNlcnRpbmcgYSBzaW5nbGUgd2hpdGUgc3BhY2UgYmV0d2VlbiBlYWNoIGNoYXJhY3RlcnNcbiAgICogIGZvciBleGFtcGxlICdDIGEgbCBpIGYgbyByIG4gaSBhJyB3aWxsIG1hdGNoICdDYWxpZm9ybmlhJy5cbiAgICovXG4gIEBJbnB1dCgpIHR5cGVhaGVhZFNpbmdsZVdvcmRzID0gdHJ1ZTtcbiAgLyoqIHNob3VsZCBiZSB1c2VkIG9ubHkgaW4gY2FzZSB0eXBlYWhlYWRTaW5nbGVXb3JkcyBhdHRyaWJ1dGUgaXMgdHJ1ZS5cbiAgICogU2V0cyB0aGUgd29yZCBkZWxpbWl0ZXIgdG8gYnJlYWsgd29yZHMuIERlZmF1bHRzIHRvIHNwYWNlLlxuICAgKi9cbiAgQElucHV0KCkgdHlwZWFoZWFkV29yZERlbGltaXRlcnMgPSAnICc7XG4gIC8qKiBzaG91bGQgYmUgdXNlZCBvbmx5IGluIGNhc2UgdHlwZWFoZWFkU2luZ2xlV29yZHMgYXR0cmlidXRlIGlzIHRydWUuXG4gICAqIFNldHMgdGhlIHdvcmQgZGVsaW1pdGVyIHRvIG1hdGNoIGV4YWN0IHBocmFzZS5cbiAgICogRGVmYXVsdHMgdG8gc2ltcGxlIGFuZCBkb3VibGUgcXVvdGVzLlxuICAgKi9cbiAgQElucHV0KCkgdHlwZWFoZWFkUGhyYXNlRGVsaW1pdGVycyA9ICdcXCdcIic7XG4gIC8qKiB1c2VkIHRvIHNwZWNpZnkgYSBjdXN0b20gaXRlbSB0ZW1wbGF0ZS5cbiAgICogVGVtcGxhdGUgdmFyaWFibGVzIGV4cG9zZWQgYXJlIGNhbGxlZCBpdGVtIGFuZCBpbmRleDtcbiAgICovXG4gICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLWFueVxuICBASW5wdXQoKSB0eXBlYWhlYWRJdGVtVGVtcGxhdGU6IFRlbXBsYXRlUmVmPGFueT47XG4gIC8qKiB1c2VkIHRvIHNwZWNpZnkgYSBjdXN0b20gb3B0aW9ucyBsaXN0IHRlbXBsYXRlLlxuICAgKiBUZW1wbGF0ZSB2YXJpYWJsZXM6IG1hdGNoZXMsIGl0ZW1UZW1wbGF0ZSwgcXVlcnlcbiAgICovXG4gICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLWFueVxuICBASW5wdXQoKSBvcHRpb25zTGlzdFRlbXBsYXRlOiBUZW1wbGF0ZVJlZjxhbnk+O1xuICAvKiogc3BlY2lmaWVzIGlmIHR5cGVhaGVhZCBpcyBzY3JvbGxhYmxlICAqL1xuICBASW5wdXQoKSB0eXBlYWhlYWRTY3JvbGxhYmxlID0gZmFsc2U7XG4gIC8qKiBzcGVjaWZpZXMgbnVtYmVyIG9mIG9wdGlvbnMgdG8gc2hvdyBpbiBzY3JvbGwgdmlldyAgKi9cbiAgQElucHV0KCkgdHlwZWFoZWFkT3B0aW9uc0luU2Nyb2xsYWJsZVZpZXcgPSA1O1xuICAvKiogdXNlZCB0byBoaWRlIHJlc3VsdCBvbiBibHVyICovXG4gIEBJbnB1dCgpIHR5cGVhaGVhZEhpZGVSZXN1bHRzT25CbHVyOiBib29sZWFuO1xuICAvKiogZmlyZWQgd2hlbiBhbiBvcHRpb25zIGxpc3Qgd2FzIG9wZW5lZCBhbmQgdGhlIHVzZXIgY2xpY2tlZCBUYWJcbiAgICogSWYgYSB2YWx1ZSBlcXVhbCB0cnVlLCBpdCB3aWxsIGJlIGNob3NlbiBmaXJzdCBvciBhY3RpdmUgaXRlbSBpbiB0aGUgbGlzdFxuICAgKiBJZiB2YWx1ZSBlcXVhbCBmYWxzZSwgaXQgd2lsbCBiZSBjaG9zZW4gYW4gYWN0aXZlIGl0ZW0gaW4gdGhlIGxpc3Qgb3Igbm90aGluZ1xuICAgKi9cbiAgQElucHV0KCkgdHlwZWFoZWFkU2VsZWN0Rmlyc3RJdGVtID0gdHJ1ZTtcbiAgLyoqIGZpcmVkIHdoZW4gJ2J1c3knIHN0YXRlIG9mIHRoaXMgY29tcG9uZW50IHdhcyBjaGFuZ2VkLFxuICAgKiBmaXJlZCBvbiBhc3luYyBtb2RlIG9ubHksIHJldHVybnMgYm9vbGVhblxuICAgKi9cbiAgQE91dHB1dCgpIHR5cGVhaGVhZExvYWRpbmcgPSBuZXcgRXZlbnRFbWl0dGVyPGJvb2xlYW4+KCk7XG4gIC8qKiBmaXJlZCBvbiBldmVyeSBrZXkgZXZlbnQgYW5kIHJldHVybnMgdHJ1ZVxuICAgKiBpbiBjYXNlIG9mIG1hdGNoZXMgYXJlIG5vdCBkZXRlY3RlZFxuICAgKi9cbiAgQE91dHB1dCgpIHR5cGVhaGVhZE5vUmVzdWx0cyA9IG5ldyBFdmVudEVtaXR0ZXI8Ym9vbGVhbj4oKTtcbiAgLyoqIGZpcmVkIHdoZW4gb3B0aW9uIHdhcyBzZWxlY3RlZCwgcmV0dXJuIG9iamVjdCB3aXRoIGRhdGEgb2YgdGhpcyBvcHRpb24gKi9cbiAgQE91dHB1dCgpIHR5cGVhaGVhZE9uU2VsZWN0ID0gbmV3IEV2ZW50RW1pdHRlcjxUeXBlYWhlYWRNYXRjaD4oKTtcbiAgLyoqIGZpcmVkIHdoZW4gYmx1ciBldmVudCBvY2N1cnMuIHJldHVybnMgdGhlIGFjdGl2ZSBpdGVtICovXG4gICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLWFueVxuICBAT3V0cHV0KCkgdHlwZWFoZWFkT25CbHVyID0gbmV3IEV2ZW50RW1pdHRlcjxhbnk+KCk7XG5cbiAgLyoqXG4gICAqIEEgc2VsZWN0b3Igc3BlY2lmeWluZyB0aGUgZWxlbWVudCB0aGUgdHlwZWFoZWFkIHNob3VsZCBiZSBhcHBlbmRlZCB0by5cbiAgICogQ3VycmVudGx5IG9ubHkgc3VwcG9ydHMgXCJib2R5XCIuXG4gICAqL1xuICBASW5wdXQoKSBjb250YWluZXI6IHN0cmluZztcblxuICAvKiogVGhpcyBhdHRyaWJ1dGUgaW5kaWNhdGVzIHRoYXQgdGhlIGRyb3Bkb3duIHNob3VsZCBiZSBvcGVuZWQgdXB3YXJkcyAqL1xuICBASW5wdXQoKSBkcm9wdXAgPSBmYWxzZTtcblxuICAvLyBub3QgeWV0IGltcGxlbWVudGVkXG4gIC8qKiBpZiBmYWxzZSByZXN0cmljdCBtb2RlbCB2YWx1ZXMgdG8gdGhlIG9uZXMgc2VsZWN0ZWQgZnJvbSB0aGUgcG9wdXAgb25seSB3aWxsIGJlIHByb3ZpZGVkICovXG4gIC8vIEBJbnB1dCgpIHByb3RlY3RlZCB0eXBlYWhlYWRFZGl0YWJsZTpib29sZWFuO1xuICAvKiogaWYgZmFsc2UgdGhlIGZpcnN0IG1hdGNoIGF1dG9tYXRpY2FsbHkgd2lsbCBub3QgYmUgZm9jdXNlZCBhcyB5b3UgdHlwZSAqL1xuICAvLyBASW5wdXQoKSBwcm90ZWN0ZWQgdHlwZWFoZWFkRm9jdXNGaXJzdDpib29sZWFuO1xuICAvKiogZm9ybWF0IHRoZSBuZy1tb2RlbCByZXN1bHQgYWZ0ZXIgc2VsZWN0aW9uICovXG4gIC8vIEBJbnB1dCgpIHByb3RlY3RlZCB0eXBlYWhlYWRJbnB1dEZvcm1hdHRlcjphbnk7XG4gIC8qKiBpZiB0cnVlIGF1dG9tYXRpY2FsbHkgc2VsZWN0IGFuIGl0ZW0gd2hlbiB0aGVyZSBpcyBvbmUgb3B0aW9uIHRoYXQgZXhhY3RseSBtYXRjaGVzIHRoZSB1c2VyIGlucHV0ICovXG4gIC8vIEBJbnB1dCgpIHByb3RlY3RlZCB0eXBlYWhlYWRTZWxlY3RPbkV4YWN0OmJvb2xlYW47XG4gIC8qKiAgaWYgdHJ1ZSBzZWxlY3QgdGhlIGN1cnJlbnRseSBoaWdobGlnaHRlZCBtYXRjaCBvbiBibHVyICovXG4gIC8vIEBJbnB1dCgpIHByb3RlY3RlZCB0eXBlYWhlYWRTZWxlY3RPbkJsdXI6Ym9vbGVhbjtcbiAgLyoqICBpZiBmYWxzZSBkb24ndCBmb2N1cyB0aGUgaW5wdXQgZWxlbWVudCB0aGUgdHlwZWFoZWFkIGRpcmVjdGl2ZSBpcyBhc3NvY2lhdGVkIHdpdGggb24gc2VsZWN0aW9uICovXG4gICAgLy8gQElucHV0KCkgcHJvdGVjdGVkIHR5cGVhaGVhZEZvY3VzT25TZWxlY3Q6Ym9vbGVhbjtcblxuICBfY29udGFpbmVyOiBUeXBlYWhlYWRDb250YWluZXJDb21wb25lbnQ7XG4gIGlzQWN0aXZlSXRlbUNoYW5nZWQgPSBmYWxzZTtcbiAgaXNUeXBlYWhlYWRPcHRpb25zTGlzdEFjdGl2ZSA9IGZhbHNlO1xuXG4gIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1hbnlcbiAgcHJvdGVjdGVkIGtleVVwRXZlbnRFbWl0dGVyOiBFdmVudEVtaXR0ZXI8YW55PiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgcHJvdGVjdGVkIF9tYXRjaGVzOiBUeXBlYWhlYWRNYXRjaFtdO1xuICBwcm90ZWN0ZWQgcGxhY2VtZW50ID0gJ2JvdHRvbS1sZWZ0JztcbiAgLy8gcHJvdGVjdGVkIHBvcHVwOkNvbXBvbmVudFJlZjxUeXBlYWhlYWRDb250YWluZXJDb21wb25lbnQ+O1xuXG4gIHByaXZhdGUgX3R5cGVhaGVhZDogQ29tcG9uZW50TG9hZGVyPFR5cGVhaGVhZENvbnRhaW5lckNvbXBvbmVudD47XG4gIHByaXZhdGUgX3N1YnNjcmlwdGlvbnM6IFN1YnNjcmlwdGlvbltdID0gW107XG4gIHByaXZhdGUgX291dHNpZGVDbGlja0xp