@ux-aspects/ux-aspects
Version:
Open source user interface framework for building modern, responsive, mobile big data applications
486 lines • 78.3 kB
JavaScript
import { coerceArray } from '@angular/cdk/coercion';
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, EventEmitter, HostBinding, HostListener, inject, Input, Output, ViewChild, } from '@angular/core';
import { BehaviorSubject, combineLatest, Subject } from 'rxjs';
import { distinctUntilChanged, takeUntil } from 'rxjs/operators';
import { InfiniteScrollDirective, } from '../../directives/infinite-scroll/index';
import { PopoverOrientationService, } from '../../services/popover-orientation/popover-orientation.service';
import { TypeaheadOptionEvent } from './typeahead-event';
import { TypeaheadService } from './typeahead.service';
import * as i0 from "@angular/core";
import * as i1 from "@angular/common";
import * as i2 from "../../directives/infinite-scroll/infinite-scroll.directive";
import * as i3 from "../../directives/infinite-scroll/infinite-scroll-loading.directive";
import * as i4 from "../../directives/safe-inner-html/safe-inner-html.directive";
import * as i5 from "./typeahead-options-list.component";
let uniqueId = 0;
export class TypeaheadComponent {
/** Specify if the typeahead is open */
get open() {
return this._service.open$.getValue();
}
set open(value) {
this._service.open$.next(value);
}
/** Specify which options are disabled */
set disabledOptions(options) {
this._disabledOptions = coerceArray(options);
}
get disabledOptions() {
return this._disabledOptions;
}
/** Specify the max height of the dropdown */
get maxHeight() {
return this._maxHeight;
}
set maxHeight(maxHeight) {
this._maxHeight = maxHeight;
if (this.maxHeight.endsWith('px')) {
this._popoverOrientationListener.maxHeight = Number(this.maxHeight.slice(0, -2));
}
}
/** Specify the currently active item */
set active(item) {
this.activeKey = this.getKey(item);
}
get highlighted() {
const value = this.highlighted$.getValue();
return value ? value.value : null;
}
constructor() {
this.typeaheadElement = inject(ElementRef);
this.popoverOrientation = inject(PopoverOrientationService);
this._changeDetector = inject(ChangeDetectorRef);
this._service = inject(TypeaheadService);
/** Define a unique id for the typeahead */
this.id = `ux-typeahead-${++uniqueId}`;
this._disabledOptions = [];
/** Specify the drop direction */
this.dropDirection = 'down';
/** Specify the aria multi selectable attribute value */
this.multiselectable = false;
/** Specify if the dropdown should appear when the filter appears */
this.openOnFilterChange = true;
/** Specify the page size */
this.pageSize = 20;
/** Specify if we should select the first item by default */
this.selectFirst = true;
/** Specify if we should select an item on enter key press */
this.selectOnEnter = false;
/** Specify the loading state */
this.loading = false;
/** Maximum number of displayed recently selected options. */
this.recentOptionsMaxCount = 5;
/** Emit when the open state changes */
this.openChange = new EventEmitter();
/** Emit when an option is selected */
this.optionSelected = new EventEmitter();
/** Emit whenever a highlighted item changes */
this.highlightedChange = new EventEmitter();
/** Emit the highlighted element when it changes */
this.highlightedElementChange = new EventEmitter();
/** Emits when recently selected options change.*/
this.recentOptionsChange = new EventEmitter();
this.activeKey = null;
this.clicking = false;
this.hasBeenOpened = false;
this.highlighted$ = new BehaviorSubject(null);
this.visibleOptions$ = new BehaviorSubject([]);
this.visibleRecentOptions$ = new BehaviorSubject([]);
this.allVisibleOptions = [];
this._onDestroy = new Subject();
this._maxHeight = '250px';
this.optionApi = {
getKey: this.getKey.bind(this),
getDisplay: this.getDisplay.bind(this),
getDisplayHtml: this.getDisplayHtml.bind(this),
getDisabled: this.isDisabled.bind(this),
};
this.loadOptionsCallback = (pageNum, pageSize, filter) => {
if (typeof this.options === 'function') {
// Invoke the callback which may return an array or a promise.
const arrayOrPromise = this.options(pageNum, pageSize, filter);
// Map the results to an array of TypeaheadVisibleOption.
return Promise.resolve(arrayOrPromise).then(newOptions => {
if (!Array.isArray(newOptions)) {
return newOptions;
}
return this.getVisibleOptions(newOptions, '');
});
}
return null;
};
this._service.open$
.pipe(distinctUntilChanged(), takeUntil(this._onDestroy))
.subscribe(isOpen => {
this.openChange.emit(isOpen);
if (isOpen) {
this.hasBeenOpened = true;
this.initOptions();
}
});
this._popoverOrientationListener = this.popoverOrientation.createPopoverOrientationListener(this.typeaheadElement.nativeElement, this.typeaheadElement.nativeElement.parentElement);
this._popoverOrientationListener.orientation$
.pipe(takeUntil(this._onDestroy))
.subscribe(direction => {
if (this.dropDirection === 'auto') {
this.dropUp = direction === 0 /* PopoverOrientation.Up */;
}
});
this.highlighted$.pipe(takeUntil(this._onDestroy)).subscribe(next => {
this.highlightedChange.emit(next ? next.value : null);
});
combineLatest([this.visibleOptions$, this.visibleRecentOptions$])
.pipe(takeUntil(this._onDestroy))
.subscribe(([visibleOptions, visibleRecentOptions]) => {
this.allVisibleOptions = [...visibleRecentOptions, ...visibleOptions];
});
combineLatest([this._service.open$, this._service.highlightedElement$, this.visibleOptions$])
.pipe(takeUntil(this._onDestroy))
.subscribe(([open, highlightedElement, visibleOptions]) => {
this.highlightedElementChange.emit(open && visibleOptions.length > 0 ? highlightedElement : null);
});
}
ngOnChanges(changes) {
// Open the dropdown if the filter value updates
if (changes.filter) {
if (this.openOnFilterChange &&
changes.filter.currentValue &&
changes.filter.currentValue.length > 0) {
// if the dropdown item was just selected, and we set the filter value to match the
// selected value then open will have also just been set to `false`, in which case we do
// not want to set open to `true`
if (changes.open &&
changes.open.previousValue === true &&
changes.open.currentValue === false) {
return;
}
// show the dropdown
this.open = true;
}
}
// Cut off recentOptions at recentOptionsMaxCount
if (changes.recentOptions || changes.recentOptionsMaxCount) {
this._recentOptions = this.recentOptions
? this.recentOptions.slice(0, this.recentOptionsMaxCount)
: undefined;
if (changes.recentOptionsMaxCount) {
// Avoid ExpressionChangedAfterChecked error
setTimeout(() => {
this.recentOptionsChange.emit(this._recentOptions);
});
}
}
if (changes.dropDirection) {
if (changes.dropDirection.currentValue === 'auto') {
this.dropUp =
this._popoverOrientationListener.orientation$.getValue() === 0 /* PopoverOrientation.Up */;
}
else {
this.dropUp = changes.dropDirection.currentValue === 'up';
}
}
if (changes.options && changes.options.firstChange === false) {
this.infiniteScroll.reset(false);
this.infiniteScroll.reload();
}
// Re-filter visibleOptions
this.updateOptions();
}
ngOnDestroy() {
this._onDestroy.next();
this._onDestroy.complete();
this._popoverOrientationListener.destroy();
}
mousedownHandler(event, target) {
this.clicking = true;
/**
* Chrome Bug Workaround: (https://bugs.chromium.org/p/chromium/issues/detail?id=6759)
* In Chrome, if the typeahead is within a tabbable element, e.g. it has a parent with
* `tabindex="0"` like our side panel has, then clicking on a scrollbar will remove
* focus from the input element.
*
* To avoid this we can determine if the mousedown event occurred within the scrollbar
* region of the typeahead and if so preventDefault which will stop the input
* from losing focus
*/
if (event.clientX >= target.clientWidth || event.clientY >= target.clientHeight) {
event.preventDefault();
}
}
mouseupHandler() {
this.clicking = false;
}
optionMousedownHandler(event) {
// Workaround to prevent focus changing when an option is clicked
event.preventDefault();
}
optionClickHandler(_event, option) {
this.select(option, 'mouse');
}
/**
* Returns the unique key value of the given option.
*/
getKey(option) {
if (typeof this.key === 'function') {
return this.key(option);
}
// eslint-disable-next-line no-prototype-builtins
if (typeof this.key === 'string' && option && option.hasOwnProperty(this.key)) {
return option[this.key];
}
return this.getDisplay(option);
}
/**
* Returns the display value of the given option.
*/
getDisplay(option) {
if (typeof this.display === 'function') {
return this.display(option);
}
// eslint-disable-next-line no-prototype-builtins
if (typeof this.display === 'string' && option && option.hasOwnProperty(this.display)) {
return option[this.display];
}
if (typeof option === 'string') {
return option;
}
}
/**
* Returns the display value of the given option with HTML markup added to highlight the part which matches the current filter value.
* @param option
*/
getDisplayHtml(option) {
const displayText = this.getDisplay(option);
// getDisplay may return undefined in certain cases
if (!displayText) {
return '';
}
let displayHtml = displayText
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>');
if (this.filter) {
const length = this.filter.length;
const matchIndex = displayText.toLowerCase().indexOf(this.filter.toLowerCase());
if (matchIndex >= 0) {
const highlight = `<span class="ux-filter-match">${displayText.substr(matchIndex, length)}</span>`;
displayHtml =
displayText.substr(0, matchIndex) + highlight + displayText.substr(matchIndex + length);
}
}
return displayHtml;
}
/**
* Returns true if the infinite scroll component should load
*/
isInfiniteScroll() {
return typeof this.options === 'function';
}
/**
* Selects the given option, emitting the optionSelected event and closing the dropdown.
*/
select(option, origin) {
if (!this.isDisabled(option.value)) {
this.optionSelected.emit(new TypeaheadOptionEvent(option.value, origin));
this.highlighted$.next(null);
this.open = false;
this.addToRecentOptions(option.value);
}
}
addToRecentOptions(value) {
if (this._recentOptions) {
this._recentOptions = [
value,
...this._recentOptions.filter(recentOption => recentOption !== value),
].slice(0, this.recentOptionsMaxCount);
this.recentOptionsChange.emit(this._recentOptions);
}
}
/**
* Returns true if the given option is part of the disabledOptions array.
*/
isDisabled(option) {
return Array.isArray(this.disabledOptions)
? this.disabledOptions.some(selectedOption => this.getKey(selectedOption) === this.getKey(option))
: false;
}
/**
* Set the given option as the current highlighted option, available in the highlightedOption parameter.
*/
highlight(option) {
if (!this.isDisabled(option.value)) {
this.highlighted$.next(option);
this._changeDetector.detectChanges();
}
}
/**
* Increment or decrement the highlighted option in the list. Disabled options are skipped.
* @param d Value to be added to the index of the highlighted option, i.e. -1 to move backwards, +1 to move forwards.
*/
moveHighlight(d) {
const highlightIndex = this.indexOfVisibleOption(this.highlighted$.getValue());
let newIndex = highlightIndex;
let disabled = true;
let inBounds = true;
do {
newIndex = newIndex + d;
inBounds = newIndex >= 0 && newIndex < this.allVisibleOptions.length;
disabled = inBounds && this.isDisabled(this.allVisibleOptions[newIndex].value);
} while (inBounds && disabled);
if (!disabled && inBounds) {
this.highlight(this.allVisibleOptions[newIndex]);
}
return this.highlighted;
}
selectHighlighted() {
if (this.highlighted$.getValue()) {
this.select(this.highlighted$.getValue(), 'keyboard');
}
}
/**
* Set up the options before the dropdown is displayed.
*/
initOptions() {
// Clear previous highlight
this.highlighted$.next(null);
if (this.selectFirst) {
// This will highlight the first non-disabled option.
this.moveHighlight(1);
}
}
/**
* Display the first item as highlighted when there are several pages
*/
onLoadedHighlight(event) {
if (this.selectFirst && this.options && event.pageNumber === 0) {
// This will highlight the first non-disabled option.
this.moveHighlight(1);
}
}
/**
* Update the visibleOptions and visibleRecentOptions arrays with the current filter.
*/
updateOptions() {
const normalisedInput = (this.filter || '').toLowerCase();
// Create new visibleOptions only if `options` is not a function
if (typeof this.options === 'object') {
this.visibleOptions$.next(this.getVisibleOptions(this.options, normalisedInput));
}
this.visibleRecentOptions$.next(this.getVisibleOptions(this._recentOptions, normalisedInput, true));
this.initOptions();
this._changeDetector.detectChanges();
}
/**
* Convert a set of raw options into a filtered list of `TypeaheadVisibleOption` objects.
* @param options Set of raw options
* @param filter The filter expression
* @param isRecentOptions Whether `options` is a set of recent options
*/
getVisibleOptions(options, filter = '', isRecentOptions = false) {
if (options) {
return options
.filter(option => this.getDisplay(option).toLowerCase().indexOf(filter) >= 0)
.map(value => ({
value,
key: this.getKey(value),
isRecentOption: isRecentOptions,
}));
}
return [];
}
/**
* Return the index of the given option in the allVisibleOptions array.
* Returns -1 if the option is not currently visible.
*/
indexOfVisibleOption(option) {
if (option) {
return this.allVisibleOptions.findIndex(el => {
return el.key === option.key && el.isRecentOption === option.isRecentOption;
});
}
return -1;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: TypeaheadComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.12", type: TypeaheadComponent, selector: "ux-typeahead", inputs: { id: "id", options: "options", filter: "filter", open: "open", display: "display", key: "key", disabledOptions: "disabledOptions", dropDirection: "dropDirection", maxHeight: "maxHeight", multiselectable: "multiselectable", ariaLabel: "ariaLabel", openOnFilterChange: "openOnFilterChange", pageSize: "pageSize", selectFirst: "selectFirst", selectOnEnter: "selectOnEnter", loading: "loading", loadingTemplate: "loadingTemplate", optionTemplate: "optionTemplate", noOptionsTemplate: "noOptionsTemplate", active: "active", recentOptions: "recentOptions", recentOptionsMaxCount: "recentOptionsMaxCount", recentOptionsHeadingTemplate: "recentOptionsHeadingTemplate", optionsHeadingTemplate: "optionsHeadingTemplate" }, outputs: { openChange: "openChange", optionSelected: "optionSelected", highlightedChange: "highlightedChange", highlightedElementChange: "highlightedElementChange", recentOptionsChange: "recentOptionsChange" }, host: { listeners: { "mousedown": "mousedownHandler($event,$event.target)", "mouseup": "mouseupHandler()" }, properties: { "class.open": "open", "style.maxHeight": "maxHeight", "attr.id": "this.id", "class.drop-up": "this.dropUp" } }, providers: [TypeaheadService, PopoverOrientationService], viewQueries: [{ propertyName: "infiniteScroll", first: true, predicate: InfiniteScrollDirective, descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div\n class=\"ux-typeahead-options\"\n [uxInfiniteScroll]=\"loadOptionsCallback\"\n [collection]=\"visibleOptions$ | async\"\n (collectionChange)=\"visibleOptions$.next($event)\"\n [enabled]=\"hasBeenOpened && isInfiniteScroll()\"\n [filter]=\"filter\"\n [loadOnScroll]=\"true\"\n [pageSize]=\"pageSize\"\n [scrollElement]=\"typeaheadElement\"\n (loading)=\"loading = true\"\n (loaded)=\"loading = false; onLoadedHighlight($event)\"\n >\n @if ((visibleRecentOptions$ | async).length > 0) {\n <div>\n <ng-container [ngTemplateOutlet]=\"recentOptionsHeadingTemplate\"></ng-container>\n </div>\n }\n\n <!-- Recent options -->\n @if ((visibleRecentOptions$ | async).length > 0) {\n <ux-typeahead-options-list\n class=\"ux-typeahead-recent-options\"\n [id]=\"id\"\n [options]=\"visibleRecentOptions$ | async\"\n [highlighted]=\"highlighted$ | async\"\n [activeKey]=\"activeKey\"\n [disabledOptions]=\"_disabledOptions\"\n [isMultiselectable]=\"multiselectable\"\n [optionTemplate]=\"optionTemplate || defaultOptionTemplate\"\n [optionApi]=\"optionApi\"\n [typeaheadElement]=\"typeaheadElement\"\n (optionMouseover)=\"highlight($event.option)\"\n (optionMousedown)=\"optionMousedownHandler($event.event)\"\n (optionClick)=\"optionClickHandler($event.event, $event.option)\"\n >\n </ux-typeahead-options-list>\n }\n\n <ng-container [ngTemplateOutlet]=\"optionsHeadingTemplate\"></ng-container>\n\n <!-- All options -->\n @if ((visibleOptions$ | async).length > 0) {\n <ux-typeahead-options-list\n class=\"ux-typeahead-all-options\"\n [id]=\"id\"\n [ariaLabel]=\"ariaLabel\"\n [startIndex]=\"(visibleRecentOptions$ | async).length\"\n [options]=\"visibleOptions$ | async\"\n [highlighted]=\"highlighted$ | async\"\n [activeKey]=\"activeKey\"\n [disabledOptions]=\"_disabledOptions\"\n [isMultiselectable]=\"multiselectable\"\n [optionTemplate]=\"optionTemplate || defaultOptionTemplate\"\n [optionApi]=\"optionApi\"\n [typeaheadElement]=\"typeaheadElement\"\n (optionMouseover)=\"highlight($event.option)\"\n (optionMousedown)=\"optionMousedownHandler($event.event)\"\n (optionClick)=\"optionClickHandler($event.event, $event.option)\"\n >\n </ux-typeahead-options-list>\n }\n\n <div *uxInfiniteScrollLoading>\n <ng-container [ngTemplateOutlet]=\"loadingTemplate || defaultLoadingTemplate\"></ng-container>\n </div>\n\n @if (isInfiniteScroll() === false && (visibleOptions$ | async).length === 0 && loading) {\n <div>\n <ng-container [ngTemplateOutlet]=\"loadingTemplate || defaultLoadingTemplate\"></ng-container>\n </div>\n }\n</div>\n@if ((visibleOptions$ | async).length === 0 && !loading) {\n <div>\n <ng-container [ngTemplateOutlet]=\"noOptionsTemplate || defaultNoOptionsTemplate\"> </ng-container>\n </div>\n}\n\n<ng-template #defaultLoadingTemplate>\n <div class=\"ux-typeahead-loading\">\n <div class=\"spinner spinner-accent spinner-bounce-middle\"></div>\n <div>Loading...</div>\n </div>\n</ng-template>\n\n<ng-template #defaultOptionTemplate let-option=\"option\" let-api=\"api\">\n <span class=\"ux-typeahead-option\" [uxSafeInnerHtml]=\"api.getDisplayHtml(option)\"></span>\n</ng-template>\n\n<ng-template #defaultNoOptionsTemplate>\n <span class=\"ux-typeahead-no-options\">No results</span>\n</ng-template>\n", dependencies: [{ kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i2.InfiniteScrollDirective, selector: "[uxInfiniteScroll]", inputs: ["uxInfiniteScroll", "collection", "scrollElement", "enabled", "filter", "loadOnInit", "loadOnScroll", "pageSize"], outputs: ["collectionChange", "loading", "loaded", "loadError"], exportAs: ["uxInfiniteScroll"] }, { kind: "directive", type: i3.InfiniteScrollLoadingDirective, selector: "[uxInfiniteScrollLoading]", inputs: ["uxInfiniteScrollLoading"] }, { kind: "directive", type: i4.SafeInnerHtmlDirective, selector: "[uxSafeInnerHtml]", inputs: ["uxSafeInnerHtml"] }, { kind: "component", type: i5.TypeaheadOptionsListComponent, selector: "ux-typeahead-options-list", inputs: ["id", "startIndex", "options", "highlighted", "activeKey", "disabledOptions", "isMultiselectable", "optionTemplate", "optionApi", "typeaheadElement", "ariaLabel"], outputs: ["optionMouseover", "optionMousedown", "optionClick"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: TypeaheadComponent, decorators: [{
type: Component,
args: [{ selector: 'ux-typeahead', providers: [TypeaheadService, PopoverOrientationService], changeDetection: ChangeDetectionStrategy.OnPush, host: {
'[class.open]': 'open',
'[style.maxHeight]': 'maxHeight',
}, template: "<div\n class=\"ux-typeahead-options\"\n [uxInfiniteScroll]=\"loadOptionsCallback\"\n [collection]=\"visibleOptions$ | async\"\n (collectionChange)=\"visibleOptions$.next($event)\"\n [enabled]=\"hasBeenOpened && isInfiniteScroll()\"\n [filter]=\"filter\"\n [loadOnScroll]=\"true\"\n [pageSize]=\"pageSize\"\n [scrollElement]=\"typeaheadElement\"\n (loading)=\"loading = true\"\n (loaded)=\"loading = false; onLoadedHighlight($event)\"\n >\n @if ((visibleRecentOptions$ | async).length > 0) {\n <div>\n <ng-container [ngTemplateOutlet]=\"recentOptionsHeadingTemplate\"></ng-container>\n </div>\n }\n\n <!-- Recent options -->\n @if ((visibleRecentOptions$ | async).length > 0) {\n <ux-typeahead-options-list\n class=\"ux-typeahead-recent-options\"\n [id]=\"id\"\n [options]=\"visibleRecentOptions$ | async\"\n [highlighted]=\"highlighted$ | async\"\n [activeKey]=\"activeKey\"\n [disabledOptions]=\"_disabledOptions\"\n [isMultiselectable]=\"multiselectable\"\n [optionTemplate]=\"optionTemplate || defaultOptionTemplate\"\n [optionApi]=\"optionApi\"\n [typeaheadElement]=\"typeaheadElement\"\n (optionMouseover)=\"highlight($event.option)\"\n (optionMousedown)=\"optionMousedownHandler($event.event)\"\n (optionClick)=\"optionClickHandler($event.event, $event.option)\"\n >\n </ux-typeahead-options-list>\n }\n\n <ng-container [ngTemplateOutlet]=\"optionsHeadingTemplate\"></ng-container>\n\n <!-- All options -->\n @if ((visibleOptions$ | async).length > 0) {\n <ux-typeahead-options-list\n class=\"ux-typeahead-all-options\"\n [id]=\"id\"\n [ariaLabel]=\"ariaLabel\"\n [startIndex]=\"(visibleRecentOptions$ | async).length\"\n [options]=\"visibleOptions$ | async\"\n [highlighted]=\"highlighted$ | async\"\n [activeKey]=\"activeKey\"\n [disabledOptions]=\"_disabledOptions\"\n [isMultiselectable]=\"multiselectable\"\n [optionTemplate]=\"optionTemplate || defaultOptionTemplate\"\n [optionApi]=\"optionApi\"\n [typeaheadElement]=\"typeaheadElement\"\n (optionMouseover)=\"highlight($event.option)\"\n (optionMousedown)=\"optionMousedownHandler($event.event)\"\n (optionClick)=\"optionClickHandler($event.event, $event.option)\"\n >\n </ux-typeahead-options-list>\n }\n\n <div *uxInfiniteScrollLoading>\n <ng-container [ngTemplateOutlet]=\"loadingTemplate || defaultLoadingTemplate\"></ng-container>\n </div>\n\n @if (isInfiniteScroll() === false && (visibleOptions$ | async).length === 0 && loading) {\n <div>\n <ng-container [ngTemplateOutlet]=\"loadingTemplate || defaultLoadingTemplate\"></ng-container>\n </div>\n }\n</div>\n@if ((visibleOptions$ | async).length === 0 && !loading) {\n <div>\n <ng-container [ngTemplateOutlet]=\"noOptionsTemplate || defaultNoOptionsTemplate\"> </ng-container>\n </div>\n}\n\n<ng-template #defaultLoadingTemplate>\n <div class=\"ux-typeahead-loading\">\n <div class=\"spinner spinner-accent spinner-bounce-middle\"></div>\n <div>Loading...</div>\n </div>\n</ng-template>\n\n<ng-template #defaultOptionTemplate let-option=\"option\" let-api=\"api\">\n <span class=\"ux-typeahead-option\" [uxSafeInnerHtml]=\"api.getDisplayHtml(option)\"></span>\n</ng-template>\n\n<ng-template #defaultNoOptionsTemplate>\n <span class=\"ux-typeahead-no-options\">No results</span>\n</ng-template>\n" }]
}], ctorParameters: () => [], propDecorators: { infiniteScroll: [{
type: ViewChild,
args: [InfiniteScrollDirective]
}], id: [{
type: Input
}, {
type: HostBinding,
args: ['attr.id']
}], options: [{
type: Input
}], filter: [{
type: Input
}], open: [{
type: Input
}], display: [{
type: Input
}], key: [{
type: Input
}], disabledOptions: [{
type: Input
}], dropDirection: [{
type: Input
}], maxHeight: [{
type: Input
}], multiselectable: [{
type: Input
}], ariaLabel: [{
type: Input
}], openOnFilterChange: [{
type: Input
}], pageSize: [{
type: Input
}], selectFirst: [{
type: Input
}], selectOnEnter: [{
type: Input
}], loading: [{
type: Input
}], loadingTemplate: [{
type: Input
}], optionTemplate: [{
type: Input
}], noOptionsTemplate: [{
type: Input
}], active: [{
type: Input
}], recentOptions: [{
type: Input
}], recentOptionsMaxCount: [{
type: Input
}], recentOptionsHeadingTemplate: [{
type: Input
}], optionsHeadingTemplate: [{
type: Input
}], openChange: [{
type: Output
}], optionSelected: [{
type: Output
}], highlightedChange: [{
type: Output
}], highlightedElementChange: [{
type: Output
}], recentOptionsChange: [{
type: Output
}], dropUp: [{
type: HostBinding,
args: ['class.drop-up']
}], mousedownHandler: [{
type: HostListener,
args: ['mousedown', ['$event', '$event.target']]
}], mouseupHandler: [{
type: HostListener,
args: ['mouseup']
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZWFoZWFkLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9jb21wb25lbnRzL3R5cGVhaGVhZC90eXBlYWhlYWQuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vc3JjL2NvbXBvbmVudHMvdHlwZWFoZWFkL3R5cGVhaGVhZC5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDcEQsT0FBTyxFQUNMLHVCQUF1QixFQUN2QixpQkFBaUIsRUFDakIsU0FBUyxFQUNULFVBQVUsRUFDVixZQUFZLEVBQ1osV0FBVyxFQUNYLFlBQVksRUFDWixNQUFNLEVBQ04sS0FBSyxFQUdMLE1BQU0sRUFHTixTQUFTLEdBQ1YsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLGVBQWUsRUFBRSxhQUFhLEVBQUUsT0FBTyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQy9ELE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxTQUFTLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUNqRSxPQUFPLEVBQ0wsdUJBQXVCLEdBR3hCLE1BQU0sd0NBQXdDLENBQUM7QUFDaEQsT0FBTyxFQUdMLHlCQUF5QixHQUMxQixNQUFNLGdFQUFnRSxDQUFDO0FBQ3hFLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBSXpELE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLHFCQUFxQixDQUFDOzs7Ozs7O0FBRXZELElBQUksUUFBUSxHQUFHLENBQUMsQ0FBQztBQWFqQixNQUFNLE9BQU8sa0JBQWtCO0lBb0I3Qix1Q0FBdUM7SUFDdkMsSUFDSSxJQUFJO1FBQ04sT0FBTyxJQUFJLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxRQUFRLEVBQUUsQ0FBQztJQUN4QyxDQUFDO0lBQ0QsSUFBSSxJQUFJLENBQUMsS0FBYztRQUNy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QkFHdEIsT0FBTztzQkFBZixLQUFLO2dCQUdHLE1BQU07c0JBQWQsS0FBSztnQkFJRixJQUFJO3NCQURQLEtBQUs7Z0JBU0csT0FBTztzQkFBZixLQUFLO2dCQUdHLEdBQUc7c0JBQVgsS0FBSztnQkFHTyxlQUFlO3NCQUEzQixLQUFLO2dCQVdHLGFBQWE7c0JBQXJCLEtBQUs7Z0JBSUYsU0FBUztzQkFEWixLQUFLO2dCQWNOLGVBQWU7c0JBRGQsS0FBSztnQkFLTixTQUFTO3NCQURSLEtBQUs7Z0JBSUcsa0JBQWtCO3NCQUExQixLQUFLO2dCQUdHLFFBQVE7c0JBQWhCLEtBQUs7Z0JBR0csV0FBVztzQkFBbkIsS0FBSztnQkFHRyxhQUFhO3NCQUFyQixLQUFLO2dCQUdHLE9BQU87c0JBQWYsS0FBSztnQkFHRyxlQUFlO3NCQUF2QixLQUFLO2dCQUdHLGNBQWM7c0JBQXRCLEtBQUs7Z0JBR0csaUJBQWlCO3NCQUF6QixLQUFLO2dCQUdPLE1BQU07c0JBQWxCLEtBQUs7Z0JBUUcsYUFBYTtzQkFBckIsS0FBSztnQkFHRyxxQkFBcUI7c0JBQTdCLEtBQUs7Z0JBRUcsNEJBQTRCO3NCQUFwQyxLQUFLO2dCQUVHLHNCQUFzQjtzQkFBOUIsS0FBSztnQkFHSSxVQUFVO3NCQUFuQixNQUFNO2dCQUdHLGNBQWM7c0JBQXZCLE1BQU07Z0JBR0csaUJBQWlCO3NCQUExQixNQUFNO2dCQUdHLHdCQUF3QjtzQkFBakMsTUFBTTtnQkFHRyxtQkFBbUI7c0JBQTVCLE1BQU07Z0JBMEJQLE1BQU07c0JBREwsV0FBVzt1QkFBQyxlQUFlO2dCQXNJNUIsZ0JBQWdCO3NCQURmLFlBQVk7dUJBQUMsV0FBVyxFQUFFLENBQUMsUUFBUSxFQUFFLGVBQWUsQ0FBQztnQkFvQnRELGNBQWM7c0JBRGIsWUFBWTt1QkFBQyxTQUFTIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRm9jdXNPcmlnaW4gfSBmcm9tICdAYW5ndWxhci9jZGsvYTExeSc7XHJcbmltcG9ydCB7IGNvZXJjZUFycmF5IH0gZnJvbSAnQGFuZ3VsYXIvY2RrL2NvZXJjaW9uJztcclxuaW1wb3J0IHtcclxuICBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSxcclxuICBDaGFuZ2VEZXRlY3RvclJlZixcclxuICBDb21wb25lbnQsXHJcbiAgRWxlbWVudFJlZixcclxuICBFdmVudEVtaXR0ZXIsXHJcbiAgSG9zdEJpbmRpbmcsXHJcbiAgSG9zdExpc3RlbmVyLFxyXG4gIGluamVjdCxcclxuICBJbnB1dCxcclxuICBPbkNoYW5nZXMsXHJcbiAgT25EZXN0cm95LFxyXG4gIE91dHB1dCxcclxuICBTaW1wbGVDaGFuZ2VzLFxyXG4gIFRlbXBsYXRlUmVmLFxyXG4gIFZpZXdDaGlsZCxcclxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgQmVoYXZpb3JTdWJqZWN0LCBjb21iaW5lTGF0ZXN0LCBTdWJqZWN0IH0gZnJvbSAncnhqcyc7XHJcbmltcG9ydCB7IGRpc3RpbmN0VW50aWxDaGFuZ2VkLCB0YWtlVW50aWwgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XHJcbmltcG9ydCB7XHJcbiAgSW5maW5pdGVTY3JvbGxEaXJlY3RpdmUsXHJcbiAgSW5maW5pdGVTY3JvbGxMb2FkZWRFdmVudCxcclxuICBJbmZpbml0ZVNjcm9sbExvYWRGdW5jdGlvbixcclxufSBmcm9tICcuLi8uLi9kaXJlY3RpdmVzL2luZmluaXRlLXNjcm9sbC9pbmRleCc7XHJcbmltcG9ydCB7XHJcbiAgUG9wb3Zlck9yaWVudGF0aW9uLFxyXG4gIFBvcG92ZXJPcmllbnRhdGlvbkxpc3RlbmVyLFxyXG4gIFBvcG92ZXJPcmllbnRhdGlvblNlcnZpY2UsXHJcbn0gZnJvbSAnLi4vLi4vc2VydmljZXMvcG9wb3Zlci1vcmllbnRhdGlvbi9wb3BvdmVyLW9yaWVudGF0aW9uLnNlcnZpY2UnO1xyXG5pbXBvcnQgeyBUeXBlYWhlYWRPcHRpb25FdmVudCB9IGZyb20gJy4vdHlwZWFoZWFkLWV2ZW50JztcclxuaW1wb3J0IHsgVHlwZWFoZWFkT3B0aW9uQXBpIH0gZnJvbSAnLi90eXBlYWhlYWQtb3B0aW9uLWFwaSc7XHJcbmltcG9ydCB7IFR5cGVhaGVhZE9wdGlvbkNvbnRleHQgfSBmcm9tICcuL3R5cGVhaGVhZC1vcHRpb24tY29udGV4dCc7XHJcbmltcG9ydCB7IFR5cGVhaGVhZFZpc2libGVPcHRpb24gfSBmcm9tICcuL3R5cGVhaGVhZC12aXNpYmxlLW9wdGlvbic7XHJcbmltcG9ydCB7IFR5cGVhaGVhZFNlcnZpY2UgfSBmcm9tICcuL3R5cGVhaGVhZC5zZXJ2aWNlJztcclxuXHJcbmxldCB1bmlxdWVJZCA9IDA7XHJcblxyXG5AQ29tcG9uZW50KHtcclxuICBzZWxlY3RvcjogJ3V4LXR5cGVhaGVhZCcsXHJcbiAgdGVtcGxhdGVVcmw6ICd0eXBlYWhlYWQuY29tcG9uZW50Lmh0bWwnLFxyXG4gIHByb3ZpZGVyczogW1R5cGVhaGVhZFNlcnZpY2UsIFBvcG92ZXJPcmllbnRhdGlvblNlcnZpY2VdLFxyXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxyXG4gIGhvc3Q6IHtcclxuICAgICdbY2xhc3Mub3Blbl0nOiAnb3BlbicsXHJcbiAgICAnW3N0eWxlLm1heEhlaWdodF0nOiAnbWF4SGVpZ2h0JyxcclxuICB9LFxyXG59KVxyXG4gXHJcbmV4cG9ydCBjbGFzcyBUeXBlYWhlYWRDb21wb25lbnQ8VCA9IGFueT4gaW1wbGVtZW50cyBPbkNoYW5nZXMsIE9uRGVzdHJveSB7XHJcbiAgcmVhZG9ubHkgdHlwZWFoZWFkRWxlbWVudCA9IGluamVjdChFbGVtZW50UmVmKTtcclxuXHJcbiAgcmVhZG9ubHkgcG9wb3Zlck9yaWVudGF0aW9uID0gaW5qZWN0KFBvcG92ZXJPcmllbnRhdGlvblNlcnZpY2UpO1xyXG5cclxuICBwcml2YXRlIHJlYWRvbmx5IF9jaGFuZ2VEZXRlY3RvciA9IGluamVjdChDaGFuZ2VEZXRlY3RvclJlZik7XHJcblxyXG4gIHByaXZhdGUgcmVhZG9ubHkgX3NlcnZpY2UgPSBpbmplY3QoVHlwZWFoZWFkU2VydmljZSk7XHJcblxyXG4gIEBWaWV3Q2hpbGQoSW5maW5pdGVTY3JvbGxEaXJlY3RpdmUpIGluZmluaXRlU2Nyb2xsOiBJbmZpbml0ZVNjcm9sbERpcmVjdGl2ZTtcclxuXHJcbiAgLyoqIERlZmluZSBhIHVuaXF1ZSBpZCBmb3IgdGhlIHR5cGVhaGVhZCAqL1xyXG4gIEBJbnB1dCgpIEBIb3N0Qmlu