fundamental-ngx
Version:
SAP Fundamentals, implemented in Angular
567 lines • 36.1 kB
JavaScript
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
import { Component, ElementRef, EventEmitter, forwardRef, Input, Output, QueryList, TemplateRef, ViewChild, ViewChildren, ViewEncapsulation } from '@angular/core';
import { NG_VALUE_ACCESSOR } from '@angular/forms';
import { MenuItemDirective } from '../menu/menu-item.directive';
import { MenuKeyboardService } from '../menu/menu-keyboard.service';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
/**
* Allows users to filter through results and select a value.
*
* Supports Angular Forms.
*/
var ComboboxComponent = /** @class */ (function () {
function ComboboxComponent(menuKeyboardService) {
this.menuKeyboardService = menuKeyboardService;
/**
* Values to be filtered in the search input.
*/
this.dropdownValues = [];
/**
* Filter function. Accepts an array of objects and a search term as arguments
* and returns a string. See search input examples for details.
*/
this.filterFn = this.defaultFilter;
/**
* Icon to display in the right-side button.
*/
this.glyph = 'navigation-down-arrow';
/**
* Max height of the popover. Any overflowing elements will be accessible through scrolling.
*/
this.maxHeight = '200px';
/**
* Whether the search input should be displayed in compact mode.
*/
this.compact = false;
/**
* Whether the matching string should be highlighted during filtration.
*/
this.highlighting = true;
/**
* Whether the popover should close when a user selects a result.
*/
this.closeOnSelect = true;
/**
* Whether the input field should be populated with the result picked by the user.
*/
this.fillOnSelect = true;
/**
* Display function. Accepts an object of the same type as the
* items passed to dropdownValues as argument, and outputs a string.
* An arrow function can be used to access the *this* keyword in the calling component.
* See search input examples for details.
*/
this.displayFn = this.defaultDisplay;
/**
* Event emitted when an item is clicked. Use *$event* to retrieve it.
*/
this.itemClicked = new EventEmitter();
/**
* @hidden
*/
this.displayedValues = [];
/**
* @hidden
*/
this.isOpen = false;
/**
* @hidden
*/
this.onDestroy$ = new Subject();
/**
* @hidden
*/
this.onChange = (/**
* @return {?}
*/
function () { });
/**
* @hidden
*/
this.onTouched = (/**
* @return {?}
*/
function () { });
}
/** @hidden */
/**
* @hidden
* @return {?}
*/
ComboboxComponent.prototype.ngOnInit = /**
* @hidden
* @return {?}
*/
function () {
if (this.dropdownValues) {
this.displayedValues = this.dropdownValues;
}
};
/** @hidden */
/**
* @hidden
* @param {?} changes
* @return {?}
*/
ComboboxComponent.prototype.ngOnChanges = /**
* @hidden
* @param {?} changes
* @return {?}
*/
function (changes) {
if (this.dropdownValues && (changes.dropdownValues || changes.searchTerm)) {
if (this.inputText) {
this.displayedValues = this.filterFn(this.dropdownValues, this.inputText);
}
else {
this.displayedValues = this.dropdownValues;
}
}
};
/**
* @return {?}
*/
ComboboxComponent.prototype.ngOnDestroy = /**
* @return {?}
*/
function () {
this.onDestroy$.next();
this.onDestroy$.complete();
};
/** @hidden */
/**
* @hidden
* @return {?}
*/
ComboboxComponent.prototype.ngAfterViewInit = /**
* @hidden
* @return {?}
*/
function () {
var _this = this;
this.menuKeyboardService.itemClicked
.pipe(takeUntil(this.onDestroy$))
.subscribe((/**
* @param {?} index
* @return {?}
*/
function (index) { return _this.onMenuClickHandler(index); }));
this.menuKeyboardService.focusEscapeBeforeList = (/**
* @return {?}
*/
function () { return _this.searchInputElement.nativeElement.focus(); });
this.menuKeyboardService.focusEscapeAfterList = (/**
* @return {?}
*/
function () { });
};
/** @hidden */
/**
* @hidden
* @param {?} event
* @return {?}
*/
ComboboxComponent.prototype.onInputKeydownHandler = /**
* @hidden
* @param {?} event
* @return {?}
*/
function (event) {
if (event.code === 'Enter' && this.searchFunction) {
this.searchFunction();
}
else if (event.code === 'ArrowDown') {
event.preventDefault();
if (this.menuItems && this.menuItems.first) {
this.menuItems.first.focus();
}
}
};
/** @hidden */
/**
* @hidden
* @return {?}
*/
ComboboxComponent.prototype.onInputKeyupHandler = /**
* @hidden
* @return {?}
*/
function () {
if (this.inputText && this.inputText.length) {
this.isOpen = true;
}
};
/** @hidden */
/**
* @hidden
* @param {?} event
* @param {?} index
* @return {?}
*/
ComboboxComponent.prototype.onMenuKeydownHandler = /**
* @hidden
* @param {?} event
* @param {?} index
* @return {?}
*/
function (event, index) {
this.menuKeyboardService.keyDownHandler(event, index, this.menuItems.toArray());
};
/** @hidden */
/**
* @hidden
* @param {?} index
* @return {?}
*/
ComboboxComponent.prototype.onMenuClickHandler = /**
* @hidden
* @param {?} index
* @return {?}
*/
function (index) {
/** @type {?} */
var selectedItem = this.displayedValues[index];
if (selectedItem) {
this.handleClickActions(selectedItem);
this.itemClicked.emit({ item: selectedItem, index: index });
}
};
Object.defineProperty(ComboboxComponent.prototype, "inputText", {
/** Get the input text of the input. */
get: /**
* Get the input text of the input.
* @return {?}
*/
function () {
return this.inputTextValue;
},
/** Set the input text of the input. */
set: /**
* Set the input text of the input.
* @param {?} value
* @return {?}
*/
function (value) {
this.inputTextValue = value;
this.onChange(value);
this.onTouched();
},
enumerable: true,
configurable: true
});
/** @hidden */
/**
* @hidden
* @param {?} value
* @return {?}
*/
ComboboxComponent.prototype.writeValue = /**
* @hidden
* @param {?} value
* @return {?}
*/
function (value) {
this.inputTextValue = value;
};
/** @hidden */
/**
* @hidden
* @param {?} fn
* @return {?}
*/
ComboboxComponent.prototype.registerOnChange = /**
* @hidden
* @param {?} fn
* @return {?}
*/
function (fn) {
this.onChange = fn;
};
/** @hidden */
/**
* @hidden
* @param {?} fn
* @return {?}
*/
ComboboxComponent.prototype.registerOnTouched = /**
* @hidden
* @param {?} fn
* @return {?}
*/
function (fn) {
this.onTouched = fn;
};
/** @hidden */
/**
* @hidden
* @return {?}
*/
ComboboxComponent.prototype.handleSearchTermChange = /**
* @hidden
* @return {?}
*/
function () {
this.displayedValues = this.filterFn(this.dropdownValues, this.inputText);
};
/** @hidden */
/**
* @hidden
* @return {?}
*/
ComboboxComponent.prototype.onPrimaryButtonClick = /**
* @hidden
* @return {?}
*/
function () {
if (this.searchFunction) {
this.searchFunction();
}
};
/** @hidden */
/**
* @hidden
* @param {?} isDisabled
* @return {?}
*/
ComboboxComponent.prototype.setDisabledState = /**
* @hidden
* @param {?} isDisabled
* @return {?}
*/
function (isDisabled) {
this.disabled = isDisabled;
};
/**
* @private
* @param {?} str
* @return {?}
*/
ComboboxComponent.prototype.defaultDisplay = /**
* @private
* @param {?} str
* @return {?}
*/
function (str) {
return str;
};
/**
* @private
* @param {?} contentArray
* @param {?} searchTerm
* @return {?}
*/
ComboboxComponent.prototype.defaultFilter = /**
* @private
* @param {?} contentArray
* @param {?} searchTerm
* @return {?}
*/
function (contentArray, searchTerm) {
var _this = this;
/** @type {?} */
var searchLower = searchTerm.toLocaleLowerCase();
return contentArray.filter((/**
* @param {?} item
* @return {?}
*/
function (item) {
if (item) {
return _this.displayFn(item).toLocaleLowerCase().includes(searchLower);
}
}));
};
/**
* @private
* @param {?} term
* @return {?}
*/
ComboboxComponent.prototype.handleClickActions = /**
* @private
* @param {?} term
* @return {?}
*/
function (term) {
if (this.closeOnSelect) {
this.isOpen = false;
}
if (this.fillOnSelect) {
this.inputText = this.displayFn(term);
this.handleSearchTermChange();
}
};
ComboboxComponent.decorators = [
{ type: Component, args: [{
selector: 'fd-combobox',
template: "<fd-popover [(isOpen)]=\"isOpen\"\n [fillControlMode]=\"'at-least'\"\n [disabled]=\"disabled\"\n class=\"fd-combobox-popover-custom\"\n [ngClass]=\"{'fd-popover-body--display-none': displayedValues && !displayedValues.length}\">\n <fd-popover-control>\n <div class=\"fd-combobox-control\">\n <div class=\"fd-input-group fd-input-group--after\" [ngClass]=\"{'fd-input-group--compact': compact}\">\n <input #searchInputElement type=\"text\" class=\"fd-input\" [ngClass]=\"{'fd-input--compact': compact}\"\n (keydown)=\"onInputKeydownHandler($event)\"\n (keyup)=\"onInputKeyupHandler()\"\n [disabled]=\"disabled\"\n [(ngModel)]=\"inputText\"\n (ngModelChange)=\"handleSearchTermChange()\"\n placeholder=\"{{placeholder}}\">\n <span class=\"fd-input-group__addon fd-input-group__addon--after fd-input-group__addon--button\">\n <button fd-button\n tabindex=\"-1\"\n type=\"button\"\n [fdType]=\"'light'\"\n [glyph]=\"glyph\"\n [disabled]=\"disabled\"\n (click)=\"onPrimaryButtonClick()\">\n </button>\n </span>\n </div>\n </div>\n </fd-popover-control>\n <fd-popover-body *ngIf=\"displayedValues && displayedValues.length\">\n <fd-menu class=\"fd-combobox-input-menu-overflow\"\n [style.maxHeight]=\"maxHeight\">\n <ng-content></ng-content>\n <ul fd-menu-list>\n <li *ngFor=\"let term of displayedValues; let index = index;\"\n (click)=\"onMenuClickHandler(index)\"\n (keydown)=\"onMenuKeydownHandler($event, index)\"\n fd-menu-item\n tabindex=\"0\">\n <span *ngIf=\"!itemTemplate\"\n [innerHTML]=\"term | displayFnPipe:displayFn | highlight:inputText:highlighting\"\n ></span>\n <ng-container *ngIf=\"itemTemplate\">\n <ng-container *ngTemplateOutlet=\"itemTemplate; context: {$implicit: term}\"></ng-container>\n </ng-container>\n </li>\n </ul>\n </fd-menu>\n </fd-popover-body>\n</fd-popover>\n\n",
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef((/**
* @return {?}
*/
function () { return ComboboxComponent; })),
multi: true
},
MenuKeyboardService
],
host: {
'[class.fd-combobox-custom-class]': 'true',
'[class.fd-combobox-input]': 'true'
},
encapsulation: ViewEncapsulation.None,
styles: [".fd-combobox-custom-class,.fd-combobox-custom-class .fd-combobox-popover-custom{display:block}.fd-combobox-custom-class .fd-combobox-input-menu-overflow{overflow:auto}"]
}] }
];
/** @nocollapse */
ComboboxComponent.ctorParameters = function () { return [
{ type: MenuKeyboardService }
]; };
ComboboxComponent.propDecorators = {
dropdownValues: [{ type: Input }],
filterFn: [{ type: Input }],
disabled: [{ type: Input }],
placeholder: [{ type: Input }],
glyph: [{ type: Input }],
itemTemplate: [{ type: Input }],
maxHeight: [{ type: Input }],
searchFunction: [{ type: Input }],
compact: [{ type: Input }],
highlighting: [{ type: Input }],
closeOnSelect: [{ type: Input }],
fillOnSelect: [{ type: Input }],
displayFn: [{ type: Input }],
itemClicked: [{ type: Output }],
menuItems: [{ type: ViewChildren, args: [MenuItemDirective,] }],
searchInputElement: [{ type: ViewChild, args: ['searchInputElement',] }]
};
return ComboboxComponent;
}());
export { ComboboxComponent };
if (false) {
/**
* Values to be filtered in the search input.
* @type {?}
*/
ComboboxComponent.prototype.dropdownValues;
/**
* Filter function. Accepts an array of objects and a search term as arguments
* and returns a string. See search input examples for details.
* @type {?}
*/
ComboboxComponent.prototype.filterFn;
/**
* Whether the search input is disabled. *
* @type {?}
*/
ComboboxComponent.prototype.disabled;
/**
* Placeholder of the search input. *
* @type {?}
*/
ComboboxComponent.prototype.placeholder;
/**
* Icon to display in the right-side button.
* @type {?}
*/
ComboboxComponent.prototype.glyph;
/**
* The template with which to display the individual listed items.
* Use it by passing an ng-template with implicit content. See examples for more info.
* @type {?}
*/
ComboboxComponent.prototype.itemTemplate;
/**
* Max height of the popover. Any overflowing elements will be accessible through scrolling.
* @type {?}
*/
ComboboxComponent.prototype.maxHeight;
/**
* Search function to execute when the Enter key is pressed on the main input.
* @type {?}
*/
ComboboxComponent.prototype.searchFunction;
/**
* Whether the search input should be displayed in compact mode.
* @type {?}
*/
ComboboxComponent.prototype.compact;
/**
* Whether the matching string should be highlighted during filtration.
* @type {?}
*/
ComboboxComponent.prototype.highlighting;
/**
* Whether the popover should close when a user selects a result.
* @type {?}
*/
ComboboxComponent.prototype.closeOnSelect;
/**
* Whether the input field should be populated with the result picked by the user.
* @type {?}
*/
ComboboxComponent.prototype.fillOnSelect;
/**
* Display function. Accepts an object of the same type as the
* items passed to dropdownValues as argument, and outputs a string.
* An arrow function can be used to access the *this* keyword in the calling component.
* See search input examples for details.
* @type {?}
*/
ComboboxComponent.prototype.displayFn;
/**
* Event emitted when an item is clicked. Use *$event* to retrieve it.
* @type {?}
*/
ComboboxComponent.prototype.itemClicked;
/**
* @hidden
* @type {?}
*/
ComboboxComponent.prototype.menuItems;
/**
* @hidden
* @type {?}
*/
ComboboxComponent.prototype.searchInputElement;
/**
* @hidden
* @type {?}
*/
ComboboxComponent.prototype.displayedValues;
/**
* @hidden
* @type {?}
*/
ComboboxComponent.prototype.isOpen;
/**
* @hidden
* @type {?}
*/
ComboboxComponent.prototype.inputTextValue;
/**
* @hidden
* @type {?}
* @private
*/
ComboboxComponent.prototype.onDestroy$;
/**
* @hidden
* @type {?}
*/
ComboboxComponent.prototype.onChange;
/**
* @hidden
* @type {?}
*/
ComboboxComponent.prototype.onTouched;
/**
* @type {?}
* @private
*/
ComboboxComponent.prototype.menuKeyboardService;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29tYm9ib3guY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6Im5nOi8vZnVuZGFtZW50YWwtbmd4LyIsInNvdXJjZXMiOlsibGliL2NvbWJvYm94L2NvbWJvYm94LmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7O0FBQUEsT0FBTyxFQUVILFNBQVMsRUFDVCxVQUFVLEVBQ1YsWUFBWSxFQUNaLFVBQVUsRUFDVixLQUFLLEVBR0wsTUFBTSxFQUNOLFNBQVMsRUFDTSxXQUFXLEVBQzFCLFNBQVMsRUFDVCxZQUFZLEVBQ1osaUJBQWlCLEVBQ3BCLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBd0IsaUJBQWlCLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUN6RSxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUVoRSxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQztBQUNwRSxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQy9CLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQzs7Ozs7O0FBTzNDO0lBNkdJLDJCQUFvQixtQkFBd0M7UUFBeEMsd0JBQW1CLEdBQW5CLG1CQUFtQixDQUFxQjs7OztRQXZGNUQsbUJBQWMsR0FBVSxFQUFFLENBQUM7Ozs7O1FBSzNCLGFBQVEsR0FBYSxJQUFJLENBQUMsYUFBYSxDQUFDOzs7O1FBWXhDLFVBQUssR0FBVyx1QkFBdUIsQ0FBQzs7OztRQVd4QyxjQUFTLEdBQVcsT0FBTyxDQUFDOzs7O1FBUTVCLFlBQU8sR0FBWSxLQUFLLENBQUM7Ozs7UUFJekIsaUJBQVksR0FBWSxJQUFJLENBQUM7Ozs7UUFJN0Isa0JBQWEsR0FBWSxJQUFJLENBQUM7Ozs7UUFJOUIsaUJBQVksR0FBWSxJQUFJLENBQUM7Ozs7Ozs7UUFPN0IsY0FBUyxHQUFhLElBQUksQ0FBQyxjQUFjLENBQUM7Ozs7UUFJMUMsZ0JBQVcsR0FBK0IsSUFB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Ozs7O0lBR3ZCLHVDQUFpRTs7Ozs7SUFHakUscUNBQTBCOzs7OztJQUcxQixzQ0FBMkI7Ozs7O0lBRWYsZ0RBQWdEIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgICBBZnRlclZpZXdJbml0LFxuICAgIENvbXBvbmVudCxcbiAgICBFbGVtZW50UmVmLFxuICAgIEV2ZW50RW1pdHRlcixcbiAgICBmb3J3YXJkUmVmLFxuICAgIElucHV0LFxuICAgIE9uQ2hhbmdlcywgT25EZXN0cm95LFxuICAgIE9uSW5pdCxcbiAgICBPdXRwdXQsXG4gICAgUXVlcnlMaXN0LFxuICAgIFNpbXBsZUNoYW5nZXMsIFRlbXBsYXRlUmVmLFxuICAgIFZpZXdDaGlsZCxcbiAgICBWaWV3Q2hpbGRyZW4sXG4gICAgVmlld0VuY2Fwc3VsYXRpb25cbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBDb250cm9sVmFsdWVBY2Nlc3NvciwgTkdfVkFMVUVfQUNDRVNTT1IgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBNZW51SXRlbURpcmVjdGl2ZSB9IGZyb20gJy4uL21lbnUvbWVudS1pdGVtLmRpcmVjdGl2ZSc7XG5pbXBvcnQgeyBDb21ib2JveEl0ZW0gfSBmcm9tICcuL2NvbWJvYm94LWl0ZW0nO1xuaW1wb3J0IHsgTWVudUtleWJvYXJkU2VydmljZSB9IGZyb20gJy4uL21lbnUvbWVudS1rZXlib2FyZC5zZXJ2aWNlJztcbmltcG9ydCB7IFN1YmplY3QgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IHRha2VVbnRpbCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcblxuLyoqXG4gKiBBbGxvd3MgdXNlcnMgdG8gZmlsdGVyIHRocm91Z2ggcmVzdWx0cyBhbmQgc2VsZWN0IGEgdmFsdWUuXG4gKlxuICogU3VwcG9ydHMgQW5ndWxhciBGb3Jtcy5cbiAqL1xuQENvbXBvbmVudCh7XG4gICAgc2VsZWN0b3I6ICdmZC1jb21ib2JveCcsXG4gICAgdGVtcGxhdGVVcmw6ICcuL2NvbWJvYm94LmNvbXBvbmVudC5odG1sJyxcbiAgICBzdHlsZVVybHM6IFsnLi9jb21ib2JveC5jb21wb25lbnQuc2NzcyddLFxuICAgIHByb3ZpZGVyczogW1xuICAgICAgICB7XG4gICAgICAgICAgICBwcm92aWRlOiBOR19WQUxVRV9BQ0NFU1NPUixcbiAgICAgICAgICAgIHVzZUV4aXN0aW5nOiBmb3J3YXJkUmVmKCgpID0+IENvbWJvYm94Q29tcG9uZW50KSxcbiAgICAgICAgICAgIG11bHRpOiB0cnVlXG4gICAgICAgIH0sXG4gICAgICAgIE1lbnVLZXlib2FyZFNlcnZpY2VcbiAgICBdLFxuICAgIGhvc3Q6IHtcbiAgICAgICAgJ1tjbGFzcy5mZC1jb21ib2JveC1jdXN0b20tY2xhc3NdJzogJ3RydWUnLFxuICAgICAgICAnW2NsYXNzLmZkLWNvbWJvYm94LWlucHV0XSc6ICd0cnVlJ1xuICAgIH0sXG4gICAgZW5jYXBzdWxhdGlvbjogVmlld0VuY2Fwc3VsYXRpb24uTm9uZVxufSlcbmV4cG9ydCBjbGFzcyBDb21ib2JveENvbXBvbmVudCBpbXBsZW1lbnRzIENvbnRyb2xWYWx1ZUFjY2Vzc29yLCBPbkluaXQsIE9uQ2hhbmdlcywgQWZ0ZXJWaWV3SW5pdCwgT25EZXN0cm95IHtcblxuICAgIC8qKiBWYWx1ZXMgdG8gYmUgZmlsdGVyZWQgaW4gdGhlIHNlYXJjaCBpbnB1dC4gKi9cbiAgICBASW5wdXQoKVxuICAgIGRyb3Bkb3duVmFsdWVzOiBhbnlbXSA9IFtdO1xuXG4gICAgLyoqIEZpbHRlciBmdW5jdGlvbi4gQWNjZXB0cyBhbiBhcnJheSBvZiBvYmplY3RzIGFuZCBhIHNlYXJjaCB0ZXJtIGFzIGFyZ3VtZW50c1xuICAgICAqIGFuZCByZXR1cm5zIGEgc3RyaW5nLiBTZWUgc2VhcmNoIGlucHV0IGV4YW1wbGVzIGZvciBkZXRhaWxzLiAqL1xuICAgIEBJbnB1dCgpXG4gICAgZmlsdGVyRm46IEZ1bmN0aW9uID0gdGhpcy5kZWZhdWx0RmlsdGVyO1xuXG4gICAgLyoqIFdoZXRoZXIgdGhlIHNlYXJjaCBpbnB1dCBpcyBkaXNhYmxlZC4gKiovXG4gICAgQElucHV0KClcbiAgICBkaXNhYmxlZDogYm9vbGVhbjtcblxuICAgIC8qKiBQbGFjZWhvbGRlciBvZiB0aGUgc2VhcmNoIGlucHV0LiAqKi9cbiAgICBASW5wdXQoKVxuICAgIHBsYWNlaG9sZGVyOiBzdHJpbmc7XG5cbiAgICAvKiogSWNvbiB0byBkaXNwbGF5IGluIHRoZSByaWdodC1zaWRlIGJ1dHRvbi4gKi9cbiAgICBASW5wdXQoKVxuICAgIGdseXBoOiBzdHJpbmcgPSAnbmF2aWdhdGlvbi1kb3duLWFycm93JztcblxuICAgIC8qKlxuICAgICAqIFRoZSB0ZW1wbGF0ZSB3aXRoIHdoaWNoIHRvIGRpc3BsYXkgdGhlIGluZGl2aWR1YWwgbGlzdGVkIGl0ZW1zLlxuICAgICAqIFVzZSBpdCBieSBwYXNzaW5nIGFuIG5nLXRlbXBsYXRlIHdpdGggaW1wbGljaXQgY29udGVudC4gU2VlIGV4YW1wbGVzIGZvciBtb3JlIGluZm8uXG4gICAgICovXG4gICAgQElucHV0KClcbiAgICBpdGVtVGVtcGxhdGU6IFRlbXBsYXRlUmVmPGFueT47XG5cbiAgICAvKiogTWF4IGhlaWdodCBvZiB0aGUgcG9wb3Zlci4gQW55IG92ZXJmbG93aW5nIGVsZW1lbnRzIHdpbGwgYmUgYWNjZXNzaWJsZSB0aHJvdWdoIHNjcm9sbGluZy4gKi9cbiAgICBASW5wdXQoKVxuICAgIG1heEhlaWdodDogc3RyaW5nID0gJzIwMHB4JztcblxuICAgIC8qKiBTZWFyY2ggZnVuY3Rpb24gdG8gZXhlY3V0ZSB3aGVuIHRoZSBFbnRlciBrZXkgaXMgcHJlc3NlZCBvbiB0aGUgbWFpbiBpbnB1dC4gKi9cbiAgICBASW5wdXQoKVxuICAgIHNlYXJjaEZ1bmN0aW9uOiBGdW5jdGlvbjtcblxuICAgIC8qKiBXaGV0aGVyIHRoZSBzZWFyY2ggaW5wdXQgc2hvdWxkIGJlIGRpc3BsYXllZCBpbiBjb21wYWN0IG1vZGUuICovXG4gICAgQElucHV0KClcbiAgICBjb21wYWN0OiBib29sZWFuID0gZmFsc2U7XG5cbiAgICAvKiogV2hldGhlciB0aGUgbWF0Y2hpbmcgc3RyaW5nIHNob3VsZCBiZSBoaWdobGlnaHRlZCBkdXJpbmcgZmlsdHJhdGlvbi4gKi9cbiAgICBASW5wdXQoKVxuICAgIGhpZ2hsaWdodGluZzogYm9vbGVhbiA9IHRydWU7XG5cbiAgICAvKiogV2hldGhlciB0aGUgcG9wb3ZlciBzaG91bGQgY2xvc2Ugd2hlbiBhIHVzZXIgc2VsZWN0cyBhIHJlc3VsdC4gKi9cbiAgICBASW5wdXQoKVxuICAgIGNsb3NlT25TZWxlY3Q6IGJvb2xlYW4gPSB0cnVlO1xuXG4gICAgLyoqIFdoZXRoZXIgdGhlIGlucHV0IGZpZWxkIHNob3VsZCBiZSBwb3B1bGF0ZWQgd2l0aCB0aGUgcmVzdWx0IHBpY2tlZCBieSB0aGUgdXNlci4gKi9cbiAgICBASW5wdXQoKVxuICAgIGZpbGxPblNlbGVjdDogYm9vbGVhbiA9IHRydWU7XG5cbiAgICAvKiogRGlzcGxheSBmdW5jdGlvbi4gQWNjZXB0cyBhbiBvYmplY3Qgb2YgdGhlIHNhbWUgdHlwZSBhcyB0aGVcbiAgICAgKiBpdGVtcyBwYXNzZWQgdG8gZHJvcGRvd25WYWx1ZXMgYXMgYXJndW1lbnQsIGFuZCBvdXRwdXRzIGEgc3RyaW5nLlxuICAgICAqIEFuIGFycm93IGZ1bmN0aW9uIGNhbiBiZSB1c2VkIHRvIGFjY2VzcyB0aGUgKnRoaXMqIGtleXdvcmQgaW4gdGhlIGNhbGxpbmcgY29tcG9uZW50LlxuICAgICAqIFNlZSBzZWFyY2ggaW5wdXQgZXhhbXBsZXMgZm9yIGRldGFpbHMuICovXG4gICAgQElucHV0KClcbiAgICBkaXNwbGF5Rm46IEZ1bmN0aW9uID0gdGhpcy5kZWZhdWx0RGlzcGxheTtcblxuICAgIC8qKiBFdmVudCBlbWl0dGVkIHdoZW4gYW4gaXRlbSBpcyBjbGlja2VkLiBVc2UgKiRldmVudCogdG8gcmV0cmlldmUgaXQuICovXG4gICAgQE91dHB1dCgpXG4gICAgaXRlbUNsaWNrZWQ6IEV2ZW50RW1pdHRlcjxDb21ib2JveEl0ZW0+ID0gbmV3IEV2ZW50RW1pdHRlcjxDb21ib2JveEl0ZW0+KCk7XG5cbiAgICAvKiogQGhpZGRlbiAqL1xuICAgIEBWaWV3Q2hpbGRyZW4oTWVudUl0ZW1EaXJlY3RpdmUpXG4gICAgbWVudUl0ZW1zOiBRdWVyeUxpc3Q8TWVudUl0ZW1EaXJlY3RpdmU+O1xuXG4gICAgLyoqIEBoaWRkZW4gKi9cbiAgICBAVmlld0NoaWxkKCdzZWFyY2hJbnB1dEVsZW1lbnQnKVxuICAgIHNlYXJjaElucHV0RWxlbWVudDogRWxlbWVudFJlZjtcblxuICAgIC8qKiBAaGlkZGVuICovXG4gICAgZGlzcGxheWVkVmFsdWVzOiBhbnlbXSA9IFtdO1xuXG4gICAgLyoqIEBoaWRkZW4gKi9cbiAgICBpc09wZW46IGJvb2xlYW4gPSBmYWxzZTtcblxuICAgIC8qKiBAaGlkZGVuICovXG4gICAgaW5wdXRUZXh0VmFsdWU6IHN0cmluZztcblxuICAgIC8qKiBAaGlkZGVuICovXG4gICAgcHJpdmF0ZSByZWFkb25seSBvbkRlc3Ryb3kkOiBTdWJqZWN0PHZvaWQ+ID0gbmV3IFN1YmplY3Q8dm9pZD4oKTtcblxuICAgIC8qKiBAaGlkZGVuICovXG4gICAgb25DaGFuZ2U6IGFueSA9ICgpID0+IHsgfTtcblxuICAgIC8qKiBAaGlkZGVuICovXG4gICAgb25Ub3VjaGVkOiBhbnkgPSAoKSA9PiB7IH07XG5cbiAgICBjb25zdHJ1Y3Rvcihwcml2YXRlIG1lbnVLZXlib2FyZFNlcnZpY2U6IE1lbnVLZXlib2FyZFNlcnZpY2UpIHsgfVxuXG4gICAgLyoqIEBoaWRkZW4gKi9cbiAgICBuZ09uSW5pdCgpIHtcbiAgICAgICAgaWYgKHRoaXMuZHJvcGRvd25WYWx1ZXMpIHtcbiAgICAgICAgICAgIHRoaXMuZGlzcGxheWVkVmFsdWVzID0gdGhpcy5kcm9wZG93blZhbHVlcztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKiBAaGlkZGVuICovXG4gICAgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcykge1xuICAgICAgICBpZiAodGhpcy5kcm9wZG93blZhbHVlcyAmJiAoY2hhbmdlcy5kcm9wZG93blZhbHVlcyB8fCBjaGFuZ2VzLnNlYXJjaFRlcm0pKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5pbnB1dFRleHQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmRpc3BsYXllZFZhbHVlcyA9IHRoaXMuZmlsdGVyRm4odGhpcy5kcm9wZG93blZhbHVlcywgdGhpcy5pbnB1dFRleHQpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLmRpc3BsYXllZFZhbHVlcyA9IHRoaXMuZHJvcGRvd25WYWx1ZXM7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5vbkRlc3Ryb3kkLm5leHQoKTtcbiAgICAgICAgdGhpcy5vbkRlc3Ryb3kkLmNvbXBsZXRlKCk7XG4gICAgfVxuXG4gICAgLyoqIEBoaWRkZW4gKi9cbiAgICBuZ0FmdGVyVmlld0luaXQoKTogdm9pZCB7XG4gICAgICAgIHRoaXMubWVudUtleWJvYXJkU2VydmljZS5pdGVtQ2xpY2tlZFxuICAgICAgICAgICAgLnBpcGUodGFrZVVudGlsKHRoaXMub25EZXN0cm95JCkpXG4gICAgICAgICAgICAuc3Vic2NyaWJlKGluZGV4ID0+IHRoaXMub25NZW51Q2xpY2tIYW5kbGVyKGluZGV4KSk7XG4gICAgICAgIHRoaXMubWVudUtleWJvYXJkU2VydmljZS5mb2N1c0VzY2FwZUJlZm9yZUxpc3QgPSAoKSA9PiB0aGlzLnNlYXJjaElucHV0RWxlbWVudC5uYXRpdmVFbGVtZW50LmZvY3VzKCk7XG4gICAgICAgIHRoaXMubWVudUtleWJvYXJkU2VydmljZS5mb2N1c0VzY2FwZUFmdGVyTGlzdCA9ICgpID0+IHsgfTtcbiAgICB9XG5cbiAgICAvKiogQGhpZGRlbiAqL1xuICAgIG9uSW5wdXRLZXlkb3duSGFuZGxlcihldmVudCkge1xuICAgICAgICBpZiAoZXZlbnQuY29kZSA9PT0gJ0VudGVyJyAmJiB0aGlzLnNlYXJjaEZ1bmN0aW9uKSB7XG4gICAgICAgICAgICB0aGlzLnNlYXJjaEZ1bmN0aW9uKCk7XG4gICAgICAgIH0gZWxzZSBpZiAoZXZlbnQuY29kZSA9PT0gJ0Fycm93RG93bicpIHtcbiAgICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICBpZiAodGhpcy5tZW51SXRlbXMgJiYgdGhpcy5tZW51SXRlbXMuZmlyc3QpIHtcbiAgICAgICAgICAgICAgICB0aGlzLm1lbnVJdGVtcy5maXJzdC5mb2N1cygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqIEBoaWRkZW4gKi9cbiAgICBvbklucHV0S2V5dXBIYW5kbGVyKCkge1xuICAgICAgICBpZiAodGhpcy5pbnB1dFRleHQgJiYgdGhpcy5pbnB1dFRleHQubGVuZ3RoKSB7XG4gICAgICAgICAgICB0aGlzLmlzT3BlbiA9IHRydWU7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKiogQGhpZGRlbiAqL1xuICAgIG9uTWVudUtleWRvd25IYW5kbGVyKGV2ZW50OiBLZXlib2FyZEV2ZW50LCBpbmRleDogbnVtYmVyKSB7XG4gICAgICAgIHRoaXMubWVudUtleWJvYXJkU2VydmljZS5rZXlEb3duSGFuZGxlcihldmVudCwgaW5kZXgsIHRoaXMubWVudUl0ZW1zLnRvQXJyYXkoKSk7XG4gICAgfVxuXG4gICAgLyoqIEBoaWRkZW4gKi9cbiAgICBvbk1lbnVDbGlja0hhbmRsZXIoaW5kZXg6IG51bWJlcikge1xuICAgICAgICBjb25zdCBzZWxlY3RlZEl0ZW0gPSB0aGlzLmRpc3BsYXllZFZhbHVlc1tpbmRleF07XG4gICAgICAgIGlmIChzZWxlY3RlZEl0ZW0pIHtcbiAgICAgICAgICAgIHRoaXMuaGFuZGxlQ2xpY2tBY3Rpb25zKHNlbGVjdGVkSXRlbSk7XG4gICAgICAgICAgICB0aGlzLml0ZW1DbGlja2VkLmVtaXQoeyBpdGVtOiBzZWxlY3RlZEl0ZW0sIGluZGV4OiBpbmRleCB9KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKiBHZXQgdGhlIGlucHV0IHRleHQgb2YgdGhlIGlucHV0LiAqL1xuICAgIGdldCBpbnB1dFRleHQoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmlucHV0VGV4dFZhbHVlO1xuICAgIH1cblxuICAgIC8qKiBTZXQgdGhlIGlucHV0IHRleHQgb2YgdGhlIGlucHV0LiAqL1xuICAgIHNldCBpbnB1dFRleHQodmFsdWUpIHtcbiAgICAgICAgdGhpcy5pbnB1dFRleHRWYWx1ZSA9IHZhbHVlO1xuICAgICAgICB0aGlzLm9uQ2hhbmdlKHZhbHVlKTtcbiAgICAgICAgdGhpcy5vblRvdWNoZWQoKTtcbiAgICB9XG5cbiAgICAvKiogQGhpZGRlbiAqL1xuICAgIHdyaXRlVmFsdWUodmFsdWU6IGFueSkge1xuICAgICAgICB0aGlzLmlucHV0VGV4dFZhbHVlID0gdmFsdWU7XG4gICAgfVxuXG4gICAgLyoqIEBoaWRkZW4gKi9cbiAgICByZWdpc3Rlck9uQ2hhbmdlKGZuKSB7XG4gICAgICAgIHRoaXMub25DaGFuZ2UgPSBmbjtcbiAgICB9XG5cbiAgICAvKiogQGhpZGRlbiAqL1xuICAgIHJlZ2lzdGVyT25Ub3VjaGVkKGZuKSB7XG4gICAgICAgIHRoaXMub25Ub3VjaGVkID0gZm47XG4gICAgfVxuXG4gICAgLyoqIEBoaWRkZW4gKi9cbiAgICBoYW5kbGVTZWFyY2hUZXJtQ2hhbmdlKCk6IHZvaWQge1xuICAgICAgICB0aGlzLmRpc3BsYXllZFZhbHVlcyA9IHRoaXMuZmlsdGVyRm4odGhpcy5kcm9wZG93blZhbHVlcywgdGhpcy5pbnB1dFRleHQpO1xuICAgIH1cblxuICAgIC8qKiBAaGlkZGVuICovXG4gICAgb25QcmltYXJ5QnV0dG9uQ2xpY2soKTogdm9pZCB7XG4gICAgICAgIGlmICh0aGlzLnNlYXJjaEZ1bmN0aW9uKSB7XG4gICAgICAgICAgICB0aGlzLnNlYXJjaEZ1bmN0aW9uKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKiogQGhpZGRlbiAqL1xuICAgIHNldERpc2FibGVkU3RhdGUoaXNEaXNhYmxlZDogYm9vbGVhbik6IHZvaWQge1xuICAgICAgICB0aGlzLmRpc2FibGVkID0gaXNEaXNhYmxlZDtcbiAgICB9XG5cbiAgICBwcml2YXRlIGRlZmF1bHREaXNwbGF5KHN0cjogYW55KTogc3RyaW5nIHtcbiAgICAgICAgcmV0dXJuIHN0cjtcbiAgICB9XG5cbiAgICBwcml2YXRlIGRlZmF1bHRGaWx0ZXIoY29udGVudEFycmF5OiBhbnlbXSwgc2VhcmNoVGVybTogc3RyaW5nKTogYW55W10ge1xuICAgICAgICBjb25zdCBzZWFyY2hMb3dlciA9IHNlYXJjaFRlcm0udG9Mb2NhbGVMb3dlckNhc2UoKTtcbiAgICAgICAgcmV0dXJuIGNvbnRlbnRBcnJheS5maWx0ZXIoaXRlbSA9PiB7XG4gICAgICAgICAgICBpZiAoaXRlbSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmRpc3BsYXlGbihpdGVtKS50b0xvY2FsZUxvd2VyQ2FzZSgpLmluY2x1ZGVzKHNlYXJjaExvd2VyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBoYW5kbGVDbGlja0FjdGlvbnModGVybSk6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy5jbG9zZU9uU2VsZWN0KSB7XG4gICAgICAgICAgICB0aGlzLmlzT3BlbiA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLmZpbGxPblNlbGVjdCkge1xuICAgICAgICAgICAgdGhpcy5pbnB1dFRleHQgPSB0aGlzLmRpc3BsYXlGbih0ZXJtKTtcbiAgICAgICAgICAgIHRoaXMuaGFuZGxlU2VhcmNoVGVybUNoYW5nZSgpO1xuICAgICAgICB9XG4gICAgfVxuXG59XG4iXX0=