UNPKG

@ux-aspects/ux-aspects

Version:

Open source user interface framework for building modern, responsive, mobile big data applications

410 lines 79.4 kB
import { coerceBooleanProperty, coerceNumberProperty } from '@angular/cdk/coercion'; import { ENTER } from '@angular/cdk/keycodes'; import { Platform } from '@angular/cdk/platform'; import { DOCUMENT } from '@angular/common'; import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ContentChild, ElementRef, EventEmitter, forwardRef, HostBinding, inject, Input, Output, ViewChild } from '@angular/core'; import { NG_VALUE_ACCESSOR } from '@angular/forms'; import { BehaviorSubject, ReplaySubject, Subject } from 'rxjs'; import { debounceTime, delay, distinctUntilChanged, filter, map, skip, take, takeUntil } from 'rxjs/operators'; import { TypeaheadKeyService } from '../typeahead/index'; import * as i0 from "@angular/core"; import * as i1 from "../../directives/accessibility/focus-indicator/focus-indicator.directive"; import * as i2 from "@angular/common"; import * as i3 from "@angular/forms"; import * as i4 from "../tag-input/tag-input.component"; import * as i5 from "../typeahead/typeahead.component"; let uniqueId = 0; export const SELECT_VALUE_ACCESSOR = { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => SelectComponent), multi: true }; export class SelectComponent { constructor() { this._element = inject(ElementRef); this._platform = inject(Platform); this._typeaheadKeyService = inject(TypeaheadKeyService); this._changeDetector = inject(ChangeDetectorRef); this._document = inject(DOCUMENT); /** A unique id for the component. */ this.id = `ux-select-${++uniqueId}`; /** * Controls whether the value of the single select control can be cleared by deleting the selected value in the * input field. This does not affect the initial state of the control, so specify a value for `value` if null should * never be allowed. */ this.allowNull = false; /** Controls the disabled state of the tag input. */ this.disabled = false; /** The positioning of the typeahead dropdown in relation to its parent. */ this.dropDirection = 'down'; /** The maximum height of the typeahead dropdown, as a CSS value. */ this.maxHeight = '250px'; /** * Controls whether the user can select more than one option in the select control. If set to true, selected * options will appear as tags in the input area. If set to false, the selected value will appear as editable text * in the input area. */ this.multiple = false; /** * The number of options to request in a page. This should ideally be more than twice the number of items which * fit into the height of the dropdown, but this is not required. */ this.pageSize = 20; /** The placeholder text which appears in the text input area when it is empty. */ this.placeholder = ''; /** * Defines the `autocomplete` property on the `input` element which can be used to prevent the browser from * displaying autocomplete suggestions. */ this.autocomplete = 'off'; /** If `true` the input field will be readonly and selection can only occur by using the dropdown. */ this.readonlyInput = false; /** Determine if we should show the clear all button */ this.clearButton = false; /** Determine an aria label for the clear button */ this.clearButtonAriaLabel = 'Reset selection'; /** Emits when `value` changes. */ this.valueChange = new EventEmitter(); /** Emits when `input` changes. */ this.inputChange = new EventEmitter(); /** Emits when `dropdownOpen` changes. */ this.dropdownOpenChange = new EventEmitter(); /** Emits when recently selected options change. */ this.recentOptionsChange = new EventEmitter(); this._value$ = new ReplaySubject(1); this._hasValue = false; this._input$ = new BehaviorSubject({ userInteraction: false, value: '' }); this._dropdownOpen = false; this._userInput = false; this._filterDebounceTime = 200; this._autoCloseDropdown = true; // eslint-disable-next-line @typescript-eslint/no-empty-function this._onChange = (_) => { }; // eslint-disable-next-line @typescript-eslint/no-empty-function this._onTouched = () => { }; this._onDestroy = new Subject(); } /** The selected option (for single select) or array of options (for multiple select). */ set value(value) { this._value$.next(value); } get value() { return this._value; } /** The text in the input area. This is used to filter the options dropdown. */ set input(value) { this._input$.next({ ...this._input$.value, value }); } get input() { return this._input$.value.value; } /** The status of the typeahead dropdown. */ set dropdownOpen(value) { this._dropdownOpen = value; this.dropdownOpenChange.emit(value); } get dropdownOpen() { return this._dropdownOpen; } /** Determine if the dropdown panel should close on external click.*/ set autoCloseDropdown(value) { this._autoCloseDropdown = coerceBooleanProperty(value); } get autoCloseDropdown() { return this._autoCloseDropdown; } /** Specify the debounceTime value for the select filter */ get filterDebounceTime() { return this._filterDebounceTime; } set filterDebounceTime(filterDebounceTime) { this._filterDebounceTime = coerceNumberProperty(filterDebounceTime); } ngOnInit() { // Emit change events this._value$.pipe(takeUntil(this._onDestroy), distinctUntilChanged()).subscribe(value => { this._value = value; this._hasValue = !!value; }); // Changes to the input field this._input$.pipe(skip(1), filter(() => this.allowNull), filter(value => !this.multiple && value.value !== this.getDisplay(this.value)), takeUntil(this._onDestroy)).subscribe((input) => { if (input.userInteraction && input.value === '') { this.value = null; this._onChange(null); this.valueChange.next(null); } }); // open the dropdown once the filter debounce has elapsed this.filter$.pipe(filter(() => this._userInput), take(1), takeUntil(this._onDestroy)) .subscribe(() => { this.dropdownOpen = true; this._userInput = false; }); // Update the single-select input when the model changes this._value$.pipe(distinctUntilChanged(), delay(0), filter(value => value !== null && !this.multiple), takeUntil(this._onDestroy)).subscribe(value => { const inputValue = this.getDisplay(value); // check if the input value has changed and if so the emit if (inputValue !== this.input) { this.input = inputValue; this.inputChange.emit(this.input); } this._changeDetector.markForCheck(); }); } ngOnChanges(changes) { if (changes.multiple && !changes.multiple.firstChange && changes.multiple.currentValue !== changes.multiple.previousValue) { this.input = ''; } // Set up filter from input this.filter$ = this._input$.pipe(map(input => !this.multiple && input.value === this.getDisplay(this.value) ? '' : input.value), debounceTime(this.filterDebounceTime)); } ngOnDestroy() { this._onDestroy.next(); this._onDestroy.complete(); } writeValue(obj) { if (obj !== undefined && obj !== this.value) { this.value = obj; this._changeDetector.markForCheck(); } } registerOnChange(fn) { this._onChange = fn; } registerOnTouched(fn) { this._onTouched = fn; } setDisabledState(isDisabled) { this.disabled = isDisabled; this._changeDetector.markForCheck(); } inputClickHandler() { this.selectInputText(); this.dropdownOpen = true; } inputBlurHandler() { // If a click on the typeahead is in progress, just refocus the input. // This works around an issue in IE where clicking a scrollbar drops focus. if (this.singleTypeahead && this.singleTypeahead.clicking) { this.singleInput.nativeElement.focus(); return; } // Close dropdown and reset text input if focus is lost setTimeout(() => { if (!this._element.nativeElement.contains(this._document.activeElement) && this._autoCloseDropdown) { this.dropdownOpen = false; if (!this.multiple) { this.input = this.getDisplay(this.value); } } }, 200); } /** * Key handler for single select only. Multiple select key handling is in TagInputComponent. */ inputKeyHandler(event) { // Standard keys for typeahead (up/down/esc) this._typeaheadKeyService.handleKey(event, this.singleTypeahead); if (event.keyCode === ENTER) { if (this._dropdownOpen) { // Set the highlighted option as the value and close this.singleTypeahead.selectHighlighted(); } else { this.dropdownOpen = true; } // Update the input field. If dropdown isn't open then reset it to the previous value. this.input = this.getDisplay(this.value); event.preventDefault(); } // when the user types and the value is not empty then we should open the dropdown except for non printable keys. if (event.key.length === 1) { this._userInput = true; this._dropdownOpen = true; } } /** This gets called whenever the user types in the input */ onInputChange(input) { this._input$.next({ value: input, userInteraction: true }); this.inputChange.emit(this.input); } /** Whenever a single select item is selected emit the values */ _singleOptionSelected(event) { if (event.option !== null && event.option !== this.value) { this.value = event.option; this.dropdownOpen = false; this.valueChange.emit(this.value); this._onChange(this.value); } } /** Whenever a multi-select item is selected emit the values */ _multipleOptionSelected(selection) { // update the internal selection this._value$.next(selection); this.valueChange.emit(this.value); this._onChange(this.value); } /** * Returns the display value of the given option. */ getDisplay(option) { if (option === null || option === undefined) { return ''; } if (typeof this.display === 'function') { return this.display(option); } // eslint-disable-next-line no-prototype-builtins if (typeof this.display === 'string' && typeof option === 'object' && option.hasOwnProperty(this.display)) { return option[this.display]; } return option; } /** Toggle the dropdown open state */ toggle() { // if the select is disabled then do not show the dropdown if (this.disabled) { return; } if (this.dropdownOpen) { this.dropdownOpen = false; } else { this.inputClickHandler(); } } /** Handle input focus events */ onFocus() { // mark form control as touched this._onTouched(); // if the input is readonly we do not want to select the text on focus if (this.readonlyInput) { // cast the select input element const element = this.singleInput.nativeElement; // firefox requires a delay before clearing the selection (other browsers don't) this._platform.FIREFOX ? requestAnimationFrame(() => element.setSelectionRange(0, 0)) : element.setSelectionRange(0, 0); } } clear() { if (this.disabled) { return; } // clear the value and input text this.value = null; this.input = null; this.selectInputText(); // emit the latest values this.valueChange.emit(this.value); this._onChange(this.value); this.inputChange.emit(this.input); } selectInputText() { if (!this.readonlyInput) { this.singleInput.nativeElement.select(); } } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: SelectComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.12", type: SelectComponent, selector: "ux-select, ux-combobox, ux-dropdown", inputs: { id: "id", value: "value", input: "input", dropdownOpen: "dropdownOpen", options: "options", display: "display", key: "key", allowNull: "allowNull", ariaLabel: "ariaLabel", ariaLabelledby: "ariaLabelledby", listboxAriaLabel: "listboxAriaLabel", disabled: "disabled", dropDirection: "dropDirection", maxHeight: "maxHeight", multiple: "multiple", pageSize: "pageSize", placeholder: "placeholder", tagTemplate: "tagTemplate", optionsHeadingTemplate: "optionsHeadingTemplate", recentOptionsHeadingTemplate: "recentOptionsHeadingTemplate", autocomplete: "autocomplete", loadingTemplate: "loadingTemplate", noOptionsTemplate: "noOptionsTemplate", readonlyInput: "readonlyInput", clearButton: "clearButton", clearButtonAriaLabel: "clearButtonAriaLabel", autoCloseDropdown: "autoCloseDropdown", optionTemplate: "optionTemplate", recentOptions: "recentOptions", recentOptionsMaxCount: "recentOptionsMaxCount", required: "required", filterDebounceTime: "filterDebounceTime" }, outputs: { valueChange: "valueChange", inputChange: "inputChange", dropdownOpenChange: "dropdownOpenChange", recentOptionsChange: "recentOptionsChange" }, host: { properties: { "class.ux-select-custom-icon": "!!icon", "class.ux-select-disabled": "disabled", "attr.id": "this.id" } }, providers: [SELECT_VALUE_ACCESSOR], queries: [{ propertyName: "icon", first: true, predicate: ["icon"], descendants: true }], viewQueries: [{ propertyName: "singleInput", first: true, predicate: ["singleInput"], descendants: true }, { propertyName: "tagInput", first: true, predicate: ["tagInput"], descendants: true }, { propertyName: "multipleTypeahead", first: true, predicate: ["multipleTypeahead"], descendants: true }, { propertyName: "singleTypeahead", first: true, predicate: ["singleTypeahead"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "@if (multiple) {\n <ux-tag-input\n #tagInput=\"ux-tag-input\"\n [id]=\"id + '-input'\"\n [tags]=\"_value$ | async\"\n (tagsChange)=\"_multipleOptionSelected($event)\"\n [ariaLabelledby]=\"ariaLabelledby\"\n [(input)]=\"input\"\n [required]=\"required\"\n (inputChange)=\"onInputChange($event)\"\n [ariaLabel]=\"ariaLabel\"\n [autocomplete]=\"autocomplete\"\n [addOnPaste]=\"false\"\n [disabled]=\"disabled\"\n [display]=\"display\"\n [freeInput]=\"false\"\n [placeholder]=\"placeholder || ''\"\n [tagTemplate]=\"tagTemplate\"\n (inputFocus)=\"onFocus()\"\n [showTypeaheadOnClick]=\"true\"\n [readonlyInput]=\"readonlyInput\"\n [icon]=\"icon\"\n [clearButton]=\"clearButton\"\n [autoCloseDropdown]=\"autoCloseDropdown\"\n [clearButtonAriaLabel]=\"clearButtonAriaLabel\">\n <ux-typeahead #multipleTypeahead\n [ariaLabel]=\"listboxAriaLabel\"\n [id]=\"id + '-typeahead'\"\n [options]=\"options\"\n [filter]=\"filter$ | async\"\n [(open)]=\"dropdownOpen\"\n [display]=\"display\"\n [key]=\"key\"\n [disabledOptions]=\"_value$ | async\"\n [dropDirection]=\"dropDirection\"\n [maxHeight]=\"maxHeight\"\n [multiselectable]=\"true\"\n [pageSize]=\"pageSize\"\n [selectFirst]=\"true\"\n [loadingTemplate]=\"loadingTemplate\"\n [optionTemplate]=\"optionTemplate\"\n [noOptionsTemplate]=\"noOptionsTemplate\"\n [recentOptions]=\"recentOptions\"\n [recentOptionsMaxCount]=\"recentOptionsMaxCount\"\n (recentOptionsChange)=\"recentOptionsChange.emit($event)\"\n [optionsHeadingTemplate]=\"optionsHeadingTemplate\"\n [recentOptionsHeadingTemplate]=\"recentOptionsHeadingTemplate\">\n </ux-typeahead>\n </ux-tag-input>\n}\n\n@if (!multiple) {\n <div\n class=\"ux-select-container\"\n [class.disabled]=\"disabled\"\n aria-haspopup=\"listbox\">\n <input #singleInput type=\"text\"\n [attr.id]=\"id + '-input'\"\n [attr.aria-labelledby]=\"ariaLabelledby\"\n class=\"form-control\"\n [required]=\"required\"\n [class.ux-tag-input-clear-inset]=\"clearButton && allowNull && _hasValue\"\n [attr.aria-activedescendant]=\"highlightedElement?.id\"\n aria-autocomplete=\"list\"\n role=\"combobox\"\n [attr.aria-controls]=\"id + '-typeahead'\"\n [attr.aria-label]=\"ariaLabel\"\n [attr.aria-expanded]=\"dropdownOpen\"\n [autocomplete]=\"autocomplete\"\n [(ngModel)]=\"input\"\n (ngModelChange)=\"onInputChange($event)\"\n [placeholder]=\"placeholder || ''\"\n [disabled]=\"disabled\"\n (click)=\"toggle()\"\n (focus)=\"onFocus()\"\n (blur)=\"inputBlurHandler()\"\n (keydown)=\"inputKeyHandler($event)\"\n [readonly]=\"readonlyInput\">\n <div class=\"ux-select-icons\">\n @if (clearButton && allowNull && _hasValue) {\n <i\n uxFocusIndicator\n [attr.tabindex]=\"disabled ? -1 : 0\"\n [attr.aria-label]=\"clearButtonAriaLabel\"\n class=\"ux-select-icon ux-icon ux-icon-close ux-select-clear-icon\"\n (click)=\"clear(); $event.stopPropagation()\"\n (keydown.enter)=\"clear(); $event.stopPropagation()\">\n </i>\n }\n @if (!icon) {\n <i\n class=\"ux-select-icon ux-icon ux-select-chevron-icon\"\n [class.ux-icon-up]=\"dropDirection === 'up'\"\n [class.ux-icon-down]=\"dropDirection === 'down'\"\n (click)=\"toggle(); $event.stopPropagation(); singleInput.focus();\">\n </i>\n }\n @if (icon) {\n <div class=\"ux-custom-icon\">\n <ng-container [ngTemplateOutlet]=\"icon\"></ng-container>\n </div>\n }\n </div>\n <ux-typeahead #singleTypeahead\n [ariaLabel]=\"listboxAriaLabel\"\n [id]=\"id + '-typeahead'\"\n [active]=\"_value$ | async\"\n [options]=\"options\"\n [filter]=\"filter$ | async\"\n [(open)]=\"dropdownOpen\"\n [display]=\"display\"\n [key]=\"key\"\n [dropDirection]=\"dropDirection\"\n [maxHeight]=\"maxHeight\"\n [multiselectable]=\"false\"\n [openOnFilterChange]=\"false\"\n [pageSize]=\"pageSize\"\n [selectFirst]=\"true\"\n [loadingTemplate]=\"loadingTemplate\"\n [optionTemplate]=\"optionTemplate\"\n [noOptionsTemplate]=\"noOptionsTemplate\"\n [recentOptions]=\"recentOptions\"\n [recentOptionsMaxCount]=\"recentOptionsMaxCount\"\n [optionsHeadingTemplate]=\"optionsHeadingTemplate\"\n [recentOptionsHeadingTemplate]=\"recentOptionsHeadingTemplate\"\n (optionSelected)=\"_singleOptionSelected($event)\"\n (highlightedElementChange)=\"highlightedElement = $event\"\n (recentOptionsChange)=\"recentOptionsChange.emit($any($event))\">\n </ux-typeahead>\n </div>\n }\n", dependencies: [{ kind: "directive", type: i1.FocusIndicatorDirective, selector: "[uxFocusIndicator]", inputs: ["checkChildren", "mouseFocusIndicator", "touchFocusIndicator", "keyboardFocusIndicator", "programmaticFocusIndicator"], outputs: ["indicator"], exportAs: ["ux-focus-indicator"] }, { kind: "directive", type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i4.TagInputComponent, selector: "ux-tag-input", inputs: ["id", "tags", "input", "display", "addOnPaste", "ariaLabel", "ariaLabelledby", "disabled", "required", "enforceTagLimits", "freeInput", "readonlyInput", "maxTags", "minTags", "placeholder", "showTypeaheadOnClick", "tagDelimiters", "tagPattern", "tagTemplate", "tagClass", "validationErrors", "autocomplete", "createTag", "icon", "clearButton", "clearButtonAriaLabel", "autoCloseDropdown"], outputs: ["tagsChange", "inputChange", "tagAdding", "tagAdded", "tagInvalidated", "tagRemoving", "tagRemoved", "tagClick", "inputFocus", "inputBlur"], exportAs: ["ux-tag-input"] }, { kind: "component", type: i5.TypeaheadComponent, selector: "ux-typeahead", inputs: ["id", "options", "filter", "open", "display", "key", "disabledOptions", "dropDirection", "maxHeight", "multiselectable", "ariaLabel", "openOnFilterChange", "pageSize", "selectFirst", "selectOnEnter", "loading", "loadingTemplate", "optionTemplate", "noOptionsTemplate", "active", "recentOptions", "recentOptionsMaxCount", "recentOptionsHeadingTemplate", "optionsHeadingTemplate"], outputs: ["openChange", "optionSelected", "highlightedChange", "highlightedElementChange", "recentOptionsChange"] }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: SelectComponent, decorators: [{ type: Component, args: [{ selector: 'ux-select, ux-combobox, ux-dropdown', providers: [SELECT_VALUE_ACCESSOR], host: { '[class.ux-select-custom-icon]': '!!icon', '[class.ux-select-disabled]': 'disabled' }, changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (multiple) {\n <ux-tag-input\n #tagInput=\"ux-tag-input\"\n [id]=\"id + '-input'\"\n [tags]=\"_value$ | async\"\n (tagsChange)=\"_multipleOptionSelected($event)\"\n [ariaLabelledby]=\"ariaLabelledby\"\n [(input)]=\"input\"\n [required]=\"required\"\n (inputChange)=\"onInputChange($event)\"\n [ariaLabel]=\"ariaLabel\"\n [autocomplete]=\"autocomplete\"\n [addOnPaste]=\"false\"\n [disabled]=\"disabled\"\n [display]=\"display\"\n [freeInput]=\"false\"\n [placeholder]=\"placeholder || ''\"\n [tagTemplate]=\"tagTemplate\"\n (inputFocus)=\"onFocus()\"\n [showTypeaheadOnClick]=\"true\"\n [readonlyInput]=\"readonlyInput\"\n [icon]=\"icon\"\n [clearButton]=\"clearButton\"\n [autoCloseDropdown]=\"autoCloseDropdown\"\n [clearButtonAriaLabel]=\"clearButtonAriaLabel\">\n <ux-typeahead #multipleTypeahead\n [ariaLabel]=\"listboxAriaLabel\"\n [id]=\"id + '-typeahead'\"\n [options]=\"options\"\n [filter]=\"filter$ | async\"\n [(open)]=\"dropdownOpen\"\n [display]=\"display\"\n [key]=\"key\"\n [disabledOptions]=\"_value$ | async\"\n [dropDirection]=\"dropDirection\"\n [maxHeight]=\"maxHeight\"\n [multiselectable]=\"true\"\n [pageSize]=\"pageSize\"\n [selectFirst]=\"true\"\n [loadingTemplate]=\"loadingTemplate\"\n [optionTemplate]=\"optionTemplate\"\n [noOptionsTemplate]=\"noOptionsTemplate\"\n [recentOptions]=\"recentOptions\"\n [recentOptionsMaxCount]=\"recentOptionsMaxCount\"\n (recentOptionsChange)=\"recentOptionsChange.emit($event)\"\n [optionsHeadingTemplate]=\"optionsHeadingTemplate\"\n [recentOptionsHeadingTemplate]=\"recentOptionsHeadingTemplate\">\n </ux-typeahead>\n </ux-tag-input>\n}\n\n@if (!multiple) {\n <div\n class=\"ux-select-container\"\n [class.disabled]=\"disabled\"\n aria-haspopup=\"listbox\">\n <input #singleInput type=\"text\"\n [attr.id]=\"id + '-input'\"\n [attr.aria-labelledby]=\"ariaLabelledby\"\n class=\"form-control\"\n [required]=\"required\"\n [class.ux-tag-input-clear-inset]=\"clearButton && allowNull && _hasValue\"\n [attr.aria-activedescendant]=\"highlightedElement?.id\"\n aria-autocomplete=\"list\"\n role=\"combobox\"\n [attr.aria-controls]=\"id + '-typeahead'\"\n [attr.aria-label]=\"ariaLabel\"\n [attr.aria-expanded]=\"dropdownOpen\"\n [autocomplete]=\"autocomplete\"\n [(ngModel)]=\"input\"\n (ngModelChange)=\"onInputChange($event)\"\n [placeholder]=\"placeholder || ''\"\n [disabled]=\"disabled\"\n (click)=\"toggle()\"\n (focus)=\"onFocus()\"\n (blur)=\"inputBlurHandler()\"\n (keydown)=\"inputKeyHandler($event)\"\n [readonly]=\"readonlyInput\">\n <div class=\"ux-select-icons\">\n @if (clearButton && allowNull && _hasValue) {\n <i\n uxFocusIndicator\n [attr.tabindex]=\"disabled ? -1 : 0\"\n [attr.aria-label]=\"clearButtonAriaLabel\"\n class=\"ux-select-icon ux-icon ux-icon-close ux-select-clear-icon\"\n (click)=\"clear(); $event.stopPropagation()\"\n (keydown.enter)=\"clear(); $event.stopPropagation()\">\n </i>\n }\n @if (!icon) {\n <i\n class=\"ux-select-icon ux-icon ux-select-chevron-icon\"\n [class.ux-icon-up]=\"dropDirection === 'up'\"\n [class.ux-icon-down]=\"dropDirection === 'down'\"\n (click)=\"toggle(); $event.stopPropagation(); singleInput.focus();\">\n </i>\n }\n @if (icon) {\n <div class=\"ux-custom-icon\">\n <ng-container [ngTemplateOutlet]=\"icon\"></ng-container>\n </div>\n }\n </div>\n <ux-typeahead #singleTypeahead\n [ariaLabel]=\"listboxAriaLabel\"\n [id]=\"id + '-typeahead'\"\n [active]=\"_value$ | async\"\n [options]=\"options\"\n [filter]=\"filter$ | async\"\n [(open)]=\"dropdownOpen\"\n [display]=\"display\"\n [key]=\"key\"\n [dropDirection]=\"dropDirection\"\n [maxHeight]=\"maxHeight\"\n [multiselectable]=\"false\"\n [openOnFilterChange]=\"false\"\n [pageSize]=\"pageSize\"\n [selectFirst]=\"true\"\n [loadingTemplate]=\"loadingTemplate\"\n [optionTemplate]=\"optionTemplate\"\n [noOptionsTemplate]=\"noOptionsTemplate\"\n [recentOptions]=\"recentOptions\"\n [recentOptionsMaxCount]=\"recentOptionsMaxCount\"\n [optionsHeadingTemplate]=\"optionsHeadingTemplate\"\n [recentOptionsHeadingTemplate]=\"recentOptionsHeadingTemplate\"\n (optionSelected)=\"_singleOptionSelected($event)\"\n (highlightedElementChange)=\"highlightedElement = $event\"\n (recentOptionsChange)=\"recentOptionsChange.emit($any($event))\">\n </ux-typeahead>\n </div>\n }\n" }] }], propDecorators: { id: [{ type: Input }, { type: HostBinding, args: ['attr.id'] }], value: [{ type: Input }], input: [{ type: Input }], dropdownOpen: [{ type: Input }], options: [{ type: Input }], display: [{ type: Input }], key: [{ type: Input }], allowNull: [{ type: Input }], ariaLabel: [{ type: Input }], ariaLabelledby: [{ type: Input }], listboxAriaLabel: [{ type: Input }], disabled: [{ type: Input }], dropDirection: [{ type: Input }], maxHeight: [{ type: Input }], multiple: [{ type: Input }], pageSize: [{ type: Input }], placeholder: [{ type: Input }], tagTemplate: [{ type: Input }], optionsHeadingTemplate: [{ type: Input }], recentOptionsHeadingTemplate: [{ type: Input }], autocomplete: [{ type: Input }], loadingTemplate: [{ type: Input }], noOptionsTemplate: [{ type: Input }], readonlyInput: [{ type: Input }], clearButton: [{ type: Input }], clearButtonAriaLabel: [{ type: Input }], autoCloseDropdown: [{ type: Input }], optionTemplate: [{ type: Input }], recentOptions: [{ type: Input }], recentOptionsMaxCount: [{ type: Input }], required: [{ type: Input }], filterDebounceTime: [{ type: Input }], valueChange: [{ type: Output }], inputChange: [{ type: Output }], dropdownOpenChange: [{ type: Output }], recentOptionsChange: [{ type: Output }], icon: [{ type: ContentChild, args: ['icon', { static: false }] }], singleInput: [{ type: ViewChild, args: ['singleInput', { static: false }] }], tagInput: [{ type: ViewChild, args: ['tagInput', { static: false }] }], multipleTypeahead: [{ type: ViewChild, args: ['multipleTypeahead', { static: false }] }], singleTypeahead: [{ type: ViewChild, args: ['singleTypeahead', { static: false }] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VsZWN0LmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9jb21wb25lbnRzL3NlbGVjdC9zZWxlY3QuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vc3JjL2NvbXBvbmVudHMvc2VsZWN0L3NlbGVjdC5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQWdCLHFCQUFxQixFQUFFLG9CQUFvQixFQUFlLE1BQU0sdUJBQXVCLENBQUM7QUFDL0csT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQzlDLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUNqRCxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDM0MsT0FBTyxFQUFFLHVCQUF1QixFQUFFLGlCQUFpQixFQUFFLFNBQVMsRUFBRSxZQUFZLEVBQUUsVUFBVSxFQUFFLFlBQVksRUFBRSxVQUFVLEVBQUUsV0FBVyxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQWdDLE1BQU0sRUFBOEMsU0FBUyxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ25RLE9BQU8sRUFBd0IsaUJBQWlCLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUN6RSxPQUFPLEVBQUUsZUFBZSxFQUFjLGFBQWEsRUFBRSxPQUFPLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDM0UsT0FBTyxFQUFFLFlBQVksRUFBRSxLQUFLLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSxFQUFFLEdBQUcsRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBRy9HLE9BQU8sRUFBc0IsbUJBQW1CLEVBQXdCLE1BQU0sb0JBQW9CLENBQUM7Ozs7Ozs7QUFHbkcsSUFBSSxRQUFRLEdBQUcsQ0FBQyxDQUFDO0FBRWpCLE1BQU0sQ0FBQyxNQUFNLHFCQUFxQixHQUFtQjtJQUNq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QixFQUFFLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRTtnQkFDQSxlQUFlO3NCQUEvRCxTQUFTO3VCQUFDLGlCQUFpQixFQUFFLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEJvb2xlYW5JbnB1dCwgY29lcmNlQm9vbGVhblByb3BlcnR5LCBjb2VyY2VOdW1iZXJQcm9wZXJ0eSwgTnVtYmVySW5wdXQgfSBmcm9tICdAYW5ndWxhci9jZGsvY29lcmNpb24nO1xyXG5pbXBvcnQgeyBFTlRFUiB9IGZyb20gJ0Bhbmd1bGFyL2Nkay9rZXljb2Rlcyc7XHJcbmltcG9ydCB7IFBsYXRmb3JtIH0gZnJvbSAnQGFuZ3VsYXIvY2RrL3BsYXRmb3JtJztcclxuaW1wb3J0IHsgRE9DVU1FTlQgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xyXG5pbXBvcnQgeyBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSwgQ2hhbmdlRGV0ZWN0b3JSZWYsIENvbXBvbmVudCwgQ29udGVudENoaWxkLCBFbGVtZW50UmVmLCBFdmVudEVtaXR0ZXIsIGZvcndhcmRSZWYsIEhvc3RCaW5kaW5nLCBpbmplY3QsIElucHV0LCBPbkNoYW5nZXMsIE9uRGVzdHJveSwgT25Jbml0LCBPdXRwdXQsIFNpbXBsZUNoYW5nZXMsIFN0YXRpY1Byb3ZpZGVyLCBUZW1wbGF0ZVJlZiwgVmlld0NoaWxkIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7IENvbnRyb2xWYWx1ZUFjY2Vzc29yLCBOR19WQUxVRV9BQ0NFU1NPUiB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcclxuaW1wb3J0IHsgQmVoYXZpb3JTdWJqZWN0LCBPYnNlcnZhYmxlLCBSZXBsYXlTdWJqZWN0LCBTdWJqZWN0IH0gZnJvbSAncnhqcyc7XHJcbmltcG9ydCB7IGRlYm91bmNlVGltZSwgZGVsYXksIGRpc3RpbmN0VW50aWxDaGFuZ2VkLCBmaWx0ZXIsIG1hcCwgc2tpcCwgdGFrZSwgdGFrZVVudGlsIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xyXG5pbXBvcnQgeyBJbmZpbml0ZVNjcm9sbExvYWRGdW5jdGlvbiB9IGZyb20gJy4uLy4uL2RpcmVjdGl2ZXMvaW5maW5pdGUtc2Nyb2xsL2luZGV4JztcclxuaW1wb3J0IHsgVGFnSW5wdXRDb21wb25lbnQsIFRhZ1RlbXBsYXRlQ29udGV4dCB9IGZyb20gJy4uL3RhZy1pbnB1dC9pbmRleCc7XHJcbmltcG9ydCB7IFR5cGVhaGVhZENvbXBvbmVudCwgVHlwZWFoZWFkS2V5U2VydmljZSwgVHlwZWFoZWFkT3B0aW9uRXZlbnQgfSBmcm9tICcuLi90eXBlYWhlYWQvaW5kZXgnO1xyXG5pbXBvcnQgeyBUeXBlYWhlYWRPcHRpb25Db250ZXh0IH0gZnJvbSAnLi4vdHlwZWFoZWFkL3R5cGVhaGVhZC1vcHRpb24tY29udGV4dCc7XHJcblxyXG5sZXQgdW5pcXVlSWQgPSAwO1xyXG5cclxuZXhwb3J0IGNvbnN0IFNFTEVDVF9WQUxVRV9BQ0NFU1NPUjogU3RhdGljUHJvdmlkZXIgPSB7XHJcbiAgICBwcm92aWRlOiBOR19WQUxVRV9BQ0NFU1NPUixcclxuICAgIHVzZUV4aXN0aW5nOiBmb3J3YXJkUmVmKCgpID0+IFNlbGVjdENvbXBvbmVudCksXHJcbiAgICBtdWx0aTogdHJ1ZVxyXG59O1xyXG5cclxuQENvbXBvbmVudCh7XHJcbiAgICBzZWxlY3RvcjogJ3V4LXNlbGVjdCwgdXgtY29tYm9ib3gsIHV4LWRyb3Bkb3duJyxcclxuICAgIHRlbXBsYXRlVXJsOiAnc2VsZWN0LmNvbXBvbmVudC5odG1sJyxcclxuICAgIHByb3ZpZGVyczogW1NFTEVDVF9WQUxVRV9BQ0NFU1NPUl0sXHJcbiAgICBob3N0OiB7XHJcbiAgICAgICAgJ1tjbGFzcy51eC1zZWxlY3QtY3VzdG9tLWljb25dJzogJyEhaWNvbicsXHJcbiAgICAgICAgJ1tjbGFzcy51eC1zZWxlY3QtZGlzYWJsZWRdJzogJ2Rpc2FibGVkJ1xyXG4gICAgfSxcclxuICAgIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxyXG59KVxyXG5leHBvcnQgY2xhc3MgU2VsZWN0Q29tcG9uZW50PFQ+IGltcGxlbWVudHMgT25Jbml0LCBPbkNoYW5nZXMsIE9uRGVzdHJveSwgQ29udHJvbFZhbHVlQWNjZXNzb3Ige1xyXG4gICAgcHJpdmF0ZSByZWFkb25seSBfZWxlbWVudCA9IGluamVjdChFbGVtZW50UmVmKTtcclxuXHJcbiAgICBwcml2YXRlIHJlYWRvbmx5IF9wbGF0Zm9ybSA9IGluamVjdChQbGF0Zm9ybSk7XHJcblxyXG4gICAgcHJpdmF0ZSByZWFkb25seSBfdHlwZWFoZWFkS2V5U2VydmljZSA9IGluamVjdChUeXBlYWhlYWRLZXlTZXJ2aWNlKTtcclxuXHJcbiAgICBwcml2YXRlIHJlYWRvbmx5IF9jaGFuZ2VEZXRlY3RvciA9IGluamVjdChDaGFuZ2VEZXRlY3RvclJlZik7XHJcblxyXG4gICAgcHJpdmF0ZSByZWFkb25seSBfZG9jdW1lbnQgPSBpbmplY3Q8RG9jdW1lbnQ+KERPQ1VNRU5UKTtcclxuXHJcbiAgICAvKiogQSB1bmlxdWUgaWQgZm9yIHRoZSBjb21wb25lbnQuICovXHJcbiAgICBASW5wdXQoKSBASG9zdEJpbmRpbmcoJ2F0dHIuaWQnKSBpZDogc3RyaW5nID0gYHV4LXNlbGVjdC0keysrdW5pcXVlSWR9YDtcclxuXHJcbiAgICAvKiogVGhlIHNlbGVjdGVkIG9wdGlvbiAoZm9yIHNpbmdsZSBzZWxlY3QpIG9yIGFycmF5IG9mIG9wdGlvbnMgKGZvciBtdWx0aXBsZSBzZWxlY3QpLiAqL1xyXG4gICAgQElucHV0KClcclxuICAgIHNldCB2YWx1ZSh2YWx1ZTogVCB8IFJlYWRvbmx5QXJyYXk8VD4pIHtcclxuICAgICAgICB0aGlzLl92YWx1ZSQubmV4dCh2YWx1ZSk7XHJcbiAgICB9XHJcblxyXG4gICAgZ2V0IHZhbHVlKCk6IFQgfCBSZWFkb25seUFycmF5PFQ+IHtcclxuICAgICAgICByZXR1cm4gdGhpcy5fdmFsdWU7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqIFRoZSB0ZXh0IGluIHRoZSBpbnB1dCBhcmVhLiBUaGlzIGlzIHVzZWQgdG8gZmlsdGVyIHRoZSBvcHRpb25zIGRyb3Bkb3duLiAqL1xyXG4gICAgQElucHV0KClcclxuICAgIHNldCBpbnB1dCh2YWx1ZTogc3RyaW5nKSB7XHJcbiAgICAgICAgdGhpcy5faW5wdXQkLm5leHQoeyAuLi50aGlzLl9pbnB1dCQudmFsdWUsIHZhbHVlIH0pO1xyXG4gICAgfVxyXG4gICAgZ2V0IGlucHV0KCkge1xyXG4gICAgICAgIHJldHVybiB0aGlzLl9pbnB1dCQudmFsdWUudmFsdWU7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqIFRoZSBzdGF0dXMgb2YgdGhlIHR5cGVhaGVhZCBkcm9wZG93bi4gKi9cclxuICAgIEBJbnB1dCgpXHJcbiAgICBzZXQgZHJvcGRvd25PcGVuKHZhbHVlOiBib29sZWFuKSB7XHJcbiAgICAgICAgdGhpcy5fZHJvcGRvd25PcGVuID0gdmFsdWU7XHJcbiAgICAgICAgdGhpcy5kcm9wZG93bk9wZW5DaGFuZ2UuZW1pdCh2YWx1ZSk7XHJcbiAgICB9XHJcbiAgICBnZXQgZHJvcGRvd25PcGVuKCkge1xyXG4gICAgICAgIHJldHVybiB0aGlzLl9kcm9wZG93bk9wZW47XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBJZiBhbiBhcnJheSBpcyBwcm92aWRlZCwgdGhpcyBpcyB0aGUgbGlzdCBvZiBvcHRpb25zIHdoaWNoIGNhbiBiZSBjaG9zZW4gZnJvbS4gSXQgY2FuIGJlIGFuIGFycmF5IG9mIHN0cmluZ3Mgb3JcclxuICAgICAqIGN1c3RvbSBvYmplY3RzLiBJZiBjdXN0b20gb2JqZWN0cyBhcmUgc