ngx-typeahead-search
Version:
399 lines • 29 kB
JavaScript
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
import { Subject, BehaviorSubject } from 'rxjs';
import { startWith, takeUntil } from 'rxjs/operators';
import { Component, Input, ChangeDetectionStrategy, ViewChild, ElementRef, forwardRef, ViewEncapsulation, Output, ChangeDetectorRef, } from '@angular/core';
import { FormControl, NG_VALUE_ACCESSOR } from '@angular/forms';
/** @type {?} */
export const TYPEAHEAD_CONTROL_VALUE_ACCESSOR = {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => NgxTypeaheadComponent),
multi: true,
};
/**
* @template S
*/
export class NgxTypeaheadComponent {
/**
* @param {?} cdRef
*/
constructor(cdRef) {
this.cdRef = cdRef;
/**
* Allow line breaks
*/
this.multiline = false;
/**
* The list of suggestions.
*/
this.suggestions = [];
/**
* The list of keys which will apply suggestion
*/
this.applyingKeys = ['Tab', 'Enter'];
/**
* The part separator
*/
this.partSeparator = ' ';
/**
* The property of a list item that should be used for matching.
*/
this.searchProperty = 'title';
/**
* The property of a list item that should be displayed.
*/
this.displayProperty = this.searchProperty;
/**
* The stream of focus changes
*/
this.focused$ = new BehaviorSubject(false);
this.plainTextControl = new FormControl('');
this.typeaheadContent = null;
this.destroy$ = new Subject();
// -------------------- Control Value Accessor --------------------
/**
* Placeholder for a callback which is later provided by the Control Value Accessor.
*/
this.onTouchedCallback = () => { };
/**
* Placeholder for a callback which is later provided by the Control Value Accessor.
*/
this.onChangeCallback = () => { };
}
/**
* @return {?}
*/
ngOnInit() {
this.plainTextControl.valueChanges
.pipe(startWith(this.plainTextControl.value), takeUntil(this.destroy$))
.subscribe(text => {
this.setWithChangeDetection({ typeaheadContent: this.getTypeahead(text) });
this.onChangeCallback(text);
});
}
/**
* @param {?} changes
* @return {?}
*/
ngOnChanges(changes) {
/** @type {?} */
const suggestions = changes.suggestions && changes.suggestions.currentValue;
if (suggestions) {
this.maxWordsInSuggestionCount = this.getGreatesWordsAmount(suggestions);
}
}
/**
* @return {?}
*/
ngOnDestroy() {
this.destroy$.next();
this.destroy$.complete();
}
/**
* @param {?} e
* @return {?}
*/
handleKeyDown(e) {
if (this.applyingKeys.includes(e.key) && this.typeaheadContent) {
e.preventDefault();
/** @type {?} */
const ok = this.applySuggestion();
if (ok) {
e.stopPropagation();
}
}
}
/**
* @param {?} v
* @return {?}
*/
writeValue(v) {
if (v == null) {
return;
}
this.plainTextControl.setValue(v);
}
/**
* @param {?} fn
* @return {?}
*/
registerOnChange(fn) {
this.onChangeCallback = fn;
}
/**
* @param {?} fn
* @return {?}
*/
registerOnTouched(fn) {
this.onTouchedCallback = fn;
}
/**
* @param {?} isDisabled
* @return {?}
*/
setDisabledState(isDisabled) {
if (isDisabled) {
this.plainTextControl.disable();
}
else {
this.plainTextControl.enable();
}
}
// -------------------- Control Value Accessor --------------------
/**
* Return suggestion completion
* @param {?=} input
* @return {?}
*/
getTypeahead(input) {
if (!input) {
return null;
}
/** @type {?} */
const chunks = input.split(this.partSeparator);
/** @type {?} */
let chunk;
/** @type {?} */
let suggestion;
for (let i = 1; i <= this.maxWordsInSuggestionCount; i++) {
chunk = chunks.slice(chunks.length - i).join(' ');
suggestion = this.getSuggestion(chunk);
if (suggestion) {
break;
}
}
if (document.activeElement !== this.plainTextElRef.nativeElement ||
!suggestion ||
chunk.length === suggestion[this.displayProperty]) {
return null;
}
/** @type {?} */
const displayValue = this.getDisplayValue(suggestion);
return [input.substr(0, input.length), displayValue.substr(chunk.length)];
}
/**
* Return appropriate suggestion or null
* @private
* @param {?} text
* @return {?}
*/
getSuggestion(text) {
/** @type {?} */
const query = text.replace(/\s/g, () => ' ');
if (!query) {
return null;
}
try {
/** @type {?} */
const searchRegExp = new RegExp(`^${query}.*`, 'i');
return this.suggestions.find(item => searchRegExp.test(this.getSearchValue(item))) || null;
}
catch (e) {
return null;
}
}
/**
* @private
* @param {?} item
* @return {?}
*/
getSearchValue(item) {
try {
return typeof item === 'string' ? item : item[this.searchProperty];
}
catch (e) {
throw Error(`Suggestion should be string or contains searchProperty. You can set it as Input [searchProperty].`);
}
}
/**
* @private
* @param {?} item
* @return {?}
*/
getDisplayValue(item) {
try {
return typeof item === 'string' ? item : item[this.displayProperty];
}
catch (e) {
throw Error(`Suggestion should be string or contains displayProperty. You can set it as Input [displayProperty].`);
}
}
/**
* Replace text content part and ahead text on suggestion
* @private
* @return {?}
*/
applySuggestion() {
/** @type {?} */
const plainText = this.plainTextControl.value;
/** @type {?} */
const typeahead = this.getTypeahead(plainText);
if (!typeahead) {
return false;
}
this.plainTextControl.setValue(typeahead[0] + typeahead[1]);
return true;
}
/**
* @private
* @param {?} items
* @return {?}
*/
getGreatesWordsAmount(items) {
return items.reduce((result, item) => {
/** @type {?} */
const count = this.getSearchValue(item).split(this.partSeparator).length;
return count > result ? count : result;
}, 0);
}
/**
* @private
* @param {?} data
* @return {?}
*/
setWithChangeDetection(data) {
Object.assign(this, data);
this.cdRef.detectChanges();
}
}
NgxTypeaheadComponent.decorators = [
{ type: Component, args: [{
selector: ' ngx-typeahead',
template: `
<div class="ngx-typeahead">
<input
#plainText
type="text"
class="ngx-plain-content text"
[placeholder]="placeholder"
[formControl]="plainTextControl"
(focus)="focused$.next(true)"
(blur)="focused$.next(false)"
(keydown)="handleKeyDown($event)"
/>
<p #typeahead class="ngx-typeahead-content">
<ng-container *ngIf="typeaheadContent">
<span [style.visibility]="(focused$ | async) ? 'visible' : 'hidden'" class="text">{{ typeaheadContent[0] }}</span
><span class="text">{{ typeaheadContent[1] }}</span>
</ng-container>
</p>
</div>
`,
providers: [TYPEAHEAD_CONTROL_VALUE_ACCESSOR],
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None,
styles: [`
.ngx-typeahead {
position: relative;
width: 100%;
height: 100%;
cursor: text;
}
.ngx-plain-content {
white-space: nowrap;
overflow: hidden;
outline: none;
-webkit-appearance: none;
padding: 8px 8px;
}
.ngx-typeahead-content {
position: absolute;
color: gray;
margin: 0;
}
`]
}] }
];
/** @nocollapse */
NgxTypeaheadComponent.ctorParameters = () => [
{ type: ChangeDetectorRef }
];
NgxTypeaheadComponent.propDecorators = {
multiline: [{ type: Input }],
suggestions: [{ type: Input }],
placeholder: [{ type: Input }],
applyingKeys: [{ type: Input }],
partSeparator: [{ type: Input }],
searchProperty: [{ type: Input }],
displayProperty: [{ type: Input }],
focused$: [{ type: Output }],
plainTextElRef: [{ type: ViewChild, args: ['plainText',] }]
};
if (false) {
/**
* Allow line breaks
* @type {?}
*/
NgxTypeaheadComponent.prototype.multiline;
/**
* The list of suggestions.
* @type {?}
*/
NgxTypeaheadComponent.prototype.suggestions;
/**
* The input placeholder.
* @type {?}
*/
NgxTypeaheadComponent.prototype.placeholder;
/**
* The list of keys which will apply suggestion
* @type {?}
*/
NgxTypeaheadComponent.prototype.applyingKeys;
/**
* The part separator
* @type {?}
*/
NgxTypeaheadComponent.prototype.partSeparator;
/**
* The property of a list item that should be used for matching.
* @type {?}
*/
NgxTypeaheadComponent.prototype.searchProperty;
/**
* The property of a list item that should be displayed.
* @type {?}
*/
NgxTypeaheadComponent.prototype.displayProperty;
/**
* The stream of focus changes
* @type {?}
*/
NgxTypeaheadComponent.prototype.focused$;
/** @type {?} */
NgxTypeaheadComponent.prototype.plainTextElRef;
/** @type {?} */
NgxTypeaheadComponent.prototype.plainTextControl;
/** @type {?} */
NgxTypeaheadComponent.prototype.typeaheadContent;
/**
* @type {?}
* @private
*/
NgxTypeaheadComponent.prototype.maxWordsInSuggestionCount;
/**
* @type {?}
* @private
*/
NgxTypeaheadComponent.prototype.destroy$;
/**
* Placeholder for a callback which is later provided by the Control Value Accessor.
* @type {?}
* @private
*/
NgxTypeaheadComponent.prototype.onTouchedCallback;
/**
* Placeholder for a callback which is later provided by the Control Value Accessor.
* @type {?}
* @private
*/
NgxTypeaheadComponent.prototype.onChangeCallback;
/**
* @type {?}
* @private
*/
NgxTypeaheadComponent.prototype.cdRef;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LXR5cGVhaGVhZC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9uZ3gtdHlwZWFoZWFkLXNlYXJjaC8iLCJzb3VyY2VzIjpbImxpYi9uZ3gtdHlwZWFoZWFkLmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7O0FBQUEsT0FBTyxFQUFFLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDaEQsT0FBTyxFQUFFLFNBQVMsRUFBRSxTQUFTLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUN0RCxPQUFPLEVBQ0wsU0FBUyxFQUNULEtBQUssRUFDTCx1QkFBdUIsRUFFdkIsU0FBUyxFQUVULFVBQVUsRUFDVixVQUFVLEVBRVYsaUJBQWlCLEVBQ2pCLE1BQU0sRUFFTixpQkFBaUIsR0FDbEIsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUF3QixXQUFXLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQzs7QUFFdEYsTUFBTSxPQUFPLGdDQUFnQyxHQUFHO0lBQzlDLE9BQU8sRUFBRSxpQkFBaUI7SUFDMUIsV0FBVyxFQUFFLFVBQVUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxxQkFBcUIsQ0FBQztJQUNwRCxLQUFLLEVBQUUsSUFBSTtDQUNaOzs7O0FBa0RELE1BQU0sT0FBTyxxQkFBcUI7Ozs7SUFrRGhDLFlBQW9CLEtBQXdCO1FBQXhCLFVBQUssR0FBTCxLQUFLLENBQW1COzs7O1FBOUM1QixjQUFTLEdBQVksS0FBSyxDQUFDOzs7O1FBSzNCLGdCQUFXLEdBQVEsRUFBRSxDQUFDOzs7O1FBVXRCLGlCQUFZLEdBQWEsQ0FBQyxLQUFLLEVBQUUsT0FBTyxDQUFDLENBQUM7Ozs7UUFLMUMsa0JBQWEsR0FBVyxHQUFHLENBQUM7Ozs7UUFLNUIsbUJBQWMsR0FBVyxPQUFPLENBQUM7Ozs7UUFLakMsb0JBQWUsR0FBVyxJQUFJLENBQUMsY0FBYyxDQUFDOzs7O1FBTXZELGFBQVEsR0FBNkIsSUFBSSxlQUFlLENB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QWdDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgU3ViamVjdCwgQmVoYXZpb3JTdWJqZWN0IH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBzdGFydFdpdGgsIHRha2VVbnRpbCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7XG4gIENvbXBvbmVudCxcbiAgSW5wdXQsXG4gIENoYW5nZURldGVjdGlvblN0cmF0ZWd5LFxuICBPbkNoYW5nZXMsXG4gIFZpZXdDaGlsZCxcbiAgU2ltcGxlQ2hhbmdlcyxcbiAgRWxlbWVudFJlZixcbiAgZm9yd2FyZFJlZixcbiAgT25EZXN0cm95LFxuICBWaWV3RW5jYXBzdWxhdGlvbixcbiAgT3V0cHV0LFxuICBPbkluaXQsXG4gIENoYW5nZURldGVjdG9yUmVmLFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IENvbnRyb2xWYWx1ZUFjY2Vzc29yLCBGb3JtQ29udHJvbCwgTkdfVkFMVUVfQUNDRVNTT1IgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5cbmV4cG9ydCBjb25zdCBUWVBFQUhFQURfQ09OVFJPTF9WQUxVRV9BQ0NFU1NPUiA9IHtcbiAgcHJvdmlkZTogTkdfVkFMVUVfQUNDRVNTT1IsXG4gIHVzZUV4aXN0aW5nOiBmb3J3YXJkUmVmKCgpID0+IE5neFR5cGVhaGVhZENvbXBvbmVudCksXG4gIG11bHRpOiB0cnVlLFxufTtcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnIG5neC10eXBlYWhlYWQnLFxuICB0ZW1wbGF0ZTogYFxuICAgIDxkaXYgY2xhc3M9XCJuZ3gtdHlwZWFoZWFkXCI+XG4gICAgICA8aW5wdXRcbiAgICAgICAgI3BsYWluVGV4dFxuICAgICAgICB0eXBlPVwidGV4dFwiXG4gICAgICAgIGNsYXNzPVwibmd4LXBsYWluLWNvbnRlbnQgdGV4dFwiXG4gICAgICAgIFtwbGFjZWhvbGRlcl09XCJwbGFjZWhvbGRlclwiXG4gICAgICAgIFtmb3JtQ29udHJvbF09XCJwbGFpblRleHRDb250cm9sXCJcbiAgICAgICAgKGZvY3VzKT1cImZvY3VzZWQkLm5leHQodHJ1ZSlcIlxuICAgICAgICAoYmx1cik9XCJmb2N1c2VkJC5uZXh0KGZhbHNlKVwiXG4gICAgICAgIChrZXlkb3duKT1cImhhbmRsZUtleURvd24oJGV2ZW50KVwiXG4gICAgICAvPlxuICAgICAgPHAgI3R5cGVhaGVhZCBjbGFzcz1cIm5neC10eXBlYWhlYWQtY29udGVudFwiPlxuICAgICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwidHlwZWFoZWFkQ29udGVudFwiPlxuICAgICAgICAgIDxzcGFuIFtzdHlsZS52aXNpYmlsaXR5XT1cIihmb2N1c2VkJCB8IGFzeW5jKSA/ICd2aXNpYmxlJyA6ICdoaWRkZW4nXCIgY2xhc3M9XCJ0ZXh0XCI+e3sgdHlwZWFoZWFkQ29udGVudFswXSB9fTwvc3BhblxuICAgICAgICAgID48c3BhbiBjbGFzcz1cInRleHRcIj57eyB0eXBlYWhlYWRDb250ZW50WzFdIH19PC9zcGFuPlxuICAgICAgICA8L25nLWNvbnRhaW5lcj5cbiAgICAgIDwvcD5cbiAgICA8L2Rpdj5cbiAgYCxcbiAgc3R5bGVzOiBbXG4gICAgYFxuICAgICAgLm5neC10eXBlYWhlYWQge1xuICAgICAgICBwb3NpdGlvbjogcmVsYXRpdmU7XG4gICAgICAgIHdpZHRoOiAxMDAlO1xuICAgICAgICBoZWlnaHQ6IDEwMCU7XG4gICAgICAgIGN1cnNvcjogdGV4dDtcbiAgICAgIH1cbiAgICAgIC5uZ3gtcGxhaW4tY29udGVudCB7XG4gICAgICAgIHdoaXRlLXNwYWNlOiBub3dyYXA7XG4gICAgICAgIG92ZXJmbG93OiBoaWRkZW47XG4gICAgICAgIG91dGxpbmU6IG5vbmU7XG4gICAgICAgIC13ZWJraXQtYXBwZWFyYW5jZTogbm9uZTtcbiAgICAgICAgcGFkZGluZzogOHB4IDhweDtcbiAgICAgIH1cbiAgICAgIC5uZ3gtdHlwZWFoZWFkLWNvbnRlbnQge1xuICAgICAgICBwb3NpdGlvbjogYWJzb2x1dGU7XG4gICAgICAgIGNvbG9yOiBncmF5O1xuICAgICAgICBtYXJnaW46IDA7XG4gICAgICB9XG4gICAgYCxcbiAgXSxcbiAgcHJvdmlkZXJzOiBbVFlQRUFIRUFEX0NPTlRST0xfVkFMVUVfQUNDRVNTT1JdLFxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbiAgZW5jYXBzdWxhdGlvbjogVmlld0VuY2Fwc3VsYXRpb24uTm9uZSxcbn0pXG5leHBvcnQgY2xhc3MgTmd4VHlwZWFoZWFkQ29tcG9uZW50PFM+IGltcGxlbWVudHMgT25Jbml0LCBPbkRlc3Ryb3ksIE9uQ2hhbmdlcywgQ29udHJvbFZhbHVlQWNjZXNzb3Ige1xuICAvKipcbiAgICogQWxsb3cgbGluZSBicmVha3NcbiAgICovXG4gIEBJbnB1dCgpIHB1YmxpYyBtdWx0aWxpbmU6IGJvb2xlYW4gPSBmYWxzZTtcblxuICAvKipcbiAgICogVGhlIGxpc3Qgb2Ygc3VnZ2VzdGlvbnMuXG4gICAqL1xuICBASW5wdXQoKSBwdWJsaWMgc3VnZ2VzdGlvbnM6IFNbXSA9IFtdO1xuXG4gIC8qKlxuICAgKiBUaGUgaW5wdXQgcGxhY2Vob2xkZXIuXG4gICAqL1xuICBASW5wdXQoKSBwdWJsaWMgcGxhY2Vob2xkZXI6IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIGxpc3Qgb2Yga2V5cyB3aGljaCB3aWxsIGFwcGx5IHN1Z2dlc3Rpb25cbiAgICovXG4gIEBJbnB1dCgpIHB1YmxpYyBhcHBseWluZ0tleXM6IHN0cmluZ1tdID0gWydUYWInLCAnRW50ZXInXTtcblxuICAvKipcbiAgICogVGhlIHBhcnQgc2VwYXJhdG9yXG4gICAqL1xuICBASW5wdXQoKSBwdWJsaWMgcGFydFNlcGFyYXRvcjogc3RyaW5nID0gJyAnO1xuXG4gIC8qKlxuICAgKiBUaGUgcHJvcGVydHkgb2YgYSBsaXN0IGl0ZW0gdGhhdCBzaG91bGQgYmUgdXNlZCBmb3IgbWF0Y2hpbmcuXG4gICAqL1xuICBASW5wdXQoKSBwdWJsaWMgc2VhcmNoUHJvcGVydHk6IHN0cmluZyA9ICd0aXRsZSc7XG5cbiAgLyoqXG4gICAqIFRoZSBwcm9wZXJ0eSBvZiBhIGxpc3QgaXRlbSB0aGF0IHNob3VsZCBiZSBkaXNwbGF5ZWQuXG4gICAqL1xuICBASW5wdXQoKSBwdWJsaWMgZGlzcGxheVByb3BlcnR5OiBzdHJpbmcgPSB0aGlzLnNlYXJjaFByb3BlcnR5O1xuXG4gIC8qKlxuICAgKiBUaGUgc3RyZWFtIG9mIGZvY3VzIGNoYW5nZXNcbiAgICovXG4gIEBPdXRwdXQoKVxuICBwdWJsaWMgZm9jdXNlZCQ6IEJlaGF2aW9yU3ViamVjdDxib29sZWFuPiA9IG5ldyBCZWhhdmlvclN1YmplY3QoZmFsc2UpO1xuXG4gIEBWaWV3Q2hpbGQoJ3BsYWluVGV4dCcpIHBsYWluVGV4dEVsUmVmOiBFbGVtZW50UmVmPEhUTUxJbnB1dEVsZW1lbnQ+O1xuXG4gIHB1YmxpYyBwbGFpblRleHRDb250cm9sOiBGb3JtQ29udHJvbCA9IG5ldyBGb3JtQ29udHJvbCgnJyk7XG4gIHB1YmxpYyB0eXBlYWhlYWRDb250ZW50OiBbc3RyaW5nLCBzdHJpbmddIHwgbnVsbCA9IG51bGw7XG5cbiAgcHJpdmF0ZSBtYXhXb3Jkc0luU3VnZ2VzdGlvbkNvdW50OiBudW1iZXI7XG4gIHByaXZhdGUgZGVzdHJveSQ6IFN1YmplY3Q8dm9pZD4gPSBuZXcgU3ViamVjdCgpO1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgY2RSZWY6IENoYW5nZURldGVjdG9yUmVmKSB7fVxuXG4gIG5nT25Jbml0KCk6IHZvaWQge1xuICAgIHRoaXMucGxhaW5UZXh0Q29udHJvbC52YWx1ZUNoYW5nZXNcbiAgICAgIC5waXBlKFxuICAgICAgICBzdGFydFdpdGgodGhpcy5wbGFpblRleHRDb250cm9sLnZhbHVlKSxcbiAgICAgICAgdGFrZVVudGlsKHRoaXMuZGVzdHJveSQpXG4gICAgICApXG4gICAgICAuc3Vic2NyaWJlKHRleHQgPT4ge1xuICAgICAgICB0aGlzLnNldFdpdGhDaGFuZ2VEZXRlY3Rpb24oeyB0eXBlYWhlYWRDb250ZW50OiB0aGlzLmdldFR5cGVhaGVhZCh0ZXh0KSB9KTtcbiAgICAgICAgdGhpcy5vbkNoYW5nZUNhbGxiYWNrKHRleHQpO1xuICAgICAgfSk7XG4gIH1cblxuICBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKTogdm9pZCB7XG4gICAgY29uc3Qgc3VnZ2VzdGlvbnMgPSBjaGFuZ2VzLnN1Z2dlc3Rpb25zICYmIGNoYW5nZXMuc3VnZ2VzdGlvbnMuY3VycmVudFZhbHVlO1xuXG4gICAgaWYgKHN1Z2dlc3Rpb25zKSB7XG4gICAgICB0aGlzLm1heFdvcmRzSW5TdWdnZXN0aW9uQ291bnQgPSB0aGlzLmdldEdyZWF0ZXNXb3Jkc0Ftb3VudChzdWdnZXN0aW9ucyk7XG4gICAgfVxuICB9XG5cbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgdGhpcy5kZXN0cm95JC5uZXh0KCk7XG4gICAgdGhpcy5kZXN0cm95JC5jb21wbGV0ZSgpO1xuICB9XG5cbiAgcHVibGljIGhhbmRsZUtleURvd24oZTogS2V5Ym9hcmRFdmVudCk6IHZvaWQge1xuICAgIGlmICh0aGlzLmFwcGx5aW5nS2V5cy5pbmNsdWRlcyhlLmtleSkgJiYgdGhpcy50eXBlYWhlYWRDb250ZW50KSB7XG4gICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG5cbiAgICAgIGNvbnN0IG9rID0gdGhpcy5hcHBseVN1Z2dlc3Rpb24oKTtcblxuICAgICAgaWYgKG9rKSB7XG4gICAgICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0gQ29udHJvbCBWYWx1ZSBBY2Nlc3NvciAtLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4gIC8qKlxuICAgKiBQbGFjZWhvbGRlciBmb3IgYSBjYWxsYmFjayB3aGljaCBpcyBsYXRlciBwcm92aWRlZCBieSB0aGUgQ29udHJvbCBWYWx1ZSBBY2Nlc3Nvci5cbiAgICovXG4gIHByaXZhdGUgb25Ub3VjaGVkQ2FsbGJhY2s6ICgpID0+IHZvaWQgPSAoKSA9PiB7fTtcblxuICAvKipcbiAgICogUGxhY2Vob2xkZXIgZm9yIGEgY2FsbGJhY2sgd2hpY2ggaXMgbGF0ZXIgcHJvdmlkZWQgYnkgdGhlIENvbnRyb2wgVmFsdWUgQWNjZXNzb3IuXG4gICAqL1xuICBwcml2YXRlIG9uQ2hhbmdlQ2FsbGJhY2s6IChfOiBhbnkpID0+IHZvaWQgPSAoKSA9PiB7fTtcblxuICBwdWJsaWMgd3JpdGVWYWx1ZSh2OiBzdHJpbmcgfCBudWxsKSB7XG4gICAgaWYgKHYgPT0gbnVsbCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMucGxhaW5UZXh0Q29udHJvbC5zZXRWYWx1ZSh2KTtcbiAgfVxuXG4gIHB1YmxpYyByZWdpc3Rlck9uQ2hhbmdlKGZuOiBhbnkpIHtcbiAgICB0aGlzLm9uQ2hhbmdlQ2FsbGJhY2sgPSBmbjtcbiAgfVxuXG4gIHB1YmxpYyByZWdpc3Rlck9uVG91Y2hlZChmbjogYW55KSB7XG4gICAgdGhpcy5vblRvdWNoZWRDYWxsYmFjayA9IGZuO1xuICB9XG5cbiAgcHVibGljIHNldERpc2FibGVkU3RhdGUoaXNEaXNhYmxlZDogYm9vbGVhbik6IHZvaWQge1xuICAgIGlmIChpc0Rpc2FibGVkKSB7XG4gICAgICB0aGlzLnBsYWluVGV4dENvbnRyb2wuZGlzYWJsZSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnBsYWluVGV4dENvbnRyb2wuZW5hYmxlKCk7XG4gICAgfVxuICB9XG5cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0gQ29udHJvbCBWYWx1ZSBBY2Nlc3NvciAtLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4gIC8qKlxuICAgKiBSZXR1cm4gc3VnZ2VzdGlvbiBjb21wbGV0aW9uXG4gICAqL1xuICBwdWJsaWMgZ2V0VHlwZWFoZWFkKGlucHV0Pzogc3RyaW5nIHwgbnVsbCk6IFtzdHJpbmcsIHN0cmluZ10gfCBudWxsIHtcbiAgICBpZiAoIWlucHV0KSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICBjb25zdCBjaHVua3MgPSBpbnB1dC5zcGxpdCh0aGlzLnBhcnRTZXBhcmF0b3IpO1xuXG4gICAgbGV0IGNodW5rOiBzdHJpbmc7XG4gICAgbGV0IHN1Z2dlc3Rpb246IFM7XG5cbiAgICBmb3IgKGxldCBpID0gMTsgaSA8PSB0aGlzLm1heFdvcmRzSW5TdWdnZXN0aW9uQ291bnQ7IGkrKykge1xuICAgICAgY2h1bmsgPSBjaHVua3Muc2xpY2UoY2h1bmtzLmxlbmd0aCAtIGkpLmpvaW4oJyAnKTtcbiAgICAgIHN1Z2dlc3Rpb24gPSB0aGlzLmdldFN1Z2dlc3Rpb24oY2h1bmspO1xuXG4gICAgICBpZiAoc3VnZ2VzdGlvbikge1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoXG4gICAgICBkb2N1bWVudC5hY3RpdmVFbGVtZW50ICE9PSB0aGlzLnBsYWluVGV4dEVsUmVmLm5hdGl2ZUVsZW1lbnQgfHxcbiAgICAgICFzdWdnZXN0aW9uIHx8XG4gICAgICBjaHVuay5sZW5ndGggPT09IHN1Z2dlc3Rpb25bdGhpcy5kaXNwbGF5UHJvcGVydHldXG4gICAgKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICBjb25zdCBkaXNwbGF5VmFsdWUgPSB0aGlzLmdldERpc3BsYXlWYWx1ZShzdWdnZXN0aW9uKTtcblxuICAgIHJldHVybiBbaW5wdXQuc3Vic3RyKDAsIGlucHV0Lmxlbmd0aCksIGRpc3BsYXlWYWx1ZS5zdWJzdHIoY2h1bmsubGVuZ3RoKV07XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJuIGFwcHJvcHJpYXRlIHN1Z2dlc3Rpb24gb3IgbnVsbFxuICAgKi9cbiAgcHJpdmF0ZSBnZXRTdWdnZXN0aW9uKHRleHQ6IHN0cmluZyk6IFMgfCBudWxsIHtcbiAgICBjb25zdCBxdWVyeSA9IHRleHQucmVwbGFjZSgvXFxzL2csICgpID0+ICcgJyk7XG5cbiAgICBpZiAoIXF1ZXJ5KSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICB0cnkge1xuICAgICAgY29uc3Qgc2VhcmNoUmVnRXhwID0gbmV3IFJlZ0V4cChgXiR7cXVlcnl9LipgLCAnaScpO1xuXG4gICAgICByZXR1cm4gdGhpcy5zdWdnZXN0aW9ucy5maW5kKGl0ZW0gPT4gc2VhcmNoUmVnRXhwLnRlc3QodGhpcy5nZXRTZWFyY2hWYWx1ZShpdGVtKSkpIHx8IG51bGw7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBnZXRTZWFyY2hWYWx1ZShpdGVtOiBTKTogc3RyaW5nIHtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIHR5cGVvZiBpdGVtID09PSAnc3RyaW5nJyA/IGl0ZW0gOiBpdGVtW3RoaXMuc2VhcmNoUHJvcGVydHldO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIHRocm93IEVycm9yKGBTdWdnZXN0aW9uIHNob3VsZCBiZSBzdHJpbmcgb3IgY29udGFpbnMgc2VhcmNoUHJvcGVydHkuIFlvdSBjYW4gc2V0IGl0IGFzIElucHV0IFtzZWFyY2hQcm9wZXJ0eV0uYCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBnZXREaXNwbGF5VmFsdWUoaXRlbTogUyk6IHN0cmluZyB7XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiB0eXBlb2YgaXRlbSA9PT0gJ3N0cmluZycgPyBpdGVtIDogaXRlbVt0aGlzLmRpc3BsYXlQcm9wZXJ0eV07XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgdGhyb3cgRXJyb3IoXG4gICAgICAgIGBTdWdnZXN0aW9uIHNob3VsZCBiZSBzdHJpbmcgb3IgY29udGFpbnMgZGlzcGxheVByb3BlcnR5LiBZb3UgY2FuIHNldCBpdCBhcyBJbnB1dCBbZGlzcGxheVByb3BlcnR5XS5gXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXBsYWNlIHRleHQgY29udGVudCBwYXJ0IGFuZCBhaGVhZCB0ZXh0IG9uIHN1Z2dlc3Rpb25cbiAgICovXG4gIHByaXZhdGUgYXBwbHlTdWdnZXN0aW9uKCk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IHBsYWluVGV4dCA9IHRoaXMucGxhaW5UZXh0Q29udHJvbC52YWx1ZTtcbiAgICBjb25zdCB0eXBlYWhlYWQgPSB0aGlzLmdldFR5cGVhaGVhZChwbGFpblRleHQpO1xuXG4gICAgaWYgKCF0eXBlYWhlYWQpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICB0aGlzLnBsYWluVGV4dENvbnRyb2wuc2V0VmFsdWUodHlwZWFoZWFkWzBdICsgdHlwZWFoZWFkWzFdKTtcblxuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRHcmVhdGVzV29yZHNBbW91bnQoaXRlbXM6IFNbXSk6IG51bWJlciB7XG4gICAgcmV0dXJuIGl0ZW1zLnJlZHVjZSgocmVzdWx0LCBpdGVtKSA9PiB7XG4gICAgICBjb25zdCBjb3VudCA9IHRoaXMuZ2V0U2VhcmNoVmFsdWUoaXRlbSkuc3BsaXQodGhpcy5wYXJ0U2VwYXJhdG9yKS5sZW5ndGg7XG5cbiAgICAgIHJldHVybiBjb3VudCA+IHJlc3VsdCA/IGNvdW50IDogcmVzdWx0O1xuICAgIH0sIDApO1xuICB9XG5cbiAgcHJpdmF0ZSBzZXRXaXRoQ2hhbmdlRGV0ZWN0aW9uKGRhdGE6IFBhcnRpYWw8Tmd4VHlwZWFoZWFkQ29tcG9uZW50PFM+Pik6IHZvaWQge1xuICAgIE9iamVjdC5hc3NpZ24odGhpcywgZGF0YSk7XG4gICAgdGhpcy5jZFJlZi5kZXRlY3RDaGFuZ2VzKCk7XG4gIH1cbn1cbiJdfQ==