@hxui/angular
Version:
An Angular library based on the [HXUI design system](https://hxui.io).
521 lines • 71.1 kB
JavaScript
import { Overlay } from '@angular/cdk/overlay';
import { ComponentPortal } from '@angular/cdk/portal';
import { Directive, ElementRef, EventEmitter, HostListener, Input, NgZone, Output, TemplateRef, ViewContainerRef } from '@angular/core';
import { NgControl } from '@angular/forms';
import { from, Observable, Subject } from 'rxjs';
import { debounceTime, filter, mergeMap, take, takeUntil, toArray } from 'rxjs/operators';
import { TypeaheadContainerComponent } from './typeahead-container.component';
import { TypeaheadMatch } from './typeahead-match.class';
import { getValueFromObject, latinize, tokenize } from './typeahead-utils';
import * as i0 from "@angular/core";
import * as i1 from "@angular/forms";
import * as i2 from "@angular/cdk/overlay";
export class TypeaheadDirective {
constructor(ngControl, overlay, _ngZone, _elementRef, _viewContainerRef) {
this.ngControl = ngControl;
this.overlay = overlay;
this._ngZone = _ngZone;
this._elementRef = _elementRef;
this._viewContainerRef = _viewContainerRef;
/** 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;
/** break words with spaces. If true the text "exact phrase" here match would match with match exact phrase here but not with phrase here exact match (kind of "google style"). */
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 = '\'"';
this.offsetY = 0;
this.offsetX = 0;
this.placement = 'bottom';
this.maxHeight = '20rem';
/** 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 occurres. returns the active item */
this.typeaheadOnBlur = new EventEmitter();
this.isTypeaheadOptionsListActive = false;
this.keyUpEventEmitter = new EventEmitter();
this._destroyed = new Subject();
}
onChange(e) {
if (this._typeaheadInstance) {
// up
if (e.key === 'ArrowUp') {
this._typeaheadInstance.prevActiveMatch();
return;
}
// down
if (e.key === 'ArrowDown') {
this._typeaheadInstance.nextActiveMatch();
return;
}
// enter
if (e.key === 'Enter') {
this._typeaheadInstance.selectActiveMatch();
return;
}
}
// For `<input>`s, use the `value` property. For others that don't have a
// `value` (such as `<span contenteditable="true">`, use `innerText`.
const value = e.target.value !== undefined ? e.target.value : e.target.innerText;
if (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();
}
}
onFocus() {
if (this.typeaheadMinLength === 0) {
this.typeaheadLoading.emit(true);
this.keyUpEventEmitter.emit('');
}
}
onBlur() {
if (this._typeaheadInstance && !this._typeaheadInstance.isFocused) {
this.typeaheadOnBlur.emit(this._typeaheadInstance.active);
this.hide();
}
}
onKeydown(e) {
// no container - no problems
if (!this._typeaheadInstance) {
return;
}
// if items is visible - prevent form submition
if (e.keyCode === 13) {
e.preventDefault();
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 &&
!(this.hxaTypeahead instanceof Observable)) {
this.typeaheadAsync = false;
}
if (this.hxaTypeahead instanceof Observable) {
this.typeaheadAsync = true;
}
if (this.typeaheadAsync) {
this.asyncActions();
}
else {
this.syncActions();
}
}
changeModel(match) {
const valueStr = match.value;
this.ngControl.viewToModelUpdate(valueStr);
this.ngControl.control.setValue(valueStr);
this.hide();
}
get matches() {
return this._matches;
}
show(delay = 0) {
if (this.disabled) {
return;
}
const overlayRef = this._createOverlay();
this._detach();
this._portal =
this._portal ||
new ComponentPortal(TypeaheadContainerComponent, this._viewContainerRef);
this._typeaheadInstance = overlayRef.attach(this._portal).instance;
this._typeaheadInstance
.afterHidden()
.pipe(takeUntil(this._destroyed))
.subscribe(() => this._detach());
this._updateContainer();
this._setWidthsRelativeTo(overlayRef);
this._typeaheadInstance.show(delay);
this._elementRef.nativeElement.focus();
}
hide() {
this._hide();
}
_hide(delay = 0) {
if (this._typeaheadInstance) {
this._typeaheadInstance.hide(delay);
}
}
ngOnDestroy() {
if (this._overlayRef) {
this._overlayRef.dispose();
this._typeaheadInstance = null;
}
this._destroyed.next(true);
this._destroyed.complete();
}
asyncActions() {
this.keyUpEventEmitter
.pipe(debounceTime(this.typeaheadWaitMs), mergeMap(() => this.hxaTypeahead))
.subscribe((matches) => {
this.finalizeAsyncCall(matches);
}, (err) => {
console.error(err);
});
}
syncActions() {
this.keyUpEventEmitter
.pipe(debounceTime(this.typeaheadWaitMs), mergeMap((value) => {
const normalizedQuery = this.normalizeQuery(value);
return from(this.hxaTypeahead).pipe(filter((option) => {
return (option &&
this.testMatch(this.normalizeOption(option), normalizedQuery));
}), toArray());
}))
.subscribe((matches) => {
this.finalizeAsyncCall(matches);
}, (err) => {
console.error(err);
});
}
normalizeOption(option) {
const optionValue = getValueFromObject(option, this.typeaheadOptionField);
const normalizedOption = this.typeaheadLatinize
? latinize(optionValue)
: optionValue;
return normalizedOption.toLowerCase();
}
normalizeQuery(value) {
// If singleWords, break model here to not be doing extra work on each
// iteration
let normalizedQuery = (this.typeaheadLatinize ? latinize(value) : value)
.toString()
.toLowerCase();
normalizedQuery = this.typeaheadSingleWords
? tokenize(normalizedQuery, this.typeaheadWordDelimiters, this.typeaheadPhraseDelimiters)
: normalizedQuery;
return normalizedQuery;
}
testMatch(match, test) {
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;
}
else {
return match.indexOf(test) >= 0;
}
}
finalizeAsyncCall(matches) {
this.prepareMatches(matches);
this.typeaheadLoading.emit(false);
this.typeaheadNoResults.emit(!this.hasMatches());
if (!this.hasMatches()) {
this.hide();
return;
}
if (this._typeaheadInstance) {
this._updateContainer();
}
else {
this.show();
}
}
prepareMatches(options) {
const limited = options.slice(0, this.typeaheadOptionsLimit);
if (this.typeaheadGroupField) {
let matches = [];
// extract all group names
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((option) => getValueFromObject(option, this.typeaheadGroupField) === group)
.map((option) => new TypeaheadMatch(option, getValueFromObject(option, this.typeaheadOptionField))));
});
this._matches = matches;
}
else {
this._matches = limited.map((option) => new TypeaheadMatch(option, getValueFromObject(option, this.typeaheadOptionField)));
}
}
hasMatches() {
return this._matches.length > 0;
}
_createOverlay() {
if (this._overlayRef) {
return this._overlayRef;
}
const positionStrategy = this.overlay
.position()
.flexibleConnectedTo(this._elementRef)
.withFlexibleDimensions(false)
.withDefaultOffsetX(this.offsetX)
.withDefaultOffsetY(this.offsetY)
.withPositions([
{ originX: 'start', originY: 'top', overlayX: 'start', overlayY: 'top' }
])
.withTransformOriginOn('.hxa-dropdown-control');
this._overlayRef = this.overlay.create({
positionStrategy: positionStrategy,
panelClass: [
'hxui-reset',
'hxa-dropdown-panel',
'is-open',
'is-fluid-min-width'
],
hasBackdrop: true,
backdropClass: 'cdk-overlay-transparent-backdrop'
});
this._updatePosition();
this._overlayRef
.detachments()
.pipe(takeUntil(this._destroyed))
.subscribe(() => this._detach());
this._overlayRef.backdropClick().subscribe(() => this.hide());
const position = this._overlayRef.getConfig()
.positionStrategy;
position.positionChanges.pipe(takeUntil(this._destroyed)).subscribe(pos => {
if (pos.connectionPair.originX === 'start') {
this.placement = 'left';
}
else if (pos.connectionPair.originX === 'end') {
this.placement = 'right';
}
else if (pos.connectionPair.originY === 'top') {
this.placement = 'top';
}
else if (pos.connectionPair.originY === 'bottom') {
this.placement = 'bottom';
}
});
return this._overlayRef;
}
_setWidthsRelativeTo(overlayRef) {
if (this.maxWidthRelativeTo && this.minWidthRelativeTo) {
const elem = document.getElementById(this.maxWidthRelativeTo);
overlayRef.updateSize({
minWidth: elem.clientWidth,
maxWidth: elem.clientWidth,
maxHeight: this.maxHeight
});
}
else if (this.maxWidthRelativeTo) {
const elem = document.getElementById(this.maxWidthRelativeTo);
overlayRef.updateSize({
maxWidth: elem.clientWidth,
maxHeight: this.maxHeight
});
}
else if (this.minWidthRelativeTo) {
const elem = document.getElementById(this.minWidthRelativeTo);
overlayRef.updateSize({
minWidth: elem.clientWidth,
maxHeight: this.maxHeight
});
}
else {
overlayRef.updateSize({ maxHeight: this.maxHeight });
}
}
_updatePosition() {
const position = this._overlayRef.getConfig()
.positionStrategy;
const origin = this._getOrigin();
const overlay = this._getOverlayPosition();
position.withPositions([
{ ...origin.main, ...overlay.main },
{ ...origin.fallback, ...overlay.fallback }
]);
}
/**
* Returns the origin position and a fallback position based on the user's position preference.
* The fallback position is the inverse of the origin (e.g. `'bottom' -> 'top'`).
*/
_getOrigin() {
const placement = this.placement;
let originPlacement;
if (placement === 'top' || placement === 'bottom') {
originPlacement = {
originX: 'center',
originY: placement === 'top' ? 'top' : 'bottom'
};
}
else if (placement === 'left') {
originPlacement = { originX: 'start', originY: 'center' };
}
else if (placement === 'right') {
originPlacement = { originX: 'end', originY: 'center' };
}
else {
console.error('Position error', placement);
}
const { x, y } = this._invertPosition(originPlacement.originX, originPlacement.originY);
return {
main: originPlacement,
fallback: { originX: x, originY: y }
};
}
/** Returns the overlay position and a fallback position based on the user's preference */
_getOverlayPosition() {
const placement = this.placement;
let overlayPlacement;
if (placement === 'top') {
overlayPlacement = { overlayX: 'center', overlayY: 'bottom' };
}
else if (placement === 'bottom') {
overlayPlacement = { overlayX: 'center', overlayY: 'top' };
}
else if (placement === 'left') {
overlayPlacement = { overlayX: 'end', overlayY: 'center' };
}
else if (placement === 'right') {
overlayPlacement = { overlayX: 'start', overlayY: 'center' };
}
else {
console.error('Could not find a position', placement);
}
const { x, y } = this._invertPosition(overlayPlacement.overlayX, overlayPlacement.overlayY);
return {
main: overlayPlacement,
fallback: { overlayX: x, overlayY: y }
};
}
_invertPosition(x, y) {
if (this.placement === 'top' || this.placement === 'bottom') {
if (y === 'top') {
y = 'bottom';
}
else if (y === 'bottom') {
y = 'top';
}
}
else {
if (x === 'end') {
x = 'start';
}
else if (x === 'start') {
x = 'end';
}
}
return { x, y };
}
_detach() {
if (this._overlayRef && this._overlayRef.hasAttached()) {
this._overlayRef.detach();
}
this._typeaheadInstance = null;
}
/** Updates the container and repositions the overlay according to the new content length */
_updateContainer() {
// Must wait for the content to be painted to the container so that the overlay can properly
// calculate the correct positioning based on the size of its contents.
if (this._typeaheadInstance) {
this._typeaheadInstance.parent = this;
this._typeaheadInstance.placement = this.placement;
const normalizedQuery = (this.typeaheadLatinize
? latinize(this.ngControl.control.value)
: this.ngControl.control.value)
.toString()
.toLowerCase();
this._typeaheadInstance.query = this.typeaheadSingleWords
? tokenize(normalizedQuery, this.typeaheadWordDelimiters, this.typeaheadPhraseDelimiters)
: normalizedQuery;
this._typeaheadInstance.matches = this._matches;
//this._typeaheadInstance.maxWidth = this.maxWidth;
this._ngZone.onMicrotaskEmpty
.asObservable()
.pipe(take(1), takeUntil(this._destroyed))
.subscribe(() => {
if (this._typeaheadInstance) {
this._overlayRef.updatePosition();
}
});
}
}
}
TypeaheadDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: TypeaheadDirective, deps: [{ token: i1.NgControl }, { token: i2.Overlay }, { token: i0.NgZone }, { token: i0.ElementRef }, { token: i0.ViewContainerRef }], target: i0.ɵɵFactoryTarget.Directive });
TypeaheadDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.3.11", type: TypeaheadDirective, selector: "[hxaTypeahead]", inputs: { hxaTypeahead: "hxaTypeahead", typeaheadMinLength: "typeaheadMinLength", typeaheadWaitMs: "typeaheadWaitMs", typeaheadOptionsLimit: "typeaheadOptionsLimit", typeaheadOptionField: "typeaheadOptionField", typeaheadGroupField: "typeaheadGroupField", typeaheadAsync: "typeaheadAsync", typeaheadLatinize: "typeaheadLatinize", typeaheadSingleWords: "typeaheadSingleWords", typeaheadWordDelimiters: "typeaheadWordDelimiters", typeaheadPhraseDelimiters: "typeaheadPhraseDelimiters", typeaheadItemTemplate: "typeaheadItemTemplate", optionsListTemplate: "optionsListTemplate", disabled: "disabled", offsetY: "offsetY", offsetX: "offsetX", placement: "placement", maxWidthRelativeTo: "maxWidthRelativeTo", minWidthRelativeTo: "minWidthRelativeTo", maxHeight: "maxHeight" }, outputs: { typeaheadLoading: "typeaheadLoading", typeaheadNoResults: "typeaheadNoResults", typeaheadOnSelect: "typeaheadOnSelect", typeaheadOnBlur: "typeaheadOnBlur" }, host: { listeners: { "keyup": "onChange($event)", "focus": "onFocus()", "blur": "onBlur()", "keydown": "onKeydown($event)" } }, exportAs: ["hx-typeahead"], ngImport: i0 });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: TypeaheadDirective, decorators: [{
type: Directive,
args: [{ selector: '[hxaTypeahead]', exportAs: 'hx-typeahead' }]
}], ctorParameters: function () { return [{ type: i1.NgControl }, { type: i2.Overlay }, { type: i0.NgZone }, { type: i0.ElementRef }, { type: i0.ViewContainerRef }]; }, propDecorators: { hxaTypeahead: [{
type: Input
}], typeaheadMinLength: [{
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
}], disabled: [{
type: Input
}], offsetY: [{
type: Input
}], offsetX: [{
type: Input
}], placement: [{
type: Input
}], maxWidthRelativeTo: [{
type: Input
}], minWidthRelativeTo: [{
type: Input
}], maxHeight: [{
type: Input
}], typeaheadLoading: [{
type: Output
}], typeaheadNoResults: [{
type: Output
}], typeaheadOnSelect: [{
type: Output
}], typeaheadOnBlur: [{
type: Output
}], onChange: [{
type: HostListener,
args: ['keyup', ['$event']]
}], onFocus: [{
type: HostListener,
args: ['focus']
}], onBlur: [{
type: HostListener,
args: ['blur']
}], onKeydown: [{
type: HostListener,
args: ['keydown', ['$event']]
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZWFoZWFkLmRpcmVjdGl2ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2h4LXVpL3NyYy9saWIvdHlwZWFoZWFkL3R5cGVhaGVhZC5kaXJlY3RpdmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUlMLE9BQU8sRUFJUixNQUFNLHNCQUFzQixDQUFDO0FBQzlCLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUN0RCxPQUFPLEVBQ0wsU0FBUyxFQUNULFVBQVUsRUFDVixZQUFZLEVBQ1osWUFBWSxFQUNaLEtBQUssRUFDTCxNQUFNLEVBR04sTUFBTSxFQUNOLFdBQVcsRUFDWCxnQkFBZ0IsRUFDakIsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFlLFNBQVMsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ3hELE9BQU8sRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLE9BQU8sRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUNqRCxPQUFPLEVBQ0wsWUFBWSxFQUNaLE1BQU0sRUFDTixRQUFRLEVBQ1IsSUFBSSxFQUNKLFNBQVMsRUFDVCxPQUFPLEVBQ1IsTUFBTSxnQkFBZ0IsQ0FBQztBQUN4QixPQUFPLEVBQUUsMkJBQTJCLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUM5RSxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDekQsT0FBTyxFQUFFLGtCQUFrQixFQUFFLFFBQVEsRUFBRSxRQUFRLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQzs7OztBQUczRSxNQUFNLE9BQU8sa0JBQWtCO0lBdUk3QixZQUNTLFNBQW9CLEVBQ3BCLE9BQWdCLEVBQ2YsT0FBZSxFQUNmLFdBQXVCLEVBQ3ZCLGlCQUFtQztRQUpwQyxjQUFTLEdBQVQsU0FBUyxDQUFXO1FBQ3BCLFlBQU8sR0FBUCxPQUFPLENBQVM7UUFDZixZQUFPLEdBQVAsT0FBTyxDQUFRO1FBQ2Ys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LFlBQVk7c0JBQTNCLEtBQUs7Z0JBRVUsa0JBQWtCO3NCQUFqQyxLQUFLO2dCQUVVLGVBQWU7c0JBQTlCLEtBQUs7Z0JBRVUscUJBQXFCO3NCQUFwQyxLQUFLO2dCQUVVLG9CQUFvQjtzQkFBbkMsS0FBSztnQkFFVSxtQkFBbUI7c0JBQWxDLEtBQUs7Z0JBRVUsY0FBYztzQkFBN0IsS0FBSztnQkFFVSxpQkFBaUI7c0JBQWhDLEtBQUs7Z0JBRVUsb0JBQW9CO3NCQUFuQyxLQUFLO2dCQUVVLHVCQUF1QjtzQkFBdEMsS0FBSztnQkFFVSx5QkFBeUI7c0JBQXhDLEtBQUs7Z0JBRVUscUJBQXFCO3NCQUFwQyxLQUFLO2dCQUVVLG1CQUFtQjtzQkFBbEMsS0FBSztnQkFHTixRQUFRO3NCQURQLEtBQUs7Z0JBSU4sT0FBTztzQkFETixLQUFLO2dCQUlOLE9BQU87c0JBRE4sS0FBSztnQkFJTixTQUFTO3NCQURSLEtBQUs7Z0JBSU4sa0JBQWtCO3NCQURqQixLQUFLO2dCQUlOLGtCQUFrQjtzQkFEakIsS0FBSztnQkFJTixTQUFTO3NCQURSLEtBQUs7Z0JBSVcsZ0JBQWdCO3NCQUFoQyxNQUFNO2dCQUVVLGtCQUFrQjtzQkFBbEMsTUFBTTtnQkFHVSxpQkFBaUI7c0JBQWpDLE1BQU07Z0JBR1UsZUFBZTtzQkFBL0IsTUFBTTtnQkFZQSxRQUFRO3NCQURkLFlBQVk7dUJBQUMsT0FBTyxFQUFFLENBQUMsUUFBUSxDQUFDO2dCQXFDMUIsT0FBTztzQkFEYixZQUFZO3VCQUFDLE9BQU87Z0JBU2QsTUFBTTtzQkFEWixZQUFZO3VCQUFDLE1BQU07Z0JBU2IsU0FBUztzQkFEZixZQUFZO3VCQUFDLFNBQVMsRUFBRSxDQUFDLFFBQVEsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XHJcbiAgRmxleGlibGVDb25uZWN0ZWRQb3NpdGlvblN0cmF0ZWd5LFxyXG4gIEhvcml6b250YWxDb25uZWN0aW9uUG9zLFxyXG4gIE9yaWdpbkNvbm5lY3Rpb25Qb3NpdGlvbixcclxuICBPdmVybGF5LFxyXG4gIE92ZXJsYXlDb25uZWN0aW9uUG9zaXRpb24sXHJcbiAgT3ZlcmxheVJlZixcclxuICBWZXJ0aWNhbENvbm5lY3Rpb25Qb3NcclxufSBmcm9tICdAYW5ndWxhci9jZGsvb3ZlcmxheSc7XHJcbmltcG9ydCB7IENvbXBvbmVudFBvcnRhbCB9IGZyb20gJ0Bhbmd1bGFyL2Nkay9wb3J0YWwnO1xyXG5pbXBvcnQge1xyXG4gIERpcmVjdGl2ZSxcclxuICBFbGVtZW50UmVmLFxyXG4gIEV2ZW50RW1pdHRlcixcclxuICBIb3N0TGlzdGVuZXIsXHJcbiAgSW5wdXQsXHJcbiAgTmdab25lLFxyXG4gIE9uRGVzdHJveSxcclxuICBPbkluaXQsXHJcbiAgT3V0cHV0LFxyXG4gIFRlbXBsYXRlUmVmLFxyXG4gIFZpZXdDb250YWluZXJSZWZcclxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgRm9ybUNvbnRyb2wsIE5nQ29udHJvbCB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcclxuaW1wb3J0IHsgZnJvbSwgT2JzZXJ2YWJsZSwgU3ViamVjdCB9IGZyb20gJ3J4anMnO1xyXG5pbXBvcnQge1xyXG4gIGRlYm91bmNlVGltZSxcclxuICBmaWx0ZXIsXHJcbiAgbWVyZ2VNYXAsXHJcbiAgdGFrZSxcclxuICB0YWtlVW50aWwsXHJcbiAgdG9BcnJheVxyXG59IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcclxuaW1wb3J0IHsgVHlwZWFoZWFkQ29udGFpbmVyQ29tcG9uZW50IH0gZnJvbSAnLi90eXBlYWhlYWQtY29udGFpbmVyLmNvbXBvbmVudCc7XHJcbmltcG9ydCB7IFR5cGVhaGVhZE1hdGNoIH0gZnJvbSAnLi90eXBlYWhlYWQtbWF0Y2guY2xhc3MnO1xyXG5pbXBvcnQgeyBnZXRWYWx1ZUZyb21PYmplY3QsIGxhdGluaXplLCB0b2tlbml6ZSB9IGZyb20gJy4vdHlwZWFoZWFkLXV0aWxzJztcclxuXHJcbkBEaXJlY3RpdmUoeyBzZWxlY3RvcjogJ1toeGFUeXBlYWhlYWRdJywgZXhwb3J0QXM6ICdoeC10eXBlYWhlYWQnIH0pXHJcbmV4cG9ydCBjbGFzcyBUeXBlYWhlYWREaXJlY3RpdmUgaW1wbGVtZW50cyBPbkluaXQsIE9uRGVzdHJveSB7XHJcbiAgLyoqIG9wdGlvbnMgc291cmNlLCBjYW4gYmUgQXJyYXkgb2Ygc3RyaW5ncywgb2JqZWN0cyBvciBhbiBPYnNlcnZhYmxlIGZvciBleHRlcm5hbCBtYXRjaGluZyBwcm9jZXNzICovXHJcbiAgQElucHV0KCkgcHVibGljIGh4YVR5cGVhaGVhZDogYW55O1xyXG4gIC8qKiBtaW5pbWFsIG5vIG9mIGNoYXJhY3RlcnMgdGhhdCBuZWVkcyB0byBiZSBlbnRlcmVkIGJlZm9yZSB0eXBlYWhlYWQga2lja3MtaW4uIFdoZW4gc2V0IHRvIDAsIHR5cGVhaGVhZCBzaG93cyBvbiBmb2N1cyB3aXRoIGZ1bGwgbGlzdCBvZiBvcHRpb25zIChsaW1pdGVkIGFzIG5vcm1hbCBieSB0eXBlYWhlYWRPcHRpb25zTGltaXQpICovXHJcbiAgQElucHV0KCkgcHVibGljIHR5cGVhaGVhZE1pbkxlbmd0aDogbnVtYmVyID0gdm9pZCAwO1xyXG4gIC8qKiBtaW5pbWFsIHdhaXQgdGltZSBhZnRlciBsYXN0IGNoYXJhY3RlciB0eXBlZCBiZWZvcmUgdHlwZWFoZWFkIGtpY2tzLWluICovXHJcbiAgQElucHV0KCkgcHVibGljIHR5cGVhaGVhZFdhaXRNczogbnVtYmVyO1xyXG4gIC8qKiBtYXhpbXVtIGxlbmd0aCBvZiBvcHRpb25zIGl0ZW1zIGxpc3QgKi9cclxuICBASW5wdXQoKSBwdWJsaWMgdHlwZWFoZWFkT3B0aW9uc0xpbWl0OiBudW1iZXI7XHJcbiAgLyoqIHdoZW4gb3B0aW9ucyBzb3VyY2UgaXMgYW4gYXJyYXkgb2Ygb2JqZWN0cywgdGhlIG5hbWUgb2YgZmllbGQgdGhhdCBjb250YWlucyB0aGUgb3B0aW9ucyB2YWx1ZSwgd2UgdXNlIGFycmF5IGl0ZW0gYXMgb3B0aW9uIGluIGNhc2Ugb2YgdGhpcyBmaWVsZCBpcyBtaXNzaW5nLiBTdXBwb3J0cyBuZXN0ZWQgcHJvcGVydGllcyBhbmQgbWV0aG9kcy4gKi9cclxuICBASW5wdXQoKSBwdWJsaWMgdHlwZWFoZWFkT3B0aW9uRmllbGQ6IHN0cmluZztcclxuICAvKiogd2hlbiBvcHRpb25zIHNvdXJjZSBpcyBhbiBhcnJheSBvZiBvYmplY3RzLCB0aGUgbmFtZSBvZiBmaWVsZCB0aGF0IGNvbnRhaW5zIHRoZSBncm91cCB2YWx1ZSwgbWF0Y2hlcyBhcmUgZ3JvdXBlZCBieSB0aGlzIGZpZWxkIHdoZW4gc2V0LiAqL1xyXG4gIEBJbnB1dCgpIHB1YmxpYyB0eXBlYWhlYWRHcm91cEZpZWxkOiBzdHJpbmc7XHJcbiAgLyoqIHNob3VsZCBiZSB1c2VkIG9ubHkgaW4gY2FzZSBvZiB0eXBlYWhlYWQgYXR0cmlidXRlIGlzIGFycmF5LiBJZiB0cnVlIC0gbG9hZGluZyBvZiBvcHRpb25zIHdpbGwgYmUgYXN5bmMsIG90aGVyd2lzZSAtIHN5bmMuIHRydWUgbWFrZSBzZW5zZSBpZiBvcHRpb25zIGFycmF5IGlzIGxhcmdlLiAqL1xyXG4gIEBJbnB1dCgpIHB1YmxpYyB0eXBlYWhlYWRBc3luYzogYm9vbGVhbiA9IHZvaWQgMDtcclxuICAvKiogbWF0Y2ggbGF0aW4gc3ltYm9scy4gSWYgdHJ1ZSB0aGUgd29yZCBzw7pwZXIgd291bGQgbWF0Y2ggc3VwZXIgYW5kIHZpY2UgdmVyc2EuICovXHJcbiAgQElucHV0KCkgcHVibGljIHR5cGVhaGVhZExhdGluaXplID0gdHJ1ZTtcclxuICAvKiogYnJlYWsgd29yZHMgd2l0aCBzcGFjZXMuIElmIHRydWUgdGhlIHRleHQgXCJleGFjdCBwaHJhc2VcIiBoZXJlIG1hdGNoIHdvdWxkIG1hdGNoIHdpdGggbWF0Y2ggZXhhY3QgcGhyYXNlIGhlcmUgYnV0IG5vdCB3aXRoIHBocmFzZSBoZXJlIGV4YWN0IG1hdGNoIChraW5kIG9mIFwiZ29vZ2xlIHN0eWxlXCIpLiAqL1xyXG4gIEBJbnB1dCgpIHB1YmxpYyB0eXBlYWhlYWRTaW5nbGVXb3JkcyA9IHRydWU7XHJcbiAgLyoqIHNob3VsZCBiZSB1c2VkIG9ubHkgaW4gY2FzZSB0eXBlYWhlYWRTaW5nbGVXb3JkcyBhdHRyaWJ1dGUgaXMgdHJ1ZS4gU2V0cyB0aGUgd29yZCBkZWxpbWl0ZXIgdG8gYnJlYWsgd29yZHMuIERlZmF1bHRzIHRvIHNwYWNlLiAqL1xyXG4gIEBJbnB1dCgpIHB1YmxpYyB0eXBlYWhlYWRXb3JkRGVsaW1pdGVycyA9ICcgJztcclxuICAvKiogc2hvdWxkIGJlIHVzZWQgb25seSBpbiBjYXNlIHR5cGVhaGVhZFNpbmdsZVdvcmRzIGF0dHJpYnV0ZSBpcyB0cnVlLiBTZXRzIHRoZSB3b3JkIGRlbGltaXRlciB0byBtYXRjaCBleGFjdCBwaHJhc2UuIERlZmF1bHRzIHRvIHNpbXBsZSBhbmQgZG91YmxlIHF1b3Rlcy4gKi9cclxuICBASW5wdXQoKSBwdWJsaWMgdHlwZWFoZWFkUGhyYXNlRGVsaW1pdGVycyA9ICdcXCdcIic7XHJcbiAgLyoqIHVzZWQgdG8gc3BlY2lmeSBhIGN1c3RvbSBpdGVtIHRlbXBsYXRlLiBUZW1wbGF0ZSB2YXJpYWJsZXMgZXhwb3NlZCBhcmUgY2FsbGVkIGl0ZW0gYW5kIGluZGV4OyAqL1xyXG4gIEBJbnB1dCgpIHB1YmxpYyB0eXBlYWhlYWRJdGVtVGVtcGxhdGU6IFRlbXBsYXRlUmVmPGFueT47XHJcbiAgLyoqIHVzZWQgdG8gc3BlY2lmeSBhIGN1c3RvbSBvcHRpb25zIGxpc3QgdGVtcGxhdGUuIFRlbXBsYXRlIHZhcmlhYmxlczogbWF0Y2hlcywgaXRlbVRlbXBsYXRlLCBxdWVyeSAqL1xyXG4gIEBJbnB1dCgpIHB1YmxpYyBvcHRpb25zTGlzdFRlbXBsYXRlOiBUZW1wbGF0ZVJlZjxhbnk+O1xyXG5cclxuICBASW5wdXQoKVxyXG4gIGRpc2FibGVkOiBib29sZWFuO1xyXG5cclxuICBASW5wdXQoKVxyXG4gIG9mZnNldFkgPSAwO1xyXG5cclxuICBASW5wdXQoKVxyXG4gIG9mZnNldFggPSAwO1xyXG5cclxuICBASW5wdXQoKVxyXG4gIHBsYWNlbWVudDogJ3RvcCcgfCAnYm90dG9tJyB8ICdsZWZ0JyB8ICdyaWdodCcgPSAnYm90dG9tJztcclxuXHJcbiAgQElucHV0KClcclxuICBtYXhXaWR0aFJlbGF0aXZlVG86IHN0cmluZztcclxuXHJcbiAgQElucHV0KClcclxuICBtaW5XaWR0aFJlbGF0aXZlVG86IHN0cmluZztcclxuXHJcbiAgQElucHV0KClcclxuICBtYXhIZWlnaHQgPSAnMjByZW0nO1xyXG5cclxuICAvKiogZmlyZWQgd2hlbiAnYnVzeScgc3RhdGUgb2YgdGhpcyBjb21wb25lbnQgd2FzIGNoYW5nZWQsIGZpcmVkIG9uIGFzeW5jIG1vZGUgb25seSwgcmV0dXJucyBib29sZWFuICovXHJcbiAgQE91dHB1dCgpIHB1YmxpYyB0eXBlYWhlYWRMb2FkaW5nOiBFdmVudEVtaXR0ZXI8Ym9vbGVhbj4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XHJcbiAgLyoqIGZpcmVkIG9uIGV2ZXJ5IGtleSBldmVudCBhbmQgcmV0dXJucyB0cnVlIGluIGNhc2Ugb2YgbWF0Y2hlcyBhcmUgbm90IGRldGVjdGVkICovXHJcbiAgQE91dHB1dCgpIHB1YmxpYyB0eXBlYWhlYWROb1Jlc3VsdHM6IEV2ZW50RW1pdHRlcjxib29sZWFuPiA9XHJcbiAgICBuZXcgRXZlbnRFbWl0dGVyKCk7XHJcbiAgLyoqIGZpcmVkIHdoZW4gb3B0aW9uIHdhcyBzZWxlY3RlZCwgcmV0dXJuIG9iamVjdCB3aXRoIGRhdGEgb2YgdGhpcyBvcHRpb24gKi9cclxuICBAT3V0cHV0KCkgcHVibGljIHR5cGVhaGVhZE9uU2VsZWN0OiBFdmVudEVtaXR0ZXI8VHlwZWFoZWFkTWF0Y2g+ID1cclxuICAgIG5ldyBFdmVudEVtaXR0ZXIoKTtcclxuICAvKiogZmlyZWQgd2hlbiBibHVyIGV2ZW50IG9jY3VycmVzLiByZXR1cm5zIHRoZSBhY3RpdmUgaXRlbSAqL1xyXG4gIEBPdXRwdXQoKSBwdWJsaWMgdHlwZWFoZWFkT25CbHVyOiBFdmVudEVtaXR0ZXI8YW55PiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcclxuXHJcbiAgcHVibGljIGlzVHlwZWFoZWFkT3B0aW9uc0xpc3RBY3RpdmUgPSBmYWxzZTtcclxuXHJcbiAgcHJvdGVjdGVkIGtleVVwRXZlbnRFbWl0dGVyOiBFdmVudEVtaXR0ZXI8YW55PiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcclxuICBwcm90ZWN0ZWQgX21hdGNoZXM6IFR5cGVhaGVhZE1hdGNoW107XHJcbiAgcHJpdmF0ZSBfb3ZlcmxheVJlZjogT3ZlcmxheVJlZiB8IG51bGw7XHJcbiAgcHJpdmF0ZSBfdHlwZWFoZWFkSW5zdGFuY2U6IFR5cGVhaGVhZENvbnRhaW5lckNvbXBvbmVudCB8IG51bGw7XHJcbiAgcHJpdmF0ZSBfcG9ydGFsOiBDb21wb25lbnRQb3J0YWw8VHlwZWFoZWFkQ29udGFpbmVyQ29tcG9uZW50PjtcclxuICBwcml2YXRlIHJlYWRvbmx5IF9kZXN0cm95ZWQgPSBuZXcgU3ViamVjdCgpO1xyXG5cclxuICBASG9zdExpc3RlbmVyKCdrZXl1cCcsIFsnJGV2ZW50J10pXHJcbiAgcHVibGljIG9uQ2hhbmdlKGU6IGFueSk6IHZvaWQge1xyXG4gICAgaWYgKHRoaXMuX3R5cGVhaGVhZEluc3RhbmNlKSB7XHJcbiAgICAgIC8vIHVwXHJcbiAgICAgIGlmIChlLmtleSA9PT0gJ0Fycm93VXAnKSB7XHJcbiAgICAgICAgdGhpcy5fdHlwZWFoZWFkSW5zdGFuY2UucHJldkFjdGl2ZU1hdGNoKCk7XHJcbiAgICAgICAgcmV0dXJuO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAvLyBkb3duXHJcbiAgICAgIGlmIChlLmtleSA9PT0gJ0Fycm93RG93bicpIHtcclxuICAgICAgICB0aGlzLl90eXBlYWhlYWRJbnN0YW5jZS5uZXh0QWN0aXZlTWF0Y2goKTtcclxuICAgICAgICByZXR1cm47XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC8vIGVudGVyXHJcbiAgICAgIGlmIChlLmtleSA9PT0gJ0VudGVyJykge1xyXG4gICAgICAgIHRoaXMuX3R5cGVhaGVhZEluc3RhbmN