primeng
Version:
PrimeNG is an open source UI library for Angular featuring a rich set of 80+ components, a theme designer, various theme alternatives such as Material, Bootstrap, Tailwind, premium templates and professional support. In addition, it integrates with PrimeB
1 lines • 171 kB
Source Map (JSON)
{"version":3,"file":"primeng-multiselect.mjs","sources":["../../src/multiselect/style/multiselectstyle.ts","../../src/multiselect/multiselect.ts","../../src/multiselect/primeng-multiselect.ts"],"sourcesContent":["import { Injectable } from '@angular/core';\nimport { BaseStyle } from 'primeng/base';\n\nconst theme = ({ dt }) => `\n.p-multiselect {\n display: inline-flex;\n cursor: pointer;\n position: relative;\n user-select: none;\n background: ${dt('multiselect.background')};\n border: 1px solid ${dt('multiselect.border.color')};\n transition: background ${dt('multiselect.transition.duration')}, color ${dt('multiselect.transition.duration')}, border-color ${dt('multiselect.transition.duration')}, outline-color ${dt('multiselect.transition.duration')}, box-shadow ${dt(\n 'multiselect.transition.duration'\n )};\n border-radius: ${dt('multiselect.border.radius')};\n outline-color: transparent;\n box-shadow: ${dt('multiselect.shadow')};\n}\n\n.p-multiselect.ng-invalid.ng-dirty {\n border-color: ${dt('multiselect.invalid.border.color')};\n}\n\n.p-multiselect:not(.p-disabled):hover {\n border-color: ${dt('multiselect.hover.border.color')};\n}\n\n.p-multiselect:not(.p-disabled).p-focus {\n border-color: ${dt('multiselect.focus.border.color')};\n box-shadow: ${dt('multiselect.focus.ring.shadow')};\n outline: ${dt('multiselect.focus.ring.width')} ${dt('multiselect.focus.ring.style')} ${dt('multiselect.focus.ring.color')};\n outline-offset: ${dt('multiselect.focus.ring.offset')};\n}\n\n.p-multiselect.p-variant-filled {\n background: ${dt('multiselect.filled.background')};\n}\n\n.p-multiselect.p-variant-filled:not(.p-disabled):hover {\n background: ${dt('multiselect.filled.hover.background')};\n}\n\n.p-multiselect.p-variant-filled.p-focus {\n background: ${dt('multiselect.filled.focus.background')};\n}\n\n.p-multiselect.p-disabled {\n opacity: 1;\n background: ${dt('multiselect.disabled.background')};\n}\n\n.p-multiselect-dropdown {\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n background: transparent;\n color: ${dt('multiselect.dropdown.color')};\n width: ${dt('multiselect.dropdown.width')};\n border-start-end-radius: ${dt('multiselect.border.radius')};\n border-end-end-radius: ${dt('multiselect.border.radius')};\n}\n\n.p-multiselect-label-container {\n overflow: hidden;\n flex: 1 1 auto;\n cursor: pointer;\n}\n\n.p-multiselect-label {\n display: flex;\n align-items-center;\n gap: calc(${dt('multiselect.padding.y')} / 2);\n white-space: nowrap;\n cursor: pointer;\n overflow: hidden;\n text-overflow: ellipsis;\n padding: ${dt('multiselect.padding.y')} ${dt('multiselect.padding.x')};\n color: ${dt('multiselect.color')};\n}\n\n.p-multiselect-label.p-placeholder {\n color: ${dt('multiselect.placeholder.color')};\n}\n\np-multiSelect.ng-invalid.ng-dirty .p-multiselect-label.p-placeholder,\np-multi-select.ng-invalid.ng-dirty .p-multiselect-label.p-placeholder,\np-multiselect.ng-invalid.ng-dirty .p-multiselect-label.p-placeholder {\n color: ${dt('multiselect.invalid.placeholder.color')};\n}\n\n.p-multiselect.p-disabled .p-multiselect-label {\n color: ${dt('multiselect.disabled.color')};\n}\n\n.p-multiselect-label-empty {\n overflow: hidden;\n visibility: hidden;\n}\n\n.p-multiselect .p-multiselect-overlay {\n min-width: 100%;\n}\n\n.p-multiselect-overlay {\n background: ${dt('multiselect.overlay.background')};\n color: ${dt('multiselect.overlay.color')};\n border: 1px solid ${dt('multiselect.overlay.border.color')};\n border-radius: ${dt('multiselect.overlay.border.radius')};\n box-shadow: ${dt('multiselect.overlay.shadow')};\n}\n\n.p-multiselect-header {\n display: flex;\n align-items: center;\n padding: ${dt('multiselect.list.header.padding')};\n}\n\n.p-multiselect-header .p-checkbox {\n margin-inline-end: ${dt('multiselect.option.gap')};\n}\n\n.p-multiselect-filter-container {\n flex: 1 1 auto;\n}\n\n.p-multiselect-filter {\n width: 100%;\n}\n\n.p-multiselect-list-container {\n overflow: auto;\n}\n\n.p-multiselect-list {\n margin: 0;\n padding: 0;\n list-style-type: none;\n padding: ${dt('multiselect.list.padding')};\n display: flex;\n flex-direction: column;\n gap: ${dt('multiselect.list.gap')}\n}\n\n.p-multiselect-option {\n cursor: pointer;\n font-weight: normal;\n white-space: nowrap;\n position: relative;\n overflow: hidden;\n display: flex;\n align-items: center;\n gap: ${dt('multiselect.option.gap')};\n padding: ${dt('multiselect.option.padding')};\n border: 0 none;\n color: ${dt('multiselect.option.color')};\n background: transparent;\n transition: background ${dt('multiselect.transition.duration')}, color ${dt('multiselect.transition.duration')}, border-color ${dt('multiselect.transition.duration')}, box-shadow ${dt('multiselect.transition.duration')}, outline-color ${dt(\n 'multiselect.transition.duration'\n )};\n border-radius: ${dt('multiselect.option.border.radius')}\n}\n\n.p-multiselect-option:not(.p-multiselect-option-selected):not(.p-disabled).p-focus {\n background: ${dt('multiselect.option.focus.background')};\n color: ${dt('multiselect.option.focus.color')};\n}\n\n.p-multiselect-option.p-multiselect-option-selected {\n background: ${dt('multiselect.option.selected.background')};\n color: ${dt('multiselect.option.selected.color')};\n}\n\n.p-multiselect-option.p-multiselect-option-selected.p-focus {\n background: ${dt('multiselect.option.selected.focus.background')};\n color: ${dt('multiselect.option.selected.focus.color')};\n}\n\n.p-multiselect-option-group {\n cursor: auto;\n margin: 0;\n padding: ${dt('multiselect.option.group.padding')};\n background: ${dt('multiselect.option.group.background')};\n color: ${dt('multiselect.option.group.color')};\n font-weight: ${dt('multiselect.option.group.font.weight')};\n}\n\n.p-multiselect-empty-message {\n padding: ${dt('multiselect.empty.message.padding')};\n}\n\n.p-multiselect-label .p-chip {\n padding-top: calc(${dt('multiselect.padding.y')} / 2);\n padding-bottom: calc(${dt('multiselect.padding.y')} / 2);\n border-radius: ${dt('multiselect.chip.border.radius')};\n}\n\n.p-multiselect-label:has(.p-chip) {\n padding: calc(${dt('multiselect.padding.y')} / 2) calc(${dt('multiselect.padding.x')} / 2);\n}\n\n.p-multiselect-fluid {\n display: flex;\n}\n\n.p-multiselect-sm .p-multiselect-label {\n font-size: ${dt('multiselect.sm.font.size')};\n padding-block: ${dt('multiselect.sm.padding.y')};\n padding-inline: ${dt('multiselect.sm.padding.x')};\n}\n\n.p-multiselect-sm .p-multiselect-dropdown .p-icon {\n font-size: ${dt('multiselect.sm.font.size')};\n width: ${dt('multiselect.sm.font.size')};\n height: ${dt('multiselect.sm.font.size')};\n}\n\n.p-multiselect-lg .p-multiselect-label {\n font-size: ${dt('multiselect.lg.font.size')};\n padding-block: ${dt('multiselect.lg.padding.y')};\n padding-inline: ${dt('multiselect.lg.padding.x')};\n}\n\n.p-multiselect-lg .p-multiselect-dropdown .p-icon {\n font-size: ${dt('multiselect.lg.font.size')};\n width: ${dt('multiselect.lg.font.size')};\n height: ${dt('multiselect.lg.font.size')};\n}\n\n.p-multiselect-clear-icon {\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n background: transparent;\n color: ${dt('multiselect.clear.icon.color')};\n}`;\n\nconst inlineStyles = {\n root: ({ props }) => ({ position: props.appendTo === 'self' ? 'relative' : undefined })\n};\n\nconst classes = {\n root: ({ instance }) => ({\n 'p-multiselect p-component p-inputwrapper': true,\n 'p-multiselect-display-chip': instance.display === 'chip',\n 'p-disabled': instance.disabled,\n 'p-invalid': instance.invalid,\n 'p-variant-filled': instance.variant ? instance.variant === 'filled' : instance.config.inputStyle === 'filled',\n 'p-focus': instance.focused,\n 'p-inputwrapper-filled': instance.filled,\n 'p-inputwrapper-focus': instance.focused || instance.overlayVisible,\n 'p-multiselect-open': instance.overlayVisible,\n 'p-multiselect-fluid': instance.hasFluid,\n 'p-multiselect-sm p-inputfield-sm': instance.size === 'small',\n 'p-multiselect-lg p-inputfield-lg': instance.size === 'large'\n }),\n labelContainer: 'p-multiselect-label-container',\n label: ({ instance }) => ({\n 'p-multiselect-label': true,\n 'p-placeholder': instance.label() === instance.placeholder(),\n 'p-multiselect-label-empty': !instance.placeholder() && !instance.defaultLabel && (!instance.modelValue() || instance.modelValue().length === 0)\n }),\n chipItem: 'p-multiselect-chip-item',\n pcChip: 'p-multiselect-chip',\n chipIcon: 'p-multiselect-chip-icon',\n dropdown: 'p-multiselect-dropdown',\n loadingIcon: 'p-multiselect-loading-icon',\n dropdownIcon: 'p-multiselect-dropdown-icon',\n overlay: 'p-multiselect-overlay p-component',\n header: 'p-multiselect-header',\n pcFilterContainer: 'p-multiselect-filter-container',\n pcFilter: 'p-multiselect-filter',\n listContainer: 'p-multiselect-list-container',\n list: 'p-multiselect-list',\n optionGroup: 'p-multiselect-option-group',\n option: ({ instance, option, index, getItemOptions }) => ({\n 'p-multiselect-option': true,\n 'p-multiselect-option-selected': instance.isSelected(option) && instance.highlightOnSelect,\n 'p-focus': instance.focusedOptionIndex === instance.getOptionIndex(index, getItemOptions),\n 'p-disabled': instance.isOptionDisabled(option)\n }),\n emptyMessage: 'p-multiselect-empty-message'\n};\n\n@Injectable()\nexport class MultiSelectStyle extends BaseStyle {\n name = 'multiselect';\n\n theme = theme;\n\n classes = classes;\n\n inlineStyles = inlineStyles;\n}\n\n/**\n *\n * MultiSelect is used to select multiple items from a collection.\n *\n * [Live Demo](https://www.primeng.org/multiselect/)\n *\n * @module multiselectstyle\n *\n */\nexport enum MultiSelectClasses {\n /**\n * Class name of the root element\n */\n root = 'p-multiselect',\n /**\n * Class name of the label container element\n */\n labelContainer = 'p-multiselect-label-container',\n /**\n * Class name of the label element\n */\n label = 'p-multiselect-label',\n /**\n * Class name of the chip item element\n */\n chipItem = 'p-multiselect-chip-item',\n /**\n * Class name of the chip element\n */\n pcChip = 'p-multiselect-chip',\n /**\n * Class name of the chip icon element\n */\n chipIcon = 'p-multiselect-chip-icon',\n /**\n * Class name of the dropdown element\n */\n dropdown = 'p-multiselect-dropdown',\n /**\n * Class name of the loading icon element\n */\n loadingIcon = 'p-multiselect-loading-icon',\n /**\n * Class name of the dropdown icon element\n */\n dropdownIcon = 'p-multiselect-dropdown-icon',\n /**\n * Class name of the overlay element\n */\n overlay = 'p-multiselect-overlay',\n /**\n * Class name of the header element\n */\n header = 'p-multiselect-header',\n /**\n * Class name of the filter container element\n */\n pcFilterContainer = 'p-multiselect-filter-container',\n /**\n * Class name of the filter element\n */\n pcFilter = 'p-multiselect-filter',\n /**\n * Class name of the list container element\n */\n listContainer = 'p-multiselect-list-container',\n /**\n * Class name of the list element\n */\n list = 'p-multiselect-list',\n /**\n * Class name of the option group element\n */\n optionGroup = 'p-multiselect-option-group',\n /**\n * Class name of the option element\n */\n option = 'p-multiselect-option',\n /**\n * Class name of the empty message element\n */\n emptyMessage = 'p-multiselect-empty-message'\n}\n\nexport interface MultiSelectStyle extends BaseStyle {}\n","import { AnimationEvent } from '@angular/animations';\nimport { CommonModule } from '@angular/common';\nimport {\n AfterContentInit,\n AfterViewChecked,\n AfterViewInit,\n booleanAttribute,\n ChangeDetectionStrategy,\n Component,\n computed,\n ContentChild,\n ContentChildren,\n effect,\n ElementRef,\n EventEmitter,\n forwardRef,\n HostBinding,\n inject,\n Input,\n NgModule,\n NgZone,\n numberAttribute,\n OnInit,\n Output,\n QueryList,\n Signal,\n signal,\n TemplateRef,\n ViewChild,\n ViewEncapsulation\n} from '@angular/core';\nimport { ControlValueAccessor, FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';\nimport {\n deepEquals,\n equals,\n findLastIndex,\n findSingle,\n focus,\n getFirstFocusableElement,\n getFocusableElements,\n getLastFocusableElement,\n hasClass,\n isArray,\n isHidden,\n isNotEmpty,\n isPrintableCharacter,\n resolveFieldData,\n unblockBodyScroll,\n uuid\n} from '@primeuix/utils';\nimport { FilterService, Footer, Header, OverlayOptions, OverlayService, PrimeTemplate, ScrollerOptions, SharedModule, TranslationKeys } from 'primeng/api';\nimport { AutoFocus } from 'primeng/autofocus';\nimport { BaseComponent } from 'primeng/basecomponent';\nimport { Checkbox } from 'primeng/checkbox';\nimport { Chip } from 'primeng/chip';\nimport { DomHandler } from 'primeng/dom';\nimport { IconField } from 'primeng/iconfield';\nimport { CheckIcon, ChevronDownIcon, SearchIcon, TimesIcon } from 'primeng/icons';\nimport { InputIcon } from 'primeng/inputicon';\nimport { InputText } from 'primeng/inputtext';\nimport { Overlay } from 'primeng/overlay';\nimport { Ripple } from 'primeng/ripple';\nimport { Scroller } from 'primeng/scroller';\nimport { Tooltip } from 'primeng/tooltip';\nimport { Nullable } from 'primeng/ts-helpers';\nimport { ObjectUtils } from 'primeng/utils';\nimport { MultiSelectBlurEvent, MultiSelectChangeEvent, MultiSelectFilterEvent, MultiSelectFilterOptions, MultiSelectFocusEvent, MultiSelectLazyLoadEvent, MultiSelectRemoveEvent, MultiSelectSelectAllChangeEvent } from './multiselect.interface';\nimport { MultiSelectStyle } from './style/multiselectstyle';\n\nexport const MULTISELECT_VALUE_ACCESSOR: any = {\n provide: NG_VALUE_ACCESSOR,\n useExisting: forwardRef(() => MultiSelect),\n multi: true\n};\n\n@Component({\n selector: 'p-multiSelectItem, p-multiselect-item',\n standalone: true,\n imports: [CommonModule, Checkbox, FormsModule, Ripple, SharedModule],\n template: `\n <li\n pRipple\n class=\"p-multiselect-option\"\n role=\"option\"\n [ngStyle]=\"{ height: itemSize + 'px' }\"\n [ngClass]=\"{\n 'p-multiselect-option-selected': selected && highlightOnSelect,\n 'p-disabled': disabled,\n 'p-focus': focused\n }\"\n [id]=\"id\"\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-disabled]=\"disabled\"\n [attr.aria-checked]=\"selected\"\n (click)=\"onOptionClick($event)\"\n (mouseenter)=\"onOptionMouseEnter($event)\"\n >\n <p-checkbox [ngModel]=\"selected\" [binary]=\"true\" [tabindex]=\"-1\" [variant]=\"variant\" [ariaLabel]=\"label\">\n <ng-container *ngIf=\"itemCheckboxIconTemplate\">\n <ng-template #checkboxicon let-klass=\"class\">\n <ng-template *ngTemplateOutlet=\"itemCheckboxIconTemplate; context: { checked: selected, class: klass }\"></ng-template>\n </ng-template>\n </ng-container>\n </p-checkbox>\n <span *ngIf=\"!template\">{{ label ?? 'empty' }}</span>\n <ng-container *ngTemplateOutlet=\"template; context: { $implicit: option }\"></ng-container>\n </li>\n `,\n encapsulation: ViewEncapsulation.None\n})\nexport class MultiSelectItem extends BaseComponent {\n @Input() id: string | undefined;\n\n @Input() option: any;\n\n @Input({ transform: booleanAttribute }) selected: boolean | undefined;\n\n @Input() label: string | undefined;\n\n @Input({ transform: booleanAttribute }) disabled: boolean | undefined;\n\n @Input({ transform: numberAttribute }) itemSize: number | undefined;\n\n @Input({ transform: booleanAttribute }) focused: boolean | undefined;\n\n @Input() ariaPosInset: string | undefined;\n\n @Input() ariaSetSize: string | undefined;\n\n @Input() variant: 'outlined' | 'filled';\n\n @Input() template: TemplateRef<any> | undefined;\n\n @Input() checkIconTemplate: TemplateRef<any> | undefined;\n\n @Input() itemCheckboxIconTemplate: TemplateRef<any> | undefined;\n\n @Input({ transform: booleanAttribute }) highlightOnSelect: boolean | undefined;\n\n @Output() onClick: EventEmitter<any> = new EventEmitter();\n\n @Output() onMouseEnter: EventEmitter<any> = new EventEmitter();\n\n onOptionClick(event: Event) {\n this.onClick.emit({\n originalEvent: event,\n option: this.option,\n selected: this.selected\n });\n event.stopPropagation();\n event.preventDefault();\n }\n\n onOptionMouseEnter(event: Event) {\n this.onMouseEnter.emit({\n originalEvent: event,\n option: this.option,\n selected: this.selected\n });\n }\n}\n// @ts-ignore\n/**\n * MultiSelect is used to select multiple items from a collection.\n * @group Components\n */\n@Component({\n selector: 'p-multiSelect, p-multiselect, p-multi-select',\n standalone: true,\n imports: [CommonModule, MultiSelectItem, Overlay, SharedModule, Tooltip, Scroller, AutoFocus, CheckIcon, SearchIcon, TimesIcon, ChevronDownIcon, IconField, InputIcon, InputText, Chip, Checkbox, FormsModule],\n template: `\n <div class=\"p-hidden-accessible\" [attr.data-p-hidden-accessible]=\"true\">\n <input\n #focusInput\n [pTooltip]=\"tooltip\"\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]=\"overlayVisible ?? false\"\n [attr.aria-controls]=\"overlayVisible ? id + '_list' : null\"\n [attr.tabindex]=\"!disabled ? tabindex : -1\"\n [attr.aria-activedescendant]=\"focused ? focusedOptionId : undefined\"\n (focus)=\"onInputFocus($event)\"\n (blur)=\"onInputBlur($event)\"\n (keydown)=\"onKeyDown($event)\"\n [pAutoFocus]=\"autofocus\"\n [attr.value]=\"label() || 'empty'\"\n />\n </div>\n <div\n class=\"p-multiselect-label-container\"\n [pTooltip]=\"tooltip\"\n (mouseleave)=\"labelContainerMouseLeave()\"\n [tooltipDisabled]=\"_disableTooltip\"\n [tooltipPosition]=\"tooltipPosition\"\n [positionStyle]=\"tooltipPositionStyle\"\n [tooltipStyleClass]=\"tooltipStyleClass\"\n >\n <div [ngClass]=\"labelClass\">\n <ng-container *ngIf=\"!selectedItemsTemplate && !_selectedItemsTemplate\">\n <ng-container *ngIf=\"display === 'comma'\">{{ label() || 'empty' }}</ng-container>\n <ng-container *ngIf=\"display === 'chip'\">\n @if (chipSelectedItems() && chipSelectedItems().length === maxSelectedLabels) {\n {{ getSelectedItemsLabel() }}\n } @else {\n <div #token *ngFor=\"let item of chipSelectedItems(); let i = index\" class=\"p-multiselect-chip-item\">\n <p-chip styleClass=\"p-multiselect-chip\" [label]=\"getLabelByValue(item)\" [removable]=\"!disabled && !readonly\" (onRemove)=\"removeOption(item, $event)\" [removeIcon]=\"chipIcon\">\n <ng-container *ngIf=\"chipIconTemplate || _chipIconTemplate || removeTokenIconTemplate || _removeTokenIconTemplate\">\n <ng-template #removeicon>\n <ng-container *ngIf=\"!disabled && !readonly\">\n <span\n class=\"p-multiselect-chip-icon\"\n *ngIf=\"chipIconTemplate || _chipIconTemplate || removeTokenIconTemplate || _removeTokenIconTemplate\"\n (click)=\"removeOption(item, $event)\"\n [attr.data-pc-section]=\"'clearicon'\"\n [attr.aria-hidden]=\"true\"\n >\n <ng-container *ngTemplateOutlet=\"chipIconTemplate || _chipIconTemplate || removeTokenIconTemplate || _removeTokenIconTemplate; context: { class: 'p-multiselect-chip-icon' }\"></ng-container>\n </span>\n </ng-container>\n </ng-template>\n </ng-container>\n </p-chip>\n </div>\n }\n <ng-container *ngIf=\"!modelValue() || modelValue().length === 0\">{{ placeholder() || defaultLabel || 'empty' }}</ng-container>\n </ng-container>\n </ng-container>\n <ng-container *ngIf=\"selectedItemsTemplate || _selectedItemsTemplate\">\n <ng-container *ngTemplateOutlet=\"selectedItemsTemplate || _selectedItemsTemplate; context: { $implicit: selectedOptions, removeChip: removeOption.bind(this) }\"></ng-container>\n <ng-container *ngIf=\"!modelValue() || modelValue().length === 0\">{{ placeholder() || defaultLabel || 'empty' }}</ng-container>\n </ng-container>\n </div>\n </div>\n <ng-container *ngIf=\"isVisibleClearIcon\">\n <TimesIcon *ngIf=\"!clearIconTemplate && !_clearIconTemplate\" class=\"p-multiselect-clear-icon\" (click)=\"clear($event)\" [attr.data-pc-section]=\"'clearicon'\" [attr.aria-hidden]=\"true\" />\n <span *ngIf=\"clearIconTemplate || _clearIconTemplate\" class=\"p-multiselect-clear-icon\" (click)=\"clear($event)\" [attr.data-pc-section]=\"'clearicon'\" [attr.aria-hidden]=\"true\">\n <ng-template *ngTemplateOutlet=\"clearIconTemplate || _clearIconTemplate\"></ng-template>\n </span>\n </ng-container>\n <div class=\"p-multiselect-dropdown\">\n <ng-container *ngIf=\"loading; else elseBlock\">\n <ng-container *ngIf=\"loadingIconTemplate || _loadingIconTemplate\">\n <ng-container *ngTemplateOutlet=\"loadingIconTemplate || _loadingIconTemplate\"></ng-container>\n </ng-container>\n <ng-container *ngIf=\"!loadingIconTemplate && !_loadingIconTemplate\">\n <span *ngIf=\"loadingIcon\" [ngClass]=\"'p-multiselect-loading-icon pi-spin ' + loadingIcon\" aria-hidden=\"true\"></span>\n <span *ngIf=\"!loadingIcon\" [class]=\"'p-multiselect-loading-icon pi pi-spinner pi-spin'\" aria-hidden=\"true\"></span>\n </ng-container>\n </ng-container>\n <ng-template #elseBlock>\n <ng-container *ngIf=\"!dropdownIconTemplate && !_dropdownIconTemplate\">\n <span *ngIf=\"dropdownIcon\" class=\"p-multiselect-dropdown-icon\" [ngClass]=\"dropdownIcon\" [attr.data-pc-section]=\"'triggericon'\" [attr.aria-hidden]=\"true\"></span>\n <ChevronDownIcon *ngIf=\"!dropdownIcon\" [styleClass]=\"'p-multiselect-dropdown-icon'\" [attr.data-pc-section]=\"'triggericon'\" [attr.aria-hidden]=\"true\" />\n </ng-container>\n <span *ngIf=\"dropdownIconTemplate || _dropdownIconTemplate\" class=\"p-multiselect-dropdown-icon\" [attr.data-pc-section]=\"'triggericon'\" [attr.aria-hidden]=\"true\">\n <ng-template *ngTemplateOutlet=\"dropdownIconTemplate || _dropdownIconTemplate\"></ng-template>\n </span>\n </ng-template>\n </div>\n <p-overlay\n #overlay\n [(visible)]=\"overlayVisible\"\n [options]=\"overlayOptions\"\n [target]=\"'@parent'\"\n [appendTo]=\"appendTo\"\n [autoZIndex]=\"autoZIndex\"\n [baseZIndex]=\"baseZIndex\"\n [showTransitionOptions]=\"showTransitionOptions\"\n [hideTransitionOptions]=\"hideTransitionOptions\"\n (onAnimationStart)=\"onOverlayAnimationStart($event)\"\n (onHide)=\"hide()\"\n >\n <ng-template #content>\n <div [attr.id]=\"id + '_list'\" [ngClass]=\"'p-multiselect-overlay p-component'\" [ngStyle]=\"panelStyle\" [class]=\"panelStyleClass\">\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 >\n </span>\n <ng-container *ngTemplateOutlet=\"headerTemplate || _headerTemplate\"></ng-container>\n <div class=\"p-multiselect-header\" *ngIf=\"showHeader\">\n <ng-content select=\"p-header\"></ng-content>\n <ng-container *ngIf=\"filterTemplate || _filterTemplate; else builtInFilterElement\">\n <ng-container *ngTemplateOutlet=\"filterTemplate || _filterTemplate; context: { options: filterOptions }\"></ng-container>\n </ng-container>\n <ng-template #builtInFilterElement>\n <p-checkbox [ngModel]=\"allSelected()\" [ariaLabel]=\"toggleAllAriaLabel\" [binary]=\"true\" (onChange)=\"onToggleAll($event)\" *ngIf=\"showToggleAll && !selectionLimit\" [variant]=\"variant\" [disabled]=\"disabled\" #headerCheckbox>\n <ng-template #checkboxicon let-klass=\"class\">\n <CheckIcon *ngIf=\"!headerCheckboxIconTemplate && !_headerCheckboxIconTemplate && allSelected()\" [styleClass]=\"klass\" [attr.data-pc-section]=\"'icon'\" />\n <ng-template\n *ngTemplateOutlet=\"\n headerCheckboxIconTemplate || _headerCheckboxIconTemplate;\n context: {\n checked: allSelected(),\n partialSelected: partialSelected(),\n class: klass\n }\n \"\n ></ng-template>\n </ng-template>\n </p-checkbox>\n\n <div class=\"p-multiselect-filter-container\" *ngIf=\"filter\">\n <p-iconfield>\n <input\n #filterInput\n pInputText\n [variant]=\"variant\"\n type=\"text\"\n [attr.autocomplete]=\"autocomplete\"\n role=\"searchbox\"\n [attr.aria-owns]=\"id + '_list'\"\n [attr.aria-activedescendant]=\"focusedOptionId\"\n [value]=\"_filterValue() || ''\"\n (input)=\"onFilterInputChange($event)\"\n (keydown)=\"onFilterKeyDown($event)\"\n (click)=\"onInputClick($event)\"\n (blur)=\"onFilterBlur($event)\"\n class=\"p-multiselect-filter\"\n [disabled]=\"disabled\"\n [attr.placeholder]=\"filterPlaceHolder\"\n [attr.aria-label]=\"ariaFilterLabel\"\n />\n <p-inputicon>\n <SearchIcon [styleClass]=\"'p-multiselect-filter-icon'\" *ngIf=\"!filterIconTemplate && !_filterIconTemplate\" />\n <span *ngIf=\"filterIconTemplate || _filterIconTemplate\" class=\"p-multiselect-filter-icon\">\n <ng-template *ngTemplateOutlet=\"filterIconTemplate || _filterIconTemplate\"></ng-template>\n </span>\n </p-inputicon>\n </p-iconfield>\n </div>\n </ng-template>\n </div>\n <div class=\"p-multiselect-list-container\" [style.max-height]=\"virtualScroll ? 'auto' : scrollHeight || 'auto'\">\n <p-scroller\n *ngIf=\"virtualScroll\"\n #scroller\n [items]=\"visibleOptions()\"\n [style]=\"{ height: scrollHeight }\"\n [itemSize]=\"virtualScrollItemSize || _itemSize\"\n [autoSize]=\"true\"\n [tabindex]=\"-1\"\n [lazy]=\"lazy\"\n (onLazyLoad)=\"onLazyLoad.emit($event)\"\n [options]=\"virtualScrollOptions\"\n >\n <ng-template #content let-items let-scrollerOptions=\"options\">\n <ng-container *ngTemplateOutlet=\"buildInItems; context: { $implicit: items, options: scrollerOptions }\"></ng-container>\n </ng-template>\n <ng-container *ngIf=\"loaderTemplate || _loaderTemplate\">\n <ng-template #loader let-scrollerOptions=\"options\">\n <ng-container *ngTemplateOutlet=\"loaderTemplate || _loaderTemplate; context: { options: scrollerOptions }\"></ng-container>\n </ng-template>\n </ng-container>\n </p-scroller>\n <ng-container *ngIf=\"!virtualScroll\">\n <ng-container *ngTemplateOutlet=\"buildInItems; context: { $implicit: visibleOptions(), options: {} }\"></ng-container>\n </ng-container>\n\n <ng-template #buildInItems let-items let-scrollerOptions=\"options\">\n <ul #items class=\"p-multiselect-list\" [ngClass]=\"scrollerOptions.contentStyleClass\" [style]=\"scrollerOptions.contentStyle\" role=\"listbox\" aria-multiselectable=\"true\" [attr.aria-label]=\"listLabel\">\n <ng-template ngFor let-option [ngForOf]=\"items\" let-i=\"index\">\n <ng-container *ngIf=\"isOptionGroup(option)\">\n <li [attr.id]=\"id + '_' + getOptionIndex(i, scrollerOptions)\" class=\"p-multiselect-option-group\" [ngStyle]=\"{ height: scrollerOptions.itemSize + 'px' }\" role=\"option\">\n <span *ngIf=\"!groupTemplate\">{{ getOptionGroupLabel(option.optionGroup) }}</span>\n <ng-container *ngTemplateOutlet=\"groupTemplate; context: { $implicit: option.optionGroup }\"></ng-container>\n </li>\n </ng-container>\n <ng-container *ngIf=\"!isOptionGroup(option)\">\n <p-multiselect-item\n [id]=\"id + '_' + getOptionIndex(i, scrollerOptions)\"\n [option]=\"option\"\n [selected]=\"isSelected(option)\"\n [label]=\"getOptionLabel(option)\"\n [disabled]=\"isOptionDisabled(option)\"\n [template]=\"itemTemplate || _itemTemplate\"\n [checkIconTemplate]=\"checkIconTemplate || _checkIconTemplate\"\n [itemCheckboxIconTemplate]=\"itemCheckboxIconTemplate || _itemCheckboxIconTemplate\"\n [itemSize]=\"scrollerOptions.itemSize\"\n [focused]=\"focusedOptionIndex() === getOptionIndex(i, scrollerOptions)\"\n [ariaPosInset]=\"getAriaPosInset(getOptionIndex(i, scrollerOptions))\"\n [ariaSetSize]=\"ariaSetSize\"\n [variant]=\"variant\"\n [highlightOnSelect]=\"highlightOnSelect\"\n (onClick)=\"onOptionSelect($event, false, getOptionIndex(i, scrollerOptions))\"\n (onMouseEnter)=\"onOptionMouseEnter($event, getOptionIndex(i, scrollerOptions))\"\n ></p-multiselect-item>\n </ng-container>\n </ng-template>\n\n <li *ngIf=\"hasFilter() && isEmpty()\" class=\"p-multiselect-empty-message\" [ngStyle]=\"{ height: scrollerOptions.itemSize + 'px' }\" role=\"option\">\n @if (!emptyFilterTemplate && !_emptyFilterTemplate && !emptyTemplate && !_emptyTemplate) {\n {{ emptyFilterMessageLabel }}\n } @else {\n <ng-container *ngTemplateOutlet=\"emptyFilterTemplate || _emptyFilterTemplate || emptyTemplate || _emptyFilterTemplate\"></ng-container>\n }\n </li>\n <li *ngIf=\"!hasFilter() && isEmpty()\" class=\"p-multiselect-empty-message\" [ngStyle]=\"{ height: scrollerOptions.itemSize + 'px' }\" role=\"option\">\n @if (!emptyTemplate && !_emptyTemplate) {\n {{ emptyMessageLabel }}\n } @else {\n <ng-container *ngTemplateOutlet=\"emptyTemplate || _emptyTemplate\"></ng-container>\n }\n </li>\n </ul>\n </ng-template>\n </div>\n <div *ngIf=\"footerFacet || footerTemplate || _footerTemplate\">\n <ng-content select=\"p-footer\"></ng-content>\n <ng-container *ngTemplateOutlet=\"footerTemplate || _footerTemplate\"></ng-container>\n </div>\n\n <span\n #lastHiddenFocusableEl\n role=\"presentation\"\n class=\"p-hidden-accessible p-hidden-focusable\"\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 providers: [MULTISELECT_VALUE_ACCESSOR, MultiSelectStyle],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n host: {\n '[attr.id]': 'id',\n '[style]': 'style',\n '(click)': 'onContainerClick($event)',\n '[class.p-variant-filled]': 'variant === \"filled\" || config.inputVariant() === \"filled\" || config.inputStyle() === \"filled\" '\n }\n})\nexport class MultiSelect extends BaseComponent implements OnInit, AfterViewInit, AfterContentInit, AfterViewChecked, ControlValueAccessor {\n /**\n * Unique identifier of the component\n * @group Props\n */\n @Input() id: string | undefined;\n /**\n * Defines a string that labels the input for accessibility.\n * @group Props\n */\n @Input() ariaLabel: string | undefined;\n /**\n * Inline style of the element.\n * @group Props\n */\n @Input() style: { [klass: string]: any } | null | undefined;\n /**\n * Style class of the element.\n * @group Props\n */\n @Input() styleClass: string | undefined;\n /**\n * Inline style of the overlay panel.\n * @group Props\n */\n @Input() panelStyle: any;\n /**\n * Style class of the overlay panel element.\n * @group Props\n */\n @Input() panelStyleClass: string | undefined;\n /**\n * Identifier of the focus input to match a label defined for the component.\n * @group Props\n */\n @Input() inputId: string | undefined;\n /**\n * When present, it specifies that the element should be disabled.\n * @group Props\n */\n @Input({ transform: booleanAttribute }) disabled: boolean | undefined;\n /**\n * Spans 100% width of the container when enabled.\n * @group Props\n */\n @Input({ transform: booleanAttribute }) fluid: boolean | undefined;\n /**\n * When present, it specifies that the component cannot be edited.\n * @group Props\n */\n @Input({ transform: booleanAttribute }) readonly: boolean | undefined;\n /**\n * Whether to display options as grouped when nested options are provided.\n * @group Props\n */\n @Input({ transform: booleanAttribute }) group: boolean | undefined;\n /**\n * When specified, displays an input field to filter the items on keyup.\n * @group Props\n */\n @Input({ transform: booleanAttribute }) filter: boolean = true;\n /**\n * Defines placeholder of the filter input.\n * @group Props\n */\n @Input() filterPlaceHolder: string | undefined;\n /**\n * Locale to use in filtering. The default locale is the host environment's current locale.\n * @group Props\n */\n @Input() filterLocale: string | undefined;\n /**\n * Specifies the visibility of the options panel.\n * @group Props\n */\n @Input({ transform: booleanAttribute }) overlayVisible: boolean | undefined;\n /**\n * Index of the element in tabbing order.\n * @group Props\n */\n @Input({ transform: numberAttribute }) tabindex: number | undefined = 0;\n /**\n * Specifies the input variant of the component.\n * @group Props\n */\n @Input() variant: 'filled' | 'outlined';\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 * @group Props\n */\n @Input() appendTo: HTMLElement | ElementRef | TemplateRef<any> | string | null | undefined | any;\n /**\n * A property to uniquely identify a value in options.\n * @group Props\n */\n @Input() dataKey: string | undefined;\n /**\n * Name of the input element.\n * @group Props\n */\n @Input() name: string | undefined;\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 @Input() ariaLabelledBy: string | undefined;\n /**\n * Whether to show labels of selected item labels or use default label.\n * @group Props\n * @defaultValue true\n */\n @Input() set displaySelectedLabel(val: boolean) {\n this._displaySelectedLabel = val;\n }\n get displaySelectedLabel(): boolean {\n return this._displaySelectedLabel;\n }\n /**\n * Decides how many selected item labels to show at most.\n * @group Props\n * @defaultValue 3\n */\n @Input() set maxSelectedLabels(val: number | null | undefined) {\n this._maxSelectedLabels = val;\n }\n get maxSelectedLabels(): number | null | undefined {\n return this._maxSelectedLabels;\n }\n /**\n * Maximum number of selectable items.\n * @group Props\n */\n @Input({ transform: numberAttribute }) selectionLimit: number | undefined;\n /**\n * Label to display after exceeding max selected labels e.g. ({0} items selected), defaults \"ellipsis\" keyword to indicate a text-overflow.\n * @group Props\n */\n @Input() selectedItemsLabel: string | undefined;\n /**\n * Whether to show the checkbox at header to toggle all items at once.\n * @group Props\n */\n @Input({ transform: booleanAttribute }) showToggleAll: boolean = true;\n /**\n * Text to display when filtering does not return any results.\n * @group Props\n */\n @Input() emptyFilterMessage: string = '';\n /**\n * Text to display when there is no data. Defaults to global value in i18n translation configuration.\n * @group Props\n */\n @Input() emptyMessage: string = '';\n /**\n * Clears the filter value when hiding the dropdown.\n * @group Props\n */\n @Input({ transform: booleanAttribute }) resetFilterOnHide: boolean = false;\n /**\n * Icon class of the dropdown icon.\n * @group Props\n */\n @Input() dropdownIcon: string | undefined;\n /**\n * Icon class of the chip icon.\n * @group Props\n */\n @Input() chipIcon: string | undefined;\n /**\n * Name of the label field of an option.\n * @group Props\n */\n @Input() optionLabel: string | undefined;\n /**\n * Name of the value field of an option.\n * @group Props\n */\n @Input() optionValue: string | undefined;\n /**\n * Name of the disabled field of an option.\n * @group Props\n */\n @Input() optionDisabled: string | undefined;\n /**\n * Name of the label field of an option group.\n * @group Props\n */\n @Input() optionGroupLabel: string | undefined = 'label';\n /**\n * Name of the options field of an option group.\n * @group Props\n */\n @Input() optionGroupChildren: string = 'items';\n /**\n * Whether to show the header.\n * @group Props\n */\n @Input({ transform: booleanAttribute }) showHeader: boolean = true;\n /**\n * When filtering is enabled, filterBy decides which field or fields (comma separated) to search against.\n * @group Props\n */\n @Input() filterBy: string | undefined;\n /**\n * Height of the viewport in pixels, a scrollbar is defined if height of list exceeds this value.\n * @group Props\n */\n @Input() scrollHeight: string = '200px';\n /**\n * Defines if data is loaded and interacted with in lazy manner.\n * @group Props\n */\n @Input({ transform: booleanAttribute }) lazy: boolean = false;\n /**\n * Whether the data should be loaded on demand during scroll.\n * @group Props\n */\n @Input({ transform: booleanAttribute }) virtualScroll: boolean | undefined;\n /**\n * Whether the multiselect is in loading state.\n * @group Props\n */\n @Input({ transform: booleanAttribute }) loading: boolean | undefined = false;\n /**\n * Height of an item in the list for VirtualScrolling.\n * @group Props\n */\n @Input({ transform: numberAttribute }) virtualScrollItemSize: number | undefined;\n /**\n * Icon to display in loading state.\n * @group Props\n */\n @Input() loadingIcon: string | undefined;\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 @Input() virtualScrollOptions: ScrollerOptions | undefined;\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 @Input() overlayOptions: OverlayOptions | undefined;\n /**\n * Defines a string that labels the filter input.\n * @group Props\n */\n @Input() ariaFilterLabel: string | undefined;\n /**\n * Defines how the items are filtered.\n * @group Props\n */\n @Input() filterMatchMode: 'contains' | 'startsWith' | 'endsWith' | 'equals' | 'notEquals' | 'in' | 'lt' | 'lte' | 'gt' | 'gte' = 'contains';\n /**\n * Advisory information to display in a tooltip on hover.\n * @group Props\n */\n @Input() tooltip: string = '';\n /**\n * Position of the tooltip.\n * @group Props\n */\n @Input() tooltipPosition: 'top' | 'left' | 'right' | 'bottom' = 'right';\n /**\n * Type of CSS position.\n * @group Props\n */\n @Input() tooltipPositionStyle: string = 'absolute';\n /**\n * Style class of the tooltip.\n * @group Props\n */\n @Input() tooltipStyleClass: string | undefined;\n /**\n * Applies focus to the filter element when the overlay is shown.\n * @group Props\n */\n @Input({ transform: booleanAttribute }) autofocusFilter: boolean = false;\n /**\n * Defines how the selected items are displayed.\n * @group Props\n */\n @Input() display: string | 'comma' | 'chip' = 'comma';\n /**\n * Defines the autocomplete is active.\n * @group Props\n */\n @Input() autocomplete: string = 'off';\n /**\n * Defines the size of the component.\n * @group Props\n */\n @Input() size: 'large' | 'small';\n /**\n * When enabled, a clear icon is displayed to clear the value.\n * @group Props\n */\n @Input({ transform: booleanAttribute }) showClear: boolean = false;\n /**\n * When present, it specifies that the component should automatically get focus on load.\n * @group Props\n */\n @Input({ transform: booleanAttribute }) autofocus: boolean | undefined;\n /**\n * @deprecated since v14.2.0, use overlayOptions property instead.\n * Whether to automatically manage layering.\n * @group Props\n */\n @Input() get autoZIndex(): boolean | undefined {\n return this._autoZIndex;\n }\n set autoZIndex(val: boolean | undefined) {\n this._autoZIndex = val;\n console.log('The autoZIndex property is deprecated since v14.2.0, use overlayOptions property instead.');\n }\n /**\n * @deprecated since v14.2.0, use overlayOptions property instead.\n * Base zIndex value to use in layering.\n * @group Props\n */\n @Input() get baseZIndex(): number | undefined {\n return this._baseZIndex;\n }\n set baseZIndex(val: number | undefined) {\n this._baseZIndex = val;\n console.log('The baseZIndex property is deprecated since v14.2.0, use overlayOptions property instead.');\n }\n /**\n * Transition options of the show animation.\n * @group Props\n * @deprecated since v14.2.0, use overlayOptions property instead.\n */\n @Input() get showTransitionOptions(): string | undefined {\n return this._showTransitionOptions;\n }\n set showTransitionOptions(val: string | undefined) {\n this._showTransitionOptions = val;\n console.log('The showTransitionOptions property is deprecated since v14.2.0, use overlayOptions property instead.');\n }\n /**\n * Transition options of the hide animation.\n * @group Props\n * @deprecated since v14.2.0, use overlayOptions property instead.\n */\n @Input() get hideTransitionOptions(): string | undefined {\n return this._hideTransitionOptions;\n }\n set hideTransitionOptions(val: string | undefined) {\n thi