primeng
Version:
PrimeNG is a premium UI library for Angular featuring a rich set of 90+ components, a theme designer, various theme alternatives such as Material, Bootstrap, Tailwind, premium templates and professional support. In addition, it integrates with PrimeBlock,
1 lines • 158 kB
Source Map (JSON)
{"version":3,"file":"primeng-select.mjs","sources":["../../src/select/select-token.ts","../../src/select/style/selectstyle.ts","../../src/select/select-item.ts","../../src/select/select.ts","../../src/select/primeng-select.ts"],"sourcesContent":["import { InjectionToken } from '@angular/core';\n\nexport const SELECT_INSTANCE = new InjectionToken<any>('SELECT_INSTANCE');\nexport const SELECT_ITEM_INSTANCE = new InjectionToken<any>('SELECT_ITEM_INSTANCE');\n","import { Injectable } from '@angular/core';\nimport { style } from '@primeuix/styles/select';\nimport { BaseStyle } from 'primeng/base';\n\nconst classes = {\n root: ({ instance }) => [\n 'p-select p-component p-inputwrapper',\n {\n 'p-disabled': instance.$disabled(),\n 'p-invalid': instance.invalid(),\n 'p-variant-filled': instance.$variant() === 'filled',\n 'p-focus': instance.focused(),\n 'p-inputwrapper-filled': instance.$filled(),\n 'p-inputwrapper-focus': instance.focused() || instance.overlayVisible(),\n 'p-select-open': instance.overlayVisible(),\n 'p-select-fluid': instance.hasFluid,\n 'p-select-sm p-inputfield-sm': instance.size() === 'small',\n 'p-select-lg p-inputfield-lg': instance.size() === 'large'\n }\n ],\n label: ({ instance }) => [\n 'p-select-label',\n {\n 'p-placeholder': instance.placeholder() && instance.label() === instance.placeholder(),\n 'p-select-label-empty': !instance.editable() && !instance.selectedItemTemplate() && (instance.label() === undefined || instance.label() === null || instance.label() === 'p-emptylabel' || instance.label().length === 0)\n }\n ],\n clearIcon: 'p-select-clear-icon',\n dropdown: 'p-select-dropdown',\n loadingIcon: 'p-select-loading-icon',\n dropdownIcon: 'p-select-dropdown-icon',\n overlay: 'p-select-overlay p-component-overlay p-component',\n header: 'p-select-header',\n pcFilter: 'p-select-filter',\n listContainer: 'p-select-list-container',\n list: 'p-select-list',\n optionGroup: 'p-select-option-group',\n optionGroupLabel: 'p-select-option-group-label',\n option: ({ instance }) => [\n 'p-select-option',\n {\n 'p-select-option-selected': instance.selected() && !instance.checkmark(),\n 'p-disabled': instance.disabled(),\n 'p-focus': instance.focused()\n }\n ],\n optionLabel: 'p-select-option-label',\n optionCheckIcon: 'p-select-option-check-icon',\n optionBlankIcon: 'p-select-option-blank-icon',\n emptyMessage: 'p-select-empty-message'\n};\n\n@Injectable()\nexport class SelectStyle extends BaseStyle {\n name = 'select';\n\n style = style;\n\n classes = classes;\n}\n\n/**\n *\n * Select also known as Select, is used to choose an item from a collection of options.\n *\n * [Live Demo](https://www.primeng.org/select/)\n *\n * @module selectstyle\n *\n */\nexport enum SelectClasses {\n /**\n * Class name of the root element\n */\n root = 'p-select',\n /**\n * Class name of the label element\n */\n label = 'p-select-label',\n /**\n * Class name of the clear icon element\n */\n clearIcon = 'p-select-clear-icon',\n /**\n * Class name of the dropdown element\n */\n dropdown = 'p-select-dropdown',\n /**\n * Class name of the loadingicon element\n */\n loadingIcon = 'p-select-loading-icon',\n /**\n * Class name of the dropdown icon element\n */\n dropdownIcon = 'p-select-dropdown-icon',\n /**\n * Class name of the overlay element\n */\n overlay = 'p-select-overlay',\n /**\n * Class name of the header element\n */\n header = 'p-select-header',\n /**\n * Class name of the filter element\n */\n pcFilter = 'p-select-filter',\n /**\n * Class name of the list container element\n */\n listContainer = 'p-select-list-container',\n /**\n * Class name of the list element\n */\n list = 'p-select-list',\n /**\n * Class name of the option group element\n */\n optionGroup = 'p-select-option-group',\n /**\n * Class name of the option group label element\n */\n optionGroupLabel = 'p-select-option-group-label',\n /**\n * Class name of the option element\n */\n option = 'p-select-option',\n /**\n * Class name of the option label element\n */\n optionLabel = 'p-select-option-label',\n /**\n * Class name of the option check icon element\n */\n optionCheckIcon = 'p-select-option-check-icon',\n /**\n * Class name of the option blank icon element\n */\n optionBlankIcon = 'p-select-option-blank-icon',\n /**\n * Class name of the empty message element\n */\n emptyMessage = 'p-select-empty-message'\n}\n\nexport interface SelectStyle extends BaseStyle {}\n","import { NgTemplateOutlet } from '@angular/common';\nimport { booleanAttribute, Component, computed, inject, input, numberAttribute, output, TemplateRef } from '@angular/core';\nimport { SharedModule } from 'primeng/api';\nimport { BaseComponent, PARENT_INSTANCE } from 'primeng/basecomponent';\nimport { BindModule } from 'primeng/bind';\nimport { Check as CheckIcon } from '@primeicons/angular/check';\nimport { Blank as BlankIcon } from '@primeicons/angular/blank';\nimport { Ripple } from 'primeng/ripple';\nimport type { Select } from './select';\nimport { SELECT_INSTANCE, SELECT_ITEM_INSTANCE } from './select-token';\nimport { SelectStyle } from './style/selectstyle';\n\n@Component({\n selector: 'p-select-item',\n standalone: true,\n imports: [NgTemplateOutlet, SharedModule, Ripple, CheckIcon, BlankIcon, BindModule],\n template: `\n <li\n [id]=\"id()\"\n [pBind]=\"getPTOptions()\"\n (click)=\"onOptionClick($event)\"\n (mouseenter)=\"onOptionMouseEnter($event)\"\n role=\"option\"\n pRipple\n [attr.aria-label]=\"label()\"\n [attr.aria-setsize]=\"ariaSetSize()\"\n [attr.aria-posinset]=\"ariaPosInset()\"\n [attr.aria-selected]=\"selected()\"\n [attr.data-p-focused]=\"focused()\"\n [attr.data-p-highlight]=\"selected()\"\n [attr.data-p-selected]=\"selected()\"\n [attr.data-p-disabled]=\"disabled()\"\n [style]=\"itemSizeStyle()\"\n [class]=\"cx('option')\"\n >\n @if (checkmark()) {\n @if (selected()) {\n <svg data-p-icon=\"check\" [class]=\"cx('optionCheckIcon')\" [pBind]=\"$pcSelect?.ptm('optionCheckIcon')\" />\n } @else {\n <svg data-p-icon=\"blank\" [class]=\"cx('optionBlankIcon')\" [pBind]=\"$pcSelect?.ptm('optionBlankIcon')\" />\n }\n }\n @if (!template()) {\n <span [pBind]=\"$pcSelect?.ptm('optionLabel')\">{{ label() ?? 'empty' }}</span>\n }\n <ng-container *ngTemplateOutlet=\"template(); context: templateContext()\"></ng-container>\n </li>\n `,\n providers: [SelectStyle, { provide: PARENT_INSTANCE, useExisting: SelectItem }]\n})\nexport class SelectItem extends BaseComponent {\n hostName = 'select';\n\n $pcSelectItem: SelectItem | undefined = inject(SELECT_ITEM_INSTANCE, { optional: true, skipSelf: true }) ?? undefined;\n\n $pcSelect: Select | undefined = inject(SELECT_INSTANCE, { optional: true, skipSelf: true }) as Select | undefined;\n\n id = input<string>();\n\n option = input<any>();\n\n selected = input(undefined, { transform: booleanAttribute });\n\n focused = input(undefined, { transform: booleanAttribute });\n\n label = input<string>();\n\n disabled = input(undefined, { transform: booleanAttribute });\n\n visible = input(undefined, { transform: booleanAttribute });\n\n itemSize = input(undefined, { transform: numberAttribute });\n\n ariaPosInset = input<string>();\n\n ariaSetSize = input<string>();\n\n template = input<TemplateRef<any>>();\n\n checkmark = input(false, { transform: booleanAttribute });\n\n index = input<number>();\n\n scrollerOptions = input<any>();\n\n templateContext = computed(() => ({ $implicit: this.option() }));\n\n itemSizeStyle = computed(() => ({ height: this.scrollerOptions()?.itemSize + 'px' }));\n\n onClick = output<any>();\n\n onMouseEnter = output<any>();\n\n _componentStyle = inject(SelectStyle);\n\n onOptionClick(event: Event) {\n this.onClick.emit(event);\n }\n\n onOptionMouseEnter(event: Event) {\n this.onMouseEnter.emit(event);\n }\n\n getPTOptions() {\n return (\n this.$pcSelect?.getPTItemOptions?.(this.option(), this.scrollerOptions(), this.index() ?? 0, 'option') ??\n this.$pcSelect?.ptm('option', {\n context: {\n option: this.option(),\n selected: this.selected(),\n focused: this.focused(),\n disabled: this.disabled()\n }\n })\n );\n }\n}\n","import { NgTemplateOutlet } from '@angular/common';\nimport {\n AfterViewChecked,\n AfterViewInit,\n booleanAttribute,\n ChangeDetectionStrategy,\n Component,\n computed,\n contentChild,\n effect,\n ElementRef,\n forwardRef,\n inject,\n input,\n NgModule,\n numberAttribute,\n output,\n signal,\n TemplateRef,\n viewChild,\n ViewEncapsulation\n} from '@angular/core';\nimport { NG_VALUE_ACCESSOR } from '@angular/forms';\nimport { ChevronDown as ChevronDownIcon } from '@primeicons/angular/chevron-down';\nimport { Search as SearchIcon } from '@primeicons/angular/search';\nimport { Times as TimesIcon } from '@primeicons/angular/times';\nimport { MotionOptions } from '@primeuix/motion';\nimport { deepEquals, equals, findLastIndex, findSingle, focus, getFirstFocusableElement, getFocusableElements, getLastFocusableElement, isEmpty, isNotEmpty, isPrintableCharacter, resolveFieldData, scrollInView, uuid } from '@primeuix/utils';\nimport { FilterMatchModeType, FilterService, OverlayOptions, ScrollerOptions, SharedModule, TranslationKeys } from 'primeng/api';\nimport { AutoFocus } from 'primeng/autofocus';\nimport { PARENT_INSTANCE } from 'primeng/basecomponent';\nimport { BaseInput } from 'primeng/baseinput';\nimport { Bind, BindModule } from 'primeng/bind';\nimport { unblockBodyScroll } from 'primeng/dom';\nimport { IconField } from 'primeng/iconfield';\nimport { InputIcon } from 'primeng/inputicon';\nimport { InputText } from 'primeng/inputtext';\nimport { Overlay } from 'primeng/overlay';\nimport { Scroller } from 'primeng/scroller';\nimport { Tooltip } from 'primeng/tooltip';\nimport { Nullable } from 'primeng/ts-helpers';\nimport {\n SelectChangeEvent,\n SelectFilterEvent,\n SelectFilterOptions,\n SelectFilterTemplateContext,\n SelectGroupTemplateContext,\n SelectHeaderTemplateContext,\n SelectIconTemplateContext,\n SelectItemTemplateContext,\n SelectLazyLoadEvent,\n SelectLoaderTemplateContext,\n SelectPassThrough,\n SelectSelectedItemTemplateContext\n} from 'primeng/types/select';\nimport type { AppendTo, CSSProperties } from 'primeng/types/shared';\nimport type { TooltipPosition } from 'primeng/types/tooltip';\nimport { SelectItem } from './select-item';\nimport { SELECT_INSTANCE } from './select-token';\nimport { SelectStyle } from './style/selectstyle';\n\nexport const SELECT_VALUE_ACCESSOR: any = {\n provide: NG_VALUE_ACCESSOR,\n useExisting: forwardRef(() => Select),\n multi: true\n};\n\n/**\n * Select is used to choose an item from a collection of options.\n * @group Components\n */\n\n@Component({\n selector: 'p-select',\n standalone: true,\n imports: [NgTemplateOutlet, SelectItem, Overlay, Tooltip, AutoFocus, TimesIcon, ChevronDownIcon, SearchIcon, InputText, IconField, InputIcon, Scroller, SharedModule, BindModule],\n template: `\n @if (!editable()) {\n <span\n #focusInput\n [class]=\"cx('label')\"\n [pBind]=\"ptm('label')\"\n [pTooltip]=\"tooltip()\"\n [pTooltipUnstyled]=\"unstyled()\"\n [tooltipPosition]=\"tooltipPosition()\"\n [positionStyle]=\"tooltipPositionStyle()\"\n [tooltipStyleClass]=\"tooltipStyleClass()\"\n [attr.aria-disabled]=\"$disabled()\"\n [attr.id]=\"inputId()\"\n role=\"combobox\"\n [attr.aria-label]=\"$ariaLabel()\"\n [attr.aria-labelledby]=\"ariaLabelledBy()\"\n [attr.aria-haspopup]=\"'listbox'\"\n [attr.aria-expanded]=\"$ariaExpanded\"\n [attr.aria-multiselectable]=\"$ariaMultiselectable()\"\n [attr.aria-controls]=\"$ariaControls()\"\n [attr.tabindex]=\"$tabindex()\"\n [pAutoFocus]=\"autofocus()\"\n [attr.aria-activedescendant]=\"$ariaActivedescendant\"\n (focus)=\"onInputFocus($event)\"\n (blur)=\"onInputBlur($event)\"\n (keydown)=\"onKeyDown($event)\"\n [attr.aria-required]=\"required()\"\n [attr.required]=\"$required()\"\n [attr.disabled]=\"$disabledAttr()\"\n [attr.data-p]=\"labelDataP\"\n >\n @if (!selectedItemTemplate()) {\n {{ label() === 'p-emptylabel' ? ' ' : label() }}\n } @else {\n @if (isSelectedOptionEmpty()) {\n <span>{{ label() === 'p-emptylabel' ? ' ' : label() }}</span>\n } @else {\n <ng-container *ngTemplateOutlet=\"selectedItemTemplate(); context: selectedItemContext\"></ng-container>\n }\n }\n </span>\n } @else {\n <input\n #editableInput\n type=\"text\"\n [attr.id]=\"inputId()\"\n [class]=\"cx('label')\"\n [pBind]=\"ptm('label')\"\n [attr.aria-haspopup]=\"'listbox'\"\n [attr.placeholder]=\"$placeholder()\"\n [attr.aria-label]=\"$ariaLabel()\"\n (input)=\"onEditableInput($event)\"\n (keydown)=\"onKeyDown($event)\"\n [pAutoFocus]=\"autofocus()\"\n [attr.aria-activedescendant]=\"$ariaActivedescendant\"\n (focus)=\"onInputFocus($event)\"\n (blur)=\"onInputBlur($event)\"\n [attr.name]=\"name()\"\n [attr.minlength]=\"minlength()\"\n [attr.min]=\"min()\"\n [attr.max]=\"max()\"\n [attr.pattern]=\"$pattern()\"\n [attr.size]=\"inputSize()\"\n [attr.maxlength]=\"maxlength()\"\n [attr.required]=\"$required()\"\n [attr.readonly]=\"$readonly()\"\n [attr.disabled]=\"$disabledAttr()\"\n [attr.data-p]=\"labelDataP\"\n />\n }\n @if (isVisibleClearIcon()) {\n @if (!clearIconTemplate()) {\n <svg data-p-icon=\"times\" [class]=\"cx('clearIcon')\" [pBind]=\"ptm('clearIcon')\" (click)=\"clear($event)\" [attr.data-pc-section]=\"'clearicon'\" />\n } @else {\n <span [class]=\"cx('clearIcon')\" [pBind]=\"ptm('clearIcon')\" (click)=\"clear($event)\" [attr.data-pc-section]=\"'clearicon'\">\n <ng-template *ngTemplateOutlet=\"clearIconTemplate(); context: clearIconContext\"></ng-template>\n </span>\n }\n }\n\n <div [class]=\"cx('dropdown')\" [pBind]=\"ptm('dropdown')\" role=\"button\" aria-label=\"dropdown trigger\" aria-haspopup=\"listbox\" [attr.aria-expanded]=\"$ariaExpanded\" [attr.data-pc-section]=\"'trigger'\">\n @if (loading()) {\n @if (loadingIconTemplate()) {\n <ng-container *ngTemplateOutlet=\"loadingIconTemplate()\"></ng-container>\n } @else {\n @if (loadingIcon()) {\n <span [class]=\"cn(cx('loadingIcon'), 'pi-spin' + loadingIcon())\" [pBind]=\"ptm('loadingIcon')\" aria-hidden=\"true\"></span>\n } @else {\n <span [class]=\"cn(cx('loadingIcon'), 'pi pi-spinner pi-spin')\" [pBind]=\"ptm('loadingIcon')\" aria-hidden=\"true\"></span>\n }\n }\n } @else {\n @if (!dropdownIconTemplate()) {\n @if (dropdownIcon()) {\n <span [class]=\"cn(cx('dropdownIcon'), dropdownIcon())\" [pBind]=\"ptm('dropdownIcon')\"></span>\n } @else {\n <svg data-p-icon=\"chevron-down\" [class]=\"cx('dropdownIcon')\" [pBind]=\"ptm('dropdownIcon')\" />\n }\n } @else {\n <span [class]=\"cx('dropdownIcon')\" [pBind]=\"ptm('dropdownIcon')\">\n <ng-template *ngTemplateOutlet=\"dropdownIconTemplate(); context: dropdownIconContext\"></ng-template>\n </span>\n }\n }\n </div>\n\n <p-overlay\n #overlay\n [hostAttrSelector]=\"$attrSelector\"\n [visible]=\"overlayVisible()\"\n (visibleChange)=\"overlayVisible.set($event)\"\n [options]=\"overlayOptions()\"\n [target]=\"'@parent'\"\n [appendTo]=\"$appendTo()\"\n [unstyled]=\"unstyled()\"\n [pt]=\"ptm('pcOverlay')\"\n [motionOptions]=\"motionOptions()\"\n (onBeforeEnter)=\"onOverlayBeforeEnter($event)\"\n (onAfterLeave)=\"onOverlayAfterLeave($event)\"\n (onHide)=\"hide()\"\n >\n <ng-template #content>\n <div [class]=\"cn(cx('overlay'), panelStyleClass())\" [style]=\"panelStyle()\" [pBind]=\"ptm('overlay')\" [attr.data-p]=\"overlayDataP\">\n <span\n #firstHiddenFocusableEl\n role=\"presentation\"\n class=\"p-hidden-accessible p-hidden-focusable\"\n [attr.tabindex]=\"0\"\n (focus)=\"onFirstHiddenFocus($event)\"\n [attr.data-p-hidden-accessible]=\"true\"\n [attr.data-p-hidden-focusable]=\"true\"\n [pBind]=\"ptm('hiddenFirstFocusableEl')\"\n >\n </span>\n <ng-container *ngTemplateOutlet=\"headerTemplate(); context: { class: cx('header') }\"></ng-container>\n @if (filter()) {\n <div [class]=\"cx('header')\" (click)=\"$event.stopPropagation()\" [pBind]=\"ptm('header')\">\n @if (filterTemplate()) {\n <ng-container *ngTemplateOutlet=\"filterTemplate(); context: filterTemplateContext\"></ng-container>\n } @else {\n <p-iconfield [pt]=\"ptm('pcFilterContainer')\" [unstyled]=\"unstyled()\">\n <input\n #filter\n pInputText\n [pSize]=\"size()\"\n type=\"text\"\n role=\"searchbox\"\n autocomplete=\"off\"\n [value]=\"filterInputValue()\"\n [class]=\"cx('pcFilter')\"\n [variant]=\"$variant()\"\n [attr.placeholder]=\"filterPlaceholder()\"\n [attr.aria-owns]=\"$ariaOwns()\"\n (input)=\"onFilterInputChange($event)\"\n [attr.aria-label]=\"ariaFilterLabel()\"\n [attr.aria-activedescendant]=\"focusedOptionId()\"\n (keydown)=\"onFilterKeyDown($event)\"\n (blur)=\"onFilterBlur($event)\"\n [pt]=\"ptm('pcFilter')\"\n [unstyled]=\"unstyled()\"\n />\n <p-inputicon [pt]=\"ptm('pcFilterIconContainer')\" [unstyled]=\"unstyled()\">\n @if (!filterIconTemplate()) {\n <svg data-p-icon=\"search\" [pBind]=\"ptm('filterIcon')\" />\n } @else {\n <span [pBind]=\"ptm('filterIcon')\">\n <ng-template *ngTemplateOutlet=\"filterIconTemplate()\"></ng-template>\n </span>\n }\n </p-inputicon>\n </p-iconfield>\n }\n </div>\n }\n <div [class]=\"cx('listContainer')\" [style.max-height]=\"virtualScroll() ? 'auto' : scrollHeight() || 'auto'\" [pBind]=\"ptm('listContainer')\">\n @if (virtualScroll()) {\n <p-scroller\n hostName=\"select\"\n #scroller\n [items]=\"visibleOptions()\"\n [style]=\"{ height: scrollHeight() }\"\n [itemSize]=\"virtualScrollItemSize()\"\n [autoSize]=\"true\"\n [lazy]=\"lazy()\"\n (onLazyLoad)=\"onLazyLoad.emit($event)\"\n [options]=\"virtualScrollOptions()\"\n [pt]=\"ptm('virtualScroller')\"\n >\n <ng-template #content let-items let-scrollerOptions=\"options\">\n <ng-container *ngTemplateOutlet=\"buildInItems; context: getBuildInItemsContext(items, scrollerOptions)\"></ng-container>\n </ng-template>\n @if (loaderTemplate()) {\n <ng-template #loader let-scrollerOptions=\"options\">\n <ng-container *ngTemplateOutlet=\"loaderTemplate(); context: getLoaderContext(scrollerOptions)\"></ng-container>\n </ng-template>\n }\n </p-scroller>\n } @else {\n <ng-container *ngTemplateOutlet=\"buildInItems; context: defaultBuildInItemsContext\"></ng-container>\n }\n\n <ng-template #buildInItems let-items let-scrollerOptions=\"options\">\n <ul #items [attr.id]=\"$id() + '_list'\" [attr.aria-label]=\"listLabel\" [class]=\"cn(cx('list'), scrollerOptions.contentStyleClass)\" [style]=\"scrollerOptions.contentStyle\" role=\"listbox\" [pBind]=\"ptm('list')\">\n @for (option of items; track trackOption(option, i); let i = $index) {\n @if (isOptionGroup(option)) {\n <li [class]=\"cx('optionGroup')\" [attr.id]=\"$id() + '_' + getOptionIndex(i, scrollerOptions)\" [style]=\"getItemSizeStyle(scrollerOptions)\" role=\"option\" [pBind]=\"ptm('optionGroup')\">\n @if (!groupTemplate()) {\n <span [class]=\"cx('optionGroupLabel')\" [pBind]=\"ptm('optionGroupLabel')\">{{ getOptionGroupLabel(option.optionGroup) }}</span>\n }\n <ng-container *ngTemplateOutlet=\"groupTemplate(); context: getGroupContext(option.optionGroup)\"></ng-container>\n </li>\n } @else {\n <p-select-item\n [id]=\"$id() + '_' + getOptionIndex(i, scrollerOptions)\"\n [option]=\"option\"\n [checkmark]=\"checkmark()\"\n [selected]=\"isSelected(option)\"\n [label]=\"getOptionLabel(option)\"\n [disabled]=\"isOptionDisabled(option)\"\n [template]=\"itemTemplate()\"\n [focused]=\"isOptionFocused(i, scrollerOptions)\"\n [ariaPosInset]=\"getAriaPosInset(getOptionIndex(i, scrollerOptions))\"\n [ariaSetSize]=\"ariaSetSize\"\n [index]=\"i\"\n [unstyled]=\"unstyled()\"\n [scrollerOptions]=\"scrollerOptions\"\n (onClick)=\"onOptionSelect($event, option)\"\n (onMouseEnter)=\"onOptionMouseEnter($event, getOptionIndex(i, scrollerOptions))\"\n ></p-select-item>\n }\n }\n @if (showEmptyFilterMessage()) {\n <li [class]=\"cx('emptyMessage')\" [style]=\"getItemSizeStyle(scrollerOptions)\" role=\"option\" [pBind]=\"ptm('emptyMessage')\">\n @if (!hasEmptyTemplate()) {\n {{ emptyFilterMessageLabel() }}\n } @else {\n <ng-container *ngTemplateOutlet=\"hasEmptyTemplate()\"></ng-container>\n }\n </li>\n }\n @if (showEmptyMessage()) {\n <li [class]=\"cx('emptyMessage')\" [style]=\"getItemSizeStyle(scrollerOptions)\" role=\"option\" [pBind]=\"ptm('emptyMessage')\">\n @if (!emptyTemplate()) {\n {{ emptyMessageLabel() || emptyFilterMessageLabel() }}\n } @else {\n <ng-container *ngTemplateOutlet=\"emptyTemplate()\"></ng-container>\n }\n </li>\n }\n </ul>\n </ng-template>\n </div>\n <ng-container *ngTemplateOutlet=\"footerTemplate()\"></ng-container>\n <span\n #lastHiddenFocusableEl\n role=\"presentation\"\n class=\"p-hidden-accessible p-hidden-focusable\"\n [pBind]=\"ptm('hiddenLastFocusableEl')\"\n [attr.tabindex]=\"0\"\n (focus)=\"onLastHiddenFocus($event)\"\n [attr.data-p-hidden-accessible]=\"true\"\n [attr.data-p-hidden-focusable]=\"true\"\n ></span>\n </div>\n </ng-template>\n </p-overlay>\n `,\n host: {\n '[class]': \"cx('root')\",\n '[attr.id]': '$id()',\n '[attr.data-p]': 'containerDataP',\n '(click)': 'onContainerClick($event)'\n },\n providers: [SELECT_VALUE_ACCESSOR, SelectStyle, { provide: SELECT_INSTANCE, useExisting: Select }, { provide: PARENT_INSTANCE, useExisting: Select }],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n hostDirectives: [Bind]\n})\nexport class Select extends BaseInput<SelectPassThrough> implements AfterViewInit, AfterViewChecked {\n componentName = 'Select';\n\n bindDirectiveInstance = inject(Bind, { self: true });\n\n filterService = inject(FilterService);\n\n /**\n * Unique identifier of the component\n * @group Props\n */\n id = input<string>();\n\n private _internalId = uuid('pn_id_');\n\n $id = computed(() => this.id() || this._internalId);\n\n /**\n * Height of the viewport in pixels, a scrollbar is defined if height of list exceeds this value.\n * @group Props\n */\n scrollHeight = input<string>('200px');\n /**\n * When specified, displays an input field to filter the items on keyup.\n * @group Props\n */\n filter = input(undefined, { transform: booleanAttribute });\n /**\n * Inline style of the overlay panel element.\n * @group Props\n */\n panelStyle = input<CSSProperties>();\n /**\n * Style class of the overlay panel element.\n * @group Props\n */\n panelStyleClass = input<string>();\n /**\n * When present, it specifies that the component cannot be edited.\n * @group Props\n */\n readonly = input(undefined, { transform: booleanAttribute });\n /**\n * When present, custom value instead of predefined options can be entered using the editable input field.\n * @group Props\n */\n editable = input(undefined, { transform: booleanAttribute });\n /**\n * Index of the element in tabbing order.\n * @group Props\n */\n tabindex = input(0, { transform: numberAttribute });\n /**\n * Default text to display when no option is selected.\n * @group Props\n */\n placeholder = input<string>();\n /**\n * Icon to display in loading state.\n * @group Props\n */\n loadingIcon = input<string>();\n /**\n * Placeholder text to show when filter input is empty.\n * @group Props\n */\n filterPlaceholder = input<string>();\n /**\n * Locale to use in filtering. The default locale is the host environment's current locale.\n * @group Props\n */\n filterLocale = input<string>();\n /**\n * Identifier of the accessible input element.\n * @group Props\n */\n inputId = input<string>();\n /**\n * A property to uniquely identify a value in options.\n * @group Props\n */\n dataKey = input<string>();\n /**\n * When filtering is enabled, filterBy decides which field or fields (comma separated) to search against.\n * @group Props\n */\n filterBy = input<string>();\n /**\n * Fields used when filtering the options, defaults to optionLabel.\n * @group Props\n */\n filterFields = input<any[]>();\n /**\n * When present, it specifies that the component should automatically get focus on load.\n * @group Props\n */\n autofocus = input(undefined, { transform: booleanAttribute });\n /**\n * Clears the filter value when hiding the select.\n * @group Props\n */\n resetFilterOnHide = input(false, { transform: booleanAttribute });\n /**\n * Whether the selected option will be shown with a check mark.\n * @group Props\n */\n checkmark = input(false, { transform: booleanAttribute });\n /**\n * Icon class of the select icon.\n * @group Props\n */\n dropdownIcon = input<string>();\n /**\n * Whether the select is in loading state.\n * @group Props\n */\n loading = input(false, { transform: booleanAttribute });\n /**\n * Name of the label field of an option.\n * @group Props\n */\n optionLabel = input<string>();\n /**\n * Name of the value field of an option.\n * @group Props\n */\n optionValue = input<string>();\n /**\n * Name of the disabled field of an option.\n * @group Props\n */\n optionDisabled = input<string>();\n /**\n * Name of the label field of an option group.\n * @group Props\n */\n optionGroupLabel = input<string>('label');\n /**\n * Name of the options field of an option group.\n * @group Props\n */\n optionGroupChildren = input<string>('items');\n /**\n * Whether to display options as grouped when nested options are provided.\n * @group Props\n */\n group = input(undefined, { transform: booleanAttribute });\n /**\n * When enabled, a clear icon is displayed to clear the value.\n * @group Props\n */\n showClear = input(undefined, { transform: booleanAttribute });\n /**\n * Text to display when filtering does not return any results. Defaults to global value in i18n translation configuration.\n * @group Props\n */\n emptyFilterMessage = input<string>('');\n /**\n * Text to display when there is no data. Defaults to global value in i18n translation configuration.\n * @group Props\n */\n emptyMessage = input<string>('');\n /**\n * Defines if data is loaded and interacted with in lazy manner.\n * @group Props\n */\n lazy = input(false, { transform: booleanAttribute });\n /**\n * Whether the data should be loaded on demand during scroll.\n * @group Props\n */\n virtualScroll = input(undefined, { transform: booleanAttribute });\n /**\n * Height of an item in the list for VirtualScrolling.\n * @group Props\n */\n virtualScrollItemSize = input(undefined, { transform: numberAttribute });\n /**\n * Whether to use the scroller feature. The properties of scroller component can be used like an object in it.\n * @group Props\n */\n virtualScrollOptions = input<ScrollerOptions>();\n /**\n * Whether to use overlay API feature. The properties of overlay API can be used like an object in it.\n * @group Props\n */\n overlayOptions = input<OverlayOptions>();\n /**\n * Defines a string that labels the filter input.\n * @group Props\n */\n ariaFilterLabel = input<string>();\n /**\n * Used to define a aria label attribute the current element.\n * @group Props\n */\n ariaLabel = input<string>();\n /**\n * Establishes relationships between the component and label(s) where its value should be one or more element IDs.\n * @group Props\n */\n ariaLabelledBy = input<string>();\n /**\n * Defines how the items are filtered.\n * @group Props\n */\n filterMatchMode = input<FilterMatchModeType>('contains');\n /**\n * Advisory information to display in a tooltip on hover.\n * @group Props\n */\n tooltip = input<string>('');\n /**\n * Position of the tooltip.\n * @group Props\n */\n tooltipPosition = input<TooltipPosition>('right');\n /**\n * Type of CSS position.\n * @group Props\n */\n tooltipPositionStyle = input<string>('absolute');\n /**\n * Style class of the tooltip.\n * @group Props\n */\n tooltipStyleClass = input<string>();\n /**\n * Fields used when filtering the options, defaults to optionLabel.\n * @group Props\n */\n focusOnHover = input(true, { transform: booleanAttribute });\n /**\n * Determines if the option will be selected on focus.\n * @group Props\n */\n selectOnFocus = input(false, { transform: booleanAttribute });\n /**\n * When enabled, allows multiple items to be selected.\n * @group Props\n */\n multiple = input(false, { transform: booleanAttribute });\n /**\n * Whether to focus on the first visible or selected element when the overlay panel is shown.\n * @group Props\n */\n autoOptionFocus = input(false, { transform: booleanAttribute });\n /**\n * Applies focus to the filter element when the overlay is shown.\n * @group Props\n */\n autofocusFilter = input(true, { transform: booleanAttribute });\n /**\n * When specified, filter displays with this value.\n * @group Props\n */\n filterValue = input<string | null>();\n /**\n * An array of objects to display as the available options.\n * @group Props\n */\n options = input<any[] | null>();\n /**\n * Target element to attach the overlay, valid values are \"body\" or a local ng-template variable of another element (note: use binding with brackets for template variables, e.g. [appendTo]=\"mydiv\" for a div element having #mydiv as variable name).\n * @defaultValue 'self'\n * @group Props\n */\n appendTo = input<AppendTo>(undefined);\n /**\n * The motion options.\n * @group Props\n */\n motionOptions = input<MotionOptions | undefined>(undefined);\n /**\n * Callback to invoke when value of select changes.\n * @param {SelectChangeEvent} event - custom change event.\n * @group Emits\n */\n onChange = output<SelectChangeEvent>();\n /**\n * Callback to invoke when data is filtered.\n * @param {SelectFilterEvent} event - custom filter event.\n * @group Emits\n */\n onFilter = output<SelectFilterEvent>();\n /**\n * Callback to invoke when select gets focus.\n * @param {Event} event - Browser event.\n * @group Emits\n */\n onFocus = output<Event>();\n /**\n * Callback to invoke when select loses focus.\n * @param {Event} event - Browser event.\n * @group Emits\n */\n onBlur = output<Event>();\n /**\n * Callback to invoke when component is clicked.\n * @param {MouseEvent} event - Mouse event.\n * @group Emits\n */\n onClick = output<MouseEvent>();\n /**\n * Callback to invoke when select overlay gets visible.\n * @param {AnimationEvent} event - Animation event.\n * @group Emits\n */\n onShow = output<AnimationEvent>();\n /**\n * Callback to invoke when select overlay gets hidden.\n * @param {AnimationEvent} event - Animation event.\n * @group Emits\n */\n onHide = output<AnimationEvent>();\n /**\n * Callback to invoke when select clears the value.\n * @param {Event} event - Browser event.\n * @group Emits\n */\n onClear = output<Event>();\n /**\n * Callback to invoke in lazy mode to load new data.\n * @param {SelectLazyLoadEvent} event - Lazy load event.\n * @group Emits\n */\n onLazyLoad = output<SelectLazyLoadEvent>();\n\n _componentStyle = inject(SelectStyle);\n\n filterViewChild = viewChild<ElementRef>('filter');\n\n focusInputViewChild = viewChild<ElementRef>('focusInput');\n\n editableInputViewChild = viewChild<ElementRef>('editableInput');\n\n itemsViewChild = viewChild<ElementRef>('items');\n\n scroller = viewChild<Scroller>('scroller');\n\n overlayViewChild = viewChild<Overlay>('overlay');\n\n firstHiddenFocusableElementOnOverlay = viewChild<ElementRef>('firstHiddenFocusableEl');\n\n lastHiddenFocusableElementOnOverlay = viewChild<ElementRef>('lastHiddenFocusableEl');\n\n itemsWrapper: Nullable<HTMLDivElement>;\n\n $appendTo = computed(() => this.appendTo() || this.config.overlayAppendTo());\n\n /**\n * Custom item template.\n * @group Templates\n */\n itemTemplate = contentChild<TemplateRef<SelectItemTemplateContext>>('item', { descendants: false });\n\n /**\n * Custom group template.\n * @group Templates\n */\n groupTemplate = contentChild<TemplateRef<SelectGroupTemplateContext>>('group', { descendants: false });\n\n /**\n * Custom loader template.\n * @group Templates\n */\n loaderTemplate = contentChild<TemplateRef<SelectLoaderTemplateContext>>('loader', { descendants: false });\n\n /**\n * Custom selected item template.\n * @group Templates\n */\n selectedItemTemplate = contentChild<TemplateRef<SelectSelectedItemTemplateContext>>('selectedItem', { descendants: false });\n\n /**\n * Custom header template.\n * @param {SelectHeaderTemplateContext} context - header context.\n * @group Templates\n */\n headerTemplate = contentChild<TemplateRef<SelectHeaderTemplateContext>>('header', { descendants: false });\n\n /**\n * Custom filter template.\n * @group Templates\n */\n filterTemplate = contentChild<TemplateRef<SelectFilterTemplateContext>>('filter', { descendants: false });\n\n /**\n * Custom footer template.\n * @group Templates\n */\n footerTemplate = contentChild<TemplateRef<void>>('footer', { descendants: false });\n\n /**\n * Custom empty filter template.\n * @group Templates\n */\n emptyFilterTemplate = contentChild<TemplateRef<void>>('emptyfilter', { descendants: false });\n\n /**\n * Custom empty template.\n * @group Templates\n */\n emptyTemplate = contentChild<TemplateRef<void>>('empty', { descendants: false });\n\n /**\n * Custom dropdown icon template.\n * @group Templates\n */\n dropdownIconTemplate = contentChild<TemplateRef<SelectIconTemplateContext>>('dropdownicon', { descendants: false });\n\n /**\n * Custom loading icon template.\n * @group Templates\n */\n loadingIconTemplate = contentChild<TemplateRef<void>>('loadingicon', { descendants: false });\n\n /**\n * Custom clear icon template.\n * @group Templates\n */\n clearIconTemplate = contentChild<TemplateRef<SelectIconTemplateContext>>('clearicon', { descendants: false });\n\n /**\n * Custom filter icon template.\n * @group Templates\n */\n filterIconTemplate = contentChild<TemplateRef<void>>('filtericon', { descendants: false });\n\n /**\n * Custom on icon template.\n * @group Templates\n */\n onIconTemplate = contentChild<TemplateRef<void>>('onicon', { descendants: false });\n\n /**\n * Custom off icon template.\n * @group Templates\n */\n offIconTemplate = contentChild<TemplateRef<void>>('officon', { descendants: false });\n\n /**\n * Custom cancel icon template.\n * @group Templates\n */\n cancelIconTemplate = contentChild<TemplateRef<void>>('cancelicon', { descendants: false });\n\n filterOptions: SelectFilterOptions | undefined;\n\n _filterValue = signal<any>(null);\n\n _placeholder = signal<string | undefined>(undefined);\n\n _options = signal<any[] | null>(null);\n\n value: any;\n\n hover: Nullable<boolean>;\n\n focused = signal<boolean>(false);\n\n overlayVisible = signal<boolean>(false);\n\n optionsChanged: Nullable<boolean>;\n\n panel: Nullable<HTMLDivElement>;\n\n dimensionsUpdated: Nullable<boolean>;\n\n hoveredItem: any;\n\n selectedOptionUpdated: Nullable<boolean>;\n\n searchValue: Nullable<string>;\n\n searchIndex: Nullable<number>;\n\n searchTimeout: any;\n\n previousSearchChar: Nullable<string>;\n\n currentSearchChar: Nullable<string>;\n\n preventModelTouched: Nullable<boolean>;\n\n focusedOptionIndex = signal<number>(-1);\n\n labelId: Nullable<string>;\n\n listId: Nullable<string>;\n\n clicked = signal<boolean>(false);\n\n emptyMessageLabel = computed(() => this.emptyMessage() || this.translate(TranslationKeys.EMPTY_MESSAGE));\n\n emptyFilterMessageLabel = computed(() => this.emptyFilterMessage() || this.translate(TranslationKeys.EMPTY_FILTER_MESSAGE));\n\n isVisibleClearIcon = computed(() => {\n if (!this.showClear() || this.$disabled()) return false;\n const value = this.modelValue();\n if (this.multiple()) {\n return Array.isArray(value) && value.length > 0;\n }\n return value != null && this.hasSelectedOption();\n });\n\n get listLabel(): string {\n return this.translate(TranslationKeys.ARIA, 'listLabel');\n }\n\n focusedOptionId = computed(() => (this.focusedOptionIndex() !== -1 ? `${this.$id()}_${this.focusedOptionIndex()}` : null));\n\n visibleOptions = computed(() => {\n const options = this.getAllVisibleAndNonVisibleOptions();\n\n if (this._filterValue()) {\n const _filterBy = this.filterBy() || this.optionLabel();\n\n const filteredOptions =\n !_filterBy && !this.filterFields() && !this.optionValue()\n ? this._options()?.filter((option) => {\n if (option.label) {\n return option.label.toString().toLowerCase().indexOf(this._filterValue().toLowerCase().trim()) !== -1;\n }\n return option.toString().toLowerCase().indexOf(this._filterValue().toLowerCase().trim()) !== -1;\n })\n : this.filterService.filter(options, this.searchFields(), this._filterValue().trim(), this.filterMatchMode(), this.filterLocale());\n\n if (this.group()) {\n const optionGroups = this._options() || [];\n const filtered: any[] = [];\n\n optionGroups.forEach((group) => {\n const groupChildren = this.getOptionGroupChildren(group);\n const filteredItems = groupChildren.filter((item) => filteredOptions?.includes(item));\n\n if (filteredItems.length > 0)\n filtered.push({\n ...group,\n [typeof this.optionGroupChildren() === 'string' ? this.optionGroupChildren() : 'items']: [...filteredItems]\n });\n });\n\n return this.flatOptions(filtered);\n }\n return filteredOptions;\n }\n\n return options;\n });\n\n label = computed(() => {\n if (this.multiple()) {\n const currentValue = this.modelValue();\n if (!Array.isArray(currentValue) || currentValue.length === 0) {\n return this.placeholder() || 'p-emptylabel';\n }\n const options = this.getAllVisibleAndNonVisibleOptions();\n const labels = currentValue\n .map((val) => {\n const opt = options.find((o) => !this.isOptionGroup(o) && equals(val, this.getOptionValue(o), this.equalityKey()));\n return opt ? this.getOptionLabel(opt) : String(val);\n })\n .filter(Boolean);\n return labels.join(', ');\n }\n\n // use getAllVisibleAndNonVisibleOptions verses just visible options\n // this will find the selected option whether or not the user is currently filtering because the filtered (i.e. visible) options, are a subset of all the options\n const options = this.getAllVisibleAndNonVisibleOptions();\n\n // use isOptionEqualsModelValue for the use case where the dropdown is initalized with a disabled option\n const selectedOptionIndex = options.findIndex((option) => {\n const isEqual = this.isOptionValueEqualsModelValue(option);\n return isEqual;\n });\n\n if (selectedOptionIndex !== -1) {\n const selectedOption = options[selectedOptionIndex];\n // Always show the label for selected options, even if disabled\n return this.getOptionLabel(selectedOption);\n }\n\n return this.placeholder() || 'p-emptylabel';\n });\n\n $ariaLabel = computed(() => {\n return this.ariaLabel() || (this.label() === 'p-emptylabel' ? undefined : this.label());\n });\n\n $ariaMultiselectable = computed(() => this.multiple() || undefined);\n\n $placeholder = computed(() => {\n const modelVal = this.modelValue();\n return modelVal === undefined || modelVal === null ? this.placeholder() || this._placeholder() : undefined;\n });\n\n $required = computed(() => (this.required() ? '' : undefined));\n\n $readonly = computed(() => (this.readonly() ? '' : undefined));\n\n $disabledAttr = computed(() => (this.$disabled() ? '' : undefined));\n\n $tabindex = computed(() => (!this.$disabled() ? this.tabindex() : -1));\n\n filterInputValue = computed(() => this._filterValue() || '');\n\n get $ariaActivedescendant() {\n return this.focused() ? this.focusedOptionId() : undefined;\n }\n\n get $ariaExpanded() {\n return this.overlayVisible();\n }\n\n $ariaControls = computed(() => (this.overlayVisible() ? this.$id() + '_list' : null));\n\n showEmptyFilterMessage = computed(() => this._filterValue() && this.isEmpty());\n\n showEmptyMessage = computed(() => !this._filterValue() && this.isEmpty());\n\n hasEmptyTemplate = computed(() => this.emptyFilterTemplate() || this.emptyTemplate());\n\n $ariaOwns = computed(() => this.$id() + '_list');\n\n get selectedItemContext(): SelectSelectedItemTemplateContext {\n return { $implicit: this.selectedOption() };\n }\n\n get clearIconContext(): SelectIconTemplateContext {\n return { class: this.cx('clearIcon') ?? '' };\n }\n\n get dropdownIconContext(): SelectIconTemplateContext {\n return { class: this.cx('dropdownIcon') ?? '' };\n }\n\n get filterTemplateContext(): SelectFilterTem