UNPKG

@hxui/angular

Version:

An Angular library based on the [HXUI design system](https://hxui.io).

521 lines 71.1 kB
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